From e3e70243428541c195bd887427a8209b41714329 Mon Sep 17 00:00:00 2001 From: Anghelo Carvajal Date: Thu, 30 May 2024 22:56:45 -0400 Subject: [PATCH] Remove librecomp usage from ultramodern (#23) * Start setting up user callbacks system * Implement RSP callbacks * move RSP callbacks (and related RSP stuff) to its own file * Move destroy_ui to gfx_callbacks_t and change recomp::start to require rsp_callbacks_t * error_handling.hpp * Remove UserCallbacks in favor of threads_callbacks_t * Add `ultramodern::set_callbacks` and some other cleanups * Move most RSP stuff to librecomp * Rename rsp_stuff.hpp to rsp.hpp * Add rsp.cpp to librecomp cmake file * review * Remove `recomp::message_box` * Fix missing rename --- librecomp/CMakeLists.txt | 1 + librecomp/include/recomp_game.h | 6 +- librecomp/include/rsp.h | 33 ++++++- librecomp/src/recomp.cpp | 22 +++-- librecomp/src/rsp.cpp | 62 +++++++++++++ ultramodern/CMakeLists.txt | 8 +- .../include/ultramodern/error_handling.hpp | 23 +++++ ultramodern/include/ultramodern/events.hpp | 25 +++++ ultramodern/include/ultramodern/recomp_ui.h | 12 --- ultramodern/include/ultramodern/rsp.hpp | 35 +++++++ .../include/ultramodern/ultramodern.hpp | 16 ++++ ultramodern/src/audio.cpp | 2 +- ultramodern/src/error_handling.cpp | 19 ++++ ultramodern/src/events.cpp | 92 ++++++------------- ultramodern/src/mesgqueue.cpp | 1 - ultramodern/src/rsp.cpp | 22 +++++ ultramodern/src/ultrainit.cpp | 16 ++++ 17 files changed, 299 insertions(+), 96 deletions(-) create mode 100644 librecomp/src/rsp.cpp create mode 100644 ultramodern/include/ultramodern/error_handling.hpp create mode 100644 ultramodern/include/ultramodern/events.hpp delete mode 100644 ultramodern/include/ultramodern/recomp_ui.h create mode 100644 ultramodern/include/ultramodern/rsp.hpp create mode 100644 ultramodern/src/error_handling.cpp create mode 100644 ultramodern/src/rsp.cpp diff --git a/librecomp/CMakeLists.txt b/librecomp/CMakeLists.txt index 1405045..596e588 100644 --- a/librecomp/CMakeLists.txt +++ b/librecomp/CMakeLists.txt @@ -24,6 +24,7 @@ add_library(librecomp STATIC "${CMAKE_CURRENT_SOURCE_DIR}/src/pi.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/print.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/recomp.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/src/rsp.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/sp.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/ultra_stubs.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/ultra_translation.cpp" diff --git a/librecomp/include/recomp_game.h b/librecomp/include/recomp_game.h index fccbfc9..788a7fd 100644 --- a/librecomp/include/recomp_game.h +++ b/librecomp/include/recomp_game.h @@ -5,6 +5,7 @@ #include #include "recomp.h" +#include "rsp.h" #include namespace recomp { @@ -38,9 +39,8 @@ namespace recomp { void set_rom_contents(std::vector&& 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); - void start(ultramodern::WindowHandle window_handle, const ultramodern::audio_callbacks_t& audio_callbacks, const ultramodern::input_callbacks_t& input_callbacks, const ultramodern::gfx_callbacks_t& gfx_callbacks); - void start_game(std::u8string game_id); - void message_box(const char* message); + void start(ultramodern::WindowHandle window_handle, const recomp::rsp::callbacks_t& rsp_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& thread_callbacks, const ultramodern::error_handling::callbacks_t& error_handling_callbacks_); + void start_game(const std::u8string& game_id); std::filesystem::path get_app_folder_path(); std::u8string current_game_id(); diff --git a/librecomp/include/rsp.h b/librecomp/include/rsp.h index 17f8f90..7e1a1e4 100644 --- a/librecomp/include/rsp.h +++ b/librecomp/include/rsp.h @@ -1,9 +1,13 @@ #ifndef __RSP_H__ #define __RSP_H__ +#include + #include "rsp_vu.h" #include "recomp.h" -#include +#include "ultramodern/ultra64.h" + +// TODO: Move these to recomp namespace? enum class RspExitReason { Invalid, @@ -13,6 +17,8 @@ enum class RspExitReason { Unsupported }; +using RspUcodeFunc = RspExitReason(uint8_t* rdram); + extern uint8_t dmem[]; extern uint16_t rspReciprocals[512]; extern uint16_t rspInverseSquareRoots[512]; @@ -61,7 +67,7 @@ static inline void RSP_MEM_H_STORE(uint32_t offset, uint32_t addr, uint32_t val) #define RSP_ADD32(a, b) \ ((int32_t)((a) + (b))) - + #define RSP_SUB32(a, b) \ ((int32_t)((a) - (b))) @@ -91,4 +97,27 @@ 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); + + /** + * 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. + * + * 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; + }; + + void set_callbacks(const callbacks_t& callbacks); + + void constants_init(); + + bool run_task(uint8_t* rdram, const OSTask* task); + } +} + #endif diff --git a/librecomp/src/recomp.cpp b/librecomp/src/recomp.cpp index 5c88564..374859e 100644 --- a/librecomp/src/recomp.cpp +++ b/librecomp/src/recomp.cpp @@ -21,7 +21,8 @@ #include "recomp_overlays.h" #include "recomp_game.h" #include "xxHash/xxh3.h" -#include +#include "ultramodern/ultramodern.hpp" +#include "ultramodern/error_handling.hpp" #ifdef _MSC_VER inline uint32_t byteswap(uint32_t val) { @@ -402,7 +403,7 @@ std::u8string recomp::current_game_id() { return current_game.value(); }; -void recomp::start_game(std::u8string game_id) { +void recomp::start_game(const std::u8string& game_id) { std::lock_guard lock(current_game_mutex); current_game = game_id; game_status.store(GameStatus::Running); @@ -412,7 +413,6 @@ bool ultramodern::is_game_started() { return game_status.load() != GameStatus::None; } -void set_audio_callbacks(const ultramodern::audio_callbacks_t& callbacks); void set_input_callbacks(const ultramodern::input_callbacks_t& callback); std::atomic_bool exited = false; @@ -426,9 +426,18 @@ void ultramodern::quit() { current_game.reset(); } -void recomp::start(ultramodern::WindowHandle window_handle, const ultramodern::audio_callbacks_t& audio_callbacks, const ultramodern::input_callbacks_t& input_callbacks, const ultramodern::gfx_callbacks_t& gfx_callbacks_) { +void recomp::start(ultramodern::WindowHandle window_handle, const recomp::rsp::callbacks_t& rsp_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& thread_callbacks_, const ultramodern::error_handling::callbacks_t& error_handling_callbacks_) { recomp::check_all_stored_roms(); - set_audio_callbacks(audio_callbacks); + + recomp::rsp::set_callbacks(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, audio_callbacks, input_callbacks, gfx_callbacks_, thread_callbacks_, error_handling_callbacks_); + set_input_callbacks(input_callbacks); ultramodern::gfx_callbacks_t gfx_callbacks = gfx_callbacks_; @@ -467,7 +476,7 @@ void recomp::start(ultramodern::WindowHandle window_handle, const ultramodern::a case GameStatus::Running: { if (!recomp::load_stored_rom(current_game.value())) { - recomp::message_box("Error opening stored ROM! Please restart this program."); + ultramodern::error_handling::message_box("Error opening stored ROM! Please restart this program."); } auto find_it = game_roms.find(current_game.value()); @@ -499,6 +508,7 @@ void recomp::start(ultramodern::WindowHandle window_handle, const ultramodern::a gfx_callbacks.update_gfx(gfx_data); } } + game_thread.join(); ultramodern::join_event_threads(); ultramodern::join_thread_cleaner_thread(); diff --git a/librecomp/src/rsp.cpp b/librecomp/src/rsp.cpp new file mode 100644 index 0000000..9f27bbb --- /dev/null +++ b/librecomp/src/rsp.cpp @@ -0,0 +1,62 @@ +#include +#include +#include + +#include "rsp.h" + +static recomp::rsp::callbacks_t rsp_callbacks {}; + +void recomp::rsp::set_callbacks(const callbacks_t& callbacks) { + rsp_callbacks = callbacks; +} + +uint8_t dmem[0x1000]; +uint16_t rspReciprocals[512]; +uint16_t rspInverseSquareRoots[512]; + +// From Ares emulator. For license details, see rsp_vu.h +void recomp::rsp::constants_init() { + rspReciprocals[0] = u16(~0); + for (u16 index = 1; index < 512; index++) { + u64 a = index + 512; + u64 b = (u64(1) << 34) / a; + rspReciprocals[index] = u16((b + 1) >> 8); + } + + 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++; + rspInverseSquareRoots[index] = u16(b >> 1); + } +} + +// Runs a recompiled RSP microcode +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); + + if (ucode_func == nullptr) { + fprintf(stderr, "No registered RSP ucode for %" PRIu32 " (returned `nullptr`)\n", task->t.type); + return false; + } + + // Load the OSTask into DMEM + memcpy(&dmem[0xFC0], task, sizeof(OSTask)); + + // Load the ucode data into DMEM + dma_rdram_to_dmem(rdram, 0x0000, task->t.ucode_data, 0xF80 - 1); + + // Run the ucode + RspExitReason exit_reason = ucode_func(rdram); + + // Ensure that the ucode exited correctly + if (exit_reason != RspExitReason::Broke) { + fprintf(stderr, "RSP ucode %" PRIu32 " exited unexpectedly. exit_reason: %i\n", task->t.type, exit_reason); + assert(exit_reason == RspExitReason::Broke); + return false; + } + + return true; +} diff --git a/ultramodern/CMakeLists.txt b/ultramodern/CMakeLists.txt index 1b62ca9..94356b1 100644 --- a/ultramodern/CMakeLists.txt +++ b/ultramodern/CMakeLists.txt @@ -11,15 +11,18 @@ set(CMAKE_CXX_EXTENSIONS OFF) add_library(ultramodern STATIC "${CMAKE_CURRENT_SOURCE_DIR}/src/audio.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/src/error_handling.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/events.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/mesgqueue.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/misc_ultra.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/src/rsp.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/rt64_layer.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/scheduling.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/task_win32.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/threadqueue.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/threads.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/src/timer.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/src/ultrainit.cpp" ) target_include_directories(ultramodern PUBLIC @@ -43,11 +46,6 @@ target_include_directories(ultramodern PRIVATE "${PROJECT_SOURCE_DIR}/../rt64/src/contrib/nativefiledialog-extended/src/include" ) -# TODO: remove when librecomp is untangled from ultramodern -target_include_directories(ultramodern PRIVATE - "${CMAKE_SOURCE_DIR}/librecomp/include" -) - if (WIN32) include(FetchContent) # Fetch SDL2 on windows diff --git a/ultramodern/include/ultramodern/error_handling.hpp b/ultramodern/include/ultramodern/error_handling.hpp new file mode 100644 index 0000000..7632806 --- /dev/null +++ b/ultramodern/include/ultramodern/error_handling.hpp @@ -0,0 +1,23 @@ +#ifndef __ERROR_HANDLING_HPP__ +#define __ERROR_HANDLING_HPP__ + +namespace ultramodern { + namespace error_handling { + struct callbacks_t { + using message_box_t = void(const char* msg); + + /** + * Show an OS dialog with the given `msg`. + * + * The `msg` parameter is always non-`nullptr`. + */ + message_box_t *message_box; + }; + + void set_callbacks(const callbacks_t& callbacks); + + void message_box(const char* msg); + } +} + +#endif diff --git a/ultramodern/include/ultramodern/events.hpp b/ultramodern/include/ultramodern/events.hpp new file mode 100644 index 0000000..dbb2ea5 --- /dev/null +++ b/ultramodern/include/ultramodern/events.hpp @@ -0,0 +1,25 @@ +#ifndef __EVENTS_HPP__ +#define __EVENTS_HPP__ + +namespace ultramodern { + namespace events { + struct callbacks_t { + using vi_callback_t = void(); + using gfx_init_callback_t = void(); + + /** + * Called in each VI. + */ + vi_callback_t* vi_callback; + + /** + * Called before entering the gfx main loop. + */ + gfx_init_callback_t* gfx_init_callback; + }; + + void set_callbacks(const callbacks_t& callbacks); + } +} + +#endif diff --git a/ultramodern/include/ultramodern/recomp_ui.h b/ultramodern/include/ultramodern/recomp_ui.h deleted file mode 100644 index 7b511fc..0000000 --- a/ultramodern/include/ultramodern/recomp_ui.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef __ULTRAMODERN_RECOMP_UI__ -#define __ULTRAMODERN_RECOMP_UI__ - -namespace recomp { - // Currently those functions are expected to be provided by the consumer of this library. - // TODO: Change these functions to a callback registering system - - void destroy_ui(); - void update_supported_options(); -} - -#endif diff --git a/ultramodern/include/ultramodern/rsp.hpp b/ultramodern/include/ultramodern/rsp.hpp new file mode 100644 index 0000000..be1a85c --- /dev/null +++ b/ultramodern/include/ultramodern/rsp.hpp @@ -0,0 +1,35 @@ +#ifndef __RSP_STUFF_HPP__ +#define __RSP_STUFF_HPP__ + +// TODO: rename + +#include + +#include "ultra64.h" + +// TODO: Move these to ultramodern namespace? + +namespace ultramodern { + namespace rsp { + struct callbacks_t { + using init_t = void(); + using run_microcode_t = bool(RDRAM_ARG const OSTask* task); + + init_t* init; + + /** + * Executes the given RSP task. + * + * Returns true if task was executed successfully. + */ + run_microcode_t* run_task; + }; + + void set_callbacks(const callbacks_t& callbacks); + + void init(); + bool run_task(RDRAM_ARG const OSTask* task); + }; +} // namespace ultramodern + +#endif diff --git a/ultramodern/include/ultramodern/ultramodern.hpp b/ultramodern/include/ultramodern/ultramodern.hpp index af2100d..1c6b8ed 100644 --- a/ultramodern/include/ultramodern/ultramodern.hpp +++ b/ultramodern/include/ultramodern/ultramodern.hpp @@ -25,6 +25,10 @@ # undef Success #endif +#include "ultramodern/error_handling.hpp" +#include "ultramodern/events.hpp" +#include "ultramodern/rsp.hpp" + struct UltraThreadContext { std::thread host_thread; moodycamel::LightweightSemaphore running; @@ -132,6 +136,7 @@ struct audio_callbacks_t { set_frequency_t* set_frequency; }; +// TODO: These functions are currently called by librecomp, but will get called by ultramodern in the future // Input struct input_callbacks_t { using poll_input_t = void(void); @@ -142,21 +147,32 @@ struct input_callbacks_t { set_rumble_t* set_rumble; }; +// TODO: Most of the members of this struct are not used by ultramodern. Should we move them to librecomp instead? struct gfx_callbacks_t { using gfx_data_t = void*; using create_gfx_t = gfx_data_t(); using create_window_t = WindowHandle(gfx_data_t); using update_gfx_t = void(gfx_data_t); + create_gfx_t* create_gfx; create_window_t* create_window; update_gfx_t* update_gfx; }; + bool is_game_started(); void quit(); void join_event_threads(); void join_thread_cleaner_thread(); void join_saving_thread(); +void set_audio_callbacks(const audio_callbacks_t& callbacks); + +/** + * Register all the callbacks used by `ultramodern`, most of them being optional. + * + * It must be called only once and it must be called before `ultramodern::preinit`. + */ +void set_callbacks(const rsp::callbacks_t& rsp_callbacks, const audio_callbacks_t& audio_callbacks, const input_callbacks_t& input_callbacks, const gfx_callbacks_t& gfx_callbacks, const events::callbacks_t& events_callbacks, const error_handling::callbacks_t& error_handling_callbacks); } // namespace ultramodern #define MIN(a, b) ((a) < (b) ? (a) : (b)) diff --git a/ultramodern/src/audio.cpp b/ultramodern/src/audio.cpp index b24e686..d3ae2e7 100644 --- a/ultramodern/src/audio.cpp +++ b/ultramodern/src/audio.cpp @@ -6,7 +6,7 @@ static uint32_t sample_rate = 48000; static ultramodern::audio_callbacks_t audio_callbacks; -void set_audio_callbacks(const ultramodern::audio_callbacks_t& callbacks) { +void ultramodern::set_audio_callbacks(const ultramodern::audio_callbacks_t& callbacks) { audio_callbacks = callbacks; } diff --git a/ultramodern/src/error_handling.cpp b/ultramodern/src/error_handling.cpp new file mode 100644 index 0000000..0adf16d --- /dev/null +++ b/ultramodern/src/error_handling.cpp @@ -0,0 +1,19 @@ +#include + +#include "ultramodern/error_handling.hpp" + +static ultramodern::error_handling::callbacks_t error_handling_callbacks{}; + +void ultramodern::error_handling::set_callbacks(const ultramodern::error_handling::callbacks_t& callbacks) { + error_handling_callbacks = callbacks; +} + +void ultramodern::error_handling::message_box(const char* msg) { + // We print the message to stderr since the user may not have provided a message_box callback + + fprintf(stderr, "%s\n", msg); + + if (error_handling_callbacks.message_box != nullptr) { + error_handling_callbacks.message_box(msg); + } +} diff --git a/ultramodern/src/events.cpp b/ultramodern/src/events.cpp index 9af5568..be1f3bd 100644 --- a/ultramodern/src/events.cpp +++ b/ultramodern/src/events.cpp @@ -12,14 +12,16 @@ #include "blockingconcurrentqueue.h" #include "ultra64.h" -#include "ultramodern.hpp" +#include "ultramodern/ultramodern.hpp" #include "config.hpp" #include "rt64_layer.h" -#include "recomp_ui.h" -#include "recomp.h" -#include "recomp_game.h" -#include "recomp_input.h" -#include "rsp.h" +#include "ultramodern/rsp.hpp" + +static ultramodern::events::callbacks_t events_callbacks{}; + +void ultramodern::events::set_callbacks(const ultramodern::events::callbacks_t& callbacks) { + events_callbacks = callbacks; +} struct SpTaskAction { OSTask task; @@ -116,7 +118,7 @@ void vi_thread_func() { // the game to generate new audio and gfx lists. ultramodern::set_native_thread_priority(ultramodern::ThreadPriority::Critical); using namespace std::chrono_literals; - + int remaining_retraces = events_context.vi.retrace_count; while (!exited) { @@ -176,9 +178,10 @@ void vi_thread_func() { } } } - - // TODO move recomp code out of ultramodern. - recomp::update_rumble(); + + if (events_callbacks.vi_callback != nullptr) { + events_callbacks.vi_callback(); + } } } @@ -194,45 +197,6 @@ void dp_complete() { osSendMesg(PASS_RDRAM events_context.dp.mq, events_context.dp.msg, OS_MESG_NOBLOCK); } -uint8_t dmem[0x1000]; -uint16_t rspReciprocals[512]; -uint16_t rspInverseSquareRoots[512]; - -using RspUcodeFunc = RspExitReason(uint8_t* rdram); -extern RspUcodeFunc njpgdspMain; -extern RspUcodeFunc aspMain; - -// From Ares emulator. For license details, see rsp_vu.h -void rsp_constants_init() { - rspReciprocals[0] = u16(~0); - for (u16 index = 1; index < 512; index++) { - u64 a = index + 512; - u64 b = (u64(1) << 34) / a; - rspReciprocals[index] = u16((b + 1) >> 8); - } - - 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++; - rspInverseSquareRoots[index] = u16(b >> 1); - } -} - -// Runs a recompiled RSP microcode -void run_rsp_microcode(uint8_t* rdram, const OSTask* task, RspUcodeFunc* ucode_func) { - // Load the OSTask into DMEM - memcpy(&dmem[0xFC0], task, sizeof(OSTask)); - // Load the ucode data into DMEM - dma_rdram_to_dmem(rdram, 0x0000, task->t.ucode_data, 0xF80 - 1); - // Run the ucode - RspExitReason exit_reason = ucode_func(rdram); - // Ensure that the ucode exited correctly - assert(exit_reason == RspExitReason::Broke); -} - - void task_thread_func(uint8_t* rdram, moodycamel::LightweightSemaphore* thread_ready) { ultramodern::set_native_thread_name("SP Task Thread"); ultramodern::set_native_thread_priority(ultramodern::ThreadPriority::Normal); @@ -249,15 +213,9 @@ void task_thread_func(uint8_t* rdram, moodycamel::LightweightSemaphore* thread_r return; } - // Run the correct function based on the task type - if (task->t.type == M_AUDTASK) { - run_rsp_microcode(rdram, task, aspMain); - } - else if (task->t.type == M_NJPEGTASK) { - run_rsp_microcode(rdram, task, njpgdspMain); - } - else { - fprintf(stderr, "Unknown task type: %" PRIu32 "\n", task->t.type); + + if (!ultramodern::rsp::run_task(PASS_RDRAM task)) { + fprintf(stderr, "Failed to execute task type: %" PRIu32 "\n", task->t.type); assert(false); std::quick_exit(EXIT_FAILURE); } @@ -323,10 +281,11 @@ void gfx_thread_func(uint8_t* rdram, moodycamel::LightweightSemaphore* thread_re return; } - // TODO move recomp code out of ultramodern. - recomp::update_supported_options(); + if (events_callbacks.gfx_init_callback != nullptr) { + events_callbacks.gfx_init_callback(); + } - rsp_constants_init(); + ultramodern::rsp::init(); // Notify the caller thread that this thread is ready. thread_ready->signal(); @@ -372,8 +331,7 @@ void gfx_thread_func(uint8_t* rdram, moodycamel::LightweightSemaphore* thread_re } } } - // TODO move recomp code out of ultramodern. - recomp::destroy_ui(); + rt64.shutdown(); } @@ -571,7 +529,7 @@ void ultramodern::init_events(RDRAM_ARG ultramodern::WindowHandle window_handle) events_context.rdram = rdram; events_context.sp.gfx_thread = std::thread{ gfx_thread_func, rdram, &gfx_thread_ready, window_handle }; events_context.sp.task_thread = std::thread{ task_thread_func, rdram, &task_thread_ready }; - + // Wait for the two sp threads to be ready before continuing to prevent the game from // running before we're able to handle RSP tasks. gfx_thread_ready.wait(); @@ -580,9 +538,11 @@ void ultramodern::init_events(RDRAM_ARG ultramodern::WindowHandle window_handle) ultramodern::RT64SetupResult setup_result = rt64_setup_result.load(); if (rt64_setup_result != ultramodern::RT64SetupResult::Success) { auto show_rt64_error = [](const std::string& msg) { - // TODO move recomp code out of ultramodern (message boxes). - recomp::message_box(("An error has been encountered on startup: " + msg).c_str()); + std::string error_msg = "An error has been encountered on startup: " + msg; + + ultramodern::error_handling::message_box(error_msg.c_str()); }; + const std::string driver_os_suffix = "\nPlease make sure your GPU drivers and your OS are up to date."; switch (rt64_setup_result) { case ultramodern::RT64SetupResult::DynamicLibrariesNotFound: diff --git a/ultramodern/src/mesgqueue.cpp b/ultramodern/src/mesgqueue.cpp index b13a3c0..b792bcd 100644 --- a/ultramodern/src/mesgqueue.cpp +++ b/ultramodern/src/mesgqueue.cpp @@ -4,7 +4,6 @@ #include "ultra64.h" #include "ultramodern.hpp" -#include "recomp.h" struct QueuedMessage { PTR(OSMesgQueue) mq; diff --git a/ultramodern/src/rsp.cpp b/ultramodern/src/rsp.cpp new file mode 100644 index 0000000..1594304 --- /dev/null +++ b/ultramodern/src/rsp.cpp @@ -0,0 +1,22 @@ +#include +#include + +#include "ultramodern/rsp.hpp" + +static ultramodern::rsp::callbacks_t rsp_callbacks {}; + +void ultramodern::rsp::set_callbacks(const callbacks_t& callbacks) { + rsp_callbacks = callbacks; +} + +void ultramodern::rsp::init() { + if (rsp_callbacks.init != nullptr) { + rsp_callbacks.init(); + } +} + +bool ultramodern::rsp::run_task(RDRAM_ARG const OSTask* task) { + assert(rsp_callbacks.run_task != nullptr); + + return rsp_callbacks.run_task(PASS_RDRAM task); +} diff --git a/ultramodern/src/ultrainit.cpp b/ultramodern/src/ultrainit.cpp index 9517113..9dd19a2 100644 --- a/ultramodern/src/ultrainit.cpp +++ b/ultramodern/src/ultrainit.cpp @@ -1,6 +1,22 @@ #include "ultra64.h" #include "ultramodern.hpp" +void ultramodern::set_callbacks( + const rsp::callbacks_t& rsp_callbacks, + const audio_callbacks_t& audio_callbacks, + const input_callbacks_t& input_callbacks, + const gfx_callbacks_t& gfx_callbacks, + const events::callbacks_t& thread_callbacks, + const error_handling::callbacks_t& error_handling_callbacks +) { + ultramodern::rsp::set_callbacks(rsp_callbacks); + ultramodern::set_audio_callbacks(audio_callbacks); + (void)input_callbacks; // nothing yet + (void)gfx_callbacks; // nothing yet + ultramodern::events::set_callbacks(thread_callbacks); + ultramodern::error_handling::set_callbacks(error_handling_callbacks); +} + void ultramodern::preinit(RDRAM_ARG ultramodern::WindowHandle window_handle) { ultramodern::set_main_thread(); ultramodern::init_events(PASS_RDRAM window_handle);