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.
This commit is contained in:
skidau 2012-12-28 14:26:46 +11:00
parent 05730af724
commit 95f6685900
14 changed files with 339 additions and 123 deletions

Binary file not shown.

View File

@ -258,7 +258,7 @@ bool CBoot::BootUp()
} }
// Scan for common HLE functions // Scan for common HLE functions
if (!_StartupPara.bEnableDebugging && Memory::Read_U16(0x00003140) >= 30) if (_StartupPara.bSkipIdle && !_StartupPara.bEnableDebugging)
{ {
PPCAnalyst::FindFunctions(0x80004000, 0x811fffff, &g_symbolDB); PPCAnalyst::FindFunctions(0x80004000, 0x811fffff, &g_symbolDB);
SignatureDB db; SignatureDB db;
@ -267,7 +267,6 @@ bool CBoot::BootUp()
db.Apply(&g_symbolDB); db.Apply(&g_symbolDB);
HLE::PatchFunctions(); HLE::PatchFunctions();
db.Clear(); db.Clear();
g_symbolDB.Clear();
} }
} }

View File

@ -375,7 +375,7 @@ bool CBoot::EmulatedBS2_Wii()
u32 iLength = Memory::ReadUnchecked_U32(0x81300008); u32 iLength = Memory::ReadUnchecked_U32(0x81300008);
u32 iDVDOffset = Memory::ReadUnchecked_U32(0x8130000c) << 2; 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); DVDInterface::DVDRead(iDVDOffset, iRamAddress, iLength);
} while(PowerPC::ppcState.gpr[3] != 0x00); } while(PowerPC::ppcState.gpr[3] != 0x00);

View File

