diff --git a/ps2xRuntime/include/ps2_runtime.h b/ps2xRuntime/include/ps2_runtime.h index 56c4ee3..b1fe05c 100644 --- a/ps2xRuntime/include/ps2_runtime.h +++ b/ps2xRuntime/include/ps2_runtime.h @@ -380,7 +380,7 @@ public: PS2Runtime(); ~PS2Runtime(); - bool initialize(); + bool initialize(const char *title = "PS2 Game"); bool loadELF(const std::string &elfPath); void run(); @@ -390,7 +390,7 @@ public: RecompiledFunction lookupFunction(uint32_t address); void SignalException(R5900Context *ctx, PS2Exception exception); - + void executeVU0Microprogram(uint8_t *rdram, R5900Context *ctx, uint32_t address); void vu0StartMicroProgram(uint8_t *rdram, R5900Context *ctx, uint32_t address); @@ -405,6 +405,13 @@ public: void handleTLBP(uint8_t *rdram, R5900Context *ctx); void clearLLBit(R5900Context *ctx); +public: + inline R5900Context &cpu() { return m_cpuContext; } + inline const R5900Context &cpu() const { return m_cpuContext; } + + inline PS2Memory &memory() { return m_memory; } + inline const PS2Memory &memory() const { return m_memory; } + public: bool check_overflow = false; diff --git a/ps2xRuntime/include/ps2_syscalls.h b/ps2xRuntime/include/ps2_syscalls.h index f4ac51f..3d04e08 100644 --- a/ps2xRuntime/include/ps2_syscalls.h +++ b/ps2xRuntime/include/ps2_syscalls.h @@ -2,6 +2,9 @@ #define PS2_SYSCALLS_H #include "ps2_runtime.h" +#include + +static std::mutex g_sys_fd_mutex; #define PS2_FIO_O_RDONLY 0x0001 #define PS2_FIO_O_WRONLY 0x0002 diff --git a/ps2xRuntime/src/main.cpp b/ps2xRuntime/src/main.cpp index 436a632..cc2b686 100644 --- a/ps2xRuntime/src/main.cpp +++ b/ps2xRuntime/src/main.cpp @@ -14,7 +14,7 @@ int main(int argc, char *argv[]) std::string elfPath = argv[1]; PS2Runtime runtime; - if (!runtime.initialize()) + if (!runtime.initialize("ps2xRuntime (Raylib host)")) { std::cerr << "Failed to initialize PS2 runtime" << std::endl; return 1; diff --git a/ps2xRuntime/src/ps2_runtime.cpp b/ps2xRuntime/src/ps2_runtime.cpp index 4218a00..30f5bc9 100644 --- a/ps2xRuntime/src/ps2_runtime.cpp +++ b/ps2xRuntime/src/ps2_runtime.cpp @@ -3,6 +3,7 @@ #include #include #include +#include "raylib.h" #define ELF_MAGIC 0x464C457F // "\x7FELF" in little endian #define ET_EXEC 2 // Executable file @@ -46,6 +47,16 @@ struct ProgramHeader }; #define PT_LOAD 1 // Loadable segment + +static constexpr int FB_WIDTH = 640; +static constexpr int FB_HEIGHT = 448; +static constexpr uint32_t DEFAULT_FB_ADDR = 0x00100000; // location in RDRAM the guest will draw to + +static void UploadFrame(Texture2D &tex, PS2Runtime *rt) +{ + uint8_t *src = rt->memory().getRDRAM() + (DEFAULT_FB_ADDR & 0x1FFFFFFF); + UpdateTexture(tex, src); +} PS2Runtime::PS2Runtime() { @@ -68,7 +79,7 @@ PS2Runtime::~PS2Runtime() m_functionTable.clear(); } -bool PS2Runtime::initialize() +bool PS2Runtime::initialize(const char *title) { if (!m_memory.initialize()) { @@ -76,6 +87,10 @@ bool PS2Runtime::initialize() return false; } + SetConfigFlags(FLAG_WINDOW_RESIZABLE); + InitWindow(FB_WIDTH, FB_HEIGHT, title); + SetTargetFPS(60); + return true; } @@ -163,7 +178,7 @@ PS2Runtime::RecompiledFunction PS2Runtime::lookupFunction(uint32_t address) std::cerr << "Warning: Function at address 0x" << std::hex << address << std::dec << " not found" << std::endl; - static RecompiledFunction defaultFunction = [](uint8_t *rdram, R5900Context *ctx, PS2Runtime* runtime) + static RecompiledFunction defaultFunction = [](uint8_t *rdram, R5900Context *ctx, PS2Runtime *runtime) { std::cerr << "Error: Called unimplemented function at address 0x" << std::hex << ctx->pc << std::dec << std::endl; }; @@ -199,7 +214,7 @@ void PS2Runtime::vu0StartMicroProgram(uint8_t *rdram, R5900Context *ctx, uint32_ void PS2Runtime::handleSyscall(uint8_t *rdram, R5900Context *ctx) { - std::cout << "Syscall encountered at PC: 0x" << std::hex << ctx->pc << std::dec << std::endl; + std::cout << "Syscall encountered at PC: 0x" << std::hex << ctx->pc << std::dec << std::endl; } void PS2Runtime::handleBreak(uint8_t *rdram, R5900Context *ctx) @@ -268,6 +283,30 @@ void PS2Runtime::run() entryPoint(m_memory.getRDRAM(), &m_cpuContext, this); std::cout << "Program execution completed successfully" << std::endl; + + // A blank image to use as a framebuffer + Image blank = GenImageColor(FB_WIDTH, FB_HEIGHT, BLANK); + Texture2D frameTex = LoadTextureFromImage(blank); + UnloadImage(blank); + + while (!WindowShouldClose()) + { + // TODO step only a small slice each host + auto self = this; + lookupFunction(memory().read32(0))( + memory().getRDRAM(), + &cpu(), + self); + + UploadFrame(frameTex, self); + + BeginDrawing(); + ClearBackground(BLACK); + DrawTexture(frameTex, 0, 0, WHITE); + EndDrawing(); + } + + CloseWindow(); } catch (const std::exception &e) { diff --git a/ps2xRuntime/src/ps2_syscalls.cpp b/ps2xRuntime/src/ps2_syscalls.cpp index a7640ad..87d3ac5 100644 --- a/ps2xRuntime/src/ps2_syscalls.cpp +++ b/ps2xRuntime/src/ps2_syscalls.cpp @@ -484,7 +484,11 @@ namespace ps2_syscalls return; } - size_t bytesRead = ::fread(hostBuf, 1, size, fp); + size_t bytesRead = 0; + { + std::lock_guard lock(g_sys_fd_mutex); + bytesRead = fread(hostBuf, 1, size, fp); + } if (bytesRead < size && ferror(fp)) {