diff --git a/SDL/audio.c b/SDL/audio.c index 1627189..f9a49a7 100644 --- a/SDL/audio.c +++ b/SDL/audio.c @@ -2,6 +2,7 @@ #include #include #include "audio/audio.h" +#include "configuration.h" #define unlikely(x) __builtin_expect((bool)(x), 0) @@ -17,6 +18,18 @@ bool GB_audio_init(void) GB_AUDIO_DRIVER_REF(SDL), }; + // First try the preferred driver + for (unsigned i = 0; i < sizeof(drivers) / sizeof(drivers[0]); i++) { + driver = drivers[i]; + if (strcmp(driver->name, configuration.audio_driver) != 0) { + continue; + } + if (driver->audio_init()) { + return true; + } + } + + // Else go by priority for (unsigned i = 0; i < sizeof(drivers) / sizeof(drivers[0]); i++) { driver = drivers[i]; if (driver->audio_init()) { @@ -69,3 +82,18 @@ const char *GB_audio_driver_name(void) if (unlikely(!driver)) return "None"; return driver->name; } + +const char *GB_audio_driver_name_at_index(unsigned index) +{ + const GB_audio_driver_t *drivers[] = { +#ifdef _WIN32 + GB_AUDIO_DRIVER_REF(XAudio2), + GB_AUDIO_DRIVER_REF(XAudio2_7), +#endif + GB_AUDIO_DRIVER_REF(SDL), + }; + if (index >= sizeof(drivers) / sizeof(drivers[0])) { + return ""; + } + return drivers[index]->name; +} diff --git a/SDL/audio/audio.h b/SDL/audio/audio.h index d743c32..1b2fa71 100644 --- a/SDL/audio/audio.h +++ b/SDL/audio/audio.h @@ -13,6 +13,7 @@ size_t GB_audio_get_queue_length(void); void GB_audio_queue_sample(GB_sample_t *sample); bool GB_audio_init(void); const char *GB_audio_driver_name(void); +const char *GB_audio_driver_name_at_index(unsigned index); typedef struct { typeof(GB_audio_is_playing) *audio_is_playing; diff --git a/SDL/configuration.c b/SDL/configuration.c new file mode 100644 index 0000000..bde42eb --- /dev/null +++ b/SDL/configuration.c @@ -0,0 +1,49 @@ +#include "configuration.h" + +configuration_t configuration = +{ + .keys = { + SDL_SCANCODE_RIGHT, + SDL_SCANCODE_LEFT, + SDL_SCANCODE_UP, + SDL_SCANCODE_DOWN, + SDL_SCANCODE_X, + SDL_SCANCODE_Z, + SDL_SCANCODE_BACKSPACE, + SDL_SCANCODE_RETURN, + SDL_SCANCODE_SPACE + }, + .keys_2 = { + SDL_SCANCODE_TAB, + SDL_SCANCODE_LSHIFT, + }, + .joypad_configuration = { + 13, + 14, + 11, + 12, + 0, + 1, + 9, + 8, + 10, + 4, + -1, + 5, + }, + .joypad_axises = { + 0, + 1, + }, + .color_correction_mode = GB_COLOR_CORRECTION_EMULATE_HARDWARE, + .highpass_mode = GB_HIGHPASS_ACCURATE, + .scaling_mode = GB_SDL_SCALING_INTEGER_FACTOR, + .blending_mode = GB_FRAME_BLENDING_MODE_ACCURATE, + .rewind_length = 60 * 2, + .model = MODEL_CGB, + .volume = 100, + .rumble_mode = GB_RUMBLE_ALL_GAMES, + .default_scale = 2, + .color_temperature = 10, + .cgb_revision = GB_MODEL_CGB_E - GB_MODEL_CGB_0, +}; diff --git a/SDL/configuration.h b/SDL/configuration.h new file mode 100644 index 0000000..b3ac934 --- /dev/null +++ b/SDL/configuration.h @@ -0,0 +1,103 @@ +#ifndef configuration_h +#define configuration_h + +#include +#include +#include "shader.h" + +enum scaling_mode { + GB_SDL_SCALING_ENTIRE_WINDOW, + GB_SDL_SCALING_KEEP_RATIO, + GB_SDL_SCALING_INTEGER_FACTOR, + GB_SDL_SCALING_MAX, +}; + +typedef enum { + JOYPAD_BUTTON_RIGHT, + JOYPAD_BUTTON_LEFT, + JOYPAD_BUTTON_UP, + JOYPAD_BUTTON_DOWN, + JOYPAD_BUTTON_A, + JOYPAD_BUTTON_B, + JOYPAD_BUTTON_SELECT, + JOYPAD_BUTTON_START, + JOYPAD_BUTTON_MENU, + JOYPAD_BUTTON_TURBO, + JOYPAD_BUTTON_REWIND, + JOYPAD_BUTTON_SLOW_MOTION, + JOYPAD_BUTTONS_MAX +} joypad_button_t; + +typedef enum { + JOYPAD_AXISES_X, + JOYPAD_AXISES_Y, + JOYPAD_AXISES_MAX +} joypad_axis_t; + +typedef struct { + SDL_Scancode keys[9]; + GB_color_correction_mode_t color_correction_mode; + enum scaling_mode scaling_mode; + uint8_t blending_mode; + + GB_highpass_mode_t highpass_mode; + + bool _deprecated_div_joystick; + bool _deprecated_flip_joystick_bit_1; + bool _deprecated_swap_joysticks_bits_1_and_2; + + char filter[32]; + enum { + MODEL_DMG, + MODEL_CGB, + MODEL_AGB, + MODEL_SGB, + MODEL_MGB, + MODEL_MAX, + } model; + + /* v0.11 */ + uint32_t rewind_length; + SDL_Scancode keys_2[32]; /* Rewind and underclock, + padding for the future */ + uint8_t joypad_configuration[32]; /* 12 Keys + padding for the future*/; + uint8_t joypad_axises[JOYPAD_AXISES_MAX]; + + /* v0.12 */ + enum { + SGB_NTSC, + SGB_PAL, + SGB_2, + SGB_MAX + } sgb_revision; + + /* v0.13 */ + uint8_t dmg_palette; + GB_border_mode_t border_mode; + uint8_t volume; + GB_rumble_mode_t rumble_mode; + + uint8_t default_scale; + + /* v0.14 */ + unsigned padding; + uint8_t color_temperature; + char bootrom_path[4096]; + uint8_t interference_volume; + GB_rtc_mode_t rtc_mode; + + /* v0.14.4 */ + bool osd; + + struct __attribute__((packed, aligned(4))) { + + /* v0.15 */ + bool allow_mouse_controls; + uint8_t cgb_revision; + /* v0.15.1 */ + char audio_driver[16]; + }; +} configuration_t; + +extern configuration_t configuration; + +#endif diff --git a/SDL/gui.c b/SDL/gui.c index ae1c6e9..b513d21 100644 --- a/SDL/gui.c +++ b/SDL/gui.c @@ -68,55 +68,6 @@ void render_texture(void *pixels, void *previous) } } -configuration_t configuration = -{ - .keys = { - SDL_SCANCODE_RIGHT, - SDL_SCANCODE_LEFT, - SDL_SCANCODE_UP, - SDL_SCANCODE_DOWN, - SDL_SCANCODE_X, - SDL_SCANCODE_Z, - SDL_SCANCODE_BACKSPACE, - SDL_SCANCODE_RETURN, - SDL_SCANCODE_SPACE - }, - .keys_2 = { - SDL_SCANCODE_TAB, - SDL_SCANCODE_LSHIFT, - }, - .joypad_configuration = { - 13, - 14, - 11, - 12, - 0, - 1, - 9, - 8, - 10, - 4, - -1, - 5, - }, - .joypad_axises = { - 0, - 1, - }, - .color_correction_mode = GB_COLOR_CORRECTION_EMULATE_HARDWARE, - .highpass_mode = GB_HIGHPASS_ACCURATE, - .scaling_mode = GB_SDL_SCALING_INTEGER_FACTOR, - .blending_mode = GB_FRAME_BLENDING_MODE_ACCURATE, - .rewind_length = 60 * 2, - .model = MODEL_CGB, - .volume = 100, - .rumble_mode = GB_RUMBLE_ALL_GAMES, - .default_scale = 2, - .color_temperature = 10, - .cgb_revision = GB_MODEL_CGB_E - GB_MODEL_CGB_0, -}; - - static const char *help[] = { "Drop a ROM to play.\n" "\n" @@ -961,17 +912,86 @@ static const char *audio_driver_string(unsigned index) return GB_audio_driver_name(); } +static const char *preferred_audio_driver_string(unsigned index) +{ + if (configuration.audio_driver[0] == 0) { + return "Auto"; + } + return configuration.audio_driver; +} + +static void audio_driver_changed(void); + +static void cycle_prefrered_audio_driver(unsigned index) +{ + audio_driver_changed(); + if (configuration.audio_driver[0] == 0) { + strcpy(configuration.audio_driver, GB_audio_driver_name_at_index(0)); + return; + } + unsigned i = 0; + while (true) { + const char *name = GB_audio_driver_name_at_index(i); + if (name[0] == 0) { // Not a supported driver? Switch to auto + configuration.audio_driver[0] = 0; + return; + } + if (strcmp(configuration.audio_driver, name) == 0) { + strcpy(configuration.audio_driver, GB_audio_driver_name_at_index(i + 1)); + return; + } + i++; + } +} + +static void cycle_preferred_audio_driver_backwards(unsigned index) +{ + audio_driver_changed(); + if (configuration.audio_driver[0] == 0) { + unsigned i = 0; + while (true) { + const char *name = GB_audio_driver_name_at_index(i); + if (name[0] == 0) { + strcpy(configuration.audio_driver, GB_audio_driver_name_at_index(i - 1)); + return; + } + i++; + } + return; + } + unsigned i = 0; + while (true) { + const char *name = GB_audio_driver_name_at_index(i); + if (name[0] == 0) { // Not a supported driver? Switch to auto + configuration.audio_driver[0] = 0; + return; + } + if (strcmp(configuration.audio_driver, name) == 0) { + strcpy(configuration.audio_driver, GB_audio_driver_name_at_index(i - 1)); + return; + } + i++; + } +} + static void nop(unsigned index){} -static const struct menu_item audio_menu[] = { +static struct menu_item audio_menu[] = { {"Highpass Filter:", cycle_highpass_filter, highpass_filter_string, cycle_highpass_filter_backwards}, {"Volume:", increase_volume, volume_string, decrease_volume}, {"Interference Volume:", increase_interference_volume, interference_volume_string, decrease_interference_volume}, - {"Audio Driver:", nop, audio_driver_string}, + {"Preferred Audio Driver:", cycle_prefrered_audio_driver, preferred_audio_driver_string, cycle_preferred_audio_driver_backwards}, + {"Active Driver:", nop, audio_driver_string}, {"Back", return_to_root_menu}, {NULL,} }; +static void audio_driver_changed(void) +{ + audio_menu[4].value_getter = NULL; + audio_menu[4].string = "Relaunch to apply"; +} + static void enter_audio_menu(unsigned index) { current_menu = audio_menu; diff --git a/SDL/gui.h b/SDL/gui.h index cc34733..f23ebd8 100644 --- a/SDL/gui.h +++ b/SDL/gui.h @@ -5,6 +5,7 @@ #include #include #include "shader.h" +#include "configuration.h" #define JOYSTICK_HIGH 0x4000 #define JOYSTICK_LOW 0x3800 @@ -24,14 +25,6 @@ extern SDL_PixelFormat *pixel_format; extern SDL_Haptic *haptic; extern shader_t shader; -enum scaling_mode { - GB_SDL_SCALING_ENTIRE_WINDOW, - GB_SDL_SCALING_KEEP_RATIO, - GB_SDL_SCALING_INTEGER_FACTOR, - GB_SDL_SCALING_MAX, -}; - - enum pending_command { GB_SDL_NO_COMMAND, GB_SDL_SAVE_STATE_COMMAND, @@ -48,93 +41,6 @@ extern enum pending_command pending_command; extern unsigned command_parameter; extern char *dropped_state_file; -typedef enum { - JOYPAD_BUTTON_RIGHT, - JOYPAD_BUTTON_LEFT, - JOYPAD_BUTTON_UP, - JOYPAD_BUTTON_DOWN, - JOYPAD_BUTTON_A, - JOYPAD_BUTTON_B, - JOYPAD_BUTTON_SELECT, - JOYPAD_BUTTON_START, - JOYPAD_BUTTON_MENU, - JOYPAD_BUTTON_TURBO, - JOYPAD_BUTTON_REWIND, - JOYPAD_BUTTON_SLOW_MOTION, - JOYPAD_BUTTONS_MAX -} joypad_button_t; - -typedef enum { - JOYPAD_AXISES_X, - JOYPAD_AXISES_Y, - JOYPAD_AXISES_MAX -} joypad_axis_t; - -typedef struct { - SDL_Scancode keys[9]; - GB_color_correction_mode_t color_correction_mode; - enum scaling_mode scaling_mode; - uint8_t blending_mode; - - GB_highpass_mode_t highpass_mode; - - bool _deprecated_div_joystick; - bool _deprecated_flip_joystick_bit_1; - bool _deprecated_swap_joysticks_bits_1_and_2; - - char filter[32]; - enum { - MODEL_DMG, - MODEL_CGB, - MODEL_AGB, - MODEL_SGB, - MODEL_MGB, - MODEL_MAX, - } model; - - /* v0.11 */ - uint32_t rewind_length; - SDL_Scancode keys_2[32]; /* Rewind and underclock, + padding for the future */ - uint8_t joypad_configuration[32]; /* 12 Keys + padding for the future*/; - uint8_t joypad_axises[JOYPAD_AXISES_MAX]; - - /* v0.12 */ - enum { - SGB_NTSC, - SGB_PAL, - SGB_2, - SGB_MAX - } sgb_revision; - - /* v0.13 */ - uint8_t dmg_palette; - GB_border_mode_t border_mode; - uint8_t volume; - GB_rumble_mode_t rumble_mode; - - uint8_t default_scale; - - /* v0.14 */ - unsigned padding; - uint8_t color_temperature; - char bootrom_path[4096]; - uint8_t interference_volume; - GB_rtc_mode_t rtc_mode; - - /* v0.14.4 */ - bool osd; - - struct __attribute__((packed, aligned(4))) { - - /* v0.15 */ - bool allow_mouse_controls; - uint8_t cgb_revision; - - }; -} configuration_t; - -extern configuration_t configuration; - void update_viewport(void); void run_gui(bool is_running); void render_texture(void *pixels, void *previous); diff --git a/SDL/main.c b/SDL/main.c index 686dcb4..51b1f69 100644 --- a/SDL/main.c +++ b/SDL/main.c @@ -870,6 +870,7 @@ int main(int argc, char **argv) configuration.color_temperature %= 21; configuration.bootrom_path[sizeof(configuration.bootrom_path) - 1] = 0; configuration.cgb_revision %= GB_MODEL_CGB_E - GB_MODEL_CGB_0 + 1; + configuration.audio_driver[15] = 0; } if (configuration.model >= MODEL_MAX) {