mirror of
https://github.com/N64Recomp/N64ModernRuntime.git
synced 2026-02-05 13:16:19 +00:00
72 lines
2.4 KiB
C++
72 lines
2.4 KiB
C++
#include <vector>
|
|
#include "librecomp/mods.hpp"
|
|
#include "librecomp/overlays.hpp"
|
|
#include "ultramodern/error_handling.hpp"
|
|
|
|
template<class... Ts>
|
|
struct overloaded : Ts... { using Ts::operator()...; };
|
|
template<class... Ts>
|
|
overloaded(Ts...) -> overloaded<Ts...>;
|
|
|
|
struct EventCallback {
|
|
size_t mod_index;
|
|
recomp::mods::GenericFunction func;
|
|
};
|
|
|
|
// Vector of callbacks for each registered event.
|
|
std::vector<std::vector<EventCallback>> event_callbacks{};
|
|
|
|
extern "C" {
|
|
// This can stay at 0 since the base events are always first in the list.
|
|
uint32_t builtin_base_event_index = 0;
|
|
}
|
|
|
|
extern "C" void recomp_trigger_event(uint8_t* rdram, recomp_context* ctx, uint32_t event_index) {
|
|
// Sanity check the event index.
|
|
if (event_index >= event_callbacks.size()) {
|
|
printf("Event %u triggered, but only %zu events have been registered!\n", event_index, event_callbacks.size());
|
|
assert(false);
|
|
ultramodern::error_handling::message_box("Encountered an error with loaded mods: event index out of bounds");
|
|
ULTRAMODERN_QUICK_EXIT();
|
|
}
|
|
|
|
// Copy the initial context state to restore it after running each callback.
|
|
recomp_context initial_context = *ctx;
|
|
|
|
// Call every callback attached to the event.
|
|
const std::vector<EventCallback>& callbacks = event_callbacks[event_index];
|
|
for (const EventCallback& callback : callbacks) {
|
|
// Run the callback.
|
|
std::visit(overloaded {
|
|
[rdram, ctx](recomp_func_t* native_func) {
|
|
native_func(rdram, ctx);
|
|
},
|
|
}, callback.func);
|
|
|
|
// Restore the original context.
|
|
*ctx = initial_context;
|
|
}
|
|
}
|
|
|
|
void recomp::mods::setup_events(size_t num_events) {
|
|
event_callbacks.resize(num_events);
|
|
}
|
|
|
|
void recomp::mods::register_event_callback(size_t event_index, size_t mod_index, GenericFunction callback) {
|
|
event_callbacks[event_index].emplace_back(EventCallback{ mod_index, callback });
|
|
}
|
|
|
|
void recomp::mods::finish_event_setup(const ModContext& context) {
|
|
// Sort callbacks by mod order.
|
|
for (std::vector<EventCallback>& cur_entry : event_callbacks) {
|
|
std::sort(cur_entry.begin(), cur_entry.end(),
|
|
[&context](const EventCallback& lhs, const EventCallback& rhs) {
|
|
return context.get_mod_order_index(lhs.mod_index) < context.get_mod_order_index(rhs.mod_index);
|
|
}
|
|
);
|
|
}
|
|
}
|
|
|
|
void recomp::mods::reset_events() {
|
|
event_callbacks.clear();
|
|
}
|