N64ModernRuntime/librecomp/src/rsp.cpp
2025-01-16 00:32:33 -05:00

62 lines
1.9 KiB
C++

#include <cassert>
#include <cstring>
#include <cinttypes>
#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<int>(exit_reason));
assert(exit_reason == RspExitReason::Broke);
return false;
}
return true;
}