diff --git a/gtk3/main.c b/gtk3/main.c index 9af7af5..7e996ac 100644 --- a/gtk3/main.c +++ b/gtk3/main.c @@ -52,6 +52,10 @@ static char *battery_save_path_ptr; static Rect viewport = {0}; static Rect scrollRect = {0}; static bool vram_viewer_visible = false; +static bool vram_viewer_updating = false; +static gchar *vram_viewer_active_tab = ""; +static gboolean vram_viewer_is_cgb = false; +static uint8_t vram_viewer_palette_data[16][0x40]; static bool running = false; static bool stopping = false; @@ -1124,6 +1128,7 @@ static void resize() { // Gets called when the VRAM viewer gets realized static void on_vram_viewer_realize() { vram_viewer_visible = true; + vram_viewer_active_tab = (gchar *)gtk_stack_get_visible_child_name(builder_get(GTK_STACK, "vram_viewer_stack")); } // Gets called when the VRAM viewer gets unrealized @@ -1354,6 +1359,7 @@ static gboolean on_motion_vram_viewer_tilemap(GtkWidget *widget, GdkEventMotion static void on_vram_tab_change(GtkWidget *widget, GParamSpec *pspec, GtkStackSwitcher *self) { gtk_label_set_text(builder_get(GTK_LABEL, "vram_viewer_status"), ""); + vram_viewer_active_tab = (gchar *)gtk_stack_get_visible_child_name(builder_get(GTK_STACK, "vram_viewer_stack")); } G_MODULE_EXPORT void on_boot_rom_location_changed(GtkWidget *w, gpointer user_data_gptr) { @@ -1651,64 +1657,10 @@ static void palette_color_data_func(GtkTreeViewColumn *col, GtkCellRenderer *ren } static void on_vblank(gpointer data) { - // Queue drawing of the current frame - if (fallback_canvas) { - gtk_widget_queue_draw(GTK_WIDGET(main_window)); - } - else if (gl_area) { - gtk_gl_area_queue_render(gl_area); - } - - if (vram_viewer_visible) { - const gchar *active = gtk_stack_get_visible_child_name(builder_get(GTK_STACK, "vram_viewer_stack")); + if (!vram_viewer_updating && vram_viewer_visible) { + vram_viewer_updating = true; - if (g_strcmp0("vram_viewer_tileset", active) == 0) { - const gchar *palette_id = gtk_combo_box_get_active_id(builder_get(GTK_COMBO_BOX, "vram_viewer_tileset_palette_selector")); - - GB_palette_type_t palette_type = g_str_has_prefix(palette_id, "bg")? GB_PALETTE_BACKGROUND : GB_PALETTE_OAM; - uint8_t palette_index = g_ascii_digit_value(palette_id[palette_type == GB_PALETTE_OAM ? 3 : 2]); - - GB_draw_tileset(&gb, tileset_buffer, - palette_type, - palette_index - ); - } - else if (g_strcmp0("vram_viewer_tilemap", active) == 0) { - const gchar *palette_id = gtk_combo_box_get_active_id(builder_get(GTK_COMBO_BOX, "vram_viewer_tilemap_palette_selector")); - uint8_t palette_index = 0; - GB_palette_type_t palette_type = GB_PALETTE_AUTO; - - if (g_strcmp0("auto", palette_id) != 0) { - palette_type = g_str_has_prefix(palette_id, "bg")? GB_PALETTE_BACKGROUND : GB_PALETTE_OAM; - palette_index = g_ascii_digit_value(palette_id[palette_type == GB_PALETTE_OAM ? 3 : 2]); - } - - GB_map_type_t map_type = GB_MAP_AUTO; - const gchar *map_type_id = gtk_combo_box_get_active_id(builder_get(GTK_COMBO_BOX, "vram_viewer_tilemap_tilemap_selector")); - if (g_strcmp0("auto", map_type_id) != 0) { - map_type = (g_strcmp0("9800", map_type_id) == 0)? GB_MAP_9800 : GB_MAP_9C00; - } - - GB_tileset_type_t tileset_type = GB_TILESET_AUTO; - const gchar *tileset_type_id = gtk_combo_box_get_active_id(builder_get(GTK_COMBO_BOX, "vram_viewer_tilemap_tileset_selector")); - if (g_strcmp0("auto", tileset_type_id) != 0) { - tileset_type = (g_strcmp0("8800", tileset_type_id) == 0)? GB_TILESET_8800 : GB_TILESET_8000; - } - - GB_draw_tilemap(&gb, tilemap_buffer, - palette_type, - palette_index, - map_type, - tileset_type - ); - - scrollRect = (Rect){ - GB_read_memory(&gb, 0xFF00 | GB_IO_SCX), - GB_read_memory(&gb, 0xFF00 | GB_IO_SCY), - 160, 144 - }; - } - else if (g_strcmp0("vram_viewer_sprites", active) == 0) { + if (g_strcmp0("vram_viewer_sprites", vram_viewer_active_tab) == 0) { GtkTreeIter iter; GtkTreeView *tree_view = builder_get(GTK_TREE_VIEW, "vram_viewer_sprites"); // gtk_tree_view_set_model(tree_view, NULL); // Do we need this? @@ -1725,8 +1677,6 @@ static void on_vblank(gpointer data) { gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter); - oamCount = GB_get_oam_info(&gb, oamInfo, &oamHeight); - for (unsigned row = 0; row < oamCount; ++row) { GdkPixbuf *pixbuf = gdk_pixbuf_new_from_bytes( g_bytes_new(oamInfo[row].image, 128 * sizeof(uint32_t)), @@ -1748,7 +1698,7 @@ static void on_vblank(gpointer data) { 3, g_strdup_printf("$%02x", oamInfo[row].tile), 4, g_strdup_printf("$%04x", 0x8000 + oamInfo[row].tile * 0x10), 5, g_strdup_printf("$%04x", oamInfo[row].oam_addr), - 6, GB_is_cgb(&gb) + 6, vram_viewer_is_cgb ? g_strdup_printf("%c%c%c%d%d", oamInfo[row].flags & 0x80? 'P' : '-', oamInfo[row].flags & 0x40? 'Y' : '-', @@ -1770,7 +1720,7 @@ static void on_vblank(gpointer data) { gtk_tree_view_set_model(tree_view, GTK_TREE_MODEL(store)); g_object_unref(store); } - else if (g_strcmp0("vram_viewer_palettes", active) == 0) { + else if (g_strcmp0("vram_viewer_palettes", vram_viewer_active_tab) == 0) { GtkTreeIter iter; GtkTreeView *tree_view = builder_get(GTK_TREE_VIEW, "vram_viewer_palettes"); // gtk_tree_view_set_model(tree_view, NULL); // Do we need this? @@ -1794,13 +1744,12 @@ static void on_vblank(gpointer data) { gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter); for (unsigned row = 0; row < 16; ++row) { - uint8_t *palette_data = GB_get_direct_access(&gb, row >= 8? GB_DIRECT_ACCESS_OBP : GB_DIRECT_ACCESS_BGP, NULL, NULL); uint8_t offset = (row & 7) * 4; - uint16_t color_0 = (palette_data[((0 + offset) << 1) + 1] << 8) | palette_data[((0 + offset) << 1)]; - uint16_t color_1 = (palette_data[((1 + offset) << 1) + 1] << 8) | palette_data[((1 + offset) << 1)]; - uint16_t color_2 = (palette_data[((2 + offset) << 1) + 1] << 8) | palette_data[((2 + offset) << 1)]; - uint16_t color_3 = (palette_data[((3 + offset) << 1) + 1] << 8) | palette_data[((3 + offset) << 1)]; + uint16_t color_0 = (vram_viewer_palette_data[row][((0 + offset) << 1) + 1] << 8) | vram_viewer_palette_data[row][((0 + offset) << 1)]; + uint16_t color_1 = (vram_viewer_palette_data[row][((1 + offset) << 1) + 1] << 8) | vram_viewer_palette_data[row][((1 + offset) << 1)]; + uint16_t color_2 = (vram_viewer_palette_data[row][((2 + offset) << 1) + 1] << 8) | vram_viewer_palette_data[row][((2 + offset) << 1)]; + uint16_t color_3 = (vram_viewer_palette_data[row][((3 + offset) << 1) + 1] << 8) | vram_viewer_palette_data[row][((3 + offset) << 1)]; gtk_list_store_insert_with_values(store, &iter, -1, 0, g_strdup_printf("%s %d", row >=8 ? "Object" : "Background", row & 7), @@ -1815,7 +1764,7 @@ static void on_vblank(gpointer data) { -1 ); } - + GtkTreeViewColumn *column_0 = gtk_tree_view_get_column(tree_view, 1); GtkTreeViewColumn *column_1 = gtk_tree_view_get_column(tree_view, 2); GtkTreeViewColumn *column_2 = gtk_tree_view_get_column(tree_view, 3); @@ -1837,6 +1786,16 @@ static void on_vblank(gpointer data) { // Queue a redraw of the VRAM viewer gtk_widget_queue_draw(GTK_WIDGET(vram_viewer)); + + vram_viewer_updating = false; + } + + // Queue drawing of the current frame + if (fallback_canvas) { + gtk_widget_queue_draw(GTK_WIDGET(main_window)); + } + else if (gl_area) { + gtk_gl_area_queue_render(gl_area); } } @@ -1844,8 +1803,6 @@ static void vblank(GB_gameboy_t *gb) { flip(); GB_set_pixels_output(gb, get_pixels()); - g_idle_add((GSourceFunc) on_vblank, NULL); - if (underclock_down && clock_mutliplier > 0.5) { clock_mutliplier -= 1.0/16; GB_set_clock_multiplier(gb, clock_mutliplier); @@ -1855,7 +1812,68 @@ static void vblank(GB_gameboy_t *gb) { GB_set_clock_multiplier(gb, clock_mutliplier); } + if (g_strcmp0("vram_viewer_tileset", vram_viewer_active_tab) == 0) { + const gchar *palette_id = gtk_combo_box_get_active_id(builder_get(GTK_COMBO_BOX, "vram_viewer_tileset_palette_selector")); + + GB_palette_type_t palette_type = g_str_has_prefix(palette_id, "bg")? GB_PALETTE_BACKGROUND : GB_PALETTE_OAM; + uint8_t palette_index = g_ascii_digit_value(palette_id[palette_type == GB_PALETTE_OAM ? 3 : 2]); + + GB_draw_tileset(gb, tileset_buffer, + palette_type, + palette_index + ); + } + else if (g_strcmp0("vram_viewer_tilemap", vram_viewer_active_tab) == 0) { + const gchar *palette_id = gtk_combo_box_get_active_id(builder_get(GTK_COMBO_BOX, "vram_viewer_tilemap_palette_selector")); + uint8_t palette_index = 0; + GB_palette_type_t palette_type = GB_PALETTE_AUTO; + + if (g_strcmp0("auto", palette_id) != 0) { + palette_type = g_str_has_prefix(palette_id, "bg")? GB_PALETTE_BACKGROUND : GB_PALETTE_OAM; + palette_index = g_ascii_digit_value(palette_id[palette_type == GB_PALETTE_OAM ? 3 : 2]); + } + + GB_map_type_t map_type = GB_MAP_AUTO; + const gchar *map_type_id = gtk_combo_box_get_active_id(builder_get(GTK_COMBO_BOX, "vram_viewer_tilemap_tilemap_selector")); + if (g_strcmp0("auto", map_type_id) != 0) { + map_type = (g_strcmp0("9800", map_type_id) == 0)? GB_MAP_9800 : GB_MAP_9C00; + } + + GB_tileset_type_t tileset_type = GB_TILESET_AUTO; + const gchar *tileset_type_id = gtk_combo_box_get_active_id(builder_get(GTK_COMBO_BOX, "vram_viewer_tilemap_tileset_selector")); + if (g_strcmp0("auto", tileset_type_id) != 0) { + tileset_type = (g_strcmp0("8800", tileset_type_id) == 0)? GB_TILESET_8800 : GB_TILESET_8000; + } + + GB_draw_tilemap(gb, tilemap_buffer, + palette_type, + palette_index, + map_type, + tileset_type + ); + + scrollRect = (Rect){ + GB_read_memory(gb, 0xFF00 | GB_IO_SCX), + GB_read_memory(gb, 0xFF00 | GB_IO_SCY), + 160, 144 + }; + } + else if (g_strcmp0("vram_viewer_sprites", vram_viewer_active_tab) == 0) { + oamCount = GB_get_oam_info(gb, oamInfo, &oamHeight); + vram_viewer_is_cgb = GB_is_cgb(gb); + } + else if (g_strcmp0("vram_viewer_palettes", vram_viewer_active_tab) == 0) { + size_t size; + + for (unsigned row = 0; row < 16; ++row) { + uint8_t *palette_data = GB_get_direct_access(gb, row >= 8? GB_DIRECT_ACCESS_OBP : GB_DIRECT_ACCESS_BGP, &size, NULL); + memcpy(vram_viewer_palette_data[row], palette_data, size); + } + } + do_rewind = rewind_down; + + g_idle_add((GSourceFunc) on_vblank, NULL); } static void run(GuiData *gui_data) {