Static hle implementation

This commit is contained in:
RipleyTom 2018-10-26 12:08:45 +02:00 committed by Ivan
parent a22297f205
commit de5379a69f
7 changed files with 263 additions and 3 deletions

View file

@ -0,0 +1,177 @@
#include "stdafx.h"
#include "StaticHLE.h"
logs::channel static_hle("static_hle");
// for future use
DECLARE(ppu_module_manager::static_hle) ("static_hle", []()
{
});
std::vector<std::array<std::string, 6>> shle_patterns_list
{
{ "2BA5000778630020788400207C6B1B78419D00702C2500004D82002028A5000F", "FF", "36D0", "05C4", "sys_libc", "memcpy" },
{ "2BA5000778630020788400207C6B1B78419D00702C2500004D82002028A5000F", "5C", "87A0", "05C4", "sys_libc", "memcpy" },
{ "2B8500077CA32A14788406207C6A1B78409D009C3903000198830000788B45E4", "B4", "1453", "00D4", "sys_libc", "memset" },
{ "280500087C661B7840800020280500004D8200207CA903A69886000038C60001", "F8", "F182", "0118", "sys_libc", "memset" },
{ "2B8500077CA32A14788406207C6A1B78409D009C3903000198830000788B45E4", "70", "DFDA", "00D4", "sys_libc", "memset" },
{ "7F832000FB61FFD8FBE1FFF8FB81FFE0FBA1FFE8FBC1FFF07C7B1B787C9F2378", "FF", "25B5", "12D4", "sys_libc", "memmove" },
{ "2B850007409D00B07C6923785520077E2F800000409E00ACE8030000E9440000", "FF", "71F1", "0158", "sys_libc", "memcmp" },
{ "280500007CE32050788B0760418200E028850100786A07607C2A580040840210", "FF", "87F2", "0470", "sys_libc", "memcmp" },
{ "2B850007409D00B07C6923785520077E2F800000409E00ACE8030000E9440000", "68", "EF18", "0158", "sys_libc", "memcmp" },
};
statichle_handler::statichle_handler()
{
load_patterns();
}
statichle_handler::~statichle_handler()
{
}
bool statichle_handler::load_patterns()
{
for (int i = 0; i < shle_patterns_list.size(); i++)
{
auto& pattern = shle_patterns_list[i];
if (pattern[0].size() != 64)
{
static_hle.error("[%d]:Start pattern length != 64", i);
continue;
}
if (pattern[1].size() != 2)
{
static_hle.error("[%d]:Crc16_length != 2", i);
continue;
}
if (pattern[2].size() != 4)
{
static_hle.error("[d]:Crc16 length != 4", i);
continue;
}
if (pattern[3].size() != 4)
{
static_hle.error("[d]:Total length != 4", i);
continue;
}
shle_pattern dapat;
auto char_to_u8 = [&](u8 char1, u8 char2) -> u16
{
u8 hv, lv;
if (char1 == '.' && char2 == '.')
return 0xFFFF;
if (char1 == '.' || char2 == '.')
{
static_hle.error("[%d]:Broken byte pattern", i);
return -1;
}
hv = char1 > '9' ? char1 - 'A' + 10 : char1 - '0';
lv = char2 > '9' ? char2 - 'A' + 10 : char2 - '0';
return (hv << 4) | lv;
};
for (int j = 0; j < 32; j++)
dapat.start_pattern[j] = char_to_u8(pattern[0][j * 2], pattern[0][(j * 2) + 1]);
dapat.crc16_length = char_to_u8(pattern[1][0], pattern[1][1]);
dapat.crc16 = (char_to_u8(pattern[2][0], pattern[2][1]) << 8) | char_to_u8(pattern[2][2], pattern[2][3]);
dapat.total_length = (char_to_u8(pattern[3][0], pattern[3][1]) << 8) | char_to_u8(pattern[3][2], pattern[3][3]);
dapat.module = pattern[4];
dapat.name = pattern[5];
dapat.fnid = ppu_generate_id(dapat.name.c_str());
static_hle.success("Added a pattern for %s(id:0x%X)", dapat.name, dapat.fnid);
hle_patterns.push_back(std::move(dapat));
}
return true;
}
#define POLY 0x8408
uint16_t statichle_handler::gen_CRC16(const uint8_t* data_p, size_t length)
{
unsigned char i;
unsigned int data;
if (length == 0)
return 0;
unsigned int crc = 0xFFFF;
do
{
data = *data_p++;
for (i = 0; i < 8; i++)
{
if ((crc ^ data) & 1)
crc = (crc >> 1) ^ POLY;
else
crc >>= 1;
data >>= 1;
}
} while (--length != 0);
crc = ~crc;
data = crc;
crc = (crc << 8) | ((data >> 8) & 0xff);
return (unsigned short)(crc);
}
bool statichle_handler::check_against_patterns(vm::cptr<u8>& data, u32 size, u32 addr)
{
for (auto& pat : hle_patterns)
{
if (size < pat.total_length)
continue;
// check start pattern
int i = 0;
for (i = 0; i < 32; i++)
{
if (pat.start_pattern[i] == 0xFFFF)
continue;
if (data[i] != pat.start_pattern[i])
break;
}
if (i != 32)
continue;
// start pattern ok, checking middle part
if (pat.crc16_length != 0)
if (gen_CRC16(&data[32], pat.crc16_length) != pat.crc16)
continue;
// we got a match!
static_hle.success("Found function %s at 0x%x", pat.name, addr);
// patch the code
const auto smodule = ppu_module_manager::get_module(pat.module);
if (smodule == nullptr)
{
static_hle.error("Couldn't find module: %s", pat.module);
return false;
}
const auto sfunc = &smodule->functions.at(pat.fnid);
const u32 target = ppu_function_manager::addr + 8 * sfunc->index;
// write stub
vm::write32(addr, ppu_instructions::LIS(0, (target&0xFFFF0000)>>16));
vm::write32(addr+4, ppu_instructions::ORI(0, 0, target&0xFFFF));
vm::write32(addr+8, ppu_instructions::MTCTR(0));
vm::write32(addr+12, ppu_instructions::BCTR());
return true;
}
return false;
}

