diff --git a/rpcs3/Emu/Cell/PPUInterpreter.h b/rpcs3/Emu/Cell/PPUInterpreter.h index 7e5d3b8b86..a21a524fc6 100644 --- a/rpcs3/Emu/Cell/PPUInterpreter.h +++ b/rpcs3/Emu/Cell/PPUInterpreter.h @@ -4,7 +4,6 @@ #include "Emu/SysCalls/SysCalls.h" #include "rpcs3/Ini.h" #include "Emu/System.h" -#include "Emu/SysCalls/Static.h" #include "Emu/SysCalls/Modules.h" #include "Emu/Memory/Memory.h" #include "Emu/SysCalls/lv2/sys_time.h" diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index 01b3a94b9e..205dc2b4eb 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -6,7 +6,6 @@ #include "Emu/Cell/PPUThread.h" #include "Emu/SysCalls/SysCalls.h" #include "Emu/SysCalls/Modules.h" -#include "Emu/SysCalls/Static.h" #include "Emu/Cell/PPUDecoder.h" #include "Emu/Cell/PPUInterpreter.h" #include "Emu/Cell/PPULLVMRecompiler.h" diff --git a/rpcs3/Emu/SysCalls/Modules.cpp b/rpcs3/Emu/SysCalls/Modules.cpp index 96ada9f27a..5939cf47b4 100644 --- a/rpcs3/Emu/SysCalls/Modules.cpp +++ b/rpcs3/Emu/SysCalls/Modules.cpp @@ -1,16 +1,17 @@ #include "stdafx.h" +#include "Ini.h" #include "Utilities/Log.h" #include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/SysCalls/Modules.h" #include "Emu/SysCalls/SysCalls.h" -#include "Emu/SysCalls/Static.h" #include "Emu/SysCalls/CB_FUNC.h" #include "Crypto/sha1.h" #include "ModuleManager.h" #include "Emu/Cell/PPUInstrTable.h" std::vector g_ppu_func_list; +std::vector g_ppu_func_subs; u32 add_ppu_func(ModuleFunc func) { @@ -38,6 +39,33 @@ u32 add_ppu_func(ModuleFunc func) return (u32)g_ppu_func_list.size() - 1; } +u32 add_ppu_func_sub(StaticFunc func) +{ + g_ppu_func_subs.push_back(func); + return func.index; +} + +u32 add_ppu_func_sub(const char group[8], const u64 ops[], const char* name, Module* module, ppu_func_caller func) +{ + StaticFunc sf; + sf.index = add_ppu_func(ModuleFunc(get_function_id(name), module, func)); + sf.name = name; + sf.group = *(u64*)group; + sf.found = 0; + + // TODO: check for self-inclusions, use CRC + for (u32 i = 0; ops[i]; i++) + { + SFuncOp op; + op.mask = re32((u32)(ops[i] >> 32)); + op.crc = re32((u32)(ops[i])); + if (op.mask) op.crc &= op.mask; + sf.ops.push_back(op); + } + + return add_ppu_func_sub(sf); +} + ModuleFunc* get_ppu_func_by_nid(u32 nid, u32* out_index) { for (auto& f : g_ppu_func_list) @@ -101,6 +129,7 @@ void execute_ppu_func_by_index(PPUThread& CPU, u32 index) void clear_ppu_functions() { g_ppu_func_list.clear(); + g_ppu_func_subs.clear(); } u32 get_function_id(const char* name) @@ -119,6 +148,180 @@ u32 get_function_id(const char* name) return (u32&)output[0]; } +void hook_ppu_funcs(u32* base, u32 size) +{ + size /= 4; + + if (!Ini.HLEHookStFunc.GetValue()) + return; + + // TODO: optimize search + for (u32 i = 0; i < size; i++) + { + for (u32 j = 0; j < g_ppu_func_subs.size(); j++) + { + if ((base[i] & g_ppu_func_subs[j].ops[0].mask) == g_ppu_func_subs[j].ops[0].crc) + { + bool found = true; + u32 can_skip = 0; + for (u32 k = i, x = 0; x + 1 <= g_ppu_func_subs[j].ops.size(); k++, x++) + { + if (k >= size) + { + found = false; + break; + } + + // skip NOP + if (base[k] == se32(0x60000000)) + { + x--; + continue; + } + + const u32 mask = g_ppu_func_subs[j].ops[x].mask; + const u32 crc = g_ppu_func_subs[j].ops[x].crc; + + if (!mask) + { + // TODO: define syntax + if (crc < 4) // skip various number of instructions that don't match next pattern entry + { + can_skip += crc; + k--; // process this position again + } + else if (base[k] != crc) // skippable pattern ("optional" instruction), no mask allowed + { + k--; + if (can_skip) // cannot define this behaviour properly + { + LOG_WARNING(LOADER, "hook_ppu_funcs(): can_skip = %d (unchanged)", can_skip); + } + } + else + { + if (can_skip) // cannot define this behaviour properly + { + LOG_WARNING(LOADER, "hook_ppu_funcs(): can_skip = %d (set to 0)", can_skip); + can_skip = 0; + } + } + } + else if ((base[k] & mask) != crc) // masked pattern + { + if (can_skip) + { + can_skip--; + } + else + { + found = false; + break; + } + } + else + { + can_skip = 0; + } + } + if (found) + { + LOG_NOTICE(LOADER, "Function '%s' hooked (addr=0x%x)", g_ppu_func_subs[j].name, vm::get_addr(base + i * 4)); + g_ppu_func_subs[j].found++; + base[i + 0] = re32(0x04000000 | g_ppu_func_subs[j].index); // hack + base[i + 1] = se32(0x4e800020); // blr + i += 1; // skip modified code + } + } + } + } + + // check function groups + for (u32 i = 0; i < g_ppu_func_subs.size(); i++) + { + if (g_ppu_func_subs[i].found) // start from some group + { + const u64 group = g_ppu_func_subs[i].group; + + enum GroupSearchResult : u32 + { + GSR_SUCCESS = 0, // every function from this group has been found once + GSR_MISSING = 1, // (error) some function not found + GSR_EXCESS = 2, // (error) some function found twice or more + }; + u32 res = GSR_SUCCESS; + + // analyse + for (u32 j = 0; j < g_ppu_func_subs.size(); j++) if (g_ppu_func_subs[j].group == group) + { + u32 count = g_ppu_func_subs[j].found; + + if (count == 0) // not found + { + // check if this function has been found with different pattern + for (u32 k = 0; k < g_ppu_func_subs.size(); k++) if (g_ppu_func_subs[k].group == group) + { + if (k != j && g_ppu_func_subs[k].index == g_ppu_func_subs[j].index) + { + count += g_ppu_func_subs[k].found; + } + } + if (count == 0) + { + res |= GSR_MISSING; + LOG_ERROR(LOADER, "Function '%s' not found", g_ppu_func_subs[j].name); + } + else if (count > 1) + { + res |= GSR_EXCESS; + } + } + else if (count == 1) // found + { + // ensure that this function has NOT been found with different pattern + for (u32 k = 0; k < g_ppu_func_subs.size(); k++) if (g_ppu_func_subs[k].group == group) + { + if (k != j && g_ppu_func_subs[k].index == g_ppu_func_subs[j].index) + { + if (g_ppu_func_subs[k].found) + { + res |= GSR_EXCESS; + LOG_ERROR(LOADER, "Function '%s' hooked twice", g_ppu_func_subs[j].name); + } + } + } + } + else + { + res |= GSR_EXCESS; + LOG_ERROR(LOADER, "Function '%s' hooked twice", g_ppu_func_subs[j].name); + } + } + + // clear data + for (u32 j = 0; j < g_ppu_func_subs.size(); j++) + { + if (g_ppu_func_subs[j].group == group) g_ppu_func_subs[j].found = 0; + } + + char name[9] = "????????"; + + *(u64*)name = group; + + if (res == GSR_SUCCESS) + { + LOG_SUCCESS(LOADER, "Function group [%s] successfully hooked", std::string(name, 9).c_str()); + } + else + { + LOG_ERROR(LOADER, "Function group [%s] failed:%s%s", std::string(name, 9).c_str(), + (res & GSR_MISSING ? " missing;" : ""), + (res & GSR_EXCESS ? " excess;" : "")); + } + } + } +} + Module::Module(const char* name, void(*init)()) : m_is_loaded(false) , m_name(name) diff --git a/rpcs3/Emu/SysCalls/Modules.h b/rpcs3/Emu/SysCalls/Modules.h index fc3133b539..6b724a1619 100644 --- a/rpcs3/Emu/SysCalls/Modules.h +++ b/rpcs3/Emu/SysCalls/Modules.h @@ -28,7 +28,7 @@ struct SFuncOp u32 mask; }; -struct SFunc +struct StaticFunc { u32 index; const char* name; @@ -37,8 +37,6 @@ struct SFunc u32 found; }; -class StaticFuncManager; - class Module : public LogBase { std::string m_name; @@ -118,9 +116,11 @@ void execute_ppu_func_by_index(PPUThread& CPU, u32 id); void clear_ppu_functions(); u32 get_function_id(const char* name); -u32 add_ppu_func_sub(SFunc sf); +u32 add_ppu_func_sub(StaticFunc sf); u32 add_ppu_func_sub(const char group[8], const u64 ops[], const char* name, Module* module, ppu_func_caller func); +void hook_ppu_funcs(u32* base, u32 size); + #define REG_FUNC(module, name) add_ppu_func(ModuleFunc(get_function_id(#name), &module, bind_func(name))) #define REG_UNNAMED(module, nid) add_ppu_func(ModuleFunc(0x##nid, &module, bind_func(_nid_##nid))) diff --git a/rpcs3/Emu/SysCalls/Static.cpp b/rpcs3/Emu/SysCalls/Static.cpp deleted file mode 100644 index b81c620897..0000000000 --- a/rpcs3/Emu/SysCalls/Static.cpp +++ /dev/null @@ -1,215 +0,0 @@ -#include "stdafx.h" -#include "rpcs3/Ini.h" -#include "Utilities/Log.h" -#include "Emu/SysCalls/Modules.h" -#include "Static.h" - -std::vector g_ppu_func_subs; - -u32 add_ppu_func_sub(SFunc func) -{ - g_ppu_func_subs.push_back(func); - return func.index; -} - -u32 add_ppu_func_sub(const char group[8], const u64 ops[], const char* name, Module* module, ppu_func_caller func) -{ - SFunc sf; - sf.index = add_ppu_func(ModuleFunc(get_function_id(name), module, func)); - sf.name = name; - sf.group = *(u64*)group; - sf.found = 0; - - // TODO: check for self-inclusions, use CRC - for (u32 i = 0; ops[i]; i++) - { - SFuncOp op; - op.mask = ops[i] >> 32; - op.crc = (u32)ops[i]; - if (op.mask) op.crc &= op.mask; - op.mask = re32(op.mask); - op.crc = re32(op.crc); - sf.ops.push_back(op); - } - - return add_ppu_func_sub(sf); -} - -void StaticFuncManager::StaticAnalyse(void* ptr, u32 size, u32 base) -{ - u32* data = (u32*)ptr; size /= 4; - - if(!Ini.HLEHookStFunc.GetValue()) - return; - - // TODO: optimize search - for (u32 i = 0; i < size; i++) - { - for (u32 j = 0; j < g_ppu_func_subs.size(); j++) - { - if ((data[i] & g_ppu_func_subs[j].ops[0].mask) == g_ppu_func_subs[j].ops[0].crc) - { - bool found = true; - u32 can_skip = 0; - for (u32 k = i, x = 0; x + 1 <= g_ppu_func_subs[j].ops.size(); k++, x++) - { - if (k >= size) - { - found = false; - break; - } - - // skip NOP - if (data[k] == se32(0x60000000)) - { - x--; - continue; - } - - const u32 mask = g_ppu_func_subs[j].ops[x].mask; - const u32 crc = g_ppu_func_subs[j].ops[x].crc; - - if (!mask) - { - // TODO: define syntax - if (crc < 4) // skip various number of instructions that don't match next pattern entry - { - can_skip += crc; - k--; // process this position again - } - else if (data[k] != crc) // skippable pattern ("optional" instruction), no mask allowed - { - k--; - if (can_skip) // cannot define this behaviour properly - { - LOG_WARNING(LOADER, "StaticAnalyse(): can_skip = %d (unchanged)", can_skip); - } - } - else - { - if (can_skip) // cannot define this behaviour properly - { - LOG_WARNING(LOADER, "StaticAnalyse(): can_skip = %d (set to 0)", can_skip); - can_skip = 0; - } - } - } - else if ((data[k] & mask) != crc) // masked pattern - { - if (can_skip) - { - can_skip--; - } - else - { - found = false; - break; - } - } - else - { - can_skip = 0; - } - } - if (found) - { - LOG_NOTICE(LOADER, "Function '%s' hooked (addr=0x%x)", g_ppu_func_subs[j].name, i * 4 + base); - g_ppu_func_subs[j].found++; - data[i + 0] = re32(0x04000000 | g_ppu_func_subs[j].index); // hack - data[i + 1] = se32(0x4e800020); // blr - i += 1; // skip modified code - } - } - } - } - - // check function groups - for (u32 i = 0; i < g_ppu_func_subs.size(); i++) - { - if (g_ppu_func_subs[i].found) // start from some group - { - const u64 group = g_ppu_func_subs[i].group; - - enum GroupSearchResult : u32 - { - GSR_SUCCESS = 0, // every function from this group has been found once - GSR_MISSING = 1, // (error) some function not found - GSR_EXCESS = 2, // (error) some function found twice or more - }; - u32 res = GSR_SUCCESS; - - // analyse - for (u32 j = 0; j < g_ppu_func_subs.size(); j++) if (g_ppu_func_subs[j].group == group) - { - u32 count = g_ppu_func_subs[j].found; - - if (count == 0) // not found - { - // check if this function has been found with different pattern - for (u32 k = 0; k < g_ppu_func_subs.size(); k++) if (g_ppu_func_subs[k].group == group) - { - if (k != j && g_ppu_func_subs[k].index == g_ppu_func_subs[j].index) - { - count += g_ppu_func_subs[k].found; - } - } - if (count == 0) - { - res |= GSR_MISSING; - LOG_ERROR(LOADER, "Function '%s' not found", g_ppu_func_subs[j].name); - } - else if (count > 1) - { - res |= GSR_EXCESS; - } - } - else if (count == 1) // found - { - // ensure that this function has NOT been found with different pattern - for (u32 k = 0; k < g_ppu_func_subs.size(); k++) if (g_ppu_func_subs[k].group == group) - { - if (k != j && g_ppu_func_subs[k].index == g_ppu_func_subs[j].index) - { - if (g_ppu_func_subs[k].found) - { - res |= GSR_EXCESS; - LOG_ERROR(LOADER, "Function '%s' hooked twice", g_ppu_func_subs[j].name); - } - } - } - } - else - { - res |= GSR_EXCESS; - LOG_ERROR(LOADER, "Function '%s' hooked twice", g_ppu_func_subs[j].name); - } - } - - // clear data - for (u32 j = 0; j < g_ppu_func_subs.size(); j++) - { - if (g_ppu_func_subs[j].group == group) g_ppu_func_subs[j].found = 0; - } - - char name[9] = "????????"; - - *(u64*)name = group; - - if (res == GSR_SUCCESS) - { - LOG_SUCCESS(LOADER, "Function group [%s] successfully hooked", std::string(name, 9).c_str()); - } - else - { - LOG_ERROR(LOADER, "Function group [%s] failed:%s%s", std::string(name, 9).c_str(), - (res & GSR_MISSING ? " missing;" : ""), - (res & GSR_EXCESS ? " excess;" : "")); - } - } - } -} - -void StaticFuncManager::StaticFinalize() -{ - g_ppu_func_subs.clear(); -} diff --git a/rpcs3/Emu/SysCalls/Static.h b/rpcs3/Emu/SysCalls/Static.h deleted file mode 100644 index 9ab1dcf3df..0000000000 --- a/rpcs3/Emu/SysCalls/Static.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -class StaticFuncManager -{ -public: - void StaticAnalyse(void* ptr, u32 size, u32 base); - void StaticFinalize(); -}; diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index 06320945e8..26a3a26cb6 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -7,7 +7,6 @@ #include "Emu/GameInfo.h" #include "Emu/ARMv7/PSVFuncList.h" #include "Emu/ARMv7/PSVObjectList.h" -#include "Emu/SysCalls/Static.h" #include "Emu/SysCalls/ModuleManager.h" #include "Emu/Cell/PPUThread.h" #include "Emu/Cell/SPUThread.h" @@ -57,7 +56,6 @@ Emulator::Emulator() , m_audio_manager(new AudioManager()) , m_callback_manager(new CallbackManager()) , m_event_manager(new EventManager()) - , m_sfunc_manager(new StaticFuncManager()) , m_module_manager(new ModuleManager()) , m_sync_prim_manager(new SyncPrimManager()) , m_vfs(new VFS()) @@ -77,7 +75,6 @@ Emulator::~Emulator() delete m_audio_manager; delete m_callback_manager; delete m_event_manager; - delete m_sfunc_manager; delete m_module_manager; delete m_sync_prim_manager; delete m_vfs; @@ -397,7 +394,6 @@ void Emulator::Stop() GetMouseManager().Close(); GetCallbackManager().Clear(); GetModuleManager().Close(); - GetSFuncManager().StaticFinalize(); GetSyncPrimManager().Close(); CurGameInfo.Reset(); diff --git a/rpcs3/Emu/System.h b/rpcs3/Emu/System.h index a5a94f0ea9..d011428d0a 100644 --- a/rpcs3/Emu/System.h +++ b/rpcs3/Emu/System.h @@ -21,7 +21,6 @@ class CallbackManager; class CPUThread; class EventManager; class ModuleManager; -class StaticFuncManager; class SyncPrimManager; struct VFS; @@ -100,7 +99,6 @@ class Emulator AudioManager* m_audio_manager; CallbackManager* m_callback_manager; EventManager* m_event_manager; - StaticFuncManager* m_sfunc_manager; ModuleManager* m_module_manager; SyncPrimManager* m_sync_prim_manager; VFS* m_vfs; @@ -163,7 +161,6 @@ public: std::vector& GetBreakPoints() { return m_break_points; } std::vector& GetMarkedPoints() { return m_marked_points; } EventManager& GetEventManager() { return *m_event_manager; } - StaticFuncManager& GetSFuncManager() { return *m_sfunc_manager; } ModuleManager& GetModuleManager() { return *m_module_manager; } SyncPrimManager& GetSyncPrimManager() { return *m_sync_prim_manager; } diff --git a/rpcs3/Gui/MainFrame.cpp b/rpcs3/Gui/MainFrame.cpp index 72f992a999..21de6c9d81 100644 --- a/rpcs3/Gui/MainFrame.cpp +++ b/rpcs3/Gui/MainFrame.cpp @@ -542,13 +542,6 @@ void MainFrame::Config(wxCommandEvent& WXUNUSED(event)) cbox_hle_loglvl ->SetSelection(Ini.HLELogLvl.GetValue()); cbox_sys_lang ->SetSelection(Ini.SysLanguage.GetValue()); - // Enable/Disable parameters - chbox_audio_dump->Enable(Emu.IsStopped()); - chbox_audio_conv->Enable(Emu.IsStopped()); - chbox_hle_logging->Enable(Emu.IsStopped()); - chbox_rsx_logging->Enable(Emu.IsStopped()); - chbox_hle_hook_stfunc->Enable(Emu.IsStopped()); - s_round_cpu_decoder->Add(cbox_cpu_decoder, wxSizerFlags().Border(wxALL, 5).Expand()); s_round_spu_decoder->Add(cbox_spu_decoder, wxSizerFlags().Border(wxALL, 5).Expand()); diff --git a/rpcs3/Loader/ELF64.cpp b/rpcs3/Loader/ELF64.cpp index 8c90bb408c..d1f646f72e 100644 --- a/rpcs3/Loader/ELF64.cpp +++ b/rpcs3/Loader/ELF64.cpp @@ -7,7 +7,6 @@ #include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/SysCalls/SysCalls.h" -#include "Emu/SysCalls/Static.h" #include "Emu/SysCalls/ModuleManager.h" #include "Emu/SysCalls/lv2/sys_prx.h" #include "Emu/Cell/PPUInstrTable.h" @@ -532,7 +531,7 @@ namespace loader { m_stream->Seek(handler::get_stream_offset() + phdr.p_offset); m_stream->Read(phdr.p_vaddr.get_ptr(), phdr.p_filesz); - Emu.GetSFuncManager().StaticAnalyse(phdr.p_vaddr.get_ptr(), (u32)phdr.p_filesz, phdr.p_vaddr.addr()); + hook_ppu_funcs((u32*)phdr.p_vaddr.get_ptr(), vm::cast(phdr.p_filesz)); } } break; diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index 56bc415e11..48916379d3 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -278,7 +278,6 @@ - @@ -511,7 +510,6 @@ - diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index 49c65e3094..3c7c2797cc 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -131,9 +131,6 @@ Emu\SysCalls - - Emu\SysCalls - Emu\SysCalls @@ -1228,9 +1225,6 @@ Emu\SysCalls - - Emu\SysCalls - Utilities\SimpleIni