From 329397a3c6ceab39fdcdeb2692d456d017e81f66 Mon Sep 17 00:00:00 2001 From: esuo1198 <54134.es@gmail.com> Date: Wed, 24 Apr 2024 07:19:39 +0900 Subject: [PATCH] Add JPN00 support --- meson.build | 1 + src/constants.h | 9 +-- src/dllmain.cpp | 4 ++ src/patches/audio.cpp | 5 ++ src/patches/patches.h | 3 + src/patches/qr.cpp | 12 ++++ src/patches/versions/JPN00.cpp | 114 +++++++++++++++++++++++++++++++++ 7 files changed, 144 insertions(+), 4 deletions(-) create mode 100644 src/patches/versions/JPN00.cpp diff --git a/meson.build b/meson.build index f8fbcd6..d1552d1 100644 --- a/meson.build +++ b/meson.build @@ -69,6 +69,7 @@ library( 'src/patches/audio.cpp', 'src/patches/qr.cpp', 'src/patches/amauth.cpp', + 'src/patches/versions/JPN00.cpp', 'src/patches/versions/JPN08.cpp', 'src/patches/versions/JPN39.cpp', 'src/patches/versions/CHN00.cpp', diff --git a/src/constants.h b/src/constants.h index 5d48df3..ae46b73 100644 --- a/src/constants.h +++ b/src/constants.h @@ -2,8 +2,9 @@ #include enum class GameVersion : XXH64_hash_t { - UNKNOWN = 0, - JPN08 = 0x67C0F3042746D488, - JPN39 = 0x49F643ADB6B18705, - CHN00 = 0xA7EE39F2CC2C57C8, + UNKNOWN = 0, + JPN00 = 0x4C07355966D815FB, + JPN08 = 0x67C0F3042746D488, + JPN39 = 0x49F643ADB6B18705, + CHN00 = 0xA7EE39F2CC2C57C8, }; \ No newline at end of file diff --git a/src/dllmain.cpp b/src/dllmain.cpp index 2db5ecd..86789bb 100644 --- a/src/dllmain.cpp +++ b/src/dllmain.cpp @@ -73,6 +73,7 @@ GetGameVersion () { free (buf); switch (gameVersion) { + case GameVersion::JPN00: case GameVersion::JPN08: case GameVersion::JPN39: case GameVersion::CHN00: break; @@ -132,6 +133,8 @@ DllMain (HMODULE module, DWORD reason, LPVOID reserved) { if (version == "auto") { GetGameVersion (); + } else if (version == "JPN00") { + gameVersion = GameVersion::JPN00; } else if (version == "JPN08") { gameVersion = GameVersion::JPN08; } else if (version == "JPN39") { @@ -186,6 +189,7 @@ DllMain (HMODULE module, DWORD reason, LPVOID reserved) { switch (gameVersion) { case GameVersion::UNKNOWN: break; + case GameVersion::JPN00: patches::JPN00::Init (); break; case GameVersion::JPN08: patches::JPN08::Init (); break; case GameVersion::JPN39: patches::JPN39::Init (); break; case GameVersion::CHN00: patches::CHN00::Init (); break; diff --git a/src/patches/audio.cpp b/src/patches/audio.cpp index 4f069c0..915eff6 100644 --- a/src/patches/audio.cpp +++ b/src/patches/audio.cpp @@ -51,6 +51,11 @@ Init () { } switch (gameVersion) { + case GameVersion::JPN00: { + INSTALL_HOOK_DYNAMIC (NUSCDeviceInit, ASLR (0x140552160)); + INSTALL_HOOK_DYNAMIC (LoadASIODriver, ASLR (0x14055A950)); + break; + } case GameVersion::JPN08: { INSTALL_HOOK_DYNAMIC (NUSCDeviceInit, ASLR (0x140692E00)); INSTALL_HOOK_DYNAMIC (LoadASIODriver, ASLR (0x14069B750)); diff --git a/src/patches/patches.h b/src/patches/patches.h index b4c1fa7..7ed4399 100644 --- a/src/patches/patches.h +++ b/src/patches/patches.h @@ -1,4 +1,7 @@ namespace patches { +namespace JPN00 { +void Init (); +} // namespace JPN00 namespace JPN08 { void Init (); } // namespace JPN08 diff --git a/src/patches/qr.cpp b/src/patches/qr.cpp index a08290d..792ff1d 100644 --- a/src/patches/qr.cpp +++ b/src/patches/qr.cpp @@ -267,6 +267,18 @@ Init () { SetConsoleOutputCP (CP_UTF8); auto amHandle = (u64)GetModuleHandle ("AMFrameWork.dll"); switch (gameVersion) { + case GameVersion::JPN00: { + INSTALL_HOOK_DYNAMIC (qrInit, (LPVOID)(amHandle + 0x1b3e0)); + INSTALL_HOOK_DYNAMIC (qrRead, (LPVOID)(amHandle + 0x1b600)); + INSTALL_HOOK_DYNAMIC (qrClose, (LPVOID)(amHandle + 0x1b5b0)); + INSTALL_HOOK_DYNAMIC (callQrUnknown, (LPVOID)(amHandle + 0xfd40)); + // 00.18 has no Send1 + INSTALL_HOOK_DYNAMIC (Send2, (LPVOID)(amHandle + 0x1bc60)); + INSTALL_HOOK_DYNAMIC (Send3, (LPVOID)(amHandle + 0x1bbf0)); + INSTALL_HOOK_DYNAMIC (Send4, (LPVOID)(amHandle + 0x1bbb0)); + INSTALL_HOOK_DYNAMIC (copy_data, (LPVOID)(amHandle + 0x1bc30)); + break; + } case GameVersion::JPN08: { INSTALL_HOOK_DYNAMIC (qrInit, (LPVOID)(amHandle + 0x1BA00)); INSTALL_HOOK_DYNAMIC (qrRead, (LPVOID)(amHandle + 0x1BC20)); diff --git a/src/patches/versions/JPN00.cpp b/src/patches/versions/JPN00.cpp new file mode 100644 index 0000000..042089f --- /dev/null +++ b/src/patches/versions/JPN00.cpp @@ -0,0 +1,114 @@ +#include "../patches.h" +#include "helpers.h" +#include + +extern u64 song_data_size; +extern void *song_data; + +#define RDX_MOV 0x48, 0xBA +#define R8_MOV 0x49, 0xB8 +#define GENERATE_MOV(instruction, location) \ + instruction, (u8)(u64)(location), (u8)((u64)(location) >> 8), (u8)((u64)(location) >> 16), (u8)((u64)(location) >> 24), (u8)((u64)(location) >> 32), (u8)((u64)(location) >> 40), \ + (u8)((u64)(location) >> 48), (u8)((u64)(location) >> 56) + +namespace patches::JPN00 { + +HOOK_DYNAMIC (char, __fastcall, AMFWTerminate, i64) { return 0; } + +const i32 datatableBufferSize = 1024 * 1024 * 12; +safetyhook::Allocation datatableBuffer; +const std::vector datatableBufferAddresses = {0x14005A418, 0x14005A445, 0x14005A778, 0x14005A7A5, 0x14005AD58, 0x14005AD85, 0x14005B1F2, 0x14005B221, 0x14005B438, + 0x14005B465, 0x14005B7D8, 0x14005B805, 0x14005BA59, 0x14005BA88, 0x14005BD78, 0x14005BDA7, 0x14005C1B3, 0x14005C1E2, + 0x14005CC52, 0x14005CC81, 0x14005D348, 0x14005D375, 0x14005D668, 0x14005D695, 0x14005D9D2, 0x14005DA04, 0x14005EA04, + 0x14005EA33, 0x14005EC18, 0x14005EC45, 0x14005EEE4, 0x14005EF10, 0x14005F158, 0x14005F185, 0x14005F47C, 0x14005F4A9}; +const std::vector memsetSizeAddresses = {0x14005A412, 0x14005A772, 0x14005AD52, 0x14005B1EC, 0x14005B432, 0x14005B7D2, 0x14005BA53, 0x14005BD72, 0x14005C1AD, + 0x14005CC4C, 0x14005D342, 0x14005D662, 0x14005D9CC, 0x14005E9FE, 0x14005EC12, 0x14005EEDE, 0x14005F152, 0x14005F476}; + +void +AllocateStaticBufferNear (void *target_address, size_t size, safetyhook::Allocation *newBuffer) { + auto allocator = safetyhook::Allocator::global (); + std::vector desired_addresses = {(uint8_t *)target_address}; + auto allocation_result = allocator->allocate_near (desired_addresses, size); + if (allocation_result.has_value ()) *newBuffer = std::move (*allocation_result); +} + +void +ReplaceLeaBufferAddress (const std::vector &bufferAddresses, void *newBufferAddress) { + for (auto bufferAddress : bufferAddresses) { + uintptr_t lea_instruction_dst = ASLR (bufferAddress) + 3; + uintptr_t lea_instruction_end = ASLR (bufferAddress) + 7; + intptr_t offset = (intptr_t)newBufferAddress - lea_instruction_end; + WRITE_MEMORY (lea_instruction_dst, i32, (i32)offset); + } +} + +void +Init () { + i32 xRes = 1920; + i32 yRes = 1080; + bool vsync = false; + bool unlockSongs = true; + + auto configPath = std::filesystem::current_path () / "config.toml"; + std::unique_ptr config_ptr (openConfig (configPath), toml_free); + if (config_ptr) { + auto patches = openConfigSection (config_ptr.get (), "patches"); + if (patches) { + auto res = openConfigSection (patches, "res"); + if (res) { + xRes = readConfigInt (res, "x", xRes); + yRes = readConfigInt (res, "y", yRes); + } + vsync = readConfigBool (patches, "vsync", vsync); + unlockSongs = readConfigBool (patches, "unlock_songs", unlockSongs); + } + } + + // Apply common config patch + WRITE_MEMORY (ASLR (0x140224B2B), i32, xRes); + WRITE_MEMORY (ASLR (0x140224B32), i32, yRes); + if (!vsync) WRITE_MEMORY (ASLR (0x1403D6189), u8, 0xBA, 0x00, 0x00, 0x00, 0x00, 0x90); + if (unlockSongs) WRITE_MEMORY (ASLR (0x1401F6B78), u8, 0xB0, 0x01); + + // Bypass errors + WRITE_MEMORY (ASLR (0x14001F0A0), u8, 0xC3); + + // Use TLS v1.2 + WRITE_MEMORY (ASLR (0x140309AC9), u8, 0x10); + + // Move various files to current dir + WRITE_MEMORY (ASLR (0x140018351), u8, 0x02); + WRITE_MEMORY (ASLR (0x1409A7138), char, "./"); + WRITE_MEMORY (ASLR (0x1409D23B8), char, ".\\Setting1.bin"); + WRITE_MEMORY (ASLR (0x1409D23C8), char, ".\\Setting2.bin"); + + // Remove datatable size limit + { + for (auto address : memsetSizeAddresses) + WRITE_MEMORY (ASLR (address) + 2, i32, datatableBufferSize); + + auto bufferBase = MODULE_HANDLE - 0x01000000; + AllocateStaticBufferNear ((void *)bufferBase, datatableBufferSize, &datatableBuffer); + + ReplaceLeaBufferAddress (datatableBufferAddresses, datatableBuffer.data ()); + } + + // Disable live check + auto amHandle = (u64)GetModuleHandle ("AMFrameWork.dll"); + INSTALL_HOOK_DYNAMIC (AMFWTerminate, (void *)(amHandle + 0x24B80)); + + // Move various files to current directory + WRITE_MEMORY (amHandle + 0x1473F, u8, 0xEB); // CreditLogPathA + WRITE_MEMORY (amHandle + 0x148AA, u8, 0xEB); // CreditLogPathB + WRITE_MEMORY (amHandle + 0x321A7, u8, 0xEB); // ErrorLogPathA + WRITE_MEMORY (amHandle + 0x322FA, u8, 0xEB); // ErrorLogPathB + WRITE_MEMORY (amHandle + 0x326D9, u8, 0xEB); // CommonLogPathA + WRITE_MEMORY (amHandle + 0x3282C, u8, 0xEB); // CommonLogPathB + WRITE_MEMORY (amHandle + 0x32C2A, u8, 0xEB); // BackupDataPathA + WRITE_MEMORY (amHandle + 0x32D7D, u8, 0xEB); // BackupDataPathB + + patches::Audio::Init (); + patches::Qr::Init (); + patches::AmAuth::Init (); +} +} // namespace patches::JPN00