366 lines
16 KiB
C
366 lines
16 KiB
C
#include "preferences_window.h"
|
|
#include "../config.h"
|
|
#include "../util.h"
|
|
|
|
struct _PreferencesWindow {
|
|
GtkWindowClass parent_class;
|
|
|
|
GtkComboBoxText *boot_rom_selector;
|
|
GtkComboBoxText *rewind_duration_selector;
|
|
GtkComboBox *dmg_revision_selector;
|
|
GtkComboBoxText *sgb_revision_selector;
|
|
GtkComboBox *cgb_revision_selector;
|
|
GtkComboBoxText *shader_selector;
|
|
GtkComboBoxText *color_correction_selector;
|
|
GtkScale *light_temperature_slider;
|
|
GtkComboBoxText *frame_blending_selector;
|
|
GtkComboBoxText *monochrome_palette_selector;
|
|
GtkComboBoxText *display_border_selector;
|
|
GtkCheckButton *integer_scaling_toggle;
|
|
GtkCheckButton *aspect_ratio_toggle;
|
|
GtkComboBoxText *highpass_filter_selector;
|
|
GtkComboBoxText *sample_rate_selector;
|
|
GtkScale *interference_volume_slider;
|
|
GtkCheckButton *analog_speed_controls_toggle;
|
|
GtkComboBoxText *rumble_mode_selector;
|
|
GtkButton *configure_joypad_skip;
|
|
|
|
GB_gameboy_t *gb;
|
|
};
|
|
|
|
G_DEFINE_TYPE(PreferencesWindow, preferences_window, GTK_TYPE_WINDOW);
|
|
|
|
typedef enum {
|
|
PROP_GB_PTR = 1,
|
|
|
|
N_PROPERTIES
|
|
} PreferencesWindowProperty;
|
|
|
|
static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, };
|
|
|
|
typedef enum {
|
|
PREF_UPDATE,
|
|
N_SIGNALS
|
|
} PreferencesWindowSignals;
|
|
|
|
static guint preferences_signals[N_SIGNALS] = { 0, };
|
|
|
|
static void preferences_window_set_property(GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) {
|
|
PreferencesWindow *self = (PreferencesWindow *) object;
|
|
|
|
switch ((PreferencesWindowProperty) property_id) {
|
|
case PROP_GB_PTR: self->gb = g_value_get_pointer(value); break;
|
|
default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
|
|
}
|
|
}
|
|
|
|
static void preferences_window_get_property(GObject *object, guint property_id, GValue *value, GParamSpec *pspec) {
|
|
PreferencesWindow *self = (PreferencesWindow *) object;
|
|
|
|
switch ((PreferencesWindowProperty) property_id) {
|
|
case PROP_GB_PTR: g_value_set_pointer(value, self->gb); break;
|
|
default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
|
|
}
|
|
}
|
|
|
|
static void preferences_window_init(PreferencesWindow *self) {
|
|
gtk_widget_init_template(GTK_WIDGET(self));
|
|
|
|
// Add a couple of "snapping points" to the sliders
|
|
gtk_scale_add_mark(self->light_temperature_slider, 0.0, GTK_POS_BOTTOM, NULL);
|
|
|
|
for (unsigned i = 1; i < 10; i++) {
|
|
gtk_scale_add_mark(self->interference_volume_slider, ((double) i / 10.0) * 100.0, GTK_POS_BOTTOM, NULL);
|
|
}
|
|
|
|
preferences_window_update_boot_rom_selector(self);
|
|
}
|
|
|
|
static void on_boot_rom_location_changed(GtkWidget *w, PreferencesWindow *self) {
|
|
GtkComboBox *box = GTK_COMBO_BOX(w);
|
|
const gchar *id = gtk_combo_box_get_active_id(box);
|
|
if (id == NULL) return;
|
|
|
|
if (g_strcmp0(id, "other") == 0) {
|
|
GtkFileChooserNative *native = gtk_file_chooser_native_new("Select Folder", GTK_WINDOW(self), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, "_Select", "_Cancel");
|
|
gint res = gtk_native_dialog_run(GTK_NATIVE_DIALOG(native));
|
|
|
|
if (res == GTK_RESPONSE_ACCEPT) {
|
|
config.emulation.boot_rom_path = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(native));
|
|
preferences_window_update_boot_rom_selector(self);
|
|
}
|
|
|
|
g_object_unref(native);
|
|
}
|
|
else {
|
|
config.emulation.boot_rom_path = (gchar *)id;
|
|
}
|
|
}
|
|
|
|
static void on_cgb_model_changed(GtkWidget *w, PreferencesWindow *self) {
|
|
GtkComboBox *box = GTK_COMBO_BOX(w);
|
|
config.emulation.cgb_revision_name = (gchar *)gtk_combo_box_get_active_id(box);
|
|
}
|
|
|
|
static void on_frame_blending_changed(GtkWidget *w, PreferencesWindow *self) {
|
|
GtkComboBox *box = GTK_COMBO_BOX(w);
|
|
config.video.frame_blending_mode = (gchar *)gtk_combo_box_get_active_id(box);
|
|
}
|
|
|
|
static void on_dmg_model_changed(GtkWidget *w, PreferencesWindow *self) {
|
|
GtkComboBox *box = GTK_COMBO_BOX(w);
|
|
config.emulation.dmg_revision_name = (gchar *)gtk_combo_box_get_active_id(box);
|
|
}
|
|
|
|
static void on_keep_aspect_ratio_changed(GtkWidget *w, PreferencesWindow *self) {
|
|
GtkCheckButton *button = GTK_CHECK_BUTTON(w);
|
|
gboolean value = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button));
|
|
config.video.keep_aspect_ratio = value;
|
|
}
|
|
|
|
static void on_sgb_model_changed(GtkWidget *w, PreferencesWindow *self) {
|
|
GtkComboBox *box = GTK_COMBO_BOX(w);
|
|
config.emulation.sgb_revision_name = (gchar *)gtk_combo_box_get_active_id(box);
|
|
}
|
|
|
|
static void on_use_integer_scaling_changed(GtkWidget *w, PreferencesWindow *self) {
|
|
GtkCheckButton *button = GTK_CHECK_BUTTON(w);
|
|
gboolean value = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button));
|
|
config.video.use_integer_scaling = value;
|
|
}
|
|
|
|
static void on_analog_speed_controls_changed(GtkWidget *w, PreferencesWindow *self) {
|
|
GtkCheckButton *button = GTK_CHECK_BUTTON(w);
|
|
gboolean value = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button));
|
|
config.controls.analog_speed_controls = value;
|
|
}
|
|
|
|
static void on_color_correction_changed(GtkWidget *w, PreferencesWindow *self) {
|
|
GtkComboBox *box = GTK_COMBO_BOX(w);
|
|
config.video.color_correction_id = (gchar *)gtk_combo_box_get_active_id(box);
|
|
|
|
if (self->gb) {
|
|
GB_set_color_correction_mode(self->gb, config_get_color_correction_mode());
|
|
}
|
|
}
|
|
|
|
static void on_light_temperature_changed(GtkWidget *w, PreferencesWindow *self) {
|
|
GtkRange *range = GTK_RANGE(w);
|
|
gdouble value = gtk_range_get_value(range);
|
|
config.video.light_temperature = (guint32) value;
|
|
|
|
g_signal_emit(
|
|
self,
|
|
preferences_signals[PREF_UPDATE],
|
|
g_quark_from_static_string("video-color-temperature"),
|
|
&config.video.light_temperature
|
|
);
|
|
}
|
|
|
|
static void on_monochrome_palette_changed(GtkWidget *w, PreferencesWindow *self) {
|
|
GtkComboBox *box = GTK_COMBO_BOX(w);
|
|
config.video.monochrome_palette_id = (gchar *)gtk_combo_box_get_active_id(box);
|
|
|
|
if (self->gb) {
|
|
GB_set_palette(self->gb, config_get_monochrome_palette());
|
|
}
|
|
}
|
|
|
|
static void on_highpass_filter_changed(GtkWidget *w, PreferencesWindow *self) {
|
|
config.audio.high_pass_filter_id = (gchar *)gtk_combo_box_get_active_id(GTK_COMBO_BOX(w));
|
|
|
|
if (self->gb) {
|
|
GB_set_highpass_filter_mode(self->gb, config_get_highpass_mode());
|
|
}
|
|
}
|
|
|
|
static void on_rewind_duration_changed(GtkWidget *w, PreferencesWindow *self) {
|
|
GtkComboBox *box = GTK_COMBO_BOX(w);
|
|
config.emulation.rewind_duration = g_ascii_strtoll(gtk_combo_box_get_active_id(box), NULL, 10);
|
|
|
|
if (self->gb) {
|
|
GB_set_rewind_length(self->gb, config.emulation.rewind_duration);
|
|
}
|
|
}
|
|
|
|
static void on_rumble_mode_changed(GtkWidget *w, PreferencesWindow *self) {
|
|
GtkComboBox *box = GTK_COMBO_BOX(w);
|
|
config.controls.rumble_mode = (gchar *)gtk_combo_box_get_active_id(box);
|
|
|
|
if (self->gb) {
|
|
GB_set_rumble_mode(self->gb, config_get_rumble_mode());
|
|
}
|
|
}
|
|
|
|
static void on_display_border_changed(GtkWidget *w, PreferencesWindow *self) {
|
|
GtkComboBox *box = GTK_COMBO_BOX(w);
|
|
config.video.display_border_mode = (gchar *)gtk_combo_box_get_active_id(box);
|
|
|
|
g_signal_emit(
|
|
self,
|
|
preferences_signals[PREF_UPDATE],
|
|
g_quark_from_static_string("video-display-border-mode"),
|
|
config.video.display_border_mode
|
|
);
|
|
}
|
|
|
|
static void on_graphic_filter_changed(GtkWidget *w, PreferencesWindow *self) {
|
|
GtkComboBox *box = GTK_COMBO_BOX(w);
|
|
config.video.shader = (gchar *)gtk_combo_box_get_active_id(box);
|
|
|
|
g_signal_emit(
|
|
self,
|
|
preferences_signals[PREF_UPDATE],
|
|
g_quark_from_static_string("video-shader"),
|
|
config.video.shader
|
|
);
|
|
}
|
|
|
|
static void on_sample_rate_changed(GtkWidget *w, PreferencesWindow *self) {
|
|
GtkComboBox *box = GTK_COMBO_BOX(w);
|
|
config.audio.sample_rate = g_ascii_strtoll(gtk_combo_box_get_active_id(box), NULL, 10);
|
|
|
|
g_signal_emit(
|
|
self,
|
|
preferences_signals[PREF_UPDATE],
|
|
g_quark_from_static_string("audio-sample-rate"),
|
|
&config.audio.sample_rate
|
|
);
|
|
}
|
|
|
|
static void on_interference_volume_changed(GtkWidget *w, PreferencesWindow *self) {
|
|
GtkRange *range = GTK_RANGE(w);
|
|
gdouble value = gtk_range_get_value(range);
|
|
config.audio.interference_volume = (guint32) value;
|
|
|
|
g_signal_emit(
|
|
self,
|
|
preferences_signals[PREF_UPDATE],
|
|
g_quark_from_static_string("audio-interference-volume"),
|
|
&config.audio.interference_volume
|
|
);
|
|
}
|
|
|
|
static void preferences_window_realize(GtkWidget *widget) {
|
|
PreferencesWindow *self = (PreferencesWindow *)widget;
|
|
|
|
gtk_combo_box_set_active_id(GTK_COMBO_BOX(self->rewind_duration_selector), g_strdup_printf("%i", config.emulation.rewind_duration));
|
|
gtk_combo_box_set_active_id(GTK_COMBO_BOX(self->dmg_revision_selector), config.emulation.dmg_revision_name);
|
|
gtk_combo_box_set_active_id(GTK_COMBO_BOX(self->sgb_revision_selector), config.emulation.sgb_revision_name);
|
|
gtk_combo_box_set_active_id(GTK_COMBO_BOX(self->cgb_revision_selector), config.emulation.cgb_revision_name);
|
|
|
|
gtk_combo_box_set_active_id(GTK_COMBO_BOX(self->shader_selector), config.video.shader);
|
|
gtk_combo_box_set_active_id(GTK_COMBO_BOX(self->color_correction_selector), config.video.color_correction_id);
|
|
gtk_range_set_value(GTK_RANGE(self->light_temperature_slider), (double) config.video.light_temperature);
|
|
gtk_combo_box_set_active_id(GTK_COMBO_BOX(self->frame_blending_selector), config.video.frame_blending_mode);
|
|
gtk_combo_box_set_active_id(GTK_COMBO_BOX(self->display_border_selector), config.video.display_border_mode);
|
|
gtk_combo_box_set_active_id(GTK_COMBO_BOX(self->monochrome_palette_selector), config.video.monochrome_palette_id);
|
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(self->integer_scaling_toggle), config.video.use_integer_scaling);
|
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(self->aspect_ratio_toggle), config.video.keep_aspect_ratio);
|
|
|
|
gtk_combo_box_set_active_id(GTK_COMBO_BOX(self->highpass_filter_selector), config.audio.high_pass_filter_id);
|
|
gtk_combo_box_set_active_id(GTK_COMBO_BOX(self->sample_rate_selector), g_strdup_printf("%i", config.audio.sample_rate));
|
|
gtk_range_set_value(GTK_RANGE(self->interference_volume_slider), (double) config.audio.interference_volume);
|
|
|
|
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(self->analog_speed_controls_toggle), config.controls.analog_speed_controls);
|
|
gtk_combo_box_set_active_id(GTK_COMBO_BOX(self->rumble_mode_selector), config.controls.rumble_mode);
|
|
|
|
set_combo_box_row_separator_func(GTK_CONTAINER(self));
|
|
|
|
GTK_WIDGET_CLASS(preferences_window_parent_class)->realize(widget);
|
|
}
|
|
|
|
static void preferences_window_class_init(PreferencesWindowClass *class) {
|
|
gtk_widget_class_set_template_from_resource(GTK_WIDGET_CLASS(class), RESOURCE_PREFIX "ui/preferences_window.ui");
|
|
|
|
gtk_widget_class_bind_template_child(GTK_WIDGET_CLASS(class), PreferencesWindow, boot_rom_selector);
|
|
gtk_widget_class_bind_template_child(GTK_WIDGET_CLASS(class), PreferencesWindow, rewind_duration_selector);
|
|
gtk_widget_class_bind_template_child(GTK_WIDGET_CLASS(class), PreferencesWindow, dmg_revision_selector);
|
|
gtk_widget_class_bind_template_child(GTK_WIDGET_CLASS(class), PreferencesWindow, sgb_revision_selector);
|
|
gtk_widget_class_bind_template_child(GTK_WIDGET_CLASS(class), PreferencesWindow, cgb_revision_selector);
|
|
gtk_widget_class_bind_template_child(GTK_WIDGET_CLASS(class), PreferencesWindow, shader_selector);
|
|
gtk_widget_class_bind_template_child(GTK_WIDGET_CLASS(class), PreferencesWindow, color_correction_selector);
|
|
gtk_widget_class_bind_template_child(GTK_WIDGET_CLASS(class), PreferencesWindow, light_temperature_slider);
|
|
gtk_widget_class_bind_template_child(GTK_WIDGET_CLASS(class), PreferencesWindow, frame_blending_selector);
|
|
gtk_widget_class_bind_template_child(GTK_WIDGET_CLASS(class), PreferencesWindow, monochrome_palette_selector);
|
|
gtk_widget_class_bind_template_child(GTK_WIDGET_CLASS(class), PreferencesWindow, display_border_selector);
|
|
gtk_widget_class_bind_template_child(GTK_WIDGET_CLASS(class), PreferencesWindow, integer_scaling_toggle);
|
|
gtk_widget_class_bind_template_child(GTK_WIDGET_CLASS(class), PreferencesWindow, aspect_ratio_toggle);
|
|
gtk_widget_class_bind_template_child(GTK_WIDGET_CLASS(class), PreferencesWindow, highpass_filter_selector);
|
|
gtk_widget_class_bind_template_child(GTK_WIDGET_CLASS(class), PreferencesWindow, sample_rate_selector);
|
|
gtk_widget_class_bind_template_child(GTK_WIDGET_CLASS(class), PreferencesWindow, interference_volume_slider);
|
|
gtk_widget_class_bind_template_child(GTK_WIDGET_CLASS(class), PreferencesWindow, analog_speed_controls_toggle);
|
|
gtk_widget_class_bind_template_child(GTK_WIDGET_CLASS(class), PreferencesWindow, rumble_mode_selector);
|
|
gtk_widget_class_bind_template_child(GTK_WIDGET_CLASS(class), PreferencesWindow, configure_joypad_skip);
|
|
|
|
gtk_widget_class_bind_template_callback(GTK_WIDGET_CLASS(class), on_boot_rom_location_changed);
|
|
gtk_widget_class_bind_template_callback(GTK_WIDGET_CLASS(class), on_rewind_duration_changed);
|
|
gtk_widget_class_bind_template_callback(GTK_WIDGET_CLASS(class), on_dmg_model_changed);
|
|
gtk_widget_class_bind_template_callback(GTK_WIDGET_CLASS(class), on_sgb_model_changed);
|
|
gtk_widget_class_bind_template_callback(GTK_WIDGET_CLASS(class), on_cgb_model_changed);
|
|
gtk_widget_class_bind_template_callback(GTK_WIDGET_CLASS(class), on_graphic_filter_changed);
|
|
gtk_widget_class_bind_template_callback(GTK_WIDGET_CLASS(class), on_color_correction_changed);
|
|
gtk_widget_class_bind_template_callback(GTK_WIDGET_CLASS(class), on_light_temperature_changed);
|
|
gtk_widget_class_bind_template_callback(GTK_WIDGET_CLASS(class), on_frame_blending_changed);
|
|
gtk_widget_class_bind_template_callback(GTK_WIDGET_CLASS(class), on_monochrome_palette_changed);
|
|
gtk_widget_class_bind_template_callback(GTK_WIDGET_CLASS(class), on_display_border_changed);
|
|
gtk_widget_class_bind_template_callback(GTK_WIDGET_CLASS(class), on_use_integer_scaling_changed);
|
|
gtk_widget_class_bind_template_callback(GTK_WIDGET_CLASS(class), on_keep_aspect_ratio_changed);
|
|
gtk_widget_class_bind_template_callback(GTK_WIDGET_CLASS(class), on_highpass_filter_changed);
|
|
gtk_widget_class_bind_template_callback(GTK_WIDGET_CLASS(class), on_sample_rate_changed);
|
|
gtk_widget_class_bind_template_callback(GTK_WIDGET_CLASS(class), on_interference_volume_changed);
|
|
gtk_widget_class_bind_template_callback(GTK_WIDGET_CLASS(class), on_analog_speed_controls_changed);
|
|
gtk_widget_class_bind_template_callback(GTK_WIDGET_CLASS(class), on_rumble_mode_changed);
|
|
|
|
// gtk_widget_class_bind_template_callback(GTK_WIDGET_CLASS(class), do_refresh_joypad_menu);
|
|
// gtk_widget_class_bind_template_callback(GTK_WIDGET_CLASS(class), on_default_joypad_changed);
|
|
// gtk_widget_class_bind_template_callback(GTK_WIDGET_CLASS(class), do_configure_joypad);
|
|
// gtk_widget_class_bind_template_callback(GTK_WIDGET_CLASS(class), do_skip_configure_joypad);
|
|
|
|
GTK_WIDGET_CLASS(class)->realize = preferences_window_realize;
|
|
|
|
obj_properties[PROP_GB_PTR] = g_param_spec_pointer(
|
|
"gb", "SameBoy core pointer", "SameBoy Core pointer (GB_gameboy_t)",
|
|
G_PARAM_CONSTRUCT | G_PARAM_READWRITE
|
|
);
|
|
|
|
G_OBJECT_CLASS(class)->set_property = preferences_window_set_property;
|
|
G_OBJECT_CLASS(class)->get_property = preferences_window_get_property;
|
|
|
|
g_object_class_install_properties(G_OBJECT_CLASS(class), N_PROPERTIES, obj_properties);
|
|
|
|
preferences_signals[PREF_UPDATE] = g_signal_new(
|
|
"pref-update", // signal name
|
|
G_TYPE_FROM_CLASS(G_OBJECT_CLASS(class)), // itype
|
|
G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE | G_SIGNAL_DETAILED, // signal_flags
|
|
0, // class_offset
|
|
NULL, // accumulator
|
|
NULL, // accumulator_data
|
|
NULL, // c_marshaller,
|
|
G_TYPE_NONE, // return_type
|
|
1, // n_params,
|
|
G_TYPE_POINTER
|
|
);
|
|
}
|
|
|
|
PreferencesWindow *preferences_window_new(GB_gameboy_t *gb) {
|
|
return g_object_new(PREFERENCES_WINDOW_TYPE, "gb", gb, NULL);
|
|
}
|
|
|
|
void preferences_window_update_boot_rom_selector(PreferencesWindow *self) {
|
|
GtkComboBoxText *combo_box = self->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.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");
|
|
}
|
|
|
|
gtk_combo_box_text_append_text(combo_box, "<separator>");
|
|
gtk_combo_box_text_append(combo_box, "other", "Other");
|
|
}
|