[GTK3] Restructure config_t by using sub structs

This commit is contained in:
Maximilian Mader 2020-05-12 20:55:29 +02:00
parent 116ea7d0d7
commit 2887110e99
Signed by: Max
GPG Key ID: F71D56A3151C4FB3
3 changed files with 214 additions and 202 deletions

View File

@ -1220,7 +1220,7 @@ static void vblank(GB_gameboy_t *gb) {
//gui_data.clock_mutliplier = clamp_double(0.5, 1.0, gui_data.clock_mutliplier + 1.0 / 16);
GB_set_clock_multiplier(gb, gui_data.clock_mutliplier);
}
else if (config.analog_speed_controls && gui_data.analog_clock_multiplier_valid) {
else if (config.controls.analog_speed_controls && gui_data.analog_clock_multiplier_valid) {
GB_set_clock_multiplier(gb, gui_data.analog_clock_multiplier);
if (gui_data.analog_clock_multiplier == 1.0) {
@ -1296,7 +1296,7 @@ static void handle_events(GB_gameboy_t *gb) {
SDL_GameControllerUpdate();
uint8_t controller_state = 0;
double analog_clock_multiplier = 1.0;
gui_data.analog_clock_multiplier = 1.0;
for (unsigned i = 0; i < gui_data.controller_count; i++) {
struct Controller_t *s = &gui_data.controllers[i];
@ -1307,16 +1307,16 @@ static void handle_events(GB_gameboy_t *gb) {
int16_t right_x_axis = SDL_GameControllerGetAxis(s->controller, SDL_CONTROLLER_AXIS_RIGHTX);
int16_t right_y_axis = SDL_GameControllerGetAxis(s->controller, SDL_CONTROLLER_AXIS_RIGHTY);
if (config.analog_speed_controls) {
if (config.controls.analog_speed_controls) {
double left_trigger = (double) SDL_GameControllerGetAxis(s->controller, SDL_CONTROLLER_AXIS_TRIGGERLEFT) / (double) 32767;
double right_trigger = (double) SDL_GameControllerGetAxis(s->controller, SDL_CONTROLLER_AXIS_TRIGGERRIGHT) / (double) 32767;
if (left_trigger > 0.0) {
analog_clock_multiplier = min_double(analog_clock_multiplier, clamp_double(1.0 / 3, 1.0, 1 - left_trigger + 0.2));
gui_data.analog_clock_multiplier = min_double(gui_data.analog_clock_multiplier, clamp_double(1.0 / 3, 1.0, 1 - left_trigger + 0.2));
gui_data.analog_clock_multiplier_valid = true;
}
else if (right_trigger > 0.0) {
analog_clock_multiplier = max_double(analog_clock_multiplier, clamp_double(1.0, 3.0, right_trigger * 3 + 0.8));
gui_data.analog_clock_multiplier = max_double(gui_data.analog_clock_multiplier, clamp_double(1.0, 3.0, right_trigger * 3 + 0.8));
gui_data.analog_clock_multiplier_valid = true;
}
}
@ -1380,8 +1380,6 @@ static void handle_events(GB_gameboy_t *gb) {
}
}
gui_data.analog_clock_multiplier = analog_clock_multiplier;
GB_set_key_state(gb, GB_KEY_RIGHT, (gui_data.pressed_buttons & BUTTON_MASK_RIGHT) | (controller_state & BUTTON_MASK_RIGHT));
GB_set_key_state(gb, GB_KEY_LEFT, (gui_data.pressed_buttons & BUTTON_MASK_LEFT) | (controller_state & BUTTON_MASK_LEFT));
GB_set_key_state(gb, GB_KEY_UP, (gui_data.pressed_buttons & BUTTON_MASK_UP) | (controller_state & BUTTON_MASK_UP));
@ -1420,8 +1418,8 @@ static void load_boot_rom(GB_gameboy_t *gb, GB_boot_rom_t type) {
}
}
else { config_boot_rom:
if (config.boot_rom_path != NULL && g_strcmp0(config.boot_rom_path, "other") != 0 && g_strcmp0(config.boot_rom_path, "auto") != 0) {
boot_rom_path = g_build_filename(config.boot_rom_path, boot_rom_name, NULL);
if (config.emulation.boot_rom_path != NULL && g_strcmp0(config.emulation.boot_rom_path, "other") != 0 && g_strcmp0(config.emulation.boot_rom_path, "auto") != 0) {
boot_rom_path = g_build_filename(config.emulation.boot_rom_path, boot_rom_name, NULL);
g_message("Trying to load boot ROM from %s", boot_rom_path);
if (GB_load_boot_rom(gb, boot_rom_path)) {
@ -1464,7 +1462,7 @@ static void init(void) {
GB_set_sample_rate(&gb, GB_audio_get_sample_rate());
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_rewind_length(&gb, config.emulation.rewind_duration);
GB_set_update_input_hint_callback(&gb, handle_events);
GB_apu_set_sample_callback(&gb, gb_audio_callback);
GB_set_input_callback(&gb, sync_console_input);
@ -1604,11 +1602,14 @@ static gpointer run_thread(gpointer null_ptr) {
gui_data.battery_save_path = battery_save_path;
gui_data.cheats_save_path = cheats_save_path;
if (!GB_is_inited(&gb)) {
init();
}
if (gui_data.stopped) {
start();
}
else {
init();
reset();
start();
}
@ -2015,11 +2016,11 @@ static void startup(GApplication *app, gpointer null_ptr) {
gui_data.console = GTK_WINDOW(get_object("console"));
gui_data.printer = GTK_WINDOW(get_object("printer"));
if (config.sample_rate == -1) {
if (config.audio.sample_rate == -1) {
gui_data.sample_rate = GB_audio_default_sample_rate();
}
else {
gui_data.sample_rate = config.sample_rate;
gui_data.sample_rate = config.audio.sample_rate;
}
// setup main window
@ -2107,12 +2108,12 @@ static void update_viewport(void) {
double x_factor = win_width / (double) GB_get_screen_width(&gb);
double y_factor = win_height / (double) GB_get_screen_height(&gb);
if (config.use_integer_scaling) {
if (config.video.use_integer_scaling) {
x_factor = (int)(x_factor);
y_factor = (int)(y_factor);
}
if (config.keep_aspect_ratio) {
if (config.video.keep_aspect_ratio) {
if (x_factor > y_factor) {
x_factor = y_factor;
}
@ -2231,7 +2232,7 @@ static void gl_init(GtkWidget *w) {
renderer = (char *)glGetString(GL_RENDERER);
g_debug("GtkGLArea on %s", renderer ? renderer : "Unknown");
if (config.shader == NULL || (!init_shader_with_name(&gui_data.shader, config.shader) && !init_shader_with_name(&gui_data.shader, "NearestNeighbor"))) {
if (config.video.shader == NULL || (!init_shader_with_name(&gui_data.shader, config.video.shader) && !init_shader_with_name(&gui_data.shader, "NearestNeighbor"))) {
GError *error = g_error_new_literal(g_quark_from_string("sameboy-gl-error"), 1, "Failed to initialize shaders");
gtk_gl_area_set_error(gl_area, error);
}
@ -2300,9 +2301,6 @@ static void setup_console(void) {
// This function gets called when the GApplication gets activated, i.e. it is ready to show widgets.
static void activate(GApplication *app, gpointer null_ptr) {
// initialize SameBoy core
init();
init_audio();
init_controllers();
@ -2535,25 +2533,25 @@ G_MODULE_EXPORT void on_boot_rom_location_changed(GtkWidget *w, gpointer user_da
gint res = gtk_native_dialog_run(GTK_NATIVE_DIALOG(native));
if (res == GTK_RESPONSE_ACCEPT) {
config.boot_rom_path = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(native));
config.emulation.boot_rom_path = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(native));
update_boot_rom_selector(gui_data.builder);
}
g_object_unref(native);
}
else {
config.boot_rom_path = (gchar *)id;
config.emulation.boot_rom_path = (gchar *)id;
}
}
G_MODULE_EXPORT void on_cgb_model_changed(GtkWidget *w, gpointer user_data_ptr) {
GtkComboBox *box = GTK_COMBO_BOX(w);
config.cgb_revision_name = (gchar *)gtk_combo_box_get_active_id(box);
config.emulation.cgb_revision_name = (gchar *)gtk_combo_box_get_active_id(box);
}
G_MODULE_EXPORT void on_color_correction_changed(GtkWidget *w, gpointer user_data_ptr) {
GtkComboBox *box = GTK_COMBO_BOX(w);
config.color_correction_id = (gchar *)gtk_combo_box_get_active_id(box);
config.video.color_correction_id = (gchar *)gtk_combo_box_get_active_id(box);
if (GB_is_inited(&gb)) {
GB_set_color_correction_mode(&gb, get_color_correction_mode());
@ -2562,42 +2560,42 @@ G_MODULE_EXPORT void on_color_correction_changed(GtkWidget *w, gpointer user_dat
G_MODULE_EXPORT void on_frame_blending_changed(GtkWidget *w, gpointer user_data_ptr) {
GtkComboBox *box = GTK_COMBO_BOX(w);
config.frame_blending_mode = (gchar *)gtk_combo_box_get_active_id(box);
config.video.frame_blending_mode = (gchar *)gtk_combo_box_get_active_id(box);
}
G_MODULE_EXPORT void on_display_border_changed(GtkWidget *w, gpointer user_data_ptr) {
GtkComboBox *box = GTK_COMBO_BOX(w);
config.display_border_mode = (gchar *)gtk_combo_box_get_active_id(box);
config.video.display_border_mode = (gchar *)gtk_combo_box_get_active_id(box);
gui_data.border_mode_changed = true;
}
G_MODULE_EXPORT void on_monochrome_palette_changed(GtkWidget *w, gpointer user_data_ptr) {
GtkComboBox *box = GTK_COMBO_BOX(w);
config.monochrome_palette_id = (gchar *)gtk_combo_box_get_active_id(box);
config.video.monochrome_palette_id = (gchar *)gtk_combo_box_get_active_id(box);
GB_set_palette(&gb, get_monochrome_palette());
}
G_MODULE_EXPORT void on_color_menubar_override_changed(GtkWidget *w, gpointer user_data_ptr) {
config.menubar_override = (gchar *)gtk_combo_box_get_active_id(GTK_COMBO_BOX(w));
config.video.menubar_override = (gchar *)gtk_combo_box_get_active_id(GTK_COMBO_BOX(w));
}
G_MODULE_EXPORT void on_dmg_model_changed(GtkWidget *w, gpointer user_data_ptr) {
GtkComboBox *box = GTK_COMBO_BOX(w);
config.dmg_revision_name = (gchar *)gtk_combo_box_get_active_id(box);
config.emulation.dmg_revision_name = (gchar *)gtk_combo_box_get_active_id(box);
}
G_MODULE_EXPORT void on_graphic_filter_changed(GtkWidget *w, gpointer user_data_ptr) {
GtkComboBox *box = GTK_COMBO_BOX(w);
config.shader = (gchar *)gtk_combo_box_get_active_id(box);
config.video.shader = (gchar *)gtk_combo_box_get_active_id(box);
free_shader(&gui_data.shader);
init_shader_with_name(&gui_data.shader, config.shader);
init_shader_with_name(&gui_data.shader, config.video.shader);
}
G_MODULE_EXPORT void on_highpass_filter_changed(GtkWidget *w, gpointer user_data_ptr) {
config.high_pass_filter_id = (gchar *)gtk_combo_box_get_active_id(GTK_COMBO_BOX(w));
config.audio.high_pass_filter_id = (gchar *)gtk_combo_box_get_active_id(GTK_COMBO_BOX(w));
if (GB_is_inited(&gb)) {
GB_set_highpass_filter_mode(&gb, get_highpass_mode());
@ -2607,25 +2605,25 @@ G_MODULE_EXPORT void on_highpass_filter_changed(GtkWidget *w, gpointer user_data
G_MODULE_EXPORT void on_keep_aspect_ratio_changed(GtkWidget *w, gpointer user_data_ptr) {
GtkCheckButton *button = GTK_CHECK_BUTTON(w);
gboolean value = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button));
config.keep_aspect_ratio = value;
config.video.keep_aspect_ratio = value;
update_viewport();
}
G_MODULE_EXPORT void on_rewind_duration_changed(GtkWidget *w, gpointer user_data_ptr) {
GtkComboBox *box = GTK_COMBO_BOX(w);
config.rewind_duration = g_ascii_strtoll(gtk_combo_box_get_active_id(box), NULL, 10);
GB_set_rewind_length(&gb, config.rewind_duration);
config.emulation.rewind_duration = g_ascii_strtoll(gtk_combo_box_get_active_id(box), NULL, 10);
GB_set_rewind_length(&gb, config.emulation.rewind_duration);
}
G_MODULE_EXPORT void on_sample_rate_changed(GtkWidget *w, gpointer user_data_ptr) {
GtkComboBox *box = GTK_COMBO_BOX(w);
config.sample_rate = g_ascii_strtoll(gtk_combo_box_get_active_id(box), NULL, 10);
config.audio.sample_rate = g_ascii_strtoll(gtk_combo_box_get_active_id(box), NULL, 10);
if (config.sample_rate == -1) {
if (config.audio.sample_rate == -1) {
gui_data.sample_rate = GB_audio_default_sample_rate();
}
else {
gui_data.sample_rate = config.sample_rate;
gui_data.sample_rate = config.audio.sample_rate;
}
init_audio();
@ -2633,13 +2631,13 @@ G_MODULE_EXPORT void on_sample_rate_changed(GtkWidget *w, gpointer user_data_ptr
G_MODULE_EXPORT void on_sgb_model_changed(GtkWidget *w, gpointer user_data_ptr) {
GtkComboBox *box = GTK_COMBO_BOX(w);
config.sgb_revision_name = (gchar *)gtk_combo_box_get_active_id(box);
config.emulation.sgb_revision_name = (gchar *)gtk_combo_box_get_active_id(box);
}
G_MODULE_EXPORT void on_use_integer_scaling_changed(GtkWidget *w, gpointer user_data_ptr) {
GtkCheckButton *button = GTK_CHECK_BUTTON(w);
gboolean value = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button));
config.use_integer_scaling = value;
config.video.use_integer_scaling = value;
update_viewport();
}
@ -2674,7 +2672,7 @@ G_MODULE_EXPORT void console_on_enter(GtkWidget *w, gpointer user_data_ptr) {
G_MODULE_EXPORT void on_rumble_mode_changed(GtkWidget *w, gpointer user_data_ptr) {
GtkComboBox *box = GTK_COMBO_BOX(w);
config.rumble_mode = (gchar *)gtk_combo_box_get_active_id(box);
config.controls.rumble_mode = (gchar *)gtk_combo_box_get_active_id(box);
GB_set_rumble_mode(&gb, get_rumble_mode());
}
@ -2682,7 +2680,7 @@ G_MODULE_EXPORT void on_rumble_mode_changed(GtkWidget *w, gpointer user_data_ptr
G_MODULE_EXPORT void on_analog_speed_controls_changed(GtkWidget *w, gpointer user_data_ptr) {
GtkCheckButton *button = GTK_CHECK_BUTTON(w);
gboolean value = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button));
config.analog_speed_controls = value;
config.controls.analog_speed_controls = value;
}
int main(int argc, char *argv[]) {

View File

@ -12,44 +12,54 @@ static void print_config_error(GError *error) {
}
void _print_config(config_t *config, GLogLevelFlags log_level) {
#define EXPAND_GROUP(group_name, members) \
g_log(G_LOG_DOMAIN, log_level, "[%s]", #group_name); \
members
#define EXPAND_GROUP(name, members) { \
g_log(G_LOG_DOMAIN, log_level, "[%s]", #name); \
struct config_ ## name ## _t *group = &config->name; \
members \
}
#define EXPAND_GROUP_MEMBER(member, key_type, default_value) \
g_log(G_LOG_DOMAIN, log_level, "%s="FORMAT_FOR_KEY_TYPE(key_type)"", #member, config->member);
#define EXPAND_GROUP_MEMBER(member, key_type, default_value) \
g_log(G_LOG_DOMAIN, log_level, "%s="FORMAT_FOR_KEY_TYPE(key_type)"", #member, group->member);
EXPAND_CONFIG
#undef EXPAND_GROUP
#undef EXPAND_GROUP_MEMBER
}
#undef EXPAND_GROUP
#undef EXPAND_GROUP_MEMBER
// Duplicates the input and converts the first character to uppercase
gchar* ascii_ucfirst(gchar *str) {
gchar *out = g_strdup(str);
out[0] = g_ascii_toupper(str[0]);
return out;
}
void load_config_from_key_file(config_t *config, GKeyFile *key_file) {
g_message("Loading config from key file");
GError *error = NULL;
gchar *group_name;
#define EXPAND_GROUP(name, members) \
group_name = #name; \
members
#define EXPAND_GROUP(name_arg, members) { \
struct config_ ## name_arg ## _t *group = &config->name_arg; \
g_autofree gchar *group_name = ascii_ucfirst(#name_arg); \
members \
}
#define EXPAND_GROUP_MEMBER(member, key_type, default_value) \
config->member = g_key_file_get_##key_type(key_file, group_name, #member, &error); \
#define EXPAND_GROUP_MEMBER(member, key_type, default_value) \
group->member = g_key_file_get_##key_type(key_file, group_name, #member, &error); \
if (error != NULL) { \
config->member = default_value; \
group->member = default_value; \
print_config_error(error); \
g_clear_error(&error); \
}
EXPAND_CONFIG
if (config->rewind_duration > 600) {
if (config->emulation.rewind_duration > 600) {
g_warning("Setting Emulation.rewind_duration too high might affect performance.");
}
#undef EXPAND_GROUP
#undef EXPAND_GROUP_MEMBER
#undef EXPAND_GROUP
#undef EXPAND_GROUP_MEMBER
}
void print_config(config_t *config) {
@ -61,16 +71,18 @@ void save_config_to_key_file(config_t *config, GKeyFile *key_file) {
GError *error = NULL;
gchar *group_name;
#define EXPAND_GROUP(name, members) \
group_name = #name; \
members
#define EXPAND_GROUP(name_arg, members) { \
struct config_ ## name_arg ## _t *group = &config->name_arg; \
g_autofree gchar *group_name = ascii_ucfirst(#name_arg); \
members \
}
#define EXPAND_GROUP_MEMBER_IF_0(member, key_type, default_value) \
g_key_file_set_##key_type(key_file, group_name, #member, config->member);
#define EXPAND_GROUP_MEMBER_IF_0(member, key_type, default_value) \
g_key_file_set_##key_type(key_file, group_name, #member, group->member);
#define EXPAND_GROUP_MEMBER_IF_1(member, key_type, default_value) \
if (config->member != NULL) { \
g_key_file_set_##key_type(key_file, group_name, #member, config->member); \
#define EXPAND_GROUP_MEMBER_IF_1(member, key_type, default_value) \
if (group->member != NULL) { \
g_key_file_set_##key_type(key_file, group_name, #member, group->member); \
} \
else if (g_key_file_has_key(key_file, group_name, #member, &error)) { \
if (error != NULL) { \
@ -84,18 +96,18 @@ void save_config_to_key_file(config_t *config, GKeyFile *key_file) {
} \
}
#define EXPAND_GROUP_MEMBER_IF_EVAL(y, member, key_type, default_value) EXPAND_GROUP_MEMBER_IF_ ## y(member, key_type, default_value)
#define EXPAND_GROUP_MEMBER_IF(member, key_type, is_pointer, default_value) EXPAND_GROUP_MEMBER_IF_EVAL(is_pointer, member, key_type, default_value)
#define EXPAND_GROUP_MEMBER(member, key_type, default_value) EXPAND_GROUP_MEMBER_IF(member, key_type, GTYPE_IS_POINTER(key_type), default_value)
#define EXPAND_GROUP_MEMBER_IF_EVAL(y, member, key_type, default_value) EXPAND_GROUP_MEMBER_IF_ ## y(member, key_type, default_value)
#define EXPAND_GROUP_MEMBER_IF(member, key_type, is_pointer, default_value) EXPAND_GROUP_MEMBER_IF_EVAL(is_pointer, member, key_type, default_value)
#define EXPAND_GROUP_MEMBER(member, key_type, default_value) EXPAND_GROUP_MEMBER_IF(member, key_type, GTYPE_IS_POINTER(key_type), default_value)
EXPAND_CONFIG
#undef EXPAND_GROUP
#undef EXPAND_GROUP_MEMBER
#undef EXPAND_GROUP_MEMBER_IF
#undef EXPAND_GROUP_MEMBER_IF_EVAL
#undef EXPAND_GROUP_MEMBER_IF_0
#undef EXPAND_GROUP_MEMBER_IF_1
#undef EXPAND_GROUP
#undef EXPAND_GROUP_MEMBER
#undef EXPAND_GROUP_MEMBER_IF
#undef EXPAND_GROUP_MEMBER_IF_EVAL
#undef EXPAND_GROUP_MEMBER_IF_0
#undef EXPAND_GROUP_MEMBER_IF_1
}
void on_preferences_realize(GtkWidget *w, gpointer builder_ptr) {
@ -105,30 +117,30 @@ void on_preferences_realize(GtkWidget *w, gpointer builder_ptr) {
update_boot_rom_selector(builder);
// Hook up the static preferences
gtk_combo_box_set_active_id(builder_get(GTK_COMBO_BOX, "rewind_duration_selector"), g_strdup_printf("%i", config.rewind_duration));
gtk_combo_box_set_active_id(builder_get(GTK_COMBO_BOX, "dmg_revision_selector"), config.dmg_revision_name);
gtk_combo_box_set_active_id(builder_get(GTK_COMBO_BOX, "sgb_revision_selector"), config.sgb_revision_name);
gtk_combo_box_set_active_id(builder_get(GTK_COMBO_BOX, "cgb_revision_selector"), config.cgb_revision_name);
gtk_combo_box_set_active_id(builder_get(GTK_COMBO_BOX, "shader_selector"), config.shader);
gtk_combo_box_set_active_id(builder_get(GTK_COMBO_BOX, "color_correction_selector"), config.color_correction_id);
gtk_combo_box_set_active_id(builder_get(GTK_COMBO_BOX, "frame_blending_selector"), config.frame_blending_mode);
gtk_combo_box_set_active_id(builder_get(GTK_COMBO_BOX, "display_border_selector"), config.display_border_mode);
gtk_combo_box_set_active_id(builder_get(GTK_COMBO_BOX, "monochrome_palette_selector"), config.monochrome_palette_id);
gtk_toggle_button_set_active(builder_get(GTK_TOGGLE_BUTTON, "integer_scaling_toggle"), config.use_integer_scaling);
gtk_toggle_button_set_active(builder_get(GTK_TOGGLE_BUTTON, "aspect_ratio_toggle"), config.keep_aspect_ratio);
gtk_combo_box_set_active_id(builder_get(GTK_COMBO_BOX, "highpass_filter_selector"), config.high_pass_filter_id);
gtk_combo_box_set_active_id(builder_get(GTK_COMBO_BOX, "sample_rate_selector"), g_strdup_printf("%i", config.sample_rate));
gtk_toggle_button_set_active(builder_get(GTK_TOGGLE_BUTTON, "analog_speed_controls_toggle"), config.analog_speed_controls);
gtk_combo_box_set_active_id(builder_get(GTK_COMBO_BOX, "rumble_mode_selector"), config.rumble_mode);
gtk_combo_box_set_active_id(builder_get(GTK_COMBO_BOX, "rewind_duration_selector"), g_strdup_printf("%i", config.emulation.rewind_duration));
gtk_combo_box_set_active_id(builder_get(GTK_COMBO_BOX, "dmg_revision_selector"), config.emulation.dmg_revision_name);
gtk_combo_box_set_active_id(builder_get(GTK_COMBO_BOX, "sgb_revision_selector"), config.emulation.sgb_revision_name);
gtk_combo_box_set_active_id(builder_get(GTK_COMBO_BOX, "cgb_revision_selector"), config.emulation.cgb_revision_name);
gtk_combo_box_set_active_id(builder_get(GTK_COMBO_BOX, "shader_selector"), config.video.shader);
gtk_combo_box_set_active_id(builder_get(GTK_COMBO_BOX, "color_correction_selector"), config.video.color_correction_id);
gtk_combo_box_set_active_id(builder_get(GTK_COMBO_BOX, "frame_blending_selector"), config.video.frame_blending_mode);
gtk_combo_box_set_active_id(builder_get(GTK_COMBO_BOX, "display_border_selector"), config.video.display_border_mode);
gtk_combo_box_set_active_id(builder_get(GTK_COMBO_BOX, "monochrome_palette_selector"), config.video.monochrome_palette_id);
gtk_toggle_button_set_active(builder_get(GTK_TOGGLE_BUTTON, "integer_scaling_toggle"), config.video.use_integer_scaling);
gtk_toggle_button_set_active(builder_get(GTK_TOGGLE_BUTTON, "aspect_ratio_toggle"), config.video.keep_aspect_ratio);
gtk_combo_box_set_active_id(builder_get(GTK_COMBO_BOX, "highpass_filter_selector"), config.audio.high_pass_filter_id);
gtk_combo_box_set_active_id(builder_get(GTK_COMBO_BOX, "sample_rate_selector"), g_strdup_printf("%i", config.audio.sample_rate));
gtk_toggle_button_set_active(builder_get(GTK_TOGGLE_BUTTON, "analog_speed_controls_toggle"), config.controls.analog_speed_controls);
gtk_combo_box_set_active_id(builder_get(GTK_COMBO_BOX, "rumble_mode_selector"), config.controls.rumble_mode);
#if ! NDEBUG
gtk_combo_box_set_active_id(builder_get(GTK_COMBO_BOX, "menubar_override_selector"), config.menubar_override);
#else
#if ! NDEBUG
gtk_combo_box_set_active_id(builder_get(GTK_COMBO_BOX, "menubar_override_selector"), config.video.menubar_override);
#else
if (builder_get(GTK_COMBO_BOX, "menubar_override_selector") != NULL) {
gtk_widget_destroy(GTK_WIDGET(builder_get(GTK_COMBO_BOX, "menubar_override_selector")));
gtk_widget_destroy(GTK_WIDGET(builder_get(GTK_COMBO_BOX, "menubar_override_selector_label")));
}
#endif
#endif
}
void init_settings(gchar *path, GtkWindow *preferences) {
@ -192,9 +204,9 @@ void update_boot_rom_selector(GtkBuilder *builder) {
GtkComboBoxText *combo_box = builder_get(GTK_COMBO_BOX_TEXT, "boot_rom_selector");
gtk_combo_box_text_remove_all(combo_box);
gtk_combo_box_text_append(combo_box, "auto", "Use Built-in Boot ROMs");
if (config.boot_rom_path != NULL && !g_str_equal(config.boot_rom_path, "auto") && !g_str_equal(config.boot_rom_path, "other")) {
gtk_combo_box_text_append(combo_box, config.boot_rom_path, config.boot_rom_path);
gtk_combo_box_set_active_id(GTK_COMBO_BOX(combo_box), config.boot_rom_path);
if (config.emulation.boot_rom_path != NULL && !g_str_equal(config.emulation.boot_rom_path, "auto") && !g_str_equal(config.emulation.boot_rom_path, "other")) {
gtk_combo_box_text_append(combo_box, config.emulation.boot_rom_path, config.emulation.boot_rom_path);
gtk_combo_box_set_active_id(GTK_COMBO_BOX(combo_box), config.emulation.boot_rom_path);
}
else {
gtk_combo_box_set_active_id(GTK_COMBO_BOX(combo_box), "auto");
@ -204,170 +216,170 @@ void update_boot_rom_selector(GtkBuilder *builder) {
}
enum menubar_type_t get_show_menubar(void) {
if (config.menubar_override == NULL) goto default_value;
if (config.video.menubar_override == NULL) goto default_value;
if (g_strcmp0(config.menubar_override, "auto") == 0) {
if (g_strcmp0(config.video.menubar_override, "auto") == 0) {
return MENUBAR_AUTO;
}
else if (g_strcmp0(config.menubar_override, "show_in_shell") == 0) {
else if (g_strcmp0(config.video.menubar_override, "show_in_shell") == 0) {
return MENUBAR_SHOW_IN_SHELL;
}
else if (g_strcmp0(config.menubar_override, "show_in_window") == 0) {
else if (g_strcmp0(config.video.menubar_override, "show_in_window") == 0) {
return MENUBAR_SHOW_IN_WINDOW;
}
else if (g_strcmp0(config.menubar_override, "show_hamburger") == 0) {
else if (g_strcmp0(config.video.menubar_override, "show_hamburger") == 0) {
return MENUBAR_SHOW_HAMBURGER;
}
// This should not happen
g_warning("Unknown menubar setting: %s\nFalling back to “Auto”", config.menubar_override);
g_warning("Unknown menubar setting: %s\nFalling back to “Auto”", config.video.menubar_override);
default_value: return MENUBAR_AUTO;
}
void set_show_menubar(enum menubar_type_t value) {
switch (value) {
case MENUBAR_AUTO:
config.menubar_override = "auto";
config.video.menubar_override = "auto";
break;
case MENUBAR_SHOW_IN_SHELL:
config.menubar_override = "show_in_shell";
config.video.menubar_override = "show_in_shell";
break;
case MENUBAR_SHOW_IN_WINDOW:
config.menubar_override = "show_in_window";
config.video.menubar_override = "show_in_window";
break;
case MENUBAR_SHOW_HAMBURGER:
config.menubar_override = "show_hamburger";
config.video.menubar_override = "show_hamburger";
break;
}
}
GB_color_correction_mode_t get_color_correction_mode(void) {
if (config.color_correction_id == NULL) goto default_value;
if (config.video.color_correction_id == NULL) goto default_value;
if (g_strcmp0(config.color_correction_id, "disabled") == 0) {
if (g_strcmp0(config.video.color_correction_id, "disabled") == 0) {
return GB_COLOR_CORRECTION_DISABLED;
}
else if (g_strcmp0(config.color_correction_id, "correct_color_curves") == 0) {
else if (g_strcmp0(config.video.color_correction_id, "correct_color_curves") == 0) {
return GB_COLOR_CORRECTION_CORRECT_CURVES;
}
else if (g_strcmp0(config.color_correction_id, "emulate_hardware") == 0) {
else if (g_strcmp0(config.video.color_correction_id, "emulate_hardware") == 0) {
return GB_COLOR_CORRECTION_EMULATE_HARDWARE;
}
else if (g_strcmp0(config.color_correction_id, "preserve_brightness") == 0) {
else if (g_strcmp0(config.video.color_correction_id, "preserve_brightness") == 0) {
return GB_COLOR_CORRECTION_PRESERVE_BRIGHTNESS;
}
else if (g_strcmp0(config.color_correction_id, "reduce_contrast") == 0) {
else if (g_strcmp0(config.video.color_correction_id, "reduce_contrast") == 0) {
return GB_COLOR_CORRECTION_REDUCE_CONTRAST;
}
// This should not happen
g_warning("Unknown color correction mode: %s\nFalling back to “Emulate Hardware”", config.color_correction_id);
g_warning("Unknown color correction mode: %s\nFalling back to “Emulate Hardware”", config.video.color_correction_id);
default_value: return GB_COLOR_CORRECTION_EMULATE_HARDWARE;
}
void set_color_correction_mode(GB_color_correction_mode_t mode) {
switch (mode) {
case GB_COLOR_CORRECTION_DISABLED:
config.color_correction_id = "disabled";
config.video.color_correction_id = "disabled";
break;
case GB_COLOR_CORRECTION_CORRECT_CURVES:
config.color_correction_id = "correct_color_curves";
config.video.color_correction_id = "correct_color_curves";
break;
case GB_COLOR_CORRECTION_EMULATE_HARDWARE:
config.color_correction_id = "emulate_hardware";
config.video.color_correction_id = "emulate_hardware";
break;
case GB_COLOR_CORRECTION_PRESERVE_BRIGHTNESS:
config.color_correction_id = "preserve_brightness";
config.video.color_correction_id = "preserve_brightness";
break;
case GB_COLOR_CORRECTION_REDUCE_CONTRAST:
config.color_correction_id = "reduce_contrast";
config.video.color_correction_id = "reduce_contrast";
break;
}
}
GB_frame_blending_mode_t get_frame_blending_mode(void) {
if (config.frame_blending_mode == NULL) goto default_value;
if (config.video.frame_blending_mode == NULL) goto default_value;
if (g_strcmp0(config.frame_blending_mode, "disabled") == 0) {
if (g_strcmp0(config.video.frame_blending_mode, "disabled") == 0) {
return GB_FRAME_BLENDING_MODE_DISABLED;
}
else if (g_strcmp0(config.frame_blending_mode, "simple") == 0) {
else if (g_strcmp0(config.video.frame_blending_mode, "simple") == 0) {
return GB_FRAME_BLENDING_MODE_SIMPLE;
}
else if (g_strcmp0(config.frame_blending_mode, "accurate") == 0) {
else if (g_strcmp0(config.video.frame_blending_mode, "accurate") == 0) {
return GB_FRAME_BLENDING_MODE_ACCURATE;
}
// This should not happen
g_warning("Unknown frame blending mode: %s\nFalling back to “Disabled”", config.frame_blending_mode);
g_warning("Unknown frame blending mode: %s\nFalling back to “Disabled”", config.video.frame_blending_mode);
default_value: return GB_FRAME_BLENDING_MODE_DISABLED;
}
void set_frame_blending_mode(GB_frame_blending_mode_t mode) {
switch (mode) {
case GB_FRAME_BLENDING_MODE_DISABLED:
config.frame_blending_mode = "disabled";
config.video.frame_blending_mode = "disabled";
break;
case GB_FRAME_BLENDING_MODE_SIMPLE:
config.frame_blending_mode = "simple";
config.video.frame_blending_mode = "simple";
break;
case GB_FRAME_BLENDING_MODE_ACCURATE:
case GB_FRAME_BLENDING_MODE_ACCURATE_ODD:
config.frame_blending_mode = "accurate";
config.video.frame_blending_mode = "accurate";
break;
}
}
GB_border_mode_t get_display_border_mode(void) {
if (config.display_border_mode == NULL) goto default_value;
if (config.video.display_border_mode == NULL) goto default_value;
if (g_strcmp0(config.display_border_mode, "never") == 0) {
if (g_strcmp0(config.video.display_border_mode, "never") == 0) {
return GB_BORDER_NEVER;
}
else if (g_strcmp0(config.display_border_mode, "sgb_only") == 0) {
else if (g_strcmp0(config.video.display_border_mode, "sgb_only") == 0) {
return GB_BORDER_SGB;
}
else if (g_strcmp0(config.display_border_mode, "always") == 0) {
else if (g_strcmp0(config.video.display_border_mode, "always") == 0) {
return GB_BORDER_ALWAYS;
}
// This should not happen
g_warning("Unknown SGB border mode: %s\nFalling back to “Never”", config.display_border_mode);
g_warning("Unknown SGB border mode: %s\nFalling back to “Never”", config.video.display_border_mode);
default_value: return GB_BORDER_NEVER;
}
void set_display_border_mode(GB_border_mode_t mode) {
switch (mode) {
case GB_BORDER_NEVER:
config.display_border_mode = "never";
config.video.display_border_mode = "never";
break;
case GB_BORDER_SGB:
config.display_border_mode = "sgb_only";
config.video.display_border_mode = "sgb_only";
break;
case GB_BORDER_ALWAYS:
config.display_border_mode = "always";
config.video.display_border_mode = "always";
break;
}
}
const GB_palette_t* get_monochrome_palette(void) {
if (config.monochrome_palette_id == NULL) goto default_value;
if (config.video.monochrome_palette_id == NULL) goto default_value;
if (g_strcmp0(config.monochrome_palette_id, "greyscale") == 0) {
if (g_strcmp0(config.video.monochrome_palette_id, "greyscale") == 0) {
return &GB_PALETTE_GREY;
}
else if (g_strcmp0(config.monochrome_palette_id, "lime") == 0) {
else if (g_strcmp0(config.video.monochrome_palette_id, "lime") == 0) {
return &GB_PALETTE_DMG;
}
else if (g_strcmp0(config.monochrome_palette_id, "olive") == 0) {
else if (g_strcmp0(config.video.monochrome_palette_id, "olive") == 0) {
return &GB_PALETTE_MGB;
}
else if (g_strcmp0(config.monochrome_palette_id, "teal") == 0) {
else if (g_strcmp0(config.video.monochrome_palette_id, "teal") == 0) {
return &GB_PALETTE_GBL;
}
// This should not happen
g_warning("Unknown monochrome palette: %s\nFalling back to “Greyscale”", config.monochrome_palette_id);
g_warning("Unknown monochrome palette: %s\nFalling back to “Greyscale”", config.video.monochrome_palette_id);
default_value: return &GB_PALETTE_GREY;
}
@ -375,90 +387,90 @@ void set_monochrome_palette(const GB_palette_t *mode) {
g_message("%p | %p | %p | %p | %p", mode, &GB_PALETTE_GREY, &GB_PALETTE_DMG, &GB_PALETTE_MGB, &GB_PALETTE_GBL);
if (mode == &GB_PALETTE_GREY) {
config.monochrome_palette_id = "greyscale";
config.video.monochrome_palette_id = "greyscale";
}
else if (mode == &GB_PALETTE_DMG) {
config.monochrome_palette_id = "lime";
config.video.monochrome_palette_id = "lime";
}
else if (mode == &GB_PALETTE_MGB) {
config.monochrome_palette_id = "olive";
config.video.monochrome_palette_id = "olive";
}
else if (mode == &GB_PALETTE_GBL) {
config.monochrome_palette_id = "teal";
config.video.monochrome_palette_id = "teal";
}
}
GB_highpass_mode_t get_highpass_mode(void) {
if (config.high_pass_filter_id == NULL) goto default_value;
if (config.audio.high_pass_filter_id == NULL) goto default_value;
if (g_strcmp0(config.high_pass_filter_id, "disabled") == 0) {
if (g_strcmp0(config.audio.high_pass_filter_id, "disabled") == 0) {
return GB_HIGHPASS_OFF;
}
else if (g_strcmp0(config.high_pass_filter_id, "emulate_hardware") == 0) {
else if (g_strcmp0(config.audio.high_pass_filter_id, "emulate_hardware") == 0) {
return GB_HIGHPASS_ACCURATE;
}
else if (g_strcmp0(config.high_pass_filter_id, "preserve_waveform") == 0) {
else if (g_strcmp0(config.audio.high_pass_filter_id, "preserve_waveform") == 0) {
return GB_HIGHPASS_REMOVE_DC_OFFSET;
}
// This should not happen
g_warning("Unknown highpass mode: %s\nFalling back to “Accurate”", config.high_pass_filter_id);
g_warning("Unknown highpass mode: %s\nFalling back to “Accurate”", config.audio.high_pass_filter_id);
default_value: return GB_HIGHPASS_ACCURATE;
}
void set_highpass_mode(GB_highpass_mode_t mode) {
switch (mode) {
case GB_HIGHPASS_OFF:
config.high_pass_filter_id = "disabled";
config.audio.high_pass_filter_id = "disabled";
break;
case GB_HIGHPASS_MAX:
g_warning("GB_HIGHPASS_MAX is not a valid highpass mode, falling back to “Accurate”.");
case GB_HIGHPASS_ACCURATE:
config.high_pass_filter_id = "emulate_hardware";
config.audio.high_pass_filter_id = "emulate_hardware";
break;
case GB_HIGHPASS_REMOVE_DC_OFFSET:
config.high_pass_filter_id = "preserve_waveform";
config.audio.high_pass_filter_id = "preserve_waveform";
break;
}
}
const GB_rumble_mode_t get_rumble_mode(void) {
if (config.rumble_mode == NULL) goto default_value;
if (config.controls.rumble_mode == NULL) goto default_value;
if (g_strcmp0(config.rumble_mode, "never") == 0) {
if (g_strcmp0(config.controls.rumble_mode, "never") == 0) {
return GB_RUMBLE_DISABLED;
}
else if (g_strcmp0(config.rumble_mode, "rumble_cartridges") == 0) {
else if (g_strcmp0(config.controls.rumble_mode, "rumble_cartridges") == 0) {
return GB_RUMBLE_CARTRIDGE_ONLY;
}
else if (g_strcmp0(config.rumble_mode, "always") == 0) {
else if (g_strcmp0(config.controls.rumble_mode, "always") == 0) {
return GB_RUMBLE_ALL_GAMES;
}
// This should not happen
g_warning("Unknown highpass mode: %s\nFalling back to “Never”", config.rumble_mode);
g_warning("Unknown highpass mode: %s\nFalling back to “Never”", config.controls.rumble_mode);
default_value: return GB_RUMBLE_DISABLED;
}
void set_rumble_mode(GB_rumble_mode_t mode) {
switch (mode) {
case GB_RUMBLE_DISABLED:
config.rumble_mode = "never";
config.controls.rumble_mode = "never";
break;
case GB_RUMBLE_CARTRIDGE_ONLY:
config.rumble_mode = "rumble_cartridges";
config.controls.rumble_mode = "rumble_cartridges";
break;
case GB_RUMBLE_ALL_GAMES:
config.rumble_mode = "always";
config.controls.rumble_mode = "always";
break;
}
}
GB_model_t get_dmg_model(void) {
if (config.dmg_revision_name == NULL) goto default_value;
if (config.emulation.dmg_revision_name == NULL) goto default_value;
// TODO: Synchronize with GB_model_t (Core/gb.h)
if (g_strcmp0(config.dmg_revision_name, "DMG_CPU_B") == 0) {
if (g_strcmp0(config.emulation.dmg_revision_name, "DMG_CPU_B") == 0) {
return GB_MODEL_DMG_B;
}
@ -466,16 +478,16 @@ GB_model_t get_dmg_model(void) {
}
GB_model_t get_sgb_model(void) {
if (config.sgb_revision_name == NULL) goto default_value;
if (config.emulation.sgb_revision_name == NULL) goto default_value;
// TODO: Synchronize with GB_model_t (Core/gb.h)
if (g_strcmp0(config.sgb_revision_name, "SGB1_NTSC") == 0) {
if (g_strcmp0(config.emulation.sgb_revision_name, "SGB1_NTSC") == 0) {
return GB_MODEL_SGB_NTSC;
}
else if (g_strcmp0(config.sgb_revision_name, "SGB1_PAL") == 0) {
else if (g_strcmp0(config.emulation.sgb_revision_name, "SGB1_PAL") == 0) {
return GB_MODEL_SGB_PAL;
}
else if (g_strcmp0(config.sgb_revision_name, "SGB2") == 0) {
else if (g_strcmp0(config.emulation.sgb_revision_name, "SGB2") == 0) {
return GB_MODEL_SGB2;
}
@ -483,13 +495,13 @@ GB_model_t get_sgb_model(void) {
}
GB_model_t get_cgb_model(void) {
if (config.cgb_revision_name == NULL) goto default_value;
if (config.emulation.cgb_revision_name == NULL) goto default_value;
// TODO: Synchronize with GB_model_t (Core/gb.h)
if (g_strcmp0(config.cgb_revision_name, "CPU_CGB_C") == 0) {
if (g_strcmp0(config.emulation.cgb_revision_name, "CPU_CGB_C") == 0) {
return GB_MODEL_CGB_C;
}
else if (g_strcmp0(config.cgb_revision_name, "CPU_CGB_E") == 0) {
else if (g_strcmp0(config.emulation.cgb_revision_name, "CPU_CGB_E") == 0) {
return GB_MODEL_CGB_E;
}

View File

@ -22,21 +22,19 @@
#define GTYPE_IS_POINTER_integer 0
#define GTYPE_IS_POINTER_boolean 0
// Note: Make sure to use a member name only once for the whole config struct
//
// Macro usage:
// EXPAND_CONFIG(EXPAND_GROUP(…) EXPAND_GROUP(…) …)
// EXPAND_GROUP(group_name, group_members)
// EXPAND_GROUP_MEMBER(member_name, key_type, default_value)
#define EXPAND_CONFIG \
EXPAND_GROUP(Emulation, \
EXPAND_GROUP(emulation, \
EXPAND_GROUP_MEMBER(boot_rom_path, string, "auto") /* overrides search location for boot ROMs by name */ \
EXPAND_GROUP_MEMBER(rewind_duration, integer, 10) \
EXPAND_GROUP_MEMBER(dmg_revision_name, string, "DMG_CPU_C") \
EXPAND_GROUP_MEMBER(sgb_revision_name, string, "SGB2") \
EXPAND_GROUP_MEMBER(cgb_revision_name, string, "CPU_CGB_E") \
) \
EXPAND_GROUP(Video, \
EXPAND_GROUP(video, \
EXPAND_GROUP_MEMBER(shader, string, "NearestNeighbor") \
EXPAND_GROUP_MEMBER(color_correction_id, string, "emulate_hardware") \
EXPAND_GROUP_MEMBER(frame_blending_mode, string, "disabled") \
@ -46,21 +44,25 @@
EXPAND_GROUP_MEMBER(use_integer_scaling, boolean, true) \
EXPAND_GROUP_MEMBER(menubar_override, string, "auto") \
) \
EXPAND_GROUP(Audio, \
EXPAND_GROUP(audio, \
EXPAND_GROUP_MEMBER(high_pass_filter_id, string, "emulate_hardware") \
EXPAND_GROUP_MEMBER(sample_rate, integer, -1) \
) \
EXPAND_GROUP(Controls, \
EXPAND_GROUP(controls, \
EXPAND_GROUP_MEMBER(analog_speed_controls, boolean, false) \
EXPAND_GROUP_MEMBER(rumble_mode, string, "Never") \
)
typedef struct config_t {
#define EXPAND_GROUP(group_name, members) members
#define EXPAND_GROUP_MEMBER(member, key_type, default_value) GTYPE_OF_KEY_TYPE(key_type) member;
#define EXPAND_GROUP(group_name, members) struct config_ ## group_name ## _t { \
members \
} group_name;
#define EXPAND_GROUP_MEMBER(member, key_type, default_value) GTYPE_OF_KEY_TYPE(key_type) member;
EXPAND_CONFIG
#undef EXPAND_GROUP
#undef EXPAND_GROUP_MEMBER
#undef EXPAND_GROUP
#undef EXPAND_GROUP_MEMBER
} config_t;
enum menubar_type_t {