diff --git a/gtk3/main.c b/gtk3/main.c index 7984917..9f20fed 100644 --- a/gtk3/main.c +++ b/gtk3/main.c @@ -468,6 +468,14 @@ static void activate(GApplication *app, gpointer user_data_gptr) { 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); + // create our renderer area if (supports_gl) { gl_area = GTK_GL_AREA(gtk_gl_area_new()); @@ -826,6 +834,112 @@ static gboolean on_draw_vram_viewer_tilemap(GtkWidget *widget, cairo_t *cr, gpoi 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"), ""); +} + G_MODULE_EXPORT void on_boot_rom_location_changed(GtkWidget *w, gpointer user_data_gptr) { GtkComboBox *box = GTK_COMBO_BOX(w); const gchar *id = gtk_combo_box_get_active_id(box); diff --git a/gtk3/main.h b/gtk3/main.h index b597863..08292e5 100644 --- a/gtk3/main.h +++ b/gtk3/main.h @@ -88,6 +88,9 @@ static void on_vram_viewer_realize(); static void on_vram_viewer_unrealize(); static gboolean on_draw_vram_viewer_tilemap(GtkWidget *widget, cairo_t *cr, gpointer data); static gboolean on_draw_vram_viewer_tileset(GtkWidget *widget, cairo_t *cr, gpointer data); +static gboolean on_motion_vram_viewer_tileset(GtkWidget *widget, GdkEventMotion *event); +static gboolean on_motion_vram_viewer_tilemap(GtkWidget *widget, GdkEventMotion *event); +static void on_vram_tab_change(GtkWidget *widget, GParamSpec *pspec, GtkStackSwitcher *self); // Option bindings G_MODULE_EXPORT void on_boot_rom_location_changed(GtkWidget *w, gpointer user_data_gptr); diff --git a/gtk3/resources/ui/window.ui b/gtk3/resources/ui/window.ui index de839b1..cddc669 100644 --- a/gtk3/resources/ui/window.ui +++ b/gtk3/resources/ui/window.ui @@ -595,23 +595,6 @@ Maximilian Mader https://github.com/max-m 3 - - - Keep Aspect Ratio - True - True - False - 5 - 10 - True - - - - False - True - 4 - - Use Integer Scaling @@ -629,6 +612,23 @@ Maximilian Mader https://github.com/max-m 4 + + + Keep Aspect Ratio + True + True + False + 5 + 10 + True + + + + False + True + 4 + + False @@ -1580,20 +1580,16 @@ Maximilian Mader https://github.com/max-m - + True False - 10 - 10 - 10 - 10 - 6 - 6 - vertical - 2 + 5 + center + True + False - False + True True 2