mirror of
https://github.com/N64Recomp/N64ModernRuntime.git
synced 2026-05-11 03:12:15 +00:00
Made rdram size an argument in recomp::start, reorganized some PI address constants
This commit is contained in:
parent
71cd05807f
commit
cc2d991972
6 changed files with 48 additions and 35 deletions
21
librecomp/include/librecomp/addresses.hpp
Normal file
21
librecomp/include/librecomp/addresses.hpp
Normal 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
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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");
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue