refactor: remove re code veronica hacks

This commit is contained in:
Ran-j
2026-01-27 17:06:22 -03:00
parent ff8d354259
commit 7b3fee9247
2 changed files with 6 additions and 649 deletions
-362
View File
@@ -10,9 +10,6 @@
#include <unordered_map>
#include "raylib.h"
// From ps2_syscalls.cpp to help keep the scheduler semaphore sane.
extern std::atomic<int> g_schedulerSemaId;
#define ELF_MAGIC 0x464C457F // "\x7FELF" in little endian
#define ET_EXEC 2 // Executable file
@@ -168,82 +165,6 @@ static void UploadFrame(Texture2D &tex, PS2Runtime *rt)
UpdateTexture(tex, scratch.data());
}
static void DumpFramebufferSample(PS2Memory &mem)
{
uint32_t base = DEFAULT_FB_ADDR & 0x1FFFFFFF;
uint8_t *ptr = mem.getRDRAM() + base;
uint32_t sum = 0;
for (int i = 0; i < 32; ++i)
{
sum += ptr[i];
}
std::cout << "[FB] addr=0x" << std::hex << DEFAULT_FB_ADDR << " first32 sum=0x" << sum << std::dec
<< " bytes:";
for (int i = 0; i < 16; ++i)
{
std::cout << " " << (int)ptr[i];
}
std::cout << std::dec << std::endl;
// Also dump the thread param block used in InitThread (0x363610 area)
uint32_t tparam = 0x363600 & PS2_RAM_MASK;
uint32_t *tp = reinterpret_cast<uint32_t *>(mem.getRDRAM() + tparam);
std::cout << "[InitThread params] @0x363600: "
<< std::hex << tp[0] << " " << tp[1] << " " << tp[2] << " " << tp[3]
<< " " << tp[4] << " " << tp[5] << " " << tp[6] << std::dec << std::endl;
}
// Trace hook for a suspected thread entry to see what it does.
static PS2Runtime::RecompiledFunction g_entry_10c920 = nullptr;
static void entry_10c920_traced(uint8_t *rdram, R5900Context *ctx, PS2Runtime *runtime)
{
std::cout << "[trace] enter 0x10c920 sp=0x" << std::hex << ctx->r[29].m128i_u32[0]
<< " gp=0x" << ctx->r[28].m128i_u32[0]
<< " ra=0x" << ctx->r[31].m128i_u32[0] << std::dec << std::endl;
if (g_entry_10c920)
{
g_entry_10c920(rdram, ctx, runtime);
}
std::cout << "[trace] exit 0x10c920 pc=0x" << std::hex << ctx->pc
<< " ra=0x" << ctx->r[31].m128i_u32[0] << std::dec << std::endl;
}
// Hook for sceGsPutDispEnv to capture display buffer setup.
static PS2Runtime::RecompiledFunction g_putDispEnv = nullptr;
static void sceGsPutDispEnv_hook(uint8_t *rdram, R5900Context *ctx, PS2Runtime *runtime)
{
uint32_t envPtr = GPR_U32(ctx, 4);
const uint8_t *base = runtime->memory().getRDRAM();
constexpr uint32_t MASK = PS2_RAM_SIZE - 1;
const uint64_t *env = reinterpret_cast<const uint64_t *>(base + (envPtr & MASK));
if (env)
{
auto &gs = runtime->memory().gs();
gs.dispfb1 = env[0];
gs.display1 = env[1];
std::cout << "[hook] sceGsPutDispEnv @0x" << std::hex << envPtr
<< " dispfb1=0x" << env[0] << " display1=0x" << env[1] << std::dec << std::endl;
}
if (g_putDispEnv)
{
g_putDispEnv(rdram, ctx, runtime);
}
}
// Hook for sceSifCallRpc to keep IOP RPC loops from stalling the main thread.
static PS2Runtime::RecompiledFunction g_sceSifCallRpc = nullptr;
static void sceSifCallRpc_stub(uint8_t *rdram, R5900Context *ctx, PS2Runtime *runtime)
{
static int logCount = 0;
if (logCount++ < 5)
{
std::cout << "[stub] sceSifCallRpc fno=0x" << std::hex << GPR_U32(ctx, 5)
<< " mode=0x" << GPR_U32(ctx, 6)
<< " send=0x" << GPR_U32(ctx, 7)
<< " recv=0x" << GPR_U32(ctx, 8) << std::dec << std::endl;
}
SET_GPR_S32(ctx, 2, 0);
}
PS2Runtime::PS2Runtime()
{
@@ -360,30 +281,6 @@ bool PS2Runtime::loadELF(const std::string &elfPath)
m_loadedModules.push_back(module);
// acccordind to GPT some titles expect cmd_sem_init to see -1 sentinels before creating semaphores.
const uint32_t semaInitAddrs[] = {0x00302c90u, 0x00302c94u, 0x00302c98u, 0x00302c9cu};
bool seeded = false;
for (uint32_t addr : semaInitAddrs)
{
uint32_t physAddr = m_memory.translateAddress(addr);
uint32_t *p = reinterpret_cast<uint32_t *>(m_memory.getRDRAM() + physAddr);
if (*p == 0)
{
*p = 0xFFFFFFFFu;
seeded = true;
}
}
if (seeded)
{
std::cout << "[init] Seeded cmd_sem_init sema IDs to -1" << std::endl;
}
// Debug: peek at some early globals to verify init state
uint32_t dbg_addr = 0x00300000 + 11240;
uint8_t *dbg_base = m_memory.getRDRAM();
uint32_t dbg_val = *reinterpret_cast<uint32_t *>(dbg_base + (dbg_addr & PS2_RAM_MASK));
std::cout << "Debug: [0x" << std::hex << dbg_addr << "] = 0x" << dbg_val << std::dec << std::endl;
std::cout << "ELF file loaded successfully. Entry point: 0x" << std::hex << m_cpuContext.pc << std::dec << std::endl;
return true;
}
@@ -425,53 +322,6 @@ void PS2Runtime::SignalException(R5900Context *ctx, PS2Exception exception)
}
}
static PS2Runtime::RecompiledFunction g_entry_10cb00 = nullptr;
static void entry_10cb00_hook(uint8_t *rdram, R5900Context *ctx, PS2Runtime *runtime)
{
static int logCount = 0;
if (logCount < 16)
{
std::cout << "[cmdq] enqueue cmd=0 tid=" << GPR_U32(ctx, 16)
<< " a0=0x" << std::hex << GPR_U32(ctx, 4) << std::dec << std::endl;
++logCount;
}
if (g_entry_10cb00)
{
g_entry_10cb00(rdram, ctx, runtime);
}
}
static PS2Runtime::RecompiledFunction g_entry_10cb98 = nullptr;
static void entry_10cb98_hook(uint8_t *rdram, R5900Context *ctx, PS2Runtime *runtime)
{
static int logCount = 0;
if (logCount < 16)
{
std::cout << "[cmdq] enqueue cmd=1 tid=" << GPR_U32(ctx, 16)
<< " a0=0x" << std::hex << GPR_U32(ctx, 4) << std::dec << std::endl;
++logCount;
}
if (g_entry_10cb98)
{
g_entry_10cb98(rdram, ctx, runtime);
}
}
static PS2Runtime::RecompiledFunction g_entry_10cc34 = nullptr;
static void entry_10cc34_hook(uint8_t *rdram, R5900Context *ctx, PS2Runtime *runtime)
{
static int logCount = 0;
if (logCount < 16)
{
std::cout << "[cmdq] enqueue cmd=2 tid=" << GPR_U32(ctx, 16)
<< " a0=0x" << std::hex << GPR_U32(ctx, 4) << std::dec << std::endl;
++logCount;
}
if (g_entry_10cc34)
{
g_entry_10cc34(rdram, ctx, runtime);
}
}
void PS2Runtime::executeVU0Microprogram(uint8_t *rdram, R5900Context *ctx, uint32_t address)
{
@@ -572,118 +422,8 @@ void PS2Runtime::run()
Texture2D frameTex = LoadTextureFromImage(blank);
UnloadImage(blank);
if (hasFunction(0x10c920))
{
g_entry_10c920 = lookupFunction(0x10c920);
registerFunction(0x10c920, entry_10c920_traced);
std::cout << "[trace] hooked entry 0x10c920 for logging" << std::endl;
}
else
{
std::cout << "[trace] entry 0x10c920 not registered" << std::endl;
}
if (hasFunction(0x1004b8))
{
g_putDispEnv = lookupFunction(0x1004b8);
registerFunction(0x1004b8, sceGsPutDispEnv_hook);
std::cout << "[hook] wrapped sceGsPutDispEnv at 0x1004b8" << std::endl;
}
if (hasFunction(0x10ed80))
{
g_sceSifCallRpc = lookupFunction(0x10ed80);
registerFunction(0x10ed80, sceSifCallRpc_stub);
std::cout << "[hook] wrapped sceSifCallRpc at 0x10ed80" << std::endl;
}
if (hasFunction(0x10cb00))
{
g_entry_10cb00 = lookupFunction(0x10cb00);
registerFunction(0x10cb00, entry_10cb00_hook);
std::cout << "[hook] wrapped cmd queue (cmd=0) at 0x10cb00" << std::endl;
}
if (hasFunction(0x10cb98))
{
g_entry_10cb98 = lookupFunction(0x10cb98);
registerFunction(0x10cb98, entry_10cb98_hook);
std::cout << "[hook] wrapped cmd queue (cmd=1) at 0x10cb98" << std::endl;
}
if (hasFunction(0x10cc34))
{
g_entry_10cc34 = lookupFunction(0x10cc34);
registerFunction(0x10cc34, entry_10cc34_hook);
std::cout << "[hook] wrapped cmd queue (cmd=2) at 0x10cc34" << std::endl;
}
g_activeThreads.store(1, std::memory_order_relaxed);
// for now if the scheduler sema hasn't been created yet, force InitThread to set it up.
if (hasFunction(0x10c9f8))
{
uint32_t *sched = reinterpret_cast<uint32_t *>(m_memory.getRDRAM() + (0x363a10 & PS2_RAM_MASK));
if (!sched || sched[0] == 0)
{
RecompiledFunction initThread = lookupFunction(0x10c9f8);
R5900Context initCtx{};
std::memset(&initCtx, 0, sizeof(initCtx));
initCtx.r[0] = _mm_set1_epi32(0);
initCtx.r[29] = _mm_set1_epi32(0x02000000);
initCtx.r[28] = _mm_set1_epi32(0x36a7f0);
initCtx.pc = 0x10c9f8;
std::cout << "[autorun] running InitThread pc=0x10c9f8" << std::endl;
initThread(m_memory.getRDRAM(), &initCtx, this);
}
}
// Fallback: if the game's main entry (ps2_main at 0x12b0a0) is registered, start it on a separate host thread.
// The normal bootstrap thread seems to stall before spawning it, so we kick it off manually.
if (hasFunction(0x12b0a0))
{
RecompiledFunction ps2Main = lookupFunction(0x12b0a0);
g_activeThreads.fetch_add(1, std::memory_order_relaxed);
std::thread([=]() mutable
{
R5900Context localCtx{};
std::memset(&localCtx, 0, sizeof(localCtx));
// Set baseline registers similar to the primary thread.
localCtx.r[0] = _mm_set1_epi32(0);
localCtx.r[29] = _mm_set1_epi32(0x02000000); // SP top of RAM
localCtx.r[28] = _mm_set1_epi32(0x36a7f0); // GP from ELF bootstrap
localCtx.pc = 0x12b0a0;
std::cout << "[autorun] starting ps2_main fallback pc=0x12b0a0 sp=0x02000000 gp=0x36a7f0" << std::endl;
try
{
ps2Main(m_memory.getRDRAM(), &localCtx, this);
std::cout << "[autorun] ps2_main returned pc=0x" << std::hex << localCtx.pc
<< " ra=0x" << localCtx.r[31].m128i_u32[0] << std::dec << std::endl;
}
catch (const std::exception &e)
{
std::cerr << "[autorun] ps2_main exception: " << e.what() << std::endl;
}
g_activeThreads.fetch_sub(1, std::memory_order_relaxed); })
.detach();
}
else
{
std::cout << "[autorun] ps2_main not registered; skipping fallback launch" << std::endl;
}
// Dump a small sample
{
uint32_t base = DEFAULT_FB_ADDR & 0x1FFFFFFF;
uint8_t *ptr = m_memory.getRDRAM() + base;
uint32_t sum = 0;
for (int i = 0; i < 32; ++i)
sum += ptr[i];
std::cout << "[FB] addr=0x" << std::hex << DEFAULT_FB_ADDR
<< " first32 sum=0x" << sum << " bytes:";
for (int i = 0; i < 16; ++i)
{
std::cout << " " << (int)ptr[i];
}
std::cout << std::dec << std::endl;
}
std::thread gameThread([&, entryPoint]()
{
try
@@ -698,66 +438,9 @@ void PS2Runtime::run()
}
g_activeThreads.fetch_sub(1, std::memory_order_relaxed); });
static uint32_t lastSchedId = 0;
uint64_t tick = 0;
while (g_activeThreads.load(std::memory_order_relaxed) > 0)
{
{
uint32_t *sched = reinterpret_cast<uint32_t *>(m_memory.getRDRAM() + (0x363a10 & PS2_RAM_MASK));
int known = g_schedulerSemaId.load(std::memory_order_relaxed);
if (sched)
{
if ((sched[0] == 0 || sched[0] > 1000) && known > 0)
sched[0] = static_cast<uint32_t>(known);
// head/tail indices
if (sched[2] > 511)
sched[2] = 0;
if (sched[3] > 511)
sched[3] = 0;
}
}
{
constexpr uint32_t kSchedSpan = 0x420;
static std::vector<uint8_t> schedSnapshot;
static int schedDeltaLogs = 0;
uint8_t *rdram = m_memory.getRDRAM();
uint32_t base = 0x363a10 & PS2_RAM_MASK;
if (schedSnapshot.empty())
{
schedSnapshot.resize(kSchedSpan);
std::memcpy(schedSnapshot.data(), rdram + base, kSchedSpan);
}
else
{
int diffCount = 0;
int detailCount = 0;
for (uint32_t i = 0; i < kSchedSpan; ++i)
{
uint8_t cur = rdram[(base + i) & PS2_RAM_MASK];
uint8_t prev = schedSnapshot[i];
if (cur != prev)
{
schedSnapshot[i] = cur;
++diffCount;
if (schedDeltaLogs < 32 && detailCount < 8)
{
std::cout << "[sched delta] off=0x" << std::hex << i
<< " " << (int)prev << "->" << (int)cur << std::dec << std::endl;
++detailCount;
}
}
}
if (diffCount > 0 && schedDeltaLogs < 32)
{
std::cout << "[sched delta] changed=" << diffCount << std::endl;
++schedDeltaLogs;
}
}
}
if ((tick++ % 120) == 0)
{
std::cout << "[run] activeThreads=" << g_activeThreads.load(std::memory_order_relaxed);
@@ -768,27 +451,6 @@ void PS2Runtime::run()
}
if ((tick % 600) == 0)
{
static int schedLog = 0;
if (schedLog < 5)
{
uint8_t *rdram = m_memory.getRDRAM();
uint32_t base = 0x363a10 & PS2_RAM_MASK;
uint32_t *p = reinterpret_cast<uint32_t *>(rdram + base);
uint32_t argPtr = 0x363a18 & PS2_RAM_MASK;
uint32_t idx = *reinterpret_cast<uint32_t *>(rdram + argPtr) & 0x1FF;
uint32_t cmdBase = (argPtr + 8) & PS2_RAM_MASK;
uint32_t tidBase = (argPtr + 9) & PS2_RAM_MASK;
uint8_t cmd0 = rdram[cmdBase & PS2_RAM_MASK];
uint8_t tid0 = rdram[tidBase & PS2_RAM_MASK];
uint8_t cmdIdx = rdram[(cmdBase + (idx << 1)) & PS2_RAM_MASK];
uint8_t tidIdx = rdram[(tidBase + (idx << 1)) & PS2_RAM_MASK];
std::cout << "[sched] sema=" << p[0] << " q1=" << p[1] << " head=" << p[2] << " tail=" << p[3]
<< " cmd0=" << (int)cmd0 << "/" << (int)tid0
<< " cmd[idx=" << idx << "]=" << (int)cmdIdx << "/" << (int)tidIdx
<< " lastId=" << lastSchedId << std::endl;
++schedLog;
}
static uint64_t lastDma = 0, lastGif = 0, lastGs = 0, lastVif = 0;
uint64_t curDma = m_memory.dmaStartCount();
uint64_t curGif = m_memory.gifCopyCount();
@@ -806,30 +468,6 @@ void PS2Runtime::run()
lastVif = curVif;
}
}
// Kick the scheduler semaphore (stored at 0x363a10) to simulate VBlank-style ticks.
{
uint32_t schedId = *reinterpret_cast<uint32_t *>(m_memory.getRDRAM() + (0x363a10 & PS2_RAM_MASK));
if (schedId && schedId < 0x1000)
{
lastSchedId = schedId;
}
if (schedId == 0 && lastSchedId != 0)
{
schedId = lastSchedId; // fall back to the last seen non-zero id
}
else if (schedId >= 0x1000 && lastSchedId != 0)
{
// Ignore obviously bogus ids that are likely other data scribbling over the struct.
schedId = lastSchedId;
}
if (schedId)
{
R5900Context semaCtx{};
R5900Context *semaCtxPtr = &semaCtx;
SET_GPR_U32(semaCtxPtr, 4, schedId);
ps2_syscalls::SignalSema(m_memory.getRDRAM(), semaCtxPtr, this);
}
}
UploadFrame(frameTex, this);
BeginDrawing();