Merge pull request #22 from ryumiyax/Refactor

[Experimental] More Optimized IO & Optimized boot speed & SDL3 & Stability fix
This commit is contained in:
RyuMiyaX
2024-12-21 05:57:17 +08:00
committed by GitHub
16 changed files with 916 additions and 631 deletions
+2 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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) {
+4 -6
View File
@@ -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
View File
@@ -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: {
+5 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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 &currentFileName) -> 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 &currentFileName) -> 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
View File
@@ -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, &currentMouseState.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
View File
@@ -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
View File
@@ -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 (&currentMouseState.Position);
// ScreenToClient (windowHandle, &currentMouseState.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
View File
@@ -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 {