@ -15,7 +15,6 @@
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include <map>
#include "Common.h" #include "Common.h"
#include "HLE.h" #include "HLE.h"
@ -29,6 +28,7 @@
#include "HLE_Misc.h" #include "HLE_Misc.h"
#include "IPC_HLE/WII_IPC_HLE_Device_es.h" #include "IPC_HLE/WII_IPC_HLE_Device_es.h"
#include "ConfigManager.h" #include "ConfigManager.h"
#include "Core.h"
namespace HLE namespace HLE
{ {
@ -47,56 +47,72 @@ struct SPatch
{ {
char m_szPatchName[128]; char m_szPatchName[128];
TPatchFunction PatchFunction; TPatchFunction PatchFunction;
int type;
int flags;
}; };
static const SPatch OSPatches[] = 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 // speedup
//{ "OSProtectRange", HLE_Misc::UnimplementedFunctionFalse }, //{ "OSProtectRange", HLE_Misc::UnimplementedFunctionFalse, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC },
//{ "THPPlayerGetState", HLE_Misc:THPPlayerGetState }, //{ "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 ;) // debug out is very nice ;)
{ "OSReport", HLE_OS::HLE_GeneralDebugPrint }, { "OSReport", HLE_OS::HLE_GeneralDebugPrint, HLE_HOOK_REPLACE, HLE_TYPE_DEBUG },
{ "DEBUGPrint", HLE_OS::HLE_GeneralDebugPrint }, { "DEBUGPrint", HLE_OS::HLE_GeneralDebugPrint, HLE_HOOK_REPLACE, HLE_TYPE_DEBUG },
{ "WUD_DEBUGPrint", HLE_OS::HLE_GeneralDebugPrint }, { "WUD_DEBUGPrint", HLE_OS::HLE_GeneralDebugPrint, HLE_HOOK_REPLACE, HLE_TYPE_DEBUG },
{ "OSPanic", HLE_OS::HLE_OSPanic }, { "OSPanic", HLE_OS::HLE_OSPanic, HLE_HOOK_REPLACE, HLE_TYPE_DEBUG },
{ "vprintf", HLE_OS::HLE_GeneralDebugPrint }, { "vprintf", HLE_OS::HLE_GeneralDebugPrint, HLE_HOOK_REPLACE, HLE_TYPE_DEBUG },
{ "printf", HLE_OS::HLE_GeneralDebugPrint }, { "printf", HLE_OS::HLE_GeneralDebugPrint, HLE_HOOK_REPLACE, HLE_TYPE_DEBUG },
{ "puts", HLE_OS::HLE_GeneralDebugPrint }, // gcc-optimized printf? { "puts", HLE_OS::HLE_GeneralDebugPrint, HLE_HOOK_REPLACE, HLE_TYPE_DEBUG }, // gcc-optimized printf?
{ "___blank(char *,...)", HLE_OS::HLE_GeneralDebugPrint }, // used for early init things (normally) { "___blank(char *,...)", HLE_OS::HLE_GeneralDebugPrint, HLE_HOOK_REPLACE, HLE_TYPE_DEBUG }, // used for early init things (normally)
{ "___blank", HLE_OS::HLE_GeneralDebugPrint }, { "___blank", HLE_OS::HLE_GeneralDebugPrint, HLE_HOOK_REPLACE, HLE_TYPE_DEBUG },
{ "__write_console", HLE_OS::HLE_write_console }, // used by sysmenu (+more?) { "__write_console", HLE_OS::HLE_write_console, HLE_HOOK_REPLACE, HLE_TYPE_DEBUG }, // used by sysmenu (+more?)
// wii only // wii only
//{ "__OSInitAudioSystem", HLE_Misc::UnimplementedFunction }, //{ "__OSInitAudioSystem", HLE_Misc::UnimplementedFunction, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC },
// Super Monkey Ball - no longer needed. // Super Monkey Ball - no longer needed.
//{ ".evil_vec_cosine", HLE_Misc::SMB_EvilVecCosine }, //{ ".evil_vec_cosine", HLE_Misc::SMB_EvilVecCosine, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC },
//{ ".evil_normalize", HLE_Misc::SMB_EvilNormalize }, //{ ".evil_normalize", HLE_Misc::SMB_EvilNormalize, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC },
//{ ".evil_vec_setlength", HLE_Misc::SMB_evil_vec_setlength }, //{ ".evil_vec_setlength", HLE_Misc::SMB_evil_vec_setlength, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC },
//{ ".evil_vec_something", HLE_Misc::FZero_evil_vec_normalize }, //{ ".evil_vec_something", HLE_Misc::FZero_evil_vec_normalize, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC },
{ "PanicAlert", HLE_Misc::HLEPanicAlert }, { "PanicAlert", HLE_Misc::HLEPanicAlert, HLE_HOOK_REPLACE, HLE_TYPE_DEBUG },
//{ ".sqrt_internal_needs_cr1", HLE_Misc::SMB_sqrt_internal }, //{ ".sqrt_internal_needs_cr1", HLE_Misc::SMB_sqrt_internal, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC },
//{ ".rsqrt_internal_needs_cr1", HLE_Misc::SMB_rsqrt_internal }, //{ ".rsqrt_internal_needs_cr1", HLE_Misc::SMB_rsqrt_internal, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC },
//{ ".atan2", HLE_Misc::SMB_atan2}, //{ ".atan2", HLE_Misc::SMB_atan2HLE_HOOK_REPLACE, HLE_TYPE_GENERIC },
//{ ".sqrt_fz", HLE_Misc::FZ_sqrt}, //{ ".sqrt_fz", HLE_Misc::FZ_sqrtHLE_HOOK_REPLACE, HLE_TYPE_GENERIC },
// F-zero still isn't working correctly, but these aren't really helping. // F-zero still isn't working correctly, but these aren't really helping.
//{ ".sqrt_internal_fz", HLE_Misc::FZ_sqrt_internal }, //{ ".sqrt_internal_fz", HLE_Misc::FZ_sqrt_internal, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC },
//{ ".rsqrt_internal_fz", HLE_Misc::FZ_rsqrt_internal }, //{ ".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 // special
// { "GXPeekZ", HLE_Misc::GXPeekZ}, // { "GXPeekZ", HLE_Misc::GXPeekZHLE_HOOK_REPLACE, HLE_TYPE_GENERIC },
// { "GXPeekARGB", HLE_Misc::GXPeekARGB}, // { "GXPeekARGB", HLE_Misc::GXPeekARGBHLE_HOOK_REPLACE, HLE_TYPE_GENERIC },
// Name doesn't matter, installed in CBoot::BootUp() // Name doesn't matter, installed in CBoot::BootUp()
{ "HBReload", HLE_Misc::HBReload }, { "HBReload", HLE_Misc::HBReload, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC },
{ "__OSBootDol", HLE_Misc::OSBootDol },
// 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[] = static const SPatch OSBreakPoints[] =
@ -104,17 +120,13 @@ static const SPatch OSBreakPoints[] =
{ "FAKE_TO_SKIP_0", HLE_Misc::UnimplementedFunction }, { "FAKE_TO_SKIP_0", HLE_Misc::UnimplementedFunction },
}; };
void Patch(u32 addr, const char *hle_func_name)
static std::map<u32, u32> orig_instruction;
void Patch(u32 address, const char *hle_func_name)
{ {
for (u32 i = 0; i < sizeof(OSPatches) / sizeof(SPatch); i++) for (u32 i = 0; i < sizeof(OSPatches) / sizeof(SPatch); i++)
{ {
if (!strcmp(OSPatches[i].m_szPatchName, hle_func_name)) if (!strcmp(OSPatches[i].m_szPatchName, hle_func_name))
{ {
u32 HLEPatchValue = (1 & 0x3f) << 26; orig_instruction[addr] = i;
Memory::Write_U32(HLEPatchValue | i, address);
return; return;
} }
} }
@ -128,11 +140,9 @@ void PatchFunctions()
Symbol *symbol = g_symbolDB.GetSymbolFromName(OSPatches[i].m_szPatchName); Symbol *symbol = g_symbolDB.GetSymbolFromName(OSPatches[i].m_szPatchName);
if (symbol > 0) if (symbol > 0)
{ {
u32 HLEPatchValue = (1 & 0x3f) << 26;
for (u32 addr = symbol->address; addr < symbol->address + symbol->size; addr += 4) for (u32 addr = symbol->address; addr < symbol->address + symbol->size; addr += 4)
{ {
orig_instruction[addr] = Memory::ReadUnchecked_U32(addr); orig_instruction[addr] = i;
Memory::Write_U32(HLEPatchValue | i, addr);
} }
INFO_LOG(OSHLE, "Patching %s %08x", OSPatches[i].m_szPatchName, symbol->address); 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); // _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<u32, u32>::const_iterator iter = orig_instruction.find(addr); std::map<u32, u32>::const_iterator iter = orig_instruction.find(addr);
return (iter != orig_instruction.end()) ? iter->second : 0; 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) u32 UnPatch(std::string patchName)
{ {
Symbol *symbol = g_symbolDB.GetSymbolFromName(patchName.c_str()); 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) 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); PowerPC::ppcState.iCache.Invalidate(addr);
} }
return symbol->address; return symbol->address;

