mirror of
https://github.com/OatmealDome/dolphin-ios.git
synced 2024-11-23 14:39:52 +00:00
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:
parent
05730af724
commit
95f6685900
Binary file not shown.
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -15,7 +15,6 @@
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include <map>
|
||||
#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<u32, u32> 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<u32, u32>::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;
|
||||
|
@ -18,16 +18,40 @@
|
||||
#ifndef _HLE_H
|
||||
#define _HLE_H
|
||||
|
||||
#include <map>
|
||||
#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<u32, u32> orig_instruction;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
|
Loading…
Reference in New Issue
Block a user