Made rdram size an argument in recomp::start, reorganized some PI address constants

This commit is contained in:
Mr-Wiseguy 2024-07-05 21:27:27 -04:00
parent 71cd05807f
commit cc2d991972
6 changed files with 48 additions and 35 deletions

View file

@ -0,0 +1,21 @@
#ifndef __RECOMP_ADDRESSES_HPP__
#define __RECOMP_ADDRESSES_HPP__
#include <cstdint>
#include "ultramodern/ultra64.h"
namespace recomp {
// We need a place in rdram to hold the PI handles, so pick an address in extended rdram
constexpr int32_t cart_handle = 0x80800000;
constexpr int32_t drive_handle = (int32_t)(cart_handle + sizeof(OSPiHandle));
constexpr int32_t flash_handle = (int32_t)(drive_handle + sizeof(OSPiHandle));
// Flashram occupies the same physical address as sram, but that issue is avoided because libultra exposes
// a high-level interface for flashram. Because that high-level interface is reimplemented, low level accesses
// that involve physical addresses don't need to be handled for flashram.
constexpr uint32_t sram_base = 0x08000000;
constexpr uint32_t rom_base = 0x10000000;
constexpr uint32_t drive_base = 0x06000000;
}
#endif

View file

@ -49,6 +49,7 @@ namespace recomp {
* It must be called only once and it must be called before `ultramodern::preinit`. * It must be called only once and it must be called before `ultramodern::preinit`.
*/ */
void start( void start(
uint32_t rdram_size,
ultramodern::renderer::WindowHandle window_handle, ultramodern::renderer::WindowHandle window_handle,
const recomp::rsp::callbacks_t& rsp_callbacks, const recomp::rsp::callbacks_t& rsp_callbacks,
const ultramodern::renderer::callbacks_t& renderer_callbacks, const ultramodern::renderer::callbacks_t& renderer_callbacks,

View file

@ -2,7 +2,8 @@
#include <cassert> #include <cassert>
#include <ultramodern/ultra64.h> #include <ultramodern/ultra64.h>
#include <ultramodern/ultramodern.hpp> #include <ultramodern/ultramodern.hpp>
#include "recomp.h" #include "librecomp/recomp.h"
#include "librecomp/addresses.hpp"
// TODO move this out into ultramodern code // TODO move this out into ultramodern code
@ -21,7 +22,7 @@ void save_clear(uint32_t start, uint32_t size, char value);
std::array<char, page_size> write_buffer; std::array<char, page_size> write_buffer;
extern "C" void osFlashInit_recomp(uint8_t * rdram, recomp_context * ctx) { extern "C" void osFlashInit_recomp(uint8_t * rdram, recomp_context * ctx) {
ctx->r2 = ultramodern::flash_handle; ctx->r2 = recomp::flash_handle;
} }
extern "C" void osFlashReadStatus_recomp(uint8_t * rdram, recomp_context * ctx) { extern "C" void osFlashReadStatus_recomp(uint8_t * rdram, recomp_context * ctx) {

View file

@ -4,9 +4,10 @@
#include <cstring> #include <cstring>
#include <string> #include <string>
#include <mutex> #include <mutex>
#include "recomp.h" #include "librecomp/recomp.h"
#include "game.hpp" #include "librecomp/addresses.hpp"
#include "files.hpp" #include "librecomp/game.hpp"
#include "librecomp/files.hpp"
#include <ultramodern/ultra64.h> #include <ultramodern/ultra64.h>
#include <ultramodern/ultramodern.hpp> #include <ultramodern/ultramodern.hpp>
@ -20,13 +21,6 @@ void recomp::set_rom_contents(std::vector<uint8_t>&& new_rom) {
rom = std::move(new_rom); rom = std::move(new_rom);
} }
// Flashram occupies the same physical address as sram, but that issue is avoided because libultra exposes
// a high-level interface for flashram. Because that high-level interface is reimplemented, low level accesses
// that involve physical addresses don't need to be handled for flashram.
constexpr uint32_t sram_base = 0x08000000;
constexpr uint32_t rom_base = 0x10000000;
constexpr uint32_t drive_base = 0x06000000;
constexpr uint32_t k1_to_phys(uint32_t addr) { constexpr uint32_t k1_to_phys(uint32_t addr) {
return addr & 0x1FFFFFFF; return addr & 0x1FFFFFFF;
} }
@ -42,21 +36,21 @@ extern "C" void __osPiRelAccess_recomp(uint8_t* rdram, recomp_context* ctx) {
} }
extern "C" void osCartRomInit_recomp(uint8_t* rdram, recomp_context* ctx) { extern "C" void osCartRomInit_recomp(uint8_t* rdram, recomp_context* ctx) {
OSPiHandle* handle = TO_PTR(OSPiHandle, ultramodern::cart_handle); OSPiHandle* handle = TO_PTR(OSPiHandle, recomp::cart_handle);
handle->type = 0; // cart handle->type = 0; // cart
handle->baseAddress = phys_to_k1(rom_base); handle->baseAddress = phys_to_k1(recomp::rom_base);
handle->domain = 0; handle->domain = 0;
ctx->r2 = (gpr)ultramodern::cart_handle; ctx->r2 = (gpr)recomp::cart_handle;
} }
extern "C" void osDriveRomInit_recomp(uint8_t * rdram, recomp_context * ctx) { extern "C" void osDriveRomInit_recomp(uint8_t * rdram, recomp_context * ctx) {
OSPiHandle* handle = TO_PTR(OSPiHandle, ultramodern::drive_handle); OSPiHandle* handle = TO_PTR(OSPiHandle, recomp::drive_handle);
handle->type = 1; // bulk handle->type = 1; // bulk
handle->baseAddress = phys_to_k1(drive_base); handle->baseAddress = phys_to_k1(recomp::drive_base);
handle->domain = 0; handle->domain = 0;
ctx->r2 = (gpr)ultramodern::drive_handle; ctx->r2 = (gpr)recomp::drive_handle;
} }
extern "C" void osCreatePiManager_recomp(uint8_t* rdram, recomp_context* ctx) { extern "C" void osCreatePiManager_recomp(uint8_t* rdram, recomp_context* ctx) {
@ -70,7 +64,7 @@ void recomp::do_rom_read(uint8_t* rdram, gpr ram_address, uint32_t physical_addr
assert((physical_addr & 0x1) == 0 && "Only PI DMA from aligned ROM addresses is currently supported"); assert((physical_addr & 0x1) == 0 && "Only PI DMA from aligned ROM addresses is currently supported");
assert((ram_address & 0x7) == 0 && "Only PI DMA to aligned RDRAM addresses is currently supported"); assert((ram_address & 0x7) == 0 && "Only PI DMA to aligned RDRAM addresses is currently supported");
assert((num_bytes & 0x1) == 0 && "Only PI DMA with aligned sizes is currently supported"); assert((num_bytes & 0x1) == 0 && "Only PI DMA with aligned sizes is currently supported");
uint8_t* rom_addr = rom.data() + physical_addr - rom_base; uint8_t* rom_addr = rom.data() + physical_addr - recomp::rom_base;
for (size_t i = 0; i < num_bytes; i++) { for (size_t i = 0; i < num_bytes; i++) {
MEM_B(i, ram_address) = *rom_addr; MEM_B(i, ram_address) = *rom_addr;
rom_addr++; rom_addr++;
@ -80,7 +74,7 @@ void recomp::do_rom_read(uint8_t* rdram, gpr ram_address, uint32_t physical_addr
void recomp::do_rom_pio(uint8_t* rdram, gpr ram_address, uint32_t physical_addr) { void recomp::do_rom_pio(uint8_t* rdram, gpr ram_address, uint32_t physical_addr) {
assert((physical_addr & 0x3) == 0 && "PIO not 4-byte aligned in device, currently unsupported"); assert((physical_addr & 0x3) == 0 && "PIO not 4-byte aligned in device, currently unsupported");
assert((ram_address & 0x3) == 0 && "PIO not 4-byte aligned in RDRAM, currently unsupported"); assert((ram_address & 0x3) == 0 && "PIO not 4-byte aligned in RDRAM, currently unsupported");
uint8_t* rom_addr = rom.data() + physical_addr - rom_base; uint8_t* rom_addr = rom.data() + physical_addr - recomp::rom_base;
MEM_B(0, ram_address) = *rom_addr++; MEM_B(0, ram_address) = *rom_addr++;
MEM_B(1, ram_address) = *rom_addr++; MEM_B(1, ram_address) = *rom_addr++;
MEM_B(2, ram_address) = *rom_addr++; MEM_B(2, ram_address) = *rom_addr++;
@ -213,15 +207,15 @@ void do_dma(RDRAM_ARG PTR(OSMesgQueue) mq, gpr rdram_address, uint32_t physical_
// TODO asynchronous transfer // TODO asynchronous transfer
// TODO implement unaligned DMA correctly // TODO implement unaligned DMA correctly
if (direction == 0) { if (direction == 0) {
if (physical_addr >= rom_base) { if (physical_addr >= recomp::rom_base) {
// read cart rom // read cart rom
recomp::do_rom_read(rdram, rdram_address, physical_addr, size); recomp::do_rom_read(rdram, rdram_address, physical_addr, size);
// Send a message to the mq to indicate that the transfer completed // Send a message to the mq to indicate that the transfer completed
osSendMesg(rdram, mq, 0, OS_MESG_NOBLOCK); osSendMesg(rdram, mq, 0, OS_MESG_NOBLOCK);
} else if (physical_addr >= sram_base) { } else if (physical_addr >= recomp::sram_base) {
// read sram // read sram
save_read(rdram, rdram_address, physical_addr - sram_base, size); save_read(rdram, rdram_address, physical_addr - recomp::sram_base, size);
// Send a message to the mq to indicate that the transfer completed // Send a message to the mq to indicate that the transfer completed
osSendMesg(rdram, mq, 0, OS_MESG_NOBLOCK); osSendMesg(rdram, mq, 0, OS_MESG_NOBLOCK);
@ -229,12 +223,12 @@ void do_dma(RDRAM_ARG PTR(OSMesgQueue) mq, gpr rdram_address, uint32_t physical_
fprintf(stderr, "[WARN] PI DMA read from unknown region, phys address 0x%08X\n", physical_addr); fprintf(stderr, "[WARN] PI DMA read from unknown region, phys address 0x%08X\n", physical_addr);
} }
} else { } else {
if (physical_addr >= rom_base) { if (physical_addr >= recomp::rom_base) {
// write cart rom // write cart rom
throw std::runtime_error("ROM DMA write unimplemented"); throw std::runtime_error("ROM DMA write unimplemented");
} else if (physical_addr >= sram_base) { } else if (physical_addr >= recomp::sram_base) {
// write sram // write sram
save_write(rdram, rdram_address, physical_addr - sram_base, size); save_write(rdram, rdram_address, physical_addr - recomp::sram_base, size);
// Send a message to the mq to indicate that the transfer completed // Send a message to the mq to indicate that the transfer completed
osSendMesg(rdram, mq, 0, OS_MESG_NOBLOCK); osSendMesg(rdram, mq, 0, OS_MESG_NOBLOCK);
@ -248,7 +242,7 @@ extern "C" void osPiStartDma_recomp(RDRAM_ARG recomp_context* ctx) {
uint32_t mb = ctx->r4; uint32_t mb = ctx->r4;
uint32_t pri = ctx->r5; uint32_t pri = ctx->r5;
uint32_t direction = ctx->r6; uint32_t direction = ctx->r6;
uint32_t devAddr = ctx->r7 | rom_base; uint32_t devAddr = ctx->r7 | recomp::rom_base;
gpr dramAddr = MEM_W(0x10, ctx->r29); gpr dramAddr = MEM_W(0x10, ctx->r29);
uint32_t size = MEM_W(0x14, ctx->r29); uint32_t size = MEM_W(0x14, ctx->r29);
PTR(OSMesgQueue) mq = MEM_W(0x18, ctx->r29); PTR(OSMesgQueue) mq = MEM_W(0x18, ctx->r29);
@ -284,7 +278,7 @@ extern "C" void osEPiReadIo_recomp(RDRAM_ARG recomp_context * ctx) {
gpr dramAddr = ctx->r6; gpr dramAddr = ctx->r6;
uint32_t physical_addr = k1_to_phys(devAddr); uint32_t physical_addr = k1_to_phys(devAddr);
if (physical_addr > rom_base) { if (physical_addr > recomp::rom_base) {
// cart rom // cart rom
recomp::do_rom_pio(PASS_RDRAM dramAddr, physical_addr); recomp::do_rom_pio(PASS_RDRAM dramAddr, physical_addr);
} else { } else {

View file

@ -374,6 +374,7 @@ void ultramodern::quit() {
} }
void recomp::start( void recomp::start(
uint32_t rdram_size,
ultramodern::renderer::WindowHandle window_handle, ultramodern::renderer::WindowHandle window_handle,
const recomp::rsp::callbacks_t& rsp_callbacks, const recomp::rsp::callbacks_t& rsp_callbacks,
const ultramodern::renderer::callbacks_t& renderer_callbacks, const ultramodern::renderer::callbacks_t& renderer_callbacks,
@ -413,8 +414,8 @@ void recomp::start(
} }
// Allocate rdram_buffer // Allocate rdram_buffer
std::unique_ptr<uint8_t[]> rdram_buffer = std::make_unique<uint8_t[]>(ultramodern::rdram_size); std::unique_ptr<uint8_t[]> rdram_buffer = std::make_unique<uint8_t[]>(rdram_size);
std::memset(rdram_buffer.get(), 0, ultramodern::rdram_size); std::memset(rdram_buffer.get(), 0, rdram_size);
std::thread game_thread{[](ultramodern::renderer::WindowHandle window_handle, uint8_t* rdram) { std::thread game_thread{[](ultramodern::renderer::WindowHandle window_handle, uint8_t* rdram) {
debug_printf("[Recomp] Starting\n"); debug_printf("[Recomp] Starting\n");

View file

@ -27,11 +27,6 @@ struct UltraThreadContext {
namespace ultramodern { namespace ultramodern {
// We need a place in rdram to hold the PI handles, so pick an address in extended rdram
constexpr uint32_t rdram_size = 1024 * 1024 * 16; // 16MB to give extra room for anything custom
constexpr int32_t cart_handle = 0x80800000;
constexpr int32_t drive_handle = (int32_t)(cart_handle + sizeof(OSPiHandle));
constexpr int32_t flash_handle = (int32_t)(drive_handle + sizeof(OSPiHandle));
constexpr uint32_t save_size = 1024 * 1024 / 8; // Maximum save size, 1Mbit for flash constexpr uint32_t save_size = 1024 * 1024 / 8; // Maximum save size, 1Mbit for flash
// Initialization. // Initialization.