Files
PS2Recomp/ps2xIOP/src/iop_module_manager.cpp
T
Ranieri 75d729ce40 Feature/iop emulator (#244)
* refactor: from guest  threads to EE scheduler

* feat: bad wip mpeg fix for code veronica

* feat: cheap copy from host
feat: small perf o vsync tick

* feat: added EE clock Hz
fix: fix MPEG out of sync with new EE refactor

* fix: fix lotr tests

* fix: fix cri dtx loading
fix: fix wrong mmi instruction translation
fix: fix thread info params
feat: added EE  timers decoder and consumer
feat: split SFI and IOP memory to prevent collision and overrides

* feat: revert wrong changes

* refactor: change GS architecture

* feat: IOP emulator
refactor: codegen to catch callbacks on mips code
feat: added a lot of entries or IOP emulator

* feat: analyzer resolve the complete constant-producing sequence with five-instruction backward scan stopped at LUI and therefore

* feat: remove recompiled version of GetRomName
refactor: split IOP emulator logic
feat: added more HLE IOP modules
feat: added ps2_path

* eat: enhance ELF parser with improved callable entry detection and control flow analysis

* feat: update memory hint handling and enhance entry point discovery logic

* feat: add SET_GPR_ZE32 macro for zero-extending loads with unsigned semantics

* refactor: Refactor PS2 IOP Host Adapter and Memory Management
feat: Added PS2Vfs for virtual file system operations, including file opening, reading, writing, and path resolution.
feat: Improve VIF1 data processing to handle GIF image packets more efficiently.

* feat: added a lot of tests

* fix: fix texture caching
feat: wip multi version on dbcman

* feat: remove LLE IOPs
2026-09-19 21:31:44 -03:00

181 lines
5.1 KiB
C++

#include "iop_module_manager.h"
#include "ps2x/iop/ps2_path.h"
#include <algorithm>
namespace ps2x::iop::detail
{
IopModuleManager::IopModuleManager()
{
// ROM modules that the no-BIOS HLE environment can legitimately provide.
// Entries with RPC services become routable only after load.
constexpr std::string_view modules[] = {
"sysmem",
"loadcore",
"intrman",
"sifman",
"sifcmd",
"sifinit",
"ioman",
"iomanx",
"modload",
"stdio",
"sysclib",
"thbase",
"thevent",
"thsemap",
"thmsgbx",
"timrman",
"vblank",
"secrman",
"sio2man",
"xsio2man",
"sio2d",
"padman",
"xpadman",
"mcman",
"xmcman",
"mcserv",
"libsd",
"cdvdman",
"cdvdfsv",
"dev9",
"usbd",
"usbhdfsd",
"udnl",
"fileio",
"poweroff",
"netman",
"ps2ip",
"dbcman",
"dbcm",
};
for (const std::string_view module : modules)
m_builtinKeys.emplace(module);
}
void IopModuleManager::reset()
{
m_records.clear();
m_hleIdsByKey.clear();
m_loadedKeyReferences.clear();
m_nextHleId = 0x40000000;
}
void IopModuleManager::setServiceModuleKeys(std::vector<std::string> keys)
{
m_serviceKeys.clear();
for (std::string &key : keys)
{
const std::string normalized = ps2PathLeafKey(key);
if (!normalized.empty())
m_serviceKeys.emplace(normalized);
}
}
ModuleLoadResult IopModuleManager::loadHle(std::string_view path)
{
ModuleLoadResult result{true, -1, -1};
const std::string key = ps2PathLeafKey(path);
if (key.empty() || (!m_builtinKeys.contains(key) && !m_serviceKeys.contains(key)))
return result;
const auto existing = m_hleIdsByKey.find(key);
if (existing != m_hleIdsByKey.end())
{
Record &record = m_records[existing->second];
++record.references;
addLoadedKey(key);
result.moduleId = existing->second;
result.startResult = 0;
return result;
}
if (m_nextHleId <= 0)
return result;
const int32_t id = m_nextHleId++;
m_records.emplace(id, Record{key, 1u, false});
m_hleIdsByKey.emplace(key, id);
addLoadedKey(key);
result.moduleId = id;
result.startResult = 0;
return result;
}
void IopModuleManager::observePhysicalLoad(int32_t moduleId, std::string_view path)
{
if (moduleId <= 0)
return;
const std::string key = ps2PathLeafKey(path);
if (key.empty())
return;
m_records[moduleId] = Record{key, 1u, true};
addLoadedKey(key);
}
bool IopModuleManager::stopHle(int32_t moduleId, int32_t *result)
{
const auto found = m_records.find(moduleId);
if (found == m_records.end() || found->second.physical)
return false;
Record &record = found->second;
removeLoadedKey(record.key);
if (record.references > 1u)
{
--record.references;
}
else
{
m_hleIdsByKey.erase(record.key);
m_records.erase(found);
}
if (result)
*result = 0;
return true;
}
void IopModuleManager::observePhysicalStop(int32_t moduleId)
{
const auto found = m_records.find(moduleId);
if (found == m_records.end() || !found->second.physical)
return;
removeLoadedKey(found->second.key);
m_records.erase(found);
}
bool IopModuleManager::isLoaded(std::span<const std::string_view> aliases) const
{
if (aliases.empty())
return true;
return std::any_of(aliases.begin(), aliases.end(), [&](std::string_view alias)
{
const std::string key = ps2PathLeafKey(alias);
const auto found = m_loadedKeyReferences.find(key);
return found != m_loadedKeyReferences.end() && found->second != 0u; });
}
bool IopModuleManager::recognizes(std::string_view path) const
{
const std::string key = ps2PathLeafKey(path);
return m_builtinKeys.contains(key) || m_serviceKeys.contains(key);
}
void IopModuleManager::addLoadedKey(std::string_view key)
{
++m_loadedKeyReferences[std::string(key)];
}
void IopModuleManager::removeLoadedKey(std::string_view key)
{
const auto found = m_loadedKeyReferences.find(std::string(key));
if (found == m_loadedKeyReferences.end())
return;
if (found->second > 1u)
--found->second;
else
m_loadedKeyReferences.erase(found);
}
}