Files
PS2Recomp/ps2xIOP/src/ps2_path.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

124 lines
3.9 KiB
C++

#include "ps2x/iop/ps2_path.h"
#include <algorithm>
#include <cctype>
namespace ps2x::iop
{
namespace
{
std::string lowerAscii(std::string_view value)
{
std::string result(value);
std::transform(result.begin(), result.end(), result.begin(), [](unsigned char ch)
{ return static_cast<char>(std::tolower(ch)); });
return result;
}
void normalizeSuffix(std::string &suffix)
{
std::replace(suffix.begin(), suffix.end(), '\\', '/');
while (!suffix.empty() && suffix.front() == '/')
suffix.erase(suffix.begin());
const size_t semicolon = suffix.rfind(';');
if (semicolon == std::string::npos || semicolon + 1u == suffix.size())
return;
const bool numeric = std::all_of(suffix.begin() + static_cast<std::ptrdiff_t>(semicolon + 1u),
suffix.end(),
[](unsigned char ch)
{ return std::isdigit(ch) != 0; });
if (numeric)
suffix.erase(semicolon);
}
}
ParsedPs2Path parsePs2Path(std::string_view value)
{
ParsedPs2Path result;
if (value.empty())
return result;
const std::string lower = lowerAscii(value);
size_t prefixLength = 0u;
if (lower.rfind("host0:", 0u) == 0u)
{
result.device = Ps2PathDevice::Host;
result.deviceName = "host0";
prefixLength = 6u;
}
else if (lower.rfind("host:", 0u) == 0u)
{
result.device = Ps2PathDevice::Host;
result.deviceName = "host";
prefixLength = 5u;
}
else if (lower.rfind("cdrom0:", 0u) == 0u)
{
result.device = Ps2PathDevice::Cdrom;
result.deviceName = "cdrom0";
prefixLength = 7u;
}
else if (lower.rfind("cdrom:", 0u) == 0u)
{
result.device = Ps2PathDevice::Cdrom;
result.deviceName = "cdrom";
prefixLength = 6u;
}
else if (lower.rfind("mc0:", 0u) == 0u)
{
result.device = Ps2PathDevice::MemoryCard0;
result.deviceName = "mc0";
prefixLength = 4u;
}
else if (lower.rfind("rom0:", 0u) == 0u)
{
result.device = Ps2PathDevice::Rom0;
result.deviceName = "rom0";
prefixLength = 5u;
}
else if (value.size() > 2u && std::isalpha(static_cast<unsigned char>(value[0])) &&
value[1] == ':' && (value[2] == '/' || value[2] == '\\'))
{
result.device = Ps2PathDevice::NativeHost;
result.deviceName = "native";
}
else if (value.find(':') != std::string_view::npos)
{
// TODO maybe log an error here, but don't fail the parse. This is a non-standard device name.
return result;
}
else
{
result.device = Ps2PathDevice::Cdrom;
result.deviceName = "cdrom0";
}
result.path.assign(value.substr(prefixLength));
if (result.device != Ps2PathDevice::NativeHost)
normalizeSuffix(result.path);
return result;
}
std::string ps2PathLeafKey(const ParsedPs2Path &parsed)
{
if (!parsed)
return {};
std::string path = parsed.path;
std::replace(path.begin(), path.end(), '\\', '/');
const size_t slash = path.find_last_of('/');
if (slash != std::string::npos)
path.erase(0u, slash + 1u);
path = lowerAscii(path);
if (path.size() > 4u && path.ends_with(".irx"))
path.resize(path.size() - 4u);
return path;
}
std::string ps2PathLeafKey(std::string_view path)
{
return ps2PathLeafKey(parsePs2Path(path));
}
}