feat: added runtime base stubs definitions

This commit is contained in:
Ran-j
2025-04-17 01:57:13 -03:00
parent fa676bd692
commit 4b59d8d2c8
8 changed files with 1133 additions and 678 deletions
+17
View File
@@ -5,15 +5,32 @@ project(PS2Runtime VERSION 0.1.0 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
include(FetchContent)
set(FETCHCONTENT_QUIET FALSE)
set(BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
set(BUILD_GAMES OFF CACHE BOOL "" FORCE)
FetchContent_Declare(
raylib
GIT_REPOSITORY "https://github.com/raysan5/raylib.git"
GIT_TAG "5.5" # we will migrate to 4.2.0 later, trust me it will be better
GIT_PROGRESS TRUE
)
FetchContent_MakeAvailable(raylib)
add_library(ps2_runtime STATIC
src/ps2_memory.cpp
src/ps2_runtime.cpp
src/ps2_stubs.cpp
src/ps2_syscalls.cpp
)
target_include_directories(ps2_runtime PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/include
)
target_link_libraries(ps2_runtime PRIVATE raylib)
install(TARGETS ps2_runtime
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
+33 -2
View File
@@ -8,6 +8,7 @@
#include <functional>
#include <immintrin.h> // For SSE/AVX instructions
constexpr uint32_t PS2_RAM_MASK = 0xF0000000;
constexpr uint32_t PS2_RAM_BASE = 0x00000000;
constexpr uint32_t PS2_RAM_SIZE = 32 * 1024 * 1024; // 32MB
constexpr uint32_t PS2_SCRATCHPAD_BASE = 0x70000000;
@@ -131,8 +132,40 @@ struct R5900Context
// Reset COP1 state
fcr31 = 0;
}
~R5900Context() = default;
};
inline uint32_t getRegU32(const R5900Context *ctx, int reg)
{
// Check if reg is valid (0-31)
if (reg < 0 || reg > 31)
return 0;
return ctx->r[reg].m128i_u32[0];
}
inline void setReturnU32(R5900Context *ctx, uint32_t value)
{
ctx->r[2] = _mm_set_epi32(0, 0, 0, value); // $v0
}
inline void setReturnS32(R5900Context *ctx, int32_t value)
{
ctx->r[2] = _mm_set_epi32(0, 0, 0, value); // $v0 Sign extension handled by cast? TODO Check MIPS ABI.
}
inline uint8_t *getMemPtr(uint8_t *rdram, uint32_t addr)
{
constexpr uint32_t PS2_RAM_MASK = PS2_RAM_SIZE - 1;
return rdram + (addr & PS2_RAM_MASK);
}
inline const uint8_t *getConstMemPtr(uint8_t *rdram, uint32_t addr)
{
constexpr uint32_t PS2_RAM_MASK = PS2_RAM_SIZE - 1;
return rdram + (addr & PS2_RAM_MASK);
}
// PS2 GS (Graphics Synthesizer) registers
struct GSRegisters
{
@@ -299,10 +332,8 @@ private:
PS2Memory m_memory;
R5900Context m_cpuContext;
// Function table for recompiled code
std::unordered_map<uint32_t, RecompiledFunction> m_functionTable;
// Currently loaded modules
struct LoadedModule
{
std::string name;
+31 -72
View File
@@ -2,11 +2,16 @@
#define PS2_STUBS_H
#include "ps2_runtime.h"
#include <cstdint>
// Standard library implementation stubs
namespace ps2_stubs
{
// Memory operations
void malloc(uint8_t *rdram, R5900Context *ctx);
void free(uint8_t *rdram, R5900Context *ctx);
void calloc(uint8_t *rdram, R5900Context *ctx);
void realloc(uint8_t *rdram, R5900Context *ctx);
void memcpy(uint8_t *rdram, R5900Context *ctx);
void memset(uint8_t *rdram, R5900Context *ctx);
void memmove(uint8_t *rdram, R5900Context *ctx);
@@ -18,87 +23,41 @@ namespace ps2_stubs
void strlen(uint8_t *rdram, R5900Context *ctx);
void strcmp(uint8_t *rdram, R5900Context *ctx);
void strncmp(uint8_t *rdram, R5900Context *ctx);
void strcat(uint8_t *rdram, R5900Context *ctx);
void strncat(uint8_t *rdram, R5900Context *ctx);
void strchr(uint8_t *rdram, R5900Context *ctx);
void strrchr(uint8_t *rdram, R5900Context *ctx);
void strstr(uint8_t *rdram, R5900Context *ctx);
// I/O operations
void printf(uint8_t *rdram, R5900Context *ctx);
void sprintf(uint8_t *rdram, R5900Context *ctx);
void snprintf(uint8_t *rdram, R5900Context *ctx);
void puts(uint8_t *rdram, R5900Context *ctx);
// Memory allocation
void malloc(uint8_t *rdram, R5900Context *ctx);
void free(uint8_t *rdram, R5900Context *ctx);
void calloc(uint8_t *rdram, R5900Context *ctx);
void realloc(uint8_t *rdram, R5900Context *ctx);
void fopen(uint8_t *rdram, R5900Context *ctx);
void fclose(uint8_t *rdram, R5900Context *ctx);
void fread(uint8_t *rdram, R5900Context *ctx);
void fwrite(uint8_t *rdram, R5900Context *ctx);
void fprintf(uint8_t *rdram, R5900Context *ctx);
void fseek(uint8_t *rdram, R5900Context *ctx);
void ftell(uint8_t *rdram, R5900Context *ctx);
void fflush(uint8_t *rdram, R5900Context *ctx);
// Math functions
void sqrt(uint8_t *rdram, R5900Context *ctx);
void sin(uint8_t *rdram, R5900Context *ctx);
void cos(uint8_t *rdram, R5900Context *ctx);
void tan(uint8_t *rdram, R5900Context *ctx);
void atan2(uint8_t *rdram, R5900Context *ctx);
void pow(uint8_t *rdram, R5900Context *ctx);
void exp(uint8_t *rdram, R5900Context *ctx);
void log(uint8_t *rdram, R5900Context *ctx);
void log10(uint8_t *rdram, R5900Context *ctx);
void ceil(uint8_t *rdram, R5900Context *ctx);
void floor(uint8_t *rdram, R5900Context *ctx);
void fabs(uint8_t *rdram, R5900Context *ctx);
void TODO(uint8_t *rdram, R5900Context *ctx);
}
// PS2 system call implementation stubs
namespace ps2_syscalls
{
void FlushCache(uint8_t *rdram, R5900Context *ctx);
void ExitThread(uint8_t *rdram, R5900Context *ctx);
void SleepThread(uint8_t *rdram, R5900Context *ctx);
void CreateThread(uint8_t *rdram, R5900Context *ctx);
void StartThread(uint8_t *rdram, R5900Context *ctx);
void SifInitRpc(uint8_t *rdram, R5900Context *ctx);
void SifBindRpc(uint8_t *rdram, R5900Context *ctx);
void SifCallRpc(uint8_t *rdram, R5900Context *ctx);
void SetGsCrt(uint8_t *rdram, R5900Context *ctx);
}
// MMI operation implementations
namespace ps2_mmi
{
void PADDW(R5900Context *ctx, int rd, int rs, int rt);
void PSUBW(R5900Context *ctx, int rd, int rs, int rt);
void PCGTW(R5900Context *ctx, int rd, int rs, int rt);
void PMAXW(R5900Context *ctx, int rd, int rs, int rt);
void PADDH(R5900Context *ctx, int rd, int rs, int rt);
void PSUBH(R5900Context *ctx, int rd, int rs, int rt);
void PCGTH(R5900Context *ctx, int rd, int rs, int rt);
void PMAXH(R5900Context *ctx, int rd, int rs, int rt);
void PADDB(R5900Context *ctx, int rd, int rs, int rt);
void PSUBB(R5900Context *ctx, int rd, int rs, int rt);
void PCGTB(R5900Context *ctx, int rd, int rs, int rt);
void PEXTLW(R5900Context *ctx, int rd, int rs, int rt);
void PEXTUW(R5900Context *ctx, int rd, int rs, int rt);
void PEXTLH(R5900Context *ctx, int rd, int rs, int rt);
void PEXTUH(R5900Context *ctx, int rd, int rs, int rt);
void PEXTLB(R5900Context *ctx, int rd, int rs, int rt);
void PEXTUB(R5900Context *ctx, int rd, int rs, int rt);
void PMADDW(R5900Context *ctx, int rd, int rs, int rt);
void PMSUBW(R5900Context *ctx, int rd, int rs, int rt);
void PMADDH(R5900Context *ctx, int rd, int rs, int rt);
void PMSUBH(R5900Context *ctx, int rd, int rs, int rt);
void PAND(R5900Context *ctx, int rd, int rs, int rt);
void POR(R5900Context *ctx, int rd, int rs, int rt);
void PXOR(R5900Context *ctx, int rd, int rs, int rt);
void PNOR(R5900Context *ctx, int rd, int rs, int rt);
}
// Hardware register handlers
namespace ps2_hardware
{
// DMA channel handlers
void handleDmacReg(uint32_t address, uint32_t value);
// GS register handlers
void handleGsReg(uint32_t address, uint32_t value);
// VIF register handlers
void handleVif0Reg(uint32_t address, uint32_t value);
void handleVif1Reg(uint32_t address, uint32_t value);
void handleTimerReg(uint32_t address, uint32_t value);
void handleSPU2Reg(uint32_t address, uint32_t value);
}
#endif // PS2_RUNTIME_H
#endif // PS2_STUBS_H
+115
View File
@@ -0,0 +1,115 @@
#ifndef PS2_SYSCALLS_H
#define PS2_SYSCALLS_H
#include "ps2_runtime.h"
#define PS2_FIO_O_RDONLY 0x0001
#define PS2_FIO_O_WRONLY 0x0002
#define PS2_FIO_O_RDWR 0x0003
#define PS2_FIO_O_NBLOCK 0x0010
#define PS2_FIO_O_APPEND 0x0100
#define PS2_FIO_O_CREAT 0x0200
#define PS2_FIO_O_TRUNC 0x0400
#define PS2_FIO_O_EXCL 0x0800
#define PS2_FIO_O_NOWAIT 0x8000
#define PS2_SEEK_SET 0
#define PS2_SEEK_CUR 1
#define PS2_SEEK_END 2
namespace ps2_syscalls
{
void FlushCache(uint8_t *rdram, R5900Context *ctx);
void ResetEE(uint8_t *rdram, R5900Context *ctx);
void SetMemoryMode(uint8_t *rdram, R5900Context *ctx);
void CreateThread(uint8_t *rdram, R5900Context *ctx);
void DeleteThread(uint8_t *rdram, R5900Context *ctx);
void StartThread(uint8_t *rdram, R5900Context *ctx);
void ExitThread(uint8_t *rdram, R5900Context *ctx);
void ExitDeleteThread(uint8_t *rdram, R5900Context *ctx);
void TerminateThread(uint8_t *rdram, R5900Context *ctx);
void SuspendThread(uint8_t *rdram, R5900Context *ctx);
void ResumeThread(uint8_t *rdram, R5900Context *ctx);
void GetThreadId(uint8_t *rdram, R5900Context *ctx);
void ReferThreadStatus(uint8_t *rdram, R5900Context *ctx);
void SleepThread(uint8_t *rdram, R5900Context *ctx);
void WakeupThread(uint8_t *rdram, R5900Context *ctx);
void iWakeupThread(uint8_t *rdram, R5900Context *ctx);
void ChangeThreadPriority(uint8_t *rdram, R5900Context *ctx);
void RotateThreadReadyQueue(uint8_t *rdram, R5900Context *ctx);
void ReleaseWaitThread(uint8_t *rdram, R5900Context *ctx);
void iReleaseWaitThread(uint8_t *rdram, R5900Context *ctx);
void CreateSema(uint8_t *rdram, R5900Context *ctx);
void DeleteSema(uint8_t *rdram, R5900Context *ctx);
void SignalSema(uint8_t *rdram, R5900Context *ctx);
void iSignalSema(uint8_t *rdram, R5900Context *ctx);
void WaitSema(uint8_t *rdram, R5900Context *ctx);
void PollSema(uint8_t *rdram, R5900Context *ctx);
void iPollSema(uint8_t *rdram, R5900Context *ctx);
void ReferSemaStatus(uint8_t *rdram, R5900Context *ctx);
void iReferSemaStatus(uint8_t *rdram, R5900Context *ctx);
void CreateEventFlag(uint8_t *rdram, R5900Context *ctx);
void DeleteEventFlag(uint8_t *rdram, R5900Context *ctx);
void SetEventFlag(uint8_t *rdram, R5900Context *ctx);
void iSetEventFlag(uint8_t *rdram, R5900Context *ctx);
void ClearEventFlag(uint8_t *rdram, R5900Context *ctx);
void iClearEventFlag(uint8_t *rdram, R5900Context *ctx);
void WaitEventFlag(uint8_t *rdram, R5900Context *ctx);
void PollEventFlag(uint8_t *rdram, R5900Context *ctx);
void iPollEventFlag(uint8_t *rdram, R5900Context *ctx);
void ReferEventFlagStatus(uint8_t *rdram, R5900Context *ctx);
void iReferEventFlagStatus(uint8_t *rdram, R5900Context *ctx);
void SetAlarm(uint8_t *rdram, R5900Context *ctx);
void iSetAlarm(uint8_t *rdram, R5900Context *ctx);
void CancelAlarm(uint8_t *rdram, R5900Context *ctx);
void iCancelAlarm(uint8_t *rdram, R5900Context *ctx);
void EnableIntc(uint8_t *rdram, R5900Context *ctx);
void DisableIntc(uint8_t *rdram, R5900Context *ctx);
void EnableDmac(uint8_t *rdram, R5900Context *ctx);
void DisableDmac(uint8_t *rdram, R5900Context *ctx);
void SifStopModule(uint8_t *rdram, R5900Context *ctx);
void SifLoadModule(uint8_t *rdram, R5900Context *ctx);
void SifInitRpc(uint8_t *rdram, R5900Context *ctx);
void SifBindRpc(uint8_t *rdram, R5900Context *ctx);
void SifCallRpc(uint8_t *rdram, R5900Context *ctx);
void SifRegisterRpc(uint8_t *rdram, R5900Context *ctx);
void SifCheckStatRpc(uint8_t *rdram, R5900Context *ctx);
void SifSetRpcQueue(uint8_t *rdram, R5900Context *ctx);
void SifRemoveRpcQueue(uint8_t *rdram, R5900Context *ctx);
void SifRemoveRpc(uint8_t *rdram, R5900Context *ctx);
void fioOpen(uint8_t *rdram, R5900Context *ctx);
void fioClose(uint8_t *rdram, R5900Context *ctx);
void fioRead(uint8_t *rdram, R5900Context *ctx);
void fioWrite(uint8_t *rdram, R5900Context *ctx);
void fioLseek(uint8_t *rdram, R5900Context *ctx);
void fioMkdir(uint8_t *rdram, R5900Context *ctx);
void fioChdir(uint8_t *rdram, R5900Context *ctx);
void fioRmdir(uint8_t *rdram, R5900Context *ctx);
void fioGetstat(uint8_t *rdram, R5900Context *ctx);
void fioRemove(uint8_t *rdram, R5900Context *ctx);
void GsSetCrt(uint8_t *rdram, R5900Context *ctx);
void GsGetIMR(uint8_t *rdram, R5900Context *ctx);
void GsPutIMR(uint8_t *rdram, R5900Context *ctx);
void GsSetVideoMode(uint8_t *rdram, R5900Context *ctx);
void GetOsdConfigParam(uint8_t *rdram, R5900Context *ctx);
void SetOsdConfigParam(uint8_t *rdram, R5900Context *ctx);
void GetRomName(uint8_t *rdram, R5900Context *ctx);
void SifLoadElfPart(uint8_t *rdram, R5900Context *ctx);
void sceSifLoadModule(uint8_t *rdram, R5900Context *ctx);
void TODO(uint8_t *rdram, R5900Context *ctx);
// Helper functions
void RenderFrame(uint8_t *rdram);
}
#endif // PS2_SYSCALLS_H
+27 -3
View File
@@ -47,12 +47,36 @@ bool PS2Memory::initialize(size_t ramSize)
}
std::memset(m_scratchpad, 0, PS2_SCRATCHPAD_SIZE);
// Initialize IO registers with default values
m_ioRegisters.clear();
// Initialize TLB entries
m_tlbEntries.clear();
// Allocate IOP RAM
iop_ram = new uint8_t[2 * 1024 * 1024]; // 2MB
if (!iop_ram)
{
delete[] m_rdram;
delete[] m_scratchpad;
m_rdram = nullptr;
m_scratchpad = nullptr;
return false;
}
// Initialize IOP RAM with zeros
std::memset(iop_ram, 0, 2 * 1024 * 1024);
// Initialize I/O registers
m_ioRegisters.clear();
// Initialize GS registers
memset(&gs_regs, 0, sizeof(gs_regs));
// Initialize VIF registers
memset(&vif0_regs, 0, sizeof(vif0_regs));
memset(&vif1_regs, 0, sizeof(vif1_regs));
// Initialize DMA registers
memset(dma_regs, 0, sizeof(dma_regs));
return true;
}
catch (const std::exception &e)
+21 -37
View File
@@ -3,12 +3,12 @@
#include <fstream>
#include <algorithm>
#include <cstring>
#define ELF_MAGIC 0x464C457F // "\x7FELF" in little endian
#define ET_EXEC 2 // Executable file
#define EM_MIPS 8 // MIPS architecture
struct ElfHeader
{
uint32_t magic;
@@ -44,27 +44,27 @@ struct ProgramHeader
uint32_t flags;
uint32_t align;
};
#define PT_LOAD 1 // Loadable segment
PS2Runtime::PS2Runtime()
{
{
std::memset(&m_cpuContext, 0, sizeof(m_cpuContext));
// R0 is always zero in MIPS
m_cpuContext.r[0] = _mm_set1_epi32(0);
// Stack pointer (SP) and global pointer (GP) will be set by the loaded ELF
m_functionTable.clear();
m_loadedModules.clear();
}
PS2Runtime::~PS2Runtime()
{
{
m_loadedModules.clear();
m_functionTable.clear();
}
@@ -75,7 +75,7 @@ bool PS2Runtime::initialize()
std::cerr << "Failed to initialize PS2 memory" << std::endl;
return false;
}
registerBuiltinStubs();
return true;
@@ -83,15 +83,7 @@ bool PS2Runtime::initialize()
void PS2Runtime::registerBuiltinStubs()
{
// Register common PS2 library functions as stubs
// Standard C library stubs
registerFunction(0xFFFFFFFF, [](uint8_t *rdram, R5900Context *ctx)
{ std::cout << "Stub: printf called" << std::endl; });
// PS2-specific system call stubs
registerFunction(0xFFFFFFFE, [](uint8_t *rdram, R5900Context *ctx)
{ std::cout << "Stub: FlushCache called with mode: " << ctx->r[4].m128i_u32[0] << std::endl; });
// TODO
}
bool PS2Runtime::loadELF(const std::string &elfPath)
@@ -103,28 +95,23 @@ bool PS2Runtime::loadELF(const std::string &elfPath)
return false;
}
// Read ELF header
ElfHeader header;
file.read(reinterpret_cast<char *>(&header), sizeof(header));
// Check ELF magic number
if (header.magic != ELF_MAGIC)
{
std::cerr << "Invalid ELF magic number" << std::endl;
return false;
}
// Check if it's a MIPS executable
if (header.machine != EM_MIPS || header.type != ET_EXEC)
{
std::cerr << "Not a MIPS executable ELF file" << std::endl;
return false;
}
// Store entry point
m_cpuContext.pc = header.entry;
// Read program headers and load segments
for (uint16_t i = 0; i < header.phnum; i++)
{
ProgramHeader ph;
@@ -132,7 +119,7 @@ bool PS2Runtime::loadELF(const std::string &elfPath)
file.read(reinterpret_cast<char *>(&ph), sizeof(ph));
if (ph.type == PT_LOAD && ph.filesz > 0)
{
{
std::cout << "Loading segment: 0x" << std::hex << ph.vaddr
<< " - 0x" << (ph.vaddr + ph.memsz)
<< " (size: 0x" << ph.memsz << ")" << std::dec << std::endl;
@@ -149,7 +136,6 @@ bool PS2Runtime::loadELF(const std::string &elfPath)
uint8_t *dest = m_memory.getRDRAM() + physAddr;
std::memcpy(dest, buffer.data(), ph.filesz);
// Zero-initialize the rest (bss-like sections)
if (ph.memsz > ph.filesz)
{
std::memset(dest + ph.filesz, 0, ph.memsz - ph.filesz);
@@ -157,7 +143,6 @@ bool PS2Runtime::loadELF(const std::string &elfPath)
}
}
// Create a loaded module entry
LoadedModule module;
module.name = elfPath.substr(elfPath.find_last_of("/\\") + 1);
module.baseAddress = 0x00100000; // Typical base address for PS2 executables
@@ -182,22 +167,21 @@ PS2Runtime::RecompiledFunction PS2Runtime::lookupFunction(uint32_t address)
{
return it->second;
}
std::cerr << "Warning: Function at address 0x" << std::hex << address << std::dec << " not found" << std::endl;
static RecompiledFunction defaultFunction = [](uint8_t* rdram, R5900Context* ctx)
{
std::cerr << "Error: Called unimplemented function at address 0x" << std::hex << ctx->pc << std::dec << std::endl;
};
static RecompiledFunction defaultFunction = [](uint8_t *rdram, R5900Context *ctx)
{
std::cerr << "Error: Called unimplemented function at address 0x" << std::hex << ctx->pc << std::dec << std::endl;
};
return defaultFunction;
}
void PS2Runtime::run()
{
{
RecompiledFunction entryPoint = lookupFunction(m_cpuContext.pc);
// Set up initial CPU state
m_cpuContext.r[4] = _mm_set1_epi32(0); // A0 = 0 (argc)
m_cpuContext.r[5] = _mm_set1_epi32(0); // A1 = 0 (argv)
m_cpuContext.r[29] = _mm_set1_epi32(0x02000000); // SP = top of RAM
@@ -215,4 +199,4 @@ void PS2Runtime::run()
{
std::cerr << "Error during program execution: " << e.what() << std::endl;
}
}
}
File diff suppressed because it is too large Load Diff
+499
View File
@@ -0,0 +1,499 @@
#include "ps2_syscalls.h"
#include "ps2_runtime.h"
#include "ps2_stubs.h"
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <unordered_map>
#include <filesystem>
std::unordered_map<int, FILE*> g_fileDescriptors;
int g_nextFd = 3; // Start after stdin, stdout, stderr
int allocatePs2Fd(FILE* file)
{
if (!file)
return -1;
int fd = g_nextFd++;
g_fileDescriptors[fd] = file;
return fd;
}
FILE* getHostFile(int ps2Fd)
{
auto it = g_fileDescriptors.find(ps2Fd);
if (it != g_fileDescriptors.end())
{
return it->second;
}
return nullptr;
}
void releasePs2Fd(int ps2Fd)
{
g_fileDescriptors.erase(ps2Fd);
}
const char *translateFioMode(int ps2Flags)
{
bool read = (ps2Flags & PS2_FIO_O_RDONLY) || (ps2Flags & PS2_FIO_O_RDWR);
bool write = (ps2Flags & PS2_FIO_O_WRONLY) || (ps2Flags & PS2_FIO_O_RDWR);
bool append = (ps2Flags & PS2_FIO_O_APPEND);
bool create = (ps2Flags & PS2_FIO_O_CREAT);
bool truncate = (ps2Flags & PS2_FIO_O_TRUNC);
if (read && write)
{
if (create && truncate)
return "w+b";
if (create)
return "a+b";
return "r+b";
}
else if (write)
{
if (append)
return "ab";
if (create && truncate)
return "wb";
if (create)
return "wx";
return "r+b";
}
else if (read)
{
return "rb";
}
return "rb";
}
std::string translatePs2Path(const char *ps2Path)
{
std::string pathStr(ps2Path);
if (pathStr.rfind("host0:", 0) == 0)
{
// Map host0: to ./host_fs/ relative to executable
std::filesystem::path hostBasePath = std::filesystem::current_path() / "host_fs";
std::filesystem::create_directories(hostBasePath); // Ensure it exists
return (hostBasePath / pathStr.substr(6)).string();
}
else if (pathStr.rfind("cdrom0:", 0) == 0)
{
// Map cdrom0: to ./cd_fs/ relative to executable (for example)
std::filesystem::path cdBasePath = std::filesystem::current_path() / "cd_fs";
std::filesystem::create_directories(cdBasePath); // Ensure it exists
return (cdBasePath / pathStr.substr(7)).string();
}
// Add other mappings (mc0:, hdd0:, etc.) as needed
std::cerr << "Warning: Unsupported PS2 path prefix: " << pathStr << std::endl;
return "";
}
#include "ps2_syscalls.h"
namespace ps2_syscalls
{
void FlushCache(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void ResetEE(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void SetMemoryMode(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void CreateThread(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void DeleteThread(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void StartThread(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void ExitThread(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void ExitDeleteThread(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void TerminateThread(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void SuspendThread(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void ResumeThread(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void GetThreadId(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void ReferThreadStatus(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void SleepThread(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void WakeupThread(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void iWakeupThread(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void ChangeThreadPriority(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void RotateThreadReadyQueue(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void ReleaseWaitThread(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void iReleaseWaitThread(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void CreateSema(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void DeleteSema(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void SignalSema(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void iSignalSema(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void WaitSema(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void PollSema(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void iPollSema(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void ReferSemaStatus(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void iReferSemaStatus(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void CreateEventFlag(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void DeleteEventFlag(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void SetEventFlag(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void iSetEventFlag(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void ClearEventFlag(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void iClearEventFlag(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void WaitEventFlag(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void PollEventFlag(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void iPollEventFlag(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void ReferEventFlagStatus(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void iReferEventFlagStatus(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void SetAlarm(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void iSetAlarm(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void CancelAlarm(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void iCancelAlarm(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void EnableIntc(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void DisableIntc(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void EnableDmac(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void DisableDmac(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void SifStopModule(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void SifLoadModule(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void SifInitRpc(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void SifBindRpc(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void SifCallRpc(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void SifRegisterRpc(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void SifCheckStatRpc(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void SifSetRpcQueue(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void SifRemoveRpcQueue(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void SifRemoveRpc(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void fioOpen(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void fioClose(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void fioRead(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void fioWrite(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void fioLseek(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void fioMkdir(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void fioChdir(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void fioRmdir(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void fioGetstat(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void fioRemove(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void GsSetCrt(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void GsGetIMR(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void GsPutIMR(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void GsSetVideoMode(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void GetOsdConfigParam(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void SetOsdConfigParam(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void GetRomName(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void SifLoadElfPart(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void sceSifLoadModule(uint8_t *rdram, R5900Context *ctx)
{
// TODO
}
void TODO(uint8_t *rdram, R5900Context *ctx)
{
uint32_t syscall_num = getRegU32(ctx, 2); // $v0 often holds syscall num before call
std::cerr << "Warning: Unimplemented syscall called. PC=0x" << std::hex << ctx->pc
<< " Syscall # (approx): 0x" << syscall_num << std::dec << std::endl;
setReturnS32(ctx, -1); // Return error
}
// Helper functions
void RenderFrame(uint8_t *rdram)
{
// TODO
}
}