From 9ff459f1f59a99c0deae0af0111786f6efc77631 Mon Sep 17 00:00:00 2001 From: Toni Riikonen Date: Wed, 1 Oct 2025 15:49:49 +0300 Subject: [PATCH] Floppy disk audio now gets settings from fdd_audio_profiles.cfg stored in roms/floppy -directory. Floppy settings audio seledtions are also populated by the settings from this config. --- src/86box.c | 6 + src/config.c | 35 +- src/floppy/fdd.c | 6 +- src/floppy/fdd_audio.c | 775 +++++++++++++++++++----------- src/include/86box/fdd.h | 4 +- src/include/86box/fdd_audio.h | 46 +- src/qt/qt_settingsfloppycdrom.cpp | 73 ++- 7 files changed, 619 insertions(+), 326 deletions(-) diff --git a/src/86box.c b/src/86box.c index 591772458..4baed45f5 100644 --- a/src/86box.c +++ b/src/86box.c @@ -79,6 +79,7 @@ #include <86box/mouse.h> #include <86box/gameport.h> #include <86box/fdd.h> +#include <86box/fdd_audio.h> #include <86box/fdc.h> #include <86box/fdc_ext.h> #include <86box/hdd.h> @@ -1380,6 +1381,11 @@ pc_init_modules(void) video_init(); fdd_init(); + + if (fdd_sounds_enabled) { + fdd_audio_load_profiles(); + fdd_audio_init(); + } sound_init(); diff --git a/src/config.c b/src/config.c index d4afe9d81..102f9de97 100644 --- a/src/config.c +++ b/src/config.c @@ -54,6 +54,7 @@ #include <86box/hdc.h> #include <86box/hdc_ide.h> #include <86box/fdd.h> +#include <86box/fdd_audio.h> #include <86box/fdc_ext.h> #include <86box/gameport.h> #include <86box/keyboard.h> @@ -1379,10 +1380,15 @@ load_floppy_and_cdrom_drives(void) int c; int d; int count = cdrom_get_type_count(); + +#ifndef DISABLE_FDD_AUDIO + fdd_audio_load_profiles(); +#endif memset(temp, 0x00, sizeof(temp)); for (c = 0; c < FDD_NUM; c++) { sprintf(temp, "fdd_%02i_type", c + 1); + p = ini_section_get_string(cat, temp, (c < 2) ? "525_2dd" : "none"); if (!strcmp(p, "525_2hd_ps2")) d = fdd_get_from_internal_name("525_2hd"); @@ -1437,14 +1443,14 @@ load_floppy_and_cdrom_drives(void) sprintf(temp, "fdd_%02i_check_bpb", c + 1); ini_section_delete_var(cat, temp); } - sprintf(temp, "fdd_%02i_audio", c + 1); - int def_prof = FDD_AUDIO_PROFILE_NONE; - int prof = ini_section_get_int(cat, temp, def_prof); - if (prof < 0 || prof >= FDD_AUDIO_PROFILE_MAX) - prof = def_prof; + sprintf(temp, "fdd_%02i_audio", c + 1); +#ifndef DISABLE_FDD_AUDIO + p = ini_section_get_string(cat, temp, "none"); + int prof = fdd_audio_get_profile_by_internal_name(p); fdd_set_audio_profile(c, prof); - if (prof == def_prof) - ini_section_delete_var(cat, temp); +#else + fdd_set_audio_profile(c, 0); +#endif for (int i = 0; i < MAX_PREV_IMAGES; i++) { fdd_image_history[c][i] = (char *) calloc((MAX_IMAGE_PATH_LEN + 1) << 1, sizeof(char)); @@ -3433,12 +3439,17 @@ save_floppy_and_cdrom_drives(void) } sprintf(temp, "fdd_%02i_audio", c + 1); - int def_prof = FDD_AUDIO_PROFILE_NONE; - int prof = fdd_get_audio_profile(c); - if (prof == def_prof) +#ifndef DISABLE_FDD_AUDIO + int prof = fdd_get_audio_profile(c); + const char *internal_name = fdd_audio_get_profile_internal_name(prof); + if (internal_name && strcmp(internal_name, "none") != 0) { + ini_section_set_string(cat, temp, internal_name); + } else { ini_section_delete_var(cat, temp); - else - ini_section_set_int(cat, temp, prof); + } +#else + ini_section_delete_var(cat, temp); +#endif } for (c = 0; c < CDROM_NUM; c++) { diff --git a/src/floppy/fdd.c b/src/floppy/fdd.c index d4d9d4476..e36b2ac30 100644 --- a/src/floppy/fdd.c +++ b/src/floppy/fdd.c @@ -409,8 +409,10 @@ fdd_seek(int drive, int track_diff) timer_add(&(fdd_seek_timer[drive]), fdd_seek_complete_callback, &drives[drive], 0); } - double initial_seek_time = FDC_FLAG_PCJR & fdd_fdc->flags ? 40000.0 : 15000.0; - double track_seek_time = FDC_FLAG_PCJR & fdd_fdc->flags ? 10000.0 : 6000.0; + /* Get seek timings from audio profile configuration */ + double initial_seek_time = fdd_audio_get_seek_time(drive, 1, actual_track_diff); + double track_seek_time = fdd_audio_get_seek_time(drive, 0, actual_track_diff); + fdd_log("Seek timing for drive %d: initial %.2f ms, per track %.2f ms\n", drive, initial_seek_time, track_seek_time); uint64_t seek_time_us = (initial_seek_time + (abs(actual_track_diff) * track_seek_time)) * TIMER_USEC; timer_set_delay_u64(&fdd_seek_timer[drive], seek_time_us); } diff --git a/src/floppy/fdd_audio.c b/src/floppy/fdd_audio.c index feb434535..8bfa28858 100644 --- a/src/floppy/fdd_audio.c +++ b/src/floppy/fdd_audio.c @@ -24,23 +24,28 @@ #include <86box/timer.h> #include <86box/fdd.h> #include <86box/fdd_audio.h> +#include <86box/fdc.h> #include <86box/mem.h> #include <86box/rom.h> #include <86box/sound.h> #include <86box/plat.h> #include <86box/path.h> +#include <86box/ini.h> #ifndef DISABLE_FDD_AUDIO +/* Global audio profile configurations */ +static fdd_audio_profile_config_t audio_profiles[FDD_AUDIO_PROFILE_MAX]; +static int audio_profile_count = 0; + /* Audio sample structure */ typedef struct { - const char *filename; - int16_t *buffer; - int samples; - float volume; + char filename[512]; + int16_t *buffer; + int samples; + float volume; } audio_sample_t; -/* Single step audio state */ typedef struct { int position; int active; @@ -64,77 +69,8 @@ typedef struct { audio_sample_t multi_track_seek; } drive_audio_samples_t; -/* 5.25" Teac FD-55GFR sample set */ -static drive_audio_samples_t samples_teac = { - .spindlemotor_start = { - .filename = "roms/floppy/samples/TeacFD-55GFR_5.25_1.2MB_motor_start_48000_16_1_PCM.wav", - .buffer = NULL, .samples = 0, .volume = 3.0f - }, - .spindlemotor_loop = { - .filename = "roms/floppy/samples/TeacFD-55GFR_5.25_1.2MB_motor_loop_48000_16_1_PCM.wav", - .buffer = NULL, .samples = 0, .volume = 3.0f - }, - .spindlemotor_stop = { - .filename = "roms/floppy/samples/TeacFD-55GFR_5.25_1.2MB_motor_stop_48000_16_1_PCM.wav", - .buffer = NULL, .samples = 0, .volume = 3.0f - }, - .single_track_step = { - .filename = "roms/floppy/samples/TeacFD-55GFR_5.25_1.2MB_track_step_48000_16_1_PCM.wav", - .buffer = NULL, .samples = 0, .volume = 2.0f - }, - .multi_track_seek = { - .filename = "roms/floppy/samples/TeacFD_55GFR_5.25_1.2MB_seekupdown_80_tracks1100ms_48000_16_1_PCM.wav", - .buffer = NULL, .samples = 0, .volume = 2.0f - } -}; - -/* 3.5" drive audio samples (Mitsumi) */ -static drive_audio_samples_t samples_35 = { - .spindlemotor_start = { - .filename = "roms/floppy/samples/mitsumi_spindle_motor_start_48000_16_1_PCM.wav", - .buffer = NULL, .samples = 0, .volume = 0.2f - }, - .spindlemotor_loop = { - .filename = "roms/floppy/samples/mitsumi_spindle_motor_loop_48000_16_1_PCM.wav", - .buffer = NULL, .samples = 0, .volume = 0.2f - }, - .spindlemotor_stop = { - .filename = "roms/floppy/samples/mitsumi_spindle_motor_stop_48000_16_1_PCM.wav", - .buffer = NULL, .samples = 0, .volume = 0.2f - }, - .single_track_step = { - .filename = "roms/floppy/samples/mitsumi_track_step_48000_16_1_PCM.wav", - .buffer = NULL, .samples = 0, .volume = 1.0f - }, - .multi_track_seek = { - .filename = "roms/floppy/samples/mitsumi_seek_80_tracks_495ms_48000_16_1_PCM.wav", - .buffer = NULL, .samples = 0, .volume = 1.0f - } -}; - -/* 5.25" drive audio samples (Panasonic) */ -static drive_audio_samples_t samples_525 = { - .spindlemotor_start = { - .filename = "roms/floppy/samples/Panasonic_JU-475-5_5.25_1.2MB_motor_start_48000_16_1_PCM.wav", - .buffer = NULL, .samples = 0, .volume = 1.0f - }, - .spindlemotor_loop = { - .filename = "roms/floppy/samples/Panasonic_JU-475-5_5.25_1.2MB_motor_loop_48000_16_1_PCM.wav", - .buffer = NULL, .samples = 0, .volume = 1.0f - }, - .spindlemotor_stop = { - .filename = "roms/floppy/samples/Panasonic_JU-475-5_5.25_1.2MB_motor_stop_48000_16_1_PCM.wav", - .buffer = NULL, .samples = 0, .volume = 1.0f - }, - .single_track_step = { - .filename = "roms/floppy/samples/Panasonic_JU-475-5_5.25_1.2MB_track_step_48000_16_1_PCM.wav", - .buffer = NULL, .samples = 0, .volume = 2.0f - }, - .multi_track_seek = { - .filename = "roms/floppy/samples/Panasonic_JU-475-5_5.25_1.2MB_seekup_40_tracks_285ms_5ms_per_track_48000_16_1_PCM.wav", - .buffer = NULL, .samples = 0, .volume = 2.0f - } -}; +/* Dynamic sample storage for each profile */ +static drive_audio_samples_t profile_samples[FDD_AUDIO_PROFILE_MAX]; /* Audio state for each drive */ static int spindlemotor_pos[FDD_NUM] = {}; @@ -149,133 +85,357 @@ static single_step_state_t single_step_state[FDD_NUM] = {}; static multi_seek_state_t multi_seek_state[FDD_NUM] = {}; extern uint64_t motoron[FDD_NUM]; -extern char exe_path[2048]; /* path (dir) of executable */ +extern char exe_path[2048]; -extern int fdd_get_audio_profile(int drive); /* from fdd.h */ +extern int fdd_get_audio_profile(int drive); /* Forward declaration */ static int16_t *load_wav(const char *filename, int *sample_count); +#ifdef ENABLE_FDD_LOG +int fdc_do_log = ENABLE_FDD_LOG; + +static void +fdd_log(const char *fmt, ...) +{ + va_list ap; + + if (fdc_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +# else +# define fdd_log(fmt, ...) +# endif + +/* Logging function for audio profile parameters */ +static void +fdd_audio_log_profile_params(int drive, const fdd_audio_profile_config_t* profile) +{ + if (!profile) { + fdd_log("FDD Audio Drive %d: No profile assigned\n", drive); + return; + } + + fdd_log("FDD Audio Drive %d Profile Parameters:\n", drive); + fdd_log(" Profile ID: %d\n", profile->id); + fdd_log(" Profile Name: %s\n", profile->name); + fdd_log(" Internal Name: %s\n", profile->internal_name); + + fdd_log(" Sample Files:\n"); + fdd_log(" Spindle Start: %s (volume: %.2f)\n", + profile->spindlemotor_start.filename, profile->spindlemotor_start.volume); + fdd_log(" Spindle Loop: %s (volume: %.2f)\n", + profile->spindlemotor_loop.filename, profile->spindlemotor_loop.volume); + fdd_log(" Spindle Stop: %s (volume: %.2f)\n", + profile->spindlemotor_stop.filename, profile->spindlemotor_stop.volume); + fdd_log(" Single Step: %s (volume: %.2f)\n", + profile->single_track_step.filename, profile->single_track_step.volume); + fdd_log(" Multi Seek: %s (volume: %.2f)\n", + profile->multi_track_seek.filename, profile->multi_track_seek.volume); + + fdd_log(" Timing Parameters:\n"); + fdd_log(" Seek Duration Per Track: %d samples\n", profile->seek_duration_per_track); + fdd_log(" Total Tracks: %d\n", profile->total_tracks); + fdd_log(" Initial Seek Time: %.1f µs\n", profile->initial_seek_time); + fdd_log(" Initial Seek Time (PCjr): %.1f µs\n", profile->initial_seek_time_pcjr); + fdd_log(" Track Seek Time: %.1f µs\n", profile->track_seek_time); + fdd_log(" Track Seek Time (PCjr): %.1f µs\n", profile->track_seek_time_pcjr); +} + +/* Log audio profile parameters for a specific drive */ +void +fdd_audio_log_drive_profile(int drive) +{ + if (drive < 0 || drive >= FDD_NUM) { + fdd_log("FDD Audio: Invalid drive number %d\n", drive); + return; + } + + int profile_id = fdd_get_audio_profile(drive); + const fdd_audio_profile_config_t* profile = fdd_audio_get_profile(profile_id); + + fdd_log("FDD Audio Drive %d: Using profile %d\n", drive, profile_id); + fdd_audio_log_profile_params(drive, profile); +} + +/* Log only the audio profiles that are actually used by configured drives */ +static void +fdd_audio_log_active_profiles(void) +{ + fdd_log("FDD Audio: Checking active drive configurations...\n"); + int active_drive_count = 0; + + for (int drive = 0; drive < FDD_NUM; drive++) { + if (fdd_get_type(drive) == 0) + continue; + + active_drive_count++; + int profile_id = fdd_get_audio_profile(drive); + if (profile_id >= 0 && profile_id < audio_profile_count) { + fdd_log("FDD Audio: Drive %d (configured) uses profile %d\n", drive, profile_id); + fdd_audio_log_profile_params(drive, &audio_profiles[profile_id]); + } + } + + if (active_drive_count == 0) { + fdd_log("FDD Audio: No drives configured - no audio profiles to log\n"); + return; + } + + fdd_log("FDD Audio: Active audio profiles for %d configured drive(s):\n", active_drive_count); +} + +void +fdd_audio_load_profiles(void) +{ + char config_path[2048]; + ini_t profiles_ini; + + path_append_filename(config_path, exe_path, "roms/floppy/fdd_audio_profiles.cfg"); + profiles_ini = ini_read(config_path); + if (profiles_ini == NULL) { + fdd_log("FDD Audio: Could not load profiles from %s\n", config_path); + return; + } + + audio_profile_count = 0; + + /* Load profiles by trying known profile section names */ + for (int i = 0; i < FDD_AUDIO_PROFILE_MAX && audio_profile_count < FDD_AUDIO_PROFILE_MAX; i++) { + char section_name[64]; + snprintf(section_name, sizeof(section_name), "Profile \"%d\"", i); + + ini_section_t section = ini_find_section(profiles_ini, section_name); + if (section) { + fdd_audio_profile_config_t *profile = &audio_profiles[audio_profile_count]; + + /* Load profile configuration */ + profile->id = ini_section_get_int(section, "id", audio_profile_count); + + const char *name = ini_section_get_string(section, "name", "Unknown"); + strncpy(profile->name, name, sizeof(profile->name) - 1); + profile->name[sizeof(profile->name) - 1] = '\0'; + + const char *internal_name = ini_section_get_string(section, "internal_name", "unknown"); + strncpy(profile->internal_name, internal_name, sizeof(profile->internal_name) - 1); + profile->internal_name[sizeof(profile->internal_name) - 1] = '\0'; + + /* Load sample configurations */ + const char *filename = ini_section_get_string(section, "spindlemotor_start_file", ""); + strncpy(profile->spindlemotor_start.filename, filename, sizeof(profile->spindlemotor_start.filename) - 1); + profile->spindlemotor_start.filename[sizeof(profile->spindlemotor_start.filename) - 1] = '\0'; + profile->spindlemotor_start.volume = ini_section_get_double(section, "spindlemotor_start_volume", 1.0); + + filename = ini_section_get_string(section, "spindlemotor_loop_file", ""); + strncpy(profile->spindlemotor_loop.filename, filename, sizeof(profile->spindlemotor_loop.filename) - 1); + profile->spindlemotor_loop.filename[sizeof(profile->spindlemotor_loop.filename) - 1] = '\0'; + profile->spindlemotor_loop.volume = ini_section_get_double(section, "spindlemotor_loop_volume", 1.0); + + filename = ini_section_get_string(section, "spindlemotor_stop_file", ""); + strncpy(profile->spindlemotor_stop.filename, filename, sizeof(profile->spindlemotor_stop.filename) - 1); + profile->spindlemotor_stop.filename[sizeof(profile->spindlemotor_stop.filename) - 1] = '\0'; + profile->spindlemotor_stop.volume = ini_section_get_double(section, "spindlemotor_stop_volume", 1.0); + + filename = ini_section_get_string(section, "single_track_step_file", ""); + strncpy(profile->single_track_step.filename, filename, sizeof(profile->single_track_step.filename) - 1); + profile->single_track_step.filename[sizeof(profile->single_track_step.filename) - 1] = '\0'; + profile->single_track_step.volume = ini_section_get_double(section, "single_track_step_volume", 1.0); + + filename = ini_section_get_string(section, "multi_track_seek_file", ""); + strncpy(profile->multi_track_seek.filename, filename, sizeof(profile->multi_track_seek.filename) - 1); + profile->multi_track_seek.filename[sizeof(profile->multi_track_seek.filename) - 1] = '\0'; + profile->multi_track_seek.volume = ini_section_get_double(section, "multi_track_seek_volume", 1.0); + + /* Load timing configurations */ + profile->seek_duration_per_track = ini_section_get_int(section, "seek_duration_per_track", 297); + profile->total_tracks = ini_section_get_int(section, "total_tracks", 80); + profile->initial_seek_time = ini_section_get_double(section, "initial_seek_time", 15000.0); + profile->initial_seek_time_pcjr = ini_section_get_double(section, "initial_seek_time_pcjr", 40000.0); + profile->track_seek_time = ini_section_get_double(section, "track_seek_time", 6000.0); + profile->track_seek_time_pcjr = ini_section_get_double(section, "track_seek_time_pcjr", 10000.0); + + audio_profile_count++; + } + } + + ini_close(profiles_ini); + + fdd_log("FDD Audio: Loaded %d audio profiles from %s\n", audio_profile_count, config_path); +} + +static void load_profile_samples(int profile_id) { + if (profile_id <= 0 || profile_id >= audio_profile_count) + return; + + fdd_audio_profile_config_t *config = &audio_profiles[profile_id]; + drive_audio_samples_t *samples = &profile_samples[profile_id]; + + fdd_log("FDD Audio: Loading samples for profile %d (%s)\n", + profile_id, config->name); + + /* Load samples if not already loaded */ + if (samples->spindlemotor_start.buffer == NULL && config->spindlemotor_start.filename[0]) { + strcpy(samples->spindlemotor_start.filename, config->spindlemotor_start.filename); + samples->spindlemotor_start.volume = config->spindlemotor_start.volume; + samples->spindlemotor_start.buffer = load_wav(config->spindlemotor_start.filename, + &samples->spindlemotor_start.samples); + if (samples->spindlemotor_start.buffer) { + fdd_log(" Loaded spindlemotor_start: %s (%d samples, volume %.2f)\n", + config->spindlemotor_start.filename, + samples->spindlemotor_start.samples, + config->spindlemotor_start.volume); + } else { + fdd_log(" Failed to load spindlemotor_start: %s\n", + config->spindlemotor_start.filename); + } + } + + if (samples->spindlemotor_loop.buffer == NULL && config->spindlemotor_loop.filename[0]) { + strcpy(samples->spindlemotor_loop.filename, config->spindlemotor_loop.filename); + samples->spindlemotor_loop.volume = config->spindlemotor_loop.volume; + samples->spindlemotor_loop.buffer = load_wav(config->spindlemotor_loop.filename, + &samples->spindlemotor_loop.samples); + if (samples->spindlemotor_loop.buffer) { + fdd_log(" Loaded spindlemotor_loop: %s (%d samples, volume %.2f)\n", + config->spindlemotor_loop.filename, + samples->spindlemotor_loop.samples, + config->spindlemotor_loop.volume); + } else { + fdd_log(" Failed to load spindlemotor_loop: %s\n", + config->spindlemotor_loop.filename); + } + } + + if (samples->spindlemotor_stop.buffer == NULL && config->spindlemotor_stop.filename[0]) { + strcpy(samples->spindlemotor_stop.filename, config->spindlemotor_stop.filename); + samples->spindlemotor_stop.volume = config->spindlemotor_stop.volume; + samples->spindlemotor_stop.buffer = load_wav(config->spindlemotor_stop.filename, + &samples->spindlemotor_stop.samples); + if (samples->spindlemotor_stop.buffer) { + fdd_log(" Loaded spindlemotor_stop: %s (%d samples, volume %.2f)\n", + config->spindlemotor_stop.filename, + samples->spindlemotor_stop.samples, + config->spindlemotor_stop.volume); + } else { + fdd_log(" Failed to load spindlemotor_stop: %s\n", + config->spindlemotor_stop.filename); + } + } + + if (samples->single_track_step.buffer == NULL && config->single_track_step.filename[0]) { + strcpy(samples->single_track_step.filename, config->single_track_step.filename); + samples->single_track_step.volume = config->single_track_step.volume; + samples->single_track_step.buffer = load_wav(config->single_track_step.filename, + &samples->single_track_step.samples); + if (samples->single_track_step.buffer) { + fdd_log(" Loaded single_track_step: %s (%d samples, volume %.2f)\n", + config->single_track_step.filename, + samples->single_track_step.samples, + config->single_track_step.volume); + } else { + fdd_log(" Failed to load single_track_step: %s\n", + config->single_track_step.filename); + } + } + + if (samples->multi_track_seek.buffer == NULL && config->multi_track_seek.filename[0]) { + strcpy(samples->multi_track_seek.filename, config->multi_track_seek.filename); + samples->multi_track_seek.volume = config->multi_track_seek.volume; + samples->multi_track_seek.buffer = load_wav(config->multi_track_seek.filename, + &samples->multi_track_seek.samples); + if (samples->multi_track_seek.buffer) { + fdd_log(" Loaded multi_track_seek: %s (%d samples, volume %.2f)\n", + config->multi_track_seek.filename, + samples->multi_track_seek.samples, + config->multi_track_seek.volume); + } else { + fdd_log(" Failed to load multi_track_seek: %s\n", + config->multi_track_seek.filename); + } + } +} static drive_audio_samples_t * get_drive_samples(int drive) { - switch (fdd_get_audio_profile(drive)) { - case FDD_AUDIO_PROFILE_PANASONIC: - return &samples_525; - case FDD_AUDIO_PROFILE_TEAC: - return &samples_teac; - case FDD_AUDIO_PROFILE_MITSUMI: - return &samples_35; - default: - return NULL; - } + int profile_id = fdd_get_audio_profile(drive); + if (profile_id <= 0 || profile_id >= audio_profile_count) + return NULL; + + /* Samples are preloaded during fdd_audio_init */ + return &profile_samples[profile_id]; } -static int16_t * -load_wav(const char *filename, int *sample_count) +/* Public API functions */ +int fdd_audio_get_profile_count(void) { + return audio_profile_count; +} + +const fdd_audio_profile_config_t* fdd_audio_get_profile(int id) { + if (id < 0 || id >= audio_profile_count) + return NULL; + return &audio_profiles[id]; +} + +const char* fdd_audio_get_profile_name(int id) { + if (id < 0 || id >= audio_profile_count) + return NULL; + return audio_profiles[id].name; +} + +const char* fdd_audio_get_profile_internal_name(int id) { + if (id < 0 || id >= audio_profile_count) + return NULL; + return audio_profiles[id].internal_name; +} + +int +fdd_audio_get_profile_by_internal_name(const char *internal_name) { - FILE *f = NULL; - char full_path[2048]; + if (!internal_name || !*internal_name) + return 0; - if ((filename == NULL) || (strlen(filename) == 0)) - return NULL; + if (audio_profile_count == 0) + fdd_audio_load_profiles(); - if (strstr(filename, "..") != NULL) - return NULL; - - f = rom_fopen(filename, "rb"); - if (f == NULL) - return NULL; - - wav_header_t hdr; - if (fread(&hdr, sizeof(hdr), 1, f) != 1) { - fclose(f); - return NULL; + for (int i = 0; i < audio_profile_count; i++) { + if (!strcmp(audio_profiles[i].internal_name, internal_name)) + return i; } + return 0; +} - if (memcmp(hdr.riff, "RIFF", 4) || memcmp(hdr.wave, "WAVE", 4) || memcmp(hdr.fmt, "fmt ", 4) || memcmp(hdr.data, "data", 4)) { - fclose(f); - return NULL; +double fdd_audio_get_seek_time(int drive, int is_initial, int track_count) { + int profile_id = fdd_get_audio_profile(drive); + if (profile_id <= 0 || profile_id >= audio_profile_count) { + /* Return default values */ + return is_initial ? 15000.0 : 6000.0; } - - /* Accept both mono and stereo, 16-bit PCM */ - if (hdr.audio_format != 1 || hdr.bits_per_sample != 16 || (hdr.num_channels != 1 && hdr.num_channels != 2)) { - fclose(f); - return NULL; - } - - int input_samples = hdr.data_size / 2; /* 2 bytes per sample */ - int16_t *input_data = malloc(hdr.data_size); - if (!input_data) { - fclose(f); - return NULL; - } - - if (fread(input_data, 1, hdr.data_size, f) != hdr.data_size) { - free(input_data); - fclose(f); - return NULL; - } - fclose(f); - - int16_t *output_data; - int output_samples; - - if (hdr.num_channels == 1) { - /* Convert mono to stereo */ - output_samples = input_samples; /* Number of stereo sample pairs */ - output_data = malloc(input_samples * 2 * sizeof(int16_t)); /* Allocate for stereo */ - if (!output_data) { - free(input_data); - return NULL; - } - - /* Convert mono to stereo by duplicating each sample */ - for (int i = 0; i < input_samples; i++) { - output_data[i * 2] = input_data[i]; /* Left channel */ - output_data[i * 2 + 1] = input_data[i]; /* Right channel */ - } - - free(input_data); + + fdd_audio_profile_config_t *profile = &audio_profiles[profile_id]; + + /* Check if using PCjr timing */ + extern fdc_t *fdd_fdc; + int is_pcjr = (fdd_fdc && (fdd_fdc->flags & FDC_FLAG_PCJR)); + + if (is_initial) { + return is_pcjr ? profile->initial_seek_time_pcjr : profile->initial_seek_time; } else { - /* Already stereo */ - output_data = input_data; - output_samples = input_samples / 2; /* Number of stereo sample pairs */ + return is_pcjr ? profile->track_seek_time_pcjr : profile->track_seek_time; } - - if (sample_count) - *sample_count = output_samples; - - return output_data; } void fdd_audio_init(void) { - int i; - - /* Load audio samples for both drive types */ - samples_35.spindlemotor_start.buffer = load_wav(samples_35.spindlemotor_start.filename, &samples_35.spindlemotor_start.samples); - samples_35.spindlemotor_loop.buffer = load_wav(samples_35.spindlemotor_loop.filename, &samples_35.spindlemotor_loop.samples); - samples_35.spindlemotor_stop.buffer = load_wav(samples_35.spindlemotor_stop.filename, &samples_35.spindlemotor_stop.samples); - samples_35.single_track_step.buffer = load_wav(samples_35.single_track_step.filename, &samples_35.single_track_step.samples); - samples_35.multi_track_seek.buffer = load_wav(samples_35.multi_track_seek.filename, &samples_35.multi_track_seek.samples); - - samples_525.spindlemotor_start.buffer = load_wav(samples_525.spindlemotor_start.filename, &samples_525.spindlemotor_start.samples); - samples_525.spindlemotor_loop.buffer = load_wav(samples_525.spindlemotor_loop.filename, &samples_525.spindlemotor_loop.samples); - samples_525.spindlemotor_stop.buffer = load_wav(samples_525.spindlemotor_stop.filename, &samples_525.spindlemotor_stop.samples); - samples_525.single_track_step.buffer = load_wav(samples_525.single_track_step.filename, &samples_525.single_track_step.samples); - samples_525.multi_track_seek.buffer = load_wav(samples_525.multi_track_seek.filename, &samples_525.multi_track_seek.samples); - - samples_teac.spindlemotor_start.buffer = load_wav(samples_teac.spindlemotor_start.filename, &samples_teac.spindlemotor_start.samples); - samples_teac.spindlemotor_loop.buffer = load_wav(samples_teac.spindlemotor_loop.filename, &samples_teac.spindlemotor_loop.samples); - samples_teac.spindlemotor_stop.buffer = load_wav(samples_teac.spindlemotor_stop.filename, &samples_teac.spindlemotor_stop.samples); - samples_teac.single_track_step.buffer = load_wav(samples_teac.single_track_step.filename, &samples_teac.single_track_step.samples); - samples_teac.multi_track_seek.buffer = load_wav(samples_teac.multi_track_seek.filename, &samples_teac.multi_track_seek.samples); + /* Load audio profiles configuration */ + fdd_audio_load_profiles(); /* Initialize audio state for all drives */ - for (i = 0; i < FDD_NUM; i++) { + for (int i = 0; i < FDD_NUM; i++) { spindlemotor_pos[i] = 0; spindlemotor_state[i] = MOTOR_STATE_STOPPED; spindlemotor_fade_volume[i] = 1.0f; @@ -293,95 +453,62 @@ fdd_audio_init(void) multi_seek_state[i].to_track = -1; } + /* Preload audio samples for each drive's selected profile */ + for (int drive = 0; drive < FDD_NUM; drive++) { + int profile_id = fdd_get_audio_profile(drive); + if (profile_id > 0 && profile_id < audio_profile_count) { + load_profile_samples(profile_id); + } + } + + /* Log only the active profiles used by configured drives */ + fdd_audio_log_active_profiles(); + /* Initialize sound thread */ sound_fdd_thread_init(); + + fdd_log("FDD Audio: Initialization complete\n"); } void fdd_audio_close(void) { - /* Free 3.5" samples */ - if (samples_35.spindlemotor_start.buffer) { - free(samples_35.spindlemotor_start.buffer); - samples_35.spindlemotor_start.buffer = NULL; - samples_35.spindlemotor_start.samples = 0; - } - if (samples_35.spindlemotor_loop.buffer) { - free(samples_35.spindlemotor_loop.buffer); - samples_35.spindlemotor_loop.buffer = NULL; - samples_35.spindlemotor_loop.samples = 0; - } - if (samples_35.spindlemotor_stop.buffer) { - free(samples_35.spindlemotor_stop.buffer); - samples_35.spindlemotor_stop.buffer = NULL; - samples_35.spindlemotor_stop.samples = 0; - } - if (samples_35.single_track_step.buffer) { - free(samples_35.single_track_step.buffer); - samples_35.single_track_step.buffer = NULL; - samples_35.single_track_step.samples = 0; - } - if (samples_35.multi_track_seek.buffer) { - free(samples_35.multi_track_seek.buffer); - samples_35.multi_track_seek.buffer = NULL; - samples_35.multi_track_seek.samples = 0; + fdd_log("FDD Audio: Shutting down audio system\n"); + + /* Free loaded profile samples */ + for (int profile_id = 0; profile_id < audio_profile_count; profile_id++) { + drive_audio_samples_t *samples = &profile_samples[profile_id]; + + if (samples->spindlemotor_start.buffer) { + free(samples->spindlemotor_start.buffer); + samples->spindlemotor_start.buffer = NULL; + samples->spindlemotor_start.samples = 0; + } + if (samples->spindlemotor_loop.buffer) { + free(samples->spindlemotor_loop.buffer); + samples->spindlemotor_loop.buffer = NULL; + samples->spindlemotor_loop.samples = 0; + } + if (samples->spindlemotor_stop.buffer) { + free(samples->spindlemotor_stop.buffer); + samples->spindlemotor_stop.buffer = NULL; + samples->spindlemotor_stop.samples = 0; + } + if (samples->single_track_step.buffer) { + free(samples->single_track_step.buffer); + samples->single_track_step.buffer = NULL; + samples->single_track_step.samples = 0; + } + if (samples->multi_track_seek.buffer) { + free(samples->multi_track_seek.buffer); + samples->multi_track_seek.buffer = NULL; + samples->multi_track_seek.samples = 0; + } } - /* Free 5.25" samples */ - if (samples_525.spindlemotor_start.buffer) { - free(samples_525.spindlemotor_start.buffer); - samples_525.spindlemotor_start.buffer = NULL; - samples_525.spindlemotor_start.samples = 0; - } - if (samples_525.spindlemotor_loop.buffer) { - free(samples_525.spindlemotor_loop.buffer); - samples_525.spindlemotor_loop.buffer = NULL; - samples_525.spindlemotor_loop.samples = 0; - } - if (samples_525.spindlemotor_stop.buffer) { - free(samples_525.spindlemotor_stop.buffer); - samples_525.spindlemotor_stop.buffer = NULL; - samples_525.spindlemotor_stop.samples = 0; - } - if (samples_525.single_track_step.buffer) { - free(samples_525.single_track_step.buffer); - samples_525.single_track_step.buffer = NULL; - samples_525.single_track_step.samples = 0; - } - if (samples_525.multi_track_seek.buffer) { - free(samples_525.multi_track_seek.buffer); - samples_525.multi_track_seek.buffer = NULL; - samples_525.multi_track_seek.samples = 0; - } - - if (samples_teac.spindlemotor_start.buffer) { - free(samples_teac.spindlemotor_start.buffer); - samples_teac.spindlemotor_start.buffer = NULL; - samples_teac.spindlemotor_start.samples = 0; - } - if (samples_teac.spindlemotor_loop.buffer) { - free(samples_teac.spindlemotor_loop.buffer); - samples_teac.spindlemotor_loop.buffer = NULL; - samples_teac.spindlemotor_loop.samples = 0; - } - if (samples_teac.spindlemotor_stop.buffer) { - free(samples_teac.spindlemotor_stop.buffer); - samples_teac.spindlemotor_stop.buffer = NULL; - samples_teac.spindlemotor_stop.samples = 0; - } - if (samples_teac.single_track_step.buffer) { - free(samples_teac.single_track_step.buffer); - samples_teac.single_track_step.buffer = NULL; - samples_teac.single_track_step.samples = 0; - } - if (samples_teac.multi_track_seek.buffer) { - free(samples_teac.multi_track_seek.buffer); - samples_teac.multi_track_seek.buffer = NULL; - samples_teac.multi_track_seek.samples = 0; - } - - /* End sound thread */ sound_fdd_thread_end(); + + fdd_log("FDD Audio: Shutdown complete\n"); } void @@ -394,16 +521,20 @@ fdd_audio_set_motor_enable(int drive, int motor_enable) if (!samples) return; + fdd_log("FDD Audio Drive %d: Motor %s\n", drive, motor_enable ? "ON" : "OFF"); + if (motor_enable && !motoron[drive]) { /* Motor starting up */ if (spindlemotor_state[drive] == MOTOR_STATE_STOPPING) { /* Interrupt stop sequence and transition back to loop */ + fdd_log("FDD Audio Drive %d: Interrupting stop sequence, returning to loop\n", drive); spindlemotor_state[drive] = MOTOR_STATE_RUNNING; spindlemotor_pos[drive] = 0; spindlemotor_fade_volume[drive] = 1.0f; spindlemotor_fade_samples_remaining[drive] = 0; } else { /* Normal startup */ + fdd_log("FDD Audio Drive %d: Starting motor (normal startup)\n", drive); spindlemotor_state[drive] = MOTOR_STATE_STARTING; spindlemotor_pos[drive] = 0; spindlemotor_fade_volume[drive] = 1.0f; @@ -411,6 +542,7 @@ fdd_audio_set_motor_enable(int drive, int motor_enable) } } else if (!motor_enable && motoron[drive]) { /* Motor stopping */ + fdd_log("FDD Audio Drive %d: Stopping motor\n", drive); spindlemotor_state[drive] = MOTOR_STATE_STOPPING; spindlemotor_pos[drive] = 0; spindlemotor_fade_volume[drive] = 1.0f; @@ -429,6 +561,8 @@ fdd_audio_play_single_track_step(int drive, int from_track, int to_track) if (abs(from_track - to_track) != 1) return; /* Only single track movements */ + fdd_log("FDD Audio Drive %d: Single track step %d -> %d\n", drive, from_track, to_track); + single_step_state[drive].position = 0; single_step_state[drive].active = 1; } @@ -457,18 +591,20 @@ fdd_audio_play_multi_track_seek(int drive, int from_track, int to_track) return; } - /* Calculate duration based on drive type */ - int duration_samples; - if (fdd_is_525(drive)) { - /* 5.25": 285ms for 40 tracks = 7.125ms per track at 48kHz sample rate */ - /* 7.125ms = 0.007125s, at 48000 Hz = 342 samples per track */ - duration_samples = track_diff * 342; - } else { - /* 3.5": 495ms for 80 tracks = 6.1875ms per track at 48kHz sample rate */ - /* 6.1875ms = 0.0061875s, at 48000 Hz = 297 samples per track */ - duration_samples = track_diff * 297; - } + fdd_log("FDD Audio Drive %d: Multi-track seek %d -> %d (%d tracks)\n", + drive, from_track, to_track, track_diff); + /* Get timing from configuration */ + int profile_id = fdd_get_audio_profile(drive); + int duration_samples; + + if (profile_id < 1 || profile_id >= audio_profile_count) + return; + + /* Use configured timing */ + duration_samples = track_diff * audio_profiles[profile_id].seek_duration_per_track; + fdd_log("FDD Audio Drive %d: Seek duration %d samples (%d tracks * %d samples/track)\n", + drive, duration_samples, track_diff, audio_profiles[profile_id].seek_duration_per_track); /* Clamp to maximum available sample length */ if (duration_samples > samples->multi_track_seek.samples) duration_samples = samples->multi_track_seek.samples; @@ -481,6 +617,92 @@ fdd_audio_play_multi_track_seek(int drive, int from_track, int to_track) multi_seek_state[drive].to_track = to_track; } +static int16_t * +load_wav(const char *filename, int *sample_count) +{ + if ((filename == NULL) || (strlen(filename) == 0)) + return NULL; + + if (strstr(filename, "..") != NULL) + return NULL; + + FILE *f = rom_fopen(filename, "rb"); + if (f == NULL) { + fdd_log("FDD Audio: Failed to open WAV file: %s\n", filename); + return NULL; + } + + wav_header_t hdr; + if (fread(&hdr, sizeof(hdr), 1, f) != 1) { + fdd_log("FDD Audio: Failed to read WAV header from: %s\n", filename); + fclose(f); + return NULL; + } + + if (memcmp(hdr.riff, "RIFF", 4) || memcmp(hdr.wave, "WAVE", 4) || memcmp(hdr.fmt, "fmt ", 4) || memcmp(hdr.data, "data", 4)) { + fdd_log("FDD Audio: Invalid WAV format in file: %s\n", filename); + fclose(f); + return NULL; + } + + /* Accept both mono and stereo, 16-bit PCM */ + if (hdr.audio_format != 1 || hdr.bits_per_sample != 16 || (hdr.num_channels != 1 && hdr.num_channels != 2)) { + fdd_log("FDD Audio: Unsupported WAV format in %s (format: %d, bits: %d, channels: %d)\n", + filename, hdr.audio_format, hdr.bits_per_sample, hdr.num_channels); + fclose(f); + return NULL; + } + + int input_samples = hdr.data_size / 2; /* 2 bytes per sample */ + int16_t *input_data = malloc(hdr.data_size); + if (!input_data) { + fdd_log("FDD Audio: Failed to allocate memory for WAV data: %s\n", filename); + fclose(f); + return NULL; + } + + if (fread(input_data, 1, hdr.data_size, f) != hdr.data_size) { + fdd_log("FDD Audio: Failed to read WAV data from: %s\n", filename); + free(input_data); + fclose(f); + return NULL; + } + fclose(f); + + int16_t *output_data; + int output_samples; + + if (hdr.num_channels == 1) { + /* Convert mono to stereo */ + output_samples = input_samples; /* Number of stereo sample pairs */ + output_data = malloc(input_samples * 2 * sizeof(int16_t)); /* Allocate for stereo */ + if (!output_data) { + fdd_log("FDD Audio: Failed to allocate stereo conversion buffer for: %s\n", filename); + free(input_data); + return NULL; + } + + /* Convert mono to stereo by duplicating each sample */ + for (int i = 0; i < input_samples; i++) { + output_data[i * 2] = input_data[i]; /* Left channel */ + output_data[i * 2 + 1] = input_data[i]; /* Right channel */ + } + + free(input_data); + fdd_log("FDD Audio: Loaded %s (mono->stereo, %d samples)\n", filename, output_samples); + } else { + /* Already stereo */ + output_data = input_data; + output_samples = input_samples / 2; /* Number of stereo sample pairs */ + fdd_log("FDD Audio: Loaded %s (stereo, %d samples)\n", filename, output_samples); + } + + if (sample_count) + *sample_count = output_samples; + + return output_data; +} + void fdd_audio_callback(int16_t *buffer, int length) { @@ -777,11 +999,24 @@ fdd_audio_callback(int16_t *buffer, int length) } #else +/* Stub implementations when audio is disabled */ +void fdd_audio_load_profiles(void) {} +int fdd_audio_get_profile_count(void) { return 1; } +const fdd_audio_profile_config_t* fdd_audio_get_profile(int id) { + static fdd_audio_profile_config_t none_profile = {0, "None", "none"}; + return (id == 0) ? &none_profile : NULL; +} +const char* fdd_audio_get_profile_name(int id) { return (id == 0) ? "None" : NULL; } +const char* fdd_audio_get_profile_internal_name(int id) { return (id == 0) ? "none" : NULL; } +int fdd_audio_get_profile_by_internal_name(const char* internal_name) { return 0; } +double fdd_audio_get_seek_time(int drive, int is_initial, int track_count) { + return is_initial ? 15000.0 : 6000.0; +} void fdd_audio_init(void) {} void fdd_audio_close(void) {} -void fdd_audio_set_motor_enable(int drive, int motor_enable) { (void) drive; (void) motor_enable; } -void fdd_audio_play_single_track_step(int drive, int from_track, int to_track) { (void) drive; (void) from_track; (void) to_track; } -void fdd_audio_play_multi_track_seek(int drive, int from_track, int to_track) { (void) drive; (void) from_track; (void) to_track; } +void fdd_audio_set_motor_enable(int drive, int motor_enable) {} +void fdd_audio_play_single_track_step(int drive, int from_track, int to_track) {} +void fdd_audio_play_multi_track_seek(int drive, int from_track, int to_track) {} void fdd_audio_callback(int16_t *buffer, int length) { memset(buffer, 0, length * sizeof(int16_t)); } #endif /* DISABLE_FDD_AUDIO */ \ No newline at end of file diff --git a/src/include/86box/fdd.h b/src/include/86box/fdd.h index b73365de2..8f21ebeda 100644 --- a/src/include/86box/fdd.h +++ b/src/include/86box/fdd.h @@ -26,11 +26,11 @@ #define SEEK_RECALIBRATE -999 /* Per-drive audio profiles */ -#define FDD_AUDIO_PROFILE_NONE 0 +/* #define FDD_AUDIO_PROFILE_NONE 0 #define FDD_AUDIO_PROFILE_MITSUMI 1 #define FDD_AUDIO_PROFILE_PANASONIC 2 #define FDD_AUDIO_PROFILE_TEAC 3 -#define FDD_AUDIO_PROFILE_MAX 4 +#define FDD_AUDIO_PROFILE_MAX 4*/ #ifdef __cplusplus extern "C" { diff --git a/src/include/86box/fdd_audio.h b/src/include/86box/fdd_audio.h index acd4e9350..c27124a05 100644 --- a/src/include/86box/fdd_audio.h +++ b/src/include/86box/fdd_audio.h @@ -23,6 +23,32 @@ extern "C" { #ifndef DISABLE_FDD_AUDIO +/* Audio sample configuration structure */ +typedef struct { + char filename[512]; + float volume; +} audio_sample_config_t; + +/* Drive type specific audio configuration */ +typedef struct { + int id; + char name[128]; + char internal_name[64]; + audio_sample_config_t spindlemotor_start; + audio_sample_config_t spindlemotor_loop; + audio_sample_config_t spindlemotor_stop; + audio_sample_config_t single_track_step; + audio_sample_config_t multi_track_seek; + int seek_duration_per_track; + int total_tracks; + double initial_seek_time; + double initial_seek_time_pcjr; + double track_seek_time; + double track_seek_time_pcjr; +} fdd_audio_profile_config_t; + +#define FDD_AUDIO_PROFILE_MAX 64 + /* Motor sound states */ typedef enum { MOTOR_STATE_STOPPED = 0, @@ -52,12 +78,29 @@ typedef struct { #define FADE_DURATION_MS 75 #define FADE_SAMPLES (48000 * FADE_DURATION_MS / 1000) +/* Functions for configuration management */ +extern void fdd_audio_load_profiles(void); +extern int fdd_audio_get_profile_count(void); +extern const fdd_audio_profile_config_t* fdd_audio_get_profile(int id); +extern const char* fdd_audio_get_profile_name(int id); +extern const char* fdd_audio_get_profile_internal_name(int id); +extern int fdd_audio_get_profile_by_internal_name(const char* internal_name); +extern double fdd_audio_get_seek_time(int drive, int is_initial, int track_count); + #else typedef enum { MOTOR_STATE_STOPPED = 0 } motor_state_t; +typedef struct { + int id; + char name[128]; + char internal_name[64]; +} fdd_audio_profile_config_t; + +#define FDD_AUDIO_PROFILE_MAX 1 + #endif /* DISABLE_FDD_AUDIO */ /* FDD audio initialization and cleanup */ @@ -76,9 +119,6 @@ extern void fdd_audio_play_multi_track_seek(int drive, int from_track, int to_tr /* Audio callback function */ extern void fdd_audio_callback(int16_t *buffer, int length); -/* State name helper function */ -extern const char *fdd_audio_motor_state_name(motor_state_t state); - #ifdef __cplusplus } #endif diff --git a/src/qt/qt_settingsfloppycdrom.cpp b/src/qt/qt_settingsfloppycdrom.cpp index 6ec130044..8ba860e0f 100644 --- a/src/qt/qt_settingsfloppycdrom.cpp +++ b/src/qt/qt_settingsfloppycdrom.cpp @@ -32,6 +32,7 @@ extern "C" { #include <86box/timer.h> #include <86box/fdd.h> #include <86box/cdrom.h> +#include <86box/fdd_audio.h> } #include "qt_models_common.hpp" @@ -136,7 +137,7 @@ SettingsFloppyCDROM::SettingsFloppyCDROM(QWidget *parent) model->setHeaderData(2, Qt::Horizontal, tr("Check BPB")); model->setHeaderData(3, Qt::Horizontal, tr("Audio")); - model->insertRows(0, FDD_NUM); +model->insertRows(0, FDD_NUM); /* Floppy drives category */ for (int i = 0; i < FDD_NUM; i++) { auto idx = model->index(i, 0); @@ -145,22 +146,21 @@ SettingsFloppyCDROM::SettingsFloppyCDROM(QWidget *parent) model->setData(idx.siblingAtColumn(1), fdd_get_turbo(i) > 0 ? tr("On") : tr("Off")); model->setData(idx.siblingAtColumn(2), fdd_get_check_bpb(i) > 0 ? tr("On") : tr("Off")); - int prof = fdd_get_audio_profile(i); + int prof = fdd_get_audio_profile(i); QString profName; - switch (prof) { - case FDD_AUDIO_PROFILE_PANASONIC: - profName = tr("Panasonic"); - break; - case FDD_AUDIO_PROFILE_TEAC: - profName = tr("Teac"); - break; - case FDD_AUDIO_PROFILE_MITSUMI: - profName = tr("Mitsumi"); - break; - default: - profName = tr("None"); - break; + +#ifndef DISABLE_FDD_AUDIO + // Get the profile name from the configuration system + const char *name = fdd_audio_get_profile_internal_name(prof); + if (name) { + profName = QString(name); + } else { + profName = tr("None"); } +#else + profName = tr("None"); +#endif + auto audioIdx = model->index(i, 3); model->setData(audioIdx, profName); model->setData(audioIdx, prof, Qt::UserRole); @@ -174,10 +174,13 @@ SettingsFloppyCDROM::SettingsFloppyCDROM(QWidget *parent) #ifndef DISABLE_FDD_AUDIO ui->comboBoxFloppyAudio->setVisible(true); - ui->comboBoxFloppyAudio->addItem(tr("None"), FDD_AUDIO_PROFILE_NONE); - ui->comboBoxFloppyAudio->addItem(tr("Generic Mitsumi 3.5\" 1.44MB"), FDD_AUDIO_PROFILE_MITSUMI); - ui->comboBoxFloppyAudio->addItem(tr("Panasonic JU-475-5 5.25\" 1.2MB"), FDD_AUDIO_PROFILE_PANASONIC); - ui->comboBoxFloppyAudio->addItem(tr("Teac FD-55GFR 5.25\" 1.2MB"), FDD_AUDIO_PROFILE_TEAC); + int profile_count = fdd_audio_get_profile_count(); + for (int i = 0; i < profile_count; i++) { + const char *name = fdd_audio_get_profile_name(i); + if (name) { + ui->comboBoxFloppyAudio->addItem(name, i); + } + } ui->comboBoxFloppyAudio->setSizeAdjustPolicy(QComboBox::AdjustToContents); #else ui->comboBoxFloppyAudio->setVisible(false); @@ -390,26 +393,22 @@ SettingsFloppyCDROM::on_comboBoxFloppyType_activated(int index) void SettingsFloppyCDROM::on_comboBoxFloppyAudio_activated(int) { - auto idx = ui->tableViewFloppy->selectionModel()->currentIndex(); - int prof = ui->comboBoxFloppyAudio->currentData().toInt(); + auto idx = ui->tableViewFloppy->selectionModel()->currentIndex(); + int prof = ui->comboBoxFloppyAudio->currentData().toInt(); QString profName; - switch (prof) { - case FDD_AUDIO_PROFILE_NONE: - profName = tr("None"); - break; - case FDD_AUDIO_PROFILE_PANASONIC: - profName = tr("Panasonic"); - break; - case FDD_AUDIO_PROFILE_TEAC: - profName = tr("Teac"); - break; - case FDD_AUDIO_PROFILE_MITSUMI: - profName = tr("Mitsumi"); - break; - default: - profName = tr("None"); - break; + +#ifndef DISABLE_FDD_AUDIO + // Get the profile name from the configuration system + const char *name = fdd_audio_get_profile_internal_name(prof); + if (name) { + profName = name; + } else { + profName = tr("None"); } +#else + profName = tr("None"); +#endif + auto audioIdx = idx.siblingAtColumn(3); ui->tableViewFloppy->model()->setData(audioIdx, profName); ui->tableViewFloppy->model()->setData(audioIdx, prof, Qt::UserRole);