1
0
mirror of synced 2024-11-28 01:10:55 +01:00

Add QR emulation

This commit is contained in:
esuo1198 2023-09-19 00:10:54 +09:00
parent 510556643b
commit 90b0c890b6
12 changed files with 285 additions and 51 deletions

4
dist/config.toml vendored
View File

@ -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 = ""

5
dist/keyconfig.toml vendored
View File

@ -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

View File

@ -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: ''
)

View File

@ -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
View 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,
};

View File

@ -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;

View File

@ -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
View 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
View File

@ -0,0 +1,3 @@
namespace KeyConfig {
void Init();
}

View File

@ -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

View File

@ -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
View 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