From 825786210a1f3aef0a15a388a26f60ab5a5c26f0 Mon Sep 17 00:00:00 2001 From: Maximilian Mader Date: Sun, 17 May 2020 05:33:41 +0200 Subject: [PATCH] [GTK3] Convert VRAM viewer into proper GTK widget --- gtk3/main.c | 536 ++--------------------------- gtk3/resources/ui/vram_viewer.ui | 516 ++++++++++++++++++++++++++++ gtk3/resources/ui/window.ui | 475 -------------------------- gtk3/sameboy.gresource.xml | 1 + gtk3/types.h | 21 +- gtk3/vram_viewer.c | 562 +++++++++++++++++++++++++++++++ gtk3/vram_viewer.h | 30 ++ 7 files changed, 1142 insertions(+), 999 deletions(-) create mode 100644 gtk3/resources/ui/vram_viewer.ui create mode 100644 gtk3/vram_viewer.c create mode 100644 gtk3/vram_viewer.h diff --git a/gtk3/main.c b/gtk3/main.c index be6e436..db7cc86 100644 --- a/gtk3/main.c +++ b/gtk3/main.c @@ -14,6 +14,8 @@ #include "shader.h" #include "check_menu_radio_group.h" +#include "vram_viewer.h" + // used for audio and game controllers #include "SDL.h" #include "../SDL/audio/audio.h" @@ -53,11 +55,6 @@ static GuiData gui_data = { .log_to_sidebar = false, .should_clear_sidebar = false, - .vram_viewer_visible = false, - .vram_viewer_updating = false, - .vram_viewer_active_tab = "", - .vram_viewer_is_cgb = false, - .audio_initialized = false, .border_mode_changed = false, @@ -118,34 +115,6 @@ static const GActionEntry app_entries[] = { { "toggle_mute", NULL, NULL, "false", on_mute_changed }, }; -static void palette_color_data_func(GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data_ptr) { - const gchar *title = gtk_tree_view_column_get_title(col); - const uint8_t color_index = g_ascii_strtoll(&title[6], NULL, 10); - const uint8_t column_index = 2 + (2 * color_index); - - GValue color_val = G_VALUE_INIT; - gtk_tree_model_get_value(model, iter, column_index, &color_val); - gint color = g_value_get_int(&color_val); - gchar *color_string = g_strdup_printf("#%06x", color); - - gint lightness = 0.299 * ((color >> 16) & 0xFF) + 0.587 * ((color >> 8) & 0xFF) + 0.114 * (color & 0xFF); - - GValue color_str = G_VALUE_INIT; - g_value_init(&color_str, G_TYPE_STRING); - g_value_set_string(&color_str, color_string); - g_object_set_property(G_OBJECT(renderer), "background", &color_str); - - GValue fg_color_str = G_VALUE_INIT; - g_value_init(&fg_color_str, G_TYPE_STRING); - g_value_set_static_string(&fg_color_str, (lightness > 0x7F)? "#000000" : "#FFFFFF"); - g_object_set_property(G_OBJECT(renderer), "foreground", &fg_color_str); - - g_value_unset(&color_val); - g_value_unset(&color_str); - g_value_unset(&fg_color_str); - g_free(color_string); -} - static const char* get_sdl_joystick_power_level_name(SDL_JoystickPowerLevel level) { switch (level) { case SDL_JOYSTICK_POWER_EMPTY: return "Empty"; @@ -718,17 +687,20 @@ static void update_viewport(void) { } } - unsigned new_width = x_factor * GB_get_screen_width(&gb); - unsigned new_height = y_factor * GB_get_screen_height(&gb); - gui_data.viewport = (Rect){ - (win_width - new_width) / 2, - (win_height - new_height) / 2, - new_width, - new_height - }; + if (gui_data.gl_area) { + unsigned new_width = x_factor * GB_get_screen_width(&gb); + unsigned new_height = y_factor * GB_get_screen_height(&gb); + + gui_data.viewport = (Rect){ + (win_width - new_width) / 2, + (win_height - new_height) / 2, + new_width, + new_height + }; - if (!gui_data.fallback_canvas) glViewport(gui_data.viewport.x, gui_data.viewport.y, gui_data.viewport.w, gui_data.viewport.h); + glViewport(gui_data.viewport.x, gui_data.viewport.y, gui_data.viewport.width, gui_data.viewport.height); + } } // WHY DO WE NEED SUCH AN UGLY METHOD, GTK?! @@ -789,8 +761,6 @@ static void update_window_geometry(void) { if (GB_is_inited(&gb)) { GB_set_pixels_output(&gb, get_pixels()); } - - update_viewport(); } static void stop(void) { @@ -811,140 +781,7 @@ static void stop(void) { gui_data.stopped = true; } -static void on_vblank(gpointer data) { - if (!gui_data.vram_viewer_updating && gui_data.vram_viewer_visible) { - gui_data.vram_viewer_updating = true; - - if (g_strcmp0("vram_viewer_sprites", gui_data.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? - - 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 - ); - - gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter); - - for (unsigned row = 0; row < gui_data.oam_count; ++row) { - GdkPixbuf *pixbuf = gdk_pixbuf_new_from_bytes( - g_bytes_new(gui_data.oam_info[row].image, 128 * sizeof(uint32_t)), - GDK_COLORSPACE_RGB, true, 8, 8, gui_data.oam_height, 8 * sizeof(uint32_t) - ); - - GdkPixbuf *dest = gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, 8, 8 * 2, gui_data.oam_height * 2); - - gdk_pixbuf_scale(pixbuf, dest, - 0, 0, 8 * 2, gui_data.oam_height * 2, - 0, 0, 2.0, 2.0, - GDK_INTERP_NEAREST - ); - - gtk_list_store_insert_with_values(store, &iter, -1, - 0, dest, - 1, g_strdup_printf("%i", gui_data.oam_info[row].x - 8), - 2, g_strdup_printf("%i", gui_data.oam_info[row].y - 16), - 3, g_strdup_printf("$%02x", gui_data.oam_info[row].tile), - 4, g_strdup_printf("$%04x", 0x8000 + gui_data.oam_info[row].tile * 0x10), - 5, g_strdup_printf("$%04x", gui_data.oam_info[row].oam_addr), - 6, gui_data.vram_viewer_is_cgb - ? g_strdup_printf("%c%c%c%d%d", - gui_data.oam_info[row].flags & 0x80? 'P' : '-', - gui_data.oam_info[row].flags & 0x40? 'Y' : '-', - gui_data.oam_info[row].flags & 0x20? 'X' : '-', - gui_data.oam_info[row].flags & 0x08? 1 : 0, - gui_data.oam_info[row].flags & 0x07) - : g_strdup_printf("%c%c%c%d", - gui_data.oam_info[row].flags & 0x80? 'P' : '-', - gui_data.oam_info[row].flags & 0x40? 'Y' : '-', - gui_data.oam_info[row].flags & 0x20? 'X' : '-', - gui_data.oam_info[row].flags & 0x10? 1 : 0), - -1 - ); - - g_object_unref(pixbuf); - g_object_unref(dest); - } - - gtk_tree_view_set_model(tree_view, GTK_TREE_MODEL(store)); - g_object_unref(store); - } - else if (g_strcmp0("vram_viewer_palettes", gui_data.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? - - GtkListStore *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 1 string - G_TYPE_INT, // Color 1 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 - ); - - gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter); - - for (unsigned row = 0; row < 16; ++row) { - uint8_t offset = (row & 7) * 4; - - uint16_t color_0 = (gui_data.vram_viewer_palette_data[row][((0 + offset) << 1) + 1] << 8) | gui_data.vram_viewer_palette_data[row][((0 + offset) << 1)]; - uint16_t color_1 = (gui_data.vram_viewer_palette_data[row][((1 + offset) << 1) + 1] << 8) | gui_data.vram_viewer_palette_data[row][((1 + offset) << 1)]; - uint16_t color_2 = (gui_data.vram_viewer_palette_data[row][((2 + offset) << 1) + 1] << 8) | gui_data.vram_viewer_palette_data[row][((2 + offset) << 1)]; - uint16_t color_3 = (gui_data.vram_viewer_palette_data[row][((3 + offset) << 1) + 1] << 8) | gui_data.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), - 1, g_strdup_printf("$%04x", color_0 & 0x7FFF), - 2, convert_color(color_0), - 3, g_strdup_printf("$%04x", color_1 & 0x7FFF), - 4, convert_color(color_1), - 5, g_strdup_printf("$%04x", color_2 & 0x7FFF), - 6, convert_color(color_2), - 7, g_strdup_printf("$%04x", color_3 & 0x7FFF), - 8, convert_color(color_3), - -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); - GtkTreeViewColumn *column_3 = gtk_tree_view_get_column(tree_view, 4); - - GtkCellRendererText *cell_renderer_0 = builder_get(GTK_CELL_RENDERER_TEXT, "vram_viewer_palette_cell_renderer_0"); - GtkCellRendererText *cell_renderer_1 = builder_get(GTK_CELL_RENDERER_TEXT, "vram_viewer_palette_cell_renderer_1"); - GtkCellRendererText *cell_renderer_2 = builder_get(GTK_CELL_RENDERER_TEXT, "vram_viewer_palette_cell_renderer_2"); - GtkCellRendererText *cell_renderer_3 = builder_get(GTK_CELL_RENDERER_TEXT, "vram_viewer_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(tree_view, GTK_TREE_MODEL(store)); - g_object_unref(store); - } - - // Queue a redraw of the VRAM viewer - gtk_widget_queue_draw(GTK_WIDGET(gui_data.vram_viewer)); - - gui_data.vram_viewer_updating = false; - } - +static void 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)); @@ -952,6 +789,8 @@ static void on_vblank(gpointer data) { else if (gui_data.gl_area) { gtk_gl_area_queue_render(gui_data.gl_area); } + + gtk_widget_queue_draw(GTK_WIDGET(gui_data.vram_viewer)); } static void vblank(GB_gameboy_t *gb) { @@ -987,68 +826,11 @@ static void vblank(GB_gameboy_t *gb) { } } - if (g_strcmp0("vram_viewer_tileset", gui_data.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, gui_data.tileset_buffer, - palette_type, - palette_index - ); - } - else if (g_strcmp0("vram_viewer_tilemap", gui_data.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, gui_data.tilemap_buffer, - palette_type, - palette_index, - map_type, - tileset_type - ); - - gui_data.scroll_rect = (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", gui_data.vram_viewer_active_tab) == 0) { - gui_data.oam_count = GB_get_oam_info(gb, gui_data.oam_info, &gui_data.oam_height); - gui_data.vram_viewer_is_cgb = GB_is_cgb(gb); - } - else if (g_strcmp0("vram_viewer_palettes", gui_data.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(gui_data.vram_viewer_palette_data[row], palette_data, size); - } - } - gui_data.do_rewind = gui_data.rewind_down; - g_idle_add((GSourceFunc) on_vblank, NULL); + vram_viewer_update(gui_data.vram_viewer, gb); + + g_idle_add((GSourceFunc) on_vblank, gb); } static void handle_events(GB_gameboy_t *gb) { @@ -1402,7 +1184,6 @@ static void quit(void) { g_debug("quit(void);"); stop(); - while (gui_data.stopping); GtkWindow *window = gui_data.main_window ? GTK_WINDOW(gui_data.main_window) : NULL; save_config(window, gui_data.config_modification_date); @@ -1496,249 +1277,6 @@ static void on_window_state_change(GtkWidget *w, GdkEventWindowState *event, gpo gui_data.is_fullscreen = event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN; } -// Gets called when the VRAM viewer gets realized -static void on_vram_viewer_realize(void) { - gui_data.vram_viewer_visible = true; - gui_data.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 -static void on_vram_viewer_unrealize(void) { - gui_data.vram_viewer_visible = false; -} - -// Gets called when the tileset viewer should be redrawn -static gboolean on_draw_vram_viewer_tileset(GtkWidget *widget, cairo_t *cr, gpointer data) { - g_mutex_lock(&gui_data.tileset_buffer_mutex); - - guint width, height; - GtkStyleContext *context; - - context = gtk_widget_get_style_context(widget); - width = gtk_widget_get_allocated_width(widget); - 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 *) gui_data.tileset_buffer, - CAIRO_FORMAT_RGB24, - 256, - 192, - cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, 256) - ); - - cairo_scale(cr, 2.0, 2.0); - cairo_set_source_surface(cr, surface, 0, 0); - cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_NEAREST); - cairo_paint(cr); - - if (gtk_toggle_button_get_active(builder_get(GTK_TOGGLE_BUTTON, "vram_viewer_tileset_toggle_grid_button"))) { - cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.25); - cairo_set_line_width(cr, 1); - - const int divisions_x = 256 / 8; - const int divisions_y = 192 / 8; - - for (int i = 0; i < divisions_x; i++) { - const int j = 256 * i; - - cairo_move_to(cr, j / divisions_x, 0); - cairo_line_to(cr, j / divisions_x, 192); - } - - for (int i = 0; i < divisions_y; i++) { - const int j = 192 * i; - - cairo_move_to(cr, 0, j / divisions_y); - cairo_line_to(cr, 256, j / divisions_y); - } - - cairo_stroke(cr); - } - - g_mutex_unlock(&gui_data.tileset_buffer_mutex); - return false; -} - -// Gets called when the tilemap viewer should be redrawn -static gboolean on_draw_vram_viewer_tilemap(GtkWidget *widget, cairo_t *cr, gpointer data) { - g_mutex_lock(&gui_data.tilemap_buffer_mutex); - - guint width, height; - GtkStyleContext *context; - - context = gtk_widget_get_style_context(widget); - width = gtk_widget_get_allocated_width(widget); - 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 *) gui_data.tilemap_buffer, - CAIRO_FORMAT_RGB24, - 256, - 256, - cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, 256) - ); - - cairo_scale(cr, 2.0, 2.0); - cairo_set_source_surface(cr, surface, 0, 0); - cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_NEAREST); - cairo_paint(cr); - - if (gtk_toggle_button_get_active(builder_get(GTK_TOGGLE_BUTTON, "vram_viewer_tilemap_toggle_grid_button"))) { - cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.25); - cairo_set_line_width(cr, 1); - - const int divisions = 256 / 8; - - for (int i = 0; i < divisions; i++) { - const int j = 256 * i; - - cairo_move_to(cr, j / divisions, 0); - cairo_line_to(cr, j / divisions, 256); - cairo_move_to(cr, 0, j / divisions); - cairo_line_to(cr, 256, j / divisions); - } - - cairo_stroke(cr); - } - - if (gtk_toggle_button_get_active(builder_get(GTK_TOGGLE_BUTTON, "vram_viewer_tilemap_toggle_scrolling_button"))) { - cairo_rectangle(cr, -2, -2, width + 2, height + 2); - - for (unsigned x = 0; x < 2; x++) { - for (unsigned y = 0; y < 2; y++) { - Rect rect = gui_data.scroll_rect; - rect.x -= 256 * x; - rect.y += 256 * y; - - cairo_rectangle(cr, rect.x, rect.y, rect.w, rect.h); - } - } - - cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD); - cairo_set_line_width(cr, 2); - cairo_set_line_join(cr, CAIRO_LINE_JOIN_ROUND); - cairo_set_source_rgba(cr, 0.2, 0.2, 0.2, 0.5); - cairo_fill_preserve(cr); - cairo_clip_preserve(cr); - cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.6); - cairo_stroke(cr); - } - - g_mutex_unlock(&gui_data.tilemap_buffer_mutex); - return false; -} - -static gboolean on_motion_vram_viewer_tileset(GtkWidget *widget, GdkEventMotion *event) { - int x, y; - - if (event->is_hint) { - gdk_window_get_pointer (event->window, &x, &y, NULL); - } - else { - x = event->x; - y = event->y; - } - - // Compensate for our canvas scale - x /= 2; - y /= 2; - - uint8_t bank = x >= 128? 1 : 0; - x &= 127; - uint16_t tile = x / 8 + y / 8 * 16; - - GtkLabel *status = builder_get(GTK_LABEL, "vram_viewer_status"); - gtk_label_set_text(status, g_strdup_printf("Tile number $%02x at %d:$%04x", tile & 0xFF, bank, 0x8000 + tile * 0x10)); - - return true; -} - -static gboolean on_motion_vram_viewer_tilemap(GtkWidget *widget, GdkEventMotion *event) { - int x, y; - - if (event->is_hint) { - gdk_window_get_pointer (event->window, &x, &y, NULL); - } - else { - x = event->x; - y = event->y; - } - - // Compensate for our canvas scale - x /= 2; - y /= 2; - - GtkLabel *status = builder_get(GTK_LABEL, "vram_viewer_status"); - - uint16_t map_offset = x / 8 + y / 8 * 32; - uint16_t map_base = 0x1800; - - 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; - } - - uint8_t lcdc = ((uint8_t *)GB_get_direct_access(&gb, GB_DIRECT_ACCESS_IO, NULL, NULL))[GB_IO_LCDC]; - uint8_t *vram = GB_get_direct_access(&gb, GB_DIRECT_ACCESS_VRAM, NULL, NULL); - - if (map_type == GB_MAP_9C00 || (map_type == GB_MAP_AUTO && lcdc & 0x08)) { - map_base = 0x1c00; - } - - if (tileset_type == GB_TILESET_AUTO) { - tileset_type = (lcdc & 0x10)? GB_TILESET_8800 : GB_TILESET_8000; - } - - uint8_t tile = vram[map_base + map_offset]; - uint16_t tile_address = 0; - if (tileset_type == GB_TILESET_8000) { - tile_address = 0x8000 + tile * 0x10; - } - else { - tile_address = 0x9000 + (int8_t)tile * 0x10; - } - - if (GB_is_cgb(&gb)) { - uint8_t attributes = 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)", - tile, - attributes & 0x8? 1 : 0, - tile_address, - 0x8000 + map_base + map_offset, - (attributes & 0x80) ? 'P' : '-', - (attributes & 0x40) ? 'V' : '-', - (attributes & 0x20) ? 'H' : '-', - attributes & 0x8? 1 : 0, - attributes & 0x7 - )); - } - else { - gtk_label_set_text(status, g_strdup_printf("Tile number $%02x ($%04x) at map address $%04x", - tile, - tile_address, - 0x8000 + map_base + map_offset - )); - } - - return true; -} - -static void on_vram_tab_change(GtkWidget *widget, GParamSpec *pspec, GtkStackSwitcher *self) { - gtk_label_set_text(builder_get(GTK_LABEL, "vram_viewer_status"), ""); - gui_data.vram_viewer_active_tab = (gchar *)gtk_stack_get_visible_child_name(builder_get(GTK_STACK, "vram_viewer_stack")); -} - // This functions gets called immediately after registration of the GApplication static void startup(GApplication *app, gpointer null_ptr) { signal(SIGINT, quit_interrupt); @@ -1774,7 +1312,7 @@ static void startup(GApplication *app, gpointer null_ptr) { g_signal_connect(gui_data.preferences, "realize", G_CALLBACK(on_preferences_realize), (gpointer) gui_data.builder); init_config(app, gui_data.cli_options.config_path, &gui_data.config_modification_date, gui_data.preferences); - gui_data.vram_viewer = GTK_WINDOW(get_object("vram_viewer")); + gui_data.vram_viewer = vram_viewer_new(); gui_data.memory_viewer = GTK_WINDOW(get_object("memory_viewer")); gui_data.console = GTK_WINDOW(get_object("console")); @@ -1890,26 +1428,12 @@ static void connect_signal_handlers(GApplication *app) { g_signal_connect(gui_data.main_window, "key_release_event", G_CALLBACK(on_key_press), NULL); g_signal_connect(gui_data.main_window, "window-state-event", G_CALLBACK(on_window_state_change), NULL); - g_signal_connect(gui_data.vram_viewer, "realize", G_CALLBACK(on_vram_viewer_realize), NULL); - g_signal_connect(gui_data.vram_viewer, "unrealize", G_CALLBACK(on_vram_viewer_unrealize), NULL); - // Just hide our sub-windows when closing them g_signal_connect(gui_data.preferences, "delete-event", G_CALLBACK(gtk_widget_hide_on_delete), NULL); g_signal_connect(gui_data.vram_viewer, "delete-event", G_CALLBACK(gtk_widget_hide_on_delete), NULL); g_signal_connect(gui_data.memory_viewer, "delete-event", G_CALLBACK(gtk_widget_hide_on_delete), NULL); g_signal_connect(gui_data.console, "delete-event", G_CALLBACK(gtk_widget_hide_on_delete), NULL); g_signal_connect(gui_data.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); - - gtk_widget_add_events(builder_get(GTK_WIDGET, "vram_viewer_tileset_canvas"), GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK); - gtk_widget_add_events(builder_get(GTK_WIDGET, "vram_viewer_tilemap_canvas"), GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK); - - g_signal_connect(get_object("vram_viewer_tileset_canvas"), "motion_notify_event", G_CALLBACK(on_motion_vram_viewer_tileset), NULL); - g_signal_connect(get_object("vram_viewer_tilemap_canvas"), "motion_notify_event", G_CALLBACK(on_motion_vram_viewer_tilemap), NULL); - - g_signal_connect(get_object("vram_viewer_stack"), "notify::visible-child", G_CALLBACK(on_vram_tab_change), NULL); } // TODO: Comment @@ -1942,7 +1466,7 @@ static void gl_draw(void) { render_bitmap_with_shader( &gui_data.shader, _pixels, previous, GB_get_screen_width(&gb), GB_get_screen_height(&gb), - gui_data.viewport.x, gui_data.viewport.y, gui_data.viewport.w, gui_data.viewport.h, + gui_data.viewport.x, gui_data.viewport.y, gui_data.viewport.width, gui_data.viewport.height, mode ); } @@ -1965,6 +1489,7 @@ static gboolean on_draw_fallback(GtkWidget *widget, cairo_t *cr, gpointer data) guint screen_height = GB_get_screen_height(&gb); gtk_render_background(context, cr, 0, 0, width, height); + gtk_render_frame(context, cr, 0, 0, width, height); cairo_surface_t *surface = cairo_image_surface_create_for_data( (unsigned char *) get_current_buffer(), @@ -1975,7 +1500,7 @@ static gboolean on_draw_fallback(GtkWidget *widget, cairo_t *cr, gpointer data) ); cairo_translate(cr, gui_data.viewport.x, gui_data.viewport.y); - cairo_scale(cr, gui_data.viewport.w / screen_width, gui_data.viewport.h / screen_height); + cairo_scale(cr, gui_data.viewport.width / screen_width, gui_data.viewport.height / screen_height); cairo_set_source_surface(cr, surface, 0, 0); cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_NEAREST); cairo_paint(cr); @@ -2103,7 +1628,6 @@ static void shutdown(GApplication *app, GFile **files, gint n_files, const gchar g_debug("SHUTDOWN"); stop(); - while (gui_data.stopping); SDL_Quit(); if (gui_data.image_buffers[0]) g_free(gui_data.image_buffers[0]); @@ -2185,13 +1709,13 @@ static void close_rom(void) { } // Clear the VRAM viewer - g_mutex_lock(&gui_data.tileset_buffer_mutex); - memset(gui_data.tileset_buffer, 0, sizeof gui_data.tileset_buffer); - g_mutex_unlock(&gui_data.tileset_buffer_mutex); + // g_mutex_lock(&gui_data.tileset_buffer_mutex); + // memset(gui_data.tileset_buffer, 0, sizeof gui_data.tileset_buffer); + // g_mutex_unlock(&gui_data.tileset_buffer_mutex); - g_mutex_lock(&gui_data.tilemap_buffer_mutex); - memset(gui_data.tilemap_buffer, 0, sizeof gui_data.tilemap_buffer); - g_mutex_unlock(&gui_data.tilemap_buffer_mutex); + // g_mutex_lock(&gui_data.tilemap_buffer_mutex); + // memset(gui_data.tilemap_buffer, 0, sizeof gui_data.tilemap_buffer); + // g_mutex_unlock(&gui_data.tilemap_buffer_mutex); gtk_stack_set_visible_child_name(builder_get(GTK_STACK, "vram_viewer_stack"), "vram_viewer_tileset"); gtk_tree_view_set_model(builder_get(GTK_TREE_VIEW, "vram_viewer_sprites"), NULL); diff --git a/gtk3/resources/ui/vram_viewer.ui b/gtk3/resources/ui/vram_viewer.ui new file mode 100644 index 0000000..574d3ed --- /dev/null +++ b/gtk3/resources/ui/vram_viewer.ui @@ -0,0 +1,516 @@ + + + + + + + + + + + diff --git a/gtk3/resources/ui/window.ui b/gtk3/resources/ui/window.ui index b275a65..6ff6464 100644 --- a/gtk3/resources/ui/window.ui +++ b/gtk3/resources/ui/window.ui @@ -1624,479 +1624,4 @@ Maximilian Mader https://github.com/max-m - - False - VRAM Viewer - False - - - True - False - 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/sameboy.gresource.xml b/gtk3/sameboy.gresource.xml index 289a671..3a8cf41 100644 --- a/gtk3/sameboy.gresource.xml +++ b/gtk3/sameboy.gresource.xml @@ -2,6 +2,7 @@ ui/window.ui + ui/vram_viewer.ui