diff --git a/CMakeLists.txt b/CMakeLists.txt index 2983b2a397..bd74628c85 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,6 +31,7 @@ include(SearchForStuff) include(SelectPcsx2Plugins) # Must be done after SearchForStuff +get_git_version_info() write_svnrev_h() if(NOT NO_TRANSLATION) diff --git a/cmake/BuildParameters.cmake b/cmake/BuildParameters.cmake index 707eb91f56..8c41725623 100644 --- a/cmake/BuildParameters.cmake +++ b/cmake/BuildParameters.cmake @@ -77,6 +77,11 @@ if(PACKAGE_MODE) add_definitions(-DPLUGIN_DIR_COMPILATION=${PLUGIN_DIR} -DGAMEINDEX_DIR_COMPILATION=${GAMEINDEX_DIR} -DDOC_DIR_COMPILATION=${DOC_DIR}) endif() +if(APPLE) + option(OSX_USE_DEFAULT_SEARCH_PATH "Don't prioritize system library paths" OFF) + option(SKIP_POSTPROCESS_BUNDLE "Skip postprocessing bundle for redistributability" OFF) +endif() + #------------------------------------------------------------------------------- # Compiler extra #------------------------------------------------------------------------------- @@ -468,3 +473,33 @@ if(CMAKE_BUILD_TYPE MATCHES "Release" OR PACKAGE_MODE) message(WARNING "GTK3 is highly experimental besides it requires a wxWidget built with __WXGTK3__ support !!!") endif() endif() + + +#------------------------------------------------------------------------------- +# MacOS-specific things +#------------------------------------------------------------------------------- + +set(CMAKE_OSX_DEPLOYMENT_TARGET 10.9) + +# CMake defaults the suffix for modules to .so on macOS but wx tells us that the +# extension is .dylib (so that's what we search for) +if(APPLE) + set(CMAKE_SHARED_MODULE_SUFFIX ".dylib") +endif() + +if(CMAKE_SYSTEM_NAME MATCHES "Darwin") + if(NOT OSX_USE_DEFAULT_SEARCH_PATH) + # Hack up the path to prioritize the path to built-in OS libraries to + # increase the chance of not depending on a bunch of copies of them + # installed by MacPorts, Fink, Homebrew, etc, and ending up copying + # them into the bundle. Since we depend on libraries which are not + # part of OS X (wx, etc.), however, don't remove the default path + # entirely. This is still kinda evil, since it defeats the user's + # path settings... + # See http://www.cmake.org/cmake/help/v3.0/command/find_program.html + list(APPEND CMAKE_PREFIX_PATH "/usr") + endif() + + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-dead_strip,-dead_strip_dylibs") + set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,-dead_strip,-dead_strip_dylibs") +endif() \ No newline at end of file diff --git a/cmake/Pcsx2PostprocessBundle.cmake b/cmake/Pcsx2PostprocessBundle.cmake new file mode 100644 index 0000000000..b74431b37f --- /dev/null +++ b/cmake/Pcsx2PostprocessBundle.cmake @@ -0,0 +1,10 @@ +# This file should be run with cmake -DPCSX2_BUNDLE_PATH=path -P Pcsx2PostprocessBundle.cmake + +get_filename_component(PCSX2_BUNDLE_PATH "${PCSX2_BUNDLE_PATH}" ABSOLUTE) + +# Fixup plugins too +file(GLOB_RECURSE plugins "${PCSX2_BUNDLE_PATH}/Contents/MacOS/*.dylib") + +include(BundleUtilities) +set(BU_CHMOD_BUNDLE_ITEMS ON) +fixup_bundle("${PCSX2_BUNDLE_PATH}" "${plugins}" "") diff --git a/cmake/Pcsx2Utils.cmake b/cmake/Pcsx2Utils.cmake index 06ebe8dd54..84304b6902 100644 --- a/cmake/Pcsx2Utils.cmake +++ b/cmake/Pcsx2Utils.cmake @@ -35,7 +35,7 @@ function(detectOperatingSystem) endif() endfunction() -function(write_svnrev_h) +function(get_git_version_info) set(PCSX2_WC_TIME 0) set(PCSX2_GIT_REV "") if (GIT_FOUND AND EXISTS ${PROJECT_SOURCE_DIR}/.git) @@ -50,9 +50,24 @@ function(write_svnrev_h) OUTPUT_VARIABLE PCSX2_GIT_REV OUTPUT_STRIP_TRAILING_WHITESPACE) endif() + if(PCSX2_GIT_REV) + set(PCSX2_VERSION_LONG "${PCSX2_GIT_REV}") + string(REGEX MATCH "[0-9]+\\.[0-9]+(\\.[0-9]+)?(-[a-z][a-z0-9]+)?" PCSX2_VERSION_SHORT "${PCSX2_VERSION_LONG}") + else() + set(PCSX2_VERSION_LONG "Unknown (git unavailable)") + set(PCSX2_VERSION_SHORT "Unknown") + endif() if ("${PCSX2_WC_TIME}" STREQUAL "") set(PCSX2_WC_TIME 0) endif() + + set(PCSX2_WC_TIME "${PCSX2_WC_TIME}" PARENT_SCOPE) + set(PCSX2_GIT_REV "${PCSX2_GIT_REV}" PARENT_SCOPE) + set(PCSX2_VERSION_LONG "${PCSX2_VERSION_LONG}" PARENT_SCOPE) + set(PCSX2_VERSION_SHORT "${PCSX2_VERSION_SHORT}" PARENT_SCOPE) +endfunction() + +function(write_svnrev_h) file(WRITE ${CMAKE_BINARY_DIR}/common/include/svnrev.h "#define SVN_REV ${PCSX2_WC_TIME}ll \n#define SVN_MODS 0\n#define GIT_REV \"${PCSX2_GIT_REV}\"") endfunction() @@ -114,6 +129,14 @@ macro(add_pcsx2_plugin lib srcs libs flags) else(PACKAGE_MODE) install(TARGETS ${lib} DESTINATION ${CMAKE_SOURCE_DIR}/bin/plugins) endif(PACKAGE_MODE) + if (APPLE) + # Copy to app bundle + add_custom_command(TARGET ${lib} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E make_directory "$/plugins" + COMMAND ${CMAKE_COMMAND} -E copy_if_different "$" "$/plugins/" + ) + add_dependencies(pcsx2-postprocess-bundle ${lib}) + endif() endmacro(add_pcsx2_plugin) macro(add_pcsx2_lib lib srcs libs flags) diff --git a/cmake/SelectPcsx2Plugins.cmake b/cmake/SelectPcsx2Plugins.cmake index 00bf22e6ca..2f1e445b62 100644 --- a/cmake/SelectPcsx2Plugins.cmake +++ b/cmake/SelectPcsx2Plugins.cmake @@ -245,9 +245,10 @@ else() endif() # old version of the plugin that still supports SDL1 -if(wxWidgets_FOUND AND GTKn_FOUND AND SDLn_FOUND AND X11_FOUND) +# Was never ported to macOS +if(wxWidgets_FOUND AND GTKn_FOUND AND SDLn_FOUND AND X11_FOUND AND NOT APPLE) set(onepad_legacy TRUE) -elseif(NOT EXISTS "${CMAKE_SOURCE_DIR}/plugins/onepad_legacy") +elseif(NOT EXISTS "${CMAKE_SOURCE_DIR}/plugins/onepad_legacy" OR APPLE) set(onepad_legacy FALSE) else() set(onepad_legacy FALSE) diff --git a/common/include/Utilities/Console.h b/common/include/Utilities/Console.h index e83b0fab36..0a6eb2ef0a 100644 --- a/common/include/Utilities/Console.h +++ b/common/include/Utilities/Console.h @@ -233,7 +233,7 @@ public: extern IConsoleWriter Console; -#if defined(__unix__) +#if defined(__unix__) || defined(__APPLE__) extern void Console_SetStdout(FILE *fp); #endif extern void Console_SetActiveHandler(const IConsoleWriter &writer, FILE *flushfp = NULL); diff --git a/common/src/Utilities/Darwin/DarwinSemaphore.cpp b/common/src/Utilities/Darwin/DarwinSemaphore.cpp index 7584c944bb..dea234ca7d 100644 --- a/common/src/Utilities/Darwin/DarwinSemaphore.cpp +++ b/common/src/Utilities/Darwin/DarwinSemaphore.cpp @@ -47,14 +47,18 @@ // // -------------------------------------------------------------------------------------- -#define MACH_CHECK(mach_retval) \ - do { \ - kern_return_t _kr = (mach_retval); \ - if (_kr != KERN_SUCCESS) { \ - fprintf(stderr, "mach error: %s", mach_error_string(_kr)); \ - assert(_kr == KERN_SUCCESS); \ - } \ - } while (0) +static void MACH_CHECK(kern_return_t mach_retval) +{ + switch (mach_retval) { + case KERN_SUCCESS: break; + case KERN_ABORTED: // Awoken due reason unrelated to semaphore (e.g. pthread_cancel) + pthread_testcancel(); // Unlike sem_wait, mach semaphore ops aren't cancellation points + // fallthrough + default: + fprintf(stderr, "mach error: %s", mach_error_string(mach_retval)); + assert(mach_retval == KERN_SUCCESS); + } +} Threading::Semaphore::Semaphore() { diff --git a/common/src/Utilities/Linux/LnxHostSys.cpp b/common/src/Utilities/Linux/LnxHostSys.cpp index 9c5250d053..f25d9d7c40 100644 --- a/common/src/Utilities/Linux/LnxHostSys.cpp +++ b/common/src/Utilities/Linux/LnxHostSys.cpp @@ -86,7 +86,12 @@ void _platform_InstallSignalHandler() sigemptyset(&sa.sa_mask); sa.sa_flags = SA_SIGINFO; sa.sa_sigaction = SysPageFaultSignalFilter; +#ifdef __APPLE__ + // MacOS uses SIGBUS for memory permission violations + sigaction(SIGBUS, &sa, NULL); +#else sigaction(SIGSEGV, &sa, NULL); +#endif } static __ri void PageSizeAssertionTest(size_t size) diff --git a/common/src/Utilities/Mutex.cpp b/common/src/Utilities/Mutex.cpp index 9f48bc4def..2b968dd066 100644 --- a/common/src/Utilities/Mutex.cpp +++ b/common/src/Utilities/Mutex.cpp @@ -61,22 +61,21 @@ static int xpthread_mutex_timedlock( int err = 0; while ((err = pthread_mutex_trylock(mutex)) == EBUSY) { + // check if the timeout has expired, gettimeofday() is implemented + // efficiently (in userspace) on OSX + struct timeval now; + gettimeofday(&now, NULL); + if (now.tv_sec > abs_timeout->tv_sec + || (now.tv_sec == abs_timeout->tv_sec + && (u64)now.tv_usec * 1000ULL > (u64)abs_timeout->tv_nsec)) { + return ETIMEDOUT; + } + // acquiring lock failed, sleep some struct timespec ts; ts.tv_sec = 0; ts.tv_nsec = TIMEDLOCK_EMU_SLEEP_NS; - int status; - while ((status = nanosleep(&ts, &ts)) == -1) - ; - - // check if the timeout has expired, gettimeofday() is implemented - // efficiently (in userspace) on OSX - struct timeval now; - int res = gettimeofday(&now, NULL); - if (abs_timeout->tv_sec == 0 || now.tv_sec > abs_timeout->tv_sec || - (u64)now.tv_usec * 1000ULL > (u64)abs_timeout->tv_nsec) { - return ETIMEDOUT; - } + while (nanosleep(&ts, &ts) == -1); } return err; diff --git a/pcsx2/CMakeLists.txt b/pcsx2/CMakeLists.txt index 07d6bc8cdb..2c7cda13a2 100644 --- a/pcsx2/CMakeLists.txt +++ b/pcsx2/CMakeLists.txt @@ -410,7 +410,7 @@ set(pcsx2LinuxSources set(pcsx2OSXSources gui/CpuUsageProviderLnx.cpp -# Linux/LnxConsolePipe.cpp + Linux/LnxConsolePipe.cpp # Linux/LnxKeyCodes.cpp Darwin/DarwinFlatFileReader.cpp ) @@ -745,6 +745,36 @@ if(NOT USE_CLANG) endif() endif() +if (APPLE) + # MacOS defaults to having a maximum protection of the __DATA segment of rw (non-executable) + # We have a bunch of page-sized arrays in bss that we use for jit + # Obviously not being able to make those arrays executable would be a problem + target_link_options(${Output} PRIVATE -Wl,-segprot,__DATA,rwx,rw) + + set_target_properties(${Output} PROPERTIES + MACOSX_BUNDLE true + MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/gui/Resources/Info.plist.in" + OUTPUT_NAME PCSX2 + ) + + target_sources(${Output} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/gui/Resources/PCSX2.icns") + set_source_files_properties("${CMAKE_CURRENT_SOURCE_DIR}/gui/Resources/PCSX2.icns" PROPERTIES MACOSX_PACKAGE_LOCATION Resources) + + # If they say to skip postprocess bundle, leave the target in but make it so they have + # to manually run it + if (SKIP_POSTPROCESS_BUNDLE) + set(postprocessBundleType "") + else() + set(postprocessBundleType ALL) + endif() + # Use custom_target and not custom_command so plugins can add themselves as dependencies + add_custom_target(pcsx2-postprocess-bundle ${postprocessBundleType} + COMMAND ${CMAKE_COMMAND} "-DPCSX2_BUNDLE_PATH=$/../.." + -P ${CMAKE_SOURCE_DIR}/cmake/Pcsx2PostprocessBundle.cmake + ) + add_dependencies(pcsx2-postprocess-bundle ${Output}) +endif() + if(dev9ghzdrk) if(PACKAGE_MODE) install(CODE "execute_process(COMMAND /bin/bash -c \"echo 'Enabling networking capability on Linux...';set -x; [ -f ${BIN_DIR}/${Output} ] && sudo setcap 'CAP_NET_RAW+eip CAP_NET_ADMIN+eip' ${BIN_DIR}/${Output}; set +x\")") diff --git a/pcsx2/DebugTools/Debug.h b/pcsx2/DebugTools/Debug.h index 6dfece3e73..8adfc0c505 100644 --- a/pcsx2/DebugTools/Debug.h +++ b/pcsx2/DebugTools/Debug.h @@ -347,7 +347,6 @@ extern void __Log( const char* fmt, ... ); # define SetDoubleBuffered(x) // TODO OSX OsxKeyCodes.cpp pending -# define NewPipeRedir(x) NULL #endif #define macTrace(trace) SysTraceActive(trace) && SysTrace.trace.Write diff --git a/pcsx2/gui/Resources/Info.plist.in b/pcsx2/gui/Resources/Info.plist.in new file mode 100644 index 0000000000..e519ca6f8e --- /dev/null +++ b/pcsx2/gui/Resources/Info.plist.in @@ -0,0 +1,42 @@ + + + + + CFBundleDocumentTypes + + + CFBundleTypeExtensions + + iso + cso + + CFBundleTypeIconFile + PCSX2.icns + CFBundleTypeName + PS2 Game + CFBundleTypeRole + Viewer + + + CFBundleExecutable + PCSX2 + CFBundleIconFile + PCSX2.icns + CFBundleIdentifier + net.pcsx2.pcsx2 + CFBundleDevelopmentRegion + English + CFBundlePackageType + APPL + CFBundleShortVersionString + ${PCSX2_VERSION_SHORT} + CFBundleVersion + ${PCSX2_VERSION_LONG} + NSHumanReadableCopyright + Licensed under GPL version 3 + LSMinimumSystemVersion + ${CMAKE_OSX_DEPLOYMENT_TARGET} + NSHighResolutionCapable + + + diff --git a/pcsx2/gui/Resources/PCSX2.icns b/pcsx2/gui/Resources/PCSX2.icns new file mode 100644 index 0000000000..46ed9be85f Binary files /dev/null and b/pcsx2/gui/Resources/PCSX2.icns differ diff --git a/plugins/onepad/Linux/linux.cpp b/plugins/onepad/Linux/linux.cpp index 685b7d212c..d5b62bf6a0 100644 --- a/plugins/onepad/Linux/linux.cpp +++ b/plugins/onepad/Linux/linux.cpp @@ -28,8 +28,10 @@ #include #include "wx_dialog/dialog.h" +#ifndef __APPLE__ Display *GSdsp; Window GSwin; +#endif void SysMessage(const char *fmt, ...) { @@ -67,8 +69,10 @@ PADtest() s32 _PADopen(void *pDsp) { +#ifndef __APPLE__ GSdsp = *(Display **)pDsp; GSwin = (Window) * (((u32 *)pDsp) + 1); +#endif return 0; } @@ -100,6 +104,7 @@ void PollForJoystickInput(int cpad) EXPORT_C_(void) PADupdate(int pad) { +#ifndef __APPLE__ // Gamepad inputs don't count as an activity. Therefore screensaver will // be fired after a couple of minute. // Emulate an user activity @@ -109,6 +114,7 @@ PADupdate(int pad) // 1 call every 4096 Vsync is enough XResetScreenSaver(GSdsp); } +#endif // Actually PADupdate is always call with pad == 0. So you need to update both // pads -- Gregory @@ -118,7 +124,7 @@ PADupdate(int pad) for (int cpad = 0; cpad < GAMEPAD_NUMBER; cpad++) { g_key_status.keyboard_state_acces(cpad); } - PollForX11KeyboardInput(); + UpdateKeyboardInput(); // Get joystick state + Commit for (int cpad = 0; cpad < GAMEPAD_NUMBER; cpad++) { diff --git a/plugins/onepad/keyboard.cpp b/plugins/onepad/keyboard.cpp index fd73d81f12..572f2c621e 100644 --- a/plugins/onepad/keyboard.cpp +++ b/plugins/onepad/keyboard.cpp @@ -27,6 +27,8 @@ #if defined(__unix__) #include #include +#elif defined(__APPLE__) +#include #endif #include "keyboard.h" @@ -41,7 +43,75 @@ char *KeysymToChar(int keysym) } #endif -#if defined(__unix__) +/// g_key_status.press but with proper handling for analog buttons +static void PressButton(u32 pad, u32 button) { + // Analog controls. + if (IsAnalogKey(button)) { + switch (button) { + case PAD_R_LEFT: + case PAD_R_UP: + case PAD_L_LEFT: + case PAD_L_UP: + g_key_status.press(pad, button, -MAX_ANALOG_VALUE); + break; + case PAD_R_RIGHT: + case PAD_R_DOWN: + case PAD_L_RIGHT: + case PAD_L_DOWN: + g_key_status.press(pad, button, MAX_ANALOG_VALUE); + break; + } + } else { + g_key_status.press(pad, button); + } +} + +#if defined(__APPLE__) +// Mac keyboard input code is based on Dolphin's Source/Core/InputCommon/ControllerInterface/Quartz/QuartzKeyboardAndMouse.mm +// Copyright 2016 Dolphin Emulator Project +// Licensed under GPLv2+ + +// All keycodes are 16 bits or less, so we use top 16 bits to differentiate source +// Keyboard keys use discriminator 0 +// Mouse buttons use discriminator 1 + +void UpdateKeyboardInput() { + for (int pad = 0; pad < GAMEPAD_NUMBER; pad++) { + const auto& map = g_conf.keysym_map[pad]; + // If we loop over all keys press/release based on current state, + // joystick axes (which have two bound keys) will always go to the later-polled key + // Instead, release all keys first and then set the ones that are pressed + for (const auto& key : map) g_key_status.release(pad, key.second); + for (const auto& key : map) { + bool state; + if (key.first >> 16 == 0) { + state = CGEventSourceKeyState(kCGEventSourceStateHIDSystemState, key.first); + } else { + state = CGEventSourceButtonState(kCGEventSourceStateHIDSystemState, (CGMouseButton)(key.first & 0xFFFF)); + } + if (state) PressButton(pad, key.second); + } + } +} + +bool PollForNewKeyboardKeys(u32 &pkey) { + // All keycodes in are 0x7e or lower. If you notice + // keys that aren't being recognized, bump this number up! + for (int key = 0; key < 0x80; key++) { + if (CGEventSourceKeyState(kCGEventSourceStateHIDSystemState, key)) { + pkey = key == kVK_Escape ? 0 : key; + return true; + } + } + for (auto btn : {kCGMouseButtonLeft, kCGMouseButtonCenter, kCGMouseButtonRight}) { + if (CGEventSourceButtonState(kCGEventSourceStateHIDSystemState, btn)) { + pkey = btn | (1 << 16); + return true; + } + } + return false; +} +#elif defined(__unix__) static bool s_grab_input = false; static bool s_Shift = false; static unsigned int s_previous_mouse_x = 0; @@ -82,24 +152,7 @@ static void AnalyzeKeyEvent(keyEvent &evt) } } - // Analog controls. - if (IsAnalogKey(index)) { - switch (index) { - case PAD_R_LEFT: - case PAD_R_UP: - case PAD_L_LEFT: - case PAD_L_UP: - g_key_status.press(pad, index, -MAX_ANALOG_VALUE); - break; - case PAD_R_RIGHT: - case PAD_R_DOWN: - case PAD_L_RIGHT: - case PAD_L_DOWN: - g_key_status.press(pad, index, MAX_ANALOG_VALUE); - break; - } - } else if (index != -1) - g_key_status.press(pad, index); + PressButton(pad, index); //PAD_LOG("Key pressed:%d\n", index); @@ -191,7 +244,7 @@ static void AnalyzeKeyEvent(keyEvent &evt) } } -void PollForX11KeyboardInput() +void UpdateKeyboardInput() { keyEvent evt = {0}; XEvent E = {0}; @@ -222,7 +275,7 @@ void PollForX11KeyboardInput() } } -bool PollX11KeyboardMouseEvent(u32 &pkey) +bool PollForNewKeyboardKeys(u32 &pkey) { GdkEvent *ev = gdk_event_get(); diff --git a/plugins/onepad/keyboard.h b/plugins/onepad/keyboard.h index beb20aa310..a6e0681e55 100644 --- a/plugins/onepad/keyboard.h +++ b/plugins/onepad/keyboard.h @@ -24,12 +24,14 @@ #include "onepad.h" -#if defined(__unix__) +#if defined(__unix__) || defined(__APPLE__) +extern void UpdateKeyboardInput(); +extern bool PollForNewKeyboardKeys(u32 &pkey); +#ifndef __APPLE__ extern Display *GSdsp; -extern void PollForX11KeyboardInput(); -extern bool PollX11KeyboardMouseEvent(u32 &pkey); extern Window GSwin; +#endif #else diff --git a/plugins/onepad/onepad.cpp b/plugins/onepad/onepad.cpp index c8653cf794..003157b38b 100644 --- a/plugins/onepad/onepad.cpp +++ b/plugins/onepad/onepad.cpp @@ -183,7 +183,7 @@ PADopen(void *pDsp) g_ev_fifo.reset(); -#if defined(__unix__) +#if defined(__unix__) || defined(__APPLE__) GamePad::EnumerateGamePads(s_vgamePad); #endif return _PADopen(pDsp); diff --git a/plugins/onepad/onepad.h b/plugins/onepad/onepad.h index 2dd787d592..b20abd5290 100644 --- a/plugins/onepad/onepad.h +++ b/plugins/onepad/onepad.h @@ -101,7 +101,7 @@ enum gamePadValues { PAD_R_LEFT // Right joystick (Left) ← }; -#if defined(__unix__) +#if defined(__unix__) || defined(__APPLE__) #include "GamePad.h" #endif #include "bitwise.h" diff --git a/plugins/onepad/res/game_controller_db.txt b/plugins/onepad/res/game_controller_db.txt index feda960850..7e561bb27a 100644 --- a/plugins/onepad/res/game_controller_db.txt +++ b/plugins/onepad/res/game_controller_db.txt @@ -1,4 +1,127 @@ -# Linux - from # https://github.com/gabomdq/ +# Mac OS, Linux - from # https://github.com/gabomdq/ +# Mac OS X +030000008f0e00000300000009010000,2In1 USB Joystick,+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X, +03000000c82d00000650000001000000,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000022000000090000001000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000203800000900000000010000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00000190000001000000,8Bitdo NES30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000102800000900000000000000,8Bitdo SFC30 GamePad Joystick,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00000161000000010000,8BitDo SN30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00000260000001000000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00000261000000010000,8BitDo SN30 Pro+,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00000031000001000000,8BitDo Wireless Adapter,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000c82d00003032000000010000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a31,start:b11,x:b4,y:b3,platform:Mac OS X, +03000000a00500003232000008010000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000a00500003232000009010000,8Bitdo Zero GamePad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000050b00000045000031000000,ASUS Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X, +030000008305000031b0000000000000,Cideko AK08b,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000260900008888000088020000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Mac OS X, +03000000a306000022f6000001030000,Cyborg V.3 Rumble Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000ad1b000001f9000000000000,Gamestop BB-070 X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X, +030000006f0e00000102000000000000,GameStop Xbox 360 Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +030000007d0400000540000001010000,Gravis Eliminator GamePad Pro,a:b1,b:b2,back:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00002d00000000100000,Hori Fighting Commander 3 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00005f00000000010000,Hori Fighting Commander 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00005e00000000010000,Hori Fighting Commander 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00005f00000000000000,HORI Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00005e00000000000000,HORI Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00004d00000000000000,HORI Gem Pad 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00009200000000010000,Hori Pokken Tournament DX Pro Pad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00006e00000000010000,HORIPAD 4 (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00006600000000010000,HORIPAD 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f00006600000000000000,HORIPAD FPS PLUS 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000000d0f0000ee00000000010000,HORIPAD mini4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000008f0e00001330000011010000,HuiJia SNES Controller,a:b4,b:b2,back:b16,dpdown:+a2,dpleft:-a0,dpright:+a0,dpup:-a2,leftshoulder:b12,rightshoulder:b14,start:b18,x:b6,y:b0,platform:Mac OS X, +03000000830500006020000000010000,iBuffalo SNES Controller,a:b1,b:b0,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Mac OS X, +03000000830500006020000000000000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Mac OS X, +030000007e0500000620000001000000,Joy-Con (L),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b13,leftshoulder:b4,leftstick:b10,rightshoulder:b5,start:b8,x:b2,y:b3,platform:Mac OS X, +030000007e0500000720000001000000,Joy-Con (R),+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b12,leftshoulder:b4,leftstick:b11,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Mac OS X, +03000000242f00002d00000007010000,JYS Wireless Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X, +030000006d04000016c2000000020000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000006d04000016c2000000030000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000006d04000016c2000014040000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000006d04000016c2000000000000,Logitech F310 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000006d04000018c2000000000000,Logitech F510 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000006d04000019c2000005030000,Logitech F710,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000006d0400001fc2000000000000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +030000006d04000018c2000000010000,Logitech RumblePad 2 USB,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3~,start:b9,x:b0,y:b3,platform:Mac OS X, +030000006d04000019c2000000000000,Logitech Wireless Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000380700005032000000010000,Mad Catz FightPad PRO (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000380700005082000000010000,Mad Catz FightPad PRO (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000380700008433000000010000,Mad Catz FightStick TE S+ (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000380700008483000000010000,Mad Catz FightStick TE S+ (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000790000004418000000010000,Mayflash GameCube Controller,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000242f00007300000000020000,Mayflash Magic NS,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b0,y:b3,platform:Mac OS X, +0300000079000000d218000026010000,Mayflash Magic NS,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X, +03000000d620000010a7000003010000,Mayflash Magic NS,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +0300000025090000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,back:b8,dpdown:b13,dpleft:b12,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Mac OS X, +03000000790000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b4,b:b8,back:b32,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b16,leftstick:b40,lefttrigger:b24,leftx:a0,lefty:a4,rightshoulder:b20,rightstick:b44,righttrigger:b28,rightx:a8,righty:a12,start:b36,x:b0,y:b12,platform:Mac OS X, +03000000d8140000cecf000000000000,MC Cthulhu,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, +030000005e0400002700000001010000,Microsoft SideWinder Plug & Play Game Pad,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,lefttrigger:b4,leftx:a0,lefty:a1,righttrigger:b5,x:b2,y:b3,platform:Mac OS X, +03000000d62000007162000001000000,Moga Pro 2 HID,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Mac OS X, +03000000632500007505000000020000,NEOGEO mini PAD Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,x:b2,y:b3,platform:Mac OS X, +030000001008000001e5000006010000,NEXT SNES Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b6,start:b9,x:b3,y:b0,platform:Mac OS X, +03000000d620000011a7000000020000,Nintendo Switch Core (Plus) Wired Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000007e0500000920000000000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X, +030000007e0500000920000001000000,Nintendo Switch Pro Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X, +030000008f0e00000300000000000000,Piranha xtreme,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Mac OS X, +030000004c050000da0c000000010000,Playstation Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X, +03000000d62000006dca000000010000,PowerA Pro Ex,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +030000004c0500006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X, +030000004c0500006802000000010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X, +030000004c050000a00b000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000004c050000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000008916000000fd000000000000,Razer Onza TE,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +03000000321500000204000000010000,Razer Panthera (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000321500000104000000010000,Razer Panthera (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000321500000010000000010000,Razer RAIJU,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000321500000507000001010000,Razer Raiju Mobile,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000321500000009000000020000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Mac OS X, +030000003215000000090000163a0000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Mac OS X, +0300000032150000030a000000000000,Razer Wildcat,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +03000000790000001100000000000000,Retrolink Classic Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a3,lefty:a4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X, +03000000790000001100000006010000,Retrolink SNES Controller,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X, +030000006b140000010d000000010000,Revolution Pro Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000c6240000fefa000000000000,Rock Candy Gamepad for PS3,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +03000000730700000401000000010000,Sanwa PlayOnline Mobile,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Mac OS X, +03000000811700007e05000000000000,Sega Saturn,a:b2,b:b4,dpdown:b16,dpleft:b15,dpright:b14,dpup:b17,leftshoulder:b8,lefttrigger:a5,leftx:a0,lefty:a2,rightshoulder:b9,righttrigger:a4,start:b13,x:b0,y:b6,platform:Mac OS X, +03000000b40400000a01000000000000,Sega Saturn USB Gamepad,a:b0,b:b1,back:b5,guide:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,x:b3,y:b4,platform:Mac OS X, +030000003512000021ab000000000000,SFC30 Joystick,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Mac OS X, +0300000000f00000f100000000000000,SNES RetroPort,a:b2,b:b3,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b5,rightshoulder:b7,start:b6,x:b0,y:b1,platform:Mac OS X, +030000004c050000cc09000000000000,Sony DualShock 4 V2,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +030000004c050000a00b000000000000,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000d11800000094000000010000,Stadia Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Mac OS X, +030000005e0400008e02000001000000,Steam Virtual Gamepad,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +03000000110100002014000000000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b12,x:b2,y:b3,platform:Mac OS X, +03000000110100002014000001000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X, +03000000381000002014000001000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X, +03000000110100001714000000000000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,start:b12,x:b2,y:b3,platform:Mac OS X, +03000000110100001714000020010000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,start:b12,x:b2,y:b3,platform:Mac OS X, +030000004f04000015b3000000000000,Thrustmaster Dual Analog 3.2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Mac OS X, +030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Mac OS X, +03000000bd12000015d0000000000000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X, +03000000bd12000015d0000000010000,Tomee SNES USB Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X, +03000000100800000100000000000000,Twin USB Joystick,a:b4,b:b2,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b12,leftstick:b20,lefttrigger:b8,leftx:a0,lefty:a2,rightshoulder:b14,rightstick:b22,righttrigger:b10,rightx:a6,righty:a4,start:b18,x:b6,y:b0,platform:Mac OS X, +030000006f0e00000302000025040000,Victrix Pro Fight Stick for PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X, +03000000791d00000103000009010000,Wii Classic Controller,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Mac OS X, +050000005769696d6f74652028303000,Wii Remote,a:b4,b:b5,back:b7,dpdown:b3,dpleft:b0,dpright:b1,dpup:b2,guide:b8,leftshoulder:b11,lefttrigger:b12,leftx:a0,lefty:a1,start:b6,x:b10,y:b9,platform:Mac OS X, +050000005769696d6f74652028313800,Wii U Pro Controller,a:b16,b:b15,back:b7,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b8,leftshoulder:b19,leftstick:b23,lefttrigger:b21,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b24,righttrigger:b22,rightx:a2,righty:a3,start:b6,x:b18,y:b17,platform:Mac OS X, +030000005e0400008e02000000000000,X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +03000000c6240000045d000000000000,Xbox 360 Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +030000005e0400000a0b000000000000,Xbox Adaptive Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +030000005e040000d102000000000000,Xbox One Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +030000005e040000dd02000000000000,Xbox One Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +030000005e040000e302000000000000,Xbox One Wired Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +030000005e040000e002000000000000,Xbox Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X, +030000005e040000e002000003090000,Xbox Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X, +030000005e040000ea02000000000000,Xbox Wireless Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X, +030000005e040000fd02000003090000,Xbox Wireless Controller,a:b0,b:b1,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000172700004431000029010000,XiaoMi Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Mac OS X, +03000000120c0000100e000000010000,ZEROPLUS P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X, + # Linux 05000000c82d00001038000000010000,8Bitdo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux, 05000000c82d00005106000000010000,8BitDo M30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,start:b11,x:b3,y:b4,platform:Linux, diff --git a/plugins/onepad/wx_dialog/dialog.cpp b/plugins/onepad/wx_dialog/dialog.cpp index c87660dc40..fa8cd93366 100644 --- a/plugins/onepad/wx_dialog/dialog.cpp +++ b/plugins/onepad/wx_dialog/dialog.cpp @@ -19,6 +19,149 @@ #include "dialog.h" +#ifdef __APPLE__ +#include + +static std::string KeyName(int pad, int key, int keysym) +{ + // Mouse + if (keysym >> 16) { + switch (keysym & 0xFFFF) { + case kCGMouseButtonLeft: + return "Mouse Left"; + case kCGMouseButtonRight: + return "Mouse Right"; + case kCGMouseButtonCenter: + return "Mouse Middle"; + default: // Use only number for extra button + return "Mouse " + std::to_string(keysym & 0xFFFF); + } + } + + switch (keysym) { + case kVK_ANSI_A: return "A"; + case kVK_ANSI_B: return "B"; + case kVK_ANSI_C: return "C"; + case kVK_ANSI_D: return "D"; + case kVK_ANSI_E: return "E"; + case kVK_ANSI_F: return "F"; + case kVK_ANSI_G: return "G"; + case kVK_ANSI_H: return "H"; + case kVK_ANSI_I: return "I"; + case kVK_ANSI_J: return "J"; + case kVK_ANSI_K: return "K"; + case kVK_ANSI_L: return "L"; + case kVK_ANSI_M: return "M"; + case kVK_ANSI_N: return "N"; + case kVK_ANSI_O: return "O"; + case kVK_ANSI_P: return "P"; + case kVK_ANSI_Q: return "Q"; + case kVK_ANSI_R: return "R"; + case kVK_ANSI_S: return "S"; + case kVK_ANSI_T: return "T"; + case kVK_ANSI_U: return "U"; + case kVK_ANSI_V: return "V"; + case kVK_ANSI_W: return "W"; + case kVK_ANSI_X: return "X"; + case kVK_ANSI_Y: return "Y"; + case kVK_ANSI_Z: return "Z"; + case kVK_ANSI_0: return "0"; + case kVK_ANSI_1: return "1"; + case kVK_ANSI_2: return "2"; + case kVK_ANSI_3: return "3"; + case kVK_ANSI_4: return "4"; + case kVK_ANSI_5: return "5"; + case kVK_ANSI_6: return "6"; + case kVK_ANSI_7: return "7"; + case kVK_ANSI_8: return "8"; + case kVK_ANSI_9: return "9"; + case kVK_ANSI_Grave: return "`"; + case kVK_ANSI_Minus: return "-"; + case kVK_ANSI_Equal: return "="; + case kVK_ANSI_LeftBracket: return "["; + case kVK_ANSI_RightBracket: return "]"; + case kVK_ANSI_Backslash: return "\\"; + case kVK_ANSI_Semicolon: return ";"; + case kVK_ANSI_Quote: return "'"; + case kVK_ANSI_Comma: return ","; + case kVK_ANSI_Period: return "."; + case kVK_ANSI_Slash: return "/"; + case kVK_Escape: return "⎋"; + case kVK_Tab: return "⇥"; + case kVK_Delete: return "⌫"; + case kVK_ForwardDelete: return "⌦"; + case kVK_Return: return "↩"; + case kVK_Space: return "␣"; + case kVK_ANSI_KeypadDecimal: return "Keypad ."; + case kVK_ANSI_KeypadMultiply: return "Keypad *"; + case kVK_ANSI_KeypadPlus: return "Keypad +"; + case kVK_ANSI_KeypadClear: return "⌧"; + case kVK_ANSI_KeypadDivide: return "Keypad /"; + case kVK_ANSI_KeypadEnter: return "⌤"; + case kVK_ANSI_KeypadMinus: return "Keypad -"; + case kVK_ANSI_KeypadEquals: return "Keypad ="; + case kVK_ANSI_Keypad0: return "Keypad 0"; + case kVK_ANSI_Keypad1: return "Keypad 1"; + case kVK_ANSI_Keypad2: return "Keypad 2"; + case kVK_ANSI_Keypad3: return "Keypad 3"; + case kVK_ANSI_Keypad4: return "Keypad 4"; + case kVK_ANSI_Keypad5: return "Keypad 5"; + case kVK_ANSI_Keypad6: return "Keypad 6"; + case kVK_ANSI_Keypad7: return "Keypad 7"; + case kVK_ANSI_Keypad8: return "Keypad 8"; + case kVK_ANSI_Keypad9: return "Keypad 9"; + case kVK_Command: return "Left ⌘"; + case kVK_Shift: return "Left ⇧"; + case kVK_CapsLock: return "⇪"; + case kVK_Option: return "Left ⌥"; + case kVK_Control: return "Left ⌃"; + case kVK_RightCommand: return "Right ⌘"; + case kVK_RightShift: return "Right ⇧"; + case kVK_RightOption: return "Right ⌥"; + case kVK_RightControl: return "Right ⌃"; + case kVK_Function: return "fn"; + case kVK_VolumeUp: return "Volume Up"; + case kVK_VolumeDown: return "Volume Down"; + case kVK_Mute: return "Mute"; + case kVK_F1: return "F1"; + case kVK_F2: return "F2"; + case kVK_F3: return "F3"; + case kVK_F4: return "F4"; + case kVK_F5: return "F5"; + case kVK_F6: return "F6"; + case kVK_F7: return "F7"; + case kVK_F8: return "F8"; + case kVK_F9: return "F9"; + case kVK_F10: return "F10"; + case kVK_F11: return "F11"; + case kVK_F12: return "F12"; + case kVK_F13: return "F13"; + case kVK_F14: return "F14"; + case kVK_F15: return "F15"; + case kVK_F16: return "F16"; + case kVK_F17: return "F17"; + case kVK_F18: return "F18"; + case kVK_F19: return "F19"; + case kVK_F20: return "F20"; + case kVK_Help: return "Help"; + case kVK_Home: return "↖"; + case kVK_PageUp: return "⇞"; + case kVK_End: return "↘"; + case kVK_PageDown: return "⇟"; + case kVK_LeftArrow: return "←"; + case kVK_RightArrow: return "→"; + case kVK_DownArrow: return "↓"; + case kVK_UpArrow: return "↑"; + case kVK_ISO_Section: return "Section"; + case kVK_JIS_Yen: return "¥"; + case kVK_JIS_Underscore: return "_"; + case kVK_JIS_KeypadComma: return "Keypad ,"; + case kVK_JIS_Eisu: return "英数"; + case kVK_JIS_Kana: return "かな"; + default: return "Key " + std::to_string(keysym); + } +} +#else static std::string KeyName(int pad, int key, int keysym) { // Mouse @@ -39,6 +182,7 @@ static std::string KeyName(int pad, int key, int keysym) return std::string(XKeysymToString(keysym)); } +#endif // Construtor of Dialog Dialog::Dialog() @@ -431,7 +575,7 @@ void Dialog::config_key(int pad, int key) u32 key_pressed = 0; while (!captured) { - if (PollX11KeyboardMouseEvent(key_pressed)) { + if (PollForNewKeyboardKeys(key_pressed)) { // special case for keyboard/mouse to handle multiple keys // Note: key_pressed == 0 when ESC is hit to abort the capture if (key_pressed > 0) { diff --git a/plugins/spu2-x/src/CMakeLists.txt b/plugins/spu2-x/src/CMakeLists.txt index f14ad5038b..30a443decf 100644 --- a/plugins/spu2-x/src/CMakeLists.txt +++ b/plugins/spu2-x/src/CMakeLists.txt @@ -20,7 +20,7 @@ set(CommonFlags # plugin name set(Output spu2x-2.0.0) -if (UNIX AND NOT APPLE) +if (UNIX) if (SDL2_API) set(spu2xFinalFlags "-DSPU2X_SDL2" ${CommonFlags}) else() diff --git a/plugins/spu2-x/src/Linux/Config.cpp b/plugins/spu2-x/src/Linux/Config.cpp index 96a9e7bc8b..f4d3d1f2e6 100644 --- a/plugins/spu2-x/src/Linux/Config.cpp +++ b/plugins/spu2-x/src/Linux/Config.cpp @@ -23,6 +23,9 @@ #include #include #endif +#ifdef __APPLE__ +#include +#endif #ifdef PCSX2_DEVBUILD static const int LATENCY_MAX = 3000; @@ -147,7 +150,7 @@ void ReadSettings() #endif #endif -#ifdef __unix__ +#if defined(__unix__) || defined(__APPLE__) CfgReadStr(L"SDL", L"HostApi", temp, L"pulseaudio"); SdlOutputAPI = 0; #if SDL_MAJOR_VERSION >= 2 @@ -165,7 +168,7 @@ void ReadSettings() #ifdef SPU2X_PORTAUDIO PortaudioOut->ReadSettings(); #endif -#ifdef __unix__ +#if defined(__unix__) || defined(__APPLE__) SDLOut->ReadSettings(); #endif SoundtouchCfg::ReadSettings(); @@ -218,7 +221,7 @@ void WriteSettings() #ifdef SPU2X_PORTAUDIO PortaudioOut->WriteSettings(); #endif -#ifdef __unix__ +#if defined(__unix__) || defined(__APPLE__) SDLOut->WriteSettings(); #endif SoundtouchCfg::WriteSettings(); @@ -235,7 +238,7 @@ void debug_dialog() DebugConfig::DisplayDialog(); } -#if defined(__unix__) +#if defined(__unix__) || defined(__APPLE__) // Format the slider with ms. static gchar *cb_scale_format_ms(GtkScale *scale, gdouble value) @@ -334,6 +337,8 @@ void DisplayDialog() gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(api_box), "0 - ALSA (recommended)"); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(api_box), "1 - OSS (legacy)"); gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(api_box), "2 - JACK"); +#elif defined(__APPLE__) + gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(api_box), "CoreAudio"); #else gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(api_box), "OSS"); #endif @@ -466,7 +471,11 @@ void DisplayDialog() #else switch (OutputAPI) { case 0: +#ifdef __APPLE__ + PortaudioOut->SetApiSettings(L"CoreAudio"); +#else PortaudioOut->SetApiSettings(L"OSS"); +#endif break; default: PortaudioOut->SetApiSettings(L"Unknown"); @@ -499,10 +508,23 @@ void DisplayDialog() void configure() { +#ifdef __APPLE__ + // Rest of macOS UI doesn't use GTK so we need to init it now + gtk_init(nullptr, nullptr); + // GTK expects us to be using its event loop, rather than Cocoa's + // If we call its stuff right now, it'll attempt to drain a static autorelease pool that was already drained by Cocoa (see https://github.com/GNOME/gtk/blob/8c1072fad1cb6a2e292fce2441b4a571f173ce0f/gdk/quartz/gdkeventloop-quartz.c#L640-L646) + // We can convince it that touching that pool would be unsafe by running all GTK calls within a CFRunLoop + // (Blocks submitted to the main queue by dispatch_async are run by its CFRunLoop) + dispatch_async(dispatch_get_main_queue(), ^{ +#endif initIni(); ReadSettings(); DisplayDialog(); WriteSettings(); delete spuConfig; spuConfig = NULL; +#ifdef __APPLE__ + // End of `dispatch_async(...` above + }); +#endif } diff --git a/plugins/spu2-x/src/Linux/ConfigDebug.cpp b/plugins/spu2-x/src/Linux/ConfigDebug.cpp index ea98e2068c..cd48527755 100644 --- a/plugins/spu2-x/src/Linux/ConfigDebug.cpp +++ b/plugins/spu2-x/src/Linux/ConfigDebug.cpp @@ -154,7 +154,7 @@ void WriteSettings() CfgWriteStr(Section, L"Reg_Dump_Filename", RegDumpFileName); } -#ifdef __unix__ +#if defined(__unix__) || defined(__APPLE__) void DisplayDialog() { GtkWidget *dialog; diff --git a/plugins/spu2-x/src/Linux/ConfigSoundTouch.cpp b/plugins/spu2-x/src/Linux/ConfigSoundTouch.cpp index 4d3d8cc4b1..f55a907c14 100644 --- a/plugins/spu2-x/src/Linux/ConfigSoundTouch.cpp +++ b/plugins/spu2-x/src/Linux/ConfigSoundTouch.cpp @@ -71,7 +71,7 @@ void WriteSettings() CfgWriteInt(L"SOUNDTOUCH", L"OverlapMS", OverlapMS); } -#ifdef __unix__ +#if defined(__unix__) || defined(__APPLE__) static GtkWidget *seq_label, *seek_label, *over_label; static GtkWidget *seq_slide, *seek_slide, *over_slide;