diff --git a/gtk3/config.c b/gtk3/config.c
index 016221c..f9f1b43 100644
--- a/gtk3/config.c
+++ b/gtk3/config.c
@@ -172,7 +172,7 @@ void save_config(GtkWindow *main_window, GDateTime *saved_modification_date) {
GError *error = NULL;
g_message("Trying to save config to %s", config_file_path);
-
+
g_autoptr(GFile) file = g_file_new_for_path(config_file_path);
g_autoptr(GFileInfo) file_info = g_file_query_info(file, "time::*", G_FILE_QUERY_INFO_NONE, NULL, NULL);
@@ -429,7 +429,7 @@ const GB_rumble_mode_t config_get_rumble_mode(void) {
}
// This should not happen
- g_warning("Unknown highpass mode: %s\nFalling back to “Never”", config.controls.rumble_mode);
+ g_warning("Unknown rumble mode: %s\nFalling back to “Never”", config.controls.rumble_mode);
default_value: return GB_RUMBLE_DISABLED;
}
diff --git a/gtk3/config.h b/gtk3/config.h
index c7c158b..850e0b0 100644
--- a/gtk3/config.h
+++ b/gtk3/config.h
@@ -47,11 +47,12 @@
EXPAND_GROUP(audio, \
EXPAND_GROUP_MEMBER(high_pass_filter_id, string, "emulate_hardware") \
EXPAND_GROUP_MEMBER(sample_rate, integer, -1) \
+ EXPAND_GROUP_MEMBER(interference_volume, integer, 0) \
EXPAND_GROUP_MEMBER(muted, boolean, false) \
) \
EXPAND_GROUP(controls, \
EXPAND_GROUP_MEMBER(analog_speed_controls, boolean, false) \
- EXPAND_GROUP_MEMBER(rumble_mode, string, "Never") \
+ EXPAND_GROUP_MEMBER(rumble_mode, string, "never") \
) \
EXPAND_GROUP(window, \
\
diff --git a/gtk3/main.c b/gtk3/main.c
index 9186cbe..6325e35 100644
--- a/gtk3/main.c
+++ b/gtk3/main.c
@@ -87,7 +87,7 @@ static const GActionEntry file_entries[] = {
};
static const GActionEntry edit_entries[] = {
-
+
};
static const GActionEntry emulation_entries[] = {
@@ -252,7 +252,7 @@ static gboolean init_controllers(void) {
if (s->haptic == NULL) {
g_warning("%s", SDL_GetError());
}
-
+
SDL_HapticClose(s->haptic);
s->haptic = NULL;
}
@@ -298,7 +298,7 @@ static gboolean init_audio(void) {
GB_audio_init(gui_data.sample_rate);
GB_set_sample_rate(&gb, GB_audio_get_sample_rate());
-
+
// restore playing state
GB_audio_set_paused(!audio_playing);
@@ -583,12 +583,12 @@ static void handle_events(GB_gameboy_t *gb) {
gui_data.last_used_controller = s;
controller_state |= BUTTON_MASK_A;
}
-
+
if (SDL_GameControllerGetButton(s->controller, SDL_CONTROLLER_BUTTON_B)) {
gui_data.last_used_controller = s;
controller_state |= BUTTON_MASK_B;
}
-
+
if (SDL_GameControllerGetButton(s->controller, SDL_CONTROLLER_BUTTON_BACK)) {
gui_data.last_used_controller = s;
controller_state |= BUTTON_MASK_SELECT;
@@ -698,9 +698,10 @@ static void init(void) {
}
GB_apu_set_sample_callback(&gb, gb_audio_callback);
-
+
GB_set_sample_rate(&gb, GB_audio_get_sample_rate());
GB_set_highpass_filter_mode(&gb, config_get_highpass_mode());
+ GB_set_interference_volume(&gb, (double) config.audio.interference_volume / 255.0);
GB_set_log_callback(&gb, wrapped_console_log);
GB_set_input_callback(&gb, wrapped_console_get_sync_input);
@@ -837,7 +838,7 @@ static gpointer run_thread(gpointer null_ptr) {
char *path = g_file_get_path(gui_data.file);
size_t path_length = strlen(path);
-
+
/* At the worst case, size is strlen(path) + 4 bytes for .sav + NULL */
char battery_save_path[path_length + 5];
char cheats_save_path[path_length + 5];
@@ -915,14 +916,14 @@ static void create_action_groups(GApplication *app) {
static gboolean on_key_press(GtkWidget *w, GdkEventKey *event, gpointer data) {
uint8_t mask;
- if (event->keyval == key_map[INPUT_UP]) mask = BUTTON_MASK_UP;
- if (event->keyval == key_map[INPUT_DOWN]) mask = BUTTON_MASK_DOWN;
- if (event->keyval == key_map[INPUT_LEFT]) mask = BUTTON_MASK_LEFT;
- if (event->keyval == key_map[INPUT_RIGHT]) mask = BUTTON_MASK_RIGHT;
- if (event->keyval == key_map[INPUT_START]) mask = BUTTON_MASK_START;
- if (event->keyval == key_map[INPUT_SELECT]) mask = BUTTON_MASK_SELECT;
- if (event->keyval == key_map[INPUT_A]) mask = BUTTON_MASK_A;
- if (event->keyval == key_map[INPUT_B]) mask = BUTTON_MASK_B;
+ if (event->keyval == key_map[INPUT_UP]) mask = BUTTON_MASK_UP;
+ if (event->keyval == key_map[INPUT_DOWN]) mask = BUTTON_MASK_DOWN;
+ if (event->keyval == key_map[INPUT_LEFT]) mask = BUTTON_MASK_LEFT;
+ if (event->keyval == key_map[INPUT_RIGHT]) mask = BUTTON_MASK_RIGHT;
+ if (event->keyval == key_map[INPUT_START]) mask = BUTTON_MASK_START;
+ if (event->keyval == key_map[INPUT_SELECT]) mask = BUTTON_MASK_SELECT;
+ if (event->keyval == key_map[INPUT_A]) mask = BUTTON_MASK_A;
+ if (event->keyval == key_map[INPUT_B]) mask = BUTTON_MASK_B;
if (event->keyval == key_map[INPUT_REWIND]) {
gui_data.rewind_down = event->type == GDK_KEY_PRESS;
@@ -956,7 +957,7 @@ static gboolean on_key_press(GtkWidget *w, GdkEventKey *event, gpointer data) {
}
}
}
-
+
if (event->type == GDK_KEY_PRESS) {
gui_data.pressed_buttons |= mask;
}
@@ -1120,6 +1121,12 @@ void on_preferences_notify_sample_rate(PreferencesWindow *pref, const guint *sam
init_audio();
}
+void on_preferences_notify_interference_volume(PreferencesWindow *pref, const guint *interference_volume) {
+ if (GB_is_inited(&gb)) {
+ GB_set_interference_volume(&gb, (double) *interference_volume / 255.0);
+ }
+}
+
static void connect_signal_handlers(GApplication *app) {
// Connect signal handlers
gtk_widget_add_events(GTK_WIDGET(gui_data.main_window), GDK_KEY_PRESS_MASK);
@@ -1140,6 +1147,7 @@ static void connect_signal_handlers(GApplication *app) {
g_signal_connect(gui_data.preferences, "pref-update::video-display-border-mode", G_CALLBACK(on_preferences_notify_border), NULL);
g_signal_connect(gui_data.preferences, "pref-update::video-shader", G_CALLBACK(on_preferences_notify_shader), NULL);
g_signal_connect(gui_data.preferences, "pref-update::audio-sample-rate", G_CALLBACK(on_preferences_notify_sample_rate), NULL);
+ g_signal_connect(gui_data.preferences, "pref-update::audio-interference-volume", G_CALLBACK(on_preferences_notify_interference_volume), NULL);
}
// This function gets called when the GApplication gets activated, i.e. it is ready to show widgets.
@@ -1167,7 +1175,7 @@ static void shutdown(GApplication *app, GFile **files, gint n_files, const gchar
stop();
SDL_Quit();
GB_free(&gb);
-
+
g_object_unref(gui_data.builder);
}
@@ -1193,7 +1201,6 @@ static void activate_about(GSimpleAction *action, GVariant *parameter, gpointer
gtk_widget_hide(GTK_WIDGET(dialog));
}
-
// app.preferences GAction
// Opens the preferences window
static void activate_preferences(GSimpleAction *action, GVariant *parameter, gpointer app) {
@@ -1234,7 +1241,7 @@ static void activate_clear_console(GSimpleAction *action, GVariant *parameter, g
static void close_rom(void) {
stop();
GB_free(&gb);
-
+
gb_screen_clear(gui_data.screen);
gb_screen_queue_render(gui_data.screen);
@@ -1244,7 +1251,7 @@ static void close_rom(void) {
// Update menu action states
action_set_enabled(gui_data.main_application, "close", false);
action_entries_set_enabled(emulation_entries, G_N_ELEMENTS(emulation_entries), false);
-
+
// Try force the queued redraws
while (g_main_context_pending(NULL)) {
g_main_context_iteration(NULL, FALSE);
diff --git a/gtk3/preferences_window.c b/gtk3/preferences_window.c
index 72c2725..aa73526 100644
--- a/gtk3/preferences_window.c
+++ b/gtk3/preferences_window.c
@@ -19,6 +19,7 @@ struct _PreferencesWindow {
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;
@@ -206,6 +207,18 @@ static void on_sample_rate_changed(GtkWidget *w, PreferencesWindow *self) {
);
}
+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) clamp_double(0, 255, 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;
@@ -225,6 +238,7 @@ static void preferences_window_realize(GtkWidget *widget) {
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);
@@ -251,6 +265,7 @@ static void preferences_window_class_init(PreferencesWindowClass *class) {
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);
@@ -269,6 +284,7 @@ static void preferences_window_class_init(PreferencesWindowClass *class) {
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);
diff --git a/gtk3/resources/ui/preferences_window.ui b/gtk3/resources/ui/preferences_window.ui
index 9c44bff..c6ed5b6 100644
--- a/gtk3/resources/ui/preferences_window.ui
+++ b/gtk3/resources/ui/preferences_window.ui
@@ -573,6 +573,8 @@ Author: Maximilian Mader
+
+
+
+ False
+ True
+ 4
+
+
+
+
+
+ False
+ True
+ 5
+
+
2
@@ -976,4 +1007,10 @@ Author: Maximilian Mader
+
+
diff --git a/gtk3/resources/ui/window.ui b/gtk3/resources/ui/window.ui
index 23d2d9c..aae98ff 100644
--- a/gtk3/resources/ui/window.ui
+++ b/gtk3/resources/ui/window.ui
@@ -37,7 +37,7 @@ Author: Maximilian Mader
False
normal
SameBoy
- Copyright © 2015-2019 Lior Halphon
+ Copyright © 2015-2021 Lior Halphon
https://sameboy.github.io
sameboy.github.io
Lior Halphon https://github.com/LIJI32
diff --git a/gtk3/util.c b/gtk3/util.c
index 00b1b56..76f75e7 100644
--- a/gtk3/util.c
+++ b/gtk3/util.c
@@ -103,7 +103,7 @@ GB_model_t config_get_model_type(GuiData *gui_data) {
GtkWidget *menubar_to_menu(GtkMenuBar *menubar) {
GtkWidget *menu = gtk_menu_new();
g_autoptr(GList) iter = gtk_container_get_children(GTK_CONTAINER(menubar));
-
+
while (iter) {
GtkWidget *item = GTK_WIDGET(iter->data);
gtk_widget_reparent(item, menu);
@@ -157,3 +157,12 @@ gboolean scroll_to_bottom(GtkTextView *textview, GtkTextMark *mark) {
return true;
}
+
+gchar* format_scale_value_pct(GtkScale *scale, gdouble value) {
+ GtkAdjustment *adj = gtk_range_get_adjustment(GTK_RANGE(scale));
+ gdouble lower = gtk_adjustment_get_lower(adj);
+ gdouble upper = gtk_adjustment_get_upper(adj);
+ gdouble range = fabs(upper - lower);
+ gdouble pct = (value / range) * 100.0;
+ return g_strdup_printf ("%.1f%% ", pct);
+}
diff --git a/gtk3/util.h b/gtk3/util.h
index 40f3d64..9050160 100644
--- a/gtk3/util.h
+++ b/gtk3/util.h
@@ -27,4 +27,6 @@ void set_combo_box_row_separator_func(GtkContainer *container);
gboolean scroll_to_bottom(GtkTextView *textview, GtkTextMark *mark);
+gchar* format_scale_value_pct(GtkScale *scale, gdouble value);
+
#endif
\ No newline at end of file