[GTK3] Implement hard-coded input handling
This commit is contained in:
parent
404e9dd1d5
commit
5f4e533f2b
139
gtk3/main.c
139
gtk3/main.c
@ -23,6 +23,17 @@ typedef struct{
|
||||
uint16_t w, h;
|
||||
} 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 GtkApplication *main_application;
|
||||
@ -38,6 +49,7 @@ static GtkWindow *printer;
|
||||
|
||||
static shader_t shader;
|
||||
|
||||
static UserData user_data = { NULL };
|
||||
static GB_gameboy_t gb;
|
||||
static uint32_t *image_buffers[3];
|
||||
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);
|
||||
}
|
||||
|
||||
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) {
|
||||
flip();
|
||||
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
|
||||
gtk_widget_queue_draw(GTK_WIDGET(vram_viewer));
|
||||
}
|
||||
|
||||
while (gtk_events_pending()) {
|
||||
gtk_main_iteration();
|
||||
}
|
||||
}
|
||||
|
||||
static void update_viewport(void) {
|
||||
@ -206,17 +229,21 @@ static void quit(GApplication *app) {
|
||||
// Tell our own main loop to quit.
|
||||
// This will allow our run() and therefore our activate() methods to end.
|
||||
running = false;
|
||||
|
||||
// Quit our application properly.
|
||||
// This fires the “shutdown” signal.
|
||||
g_application_quit(app);
|
||||
}
|
||||
|
||||
// app.quit GAction
|
||||
// Exits the application
|
||||
static void activate_quit(GSimpleAction *action, GVariant *parameter, gpointer user_data) {
|
||||
quit(G_APPLICATION(user_data));
|
||||
static void activate_quit(GSimpleAction *action, GVariant *parameter, gpointer app) {
|
||||
quit(G_APPLICATION(app));
|
||||
}
|
||||
|
||||
// app.about GAction
|
||||
// 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");
|
||||
gtk_dialog_run(GTK_DIALOG(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
|
||||
// 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);
|
||||
}
|
||||
|
||||
// app.preferences GAction
|
||||
// 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")));
|
||||
}
|
||||
|
||||
// app.open_vram_viewer GAction
|
||||
// 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));
|
||||
}
|
||||
|
||||
// app.open_memory_viewer GAction
|
||||
// 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));
|
||||
}
|
||||
|
||||
// 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
|
||||
static GActionEntry app_entries[] = {
|
||||
{ "quit", activate_quit, 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 },
|
||||
{ "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 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) {
|
||||
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));
|
||||
|
||||
// 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, "render", G_CALLBACK(gl_draw), 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_highpass_filter_mode(&gb, get_highpass_mode());
|
||||
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);
|
||||
}
|
||||
|
||||
@ -794,43 +867,35 @@ static void run(GApplication *app, UserData *user_data) {
|
||||
}
|
||||
}
|
||||
|
||||
if (user_data->file != NULL) {
|
||||
GB_load_rom(&gb, g_file_get_path(user_data->file));
|
||||
}
|
||||
|
||||
/* Run emulation */
|
||||
while (running) {
|
||||
if (paused || rewind_paused) {
|
||||
while (gtk_events_pending()) {
|
||||
gtk_main_iteration();
|
||||
if (user_data->file != NULL && GB_load_rom(&gb, g_file_get_path(user_data->file)) == 0) {
|
||||
/* Run emulation */
|
||||
while (running) {
|
||||
if (paused || rewind_paused) {
|
||||
while (gtk_events_pending()) {
|
||||
gtk_main_iteration();
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (do_rewind) {
|
||||
GB_rewind_pop(&gb);
|
||||
if (turbo_down) {
|
||||
else {
|
||||
if (do_rewind) {
|
||||
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)) {
|
||||
rewind_paused = true;
|
||||
}
|
||||
do_rewind = false;
|
||||
GB_run(&gb);
|
||||
}
|
||||
GB_run(&gb);
|
||||
}
|
||||
}
|
||||
|
||||
// Quit our application properly.
|
||||
// This fires the “shutdown” signal.
|
||||
g_application_quit(app);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
// Create our GApplication and tell GTK that we are able to handle files
|
||||
main_application = gtk_application_new(APP_ID, G_APPLICATION_HANDLES_OPEN);
|
||||
|
||||
UserData user_data = { NULL };
|
||||
|
||||
// Define our command line parameters
|
||||
GOptionEntry entries[] = {
|
||||
{ "version", 'v', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, NULL, "Show the application version", NULL },
|
||||
|
Loading…
Reference in New Issue
Block a user