mirror of
https://github.com/Zelda64Recomp/Zelda64Recomp
synced 2026-08-04 09:28:36 -04:00
Removed use of std::exit and changed recomp runtime to exit normally, added helpers for getting recompiled args and returning values, added example of patch code calling native code
This commit is contained in:
+21
-15
@@ -1,5 +1,5 @@
|
||||
#include "../portultra/multilibultra.hpp"
|
||||
#include "recomp.h"
|
||||
#include "recomp_helpers.h"
|
||||
|
||||
static Multilibultra::input_callbacks_t input_callbacks;
|
||||
|
||||
@@ -10,8 +10,8 @@ void set_input_callbacks(const Multilibultra::input_callbacks_t& callbacks) {
|
||||
static int max_controllers = 0;
|
||||
|
||||
extern "C" void osContInit_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
gpr bitpattern = ctx->r5;
|
||||
gpr status = ctx->r6;
|
||||
PTR(void) bitpattern = _arg<1, PTR(void)>(rdram, ctx);
|
||||
PTR(void) status = _arg<2, PTR(void)>(rdram, ctx);
|
||||
|
||||
// Set bit 0 to indicate that controller 0 is present
|
||||
MEM_B(0, bitpattern) = 0x01;
|
||||
@@ -29,22 +29,15 @@ extern "C" void osContInit_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
MEM_B(4 * controller + 3, status) = 0x80 >> 4; // errno: CONT_NO_RESPONSE_ERROR >> 4
|
||||
}
|
||||
|
||||
ctx->r2 = 0;
|
||||
_return<s32>(ctx, 0);
|
||||
}
|
||||
|
||||
extern "C" void osContStartReadData_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
Multilibultra::send_si_message();
|
||||
}
|
||||
|
||||
struct OSContPad {
|
||||
u16 button;
|
||||
s8 stick_x; /* -80 <= stick_x <= 80 */
|
||||
s8 stick_y; /* -80 <= stick_y <= 80 */
|
||||
u8 errno_;
|
||||
};
|
||||
|
||||
extern "C" void osContGetReadData_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
int32_t pad = (int32_t)ctx->r4;
|
||||
PTR(void) pad = _arg<0, PTR(void)>(rdram, ctx);
|
||||
|
||||
uint16_t buttons = 0;
|
||||
float x = 0.0f;
|
||||
@@ -74,7 +67,7 @@ extern "C" void osContStartQuery_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
}
|
||||
|
||||
extern "C" void osContGetQuery_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
gpr status = ctx->r4;
|
||||
PTR(void) status = _arg<0, PTR(void)>(rdram, ctx);
|
||||
|
||||
// Mark controller 0 as present
|
||||
MEM_H(0, status) = 0x0005; // type: CONT_TYPE_NORMAL (from joybus)
|
||||
@@ -89,8 +82,8 @@ extern "C" void osContGetQuery_recomp(uint8_t * rdram, recomp_context * ctx) {
|
||||
}
|
||||
|
||||
extern "C" void osContSetCh_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
max_controllers = std::min((unsigned int)ctx->r4, 4u);
|
||||
ctx->r2 = 0;
|
||||
max_controllers = std::min(_arg<0, u8>(rdram, ctx), u8(4));
|
||||
_return<s32>(ctx, 0);
|
||||
}
|
||||
|
||||
extern "C" void __osMotorAccess_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
@@ -108,3 +101,16 @@ extern "C" void osMotorStart_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
extern "C" void osMotorStop_recomp(uint8_t* rdram, recomp_context* ctx) {
|
||||
;
|
||||
}
|
||||
|
||||
#include "../patches/input.h"
|
||||
|
||||
extern "C" void recomp_get_item_inputs(uint8_t* rdram, recomp_context* ctx) {
|
||||
RecompInputs* inputs = _arg<0, RecompInputs*>(rdram, ctx);
|
||||
|
||||
if (input_callbacks.get_input) {
|
||||
u16 buttons;
|
||||
input_callbacks.get_input(&buttons, &inputs->x, &inputs->y);
|
||||
// TODO remap the inputs for items here
|
||||
inputs->buttons = buttons;
|
||||
}
|
||||
}
|
||||
|
||||
+7
-6
@@ -99,7 +99,7 @@ std::vector<GameControllerButtonMapping> controller_button_map{
|
||||
|
||||
std::vector<SDL_JoystickID> controllers{};
|
||||
|
||||
int sdl_event_filter(void* userdata, SDL_Event* event) {
|
||||
bool sdl_event_filter(void* userdata, SDL_Event* event) {
|
||||
switch (event->type) {
|
||||
//case SDL_EventType::SDL_KEYUP:
|
||||
//case SDL_EventType::SDL_KEYDOWN:
|
||||
@@ -138,13 +138,13 @@ int sdl_event_filter(void* userdata, SDL_Event* event) {
|
||||
}
|
||||
break;
|
||||
case SDL_EventType::SDL_QUIT:
|
||||
std::quick_exit(EXIT_SUCCESS);
|
||||
break;
|
||||
Multilibultra::quit();
|
||||
return true;
|
||||
default:
|
||||
queue_event(*event);
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
Multilibultra::gfx_callbacks_t::gfx_data_t create_gfx() {
|
||||
@@ -185,8 +185,9 @@ void update_gfx(void*) {
|
||||
constexpr int max_events_per_frame = 16;
|
||||
SDL_Event cur_event;
|
||||
int i = 0;
|
||||
while (i++ < max_events_per_frame && SDL_PollEvent(&cur_event)) {
|
||||
sdl_event_filter(nullptr, &cur_event);
|
||||
static bool exited = false;
|
||||
while (i++ < max_events_per_frame && SDL_PollEvent(&cur_event) && !exited) {
|
||||
exited = sdl_event_filter(nullptr, &cur_event);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+39
-1
@@ -122,6 +122,28 @@ extern "C" void unload_overlays(int32_t ram_addr, uint32_t size);
|
||||
std::unique_ptr<uint8_t[]> rdram_buffer;
|
||||
recomp_context context{};
|
||||
|
||||
void read_patch_data(uint8_t* rdram, gpr patch_data_address) {
|
||||
const char patches_data_file_path[] = "patches/patches.bin";
|
||||
std::ifstream patches_data_file{ patches_data_file_path, std::ios::binary };
|
||||
|
||||
if (!patches_data_file) {
|
||||
fprintf(stderr, "Failed to open patches data file: %s\n", patches_data_file_path);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
patches_data_file.seekg(0, std::ios::end);
|
||||
size_t patches_data_size = patches_data_file.tellg();
|
||||
patches_data_file.seekg(0, std::ios::beg);
|
||||
|
||||
std::unique_ptr<uint8_t[]> patches_data = std::make_unique<uint8_t[]>(patches_data_size);
|
||||
|
||||
patches_data_file.read(reinterpret_cast<char*>(patches_data.get()), patches_data_size);
|
||||
|
||||
for (size_t i = 0; i < patches_data_size; i++) {
|
||||
MEM_B(i, patch_data_address) = patches_data[i];
|
||||
}
|
||||
}
|
||||
|
||||
EXPORT extern "C" void init() {
|
||||
{
|
||||
std::ifstream rom_file{ get_rom_name(), std::ios::binary };
|
||||
@@ -160,6 +182,9 @@ EXPORT extern "C" void init() {
|
||||
// Initial 1MB DMA (rom address 0x1000 = physical address 0x10001000)
|
||||
do_rom_read(rdram_buffer.get(), entrypoint, 0x10001000, 0x100000);
|
||||
|
||||
// Read in any extra data from patches
|
||||
read_patch_data(rdram_buffer.get(), (gpr)(s32)0x80800100);
|
||||
|
||||
// Set up stack pointer
|
||||
context.r29 = 0xFFFFFFFF803FFFF0u;
|
||||
|
||||
@@ -197,6 +222,15 @@ bool Multilibultra::is_game_started() {
|
||||
void set_audio_callbacks(const Multilibultra::audio_callbacks_t& callbacks);
|
||||
void set_input_callbacks(const Multilibultra::input_callbacks_t& callback);
|
||||
|
||||
std::atomic_bool exited = false;
|
||||
|
||||
void Multilibultra::quit() {
|
||||
exited.store(true);
|
||||
int desired = -1;
|
||||
game_started.compare_exchange_strong(desired, -2);
|
||||
game_started.notify_all();
|
||||
}
|
||||
|
||||
void Multilibultra::start(WindowHandle window_handle, const audio_callbacks_t& audio_callbacks, const input_callbacks_t& input_callbacks, const gfx_callbacks_t& gfx_callbacks_) {
|
||||
set_audio_callbacks(audio_callbacks);
|
||||
set_input_callbacks(input_callbacks);
|
||||
@@ -231,16 +265,20 @@ void Multilibultra::start(WindowHandle window_handle, const audio_callbacks_t& a
|
||||
case 0:
|
||||
recomp_entrypoint(rdram_buffer.get(), &context);
|
||||
break;
|
||||
case -2:
|
||||
break;
|
||||
}
|
||||
|
||||
debug_printf("[Recomp] Quitting\n");
|
||||
}, window_handle};
|
||||
|
||||
while (true) {
|
||||
while (!exited) {
|
||||
using namespace std::chrono_literals;
|
||||
std::this_thread::sleep_for(1ms);
|
||||
if (gfx_callbacks.update_gfx != nullptr) {
|
||||
gfx_callbacks.update_gfx(gfx_data);
|
||||
}
|
||||
}
|
||||
game_thread.join();
|
||||
Multilibultra::join_event_threads();
|
||||
}
|
||||
|
||||
@@ -130,3 +130,7 @@ void RT64UpdateScreen(uint32_t vi_origin) {
|
||||
void RT64ChangeWindow() {
|
||||
ChangeWindow();
|
||||
}
|
||||
|
||||
void RT64Shutdown() {
|
||||
PluginShutdown();
|
||||
}
|
||||
|
||||
+10
-1
@@ -587,6 +587,10 @@ struct {
|
||||
Rml::Context* context;
|
||||
std::unique_ptr<Rml::EventListenerInstancer> event_listener_instancer;
|
||||
|
||||
void unload() {
|
||||
render_interface.reset();
|
||||
}
|
||||
|
||||
void swap_document(Menu menu) {
|
||||
if (current_document != nullptr) {
|
||||
current_document->Hide();
|
||||
@@ -751,4 +755,9 @@ void set_rt64_hooks() {
|
||||
|
||||
void set_current_menu(Menu menu) {
|
||||
open_menu.store(menu);
|
||||
}
|
||||
}
|
||||
|
||||
void destroy_ui() {
|
||||
Rml::Shutdown();
|
||||
UIContext.rml.unload();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user