2014-12-03 14:05:05 -08:00

170 lines
4.7 KiB
C++

// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
#include "Common/CommonTypes.h"
#include "Core/ConfigManager.h"
#include "Core/Core.h"
#include "Core/Debugger/Debugger_SymbolMap.h"
#include "Core/HLE/HLE.h"
#include "Core/HLE/HLE_Misc.h"
#include "Core/HLE/HLE_OS.h"
#include "Core/HW/Memmap.h"
#include "Core/IPC_HLE/WII_IPC_HLE_Device_es.h"
#include "Core/PowerPC/PowerPC.h"
#include "Core/PowerPC/PPCSymbolDB.h"
namespace HLE
{
using namespace PowerPC;
typedef void (*TPatchFunction)();
enum
{
HLE_RETURNTYPE_BLR = 0,
HLE_RETURNTYPE_RFI = 1,
};
struct SPatch
{
char m_szPatchName[128];
TPatchFunction PatchFunction;
int type;
int flags;
};
static const SPatch OSPatches[] =
{
{ "FAKE_TO_SKIP_0", HLE_Misc::UnimplementedFunction, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC },
{ "PanicAlert", HLE_Misc::HLEPanicAlert, HLE_HOOK_REPLACE, HLE_TYPE_DEBUG },
// Name doesn't matter, installed in CBoot::BootUp()
{ "HBReload", HLE_Misc::HBReload, HLE_HOOK_REPLACE, HLE_TYPE_GENERIC },
// Debug/OS Support
{ "OSPanic", HLE_OS::HLE_OSPanic, HLE_HOOK_REPLACE, HLE_TYPE_DEBUG },
{ "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 },
{ "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?)
{ "GeckoCodehandler", HLE_Misc::HLEGeckoCodehandler, HLE_HOOK_START, HLE_TYPE_GENERIC },
};
static const SPatch OSBreakPoints[] =
{
{ "FAKE_TO_SKIP_0", HLE_Misc::UnimplementedFunction },
};
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))
{
orig_instruction[addr] = i;
return;
}
}
}
void PatchFunctions()
{
orig_instruction.clear();
for (u32 i = 0; i < sizeof(OSPatches) / sizeof(SPatch); i++)
{
Symbol *symbol = g_symbolDB.GetSymbolFromName(OSPatches[i].m_szPatchName);
if (symbol)
{
for (u32 addr = symbol->address; addr < symbol->address + symbol->size; addr += 4)
{
orig_instruction[addr] = i;
}
INFO_LOG(OSHLE, "Patching %s %08x", OSPatches[i].m_szPatchName, symbol->address);
}
}
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableDebugging)
{
for (size_t i = 1; i < sizeof(OSBreakPoints) / sizeof(SPatch); i++)
{
Symbol *symbol = g_symbolDB.GetSymbolFromName(OSPatches[i].m_szPatchName);
if (symbol)
{
PowerPC::breakpoints.Add(symbol->address, false);
INFO_LOG(OSHLE, "Adding BP to %s %08x", OSBreakPoints[i].m_szPatchName, symbol->address);
}
}
}
// CBreakPoints::AddBreakPoint(0x8000D3D0, false);
}
void Execute(u32 _CurrentPC, u32 _Instruction)
{
unsigned int FunctionIndex = _Instruction & 0xFFFFF;
if ((FunctionIndex > 0) && (FunctionIndex < (sizeof(OSPatches) / sizeof(SPatch))))
{
OSPatches[FunctionIndex].PatchFunction();
}
else
{
PanicAlert("HLE system tried to call an undefined HLE function %i.", FunctionIndex);
}
// _dbg_assert_msg_(HLE,NPC == LR, "Broken HLE function (doesn't set NPC)", OSPatches[pos].m_szPatchName);
}
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_DEBUG && !SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableDebugging && PowerPC::GetMode() != MODE_INTERPRETER)
return false;
return true;
}
u32 UnPatch(const std::string& patchName)
{
Symbol* symbol = g_symbolDB.GetSymbolFromName(patchName);
if (symbol)
{
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