Update modern runtime for mod support, add some exports and events in the patches

This commit is contained in:
Mr-Wiseguy 2024-09-02 12:01:22 -04:00
parent d4a8cd351e
commit 5a8de31e82
12 changed files with 50 additions and 21 deletions

@ -1 +1 @@
Subproject commit 0a538553330ea5fdb1673708704bb92a854241b9
Subproject commit 5699906f34fcc82905303092d081ad92aa74f926

View File

@ -14,3 +14,5 @@ data_reference_syms_files = [ "Zelda64RecompSyms/mm.us.rev1.datasyms.toml", "Zel
output_binary_path = "patches/patches.bin"
# Do not emit warnings for unpaired LO16 values, as clang produces many of them.
unpaired_lo16_warnings = false
# Allow exporting functions and events for mods to use.
allow_exports = true

View File

@ -67,10 +67,10 @@ RECOMP_PATCH void KaleidoSetup_Update(PlayState* play) {
void Sram_SyncWriteToFlash(SramContext* sramCtx, s32 curPage, s32 numPages);
void autosave_reset_timer();
void autosave_reset_timer_slow();
void recomp_reset_autosave_timer();
void recomp_reset_autosave_timer_slow();
void do_autosave(PlayState* play) {
RECOMP_EXPORT void recomp_do_autosave(PlayState* play) {
// Transfer the scene flags into the cycle flags.
Play_SaveCycleSceneFlags(&play->state);
// Transfer the cycle flags into the save buffer. Logic copied from func_8014546C.
@ -176,7 +176,7 @@ RECOMP_PATCH void func_8014546C(SramContext* sramCtx) {
// @recomp Delete the owl save.
delete_owl_save(sramCtx, gSaveContext.fileNum);
// @recomp Reset the autosave timer.
autosave_reset_timer();
recomp_reset_autosave_timer();
for (i = 0; i < ARRAY_COUNT(gSaveContext.cycleSceneFlags); i++) {
gSaveContext.save.saveInfo.permanentSceneFlags[i].chest = gSaveContext.cycleSceneFlags[i].chest;
gSaveContext.save.saveInfo.permanentSceneFlags[i].switch0 = gSaveContext.cycleSceneFlags[i].switch0;
@ -344,11 +344,11 @@ void draw_autosave_icon(PlayState* play) {
CLOSE_DISPS(play->state.gfxCtx);
}
void show_autosave_icon() {
RECOMP_EXPORT void recomp_show_autosave_icon() {
autosave_icon_counter = AUTOSAVE_ICON_TOTAL_FRAMES;
}
u32 recomp_autosave_interval() {
RECOMP_EXPORT u32 recomp_autosave_interval() {
return 2 * 60 * 1000;
}
@ -367,12 +367,12 @@ bool reached_final_three_hours() {
return false;
}
void autosave_reset_timer() {
RECOMP_EXPORT void recomp_reset_autosave_timer() {
last_autosave_time = osGetTime();
extra_autosave_delay_milliseconds = 0;
}
void autosave_reset_timer_slow() {
RECOMP_EXPORT void recomp_reset_autosave_timer_slow() {
// Set the most recent autosave time in the future to give extra time before an autosave triggers.
last_autosave_time = osGetTime();
extra_autosave_delay_milliseconds = 2 * 60 * 1000;
@ -425,20 +425,20 @@ void autosave_post_play_update(PlayState* play) {
frames_since_autosave_ready >= MIN_FRAMES_SINCE_READY &&
time_now - last_autosave_time > (OS_USEC_TO_CYCLES(1000 * (recomp_autosave_interval() + extra_autosave_delay_milliseconds)))
) {
do_autosave(play);
show_autosave_icon();
autosave_reset_timer();
recomp_do_autosave(play);
recomp_show_autosave_icon();
recomp_reset_autosave_timer();
}
}
else {
// Update the last autosave time to the current time to prevent autosaving immediately if autosaves are turned back on.
autosave_reset_timer();
recomp_reset_autosave_timer();
}
gCanPause = false;
}
void autosave_init() {
autosave_reset_timer_slow();
recomp_reset_autosave_timer_slow();
Lib_MemCpy(&prev_save_ctx, &gSaveContext, offsetof(SaveContext, fileNum));
}
@ -705,7 +705,7 @@ RECOMP_PATCH void Sram_ResetSaveFromMoonCrash(SramContext* sramCtx) {
gSaveContext.jinxTimer = 0;
// @recomp Use the slow autosave timer to give the player extra time to respond to the moon crashing to decide if they want to reload their autosave.
autosave_reset_timer_slow();
recomp_reset_autosave_timer_slow();
}

View File

@ -4,6 +4,11 @@
#define RECOMP_EXPORT __attribute__((section(".recomp_export")))
#define RECOMP_PATCH __attribute__((section(".recomp_patch")))
#define RECOMP_FORCE_PATCH __attribute__((section(".recomp_force_patch")))
#define RECOMP_DECLARE_EVENT(func) \
_Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Wunused-parameter\"") \
__attribute__((noinline, weak, used, section(".recomp_event"))) void func {} \
_Pragma("GCC diagnostic pop")
// TODO fix renaming symbols in patch recompilation
#define osCreateMesgQueue osCreateMesgQueue_recomp

View File

@ -1,5 +1,5 @@
RAMBASE = 0x80801000; /* Used to hold any new symbols */
EXTRA_RAM_SIZE = 0x01000000; /* Amount of extra ram allocated by recomp */
PATCH_RAM_END = 0x81000000; /* Amount of extra ram allocated by recomp */
MEMORY {
extram : ORIGIN = RAMBASE, LENGTH = 64M
@ -12,10 +12,11 @@ SECTIONS {
.text : { *(.text*) } >extram AT >rom
.recomp_patch : { *(.recomp_patch*) *(.recomp_force_patch*) } >extram AT >rom
.recomp_export : { *(.recomp_export*) } >extram AT >rom
.recomp_event : { *(.recomp_event*) } >extram AT >rom
.rodata : { *(.rodata*) } >extram AT >rom
.data : { *(.data*) } >extram AT >rom
.bss (NOLOAD) : { *(.bss*) *(COMMON) } >extram
ASSERT(. < RAMBASE + EXTRA_RAM_SIZE, "Maxed out recomp extra ram")
ASSERT(. <= PATCH_RAM_END, "Maxed out recomp extra ram")
.reloc 0 : { *(.reloc*) }
.symtab 0 : { *(.symtab) }

View File

@ -4,6 +4,10 @@
extern Input D_801F6C18;
RECOMP_DECLARE_EVENT(recomp_on_play_main(PlayState* play));
RECOMP_DECLARE_EVENT(recomp_before_play_update(PlayState* play));
RECOMP_DECLARE_EVENT(recomp_after_play_update(PlayState* play));
void controls_play_update(PlayState* play) {
gSaveContext.options.zTargetSetting = recomp_get_targeting_mode();
}
@ -12,6 +16,7 @@ void controls_play_update(PlayState* play) {
RECOMP_PATCH void Play_Main(GameState* thisx) {
static Input* prevInput = NULL;
PlayState* this = (PlayState*)thisx;
recomp_on_play_main(this);
// @recomp
debug_play_update(this);
@ -32,7 +37,9 @@ RECOMP_PATCH void Play_Main(GameState* thisx) {
this->state.gfxCtx = NULL;
}
camera_pre_play_update(this);
recomp_before_play_update(this);
Play_Update(this);
recomp_after_play_update(this);
camera_post_play_update(this);
analog_cam_post_play_update(this);
autosave_post_play_update(this);

View File

@ -6,7 +6,7 @@ void* proutPrintf(void* dst, const char* fmt, size_t size) {
return (void*)1;
}
int recomp_printf(const char* fmt, ...) {
RECOMP_EXPORT int recomp_printf(const char* fmt, ...) {
va_list args;
va_start(args, fmt);

View File

@ -1266,7 +1266,7 @@ extern Gfx ovl_En_Tanron1_DL_001888[];
extern Gfx ovl_En_Tanron1_DL_001900[];
// @recomp Patched to interpolate the moths that circle torches.
void func_80BB5AAC(EnTanron1* this, PlayState* play) {
RECOMP_PATCH void func_80BB5AAC(EnTanron1* this, PlayState* play) {
EnTanron1Struct* ptrBase = &this->unk_160[0];
s16 i;
u8 flag = 0;

View File

@ -27,6 +27,7 @@
#include "zelda_render.h"
#include "ovl_patches.hpp"
#include "librecomp/game.hpp"
#include "librecomp/mods.hpp"
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
@ -327,6 +328,7 @@ std::vector<recomp::GameEntry> supported_games = {
.rom_hash = 0xEF18B4A9E2386169ULL,
.internal_name = "ZELDA MAJORA'S MASK",
.game_id = u8"mm.n64.us.1.0",
.mod_game_id = "mm",
.is_enabled = true,
.entrypoint_address = get_entrypoint_address(),
.entrypoint = recomp_entrypoint,
@ -568,6 +570,8 @@ int main(int argc, char** argv) {
fprintf(stderr, "Failed to load controller mappings: %s\n", SDL_GetError());
}
recomp::register_config_path(zelda64::get_app_folder_path());
// Register supported games and patches
for (const auto& game : supported_games) {
recomp::register_game(game);
@ -575,8 +579,6 @@ int main(int argc, char** argv) {
zelda64::register_overlays();
zelda64::register_patches();
recomp::register_config_path(zelda64::get_app_folder_path());
zelda64::load_config();
recomp::rsp::callbacks_t rsp_callbacks{
@ -619,7 +621,10 @@ int main(int argc, char** argv) {
.get_game_thread_name = zelda64::get_game_thread_name,
};
recomp::mods::scan_mods();
recomp::start(
64 * 1024 * 1024, // 64MB to have plenty of room for loading mods
{},
rsp_callbacks,
renderer_callbacks,

View File

@ -7,4 +7,6 @@
void zelda64::register_patches() {
recomp::overlays::register_patches(mm_patches_bin, sizeof(mm_patches_bin), section_table, ARRLEN(section_table));
recomp::overlays::register_base_exports(export_table);
recomp::overlays::register_base_events(event_name_table);
}

View File

@ -1287,6 +1287,12 @@ void draw_hook(RT64::RenderCommandList* command_list, RT64::RenderFramebuffer* s
static recompui::Menu prev_menu = recompui::Menu::None;
recompui::Menu cur_menu = open_menu.load();
// Return to the launcher if no menu is open and the game isn't started.
if (cur_menu == recompui::Menu::None && !ultramodern::is_game_started()) {
cur_menu = recompui::Menu::Launcher;
recompui::set_current_menu(cur_menu);
}
if (reload_sheets) {
ui_context->rml.load_documents();
prev_menu = recompui::Menu::None;

View File

@ -5,6 +5,7 @@ entrypoint = 0x80080000
# Paths are relative to the location of this config file.
output_func_path = "RecompiledFuncs"
relocatable_sections_path = "overlays.us.rev1.txt"
# elf_path = "mm.us.rev1.rom_uncompressed.elf"
symbols_file_path = "Zelda64RecompSyms/mm.us.rev1.syms.toml"
rom_file_path = "mm.us.rev1.rom_uncompressed.z64"