#include #include #include #include "rsp.hpp" static recomp::rsp::callbacks_t rsp_callbacks {}; void recomp::rsp::set_callbacks(const callbacks_t& callbacks) { rsp_callbacks = callbacks; } uint8_t dmem[0x1000]; uint16_t rspReciprocals[512]; uint16_t rspInverseSquareRoots[512]; // From Ares emulator. For license details, see rsp_vu.h void recomp::rsp::constants_init() { rspReciprocals[0] = u16(~0); for (u16 index = 1; index < 512; index++) { u64 a = index + 512; u64 b = (u64(1) << 34) / a; rspReciprocals[index] = u16((b + 1) >> 8); } for (u16 index = 0; index < 512; index++) { u64 a = (index + 512) >> ((index % 2 == 1) ? 1 : 0); u64 b = 1 << 17; //find the largest b where b < 1.0 / sqrt(a) while (a * (b + 1) * (b + 1) < (u64(1) << 44)) b++; rspInverseSquareRoots[index] = u16(b >> 1); } } // Runs a recompiled RSP microcode bool recomp::rsp::run_task(uint8_t* rdram, const OSTask* task) { assert(rsp_callbacks.get_rsp_microcode != nullptr); RspUcodeFunc* ucode_func = rsp_callbacks.get_rsp_microcode(task); if (ucode_func == nullptr) { fprintf(stderr, "No registered RSP ucode for %" PRIu32 " (returned `nullptr`)\n", task->t.type); return false; } // Load the OSTask into DMEM memcpy(&dmem[0xFC0], task, sizeof(OSTask)); // Load the ucode data into DMEM dma_rdram_to_dmem(rdram, 0x0000, task->t.ucode_data, 0xF80 - 1); // Run the ucode RspExitReason exit_reason = ucode_func(rdram, task->t.ucode); // Ensure that the ucode exited correctly if (exit_reason != RspExitReason::Broke) { fprintf(stderr, "RSP ucode %" PRIu32 " exited unexpectedly. exit_reason: %i\n", task->t.type, static_cast(exit_reason)); assert(exit_reason == RspExitReason::Broke); return false; } return true; }