From 4188eb5b7c459df34fb11c3078d737a90dc56eeb Mon Sep 17 00:00:00 2001 From: neonloop Date: Wed, 25 Jan 2023 07:35:46 +0000 Subject: Fixes load new content Cores do not always clean up on unload content, deinit and reinit is more reliable. Some cores do not even clean up on deinit and reinit, need all statics reinitialized. On many platforms dlclose / dlopen will work. FunKey uses musl libc where dlclose is no-op, so instead will exec again with current core and new content path. Overrides decide whether easy or hard clean up is needed. Assume unknown cores need hard cleanup, otherwise specified by "needs_reopen" override. Also - FunKey will now autosave and resume during load new content - Load new content deferred until after menu responds to keypress, otherwise key release can be missed and menu seems stuck --- funkey/fk_instant_play.c | 61 ++++++++++++++++++++++++++++++++++++++++++------ funkey/fk_instant_play.h | 4 ++++ 2 files changed, 58 insertions(+), 7 deletions(-) (limited to 'funkey') diff --git a/funkey/fk_instant_play.c b/funkey/fk_instant_play.c index 8c8fc33..638e0fd 100644 --- a/funkey/fk_instant_play.c +++ b/funkey/fk_instant_play.c @@ -41,6 +41,7 @@ #endif static char *prog_name; +int instant_play = 0; /* Handler for SIGUSR1, caused by closing the console */ static void handle_sigusr1(int signal) @@ -77,12 +78,7 @@ void FK_Suspend(void) FILE *fp; char pidcmd[100]; - state_slot = AUTOSAVE_SLOT; - if(state_write()) { - printf("Save failed\n"); - state_slot = 0; - } - + FK_Autosave(); sram_write(); save_config(CONFIG_TYPE_AUTO); @@ -108,10 +104,61 @@ void FK_Suspend(void) exit(0); } +void FK_LoadNewGame(const char *fname) +{ + char prog_path[PATH_MAX]; + realpath(prog_name, prog_path); + + /* FunKey uses musl libc so dlclose is no-op. If core depends on + * all statics being reset, FunKey cannot reload it. Instead, + * re-exec with new content. */ + PA_INFO("Restarting with %s %s %s\n", prog_path, core_path, fname); + finish(); + execl(prog_path, prog_name, core_path, fname, NULL); + + /* Should not be reached */ + PA_ERROR("Failed to load game\n"); + + /* Exit application */ + exit(0); +} + +void FK_Autosave(void) +{ + if (state_allowed()) { + int prev_state_slot = state_slot; + state_slot = AUTOSAVE_SLOT; + state_write(); + state_slot = prev_state_slot; + } +} + +void FK_Resume(void) +{ + char autosave_path[MAX_PATH]; + + state_file_name(autosave_path, MAX_PATH, AUTOSAVE_SLOT); + if (access(autosave_path, F_OK) == 0) { + if (instant_play) { + resume_slot = AUTOSAVE_SLOT; + } else { + SDL_Surface *screen = SDL_GetVideoSurface(); + int resume = FK_RunResumeMenu(screen); + if (resume == RESUME_YES) { + resume_slot = AUTOSAVE_SLOT; + } + } + } + + instant_play = false; + state_resume(); + + remove(autosave_path); + remove_config(CONFIG_TYPE_AUTO); +} void FK_InitInstantPlay(int argc, char **argv) { prog_name = argv[0]; signal(SIGUSR1, handle_sigusr1); } - diff --git a/funkey/fk_instant_play.h b/funkey/fk_instant_play.h index 5185065..2ed3c71 100644 --- a/funkey/fk_instant_play.h +++ b/funkey/fk_instant_play.h @@ -39,8 +39,12 @@ extern "C" { #include #define AUTOSAVE_SLOT 99 +extern int instant_play; extern void FK_InitInstantPlay(int argc, char **argv); +extern void FK_LoadNewGame(const char *fname); +extern void FK_Autosave(void); +extern void FK_Resume(void); extern void FK_Suspend(void); /* Ends C function definitions when using C++ */ -- cgit v1.2.3