diff --git a/gtk3/main.c b/gtk3/main.c index 9668fed..a0badf3 100644 --- a/gtk3/main.c +++ b/gtk3/main.c @@ -23,6 +23,8 @@ static SDL_GameController *controller = NULL; static SDL_AudioSpec want_aspec, have_aspec; static SDL_AudioDeviceID device_id; +static const GThread *main_thread; + static GtkApplication *main_application; static GtkBuilder *builder; static GtkGLArea *gl_area; @@ -72,12 +74,15 @@ static uint8_t oamHeight; static uint8_t pressed_buttons; +static GtkTextBuffer *pending_console_output = NULL; static gboolean in_sync_input = false; static gchar *last_console_input = NULL; +static gboolean log_to_sidebar = false; +static gboolean should_clear_sidebar = false; static GMutex debugger_input_mutex; static GCond debugger_input_cond; -static GMutex console_output_lock; +static GRecMutex console_output_lock; static GPtrArray *debugger_input_queue; // List of GActions for the `app` prefix @@ -97,9 +102,12 @@ static const GActionEntry app_entries[] = { { "change_model", NULL, "s", "@s 'CGB'", on_model_changed }, { "toggle_mute", NULL, NULL, "false", on_mute_changed }, { "pause", NULL, NULL, "false", on_pause_changed }, + { "clear_console", activate_clear_console, NULL, NULL, NULL }, }; int main(int argc, char *argv[]) { + main_thread = g_thread_self(); + // initialize GB_model_t to invalid value gui_data.cli_options.model = -1; gui_data.prev_model = -1; @@ -245,7 +253,7 @@ void gl_check_realize(GtkWidget *w, gpointer user_data_gptr) { else { gdk_gl_context_make_current(context); int version = epoxy_gl_version(); - + g_object_run_dispose(G_OBJECT(context)); g_object_unref(context); context = NULL; @@ -278,7 +286,7 @@ static gboolean init_controllers() { if (val < 0) { g_warning("Failed to load controller mappings: %s", SDL_GetError()); } - + g_bytes_unref(db_f); } @@ -363,7 +371,7 @@ static GB_model_t get_model() { else if (g_strcmp0(family, "SGB") == 0) { return get_sgb_model(); } - + return get_cgb_model(); } @@ -386,7 +394,13 @@ static void gb_audio_callback(GB_gameboy_t *gb, GB_sample_t *sample) { SDL_QueueAudio(device_id, sample, sizeof(*sample)); } +// Console TODO: +// TODO: clear sidebar when switching to async mode +// TODO: Command history (up / down arrow in input) +// TODO: reverse search of commands +// TODO: search in output static char *sync_console_input(GB_gameboy_t *gb) { + update_debugger_sidebar(gb); console_log(gb, "> ", 0); in_sync_input = true; @@ -403,11 +417,6 @@ static char *sync_console_input(GB_gameboy_t *gb) { in_sync_input = false; - // clear sidebar - GtkTextView *sidebar_output = builder_get(GTK_TEXT_VIEW, "console_sidebar_output"); - GtkTextBuffer *sidebar_text_buf = gtk_text_view_get_buffer(sidebar_output); - gtk_text_buffer_set_text(sidebar_text_buf, "", -1); - return input; } @@ -429,50 +438,140 @@ static char *async_console_input(GB_gameboy_t *gb) { return input; } -static void on_console_log(gpointer user_data_gptr) { - LogData *log_data = (LogData *)user_data_gptr; - GB_gameboy_t *gb = log_data->gb; - GB_log_attributes attributes = log_data->attributes; +static void update_debugger_sidebar(GB_gameboy_t *gb) { + if (!GB_debugger_is_stopped(gb)) { + return; + } - g_mutex_lock(&console_output_lock); - - GtkTextView *text_view = builder_get(GTK_TEXT_VIEW, "console_screen"); - GtkTextBuffer *text_buf = gtk_text_view_get_buffer(text_view); + if (main_thread != g_thread_self()) { + g_idle_add((GSourceFunc) update_debugger_sidebar, gb); + return; + } + + g_rec_mutex_lock(&console_output_lock); + should_clear_sidebar = true; + append_pending_output(); + log_to_sidebar = true; + g_rec_mutex_unlock(&console_output_lock); + + GtkTextView *sidebar_input = builder_get(GTK_TEXT_VIEW, "console_sidebar_input"); + GtkTextBuffer *sidebar_input_text_buf = gtk_text_view_get_buffer(sidebar_input); + + gint line_count = gtk_text_buffer_get_line_count(sidebar_input_text_buf); + + for (unsigned line = 0; line < line_count; ++line) { + GtkTextIter start_iter; + GtkTextIter end_iter; + gunichar ch; + + gtk_text_buffer_get_iter_at_line(sidebar_input_text_buf, &start_iter, line); + end_iter = start_iter; + + do { + ch = gtk_text_iter_get_char(&end_iter); + if (!gtk_text_iter_forward_char(&end_iter)) { + break; + } + } + while (ch != '\n'); + + gchar *cmd = gtk_text_buffer_get_text(sidebar_input_text_buf, &start_iter, &end_iter, false); + g_strchug(cmd); // trim leading whitespace + g_strchomp(cmd); // trim trailing whitespace + + if (g_strcmp0("", cmd) != 0) { + char *duped = g_strdup(cmd); + GB_attributed_log(gb, GB_LOG_BOLD, "%s:\n", duped); + GB_debugger_execute_command(gb, duped); + GB_log(gb, "\n"); + g_free(duped); + } + + g_free(cmd); + } + + g_rec_mutex_lock(&console_output_lock); + append_pending_output(); + log_to_sidebar = false; + g_rec_mutex_unlock(&console_output_lock); +} + +static gboolean scroll_to_bottom(GtkTextView *textview, GtkTextMark *mark) { + GtkTextBuffer *buffer = gtk_text_view_get_buffer(textview); GtkTextIter iter; - GtkTextIter start; - - gtk_text_buffer_get_end_iter(text_buf, &iter); - GtkTextMark *start_mark = gtk_text_buffer_create_mark(text_buf, NULL, &iter, TRUE); - gtk_text_buffer_insert(text_buf, &iter, g_strdup(log_data->string), -1); - gtk_text_buffer_get_iter_at_mark(text_buf, &start, start_mark); - if (attributes & GB_LOG_BOLD) { - gtk_text_buffer_apply_tag_by_name(text_buf, "bold", &start, &iter); + gtk_text_buffer_get_end_iter(buffer, &iter); + gtk_text_iter_set_line_offset(&iter, 0); + + gtk_text_buffer_move_mark(buffer, mark, &iter); + gtk_text_view_scroll_to_mark(textview, mark, 0.0, TRUE, 0.0, 0.10); + + gtk_text_buffer_delete_mark(buffer, mark); + + return TRUE; +} + +static void append_pending_output(void) { + g_rec_mutex_lock(&console_output_lock); + + if (should_clear_sidebar) { + GtkTextView *sidebar_output = builder_get(GTK_TEXT_VIEW, "console_sidebar_output"); + GtkTextBuffer *sidebar_output_text_buf = gtk_text_view_get_buffer(sidebar_output); + gtk_text_buffer_set_text(sidebar_output_text_buf, "", -1); + should_clear_sidebar = FALSE; } - if (attributes & GB_LOG_DASHED_UNDERLINE) { - gtk_text_buffer_apply_tag_by_name(text_buf, "dashed_underline", &start, &iter); + if (gtk_text_buffer_get_char_count(pending_console_output) > 0) { + GtkTextView *text_view = builder_get(GTK_TEXT_VIEW, log_to_sidebar? "console_sidebar_output" : "console_screen"); + GtkTextBuffer *text_buf = gtk_text_view_get_buffer(text_view); + GtkTextIter start; + GtkTextIter end; + gtk_text_buffer_get_start_iter(pending_console_output, &start); + gtk_text_buffer_get_end_iter(pending_console_output, &end); + + GtkTextIter iter; + gtk_text_buffer_get_end_iter(text_buf, &iter); + gtk_text_buffer_insert_range(text_buf, &iter, &start, &end); + + scroll_to_bottom(text_view, gtk_text_buffer_create_mark(text_buf, NULL, &iter, TRUE)); + + gtk_text_buffer_set_text(pending_console_output, "", -1); } - if (attributes & GB_LOG_UNDERLINE) { - gtk_text_buffer_apply_tag_by_name(text_buf, "underline", &start, &iter); - } - - g_free((gpointer)log_data->string); - g_free(log_data); - gtk_text_buffer_delete_mark(text_buf, start_mark); - g_mutex_unlock(&console_output_lock); + g_rec_mutex_unlock(&console_output_lock); } static void console_log(GB_gameboy_t *gb, const char *string, GB_log_attributes attributes) { - if (string != NULL && !g_str_equal("", string)) { - LogData *log_data = g_malloc(sizeof(LogData)); - log_data->gb = gb; - log_data->string = g_strdup(string); - log_data->attributes = attributes; + g_rec_mutex_lock(&console_output_lock); - g_idle_add((GSourceFunc) on_console_log, log_data); + if (string != NULL && !g_str_equal("", string)) { + GtkTextIter iter; + GtkTextIter start; + + // Append attributed text to "pending_console_output" GtkTextBuffer + gtk_text_buffer_get_end_iter(pending_console_output, &iter); + GtkTextMark *start_mark = gtk_text_buffer_create_mark(pending_console_output, NULL, &iter, TRUE); + gtk_text_buffer_insert(pending_console_output, &iter, g_strdup(string), -1); + gtk_text_buffer_get_iter_at_mark(pending_console_output, &start, start_mark); + + if (attributes & GB_LOG_BOLD) { + gtk_text_buffer_apply_tag_by_name(pending_console_output, "bold", &start, &iter); + } + + if (attributes & GB_LOG_DASHED_UNDERLINE) { + gtk_text_buffer_apply_tag_by_name(pending_console_output, "dashed_underline", &start, &iter); + } + + if (attributes & GB_LOG_UNDERLINE) { + gtk_text_buffer_apply_tag_by_name(pending_console_output, "underline", &start, &iter); + } + + gtk_text_buffer_delete_mark(pending_console_output, start_mark); + + g_idle_add((GSourceFunc) append_pending_output, NULL); } + + g_rec_mutex_unlock(&console_output_lock); } // Returns a `GApplication`s `GMenuModel` by ID @@ -494,7 +593,7 @@ static void create_fallback_canvas(void) { } // Create our application’s menu. -// +// // This function tries to stick to the desktop environment’s conventions. // For the GNOME Shell it uses a hamburger menu, otherwise it either lets // the desktop environment shell handle the menu if it signals support for it @@ -512,7 +611,7 @@ static void setup_menu(GApplication *app) { const gchar *xdg_current_desktop = g_getenv("XDG_CURRENT_DESKTOP"); const gchar *gdm_session = g_getenv("GDMSESSION"); const gchar *desktop_session = g_getenv("DESKTOP_SESSION"); - + gchar *desktop = (gchar *)xdg_current_desktop; if (desktop == NULL || g_str_equal(desktop, "")) desktop = (gchar *)gdm_session; if (desktop == NULL || g_str_equal(desktop, "")) desktop = (gchar *)desktop_session; @@ -764,7 +863,7 @@ static void activate(GApplication *app, gpointer gui_data_gptr) { g_signal_connect(memory_viewer, "delete-event", G_CALLBACK(gtk_widget_hide_on_delete), NULL); g_signal_connect(console, "delete-event", G_CALLBACK(gtk_widget_hide_on_delete), NULL); g_signal_connect(printer, "delete-event", G_CALLBACK(gtk_widget_hide_on_delete), NULL); - + g_signal_connect(get_object("vram_viewer_tileset_canvas"), "draw", G_CALLBACK(on_draw_vram_viewer_tileset), NULL); g_signal_connect(get_object("vram_viewer_tilemap_canvas"), "draw", G_CALLBACK(on_draw_vram_viewer_tilemap), NULL); @@ -798,6 +897,12 @@ static void activate(GApplication *app, gpointer gui_data_gptr) { GtkTextView *text_view = builder_get(GTK_TEXT_VIEW, "console_screen"); GtkTextBuffer *text_buf = gtk_text_view_get_buffer(text_view); + + gtk_text_view_set_buffer( + builder_get(GTK_TEXT_VIEW, "console_sidebar_output"), + gtk_text_buffer_new(gtk_text_buffer_get_tag_table(text_buf)) + ); + gtk_text_buffer_create_tag(text_buf, "bold", "weight", PANGO_WEIGHT_BOLD, NULL); 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); @@ -811,12 +916,16 @@ static void activate(GApplication *app, gpointer gui_data_gptr) { g_mutex_init(&debugger_input_mutex); g_cond_init(&debugger_input_cond); - g_mutex_init(&console_output_lock); + g_rec_mutex_init(&console_output_lock); if (!debugger_input_queue) { debugger_input_queue = g_ptr_array_sized_new(4); } + if (!pending_console_output) { + pending_console_output = gtk_text_buffer_new(gtk_text_buffer_get_tag_table(text_buf)); + } + // Start the emulation thread run(gui_data); } @@ -861,7 +970,7 @@ static void open(GApplication *app, GFile **files, gint n_files, const gchar *hi // Tell our application to quit. // After this functions has been called the `shutdown` signal will be issued. -// +// // TODO: Make sure we have a way to quit our emulation loop before `shutdown` gets called static void quit(GApplication *app) { // Tell our own main loop to quit. @@ -884,10 +993,10 @@ static gboolean on_key_press(GtkWidget *w, GdkEventKey *event, gpointer data) { case GDK_KEY_a: mask = BUTTON_MASK_LEFT; break; case GDK_KEY_s: mask = BUTTON_MASK_DOWN; break; case GDK_KEY_d: mask = BUTTON_MASK_RIGHT; break; - + case GDK_KEY_g: mask = BUTTON_MASK_SELECT; break; case GDK_KEY_h: mask = BUTTON_MASK_START; break; - + case GDK_KEY_k: mask = BUTTON_MASK_B; break; case GDK_KEY_l: mask = BUTTON_MASK_A; break; @@ -923,7 +1032,7 @@ static gboolean on_key_press(GtkWidget *w, GdkEventKey *event, gpointer data) { } break; } } - + if (event->type == GDK_KEY_PRESS) { pressed_buttons |= mask; } @@ -981,7 +1090,7 @@ static void activate_open_vram_viewer(GSimpleAction *action, GVariant *parameter static void activate_open(GSimpleAction *action, GVariant *parameter, gpointer app) { GtkFileChooserNative *native = gtk_file_chooser_native_new("Open File", GTK_WINDOW(main_window), GTK_FILE_CHOOSER_ACTION_OPEN, "_Open", "_Cancel"); gint res = gtk_native_dialog_run(GTK_NATIVE_DIALOG(native)); - + if (res == GTK_RESPONSE_ACCEPT) { // TODO: Emit an event for our emulation loop g_message("%s", gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(native))); @@ -1015,6 +1124,18 @@ static void activate_reset(GSimpleAction *action, GVariant *parameter, gpointer } } +// app.clear_console GAction +// Clears the debugger console +static void activate_clear_console(GSimpleAction *action, GVariant *parameter, gpointer app) { + g_rec_mutex_lock(&console_output_lock); + + GtkTextView *text_view = builder_get(GTK_TEXT_VIEW, "console_screen"); + GtkTextBuffer *text_buf = gtk_text_view_get_buffer(text_view); + gtk_text_buffer_set_text(text_buf, "", -1); + + g_rec_mutex_unlock(&console_output_lock); +} + static void on_model_changed(GSimpleAction *action, GVariant *value, gpointer user_data) { if (!GB_is_inited(&gb)) { g_simple_action_set_state(action, value); @@ -1092,7 +1213,7 @@ static void gl_init(GtkWidget *w) { g_debug("GL Context: %p", gtk_gl_area_get_context(gl_area)); gtk_gl_area_make_current(gl_area); - + if (gtk_gl_area_get_error(gl_area) != NULL) { goto error; } @@ -1181,7 +1302,7 @@ static gboolean on_draw_vram_viewer_tileset(GtkWidget *widget, cairo_t *cr, gpoi height = gtk_widget_get_allocated_height(widget); gtk_render_background(context, cr, 0, 0, width, height); - + cairo_surface_t *surface = cairo_image_surface_create_for_data( (unsigned char *) tileset_buffer, CAIRO_FORMAT_RGB24, @@ -1405,7 +1526,7 @@ G_MODULE_EXPORT void on_boot_rom_location_changed(GtkWidget *w, gpointer user_da if (g_strcmp0(id, "other") == 0) { GtkFileChooserNative *native = gtk_file_chooser_native_new("Select Folder", preferences, GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, "_Select", "_Cancel"); gint res = gtk_native_dialog_run(GTK_NATIVE_DIALOG(native)); - + if (res == GTK_RESPONSE_ACCEPT) { config.boot_rom_path = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(native)); update_boot_rom_selector(builder); @@ -1537,7 +1658,7 @@ static void render_texture(void *pixels, void *previous) { glClearColor(0, 0, 0, 1); glClear(GL_COLOR_BUFFER_BIT); - + render_bitmap_with_shader(&shader, _pixels, previous, GB_get_screen_width(&gb), GB_get_screen_height(&gb), viewport.x, viewport.y, viewport.w, viewport.h); } @@ -1582,7 +1703,7 @@ static void update_window_geometry() { GdkGeometry hints; hints.min_width = GB_get_screen_width(&gb); hints.min_height = GB_get_screen_height(&gb); - + gtk_window_set_geometry_hints( GTK_WINDOW(main_window), NULL, @@ -1716,7 +1837,7 @@ static void on_vblank(gpointer data) { g_bytes_new(oamInfo[row].image, 128 * sizeof(uint32_t)), GDK_COLORSPACE_RGB, true, 8, 8, oamHeight, 8 * sizeof(uint32_t) ); - + GdkPixbuf *dest = gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, 8, 8 * 2, oamHeight * 2); gdk_pixbuf_scale(pixbuf, dest, @@ -1998,13 +2119,13 @@ static void load_boot_rom(GuiData *gui_data) { if (config.boot_rom_path != NULL && g_strcmp0(config.boot_rom_path, "other") != 0 && g_strcmp0(config.boot_rom_path, "auto") != 0) { boot_rom_path = g_build_filename(config.boot_rom_path, boot_rom_name, NULL); g_message("Trying to load boot ROM from %s", boot_rom_path); - + if (GB_load_boot_rom(&gb, boot_rom_path)) { g_free(boot_rom_path); g_warning("Falling back to internal boot ROM"); goto internal_boot_rom; } - + g_free(boot_rom_path); } else { internal_boot_rom: @@ -2020,7 +2141,7 @@ static void load_boot_rom(GuiData *gui_data) { boot_rom_data = g_bytes_get_data(boot_rom_f, &boot_rom_size); GB_load_boot_rom_from_buffer(&gb, boot_rom_data, boot_rom_size); - + g_bytes_unref(boot_rom_f); } } diff --git a/gtk3/main.h b/gtk3/main.h index 900b1a2..cb22790 100644 --- a/gtk3/main.h +++ b/gtk3/main.h @@ -70,6 +70,8 @@ static gboolean init_audio(); static void gb_audio_callback(GB_gameboy_t *gb, GB_sample_t *sample); static char *sync_console_input(GB_gameboy_t *gb); static char *async_console_input(GB_gameboy_t *gb); +static void update_debugger_sidebar(GB_gameboy_t *gb); +static void append_pending_output(); static void on_console_log(gpointer user_data_gptr); static void console_log(GB_gameboy_t *gb, const char *string, GB_log_attributes attributes); @@ -107,6 +109,7 @@ static void activate_open(GSimpleAction *action, GVariant *parameter, gpointer a static void activate_preferences(GSimpleAction *action, GVariant *parameter, gpointer app); static void activate_quit(GSimpleAction *action, GVariant *parameter, gpointer app); static void activate_reset(GSimpleAction *action, GVariant *parameter, gpointer app); +static void activate_clear_console(GSimpleAction *action, GVariant *parameter, gpointer app); static void on_model_changed(GSimpleAction *action, GVariant *value, gpointer user_data); static void on_mute_changed(GSimpleAction *action, GVariant *value, gpointer user_data); diff --git a/gtk3/resources/ui/#window.ui# b/gtk3/resources/ui/#window.ui# new file mode 100644 index 0000000..1372d10 --- /dev/null +++ b/gtk3/resources/ui/#window.ui# @@ -0,0 +1,1669 @@ + + + + + + + + + + + False + normal + SameBoy + Copyright © 2015-2019 Lior Halphon + https://sameboy.github.io + sameboy.github.io + Lior Halphon https://github.com/LIJI32 + +GTK3 frontend by +Maximilian Mader https://github.com/max-m + + mit-x11 + + + + + + False + vertical + 2 + + + False + end + + + False + False + 0 + + + + + + + + + + + + + + + + + + + + CPU_CGB_0 + CPU-CGB 0 + False + + + CPU_CGB_A + CPU-CGB A + False + + + CPU_CGB_B + CPU-CGB B + False + + + CPU_CGB_C + CPU-CGB C (Experimental) + True + + + CPU_CGB_D + CPU-CGB D + False + + + CPU_CGB_E + CPU-CGB E + True + + + + + + + + + + + + + + + DMG_CPU_0 + DMG-CPU 0 + False + + + DMG_CPU_A + DMG-CPU A + False + + + DMG_CPU_B + DMG-CPU B + True + + + DMG_CPU_C + DMG-CPU C + False + + + + + False + Preferences + False + + + + + + True + True + + + True + False + 16 + 16 + 16 + 16 + vertical + + + True + False + Boot ROMs location: + + + False + True + 0 + + + + + True + False + 5 + 10 + + + + False + True + 1 + + + + + True + False + Rewinding Duration: + + + False + True + 2 + + + + + True + False + 5 + 10 + + 10 Seconds + 30 Seconds + 1 Minute + 2 Minutes + 5 Minutes + 10 Minutes + + + + + False + True + 3 + + + + + True + False + 5 + + + False + True + 4 + + + + + True + False + Game Boy Revision: + + + False + True + 5 + + + + + True + False + 5 + 10 + dmg_models + 0 + + + + + 2 + 2 + 1 + + + + + False + True + 6 + + + + + True + False + Super Game Boy Model: + + + False + True + 7 + + + + + True + False + 5 + 10 + + Super Game Boy (NTSC) + Super Game Boy (PAL) + Super Game Boy 2 + + + + + False + True + 8 + + + + + True + False + Game Boy Color Revision: + + + False + True + 9 + + + + + True + False + 5 + 10 + cgb_models + 0 + + + + + 2 + 2 + 1 + + + + + False + True + 10 + + + + + + + True + False + vertical + + + True + False + 2 + /io/github/sameboy/pixmaps/CPU.png + 3 + + + False + True + 0 + + + + + True + False + Emulation + + + False + True + 1 + + + + + False + + + + + True + False + 16 + 16 + 16 + 16 + vertical + + + True + False + Graphics Filter: + + + False + True + 0 + + + + + True + False + 5 + 10 + + Nearest Neighbor (Pixelated) + Bilinear (Blurry) + Smooth Bilinear (Less blurry) + LCD Display + CRT Display + Scale2x + Scale4x + Anti-aliased Scale2x + Anti-aliased Scale4x + HQ2x + OmniScale (Any factor) + OmniScale Legacy + Anti-aliased OmniScale Legacy + + + + + False + True + 1 + + + + + True + False + Color Correction: + + + False + True + 2 + + + + + True + False + 5 + 10 + + Disabled + Correct Color Curves + Emulate Hardware + Preserve Brightness + + + + + False + True + 3 + + + + + Use Integer Scaling + True + True + False + 5 + 10 + True + + + + False + True + 4 + + + + + Keep Aspect Ratio + True + True + False + 5 + 10 + True + + + + False + True + 4 + + + + + False + Main Menu Override + + + False + True + 6 + + + + + False + + Automatic + Force Menubar In Desktop Shell + Force Menubar In Window + Force Hamburger Menu + + + + + False + True + 7 + + + + + 1 + + + + + True + False + vertical + + + True + False + 2 + /io/github/sameboy/pixmaps/Display.png + 3 + + + False + True + 0 + + + + + True + False + Video + + + False + True + 1 + + + + + 1 + False + + + + + True + False + 14 + 16 + 16 + 16 + vertical + + + True + False + High-pass Filter: + + + False + True + 0 + + + + + True + False + 5 + 10 + + Disabled (Keep DC Offset) + Accurate (Emulate Hardware) + Preserve Waveform + + + + + False + True + 1 + + + + + True + False + Sample Rate: + + + False + True + 2 + + + + + True + False + + Default + <separator> + 44.1 kHz + 48 kHz + 96 kHz + + + + + False + True + 3 + + + + + 2 + + + + + True + False + vertical + + + True + False + 2 + /io/github/sameboy/pixmaps/Speaker.png + 3 + + + False + True + 0 + + + + + True + False + Audio + + + False + True + 1 + + + + + 2 + False + + + + + True + False + 16 + 16 + 16 + 16 + vertical + + + True + False + 10 + + + True + False + Control settings for + + + False + True + 0 + + + + + True + False + 5 + 5 + 0 + + Player 1 + Player 2 + Player 3 + Player 4 + + + + + False + True + 1 + + + + + True + False + : + + + False + True + 2 + + + + + False + True + 0 + + + + + True + False + 90 + 90 + True + + + False + True + 1 + + + + + True + False + Joypad for multiplayer games: + + + False + True + 2 + + + + + True + False + 5 + 10 + 0 + + None + + + + + False + True + 3 + + + + + True + False + 5 + + + False + True + 4 + + + + + True + False + + + Configure Joypad + True + True + True + + + + False + True + 0 + + + + + Skip + True + False + True + True + + + + False + True + end + 1 + + + + + False + True + 5 + + + + + 3 + + + + + True + False + vertical + + + True + False + 2 + /io/github/sameboy/pixmaps/Joypad.png + 3 + + + False + True + 0 + + + + + True + False + Controls + + + False + True + 1 + + + + + 3 + False + + + + + + + + False + Debug Console + 920 + 400 + + + + + + True + False + vertical + + + True + False + + + True + True + in + 600 + 376 + 600 + 376 + + + True + True + False + word + 5 + 5 + 5 + 5 + False + False + True + + + + + + + True + True + 0 + + + + + 320 + True + False + vertical + + + True + True + in + 320 + 80 + + + True + True + word + 5 + 5 + 5 + 5 + False + GTK_INPUT_HINT_NO_SPELLCHECK | GTK_INPUT_HINT_NO_EMOJI | GTK_INPUT_HINT_NONE + True + + + + + + + False + True + 0 + + + + + True + True + in + + + True + True + False + word + 5 + 5 + 5 + 5 + False + False + True + + + + + + + True + True + 1 + + + + + False + True + 1 + + + + + + True + True + 0 + + + + + True + True + 3 + 3 + 3 + 3 + Console input + entrycompletion1 + GTK_INPUT_HINT_NO_SPELLCHECK | GTK_INPUT_HINT_NO_EMOJI | GTK_INPUT_HINT_NONE + + + + False + True + 1 + + + + + + + + True + False + False + True + + + True + True + True + none + + + + + + end + + + + + False + Memory Viewer + + + + + + True + False + vertical + True + + + True + False + Placeholder + + + False + True + 0 + + + + + True + False + Placeholder + + + False + True + 1 + + + + + True + False + Placeholder + + + False + True + 2 + + + + + + + False + False + 320 + 432 + + + True + False + Printer + False + True + + + gtk-save + True + True + True + True + + + end + + + + + gtk-delete + True + True + True + True + + + end + 1 + + + + + + + True + True + in + + + True + False + none + + + True + False + + + + + + + + + False + VRAM Viewer + False + + + + + + True + False + 3 + 3 + 3 + vertical + 6 + + + True + False + center + vram_viewer_stack + + + False + True + 0 + + + + + True + False + False + False + slide-left-right + True + + + True + False + vertical + + + True + False + 6 + 6 + 3 + + + True + False + 0 + bg0 + + Background Palette 0 + Background Palette 1 + Background Palette 2 + Background Palette 3 + Background Palette 4 + Background Palette 5 + Background Palette 6 + Background Palette 7 + <separator> + Object Palette 0 + Object Palette 1 + Object Palette 2 + Object Palette 3 + Object Palette 4 + Object Palette 5 + Object Palette 6 + Object Palette 7 + + + + False + True + 0 + + + + + Grid + 70 + True + True + True + + + False + True + end + 2 + + + + + + False + True + 0 + + + + + 512 + 384 + True + True + False + + + True + True + 1 + + + + + vram_viewer_tileset + Tileset + + + + + True + False + vertical + + + True + False + 6 + 6 + 3 + + + True + False + 0 + auto + + Effective Palettes + <separator> + Background Palette 0 + Background Palette 1 + Background Palette 2 + Background Palette 3 + Background Palette 4 + Background Palette 5 + Background Palette 6 + Background Palette 7 + <separator> + Object Palette 0 + Object Palette 1 + Object Palette 2 + Object Palette 3 + Object Palette 4 + Object Palette 5 + Object Palette 6 + Object Palette 7 + + + + False + False + 0 + + + + + True + False + 0 + auto + + Effective Tilemap + <separator> + Tilemap at $9800 + Tilemap at $9C00 + + + + False + True + 1 + + + + + Grid + True + True + True + 2 + + + False + True + end + 2 + + + + + Scrolling + True + True + True + 2 + 2 + + + False + True + end + 3 + + + + + True + False + 0 + auto + + Effective Tileset + <separator> + Tileset at $8800 + Tileset at $8000 + + + + False + True + 4 + + + + + + False + False + 0 + + + + + 512 + 512 + True + True + False + start + start + False + False + + + True + True + 1 + + + + + vram_viewer_tilemap + Tilemap + 1 + + + + + 512 + 512 + True + True + in + + + True + True + False + False + False + + + + + + 32 + + + + 0 + + + + + + + X + + + + 1 + + + + + + + Y + + + + 2 + + + + + + + Tile + + + + 3 + + + + + + + Tile Addr. + + + + 4 + + + + + + + OAM Addr. + + + + 5 + + + + + + + Attributes + + + + 6 + + + + + + + + + vram_viewer_sprites + Sprites + 2 + + + + + True + True + False + False + False + False + + + + + + Type + + + + 0 + + + + + + + Color 0 + + + + 1 + + + + + + + Color 1 + + + + 3 + + + + + + + Color 2 + + + + 5 + + + + + + + Color 3 + + + + 7 + + + + + + + vram_viewer_palettes + Palettes + 3 + + + + + True + True + 1 + + + + + True + False + 5 + center + True + False + + + True + True + 2 + + + + + + diff --git a/gtk3/resources/ui/window.ui b/gtk3/resources/ui/window.ui index c02b8bb..89ec98d 100644 --- a/gtk3/resources/ui/window.ui +++ b/gtk3/resources/ui/window.ui @@ -140,27 +140,18 @@ Maximilian Mader https://github.com/max-m 600 376 - + True - False - - - True - True - False - word - 5 - 5 - 5 - 5 - False - False - True - - - + True + False + word + 5 + 5 + 5 + 5 + False + False + True @@ -191,25 +182,16 @@ Maximilian Mader https://github.com/max-m 320 80 - + True - False - - - True - True - word - 5 - 5 - 5 - 5 - False - True - - - + True + word + 5 + 5 + 5 + 5 + False + True @@ -232,26 +214,17 @@ Maximilian Mader https://github.com/max-m True in - + True - False - - - True - True - False - word - 5 - 5 - 5 - 5 - False - True - - - + True + False + word + 5 + 5 + 5 + 5 + False + True @@ -655,23 +628,6 @@ Maximilian Mader https://github.com/max-m 3 - - - Use Integer Scaling - True - True - False - 5 - 10 - True - - - - False - True - 4 - - Keep Aspect Ratio @@ -689,6 +645,23 @@ Maximilian Mader https://github.com/max-m 4 + + + Use Integer Scaling + True + True + False + 5 + 10 + True + + + + False + True + 4 + + False