diff --git a/Data/Sys/totaldb.dsy b/Data/Sys/totaldb.dsy index 790a942eae..8eb9c28bf7 100644 Binary files a/Data/Sys/totaldb.dsy and b/Data/Sys/totaldb.dsy differ diff --git a/Source/Core/Core/Src/Boot/Boot.cpp b/Source/Core/Core/Src/Boot/Boot.cpp index be82d217dc..aaaa4dd39a 100644 --- a/Source/Core/Core/Src/Boot/Boot.cpp +++ b/Source/Core/Core/Src/Boot/Boot.cpp @@ -257,6 +257,19 @@ bool CBoot::BootUp() EmulatedBS2(_StartupPara.bWii); } + // Scan for common HLE functions + if (_StartupPara.bSkipIdle && !_StartupPara.bEnableDebugging) + { + PPCAnalyst::FindFunctions(0x80004000, 0x811fffff, &g_symbolDB); + SignatureDB db; + if (db.Load((File::GetSysDirectory() + TOTALDB).c_str())) + { + db.Apply(&g_symbolDB); + HLE::PatchFunctions(); + db.Clear(); + } + } + /* Try to load the symbol map if there is one, and then scan it for and eventually replace code */ if (LoadMapFromFilename(_StartupPara.m_strFilename, gameID)) 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 84c6b2eb86..ae25060c64 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" @@ -27,6 +26,9 @@ #include "HLE_OS.h" #include "HLE_Misc.h" +#include "IPC_HLE/WII_IPC_HLE_Device_es.h" +#include "ConfigManager.h" +#include "Core.h" namespace HLE { @@ -45,55 +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::gc_memcpy, HLE_HOOK_REPLACE, HLE_TYPE_MEMORY }, + //{ "memcmp", HLE_Misc::gc_memcmp, HLE_HOOK_REPLACE, HLE_TYPE_MEMORY }, + //{ "memset", HLE_Misc::gc_memset, HLE_HOOK_REPLACE, HLE_TYPE_MEMORY }, + //{ "memmove", HLE_Misc::gc_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 }, + { "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[] = @@ -101,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; } } @@ -125,23 +140,24 @@ 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); } } - for (size_t i = 1; i < sizeof(OSBreakPoints) / sizeof(SPatch); i++) + if (SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableDebugging) { - Symbol *symbol = g_symbolDB.GetSymbolFromName(OSPatches[i].m_szPatchName); - if (symbol > 0) + for (size_t i = 1; i < sizeof(OSBreakPoints) / sizeof(SPatch); i++) { - PowerPC::breakpoints.Add(symbol->address, false); - INFO_LOG(OSHLE, "Adding BP to %s %08x", OSBreakPoints[i].m_szPatchName, symbol->address); + Symbol *symbol = g_symbolDB.GetSymbolFromName(OSPatches[i].m_szPatchName); + if (symbol > 0) + { + PowerPC::breakpoints.Add(symbol->address, false); + INFO_LOG(OSHLE, "Adding BP to %s %08x", OSBreakPoints[i].m_szPatchName, symbol->address); + } } } @@ -163,10 +179,46 @@ 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()); + if (symbol > 0) + { + for (u32 addr = symbol->address; addr < symbol->address + symbol->size; addr += 4) + { + orig_instruction[addr] = 0; + PowerPC::ppcState.iCache.Invalidate(addr); + } + return symbol->address; + } + return 0; +} + } // end of namespace HLE diff --git a/Source/Core/Core/Src/HLE/HLE.h b/Source/Core/Core/Src/HLE/HLE.h index 04c3d35198..9318d34197 100644 --- a/Source/Core/Core/Src/HLE/HLE.h +++ b/Source/Core/Core/Src/HLE/HLE.h @@ -18,15 +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 d69bf09680..7e23798df1 100644 --- a/Source/Core/Core/Src/HLE/HLE_Misc.cpp +++ b/Source/Core/Core/Src/HLE/HLE_Misc.cpp @@ -22,10 +22,25 @@ #include "../PowerPC/PowerPC.h" #include "../HW/Memmap.h" #include "../Host.h" +#include "IPC_HLE/WII_IPC_HLE_Device_DI.h" +#include "ConfigManager.h" +#include "VolumeCreator.h" +#include "Filesystem.h" +#include "../Boot/Boot_DOL.h" +#include "IPC_HLE/WII_IPC_HLE_Device_usb.h" +#include "HLE.h" +#include "PowerPC/PPCAnalyst.h" +#include "PowerPC/SignatureDB.h" +#include "PowerPC/PPCSymbolDB.h" +#include "CommonPaths.h" namespace HLE_Misc { +std::string args; +u32 argsPtr; +u32 bootType; + // Helper to quickly read the floating point value at a memory location. inline float F(u32 addr) { @@ -282,4 +297,253 @@ void HBReload() Host_Message(WM_USER_STOP); } +void ExecuteDOL(u8* dolFile, u32 fileSize) +{ + // Clear memory before loading the dol + for (u32 i = 0x80004000; i < Memory::Read_U32(0x00000034); i += 4) + { + // TODO: Should not write over the "save region" + Memory::Write_U32(0x00000000, i); + } + CDolLoader dolLoader(dolFile, fileSize); + dolLoader.Load(); + + // Scan for common HLE functions + if (!SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableDebugging) + { + g_symbolDB.Clear(); + PPCAnalyst::FindFunctions(0x80004000, 0x811fffff, &g_symbolDB); + SignatureDB db; + if (db.Load((File::GetSysDirectory() + TOTALDB).c_str())) + { + db.Apply(&g_symbolDB); + HLE::PatchFunctions(); + db.Clear(); + } + } + + PowerPC::ppcState.iCache.Reset(); + + CWII_IPC_HLE_Device_usb_oh1_57e_305* s_Usb = GetUsbPointer(); + size_t size = s_Usb->m_WiiMotes.size(); + bool* wiiMoteConnected = new bool[size]; + for (unsigned int i = 0; i < size; i++) + wiiMoteConnected[i] = s_Usb->m_WiiMotes[i].IsConnected(); + + WII_IPC_HLE_Interface::Reset(true); + WII_IPC_HLE_Interface::Init(); + s_Usb = GetUsbPointer(); + for (unsigned int i = 0; i < s_Usb->m_WiiMotes.size(); i++) + { + if (wiiMoteConnected[i]) + { + s_Usb->m_WiiMotes[i].Activate(false); + s_Usb->m_WiiMotes[i].Activate(true); + } + else + { + s_Usb->m_WiiMotes[i].Activate(false); + } + } + + delete[] wiiMoteConnected; + + if (argsPtr) + { + u32 args_base = Memory::Read_U32(0x800000f4); + u32 ptr_to_num_args = 0xc; + u32 num_args = 1; + u32 hi_ptr = args_base + ptr_to_num_args + 4; + u32 new_args_ptr = args_base + ptr_to_num_args + 8; + + Memory::Write_U32(ptr_to_num_args, args_base + 8); + Memory::Write_U32(num_args, args_base + ptr_to_num_args); + Memory::Write_U32(0x14, hi_ptr); + + for (unsigned int i = 0; i < args.length(); i++) + Memory::WriteUnchecked_U8(args[i], new_args_ptr+i); + } + + NPC = dolLoader.GetEntryPoint() | 0x80000000; +} + +void LoadDOLFromDisc(std::string dol) +{ + DiscIO::IVolume* pVolume = DiscIO::CreateVolumeFromFilename(SConfig::GetInstance().m_LastFilename.c_str()); + DiscIO::IFileSystem* pFileSystem = DiscIO::CreateFileSystem(pVolume); + + if (dol.length() > 1 && dol.compare(0, 1, "/") == 0) + dol = dol.substr(1); + + u32 fileSize = (u32) pFileSystem->GetFileSize(dol.c_str()); + u8* dolFile = new u8[fileSize]; + if (fileSize > 0) + { + pFileSystem->ReadFile(dol.c_str(), dolFile, fileSize); + ExecuteDOL(dolFile, fileSize); + } + delete[] dolFile; +} + +void LoadBootDOLFromDisc() +{ + DiscIO::IVolume* pVolume = DiscIO::CreateVolumeFromFilename(SConfig::GetInstance().m_LastFilename.c_str()); + DiscIO::IFileSystem* pFileSystem = DiscIO::CreateFileSystem(pVolume); + u32 fileSize = pFileSystem->GetBootDOLSize(); + u8* dolFile = new u8[fileSize]; + if (fileSize > 0) + { + pFileSystem->GetBootDOL(dolFile, fileSize); + ExecuteDOL(dolFile, fileSize); + } + delete[] dolFile; +} + +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.length() > 1 && dol.compare(0, 1, "/") == 0) + dolFile = dol.substr(1); + else + dolFile = dol; + + return (u32)pFileSystem->GetFileSize(dolFile.c_str()); +} + +void gc_memmove() +{ + u32 dest = GPR(3); + u32 src = GPR(4); + u32 count = GPR(5); + memmove((u8*)(Memory::base + dest), (u8*)(Memory::base + src), count); + NPC = LR; +} + +void gc_memcpy() +{ + u32 dest = GPR(3); + u32 src = GPR(4); + u32 count = GPR(5); + memcpy((u8*)(Memory::base + dest), (u8*)(Memory::base + src), count); + NPC = LR; +} + +void gc_memset() +{ + u32 dest = GPR(3); + u32 ch = GPR(4); + u32 count = GPR(5); + memset((u8*)(Memory::base + dest), ch, count); + NPC = LR; +} + +void gc_memcmp() +{ + u32 dest = GPR(3); + u32 src = GPR(4); + u32 count = GPR(5); + GPR(3) = 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 & 0x1fffffff) != 0) + { + GPR(3) = resetCode | 0x80000000; + } + else + { + GPR(3) = 0; + } + + NPC = LR; +} + +u16 GetIOSVersion() +{ + return Memory::Read_U16(0x00003140); +} + +void OSBootDol() +{ + if (GetIOSVersion() >= 30) + { + bootType = GPR(4); + + if ((GPR(4) >> 28) == 0x8) + { + u32 resetCode = GPR(30); + + // Reset game + Memory::Write_U32(resetCode, 0xCC003024); + LoadBootDOLFromDisc(); + return; + } + else if ((GPR(4) >> 28) == 0xA) + { + // Boot from disc partition + PanicAlert("Boot Partition: %08x", GPR(26)); + } + else if ((GPR(4) >> 28) == 0xC) + { + std::string dol; + + // Boot DOL from disc + u32 ptr = GPR(28); + Memory::GetString(dol, ptr); + + if (GetDolFileSize(dol) == 0) + { + ptr = GPR(30); + Memory::GetString(dol, ptr); + if (GetDolFileSize(dol) == 0) + { + // Cannot locate the dol file, exit. + HLE::UnPatch("__OSBootDol"); + NPC = PC; + return; + } + } + + argsPtr = Memory::Read_U32(GPR(5)); + Memory::GetString(args, argsPtr); + LoadDOLFromDisc(dol); + return; + } + else + { + PanicAlert("Unknown boot type: %08x", GPR(4)); + } + } + HLE::UnPatch("__OSBootDol"); + NPC = PC; +} + } diff --git a/Source/Core/Core/Src/HLE/HLE_Misc.h b/Source/Core/Core/Src/HLE/HLE_Misc.h index 6c932258a7..d0d098835f 100644 --- a/Source/Core/Core/Src/HLE/HLE_Misc.h +++ b/Source/Core/Core/Src/HLE/HLE_Misc.h @@ -39,6 +39,15 @@ namespace HLE_Misc void FZ_sqrt_internal(); 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); } #endif 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 4a18ce63b5..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); @@ -199,6 +198,7 @@ void Write32(const u32 _uValue, const u32 _iAddress) case PI_RESET_CODE: DEBUG_LOG(PROCESSORINTERFACE, "Write %08x to PI_RESET_CODE", _uValue); + m_ResetCode = _uValue; break; case PI_FLIPPER_UNK: diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp index 545002f914..3eb0096929 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp @@ -780,7 +780,7 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress) // someone with an affected game should test IOSv = TitleID & 0xffff; } - if (!bSuccess) + if (!bSuccess && IOSv >= 30 && IOSv != 0xffff) { PanicAlertT("IOCTL_ES_LAUNCH: Game tried to reload ios or a title that is not available in your nand dump\n" "TitleID %016llx.\n Dolphin will likely hang now", TitleID); 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 a8cc0e9b46..d409518bf9 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 7f1c9b590c..4cfc3ab934 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)); diff --git a/Source/Core/DiscIO/Src/FileSystemGCWii.cpp b/Source/Core/DiscIO/Src/FileSystemGCWii.cpp index 6103f53e67..47651e2f23 100644 --- a/Source/Core/DiscIO/Src/FileSystemGCWii.cpp +++ b/Source/Core/DiscIO/Src/FileSystemGCWii.cpp @@ -153,7 +153,7 @@ bool CFileSystemGCWii::ExportApploader(const char* _rExportFolder) const return false; } -bool CFileSystemGCWii::ExportDOL(const char* _rExportFolder) const +u32 CFileSystemGCWii::GetBootDOLSize() const { u32 DolOffset = Read32(0x420) << m_OffsetShift; u32 DolSize = 0, offset = 0, size = 0; @@ -175,6 +175,19 @@ bool CFileSystemGCWii::ExportDOL(const char* _rExportFolder) const if (offset + size > DolSize) DolSize = offset + size; } + return DolSize; +} + +bool CFileSystemGCWii::GetBootDOL(u8* &buffer, u32 DolSize) const +{ + u32 DolOffset = Read32(0x420) << m_OffsetShift; + return m_rVolume->Read(DolOffset, DolSize, buffer); +} + +bool CFileSystemGCWii::ExportDOL(const char* _rExportFolder) const +{ + u32 DolOffset = Read32(0x420) << m_OffsetShift; + u32 DolSize = GetBootDOLSize(); std::vector buffer(DolSize); if (m_rVolume->Read(DolOffset, DolSize, &buffer[0])) diff --git a/Source/Core/DiscIO/Src/FileSystemGCWii.h b/Source/Core/DiscIO/Src/FileSystemGCWii.h index 38e5f181f9..0e7d836d75 100644 --- a/Source/Core/DiscIO/Src/FileSystemGCWii.h +++ b/Source/Core/DiscIO/Src/FileSystemGCWii.h @@ -38,6 +38,8 @@ public: virtual bool ExportFile(const char* _rFullPath, const char* _rExportFilename); virtual bool ExportApploader(const char* _rExportFolder) const; virtual bool ExportDOL(const char* _rExportFolder) const; + virtual bool GetBootDOL(u8* &buffer, u32 DolSize) const; + virtual u32 GetBootDOLSize() const; private: bool m_Initialized; diff --git a/Source/Core/DiscIO/Src/Filesystem.h b/Source/Core/DiscIO/Src/Filesystem.h index 71be4293e3..8bc98e6a77 100644 --- a/Source/Core/DiscIO/Src/Filesystem.h +++ b/Source/Core/DiscIO/Src/Filesystem.h @@ -57,6 +57,8 @@ public: virtual bool ExportApploader(const char* _rExportFolder) const = 0; virtual bool ExportDOL(const char* _rExportFolder) const = 0; virtual const char* GetFileName(u64 _Address) = 0; + virtual bool GetBootDOL(u8* &buffer, u32 DolSize) const = 0; + virtual u32 GetBootDOLSize() const = 0; virtual const IVolume *GetVolume() const { return m_rVolume; } protected: