diff --git a/dist/config.toml b/dist/config.toml index 7fd45f1..f6c2edd 100644 --- a/dist/config.toml +++ b/dist/config.toml @@ -1,5 +1,7 @@ server = "127.0.0.1" -res = { x = 1360, y = 768 } +res = { x = 1920, y = 1080 } unlock_songs = true shared_audio = true vsync = false +qr_card_string = "" +qr_data_string = "" \ No newline at end of file diff --git a/dist/keyconfig.toml b/dist/keyconfig.toml index bd3ff58..df29b1b 100644 --- a/dist/keyconfig.toml +++ b/dist/keyconfig.toml @@ -7,7 +7,8 @@ DEBUG_DOWN = ["DOWNARROW"] DEBUG_ENTER = ["ENTER"] COIN_ADD = ["ENTER", "SDL_START"] -CARD_INSERT = ["P"] +QR_CARD_READ = ["P"] +QR_DATA_READ = ["Q"] P1_LEFT_BLUE = ["D", "SDL_LTRIGGER"] P1_LEFT_RED = ["F", "SDL_LSTICK_PRESS"] @@ -30,4 +31,4 @@ P2_RIGHT_BLUE = [] # SDL_DPAD_UP SDL_DPAD_LEFT SDL_DPAD_DOWN SDL_DPAD_RIGHT # SDL_MISC SDL_PADDLE1 SDL_PADDLE2 SDL_PADDLE3 SDL_PADDLE4 SDL_TOUCHPAD # SDL_LSTICK_UP SDL_LSTICK_LEFT SDL_LSTICK_DOWN SDL_LSTICK_RIGHT SDL_LSTICK_PRESS -# SDL_RSTICK_UP SDL_RSTICK_LEFT SDL_RSTICK_DOWN SDL_RSTICK_RIGHT SDL_RSTICK_PRESS +# SDL_RSTICK_UP SDL_RSTICK_LEFT SDL_RSTICK_DOWN SDL_RSTICK_RIGHT SDL_RSTICK_PRESS \ No newline at end of file diff --git a/meson.build b/meson.build index bf2f779..c6fee5a 100644 --- a/meson.build +++ b/meson.build @@ -51,10 +51,12 @@ library( 'src/dllmain.cpp', 'src/helpers.cpp', 'src/poll.cpp', + 'src/keyconfig.cpp', 'src/bnusio.cpp', 'src/patches/jp_nov_2020.cpp', 'src/patches/cn_jun_2023.cpp', 'src/patches/amauth.cpp', + 'src/patches/qr.cpp', ], name_prefix: '' ) diff --git a/src/bnusio.cpp b/src/bnusio.cpp index 1c2e556..34b959b 100644 --- a/src/bnusio.cpp +++ b/src/bnusio.cpp @@ -1,9 +1,14 @@ #include "helpers.h" #include "poll.h" +#include "patches/patches.h" +#include +#include "keyconfig.h" +#include "constants.h" extern std::vector plugins; extern char accessCode[21]; extern char chipId[33]; +extern GameVersion version; namespace bnusio { #define RETURN_FALSE(returnType, functionName, ...) \ @@ -56,22 +61,21 @@ bnusio_GetFirmwareVersion () { return 126; } -Keybindings EXIT = {.keycodes = {VK_ESCAPE}}; -Keybindings TEST = {.keycodes = {VK_F1}}; -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 CARD_INSERT = {.keycodes = {'P'}}; -Keybindings P1_LEFT_BLUE = {.keycodes = {'D'}, .axis = {SDL_AXIS_LTRIGGER_DOWN}}; -Keybindings P1_LEFT_RED = {.keycodes = {'F'}, .buttons = {SDL_CONTROLLER_BUTTON_LEFTSTICK}}; -Keybindings P1_RIGHT_RED = {.keycodes = {'J'}, .buttons = {SDL_CONTROLLER_BUTTON_RIGHTSTICK}}; -Keybindings P1_RIGHT_BLUE = {.keycodes = {'K'}, .axis = {SDL_AXIS_RTRIGGER_DOWN}}; -Keybindings P2_LEFT_BLUE = {}; -Keybindings P2_LEFT_RED = {}; -Keybindings P2_RIGHT_RED = {}; -Keybindings P2_RIGHT_BLUE = {}; +extern Keybindings EXIT; +extern Keybindings TEST; +extern Keybindings SERVICE; +extern Keybindings DEBUG_UP; +extern Keybindings DEBUG_DOWN; +extern Keybindings DEBUG_ENTER; +extern Keybindings COIN_ADD; +extern Keybindings P1_LEFT_BLUE; +extern Keybindings P1_LEFT_RED; +extern Keybindings P1_RIGHT_RED; +extern Keybindings P1_RIGHT_BLUE; +extern Keybindings P2_LEFT_BLUE; +extern Keybindings P2_LEFT_RED; +extern Keybindings P2_RIGHT_RED; +extern Keybindings P2_RIGHT_BLUE; u16 drumMin = 10000; u16 drumMax = 20000; @@ -160,6 +164,8 @@ u16 __fastcall bnusio_GetCoin (i32 a1) { if (updateEvent) updateEvent (); } + if (version == GameVersion::CN_JUN_2023) patches::Qr::Update(); + return coin_count; } @@ -217,32 +223,8 @@ Init () { INSTALL_HOOK (bngrw_ReqSendUrl); INSTALL_HOOK (bngrw_ReqSetLedPower); INSTALL_HOOK (bngrw_reqCancel); - INSTALL_HOOK (bngrw_Init); + INSTALL_HOOK (bngrw_Init) - auto configPath = std::filesystem::current_path () / "keyconfig.toml"; - toml_table_t *config = openConfig (configPath); - if (config) { - SetConfigValue (config, "EXIT", &EXIT); - - SetConfigValue (config, "TEST", &TEST); - SetConfigValue (config, "SERVICE", &SERVICE); - SetConfigValue (config, "DEBUG_UP", &DEBUG_UP); - SetConfigValue (config, "DEBUG_DOWN", &DEBUG_DOWN); - SetConfigValue (config, "DEBUG_ENTER", &DEBUG_ENTER); - - SetConfigValue (config, "COIN_ADD", &COIN_ADD); - SetConfigValue (config, "CARD_INSERT", &CARD_INSERT); - - SetConfigValue (config, "P1_LEFT_BLUE", &P1_LEFT_BLUE); - SetConfigValue (config, "P1_LEFT_RED", &P1_LEFT_RED); - SetConfigValue (config, "P1_RIGHT_RED", &P1_RIGHT_RED); - SetConfigValue (config, "P1_RIGHT_BLUE", &P1_RIGHT_BLUE); - SetConfigValue (config, "P2_LEFT_BLUE", &P2_LEFT_BLUE); - SetConfigValue (config, "P2_LEFT_RED", &P2_LEFT_RED); - SetConfigValue (config, "P2_RIGHT_RED", &P2_RIGHT_RED); - SetConfigValue (config, "P2_RIGHT_BLUE", &P2_RIGHT_BLUE); - - toml_free (config); - } + KeyConfig::Init(); } } // namespace bnusio diff --git a/src/constants.h b/src/constants.h new file mode 100644 index 0000000..007f48d --- /dev/null +++ b/src/constants.h @@ -0,0 +1,8 @@ +#pragma once +#include + +enum class GameVersion : XXH64_hash_t { + UNKNOWN = 0, + JP_NOV_2020 = 0x67C0F3042746D488, + CN_JUN_2023 = 0xA7EE39F2CC2C57C8, +}; \ No newline at end of file diff --git a/src/dllmain.cpp b/src/dllmain.cpp index c9670b9..346fd21 100644 --- a/src/dllmain.cpp +++ b/src/dllmain.cpp @@ -2,13 +2,8 @@ #include "helpers.h" #include "patches/patches.h" #include "poll.h" -#include +#include "constants.h" -enum class GameVersion : XXH64_hash_t { - UNKNOWN = 0, - JP_NOV_2020 = 0x67C0F3042746D488, - CN_JUN_2023 = 0xA7EE39F2CC2C57C8, -}; GameVersion version = GameVersion::UNKNOWN; std::vector plugins; diff --git a/src/helpers.h b/src/helpers.h index 3bfa671..522855f 100644 --- a/src/helpers.h +++ b/src/helpers.h @@ -37,6 +37,12 @@ const HMODULE MODULE_HANDLE = GetModuleHandle (nullptr); void *where##functionName = (void *)(location); \ returnType implOf##functionName (__VA_ARGS__) +#define HOOK_DYNAMIC(returnType, callingConvention, functionName, ...) \ + typedef returnType callingConvention (*functionName) (__VA_ARGS__); \ + functionName original##functionName = NULL; \ + void *where##functionName = NULL; \ + returnType callingConvention implOf##functionName (__VA_ARGS__) + #define VTABLE_HOOK(returnType, className, functionName, ...) \ typedef returnType (*className##functionName) (className * This, __VA_ARGS__); \ className##functionName original##className##functionName = NULL; \ @@ -50,6 +56,12 @@ const HMODULE MODULE_HANDLE = GetModuleHandle (nullptr); MH_EnableHook ((void *)where##functionName); \ } +#define INSTALL_HOOK_DYNAMIC(functionName, location) \ + { \ + where##functionName = (void *)location; \ + INSTALL_HOOK (functionName); \ + } + #define INSTALL_VTABLE_HOOK(className, object, functionName, functionIndex) \ { \ where##className##functionName = (*(className##functionName ***)object)[functionIndex]; \ diff --git a/src/keyconfig.cpp b/src/keyconfig.cpp new file mode 100644 index 0000000..12d54ad --- /dev/null +++ b/src/keyconfig.cpp @@ -0,0 +1,54 @@ +#include "keyconfig.h" +#include "helpers.h" +#include "poll.h" + +Keybindings EXIT = {.keycodes = {VK_ESCAPE}}; +Keybindings TEST = {.keycodes = {VK_F1}}; +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 QR_CARD_READ = {.keycodes = {'P'}}; +Keybindings QR_DATA_READ = {.keycodes = {'Q'}}; +Keybindings P1_LEFT_BLUE = {.keycodes = {'D'}, .axis = {SDL_AXIS_LTRIGGER_DOWN}}; +Keybindings P1_LEFT_RED = {.keycodes = {'F'}, .buttons = {SDL_CONTROLLER_BUTTON_LEFTSTICK}}; +Keybindings P1_RIGHT_RED = {.keycodes = {'J'}, .buttons = {SDL_CONTROLLER_BUTTON_RIGHTSTICK}}; +Keybindings P1_RIGHT_BLUE = {.keycodes = {'K'}, .axis = {SDL_AXIS_RTRIGGER_DOWN}}; +Keybindings P2_LEFT_BLUE = {}; +Keybindings P2_LEFT_RED = {}; +Keybindings P2_RIGHT_RED = {}; +Keybindings P2_RIGHT_BLUE = {}; + +namespace KeyConfig { + +void +Init() { + auto configPath = std::filesystem::current_path () / "keyconfig.toml"; + toml_table_t *config = openConfig (configPath); + if (config) { + SetConfigValue (config, "EXIT", &EXIT); + + SetConfigValue (config, "TEST", &TEST); + SetConfigValue (config, "SERVICE", &SERVICE); + SetConfigValue (config, "DEBUG_UP", &DEBUG_UP); + SetConfigValue (config, "DEBUG_DOWN", &DEBUG_DOWN); + SetConfigValue (config, "DEBUG_ENTER", &DEBUG_ENTER); + + SetConfigValue (config, "COIN_ADD", &COIN_ADD); + SetConfigValue (config, "QR_CARD_READ", &QR_CARD_READ); + SetConfigValue (config, "QR_DATA_READ", &QR_DATA_READ); + + SetConfigValue (config, "P1_LEFT_BLUE", &P1_LEFT_BLUE); + SetConfigValue (config, "P1_LEFT_RED", &P1_LEFT_RED); + SetConfigValue (config, "P1_RIGHT_RED", &P1_RIGHT_RED); + SetConfigValue (config, "P1_RIGHT_BLUE", &P1_RIGHT_BLUE); + SetConfigValue (config, "P2_LEFT_BLUE", &P2_LEFT_BLUE); + SetConfigValue (config, "P2_LEFT_RED", &P2_LEFT_RED); + SetConfigValue (config, "P2_RIGHT_RED", &P2_RIGHT_RED); + SetConfigValue (config, "P2_RIGHT_BLUE", &P2_RIGHT_BLUE); + + toml_free (config); + } +} +} \ No newline at end of file diff --git a/src/keyconfig.h b/src/keyconfig.h new file mode 100644 index 0000000..b1a0ac4 --- /dev/null +++ b/src/keyconfig.h @@ -0,0 +1,3 @@ +namespace KeyConfig { + void Init(); +} \ No newline at end of file diff --git a/src/patches/cn_jun_2023.cpp b/src/patches/cn_jun_2023.cpp index 26836e9..8f65dd4 100644 --- a/src/patches/cn_jun_2023.cpp +++ b/src/patches/cn_jun_2023.cpp @@ -1,4 +1,5 @@ #include "helpers.h" +#include "patches.h" namespace patches::CN_JUN_2023 { u8 *haspBuffer; @@ -79,5 +80,7 @@ Init () { // Disable SSLVerify WRITE_MEMORY (ASLR (0x14034C182), u8, 0x00); + + patches::Qr::Init (); } } // namespace patches::CN_JUN_2023 diff --git a/src/patches/patches.h b/src/patches/patches.h index d5392de..3b7933a 100644 --- a/src/patches/patches.h +++ b/src/patches/patches.h @@ -8,4 +8,8 @@ void Init (); namespace AmAuth { void Init (); } // namespace AmAuth +namespace Qr { +void Init (); +void Update (); +} // namespace Qr } // namespace patches diff --git a/src/patches/qr.cpp b/src/patches/qr.cpp new file mode 100644 index 0000000..4a41536 --- /dev/null +++ b/src/patches/qr.cpp @@ -0,0 +1,168 @@ +#include "helpers.h" +#include "poll.h" +#include "patches.h" +#include +#include +#include +#include +#include + +extern Keybindings QR_CARD_READ; +extern Keybindings QR_DATA_READ; + +namespace patches::Qr { + +enum class State +{ + Ready, + CopyWait, + AfterCopy1, + AfterCopy2, +}; + +enum class Mode +{ + Card, + Data +}; + +State gState = State::Ready; +Mode gMode = Mode::Card; + +HOOK_DYNAMIC (char, __fastcall, qrInit, int64_t a1) { return 1; } +HOOK_DYNAMIC (char, __fastcall, qrRead, int64_t a1) +{ + *reinterpret_cast(a1 + 40) = 1; + *reinterpret_cast(a1 + 16) = 1; + *reinterpret_cast(a1 + 112) = 0; + return 1; +} +HOOK_DYNAMIC (char, __fastcall, qrClose, int64_t a1) { return 1; } +HOOK_DYNAMIC (int64_t, __fastcall, callQrUnknown, int64_t a1) +{ + switch (gState) + { + case State::Ready: + case State::CopyWait: + { + return 1; + } + case State::AfterCopy1: + { + gState = State::AfterCopy2; + return 1; + } + case State::AfterCopy2: + { + return 1; + } + default: + return 0; + } +} +HOOK_DYNAMIC (bool, __fastcall, Send1, int64_t, const void*, int64_t) { return true; } +HOOK_DYNAMIC (bool, __fastcall, Send2, int64_t a1, char a2) { return true; } +HOOK_DYNAMIC (bool, __fastcall, Send3, int64_t a1) +{ + *(WORD*)(a1 + 88) = 0; + *(BYTE*)(a1 + 90) = 0; + return true; +} +HOOK_DYNAMIC (bool, __fastcall, Send4, int64_t a1) +{ + *(BYTE*)(a1 + 88) = 1; + *(int64_t*)(a1 + 32) = *(int64_t*)(a1 + 24); + *(WORD*)(a1 + 89) = 0; + return true; +} +HOOK_DYNAMIC (int64_t, __fastcall, copy_data, int64_t this_, void* dest, int length) +{ + if (gState == State::CopyWait) + { + std::cout << "Copy data, length: " << length << std::endl; + auto configPath = std::filesystem::current_path () / "config.toml"; + toml_table_t *config = openConfig (configPath); + std::string data = ""; + + if (gMode == Mode::Card) + { + if (config) { + data = readConfigString (config, "qr_card_string", ""); + toml_free (config); + } + + memcpy(dest, data.c_str(), data.size() + 1); + gState = State::AfterCopy1; + return data.size() + 1; + } + else if (gMode == Mode::Data) + { + if (config) { + data = readConfigString (config, "qr_data_string", ""); + toml_free (config); + } + + BYTE data_length = static_cast(data.size()); + std::vector byteBuffer = { + 0x53, 0x31, 0x32, 0x00, 0x00, 0xFF, 0xFF, data_length, 0x01, 0x00 + }; + + for (char c : data) { + byteBuffer.push_back(static_cast(c)); + } + + byteBuffer.push_back(0xEE); + byteBuffer.push_back(0xFF); + + memcpy(dest, byteBuffer.data(), byteBuffer.size()); + gState = State::AfterCopy1; + return byteBuffer.size(); + } + } + return 0; +} + +int gCount = 0; + +void +Update () { + if (gState == State::AfterCopy2) + { + gCount++; + if (gCount > 10) + { + gCount = 0; + gState = State::Ready; + } + } + if (gState == State::Ready) + { + if (IsButtonTapped(QR_CARD_READ)) + { + std::cout << "Insert" << std::endl; + gState = State::CopyWait; + gMode = Mode::Card; + } + else if (IsButtonTapped(QR_DATA_READ)) + { + std::cout << "Insert" << std::endl; + gState = State::CopyWait; + gMode = Mode::Data; + } + } +} + +void +Init () { + auto amHandle = reinterpret_cast(GetModuleHandle ("AMFrameWork.dll")); + INSTALL_HOOK_DYNAMIC (qrInit, reinterpret_cast(amHandle + 0x161B0)); + INSTALL_HOOK_DYNAMIC (qrRead, reinterpret_cast(amHandle + 0x163A0)); + INSTALL_HOOK_DYNAMIC (qrClose, reinterpret_cast(amHandle + 0x16350)); + INSTALL_HOOK_DYNAMIC (callQrUnknown, reinterpret_cast(amHandle + 0x8F60)); + INSTALL_HOOK_DYNAMIC (Send1, reinterpret_cast(amHandle + 0x16A30)); + INSTALL_HOOK_DYNAMIC (Send2, reinterpret_cast(amHandle + 0x16A00)); + INSTALL_HOOK_DYNAMIC (Send3, reinterpret_cast(amHandle + 0x16990)); + INSTALL_HOOK_DYNAMIC (Send4, reinterpret_cast(amHandle + 0x16940)); + INSTALL_HOOK_DYNAMIC (copy_data, reinterpret_cast(amHandle + 0x169D0)); +} +} // namespace patches::Qr