View file

@ -0,0 +1,33 @@
#pragma once
#include "../../Utilities/types.h"
#include "Emu/Cell/PPUModule.h"
#include "Emu/Cell/PPUOpcodes.h"
#include <vector>
struct shle_pattern
{
u16 start_pattern[32];
u8 crc16_length;
u16 crc16;
u16 total_length;
std::string module;
std::string name;
u32 fnid;
};
class statichle_handler
{
public:
statichle_handler();
~statichle_handler();
bool load_patterns();
bool check_against_patterns(vm::cptr<u8>& data, u32 size, u32 addr);
protected:
uint16_t gen_CRC16(const uint8_t* data_p, size_t length);
std::vector<shle_pattern> hle_patterns;
};

View file

@ -1,17 +1,43 @@
#include "stdafx.h"
#include "stdafx.h"
#include "Emu/System.h"
#include "Emu/Cell/PPUModule.h"
LOG_CHANNEL(sys_libc);
void sys_libc_memcpy(vm::ptr<void> dst, vm::cptr<void> src, u32 size)
vm::ptr<void> sys_libc_memcpy(vm::ptr<void> dst, vm::cptr<void> src, u32 size)
{
sys_libc.trace("memcpy(dst=*0x%x, src=*0x%x, size=0x%x)", dst, src, size);
::memcpy(dst.get_ptr(), src.get_ptr(), size);
return dst;
}
vm::ptr<void> sys_libc_memset(vm::ptr<void> dst, s32 value, u32 size)
{
sys_libc.trace("memset(dst=*0x%x, value=0x%x, size=0x%x)", dst, value, size);
::memset(dst.get_ptr(), value, size);
return dst;
}
vm::ptr<void> sys_libc_memmove(vm::ptr<void> dst, vm::ptr<void> src, u32 size)
{
sys_libc.trace("memmove(dst=*0x%x, src=*0x%x, size=0x%x)", dst, src, size);
::memmove(dst.get_ptr(), src.get_ptr(), size);
return dst;
}
u32 sys_libc_memcmp(vm::ptr<void> buf1, vm::ptr<void> buf2, u32 size)
{
sys_libc.trace("memcmp(buf1=*0x%x, buf2=*0x%x, size=0x%x)", buf1, buf2, size);
return ::memcmp(buf1.get_ptr(), buf2.get_ptr(), size);
}
DECLARE(ppu_module_manager::sys_libc)("sys_libc", []()
{
REG_FNID(sys_libc, "memcpy", sys_libc_memcpy)/*.flag(MFF_FORCED_HLE)*/;
REG_FNID(sys_libc, "memset", sys_libc_memset);
REG_FNID(sys_libc, "memmove", sys_libc_memmove);
REG_FNID(sys_libc, "memcmp", sys_libc_memcmp);
});

