From 95f66859008fe3dd16f0232e0da5623857abbe44 Mon Sep 17 00:00:00 2001 From: skidau Date: Fri, 28 Dec 2012 14:26:46 +1100 Subject: [PATCH] Changed the HLE system to allow it to hook the beginning, the end or replace the entire function without changing the GC memory. Fixes Kirby's Return to Dreamland. Added a way to categorise the type of HLE function. Currently, there are debug, floating point, memory and generic functions. Added a HLE function for OSGetResetCode (Warm reset). Fixes the CSI games. Added a switch to disable all of the HLE functions if the idle skipping option is disabled. --- Data/Sys/totaldb.dsy | Bin 723252 -> 723388 bytes Source/Core/Core/Src/Boot/Boot.cpp | 3 +- Source/Core/Core/Src/Boot/Boot_BS2Emu.cpp | 2 +- Source/Core/Core/Src/HLE/HLE.cpp | 115 +++++++++++------- Source/Core/Core/Src/HLE/HLE.h | 26 +++- Source/Core/Core/Src/HLE/HLE_Misc.cpp | 96 +++++++++++++-- Source/Core/Core/Src/HLE/HLE_Misc.h | 7 ++ Source/Core/Core/Src/HW/Memmap.cpp | 5 +- .../Core/Core/Src/HW/ProcessorInterface.cpp | 3 +- .../Src/PowerPC/Interpreter/Interpreter.cpp | 98 +++++++++------ Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp | 37 +++++- .../Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp | 39 +++++- .../Core/Src/PowerPC/JitCommon/JitCache.cpp | 6 +- .../Core/Src/PowerPC/JitCommon/Jit_Util.cpp | 25 ++-- 14 files changed, 339 insertions(+), 123 deletions(-) diff --git a/Data/Sys/totaldb.dsy b/Data/Sys/totaldb.dsy index a1c9683c9f57ca74ba2693c818d474dcb4761b2e..8eb9c28bf769b1b762c83b503d2733400a02e697 100644 GIT binary patch delta 56 zcmdloNoUVw9meC0jIE47#MH{j+{(z(%E;Qv$kxip-pa_)%E;Nu$hDP`+nAH}*sruk LgXu57u{8q#y~7ZL delta 45 zcmdlpS!c^69mZpgjIE47#MH{j+{(z(%E;Qv$kxip-pa_)%E;Nu$hDP`+n5soCFBaH diff --git a/Source/Core/Core/Src/Boot/Boot.cpp b/Source/Core/Core/Src/Boot/Boot.cpp index 0fa89a28cc..aaaa4dd39a 100644 --- a/Source/Core/Core/Src/Boot/Boot.cpp +++ b/Source/Core/Core/Src/Boot/Boot.cpp @@ -258,7 +258,7 @@ bool CBoot::BootUp() } // Scan for common HLE functions - if (!_StartupPara.bEnableDebugging && Memory::Read_U16(0x00003140) >= 30) + if (_StartupPara.bSkipIdle && !_StartupPara.bEnableDebugging) { PPCAnalyst::FindFunctions(0x80004000, 0x811fffff, &g_symbolDB); SignatureDB db; @@ -267,7 +267,6 @@ bool CBoot::BootUp() db.Apply(&g_symbolDB); HLE::PatchFunctions(); db.Clear(); - g_symbolDB.Clear(); } } diff --git a/Source/Core/Core/Src/Boot/Boot_BS2Emu.cpp b/Source/Core/Core/Src/Boot/Boot_BS2Emu.cpp index bd789fa82b..5011543448 100644 --- a/Source/Core/Core/Src/Boot/Boot_BS2Emu.cpp +++ b/Source/Core/Core/Src/Boot/Boot_BS2Emu.cpp @@ -375,7 +375,7 @@ bool CBoot::EmulatedBS2_Wii() u32 iLength = Memory::ReadUnchecked_U32(0x81300008); u32 iDVDOffset = Memory::ReadUnchecked_U32(0x8130000c) << 2; - INFO_LOG(BOOT, "DVDRead: offset: %08x memOffse: %08x length: %i", iDVDOffset, iRamAddress, iLength); + INFO_LOG(BOOT, "DVDRead: offset: %08x memOffset: %08x length: %i", iDVDOffset, iRamAddress, iLength); DVDInterface::DVDRead(iDVDOffset, iRamAddress, iLength); } while(PowerPC::ppcState.gpr[3] != 0x00); diff --git a/Source/Core/Core/Src/HLE/HLE.cpp b/Source/Core/Core/Src/HLE/HLE.cpp index 0c42f7f4df..457870ba1d 100644 --- a/Source/Core/Core/Src/HLE/HLE.cpp +++ b/Source/Core/Core/Src/HLE/HLE.cpp @@ -15,7 +15,6 @@ // Official SVN repository and contact information can be found at // http://code.google.com/p/dolphin-emu/ -#include #include "Common.h" #include "HLE.h" @@ -29,6 +28,7 @@ #include "HLE_Misc.h" #include "IPC_HLE/WII_IPC_HLE_Device_es.h" #include "ConfigManager.h" +#include "Core.h" namespace HLE { @@ -47,56 +47,72 @@ struct SPatch { char m_szPatchName[128]; TPatchFunction PatchFunction; + int type; + int flags; }; static const SPatch OSPatches[] = { - { "FAKE_TO_SKIP_0", HLE_Misc::UnimplementedFunction }, + { "FAKE_TO_SKIP_0", HLE_Misc::UnimplementedFunction, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC }, // speedup - //{ "OSProtectRange", HLE_Misc::UnimplementedFunctionFalse }, - //{ "THPPlayerGetState", HLE_Misc:THPPlayerGetState }, + //{ "OSProtectRange", HLE_Misc::UnimplementedFunctionFalse, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC }, + //{ "THPPlayerGetState", HLE_Misc:THPPlayerGetState, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC }, + //{ "memcpy", HLE_Misc::memcpy, HLE_HOOK_REPLACE, HLE_TYPE_MEMORY }, + //{ "memcmp", HLE_Misc::memcmp, HLE_HOOK_REPLACE, HLE_TYPE_MEMORY }, + //{ "memset", HLE_Misc::memset, HLE_HOOK_REPLACE, HLE_TYPE_MEMORY }, + //{ "memmove", HLE_Misc::memmove, HLE_HOOK_REPLACE, HLE_TYPE_MEMORY }, + //{ "__div2i", HLE_Misc::div2i, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC }, // Slower? + //{ "__div2u", HLE_Misc::div2u, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC }, // Slower? + + //{ "DCFlushRange", HLE_Misc::UnimplementedFunction, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC }, + //{ "DCInvalidateRange", HLE_Misc::UnimplementedFunction, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC }, + //{ "DCZeroRange", HLE_Misc::UnimplementedFunction, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC }, // debug out is very nice ;) - { "OSReport", HLE_OS::HLE_GeneralDebugPrint }, - { "DEBUGPrint", HLE_OS::HLE_GeneralDebugPrint }, - { "WUD_DEBUGPrint", HLE_OS::HLE_GeneralDebugPrint }, - { "OSPanic", HLE_OS::HLE_OSPanic }, - { "vprintf", HLE_OS::HLE_GeneralDebugPrint }, - { "printf", HLE_OS::HLE_GeneralDebugPrint }, - { "puts", HLE_OS::HLE_GeneralDebugPrint }, // gcc-optimized printf? - { "___blank(char *,...)", HLE_OS::HLE_GeneralDebugPrint }, // used for early init things (normally) - { "___blank", HLE_OS::HLE_GeneralDebugPrint }, - { "__write_console", HLE_OS::HLE_write_console }, // used by sysmenu (+more?) + { "OSReport", HLE_OS::HLE_GeneralDebugPrint, HLE_HOOK_REPLACE, HLE_TYPE_DEBUG }, + { "DEBUGPrint", HLE_OS::HLE_GeneralDebugPrint, HLE_HOOK_REPLACE, HLE_TYPE_DEBUG }, + { "WUD_DEBUGPrint", HLE_OS::HLE_GeneralDebugPrint, HLE_HOOK_REPLACE, HLE_TYPE_DEBUG }, + { "OSPanic", HLE_OS::HLE_OSPanic, HLE_HOOK_REPLACE, HLE_TYPE_DEBUG }, + { "vprintf", HLE_OS::HLE_GeneralDebugPrint, HLE_HOOK_REPLACE, HLE_TYPE_DEBUG }, + { "printf", HLE_OS::HLE_GeneralDebugPrint, HLE_HOOK_REPLACE, HLE_TYPE_DEBUG }, + { "puts", HLE_OS::HLE_GeneralDebugPrint, HLE_HOOK_REPLACE, HLE_TYPE_DEBUG }, // gcc-optimized printf? + { "___blank(char *,...)", HLE_OS::HLE_GeneralDebugPrint, HLE_HOOK_REPLACE, HLE_TYPE_DEBUG }, // used for early init things (normally) + { "___blank", HLE_OS::HLE_GeneralDebugPrint, HLE_HOOK_REPLACE, HLE_TYPE_DEBUG }, + { "__write_console", HLE_OS::HLE_write_console, HLE_HOOK_REPLACE, HLE_TYPE_DEBUG }, // used by sysmenu (+more?) // wii only - //{ "__OSInitAudioSystem", HLE_Misc::UnimplementedFunction }, + //{ "__OSInitAudioSystem", HLE_Misc::UnimplementedFunction, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC }, // Super Monkey Ball - no longer needed. - //{ ".evil_vec_cosine", HLE_Misc::SMB_EvilVecCosine }, - //{ ".evil_normalize", HLE_Misc::SMB_EvilNormalize }, - //{ ".evil_vec_setlength", HLE_Misc::SMB_evil_vec_setlength }, - //{ ".evil_vec_something", HLE_Misc::FZero_evil_vec_normalize }, - { "PanicAlert", HLE_Misc::HLEPanicAlert }, - //{ ".sqrt_internal_needs_cr1", HLE_Misc::SMB_sqrt_internal }, - //{ ".rsqrt_internal_needs_cr1", HLE_Misc::SMB_rsqrt_internal }, - //{ ".atan2", HLE_Misc::SMB_atan2}, - //{ ".sqrt_fz", HLE_Misc::FZ_sqrt}, + //{ ".evil_vec_cosine", HLE_Misc::SMB_EvilVecCosine, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC }, + //{ ".evil_normalize", HLE_Misc::SMB_EvilNormalize, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC }, + //{ ".evil_vec_setlength", HLE_Misc::SMB_evil_vec_setlength, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC }, + //{ ".evil_vec_something", HLE_Misc::FZero_evil_vec_normalize, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC }, + { "PanicAlert", HLE_Misc::HLEPanicAlert, HLE_HOOK_REPLACE, HLE_TYPE_DEBUG }, + //{ ".sqrt_internal_needs_cr1", HLE_Misc::SMB_sqrt_internal, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC }, + //{ ".rsqrt_internal_needs_cr1", HLE_Misc::SMB_rsqrt_internal, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC }, + //{ ".atan2", HLE_Misc::SMB_atan2HLE_HOOK_REPLACE, HLE_TYPE_GENERIC }, + //{ ".sqrt_fz", HLE_Misc::FZ_sqrtHLE_HOOK_REPLACE, HLE_TYPE_GENERIC }, // F-zero still isn't working correctly, but these aren't really helping. - //{ ".sqrt_internal_fz", HLE_Misc::FZ_sqrt_internal }, - //{ ".rsqrt_internal_fz", HLE_Misc::FZ_rsqrt_internal }, + //{ ".sqrt_internal_fz", HLE_Misc::FZ_sqrt_internal, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC }, + //{ ".rsqrt_internal_fz", HLE_Misc::FZ_rsqrt_internal, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC }, - //{ ".kill_infinites", HLE_Misc::FZero_kill_infinites }, + //{ ".kill_infinites", HLE_Misc::FZero_kill_infinites, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC }, // special - // { "GXPeekZ", HLE_Misc::GXPeekZ}, - // { "GXPeekARGB", HLE_Misc::GXPeekARGB}, + // { "GXPeekZ", HLE_Misc::GXPeekZHLE_HOOK_REPLACE, HLE_TYPE_GENERIC }, + // { "GXPeekARGB", HLE_Misc::GXPeekARGBHLE_HOOK_REPLACE, HLE_TYPE_GENERIC }, // Name doesn't matter, installed in CBoot::BootUp() - { "HBReload", HLE_Misc::HBReload }, - { "__OSBootDol", HLE_Misc::OSBootDol }, + { "HBReload", HLE_Misc::HBReload, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC }, + + // ES_LAUNCH + { "__OSBootDol", HLE_Misc::OSBootDol, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC }, + { "OSGetResetCode", HLE_Misc::OSGetResetCode, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC }, + }; static const SPatch OSBreakPoints[] = @@ -104,17 +120,13 @@ static const SPatch OSBreakPoints[] = { "FAKE_TO_SKIP_0", HLE_Misc::UnimplementedFunction }, }; - -static std::map orig_instruction; - -void Patch(u32 address, const char *hle_func_name) +void Patch(u32 addr, const char *hle_func_name) { for (u32 i = 0; i < sizeof(OSPatches) / sizeof(SPatch); i++) { if (!strcmp(OSPatches[i].m_szPatchName, hle_func_name)) { - u32 HLEPatchValue = (1 & 0x3f) << 26; - Memory::Write_U32(HLEPatchValue | i, address); + orig_instruction[addr] = i; return; } } @@ -128,11 +140,9 @@ void PatchFunctions() Symbol *symbol = g_symbolDB.GetSymbolFromName(OSPatches[i].m_szPatchName); if (symbol > 0) { - u32 HLEPatchValue = (1 & 0x3f) << 26; for (u32 addr = symbol->address; addr < symbol->address + symbol->size; addr += 4) { - orig_instruction[addr] = Memory::ReadUnchecked_U32(addr); - Memory::Write_U32(HLEPatchValue | i, addr); + orig_instruction[addr] = i; } INFO_LOG(OSHLE, "Patching %s %08x", OSPatches[i].m_szPatchName, symbol->address); } @@ -169,12 +179,33 @@ void Execute(u32 _CurrentPC, u32 _Instruction) // _dbg_assert_msg_(HLE,NPC == LR, "Broken HLE function (doesn't set NPC)", OSPatches[pos].m_szPatchName); } -u32 GetOrigInstruction(u32 addr) +u32 GetFunctionIndex(u32 addr) { std::map::const_iterator iter = orig_instruction.find(addr); return (iter != orig_instruction.end()) ? iter->second : 0; } +int GetFunctionTypeByIndex(u32 index) +{ + return OSPatches[index].type; +} + +int GetFunctionFlagsByIndex(u32 index) +{ + return OSPatches[index].flags; +} + +bool IsEnabled(int flags) +{ + if (flags == HLE::HLE_TYPE_MEMORY && Core::g_CoreStartupParameter.bMMU) + return false; + + if (flags == HLE::HLE_TYPE_DEBUG && !Core::g_CoreStartupParameter.bEnableDebugging && PowerPC::GetMode() != MODE_INTERPRETER) + return false; + + return true; +} + u32 UnPatch(std::string patchName) { Symbol *symbol = g_symbolDB.GetSymbolFromName(patchName.c_str()); @@ -182,7 +213,7 @@ u32 UnPatch(std::string patchName) { for (u32 addr = symbol->address; addr < symbol->address + symbol->size; addr += 4) { - Memory::WriteUnchecked_U32(orig_instruction[addr], addr); + orig_instruction[addr] = 0; PowerPC::ppcState.iCache.Invalidate(addr); } return symbol->address; diff --git a/Source/Core/Core/Src/HLE/HLE.h b/Source/Core/Core/Src/HLE/HLE.h index b81f347b9f..9318d34197 100644 --- a/Source/Core/Core/Src/HLE/HLE.h +++ b/Source/Core/Core/Src/HLE/HLE.h @@ -18,16 +18,40 @@ #ifndef _HLE_H #define _HLE_H +#include #include "Common.h" namespace HLE { + enum + { + HLE_HOOK_START = 0, // Hook the beginning of the function and execute the function afterwards + HLE_HOOK_END = 1, // Hook the end of the function, executing the function first before the hook + HLE_HOOK_REPLACE = 2, // Replace the function with the HLE version + HLE_HOOK_NONE = 3, // Do not hook the function + }; + + enum + { + HLE_TYPE_GENERIC = 0, // Miscellaneous function + HLE_TYPE_MEMORY = 1, // Memory operation + HLE_TYPE_FP = 2, // Floating Point operation + HLE_TYPE_DEBUG = 3, // Debug output function + }; + void PatchFunctions(); + void Patch(u32 pc, const char *func_name); u32 UnPatch(std::string patchName); void Execute(u32 _CurrentPC, u32 _Instruction); - u32 GetOrigInstruction(u32 em_address); + u32 GetFunctionIndex(u32 em_address); + int GetFunctionTypeByIndex(u32 index); + int GetFunctionFlagsByIndex(u32 index); + + bool IsEnabled(int flags); + + static std::map orig_instruction; } #endif diff --git a/Source/Core/Core/Src/HLE/HLE_Misc.cpp b/Source/Core/Core/Src/HLE/HLE_Misc.cpp index b04e8004fd..4a17ffd748 100644 --- a/Source/Core/Core/Src/HLE/HLE_Misc.cpp +++ b/Source/Core/Core/Src/HLE/HLE_Misc.cpp @@ -37,7 +37,6 @@ namespace HLE_Misc { -std::string dol; std::string args; u32 argsPtr; u32 bootType; @@ -302,7 +301,7 @@ void HBReload() void ExecuteDOL(u8* dolFile, u32 fileSize) { // Clear memory before loading the dol - for (int i = 0x80004000; i < Memory::Read_U32(0x00000034); i += 4) + for (u32 i = 0x80004000; i < Memory::Read_U32(0x00000034); i += 4) { // TODO: Should not write over the "save region" Memory::Write_U32(0x00000000, i); @@ -320,7 +319,6 @@ void ExecuteDOL(u8* dolFile, u32 fileSize) db.Apply(&g_symbolDB); HLE::PatchFunctions(); db.Clear(); - g_symbolDB.Clear(); } } @@ -359,12 +357,12 @@ void ExecuteDOL(u8* dolFile, u32 fileSize) NPC = dolLoader.GetEntryPoint() | 0x80000000; } -void LoadDOLFromDisc() +void LoadDOLFromDisc(std::string dol) { DiscIO::IVolume* pVolume = DiscIO::CreateVolumeFromFilename(SConfig::GetInstance().m_LastFilename.c_str()); DiscIO::IFileSystem* pFileSystem = DiscIO::CreateFileSystem(pVolume); - if (dol.substr(1, 1).compare("//")) + if (dol.length() > 1 && dol.compare(0, 1, "/") == 0) dol = dol.substr(1); u32 fileSize = (u32) pFileSystem->GetFileSize(dol.c_str()); @@ -391,19 +389,92 @@ void LoadBootDOLFromDisc() delete[] dolFile; } -u32 GetDolFileSize() +u32 GetDolFileSize(std::string dol) { DiscIO::IVolume* pVolume = DiscIO::CreateVolumeFromFilename(SConfig::GetInstance().m_LastFilename.c_str()); DiscIO::IFileSystem* pFileSystem = DiscIO::CreateFileSystem(pVolume); std::string dolFile; - if (dol.substr(1, 1).compare("//")) + if (dol.length() > 1 && dol.compare(0, 1, "/") == 0) dolFile = dol.substr(1); + else + dolFile = dol; return (u32)pFileSystem->GetFileSize(dolFile.c_str()); } +void memmove() +{ + u32 dest = GPR(3); + u32 src = GPR(4); + u32 count = GPR(5); + std::memmove((u8*)(Memory::base + dest), (u8*)(Memory::base + src), count); + NPC = LR; +} + +void memcpy() +{ + u32 dest = GPR(3); + u32 src = GPR(4); + u32 count = GPR(5); + std::memcpy((u8*)(Memory::base + dest), (u8*)(Memory::base + src), count); + NPC = LR; +} + +void memset() +{ + u32 dest = GPR(3); + u32 ch = GPR(4); + u32 count = GPR(5); + std::memset((u8*)(Memory::base + dest), ch, count); + NPC = LR; +} + +void memcmp() +{ + u32 dest = GPR(3); + u32 src = GPR(4); + u32 count = GPR(5); + GPR(3) = std::memcmp((u8*)(Memory::base + dest), (u8*)(Memory::base + src), count); + NPC = LR; +} + +void div2i() +{ + s64 num = (s64)(GPR(3)) << 32 | GPR(4); + s64 den = (s64)(GPR(5)) << 32 | GPR(6); + s64 quo = num / den; + GPR(3) = quo >> 32; + GPR(4) = quo & 0xffffffff; + NPC = LR; +} + +void div2u() +{ + u64 num = (u64)(GPR(3)) << 32 | GPR(4); + u64 den = (u64)(GPR(5)) << 32 | GPR(6); + u64 quo = num / den; + GPR(3) = quo >> 32; + GPR(4) = quo & 0xffffffff; + NPC = LR; +} + +void OSGetResetCode() +{ + u32 resetCode = Memory::Read_U32(0xCC003024); + if (resetCode != 0) + { + GPR(3) = resetCode | 0x80000000; + } + else + { + GPR(3) = 0; + } + + NPC = LR; +} + void OSBootDol() { IOSv = Memory::Read_U16(0x00003140); @@ -417,8 +488,7 @@ void OSBootDol() u32 resetCode = GPR(30); // Reset game - Memory::Write_U32(resetCode << 3, 0xCC003024); - //Memory::Write_U32((resetCode << 3) | 0x80000000, 0x800030f0); // Warm reset + Memory::Write_U32(resetCode, 0xCC003024); LoadBootDOLFromDisc(); return; } @@ -429,15 +499,17 @@ void OSBootDol() } else if ((GPR(4) >> 28) == 0xC) { + std::string dol; + // Boot DOL from disc u32 ptr = GPR(28); Memory::GetString(dol, ptr); - if (GetDolFileSize() == 0) + if (GetDolFileSize(dol) == 0) { ptr = GPR(30); Memory::GetString(dol, ptr); - if (GetDolFileSize() == 0) + if (GetDolFileSize(dol) == 0) { // Cannot locate the dol file, exit. HLE::UnPatch("__OSBootDol"); @@ -448,7 +520,7 @@ void OSBootDol() argsPtr = Memory::Read_U32(GPR(5)); Memory::GetString(args, argsPtr); - LoadDOLFromDisc(); + LoadDOLFromDisc(dol); return; } else diff --git a/Source/Core/Core/Src/HLE/HLE_Misc.h b/Source/Core/Core/Src/HLE/HLE_Misc.h index d39280831c..d0d098835f 100644 --- a/Source/Core/Core/Src/HLE/HLE_Misc.h +++ b/Source/Core/Core/Src/HLE/HLE_Misc.h @@ -40,6 +40,13 @@ namespace HLE_Misc void FZ_rsqrt_internal(); void HBReload(); void OSBootDol(); + void OSGetResetCode(); + void memcpy(); + void memset(); + void memmove(); + void memcmp(); + void div2i(); + void div2u(); void ExecuteDOL(u8* dolFile, u32 fileSize); } diff --git a/Source/Core/Core/Src/HW/Memmap.cpp b/Source/Core/Core/Src/HW/Memmap.cpp index 2da999eeac..88f6b2c358 100644 --- a/Source/Core/Core/Src/HW/Memmap.cpp +++ b/Source/Core/Core/Src/HW/Memmap.cpp @@ -416,10 +416,7 @@ bool AreMemoryBreakpointsActivated() u32 Read_Instruction(const u32 em_address) { UGeckoInstruction inst = ReadUnchecked_U32(em_address); - if (inst.OPCD == 1) - return HLE::GetOrigInstruction(em_address); - else - return inst.hex; + return inst.hex; } u32 Read_Opcode_JIT_Uncached(const u32 _Address) diff --git a/Source/Core/Core/Src/HW/ProcessorInterface.cpp b/Source/Core/Core/Src/HW/ProcessorInterface.cpp index 0e989d3f50..9e72cc2169 100644 --- a/Source/Core/Core/Src/HW/ProcessorInterface.cpp +++ b/Source/Core/Core/Src/HW/ProcessorInterface.cpp @@ -96,8 +96,7 @@ void Init() m_FlipperRev = 0x246500B1; // revision C m_Unknown = 0; - // Bleh, why? - //m_ResetCode |= 0x80000000; + m_ResetCode = 0x80000000; // Cold reset m_InterruptCause = INT_CAUSE_RST_BUTTON | INT_CAUSE_VI; toggleResetButton = CoreTiming::RegisterEvent("ToggleResetButton", &ToggleResetButtonCallback); diff --git a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter.cpp b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter.cpp index a8277d868a..be68d357a3 100644 --- a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter.cpp +++ b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter.cpp @@ -26,6 +26,7 @@ #include "PowerPCDisasm.h" #include "../../IPC_HLE/WII_IPC_HLE.h" #include "Atomic.h" +#include "HLE/HLE.h" namespace { @@ -79,57 +80,63 @@ int startTrace = 0; void Trace( UGeckoInstruction &instCode ) { - char regs[500]=""; + char reg[25]=""; + std::string regs = ""; for (int i=0; i<32; i++) { - sprintf(regs, "%sr%02d: %08x ", regs, i, PowerPC::ppcState.gpr[i]); + sprintf(reg, "r%02d: %08x ", i, PowerPC::ppcState.gpr[i]); + regs.append(reg); } - char fregs[500]=""; + char freg[25]=""; + std::string fregs = ""; for (int i=0; i<32; i++) { - sprintf(fregs, "%sf%02d: %08llx %08llx ", fregs, i, - PowerPC::ppcState.ps[i][0], PowerPC::ppcState.ps[i][1]); + sprintf(freg, "f%02d: %08llx %08llx ", i, PowerPC::ppcState.ps[i][0], PowerPC::ppcState.ps[i][1]); + fregs.append(freg); } char ppcInst[256]; DisassembleGekko(instCode.hex, PC, ppcInst, 256); - DEBUG_LOG(POWERPC, "INTER PC: %08x SRR0: %08x SRR1: %08x CRfast: %02x%02x%02x%02x%02x%02x%02x%02x FPSCR: %08x MSR: %08x LR: %08x %s %s %08x %s", PC, SRR0, SRR1, PowerPC::ppcState.cr_fast[0], PowerPC::ppcState.cr_fast[1], PowerPC::ppcState.cr_fast[2], PowerPC::ppcState.cr_fast[3], PowerPC::ppcState.cr_fast[4], PowerPC::ppcState.cr_fast[5], PowerPC::ppcState.cr_fast[6], PowerPC::ppcState.cr_fast[7], PowerPC::ppcState.fpscr, PowerPC::ppcState.msr, PowerPC::ppcState.spr[8], regs, fregs, instCode.hex, ppcInst); + DEBUG_LOG(POWERPC, "INTER PC: %08x SRR0: %08x SRR1: %08x CRfast: %02x%02x%02x%02x%02x%02x%02x%02x FPSCR: %08x MSR: %08x LR: %08x %s %s %08x %s", PC, SRR0, SRR1, PowerPC::ppcState.cr_fast[0], PowerPC::ppcState.cr_fast[1], PowerPC::ppcState.cr_fast[2], PowerPC::ppcState.cr_fast[3], PowerPC::ppcState.cr_fast[4], PowerPC::ppcState.cr_fast[5], PowerPC::ppcState.cr_fast[6], PowerPC::ppcState.cr_fast[7], PowerPC::ppcState.fpscr, PowerPC::ppcState.msr, PowerPC::ppcState.spr[8], regs.c_str(), fregs.c_str(), instCode.hex, ppcInst); } int Interpreter::SingleStepInner(void) { static UGeckoInstruction instCode; - NPC = PC + sizeof(UGeckoInstruction); - instCode.hex = Memory::Read_Opcode(PC); - - // Uncomment to trace the interpreter - //if ((PC & 0xffffff)>=0x0ab54c && (PC & 0xffffff)<=0x0ab624) - // startTrace = 1; - //else - // startTrace = 0; - - if (startTrace) + u32 function = m_EndBlock ? HLE::GetFunctionIndex(PC) : 0; // Check for HLE functions after branches + if (function != 0) { - Trace(instCode); - } - - if (instCode.hex != 0) - { - UReg_MSR& msr = (UReg_MSR&)MSR; - if (msr.FP) //If FPU is enabled, just execute + int type = HLE::GetFunctionTypeByIndex(function); + if (type == HLE::HLE_HOOK_START || type == HLE::HLE_HOOK_REPLACE) { - m_opTable[instCode.OPCD](instCode); - if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) + int flags = HLE::GetFunctionFlagsByIndex(function); + if (HLE::IsEnabled(flags)) { - PowerPC::CheckExceptions(); - m_EndBlock = true; + HLEFunction(function); } } - else + } + else + { + NPC = PC + sizeof(UGeckoInstruction); + instCode.hex = Memory::Read_Opcode(PC); + + // Uncomment to trace the interpreter + //if ((PC & 0xffffff)>=0x0ab54c && (PC & 0xffffff)<=0x0ab624) + // startTrace = 1; + //else + // startTrace = 0; + + if (startTrace) { - // check if we have to generate a FPU unavailable exception - if (!PPCTables::UsesFPU(instCode)) + Trace(instCode); + } + + if (instCode.hex != 0) + { + UReg_MSR& msr = (UReg_MSR&)MSR; + if (msr.FP) //If FPU is enabled, just execute { m_opTable[instCode.OPCD](instCode); if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) @@ -140,17 +147,30 @@ int Interpreter::SingleStepInner(void) } else { - Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_FPU_UNAVAILABLE); - PowerPC::CheckExceptions(); - m_EndBlock = true; + // check if we have to generate a FPU unavailable exception + if (!PPCTables::UsesFPU(instCode)) + { + m_opTable[instCode.OPCD](instCode); + if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) + { + PowerPC::CheckExceptions(); + m_EndBlock = true; + } + } + else + { + Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_FPU_UNAVAILABLE); + PowerPC::CheckExceptions(); + m_EndBlock = true; + } } } - } - else - { - // Memory exception on instruction fetch - PowerPC::CheckExceptions(); - m_EndBlock = true; + else + { + // Memory exception on instruction fetch + PowerPC::CheckExceptions(); + m_EndBlock = true; + } } last_pc = PC; PC = NPC; diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp index 357eeb7809..31caca0a43 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit.cpp @@ -252,8 +252,6 @@ void Jit64::HLEFunction(UGeckoInstruction _inst) gpr.Flush(FLUSH_ALL); fpr.Flush(FLUSH_ALL); ABI_CallFunctionCC((void*)&HLE::Execute, js.compilerPC, _inst.hex); - MOV(32, R(EAX), M(&NPC)); - WriteExitDestInEAX(); } void Jit64::DoNothing(UGeckoInstruction _inst) @@ -566,6 +564,27 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc ABI_CallFunction(thunks.ProtectFunction((void *)&GPFifo::CheckGatherPipe, 0)); } + u32 function = HLE::GetFunctionIndex(ops[i].address); + if (function != 0) + { + int type = HLE::GetFunctionTypeByIndex(function); + if (type == HLE::HLE_HOOK_START || type == HLE::HLE_HOOK_REPLACE) + { + int flags = HLE::GetFunctionFlagsByIndex(function); + if (HLE::IsEnabled(flags)) + { + HLEFunction(function); + if (type == HLE::HLE_HOOK_REPLACE) + { + MOV(32, R(EAX), M(&NPC)); + js.downcountAmount += js.st.numCycles; + WriteExitDestInEAX(); + break; + } + } + } + } + if (!ops[i].skip) { if ((opinfo->flags & FL_USE_FPU) && !js.firstFPInstructionFound) @@ -668,6 +687,20 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc break; } + u32 function = HLE::GetFunctionIndex(js.blockStart); + if (function != 0) + { + int type = HLE::GetFunctionTypeByIndex(function); + if (type == HLE::HLE_HOOK_END) + { + int flags = HLE::GetFunctionFlagsByIndex(function); + if (HLE::IsEnabled(flags)) + { + HLEFunction(function); + } + } + } + if (memory_exception) { // Address of instruction could not be translated diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp index c9d4e44e71..d56c9ffee8 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp @@ -199,7 +199,7 @@ namespace JitILProfiler static u64 beginTime; static Block& Add(u64 codeHash) { - const u32 _blockIndex = blocks.size(); + const u32 _blockIndex = (u32)blocks.size(); blocks.push_back(Block()); Block& block = blocks.back(); block.index = _blockIndex; @@ -649,6 +649,27 @@ const u8* JitIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc js.next_compilerPC = ops[i + 1].address; } + u32 function = HLE::GetFunctionIndex(ops[i].address); + if (function != 0) + { + int type = HLE::GetFunctionTypeByIndex(function); + if (type == HLE::HLE_HOOK_START || type == HLE::HLE_HOOK_REPLACE) + { + int flags = HLE::GetFunctionFlagsByIndex(function); + if (HLE::IsEnabled(flags)) + { + HLEFunction(function); + if (type == HLE::HLE_HOOK_REPLACE) + { + MOV(32, R(EAX), M(&NPC)); + jit->js.downcountAmount += jit->js.st.numCycles; + WriteExitDestInOpArg(R(EAX)); + break; + } + } + } + } + if (!ops[i].skip) { if (js.memcheck && (opinfo->flags & FL_USE_FPU)) @@ -665,7 +686,7 @@ const u8* JitIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc { ibuild.EmitBreakPointCheck(ibuild.EmitIntConst(ops[i].address)); } - + JitILTables::CompileInstruction(ops[i]); if (js.memcheck && (opinfo->flags & FL_LOADSTORE)) @@ -681,6 +702,20 @@ const u8* JitIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc } } + u32 function = HLE::GetFunctionIndex(jit->js.blockStart); + if (function != 0) + { + int type = HLE::GetFunctionTypeByIndex(function); + if (type == HLE::HLE_HOOK_END) + { + int flags = HLE::GetFunctionFlagsByIndex(function); + if (HLE::IsEnabled(flags)) + { + HLEFunction(function); + } + } + } + if (memory_exception) { ibuild.EmitISIException(ibuild.EmitIntConst(em_address)); diff --git a/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.cpp b/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.cpp index 496ddebf7a..57827ec662 100644 --- a/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.cpp +++ b/Source/Core/Core/Src/PowerPC/JitCommon/JitCache.cpp @@ -135,7 +135,11 @@ bool JitBlock::ContainsAddress(u32 em_address) // is full and when saving and loading states. void JitBlockCache::Clear() { - Core::DisplayMessage("Clearing code cache.", 3000); + if (IsFull()) + Core::DisplayMessage("Clearing block cache.", 3000); + else + Core::DisplayMessage("Clearing code cache.", 3000); + for (int i = 0; i < num_blocks; i++) { DestroyBlock(i, false); diff --git a/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.cpp b/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.cpp index 333f0cdc05..7ec780b336 100644 --- a/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.cpp +++ b/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.cpp @@ -269,23 +269,18 @@ void EmuCodeBlock::SafeWriteRegToReg(X64Reg reg_value, X64Reg reg_addr, int acce void EmuCodeBlock::SafeWriteFloatToReg(X64Reg xmm_value, X64Reg reg_addr) { - u32 mem_mask = Memory::ADDR_MASK_HW_ACCESS; - - if (Core::g_CoreStartupParameter.bMMU || Core::g_CoreStartupParameter.iTLBHack) - { - mem_mask |= Memory::ADDR_MASK_MEM1; - } - -#ifdef ENABLE_MEM_CHECK - if (Core::g_CoreStartupParameter.bEnableDebugging) - { - mem_mask |= Memory::EXRAM_MASK; - } -#endif - - TEST(32, R(reg_addr), Imm32(mem_mask)); if (false && cpu_info.bSSSE3) { // This path should be faster but for some reason it causes errors so I've disabled it. + u32 mem_mask = Memory::ADDR_MASK_HW_ACCESS; + + if (Core::g_CoreStartupParameter.bMMU || Core::g_CoreStartupParameter.iTLBHack) + mem_mask |= Memory::ADDR_MASK_MEM1; + +#ifdef ENABLE_MEM_CHECK + if (Core::g_CoreStartupParameter.bEnableDebugging) + mem_mask |= Memory::EXRAM_MASK; +#endif + TEST(32, R(reg_addr), Imm32(mem_mask)); FixupBranch argh = J_CC(CC_Z); MOVSS(M(&float_buffer), xmm_value); MOV(32, R(EAX), M(&float_buffer));