From 30258ef8098d681cdf56aee8f88697692e029d39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=81=8D=E5=85=AE=E6=83=9A=E5=85=AE?= <1173718158@qq.com> Date: Tue, 3 Dec 2024 16:26:37 +0800 Subject: [PATCH] . --- cpp/LunaHook/LunaHook/engine64/vita3k.cpp | 81 ++++++++++--- .../LunaHook/engines/ppsspp/ppsspp.cpp | 109 ++++-------------- .../LunaHook/engines/ppsspp/specialgames.hpp | 88 ++++++++++++++ cpp/LunaHook/LunaHook/hookfinder.cc | 7 ++ cpp/LunaHook/LunaHook/texthook.cc | 4 +- cpp/version.cmake | 2 +- 6 files changed, 181 insertions(+), 110 deletions(-) diff --git a/cpp/LunaHook/LunaHook/engine64/vita3k.cpp b/cpp/LunaHook/LunaHook/engine64/vita3k.cpp index 256e7f44..f8f84bec 100644 --- a/cpp/LunaHook/LunaHook/engine64/vita3k.cpp +++ b/cpp/LunaHook/LunaHook/engine64/vita3k.cpp @@ -5,28 +5,21 @@ namespace auto idxDescriptor = isVirtual == true ? 2 : 1; auto idxEntrypoint = idxDescriptor + 1; std::string Vita3KGameID; + std::atomic unindexablehooks_near = 0; uintptr_t getDoJitAddress() { - auto RegisterBlockSig1 = "40 55 53 56 57 41 54 41 56 41 57 48 8D 6C 24 E9 48 81 EC 90 00 00 00 48 8B ?? ?? ?? ?? ?? 48 33 C4 48 89 45 07 4D 8B F1 49 8B F0 48 8B FA 48 8B D9 4C 8B 7D 77 48 8B 01 48 8D 55 C7 FF 50 10"; - auto first = find_pattern(RegisterBlockSig1, processStartAddress, processStopAddress); + // Vita3K\external\dynarmic\src\dynarmic\backend\x64\emit_x64.h + // BlockDescriptor EmitX64::RegisterBlock(const IR::LocationDescriptor& location_descriptor, CodePtr entrypoint, size_t size); + BYTE RegisterBlockSig1[] = {0x40, 0x55, 0x53, 0x56, 0x57, 0x41, 0x54, 0x41, 0x56, 0x41, 0x57, 0x48, 0x8D, 0x6C, 0x24, 0xE9, 0x48, 0x81, 0xEC, 0x90, 0x00, 0x00, 0x00, 0x48, 0x8B, XX, XX, XX, XX, XX, 0x48, 0x33, 0xC4, 0x48, 0x89, 0x45, 0x07, 0x4D, 0x8B, 0xF1, 0x49, 0x8B, 0xF0, 0x48, 0x8B, 0xFA, 0x48, 0x8B, 0xD9, 0x4C, 0x8B, 0x7D, 0x77, 0x48, 0x8B, 0x01, 0x48, 0x8D, 0x55, 0xC7, 0xFF, 0x50, 0x10}; + auto first = MemDbg::findBytes(RegisterBlockSig1, sizeof(RegisterBlockSig1), processStartAddress, processStopAddress); if (first) return first; - /* - // DebugSymbol: RegisterBlock - // ?RegisterBlock@EmitX64@X64@Backend@Dynarmic@@IEAA?AUBlockDescriptor@1234@AEBVLocationDescriptor@IR@4@PEBX_K@Z <- new - // ?RegisterBlock@EmitX64@X64@Backend@Dynarmic@@IEAA?AUBlockDescriptor@1234@AEBVLocationDescriptor@IR@4@PEBX1_K@Z - const symbols = DebugSymbol.findFunctionsMatching( - 'Dynarmic::Backend::X64::EmitX64::RegisterBlock' - ); - if (symbols.length !== 0) { - console.warn('Sym RegisterBlock'); - return symbols[0]; - } - */ - auto PatchBlockSig1 = "4C 8B DC 49 89 5B 10 49 89 6B 18 56 57 41 54 41 56 41 57"; - first = find_pattern(PatchBlockSig1, processStartAddress, processStopAddress); + + BYTE PatchBlockSig1[] = {0x4C, 0x8B, 0xDC, 0x49, 0x89, 0x5B, 0x10, 0x49, 0x89, 0x6B, 0x18, 0x56, 0x57, 0x41, 0x54, 0x41, 0x56, 0x41, 0x57}; + BYTE PatchBlockSig2[] = {0x4C, 0x8B, 0xDC, 0x49, 0x89, 0x5B, XX, 0x49, 0x89, 0x6B, XX, 0x56, 0x57, 0x41, 0x54, 0x41, 0x56, 0x41, 0x57}; + first = MemDbg::findBytes(PatchBlockSig1, sizeof(PatchBlockSig1), processStartAddress, processStopAddress); if (!first) - first = find_pattern("4C 8B DC 49 89 5B ?? 49 89 6B ?? 56 57 41 54 41 56 41 57", processStartAddress, processStopAddress); // 0.1.9 3339 + first = MemDbg::findBytes(PatchBlockSig2, sizeof(PatchBlockSig2), processStartAddress, processStopAddress); // 0.1.9 3339 if (first) { idxDescriptor = 1; @@ -45,7 +38,7 @@ namespace const char *_id; }; std::unordered_map emfunctionhooks; - + std::unordered_map> unindexablehooks; } namespace @@ -86,7 +79,28 @@ namespace return; Vita3KGameID = wcasta(curr); last = curr; - return HostInfo(HOSTINFO::EmuGameName, WideStringToString(game).c_str()); + HostInfo(HOSTINFO::EmuGameName, WideStringToString(game).c_str()); + for (auto &&[id, ptr] : unindexablehooks) + { + if (id == Vita3KGameID) + { + HookParam hp; + static int __fake = 0x10; + hp.address = __fake++; + hp.type = DIRECT_READ; + hp.user_value = (uintptr_t)&ptr; + hp.text_fun = [](hook_stack *stack, HookParam *hp, TextBuffer *buffer, uintptr_t *split) + { + auto __ = unindexablehooks_near.load(); + if (!__) + return; + if ((*((decltype(ptr) *)hp->user_value))(__)) + hp->type |= HOOK_EMPTY; + }; + NewHook(hp, (id + " Loader").c_str()); + } + } + return; } }; hp.type = DIRECT_READ; @@ -109,6 +123,7 @@ bool vita3k::attach_function() { auto descriptor = *argidx(stack, idxDescriptor + 1); // r8 auto entrypoint = *argidx(stack, idxEntrypoint + 1); // r9 + unindexablehooks_near.store(entrypoint); auto em_address = *(uint32_t *)descriptor; if (em_address < 0x80000000) em_address += 0x80000000; // 0.1.9 3339 @@ -504,8 +519,36 @@ namespace return buffer->clear(); last = s; } + + bool PCSG00397(uintptr_t funcnear) + { + BYTE sig[] = { + 0x41, 0x8b, 0x47, 0x10, + 0x45, 0x0f, 0xb6, 0x74, 0x05, 0x00, + 0x45, 0x0f, 0xbe, 0xf6, + 0x45, 0x89, 0x37, + 0x31, 0xc0, + 0x41, 0x83, 0xfe, 0x00}; + for (auto addr : Util::SearchMemory(sig, sizeof(sig), PAGE_EXECUTE_READWRITE, funcnear - 0x1000000, funcnear + 0x1000000)) + { + HookParam hp; + hp.address = addr; + hp.type = CODEC_UTF8 | USING_STRING | BREAK_POINT; + hp.text_fun = [](hook_stack *stack, HookParam *hp, TextBuffer *buffer, uintptr_t *split) + { + buffer->from((char *)VITA3K::emu_arg(stack)[4]); + }; + return NewHook(hp, "PCSG00397"); + } + return false; + } + auto _ = []() { + unindexablehooks = { + // ニセコイ ヨメイリ!? + {"PCSG00397", PCSG00397}, + }; emfunctionhooks = { // 追放選挙 {0x8002e176, {0, 0, 0, 0, FPCSG01023, "PCSG01023"}}, // dialogue+name,sjis diff --git a/cpp/LunaHook/LunaHook/engines/ppsspp/ppsspp.cpp b/cpp/LunaHook/LunaHook/engines/ppsspp/ppsspp.cpp index 0cdfaa8b..72c0180b 100644 --- a/cpp/LunaHook/LunaHook/engines/ppsspp/ppsspp.cpp +++ b/cpp/LunaHook/LunaHook/engines/ppsspp/ppsspp.cpp @@ -63,7 +63,7 @@ struct PPSSPPFunction const char *pattern; // debug string used within the function }; -namespace +namespace PPSSPP { uintptr_t findleapushalignfuncaddr(uintptr_t addr) { @@ -148,7 +148,7 @@ bool InsertPPSSPPHLEHooks() auto addr = MemDbg::findBytes(function.pattern, ::strlen(function.pattern), processStartAddress, processStopAddress); if (!addr) continue; - addr = findleapushalignfuncaddr(addr); + addr = PPSSPP::findleapushalignfuncaddr(addr); if (!addr) continue; @@ -488,7 +488,16 @@ namespace ppsspp } return true; } - + void LoadNativeHooks(const std::string &GameID) + { + for (auto &&[id, ptr] : nativehooks) + { + if (id == GameID) + { + ptr(); + } + } + } void Load_PSP_ISO_StringFromFormat() { /* @@ -529,6 +538,7 @@ namespace ppsspp game_info.TITLE = (char *)stack->ARG4; HostInfo(HOSTINFO::EmuGameName, "%s %s", stack->ARG3, stack->ARG4); jitaddrclear(); + LoadNativeHooks(game_info.DISC_ID); }; NewHook(hp, "PPSSPPGameInfo"); } @@ -537,10 +547,14 @@ namespace ppsspp auto wininfos = get_proc_windows(); for (auto &&info : wininfos) { - if (info.title.find(L'-') != info.title.npos) - { - return HostInfo(HOSTINFO::EmuGameName, WideStringToString(info.title.substr(info.title.find(L'-') + 1)).c_str()); - } + if (info.title.find(L'-') == info.title.npos) + continue; + auto title = WideStringToString(info.title.substr(info.title.find(L'-') + 2)); + game_info.DISC_ID = title.substr(0, title.find(':') - 1); + game_info.TITLE = title.substr(title.find(':') + 2); + HostInfo(HOSTINFO::EmuGameName, "%s %s", game_info.DISC_ID.c_str(), game_info.TITLE.c_str()); + LoadNativeHooks(game_info.DISC_ID); + return; } } bool hookPPSSPPDoJit() @@ -588,90 +602,9 @@ namespace ppsspp return NewHook(hp, "PPSSPPDoJit"); } } -namespace -{ - // ULJS00035 ULJS00149 流行り神 - void *findGetPointer() - { - char GetPointer[] = "Unknown GetPointer %08x PC %08x LR %08x"; - auto addr = MemDbg::findBytes(GetPointer, sizeof(GetPointer), processStartAddress, processStopAddress); - if (!addr) - return nullptr; - addr = findleapushalignfuncaddr(addr); - return (void *)addr; - } - bool Replace_memcpy() - { - // static int Replace_memcpy() { - // u32 destPtr = PARAM(0); - // u32 srcPtr = PARAM(1); - // u32 bytes = PARAM(2); - static auto GetPointer = (void *(*)(uintptr_t))findGetPointer(); - if (!GetPointer) - return false; - ConsoleOutput("GetPointer %p", GetPointer); - char ReplaceMemcpy_VideoDecodeRange[] = "ReplaceMemcpy/VideoDecodeRange"; - auto addr = MemDbg::findBytes(ReplaceMemcpy_VideoDecodeRange, sizeof(ReplaceMemcpy_VideoDecodeRange), processStartAddress, processStopAddress); - if (!addr) - return false; - ConsoleOutput("ReplaceMemcpy/VideoDecodeRange %p", addr); -#ifndef _WIN64 - BYTE sig[] = {0xb9, XX4}; - *(uintptr_t *)(sig + 1) = addr; - bool succ = false; - for (auto addr : Util::SearchMemory(sig, sizeof(sig), PAGE_EXECUTE, processStartAddress, processStopAddress)) - { - BYTE sig1[] = { - 0x55, 0x8b, 0xec, - 0x81, 0xec, XX4, - 0x8b, 0x0d, XX4}; - addr = reverseFindBytes(sig1, sizeof(sig1), addr - 0x200, addr); - if (!addr) - continue; - DWORD off_106D180 = *(DWORD *)(addr + sizeof(sig1) - 4); - HookParam hp; - hp.user_value = *(DWORD *)off_106D180; -#else - bool succ = false; - for (auto addr : MemDbg::findleaaddr_all(addr, processStartAddress, processStopAddress)) - { - BYTE sig1[] = { - 0x48, 0x89, XX, 0x24, 0x18, - 0x48, 0x89, XX, 0x24, 0x20, - 0x57, - 0x48, 0x81, 0xec, XX4, - 0x48, 0x8b, XX, XX4}; - addr = reverseFindBytes(sig1, sizeof(sig1), addr - 0x200, addr); - if (!addr) - continue; - DWORD off_140F4C810 = *(DWORD *)(addr + sizeof(sig1) - 4); - HookParam hp; - hp.user_value = *(uintptr_t *)(off_140F4C810 + addr + sizeof(sig1)); -#endif - hp.address = addr; - hp.text_fun = [](hook_stack *stack, HookParam *hp, auto *buff, auto *split) - { - auto bytes = *((DWORD *)hp->user_value + 6); - auto srcPtr = GetPointer(*((DWORD *)hp->user_value + 5)); - - if (!IsShiftjisLeadByte(*(BYTE *)srcPtr)) - return; - if (bytes != 2) - return; - if (bytes != strnlen((char *)srcPtr, TEXT_BUFFER_SIZE)) - return; - buff->from(srcPtr, bytes); - }; - succ |= NewHook(hp, "Replace_memcpy"); - } - return succ; - } -} bool InsertPPSSPPcommonhooks() { - auto succ = ppsspp::hookPPSSPPDoJit(); succ |= InsertPPSSPPHLEHooks(); - succ |= Replace_memcpy(); return succ; } \ No newline at end of file diff --git a/cpp/LunaHook/LunaHook/engines/ppsspp/specialgames.hpp b/cpp/LunaHook/LunaHook/engines/ppsspp/specialgames.hpp index f19e4b7a..a39d9ac5 100644 --- a/cpp/LunaHook/LunaHook/engines/ppsspp/specialgames.hpp +++ b/cpp/LunaHook/LunaHook/engines/ppsspp/specialgames.hpp @@ -1,6 +1,86 @@ #include #include "emujitarg.hpp" +namespace PPSSPP +{ + uintptr_t findleapushalignfuncaddr(uintptr_t addr); + // ULJS00035 ULJS00149 流行り神 + void *findGetPointer() + { + char GetPointer[] = "Unknown GetPointer %08x PC %08x LR %08x"; + auto addr = MemDbg::findBytes(GetPointer, sizeof(GetPointer), processStartAddress, processStopAddress); + if (!addr) + return nullptr; + addr = findleapushalignfuncaddr(addr); + return (void *)addr; + } + void Replace_memcpy() + { + // static int Replace_memcpy() { + // u32 destPtr = PARAM(0); + // u32 srcPtr = PARAM(1); + // u32 bytes = PARAM(2); + static auto GetPointer = (void *(*)(uintptr_t))findGetPointer(); + if (!GetPointer) + return; + ConsoleOutput("GetPointer %p", GetPointer); + char ReplaceMemcpy_VideoDecodeRange[] = "ReplaceMemcpy/VideoDecodeRange"; + auto addr = MemDbg::findBytes(ReplaceMemcpy_VideoDecodeRange, sizeof(ReplaceMemcpy_VideoDecodeRange), processStartAddress, processStopAddress); + if (!addr) + return; + ConsoleOutput("ReplaceMemcpy/VideoDecodeRange %p", addr); +#ifndef _WIN64 + BYTE sig[] = {0xb9, XX4}; + *(uintptr_t *)(sig + 1) = addr; + bool succ = ; + for (auto addr : Util::SearchMemory(sig, sizeof(sig), PAGE_EXECUTE, processStartAddress, processStopAddress)) + { + BYTE sig1[] = { + 0x55, 0x8b, 0xec, + 0x81, 0xec, XX4, + 0x8b, 0x0d, XX4}; + addr = reverseFindBytes(sig1, sizeof(sig1), addr - 0x200, addr); + if (!addr) + continue; + DWORD off_106D180 = *(DWORD *)(addr + sizeof(sig1) - 4); + HookParam hp; + hp.user_value = *(DWORD *)off_106D180; +#else + + for (auto addr : MemDbg::findleaaddr_all(addr, processStartAddress, processStopAddress)) + { + BYTE sig1[] = { + 0x48, 0x89, XX, 0x24, 0x18, + 0x48, 0x89, XX, 0x24, 0x20, + 0x57, + 0x48, 0x81, 0xec, XX4, + 0x48, 0x8b, XX, XX4}; + addr = reverseFindBytes(sig1, sizeof(sig1), addr - 0x200, addr); + if (!addr) + continue; + DWORD off_140F4C810 = *(DWORD *)(addr + sizeof(sig1) - 4); + HookParam hp; + hp.user_value = *(uintptr_t *)(off_140F4C810 + addr + sizeof(sig1)); +#endif + hp.address = addr; + hp.text_fun = [](hook_stack *stack, HookParam *hp, auto *buff, auto *split) + { + auto bytes = *((DWORD *)hp->user_value + 6); + auto srcPtr = GetPointer(*((DWORD *)hp->user_value + 5)); + + if (!IsShiftjisLeadByte(*(BYTE *)srcPtr)) + return; + if (bytes != 2) + return; + if (bytes != strnlen((char *)srcPtr, TEXT_BUFFER_SIZE)) + return; + buff->from(srcPtr, bytes); + }; + NewHook(hp, "Replace_memcpy"); + } + } +} + namespace ppsspp { void ULJS00403_filter(TextBuffer *buffer, HookParam *hp) @@ -710,6 +790,14 @@ namespace ppsspp return buffer->clear(); } } + std::unordered_map> nativehooks = { + // 流行り神PORTABLE + {"ULJS00035", PPSSPP::Replace_memcpy}, + // 流行り神2PORTABLE + {"ULJS00149", PPSSPP::Replace_memcpy}, + // 流行り神3 + {"ULJS00204", PPSSPP::Replace_memcpy}, // 乱码太多 + }; std::unordered_map emfunctionhooks = { // 死神と少女 {0x883bf34, {0, 1, 0, 0, ULJS00403_filter, "ULJS00403"}}, diff --git a/cpp/LunaHook/LunaHook/hookfinder.cc b/cpp/LunaHook/LunaHook/hookfinder.cc index ed64106d..c5d4f38a 100644 --- a/cpp/LunaHook/LunaHook/hookfinder.cc +++ b/cpp/LunaHook/LunaHook/hookfinder.cc @@ -472,6 +472,13 @@ void SearchForHooks(SearchParam spUser) } ConsoleOutput("%p %p",minemaddr,maxemaddr); ConsoleOutput("%p %p",sp.minAddress,sp.maxAddress); + if(0){ + auto f=fopen("1.txt","a"); + for(auto addr:jitaddr2emuaddr){ + fprintf(f,"%llx => %llx\n", addr.second.second ,addr.first); + } + fclose(f); + } for(auto addr:jitaddr2emuaddr){ //ConsoleOutput("%llx => %p", addr.second.second ,addr.first); if(addr.second.second>sp.maxAddress||addr.second.second