diff --git a/LunaHook/engines/ppsspp/ppsspp.cpp b/LunaHook/engines/ppsspp/ppsspp.cpp index bb9fc6f..3a21767 100644 --- a/LunaHook/engines/ppsspp/ppsspp.cpp +++ b/LunaHook/engines/ppsspp/ppsspp.cpp @@ -277,6 +277,166 @@ bool checkiscurrentgame(const emfuncinfo& em){ } std::unordered_setbreakpoints; +inline bool IsValidAddress(const uintptr_t address) { + if ((address & 0x3E000000) == 0x08000000) { + return true; + } else if ((address & 0x3F800000) == 0x04000000) { + return true; + } else if ((address & 0xBFFFC000) == 0x00010000) { + return true; + } else if ((address & 0x3F000000) >= 0x08000000){// && (address & 0x3F000000) < 0x08000000 + g_MemorySize) { + return true; + } else { + return false; + } +} +void dohookemaddr(uintptr_t em_address,uintptr_t ret){ + jitaddraddr(em_address,ret,JITTYPE::PPSSPP); + + if(emfunctionhooks.find(em_address)==emfunctionhooks.end())return; + if(!(checkiscurrentgame(emfunctionhooks.at(em_address))))return; + + auto op=emfunctionhooks.at(em_address); + ConsoleOutput("jit function addr %p",ret); + #ifndef _WIN64 + BYTE sig[]={ + 0x8b,XX2,//mov reg,[ebp-off] + 0x8b,0xc6,//mov eax,esi + 0x25,0xff,0xff,0xff,0x3f,//and eax,0x3fffffff + 0x89,XX,XX4,//mov [eax+base+off],reg + + }; + auto findbase=MemDbg::findBytes(sig,sizeof(sig),ret,ret+0x20); + if(!findbase) + findbase=MemDbg::findBytes(sig,sizeof(sig),ret-0x1000,ret+0x1000); + if(!findbase) + ConsoleOutput("can't find emu_baseaddr"); + PPSSPP::x86_baseaddr=(*(DWORD*)(findbase+12))&0xffff0000; + ConsoleOutput("x86 base addr %p",PPSSPP::x86_baseaddr); + #endif + HookParam hpinternal; + hpinternal.address=ret; + hpinternal.emu_addr=em_address;//用于生成hcode + hpinternal.type=USING_STRING|NO_CONTEXT|BREAK_POINT|op.type; + hpinternal.text_fun=(decltype(hpinternal.text_fun))op.hookfunc; + hpinternal.filter_fun=(decltype(hpinternal.filter_fun))op.filterfun; + hpinternal.argidx=op.argidx; + hpinternal.padding=op.padding; + hpinternal.jittype=JITTYPE::PPSSPP; + NewHook(hpinternal,op._id); +} +namespace{ + typedef DWORD u32; + typedef BYTE u8; + typedef WORD u16; + const int MAX_JIT_BLOCK_EXITS = 8; + namespace Memory { + struct Opcode { + Opcode() { + } + + explicit Opcode(u32 v) : encoding(v) { + } + + u32 operator & (const u32& arg) const { + return encoding & arg; + } + + u32 operator >> (const u32& arg) const { + return encoding >> arg; + } + + bool operator == (const u32& arg) const { + return encoding == arg; + } + + bool operator != (const u32& arg) const { + return encoding != arg; + } + + u32 encoding; + }; + + } + + typedef Memory::Opcode MIPSOpcode; + + struct JitBlock { + bool ContainsAddress(u32 em_address) const; + + const u8* checkedEntry; // const, we have to translate to writable. + const u8* normalEntry; + + u8* exitPtrs[MAX_JIT_BLOCK_EXITS]; // to be able to rewrite the exit jump + u32 exitAddress[MAX_JIT_BLOCK_EXITS]; // 0xFFFFFFFF == unknown + + u32 originalAddress; + MIPSOpcode originalFirstOpcode; //to be able to restore + uint64_t compiledHash; + u16 codeSize; + u16 originalSize; + u16 blockNum; + + bool invalid; + bool linkStatus[MAX_JIT_BLOCK_EXITS]; + + #ifdef USE_VTUNE + char blockName[32]; + #endif + + // By having a pointer, we avoid a constructor/destructor being generated and dog slow + // performance in debug. + std::vector* proxyFor; + + bool IsPureProxy() const { + return originalFirstOpcode.encoding == 0x68FF0000; + } + void SetPureProxy() { + // Magic number that won't be a real opcode. + originalFirstOpcode.encoding = 0x68FF0000; + } + }; +} + +void unsafeoncegetJitBlockCache(hook_stack* stack){ + + //class JitBlockCache : public JitBlockCacheDebugInterface { + //... + //JitBlock *blocks_ = nullptr; + //std::unordered_multimap proxyBlockMap_; ->64 + //int num_blocks_ = 0; + #ifdef _WIN64 + auto num_blocks_=*(uint32_t*)(stack->rcx+72+16+88); + auto blocks_=(JitBlock*)*(uintptr_t*)(stack->rcx+72+16+88-64-8); + #else + auto num_blocks_=*(uint32_t*)(stack->ecx+88); + auto blocks_=(JitBlock*)*(uintptr_t*)(stack->ecx+88-32-4); + #endif + int checkvalid=0; + num_blocks_-=1;//last one is now dojiting + for(int i=0;iTHISCALLARG1; *(uintptr_t*)(hp->user_value)=em_address; @@ -297,44 +458,13 @@ bool hookPPSSPPDoJit(){ hpinternal.address=stack->retaddr; hpinternal.text_fun=[](hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* split, size_t* len){ auto em_address=*(uintptr_t*)(hp->user_value); + if(!IsValidAddress(em_address))return; [&](){ auto ret=stack->RETADDR; if(breakpoints.find(ret)!=breakpoints.end())return; breakpoints.insert(ret); - jitaddraddr(em_address,ret,JITTYPE::PPSSPP); - - if(emfunctionhooks.find(em_address)==emfunctionhooks.end())return; - if(!(checkiscurrentgame(emfunctionhooks.at(em_address))))return; - - auto op=emfunctionhooks.at(em_address); - ConsoleOutput("jit function addr %p",ret); - #ifndef _WIN64 - BYTE sig[]={ - 0x8b,XX2,//mov reg,[ebp-off] - 0x8b,0xc6,//mov eax,esi - 0x25,0xff,0xff,0xff,0x3f,//and eax,0x3fffffff - 0x89,XX,XX4,//mov [eax+base+off],reg - - }; - auto findbase=MemDbg::findBytes(sig,sizeof(sig),ret,ret+0x20); - if(!findbase) - findbase=MemDbg::findBytes(sig,sizeof(sig),ret-0x1000,ret+0x1000); - if(!findbase) - ConsoleOutput("can't find emu_baseaddr"); - PPSSPP::x86_baseaddr=(*(DWORD*)(findbase+12))&0xffff0000; - ConsoleOutput("x86 base addr %p",PPSSPP::x86_baseaddr); - #endif - HookParam hpinternal; - hpinternal.address=ret; - hpinternal.emu_addr=em_address;//用于生成hcode - hpinternal.type=USING_STRING|NO_CONTEXT|BREAK_POINT|op.type; - hpinternal.text_fun=(decltype(hpinternal.text_fun))op.hookfunc; - hpinternal.filter_fun=(decltype(hpinternal.filter_fun))op.filterfun; - hpinternal.argidx=op.argidx; - hpinternal.padding=op.padding; - hpinternal.jittype=JITTYPE::PPSSPP; - NewHook(hpinternal,op._id); + dohookemaddr(em_address,ret); }(); delayinsertNewHook(em_address); };