aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorneonloop2023-01-25 07:35:46 +0000
committerneonloop2023-01-25 07:35:46 +0000
commit4188eb5b7c459df34fb11c3078d737a90dc56eeb (patch)
tree72f7c0d4341d39adc7b173eb116f591a29df4723
parentb90dbbdc967878dc461fefe78a8ef86886ae7a5a (diff)
downloadpicoarch-4188eb5b7c459df34fb11c3078d737a90dc56eeb.tar.gz
picoarch-4188eb5b7c459df34fb11c3078d737a90dc56eeb.tar.bz2
picoarch-4188eb5b7c459df34fb11c3078d737a90dc56eeb.zip
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
-rw-r--r--core.c7
-rw-r--r--core.h1
-rw-r--r--funkey/fk_instant_play.c61
-rw-r--r--funkey/fk_instant_play.h4
-rw-r--r--main.c70
-rw-r--r--main.h1
-rw-r--r--menu.c43
-rw-r--r--overrides.h2
-rw-r--r--overrides/mame2000.h2
9 files changed, 129 insertions, 62 deletions
diff --git a/core.c b/core.c
index 8dead78..34810a5 100644
--- a/core.c
+++ b/core.c
@@ -715,14 +715,17 @@ const char **core_extensions(void) {
}
void core_unload(void) {
- PA_INFO("Unloading core...\n");
-
if (current_core.initialized) {
core_unload_content();
current_core.retro_deinit();
current_core.initialized = false;
}
+}
+
+void core_close(void) {
+ PA_INFO("Unloading core...\n");
+ core_unload();
string_list_free(extensions);
extensions = NULL;
diff --git a/core.h b/core.h
index 2ec86b5..bc855d4 100644
--- a/core.h
+++ b/core.h
@@ -68,5 +68,6 @@ void core_apply_cheats(struct cheats *cheats);
void core_unload_content(void);
const char **core_extensions(void);
void core_unload(void);
+void core_close(void);
#endif
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 <signal.h>
#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++ */
diff --git a/main.c b/main.c
index e59f2fd..b4e19be 100644
--- a/main.c
+++ b/main.c
@@ -25,7 +25,6 @@ char save_template_path[MAX_PATH];
#ifdef FUNKEY_S
#include "funkey/fk_menu.h"
#include "funkey/fk_instant_play.h"
-static bool instant_play = false;
bool should_suspend = false;
#endif
@@ -610,10 +609,6 @@ int state_resume(void) {
int main(int argc, char **argv) {
char content_path[MAX_PATH];
-#ifdef FUNKEY_S
- char autosave_path[MAX_PATH];
-#endif
-
if (argc > 1) {
if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
@@ -662,20 +657,6 @@ int main(int argc, char **argv) {
load_config();
core_load();
- if (core_load_content(content)) {
- quit(-1);
- }
-
- load_config_keys();
-
-#ifdef MMENU
-
- mmenu = dlopen("libmmenu.so", RTLD_LAZY);
- if (mmenu) {
- ResumeSlot_t ResumeSlot = (ResumeSlot_t)dlsym(mmenu, "ResumeSlot");
- if (ResumeSlot) resume_slot = ResumeSlot();
- }
-#endif
#ifdef FUNKEY_S
if (IMG_Init(IMG_INIT_JPG | IMG_INIT_PNG | IMG_INIT_TIF | IMG_INIT_WEBP) == 0) {
PA_ERROR("Error initializing SDL_Image\n");
@@ -686,30 +667,30 @@ int main(int argc, char **argv) {
PA_ERROR("Error initializing SDL_ttf\n");
quit(-1);
}
- FK_InitMenu();
+#endif
- 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;
- }
- }
+ if (core_load_content(content)) {
+ quit(-1);
}
- instant_play = false;
- FK_InitInstantPlay(argc, argv);
+ load_config_keys();
+
+#ifdef MMENU
+ mmenu = dlopen("libmmenu.so", RTLD_LAZY);
+ if (mmenu) {
+ ResumeSlot_t ResumeSlot = (ResumeSlot_t)dlsym(mmenu, "ResumeSlot");
+ if (ResumeSlot) resume_slot = ResumeSlot();
+ }
+
+ state_resume();
#endif
+
show_startup_message();
- state_resume();
#ifdef FUNKEY_S
- remove(autosave_path);
- remove_config(CONFIG_TYPE_AUTO);
+ FK_InitMenu();
+ FK_Resume();
+ FK_InitInstantPlay(argc, argv);
#endif
do {
@@ -731,21 +712,20 @@ int main(int argc, char **argv) {
return quit(0);
}
-int quit(int code) {
- menu_finish();
-
+void finish(void) {
#ifdef FUNKEY_S
- if (current_core.initialized && state_allowed()) {
- state_slot = AUTOSAVE_SLOT;
- state_write();
- }
-
+ FK_Autosave();
FK_EndMenu();
TTF_Quit();
IMG_Quit();
#endif
- core_unload();
+ menu_finish();
+ core_close();
plat_finish();
+}
+
+int quit(int code) {
+ finish();
exit(code);
}
diff --git a/main.h b/main.h
index f4fc12a..ca7ac07 100644
--- a/main.h
+++ b/main.h
@@ -65,6 +65,7 @@ int remove_config(config_type config_type);
void handle_emu_action(emu_action action);
void pa_log(enum retro_log_level level, const char *fmt, ...);
void pa_track_render(void);
+void finish(void);
int quit(int code);
#endif /* __MAIN_H__ */
diff --git a/menu.c b/menu.c
index fde7c10..bd00e52 100644
--- a/menu.c
+++ b/menu.c
@@ -8,12 +8,18 @@
#include "scale.h"
#include "util.h"
+#ifdef FUNKEY_S
+#include "funkey/fk_instant_play.h"
+#endif
+
static int drew_alt_bg = 0;
static char cores_path[MAX_PATH];
static struct dirent **corelist = NULL;
static int corelist_len = 0;
+static const char *new_fname = NULL;
+
#define MENU_ALIGN_LEFT 0
#define MENU_X2 0
@@ -306,7 +312,29 @@ static int menu_loop_select_content(int id, int keys) {
if (fname == NULL)
return -1;
- core_unload_content();
+ new_fname = fname;
+
+ return 1;
+}
+
+static void load_new_content(const char *fname) {
+ const struct core_override *override = get_overrides();
+
+ if (!override || override->needs_reopen) {
+#ifdef FUNKEY_S
+ FK_LoadNewGame(fname);
+ /* Does not return */
+#else
+ core_close();
+ core_open(core_path);
+#endif
+ } else {
+#ifdef FUNKEY_S
+ FK_Autosave();
+#endif
+ core_unload();
+ }
+ core_load();
content = content_init(fname);
if (!content) {
@@ -328,7 +356,9 @@ static int menu_loop_select_content(int id, int keys) {
state_resume();
}
- return 1;
+#ifdef FUNKEY_S
+ FK_Resume();
+#endif
}
static int menu_loop_disc(int id, int keys)
@@ -685,7 +715,6 @@ void menu_loop(void)
{
static int sel = 0;
bool needs_disc_ctrl = disc_get_count() > 1;
- const struct core_override *override = get_overrides();
plat_video_menu_enter(1);
@@ -697,9 +726,6 @@ void menu_loop(void)
me_enable(e_menu_main, MA_MAIN_DISC_CTRL, needs_disc_ctrl);
- if (override)
- me_enable(e_menu_main, MA_MAIN_CONTENT_SEL, !override->block_load_content);
-
#ifdef MMENU
if (state_allowed()) {
me_enable(e_menu_main, MA_MAIN_SAVE_STATE, mmenu == NULL);
@@ -712,6 +738,11 @@ void menu_loop(void)
while (in_menu_wait_any(NULL, 50) & (PBTN_MENU|PBTN_MOK|PBTN_MBACK))
;
+ if (new_fname) {
+ load_new_content(new_fname);
+ new_fname = NULL;
+ }
+
/* Force the hud to clear */
plat_video_set_msg(NULL, 0, 0);
plat_video_menu_leave();
diff --git a/overrides.h b/overrides.h
index fd1f9c2..19efdf3 100644
--- a/overrides.h
+++ b/overrides.h
@@ -35,7 +35,7 @@ struct core_override {
me_bind_action* emu_actions;
const size_t emu_action_size;
const struct core_override_option* options;
- int block_load_content;
+ int needs_reopen;
};
#define CORE_OVERRIDE(override, key, fallback) ((override && override->key) ? (override->key) : (fallback))
diff --git a/overrides/mame2000.h b/overrides/mame2000.h
index 81af3fc..a74da1f 100644
--- a/overrides/mame2000.h
+++ b/overrides/mame2000.h
@@ -80,5 +80,5 @@ const struct core_override_fast_forward mame2000_fast_forward = {
.emu_actions = mame2000_emu_actions, \
.emu_action_size = array_size(mame2000_emu_actions), \
.options = mame2000_core_option_overrides, \
- .block_load_content = 1 \
+ .needs_reopen = 1, \
}