├── CMakeLists.txt ├── README.md ├── buttonswap.c └── buttonswap.yml /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | if(NOT DEFINED CMAKE_TOOLCHAIN_FILE) 4 | if(DEFINED ENV{VITASDK}) 5 | set(CMAKE_TOOLCHAIN_FILE "$ENV{VITASDK}/share/vita.toolchain.cmake" CACHE PATH "toolchain file") 6 | else() 7 | message(FATAL_ERROR "Please define VITASDK to point to your SDK path!") 8 | endif() 9 | endif() 10 | 11 | project(ButtonSwap) 12 | include("${VITASDK}/share/vita.cmake" REQUIRED) 13 | 14 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-q -Wall -O3 -std=gnu99") 15 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-rtti -fno-exceptions") 16 | 17 | include_directories( 18 | ) 19 | 20 | link_directories( 21 | ${CMAKE_CURRENT_BINARY_DIR} 22 | ) 23 | 24 | if (NOT ${RELEASE}) 25 | add_definitions(-DENABLE_LOGGING) 26 | endif() 27 | 28 | add_executable(buttonswap 29 | buttonswap.c 30 | ) 31 | 32 | target_link_libraries(buttonswap 33 | taihen_stub 34 | SceLibKernel_stub 35 | SceIofilemgr_stub 36 | ) 37 | 38 | set_target_properties(buttonswap 39 | PROPERTIES LINK_FLAGS "-nostdlib" 40 | ) 41 | 42 | vita_create_self(buttonswap.suprx buttonswap 43 | CONFIG ${CMAKE_SOURCE_DIR}/buttonswap.yml 44 | ) 45 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Button Swap 2 | taiHEN plugin for swapping X and O buttons on PSVita 3 | 4 | Installation 5 | -------------------------------------------------------------------------------- 6 | 7 | Put "buttonswap.suprx" in 'tai' folder in the root of your Vita. 8 | 9 | Change config.txt in that directory to load plugin for title of your choice by adding new lines like below: 10 | 11 | ```text 12 | # titleid for your game (this one is for Root//Letter for example) 13 | *PCSB01019 14 | ux0:tai/buttonswap.suprx 15 | ``` 16 | 17 | After that just run the game and your buttons should be swapped (this would work only for this game). -------------------------------------------------------------------------------- /buttonswap.c: -------------------------------------------------------------------------------- 1 | // Button Swap taiHEN plugin 2 | // Copyright (c) 2016 Scorp 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | static SceUID g_hooks[4]; 9 | 10 | int invertButtons(int port, tai_hook_ref_t ref_hook, SceCtrlData *ctrl, int count) { 11 | int ret; 12 | 13 | if (ref_hook == 0) 14 | ret = 1; 15 | else 16 | { 17 | ret = TAI_CONTINUE(int, ref_hook, port, ctrl, count); 18 | 19 | if ((ctrl->buttons & 0x6000) && ((ctrl->buttons & 0x6000) != 0x6000)) 20 | ctrl->buttons = ctrl->buttons ^ 0x6000; 21 | } 22 | 23 | return ret; 24 | } 25 | 26 | static tai_hook_ref_t ref_hook1; 27 | static int keys_patched1(int port, SceCtrlData *ctrl, int count) { 28 | return invertButtons(port, ref_hook1, ctrl, count); 29 | } 30 | 31 | static tai_hook_ref_t ref_hook2; 32 | static int keys_patched2(int port, SceCtrlData *ctrl, int count) { 33 | return invertButtons(port, ref_hook2, ctrl, count); 34 | } 35 | 36 | static tai_hook_ref_t ref_hook3; 37 | static int keys_patched3(int port, SceCtrlData *ctrl, int count) { 38 | return invertButtons(port, ref_hook3, ctrl, count); 39 | } 40 | 41 | static tai_hook_ref_t ref_hook4; 42 | static int keys_patched4(int port, SceCtrlData *ctrl, int count) { 43 | return invertButtons(port, ref_hook4, ctrl, count); 44 | } 45 | 46 | 47 | void _start() __attribute__ ((weak, alias ("module_start"))); 48 | 49 | int module_start(SceSize argc, const void *args) { 50 | 51 | g_hooks[0] = taiHookFunctionImport(&ref_hook1, 52 | TAI_MAIN_MODULE, 53 | TAI_ANY_LIBRARY, 54 | 0xA9C3CED6, // sceCtrlPeekBufferPositive 55 | keys_patched1); 56 | 57 | g_hooks[1] = taiHookFunctionImport(&ref_hook2, 58 | TAI_MAIN_MODULE, 59 | TAI_ANY_LIBRARY, 60 | 0x15F81E8C, // sceCtrlPeekBufferPositive2 61 | keys_patched2); 62 | 63 | g_hooks[2] = taiHookFunctionImport(&ref_hook3, 64 | TAI_MAIN_MODULE, 65 | TAI_ANY_LIBRARY, 66 | 0x67E7AB83, // sceCtrlReadBufferPositive 67 | keys_patched3); 68 | 69 | g_hooks[3] = taiHookFunctionImport(&ref_hook4, 70 | TAI_MAIN_MODULE, 71 | TAI_ANY_LIBRARY, 72 | 0xC4226A3E, // sceCtrlReadBufferPositive2 73 | keys_patched4); 74 | 75 | return SCE_KERNEL_START_SUCCESS; 76 | } 77 | 78 | int module_stop(SceSize argc, const void *args) { 79 | 80 | // free hooks that didn't fail 81 | if (g_hooks[0] >= 0) taiHookRelease(g_hooks[0], ref_hook1); 82 | if (g_hooks[1] >= 0) taiHookRelease(g_hooks[1], ref_hook2); 83 | if (g_hooks[2] >= 0) taiHookRelease(g_hooks[2], ref_hook3); 84 | if (g_hooks[3] >= 0) taiHookRelease(g_hooks[3], ref_hook4); 85 | 86 | return SCE_KERNEL_STOP_SUCCESS; 87 | } 88 | -------------------------------------------------------------------------------- /buttonswap.yml: -------------------------------------------------------------------------------- 1 | ButtonSwap: 2 | attributes: 0 3 | version: 4 | major: 1 5 | minor: 1 6 | main: 7 | start: module_start 8 | stop: module_stop 9 | --------------------------------------------------------------------------------