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:
Mr-Wiseguy
2023-11-12 14:47:38 -05:00
parent 398988a961
commit 8188aee2c1
21 changed files with 264 additions and 60 deletions
+21 -15
View File
@@ -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
View File
@@ -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
View File
@@ -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();
}
+4
View File
@@ -130,3 +130,7 @@ void RT64UpdateScreen(uint32_t vi_origin) {
void RT64ChangeWindow() {
ChangeWindow();
}
void RT64Shutdown() {
PluginShutdown();
}
+10 -1
View File
@@ -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();
}