2019-08-17 13:51:31 -04:00
|
|
|
#include <cstring>
|
2008-01-15 20:27:44 +00:00
|
|
|
#include "Iop_Dynamic.h"
|
2024-07-22 12:54:35 -04:00
|
|
|
#include "Log.h"
|
|
|
|
|
|
|
|
#define LOG_NAME ("iop_dynamic")
|
2008-01-15 20:27:44 +00:00
|
|
|
|
|
|
|
using namespace Iop;
|
|
|
|
|
2024-07-22 12:54:35 -04:00
|
|
|
static constexpr uint32 g_exportModuleNameOffset = 3;
|
|
|
|
static constexpr uint32 g_exportFctTableOffset = 5;
|
|
|
|
|
|
|
|
CDynamic::CDynamic(const uint32* exportTable)
|
2018-04-30 21:01:23 +01:00
|
|
|
: m_exportTable(exportTable)
|
2021-01-25 20:50:57 -05:00
|
|
|
{
|
|
|
|
m_name = GetDynamicModuleName(exportTable);
|
2024-07-22 12:54:35 -04:00
|
|
|
m_functionCount = GetDynamicModuleExportCount(exportTable);
|
2021-01-25 20:50:57 -05:00
|
|
|
}
|
|
|
|
|
2024-07-22 12:54:35 -04:00
|
|
|
std::string CDynamic::GetDynamicModuleName(const uint32* exportTable)
|
2008-01-15 20:27:44 +00:00
|
|
|
{
|
2012-10-21 01:41:14 +00:00
|
|
|
//Name is 8 bytes long without zero, so we need to make sure it's properly null-terminated
|
|
|
|
const unsigned int nameLength = 8;
|
|
|
|
char name[nameLength + 1];
|
|
|
|
memset(name, 0, nameLength + 1);
|
2024-07-22 12:54:35 -04:00
|
|
|
memcpy(name, reinterpret_cast<const char*>(exportTable + g_exportModuleNameOffset), nameLength);
|
2021-01-25 20:50:57 -05:00
|
|
|
return name;
|
2008-01-15 20:27:44 +00:00
|
|
|
}
|
|
|
|
|
2024-07-22 12:54:35 -04:00
|
|
|
uint32 CDynamic::GetDynamicModuleExportCount(const uint32* exportTable)
|
|
|
|
{
|
|
|
|
//Export tables are supposed to finish with a 0 value.
|
|
|
|
uint32 functionCount = 0;
|
|
|
|
while(exportTable[g_exportFctTableOffset + functionCount] != 0)
|
|
|
|
{
|
|
|
|
functionCount++;
|
|
|
|
if(functionCount >= 1000)
|
|
|
|
{
|
|
|
|
CLog::GetInstance().Warn(LOG_NAME, "Export count exceeded threshold of %d functions. Bailing.\r\n", functionCount);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return functionCount;
|
|
|
|
}
|
|
|
|
|
2012-04-07 20:38:41 +00:00
|
|
|
std::string CDynamic::GetId() const
|
2008-01-15 20:27:44 +00:00
|
|
|
{
|
2012-04-07 20:38:41 +00:00
|
|
|
return m_name;
|
2008-01-15 20:27:44 +00:00
|
|
|
}
|
|
|
|
|
2012-04-07 20:38:41 +00:00
|
|
|
std::string CDynamic::GetFunctionName(unsigned int functionId) const
|
2008-11-28 23:46:52 +00:00
|
|
|
{
|
2012-04-12 03:50:09 +00:00
|
|
|
char functionName[256];
|
2017-05-29 06:01:32 +01:00
|
|
|
sprintf(functionName, "unknown_%04X", functionId);
|
2012-04-12 03:50:09 +00:00
|
|
|
return functionName;
|
2008-11-28 23:46:52 +00:00
|
|
|
}
|
|
|
|
|
2008-01-15 20:27:44 +00:00
|
|
|
void CDynamic::Invoke(CMIPS& context, unsigned int functionId)
|
|
|
|
{
|
2024-07-22 12:54:35 -04:00
|
|
|
if(functionId < m_functionCount)
|
|
|
|
{
|
|
|
|
uint32 functionAddress = m_exportTable[g_exportFctTableOffset + functionId];
|
|
|
|
context.m_State.nGPR[CMIPS::RA].nD0 = context.m_State.nPC;
|
|
|
|
context.m_State.nPC = functionAddress;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CLog::GetInstance().Warn(LOG_NAME, "Failed to find export %d for module '%s'.\r\n",
|
|
|
|
functionId, m_name.c_str());
|
|
|
|
}
|
2008-01-15 20:27:44 +00:00
|
|
|
}
|
2009-02-06 05:10:51 +00:00
|
|
|
|
2024-07-22 12:54:35 -04:00
|
|
|
const uint32* CDynamic::GetExportTable() const
|
2009-02-06 05:10:51 +00:00
|
|
|
{
|
2012-04-07 20:38:41 +00:00
|
|
|
return m_exportTable;
|
2009-02-06 05:10:51 +00:00
|
|
|
}
|