mirror of
https://github.com/esuo1198/TaikoArcadeLoader.git
synced 2026-09-28 17:58:11 +03:00
Merge pull request #22 from ryumiyax/Refactor
[Experimental] More Optimized IO & Optimized boot speed & SDL3 & Stability fix
This commit is contained in:
@@ -12,9 +12,9 @@ jobs:
|
||||
- name: Set up MSVC
|
||||
uses: ilammy/msvc-dev-cmd@v1
|
||||
- name: Configure CMake
|
||||
run: cmake -B build -S . -G "Visual Studio 17 2022" -A x64 -DCMAKE_BUILD_TYPE=Release
|
||||
run: cmake -B build -S . -G "Visual Studio 17 2022" -A x64 -DCMAKE_BUILD_TYPE=Release -DCMAKE_SYSTEM_VERSION=10.0.26100.0
|
||||
- name: Build
|
||||
run: cmake --build build --config Release --target bnusio
|
||||
run: cmake --build build --config Release --target bnusio --verbose
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: TaikoArcadeLoader
|
||||
|
||||
+8
-7
@@ -94,15 +94,17 @@ FetchContent_Declare(
|
||||
set(SAFETYHOOK_FETCH_ZYDIS ON CACHE BOOL "" FORCE)
|
||||
FetchContent_MakeAvailable(safetyhook)
|
||||
|
||||
# Fetch SDL2
|
||||
# Fetch SDL3
|
||||
FetchContent_Declare(
|
||||
SDL2
|
||||
URL https://github.com/libsdl-org/SDL/releases/download/release-2.26.5/SDL2-2.26.5.tar.gz
|
||||
SDL3
|
||||
GIT_REPOSITORY https://github.com/libsdl-org/SDL.git
|
||||
GIT_TAG 78cc5c173404488d80751af226d1eaf67033bcc4 # v3.1.6
|
||||
# URL https://github.com/libsdl-org/SDL/releases/download/preview-3.1.6/SDL3-3.1.6.tar.gz
|
||||
)
|
||||
set(SDL_SHARED OFF CACHE BOOL "" FORCE)
|
||||
set(SDL_STATIC ON CACHE BOOL "" FORCE)
|
||||
set(SDL_TEST OFF CACHE BOOL "" FORCE)
|
||||
FetchContent_MakeAvailable(SDL2)
|
||||
FetchContent_MakeAvailable(SDL3)
|
||||
|
||||
# Fetch xxHash
|
||||
FetchContent_Declare(
|
||||
@@ -137,7 +139,6 @@ set(SOURCES
|
||||
src/patches/audio.cpp
|
||||
src/patches/plugins.cpp
|
||||
src/patches/scanner.cpp
|
||||
# src/patches/qr.cpp
|
||||
src/patches/layeredfs.cpp
|
||||
src/patches/testmode.cpp
|
||||
src/patches/timer.cpp
|
||||
@@ -157,7 +158,7 @@ set_target_properties(bnusio PROPERTIES PREFIX "")
|
||||
target_include_directories(bnusio PRIVATE
|
||||
src
|
||||
${tomlc99_SOURCE_DIR}
|
||||
${SDL2_SOURCE_DIR}/include
|
||||
${SDL3_SOURCE_DIR}/include
|
||||
${xxhash_SOURCE_DIR}
|
||||
${zlib_SOURCE_DIR}
|
||||
${libtomcrypt_SOURCE_DIR}/src/headers
|
||||
@@ -177,7 +178,7 @@ endif()
|
||||
# Link libraries
|
||||
target_link_libraries(bnusio PRIVATE
|
||||
tomlc99
|
||||
SDL2-static
|
||||
SDL3-static
|
||||
xxhash
|
||||
zlibstatic
|
||||
libtomcrypt
|
||||
|
||||
+86
-53
@@ -35,7 +35,7 @@ Keybindings SERVICE = {.keycodes = {VK_F2}};
|
||||
Keybindings DEBUG_UP = {.keycodes = {VK_UP}};
|
||||
Keybindings DEBUG_DOWN = {.keycodes = {VK_DOWN}};
|
||||
Keybindings DEBUG_ENTER = {.keycodes = {VK_RETURN}};
|
||||
Keybindings COIN_ADD = {.keycodes = {VK_RETURN}, .buttons = {SDL_CONTROLLER_BUTTON_START}};
|
||||
Keybindings COIN_ADD = {.keycodes = {VK_RETURN}, .buttons = {SDL_GAMEPAD_BUTTON_START}};
|
||||
Keybindings CARD_INSERT_1 = {.keycodes = {'P'}};
|
||||
Keybindings CARD_INSERT_2 = {};
|
||||
Keybindings QR_DATA_READ = {.keycodes = {'Q'}};
|
||||
@@ -52,20 +52,26 @@ Keybindings P2_RIGHT_BLUE = {.keycodes = {'V'}};
|
||||
// CARD_INSERT_1, CARD_INSERT_2, QR_DATA_READ, QR_IMAGE_READ, P1_LEFT_BLUE, P1_LEFT_RED,
|
||||
// P1_RIGHT_RED, P1_RIGHT_BLUE, P2_LEFT_BLUE, P2_LEFT_RED, P2_RIGHT_RED, P2_RIGHT_BLUE };
|
||||
|
||||
int exited = 0;
|
||||
bool testEnabled = false;
|
||||
int coin_count = 0;
|
||||
int service_count = 0;
|
||||
bool inited = false;
|
||||
bool updateByCoin = false;
|
||||
HWND windowHandle = nullptr;
|
||||
bool usePoll = false;
|
||||
const int exitWait = 100;
|
||||
int exited = 0;
|
||||
bool testEnabled = false;
|
||||
bool insert_coin = false;
|
||||
bool insert_service = false;
|
||||
u16 coin_count = 0;
|
||||
u16 service_count = 0;
|
||||
bool inited = false;
|
||||
bool updateByCoin = false;
|
||||
HWND windowHandle = nullptr;
|
||||
bool usePoll = false;
|
||||
HKL currentLayout;
|
||||
|
||||
namespace bnusio {
|
||||
#define RETURN_FALSE(returnType, functionName, ...) \
|
||||
returnType functionName (__VA_ARGS__) { return 0; }
|
||||
|
||||
typedef u16 (__fastcall *AnalogMethod) (const u8);
|
||||
AnalogMethod analogMethod = nullptr;
|
||||
|
||||
extern "C" {
|
||||
RETURN_FALSE (i64, bnusio_Open);
|
||||
RETURN_FALSE (i64, bnusio_Close);
|
||||
@@ -124,13 +130,14 @@ bnusio_GetSwIn () {
|
||||
}
|
||||
|
||||
bool waitAll = false;
|
||||
u16 drumWaitPeriod = 4;
|
||||
short drumWaitPeriod = 4;
|
||||
bool analogInput = false;
|
||||
bool valueStates[] = {false, false, false, false, false, false, false, false};
|
||||
|
||||
Keybindings *analogButtons[]
|
||||
= {&P1_LEFT_BLUE, &P1_LEFT_RED, &P1_RIGHT_RED, &P1_RIGHT_BLUE, &P2_LEFT_BLUE, &P2_LEFT_RED, &P2_RIGHT_RED, &P2_RIGHT_BLUE};
|
||||
|
||||
u16 cooldown[8] = { 0 };
|
||||
// u16 cooldown[8] = { 0 };
|
||||
u16 buttonWaitPeriod[] = { 0, 0 };
|
||||
std::queue<u8> buttonQueue[] = { {}, {} };
|
||||
|
||||
@@ -139,7 +146,7 @@ std::queue<u8> buttonQueue[] = { {}, {} };
|
||||
// std::queue<u8> buttonQueueP1;
|
||||
// std::queue<u8> buttonQueueP2;
|
||||
|
||||
bool analogInput;
|
||||
|
||||
SDLAxis analogBindings[] = {
|
||||
SDL_AXIS_LEFT_LEFT, SDL_AXIS_LEFT_RIGHT, SDL_AXIS_LEFT_DOWN, SDL_AXIS_LEFT_UP, // P1: LB, LR, RR, RB
|
||||
SDL_AXIS_RIGHT_LEFT, SDL_AXIS_RIGHT_RIGHT, SDL_AXIS_RIGHT_DOWN, SDL_AXIS_RIGHT_UP, // P2: LB, LR, RR, RB
|
||||
@@ -147,41 +154,8 @@ SDLAxis analogBindings[] = {
|
||||
|
||||
u16
|
||||
bnusio_GetAnalogIn (const u8 which) {
|
||||
if (analogInput) {
|
||||
const u16 analogValue = static_cast<u16> (32768 * ControllerAxisIsDown (analogBindings[which]));
|
||||
if (analogValue > 100) return analogValue;
|
||||
else return 0;
|
||||
}
|
||||
const auto button = analogButtons[which];
|
||||
const bool blue = !(which % 4 % 3);
|
||||
const int player = which / 4;
|
||||
|
||||
u16 analogValue = 0;
|
||||
if (which == 0) {
|
||||
for (int i=0; i<2; i++) if (buttonWaitPeriod[i] > 0) buttonWaitPeriod[i]--;
|
||||
for (int i=0; i<8; i++) if (cooldown[i] > 0) cooldown[i]--;
|
||||
}
|
||||
if (buttonWaitPeriod[player] == 0 && !buttonQueue[player].empty () && buttonQueue[player].front () == which) {
|
||||
buttonWaitPeriod[player] = drumWaitPeriod;
|
||||
buttonQueue[player].pop ();
|
||||
|
||||
const u16 hitValue = !valueStates[which] ? 50 : 51;
|
||||
valueStates[which] = !valueStates[which];
|
||||
analogValue = (hitValue << 15) / 100 + 1;
|
||||
}
|
||||
if (IsButtonTapped (*button)) {
|
||||
if ((waitAll || blue) && buttonWaitPeriod[player] > 0) {
|
||||
buttonQueue[player].push (which);
|
||||
return analogValue;
|
||||
} else if ((waitAll || blue) && cooldown[which] > 0) return 0;
|
||||
buttonWaitPeriod[player] = drumWaitPeriod;
|
||||
if (waitAll || blue) cooldown[which] = 4;
|
||||
|
||||
const u16 hitValue = !valueStates[which] ? 50 : 51;
|
||||
valueStates[which] = !valueStates[which];
|
||||
analogValue = (hitValue << 15) / 100 + 1;
|
||||
}
|
||||
return analogValue;
|
||||
if (analogMethod) return analogMethod (which);
|
||||
else return 0;
|
||||
}
|
||||
|
||||
u16 __fastcall bnusio_GetCoin (i32 a1) {
|
||||
@@ -237,6 +211,54 @@ FUNCTION_PTR (i64, bnusio_DecCoin_Original, PROC_ADDRESS ("bnusio_original.dll",
|
||||
FUNCTION_PTR (u64, bnusio_DecService_Original, PROC_ADDRESS ("bnusio_original.dll", "bnusio_DecService"), i32, u16);
|
||||
FUNCTION_PTR (i64, bnusio_ResetCoin_Original, PROC_ADDRESS ("bnusio_original.dll", "bnusio_ResetCoin"));
|
||||
|
||||
u16 __fastcall
|
||||
AnalogInputAxis (const u8 which) {
|
||||
const u16 analogValue = static_cast<u16> (32768 * ControllerAxisIsDown (analogBindings[which]));
|
||||
if (analogValue > 100) return analogValue;
|
||||
else return 0;
|
||||
}
|
||||
|
||||
u16 __fastcall
|
||||
AnalogInputWaitPeriod (const u8 which) {
|
||||
const auto button = analogButtons[which];
|
||||
const bool blue = !(which % 4 % 3);
|
||||
const int player = which / 4;
|
||||
|
||||
u16 analogValue = 0;
|
||||
if (which == 0) for (int i=0; i<2; i++) if (buttonWaitPeriod[i] > 0) buttonWaitPeriod[i]--;
|
||||
if (buttonWaitPeriod[player] == 0 && !buttonQueue[player].empty () && buttonQueue[player].front () == which) {
|
||||
buttonWaitPeriod[player] = drumWaitPeriod;
|
||||
buttonQueue[player].pop ();
|
||||
|
||||
const u16 hitValue = !valueStates[which] ? 50 : 51;
|
||||
valueStates[which] = !valueStates[which];
|
||||
analogValue = (hitValue << 15) / 100 + 1;
|
||||
}
|
||||
if (IsButtonTapped (*button)) {
|
||||
if ((waitAll || blue) && buttonWaitPeriod[player] > 0) {
|
||||
buttonQueue[player].push (which);
|
||||
return analogValue;
|
||||
}
|
||||
buttonWaitPeriod[player] = drumWaitPeriod;
|
||||
|
||||
const u16 hitValue = !valueStates[which] ? 50 : 51;
|
||||
valueStates[which] = !valueStates[which];
|
||||
analogValue = (hitValue << 15) / 100 + 1;
|
||||
}
|
||||
return analogValue;
|
||||
}
|
||||
|
||||
u16 __fastcall
|
||||
AnalogInputSimple (const u8 which) {
|
||||
const auto button = analogButtons[which];
|
||||
if (IsButtonTapped (*button)) {
|
||||
const u16 hitValue = !valueStates[which] ? 50 : 51;
|
||||
valueStates[which] = !valueStates[which];
|
||||
return (hitValue << 15) / 100 + 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef ASYNC_UPDATE
|
||||
void
|
||||
Update () {
|
||||
@@ -250,10 +272,10 @@ void
|
||||
UpdateLoop () {
|
||||
LogMessage (LogLevel::WARN, "(experimental) Using Async Update!");
|
||||
std::unique_lock<std::mutex> syncLock(syncMtx);
|
||||
while (exited < 120) {
|
||||
while (exited < exitWait) {
|
||||
syncCV.wait (syncLock);
|
||||
#endif
|
||||
if (exited && ++exited >= 120) ExitProcess (0);
|
||||
if (exited && ++exited >= exitWait) ExitProcess (0);
|
||||
|
||||
#ifndef ASYNC_IO
|
||||
if (!inited) {
|
||||
@@ -273,9 +295,9 @@ UpdateLoop () {
|
||||
#endif
|
||||
std::vector<uint8_t> buffer = {};
|
||||
if (IsButtonTapped (COIN_ADD)) coin_count++;
|
||||
if (IsButtonTapped (SERVICE) && !testEnabled) service_count++;
|
||||
if (IsButtonTapped (SERVICE)) service_count++;
|
||||
if (IsButtonTapped (TEST)) testEnabled = !testEnabled;
|
||||
if (IsButtonTapped (EXIT)) {
|
||||
if (IsButtonTapped (EXIT)) {
|
||||
LogMessage (LogLevel::INFO, "Exit By Press Exit Button!");
|
||||
exited += 1; testEnabled = 1; patches::Plugins::Exit ();
|
||||
}
|
||||
@@ -307,9 +329,8 @@ Init () {
|
||||
if (config_ptr) {
|
||||
const toml_table_t *config = config_ptr.get ();
|
||||
if (const auto controller = openConfigSection (config, "controller")) {
|
||||
drumWaitPeriod = static_cast<u16> (readConfigInt (controller, "wait_period", drumWaitPeriod));
|
||||
drumWaitPeriod = static_cast<short> (readConfigInt (controller, "wait_period", drumWaitPeriod));
|
||||
analogInput = readConfigBool (controller, "analog_input", analogInput);
|
||||
if (analogInput) LogMessage (LogLevel::WARN, "Using analog input mode. All the keyboard drum inputs have been disabled.");
|
||||
}
|
||||
auto graphics = openConfigSection (config, "graphics");
|
||||
if (graphics) {
|
||||
@@ -317,6 +338,17 @@ Init () {
|
||||
}
|
||||
}
|
||||
|
||||
if (analogInput) {
|
||||
LogMessage (LogLevel::WARN, "[Analog Type] Axis: All the keyboard drum inputs have been disabled");
|
||||
analogMethod = AnalogInputAxis;
|
||||
} else if (drumWaitPeriod > 0) {
|
||||
LogMessage (LogLevel::WARN, "[Analog Type] WaitPeriod: Fast input might be queued");
|
||||
analogMethod = AnalogInputWaitPeriod;
|
||||
} else {
|
||||
LogMessage (LogLevel::INFO, "[Analog Type] Simple: Fastest and original input");
|
||||
analogMethod = AnalogInputSimple;
|
||||
}
|
||||
|
||||
updateByCoin = fpsLimit == 0;
|
||||
if (updateByCoin) {
|
||||
LogMessage (LogLevel::INFO, "fpsLimit is set to 0, bnusio::Update() will invoke in getCoin callback");
|
||||
@@ -324,6 +356,7 @@ Init () {
|
||||
const auto keyConfigPath = std::filesystem::current_path () / "keyconfig.toml";
|
||||
const std::unique_ptr<toml_table_t, void (*) (toml_table_t *)> keyConfig_ptr (openConfig (keyConfigPath), toml_free);
|
||||
if (keyConfig_ptr) {
|
||||
if (analogInput) usePoll = true;
|
||||
const toml_table_t *keyConfig = keyConfig_ptr.get ();
|
||||
SetConfigValue (keyConfig, "EXIT", &EXIT, &usePoll);
|
||||
|
||||
|
||||
+88
-44
@@ -4,6 +4,7 @@
|
||||
#include "patches/patches.h"
|
||||
#include "poll.h"
|
||||
#include "logger.h"
|
||||
#include <dbghelp.h>
|
||||
|
||||
auto gameVersion = GameVersion::UNKNOWN;
|
||||
std::vector<HMODULE> plugins;
|
||||
@@ -22,7 +23,6 @@ char accessCode1[21] = "00000000000000000001";
|
||||
char accessCode2[21] = "00000000000000000002";
|
||||
char chipId1[33] = "00000000000000000000000000000001";
|
||||
char chipId2[33] = "00000000000000000000000000000002";
|
||||
bool highResTimer = true;
|
||||
bool windowed = false;
|
||||
bool autoIme = false;
|
||||
bool jpLayout = false;
|
||||
@@ -36,22 +36,22 @@ std::string logLevelStr = "INFO";
|
||||
bool logToFile = true;
|
||||
|
||||
HWND hGameWnd;
|
||||
HOOK (i32, ShowMouse, PROC_ADDRESS ("user32.dll", "ShowCursor"), bool) { return originalShowMouse (true); }
|
||||
HOOK (i32, ExitWindows, PROC_ADDRESS ("user32.dll", "ExitWindowsEx")) { ExitProcess (0); }
|
||||
HOOK (HWND, CreateWindow, PROC_ADDRESS ("user32.dll", "CreateWindowExW"), DWORD dwExStyle, LPCWSTR lpClassName, LPCWSTR lpWindowName, DWORD dwStyle,
|
||||
FAST_HOOK (i32, ShowMouse, PROC_ADDRESS ("user32.dll", "ShowCursor"), bool) { return originalShowMouse.stdcall<i32> (true); }
|
||||
FAST_HOOK (i32, ExitWindows, PROC_ADDRESS ("user32.dll", "ExitWindowsEx")) { ExitProcess (0); }
|
||||
FAST_HOOK (HWND, CreateWindow, PROC_ADDRESS ("user32.dll", "CreateWindowExW"), DWORD dwExStyle, LPCWSTR lpClassName, LPCWSTR lpWindowName, DWORD dwStyle,
|
||||
i32 X, i32 Y, i32 nWidth, i32 nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance, LPVOID lpParam) {
|
||||
if (lpWindowName != nullptr) {
|
||||
if (wcscmp (lpWindowName, L"Taiko") == 0) {
|
||||
if (windowed) dwStyle = WS_TILEDWINDOW ^ WS_MAXIMIZEBOX ^ WS_THICKFRAME;
|
||||
|
||||
hGameWnd
|
||||
= originalCreateWindow (dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
|
||||
= originalCreateWindow.stdcall<HWND> (dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
|
||||
return hGameWnd;
|
||||
}
|
||||
}
|
||||
return originalCreateWindow (dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
|
||||
return originalCreateWindow.stdcall<HWND> (dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam);
|
||||
}
|
||||
HOOK (bool, SetWindowPosition, PROC_ADDRESS ("user32.dll", "SetWindowPos"), HWND hWnd, HWND hWndInsertAfter, i32 X, i32 Y, i32 cx, i32 cy,
|
||||
FAST_HOOK (bool, SetWindowPosition, PROC_ADDRESS ("user32.dll", "SetWindowPos"), HWND hWnd, HWND hWndInsertAfter, i32 X, i32 Y, i32 cx, i32 cy,
|
||||
u32 uFlags) {
|
||||
if (hWnd == hGameWnd) {
|
||||
RECT rw, rc;
|
||||
@@ -60,29 +60,29 @@ HOOK (bool, SetWindowPosition, PROC_ADDRESS ("user32.dll", "SetWindowPos"), HWND
|
||||
cx = rw.right - rw.left - (rc.right - rc.left) + cx;
|
||||
cy = rw.bottom - rw.top - (rc.bottom - rc.top) + cy;
|
||||
}
|
||||
return originalSetWindowPosition (hWnd, hWndInsertAfter, X, Y, cx, cy, uFlags);
|
||||
return originalSetWindowPosition.stdcall<bool> (hWnd, hWndInsertAfter, X, Y, cx, cy, uFlags);
|
||||
}
|
||||
|
||||
HOOK (void, ExitProcessHook, PROC_ADDRESS ("kernel32.dll", "ExitProcess"), u32 uExitCode) {
|
||||
FAST_HOOK (void, ExitProcessHook, PROC_ADDRESS ("kernel32.dll", "ExitProcess"), u32 uExitCode) {
|
||||
bnusio::Close ();
|
||||
originalExitProcessHook (uExitCode);
|
||||
originalExitProcessHook.stdcall<void> (uExitCode);
|
||||
}
|
||||
|
||||
HOOK (i32, XinputGetState, PROC_ADDRESS ("xinput9_1_0.dll", "XInputGetState")) { return ERROR_DEVICE_NOT_CONNECTED; }
|
||||
HOOK (i32, XinputSetState, PROC_ADDRESS ("xinput9_1_0.dll", "XInputSetState")) { return ERROR_DEVICE_NOT_CONNECTED; }
|
||||
HOOK (i32, XinputGetCapabilites, PROC_ADDRESS ("xinput9_1_0.dll", "XInputGetCapabilities")) { return ERROR_DEVICE_NOT_CONNECTED; }
|
||||
FAST_HOOK (i32, XinputGetState, PROC_ADDRESS ("xinput9_1_0.dll", "XInputGetState")) { return ERROR_DEVICE_NOT_CONNECTED; }
|
||||
FAST_HOOK (i32, XinputSetState, PROC_ADDRESS ("xinput9_1_0.dll", "XInputSetState")) { return ERROR_DEVICE_NOT_CONNECTED; }
|
||||
FAST_HOOK (i32, XinputGetCapabilites, PROC_ADDRESS ("xinput9_1_0.dll", "XInputGetCapabilities")) { return ERROR_DEVICE_NOT_CONNECTED; }
|
||||
|
||||
HOOK (i32, ssleay_Shutdown, PROC_ADDRESS ("ssleay32.dll", "SSL_shutdown")) { return 1; }
|
||||
FAST_HOOK (i32, ssleay_Shutdown, PROC_ADDRESS ("ssleay32.dll", "SSL_shutdown")) { return 1; }
|
||||
|
||||
HOOK (i64, UsbFinderInitialize, PROC_ADDRESS ("nbamUsbFinder.dll", "nbamUsbFinderInitialize")) { return 0; }
|
||||
HOOK (i64, UsbFinderRelease, PROC_ADDRESS ("nbamUsbFinder.dll", "nbamUsbFinderRelease")) { return 0; }
|
||||
HOOK (i64, UsbFinderGetSerialNumber, PROC_ADDRESS ("nbamUsbFinder.dll", "nbamUsbFinderGetSerialNumber"), i32 a1, char *a2) {
|
||||
FAST_HOOK (i64, UsbFinderInitialize, PROC_ADDRESS ("nbamUsbFinder.dll", "nbamUsbFinderInitialize")) { return 0; }
|
||||
FAST_HOOK (i64, UsbFinderRelease, PROC_ADDRESS ("nbamUsbFinder.dll", "nbamUsbFinderRelease")) { return 0; }
|
||||
FAST_HOOK (i64, UsbFinderGetSerialNumber, PROC_ADDRESS ("nbamUsbFinder.dll", "nbamUsbFinderGetSerialNumber"), i32 a1, char *a2) {
|
||||
strcpy (a2, chassisId.c_str ());
|
||||
return 0;
|
||||
}
|
||||
|
||||
HOOK (i32, ws2_getaddrinfo, PROC_ADDRESS ("ws2_32.dll", "getaddrinfo"), const char *node, char *service, void *hints, void *out) {
|
||||
return originalws2_getaddrinfo (server.c_str (), service, hints, out);
|
||||
FAST_HOOK (i32, ws2_getaddrinfo, PROC_ADDRESS ("ws2_32.dll", "getaddrinfo"), const char *node, char *service, void *hints, void *out) {
|
||||
return originalws2_getaddrinfo.stdcall<i32> (server.c_str (), service, hints, out);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -140,6 +140,51 @@ CreateCard () {
|
||||
WritePrivateProfileStringA ("card", "chipId2", buf, ".\\card.ini");
|
||||
}
|
||||
|
||||
void
|
||||
ElevateProcess () {
|
||||
HANDLE hToken;
|
||||
TOKEN_PRIVILEGES tp;
|
||||
LUID luid;
|
||||
|
||||
// 获取当前进程的访问令牌
|
||||
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
|
||||
LogMessage (LogLevel::ERROR, "OpenProcessToken failed: {}", GetLastError());
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取 SE_DEBUG_NAME 权限的 LUID
|
||||
if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid)) {
|
||||
LogMessage (LogLevel::ERROR, "LookupPrivilegeValue failed: {}", GetLastError());
|
||||
CloseHandle(hToken);
|
||||
return;
|
||||
}
|
||||
|
||||
tp.PrivilegeCount = 1;
|
||||
tp.Privileges[0].Luid = luid;
|
||||
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||||
|
||||
// 调整权限
|
||||
if (!AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL)) {
|
||||
LogMessage (LogLevel::ERROR, "AdjustTokenPrivileges failed: {}", GetLastError());
|
||||
CloseHandle(hToken);
|
||||
return;
|
||||
}
|
||||
|
||||
LogMessage (LogLevel::INFO, "Privileges adjusted successfully!");
|
||||
CloseHandle(hToken);
|
||||
}
|
||||
|
||||
bool DisableDEP() {
|
||||
if (SetProcessDEPPolicy(PROCESS_DEP_ENABLE)) {
|
||||
// std::cout << "DEP disabled successfully.\n";
|
||||
return true;
|
||||
} else {
|
||||
LogMessage (LogLevel::ERROR, "Failed to disable DEP: {}", GetLastError());
|
||||
// std::cerr << "Failed to disable DEP: " << GetLastError() << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL
|
||||
DllMain (HMODULE module, const DWORD reason, LPVOID reserved) {
|
||||
if (reason == DLL_PROCESS_ATTACH) {
|
||||
@@ -147,14 +192,19 @@ DllMain (HMODULE module, const DWORD reason, LPVOID reserved) {
|
||||
// I/O in DllMain can easily cause a deadlock
|
||||
|
||||
// Init logger for loading config
|
||||
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
InitializeLogger (GetLogLevel (logLevelStr), logToFile);
|
||||
LogMessage (LogLevel::INFO, "Loading config...");
|
||||
|
||||
// ElevateProcess ();
|
||||
// DisableDEP ();
|
||||
patches::Timer::Init ();
|
||||
#ifdef ASYNC_IO
|
||||
LogMessage (LogLevel::WARN, "(experimental) Using Async IO!");
|
||||
InitializeKeyboard ();
|
||||
#endif
|
||||
|
||||
LogMessage (LogLevel::INFO, "Loading config...");
|
||||
|
||||
std::string version = "auto";
|
||||
const std::filesystem::path configPath = std::filesystem::current_path () / "config.toml";
|
||||
const std::unique_ptr<toml_table_t, void (*) (toml_table_t *)> config_ptr (openConfig (configPath), toml_free);
|
||||
@@ -177,10 +227,7 @@ DllMain (HMODULE module, const DWORD reason, LPVOID reserved) {
|
||||
std::strcat (placeId, countryCode.c_str ());
|
||||
std::strcat (placeId, "0FF0");
|
||||
}
|
||||
if (const auto patches = openConfigSection (config, "patches")) {
|
||||
version = readConfigString (patches, "version", version);
|
||||
highResTimer = readConfigBool (patches, "high_res_timer", highResTimer);
|
||||
}
|
||||
if (const auto patches = openConfigSection (config, "patches")) version = readConfigString (patches, "version", version);
|
||||
if (const auto emulation = openConfigSection (config, "emulation")) {
|
||||
emulateUsio = readConfigBool (emulation, "usio", emulateUsio);
|
||||
emulateCardReader = readConfigBool (emulation, "card_reader", emulateCardReader);
|
||||
@@ -221,7 +268,7 @@ DllMain (HMODULE module, const DWORD reason, LPVOID reserved) {
|
||||
MessageBoxA (nullptr, "Unknown patch version", nullptr, MB_OK);
|
||||
ExitProcess (0);
|
||||
}
|
||||
LogMessage (LogLevel::INFO, "GameVersion is %s", GameVersionToString (gameVersion));
|
||||
LogMessage (LogLevel::INFO, "GameVersion is {}", GameVersionToString (gameVersion));
|
||||
|
||||
patches::Plugins::LoadPlugins ();
|
||||
patches::Plugins::InitVersion (gameVersion);
|
||||
@@ -234,24 +281,24 @@ DllMain (HMODULE module, const DWORD reason, LPVOID reserved) {
|
||||
|
||||
LogMessage (LogLevel::INFO, "==== Loading patches, please wait...");
|
||||
|
||||
if (cursor) INSTALL_HOOK (ShowMouse);
|
||||
INSTALL_HOOK (ExitWindows);
|
||||
INSTALL_HOOK (CreateWindow);
|
||||
INSTALL_HOOK (SetWindowPosition);
|
||||
if (cursor) INSTALL_FAST_HOOK (ShowMouse);
|
||||
INSTALL_FAST_HOOK (ExitWindows);
|
||||
INSTALL_FAST_HOOK (CreateWindow);
|
||||
INSTALL_FAST_HOOK (SetWindowPosition);
|
||||
|
||||
INSTALL_HOOK (ExitProcessHook);
|
||||
INSTALL_FAST_HOOK (ExitProcessHook);
|
||||
|
||||
INSTALL_HOOK (XinputGetState);
|
||||
INSTALL_HOOK (XinputSetState);
|
||||
INSTALL_HOOK (XinputGetCapabilites);
|
||||
INSTALL_FAST_HOOK (XinputGetState);
|
||||
INSTALL_FAST_HOOK (XinputSetState);
|
||||
INSTALL_FAST_HOOK (XinputGetCapabilites);
|
||||
|
||||
INSTALL_HOOK (ssleay_Shutdown);
|
||||
INSTALL_FAST_HOOK (ssleay_Shutdown);
|
||||
|
||||
INSTALL_HOOK (UsbFinderInitialize);
|
||||
INSTALL_HOOK (UsbFinderRelease);
|
||||
INSTALL_HOOK (UsbFinderGetSerialNumber);
|
||||
INSTALL_FAST_HOOK (UsbFinderInitialize);
|
||||
INSTALL_FAST_HOOK (UsbFinderRelease);
|
||||
INSTALL_FAST_HOOK (UsbFinderGetSerialNumber);
|
||||
|
||||
INSTALL_HOOK (ws2_getaddrinfo);
|
||||
INSTALL_FAST_HOOK (ws2_getaddrinfo);
|
||||
|
||||
bnusio::Init ();
|
||||
|
||||
@@ -270,11 +317,8 @@ DllMain (HMODULE module, const DWORD reason, LPVOID reserved) {
|
||||
patches::LayeredFs::Init ();
|
||||
patches::TestMode::Init ();
|
||||
|
||||
if (highResTimer) {
|
||||
patches::Timer::Init ();
|
||||
}
|
||||
|
||||
LogMessage (LogLevel::INFO, "==== Finished Loading patches!");
|
||||
std::chrono::duration<double> duration = std::chrono::high_resolution_clock::now() - start;
|
||||
LogMessage (LogLevel::INFO, "==== Finished Loading patches! using: {:.2f}ms", duration.count () * 1000);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
+36
-6
@@ -66,6 +66,17 @@ const HMODULE MODULE_HANDLE = GetModuleHandle (nullptr);
|
||||
std::map<u64, SafetyHookMid> mapOf##functionName; \
|
||||
void implOf##functionName (SafetyHookContext &ctx)
|
||||
|
||||
#define FAST_HOOK(returnType, functionName, location, ...) \
|
||||
typedef returnType (*functionName) (__VA_ARGS__); \
|
||||
SafetyHookInline original##functionName; \
|
||||
void *where##functionName = (void *)(location); \
|
||||
returnType implOf##functionName (__VA_ARGS__)
|
||||
|
||||
#define FAST_HOOK_DYNAMIC(returnType, functionName, ...) \
|
||||
typedef returnType (*functionName) (__VA_ARGS__); \
|
||||
SafetyHookInline original##functionName; \
|
||||
returnType implOf##functionName (__VA_ARGS__)
|
||||
|
||||
#define INSTALL_HOOK(functionName) \
|
||||
{ \
|
||||
LogMessage (LogLevel::DEBUG, std::string ("Installing hook for ") + #functionName); \
|
||||
@@ -103,27 +114,46 @@ const HMODULE MODULE_HANDLE = GetModuleHandle (nullptr);
|
||||
#define INSTALL_MID_HOOK_DYNAMIC(functionName, location) \
|
||||
{ mapOf##functionName[location] = safetyhook::create_mid (location, implOf##functionName); }
|
||||
|
||||
#define INSTALL_FAST_HOOK(functionName) \
|
||||
{ \
|
||||
LogMessage (LogLevel::DEBUG, std::string ("Installing fast hook for ") + #functionName); \
|
||||
original##functionName = safetyhook::create_inline (where##functionName, (void*)implOf##functionName); \
|
||||
}
|
||||
|
||||
#define INSTALL_FAST_HOOK_DYNAMIC(functionName, location) \
|
||||
{ \
|
||||
LogMessage (LogLevel::DEBUG, std::string ("Installing fast hook dynamic for ") + #functionName); \
|
||||
if (auto hook = safetyhook::InlineHook::create((void *)location, (void*)implOf##functionName)) {\
|
||||
original##functionName = std::move(*hook); \
|
||||
} else { \
|
||||
LogMessage (LogLevel::ERROR, std::string ("Error Installing fast hook dynamic for ") + #functionName);\
|
||||
ExitProcess (1); \
|
||||
} \
|
||||
}
|
||||
// original##functionName = safetyhook::create_inline ((void *)location, (void*)implOf##functionName); \
|
||||
// }
|
||||
|
||||
inline bool sendFlag = false;
|
||||
#define SCENE_RESULT_HOOK(functionName, location) \
|
||||
HOOK (void, functionName, location, i64 a1, i64 a2, i64 a3) { \
|
||||
FAST_HOOK (void, functionName, location, i64 a1, i64 a2, i64 a3) { \
|
||||
if (TestMode::ReadTestModeValue (L"ModInstantResult") != 1 && TestMode::ReadTestModeValue (L"NumberOfStageItem") <= 4) { \
|
||||
original##functionName (a1, a2, a3); \
|
||||
original##functionName.fastcall (a1, a2, a3); \
|
||||
return; \
|
||||
} \
|
||||
sendFlag = true; \
|
||||
original##functionName (a1, a2, a3); \
|
||||
original##functionName.fastcall (a1, a2, a3); \
|
||||
ExecuteSendResultData (); \
|
||||
}
|
||||
|
||||
#define SEND_RESULT_HOOK(functionName, location) \
|
||||
HOOK (void, functionName, location, i64 a1) { \
|
||||
FAST_HOOK (void, functionName, location, i64 a1) { \
|
||||
if (TestMode::ReadTestModeValue (L"ModInstantResult") != 1 && TestMode::ReadTestModeValue (L"NumberOfStageItem") <= 4) { \
|
||||
original##functionName (a1); \
|
||||
original##functionName.fastcall (a1); \
|
||||
return; \
|
||||
} \
|
||||
if (sendFlag) { \
|
||||
sendFlag = false; \
|
||||
original##functionName (a1); \
|
||||
original##functionName.fastcall (a1); \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
+10
-5
@@ -70,11 +70,16 @@ LogMessageHandler (const char *function, const char *codeFile, int codeLine, Log
|
||||
std::string logMessage = logStream.str ();
|
||||
|
||||
// Print the log message
|
||||
std::cout << "[" << timeStamp.str () << "] "; // Timestamp
|
||||
SetConsoleTextAttribute (consoleHandle, GetLogLevelColor (messageLevel)); // Set Level color
|
||||
std::cout << logType; // Level
|
||||
SetConsoleTextAttribute (consoleHandle, FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY); // Reset console color
|
||||
std::cout << logMessage << std::endl; // Log message
|
||||
std::cout << "[" << timeStamp.str () << "] "; // Timestamp
|
||||
SetConsoleTextAttribute (consoleHandle, GetLogLevelColor (messageLevel)); // Set Level color
|
||||
std::cout << logType; // Level
|
||||
if (messageLevel != LogLevel::ERROR) {
|
||||
SetConsoleTextAttribute (consoleHandle, FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY); // Reset console color
|
||||
}
|
||||
std::cout << logMessage << std::endl; // Log message
|
||||
if (messageLevel == LogLevel::ERROR) {
|
||||
SetConsoleTextAttribute (consoleHandle, FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY); // Reset console color
|
||||
}
|
||||
std::cout.flush (); // Flush to ensure immediate writing
|
||||
|
||||
if (loggerInstance->logFile != nullptr) {
|
||||
|
||||
@@ -525,7 +525,7 @@ public:
|
||||
HRESULT LockServer (i32 lock) override { return 0; }
|
||||
};
|
||||
|
||||
static HRESULT (STDAPICALLTYPE *g_origCoCreateInstance) (const IID *rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, const IID *riid, LPVOID *ppv);
|
||||
SafetyHookInline originalCoCreateInstanceHook;
|
||||
|
||||
static HRESULT STDAPICALLTYPE
|
||||
CoCreateInstanceHook (const IID *const rclsid, const LPUNKNOWN pUnkOuter, const DWORD dwClsContext, const IID *const riid, LPVOID *ppv) {
|
||||
@@ -540,7 +540,7 @@ CoCreateInstanceHook (const IID *const rclsid, const LPUNKNOWN pUnkOuter, const
|
||||
const auto cauth = new CAuth ();
|
||||
result = cauth->QueryInterface (*riid, ppv);
|
||||
} else {
|
||||
result = g_origCoCreateInstance (rclsid, pUnkOuter, dwClsContext, riid, ppv);
|
||||
result = originalCoCreateInstanceHook.stdcall<HRESULT> (rclsid, pUnkOuter, dwClsContext, riid, ppv);
|
||||
}
|
||||
|
||||
CoTaskMemFree (clsidStr);
|
||||
@@ -552,10 +552,8 @@ void
|
||||
Init () {
|
||||
LogMessage (LogLevel::INFO, "Init AmAuth patches");
|
||||
|
||||
MH_Initialize ();
|
||||
MH_CreateHookApi (L"ole32.dll", "CoCreateInstance", reinterpret_cast<LPVOID> (CoCreateInstanceHook),
|
||||
reinterpret_cast<void **> (&g_origCoCreateInstance));
|
||||
MH_EnableHook (nullptr);
|
||||
auto whereCoCreateInstance = GetProcAddress (LoadLibraryW (L"ole32.dll"), "CoCreateInstance");
|
||||
originalCoCreateInstanceHook = safetyhook::create_inline ((void *)whereCoCreateInstance, CoCreateInstanceHook);
|
||||
|
||||
addrinfo *res = nullptr;
|
||||
getaddrinfo (server.c_str (), "", nullptr, &res);
|
||||
|
||||
+16
-16
@@ -24,16 +24,16 @@ std::string asioDriver;
|
||||
|
||||
float volumeRate = 0.0f;
|
||||
|
||||
HOOK_DYNAMIC (i64, NUSCDeviceInit, void *a1, nusc_init_config_t *a2, nusc_init_config_t *a3, void *a4) {
|
||||
FAST_HOOK_DYNAMIC (i64, NUSCDeviceInit, void *a1, nusc_init_config_t *a2, nusc_init_config_t *a3, void *a4) {
|
||||
LogMessage (LogLevel::INFO, std::string ("Device mode is ") + (asio ? "ASIO" : wasapiShared ? "wasapi shared" : "wasapi exclusive"));
|
||||
if (asio) LogMessage (LogLevel::INFO, (std::string ("ASIO driver is ") + asioDriver).c_str ());
|
||||
a2->device_mode = asio;
|
||||
a2->asio_driver_name = asio ? asioDriver.c_str () : "";
|
||||
a2->wasapi_exclusive = asio ? 1 : wasapiShared ? 0 : 1;
|
||||
return originalNUSCDeviceInit (a1, a2, a3, a4);
|
||||
return originalNUSCDeviceInit.fastcall<i64> (a1, a2, a3, a4);
|
||||
}
|
||||
HOOK_DYNAMIC (bool, LoadASIODriver, void *a1, const char *a2) {
|
||||
const auto result = originalLoadASIODriver (a1, a2);
|
||||
FAST_HOOK_DYNAMIC (bool, LoadASIODriver, void *a1, const char *a2) {
|
||||
const auto result = originalLoadASIODriver.fastcall<bool> (a1, a2);
|
||||
if (!result) {
|
||||
LogMessage (LogLevel::ERROR, (std::string ("Failed to load ASIO driver ") + asioDriver).c_str ());
|
||||
MessageBoxA (nullptr, "Failed to load ASIO driver", nullptr, MB_OK);
|
||||
@@ -41,13 +41,13 @@ HOOK_DYNAMIC (bool, LoadASIODriver, void *a1, const char *a2) {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
HOOK_DYNAMIC (u64, NuscBusVolume, u64 a1, u64 a2, float a3) {
|
||||
FAST_HOOK_DYNAMIC (u64, NuscBusVolume, u64 a1, u64 a2, float a3) {
|
||||
if (volumeRate == 0.0f) {
|
||||
int value = patches::TestMode::ReadTestModeValue (L"OutputLevelSpeakerItem");
|
||||
if (value == -1) return originalNuscBusVolume (a1, a2, a3);
|
||||
if (value == -1) return originalNuscBusVolume.fastcall<u64> (a1, a2, a3);
|
||||
volumeRate = value <= 100 ? 1.0f : value / 100.0f;
|
||||
}
|
||||
return originalNuscBusVolume (a1, a2, a3 * volumeRate);
|
||||
return originalNuscBusVolume.fastcall<u64> (a1, a2, a3 * volumeRate);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -71,24 +71,24 @@ Init () {
|
||||
|
||||
switch (gameVersion) {
|
||||
case GameVersion::JPN00: {
|
||||
INSTALL_HOOK_DYNAMIC (NUSCDeviceInit, ASLR (0x140552160));
|
||||
INSTALL_HOOK_DYNAMIC (LoadASIODriver, ASLR (0x14055A950));
|
||||
INSTALL_FAST_HOOK_DYNAMIC (NUSCDeviceInit, ASLR (0x140552160));
|
||||
INSTALL_FAST_HOOK_DYNAMIC (LoadASIODriver, ASLR (0x14055A950));
|
||||
break;
|
||||
}
|
||||
case GameVersion::JPN08: {
|
||||
INSTALL_HOOK_DYNAMIC (NUSCDeviceInit, ASLR (0x140692E00));
|
||||
INSTALL_HOOK_DYNAMIC (LoadASIODriver, ASLR (0x14069B750));
|
||||
INSTALL_FAST_HOOK_DYNAMIC (NUSCDeviceInit, ASLR (0x140692E00));
|
||||
INSTALL_FAST_HOOK_DYNAMIC (LoadASIODriver, ASLR (0x14069B750));
|
||||
break;
|
||||
}
|
||||
case GameVersion::JPN39: {
|
||||
INSTALL_HOOK_DYNAMIC (NUSCDeviceInit, ASLR (0x1407C8620));
|
||||
INSTALL_HOOK_DYNAMIC (LoadASIODriver, ASLR (0x1407D0F70));
|
||||
INSTALL_HOOK_DYNAMIC (NuscBusVolume, ASLR (0x1407B1C30));
|
||||
INSTALL_FAST_HOOK_DYNAMIC (NUSCDeviceInit, ASLR (0x1407C8620));
|
||||
INSTALL_FAST_HOOK_DYNAMIC (LoadASIODriver, ASLR (0x1407D0F70));
|
||||
INSTALL_FAST_HOOK_DYNAMIC (NuscBusVolume, ASLR (0x1407B1C30));
|
||||
break;
|
||||
}
|
||||
case GameVersion::CHN00: {
|
||||
INSTALL_HOOK_DYNAMIC (NUSCDeviceInit, ASLR (0x140777F70));
|
||||
INSTALL_HOOK_DYNAMIC (LoadASIODriver, ASLR (0x1407808C0));
|
||||
INSTALL_FAST_HOOK_DYNAMIC (NUSCDeviceInit, ASLR (0x140777F70));
|
||||
INSTALL_FAST_HOOK_DYNAMIC (LoadASIODriver, ASLR (0x1407808C0));
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
|
||||
@@ -38,8 +38,10 @@ void Init ();
|
||||
} // namespace AmAuth
|
||||
namespace LayeredFs {
|
||||
void Init ();
|
||||
void RegisterBefore (const std::function<std::string (const std::string, const std::string)> &fileHandler);
|
||||
void RegisterAfter (const std::function<std::string (const std::string, const std::string)> &fileHandler);
|
||||
void RegisterBeforeA (const std::function<std::string (const std::string, const std::string)> &fileHandler);
|
||||
void RegisterAfterA (const std::function<std::string (const std::string, const std::string)> &fileHandler);
|
||||
void RegisterBeforeW (const std::function<std::wstring (const std::wstring, const std::wstring)> &fileHandler);
|
||||
void RegisterAfterW (const std::function<std::wstring (const std::wstring, const std::wstring)> &fileHandler);
|
||||
} // namespace LayeredFs
|
||||
namespace TestMode {
|
||||
class Applicable {
|
||||
@@ -68,6 +70,7 @@ void RegisterItemAfter (const std::wstring &query, const std::wstring &item);
|
||||
void RegisterItemAfter (const std::wstring &query, Applicable *item);
|
||||
void RegisterModify (const std::wstring &query, const std::function<void (pugi::xml_node &)> &nodeModify, const std::function<void ()> &initMethod);
|
||||
void RegisterModify (const std::wstring &query, const std::function<void (pugi::xml_node &)> &nodeModify);
|
||||
void RegisterHook (const std::function<void()> &initMethod);
|
||||
} // namespace TestMode
|
||||
namespace Plugins {
|
||||
// typedefs
|
||||
|
||||
+135
-104
@@ -47,17 +47,39 @@ namespace Card {
|
||||
};
|
||||
|
||||
namespace Internal {
|
||||
enum CardErrorCode { ReadError = -201, NotSupport = -400 };
|
||||
|
||||
void
|
||||
AgentInsertCard (uint8_t cardData[168], bool internalInvoke) {
|
||||
InsertCard (uint8_t cardData[168], bool internalInvoke) {
|
||||
if (callbackTouch) {
|
||||
state = internalInvoke ? State::Disable : State::CopyWait;
|
||||
patches::Plugins::UpdateStatus (1, false);
|
||||
if (!internalInvoke) {
|
||||
LogMessage (LogLevel::DEBUG, "[Card] Call CallbackTouch!");
|
||||
for (int i = 0; i < 8; i++) {
|
||||
std::ostringstream cardDataOut;
|
||||
cardDataOut << std::hex << std::uppercase;
|
||||
for (int j = 0; j < 21; j++) {
|
||||
cardDataOut << std::setw (2) << std::setfill ('0') << (int)cardData[i * 21 + j] << " ";
|
||||
}
|
||||
LogMessage (LogLevel::DEBUG, cardDataOut.str ());
|
||||
}
|
||||
}
|
||||
callbackTouch (0, 0, cardData, touchData);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AgentInsertCardPlugin (int32_t a1, int32_t a2, uint8_t *a3, uint64_t a4) {
|
||||
InsertError (CardErrorCode errorCode) {
|
||||
if (callbackTouch) {
|
||||
state = State::CopyWait;
|
||||
patches::Plugins::UpdateStatus (1, false);
|
||||
callbackTouch (0, errorCode, cardData, touchData);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AgentCallbackTouch (int32_t a1, int32_t a2, uint8_t *a3, uint64_t a4) {
|
||||
if (callbackTouch) {
|
||||
state = State::CopyWait;
|
||||
patches::Plugins::UpdateStatus (1, false);
|
||||
@@ -66,10 +88,11 @@ namespace Card {
|
||||
}
|
||||
|
||||
void
|
||||
AgentInsertCardOfficial (int32_t a1, int32_t a2, uint8_t *a3, uint64_t a4) {
|
||||
AgentCallbackTouchOfficial (int32_t a1, int32_t a2, uint8_t *a3, uint64_t a4) {
|
||||
if (callbackTouch) {
|
||||
state = State::CopyWait;
|
||||
patches::Plugins::UpdateStatus (1, false);
|
||||
LogMessage (LogLevel::DEBUG, "Official CallbackTouch a1={} a2={}", a1, a2);
|
||||
if (acceptInvalidCards && !a3[0]) {
|
||||
char AccessId[21] = "00000000000000000001";
|
||||
uint8_t UID[8] = {a3[12], a3[14], a3[15], a3[16], 0x90, 0x00, 0x00, 0x00};
|
||||
@@ -94,45 +117,45 @@ namespace Card {
|
||||
for (size_t i = 0; i < 32; i++) *(cardData + 0x2C + i) = i < chipId.length() ? chipId[i] : 0;
|
||||
for (size_t i = 0; i < 20; i++) *(cardData + 0x50 + i) = i < accessCode.length() ? accessCode[i] : 0;
|
||||
if (!internalInvoke) LogMessage (LogLevel::INFO, "[Card] Insert Card accessCode: \"{}\" chipId: \"{}\"", accessCode, chipId);
|
||||
patches::Scanner::Card::Internal::AgentInsertCard (cardData, internalInvoke);
|
||||
patches::Scanner::Card::Internal::InsertCard (cardData, internalInvoke);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
HOOK (u64, bngrw_Init, PROC_ADDRESS ("bngrw.dll", "BngRwInit")) { return 0; }
|
||||
HOOK (void, bngrw_Fin, PROC_ADDRESS ("bngrw.dll", "BngRwFin")) { return; }
|
||||
HOOK (u64, bngrw_IsCmdExec, PROC_ADDRESS ("bngrw.dll", "BngRwIsCmdExec")) { return 0xFFFFFFFF; }
|
||||
HOOK (i32, bngrw_ReqSendUrl, PROC_ADDRESS ("bngrw.dll", "BngRwReqSendUrlTo")) { return 1; }
|
||||
HOOK (u64, bngrw_ReqLed, PROC_ADDRESS ("bngrw.dll", "BngRwReqLed")) { return 1; }
|
||||
HOOK (u64, bngrw_ReqBeep, PROC_ADDRESS ("bngrw.dll", "BngRwReqBeep")) { return 1; }
|
||||
HOOK (u64, bngrw_ReqAction, PROC_ADDRESS ("bngrw.dll", "BngRwReqAction")) { return 1; }
|
||||
HOOK (u64, bngrw_ReqSetLedPower, PROC_ADDRESS ("bngrw.dll", "BngRwReqSetLedPower")) { return 0; }
|
||||
HOOK (u64, bngrw_GetRetryCount, PROC_ADDRESS ("bngrw.dll", "BngRwGetTotalRetryCount")) { return 0; }
|
||||
HOOK (u64, bngrw_GetFwVersion, PROC_ADDRESS ("bngrw.dll", "BngRwGetFwVersion")) { return 0; }
|
||||
HOOK (u64, bngrw_ReqFwVersionUp, PROC_ADDRESS ("bngrw.dll", "BngRwReqFwVersionUp")) { return 1; }
|
||||
HOOK (u64, bngrw_ReqFwCleanup, PROC_ADDRESS ("bngrw.dll", "BngRwReqFwCleanup")) { return 1; }
|
||||
HOOK (u64, bngrw_ReadMifare, PROC_ADDRESS ("bngrw.dll", "BngRwExReadMifareAllBlock")) { return 0xFFFFFF9C; }
|
||||
HOOK (u64, bngrw_GetStationID, PROC_ADDRESS ("bngrw.dll", "BngRwGetStationID")) { return 0; }
|
||||
HOOK (i32, bngrw_ReqSendMail, PROC_ADDRESS ("bngrw.dll", "BngRwReqSendMailTo")) { return 1; }
|
||||
HOOK (i32, bngrw_ReqLatchID, PROC_ADDRESS ("bngrw.dll", "BngRwReqLatchID")) { return 1; }
|
||||
HOOK (u64, bngrw_ReqAiccAuth, PROC_ADDRESS ("bngrw.dll", "BngRwReqAiccAuth")) { return 1; }
|
||||
HOOK (u64, bngrw_DevReset, PROC_ADDRESS ("bngrw.dll", "BngRwDevReset")) { return 1; } // Invoke when enter testmode
|
||||
HOOK (i32, bngrw_ReqCancel, PROC_ADDRESS ("bngrw.dll", "BngRwReqCancel")) {
|
||||
FAST_HOOK (u64, bngrw_Init, PROC_ADDRESS ("bngrw.dll", "BngRwInit")) { return 0; }
|
||||
FAST_HOOK (void, bngrw_Fin, PROC_ADDRESS ("bngrw.dll", "BngRwFin")) { return; }
|
||||
FAST_HOOK (u64, bngrw_IsCmdExec, PROC_ADDRESS ("bngrw.dll", "BngRwIsCmdExec")) { return 0xFFFFFFFF; }
|
||||
FAST_HOOK (i32, bngrw_ReqSendUrl, PROC_ADDRESS ("bngrw.dll", "BngRwReqSendUrlTo")) { return 1; }
|
||||
FAST_HOOK (u64, bngrw_ReqLed, PROC_ADDRESS ("bngrw.dll", "BngRwReqLed")) { return 1; }
|
||||
FAST_HOOK (u64, bngrw_ReqBeep, PROC_ADDRESS ("bngrw.dll", "BngRwReqBeep")) { return 1; }
|
||||
FAST_HOOK (u64, bngrw_ReqAction, PROC_ADDRESS ("bngrw.dll", "BngRwReqAction")) { return 1; }
|
||||
FAST_HOOK (u64, bngrw_ReqSetLedPower, PROC_ADDRESS ("bngrw.dll", "BngRwReqSetLedPower")) { return 0; }
|
||||
FAST_HOOK (u64, bngrw_GetRetryCount, PROC_ADDRESS ("bngrw.dll", "BngRwGetTotalRetryCount")) { return 0; }
|
||||
FAST_HOOK (u64, bngrw_GetFwVersion, PROC_ADDRESS ("bngrw.dll", "BngRwGetFwVersion")) { return 0; }
|
||||
FAST_HOOK (u64, bngrw_ReqFwVersionUp, PROC_ADDRESS ("bngrw.dll", "BngRwReqFwVersionUp")) { return 1; }
|
||||
FAST_HOOK (u64, bngrw_ReqFwCleanup, PROC_ADDRESS ("bngrw.dll", "BngRwReqFwCleanup")) { return 1; }
|
||||
FAST_HOOK (u64, bngrw_ReadMifare, PROC_ADDRESS ("bngrw.dll", "BngRwExReadMifareAllBlock")) { return 0xFFFFFF9C; }
|
||||
FAST_HOOK (u64, bngrw_GetStationID, PROC_ADDRESS ("bngrw.dll", "BngRwGetStationID")) { return 0; }
|
||||
FAST_HOOK (i32, bngrw_ReqSendMail, PROC_ADDRESS ("bngrw.dll", "BngRwReqSendMailTo")) { return 1; }
|
||||
FAST_HOOK (i32, bngrw_ReqLatchID, PROC_ADDRESS ("bngrw.dll", "BngRwReqLatchID")) { return 1; }
|
||||
FAST_HOOK (u64, bngrw_ReqAiccAuth, PROC_ADDRESS ("bngrw.dll", "BngRwReqAiccAuth")) { return 1; }
|
||||
FAST_HOOK (u64, bngrw_DevReset, PROC_ADDRESS ("bngrw.dll", "BngRwDevReset")) { return 1; } // Invoke when enter testmode
|
||||
FAST_HOOK (i32, bngrw_ReqCancel, PROC_ADDRESS ("bngrw.dll", "BngRwReqCancel")) {
|
||||
if (state != State::Disable) {
|
||||
state = State::Disable;
|
||||
patches::Scanner::Card::Internal::Commit0 (accessCodeTemplate, chipIdTemplate, true);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
HOOK (u64, bngrw_Attach, PROC_ADDRESS ("bngrw.dll", "BngRwAttach"), i32 a1, char *a2, i32 a3, i32 a4, CallbackAttach callback, i32 *a6) {
|
||||
FAST_HOOK (u64, bngrw_Attach, PROC_ADDRESS ("bngrw.dll", "BngRwAttach"), i32 a1, char *a2, i32 a3, i32 a4, CallbackAttach callback, i32 *a6) {
|
||||
callbackAttach = callback;
|
||||
attachData = a6;
|
||||
return 1;
|
||||
}
|
||||
HOOK (u64, bngrw_ReqWaitTouch, PROC_ADDRESS ("bngrw.dll", "BngRwReqWaitTouch"), u32 a1, i32 a2, u32 a3, CallbackTouch callback, u64 a5) {
|
||||
FAST_HOOK (u64, bngrw_ReqWaitTouch, PROC_ADDRESS ("bngrw.dll", "BngRwReqWaitTouch"), u32 a1, i32 a2, u32 a3, CallbackTouch callback, u64 a5) {
|
||||
state = State::Ready;
|
||||
patches::Plugins::UpdateStatus (1, true);
|
||||
patches::Plugins::WaitTouch (Internal::AgentInsertCardPlugin, a5);
|
||||
patches::Plugins::WaitTouch (Internal::AgentCallbackTouch, a5);
|
||||
callbackTouch = callback;
|
||||
touchData = a5;
|
||||
return 1;
|
||||
@@ -143,14 +166,14 @@ namespace Card {
|
||||
state = State::Disable;
|
||||
patches::Plugins::UpdateStatus (1, false);
|
||||
}
|
||||
return originalbngrw_ReqCancelOfficial(a1);
|
||||
return originalbngrw_ReqCancelOfficial (a1);
|
||||
}
|
||||
HOOK (u64, bngrw_ReqWaitTouchOfficial, PROC_ADDRESS ("bngrw.dll", "BngRwReqWaitTouch"), u32 a1, i32 a2, u32 a3, CallbackTouch callback, u64 a5) {
|
||||
state = State::Ready;
|
||||
patches::Plugins::UpdateStatus (1, true);
|
||||
callbackTouch = callback;
|
||||
touchData = a5;
|
||||
return originalbngrw_ReqWaitTouchOfficial (a1, a2, a3, Internal::AgentInsertCardOfficial, a5);
|
||||
return originalbngrw_ReqWaitTouchOfficial (a1, a2, a3, Internal::AgentCallbackTouchOfficial, a5);
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -165,10 +188,12 @@ namespace Card {
|
||||
}
|
||||
if (accessCode.length() == 0 || accessCode.length() > 20) {
|
||||
LogMessage (LogLevel::ERROR, "[Card] Not an effective accessCode: \"{}\"", accessCode);
|
||||
patches::Scanner::Card::Internal::InsertError (Internal::CardErrorCode::NotSupport);
|
||||
return false;
|
||||
}
|
||||
if (chipId.length() > 32) {
|
||||
LogMessage (LogLevel::ERROR, "[Card] Not an effective chipId: \"{}\"", chipId);
|
||||
patches::Scanner::Card::Internal::InsertError (Internal::CardErrorCode::NotSupport);
|
||||
return false;
|
||||
}
|
||||
return patches::Scanner::Card::Internal::Commit0 (accessCode, chipId, false);
|
||||
@@ -190,75 +215,81 @@ namespace Card {
|
||||
return;
|
||||
}
|
||||
|
||||
INSTALL_HOOK (bngrw_Init)
|
||||
INSTALL_HOOK (bngrw_Fin);
|
||||
INSTALL_HOOK (bngrw_IsCmdExec);
|
||||
INSTALL_HOOK (bngrw_ReqCancel);
|
||||
INSTALL_HOOK (bngrw_ReqWaitTouch);
|
||||
INSTALL_HOOK (bngrw_ReqSendUrl);
|
||||
INSTALL_HOOK (bngrw_ReqLed);
|
||||
INSTALL_HOOK (bngrw_ReqBeep);
|
||||
INSTALL_HOOK (bngrw_ReqAction);
|
||||
INSTALL_HOOK (bngrw_ReqSetLedPower);
|
||||
INSTALL_HOOK (bngrw_GetRetryCount);
|
||||
INSTALL_HOOK (bngrw_GetFwVersion);
|
||||
INSTALL_HOOK (bngrw_ReqFwVersionUp);
|
||||
INSTALL_HOOK (bngrw_ReqFwCleanup);
|
||||
INSTALL_HOOK (bngrw_ReadMifare);
|
||||
INSTALL_HOOK (bngrw_GetStationID);
|
||||
INSTALL_HOOK (bngrw_ReqSendMail);
|
||||
INSTALL_HOOK (bngrw_ReqLatchID);
|
||||
INSTALL_HOOK (bngrw_ReqAiccAuth);
|
||||
INSTALL_HOOK (bngrw_Attach);
|
||||
INSTALL_HOOK (bngrw_DevReset);
|
||||
INSTALL_FAST_HOOK (bngrw_Init)
|
||||
INSTALL_FAST_HOOK (bngrw_Fin);
|
||||
INSTALL_FAST_HOOK (bngrw_IsCmdExec);
|
||||
INSTALL_FAST_HOOK (bngrw_ReqCancel);
|
||||
INSTALL_FAST_HOOK (bngrw_ReqWaitTouch);
|
||||
INSTALL_FAST_HOOK (bngrw_ReqSendUrl);
|
||||
INSTALL_FAST_HOOK (bngrw_ReqLed);
|
||||
INSTALL_FAST_HOOK (bngrw_ReqBeep);
|
||||
INSTALL_FAST_HOOK (bngrw_ReqAction);
|
||||
INSTALL_FAST_HOOK (bngrw_ReqSetLedPower);
|
||||
INSTALL_FAST_HOOK (bngrw_GetRetryCount);
|
||||
INSTALL_FAST_HOOK (bngrw_GetFwVersion);
|
||||
INSTALL_FAST_HOOK (bngrw_ReqFwVersionUp);
|
||||
INSTALL_FAST_HOOK (bngrw_ReqFwCleanup);
|
||||
INSTALL_FAST_HOOK (bngrw_ReadMifare);
|
||||
INSTALL_FAST_HOOK (bngrw_GetStationID);
|
||||
INSTALL_FAST_HOOK (bngrw_ReqSendMail);
|
||||
INSTALL_FAST_HOOK (bngrw_ReqLatchID);
|
||||
INSTALL_FAST_HOOK (bngrw_ReqAiccAuth);
|
||||
INSTALL_FAST_HOOK (bngrw_Attach);
|
||||
INSTALL_FAST_HOOK (bngrw_DevReset);
|
||||
patches::Plugins::InitCardReader (patches::Scanner::Card::Commit);
|
||||
}
|
||||
}
|
||||
namespace Qr {
|
||||
std::queue<std::vector<uint8_t>> scanQueue;
|
||||
std::queue<std::vector<uint8_t> *> scanQueue;
|
||||
State state = State::Disable;
|
||||
long long lastScan;
|
||||
|
||||
HOOK_DYNAMIC (char, QrInit, i64) { return 1; }
|
||||
HOOK_DYNAMIC (char, QrClose, i64) { return 1; }
|
||||
HOOK_DYNAMIC (char, QrRead, i64 a1) {
|
||||
FAST_HOOK_DYNAMIC (char, QrInit, i64) { return 1; }
|
||||
FAST_HOOK_DYNAMIC (char, QrClose, i64) { return 1; }
|
||||
FAST_HOOK_DYNAMIC (char, QrRead, i64 a1) {
|
||||
*(DWORD *)(a1 + 40) = 1;
|
||||
*(DWORD *)(a1 + 16) = 1;
|
||||
*(BYTE *)(a1 + 112) = 0;
|
||||
return 1;
|
||||
}
|
||||
HOOK_DYNAMIC (i64, CallQrUnknown, i64) { return 1; }
|
||||
HOOK_DYNAMIC (bool, Send1, i64 a1) {
|
||||
FAST_HOOK_DYNAMIC (i64, CallQrUnknown, i64) { return 1; }
|
||||
FAST_HOOK_DYNAMIC (bool, Send1, i64 a1) {
|
||||
*(BYTE *)(a1 + 88) = 1;
|
||||
*(i64 *)(a1 + 32) = *(i64 *)(a1 + 24);
|
||||
*(WORD *)(a1 + 89) = 0;
|
||||
return true;
|
||||
}
|
||||
HOOK_DYNAMIC (bool, Send2, i64 a1) {
|
||||
FAST_HOOK_DYNAMIC (bool, Send2, i64 a1) {
|
||||
*(WORD *)(a1 + 88) = 0;
|
||||
*(BYTE *)(a1 + 90) = 0;
|
||||
return true;
|
||||
}
|
||||
HOOK_DYNAMIC (bool, Send3, i64, char) { return true; }
|
||||
HOOK_DYNAMIC (bool, Send4, i64, const void *, i64) { return true; }
|
||||
HOOK_DYNAMIC (i64, CopyData, i64, void *dest, int length) {
|
||||
FAST_HOOK_DYNAMIC (bool, Send3, i64, char) { return true; }
|
||||
FAST_HOOK_DYNAMIC (bool, Send4, i64, const void *, i64) { return true; }
|
||||
FAST_HOOK_DYNAMIC (i64, CopyData, i64, void *dest, int length) {
|
||||
patches::Plugins::UsingQr ();
|
||||
lastScan = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now ().time_since_epoch ()).count ();
|
||||
if (state == State::CopyWait && scanQueue.size () > 0) {
|
||||
std::vector<uint8_t> data = scanQueue.front ();
|
||||
if ((int)data.size () > length) {
|
||||
LogMessage (LogLevel::ERROR, "[QR] Not an effective code, length: {} require: {}", data.size (), length);
|
||||
std::vector<uint8_t> *data = scanQueue.front ();
|
||||
if ((int)data->size () > length) {
|
||||
LogMessage (LogLevel::ERROR, "[QR] Not an effective code, length: {} require: {}", data->size (), length);
|
||||
}
|
||||
std::stringstream hexStream;
|
||||
hexStream << std::hex << std::uppercase << std::setfill ('0') << std::setw (2);
|
||||
for (size_t i = 0; i < data.size (); i++) hexStream << static_cast<int> (data[i]) << " ";
|
||||
LogMessage (LogLevel::INFO, "[QR] Read QRData size: {} data: {}\n", data.size (), hexStream.str ());
|
||||
memcpy (dest, data.data (), data.size () + 1);
|
||||
for (size_t i = 0; i < data->size (); i++) hexStream << static_cast<int> ((*data)[i]) << " ";
|
||||
LogMessage (LogLevel::INFO, "[QR] Read QRData size: {} data: {}\n", data->size (), hexStream.str ());
|
||||
size_t finalCopySize = std::min (data->size () + 1, (size_t)length);
|
||||
memcpy (dest, data->data (), finalCopySize);
|
||||
scanQueue.pop ();
|
||||
delete data;
|
||||
if (scanQueue.size () == 0) state = State::Ready;
|
||||
return data.size ();
|
||||
return finalCopySize;
|
||||
} else if (state == State::Disable) {
|
||||
while (!scanQueue.empty ()) scanQueue.pop ();
|
||||
while (!scanQueue.empty ()) {
|
||||
std::vector<uint8_t> *data = scanQueue.front ();
|
||||
delete data;
|
||||
scanQueue.pop ();
|
||||
}
|
||||
state = State::Ready;
|
||||
patches::Plugins::UpdateStatus (2, true);
|
||||
}
|
||||
@@ -279,10 +310,10 @@ namespace Qr {
|
||||
LogMessage (LogLevel::ERROR, "[QR] Not an effective code, length: 0");
|
||||
return false;
|
||||
}
|
||||
if (scanQueue.empty() || scanQueue.back() != buffer) {
|
||||
std::vector<uint8_t> scanData = {};
|
||||
if (scanQueue.empty() || *scanQueue.back() != buffer) {
|
||||
std::vector<uint8_t> *scanData = new std::vector<uint8_t> ();
|
||||
for (uint8_t byte_data : buffer)
|
||||
scanData.push_back (byte_data);
|
||||
scanData->push_back (byte_data);
|
||||
scanQueue.push (scanData);
|
||||
}
|
||||
if (state == State::Ready) state = State::CopyWait;
|
||||
@@ -406,51 +437,51 @@ namespace Qr {
|
||||
auto amHandle = reinterpret_cast<u64> (GetModuleHandle ("AMFrameWork.dll"));
|
||||
switch (gameVersion) {
|
||||
case GameVersion::JPN00: {
|
||||
INSTALL_HOOK_DYNAMIC (QrInit, (LPVOID)(amHandle + 0x1B3E0));
|
||||
INSTALL_HOOK_DYNAMIC (QrClose, (LPVOID)(amHandle + 0x1B5B0));
|
||||
INSTALL_HOOK_DYNAMIC (QrRead, (LPVOID)(amHandle + 0x1B600));
|
||||
INSTALL_HOOK_DYNAMIC (CallQrUnknown, (LPVOID)(amHandle + 0xFD40));
|
||||
INSTALL_HOOK_DYNAMIC (Send1, (LPVOID)(amHandle + 0x1BBB0));
|
||||
INSTALL_HOOK_DYNAMIC (Send2, (LPVOID)(amHandle + 0x1BBF0));
|
||||
INSTALL_HOOK_DYNAMIC (Send3, (LPVOID)(amHandle + 0x1BC60));
|
||||
INSTALL_FAST_HOOK_DYNAMIC (QrInit, (LPVOID)(amHandle + 0x1B3E0));
|
||||
INSTALL_FAST_HOOK_DYNAMIC (QrClose, (LPVOID)(amHandle + 0x1B5B0));
|
||||
INSTALL_FAST_HOOK_DYNAMIC (QrRead, (LPVOID)(amHandle + 0x1B600));
|
||||
INSTALL_FAST_HOOK_DYNAMIC (CallQrUnknown, (LPVOID)(amHandle + 0xFD40));
|
||||
INSTALL_FAST_HOOK_DYNAMIC (Send1, (LPVOID)(amHandle + 0x1BBB0));
|
||||
INSTALL_FAST_HOOK_DYNAMIC (Send2, (LPVOID)(amHandle + 0x1BBF0));
|
||||
INSTALL_FAST_HOOK_DYNAMIC (Send3, (LPVOID)(amHandle + 0x1BC60));
|
||||
// JPN00 has no Send4
|
||||
INSTALL_HOOK_DYNAMIC (CopyData, (LPVOID)(amHandle + 0x1BC30));
|
||||
INSTALL_FAST_HOOK_DYNAMIC (CopyData, (LPVOID)(amHandle + 0x1BC30));
|
||||
break;
|
||||
}
|
||||
case GameVersion::JPN08: {
|
||||
INSTALL_HOOK_DYNAMIC (QrInit, (LPVOID)(amHandle + 0x1BA00));
|
||||
INSTALL_HOOK_DYNAMIC (QrClose, (LPVOID)(amHandle + 0x1BBD0));
|
||||
INSTALL_HOOK_DYNAMIC (QrRead, (LPVOID)(amHandle + 0x1BC20));
|
||||
INSTALL_HOOK_DYNAMIC (CallQrUnknown, (LPVOID)(amHandle + 0xFD40));
|
||||
INSTALL_HOOK_DYNAMIC (Send1, (LPVOID)(amHandle + 0x1C220));
|
||||
INSTALL_HOOK_DYNAMIC (Send2, (LPVOID)(amHandle + 0x1C260));
|
||||
INSTALL_HOOK_DYNAMIC (Send3, (LPVOID)(amHandle + 0x1C2D0));
|
||||
INSTALL_FAST_HOOK_DYNAMIC (QrInit, (LPVOID)(amHandle + 0x1BA00));
|
||||
INSTALL_FAST_HOOK_DYNAMIC (QrClose, (LPVOID)(amHandle + 0x1BBD0));
|
||||
INSTALL_FAST_HOOK_DYNAMIC (QrRead, (LPVOID)(amHandle + 0x1BC20));
|
||||
INSTALL_FAST_HOOK_DYNAMIC (CallQrUnknown, (LPVOID)(amHandle + 0xFD40));
|
||||
INSTALL_FAST_HOOK_DYNAMIC (Send1, (LPVOID)(amHandle + 0x1C220));
|
||||
INSTALL_FAST_HOOK_DYNAMIC (Send2, (LPVOID)(amHandle + 0x1C260));
|
||||
INSTALL_FAST_HOOK_DYNAMIC (Send3, (LPVOID)(amHandle + 0x1C2D0));
|
||||
// JPN08 has no Send4
|
||||
INSTALL_HOOK_DYNAMIC (CopyData, (LPVOID)(amHandle + 0x1C2A0));
|
||||
INSTALL_FAST_HOOK_DYNAMIC (CopyData, (LPVOID)(amHandle + 0x1C2A0));
|
||||
break;
|
||||
}
|
||||
case GameVersion::JPN39: {
|
||||
INSTALL_HOOK_DYNAMIC (QrInit, (LPVOID)(amHandle + 0x1EDC0));
|
||||
INSTALL_HOOK_DYNAMIC (QrClose, (LPVOID)(amHandle + 0x1EF60));
|
||||
INSTALL_HOOK_DYNAMIC (QrRead, (LPVOID)(amHandle + 0x1EFB0));
|
||||
INSTALL_HOOK_DYNAMIC (CallQrUnknown, (LPVOID)(amHandle + 0x11A70));
|
||||
INSTALL_HOOK_DYNAMIC (Send1, (LPVOID)(amHandle + 0x1F5B0));
|
||||
INSTALL_HOOK_DYNAMIC (Send2, (LPVOID)(amHandle + 0x1F5F0));
|
||||
INSTALL_HOOK_DYNAMIC (Send3, (LPVOID)(amHandle + 0x1F660));
|
||||
INSTALL_HOOK_DYNAMIC (Send4, (LPVOID)(amHandle + 0x1F690));
|
||||
INSTALL_HOOK_DYNAMIC (CopyData, (LPVOID)(amHandle + 0x1F630));
|
||||
INSTALL_FAST_HOOK_DYNAMIC (QrInit, (LPVOID)(amHandle + 0x1EDC0));
|
||||
INSTALL_FAST_HOOK_DYNAMIC (QrClose, (LPVOID)(amHandle + 0x1EF60));
|
||||
INSTALL_FAST_HOOK_DYNAMIC (QrRead, (LPVOID)(amHandle + 0x1EFB0));
|
||||
INSTALL_FAST_HOOK_DYNAMIC (CallQrUnknown, (LPVOID)(amHandle + 0x11A70));
|
||||
INSTALL_FAST_HOOK_DYNAMIC (Send1, (LPVOID)(amHandle + 0x1F5B0));
|
||||
INSTALL_FAST_HOOK_DYNAMIC (Send2, (LPVOID)(amHandle + 0x1F5F0));
|
||||
INSTALL_FAST_HOOK_DYNAMIC (Send3, (LPVOID)(amHandle + 0x1F660));
|
||||
INSTALL_FAST_HOOK_DYNAMIC (Send4, (LPVOID)(amHandle + 0x1F690));
|
||||
INSTALL_FAST_HOOK_DYNAMIC (CopyData, (LPVOID)(amHandle + 0x1F630));
|
||||
break;
|
||||
}
|
||||
case GameVersion::CHN00: {
|
||||
INSTALL_HOOK_DYNAMIC (QrInit, (LPVOID)(amHandle + 0x161B0));
|
||||
INSTALL_HOOK_DYNAMIC (QrClose, (LPVOID)(amHandle + 0x16350));
|
||||
INSTALL_HOOK_DYNAMIC (QrRead, (LPVOID)(amHandle + 0x163A0));
|
||||
INSTALL_HOOK_DYNAMIC (CallQrUnknown, (LPVOID)(amHandle + 0x8F60));
|
||||
INSTALL_HOOK_DYNAMIC (Send1, (LPVOID)(amHandle + 0x16940));
|
||||
INSTALL_HOOK_DYNAMIC (Send2, (LPVOID)(amHandle + 0x16990));
|
||||
INSTALL_HOOK_DYNAMIC (Send3, (LPVOID)(amHandle + 0x16A00));
|
||||
INSTALL_HOOK_DYNAMIC (Send4, (LPVOID)(amHandle + 0x16A30));
|
||||
INSTALL_HOOK_DYNAMIC (CopyData, (LPVOID)(amHandle + 0x169D0));
|
||||
INSTALL_FAST_HOOK_DYNAMIC (QrInit, (LPVOID)(amHandle + 0x161B0));
|
||||
INSTALL_FAST_HOOK_DYNAMIC (QrClose, (LPVOID)(amHandle + 0x16350));
|
||||
INSTALL_FAST_HOOK_DYNAMIC (QrRead, (LPVOID)(amHandle + 0x163A0));
|
||||
INSTALL_FAST_HOOK_DYNAMIC (CallQrUnknown, (LPVOID)(amHandle + 0x8F60));
|
||||
INSTALL_FAST_HOOK_DYNAMIC (Send1, (LPVOID)(amHandle + 0x16940));
|
||||
INSTALL_FAST_HOOK_DYNAMIC (Send2, (LPVOID)(amHandle + 0x16990));
|
||||
INSTALL_FAST_HOOK_DYNAMIC (Send3, (LPVOID)(amHandle + 0x16A00));
|
||||
INSTALL_FAST_HOOK_DYNAMIC (Send4, (LPVOID)(amHandle + 0x16A30));
|
||||
INSTALL_FAST_HOOK_DYNAMIC (CopyData, (LPVOID)(amHandle + 0x169D0));
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
|
||||
+80
-20
@@ -3,6 +3,7 @@
|
||||
#include "patches.h"
|
||||
#include <exception>
|
||||
#include <format>
|
||||
#include <queue>
|
||||
|
||||
extern GameVersion gameVersion;
|
||||
|
||||
@@ -10,6 +11,31 @@ bool chsPatch = false;
|
||||
#define MIN(a, b) ((a)<(b)?(a):(b))
|
||||
|
||||
namespace patches::TestMode {
|
||||
bool hookInstallFinished = false;
|
||||
std::vector<std::function<void ()>> hooks = {};
|
||||
std::thread *hookInstall;
|
||||
std::mutex hooksMutex;
|
||||
std::condition_variable hooksCV;
|
||||
|
||||
// void
|
||||
// AddHookInLoop (std::function<void ()> installMethod) {
|
||||
// // hooks.push (installMethod);
|
||||
// hooksCV.notify_all ();
|
||||
// }
|
||||
|
||||
// void
|
||||
// HookInstallLoop () {
|
||||
// std::unique_lock<std::mutex> hooksLock(hooksMutex);
|
||||
// while (!hookInstallFinished) {
|
||||
// while (!hooks.empty ()) {
|
||||
// auto installMethod = hooks.front ();
|
||||
// hooks.pop ();
|
||||
// if (installMethod) installMethod ();
|
||||
// }
|
||||
// if (!hookInstallFinished) hooksCV.wait (hooksLock);
|
||||
// }
|
||||
// }
|
||||
|
||||
std::wstring
|
||||
mergeCondition (std::wstring original, std::wstring addition, std::wstring value) {
|
||||
size_t pos = original.find (L"/");
|
||||
@@ -30,7 +56,18 @@ addConditionValue (pugi::xml_node *node, std::wstring key, std::wstring addition
|
||||
attr.set_value (mergeCondition(attr.value (), addition, value).c_str ());
|
||||
} else node->append_attribute (key.c_str ()) = std::format(L"True/{}:{}", addition, value).c_str ();
|
||||
}
|
||||
|
||||
class RegisteredHook : public Applicable {
|
||||
public:
|
||||
std::function<void ()> registerInit;
|
||||
RegisteredHook (const std::function<void ()> &initMethod) {
|
||||
this->registerInit = initMethod;
|
||||
}
|
||||
pugi::xml_node *
|
||||
Apply (pugi::xml_node *doc, pugi::xml_node *node) override {
|
||||
// AddHookInLoop (this->registerInit);
|
||||
return node;
|
||||
}
|
||||
};
|
||||
class RegisteredItem : public Applicable {
|
||||
public:
|
||||
std::wstring selectItem;
|
||||
@@ -49,7 +86,7 @@ public:
|
||||
LogMessage (LogLevel::ERROR, L"Failed to parse item: {}\n", this->selectItem);
|
||||
itemDoc.load_string (L"<root><text-item label=\"@Color/Red;!!!ERROR APPLYING ITEM!!!@Color/Default;\"/></root>");
|
||||
}
|
||||
if (success) this->registerInit ();
|
||||
// if (success) AddHookInLoop (this->registerInit);
|
||||
std::wstring layoutName = L"layout";
|
||||
if (layoutName == node->name ()) {
|
||||
temp = node->append_copy (itemDoc.first_child ().first_child ());
|
||||
@@ -189,7 +226,7 @@ public:
|
||||
try {
|
||||
if (pugi::xml_node modifyNode = node->select_node (modifyQuery).node ()) {
|
||||
this->nodeModify (modifyNode);
|
||||
this->registerInit ();
|
||||
// AddHookInLoop (this->registerInit);
|
||||
}
|
||||
} catch ([[maybe_unused]] std::exception &e) { LogMessage (LogLevel::ERROR, L"Failed to find node by xpath: {}\n", this->query); }
|
||||
return nullptr;
|
||||
@@ -200,6 +237,7 @@ Menu *modManager = new RegisteredMenu (L"MOD MANAGER", L"ModManagerMenu");
|
||||
// std::vector<RegisteredItem *> registeredItems = {};
|
||||
std::vector<RegisteredSingleItem *> registeredSingleItems = {};
|
||||
std::vector<RegisteredModify *> registeredModifies = {};
|
||||
std::vector<RegisteredHook *> registeredHooks = {};
|
||||
std::wstring moddedInitial = L"";
|
||||
std::wstring modded = L"";
|
||||
|
||||
@@ -221,8 +259,10 @@ ReadXMLFileSwitcher (std::wstring &fileName) {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
HOOK_DYNAMIC (void, TestModeSetMenuHook, u64 testModeLibrary, const wchar_t *lFileName) {
|
||||
FAST_HOOK_DYNAMIC (void, TestModeSetMenuHook, u64 testModeLibrary, const wchar_t *lFileName) {
|
||||
auto start = std::chrono::high_resolution_clock::now();
|
||||
const auto originalFileName = std::wstring (lFileName);
|
||||
LogMessage (LogLevel::DEBUG, L"Begin Loading {}", originalFileName);
|
||||
std::wstring fileName = originalFileName;
|
||||
if (fileName.ends_with (L"DeviceInitialize.xml") || fileName.ends_with (L"DeviceInitialize_asia.xml")
|
||||
|| fileName.ends_with (L"DeviceInitialize_china.xml")) {
|
||||
@@ -280,6 +320,13 @@ HOOK_DYNAMIC (void, TestModeSetMenuHook, u64 testModeLibrary, const wchar_t *lFi
|
||||
LogMessage (LogLevel::DEBUG, "End Apply Modify Items");
|
||||
}
|
||||
|
||||
if (!registeredHooks.empty ()) {
|
||||
LogMessage (LogLevel::DEBUG, "Begin Apply Hooks");
|
||||
for (RegisteredHook *hook : registeredHooks) hook->Apply (&doc, &doc);
|
||||
LogMessage (LogLevel::DEBUG, "End Apply Hooks");
|
||||
}
|
||||
|
||||
// AddHookInLoop ([&](){ hookInstallFinished = true; });
|
||||
[[maybe_unused]] auto _ = doc.save_file (modFileName.c_str ());
|
||||
modded = modFileName;
|
||||
fileName = modFileName;
|
||||
@@ -288,8 +335,9 @@ HOOK_DYNAMIC (void, TestModeSetMenuHook, u64 testModeLibrary, const wchar_t *lFi
|
||||
} else fileName = modded;
|
||||
}
|
||||
|
||||
LogMessage (LogLevel::DEBUG, L"TestModeLibrary load: " + fileName);
|
||||
originalTestModeSetMenuHook (testModeLibrary, fileName.c_str ());
|
||||
std::chrono::duration<double> duration = std::chrono::high_resolution_clock::now() - start;
|
||||
LogMessage (LogLevel::DEBUG, L"TestModeLibrary load: {}, spend: {:.2f}ms", fileName, duration.count () * 1000);
|
||||
originalTestModeSetMenuHook.fastcall<void> (testModeLibrary, fileName.c_str ());
|
||||
}
|
||||
|
||||
// HOOK_DYNAMIC (void, TestModeGetValueHook, u64 *reader, const wchar_t *lItemName, int *value) {
|
||||
@@ -462,7 +510,8 @@ Init () {
|
||||
|
||||
CommonModify ();
|
||||
|
||||
INSTALL_HOOK_DYNAMIC (TestModeSetMenuHook, testModeSetMenu);
|
||||
INSTALL_FAST_HOOK_DYNAMIC (TestModeSetMenuHook, testModeSetMenu);
|
||||
for (auto method : hooks) method ();
|
||||
// INSTALL_HOOK_DYNAMIC (TestModeGetValueHook, testModeGetValue);
|
||||
// INSTALL_HOOK_DYNAMIC (TestModeSetValueHook, testModeSetValue);
|
||||
}
|
||||
@@ -508,25 +557,27 @@ CreateMenu (const std::wstring &menuName, const std::wstring &menuId) {
|
||||
|
||||
void
|
||||
RegisterItem (const std::wstring &item, const std::function<void ()> &initMethod, Menu *menu) {
|
||||
LogMessage (LogLevel::DEBUG, L"Register Item: {}", item);
|
||||
menu->RegisterItem (new RegisteredItem (item, initMethod));
|
||||
LogMessage (LogLevel::DEBUG, L"Register \nItem: {}", item);
|
||||
hooks.push_back (initMethod);
|
||||
menu->RegisterItem (new RegisteredItem (item, [](){}));
|
||||
}
|
||||
|
||||
void
|
||||
RegisterItem (const std::wstring &item, const std::function<void ()> &initMethod) {
|
||||
LogMessage (LogLevel::DEBUG, L"Register Item: {}", item);
|
||||
modManager->RegisterItem (new RegisteredItem (item, initMethod));
|
||||
LogMessage (LogLevel::DEBUG, L"Register \nItem: {}", item);
|
||||
hooks.push_back (initMethod);
|
||||
modManager->RegisterItem (new RegisteredItem (item, [](){}));
|
||||
}
|
||||
|
||||
void
|
||||
RegisterItem (const std::wstring &item, Menu *menu) {
|
||||
LogMessage (LogLevel::DEBUG, L"Register Item: {}", item);
|
||||
LogMessage (LogLevel::DEBUG, L"Register \nItem: {}", item);
|
||||
menu->RegisterItem (new RegisteredItem (item, [](){}));
|
||||
}
|
||||
|
||||
void
|
||||
RegisterItem (const std::wstring &item) {
|
||||
LogMessage (LogLevel::DEBUG, L"Register Item: {}", item);
|
||||
LogMessage (LogLevel::DEBUG, L"Register \nItem: {}", item);
|
||||
modManager->RegisterItem (new RegisteredItem (item, [](){}));
|
||||
}
|
||||
|
||||
@@ -544,34 +595,43 @@ RegisterItem (Applicable *item) {
|
||||
|
||||
void
|
||||
RegisterItemAfter (const std::wstring &query, const std::wstring &item, const std::function<void()> &initMethod) {
|
||||
LogMessage (LogLevel::DEBUG, L"Register Query: {} Item: {}", query, item);
|
||||
registeredSingleItems.push_back (new RegisteredSingleItem (query, new RegisteredItem (item, initMethod)));
|
||||
LogMessage (LogLevel::DEBUG, L"Register \nQuery: {} \nItem: {}", query, item);
|
||||
hooks.push_back (initMethod);
|
||||
registeredSingleItems.push_back (new RegisteredSingleItem (query, new RegisteredItem (item, [](){})));
|
||||
}
|
||||
|
||||
void
|
||||
RegisterItemAfter (const std::wstring &query, const std::wstring &item) {
|
||||
LogMessage (LogLevel::DEBUG, L"Register Query: {} Item: {}", query, item);
|
||||
LogMessage (LogLevel::DEBUG, L"Register \nQuery: {} \nItem: {}", query, item);
|
||||
registeredSingleItems.push_back (new RegisteredSingleItem (query, new RegisteredItem (item, [](){})));
|
||||
}
|
||||
|
||||
void
|
||||
RegisterItemAfter (const std::wstring &query, Applicable *item) {
|
||||
LogMessage (LogLevel::DEBUG, L"Register Query: {} Item: ptr", query);
|
||||
LogMessage (LogLevel::DEBUG, L"Register \nQuery: {} \nItem: ptr", query);
|
||||
registeredSingleItems.push_back (new RegisteredSingleItem (query, item));
|
||||
}
|
||||
|
||||
void
|
||||
RegisterModify (const std::wstring &query, const std::function<void (pugi::xml_node &)> &nodeModify, const std::function<void ()> &initMethod) {
|
||||
LogMessage (LogLevel::DEBUG, L"Register Modify: {}", query);
|
||||
registeredModifies.push_back (new RegisteredModify (query, nodeModify, initMethod));
|
||||
LogMessage (LogLevel::DEBUG, L"Register \nModify: {}", query);
|
||||
hooks.push_back (initMethod);
|
||||
registeredModifies.push_back (new RegisteredModify (query, nodeModify, [](){}));
|
||||
}
|
||||
|
||||
void
|
||||
RegisterModify (const std::wstring &query, const std::function<void (pugi::xml_node &)> &nodeModify) {
|
||||
LogMessage (LogLevel::DEBUG, L"Register Modify: {}", query);
|
||||
LogMessage (LogLevel::DEBUG, L"Register \nModify: {}", query);
|
||||
registeredModifies.push_back (new RegisteredModify (query, nodeModify, [](){}));
|
||||
}
|
||||
|
||||
void
|
||||
RegisterHook (const std::function<void()> &initMethod) {
|
||||
LogMessage (LogLevel::DEBUG, L"Register Hook");
|
||||
hooks.push_back (initMethod);
|
||||
// registeredHooks.push_back (new RegisteredHook (initMethod));
|
||||
}
|
||||
|
||||
void
|
||||
Append (const pugi::xml_node &node, const wchar_t *attr, const std::wstring &append) {
|
||||
pugi::xml_attribute attribute = node.attribute (attr);
|
||||
|
||||
+202
-156
@@ -5,18 +5,18 @@
|
||||
|
||||
namespace patches::JPN39 {
|
||||
int language = 0;
|
||||
HOOK_DYNAMIC (char, AMFWTerminate, i64) {
|
||||
FAST_HOOK_DYNAMIC (char, AMFWTerminate, i64) {
|
||||
LogMessage (LogLevel::HOOKS, "AMFWTerminate was called");
|
||||
return 0;
|
||||
}
|
||||
|
||||
HOOK_DYNAMIC (i64, curl_easy_setopt, i64 a1, i64 a2, i64 a3, i64 a4, i64 a5) {
|
||||
FAST_HOOK_DYNAMIC (i64, curl_easy_setopt, i64 a1, i64 a2, i64 a3, i64 a4, i64 a5) {
|
||||
LogMessage (LogLevel::HOOKS, "Garmc curl_easy_setopt was called");
|
||||
originalcurl_easy_setopt (a1, 64, 0, 0, 0);
|
||||
originalcurl_easy_setopt (a1, 81, 0, 0, 0);
|
||||
return originalcurl_easy_setopt (a1, a2, a3, a4, a5);
|
||||
originalcurl_easy_setopt.call<i64> (a1, 64, 0, 0, 0);
|
||||
originalcurl_easy_setopt.call<i64> (a1, 81, 0, 0, 0);
|
||||
return originalcurl_easy_setopt.call<i64> (a1, a2, a3, a4, a5);
|
||||
}
|
||||
HOOK_DYNAMIC (void, garmc_logger_log, i64 a1, int a2, void *a3, char a4) {
|
||||
FAST_HOOK_DYNAMIC (void, garmc_logger_log, i64 a1, int a2, void *a3, char a4) {
|
||||
// remove garmc log
|
||||
return;
|
||||
}
|
||||
@@ -24,7 +24,7 @@ HOOK_DYNAMIC (void, garmc_logger_log, i64 a1, int a2, void *a3, char a4) {
|
||||
FUNCTION_PTR (i64, GetPlayDataManagerRef, ASLR (0x140024AC0), i64);
|
||||
|
||||
i64 lua_State = 0;
|
||||
HOOK (i64, luaL_newstate, PROC_ADDRESS ("lua51.dll", "luaL_newstate")) { return lua_State = originalluaL_newstate (); }
|
||||
FAST_HOOK (i64, luaL_newstate, PROC_ADDRESS ("lua51.dll", "luaL_newstate")) { return lua_State = originalluaL_newstate.call<i64> (); }
|
||||
FUNCTION_PTR (void, lua_settop, PROC_ADDRESS ("lua51.dll", "lua_settop"), i64, i32);
|
||||
FUNCTION_PTR (void, lua_replace, PROC_ADDRESS ("lua51.dll", "lua_replace"), i64, i32);
|
||||
FUNCTION_PTR (void, lua_pushcclosure, PROC_ADDRESS ("lua51.dll", "lua_pushcclosure"), i64, i64, i32);
|
||||
@@ -50,12 +50,12 @@ lua_pushbool (const i64 a1, const bool val) {
|
||||
|
||||
u64 appAccessor = 0;
|
||||
u64 componentAccessor = 0;
|
||||
HOOK (i64, DeviceCheck, ASLR (0x140464FC0), i64 a1, i64 a2, i64 a3) {
|
||||
FAST_HOOK (i64, DeviceCheck, ASLR (0x140464FC0), i64 a1, i64 a2, i64 a3) {
|
||||
LogMessage (LogLevel::HOOKS, "DeviceCheck was called");
|
||||
TestMode::SetupAccessor (a3, RefTestModeMain);
|
||||
componentAccessor = a2;
|
||||
appAccessor = a3;
|
||||
return originalDeviceCheck (a1, a2, a3);
|
||||
return originalDeviceCheck.fastcall<i64> (a1, a2, a3);
|
||||
}
|
||||
|
||||
i64
|
||||
@@ -66,49 +66,49 @@ GetUserStatus () {
|
||||
return -1;
|
||||
}
|
||||
|
||||
HOOK (bool, IsSongRelease, ASLR (0x1403F4510), i64 a1, i64 a2, int a3) {
|
||||
FAST_HOOK (bool, IsSongRelease, ASLR (0x1403F4510), i64 a1, i64 a2, int a3) {
|
||||
if (TestMode::ReadTestModeValue (L"ModUnlockSongs") == 1) return true;
|
||||
return originalIsSongRelease (a1, a2, a3);
|
||||
return originalIsSongRelease.fastcall<bool> (a1, a2, a3);
|
||||
}
|
||||
HOOK (bool, IsSongReleasePlayer, ASLR (0x1403F45F0), i64 a1, u64 a2, i32 a3) {
|
||||
FAST_HOOK (bool, IsSongReleasePlayer, ASLR (0x1403F45F0), i64 a1, u64 a2, i32 a3) {
|
||||
if (TestMode::ReadTestModeValue (L"ModUnlockSongs") == 2) return true;
|
||||
return originalIsSongReleasePlayer (a1, a2, a3);
|
||||
return originalIsSongReleasePlayer.fastcall<bool> (a1, a2, a3);
|
||||
}
|
||||
MID_HOOK (DifficultyPanelCrown, ASLR (0x1403F2A25), SafetyHookContext &ctx) {
|
||||
if (TestMode::ReadTestModeValue (L"ModUnlockSongs") != 1) return;
|
||||
ctx.r15 |= 1;
|
||||
}
|
||||
HOOK (i64, AvailableMode_Collabo024, ASLR (0x1402DE710), i64 a1) {
|
||||
FAST_HOOK (i64, AvailableMode_Collabo024, ASLR (0x1402DE710), i64 a1) {
|
||||
LogMessage (LogLevel::HOOKS, "AvailableMode_Collabo024 was called");
|
||||
const int tournamentMode = TestMode::ReadTestModeValue (L"TournamentMode");
|
||||
if (tournamentMode == 1) return originalAvailableMode_Collabo024 (a1);
|
||||
if (tournamentMode == 1) return originalAvailableMode_Collabo024.fastcall<i64> (a1);
|
||||
const int status = TestMode::ReadTestModeValue (L"ModModeCollabo024");
|
||||
if (status == 1 && GetUserStatus () == 1) return lua_pushbool (a1, true);
|
||||
return originalAvailableMode_Collabo024 (a1);
|
||||
return originalAvailableMode_Collabo024.fastcall<i64> (a1);
|
||||
}
|
||||
HOOK (i64, AvailableMode_Collabo025, ASLR (0x1402DE6B0), i64 a1) {
|
||||
FAST_HOOK (i64, AvailableMode_Collabo025, ASLR (0x1402DE6B0), i64 a1) {
|
||||
LogMessage (LogLevel::HOOKS, "AvailableMode_Collabo025 was called");
|
||||
const int tournamentMode = TestMode::ReadTestModeValue (L"TournamentMode");
|
||||
if (tournamentMode == 1) return originalAvailableMode_Collabo025 (a1);
|
||||
if (tournamentMode == 1) return originalAvailableMode_Collabo025.fastcall<i64> (a1);
|
||||
const int status = TestMode::ReadTestModeValue (L"ModModeCollabo025");
|
||||
if (status == 1 && GetUserStatus () == 1) return lua_pushbool (a1, true);
|
||||
return originalAvailableMode_Collabo025 (a1);
|
||||
return originalAvailableMode_Collabo025.fastcall<i64> (a1);
|
||||
}
|
||||
HOOK (i64, AvailableMode_Collabo026, ASLR (0x1402DE670), i64 a1) {
|
||||
FAST_HOOK (i64, AvailableMode_Collabo026, ASLR (0x1402DE670), i64 a1) {
|
||||
LogMessage (LogLevel::HOOKS, "AvailableMode_Collabo026 was called");
|
||||
const int tournamentMode = TestMode::ReadTestModeValue (L"TournamentMode");
|
||||
if (tournamentMode == 1) return originalAvailableMode_Collabo026 (a1);
|
||||
if (tournamentMode == 1) return originalAvailableMode_Collabo026.fastcall<i64> (a1);
|
||||
const int status = TestMode::ReadTestModeValue (L"ModModeCollabo026");
|
||||
if (status == 1 && GetUserStatus () == 1) return lua_pushbool (a1, true);
|
||||
return originalAvailableMode_Collabo026 (a1);
|
||||
return originalAvailableMode_Collabo026.fastcall<i64> (a1);
|
||||
}
|
||||
HOOK (i64, AvailableMode_AprilFool001, ASLR (0x1402DE5B0), i64 a1) {
|
||||
FAST_HOOK (i64, AvailableMode_AprilFool001, ASLR (0x1402DE5B0), i64 a1) {
|
||||
LogMessage (LogLevel::HOOKS, "AvailableMode_AprilFool001 was called");
|
||||
const int tournamentMode = TestMode::ReadTestModeValue (L"TournamentMode");
|
||||
if (tournamentMode == 1) return originalAvailableMode_AprilFool001 (a1);
|
||||
if (tournamentMode == 1) return originalAvailableMode_AprilFool001.fastcall<i64> (a1);
|
||||
const int status = TestMode::ReadTestModeValue (L"ModModeAprilFool001");
|
||||
if (status == 1) return lua_pushbool (a1, true);
|
||||
return originalAvailableMode_AprilFool001 (a1);
|
||||
return originalAvailableMode_AprilFool001.fastcall<i64> (a1);
|
||||
}
|
||||
i64 __fastcall lua_freeze_timer (const i64 a1) {
|
||||
LogMessage (LogLevel::HOOKS, "lua_freeze_timer was called");
|
||||
@@ -183,40 +183,59 @@ SEND_RESULT_HOOK (SendResultData_Enso, ASLR (0x1401817B0));
|
||||
SEND_RESULT_HOOK (SendResultData_AI, ASLR (0x1401755E0));
|
||||
SEND_RESULT_HOOK (SendResultData_Collabo025_026, ASLR (0x140179A00));
|
||||
SEND_RESULT_HOOK (SendResultData_AprilFool, ASLR (0x140177800));
|
||||
|
||||
CHANGE_RESULT_SIZE_HOOK (ChangeResultDataSize_Enso, ASLR (0x140180074), rax);
|
||||
CHANGE_RESULT_SIZE_HOOK (ChangeResultDataSize_AI, ASLR (0x140173774), rax);
|
||||
CHANGE_RESULT_SIZE_HOOK (ChangeResultDataSize_Collabo025_026, ASLR (0x140178244), rax);
|
||||
CHANGE_RESULT_SIZE_HOOK (ChangeResultDataSize_AprilFool, ASLR (0x140176044), rax);
|
||||
|
||||
CHANGE_RESULT_INDEX_HOOK (ChangeResultDataIndex_Enso, ASLR (0x14018074B), rax, 0x34, 0x07);
|
||||
CHANGE_RESULT_INDEX_HOOK (ChangeResultDataIndex_AI, ASLR (0x140173EDD), r13, 0x24, 0x08);
|
||||
CHANGE_RESULT_INDEX_HOOK (ChangeResultDataIndex_Collabo025_026, ASLR (0x1401789AD), r13, 0x24, 0x08);
|
||||
CHANGE_RESULT_INDEX_HOOK (ChangeResultDataIndex_AprilFool, ASLR (0x140176716), rax, 0x34, 0x06);
|
||||
|
||||
HOOK (i64, GetLanguage, ASLR (0x140024AC0), i64 a1) {
|
||||
FAST_HOOK (i64, GetLanguage, ASLR (0x140024AC0), i64 a1) {
|
||||
LogMessage (LogLevel::HOOKS, "GetLanguage was called");
|
||||
const auto result = originalGetLanguage (a1);
|
||||
const auto result = originalGetLanguage.fastcall<i64> (a1);
|
||||
language = *reinterpret_cast<u32 *> (result);
|
||||
return result;
|
||||
}
|
||||
HOOK (i64, GetRegionLanguage, ASLR (0x1401CE9B0), i64 a1) {
|
||||
FAST_HOOK (i64, GetRegionLanguage, ASLR (0x1401CE9B0), i64 a1) {
|
||||
LogMessage (LogLevel::HOOKS, "GetRegionLanguage was called");
|
||||
if (patches::TestMode::ReadTestModeValue (L"ModFixLanguage") == 1) {
|
||||
lua_settop (a1, 0);
|
||||
lua_pushstring (a1, languageStr (language));
|
||||
return 1;
|
||||
} else return originalGetRegionLanguage (a1);
|
||||
} else return originalGetRegionLanguage.fastcall<i64> (a1);
|
||||
}
|
||||
std::thread::id *LoadMovieThreadId = nullptr;
|
||||
FUNCTION_PTR (void **, std_string_assign, ASLR (0x1400209E0), void **, const void *, size_t);
|
||||
HOOK (i64, GetCabinetLanguage, ASLR (0x14014DB80), u64 *a1, i64 a2) {
|
||||
FAST_HOOK (i64, GetCabinetLanguage, ASLR (0x14014DB80), u64 *a1, i64 a2) {
|
||||
LogMessage (LogLevel::HOOKS, "GetCabinetLanguage was called");
|
||||
i64 result = originalGetCabinetLanguage (a1, a2);
|
||||
i64 result = originalGetCabinetLanguage.fastcall<i64> (a1, a2);
|
||||
if (patches::TestMode::ReadTestModeValue (L"ModFixLanguage") == 1) {
|
||||
std_string_assign ((void **)result, (const void*)languageStr (language), (language == 0 || language == 3) ? 3 : 5);
|
||||
if (language == 2 && LoadMovieThreadId != nullptr && *LoadMovieThreadId == std::this_thread::get_id()) {
|
||||
LogMessage (LogLevel::DEBUG, "Loading DemoMovie cn_tw, redirect to cn_cn");
|
||||
std_string_assign ((void **)result, (const void*)languageStr (4), 5);
|
||||
} else {
|
||||
std_string_assign ((void **)result, (const void*)languageStr (language), (language == 0 || language == 3) ? 3 : 5);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
FAST_HOOK (i64, LoadDemoMovie, ASLR (0x1404313F0), i64 a1, i64 a2, i64 a3) {
|
||||
std::thread::id this_id = std::this_thread::get_id();
|
||||
LoadMovieThreadId = &this_id;
|
||||
i64 result = originalLoadDemoMovie.fastcall<i64> (a1, a2, a3);
|
||||
LoadMovieThreadId = nullptr;
|
||||
return result;
|
||||
}
|
||||
std::string onpCn = "textures/onpu_cn/onp_all.nutexb";
|
||||
MID_HOOK (ChangeOnpFile, ASLR (0x140134D16), SafetyHookContext &ctx) {
|
||||
if (language == 2 && patches::TestMode::ReadTestModeValue (L"ModFixLanguage") == 1) {
|
||||
LogMessage (LogLevel::DEBUG, "Load onp_all_cn");
|
||||
ctx.rdx = (uintptr_t) onpCn.c_str ();
|
||||
ctx.r8 = 0x1F;
|
||||
}
|
||||
}
|
||||
|
||||
MID_HOOK (ChangeLanguageType, ASLR (0x1400B2016), SafetyHookContext &ctx) {
|
||||
LogMessage (LogLevel::HOOKS, "ChangeLanguageType was called");
|
||||
@@ -240,6 +259,7 @@ get_bank_id (const std::string &bankName) {
|
||||
nus3bankMap[bankName] = nus3bankIdCounter;
|
||||
nus3bankIdCounter++;
|
||||
}
|
||||
LogMessage (LogLevel::DEBUG, "LoadBank {} id={}", bankName, nus3bankMap[bankName]);
|
||||
return nus3bankMap[bankName];
|
||||
}
|
||||
|
||||
@@ -305,7 +325,7 @@ FixToneName (const std::string &bankName, std::string toneName, int voiceLang) {
|
||||
}
|
||||
|
||||
size_t commonSize = 0;
|
||||
HOOK (i64, PlaySoundMain, ASLR (0x1404C6DC0), i64 a1) {
|
||||
FAST_HOOK (i64, PlaySoundMain, ASLR (0x1404C6DC0), i64 a1) {
|
||||
LogMessage (LogLevel::HOOKS, "PlaySoundMain was called");
|
||||
int lang = TestMode::ReadTestModeValue (L"VoiceLanguageItem");
|
||||
if (enableSwitchVoice && lang != 0) {
|
||||
@@ -315,10 +335,10 @@ HOOK (i64, PlaySoundMain, ASLR (0x1404C6DC0), i64 a1) {
|
||||
lua_replace (a1, -3);
|
||||
}
|
||||
}
|
||||
return originalPlaySoundMain (a1);
|
||||
return originalPlaySoundMain.fastcall<i64> (a1);
|
||||
}
|
||||
|
||||
HOOK (i64, PlaySoundMulti, ASLR (0x1404C6D60), i64 a1) {
|
||||
FAST_HOOK (i64, PlaySoundMulti, ASLR (0x1404C6D60), i64 a1) {
|
||||
LogMessage (LogLevel::HOOKS, "PlaySoundMulti was called");
|
||||
int lang = TestMode::ReadTestModeValue (L"VoiceLanguageItem");
|
||||
if (enableSwitchVoice && lang != 0) {
|
||||
@@ -328,7 +348,7 @@ HOOK (i64, PlaySoundMulti, ASLR (0x1404C6D60), i64 a1) {
|
||||
lua_replace (a1, -3);
|
||||
}
|
||||
}
|
||||
return originalPlaySoundMulti (a1);
|
||||
return originalPlaySoundMulti.fastcall<i64> (a1);
|
||||
}
|
||||
|
||||
FUNCTION_PTR (u64 *, append_chars_to_basic_string, ASLR (0x140028DA0), u64 *, const char *, size_t);
|
||||
@@ -341,50 +361,48 @@ FixToneNameEnso (u64 *Src, const std::string &bankName, int voiceLang) {
|
||||
return Src;
|
||||
}
|
||||
|
||||
HOOK (bool, PlaySoundEnso, ASLR (0x1404ED590), u64 *a1, u64 *a2, i64 a3) {
|
||||
FAST_HOOK (bool, PlaySoundEnso, ASLR (0x1404ED590), u64 *a1, u64 *a2, i64 a3) {
|
||||
LogMessage (LogLevel::HOOKS, "PlaySoundEnso was called");
|
||||
int lang = TestMode::ReadTestModeValue (L"VoiceLanguageItem");
|
||||
if (enableSwitchVoice && lang != 0) {
|
||||
const std::string bankName = a1[3] > 0x10 ? std::string (*reinterpret_cast<char **> (a1)) : std::string (reinterpret_cast<char *> (a1));
|
||||
if (bankName[0] == 'v') a2 = FixToneNameEnso (a2, bankName, lang);
|
||||
}
|
||||
return originalPlaySoundEnso (a1, a2, a3);
|
||||
return originalPlaySoundEnso.fastcall<bool> (a1, a2, a3);
|
||||
}
|
||||
|
||||
HOOK (bool, PlaySoundSpecial, ASLR (0x1404ED230), u64 *a1, u64 *a2) {
|
||||
FAST_HOOK (bool, PlaySoundSpecial, ASLR (0x1404ED230), u64 *a1, u64 *a2) {
|
||||
LogMessage (LogLevel::HOOKS, "PlaySoundSpecial was called");
|
||||
int lang = TestMode::ReadTestModeValue (L"VoiceLanguageItem");
|
||||
if (enableSwitchVoice && lang != 0) {
|
||||
const std::string bankName = a1[3] > 0x10 ? std::string (*reinterpret_cast<char **> (a1)) : std::string (reinterpret_cast<char *> (a1));
|
||||
if (bankName[0] == 'v') a2 = FixToneNameEnso (a2, bankName, lang);
|
||||
}
|
||||
return originalPlaySoundSpecial (a1, a2);
|
||||
return originalPlaySoundSpecial.fastcall<bool> (a1, a2);
|
||||
}
|
||||
|
||||
int loaded_fail_count = 0;
|
||||
HOOK (i64, LoadedBankAll, ASLR (0x1404C69F0), i64 a1) {
|
||||
FAST_HOOK (char, LoadedBankAll, ASLR (0x1404EC2F0), u64 a1) {
|
||||
LogMessage (LogLevel::HOOKS, "LoadedBankAll was called");
|
||||
originalLoadedBankAll (a1);
|
||||
const auto result = lua_toboolean (a1, -1);
|
||||
lua_settop (a1, 0);
|
||||
char result = originalLoadedBankAll.fastcall<char> (a1);
|
||||
if (result) {
|
||||
loaded_fail_count = 0;
|
||||
lua_pushboolean (a1, 1);
|
||||
} else if (loaded_fail_count > 100) {
|
||||
return 1;
|
||||
} else if (loaded_fail_count > 60) {
|
||||
LogMessage (LogLevel::WARN, "LoadBankAll Guardian!!!");
|
||||
loaded_fail_count = 0;
|
||||
lua_pushboolean (a1, 1);
|
||||
return 1;
|
||||
} else {
|
||||
loaded_fail_count += 1;
|
||||
lua_pushboolean (a1, 0);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
float soundRate = 1.0F;
|
||||
HOOK (i32, SetMasterVolumeSpeaker, ASLR (0x140160330), i32 a1) {
|
||||
FAST_HOOK (i32, SetMasterVolumeSpeaker, ASLR (0x140160330), i32 a1) {
|
||||
LogMessage (LogLevel::HOOKS, "SetMasterVolumeSpeaker was called");
|
||||
patches::Audio::SetVolumeRate (a1 <= 100 ? 1.0f : a1 / 100.0f);
|
||||
return originalSetMasterVolumeSpeaker (a1 > 100 ? 100 : a1);
|
||||
return originalSetMasterVolumeSpeaker.fastcall<i32> (a1 > 100 ? 100 : a1);
|
||||
}
|
||||
|
||||
// std::string *fontName = nullptr;
|
||||
@@ -407,45 +425,45 @@ MID_HOOK (AttractDemo, ASLR (0x14045A720), SafetyHookContext &ctx) {
|
||||
if (TestMode::ReadTestModeValue (L"AttractDemoItem") == 1) ctx.r14 = 0;
|
||||
}
|
||||
|
||||
HOOK (u64, EnsoGameManagerInitialize, ASLR (0x1400E2520), u64 a1, u64 a2, u64 a3) {
|
||||
FAST_HOOK (u64, EnsoGameManagerInitialize, ASLR (0x1400E2520), u64 a1, u64 a2, u64 a3) {
|
||||
LogMessage (LogLevel::DEBUG, "Begin EnsoGameManagerInitialize");
|
||||
u64 result = originalEnsoGameManagerInitialize (a1, a2, a3);
|
||||
u64 result = originalEnsoGameManagerInitialize.fastcall<u64> (a1, a2, a3);
|
||||
LogMessage (LogLevel::DEBUG, "End EnsoGameManagerInitialize result={}", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
HOOK (u64, EnsoGameManagerLoading, ASLR (0x1400E2750), u64 a1, u64 a2, u64 a3) {
|
||||
FAST_HOOK (u64, EnsoGameManagerLoading, ASLR (0x1400E2750), u64 a1, u64 a2, u64 a3) {
|
||||
LogMessage (LogLevel::DEBUG, "Begin EnsoGameManagerLoading");
|
||||
u64 result = originalEnsoGameManagerLoading (a1, a2, a3);
|
||||
u64 result = originalEnsoGameManagerLoading.fastcall<u64> (a1, a2, a3);
|
||||
LogMessage (LogLevel::DEBUG, "End EnsoGameManagerLoading result={}", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
HOOK (bool, EnsoGameManagerPreparing, ASLR (0x1400E2990), u64 a1, u64 a2, u64 a3) {
|
||||
FAST_HOOK (bool, EnsoGameManagerPreparing, ASLR (0x1400E2990), u64 a1, u64 a2, u64 a3) {
|
||||
LogMessage (LogLevel::DEBUG, "Begin EnsoGameManagerPreparing");
|
||||
bool result = originalEnsoGameManagerPreparing (a1, a2, a3); // crashes here
|
||||
bool result = originalEnsoGameManagerPreparing.fastcall<u64> (a1, a2, a3); // crashes here
|
||||
LogMessage (LogLevel::DEBUG, "End EnsoGameManagerPreparing result={}", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
HOOK (u64, EnsoGraphicManagerPreparing, ASLR (0x1400F0AB0), u64 a1, u64 a2, u64 a3) {
|
||||
FAST_HOOK (u64, EnsoGraphicManagerPreparing, ASLR (0x1400F0AB0), u64 a1, u64 a2, u64 a3) {
|
||||
LogMessage (LogLevel::DEBUG, "Begin EnsoGraphicManagerPreparing");
|
||||
u64 result = originalEnsoGraphicManagerPreparing (a1, a2, a3);
|
||||
u64 result = originalEnsoGraphicManagerPreparing.fastcall<u64> (a1, a2, a3);
|
||||
LogMessage (LogLevel::DEBUG, "End EnsoGraphicManagerPreparing result={}", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
HOOK (u64, EnsoGameManagerStart, ASLR (0x1400E2A10), u64 a1, u64 a2, u64 a3) {
|
||||
FAST_HOOK (u64, EnsoGameManagerStart, ASLR (0x1400E2A10), u64 a1, u64 a2, u64 a3) {
|
||||
LogMessage (LogLevel::DEBUG, "Begin EnsoGameManagerStart");
|
||||
u64 result = originalEnsoGameManagerStart (a1, a2, a3);
|
||||
u64 result = originalEnsoGameManagerStart.fastcall<u64> (a1, a2, a3);
|
||||
LogMessage (LogLevel::DEBUG, "End EnsoGameManagerStart result={}", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
HOOK (u64, EnsoGameManagerChechEnsoEnd, ASLR (0x1400E2A10), u64 a1, u64 a2, u64 a3) {
|
||||
FAST_HOOK (u64, EnsoGameManagerChechEnsoEnd, ASLR (0x1400E2A10), u64 a1, u64 a2, u64 a3) {
|
||||
LogMessage (LogLevel::DEBUG, "Begin EnsoGameManagerChechEnsoEnd");
|
||||
u64 result = originalEnsoGameManagerChechEnsoEnd (a1, a2, a3);
|
||||
u64 result = originalEnsoGameManagerChechEnsoEnd.fastcall<u64> (a1, a2, a3);
|
||||
LogMessage (LogLevel::DEBUG, "End EnsoGameManagerChechEnsoEnd result={}", result);
|
||||
return result;
|
||||
}
|
||||
@@ -457,41 +475,45 @@ HOOK (u64, EnsoGameManagerChechEnsoEnd, ASLR (0x1400E2A10), u64 a1, u64 a2, u64
|
||||
// return originalAcquireMostCompatibleDisplayMode (a1, a2, a3);
|
||||
// }
|
||||
|
||||
HOOK (char, SceneTestModeLoading, ASLR (0x1404793D0), u64 a1, u64 a2, u64 a3) {
|
||||
LogMessage (LogLevel::DEBUG, "Begin SceneTestModeLoading");
|
||||
char result = originalSceneTestModeLoading (a1, a2, a3);
|
||||
LogMessage (LogLevel::DEBUG, "End originalSceneTestModeLoading");
|
||||
FAST_HOOK (char, SceneTestModeLoading, ASLR (0x1404793D0), u64 a1, u64 a2, u64 a3) {
|
||||
// LogMessage (LogLevel::DEBUG, "Begin SceneTestModeLoading");
|
||||
char result = originalSceneTestModeLoading.fastcall<char> (a1, a2, a3);
|
||||
// LogMessage (LogLevel::DEBUG, "End originalSceneTestModeLoading result={}", (int)result);
|
||||
TestMode::SetTestModeValue (L"EnableSwitchVoice", (int)enableSwitchVoice);
|
||||
if (!enableSwitchVoice) TestMode::SetTestModeValue (L"VoiceLanguageItem", 0);
|
||||
LogMessage (LogLevel::DEBUG, "End SceneTestModeLoading");
|
||||
// if (!enableSwitchVoice) TestMode::SetTestModeValue (L"VoiceLanguageItem", 0);
|
||||
// LogMessage (LogLevel::DEBUG, "End SceneTestModeLoading");
|
||||
return result;
|
||||
}
|
||||
|
||||
constexpr i32 datatableBufferSize = 1024 * 1024 * 12;
|
||||
safetyhook::Allocation datatableBuffer1;
|
||||
safetyhook::Allocation datatableBuffer2;
|
||||
safetyhook::Allocation datatableBuffer3;
|
||||
const std::vector<uintptr_t> datatableBuffer1Addresses = {0x1400ABE40, 0x1400ABEB1, 0x1400ABEDB, 0x1400ABF4C};
|
||||
const std::vector<uintptr_t> datatableBuffer2Addresses = {0x1400ABE2C, 0x1400ABF5B, 0x1400ABF8E};
|
||||
const std::vector<uintptr_t> datatableBuffer3Addresses = {0x1400ABF7F, 0x1400ABF95, 0x1400ABFBF};
|
||||
const std::vector<uintptr_t> memsetSizeAddresses = {0x1400ABE26, 0x1400ABE3A, 0x1400ABF79};
|
||||
|
||||
void
|
||||
AllocateStaticBufferNear (void *target_address, const size_t size, safetyhook::Allocation *newBuffer) {
|
||||
const auto allocator = safetyhook::Allocator::global ();
|
||||
const std::vector desired_addresses = {static_cast<u8 *> (target_address)};
|
||||
auto allocation_result = allocator->allocate_near (desired_addresses, size);
|
||||
if (allocation_result.has_value ()) *newBuffer = std::move (*allocation_result);
|
||||
MID_HOOK (LogLoadTexture12, ASLR (0x14065BC8A), SafetyHookContext &ctx) {
|
||||
char* src = (char*)(ctx.rsp + 0x2B0);
|
||||
if (src != nullptr) {
|
||||
std::string srcStr = std::string (src);
|
||||
LogMessage (LogLevel::HOOKS, "LogLoadTexture12 src={}", srcStr);
|
||||
} else LogMessage (LogLevel::HOOKS, "LogLoadTexture12 src=nullptr");
|
||||
}
|
||||
|
||||
constexpr i32 datatableBufferSize = 1024 * 1024 * 12;
|
||||
uint8_t *datatableBuffer[3] = { nullptr };
|
||||
std::vector<SafetyHookMid> datatable_patch = {};
|
||||
#define DATATABLE_PATCH_REGISTER(location, reg, value, skip) { datatable_patch.push_back(safetyhook::create_mid(location, [](SafetyHookContext &ctx) {ctx.reg = (uintptr_t)(value); ctx.rip = location + skip;})); }
|
||||
void
|
||||
ReplaceLeaBufferAddress (const std::vector<uintptr_t> &bufferAddresses, void *newBufferAddress) {
|
||||
for (const auto bufferAddress : bufferAddresses) {
|
||||
const uintptr_t lea_instruction_dst = ASLR (bufferAddress) + 3;
|
||||
const uintptr_t lea_instruction_end = ASLR (bufferAddress) + 7;
|
||||
const intptr_t offset = reinterpret_cast<intptr_t> (newBufferAddress) - lea_instruction_end;
|
||||
WRITE_MEMORY (lea_instruction_dst, i32, static_cast<i32> (offset));
|
||||
}
|
||||
ReplaceDatatableBufferAddresses () {
|
||||
LogMessage (LogLevel::INFO, "Set Datatable Size to 12MB");
|
||||
for (int i = 0; i < 3; i ++) datatableBuffer[i] = (uint8_t *)malloc (datatableBufferSize);
|
||||
DATATABLE_PATCH_REGISTER (ASLR (0x1400ABE26), r8, datatableBufferSize, 6);
|
||||
DATATABLE_PATCH_REGISTER (ASLR (0x1400ABE3A), r8, datatableBufferSize, 6);
|
||||
DATATABLE_PATCH_REGISTER (ASLR (0x1400ABF79), r8, datatableBufferSize, 6);
|
||||
DATATABLE_PATCH_REGISTER (ASLR (0x1400ABE40), rcx, datatableBuffer[0], 7);
|
||||
DATATABLE_PATCH_REGISTER (ASLR (0x1400ABEB1), rdi, datatableBuffer[0], 7);
|
||||
DATATABLE_PATCH_REGISTER (ASLR (0x1400ABEDB), rdi, datatableBuffer[0], 7);
|
||||
DATATABLE_PATCH_REGISTER (ASLR (0x1400ABF4C), rdi, datatableBuffer[0], 7);
|
||||
DATATABLE_PATCH_REGISTER (ASLR (0x1400ABE2C), rcx, datatableBuffer[1], 7);
|
||||
DATATABLE_PATCH_REGISTER (ASLR (0x1400ABF5B), rcx, datatableBuffer[1], 7);
|
||||
DATATABLE_PATCH_REGISTER (ASLR (0x1400ABF8E), r8 , datatableBuffer[1], 7);
|
||||
DATATABLE_PATCH_REGISTER (ASLR (0x1400ABF7F), rcx, datatableBuffer[2], 7);
|
||||
DATATABLE_PATCH_REGISTER (ASLR (0x1400ABF95), rcx, datatableBuffer[2], 7);
|
||||
DATATABLE_PATCH_REGISTER (ASLR (0x1400ABFBF), rdx, datatableBuffer[2], 7);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -526,16 +548,10 @@ Init () {
|
||||
}
|
||||
|
||||
// Hook to get AppAccessor and ComponentAccessor
|
||||
INSTALL_HOOK (DeviceCheck);
|
||||
INSTALL_HOOK (luaL_newstate);
|
||||
INSTALL_HOOK (EnsoGameManagerInitialize);
|
||||
INSTALL_HOOK (EnsoGameManagerLoading);
|
||||
INSTALL_HOOK (EnsoGameManagerPreparing);
|
||||
INSTALL_HOOK (EnsoGraphicManagerPreparing);
|
||||
INSTALL_HOOK (EnsoGameManagerStart);
|
||||
INSTALL_HOOK (EnsoGameManagerChechEnsoEnd);
|
||||
INSTALL_FAST_HOOK (DeviceCheck);
|
||||
INSTALL_FAST_HOOK (luaL_newstate);
|
||||
INSTALL_MID_HOOK (LogLoadTexture12);
|
||||
// INSTALL_HOOK (AcquireMostCompatibleDisplayMode);
|
||||
INSTALL_HOOK (SceneTestModeLoading);
|
||||
|
||||
// Apply common config patch
|
||||
WRITE_MEMORY (ASLR (0x140494533), i32, xRes);
|
||||
@@ -574,21 +590,22 @@ Init () {
|
||||
WRITE_MEMORY (ASLR (0x140CC05B0), char, ".\\Garmc\\ErrorLogData\\GarmcOErrorLogData.dat");
|
||||
|
||||
// Remove datatable size limit
|
||||
{
|
||||
for (auto address : memsetSizeAddresses)
|
||||
WRITE_MEMORY (ASLR (address) + 2, i32, datatableBufferSize);
|
||||
ReplaceDatatableBufferAddresses ();
|
||||
// {
|
||||
// for (auto address : memsetSizeAddresses)
|
||||
// WRITE_MEMORY (ASLR (address) + 2, i32, datatableBufferSize);
|
||||
|
||||
auto bufferBase = MODULE_HANDLE - 0x03000000;
|
||||
AllocateStaticBufferNear (bufferBase, datatableBufferSize, &datatableBuffer1);
|
||||
bufferBase += datatableBufferSize;
|
||||
AllocateStaticBufferNear (bufferBase, datatableBufferSize, &datatableBuffer2);
|
||||
bufferBase += datatableBufferSize;
|
||||
AllocateStaticBufferNear (bufferBase, datatableBufferSize, &datatableBuffer3);
|
||||
// auto bufferBase = MODULE_HANDLE - 0x03000000;
|
||||
// AllocateStaticBufferNear (bufferBase, datatableBufferSize, &datatableBuffer1);
|
||||
// bufferBase += datatableBufferSize;
|
||||
// AllocateStaticBufferNear (bufferBase, datatableBufferSize, &datatableBuffer2);
|
||||
// bufferBase += datatableBufferSize;
|
||||
// AllocateStaticBufferNear (bufferBase, datatableBufferSize, &datatableBuffer3);
|
||||
|
||||
ReplaceLeaBufferAddress (datatableBuffer1Addresses, datatableBuffer1.data ());
|
||||
ReplaceLeaBufferAddress (datatableBuffer2Addresses, datatableBuffer2.data ());
|
||||
ReplaceLeaBufferAddress (datatableBuffer3Addresses, datatableBuffer3.data ());
|
||||
}
|
||||
// ReplaceLeaBufferAddress (datatableBuffer1Addresses, datatableBuffer1.data ());
|
||||
// ReplaceLeaBufferAddress (datatableBuffer2Addresses, datatableBuffer2.data ());
|
||||
// ReplaceLeaBufferAddress (datatableBuffer3Addresses, datatableBuffer3.data ());
|
||||
// }
|
||||
|
||||
// Language
|
||||
TestMode::Menu *langPatchesMenu = TestMode::CreateMenu (L"LANGUAGE PATCHES", L"LanguagePatchesMenu");
|
||||
@@ -597,9 +614,9 @@ Init () {
|
||||
L"<select-item label=\"FIX LANGUAGE\" param-offset-x=\"35\" replace-text=\"0:OFF, 1:ON\" "
|
||||
L"group=\"Setting\" id=\"ModFixLanguage\" max=\"1\" min=\"0\" default=\"1\"/>",
|
||||
[&]() {
|
||||
INSTALL_HOOK (GetLanguage);
|
||||
INSTALL_HOOK (GetRegionLanguage);
|
||||
INSTALL_HOOK (GetCabinetLanguage);
|
||||
INSTALL_FAST_HOOK (GetLanguage);
|
||||
INSTALL_FAST_HOOK (GetRegionLanguage);
|
||||
INSTALL_FAST_HOOK (GetCabinetLanguage);
|
||||
}, langPatchesMenu
|
||||
);
|
||||
TestMode::RegisterItem(
|
||||
@@ -609,13 +626,13 @@ Init () {
|
||||
);
|
||||
TestMode::RegisterItemAfter(
|
||||
L"/root/menu[@id='OthersMenu']/layout[@type='Center']/select-item[@id='LanguageItem']",
|
||||
L"<select-item label=\"VOICE\" param-offset-x=\"35\" invisible=\"True/EnableSwitchVoice:0\" disable=\"True/EnableSwitchVoice:0\" "
|
||||
L"<select-item label=\"VOICE\" param-offset-x=\"35\" disable=\"True/EnableSwitchVoice:0\" "
|
||||
L"replace-text=\"0:JPN, 1:CHN\" group=\"Setting\" id=\"VoiceLanguageItem\" max=\"1\" min=\"0\" default=\"0\"/>",
|
||||
[&](){
|
||||
INSTALL_HOOK (PlaySoundMain);
|
||||
INSTALL_HOOK (PlaySoundMulti);
|
||||
INSTALL_HOOK (PlaySoundEnso);
|
||||
INSTALL_HOOK (PlaySoundSpecial);
|
||||
INSTALL_FAST_HOOK (PlaySoundMain);
|
||||
INSTALL_FAST_HOOK (PlaySoundMulti);
|
||||
INSTALL_FAST_HOOK (PlaySoundEnso);
|
||||
INSTALL_FAST_HOOK (PlaySoundSpecial);
|
||||
}
|
||||
);
|
||||
TestMode::RegisterItem(langResourceIndicator, langPatchesMenu);
|
||||
@@ -626,8 +643,8 @@ Init () {
|
||||
L"<select-item label=\"UNLOCK SONGS\" param-offset-x=\"35\" replace-text=\"0:OFF, 1:ON, "
|
||||
L"2:FORCE\" group=\"Setting\" id=\"ModUnlockSongs\" max=\"2\" min=\"0\" default=\"1\"/>",
|
||||
[&]() {
|
||||
INSTALL_HOOK (IsSongRelease);
|
||||
INSTALL_HOOK (IsSongReleasePlayer);
|
||||
INSTALL_FAST_HOOK (IsSongRelease);
|
||||
INSTALL_FAST_HOOK (IsSongReleasePlayer);
|
||||
INSTALL_MID_HOOK (DifficultyPanelCrown);
|
||||
}
|
||||
);
|
||||
@@ -642,22 +659,22 @@ Init () {
|
||||
TestMode::RegisterItem (
|
||||
L"<select-item label=\"KIMETSU MODE\" param-offset-x=\"35\" replace-text=\"0:DEFAULT, 1:ENABLE, "
|
||||
L"2:CARD ONLY\" group=\"Setting\" id=\"ModModeCollabo024\" max=\"1\" min=\"0\" default=\"0\"/>",
|
||||
[&] { INSTALL_HOOK (AvailableMode_Collabo024); }//, modeUnlock
|
||||
[&] { INSTALL_FAST_HOOK (AvailableMode_Collabo024); }//, modeUnlock
|
||||
);
|
||||
TestMode::RegisterItem (
|
||||
L"<select-item label=\"ONE PIECE MODE\" param-offset-x=\"35\" replace-text=\"0:DEFAULT, "
|
||||
L"1:ENABLE, 2:CARD ONLY\" group=\"Setting\" id=\"ModModeCollabo025\" max=\"1\" min=\"0\" default=\"0\"/>",
|
||||
[&] { INSTALL_HOOK (AvailableMode_Collabo025); }//, modeUnlock
|
||||
[&] { INSTALL_FAST_HOOK (AvailableMode_Collabo025); }//, modeUnlock
|
||||
);
|
||||
TestMode::RegisterItem (
|
||||
L"<select-item label=\"AI SOSHINA MODE\" param-offset-x=\"35\" replace-text=\"0:DEFAULT, "
|
||||
L"1:ENABLE, 2:CARD ONLY\" group=\"Setting\" id=\"ModModeCollabo026\" max=\"1\" min=\"0\" default=\"0\"/>",
|
||||
[&] { INSTALL_HOOK (AvailableMode_Collabo026); }//, modeUnlock
|
||||
[&] { INSTALL_FAST_HOOK (AvailableMode_Collabo026); }//, modeUnlock
|
||||
);
|
||||
TestMode::RegisterItem (
|
||||
L"<select-item label=\"AOHARU MODE\" param-offset-x=\"35\" replace-text=\"0:DEFAULT, 1:ENABLE, "
|
||||
L"2:CARD ONLY\" group=\"Setting\" id=\"ModModeAprilFool001\" max=\"1\" min=\"0\" default=\"0\"/>",
|
||||
[&] { INSTALL_HOOK (AvailableMode_AprilFool001); }//, modeUnlock
|
||||
[&] { INSTALL_FAST_HOOK (AvailableMode_AprilFool001); }//, modeUnlock
|
||||
);
|
||||
// TestMode::RegisterItem (modeUnlock);
|
||||
// InstantResult
|
||||
@@ -665,15 +682,15 @@ Init () {
|
||||
L"<select-item label=\"INSTANT RESULT\" param-offset-x=\"35\" replace-text=\"0:OFF, 1:ON\" "
|
||||
L"group=\"Setting\" id=\"ModInstantResult\" max=\"1\" min=\"0\" default=\"0\"/>",
|
||||
[&] {
|
||||
INSTALL_HOOK (SceneResultInitialize_Enso);
|
||||
INSTALL_HOOK (SceneResultInitialize_AI);
|
||||
INSTALL_HOOK (SceneResultInitialize_Collabo025);
|
||||
INSTALL_HOOK (SceneResultInitialize_Collabo026);
|
||||
INSTALL_HOOK (SceneResultInitialize_AprilFool);
|
||||
INSTALL_HOOK (SendResultData_Enso);
|
||||
INSTALL_HOOK (SendResultData_AI);
|
||||
INSTALL_HOOK (SendResultData_Collabo025_026);
|
||||
INSTALL_HOOK (SendResultData_AprilFool);
|
||||
INSTALL_FAST_HOOK (SceneResultInitialize_Enso);
|
||||
INSTALL_FAST_HOOK (SceneResultInitialize_AI);
|
||||
INSTALL_FAST_HOOK (SceneResultInitialize_Collabo025);
|
||||
INSTALL_FAST_HOOK (SceneResultInitialize_Collabo026);
|
||||
INSTALL_FAST_HOOK (SceneResultInitialize_AprilFool);
|
||||
INSTALL_FAST_HOOK (SendResultData_Enso);
|
||||
INSTALL_FAST_HOOK (SendResultData_AI);
|
||||
INSTALL_FAST_HOOK (SendResultData_Collabo025_026);
|
||||
INSTALL_FAST_HOOK (SendResultData_AprilFool);
|
||||
INSTALL_MID_HOOK (ChangeResultDataSize_Enso);
|
||||
INSTALL_MID_HOOK (ChangeResultDataSize_AI);
|
||||
INSTALL_MID_HOOK (ChangeResultDataSize_Collabo025_026);
|
||||
@@ -692,7 +709,7 @@ Init () {
|
||||
node.attribute (L"max").set_value (L"300");
|
||||
node.attribute (L"delta").set_value (L"1");
|
||||
},
|
||||
[&] () { INSTALL_HOOK (SetMasterVolumeSpeaker); }
|
||||
[&] () { INSTALL_FAST_HOOK (SetMasterVolumeSpeaker); }
|
||||
);
|
||||
TestMode::RegisterItemAfter(
|
||||
L"/root/menu[@id='OthersMenu']/layout[@type='Center']/select-item[@id='AttractMovieItem']",
|
||||
@@ -700,7 +717,15 @@ Init () {
|
||||
L"replace-text=\"0:ON, 1:OFF\" group=\"Setting\" id=\"AttractDemoItem\" max=\"1\" min=\"0\" default=\"0\"/>",
|
||||
[&](){ INSTALL_MID_HOOK (AttractDemo); }
|
||||
);
|
||||
|
||||
TestMode::RegisterHook([&](){
|
||||
INSTALL_FAST_HOOK (EnsoGameManagerInitialize);
|
||||
INSTALL_FAST_HOOK (EnsoGameManagerLoading);
|
||||
INSTALL_FAST_HOOK (EnsoGameManagerPreparing);
|
||||
INSTALL_FAST_HOOK (EnsoGraphicManagerPreparing);
|
||||
INSTALL_FAST_HOOK (EnsoGameManagerStart);
|
||||
INSTALL_FAST_HOOK (EnsoGameManagerChechEnsoEnd);
|
||||
INSTALL_FAST_HOOK (SceneTestModeLoading);
|
||||
});
|
||||
// for (size_t i=0; i < 40; i++) TestMode::RegisterItem(std::format (L"<text-item label=\"TEST{}\"/>", i + 1));
|
||||
|
||||
// Instant Result
|
||||
@@ -712,6 +737,11 @@ Init () {
|
||||
|
||||
// Use chs font/wordlist instead of cht
|
||||
if (chsPatch) {
|
||||
WRITE_MEMORY (ASLR (0x140CD1E40), wchar_t, L"加載中\0");
|
||||
WRITE_MEMORY (ASLR (0x140CD1E28), wchar_t, L"加載中.\0");
|
||||
WRITE_MEMORY (ASLR (0x140CD1E68), wchar_t, L"加載中..\0");
|
||||
WRITE_MEMORY (ASLR (0x140CD1E50), wchar_t, L"加載中...\0");
|
||||
|
||||
bool fontExistAll = true;
|
||||
const char *fontToCheck[]{"cn_30.nutexb", "cn_30.xml", "cn_32.nutexb", "cn_32.xml", "cn_64.nutexb", "cn_64.xml"};
|
||||
for (int i = 0; i < 6; i++) {
|
||||
@@ -719,38 +749,54 @@ Init () {
|
||||
if (std::filesystem::exists (std::string ("..\\..\\Data\\x64\\font\\") + fontToCheck[i])) continue;
|
||||
fontExistAll = false;
|
||||
}
|
||||
|
||||
if (fontExistAll) {
|
||||
LogMessage (LogLevel::INFO, "Font all exist, using chs_patch font part!");
|
||||
WRITE_MEMORY (ASLR (0x140CD1AE0), char, "cn_64");
|
||||
WRITE_MEMORY (ASLR (0x140CD1AF0), char, "cn_32");
|
||||
WRITE_MEMORY (ASLR (0x140CD1AF8), char, "cn_30");
|
||||
WRITE_MEMORY (ASLR (0x140C946A0), char, "chineseSText");
|
||||
WRITE_MEMORY (ASLR (0x140C946B0), char, "chineseSFontType");
|
||||
WRITE_MEMORY (ASLR (0x140CD1E40), wchar_t, L"加載中\0");
|
||||
WRITE_MEMORY (ASLR (0x140CD1E28), wchar_t, L"加載中.\0");
|
||||
WRITE_MEMORY (ASLR (0x140CD1E68), wchar_t, L"加載中..\0");
|
||||
WRITE_MEMORY (ASLR (0x140CD1E50), wchar_t, L"加載中...\0");
|
||||
INSTALL_MID_HOOK (ChangeLanguageType);
|
||||
// INSTALL_HOOK (SetupFontInfo);
|
||||
// INSTALL_HOOK (ReadFontInfoInt);
|
||||
}
|
||||
|
||||
LayeredFs::RegisterBefore ([=] (const std::string &originalFileName, const std::string ¤tFileName) -> std::string {
|
||||
if (currentFileName.find ("\\lumen\\") == std::string::npos) return "";
|
||||
std::string fileName = currentFileName;
|
||||
fileName = replace (fileName, "\\lumen\\", "\\lumen_cn\\");
|
||||
if (std::filesystem::exists (fileName)) return fileName;
|
||||
return currentFileName;
|
||||
});
|
||||
bool demoMovieExistAll = true;
|
||||
const char *movieToCheck[]{"movie\\attractdemo_cn_cn.wmv", "sound\\attractdemo_cn_cn.nus3bank"};
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (useLayeredfs && std::filesystem::exists (std::string ("..\\..\\Data_mods\\x64\\") + movieToCheck[i])) continue;
|
||||
if (std::filesystem::exists (std::string ("..\\..\\Data\\x64\\") + movieToCheck[i])) continue;
|
||||
demoMovieExistAll = false;
|
||||
}
|
||||
if (demoMovieExistAll) {
|
||||
LogMessage (LogLevel::INFO, "Resource all exist, using chs_patch attractdemo part!");
|
||||
INSTALL_FAST_HOOK (LoadDemoMovie);
|
||||
}
|
||||
|
||||
bool onpCnExist = false;
|
||||
if (useLayeredfs && std::filesystem::exists (std::string ("..\\..\\Data_mods\\x64\\textures\\onpu_cn\\onp_all.nutexb"))) onpCnExist = true;
|
||||
if (std::filesystem::exists (std::string ("..\\..\\Data\\x64\\textures\\onpu_cn\\onp_all.nutexb"))) onpCnExist = true;
|
||||
if (onpCnExist) {
|
||||
LogMessage (LogLevel::INFO, "onpu_cn/onp_all exist, using chs_patch onp part!");
|
||||
INSTALL_MID_HOOK (ChangeOnpFile);
|
||||
}
|
||||
|
||||
// LayeredFs::RegisterBeforeA ([=] (const std::string &originalFileName, const std::string ¤tFileName) -> std::string {
|
||||
// if (currentFileName.find ("\\lumen\\") == std::string::npos) return "";
|
||||
// std::string fileName = currentFileName;
|
||||
// fileName = replace (fileName, "\\lumen\\", "\\lumen_cn\\");
|
||||
// if (std::filesystem::exists (fileName)) return fileName;
|
||||
// return "";
|
||||
// });
|
||||
}
|
||||
|
||||
// Fix normal song play after passing through silent song
|
||||
INSTALL_MID_HOOK (GenNus3bankId);
|
||||
INSTALL_HOOK (LoadedBankAll);
|
||||
INSTALL_FAST_HOOK (LoadedBankAll);
|
||||
|
||||
// Disable live check
|
||||
auto amHandle = reinterpret_cast<u64> (GetModuleHandle ("AMFrameWork.dll"));
|
||||
INSTALL_HOOK_DYNAMIC (AMFWTerminate, reinterpret_cast<void *> (amHandle + 0x42DE0));
|
||||
INSTALL_FAST_HOOK_DYNAMIC (AMFWTerminate, reinterpret_cast<void *> (amHandle + 0x42DE0));
|
||||
|
||||
// Move various files to current directory
|
||||
WRITE_MEMORY (amHandle + 0x15252, u8, 0xEB); // CreditLogPathA
|
||||
@@ -764,7 +810,7 @@ Init () {
|
||||
|
||||
// Redirect garmc requests
|
||||
auto garmcHandle = reinterpret_cast<u64> (GetModuleHandle ("garmc.dll"));
|
||||
INSTALL_HOOK_DYNAMIC (curl_easy_setopt, reinterpret_cast<void *> (garmcHandle + 0x1FBBB0));
|
||||
INSTALL_HOOK_DYNAMIC (garmc_logger_log, reinterpret_cast<void *> (garmcHandle + 0x13AB70));
|
||||
INSTALL_FAST_HOOK_DYNAMIC (curl_easy_setopt, reinterpret_cast<void *> (garmcHandle + 0x1FBBB0));
|
||||
INSTALL_FAST_HOOK_DYNAMIC (garmc_logger_log, reinterpret_cast<void *> (garmcHandle + 0x13AB70));
|
||||
}
|
||||
} // namespace patches::JPN39
|
||||
|
||||
+82
-64
@@ -2,18 +2,20 @@
|
||||
|
||||
#ifndef ASYNC_IO
|
||||
#include "polldef.h"
|
||||
#include <SDL3/SDL_main.h>
|
||||
extern bool jpLayout;
|
||||
|
||||
|
||||
bool currentKeyboardState[0xFF];
|
||||
bool lastKeyboardState[0xFF];
|
||||
|
||||
bool currentControllerButtonsState[SDL_CONTROLLER_BUTTON_MAX];
|
||||
bool lastControllerButtonsState[SDL_CONTROLLER_BUTTON_MAX];
|
||||
bool currentControllerButtonsState[SDL_GAMEPAD_BUTTON_COUNT];
|
||||
bool lastControllerButtonsState[SDL_GAMEPAD_BUTTON_COUNT];
|
||||
SDLAxisState currentControllerAxisState;
|
||||
SDLAxisState lastControllerAxisState;
|
||||
|
||||
SDL_Window *window;
|
||||
SDL_GameController *controllers[255];
|
||||
SDL_Gamepad *controllers[255];
|
||||
|
||||
void
|
||||
SetKeyboardButtons () {
|
||||
@@ -32,7 +34,7 @@ SetConfigValue (const toml_table_t *table, const char *key, Keybindings *key_bin
|
||||
|
||||
memset (key_bind, 0, sizeof (*key_bind));
|
||||
for (size_t i = 0; i < std::size (key_bind->buttons); i++)
|
||||
key_bind->buttons[i] = SDL_CONTROLLER_BUTTON_INVALID;
|
||||
key_bind->buttons[i] = SDL_GAMEPAD_BUTTON_INVALID;
|
||||
|
||||
for (int idx = 0;; idx++) {
|
||||
const auto [ok, u] = toml_string_at (array, idx);
|
||||
@@ -54,7 +56,7 @@ SetConfigValue (const toml_table_t *table, const char *key, Keybindings *key_bin
|
||||
case button: {
|
||||
*usePoll = true;
|
||||
for (int i = 0; i < std::size (key_bind->buttons); i++) {
|
||||
if (key_bind->buttons[i] == SDL_CONTROLLER_BUTTON_INVALID) {
|
||||
if (key_bind->buttons[i] == SDL_GAMEPAD_BUTTON_INVALID) {
|
||||
key_bind->buttons[i] = value.button;
|
||||
break;
|
||||
}
|
||||
@@ -95,36 +97,51 @@ InitializePoll (const HWND windowHandle) {
|
||||
SDL_SetHint (SDL_HINT_JOYSTICK_HIDAPI_PS5, "1");
|
||||
SDL_SetHint (SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, "1");
|
||||
|
||||
if (SDL_Init (SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER | SDL_INIT_EVENTS | SDL_INIT_VIDEO) != 0) {
|
||||
if (SDL_Init (SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER | SDL_INIT_EVENTS | SDL_INIT_VIDEO) == 0) {
|
||||
if (SDL_Init (SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMEPAD | SDL_INIT_EVENTS | SDL_INIT_VIDEO) != 0) {
|
||||
if (SDL_Init (SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD | SDL_INIT_EVENTS | SDL_INIT_VIDEO) == 0) {
|
||||
hasRumble = false;
|
||||
} else {
|
||||
LogMessage (LogLevel::ERROR,
|
||||
std::string ("SDL_Init (SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER | SDL_INIT_EVENTS | SDL_INIT_VIDEO): ")
|
||||
std::string ("SDL_Init (SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMEPAD | SDL_INIT_EVENTS | SDL_INIT_VIDEO): ")
|
||||
+ SDL_GetError ());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (const auto configPath = std::filesystem::current_path () / "gamecontrollerdb.txt";
|
||||
SDL_GameControllerAddMappingsFromFile (configPath.string ().c_str ()) == -1)
|
||||
SDL_AddGamepadMappingsFromFile (configPath.string ().c_str ()) == -1)
|
||||
LogMessage (LogLevel::ERROR, "Cannot read gamecontrollerdb.txt");
|
||||
SDL_GameControllerEventState (SDL_ENABLE);
|
||||
SDL_JoystickEventState (SDL_ENABLE);
|
||||
SDL_SetGamepadEventsEnabled (true);
|
||||
SDL_SetJoystickEventsEnabled (true);
|
||||
|
||||
for (int i = 0; i < SDL_NumJoysticks (); i++) {
|
||||
if (!SDL_IsGameController (i)) continue;
|
||||
int numJoysticks = 0;
|
||||
auto* joyStickIds = SDL_GetJoysticks(&numJoysticks);
|
||||
if (joyStickIds == nullptr) {
|
||||
LogMessage (LogLevel::ERROR, "Error getting joystick ids");
|
||||
exit(1);
|
||||
}
|
||||
for (auto id:joyStickIds) {
|
||||
if (!SDL_IsGamepad (id)) continue;
|
||||
SDL_Gamepad *controller = SDL_OpenGamepad (id);
|
||||
|
||||
SDL_GameController *controller = SDL_GameControllerOpen (i);
|
||||
if (!controller) {
|
||||
LogMessage (LogLevel::WARN, std::string ("Could not open gamecontroller ") + SDL_GameControllerNameForIndex (i) + ": " + SDL_GetError ());
|
||||
LogMessage (LogLevel::WARN, std::string ("Could not open gamecontroller ") + SDL_GetGamepadNameForID (id) + ": " + SDL_GetError ());
|
||||
continue;
|
||||
}
|
||||
controllers[i] = controller;
|
||||
}
|
||||
|
||||
window = SDL_CreateWindowFrom (windowHandle);
|
||||
if (window == nullptr) LogMessage (LogLevel::ERROR, std::string ("SDL_CreateWindowFrom (windowHandle): ") + SDL_GetError ());
|
||||
LogMessage (LogLevel::DEBUG, "Init Controller connected!");
|
||||
controllers[id] = controller;
|
||||
}
|
||||
SDL_free (joyStickIds);
|
||||
|
||||
SDL_PropertiesID props = SDL_CreateProperties();
|
||||
if(props == 0) {
|
||||
LogMessage (LogLevel::ERROR, "Unable to create SDL_Properties");
|
||||
exit(1);
|
||||
}
|
||||
SDL_SetPointerProperty (props, SDL_PROP_WINDOW_CREATE_WIN32_HWND_POINTER, windowHandle);
|
||||
window = SDL_CreateWindowWithProperties (props);
|
||||
if (window == NULL) LogMessage (LogLevel::ERROR, std::string ("SDL_CreateWindowFrom (windowHandle): ") + SDL_GetError ());
|
||||
atexit (DisposePoll);
|
||||
|
||||
return hasRumble;
|
||||
@@ -149,71 +166,71 @@ UpdatePoll (const HWND windowHandle) {
|
||||
ScreenToClient (windowHandle, ¤tMouseState.Position);
|
||||
|
||||
SDL_Event event;
|
||||
SDL_GameController *controller;
|
||||
SDL_Gamepad *controller;
|
||||
while (SDL_PollEvent (&event) != 0) {
|
||||
switch (event.type) {
|
||||
case SDL_CONTROLLERDEVICEADDED:
|
||||
if (!SDL_IsGameController (event.cdevice.which)) break;
|
||||
case SDL_EVENT_GAMEPAD_ADDED:
|
||||
if (!SDL_IsGamepad (event.cdevice.which)) break;
|
||||
|
||||
controller = SDL_GameControllerOpen (event.cdevice.which);
|
||||
controller = SDL_OpenGamepad (event.cdevice.which);
|
||||
if (!controller) {
|
||||
LogMessage (LogLevel::ERROR, std::string ("Could not open gamecontroller ") + SDL_GameControllerNameForIndex (event.cdevice.which)
|
||||
LogMessage (LogLevel::ERROR, std::string ("Could not open gamecontroller ") + SDL_GetGamepadNameForID (event.cdevice.which)
|
||||
+ ": " + SDL_GetError ());
|
||||
continue;
|
||||
}
|
||||
controllers[event.cdevice.which] = controller;
|
||||
break;
|
||||
case SDL_CONTROLLERDEVICEREMOVED:
|
||||
if (!SDL_IsGameController (event.cdevice.which)) break;
|
||||
SDL_GameControllerClose (controllers[event.cdevice.which]);
|
||||
case SDL_EVENT_GAMEPAD_REMOVED:
|
||||
if (!SDL_IsGamepad (event.cdevice.which)) break;
|
||||
SDL_CloseGamepad (controllers[event.cdevice.which]);
|
||||
break;
|
||||
case SDL_MOUSEWHEEL:
|
||||
case SDL_EVENT_MOUSE_WHEEL:
|
||||
if (event.wheel.y > 0) currentMouseState.ScrolledUp = true;
|
||||
else if (event.wheel.y < 0) currentMouseState.ScrolledDown = true;
|
||||
break;
|
||||
case SDL_CONTROLLERBUTTONUP:
|
||||
case SDL_CONTROLLERBUTTONDOWN: currentControllerButtonsState[event.cbutton.button] = event.cbutton.state; break;
|
||||
case SDL_CONTROLLERAXISMOTION:
|
||||
if (event.caxis.value > 1) {
|
||||
switch (event.caxis.axis) {
|
||||
case SDL_CONTROLLER_AXIS_LEFTX: currentControllerAxisState.LeftRight = static_cast<float> (event.caxis.value) / 32767; break;
|
||||
case SDL_CONTROLLER_AXIS_LEFTY: currentControllerAxisState.LeftDown = static_cast<float> (event.caxis.value) / 32767; break;
|
||||
case SDL_CONTROLLER_AXIS_RIGHTX: currentControllerAxisState.RightRight = static_cast<float> (event.caxis.value) / 32767; break;
|
||||
case SDL_CONTROLLER_AXIS_RIGHTY: currentControllerAxisState.RightDown = static_cast<float> (event.caxis.value) / 32767; break;
|
||||
case SDL_CONTROLLER_AXIS_TRIGGERLEFT: currentControllerAxisState.LTriggerDown = static_cast<float> (event.caxis.value) / 32767; break;
|
||||
case SDL_CONTROLLER_AXIS_TRIGGERRIGHT:
|
||||
currentControllerAxisState.RTriggerDown = static_cast<float> (event.caxis.value) / 32767;
|
||||
case SDL_EVENT_GAMEPAD_BUTTON_UP:
|
||||
case SDL_EVENT_GAMEPAD_BUTTON_DOWN: currentControllerButtonsState[event.gbutton.button] = event.gbutton.down; break;
|
||||
case SDL_EVENT_GAMEPAD_AXIS_MOTION:
|
||||
if (event.gaxis.value > 1) {
|
||||
switch (event.gaxis.axis) {
|
||||
case SDL_GAMEPAD_AXIS_LEFTX: currentControllerAxisState.LeftRight = static_cast<float> (event.gaxis.value) / 32767; break;
|
||||
case SDL_GAMEPAD_AXIS_LEFTY: currentControllerAxisState.LeftDown = static_cast<float> (event.gaxis.value) / 32767; break;
|
||||
case SDL_GAMEPAD_AXIS_RIGHTX: currentControllerAxisState.RightRight = static_cast<float> (event.gaxis.value) / 32767; break;
|
||||
case SDL_GAMEPAD_AXIS_RIGHTY: currentControllerAxisState.RightDown = static_cast<float> (event.gaxis.value) / 32767; break;
|
||||
case SDL_GAMEPAD_AXIS_LEFT_TRIGGER: currentControllerAxisState.LTriggerDown = static_cast<float> (event.gaxis.value) / 32767; break;
|
||||
case SDL_GAMEPAD_AXIS_RIGHT_TRIGGER:
|
||||
currentControllerAxisState.RTriggerDown = static_cast<float> (event.gaxis.value) / 32767;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
} else if (event.caxis.value < -1) {
|
||||
switch (event.caxis.axis) {
|
||||
case SDL_CONTROLLER_AXIS_LEFTX: currentControllerAxisState.LeftLeft = static_cast<float> (event.caxis.value) / -32768; break;
|
||||
case SDL_CONTROLLER_AXIS_LEFTY: currentControllerAxisState.LeftUp = static_cast<float> (event.caxis.value) / -32768; break;
|
||||
case SDL_CONTROLLER_AXIS_RIGHTX: currentControllerAxisState.RightLeft = static_cast<float> (event.caxis.value) / -32768; break;
|
||||
case SDL_CONTROLLER_AXIS_RIGHTY: currentControllerAxisState.RightUp = static_cast<float> (event.caxis.value) / -32768; break;
|
||||
} else if (event.gaxis.value < -1) {
|
||||
switch (event.gaxis.axis) {
|
||||
case SDL_GAMEPAD_AXIS_LEFTX: currentControllerAxisState.LeftLeft = static_cast<float> (event.gaxis.value) / -32768; break;
|
||||
case SDL_GAMEPAD_AXIS_LEFTY: currentControllerAxisState.LeftUp = static_cast<float> (event.gaxis.value) / -32768; break;
|
||||
case SDL_GAMEPAD_AXIS_RIGHTX: currentControllerAxisState.RightLeft = static_cast<float> (event.gaxis.value) / -32768; break;
|
||||
case SDL_GAMEPAD_AXIS_RIGHTY: currentControllerAxisState.RightUp = static_cast<float> (event.gaxis.value) / -32768; break;
|
||||
default: break;
|
||||
}
|
||||
} else {
|
||||
switch (event.caxis.axis) {
|
||||
case SDL_CONTROLLER_AXIS_LEFTX:
|
||||
switch (event.gaxis.axis) {
|
||||
case SDL_GAMEPAD_AXIS_LEFTX:
|
||||
currentControllerAxisState.LeftRight = 0;
|
||||
currentControllerAxisState.LeftLeft = 0;
|
||||
break;
|
||||
case SDL_CONTROLLER_AXIS_LEFTY:
|
||||
case SDL_GAMEPAD_AXIS_LEFTY:
|
||||
currentControllerAxisState.LeftDown = 0;
|
||||
currentControllerAxisState.LeftUp = 0;
|
||||
break;
|
||||
case SDL_CONTROLLER_AXIS_RIGHTX:
|
||||
case SDL_GAMEPAD_AXIS_RIGHTX:
|
||||
currentControllerAxisState.RightRight = 0;
|
||||
currentControllerAxisState.RightLeft = 0;
|
||||
break;
|
||||
case SDL_CONTROLLER_AXIS_RIGHTY:
|
||||
case SDL_GAMEPAD_AXIS_RIGHTY:
|
||||
currentControllerAxisState.RightDown = 0;
|
||||
currentControllerAxisState.RightUp = 0;
|
||||
break;
|
||||
case SDL_CONTROLLER_AXIS_TRIGGERLEFT: currentControllerAxisState.LTriggerDown = 0; break;
|
||||
case SDL_CONTROLLER_AXIS_TRIGGERRIGHT: currentControllerAxisState.RTriggerDown = 0; break;
|
||||
case SDL_GAMEPAD_AXIS_LEFT_TRIGGER: currentControllerAxisState.LTriggerDown = 0; break;
|
||||
case SDL_GAMEPAD_AXIS_RIGHT_TRIGGER: currentControllerAxisState.RTriggerDown = 0; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
@@ -272,7 +289,7 @@ GetInternalButtonState (const Keybindings &bindings) {
|
||||
if (KeyboardIsTapped (bindings.keycodes[i])) buttons.Tapped = true;
|
||||
}
|
||||
for (size_t i = 0; i < std::size (ConfigControllerButtons); i++) {
|
||||
if (bindings.buttons[i] == SDL_CONTROLLER_BUTTON_INVALID) continue;
|
||||
if (bindings.buttons[i] == SDL_GAMEPAD_BUTTON_INVALID) continue;
|
||||
if (ControllerButtonIsReleased (bindings.buttons[i])) buttons.Released = true;
|
||||
if (ControllerButtonIsDown (bindings.buttons[i])) buttons.Down = 1;
|
||||
if (ControllerButtonIsTapped (bindings.buttons[i])) buttons.Tapped = true;
|
||||
@@ -295,11 +312,12 @@ GetInternalButtonState (const Keybindings &bindings) {
|
||||
}
|
||||
|
||||
void
|
||||
SetRumble (const int left, const int right, const int length) {
|
||||
SetRumble (int left, int right, int length) {
|
||||
for (auto &controller : controllers) {
|
||||
if (!controller || !SDL_GameControllerHasRumble (controller)) continue;
|
||||
|
||||
SDL_GameControllerRumble (controller, left, right, length);
|
||||
const auto props = SDL_GetGamepadProperties(controller);
|
||||
const bool hasRumble = SDL_GetBooleanProperty (props, SDL_PROP_GAMEPAD_CAP_RUMBLE_BOOLEAN, false);
|
||||
if (!controller || !hasRumble) continue;
|
||||
SDL_RumbleGamepad (controller, left, right, length);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -389,32 +407,32 @@ GetMouseScrollIsTapped (const Scroll scroll) {
|
||||
}
|
||||
|
||||
bool
|
||||
ControllerButtonIsDown (const SDL_GameControllerButton button) {
|
||||
ControllerButtonIsDown (const SDL_GamepadButton button) {
|
||||
return currentControllerButtonsState[button];
|
||||
}
|
||||
|
||||
bool
|
||||
ControllerButtonIsUp (const SDL_GameControllerButton button) {
|
||||
ControllerButtonIsUp (const SDL_GamepadButton button) {
|
||||
return !ControllerButtonIsDown (button);
|
||||
}
|
||||
|
||||
bool
|
||||
ControllerButtonWasDown (const SDL_GameControllerButton button) {
|
||||
ControllerButtonWasDown (const SDL_GamepadButton button) {
|
||||
return lastControllerButtonsState[button];
|
||||
}
|
||||
|
||||
bool
|
||||
ControllerButtonWasUp (const SDL_GameControllerButton button) {
|
||||
ControllerButtonWasUp (const SDL_GamepadButton button) {
|
||||
return !ControllerButtonWasDown (button);
|
||||
}
|
||||
|
||||
bool
|
||||
ControllerButtonIsTapped (const SDL_GameControllerButton button) {
|
||||
ControllerButtonIsTapped (const SDL_GamepadButton button) {
|
||||
return ControllerButtonIsDown (button) && ControllerButtonWasUp (button);
|
||||
}
|
||||
|
||||
bool
|
||||
ControllerButtonIsReleased (const SDL_GameControllerButton button) {
|
||||
ControllerButtonIsReleased (const SDL_GamepadButton button) {
|
||||
return ControllerButtonIsUp (button) && ControllerButtonWasDown (button);
|
||||
}
|
||||
|
||||
|
||||
+14
-14
@@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#include <SDL.h>
|
||||
#include <SDL3/SDL.h>
|
||||
#include "helpers.h"
|
||||
#include "bnusio.h"
|
||||
|
||||
@@ -41,7 +41,7 @@ enum Scroll { MOUSE_SCROLL_INVALID, MOUSE_SCROLL_UP, MOUSE_SCROLL_DOWN };
|
||||
|
||||
struct Keybindings {
|
||||
u8 keycodes[255];
|
||||
SDL_GameControllerButton buttons[255];
|
||||
SDL_GamepadButton buttons[255];
|
||||
SDLAxis axis[255];
|
||||
Scroll scroll[2];
|
||||
};
|
||||
@@ -52,7 +52,7 @@ struct ConfigValue {
|
||||
EnumType type;
|
||||
union {
|
||||
u8 keycode;
|
||||
SDL_GameControllerButton button;
|
||||
SDL_GamepadButton button;
|
||||
SDLAxis axis;
|
||||
Scroll scroll;
|
||||
};
|
||||
@@ -72,16 +72,16 @@ void SetConfigValue (const toml_table_t *table, const char *key, Keybindings *ke
|
||||
InternalButtonState GetInternalButtonState (const Keybindings &bindings);
|
||||
void SetRumble (int left, int right, int length);
|
||||
|
||||
bool KeyboardIsDown (const uint8_t keycode);
|
||||
bool KeyboardIsTapped (const uint8_t keycode);
|
||||
bool KeyboardIsDown (uint8_t keycode);
|
||||
bool KeyboardIsTapped (uint8_t keycode);
|
||||
bool GetMouseScrollUp ();
|
||||
bool GetMouseScrollDown ();
|
||||
bool GetMouseScrollIsDown (const Scroll scroll);
|
||||
bool GetMouseScrollIsTapped (const Scroll scroll);
|
||||
bool ControllerButtonIsDown (const SDL_GameControllerButton button);
|
||||
bool ControllerButtonIsTapped (const SDL_GameControllerButton button);
|
||||
float ControllerAxisIsDown (const SDLAxis axis);
|
||||
bool ControllerAxisIsTapped (const SDLAxis axis);
|
||||
bool GetMouseScrollIsDown (Scroll scroll);
|
||||
bool GetMouseScrollIsTapped (Scroll scroll);
|
||||
bool ControllerButtonIsDown (SDL_GamepadButton button);
|
||||
bool ControllerButtonIsTapped (SDL_GamepadButton button);
|
||||
float ControllerAxisIsDown (SDLAxis axis);
|
||||
bool ControllerAxisIsTapped (SDLAxis axis);
|
||||
bool IsButtonTapped (const Keybindings &bindings);
|
||||
float IsButtonDown (const Keybindings &bindings);
|
||||
|
||||
@@ -99,9 +99,9 @@ void SetMousePosition (const POINT newPosition);
|
||||
bool GetWasMouseScrollUp ();
|
||||
bool GetWasMouseScrollDown ();
|
||||
bool GetMouseScrollIsReleased (const Scroll scroll);
|
||||
bool ControllerButtonWasDown (const SDL_GameControllerButton button);
|
||||
bool ControllerButtonWasUp (const SDL_GameControllerButton button);
|
||||
bool ControllerButtonIsReleased (const SDL_GameControllerButton button);
|
||||
bool ControllerButtonWasDown (const SDL_GamepadButton button);
|
||||
bool ControllerButtonWasUp (const SDL_GamepadButton button);
|
||||
bool ControllerButtonIsReleased (const SDL_GamepadButton button);
|
||||
bool ControllerAxisIsUp (const SDLAxis axis);
|
||||
float ControllerAxisWasDown (const SDLAxis axis);
|
||||
bool ControllerAxisWasUp (const SDLAxis axis);
|
||||
|
||||
+126
-110
@@ -2,31 +2,32 @@
|
||||
|
||||
#ifdef ASYNC_IO
|
||||
#include "polldef.h"
|
||||
#define SDL_MAIN_NOIMPL
|
||||
#include <SDL3/SDL_main.h>
|
||||
|
||||
extern bool jpLayout;
|
||||
extern int exited;
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a,b) ((a)<(b)?(a):(b))
|
||||
#endif
|
||||
|
||||
bool wndForeground = false;
|
||||
|
||||
bool currentKeyboardState[0xFF] = { false };
|
||||
int keyboardCount[0xFF] = { 0 };
|
||||
int keyboardDiff[0xFF] = { 0 };
|
||||
bool currentControllerButtonsState[SDL_CONTROLLER_BUTTON_MAX] = { false };
|
||||
int controllerCount[SDL_CONTROLLER_BUTTON_MAX] = { 0 };
|
||||
int controllerDiff[SDL_CONTROLLER_BUTTON_MAX] = { 0 };
|
||||
uint8_t keyboardCount[0xFF] = { 0 };
|
||||
uint8_t keyboardDiff[0xFF] = { 0 };
|
||||
bool keyboardClean = false;
|
||||
bool currentControllerButtonsState[SDL_GAMEPAD_BUTTON_COUNT] = { false };
|
||||
uint8_t controllerCount[SDL_GAMEPAD_BUTTON_COUNT] = { 0 };
|
||||
uint8_t controllerDiff[SDL_GAMEPAD_BUTTON_COUNT] = { 0 };
|
||||
char currentMouseWheelDirection = 0;
|
||||
int mouseWheelCount[2] = { 0 };
|
||||
int mouseWheelDiff[2] = { 0 };
|
||||
uint8_t mouseWheelCount[2] = { 0 };
|
||||
uint8_t mouseWheelDiff[2] = { 0 };
|
||||
|
||||
int maxCount = 1;
|
||||
|
||||
SDLAxisState currentControllerAxisState;
|
||||
|
||||
SDL_Window *window;
|
||||
SDL_GameController *controllers[255];
|
||||
SDL_Gamepad *controllers[255];
|
||||
bool flipped[255];
|
||||
|
||||
std::thread updatePollThread;
|
||||
|
||||
@@ -47,7 +48,7 @@ SetConfigValue (const toml_table_t *table, const char *key, Keybindings *key_bin
|
||||
|
||||
memset (key_bind, 0, sizeof (*key_bind));
|
||||
for (size_t i = 0; i < std::size (key_bind->buttons); i++)
|
||||
key_bind->buttons[i] = SDL_CONTROLLER_BUTTON_INVALID;
|
||||
key_bind->buttons[i] = SDL_GAMEPAD_BUTTON_INVALID;
|
||||
|
||||
for (int idx = 0;; idx++) {
|
||||
const auto [ok, u] = toml_string_at (array, idx);
|
||||
@@ -68,7 +69,7 @@ SetConfigValue (const toml_table_t *table, const char *key, Keybindings *key_bin
|
||||
case button: {
|
||||
*usePoll = true;
|
||||
for (int i = 0; i < std::size (key_bind->buttons); i++) {
|
||||
if (key_bind->buttons[i] == SDL_CONTROLLER_BUTTON_INVALID) {
|
||||
if (key_bind->buttons[i] == SDL_GAMEPAD_BUTTON_INVALID) {
|
||||
key_bind->buttons[i] = value.button;
|
||||
break;
|
||||
}
|
||||
@@ -107,9 +108,9 @@ LRESULT CALLBACK InputProc(int nCode, WPARAM wParam, LPARAM lParam) {
|
||||
if (nCode == HC_ACTION) {
|
||||
switch (wParam) {
|
||||
case WM_KEYDOWN: if (wndForeground) {
|
||||
KBDLLHOOKSTRUCT* pKeyboard = reinterpret_cast<KBDLLHOOKSTRUCT*>(lParam);
|
||||
auto* pKeyboard = reinterpret_cast<KBDLLHOOKSTRUCT*>(lParam);
|
||||
DWORD keyCode = pKeyboard->vkCode;
|
||||
if (!currentKeyboardState[keyCode]) keyboardCount[keyCode] = MIN (keyboardCount[keyCode] + 1, maxCount);
|
||||
if (!currentKeyboardState[keyCode]) keyboardCount[keyCode] = std::min (keyboardCount[keyCode] + 1, maxCount);
|
||||
currentKeyboardState[keyCode] = true;
|
||||
} break;
|
||||
// keyup will accepted even if you're not focus in this window
|
||||
@@ -122,13 +123,14 @@ LRESULT CALLBACK InputProc(int nCode, WPARAM wParam, LPARAM lParam) {
|
||||
MSLLHOOKSTRUCT *pMouseStruct = (MSLLHOOKSTRUCT*)lParam;
|
||||
int wheelDelta = GET_WHEEL_DELTA_WPARAM(pMouseStruct->mouseData);
|
||||
if (wheelDelta > 0) {
|
||||
mouseWheelCount[0] = MIN (mouseWheelCount[0] + wheelDelta, maxCount);
|
||||
mouseWheelCount[0] = std::min (mouseWheelCount[0] + wheelDelta, maxCount);
|
||||
currentMouseState.ScrolledUp = true;
|
||||
} else if (wheelDelta < 0) {
|
||||
mouseWheelCount[1] = MIN (mouseWheelCount[1] - wheelDelta, maxCount);
|
||||
mouseWheelCount[1] = std::min (mouseWheelCount[1] - wheelDelta, maxCount);
|
||||
currentMouseState.ScrolledDown = true;
|
||||
}
|
||||
} break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
return CallNextHookEx(keyboardHook, nCode, wParam, lParam);
|
||||
@@ -149,14 +151,12 @@ DisposeKeyboard () {
|
||||
if (mouseHook) UnhookWindowsHookEx(mouseHook);
|
||||
}
|
||||
|
||||
// void
|
||||
// UpdateLoop () {
|
||||
// LogMessage (LogLevel::DEBUG, "Enter Controller UpdateLoop");
|
||||
|
||||
// while (!exited) {
|
||||
|
||||
// }
|
||||
// }
|
||||
void
|
||||
CheckFlipped (uint32_t which, SDL_Gamepad *gamepad) {
|
||||
if (SDL_GetGamepadButtonLabel(gamepad, SDL_GAMEPAD_BUTTON_SOUTH) == SDL_GAMEPAD_BUTTON_LABEL_B) {
|
||||
flipped[which] = true;
|
||||
} else flipped[which] = false;
|
||||
}
|
||||
|
||||
bool
|
||||
InitializePoll (HWND windowHandle) {
|
||||
@@ -170,44 +170,53 @@ InitializePoll (HWND windowHandle) {
|
||||
SDL_SetHint (SDL_HINT_JOYSTICK_HIDAPI_PS5, "1");
|
||||
SDL_SetHint (SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, "1");
|
||||
|
||||
if (SDL_Init (SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER | SDL_INIT_EVENTS | SDL_INIT_VIDEO) != 0) {
|
||||
if (SDL_Init (SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER | SDL_INIT_EVENTS | SDL_INIT_VIDEO) == 0) {
|
||||
if (!SDL_Init (SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMEPAD | SDL_INIT_EVENTS | SDL_INIT_VIDEO)) {
|
||||
if (SDL_Init (SDL_INIT_JOYSTICK | SDL_INIT_GAMEPAD | SDL_INIT_EVENTS | SDL_INIT_VIDEO)) {
|
||||
hasRumble = false;
|
||||
} else {
|
||||
LogMessage (LogLevel::ERROR,
|
||||
std::string ("SDL_Init (SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER | SDL_INIT_EVENTS | SDL_INIT_VIDEO): ")
|
||||
+ SDL_GetError ());
|
||||
LogMessage (LogLevel::ERROR, std::string ("SDL_Init (SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMEPAD | SDL_INIT_EVENTS | SDL_INIT_VIDEO): ") + SDL_GetError ());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
auto configPath = std::filesystem::current_path () / "gamecontrollerdb.txt";
|
||||
if (SDL_GameControllerAddMappingsFromFile (configPath.string ().c_str ()) == -1)
|
||||
if (SDL_AddGamepadMappingsFromFile (configPath.string ().c_str ()) == -1)
|
||||
LogMessage (LogLevel::ERROR, "Cannot read gamecontrollerdb.txt");
|
||||
SDL_GameControllerEventState (SDL_ENABLE);
|
||||
SDL_JoystickEventState (SDL_ENABLE);
|
||||
SDL_SetGamepadEventsEnabled (true);
|
||||
SDL_SetJoystickEventsEnabled (true);
|
||||
|
||||
for (int i = 0; i < SDL_NumJoysticks (); i++) {
|
||||
if (!SDL_IsGameController (i)) continue;
|
||||
int numJoysticks = 0;
|
||||
auto* joyStickIds = SDL_GetJoysticks(&numJoysticks);
|
||||
if (joyStickIds == nullptr) {
|
||||
LogMessage (LogLevel::ERROR, "Error getting joystick ids");
|
||||
exit(1);
|
||||
}
|
||||
for (int i = 0; i < numJoysticks; i++) {
|
||||
auto id = joyStickIds[i];
|
||||
if (!SDL_IsGamepad (id)) continue;
|
||||
SDL_Gamepad *controller = SDL_OpenGamepad (id);
|
||||
|
||||
SDL_GameController *controller = SDL_GameControllerOpen (i);
|
||||
if (!controller) {
|
||||
LogMessage (LogLevel::WARN, std::string ("Could not open gamecontroller ") + SDL_GameControllerNameForIndex (i) + ": " + SDL_GetError ());
|
||||
LogMessage (LogLevel::WARN, std::string ("Could not open gamecontroller ") + SDL_GetGamepadNameForID (id) + ": " + SDL_GetError ());
|
||||
continue;
|
||||
}
|
||||
|
||||
LogMessage (LogLevel::DEBUG, "Init Controller connected!");
|
||||
controllers[i] = controller;
|
||||
CheckFlipped (id, controller);
|
||||
controllers[id] = controller;
|
||||
}
|
||||
SDL_free (joyStickIds);
|
||||
|
||||
window = SDL_CreateWindowFrom (windowHandle);
|
||||
SDL_PropertiesID props = SDL_CreateProperties();
|
||||
if(props == 0) {
|
||||
LogMessage (LogLevel::ERROR, "Unable to create SDL_Properties");
|
||||
exit(1);
|
||||
}
|
||||
SDL_SetPointerProperty (props, SDL_PROP_WINDOW_CREATE_WIN32_HWND_POINTER, windowHandle);
|
||||
window = SDL_CreateWindowWithProperties (props);
|
||||
if (window == NULL) LogMessage (LogLevel::ERROR, std::string ("SDL_CreateWindowFrom (windowHandle): ") + SDL_GetError ());
|
||||
|
||||
atexit (DisposePoll);
|
||||
|
||||
// updatePollThread = std::thread (UpdateLoop);
|
||||
// updatePollThread.detach ();
|
||||
|
||||
return hasRumble;
|
||||
}
|
||||
|
||||
@@ -221,78 +230,82 @@ CheckForegroundWindow (HWND processWindow) {
|
||||
return wndForeground;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
CorrectButton (uint32_t which, uint8_t button) {
|
||||
if (!flipped[which]) return button;
|
||||
switch (button) {
|
||||
case SDL_GAMEPAD_BUTTON_SOUTH: return SDL_GAMEPAD_BUTTON_EAST;
|
||||
case SDL_GAMEPAD_BUTTON_EAST: return SDL_GAMEPAD_BUTTON_SOUTH;
|
||||
case SDL_GAMEPAD_BUTTON_WEST: return SDL_GAMEPAD_BUTTON_NORTH;
|
||||
case SDL_GAMEPAD_BUTTON_NORTH: return SDL_GAMEPAD_BUTTON_WEST;
|
||||
default: return button;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
UpdatePoll (HWND windowHandle, bool useController) {
|
||||
if (!CheckForegroundWindow (windowHandle)) return;
|
||||
|
||||
currentMouseState.ScrolledUp = false;
|
||||
currentMouseState.ScrolledDown = false;
|
||||
for (int i=0; i<255; i++) keyboardCount[i] -= (bool)keyboardDiff[i];
|
||||
for (int i=0; i<SDL_CONTROLLER_BUTTON_MAX; i++) controllerCount[i] -= (bool)controllerDiff[i];
|
||||
for (int i=0; i<2; i++) if (mouseWheelCount[i] > 0) mouseWheelCount[i] -= (bool)mouseWheelDiff[i];
|
||||
std::fill_n (keyboardDiff, 0xFF, 0);
|
||||
std::fill_n (controllerDiff, SDL_CONTROLLER_BUTTON_MAX, 0);
|
||||
std::fill_n (mouseWheelDiff, 2, 0);
|
||||
if (keyboardClean) {
|
||||
keyboardClean = false;
|
||||
for (int i=0; i<0xFF; i++) keyboardCount[i] -= (bool)keyboardDiff[i];
|
||||
memset (keyboardDiff, 0, 0XFF);
|
||||
}
|
||||
if (mouseWheelCount[0] > 0) mouseWheelCount[0] -= (bool)mouseWheelDiff[0];
|
||||
if (mouseWheelCount[1] > 0) mouseWheelCount[1] -= (bool)mouseWheelDiff[1];
|
||||
memset (mouseWheelDiff, 0, 2);
|
||||
|
||||
// GetCursorPos (¤tMouseState.Position);
|
||||
// ScreenToClient (windowHandle, ¤tMouseState.Position);
|
||||
if (useController) {
|
||||
for (int i=0; i<SDL_GAMEPAD_BUTTON_COUNT; i++) controllerCount[i] -= (bool)controllerDiff[i];
|
||||
memset (controllerDiff, 0, SDL_GAMEPAD_BUTTON_COUNT);
|
||||
SDL_Event event;
|
||||
SDL_GameController *controller;
|
||||
SDL_Gamepad *controller;
|
||||
while (SDL_PollEvent (&event) != 0) {
|
||||
// LogMessage (LogLevel::DEBUG, "Receive SDL Event! type={}", (u64)event.type);
|
||||
switch (event.type) {
|
||||
case SDL_CONTROLLERDEVICEADDED:
|
||||
if (!SDL_IsGameController (event.cdevice.which)) break;
|
||||
controller = SDL_GameControllerOpen (event.cdevice.which);
|
||||
case SDL_EVENT_GAMEPAD_ADDED:
|
||||
if (!SDL_IsGamepad (event.gdevice.which)) break;
|
||||
controller = SDL_OpenGamepad (event.gdevice.which);
|
||||
if (!controller) {
|
||||
LogMessage (LogLevel::ERROR, std::string ("Could not open gamecontroller ") + SDL_GameControllerNameForIndex (event.cdevice.which)
|
||||
+ ": " + SDL_GetError ());
|
||||
LogMessage (LogLevel::ERROR, "Could not open gamecontroller {}: {}", SDL_GetGamepadNameForID (event.gdevice.which), SDL_GetError ());
|
||||
continue;
|
||||
}
|
||||
LogMessage (LogLevel::DEBUG, "Controller connected!");
|
||||
controllers[event.cdevice.which] = controller;
|
||||
CheckFlipped (event.gdevice.which, controller);
|
||||
controllers[event.gdevice.which] = controller;
|
||||
break;
|
||||
case SDL_CONTROLLERDEVICEREMOVED:
|
||||
case SDL_EVENT_GAMEPAD_REMOVED:
|
||||
LogMessage (LogLevel::DEBUG, "Controller removed!");
|
||||
if (!SDL_IsGameController (event.cdevice.which)) break;
|
||||
SDL_GameControllerClose (controllers[event.cdevice.which]);
|
||||
if (!SDL_IsGamepad (event.gdevice.which)) break;
|
||||
SDL_CloseGamepad (controllers[event.gdevice.which]);
|
||||
break;
|
||||
// case SDL_MOUSEWHEEL:
|
||||
// if (wndForeground) {
|
||||
// // LogMessage (LogLevel::DEBUG, "Mouse Wheel moves {}", event.wheel.y);
|
||||
// if (event.wheel.y > 0) {
|
||||
// mouseWheelCount[0] = MIN (mouseWheelCount[0] + event.wheel.y, maxCount);
|
||||
// // mouseWheelCount[1] = 0;
|
||||
// currentMouseState.ScrolledUp = true;
|
||||
// } else if (event.wheel.y < 0) {
|
||||
// mouseWheelCount[1] = MIN (mouseWheelCount[1] - event.wheel.y, maxCount);
|
||||
// // mouseWheelCount[0] = 0;
|
||||
// currentMouseState.ScrolledDown = true;
|
||||
// }
|
||||
// }
|
||||
// break;
|
||||
case SDL_CONTROLLERBUTTONUP:
|
||||
// keyup will accepted even if you're not focus in this window
|
||||
currentControllerButtonsState[event.cbutton.button] = false; break;
|
||||
case SDL_CONTROLLERBUTTONDOWN:
|
||||
case SDL_EVENT_GAMEPAD_BUTTON_UP: {
|
||||
uint8_t button = CorrectButton (event.gbutton.which, event.gbutton.button);
|
||||
currentControllerButtonsState[button] = false;
|
||||
} break;
|
||||
case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
|
||||
if (wndForeground) {
|
||||
if (!currentControllerButtonsState[event.cbutton.button]) {
|
||||
controllerCount[event.cbutton.button] = MIN (controllerCount[event.cbutton.button] + 1, maxCount);
|
||||
uint8_t button = CorrectButton (event.gbutton.which, event.gbutton.button);
|
||||
LogMessage (LogLevel::DEBUG, "Controller {}: button {} pressed, remapped to {}", event.gbutton.which, event.gbutton.button, button);
|
||||
if (!currentControllerButtonsState[button]) {
|
||||
controllerCount[button] = std::min (controllerCount[button] + 1, maxCount);
|
||||
}
|
||||
currentControllerButtonsState[event.cbutton.button] = true;
|
||||
} else LogMessage (LogLevel::WARN, "Controller button pressed but window not focused!");
|
||||
currentControllerButtonsState[button] = true;
|
||||
} else LogMessage (LogLevel::DEBUG, "Controller button pressed but window not focused!");
|
||||
break;
|
||||
case SDL_CONTROLLERAXISMOTION:
|
||||
float sensorValue = event.caxis.value == 0 ? 0 : event.caxis.value / (event.caxis.value > 0 ? 32767.0f : -32768.0f);
|
||||
case SDL_EVENT_GAMEPAD_AXIS_MOTION:
|
||||
float sensorValue = event.gaxis.value == 0 ? 0 : event.gaxis.value / (event.gaxis.value > 0 ? 32767.0f : -32768.0f);
|
||||
if (wndForeground || sensorValue == 0) {
|
||||
switch (event.caxis.axis) {
|
||||
case SDL_CONTROLLER_AXIS_LEFTX: currentControllerAxisState.LeftRight = sensorValue; break;
|
||||
case SDL_CONTROLLER_AXIS_LEFTY: currentControllerAxisState.LeftDown = sensorValue; break;
|
||||
case SDL_CONTROLLER_AXIS_RIGHTX: currentControllerAxisState.RightRight = sensorValue; break;
|
||||
case SDL_CONTROLLER_AXIS_RIGHTY: currentControllerAxisState.RightDown = sensorValue; break;
|
||||
case SDL_CONTROLLER_AXIS_TRIGGERLEFT: currentControllerAxisState.LTriggerDown = sensorValue; break;
|
||||
case SDL_CONTROLLER_AXIS_TRIGGERRIGHT: currentControllerAxisState.RTriggerDown = sensorValue; break;
|
||||
switch (event.gaxis.axis) {
|
||||
case SDL_GAMEPAD_AXIS_LEFTX: currentControllerAxisState.LeftRight = sensorValue; break;
|
||||
case SDL_GAMEPAD_AXIS_LEFTY: currentControllerAxisState.LeftDown = sensorValue; break;
|
||||
case SDL_GAMEPAD_AXIS_RIGHTX: currentControllerAxisState.RightRight = sensorValue; break;
|
||||
case SDL_GAMEPAD_AXIS_RIGHTY: currentControllerAxisState.RightDown = sensorValue; break;
|
||||
case SDL_GAMEPAD_AXIS_LEFT_TRIGGER: currentControllerAxisState.LTriggerDown = sensorValue; break;
|
||||
case SDL_GAMEPAD_AXIS_RIGHT_TRIGGER: currentControllerAxisState.RTriggerDown = sensorValue; break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -342,8 +355,10 @@ StringToConfigEnum (const char *value) {
|
||||
void
|
||||
SetRumble (int left, int right, int length) {
|
||||
for (auto &controller : controllers) {
|
||||
if (!controller || !SDL_GameControllerHasRumble (controller)) continue;
|
||||
SDL_GameControllerRumble (controller, left, right, length);
|
||||
const auto props = SDL_GetGamepadProperties(controller);
|
||||
const bool hasRumble = SDL_GetBooleanProperty (props, SDL_PROP_GAMEPAD_CAP_RUMBLE_BOOLEAN, false);
|
||||
if (!controller || !hasRumble) continue;
|
||||
SDL_RumbleGamepad (controller, left, right, length);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -356,11 +371,12 @@ int maxKeyboardCount = 1;
|
||||
bool
|
||||
KeyboardIsTapped (const uint8_t keycode) {
|
||||
if (keyboardCount[keycode] > 0) {
|
||||
if (maxKeyboardCount < keyboardCount[keycode]) {
|
||||
maxKeyboardCount = keyboardCount[keycode];
|
||||
LogMessage (LogLevel::DEBUG, "MAX KEYBOARD COLLECTED {} {}", keycode, maxKeyboardCount);
|
||||
}
|
||||
// if (maxKeyboardCount < keyboardCount[keycode]) {
|
||||
// maxKeyboardCount = keyboardCount[keycode];
|
||||
// LogMessage (LogLevel::DEBUG, "MAX KEYBOARD COLLECTED {} {}", keycode, maxKeyboardCount);
|
||||
// }
|
||||
keyboardDiff[keycode] = 1;
|
||||
keyboardClean = true;
|
||||
return true;
|
||||
} return false;
|
||||
}
|
||||
@@ -386,28 +402,28 @@ bool
|
||||
GetMouseScrollIsTapped (const Scroll scroll) {
|
||||
if (scroll == MOUSE_SCROLL_INVALID) return false;
|
||||
if (mouseWheelCount[scroll - 1] > 0) {
|
||||
if (maxWheelCount < mouseWheelCount[scroll - 1]) {
|
||||
maxWheelCount = mouseWheelCount[scroll - 1];
|
||||
LogMessage (LogLevel::DEBUG, "MAX WHEEL COLLECTED {} {}", (int)scroll, maxWheelCount);
|
||||
}
|
||||
// if (maxWheelCount < mouseWheelCount[scroll - 1]) {
|
||||
// maxWheelCount = mouseWheelCount[scroll - 1];
|
||||
// LogMessage (LogLevel::DEBUG, "MAX WHEEL COLLECTED {} {}", (int)scroll, maxWheelCount);
|
||||
// }
|
||||
mouseWheelDiff[scroll - 1] = 1;
|
||||
return true;
|
||||
} return false;
|
||||
}
|
||||
|
||||
bool
|
||||
ControllerButtonIsDown (const SDL_GameControllerButton button) {
|
||||
ControllerButtonIsDown (const SDL_GamepadButton button) {
|
||||
return currentControllerButtonsState[button];
|
||||
}
|
||||
|
||||
int maxButtonCount = 1;
|
||||
bool
|
||||
ControllerButtonIsTapped (const SDL_GameControllerButton button) {
|
||||
ControllerButtonIsTapped (const SDL_GamepadButton button) {
|
||||
if (controllerCount[button] > 0) {
|
||||
if (maxButtonCount < controllerCount[button]) {
|
||||
maxButtonCount = controllerCount[button];
|
||||
LogMessage (LogLevel::DEBUG, "MAX BUTTON COLLECTED {} {}", (int)button, maxButtonCount);
|
||||
}
|
||||
// if (maxButtonCount < controllerCount[button]) {
|
||||
// maxButtonCount = controllerCount[button];
|
||||
// LogMessage (LogLevel::DEBUG, "MAX BUTTON COLLECTED {} {}", (int)button, maxButtonCount);
|
||||
// }
|
||||
controllerDiff[button] = 1;
|
||||
return true;
|
||||
} return false;
|
||||
@@ -443,7 +459,7 @@ IsButtonTapped (const Keybindings &bindings) {
|
||||
if (KeyboardIsTapped (bindings.keycodes[i])) return true;
|
||||
}
|
||||
for (size_t i = 0; i < std::size (ConfigControllerButtons); i++) {
|
||||
if (bindings.buttons[i] == SDL_CONTROLLER_BUTTON_INVALID) continue;
|
||||
if (bindings.buttons[i] == SDL_GAMEPAD_BUTTON_INVALID) continue;
|
||||
if (ControllerButtonIsTapped (bindings.buttons[i])) return true;
|
||||
}
|
||||
for (size_t i = 0; i < std::size (ConfigControllerAXIS); i++) {
|
||||
@@ -465,7 +481,7 @@ IsButtonDown (const Keybindings &bindings) {
|
||||
if (KeyboardIsDown (bindings.keycodes[i])) return 1.0f;
|
||||
}
|
||||
for (size_t i = 0; i < std::size (ConfigControllerButtons); i++) {
|
||||
if (bindings.buttons[i] == SDL_CONTROLLER_BUTTON_INVALID) continue;
|
||||
if (bindings.buttons[i] == SDL_GAMEPAD_BUTTON_INVALID) continue;
|
||||
if (ControllerButtonIsDown (bindings.buttons[i])) return 1.0f;
|
||||
}
|
||||
for (size_t i = 0; i < std::size (ConfigControllerAXIS); i++) {
|
||||
|
||||
+22
-22
@@ -254,29 +254,29 @@ KeyCodePair ConfigKeyboardButtons_JP[] = {
|
||||
|
||||
struct {
|
||||
const char *string;
|
||||
SDL_GameControllerButton button;
|
||||
SDL_GamepadButton button;
|
||||
} ConfigControllerButtons[] = {
|
||||
{"SDL_A", SDL_CONTROLLER_BUTTON_A},
|
||||
{"SDL_B", SDL_CONTROLLER_BUTTON_B},
|
||||
{"SDL_X", SDL_CONTROLLER_BUTTON_X},
|
||||
{"SDL_Y", SDL_CONTROLLER_BUTTON_Y},
|
||||
{"SDL_BACK", SDL_CONTROLLER_BUTTON_BACK},
|
||||
{"SDL_GUIDE", SDL_CONTROLLER_BUTTON_GUIDE},
|
||||
{"SDL_START", SDL_CONTROLLER_BUTTON_START},
|
||||
{"SDL_LSTICK_PRESS", SDL_CONTROLLER_BUTTON_LEFTSTICK},
|
||||
{"SDL_RSTICK_PRESS", SDL_CONTROLLER_BUTTON_RIGHTSTICK},
|
||||
{"SDL_LSHOULDER", SDL_CONTROLLER_BUTTON_LEFTSHOULDER},
|
||||
{"SDL_RSHOULDER", SDL_CONTROLLER_BUTTON_RIGHTSHOULDER},
|
||||
{"SDL_DPAD_UP", SDL_CONTROLLER_BUTTON_DPAD_UP},
|
||||
{"SDL_DPAD_DOWN", SDL_CONTROLLER_BUTTON_DPAD_DOWN},
|
||||
{"SDL_DPAD_LEFT", SDL_CONTROLLER_BUTTON_DPAD_LEFT},
|
||||
{"SDL_DPAD_RIGHT", SDL_CONTROLLER_BUTTON_DPAD_RIGHT},
|
||||
{"SDL_MISC", SDL_CONTROLLER_BUTTON_MISC1},
|
||||
{"SDL_PADDLE1", SDL_CONTROLLER_BUTTON_PADDLE1},
|
||||
{"SDL_PADDLE2", SDL_CONTROLLER_BUTTON_PADDLE2},
|
||||
{"SDL_PADDLE3", SDL_CONTROLLER_BUTTON_PADDLE3},
|
||||
{"SDL_PADDLE4", SDL_CONTROLLER_BUTTON_PADDLE4},
|
||||
{"SDL_TOUCHPAD", SDL_CONTROLLER_BUTTON_TOUCHPAD},
|
||||
{"SDL_A", SDL_GAMEPAD_BUTTON_SOUTH},
|
||||
{"SDL_B", SDL_GAMEPAD_BUTTON_EAST},
|
||||
{"SDL_X", SDL_GAMEPAD_BUTTON_WEST},
|
||||
{"SDL_Y", SDL_GAMEPAD_BUTTON_NORTH},
|
||||
{"SDL_BACK", SDL_GAMEPAD_BUTTON_BACK},
|
||||
{"SDL_GUIDE", SDL_GAMEPAD_BUTTON_GUIDE},
|
||||
{"SDL_START", SDL_GAMEPAD_BUTTON_START},
|
||||
{"SDL_LSTICK_PRESS", SDL_GAMEPAD_BUTTON_LEFT_STICK},
|
||||
{"SDL_RSTICK_PRESS", SDL_GAMEPAD_BUTTON_RIGHT_STICK},
|
||||
{"SDL_LSHOULDER", SDL_GAMEPAD_BUTTON_LEFT_SHOULDER},
|
||||
{"SDL_RSHOULDER", SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER},
|
||||
{"SDL_DPAD_UP", SDL_GAMEPAD_BUTTON_DPAD_UP},
|
||||
{"SDL_DPAD_DOWN", SDL_GAMEPAD_BUTTON_DPAD_DOWN},
|
||||
{"SDL_DPAD_LEFT", SDL_GAMEPAD_BUTTON_DPAD_LEFT},
|
||||
{"SDL_DPAD_RIGHT", SDL_GAMEPAD_BUTTON_DPAD_RIGHT},
|
||||
{"SDL_MISC", SDL_GAMEPAD_BUTTON_MISC1},
|
||||
{"SDL_PADDLE1", SDL_GAMEPAD_BUTTON_RIGHT_PADDLE1},
|
||||
{"SDL_PADDLE2", SDL_GAMEPAD_BUTTON_LEFT_PADDLE1},
|
||||
{"SDL_PADDLE3", SDL_GAMEPAD_BUTTON_RIGHT_PADDLE2},
|
||||
{"SDL_PADDLE4", SDL_GAMEPAD_BUTTON_LEFT_PADDLE2},
|
||||
{"SDL_TOUCHPAD", SDL_GAMEPAD_BUTTON_TOUCHPAD},
|
||||
};
|
||||
|
||||
struct {
|
||||
|
||||
Reference in New Issue
Block a user