Play-/Source/iop/Iop_Modload.cpp

313 lines
10 KiB
C++
Raw Normal View History

#include "Iop_Modload.h"
#include "IopBios.h"
2025-03-11 12:48:26 -04:00
#include "Log.h"
using namespace Iop;
2018-04-30 21:01:23 +01:00
#define LOG_NAME ("iop_modload")
2018-04-30 21:01:23 +01:00
#define FUNCTION_LOADSTARTMODULE "LoadStartModule"
#define FUNCTION_STARTMODULE "StartModule"
2020-05-03 12:07:08 -04:00
#define FUNCTION_LOADMODULEBUFFERADDRESS "LoadModuleBufferAddress"
2018-04-30 21:01:23 +01:00
#define FUNCTION_LOADMODULEBUFFER "LoadModuleBuffer"
#define FUNCTION_GETMODULEIDLIST "GetModuleIdList"
#define FUNCTION_REFERMODULESTATUS "ReferModuleStatus"
2025-02-27 15:30:16 -05:00
#define FUNCTION_GETMODULEIDLISTBYNAME "GetModuleIdListByName"
#define FUNCTION_LOADMODULEWITHOPTION "LoadModuleWithOption"
2022-02-22 14:00:23 -05:00
#define FUNCTION_STOPMODULE "StopModule"
#define FUNCTION_UNLOADMODULE "UnloadModule"
2018-04-30 21:01:23 +01:00
#define FUNCTION_SEARCHMODULEBYNAME "SearchModuleByName"
2021-01-03 20:38:15 -05:00
#define FUNCTION_ALLOCLOADMEMORY "AllocLoadMemory"
2016-12-05 11:06:37 -05:00
struct LMWO_OPTION
{
uint8 position;
uint8 access;
uint8 reserved1[2];
uint32 distAddrPtr;
uint32 distOffset;
uint32 funcTablePtr;
uint32 funcOpt;
uint32 reserved2[3];
};
static_assert(sizeof(LMWO_OPTION) == 0x20);
2016-12-04 21:45:03 -05:00
CModload::CModload(CIopBios& bios, uint8* ram)
2018-04-30 21:01:23 +01:00
: m_bios(bios)
, m_ram(ram)
{
}
std::string CModload::GetId() const
{
return "modload";
}
std::string CModload::GetFunctionName(unsigned int functionId) const
{
switch(functionId)
{
case 7:
2016-12-05 11:06:37 -05:00
return FUNCTION_LOADSTARTMODULE;
break;
case 8:
2016-12-05 11:06:37 -05:00
return FUNCTION_STARTMODULE;
break;
2020-05-03 12:07:08 -04:00
case 9:
return FUNCTION_LOADMODULEBUFFERADDRESS;
break;
case 10:
2016-12-05 11:06:37 -05:00
return FUNCTION_LOADMODULEBUFFER;
break;
case 16:
2016-12-05 11:06:37 -05:00
return FUNCTION_GETMODULEIDLIST;
break;
case 17:
2016-12-05 11:06:37 -05:00
return FUNCTION_REFERMODULESTATUS;
break;
2025-02-27 15:30:16 -05:00
case 18:
return FUNCTION_GETMODULEIDLISTBYNAME;
break;
case 19:
return FUNCTION_LOADMODULEWITHOPTION;
break;
2022-02-22 14:00:23 -05:00
case 20:
return FUNCTION_STOPMODULE;
break;
case 21:
return FUNCTION_UNLOADMODULE;
break;
case 22:
return FUNCTION_SEARCHMODULEBYNAME;
break;
2021-01-03 20:38:15 -05:00
case 28:
return FUNCTION_ALLOCLOADMEMORY;
break;
default:
return "unknown";
break;
}
}
void CModload::Invoke(CMIPS& context, unsigned int functionId)
{
switch(functionId)
{
case 7:
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(LoadStartModule(
2018-04-30 21:01:23 +01:00
context.m_State.nGPR[CMIPS::A0].nV0,
context.m_State.nGPR[CMIPS::A1].nV0,
context.m_State.nGPR[CMIPS::A2].nV0,
context.m_State.nGPR[CMIPS::A3].nV0));
break;
case 8:
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(StartModule(
2018-04-30 21:01:23 +01:00
context.m_State.nGPR[CMIPS::A0].nV0,
context.m_State.nGPR[CMIPS::A1].nV0,
context.m_State.nGPR[CMIPS::A2].nV0,
context.m_State.nGPR[CMIPS::A3].nV0,
context.m_pMemoryMap->GetWord(context.m_State.nGPR[CMIPS::SP].nV0 + 0x10)));
break;
2020-05-03 12:07:08 -04:00
case 9:
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(LoadModuleBufferAddress(
2020-05-03 12:55:45 -04:00
context.m_State.nGPR[CMIPS::A0].nV0,
context.m_State.nGPR[CMIPS::A1].nV0,
context.m_State.nGPR[CMIPS::A2].nV0));
2020-05-03 12:07:08 -04:00
break;
case 10:
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(LoadModuleBuffer(
2018-04-30 21:01:23 +01:00
context.m_State.nGPR[CMIPS::A0].nV0));
break;
case 16:
2016-12-04 21:45:03 -05:00
context.m_State.nGPR[CMIPS::V0].nD0 = static_cast<int32>(GetModuleIdList(
2018-04-30 21:01:23 +01:00
context.m_State.nGPR[CMIPS::A0].nV0,
context.m_State.nGPR[CMIPS::A1].nV0,
context.m_State.nGPR[CMIPS::A2].nV0));
break;
case 17:
context.m_State.nGPR[CMIPS::V0].nD0 = ReferModuleStatus(
2018-04-30 21:01:23 +01:00
context.m_State.nGPR[CMIPS::A0].nV0,
context.m_State.nGPR[CMIPS::A1].nV0);
break;
2025-02-27 15:30:16 -05:00
case 18:
context.m_State.nGPR[CMIPS::V0].nD0 = GetModuleIdListByName(
context.m_State.nGPR[CMIPS::A0].nV0,
context.m_State.nGPR[CMIPS::A1].nV0,
context.m_State.nGPR[CMIPS::A2].nV0,
context.m_State.nGPR[CMIPS::A3].nV0);
break;
case 19:
context.m_State.nGPR[CMIPS::V0].nD0 = LoadModuleWithOption(
context.m_State.nGPR[CMIPS::A0].nV0,
context.m_State.nGPR[CMIPS::A1].nV0);
break;
2022-02-22 14:00:23 -05:00
case 20:
context.m_State.nGPR[CMIPS::V0].nD0 = StopModule(
context.m_State.nGPR[CMIPS::A0].nV0,
context.m_State.nGPR[CMIPS::A1].nV0,
context.m_State.nGPR[CMIPS::A2].nV0,
context.m_State.nGPR[CMIPS::A3].nV0);
break;
case 21:
context.m_State.nGPR[CMIPS::V0].nD0 = UnloadModule(
context.m_State.nGPR[CMIPS::A0].nV0);
break;
case 22:
context.m_State.nGPR[CMIPS::V0].nD0 = SearchModuleByName(
2018-04-30 21:01:23 +01:00
context.m_State.nGPR[CMIPS::A0].nV0);
break;
2021-01-03 20:38:15 -05:00
case 28:
context.m_State.nGPR[CMIPS::V0].nD0 = AllocLoadMemory(
context.m_State.nGPR[CMIPS::A0].nV0,
context.m_State.nGPR[CMIPS::A1].nV0,
context.m_State.nGPR[CMIPS::A2].nV0);
break;
default:
2018-05-24 12:59:15 -04:00
CLog::GetInstance().Warn(LOG_NAME, "(%08X): Unknown function (%d) called.\r\n",
2018-05-25 12:26:07 -04:00
context.m_State.nPC, functionId);
break;
}
}
uint32 CModload::LoadStartModule(uint32 pathPtr, uint32 argsLength, uint32 argsPtr, uint32 resultPtr)
{
const char* path = reinterpret_cast<const char*>(m_ram + pathPtr);
const char* args = reinterpret_cast<const char*>(m_ram + argsPtr);
try
{
auto moduleId = m_bios.LoadModuleFromPath(path);
if(moduleId >= 0)
{
moduleId = m_bios.StartModule(CIopBios::MODULESTARTREQUEST_SOURCE::LOCAL, moduleId, path, args, argsLength);
}
return moduleId;
}
catch(const std::exception& except)
{
2018-05-24 12:59:15 -04:00
CLog::GetInstance().Warn(LOG_NAME, "Error occured while trying to load module '%s' : %s\r\n",
2018-05-25 12:26:07 -04:00
path, except.what());
}
return -1;
}
uint32 CModload::StartModule(uint32 moduleId, uint32 pathPtr, uint32 argsLength, uint32 argsPtr, uint32 resultPtr)
{
const char* path = reinterpret_cast<const char*>(m_ram + pathPtr);
const char* args = reinterpret_cast<const char*>(m_ram + argsPtr);
CLog::GetInstance().Print(LOG_NAME, FUNCTION_STARTMODULE "(moduleId = %d, path = '%s', argsLength = %d, argsPtr = 0x%08X, resultPtr = 0x%08X);\r\n",
2018-04-30 21:01:23 +01:00
moduleId, path, argsLength, argsPtr, resultPtr);
auto result = m_bios.StartModule(CIopBios::MODULESTARTREQUEST_SOURCE::LOCAL, moduleId, path, args, argsLength);
return result;
}
2020-05-03 12:07:08 -04:00
uint32 CModload::LoadModuleBufferAddress(uint32 modBufPtr, uint32 dstAddr, uint32 offset)
{
CLog::GetInstance().Print(LOG_NAME, FUNCTION_LOADMODULEBUFFERADDRESS "(modBufPtr = 0x%08X, dstAddr = 0x%08X, offset = %d);\r\n",
modBufPtr, dstAddr, offset);
assert((modBufPtr & 0x03) == 0);
if(dstAddr == 0)
{
return m_bios.LoadModuleFromAddress(modBufPtr);
}
else
{
return m_bios.LoadModuleFromAddress(modBufPtr, dstAddr + offset, offset == 0);
}
2020-05-03 12:07:08 -04:00
}
uint32 CModload::LoadModuleBuffer(uint32 modBufPtr)
{
CLog::GetInstance().Print(LOG_NAME, FUNCTION_LOADMODULEBUFFER "(modBufPtr = 0x%08X);\r\n",
2018-04-30 21:01:23 +01:00
modBufPtr);
assert((modBufPtr & 0x03) == 0);
auto result = m_bios.LoadModuleFromAddress(modBufPtr);
return result;
}
uint32 CModload::GetModuleIdList(uint32 readBufPtr, uint32 readBufSize, uint32 moduleCountPtr)
{
CLog::GetInstance().Print(LOG_NAME, FUNCTION_GETMODULEIDLIST "(readBufPtr = 0x%08X, readBufSize = 0x%08X, moduleCountPtr = 0x%08X);\r\n",
2018-04-30 21:01:23 +01:00
readBufPtr, readBufSize, moduleCountPtr);
auto moduleCount = (moduleCountPtr != 0) ? reinterpret_cast<uint32*>(m_ram + moduleCountPtr) : nullptr;
if(moduleCount)
{
(*moduleCount) = 0;
}
2021-04-22 15:27:33 -04:00
CLog::GetInstance().Warn(LOG_NAME, "Using " FUNCTION_GETMODULEIDLIST ", but it is not implemented.\r\n");
return 0;
}
int32 CModload::ReferModuleStatus(uint32 moduleId, uint32 moduleStatusPtr)
{
CLog::GetInstance().Print(LOG_NAME, FUNCTION_REFERMODULESTATUS "(moduleId = %d, moduleStatusPtr = 0x%08X);\r\n",
2018-04-30 21:01:23 +01:00
moduleId, moduleStatusPtr);
2021-02-20 08:34:12 -05:00
return m_bios.ReferModuleStatus(moduleId, moduleStatusPtr);
}
2025-02-27 15:30:16 -05:00
int32 CModload::GetModuleIdListByName(uint32 moduleNamePtr, uint32 readBufPtr, uint32 readBufSize, uint32 moduleCountPtr)
{
CLog::GetInstance().Print(LOG_NAME, FUNCTION_GETMODULEIDLISTBYNAME "(moduleNamePtr = %s, readBufPtr = 0x%08X, readBufSize = 0x%08X, moduleCountPtr = 0x%08X);\r\n",
PrintStringParameter(m_ram, moduleNamePtr).c_str(), readBufPtr, readBufSize, moduleCountPtr);
std::vector<int32> moduleIds;
{
int32 moduleId = SearchModuleByName(moduleNamePtr);
if(moduleId >= 0) moduleIds.push_back(moduleId);
}
int32 readAmount = 0;
auto readBuf = reinterpret_cast<uint32*>(m_ram + readBufPtr);
for(size_t i = 0; i < moduleIds.size(); i++)
{
if(i >= readBufSize) break;
(*readBuf) = moduleIds[i];
readAmount++;
}
auto moduleCount = (moduleCountPtr != 0) ? reinterpret_cast<uint32*>(m_ram + moduleCountPtr) : nullptr;
if(moduleCount)
{
(*moduleCount) = static_cast<uint32>(moduleIds.size());
}
return readAmount;
}
int32 CModload::LoadModuleWithOption(uint32 pathPtr, uint32 optionPtr)
{
CLog::GetInstance().Print(LOG_NAME, FUNCTION_LOADMODULEWITHOPTION "(pathPtr = 0x%08X, optionPtr = 0x%08X);\r\n",
pathPtr, optionPtr);
const char* path = reinterpret_cast<const char*>(m_ram + pathPtr);
2023-07-06 11:45:07 -04:00
FRAMEWORK_MAYBE_UNUSED auto option = reinterpret_cast<const LMWO_OPTION*>(m_ram + optionPtr);
//We don't support custom loader functions
assert(option->funcTablePtr == 0);
return m_bios.LoadModuleFromPath(path);
}
2022-02-22 14:00:23 -05:00
int32 CModload::StopModule(uint32 moduleId, uint32 argsLength, uint32 argsPtr, uint32 resultPtr)
{
2023-05-02 08:56:25 -04:00
FRAMEWORK_MAYBE_UNUSED const char* args = reinterpret_cast<const char*>(m_ram + argsPtr);
2022-02-22 14:00:23 -05:00
CLog::GetInstance().Print(LOG_NAME, FUNCTION_STOPMODULE "(moduleId = %d, argsLength = %d, argsPtr = 0x%08X, resultPtr = 0x%08X);\r\n",
moduleId, argsLength, argsPtr, resultPtr);
return m_bios.StopModule(CIopBios::MODULESTARTREQUEST_SOURCE::LOCAL, moduleId);
}
int32 CModload::UnloadModule(uint32 moduleId)
{
CLog::GetInstance().Print(LOG_NAME, FUNCTION_UNLOADMODULE "(moduleId = %d);\r\n",
moduleId);
return m_bios.UnloadModule(moduleId);
}
int32 CModload::SearchModuleByName(uint32 moduleNamePtr)
{
CLog::GetInstance().Print(LOG_NAME, FUNCTION_SEARCHMODULEBYNAME "(moduleNamePtr = %s);\r\n",
2018-04-30 21:01:23 +01:00
PrintStringParameter(m_ram, moduleNamePtr).c_str());
return m_bios.SearchModuleByName(reinterpret_cast<const char*>(m_ram + moduleNamePtr));
}
2021-01-03 20:38:15 -05:00
int32 CModload::AllocLoadMemory(uint32 unknown1, uint32 size, uint32 unknown2)
{
CLog::GetInstance().Print(LOG_NAME, FUNCTION_ALLOCLOADMEMORY "(unknown1 = %d, size = 0x%08X, unknown2 = %d);\r\n",
2021-01-08 18:30:28 -05:00
unknown1, size, unknown2);
2021-01-03 20:38:15 -05:00
auto sysmem = m_bios.GetSysmem();
uint32 result = sysmem->AllocateMemory(size, 0, 0);
return result;
}