View file

@ -1,4 +1,4 @@
#include "stdafx.h"
#include "stdafx.h"
#include "Utilities/VirtualMemory.h"
#include "Utilities/bin_patch.h"
#include "Crypto/sha1.h"
@ -14,6 +14,8 @@
#include "Emu/Cell/lv2/sys_prx.h"
#include "Emu/Cell/lv2/sys_memory.h"
#include "Emu/Cell/Modules/StaticHLE.h"
#include <map>
#include <set>
#include <algorithm>
@ -255,6 +257,7 @@ static void ppu_initialize_modules(const std::shared_ptr<ppu_linkage_info>& link
&ppu_module_manager::sysPrxForUser,
&ppu_module_manager::sys_libc,
&ppu_module_manager::sys_lv2dbg,
&ppu_module_manager::static_hle,
};
// Initialize double-purpose fake OPD array for HLE functions
@ -1136,6 +1139,18 @@ void ppu_load_exec(const ppu_exec_object& elf)
// Initialize HLE modules
ppu_initialize_modules(link);
// Static HLE patching
if (g_cfg.core.hook_functions)
{
auto shle = fxm::get_always<statichle_handler>();
for (u32 i = _main->segs[0].addr; i < (_main->segs[0].addr + _main->segs[0].size); i += 4)
{
vm::cptr<u8> _ptr = vm::cast(i);
shle->check_against_patterns(_ptr, (_main->segs[0].addr + _main->segs[0].size) - i, i);
}
}
// Load other programs
for (auto& prog : elf.progs)
{

View file

@ -264,6 +264,7 @@ public:
static const ppu_static_module sysPrxForUser;
static const ppu_static_module sys_libc;
static const ppu_static_module sys_lv2dbg;
static const ppu_static_module static_hle;
};
template <auto* Func>

View file

@ -114,6 +114,7 @@
<ClCompile Include="..\Utilities\VirtualMemory.cpp" />
<ClCompile Include="Emu\Cell\lv2\sys_gpio.cpp" />
<ClCompile Include="Emu\Cell\lv2\sys_net.cpp" />
<ClCompile Include="Emu\Cell\Modules\StaticHLE.cpp" />
<ClCompile Include="Emu\Cell\PPUAnalyser.cpp" />
<ClCompile Include="Emu\Cell\PPUTranslator.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
@ -402,6 +403,7 @@
<ClInclude Include="Emu\Cell\Modules\cellJpgEnc.h" />
<ClInclude Include="Emu\Cell\Modules\cellOskDialog.h" />
<ClInclude Include="Emu\Cell\Modules\cellVoice.h" />
<ClInclude Include="Emu\Cell\Modules\StaticHLE.h" />
<ClInclude Include="Emu\Cell\PPUAnalyser.h" />
<ClInclude Include="Emu\Cell\PPUTranslator.h" />
<ClInclude Include="Emu\CPU\CPUTranslator.h" />

View file

@ -752,6 +752,9 @@
<ClCompile Include="Emu\RSX\RSXFIFO.cpp">
<Filter>Emu\GPU\RSX</Filter>
</ClCompile>
<ClCompile Include="Emu\Cell\Modules\StaticHLE.cpp">
<Filter>Emu\Cell\Modules</Filter>
</ClCompile>
<ClCompile Include="Emu\RSX\Overlays\overlay_osk.cpp">
<Filter>Emu\GPU\RSX\Overlays</Filter>
</ClCompile>
@ -1456,6 +1459,9 @@
<ClInclude Include="Emu\RSX\Common\texture_cache_predictor.h">
<Filter>Emu\GPU\RSX\Common</Filter>
</ClInclude>
<ClInclude Include="Emu\Cell\Modules\StaticHLE.h">
<Filter>Emu\Cell\Modules</Filter>
</ClInclude>
<ClInclude Include="Emu\Audio\AudioBackend.h">
<Filter>Emu\Audio</Filter>
</ClInclude>