Add QR emulation for 08.18
This commit is contained in:
parent
d25a3743f2
commit
92c3e6aa81
@ -223,7 +223,7 @@ u16 __fastcall bnusio_GetCoin (i32 a1) {
|
|||||||
if (updateEvent) updateEvent ();
|
if (updateEvent) updateEvent ();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (version == GameVersion::CN_JUN_2023) patches::Qr::Update();
|
patches::Qr::Update();
|
||||||
|
|
||||||
return coin_count;
|
return coin_count;
|
||||||
}
|
}
|
||||||
|
@ -126,6 +126,8 @@ Init () {
|
|||||||
WRITE_MEMORY ((u64)amHandle + 0x148AF, u8, 0xEB);
|
WRITE_MEMORY ((u64)amHandle + 0x148AF, u8, 0xEB);
|
||||||
WRITE_MEMORY ((u64)amHandle + 0x14A1A, u8, 0xEB);
|
WRITE_MEMORY ((u64)amHandle + 0x14A1A, u8, 0xEB);
|
||||||
|
|
||||||
|
patches::Qr::Init ();
|
||||||
|
|
||||||
patches::AmAuth::Init ();
|
patches::AmAuth::Init ();
|
||||||
}
|
}
|
||||||
} // namespace patches::JP_NOV_2020
|
} // namespace patches::JP_NOV_2020
|
||||||
|
@ -1,122 +1,101 @@
|
|||||||
|
#include "constants.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include "poll.h"
|
#include "poll.h"
|
||||||
#include "patches.h"
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
|
extern GameVersion version;
|
||||||
extern Keybindings QR_CARD_READ;
|
extern Keybindings QR_CARD_READ;
|
||||||
extern Keybindings QR_DATA_READ;
|
extern Keybindings QR_DATA_READ;
|
||||||
|
|
||||||
namespace patches::Qr {
|
namespace patches::Qr {
|
||||||
|
|
||||||
enum class State
|
enum class State {
|
||||||
{
|
|
||||||
Ready,
|
Ready,
|
||||||
CopyWait,
|
CopyWait,
|
||||||
AfterCopy1,
|
AfterCopy1,
|
||||||
AfterCopy2,
|
AfterCopy2,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class Mode
|
enum class Mode { Card, Data };
|
||||||
{
|
|
||||||
Card,
|
|
||||||
Data
|
|
||||||
};
|
|
||||||
|
|
||||||
State gState = State::Ready;
|
State gState = State::Ready;
|
||||||
Mode gMode = Mode::Card;
|
Mode gMode = Mode::Card;
|
||||||
|
|
||||||
HOOK_DYNAMIC (char, __fastcall, qrInit, int64_t a1) { return 1; }
|
HOOK_DYNAMIC (char, __fastcall, qrInit, int64_t a1) { return 1; }
|
||||||
HOOK_DYNAMIC (char, __fastcall, qrRead, int64_t a1)
|
HOOK_DYNAMIC (char, __fastcall, qrRead, int64_t a1) {
|
||||||
{
|
*reinterpret_cast<DWORD *> (a1 + 40) = 1;
|
||||||
*reinterpret_cast<DWORD*>(a1 + 40) = 1;
|
*reinterpret_cast<DWORD *> (a1 + 16) = 1;
|
||||||
*reinterpret_cast<DWORD*>(a1 + 16) = 1;
|
*reinterpret_cast<BYTE *> (a1 + 112) = 0;
|
||||||
*reinterpret_cast<BYTE*>(a1 + 112) = 0;
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
HOOK_DYNAMIC (char, __fastcall, qrClose, int64_t a1) { return 1; }
|
HOOK_DYNAMIC (char, __fastcall, qrClose, int64_t a1) { return 1; }
|
||||||
HOOK_DYNAMIC (int64_t, __fastcall, callQrUnknown, int64_t a1)
|
HOOK_DYNAMIC (int64_t, __fastcall, callQrUnknown, int64_t a1) {
|
||||||
{
|
switch (gState) {
|
||||||
switch (gState)
|
|
||||||
{
|
|
||||||
case State::Ready:
|
case State::Ready:
|
||||||
case State::CopyWait:
|
case State::CopyWait: {
|
||||||
{
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
case State::AfterCopy1:
|
case State::AfterCopy1: {
|
||||||
{
|
|
||||||
gState = State::AfterCopy2;
|
gState = State::AfterCopy2;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
case State::AfterCopy2:
|
case State::AfterCopy2: {
|
||||||
{
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
default:
|
default: return 0;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
HOOK_DYNAMIC (bool, __fastcall, Send1, int64_t, const void*, int64_t) { return true; }
|
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, Send2, int64_t a1, char a2) { return true; }
|
||||||
HOOK_DYNAMIC (bool, __fastcall, Send3, int64_t a1)
|
HOOK_DYNAMIC (bool, __fastcall, Send3, int64_t a1) {
|
||||||
{
|
*(WORD *)(a1 + 88) = 0;
|
||||||
*(WORD*)(a1 + 88) = 0;
|
*(BYTE *)(a1 + 90) = 0;
|
||||||
*(BYTE*)(a1 + 90) = 0;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
HOOK_DYNAMIC (bool, __fastcall, Send4, int64_t a1)
|
HOOK_DYNAMIC (bool, __fastcall, Send4, int64_t a1) {
|
||||||
{
|
*(BYTE *)(a1 + 88) = 1;
|
||||||
*(BYTE*)(a1 + 88) = 1;
|
*(int64_t *)(a1 + 32) = *(int64_t *)(a1 + 24);
|
||||||
*(int64_t*)(a1 + 32) = *(int64_t*)(a1 + 24);
|
*(WORD *)(a1 + 89) = 0;
|
||||||
*(WORD*)(a1 + 89) = 0;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
HOOK_DYNAMIC (int64_t, __fastcall, copy_data, int64_t this_, void* dest, int length)
|
HOOK_DYNAMIC (int64_t, __fastcall, copy_data, int64_t this_, void *dest, int length) {
|
||||||
{
|
if (gState == State::CopyWait) {
|
||||||
if (gState == State::CopyWait)
|
|
||||||
{
|
|
||||||
std::cout << "Copy data, length: " << length << std::endl;
|
std::cout << "Copy data, length: " << length << std::endl;
|
||||||
auto configPath = std::filesystem::current_path () / "config.toml";
|
auto configPath = std::filesystem::current_path () / "config.toml";
|
||||||
toml_table_t *config = openConfig (configPath);
|
toml_table_t *config = openConfig (configPath);
|
||||||
std::string data = "";
|
std::string data = "";
|
||||||
|
|
||||||
if (gMode == Mode::Card)
|
if (gMode == Mode::Card) {
|
||||||
{
|
|
||||||
if (config) {
|
if (config) {
|
||||||
data = readConfigString (config, "qr_card_string", "");
|
data = readConfigString (config, "qr_card_string", "");
|
||||||
toml_free (config);
|
toml_free (config);
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(dest, data.c_str(), data.size() + 1);
|
memcpy (dest, data.c_str (), data.size () + 1);
|
||||||
gState = State::AfterCopy1;
|
gState = State::AfterCopy1;
|
||||||
return data.size() + 1;
|
return data.size () + 1;
|
||||||
}
|
} else if (gMode == Mode::Data) {
|
||||||
else if (gMode == Mode::Data)
|
|
||||||
{
|
|
||||||
if (config) {
|
if (config) {
|
||||||
data = readConfigString (config, "qr_data_string", "");
|
data = readConfigString (config, "qr_data_string", "");
|
||||||
toml_free (config);
|
toml_free (config);
|
||||||
}
|
}
|
||||||
|
|
||||||
BYTE data_length = static_cast<BYTE>(data.size());
|
BYTE data_length = static_cast<BYTE> (data.size ());
|
||||||
std::vector<BYTE> byteBuffer = {
|
std::vector<BYTE> byteBuffer = {0x53, 0x31, 0x32, 0x00, 0x00, 0xFF, 0xFF, data_length, 0x01, 0x00};
|
||||||
0x53, 0x31, 0x32, 0x00, 0x00, 0xFF, 0xFF, data_length, 0x01, 0x00
|
|
||||||
};
|
|
||||||
|
|
||||||
for (char c : data) {
|
for (char c : data)
|
||||||
byteBuffer.push_back(static_cast<BYTE>(c));
|
byteBuffer.push_back (static_cast<BYTE> (c));
|
||||||
}
|
|
||||||
|
|
||||||
byteBuffer.push_back(0xEE);
|
byteBuffer.push_back (0xEE);
|
||||||
byteBuffer.push_back(0xFF);
|
byteBuffer.push_back (0xFF);
|
||||||
|
|
||||||
memcpy(dest, byteBuffer.data(), byteBuffer.size());
|
memcpy (dest, byteBuffer.data (), byteBuffer.size ());
|
||||||
gState = State::AfterCopy1;
|
gState = State::AfterCopy1;
|
||||||
return byteBuffer.size();
|
return byteBuffer.size ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -126,25 +105,19 @@ int gCount = 0;
|
|||||||
|
|
||||||
void
|
void
|
||||||
Update () {
|
Update () {
|
||||||
if (gState == State::AfterCopy2)
|
if (gState == State::AfterCopy2) {
|
||||||
{
|
|
||||||
gCount++;
|
gCount++;
|
||||||
if (gCount > 10)
|
if (gCount > 10) {
|
||||||
{
|
|
||||||
gCount = 0;
|
gCount = 0;
|
||||||
gState = State::Ready;
|
gState = State::Ready;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (gState == State::Ready)
|
if (gState == State::Ready) {
|
||||||
{
|
if (IsButtonTapped (QR_CARD_READ)) {
|
||||||
if (IsButtonTapped(QR_CARD_READ))
|
|
||||||
{
|
|
||||||
std::cout << "Insert" << std::endl;
|
std::cout << "Insert" << std::endl;
|
||||||
gState = State::CopyWait;
|
gState = State::CopyWait;
|
||||||
gMode = Mode::Card;
|
gMode = Mode::Card;
|
||||||
}
|
} else if (IsButtonTapped (QR_DATA_READ)) {
|
||||||
else if (IsButtonTapped(QR_DATA_READ))
|
|
||||||
{
|
|
||||||
std::cout << "Insert" << std::endl;
|
std::cout << "Insert" << std::endl;
|
||||||
gState = State::CopyWait;
|
gState = State::CopyWait;
|
||||||
gMode = Mode::Data;
|
gMode = Mode::Data;
|
||||||
@ -154,15 +127,35 @@ Update () {
|
|||||||
|
|
||||||
void
|
void
|
||||||
Init () {
|
Init () {
|
||||||
auto amHandle = reinterpret_cast<uintptr_t>(GetModuleHandle ("AMFrameWork.dll"));
|
auto amHandle = reinterpret_cast<uintptr_t> (GetModuleHandle ("AMFrameWork.dll"));
|
||||||
INSTALL_HOOK_DYNAMIC (qrInit, reinterpret_cast<LPVOID>(amHandle + 0x161B0));
|
switch (version) {
|
||||||
INSTALL_HOOK_DYNAMIC (qrRead, reinterpret_cast<LPVOID>(amHandle + 0x163A0));
|
case GameVersion::JP_NOV_2020: {
|
||||||
INSTALL_HOOK_DYNAMIC (qrClose, reinterpret_cast<LPVOID>(amHandle + 0x16350));
|
INSTALL_HOOK_DYNAMIC (qrInit, reinterpret_cast<LPVOID> (amHandle + 0x1BA00));
|
||||||
INSTALL_HOOK_DYNAMIC (callQrUnknown, reinterpret_cast<LPVOID>(amHandle + 0x8F60));
|
INSTALL_HOOK_DYNAMIC (qrRead, reinterpret_cast<LPVOID> (amHandle + 0x1BC20));
|
||||||
INSTALL_HOOK_DYNAMIC (Send1, reinterpret_cast<LPVOID>(amHandle + 0x16A30));
|
INSTALL_HOOK_DYNAMIC (qrClose, reinterpret_cast<LPVOID> (amHandle + 0x1BBD0));
|
||||||
INSTALL_HOOK_DYNAMIC (Send2, reinterpret_cast<LPVOID>(amHandle + 0x16A00));
|
INSTALL_HOOK_DYNAMIC (callQrUnknown, reinterpret_cast<LPVOID> (amHandle + 0xFD40));
|
||||||
INSTALL_HOOK_DYNAMIC (Send3, reinterpret_cast<LPVOID>(amHandle + 0x16990));
|
// 08.18 has no Send1
|
||||||
INSTALL_HOOK_DYNAMIC (Send4, reinterpret_cast<LPVOID>(amHandle + 0x16940));
|
INSTALL_HOOK_DYNAMIC (Send2, reinterpret_cast<LPVOID> (amHandle + 0x1C2D0));
|
||||||
INSTALL_HOOK_DYNAMIC (copy_data, reinterpret_cast<LPVOID>(amHandle + 0x169D0));
|
INSTALL_HOOK_DYNAMIC (Send3, reinterpret_cast<LPVOID> (amHandle + 0x1C260));
|
||||||
|
INSTALL_HOOK_DYNAMIC (Send4, reinterpret_cast<LPVOID> (amHandle + 0x1C220));
|
||||||
|
INSTALL_HOOK_DYNAMIC (copy_data, reinterpret_cast<LPVOID> (amHandle + 0x1C2A0));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GameVersion::CN_JUN_2023: {
|
||||||
|
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));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} // namespace patches::Qr
|
} // namespace patches::Qr
|
||||||
|
Loading…
x
Reference in New Issue
Block a user