Merge pull request #6512 from Domppari/feature/separate_samples_for_each_fdd_track_seek

Feature / separate samples for each fdd track seek
This commit is contained in:
Miran Grča
2025-11-29 22:41:29 +01:00
committed by GitHub
6 changed files with 641 additions and 509 deletions

View File

@@ -390,10 +390,7 @@ fdd_seek(int drive, int track_diff)
else {
/* Trigger appropriate audio for track movements */
int actual_track_diff = abs(old_track - fdd[drive].track);
if (actual_track_diff == 1) {
/* Single track movement */
fdd_audio_play_single_track_step(drive, old_track, fdd[drive].track);
} else if (actual_track_diff > 1) {
if (actual_track_diff > 0) {
/* Multi-track seek */
fdd_audio_play_multi_track_seek(drive, old_track, fdd[drive].track);
}
@@ -409,12 +406,15 @@ fdd_seek(int drive, int track_diff)
timer_add(&(fdd_seek_timer[drive]), fdd_seek_complete_callback, &drives[drive], 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);
/* Determine seek direction - seeking down means moving toward track 0 */
int is_seek_down = (fdd[drive].track < old_track);
/* Get seek timings from audio profile configuration with direction awareness */
double seek_time_us = fdd_audio_get_seek_time(drive, actual_track_diff, is_seek_down);
fdd_log("Seek timing for drive %d: %.2f µs (%s)\n",
drive, seek_time_us, is_seek_down ? "DOWN" : "UP");
uint64_t seek_delay_us = seek_time_us * TIMER_USEC;
timer_set_delay_u64(&fdd_seek_timer[drive], seek_delay_us);
}
}
@@ -430,6 +430,15 @@ fdd_track0(int drive)
return !fdd[drive].track;
}
int
fdd_get_type_max_track(int type)
{
if (type < 0 || type >= (sizeof(drive_types) / sizeof(drive_types[0])))
return 0;
return drive_types[type].max_track;
}
int
fdd_current_track(int drive)
{

File diff suppressed because it is too large Load Diff

View File

@@ -36,6 +36,7 @@ extern void fdd_do_seek(int drive, int track);
extern void fdd_forced_seek(int drive, int track_diff);
extern void fdd_seek(int drive, int track_diff);
extern int fdd_track0(int drive);
extern int fdd_get_type_max_track(int type);
extern int fdd_getrpm(int drive);
extern void fdd_set_densel(int densel);
extern int fdd_can_read_medium(int drive);

View File

@@ -23,6 +23,12 @@ extern "C" {
#ifndef DISABLE_FDD_AUDIO
/* Maximum number of seek samples (for 80-track drives: 1-79 tracks) */
#define MAX_SEEK_SAMPLES 79
/* Maximum number of simultaneous seek sounds per drive */
#define MAX_CONCURRENT_SEEKS 8
/* Audio sample configuration structure */
typedef struct {
char filename[512];
@@ -37,14 +43,10 @@ typedef struct {
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 total_tracks;
int samples_per_track;
double initial_seek_time;
double initial_seek_time_pcjr;
double track_seek_time;
double track_seek_time_pcjr;
audio_sample_config_t seek_up[MAX_SEEK_SAMPLES];
audio_sample_config_t seek_down[MAX_SEEK_SAMPLES];
double seek_time_ms[MAX_SEEK_SAMPLES]; /* Seek time in milliseconds for each track count */
int total_tracks; /* 40 or 80 */
} fdd_audio_profile_config_t;
#define FDD_AUDIO_PROFILE_MAX 64
@@ -84,8 +86,9 @@ 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);
extern int fdd_audio_get_profile_by_internal_name(const char *internal_name);
extern double fdd_audio_get_seek_time(int drive, int track_count, int is_seek_down);
extern void load_profile_samples(int profile_id);
#else

View File

@@ -166,10 +166,10 @@ asset_get_full_path(char *dest, const char *fn)
dest[0] = 0x00;
if (!strncmp(fn, "assets/", 5)) {
if (!strncmp(fn, "assets/", 7)) {
/* Relative path */
for (rom_path_t *asset_path = &asset_paths; asset_path != NULL; asset_path = asset_path->next) {
path_append_filename(temp, asset_path->path, fn + 5);
path_append_filename(temp, asset_path->path, fn + 7);
if (rom_check(temp)) {
strcpy(dest, temp);
@@ -218,10 +218,10 @@ asset_fopen(const char *fn, char *mode)
if ((fn == NULL) || (mode == NULL))
return NULL;
if (!strncmp(fn, "assets/", 5)) {
if (!strncmp(fn, "assets/", 7)) {
/* Relative path */
for (rom_path_t *asset_path = &asset_paths; asset_path != NULL; asset_path = asset_path->next) {
path_append_filename(temp, asset_path->path, fn + 5);
path_append_filename(temp, asset_path->path, fn + 7);
if ((fp = plat_fopen(temp, mode)) != NULL)
return fp;
@@ -267,10 +267,10 @@ asset_getfile(const char *fn, char *s, int size)
{
char temp[1024];
if (!strncmp(fn, "assets/", 5)) {
if (!strncmp(fn, "assets/", 7)) {
/* Relative path */
for (rom_path_t *asset_path = &asset_paths; asset_path != NULL; asset_path = asset_path->next) {
path_append_filename(temp, asset_path->path, fn + 5);
path_append_filename(temp, asset_path->path, fn + 7);
if (plat_file_check(temp)) {
strncpy(s, temp, size);
@@ -322,10 +322,10 @@ asset_present(const char *fn)
if (fn == NULL)
return 0;
if (!strncmp(fn, "assets/", 5)) {
if (!strncmp(fn, "assets/", 7)) {
/* Relative path */
for (rom_path_t *asset_path = &asset_paths; asset_path != NULL; asset_path = asset_path->next) {
path_append_filename(temp, asset_path->path, fn + 5);
path_append_filename(temp, asset_path->path, fn + 7);
if (plat_file_check(temp))
return 1;

View File

@@ -303,9 +303,68 @@ SettingsFloppyCDROM::onFloppyRowChanged(const QModelIndex &current)
ui->checkBoxTurboTimings->setChecked(current.siblingAtColumn(1).data() == tr("On"));
ui->checkBoxCheckBPB->setChecked(current.siblingAtColumn(2).data() == tr("On"));
int prof = current.siblingAtColumn(3).data(Qt::UserRole).toInt();
int prof = current.siblingAtColumn(3).data(Qt::UserRole).toInt();
#ifndef DISABLE_FDD_AUDIO
// Rebuild audio profile combo box based on drive type
int row = current.row();
ui->comboBoxFloppyAudio->clear();
if (type == 0) {
ui->comboBoxFloppyAudio->addItem(tr("None"), 0);
ui->comboBoxFloppyAudio->setCurrentIndex(0);
ui->comboBoxFloppyAudio->setEnabled(false);
// Update the model to reflect "None" profile
auto audioIdx = current.siblingAtColumn(3);
ui->tableViewFloppy->model()->setData(audioIdx, tr("None"));
ui->tableViewFloppy->model()->setData(audioIdx, 0, Qt::UserRole);
return;
}
ui->comboBoxFloppyAudio->setEnabled(true);
// Get drive type's track count to determine 40-track vs 80-track
int drive_max_tracks = fdd_get_type_max_track(type);
bool is_40_track = (drive_max_tracks <= 43);
int profile_count = fdd_audio_get_profile_count();
int currentProfileIndex = -1;
int comboIndex = 0;
for (int i = 0; i < profile_count; i++) {
const char *name = fdd_audio_get_profile_name(i);
if (name) {
const fdd_audio_profile_config_t *profile = fdd_audio_get_profile(i);
if (profile) {
// Only show profiles that match the drive type's track count
if (profile->total_tracks == 0 ||
(is_40_track && profile->total_tracks == 40) ||
(!is_40_track && profile->total_tracks == 80)) {
ui->comboBoxFloppyAudio->addItem(name, i);
if (i == prof) {
currentProfileIndex = comboIndex;
}
comboIndex++;
}
}
}
}
// If current profile is not compatible, select "None" (profile 0)
if (currentProfileIndex == -1) {
currentProfileIndex = ui->comboBoxFloppyAudio->findData(0);
// Update the model to reflect "None" profile
auto audioIdx = current.siblingAtColumn(3);
ui->tableViewFloppy->model()->setData(audioIdx, tr("None"));
ui->tableViewFloppy->model()->setData(audioIdx, 0, Qt::UserRole);
}
ui->comboBoxFloppyAudio->setCurrentIndex(currentProfileIndex);
#else
int comboIndex = ui->comboBoxFloppyAudio->findData(prof);
ui->comboBoxFloppyAudio->setCurrentIndex(comboIndex);
#endif
}
void
@@ -375,8 +434,11 @@ SettingsFloppyCDROM::on_checkBoxCheckBPB_stateChanged(int arg1)
void
SettingsFloppyCDROM::on_comboBoxFloppyType_activated(int index)
{
setFloppyType(ui->tableViewFloppy->model(),
ui->tableViewFloppy->selectionModel()->currentIndex(), index);
auto currentIndex = ui->tableViewFloppy->selectionModel()->currentIndex();
setFloppyType(ui->tableViewFloppy->model(), currentIndex, index);
// Trigger row changed to rebuild audio profile list
onFloppyRowChanged(currentIndex);
}
void
@@ -394,6 +456,9 @@ SettingsFloppyCDROM::on_comboBoxFloppyAudio_activated(int)
} else {
profName = tr("None");
}
if (prof > 0) {
load_profile_samples(prof);
}
#else
profName = tr("None");
#endif