mirror of
https://github.com/N64Recomp/N64ModernRuntime.git
synced 2026-03-25 20:43:11 +00:00
format librecomp
This commit is contained in:
parent
108a240186
commit
0bec4adafc
23 changed files with 389 additions and 372 deletions
|
|
@ -9,6 +9,6 @@ namespace recomp {
|
|||
std::ifstream open_input_backup_file(const std::filesystem::path& filepath, std::ios_base::openmode mode = std::ios_base::in);
|
||||
std::ofstream open_output_file_with_backup(const std::filesystem::path& filepath, std::ios_base::openmode mode = std::ios_base::out);
|
||||
bool finalize_output_file_with_backup(const std::filesystem::path& filepath);
|
||||
};
|
||||
}; // namespace recomp
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
#ifndef __RECOMP_GAME__
|
||||
#define __RECOMP_GAME__
|
||||
|
||||
#include <vector>
|
||||
#include <filesystem>
|
||||
#include <vector>
|
||||
|
||||
#include "recomp.h"
|
||||
#include "rsp.hpp"
|
||||
|
|
@ -17,50 +17,46 @@ namespace recomp {
|
|||
bool is_enabled;
|
||||
|
||||
gpr entrypoint_address;
|
||||
void (*entrypoint)(uint8_t* rdram, recomp_context* context);
|
||||
void (*entrypoint)(uint8_t *rdram, recomp_context *context);
|
||||
|
||||
std::u8string stored_filename() const;
|
||||
};
|
||||
enum class RomValidationError {
|
||||
Good,
|
||||
FailedToOpen,
|
||||
NotARom,
|
||||
IncorrectRom,
|
||||
NotYet,
|
||||
IncorrectVersion,
|
||||
OtherError
|
||||
};
|
||||
void register_config_path(std::filesystem::path path);
|
||||
bool register_game(const recomp::GameEntry& entry);
|
||||
void check_all_stored_roms();
|
||||
bool load_stored_rom(std::u8string& game_id);
|
||||
RomValidationError select_rom(const std::filesystem::path& rom_path, std::u8string& game_id);
|
||||
bool is_rom_valid(std::u8string& game_id);
|
||||
bool is_rom_loaded();
|
||||
void set_rom_contents(std::vector<uint8_t>&& new_rom);
|
||||
void do_rom_read(uint8_t* rdram, gpr ram_address, uint32_t physical_addr, size_t num_bytes);
|
||||
void do_rom_pio(uint8_t* rdram, gpr ram_address, uint32_t physical_addr);
|
||||
enum class RomValidationError {
|
||||
Good,
|
||||
FailedToOpen,
|
||||
NotARom,
|
||||
IncorrectRom,
|
||||
NotYet,
|
||||
IncorrectVersion,
|
||||
OtherError
|
||||
};
|
||||
void register_config_path(std::filesystem::path path);
|
||||
bool register_game(const recomp::GameEntry& entry);
|
||||
void check_all_stored_roms();
|
||||
bool load_stored_rom(std::u8string& game_id);
|
||||
RomValidationError select_rom(const std::filesystem::path& rom_path, std::u8string& game_id);
|
||||
bool is_rom_valid(std::u8string& game_id);
|
||||
bool is_rom_loaded();
|
||||
void set_rom_contents(std::vector<uint8_t>&& new_rom);
|
||||
void do_rom_read(uint8_t *rdram, gpr ram_address, uint32_t physical_addr, size_t num_bytes);
|
||||
void do_rom_pio(uint8_t *rdram, gpr ram_address, uint32_t physical_addr);
|
||||
|
||||
/**
|
||||
* The following arguments contain mandatory callbacks that need to be registered (i.e., can't be `nullptr`):
|
||||
* - `rsp_callbacks`
|
||||
* - `renderer_callbacks`
|
||||
*
|
||||
* It must be called only once and it must be called before `ultramodern::preinit`.
|
||||
*/
|
||||
/**
|
||||
* The following arguments contain mandatory callbacks that need to be registered (i.e., can't be `nullptr`):
|
||||
* - `rsp_callbacks`
|
||||
* - `renderer_callbacks`
|
||||
*
|
||||
* It must be called only once and it must be called before `ultramodern::preinit`.
|
||||
*/
|
||||
void start(
|
||||
ultramodern::renderer::WindowHandle window_handle,
|
||||
const recomp::rsp::callbacks_t& rsp_callbacks,
|
||||
const ultramodern::renderer::callbacks_t& renderer_callbacks,
|
||||
const ultramodern::audio_callbacks_t& audio_callbacks,
|
||||
const ultramodern::input::callbacks_t& input_callbacks,
|
||||
const ultramodern::gfx_callbacks_t& gfx_callbacks,
|
||||
ultramodern::renderer::WindowHandle window_handle, const recomp::rsp::callbacks_t& rsp_callbacks,
|
||||
const ultramodern::renderer::callbacks_t& renderer_callbacks, const ultramodern::audio_callbacks_t& audio_callbacks,
|
||||
const ultramodern::input::callbacks_t& input_callbacks, const ultramodern::gfx_callbacks_t& gfx_callbacks,
|
||||
const ultramodern::events::callbacks_t& events_callbacks,
|
||||
const ultramodern::error_handling::callbacks_t& error_handling_callbacks_
|
||||
);
|
||||
const ultramodern::error_handling::callbacks_t& error_handling_callbacks_);
|
||||
|
||||
void start_game(const std::u8string& game_id);
|
||||
std::u8string current_game_id();
|
||||
}
|
||||
void start_game(const std::u8string& game_id);
|
||||
std::u8string current_game_id();
|
||||
} // namespace recomp
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
#include <ultramodern/ultra64.h>
|
||||
|
||||
template<int index, typename T>
|
||||
T _arg(uint8_t* rdram, recomp_context* ctx) {
|
||||
T _arg(uint8_t *rdram, recomp_context *ctx) {
|
||||
static_assert(index < 4, "Only args 0 through 3 supported");
|
||||
gpr raw_arg = (&ctx->r4)[index];
|
||||
if constexpr (std::is_same_v<T, float>) {
|
||||
|
|
@ -15,13 +15,14 @@ T _arg(uint8_t* rdram, recomp_context* ctx) {
|
|||
}
|
||||
else {
|
||||
// static_assert in else workaround
|
||||
[] <bool flag = false>() {
|
||||
[]<bool flag = false>() {
|
||||
static_assert(flag, "Floats in a2/a3 not supported");
|
||||
}();
|
||||
}
|
||||
();
|
||||
}
|
||||
}
|
||||
else if constexpr (std::is_pointer_v<T>) {
|
||||
static_assert (!std::is_pointer_v<std::remove_pointer_t<T>>, "Double pointers not supported");
|
||||
static_assert(!std::is_pointer_v<std::remove_pointer_t<T>>, "Double pointers not supported");
|
||||
return TO_PTR(std::remove_pointer_t<T>, raw_arg);
|
||||
}
|
||||
else if constexpr (std::is_integral_v<T>) {
|
||||
|
|
@ -30,14 +31,15 @@ T _arg(uint8_t* rdram, recomp_context* ctx) {
|
|||
}
|
||||
else {
|
||||
// static_assert in else workaround
|
||||
[] <bool flag = false>() {
|
||||
[]<bool flag = false>() {
|
||||
static_assert(flag, "Unsupported type");
|
||||
}();
|
||||
}
|
||||
();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void _return(recomp_context* ctx, T val) {
|
||||
template<typename T>
|
||||
void _return(recomp_context *ctx, T val) {
|
||||
static_assert(sizeof(T) <= 4 && "Only 32-bit value returns supported currently");
|
||||
if constexpr (std::is_same_v<T, float>) {
|
||||
ctx->f0.fl = val;
|
||||
|
|
@ -47,9 +49,10 @@ void _return(recomp_context* ctx, T val) {
|
|||
}
|
||||
else {
|
||||
// static_assert in else workaround
|
||||
[] <bool flag = false>() {
|
||||
[]<bool flag = false>() {
|
||||
static_assert(flag, "Unsupported type");
|
||||
}();
|
||||
}
|
||||
();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,30 +1,30 @@
|
|||
#ifndef __RECOMP_OVERLAYS_H__
|
||||
#define __RECOMP_OVERLAYS_H__
|
||||
|
||||
#include <cstdint>
|
||||
#include "sections.h"
|
||||
#include <cstdint>
|
||||
|
||||
namespace recomp {
|
||||
namespace overlays {
|
||||
struct overlay_section_table_data_t {
|
||||
SectionTableEntry* code_sections;
|
||||
SectionTableEntry *code_sections;
|
||||
size_t num_code_sections;
|
||||
size_t total_num_sections;
|
||||
};
|
||||
|
||||
struct overlays_by_index_t {
|
||||
int* table;
|
||||
int *table;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
void register_overlays(const overlay_section_table_data_t& sections, const overlays_by_index_t& overlays);
|
||||
|
||||
void register_patches(const char* patch_data, std::size_t patch_size, SectionTableEntry* code_sections);
|
||||
void read_patch_data(uint8_t* rdram, gpr patch_data_address);
|
||||
void register_patches(const char *patch_data, std::size_t patch_size, SectionTableEntry *code_sections);
|
||||
void read_patch_data(uint8_t *rdram, gpr patch_data_address);
|
||||
|
||||
void init_overlays();
|
||||
}
|
||||
};
|
||||
} // namespace overlays
|
||||
}; // namespace recomp
|
||||
|
||||
extern "C" void load_overlays(uint32_t rom, int32_t ram_addr, uint32_t size);
|
||||
extern "C" void unload_overlays(int32_t ram_addr, uint32_t size);
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
|
||||
#include <cstdio>
|
||||
|
||||
#include "rsp_vu.hpp"
|
||||
#include "recomp.h"
|
||||
#include "rsp_vu.hpp"
|
||||
#include "ultramodern/ultra64.h"
|
||||
|
||||
// TODO: Move these to recomp namespace?
|
||||
|
|
@ -17,36 +17,34 @@ enum class RspExitReason {
|
|||
Unsupported
|
||||
};
|
||||
|
||||
using RspUcodeFunc = RspExitReason(uint8_t* rdram);
|
||||
using RspUcodeFunc = RspExitReason(uint8_t *rdram);
|
||||
|
||||
extern uint8_t dmem[];
|
||||
extern uint16_t rspReciprocals[512];
|
||||
extern uint16_t rspInverseSquareRoots[512];
|
||||
|
||||
#define RSP_MEM_B(offset, addr) \
|
||||
(*reinterpret_cast<int8_t*>(dmem + (0xFFF & (((offset) + (addr)) ^ 3))))
|
||||
#define RSP_MEM_B(offset, addr) (*reinterpret_cast<int8_t *>(dmem + (0xFFF & (((offset) + (addr)) ^ 3))))
|
||||
|
||||
#define RSP_MEM_BU(offset, addr) \
|
||||
(*reinterpret_cast<uint8_t*>(dmem + (0xFFF & (((offset) + (addr)) ^ 3))))
|
||||
#define RSP_MEM_BU(offset, addr) (*reinterpret_cast<uint8_t *>(dmem + (0xFFF & (((offset) + (addr)) ^ 3))))
|
||||
|
||||
static inline uint32_t RSP_MEM_W_LOAD(uint32_t offset, uint32_t addr) {
|
||||
uint32_t out;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
reinterpret_cast<uint8_t*>(&out)[i ^ 3] = RSP_MEM_BU(offset + i, addr);
|
||||
reinterpret_cast<uint8_t *>(&out)[i ^ 3] = RSP_MEM_BU(offset + i, addr);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
static inline void RSP_MEM_W_STORE(uint32_t offset, uint32_t addr, uint32_t val) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
RSP_MEM_BU(offset + i, addr) = reinterpret_cast<uint8_t*>(&val)[i ^ 3];
|
||||
RSP_MEM_BU(offset + i, addr) = reinterpret_cast<uint8_t *>(&val)[i ^ 3];
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint32_t RSP_MEM_HU_LOAD(uint32_t offset, uint32_t addr) {
|
||||
uint16_t out;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
reinterpret_cast<uint8_t*>(&out)[(i + 2) ^ 3] = RSP_MEM_BU(offset + i, addr);
|
||||
reinterpret_cast<uint8_t *>(&out)[(i + 2) ^ 3] = RSP_MEM_BU(offset + i, addr);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
|
@ -54,32 +52,29 @@ static inline uint32_t RSP_MEM_HU_LOAD(uint32_t offset, uint32_t addr) {
|
|||
static inline uint32_t RSP_MEM_H_LOAD(uint32_t offset, uint32_t addr) {
|
||||
int16_t out;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
reinterpret_cast<uint8_t*>(&out)[(i + 2) ^ 3] = RSP_MEM_BU(offset + i, addr);
|
||||
reinterpret_cast<uint8_t *>(&out)[(i + 2) ^ 3] = RSP_MEM_BU(offset + i, addr);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
static inline void RSP_MEM_H_STORE(uint32_t offset, uint32_t addr, uint32_t val) {
|
||||
for (int i = 0; i < 2; i++) {
|
||||
RSP_MEM_BU(offset + i, addr) = reinterpret_cast<uint8_t*>(&val)[(i + 2) ^ 3];
|
||||
RSP_MEM_BU(offset + i, addr) = reinterpret_cast<uint8_t *>(&val)[(i + 2) ^ 3];
|
||||
}
|
||||
}
|
||||
|
||||
#define RSP_ADD32(a, b) \
|
||||
((int32_t)((a) + (b)))
|
||||
#define RSP_ADD32(a, b) ((int32_t)((a) + (b)))
|
||||
|
||||
#define RSP_SUB32(a, b) \
|
||||
((int32_t)((a) - (b)))
|
||||
#define RSP_SUB32(a, b) ((int32_t)((a) - (b)))
|
||||
|
||||
#define RSP_SIGNED(val) \
|
||||
((int32_t)(val))
|
||||
#define RSP_SIGNED(val) ((int32_t)(val))
|
||||
|
||||
#define SET_DMA_DMEM(dmem_addr) dma_dmem_address = (dmem_addr)
|
||||
#define SET_DMA_DRAM(dram_addr) dma_dram_address = (dram_addr)
|
||||
#define DO_DMA_READ(rd_len) dma_rdram_to_dmem(rdram, dma_dmem_address, dma_dram_address, (rd_len))
|
||||
#define DO_DMA_WRITE(wr_len) dma_dmem_to_rdram(rdram, dma_dmem_address, dma_dram_address, (wr_len))
|
||||
|
||||
static inline void dma_rdram_to_dmem(uint8_t* rdram, uint32_t dmem_addr, uint32_t dram_addr, uint32_t rd_len) {
|
||||
static inline void dma_rdram_to_dmem(uint8_t *rdram, uint32_t dmem_addr, uint32_t dram_addr, uint32_t rd_len) {
|
||||
rd_len += 1; // Read length is inclusive
|
||||
dram_addr &= 0xFFFFF8;
|
||||
assert(dmem_addr + rd_len <= 0x1000);
|
||||
|
|
@ -88,7 +83,7 @@ static inline void dma_rdram_to_dmem(uint8_t* rdram, uint32_t dmem_addr, uint32_
|
|||
}
|
||||
}
|
||||
|
||||
static inline void dma_dmem_to_rdram(uint8_t* rdram, uint32_t dmem_addr, uint32_t dram_addr, uint32_t wr_len) {
|
||||
static inline void dma_dmem_to_rdram(uint8_t *rdram, uint32_t dmem_addr, uint32_t dram_addr, uint32_t wr_len) {
|
||||
wr_len += 1; // Write length is inclusive
|
||||
dram_addr &= 0xFFFFF8;
|
||||
assert(dmem_addr + wr_len <= 0x1000);
|
||||
|
|
@ -100,24 +95,26 @@ static inline void dma_dmem_to_rdram(uint8_t* rdram, uint32_t dmem_addr, uint32_
|
|||
namespace recomp {
|
||||
namespace rsp {
|
||||
struct callbacks_t {
|
||||
using get_rsp_microcode_t = RspUcodeFunc*(const OSTask* task);
|
||||
using get_rsp_microcode_t = RspUcodeFunc *(const OSTask *task);
|
||||
|
||||
/**
|
||||
* Return a function pointer to the corresponding RSP microcode function for the given `task_type`.
|
||||
*
|
||||
* The full OSTask (`task` parameter) is passed in case the `task_type` number is not enough information to distinguish out the exact microcode function.
|
||||
* The full OSTask (`task` parameter) is passed in case the `task_type` number is not enough information to distinguish out the
|
||||
* exact microcode function.
|
||||
*
|
||||
* This function is allowed to return `nullptr` if no microcode matches the specified task. In this case a message will be printed to stderr and the program will exit.
|
||||
* This function is allowed to return `nullptr` if no microcode matches the specified task. In this case a message will be
|
||||
* printed to stderr and the program will exit.
|
||||
*/
|
||||
get_rsp_microcode_t* get_rsp_microcode;
|
||||
get_rsp_microcode_t *get_rsp_microcode;
|
||||
};
|
||||
|
||||
void set_callbacks(const callbacks_t& callbacks);
|
||||
|
||||
void constants_init();
|
||||
|
||||
bool run_task(uint8_t* rdram, const OSTask* task);
|
||||
}
|
||||
}
|
||||
bool run_task(uint8_t *rdram, const OSTask *task);
|
||||
} // namespace rsp
|
||||
} // namespace recomp
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -2,12 +2,13 @@
|
|||
#define __SECTIONS_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "recomp.h"
|
||||
|
||||
#define ARRLEN(x) (sizeof(x) / sizeof((x)[0]))
|
||||
|
||||
typedef struct {
|
||||
recomp_func_t* func;
|
||||
recomp_func_t *func;
|
||||
uint32_t offset;
|
||||
} FuncEntry;
|
||||
|
||||
|
|
|
|||
|
|
@ -6,24 +6,24 @@
|
|||
|
||||
#define VI_NTSC_CLOCK 48681812
|
||||
|
||||
extern "C" void osAiSetFrequency_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
extern "C" void osAiSetFrequency_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
uint32_t freq = ctx->r4;
|
||||
// This makes actual audio frequency more accurate to console, but may not be desirable
|
||||
//uint32_t dacRate = (uint32_t)(((float)VI_NTSC_CLOCK / freq) + 0.5f);
|
||||
//freq = VI_NTSC_CLOCK / dacRate;
|
||||
// uint32_t dacRate = (uint32_t)(((float)VI_NTSC_CLOCK / freq) + 0.5f);
|
||||
// freq = VI_NTSC_CLOCK / dacRate;
|
||||
ctx->r2 = freq;
|
||||
ultramodern::set_audio_frequency(freq);
|
||||
}
|
||||
|
||||
extern "C" void osAiSetNextBuffer_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
extern "C" void osAiSetNextBuffer_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
ultramodern::queue_audio_buffer(rdram, ctx->r4, ctx->r5);
|
||||
ctx->r2 = 0;
|
||||
}
|
||||
|
||||
extern "C" void osAiGetLength_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
extern "C" void osAiGetLength_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
ctx->r2 = ultramodern::get_remaining_audio_bytes();
|
||||
}
|
||||
|
||||
extern "C" void osAiGetStatus_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
extern "C" void osAiGetStatus_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
ctx->r2 = 0x00000000; // Pretend the audio DMAs finish instantly
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,15 +4,15 @@
|
|||
|
||||
#define MAXCONTROLLERS 4
|
||||
|
||||
extern "C" void recomp_set_current_frame_poll_id(uint8_t* rdram, recomp_context* ctx) {
|
||||
extern "C" void recomp_set_current_frame_poll_id(uint8_t *rdram, recomp_context *ctx) {
|
||||
// TODO reimplement the system for tagging polls with IDs to handle games with multithreaded input polling.
|
||||
}
|
||||
|
||||
extern "C" void recomp_measure_latency(uint8_t* rdram, recomp_context* ctx) {
|
||||
extern "C" void recomp_measure_latency(uint8_t *rdram, recomp_context *ctx) {
|
||||
ultramodern::measure_input_latency();
|
||||
}
|
||||
|
||||
extern "C" void osContInit_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
extern "C" void osContInit_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
PTR(OSMesgQueue) mq = _arg<0, PTR(OSMesgQueue)>(rdram, ctx);
|
||||
PTR(u8) bitpattern = _arg<1, PTR(u8)>(rdram, ctx);
|
||||
PTR(OSContStatus) data = _arg<2, PTR(OSContStatus)>(rdram, ctx);
|
||||
|
|
@ -22,7 +22,7 @@ extern "C" void osContInit_recomp(uint8_t* rdram, recomp_context* ctx) {
|
|||
_return<s32>(ctx, ret);
|
||||
}
|
||||
|
||||
extern "C" void osContReset_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
extern "C" void osContReset_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
PTR(OSMesgQueue) mq = _arg<0, PTR(OSMesgQueue)>(rdram, ctx);
|
||||
PTR(OSContStatus) data = _arg<1, PTR(OSContStatus)>(rdram, ctx);
|
||||
|
||||
|
|
@ -31,7 +31,7 @@ extern "C" void osContReset_recomp(uint8_t* rdram, recomp_context* ctx) {
|
|||
_return<s32>(ctx, ret);
|
||||
}
|
||||
|
||||
extern "C" void osContStartReadData_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
extern "C" void osContStartReadData_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
PTR(OSMesgQueue) mq = _arg<0, PTR(OSMesgQueue)>(rdram, ctx);
|
||||
|
||||
s32 ret = osContStartReadData(PASS_RDRAM mq);
|
||||
|
|
@ -39,7 +39,7 @@ extern "C" void osContStartReadData_recomp(uint8_t* rdram, recomp_context* ctx)
|
|||
_return<s32>(ctx, ret);
|
||||
}
|
||||
|
||||
extern "C" void osContGetReadData_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
extern "C" void osContGetReadData_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
PTR(OSContPad) data = _arg<0, PTR(OSContPad)>(rdram, ctx);
|
||||
|
||||
OSContPad dummy_data[MAXCONTROLLERS];
|
||||
|
|
@ -54,7 +54,7 @@ extern "C" void osContGetReadData_recomp(uint8_t* rdram, recomp_context* ctx) {
|
|||
}
|
||||
}
|
||||
|
||||
extern "C" void osContStartQuery_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void osContStartQuery_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
PTR(OSMesgQueue) mq = _arg<0, PTR(OSMesgQueue)>(rdram, ctx);
|
||||
|
||||
s32 ret = osContStartQuery(PASS_RDRAM mq);
|
||||
|
|
@ -62,13 +62,13 @@ extern "C" void osContStartQuery_recomp(uint8_t * rdram, recomp_context * ctx) {
|
|||
_return<s32>(ctx, ret);
|
||||
}
|
||||
|
||||
extern "C" void osContGetQuery_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void osContGetQuery_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
PTR(OSContStatus) data = _arg<0, PTR(OSContStatus)>(rdram, ctx);
|
||||
|
||||
osContGetQuery(PASS_RDRAM data);
|
||||
}
|
||||
|
||||
extern "C" void osContSetCh_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
extern "C" void osContSetCh_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
u8 ch = _arg<0, u8>(rdram, ctx);
|
||||
|
||||
s32 ret = osContSetCh(PASS_RDRAM ch);
|
||||
|
|
@ -76,7 +76,7 @@ extern "C" void osContSetCh_recomp(uint8_t* rdram, recomp_context* ctx) {
|
|||
_return<s32>(ctx, ret);
|
||||
}
|
||||
|
||||
extern "C" void __osMotorAccess_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
extern "C" void __osMotorAccess_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
PTR(OSPfs) pfs = _arg<0, PTR(OSPfs)>(rdram, ctx);
|
||||
s32 flag = _arg<1, s32>(rdram, ctx);
|
||||
|
||||
|
|
@ -85,7 +85,7 @@ extern "C" void __osMotorAccess_recomp(uint8_t* rdram, recomp_context* ctx) {
|
|||
_return<s32>(ctx, ret);
|
||||
}
|
||||
|
||||
extern "C" void osMotorInit_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
extern "C" void osMotorInit_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
PTR(OSMesgQueue) mq = _arg<0, PTR(OSMesgQueue)>(rdram, ctx);
|
||||
PTR(OSPfs) pfs = _arg<1, PTR(OSPfs)>(rdram, ctx);
|
||||
int channel = _arg<2, s32>(rdram, ctx);
|
||||
|
|
@ -95,7 +95,7 @@ extern "C" void osMotorInit_recomp(uint8_t* rdram, recomp_context* ctx) {
|
|||
_return<s32>(ctx, ret);
|
||||
}
|
||||
|
||||
extern "C" void osMotorStart_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
extern "C" void osMotorStart_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
PTR(OSPfs) pfs = _arg<0, PTR(OSPfs)>(rdram, ctx);
|
||||
|
||||
s32 ret = osMotorStart(PASS_RDRAM pfs);
|
||||
|
|
@ -103,7 +103,7 @@ extern "C" void osMotorStart_recomp(uint8_t* rdram, recomp_context* ctx) {
|
|||
_return<s32>(ctx, ret);
|
||||
}
|
||||
|
||||
extern "C" void osMotorStop_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
extern "C" void osMotorStop_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
PTR(OSPfs) pfs = _arg<0, PTR(OSPfs)>(rdram, ctx);
|
||||
|
||||
s32 ret = osMotorStop(PASS_RDRAM pfs);
|
||||
|
|
|
|||
|
|
@ -29,15 +29,15 @@ constexpr void update_bit(uint32_t& state, uint32_t flags, RDPStatusBit bit) {
|
|||
|
||||
uint32_t rdp_state = 1 << (int)RDPStatusBit::BufferReady;
|
||||
|
||||
extern "C" void osDpSetNextBuffer_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
extern "C" void osDpSetNextBuffer_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
extern "C" void osDpGetStatus_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
extern "C" void osDpGetStatus_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
ctx->r2 = rdp_state;
|
||||
}
|
||||
|
||||
extern "C" void osDpSetStatus_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
extern "C" void osDpSetStatus_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
update_bit(rdp_state, ctx->r4, RDPStatusBit::XbusDmem);
|
||||
update_bit(rdp_state, ctx->r4, RDPStatusBit::Freeze);
|
||||
update_bit(rdp_state, ctx->r4, RDPStatusBit::Flush);
|
||||
|
|
|
|||
|
|
@ -11,15 +11,15 @@ constexpr int eep4_block_count = eep4_size / eeprom_block_size;
|
|||
constexpr int eep16_size = 16384;
|
||||
constexpr int eep16_block_count = eep16_size / eeprom_block_size;
|
||||
|
||||
extern "C" void osEepromProbe_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
extern "C" void osEepromProbe_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
ctx->r2 = 0x02; // EEP16K
|
||||
}
|
||||
|
||||
extern "C" void osEepromWrite_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
assert(false);// ctx->r2 = 8; // CONT_NO_RESPONSE_ERROR
|
||||
extern "C" void osEepromWrite_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
assert(false); // ctx->r2 = 8; // CONT_NO_RESPONSE_ERROR
|
||||
}
|
||||
|
||||
extern "C" void osEepromLongWrite_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
extern "C" void osEepromLongWrite_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
uint8_t eep_address = ctx->r5;
|
||||
gpr buffer = ctx->r6;
|
||||
int32_t nbytes = ctx->r7;
|
||||
|
|
@ -32,11 +32,11 @@ extern "C" void osEepromLongWrite_recomp(uint8_t* rdram, recomp_context* ctx) {
|
|||
ctx->r2 = 0;
|
||||
}
|
||||
|
||||
extern "C" void osEepromRead_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
assert(false);// ctx->r2 = 8; // CONT_NO_RESPONSE_ERROR
|
||||
extern "C" void osEepromRead_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
assert(false); // ctx->r2 = 8; // CONT_NO_RESPONSE_ERROR
|
||||
}
|
||||
|
||||
extern "C" void osEepromLongRead_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
extern "C" void osEepromLongRead_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
uint8_t eep_address = ctx->r5;
|
||||
gpr buffer = ctx->r6;
|
||||
int32_t nbytes = ctx->r7;
|
||||
|
|
|
|||
|
|
@ -4,13 +4,13 @@ constexpr std::u8string_view backup_suffix = u8".bak";
|
|||
constexpr std::u8string_view temp_suffix = u8".temp";
|
||||
|
||||
std::ifstream recomp::open_input_backup_file(const std::filesystem::path& filepath, std::ios_base::openmode mode) {
|
||||
std::filesystem::path backup_path{filepath};
|
||||
std::filesystem::path backup_path{ filepath };
|
||||
backup_path += backup_suffix;
|
||||
return std::ifstream{backup_path, mode};
|
||||
return std::ifstream{ backup_path, mode };
|
||||
}
|
||||
|
||||
std::ifstream recomp::open_input_file_with_backup(const std::filesystem::path& filepath, std::ios_base::openmode mode) {
|
||||
std::ifstream ret{filepath, mode};
|
||||
std::ifstream ret{ filepath, mode };
|
||||
|
||||
// Check if the file failed to open and open the corresponding backup file instead if so.
|
||||
if (!ret.good()) {
|
||||
|
|
@ -21,7 +21,7 @@ std::ifstream recomp::open_input_file_with_backup(const std::filesystem::path& f
|
|||
}
|
||||
|
||||
std::ofstream recomp::open_output_file_with_backup(const std::filesystem::path& filepath, std::ios_base::openmode mode) {
|
||||
std::filesystem::path temp_path{filepath};
|
||||
std::filesystem::path temp_path{ filepath };
|
||||
temp_path += temp_suffix;
|
||||
std::ofstream temp_file_out{ temp_path, mode };
|
||||
|
||||
|
|
@ -29,10 +29,10 @@ std::ofstream recomp::open_output_file_with_backup(const std::filesystem::path&
|
|||
}
|
||||
|
||||
bool recomp::finalize_output_file_with_backup(const std::filesystem::path& filepath) {
|
||||
std::filesystem::path backup_path{filepath};
|
||||
std::filesystem::path backup_path{ filepath };
|
||||
backup_path += backup_suffix;
|
||||
|
||||
std::filesystem::path temp_path{filepath};
|
||||
std::filesystem::path temp_path{ filepath };
|
||||
temp_path += temp_suffix;
|
||||
|
||||
std::error_code ec;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
#include <array>
|
||||
#include <cassert>
|
||||
|
||||
#include <ultramodern/ultra64.h>
|
||||
#include <ultramodern/ultramodern.hpp>
|
||||
|
||||
#include "recomp.h"
|
||||
|
||||
// TODO move this out into ultramodern code
|
||||
|
|
@ -13,24 +15,24 @@ constexpr uint32_t page_count = flash_size / page_size;
|
|||
constexpr uint32_t sector_size = page_size * pages_per_sector;
|
||||
constexpr uint32_t sector_count = flash_size / sector_size;
|
||||
|
||||
void save_write_ptr(const void* in, uint32_t offset, uint32_t count);
|
||||
void save_write_ptr(const void *in, uint32_t offset, uint32_t count);
|
||||
void save_write(RDRAM_ARG PTR(void) rdram_address, uint32_t offset, uint32_t count);
|
||||
void save_read(RDRAM_ARG PTR(void) rdram_address, uint32_t offset, uint32_t count);
|
||||
void save_clear(uint32_t start, uint32_t size, char value);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
extern "C" void osFlashReadStatus_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void osFlashReadStatus_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
PTR(u8) flash_status = ctx->r4;
|
||||
|
||||
MEM_B(0, flash_status) = 0;
|
||||
}
|
||||
|
||||
extern "C" void osFlashReadId_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void osFlashReadId_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
PTR(u32) flash_type = ctx->r4;
|
||||
PTR(u32) flash_maker = ctx->r5;
|
||||
|
||||
|
|
@ -39,24 +41,23 @@ extern "C" void osFlashReadId_recomp(uint8_t * rdram, recomp_context * ctx) {
|
|||
MEM_W(0, flash_maker) = 0x00C2001E;
|
||||
}
|
||||
|
||||
extern "C" void osFlashClearStatus_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
|
||||
extern "C" void osFlashClearStatus_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
}
|
||||
|
||||
extern "C" void osFlashAllErase_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void osFlashAllErase_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
save_clear(0, ultramodern::save_size, 0xFF);
|
||||
|
||||
ctx->r2 = 0;
|
||||
}
|
||||
|
||||
extern "C" void osFlashAllEraseThrough_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void osFlashAllEraseThrough_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
save_clear(0, ultramodern::save_size, 0xFF);
|
||||
|
||||
ctx->r2 = 0;
|
||||
}
|
||||
|
||||
// This function is named sector but really means page.
|
||||
extern "C" void osFlashSectorErase_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void osFlashSectorErase_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
uint32_t page_num = (uint32_t)ctx->r4;
|
||||
|
||||
// Prevent out of bounds erase
|
||||
|
|
@ -71,7 +72,7 @@ extern "C" void osFlashSectorErase_recomp(uint8_t * rdram, recomp_context * ctx)
|
|||
}
|
||||
|
||||
// Same naming issue as above.
|
||||
extern "C" void osFlashSectorEraseThrough_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void osFlashSectorEraseThrough_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
uint32_t page_num = (uint32_t)ctx->r4;
|
||||
|
||||
// Prevent out of bounds erase
|
||||
|
|
@ -85,17 +86,17 @@ extern "C" void osFlashSectorEraseThrough_recomp(uint8_t * rdram, recomp_context
|
|||
ctx->r2 = 0;
|
||||
}
|
||||
|
||||
extern "C" void osFlashCheckEraseEnd_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void osFlashCheckEraseEnd_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
// All erases are blocking in this implementation, so this should always return OK.
|
||||
ctx->r2 = 0; // FLASH_STATUS_ERASE_OK
|
||||
}
|
||||
|
||||
extern "C" void osFlashWriteBuffer_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
OSIoMesg* mb = TO_PTR(OSIoMesg, ctx->r4);
|
||||
extern "C" void osFlashWriteBuffer_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
OSIoMesg *mb = TO_PTR(OSIoMesg, ctx->r4);
|
||||
int32_t pri = ctx->r5;
|
||||
PTR(void) dramAddr = ctx->r6;
|
||||
PTR(OSMesgQueue) mq = ctx->r7;
|
||||
|
||||
|
||||
// Copy the input data into the write buffer
|
||||
for (size_t i = 0; i < page_size; i++) {
|
||||
write_buffer[i] = MEM_B(i, dramAddr);
|
||||
|
|
@ -107,7 +108,7 @@ extern "C" void osFlashWriteBuffer_recomp(uint8_t * rdram, recomp_context * ctx)
|
|||
ctx->r2 = 0;
|
||||
}
|
||||
|
||||
extern "C" void osFlashWriteArray_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void osFlashWriteArray_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
uint32_t page_num = ctx->r4;
|
||||
|
||||
// Copy the write buffer into the save file
|
||||
|
|
@ -116,8 +117,8 @@ extern "C" void osFlashWriteArray_recomp(uint8_t * rdram, recomp_context * ctx)
|
|||
ctx->r2 = 0;
|
||||
}
|
||||
|
||||
extern "C" void osFlashReadArray_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
OSIoMesg* mb = TO_PTR(OSIoMesg, ctx->r4);
|
||||
extern "C" void osFlashReadArray_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
OSIoMesg *mb = TO_PTR(OSIoMesg, ctx->r4);
|
||||
int32_t pri = ctx->r5;
|
||||
uint32_t page_num = ctx->r6;
|
||||
PTR(void) dramAddr = ctx->r7;
|
||||
|
|
@ -136,6 +137,6 @@ extern "C" void osFlashReadArray_recomp(uint8_t * rdram, recomp_context * ctx) {
|
|||
ctx->r2 = 0;
|
||||
}
|
||||
|
||||
extern "C" void osFlashChange_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void osFlashChange_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
assert(false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
#include <ultramodern/ultramodern.hpp>
|
||||
|
||||
#include "recomp.h"
|
||||
|
||||
// TODO remove these by implementing the necessary instructions and control flow handling in the recompiler.
|
||||
// This has already been partially completed.
|
||||
|
||||
extern "C" void __udivdi3_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void __udivdi3_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
uint64_t a = (ctx->r4 << 32) | ((ctx->r5 << 0) & 0xFFFFFFFFu);
|
||||
uint64_t b = (ctx->r6 << 32) | ((ctx->r7 << 0) & 0xFFFFFFFFu);
|
||||
uint64_t ret = a / b;
|
||||
|
|
@ -13,7 +14,7 @@ extern "C" void __udivdi3_recomp(uint8_t * rdram, recomp_context * ctx) {
|
|||
ctx->r3 = (int32_t)(ret >> 0);
|
||||
}
|
||||
|
||||
extern "C" void __divdi3_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void __divdi3_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
int64_t a = (ctx->r4 << 32) | ((ctx->r5 << 0) & 0xFFFFFFFFu);
|
||||
int64_t b = (ctx->r6 << 32) | ((ctx->r7 << 0) & 0xFFFFFFFFu);
|
||||
int64_t ret = a / b;
|
||||
|
|
@ -22,7 +23,7 @@ extern "C" void __divdi3_recomp(uint8_t * rdram, recomp_context * ctx) {
|
|||
ctx->r3 = (int32_t)(ret >> 0);
|
||||
}
|
||||
|
||||
extern "C" void __umoddi3_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void __umoddi3_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
uint64_t a = (ctx->r4 << 32) | ((ctx->r5 << 0) & 0xFFFFFFFFu);
|
||||
uint64_t b = (ctx->r6 << 32) | ((ctx->r7 << 0) & 0xFFFFFFFFu);
|
||||
uint64_t ret = a % b;
|
||||
|
|
@ -31,7 +32,7 @@ extern "C" void __umoddi3_recomp(uint8_t * rdram, recomp_context * ctx) {
|
|||
ctx->r3 = (int32_t)(ret >> 0);
|
||||
}
|
||||
|
||||
extern "C" void __ull_div_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void __ull_div_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
uint64_t a = (ctx->r4 << 32) | ((ctx->r5 << 0) & 0xFFFFFFFFu);
|
||||
uint64_t b = (ctx->r6 << 32) | ((ctx->r7 << 0) & 0xFFFFFFFFu);
|
||||
uint64_t ret = a / b;
|
||||
|
|
@ -40,7 +41,7 @@ extern "C" void __ull_div_recomp(uint8_t * rdram, recomp_context * ctx) {
|
|||
ctx->r3 = (int32_t)(ret >> 0);
|
||||
}
|
||||
|
||||
extern "C" void __ll_div_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void __ll_div_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
int64_t a = (ctx->r4 << 32) | ((ctx->r5 << 0) & 0xFFFFFFFFu);
|
||||
int64_t b = (ctx->r6 << 32) | ((ctx->r7 << 0) & 0xFFFFFFFFu);
|
||||
int64_t ret = a / b;
|
||||
|
|
@ -49,7 +50,7 @@ extern "C" void __ll_div_recomp(uint8_t * rdram, recomp_context * ctx) {
|
|||
ctx->r3 = (int32_t)(ret >> 0);
|
||||
}
|
||||
|
||||
extern "C" void __ll_mul_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void __ll_mul_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
uint64_t a = (ctx->r4 << 32) | ((ctx->r5 << 0) & 0xFFFFFFFFu);
|
||||
uint64_t b = (ctx->r6 << 32) | ((ctx->r7 << 0) & 0xFFFFFFFFu);
|
||||
uint64_t ret = a * b;
|
||||
|
|
@ -58,7 +59,7 @@ extern "C" void __ll_mul_recomp(uint8_t * rdram, recomp_context * ctx) {
|
|||
ctx->r3 = (int32_t)(ret >> 0);
|
||||
}
|
||||
|
||||
extern "C" void __ull_rem_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void __ull_rem_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
uint64_t a = (ctx->r4 << 32) | ((ctx->r5 << 0) & 0xFFFFFFFFu);
|
||||
uint64_t b = (ctx->r6 << 32) | ((ctx->r7 << 0) & 0xFFFFFFFFu);
|
||||
uint64_t ret = a % b;
|
||||
|
|
@ -67,14 +68,14 @@ extern "C" void __ull_rem_recomp(uint8_t * rdram, recomp_context * ctx) {
|
|||
ctx->r3 = (int32_t)(ret >> 0);
|
||||
}
|
||||
|
||||
extern "C" void __ull_to_d_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void __ull_to_d_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
uint64_t a = (ctx->r4 << 32) | ((ctx->r5 << 0) & 0xFFFFFFFFu);
|
||||
double ret = (double)a;
|
||||
|
||||
ctx->f0.d = ret;
|
||||
}
|
||||
|
||||
extern "C" void __ull_to_f_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void __ull_to_f_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
uint64_t a = (ctx->r4 << 32) | ((ctx->r5 << 0) & 0xFFFFFFFFu);
|
||||
float ret = (float)a;
|
||||
|
||||
|
|
|
|||
|
|
@ -7,14 +7,14 @@
|
|||
|
||||
#include "ultramodern/ultramodern.hpp"
|
||||
|
||||
#include "recomp.h"
|
||||
#include "overlays.hpp"
|
||||
#include "recomp.h"
|
||||
#include "sections.h"
|
||||
|
||||
static recomp::overlays::overlay_section_table_data_t sections_info {};
|
||||
static recomp::overlays::overlays_by_index_t overlays_info {};
|
||||
static recomp::overlays::overlay_section_table_data_t sections_info{};
|
||||
static recomp::overlays::overlays_by_index_t overlays_info{};
|
||||
|
||||
static SectionTableEntry* patch_code_sections = nullptr;
|
||||
static SectionTableEntry *patch_code_sections = nullptr;
|
||||
static std::vector<char> patch_data;
|
||||
|
||||
void recomp::overlays::register_overlays(const overlay_section_table_data_t& sections, const overlays_by_index_t& overlays) {
|
||||
|
|
@ -22,7 +22,7 @@ void recomp::overlays::register_overlays(const overlay_section_table_data_t& sec
|
|||
overlays_info = overlays;
|
||||
}
|
||||
|
||||
void recomp::overlays::register_patches(const char* patch, std::size_t size, SectionTableEntry* sections) {
|
||||
void recomp::overlays::register_patches(const char *patch, std::size_t size, SectionTableEntry *sections) {
|
||||
patch_code_sections = sections;
|
||||
|
||||
patch_data.resize(size);
|
||||
|
|
@ -44,7 +44,7 @@ struct LoadedSection {
|
|||
};
|
||||
|
||||
std::vector<LoadedSection> loaded_sections{};
|
||||
std::unordered_map<int32_t, recomp_func_t*> func_map{};
|
||||
std::unordered_map<int32_t, recomp_func_t *> func_map{};
|
||||
|
||||
void load_overlay(size_t section_table_index, int32_t ram) {
|
||||
const SectionTableEntry& section = sections_info.code_sections[section_table_index];
|
||||
|
|
@ -73,29 +73,29 @@ static void load_patch_functions() {
|
|||
load_special_overlay(patch_code_sections[0], patch_code_sections[0].ram_addr);
|
||||
}
|
||||
|
||||
void recomp::overlays::read_patch_data(uint8_t* rdram, gpr patch_data_address) {
|
||||
void recomp::overlays::read_patch_data(uint8_t *rdram, gpr patch_data_address) {
|
||||
for (size_t i = 0; i < patch_data.size(); i++) {
|
||||
MEM_B(i, patch_data_address) = patch_data[i];
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
int32_t* section_addresses = nullptr;
|
||||
int32_t *section_addresses = nullptr;
|
||||
}
|
||||
|
||||
extern "C" void load_overlays(uint32_t rom, int32_t ram_addr, uint32_t size) {
|
||||
// Search for the first section that's included in the loaded rom range
|
||||
// Sections were sorted by `init_overlays` so we can use the bounds functions
|
||||
auto lower = std::lower_bound(§ions_info.code_sections[0], §ions_info.code_sections[sections_info.num_code_sections], rom,
|
||||
auto lower = std::lower_bound(
|
||||
§ions_info.code_sections[0], §ions_info.code_sections[sections_info.num_code_sections], rom,
|
||||
[](const SectionTableEntry& entry, uint32_t addr) {
|
||||
return entry.rom_addr < addr;
|
||||
}
|
||||
);
|
||||
auto upper = std::upper_bound(§ions_info.code_sections[0], §ions_info.code_sections[sections_info.num_code_sections], (uint32_t)(rom + size),
|
||||
});
|
||||
auto upper = std::upper_bound(
|
||||
§ions_info.code_sections[0], §ions_info.code_sections[sections_info.num_code_sections], (uint32_t)(rom + size),
|
||||
[](uint32_t addr, const SectionTableEntry& entry) {
|
||||
return addr < entry.size + entry.rom_addr;
|
||||
}
|
||||
);
|
||||
});
|
||||
// Load the overlays that were found
|
||||
for (auto it = lower; it != upper; ++it) {
|
||||
load_overlay(std::distance(§ions_info.code_sections[0], it), it->rom_addr - rom + ram_addr);
|
||||
|
|
@ -106,7 +106,9 @@ extern "C" void unload_overlay_by_id(uint32_t id) {
|
|||
uint32_t section_table_index = overlays_info.table[id];
|
||||
const SectionTableEntry& section = sections_info.code_sections[section_table_index];
|
||||
|
||||
auto find_it = std::find_if(loaded_sections.begin(), loaded_sections.end(), [section_table_index](const LoadedSection& s) { return s.section_table_index == section_table_index; });
|
||||
auto find_it = std::find_if(loaded_sections.begin(), loaded_sections.end(), [section_table_index](const LoadedSection& s) {
|
||||
return s.section_table_index == section_table_index;
|
||||
});
|
||||
|
||||
if (find_it != loaded_sections.end()) {
|
||||
// Determine where each function was loaded to and remove that entry from the function map
|
||||
|
|
@ -144,11 +146,12 @@ extern "C" void unload_overlays(int32_t ram_addr, uint32_t size) {
|
|||
if (ram_addr < (it->loaded_ram_addr + section.size) && (ram_addr + size) >= it->loaded_ram_addr) {
|
||||
// Check if the section isn't entirely in the loaded region
|
||||
if (ram_addr > it->loaded_ram_addr || (ram_addr + size) < (it->loaded_ram_addr + section.size)) {
|
||||
fprintf(stderr,
|
||||
fprintf(
|
||||
stderr,
|
||||
"Cannot partially unload section\n"
|
||||
" rom: 0x%08X size: 0x%08X loaded_addr: 0x%08X\n"
|
||||
" unloaded_ram: 0x%08X unloaded_size : 0x%08X\n",
|
||||
section.rom_addr, section.size, it->loaded_ram_addr, ram_addr, size);
|
||||
section.rom_addr, section.size, it->loaded_ram_addr, ram_addr, size);
|
||||
assert(false);
|
||||
std::exit(EXIT_FAILURE);
|
||||
}
|
||||
|
|
@ -177,16 +180,16 @@ void recomp::overlays::init_overlays() {
|
|||
}
|
||||
|
||||
// Sort the executable sections by rom address
|
||||
std::sort(§ions_info.code_sections[0], §ions_info.code_sections[sections_info.num_code_sections],
|
||||
std::sort(
|
||||
§ions_info.code_sections[0], §ions_info.code_sections[sections_info.num_code_sections],
|
||||
[](const SectionTableEntry& a, const SectionTableEntry& b) {
|
||||
return a.rom_addr < b.rom_addr;
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
load_patch_functions();
|
||||
}
|
||||
|
||||
extern "C" recomp_func_t * get_function(int32_t addr) {
|
||||
extern "C" recomp_func_t *get_function(int32_t addr) {
|
||||
auto func_find = func_map.find(addr);
|
||||
if (func_find == func_map.end()) {
|
||||
fprintf(stderr, "Failed to find function at 0x%08X\n", addr);
|
||||
|
|
@ -195,4 +198,3 @@ extern "C" recomp_func_t * get_function(int32_t addr) {
|
|||
}
|
||||
return func_find->second;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,34 +2,34 @@
|
|||
#include <ultramodern/ultra64.h>
|
||||
#include <ultramodern/ultramodern.hpp>
|
||||
|
||||
extern "C" void osPfsInitPak_recomp(uint8_t * rdram, recomp_context* ctx) {
|
||||
extern "C" void osPfsInitPak_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
ctx->r2 = 1; // PFS_ERR_NOPACK
|
||||
}
|
||||
|
||||
extern "C" void osPfsFreeBlocks_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void osPfsFreeBlocks_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
ctx->r2 = 1; // PFS_ERR_NOPACK
|
||||
}
|
||||
|
||||
extern "C" void osPfsAllocateFile_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void osPfsAllocateFile_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
ctx->r2 = 1; // PFS_ERR_NOPACK
|
||||
}
|
||||
|
||||
extern "C" void osPfsDeleteFile_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void osPfsDeleteFile_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
ctx->r2 = 1; // PFS_ERR_NOPACK
|
||||
}
|
||||
|
||||
extern "C" void osPfsFileState_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void osPfsFileState_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
ctx->r2 = 1; // PFS_ERR_NOPACK
|
||||
}
|
||||
|
||||
extern "C" void osPfsFindFile_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void osPfsFindFile_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
ctx->r2 = 1; // PFS_ERR_NOPACK
|
||||
}
|
||||
|
||||
extern "C" void osPfsReadWriteFile_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void osPfsReadWriteFile_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
ctx->r2 = 1; // PFS_ERR_NOPACK
|
||||
}
|
||||
|
||||
extern "C" void osPfsChecker_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void osPfsChecker_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
ctx->r2 = 1; // PFS_ERR_NOPACK
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,17 @@
|
|||
#include <memory>
|
||||
#include <fstream>
|
||||
#include <array>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include "recomp.h"
|
||||
#include "game.hpp"
|
||||
#include "files.hpp"
|
||||
#include <string>
|
||||
|
||||
#include <ultramodern/ultra64.h>
|
||||
#include <ultramodern/ultramodern.hpp>
|
||||
|
||||
#include "files.hpp"
|
||||
#include "game.hpp"
|
||||
#include "recomp.h"
|
||||
|
||||
static std::vector<uint8_t> rom;
|
||||
|
||||
bool recomp::is_rom_loaded() {
|
||||
|
|
@ -35,14 +37,14 @@ constexpr uint32_t phys_to_k1(uint32_t addr) {
|
|||
return addr | 0xA0000000;
|
||||
}
|
||||
|
||||
extern "C" void __osPiGetAccess_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
extern "C" void __osPiGetAccess_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
}
|
||||
|
||||
extern "C" void __osPiRelAccess_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
extern "C" void __osPiRelAccess_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);
|
||||
extern "C" void osCartRomInit_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
OSPiHandle *handle = TO_PTR(OSPiHandle, ultramodern::cart_handle);
|
||||
handle->type = 0; // cart
|
||||
handle->baseAddress = phys_to_k1(rom_base);
|
||||
handle->domain = 0;
|
||||
|
|
@ -50,8 +52,8 @@ extern "C" void osCartRomInit_recomp(uint8_t* rdram, recomp_context* ctx) {
|
|||
ctx->r2 = (gpr)ultramodern::cart_handle;
|
||||
}
|
||||
|
||||
extern "C" void osDriveRomInit_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
OSPiHandle* handle = TO_PTR(OSPiHandle, ultramodern::drive_handle);
|
||||
extern "C" void osDriveRomInit_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
OSPiHandle *handle = TO_PTR(OSPiHandle, ultramodern::drive_handle);
|
||||
handle->type = 1; // bulk
|
||||
handle->baseAddress = phys_to_k1(drive_base);
|
||||
handle->domain = 0;
|
||||
|
|
@ -59,28 +61,28 @@ extern "C" void osDriveRomInit_recomp(uint8_t * rdram, recomp_context * ctx) {
|
|||
ctx->r2 = (gpr)ultramodern::drive_handle;
|
||||
}
|
||||
|
||||
extern "C" void osCreatePiManager_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
extern "C" void osCreatePiManager_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
;
|
||||
}
|
||||
|
||||
void recomp::do_rom_read(uint8_t* rdram, gpr ram_address, uint32_t physical_addr, size_t num_bytes) {
|
||||
void recomp::do_rom_read(uint8_t *rdram, gpr ram_address, uint32_t physical_addr, size_t num_bytes) {
|
||||
// TODO use word copies when possible
|
||||
|
||||
// TODO handle misaligned DMA
|
||||
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((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 - rom_base;
|
||||
for (size_t i = 0; i < num_bytes; i++) {
|
||||
MEM_B(i, ram_address) = *rom_addr;
|
||||
rom_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((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 - rom_base;
|
||||
MEM_B(0, ram_address) = *rom_addr++;
|
||||
MEM_B(1, ram_address) = *rom_addr++;
|
||||
MEM_B(2, ram_address) = *rom_addr++;
|
||||
|
|
@ -99,7 +101,7 @@ const std::u8string save_folder = u8"saves";
|
|||
extern std::filesystem::path config_path;
|
||||
|
||||
std::filesystem::path get_save_file_path() {
|
||||
return config_path / save_folder / (std::u8string{recomp::current_game_id()} + u8".bin");
|
||||
return config_path / save_folder / (std::u8string{ recomp::current_game_id() } + u8".bin");
|
||||
}
|
||||
|
||||
void update_save_file() {
|
||||
|
|
@ -119,7 +121,8 @@ void update_save_file() {
|
|||
saving_failed = !recomp::finalize_output_file_with_backup(get_save_file_path());
|
||||
}
|
||||
if (saving_failed) {
|
||||
ultramodern::error_handling::message_box("Failed to write to the save file. Check your file permissions and whether the save folder has been moved to Dropbox or similar, as this can cause issues.");
|
||||
ultramodern::error_handling::message_box("Failed to write to the save file. Check your file permissions and whether the save "
|
||||
"folder has been moved to Dropbox or similar, as this can cause issues.");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -148,18 +151,18 @@ void saving_thread_func(RDRAM_ARG1) {
|
|||
}
|
||||
}
|
||||
|
||||
void save_write_ptr(const void* in, uint32_t offset, uint32_t count) {
|
||||
void save_write_ptr(const void *in, uint32_t offset, uint32_t count) {
|
||||
{
|
||||
std::lock_guard lock { save_context.save_buffer_mutex };
|
||||
std::lock_guard lock{ save_context.save_buffer_mutex };
|
||||
memcpy(&save_context.save_buffer[offset], in, count);
|
||||
}
|
||||
|
||||
|
||||
save_context.write_sempahore.signal();
|
||||
}
|
||||
|
||||
void save_write(RDRAM_ARG PTR(void) rdram_address, uint32_t offset, uint32_t count) {
|
||||
{
|
||||
std::lock_guard lock { save_context.save_buffer_mutex };
|
||||
std::lock_guard lock{ save_context.save_buffer_mutex };
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
save_context.save_buffer[offset + i] = MEM_B(i, rdram_address);
|
||||
}
|
||||
|
|
@ -169,7 +172,7 @@ void save_write(RDRAM_ARG PTR(void) rdram_address, uint32_t offset, uint32_t cou
|
|||
}
|
||||
|
||||
void save_read(RDRAM_ARG PTR(void) rdram_address, uint32_t offset, uint32_t count) {
|
||||
std::lock_guard lock { save_context.save_buffer_mutex };
|
||||
std::lock_guard lock{ save_context.save_buffer_mutex };
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
MEM_B(i, rdram_address) = save_context.save_buffer[offset + i];
|
||||
}
|
||||
|
|
@ -177,7 +180,7 @@ void save_read(RDRAM_ARG PTR(void) rdram_address, uint32_t offset, uint32_t coun
|
|||
|
||||
void save_clear(uint32_t start, uint32_t size, char value) {
|
||||
{
|
||||
std::lock_guard lock { save_context.save_buffer_mutex };
|
||||
std::lock_guard lock{ save_context.save_buffer_mutex };
|
||||
std::fill_n(save_context.save_buffer.begin() + start, size, value);
|
||||
}
|
||||
|
||||
|
|
@ -200,7 +203,7 @@ void ultramodern::init_saving(RDRAM_ARG1) {
|
|||
save_context.save_buffer.fill(0);
|
||||
}
|
||||
|
||||
save_context.saving_thread = std::thread{saving_thread_func, PASS_RDRAM};
|
||||
save_context.saving_thread = std::thread{ saving_thread_func, PASS_RDRAM };
|
||||
}
|
||||
|
||||
void ultramodern::join_saving_thread() {
|
||||
|
|
@ -217,32 +220,37 @@ void do_dma(RDRAM_ARG PTR(OSMesgQueue) mq, gpr rdram_address, uint32_t physical_
|
|||
|
||||
// Send a message to the mq to indicate that the transfer completed
|
||||
osSendMesg(rdram, mq, 0, OS_MESG_NOBLOCK);
|
||||
} else if (physical_addr >= sram_base) {
|
||||
}
|
||||
else if (physical_addr >= sram_base) {
|
||||
// read sram
|
||||
save_read(rdram, rdram_address, physical_addr - sram_base, size);
|
||||
|
||||
// Send a message to the mq to indicate that the transfer completed
|
||||
osSendMesg(rdram, mq, 0, OS_MESG_NOBLOCK);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "[WARN] PI DMA read from unknown region, phys address 0x%08X\n", physical_addr);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
if (physical_addr >= rom_base) {
|
||||
// write cart rom
|
||||
throw std::runtime_error("ROM DMA write unimplemented");
|
||||
} else if (physical_addr >= sram_base) {
|
||||
}
|
||||
else if (physical_addr >= sram_base) {
|
||||
// write sram
|
||||
save_write(rdram, rdram_address, physical_addr - sram_base, size);
|
||||
|
||||
// Send a message to the mq to indicate that the transfer completed
|
||||
osSendMesg(rdram, mq, 0, OS_MESG_NOBLOCK);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "[WARN] PI DMA write to unknown region, phys address 0x%08X\n", physical_addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void osPiStartDma_recomp(RDRAM_ARG recomp_context* ctx) {
|
||||
extern "C" void osPiStartDma_recomp(RDRAM_ARG recomp_context *ctx) {
|
||||
uint32_t mb = ctx->r4;
|
||||
uint32_t pri = ctx->r5;
|
||||
uint32_t direction = ctx->r6;
|
||||
|
|
@ -259,9 +267,9 @@ extern "C" void osPiStartDma_recomp(RDRAM_ARG recomp_context* ctx) {
|
|||
ctx->r2 = 0;
|
||||
}
|
||||
|
||||
extern "C" void osEPiStartDma_recomp(RDRAM_ARG recomp_context* ctx) {
|
||||
OSPiHandle* handle = TO_PTR(OSPiHandle, ctx->r4);
|
||||
OSIoMesg* mb = TO_PTR(OSIoMesg, ctx->r5);
|
||||
extern "C" void osEPiStartDma_recomp(RDRAM_ARG recomp_context *ctx) {
|
||||
OSPiHandle *handle = TO_PTR(OSPiHandle, ctx->r4);
|
||||
OSIoMesg *mb = TO_PTR(OSIoMesg, ctx->r5);
|
||||
uint32_t direction = ctx->r6;
|
||||
uint32_t devAddr = handle->baseAddress | mb->devAddr;
|
||||
gpr dramAddr = mb->dramAddr;
|
||||
|
|
@ -276,8 +284,8 @@ extern "C" void osEPiStartDma_recomp(RDRAM_ARG recomp_context* ctx) {
|
|||
ctx->r2 = 0;
|
||||
}
|
||||
|
||||
extern "C" void osEPiReadIo_recomp(RDRAM_ARG recomp_context * ctx) {
|
||||
OSPiHandle* handle = TO_PTR(OSPiHandle, ctx->r4);
|
||||
extern "C" void osEPiReadIo_recomp(RDRAM_ARG recomp_context *ctx) {
|
||||
OSPiHandle *handle = TO_PTR(OSPiHandle, ctx->r4);
|
||||
uint32_t devAddr = handle->baseAddress | ctx->r5;
|
||||
gpr dramAddr = ctx->r6;
|
||||
uint32_t physical_addr = k1_to_phys(devAddr);
|
||||
|
|
@ -285,7 +293,8 @@ extern "C" void osEPiReadIo_recomp(RDRAM_ARG recomp_context * ctx) {
|
|||
if (physical_addr > rom_base) {
|
||||
// cart rom
|
||||
recomp::do_rom_pio(PASS_RDRAM dramAddr, physical_addr);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// sram
|
||||
assert(false && "SRAM ReadIo unimplemented");
|
||||
}
|
||||
|
|
@ -293,10 +302,10 @@ extern "C" void osEPiReadIo_recomp(RDRAM_ARG recomp_context * ctx) {
|
|||
ctx->r2 = 0;
|
||||
}
|
||||
|
||||
extern "C" void osPiGetStatus_recomp(RDRAM_ARG recomp_context * ctx) {
|
||||
extern "C" void osPiGetStatus_recomp(RDRAM_ARG recomp_context *ctx) {
|
||||
ctx->r2 = 0;
|
||||
}
|
||||
|
||||
extern "C" void osPiRawStartDma_recomp(RDRAM_ARG recomp_context * ctx) {
|
||||
extern "C" void osPiRawStartDma_recomp(RDRAM_ARG recomp_context *ctx) {
|
||||
ctx->r2 = 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,34 +2,35 @@
|
|||
|
||||
#include <ultramodern/ultra64.h>
|
||||
#include <ultramodern/ultramodern.hpp>
|
||||
#include "recomp.h"
|
||||
|
||||
#include "euc-jp.hpp"
|
||||
#include "recomp.h"
|
||||
|
||||
extern "C" void __checkHardware_msp_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void __checkHardware_msp_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
ctx->r2 = 0;
|
||||
}
|
||||
|
||||
extern "C" void __checkHardware_kmc_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void __checkHardware_kmc_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
ctx->r2 = 0;
|
||||
}
|
||||
|
||||
extern "C" void __checkHardware_isv_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void __checkHardware_isv_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
ctx->r2 = 0;
|
||||
}
|
||||
|
||||
extern "C" void __osInitialize_msp_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void __osInitialize_msp_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
}
|
||||
|
||||
extern "C" void __osInitialize_kmc_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void __osInitialize_kmc_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
}
|
||||
|
||||
extern "C" void __osInitialize_isv_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void __osInitialize_isv_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
}
|
||||
|
||||
extern "C" void isPrintfInit_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void isPrintfInit_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
}
|
||||
|
||||
extern "C" void __osRdbSend_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void __osRdbSend_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
gpr buf = ctx->r4;
|
||||
size_t size = ctx->r5;
|
||||
u32 type = (u32)ctx->r6;
|
||||
|
|
@ -45,16 +46,16 @@ extern "C" void __osRdbSend_recomp(uint8_t * rdram, recomp_context * ctx) {
|
|||
ctx->r2 = size;
|
||||
}
|
||||
|
||||
extern "C" void is_proutSyncPrintf_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void is_proutSyncPrintf_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
// Buffering to speed up print performance
|
||||
static std::vector<char> print_buffer;
|
||||
|
||||
gpr buf = ctx->r5;
|
||||
size_t size = ctx->r6;
|
||||
|
||||
//for (size_t i = 0; i < size; i++) {
|
||||
// // Add the new character to the buffer
|
||||
// char cur_char = MEM_B(i, buf);
|
||||
// for (size_t i = 0; i < size; i++) {
|
||||
// // Add the new character to the buffer
|
||||
// char cur_char = MEM_B(i, buf);
|
||||
|
||||
// // If the new character is a newline, flush the buffer
|
||||
// if (cur_char == '\n') {
|
||||
|
|
@ -66,7 +67,7 @@ extern "C" void is_proutSyncPrintf_recomp(uint8_t * rdram, recomp_context * ctx)
|
|||
// }
|
||||
//}
|
||||
|
||||
//fwrite(to_print.get(), size, 1, stdout);
|
||||
// fwrite(to_print.get(), size, 1, stdout);
|
||||
|
||||
ctx->r2 = 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,22 +1,24 @@
|
|||
#include <array>
|
||||
#include <cmath>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <cmath>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <optional>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <array>
|
||||
#include <optional>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
#include "recomp.h"
|
||||
#include "overlays.hpp"
|
||||
#include "game.hpp"
|
||||
#include "xxHash/xxh3.h"
|
||||
#include "ultramodern/ultramodern.hpp"
|
||||
|
||||
#include "ultramodern/error_handling.hpp"
|
||||
#include "ultramodern/ultramodern.hpp"
|
||||
|
||||
#include "game.hpp"
|
||||
#include "overlays.hpp"
|
||||
#include "recomp.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
inline uint32_t byteswap(uint32_t val) {
|
||||
|
|
@ -40,7 +42,7 @@ std::mutex current_game_mutex;
|
|||
|
||||
// Global variables
|
||||
std::filesystem::path config_path;
|
||||
std::unordered_map<std::u8string, recomp::GameEntry> game_roms {};
|
||||
std::unordered_map<std::u8string, recomp::GameEntry> game_roms{};
|
||||
|
||||
std::u8string recomp::GameEntry::stored_filename() const {
|
||||
return game_id + u8".z64";
|
||||
|
|
@ -64,14 +66,14 @@ bool check_hash(const std::vector<uint8_t>& rom_data, uint64_t expected_hash) {
|
|||
static std::vector<uint8_t> read_file(const std::filesystem::path& path) {
|
||||
std::vector<uint8_t> ret;
|
||||
|
||||
std::ifstream file{ path, std::ios::binary};
|
||||
std::ifstream file{ path, std::ios::binary };
|
||||
|
||||
if (file.good()) {
|
||||
file.seekg(0, std::ios::end);
|
||||
ret.resize(file.tellg());
|
||||
file.seekg(0, std::ios::beg);
|
||||
|
||||
file.read(reinterpret_cast<char*>(ret.data()), ret.size());
|
||||
file.read(reinterpret_cast<char *>(ret.data()), ret.size());
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
@ -84,7 +86,7 @@ bool write_file(const std::filesystem::path& path, const std::vector<uint8_t>& d
|
|||
return false;
|
||||
}
|
||||
|
||||
out_file.write(reinterpret_cast<const char*>(data.data()), data.size());
|
||||
out_file.write(reinterpret_cast<const char *>(data.data()), data.size());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -108,7 +110,7 @@ bool recomp::is_rom_valid(std::u8string& game_id) {
|
|||
}
|
||||
|
||||
void recomp::check_all_stored_roms() {
|
||||
for (const auto& cur_rom_entry: game_roms) {
|
||||
for (const auto& cur_rom_entry : game_roms) {
|
||||
if (check_stored_rom(cur_rom_entry.second)) {
|
||||
valid_game_roms.insert(cur_rom_entry.first);
|
||||
}
|
||||
|
|
@ -121,7 +123,7 @@ bool recomp::load_stored_rom(std::u8string& game_id) {
|
|||
if (find_it == game_roms.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
std::vector<uint8_t> stored_rom_data = read_file(config_path / find_it->second.stored_filename());
|
||||
|
||||
if (!check_hash(stored_rom_data, find_it->second.rom_hash)) {
|
||||
|
|
@ -134,7 +136,7 @@ bool recomp::load_stored_rom(std::u8string& game_id) {
|
|||
return true;
|
||||
}
|
||||
|
||||
const std::array<uint8_t, 4> first_rom_bytes { 0x80, 0x37, 0x12, 0x40 };
|
||||
const std::array<uint8_t, 4> first_rom_bytes{ 0x80, 0x37, 0x12, 0x40 };
|
||||
|
||||
enum class ByteswapType {
|
||||
NotByteswapped,
|
||||
|
|
@ -149,25 +151,22 @@ ByteswapType check_rom_start(const std::vector<uint8_t>& rom_data) {
|
|||
}
|
||||
|
||||
auto check_match = [&](uint8_t index0, uint8_t index1, uint8_t index2, uint8_t index3) {
|
||||
return
|
||||
rom_data[0] == first_rom_bytes[index0] &&
|
||||
rom_data[1] == first_rom_bytes[index1] &&
|
||||
rom_data[2] == first_rom_bytes[index2] &&
|
||||
rom_data[3] == first_rom_bytes[index3];
|
||||
return rom_data[0] == first_rom_bytes[index0] && rom_data[1] == first_rom_bytes[index1] && rom_data[2] == first_rom_bytes[index2] &&
|
||||
rom_data[3] == first_rom_bytes[index3];
|
||||
};
|
||||
|
||||
// Check if the ROM is already in the correct byte order.
|
||||
if (check_match(0,1,2,3)) {
|
||||
if (check_match(0, 1, 2, 3)) {
|
||||
return ByteswapType::NotByteswapped;
|
||||
}
|
||||
|
||||
// Check if the ROM has been byteswapped in groups of 4 bytes.
|
||||
if (check_match(3,2,1,0)) {
|
||||
if (check_match(3, 2, 1, 0)) {
|
||||
return ByteswapType::Byteswapped4;
|
||||
}
|
||||
|
||||
// Check if the ROM has been byteswapped in groups of 2 bytes.
|
||||
if (check_match(1,0,3,2)) {
|
||||
if (check_match(1, 0, 3, 2)) {
|
||||
return ByteswapType::Byteswapped2;
|
||||
}
|
||||
|
||||
|
|
@ -223,12 +222,13 @@ recomp::RomValidationError recomp::select_rom(const std::filesystem::path& rom_p
|
|||
}
|
||||
|
||||
if (!check_hash(rom_data, game_entry.rom_hash)) {
|
||||
const std::string_view name{ reinterpret_cast<const char*>(rom_data.data()) + 0x20, game_entry.internal_name.size()};
|
||||
const std::string_view name{ reinterpret_cast<const char *>(rom_data.data()) + 0x20, game_entry.internal_name.size() };
|
||||
if (name == game_entry.internal_name) {
|
||||
return recomp::RomValidationError::IncorrectVersion;
|
||||
}
|
||||
else {
|
||||
if (game_entry.is_enabled && std::string_view{ reinterpret_cast<const char*>(rom_data.data()) + 0x20, 19 } == game_entry.internal_name) {
|
||||
if (game_entry.is_enabled &&
|
||||
std::string_view{ reinterpret_cast<const char *>(rom_data.data()) + 0x20, 19 } == game_entry.internal_name) {
|
||||
return recomp::RomValidationError::NotYet;
|
||||
}
|
||||
else {
|
||||
|
|
@ -238,11 +238,11 @@ recomp::RomValidationError recomp::select_rom(const std::filesystem::path& rom_p
|
|||
}
|
||||
|
||||
write_file(config_path / game_entry.stored_filename(), rom_data);
|
||||
|
||||
|
||||
return recomp::RomValidationError::Good;
|
||||
}
|
||||
|
||||
extern "C" void osGetMemSize_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void osGetMemSize_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
ctx->r2 = 8 * 1024 * 1024;
|
||||
}
|
||||
|
||||
|
|
@ -250,7 +250,7 @@ enum class StatusReg {
|
|||
FR = 0x04000000,
|
||||
};
|
||||
|
||||
extern "C" void cop0_status_write(recomp_context* ctx, gpr value) {
|
||||
extern "C" void cop0_status_write(recomp_context *ctx, gpr value) {
|
||||
uint32_t old_sr = ctx->status_reg;
|
||||
uint32_t new_sr = (uint32_t)value;
|
||||
uint32_t changed = old_sr ^ new_sr;
|
||||
|
|
@ -280,16 +280,16 @@ extern "C" void cop0_status_write(recomp_context* ctx, gpr value) {
|
|||
assert(false);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
// Update the status register in the context
|
||||
ctx->status_reg = new_sr;
|
||||
}
|
||||
|
||||
extern "C" gpr cop0_status_read(recomp_context* ctx) {
|
||||
extern "C" gpr cop0_status_read(recomp_context *ctx) {
|
||||
return (gpr)(int32_t)ctx->status_reg;
|
||||
}
|
||||
|
||||
extern "C" void switch_error(const char* func, uint32_t vram, uint32_t jtbl) {
|
||||
extern "C" void switch_error(const char *func, uint32_t vram, uint32_t jtbl) {
|
||||
printf("Switch-case out of bounds in %s at 0x%08X for jump table at 0x%08X\n", func, vram, jtbl);
|
||||
assert(false);
|
||||
exit(EXIT_FAILURE);
|
||||
|
|
@ -301,17 +301,17 @@ extern "C" void do_break(uint32_t vram) {
|
|||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
void run_thread_function(uint8_t* rdram, uint64_t addr, uint64_t sp, uint64_t arg) {
|
||||
void run_thread_function(uint8_t *rdram, uint64_t addr, uint64_t sp, uint64_t arg) {
|
||||
recomp_context ctx{};
|
||||
ctx.r29 = sp;
|
||||
ctx.r4 = arg;
|
||||
ctx.mips3_float_mode = 0;
|
||||
ctx.f_odd = &ctx.f0.u32h;
|
||||
recomp_func_t* func = get_function(addr);
|
||||
recomp_func_t *func = get_function(addr);
|
||||
func(rdram, &ctx);
|
||||
}
|
||||
|
||||
void init(uint8_t* rdram, recomp_context* ctx, gpr entrypoint) {
|
||||
void init(uint8_t *rdram, recomp_context *ctx, gpr entrypoint) {
|
||||
// Initialize the overlays
|
||||
recomp::overlays::init_overlays();
|
||||
|
||||
|
|
@ -337,9 +337,9 @@ void init(uint8_t* rdram, recomp_context* ctx, gpr entrypoint) {
|
|||
constexpr int32_t osVersion = 0x80000314;
|
||||
constexpr int32_t osMemSize = 0x80000318;
|
||||
constexpr int32_t osAppNMIBuffer = 0x8000031c;
|
||||
MEM_W(osTvType, 0) = 1; // NTSC
|
||||
MEM_W(osRomBase, 0) = 0xB0000000u; // standard rom base
|
||||
MEM_W(osResetType, 0) = 0; // cold reset
|
||||
MEM_W(osTvType, 0) = 1; // NTSC
|
||||
MEM_W(osRomBase, 0) = 0xB0000000u; // standard rom base
|
||||
MEM_W(osResetType, 0) = 0; // cold reset
|
||||
MEM_W(osMemSize, 0) = 8 * 1024 * 1024; // 8MB
|
||||
}
|
||||
|
||||
|
|
@ -374,25 +374,22 @@ void ultramodern::quit() {
|
|||
}
|
||||
|
||||
void recomp::start(
|
||||
ultramodern::renderer::WindowHandle window_handle,
|
||||
const recomp::rsp::callbacks_t& rsp_callbacks,
|
||||
const ultramodern::renderer::callbacks_t& renderer_callbacks,
|
||||
const ultramodern::audio_callbacks_t& audio_callbacks,
|
||||
const ultramodern::input::callbacks_t& input_callbacks,
|
||||
const ultramodern::gfx_callbacks_t& gfx_callbacks_,
|
||||
const ultramodern::events::callbacks_t& events_callbacks,
|
||||
const ultramodern::error_handling::callbacks_t& error_handling_callbacks_
|
||||
) {
|
||||
ultramodern::renderer::WindowHandle window_handle, const recomp::rsp::callbacks_t& rsp_callbacks,
|
||||
const ultramodern::renderer::callbacks_t& renderer_callbacks, const ultramodern::audio_callbacks_t& audio_callbacks,
|
||||
const ultramodern::input::callbacks_t& input_callbacks, const ultramodern::gfx_callbacks_t& gfx_callbacks_,
|
||||
const ultramodern::events::callbacks_t& events_callbacks, const ultramodern::error_handling::callbacks_t& error_handling_callbacks_) {
|
||||
recomp::check_all_stored_roms();
|
||||
|
||||
recomp::rsp::set_callbacks(rsp_callbacks);
|
||||
|
||||
static const ultramodern::rsp::callbacks_t ultramodern_rsp_callbacks {
|
||||
static const ultramodern::rsp::callbacks_t ultramodern_rsp_callbacks{
|
||||
.init = recomp::rsp::constants_init,
|
||||
.run_task = recomp::rsp::run_task,
|
||||
};
|
||||
|
||||
ultramodern::set_callbacks(ultramodern_rsp_callbacks, renderer_callbacks, audio_callbacks, input_callbacks, gfx_callbacks_, events_callbacks, error_handling_callbacks_);
|
||||
ultramodern::set_callbacks(
|
||||
ultramodern_rsp_callbacks, renderer_callbacks, audio_callbacks, input_callbacks, gfx_callbacks_, events_callbacks,
|
||||
error_handling_callbacks_);
|
||||
|
||||
ultramodern::gfx_callbacks_t gfx_callbacks = gfx_callbacks_;
|
||||
|
||||
|
|
@ -415,20 +412,20 @@ void recomp::start(
|
|||
std::unique_ptr<uint8_t[]> rdram_buffer = std::make_unique<uint8_t[]>(ultramodern::rdram_size);
|
||||
std::memset(rdram_buffer.get(), 0, ultramodern::rdram_size);
|
||||
|
||||
std::thread game_thread{[](ultramodern::renderer::WindowHandle window_handle, uint8_t* rdram) {
|
||||
debug_printf("[Recomp] Starting\n");
|
||||
std::thread game_thread{
|
||||
[](ultramodern::renderer::WindowHandle window_handle, uint8_t *rdram) {
|
||||
debug_printf("[Recomp] Starting\n");
|
||||
|
||||
ultramodern::set_native_thread_name("Game Start Thread");
|
||||
ultramodern::set_native_thread_name("Game Start Thread");
|
||||
|
||||
ultramodern::preinit(rdram, window_handle);
|
||||
ultramodern::preinit(rdram, window_handle);
|
||||
|
||||
game_status.wait(GameStatus::None);
|
||||
recomp_context context{};
|
||||
game_status.wait(GameStatus::None);
|
||||
recomp_context context{};
|
||||
|
||||
switch (game_status.load()) {
|
||||
// TODO refactor this to allow a project to specify what entrypoint function to run for a give game.
|
||||
case GameStatus::Running:
|
||||
{
|
||||
switch (game_status.load()) {
|
||||
// TODO refactor this to allow a project to specify what entrypoint function to run for a give game.
|
||||
case GameStatus::Running: {
|
||||
if (!recomp::load_stored_rom(current_game.value())) {
|
||||
ultramodern::error_handling::message_box("Error opening stored ROM! Please restart this program.");
|
||||
}
|
||||
|
|
@ -443,20 +440,21 @@ void recomp::start(
|
|||
try {
|
||||
game_entry.entrypoint(rdram, &context);
|
||||
} catch (ultramodern::thread_terminated& terminated) {
|
||||
|
||||
}
|
||||
}
|
||||
break;
|
||||
} break;
|
||||
|
||||
case GameStatus::Quit:
|
||||
break;
|
||||
case GameStatus::Quit:
|
||||
break;
|
||||
|
||||
case GameStatus::None:
|
||||
break;
|
||||
}
|
||||
case GameStatus::None:
|
||||
break;
|
||||
}
|
||||
|
||||
debug_printf("[Recomp] Quitting\n");
|
||||
}, window_handle, rdram_buffer.get()};
|
||||
debug_printf("[Recomp] Quitting\n");
|
||||
},
|
||||
window_handle,
|
||||
rdram_buffer.get(),
|
||||
};
|
||||
|
||||
while (!exited) {
|
||||
ultramodern::sleep_milliseconds(1);
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <cinttypes>
|
||||
#include <cstring>
|
||||
|
||||
#include "rsp.hpp"
|
||||
|
||||
static recomp::rsp::callbacks_t rsp_callbacks {};
|
||||
static recomp::rsp::callbacks_t rsp_callbacks{};
|
||||
|
||||
void recomp::rsp::set_callbacks(const callbacks_t& callbacks) {
|
||||
rsp_callbacks = callbacks;
|
||||
|
|
@ -26,16 +26,17 @@ void recomp::rsp::constants_init() {
|
|||
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++;
|
||||
// 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) {
|
||||
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);
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -1,21 +1,24 @@
|
|||
#include <cstdio>
|
||||
#include <fstream>
|
||||
|
||||
#include <ultramodern/ultramodern.hpp>
|
||||
|
||||
#include "recomp.h"
|
||||
|
||||
extern "C" void osSpTaskLoad_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
extern "C" void osSpTaskLoad_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
// Nothing to do here
|
||||
}
|
||||
|
||||
bool dump_frame = false;
|
||||
|
||||
extern "C" void osSpTaskStartGo_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
//printf("[sp] osSpTaskStartGo(0x%08X)\n", (uint32_t)ctx->r4);
|
||||
OSTask* task = TO_PTR(OSTask, ctx->r4);
|
||||
extern "C" void osSpTaskStartGo_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
// printf("[sp] osSpTaskStartGo(0x%08X)\n", (uint32_t)ctx->r4);
|
||||
OSTask *task = TO_PTR(OSTask, ctx->r4);
|
||||
if (task->t.type == M_GFXTASK) {
|
||||
//printf("[sp] Gfx task: %08X\n", (uint32_t)ctx->r4);
|
||||
} else if (task->t.type == M_AUDTASK) {
|
||||
//printf("[sp] Audio task: %08X\n", (uint32_t)ctx->r4);
|
||||
// printf("[sp] Gfx task: %08X\n", (uint32_t)ctx->r4);
|
||||
}
|
||||
else if (task->t.type == M_AUDTASK) {
|
||||
// printf("[sp] Audio task: %08X\n", (uint32_t)ctx->r4);
|
||||
}
|
||||
// For debugging
|
||||
if (dump_frame) {
|
||||
|
|
@ -24,7 +27,7 @@ extern "C" void osSpTaskStartGo_recomp(uint8_t* rdram, recomp_context* ctx) {
|
|||
std::unique_ptr<char[]> ram_unswapped = std::make_unique<char[]>(ram_size);
|
||||
snprintf(addr_str, sizeof(addr_str) - 1, "%08X", task->t.data_ptr);
|
||||
addr_str[sizeof(addr_str) - 1] = '\0';
|
||||
std::ofstream dump_file{ "ramdump" + std::string{ addr_str } + ".bin", std::ios::binary};
|
||||
std::ofstream dump_file{ "ramdump" + std::string{ addr_str } + ".bin", std::ios::binary };
|
||||
|
||||
for (size_t i = 0; i < ram_size; i++) {
|
||||
ram_unswapped[i] = rdram[i ^ 3];
|
||||
|
|
@ -36,15 +39,15 @@ extern "C" void osSpTaskStartGo_recomp(uint8_t* rdram, recomp_context* ctx) {
|
|||
ultramodern::submit_rsp_task(rdram, ctx->r4);
|
||||
}
|
||||
|
||||
extern "C" void osSpTaskYield_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
extern "C" void osSpTaskYield_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
// Ignore yield requests (acts as if the task completed before it received the yield request)
|
||||
}
|
||||
|
||||
extern "C" void osSpTaskYielded_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
extern "C" void osSpTaskYielded_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
// Task yield requests are ignored, so always return 0 as tasks will never be yielded
|
||||
ctx->r2 = 0;
|
||||
}
|
||||
|
||||
extern "C" void __osSpSetPc_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
extern "C" void __osSpSetPc_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
assert(false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,45 +1,45 @@
|
|||
#include <ultramodern/ultra64.h>
|
||||
#include <ultramodern/ultramodern.hpp>
|
||||
|
||||
#include "recomp.h"
|
||||
|
||||
// None of these functions need to be reimplemented, so stub them out
|
||||
extern "C" void osUnmapTLBAll_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void osUnmapTLBAll_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
// TODO this will need to be implemented in the future for any games that actually use the TLB
|
||||
}
|
||||
|
||||
extern "C" void osVoiceInit_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void osVoiceInit_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
ctx->r2 = 11; // CONT_ERR_DEVICE
|
||||
}
|
||||
|
||||
extern "C" void osVoiceSetWord_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void osVoiceSetWord_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
extern "C" void osVoiceCheckWord_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void osVoiceCheckWord_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
extern "C" void osVoiceStopReadData_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void osVoiceStopReadData_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
extern "C" void osVoiceMaskDictionary_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void osVoiceMaskDictionary_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
extern "C" void osVoiceStartReadData_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void osVoiceStartReadData_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
extern "C" void osVoiceControlGain_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void osVoiceControlGain_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
extern "C" void osVoiceGetReadData_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void osVoiceGetReadData_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
extern "C" void osVoiceClearDictionary_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void osVoiceClearDictionary_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,132 +1,135 @@
|
|||
#include <memory>
|
||||
|
||||
#include <ultramodern/ultra64.h>
|
||||
#include <ultramodern/ultramodern.hpp>
|
||||
|
||||
#include "recomp.h"
|
||||
|
||||
extern "C" void osInitialize_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void osInitialize_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
osInitialize();
|
||||
}
|
||||
|
||||
extern "C" void __osInitialize_common_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void __osInitialize_common_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
osInitialize();
|
||||
}
|
||||
|
||||
extern "C" void osCreateThread_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
osCreateThread(rdram, (int32_t)ctx->r4, (OSId)ctx->r5, (int32_t)ctx->r6, (int32_t)ctx->r7,
|
||||
(int32_t)MEM_W(0x10, ctx->r29), (OSPri)MEM_W(0x14, ctx->r29));
|
||||
extern "C" void osCreateThread_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
osCreateThread(
|
||||
rdram, (int32_t)ctx->r4, (OSId)ctx->r5, (int32_t)ctx->r6, (int32_t)ctx->r7, (int32_t)MEM_W(0x10, ctx->r29),
|
||||
(OSPri)MEM_W(0x14, ctx->r29));
|
||||
}
|
||||
|
||||
extern "C" void osStartThread_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
extern "C" void osStartThread_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
osStartThread(rdram, (int32_t)ctx->r4);
|
||||
}
|
||||
|
||||
extern "C" void osStopThread_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void osStopThread_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
osStopThread(rdram, (int32_t)ctx->r4);
|
||||
}
|
||||
|
||||
extern "C" void osDestroyThread_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void osDestroyThread_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
osDestroyThread(rdram, (int32_t)ctx->r4);
|
||||
}
|
||||
|
||||
extern "C" void osYieldThread_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void osYieldThread_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
assert(false);
|
||||
// osYieldThread(rdram);
|
||||
}
|
||||
|
||||
extern "C" void osSetThreadPri_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
extern "C" void osSetThreadPri_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
osSetThreadPri(rdram, (int32_t)ctx->r4, (OSPri)ctx->r5);
|
||||
}
|
||||
|
||||
extern "C" void osGetThreadPri_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void osGetThreadPri_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
ctx->r2 = osGetThreadPri(rdram, (int32_t)ctx->r4);
|
||||
}
|
||||
|
||||
extern "C" void osGetThreadId_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void osGetThreadId_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
ctx->r2 = osGetThreadId(rdram, (int32_t)ctx->r4);
|
||||
}
|
||||
|
||||
extern "C" void osCreateMesgQueue_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
extern "C" void osCreateMesgQueue_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
osCreateMesgQueue(rdram, (int32_t)ctx->r4, (int32_t)ctx->r5, (s32)ctx->r6);
|
||||
}
|
||||
|
||||
extern "C" void osRecvMesg_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
extern "C" void osRecvMesg_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
ctx->r2 = osRecvMesg(rdram, (int32_t)ctx->r4, (int32_t)ctx->r5, (s32)ctx->r6);
|
||||
}
|
||||
|
||||
extern "C" void osSendMesg_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
extern "C" void osSendMesg_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
ctx->r2 = osSendMesg(rdram, (int32_t)ctx->r4, (OSMesg)ctx->r5, (s32)ctx->r6);
|
||||
}
|
||||
|
||||
extern "C" void osJamMesg_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
extern "C" void osJamMesg_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
ctx->r2 = osJamMesg(rdram, (int32_t)ctx->r4, (OSMesg)ctx->r5, (s32)ctx->r6);
|
||||
}
|
||||
|
||||
extern "C" void osSetEventMesg_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
extern "C" void osSetEventMesg_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
osSetEventMesg(rdram, (OSEvent)ctx->r4, (int32_t)ctx->r5, (OSMesg)ctx->r6);
|
||||
}
|
||||
|
||||
extern "C" void osViSetEvent_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void osViSetEvent_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
osViSetEvent(rdram, (int32_t)ctx->r4, (OSMesg)ctx->r5, (u32)ctx->r6);
|
||||
}
|
||||
|
||||
extern "C" void osGetCount_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void osGetCount_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
ctx->r2 = osGetCount();
|
||||
}
|
||||
|
||||
extern "C" void osGetTime_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void osGetTime_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
uint64_t total_count = osGetTime();
|
||||
ctx->r2 = (int32_t)(total_count >> 32);
|
||||
ctx->r3 = (int32_t)(total_count >> 0);
|
||||
}
|
||||
|
||||
extern "C" void osSetTimer_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void osSetTimer_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
uint64_t countdown = ((uint64_t)(ctx->r6) << 32) | ((ctx->r7) & 0xFFFFFFFFu);
|
||||
uint64_t interval = load_doubleword(rdram, ctx->r29, 0x10);
|
||||
ctx->r2 = osSetTimer(rdram, (int32_t)ctx->r4, countdown, interval, (int32_t)MEM_W(0x18, ctx->r29), (OSMesg)MEM_W(0x1C, ctx->r29));
|
||||
}
|
||||
|
||||
extern "C" void osStopTimer_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void osStopTimer_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
ctx->r2 = osStopTimer(rdram, (int32_t)ctx->r4);
|
||||
}
|
||||
|
||||
extern "C" void osVirtualToPhysical_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void osVirtualToPhysical_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
ctx->r2 = osVirtualToPhysical((int32_t)ctx->r4);
|
||||
}
|
||||
|
||||
extern "C" void osInvalDCache_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void osInvalDCache_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
;
|
||||
}
|
||||
|
||||
extern "C" void osInvalICache_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void osInvalICache_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
;
|
||||
}
|
||||
|
||||
extern "C" void osWritebackDCache_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void osWritebackDCache_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
;
|
||||
}
|
||||
|
||||
extern "C" void osWritebackDCacheAll_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void osWritebackDCacheAll_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
;
|
||||
}
|
||||
|
||||
extern "C" void osSetIntMask_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void osSetIntMask_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
;
|
||||
}
|
||||
|
||||
extern "C" void __osDisableInt_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void __osDisableInt_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
;
|
||||
}
|
||||
|
||||
extern "C" void __osRestoreInt_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void __osRestoreInt_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
;
|
||||
}
|
||||
|
||||
extern "C" void __osSetFpcCsr_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
extern "C" void __osSetFpcCsr_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
ctx->r2 = 0;
|
||||
}
|
||||
|
||||
// For the Mario Party games (not working)
|
||||
//extern "C" void longjmp_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
// extern "C" void longjmp_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
// RecompJmpBuf* buf = TO_PTR(RecompJmpBuf, ctx->r4);
|
||||
//
|
||||
// // Check if this is a buffer that was set up with setjmp
|
||||
|
|
@ -153,11 +156,11 @@ extern "C" void __osSetFpcCsr_recomp(uint8_t * rdram, recomp_context * ctx) {
|
|||
//}
|
||||
//
|
||||
//#undef setjmp_recomp
|
||||
//extern "C" void setjmp_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
// extern "C" void setjmp_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
// fprintf(stderr, "Program called setjmp_recomp\n");
|
||||
// std::quick_exit(EXIT_FAILURE);
|
||||
//}
|
||||
//
|
||||
//extern "C" int32_t osGetThreadEx(void) {
|
||||
// extern "C" int32_t osGetThreadEx(void) {
|
||||
// return ultramodern::this_thread();
|
||||
//}
|
||||
|
|
|
|||
|
|
@ -1,45 +1,46 @@
|
|||
#include <ultramodern/ultramodern.hpp>
|
||||
|
||||
#include "recomp.h"
|
||||
|
||||
extern "C" void osViSetYScale_recomp(uint8_t* rdram, recomp_context * ctx) {
|
||||
extern "C" void osViSetYScale_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
osViSetYScale(ctx->f12.fl);
|
||||
}
|
||||
|
||||
extern "C" void osViSetXScale_recomp(uint8_t* rdram, recomp_context * ctx) {
|
||||
extern "C" void osViSetXScale_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
osViSetXScale(ctx->f12.fl);
|
||||
}
|
||||
|
||||
extern "C" void osCreateViManager_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
extern "C" void osCreateViManager_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
;
|
||||
}
|
||||
|
||||
extern "C" void osViBlack_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
extern "C" void osViBlack_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
osViBlack((uint32_t)ctx->r4);
|
||||
}
|
||||
|
||||
extern "C" void osViSetSpecialFeatures_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
extern "C" void osViSetSpecialFeatures_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
osViSetSpecialFeatures((uint32_t)ctx->r4);
|
||||
}
|
||||
|
||||
extern "C" void osViGetCurrentFramebuffer_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
extern "C" void osViGetCurrentFramebuffer_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
ctx->r2 = (gpr)(int32_t)osViGetCurrentFramebuffer();
|
||||
}
|
||||
|
||||
extern "C" void osViGetNextFramebuffer_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
extern "C" void osViGetNextFramebuffer_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
ctx->r2 = (gpr)(int32_t)osViGetNextFramebuffer();
|
||||
}
|
||||
|
||||
extern "C" void osViSwapBuffer_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
extern "C" void osViSwapBuffer_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
osViSwapBuffer(rdram, (int32_t)ctx->r4);
|
||||
}
|
||||
|
||||
extern "C" void osViSetMode_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
extern "C" void osViSetMode_recomp(uint8_t *rdram, recomp_context *ctx) {
|
||||
osViSetMode(rdram, (int32_t)ctx->r4);
|
||||
}
|
||||
|
||||
extern uint64_t total_vis;
|
||||
|
||||
extern "C" void wait_one_frame(uint8_t* rdram, recomp_context* ctx) {
|
||||
extern "C" void wait_one_frame(uint8_t *rdram, recomp_context *ctx) {
|
||||
uint64_t cur_vis = total_vis;
|
||||
while (cur_vis == total_vis) {
|
||||
std::this_thread::yield();
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue