Update modern runtime for mod support, add some exports and events in the patches
This commit is contained in:
parent
cf1943fe6a
commit
ba39a73dca
|
@ -1 +1 @@
|
||||||
Subproject commit 0a538553330ea5fdb1673708704bb92a854241b9
|
Subproject commit 5699906f34fcc82905303092d081ad92aa74f926
|
|
@ -14,3 +14,5 @@ data_reference_syms_files = [ "Zelda64RecompSyms/mm.us.rev1.datasyms.toml", "Zel
|
||||||
output_binary_path = "patches/patches.bin"
|
output_binary_path = "patches/patches.bin"
|
||||||
# Do not emit warnings for unpaired LO16 values, as clang produces many of them.
|
# Do not emit warnings for unpaired LO16 values, as clang produces many of them.
|
||||||
unpaired_lo16_warnings = false
|
unpaired_lo16_warnings = false
|
||||||
|
# Allow exporting functions and events for mods to use.
|
||||||
|
allow_exports = true
|
||||||
|
|
|
@ -67,10 +67,10 @@ RECOMP_PATCH void KaleidoSetup_Update(PlayState* play) {
|
||||||
|
|
||||||
void Sram_SyncWriteToFlash(SramContext* sramCtx, s32 curPage, s32 numPages);
|
void Sram_SyncWriteToFlash(SramContext* sramCtx, s32 curPage, s32 numPages);
|
||||||
|
|
||||||
void autosave_reset_timer();
|
void recomp_reset_autosave_timer();
|
||||||
void autosave_reset_timer_slow();
|
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.
|
// Transfer the scene flags into the cycle flags.
|
||||||
Play_SaveCycleSceneFlags(&play->state);
|
Play_SaveCycleSceneFlags(&play->state);
|
||||||
// Transfer the cycle flags into the save buffer. Logic copied from func_8014546C.
|
// 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.
|
// @recomp Delete the owl save.
|
||||||
delete_owl_save(sramCtx, gSaveContext.fileNum);
|
delete_owl_save(sramCtx, gSaveContext.fileNum);
|
||||||
// @recomp Reset the autosave timer.
|
// @recomp Reset the autosave timer.
|
||||||
autosave_reset_timer();
|
recomp_reset_autosave_timer();
|
||||||
for (i = 0; i < ARRAY_COUNT(gSaveContext.cycleSceneFlags); i++) {
|
for (i = 0; i < ARRAY_COUNT(gSaveContext.cycleSceneFlags); i++) {
|
||||||
gSaveContext.save.saveInfo.permanentSceneFlags[i].chest = gSaveContext.cycleSceneFlags[i].chest;
|
gSaveContext.save.saveInfo.permanentSceneFlags[i].chest = gSaveContext.cycleSceneFlags[i].chest;
|
||||||
gSaveContext.save.saveInfo.permanentSceneFlags[i].switch0 = gSaveContext.cycleSceneFlags[i].switch0;
|
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);
|
CLOSE_DISPS(play->state.gfxCtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void show_autosave_icon() {
|
RECOMP_EXPORT void recomp_show_autosave_icon() {
|
||||||
autosave_icon_counter = AUTOSAVE_ICON_TOTAL_FRAMES;
|
autosave_icon_counter = AUTOSAVE_ICON_TOTAL_FRAMES;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 recomp_autosave_interval() {
|
RECOMP_EXPORT u32 recomp_autosave_interval() {
|
||||||
return 2 * 60 * 1000;
|
return 2 * 60 * 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -367,12 +367,12 @@ bool reached_final_three_hours() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void autosave_reset_timer() {
|
RECOMP_EXPORT void recomp_reset_autosave_timer() {
|
||||||
last_autosave_time = osGetTime();
|
last_autosave_time = osGetTime();
|
||||||
extra_autosave_delay_milliseconds = 0;
|
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.
|
// Set the most recent autosave time in the future to give extra time before an autosave triggers.
|
||||||
last_autosave_time = osGetTime();
|
last_autosave_time = osGetTime();
|
||||||
extra_autosave_delay_milliseconds = 2 * 60 * 1000;
|
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 &&
|
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)))
|
time_now - last_autosave_time > (OS_USEC_TO_CYCLES(1000 * (recomp_autosave_interval() + extra_autosave_delay_milliseconds)))
|
||||||
) {
|
) {
|
||||||
do_autosave(play);
|
recomp_do_autosave(play);
|
||||||
show_autosave_icon();
|
recomp_show_autosave_icon();
|
||||||
autosave_reset_timer();
|
recomp_reset_autosave_timer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Update the last autosave time to the current time to prevent autosaving immediately if autosaves are turned back on.
|
// 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;
|
gCanPause = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void autosave_init() {
|
void autosave_init() {
|
||||||
autosave_reset_timer_slow();
|
recomp_reset_autosave_timer_slow();
|
||||||
Lib_MemCpy(&prev_save_ctx, &gSaveContext, offsetof(SaveContext, fileNum));
|
Lib_MemCpy(&prev_save_ctx, &gSaveContext, offsetof(SaveContext, fileNum));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -705,7 +705,7 @@ RECOMP_PATCH void Sram_ResetSaveFromMoonCrash(SramContext* sramCtx) {
|
||||||
gSaveContext.jinxTimer = 0;
|
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.
|
// @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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,11 @@
|
||||||
#define RECOMP_EXPORT __attribute__((section(".recomp_export")))
|
#define RECOMP_EXPORT __attribute__((section(".recomp_export")))
|
||||||
#define RECOMP_PATCH __attribute__((section(".recomp_patch")))
|
#define RECOMP_PATCH __attribute__((section(".recomp_patch")))
|
||||||
#define RECOMP_FORCE_PATCH __attribute__((section(".recomp_force_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
|
// TODO fix renaming symbols in patch recompilation
|
||||||
#define osCreateMesgQueue osCreateMesgQueue_recomp
|
#define osCreateMesgQueue osCreateMesgQueue_recomp
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
RAMBASE = 0x80801000; /* Used to hold any new symbols */
|
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 {
|
MEMORY {
|
||||||
extram : ORIGIN = RAMBASE, LENGTH = 64M
|
extram : ORIGIN = RAMBASE, LENGTH = 64M
|
||||||
|
@ -12,10 +12,11 @@ SECTIONS {
|
||||||
.text : { *(.text*) } >extram AT >rom
|
.text : { *(.text*) } >extram AT >rom
|
||||||
.recomp_patch : { *(.recomp_patch*) *(.recomp_force_patch*) } >extram AT >rom
|
.recomp_patch : { *(.recomp_patch*) *(.recomp_force_patch*) } >extram AT >rom
|
||||||
.recomp_export : { *(.recomp_export*) } >extram AT >rom
|
.recomp_export : { *(.recomp_export*) } >extram AT >rom
|
||||||
|
.recomp_event : { *(.recomp_event*) } >extram AT >rom
|
||||||
.rodata : { *(.rodata*) } >extram AT >rom
|
.rodata : { *(.rodata*) } >extram AT >rom
|
||||||
.data : { *(.data*) } >extram AT >rom
|
.data : { *(.data*) } >extram AT >rom
|
||||||
.bss (NOLOAD) : { *(.bss*) *(COMMON) } >extram
|
.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*) }
|
.reloc 0 : { *(.reloc*) }
|
||||||
.symtab 0 : { *(.symtab) }
|
.symtab 0 : { *(.symtab) }
|
||||||
|
|
|
@ -4,6 +4,10 @@
|
||||||
|
|
||||||
extern Input D_801F6C18;
|
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) {
|
void controls_play_update(PlayState* play) {
|
||||||
gSaveContext.options.zTargetSetting = recomp_get_targeting_mode();
|
gSaveContext.options.zTargetSetting = recomp_get_targeting_mode();
|
||||||
}
|
}
|
||||||
|
@ -12,6 +16,7 @@ void controls_play_update(PlayState* play) {
|
||||||
RECOMP_PATCH void Play_Main(GameState* thisx) {
|
RECOMP_PATCH void Play_Main(GameState* thisx) {
|
||||||
static Input* prevInput = NULL;
|
static Input* prevInput = NULL;
|
||||||
PlayState* this = (PlayState*)thisx;
|
PlayState* this = (PlayState*)thisx;
|
||||||
|
recomp_on_play_main(this);
|
||||||
|
|
||||||
// @recomp
|
// @recomp
|
||||||
debug_play_update(this);
|
debug_play_update(this);
|
||||||
|
@ -32,7 +37,9 @@ RECOMP_PATCH void Play_Main(GameState* thisx) {
|
||||||
this->state.gfxCtx = NULL;
|
this->state.gfxCtx = NULL;
|
||||||
}
|
}
|
||||||
camera_pre_play_update(this);
|
camera_pre_play_update(this);
|
||||||
|
recomp_before_play_update(this);
|
||||||
Play_Update(this);
|
Play_Update(this);
|
||||||
|
recomp_after_play_update(this);
|
||||||
camera_post_play_update(this);
|
camera_post_play_update(this);
|
||||||
analog_cam_post_play_update(this);
|
analog_cam_post_play_update(this);
|
||||||
autosave_post_play_update(this);
|
autosave_post_play_update(this);
|
||||||
|
|
|
@ -6,7 +6,7 @@ void* proutPrintf(void* dst, const char* fmt, size_t size) {
|
||||||
return (void*)1;
|
return (void*)1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int recomp_printf(const char* fmt, ...) {
|
RECOMP_EXPORT int recomp_printf(const char* fmt, ...) {
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "zelda_render.h"
|
#include "zelda_render.h"
|
||||||
#include "ovl_patches.hpp"
|
#include "ovl_patches.hpp"
|
||||||
#include "librecomp/game.hpp"
|
#include "librecomp/game.hpp"
|
||||||
|
#include "librecomp/mods.hpp"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
@ -327,6 +328,7 @@ std::vector<recomp::GameEntry> supported_games = {
|
||||||
.rom_hash = 0xEF18B4A9E2386169ULL,
|
.rom_hash = 0xEF18B4A9E2386169ULL,
|
||||||
.internal_name = "ZELDA MAJORA'S MASK",
|
.internal_name = "ZELDA MAJORA'S MASK",
|
||||||
.game_id = u8"mm.n64.us.1.0",
|
.game_id = u8"mm.n64.us.1.0",
|
||||||
|
.mod_game_id = "mm",
|
||||||
.is_enabled = true,
|
.is_enabled = true,
|
||||||
.entrypoint_address = get_entrypoint_address(),
|
.entrypoint_address = get_entrypoint_address(),
|
||||||
.entrypoint = recomp_entrypoint,
|
.entrypoint = recomp_entrypoint,
|
||||||
|
@ -568,6 +570,8 @@ int main(int argc, char** argv) {
|
||||||
fprintf(stderr, "Failed to load controller mappings: %s\n", SDL_GetError());
|
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
|
// Register supported games and patches
|
||||||
for (const auto& game : supported_games) {
|
for (const auto& game : supported_games) {
|
||||||
recomp::register_game(game);
|
recomp::register_game(game);
|
||||||
|
@ -575,8 +579,6 @@ int main(int argc, char** argv) {
|
||||||
|
|
||||||
zelda64::register_overlays();
|
zelda64::register_overlays();
|
||||||
zelda64::register_patches();
|
zelda64::register_patches();
|
||||||
|
|
||||||
recomp::register_config_path(zelda64::get_app_folder_path());
|
|
||||||
zelda64::load_config();
|
zelda64::load_config();
|
||||||
|
|
||||||
recomp::rsp::callbacks_t rsp_callbacks{
|
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,
|
.get_game_thread_name = zelda64::get_game_thread_name,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
recomp::mods::scan_mods();
|
||||||
|
|
||||||
recomp::start(
|
recomp::start(
|
||||||
|
64 * 1024 * 1024, // 64MB to have plenty of room for loading mods
|
||||||
{},
|
{},
|
||||||
rsp_callbacks,
|
rsp_callbacks,
|
||||||
renderer_callbacks,
|
renderer_callbacks,
|
||||||
|
|
|
@ -7,4 +7,6 @@
|
||||||
|
|
||||||
void zelda64::register_patches() {
|
void zelda64::register_patches() {
|
||||||
recomp::overlays::register_patches(mm_patches_bin, sizeof(mm_patches_bin), section_table, ARRLEN(section_table));
|
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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1287,6 +1287,12 @@ void draw_hook(RT64::RenderCommandList* command_list, RT64::RenderFramebuffer* s
|
||||||
static recompui::Menu prev_menu = recompui::Menu::None;
|
static recompui::Menu prev_menu = recompui::Menu::None;
|
||||||
recompui::Menu cur_menu = open_menu.load();
|
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) {
|
if (reload_sheets) {
|
||||||
ui_context->rml.load_documents();
|
ui_context->rml.load_documents();
|
||||||
prev_menu = recompui::Menu::None;
|
prev_menu = recompui::Menu::None;
|
||||||
|
|
|
@ -5,6 +5,7 @@ entrypoint = 0x80080000
|
||||||
# Paths are relative to the location of this config file.
|
# Paths are relative to the location of this config file.
|
||||||
output_func_path = "RecompiledFuncs"
|
output_func_path = "RecompiledFuncs"
|
||||||
relocatable_sections_path = "overlays.us.rev1.txt"
|
relocatable_sections_path = "overlays.us.rev1.txt"
|
||||||
|
# elf_path = "mm.us.rev1.rom_uncompressed.elf"
|
||||||
symbols_file_path = "Zelda64RecompSyms/mm.us.rev1.syms.toml"
|
symbols_file_path = "Zelda64RecompSyms/mm.us.rev1.syms.toml"
|
||||||
rom_file_path = "mm.us.rev1.rom_uncompressed.z64"
|
rom_file_path = "mm.us.rev1.rom_uncompressed.z64"
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue