mirror of
https://github.com/HIllya51/LunaHook.git
synced 2024-12-24 04:04:14 +08:00
ppsspp
1 1 Update PPSSPP.cpp Update PPSSPP.cpp
This commit is contained in:
parent
271aa43cee
commit
c031c40521
@ -2,7 +2,6 @@
|
||||
#include"PPSSPP.h"
|
||||
|
||||
#include"ppsspp/psputils.hpp"
|
||||
#include "ppsspp/funcinfo.h"
|
||||
namespace { // unnamed
|
||||
|
||||
inline bool _bandaigarbage_ch(char c)
|
||||
@ -210,43 +209,6 @@ void SpecialPSPHook(hook_stack* stack, HookParam *hp, uintptr_t *data, uintptr_
|
||||
}
|
||||
}
|
||||
|
||||
bool InsertPPSSPPHLEHooks()
|
||||
{
|
||||
ConsoleOutput("PPSSPP HLE: enter");
|
||||
|
||||
// 0x400000 - 0x139f000
|
||||
//GROWL_DWORD2(processStartAddress, processStopAddress);
|
||||
|
||||
HookParam hp;
|
||||
hp.length_offset = 1; // determine string length at runtime
|
||||
auto succ=false;
|
||||
const PPSSPPFunction funcs[] = { PPSSPP_FUNCTIONS_INITIALIZER };
|
||||
enum { FunctionCount = sizeof(funcs) / sizeof(*funcs) };
|
||||
for (size_t i = 0; i < FunctionCount; i++) {
|
||||
const auto &it = funcs[i];
|
||||
ULONG addr = MemDbg::findBytes(it.pattern, ::strlen(it.pattern), processStartAddress, processStopAddress);
|
||||
if (addr
|
||||
&& (addr = MemDbg::findPushAddress(addr, processStartAddress, processStopAddress))
|
||||
&& (addr = SafeFindEnclosingAlignedFunction(addr, 0x200)) // range = 0x200, use the safe version or it might raise
|
||||
) {
|
||||
hp.address = addr;
|
||||
hp.type = USING_STRING|it.hookType;
|
||||
hp.offset=get_stack(it.argIndex);
|
||||
hp.split = it.hookSplit;
|
||||
if (hp.split)
|
||||
hp.type |= USING_SPLIT;
|
||||
succ|=NewHook(hp, it.hookName);
|
||||
}
|
||||
if (addr)
|
||||
ConsoleOutput("PPSSPP HLE: found pattern");
|
||||
else
|
||||
ConsoleOutput("PPSSPP HLE: not found pattern");
|
||||
//ConsoleOutput(it.hookName); // wchar_t not supported
|
||||
ConsoleOutput(it.pattern);
|
||||
}
|
||||
ConsoleOutput("PPSSPP HLE: leave");
|
||||
return succ;
|
||||
}
|
||||
|
||||
/** 8/9/2014 jichi imageepoch.co.jp PSP engine, 0.9.8, 0.9.9
|
||||
* Sample game: Sol Trigger (0.9.8, 0.9.9)
|
||||
@ -3625,7 +3587,6 @@ bool InsertPPSSPPHooks()
|
||||
//
|
||||
//}
|
||||
|
||||
InsertPPSSPPHLEHooks();
|
||||
|
||||
if (PPSSPP_VERSION[1] == 9 && PPSSPP_VERSION[2] == 9 && PPSSPP_VERSION[3] == 0) // 0.9.9.0
|
||||
InsertOtomatePPSSPPHook();
|
||||
@ -3677,54 +3638,19 @@ bool InsertPPSSPPHooks()
|
||||
return true;
|
||||
}
|
||||
|
||||
/** 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 FindPPSSPP()
|
||||
namespace ppsspp{
|
||||
std::unordered_map<uintptr_t,emfuncinfo> loademfunctionhooks()
|
||||
{
|
||||
bool found = false;
|
||||
SYSTEM_INFO systemInfo;
|
||||
GetNativeSystemInfo(&systemInfo);
|
||||
for (BYTE* probe = NULL; probe < systemInfo.lpMaximumApplicationAddress;)
|
||||
{
|
||||
MEMORY_BASIC_INFORMATION info;
|
||||
if (!VirtualQuery(probe, &info, sizeof(info)))
|
||||
{
|
||||
probe += systemInfo.dwPageSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (info.RegionSize == 0x1f00000 && info.Protect == PAGE_READWRITE && info.Type == MEM_MAPPED)
|
||||
{
|
||||
found = true;
|
||||
ConsoleOutput("PPSSPP memory found: searching for hooks should yield working hook codes");
|
||||
// PPSSPP 1.8.0 compiles jal to sub dword ptr [ebp+0x360],??
|
||||
memcpy(spDefault.pattern, Array<BYTE>{ 0x83, 0xAD, 0x60, 0x03, 0x00, 0x00 }, spDefault.length = 6);
|
||||
spDefault.offset = 0;
|
||||
spDefault.minAddress = 0;
|
||||
spDefault.maxAddress = -1ULL;
|
||||
spDefault.padding = (uintptr_t)probe - 0x8000000;
|
||||
spDefault.hookPostProcessor = [](HookParam& hp)
|
||||
{
|
||||
hp.type |= NO_CONTEXT | USING_SPLIT | SPLIT_INDIRECT;
|
||||
hp.split = get_reg(regs::ebp);
|
||||
hp.split_index =get_reg(regs::eax); // this is where PPSSPP 1.8.0 stores its return address stack
|
||||
};
|
||||
}
|
||||
probe += info.RegionSize;
|
||||
}
|
||||
}
|
||||
return found;
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool PPSSPP::attach_function() {
|
||||
bool _b1=InsertPPSSPPHooks(); // Artikash 8/4/2018: removed for now as doesn't work for non ancient ppsspp versions
|
||||
bool _b2=FindPPSSPP();
|
||||
if(_b1||_b2)
|
||||
return true;
|
||||
return false;
|
||||
auto succ=InsertPPSSPPcommonhooks();
|
||||
|
||||
//succ|=InsertPPSSPPHooks(); // Artikash 8/4/2018: removed for now as doesn't work for non ancient ppsspp versions
|
||||
|
||||
return succ;
|
||||
}
|
||||
|
@ -1,91 +1,10 @@
|
||||
#include"PPSSPP.h"
|
||||
#include"ppsspp/psputils.hpp"
|
||||
#include<queue>
|
||||
/** 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 PPSSPPinithooksearch(){
|
||||
bool found = false;
|
||||
SYSTEM_INFO systemInfo;
|
||||
GetNativeSystemInfo(&systemInfo);
|
||||
for (BYTE* probe = NULL; probe < systemInfo.lpMaximumApplicationAddress;)
|
||||
{
|
||||
MEMORY_BASIC_INFORMATION info;
|
||||
if (!VirtualQuery(probe, &info, sizeof(info)))
|
||||
{
|
||||
probe += systemInfo.dwPageSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (info.RegionSize == 0x1f00000 && info.Protect == PAGE_READWRITE && info.Type == MEM_MAPPED)
|
||||
{
|
||||
found = true;
|
||||
ConsoleOutput("PPSSPP memory found: searching for hooks should yield working hook codes");
|
||||
// PPSSPP 1.8.0 compiles jal to sub dword ptr [r14+0x360],??
|
||||
memcpy(spDefault.pattern, Array<BYTE>{ 0x41, 0x83, 0xae, 0x60, 0x03, 0x00, 0x00 }, spDefault.length = 7);
|
||||
spDefault.offset = 0;
|
||||
spDefault.minAddress = 0;
|
||||
spDefault.maxAddress = -1ULL;
|
||||
spDefault.padding = (uintptr_t)probe - 0x8000000;
|
||||
spDefault.hookPostProcessor = [](HookParam& hp)
|
||||
{
|
||||
hp.type |= NO_CONTEXT | USING_SPLIT | SPLIT_INDIRECT;
|
||||
hp.split = get_reg(regs::r14);
|
||||
hp.split_index = -8; // this is where PPSSPP 1.8.0 stores its return address stack
|
||||
};
|
||||
}
|
||||
probe += info.RegionSize;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
void* filterfun;
|
||||
const wchar_t* _id;
|
||||
};
|
||||
std::unordered_map<uintptr_t,emfuncinfo>emfunctionhooks;
|
||||
std::unordered_set<uintptr_t>breakpoints;
|
||||
|
||||
bool checkiscurrentgame(const emfuncinfo& em){
|
||||
auto wininfos=get_proc_windows();
|
||||
for(auto&& info:wininfos){
|
||||
if(info.title.find(em._id)!=info.title.npos)return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
template<int index,int offset=0>
|
||||
void simple932getter(hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* split, size_t* len){
|
||||
hp->type=USING_STRING|NO_CONTEXT;
|
||||
@ -105,53 +24,19 @@ void simpleutf16getter(hook_stack* stack, HookParam* hp, uintptr_t* data, uintpt
|
||||
hp->type=USING_STRING|CODEC_UTF16|NO_CONTEXT|_type;
|
||||
*data=address;*len=wcslen((wchar_t*)address)*2;
|
||||
}
|
||||
}
|
||||
bool hookPPSSPPDoJit(){
|
||||
ConsoleOutput("[Compatibility] PPSSPP 1.12.3-867 -> v1.16.1-35");
|
||||
auto DoJitPtr=getDoJitAddress();
|
||||
if(DoJitPtr==0)return false;
|
||||
HookParam hp;
|
||||
hp.address=DoJitPtr;//Jit::DoJit
|
||||
ConsoleOutput("DoJitPtr %p",DoJitPtr);
|
||||
|
||||
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;
|
||||
|
||||
if(!(checkiscurrentgame(emfunctionhooks.at(em_address))))return;
|
||||
|
||||
HookParam hpinternal;
|
||||
hpinternal.user_value=em_address;
|
||||
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 ret=stack->rax;
|
||||
if(breakpoints.find(ret)!=breakpoints.end())return;
|
||||
breakpoints.insert(ret);
|
||||
|
||||
auto em_address=hp->user_value;
|
||||
auto op=emfunctionhooks.at(em_address);
|
||||
|
||||
HookParam hpinternal;
|
||||
hpinternal.address=ret;
|
||||
hpinternal.user_value=em_address;
|
||||
hpinternal.text_fun=(decltype(hpinternal.text_fun))op.hookfunc;
|
||||
hpinternal.filter_fun=(decltype(hpinternal.filter_fun))op.filterfun;
|
||||
NewHook(hpinternal,op.hookname);
|
||||
};
|
||||
NewHook(hpinternal,"DoJitPtrRet");
|
||||
};
|
||||
|
||||
return NewHook(hp,"PPSSPPDoJit");
|
||||
}
|
||||
|
||||
bool PPSSPP::attach_function()
|
||||
{
|
||||
return PPSSPPinithooksearch()| hookPPSSPPDoJit();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
bool ULJS00403_filter(void* data, size_t* len, HookParam* hp){
|
||||
std::string result = std::string((char*)data,*len);
|
||||
@ -402,11 +287,10 @@ void QNPJH50909(hook_stack* stack, HookParam* hp, uintptr_t* data, uintptr_t* sp
|
||||
if(0x6e87==*(WORD*)*data)*len=0;
|
||||
if(0x000a==*(WORD*)*data)*len=0;
|
||||
}
|
||||
|
||||
|
||||
namespace{
|
||||
auto _=[](){
|
||||
emfunctionhooks={
|
||||
namespace ppsspp{
|
||||
std::unordered_map<uintptr_t,emfuncinfo> loademfunctionhooks()
|
||||
{
|
||||
return {
|
||||
/*
|
||||
0x883b0bc: mainHandler.bind_(null, 2), // a2 - choices (un-formated)
|
||||
0x883cf04: mainHandler.bind_(null, 3), // a3 - choices + nameX2
|
||||
@ -436,6 +320,9 @@ auto _=[](){
|
||||
{0x88eeba4,{"Gekka Ryouran Romance",simple932getter<0,0>,ULJM05943F,L"ULJM05943"}},// a0 - monologue text
|
||||
{0x8875e0c,{"Gekka Ryouran Romance",simple932getter<1,6>,ULJM05943F,L"ULJM05943"}},// a1 - dialogue text
|
||||
};
|
||||
return 1;
|
||||
}();
|
||||
}
|
||||
}
|
||||
}
|
||||
bool PPSSPP::attach_function()
|
||||
{
|
||||
return InsertPPSSPPcommonhooks();
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
|
||||
add_library(commonengine mages/mages.cpp v8/v8.cpp python/python2.cpp python/python3.cpp python/python.cpp pchooks/pchooks.cpp)
|
||||
add_library(commonengine ppsspp/ppsspp.cpp mages/mages.cpp v8/v8.cpp python/python2.cpp python/python3.cpp python/python.cpp pchooks/pchooks.cpp)
|
||||
target_precompile_headers(commonengine REUSE_FROM pch)
|
||||
|
||||
|
@ -1,105 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
// ppsspp/funcinfo.h
|
||||
// 12/26/2014
|
||||
// See: https://github.com/hrydgard/ppsspp
|
||||
|
||||
// Core/HLE (High Level Emulator)
|
||||
// - sceCcc
|
||||
// #void sceCccSetTable(u32 jis2ucs, u32 ucs2jis)
|
||||
// int sceCccUTF8toUTF16(u32 dstAddr, u32 dstSize, u32 srcAddr)
|
||||
// int sceCccUTF8toSJIS(u32 dstAddr, u32 dstSize, u32 srcAddr)
|
||||
// int sceCccUTF16toUTF8(u32 dstAddr, u32 dstSize, u32 srcAddr)
|
||||
// int sceCccUTF16toSJIS(u32 dstAddr, u32 dstSize, u32 srcAddr)
|
||||
// int sceCccSJIStoUTF8(u32 dstAddr, u32 dstSize, u32 srcAddr)
|
||||
// int sceCccSJIStoUTF16(u32 dstAddr, u32 dstSize, u32 srcAddr)
|
||||
// int sceCccStrlenUTF8(u32 strAddr)
|
||||
// int sceCccStrlenUTF16(u32 strAddr)
|
||||
// int sceCccStrlenSJIS(u32 strAddr)
|
||||
// u32 sceCccEncodeUTF8(u32 dstAddrAddr, u32 ucs)
|
||||
// void sceCccEncodeUTF16(u32 dstAddrAddr, u32 ucs)
|
||||
// u32 sceCccEncodeSJIS(u32 dstAddrAddr, u32 jis)
|
||||
// u32 sceCccDecodeUTF8(u32 dstAddrAddr)
|
||||
// u32 sceCccDecodeUTF16(u32 dstAddrAddr)
|
||||
// u32 sceCccDecodeSJIS(u32 dstAddrAddr)
|
||||
// int sceCccIsValidUTF8(u32 c)
|
||||
// int sceCccIsValidUTF16(u32 c)
|
||||
// int sceCccIsValidSJIS(u32 c)
|
||||
// int sceCccIsValidUCS2(u32 c)
|
||||
// int sceCccIsValidUCS4(u32 c)
|
||||
// int sceCccIsValidJIS(u32 c)
|
||||
// int sceCccIsValidUnicode(u32 c)
|
||||
// #u32 sceCccSetErrorCharUTF8(u32 c)
|
||||
// #u32 sceCccSetErrorCharUTF16(u32 c)
|
||||
// #u32 sceCccSetErrorCharSJIS(u32 c)
|
||||
// u32 sceCccUCStoJIS(u32 c, u32 alt)
|
||||
// u32 sceCccJIStoUCS(u32 c, u32 alt)
|
||||
// - sceFont: search charCode
|
||||
// int sceFontGetCharInfo(u32 fontHandle, u32 charCode, u32 charInfoPtr)
|
||||
// int sceFontGetShadowInfo(u32 fontHandle, u32 charCode, u32 charInfoPtr)
|
||||
// int sceFontGetCharImageRect(u32 fontHandle, u32 charCode, u32 charRectPtr)
|
||||
// int sceFontGetShadowImageRect(u32 fontHandle, u32 charCode, u32 charRectPtr)
|
||||
// int sceFontGetCharGlyphImage(u32 fontHandle, u32 charCode, u32 glyphImagePtr)
|
||||
// int sceFontGetCharGlyphImage_Clip(u32 fontHandle, u32 charCode, u32 glyphImagePtr, int clipXPos, int clipYPos, int clipWidth, int clipHeight)
|
||||
// #int sceFontSetAltCharacterCode(u32 fontLibHandle, u32 charCode)
|
||||
// int sceFontGetShadowGlyphImage(u32 fontHandle, u32 charCode, u32 glyphImagePtr)
|
||||
// int sceFontGetShadowGlyphImage_Clip(u32 fontHandle, u32 charCode, u32 glyphImagePtr, int clipXPos, int clipYPos, int clipWidth, int clipHeight)
|
||||
// - sceKernelInterrupt
|
||||
// u32 sysclib_strcat(u32 dst, u32 src)
|
||||
// int sysclib_strcmp(u32 dst, u32 src)
|
||||
// u32 sysclib_strcpy(u32 dst, u32 src)
|
||||
// u32 sysclib_strlen(u32 src)
|
||||
//
|
||||
// Sample debug string:
|
||||
// 006EFD8E PUSH PPSSPPWi.00832188 ASCII "sceCccEncodeSJIS(%08x, U+%04x)"
|
||||
// Corresponding source code in sceCcc:
|
||||
// ERROR_LOG(HLE, "sceCccEncodeSJIS(%08x, U+%04x): invalid pointer", dstAddrAddr, jis);
|
||||
|
||||
struct PPSSPPFunction
|
||||
{
|
||||
const char *hookName; // hook name
|
||||
size_t argIndex; // argument index
|
||||
unsigned long hookType; // hook parameter type
|
||||
unsigned long hookSplit; // hook parameter split, positive: stack, negative: registers
|
||||
const char *pattern; // debug string used within the function
|
||||
};
|
||||
|
||||
// jichi 7/14/2014: UTF-8 is treated as STRING
|
||||
// http://867258173.diandian.com/post/2014-06-26/40062099618
|
||||
// sceFontGetCharGlyphImage_Clip
|
||||
// Sample game: [KID] Monochrome: sceFontGetCharInfo, sceFontGetCharGlyphImage_Clip
|
||||
//
|
||||
// Example: { L"sceFontGetCharInfo", 2, CODEC_UTF16, 4, "sceFontGetCharInfo(" }
|
||||
// Text is at arg2, using arg1 as split
|
||||
#define PPSSPP_FUNCTIONS_INITIALIZER \
|
||||
{ "sceCccStrlenSJIS", 1, USING_STRING, 0, "sceCccStrlenSJIS(" } \
|
||||
, { "sceCccStrlenUTF8", 1, CODEC_UTF8, 0, "sceCccStrlenUTF8(" } \
|
||||
, { "sceCccStrlenUTF16", 1, CODEC_UTF16, 0, "sceCccStrlenUTF16(" } \
|
||||
\
|
||||
, { "sceCccSJIStoUTF8", 3, CODEC_UTF8, 0, "sceCccSJIStoUTF8(" } \
|
||||
, { "sceCccSJIStoUTF16", 3, USING_STRING, 0, "sceCccSJIStoUTF16(" } \
|
||||
, { "sceCccUTF8toSJIS", 3, CODEC_UTF8, 0, "sceCccUTF8toSJIS(" } \
|
||||
, { "sceCccUTF8toUTF16", 3, CODEC_UTF8, 0, "sceCccUTF8toUTF16(" } \
|
||||
, { "sceCccUTF16toSJIS", 3, CODEC_UTF16, 0, "sceCccUTF16toSJIS(" } \
|
||||
, { "sceCccUTF16toUTF8", 3, CODEC_UTF16, 0, "sceCccUTF16toUTF8(" } \
|
||||
\
|
||||
, { "sceFontGetCharInfo", 2, CODEC_UTF16, 4, "sceFontGetCharInfo(" } \
|
||||
, { "sceFontGetShadowInfo", 2, CODEC_UTF16, 4, "sceFontGetShadowInfo("} \
|
||||
, { "sceFontGetCharImageRect", 2, CODEC_UTF16, 4, "sceFontGetCharImageRect(" } \
|
||||
, { "sceFontGetShadowImageRect", 2, CODEC_UTF16, 4, "sceFontGetShadowImageRect(" } \
|
||||
, { "sceFontGetCharGlyphImage", 2, CODEC_UTF16, 4, "sceFontGetCharGlyphImage(" } \
|
||||
, { "sceFontGetCharGlyphImage_Clip", 2, CODEC_UTF16, 4, "sceFontGetCharGlyphImage_Clip(" } \
|
||||
, { "sceFontGetShadowGlyphImage", 2, CODEC_UTF16, 4, "sceFontGetShadowGlyphImage(" } \
|
||||
, { "sceFontGetShadowGlyphImage_Clip", 2, CODEC_UTF16, 4, "sceFontGetShadowGlyphImage_Clip(" } \
|
||||
\
|
||||
, { "sysclib_strcat", 2, USING_STRING, 0, "Untested sysclib_strcat(" } \
|
||||
, { "sysclib_strcpy", 2, USING_STRING, 0, "Untested sysclib_strcpy(" } \
|
||||
, { "sysclib_strlen", 1, USING_STRING, 0, "Untested sysclib_strlen(" }
|
||||
|
||||
// Disabled as I am not sure how to deal with the source string
|
||||
//, { "sceCccEncodeSJIS", 2, USING_STRING, 0, "sceCccEncodeSJIS(" }
|
||||
//, { "sceCccEncodeUTF8", 2, CODEC_UTF8, 0, "sceCccEncodeUTF8(" }
|
||||
//, { "sceCccEncodeUTF16", 2, CODEC_UTF16, 0, "sceCccEncodeUTF16(" }
|
||||
//, { "sysclib_strcmp", 2, USING_STRING, 0, "Untested sysclib_strcmp(" }
|
||||
|
||||
// EOF
|
329
LunaHook/engines/ppsspp/ppsspp.cpp
Normal file
329
LunaHook/engines/ppsspp/ppsspp.cpp
Normal file
@ -0,0 +1,329 @@
|
||||
|
||||
#include"engine.h"
|
||||
#include"util/util.h"
|
||||
#include"psputils.hpp"
|
||||
// See: https://github.com/hrydgard/ppsspp
|
||||
|
||||
// Core/HLE (High Level Emulator)
|
||||
// - sceCcc
|
||||
// #void sceCccSetTable(u32 jis2ucs, u32 ucs2jis)
|
||||
// int sceCccUTF8toUTF16(u32 dstAddr, u32 dstSize, u32 srcAddr)
|
||||
// int sceCccUTF8toSJIS(u32 dstAddr, u32 dstSize, u32 srcAddr)
|
||||
// int sceCccUTF16toUTF8(u32 dstAddr, u32 dstSize, u32 srcAddr)
|
||||
// int sceCccUTF16toSJIS(u32 dstAddr, u32 dstSize, u32 srcAddr)
|
||||
// int sceCccSJIStoUTF8(u32 dstAddr, u32 dstSize, u32 srcAddr)
|
||||
// int sceCccSJIStoUTF16(u32 dstAddr, u32 dstSize, u32 srcAddr)
|
||||
// int sceCccStrlenUTF8(u32 strAddr)
|
||||
// int sceCccStrlenUTF16(u32 strAddr)
|
||||
// int sceCccStrlenSJIS(u32 strAddr)
|
||||
// u32 sceCccEncodeUTF8(u32 dstAddrAddr, u32 ucs)
|
||||
// void sceCccEncodeUTF16(u32 dstAddrAddr, u32 ucs)
|
||||
// u32 sceCccEncodeSJIS(u32 dstAddrAddr, u32 jis)
|
||||
// u32 sceCccDecodeUTF8(u32 dstAddrAddr)
|
||||
// u32 sceCccDecodeUTF16(u32 dstAddrAddr)
|
||||
// u32 sceCccDecodeSJIS(u32 dstAddrAddr)
|
||||
// int sceCccIsValidUTF8(u32 c)
|
||||
// int sceCccIsValidUTF16(u32 c)
|
||||
// int sceCccIsValidSJIS(u32 c)
|
||||
// int sceCccIsValidUCS2(u32 c)
|
||||
// int sceCccIsValidUCS4(u32 c)
|
||||
// int sceCccIsValidJIS(u32 c)
|
||||
// int sceCccIsValidUnicode(u32 c)
|
||||
// #u32 sceCccSetErrorCharUTF8(u32 c)
|
||||
// #u32 sceCccSetErrorCharUTF16(u32 c)
|
||||
// #u32 sceCccSetErrorCharSJIS(u32 c)
|
||||
// u32 sceCccUCStoJIS(u32 c, u32 alt)
|
||||
// u32 sceCccJIStoUCS(u32 c, u32 alt)
|
||||
// - sceFont: search charCode
|
||||
// int sceFontGetCharInfo(u32 fontHandle, u32 charCode, u32 charInfoPtr)
|
||||
// int sceFontGetShadowInfo(u32 fontHandle, u32 charCode, u32 charInfoPtr)
|
||||
// int sceFontGetCharImageRect(u32 fontHandle, u32 charCode, u32 charRectPtr)
|
||||
// int sceFontGetShadowImageRect(u32 fontHandle, u32 charCode, u32 charRectPtr)
|
||||
// int sceFontGetCharGlyphImage(u32 fontHandle, u32 charCode, u32 glyphImagePtr)
|
||||
// int sceFontGetCharGlyphImage_Clip(u32 fontHandle, u32 charCode, u32 glyphImagePtr, int clipXPos, int clipYPos, int clipWidth, int clipHeight)
|
||||
// #int sceFontSetAltCharacterCode(u32 fontLibHandle, u32 charCode)
|
||||
// int sceFontGetShadowGlyphImage(u32 fontHandle, u32 charCode, u32 glyphImagePtr)
|
||||
// int sceFontGetShadowGlyphImage_Clip(u32 fontHandle, u32 charCode, u32 glyphImagePtr, int clipXPos, int clipYPos, int clipWidth, int clipHeight)
|
||||
// - sceKernelInterrupt
|
||||
// u32 sysclib_strcat(u32 dst, u32 src)
|
||||
// int sysclib_strcmp(u32 dst, u32 src)
|
||||
// u32 sysclib_strcpy(u32 dst, u32 src)
|
||||
// u32 sysclib_strlen(u32 src)
|
||||
//
|
||||
// Sample debug string:
|
||||
// 006EFD8E PUSH PPSSPPWi.00832188 ASCII "sceCccEncodeSJIS(%08x, U+%04x)"
|
||||
// Corresponding source code in sceCcc:
|
||||
// ERROR_LOG(HLE, "sceCccEncodeSJIS(%08x, U+%04x): invalid pointer", dstAddrAddr, jis);
|
||||
|
||||
struct PPSSPPFunction
|
||||
{
|
||||
const char *hookName; // hook name
|
||||
int argIndex; // argument index
|
||||
uint64_t hookType; // hook parameter type
|
||||
int hookSplit; // hook parameter split, positive: stack, negative: registers
|
||||
const char *pattern; // debug string used within the function
|
||||
};
|
||||
|
||||
uint64_t findleaaddr(uint64_t addr,uint64_t start,uint64_t end)
|
||||
{
|
||||
for(auto _addr=start;_addr<end;_addr+=1)
|
||||
{
|
||||
auto lea=(*(WORD*)_addr);
|
||||
if(lea!=0x8d4c&&lea!=0x8d48)
|
||||
continue;
|
||||
|
||||
auto offset=*(DWORD*)(_addr+3);
|
||||
auto refaddr=(offset)+_addr+7;
|
||||
if(refaddr==addr)
|
||||
return _addr;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool InsertPPSSPPHLEHooks()
|
||||
{
|
||||
auto functions=std::vector<PPSSPPFunction>{
|
||||
|
||||
//https://github.com/hrydgard/ppsspp/blob/master/Core/HLE/sceCcc.cpp
|
||||
{ "sceCccStrlenSJIS", GETARG1, USING_STRING, 0, "sceCccStrlenSJIS(" } ,
|
||||
{ "sceCccStrlenUTF8", GETARG1, CODEC_UTF8|USING_STRING, 0, "sceCccStrlenUTF8(" } ,
|
||||
{ "sceCccStrlenUTF16", GETARG1, CODEC_UTF16|USING_STRING, 0, "sceCccStrlenUTF16(" } ,
|
||||
|
||||
{ "sceCccSJIStoUTF8", GETARG3, USING_STRING, 0, "sceCccSJIStoUTF8(" } ,
|
||||
{ "sceCccSJIStoUTF16", GETARG3, USING_STRING, 0, "sceCccSJIStoUTF16(" } ,
|
||||
{ "sceCccUTF8toSJIS", GETARG3, CODEC_UTF8|USING_STRING, 0, "sceCccUTF8toSJIS(" } ,
|
||||
{ "sceCccUTF8toUTF16", GETARG3, CODEC_UTF8|USING_STRING, 0, "sceCccUTF8toUTF16(" } ,
|
||||
{ "sceCccUTF16toSJIS", GETARG3, CODEC_UTF16|USING_STRING, 0, "sceCccUTF16toSJIS(" } ,
|
||||
{ "sceCccUTF16toUTF8", GETARG3, CODEC_UTF16|USING_STRING, 0, "sceCccUTF16toUTF8(" } ,
|
||||
|
||||
//https://github.com/hrydgard/ppsspp/blob/master/Core/HLE/sceFont.cpp
|
||||
{ "sceFontGetCharInfo", GETARG2, CODEC_UTF16, GETARG1, "sceFontGetCharInfo(" } ,
|
||||
{ "sceFontGetShadowInfo", GETARG2, CODEC_UTF16, GETARG1, "sceFontGetShadowInfo("} ,
|
||||
{ "sceFontGetCharImageRect", GETARG2, CODEC_UTF16, GETARG1, "sceFontGetCharImageRect(" } ,
|
||||
{ "sceFontGetShadowImageRect", GETARG2, CODEC_UTF16, GETARG1, "sceFontGetShadowImageRect(" } ,
|
||||
{ "sceFontGetCharGlyphImage", GETARG2, CODEC_UTF16, GETARG1, "sceFontGetCharGlyphImage(" } ,
|
||||
{ "sceFontGetCharGlyphImage_Clip", GETARG2, CODEC_UTF16, GETARG1, "sceFontGetCharGlyphImage_Clip(" } ,
|
||||
{ "sceFontGetShadowGlyphImage", GETARG2, CODEC_UTF16, GETARG1, "sceFontGetShadowGlyphImage(" } ,
|
||||
{ "sceFontGetShadowGlyphImage_Clip", GETARG2, CODEC_UTF16, GETARG1, "sceFontGetShadowGlyphImage_Clip(" } ,
|
||||
|
||||
//https://github.com/hrydgard/ppsspp/blob/master/Core/HLE/sceKernelInterrupt.cpp
|
||||
{ "sysclib_strcat", GETARG2, USING_STRING, 0, "Untested sysclib_strcat(" } ,
|
||||
{ "sysclib_strcpy", GETARG2, USING_STRING, 0, "Untested sysclib_strcpy(" } ,
|
||||
{ "sysclib_strlen", GETARG1, USING_STRING, 0, "Untested sysclib_strlen(" }
|
||||
|
||||
// Disabled as I am not sure how to deal with the source string
|
||||
//, { "sceCccEncodeSJIS", 2, USING_STRING, 0, "sceCccEncodeSJIS(" }
|
||||
//, { "sceCccEncodeUTF8", 2, CODEC_UTF8, 0, "sceCccEncodeUTF8(" }
|
||||
//, { "sceCccEncodeUTF16", 2, CODEC_UTF16, 0, "sceCccEncodeUTF16(" }
|
||||
//, { "sysclib_strcmp", 2, USING_STRING, 0, "Untested sysclib_strcmp(" }
|
||||
};
|
||||
auto succ=false;
|
||||
for (auto&& function :functions) {
|
||||
auto addr = MemDbg::findBytes(function.pattern, ::strlen(function.pattern), processStartAddress, processStopAddress);
|
||||
if(!addr)continue;
|
||||
#ifndef _WIN64
|
||||
addr=MemDbg::findPushAddress(addr, processStartAddress, processStopAddress);
|
||||
if(!addr)continue;
|
||||
addr=SafeFindEnclosingAlignedFunction(addr, 0x200);
|
||||
#else
|
||||
addr=findleaaddr(addr, processStartAddress, processStopAddress);
|
||||
|
||||
if(!addr)continue;
|
||||
|
||||
BYTE sig1[]={
|
||||
0xCC,
|
||||
0x48,0x89,XX,0x24,XX,
|
||||
};
|
||||
|
||||
BYTE sig2[]={
|
||||
0xC3,
|
||||
0x48,0x89,XX,0x24,XX,
|
||||
};
|
||||
BYTE sig3[]={
|
||||
0xCC,
|
||||
0x89,XX,0x24,XX,
|
||||
};
|
||||
BYTE sig4[]={
|
||||
0xC3,
|
||||
0x89,XX,0x24,XX,
|
||||
};
|
||||
int idx=0;
|
||||
uintptr_t maxaddr=0;
|
||||
for(auto sig:{sig1,sig2,sig3,sig4})
|
||||
{
|
||||
idx+=1;
|
||||
maxaddr=max(maxaddr,reverseFindBytes(sig,(idx>2)?5:6,addr-0x500,addr,1,true));
|
||||
}
|
||||
maxaddr=max(maxaddr,MemDbg::findEnclosingAlignedFunction_strict(addr,0x500));
|
||||
|
||||
addr=maxaddr;
|
||||
#endif
|
||||
|
||||
if(!addr)continue;
|
||||
HookParam hp;
|
||||
hp.address=addr;
|
||||
hp.type = function.hookType;
|
||||
hp.offset=function.argIndex;
|
||||
hp.split = function.hookSplit;
|
||||
if (hp.split)hp.type |= USING_SPLIT;
|
||||
succ|=NewHook(hp, function.hookName);
|
||||
}
|
||||
return succ;
|
||||
}
|
||||
|
||||
bool PPSSPPinithooksearch(){
|
||||
bool found = false;
|
||||
SYSTEM_INFO systemInfo;
|
||||
GetNativeSystemInfo(&systemInfo);
|
||||
for (BYTE* probe = NULL; probe < systemInfo.lpMaximumApplicationAddress;)
|
||||
{
|
||||
MEMORY_BASIC_INFORMATION info;
|
||||
if (!VirtualQuery(probe, &info, sizeof(info)))
|
||||
{
|
||||
probe += systemInfo.dwPageSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (info.RegionSize == 0x1f00000 && info.Protect == PAGE_READWRITE && info.Type == MEM_MAPPED)
|
||||
{
|
||||
found = true;
|
||||
ConsoleOutput("PPSSPP memory found: searching for hooks should yield working hook codes");
|
||||
#ifndef _WIN64
|
||||
// PPSSPP 1.8.0 compiles jal to sub dword ptr [ebp+0x360],??
|
||||
memcpy(spDefault.pattern, Array<BYTE>{ 0x83, 0xAD, 0x60, 0x03, 0x00, 0x00 }, spDefault.length = 6);
|
||||
#else
|
||||
// PPSSPP 1.8.0 compiles jal to sub dword ptr [r14+0x360],??
|
||||
memcpy(spDefault.pattern, Array<BYTE>{ 0x41, 0x83, 0xae, 0x60, 0x03, 0x00, 0x00 }, spDefault.length = 7);
|
||||
#endif
|
||||
spDefault.offset = 0;
|
||||
spDefault.minAddress = 0;
|
||||
spDefault.maxAddress = -1ULL;
|
||||
spDefault.padding = (uintptr_t)probe - 0x8000000;
|
||||
spDefault.hookPostProcessor = [](HookParam& hp)
|
||||
{
|
||||
hp.type |= NO_CONTEXT | USING_SPLIT | SPLIT_INDIRECT;
|
||||
#ifndef _WIN64
|
||||
hp.split = get_reg(regs::ebp);
|
||||
hp.split_index =get_reg(regs::eax); // this is where PPSSPP 1.8.0 stores its return address stack
|
||||
#else
|
||||
hp.split = get_reg(regs::r14);
|
||||
hp.split_index = -8; // this is where PPSSPP 1.8.0 stores its return address stack
|
||||
#endif
|
||||
};
|
||||
}
|
||||
probe += info.RegionSize;
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
uintptr_t getDoJitAddress() {
|
||||
#ifndef _WIN64
|
||||
auto string1="Jump target too far away, needs indirect register";
|
||||
auto string2="Jump target too far away, needs force5Bytes = true";
|
||||
auto addr1 = MemDbg::findBytes(string1, ::strlen(string1), processStartAddress, processStopAddress);
|
||||
auto addr2 = MemDbg::findBytes(string2, ::strlen(string2), processStartAddress, processStopAddress);
|
||||
|
||||
if(addr1==0||addr2==0)return 0;
|
||||
//都是被push两次,但是都是第一个
|
||||
addr1=MemDbg::findPushAddress(addr1, processStartAddress, processStopAddress);
|
||||
addr2=MemDbg::findPushAddress(addr2, processStartAddress, processStopAddress);
|
||||
if(addr1==0||addr2==0)return 0;
|
||||
addr1=MemDbg::findEnclosingAlignedFunction_strict(addr1,0x100);
|
||||
addr2=MemDbg::findEnclosingAlignedFunction_strict(addr2,0x100);
|
||||
if(addr1==0||addr2==0||addr1!=addr2)return 0;
|
||||
auto xrefs=findxref_reverse_checkcallop(addr1,processStartAddress,processStopAddress,0xe8);
|
||||
if(xrefs.size()!=28)return 0;
|
||||
|
||||
addr1=MemDbg::findEnclosingAlignedFunction_strict(xrefs[28-1-3],0x400);
|
||||
addr2=MemDbg::findEnclosingAlignedFunction_strict(xrefs[28-1-4],0x400);
|
||||
|
||||
if(addr1==0||addr2==0||addr1!=addr2)return 0;
|
||||
return addr1;
|
||||
#else
|
||||
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;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
auto DoJitSig2 = "C7 83 ?? 0? 00 00 11 00 00 00 F6 83 ?? 0? 00 00 01 ?? ?? ?? ?? ?? ?? ?? C7 83 ?? 0? 00 00 E4 00 00 00";
|
||||
first=find_pattern(DoJitSig2,processStartAddress,processStopAddress);
|
||||
if (first) {
|
||||
first=MemDbg::findEnclosingAlignedFunction_strict(first,0x400);
|
||||
return first;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
namespace ppsspp{
|
||||
|
||||
bool checkiscurrentgame(const emfuncinfo& em){
|
||||
auto wininfos=get_proc_windows();
|
||||
for(auto&& info:wininfos){
|
||||
if(info.title.find(em._id)!=info.title.npos)return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
std::unordered_set<uintptr_t>breakpoints;
|
||||
std::unordered_map<uintptr_t,emfuncinfo>emfunctionhooks=loademfunctionhooks();
|
||||
|
||||
bool hookPPSSPPDoJit(){
|
||||
auto DoJitPtr=getDoJitAddress();
|
||||
if(DoJitPtr==0)return false;
|
||||
HookParam hp;
|
||||
hp.address=DoJitPtr;//Jit::DoJit
|
||||
ConsoleOutput("DoJitPtr %p",DoJitPtr);
|
||||
|
||||
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;
|
||||
|
||||
if(!(checkiscurrentgame(emfunctionhooks.at(em_address))))return;
|
||||
|
||||
HookParam hpinternal;
|
||||
hpinternal.user_value=em_address;
|
||||
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 ret=stack->RETADDR;
|
||||
if(breakpoints.find(ret)!=breakpoints.end())return;
|
||||
breakpoints.insert(ret);
|
||||
|
||||
auto em_address=hp->user_value;
|
||||
auto op=emfunctionhooks.at(em_address);
|
||||
|
||||
HookParam hpinternal;
|
||||
hpinternal.address=ret;
|
||||
hpinternal.user_value=em_address;
|
||||
hpinternal.text_fun=(decltype(hpinternal.text_fun))op.hookfunc;
|
||||
hpinternal.filter_fun=(decltype(hpinternal.filter_fun))op.filterfun;
|
||||
NewHook(hpinternal,op.hookname);
|
||||
};
|
||||
NewHook(hpinternal,"DoJitPtrRet");
|
||||
};
|
||||
|
||||
return NewHook(hp,"PPSSPPDoJit");
|
||||
}
|
||||
}
|
||||
bool InsertPPSSPPcommonhooks()
|
||||
{
|
||||
|
||||
auto succ=InsertPPSSPPHLEHooks();
|
||||
succ|=PPSSPPinithooksearch();
|
||||
succ|=ppsspp::hookPPSSPPDoJit();
|
||||
return succ;
|
||||
}
|
@ -1,6 +1,22 @@
|
||||
#ifndef __LUNA_PSPUILTS_H
|
||||
#define __LUNA_PSPUILTS_H
|
||||
namespace ppsspp
|
||||
{
|
||||
|
||||
struct emfuncinfo{
|
||||
const char* hookname;
|
||||
void* hookfunc;
|
||||
void* filterfun;
|
||||
const wchar_t* _id;
|
||||
};
|
||||
std::unordered_map<uintptr_t,emfuncinfo> loademfunctionhooks();
|
||||
|
||||
}
|
||||
|
||||
bool InsertPPSSPPcommonhooks();
|
||||
|
||||
|
||||
#ifndef _WIN64
|
||||
namespace{
|
||||
int PPSSPP_VERSION[4] = { 0, 9, 8, 0 }; // 0.9.8 by default
|
||||
|
||||
@ -39,4 +55,6 @@ ULONG SafeMatchBytesInPS2Memory(LPCVOID pattern, DWORD patternSize)
|
||||
return _SafeMatchBytesInMappedMemory(pattern, patternSize, XX, start, stop, step);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -87,16 +87,22 @@ inline uintptr_t regof(regs reg,hook_stack* stack){
|
||||
#define ARG1 stack[1]
|
||||
#define ARG2 stack[2]
|
||||
#define ARG3 stack[3]
|
||||
#define RETADDR eax
|
||||
#define THISCALL __thiscall
|
||||
#define THISCALLTHIS ecx
|
||||
#define GETARG1 get_stack(1)
|
||||
#define GETARG2 get_stack(2)
|
||||
#define GETARG3 get_stack(3)
|
||||
#define GETARG4 get_stack(4)
|
||||
#else
|
||||
#define ARG1 rcx
|
||||
#define ARG2 rdx
|
||||
#define ARG3 r8
|
||||
#define RETADDR rax
|
||||
#define THISCALLTHIS rcx
|
||||
#define THISCALL
|
||||
#define GETARG1 get_reg(regs::rcx)
|
||||
#define GETARG2 get_reg(regs::rdx)
|
||||
#define GETARG3 get_reg(regs::r8)
|
||||
#define GETARG4 get_reg(regs::r9)
|
||||
#endif
|
@ -328,18 +328,16 @@ uintptr_t FindFunction(const char* function)
|
||||
|
||||
}
|
||||
|
||||
#ifndef _WIN64
|
||||
|
||||
ULONG SafeFindEnclosingAlignedFunction(DWORD addr, DWORD range)
|
||||
uintptr_t SafeFindEnclosingAlignedFunction(uintptr_t addr, uintptr_t range)
|
||||
{
|
||||
ULONG r = 0;
|
||||
uintptr_t r = 0;
|
||||
__try{
|
||||
r = MemDbg::findEnclosingAlignedFunction(addr, range); // this function might raise if failed
|
||||
}__except(EXCEPTION_EXECUTE_HANDLER) {}
|
||||
return r;
|
||||
}
|
||||
|
||||
ULONG SafeFindBytes(LPCVOID pattern, DWORD patternSize, DWORD lowerBound, DWORD upperBound)
|
||||
uintptr_t SafeFindBytes(LPCVOID pattern, size_t patternSize, uintptr_t lowerBound, uintptr_t upperBound)
|
||||
{
|
||||
ULONG r = 0;
|
||||
__try{
|
||||
@ -347,6 +345,8 @@ ULONG SafeFindBytes(LPCVOID pattern, DWORD patternSize, DWORD lowerBound, DWORD
|
||||
}__except(EXCEPTION_EXECUTE_HANDLER) {}
|
||||
return r;
|
||||
}
|
||||
#ifndef _WIN64
|
||||
|
||||
// jichi 7/17/2014: Search mapped memory for emulators
|
||||
ULONG _SafeMatchBytesInMappedMemory(LPCVOID pattern, DWORD patternSize, BYTE wildcard,
|
||||
ULONG start, ULONG stop, ULONG step)
|
||||
@ -443,7 +443,7 @@ uintptr_t findfuncstart(uintptr_t addr,uintptr_t range){
|
||||
#endif
|
||||
|
||||
|
||||
uintptr_t reverseFindBytes(const BYTE* pattern, int length, uintptr_t start, uintptr_t end) {
|
||||
uintptr_t reverseFindBytes(const BYTE* pattern, int length, uintptr_t start, uintptr_t end,int offset,bool checkalign) {
|
||||
for (end -= length; end >= start; end -= 1) {
|
||||
bool success=true;
|
||||
for(int i=0;i<length;i++){
|
||||
@ -451,7 +451,15 @@ uintptr_t reverseFindBytes(const BYTE* pattern, int length, uintptr_t start, uin
|
||||
success=false;break;
|
||||
}
|
||||
}
|
||||
if(success)return end;
|
||||
if(success)
|
||||
{
|
||||
auto ret=end+offset;
|
||||
|
||||
if(checkalign && ret&0xf)
|
||||
continue;
|
||||
|
||||
return ret;
|
||||
}
|
||||
// if (memcmp(pattern, (const BYTE*)(end), length) == 0) {
|
||||
// return end;
|
||||
// }
|
||||
|
@ -45,10 +45,10 @@ uintptr_t FindFunction(const char* function);
|
||||
} // namespace Util
|
||||
|
||||
|
||||
uintptr_t SafeFindEnclosingAlignedFunction(uintptr_t addr, uintptr_t range);
|
||||
uintptr_t SafeFindBytes(LPCVOID pattern, size_t patternSize, uintptr_t lowerBound, uintptr_t upperBound);
|
||||
#ifndef _WIN64
|
||||
|
||||
ULONG SafeFindEnclosingAlignedFunction(DWORD addr, DWORD range);
|
||||
ULONG SafeFindBytes(LPCVOID pattern, DWORD patternSize, DWORD lowerBound, DWORD upperBound);
|
||||
ULONG _SafeMatchBytesInMappedMemory(LPCVOID pattern, DWORD patternSize, BYTE wildcard,
|
||||
ULONG start, ULONG stop, ULONG step);
|
||||
ULONG SafeMatchBytesInGCMemory(LPCVOID pattern, DWORD patternSize);
|
||||
@ -60,7 +60,7 @@ uintptr_t findfuncstart(uintptr_t addr,uintptr_t range=0x100);
|
||||
#endif
|
||||
|
||||
uintptr_t find_pattern(const char* pattern,uintptr_t start,uintptr_t end);
|
||||
uintptr_t reverseFindBytes(const BYTE* pattern, int length, uintptr_t start, uintptr_t end);
|
||||
uintptr_t reverseFindBytes(const BYTE* pattern, int length, uintptr_t start, uintptr_t end,int offset=0,bool checkalign=false);
|
||||
std::vector<uintptr_t> findxref_reverse(uintptr_t addr, uintptr_t from, uintptr_t to);
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user