diff --git a/LunaHook/engine64/PPSSPP.cpp b/LunaHook/engine64/PPSSPP.cpp index 78fee28..4359d8c 100644 --- a/LunaHook/engine64/PPSSPP.cpp +++ b/LunaHook/engine64/PPSSPP.cpp @@ -1,13 +1,12 @@ #include"PPSSPP.h" - +#include /** Artikash 6/7/2019 * PPSSPP JIT code has pointers, but they are all added to an offset before being used. Find that offset so that hook searching works properly. To find the offset, find a page of mapped memory with size 0x1f00000, read and write permissions, take its address and subtract 0x8000000. The above is useful for emulating PSP hardware, so unlikely to change between versions. */ -bool PPSSPP::attach_function() -{ +bool PPSSPPinithooksearch(){ bool found = false; SYSTEM_INFO systemInfo; GetNativeSystemInfo(&systemInfo); @@ -41,4 +40,208 @@ bool PPSSPP::attach_function() } } return found; +} +namespace{ +uintptr_t getDoJitAddress() { + auto DoJitSig1 = "C7 83 ?? 0? 00 00 11 00 00 00 F6 83 ?? 0? 00 00 01 C7 83 ?? 0? 00 00 E4 00 00 00"; + auto first=find_pattern(DoJitSig1,processStartAddress,processStopAddress); + if (first) { + auto beginSubSig1 = "55 41 ?? 41 ?? 41"; + auto lookbackSize = 0x400; + auto address=first-lookbackSize; + auto subs=find_pattern(beginSubSig1,address,address+lookbackSize); + if(subs){ + return subs; + } + } + return 0; +} +template +class lockedqueue{ + std::mutex lock; + std::queuedata; + HANDLE hsema; + public: + lockedqueue(){ + hsema=CreateSemaphore(NULL,0,65535,NULL); + } + ~lockedqueue(){ + CloseHandle(hsema); + } + void push(T&& _){ + std::lock_guard _l(lock); + data.push(std::move(_)); + ReleaseSemaphore(hsema,1,NULL); + } + T pop(){ + WaitForSingleObject(hsema,INFINITE); + std::lock_guard _l(lock); + auto _=data.front(); + data.pop(); + return _; + } + bool empty(){ + std::lock_guard _l(lock); + return data.empty(); + } +}; +class emu_arg{ + hook_stack* stack; +public: + emu_arg(hook_stack* stack_):stack(stack_){}; + uintptr_t operator [](int idx){ + auto base=stack->rbx; + auto args=stack->r14; + auto offR = -0x80; + auto offset = offR + 0x10 + idx * 4; + return base+*(uint32_t*)(args+offset); + } +}; +struct emfuncinfo{ + const char* hookname; + void* hookfunc; + const wchar_t* _id; +}; +std::unordered_mapemfunctionhooks; + +} +bool hookPPSSPPDoJit(){ + ConsoleOutput("[Compatibility]"); + ConsoleOutput("PPSSPP 1.12.3-867 -> v1.16.1-35"); + ConsoleOutput("[Mirror] Download: https://github.com/koukdw/emulators/releases"); + auto DoJitPtr=getDoJitAddress(); + if(DoJitPtr==0)return false; + HookParam hp; + hp.address=DoJitPtr;//Jit::DoJit + ConsoleOutput("DoJitPtr %p",DoJitPtr); + + static lockedqueue> message; + + hp.text_fun=[](hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* split, size_t* len){ + auto em_address=stack->ARG2; + if(emfunctionhooks.find(em_address)==emfunctionhooks.end())return; + auto op=emfunctionhooks.at(em_address); + auto GetCodePtr=(*(__int64 (__fastcall **)(__int64))(*(uintptr_t *)stack->THISCALLTHIS + 8LL))(stack->THISCALLTHIS); + GetCodePtr+=0x12; + message.push({GetCodePtr,op}); + HookParam hpinternal; + hpinternal.address=stack->retaddr; + hpinternal.text_fun=[](hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* split, size_t* len){ + hp->text_fun=nullptr;hp->type=HOOK_EMPTY; + auto [GetCodePtr,op]=message.pop(); + ConsoleOutput("%p",GetCodePtr); + DWORD _; + VirtualProtect((LPVOID)GetCodePtr,0x10,PAGE_EXECUTE_READWRITE,&_); + HookParam hpinternal; + hpinternal.address=GetCodePtr; + hpinternal.type=CODEC_UTF16|USING_STRING|NO_CONTEXT; + hpinternal.text_fun=(decltype(hpinternal.text_fun))op.hookfunc; + NewHook(hpinternal,op.hookname); + }; + NewHook(hpinternal,"doonce");//必须退出Dojit再newhook,否则无效,原因不明。 + }; + + return NewHook(hp,"PPSSPPDoJit"); +} + +bool PPSSPP::attach_function() +{ + return PPSSPPinithooksearch()| hookPPSSPPDoJit(); +} + +// ==UserScript== +// @name [ULJS00403] Shinigami to Shoujo +// @version 0.1 +// @author [DC] +// @description PPSSPP x64 +// * TAKUYO +// * TAKUYO +// * +void ULJS00403(hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* split, size_t* len){ + hp->type=USING_STRING|NO_CONTEXT; + hp->codepage=932; + auto address= emu_arg(stack)[1]; + *data=address; + *len=strlen((char*)address); +} + +// ==UserScript== +// @name [ULJS00339] Amagami +// @version v1.02 +// @author [DC] +// @description +// * Kadokawa +// * K2X_Script +void ULJS00339(hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* split, size_t* len){ + hp->type=USING_STRING|NO_CONTEXT; + hp->codepage=932; + auto base=stack->rbx; + auto a2= emu_arg(stack)[0]; + + auto vm = *(DWORD*)(a2+(0x28)); + vm=*(DWORD*)(vm+base); + vm=*(DWORD*)(vm+base+8); + auto address=vm+base; + auto len1=*(DWORD*)(address+4); + auto p=address+0x20; + if(len1>4 && *(WORD*)(p+2)==0){ + auto p1=*(DWORD*)(address+8); + vm=*(DWORD*)(vm+base); + vm=*(DWORD*)(vm+base+0xC); + p=vm+base; + } + static int fm=0; + static std::string pre; + auto b=fm; + auto s=[](uintptr_t address){ + auto frist = *(WORD*)address; + auto lo = frist & 0xFF; // uppercase: 41->5A + auto hi = frist >> 8; + if (hi == 0 && (lo > 0x5a || lo < 0x41) /* T,W,? */) { + return std::string(); + } + std::string s ;int i = 0;WORD c; + char buf[3]={0}; + while ((c = *(WORD*)(address+i)) != 0) { + // reverse endian: ShiftJIS BE => LE + buf[0] = c >> 8; + buf[1] = c & 0xFF; + + if (c == 0x815e /* / */) { + s += ' '; // single line + } + else if (buf[0] == 0) { + //// UTF16 LE turned BE: 5700=>0057, 3100, 3500 + //// 4e00 6d00=>PLAYER + // do nothing + if (buf[1] == 0x4e) { + s += "PLAYER"; + fm++; + } + } + else { + s+=buf; + } + i += 2; + } + return s; + }(p); + if(b>0){ + fm--; + return; + } + if(s==pre)return ; + pre=s; + write_string_new(data,len,s); +} + + +namespace{ +auto _=[](){ + emfunctionhooks={ + {0x883bf34,{"Shinigami to Shoujo",ULJS00403,L"PCSG01282"}}, + {0x0886775c,{"Amagami",ULJS00339,L"ULJS00339"}}, + }; + return 1; +}(); } \ No newline at end of file diff --git a/LunaHook/engine64/yuzusuyu.cpp b/LunaHook/engine64/yuzusuyu.cpp index 64f3a6e..cdf1a6e 100644 --- a/LunaHook/engine64/yuzusuyu.cpp +++ b/LunaHook/engine64/yuzusuyu.cpp @@ -89,12 +89,16 @@ std::unordered_mapemfunctionhooks; } bool yuzusuyu::attach_function() { + + ConsoleOutput("[Compatibility]"); + ConsoleOutput("Yuzu 1616+"); + ConsoleOutput("[Mirror] Download: https://github.com/koukdw/emulators/releases"); auto DoJitPtr=getDoJitAddress(); if(DoJitPtr==0)return false; + ConsoleOutput("DoJitPtr %p",DoJitPtr); HookParam hp; hp.address=DoJitPtr; hp.text_fun=[](hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* split, size_t* len){ - //hp->text_fun=nullptr;hp->type=HOOK_EMPTY; auto descriptor = *argidx(stack,idxDescriptor); // r8 auto entrypoint = *argidx(stack,idxEntrypoint); // r9 auto em_address = *(uintptr_t*)descriptor; @@ -103,7 +107,6 @@ bool yuzusuyu::attach_function() auto op=emfunctionhooks.at(em_address); - DWORD _; VirtualProtect((LPVOID)entrypoint,0x10,PAGE_EXECUTE_READWRITE,&_); HookParam hpinternal; @@ -126,10 +129,12 @@ void _0100978013276000(hook_stack* stack, HookParam* hp, uintptr_t* data, uintpt auto s=mages::readString(emu_arg(stack)[0],0); write_string_new(data,len,s); } +namespace{ auto _=[](){ emfunctionhooks={ {0x8003eeac - 0x80004000,{"Memories Off",_0100978013276000,L"0100978013276000",L"1.0.0"}}, {0x8003eebc - 0x80004000,{"Memories Off",_0100978013276000,L"0100978013276000",L"1.0.1"}}, }; return 1; -}(); \ No newline at end of file +}(); +} \ No newline at end of file diff --git a/LunaHook/enginecollection64.cpp b/LunaHook/enginecollection64.cpp index 85a8054..9393585 100644 --- a/LunaHook/enginecollection64.cpp +++ b/LunaHook/enginecollection64.cpp @@ -21,7 +21,6 @@ std::vector unsafe_check_atlast(){ return{ }; } std::vector check_engines(){ return { - new PPSSPP, new Godot, new V8, new Renpy, @@ -38,7 +37,8 @@ std::vector check_engines(){ new _5pb, new TYPEMOON, new ENTERGRAM, - new yuzusuyu + new yuzusuyu, + new PPSSPP, }; }