mirror of
https://github.com/ran-j/PS2Recomp.git
synced 2026-09-26 08:51:05 -04:00
feat: added runtime base stubs definitions
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+390
-564
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user