Merge branch 'ES_LAUNCH'

Games that are now playable:

Back to the Future: The Game
CSI - Hard Evidence
CSI - Deadly Intent
CSI - Fatal Conspiracy
Red Steel
Metroid Prime: Trilogy
Wii Sports + Wii Sports Resort pack
Sam & Max: Season One
Sam & Max: Beyond Time and Space
Kirby's Dream Collection: Classic Collection
Indiana Jones and the Staff of Kings: Fate of Atlantis


* ES_LAUNCH:
  Fixed SSBB from starting at the mini-games screen.
  Build fix
  Corrected a state bug where newly loaded dols did not have their patches applied.
  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.
  Added some IOS version checks and code to clear memory before loading the dol.
  Added support for Reset (from menu).  Fixes Sam & Max.
  Added an IOS check as games which use IOS older than IOS30 do not need to be HLE'd.  Added some stubs for Reset to Menu and SSBB's load from disc partition.  Fixed loading Fate of Atlantis from the Indiana Jones and the Staff of Kings game.
  Added argument detection and passing to the loaded dol.  This fixes the Wii Sports+Wii Sports Resort bundle pack.
  Added preliminary support for ES_LAUNCH (Wii Multi-boot games) by using HLE to hijack the OSBootDol function.

Conflicts:
	Source/Core/DiscIO/Src/FileSystemGCWii.cpp
This commit is contained in:
skidau 2013-01-16 20:22:29 +11:00
commit 7e5d877858
18 changed files with 578 additions and 114 deletions

Binary file not shown.

View File

@ -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))

View File

@ -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);

View File

@ -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"
@ -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<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;
}
}
@ -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<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());
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

View File

@ -18,15 +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

View File

@ -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;
}
}

View File

@ -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

View File

@ -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)

View File

@ -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:

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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));

View File

@ -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);

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)
{
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));

View File

@ -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<u8> buffer(DolSize);
if (m_rVolume->Read(DolOffset, DolSize, &buffer[0]))

View File

@ -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;

View File

@ -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: