[GTK3] Implement hard-coded input handling

This commit is contained in:
Maximilian Mader 2019-09-28 23:34:18 +02:00
parent a243325b8c
commit 6c5dfece40
Signed by: Max
GPG Key ID: F71D56A3151C4FB3

View File

@ -23,6 +23,17 @@ typedef struct{
uint16_t w, h; uint16_t w, h;
} Rect; } Rect;
#define BUTTON_MASK_A 0x01
#define BUTTON_MASK_B 0x02
#define BUTTON_MASK_START 0x04
#define BUTTON_MASK_SELECT 0x08
#define BUTTON_MASK_UP 0x10
#define BUTTON_MASK_DOWN 0x20
#define BUTTON_MASK_LEFT 0x40
#define BUTTON_MASK_RIGHT 0x80
static uint8_t pressed_buttons;
static void run(GApplication *app, UserData *user_data); static void run(GApplication *app, UserData *user_data);
static GtkApplication *main_application; static GtkApplication *main_application;
@ -38,6 +49,7 @@ static GtkWindow *printer;
static shader_t shader; static shader_t shader;
static UserData user_data = { NULL };
static GB_gameboy_t gb; static GB_gameboy_t gb;
static uint32_t *image_buffers[3]; static uint32_t *image_buffers[3];
static unsigned char current_buffer; static unsigned char current_buffer;
@ -90,6 +102,21 @@ static void render_texture(void *pixels, void *previous) {
render_bitmap_with_shader(&shader, _pixels, previous, GB_get_screen_width(&gb), GB_get_screen_height(&gb), rect.x, rect.y, rect.w, rect.h); render_bitmap_with_shader(&shader, _pixels, previous, GB_get_screen_width(&gb), GB_get_screen_height(&gb), rect.x, rect.y, rect.w, rect.h);
} }
static void handle_events(GB_gameboy_t *gb) {
while (gtk_events_pending()) {
gtk_main_iteration();
}
GB_set_key_state(gb, GB_KEY_RIGHT, pressed_buttons & BUTTON_MASK_RIGHT);
GB_set_key_state(gb, GB_KEY_LEFT, pressed_buttons & BUTTON_MASK_LEFT);
GB_set_key_state(gb, GB_KEY_UP, pressed_buttons & BUTTON_MASK_UP);
GB_set_key_state(gb, GB_KEY_DOWN, pressed_buttons & BUTTON_MASK_DOWN);
GB_set_key_state(gb, GB_KEY_A, pressed_buttons & BUTTON_MASK_A);
GB_set_key_state(gb, GB_KEY_B, pressed_buttons & BUTTON_MASK_B);
GB_set_key_state(gb, GB_KEY_SELECT, pressed_buttons & BUTTON_MASK_SELECT);
GB_set_key_state(gb, GB_KEY_START, pressed_buttons & BUTTON_MASK_START);
}
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());
@ -105,10 +132,6 @@ static void vblank(GB_gameboy_t *gb) {
// Queue a redraw of the VRAM viewer // Queue a redraw of the VRAM viewer
gtk_widget_queue_draw(GTK_WIDGET(vram_viewer)); gtk_widget_queue_draw(GTK_WIDGET(vram_viewer));
} }
while (gtk_events_pending()) {
gtk_main_iteration();
}
} }
static void update_viewport(void) { static void update_viewport(void) {
@ -206,17 +229,21 @@ static void quit(GApplication *app) {
// Tell our own main loop to quit. // Tell our own main loop to quit.
// This will allow our run() and therefore our activate() methods to end. // This will allow our run() and therefore our activate() methods to end.
running = false; running = false;
// Quit our application properly.
// This fires the “shutdown” signal.
g_application_quit(app);
} }
// app.quit GAction // app.quit GAction
// Exits the application // Exits the application
static void activate_quit(GSimpleAction *action, GVariant *parameter, gpointer user_data) { static void activate_quit(GSimpleAction *action, GVariant *parameter, gpointer app) {
quit(G_APPLICATION(user_data)); quit(G_APPLICATION(app));
} }
// app.about GAction // app.about GAction
// Opens the about dialog // Opens the about dialog
static void activate_about(GSimpleAction *action, GVariant *parameter, gpointer user_data) { static void activate_about(GSimpleAction *action, GVariant *parameter, gpointer app) {
GObject *dialog = get_object("about_dialog"); GObject *dialog = get_object("about_dialog");
gtk_dialog_run(GTK_DIALOG(dialog)); gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_hide(GTK_WIDGET(dialog)); gtk_widget_hide(GTK_WIDGET(dialog));
@ -224,38 +251,79 @@ static void activate_about(GSimpleAction *action, GVariant *parameter, gpointer
// app.open_gtk_debugger GAction // app.open_gtk_debugger GAction
// Opens the GTK debugger // Opens the GTK debugger
static void activate_open_gtk_debugger(GSimpleAction *action, GVariant *parameter, gpointer user_data) { static void activate_open_gtk_debugger(GSimpleAction *action, GVariant *parameter, gpointer app) {
gtk_window_set_interactive_debugging(true); gtk_window_set_interactive_debugging(true);
} }
// app.preferences GAction // app.preferences GAction
// Opens the preferences window // Opens the preferences window
static void activate_preferences(GSimpleAction *action, GVariant *parameter, gpointer user_data) { static void activate_preferences(GSimpleAction *action, GVariant *parameter, gpointer app) {
gtk_widget_show_all(GTK_WIDGET(get_object("preferences"))); gtk_widget_show_all(GTK_WIDGET(get_object("preferences")));
} }
// app.open_vram_viewer GAction // app.open_vram_viewer GAction
// Opens the VRAM viewer window // Opens the VRAM viewer window
static void activate_open_vram_viewer(GSimpleAction *action, GVariant *parameter, gpointer user_data) { static void activate_open_vram_viewer(GSimpleAction *action, GVariant *parameter, gpointer app) {
gtk_widget_show_all(GTK_WIDGET(vram_viewer)); gtk_widget_show_all(GTK_WIDGET(vram_viewer));
} }
// app.open_memory_viewer GAction // app.open_memory_viewer GAction
// Opens the memory viewer window // Opens the memory viewer window
static void activate_open_memory_viewer(GSimpleAction *action, GVariant *parameter, gpointer user_data) { static void activate_open_memory_viewer(GSimpleAction *action, GVariant *parameter, gpointer app) {
gtk_widget_show_all(GTK_WIDGET(memory_viewer)); gtk_widget_show_all(GTK_WIDGET(memory_viewer));
} }
// app.open GAction
// Opens a ROM file
static void activate_open(GSimpleAction *action, GVariant *parameter, gpointer app) {
GtkFileChooserNative *native = gtk_file_chooser_native_new("Open File", GTK_WINDOW(main_window), GTK_FILE_CHOOSER_ACTION_OPEN, "_Open", "_Cancel");
gint res = gtk_native_dialog_run(GTK_NATIVE_DIALOG(native));
if (res == GTK_RESPONSE_ACCEPT) {
g_print("%s\n", gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(native)));
}
g_object_unref(native);
}
// List of GActions for the `app` prefix // List of GActions for the `app` prefix
static GActionEntry app_entries[] = { static GActionEntry app_entries[] = {
{ "quit", activate_quit, NULL, NULL, NULL }, { "quit", activate_quit, NULL, NULL, NULL },
{ "about", activate_about, NULL, NULL, NULL }, { "about", activate_about, NULL, NULL, NULL },
{ "open", activate_open, NULL, NULL, NULL },
{ "open_gtk_debugger", activate_open_gtk_debugger, NULL, NULL, NULL }, { "open_gtk_debugger", activate_open_gtk_debugger, NULL, NULL, NULL },
{ "preferences", activate_preferences, NULL, NULL, NULL }, { "preferences", activate_preferences, NULL, NULL, NULL },
{ "open_vram_viewer", activate_open_vram_viewer, NULL, NULL, NULL }, { "open_vram_viewer", activate_open_vram_viewer, NULL, NULL, NULL },
{ "open_memory_viewer", activate_open_memory_viewer, NULL, NULL, NULL }, { "open_memory_viewer", activate_open_memory_viewer, NULL, NULL, NULL },
}; };
G_MODULE_EXPORT gboolean on_key_press(GtkWidget *w, GdkEventKey *event, gpointer data) {
uint8_t mask;
// TODO: Allow control remapping in the GUI
switch (event->keyval) {
case GDK_KEY_w: mask = BUTTON_MASK_UP; break;
case GDK_KEY_a: mask = BUTTON_MASK_LEFT; break;
case GDK_KEY_s: mask = BUTTON_MASK_DOWN; break;
case GDK_KEY_d: mask = BUTTON_MASK_RIGHT; break;
case GDK_KEY_g: mask = BUTTON_MASK_SELECT; break;
case GDK_KEY_h: mask = BUTTON_MASK_START; break;
case GDK_KEY_k: mask = BUTTON_MASK_B; break;
case GDK_KEY_l: mask = BUTTON_MASK_A; break;
}
if (event->type == GDK_KEY_PRESS) {
pressed_buttons |= mask;
}
else if (event->type == GDK_KEY_RELEASE) {
pressed_buttons &= ~mask;
}
return FALSE;
}
G_MODULE_EXPORT void on_quit(GtkWidget *w, gpointer app) { G_MODULE_EXPORT void on_quit(GtkWidget *w, gpointer app) {
quit(G_APPLICATION(app)); quit(G_APPLICATION(app));
} }
@ -473,6 +541,11 @@ static void startup(GApplication *app, gpointer user_data_gptr) {
set_combo_box_row_separator_func(GTK_CONTAINER(memory_viewer)); set_combo_box_row_separator_func(GTK_CONTAINER(memory_viewer));
// Connect signal handlers // Connect signal handlers
gtk_widget_add_events(GTK_WIDGET(main_window), GDK_KEY_PRESS_MASK);
gtk_widget_add_events(GTK_WIDGET(main_window), GDK_KEY_RELEASE_MASK);
g_signal_connect(main_window, "key_press_event", G_CALLBACK(on_key_press), NULL);
g_signal_connect(main_window, "key_release_event", G_CALLBACK(on_key_press), NULL);
g_signal_connect(gl_area, "realize", G_CALLBACK(gl_init), NULL); 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, "render", G_CALLBACK(gl_draw), NULL);
g_signal_connect(gl_area, "resize", G_CALLBACK(gl_resize), NULL); g_signal_connect(gl_area, "resize", G_CALLBACK(gl_resize), NULL);
@ -725,7 +798,7 @@ static void run(GApplication *app, UserData *user_data) {
GB_set_color_correction_mode(&gb, get_color_correction_mode()); GB_set_color_correction_mode(&gb, get_color_correction_mode());
GB_set_highpass_filter_mode(&gb, get_highpass_mode()); GB_set_highpass_filter_mode(&gb, get_highpass_mode());
GB_set_rewind_length(&gb, config.rewind_duration); GB_set_rewind_length(&gb, config.rewind_duration);
// GB_set_update_input_hint_callback(&gb, handle_events); GB_set_update_input_hint_callback(&gb, handle_events);
// GB_apu_set_sample_callback(&gb, gb_audio_callback); // GB_apu_set_sample_callback(&gb, gb_audio_callback);
} }
@ -794,43 +867,35 @@ static void run(GApplication *app, UserData *user_data) {
} }
} }
if (user_data->file != NULL) { if (user_data->file != NULL && GB_load_rom(&gb, g_file_get_path(user_data->file)) == 0) {
GB_load_rom(&gb, g_file_get_path(user_data->file)); /* Run emulation */
} while (running) {
if (paused || rewind_paused) {
/* Run emulation */ while (gtk_events_pending()) {
while (running) { gtk_main_iteration();
if (paused || rewind_paused) { }
while (gtk_events_pending()) {
gtk_main_iteration();
} }
} else {
else { if (do_rewind) {
if (do_rewind) {
GB_rewind_pop(&gb);
if (turbo_down) {
GB_rewind_pop(&gb); GB_rewind_pop(&gb);
if (turbo_down) {
GB_rewind_pop(&gb);
}
if (!GB_rewind_pop(&gb)) {
rewind_paused = true;
}
do_rewind = false;
} }
if (!GB_rewind_pop(&gb)) { GB_run(&gb);
rewind_paused = true;
}
do_rewind = false;
} }
GB_run(&gb);
} }
} }
// Quit our application properly.
// This fires the “shutdown” signal.
g_application_quit(app);
} }
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
// Create our GApplication and tell GTK that we are able to handle files // Create our GApplication and tell GTK that we are able to handle files
main_application = gtk_application_new(APP_ID, G_APPLICATION_HANDLES_OPEN); main_application = gtk_application_new(APP_ID, G_APPLICATION_HANDLES_OPEN);
UserData user_data = { NULL };
// Define our command line parameters // Define our command line parameters
GOptionEntry entries[] = { GOptionEntry entries[] = {
{ "version", 'v', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, NULL, "Show the application version", NULL }, { "version", 'v', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, NULL, "Show the application version", NULL },