From cc58e34cf87c92f0c76512fab64363a5d731bfd3 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 6 Jul 2013 19:08:59 +0200 Subject: [PATCH] Remove legacy key mapping and associate devices with keys (DInput has been left behind for now, will be fixed up soon). Saving is broken, will be fixed soon. --- Common/KeyMap.cpp | 343 +++++++++++++++-------- Common/KeyMap.h | 125 +++++---- Core/Config.cpp | 4 +- Core/Config.h | 2 +- Core/HLE/__sceAudio.cpp | 2 +- Core/HLE/sceAtrac.cpp | 6 +- Core/HLE/sceCtrl.cpp | 12 +- Core/HLE/sceCtrl.h | 3 +- GPU/GLES/Framebuffer.cpp | 6 +- GPU/Math3D.h | 13 +- UI/EmuScreen.cpp | 126 +++++---- UI/EmuScreen.h | 12 +- UI/MenuScreens.cpp | 80 ++++-- UI/MenuScreens.h | 17 +- UI/NativeApp.cpp | 13 +- Windows/ControlMapping.cpp | 230 +-------------- Windows/ControlMapping.h | 52 +--- Windows/InputDevice.cpp | 8 - Windows/InputDevice.h | 2 - Windows/KeyboardDevice.cpp | 48 +++- Windows/KeyboardDevice.h | 14 + Windows/WindowsHost.cpp | 20 ++ Windows/WindowsHost.h | 13 +- Windows/WndMainWindow.cpp | 559 ++----------------------------------- Windows/XinputDevice.cpp | 145 ++++++---- Windows/XinputDevice.h | 3 +- Windows/ppsspp.rc | Bin 43954 -> 38368 bytes lang | 2 +- native | 2 +- pspautotests | 2 +- 30 files changed, 671 insertions(+), 1193 deletions(-) diff --git a/Common/KeyMap.cpp b/Common/KeyMap.cpp index 4bb6b5937..9db19e716 100644 --- a/Common/KeyMap.cpp +++ b/Common/KeyMap.cpp @@ -19,39 +19,110 @@ #include "../Core/Config.h" #include "KeyMap.h" -using namespace KeyMap; - -// Platform specific -// default -std::map *platform_keymap = NULL; +namespace KeyMap { // TODO: Make use const_map.h from native struct DefaultKeyMap { - static std::map init() + static KeyMapping defaultKeyboardMap() { - std::map m; - m[KEYCODE_A] = CTRL_SQUARE; - m[KEYCODE_S] = CTRL_TRIANGLE; - m[KEYCODE_X] = CTRL_CIRCLE; - m[KEYCODE_Z] = CTRL_CROSS; - m[KEYCODE_Q] = CTRL_LTRIGGER; - m[KEYCODE_W] = CTRL_RTRIGGER; - m[KEYCODE_SPACE] = CTRL_START; + KeyMapping m; + m[KeyDef(DEVICE_ID_KEYBOARD, KEYCODE_A)] = CTRL_SQUARE; + m[KeyDef(DEVICE_ID_KEYBOARD, KEYCODE_S)] = CTRL_TRIANGLE; + m[KeyDef(DEVICE_ID_KEYBOARD, KEYCODE_X)] = CTRL_CIRCLE; + m[KeyDef(DEVICE_ID_KEYBOARD, KEYCODE_Z)] = CTRL_CROSS; + m[KeyDef(DEVICE_ID_KEYBOARD, KEYCODE_Q)] = CTRL_LTRIGGER; + m[KeyDef(DEVICE_ID_KEYBOARD, KEYCODE_W)] = CTRL_RTRIGGER; + m[KeyDef(DEVICE_ID_KEYBOARD, KEYCODE_SPACE)] = CTRL_START; #ifdef _WIN32 - m[KEYCODE_V] = CTRL_SELECT; + m[KeyDef(DEVICE_ID_KEYBOARD, KEYCODE_V)] = CTRL_SELECT; #else - m[KEYCODE_ENTER] = CTRL_SELECT; + m[KeyDef(DEVICE_ID_KEYBOARD, KEYCODE_ENTER)] = CTRL_SELECT; #endif - m[KEYCODE_DPAD_UP] = CTRL_UP; - m[KEYCODE_DPAD_DOWN] = CTRL_DOWN; - m[KEYCODE_DPAD_LEFT] = CTRL_LEFT; - m[KEYCODE_DPAD_RIGHT] = CTRL_RIGHT; + m[KeyDef(DEVICE_ID_KEYBOARD, KEYCODE_DPAD_UP)] = CTRL_UP; + m[KeyDef(DEVICE_ID_KEYBOARD, KEYCODE_DPAD_DOWN)] = CTRL_DOWN; + m[KeyDef(DEVICE_ID_KEYBOARD, KEYCODE_DPAD_LEFT)] = CTRL_LEFT; + m[KeyDef(DEVICE_ID_KEYBOARD, KEYCODE_DPAD_RIGHT)] = CTRL_RIGHT; return m; } - static std::map KeyMap; + + static KeyMapping default360Map() + { + KeyMapping m; + m[KeyDef(DEVICE_ID_X360_0, KEYCODE_BUTTON_A)] = CTRL_CROSS; + m[KeyDef(DEVICE_ID_X360_0, KEYCODE_BUTTON_B)] = CTRL_CIRCLE; + m[KeyDef(DEVICE_ID_X360_0, KEYCODE_BUTTON_X)] = CTRL_SQUARE; + m[KeyDef(DEVICE_ID_X360_0, KEYCODE_BUTTON_Y)] = CTRL_TRIANGLE; + m[KeyDef(DEVICE_ID_X360_0, KEYCODE_DPAD_UP)] = CTRL_UP; + m[KeyDef(DEVICE_ID_X360_0, KEYCODE_DPAD_RIGHT)] = CTRL_RIGHT; + m[KeyDef(DEVICE_ID_X360_0, KEYCODE_DPAD_DOWN)] = CTRL_DOWN; + m[KeyDef(DEVICE_ID_X360_0, KEYCODE_DPAD_LEFT)] = CTRL_LEFT; + m[KeyDef(DEVICE_ID_X360_0, KEYCODE_BUTTON_START)] = CTRL_START; + m[KeyDef(DEVICE_ID_X360_0, KEYCODE_BACK)] = CTRL_SELECT; + m[KeyDef(DEVICE_ID_X360_0, KEYCODE_BUTTON_L1)] = CTRL_LTRIGGER; + m[KeyDef(DEVICE_ID_X360_0, KEYCODE_BUTTON_R1)] = CTRL_RTRIGGER; + return m; + } + + static KeyMapping defaultPadMap() + { + KeyMapping m; + m[KeyDef(DEVICE_ID_PAD_0, KEYCODE_BUTTON_A)] = CTRL_CROSS; + m[KeyDef(DEVICE_ID_PAD_0, KEYCODE_BUTTON_B)] = CTRL_CIRCLE; + m[KeyDef(DEVICE_ID_PAD_0, KEYCODE_BUTTON_X)] = CTRL_SQUARE; + m[KeyDef(DEVICE_ID_PAD_0, KEYCODE_BUTTON_Y)] = CTRL_TRIANGLE; + m[KeyDef(DEVICE_ID_PAD_0, KEYCODE_DPAD_UP)] = CTRL_UP; + m[KeyDef(DEVICE_ID_PAD_0, KEYCODE_DPAD_RIGHT)] = CTRL_RIGHT; + m[KeyDef(DEVICE_ID_PAD_0, KEYCODE_DPAD_DOWN)] = CTRL_DOWN; + m[KeyDef(DEVICE_ID_PAD_0, KEYCODE_DPAD_LEFT)] = CTRL_LEFT; + m[KeyDef(DEVICE_ID_PAD_0, KEYCODE_BUTTON_START)] = CTRL_START; + m[KeyDef(DEVICE_ID_PAD_0, KEYCODE_BACK)] = CTRL_SELECT; + m[KeyDef(DEVICE_ID_PAD_0, KEYCODE_BUTTON_L1)] = CTRL_LTRIGGER; + m[KeyDef(DEVICE_ID_PAD_0, KEYCODE_BUTTON_R1)] = CTRL_RTRIGGER; + return m; + } + + static std::vector init() + { + std::vector m; + +#if defined(USING_GLES2) + // Mobile! Only a pad map required, some can use a keyboard map though. + ControllerMap pad; + pad.keys = defaultPadMap(); + pad.name = "Pad"; + m.push_back(pad); + + ControllerMap kbd; + kbd.keys = defaultKeyboardMap(); + kbd.name = "Keyboard"; + m.push_back(kbd); +#else + ControllerMap kbd; + kbd.keys = defaultKeyboardMap(); + kbd.name = "Keyboard"; + m.push_back(kbd); + +#ifdef _WIN32 + ControllerMap x360; + x360.keys = default360Map(); + x360.name = "360"; + m.push_back(x360); +#endif + // Keyboard and pad maps. + ControllerMap pad; + pad.keys = defaultPadMap(); + pad.name = "Pad"; + pad.active = false; + m.push_back(pad); +#endif + return m; + } + + static std::vector KeyMap; }; -std::map DefaultKeyMap::KeyMap = DefaultKeyMap::init(); +std::vector DefaultKeyMap::KeyMap = DefaultKeyMap::init(); + // Key & Button names struct KeyMap_IntStrPair { @@ -86,6 +157,7 @@ const KeyMap_IntStrPair key_names[] = { {KEYCODE_Y, "Y"}, {KEYCODE_Z, "Z"}, + {KEYCODE_0, "0"}, {KEYCODE_1, "1"}, {KEYCODE_2, "2"}, {KEYCODE_3, "3"}, @@ -95,39 +167,96 @@ const KeyMap_IntStrPair key_names[] = { {KEYCODE_7, "7"}, {KEYCODE_8, "8"}, {KEYCODE_9, "9"}, - {KEYCODE_0, "0"}, + {KEYCODE_F1, "F1"}, + {KEYCODE_F2, "F2"}, + {KEYCODE_F3, "F3"}, + {KEYCODE_F4, "F4"}, + {KEYCODE_F5, "F5"}, + {KEYCODE_F6, "F6"}, + {KEYCODE_F7, "F7"}, + {KEYCODE_F8, "F8"}, + {KEYCODE_F9, "F9"}, + {KEYCODE_F10, "F10"}, + {KEYCODE_F11, "F11"}, + {KEYCODE_F12, "F12"}, + + {KEYCODE_COMMA, ","}, + {KEYCODE_PERIOD, "."}, {KEYCODE_BACK, "Back"}, {KEYCODE_TAB, "Tab"}, {KEYCODE_ENTER, "Enter"}, - {KEYCODE_SHIFT_LEFT, "Shift"}, - {KEYCODE_SHIFT_RIGHT, "Shift"}, - {KEYCODE_CTRL_LEFT, "Ctrl"}, - {KEYCODE_CTRL_RIGHT, "Ctrl"}, - {KEYCODE_ALT_LEFT, "Alt"}, - {KEYCODE_ALT_RIGHT, "Alt"}, + {KEYCODE_SHIFT_LEFT, "LShift"}, + {KEYCODE_SHIFT_RIGHT, "RShift"}, + {KEYCODE_CTRL_LEFT, "LCtrl"}, + {KEYCODE_CTRL_RIGHT, "RCtrl"}, + {KEYCODE_ALT_LEFT, "LAlt"}, + {KEYCODE_ALT_RIGHT, "RAlt"}, {KEYCODE_SPACE, "Space"}, {KEYCODE_WINDOW, "Windows"}, + {KEYCODE_DEL, "Del"}, + {KEYCODE_MOVE_HOME, "Home"}, + {KEYCODE_MOVE_END, "End"}, - {KEYCODE_VOLUME_UP, "Vol Up"}, - {KEYCODE_VOLUME_DOWN, "Vol Down"}, + {KEYCODE_VOLUME_UP, "Vol +"}, + {KEYCODE_VOLUME_DOWN, "Vol -"}, {KEYCODE_HOME, "Home"}, - {KEYCODE_CALL, "Start Call"}, + {KEYCODE_CALL, "Call"}, {KEYCODE_ENDCALL, "End Call"}, {KEYCODE_DPAD_LEFT, "Left"}, {KEYCODE_DPAD_UP, "Up"}, {KEYCODE_DPAD_RIGHT, "Right"}, {KEYCODE_DPAD_DOWN, "Down"}, + + {KEYCODE_BUTTON_L1, "L1"}, + {KEYCODE_BUTTON_L2, "L2"}, + {KEYCODE_BUTTON_R1, "R1"}, + {KEYCODE_BUTTON_R2, "R2"}, + + {KEYCODE_BUTTON_A, "[A]"}, + {KEYCODE_BUTTON_B, "[B]"}, + {KEYCODE_BUTTON_C, "[C]"}, + {KEYCODE_BUTTON_X, "[X]"}, + {KEYCODE_BUTTON_Y, "[Y]"}, + {KEYCODE_BUTTON_Z, "[Z]"}, + {KEYCODE_BUTTON_1, "b1"}, + {KEYCODE_BUTTON_2, "b2"}, + {KEYCODE_BUTTON_3, "b3"}, + {KEYCODE_BUTTON_4, "b4"}, + {KEYCODE_BUTTON_5, "b5"}, + {KEYCODE_BUTTON_6, "b6"}, + {KEYCODE_BUTTON_7, "b7"}, + {KEYCODE_BUTTON_8, "b8"}, + {KEYCODE_BUTTON_9, "b9"}, + {KEYCODE_BUTTON_10, "b10"}, + {KEYCODE_BUTTON_11, "b11"}, + {KEYCODE_BUTTON_12, "b12"}, + {KEYCODE_BUTTON_13, "b13"}, + {KEYCODE_BUTTON_14, "b14"}, + {KEYCODE_BUTTON_15, "b15"}, + {KEYCODE_BUTTON_16, "b16"}, + {KEYCODE_BUTTON_START, "Start"}, + {KEYCODE_BUTTON_SELECT, "Select"}, + {KEYCODE_BUTTON_CIRCLE, "Circle"}, + {KEYCODE_BUTTON_CIRCLE_PS3, "Circle3"}, + {KEYCODE_BUTTON_CROSS, "Cross"}, + {KEYCODE_BUTTON_CROSS_PS3, "Cross3"}, + {KEYCODE_BUTTON_TRIANGLE, "Triangle"}, + {KEYCODE_BUTTON_SQUARE, "Square"}, + {KEYCODE_BUTTON_THUMBL, "ThumbL"}, + {KEYCODE_BUTTON_THUMBR, "ThumbR"}, + {KEYCODE_BUTTON_MODE, "Mode"}, }; + static int key_names_count = sizeof(key_names) / sizeof(key_names[0]); static std::string unknown_key_name = "Unknown"; const KeyMap_IntStrPair psp_button_names[] = { - {CTRL_CIRCLE, "○"}, - {CTRL_CROSS, "⨯"}, - {CTRL_SQUARE, "□"}, - {CTRL_TRIANGLE, "△"}, + {CTRL_CIRCLE, "O"}, + {CTRL_CROSS, "X"}, + {CTRL_SQUARE, "[ ]"}, + {CTRL_TRIANGLE, "/\\"}, {CTRL_LTRIGGER, "L"}, {CTRL_RTRIGGER, "R"}, {CTRL_START, "Start"}, @@ -139,7 +268,6 @@ const KeyMap_IntStrPair psp_button_names[] = { }; static int psp_button_names_count = sizeof(psp_button_names) / sizeof(psp_button_names[0]); - static std::string FindName(int key, const KeyMap_IntStrPair list[], int size) { for (int i = 0; i < size; i++) @@ -149,125 +277,96 @@ static std::string FindName(int key, const KeyMap_IntStrPair list[], int size) return unknown_key_name; } -std::string KeyMap::GetKeyName(int key) +std::string GetKeyName(int keyCode) { - return FindName(key, key_names, key_names_count); + return FindName(keyCode, key_names, key_names_count); } -std::string KeyMap::GetPspButtonName(int btn) +std::string GetPspButtonName(int btn) { return FindName(btn, psp_button_names, psp_button_names_count); } -static bool FindKeyMapping(int key, int *map_id, int *psp_button) +static bool FindKeyMapping(int deviceId, int key, int *psp_button) { - std::map::iterator it; - if (*map_id <= 0) { - // check user configuration - std::map user_map = g_Config.iMappingMap; - it = user_map.find(key); - if (it != user_map.end()) { - *map_id = 0; - *psp_button = it->second; + for (size_t i = 0; i < controllerMaps.size(); i++) { + if (!controllerMaps[i].active) + continue; + + auto iter = controllerMaps[i].keys.find(KeyDef(deviceId, key)); + if (iter != controllerMaps[i].keys.end()) { + *psp_button = iter->second; return true; } } - - if (*map_id <= 1 && platform_keymap != NULL) { - // check optional platform specific keymap - std::map port_map = *platform_keymap; - it = port_map.find(key); - if (it != port_map.end()) { - *map_id = 1; - *psp_button = it->second; - return true; - } - } - - if (*map_id <= 2) { - // check default keymap - const std::map default_map = DefaultKeyMap::KeyMap; - const std::map::const_iterator const_it = default_map.find(key); - if (const_it != default_map.end()) { - *map_id = 2; - *psp_button = const_it->second; - return true; - } - } - - *map_id = -1; return false; } - - -int KeyMap::KeyToPspButton(int key) +int KeyToPspButton(int deviceId, int key) { int search_start_layer = 0; int psp_button; - if (FindKeyMapping(key, &search_start_layer, &psp_button)) + if (FindKeyMapping(deviceId, key, &psp_button)) return psp_button; return KEYMAP_ERROR_UNKNOWN_KEY; } -bool KeyMap::IsMappedKey(int key) +bool KeyFromPspButton(int controllerMap, int btn, int *deviceId, int *keyCode) { - return KeyMap::KeyToPspButton(key) != KEYMAP_ERROR_UNKNOWN_KEY; + int search_start_layer = 0; + + for (auto iter = controllerMaps[controllerMap].keys.begin(); iter != controllerMaps[controllerMap].keys.end(); ++iter) { + if (iter->second == btn) { + *deviceId = iter->first.deviceId; + *keyCode = iter->first.keyCode; + return true; + } + } + return false; } - -bool KeyMap::IsUserDefined(int key) -{ - int layer = 0; - int ignored; - FindKeyMapping(key, &layer, &ignored); - return layer == 0; // key found in user settings +std::string NameKeyFromPspButton(int controllerMap, int btn) { + int deviceId; + int keyCode; + if (KeyFromPspButton(controllerMap, btn, &deviceId, &keyCode)) { + return GetKeyName(keyCode); + } + return "unknown"; } - -std::string KeyMap::NamePspButtonFromKey(int key) -{ - return KeyMap::GetPspButtonName(KeyMap::KeyToPspButton(key)); +std::string NameDeviceFromPspButton(int controllerMap, int btn) { + int deviceId; + int keyCode; + if (KeyFromPspButton(controllerMap, btn, &deviceId, &keyCode)) { + return GetDeviceName(deviceId); + } + return "unknown"; } -std::string KeyMap::NameKeyFromPspButton(int btn) +bool IsMappedKey(int deviceId, int key) { - // We drive our iteration - // with the list of key names. - for (int i = 0; i < key_names_count; i++) { - const struct KeyMap_IntStrPair key_name = key_names[i]; - if (btn == KeyMap::KeyToPspButton(key_name.key)) - return key_name.name; + return KeyToPspButton(deviceId, key) != KEYMAP_ERROR_UNKNOWN_KEY; +} + +std::string NamePspButtonFromKey(int deviceId, int key) +{ + return GetPspButtonName(KeyToPspButton(deviceId, key)); +} + +int SetKeyMapping(int map, int deviceId, int key, int btn) +{ + if (IsMappedKey(deviceId, key)) { + // TODO: Remove the existing mapping instead, less annoying. + return KEYMAP_ERROR_KEY_ALREADY_USED; + } else { + controllerMaps[map].keys[KeyDef(deviceId, key)] = btn; } - // all psp buttons are mapped from some key - // but it appears we do not have a name - // for this key. - return unknown_key_name; -} - -int KeyMap::SetKeyMapping(int key, int btn) -{ - if (KeyMap::IsMappedKey(key)) - return KEYMAP_ERROR_KEY_ALREADY_USED; - - g_Config.iMappingMap[key] = btn; return btn; } -int KeyMap::RegisterPlatformDefaultKeyMap(std::map *overriding_map) -{ - if (overriding_map == NULL) - return 1; - platform_keymap = overriding_map; - return 0; -} - -void KeyMap::DeregisterPlatformDefaultKeyMap() -{ - platform_keymap = NULL; - return; -} +} // KeyMap +std::vector controllerMaps = KeyMap::DefaultKeyMap::KeyMap; diff --git a/Common/KeyMap.h b/Common/KeyMap.h index d60d726b8..b8f0c073a 100644 --- a/Common/KeyMap.h +++ b/Common/KeyMap.h @@ -25,73 +25,80 @@ #define KEYMAP_ERROR_KEY_ALREADY_USED -1 #define KEYMAP_ERROR_UNKNOWN_KEY 0 +class KeyDef { +public: + KeyDef(int devId, int k) : deviceId(devId), keyCode(k) {} + int deviceId; + int keyCode; + + bool operator < (const KeyDef &other) const { + if (deviceId < other.deviceId) return true; + if (deviceId > other.deviceId) return false; + if (keyCode < other.keyCode) return true; + return false; + } +}; + +struct AxisPos { + int axis; + float position; +}; + +typedef std::map KeyMapping; +typedef std::map AxisMapping; + + +// Multiple maps can be active at the same time. +class ControllerMap { +public: + ControllerMap() : active(true) {} + bool active; + KeyMapping keys; + AxisMapping axis; // TODO + std::string name; +}; + + +extern std::vector controllerMaps; + // KeyMap -// A translation layer for -// key assignment. Provides -// integration with Core's -// config state. +// A translation layer for key assignment. Provides +// integration with Core's config state. // -// Does not handle input -// state managment. +// Does not handle input state managment. // -// Platform ports should -// map their platform's -// keys to KeyMap's keys. -// Then have KeyMap transform -// those into psp buttons. +// Platform ports should map their platform's keys to KeyMap's keys (KEYCODE_*). +// +// Then have KeyMap transform those into psp buttons. + namespace KeyMap { - // Use if you need to - // display the textual - // name - // These functions are not - // fast, do not call them - // a million times. - std::string GetKeyName(int key); - std::string GetPspButtonName(int btn); + // Use if you need to display the textual name + std::string GetKeyName(int keyCode); + std::string GetPspButtonName(int btn); - // Use if to translate - // KeyMap Keys to PSP - // buttons. - // You should have - // already translated - // your platform's keys - // to KeyMap keys. - // - // Returns KEYMAP_ERROR_UNKNOWN_KEY - // for any unmapped key - int KeyToPspButton(int key); + // Use if to translate KeyMap Keys to PSP + // buttons. You should have already translated + // your platform's keys to KeyMap keys. + // + // Returns KEYMAP_ERROR_UNKNOWN_KEY + // for any unmapped key + int KeyToPspButton(int deviceId, int key); - bool IsMappedKey(int key); - bool IsUserDefined(int key); + bool IsMappedKey(int deviceId, int key); - // Might be usful if you want - // to provide hints to users - // upon mapping conflicts - std::string NamePspButtonFromKey(int key); + // Might be useful if you want to provide hints to users + // about mapping conflicts + std::string NamePspButtonFromKey(int deviceId, int key); - // Use for showing the existing - // key mapping. - std::string NameKeyFromPspButton(int btn); + bool KeyFromPspButton(int controllerMap, int btn, int *deviceId, int *keyCode); + std::string NameKeyFromPspButton(int controllerMap, int btn); + std::string NameDeviceFromPspButton(int controllerMap, int btn); - // Configure the key mapping. - // Any configuration will - // be saved to the Core - // config. - // - // Returns KEYMAP_ERROR_KEY_ALREADY_USED - // for mapping conflicts. 0 otherwise. - int SetKeyMapping(int kb_key, int psp_key); - - // Platform specific keymaps - // override KeyMap's defaults. - // They do not override user's - // configuration. - // A platform default keymap - // does not need to cover - // all psp buttons. - // Any buttons missing will - // fallback to KeyMap's keymap. - int RegisterPlatformDefaultKeyMap(std::map *overriding_map); - void DeregisterPlatformDefaultKeyMap(); + // Configure the key mapping. + // Any configuration will be saved to the Core config. + // + // Returns KEYMAP_ERROR_KEY_ALREADY_USED + // for mapping conflicts. 0 otherwise. + int SetKeyMapping(int map, int deviceId, int keyCode, int psp_key); } diff --git a/Core/Config.cpp b/Core/Config.cpp index 7cae2fc22..36d1d0ed2 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -138,7 +138,7 @@ void Config::Load(const char *iniFileName) control->Get("ShowTouchControls", &bShowTouchControls,false); #endif control->Get("LargeControls", &bLargeControls, false); - control->Get("KeyMapping",iMappingMap); + // control->Get("KeyMapping",iMappingMap); control->Get("AccelerometerToAnalogHoriz", &bAccelerometerToAnalogHoriz, false); control->Get("ForceInputDevice", &iForceInputDevice, -1); control->Get("RightStickBind", &iRightStickBind, 0); @@ -246,7 +246,7 @@ void Config::Save() control->Set("ShowStick", bShowAnalogStick); control->Set("ShowTouchControls", bShowTouchControls); control->Set("LargeControls", bLargeControls); - control->Set("KeyMapping",iMappingMap); + // control->Set("KeyMapping",iMappingMap); control->Set("AccelerometerToAnalogHoriz", bAccelerometerToAnalogHoriz); control->Set("ForceInputDevice", iForceInputDevice); control->Set("RightStickBind", iRightStickBind); diff --git a/Core/Config.h b/Core/Config.h index 077e7b644..84dbd49c9 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -20,6 +20,7 @@ #include #include #include + #include "CommonTypes.h" extern const char *PPSSPP_GIT_VERSION; @@ -114,7 +115,6 @@ public: int iSwapRightAxes; // Control - std::map iMappingMap; // Can be used differently depending on systems int iForceInputDevice; int iTouchButtonOpacity; float fButtonScale; diff --git a/Core/HLE/__sceAudio.cpp b/Core/HLE/__sceAudio.cpp index 1e8eae48b..cc09d0307 100644 --- a/Core/HLE/__sceAudio.cpp +++ b/Core/HLE/__sceAudio.cpp @@ -357,7 +357,7 @@ int __AudioMix(short *outstereo, int numFrames) if (sz1 + sz2 < (size_t)numFrames) { underrun = (int)(sz1 + sz2) / 2; - DEBUG_LOG(HLE, "Audio out buffer UNDERRUN at %i of %i", underrun, numFrames); + VERBOSE_LOG(HLE, "Audio out buffer UNDERRUN at %i of %i", underrun, numFrames); } return underrun >= 0 ? underrun : numFrames; } diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index f3bd6466a..e127b2c68 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -612,7 +612,7 @@ u32 _AtracDecodeData(int atracID, u8* outbuf, u32 *SamplesNum, u32* finish, int if (atrac->decoder_context) { static u8 buf[0x8000]; - if (atrac->sampleQueue.getQueueSize() < ATRAC3PLUS_MAX_SAMPLES * sizeof(s16) * atrac->atracChannels) { + if ((size_t)atrac->sampleQueue.getQueueSize() < ATRAC3PLUS_MAX_SAMPLES * sizeof(s16) * atrac->atracChannels) { int decodebytes = 0; atrac->decodePos = atrac->getDecodePosBySample(atrac->currentSample); int inbytes = std::max((int)atrac->first.size - (int)atrac->decodePos, 0); @@ -658,7 +658,7 @@ u32 _AtracDecodeData(int atracID, u8* outbuf, u32 *SamplesNum, u32* finish, int atrac->decodePos = atrac->getDecodePosBySample(atrac->currentSample); int finishFlag = 0; - if (atrac->loopNum != 0 && (atrac->currentSample + atracSamplesPerFrame > atrac->loopEndSample || + if (atrac->loopNum != 0 && (atrac->currentSample + (int)atracSamplesPerFrame > atrac->loopEndSample || (numSamples == 0 && atrac->first.size >= atrac->first.filesize))) { atrac->currentSample = atrac->loopStartSample; if (atrac->loopNum > 0) @@ -1702,7 +1702,7 @@ int sceAtracLowLevelDecode(int atracID, u32 sourceAddr, u32 sourceBytesConsumedA } numSamples = ATRAC3PLUS_MAX_SAMPLES; Memory::Write_U32(numSamples * sizeof(s16) * atrac->atracOutputChannels, sampleBytesAddr); - int space = atrac->sampleQueue.getQueueSize(); + size_t space = atrac->sampleQueue.getQueueSize(); if (space < ATRAC3PLUS_MAX_SAMPLES * sizeof(s16) * atrac->atracChannels) atrac->first.writableBytes = atrac->atracBytesPerFrame; else diff --git a/Core/HLE/sceCtrl.cpp b/Core/HLE/sceCtrl.cpp index 7f828cb90..3e4f12931 100644 --- a/Core/HLE/sceCtrl.cpp +++ b/Core/HLE/sceCtrl.cpp @@ -157,14 +157,22 @@ void __CtrlButtonUp(u32 buttonBit) ctrlCurrent.buttons &= ~buttonBit; } -void __CtrlSetAnalog(float x, float y, int stick) +void __CtrlSetAnalogX(float x, int stick) { std::lock_guard guard(ctrlMutex); if (stick == 0) { ctrlCurrent.analog[0] = (u8)ceilf(x * 127.5f + 127.5f); - ctrlCurrent.analog[1] = (u8)ceilf(-y * 127.5f + 127.5f); } else { ctrlCurrent.analogRight[0] = (u8)ceilf(x * 127.5f + 127.5f); + } +} + +void __CtrlSetAnalogY(float y, int stick) +{ + std::lock_guard guard(ctrlMutex); + if (stick == 0) { + ctrlCurrent.analog[1] = (u8)ceilf(-y * 127.5f + 127.5f); + } else { ctrlCurrent.analogRight[1] = (u8)ceilf(-y * 127.5f + 127.5f); } } diff --git a/Core/HLE/sceCtrl.h b/Core/HLE/sceCtrl.h index b25464b98..0446e5381 100644 --- a/Core/HLE/sceCtrl.h +++ b/Core/HLE/sceCtrl.h @@ -43,7 +43,8 @@ void __CtrlShutdown(); void __CtrlButtonDown(u32 buttonBit); void __CtrlButtonUp(u32 buttonBit); // -1 to 1, try to keep it in the circle -void __CtrlSetAnalog(float x, float y, int stick = 0); +void __CtrlSetAnalogX(float value, int stick = 0); +void __CtrlSetAnalogY(float value, int stick = 0); // For use by internal UI like MsgDialog u32 __CtrlPeekButtons(); diff --git a/GPU/GLES/Framebuffer.cpp b/GPU/GLES/Framebuffer.cpp index bef01ed5d..cd2de199a 100644 --- a/GPU/GLES/Framebuffer.cpp +++ b/GPU/GLES/Framebuffer.cpp @@ -842,7 +842,7 @@ void ConvertFromRGBA8888(u8 *dst, u8 *src, u32 stride, u32 height, int format) { memcpy(dst, src, stride * height * 4); } } else { // But here it shouldn't matter if they do - u32 size = height * stride; + int size = height * stride; const u32 *src32 = (const u32 *)src; u16 *dst16 = (u16 *)dst; switch (format) { @@ -1034,8 +1034,8 @@ void FramebufferManager::PackFramebufferGLES_(VirtualFramebuffer *vfb) { } if(packed) { - DEBUG_LOG(HLE, "Reading framebuffer to mem, bufSize = %u, packed = %08x, fb_address = %08x", - bufSize, packed, fb_address); + DEBUG_LOG(HLE, "Reading framebuffer to mem, bufSize = %u, packed = %p, fb_address = %08x", + (u32)bufSize, packed, fb_address); glPixelStorei(GL_PACK_ALIGNMENT, 4); glReadPixels(0, 0, vfb->fb_stride, vfb->height, GL_RGBA, GL_UNSIGNED_BYTE, packed); diff --git a/GPU/Math3D.h b/GPU/Math3D.h index b526b731e..28565b2b1 100644 --- a/GPU/Math3D.h +++ b/GPU/Math3D.h @@ -30,11 +30,15 @@ public: float x,y,z; }; }; - Vec3(unsigned int rgb) { x=(rgb&0xFF)/255.0f; y=((rgb>>8)&0xFF)/255.0f; z=((rgb>>16)&0xFF)/255.0f;} + Vec3(unsigned int rgb) { + x = (rgb & 0xFF) * (1.0f/255.0f); + y = ((rgb >> 8) & 0xFF) * (1.0f/255.0f); + z = ((rgb >> 16) & 0xFF) * (1.0f/255.0f); + } Vec3(const float a[3]) { - v[0]=a[0]; - v[1]=a[1]; - v[2]=a[2]; + v[0] = a[0]; + v[1] = a[1]; + v[2] = a[2]; } Vec3(float _x, float _y, float _z) : x(_x), y(_y), z(_z) {} Vec3() {} @@ -92,7 +96,6 @@ public: { return Vec3(y*v.z-z*v.y, z*v.x-x*v.z, x*v.y-y*v.x); } - float Length2() const { return x*x + y*y + z*z; diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index 7f8e22c11..14a30c32c 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -15,6 +15,7 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. +#include "android/app-android.h" #include "base/logging.h" #include "gfx_es2/glsl_program.h" @@ -106,7 +107,7 @@ EmuScreen::EmuScreen(const std::string &filename) : invalid_(true) { osm.Show(s->T("PressESC", "Press ESC to open the pause menu"), 3.0f); } #endif - pressedLastUpdate = 0; + memset(analog_, 0, sizeof(analog_)); } EmuScreen::~EmuScreen() { @@ -175,6 +176,48 @@ inline float clamp1(float x) { return x; } +void EmuScreen::touch(const TouchInput &touch) { + +} + +void EmuScreen::key(const KeyInput &key) { + int result = KeyMap::KeyToPspButton(key.deviceId, key.keyCode); + if (result == KEYMAP_ERROR_UNKNOWN_KEY) + return; + + if (key.flags & KEY_DOWN) + __CtrlButtonDown(result); + if (key.flags & KEY_UP) + __CtrlButtonUp(result); +} + +void EmuScreen::axis(const AxisInput &axis) { + // TODO: Apply some form of axis mapping + switch (axis.axisId) { + case JOYSTICK_AXIS_X: analog_[0].x = axis.value; break; + case JOYSTICK_AXIS_Y: analog_[0].y = axis.value; break; + case JOYSTICK_AXIS_Z: analog_[1].x = axis.value; break; + case JOYSTICK_AXIS_RZ: analog_[1].y = axis.value; break; + } +} + + +// TODO: Get rid of this. +static const struct { int from, to; } legacy_touch_mapping[12] = { + {PAD_BUTTON_A, CTRL_CROSS}, + {PAD_BUTTON_B, CTRL_CIRCLE}, + {PAD_BUTTON_X, CTRL_SQUARE}, + {PAD_BUTTON_Y, CTRL_TRIANGLE}, + {PAD_BUTTON_START, CTRL_START}, + {PAD_BUTTON_BACK, CTRL_SELECT}, + {PAD_BUTTON_LBUMPER, CTRL_LTRIGGER}, + {PAD_BUTTON_RBUMPER, CTRL_RTRIGGER}, + {PAD_BUTTON_UP, CTRL_UP}, + {PAD_BUTTON_RIGHT, CTRL_RIGHT}, + {PAD_BUTTON_DOWN, CTRL_DOWN}, + {PAD_BUTTON_LEFT, CTRL_LEFT}, +}; + void EmuScreen::update(InputState &input) { globalUIState = UISTATE_INGAME; if (errorMessage_.size()) { @@ -196,72 +239,47 @@ void EmuScreen::update(InputState &input) { #ifdef _WIN32 if(g_Config.bShowTouchControls) { #endif - UpdateGamepad(input); + // TODO: Make new better touch buttons so we don't have to do this crap. + + // Copy over the mouse data from the real inputstate. + fakeInputState.mouse_valid = input.mouse_valid; + fakeInputState.pad_last_buttons = fakeInputState.pad_buttons; + fakeInputState.pad_buttons = 0; + memcpy(fakeInputState.pointer_down, input.pointer_down, sizeof(input.pointer_down)); + memcpy(fakeInputState.pointer_x, input.pointer_x, sizeof(input.pointer_x)); + memcpy(fakeInputState.pointer_y, input.pointer_y, sizeof(input.pointer_y)); + UpdateGamepad(fakeInputState); + UpdateInputState(&fakeInputState); + + for (int i = 0; i < ARRAY_SIZE(legacy_touch_mapping); i++) { + if (fakeInputState.pad_buttons_down & legacy_touch_mapping[i].from) + __CtrlButtonDown(legacy_touch_mapping[i].to); + if (fakeInputState.pad_buttons_up & legacy_touch_mapping[i].from) + __CtrlButtonUp(legacy_touch_mapping[i].to); + } - UpdateInputState(&input); #ifdef _WIN32 } #endif - // Set Keys ---- - - // Legacy key mapping - // Then translate pad input into PSP pad input. Also, add in tilt. - static const int mapping[12][2] = { - {PAD_BUTTON_A, CTRL_CROSS}, - {PAD_BUTTON_B, CTRL_CIRCLE}, - {PAD_BUTTON_X, CTRL_SQUARE}, - {PAD_BUTTON_Y, CTRL_TRIANGLE}, - {PAD_BUTTON_UP, CTRL_UP}, - {PAD_BUTTON_DOWN, CTRL_DOWN}, - {PAD_BUTTON_LEFT, CTRL_LEFT}, - {PAD_BUTTON_RIGHT, CTRL_RIGHT}, - {PAD_BUTTON_LBUMPER, CTRL_LTRIGGER}, - {PAD_BUTTON_RBUMPER, CTRL_RTRIGGER}, - {PAD_BUTTON_START, CTRL_START}, - {PAD_BUTTON_SELECT, CTRL_SELECT}, - }; - - for (int i = 0; i < 12; i++) { - if (input.pad_buttons_down & mapping[i][0]) { - __CtrlButtonDown(mapping[i][1]); - } - if (input.pad_buttons_up & mapping[i][0]) { - __CtrlButtonUp(mapping[i][1]); - } - } - - // Modern key mapping - uint32_t pressed = 0; - for (int i = 0; i < MAX_KEYQUEUESIZE; i++) { - int key = input.key_queue[i]; - if (key == 0) - break; - - // TODO: Add virt_sce_* codes for analog sticks - pressed |= KeyMap::KeyToPspButton(key); - } - __CtrlButtonDown(pressed); - __CtrlButtonUp(pressedLastUpdate & ~pressed); - pressedLastUpdate = pressed; - // End Set Keys -- - - float stick_x = input.pad_lstick_x; - float stick_y = input.pad_lstick_y; - float rightstick_x = input.pad_rstick_x; - float rightstick_y = input.pad_rstick_y; + float leftstick_x = analog_[0].x; + float leftstick_y = analog_[0].y; + float rightstick_x = analog_[1].x; + float rightstick_y = analog_[1].y; I18NCategory *s = GetI18NCategory("Screen"); // Apply tilt to left stick if (g_Config.bAccelerometerToAnalogHoriz) { // TODO: Deadzone, etc. - stick_x += clamp1(curve1(input.acc.y) * 2.0f); - stick_x = clamp1(stick_x); + leftstick_x += clamp1(curve1(input.acc.y) * 2.0f); + leftstick_x = clamp1(leftstick_x); } - __CtrlSetAnalog(stick_x, stick_y, 0); - __CtrlSetAnalog(rightstick_x, rightstick_x, 1); + __CtrlSetAnalogX(leftstick_x, 0); + __CtrlSetAnalogY(leftstick_y, 0); + __CtrlSetAnalogX(rightstick_x, 1); + __CtrlSetAnalogY(rightstick_y, 1); if (PSP_CoreParameter().fpsLimit != 2) { // Don't really need to show these, it's pretty obvious what unthrottle does, diff --git a/UI/EmuScreen.h b/UI/EmuScreen.h index ef166607f..61acc9fac 100644 --- a/UI/EmuScreen.h +++ b/UI/EmuScreen.h @@ -34,9 +34,19 @@ public: virtual void dialogFinished(const Screen *dialog, DialogResult result); virtual void sendMessage(const char *msg, const char *value); + virtual void touch(const TouchInput &touch); + virtual void key(const KeyInput &key); + virtual void axis(const AxisInput &axis); + private: // Something invalid was loaded, don't try to emulate bool invalid_; std::string errorMessage_; - uint32_t pressedLastUpdate; + + // For the virtual touch buttons, that currently can't send key events. + InputState fakeInputState; + + + // Analog is still buffered. + struct {float x, y;} analog_[2]; }; diff --git a/UI/MenuScreens.cpp b/UI/MenuScreens.cpp index d8db34a32..dfad96d69 100644 --- a/UI/MenuScreens.cpp +++ b/UI/MenuScreens.cpp @@ -686,19 +686,14 @@ void ControlsScreen::update(InputState &input) { } } -void KeyMappingScreen::update(InputState &input) { - if (input.pad_buttons_down & PAD_BUTTON_BACK) { - g_Config.Save(); - screenManager()->finishDialog(this, DR_OK); +void KeyMappingNewKeyDialog::key(const KeyInput &key) { + if (key.flags & KEY_DOWN) { + last_kb_deviceid = key.deviceId; + last_kb_key = key.keyCode; } } void KeyMappingNewKeyDialog::update(InputState &input) { - int new_key = input.key_queue[0]; - - if (new_key != 0) - last_kb_key = new_key; - if (input.pad_buttons_down & PAD_BUTTON_BACK) { g_Config.Save(); screenManager()->finishDialog(this, DR_OK); @@ -1527,6 +1522,13 @@ void ControlsScreen::render() { UIEnd(); } +void KeyMappingScreen::update(InputState &input) { + if (input.pad_buttons_down & PAD_BUTTON_BACK) { + g_Config.Save(); + screenManager()->finishDialog(this, DR_OK); + } +} + void KeyMappingScreen::render() { UIShader_Prepare(); UIBegin(UIShader_Get()); @@ -1537,20 +1539,22 @@ void KeyMappingScreen::render() { #define KeyBtn(x, y, symbol) \ - if (UIButton(GEN_ID, Pos(x, y), 50, 0, (KeyMap::GetPspButtonName(symbol)).c_str(), \ + if (UIButton(GEN_ID, Pos(x, y), 60, 0, KeyMap::NameKeyFromPspButton(currentMap_, symbol).c_str(), \ ALIGN_TOPLEFT)) {\ - screenManager()->push(new KeyMappingNewKeyDialog(symbol), 0); \ + screenManager()->push(new KeyMappingNewKeyDialog(symbol, currentMap_), 0); \ UIReset(); \ - } + } \ + UIText(0, Pos(x+30, y+50), KeyMap::NameDeviceFromPspButton(currentMap_, symbol).c_str(), 0xFFFFFFFF, 0.78f, ALIGN_HCENTER); \ + UIText(0, Pos(x+30, y+80), KeyMap::GetPspButtonName(symbol).c_str(), 0xFFFFFFFF, 0.5f, ALIGN_HCENTER); \ - KeyMap::DeregisterPlatformDefaultKeyMap(); + // \ + // UIText(0, Pos(x, y+50), controllerMaps[currentMap_].name.c_str(), 0xFFFFFFFF, 0.5f, ALIGN_HCENTER); - int pad = 150; + int pad = 130; int hlfpad = pad / 2; int left = 30; KeyBtn(left, 30, CTRL_LTRIGGER); - KeyBtn(dp_yres, 30, CTRL_RTRIGGER); int top = 100; KeyBtn(left+hlfpad, top, CTRL_UP); // ^ @@ -1558,21 +1562,35 @@ void KeyMappingScreen::render() { KeyBtn(left+pad, top+hlfpad, CTRL_RIGHT); // > KeyBtn(left+hlfpad, top+pad, CTRL_DOWN); // < - left = dp_yres; + left = 500; KeyBtn(left+hlfpad, top, CTRL_TRIANGLE); // Triangle KeyBtn(left, top+hlfpad, CTRL_SQUARE); // Square KeyBtn(left+pad, top+hlfpad, CTRL_CIRCLE); // Circle KeyBtn(left+hlfpad, top+pad, CTRL_CROSS); // Cross + KeyBtn(left, 30, CTRL_RTRIGGER); top += pad; - left = dp_yres /2; - KeyBtn(left, top, CTRL_START); - KeyBtn(left + pad, top, CTRL_SELECT); + left = 250; + KeyBtn(left, top, CTRL_SELECT); + KeyBtn(left + pad, top, CTRL_START); #undef KeyBtn if (UIButton(GEN_ID, Pos(dp_xres - 10, dp_yres - 10), LARGE_BUTTON_WIDTH, 0, generalI18N->T("Back"), ALIGN_RIGHT | ALIGN_BOTTOM)) { screenManager()->finishDialog(this, DR_OK); } + + if (UIButton(GEN_ID, Pos(10, dp_yres-10), LARGE_BUTTON_WIDTH, 0, generalI18N->T("Prev"), ALIGN_BOTTOMLEFT)) { + currentMap_--; + if (currentMap_ < 0) + currentMap_ = controllerMaps.size() - 1; + } + if (UIButton(GEN_ID, Pos(10 + 10 + LARGE_BUTTON_WIDTH, dp_yres-10), LARGE_BUTTON_WIDTH, 0, generalI18N->T("Next"), ALIGN_BOTTOMLEFT)) { + currentMap_++; + if (currentMap_ >= controllerMaps.size()) + currentMap_ = 0; + } + UIText(0, Pos(10, dp_yres-170), controllerMaps[currentMap_].name.c_str(), 0xFFFFFFFF, 1.0f, ALIGN_BOTTOMLEFT); + UICheckBox(GEN_ID,10, dp_yres - 80, "Mapping Active", ALIGN_BOTTOMLEFT, &controllerMaps[currentMap_].active); UIEnd(); } @@ -1598,22 +1616,26 @@ void KeyMappingNewKeyDialog::render() { KeyScale(1.3f); KeyText(left, top += stride, keyI18N->T("Current key")); KeyScale(2.0f); - KeyText(left, top + stride, (KeyMap::NameKeyFromPspButton(this->pspBtn)).c_str()); + KeyText(left, top += stride, (KeyMap::NameKeyFromPspButton(currentMap_, this->pspBtn)).c_str()); + KeyScale(1.4f); + KeyText(left, top + stride, (KeyMap::NameDeviceFromPspButton(currentMap_, this->pspBtn)).c_str()); int right = dp_yres; KeyScale(1.4f); KeyText(right, top, keyI18N->T("New Key")); KeyScale(2.0f); if (last_kb_key != 0) { - bool key_used = KeyMap::IsMappedKey(last_kb_key); + bool key_used = KeyMap::IsMappedKey(last_kb_deviceid, last_kb_key); if (!key_used) { - KeyText(right, top + stride, KeyMap::GetKeyName(last_kb_key).c_str()); + KeyText(right, top += stride, KeyMap::GetKeyName(last_kb_key).c_str()); + KeyScale(1.4f); + KeyText(right, top + stride, GetDeviceName(last_kb_deviceid)); } else { KeyScale(1.0f); KeyText(left + stride, top + 2*stride, keyI18N->T("Error: Key is already used by")); - KeyText(left + stride, top + 3*stride, - (KeyMap::NamePspButtonFromKey(last_kb_key)).c_str()); + //KeyText(left + stride, top + 3*stride, + // (KeyMap::NamePspButtonFromKey(last_kb_key)).c_str()); } } @@ -1623,7 +1645,7 @@ void KeyMappingNewKeyDialog::render() { // Save & cancel buttons if (UIButton(GEN_ID, Pos(10, dp_yres - 10), LARGE_BUTTON_WIDTH, 0, keyI18N->T("Save Mapping"), ALIGN_LEFT | ALIGN_BOTTOM)) { - KeyMap::SetKeyMapping(this->last_kb_key, this->pspBtn); + KeyMap::SetKeyMapping(currentMap_, this->last_kb_deviceid, this->last_kb_key, this->pspBtn); g_Config.Save(); screenManager()->finishDialog(this, DR_OK); } @@ -1879,6 +1901,14 @@ void CreditsScreen::render() { screenManager()->finishDialog(this, DR_OK); } +#ifdef ANDROID +#ifndef GOLD + if (UIButton(GEN_ID, Pos(10, dp_yres - 10), 200, 0, g->T("Buy PPSSPP Gold"), ALIGN_BOTTOMLEFT)) { + sendMessage("launchBrowser", "market://details?id=org.ppsspp.ppssppgold"); + } +#endif +#endif + UIEnd(); } diff --git a/UI/MenuScreens.h b/UI/MenuScreens.h index 94ff308f4..fa80e040a 100644 --- a/UI/MenuScreens.h +++ b/UI/MenuScreens.h @@ -135,23 +135,32 @@ public: class KeyMappingScreen : public Screen { public: + KeyMappingScreen() : currentMap_(0) {} void update(InputState &input); void render(); +private: + int currentMap_; }; // Dialog box, meant to be pushed class KeyMappingNewKeyDialog : public Screen { -private: - int pspBtn; - int last_kb_key; public: - KeyMappingNewKeyDialog(int btn) { + KeyMappingNewKeyDialog(int btn, int currentMap) { pspBtn = btn; + last_kb_deviceid = 0; last_kb_key = 0; + currentMap_ = currentMap; } void update(InputState &input); void render(); + void key(const KeyInput &key); + +private: + int pspBtn; + int last_kb_deviceid; + int last_kb_key; + int currentMap_; }; struct FileSelectScreenOptions { diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index b506e8921..e3c9a2f4c 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -542,8 +542,7 @@ void NativeDeviceLost() { } bool NativeIsAtTopLevel() { - // TODO - return false; + return globalUIState == UISTATE_MENU; } void NativeTouch(const TouchInput &touch) { @@ -551,6 +550,16 @@ void NativeTouch(const TouchInput &touch) { screenManager->touch(touch); } +void NativeKey(const KeyInput &key) { + if (screenManager) + screenManager->key(key); +} + +void NativeAxis(const AxisInput &key) { + if (screenManager) + screenManager->axis(key); +} + void NativeMessageReceived(const char *message, const char *value) { // We can only have one message queued. lock_guard lock(pendingMutex); diff --git a/Windows/ControlMapping.cpp b/Windows/ControlMapping.cpp index e6c1269a7..a10638804 100644 --- a/Windows/ControlMapping.cpp +++ b/Windows/ControlMapping.cpp @@ -15,235 +15,7 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. +#include "Common/KeyMap.h" #include "ControlMapping.h" #include "DinputDevice.h" #include "XinputDevice.h" - -extern unsigned int key_pad_map[]; -extern unsigned short analog_ctrl_map[]; -extern unsigned int dinput_ctrl_map[]; -extern unsigned int xinput_ctrl_map[]; - -inline UINT* ControlMapping::GetDeviceButtonsMap(UINT curDevice) -{ - switch (curDevice) - { - case CONTROLS_KEYBOARD_INDEX: - return pButtonsMap; - case CONTROLS_DIRECT_INPUT_INDEX: - return pButtonsMap + buttonsCount; - case CONTROLS_XINPUT_INDEX: - return pButtonsMap + (buttonsCount * 2); - case CONTROLS_KEYBOARD_ANALOG_INDEX: - return pButtonsMap + (buttonsCount * 3); - } - return NULL; -} - -ControlMapping * ControlMapping::CreateInstance(UINT nButtons) -{ - if (nButtons != (key_pad_map_size / sizeof(key_pad_map[0]) / 2)) - return FALSE; - if (nButtons != (dinput_ctrl_map_size / sizeof(dinput_ctrl_map[0]) / 2)) - return FALSE; - if (nButtons != (xinput_ctrl_map_size / sizeof(xinput_ctrl_map[0]) / 2)) - return FALSE; - if (4 != (analog_ctrl_map_size / sizeof(analog_ctrl_map[0]) / 2)) - return FALSE; - auto inst = new ControlMapping(nButtons); - if (!inst->pButtonsMap) - return FALSE; - return inst; -} - -ControlMapping::ControlMapping(UINT nButtons) : - currentDevicePage(-1), - currentButtonIndex(-1), - pButtonsMap(0), - buttonsCount(nButtons), - dinput(0), - xinput(0) -{ - dinput = std::shared_ptr(new DinputDevice()); - xinput = std::shared_ptr(new XinputDevice()); - - pButtonsMap = new UINT[CONTROLS_DEVICE_NUM * nButtons]; - ZeroMemory(pButtonsMap, sizeof(UINT) * CONTROLS_DEVICE_NUM * nButtons); - for (UINT i = 0; i < nButtons; i++) { - *(GetDeviceButtonsMap(CONTROLS_KEYBOARD_INDEX) + i) = key_pad_map[i * 2]; - *(GetDeviceButtonsMap(CONTROLS_DIRECT_INPUT_INDEX) + i) = dinput_ctrl_map[i * 2]; - *(GetDeviceButtonsMap(CONTROLS_XINPUT_INDEX) + i) = xinput_ctrl_map[i * 2]; - } - - for (int i = 0; i < 4; i++) { - *(GetDeviceButtonsMap(CONTROLS_KEYBOARD_ANALOG_INDEX) + i) = (UINT)analog_ctrl_map[i * 2]; - } -} - -ControlMapping::~ControlMapping() -{ - if (pButtonsMap) { - delete [] pButtonsMap; - pButtonsMap = NULL; - } -} - -void ControlMapping::UpdateState() -{ - rawState.button = -1; - switch(currentDevicePage) - { - case CONTROLS_KEYBOARD_INDEX: - case CONTROLS_KEYBOARD_ANALOG_INDEX: - { - ; // leave it to KeyboardProc. - } - break; - case CONTROLS_DIRECT_INPUT_INDEX: - { - - dinput->UpdateRawStateSingle(rawState); - UINT newButton = (rawState.button != rawState.prevButton && rawState.prevButton == -1) - ? rawState.button : -1; - if (newButton != -1) { - SetBindCode(newButton); - } - } - break; - case CONTROLS_XINPUT_INDEX: - { - xinput->UpdateRawStateSingle(rawState); - UINT newButton = (rawState.button != rawState.prevButton && rawState.prevButton == -1) - ? rawState.button : -1; - if (newButton != -1) { - SetBindCode(newButton); - } - } - break; - } - rawState.prevButton = rawState.button; -} - -void ControlMapping::BindToDevices() -{ - for (UINT i = 0; i < buttonsCount; i++) { - key_pad_map[i * 2] = *(GetDeviceButtonsMap(CONTROLS_KEYBOARD_INDEX) + i); - dinput_ctrl_map[i * 2] = *(GetDeviceButtonsMap(CONTROLS_DIRECT_INPUT_INDEX) + i); - xinput_ctrl_map[i * 2] = *(GetDeviceButtonsMap(CONTROLS_XINPUT_INDEX) + i); - } - for (UINT i = 0; i < 4; i++) { - analog_ctrl_map[i * 2] = (USHORT)*(GetDeviceButtonsMap(CONTROLS_KEYBOARD_ANALOG_INDEX) + i); - } -} - -void ControlMapping::SetBindCode(UINT newCode) -{ - SetBindCode(newCode, currentDevicePage, currentButtonIndex); -} - -void ControlMapping::SetBindCode(UINT newCode, UINT buttonIdx) -{ - SetBindCode(newCode, currentDevicePage, buttonIdx); -} - -void ControlMapping::SetBindCode(UINT newCode, UINT deviceIdx, UINT buttonIdx) -{ - if (deviceIdx < CONTROLS_DEVICE_NUM && buttonIdx < buttonsCount) - *(GetDeviceButtonsMap(deviceIdx) + buttonIdx) = newCode; -} - -UINT ControlMapping::GetBindCode(UINT deviceIdx, UINT buttonIdx) -{ - if (deviceIdx < CONTROLS_DEVICE_NUM && buttonIdx < buttonsCount) - return *(GetDeviceButtonsMap(deviceIdx) + buttonIdx); - return -1; -} - -UINT ControlMapping::GetBindCode(UINT buttonIdx) -{ - return GetBindCode(currentDevicePage, buttonIdx); -} - -UINT ControlMapping::GetBindCode() -{ - return GetBindCode(currentDevicePage, currentButtonIndex); -} - -void ControlMapping::SetDisableBind(UINT deviceIdx, UINT buttonIdx) -{ - u32 disableCode = 0; - if (deviceIdx == CONTROLS_DIRECT_INPUT_INDEX) { - disableCode = 0xFFFFFFFF; - } - SetBindCode(disableCode, deviceIdx, buttonIdx); -} - -void ControlMapping::SetDisableBind(UINT buttonIdx) -{ - SetDisableBind(currentDevicePage, buttonIdx); -} - -void ControlMapping::SetDisableBind() -{ - SetDisableBind(currentDevicePage, currentButtonIndex); -} - -UINT ControlMapping::GetTargetDevice() -{ - return currentDevicePage; -} - -void ControlMapping::SetTargetDevice(UINT deviceIdx) -{ - rawState.prevButton = -1; - currentDevicePage = deviceIdx; -} - -UINT ControlMapping::GetTargetButton() -{ - return currentButtonIndex; -} - -void ControlMapping::SetTargetButton(UINT buttonIdx) -{ - currentButtonIndex = buttonIdx; -} - -bool saveControlsToFile() { - FILE *wfp = fopen("PPSSPPControls.dat", "wb"); - if (!wfp) - return false; - - fwrite(key_pad_map, 1, key_pad_map_size, wfp); - fwrite(analog_ctrl_map, 1, analog_ctrl_map_size, wfp); - fwrite(dinput_ctrl_map, 1, dinput_ctrl_map_size, wfp); - fwrite(xinput_ctrl_map, 1, xinput_ctrl_map_size, wfp); - fclose(wfp); - return true; -} - -bool loadControlsFromFile() { - FILE *rfp = fopen("PPSSPPControls.dat", "rb"); - if (!rfp) - return false; - - fseek(rfp, 0, SEEK_END); - fpos_t fsize = 0; - fgetpos(rfp, &fsize); - - if (fsize != (key_pad_map_size + analog_ctrl_map_size + dinput_ctrl_map_size + xinput_ctrl_map_size)) - { - fclose(rfp); - return false; - } - - fseek(rfp, 0, SEEK_SET); - fread(key_pad_map, 1, key_pad_map_size, rfp); - fread(analog_ctrl_map, 1, analog_ctrl_map_size, rfp); - fread(dinput_ctrl_map, 1, dinput_ctrl_map_size, rfp); - fread(xinput_ctrl_map, 1, xinput_ctrl_map_size, rfp); - fclose(rfp); - - return true; -} - diff --git a/Windows/ControlMapping.h b/Windows/ControlMapping.h index 3f361d26e..8f53c0dee 100644 --- a/Windows/ControlMapping.h +++ b/Windows/ControlMapping.h @@ -33,8 +33,8 @@ struct RawInputState #define POV_CODE_DOWN 0x0200 #define POV_CODE_LEFT 0x0400 #define POV_CODE_RIGHT 0x0800 -#define XBOX_CODE_LEFTTRIGER 0x00010000 -#define XBOX_CODE_RIGHTTRIGER 0x00020000 +#define XBOX_CODE_LEFTTRIGGER 0x00010000 +#define XBOX_CODE_RIGHTTRIGGER 0x00020000 #define CONTROLS_KEYBOARD_INDEX 0 #define CONTROLS_DIRECT_INPUT_INDEX 1 @@ -42,51 +42,3 @@ struct RawInputState #define CONTROLS_KEYBOARD_ANALOG_INDEX 3 #define CONTROLS_DEVICE_NUM 4 - -extern bool saveControlsToFile(); -extern bool loadControlsFromFile(); - -extern const unsigned int xinput_ctrl_map_size; -extern const unsigned int key_pad_map_size; -extern const unsigned int analog_ctrl_map_size; -extern const unsigned int dinput_ctrl_map_size; - -struct RawInputState; -class DinputDevice; -class XinputDevice; - -class ControlMapping -{ -public: - static ControlMapping * CreateInstance(UINT nButtons); - virtual ~ControlMapping(); - void UpdateState(); - void BindToDevices(); - void SetTargetDevice(UINT deviceIdx); - UINT GetTargetDevice(); - void SetTargetButton(UINT buttonIdx); - UINT GetTargetButton(); - void SetBindCode(UINT newCode); - void SetBindCode(UINT newCode, UINT buttonIdx); - void SetBindCode(UINT newCode, UINT deviceIdx, UINT buttonIdx); - UINT GetBindCode(); - UINT GetBindCode(UINT buttonIdx); - UINT GetBindCode(UINT deviceIdx, UINT buttonIdx); - void SetDisableBind(); - void SetDisableBind(UINT buttonIdx); - void SetDisableBind(UINT deviceIdx, UINT buttonIdx); - -private: - ControlMapping(UINT nButtons); - ControlMapping(); - inline UINT* GetDeviceButtonsMap(UINT curDevice); - -private: - std::shared_ptr dinput; - std::shared_ptr xinput; - UINT currentDevicePage; - UINT currentButtonIndex; - UINT buttonsCount; - RawInputState rawState; - UINT *pButtonsMap; -}; diff --git a/Windows/InputDevice.cpp b/Windows/InputDevice.cpp index 8c1aa7eab..a3cc337ab 100644 --- a/Windows/InputDevice.cpp +++ b/Windows/InputDevice.cpp @@ -5,11 +5,3 @@ #include #include -#define PUSH_BACK(Cls) do { list.push_back(std::shared_ptr(new Cls())); } while (0) -std::list> getInputDevices() { - std::list> list; - PUSH_BACK(XinputDevice); - PUSH_BACK(DinputDevice); - PUSH_BACK(KeyboardDevice); - return list; -} diff --git a/Windows/InputDevice.h b/Windows/InputDevice.h index 7a8d6ab78..07b4d9672 100644 --- a/Windows/InputDevice.h +++ b/Windows/InputDevice.h @@ -14,5 +14,3 @@ public: virtual int UpdateState(InputState &input_state) = 0; virtual bool IsPad() = 0; }; - -std::list> getInputDevices(); diff --git a/Windows/KeyboardDevice.cpp b/Windows/KeyboardDevice.cpp index a698024f8..3e48fc7b3 100644 --- a/Windows/KeyboardDevice.cpp +++ b/Windows/KeyboardDevice.cpp @@ -1,4 +1,6 @@ +#include "base/NativeApp.h" #include "input/input_state.h" +#include "input/keycodes.h" #include "util/const_map.h" #include "KeyMap.h" #include "ControlMapping.h" @@ -26,6 +28,7 @@ unsigned int key_pad_map[] = { VK_LEFT, PAD_BUTTON_LEFT, VK_RIGHT, PAD_BUTTON_RIGHT, }; + const unsigned int key_pad_map_size = sizeof(key_pad_map); unsigned short analog_ctrl_map[] = { @@ -123,7 +126,7 @@ const unsigned int analog_ctrl_map_size = sizeof(analog_ctrl_map); int KeyboardDevice::UpdateState(InputState &input_state) { if (MainWindow::GetHWND() != GetForegroundWindow()) return -1; bool alternate = GetAsyncKeyState(VK_SHIFT) != 0; - KeyQueueBlank(input_state.key_queue); + static u32 alternator = 0; bool doAlternate = alternate && (alternator++ % 10) < 5; @@ -139,19 +142,37 @@ int KeyboardDevice::UpdateState(InputState &input_state) { if (!doAlternate || key_pad_map[i + 1] > PAD_BUTTON_SELECT) { // TODO: remove once EmuScreen supports virtual keys - switch (key_pad_map[i]) { - case VK_ESCAPE: - case VK_F3: - case VK_PAUSE: - case VK_BACK: + switch (key_pad_map[i + 1]) { + case PAD_BUTTON_MENU: + case PAD_BUTTON_BACK: + case PAD_BUTTON_RIGHT_THUMB: input_state.pad_buttons |= key_pad_map[i + 1]; break; } - - KeyQueueAttemptTranslatedAdd(input_state.key_queue, windowsTransTable, key_pad_map[i]); } } + for (size_t i = 0; i < downKeys.size(); i++) { + KeyInput key; + key.deviceId = DEVICE_ID_KEYBOARD; + key.flags = KEY_DOWN; + key.keyCode = windowsTransTable[downKeys[i]]; + if (key.keyCode) + NativeKey(key); + } + downKeys.clear(); + + for (size_t i = 0; i < upKeys.size(); i++) { + KeyInput key; + key.deviceId = DEVICE_ID_KEYBOARD; + key.flags = KEY_UP; + key.keyCode = windowsTransTable[upKeys[i]]; + if (key.keyCode) + NativeKey(key); + } + upKeys.clear(); + + // TODO: Better axis mapping float analogX = 0; float analogY = 0; for (int i = 0; i < sizeof(analog_ctrl_map)/sizeof(analog_ctrl_map[0]); i += 2) { @@ -175,9 +196,14 @@ int KeyboardDevice::UpdateState(InputState &input_state) { } } - // keyboard device - input_state.pad_lstick_x += analogX; - input_state.pad_lstick_y += analogY; + AxisInput axis; + axis.deviceId = DEVICE_ID_KEYBOARD; + axis.axisId = JOYSTICK_AXIS_X; + axis.value = analogX; + NativeAxis(axis); + axis.axisId = JOYSTICK_AXIS_Y; + axis.value = analogY; + NativeAxis(axis); return 0; } diff --git a/Windows/KeyboardDevice.h b/Windows/KeyboardDevice.h index 87b4d871f..5b03152c5 100644 --- a/Windows/KeyboardDevice.h +++ b/Windows/KeyboardDevice.h @@ -1,8 +1,22 @@ #pragma once + +#include +#include "base/mutex.h" #include "InputDevice.h" class KeyboardDevice : public InputDevice { public: virtual int UpdateState(InputState &input_state); virtual bool IsPad() { return false; } + + virtual void KeyDown(int keycode) { + downKeys.push_back(keycode); + } + virtual void KeyUp(int keycode) { + upKeys.push_back(keycode); + } + +private: + std::vector downKeys; + std::vector upKeys; }; diff --git a/Windows/WindowsHost.cpp b/Windows/WindowsHost.cpp index 7bf05e021..c804f2fdc 100644 --- a/Windows/WindowsHost.cpp +++ b/Windows/WindowsHost.cpp @@ -28,6 +28,11 @@ #include "Windows/Debugger/DebuggerShared.h" #include "Windows/Debugger/Debugger_Disasm.h" #include "Windows/Debugger/Debugger_MemoryDlg.h" + +#include "Windows/DinputDevice.h" +#include "Windows/XinputDevice.h" +#include "Windows/KeyboardDevice.h" + #include "Core/Debugger/SymbolMap.h" #include "main.h" @@ -51,6 +56,21 @@ static BOOL PostDialogMessage(Dialog *dialog, UINT message, WPARAM wParam = 0, L return PostMessage(dialog->GetDlgHandle(), message, wParam, lParam); } +WindowsHost::WindowsHost(HWND mainWindow, HWND displayWindow) +{ + mainWindow_ = mainWindow; + displayWindow_ = displayWindow; + +#define PUSH_BACK(Cls) do { list.push_back(std::shared_ptr(new Cls())); } while (0) + + input.push_back(std::shared_ptr(new XinputDevice())); + input.push_back(std::shared_ptr(new DinputDevice())); + keyboard = std::shared_ptr(new KeyboardDevice()); + input.push_back(keyboard); + + SetConsolePosition(); +} + bool WindowsHost::InitGL(std::string *error_message) { return GL_Init(MainWindow::GetDisplayHWND(), error_message); diff --git a/Windows/WindowsHost.h b/Windows/WindowsHost.h index a4428693d..594387531 100644 --- a/Windows/WindowsHost.h +++ b/Windows/WindowsHost.h @@ -17,19 +17,15 @@ #include "../Core/Host.h" #include "InputDevice.h" +#include "KeyboardDevice.h" #include #include class WindowsHost : public Host { public: - WindowsHost(HWND mainWindow, HWND displayWindow) - { - mainWindow_ = mainWindow; - displayWindow_ = displayWindow; - input = getInputDevices(); - SetConsolePosition(); - } + WindowsHost(HWND mainWindow, HWND displayWindow); + ~WindowsHost() { UpdateConsolePosition(); @@ -56,11 +52,14 @@ public: void SaveSymbolMap(); void SetWindowTitle(const char *message); + std::shared_ptr keyboard; + private: void SetConsolePosition(); void UpdateConsolePosition(); HWND displayWindow_; HWND mainWindow_; + std::list> input; }; \ No newline at end of file diff --git a/Windows/WndMainWindow.cpp b/Windows/WndMainWindow.cpp index aa800cf3f..52af4cfec 100644 --- a/Windows/WndMainWindow.cpp +++ b/Windows/WndMainWindow.cpp @@ -26,6 +26,7 @@ #include "resource.h" #include "Windows/WndMainWindow.h" +#include "Windows/WindowsHost.h" #include "Common/LogManager.h" #include "Common/ConsoleListener.h" #include "Windows/W32Util/DialogManager.h" @@ -80,7 +81,6 @@ namespace MainWindow LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK DisplayProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM); - LRESULT CALLBACK Controls(HWND, UINT, WPARAM, LPARAM); HWND GetHWND() { @@ -446,7 +446,6 @@ namespace MainWindow switch (message) { case WM_CREATE: - loadControlsFromFile(); break; case WM_MOVE: @@ -768,10 +767,9 @@ namespace MainWindow ResizeDisplay(true); break; case ID_OPTIONS_CONTROLS: - DialogManager::EnableAll(FALSE); - DialogBox(hInst, (LPCTSTR)IDD_CONTROLS, hWnd, (DLGPROC)Controls); - DialogManager::EnableAll(TRUE); + MessageBox(hWnd, "Control mapping has been moved to the in-window Settings menu.\n", "Sorry", 0); break; + case ID_EMULATION_SOUND: g_Config.bEnableSound = !g_Config.bEnableSound; break; @@ -799,7 +797,23 @@ namespace MainWindow } } break; + case WM_KEYDOWN: + { + // Ugly + WindowsHost *whost = static_cast(host); + int vkey = wParam; + whost->keyboard->KeyDown(vkey); + } + return 0; + + case WM_KEYUP: + { + // Ugly + WindowsHost *whost = static_cast(host); + int vkey = wParam; + whost->keyboard->KeyUp(vkey); + } return 0; case WM_DROPFILES: @@ -1002,7 +1016,6 @@ namespace MainWindow EnableMenuItem(menu,ID_EMULATION_STOP, !menuEnable); } - // Message handler for about box. LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { @@ -1029,540 +1042,6 @@ namespace MainWindow return FALSE; } -#define CONTROLS_IDC_EDIT_BEGIN IDC_EDIT_KEY_MENU -#define CONTROLS_IDC_EDIT_END IDC_EDIT_KEY_ANALOG_RIGHT -#define CONTROLS_BUTTONS_COUNT (IDC_EDIT_KEYRIGHT - CONTROLS_IDC_EDIT_BEGIN + 1) -#define CONTROLS_BUTTONNAME_MAX 16 -// for controls dialog device polling and bind update. -#define TIMER_CONTROLS_BINDUPDATE 1 -#define BINDUPDATE_INTERVAL_MS 50 - - static const char *controllist[] = { - "Menu", // Open PauseScreen - "Back", // Toggle PauseScreen & Back Setting Page. - "Triangle", - "Rectangle", - "Cross", - "Circle", - "Select", - "Start", - "Left Trigger", - "Right Trigger", - "Turbo", // LBUMPER (Turbo) - "Reserved", // RBUMPER (Open PauseScreen) - "Up", - "Down", - "Left", - "Right", - "LY+", - "LY-", - "LX-", - "LX+", - }; - - struct ControlsDlgState { - HHOOK pKeydownHook; - HBITMAP hbmPspImage; - HWND hCtrlTab; - UINT_PTR timerId; - WNDPROC orgPSPImageProc; - WNDPROC orgEditProc; - ControlMapping *pCtrlMap; - HWND hStaticPspImage; - }; - static ControlsDlgState *pCtrlDlgState; - - RECT getRedrawRect(HWND hWnd) { - RECT rc; - HWND hDlg = GetParent(hWnd); - GetWindowRect(hWnd, &rc); - POINT pt = {0, 0}; - ScreenToClient(hDlg, &pt); - rc.left += pt.x; - rc.right += pt.x; - rc.top += pt.y; - rc.bottom += pt.y; - - return rc; - } - - LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) - { - if (pCtrlDlgState->pCtrlMap->GetTargetDevice() == CONTROLS_KEYBOARD_INDEX) { - HWND hEdit = GetFocus(); - UINT nCtrlID = GetDlgCtrlID(hEdit); - if (nCtrlID < CONTROLS_IDC_EDIT_BEGIN || nCtrlID > CONTROLS_IDC_EDIT_END) { - return CallNextHookEx(pCtrlDlgState->pKeydownHook, nCode, wParam, lParam); - } - if (!(lParam&(1<<31))) { - // key down - HWND hDlg = GetParent(hEdit); - const char *str = getVirtualKeyName(wParam); - if (str) { - if (nCtrlID >= IDC_EDIT_KEY_ANALOG_UP) { - pCtrlDlgState->pCtrlMap->SetBindCode(wParam, CONTROLS_KEYBOARD_ANALOG_INDEX, - nCtrlID - IDC_EDIT_KEY_ANALOG_UP); - } else { - pCtrlDlgState->pCtrlMap->SetBindCode(wParam); - } - SetWindowTextA(hEdit, str); - RECT rc = getRedrawRect(hEdit); - InvalidateRect(hDlg, &rc, false); - } - else - MessageBoxA(hDlg, "Not supported!", "controller", MB_OK); - } - } - return 1; - } - - HBITMAP LoadImageFromResource(HINSTANCE hInstance,LPCTSTR pszResourceName, LPCTSTR lpType) - { - HRSRC hrsrc = FindResource(hInstance, pszResourceName, lpType); - if (!hrsrc) - return FALSE; - DWORD dwlen = SizeofResource(hInstance, hrsrc); - BYTE *lpRsrc = (BYTE*)LoadResource(hInstance, hrsrc); - if (!lpRsrc) - return FALSE; - int width, height; - unsigned char *image_data = 0; - bool bResult = pngLoadPtr(lpRsrc, dwlen, &width, &height, &image_data, false) != 0; - FreeResource(lpRsrc); - if (!bResult) - return 0; - HBITMAP hbm = CreateBitmap(width, height, 1, 32, image_data); - free(image_data); - return hbm; - } - void BitBlt(HBITMAP hbm, HDC dstDC, int dstX, int dstY, int width, int height, int srcX, int srcY) - { - HDC hCompDC = CreateCompatibleDC(dstDC); - HBITMAP oldbm = (HBITMAP)SelectObject(hCompDC, hbm); - BitBlt(dstDC, dstX, dstY, width, height, hCompDC, srcX, srcY, SRCCOPY); - SelectObject(hCompDC, oldbm); - DeleteObject(hCompDC); - } - - inline void SetWindowTextForButton(HWND hEdit, u32 buttonCode, const char *pszButtonName) - { - if (buttonCode == 0) { - SetWindowTextA(hEdit, "Disable"); - } else { - SetWindowTextA(hEdit, pszButtonName); - } - } - - // Draw background image of Controls Dialog (pspmode.png) by use static control. - LRESULT CALLBACK PSPImageProc(HWND hStatic, UINT message, WPARAM wParam, LPARAM lParam) - { - - switch(message) { - case WM_PAINT: - { - PAINTSTRUCT pst; - HDC hdc = BeginPaint(hStatic, &pst); - - BITMAP bm; - GetObject(pCtrlDlgState->hbmPspImage, sizeof(BITMAP), &bm); - BitBlt(pCtrlDlgState->hbmPspImage, hdc, 0, 0, bm.bmWidth, bm.bmHeight, 0 , 0); - EndPaint(hStatic, &pst); - - return TRUE; - } - default: - break; - } - return CallWindowProc(pCtrlDlgState->orgPSPImageProc, hStatic, message, wParam, lParam); - } - - LRESULT CALLBACK ButtonsEditProc(HWND hEdit, UINT message, WPARAM wParam, LPARAM lParam) - { - switch (message) { - case WM_RBUTTONUP: - { - UINT nCtrlID = GetDlgCtrlID(hEdit); - int deviceIdx = TabCtrl_GetCurSel(pCtrlDlgState->hCtrlTab); - if (deviceIdx != CONTROLS_KEYBOARD_INDEX && nCtrlID >= IDC_EDIT_KEY_ANALOG_UP) - return TRUE; - - HMENU hSubMenu = GetSubMenu(g_hPopupMenus, 4); - POINT pos; - pos.x = LOWORD(lParam); - pos.y = HIWORD(lParam); - ClientToScreen(hEdit, &pos); - switch(TrackPopupMenuEx(GetSubMenu(g_hPopupMenus, 4), TPM_RETURNCMD, pos.x, pos.y, hEdit, NULL)) - { - case ID_CONTROLS_KEY_DISABLE: - { - if (nCtrlID < IDC_EDIT_KEY_ANALOG_UP) { - pCtrlDlgState->pCtrlMap->SetDisableBind(deviceIdx, nCtrlID - CONTROLS_IDC_EDIT_BEGIN); - } - else if (deviceIdx == CONTROLS_KEYBOARD_INDEX) { - pCtrlDlgState->pCtrlMap->SetDisableBind( - CONTROLS_KEYBOARD_ANALOG_INDEX, nCtrlID - IDC_EDIT_KEY_ANALOG_UP); - } - SetWindowTextA(hEdit, "Disable"); - RECT rc = getRedrawRect(hEdit); - HWND hDlg = GetParent(hEdit); - InvalidateRect(hDlg, &rc, false); - break; - } - default: - break; - } - return TRUE; - } - default : - break; - } - return CallWindowProc(pCtrlDlgState->orgEditProc, hEdit, message, wParam, lParam); - } - - // Message handler for control box. - LRESULT CALLBACK Controls(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) - { - switch (message) - { - case WM_INITDIALOG: - W32Util::CenterWindow(hDlg); - { - // IDC_EDIT_xxx is need continuous value to IDC_EDIT_KEY_ANALOG_RIGHT from IDC_EDIT_KEY_MENU. - // it is total 16. - // it is need the same order as the dinput_ctrl_map(and xinput/keyboard). - if (CONTROLS_BUTTONS_COUNT != 16) { - char mes[100]; - snprintf(mes, 100, "CONTROLS_BUTTONS_COUNT(%d) is need 16.", CONTROLS_BUTTONS_COUNT); - MessageBoxA(hDlg, mes, "Controls dialog init error.", MB_OK); - } - pCtrlDlgState = new ControlsDlgState(); - ZeroMemory(pCtrlDlgState, sizeof(ControlsDlgState)); - pCtrlDlgState->pCtrlMap = ControlMapping::CreateInstance(CONTROLS_BUTTONS_COUNT); - if (!pCtrlDlgState->pCtrlMap) { - MessageBoxA(hDlg, "Cannot Created ControlMapping instance.", "Controls dialog init error.", MB_OK); - } - pCtrlDlgState->pCtrlMap->SetTargetDevice(CONTROLS_KEYBOARD_INDEX); - - pCtrlDlgState->hCtrlTab = GetDlgItem(hDlg, IDC_TAB_INPUT_DEVICE); - TCITEM tcItem; - ZeroMemory(&tcItem, sizeof(tcItem)); - tcItem.mask = TCIF_TEXT; - tcItem.dwState = 0; - tcItem.pszText = "Keyboard"; - tcItem.cchTextMax = (int)strlen(tcItem.pszText)+1; - tcItem.iImage = 0; - TabCtrl_InsertItem(pCtrlDlgState->hCtrlTab, TabCtrl_GetItemCount(pCtrlDlgState->hCtrlTab),&tcItem); - tcItem.pszText = "DirectInput"; - tcItem.cchTextMax = (int)strlen(tcItem.pszText)+1; - TabCtrl_InsertItem(pCtrlDlgState->hCtrlTab, TabCtrl_GetItemCount(pCtrlDlgState->hCtrlTab),&tcItem); - tcItem.pszText = "XInput"; - tcItem.cchTextMax = (int)strlen(tcItem.pszText)+1; - TabCtrl_InsertItem(pCtrlDlgState->hCtrlTab, TabCtrl_GetItemCount(pCtrlDlgState->hCtrlTab),&tcItem); - int tp_w = 0, tp_h = 0; - // TODO: connect to keyboard device instead - { - - HBITMAP hResBM = LoadImageFromResource(hInst, MAKEINTRESOURCE(IDB_IMAGE_PSP), "IMAGE"); - pCtrlDlgState->hStaticPspImage = GetDlgItem(hDlg,IDC_STATIC_IMAGE_PSP); - RECT clientRect, tabPageRect, imgRect; - - GetClientRect(hDlg, &clientRect); - memcpy(&tabPageRect, &clientRect, sizeof(RECT)); - TabCtrl_AdjustRect(pCtrlDlgState->hCtrlTab, FALSE, &tabPageRect); - tp_w = tabPageRect.right - tabPageRect.left; - tp_h = tabPageRect.bottom - tabPageRect.top; - MoveWindow(pCtrlDlgState->hStaticPspImage, tabPageRect.left, tabPageRect.top, tp_w, tp_h, FALSE); - - HDC hDC = GetDC(pCtrlDlgState->hStaticPspImage); - HBITMAP hMemBM = CreateCompatibleBitmap(hDC, tp_w, tp_h); - HDC hResDC = CreateCompatibleDC(hDC); - HDC hMemDC = CreateCompatibleDC(hDC); - SelectObject(hResDC, hResBM); - SelectObject(hMemDC, hMemBM); - - BITMAP bm; - GetObject(hResBM, sizeof(BITMAP), &bm); - SetStretchBltMode(hMemDC, HALFTONE); - float scaleX = (float)bm.bmWidth / clientRect.right; - float scaleY = (float)bm.bmHeight / clientRect.bottom; - imgRect.left = (int)(tabPageRect.left * scaleX); - imgRect.top = (int)(tabPageRect.top * scaleY); - imgRect.right= (int)(bm.bmWidth - ((clientRect.right - tabPageRect.right) * scaleX)); - imgRect.bottom = (int)(bm.bmHeight - ((clientRect.bottom - tabPageRect.bottom) * scaleY)); - StretchBlt(hMemDC, 0, 0, tp_w, tp_h, hResDC, imgRect.left, imgRect.top, - imgRect.right - imgRect.left, imgRect.bottom - imgRect.top, SRCCOPY); - if (pCtrlDlgState->hbmPspImage) - DeleteObject(pCtrlDlgState->hbmPspImage); - pCtrlDlgState->hbmPspImage = hMemBM; - - DeleteDC(hMemDC); - DeleteDC(hResDC); - ReleaseDC(pCtrlDlgState->hStaticPspImage, hDC); - DeleteObject(hResBM); - } - - pCtrlDlgState->orgEditProc = (WNDPROC)GetWindowLongPtr( - GetDlgItem(hDlg, CONTROLS_IDC_EDIT_BEGIN), GWLP_WNDPROC); - for (int i = 0; i <= CONTROLS_IDC_EDIT_END - CONTROLS_IDC_EDIT_BEGIN; i++) { - HWND hEdit = GetDlgItem(hDlg, CONTROLS_IDC_EDIT_BEGIN + i); - if (i < CONTROLS_BUTTONS_COUNT) { - u32 keyCode = pCtrlDlgState->pCtrlMap->GetBindCode(CONTROLS_KEYBOARD_INDEX, i); - SetWindowTextForButton(hEdit, keyCode, getVirtualKeyName(keyCode)); - } else { - u32 analogCode = pCtrlDlgState->pCtrlMap->GetBindCode( - CONTROLS_KEYBOARD_ANALOG_INDEX, i - CONTROLS_BUTTONS_COUNT); - SetWindowTextForButton(hEdit, analogCode, getVirtualKeyName(analogCode)); - } - if (pCtrlDlgState->orgEditProc != (WNDPROC)GetWindowLongPtr(hEdit, GWLP_WNDPROC)) { - MessageBoxA(hDlg, - "Can not hook to the inherited Edit control. need wndproc of original edit control.", - "Controls dialog init error.", MB_OK); - break; - } - SetWindowLongPtr(hEdit, GWLP_WNDPROC, (LONG_PTR)ButtonsEditProc); - } - - ComboBox_AddString(GetDlgItem(hDlg, IDC_FORCE_INPUT_DEVICE), "None"); - ComboBox_AddString(GetDlgItem(hDlg, IDC_FORCE_INPUT_DEVICE), "XInput"); - ComboBox_AddString(GetDlgItem(hDlg, IDC_FORCE_INPUT_DEVICE), "DirectInput"); - if ((g_Config.iForceInputDevice < 0) || (g_Config.iForceInputDevice > 1)) - { - ComboBox_SetCurSel(GetDlgItem(hDlg, IDC_FORCE_INPUT_DEVICE), 0); - } - else - { - ComboBox_SetCurSel(GetDlgItem(hDlg, IDC_FORCE_INPUT_DEVICE), (g_Config.iForceInputDevice + 1)); - } - pCtrlDlgState->orgPSPImageProc = (WNDPROC)GetWindowLongPtr(pCtrlDlgState->hStaticPspImage, GWLP_WNDPROC); - SetWindowLongPtr(pCtrlDlgState->hStaticPspImage, GWLP_WNDPROC, (LONG_PTR)PSPImageProc); - DWORD dwThreadID = GetWindowThreadProcessId(hDlg, NULL); - pCtrlDlgState->pKeydownHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, NULL, dwThreadID); - - pCtrlDlgState->timerId = SetTimer(hDlg, TIMER_CONTROLS_BINDUPDATE, BINDUPDATE_INTERVAL_MS, 0); - } - return TRUE; - case WM_TIMER: - { - if (wParam == TIMER_CONTROLS_BINDUPDATE && - pCtrlDlgState->pCtrlMap->GetTargetDevice() != CONTROLS_KEYBOARD_INDEX) { - HWND hEdit = GetFocus(); - UINT nCtrlID = GetDlgCtrlID(hEdit); - if (nCtrlID < CONTROLS_IDC_EDIT_BEGIN || nCtrlID > IDC_EDIT_KEYRIGHT) { - break; - } - // device polling and update. - int prevButton = pCtrlDlgState->pCtrlMap->GetBindCode(); - pCtrlDlgState->pCtrlMap->UpdateState(); - char str[CONTROLS_BUTTONNAME_MAX]; - ZeroMemory(str, CONTROLS_BUTTONNAME_MAX * sizeof(char)); - int buttonCode = pCtrlDlgState->pCtrlMap->GetBindCode(); - if (buttonCode == -1 || prevButton == buttonCode) - break; - - switch(pCtrlDlgState->pCtrlMap->GetTargetDevice()) - { - case CONTROLS_KEYBOARD_INDEX: - { - ; // leave it to KeyboardProc. - } - break; - case CONTROLS_DIRECT_INPUT_INDEX: - { - if (buttonCode > 0xFF) { - int n = 1; - for (int i = buttonCode >> 8; i > 1; i >>= 1) { - n++; - } - snprintf(str, CONTROLS_BUTTONNAME_MAX, "%s", - controllist[(IDC_EDIT_KEYUP - CONTROLS_IDC_EDIT_BEGIN - 1) + n]); - } else { - snprintf(str, CONTROLS_BUTTONNAME_MAX, "%d", buttonCode + 1); - } - SetWindowTextA(hEdit, str); - RECT rc = getRedrawRect(hEdit); - InvalidateRect(hDlg, &rc, FALSE); - } - break; - case CONTROLS_XINPUT_INDEX: - { - SetWindowTextA(hEdit, getXinputButtonName(buttonCode)); - RECT rc = getRedrawRect(hEdit); - InvalidateRect(hDlg, &rc, FALSE); - } - break; - } - } - } - break; - case WM_NOTIFY: - { - switch (((NMHDR *)lParam)->code) - { - case TCN_SELCHANGE: - { - int cursel = TabCtrl_GetCurSel(pCtrlDlgState->hCtrlTab); - pCtrlDlgState->pCtrlMap->SetTargetDevice(cursel); - switch (cursel) - { - case CONTROLS_KEYBOARD_INDEX: - { - for (u32 i = 0; i <= IDC_EDIT_KEYRIGHT - CONTROLS_IDC_EDIT_BEGIN; i++) { - HWND hEdit = GetDlgItem(hDlg, CONTROLS_IDC_EDIT_BEGIN + i); - u32 keyCode = pCtrlDlgState->pCtrlMap->GetBindCode(i); - SetWindowTextForButton(hEdit, keyCode, getVirtualKeyName(keyCode)); - } - for (u32 i = 0; i <= CONTROLS_IDC_EDIT_END - IDC_EDIT_KEY_ANALOG_UP; i++) { - HWND hEdit = GetDlgItem(hDlg, IDC_EDIT_KEY_ANALOG_UP + i); - Edit_SetReadOnly(hEdit, FALSE); - u32 analogCode = pCtrlDlgState->pCtrlMap->GetBindCode( - CONTROLS_KEYBOARD_ANALOG_INDEX, i); - SetWindowTextForButton(hEdit, analogCode, getVirtualKeyName(analogCode)); - } - InvalidateRect(hDlg, 0, 0); - } - break; - case CONTROLS_DIRECT_INPUT_INDEX: - { - - for (u32 i = 0; i <= CONTROLS_IDC_EDIT_END - CONTROLS_IDC_EDIT_BEGIN; i++) { - HWND hEdit = GetDlgItem(hDlg, CONTROLS_IDC_EDIT_BEGIN + i); - int buttonCode = (int)pCtrlDlgState->pCtrlMap->GetBindCode(i); - char str[16]; - if (i >= IDC_EDIT_KEYUP - CONTROLS_IDC_EDIT_BEGIN) { - if (i >= IDC_EDIT_KEY_ANALOG_UP - CONTROLS_IDC_EDIT_BEGIN) { - Edit_SetReadOnly(hEdit, TRUE); - SetWindowTextA(hEdit, controllist[i]); - } else { - int n = 1; - if (buttonCode != -1) { - for (int j = buttonCode >> 8; j > 1; j >>= 1) { - n++; - } - snprintf(str, CONTROLS_BUTTONNAME_MAX, "%s", - controllist[(IDC_EDIT_KEYUP - CONTROLS_IDC_EDIT_BEGIN - 1) + n]); - } - SetWindowTextForButton(hEdit, buttonCode + 1, str); - } - continue; - } - snprintf(str, CONTROLS_BUTTONNAME_MAX, "%d", pCtrlDlgState->pCtrlMap->GetBindCode(i) + 1); - SetWindowTextForButton(hEdit, buttonCode + 1, str); - } - InvalidateRect(hDlg, 0, 0); - } - break; - case CONTROLS_XINPUT_INDEX: - { - for (u32 i = 0; i <= CONTROLS_IDC_EDIT_END - CONTROLS_IDC_EDIT_BEGIN; i++) { - HWND hEdit = GetDlgItem(hDlg, CONTROLS_IDC_EDIT_BEGIN + i); - if (i >= IDC_EDIT_KEY_ANALOG_UP - CONTROLS_IDC_EDIT_BEGIN) { - Edit_SetReadOnly(hEdit, TRUE); - SetWindowTextA(hEdit, controllist[i]); - continue; - } - u32 button = pCtrlDlgState->pCtrlMap->GetBindCode(i); - SetWindowTextForButton(hEdit, button, getXinputButtonName(button)); - } - InvalidateRect(hDlg, 0, 0); - } - break; - default: - break; - } // pCtrlDlgState->curDevice - } // TCN_SELCHANGING: - break; - default: - break; - } // ((NMHDR *)lParam)->code - } // WM_NOTIFY: - break; - case WM_PAINT: - { - return DefWindowProc(hDlg, message, wParam, lParam); - } - case WM_CTLCOLORSTATIC: - { - HDC hdc=(HDC)wParam; - HWND hCtrl = (HWND)lParam; - SetBkMode(hdc, TRANSPARENT); - int ctrlId = GetDlgCtrlID(hCtrl); - if (ctrlId >= IDC_EDIT_KEY_ANALOG_UP && ctrlId <= IDC_EDIT_KEY_ANALOG_RIGHT) { - SetTextColor(hdc, RGB(128,128,128)); - RECT rc = getRedrawRect(hCtrl); - TabCtrl_AdjustRect(pCtrlDlgState->hCtrlTab, TRUE, &rc); - RECT clientrc; - GetClientRect(hCtrl, &clientrc); - TabCtrl_AdjustRect(pCtrlDlgState->hCtrlTab, TRUE, &clientrc); - BitBlt(pCtrlDlgState->hbmPspImage, hdc, 0, 0, rc.right - rc.left, rc.bottom - rc.top, rc.left, rc.top); - char str[11]; - GetWindowTextA(hCtrl, str, 10); - DrawTextA(hdc, str, (int)strlen(str), &clientrc, DT_CENTER|DT_SINGLELINE); - } - return (LRESULT)GetStockObject(NULL_BRUSH); - } - case WM_CTLCOLOREDIT: - { - if ((HWND)lParam == GetDlgItem(hDlg, IDC_FORCE_INPUT_DEVICE)) - return FALSE; - HDC hdc = (HDC)wParam; - SetBkMode(hdc, TRANSPARENT); - SetTextColor(hdc, RGB(255, 0, 0)); - HWND hEdit = (HWND)lParam; - RECT rc = getRedrawRect(hEdit); - TabCtrl_AdjustRect(pCtrlDlgState->hCtrlTab, TRUE, &rc); - RECT clientrc; - GetClientRect(hEdit, &clientrc); - TabCtrl_AdjustRect(pCtrlDlgState->hCtrlTab, TRUE, &clientrc); - BitBlt(pCtrlDlgState->hbmPspImage, hdc, 0, 0, rc.right - rc.left, rc.bottom - rc.top, rc.left, rc.top); - char str[11]; - GetWindowTextA(hEdit, str, 10); - DrawTextA(hdc, str, (int)strlen(str), &clientrc, DT_CENTER|DT_SINGLELINE); - return (LRESULT)GetStockObject(NULL_BRUSH); - } - case WM_COMMAND: - if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) - { - if (LOWORD(wParam) == IDOK) { - g_Config.iForceInputDevice = (ComboBox_GetCurSel(GetDlgItem(hDlg, IDC_FORCE_INPUT_DEVICE)) - 1); - pCtrlDlgState->pCtrlMap->BindToDevices(); - saveControlsToFile(); - } - UnhookWindowsHookEx(pCtrlDlgState->pKeydownHook); - KillTimer(hDlg, pCtrlDlgState->timerId); - SetWindowLongPtr(pCtrlDlgState->hStaticPspImage, GWLP_WNDPROC, (LONG_PTR)pCtrlDlgState->orgPSPImageProc); - for (u32 i = CONTROLS_IDC_EDIT_BEGIN; i <= CONTROLS_IDC_EDIT_END; i++) { - HWND hEdit = GetDlgItem(hDlg, i); - SetWindowLongPtr(hEdit, GWLP_WNDPROC, (LONG_PTR)pCtrlDlgState->orgEditProc); - } - EndDialog(hDlg, LOWORD(wParam)); - if (pCtrlDlgState->hbmPspImage) { - DeleteObject(pCtrlDlgState->hbmPspImage); - pCtrlDlgState->hbmPspImage = 0; - } - if (pCtrlDlgState->pCtrlMap) { - delete pCtrlDlgState->pCtrlMap; - pCtrlDlgState->pCtrlMap = NULL; - } - if (pCtrlDlgState) { - delete pCtrlDlgState; - pCtrlDlgState = NULL; - } - return TRUE; - } else if (LOWORD(wParam) >= CONTROLS_IDC_EDIT_BEGIN && - LOWORD(wParam) <= IDC_EDIT_KEYRIGHT && - HIWORD(wParam) == EN_SETFOCUS) { - // send about buttonsMap-index of current focus Edit-Control to ControlMapping instance. - UINT nCtrlID = LOWORD(wParam); - if (nCtrlID < CONTROLS_IDC_EDIT_BEGIN || nCtrlID > IDC_EDIT_KEYRIGHT) { - break; - } - pCtrlDlgState->pCtrlMap->SetTargetButton(nCtrlID - CONTROLS_IDC_EDIT_BEGIN); - } - break; - } - return FALSE; - } - void Update() { InvalidateRect(hwndDisplay,0,0); diff --git a/Windows/XinputDevice.cpp b/Windows/XinputDevice.cpp index d3939ce4a..463b93f06 100644 --- a/Windows/XinputDevice.cpp +++ b/Windows/XinputDevice.cpp @@ -1,6 +1,8 @@ #include +#include "base/NativeApp.h" #include "Core/Config.h" #include "input/input_state.h" +#include "input/keycodes.h" #include "XinputDevice.h" #include "ControlMapping.h" @@ -9,27 +11,27 @@ #define XUSER_MAX_COUNT 4 #endif -// Yes, this maps more than the PSP has, but that's fine as this lets us -// map buttons to extra functionality like speedup. -unsigned int xinput_ctrl_map[] = { - XBOX_CODE_LEFTTRIGER, PAD_BUTTON_UNTHROTTLE, - XBOX_CODE_RIGHTTRIGER, PAD_BUTTON_BACK, - XINPUT_GAMEPAD_A, PAD_BUTTON_A, - XINPUT_GAMEPAD_B, PAD_BUTTON_B, - XINPUT_GAMEPAD_X, PAD_BUTTON_X, - XINPUT_GAMEPAD_Y, PAD_BUTTON_Y, - XINPUT_GAMEPAD_BACK, PAD_BUTTON_SELECT, - XINPUT_GAMEPAD_START, PAD_BUTTON_START, - XINPUT_GAMEPAD_LEFT_SHOULDER, PAD_BUTTON_LBUMPER, - XINPUT_GAMEPAD_RIGHT_SHOULDER, PAD_BUTTON_RBUMPER, - XINPUT_GAMEPAD_LEFT_THUMB, PAD_BUTTON_LEFT_THUMB, // Turbo - XINPUT_GAMEPAD_RIGHT_THUMB, PAD_BUTTON_RIGHT_THUMB, // Open PauseScreen - XINPUT_GAMEPAD_DPAD_UP, PAD_BUTTON_UP, - XINPUT_GAMEPAD_DPAD_DOWN, PAD_BUTTON_DOWN, - XINPUT_GAMEPAD_DPAD_LEFT, PAD_BUTTON_LEFT, - XINPUT_GAMEPAD_DPAD_RIGHT, PAD_BUTTON_RIGHT, +// Permanent map. Actual mapping happens elsewhere. +static const struct {int from, to;} xinput_ctrl_map[] = { + {XBOX_CODE_LEFTTRIGGER, KEYCODE_BUTTON_L2}, + {XBOX_CODE_RIGHTTRIGGER, KEYCODE_BUTTON_R2}, + {XINPUT_GAMEPAD_A, KEYCODE_BUTTON_A}, + {XINPUT_GAMEPAD_B, KEYCODE_BUTTON_B}, + {XINPUT_GAMEPAD_X, KEYCODE_BUTTON_X}, + {XINPUT_GAMEPAD_Y, KEYCODE_BUTTON_Y}, + {XINPUT_GAMEPAD_BACK, KEYCODE_BACK}, + {XINPUT_GAMEPAD_START, KEYCODE_BUTTON_START}, + {XINPUT_GAMEPAD_LEFT_SHOULDER, KEYCODE_BUTTON_L1}, + {XINPUT_GAMEPAD_RIGHT_SHOULDER, KEYCODE_BUTTON_R1}, + {XINPUT_GAMEPAD_LEFT_THUMB, KEYCODE_BUTTON_THUMBL}, + {XINPUT_GAMEPAD_RIGHT_THUMB, KEYCODE_BUTTON_THUMBR}, + {XINPUT_GAMEPAD_DPAD_UP, KEYCODE_DPAD_UP}, + {XINPUT_GAMEPAD_DPAD_DOWN, KEYCODE_DPAD_DOWN}, + {XINPUT_GAMEPAD_DPAD_LEFT, KEYCODE_DPAD_LEFT}, + {XINPUT_GAMEPAD_DPAD_RIGHT, KEYCODE_DPAD_RIGHT}, }; -static const unsigned int xinput_ctrl_map_size = sizeof(xinput_ctrl_map); + +static const unsigned int xinput_ctrl_map_size = sizeof(xinput_ctrl_map) / sizeof(xinput_ctrl_map[0]); XinputDevice::XinputDevice() { ZeroMemory( &this->prevState, sizeof(this->prevState) ); @@ -64,7 +66,7 @@ int XinputDevice::UpdateState(InputState &input_state) { } if ( dwResult == ERROR_SUCCESS ) { - ApplyDiff(state, input_state); + ApplyButtons(state, input_state); Stick left = NormalizedDeadzoneFilter(state.Gamepad.sThumbLX, state.Gamepad.sThumbLY); Stick right = NormalizedDeadzoneFilter(state.Gamepad.sThumbRX, state.Gamepad.sThumbRY); input_state.pad_lstick_x += left.x; @@ -79,6 +81,21 @@ int XinputDevice::UpdateState(InputState &input_state) { this->prevState = state; this->check_delay = 0; + AxisInput axis; + axis.deviceId = DEVICE_ID_KEYBOARD; + axis.axisId = JOYSTICK_AXIS_X; + axis.value = left.x; + NativeAxis(axis); + axis.axisId = JOYSTICK_AXIS_Y; + axis.value = left.y; + NativeAxis(axis); + axis.axisId = JOYSTICK_AXIS_Z; + axis.value = right.x; + NativeAxis(axis); + axis.axisId = JOYSTICK_AXIS_RZ; + axis.value = right.y; + NativeAxis(axis); + // If there's an XInput pad, skip following pads. This prevents DInput and XInput // from colliding. return UPDATESTATE_SKIP_PAD; @@ -128,8 +145,8 @@ struct xinput_button_name { }; const xinput_button_name xinput_name_map[] = { - {XBOX_CODE_LEFTTRIGER, "LT"}, - {XBOX_CODE_RIGHTTRIGER, "RT"}, + {XBOX_CODE_LEFTTRIGGER, "LT"}, + {XBOX_CODE_RIGHTTRIGGER, "RT"}, {XINPUT_GAMEPAD_A, "A"}, {XINPUT_GAMEPAD_B, "B"}, {XINPUT_GAMEPAD_X, "X"}, @@ -145,6 +162,7 @@ const xinput_button_name xinput_name_map[] = { {XINPUT_GAMEPAD_DPAD_LEFT, "Left"}, {XINPUT_GAMEPAD_DPAD_RIGHT, "Right"}, }; + static const int xbutton_name_map_size = sizeof(xinput_name_map) / sizeof(xinput_button_name); const char * getXinputButtonName(unsigned int button) { @@ -155,22 +173,14 @@ const char * getXinputButtonName(unsigned int button) { return 0; } -void XinputDevice::ApplyDiff(XINPUT_STATE &state, InputState &input_state) { - // Skip XBOX_CODE_LIFT/RIGHT TRIGER. it's virtual code for Mapping. - for (int i = 0; i < sizeof(xinput_ctrl_map)/sizeof(xinput_ctrl_map[0]); i += 2) { - if (state.Gamepad.wButtons & (WORD)(xinput_ctrl_map[i])) { - input_state.pad_buttons |= (int)xinput_ctrl_map[i + 1]; - } - // Effective use of triggers that are not used. - if (xinput_ctrl_map[i] == XBOX_CODE_LEFTTRIGER && - state.Gamepad.bLeftTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD) { - input_state.pad_buttons |= xinput_ctrl_map[i + 1]; - } - if (xinput_ctrl_map[i] == XBOX_CODE_RIGHTTRIGER && - state.Gamepad.bRightTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD) { - input_state.pad_buttons |= xinput_ctrl_map[i + 1]; - } - } +void XinputDevice::ApplyButtons(XINPUT_STATE &state, InputState &input_state) { + u32 buttons = state.Gamepad.wButtons; + // Simulate some extra buttons from axes. This should be done elsewhere really. + + if (state.Gamepad.bLeftTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD) + buttons |= XBOX_CODE_LEFTTRIGGER; + if (state.Gamepad.bLeftTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD) + buttons |= XBOX_CODE_RIGHTTRIGGER; const SHORT rthreshold = 22000; @@ -178,32 +188,53 @@ void XinputDevice::ApplyDiff(XINPUT_STATE &state, InputState &input_state) { case 0: break; case 1: - if (state.Gamepad.sThumbRX > rthreshold) input_state.pad_buttons |= PAD_BUTTON_RIGHT; - else if (state.Gamepad.sThumbRX < -rthreshold) input_state.pad_buttons |= PAD_BUTTON_LEFT; - if (state.Gamepad.sThumbRY > rthreshold) input_state.pad_buttons |= PAD_BUTTON_UP; - else if (state.Gamepad.sThumbRY < -rthreshold) input_state.pad_buttons |= PAD_BUTTON_DOWN; + if (state.Gamepad.sThumbRX > rthreshold) buttons |= XINPUT_GAMEPAD_DPAD_RIGHT; + else if (state.Gamepad.sThumbRX < -rthreshold) buttons |= XINPUT_GAMEPAD_DPAD_LEFT; + if (state.Gamepad.sThumbRY > rthreshold) buttons |= XINPUT_GAMEPAD_DPAD_UP; + else if (state.Gamepad.sThumbRY < -rthreshold) buttons |= XINPUT_GAMEPAD_DPAD_DOWN; break; case 2: - if (state.Gamepad.sThumbRX > rthreshold) input_state.pad_buttons |= PAD_BUTTON_B; - else if (state.Gamepad.sThumbRX < -rthreshold) input_state.pad_buttons |= PAD_BUTTON_X; - if (state.Gamepad.sThumbRY > rthreshold) input_state.pad_buttons |= PAD_BUTTON_Y; - else if (state.Gamepad.sThumbRY < -rthreshold) input_state.pad_buttons |= PAD_BUTTON_A; + if (state.Gamepad.sThumbRX > rthreshold) buttons |= XINPUT_GAMEPAD_B; + else if (state.Gamepad.sThumbRX < -rthreshold) buttons |= XINPUT_GAMEPAD_X; + if (state.Gamepad.sThumbRY > rthreshold) buttons |= XINPUT_GAMEPAD_Y; + else if (state.Gamepad.sThumbRY < -rthreshold) buttons |= XINPUT_GAMEPAD_A; break; case 3: - if (state.Gamepad.sThumbRX > rthreshold) input_state.pad_buttons |= PAD_BUTTON_RBUMPER; - else if (state.Gamepad.sThumbRX < -rthreshold) input_state.pad_buttons |= PAD_BUTTON_LBUMPER; + if (state.Gamepad.sThumbRX > rthreshold) buttons |= XINPUT_GAMEPAD_RIGHT_SHOULDER; + else if (state.Gamepad.sThumbRX < -rthreshold) buttons |= XINPUT_GAMEPAD_LEFT_SHOULDER; break; case 4: - if (state.Gamepad.sThumbRX > rthreshold) input_state.pad_buttons |= PAD_BUTTON_RBUMPER; - else if (state.Gamepad.sThumbRX < -rthreshold) input_state.pad_buttons |= PAD_BUTTON_LBUMPER; - if (state.Gamepad.sThumbRY > rthreshold) input_state.pad_buttons |= PAD_BUTTON_Y; - else if (state.Gamepad.sThumbRY < -rthreshold) input_state.pad_buttons |= PAD_BUTTON_A; + if (state.Gamepad.sThumbRX > rthreshold) buttons |= XINPUT_GAMEPAD_RIGHT_SHOULDER; + else if (state.Gamepad.sThumbRX < -rthreshold) buttons |= XINPUT_GAMEPAD_LEFT_SHOULDER; + if (state.Gamepad.sThumbRY > rthreshold) buttons |= XINPUT_GAMEPAD_Y; + else if (state.Gamepad.sThumbRY < -rthreshold) buttons |= XINPUT_GAMEPAD_A; break; case 5: - if (state.Gamepad.sThumbRX > rthreshold) input_state.pad_buttons |= PAD_BUTTON_RIGHT; - else if (state.Gamepad.sThumbRX < -rthreshold) input_state.pad_buttons |= PAD_BUTTON_LEFT; + if (state.Gamepad.sThumbRX > rthreshold) buttons |= XINPUT_GAMEPAD_DPAD_RIGHT; + else if (state.Gamepad.sThumbRX < -rthreshold) buttons |= XINPUT_GAMEPAD_DPAD_LEFT; break; } + + u32 downMask = buttons & (~prevState.Gamepad.wButtons); + u32 upMask = (~buttons) & prevState.Gamepad.wButtons; + prevButtons = buttons; + + for (int i = 0; i < xinput_ctrl_map_size; i++) { + if (downMask & xinput_ctrl_map[i].from) { + KeyInput key; + key.deviceId = DEVICE_ID_X360_0; + key.flags = KEY_DOWN; + key.keyCode = xinput_ctrl_map[i].to; + NativeKey(key); + } + if (upMask & xinput_ctrl_map[i].from) { + KeyInput key; + key.deviceId = DEVICE_ID_X360_0; + key.flags = KEY_UP; + key.keyCode = xinput_ctrl_map[i].to; + NativeKey(key); + } + } } int XinputDevice::UpdateRawStateSingle(RawInputState &rawState) @@ -235,9 +266,9 @@ int XinputDevice::UpdateRawStateSingle(RawInputState &rawState) } } if (state.Gamepad.bLeftTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD) { - rawState.button = XBOX_CODE_LEFTTRIGER; + rawState.button = XBOX_CODE_LEFTTRIGGER; } else if (state.Gamepad.bRightTrigger > XINPUT_GAMEPAD_TRIGGER_THRESHOLD) { - rawState.button = XBOX_CODE_RIGHTTRIGER; + rawState.button = XBOX_CODE_RIGHTTRIGGER; } return TRUE; } diff --git a/Windows/XinputDevice.h b/Windows/XinputDevice.h index 6b5f44e7b..1693a5ada 100644 --- a/Windows/XinputDevice.h +++ b/Windows/XinputDevice.h @@ -13,9 +13,10 @@ public: virtual bool IsPad() { return true; } int UpdateRawStateSingle(RawInputState &rawState); private: - void ApplyDiff(XINPUT_STATE &state, InputState &input_state); + void ApplyButtons(XINPUT_STATE &state, InputState &input_state); int gamepad_idx; int check_delay; XINPUT_STATE prevState; + u32 prevButtons; }; diff --git a/Windows/ppsspp.rc b/Windows/ppsspp.rc index 0fb48aeb0c30d255410e0a4f56b76436886bd66d..062cb7aa716650c7701081e837a391cebe0b29d9 100644 GIT binary patch delta 18 acmdmVo$0}9rVR=%lS5)fHnT;o2?PL6^#_#z delta 2550 zcmbtWzi-n}5I#B}0Zm00O2rR_EHq%Lj$@N15|qSF(x^?-I7wTCDht{S2n48wPAvQZ zNR{4Sz|2BnM@a0f3@jb_4_Nu`9M?@^)HqdSKj-$^@j2X%!Tb_@ z(|cFoD?Ei4?<@1_=bcG))0%9u7j-I96?;8+)54{}^F74z1lKd##y<`7>`e))+p?Zl zMWg?HSWINV%mP*zl%bp|7Pk`oWSp3pRo~3ir8d0=XoREA;>WWl?qy+;Gs>zcldC?Y((2FMDRq>(s-_Ba5y&NE z$c7z8(gh`qG6wSUu+KKs)ev?y;OcZw{4`{Y<#jy@yC&LY#WH$;r%RrKeC^7qQXMevG=>7`AfUsRrzrV2BkzR{bsx+UZEQ_A{G9uVD=_`iPyTJct)?6XFDQ6a%$7 zh#GRCp+|E!59>1q?vS?*I@boOpVb%iEzVjj4w{4BdQ$I2)MW#G#e+ilTW7&@pI83o z$5MEN2DxX27DCop>1@U7