diff --git a/86box/86Box.exe b/86box/86Box.exe new file mode 100644 index 000000000..7d5c0071e Binary files /dev/null and b/86box/86Box.exe differ diff --git a/src/.vs/CMake Overview b/src/.vs/CMake Overview new file mode 100644 index 000000000..e69de29bb diff --git a/src/.vs/ProjectSettings.json b/src/.vs/ProjectSettings.json new file mode 100644 index 000000000..8f0d73346 --- /dev/null +++ b/src/.vs/ProjectSettings.json @@ -0,0 +1,3 @@ +{ + "CurrentProjectSetting": "x64-Debug" +} \ No newline at end of file diff --git a/src/.vs/VSWorkspaceState.json b/src/.vs/VSWorkspaceState.json new file mode 100644 index 000000000..287f4fc17 --- /dev/null +++ b/src/.vs/VSWorkspaceState.json @@ -0,0 +1,12 @@ +{ + "OutputFoldersPerTargetSystem": { + "Local Machine": [ + "out\\build\\x64-Debug", + "out\\install\\x64-Debug" + ] + }, + "ExpandedNodes": [ + "" + ], + "PreviewInSolutionExplorer": false +} \ No newline at end of file diff --git a/src/.vs/slnx.sqlite b/src/.vs/slnx.sqlite new file mode 100644 index 000000000..76935ebcb Binary files /dev/null and b/src/.vs/slnx.sqlite differ diff --git a/src/.vs/src/CopilotIndices/17.14.1091.29919/CodeChunks.db b/src/.vs/src/CopilotIndices/17.14.1091.29919/CodeChunks.db new file mode 100644 index 000000000..77c2f33b5 Binary files /dev/null and b/src/.vs/src/CopilotIndices/17.14.1091.29919/CodeChunks.db differ diff --git a/src/.vs/src/CopilotIndices/17.14.1091.29919/SemanticSymbols.db b/src/.vs/src/CopilotIndices/17.14.1091.29919/SemanticSymbols.db new file mode 100644 index 000000000..735bfcafd Binary files /dev/null and b/src/.vs/src/CopilotIndices/17.14.1091.29919/SemanticSymbols.db differ diff --git a/src/.vs/src/FileContentIndex/98bf2c6c-23cb-46f3-98e8-296efefa37ba.vsidx b/src/.vs/src/FileContentIndex/98bf2c6c-23cb-46f3-98e8-296efefa37ba.vsidx new file mode 100644 index 000000000..d690dca4d Binary files /dev/null and b/src/.vs/src/FileContentIndex/98bf2c6c-23cb-46f3-98e8-296efefa37ba.vsidx differ diff --git a/src/.vs/src/FileContentIndex/e2cf3db7-963a-4cad-921f-61826474cda3.vsidx b/src/.vs/src/FileContentIndex/e2cf3db7-963a-4cad-921f-61826474cda3.vsidx new file mode 100644 index 000000000..ed47e0b86 Binary files /dev/null and b/src/.vs/src/FileContentIndex/e2cf3db7-963a-4cad-921f-61826474cda3.vsidx differ diff --git a/src/.vs/src/v17/.wsuo b/src/.vs/src/v17/.wsuo new file mode 100644 index 000000000..ad40ebd38 Binary files /dev/null and b/src/.vs/src/v17/.wsuo differ diff --git a/src/.vs/src/v17/Browse.VC.db b/src/.vs/src/v17/Browse.VC.db new file mode 100644 index 000000000..53f9ee380 Binary files /dev/null and b/src/.vs/src/v17/Browse.VC.db differ diff --git a/src/.vs/src/v17/DocumentLayout.json b/src/.vs/src/v17/DocumentLayout.json new file mode 100644 index 000000000..a730df9a2 --- /dev/null +++ b/src/.vs/src/v17/DocumentLayout.json @@ -0,0 +1,61 @@ +{ + "Version": 1, + "WorkspaceRootPath": "D:\\msys64\\home\\dompp\\86Box\\src\\", + "Documents": [ + { + "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|D:\\msys64\\home\\dompp\\86Box\\src\\CMakeSettings.json||{10608CD5-279C-4A28-BD5F-BA2CFCE06219}", + "RelativeMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|solutionrelative:CMakeSettings.json||{10608CD5-279C-4A28-BD5F-BA2CFCE06219}" + }, + { + "AbsoluteMoniker": "D:0:0:{A2FE74E1-B743-11D0-AE1A-00A0C90FFFC3}|\u003CMiscFiles\u003E|CMake Overview Pages||{B1CAA5B0-FEB1-4350-8AB9-F895876842F2}" + } + ], + "DocumentGroupContainers": [ + { + "Orientation": 0, + "VerticalTabListWidth": 256, + "DocumentGroups": [ + { + "DockedWidth": 200, + "SelectedChildIndex": 3, + "Children": [ + { + "$type": "Bookmark", + "Name": "ST:0:0:{65ddf8c3-8f89-4077-a6c6-dbb8853aab13}" + }, + { + "$type": "Bookmark", + "Name": "ST:11:0:{2456bd12-ecf7-4988-a4a6-67d49173f565}" + }, + { + "$type": "Bookmark", + "Name": "ST:12:0:{2456bd12-ecf7-4988-a4a6-67d49173f565}" + }, + { + "$type": "Document", + "DocumentIndex": 0, + "Title": "CMakeSettings.json", + "DocumentMoniker": "D:\\msys64\\home\\dompp\\86Box\\src\\CMakeSettings.json", + "RelativeDocumentMoniker": "CMakeSettings.json", + "ToolTip": "D:\\msys64\\home\\dompp\\86Box\\src\\CMakeSettings.json", + "RelativeToolTip": "CMakeSettings.json", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001642|", + "WhenOpened": "2025-08-30T19:09:23.796Z", + "EditorCaption": "" + }, + { + "$type": "Document", + "DocumentIndex": 1, + "Title": "CMake Overview Pages", + "DocumentMoniker": "CMake Overview Pages", + "ToolTip": "CMake Overview Pages", + "Icon": "ae27a6b0-e345-4288-96df-5eaf394ee369.001001|", + "WhenOpened": "2025-08-30T19:09:12.336Z", + "EditorCaption": "" + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/src/.vs/src/v17/workspaceFileList.bin b/src/.vs/src/v17/workspaceFileList.bin new file mode 100644 index 000000000..3e3aae541 Binary files /dev/null and b/src/.vs/src/v17/workspaceFileList.bin differ diff --git a/src/CMakeSettings.json b/src/CMakeSettings.json new file mode 100644 index 000000000..9204f06eb --- /dev/null +++ b/src/CMakeSettings.json @@ -0,0 +1,15 @@ +{ + "configurations": [ + { + "name": "x64-Debug", + "generator": "Ninja", + "configurationType": "Debug", + "inheritEnvironments": [ "msvc_x64_x64" ], + "buildRoot": "${projectDir}\\out\\build\\${name}", + "installRoot": "${projectDir}\\out\\install\\${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "", + "ctestCommandArgs": "" + } + ] +} \ No newline at end of file diff --git a/src/floppy/fdd.c b/src/floppy/fdd.c index 8bc946388..4d504e709 100644 --- a/src/floppy/fdd.c +++ b/src/floppy/fdd.c @@ -23,6 +23,8 @@ #include #include #include +#include + #define HAVE_STDARG_H #include <86box/86box.h> #include <86box/timer.h> @@ -39,6 +41,43 @@ #include <86box/fdd_mfm.h> #include <86box/fdd_td0.h> #include <86box/fdc.h> +#include <86box/sound.h> + +static int16_t *load_wav(const char *filename, int *sample_count); + +// TODO: +// 1. Implement spindle motor spin-up and spin-down +// 2. Implement sound support for all drives (not only for drive 0) + +static int16_t *spindlemotor_wav = NULL; +static int spindlemotor_wav_samples = 0; +static char *spindlemotor_wav_filename = "mitsumi_spindle_motor_loop_48000_16_1_PCM.wav"; +static int16_t *steptrackup_wav[80]; +static int steptrackup_wav_samples[80]; +static int16_t *steptrackdown_wav[80]; +static int steptrackdown_wav_samples[80]; +static int16_t *seekmultipletracks_wav[79]; // Seek 2, 3, 4 ... 80 tracks = 79 sounds +static int seekmultipletracks_wav_samples[79]; + +static int spindlemotor_pos[FDD_NUM] = {}; +static int spindlemotor_playing[FDD_NUM] = {}; + +// WAV-header +typedef struct { + char riff[4]; + uint32_t size; + char wave[4]; + char fmt[4]; + uint32_t fmt_size; + uint16_t audio_format; + uint16_t num_channels; + uint32_t sample_rate; + uint32_t byte_rate; + uint16_t block_align; + uint16_t bits_per_sample; + char data[4]; + uint32_t data_size; +} wav_header_t; /* Flags: Bit 0: 300 rpm supported; @@ -461,8 +500,6 @@ fdd_load(int drive, char *fn) FILE *fp; int offs = 0; - fdd_log("FDD: loading drive %d with '%s'\n", drive, fn); - if (!fn) return; if (strstr(fn, "wp://") == fn) { @@ -495,7 +532,6 @@ fdd_load(int drive, char *fn) c++; } } - fdd_log("FDD: could not load '%s' %s\n", fn, p); drive_empty[drive] = 1; fdd_set_head(drive, 0); memset(floppyfns[drive], 0, sizeof(floppyfns[drive])); @@ -505,8 +541,6 @@ fdd_load(int drive, char *fn) void fdd_close(int drive) { - fdd_log("FDD: closing drive %d\n", drive); - d86f_stop(drive); /* Call this first of all to make sure the 86F poll is back to idle state. */ if (loaders[driveloaders[drive]].close) loaders[driveloaders[drive]].close(drive); @@ -548,11 +582,16 @@ fdd_byteperiod(int drive) void fdd_set_motor_enable(int drive, int motor_enable) { - /* I think here is where spin-up and spin-down should be implemented. */ - if (motor_enable && !motoron[drive]) + if (motor_enable && !motoron[drive]) { + // Motor starting up + spindlemotor_pos[drive] = 0; + spindlemotor_playing[drive] = 1; timer_set_delay_u64(&fdd_poll_time[drive], fdd_byteperiod(drive)); - else if (!motor_enable) + } else if (!motor_enable) { + // Motor stopping + spindlemotor_playing[drive] = 0; timer_disable(&fdd_poll_time[drive]); + } motoron[drive] = motor_enable; } @@ -675,10 +714,14 @@ fdd_init(void) { int i; + spindlemotor_wav = load_wav(spindlemotor_wav_filename, &spindlemotor_wav_samples); + for (i = 0; i < FDD_NUM; i++) { drives[i].poll = 0; drives[i].seek = 0; drives[i].readsector = 0; + spindlemotor_pos[i] = 0; + spindlemotor_playing[i] = 0; } img_init(); @@ -690,6 +733,8 @@ fdd_init(void) for (i = 0; i < FDD_NUM; i++) { fdd_load(i, floppyfns[i]); } + + sound_fdd_thread_init(); } void @@ -697,3 +742,113 @@ fdd_do_writeback(int drive) { d86f_handler[drive].writeback(drive); } + +static int16_t * +load_wav(const char *filename, int *sample_count) +{ + FILE *f = fopen(filename, "rb"); + + if (!f) { + return NULL; + } + + wav_header_t hdr; + if (fread(&hdr, sizeof(hdr), 1, f) != 1) { + 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)) { + 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)) { + 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); + } else { + // Already stereo + output_data = input_data; + output_samples = input_samples / 2; // Number of stereo sample pairs + } + + if (sample_count) + *sample_count = output_samples; + + return output_data; +} + +void +fdd_audio_callback(int16_t *buffer, int length) +{ + // Clear buffer + memset(buffer, 0, length * sizeof(int16_t)); + + // Check if any motor is running + int any_motor_running = 0; + for (int drive = 0; drive < FDD_NUM; drive++) { + if (motoron[drive]) { + any_motor_running = 1; + } + } + + float *float_buffer = (float*)buffer; + int samples_in_buffer = length / 2; + + if (any_motor_running && spindlemotor_wav && spindlemotor_wav_samples > 0) { + for (int i = 0; i < samples_in_buffer; i++) { + // Only for fdd0 + int wav_pos = spindlemotor_pos[0]; + + // int16 -> float conversion + float left_sample = (float)spindlemotor_wav[wav_pos * 2] / 32768.0f; + float right_sample = (float)spindlemotor_wav[wav_pos * 2 + 1] / 32768.0f; + + float_buffer[i * 2] = left_sample; + float_buffer[i * 2 + 1] = right_sample; + + spindlemotor_pos[0]++; + + // Loop back to beginning for sample, when end is reached + if (spindlemotor_pos[0] >= spindlemotor_wav_samples) { + spindlemotor_pos[0] = 0; + } + } + } +} \ No newline at end of file diff --git a/src/include/86box/fdd.h b/src/include/86box/fdd.h index d6ade3bc6..ee3b7056a 100644 --- a/src/include/86box/fdd.h +++ b/src/include/86box/fdd.h @@ -109,6 +109,7 @@ extern void fdd_format(int drive, int side, int density, uint8_t fill); extern int fdd_hole(int drive); extern void fdd_stop(int drive); extern void fdd_do_writeback(int drive); +extern void fdd_audio_callback(int16_t *buffer, int length); extern int motorspin; extern uint64_t motoron[FDD_NUM]; diff --git a/src/include/86box/sound.h b/src/include/86box/sound.h index 5f91ec9d0..ad761dbd6 100644 --- a/src/include/86box/sound.h +++ b/src/include/86box/sound.h @@ -103,12 +103,16 @@ extern void sound_card_reset(void); extern void sound_cd_thread_end(void); extern void sound_cd_thread_reset(void); +extern void sound_fdd_thread_init(void); +extern void sound_fdd_thread_end(void); + extern void closeal(void); extern void inital(void); extern void givealbuffer(const void *buf); extern void givealbuffer_music(const void *buf); extern void givealbuffer_wt(const void *buf); extern void givealbuffer_cd(const void *buf); +extern void givealbuffer_fdd(const void *buf, const uint32_t size); #define sb_vibra16c_onboard_relocate_base sb_vibra16s_onboard_relocate_base #define sb_vibra16cl_onboard_relocate_base sb_vibra16s_onboard_relocate_base diff --git a/src/out/build/x64-Debug/.cmake/api/v1/query/client-MicrosoftVS/query.json b/src/out/build/x64-Debug/.cmake/api/v1/query/client-MicrosoftVS/query.json new file mode 100644 index 000000000..7d776af01 --- /dev/null +++ b/src/out/build/x64-Debug/.cmake/api/v1/query/client-MicrosoftVS/query.json @@ -0,0 +1 @@ +{"requests":[{"kind":"cache","version":2},{"kind":"cmakeFiles","version":1},{"kind":"codemodel","version":2},{"kind":"toolchains","version":1}]} \ No newline at end of file diff --git a/src/out/build/x64-Debug/VSInheritEnvironments.txt b/src/out/build/x64-Debug/VSInheritEnvironments.txt new file mode 100644 index 000000000..f8cc9d8ac --- /dev/null +++ b/src/out/build/x64-Debug/VSInheritEnvironments.txt @@ -0,0 +1 @@ +msvc_x64_x64 \ No newline at end of file diff --git a/src/sound/audio4.c b/src/sound/audio4.c index 4e74d2c0c..a53deffb4 100644 --- a/src/sound/audio4.c +++ b/src/sound/audio4.c @@ -38,14 +38,15 @@ #define I_WT 2 #define I_CD 3 #define I_MIDI 4 +#define I_FDD 5 -static int audio[5] = {-1, -1, -1, -1, -1}; +static int audio[6] = {-1, -1, -1, -1, -1, -1}; #ifdef USE_NEW_API static struct audio_swpar info[5]; #else -static audio_info_t info[5]; +static audio_info_t info[6]; #endif -static int freqs[5] = {SOUND_FREQ, MUSIC_FREQ, WT_FREQ, CD_FREQ, 0}; +static int freqs[6] = {SOUND_FREQ, MUSIC_FREQ, WT_FREQ, CD_FREQ, SOUND_FREQ, 0}; void closeal(void){ int i; @@ -152,6 +153,11 @@ void givealbuffer_wt(const void *buf){ void givealbuffer_cd(const void *buf){ givealbuffer_common(buf, I_CD, CD_BUFLEN << 1); } + +void givealbuffer_fdd(const void *buf, const uint32_t size){ + givealbuffer_common(buf, I_FDD, (int) size); +} + void givealbuffer_midi(const void *buf, const uint32_t size){ givealbuffer_common(buf, I_MIDI, (int) size); } diff --git a/src/sound/openal.c b/src/sound/openal.c index 90f626362..ca6cd54a8 100644 --- a/src/sound/openal.c +++ b/src/sound/openal.c @@ -41,8 +41,9 @@ ALuint buffers[4]; /* front and back buffers */ ALuint buffers_music[4]; /* front and back buffers */ ALuint buffers_wt[4]; /* front and back buffers */ ALuint buffers_cd[4]; /* front and back buffers */ +ALuint buffers_fdd[4]; /* front and back buffers */ ALuint buffers_midi[4]; /* front and back buffers */ -static ALuint source[5]; /* audio source */ +static ALuint source[6]; /* audio source - CHANGED FROM 5 TO 6 */ static int midi_freq = 44100; static int midi_buf_size = 4410; @@ -99,8 +100,9 @@ closeal(void) alSourceStopv(sources, source); alDeleteSources(sources, source); - if (sources == 4) + if (sources >= 6) alDeleteBuffers(4, buffers_midi); + alDeleteBuffers(4, buffers_fdd); alDeleteBuffers(4, buffers_cd); alDeleteBuffers(4, buffers_music); alDeleteBuffers(4, buffers); @@ -118,13 +120,15 @@ inital(void) float *wt_buf = NULL; float *cd_buf = NULL; float *midi_buf = NULL; + float *fdd_buf = NULL; int16_t *buf_int16 = NULL; int16_t *music_buf_int16 = NULL; int16_t *wt_buf_int16 = NULL; int16_t *cd_buf_int16 = NULL; int16_t *midi_buf_int16 = NULL; + int16_t *fdd_buf_int16 = NULL; - int init_midi = 0; + int init_midi = 0; if (initialized) return; @@ -136,13 +140,14 @@ inital(void) if ((strcmp(mdn, "none") != 0) && (strcmp(mdn, SYSTEM_MIDI_INTERNAL_NAME) != 0)) init_midi = 1; /* If the device is neither none, nor system MIDI, initialize the MIDI buffer and source, otherwise, do not. */ - sources = 4 + !!init_midi; + sources = 5 + !!init_midi; if (sound_is_float) { buf = (float *) calloc((BUFLEN << 1), sizeof(float)); music_buf = (float *) calloc((MUSICBUFLEN << 1), sizeof(float)); wt_buf = (float *) calloc((WTBUFLEN << 1), sizeof(float)); cd_buf = (float *) calloc((CD_BUFLEN << 1), sizeof(float)); + fdd_buf = (float *) calloc((BUFLEN << 1), sizeof(float)); if (init_midi) midi_buf = (float *) calloc(midi_buf_size, sizeof(float)); } else { @@ -150,48 +155,29 @@ inital(void) music_buf_int16 = (int16_t *) calloc((MUSICBUFLEN << 1), sizeof(int16_t)); wt_buf_int16 = (int16_t *) calloc((WTBUFLEN << 1), sizeof(int16_t)); cd_buf_int16 = (int16_t *) calloc((CD_BUFLEN << 1), sizeof(int16_t)); + fdd_buf_int16 = (int16_t *) calloc((BUFLEN << 1), sizeof(int16_t)); if (init_midi) midi_buf_int16 = (int16_t *) calloc(midi_buf_size, sizeof(int16_t)); } alGenBuffers(4, buffers); alGenBuffers(4, buffers_cd); + alGenBuffers(4, buffers_fdd); alGenBuffers(4, buffers_music); alGenBuffers(4, buffers_wt); if (init_midi) alGenBuffers(4, buffers_midi); - if (init_midi) - alGenSources(5, source); - else - alGenSources(4, source); + // Create sources: 0=main, 1=music, 2=wt, 3=cd, 4=fdd, 5=midi(optional) + alGenSources(sources, source); - alSource3f(source[0], AL_POSITION, 0.0f, 0.0f, 0.0f); - alSource3f(source[0], AL_VELOCITY, 0.0f, 0.0f, 0.0f); - alSource3f(source[0], AL_DIRECTION, 0.0f, 0.0f, 0.0f); - alSourcef(source[0], AL_ROLLOFF_FACTOR, 0.0f); - alSourcei(source[0], AL_SOURCE_RELATIVE, AL_TRUE); - alSource3f(source[1], AL_POSITION, 0.0f, 0.0f, 0.0f); - alSource3f(source[1], AL_VELOCITY, 0.0f, 0.0f, 0.0f); - alSource3f(source[1], AL_DIRECTION, 0.0f, 0.0f, 0.0f); - alSourcef(source[1], AL_ROLLOFF_FACTOR, 0.0f); - alSourcei(source[1], AL_SOURCE_RELATIVE, AL_TRUE); - alSource3f(source[2], AL_POSITION, 0.0f, 0.0f, 0.0f); - alSource3f(source[2], AL_VELOCITY, 0.0f, 0.0f, 0.0f); - alSource3f(source[2], AL_DIRECTION, 0.0f, 0.0f, 0.0f); - alSourcef(source[2], AL_ROLLOFF_FACTOR, 0.0f); - alSourcei(source[2], AL_SOURCE_RELATIVE, AL_TRUE); - alSource3f(source[3], AL_POSITION, 0.0f, 0.0f, 0.0f); - alSource3f(source[3], AL_VELOCITY, 0.0f, 0.0f, 0.0f); - alSource3f(source[3], AL_DIRECTION, 0.0f, 0.0f, 0.0f); - alSourcef(source[3], AL_ROLLOFF_FACTOR, 0.0f); - alSourcei(source[3], AL_SOURCE_RELATIVE, AL_TRUE); - if (init_midi) { - alSource3f(source[4], AL_POSITION, 0.0f, 0.0f, 0.0f); - alSource3f(source[4], AL_VELOCITY, 0.0f, 0.0f, 0.0f); - alSource3f(source[4], AL_DIRECTION, 0.0f, 0.0f, 0.0f); - alSourcef(source[4], AL_ROLLOFF_FACTOR, 0.0f); - alSourcei(source[4], AL_SOURCE_RELATIVE, AL_TRUE); + // Initialize all sources + for (int i = 0; i < sources; i++) { + alSource3f(source[i], AL_POSITION, 0.0f, 0.0f, 0.0f); + alSource3f(source[i], AL_VELOCITY, 0.0f, 0.0f, 0.0f); + alSource3f(source[i], AL_DIRECTION, 0.0f, 0.0f, 0.0f); + alSourcef(source[i], AL_ROLLOFF_FACTOR, 0.0f); + alSourcei(source[i], AL_SOURCE_RELATIVE, AL_TRUE); } if (sound_is_float) { @@ -199,6 +185,7 @@ inital(void) memset(cd_buf, 0, CD_BUFLEN * 2 * sizeof(float)); memset(music_buf, 0, MUSICBUFLEN * 2 * sizeof(float)); memset(wt_buf, 0, WTBUFLEN * 2 * sizeof(float)); + memset(fdd_buf, 0, BUFLEN * 2 * sizeof(float)); if (init_midi) memset(midi_buf, 0, midi_buf_size * sizeof(float)); } else { @@ -206,6 +193,7 @@ inital(void) memset(cd_buf_int16, 0, CD_BUFLEN * 2 * sizeof(int16_t)); memset(music_buf_int16, 0, MUSICBUFLEN * 2 * sizeof(int16_t)); memset(wt_buf_int16, 0, WTBUFLEN * 2 * sizeof(int16_t)); + memset(fdd_buf_int16, 0, BUFLEN * 2 * sizeof(int16_t)); if (init_midi) memset(midi_buf_int16, 0, midi_buf_size * sizeof(int16_t)); } @@ -216,6 +204,7 @@ inital(void) alBufferData(buffers_music[c], AL_FORMAT_STEREO_FLOAT32, music_buf, MUSICBUFLEN * 2 * sizeof(float), MUSIC_FREQ); alBufferData(buffers_wt[c], AL_FORMAT_STEREO_FLOAT32, wt_buf, WTBUFLEN * 2 * sizeof(float), WT_FREQ); alBufferData(buffers_cd[c], AL_FORMAT_STEREO_FLOAT32, cd_buf, CD_BUFLEN * 2 * sizeof(float), CD_FREQ); + alBufferData(buffers_fdd[c], AL_FORMAT_STEREO_FLOAT32, fdd_buf, BUFLEN * 2 * sizeof(float), FREQ); if (init_midi) alBufferData(buffers_midi[c], AL_FORMAT_STEREO_FLOAT32, midi_buf, midi_buf_size * (int) sizeof(float), midi_freq); } else { @@ -223,6 +212,7 @@ inital(void) alBufferData(buffers_music[c], AL_FORMAT_STEREO16, music_buf_int16, MUSICBUFLEN * 2 * sizeof(int16_t), MUSIC_FREQ); alBufferData(buffers_wt[c], AL_FORMAT_STEREO16, wt_buf_int16, WTBUFLEN * 2 * sizeof(int16_t), WT_FREQ); alBufferData(buffers_cd[c], AL_FORMAT_STEREO16, cd_buf_int16, CD_BUFLEN * 2 * sizeof(int16_t), CD_FREQ); + alBufferData(buffers_fdd[c], AL_FORMAT_STEREO16, fdd_buf_int16, BUFLEN * 2 * sizeof(int16_t), FREQ); if (init_midi) alBufferData(buffers_midi[c], AL_FORMAT_STEREO16, midi_buf_int16, midi_buf_size * (int) sizeof(int16_t), midi_freq); } @@ -232,14 +222,17 @@ inital(void) alSourceQueueBuffers(source[1], 4, buffers_music); alSourceQueueBuffers(source[2], 4, buffers_wt); alSourceQueueBuffers(source[3], 4, buffers_cd); + alSourceQueueBuffers(source[4], 4, buffers_fdd); if (init_midi) - alSourceQueueBuffers(source[4], 4, buffers_midi); + alSourceQueueBuffers(source[5], 4, buffers_midi); + alSourcePlay(source[0]); alSourcePlay(source[1]); alSourcePlay(source[2]); alSourcePlay(source[3]); + alSourcePlay(source[4]); if (init_midi) - alSourcePlay(source[4]); + alSourcePlay(source[5]); if (sound_is_float) { if (init_midi) @@ -248,6 +241,7 @@ inital(void) free(wt_buf); free(music_buf); free(buf); + free(fdd_buf); } else { if (init_midi) free(midi_buf_int16); @@ -255,6 +249,7 @@ inital(void) free(wt_buf_int16); free(music_buf_int16); free(buf_int16); + free(fdd_buf_int16); } initialized = 1; @@ -319,5 +314,11 @@ givealbuffer_cd(const void *buf) void givealbuffer_midi(const void *buf, const uint32_t size) { - givealbuffer_common(buf, 4, (int) size, midi_freq); + givealbuffer_common(buf, 5, (int) size, midi_freq); } + +void +givealbuffer_fdd(const void *buf, const uint32_t size) +{ + givealbuffer_common(buf, 4, (int) size, FREQ); +} \ No newline at end of file diff --git a/src/sound/sndio.c b/src/sound/sndio.c index 2fe1434df..f6248dd6a 100644 --- a/src/sound/sndio.c +++ b/src/sound/sndio.c @@ -19,7 +19,6 @@ #include #include #include - #include #include <86box/86box.h> @@ -31,10 +30,11 @@ #define I_WT 2 #define I_CD 3 #define I_MIDI 4 +#define I_FDD 5 -static struct sio_hdl* audio[5] = {NULL, NULL, NULL, NULL, NULL}; -static struct sio_par info[5]; -static int freqs[5] = {SOUND_FREQ, MUSIC_FREQ, WT_FREQ, CD_FREQ, 0}; +static struct sio_hdl* audio[6] = {NULL, NULL, NULL, NULL, NULL, NULL}; +static struct sio_par info[6]; +static int freqs[6] = { SOUND_FREQ, MUSIC_FREQ, WT_FREQ, CD_FREQ, SOUND_FREQ, 0 }; void closeal(void){ int i; @@ -131,9 +131,14 @@ void givealbuffer_wt(const void *buf){ void givealbuffer_cd(const void *buf){ givealbuffer_common(buf, I_CD, CD_BUFLEN << 1); } + void givealbuffer_midi(const void *buf, const uint32_t size){ givealbuffer_common(buf, I_MIDI, (int) size); } + +void givealbuffer_fdd(const void *buf, const uint32_t size) { + givealbuffer_common(buf, I_FDD, (int) size); +} void al_set_midi(const int freq, UNUSED(const int buf_size)){ freqs[I_MIDI] = freq; diff --git a/src/sound/sound.c b/src/sound/sound.c index c81dc47b0..eb18f9302 100644 --- a/src/sound/sound.c +++ b/src/sound/sound.c @@ -38,6 +38,7 @@ #include <86box/timer.h> #include <86box/snd_mpu401.h> #include <86box/sound.h> +#include <86box/fdd.h> typedef struct { const device_t *device; @@ -55,7 +56,6 @@ int wavetable_pos_global = 0; int sound_gain = 0; static sound_handler_t sound_handlers[8]; - static sound_handler_t music_handlers[8]; static sound_handler_t wavetable_handlers[8]; @@ -92,6 +92,13 @@ static int cd_buf_update = CD_BUFLEN / SOUNDBUFLEN; static volatile int cdaudioon = 0; static int cd_thread_enable = 0; +static thread_t *sound_fdd_thread_h; +static event_t *sound_fdd_event; +static event_t *sound_fdd_start_event; +static int16_t fdd_out_buffer[SOUNDBUFLEN * 2]; +static volatile int fddaudioon = 0; +static int fdd_thread_enable = 0; + static void (*filter_cd_audio)(int channel, double *buffer, void *priv) = NULL; static void *filter_cd_audio_p = NULL; @@ -595,6 +602,9 @@ sound_poll(UNUSED(void *priv)) } } + if (fdd_thread_enable) { + thread_set_event(sound_fdd_event); + } sound_pos_global = 0; } } @@ -696,17 +706,14 @@ sound_reset(void) inital(); timer_add(&sound_poll_timer, sound_poll, NULL, 1); - sound_handlers_num = 0; memset(sound_handlers, 0x00, 8 * sizeof(sound_handler_t)); timer_add(&music_poll_timer, music_poll, NULL, 1); - music_handlers_num = 0; memset(music_handlers, 0x00, 8 * sizeof(sound_handler_t)); timer_add(&wavetable_poll_timer, wavetable_poll, NULL, 1); - wavetable_handlers_num = 0; memset(wavetable_handlers, 0x00, 8 * sizeof(sound_handler_t)); @@ -783,3 +790,67 @@ sound_cd_thread_reset(void) cd_thread_enable = available_cdrom_drives ? 1 : 0; } + +static void +sound_fdd_clean_buffers(void) +{ + memset(fdd_out_buffer, 0, SOUNDBUFLEN * 2); +} + +static void +sound_fdd_thread(UNUSED(void *param)) +{ + thread_set_event(sound_fdd_start_event); + while (fddaudioon) { + thread_wait_event(sound_fdd_event, -1); + thread_reset_event(sound_fdd_event); + + if (!fddaudioon) + break; + + static float fdd_float_buffer[SOUNDBUFLEN * 2]; + memset(fdd_float_buffer, 0, sizeof(fdd_float_buffer)); + fdd_audio_callback((int16_t*)fdd_float_buffer, SOUNDBUFLEN * 2); + givealbuffer_fdd(fdd_float_buffer, SOUNDBUFLEN * 2); + } +} + +void +sound_fdd_thread_init(void) +{ + if (!fddaudioon) { + fddaudioon = 1; + fdd_thread_enable = 1; + + sound_fdd_start_event = thread_create_event(); + sound_fdd_event = thread_create_event(); + sound_fdd_thread_h = thread_create(sound_fdd_thread, NULL); + + thread_wait_event(sound_fdd_start_event, -1); + thread_reset_event(sound_fdd_start_event); + } +} + +void +sound_fdd_thread_end(void) +{ + if (fddaudioon) { + fddaudioon = 0; + fdd_thread_enable = 0; + + thread_set_event(sound_fdd_event); + thread_wait(sound_fdd_thread_h); + + if (sound_fdd_event) { + thread_destroy_event(sound_fdd_event); + sound_fdd_event = NULL; + } + + sound_fdd_thread_h = NULL; + + if (sound_fdd_start_event) { + thread_destroy_event(sound_fdd_start_event); + sound_fdd_start_event = NULL; + } + } +} \ No newline at end of file diff --git a/src/sound/xaudio2.c b/src/sound/xaudio2.c index 2aee97efc..5b0cc0720 100644 --- a/src/sound/xaudio2.c +++ b/src/sound/xaudio2.c @@ -55,6 +55,7 @@ static IXAudio2SourceVoice *srcvoicemusic = NULL; static IXAudio2SourceVoice *srcvoicewt = NULL; static IXAudio2SourceVoice *srcvoicemidi = NULL; static IXAudio2SourceVoice *srcvoicecd = NULL; +static IXAudio2SourceVoice *srcvoicefdd = NULL; #define FREQ SOUND_FREQ #define BUFLEN SOUNDBUFLEN @@ -184,11 +185,18 @@ inital(void) (void) IXAudio2_CreateSourceVoice(xaudio2, &srcvoicecd, &fmt, 0, 2.0f, &callbacks, NULL, NULL); + fmt.nSamplesPerSec = FREQ; + fmt.nBlockAlign = fmt.nChannels * fmt.wBitsPerSample / 8; + fmt.nAvgBytesPerSec = fmt.nSamplesPerSec * fmt.nBlockAlign; + + (void) IXAudio2_CreateSourceVoice(xaudio2, &srcvoicefdd, &fmt, 0, 2.0f, &callbacks, NULL, NULL); + (void) IXAudio2SourceVoice_SetVolume(srcvoice, 1, XAUDIO2_COMMIT_NOW); (void) IXAudio2SourceVoice_Start(srcvoice, 0, XAUDIO2_COMMIT_NOW); (void) IXAudio2SourceVoice_Start(srcvoicecd, 0, XAUDIO2_COMMIT_NOW); (void) IXAudio2SourceVoice_Start(srcvoicemusic, 0, XAUDIO2_COMMIT_NOW); (void) IXAudio2SourceVoice_Start(srcvoicewt, 0, XAUDIO2_COMMIT_NOW); + (void) IXAudio2SourceVoice_Start(srcvoicefdd, 0, XAUDIO2_COMMIT_NOW); const char *mdn = midi_out_device_get_internal_name(midi_output_device_current); @@ -218,6 +226,8 @@ closeal(void) (void) IXAudio2SourceVoice_FlushSourceBuffers(srcvoicewt); (void) IXAudio2SourceVoice_Stop(srcvoicecd, 0, XAUDIO2_COMMIT_NOW); (void) IXAudio2SourceVoice_FlushSourceBuffers(srcvoicecd); + (void) IXAudio2SourceVoice_Stop(srcvoicefdd, 0, XAUDIO2_COMMIT_NOW); + (void) IXAudio2SourceVoice_FlushSourceBuffers(srcvoicefdd); if (srcvoicemidi) { (void) IXAudio2SourceVoice_Stop(srcvoicemidi, 0, XAUDIO2_COMMIT_NOW); (void) IXAudio2SourceVoice_FlushSourceBuffers(srcvoicemidi); @@ -225,13 +235,14 @@ closeal(void) } IXAudio2SourceVoice_DestroyVoice(srcvoicewt); IXAudio2SourceVoice_DestroyVoice(srcvoicecd); + IXAudio2SourceVoice_DestroyVoice(srcvoicefdd); IXAudio2SourceVoice_DestroyVoice(srcvoicemusic); IXAudio2SourceVoice_DestroyVoice(srcvoice); IXAudio2MasteringVoice_DestroyVoice(mastervoice); IXAudio2_Release(xaudio2); - srcvoice = srcvoicecd = srcvoicemidi = NULL; - mastervoice = NULL; - xaudio2 = NULL; + srcvoice = srcvoicecd = srcvoicemidi = srcvoicefdd = NULL; + mastervoice = NULL; + xaudio2 = NULL; #if defined(_WIN32) && !defined(USE_FAUDIO) dynld_close(xaudio2_handle); @@ -291,6 +302,18 @@ givealbuffer_cd(const void *buf) givealbuffer_common(buf, srcvoicecd, CD_BUFLEN << 1); } +void +givealbuffer_fdd(const void *buf, const uint32_t size) +{ + if (!initialized) + return; + + if (!srcvoicefdd) + return; + + givealbuffer_common(buf, srcvoicefdd, size); +} + void al_set_midi(const int freq, const int buf_size) { @@ -324,4 +347,4 @@ void givealbuffer_midi(const void *buf, const uint32_t size) { givealbuffer_common(buf, srcvoicemidi, size); -} +} \ No newline at end of file