[GTK3] Implement palette viewer

This commit is contained in:
Maximilian Mader 2019-10-05 00:57:03 +02:00
parent 36299d124a
commit 94e1b397ca
Signed by: Max
GPG Key ID: F71D56A3151C4FB3
3 changed files with 227 additions and 137 deletions

View File

@ -1006,6 +1006,42 @@ static void handle_events(GB_gameboy_t *gb) {
GB_set_key_state(gb, GB_KEY_START, pressed_buttons & BUTTON_MASK_START); GB_set_key_state(gb, GB_KEY_START, pressed_buttons & BUTTON_MASK_START);
} }
static uint32_t convert_color(uint16_t color) {
const uint8_t r = ((uint16_t)(color & 0x1F) * 255) / 31;
const uint8_t g = ((uint16_t)((color >> 5) & 0x1F) * 255) / 31;
const uint8_t b = ((uint16_t)((color >> 10) & 0x1F) * 255) / 31;
return (r << 16) | (g << 8) | b;
}
static void palette_color_data_func(GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data) {
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 void vblank(GB_gameboy_t *gb) { static void vblank(GB_gameboy_t *gb) {
flip(); flip();
GB_set_pixels_output(gb, get_pixels()); GB_set_pixels_output(gb, get_pixels());
@ -1068,10 +1104,20 @@ static void vblank(GB_gameboy_t *gb) {
}; };
} }
else if (g_strcmp0("vram_viewer_sprites", active) == 0) { else if (g_strcmp0("vram_viewer_sprites", active) == 0) {
GtkListStore *store = builder_get(GTK_LIST_STORE, "sprite_list_store");
GtkTreeIter iter; 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_list_store_clear(store);
gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter); gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter);
oamCount = GB_get_oam_info(gb, oamInfo, &oamHeight); oamCount = GB_get_oam_info(gb, oamInfo, &oamHeight);
@ -1090,8 +1136,6 @@ static void vblank(GB_gameboy_t *gb) {
GDK_INTERP_NEAREST GDK_INTERP_NEAREST
); );
g_object_unref(pixbuf);
gtk_list_store_insert_with_values(store, &iter, -1, gtk_list_store_insert_with_values(store, &iter, -1,
0, dest, 0, dest,
1, itoa(oamInfo[row].x - 8), 1, itoa(oamInfo[row].x - 8),
@ -1113,10 +1157,77 @@ static void vblank(GB_gameboy_t *gb) {
oamInfo[row].flags & 0x10? 1 : 0), oamInfo[row].flags & 0x10? 1 : 0),
-1 -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", active) == 0) { else if (g_strcmp0("vram_viewer_palettes", active) == 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 *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)];
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 // Queue a redraw of the VRAM viewer

View File

@ -108,6 +108,8 @@ static void update_viewport(void);
static void update_window_geometry(); static void update_window_geometry();
static void handle_events(GB_gameboy_t *gb); static void handle_events(GB_gameboy_t *gb);
static uint32_t convert_color(uint16_t color);
static void palette_color_data_func(GtkTreeViewColumn *col, GtkCellRenderer *renderer, GtkTreeModel *model, GtkTreeIter *iter, gpointer user_data);
static void vblank(GB_gameboy_t *gb); static void vblank(GB_gameboy_t *gb);
static void run(GApplication *app, UserData *user_data); static void run(GApplication *app, UserData *user_data);

View File

@ -595,23 +595,6 @@ Maximilian Mader https://github.com/max-m</property>
<property name="position">3</property> <property name="position">3</property>
</packing> </packing>
</child> </child>
<child>
<object class="GtkCheckButton" id="integer_scaling_toggle">
<property name="label" translatable="yes">Use Integer Scaling</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_use_integer_scaling_changed" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">4</property>
</packing>
</child>
<child> <child>
<object class="GtkCheckButton" id="aspect_ratio_toggle"> <object class="GtkCheckButton" id="aspect_ratio_toggle">
<property name="label" translatable="yes">Keep Aspect Ratio</property> <property name="label" translatable="yes">Keep Aspect Ratio</property>
@ -629,6 +612,23 @@ Maximilian Mader https://github.com/max-m</property>
<property name="position">4</property> <property name="position">4</property>
</packing> </packing>
</child> </child>
<child>
<object class="GtkCheckButton" id="integer_scaling_toggle">
<property name="label" translatable="yes">Use Integer Scaling</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_use_integer_scaling_changed" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">4</property>
</packing>
</child>
<child> <child>
<object class="GtkLabel" id="menubar_override_selector_label"> <object class="GtkLabel" id="menubar_override_selector_label">
<property name="can_focus">False</property> <property name="can_focus">False</property>
@ -1120,35 +1120,6 @@ Maximilian Mader https://github.com/max-m</property>
</object> </object>
</child> </child>
</object> </object>
<object class="GtkListStore" id="sprite_list_store">
<columns>
<!-- column-name Sprite -->
<column type="GdkPixbuf"/>
<!-- column-name X -->
<column type="gchararray"/>
<!-- column-name Y -->
<column type="gchararray"/>
<!-- column-name Tile -->
<column type="gchararray"/>
<!-- column-name Tile1 -->
<column type="gchararray"/>
<!-- column-name OAM -->
<column type="gchararray"/>
<!-- column-name Attributes -->
<column type="gchararray"/>
</columns>
<data>
<row>
<col id="0"/>
<col id="1" translatable="yes">148</col>
<col id="2" translatable="yes">2</col>
<col id="3" translatable="yes">$7f</col>
<col id="4" translatable="yes">$87f0</col>
<col id="5" translatable="yes">$fe20</col>
<col id="6" translatable="yes">---01</col>
</row>
</data>
</object>
<object class="GtkWindow" id="vram_viewer"> <object class="GtkWindow" id="vram_viewer">
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="title" translatable="yes">VRAM Viewer</property> <property name="title" translatable="yes">VRAM Viewer</property>
@ -1426,91 +1397,98 @@ Maximilian Mader https://github.com/max-m</property>
</packing> </packing>
</child> </child>
<child> <child>
<object class="GtkTreeView" id="vram_viewer_sprites"> <object class="GtkScrolledWindow">
<property name="width_request">512</property>
<property name="height_request">512</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="model">sprite_list_store</property> <property name="shadow_type">in</property>
<property name="headers_clickable">False</property>
<property name="rules_hint">True</property>
<property name="enable_search">False</property>
<property name="enable_grid_lines">horizontal</property>
<child internal-child="selection">
<object class="GtkTreeSelection"/>
</child>
<child> <child>
<object class="GtkTreeViewColumn"> <object class="GtkTreeView" id="vram_viewer_sprites">
<property name="min_width">32</property> <property name="visible">True</property>
<child> <property name="can_focus">True</property>
<object class="GtkCellRendererPixbuf"/> <property name="headers_clickable">False</property>
<attributes> <property name="enable_search">False</property>
<attribute name="pixbuf">0</attribute> <property name="show_expanders">False</property>
</attributes> <child internal-child="selection">
<object class="GtkTreeSelection"/>
</child> </child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn">
<property name="title" translatable="yes">X</property>
<child> <child>
<object class="GtkCellRendererText"/> <object class="GtkTreeViewColumn">
<attributes> <property name="min_width">32</property>
<attribute name="text">1</attribute> <child>
</attributes> <object class="GtkCellRendererPixbuf"/>
<attributes>
<attribute name="pixbuf">0</attribute>
</attributes>
</child>
</object>
</child> </child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn">
<property name="title" translatable="yes">Y</property>
<child> <child>
<object class="GtkCellRendererText"/> <object class="GtkTreeViewColumn">
<attributes> <property name="title" translatable="yes">X</property>
<attribute name="text">2</attribute> <child>
</attributes> <object class="GtkCellRendererText"/>
<attributes>
<attribute name="text">1</attribute>
</attributes>
</child>
</object>
</child> </child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn">
<property name="title" translatable="yes">Tile</property>
<child> <child>
<object class="GtkCellRendererText"/> <object class="GtkTreeViewColumn">
<attributes> <property name="title" translatable="yes">Y</property>
<attribute name="text">3</attribute> <child>
</attributes> <object class="GtkCellRendererText"/>
<attributes>
<attribute name="text">2</attribute>
</attributes>
</child>
</object>
</child> </child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn">
<property name="title" translatable="yes">Tile Addr.</property>
<child> <child>
<object class="GtkCellRendererText"/> <object class="GtkTreeViewColumn">
<attributes> <property name="title" translatable="yes">Tile</property>
<attribute name="text">4</attribute> <child>
</attributes> <object class="GtkCellRendererText"/>
<attributes>
<attribute name="text">3</attribute>
</attributes>
</child>
</object>
</child> </child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn">
<property name="title" translatable="yes">OAM Addr.</property>
<child> <child>
<object class="GtkCellRendererText"/> <object class="GtkTreeViewColumn">
<attributes> <property name="title" translatable="yes">Tile Addr.</property>
<attribute name="text">5</attribute> <child>
</attributes> <object class="GtkCellRendererText"/>
<attributes>
<attribute name="text">4</attribute>
</attributes>
</child>
</object>
</child> </child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn">
<property name="title" translatable="yes">Attributes</property>
<child> <child>
<object class="GtkCellRendererText"/> <object class="GtkTreeViewColumn">
<attributes> <property name="title" translatable="yes">OAM Addr.</property>
<attribute name="text">6</attribute> <child>
</attributes> <object class="GtkCellRendererText"/>
<attributes>
<attribute name="text">5</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn">
<property name="title" translatable="yes">Attributes</property>
<child>
<object class="GtkCellRendererText"/>
<attributes>
<attribute name="text">6</attribute>
</attributes>
</child>
</object>
</child> </child>
</object> </object>
</child> </child>
@ -1525,11 +1503,10 @@ Maximilian Mader https://github.com/max-m</property>
<object class="GtkTreeView" id="vram_viewer_palettes"> <object class="GtkTreeView" id="vram_viewer_palettes">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="headers_visible">False</property>
<property name="headers_clickable">False</property> <property name="headers_clickable">False</property>
<property name="rules_hint">True</property>
<property name="enable_search">False</property> <property name="enable_search">False</property>
<property name="show_expanders">False</property> <property name="show_expanders">False</property>
<property name="enable_grid_lines">both</property>
<child internal-child="selection"> <child internal-child="selection">
<object class="GtkTreeSelection"/> <object class="GtkTreeSelection"/>
</child> </child>
@ -1548,7 +1525,7 @@ Maximilian Mader https://github.com/max-m</property>
<object class="GtkTreeViewColumn"> <object class="GtkTreeViewColumn">
<property name="title" translatable="yes">Color 0</property> <property name="title" translatable="yes">Color 0</property>
<child> <child>
<object class="GtkCellRendererText"/> <object class="GtkCellRendererText" id="vram_viewer_palette_cell_renderer_0"/>
<attributes> <attributes>
<attribute name="text">1</attribute> <attribute name="text">1</attribute>
</attributes> </attributes>
@ -1559,31 +1536,31 @@ Maximilian Mader https://github.com/max-m</property>
<object class="GtkTreeViewColumn"> <object class="GtkTreeViewColumn">
<property name="title" translatable="yes">Color 1</property> <property name="title" translatable="yes">Color 1</property>
<child> <child>
<object class="GtkCellRendererText"/> <object class="GtkCellRendererText" id="vram_viewer_palette_cell_renderer_1"/>
<attributes>
<attribute name="text">2</attribute>
</attributes>
</child>
</object>
</child>
<child>
<object class="GtkTreeViewColumn">
<property name="title" translatable="yes">Color 2</property>
<child>
<object class="GtkCellRendererText"/>
<attributes> <attributes>
<attribute name="text">3</attribute> <attribute name="text">3</attribute>
</attributes> </attributes>
</child> </child>
</object> </object>
</child> </child>
<child>
<object class="GtkTreeViewColumn">
<property name="title" translatable="yes">Color 2</property>
<child>
<object class="GtkCellRendererText" id="vram_viewer_palette_cell_renderer_2"/>
<attributes>
<attribute name="text">5</attribute>
</attributes>
</child>
</object>
</child>
<child> <child>
<object class="GtkTreeViewColumn"> <object class="GtkTreeViewColumn">
<property name="title" translatable="yes">Color 3</property> <property name="title" translatable="yes">Color 3</property>
<child> <child>
<object class="GtkCellRendererText"/> <object class="GtkCellRendererText" id="vram_viewer_palette_cell_renderer_3"/>
<attributes> <attributes>
<attribute name="text">4</attribute> <attribute name="text">7</attribute>
</attributes> </attributes>
</child> </child>
</object> </object>