diff --git a/gtk3/main.c b/gtk3/main.c index db7cc86..7866ce7 100644 --- a/gtk3/main.c +++ b/gtk3/main.c @@ -354,10 +354,12 @@ static void rumble_callback(GB_gameboy_t *gb, double amp) { } } -static void clear_sidebar(void) { +static gboolean clear_sidebar(void) { 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); + + return false; } static gboolean scroll_to_bottom(GtkTextView *textview, GtkTextMark *mark) { @@ -375,7 +377,7 @@ static gboolean scroll_to_bottom(GtkTextView *textview, GtkTextMark *mark) { return true; } -static void append_pending_output(void) { +static gboolean append_pending_output(void) { g_rec_mutex_lock(&gui_data.console_output_lock); if (gui_data.should_clear_sidebar) { @@ -401,16 +403,18 @@ static void append_pending_output(void) { } g_rec_mutex_unlock(&gui_data.console_output_lock); + + return false; } -static void update_debugger_sidebar(GB_gameboy_t *gb) { +static gboolean update_debugger_sidebar(GB_gameboy_t *gb) { if (!GB_debugger_is_stopped(gb)) { - return; + return false; } if (gui_data.main_thread != g_thread_self()) { g_idle_add((GSourceFunc) update_debugger_sidebar, gb); - return; + return false; } g_rec_mutex_lock(&gui_data.console_output_lock); @@ -459,6 +463,8 @@ static void update_debugger_sidebar(GB_gameboy_t *gb) { append_pending_output(); gui_data.log_to_sidebar = false; g_rec_mutex_unlock(&gui_data.console_output_lock); + + return false; } static void console_log(GB_gameboy_t *gb, const char *string, GB_log_attributes attributes) { @@ -781,7 +787,7 @@ static void stop(void) { gui_data.stopped = true; } -static void on_vblank(GB_gameboy_t *gb) { +static gboolean on_vblank(GB_gameboy_t *gb) { // Queue drawing of the current frame if (gui_data.fallback_canvas) { gtk_widget_queue_draw(GTK_WIDGET(gui_data.main_window)); @@ -791,6 +797,8 @@ static void on_vblank(GB_gameboy_t *gb) { } gtk_widget_queue_draw(GTK_WIDGET(gui_data.vram_viewer)); + + return false; } static void vblank(GB_gameboy_t *gb) { diff --git a/gtk3/resources/css/main.css b/gtk3/resources/css/main.css index fbbb1db..40cdce9 100644 --- a/gtk3/resources/css/main.css +++ b/gtk3/resources/css/main.css @@ -43,3 +43,6 @@ border-bottom: 1px solid #3d4548; } +.monospace { + font-family: monospace; +} diff --git a/gtk3/resources/ui/vram_viewer.ui b/gtk3/resources/ui/vram_viewer.ui index 574d3ed..b3f205a 100644 --- a/gtk3/resources/ui/vram_viewer.ui +++ b/gtk3/resources/ui/vram_viewer.ui @@ -49,6 +49,8 @@ Author: Maximilian Mader True False center + 10 + 10 stack @@ -65,7 +67,7 @@ Author: Maximilian Mader False slide-left-right True - + True @@ -75,8 +77,8 @@ Author: Maximilian Mader True False - 6 - 6 + 6 + 6 3 @@ -142,8 +144,8 @@ Author: Maximilian Mader True True False - - + + True @@ -166,8 +168,8 @@ Author: Maximilian Mader True False - 6 - 6 + 6 + 6 3 @@ -228,7 +230,7 @@ Author: Maximilian Mader True True True - 2 + 2 False @@ -243,8 +245,8 @@ Author: Maximilian Mader True True True - 2 - 2 + 2 + 2 False @@ -293,8 +295,8 @@ Author: Maximilian Mader start False False - - + + True @@ -420,6 +422,9 @@ Author: Maximilian Mader False False False + @@ -437,6 +442,7 @@ Author: Maximilian Mader Color 0 + True @@ -448,6 +454,7 @@ Author: Maximilian Mader Color 1 + True @@ -459,6 +466,7 @@ Author: Maximilian Mader Color 2 + True @@ -470,6 +478,7 @@ Author: Maximilian Mader Color 3 + True diff --git a/gtk3/vram_viewer.c b/gtk3/vram_viewer.c index a885cbf..26ea875 100644 --- a/gtk3/vram_viewer.c +++ b/gtk3/vram_viewer.c @@ -188,7 +188,19 @@ static gboolean tileset_canvas_motion(GtkWidget *widget, GdkEventMotion *event, x &= 127; uint16_t tile = x / 8 + y / 8 * 16; - gtk_label_set_text(window->status, g_strdup_printf("Tile number $%02x at %d:$%04x", tile & 0xFF, bank, 0x8000 + tile * 0x10)); + const char *format = + "Tile number" + " $%02x" + " at" + " %d:$%04x"; + + g_autofree char *markup = g_markup_printf_escaped( + format, + tile & 0xFF, + bank, 0x8000 + tile * 0x10 + ); + + gtk_label_set_markup(window->status, markup); return true; } @@ -213,8 +225,6 @@ static gboolean tilemap_canvas_motion(GtkWidget *widget, GdkEventMotion *event, x /= 2; y /= 2; - GtkLabel *status = window->status; - uint16_t map_offset = x / 8 + y / 8 * 32; uint16_t map_base = 0x1800; @@ -249,7 +259,17 @@ static gboolean tilemap_canvas_motion(GtkWidget *widget, GdkEventMotion *event, if (window->is_cgb) { uint8_t attributes = window->gb_vram[map_base + map_offset + 0x2000]; - gtk_label_set_text(status, g_strdup_printf("Tile number $%02x (%d:$%04x) at map address $%04x (Attributes: %c%c%c%d%d)", + + const char *format = + "Tile number" + " $%02x" + " (%d:$%04x)" + " at map address" + " $%04x" + " (Attributes: %c%c%c%d%d)"; + + g_autofree char *markup = g_markup_printf_escaped( + format, tile, attributes & 0x8? 1 : 0, tile_address, @@ -259,14 +279,25 @@ static gboolean tilemap_canvas_motion(GtkWidget *widget, GdkEventMotion *event, (attributes & 0x20) ? 'H' : '-', attributes & 0x8? 1 : 0, attributes & 0x7 - )); + ); + + gtk_label_set_markup(window->status, markup); } else { - gtk_label_set_text(status, g_strdup_printf("Tile number $%02x ($%04x) at map address $%04x", + const char *format = + "Tile number" + " $%02x ($%04x)" + " at map address" + " $%04x"; + + g_autofree char *markup = g_markup_printf_escaped( + format, tile, tile_address, 0x8000 + map_base + map_offset - )); + ); + + gtk_label_set_markup(window->status, markup); } return true; @@ -338,30 +369,40 @@ const gchar *vram_viewer_get_tileset_type_id(VramViewerWindow *window) { return gtk_combo_box_get_active_id(GTK_COMBO_BOX(window->tilemap_tileset_selector)); } -static void update_sprite_list(VramViewerWindow *window) { +static gboolean update_sprite_list(VramViewerWindow *window) { GtkTreeIter iter; + GtkTreeModel *model = gtk_tree_view_get_model(window->sprites); + GtkListStore *store; - GtkListStore *store = gtk_list_store_new(7, - GDK_TYPE_PIXBUF, // Preview image - G_TYPE_STRING, // X position - G_TYPE_STRING, // Y position - G_TYPE_STRING, // Tile - G_TYPE_STRING, // Tile Address - G_TYPE_STRING, // OAM Address - G_TYPE_STRING // Attributes - ); + if (!model) { + g_autoptr(GtkListStore) new_store = gtk_list_store_new(7, + GDK_TYPE_PIXBUF, // Preview image + G_TYPE_STRING, // X position + G_TYPE_STRING, // Y position + G_TYPE_STRING, // Tile + G_TYPE_STRING, // Tile Address + G_TYPE_STRING, // OAM Address + G_TYPE_STRING // Attributes + ); + + gtk_tree_view_set_model(window->sprites, GTK_TREE_MODEL(new_store)); + store = new_store; + } + else { + store = GTK_LIST_STORE(model); + gtk_list_store_clear(store); + } gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter); - GB_oam_info_t *oam_info = window->oam_info; - for (unsigned row = 0; row < window->oam_count; ++row) { - GdkPixbuf *pixbuf = gdk_pixbuf_new_from_bytes( - g_bytes_new(oam_info[row].image, 128 * sizeof(uint32_t)), + g_autoptr(GBytes) bytes = g_bytes_new(window->oam_info[row].image, 128 * sizeof(uint32_t)); + g_autoptr(GdkPixbuf) pixbuf = gdk_pixbuf_new_from_bytes( + bytes, GDK_COLORSPACE_RGB, true, 8, 8, window->oam_height, 8 * sizeof(uint32_t) ); - GdkPixbuf *dest = gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, 8, 8 * 2, window->oam_height * 2); + g_autoptr(GdkPixbuf) dest = gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, 8, 8 * 2, window->oam_height * 2); gdk_pixbuf_scale(pixbuf, dest, 0, 0, 8 * 2, window->oam_height * 2, @@ -369,34 +410,37 @@ static void update_sprite_list(VramViewerWindow *window) { GDK_INTERP_NEAREST ); + g_autofree gchar *str_1 = g_strdup_printf("%i", window->oam_info[row].x - 8); + g_autofree gchar *str_2 = g_strdup_printf("%i", window->oam_info[row].y - 16); + g_autofree gchar *str_3 = g_strdup_printf("$%02x", window->oam_info[row].tile); + g_autofree gchar *str_4 = g_strdup_printf("$%04x", 0x8000 + window->oam_info[row].tile * 0x10); + g_autofree gchar *str_5 = g_strdup_printf("$%04x", window->oam_info[row].oam_addr); + g_autofree gchar *str_6 = window->is_cgb + ? g_strdup_printf("%c%c%c%d%d", + window->oam_info[row].flags & 0x80? 'P' : '-', + window->oam_info[row].flags & 0x40? 'Y' : '-', + window->oam_info[row].flags & 0x20? 'X' : '-', + window->oam_info[row].flags & 0x08? 1 : 0, + window->oam_info[row].flags & 0x07) + : g_strdup_printf("%c%c%c%d", + window->oam_info[row].flags & 0x80? 'P' : '-', + window->oam_info[row].flags & 0x40? 'Y' : '-', + window->oam_info[row].flags & 0x20? 'X' : '-', + window->oam_info[row].flags & 0x10? 1 : 0); + gtk_list_store_insert_with_values(store, &iter, -1, 0, dest, - 1, g_strdup_printf("%i", oam_info[row].x - 8), - 2, g_strdup_printf("%i", oam_info[row].y - 16), - 3, g_strdup_printf("$%02x", oam_info[row].tile), - 4, g_strdup_printf("$%04x", 0x8000 + oam_info[row].tile * 0x10), - 5, g_strdup_printf("$%04x", oam_info[row].oam_addr), - 6, window->is_cgb - ? g_strdup_printf("%c%c%c%d%d", - oam_info[row].flags & 0x80? 'P' : '-', - oam_info[row].flags & 0x40? 'Y' : '-', - oam_info[row].flags & 0x20? 'X' : '-', - oam_info[row].flags & 0x08? 1 : 0, - oam_info[row].flags & 0x07) - : g_strdup_printf("%c%c%c%d", - oam_info[row].flags & 0x80? 'P' : '-', - oam_info[row].flags & 0x40? 'Y' : '-', - oam_info[row].flags & 0x20? 'X' : '-', - oam_info[row].flags & 0x10? 1 : 0), + 1, str_1, + 2, str_2, + 3, str_3, + 4, str_4, + 5, str_5, + 6, str_6, -1 ); - - g_object_unref(pixbuf); - g_object_unref(dest); } - gtk_tree_view_set_model(window->sprites, GTK_TREE_MODEL(store)); - g_object_unref(store); + return false; } static void palette_color_data_func(GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data_ptr) { @@ -427,24 +471,44 @@ static void palette_color_data_func(GtkTreeViewColumn *col, GtkCellRenderer *ren g_free(color_string); } -static void update_palettes(VramViewerWindow *window) { +static gboolean update_palettes(VramViewerWindow *window) { GtkTreeIter iter; + GtkTreeModel *model = gtk_tree_view_get_model(window->palettes); + GtkListStore *store; - GtkListStore *store = gtk_list_store_new(9, - G_TYPE_STRING, // Name + if (!model) { + g_autoptr(GtkListStore) new_store = gtk_list_store_new(9, + G_TYPE_STRING, // Name - G_TYPE_STRING, // Color 0 string - G_TYPE_INT, // Color 0 integer + G_TYPE_STRING, // Color 0 string + G_TYPE_INT, // Color 0 integer - G_TYPE_STRING, // Color 1 string - G_TYPE_INT, // Color 1 integer + G_TYPE_STRING, // Color 1 string + G_TYPE_INT, // Color 1 integer - G_TYPE_STRING, // Color 2 string - G_TYPE_INT, // Color 2 integer + G_TYPE_STRING, // Color 2 string + G_TYPE_INT, // Color 2 integer - G_TYPE_STRING, // Color 3 string - G_TYPE_INT // Color 3 integer - ); + G_TYPE_STRING, // Color 3 string + G_TYPE_INT // Color 3 integer + ); + gtk_tree_view_set_model(window->palettes, GTK_TREE_MODEL(new_store)); + store = new_store; + + GtkTreeViewColumn *column_0 = gtk_tree_view_get_column(window->palettes, 1); + GtkTreeViewColumn *column_1 = gtk_tree_view_get_column(window->palettes, 2); + GtkTreeViewColumn *column_2 = gtk_tree_view_get_column(window->palettes, 3); + GtkTreeViewColumn *column_3 = gtk_tree_view_get_column(window->palettes, 4); + + gtk_tree_view_column_set_cell_data_func(column_0, GTK_CELL_RENDERER(window->palette_cell_renderer_0), palette_color_data_func, NULL, NULL); + gtk_tree_view_column_set_cell_data_func(column_1, GTK_CELL_RENDERER(window->palette_cell_renderer_1), palette_color_data_func, NULL, NULL); + gtk_tree_view_column_set_cell_data_func(column_2, GTK_CELL_RENDERER(window->palette_cell_renderer_2), palette_color_data_func, NULL, NULL); + gtk_tree_view_column_set_cell_data_func(column_3, GTK_CELL_RENDERER(window->palette_cell_renderer_3), palette_color_data_func, NULL, NULL); + } + else { + store = GTK_LIST_STORE(model); + gtk_list_store_clear(store); + } gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter); @@ -456,37 +520,27 @@ static void update_palettes(VramViewerWindow *window) { uint16_t color_2 = (window->palette_data[row][((2 + offset) << 1) + 1] << 8) | window->palette_data[row][((2 + offset) << 1)]; uint16_t color_3 = (window->palette_data[row][((3 + offset) << 1) + 1] << 8) | window->palette_data[row][((3 + offset) << 1)]; + g_autofree gchar *str_0 = g_strdup_printf("%s %d", row >=8 ? "Object" : "Background", row & 7); + g_autofree gchar *str_1 = g_strdup_printf("$%04x", color_0 & 0x7FFF); + g_autofree gchar *str_3 = g_strdup_printf("$%04x", color_1 & 0x7FFF); + g_autofree gchar *str_5 = g_strdup_printf("$%04x", color_2 & 0x7FFF); + g_autofree gchar *str_7 = g_strdup_printf("$%04x", color_3 & 0x7FFF); + gtk_list_store_insert_with_values(store, &iter, -1, - 0, g_strdup_printf("%s %d", row >=8 ? "Object" : "Background", row & 7), - 1, g_strdup_printf("$%04x", color_0 & 0x7FFF), + 0, str_0, + 1, str_1, 2, convert_color(color_0), - 3, g_strdup_printf("$%04x", color_1 & 0x7FFF), + 3, str_3, 4, convert_color(color_1), - 5, g_strdup_printf("$%04x", color_2 & 0x7FFF), + 5, str_5, 6, convert_color(color_2), - 7, g_strdup_printf("$%04x", color_3 & 0x7FFF), + 7, str_7, 8, convert_color(color_3), -1 ); } - GtkTreeViewColumn *column_0 = gtk_tree_view_get_column(window->palettes, 1); - GtkTreeViewColumn *column_1 = gtk_tree_view_get_column(window->palettes, 2); - GtkTreeViewColumn *column_2 = gtk_tree_view_get_column(window->palettes, 3); - GtkTreeViewColumn *column_3 = gtk_tree_view_get_column(window->palettes, 4); - - GtkCellRendererText *cell_renderer_0 = window->palette_cell_renderer_0; - GtkCellRendererText *cell_renderer_1 = window->palette_cell_renderer_1; - GtkCellRendererText *cell_renderer_2 = window->palette_cell_renderer_2; - GtkCellRendererText *cell_renderer_3 = window->palette_cell_renderer_3; - - gtk_tree_view_column_set_cell_data_func(column_0, GTK_CELL_RENDERER(cell_renderer_0), palette_color_data_func, NULL, NULL); - gtk_tree_view_column_set_cell_data_func(column_1, GTK_CELL_RENDERER(cell_renderer_1), palette_color_data_func, NULL, NULL); - gtk_tree_view_column_set_cell_data_func(column_2, GTK_CELL_RENDERER(cell_renderer_2), palette_color_data_func, NULL, NULL); - gtk_tree_view_column_set_cell_data_func(column_3, GTK_CELL_RENDERER(cell_renderer_3), palette_color_data_func, NULL, NULL); - - gtk_tree_view_set_model(window->palettes, GTK_TREE_MODEL(store)); - g_object_unref(store); + return false; } void vram_viewer_update(VramViewerWindow *window, GB_gameboy_t *gb) {