diff --git a/gtk3/main.c b/gtk3/main.c
index 105a837..43ea4bc 100644
--- a/gtk3/main.c
+++ b/gtk3/main.c
@@ -29,8 +29,14 @@ static void run(UserData *user_data);
static GtkApplication *main_application;
static GtkBuilder *builder;
-static GtkApplicationWindow *main_window;
static GtkGLArea *gl_area;
+
+static GtkApplicationWindow *main_window;
+static GtkWindow *vram_viewer;
+static GtkWindow *memory_viewer;
+static GtkWindow *console;
+static GtkWindow *printer;
+
static shader_t shader;
static GB_gameboy_t gb;
@@ -42,9 +48,20 @@ static bool underclock_down = false, rewind_down = false, do_rewind = false, rew
static double clock_mutliplier = 1.0;
static char *battery_save_path_ptr;
static Rect rect;
-
+static bool vram_viewer_visible = false;
static bool running = true;
+static const size_t tileset_buffer_length = 256 * 192 * 4;
+static uint32_t tileset_buffer[tileset_buffer_length] = {0};
+
+static const size_t tilemap_buffer_length = 256 * 256 * 4;
+static uint32_t tilemap_buffer[tilemap_buffer_length] = {0};
+
+// Returns a GObject by ID from our GtkBuilder instance
+static GObject *get_object(gchararray id) {
+ return gtk_builder_get_object(builder, id);
+}
+
static unsigned char number_of_buffers(void) {
bool should_blend = true;
@@ -85,6 +102,15 @@ static void vblank(GB_gameboy_t *gb) {
// Queue drawing of the current frame
gtk_gl_area_queue_render(gl_area);
+
+ if (vram_viewer_visible) {
+ // TODO: Only update what is needed
+ GB_draw_tileset(gb, tileset_buffer, GB_PALETTE_NONE, 0);
+ GB_draw_tilemap(gb, tilemap_buffer, GB_PALETTE_AUTO, 0, GB_MAP_AUTO, GB_TILESET_AUTO);
+
+ // Queue a redraw of the VRAM viewer
+ gtk_widget_queue_draw(GTK_WIDGET(vram_viewer));
+ }
while (gtk_events_pending()) {
gtk_main_iteration();
@@ -158,17 +184,18 @@ static void set_combo_box_row_separator_func(GtkContainer *container) {
// Returns true if the application should show a menubar
static gboolean show_menubar(void) {
- GtkSettings *settings = gtk_settings_get_default();
- gboolean result;
+ switch (get_show_menubar()) {
+ case MENUBAR_AUTO: {
+ GtkSettings *settings = gtk_settings_get_default();
+ gboolean result;
- g_object_get(settings, "gtk-shell-shows-menubar", &result, NULL);
+ g_object_get(settings, "gtk-shell-shows-menubar", &result, NULL);
- return result;
-}
-
-// Returns a GObject by ID from our GtkBuilder instance
-static GObject *get_object(gchararray id) {
- return gtk_builder_get_object(builder, id);
+ return result;
+ }
+ case MENUBAR_SHOW: return true;
+ case MENUBAR_HIDE: return false;
+ }
}
// Returns a `GApplication`s `GMenuModel` by ID
@@ -212,12 +239,26 @@ static void activate_preferences(GSimpleAction *action, GVariant *parameter, gpo
gtk_widget_show_all(GTK_WIDGET(get_object("preferences")));
}
+// app.open_vram_viewer GAction
+// Opens the VRAM viewer window
+static void activate_open_vram_viewer(GSimpleAction *action, GVariant *parameter, gpointer user_data) {
+ gtk_widget_show_all(GTK_WIDGET(vram_viewer));
+}
+
+// app.open_memory_viewer GAction
+// Opens the memory viewer window
+static void activate_open_memory_viewer(GSimpleAction *action, GVariant *parameter, gpointer user_data) {
+ gtk_widget_show_all(GTK_WIDGET(memory_viewer));
+}
+
// List of GActions for the `app` prefix
static GActionEntry app_entries[] = {
{ "quit", activate_quit, NULL, NULL, NULL },
{ "about", activate_about, NULL, NULL, NULL },
{ "open_gtk_debugger", activate_open_gtk_debugger, NULL, NULL, NULL },
{ "preferences", activate_preferences, NULL, NULL, NULL },
+ { "open_vram_viewer", activate_open_vram_viewer, NULL, NULL, NULL },
+ { "open_memory_viewer", activate_open_memory_viewer, NULL, NULL, NULL },
};
G_MODULE_EXPORT void on_quit(GtkWidget *w, gpointer app) {
@@ -228,12 +269,6 @@ G_MODULE_EXPORT void on_show_window(GtkWidget *w, gpointer window) {
gtk_widget_show_all(GTK_WIDGET(window));
}
-G_MODULE_EXPORT void on_boot_rom_location_changed(GtkWidget *w, gpointer user_data_gptr) {
- GtkComboBox *box = GTK_COMBO_BOX(w);
-
- g_print("Active: %s", gtk_combo_box_get_active_id(box));
-}
-
G_MODULE_EXPORT void gl_init() {
const char *renderer;
@@ -260,12 +295,66 @@ G_MODULE_EXPORT void gl_draw() {
G_MODULE_EXPORT void gl_finish() { }
+G_MODULE_EXPORT void on_vram_viewer_realize(gpointer visible) {
+ vram_viewer_visible = true;
+}
+
+G_MODULE_EXPORT void on_vram_viewer_unrealize(gpointer visible) {
+ vram_viewer_visible = false;
+}
+
+G_MODULE_EXPORT gboolean on_draw_vram_viewer_tileset(GtkWidget *widget, cairo_t *cr, gpointer data) {
+ 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 *) tileset_buffer,
+ CAIRO_FORMAT_RGB24,
+ 256,
+ 192,
+ cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, 256)
+ );
+
+ cairo_set_source_surface(cr, surface, 0, 0);
+ cairo_paint(cr);
+
+ return FALSE;
+}
+
+G_MODULE_EXPORT gboolean on_vram_viewer_tilemap(GtkWidget *widget, cairo_t *cr, gpointer data) {
+ 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 *) tilemap_buffer,
+ CAIRO_FORMAT_RGB24,
+ 256,
+ 256,
+ cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, 256)
+ );
+
+ cairo_set_source_surface(cr, surface, 0, 0);
+ cairo_paint(cr);
+
+ return FALSE;
+}
+
// This functions gets called immediately after registration of the GApplication
static void startup(GApplication *app, gpointer user_data_gptr) {
UserData *user_data = user_data_gptr;
- init_settings(user_data->config_path);
-
builder = gtk_builder_new_from_resource(RESOURCE_PREFIX "ui/window.ui");
gtk_builder_connect_signals(builder, NULL);
@@ -274,9 +363,17 @@ static void startup(GApplication *app, gpointer user_data_gptr) {
GtkWindow *preferences = GTK_WINDOW(get_object("preferences"));
set_combo_box_row_separator_func(GTK_CONTAINER(preferences));
- GtkWindow *vram_viewer = GTK_WINDOW(get_object("vram_viewer"));
+ init_settings(user_data->config_path, preferences);
+
+ vram_viewer = GTK_WINDOW(get_object("vram_viewer"));
set_combo_box_row_separator_func(GTK_CONTAINER(vram_viewer));
+ memory_viewer = GTK_WINDOW(get_object("memory_viewer"));
+ set_combo_box_row_separator_func(GTK_CONTAINER(memory_viewer));
+
+ console = GTK_WINDOW(get_object("console"));
+ printer = GTK_WINDOW(get_object("printer"));
+
// setup main window
main_window = GTK_APPLICATION_WINDOW(gtk_application_window_new(GTK_APPLICATION(app)));
gtk_application_window_set_show_menubar(main_window, true);
@@ -284,11 +381,26 @@ static void startup(GApplication *app, gpointer user_data_gptr) {
// create our renderer area
gl_area = GTK_GL_AREA(gtk_gl_area_new());
gtk_gl_area_set_auto_render(gl_area, false);
- g_signal_connect(gl_area, "realize", G_CALLBACK(gl_init), NULL);
- g_signal_connect(gl_area, "render", G_CALLBACK(gl_draw), NULL);
- g_signal_connect(gl_area, "resize", G_CALLBACK(gl_resize), NULL);
+
+ // Connect signal handlers
+ g_signal_connect(gl_area, "realize", G_CALLBACK(gl_init), NULL);
+ g_signal_connect(gl_area, "render", G_CALLBACK(gl_draw), NULL);
+ g_signal_connect(gl_area, "resize", G_CALLBACK(gl_resize), NULL);
g_signal_connect(gl_area, "unrealize", G_CALLBACK(gl_finish), NULL);
+ g_signal_connect(vram_viewer, "realize", G_CALLBACK(on_vram_viewer_realize), NULL);
+ g_signal_connect(vram_viewer, "unrealize", G_CALLBACK(on_vram_viewer_unrealize), NULL);
+
+ // Just hide our sub-windows when closing them
+ g_signal_connect(preferences, "delete-event", G_CALLBACK(gtk_widget_hide_on_delete), NULL);
+ g_signal_connect(vram_viewer, "delete-event", G_CALLBACK(gtk_widget_hide_on_delete), NULL);
+ g_signal_connect(memory_viewer, "delete-event", G_CALLBACK(gtk_widget_hide_on_delete), NULL);
+ g_signal_connect(console, "delete-event", G_CALLBACK(gtk_widget_hide_on_delete), NULL);
+ g_signal_connect(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_vram_viewer_tilemap), NULL);
+
gtk_container_add(GTK_CONTAINER(main_window), GTK_WIDGET(gl_area));
// Handle the whole menubar situation …
@@ -311,7 +423,7 @@ static void startup(GApplication *app, gpointer user_data_gptr) {
gtk_menu_button_set_menu_model(hamburger_button, hamburger_menu);
}
- gtk_window_set_title(GTK_WINDOW(main_window), "SameBoy v" xstr(VERSION));
+ gtk_window_set_title(GTK_WINDOW(main_window), "SameBoy");
// Define a set of window icons
GList *icon_list = NULL;
diff --git a/gtk3/resources/gtk/menus-common.ui b/gtk3/resources/gtk/menus-common.ui
index 5adb447..276a7ef 100644
--- a/gtk3/resources/gtk/menus-common.ui
+++ b/gtk3/resources/gtk/menus-common.ui
@@ -71,7 +71,7 @@ Author: Maximilian Mader
file-section-0
-
_Open
- win.open
+ app.open
Open _Recent
@@ -85,7 +85,7 @@ Author: Maximilian Mader
file-section-1
-
Close
- win.close
+ app.close
@@ -96,11 +96,11 @@ Author: Maximilian Mader
edit-section-0
-
Undo
- win.undo
+ app.undo
-
Redo
- win.redo
+ app.redo
@@ -108,23 +108,23 @@ Author: Maximilian Mader
edit-section-1
-
Cut
- win.cut
+ app.cut
-
Copy
- win.copy
+ app.copy
-
Paste
- win.paste
+ app.paste
-
Delete
- win.delete
+ app.delete
-
Select All
- win.select_all
+ app.select_all
@@ -135,23 +135,23 @@ Author: Maximilian Mader
find-section-0
-
Find…
- win.find
+ app.find
-
Find Next
- win.find_next
+ app.find_next
-
Find Previous
- win.find_previous
+ app.find_previous
-
Use Selection for Find
- win.find_selection
+ app.find_selection
-
Jump to Selection
- win.jump_selection
+ app.jump_selection
@@ -164,11 +164,11 @@ Author: Maximilian Mader
emulation-section-0
-
Reset
- win.reset
+ app.reset
-
Pause
- win.pause
+ app.pause
@@ -178,53 +178,53 @@ Author: Maximilian Mader
Save State
-
Slot 1
- 0
- win.save_state
+ 0
+ app.save_state
-
Slot 2
- 1
- win.save_state
+ 1
+ app.save_state
-
Slot 3
- 2
- win.save_state
+ 2
+ app.save_state
-
Slot 4
- 3
- win.save_state
+ 3
+ app.save_state
-
Slot 5
- 4
- win.save_state
+ 4
+ app.save_state
-
Slot 6
- 5
- win.save_state
+ 5
+ app.save_state
-
Slot 7
- 6
- win.save_state
+ 6
+ app.save_state
-
Slot 8
- 7
- win.save_state
+ 7
+ app.save_state
-
Slot 9
- 8
- win.save_state
+ 8
+ app.save_state
-
Slot 10
- 9
- win.save_state
+ 9
+ app.save_state
@@ -232,53 +232,53 @@ Author: Maximilian Mader
Save State
-
Slot 1
- 0
- win.load_state
+ 0
+ app.load_state
-
Slot 2
- 1
- win.load_state
+ 1
+ app.load_state
-
Slot 3
- 2
- win.load_state
+ 2
+ app.load_state
-
Slot 4
- 3
- win.load_state
+ 3
+ app.load_state
-
Slot 5
- 4
- win.load_state
+ 4
+ app.load_state
-
Slot 6
- 5
- win.load_state
+ 5
+ app.load_state
-
Slot 7
- 6
- win.load_state
+ 6
+ app.load_state
-
Slot 8
- 7
- win.load_state
+ 7
+ app.load_state
-
Slot 9
- 8
- win.load_state
+ 8
+ app.load_state
-
Slot 10
- 9
- win.load_state
+ 9
+ app.load_state
@@ -287,22 +287,22 @@ Author: Maximilian Mader
emulation-section-2
-
Game Boy
- win.change_model
+ app.change_model
DMG
-
Super Game Boy
- win.change_model
+ app.change_model
SGB
-
Game Boy Color
- win.change_model
+ app.change_model
CGB
-
Game Boy Advance
- win.change_model
+ app.change_model
AGB
@@ -311,7 +311,7 @@ Author: Maximilian Mader
emulation-section-3
-
Mute Sound
- win.toggle_mute
+ app.toggle_mute
@@ -319,7 +319,7 @@ Author: Maximilian Mader
emulation-section-4
-
Blend Frames
- win.toggle_blend_frames
+ app.toggle_blend_frames
@@ -330,13 +330,13 @@ Author: Maximilian Mader
connectivity-section-0
-
None
- win.change_serial_device
- none
+ app.change_serial_device
+ none
-
Game Boy Printer
- win.change_serial_device
- gb_printer
+ app.change_serial_device
+ gb_printer
@@ -347,7 +347,7 @@ Author: Maximilian Mader
developer-section-0
-
Developer Mode
- win.toggle_developer_mode
+ app.toggle_developer_mode
@@ -355,11 +355,11 @@ Author: Maximilian Mader
developer-section-1
-
Show Console
- win.show_console
+ app.show_console
-
Clear Console
- win.clear_console
+ app.clear_console
@@ -367,7 +367,7 @@ Author: Maximilian Mader
developer-section-2
-
Break Debugger
- win.break_debugger
+ app.break_debugger
@@ -375,11 +375,11 @@ Author: Maximilian Mader
developer-section-3
-
Show Memory Viewer
- win.open_memory_viewer
+ app.open_memory_viewer
-
Show VRAM Viewer
- win.open_vram_viewer
+ app.open_vram_viewer
@@ -398,11 +398,11 @@ Author: Maximilian Mader
window-section-0
-
Minimize
- win.minimize
+ app.minimize
-
Zoom
- win.zoom
+ app.zoom
@@ -410,7 +410,7 @@ Author: Maximilian Mader
window-section-1
-
Bring All to Front
- win.bring_to_front
+ app.bring_to_front
@@ -421,7 +421,7 @@ Author: Maximilian Mader
help-section-0
-
SameBoy Help
- win.help
+ app.help
diff --git a/gtk3/resources/ui/window.ui b/gtk3/resources/ui/window.ui
index 44ce981..9072597 100644
--- a/gtk3/resources/ui/window.ui
+++ b/gtk3/resources/ui/window.ui
@@ -612,24 +612,6 @@ Maximilian Mader https://github.com/max-m
3
-
-
-
- False
- True
- 4
-
-
+
+
+
+ False
+ True
+ 4
+
+
1
@@ -1258,18 +1258,6 @@ Maximilian Mader https://github.com/max-m
True
False
vertical
-
-
-
- False
- True
- 0
-
-
+
+
+
+ True
+ True
1