mirror of
https://github.com/HIllya51/LunaTranslator.git
synced 2025-01-14 08:14:07 +08:00
.
This commit is contained in:
parent
60f86ef52b
commit
30258ef809
@ -5,28 +5,21 @@ namespace
|
||||
auto idxDescriptor = isVirtual == true ? 2 : 1;
|
||||
auto idxEntrypoint = idxDescriptor + 1;
|
||||
std::string Vita3KGameID;
|
||||
std::atomic<uintptr_t> 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<uintptr_t, emfuncinfo> emfunctionhooks;
|
||||
|
||||
std::unordered_map<std::string, std::function<bool(uintptr_t)>> 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
|
||||
|
@ -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;
|
||||
}
|
@ -1,6 +1,86 @@
|
||||
#include <queue>
|
||||
#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<std::string, std::function<void()>> nativehooks = {
|
||||
// 流行り神PORTABLE
|
||||
{"ULJS00035", PPSSPP::Replace_memcpy},
|
||||
// 流行り神2PORTABLE
|
||||
{"ULJS00149", PPSSPP::Replace_memcpy},
|
||||
// 流行り神3
|
||||
{"ULJS00204", PPSSPP::Replace_memcpy}, // 乱码太多
|
||||
};
|
||||
std::unordered_map<uintptr_t, emfuncinfo> emfunctionhooks = {
|
||||
// 死神と少女
|
||||
{0x883bf34, {0, 1, 0, 0, ULJS00403_filter, "ULJS00403"}},
|
||||
|
@ -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<sp.minAddress)continue;
|
||||
|
@ -482,8 +482,8 @@ void TextHook::Read()
|
||||
{
|
||||
if (hp.text_fun)
|
||||
{
|
||||
while (WaitForSingleObject(readerEvent, 500) == WAIT_TIMEOUT)
|
||||
hp.text_fun(0, 0, 0, 0);
|
||||
while ((!(hp.type & HOOK_EMPTY)) && (WaitForSingleObject(readerEvent, 500) == WAIT_TIMEOUT))
|
||||
hp.text_fun(0, &hp, 0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1,7 +1,7 @@
|
||||
|
||||
set(VERSION_MAJOR 6)
|
||||
set(VERSION_MINOR 9)
|
||||
set(VERSION_PATCH 6)
|
||||
set(VERSION_PATCH 7)
|
||||
set(VERSION_REVISION 0)
|
||||
set(LUNA_VERSION "{${VERSION_MAJOR},${VERSION_MINOR},${VERSION_PATCH},${VERSION_REVISION}}")
|
||||
add_library(VERSION_DEF ${CMAKE_CURRENT_LIST_DIR}/version_def.cpp)
|
||||
|
Loading…
x
Reference in New Issue
Block a user