View File

@ -18,16 +18,40 @@
#ifndef _HLE_H #ifndef _HLE_H
#define _HLE_H #define _HLE_H
#include <map>
#include "Common.h" #include "Common.h"
namespace HLE 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 PatchFunctions();
void Patch(u32 pc, const char *func_name); void Patch(u32 pc, const char *func_name);
u32 UnPatch(std::string patchName); u32 UnPatch(std::string patchName);
void Execute(u32 _CurrentPC, u32 _Instruction); 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<u32, u32> orig_instruction;
} }
#endif #endif

View File

@ -37,7 +37,6 @@
namespace HLE_Misc namespace HLE_Misc
{ {
std::string dol;
std::string args; std::string args;
u32 argsPtr; u32 argsPtr;
u32 bootType; u32 bootType;
@ -302,7 +301,7 @@ void HBReload()
void ExecuteDOL(u8* dolFile, u32 fileSize) void ExecuteDOL(u8* dolFile, u32 fileSize)
{ {
// Clear memory before loading the dol // 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" // TODO: Should not write over the "save region"
Memory::Write_U32(0x00000000, i); Memory::Write_U32(0x00000000, i);
@ -320,7 +319,6 @@ void ExecuteDOL(u8* dolFile, u32 fileSize)
db.Apply(&g_symbolDB); db.Apply(&g_symbolDB);
HLE::PatchFunctions(); HLE::PatchFunctions();
db.Clear(); db.Clear();
g_symbolDB.Clear();
} }
} }
@ -359,12 +357,12 @@ void ExecuteDOL(u8* dolFile, u32 fileSize)
NPC = dolLoader.GetEntryPoint() | 0x80000000; NPC = dolLoader.GetEntryPoint() | 0x80000000;
} }
void LoadDOLFromDisc() void LoadDOLFromDisc(std::string dol)
{ {
DiscIO::IVolume* pVolume = DiscIO::CreateVolumeFromFilename(SConfig::GetInstance().m_LastFilename.c_str()); DiscIO::IVolume* pVolume = DiscIO::CreateVolumeFromFilename(SConfig::GetInstance().m_LastFilename.c_str());
DiscIO::IFileSystem* pFileSystem = DiscIO::CreateFileSystem(pVolume); 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); dol = dol.substr(1);
u32 fileSize = (u32) pFileSystem->GetFileSize(dol.c_str()); u32 fileSize = (u32) pFileSystem->GetFileSize(dol.c_str());
@ -391,19 +389,92 @@ void LoadBootDOLFromDisc()
delete[] dolFile; delete[] dolFile;
} }
u32 GetDolFileSize() u32 GetDolFileSize(std::string dol)
{ {
DiscIO::IVolume* pVolume = DiscIO::CreateVolumeFromFilename(SConfig::GetInstance().m_LastFilename.c_str()); DiscIO::IVolume* pVolume = DiscIO::CreateVolumeFromFilename(SConfig::GetInstance().m_LastFilename.c_str());
DiscIO::IFileSystem* pFileSystem = DiscIO::CreateFileSystem(pVolume); DiscIO::IFileSystem* pFileSystem = DiscIO::CreateFileSystem(pVolume);
std::string dolFile; std::string dolFile;
if (dol.substr(1, 1).compare("//")) if (dol.length() > 1 && dol.compare(0, 1, "/") == 0)
dolFile = dol.substr(1); dolFile = dol.substr(1);
else
dolFile = dol;
return (u32)pFileSystem->GetFileSize(dolFile.c_str()); 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() void OSBootDol()
{ {
IOSv = Memory::Read_U16(0x00003140); IOSv = Memory::Read_U16(0x00003140);
@ -417,8 +488,7 @@ void OSBootDol()
u32 resetCode = GPR(30); u32 resetCode = GPR(30);
// Reset game // Reset game
Memory::Write_U32(resetCode << 3, 0xCC003024); Memory::Write_U32(resetCode, 0xCC003024);
//Memory::Write_U32((resetCode << 3) | 0x80000000, 0x800030f0); // Warm reset
LoadBootDOLFromDisc(); LoadBootDOLFromDisc();
return; return;
} }
@ -429,15 +499,17 @@ void OSBootDol()
} }
else if ((GPR(4) >> 28) == 0xC) else if ((GPR(4) >> 28) == 0xC)
{ {
std::string dol;
// Boot DOL from disc // Boot DOL from disc
u32 ptr = GPR(28); u32 ptr = GPR(28);
Memory::GetString(dol, ptr); Memory::GetString(dol, ptr);
if (GetDolFileSize() == 0) if (GetDolFileSize(dol) == 0)
{ {
ptr = GPR(30); ptr = GPR(30);
Memory::GetString(dol, ptr); Memory::GetString(dol, ptr);
if (GetDolFileSize() == 0) if (GetDolFileSize(dol) == 0)
{ {
// Cannot locate the dol file, exit. // Cannot locate the dol file, exit.
HLE::UnPatch("__OSBootDol"); HLE::UnPatch("__OSBootDol");
@ -448,7 +520,7 @@ void OSBootDol()
argsPtr = Memory::Read_U32(GPR(5)); argsPtr = Memory::Read_U32(GPR(5));
Memory::GetString(args, argsPtr); Memory::GetString(args, argsPtr);
LoadDOLFromDisc(); LoadDOLFromDisc(dol);
return; return;
} }
else else

View File

@ -40,6 +40,13 @@ namespace HLE_Misc
void FZ_rsqrt_internal(); void FZ_rsqrt_internal();
void HBReload(); void HBReload();
void OSBootDol(); void OSBootDol();
void OSGetResetCode();
void memcpy();
void memset();
void memmove();
void memcmp();
void div2i();
void div2u();
void ExecuteDOL(u8* dolFile, u32 fileSize); void ExecuteDOL(u8* dolFile, u32 fileSize);
} }

View File

@ -416,10 +416,7 @@ bool AreMemoryBreakpointsActivated()
u32 Read_Instruction(const u32 em_address) u32 Read_Instruction(const u32 em_address)
{ {
UGeckoInstruction inst = ReadUnchecked_U32(em_address); UGeckoInstruction inst = ReadUnchecked_U32(em_address);
if (inst.OPCD == 1) return inst.hex;
return HLE::GetOrigInstruction(em_address);
else
return inst.hex;
} }
u32 Read_Opcode_JIT_Uncached(const u32 _Address) u32 Read_Opcode_JIT_Uncached(const u32 _Address)

View File

@ -96,8 +96,7 @@ void Init()
m_FlipperRev = 0x246500B1; // revision C m_FlipperRev = 0x246500B1; // revision C
m_Unknown = 0; m_Unknown = 0;
// Bleh, why? m_ResetCode = 0x80000000; // Cold reset
//m_ResetCode |= 0x80000000;
m_InterruptCause = INT_CAUSE_RST_BUTTON | INT_CAUSE_VI; m_InterruptCause = INT_CAUSE_RST_BUTTON | INT_CAUSE_VI;
toggleResetButton = CoreTiming::RegisterEvent("ToggleResetButton", &ToggleResetButtonCallback); toggleResetButton = CoreTiming::RegisterEvent("ToggleResetButton", &ToggleResetButtonCallback);

View File

@ -26,6 +26,7 @@
#include "PowerPCDisasm.h" #include "PowerPCDisasm.h"
#include "../../IPC_HLE/WII_IPC_HLE.h" #include "../../IPC_HLE/WII_IPC_HLE.h"
#include "Atomic.h" #include "Atomic.h"
#include "HLE/HLE.h"
namespace { namespace {
@ -79,57 +80,63 @@ int startTrace = 0;
void Trace( UGeckoInstruction &instCode ) void Trace( UGeckoInstruction &instCode )
{ {
char regs[500]=""; char reg[25]="";
std::string regs = "";
for (int i=0; i<32; i++) { 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++) { for (int i=0; i<32; i++) {
sprintf(fregs, "%sf%02d: %08llx %08llx ", fregs, i, sprintf(freg, "f%02d: %08llx %08llx ", i, PowerPC::ppcState.ps[i][0], PowerPC::ppcState.ps[i][1]);
PowerPC::ppcState.ps[i][0], PowerPC::ppcState.ps[i][1]); fregs.append(freg);
} }
char ppcInst[256]; char ppcInst[256];
DisassembleGekko(instCode.hex, PC, 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) int Interpreter::SingleStepInner(void)
{ {
static UGeckoInstruction instCode; static UGeckoInstruction instCode;
NPC = PC + sizeof(UGeckoInstruction); u32 function = m_EndBlock ? HLE::GetFunctionIndex(PC) : 0; // Check for HLE functions after branches
instCode.hex = Memory::Read_Opcode(PC); if (function != 0)
// Uncomment to trace the interpreter
//if ((PC & 0xffffff)>=0x0ab54c && (PC & 0xffffff)<=0x0ab624)
// startTrace = 1;
//else
// startTrace = 0;
if (startTrace)
{ {
Trace(instCode); int type = HLE::GetFunctionTypeByIndex(function);
} if (type == HLE::HLE_HOOK_START || type == HLE::HLE_HOOK_REPLACE)
if (instCode.hex != 0)
{
UReg_MSR& msr = (UReg_MSR&)MSR;
if (msr.FP) //If FPU is enabled, just execute
{ {
m_opTable[instCode.OPCD](instCode); int flags = HLE::GetFunctionFlagsByIndex(function);
if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) if (HLE::IsEnabled(flags))
{ {
PowerPC::CheckExceptions(); HLEFunction(function);
m_EndBlock = true;
} }
} }
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 Trace(instCode);
if (!PPCTables::UsesFPU(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); m_opTable[instCode.OPCD](instCode);
if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI) if (PowerPC::ppcState.Exceptions & EXCEPTION_DSI)
@ -140,17 +147,30 @@ int Interpreter::SingleStepInner(void)
} }
else else
{ {
Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_FPU_UNAVAILABLE); // check if we have to generate a FPU unavailable exception
PowerPC::CheckExceptions(); if (!PPCTables::UsesFPU(instCode))
m_EndBlock = true; {
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
else {
{ // Memory exception on instruction fetch
// Memory exception on instruction fetch PowerPC::CheckExceptions();
PowerPC::CheckExceptions(); m_EndBlock = true;
m_EndBlock = true; }
} }
last_pc = PC; last_pc = PC;
PC = NPC; PC = NPC;

View File

@ -252,8 +252,6 @@ void Jit64::HLEFunction(UGeckoInstruction _inst)
gpr.Flush(FLUSH_ALL); gpr.Flush(FLUSH_ALL);
fpr.Flush(FLUSH_ALL); fpr.Flush(FLUSH_ALL);
ABI_CallFunctionCC((void*)&HLE::Execute, js.compilerPC, _inst.hex); ABI_CallFunctionCC((void*)&HLE::Execute, js.compilerPC, _inst.hex);
MOV(32, R(EAX), M(&NPC));
WriteExitDestInEAX();
} }
void Jit64::DoNothing(UGeckoInstruction _inst) 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)); 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 (!ops[i].skip)
{ {
if ((opinfo->flags & FL_USE_FPU) && !js.firstFPInstructionFound) 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; 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) if (memory_exception)
{ {
// Address of instruction could not be translated // Address of instruction could not be translated

View File

@ -199,7 +199,7 @@ namespace JitILProfiler
static u64 beginTime; static u64 beginTime;
static Block& Add(u64 codeHash) static Block& Add(u64 codeHash)
{ {
const u32 _blockIndex = blocks.size(); const u32 _blockIndex = (u32)blocks.size();
blocks.push_back(Block()); blocks.push_back(Block());
Block& block = blocks.back(); Block& block = blocks.back();
block.index = _blockIndex; 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; 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 (!ops[i].skip)
{ {
if (js.memcheck && (opinfo->flags & FL_USE_FPU)) 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)); ibuild.EmitBreakPointCheck(ibuild.EmitIntConst(ops[i].address));
} }
JitILTables::CompileInstruction(ops[i]); JitILTables::CompileInstruction(ops[i]);
if (js.memcheck && (opinfo->flags & FL_LOADSTORE)) 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) if (memory_exception)
{ {
ibuild.EmitISIException(ibuild.EmitIntConst(em_address)); ibuild.EmitISIException(ibuild.EmitIntConst(em_address));

View File

@ -135,7 +135,11 @@ bool JitBlock::ContainsAddress(u32 em_address)
// is full and when saving and loading states. // is full and when saving and loading states.
void JitBlockCache::Clear() 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++) for (int i = 0; i < num_blocks; i++)
{ {
DestroyBlock(i, false); DestroyBlock(i, false);

View File

@ -269,23 +269,18 @@ void EmuCodeBlock::SafeWriteRegToReg(X64Reg reg_value, X64Reg reg_addr, int acce
void EmuCodeBlock::SafeWriteFloatToReg(X64Reg xmm_value, X64Reg reg_addr) 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) { if (false && cpu_info.bSSSE3) {
// This path should be faster but for some reason it causes errors so I've disabled it. // 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); FixupBranch argh = J_CC(CC_Z);
MOVSS(M(&float_buffer), xmm_value); MOVSS(M(&float_buffer), xmm_value);
MOV(32, R(EAX), M(&float_buffer)); MOV(32, R(EAX), M(&float_buffer));