Add QR emulation
This commit is contained in:
parent
510556643b
commit
90b0c890b6
4
dist/config.toml
vendored
4
dist/config.toml
vendored
@ -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 = ""
|
3
dist/keyconfig.toml
vendored
3
dist/keyconfig.toml
vendored
@ -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"]
|
||||
|
@ -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: ''
|
||||
)
|
||||
|
@ -1,9 +1,14 @@
|
||||
#include "helpers.h"
|
||||
#include "poll.h"
|
||||
#include "patches/patches.h"
|
||||
#include <xxhash.h>
|
||||
#include "keyconfig.h"
|
||||
#include "constants.h"
|
||||
|
||||
extern std::vector<HMODULE> 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
|
||||
|
8
src/constants.h
Normal file
8
src/constants.h
Normal file
@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
#include <xxhash.h>
|
||||
|
||||
enum class GameVersion : XXH64_hash_t {
|
||||
UNKNOWN = 0,
|
||||
JP_NOV_2020 = 0x67C0F3042746D488,
|
||||
CN_JUN_2023 = 0xA7EE39F2CC2C57C8,
|
||||
};
|
@ -2,13 +2,8 @@
|
||||
#include "helpers.h"
|
||||
#include "patches/patches.h"
|
||||
#include "poll.h"
|
||||
#include <xxhash.h>
|
||||
#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<HMODULE> plugins;
|
||||
|
||||
|
@ -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]; \
|
||||
|
54
src/keyconfig.cpp
Normal file
54
src/keyconfig.cpp
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
3
src/keyconfig.h
Normal file
3
src/keyconfig.h
Normal file
@ -0,0 +1,3 @@
|
||||
namespace KeyConfig {
|
||||
void Init();
|
||||
}
|
@ -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
|
||||
|
@ -8,4 +8,8 @@ void Init ();
|
||||
namespace AmAuth {
|
||||
void Init ();
|
||||
} // namespace AmAuth
|
||||
namespace Qr {
|
||||
void Init ();
|
||||
void Update ();
|
||||
} // namespace Qr
|
||||
} // namespace patches
|
||||
|
168
src/patches/qr.cpp
Normal file
168
src/patches/qr.cpp
Normal file
@ -0,0 +1,168 @@
|
||||
#include "helpers.h"
|
||||
#include "poll.h"
|
||||
#include "patches.h"
|
||||
#include <cstdint>
|
||||
#include <filesystem>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
|
||||
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<DWORD*>(a1 + 40) = 1;
|
||||
*reinterpret_cast<DWORD*>(a1 + 16) = 1;
|
||||
*reinterpret_cast<BYTE*>(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<BYTE>(data.size());
|
||||
std::vector<BYTE> byteBuffer = {
|
||||
0x53, 0x31, 0x32, 0x00, 0x00, 0xFF, 0xFF, data_length, 0x01, 0x00
|
||||
};
|
||||
|
||||
for (char c : data) {
|
||||
byteBuffer.push_back(static_cast<BYTE>(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<uintptr_t>(GetModuleHandle ("AMFrameWork.dll"));
|
||||
INSTALL_HOOK_DYNAMIC (qrInit, reinterpret_cast<LPVOID>(amHandle + 0x161B0));
|
||||
INSTALL_HOOK_DYNAMIC (qrRead, reinterpret_cast<LPVOID>(amHandle + 0x163A0));
|
||||
INSTALL_HOOK_DYNAMIC (qrClose, reinterpret_cast<LPVOID>(amHandle + 0x16350));
|
||||
INSTALL_HOOK_DYNAMIC (callQrUnknown, reinterpret_cast<LPVOID>(amHandle + 0x8F60));
|
||||
INSTALL_HOOK_DYNAMIC (Send1, reinterpret_cast<LPVOID>(amHandle + 0x16A30));
|
||||
INSTALL_HOOK_DYNAMIC (Send2, reinterpret_cast<LPVOID>(amHandle + 0x16A00));
|
||||
INSTALL_HOOK_DYNAMIC (Send3, reinterpret_cast<LPVOID>(amHandle + 0x16990));
|
||||
INSTALL_HOOK_DYNAMIC (Send4, reinterpret_cast<LPVOID>(amHandle + 0x16940));
|
||||
INSTALL_HOOK_DYNAMIC (copy_data, reinterpret_cast<LPVOID>(amHandle + 0x169D0));
|
||||
}
|
||||
} // namespace patches::Qr
|
Loading…
Reference in New Issue
Block a user