[GTK3] Run the emulation in its own thread

The code has not been checked for thread safety yet!
This commit is contained in:
Maximilian Mader 2019-10-05 21:09:30 +02:00
parent ee6881285a
commit 8a90af4d98
Signed by: Max
GPG Key ID: F71D56A3151C4FB3
2 changed files with 25 additions and 25 deletions

View File

@ -499,9 +499,7 @@ static void activate(GApplication *app, gpointer user_data_gptr) {
gtk_application_add_window(GTK_APPLICATION(app), GTK_WINDOW(main_window)); gtk_application_add_window(GTK_APPLICATION(app), GTK_WINDOW(main_window));
gtk_widget_show_all(GTK_WIDGET(main_window)); gtk_widget_show_all(GTK_WIDGET(main_window));
// Start the emulation loop. g_thread_new("CoreLoop", run, user_data);
// This loop takes care of the GTK main loop.
run(app, user_data);
} }
// This function gets called when the application is closed. // This function gets called when the application is closed.
@ -522,7 +520,7 @@ static void open(GApplication *app, GFile **files, gint n_files, const gchar *hi
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
user_data->file = files[0]; user_data->file = g_file_dup(files[0]);
// We have handled the files, now activate the application // We have handled the files, now activate the application
activate(app, user_data_gptr); activate(app, user_data_gptr);
@ -1106,10 +1104,6 @@ static void update_window_geometry() {
} }
static void handle_events(GB_gameboy_t *gb) { 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_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_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_UP, pressed_buttons & BUTTON_MASK_UP);
@ -1156,10 +1150,7 @@ static void palette_color_data_func(GtkTreeViewColumn *col, GtkCellRenderer *ren
g_free(color_string); g_free(color_string);
} }
static void vblank(GB_gameboy_t *gb) { static void on_vblank(gpointer data) {
flip();
GB_set_pixels_output(gb, get_pixels());
// Queue drawing of the current frame // Queue drawing of the current frame
if (fallback_canvas) { if (fallback_canvas) {
gtk_widget_queue_draw(GTK_WIDGET(main_window)); gtk_widget_queue_draw(GTK_WIDGET(main_window));
@ -1177,7 +1168,7 @@ static void vblank(GB_gameboy_t *gb) {
GB_palette_type_t palette_type = g_str_has_prefix(palette_id, "bg")? GB_PALETTE_BACKGROUND : GB_PALETTE_OAM; GB_palette_type_t palette_type = g_str_has_prefix(palette_id, "bg")? GB_PALETTE_BACKGROUND : GB_PALETTE_OAM;
uint8_t palette_index = g_ascii_digit_value(palette_id[palette_type == GB_PALETTE_OAM ? 3 : 2]); uint8_t palette_index = g_ascii_digit_value(palette_id[palette_type == GB_PALETTE_OAM ? 3 : 2]);
GB_draw_tileset(gb, tileset_buffer, GB_draw_tileset(&gb, tileset_buffer,
palette_type, palette_type,
palette_index palette_index
); );
@ -1204,7 +1195,7 @@ static void vblank(GB_gameboy_t *gb) {
tileset_type = (g_strcmp0("8800", tileset_type_id) == 0)? GB_TILESET_8800 : GB_TILESET_8000; tileset_type = (g_strcmp0("8800", tileset_type_id) == 0)? GB_TILESET_8800 : GB_TILESET_8000;
} }
GB_draw_tilemap(gb, tilemap_buffer, GB_draw_tilemap(&gb, tilemap_buffer,
palette_type, palette_type,
palette_index, palette_index,
map_type, map_type,
@ -1212,8 +1203,8 @@ static void vblank(GB_gameboy_t *gb) {
); );
scrollRect = (Rect){ scrollRect = (Rect){
GB_read_memory(gb, 0xFF00 | GB_IO_SCX), GB_read_memory(&gb, 0xFF00 | GB_IO_SCX),
GB_read_memory(gb, 0xFF00 | GB_IO_SCY), GB_read_memory(&gb, 0xFF00 | GB_IO_SCY),
160, 144 160, 144
}; };
} }
@ -1234,7 +1225,7 @@ static void vblank(GB_gameboy_t *gb) {
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);
for (unsigned row = 0; row < oamCount; ++row) { for (unsigned row = 0; row < oamCount; ++row) {
GdkPixbuf *pixbuf = gdk_pixbuf_new_from_bytes( GdkPixbuf *pixbuf = gdk_pixbuf_new_from_bytes(
@ -1257,7 +1248,7 @@ static void vblank(GB_gameboy_t *gb) {
3, g_strdup_printf("$%02x", oamInfo[row].tile), 3, g_strdup_printf("$%02x", oamInfo[row].tile),
4, g_strdup_printf("$%04x", 0x8000 + oamInfo[row].tile * 0x10), 4, g_strdup_printf("$%04x", 0x8000 + oamInfo[row].tile * 0x10),
5, g_strdup_printf("$%04x", oamInfo[row].oam_addr), 5, g_strdup_printf("$%04x", oamInfo[row].oam_addr),
6, GB_is_cgb(gb) 6, GB_is_cgb(&gb)
? g_strdup_printf("%c%c%c%d%d", ? g_strdup_printf("%c%c%c%d%d",
oamInfo[row].flags & 0x80? 'P' : '-', oamInfo[row].flags & 0x80? 'P' : '-',
oamInfo[row].flags & 0x40? 'Y' : '-', oamInfo[row].flags & 0x40? 'Y' : '-',
@ -1303,7 +1294,7 @@ static void vblank(GB_gameboy_t *gb) {
gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter); gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter);
for (unsigned row = 0; row < 16; ++row) { 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 *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; 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_0 = (palette_data[((0 + offset) << 1) + 1] << 8) | palette_data[((0 + offset) << 1)];
@ -1349,7 +1340,16 @@ static void vblank(GB_gameboy_t *gb) {
} }
} }
static void run(GApplication *app, UserData *user_data) { static void vblank(GB_gameboy_t *gb) {
flip();
GB_set_pixels_output(gb, get_pixels());
g_idle_add((GSourceFunc) on_vblank, NULL);
}
static gpointer run(gpointer user_data_gptr) {
UserData *user_data = user_data_gptr;
GB_model_t prev_model = GB_get_model(&gb); GB_model_t prev_model = GB_get_model(&gb);
GB_model_t model = user_data->model? user_data->model : GB_MODEL_CGB_E; // TODO: Model from config GB_model_t model = user_data->model? user_data->model : GB_MODEL_CGB_E; // TODO: Model from config
@ -1449,9 +1449,7 @@ static void run(GApplication *app, UserData *user_data) {
/* Run emulation */ /* Run emulation */
while (running) { while (running) {
if (paused || rewind_paused) { if (paused || rewind_paused) {
while (gtk_events_pending()) {
gtk_main_iteration();
}
} }
else { else {
if (do_rewind) { if (do_rewind) {
@ -1468,4 +1466,6 @@ static void run(GApplication *app, UserData *user_data) {
} }
} }
} }
return NULL;
} }

View File

@ -114,6 +114,6 @@ static void handle_events(GB_gameboy_t *gb);
static uint32_t convert_color(uint16_t color); 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 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 gpointer run(gpointer user_data_gptr);
#endif /* main_h */ #endif /* main_h */