[GTK3] Implement VRAM tile information on hover

This commit is contained in:
Maximilian Mader 2019-10-05 16:21:53 +02:00
parent 13d849cb41
commit b23399c9ca
Signed by: Max
GPG Key ID: F71D56A3151C4FB3
3 changed files with 140 additions and 27 deletions

View File

@ -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);

View File

@ -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);

View File

@ -595,23 +595,6 @@ Maximilian Mader https://github.com/max-m</property>
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="aspect_ratio_toggle">
<property name="label" translatable="yes">Keep Aspect Ratio</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="margin_top">5</property>
<property name="margin_bottom">10</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="on_keep_aspect_ratio_changed" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">4</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="integer_scaling_toggle">
<property name="label" translatable="yes">Use Integer Scaling</property>
@ -629,6 +612,23 @@ Maximilian Mader https://github.com/max-m</property>
<property name="position">4</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="aspect_ratio_toggle">
<property name="label" translatable="yes">Keep Aspect Ratio</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="margin_top">5</property>
<property name="margin_bottom">10</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="on_keep_aspect_ratio_changed" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">4</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="menubar_override_selector_label">
<property name="can_focus">False</property>
@ -1580,20 +1580,16 @@ Maximilian Mader https://github.com/max-m</property>
</packing>
</child>
<child>
<object class="GtkStatusbar" id="vram_viewer_status">
<object class="GtkLabel" id="vram_viewer_status">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">10</property>
<property name="margin_right">10</property>
<property name="margin_start">10</property>
<property name="margin_end">10</property>
<property name="margin_top">6</property>
<property name="margin_bottom">6</property>
<property name="orientation">vertical</property>
<property name="spacing">2</property>
<property name="margin_bottom">5</property>
<property name="justify">center</property>
<property name="single_line_mode">True</property>
<property name="track_visited_links">False</property>
</object>
<packing>
<property name="expand">False</property>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>