From d5f4376d03b3ee52479acd1181a071e8cd4631f3 Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Wed, 18 Sep 2024 22:54:47 -0700 Subject: [PATCH 01/63] First iteration of MIDI synth support --- .github/workflows/build.yml | 14 +- Makefile | 2 +- src/main.c | 16 ++ src/memory.c | 6 + src/midi.c | 296 ++++++++++++++++++++++++++++++++++++ src/midi.h | 14 ++ 6 files changed, 340 insertions(+), 8 deletions(-) create mode 100644 src/midi.c create mode 100644 src/midi.h diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c90be6b..712b490 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -40,7 +40,7 @@ jobs: with: msystem: MINGW64 update: true - install: make git mingw-w64-x86_64-toolchain mingw-w64-x86_64-libelf mingw-w64-x86_64-SDL2 + install: make git mingw-w64-x86_64-toolchain mingw-w64-x86_64-libelf mingw-w64-x86_64-SDL2 mingw-w64-x86_64-fluidsynth - uses: actions/setup-python@v5 with: python-version: '3.9' @@ -103,7 +103,7 @@ jobs: with: msystem: MINGW64 update: true - install: make git mingw-w64-i686-toolchain mingw-w64-i686-libelf mingw-w64-i686-SDL2 + install: make git mingw-w64-i686-toolchain mingw-w64-i686-libelf mingw-w64-i686-SDL2 mingw-w64-i686-fluidsynth path-type: inherit - uses: actions/setup-python@v5 with: @@ -165,7 +165,7 @@ jobs: with: python-version: '3.9' - name: Install Dependencies - run: sudo apt-get update && sudo apt-get install -y build-essential make libsdl2-dev + run: sudo apt-get update && sudo apt-get install -y build-essential make libsdl2-dev libfluidsynth-dev - name: Fetch latest ROM if: startsWith(github.ref, 'refs/tags/r') != true run: | @@ -241,7 +241,7 @@ jobs: copy_artifact_path: emu_binaries commands: | apt-get update - apt-get install -y build-essential make libsdl2-dev file git + apt-get install -y build-essential make libsdl2-dev file git libfluidsynth-dev TRACE=1 make V=1 -j3 mkdir emu_binaries cp sdcard.img.zip emu_binaries/. @@ -301,7 +301,7 @@ jobs: copy_artifact_path: emu_binaries commands: | apt-get update - apt-get install -y build-essential make libsdl2-dev file git + apt-get install -y build-essential make libsdl2-dev file git libfluidsynth-dev TRACE=1 make V=1 -j3 mkdir emu_binaries cp sdcard.img.zip emu_binaries/. @@ -333,7 +333,7 @@ jobs: - uses: actions/checkout@v4 - name: Install Dependencies run: | - brew install make sdl2 + brew install make sdl2 fluid-synth - uses: actions/setup-python@v5 with: python-version: '3.9' @@ -383,7 +383,7 @@ jobs: - uses: actions/checkout@v4 - name: Install Dependencies run: | - brew install make sdl2 + brew install make sdl2 fluid-synth - uses: actions/setup-python@v5 with: python-version: '3.10' diff --git a/Makefile b/Makefile index c62a088..311b71d 100644 --- a/Makefile +++ b/Makefile @@ -74,7 +74,7 @@ ifdef EMSCRIPTEN MAKECART_OUTPUT=makecart.html endif -_X16_OBJS = cpu/fake6502.o memory.o disasm.o video.o i2c.o smc.o rtc.o via.o serial.o ieee.o vera_spi.o audio.o vera_pcm.o vera_psg.o sdcard.o main.o debugger.o javascript_interface.o joystick.o rendertext.o keyboard.o icon.o timing.o wav_recorder.o testbench.o files.o cartridge.o iso_8859_15.o ymglue.o +_X16_OBJS = cpu/fake6502.o memory.o disasm.o video.o i2c.o smc.o rtc.o via.o serial.o ieee.o vera_spi.o audio.o vera_pcm.o vera_psg.o sdcard.o main.o debugger.o javascript_interface.o joystick.o rendertext.o keyboard.o icon.o timing.o wav_recorder.o testbench.o files.o cartridge.o iso_8859_15.o ymglue.o midi.o _X16_OBJS += extern/ymfm/src/ymfm_opm.o ifdef TARGET_WIN32 diff --git a/src/main.c b/src/main.c index b7b0a1f..f88cd5f 100644 --- a/src/main.c +++ b/src/main.c @@ -42,6 +42,7 @@ #include "wav_recorder.h" #include "testbench.h" #include "cartridge.h" +#include "midi.h" #ifdef __EMSCRIPTEN__ #include @@ -556,6 +557,7 @@ main(int argc, char **argv) char *rom_path = rom_path_data; char *prg_path = NULL; char *bas_path = NULL; + char *sf2_path = NULL; char *sdcard_path = NULL; bool run_test = false; int test_number = 0; @@ -630,6 +632,15 @@ main(int argc, char **argv) prg_path = argv[0]; argc--; argv++; + } else if (!strcmp(argv[0], "-sf2")) { + argc--; + argv++; + if (!argc || argv[0][0] == '-') { + usage(); + } + sf2_path = argv[0]; + argc--; + argv++; } else if (!strcmp(argv[0], "-run")) { argc--; argv++; @@ -1088,6 +1099,11 @@ main(int argc, char **argv) #endif } + if (sf2_path) { + midi_init(); + midi_load_sf2((uint8_t *)sf2_path); + } + if (cartridge_path) { if (!cartridge_load(cartridge_path, !zeroram)) { printf("Cannot open %s!\n", cartridge_path); diff --git a/src/memory.c b/src/memory.c index 5826d13..5f5d726 100644 --- a/src/memory.c +++ b/src/memory.c @@ -18,6 +18,7 @@ #include "audio.h" #include "cartridge.h" #include "iso_8859_15.h" +#include "midi.h" uint8_t ram_bank; uint8_t rom_bank; @@ -197,6 +198,9 @@ real_read6502(uint16_t address, bool debugOn, int16_t bank) return YM_read_status(); } return 0x9f; // open bus read + } else if (address >= 0x9f60 && address < 0x9f70) { + // midi card + return midi_serial_read(address & 0x7, debugOn); } else if (address >= 0x9fb0 && address < 0x9fc0) { // emulator state return emu_read(address & 0xf, debugOn); @@ -274,6 +278,8 @@ write6502(uint16_t address, uint8_t value) audio_render(); YM_write_reg(addr_ym, value); } + } else if (address >= 0x9f60 && address < 0x9f70) { + midi_serial_write(address & 0x7, value); } else if (address >= 0x9fb0 && address < 0x9fc0) { // emulator state emu_write(address & 0xf, value); diff --git a/src/midi.c b/src/midi.c new file mode 100644 index 0000000..863e633 --- /dev/null +++ b/src/midi.c @@ -0,0 +1,296 @@ +// Commander X16 Emulator +// Copyright (c) 2024 MooingLemur +// All rights reserved. License: 2-clause BSD + +#include "glue.h" +#include "midi.h" + +#ifndef __EMSCRIPTEN__ + +#ifdef _WIN32 + #include + #define LIBRARY_TYPE HMODULE + #define LOAD_LIBRARY(name) LoadLibrary(name) + #define GET_FUNCTION(lib, name) GetProcAddress(lib, name) + #define CLOSE_LIBRARY(lib) FreeLibrary(lib) +#else + #include + #define LIBRARY_TYPE void* + #define LOAD_LIBRARY(name) dlopen(name, RTLD_LAZY) + #define GET_FUNCTION(lib, name) dlsym(lib, name) + #define CLOSE_LIBRARY(lib) dlclose(lib) +#endif + +#define ASSIGN_FUNCTION(lib, var, name) {\ + var = GET_FUNCTION(lib, name);\ + if (!var) { fprintf(stderr, "Unable to find symbol for '%s'\n", name); CLOSE_LIBRARY(handle); return; }\ +} + +enum MIDI_states { + NORMAL, + PARAM, + SYSEX, +}; + +static bool midi_initialized = false; + +static fluid_settings_t* fl_settings; +//static fluid_midi_driver_t* fl_mdriver; +static fluid_audio_driver_t* fl_adriver; +static fluid_synth_t* fl_synth; +static int fl_sf2id; + +static uint8_t sysex_buffer[1024]; +static int sysex_bufptr; + +static enum MIDI_states midi_state = NORMAL; +static uint8_t midi_last_command = 0; +static uint8_t midi_first_param; + +static bool serial_dlab = false; +static uint8_t serial_dll, serial_dlm, serial_spr; + +typedef fluid_settings_t* (*new_fluid_settings_f_t)(void); +typedef fluid_synth_t* (*new_fluid_synth_f_t)(fluid_settings_t*); +typedef fluid_audio_driver_t* (*new_fluid_audio_driver_f_t)(fluid_settings_t*, fluid_synth_t*); +typedef int (*fluid_synth_sfload_f_t)(fluid_synth_t*,const char *,int); +typedef int (*fluid_synth_program_change_f_t)(fluid_synth_t*, int, int); +typedef int (*fluid_synth_channel_pressure_f_t)(fluid_synth_t*, int, int); +typedef int (*fluid_synth_system_reset_f_t)(fluid_synth_t*); +typedef int (*fluid_synth_noteoff_f_t)(fluid_synth_t*, int, int); +typedef int (*fluid_synth_noteon_f_t)(fluid_synth_t*, int, int, int); +typedef int (*fluid_synth_key_pressure_f_t)(fluid_synth_t*, int, int, int); +typedef int (*fluid_synth_cc_f_t)(fluid_synth_t*, int, int, int); +typedef int (*fluid_synth_pitch_bend_f_t)(fluid_synth_t*, int, int); +typedef int (*fluid_synth_sysex_f_t)(fluid_synth_t*, const char*, int, char*, int*, int*, int); + +static new_fluid_settings_f_t dl_new_fluid_settings; +static new_fluid_synth_f_t dl_new_fluid_synth; +static new_fluid_audio_driver_f_t dl_new_fluid_audio_driver; +static fluid_synth_sfload_f_t dl_fs_sfload; +static fluid_synth_program_change_f_t dl_fs_program_change; +static fluid_synth_channel_pressure_f_t dl_fs_channel_pressure; +static fluid_synth_system_reset_f_t dl_fs_system_reset; +static fluid_synth_noteoff_f_t dl_fs_noteoff; +static fluid_synth_noteon_f_t dl_fs_noteon; +static fluid_synth_key_pressure_f_t dl_fs_key_pressure; +static fluid_synth_cc_f_t dl_fs_cc; +static fluid_synth_pitch_bend_f_t dl_fs_pitch_bend; +static fluid_synth_sysex_f_t dl_fs_sysex; + +void midi_init() +{ + + LIBRARY_TYPE handle = LOAD_LIBRARY( +#ifdef _WIN32 + "fluidsynth.dll" +#else + "libfluidsynth.so" +#endif + ); + + if (!handle) { + // Handle the error on both platforms +#ifdef _WIN32 + fprintf(stderr, "Could not load MIDI synth library: error code %lu\n", GetLastError()); +#else + fprintf(stderr, "Could not load MIDI synth library: %s\n", dlerror()); +#endif + return; + } + + ASSIGN_FUNCTION(handle, dl_new_fluid_settings, "new_fluid_settings"); + ASSIGN_FUNCTION(handle, dl_new_fluid_synth, "new_fluid_synth"); + ASSIGN_FUNCTION(handle, dl_new_fluid_audio_driver, "new_fluid_audio_driver"); + ASSIGN_FUNCTION(handle, dl_fs_sfload, "fluid_synth_sfload"); + ASSIGN_FUNCTION(handle, dl_fs_program_change, "fluid_synth_program_change"); + ASSIGN_FUNCTION(handle, dl_fs_channel_pressure, "fluid_synth_channel_pressure"); + ASSIGN_FUNCTION(handle, dl_fs_system_reset, "fluid_synth_system_reset"); + ASSIGN_FUNCTION(handle, dl_fs_noteoff, "fluid_synth_noteoff"); + ASSIGN_FUNCTION(handle, dl_fs_noteon, "fluid_synth_noteon"); + ASSIGN_FUNCTION(handle, dl_fs_key_pressure, "fluid_synth_key_pressure"); + ASSIGN_FUNCTION(handle, dl_fs_cc, "fluid_synth_cc"); + ASSIGN_FUNCTION(handle, dl_fs_pitch_bend, "fluid_synth_pitch_bend"); + ASSIGN_FUNCTION(handle, dl_fs_sysex, "fluid_synth_sysex"); + + fl_settings = dl_new_fluid_settings(); + fl_synth = dl_new_fluid_synth(fl_settings); + fl_adriver = dl_new_fluid_audio_driver(fl_settings, fl_synth); + + midi_initialized = true; + printf("FLUID INIT\n"); +} + +void midi_load_sf2(uint8_t* filename) +{ + if (!midi_initialized) return; + fl_sf2id = dl_fs_sfload(fl_synth, (const char *)filename, true); + if (fl_sf2id == FLUID_FAILED) { + printf("Unable to load soundfont.\n"); + } +} + +// Receive a byte from client +// Store state, or dispatch event +void midi_byte(uint8_t b) +{ + if (!midi_initialized) return; + + switch (midi_state) { + case NORMAL: + if (b < 0x80) { + if ((midi_last_command & 0xf0) == 0xc0) { // patch change + dl_fs_program_change(fl_synth, midi_last_command & 0xf, b); + } else if ((midi_last_command & 0xf0) == 0xd0) { // channel pressure + dl_fs_channel_pressure(fl_synth, midi_last_command & 0xf, b); + } else if (midi_last_command >= 0x80) { // two-param command + midi_first_param = b; + midi_state = PARAM; + } + } else { + if (b < 0xf0) { + midi_last_command = b; + } else if (b == 0xf0) { + sysex_bufptr = 0; + midi_state = SYSEX; + } else if (b == 0xff) { + dl_fs_system_reset(fl_synth); + midi_last_command = 0; + } + } + break; + case PARAM: + switch (midi_last_command & 0xf0) { + case 0x80: // note off + dl_fs_noteoff(fl_synth, midi_last_command & 0xf, midi_first_param); // no release velocity + break; + case 0x90: // note on + if (b == 0) { + dl_fs_noteoff(fl_synth, midi_last_command & 0xf, midi_first_param); + } else { + dl_fs_noteon(fl_synth, midi_last_command & 0xf, midi_first_param, b); + } + break; + case 0xa0: // aftertouch + dl_fs_key_pressure(fl_synth, midi_last_command & 0xf, midi_first_param, b); + break; + case 0xb0: // controller + dl_fs_cc(fl_synth, midi_last_command & 0xf, midi_first_param, b); + break; + case 0xe0: // pitch bend + dl_fs_pitch_bend(fl_synth, midi_last_command & 0xf, ((uint16_t)midi_first_param) | (uint16_t)b << 7); + break; + } + midi_state = NORMAL; + break; + case SYSEX: + if (b == 0xf7) { + sysex_buffer[sysex_bufptr] = 0; + dl_fs_sysex(fl_synth, (const char *)sysex_buffer, sysex_bufptr, NULL, NULL, NULL, 0); + midi_state = NORMAL; + } else { + sysex_buffer[sysex_bufptr++] = b; + } + break; + } +} + +#else +void midi_load_sf2(uint8_t* filename) +{ + // no-op +} + +void midi_init() +{ + printf("No fluidsynth support on WebAssembly.\n"); +} + +void midi_byte(uint8_t b) { + // no-op +} + +#endif + + +uint8_t midi_serial_read(uint8_t reg, bool debugOn) { + //printf("midi_serial_read %d\n", reg); + switch (reg) { + case 0x0: + if (serial_dlab) { + return serial_dll; + } else { + // TODO: RHR + } + break; + case 0x1: + if (serial_dlab) { + return serial_dlm; + } + return 0x00; + // TODO: IER + break; + case 0x2: + return 0x00; + // TODO: ISR + break; + case 0x3: + return 0x03 | ((int)serial_dlab << 7); + // TODO: rest of LCR + break; + case 0x4: + return 0x03; + // TODO: MCR + break; + case 0x5: + return 0x20; + // TODO: LSR + break; + case 0x6: + return 0x00; + // TODO: MSR + break; + case 0x7: + return serial_spr; + break; + } + return 0x00; +} + +void midi_serial_write(uint8_t reg, uint8_t val) { + //printf("midi_serial_write %d %d\n", reg, val); + switch (reg) { + case 0x0: + if (serial_dlab) { + serial_dll = val; + } else { + midi_byte((uint8_t)val); + } + break; + case 0x1: + if (serial_dlab) { + serial_dlm = val; + } + // TODO: IER + break; + case 0x2: + // TODO: FCR + break; + case 0x3: + serial_dlab = (bool)(val >> 7); + // TODO: rest of LCR + break; + case 0x4: + // TODO: MCR + break; + case 0x5: + if (serial_dlab) { + // TODO: PSD + } + break; + case 0x7: + serial_spr = val; + break; + } +} + diff --git a/src/midi.h b/src/midi.h new file mode 100644 index 0000000..5fac2d3 --- /dev/null +++ b/src/midi.h @@ -0,0 +1,14 @@ +// Commander X16 Emulator +// Copyright (c) 2024 MooingLemur +// All rights reserved. License: 2-clause BSD + +#pragma once + +#ifndef __EMSCRIPTEN__ +#include +#endif + +void midi_init(); +uint8_t midi_serial_read(uint8_t reg, bool debugOn); +void midi_serial_write(uint8_t reg, uint8_t val); +void midi_load_sf2(uint8_t* filename); From a3dd97fd06cd19bf498dda4c537e4aa70e92a419 Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Wed, 18 Sep 2024 23:06:46 -0700 Subject: [PATCH 02/63] fix some autobuild issues --- .github/workflows/build.yml | 2 +- Makefile | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 712b490..9122ec3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -404,7 +404,7 @@ jobs: cp latest_rom/*.h src/. - name: Build Emulator run: | - TRACE=1 MAC_STATIC=1 LIBSDL_FILE=/opt/homebrew/Cellar/sdl2/*/lib/libSDL2.a make V=1 -j3 + TRACE=1 MAC_STATIC=1 FLUIDSYNTH_INCLUDE=/opt/homebrew/include/fluid-synth LIBSDL_FILE=/opt/homebrew/Cellar/sdl2/*/lib/libSDL2.a make V=1 -j3 mkdir emu_binaries cp sdcard.img.zip emu_binaries/. cp x16emu emu_binaries/. diff --git a/Makefile b/Makefile index 311b71d..93d0877 100644 --- a/Makefile +++ b/Makefile @@ -18,7 +18,7 @@ endif CFLAGS=-std=c99 -O3 -Wall -Werror -g $(shell $(SDL2CONFIG) --cflags) -Isrc/extern/include CXXFLAGS=-std=c++17 -O3 -Wall -Werror -Isrc/extern/ymfm/src -LDFLAGS=$(shell $(SDL2CONFIG) --libs) -lm -lz +LDFLAGS=$(shell $(SDL2CONFIG) --libs) -lm -lz -ldl # build with link time optimization ifndef NOLTO @@ -43,6 +43,10 @@ GIT_REV=$(shell git diff --quiet && /bin/echo -n $$(git rev-parse --short=8 HEAD CFLAGS+=-D GIT_REV='"$(GIT_REV)"' +ifdef FLUIDSYNTH_INCLUDE + CFLAGS+=-I$(FLUIDSYNTH_INCLUDE) +endif + ifeq ($(MAC_STATIC),1) LDFLAGS=$(LIBSDL_FILE) -lm -liconv -lz -Wl,-framework,CoreAudio -Wl,-framework,AudioToolbox -Wl,-framework,ForceFeedback -lobjc -Wl,-framework,CoreVideo -Wl,-framework,Cocoa -Wl,-framework,Carbon -Wl,-framework,IOKit -Wl,-weak_framework,QuartzCore -Wl,-weak_framework,Metal -Wl,-weak_framework,CoreHaptics -Wl,-weak_framework,GameController endif From c232aebe77d6201b111d19a6ef00bf326d7c7c94 Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Wed, 18 Sep 2024 23:10:14 -0700 Subject: [PATCH 03/63] adding some debugging --- .github/workflows/build.yml | 1 + src/midi.c | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9122ec3..778ad49 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -404,6 +404,7 @@ jobs: cp latest_rom/*.h src/. - name: Build Emulator run: | + find /opt/homebrew/include TRACE=1 MAC_STATIC=1 FLUIDSYNTH_INCLUDE=/opt/homebrew/include/fluid-synth LIBSDL_FILE=/opt/homebrew/Cellar/sdl2/*/lib/libSDL2.a make V=1 -j3 mkdir emu_binaries cp sdcard.img.zip emu_binaries/. diff --git a/src/midi.c b/src/midi.c index 863e633..21adee7 100644 --- a/src/midi.c +++ b/src/midi.c @@ -5,8 +5,6 @@ #include "glue.h" #include "midi.h" -#ifndef __EMSCRIPTEN__ - #ifdef _WIN32 #include #define LIBRARY_TYPE HMODULE @@ -32,14 +30,6 @@ enum MIDI_states { SYSEX, }; -static bool midi_initialized = false; - -static fluid_settings_t* fl_settings; -//static fluid_midi_driver_t* fl_mdriver; -static fluid_audio_driver_t* fl_adriver; -static fluid_synth_t* fl_synth; -static int fl_sf2id; - static uint8_t sysex_buffer[1024]; static int sysex_bufptr; @@ -50,6 +40,16 @@ static uint8_t midi_first_param; static bool serial_dlab = false; static uint8_t serial_dll, serial_dlm, serial_spr; +#ifndef __EMSCRIPTEN__ + +static bool midi_initialized = false; + +static fluid_settings_t* fl_settings; +//static fluid_midi_driver_t* fl_mdriver; +static fluid_audio_driver_t* fl_adriver; +static fluid_synth_t* fl_synth; +static int fl_sf2id; + typedef fluid_settings_t* (*new_fluid_settings_f_t)(void); typedef fluid_synth_t* (*new_fluid_synth_f_t)(fluid_settings_t*); typedef fluid_audio_driver_t* (*new_fluid_audio_driver_f_t)(fluid_settings_t*, fluid_synth_t*); From a8d1a2ba9846cc461465a7a902bd72b4c4fc872b Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Wed, 18 Sep 2024 23:24:07 -0700 Subject: [PATCH 04/63] more updates to try to resolve windows builds --- .github/workflows/build.yml | 4 ++-- Makefile | 4 ---- src/midi.c | 12 ++++++------ 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 778ad49..c41f2cf 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -354,7 +354,7 @@ jobs: cp latest_rom/*.h src/. - name: Build Emulator run: | - TRACE=1 MAC_STATIC=1 LIBSDL_FILE=/usr/local/Cellar/sdl2/*/lib/libSDL2.a make V=1 -j3 + TRACE=1 MAC_STATIC=1 $(pkg-config --cflags fluid-synth) LIBSDL_FILE=/usr/local/Cellar/sdl2/*/lib/libSDL2.a make V=1 -j3 mkdir emu_binaries cp sdcard.img.zip emu_binaries/. cp x16emu emu_binaries/. @@ -405,7 +405,7 @@ jobs: - name: Build Emulator run: | find /opt/homebrew/include - TRACE=1 MAC_STATIC=1 FLUIDSYNTH_INCLUDE=/opt/homebrew/include/fluid-synth LIBSDL_FILE=/opt/homebrew/Cellar/sdl2/*/lib/libSDL2.a make V=1 -j3 + TRACE=1 MAC_STATIC=1 $(pkg-config --cflags fluid-synth) LIBSDL_FILE=/opt/homebrew/Cellar/sdl2/*/lib/libSDL2.a make V=1 -j3 mkdir emu_binaries cp sdcard.img.zip emu_binaries/. cp x16emu emu_binaries/. diff --git a/Makefile b/Makefile index 93d0877..016531c 100644 --- a/Makefile +++ b/Makefile @@ -43,10 +43,6 @@ GIT_REV=$(shell git diff --quiet && /bin/echo -n $$(git rev-parse --short=8 HEAD CFLAGS+=-D GIT_REV='"$(GIT_REV)"' -ifdef FLUIDSYNTH_INCLUDE - CFLAGS+=-I$(FLUIDSYNTH_INCLUDE) -endif - ifeq ($(MAC_STATIC),1) LDFLAGS=$(LIBSDL_FILE) -lm -liconv -lz -Wl,-framework,CoreAudio -Wl,-framework,AudioToolbox -Wl,-framework,ForceFeedback -lobjc -Wl,-framework,CoreVideo -Wl,-framework,Cocoa -Wl,-framework,Carbon -Wl,-framework,IOKit -Wl,-weak_framework,QuartzCore -Wl,-weak_framework,Metal -Wl,-weak_framework,CoreHaptics -Wl,-weak_framework,GameController endif diff --git a/src/midi.c b/src/midi.c index 21adee7..3731f4c 100644 --- a/src/midi.c +++ b/src/midi.c @@ -20,7 +20,7 @@ #endif #define ASSIGN_FUNCTION(lib, var, name) {\ - var = GET_FUNCTION(lib, name);\ + (void *)var = (void *)GET_FUNCTION(lib, name);\ if (!var) { fprintf(stderr, "Unable to find symbol for '%s'\n", name); CLOSE_LIBRARY(handle); return; }\ } @@ -30,6 +30,11 @@ enum MIDI_states { SYSEX, }; +static bool serial_dlab = false; +static uint8_t serial_dll, serial_dlm, serial_spr; + +#ifndef __EMSCRIPTEN__ + static uint8_t sysex_buffer[1024]; static int sysex_bufptr; @@ -37,11 +42,6 @@ static enum MIDI_states midi_state = NORMAL; static uint8_t midi_last_command = 0; static uint8_t midi_first_param; -static bool serial_dlab = false; -static uint8_t serial_dll, serial_dlm, serial_spr; - -#ifndef __EMSCRIPTEN__ - static bool midi_initialized = false; static fluid_settings_t* fl_settings; From 9d847e79705b7a50679972f359974adc10ab2f54 Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Wed, 18 Sep 2024 23:28:17 -0700 Subject: [PATCH 05/63] more fixes --- .github/workflows/build.yml | 4 ++-- src/midi.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c41f2cf..592f3f2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -354,7 +354,7 @@ jobs: cp latest_rom/*.h src/. - name: Build Emulator run: | - TRACE=1 MAC_STATIC=1 $(pkg-config --cflags fluid-synth) LIBSDL_FILE=/usr/local/Cellar/sdl2/*/lib/libSDL2.a make V=1 -j3 + TRACE=1 MAC_STATIC=1 LIBSDL_FILE=/usr/local/Cellar/sdl2/*/lib/libSDL2.a make V=1 -j3 mkdir emu_binaries cp sdcard.img.zip emu_binaries/. cp x16emu emu_binaries/. @@ -404,7 +404,7 @@ jobs: cp latest_rom/*.h src/. - name: Build Emulator run: | - find /opt/homebrew/include + brew ls --verbose fluid-synth TRACE=1 MAC_STATIC=1 $(pkg-config --cflags fluid-synth) LIBSDL_FILE=/opt/homebrew/Cellar/sdl2/*/lib/libSDL2.a make V=1 -j3 mkdir emu_binaries cp sdcard.img.zip emu_binaries/. diff --git a/src/midi.c b/src/midi.c index 3731f4c..10e7697 100644 --- a/src/midi.c +++ b/src/midi.c @@ -20,7 +20,7 @@ #endif #define ASSIGN_FUNCTION(lib, var, name) {\ - (void *)var = (void *)GET_FUNCTION(lib, name);\ + var = (void *)GET_FUNCTION(lib, name);\ if (!var) { fprintf(stderr, "Unable to find symbol for '%s'\n", name); CLOSE_LIBRARY(handle); return; }\ } From 8008b79a18dced54009605c132deb9baef0f86ef Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Wed, 18 Sep 2024 23:34:03 -0700 Subject: [PATCH 06/63] more fixes --- .github/workflows/build.yml | 3 +-- Makefile | 4 +++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 592f3f2..d59c943 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -404,8 +404,7 @@ jobs: cp latest_rom/*.h src/. - name: Build Emulator run: | - brew ls --verbose fluid-synth - TRACE=1 MAC_STATIC=1 $(pkg-config --cflags fluid-synth) LIBSDL_FILE=/opt/homebrew/Cellar/sdl2/*/lib/libSDL2.a make V=1 -j3 + TRACE=1 MAC_STATIC=1 -I$(dirname $(find /opt/homebrew/Cellar/fluid-synth/ -name fluidsynth.h)) LIBSDL_FILE=/opt/homebrew/Cellar/sdl2/*/lib/libSDL2.a make V=1 -j3 mkdir emu_binaries cp sdcard.img.zip emu_binaries/. cp x16emu emu_binaries/. diff --git a/Makefile b/Makefile index 016531c..6d9db5f 100644 --- a/Makefile +++ b/Makefile @@ -18,7 +18,7 @@ endif CFLAGS=-std=c99 -O3 -Wall -Werror -g $(shell $(SDL2CONFIG) --cflags) -Isrc/extern/include CXXFLAGS=-std=c++17 -O3 -Wall -Werror -Isrc/extern/ymfm/src -LDFLAGS=$(shell $(SDL2CONFIG) --libs) -lm -lz -ldl +LDFLAGS=$(shell $(SDL2CONFIG) --libs) -lm -lz # build with link time optimization ifndef NOLTO @@ -63,6 +63,8 @@ endif ifdef TARGET_WIN32 LDFLAGS+=-ldwmapi +else + LDFLAGS+=-ldl endif ifdef EMSCRIPTEN From aa3249f9d92701ab7619116387d2eaf94aa5f04e Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Wed, 18 Sep 2024 23:40:42 -0700 Subject: [PATCH 07/63] perhaps everything will build now --- .github/workflows/build.yml | 4 +++- Makefile | 4 ++++ src/midi.c | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d59c943..e54dbf2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -70,6 +70,7 @@ jobs: cp $(which SDL2.dll) emu_binaries/. cp $(which zlib1.dll) emu_binaries/. cp $(which libwinpthread-1.dll) emu_binaries/. + cp $(which libfluidsynth-3.dll) emu_binaries/. cp sdcard.img.zip emu_binaries/. cp x16emu.exe emu_binaries/. cp makecart.exe emu_binaries/. @@ -136,6 +137,7 @@ jobs: cp $(which SDL2.dll) emu_binaries/. cp $(which zlib1.dll) emu_binaries/. cp $(which libwinpthread-1.dll) emu_binaries/. + cp $(which libfluidsynth-3.dll) emu_binaries/. cp sdcard.img.zip emu_binaries/. cp x16emu.exe emu_binaries/. cp makecart.exe emu_binaries/. @@ -404,7 +406,7 @@ jobs: cp latest_rom/*.h src/. - name: Build Emulator run: | - TRACE=1 MAC_STATIC=1 -I$(dirname $(find /opt/homebrew/Cellar/fluid-synth/ -name fluidsynth.h)) LIBSDL_FILE=/opt/homebrew/Cellar/sdl2/*/lib/libSDL2.a make V=1 -j3 + TRACE=1 MAC_STATIC=1 ADDL_INCLUDE=$(dirname $(find /opt/homebrew/Cellar/fluid-synth -name fluidsynth.h)) LIBSDL_FILE=/opt/homebrew/Cellar/sdl2/*/lib/libSDL2.a make V=1 -j3 mkdir emu_binaries cp sdcard.img.zip emu_binaries/. cp x16emu emu_binaries/. diff --git a/Makefile b/Makefile index 6d9db5f..ee47345 100644 --- a/Makefile +++ b/Makefile @@ -26,6 +26,10 @@ ifndef NOLTO LDFLAGS+=-flto endif +ifdef ADDLINCLUDE + CFLAGS+=-I$(ADDLINCLUDE) +endif + X16_ODIR = build/x16emu X16_SDIR = src diff --git a/src/midi.c b/src/midi.c index 10e7697..a503c40 100644 --- a/src/midi.c +++ b/src/midi.c @@ -83,7 +83,7 @@ void midi_init() LIBRARY_TYPE handle = LOAD_LIBRARY( #ifdef _WIN32 - "fluidsynth.dll" + "libfluidsynth-3.dll" #else "libfluidsynth.so" #endif From dac898998dd4c7ed684107f04c6e53ec8aa7e18d Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Wed, 18 Sep 2024 23:42:56 -0700 Subject: [PATCH 08/63] typo of variable name --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index ee47345..8c802fe 100644 --- a/Makefile +++ b/Makefile @@ -26,8 +26,8 @@ ifndef NOLTO LDFLAGS+=-flto endif -ifdef ADDLINCLUDE - CFLAGS+=-I$(ADDLINCLUDE) +ifdef ADDL_INCLUDE + CFLAGS+=-I$(ADDL_INCLUDE) endif X16_ODIR = build/x16emu From 385fd4700c645717826ef4728a41ee88d52a2a4a Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Thu, 19 Sep 2024 00:06:11 -0700 Subject: [PATCH 09/63] attempt to fix windows runtime --- src/midi.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/midi.c b/src/midi.c index a503c40..82d3e9e 100644 --- a/src/midi.c +++ b/src/midi.c @@ -8,7 +8,7 @@ #ifdef _WIN32 #include #define LIBRARY_TYPE HMODULE - #define LOAD_LIBRARY(name) LoadLibrary(name) + #define LOAD_LIBRARY(name) LoadLibraryEx(name, NULL, LOAD_LIBRARY_SEARCH_APPLICATION_DIR) #define GET_FUNCTION(lib, name) GetProcAddress(lib, name) #define CLOSE_LIBRARY(lib) FreeLibrary(lib) #else @@ -81,13 +81,11 @@ static fluid_synth_sysex_f_t dl_fs_sysex; void midi_init() { - LIBRARY_TYPE handle = LOAD_LIBRARY( #ifdef _WIN32 - "libfluidsynth-3.dll" + LIBRARY_TYPE handle = LOAD_LIBRARY("libfluidsynth-3.dll") #else - "libfluidsynth.so" + LIBRARY_TYPE handle = LOAD_LIBRARY("libfluidsynth.so") #endif - ); if (!handle) { // Handle the error on both platforms @@ -99,6 +97,10 @@ void midi_init() return; } +#ifndef _WIN32 + dlerror(); +#endif + ASSIGN_FUNCTION(handle, dl_new_fluid_settings, "new_fluid_settings"); ASSIGN_FUNCTION(handle, dl_new_fluid_synth, "new_fluid_synth"); ASSIGN_FUNCTION(handle, dl_new_fluid_audio_driver, "new_fluid_audio_driver"); From 387848648fc7114d9f2e67637de4370c644070c4 Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Thu, 19 Sep 2024 00:08:08 -0700 Subject: [PATCH 10/63] missing semicolon --- src/midi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/midi.c b/src/midi.c index 82d3e9e..7d72471 100644 --- a/src/midi.c +++ b/src/midi.c @@ -82,9 +82,9 @@ void midi_init() { #ifdef _WIN32 - LIBRARY_TYPE handle = LOAD_LIBRARY("libfluidsynth-3.dll") + LIBRARY_TYPE handle = LOAD_LIBRARY("libfluidsynth-3.dll"); #else - LIBRARY_TYPE handle = LOAD_LIBRARY("libfluidsynth.so") + LIBRARY_TYPE handle = LOAD_LIBRARY("libfluidsynth.so"); #endif if (!handle) { From ed53b76f7620bf5beff1814137c757562a6820ac Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Thu, 19 Sep 2024 00:22:00 -0700 Subject: [PATCH 11/63] switch windows to bind to bundled DLL --- Makefile | 1 + src/midi.c | 28 ++++++++++++++-------------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/Makefile b/Makefile index 8c802fe..89c1ea2 100644 --- a/Makefile +++ b/Makefile @@ -56,6 +56,7 @@ ifeq ($(CROSS_COMPILE_WINDOWS),1) # this enables printf() to show, but also forces a console window LDFLAGS+=-Wl,--subsystem,console LDFLAGS+=-static-libstdc++ -static-libgcc + LDFLAGS+=-lfluidsynth ifeq ($(TARGET_CPU),x86) CC=i686-w64-mingw32-gcc CXX=i686-w64-mingw32-g++ diff --git a/src/midi.c b/src/midi.c index 7d72471..3ba7cd8 100644 --- a/src/midi.c +++ b/src/midi.c @@ -7,10 +7,6 @@ #ifdef _WIN32 #include - #define LIBRARY_TYPE HMODULE - #define LOAD_LIBRARY(name) LoadLibraryEx(name, NULL, LOAD_LIBRARY_SEARCH_APPLICATION_DIR) - #define GET_FUNCTION(lib, name) GetProcAddress(lib, name) - #define CLOSE_LIBRARY(lib) FreeLibrary(lib) #else #include #define LIBRARY_TYPE void* @@ -20,7 +16,7 @@ #endif #define ASSIGN_FUNCTION(lib, var, name) {\ - var = (void *)GET_FUNCTION(lib, name);\ + var = GET_FUNCTION(lib, name);\ if (!var) { fprintf(stderr, "Unable to find symbol for '%s'\n", name); CLOSE_LIBRARY(handle); return; }\ } @@ -82,24 +78,27 @@ void midi_init() { #ifdef _WIN32 - LIBRARY_TYPE handle = LOAD_LIBRARY("libfluidsynth-3.dll"); + dl_new_fluid_settings = new_fluid_settings; + dl_new_fluid_synth = new_fluid_synth; + dl_fs_sfload = fluid_synth_sfload; + dl_fs_program_change = fluid_synth_program_change; + dl_fs_channel_pressure = fluid_synth_channel_pressure; + dl_fs_system_reset = fluid_synth_system_reset; + dl_fs_noteoff = fluid_synth_noteoff; + dl_fs_noteon = fluid_synth_noteon; + dl_fs_key_pressure = fluid_synth_key_pressure; + dl_fs_cc = fluid_synth_cc; + dl_fs_pitch_bend = fluid_synth_pitch_bend; + dl_fs_sysex = fluid_synth_sysex; #else LIBRARY_TYPE handle = LOAD_LIBRARY("libfluidsynth.so"); -#endif if (!handle) { - // Handle the error on both platforms -#ifdef _WIN32 - fprintf(stderr, "Could not load MIDI synth library: error code %lu\n", GetLastError()); -#else fprintf(stderr, "Could not load MIDI synth library: %s\n", dlerror()); -#endif return; } -#ifndef _WIN32 dlerror(); -#endif ASSIGN_FUNCTION(handle, dl_new_fluid_settings, "new_fluid_settings"); ASSIGN_FUNCTION(handle, dl_new_fluid_synth, "new_fluid_synth"); @@ -114,6 +113,7 @@ void midi_init() ASSIGN_FUNCTION(handle, dl_fs_cc, "fluid_synth_cc"); ASSIGN_FUNCTION(handle, dl_fs_pitch_bend, "fluid_synth_pitch_bend"); ASSIGN_FUNCTION(handle, dl_fs_sysex, "fluid_synth_sysex"); +#endif fl_settings = dl_new_fluid_settings(); fl_synth = dl_new_fluid_synth(fl_settings); From 4431b70777c3553af593218fadf549b5a8a1c05b Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Thu, 19 Sep 2024 00:27:20 -0700 Subject: [PATCH 12/63] additional DLL dependency --- .github/workflows/build.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e54dbf2..2d7ceae 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -71,6 +71,7 @@ jobs: cp $(which zlib1.dll) emu_binaries/. cp $(which libwinpthread-1.dll) emu_binaries/. cp $(which libfluidsynth-3.dll) emu_binaries/. + cp $(which libgcc_s_seh-1.dll) emu_binaries/. cp sdcard.img.zip emu_binaries/. cp x16emu.exe emu_binaries/. cp makecart.exe emu_binaries/. @@ -138,6 +139,7 @@ jobs: cp $(which zlib1.dll) emu_binaries/. cp $(which libwinpthread-1.dll) emu_binaries/. cp $(which libfluidsynth-3.dll) emu_binaries/. + cp $(which libgcc_s_seh-1.dll) emu_binaries/. cp sdcard.img.zip emu_binaries/. cp x16emu.exe emu_binaries/. cp makecart.exe emu_binaries/. From 8c49d2731744b9de5eed88bc61a2595d79cf8c99 Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Thu, 19 Sep 2024 00:32:33 -0700 Subject: [PATCH 13/63] more DLL deps --- .github/workflows/build.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2d7ceae..bff3f46 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -72,6 +72,8 @@ jobs: cp $(which libwinpthread-1.dll) emu_binaries/. cp $(which libfluidsynth-3.dll) emu_binaries/. cp $(which libgcc_s_seh-1.dll) emu_binaries/. + cp $(which libglib-2.0-0.dll) emu_binaries/. + cp $(which libgmodule-2.0-0.dll) emu_binaries/. cp sdcard.img.zip emu_binaries/. cp x16emu.exe emu_binaries/. cp makecart.exe emu_binaries/. @@ -140,6 +142,8 @@ jobs: cp $(which libwinpthread-1.dll) emu_binaries/. cp $(which libfluidsynth-3.dll) emu_binaries/. cp $(which libgcc_s_seh-1.dll) emu_binaries/. + cp $(which libglib-2.0-0.dll) emu_binaries/. + cp $(which libgmodule-2.0-0.dll) emu_binaries/. cp sdcard.img.zip emu_binaries/. cp x16emu.exe emu_binaries/. cp makecart.exe emu_binaries/. From b8c6820279e6b616c5de01d7c6ac3ed642194b43 Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Thu, 19 Sep 2024 00:37:21 -0700 Subject: [PATCH 14/63] another DLL dep --- .github/workflows/build.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bff3f46..32d9783 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -74,6 +74,7 @@ jobs: cp $(which libgcc_s_seh-1.dll) emu_binaries/. cp $(which libglib-2.0-0.dll) emu_binaries/. cp $(which libgmodule-2.0-0.dll) emu_binaries/. + cp $(which libportaudio.dll) emu_binaries/. cp sdcard.img.zip emu_binaries/. cp x16emu.exe emu_binaries/. cp makecart.exe emu_binaries/. @@ -144,6 +145,7 @@ jobs: cp $(which libgcc_s_seh-1.dll) emu_binaries/. cp $(which libglib-2.0-0.dll) emu_binaries/. cp $(which libgmodule-2.0-0.dll) emu_binaries/. + cp $(which libportaudio.dll) emu_binaries/. cp sdcard.img.zip emu_binaries/. cp x16emu.exe emu_binaries/. cp makecart.exe emu_binaries/. From 516928ba7c4b04310b013dc9a60e71704f46994c Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Thu, 19 Sep 2024 00:46:52 -0700 Subject: [PATCH 15/63] go back to dynamic loading for DLL --- Makefile | 1 - src/midi.c | 28 ++++++++++++++-------------- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/Makefile b/Makefile index 89c1ea2..8c802fe 100644 --- a/Makefile +++ b/Makefile @@ -56,7 +56,6 @@ ifeq ($(CROSS_COMPILE_WINDOWS),1) # this enables printf() to show, but also forces a console window LDFLAGS+=-Wl,--subsystem,console LDFLAGS+=-static-libstdc++ -static-libgcc - LDFLAGS+=-lfluidsynth ifeq ($(TARGET_CPU),x86) CC=i686-w64-mingw32-gcc CXX=i686-w64-mingw32-g++ diff --git a/src/midi.c b/src/midi.c index 3ba7cd8..4b838cd 100644 --- a/src/midi.c +++ b/src/midi.c @@ -7,6 +7,10 @@ #ifdef _WIN32 #include + #define LIBRARY_TYPE HMODULE + #define LOAD_LIBRARY(name) LoadLibrary(name) + #define GET_FUNCTION(lib, name) GetProcAddress(lib, name) + #define CLOSE_LIBRARY(lib) FreeLibrary(lib) #else #include #define LIBRARY_TYPE void* @@ -16,7 +20,7 @@ #endif #define ASSIGN_FUNCTION(lib, var, name) {\ - var = GET_FUNCTION(lib, name);\ + var = (void *)GET_FUNCTION(lib, name);\ if (!var) { fprintf(stderr, "Unable to find symbol for '%s'\n", name); CLOSE_LIBRARY(handle); return; }\ } @@ -78,27 +82,24 @@ void midi_init() { #ifdef _WIN32 - dl_new_fluid_settings = new_fluid_settings; - dl_new_fluid_synth = new_fluid_synth; - dl_fs_sfload = fluid_synth_sfload; - dl_fs_program_change = fluid_synth_program_change; - dl_fs_channel_pressure = fluid_synth_channel_pressure; - dl_fs_system_reset = fluid_synth_system_reset; - dl_fs_noteoff = fluid_synth_noteoff; - dl_fs_noteon = fluid_synth_noteon; - dl_fs_key_pressure = fluid_synth_key_pressure; - dl_fs_cc = fluid_synth_cc; - dl_fs_pitch_bend = fluid_synth_pitch_bend; - dl_fs_sysex = fluid_synth_sysex; + LIBRARY_TYPE handle = LOAD_LIBRARY("libfluidsynth-3.dll"); #else LIBRARY_TYPE handle = LOAD_LIBRARY("libfluidsynth.so"); +#endif if (!handle) { + // Handle the error on both platforms +#ifdef _WIN32 + fprintf(stderr, "Could not load MIDI synth library: error code %lu\n", GetLastError()); +#else fprintf(stderr, "Could not load MIDI synth library: %s\n", dlerror()); +#endif return; } +#ifndef _WIN32 dlerror(); +#endif ASSIGN_FUNCTION(handle, dl_new_fluid_settings, "new_fluid_settings"); ASSIGN_FUNCTION(handle, dl_new_fluid_synth, "new_fluid_synth"); @@ -113,7 +114,6 @@ void midi_init() ASSIGN_FUNCTION(handle, dl_fs_cc, "fluid_synth_cc"); ASSIGN_FUNCTION(handle, dl_fs_pitch_bend, "fluid_synth_pitch_bend"); ASSIGN_FUNCTION(handle, dl_fs_sysex, "fluid_synth_sysex"); -#endif fl_settings = dl_new_fluid_settings(); fl_synth = dl_new_fluid_synth(fl_settings); From dac597bd68a2d28d8bb404d517b24eaffd67f80a Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Thu, 19 Sep 2024 00:53:52 -0700 Subject: [PATCH 16/63] more DLL deps --- .github/workflows/build.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 32d9783..49a42f6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -75,6 +75,11 @@ jobs: cp $(which libglib-2.0-0.dll) emu_binaries/. cp $(which libgmodule-2.0-0.dll) emu_binaries/. cp $(which libportaudio.dll) emu_binaries/. + cp $(which libintl-8.dll) emu_binaries/. + cp $(which libstdc++-6.dll) emu_binaries/. + cp $(which libgomp-1.dll) emu_binaries/. + cp $(which libreadline-8.dll) emu_binaries/. + cp $(which libsndfile-1.dll) emu_binaries/. cp sdcard.img.zip emu_binaries/. cp x16emu.exe emu_binaries/. cp makecart.exe emu_binaries/. @@ -146,6 +151,11 @@ jobs: cp $(which libglib-2.0-0.dll) emu_binaries/. cp $(which libgmodule-2.0-0.dll) emu_binaries/. cp $(which libportaudio.dll) emu_binaries/. + cp $(which libintl-8.dll) emu_binaries/. + cp $(which libstdc++-6.dll) emu_binaries/. + cp $(which libgomp-1.dll) emu_binaries/. + cp $(which libreadline-8.dll) emu_binaries/. + cp $(which libsndfile-1.dll) emu_binaries/. cp sdcard.img.zip emu_binaries/. cp x16emu.exe emu_binaries/. cp makecart.exe emu_binaries/. From 09313690d0b38abcf9b47b9f64cde41424ee607a Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Thu, 19 Sep 2024 00:57:29 -0700 Subject: [PATCH 17/63] fix typo --- .github/workflows/build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 49a42f6..69f2d59 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -78,7 +78,7 @@ jobs: cp $(which libintl-8.dll) emu_binaries/. cp $(which libstdc++-6.dll) emu_binaries/. cp $(which libgomp-1.dll) emu_binaries/. - cp $(which libreadline-8.dll) emu_binaries/. + cp $(which libreadline8.dll) emu_binaries/. cp $(which libsndfile-1.dll) emu_binaries/. cp sdcard.img.zip emu_binaries/. cp x16emu.exe emu_binaries/. @@ -154,7 +154,7 @@ jobs: cp $(which libintl-8.dll) emu_binaries/. cp $(which libstdc++-6.dll) emu_binaries/. cp $(which libgomp-1.dll) emu_binaries/. - cp $(which libreadline-8.dll) emu_binaries/. + cp $(which libreadline8.dll) emu_binaries/. cp $(which libsndfile-1.dll) emu_binaries/. cp sdcard.img.zip emu_binaries/. cp x16emu.exe emu_binaries/. From b7aeac5fd8657e522c882b2a7562f309f857833c Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Thu, 19 Sep 2024 01:05:39 -0700 Subject: [PATCH 18/63] more deep DLL deps --- .github/workflows/build.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 69f2d59..2d410f9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -80,6 +80,16 @@ jobs: cp $(which libgomp-1.dll) emu_binaries/. cp $(which libreadline8.dll) emu_binaries/. cp $(which libsndfile-1.dll) emu_binaries/. + cp $(which libpcre2-8-0.dll) emu_binaries/. + cp $(which libiconv-2.dll) emu_binaries/. + cp $(which libtermcap-0.dll) emu_binaries/. + cp $(which libFLAC.dll) emu_binaries/. + cp $(which libmp3lame-0.dll) emu_binaries/. + cp $(which libmpg123-0.dll) emu_binaries/. + cp $(which libogg-0.dll) emu_binaries/. + cp $(which libopus-0.dll) emu_binaries/. + cp $(which libvorbis-0.dll) emu_binaries/. + cp $(which libvorbisenc-2.dll) emu_binaries/. cp sdcard.img.zip emu_binaries/. cp x16emu.exe emu_binaries/. cp makecart.exe emu_binaries/. @@ -156,6 +166,16 @@ jobs: cp $(which libgomp-1.dll) emu_binaries/. cp $(which libreadline8.dll) emu_binaries/. cp $(which libsndfile-1.dll) emu_binaries/. + cp $(which libpcre2-8-0.dll) emu_binaries/. + cp $(which libiconv-2.dll) emu_binaries/. + cp $(which libtermcap-0.dll) emu_binaries/. + cp $(which libFLAC.dll) emu_binaries/. + cp $(which libmp3lame-0.dll) emu_binaries/. + cp $(which libmpg123-0.dll) emu_binaries/. + cp $(which libogg-0.dll) emu_binaries/. + cp $(which libopus-0.dll) emu_binaries/. + cp $(which libvorbis-0.dll) emu_binaries/. + cp $(which libvorbisenc-2.dll) emu_binaries/. cp sdcard.img.zip emu_binaries/. cp x16emu.exe emu_binaries/. cp makecart.exe emu_binaries/. From 7c67153bb375537f45559ad4c06480af4fb94d54 Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Thu, 19 Sep 2024 12:37:23 -0700 Subject: [PATCH 19/63] macos fix --- src/midi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/midi.c b/src/midi.c index 4b838cd..81f05ab 100644 --- a/src/midi.c +++ b/src/midi.c @@ -83,6 +83,8 @@ void midi_init() #ifdef _WIN32 LIBRARY_TYPE handle = LOAD_LIBRARY("libfluidsynth-3.dll"); +#elif __APPLE__ + LIBRARY_TYPE handle = LOAD_LIBRARY("libfluidsynth.dylib"); #else LIBRARY_TYPE handle = LOAD_LIBRARY("libfluidsynth.so"); #endif From a20de955d28e2b5e9c646c3f4345b60035c8f5e5 Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Sat, 21 Sep 2024 16:00:05 -0700 Subject: [PATCH 20/63] Static link builds for fluidsynth --- .github/workflows/build.yml | 4 +- Makefile | 12 ++--- src/midi.c | 95 ++++++------------------------------- 3 files changed, 23 insertions(+), 88 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2d410f9..bcec47d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -394,7 +394,7 @@ jobs: cp latest_rom/*.h src/. - name: Build Emulator run: | - TRACE=1 MAC_STATIC=1 LIBSDL_FILE=/usr/local/Cellar/sdl2/*/lib/libSDL2.a make V=1 -j3 + TRACE=1 MAC_STATIC=1 HOMEBREW_LIB=/usr/local/lib make V=1 -j3 mkdir emu_binaries cp sdcard.img.zip emu_binaries/. cp x16emu emu_binaries/. @@ -444,7 +444,7 @@ jobs: cp latest_rom/*.h src/. - name: Build Emulator run: | - TRACE=1 MAC_STATIC=1 ADDL_INCLUDE=$(dirname $(find /opt/homebrew/Cellar/fluid-synth -name fluidsynth.h)) LIBSDL_FILE=/opt/homebrew/Cellar/sdl2/*/lib/libSDL2.a make V=1 -j3 + TRACE=1 MAC_STATIC=1 ADDL_INCLUDE=/opt/homebrew/include HOMEBREW_LIB=/opt/homebew/lib make V=1 -j3 mkdir emu_binaries cp sdcard.img.zip emu_binaries/. cp x16emu emu_binaries/. diff --git a/Makefile b/Makefile index 8c802fe..44ebbdf 100644 --- a/Makefile +++ b/Makefile @@ -48,14 +48,13 @@ GIT_REV=$(shell git diff --quiet && /bin/echo -n $$(git rev-parse --short=8 HEAD CFLAGS+=-D GIT_REV='"$(GIT_REV)"' ifeq ($(MAC_STATIC),1) - LDFLAGS=$(LIBSDL_FILE) -lm -liconv -lz -Wl,-framework,CoreAudio -Wl,-framework,AudioToolbox -Wl,-framework,ForceFeedback -lobjc -Wl,-framework,CoreVideo -Wl,-framework,Cocoa -Wl,-framework,Carbon -Wl,-framework,IOKit -Wl,-weak_framework,QuartzCore -Wl,-weak_framework,Metal -Wl,-weak_framework,CoreHaptics -Wl,-weak_framework,GameController -endif - -ifeq ($(CROSS_COMPILE_WINDOWS),1) + LDFLAGS=-L$(HOMEBREW_LIB) libSDL2.a libfluidsynth.a -lm -liconv -lz -Wl,-framework,CoreAudio -Wl,-framework,AudioToolbox -Wl,-framework,ForceFeedback -lobjc -Wl,-framework,CoreVideo -Wl,-framework,Cocoa -Wl,-framework,Carbon -Wl,-framework,IOKit -Wl,-weak_framework,QuartzCore -Wl,-weak_framework,Metal -Wl,-weak_framework,CoreHaptics -Wl,-weak_framework,GameController +else ifeq ($(CROSS_COMPILE_WINDOWS),1) LDFLAGS+=-L$(MINGW32)/lib # this enables printf() to show, but also forces a console window LDFLAGS+=-Wl,--subsystem,console LDFLAGS+=-static-libstdc++ -static-libgcc + LDFLAGS+=libSDL2.a libfluidsynth.a ifeq ($(TARGET_CPU),x86) CC=i686-w64-mingw32-gcc CXX=i686-w64-mingw32-g++ @@ -63,12 +62,13 @@ else CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++ endif +else # Not Mac, not Windows, probably Linux + # Link static if possible, otherwise fall back to dynamic + LDFLAGS+=$(shell $(CC) -static -lfluidsynth &>/dev/null && /bin/echo "-Wl,-Bstatic -lfluidsynth -Wl,-Bdynamic" || /bin/echo "-lfluidsynth") endif ifdef TARGET_WIN32 LDFLAGS+=-ldwmapi -else - LDFLAGS+=-ldl endif ifdef EMSCRIPTEN diff --git a/src/midi.c b/src/midi.c index 81f05ab..a8afebf 100644 --- a/src/midi.c +++ b/src/midi.c @@ -50,85 +50,20 @@ static fluid_audio_driver_t* fl_adriver; static fluid_synth_t* fl_synth; static int fl_sf2id; -typedef fluid_settings_t* (*new_fluid_settings_f_t)(void); -typedef fluid_synth_t* (*new_fluid_synth_f_t)(fluid_settings_t*); -typedef fluid_audio_driver_t* (*new_fluid_audio_driver_f_t)(fluid_settings_t*, fluid_synth_t*); -typedef int (*fluid_synth_sfload_f_t)(fluid_synth_t*,const char *,int); -typedef int (*fluid_synth_program_change_f_t)(fluid_synth_t*, int, int); -typedef int (*fluid_synth_channel_pressure_f_t)(fluid_synth_t*, int, int); -typedef int (*fluid_synth_system_reset_f_t)(fluid_synth_t*); -typedef int (*fluid_synth_noteoff_f_t)(fluid_synth_t*, int, int); -typedef int (*fluid_synth_noteon_f_t)(fluid_synth_t*, int, int, int); -typedef int (*fluid_synth_key_pressure_f_t)(fluid_synth_t*, int, int, int); -typedef int (*fluid_synth_cc_f_t)(fluid_synth_t*, int, int, int); -typedef int (*fluid_synth_pitch_bend_f_t)(fluid_synth_t*, int, int); -typedef int (*fluid_synth_sysex_f_t)(fluid_synth_t*, const char*, int, char*, int*, int*, int); - -static new_fluid_settings_f_t dl_new_fluid_settings; -static new_fluid_synth_f_t dl_new_fluid_synth; -static new_fluid_audio_driver_f_t dl_new_fluid_audio_driver; -static fluid_synth_sfload_f_t dl_fs_sfload; -static fluid_synth_program_change_f_t dl_fs_program_change; -static fluid_synth_channel_pressure_f_t dl_fs_channel_pressure; -static fluid_synth_system_reset_f_t dl_fs_system_reset; -static fluid_synth_noteoff_f_t dl_fs_noteoff; -static fluid_synth_noteon_f_t dl_fs_noteon; -static fluid_synth_key_pressure_f_t dl_fs_key_pressure; -static fluid_synth_cc_f_t dl_fs_cc; -static fluid_synth_pitch_bend_f_t dl_fs_pitch_bend; -static fluid_synth_sysex_f_t dl_fs_sysex; - void midi_init() { - -#ifdef _WIN32 - LIBRARY_TYPE handle = LOAD_LIBRARY("libfluidsynth-3.dll"); -#elif __APPLE__ - LIBRARY_TYPE handle = LOAD_LIBRARY("libfluidsynth.dylib"); -#else - LIBRARY_TYPE handle = LOAD_LIBRARY("libfluidsynth.so"); -#endif - - if (!handle) { - // Handle the error on both platforms -#ifdef _WIN32 - fprintf(stderr, "Could not load MIDI synth library: error code %lu\n", GetLastError()); -#else - fprintf(stderr, "Could not load MIDI synth library: %s\n", dlerror()); -#endif - return; - } - -#ifndef _WIN32 - dlerror(); -#endif - - ASSIGN_FUNCTION(handle, dl_new_fluid_settings, "new_fluid_settings"); - ASSIGN_FUNCTION(handle, dl_new_fluid_synth, "new_fluid_synth"); - ASSIGN_FUNCTION(handle, dl_new_fluid_audio_driver, "new_fluid_audio_driver"); - ASSIGN_FUNCTION(handle, dl_fs_sfload, "fluid_synth_sfload"); - ASSIGN_FUNCTION(handle, dl_fs_program_change, "fluid_synth_program_change"); - ASSIGN_FUNCTION(handle, dl_fs_channel_pressure, "fluid_synth_channel_pressure"); - ASSIGN_FUNCTION(handle, dl_fs_system_reset, "fluid_synth_system_reset"); - ASSIGN_FUNCTION(handle, dl_fs_noteoff, "fluid_synth_noteoff"); - ASSIGN_FUNCTION(handle, dl_fs_noteon, "fluid_synth_noteon"); - ASSIGN_FUNCTION(handle, dl_fs_key_pressure, "fluid_synth_key_pressure"); - ASSIGN_FUNCTION(handle, dl_fs_cc, "fluid_synth_cc"); - ASSIGN_FUNCTION(handle, dl_fs_pitch_bend, "fluid_synth_pitch_bend"); - ASSIGN_FUNCTION(handle, dl_fs_sysex, "fluid_synth_sysex"); - - fl_settings = dl_new_fluid_settings(); - fl_synth = dl_new_fluid_synth(fl_settings); - fl_adriver = dl_new_fluid_audio_driver(fl_settings, fl_synth); + fl_settings = new_fluid_settings(); + fl_synth = new_fluid_synth(fl_settings); + fl_adriver = new_fluid_audio_driver(fl_settings, fl_synth); midi_initialized = true; - printf("FLUID INIT\n"); + printf("Initialized MIDI synth.\n"); } void midi_load_sf2(uint8_t* filename) { if (!midi_initialized) return; - fl_sf2id = dl_fs_sfload(fl_synth, (const char *)filename, true); + fl_sf2id = fluid_synth_sfload(fl_synth, (const char *)filename, true); if (fl_sf2id == FLUID_FAILED) { printf("Unable to load soundfont.\n"); } @@ -144,9 +79,9 @@ void midi_byte(uint8_t b) case NORMAL: if (b < 0x80) { if ((midi_last_command & 0xf0) == 0xc0) { // patch change - dl_fs_program_change(fl_synth, midi_last_command & 0xf, b); + fluid_synth_program_change(fl_synth, midi_last_command & 0xf, b); } else if ((midi_last_command & 0xf0) == 0xd0) { // channel pressure - dl_fs_channel_pressure(fl_synth, midi_last_command & 0xf, b); + fluid_synth_channel_pressure(fl_synth, midi_last_command & 0xf, b); } else if (midi_last_command >= 0x80) { // two-param command midi_first_param = b; midi_state = PARAM; @@ -158,7 +93,7 @@ void midi_byte(uint8_t b) sysex_bufptr = 0; midi_state = SYSEX; } else if (b == 0xff) { - dl_fs_system_reset(fl_synth); + fluid_synth_system_reset(fl_synth); midi_last_command = 0; } } @@ -166,23 +101,23 @@ void midi_byte(uint8_t b) case PARAM: switch (midi_last_command & 0xf0) { case 0x80: // note off - dl_fs_noteoff(fl_synth, midi_last_command & 0xf, midi_first_param); // no release velocity + fluid_synth_noteoff(fl_synth, midi_last_command & 0xf, midi_first_param); // no release velocity break; case 0x90: // note on if (b == 0) { - dl_fs_noteoff(fl_synth, midi_last_command & 0xf, midi_first_param); + fluid_synth_noteoff(fl_synth, midi_last_command & 0xf, midi_first_param); } else { - dl_fs_noteon(fl_synth, midi_last_command & 0xf, midi_first_param, b); + fluid_synth_noteon(fl_synth, midi_last_command & 0xf, midi_first_param, b); } break; case 0xa0: // aftertouch - dl_fs_key_pressure(fl_synth, midi_last_command & 0xf, midi_first_param, b); + fluid_synth_key_pressure(fl_synth, midi_last_command & 0xf, midi_first_param, b); break; case 0xb0: // controller - dl_fs_cc(fl_synth, midi_last_command & 0xf, midi_first_param, b); + fluid_synth_cc(fl_synth, midi_last_command & 0xf, midi_first_param, b); break; case 0xe0: // pitch bend - dl_fs_pitch_bend(fl_synth, midi_last_command & 0xf, ((uint16_t)midi_first_param) | (uint16_t)b << 7); + fluid_synth_pitch_bend(fl_synth, midi_last_command & 0xf, ((uint16_t)midi_first_param) | (uint16_t)b << 7); break; } midi_state = NORMAL; @@ -190,7 +125,7 @@ void midi_byte(uint8_t b) case SYSEX: if (b == 0xf7) { sysex_buffer[sysex_bufptr] = 0; - dl_fs_sysex(fl_synth, (const char *)sysex_buffer, sysex_bufptr, NULL, NULL, NULL, 0); + fluid_synth_sysex(fl_synth, (const char *)sysex_buffer, sysex_bufptr, NULL, NULL, NULL, 0); midi_state = NORMAL; } else { sysex_buffer[sysex_bufptr++] = b; From e3c07f3a19e06e7cacd3353b870150024b67507e Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Sat, 21 Sep 2024 18:02:55 -0700 Subject: [PATCH 21/63] test --- .github/workflows/build.yml | 2 ++ Makefile | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bcec47d..0871747 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -223,6 +223,8 @@ jobs: cp latest_rom/*.h src/. - name: Build Emulator run: | + dpkg-query -L libfluidsynth-dev + dpkg-query -L libfluidsynth2 TRACE=1 make V=1 -j3 mkdir emu_binaries cp sdcard.img.zip emu_binaries/. diff --git a/Makefile b/Makefile index 44ebbdf..0952dd3 100644 --- a/Makefile +++ b/Makefile @@ -64,7 +64,7 @@ else endif else # Not Mac, not Windows, probably Linux # Link static if possible, otherwise fall back to dynamic - LDFLAGS+=$(shell $(CC) -static -lfluidsynth &>/dev/null && /bin/echo "-Wl,-Bstatic -lfluidsynth -Wl,-Bdynamic" || /bin/echo "-lfluidsynth") + LDFLUID=$(shell $(CC) -static -lfluidsynth &>/dev/null && /bin/echo "-Wl,-Bstatic -lfluidsynth -Wl,-Bdynamic" || /bin/echo "-lfluidsynth") endif ifdef TARGET_WIN32 @@ -99,7 +99,7 @@ MAKECART_DEPS := $(MAKECART_OBJS:.o=.d) all: x16emu makecart x16emu: $(X16_OBJS) - $(CXX) -o $(X16_OUTPUT) $(X16_OBJS) $(LDFLAGS) + $(CXX) -o $(X16_OUTPUT) $(X16_OBJS) $(LDFLAGS) $(LDFLUID) $(X16_ODIR)/%.o: $(X16_SDIR)/%.c @mkdir -p $$(dirname $@) From f0fc780f74907561ae14ecb8c407dc01b2eb9768 Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Sat, 21 Sep 2024 18:26:49 -0700 Subject: [PATCH 22/63] static lib --- .github/workflows/build.yml | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0871747..f1507a2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -205,13 +205,23 @@ jobs: with: python-version: '3.9' - name: Install Dependencies - run: sudo apt-get update && sudo apt-get install -y build-essential make libsdl2-dev libfluidsynth-dev + run: sudo apt-get update && sudo apt-get install -y build-essential make libsdl2-dev cmake - name: Fetch latest ROM if: startsWith(github.ref, 'refs/tags/r') != true run: | gh run download -R X16Community/x16-rom -n "ROM Image" --dir latest_rom env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Pull down and build FluidSynth + run: | + sudo apt-get build-dep fluidsynth --no-install-recommends + git clone https://github.com/FluidSynth/fluidsynth.git + cd fluidsynth + mkdir build + cd build + cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DBUILD_SHARED_LIBS=0 + make libfluidsynth + sudo make install - name: Fetch latest release ROM if: startsWith(github.ref, 'refs/tags/r') run: | @@ -223,8 +233,6 @@ jobs: cp latest_rom/*.h src/. - name: Build Emulator run: | - dpkg-query -L libfluidsynth-dev - dpkg-query -L libfluidsynth2 TRACE=1 make V=1 -j3 mkdir emu_binaries cp sdcard.img.zip emu_binaries/. From 31a8ae8d3ba74017def024f98c9972cad0a7a999 Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Sat, 21 Sep 2024 18:35:30 -0700 Subject: [PATCH 23/63] static lib --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f1507a2..d82e245 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -214,7 +214,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Pull down and build FluidSynth run: | - sudo apt-get build-dep fluidsynth --no-install-recommends + sudo apt-get build-dep fluidsynth2 --no-install-recommends git clone https://github.com/FluidSynth/fluidsynth.git cd fluidsynth mkdir build From c5c33f563ab6dff8c13669cf656b961a94ec9641 Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Sat, 21 Sep 2024 18:39:35 -0700 Subject: [PATCH 24/63] more testing with custom ubuntu build --- .github/workflows/build.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d82e245..bfb17b3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -205,7 +205,11 @@ jobs: with: python-version: '3.9' - name: Install Dependencies - run: sudo apt-get update && sudo apt-get install -y build-essential make libsdl2-dev cmake + run: | + sudo cp /etc/apt/sources.list /etc/apt/sources.list~ + sudo sed -Ei 's/^# deb-src /deb-src /' /etc/apt/sources.list + sudo apt-get update + sudo apt-get install -y build-essential make libsdl2-dev cmake - name: Fetch latest ROM if: startsWith(github.ref, 'refs/tags/r') != true run: | From 64be6816400566c96fe9007742baa5acf15aeacb Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Sat, 21 Sep 2024 18:42:31 -0700 Subject: [PATCH 25/63] package name --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bfb17b3..3244e13 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -218,7 +218,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Pull down and build FluidSynth run: | - sudo apt-get build-dep fluidsynth2 --no-install-recommends + sudo apt-get build-dep fluidsynth --no-install-recommends git clone https://github.com/FluidSynth/fluidsynth.git cd fluidsynth mkdir build From a938d40143996fbe1a55edfb1c51dba0c772b51d Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Sat, 21 Sep 2024 18:51:05 -0700 Subject: [PATCH 26/63] more testing --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 0952dd3..d36b503 100644 --- a/Makefile +++ b/Makefile @@ -48,13 +48,13 @@ GIT_REV=$(shell git diff --quiet && /bin/echo -n $$(git rev-parse --short=8 HEAD CFLAGS+=-D GIT_REV='"$(GIT_REV)"' ifeq ($(MAC_STATIC),1) - LDFLAGS=-L$(HOMEBREW_LIB) libSDL2.a libfluidsynth.a -lm -liconv -lz -Wl,-framework,CoreAudio -Wl,-framework,AudioToolbox -Wl,-framework,ForceFeedback -lobjc -Wl,-framework,CoreVideo -Wl,-framework,Cocoa -Wl,-framework,Carbon -Wl,-framework,IOKit -Wl,-weak_framework,QuartzCore -Wl,-weak_framework,Metal -Wl,-weak_framework,CoreHaptics -Wl,-weak_framework,GameController + LDFLAGS=-L$(HOMEBREW_LIB) -Wl,-Bstatic -lSDL2 -lfluidsynth -Wl,-Bdynamic -lm -liconv -lz -Wl,-framework,CoreAudio -Wl,-framework,AudioToolbox -Wl,-framework,ForceFeedback -lobjc -Wl,-framework,CoreVideo -Wl,-framework,Cocoa -Wl,-framework,Carbon -Wl,-framework,IOKit -Wl,-weak_framework,QuartzCore -Wl,-weak_framework,Metal -Wl,-weak_framework,CoreHaptics -Wl,-weak_framework,GameController else ifeq ($(CROSS_COMPILE_WINDOWS),1) LDFLAGS+=-L$(MINGW32)/lib # this enables printf() to show, but also forces a console window LDFLAGS+=-Wl,--subsystem,console LDFLAGS+=-static-libstdc++ -static-libgcc - LDFLAGS+=libSDL2.a libfluidsynth.a + LDFLAGS+=-Wl,-Bstatic -lSDL2 -lfluidsynth -Wl,-Bdynamic ifeq ($(TARGET_CPU),x86) CC=i686-w64-mingw32-gcc CXX=i686-w64-mingw32-g++ From 56ad845de501413cb8b784892b1c4f360d1ea2d5 Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Sat, 21 Sep 2024 19:31:18 -0700 Subject: [PATCH 27/63] test macos --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index d36b503..fdec240 100644 --- a/Makefile +++ b/Makefile @@ -48,7 +48,7 @@ GIT_REV=$(shell git diff --quiet && /bin/echo -n $$(git rev-parse --short=8 HEAD CFLAGS+=-D GIT_REV='"$(GIT_REV)"' ifeq ($(MAC_STATIC),1) - LDFLAGS=-L$(HOMEBREW_LIB) -Wl,-Bstatic -lSDL2 -lfluidsynth -Wl,-Bdynamic -lm -liconv -lz -Wl,-framework,CoreAudio -Wl,-framework,AudioToolbox -Wl,-framework,ForceFeedback -lobjc -Wl,-framework,CoreVideo -Wl,-framework,Cocoa -Wl,-framework,Carbon -Wl,-framework,IOKit -Wl,-weak_framework,QuartzCore -Wl,-weak_framework,Metal -Wl,-weak_framework,CoreHaptics -Wl,-weak_framework,GameController + LDFLAGS=$(HOMEBREW_LIB)/libSDL2.a $(HOMEBREW_LIB)/libfluidsynth.a -Wl,-Bdynamic -lm -liconv -lz -Wl,-framework,CoreAudio -Wl,-framework,AudioToolbox -Wl,-framework,ForceFeedback -lobjc -Wl,-framework,CoreVideo -Wl,-framework,Cocoa -Wl,-framework,Carbon -Wl,-framework,IOKit -Wl,-weak_framework,QuartzCore -Wl,-weak_framework,Metal -Wl,-weak_framework,CoreHaptics -Wl,-weak_framework,GameController else ifeq ($(CROSS_COMPILE_WINDOWS),1) LDFLAGS+=-L$(MINGW32)/lib # this enables printf() to show, but also forces a console window From 3bf10e3801f26152cb3d55b0e47f3a5dd80d5b21 Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Sat, 21 Sep 2024 19:37:32 -0700 Subject: [PATCH 28/63] test fix macos --- .github/workflows/build.yml | 2 +- Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3244e13..cb299b3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -458,7 +458,7 @@ jobs: cp latest_rom/*.h src/. - name: Build Emulator run: | - TRACE=1 MAC_STATIC=1 ADDL_INCLUDE=/opt/homebrew/include HOMEBREW_LIB=/opt/homebew/lib make V=1 -j3 + TRACE=1 MAC_STATIC=1 ADDL_INCLUDE=/opt/homebrew/include HOMEBREW_LIB=/opt/homebrew/lib make V=1 -j3 mkdir emu_binaries cp sdcard.img.zip emu_binaries/. cp x16emu emu_binaries/. diff --git a/Makefile b/Makefile index fdec240..2880d29 100644 --- a/Makefile +++ b/Makefile @@ -48,7 +48,7 @@ GIT_REV=$(shell git diff --quiet && /bin/echo -n $$(git rev-parse --short=8 HEAD CFLAGS+=-D GIT_REV='"$(GIT_REV)"' ifeq ($(MAC_STATIC),1) - LDFLAGS=$(HOMEBREW_LIB)/libSDL2.a $(HOMEBREW_LIB)/libfluidsynth.a -Wl,-Bdynamic -lm -liconv -lz -Wl,-framework,CoreAudio -Wl,-framework,AudioToolbox -Wl,-framework,ForceFeedback -lobjc -Wl,-framework,CoreVideo -Wl,-framework,Cocoa -Wl,-framework,Carbon -Wl,-framework,IOKit -Wl,-weak_framework,QuartzCore -Wl,-weak_framework,Metal -Wl,-weak_framework,CoreHaptics -Wl,-weak_framework,GameController + LDFLAGS=$(HOMEBREW_LIB)/libSDL2.a $(HOMEBREW_LIB)/libfluidsynth.a -lm -liconv -lz -Wl,-framework,CoreAudio -Wl,-framework,AudioToolbox -Wl,-framework,ForceFeedback -lobjc -Wl,-framework,CoreVideo -Wl,-framework,Cocoa -Wl,-framework,Carbon -Wl,-framework,IOKit -Wl,-weak_framework,QuartzCore -Wl,-weak_framework,Metal -Wl,-weak_framework,CoreHaptics -Wl,-weak_framework,GameController else ifeq ($(CROSS_COMPILE_WINDOWS),1) LDFLAGS+=-L$(MINGW32)/lib # this enables printf() to show, but also forces a console window From 002927f63ff4aea93431ea5e0e02a3bf38829de3 Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Sat, 21 Sep 2024 19:52:50 -0700 Subject: [PATCH 29/63] more static build tests on macos --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 2880d29..e603642 100644 --- a/Makefile +++ b/Makefile @@ -48,7 +48,7 @@ GIT_REV=$(shell git diff --quiet && /bin/echo -n $$(git rev-parse --short=8 HEAD CFLAGS+=-D GIT_REV='"$(GIT_REV)"' ifeq ($(MAC_STATIC),1) - LDFLAGS=$(HOMEBREW_LIB)/libSDL2.a $(HOMEBREW_LIB)/libfluidsynth.a -lm -liconv -lz -Wl,-framework,CoreAudio -Wl,-framework,AudioToolbox -Wl,-framework,ForceFeedback -lobjc -Wl,-framework,CoreVideo -Wl,-framework,Cocoa -Wl,-framework,Carbon -Wl,-framework,IOKit -Wl,-weak_framework,QuartzCore -Wl,-weak_framework,Metal -Wl,-weak_framework,CoreHaptics -Wl,-weak_framework,GameController + LDFLAGS=$(shell for i in $$(brew deps --tree --installed fluid-synth | awk '{print $$NF}'); do brew list "$$i" | grep '.a$') $(HOMEBREW_LIB)/libSDL2.a -lm -liconv -lz -Wl,-framework,CoreAudio -Wl,-framework,AudioToolbox -Wl,-framework,ForceFeedback -lobjc -Wl,-framework,CoreVideo -Wl,-framework,Cocoa -Wl,-framework,Carbon -Wl,-framework,IOKit -Wl,-weak_framework,QuartzCore -Wl,-weak_framework,Metal -Wl,-weak_framework,CoreHaptics -Wl,-weak_framework,GameController else ifeq ($(CROSS_COMPILE_WINDOWS),1) LDFLAGS+=-L$(MINGW32)/lib # this enables printf() to show, but also forces a console window From b3fc57cd63fe37e83feff2dfc046b261ef75a191 Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Sat, 21 Sep 2024 19:54:06 -0700 Subject: [PATCH 30/63] forgot doubled $ --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index e603642..ef84616 100644 --- a/Makefile +++ b/Makefile @@ -48,7 +48,7 @@ GIT_REV=$(shell git diff --quiet && /bin/echo -n $$(git rev-parse --short=8 HEAD CFLAGS+=-D GIT_REV='"$(GIT_REV)"' ifeq ($(MAC_STATIC),1) - LDFLAGS=$(shell for i in $$(brew deps --tree --installed fluid-synth | awk '{print $$NF}'); do brew list "$$i" | grep '.a$') $(HOMEBREW_LIB)/libSDL2.a -lm -liconv -lz -Wl,-framework,CoreAudio -Wl,-framework,AudioToolbox -Wl,-framework,ForceFeedback -lobjc -Wl,-framework,CoreVideo -Wl,-framework,Cocoa -Wl,-framework,Carbon -Wl,-framework,IOKit -Wl,-weak_framework,QuartzCore -Wl,-weak_framework,Metal -Wl,-weak_framework,CoreHaptics -Wl,-weak_framework,GameController + LDFLAGS=$(shell for i in $$(brew deps --tree --installed fluid-synth | awk '{print $$NF}'); do brew list "$$i" | grep '.a$$') $(HOMEBREW_LIB)/libSDL2.a -lm -liconv -lz -Wl,-framework,CoreAudio -Wl,-framework,AudioToolbox -Wl,-framework,ForceFeedback -lobjc -Wl,-framework,CoreVideo -Wl,-framework,Cocoa -Wl,-framework,Carbon -Wl,-framework,IOKit -Wl,-weak_framework,QuartzCore -Wl,-weak_framework,Metal -Wl,-weak_framework,CoreHaptics -Wl,-weak_framework,GameController else ifeq ($(CROSS_COMPILE_WINDOWS),1) LDFLAGS+=-L$(MINGW32)/lib # this enables printf() to show, but also forces a console window From 5d3e1978e7c3743bbf72f3f66b8ca794000f6605 Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Sat, 21 Sep 2024 20:00:10 -0700 Subject: [PATCH 31/63] update shell expansion for static libs on mac --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index ef84616..3ff5d77 100644 --- a/Makefile +++ b/Makefile @@ -48,7 +48,7 @@ GIT_REV=$(shell git diff --quiet && /bin/echo -n $$(git rev-parse --short=8 HEAD CFLAGS+=-D GIT_REV='"$(GIT_REV)"' ifeq ($(MAC_STATIC),1) - LDFLAGS=$(shell for i in $$(brew deps --tree --installed fluid-synth | awk '{print $$NF}'); do brew list "$$i" | grep '.a$$') $(HOMEBREW_LIB)/libSDL2.a -lm -liconv -lz -Wl,-framework,CoreAudio -Wl,-framework,AudioToolbox -Wl,-framework,ForceFeedback -lobjc -Wl,-framework,CoreVideo -Wl,-framework,Cocoa -Wl,-framework,Carbon -Wl,-framework,IOKit -Wl,-weak_framework,QuartzCore -Wl,-weak_framework,Metal -Wl,-weak_framework,CoreHaptics -Wl,-weak_framework,GameController + LDFLAGS=$(shell for i in $$(brew deps --tree --installed fluid-synth | awk '{print $$NF}'); do brew list "$$i" | grep '\.a$$'; done) $(HOMEBREW_LIB)/libSDL2.a -lm -liconv -lz -Wl,-framework,CoreAudio -Wl,-framework,AudioToolbox -Wl,-framework,ForceFeedback -lobjc -Wl,-framework,CoreVideo -Wl,-framework,Cocoa -Wl,-framework,Carbon -Wl,-framework,IOKit -Wl,-weak_framework,QuartzCore -Wl,-weak_framework,Metal -Wl,-weak_framework,CoreHaptics -Wl,-weak_framework,GameController else ifeq ($(CROSS_COMPILE_WINDOWS),1) LDFLAGS+=-L$(MINGW32)/lib # this enables printf() to show, but also forces a console window From 9341874196f3d66cc1bb5560dee8854e29247c1a Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Wed, 25 Sep 2024 22:21:09 -0700 Subject: [PATCH 32/63] back to dynamic loading, lets see how this does in the actions --- .github/workflows/build.yml | 12 +---- Makefile | 9 ++-- src/midi.c | 92 +++++++++++++++++++++++++++++++------ 3 files changed, 83 insertions(+), 30 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index cb299b3..446ef52 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -209,23 +209,13 @@ jobs: sudo cp /etc/apt/sources.list /etc/apt/sources.list~ sudo sed -Ei 's/^# deb-src /deb-src /' /etc/apt/sources.list sudo apt-get update - sudo apt-get install -y build-essential make libsdl2-dev cmake + sudo apt-get install -y build-essential make libsdl2-dev libfluidsynth-dev - name: Fetch latest ROM if: startsWith(github.ref, 'refs/tags/r') != true run: | gh run download -R X16Community/x16-rom -n "ROM Image" --dir latest_rom env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Pull down and build FluidSynth - run: | - sudo apt-get build-dep fluidsynth --no-install-recommends - git clone https://github.com/FluidSynth/fluidsynth.git - cd fluidsynth - mkdir build - cd build - cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DBUILD_SHARED_LIBS=0 - make libfluidsynth - sudo make install - name: Fetch latest release ROM if: startsWith(github.ref, 'refs/tags/r') run: | diff --git a/Makefile b/Makefile index 3ff5d77..13f9363 100644 --- a/Makefile +++ b/Makefile @@ -48,13 +48,13 @@ GIT_REV=$(shell git diff --quiet && /bin/echo -n $$(git rev-parse --short=8 HEAD CFLAGS+=-D GIT_REV='"$(GIT_REV)"' ifeq ($(MAC_STATIC),1) - LDFLAGS=$(shell for i in $$(brew deps --tree --installed fluid-synth | awk '{print $$NF}'); do brew list "$$i" | grep '\.a$$'; done) $(HOMEBREW_LIB)/libSDL2.a -lm -liconv -lz -Wl,-framework,CoreAudio -Wl,-framework,AudioToolbox -Wl,-framework,ForceFeedback -lobjc -Wl,-framework,CoreVideo -Wl,-framework,Cocoa -Wl,-framework,Carbon -Wl,-framework,IOKit -Wl,-weak_framework,QuartzCore -Wl,-weak_framework,Metal -Wl,-weak_framework,CoreHaptics -Wl,-weak_framework,GameController + LDFLAGS+=$(HOMEBREW_LIB)/libSDL2.a -lm -liconv -lz -Wl,-framework,CoreAudio -Wl,-framework,AudioToolbox -Wl,-framework,ForceFeedback -lobjc -Wl,-framework,CoreVideo -Wl,-framework,Cocoa -Wl,-framework,Carbon -Wl,-framework,IOKit -Wl,-weak_framework,QuartzCore -Wl,-weak_framework,Metal -Wl,-weak_framework,CoreHaptics -Wl,-weak_framework,GameController + LDEMU=-ldl -Wl,-rpath,$(HOMEBREW_LIB) else ifeq ($(CROSS_COMPILE_WINDOWS),1) LDFLAGS+=-L$(MINGW32)/lib # this enables printf() to show, but also forces a console window LDFLAGS+=-Wl,--subsystem,console LDFLAGS+=-static-libstdc++ -static-libgcc - LDFLAGS+=-Wl,-Bstatic -lSDL2 -lfluidsynth -Wl,-Bdynamic ifeq ($(TARGET_CPU),x86) CC=i686-w64-mingw32-gcc CXX=i686-w64-mingw32-g++ @@ -63,8 +63,7 @@ else CXX=x86_64-w64-mingw32-g++ endif else # Not Mac, not Windows, probably Linux - # Link static if possible, otherwise fall back to dynamic - LDFLUID=$(shell $(CC) -static -lfluidsynth &>/dev/null && /bin/echo "-Wl,-Bstatic -lfluidsynth -Wl,-Bdynamic" || /bin/echo "-lfluidsynth") + LDEMU=-ldl endif ifdef TARGET_WIN32 @@ -99,7 +98,7 @@ MAKECART_DEPS := $(MAKECART_OBJS:.o=.d) all: x16emu makecart x16emu: $(X16_OBJS) - $(CXX) -o $(X16_OUTPUT) $(X16_OBJS) $(LDFLAGS) $(LDFLUID) + $(CXX) -o $(X16_OUTPUT) $(X16_OBJS) $(LDFLAGS) $(LDEMU) $(X16_ODIR)/%.o: $(X16_SDIR)/%.c @mkdir -p $$(dirname $@) diff --git a/src/midi.c b/src/midi.c index a8afebf..3ee1c05 100644 --- a/src/midi.c +++ b/src/midi.c @@ -50,11 +50,75 @@ static fluid_audio_driver_t* fl_adriver; static fluid_synth_t* fl_synth; static int fl_sf2id; +typedef fluid_settings_t* (*new_fluid_settings_f_t)(void); +typedef fluid_synth_t* (*new_fluid_synth_f_t)(fluid_settings_t*); +typedef fluid_audio_driver_t* (*new_fluid_audio_driver_f_t)(fluid_settings_t*, fluid_synth_t*); +typedef int (*fluid_synth_sfload_f_t)(fluid_synth_t*,const char *,int); +typedef int (*fluid_synth_program_change_f_t)(fluid_synth_t*, int, int); +typedef int (*fluid_synth_channel_pressure_f_t)(fluid_synth_t*, int, int); +typedef int (*fluid_synth_system_reset_f_t)(fluid_synth_t*); +typedef int (*fluid_synth_noteoff_f_t)(fluid_synth_t*, int, int); +typedef int (*fluid_synth_noteon_f_t)(fluid_synth_t*, int, int, int); +typedef int (*fluid_synth_key_pressure_f_t)(fluid_synth_t*, int, int, int); +typedef int (*fluid_synth_cc_f_t)(fluid_synth_t*, int, int, int); +typedef int (*fluid_synth_pitch_bend_f_t)(fluid_synth_t*, int, int); +typedef int (*fluid_synth_sysex_f_t)(fluid_synth_t*, const char*, int, char*, int*, int*, int); + +static new_fluid_settings_f_t dl_new_fluid_settings; +static new_fluid_synth_f_t dl_new_fluid_synth; +static new_fluid_audio_driver_f_t dl_new_fluid_audio_driver; +static fluid_synth_sfload_f_t dl_fs_sfload; +static fluid_synth_program_change_f_t dl_fs_program_change; +static fluid_synth_channel_pressure_f_t dl_fs_channel_pressure; +static fluid_synth_system_reset_f_t dl_fs_system_reset; +static fluid_synth_noteoff_f_t dl_fs_noteoff; +static fluid_synth_noteon_f_t dl_fs_noteon; +static fluid_synth_key_pressure_f_t dl_fs_key_pressure; +static fluid_synth_cc_f_t dl_fs_cc; +static fluid_synth_pitch_bend_f_t dl_fs_pitch_bend; +static fluid_synth_sysex_f_t dl_fs_sysex; + void midi_init() { - fl_settings = new_fluid_settings(); - fl_synth = new_fluid_synth(fl_settings); - fl_adriver = new_fluid_audio_driver(fl_settings, fl_synth); +#ifdef _WIN32 + LIBRARY_TYPE handle = LOAD_LIBRARY("libfluidsynth-3.dll"); +#elif __APPLE__ + LIBRARY_TYPE handle = LOAD_LIBRARY("libfluidsynth.dylib"); +#else + LIBRARY_TYPE handle = LOAD_LIBRARY("libfluidsynth.so"); +#endif + + if (!handle) { + // Handle the error on both platforms +#ifdef _WIN32 + fprintf(stderr, "Could not load MIDI synth library: error code %lu\n", GetLastError()); +#else + fprintf(stderr, "Could not load MIDI synth library: %s\n", dlerror()); +#endif + return; + } + +#ifndef _WIN32 + dlerror(); +#endif + + ASSIGN_FUNCTION(handle, dl_new_fluid_settings, "new_fluid_settings"); + ASSIGN_FUNCTION(handle, dl_new_fluid_synth, "new_fluid_synth"); + ASSIGN_FUNCTION(handle, dl_new_fluid_audio_driver, "new_fluid_audio_driver"); + ASSIGN_FUNCTION(handle, dl_fs_sfload, "fluid_synth_sfload"); + ASSIGN_FUNCTION(handle, dl_fs_program_change, "fluid_synth_program_change"); + ASSIGN_FUNCTION(handle, dl_fs_channel_pressure, "fluid_synth_channel_pressure"); + ASSIGN_FUNCTION(handle, dl_fs_system_reset, "fluid_synth_system_reset"); + ASSIGN_FUNCTION(handle, dl_fs_noteoff, "fluid_synth_noteoff"); + ASSIGN_FUNCTION(handle, dl_fs_noteon, "fluid_synth_noteon"); + ASSIGN_FUNCTION(handle, dl_fs_key_pressure, "fluid_synth_key_pressure"); + ASSIGN_FUNCTION(handle, dl_fs_cc, "fluid_synth_cc"); + ASSIGN_FUNCTION(handle, dl_fs_pitch_bend, "fluid_synth_pitch_bend"); + ASSIGN_FUNCTION(handle, dl_fs_sysex, "fluid_synth_sysex"); + + fl_settings = dl_new_fluid_settings(); + fl_synth = dl_new_fluid_synth(fl_settings); + fl_adriver = dl_new_fluid_audio_driver(fl_settings, fl_synth); midi_initialized = true; printf("Initialized MIDI synth.\n"); @@ -63,7 +127,7 @@ void midi_init() void midi_load_sf2(uint8_t* filename) { if (!midi_initialized) return; - fl_sf2id = fluid_synth_sfload(fl_synth, (const char *)filename, true); + fl_sf2id = dl_fs_sfload(fl_synth, (const char *)filename, true); if (fl_sf2id == FLUID_FAILED) { printf("Unable to load soundfont.\n"); } @@ -79,9 +143,9 @@ void midi_byte(uint8_t b) case NORMAL: if (b < 0x80) { if ((midi_last_command & 0xf0) == 0xc0) { // patch change - fluid_synth_program_change(fl_synth, midi_last_command & 0xf, b); + dl_fs_program_change(fl_synth, midi_last_command & 0xf, b); } else if ((midi_last_command & 0xf0) == 0xd0) { // channel pressure - fluid_synth_channel_pressure(fl_synth, midi_last_command & 0xf, b); + dl_fs_channel_pressure(fl_synth, midi_last_command & 0xf, b); } else if (midi_last_command >= 0x80) { // two-param command midi_first_param = b; midi_state = PARAM; @@ -93,7 +157,7 @@ void midi_byte(uint8_t b) sysex_bufptr = 0; midi_state = SYSEX; } else if (b == 0xff) { - fluid_synth_system_reset(fl_synth); + dl_fs_system_reset(fl_synth); midi_last_command = 0; } } @@ -101,23 +165,23 @@ void midi_byte(uint8_t b) case PARAM: switch (midi_last_command & 0xf0) { case 0x80: // note off - fluid_synth_noteoff(fl_synth, midi_last_command & 0xf, midi_first_param); // no release velocity + dl_fs_noteoff(fl_synth, midi_last_command & 0xf, midi_first_param); // no release velocity break; case 0x90: // note on if (b == 0) { - fluid_synth_noteoff(fl_synth, midi_last_command & 0xf, midi_first_param); + dl_fs_noteoff(fl_synth, midi_last_command & 0xf, midi_first_param); } else { - fluid_synth_noteon(fl_synth, midi_last_command & 0xf, midi_first_param, b); + dl_fs_noteon(fl_synth, midi_last_command & 0xf, midi_first_param, b); } break; case 0xa0: // aftertouch - fluid_synth_key_pressure(fl_synth, midi_last_command & 0xf, midi_first_param, b); + dl_fs_key_pressure(fl_synth, midi_last_command & 0xf, midi_first_param, b); break; case 0xb0: // controller - fluid_synth_cc(fl_synth, midi_last_command & 0xf, midi_first_param, b); + dl_fs_cc(fl_synth, midi_last_command & 0xf, midi_first_param, b); break; case 0xe0: // pitch bend - fluid_synth_pitch_bend(fl_synth, midi_last_command & 0xf, ((uint16_t)midi_first_param) | (uint16_t)b << 7); + dl_fs_pitch_bend(fl_synth, midi_last_command & 0xf, ((uint16_t)midi_first_param) | (uint16_t)b << 7); break; } midi_state = NORMAL; @@ -125,7 +189,7 @@ void midi_byte(uint8_t b) case SYSEX: if (b == 0xf7) { sysex_buffer[sysex_bufptr] = 0; - fluid_synth_sysex(fl_synth, (const char *)sysex_buffer, sysex_bufptr, NULL, NULL, NULL, 0); + dl_fs_sysex(fl_synth, (const char *)sysex_buffer, sysex_bufptr, NULL, NULL, NULL, 0); midi_state = NORMAL; } else { sysex_buffer[sysex_bufptr++] = b; From ad76f2b222d1782ab8def4d9afbc7f50367c97d2 Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Sun, 29 Sep 2024 01:14:04 -0700 Subject: [PATCH 33/63] full serial port behaviors --- src/main.c | 3 + src/memory.c | 4 +- src/midi.c | 482 ++++++++++++++++++++++++++++++++++++++++++++++----- src/midi.h | 5 + 4 files changed, 446 insertions(+), 48 deletions(-) diff --git a/src/main.c b/src/main.c index f88cd5f..56aa659 100644 --- a/src/main.c +++ b/src/main.c @@ -333,6 +333,7 @@ machine_reset() video_reset(); mouse_state_init(); reset6502(regs.is65c816); + midi_serial_init(); } void @@ -1603,6 +1604,8 @@ emulator_loop(void *param) audio_step(clocks); } + midi_serial_step(clocks); + if (!headless && new_frame) { if (nvram_dirty && nvram_path) { SDL_RWops *f = SDL_RWFromFile(nvram_path, "wb"); diff --git a/src/memory.c b/src/memory.c index 5f5d726..daeed2e 100644 --- a/src/memory.c +++ b/src/memory.c @@ -200,7 +200,7 @@ real_read6502(uint16_t address, bool debugOn, int16_t bank) return 0x9f; // open bus read } else if (address >= 0x9f60 && address < 0x9f70) { // midi card - return midi_serial_read(address & 0x7, debugOn); + return midi_serial_read(address & 0xf, debugOn); } else if (address >= 0x9fb0 && address < 0x9fc0) { // emulator state return emu_read(address & 0xf, debugOn); @@ -279,7 +279,7 @@ write6502(uint16_t address, uint8_t value) YM_write_reg(addr_ym, value); } } else if (address >= 0x9f60 && address < 0x9f70) { - midi_serial_write(address & 0x7, value); + midi_serial_write(address & 0xf, value); } else if (address >= 0x9fb0 && address < 0x9fc0) { // emulator state emu_write(address & 0xf, value); diff --git a/src/midi.c b/src/midi.c index 3ee1c05..456af32 100644 --- a/src/midi.c +++ b/src/midi.c @@ -2,6 +2,7 @@ // Copyright (c) 2024 MooingLemur // All rights reserved. License: 2-clause BSD +#include #include "glue.h" #include "midi.h" @@ -30,8 +31,95 @@ enum MIDI_states { SYSEX, }; -static bool serial_dlab = false; -static uint8_t serial_dll, serial_dlm, serial_spr; +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#define LOW_HIGH_UNION(name, low, high) \ + union { \ + struct { \ + uint8_t low; \ + uint8_t high; \ + }; \ + uint16_t name; \ + } +#else +#define LOW_HIGH_UNION(name, low, high) \ + union { \ + struct { \ + uint8_t high; \ + uint8_t low; \ + }; \ + uint16_t name; \ + } +#endif + +struct midi_serial_regs +{ + LOW_HIGH_UNION(dl, dll, dlm); + + bool ier_erbi; + bool ier_etbei; + bool ier_elsi; + bool ier_edssi; + + uint8_t iir; + + bool fcr_fifo_enable; + uint8_t fcr_ififo_trigger_level_bytes; + + uint8_t lcr_word_length_bits; + bool lcr_stb; + bool lcr_pen; + bool lcr_eps; + bool lcr_stick; + bool lcr_break; + bool lcr_dlab; + + bool mcr_dtr; + bool mcr_rts; + bool mcr_out1; + bool mcr_out2; + bool mcr_loop; + bool mcr_afe; + + bool lsr_oe; + bool lsr_pe; + bool lsr_fe; + bool lsr_bi; + bool lsr_eif; + + bool msr_dcts; + bool msr_ddsr; + bool msr_teri; + bool msr_ddcd; + bool msr_cts; + bool msr_dsr; + bool msr_ri; + bool msr_dcd; + + uint8_t obyte_bits_remain; + uint8_t rx_timeout; + bool rx_timeout_enabled; + + bool thre_intr; + uint8_t thre_bits_remain; + + uint8_t scratch; + uint8_t ififo[16]; + uint8_t ifsz; + uint8_t ofifo[16]; + uint8_t ofsz; + + int64_t clock; // 40.24 fixed point + int32_t clockdec; // 8.24 fixed point + + time_t last_warning; + + pthread_mutex_t fifo_mutex; + pthread_mutexattr_t fifo_mutex_attr; +}; + +#undef LOW_HIGH_UNION + +struct midi_serial_regs mregs[2]; #ifndef __EMSCRIPTEN__ @@ -43,6 +131,7 @@ static uint8_t midi_last_command = 0; static uint8_t midi_first_param; static bool midi_initialized = false; +static bool serial_midi_mutexes_initialized = false; static fluid_settings_t* fl_settings; //static fluid_midi_driver_t* fl_mdriver; @@ -80,6 +169,10 @@ static fluid_synth_sysex_f_t dl_fs_sysex; void midi_init() { + if (midi_initialized) { + return; + } + #ifdef _WIN32 LIBRARY_TYPE handle = LOAD_LIBRARY("libfluidsynth-3.dll"); #elif __APPLE__ @@ -138,7 +231,6 @@ void midi_load_sf2(uint8_t* filename) void midi_byte(uint8_t b) { if (!midi_initialized) return; - switch (midi_state) { case NORMAL: if (b < 0x80) { @@ -188,11 +280,18 @@ void midi_byte(uint8_t b) break; case SYSEX: if (b == 0xf7) { - sysex_buffer[sysex_bufptr] = 0; - dl_fs_sysex(fl_synth, (const char *)sysex_buffer, sysex_bufptr, NULL, NULL, NULL, 0); + if (sysex_bufptr < (sizeof(sysex_buffer) / sizeof(sysex_buffer[0]))-1) { // only if buffer didn't fill + sysex_buffer[sysex_bufptr] = 0; + dl_fs_sysex(fl_synth, (const char *)sysex_buffer, sysex_bufptr, NULL, NULL, NULL, 0); + } midi_state = NORMAL; } else { - sysex_buffer[sysex_bufptr++] = b; + sysex_buffer[sysex_bufptr] = b; + // we can't do much about a runaway sysex other than continue to absorb it + // but we throw it all away later if the buffer filled + if (sysex_bufptr < (sizeof(sysex_buffer) / sizeof(sysex_buffer[0]))-1) { + sysex_bufptr++; + } } break; } @@ -206,93 +305,384 @@ void midi_load_sf2(uint8_t* filename) void midi_init() { - printf("No fluidsynth support on WebAssembly.\n"); + fprintf(stderr, "No FluidSynth support.\n"); } -void midi_byte(uint8_t b) { +void midi_byte(uint8_t b) +{ // no-op } #endif +void midi_serial_init() +{ + uint8_t sel; + + for (sel=0; sel<2; sel++) { + mregs[sel].ier_erbi = false; + mregs[sel].ier_etbei = false; + mregs[sel].ier_elsi = false; + mregs[sel].ier_edssi = false; + + mregs[sel].iir = 0x01; + + mregs[sel].fcr_fifo_enable = false; + mregs[sel].fcr_ififo_trigger_level_bytes = 1; + + mregs[sel].lcr_word_length_bits = 5; + mregs[sel].lcr_stb = false; + mregs[sel].lcr_pen = false; + mregs[sel].lcr_eps = false; + mregs[sel].lcr_stick = false; + mregs[sel].lcr_break = false; + mregs[sel].lcr_dlab = false; + + mregs[sel].mcr_dtr = false; + mregs[sel].mcr_rts = false; + mregs[sel].mcr_out1 = false; + mregs[sel].mcr_out2 = false; + mregs[sel].mcr_loop = false; + mregs[sel].mcr_afe = false; + + mregs[sel].lsr_oe = false; + mregs[sel].lsr_pe = false; + mregs[sel].lsr_fe = false; + mregs[sel].lsr_bi = false; + mregs[sel].lsr_eif = false; + + mregs[sel].msr_dcts = false; + mregs[sel].msr_ddsr = false; + mregs[sel].msr_teri = false; + mregs[sel].msr_ddcd = false; + + mregs[sel].msr_cts = false; + mregs[sel].msr_dsr = false; + mregs[sel].msr_ri = false; + mregs[sel].msr_dcd = false; + + mregs[sel].obyte_bits_remain = 0; + mregs[sel].rx_timeout = 0; + mregs[sel].rx_timeout_enabled = false; + mregs[sel].thre_intr = false; + mregs[sel].thre_bits_remain = 0; + + mregs[sel].ifsz = 0; + mregs[sel].ofsz = 0; + mregs[sel].clock = 0; + mregs[sel].clockdec = 0; + mregs[sel].last_warning = 0; + + } + + if (!serial_midi_mutexes_initialized) { + for (sel=0; sel<2; sel++) { + pthread_mutexattr_init(&mregs[sel].fifo_mutex_attr); + pthread_mutex_init(&mregs[sel].fifo_mutex, &mregs[sel].fifo_mutex_attr); + } + serial_midi_mutexes_initialized = true; + } +} + +void midi_serial_step(int clocks) +{ + uint8_t sel, i; + for (sel=0; sel<2; sel++) { + mregs[sel].clock -= (int64_t)mregs[sel].clockdec * clocks; + while (mregs[sel].clock < 0) { + // process uart + pthread_mutex_lock(&mregs[sel].fifo_mutex); + if (mregs[sel].obyte_bits_remain > 0) { + mregs[sel].obyte_bits_remain--; + } + if (mregs[sel].ofsz > 0) { + if (mregs[sel].obyte_bits_remain == 0) { + if (sel == 1) { + midi_byte(mregs[sel].ofifo[0]); + } + mregs[sel].ofsz--; + if (mregs[sel].ofsz > 0) { + for (i=0; i 0) { + mregs[sel].thre_bits_remain--; + if (mregs[sel].thre_bits_remain == 0) { + mregs[sel].thre_intr = true; + } + } + } + pthread_mutex_unlock(&mregs[sel].fifo_mutex); + mregs[sel].clock += 0x1000000LL; + } + } +} + +void midi_serial_enqueue_obyte(uint8_t sel, uint8_t val) { + pthread_mutex_lock(&mregs[sel].fifo_mutex); + if (mregs[sel].ofsz < (mregs[sel].fcr_fifo_enable ? 16 : 1)) { + mregs[sel].ofifo[mregs[sel].ofsz] = val; + mregs[sel].thre_intr = false; + mregs[sel].ofsz++; + if (mregs[sel].ofsz == 1) { // We were empty + if (mregs[sel].fcr_fifo_enable) { + // We delay a bit longer to reraise the THRE interrupt if we're coming from 0 + mregs[sel].thre_bits_remain = 1 + mregs[sel].lcr_word_length_bits + mregs[sel].lcr_stb + mregs[sel].lcr_pen; + } + } else { + mregs[sel].thre_bits_remain = 0; + } + } else { + printf("TX Overflow\n"); + } + pthread_mutex_unlock(&mregs[sel].fifo_mutex); +} + +void midi_serial_iir_check(uint8_t sel) { + uint8_t fifoen = (uint8_t)mregs[sel].fcr_fifo_enable << 6 | (uint8_t)mregs[sel].fcr_fifo_enable << 7; + if (mregs[sel].ier_elsi && (mregs[sel].lsr_oe || mregs[sel].lsr_pe || mregs[sel].lsr_fe || mregs[sel].lsr_bi)) { + mregs[sel].iir = (0x06 | fifoen); // Receiver line status interrupt + } else if (mregs[sel].ier_erbi && !mregs[sel].fcr_fifo_enable && mregs[sel].ifsz > 0) { + mregs[sel].iir = (0x04 | fifoen); // Received data available interrupt (16450 mode) + } else if (mregs[sel].ier_erbi && mregs[sel].fcr_fifo_enable && mregs[sel].ifsz >= mregs[sel].fcr_ififo_trigger_level_bytes) { + mregs[sel].iir = (0x04 | fifoen); // Received data available interrupt (16550 mode) + } else if (mregs[sel].ier_erbi && mregs[sel].fcr_fifo_enable && mregs[sel].ifsz > 0 && mregs[sel].rx_timeout_enabled && mregs[sel].rx_timeout == 0) { + mregs[sel].iir = (0x0c | fifoen); // Received data available interrupt (timeout, 16550 mode) + } else if (mregs[sel].ier_etbei && mregs[sel].thre_intr) { + mregs[sel].iir = (0x02 | fifoen); // Transmitter holding register empty interrupt + } else if (mregs[sel].ier_edssi && ((!mregs[sel].mcr_afe && mregs[sel].msr_dcts) || mregs[sel].msr_ddcd || mregs[sel].msr_ddsr || mregs[sel].msr_teri)) { + mregs[sel].iir = (0x00 | fifoen); // Modem status register interrupt + } else { + mregs[sel].iir = (0x01 | fifoen); // no interrupt waiting + } +} -uint8_t midi_serial_read(uint8_t reg, bool debugOn) { +uint8_t midi_serial_read(uint8_t reg, bool debugOn) +{ //printf("midi_serial_read %d\n", reg); - switch (reg) { + uint8_t sel = (reg & 8) >> 3; + switch (reg & 7) { case 0x0: - if (serial_dlab) { - return serial_dll; + if (mregs[sel].lcr_dlab) { + return mregs[sel].dll; } else { // TODO: RHR } break; case 0x1: - if (serial_dlab) { - return serial_dlm; + if (mregs[sel].lcr_dlab) { + return mregs[sel].dlm; + } else { + return (((uint8_t)mregs[sel].ier_edssi << 3) | + ((uint8_t)mregs[sel].ier_elsi << 2) | + ((uint8_t)mregs[sel].ier_etbei << 1) | + ((uint8_t)mregs[sel].ier_erbi)); } - return 0x00; - // TODO: IER break; - case 0x2: - return 0x00; - // TODO: ISR + case 0x2: { + uint8_t ret = mregs[sel].iir; + if (!debugOn) { + mregs[sel].thre_intr = false; + midi_serial_iir_check(sel); + } + return ret; break; + } case 0x3: - return 0x03 | ((int)serial_dlab << 7); - // TODO: rest of LCR + return (((uint8_t)mregs[sel].lcr_dlab << 7) | + ((uint8_t)mregs[sel].lcr_break << 6) | + ((uint8_t)mregs[sel].lcr_stick << 5) | + ((uint8_t)mregs[sel].lcr_eps << 4) | + ((uint8_t)mregs[sel].lcr_pen << 3) | + ((uint8_t)mregs[sel].lcr_stb << 2) | + ((mregs[sel].lcr_word_length_bits - 5) & 0x3)); break; case 0x4: - return 0x03; - // TODO: MCR + return (((uint8_t)mregs[sel].mcr_afe << 5) | + ((uint8_t)mregs[sel].mcr_loop << 4) | + ((uint8_t)mregs[sel].mcr_out2 << 3) | + ((uint8_t)mregs[sel].mcr_out1 << 2) | + ((uint8_t)mregs[sel].mcr_rts << 1) | + ((uint8_t)mregs[sel].mcr_dtr)); break; - case 0x5: - return 0x20; - // TODO: LSR + case 0x5: { + uint8_t ret = (((uint8_t)mregs[sel].lsr_eif << 7) | + ((uint8_t)(mregs[sel].obyte_bits_remain == 0 && mregs[sel].ofsz == 0) << 6) | + ((uint8_t)(mregs[sel].ofsz == 0) << 5) | + ((uint8_t)mregs[sel].lsr_bi << 4) | + ((uint8_t)mregs[sel].lsr_fe << 3) | + ((uint8_t)mregs[sel].lsr_pe << 2) | + ((uint8_t)mregs[sel].lsr_oe << 1) | + ((uint8_t)(mregs[sel].ifsz > 0))); + if (!debugOn) { + mregs[sel].lsr_oe = false; + mregs[sel].lsr_pe = false; + mregs[sel].lsr_fe = false; + mregs[sel].lsr_bi = false; + } + return ret; break; + } case 0x6: - return 0x00; - // TODO: MSR + return (((uint8_t)mregs[sel].msr_dcd << 7) | + ((uint8_t)mregs[sel].msr_ri << 6) | + ((uint8_t)mregs[sel].msr_dsr << 5) | + ((uint8_t)mregs[sel].msr_cts << 4) | + ((uint8_t)mregs[sel].msr_ddcd << 3) | + ((uint8_t)mregs[sel].msr_teri << 2) | + ((uint8_t)mregs[sel].msr_ddsr << 1) | + ((uint8_t)mregs[sel].msr_dcts)); break; case 0x7: - return serial_spr; + return mregs[sel].scratch; break; } return 0x00; } -void midi_serial_write(uint8_t reg, uint8_t val) { +void midi_serial_calculate_clk(uint8_t sel) +{ + double uart_clks_per_cpu = (MIDI_UART_OSC_RATE_MHZ / MIDI_UART_PRIMARY_DIVIDER) / MHZ; + if (mregs[sel].dl > 0) { + uart_clks_per_cpu /= mregs[sel].dl; + mregs[sel].clockdec = uart_clks_per_cpu * 0x1000000L; // convert to 8.24 fixed point + } else { + mregs[sel].clockdec = 0; + } +} + +void midi_serial_write(uint8_t reg, uint8_t val) +{ //printf("midi_serial_write %d %d\n", reg, val); - switch (reg) { + uint8_t sel = (reg & 8) >> 3; + switch (reg & 7) { case 0x0: - if (serial_dlab) { - serial_dll = val; + if (mregs[sel].lcr_dlab) { + mregs[sel].dll = val; + midi_serial_calculate_clk(sel); } else { - midi_byte((uint8_t)val); + if (mregs[sel].lcr_word_length_bits != 8 || mregs[sel].lcr_stb || mregs[sel].lcr_pen || mregs[sel].lcr_eps || mregs[sel].lcr_stick || mregs[sel].lcr_break) { + if (mregs[sel].last_warning + 60 < time(NULL)) { + unsigned char par = 'N'; + if (mregs[sel].lcr_pen) { + switch ((uint8_t)(mregs[sel].lcr_eps << 1) | (uint8_t)mregs[sel].lcr_stick) { + case 0: + par = 'O'; + break; + case 1: + par = 'M'; + break; + case 2: + par = 'E'; + break; + case 3: + par = 'S'; + break; + } + } + fprintf(stderr, "Serial MIDI: Warning: improper LCR %d%c%d for UART %d, must be set to 8N1.\n", mregs[sel].lcr_word_length_bits, par, 1+(uint8_t)mregs[sel].lcr_stb, sel); + mregs[sel].last_warning = time(NULL); + } + } else if (mregs[sel].dl != 32 && mregs[sel].last_warning + 60 < time(NULL)) { + fprintf(stderr, "Serial MIDI: Warning: improper divisor %d for UART %d, must be set to 32 for standard MIDI bitrate.\n", mregs[sel].dl, sel); + mregs[sel].last_warning = time(NULL); + } else { + midi_serial_enqueue_obyte(sel, val); + } } break; case 0x1: - if (serial_dlab) { - serial_dlm = val; + if (mregs[sel].lcr_dlab) { + mregs[sel].dlm = val; + midi_serial_calculate_clk(sel); + } else { + mregs[sel].ier_erbi = !!(val & 1); + mregs[sel].ier_etbei = !!(val & 2); + mregs[sel].ier_elsi = !!(val & 4); + mregs[sel].ier_edssi = !!(val & 8); } - // TODO: IER break; case 0x2: - // TODO: FCR + if (val & 1) { + mregs[sel].fcr_fifo_enable = true; + switch ((val & 0xc0) >> 6) { + case 0: + mregs[sel].fcr_ififo_trigger_level_bytes = 1; + break; + case 1: + mregs[sel].fcr_ififo_trigger_level_bytes = 4; + break; + case 2: + mregs[sel].fcr_ififo_trigger_level_bytes = 8; + break; + case 3: + mregs[sel].fcr_ififo_trigger_level_bytes = 14; + break; + } + } else { + mregs[sel].fcr_fifo_enable = false; + mregs[sel].fcr_ififo_trigger_level_bytes = 1; + } + if (val & 2) { + mregs[sel].ifsz = 0; + } + if (val & 4) { + mregs[sel].ofsz = 0; + } + if (mregs[sel].thre_bits_remain == 0) { + mregs[sel].thre_intr = true; + } + midi_serial_iir_check(sel); break; case 0x3: - serial_dlab = (bool)(val >> 7); - // TODO: rest of LCR + mregs[sel].lcr_word_length_bits = (val & 0x03)+5; + mregs[sel].lcr_stb = !!(val & 0x04); + mregs[sel].lcr_pen = !!(val & 0x08); + mregs[sel].lcr_eps = !!(val & 0x10); + mregs[sel].lcr_stick = !!(val & 0x20); + mregs[sel].lcr_break = !!(val & 0x40); + mregs[sel].lcr_dlab = !!(val & 0x80); break; case 0x4: - // TODO: MCR - break; - case 0x5: - if (serial_dlab) { - // TODO: PSD + mregs[sel].mcr_dtr = !!(val & 0x01); + mregs[sel].mcr_rts = !!(val & 0x02); + mregs[sel].mcr_out1 = !!(val & 0x04); + mregs[sel].mcr_out2 = !!(val & 0x08); + mregs[sel].mcr_loop = !!(val & 0x10); + mregs[sel].mcr_afe = !!(val & 0x20); + + if (mregs[sel].mcr_loop) { + mregs[sel].msr_dcts |= mregs[sel].msr_cts ^ mregs[sel].mcr_dtr; + mregs[sel].msr_cts = mregs[sel].mcr_dtr; + + mregs[sel].msr_ddsr |= mregs[sel].msr_dsr ^ mregs[sel].mcr_rts; + mregs[sel].msr_dsr = mregs[sel].mcr_rts; + + if (mregs[sel].msr_ri) { + mregs[sel].msr_teri |= mregs[sel].msr_ri ^ mregs[sel].mcr_out1; + } + mregs[sel].msr_ri = mregs[sel].mcr_out1; + + mregs[sel].msr_ddcd |= mregs[sel].msr_dcd ^ mregs[sel].mcr_out2; + mregs[sel].msr_dcd = mregs[sel].mcr_out2; + + } else { + // DTR tied to RI on opposite UART, wired this way on the official X16 MIDI card + if (mregs[sel ^ 1].msr_ri && !mregs[sel].mcr_dtr) { + mregs[sel ^ 1].msr_teri = true; + } + mregs[sel ^ 1].msr_ri = mregs[sel].mcr_dtr; } + break; case 0x7: - serial_spr = val; + mregs[sel].scratch = val; break; } } diff --git a/src/midi.h b/src/midi.h index 5fac2d3..d39738f 100644 --- a/src/midi.h +++ b/src/midi.h @@ -8,7 +8,12 @@ #include #endif +#define MIDI_UART_OSC_RATE_MHZ 16.0f +#define MIDI_UART_PRIMARY_DIVIDER 16 + void midi_init(); +void midi_serial_init(); +void midi_serial_step(int clocks); uint8_t midi_serial_read(uint8_t reg, bool debugOn); void midi_serial_write(uint8_t reg, uint8_t val); void midi_load_sf2(uint8_t* filename); From a7f27c883ccc70fd92eb02f642a1fea17ff9b3a0 Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Sun, 29 Sep 2024 13:05:54 -0700 Subject: [PATCH 34/63] fix some build problems --- Makefile | 2 +- src/midi.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 13f9363..235f229 100644 --- a/Makefile +++ b/Makefile @@ -18,7 +18,7 @@ endif CFLAGS=-std=c99 -O3 -Wall -Werror -g $(shell $(SDL2CONFIG) --cflags) -Isrc/extern/include CXXFLAGS=-std=c++17 -O3 -Wall -Werror -Isrc/extern/ymfm/src -LDFLAGS=$(shell $(SDL2CONFIG) --libs) -lm -lz +LDFLAGS=$(shell $(SDL2CONFIG) --libs) -lm -lz -pthread # build with link time optimization ifndef NOLTO diff --git a/src/midi.c b/src/midi.c index 456af32..7e01685 100644 --- a/src/midi.c +++ b/src/midi.c @@ -120,6 +120,7 @@ struct midi_serial_regs #undef LOW_HIGH_UNION struct midi_serial_regs mregs[2]; +static bool serial_midi_mutexes_initialized = false; #ifndef __EMSCRIPTEN__ @@ -131,7 +132,6 @@ static uint8_t midi_last_command = 0; static uint8_t midi_first_param; static bool midi_initialized = false; -static bool serial_midi_mutexes_initialized = false; static fluid_settings_t* fl_settings; //static fluid_midi_driver_t* fl_mdriver; From c98aea78347ecaaef8fcdcf1be801a4bfa8c3a78 Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Sun, 29 Sep 2024 23:11:52 -0700 Subject: [PATCH 35/63] fluidsynth audio now routed into the x16emu mixer rather than creating its own channel --- src/audio.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++---- src/midi.c | 22 +++++++++++++++--- src/midi.h | 1 + 3 files changed, 82 insertions(+), 8 deletions(-) diff --git a/src/audio.c b/src/audio.c index 4171aba..f258ab2 100644 --- a/src/audio.c +++ b/src/audio.c @@ -8,6 +8,7 @@ #include "vera_pcm.h" #include "wav_recorder.h" #include "ymglue.h" +#include "midi.h" #include #include #include @@ -23,6 +24,7 @@ #define VERA_SAMP_CLKS_PER_CPU_CLK ((25000000ULL << SAMP_POS_FRAC_BITS) / 512 / MHZ / 1000000) #define YM_SAMP_CLKS_PER_CPU_CLK ((3579545ULL << SAMP_POS_FRAC_BITS) / 64 / MHZ / 1000000) +#define FS_SAMP_CLKS_PER_CPU_CLK VERA_SAMP_CLKS_PER_CPU_CLK #define SAMPLE_BYTES (2 * sizeof(int16_t)) #define SAMP_POS_MASK (SAMPLES_PER_BUFFER - 1) #define SAMP_POS_MASK_FRAC (((uint32_t)SAMPLES_PER_BUFFER << SAMP_POS_FRAC_BITS) - 1) @@ -75,13 +77,18 @@ static uint32_t vera_samp_pos_hd = 0; static uint32_t ym_samp_pos_rd = 0; static uint32_t ym_samp_pos_wr = 0; static uint32_t ym_samp_pos_hd = 0; +static uint32_t fs_samp_pos_rd = 0; +static uint32_t fs_samp_pos_wr = 0; +static uint32_t fs_samp_pos_hd = 0; static uint32_t vera_samps_per_host_samps = 0; static uint32_t ym_samps_per_host_samps = 0; +static uint32_t fs_samps_per_host_samps = 0; static uint32_t limiter_amp = 0; static int16_t psg_buf[2 * SAMPLES_PER_BUFFER]; static int16_t pcm_buf[2 * SAMPLES_PER_BUFFER]; static int16_t ym_buf[2 * SAMPLES_PER_BUFFER]; +static int16_t fs_buf[2 * SAMPLES_PER_BUFFER]; uint32_t host_sample_rate = 0; @@ -181,17 +188,22 @@ audio_init(const char *dev_name, int num_audio_buffers) host_sample_rate = obtained.freq; vera_samps_per_host_samps = ((25000000ULL << SAMP_POS_FRAC_BITS) / 512 / host_sample_rate); ym_samps_per_host_samps = ((3579545ULL << SAMP_POS_FRAC_BITS) / 64 / host_sample_rate); + fs_samps_per_host_samps = vera_samps_per_host_samps; vera_samp_pos_rd = 0; vera_samp_pos_wr = 0; vera_samp_pos_hd = 0; ym_samp_pos_rd = 0; ym_samp_pos_wr = 0; ym_samp_pos_hd = 0; + fs_samp_pos_rd = 0; + fs_samp_pos_wr = 0; + fs_samp_pos_hd = 0; limiter_amp = (1 << 16); psg_buf[0] = psg_buf[1] = 0; pcm_buf[0] = pcm_buf[1] = 0; ym_buf[0] = ym_buf[1] = 0; + fs_buf[0] = fs_buf[1] = 0; // Start playback SDL_PauseAudioDevice(audio_dev, 0); @@ -228,6 +240,7 @@ audio_step(int cpu_clocks) uint32_t max_cpu_clks = SDL_min(cpu_clocks, max_cpu_clks_ym); vera_samp_pos_hd = (vera_samp_pos_hd + max_cpu_clks * VERA_SAMP_CLKS_PER_CPU_CLK) & SAMP_POS_MASK_FRAC; ym_samp_pos_hd = (ym_samp_pos_hd + max_cpu_clks * YM_SAMP_CLKS_PER_CPU_CLK) & SAMP_POS_MASK_FRAC; + fs_samp_pos_hd = (fs_samp_pos_hd + max_cpu_clks * FS_SAMP_CLKS_PER_CPU_CLK) & SAMP_POS_MASK_FRAC; cpu_clocks -= max_cpu_clks; if (cpu_clocks > 0) audio_render(); } @@ -271,16 +284,31 @@ audio_render() YM_stream_update((uint16_t *)&ym_buf[pos * 2], len); } + pos = (fs_samp_pos_wr + 1) & SAMP_POS_MASK; + len = ((fs_samp_pos_hd >> SAMP_POS_FRAC_BITS) - fs_samp_pos_wr) & SAMP_POS_MASK; + fs_samp_pos_wr = fs_samp_pos_hd >> SAMP_POS_FRAC_BITS; + if ((pos + len) > SAMPLES_PER_BUFFER) { + midi_synth_render(&fs_buf[pos * 2], SAMPLES_PER_BUFFER - pos); + len -= SAMPLES_PER_BUFFER - pos; + pos = 0; + } + if (len > 0) { + midi_synth_render(&fs_buf[pos * 2], len); + } + uint32_t wridx_old = wridx; uint32_t len_vera = (vera_samp_pos_hd - vera_samp_pos_rd) & SAMP_POS_MASK_FRAC; uint32_t len_ym = (ym_samp_pos_hd - ym_samp_pos_rd) & SAMP_POS_MASK_FRAC; - if (len_vera < (4 << SAMP_POS_FRAC_BITS) || len_ym < (4 << SAMP_POS_FRAC_BITS)) { + uint32_t len_fs = (fs_samp_pos_hd - fs_samp_pos_rd) & SAMP_POS_MASK_FRAC; + if (len_vera < (4 << SAMP_POS_FRAC_BITS) || len_ym < (4 << SAMP_POS_FRAC_BITS) || len_fs < (4 << SAMP_POS_FRAC_BITS)) { // not enough samples yet, at least 4 are needed for the filter return; } len_vera = (len_vera - (4 << SAMP_POS_FRAC_BITS)) / vera_samps_per_host_samps; len_ym = (len_ym - (4 << SAMP_POS_FRAC_BITS)) / ym_samps_per_host_samps; + len_fs = (len_fs - (4 << SAMP_POS_FRAC_BITS)) / fs_samps_per_host_samps; len = SDL_min(len_vera, len_ym); + len = SDL_min(len, len_fs); SDL_LockAudioDevice(audio_dev); for (int i = 0; i < len; i++) { int32_t samp[8]; @@ -289,6 +317,8 @@ audio_render() int32_t vera_out_r = 0; int32_t ym_out_l = 0; int32_t ym_out_r = 0; + int32_t fs_out_l = 0; + int32_t fs_out_r = 0; // Don't resample VERA outputs if the host sample rate is as desired if (host_sample_rate == AUDIO_SAMPLERATE) { pos = (vera_samp_pos_rd >> SAMP_POS_FRAC_BITS) * 2; @@ -326,11 +356,33 @@ audio_render() ym_out_r += samp[5] * filter[255 - filter_idx]; ym_out_l += samp[6] * filter[511 - filter_idx]; ym_out_r += samp[7] * filter[511 - filter_idx]; - // Mixing is according to the Developer Board + // Don't resample MIDI synth outputs if the host sample rate matches it + if (host_sample_rate == AUDIO_SAMPLERATE) { + pos = (fs_samp_pos_rd >> SAMP_POS_FRAC_BITS) * 2; + fs_out_l = (uint32_t)fs_buf[pos] << 14; + fs_out_r = (uint32_t)fs_buf[pos + 1] << 14; + } else { + filter_idx = (fs_samp_pos_rd >> (SAMP_POS_FRAC_BITS - 8)) & 0xff; + pos = (fs_samp_pos_rd >> SAMP_POS_FRAC_BITS) * 2; + for (int j = 0; j < 8; j += 2) { + samp[j] = fs_buf[pos]; + samp[j + 1] = fs_buf[pos + 1]; + pos = (pos + 2) & (SAMP_POS_MASK * 2); + } + fs_out_l += samp[0] * filter[256 + filter_idx]; + fs_out_r += samp[1] * filter[256 + filter_idx]; + fs_out_l += samp[2] * filter[ 0 + filter_idx]; + fs_out_r += samp[3] * filter[ 0 + filter_idx]; + fs_out_l += samp[4] * filter[255 - filter_idx]; + fs_out_r += samp[5] * filter[255 - filter_idx]; + fs_out_l += samp[6] * filter[511 - filter_idx]; + fs_out_r += samp[7] * filter[511 - filter_idx]; + } + // VERA+YM mixing is according to the Developer Board // Loudest single PSG channel is 1/8 times the max output - // mix = (psg + pcm) * 2 + ym - int32_t mix_l = (vera_out_l >> 13) + (ym_out_l >> 15); - int32_t mix_r = (vera_out_r >> 13) + (ym_out_r >> 15); + // mix = (psg + pcm) * 2 + ym + fs + int32_t mix_l = (vera_out_l >> 13) + (ym_out_l >> 15) + (fs_out_l >> 13); + int32_t mix_r = (vera_out_r >> 13) + (ym_out_r >> 15) + (fs_out_r >> 13); uint32_t amp = SDL_max(SDL_abs(mix_l), SDL_abs(mix_r)); if (amp > 32767) { uint32_t limiter_amp_new = (32767 << 16) / amp; @@ -341,6 +393,7 @@ audio_render() if (limiter_amp < (1 << 16)) limiter_amp++; vera_samp_pos_rd = (vera_samp_pos_rd + vera_samps_per_host_samps) & SAMP_POS_MASK_FRAC; ym_samp_pos_rd = (ym_samp_pos_rd + ym_samps_per_host_samps) & SAMP_POS_MASK_FRAC; + fs_samp_pos_rd = (fs_samp_pos_rd + fs_samps_per_host_samps) & SAMP_POS_MASK_FRAC; if (wridx == buffer_size) { wav_recorder_process(&buffer[wridx_old], (buffer_size - wridx_old) / 2); wridx = 0; @@ -368,6 +421,10 @@ audio_render() if (skip > 1) { ym_samp_pos_rd = (ym_samp_pos_rd + ym_samps_per_host_samps) & SAMP_POS_MASK_FRAC; } + skip = len_fs - len; + if (skip > 1) { + fs_samp_pos_rd = (fs_samp_pos_rd + fs_samps_per_host_samps) & SAMP_POS_MASK_FRAC; + } } void diff --git a/src/midi.c b/src/midi.c index 7e01685..7ed2d78 100644 --- a/src/midi.c +++ b/src/midi.c @@ -5,6 +5,7 @@ #include #include "glue.h" #include "midi.h" +#include "audio.h" #ifdef _WIN32 #include @@ -135,14 +136,15 @@ static bool midi_initialized = false; static fluid_settings_t* fl_settings; //static fluid_midi_driver_t* fl_mdriver; -static fluid_audio_driver_t* fl_adriver; +//static fluid_audio_driver_t* fl_adriver; static fluid_synth_t* fl_synth; static int fl_sf2id; typedef fluid_settings_t* (*new_fluid_settings_f_t)(void); typedef fluid_synth_t* (*new_fluid_synth_f_t)(fluid_settings_t*); typedef fluid_audio_driver_t* (*new_fluid_audio_driver_f_t)(fluid_settings_t*, fluid_synth_t*); -typedef int (*fluid_synth_sfload_f_t)(fluid_synth_t*,const char *,int); +typedef int (*fluid_settings_setnum_f_t)(fluid_settings_t*,const char *, double); +typedef int (*fluid_synth_sfload_f_t)(fluid_synth_t*, const char *, int); typedef int (*fluid_synth_program_change_f_t)(fluid_synth_t*, int, int); typedef int (*fluid_synth_channel_pressure_f_t)(fluid_synth_t*, int, int); typedef int (*fluid_synth_system_reset_f_t)(fluid_synth_t*); @@ -152,10 +154,12 @@ typedef int (*fluid_synth_key_pressure_f_t)(fluid_synth_t*, int, int, int); typedef int (*fluid_synth_cc_f_t)(fluid_synth_t*, int, int, int); typedef int (*fluid_synth_pitch_bend_f_t)(fluid_synth_t*, int, int); typedef int (*fluid_synth_sysex_f_t)(fluid_synth_t*, const char*, int, char*, int*, int*, int); +typedef int (*fluid_synth_write_s16_f_t)(fluid_synth_t*, int, void*, int, int, void*, int, int); static new_fluid_settings_f_t dl_new_fluid_settings; static new_fluid_synth_f_t dl_new_fluid_synth; static new_fluid_audio_driver_f_t dl_new_fluid_audio_driver; +static fluid_settings_setnum_f_t dl_fluid_settings_setnum; static fluid_synth_sfload_f_t dl_fs_sfload; static fluid_synth_program_change_f_t dl_fs_program_change; static fluid_synth_channel_pressure_f_t dl_fs_channel_pressure; @@ -166,6 +170,7 @@ static fluid_synth_key_pressure_f_t dl_fs_key_pressure; static fluid_synth_cc_f_t dl_fs_cc; static fluid_synth_pitch_bend_f_t dl_fs_pitch_bend; static fluid_synth_sysex_f_t dl_fs_sysex; +static fluid_synth_write_s16_f_t dl_fs_write_s16; void midi_init() { @@ -198,6 +203,7 @@ void midi_init() ASSIGN_FUNCTION(handle, dl_new_fluid_settings, "new_fluid_settings"); ASSIGN_FUNCTION(handle, dl_new_fluid_synth, "new_fluid_synth"); ASSIGN_FUNCTION(handle, dl_new_fluid_audio_driver, "new_fluid_audio_driver"); + ASSIGN_FUNCTION(handle, dl_fluid_settings_setnum, "fluid_settings_setnum"); ASSIGN_FUNCTION(handle, dl_fs_sfload, "fluid_synth_sfload"); ASSIGN_FUNCTION(handle, dl_fs_program_change, "fluid_synth_program_change"); ASSIGN_FUNCTION(handle, dl_fs_channel_pressure, "fluid_synth_channel_pressure"); @@ -208,10 +214,11 @@ void midi_init() ASSIGN_FUNCTION(handle, dl_fs_cc, "fluid_synth_cc"); ASSIGN_FUNCTION(handle, dl_fs_pitch_bend, "fluid_synth_pitch_bend"); ASSIGN_FUNCTION(handle, dl_fs_sysex, "fluid_synth_sysex"); + ASSIGN_FUNCTION(handle, dl_fs_write_s16, "fluid_synth_write_s16"); fl_settings = dl_new_fluid_settings(); + dl_fluid_settings_setnum(fl_settings, "synth.sample-rate", AUDIO_SAMPLERATE); fl_synth = dl_new_fluid_synth(fl_settings); - fl_adriver = dl_new_fluid_audio_driver(fl_settings, fl_synth); midi_initialized = true; printf("Initialized MIDI synth.\n"); @@ -297,6 +304,10 @@ void midi_byte(uint8_t b) } } +void midi_synth_render(int16_t* buf, int len) { + dl_fs_write_s16(fl_synth, len, buf, 0, 2, buf, 1, 2); +} + #else void midi_load_sf2(uint8_t* filename) { @@ -313,6 +324,11 @@ void midi_byte(uint8_t b) // no-op } +void midi_synth_render(int16_t* buf, int len) { + // no synth, return zeroed buffer + memset(buf, 0, len * 2 * sizeof(int16_t)); +} + #endif void midi_serial_init() diff --git a/src/midi.h b/src/midi.h index d39738f..126f927 100644 --- a/src/midi.h +++ b/src/midi.h @@ -17,3 +17,4 @@ void midi_serial_step(int clocks); uint8_t midi_serial_read(uint8_t reg, bool debugOn); void midi_serial_write(uint8_t reg, uint8_t val); void midi_load_sf2(uint8_t* filename); +void midi_synth_render(int16_t* buf, int len); From 8e6097336c237a25e4c22293d1a57bf8c0bd6ce1 Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Mon, 30 Sep 2024 08:40:48 -0700 Subject: [PATCH 36/63] make midi_synth_render an effective no-op unless the synth is initialized --- src/midi.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/midi.c b/src/midi.c index 7ed2d78..70cd978 100644 --- a/src/midi.c +++ b/src/midi.c @@ -305,7 +305,11 @@ void midi_byte(uint8_t b) } void midi_synth_render(int16_t* buf, int len) { - dl_fs_write_s16(fl_synth, len, buf, 0, 2, buf, 1, 2); + if (midi_initialized) { + dl_fs_write_s16(fl_synth, len, buf, 0, 2, buf, 1, 2); + } else { + memset(buf, 0, len * 2 * sizeof(int16_t)); + } } #else From 00a7bacc21b73cb80f5259c89ae2a5d4c673503a Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Tue, 1 Oct 2024 01:37:12 -0700 Subject: [PATCH 37/63] external MIDI working, inbound serial working --- src/memory.c | 4 +- src/midi.c | 276 ++++++++++++++++++++++++++++++++++++++++++++------- src/midi.h | 23 +++++ 3 files changed, 266 insertions(+), 37 deletions(-) diff --git a/src/memory.c b/src/memory.c index daeed2e..a9ac8e2 100644 --- a/src/memory.c +++ b/src/memory.c @@ -198,7 +198,7 @@ real_read6502(uint16_t address, bool debugOn, int16_t bank) return YM_read_status(); } return 0x9f; // open bus read - } else if (address >= 0x9f60 && address < 0x9f70) { + } else if (address >= 0x9fc0 && address < 0x9fd0) { // midi card return midi_serial_read(address & 0xf, debugOn); } else if (address >= 0x9fb0 && address < 0x9fc0) { @@ -278,7 +278,7 @@ write6502(uint16_t address, uint8_t value) audio_render(); YM_write_reg(addr_ym, value); } - } else if (address >= 0x9f60 && address < 0x9f70) { + } else if (address >= 0x9fc0 && address < 0x9fd0) { midi_serial_write(address & 0xf, value); } else if (address >= 0x9fb0 && address < 0x9fc0) { // emulator state diff --git a/src/midi.c b/src/midi.c index 70cd978..31b21a7 100644 --- a/src/midi.c +++ b/src/midi.c @@ -97,6 +97,7 @@ struct midi_serial_regs bool msr_dcd; uint8_t obyte_bits_remain; + uint8_t ibyte_bits_remain; uint8_t rx_timeout; bool rx_timeout_enabled; @@ -114,6 +115,10 @@ struct midi_serial_regs time_t last_warning; + uint8_t midi_event_fifo[256]; + int mfsz; + uint8_t in_midi_last_command; + pthread_mutex_t fifo_mutex; pthread_mutexattr_t fifo_mutex_attr; }; @@ -129,13 +134,13 @@ static uint8_t sysex_buffer[1024]; static int sysex_bufptr; static enum MIDI_states midi_state = NORMAL; -static uint8_t midi_last_command = 0; -static uint8_t midi_first_param; +static uint8_t out_midi_last_command[2] = {0, 0}; +static uint8_t out_midi_first_param[2]; static bool midi_initialized = false; static fluid_settings_t* fl_settings; -//static fluid_midi_driver_t* fl_mdriver; +static fluid_midi_driver_t* fl_mdriver; //static fluid_audio_driver_t* fl_adriver; static fluid_synth_t* fl_synth; static int fl_sf2id; @@ -143,7 +148,10 @@ static int fl_sf2id; typedef fluid_settings_t* (*new_fluid_settings_f_t)(void); typedef fluid_synth_t* (*new_fluid_synth_f_t)(fluid_settings_t*); typedef fluid_audio_driver_t* (*new_fluid_audio_driver_f_t)(fluid_settings_t*, fluid_synth_t*); -typedef int (*fluid_settings_setnum_f_t)(fluid_settings_t*,const char *, double); +typedef fluid_midi_driver_t* (*new_fluid_midi_driver_f_t)(fluid_settings_t*, handle_midi_event_func_t, void*); +typedef int (*fluid_settings_setnum_f_t)(fluid_settings_t*,const char*, double); +typedef int (*fluid_settings_setint_f_t)(fluid_settings_t*,const char*, int); +typedef int (*fluid_settings_setstr_f_t)(fluid_settings_t*,const char*, const char*); typedef int (*fluid_synth_sfload_f_t)(fluid_synth_t*, const char *, int); typedef int (*fluid_synth_program_change_f_t)(fluid_synth_t*, int, int); typedef int (*fluid_synth_channel_pressure_f_t)(fluid_synth_t*, int, int); @@ -155,11 +163,24 @@ typedef int (*fluid_synth_cc_f_t)(fluid_synth_t*, int, int, int); typedef int (*fluid_synth_pitch_bend_f_t)(fluid_synth_t*, int, int); typedef int (*fluid_synth_sysex_f_t)(fluid_synth_t*, const char*, int, char*, int*, int*, int); typedef int (*fluid_synth_write_s16_f_t)(fluid_synth_t*, int, void*, int, int, void*, int, int); +typedef int (*fluid_midi_event_get_channel_f_t)(const fluid_midi_event_t*); +typedef int (*fluid_midi_event_get_control_f_t)(const fluid_midi_event_t*); +typedef int (*fluid_midi_event_get_key_f_t)(const fluid_midi_event_t*); +typedef int (*fluid_midi_event_get_lyrics_f_t)(const fluid_midi_event_t*, void**, int*); +typedef int (*fluid_midi_event_get_pitch_f_t)(const fluid_midi_event_t*); +typedef int (*fluid_midi_event_get_program_f_t)(const fluid_midi_event_t*); +typedef int (*fluid_midi_event_get_text_f_t)(const fluid_midi_event_t*, void**, int*); +typedef int (*fluid_midi_event_get_type_f_t)(const fluid_midi_event_t*); +typedef int (*fluid_midi_event_get_value_f_t)(const fluid_midi_event_t*); +typedef int (*fluid_midi_event_get_velocity_f_t)(const fluid_midi_event_t*); static new_fluid_settings_f_t dl_new_fluid_settings; static new_fluid_synth_f_t dl_new_fluid_synth; static new_fluid_audio_driver_f_t dl_new_fluid_audio_driver; +static new_fluid_midi_driver_f_t dl_new_fluid_midi_driver; static fluid_settings_setnum_f_t dl_fluid_settings_setnum; +static fluid_settings_setint_f_t dl_fluid_settings_setint; +static fluid_settings_setstr_f_t dl_fluid_settings_setstr; static fluid_synth_sfload_f_t dl_fs_sfload; static fluid_synth_program_change_f_t dl_fs_program_change; static fluid_synth_channel_pressure_f_t dl_fs_channel_pressure; @@ -171,6 +192,17 @@ static fluid_synth_cc_f_t dl_fs_cc; static fluid_synth_pitch_bend_f_t dl_fs_pitch_bend; static fluid_synth_sysex_f_t dl_fs_sysex; static fluid_synth_write_s16_f_t dl_fs_write_s16; +static fluid_midi_event_get_channel_f_t dl_fluid_midi_event_get_channel; +static fluid_midi_event_get_control_f_t dl_fluid_midi_event_get_control; +static fluid_midi_event_get_key_f_t dl_fluid_midi_event_get_key; +static fluid_midi_event_get_lyrics_f_t dl_fluid_midi_event_get_lyrics; +static fluid_midi_event_get_pitch_f_t dl_fluid_midi_event_get_pitch; +static fluid_midi_event_get_program_f_t dl_fluid_midi_event_get_program; +static fluid_midi_event_get_text_f_t dl_fluid_midi_event_get_text; +static fluid_midi_event_get_type_f_t dl_fluid_midi_event_get_type; +static fluid_midi_event_get_value_f_t dl_fluid_midi_event_get_value; +static fluid_midi_event_get_velocity_f_t dl_fluid_midi_event_get_velocity; + void midi_init() { @@ -203,7 +235,10 @@ void midi_init() ASSIGN_FUNCTION(handle, dl_new_fluid_settings, "new_fluid_settings"); ASSIGN_FUNCTION(handle, dl_new_fluid_synth, "new_fluid_synth"); ASSIGN_FUNCTION(handle, dl_new_fluid_audio_driver, "new_fluid_audio_driver"); + ASSIGN_FUNCTION(handle, dl_new_fluid_midi_driver, "new_fluid_midi_driver"); ASSIGN_FUNCTION(handle, dl_fluid_settings_setnum, "fluid_settings_setnum"); + ASSIGN_FUNCTION(handle, dl_fluid_settings_setint, "fluid_settings_setint"); + ASSIGN_FUNCTION(handle, dl_fluid_settings_setstr, "fluid_settings_setstr"); ASSIGN_FUNCTION(handle, dl_fs_sfload, "fluid_synth_sfload"); ASSIGN_FUNCTION(handle, dl_fs_program_change, "fluid_synth_program_change"); ASSIGN_FUNCTION(handle, dl_fs_channel_pressure, "fluid_synth_channel_pressure"); @@ -215,10 +250,22 @@ void midi_init() ASSIGN_FUNCTION(handle, dl_fs_pitch_bend, "fluid_synth_pitch_bend"); ASSIGN_FUNCTION(handle, dl_fs_sysex, "fluid_synth_sysex"); ASSIGN_FUNCTION(handle, dl_fs_write_s16, "fluid_synth_write_s16"); + ASSIGN_FUNCTION(handle, dl_fluid_midi_event_get_channel, "fluid_midi_event_get_channel"); + ASSIGN_FUNCTION(handle, dl_fluid_midi_event_get_control, "fluid_midi_event_get_control"); + ASSIGN_FUNCTION(handle, dl_fluid_midi_event_get_key, "fluid_midi_event_get_key"); + ASSIGN_FUNCTION(handle, dl_fluid_midi_event_get_lyrics, "fluid_midi_event_get_lyrics"); + ASSIGN_FUNCTION(handle, dl_fluid_midi_event_get_pitch, "fluid_midi_event_get_pitch"); + ASSIGN_FUNCTION(handle, dl_fluid_midi_event_get_program, "fluid_midi_event_get_program"); + ASSIGN_FUNCTION(handle, dl_fluid_midi_event_get_text, "fluid_midi_event_get_text"); + ASSIGN_FUNCTION(handle, dl_fluid_midi_event_get_type, "fluid_midi_event_get_type"); + ASSIGN_FUNCTION(handle, dl_fluid_midi_event_get_value, "fluid_midi_event_get_value"); + ASSIGN_FUNCTION(handle, dl_fluid_midi_event_get_velocity, "fluid_midi_event_get_velocity"); fl_settings = dl_new_fluid_settings(); dl_fluid_settings_setnum(fl_settings, "synth.sample-rate", AUDIO_SAMPLERATE); + dl_fluid_settings_setint(fl_settings, "midi.autoconnect", 1); fl_synth = dl_new_fluid_synth(fl_settings); + fl_mdriver = dl_new_fluid_midi_driver(fl_settings, handle_midi_event, &mregs[0]); midi_initialized = true; printf("Initialized MIDI synth.\n"); @@ -235,63 +282,64 @@ void midi_load_sf2(uint8_t* filename) // Receive a byte from client // Store state, or dispatch event -void midi_byte(uint8_t b) +void midi_byte_out(uint8_t sel, uint8_t b) { if (!midi_initialized) return; switch (midi_state) { case NORMAL: if (b < 0x80) { - if ((midi_last_command & 0xf0) == 0xc0) { // patch change - dl_fs_program_change(fl_synth, midi_last_command & 0xf, b); - } else if ((midi_last_command & 0xf0) == 0xd0) { // channel pressure - dl_fs_channel_pressure(fl_synth, midi_last_command & 0xf, b); - } else if (midi_last_command >= 0x80) { // two-param command - midi_first_param = b; + if ((out_midi_last_command[sel] & 0xf0) == 0xc0) { // patch change + dl_fs_program_change(fl_synth, out_midi_last_command[sel] & 0xf, b); + } else if ((out_midi_last_command[sel] & 0xf0) == 0xd0) { // channel pressure + dl_fs_channel_pressure(fl_synth, out_midi_last_command[sel] & 0xf, b); + } else if (out_midi_last_command[sel] >= 0x80) { // two-param command + out_midi_first_param[sel] = b; midi_state = PARAM; } } else { if (b < 0xf0) { - midi_last_command = b; + out_midi_last_command[sel] = b; } else if (b == 0xf0) { sysex_bufptr = 0; midi_state = SYSEX; } else if (b == 0xff) { dl_fs_system_reset(fl_synth); - midi_last_command = 0; + out_midi_last_command[sel] = 0; } } break; case PARAM: - switch (midi_last_command & 0xf0) { + switch (out_midi_last_command[sel] & 0xf0) { case 0x80: // note off - dl_fs_noteoff(fl_synth, midi_last_command & 0xf, midi_first_param); // no release velocity + dl_fs_noteoff(fl_synth, out_midi_last_command[sel] & 0xf, out_midi_first_param[sel]); // no release velocity break; case 0x90: // note on if (b == 0) { - dl_fs_noteoff(fl_synth, midi_last_command & 0xf, midi_first_param); + dl_fs_noteoff(fl_synth, out_midi_last_command[sel] & 0xf, out_midi_first_param[sel]); } else { - dl_fs_noteon(fl_synth, midi_last_command & 0xf, midi_first_param, b); + dl_fs_noteon(fl_synth, out_midi_last_command[sel] & 0xf, out_midi_first_param[sel], b); } break; case 0xa0: // aftertouch - dl_fs_key_pressure(fl_synth, midi_last_command & 0xf, midi_first_param, b); + dl_fs_key_pressure(fl_synth, out_midi_last_command[sel] & 0xf, out_midi_first_param[sel], b); break; case 0xb0: // controller - dl_fs_cc(fl_synth, midi_last_command & 0xf, midi_first_param, b); + dl_fs_cc(fl_synth, out_midi_last_command[sel] & 0xf, out_midi_first_param[sel], b); break; case 0xe0: // pitch bend - dl_fs_pitch_bend(fl_synth, midi_last_command & 0xf, ((uint16_t)midi_first_param) | (uint16_t)b << 7); + dl_fs_pitch_bend(fl_synth, out_midi_last_command[sel] & 0xf, ((uint16_t)out_midi_first_param[sel]) | (uint16_t)b << 7); break; } midi_state = NORMAL; break; case SYSEX: - if (b == 0xf7) { + if (b & 0x80) { // any command byte can terminate a SYSEX, not just 0xf7 if (sysex_bufptr < (sizeof(sysex_buffer) / sizeof(sysex_buffer[0]))-1) { // only if buffer didn't fill sysex_buffer[sysex_bufptr] = 0; dl_fs_sysex(fl_synth, (const char *)sysex_buffer, sysex_bufptr, NULL, NULL, NULL, 0); } midi_state = NORMAL; + return midi_byte_out(sel, b); } else { sysex_buffer[sysex_bufptr] = b; // we can't do much about a runaway sysex other than continue to absorb it @@ -304,7 +352,8 @@ void midi_byte(uint8_t b) } } -void midi_synth_render(int16_t* buf, int len) { +void midi_synth_render(int16_t* buf, int len) +{ if (midi_initialized) { dl_fs_write_s16(fl_synth, len, buf, 0, 2, buf, 1, 2); } else { @@ -323,12 +372,13 @@ void midi_init() fprintf(stderr, "No FluidSynth support.\n"); } -void midi_byte(uint8_t b) +void midi_byte_out(uint8_t sel, uint8_t b) { // no-op } -void midi_synth_render(int16_t* buf, int len) { +void midi_synth_render(int16_t* buf, int len) +{ // no synth, return zeroed buffer memset(buf, 0, len * 2 * sizeof(int16_t)); } @@ -387,12 +437,17 @@ void midi_serial_init() mregs[sel].thre_intr = false; mregs[sel].thre_bits_remain = 0; + mregs[sel].ibyte_bits_remain = 7; + mregs[sel].ifsz = 0; + mregs[sel].ififo[0] = 0; mregs[sel].ofsz = 0; mregs[sel].clock = 0; mregs[sel].clockdec = 0; mregs[sel].last_warning = 0; + mregs[sel].mfsz = 0; + mregs[sel].in_midi_last_command = 0; } if (!serial_midi_mutexes_initialized) { @@ -412,14 +467,13 @@ void midi_serial_step(int clocks) while (mregs[sel].clock < 0) { // process uart pthread_mutex_lock(&mregs[sel].fifo_mutex); + if (mregs[sel].obyte_bits_remain > 0) { mregs[sel].obyte_bits_remain--; } if (mregs[sel].ofsz > 0) { if (mregs[sel].obyte_bits_remain == 0) { - if (sel == 1) { - midi_byte(mregs[sel].ofifo[0]); - } + midi_byte_out(sel, mregs[sel].ofifo[0]); mregs[sel].ofsz--; if (mregs[sel].ofsz > 0) { for (i=0; i 0) { + mregs[sel].rx_timeout--; + } + + if (mregs[sel].ibyte_bits_remain > 0 && mregs[sel].mfsz > 0) { + mregs[sel].ibyte_bits_remain--; + } + if (mregs[sel].ibyte_bits_remain == 0 && mregs[sel].mfsz > 0) { + if (mregs[sel].ifsz < (mregs[sel].fcr_fifo_enable ? 16 : 1)) { + mregs[sel].ififo[mregs[sel].ifsz++] = mregs[sel].midi_event_fifo[0]; + mregs[sel].rx_timeout_enabled = true; + mregs[sel].rx_timeout = 4 * (2 + mregs[sel].lcr_word_length_bits + mregs[sel].lcr_stb + mregs[sel].lcr_pen); + } else { + mregs[sel].lsr_oe = true; // inbound FIFO overflow + if (!mregs[sel].fcr_fifo_enable) { + // RBR is overwritten by RSR in this mode + // whenever overflow happens + mregs[sel].ififo[mregs[sel].ifsz-1] = mregs[sel].midi_event_fifo[0]; + } + } + mregs[sel].mfsz--; + if (mregs[sel].mfsz > 0) { + for (i=0; i 0) { + mregs[sel].ifsz--; + if (mregs[sel].ifsz == 0) { + mregs[sel].rx_timeout_enabled = false; + } else { + for (i=0; i> 3; switch (reg & 7) { @@ -587,8 +702,8 @@ void midi_serial_write(uint8_t reg, uint8_t val) mregs[sel].dll = val; midi_serial_calculate_clk(sel); } else { - if (mregs[sel].lcr_word_length_bits != 8 || mregs[sel].lcr_stb || mregs[sel].lcr_pen || mregs[sel].lcr_eps || mregs[sel].lcr_stick || mregs[sel].lcr_break) { - if (mregs[sel].last_warning + 60 < time(NULL)) { + if (mregs[sel].lcr_word_length_bits != 8 || mregs[sel].lcr_stb || mregs[sel].lcr_pen) { + if (mregs[sel].last_warning + 60 < now) { unsigned char par = 'N'; if (mregs[sel].lcr_pen) { switch ((uint8_t)(mregs[sel].lcr_eps << 1) | (uint8_t)mregs[sel].lcr_stick) { @@ -607,11 +722,14 @@ void midi_serial_write(uint8_t reg, uint8_t val) } } fprintf(stderr, "Serial MIDI: Warning: improper LCR %d%c%d for UART %d, must be set to 8N1.\n", mregs[sel].lcr_word_length_bits, par, 1+(uint8_t)mregs[sel].lcr_stb, sel); - mregs[sel].last_warning = time(NULL); + mregs[sel].last_warning = now; } - } else if (mregs[sel].dl != 32 && mregs[sel].last_warning + 60 < time(NULL)) { + } else if (mregs[sel].lcr_break && mregs[sel].last_warning + 60 < now) { + fprintf(stderr, "Serial MIDI: Warning: break improperly set for UART %d.\n", sel); + mregs[sel].last_warning = now; + } else if (mregs[sel].dl != 32 && mregs[sel].last_warning + 60 < now) { fprintf(stderr, "Serial MIDI: Warning: improper divisor %d for UART %d, must be set to 32 for standard MIDI bitrate.\n", mregs[sel].dl, sel); - mregs[sel].last_warning = time(NULL); + mregs[sel].last_warning = now; } else { midi_serial_enqueue_obyte(sel, val); } @@ -668,6 +786,9 @@ void midi_serial_write(uint8_t reg, uint8_t val) mregs[sel].lcr_stick = !!(val & 0x20); mregs[sel].lcr_break = !!(val & 0x40); mregs[sel].lcr_dlab = !!(val & 0x80); + if (mregs[sel].mfsz == 0) { + mregs[sel].ibyte_bits_remain = 2 + mregs[sel].lcr_word_length_bits + mregs[sel].lcr_stb + mregs[sel].lcr_pen; + } break; case 0x4: mregs[sel].mcr_dtr = !!(val & 0x01); @@ -707,3 +828,88 @@ void midi_serial_write(uint8_t reg, uint8_t val) } } +void midi_event_enqueue_byte(struct midi_serial_regs* mrp, uint8_t val) +{ + if (mrp->mfsz >= 256) return; + mrp->midi_event_fifo[mrp->mfsz++] = val; + mrp->in_midi_last_command = 0; +} + +void midi_event_enqueue_short(struct midi_serial_regs* mrp, uint8_t cmd, uint8_t val) +{ + if (mrp->mfsz >= 255) { + mrp->in_midi_last_command = 0; + return; + } + if (mrp->in_midi_last_command != cmd) { + mrp->midi_event_fifo[mrp->mfsz++] = cmd; + mrp->in_midi_last_command = cmd; + } + mrp->midi_event_fifo[mrp->mfsz++] = val; +} + +void midi_event_enqueue_normal(struct midi_serial_regs* mrp, uint8_t cmd, uint8_t key, uint8_t val) +{ + if (mrp->mfsz >= 254) { + mrp->in_midi_last_command = 0; + return; + } + if (mrp->in_midi_last_command != cmd) { + mrp->midi_event_fifo[mrp->mfsz++] = cmd; + mrp->in_midi_last_command = cmd; + } + mrp->midi_event_fifo[mrp->mfsz++] = key; + mrp->midi_event_fifo[mrp->mfsz++] = val; +} + +int handle_midi_event(void* data, fluid_midi_event_t* event) +{ + struct midi_serial_regs* mrp = (struct midi_serial_regs*)data; + pthread_mutex_lock(&mrp->fifo_mutex); + + uint8_t type = dl_fluid_midi_event_get_type(event); + uint8_t chan = dl_fluid_midi_event_get_channel(event); + uint8_t cmd = type | chan; + uint8_t key, val; + + switch (type) { + case NOTE_OFF: + case NOTE_ON: + key = dl_fluid_midi_event_get_key(event); + val = dl_fluid_midi_event_get_velocity(event); + midi_event_enqueue_normal(mrp, cmd, key, val); + break; + case KEY_PRESSURE: + key = dl_fluid_midi_event_get_key(event); + val = dl_fluid_midi_event_get_value(event); + midi_event_enqueue_normal(mrp, cmd, key, val); + break; + case CONTROL_CHANGE: + key = dl_fluid_midi_event_get_control(event); + val = dl_fluid_midi_event_get_value(event); + midi_event_enqueue_normal(mrp, cmd, key, val); + break; + case PITCH_BEND: + key = dl_fluid_midi_event_get_pitch(event) & 0x7f; + val = (dl_fluid_midi_event_get_pitch(event) >> 7) & 0x7f; + midi_event_enqueue_normal(mrp, cmd, key, val); + break; + case PROGRAM_CHANGE: + case CHANNEL_PRESSURE: + val = dl_fluid_midi_event_get_program(event); + midi_event_enqueue_short(mrp, cmd, val); + break; + case MIDI_SYNC: + case MIDI_TUNE_REQUEST: + case MIDI_START: + case MIDI_CONTINUE: + case MIDI_STOP: + case MIDI_ACTIVE_SENSING: + case MIDI_SYSTEM_RESET: + midi_event_enqueue_byte(mrp, type); + break; + } + + pthread_mutex_unlock(&mrp->fifo_mutex); + return FLUID_OK; +} diff --git a/src/midi.h b/src/midi.h index 126f927..0e7cfe0 100644 --- a/src/midi.h +++ b/src/midi.h @@ -11,6 +11,28 @@ #define MIDI_UART_OSC_RATE_MHZ 16.0f #define MIDI_UART_PRIMARY_DIVIDER 16 +#define NOTE_OFF 0x80 +#define NOTE_ON 0x90 +#define KEY_PRESSURE 0xa0 +#define CONTROL_CHANGE 0xb0 +#define PROGRAM_CHANGE 0xc0 +#define CHANNEL_PRESSURE 0xd0 +#define PITCH_BEND 0xe0 +#define MIDI_SYSEX 0xf0 +#define MIDI_TIME_CODE 0xf1 +#define MIDI_SONG_POSITION 0xf2 +#define MIDI_SONG_SELECT 0xf3 +#define MIDI_TUNE_REQUEST 0xf6 +#define MIDI_EOX 0xf7 +#define MIDI_SYNC 0xf8 +#define MIDI_TICK 0xf9 +#define MIDI_START 0xfa +#define MIDI_CONTINUE 0xfb +#define MIDI_STOP 0xfc +#define MIDI_ACTIVE_SENSING 0xfe +#define MIDI_SYSTEM_RESET 0xff + + void midi_init(); void midi_serial_init(); void midi_serial_step(int clocks); @@ -18,3 +40,4 @@ uint8_t midi_serial_read(uint8_t reg, bool debugOn); void midi_serial_write(uint8_t reg, uint8_t val); void midi_load_sf2(uint8_t* filename); void midi_synth_render(int16_t* buf, int len); +int handle_midi_event(void* data, fluid_midi_event_t* event); From 5df577e4f8532f2d54d503a6d7da575c3a0a36c8 Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Tue, 1 Oct 2024 01:44:15 -0700 Subject: [PATCH 38/63] move handler functions so that wasm will build --- src/midi.c | 173 +++++++++++++++++++++++++++-------------------------- 1 file changed, 87 insertions(+), 86 deletions(-) diff --git a/src/midi.c b/src/midi.c index 31b21a7..1413764 100644 --- a/src/midi.c +++ b/src/midi.c @@ -361,6 +361,93 @@ void midi_synth_render(int16_t* buf, int len) } } +void midi_event_enqueue_byte(struct midi_serial_regs* mrp, uint8_t val) +{ + mrp->in_midi_last_command = 0; + if (mrp->mfsz >= 256) return; + mrp->midi_event_fifo[mrp->mfsz++] = val; +} + +void midi_event_enqueue_short(struct midi_serial_regs* mrp, uint8_t cmd, uint8_t val) +{ + if (mrp->mfsz >= 255) { + mrp->in_midi_last_command = 0; + return; + } + if (mrp->in_midi_last_command != cmd) { + mrp->midi_event_fifo[mrp->mfsz++] = cmd; + mrp->in_midi_last_command = cmd; + } + mrp->midi_event_fifo[mrp->mfsz++] = val; +} + +void midi_event_enqueue_normal(struct midi_serial_regs* mrp, uint8_t cmd, uint8_t key, uint8_t val) +{ + if (mrp->mfsz >= 254) { + mrp->in_midi_last_command = 0; + return; + } + if (mrp->in_midi_last_command != cmd) { + mrp->midi_event_fifo[mrp->mfsz++] = cmd; + mrp->in_midi_last_command = cmd; + } + mrp->midi_event_fifo[mrp->mfsz++] = key; + mrp->midi_event_fifo[mrp->mfsz++] = val; +} + +int handle_midi_event(void* data, fluid_midi_event_t* event) +{ + struct midi_serial_regs* mrp = (struct midi_serial_regs*)data; + pthread_mutex_lock(&mrp->fifo_mutex); + + uint8_t type = dl_fluid_midi_event_get_type(event); + uint8_t chan = dl_fluid_midi_event_get_channel(event); + uint8_t cmd = type | chan; + uint8_t key, val; + + switch (type) { + case NOTE_OFF: + case NOTE_ON: + key = dl_fluid_midi_event_get_key(event); + val = dl_fluid_midi_event_get_velocity(event); + midi_event_enqueue_normal(mrp, cmd, key, val); + break; + case KEY_PRESSURE: + key = dl_fluid_midi_event_get_key(event); + val = dl_fluid_midi_event_get_value(event); + midi_event_enqueue_normal(mrp, cmd, key, val); + break; + case CONTROL_CHANGE: + key = dl_fluid_midi_event_get_control(event); + val = dl_fluid_midi_event_get_value(event); + midi_event_enqueue_normal(mrp, cmd, key, val); + break; + case PITCH_BEND: + key = dl_fluid_midi_event_get_pitch(event) & 0x7f; + val = (dl_fluid_midi_event_get_pitch(event) >> 7) & 0x7f; + midi_event_enqueue_normal(mrp, cmd, key, val); + break; + case PROGRAM_CHANGE: + case CHANNEL_PRESSURE: + val = dl_fluid_midi_event_get_program(event); + midi_event_enqueue_short(mrp, cmd, val); + break; + case MIDI_SYNC: + case MIDI_TUNE_REQUEST: + case MIDI_START: + case MIDI_CONTINUE: + case MIDI_STOP: + case MIDI_ACTIVE_SENSING: + case MIDI_SYSTEM_RESET: + midi_event_enqueue_byte(mrp, type); + break; + } + + pthread_mutex_unlock(&mrp->fifo_mutex); + return FLUID_OK; +} + + #else void midi_load_sf2(uint8_t* filename) { @@ -827,89 +914,3 @@ void midi_serial_write(uint8_t reg, uint8_t val) break; } } - -void midi_event_enqueue_byte(struct midi_serial_regs* mrp, uint8_t val) -{ - if (mrp->mfsz >= 256) return; - mrp->midi_event_fifo[mrp->mfsz++] = val; - mrp->in_midi_last_command = 0; -} - -void midi_event_enqueue_short(struct midi_serial_regs* mrp, uint8_t cmd, uint8_t val) -{ - if (mrp->mfsz >= 255) { - mrp->in_midi_last_command = 0; - return; - } - if (mrp->in_midi_last_command != cmd) { - mrp->midi_event_fifo[mrp->mfsz++] = cmd; - mrp->in_midi_last_command = cmd; - } - mrp->midi_event_fifo[mrp->mfsz++] = val; -} - -void midi_event_enqueue_normal(struct midi_serial_regs* mrp, uint8_t cmd, uint8_t key, uint8_t val) -{ - if (mrp->mfsz >= 254) { - mrp->in_midi_last_command = 0; - return; - } - if (mrp->in_midi_last_command != cmd) { - mrp->midi_event_fifo[mrp->mfsz++] = cmd; - mrp->in_midi_last_command = cmd; - } - mrp->midi_event_fifo[mrp->mfsz++] = key; - mrp->midi_event_fifo[mrp->mfsz++] = val; -} - -int handle_midi_event(void* data, fluid_midi_event_t* event) -{ - struct midi_serial_regs* mrp = (struct midi_serial_regs*)data; - pthread_mutex_lock(&mrp->fifo_mutex); - - uint8_t type = dl_fluid_midi_event_get_type(event); - uint8_t chan = dl_fluid_midi_event_get_channel(event); - uint8_t cmd = type | chan; - uint8_t key, val; - - switch (type) { - case NOTE_OFF: - case NOTE_ON: - key = dl_fluid_midi_event_get_key(event); - val = dl_fluid_midi_event_get_velocity(event); - midi_event_enqueue_normal(mrp, cmd, key, val); - break; - case KEY_PRESSURE: - key = dl_fluid_midi_event_get_key(event); - val = dl_fluid_midi_event_get_value(event); - midi_event_enqueue_normal(mrp, cmd, key, val); - break; - case CONTROL_CHANGE: - key = dl_fluid_midi_event_get_control(event); - val = dl_fluid_midi_event_get_value(event); - midi_event_enqueue_normal(mrp, cmd, key, val); - break; - case PITCH_BEND: - key = dl_fluid_midi_event_get_pitch(event) & 0x7f; - val = (dl_fluid_midi_event_get_pitch(event) >> 7) & 0x7f; - midi_event_enqueue_normal(mrp, cmd, key, val); - break; - case PROGRAM_CHANGE: - case CHANNEL_PRESSURE: - val = dl_fluid_midi_event_get_program(event); - midi_event_enqueue_short(mrp, cmd, val); - break; - case MIDI_SYNC: - case MIDI_TUNE_REQUEST: - case MIDI_START: - case MIDI_CONTINUE: - case MIDI_STOP: - case MIDI_ACTIVE_SENSING: - case MIDI_SYSTEM_RESET: - midi_event_enqueue_byte(mrp, type); - break; - } - - pthread_mutex_unlock(&mrp->fifo_mutex); - return FLUID_OK; -} From d7b52ff1ffdf5c938c3a387512abeb981ef06859 Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Tue, 1 Oct 2024 01:55:42 -0700 Subject: [PATCH 39/63] move handler prototype so that wasm will build --- src/midi.c | 2 ++ src/midi.h | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/midi.c b/src/midi.c index 1413764..fc9337b 100644 --- a/src/midi.c +++ b/src/midi.c @@ -130,6 +130,8 @@ static bool serial_midi_mutexes_initialized = false; #ifndef __EMSCRIPTEN__ +int handle_midi_event(void* data, fluid_midi_event_t* event); + static uint8_t sysex_buffer[1024]; static int sysex_bufptr; diff --git a/src/midi.h b/src/midi.h index 0e7cfe0..78d87a2 100644 --- a/src/midi.h +++ b/src/midi.h @@ -40,4 +40,3 @@ uint8_t midi_serial_read(uint8_t reg, bool debugOn); void midi_serial_write(uint8_t reg, uint8_t val); void midi_load_sf2(uint8_t* filename); void midi_synth_render(int16_t* buf, int len); -int handle_midi_event(void* data, fluid_midi_event_t* event); From 621461502eb59fc5bff8823c32fe0e1a08cf8ba0 Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Tue, 1 Oct 2024 18:57:14 -0700 Subject: [PATCH 40/63] Make MIDI card address flexible, add interrupts --- src/glue.h | 3 +++ src/main.c | 36 ++++++++++++++++++++++++++++++++---- src/memory.c | 10 +++++----- src/midi.c | 26 +++++++++++++++++++++----- src/midi.h | 1 + 5 files changed, 62 insertions(+), 14 deletions(-) diff --git a/src/glue.h b/src/glue.h index 813f841..ad61f23 100644 --- a/src/glue.h +++ b/src/glue.h @@ -79,6 +79,9 @@ extern bool has_via2; extern uint32_t host_sample_rate; extern bool enable_midline; +extern bool has_midi_card; +extern uint16_t midi_card_addr; + extern void machine_dump(const char* reason); extern void machine_reset(); extern void machine_nmi(); diff --git a/src/main.c b/src/main.c index 56aa659..78231ba 100644 --- a/src/main.c +++ b/src/main.c @@ -131,6 +131,9 @@ bool enable_midline = false; bool ym2151_irq_support = false; char *cartridge_path = NULL; +bool has_midi_card = false; +uint16_t midi_card_addr; + bool using_hostfs = true; uint8_t MHZ = 8; @@ -528,6 +531,12 @@ usage() printf("\tSuppress warning emitted when encountering a Rockwell extension on the 65C02\n"); printf("-longpwron\n"); printf("\tSimulate a long press of the power button at system power-on.\n"); + printf("-midicard [
]\n"); + printf("\tInstall a serial MIDI card at the specified address, or at $9F60 by default.\n"); + printf("\tThe -sf2 option must be specified along with this option.\n"); + printf("-sf2 \n"); + printf("\tInitialize MIDI synth with the specified SoundFont.\n"); + printf("\tThe -midicard option must be specified along with this option.\n"); #ifdef TRACE printf("-trace [
]\n"); printf("\tPrint instruction trace. Optionally, a trigger address\n"); @@ -633,6 +642,18 @@ main(int argc, char **argv) prg_path = argv[0]; argc--; argv++; + } else if (!strcmp(argv[0], "-midicard")) { + argc--; + argv++; + has_midi_card = true; + if (argc && argv[0][0] != '-') { + midi_card_addr = 0x9f00 | ((uint16_t)strtol(argv[0], NULL, 16) & 0xff); + midi_card_addr &= 0xfff0; + argc--; + argv++; + } else { + midi_card_addr = 0x9f60; + } } else if (!strcmp(argv[0], "-sf2")) { argc--; argv++; @@ -1100,9 +1121,16 @@ main(int argc, char **argv) #endif } - if (sf2_path) { - midi_init(); - midi_load_sf2((uint8_t *)sf2_path); + if (sf2_path && has_midi_card) { + if (midi_card_addr < 0x9f60) { + fprintf(stderr, "Warning: Serial MIDI card address must be in the range of 9F60-9FF0\n"); + } else { + midi_init(); + midi_load_sf2((uint8_t *)sf2_path); + } + } else if (sf2_path || has_midi_card) { + fprintf(stderr, "Warning: -sf2 and -midicard must be specified together in order to enable the MIDI synth.\n"); + has_midi_card = false; } if (cartridge_path) { @@ -1634,7 +1662,7 @@ emulator_loop(void *param) audio_render(); } - if (video_get_irq_out() || via1_irq() || (has_via2 && via2_irq()) || (ym2151_irq_support && YM_irq())) { + if (video_get_irq_out() || via1_irq() || (has_via2 && via2_irq()) || (ym2151_irq_support && YM_irq()) || (has_midi_card && midi_serial_irq())) { // printf("IRQ!\n"); irq6502(); } diff --git a/src/memory.c b/src/memory.c index a9ac8e2..1e0cc65 100644 --- a/src/memory.c +++ b/src/memory.c @@ -198,12 +198,12 @@ real_read6502(uint16_t address, bool debugOn, int16_t bank) return YM_read_status(); } return 0x9f; // open bus read - } else if (address >= 0x9fc0 && address < 0x9fd0) { - // midi card - return midi_serial_read(address & 0xf, debugOn); } else if (address >= 0x9fb0 && address < 0x9fc0) { // emulator state return emu_read(address & 0xf, debugOn); + } else if (has_midi_card && (address & 0xfff0) == midi_card_addr) { + // midi card + return midi_serial_read(address & 0xf, debugOn); } else { // future expansion return 0x9f; // open bus read @@ -278,11 +278,11 @@ write6502(uint16_t address, uint8_t value) audio_render(); YM_write_reg(addr_ym, value); } - } else if (address >= 0x9fc0 && address < 0x9fd0) { - midi_serial_write(address & 0xf, value); } else if (address >= 0x9fb0 && address < 0x9fc0) { // emulator state emu_write(address & 0xf, value); + } else if (has_midi_card && (address & 0xfff0) == midi_card_addr) { + midi_serial_write(address & 0xf, value); } else { // future expansion } diff --git a/src/midi.c b/src/midi.c index fc9337b..e9379dd 100644 --- a/src/midi.c +++ b/src/midi.c @@ -131,6 +131,7 @@ static bool serial_midi_mutexes_initialized = false; #ifndef __EMSCRIPTEN__ int handle_midi_event(void* data, fluid_midi_event_t* event); +void midi_serial_iir_check(uint8_t sel); static uint8_t sysex_buffer[1024]; static int sysex_bufptr; @@ -143,7 +144,6 @@ static bool midi_initialized = false; static fluid_settings_t* fl_settings; static fluid_midi_driver_t* fl_mdriver; -//static fluid_audio_driver_t* fl_adriver; static fluid_synth_t* fl_synth; static int fl_sf2id; @@ -270,7 +270,7 @@ void midi_init() fl_mdriver = dl_new_fluid_midi_driver(fl_settings, handle_midi_event, &mregs[0]); midi_initialized = true; - printf("Initialized MIDI synth.\n"); + fprintf(stderr, "Initialized MIDI synth at $%04X.\n", midi_card_addr); } void midi_load_sf2(uint8_t* filename) @@ -278,7 +278,7 @@ void midi_load_sf2(uint8_t* filename) if (!midi_initialized) return; fl_sf2id = dl_fs_sfload(fl_synth, (const char *)filename, true); if (fl_sf2id == FLUID_FAILED) { - printf("Unable to load soundfont.\n"); + fprintf(stderr, "Unable to load soundfont.\n"); } } @@ -365,7 +365,6 @@ void midi_synth_render(int16_t* buf, int len) void midi_event_enqueue_byte(struct midi_serial_regs* mrp, uint8_t val) { - mrp->in_midi_last_command = 0; if (mrp->mfsz >= 256) return; mrp->midi_event_fifo[mrp->mfsz++] = val; } @@ -434,8 +433,17 @@ int handle_midi_event(void* data, fluid_midi_event_t* event) val = dl_fluid_midi_event_get_program(event); midi_event_enqueue_short(mrp, cmd, val); break; - case MIDI_SYNC: + case MIDI_TIME_CODE: + val = dl_fluid_midi_event_get_value(event); + midi_event_enqueue_short(mrp, type, val); + mrp->in_midi_last_command = 0; + break; case MIDI_TUNE_REQUEST: + midi_event_enqueue_byte(mrp, type); + mrp->in_midi_last_command = 0; + break; + case MIDI_SYNC: + case MIDI_TICK: case MIDI_START: case MIDI_CONTINUE: case MIDI_STOP: @@ -614,6 +622,7 @@ void midi_serial_step(int clocks) pthread_mutex_unlock(&mregs[sel].fifo_mutex); mregs[sel].clock += 0x1000000LL; } + midi_serial_iir_check(sel); } } @@ -916,3 +925,10 @@ void midi_serial_write(uint8_t reg, uint8_t val) break; } } + +bool midi_serial_irq(void) +{ + bool uart0int = (mregs[0].iir & 1) == 0 && mregs[0].mcr_out2; + bool uart1int = (mregs[1].iir & 1) == 0 && mregs[1].mcr_out2; + return (uart0int | uart1int); +} diff --git a/src/midi.h b/src/midi.h index 78d87a2..a835d99 100644 --- a/src/midi.h +++ b/src/midi.h @@ -40,3 +40,4 @@ uint8_t midi_serial_read(uint8_t reg, bool debugOn); void midi_serial_write(uint8_t reg, uint8_t val); void midi_load_sf2(uint8_t* filename); void midi_synth_render(int16_t* buf, int len); +bool midi_serial_irq(void); From 27ed6ac655f0e153b9af6509e639bb24ca7fcaab Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Tue, 1 Oct 2024 19:01:16 -0700 Subject: [PATCH 41/63] fix for wasm --- src/midi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/midi.c b/src/midi.c index e9379dd..c1d7262 100644 --- a/src/midi.c +++ b/src/midi.c @@ -128,10 +128,11 @@ struct midi_serial_regs struct midi_serial_regs mregs[2]; static bool serial_midi_mutexes_initialized = false; +void midi_serial_iir_check(uint8_t sel); + #ifndef __EMSCRIPTEN__ int handle_midi_event(void* data, fluid_midi_event_t* event); -void midi_serial_iir_check(uint8_t sel); static uint8_t sysex_buffer[1024]; static int sysex_bufptr; From 39a105ee400dc8c954f184cd434c9af4855d59d4 Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Wed, 2 Oct 2024 19:05:47 -0700 Subject: [PATCH 42/63] adding debug --- src/midi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/midi.c b/src/midi.c index c1d7262..237a595 100644 --- a/src/midi.c +++ b/src/midi.c @@ -218,7 +218,7 @@ void midi_init() #elif __APPLE__ LIBRARY_TYPE handle = LOAD_LIBRARY("libfluidsynth.dylib"); #else - LIBRARY_TYPE handle = LOAD_LIBRARY("libfluidsynth.so"); + LIBRARY_TYPE handle = LOAD_LIBRARY("libfluidsynth.so.3"); #endif if (!handle) { @@ -454,6 +454,8 @@ int handle_midi_event(void* data, fluid_midi_event_t* event) break; } + fprintf(stderr, "Debug: MIDI IN: Type: %02X\n", type); + pthread_mutex_unlock(&mrp->fifo_mutex); return FLUID_OK; } From 0cf6e02cd48f531407f171547d3cfa4dc8de5950 Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Wed, 2 Oct 2024 21:44:25 -0700 Subject: [PATCH 43/63] fix interrupt logic --- src/midi.c | 44 +++++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/src/midi.c b/src/midi.c index 237a595..39c9e8f 100644 --- a/src/midi.c +++ b/src/midi.c @@ -559,6 +559,26 @@ void midi_serial_init() } } +void midi_serial_iir_check(uint8_t sel) +{ + uint8_t fifoen = (uint8_t)mregs[sel].fcr_fifo_enable << 6 | (uint8_t)mregs[sel].fcr_fifo_enable << 7; + if (mregs[sel].ier_elsi && (mregs[sel].lsr_oe || mregs[sel].lsr_pe || mregs[sel].lsr_fe || mregs[sel].lsr_bi)) { + mregs[sel].iir = (0x06 | fifoen); // Receiver line status interrupt + } else if (mregs[sel].ier_erbi && !mregs[sel].fcr_fifo_enable && mregs[sel].ifsz > 0) { + mregs[sel].iir = (0x04 | fifoen); // Received data available interrupt (16450 mode) + } else if (mregs[sel].ier_erbi && mregs[sel].fcr_fifo_enable && mregs[sel].ifsz >= mregs[sel].fcr_ififo_trigger_level_bytes) { + mregs[sel].iir = (0x04 | fifoen); // Received data available interrupt (16550 mode) + } else if (mregs[sel].ier_erbi && mregs[sel].fcr_fifo_enable && mregs[sel].ifsz > 0 && mregs[sel].rx_timeout_enabled && mregs[sel].rx_timeout == 0) { + mregs[sel].iir = (0x0c | fifoen); // Received data available interrupt (timeout, 16550 mode) + } else if (mregs[sel].ier_etbei && mregs[sel].thre_intr) { + mregs[sel].iir = (0x02 | fifoen); // Transmitter holding register empty interrupt + } else if (mregs[sel].ier_edssi && ((!mregs[sel].mcr_afe && mregs[sel].msr_dcts) || mregs[sel].msr_ddcd || mregs[sel].msr_ddsr || mregs[sel].msr_teri)) { + mregs[sel].iir = (0x00 | fifoen); // Modem status register interrupt + } else { + mregs[sel].iir = (0x01 | fifoen); // no interrupt waiting + } +} + void midi_serial_step(int clocks) { uint8_t sel, i; @@ -624,8 +644,8 @@ void midi_serial_step(int clocks) pthread_mutex_unlock(&mregs[sel].fifo_mutex); mregs[sel].clock += 0x1000000LL; + midi_serial_iir_check(sel); } - midi_serial_iir_check(sel); } } @@ -646,6 +666,7 @@ uint8_t midi_serial_dequeue_ibyte(uint8_t sel) mregs[sel].rx_timeout_enabled = true; mregs[sel].rx_timeout = 4 * (2 + mregs[sel].lcr_word_length_bits + mregs[sel].lcr_stb + mregs[sel].lcr_pen); } + midi_serial_iir_check(sel); } pthread_mutex_unlock(&mregs[sel].fifo_mutex); @@ -670,29 +691,10 @@ void midi_serial_enqueue_obyte(uint8_t sel, uint8_t val) } else { printf("TX Overflow\n"); } + midi_serial_iir_check(sel); pthread_mutex_unlock(&mregs[sel].fifo_mutex); } -void midi_serial_iir_check(uint8_t sel) -{ - uint8_t fifoen = (uint8_t)mregs[sel].fcr_fifo_enable << 6 | (uint8_t)mregs[sel].fcr_fifo_enable << 7; - if (mregs[sel].ier_elsi && (mregs[sel].lsr_oe || mregs[sel].lsr_pe || mregs[sel].lsr_fe || mregs[sel].lsr_bi)) { - mregs[sel].iir = (0x06 | fifoen); // Receiver line status interrupt - } else if (mregs[sel].ier_erbi && !mregs[sel].fcr_fifo_enable && mregs[sel].ifsz > 0) { - mregs[sel].iir = (0x04 | fifoen); // Received data available interrupt (16450 mode) - } else if (mregs[sel].ier_erbi && mregs[sel].fcr_fifo_enable && mregs[sel].ifsz >= mregs[sel].fcr_ififo_trigger_level_bytes) { - mregs[sel].iir = (0x04 | fifoen); // Received data available interrupt (16550 mode) - } else if (mregs[sel].ier_erbi && mregs[sel].fcr_fifo_enable && mregs[sel].ifsz > 0 && mregs[sel].rx_timeout_enabled && mregs[sel].rx_timeout == 0) { - mregs[sel].iir = (0x0c | fifoen); // Received data available interrupt (timeout, 16550 mode) - } else if (mregs[sel].ier_etbei && mregs[sel].thre_intr) { - mregs[sel].iir = (0x02 | fifoen); // Transmitter holding register empty interrupt - } else if (mregs[sel].ier_edssi && ((!mregs[sel].mcr_afe && mregs[sel].msr_dcts) || mregs[sel].msr_ddcd || mregs[sel].msr_ddsr || mregs[sel].msr_teri)) { - mregs[sel].iir = (0x00 | fifoen); // Modem status register interrupt - } else { - mregs[sel].iir = (0x01 | fifoen); // no interrupt waiting - } -} - uint8_t midi_serial_read(uint8_t reg, bool debugOn) { //printf("midi_serial_read %d\n", reg); From abd311b04fb20f38c3535fffc17a2a6a90ff8ff3 Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Wed, 2 Oct 2024 22:19:21 -0700 Subject: [PATCH 44/63] add the ability to select specific MIDI IN, other fixes --- src/main.c | 14 ++++++++++++++ src/midi.c | 19 +++++++++++++++---- src/midi.h | 2 ++ 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/src/main.c b/src/main.c index 78231ba..68c3729 100644 --- a/src/main.c +++ b/src/main.c @@ -537,6 +537,11 @@ usage() printf("-sf2 \n"); printf("\tInitialize MIDI synth with the specified SoundFont.\n"); printf("\tThe -midicard option must be specified along with this option.\n"); + printf("-midi-in \n"); + printf("\tConnect a specific system MIDI device to the virtualized MIDI card.\n"); + printf("\tIf -midicard is set but this option is not, all MIDI input devices\n"); + printf("\tare connected.\n"); + printf("\tThe -midicard option must be specified along with this option.\n"); #ifdef TRACE printf("-trace [
]\n"); printf("\tPrint instruction trace. Optionally, a trigger address\n"); @@ -663,6 +668,15 @@ main(int argc, char **argv) sf2_path = argv[0]; argc--; argv++; + } else if (!strcmp(argv[0], "-midi-in")) { + argc--; + argv++; + if (!argc || argv[0][0] == '-') { + usage(); + } + fs_midi_input_device = argv[0]; + argc--; + argv++; } else if (!strcmp(argv[0], "-run")) { argc--; argv++; diff --git a/src/midi.c b/src/midi.c index 39c9e8f..c622b04 100644 --- a/src/midi.c +++ b/src/midi.c @@ -127,6 +127,7 @@ struct midi_serial_regs struct midi_serial_regs mregs[2]; static bool serial_midi_mutexes_initialized = false; +const char *fs_midi_input_device; void midi_serial_iir_check(uint8_t sel); @@ -265,8 +266,18 @@ void midi_init() ASSIGN_FUNCTION(handle, dl_fluid_midi_event_get_velocity, "fluid_midi_event_get_velocity"); fl_settings = dl_new_fluid_settings(); - dl_fluid_settings_setnum(fl_settings, "synth.sample-rate", AUDIO_SAMPLERATE); - dl_fluid_settings_setint(fl_settings, "midi.autoconnect", 1); + dl_fluid_settings_setnum(fl_settings, "synth.sample-rate", + AUDIO_SAMPLERATE); + dl_fluid_settings_setstr(fl_settings, "midi.portname", "Commander X16 Emulator"); + if (fs_midi_input_device) { + dl_fluid_settings_setstr(fl_settings, "midi.winmidi.device", fs_midi_input_device); + dl_fluid_settings_setstr(fl_settings, "midi.alsa_seq.device", fs_midi_input_device); + dl_fluid_settings_setint(fl_settings, "midi.autoconnect", 0); + } else { + dl_fluid_settings_setstr(fl_settings, "midi.winmidi.device", "default"); + dl_fluid_settings_setstr(fl_settings, "midi.alsa_seq.device", "default"); + dl_fluid_settings_setint(fl_settings, "midi.autoconnect", 1); + } fl_synth = dl_new_fluid_synth(fl_settings); fl_mdriver = dl_new_fluid_midi_driver(fl_settings, handle_midi_event, &mregs[0]); @@ -404,7 +415,7 @@ int handle_midi_event(void* data, fluid_midi_event_t* event) uint8_t type = dl_fluid_midi_event_get_type(event); uint8_t chan = dl_fluid_midi_event_get_channel(event); - uint8_t cmd = type | chan; + uint8_t cmd = (type < 0x80 || type >= 0xf0) ? type : (type | (chan & 0xf)); uint8_t key, val; switch (type) { @@ -454,7 +465,7 @@ int handle_midi_event(void* data, fluid_midi_event_t* event) break; } - fprintf(stderr, "Debug: MIDI IN: Type: %02X\n", type); + fprintf(stderr, "Debug: MIDI IN: Type: %02X Chan: %02X\n", type, chan); pthread_mutex_unlock(&mrp->fifo_mutex); return FLUID_OK; diff --git a/src/midi.h b/src/midi.h index a835d99..33a4ef1 100644 --- a/src/midi.h +++ b/src/midi.h @@ -41,3 +41,5 @@ void midi_serial_write(uint8_t reg, uint8_t val); void midi_load_sf2(uint8_t* filename); void midi_synth_render(int16_t* buf, int len); bool midi_serial_irq(void); + +extern const char *fs_midi_input_device; From 69499050fbafc30ea08c6cf580672fb3fd1b7e87 Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Wed, 2 Oct 2024 23:24:08 -0700 Subject: [PATCH 45/63] revert device selection logic --- src/main.c | 14 -------------- src/midi.c | 11 +---------- src/midi.h | 1 - 3 files changed, 1 insertion(+), 25 deletions(-) diff --git a/src/main.c b/src/main.c index 68c3729..78231ba 100644 --- a/src/main.c +++ b/src/main.c @@ -537,11 +537,6 @@ usage() printf("-sf2 \n"); printf("\tInitialize MIDI synth with the specified SoundFont.\n"); printf("\tThe -midicard option must be specified along with this option.\n"); - printf("-midi-in \n"); - printf("\tConnect a specific system MIDI device to the virtualized MIDI card.\n"); - printf("\tIf -midicard is set but this option is not, all MIDI input devices\n"); - printf("\tare connected.\n"); - printf("\tThe -midicard option must be specified along with this option.\n"); #ifdef TRACE printf("-trace [
]\n"); printf("\tPrint instruction trace. Optionally, a trigger address\n"); @@ -668,15 +663,6 @@ main(int argc, char **argv) sf2_path = argv[0]; argc--; argv++; - } else if (!strcmp(argv[0], "-midi-in")) { - argc--; - argv++; - if (!argc || argv[0][0] == '-') { - usage(); - } - fs_midi_input_device = argv[0]; - argc--; - argv++; } else if (!strcmp(argv[0], "-run")) { argc--; argv++; diff --git a/src/midi.c b/src/midi.c index c622b04..164ecbc 100644 --- a/src/midi.c +++ b/src/midi.c @@ -127,7 +127,6 @@ struct midi_serial_regs struct midi_serial_regs mregs[2]; static bool serial_midi_mutexes_initialized = false; -const char *fs_midi_input_device; void midi_serial_iir_check(uint8_t sel); @@ -269,15 +268,7 @@ void midi_init() dl_fluid_settings_setnum(fl_settings, "synth.sample-rate", AUDIO_SAMPLERATE); dl_fluid_settings_setstr(fl_settings, "midi.portname", "Commander X16 Emulator"); - if (fs_midi_input_device) { - dl_fluid_settings_setstr(fl_settings, "midi.winmidi.device", fs_midi_input_device); - dl_fluid_settings_setstr(fl_settings, "midi.alsa_seq.device", fs_midi_input_device); - dl_fluid_settings_setint(fl_settings, "midi.autoconnect", 0); - } else { - dl_fluid_settings_setstr(fl_settings, "midi.winmidi.device", "default"); - dl_fluid_settings_setstr(fl_settings, "midi.alsa_seq.device", "default"); - dl_fluid_settings_setint(fl_settings, "midi.autoconnect", 1); - } + dl_fluid_settings_setint(fl_settings, "midi.autoconnect", 1); fl_synth = dl_new_fluid_synth(fl_settings); fl_mdriver = dl_new_fluid_midi_driver(fl_settings, handle_midi_event, &mregs[0]); diff --git a/src/midi.h b/src/midi.h index 33a4ef1..ea51b96 100644 --- a/src/midi.h +++ b/src/midi.h @@ -42,4 +42,3 @@ void midi_load_sf2(uint8_t* filename); void midi_synth_render(int16_t* buf, int len); bool midi_serial_irq(void); -extern const char *fs_midi_input_device; From 3f8303b261019d8250e5640b34ba8ee64d2075c2 Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Wed, 2 Oct 2024 23:42:55 -0700 Subject: [PATCH 46/63] add -midi-in option back as a toggle --- src/main.c | 8 ++++++++ src/midi.c | 3 ++- src/midi.h | 1 + 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/main.c b/src/main.c index 78231ba..10d5d1e 100644 --- a/src/main.c +++ b/src/main.c @@ -537,6 +537,10 @@ usage() printf("-sf2 \n"); printf("\tInitialize MIDI synth with the specified SoundFont.\n"); printf("\tThe -midicard option must be specified along with this option.\n"); + printf("-midi-in\n"); + printf("\tConnect the system MIDI input devices to the input of the first UART.\n"); + printf("\tof the emulated MIDI card. The -midicard option is required for this\n"); + printf("\toption to have any effect.\n"); #ifdef TRACE printf("-trace [
]\n"); printf("\tPrint instruction trace. Optionally, a trigger address\n"); @@ -663,6 +667,10 @@ main(int argc, char **argv) sf2_path = argv[0]; argc--; argv++; + } else if (!strcmp(argv[0], "-midi-in")) { + argc--; + argv++; + fs_midi_autoconnect = true; } else if (!strcmp(argv[0], "-run")) { argc--; argv++; diff --git a/src/midi.c b/src/midi.c index 164ecbc..871c70f 100644 --- a/src/midi.c +++ b/src/midi.c @@ -129,6 +129,7 @@ struct midi_serial_regs mregs[2]; static bool serial_midi_mutexes_initialized = false; void midi_serial_iir_check(uint8_t sel); +bool fs_midi_autoconnect = false; #ifndef __EMSCRIPTEN__ @@ -268,7 +269,7 @@ void midi_init() dl_fluid_settings_setnum(fl_settings, "synth.sample-rate", AUDIO_SAMPLERATE); dl_fluid_settings_setstr(fl_settings, "midi.portname", "Commander X16 Emulator"); - dl_fluid_settings_setint(fl_settings, "midi.autoconnect", 1); + dl_fluid_settings_setint(fl_settings, "midi.autoconnect", fs_midi_autoconnect); fl_synth = dl_new_fluid_synth(fl_settings); fl_mdriver = dl_new_fluid_midi_driver(fl_settings, handle_midi_event, &mregs[0]); diff --git a/src/midi.h b/src/midi.h index ea51b96..5d7fb40 100644 --- a/src/midi.h +++ b/src/midi.h @@ -42,3 +42,4 @@ void midi_load_sf2(uint8_t* filename); void midi_synth_render(int16_t* buf, int len); bool midi_serial_irq(void); +extern bool fs_midi_autoconnect; From d4b66a2912dab28534d29eec068227fd19cf0e7c Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Wed, 2 Oct 2024 23:43:49 -0700 Subject: [PATCH 47/63] fix punctuation in usage --- src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.c b/src/main.c index 10d5d1e..70a1cc9 100644 --- a/src/main.c +++ b/src/main.c @@ -538,7 +538,7 @@ usage() printf("\tInitialize MIDI synth with the specified SoundFont.\n"); printf("\tThe -midicard option must be specified along with this option.\n"); printf("-midi-in\n"); - printf("\tConnect the system MIDI input devices to the input of the first UART.\n"); + printf("\tConnect the system MIDI input devices to the input of the first UART\n"); printf("\tof the emulated MIDI card. The -midicard option is required for this\n"); printf("\toption to have any effect.\n"); #ifdef TRACE From 3e8783a5ca53f9a8954f3e9503a45e6309d0ce4d Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Wed, 2 Oct 2024 23:52:54 -0700 Subject: [PATCH 48/63] -midi-in now controls whether the midi driver gets instantiated --- src/main.c | 2 +- src/midi.c | 8 +++++--- src/midi.h | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/main.c b/src/main.c index 70a1cc9..d5f133b 100644 --- a/src/main.c +++ b/src/main.c @@ -670,7 +670,7 @@ main(int argc, char **argv) } else if (!strcmp(argv[0], "-midi-in")) { argc--; argv++; - fs_midi_autoconnect = true; + fs_midi_in_connect = true; } else if (!strcmp(argv[0], "-run")) { argc--; argv++; diff --git a/src/midi.c b/src/midi.c index 871c70f..f6852c0 100644 --- a/src/midi.c +++ b/src/midi.c @@ -129,7 +129,7 @@ struct midi_serial_regs mregs[2]; static bool serial_midi_mutexes_initialized = false; void midi_serial_iir_check(uint8_t sel); -bool fs_midi_autoconnect = false; +bool fs_midi_in_connect = false; #ifndef __EMSCRIPTEN__ @@ -269,9 +269,11 @@ void midi_init() dl_fluid_settings_setnum(fl_settings, "synth.sample-rate", AUDIO_SAMPLERATE); dl_fluid_settings_setstr(fl_settings, "midi.portname", "Commander X16 Emulator"); - dl_fluid_settings_setint(fl_settings, "midi.autoconnect", fs_midi_autoconnect); + dl_fluid_settings_setint(fl_settings, "midi.autoconnect", fs_midi_in_connect); fl_synth = dl_new_fluid_synth(fl_settings); - fl_mdriver = dl_new_fluid_midi_driver(fl_settings, handle_midi_event, &mregs[0]); + if (fs_midi_in_connect) { + fl_mdriver = dl_new_fluid_midi_driver(fl_settings, handle_midi_event, &mregs[0]); + } midi_initialized = true; fprintf(stderr, "Initialized MIDI synth at $%04X.\n", midi_card_addr); diff --git a/src/midi.h b/src/midi.h index 5d7fb40..7696e1d 100644 --- a/src/midi.h +++ b/src/midi.h @@ -42,4 +42,4 @@ void midi_load_sf2(uint8_t* filename); void midi_synth_render(int16_t* buf, int len); bool midi_serial_irq(void); -extern bool fs_midi_autoconnect; +extern bool fs_midi_in_connect; From 264ee12e4283091060715e797a3275e578f1e482 Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Fri, 4 Oct 2024 14:00:20 -0700 Subject: [PATCH 49/63] Add SysEx handler for midi-in --- src/midi.c | 35 +++++++++++++++++++++++++++++++++-- src/midi.h | 1 + 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/midi.c b/src/midi.c index f6852c0..238e849 100644 --- a/src/midi.c +++ b/src/midi.c @@ -177,6 +177,7 @@ typedef int (*fluid_midi_event_get_text_f_t)(const fluid_midi_event_t*, void**, typedef int (*fluid_midi_event_get_type_f_t)(const fluid_midi_event_t*); typedef int (*fluid_midi_event_get_value_f_t)(const fluid_midi_event_t*); typedef int (*fluid_midi_event_get_velocity_f_t)(const fluid_midi_event_t*); +typedef int (*fluid_midi_event_set_type_f_t)(fluid_midi_event_t*, int); static new_fluid_settings_f_t dl_new_fluid_settings; static new_fluid_synth_f_t dl_new_fluid_synth; @@ -206,6 +207,7 @@ static fluid_midi_event_get_text_f_t dl_fluid_midi_event_get_text; static fluid_midi_event_get_type_f_t dl_fluid_midi_event_get_type; static fluid_midi_event_get_value_f_t dl_fluid_midi_event_get_value; static fluid_midi_event_get_velocity_f_t dl_fluid_midi_event_get_velocity; +static fluid_midi_event_set_type_f_t dl_fluid_midi_event_set_type; void midi_init() @@ -264,6 +266,7 @@ void midi_init() ASSIGN_FUNCTION(handle, dl_fluid_midi_event_get_type, "fluid_midi_event_get_type"); ASSIGN_FUNCTION(handle, dl_fluid_midi_event_get_value, "fluid_midi_event_get_value"); ASSIGN_FUNCTION(handle, dl_fluid_midi_event_get_velocity, "fluid_midi_event_get_velocity"); + ASSIGN_FUNCTION(handle, dl_fluid_midi_event_set_type, "fluid_midi_event_set_type"); fl_settings = dl_new_fluid_settings(); dl_fluid_settings_setnum(fl_settings, "synth.sample-rate", @@ -402,6 +405,21 @@ void midi_event_enqueue_normal(struct midi_serial_regs* mrp, uint8_t cmd, uint8_ mrp->midi_event_fifo[mrp->mfsz++] = val; } +void midi_event_enqueue_sysex(struct midi_serial_regs* mrp, uint8_t *bufptr, int buflen) +{ + int i; + if (mrp->mfsz >= 255 - (buflen + 2)) { // too full + mrp->in_midi_last_command = 0; + return; + } + + mrp->midi_event_fifo[mrp->mfsz++] = 0xf0; + for (i = 0; i < buflen; i++) { + mrp->midi_event_fifo[mrp->mfsz++] = bufptr[i]; + } + mrp->midi_event_fifo[mrp->mfsz++] = 0xf7; +} + int handle_midi_event(void* data, fluid_midi_event_t* event) { struct midi_serial_regs* mrp = (struct midi_serial_regs*)data; @@ -411,6 +429,8 @@ int handle_midi_event(void* data, fluid_midi_event_t* event) uint8_t chan = dl_fluid_midi_event_get_channel(event); uint8_t cmd = (type < 0x80 || type >= 0xf0) ? type : (type | (chan & 0xf)); uint8_t key, val; + uint8_t *bufptr; + int buflen; switch (type) { case NOTE_OFF: @@ -457,9 +477,20 @@ int handle_midi_event(void* data, fluid_midi_event_t* event) case MIDI_SYSTEM_RESET: midi_event_enqueue_byte(mrp, type); break; + case MIDI_SYSEX: + dl_fluid_midi_event_set_type(event, MIDI_TEXT); + dl_fluid_midi_event_get_text(event, (void **)&bufptr, &buflen); + midi_event_enqueue_sysex(mrp, bufptr, buflen); + fprintf(stderr, "Debug: MIDI IN: Type: SysEx Chan: %02X\n", chan); + break; + case 0xF4: + case 0xF5: + midi_event_enqueue_byte(mrp, type); + mrp->in_midi_last_command = 0; + break; } - fprintf(stderr, "Debug: MIDI IN: Type: %02X Chan: %02X\n", type, chan); + //fprintf(stderr, "Debug: MIDI IN: Type: %02X Chan: %02X\n", type, chan); pthread_mutex_unlock(&mrp->fifo_mutex); return FLUID_OK; @@ -694,7 +725,7 @@ void midi_serial_enqueue_obyte(uint8_t sel, uint8_t val) mregs[sel].thre_bits_remain = 0; } } else { - printf("TX Overflow\n"); + fprintf(stderr, "Serial MIDI: Warning: UART %d TX Overflow\n", sel); } midi_serial_iir_check(sel); pthread_mutex_unlock(&mregs[sel].fifo_mutex); diff --git a/src/midi.h b/src/midi.h index 7696e1d..1831327 100644 --- a/src/midi.h +++ b/src/midi.h @@ -11,6 +11,7 @@ #define MIDI_UART_OSC_RATE_MHZ 16.0f #define MIDI_UART_PRIMARY_DIVIDER 16 +#define MIDI_TEXT 0x01 #define NOTE_OFF 0x80 #define NOTE_ON 0x90 #define KEY_PRESSURE 0xa0 From 8e64857c893957bfaba5bcc6a780134decb93b09 Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Fri, 4 Oct 2024 15:24:45 -0700 Subject: [PATCH 50/63] type fixup --- src/midi.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/midi.c b/src/midi.c index 238e849..da25c38 100644 --- a/src/midi.c +++ b/src/midi.c @@ -408,7 +408,7 @@ void midi_event_enqueue_normal(struct midi_serial_regs* mrp, uint8_t cmd, uint8_ void midi_event_enqueue_sysex(struct midi_serial_regs* mrp, uint8_t *bufptr, int buflen) { int i; - if (mrp->mfsz >= 255 - (buflen + 2)) { // too full + if (mrp->mfsz >= 255L - (buflen + 2)) { // too full mrp->in_midi_last_command = 0; return; } @@ -418,6 +418,7 @@ void midi_event_enqueue_sysex(struct midi_serial_regs* mrp, uint8_t *bufptr, int mrp->midi_event_fifo[mrp->mfsz++] = bufptr[i]; } mrp->midi_event_fifo[mrp->mfsz++] = 0xf7; + mrp->in_midi_last_command = 0; } int handle_midi_event(void* data, fluid_midi_event_t* event) @@ -465,6 +466,8 @@ int handle_midi_event(void* data, fluid_midi_event_t* event) mrp->in_midi_last_command = 0; break; case MIDI_TUNE_REQUEST: + case 0xF4: + case 0xF5: midi_event_enqueue_byte(mrp, type); mrp->in_midi_last_command = 0; break; @@ -483,11 +486,6 @@ int handle_midi_event(void* data, fluid_midi_event_t* event) midi_event_enqueue_sysex(mrp, bufptr, buflen); fprintf(stderr, "Debug: MIDI IN: Type: SysEx Chan: %02X\n", chan); break; - case 0xF4: - case 0xF5: - midi_event_enqueue_byte(mrp, type); - mrp->in_midi_last_command = 0; - break; } //fprintf(stderr, "Debug: MIDI IN: Type: %02X Chan: %02X\n", type, chan); From 64f1719e36743ccf3c2e071e7e2517d5fb2a6f81 Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Sat, 5 Oct 2024 01:19:27 -0700 Subject: [PATCH 51/63] remove debugging, add a bit of error checking --- src/midi.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/midi.c b/src/midi.c index da25c38..dc61c9b 100644 --- a/src/midi.c +++ b/src/midi.c @@ -408,8 +408,9 @@ void midi_event_enqueue_normal(struct midi_serial_regs* mrp, uint8_t cmd, uint8_ void midi_event_enqueue_sysex(struct midi_serial_regs* mrp, uint8_t *bufptr, int buflen) { int i; + + mrp->in_midi_last_command = 0; if (mrp->mfsz >= 255L - (buflen + 2)) { // too full - mrp->in_midi_last_command = 0; return; } @@ -418,7 +419,6 @@ void midi_event_enqueue_sysex(struct midi_serial_regs* mrp, uint8_t *bufptr, int mrp->midi_event_fifo[mrp->mfsz++] = bufptr[i]; } mrp->midi_event_fifo[mrp->mfsz++] = 0xf7; - mrp->in_midi_last_command = 0; } int handle_midi_event(void* data, fluid_midi_event_t* event) @@ -482,9 +482,9 @@ int handle_midi_event(void* data, fluid_midi_event_t* event) break; case MIDI_SYSEX: dl_fluid_midi_event_set_type(event, MIDI_TEXT); - dl_fluid_midi_event_get_text(event, (void **)&bufptr, &buflen); - midi_event_enqueue_sysex(mrp, bufptr, buflen); - fprintf(stderr, "Debug: MIDI IN: Type: SysEx Chan: %02X\n", chan); + if (dl_fluid_midi_event_get_text(event, (void **)&bufptr, &buflen) == FLUID_OK && bufptr != NULL) { + midi_event_enqueue_sysex(mrp, bufptr, buflen); + } break; } From af5155f51b9555281e136b5891a4a47d40d06bc1 Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Sat, 5 Oct 2024 13:13:10 -0700 Subject: [PATCH 52/63] allow building without fluidsynth --- Makefile | 2 ++ src/main.c | 38 ++++++++++++++++++++++++++++++++++++++ src/midi.c | 8 +++++++- src/midi.h | 2 +- 4 files changed, 48 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 235f229..e257efc 100644 --- a/Makefile +++ b/Makefile @@ -77,6 +77,8 @@ ifdef EMSCRIPTEN CFLAGS+=-s USE_ZLIB=1 X16_OUTPUT=x16emu.html MAKECART_OUTPUT=makecart.html +else ifeq "$(shell printf '#include \nint main(){return 0;}' | $(CC) -x c -Wall -O -o /dev/null > /dev/null 2>/dev/null - && echo $$? )" "0" + CFLAGS+=-DHAS_FLUIDSYNTH endif _X16_OBJS = cpu/fake6502.o memory.o disasm.o video.o i2c.o smc.o rtc.o via.o serial.o ieee.o vera_spi.o audio.o vera_pcm.o vera_psg.o sdcard.o main.o debugger.o javascript_interface.o joystick.o rendertext.o keyboard.o icon.o timing.o wav_recorder.o testbench.o files.o cartridge.o iso_8859_15.o ymglue.o midi.o diff --git a/src/main.c b/src/main.c index d5f133b..66ff20a 100644 --- a/src/main.c +++ b/src/main.c @@ -562,6 +562,35 @@ usage_keymap() exit(1); } +void no_fluidsynth_warning(void) +{ + static bool already_warned; + + if (!already_warned) { + fprintf(stderr, "\nWarning: x16emu was built without FluidSynth support,\n"); + fprintf(stderr, "so the MIDI synth will be inoperative.\n\n"); +#if defined(__linux__) + fprintf(stderr, "To build x16emu with fluidsynth support, you distro may\n"); + fprintf(stderr, "have a libfluidsynth-dev or fluidsynth-devel package that\n"); + fprintf(stderr, "needs to be installed before building x16emu.\n\n"); +#elif defined(__APPLE__) + fprintf(stderr, "To build x16emu with fluidsynth support,\n"); + fprintf(stderr, "install the homebrew package fluid-synth before\n"); + fprintf(stderr, "building x16emu.\n\n"); +#elif defined(_WIN64) + fprintf(stderr, "To build x16emu with fluidsynth support under MSYS2,\n"); + fprintf(stderr, "install the mingw-w64-x86_64-fluidsynth package before\n"); + fprintf(stderr, "building x16emu.\n\n"); +#elif defined(_WIN32) + fprintf(stderr, "To build x16emu with fluidsynth support under MSYS2,\n"); + fprintf(stderr, "install the mingw-w64-i686-fluidsynth package before\n"); + fprintf(stderr, "building x16emu.\n\n"); +#endif + + already_warned = true; + } +} + int main(int argc, char **argv) { @@ -647,6 +676,9 @@ main(int argc, char **argv) argc--; argv++; } else if (!strcmp(argv[0], "-midicard")) { +#ifndef HAS_FLUIDSYNTH + no_fluidsynth_warning(); +#endif argc--; argv++; has_midi_card = true; @@ -659,6 +691,9 @@ main(int argc, char **argv) midi_card_addr = 0x9f60; } } else if (!strcmp(argv[0], "-sf2")) { +#ifndef HAS_FLUIDSYNTH + no_fluidsynth_warning(); +#endif argc--; argv++; if (!argc || argv[0][0] == '-') { @@ -668,6 +703,9 @@ main(int argc, char **argv) argc--; argv++; } else if (!strcmp(argv[0], "-midi-in")) { +#ifndef HAS_FLUIDSYNTH + no_fluidsynth_warning(); +#endif argc--; argv++; fs_midi_in_connect = true; diff --git a/src/midi.c b/src/midi.c index dc61c9b..3fbe6d6 100644 --- a/src/midi.c +++ b/src/midi.c @@ -131,7 +131,7 @@ static bool serial_midi_mutexes_initialized = false; void midi_serial_iir_check(uint8_t sel); bool fs_midi_in_connect = false; -#ifndef __EMSCRIPTEN__ +#ifdef HAS_FLUIDSYNTH int handle_midi_event(void* data, fluid_midi_event_t* event); @@ -481,6 +481,12 @@ int handle_midi_event(void* data, fluid_midi_event_t* event) midi_event_enqueue_byte(mrp, type); break; case MIDI_SYSEX: + // FluidSynth doesn't offer a get_sysex function, but internally + // a text event is equivalent to a sysex event, in terms of what + // parts of the event structure are populated + // + // Unfortunately that means we have to fool it in order to + // access the data. dl_fluid_midi_event_set_type(event, MIDI_TEXT); if (dl_fluid_midi_event_get_text(event, (void **)&bufptr, &buflen) == FLUID_OK && bufptr != NULL) { midi_event_enqueue_sysex(mrp, bufptr, buflen); diff --git a/src/midi.h b/src/midi.h index 1831327..309065d 100644 --- a/src/midi.h +++ b/src/midi.h @@ -4,7 +4,7 @@ #pragma once -#ifndef __EMSCRIPTEN__ +#ifdef HAS_FLUIDSYNTH #include #endif From 9eaf32b66ee4291c2e42a5c98aa10f1af4cac537 Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Sat, 5 Oct 2024 13:17:14 -0700 Subject: [PATCH 53/63] less lenient Makefile syntax --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index e257efc..31b119c 100644 --- a/Makefile +++ b/Makefile @@ -77,7 +77,7 @@ ifdef EMSCRIPTEN CFLAGS+=-s USE_ZLIB=1 X16_OUTPUT=x16emu.html MAKECART_OUTPUT=makecart.html -else ifeq "$(shell printf '#include \nint main(){return 0;}' | $(CC) -x c -Wall -O -o /dev/null > /dev/null 2>/dev/null - && echo $$? )" "0" +else ifeq ($(shell printf '#include \nint main(){return 0;}' | $(CC) -x c -Wall -O -o /dev/null > /dev/null 2>/dev/null - && echo $$? ),0) CFLAGS+=-DHAS_FLUIDSYNTH endif From fb0cbc02cf4c3561909c9c834f11fdbb5268d43f Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Sat, 5 Oct 2024 13:19:08 -0700 Subject: [PATCH 54/63] even less lenient Makefile syntax --- Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 31b119c..5ae0e47 100644 --- a/Makefile +++ b/Makefile @@ -77,9 +77,11 @@ ifdef EMSCRIPTEN CFLAGS+=-s USE_ZLIB=1 X16_OUTPUT=x16emu.html MAKECART_OUTPUT=makecart.html -else ifeq ($(shell printf '#include \nint main(){return 0;}' | $(CC) -x c -Wall -O -o /dev/null > /dev/null 2>/dev/null - && echo $$? ),0) +else +ifeq ($(shell printf '#include \nint main(){return 0;}' | $(CC) -x c -Wall -O -o /dev/null > /dev/null 2>/dev/null - && echo $$? ),0) CFLAGS+=-DHAS_FLUIDSYNTH endif +endif _X16_OBJS = cpu/fake6502.o memory.o disasm.o video.o i2c.o smc.o rtc.o via.o serial.o ieee.o vera_spi.o audio.o vera_pcm.o vera_psg.o sdcard.o main.o debugger.o javascript_interface.o joystick.o rendertext.o keyboard.o icon.o timing.o wav_recorder.o testbench.o files.o cartridge.o iso_8859_15.o ymglue.o midi.o _X16_OBJS += extern/ymfm/src/ymfm_opm.o From 95b81b8e3a33a4997debc776b32d255b5c9a8d7c Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Sat, 5 Oct 2024 13:20:08 -0700 Subject: [PATCH 55/63] even less lenient Makefile syntax --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 5ae0e47..959216f 100644 --- a/Makefile +++ b/Makefile @@ -78,7 +78,7 @@ ifdef EMSCRIPTEN X16_OUTPUT=x16emu.html MAKECART_OUTPUT=makecart.html else -ifeq ($(shell printf '#include \nint main(){return 0;}' | $(CC) -x c -Wall -O -o /dev/null > /dev/null 2>/dev/null - && echo $$? ),0) +ifeq ($(shell printf '#include \nint main(){return 0;}' | $(CC) -x c -Wall -O -o /dev/null > /dev/null 2>/dev/null - && echo $$?),0) CFLAGS+=-DHAS_FLUIDSYNTH endif endif From 8eef60487d1a2d241b15ec3b9fbe5d230cdb28ff Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Sat, 5 Oct 2024 13:27:48 -0700 Subject: [PATCH 56/63] test makefile on runners --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 959216f..40187d8 100644 --- a/Makefile +++ b/Makefile @@ -78,7 +78,7 @@ ifdef EMSCRIPTEN X16_OUTPUT=x16emu.html MAKECART_OUTPUT=makecart.html else -ifeq ($(shell printf '#include \nint main(){return 0;}' | $(CC) -x c -Wall -O -o /dev/null > /dev/null 2>/dev/null - && echo $$?),0) +ifeq ($(shell /usr/bin/printf '#include \nint main(){return 0;}' | $(CC) -x c -Wall -O -o /dev/null - && echo $$?),0) CFLAGS+=-DHAS_FLUIDSYNTH endif endif From 7144ec186dcb9d925243306937f527dd07a92aa0 Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Sat, 5 Oct 2024 13:36:33 -0700 Subject: [PATCH 57/63] trying it another way --- Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 40187d8..9fcdcab 100644 --- a/Makefile +++ b/Makefile @@ -78,7 +78,8 @@ ifdef EMSCRIPTEN X16_OUTPUT=x16emu.html MAKECART_OUTPUT=makecart.html else -ifeq ($(shell /usr/bin/printf '#include \nint main(){return 0;}' | $(CC) -x c -Wall -O -o /dev/null - && echo $$?),0) + FLUIDSYNTH_TEST=$(shell /usr/bin/printf '#include \nint main(){return 0;}' | $(CC) -x c -Wall -O -o /dev/null > /dev/null 2>/dev/null - && echo $$?) +ifeq ($(FLUIDSYNTH_TEST),0) CFLAGS+=-DHAS_FLUIDSYNTH endif endif From c7c5ade27887b2049eea8901f81d41733c3bdbb8 Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Sat, 5 Oct 2024 13:43:08 -0700 Subject: [PATCH 58/63] trying something else --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 9fcdcab..e257b15 100644 --- a/Makefile +++ b/Makefile @@ -78,7 +78,7 @@ ifdef EMSCRIPTEN X16_OUTPUT=x16emu.html MAKECART_OUTPUT=makecart.html else - FLUIDSYNTH_TEST=$(shell /usr/bin/printf '#include \nint main(){return 0;}' | $(CC) -x c -Wall -O -o /dev/null > /dev/null 2>/dev/null - && echo $$?) + FLUIDSYNTH_TEST=$(shell /usr/bin/printf '\043include \nint main(){return 0;} ' | $(CC) -x c -Wall -O -o /dev/null > /dev/null 2>/dev/null - && echo $$?) ifeq ($(FLUIDSYNTH_TEST),0) CFLAGS+=-DHAS_FLUIDSYNTH endif From 07025baaaf7b382a785bc193181ec84616d42ba3 Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Sat, 5 Oct 2024 14:01:35 -0700 Subject: [PATCH 59/63] update builds for fluidsynth --- .github/workflows/build.yml | 14 +++++++------- Makefile | 9 ++++----- src/main.c | 3 ++- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 446ef52..e549d7c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -65,7 +65,7 @@ jobs: run: | git reset --hard git diff - TRACE=1 CROSS_COMPILE_WINDOWS=1 SDL2CONFIG=sdl2-config make V=1 -j2 + TRACE=1 FLUIDSYNTH=1 CROSS_COMPILE_WINDOWS=1 SDL2CONFIG=sdl2-config make V=1 -j2 mkdir emu_binaries cp $(which SDL2.dll) emu_binaries/. cp $(which zlib1.dll) emu_binaries/. @@ -151,7 +151,7 @@ jobs: run: | git reset --hard git diff - TRACE=1 WIN_SDL2=/mingw32 TARGET_CPU=x86 CROSS_COMPILE_WINDOWS=1 make V=1 -j2 + TRACE=1 FLUIDSYNTH=1 WIN_SDL2=/mingw32 TARGET_CPU=x86 CROSS_COMPILE_WINDOWS=1 make V=1 -j2 mkdir emu_binaries cp $(which SDL2.dll) emu_binaries/. cp $(which zlib1.dll) emu_binaries/. @@ -227,7 +227,7 @@ jobs: cp latest_rom/*.h src/. - name: Build Emulator run: | - TRACE=1 make V=1 -j3 + TRACE=1 FLUIDSYNTH=1 make V=1 -j3 mkdir emu_binaries cp sdcard.img.zip emu_binaries/. cp x16emu emu_binaries/. @@ -286,7 +286,7 @@ jobs: commands: | apt-get update apt-get install -y build-essential make libsdl2-dev file git libfluidsynth-dev - TRACE=1 make V=1 -j3 + TRACE=1 FLUIDSYNTH=1 make V=1 -j3 mkdir emu_binaries cp sdcard.img.zip emu_binaries/. cp x16emu emu_binaries/. @@ -346,7 +346,7 @@ jobs: commands: | apt-get update apt-get install -y build-essential make libsdl2-dev file git libfluidsynth-dev - TRACE=1 make V=1 -j3 + TRACE=1 FLUIDSYNTH=1 make V=1 -j3 mkdir emu_binaries cp sdcard.img.zip emu_binaries/. cp x16emu emu_binaries/. @@ -398,7 +398,7 @@ jobs: cp latest_rom/*.h src/. - name: Build Emulator run: | - TRACE=1 MAC_STATIC=1 HOMEBREW_LIB=/usr/local/lib make V=1 -j3 + TRACE=1 MAC_STATIC=1 LIBSDL_FILE=/usr/local/Cellar/sdl2/*/lib/libSDL2.a HOMEBREW_LIB=/usr/local/lib make V=1 -j3 mkdir emu_binaries cp sdcard.img.zip emu_binaries/. cp x16emu emu_binaries/. @@ -448,7 +448,7 @@ jobs: cp latest_rom/*.h src/. - name: Build Emulator run: | - TRACE=1 MAC_STATIC=1 ADDL_INCLUDE=/opt/homebrew/include HOMEBREW_LIB=/opt/homebrew/lib make V=1 -j3 + TRACE=1 MAC_STATIC=1 LIBSDL_FILE=/opt/homebrew/Cellar/sdl2/*/lib/libSDL2.a ADDL_INCLUDE=/opt/homebrew/include HOMEBREW_LIB=/opt/homebrew/lib FLUIDSYNTH=1 make V=1 -j3 mkdir emu_binaries cp sdcard.img.zip emu_binaries/. cp x16emu emu_binaries/. diff --git a/Makefile b/Makefile index e257b15..5be7688 100644 --- a/Makefile +++ b/Makefile @@ -48,7 +48,7 @@ GIT_REV=$(shell git diff --quiet && /bin/echo -n $$(git rev-parse --short=8 HEAD CFLAGS+=-D GIT_REV='"$(GIT_REV)"' ifeq ($(MAC_STATIC),1) - LDFLAGS+=$(HOMEBREW_LIB)/libSDL2.a -lm -liconv -lz -Wl,-framework,CoreAudio -Wl,-framework,AudioToolbox -Wl,-framework,ForceFeedback -lobjc -Wl,-framework,CoreVideo -Wl,-framework,Cocoa -Wl,-framework,Carbon -Wl,-framework,IOKit -Wl,-weak_framework,QuartzCore -Wl,-weak_framework,Metal -Wl,-weak_framework,CoreHaptics -Wl,-weak_framework,GameController + LDFLAGS+=$(LIBSDL_FILE) -lm -liconv -lz -Wl,-framework,CoreAudio -Wl,-framework,AudioToolbox -Wl,-framework,ForceFeedback -lobjc -Wl,-framework,CoreVideo -Wl,-framework,Cocoa -Wl,-framework,Carbon -Wl,-framework,IOKit -Wl,-weak_framework,QuartzCore -Wl,-weak_framework,Metal -Wl,-weak_framework,CoreHaptics -Wl,-weak_framework,GameController LDEMU=-ldl -Wl,-rpath,$(HOMEBREW_LIB) else ifeq ($(CROSS_COMPILE_WINDOWS),1) LDFLAGS+=-L$(MINGW32)/lib @@ -77,11 +77,10 @@ ifdef EMSCRIPTEN CFLAGS+=-s USE_ZLIB=1 X16_OUTPUT=x16emu.html MAKECART_OUTPUT=makecart.html -else - FLUIDSYNTH_TEST=$(shell /usr/bin/printf '\043include \nint main(){return 0;} ' | $(CC) -x c -Wall -O -o /dev/null > /dev/null 2>/dev/null - && echo $$?) -ifeq ($(FLUIDSYNTH_TEST),0) - CFLAGS+=-DHAS_FLUIDSYNTH endif + +ifeq ($(FLUIDSYNTH),1) + CFLAGS+=-DHAS_FLUIDSYNTH endif _X16_OBJS = cpu/fake6502.o memory.o disasm.o video.o i2c.o smc.o rtc.o via.o serial.o ieee.o vera_spi.o audio.o vera_pcm.o vera_psg.o sdcard.o main.o debugger.o javascript_interface.o joystick.o rendertext.o keyboard.o icon.o timing.o wav_recorder.o testbench.o files.o cartridge.o iso_8859_15.o ymglue.o midi.o diff --git a/src/main.c b/src/main.c index 66ff20a..2a15a4d 100644 --- a/src/main.c +++ b/src/main.c @@ -586,7 +586,8 @@ void no_fluidsynth_warning(void) fprintf(stderr, "install the mingw-w64-i686-fluidsynth package before\n"); fprintf(stderr, "building x16emu.\n\n"); #endif - + fprintf(stderr, "Then build x16emu with FLUIDSYNTH=1. For example:\n"); + fprintf(stderr, "FLUIDSYNTH=1 make\n"); already_warned = true; } } From ba8af959835d0d6eeffe0cae08636bfb3c32d611 Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Sat, 5 Oct 2024 14:10:49 -0700 Subject: [PATCH 60/63] fix MAC static SDL2 build --- Makefile | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 5be7688..0bba141 100644 --- a/Makefile +++ b/Makefile @@ -20,12 +20,6 @@ CFLAGS=-std=c99 -O3 -Wall -Werror -g $(shell $(SDL2CONFIG) --cflags) -Isrc/exter CXXFLAGS=-std=c++17 -O3 -Wall -Werror -Isrc/extern/ymfm/src LDFLAGS=$(shell $(SDL2CONFIG) --libs) -lm -lz -pthread -# build with link time optimization -ifndef NOLTO - CFLAGS+=-flto - LDFLAGS+=-flto -endif - ifdef ADDL_INCLUDE CFLAGS+=-I$(ADDL_INCLUDE) endif @@ -48,7 +42,7 @@ GIT_REV=$(shell git diff --quiet && /bin/echo -n $$(git rev-parse --short=8 HEAD CFLAGS+=-D GIT_REV='"$(GIT_REV)"' ifeq ($(MAC_STATIC),1) - LDFLAGS+=$(LIBSDL_FILE) -lm -liconv -lz -Wl,-framework,CoreAudio -Wl,-framework,AudioToolbox -Wl,-framework,ForceFeedback -lobjc -Wl,-framework,CoreVideo -Wl,-framework,Cocoa -Wl,-framework,Carbon -Wl,-framework,IOKit -Wl,-weak_framework,QuartzCore -Wl,-weak_framework,Metal -Wl,-weak_framework,CoreHaptics -Wl,-weak_framework,GameController + LDFLAGS=$(LIBSDL_FILE) -lm -liconv -lz -Wl,-framework,CoreAudio -Wl,-framework,AudioToolbox -Wl,-framework,ForceFeedback -lobjc -Wl,-framework,CoreVideo -Wl,-framework,Cocoa -Wl,-framework,Carbon -Wl,-framework,IOKit -Wl,-weak_framework,QuartzCore -Wl,-weak_framework,Metal -Wl,-weak_framework,CoreHaptics -Wl,-weak_framework,GameController -pthread LDEMU=-ldl -Wl,-rpath,$(HOMEBREW_LIB) else ifeq ($(CROSS_COMPILE_WINDOWS),1) LDFLAGS+=-L$(MINGW32)/lib @@ -66,6 +60,12 @@ else # Not Mac, not Windows, probably Linux LDEMU=-ldl endif +# build with link time optimization +ifndef NOLTO + CFLAGS+=-flto + LDFLAGS+=-flto +endif + ifdef TARGET_WIN32 LDFLAGS+=-ldwmapi endif From 726300167c070104240122aeb40ff58233f91248 Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Sat, 5 Oct 2024 17:35:43 -0700 Subject: [PATCH 61/63] some changes for review --- src/cpu/registers.h | 23 +----------------- src/endian.h | 21 ++++++++++++++++ src/midi.c | 59 +++++++++++++++------------------------------ src/midi.h | 46 +++++++++++++++++------------------ 4 files changed, 64 insertions(+), 85 deletions(-) create mode 100644 src/endian.h diff --git a/src/cpu/registers.h b/src/cpu/registers.h index b1f9195..a35d5b2 100644 --- a/src/cpu/registers.h +++ b/src/cpu/registers.h @@ -4,6 +4,7 @@ #include #include +#include "../endian.h" #define FLAG_CARRY 0x01 #define FLAG_ZERO 0x02 @@ -20,26 +21,6 @@ //6502 CPU registers -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -#define LOW_HIGH_UNION(name, low, high) \ - union { \ - struct { \ - uint8_t low; \ - uint8_t high; \ - }; \ - uint16_t name; \ - } -#else -#define LOW_HIGH_UNION(name, low, high) \ - union { \ - struct { \ - uint8_t high; \ - uint8_t low; \ - }; \ - uint16_t name; \ - } -#endif - struct regs { LOW_HIGH_UNION(c, a, b); @@ -59,8 +40,6 @@ struct regs bool is65c816; }; -#undef LOW_HIGH_UNION - void increment_wrap_at_page_boundary(uint16_t *value); void decrement_wrap_at_page_boundary(uint16_t *value); uint16_t direct_page_add(uint16_t offset); diff --git a/src/endian.h b/src/endian.h new file mode 100644 index 0000000..03a7278 --- /dev/null +++ b/src/endian.h @@ -0,0 +1,21 @@ +#pragma once + +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#define LOW_HIGH_UNION(name, low, high) \ + union { \ + struct { \ + uint8_t low; \ + uint8_t high; \ + }; \ + uint16_t name; \ + } +#else +#define LOW_HIGH_UNION(name, low, high) \ + union { \ + struct { \ + uint8_t high; \ + uint8_t low; \ + }; \ + uint16_t name; \ + } +#endif diff --git a/src/midi.c b/src/midi.c index 3fbe6d6..3302582 100644 --- a/src/midi.c +++ b/src/midi.c @@ -6,6 +6,7 @@ #include "glue.h" #include "midi.h" #include "audio.h" +#include "endian.h" #ifdef _WIN32 #include @@ -32,26 +33,6 @@ enum MIDI_states { SYSEX, }; -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -#define LOW_HIGH_UNION(name, low, high) \ - union { \ - struct { \ - uint8_t low; \ - uint8_t high; \ - }; \ - uint16_t name; \ - } -#else -#define LOW_HIGH_UNION(name, low, high) \ - union { \ - struct { \ - uint8_t high; \ - uint8_t low; \ - }; \ - uint16_t name; \ - } -#endif - struct midi_serial_regs { LOW_HIGH_UNION(dl, dll, dlm); @@ -123,8 +104,6 @@ struct midi_serial_regs pthread_mutexattr_t fifo_mutex_attr; }; -#undef LOW_HIGH_UNION - struct midi_serial_regs mregs[2]; static bool serial_midi_mutexes_initialized = false; @@ -434,60 +413,60 @@ int handle_midi_event(void* data, fluid_midi_event_t* event) int buflen; switch (type) { - case NOTE_OFF: - case NOTE_ON: + case FS_NOTE_OFF: + case FS_NOTE_ON: key = dl_fluid_midi_event_get_key(event); val = dl_fluid_midi_event_get_velocity(event); midi_event_enqueue_normal(mrp, cmd, key, val); break; - case KEY_PRESSURE: + case FS_KEY_PRESSURE: key = dl_fluid_midi_event_get_key(event); val = dl_fluid_midi_event_get_value(event); midi_event_enqueue_normal(mrp, cmd, key, val); break; - case CONTROL_CHANGE: + case FS_CONTROL_CHANGE: key = dl_fluid_midi_event_get_control(event); val = dl_fluid_midi_event_get_value(event); midi_event_enqueue_normal(mrp, cmd, key, val); break; - case PITCH_BEND: + case FS_PITCH_BEND: key = dl_fluid_midi_event_get_pitch(event) & 0x7f; val = (dl_fluid_midi_event_get_pitch(event) >> 7) & 0x7f; midi_event_enqueue_normal(mrp, cmd, key, val); break; - case PROGRAM_CHANGE: - case CHANNEL_PRESSURE: + case FS_PROGRAM_CHANGE: + case FS_CHANNEL_PRESSURE: val = dl_fluid_midi_event_get_program(event); midi_event_enqueue_short(mrp, cmd, val); break; - case MIDI_TIME_CODE: + case FS_MIDI_TIME_CODE: val = dl_fluid_midi_event_get_value(event); midi_event_enqueue_short(mrp, type, val); mrp->in_midi_last_command = 0; break; - case MIDI_TUNE_REQUEST: + case FS_MIDI_TUNE_REQUEST: case 0xF4: case 0xF5: midi_event_enqueue_byte(mrp, type); mrp->in_midi_last_command = 0; break; - case MIDI_SYNC: - case MIDI_TICK: - case MIDI_START: - case MIDI_CONTINUE: - case MIDI_STOP: - case MIDI_ACTIVE_SENSING: - case MIDI_SYSTEM_RESET: + case FS_MIDI_SYNC: + case FS_MIDI_TICK: + case FS_MIDI_START: + case FS_MIDI_CONTINUE: + case FS_MIDI_STOP: + case FS_MIDI_ACTIVE_SENSING: + case FS_MIDI_SYSTEM_RESET: midi_event_enqueue_byte(mrp, type); break; - case MIDI_SYSEX: + case FS_MIDI_SYSEX: // FluidSynth doesn't offer a get_sysex function, but internally // a text event is equivalent to a sysex event, in terms of what // parts of the event structure are populated // // Unfortunately that means we have to fool it in order to // access the data. - dl_fluid_midi_event_set_type(event, MIDI_TEXT); + dl_fluid_midi_event_set_type(event, FS_MIDI_TEXT); if (dl_fluid_midi_event_get_text(event, (void **)&bufptr, &buflen) == FLUID_OK && bufptr != NULL) { midi_event_enqueue_sysex(mrp, bufptr, buflen); } diff --git a/src/midi.h b/src/midi.h index 309065d..8aed657 100644 --- a/src/midi.h +++ b/src/midi.h @@ -11,31 +11,31 @@ #define MIDI_UART_OSC_RATE_MHZ 16.0f #define MIDI_UART_PRIMARY_DIVIDER 16 -#define MIDI_TEXT 0x01 -#define NOTE_OFF 0x80 -#define NOTE_ON 0x90 -#define KEY_PRESSURE 0xa0 -#define CONTROL_CHANGE 0xb0 -#define PROGRAM_CHANGE 0xc0 -#define CHANNEL_PRESSURE 0xd0 -#define PITCH_BEND 0xe0 -#define MIDI_SYSEX 0xf0 -#define MIDI_TIME_CODE 0xf1 -#define MIDI_SONG_POSITION 0xf2 -#define MIDI_SONG_SELECT 0xf3 -#define MIDI_TUNE_REQUEST 0xf6 -#define MIDI_EOX 0xf7 -#define MIDI_SYNC 0xf8 -#define MIDI_TICK 0xf9 -#define MIDI_START 0xfa -#define MIDI_CONTINUE 0xfb -#define MIDI_STOP 0xfc -#define MIDI_ACTIVE_SENSING 0xfe -#define MIDI_SYSTEM_RESET 0xff +#define FS_MIDI_TEXT 0x01 +#define FS_NOTE_OFF 0x80 +#define FS_NOTE_ON 0x90 +#define FS_KEY_PRESSURE 0xa0 +#define FS_CONTROL_CHANGE 0xb0 +#define FS_PROGRAM_CHANGE 0xc0 +#define FS_CHANNEL_PRESSURE 0xd0 +#define FS_PITCH_BEND 0xe0 +#define FS_MIDI_SYSEX 0xf0 +#define FS_MIDI_TIME_CODE 0xf1 +#define FS_MIDI_SONG_POSITION 0xf2 +#define FS_MIDI_SONG_SELECT 0xf3 +#define FS_MIDI_TUNE_REQUEST 0xf6 +#define FS_MIDI_EOX 0xf7 +#define FS_MIDI_SYNC 0xf8 +#define FS_MIDI_TICK 0xf9 +#define FS_MIDI_START 0xfa +#define FS_MIDI_CONTINUE 0xfb +#define FS_MIDI_STOP 0xfc +#define FS_MIDI_ACTIVE_SENSING 0xfe +#define FS_MIDI_SYSTEM_RESET 0xff -void midi_init(); -void midi_serial_init(); +void midi_init(void); +void midi_serial_init(void); void midi_serial_step(int clocks); uint8_t midi_serial_read(uint8_t reg, bool debugOn); void midi_serial_write(uint8_t reg, uint8_t val); From c4e286c1c6d902c6a80a837fe91e987197d64e58 Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Sat, 5 Oct 2024 20:04:11 -0700 Subject: [PATCH 62/63] more updates via review, doubled FS level in audio mix --- src/audio.c | 6 +++--- src/midi.c | 26 +++++++++++++------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/audio.c b/src/audio.c index f258ab2..c2bfae7 100644 --- a/src/audio.c +++ b/src/audio.c @@ -380,9 +380,9 @@ audio_render() } // VERA+YM mixing is according to the Developer Board // Loudest single PSG channel is 1/8 times the max output - // mix = (psg + pcm) * 2 + ym + fs - int32_t mix_l = (vera_out_l >> 13) + (ym_out_l >> 15) + (fs_out_l >> 13); - int32_t mix_r = (vera_out_r >> 13) + (ym_out_r >> 15) + (fs_out_r >> 13); + // mix = (psg + pcm) * 2 + ym + fs * 4 + int32_t mix_l = (vera_out_l >> 13) + (ym_out_l >> 15) + (fs_out_l >> 12); + int32_t mix_r = (vera_out_r >> 13) + (ym_out_r >> 15) + (fs_out_r >> 12); uint32_t amp = SDL_max(SDL_abs(mix_l), SDL_abs(mix_r)); if (amp > 32767) { uint32_t limiter_amp_new = (32767 << 16) / amp; diff --git a/src/midi.c b/src/midi.c index 3302582..5d4c146 100644 --- a/src/midi.c +++ b/src/midi.c @@ -12,7 +12,7 @@ #include #define LIBRARY_TYPE HMODULE #define LOAD_LIBRARY(name) LoadLibrary(name) - #define GET_FUNCTION(lib, name) GetProcAddress(lib, name) + #define GET_FUNCTION(lib, name) (void *)GetProcAddress(lib, name) #define CLOSE_LIBRARY(lib) FreeLibrary(lib) #else #include @@ -23,14 +23,14 @@ #endif #define ASSIGN_FUNCTION(lib, var, name) {\ - var = (void *)GET_FUNCTION(lib, name);\ + var = GET_FUNCTION(lib, name);\ if (!var) { fprintf(stderr, "Unable to find symbol for '%s'\n", name); CLOSE_LIBRARY(handle); return; }\ } enum MIDI_states { - NORMAL, - PARAM, - SYSEX, + MSTATE_Normal, + MSTATE_Param, + MSTATE_SysEx, }; struct midi_serial_regs @@ -117,7 +117,7 @@ int handle_midi_event(void* data, fluid_midi_event_t* event); static uint8_t sysex_buffer[1024]; static int sysex_bufptr; -static enum MIDI_states midi_state = NORMAL; +static enum MIDI_states midi_state = MSTATE_Normal; static uint8_t out_midi_last_command[2] = {0, 0}; static uint8_t out_midi_first_param[2]; @@ -276,7 +276,7 @@ void midi_byte_out(uint8_t sel, uint8_t b) { if (!midi_initialized) return; switch (midi_state) { - case NORMAL: + case MSTATE_Normal: if (b < 0x80) { if ((out_midi_last_command[sel] & 0xf0) == 0xc0) { // patch change dl_fs_program_change(fl_synth, out_midi_last_command[sel] & 0xf, b); @@ -284,21 +284,21 @@ void midi_byte_out(uint8_t sel, uint8_t b) dl_fs_channel_pressure(fl_synth, out_midi_last_command[sel] & 0xf, b); } else if (out_midi_last_command[sel] >= 0x80) { // two-param command out_midi_first_param[sel] = b; - midi_state = PARAM; + midi_state = MSTATE_Param; } } else { if (b < 0xf0) { out_midi_last_command[sel] = b; } else if (b == 0xf0) { sysex_bufptr = 0; - midi_state = SYSEX; + midi_state = MSTATE_SysEx; } else if (b == 0xff) { dl_fs_system_reset(fl_synth); out_midi_last_command[sel] = 0; } } break; - case PARAM: + case MSTATE_Param: switch (out_midi_last_command[sel] & 0xf0) { case 0x80: // note off dl_fs_noteoff(fl_synth, out_midi_last_command[sel] & 0xf, out_midi_first_param[sel]); // no release velocity @@ -320,15 +320,15 @@ void midi_byte_out(uint8_t sel, uint8_t b) dl_fs_pitch_bend(fl_synth, out_midi_last_command[sel] & 0xf, ((uint16_t)out_midi_first_param[sel]) | (uint16_t)b << 7); break; } - midi_state = NORMAL; + midi_state = MSTATE_Normal; break; - case SYSEX: + case MSTATE_SysEx: if (b & 0x80) { // any command byte can terminate a SYSEX, not just 0xf7 if (sysex_bufptr < (sizeof(sysex_buffer) / sizeof(sysex_buffer[0]))-1) { // only if buffer didn't fill sysex_buffer[sysex_bufptr] = 0; dl_fs_sysex(fl_synth, (const char *)sysex_buffer, sysex_bufptr, NULL, NULL, NULL, 0); } - midi_state = NORMAL; + midi_state = MSTATE_Normal; return midi_byte_out(sel, b); } else { sysex_buffer[sysex_bufptr] = b; From 7ca6c8aecf1b3e50f64ece81ed2414d3916ee055 Mon Sep 17 00:00:00 2001 From: mooinglemur Date: Sat, 5 Oct 2024 22:59:23 -0700 Subject: [PATCH 63/63] add master volume sysex handling --- src/midi.c | 17 +++++++++++------ src/midi.h | 1 + 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/midi.c b/src/midi.c index 5d4c146..5e79bd7 100644 --- a/src/midi.c +++ b/src/midi.c @@ -117,7 +117,7 @@ int handle_midi_event(void* data, fluid_midi_event_t* event); static uint8_t sysex_buffer[1024]; static int sysex_bufptr; -static enum MIDI_states midi_state = MSTATE_Normal; +static enum MIDI_states midi_state[2] = {MSTATE_Normal, MSTATE_Normal}; static uint8_t out_midi_last_command[2] = {0, 0}; static uint8_t out_midi_first_param[2]; @@ -250,6 +250,7 @@ void midi_init() fl_settings = dl_new_fluid_settings(); dl_fluid_settings_setnum(fl_settings, "synth.sample-rate", AUDIO_SAMPLERATE); + dl_fluid_settings_setnum(fl_settings, "synth.gain", FL_DEFAULT_GAIN); dl_fluid_settings_setstr(fl_settings, "midi.portname", "Commander X16 Emulator"); dl_fluid_settings_setint(fl_settings, "midi.autoconnect", fs_midi_in_connect); fl_synth = dl_new_fluid_synth(fl_settings); @@ -275,7 +276,7 @@ void midi_load_sf2(uint8_t* filename) void midi_byte_out(uint8_t sel, uint8_t b) { if (!midi_initialized) return; - switch (midi_state) { + switch (midi_state[sel]) { case MSTATE_Normal: if (b < 0x80) { if ((out_midi_last_command[sel] & 0xf0) == 0xc0) { // patch change @@ -284,14 +285,14 @@ void midi_byte_out(uint8_t sel, uint8_t b) dl_fs_channel_pressure(fl_synth, out_midi_last_command[sel] & 0xf, b); } else if (out_midi_last_command[sel] >= 0x80) { // two-param command out_midi_first_param[sel] = b; - midi_state = MSTATE_Param; + midi_state[sel] = MSTATE_Param; } } else { if (b < 0xf0) { out_midi_last_command[sel] = b; } else if (b == 0xf0) { sysex_bufptr = 0; - midi_state = MSTATE_SysEx; + midi_state[sel] = MSTATE_SysEx; } else if (b == 0xff) { dl_fs_system_reset(fl_synth); out_midi_last_command[sel] = 0; @@ -320,15 +321,19 @@ void midi_byte_out(uint8_t sel, uint8_t b) dl_fs_pitch_bend(fl_synth, out_midi_last_command[sel] & 0xf, ((uint16_t)out_midi_first_param[sel]) | (uint16_t)b << 7); break; } - midi_state = MSTATE_Normal; + midi_state[sel] = MSTATE_Normal; break; case MSTATE_SysEx: if (b & 0x80) { // any command byte can terminate a SYSEX, not just 0xf7 if (sysex_bufptr < (sizeof(sysex_buffer) / sizeof(sysex_buffer[0]))-1) { // only if buffer didn't fill sysex_buffer[sysex_bufptr] = 0; + // Handle Master Volume SysEx + if (!strncmp((const char *)sysex_buffer, "\x7F\x7F\x04\x01\x00", sysex_bufptr-1)) { + dl_fluid_settings_setnum(fl_settings, "synth.gain", FL_DEFAULT_GAIN*((float)sysex_buffer[sysex_bufptr-1]/127)); + } dl_fs_sysex(fl_synth, (const char *)sysex_buffer, sysex_bufptr, NULL, NULL, NULL, 0); } - midi_state = MSTATE_Normal; + midi_state[sel] = MSTATE_Normal; return midi_byte_out(sel, b); } else { sysex_buffer[sysex_bufptr] = b; diff --git a/src/midi.h b/src/midi.h index 8aed657..236feb0 100644 --- a/src/midi.h +++ b/src/midi.h @@ -33,6 +33,7 @@ #define FS_MIDI_ACTIVE_SENSING 0xfe #define FS_MIDI_SYSTEM_RESET 0xff +#define FL_DEFAULT_GAIN 0.2f void midi_init(void); void midi_serial_init(void);