From 6a9ca41970c67b0224543cb1888cd0248d208aa1 Mon Sep 17 00:00:00 2001 From: Maximilian Mader Date: Mon, 14 Oct 2019 16:01:51 +0200 Subject: [PATCH] [GTK3] Allow switching the emulated model --- gtk3/main.c | 95 +++++++++++++++++++++++++------------ gtk3/main.h | 23 ++++----- gtk3/resources/ui/window.ui | 4 +- gtk3/settings.c | 42 ++++++++++++++++ gtk3/settings.h | 4 ++ 5 files changed, 120 insertions(+), 48 deletions(-) diff --git a/gtk3/main.c b/gtk3/main.c index 976ee1e..2b15f24 100644 --- a/gtk3/main.c +++ b/gtk3/main.c @@ -38,7 +38,7 @@ static GtkWindow *printer; static shader_t shader; -static GuiData gui_data = { NULL }; +static GuiData gui_data = { { NULL }, NULL }; static GB_gameboy_t gb; static uint32_t *image_buffers[3]; static unsigned char current_buffer; @@ -92,6 +92,10 @@ static const GActionEntry app_entries[] = { }; int main(int argc, char *argv[]) { + // initialize GB_model_t to invalid value + gui_data.cli_options.model = -1; + gui_data.prev_model = -1; + // Create our GApplication and tell GTK that we are able to handle files main_application = gtk_application_new(APP_ID, G_APPLICATION_NON_UNIQUE | G_APPLICATION_HANDLES_OPEN); @@ -99,9 +103,9 @@ int main(int argc, char *argv[]) { GOptionEntry entries[] = { { "version", 'v', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, NULL, "Show the application version", NULL }, { "fullscreen", 'f', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, NULL, "Start in fullscreen mode", NULL }, - { "bootrom", 'b', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, &gui_data.boot_rom_path, "Path to the boot ROM to use", "" }, + { "bootrom", 'b', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, &gui_data.cli_options.boot_rom_path, "Path to the boot ROM to use", "" }, { "model", 'm', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, NULL, "Override the model type to emulate", "" }, - { "config", 'c', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, &gui_data.config_path, "Override the path of the configuration file", "" }, + { "config", 'c', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, &gui_data.cli_options.config_path, "Override the path of the configuration file", "" }, { NULL } }; // Setup our command line information @@ -134,7 +138,7 @@ static gint handle_local_options(GApplication *app, GVariantDict *options, gpoin } if (g_variant_dict_lookup(options, "fullscreen", "b", &count)) { - gui_data->fullscreen = true; + gui_data->cli_options.fullscreen = true; } // Handle model override @@ -145,42 +149,42 @@ static gint handle_local_options(GApplication *app, GVariantDict *options, gpoin // TODO: Synchronize with GB_model_t (Core/gb.h) if (g_str_has_prefix(model_name, "DMG")) { if (g_str_has_suffix(model_name, "-B") || g_strcmp0(model_name, "DMG") == 0) { - gui_data->model = GB_MODEL_DMG_B; + gui_data->cli_options.model = GB_MODEL_DMG_B; } else { - gui_data->model = GB_MODEL_DMG_B; + gui_data->cli_options.model = GB_MODEL_DMG_B; g_printerr("Unsupported revision: %s\nFalling back to DMG-B", model_name); } } else if (g_str_has_prefix(model_name, "SGB")) { if (g_str_has_suffix(model_name, "-NTSC") || g_strcmp0(model_name, "SGB") == 0) { - gui_data->model = GB_MODEL_SGB; + gui_data->cli_options.model = GB_MODEL_SGB; } else if (g_str_has_suffix(model_name, "-PAL")) { - gui_data->model = GB_MODEL_SGB | GB_MODEL_PAL_BIT; + gui_data->cli_options.model = GB_MODEL_SGB | GB_MODEL_PAL_BIT; } else if (g_str_has_suffix(model_name, "2")) { - gui_data->model = GB_MODEL_SGB2; + gui_data->cli_options.model = GB_MODEL_SGB2; } else { - gui_data->model = GB_MODEL_SGB2; + gui_data->cli_options.model = GB_MODEL_SGB2; g_printerr("Unsupported revision: %s\nFalling back to SGB2", model_name); } } else if (g_str_has_prefix(model_name, "CGB")) { if (g_str_has_suffix(model_name, "-C")) { - gui_data->model = GB_MODEL_CGB_C; + gui_data->cli_options.model = GB_MODEL_CGB_C; } else if (g_str_has_suffix(model_name, "-E") || g_strcmp0(model_name, "CGB") == 0) { - gui_data->model = GB_MODEL_CGB_E; + gui_data->cli_options.model = GB_MODEL_CGB_E; } else { - gui_data->model = GB_MODEL_CGB_E; + gui_data->cli_options.model = GB_MODEL_CGB_E; g_printerr("Unsupported revision: %s\nFalling back to CGB-E", model_name); } } else if (g_str_has_prefix(model_name, "AGB")) { - gui_data->model = GB_MODEL_AGB; + gui_data->cli_options.model = GB_MODEL_AGB; } else { g_printerr("Unknown model: %s\n", model_name); @@ -323,6 +327,28 @@ static gboolean init_audio() { return TRUE; } +static GB_model_t get_model() { + if (gui_data.cli_options.model != -1) { + return gui_data.cli_options.model; + } + + GAction *action = g_action_map_lookup_action(G_ACTION_MAP(main_application), "change_model"); + GVariant *value = g_action_get_state(action); + const gchar *family = g_variant_get_string(value, NULL); + + if (g_strcmp0(family, "DMG") == 0) { + return get_dmg_model(); + } + else if (g_strcmp0(family, "AGB") == 0) { + return GB_MODEL_AGB; + } + else if (g_strcmp0(family, "SGB") == 0) { + return get_sgb_model(); + } + + return get_cgb_model(); +} + static void gb_audio_callback(GB_gameboy_t *gb, GB_sample_t *sample) { if (turbo_down) { static unsigned skip = 0; @@ -620,7 +646,7 @@ static void startup(GApplication *app, gpointer gui_data_gptr) { preferences = GTK_WINDOW(get_object("preferences")); g_signal_connect(preferences, "realize", G_CALLBACK(on_preferences_realize), (gpointer) builder); - init_settings(gui_data->config_path, preferences); + init_settings(gui_data->cli_options.config_path, preferences); vram_viewer = GTK_WINDOW(get_object("vram_viewer")); memory_viewer = GTK_WINDOW(get_object("memory_viewer")); @@ -745,7 +771,7 @@ static void activate(GApplication *app, gpointer gui_data_gptr) { gtk_text_buffer_create_tag(text_buf, "underline", "underline", PANGO_UNDERLINE_SINGLE, "underline-set", TRUE, NULL); gtk_text_buffer_create_tag(text_buf, "dashed_underline", "underline", PANGO_UNDERLINE_DOUBLE, "underline-set", TRUE, NULL); - if (gui_data->fullscreen) { + if (gui_data->cli_options.fullscreen) { gtk_window_fullscreen(GTK_WINDOW(main_window)); } @@ -953,8 +979,8 @@ static void on_model_changed(GSimpleAction *action, GVariant *value, gpointer us switch (result) { case GTK_RESPONSE_YES: - g_print("TODO: RESET!\n"); g_simple_action_set_state(action, value); + reset(&gui_data); break; default: // Action has been canceled @@ -1805,12 +1831,8 @@ static gpointer run_thread(gpointer gui_data_gptr) { static void init(GuiData *gui_data) { if (GB_is_inited(&gb)) return; - g_print("init: %p\n", g_thread_self()); - GB_model_t prev_model = GB_get_model(&gb); - gui_data->model = gui_data->model? gui_data->model : GB_MODEL_CGB_E; // TODO: Model from config - - GB_init(&gb, gui_data->model); + GB_init(&gb, get_model()); update_window_geometry(); GB_set_vblank_callback(&gb, vblank); @@ -1828,22 +1850,23 @@ static void init(GuiData *gui_data) { } static void load_boot_rom(GuiData *gui_data) { - GError *error; - char *boot_rom_path; - char *boot_rom_name; - GBytes *boot_rom_f; + GError *error = NULL; + char *boot_rom_path = NULL; + char *boot_rom_name = NULL; + GBytes *boot_rom_f = NULL; const guchar *boot_rom_data; gsize boot_rom_size; - if (gui_data->boot_rom_path != NULL) { - g_print("Trying to load boot ROM from %s\n", gui_data->boot_rom_path); - if (GB_load_boot_rom(&gb, gui_data->boot_rom_path)) { + if (gui_data->cli_options.boot_rom_path != NULL) { + g_print("Trying to load boot ROM from %s\n", gui_data->cli_options.boot_rom_path); + if (GB_load_boot_rom(&gb, gui_data->cli_options.boot_rom_path)) { g_printerr("Falling back to boot ROM from config\n"); goto config_boot_rom; } } else { config_boot_rom: - switch (gui_data->model) { + // TODO: Synchronize with GB_model_t (Core/gb.h) + switch (get_model()) { case GB_MODEL_DMG_B: boot_rom_name = "dmg_boot.bin"; break; @@ -1919,7 +1942,17 @@ static void stop(GuiData *gui_data) { } static void reset(GuiData *gui_data) { - GB_switch_model_and_reset(&gb, gui_data->model); + g_print("Reset: %d == %d\n", get_model(), gui_data->prev_model); + GB_model_t current_model = get_model(); + + if (gui_data->prev_model == -1 || gui_data->prev_model == current_model) { + GB_reset(&gb); + } + else { + GB_switch_model_and_reset(&gb, current_model); + } + + gui_data->prev_model = get_model(); GtkRequisition minimum_size; GtkRequisition natural_size; diff --git a/gtk3/main.h b/gtk3/main.h index bcd355b..80ef074 100644 --- a/gtk3/main.h +++ b/gtk3/main.h @@ -16,26 +16,19 @@ #include "settings.h" #include "shader.h" -enum generic_model { - MODEL_NONE, - MODEL_DMG, - MODEL_CGB, - MODEL_AGB, - MODEL_SGB, -}; - typedef struct GuiData { - bool fullscreen; - gint sample_rate; + struct CliOptionData { + gchar *config_path; + gchar *boot_rom_path; + gboolean fullscreen; + GB_model_t model; + } cli_options; GFile *file; - gchar *boot_rom_path; - gchar *config_path; + gint sample_rate; - enum generic_model generic_model; - GB_model_t model; - bool stopped; + GB_model_t prev_model; } GuiData; typedef struct{ diff --git a/gtk3/resources/ui/window.ui b/gtk3/resources/ui/window.ui index 133f45e..c02b8bb 100644 --- a/gtk3/resources/ui/window.ui +++ b/gtk3/resources/ui/window.ui @@ -331,12 +331,12 @@ Maximilian Mader https://github.com/max-m DMG_CPU_B DMG-CPU B - False + True DMG_CPU_C DMG-CPU C - True + False diff --git a/gtk3/settings.c b/gtk3/settings.c index a656846..c0a7123 100644 --- a/gtk3/settings.c +++ b/gtk3/settings.c @@ -300,3 +300,45 @@ void set_highpass_mode(GB_highpass_mode_t mode) { break; } } + +GB_model_t get_dmg_model(void) { + if (config.dmg_revision_name == NULL) goto default_value; + + // TODO: Synchronize with GB_model_t (Core/gb.h) + if (g_strcmp0(config.dmg_revision_name, "DMG_CPU_B") == 0) { + return GB_MODEL_DMG_B; + } + + default_value: return GB_MODEL_DMG_B; +} + +GB_model_t get_sgb_model(void) { + if (config.sgb_revision_name == NULL) goto default_value; + + // TODO: Synchronize with GB_model_t (Core/gb.h) + if (g_strcmp0(config.sgb_revision_name, "SGB1_NTSC") == 0) { + return GB_MODEL_SGB_NTSC; + } + else if (g_strcmp0(config.sgb_revision_name, "SGB1_PAL") == 0) { + return GB_MODEL_SGB_PAL; + } + else if (g_strcmp0(config.sgb_revision_name, "SGB2") == 0) { + return GB_MODEL_SGB2; + } + + default_value: return GB_MODEL_SGB2; +} + +GB_model_t get_cgb_model(void) { + if (config.cgb_revision_name == NULL) goto default_value; + + // TODO: Synchronize with GB_model_t (Core/gb.h) + if (g_strcmp0(config.cgb_revision_name, "CPU_CGB_C") == 0) { + return GB_MODEL_CGB_C; + } + else if (g_strcmp0(config.cgb_revision_name, "CPU_CGB_E") == 0) { + return GB_MODEL_CGB_E; + } + + default_value: return GB_MODEL_CGB_E; +} diff --git a/gtk3/settings.h b/gtk3/settings.h index 9738c5c..50415c4 100644 --- a/gtk3/settings.h +++ b/gtk3/settings.h @@ -91,4 +91,8 @@ void set_color_correction_mode(GB_color_correction_mode_t); GB_highpass_mode_t get_highpass_mode(void); void set_highpass_mode(GB_highpass_mode_t); +GB_model_t get_dmg_model(void); +GB_model_t get_sgb_model(void); +GB_model_t get_cgb_model(void); + #endif /* settings_h */