From d15342f46cb6e8144d3b78aff4ec59451b284404 Mon Sep 17 00:00:00 2001 From: Jose Phillips Date: Sun, 1 Dec 2024 18:07:35 -0500 Subject: [PATCH 01/24] Initial Support for OPL2Board Arduino --- src/include/86box/snd_opl.h | 6 +- src/include/86box/sound.h | 3 + src/sound/CMakeLists.txt | 11 +- src/sound/snd_opl.c | 7 + src/sound/snd_opl2board.c | 183 +++++++++++ src/sound/snd_opl_opl2board.cpp | 550 ++++++++++++++++++++++++++++++++ src/sound/sound.c | 1 + 7 files changed, 758 insertions(+), 3 deletions(-) create mode 100644 src/sound/snd_opl2board.c create mode 100644 src/sound/snd_opl_opl2board.cpp diff --git a/src/include/86box/snd_opl.h b/src/include/86box/snd_opl.h index 441e2a119..95eec2687 100644 --- a/src/include/86box/snd_opl.h +++ b/src/include/86box/snd_opl.h @@ -23,7 +23,8 @@ enum fm_type { FM_YMF289B = 2, /* OPL3-L */ FM_YMF278B = 3, /* OPL 4 */ FM_ESFM = 4, /* ESFM */ - FM_MAX = 5 + FM_MAX = 5, + FM_OPL2BOARD = 6 /* OPL2BOARD (External Device)*/ }; enum fm_driver { @@ -47,6 +48,7 @@ extern uint8_t fm_driver_get(int chip_id, fm_drv_t *drv); extern const fm_drv_t nuked_opl_drv; extern const fm_drv_t ymfm_drv; extern const fm_drv_t esfmu_opl_drv; +extern const fm_drv_t ymfm_opl2board_drv; #ifdef EMU_DEVICE_H extern const device_t ym3812_nuked_device; @@ -58,6 +60,8 @@ extern const device_t ymf289b_ymfm_device; extern const device_t ymf278b_ymfm_device; extern const device_t esfm_esfmu_device; + +extern const device_t ym_opl2board_device; #endif #endif /*SOUND_OPL_H*/ diff --git a/src/include/86box/sound.h b/src/include/86box/sound.h index 9895e73d7..428f12932 100644 --- a/src/include/86box/sound.h +++ b/src/include/86box/sound.h @@ -209,6 +209,9 @@ extern const device_t tndy_device; extern const device_t wss_device; extern const device_t ncr_business_audio_device; +/* External Audio device OPL2Board (Host Connected hardware)*/ +extern const device_t opl2board_device; + #endif #endif /*EMU_SOUND_H*/ diff --git a/src/sound/CMakeLists.txt b/src/sound/CMakeLists.txt index f67630c47..438b558a2 100644 --- a/src/sound/CMakeLists.txt +++ b/src/sound/CMakeLists.txt @@ -13,9 +13,9 @@ # Copyright 2020-2021 David Hrdlička. # -add_library(snd OBJECT sound.c snd_opl.c snd_opl_nuked.c snd_opl_ymfm.cpp snd_resid.cc +add_library(snd OBJECT sound.c snd_opl.c snd_opl_nuked.c snd_opl_ymfm.cpp snd_opl_opl2board.cpp snd_resid.cc midi.c snd_speaker.c snd_pssj.c snd_lpt_dac.c snd_ac97_codec.c snd_ac97_via.c - snd_lpt_dss.c snd_ps1.c snd_adlib.c snd_adlibgold.c snd_ad1848.c snd_audiopci.c + snd_lpt_dss.c snd_ps1.c snd_adlib.c snd_adlibgold.c snd_opl2board.c snd_ad1848.c snd_audiopci.c snd_azt2316a.c snd_cms.c snd_cmi8x38.c snd_cs423x.c snd_gus.c snd_sb.c snd_sb_dsp.c snd_emu8k.c snd_mpu401.c snd_pas16.c snd_sn76489.c snd_ssi2001.c snd_wss.c snd_ym7128.c snd_optimc.c esfmu/esfm.c esfmu/esfm_registers.c snd_opl_esfm.c) @@ -125,5 +125,12 @@ if(OPL4ML) target_sources(snd PRIVATE midi_opl4.c midi_opl4_yrw801.c) endif() + find_package(PkgConfig REQUIRED) + pkg_check_modules(SERIALPORT REQUIRED libserialport) + include_directories(${SERIALPORT_INCLUDE}) + target_link_libraries(86Box ${SERIALPORT_LIBRARIES}) + + + add_subdirectory(resid-fp) target_link_libraries(86Box resid-fp) diff --git a/src/sound/snd_opl.c b/src/sound/snd_opl.c index d98b3ccc2..9f7e4c459 100644 --- a/src/sound/snd_opl.c +++ b/src/sound/snd_opl.c @@ -59,6 +59,13 @@ fm_driver_get(int chip_id, fm_drv_t *drv) } break; + case FM_OPL2BOARD: + + *drv = ymfm_opl2board_drv; + drv->priv = device_add_inst(&ym_opl2board_device, fm_dev_inst[fm_driver][chip_id]++); + + break; + case FM_YMF289B: *drv = ymfm_drv; drv->priv = device_add_inst(&ymf289b_ymfm_device, fm_dev_inst[fm_driver][chip_id]++); diff --git a/src/sound/snd_opl2board.c b/src/sound/snd_opl2board.c new file mode 100644 index 000000000..1ad147e8c --- /dev/null +++ b/src/sound/snd_opl2board.c @@ -0,0 +1,183 @@ +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H + +#include <86box/86box.h> +#include <86box/device.h> +#include <86box/io.h> +#include <86box/mca.h> +#include <86box/sound.h> +#include <86box/timer.h> +#include <86box/snd_opl.h> +#include <86box/plat_unused.h> + + +#ifdef ENABLE_OPL2DEVICE_LOG +int opl2board_device_do_log = ENABLE_OPL2DEVICE_LOG; + +static void +opl2board_device_log(const char *fmt, ...) +{ + va_list ap; + + if (opl2board_device_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define opl2board_device_log(fmt, ...) +#endif + +typedef struct opl2board_device_t { + fm_drv_t opl; + + uint8_t pos_regs[8]; + + +} opl2board_device_t; + + + + +static void +opl2board_device_get_buffer(int32_t *buffer, int len, void *priv) +{ + opl2board_device_t *serial = (opl2board_device_t *) priv; + + const int32_t *opl_buf = serial->opl.update(serial->opl.priv); + + for (int c = 0; c < len * 2; c++) + buffer[c] += opl_buf[c]; + + serial->opl.reset_buffer(serial->opl.priv); +} + +uint8_t +opl2board_device_mca_read(int port, void *priv) +{ + const opl2board_device_t *serial = (opl2board_device_t *) priv; + + opl2board_device_log("opl2board_device_mca_read: port=%04x\n", port); + + return serial->pos_regs[port & 7]; +} + +void +opl2board_device_mca_write(int port, uint8_t val, void *priv) +{ + opl2board_device_t *serial = (opl2board_device_t *) priv; + + if (port < 0x102) + return; + + opl2board_device_log("opl2board_device_mca_write: port=%04x val=%02x\n", port, val); + + switch (port) { + case 0x102: + if ((serial->pos_regs[2] & 1) && !(val & 1)) + io_removehandler(0x0388, 0x0002, + serial->opl.read, NULL, NULL, + serial->opl.write, NULL, NULL, + serial->opl.priv); + if (!(serial->pos_regs[2] & 1) && (val & 1)) + io_sethandler(0x0388, 0x0002, + serial->opl.read, NULL, NULL, + serial->opl.write, NULL, NULL, + serial->opl.priv); + break; + + default: + break; + } + serial->pos_regs[port & 7] = val; +} + +uint8_t +opl2board_device_mca_feedb(void *priv) +{ + const opl2board_device_t *serial = (opl2board_device_t *) priv; + + return (serial->pos_regs[2] & 1); +} + +void * +opl2board_device_init(UNUSED(const device_t *info)) +{ + opl2board_device_t *serial = malloc(sizeof(opl2board_device_t)); + memset(serial, 0, sizeof(opl2board_device_t)); + + + opl2board_device_log("opl2board_device_init\n"); + fm_driver_get(FM_OPL2BOARD, &serial->opl); + io_sethandler(0x0388, 0x0002, + serial->opl.read, NULL, NULL, + serial->opl.write, NULL, NULL, + serial->opl.priv); + music_add_handler(opl2board_device_get_buffer, serial); + + + return serial; + +} + +void * +opl2board_device_mca_init(const device_t *info) +{ + opl2board_device_t *serial = opl2board_device_init(info); + + io_removehandler(0x0388, 0x0002, + serial->opl.read, NULL, NULL, + serial->opl.write, NULL, NULL, + serial->opl.priv); + mca_add(opl2board_device_mca_read, + opl2board_device_mca_write, + opl2board_device_mca_feedb, + NULL, + serial); + serial->pos_regs[0] = 0xd7; + serial->pos_regs[1] = 0x70; + + return serial; +} + +void +opl2board_device_close(void *priv) +{ + opl2board_device_t *serial = (opl2board_device_t *) priv; + free(serial); +} + + +static const device_config_t opl2board_config[] = { + + { + .name = "host_serial_path", + .description = "Host Serial Device", + .type = CONFIG_SERPORT, + .default_string = "", + .file_filter = NULL, + .spinner = {}, + .selection = {} + }, + { .name = "", .description = "", .type = CONFIG_END } + + }; +const device_t opl2board_device = { + .name = "OPL2Board (External Device)", + .internal_name = "opl2board_device", + .flags = DEVICE_ISA, + .local = 0, + .init = opl2board_device_init, + .close = opl2board_device_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = opl2board_config +}; diff --git a/src/sound/snd_opl_opl2board.cpp b/src/sound/snd_opl_opl2board.cpp new file mode 100644 index 000000000..91649f372 --- /dev/null +++ b/src/sound/snd_opl_opl2board.cpp @@ -0,0 +1,550 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Interface to the YMFM External audio device (USB) + * For OPL2Board arduino based. + * + * Authors: Jose Phillips, + * Adrien Moulin, + * + * Copyright 2024 Jose Phillips. + * Copyright 2022 Adrien Moulin. + */ +#include +#include +#include +#include +#include +#include "ymfm/ymfm_opl.h" +#include + + +extern "C" { +#define HAVE_STDARG_H +#include <86box/86box.h> +#include <86box/timer.h> +#include <86box/device.h> +#include <86box/sound.h> +#include <86box/snd_opl.h> +#include <86box/mem.h> +#include <86box/rom.h> +#include <86box/plat_unused.h> +#include <86box/config.h> +#include <86box/ini.h> +#include <86box/device.h> + + +// Disable c99-designator to avoid the warnings in *_ymfm_device +#ifdef __clang__ +# if __has_warning("-Wc99-designator") +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wc99-designator" +# endif +#endif + +} + + +#define RSM_FRAC 10 + +#define OPL_FREQ FREQ_48000 + +enum { + FLAG_CYCLES = (1 << 0) +}; + +uint8_t lastval = 0x00; + + +class OPLBOARDChipBase { +public: + OPLBOARDChipBase(UNUSED(uint32_t clock), fm_type type, uint32_t samplerate) + : m_buf_pos(0) + , m_flags(0) + , m_type(type) + , m_samplerate(samplerate) + { + memset(m_buffer, 0, sizeof(m_buffer)); + } + + virtual ~OPLBOARDChipBase() + { + } + + fm_type type() const { return m_type; } + int8_t flags() const { return m_flags; } + void set_do_cycles(int8_t do_cycles) { do_cycles ? m_flags |= FLAG_CYCLES : m_flags &= ~FLAG_CYCLES; } + int32_t *buffer() const { return (int32_t *) m_buffer; } + void reset_buffer() { m_buf_pos = 0; } + + virtual uint32_t sample_rate() const = 0; + + virtual void write(uint16_t addr, uint8_t data) = 0; + virtual void generate(int32_t *data, uint32_t num_samples) = 0; + virtual int32_t *update() = 0; + virtual uint8_t read(uint16_t addr) = 0; + virtual void set_clock(uint32_t clock) = 0; + + +protected: + int32_t m_buffer[MUSICBUFLEN * 2]; + int m_buf_pos; + int *m_buf_pos_global; + int8_t m_flags; + fm_type m_type; + uint32_t m_samplerate; +}; + +template +class OPLBOARDChip : public OPLBOARDChipBase, public ymfm::ymfm_interface { +public: + OPLBOARDChip(uint32_t clock, fm_type type, uint32_t samplerate) + : OPLBOARDChipBase(clock, type, samplerate) + , m_chip(*this) + , m_clock(clock) + , m_samplerate(samplerate) + , m_samplecnt(0) + { + memset(m_samples, 0, sizeof(m_samples)); + memset(m_oldsamples, 0, sizeof(m_oldsamples)); + m_rateratio = (samplerate << RSM_FRAC) / m_chip.sample_rate(m_clock); + m_clock_us = 1000000.0 / (double) m_clock; + m_subtract[0] = 80.0; + m_subtract[1] = 320.0; + m_type = type; + m_buf_pos_global = (samplerate == FREQ_49716) ? &music_pos_global : &wavetable_pos_global; + + if (m_type == FM_YMF278B) { + if (rom_load_linear("roms/sound/yamaha/yrw801.rom", 0, 0x200000, 0, m_yrw801) == 0) { + fatal("YRW801 ROM image \"roms/sound/yamaha/yrw801.rom\" not found\n"); + } + } + + timer_add(&m_timers[0], OPLBOARDChip::timer1, this, 0); + timer_add(&m_timers[1], OPLBOARDChip::timer2, this, 0); + } + + virtual uint32_t sample_rate() const override + { + return m_chip.sample_rate(m_clock); + } + + virtual void ymfm_set_timer(uint32_t tnum, int32_t duration_in_clocks) override + { + if (tnum > 1) + return; + + m_duration_in_clocks[tnum] = duration_in_clocks; + pc_timer_t *timer = &m_timers[tnum]; + if (duration_in_clocks < 0) + timer_stop(timer); + else { + double period = m_clock_us * duration_in_clocks; + if (period < m_subtract[tnum]) + m_engine->engine_timer_expired(tnum); + else + timer_on_auto(timer, period); + } + } + + virtual void set_clock(uint32_t clock) override + { + m_clock = clock; + m_clock_us = 1000000.0 / (double) m_clock; + m_rateratio = (m_samplerate << RSM_FRAC) / m_chip.sample_rate(m_clock); + + ymfm_set_timer(0, m_duration_in_clocks[0]); + ymfm_set_timer(1, m_duration_in_clocks[1]); + } + + virtual void generate(int32_t *data, uint32_t num_samples) override + { + for (uint32_t i = 0; i < num_samples; i++) { + m_chip.generate(&m_output); + if ((m_type == FM_YMF278B) && (sizeof(m_output.data) > (4 * sizeof(int32_t)))) { + if (ChipType::OUTPUTS == 1) { + *data++ = m_output.data[4]; + *data++ = m_output.data[4]; + } else { + *data++ = m_output.data[4]; + *data++ = m_output.data[5]; + } + } else if (ChipType::OUTPUTS == 1) { + *data++ = m_output.data[0]; + *data++ = m_output.data[0]; + } else { + *data++ = m_output.data[0]; + *data++ = m_output.data[1 % ChipType::OUTPUTS]; + } + } + } + +#if 0 + virtual void generate_resampled(int32_t *data, uint32_t num_samples) override + { + if ((m_samplerate == FREQ_49716) || (m_samplerate == FREQ_44100)) { + generate(data, num_samples); + return; + } + + for (uint32_t i = 0; i < num_samples; i++) { + while (m_samplecnt >= m_rateratio) { + m_oldsamples[0] = m_samples[0]; + m_oldsamples[1] = m_samples[1]; + m_chip.generate(&m_output); + if ((m_type == FM_YMF278B) && (sizeof(m_output.data) > (4 * sizeof(int32_t)))) { + if (ChipType::OUTPUTS == 1) { + m_samples[0] = m_output.data[4]; + m_samples[1] = m_output.data[4]; + } else { + m_samples[0] = m_output.data[4]; + m_samples[1] = m_output.data[5]; + } + } else if (ChipType::OUTPUTS == 1) { + m_samples[0] = m_output.data[0]; + m_samples[1] = m_output.data[0]; + } else { + m_samples[0] = m_output.data[0]; + m_samples[1] = m_output.data[1 % ChipType::OUTPUTS]; + } + m_samplecnt -= m_rateratio; + } + + *data++ = ((int32_t) ((m_oldsamples[0] * (m_rateratio - m_samplecnt) + + m_samples[0] * m_samplecnt) + / m_rateratio)); + *data++ = ((int32_t) ((m_oldsamples[1] * (m_rateratio - m_samplecnt) + + m_samples[1] * m_samplecnt) + / m_rateratio)); + + m_samplecnt += 1 << RSM_FRAC; + } + } +#endif + + virtual int32_t *update() override + { + if (m_buf_pos >= *m_buf_pos_global) + return m_buffer; + + generate(&m_buffer[m_buf_pos * 2], *m_buf_pos_global - m_buf_pos); + + for (; m_buf_pos < *m_buf_pos_global; m_buf_pos++) { + m_buffer[m_buf_pos * 2] /= 2; + m_buffer[(m_buf_pos * 2) + 1] /= 2; + } + + return m_buffer; + } + + virtual void write(uint16_t addr, uint8_t data) override + { + + m_chip.write(addr, data); + } + + virtual uint8_t read(uint16_t addr) override + { + return m_chip.read(addr); + } + + virtual uint32_t get_special_flags(void) override + { + return ((m_type == FM_YMF262) || (m_type == FM_YMF289B) || (m_type == FM_YMF278B)) ? 0x8000 : 0x0000; + } + + static void timer1(void *priv) + { + OPLBOARDChip *drv = (OPLBOARDChip *) priv; + drv->m_engine->engine_timer_expired(0); + } + + static void timer2(void *priv) + { + OPLBOARDChip *drv = (OPLBOARDChip *) priv; + drv->m_engine->engine_timer_expired(1); + } + + virtual uint8_t ymfm_external_read(ymfm::access_class type, uint32_t address) override + { + if (type == ymfm::access_class::ACCESS_PCM && address < 0x200000) { + return m_yrw801[address]; + } + return 0xFF; + } + +private: + ChipType m_chip; + uint32_t m_clock; + double m_clock_us; + double m_subtract[2]; + typename ChipType::output_data m_output; + pc_timer_t m_timers[2]; + int32_t m_duration_in_clocks[2]; // Needed for clock switches. + uint32_t m_samplerate; + + // YRW801-M wavetable ROM. + uint8_t m_yrw801[0x200000]; + + // Resampling + int32_t m_rateratio; + int32_t m_samplecnt; + int32_t m_oldsamples[2]; + int32_t m_samples[2]; +}; + +extern "C" { +#include +#include +#include +#include +#include +#include +#define HAVE_STDARG_H + +#include "cpu.h" +#include <86box/86box.h> +#include <86box/io.h> +#include <86box/snd_opl.h> +#include <86box/device.h> +#include <86box/config.h> +#include <86box/ini.h> + + +#ifdef ENABLE_OPL_LOG +int ymfm_do_log = ENABLE_OPL_LOG; + +static void +ymfm_log(const char *fmt, ...) +{ + va_list ap; + + if (ymfm_do_log) { + va_start(ap, fmt); + pclog_ex(fmt, ap); + va_end(ap); + } +} +#else +# define ymfm_log(fmt, ...) +#endif + +struct sp_port *port; + + + +void opl2board_init() { + + device_add(&opl2board_device); + const char* port_name = device_get_config_string("host_serial_path"); + device_context_restore(); + + enum sp_return result; + + result = sp_get_port_by_name(port_name, &port); + if (result != SP_OK) { + ymfm_log("Error: Cannot find port %s\n", port_name); + return; + } + + result = sp_open(port, SP_MODE_READ_WRITE); + if (result != SP_OK) { + ymfm_log ("Error: Cannot open port %s\n", port_name); + return; + } + + // Set port configuration this values are hardcoded. + sp_set_baudrate(port, 115200); + sp_set_bits(port, 8); + sp_set_parity(port, SP_PARITY_NONE); + sp_set_stopbits(port, 1); + sp_set_flowcontrol(port, SP_FLOWCONTROL_NONE); + + + ymfm_log("OPL2Board Serial port %s initialized at 115200 baud.\n", port_name); + +} + + +void opl2board_write(uint8_t data) { + if (port == NULL) { + ymfm_log(stderr, "Error: OPL2Board Port not initialized.\n"); + + return; + } + + enum sp_return result = sp_blocking_write(port, &data, sizeof(data), 1000); + if (result < 0) { + ymfm_log(stderr, "Error: Failed to write to OPL2Board port.\n"); + } else { + ymfm_log("OPL2Board: data sent: %02X\n", data); + } +} + + +void opl2board_reset() { + + // Reset all voices to 0 + ymfm_log("Performing OPL2Board reset\n"); + for (uint8_t i = 0x00; i < 0xFF; i++) { + if (i >= 0x40 && i <= 0x55) { + opl2board_write(i); + opl2board_write(0x3F); + } else { + opl2board_write (i); + opl2board_write(0x00); + } } +} + +void opl2board_close() { + + if (port != NULL) { + opl2board_reset(); + sp_close(port); + sp_free_port(port); + port = NULL; + ymfm_log("OPL2Board port closed.\n"); + } +} + + +static void * +ymfm_opl2board_drv_init(const device_t *info) +{ + OPLBOARDChipBase *fm; + + switch (info->local) { + default: + case FM_OPL2BOARD: + fm = (OPLBOARDChipBase *) new OPLBOARDChip(3579545, FM_OPL2BOARD, FREQ_49716); + break; + } + fm->set_do_cycles(1); + + return fm; +} + +static void +ymfm_opl2board_drv_close(void *priv) +{ + OPLBOARDChipBase *drv = (OPLBOARDChipBase *) priv; + opl2board_close(); + if (drv != NULL) + delete drv; +} + +static uint8_t +ymfm_opl2board_drv_read(uint16_t port, void *priv) +{ + OPLBOARDChipBase *drv = (OPLBOARDChipBase *) priv; + + if ((port == 0x380) || (port == 0x381)) + port |= 4; + + /* Point to register read port. */ + if (drv->flags() & FLAG_CYCLES) + cycles -= ((int) (isa_timing * 8)); + + uint8_t ret = drv->read(port); + drv->update(); + + ymfm_log("YMFM read port %04x, status = %02x\n", port, ret); + return ret; +} + +static void +ymfm_opl2board_drv_write(uint16_t port, uint8_t val, void *priv) +{ + + OPLBOARDChipBase *drv = (OPLBOARDChipBase *) priv; + + ymfm_log("YMFM write port %04x value = %02x\n", port, val); + if ((port == 0x380) || (port == 0x381)) + port |= 4; + // Allow initialization of adlib + if ((val == 0x04 || val == 0x02) || (lastval == 0x04 || lastval == 0x02)) { + drv->write(port, val); + } + lastval = val; + opl2board_write(val); + drv->update(); +} + + +static int32_t * +ymfm_opl2board_drv_update(void *priv) +{ + if (port == NULL) { + opl2board_init(); + opl2board_reset(); + } + OPLBOARDChipBase *drv = (OPLBOARDChipBase *) priv; + + return drv->update(); +} + +static void +ymfm_opl2board_drv_reset_buffer(void *priv) +{ + OPLBOARDChipBase *drv = (OPLBOARDChipBase *) priv; + + drv->reset_buffer(); +} + +static void +ymfm_opl2board_drv_set_do_cycles(void *priv, int8_t do_cycles) +{ + OPLBOARDChipBase *drv = (OPLBOARDChipBase *) priv; + drv->set_do_cycles(do_cycles); +} + +static void +ymfm_opl2board_drv_generate(void *priv, int32_t *data, uint32_t num_samples) +{ + + OPLBOARDChipBase *drv = (OPLBOARDChipBase *) priv; + // drv->generate_resampled(data, num_samples); + drv->generate(data, num_samples); + +} + + + + +const device_t ym_opl2board_device = { + .name = "YMOPL2Board (External Device)", + .internal_name = "ym_opl2board_device", + .flags = 0, + .local = FM_OPL2BOARD, + .init = ymfm_opl2board_drv_init, + .close = ymfm_opl2board_drv_close, + .reset = NULL, + { .available = NULL }, + .speed_changed = NULL, + .force_redraw = NULL, + .config = NULL +}; + +const fm_drv_t ymfm_opl2board_drv { + &ymfm_opl2board_drv_read, + &ymfm_opl2board_drv_write, + &ymfm_opl2board_drv_update, + &ymfm_opl2board_drv_reset_buffer, + &ymfm_opl2board_drv_set_do_cycles, + NULL, + ymfm_opl2board_drv_generate + +}; + +#ifdef __clang__ +# if __has_warning("-Wc99-designator") +# pragma clang diagnostic pop +# endif +#endif + +} diff --git a/src/sound/sound.c b/src/sound/sound.c index f941c8817..0571bc203 100644 --- a/src/sound/sound.c +++ b/src/sound/sound.c @@ -181,6 +181,7 @@ static const SOUND_CARD sound_cards[] = { { &ess_1688_device }, { &ess_ess0102_pnp_device }, { &ess_ess0968_pnp_device }, + { &opl2board_device }, { NULL } // clang-format on }; From a651cd113b0deb08cda3fac57bc2bd7a8a19a704 Mon Sep 17 00:00:00 2001 From: Jose Phillips Date: Sun, 1 Dec 2024 18:12:57 -0500 Subject: [PATCH 02/24] Some code clean --- src/sound/CMakeLists.txt | 4 ---- src/sound/snd_opl.c | 5 +---- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/src/sound/CMakeLists.txt b/src/sound/CMakeLists.txt index 438b558a2..98788b6b8 100644 --- a/src/sound/CMakeLists.txt +++ b/src/sound/CMakeLists.txt @@ -124,13 +124,9 @@ if(OPL4ML) target_compile_definitions(snd PRIVATE USE_OPL4ML) target_sources(snd PRIVATE midi_opl4.c midi_opl4_yrw801.c) endif() - find_package(PkgConfig REQUIRED) pkg_check_modules(SERIALPORT REQUIRED libserialport) include_directories(${SERIALPORT_INCLUDE}) target_link_libraries(86Box ${SERIALPORT_LIBRARIES}) - - - add_subdirectory(resid-fp) target_link_libraries(86Box resid-fp) diff --git a/src/sound/snd_opl.c b/src/sound/snd_opl.c index 9f7e4c459..931277332 100644 --- a/src/sound/snd_opl.c +++ b/src/sound/snd_opl.c @@ -60,12 +60,9 @@ fm_driver_get(int chip_id, fm_drv_t *drv) break; case FM_OPL2BOARD: - *drv = ymfm_opl2board_drv; - drv->priv = device_add_inst(&ym_opl2board_device, fm_dev_inst[fm_driver][chip_id]++); - + drv->priv = device_add_inst(&ym_opl2board_device, fm_dev_inst[fm_driver][chip_id]++); break; - case FM_YMF289B: *drv = ymfm_drv; drv->priv = device_add_inst(&ymf289b_ymfm_device, fm_dev_inst[fm_driver][chip_id]++); From 984a71ccfb90c64fc6879876639f984c3fd64a25 Mon Sep 17 00:00:00 2001 From: Jose Phillips Date: Sun, 1 Dec 2024 19:04:55 -0500 Subject: [PATCH 03/24] Added dependencies on CI --- .ci/dependencies_macports.txt | 1 + .ci/dependencies_msys.txt | 1 + src/sound/CMakeLists.txt | 1 + src/sound/snd_opl2board.c | 20 ++++++++++++++++++++ 4 files changed, 23 insertions(+) diff --git a/.ci/dependencies_macports.txt b/.ci/dependencies_macports.txt index b23ac441d..e530871ae 100644 --- a/.ci/dependencies_macports.txt +++ b/.ci/dependencies_macports.txt @@ -16,3 +16,4 @@ ghostscript libslirp vde2 libsndfile +libserialport diff --git a/.ci/dependencies_msys.txt b/.ci/dependencies_msys.txt index eacdb8b36..1d4692d3f 100644 --- a/.ci/dependencies_msys.txt +++ b/.ci/dependencies_msys.txt @@ -14,3 +14,4 @@ qt5-static qt5-translations vulkan-headers libsndfile +ibserialport \ No newline at end of file diff --git a/src/sound/CMakeLists.txt b/src/sound/CMakeLists.txt index b77ad423a..e25c39391 100644 --- a/src/sound/CMakeLists.txt +++ b/src/sound/CMakeLists.txt @@ -32,6 +32,7 @@ add_library(snd OBJECT snd_adlib.c snd_adlibgold.c snd_opl2board.c + snd_opl_opl2board.cpp snd_ad1848.c snd_audiopci.c snd_azt2316a.c diff --git a/src/sound/snd_opl2board.c b/src/sound/snd_opl2board.c index 1ad147e8c..57fafbae7 100644 --- a/src/sound/snd_opl2board.c +++ b/src/sound/snd_opl2board.c @@ -1,3 +1,23 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Interface to the OPL2Board External audio device (USB) + * + * + * Authors: Jose Phillips + * Fred N. van Kempen, + * Miran Grca, + * + * Copyright 2024 Jose Phillips. + * Copyright 2017-2020 Fred N. van Kempen. + * Copyright 2016-2020 Miran Grca. + */ + #include #include #include From a71dafcae3234e36b57e7c71479404510483ce9c Mon Sep 17 00:00:00 2001 From: Jose Phillips Date: Sun, 1 Dec 2024 19:15:22 -0500 Subject: [PATCH 04/24] More CI tests --- .ci/dependencies_msys.txt | 2 +- debian/control | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.ci/dependencies_msys.txt b/.ci/dependencies_msys.txt index 1d4692d3f..766aadda3 100644 --- a/.ci/dependencies_msys.txt +++ b/.ci/dependencies_msys.txt @@ -14,4 +14,4 @@ qt5-static qt5-translations vulkan-headers libsndfile -ibserialport \ No newline at end of file +libserialport \ No newline at end of file diff --git a/debian/control b/debian/control index a718aee33..a11e2af48 100644 --- a/debian/control +++ b/debian/control @@ -16,7 +16,8 @@ Build-Depends: cmake (>= 3.21), libsndfile-dev, ninja-build, qttools5-dev, - qtbase5-private-dev + qtbase5-private-dev, + libserialport-dev Standards-Version: 4.6.0 Homepage: https://86box.net/ #Vcs-Browser: https://salsa.debian.org/debian/86box From 2b6538460b084bae4f76a348c147bba07c7361b3 Mon Sep 17 00:00:00 2001 From: Jose Phillips Date: Sun, 1 Dec 2024 19:23:08 -0500 Subject: [PATCH 05/24] More CI additions --- .github/workflows/cmake_linux.yml | 1 + .github/workflows/cmake_macos.yml | 1 + .github/workflows/cmake_windows_msys2.yml | 1 + 3 files changed, 3 insertions(+) diff --git a/.github/workflows/cmake_linux.yml b/.github/workflows/cmake_linux.yml index a8945172b..b2ec5321a 100644 --- a/.github/workflows/cmake_linux.yml +++ b/.github/workflows/cmake_linux.yml @@ -82,6 +82,7 @@ jobs: libslirp-dev libfluidsynth-dev libvdeplug-dev + libserialport-dev ${{ matrix.ui.packages }} - name: Checkout repository diff --git a/.github/workflows/cmake_macos.yml b/.github/workflows/cmake_macos.yml index d02ec595b..2e35c13de 100644 --- a/.github/workflows/cmake_macos.yml +++ b/.github/workflows/cmake_macos.yml @@ -82,6 +82,7 @@ jobs: fluidsynth libslirp vde + libserialport ${{ matrix.ui.packages }} - name: Checkout repository diff --git a/.github/workflows/cmake_windows_msys2.yml b/.github/workflows/cmake_windows_msys2.yml index 7620351b3..e55e1c1f7 100644 --- a/.github/workflows/cmake_windows_msys2.yml +++ b/.github/workflows/cmake_windows_msys2.yml @@ -97,6 +97,7 @@ jobs: rtmidi:p libslirp:p fluidsynth:p + libserialport:p ${{ matrix.ui.packages }} - name: Checkout repository From 7f8a34990c761c4336cc218fde61c9a13cbe5354 Mon Sep 17 00:00:00 2001 From: Jose Phillips Date: Sun, 1 Dec 2024 19:33:10 -0500 Subject: [PATCH 06/24] added dependencies to codeql --- .github/workflows/codeql_linux.yml | 1 + .github/workflows/codeql_macos.yml | 1 + .github/workflows/codeql_windows_msys2.yml | 1 + 3 files changed, 3 insertions(+) diff --git a/.github/workflows/codeql_linux.yml b/.github/workflows/codeql_linux.yml index 412a2045c..fc0397703 100644 --- a/.github/workflows/codeql_linux.yml +++ b/.github/workflows/codeql_linux.yml @@ -85,6 +85,7 @@ jobs: libslirp-dev libfluidsynth-dev libvdeplug-dev + libserialport-dev ${{ matrix.ui.packages }} - name: Checkout repository diff --git a/.github/workflows/codeql_macos.yml b/.github/workflows/codeql_macos.yml index 5ce12548b..234e04f55 100644 --- a/.github/workflows/codeql_macos.yml +++ b/.github/workflows/codeql_macos.yml @@ -76,6 +76,7 @@ jobs: fluidsynth libslirp vde + libserialport ${{ matrix.ui.packages }} - name: Checkout repository diff --git a/.github/workflows/codeql_windows_msys2.yml b/.github/workflows/codeql_windows_msys2.yml index 67de8ec8b..7a0055910 100644 --- a/.github/workflows/codeql_windows_msys2.yml +++ b/.github/workflows/codeql_windows_msys2.yml @@ -102,6 +102,7 @@ jobs: rtmidi:p libslirp:p fluidsynth:p + libserialport:p ${{ matrix.ui.packages }} - name: Checkout repository From 04db328bf32948ca05fa24d2a57ca3e9ff6e833f Mon Sep 17 00:00:00 2001 From: Jose Phillips Date: Sun, 1 Dec 2024 20:33:51 -0500 Subject: [PATCH 07/24] Added library on CMAKE --- .github/workflows/cmake_macos.yml | 3 +++ .github/workflows/codeql_macos.yml | 1 + CMakePresets.json | 4 +++- src/sound/sound.c | 5 ----- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/workflows/cmake_macos.yml b/.github/workflows/cmake_macos.yml index 2e35c13de..18aafd544 100644 --- a/.github/workflows/cmake_macos.yml +++ b/.github/workflows/cmake_macos.yml @@ -103,6 +103,7 @@ jobs: -D Qt5_ROOT=$(brew --prefix qt@5) -D Qt5LinguistTools_ROOT=$(brew --prefix qt@5) -D OpenAL_ROOT=$(brew --prefix openal-soft) + -D LIBSERIALPORT_ROOT=$(brew --prefix libserialport) - name: Build run: | @@ -182,6 +183,7 @@ jobs: openal-soft fluidsynth libslirp + libserialport ${{ matrix.ui.packages }} - name: Checkout repository @@ -202,6 +204,7 @@ jobs: -D Qt5_ROOT=$(brew --prefix qt@5) -D Qt5LinguistTools_ROOT=$(brew --prefix qt@5) -D OpenAL_ROOT=$(brew --prefix openal-soft) + -D LIBSERIALPORT_ROOT=$(brew --prefix libserialport) - name: Build run: | diff --git a/.github/workflows/codeql_macos.yml b/.github/workflows/codeql_macos.yml index 234e04f55..841ca98f5 100644 --- a/.github/workflows/codeql_macos.yml +++ b/.github/workflows/codeql_macos.yml @@ -98,6 +98,7 @@ jobs: -D Qt5_ROOT=$(brew --prefix qt@5) -D Qt5LinguistTools_ROOT=$(brew --prefix qt@5) -D OpenAL_ROOT=$(brew --prefix openal-soft) + -D LIBSERIALPORT_ROOT=$(brew --prefix libserialport) - name: Build run: cmake --build build diff --git a/CMakePresets.json b/CMakePresets.json index c19a7abc0..d4af8e6cb 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -68,7 +68,8 @@ "Qt5_DIR": "/opt/homebrew/opt/qt@5/lib/cmake/Qt5", "MOLTENVK_DIR": "/opt/homebrew/opt/molten-vk", "Qt5LinguistTools_DIR": "/opt/homebrew/opt/qt@5/lib/cmake/Qt5LinguistTools", - "OpenAL_ROOT": "/opt/homebrew/opt/openal-soft" + "OpenAL_ROOT": "/opt/homebrew/opt/openal-soft", + "LIBSERIALPORT_ROOT": "/opt/homebrew/opt/libserialport" }, "inherits": "regular" }, @@ -86,6 +87,7 @@ "MOLTENVK_DIR": "/opt/homebrew/opt/molten-vk", "Qt5LinguistTools_DIR": "/opt/homebrew/opt/qt@5/lib/cmake/Qt5LinguistTools", "OpenAL_ROOT": "/opt/homebrew/opt/openal-soft", + "LIBSERIALPORT_ROOT": "/opt/homebrew/opt/libserialport", "CMAKE_CXX_FLAGS_DEBUG": "-g -O0 -DENABLE_VDE_LOG", "CMAKE_C_FLAGS_DEBUG": "-g -O0 -DENABLE_VDE_LOG" }, diff --git a/src/sound/sound.c b/src/sound/sound.c index 54d0d857f..851c849e4 100644 --- a/src/sound/sound.c +++ b/src/sound/sound.c @@ -153,11 +153,6 @@ static const SOUND_CARD sound_cards[] = { { &ct5880_device }, { &ad1881_device }, { &cs4297a_device }, - { &ess_688_device }, - { &ess_ess0100_pnp_device }, - { &ess_1688_device }, - { &ess_ess0102_pnp_device }, - { &ess_ess0968_pnp_device }, { &opl2board_device }, { NULL } // clang-format on From 875bfc6fb7851046e987c6bc60edf98251210b5e Mon Sep 17 00:00:00 2001 From: Jose Phillips Date: Sun, 1 Dec 2024 21:03:43 -0500 Subject: [PATCH 08/24] More fixes on Cmakelists --- src/sound/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sound/CMakeLists.txt b/src/sound/CMakeLists.txt index e25c39391..644deb5c3 100644 --- a/src/sound/CMakeLists.txt +++ b/src/sound/CMakeLists.txt @@ -173,7 +173,7 @@ if(OPL4ML) target_sources(snd PRIVATE midi_opl4.c midi_opl4_yrw801.c) endif() find_package(PkgConfig REQUIRED) - pkg_check_modules(SERIALPORT REQUIRED libserialport) + pkg_check_modules(LIBSERIALPORT REQUIRED libserialport) include_directories(${SERIALPORT_INCLUDE}) target_link_libraries(86Box ${SERIALPORT_LIBRARIES}) add_subdirectory(resid-fp) From 9003217840d7146e9343bc26c5725ec1ea2f1e76 Mon Sep 17 00:00:00 2001 From: Jose Phillips Date: Sun, 1 Dec 2024 21:44:51 -0500 Subject: [PATCH 09/24] fix apple --- src/sound/CMakeLists.txt | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/sound/CMakeLists.txt b/src/sound/CMakeLists.txt index 644deb5c3..386e8a2dc 100644 --- a/src/sound/CMakeLists.txt +++ b/src/sound/CMakeLists.txt @@ -172,9 +172,13 @@ if(OPL4ML) target_compile_definitions(snd PRIVATE USE_OPL4ML) target_sources(snd PRIVATE midi_opl4.c midi_opl4_yrw801.c) endif() - find_package(PkgConfig REQUIRED) - pkg_check_modules(LIBSERIALPORT REQUIRED libserialport) - include_directories(${SERIALPORT_INCLUDE}) - target_link_libraries(86Box ${SERIALPORT_LIBRARIES}) + +find_package(PkgConfig REQUIRED) +pkg_check_modules(SERIALPORT REQUIRED libserialport) +if(APPLE) + include_directories(${LIBSERIALPORT_ROOT}/include) + target_link_libraries(86Box ${LIBSERIALPORT_ROOT}/lib/libserialport.dylib) +endif() + add_subdirectory(resid-fp) target_link_libraries(86Box resid-fp) From 7f8f49e6e7f0d283ce95142bb3bfce17c131dd23 Mon Sep 17 00:00:00 2001 From: Jose Phillips Date: Sun, 1 Dec 2024 22:32:15 -0500 Subject: [PATCH 10/24] fix for other platforms --- src/sound/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/sound/CMakeLists.txt b/src/sound/CMakeLists.txt index 386e8a2dc..b4a0f3796 100644 --- a/src/sound/CMakeLists.txt +++ b/src/sound/CMakeLists.txt @@ -178,6 +178,9 @@ pkg_check_modules(SERIALPORT REQUIRED libserialport) if(APPLE) include_directories(${LIBSERIALPORT_ROOT}/include) target_link_libraries(86Box ${LIBSERIALPORT_ROOT}/lib/libserialport.dylib) +else() + include_directories(${SERIALPORT_INCLUDE_DIRS}) + target_link_libraries(86Box ${SERIALPORT_LIBRARIES}) endif() add_subdirectory(resid-fp) From 9e77792f7b2b7de989ccc794738428a6b98ff21b Mon Sep 17 00:00:00 2001 From: Jose Phillips Date: Sun, 1 Dec 2024 23:45:53 -0500 Subject: [PATCH 11/24] test windows --- src/sound/CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/sound/CMakeLists.txt b/src/sound/CMakeLists.txt index b4a0f3796..4837d76ac 100644 --- a/src/sound/CMakeLists.txt +++ b/src/sound/CMakeLists.txt @@ -182,6 +182,9 @@ else() include_directories(${SERIALPORT_INCLUDE_DIRS}) target_link_libraries(86Box ${SERIALPORT_LIBRARIES}) endif() - +if (WIN32) + target_compile_options(86Box PUBLIC ${SERIALPORT_CFLAGS_OTHER} --static ) +endif() + add_subdirectory(resid-fp) target_link_libraries(86Box resid-fp) From d3a69df4d31eb17aa5d66e7d380868023aa376c3 Mon Sep 17 00:00:00 2001 From: Jose Phillips Date: Mon, 2 Dec 2024 00:09:43 -0500 Subject: [PATCH 12/24] test windows --- .github/workflows/cmake_windows_msys2.yml | 1 + .github/workflows/codeql_windows_msys2.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/workflows/cmake_windows_msys2.yml b/.github/workflows/cmake_windows_msys2.yml index e55e1c1f7..d5d3e8200 100644 --- a/.github/workflows/cmake_windows_msys2.yml +++ b/.github/workflows/cmake_windows_msys2.yml @@ -116,6 +116,7 @@ jobs: -D CMAKE_INSTALL_PREFIX=./build/artifacts -D QT=${{ matrix.ui.qt }} -D STATIC_BUILD=${{ matrix.ui.static }} + -D CMAKE_EXE_LINKER_FLAGS="$(pkg-config --libs libserialport --static )" - name: Build run: | diff --git a/.github/workflows/codeql_windows_msys2.yml b/.github/workflows/codeql_windows_msys2.yml index 7a0055910..7382f503c 100644 --- a/.github/workflows/codeql_windows_msys2.yml +++ b/.github/workflows/codeql_windows_msys2.yml @@ -122,6 +122,7 @@ jobs: -D CMAKE_INSTALL_PREFIX=./build/artifacts -D QT=${{ matrix.ui.qt }} -D STATIC_BUILD=${{ matrix.ui.static }} + -D CMAKE_EXE_LINKER_FLAGS="$(pkg-config --libs libserialport --static )" - name: Build run: cmake --build build From 267d4b2e022fd97e91aa6fbd131b69e1858ab5b1 Mon Sep 17 00:00:00 2001 From: Jose Phillips Date: Mon, 2 Dec 2024 00:40:06 -0500 Subject: [PATCH 13/24] adding setupAPI --- .github/workflows/cmake_windows_msys2.yml | 1 - .github/workflows/codeql_windows_msys2.yml | 1 - src/sound/CMakeLists.txt | 7 ++++--- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/cmake_windows_msys2.yml b/.github/workflows/cmake_windows_msys2.yml index d5d3e8200..e55e1c1f7 100644 --- a/.github/workflows/cmake_windows_msys2.yml +++ b/.github/workflows/cmake_windows_msys2.yml @@ -116,7 +116,6 @@ jobs: -D CMAKE_INSTALL_PREFIX=./build/artifacts -D QT=${{ matrix.ui.qt }} -D STATIC_BUILD=${{ matrix.ui.static }} - -D CMAKE_EXE_LINKER_FLAGS="$(pkg-config --libs libserialport --static )" - name: Build run: | diff --git a/.github/workflows/codeql_windows_msys2.yml b/.github/workflows/codeql_windows_msys2.yml index 7382f503c..7a0055910 100644 --- a/.github/workflows/codeql_windows_msys2.yml +++ b/.github/workflows/codeql_windows_msys2.yml @@ -122,7 +122,6 @@ jobs: -D CMAKE_INSTALL_PREFIX=./build/artifacts -D QT=${{ matrix.ui.qt }} -D STATIC_BUILD=${{ matrix.ui.static }} - -D CMAKE_EXE_LINKER_FLAGS="$(pkg-config --libs libserialport --static )" - name: Build run: cmake --build build diff --git a/src/sound/CMakeLists.txt b/src/sound/CMakeLists.txt index 4837d76ac..315da61e4 100644 --- a/src/sound/CMakeLists.txt +++ b/src/sound/CMakeLists.txt @@ -178,13 +178,14 @@ pkg_check_modules(SERIALPORT REQUIRED libserialport) if(APPLE) include_directories(${LIBSERIALPORT_ROOT}/include) target_link_libraries(86Box ${LIBSERIALPORT_ROOT}/lib/libserialport.dylib) +elseif(WIN32) + include_directories(${SERIALPORT_INCLUDE_DIRS}) + target_link_libraries(86Box ${SERIALPORT_LIBRARIES} SetupAPI) else() include_directories(${SERIALPORT_INCLUDE_DIRS}) target_link_libraries(86Box ${SERIALPORT_LIBRARIES}) endif() -if (WIN32) - target_compile_options(86Box PUBLIC ${SERIALPORT_CFLAGS_OTHER} --static ) -endif() + add_subdirectory(resid-fp) target_link_libraries(86Box resid-fp) From 025e3b3088d3fafcc299029f04738bfbceaf24ad Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 7 Dec 2024 01:17:36 +0100 Subject: [PATCH 14/24] ESS AudioDrive: Fix some mixer register and DSP command readouts to match the probing of real cards, also fixes Windows 3.1 ES688 drivers. --- src/sound/snd_sb.c | 90 ++++++++++++++++++++++++------------------ src/sound/snd_sb_dsp.c | 33 +++++++++++++--- 2 files changed, 79 insertions(+), 44 deletions(-) diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index 6536071b0..4028a1ae9 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -1452,9 +1452,6 @@ ess_mixer_write(uint16_t addr, uint8_t val, void *priv) if (!(addr & 1)) { mixer->index = val; mixer->regs[0x01] = val; - if (val == 0x40) { - mixer->ess_id_str_pos = 0; - } } else { if (mixer->index == 0) { /* Reset */ @@ -1473,6 +1470,8 @@ ess_mixer_write(uint16_t addr, uint8_t val, void *priv) mixer->regs[0x3c] = 0x05; mixer->regs[0x3e] = 0x00; + mixer->regs[0x64] = 0x08; + sb_dsp_set_stereo(&ess->dsp, mixer->regs[0x0e] & 2); } else { mixer->regs[mixer->index] = val; @@ -1525,6 +1524,7 @@ ess_mixer_write(uint16_t addr, uint8_t val, void *priv) break; case 0x1C: + mixer->regs[mixer->index] = val & 0x2f; if ((mixer->regs[0x1C] & 0x07) == 0x07) { mixer->input_selector = INPUT_MIXER_L | INPUT_MIXER_R; } else if ((mixer->regs[0x1C] & 0x07) == 0x06) { @@ -1556,12 +1556,12 @@ ess_mixer_write(uint16_t addr, uint8_t val, void *priv) break; case 0x64: - mixer->regs[mixer->index] = (mixer->regs[mixer->index] & 0xf7) | 0x20; - // mixer->regs[mixer->index] &= ~0x8; + if (ess->dsp.sb_subtype > SB_SUBTYPE_ESS_ES1688) + mixer->regs[mixer->index] = (mixer->regs[mixer->index] & 0xf7) | 0x20; break; case 0x40: - { + if (ess->dsp.sb_subtype >= SB_SUBTYPE_ESS_ES1688) { uint16_t mpu401_base_addr = 0x300 | ((mixer->regs[0x40] << 1) & 0x30); sb_log("mpu401_base_addr = %04X\n", mpu401_base_addr); @@ -1572,7 +1572,7 @@ ess_mixer_write(uint16_t addr, uint8_t val, void *priv) gameport_remap(ess->gameport, !(mixer->regs[0x40] & 0x2) ? 0x00 : 0x200); - if (ess->dsp.sb_subtype != SB_SUBTYPE_ESS_ES1688) { + if (ess->dsp.sb_subtype > SB_SUBTYPE_ESS_ES1688) { /* Not on ES1688. */ io_removehandler(0x0388, 0x0004, ess->opl.read, NULL, NULL, @@ -1585,6 +1585,7 @@ ess_mixer_write(uint16_t addr, uint8_t val, void *priv) ess->opl.priv); } } + if (ess->mpu != NULL) switch ((mixer->regs[0x40] >> 5) & 0x7) { default: break; @@ -1627,11 +1628,12 @@ ess_mixer_write(uint16_t addr, uint8_t val, void *priv) ess_fm_midi_read, NULL, NULL, ess_fm_midi_write, NULL, NULL, ess); - break; } + break; default: - sb_log("ess: Unknown mixer register WRITE: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); + sb_log("ess: Unknown mixer register WRITE: %02X\t%02X\n", + mixer->index, mixer->regs[mixer->index]); break; } } @@ -1667,6 +1669,7 @@ ess_mixer_read(uint16_t addr, void *priv) case 0x0c: case 0x0e: case 0x14: + case 0x1a: case 0x02: case 0x06: case 0x30: @@ -1685,28 +1688,56 @@ ess_mixer_read(uint16_t addr, void *priv) ret = mixer->regs[mixer->index] | 0x11; break; - case 0x40: - if (ess->dsp.sb_subtype == SB_SUBTYPE_ESS_ES1688) - ret = mixer->regs[mixer->index]; - else - ret = 0x0a; + /* Bit 1 always set, bits 7-6 always clear on both the real ES688 and ES1688. */ + case 0x1c: + ret = mixer->regs[mixer->index] | 0x10; break; - case 0x48: - ret = mixer->regs[mixer->index]; - break; + /* + Real ES688: Always 0x00; + Real ES1688: Bit 2 always clear. + */ + case 0x40: + if (ess->dsp.sb_subtype > SB_SUBTYPE_ESS_ES1688) + ret = mixer->regs[mixer->index]; + else if (ess->dsp.sb_subtype >= SB_SUBTYPE_ESS_ES1688) + ret = mixer->regs[mixer->index] & 0xfb; + else + ret = 0x00; + break; - /* Return 0x00 so it has bit 3 clear, so NT 5.x drivers don't misdetect it as ES1788. */ + /* + Real ES688: Always 0x00; + Real ES1688: All bits writable. + */ + case 0x48: + if (ess->dsp.sb_subtype >= SB_SUBTYPE_ESS_ES1688) + ret = mixer->regs[mixer->index]; + else + ret = 0x00; + break; + + /* + Return 0x00 so it has bit 3 clear, so NT 5.x drivers don't misdetect it as ES1788. + Bit 3 set and writable: ESSCFG detects the card as ES1788 if register 70h is read-only, + otherwise, as ES1887. + Bit 3 set and read-only: ESSCFG detects the card as ES1788 if register 70h is read-only, + otherwise, as ES1888. + Real ES688 and ES1688: Always 0x00. + */ case 0x64: - ret = (mixer->regs[mixer->index] & 0xf7) | 0x20; + if (ess->dsp.sb_subtype > SB_SUBTYPE_ESS_ES1688) + ret = (mixer->regs[mixer->index] & 0xf7) | 0x20; + else + ret = 0x00; break; default: - sb_log("ess: Unknown mixer register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); + sb_log("ess: Unknown mixer register READ: %02X\t%02X\n", mixer->index, mixer->regs[miwinxer->index]); break; } - sb_log("[%04X:%08X] [R] %04X = %02X\n", CS, cpu_state.pc, addr, ret); + sb_log("[%04X:%08X] [R] %04X = %02X (%02X)\n", CS, cpu_state.pc, addr, ret, mixer->index); return ret; } @@ -2268,9 +2299,6 @@ ess_x688_pnp_config_changed(UNUSED(const uint8_t ld), isapnp_device_config_t *co ess_base_write, NULL, NULL, ess); - ess->mixer_ess.ess_id_str[2] = 0x00; - ess->mixer_ess.ess_id_str[3] = 0x00; - addr = ess->opl_pnp_addr; if (addr) { ess->opl_pnp_addr = 0; @@ -2337,9 +2365,6 @@ ess_x688_pnp_config_changed(UNUSED(const uint8_t ld), isapnp_device_config_t *co ess_base_read, NULL, NULL, ess_base_write, NULL, NULL, ess); - - ess->mixer_ess.ess_id_str[2] = (addr >> 8) & 0xff; - ess->mixer_ess.ess_id_str[3] = addr & 0xff; } addr = config->io[1].base; @@ -3748,11 +3773,6 @@ ess_x688_init(UNUSED(const device_t *info)) midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &ess->dsp); if (info->local) { - ess->mixer_ess.ess_id_str[0] = 0x16; - ess->mixer_ess.ess_id_str[1] = 0x88; - ess->mixer_ess.ess_id_str[2] = (addr >> 8) & 0xff; - ess->mixer_ess.ess_id_str[3] = addr & 0xff; - ess->mpu = (mpu_t *) calloc(1, sizeof(mpu_t)); /* NOTE: The MPU is initialized disabled and with no IRQ assigned. * It will be later initialized by the guest OS's drivers. */ @@ -3818,12 +3838,6 @@ ess_x688_pnp_init(UNUSED(const device_t *info)) if (device_get_config_int("receive_input")) midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &ess->dsp); - /* Not on ES688. */ - ess->mixer_ess.ess_id_str[0] = 0x16; - ess->mixer_ess.ess_id_str[1] = 0x88; - ess->mixer_ess.ess_id_str[2] = 0x00; - ess->mixer_ess.ess_id_str[3] = 0x00; - ess->mpu = (mpu_t *) calloc(1, sizeof(mpu_t)); /* NOTE: The MPU is initialized disabled and with no IRQ assigned. * It will be later initialized by the guest OS's drivers. */ diff --git a/src/sound/snd_sb_dsp.c b/src/sound/snd_sb_dsp.c index 4cfd2c7bb..0063f0ae7 100644 --- a/src/sound/snd_sb_dsp.c +++ b/src/sound/snd_sb_dsp.c @@ -1687,6 +1687,10 @@ sb_exec_command(sb_dsp_t *dsp) break; case 0xE1: /* Get DSP version */ if (IS_ESS(dsp)) { + /* + 0x03 0x01 (Sound Blaster Pro compatibility) confirmed by both the + ES1888 datasheet and the probing of the real ES688 and ES1688 cards. + */ sb_add_data(dsp, 0x3); sb_add_data(dsp, 0x1); break; @@ -1722,9 +1726,12 @@ sb_exec_command(sb_dsp_t *dsp) while (sb16_copyright[c]) sb_add_data(dsp, sb16_copyright[c++]); sb_add_data(dsp, 0); - } else if (IS_ESS(dsp)) { - sb_add_data(dsp, 0); - } + } /* else if (IS_ESS(dsp)) + sb_add_data(dsp, 0); */ + /* + TODO: What ESS card returns 0x00 here? Probing of the real ES688 and ES1688 cards + revealed that they in fact return nothing on this command. + */ break; case 0xE4: /* Write test register */ dsp->sb_test = dsp->sb_data[0]; @@ -1736,12 +1743,26 @@ sb_exec_command(sb_dsp_t *dsp) break; case SB_SUBTYPE_ESS_ES688: sb_add_data(dsp, 0x68); - sb_add_data(dsp, 0x80 | 0x04); + /* + 80h: ESSCFG fails to detect the AudioDrive; + 81h-83h: ES??88, Windows 3.1 driver expects MPU-401 and gives a legacy mixer error; + 84h: ES688, Windows 3.1 driver expects MPU-401, returned by DOSBox-X; + 85h-87h: ES688, Windows 3.1 driver does not expect MPU-401: + 85h: Returned by MSDOS622's real ESS688, + 86h: Returned by Dizzy's real ES688. + We return 86h if MPU is absent, 84h otherwise, who knows what the actual + PnP ES688 returns here. + */ + sb_add_data(dsp, 0x80 | ((dsp->mpu != NULL) ? 0x04 : 0x06)); break; case SB_SUBTYPE_ESS_ES1688: - // Determined via Windows driver debugging. sb_add_data(dsp, 0x68); - sb_add_data(dsp, 0x80 | 0x09); + /* + 89h: ES1688, returned by DOSBox-X, determined via Windows driver + debugging; + 8Bh: ES1688, returned by both MSDOS622's and Dizzy's real ES1688's. + */ + sb_add_data(dsp, 0x80 | 0x0b); break; } } From e83a61d6a234ac66d4f7599c331e3659e8ae602a Mon Sep 17 00:00:00 2001 From: OBattler Date: Sat, 7 Dec 2024 03:13:38 +0100 Subject: [PATCH 15/24] Fixed a typo in sound/snd_sb.c. --- src/sound/snd_sb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index 4028a1ae9..0a01a4be5 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -1733,7 +1733,7 @@ ess_mixer_read(uint16_t addr, void *priv) break; default: - sb_log("ess: Unknown mixer register READ: %02X\t%02X\n", mixer->index, mixer->regs[miwinxer->index]); + sb_log("ess: Unknown mixer register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]); break; } From e2b86caf5dfec66b2333e86bb1fda9c6680b4d05 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sat, 30 Nov 2024 02:05:33 -0500 Subject: [PATCH 16/24] Update YMFM to latest version as of 11/30/2024 --- src/sound/ymfm/ymfm.h | 22 ++++++---------------- src/sound/ymfm/ymfm_fm.h | 4 ++-- src/sound/ymfm/ymfm_fm.ipp | 24 ++++++++++-------------- src/sound/ymfm/ymfm_opl.cpp | 34 +++++++++++++++++----------------- src/sound/ymfm/ymfm_opm.cpp | 20 ++++++++++---------- src/sound/ymfm/ymfm_opn.cpp | 16 ++++++++-------- src/sound/ymfm/ymfm_opq.cpp | 12 ++++++------ src/sound/ymfm/ymfm_opz.cpp | 36 ++++++++++++++++++------------------ 8 files changed, 77 insertions(+), 91 deletions(-) diff --git a/src/sound/ymfm/ymfm.h b/src/sound/ymfm/ymfm.h index c5986d66b..062247a82 100644 --- a/src/sound/ymfm/ymfm.h +++ b/src/sound/ymfm/ymfm.h @@ -42,12 +42,11 @@ #include #include #include +#include #include #include #include -#define SNPRINTF_BUFFER_SIZE_CALC (256 - (end - &buffer[0])) - namespace ymfm { @@ -111,17 +110,6 @@ inline int32_t clamp(int32_t value, int32_t minval, int32_t maxval) } -//------------------------------------------------- -// array_size - return the size of an array -//------------------------------------------------- - -template -constexpr uint32_t array_size(ArrayType (&array)[ArraySize]) -{ - return ArraySize; -} - - //------------------------------------------------- // count_leading_zeros - return the number of // leading zeros in a 32-bit value; CPU-optimized @@ -256,7 +244,8 @@ inline int16_t roundtrip_fp(int32_t value) // apply the shift back and forth to zero out bits that are lost exponent -= 1; - return (value >> exponent) << exponent; + int32_t mask = (1 << exponent) - 1; + return value & ~mask; } @@ -352,7 +341,7 @@ public: { // create file char name[20]; - snprintf(name, sizeof(name), "wavlog-%02d.wav", m_index); + snprintf(&name[0], sizeof(name), "wavlog-%02d.wav", m_index); FILE *out = fopen(name, "wb"); // make the wav file header @@ -485,7 +474,7 @@ public: class ymfm_engine_callbacks { public: - virtual ~ymfm_engine_callbacks() = default; + virtual ~ymfm_engine_callbacks() = default; // timer callback; called by the interface when a timer fires virtual void engine_timer_expired(uint32_t tnum) = 0; @@ -509,6 +498,7 @@ class ymfm_interface public: virtual ~ymfm_interface() = default; + // the following functions must be implemented by any derived classes; the // default implementations are sufficient for some minimal operation, but will // likely need to be overridden to integrate with the outside world; they are diff --git a/src/sound/ymfm/ymfm_fm.h b/src/sound/ymfm/ymfm_fm.h index 81795f8fe..d40409fdd 100644 --- a/src/sound/ymfm/ymfm_fm.h +++ b/src/sound/ymfm/ymfm_fm.h @@ -267,7 +267,7 @@ public: // assign operators void assign(uint32_t index, fm_operator *op) { - assert(index < array_size(m_op)); + assert(index < m_op.size()); m_op[index] = op; if (op != nullptr) op->set_choffs(m_choffs); @@ -330,7 +330,7 @@ private: uint32_t m_choffs; // channel offset in registers int16_t m_feedback[2]; // feedback memory for operator 1 mutable int16_t m_feedback_in; // next input value for op 1 feedback (set in output) - fm_operator *m_op[4]; // up to 4 operators + std::array *, 4> m_op; // up to 4 operators RegisterType &m_regs; // direct reference to registers fm_engine_base &m_owner; // reference to the owning engine }; diff --git a/src/sound/ymfm/ymfm_fm.ipp b/src/sound/ymfm/ymfm_fm.ipp index a3ee8d333..2aa0a216b 100644 --- a/src/sound/ymfm/ymfm_fm.ipp +++ b/src/sound/ymfm/ymfm_fm.ipp @@ -839,12 +839,12 @@ void fm_channel::save_restore(ymfm_saved_state &state) template void fm_channel::keyonoff(uint32_t states, keyon_type type, uint32_t chnum) { - for (uint32_t opnum = 0; opnum < array_size(m_op); opnum++) + for (uint32_t opnum = 0; opnum < m_op.size(); opnum++) if (m_op[opnum] != nullptr) m_op[opnum]->keyonoff(bitfield(states, opnum), type); if (debug::LOG_KEYON_EVENTS && ((debug::GLOBAL_FM_CHANNEL_MASK >> chnum) & 1) != 0) - for (uint32_t opnum = 0; opnum < array_size(m_op); opnum++) + for (uint32_t opnum = 0; opnum < m_op.size(); opnum++) if (m_op[opnum] != nullptr) debug::log_keyon("%c%s\n", bitfield(states, opnum) ? '+' : '-', m_regs.log_keyon(m_choffs, m_op[opnum]->opoffs()).c_str()); } @@ -860,7 +860,7 @@ bool fm_channel::prepare() uint32_t active_mask = 0; // prepare all operators and determine if they are active - for (uint32_t opnum = 0; opnum < array_size(m_op); opnum++) + for (uint32_t opnum = 0; opnum < m_op.size(); opnum++) if (m_op[opnum] != nullptr) if (m_op[opnum]->prepare()) active_mask |= 1 << opnum; @@ -880,7 +880,7 @@ void fm_channel::clock(uint32_t env_counter, int32_t lfo_raw_pm) m_feedback[0] = m_feedback[1]; m_feedback[1] = m_feedback_in; - for (uint32_t opnum = 0; opnum < array_size(m_op); opnum++) + for (uint32_t opnum = 0; opnum < m_op.size(); opnum++) if (m_op[opnum] != nullptr) m_op[opnum]->clock(env_counter, lfo_raw_pm); @@ -888,7 +888,7 @@ void fm_channel::clock(uint32_t env_counter, int32_t lfo_raw_pm) useful temporary code for envelope debugging if (m_choffs == 0x101) { - for (uint32_t opnum = 0; opnum < array_size(m_op); opnum++) + for (uint32_t opnum = 0; opnum < m_op.size(); opnum++) { auto &op = *m_op[((opnum & 1) << 1) | ((opnum >> 1) & 1)]; printf(" %c%03X%c%c ", @@ -1473,14 +1473,11 @@ void fm_engine_base::assign_operators() template void fm_engine_base::update_timer(uint32_t tnum, uint32_t enable, int32_t delta_clocks) { - uint32_t subtract = !!(tnum >> 15); - tnum &= 0x7fff; - // if the timer is live, but not currently enabled, set the timer if (enable && !m_timer_running[tnum]) { // period comes from the registers, and is different for each - uint32_t period = (tnum == 0) ? (1024 - subtract - m_regs.timer_a_value()) : 16 * (256 - subtract - m_regs.timer_b_value()); + uint32_t period = (tnum == 0) ? (1024 - m_regs.timer_a_value()) : 16 * (256 - m_regs.timer_b_value()); // caller can also specify a delta to account for other effects period += delta_clocks; @@ -1507,6 +1504,8 @@ void fm_engine_base::update_timer(uint32_t tnum, uint32_t enable, template void fm_engine_base::engine_timer_expired(uint32_t tnum) { + assert(tnum == 0 || tnum == 1); + // update status if (tnum == 0 && m_regs.enable_timer_a()) set_reset_status(STATUS_TIMERA, 0); @@ -1522,11 +1521,8 @@ void fm_engine_base::engine_timer_expired(uint32_t tnum) m_modified_channels |= 1 << chnum; } - // Make sure the array does not go out of bounds to keep gcc happy - if ((tnum < 2) || (sizeof(m_timer_running) > (2 * sizeof(uint8_t)))) { - // reset - m_timer_running[tnum] = false; - } + // reset + m_timer_running[tnum] = false; update_timer(tnum, 1, 0); } diff --git a/src/sound/ymfm/ymfm_opl.cpp b/src/sound/ymfm/ymfm_opl.cpp index bb91c5dc0..8e8025fd9 100644 --- a/src/sound/ymfm/ymfm_opl.cpp +++ b/src/sound/ymfm/ymfm_opl.cpp @@ -386,9 +386,9 @@ std::string opl_registers_base::log_keyon(uint32_t choffs, uint32_t op uint32_t opnum = (opoffs & 31) - 2 * ((opoffs & 31) / 8) + 18 * bitfield(opoffs, 8); char buffer[256]; - char *end = &buffer[0]; + int end = 0; - end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, "%2u.%02u freq=%04X fb=%u alg=%X mul=%X tl=%02X ksr=%u ns=%u ksl=%u adr=%X/%X/%X sl=%X sus=%u", + end += snprintf(&buffer[end], sizeof(buffer) - end, "%2u.%02u freq=%04X fb=%u alg=%X mul=%X tl=%02X ksr=%u ns=%u ksl=%u adr=%X/%X/%X sl=%X sus=%u", chnum, opnum, ch_block_freq(choffs), ch_feedback(choffs), @@ -405,25 +405,25 @@ std::string opl_registers_base::log_keyon(uint32_t choffs, uint32_t op op_eg_sustain(opoffs)); if (OUTPUTS > 1) - end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " out=%c%c%c%c", + end += snprintf(&buffer[end], sizeof(buffer) - end, " out=%c%c%c%c", ch_output_0(choffs) ? 'L' : '-', ch_output_1(choffs) ? 'R' : '-', ch_output_2(choffs) ? '0' : '-', ch_output_3(choffs) ? '1' : '-'); if (op_lfo_am_enable(opoffs) != 0) - end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " am=%u", lfo_am_depth()); + end += snprintf(&buffer[end], sizeof(buffer) - end, " am=%u", lfo_am_depth()); if (op_lfo_pm_enable(opoffs) != 0) - end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " pm=%u", lfo_pm_depth()); + end += snprintf(&buffer[end], sizeof(buffer) - end, " pm=%u", lfo_pm_depth()); if (waveform_enable() && op_waveform(opoffs) != 0) - end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " wf=%u", op_waveform(opoffs)); + end += snprintf(&buffer[end], sizeof(buffer) - end, " wf=%u", op_waveform(opoffs)); if (is_rhythm(choffs)) - end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " rhy=1"); + end += snprintf(&buffer[end], sizeof(buffer) - end, " rhy=1"); if (DYNAMIC_OPS) { operator_mapping map; operator_map(map); if (bitfield(map.chan[chnum], 16, 8) != 0xff) - end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " 4op"); + end += snprintf(&buffer[end], sizeof(buffer) - end, " 4op"); } return buffer; @@ -685,9 +685,9 @@ std::string opll_registers::log_keyon(uint32_t choffs, uint32_t opoffs) uint32_t opnum = opoffs; char buffer[256]; - char *end = &buffer[0]; + int end = 0; - end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, "%u.%02u freq=%04X inst=%X fb=%u mul=%X", + end += snprintf(&buffer[end], sizeof(buffer) - end, "%u.%02u freq=%04X inst=%X fb=%u mul=%X", chnum, opnum, ch_block_freq(choffs), ch_instrument(choffs), @@ -695,11 +695,11 @@ std::string opll_registers::log_keyon(uint32_t choffs, uint32_t opoffs) op_multiple(opoffs)); if (bitfield(opoffs, 0) == 1 || (is_rhythm(choffs) && choffs >= 6)) - end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " vol=%X", op_volume(opoffs)); + end += snprintf(&buffer[end], sizeof(buffer) - end, " vol=%X", op_volume(opoffs)); else - end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " tl=%02X", ch_total_level(choffs)); + end += snprintf(&buffer[end], sizeof(buffer) - end, " tl=%02X", ch_total_level(choffs)); - end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " ksr=%u ksl=%u adr=%X/%X/%X sl=%X sus=%u/%u", + end += snprintf(&buffer[end], sizeof(buffer) - end, " ksr=%u ksl=%u adr=%X/%X/%X sl=%X sus=%u/%u", op_ksr(opoffs), op_ksl(opoffs), op_attack_rate(opoffs), @@ -710,13 +710,13 @@ std::string opll_registers::log_keyon(uint32_t choffs, uint32_t opoffs) ch_sustain(choffs)); if (op_lfo_am_enable(opoffs)) - end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " am=1"); + end += snprintf(&buffer[end], sizeof(buffer) - end, " am=1"); if (op_lfo_pm_enable(opoffs)) - end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " pm=1"); + end += snprintf(&buffer[end], sizeof(buffer) - end, " pm=1"); if (op_waveform(opoffs) != 0) - end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " wf=1"); + end += snprintf(&buffer[end], sizeof(buffer) - end, " wf=1"); if (is_rhythm(choffs)) - end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " rhy=1"); + end += snprintf(&buffer[end], sizeof(buffer) - end, " rhy=1"); return buffer; } diff --git a/src/sound/ymfm/ymfm_opm.cpp b/src/sound/ymfm/ymfm_opm.cpp index c72badb57..03f54fb90 100644 --- a/src/sound/ymfm/ymfm_opm.cpp +++ b/src/sound/ymfm/ymfm_opm.cpp @@ -60,17 +60,17 @@ opm_registers::opm_registers() : { // waveform 0 is a sawtooth uint8_t am = index ^ 0xff; - int8_t pm = int8_t(index); + uint8_t pm = index; m_lfo_waveform[0][index] = am | (pm << 8); // waveform 1 is a square wave am = bitfield(index, 7) ? 0 : 0xff; - pm = int8_t(am ^ 0x80); + pm = am ^ 0x80; m_lfo_waveform[1][index] = am | (pm << 8); // waveform 2 is a triangle wave am = bitfield(index, 7) ? (index << 1) : ((index ^ 0xff) << 1); - pm = int8_t(bitfield(index, 6) ? am : ~am); + pm = bitfield(index, 6) ? am : ~am; m_lfo_waveform[2][index] = am | (pm << 8); // waveform 3 is noise; it is filled in dynamically @@ -330,7 +330,7 @@ uint32_t opm_registers::compute_phase_step(uint32_t choffs, uint32_t opoffs, opd if (pm_sensitivity < 6) delta += lfo_raw_pm >> (6 - pm_sensitivity); else - delta += lfo_raw_pm << (pm_sensitivity - 5); + delta += uint32_t(lfo_raw_pm) << (pm_sensitivity - 5); } // apply delta and convert to a frequency number @@ -354,9 +354,9 @@ std::string opm_registers::log_keyon(uint32_t choffs, uint32_t opoffs) uint32_t opnum = opoffs; char buffer[256]; - char *end = &buffer[0]; + int end = 0; - end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, "%u.%02u freq=%04X dt2=%u dt=%u fb=%u alg=%X mul=%X tl=%02X ksr=%u adsr=%02X/%02X/%02X/%X sl=%X out=%c%c", + end += snprintf(&buffer[end], sizeof(buffer) - end, "%u.%02u freq=%04X dt2=%u dt=%u fb=%u alg=%X mul=%X tl=%02X ksr=%u adsr=%02X/%02X/%02X/%X sl=%X out=%c%c", chnum, opnum, ch_block_freq(choffs), op_detune2(opoffs), @@ -376,14 +376,14 @@ std::string opm_registers::log_keyon(uint32_t choffs, uint32_t opoffs) bool am = (lfo_am_depth() != 0 && ch_lfo_am_sens(choffs) != 0 && op_lfo_am_enable(opoffs) != 0); if (am) - end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " am=%u/%02X", ch_lfo_am_sens(choffs), lfo_am_depth()); + end += snprintf(&buffer[end], sizeof(buffer) - end, " am=%u/%02X", ch_lfo_am_sens(choffs), lfo_am_depth()); bool pm = (lfo_pm_depth() != 0 && ch_lfo_pm_sens(choffs) != 0); if (pm) - end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " pm=%u/%02X", ch_lfo_pm_sens(choffs), lfo_pm_depth()); + end += snprintf(&buffer[end], sizeof(buffer) - end, " pm=%u/%02X", ch_lfo_pm_sens(choffs), lfo_pm_depth()); if (am || pm) - end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " lfo=%02X/%c", lfo_rate(), "WQTN"[lfo_waveform()]); + end += snprintf(&buffer[end], sizeof(buffer) - end, " lfo=%02X/%c", lfo_rate(), "WQTN"[lfo_waveform()]); if (noise_enable() && opoffs == 31) - end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " noise=1"); + end += snprintf(&buffer[end], sizeof(buffer) - end, " noise=1"); return buffer; } diff --git a/src/sound/ymfm/ymfm_opn.cpp b/src/sound/ymfm/ymfm_opn.cpp index 388162dfe..16ca3416c 100644 --- a/src/sound/ymfm/ymfm_opn.cpp +++ b/src/sound/ymfm/ymfm_opn.cpp @@ -409,9 +409,9 @@ std::string opn_registers_base::log_keyon(uint32_t choffs, uint32_t opof } char buffer[256]; - char *end = &buffer[0]; + int end = 0; - end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, "%u.%02u freq=%04X dt=%u fb=%u alg=%X mul=%X tl=%02X ksr=%u adsr=%02X/%02X/%02X/%X sl=%X", + end += snprintf(&buffer[end], sizeof(buffer) - end, "%u.%02u freq=%04X dt=%u fb=%u alg=%X mul=%X tl=%02X ksr=%u adsr=%02X/%02X/%02X/%X sl=%X", chnum, opnum, block_freq, op_detune(opoffs), @@ -427,21 +427,21 @@ std::string opn_registers_base::log_keyon(uint32_t choffs, uint32_t opof op_sustain_level(opoffs)); if (OUTPUTS > 1) - end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " out=%c%c", + end += snprintf(&buffer[end], sizeof(buffer) - end, " out=%c%c", ch_output_0(choffs) ? 'L' : '-', ch_output_1(choffs) ? 'R' : '-'); if (op_ssg_eg_enable(opoffs)) - end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " ssg=%X", op_ssg_eg_mode(opoffs)); + end += snprintf(&buffer[end], sizeof(buffer) - end, " ssg=%X", op_ssg_eg_mode(opoffs)); bool am = (op_lfo_am_enable(opoffs) && ch_lfo_am_sens(choffs) != 0); if (am) - end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " am=%u", ch_lfo_am_sens(choffs)); + end += snprintf(&buffer[end], sizeof(buffer) - end, " am=%u", ch_lfo_am_sens(choffs)); bool pm = (ch_lfo_pm_sens(choffs) != 0); if (pm) - end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " pm=%u", ch_lfo_pm_sens(choffs)); + end += snprintf(&buffer[end], sizeof(buffer) - end, " pm=%u", ch_lfo_pm_sens(choffs)); if (am || pm) - end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " lfo=%02X", lfo_rate()); + end += snprintf(&buffer[end], sizeof(buffer) - end, " lfo=%02X", lfo_rate()); if (multi_freq() && choffs == 2) - end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " multi=1"); + end += snprintf(&buffer[end], sizeof(buffer) - end, " multi=1"); return buffer; } diff --git a/src/sound/ymfm/ymfm_opq.cpp b/src/sound/ymfm/ymfm_opq.cpp index e6f6fa5ea..78ae16164 100644 --- a/src/sound/ymfm/ymfm_opq.cpp +++ b/src/sound/ymfm/ymfm_opq.cpp @@ -339,9 +339,9 @@ std::string opq_registers::log_keyon(uint32_t choffs, uint32_t opoffs) uint32_t opnum = opoffs; char buffer[256]; - char *end = &buffer[0]; + int end = 0; - end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, "%u.%02u freq=%04X dt=%+2d fb=%u alg=%X mul=%X tl=%02X ksr=%u adsr=%02X/%02X/%02X/%X sl=%X out=%c%c", + end += snprintf(&buffer[end], sizeof(buffer) - end, "%u.%02u freq=%04X dt=%+2d fb=%u alg=%X mul=%X tl=%02X ksr=%u adsr=%02X/%02X/%02X/%X sl=%X out=%c%c", chnum, opnum, (opoffs & 1) ? ch_block_freq_24(choffs) : ch_block_freq_13(choffs), int32_t(op_detune(opoffs)) - 0x20, @@ -360,14 +360,14 @@ std::string opq_registers::log_keyon(uint32_t choffs, uint32_t opoffs) bool am = (lfo_enable() && op_lfo_am_enable(opoffs) && ch_lfo_am_sens(choffs) != 0); if (am) - end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " am=%u", ch_lfo_am_sens(choffs)); + end += snprintf(&buffer[end], sizeof(buffer) - end, " am=%u", ch_lfo_am_sens(choffs)); bool pm = (lfo_enable() && ch_lfo_pm_sens(choffs) != 0); if (pm) - end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " pm=%u", ch_lfo_pm_sens(choffs)); + end += snprintf(&buffer[end], sizeof(buffer) - end, " pm=%u", ch_lfo_pm_sens(choffs)); if (am || pm) - end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " lfo=%02X", lfo_rate()); + end += snprintf(&buffer[end], sizeof(buffer) - end, " lfo=%02X", lfo_rate()); if (ch_reverb(choffs)) - end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " reverb"); + end += snprintf(&buffer[end], sizeof(buffer) - end, " reverb"); return buffer; } diff --git a/src/sound/ymfm/ymfm_opz.cpp b/src/sound/ymfm/ymfm_opz.cpp index a5ec912aa..1178417bb 100644 --- a/src/sound/ymfm/ymfm_opz.cpp +++ b/src/sound/ymfm/ymfm_opz.cpp @@ -129,17 +129,17 @@ opz_registers::opz_registers() : { // waveform 0 is a sawtooth uint8_t am = index ^ 0xff; - int8_t pm = int8_t(index); + uint8_t pm = index; m_lfo_waveform[0][index] = am | (pm << 8); // waveform 1 is a square wave am = bitfield(index, 7) ? 0 : 0xff; - pm = int8_t(am ^ 0x80); + pm = am ^ 0x80; m_lfo_waveform[1][index] = am | (pm << 8); // waveform 2 is a triangle wave am = bitfield(index, 7) ? (index << 1) : ((index ^ 0xff) << 1); - pm = int8_t(bitfield(index, 6) ? am : ~am); + pm = bitfield(index, 6) ? am : ~am; m_lfo_waveform[2][index] = am | (pm << 8); // waveform 3 is noise; it is filled in dynamically @@ -555,16 +555,16 @@ std::string opz_registers::log_keyon(uint32_t choffs, uint32_t opoffs) uint32_t opnum = opoffs; char buffer[256]; - char *end = &buffer[0]; + int end = 0; - end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, "%u.%02u", chnum, opnum); + end += snprintf(&buffer[end], sizeof(buffer) - end, "%u.%02u", chnum, opnum); if (op_fix_mode(opoffs)) - end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " fixfreq=%X fine=%X shift=%X", op_fix_frequency(opoffs), op_fine(opoffs), op_fix_range(opoffs)); + end += snprintf(&buffer[end], sizeof(buffer) - end, " fixfreq=%X fine=%X shift=%X", op_fix_frequency(opoffs), op_fine(opoffs), op_fix_range(opoffs)); else - end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " freq=%04X dt2=%u fine=%X", ch_block_freq(choffs), op_detune2(opoffs), op_fine(opoffs)); + end += snprintf(&buffer[end], sizeof(buffer) - end, " freq=%04X dt2=%u fine=%X", ch_block_freq(choffs), op_detune2(opoffs), op_fine(opoffs)); - end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " dt=%u fb=%u alg=%X mul=%X tl=%02X ksr=%u adsr=%02X/%02X/%02X/%X sl=%X out=%c%c", + end += snprintf(&buffer[end], sizeof(buffer) - end, " dt=%u fb=%u alg=%X mul=%X tl=%02X ksr=%u adsr=%02X/%02X/%02X/%X sl=%X out=%c%c", op_detune(opoffs), ch_feedback(choffs), ch_algorithm(choffs), @@ -580,32 +580,32 @@ std::string opz_registers::log_keyon(uint32_t choffs, uint32_t opoffs) ch_output_1(choffs) ? 'R' : '-'); if (op_eg_shift(opoffs) != 0) - end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " egshift=%u", op_eg_shift(opoffs)); + end += snprintf(&buffer[end], sizeof(buffer) - end, " egshift=%u", op_eg_shift(opoffs)); bool am = (lfo_am_depth() != 0 && ch_lfo_am_sens(choffs) != 0 && op_lfo_am_enable(opoffs) != 0); if (am) - end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " am=%u/%02X", ch_lfo_am_sens(choffs), lfo_am_depth()); + end += snprintf(&buffer[end], sizeof(buffer) - end, " am=%u/%02X", ch_lfo_am_sens(choffs), lfo_am_depth()); bool pm = (lfo_pm_depth() != 0 && ch_lfo_pm_sens(choffs) != 0); if (pm) - end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " pm=%u/%02X", ch_lfo_pm_sens(choffs), lfo_pm_depth()); + end += snprintf(&buffer[end], sizeof(buffer) - end, " pm=%u/%02X", ch_lfo_pm_sens(choffs), lfo_pm_depth()); if (am || pm) - end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " lfo=%02X/%c", lfo_rate(), "WQTN"[lfo_waveform()]); + end += snprintf(&buffer[end], sizeof(buffer) - end, " lfo=%02X/%c", lfo_rate(), "WQTN"[lfo_waveform()]); bool am2 = (lfo2_am_depth() != 0 && ch_lfo2_am_sens(choffs) != 0 && op_lfo_am_enable(opoffs) != 0); if (am2) - end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " am2=%u/%02X", ch_lfo2_am_sens(choffs), lfo2_am_depth()); + end += snprintf(&buffer[end], sizeof(buffer) - end, " am2=%u/%02X", ch_lfo2_am_sens(choffs), lfo2_am_depth()); bool pm2 = (lfo2_pm_depth() != 0 && ch_lfo2_pm_sens(choffs) != 0); if (pm2) - end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " pm2=%u/%02X", ch_lfo2_pm_sens(choffs), lfo2_pm_depth()); + end += snprintf(&buffer[end], sizeof(buffer) - end, " pm2=%u/%02X", ch_lfo2_pm_sens(choffs), lfo2_pm_depth()); if (am2 || pm2) - end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " lfo2=%02X/%c", lfo2_rate(), "WQTN"[lfo2_waveform()]); + end += snprintf(&buffer[end], sizeof(buffer) - end, " lfo2=%02X/%c", lfo2_rate(), "WQTN"[lfo2_waveform()]); if (op_reverb_rate(opoffs) != 0) - end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " rev=%u", op_reverb_rate(opoffs)); + end += snprintf(&buffer[end], sizeof(buffer) - end, " rev=%u", op_reverb_rate(opoffs)); if (op_waveform(opoffs) != 0) - end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " wf=%u", op_waveform(opoffs)); + end += snprintf(&buffer[end], sizeof(buffer) - end, " wf=%u", op_waveform(opoffs)); if (noise_enable() && opoffs == 31) - end += snprintf(end, SNPRINTF_BUFFER_SIZE_CALC, " noise=1"); + end += snprintf(&buffer[end], sizeof(buffer) - end, " noise=1"); return buffer; } From e7f0974ab4c5bbf8d5880b3fe5e683778cedec62 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 8 Dec 2024 01:55:27 +0100 Subject: [PATCH 17/24] FDC: Do not clear disk changed status on DOR reset (DSKCHG is an input pin and the FDC can not change it), fixes #5003. --- src/floppy/fdc.c | 61 ++++++++++++++++++++---------------------------- 1 file changed, 25 insertions(+), 36 deletions(-) diff --git a/src/floppy/fdc.c b/src/floppy/fdc.c index 7426bc216..546174c57 100644 --- a/src/floppy/fdc.c +++ b/src/floppy/fdc.c @@ -652,13 +652,31 @@ fdc_sis(fdc_t *fdc) fdc->paramstogo = 2; } +static void +fdc_soft_reset(fdc_t *fdc) +{ + if (fdc->power_down) { + timer_set_delay_u64(&fdc->timer, 1000 * TIMER_USEC); + fdc->interrupt = -5; + } else { + timer_set_delay_u64(&fdc->timer, 8 * TIMER_USEC); + fdc->interrupt = -1; + + fdc->perp &= 0xfc; + + for (int i = 0; i < FDD_NUM; i++) + ui_sb_update_icon(SB_FLOPPY | i, 0); + + fdc_ctrl_reset(fdc); + } +} + static void fdc_write(uint16_t addr, uint8_t val, void *priv) { fdc_t *fdc = (fdc_t *) priv; int drive; - int i; int drive_num; fdc_log("Write FDC %04X %02X\n", addr, val); @@ -682,7 +700,6 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) fdc->interrupt = -1; ui_sb_update_icon(SB_FLOPPY | 0, 0); fdc_ctrl_reset(fdc); - fdd_changed[0] = 1; } if (!fdd_get_flags(0)) val &= 0xfe; @@ -699,24 +716,10 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) fdc->stat = 0x00; fdc->pnum = fdc->ptot = 0; } - if ((val & 4) && !(fdc->dor & 4)) { - if (fdc->power_down) { - timer_set_delay_u64(&fdc->timer, 1000 * TIMER_USEC); - fdc->interrupt = -5; - } else { - timer_set_delay_u64(&fdc->timer, 8 * TIMER_USEC); - fdc->interrupt = -1; - - fdc->perp &= 0xfc; - - for (i = 0; i < FDD_NUM; i++) - ui_sb_update_icon(SB_FLOPPY | i, 0); - - fdc_ctrl_reset(fdc); - } - } + if ((val & 4) && !(fdc->dor & 4)) + fdc_soft_reset(fdc); /* We can now simplify this since each motor now spins separately. */ - for (i = 0; i < FDD_NUM; i++) { + for (int i = 0; i < FDD_NUM; i++) { drive_num = real_drive(fdc, i); if ((!fdd_get_flags(drive_num)) || (drive_num >= FDD_NUM)) val &= ~(0x10 << drive_num); @@ -735,28 +738,14 @@ fdc_write(uint16_t addr, uint8_t val, void *priv) fdc_update_rwc(fdc, drive, (val & 0x30) >> 4); } return; - case 4: + case 4: /* DSR */ if (!(fdc->flags & FDC_FLAG_NO_DSR_RESET)) { if (!(val & 0x80)) { timer_set_delay_u64(&fdc->timer, 8 * TIMER_USEC); fdc->interrupt = -6; } - if (fdc->power_down || ((val & 0x80) && !(fdc->dsr & 0x80))) { - if (fdc->power_down) { - timer_set_delay_u64(&fdc->timer, 1000 * TIMER_USEC); - fdc->interrupt = -5; - } else { - timer_set_delay_u64(&fdc->timer, 8 * TIMER_USEC); - fdc->interrupt = -1; - - fdc->perp &= 0xfc; - - for (i = 0; i < FDD_NUM; i++) - ui_sb_update_icon(SB_FLOPPY | i, 0); - - fdc_ctrl_reset(fdc); - } - } + if (fdc->power_down || ((val & 0x80) && !(fdc->dsr & 0x80))) + fdc_soft_reset(fdc); } fdc->dsr = val; return; From db34cc06b95cf08cfdffcdac6e7e99f6bd3814b8 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sun, 24 Nov 2024 00:53:09 -0500 Subject: [PATCH 18/24] Deal with many magic numbers in gameport.c --- src/game/gameport.c | 28 ++++++++++++++-------------- src/include/86box/gameport.h | 3 +++ 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/game/gameport.c b/src/game/gameport.c index 58d9a446f..4c7b4c74b 100644 --- a/src/game/gameport.c +++ b/src/game/gameport.c @@ -468,7 +468,7 @@ const device_t gameport_device = { .name = "Game port", .internal_name = "gameport", .flags = 0, - .local = 0x080200, + .local = GAMEPORT_8ADDR | 0x0200, .init = gameport_init, .close = gameport_close, .reset = NULL, @@ -482,7 +482,7 @@ const device_t gameport_201_device = { .name = "Game port (Port 201h only)", .internal_name = "gameport_201", .flags = 0, - .local = 0x010201, + .local = GAMEPORT_1ADDR | 0x0201, .init = gameport_init, .close = gameport_close, .reset = NULL, @@ -496,7 +496,7 @@ const device_t gameport_203_device = { .name = "Game port (Port 203h only)", .internal_name = "gameport_203", .flags = 0, - .local = 0x010203, + .local = GAMEPORT_1ADDR | 0x0203, .init = gameport_init, .close = gameport_close, .reset = NULL, @@ -510,7 +510,7 @@ const device_t gameport_205_device = { .name = "Game port (Port 205h only)", .internal_name = "gameport_205", .flags = 0, - .local = 0x010205, + .local = GAMEPORT_1ADDR | 0x0205, .init = gameport_init, .close = gameport_close, .reset = NULL, @@ -524,7 +524,7 @@ const device_t gameport_207_device = { .name = "Game port (Port 207h only)", .internal_name = "gameport_207", .flags = 0, - .local = 0x010207, + .local = GAMEPORT_1ADDR | 0x0207, .init = gameport_init, .close = gameport_close, .reset = NULL, @@ -538,7 +538,7 @@ const device_t gameport_208_device = { .name = "Game port (Port 208h-20fh)", .internal_name = "gameport_208", .flags = 0, - .local = 0x080208, + .local = GAMEPORT_8ADDR | 0x0208, .init = gameport_init, .close = gameport_close, .reset = NULL, @@ -552,7 +552,7 @@ const device_t gameport_209_device = { .name = "Game port (Port 209h only)", .internal_name = "gameport_209", .flags = 0, - .local = 0x010209, + .local = GAMEPORT_1ADDR | 0x0209, .init = gameport_init, .close = gameport_close, .reset = NULL, @@ -566,7 +566,7 @@ const device_t gameport_20b_device = { .name = "Game port (Port 20Bh only)", .internal_name = "gameport_20b", .flags = 0, - .local = 0x01020B, + .local = GAMEPORT_1ADDR | 0x020B, .init = gameport_init, .close = gameport_close, .reset = NULL, @@ -580,7 +580,7 @@ const device_t gameport_20d_device = { .name = "Game port (Port 20Dh only)", .internal_name = "gameport_20d", .flags = 0, - .local = 0x01020D, + .local = GAMEPORT_1ADDR | 0x020D, .init = gameport_init, .close = gameport_close, .reset = NULL, @@ -594,7 +594,7 @@ const device_t gameport_20f_device = { .name = "Game port (Port 20Fh only)", .internal_name = "gameport_20f", .flags = 0, - .local = 0x01020F, + .local = GAMEPORT_1ADDR | 0x020F, .init = gameport_init, .close = gameport_close, .reset = NULL, @@ -662,7 +662,7 @@ const device_t gameport_pnp_device = { .name = "Game port (Plug and Play only)", .internal_name = "gameport_pnp", .flags = 0, - .local = 0x080000, + .local = GAMEPORT_8ADDR, .init = gameport_init, .close = gameport_close, .reset = NULL, @@ -676,7 +676,7 @@ const device_t gameport_pnp_6io_device = { .name = "Game port (Plug and Play only, 6 I/O ports)", .internal_name = "gameport_pnp_6io", .flags = 0, - .local = 0x060000, + .local = GAMEPORT_6ADDR, .init = gameport_init, .close = gameport_close, .reset = NULL, @@ -690,7 +690,7 @@ const device_t gameport_sio_device = { .name = "Game port (Super I/O)", .internal_name = "gameport_sio", .flags = 0, - .local = 0x1080000, + .local = GAMEPORT_SIO | GAMEPORT_8ADDR, .init = gameport_init, .close = gameport_close, .reset = NULL, @@ -704,7 +704,7 @@ const device_t gameport_sio_1io_device = { .name = "Game port (Super I/O, 1 I/O port)", .internal_name = "gameport_sio", .flags = 0, - .local = 0x1010000, + .local = GAMEPORT_SIO | GAMEPORT_1ADDR, .init = gameport_init, .close = gameport_close, .reset = NULL, diff --git a/src/include/86box/gameport.h b/src/include/86box/gameport.h index d9c702394..0dcb5a805 100644 --- a/src/include/86box/gameport.h +++ b/src/include/86box/gameport.h @@ -45,6 +45,9 @@ #define JOYSTICK_PRESENT(n) (joystick_state[n].plat_joystick_nr != 0) +#define GAMEPORT_1ADDR 0x010000 +#define GAMEPORT_6ADDR 0x060000 +#define GAMEPORT_8ADDR 0x080000 #define GAMEPORT_SIO 0x1000000 typedef struct plat_joystick_t { From 53c6c9660c0878eac33672d85295350c2fd76710 Mon Sep 17 00:00:00 2001 From: Jasmine Iwanek Date: Sat, 30 Nov 2024 15:33:29 -0500 Subject: [PATCH 19/24] Update gameport copyright --- src/game/gameport.c | 4 +++- src/include/86box/gameport.h | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/game/gameport.c b/src/game/gameport.c index 4c7b4c74b..e7495e365 100644 --- a/src/game/gameport.c +++ b/src/game/gameport.c @@ -13,10 +13,12 @@ * Authors: Miran Grca, * Sarah Walker, * RichardG, + * Jasmine Iwanek, * - * Copyright 2016-2018 Miran Grca. + * Copyright 2016-2022 Miran Grca. * Copyright 2008-2018 Sarah Walker. * Copyright 2021 RichardG. + * Copyright 2021-2024 Jasmine Iwanek. */ #include #include diff --git a/src/include/86box/gameport.h b/src/include/86box/gameport.h index 0dcb5a805..576d6b8e7 100644 --- a/src/include/86box/gameport.h +++ b/src/include/86box/gameport.h @@ -13,10 +13,12 @@ * Authors: Miran Grca, * Sarah Walker, * RichardG, + * Jasmine Iwanek, * - * Copyright 2016-2018 Miran Grca. + * Copyright 2016-2022 Miran Grca. * Copyright 2008-2018 Sarah Walker. * Copyright 2021 RichardG. + * Copyright 2021-2024 Jasmine Iwanek. */ #ifndef EMU_GAMEPORT_H #define EMU_GAMEPORT_H From 20feee1e00102bb3efbc047ac59ac69da1c3e067 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 8 Dec 2024 02:58:57 +0100 Subject: [PATCH 20/24] 86F: Preserve weak bits. --- src/floppy/fdd_86f.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/floppy/fdd_86f.c b/src/floppy/fdd_86f.c index cf9e83694..0e8a6590a 100644 --- a/src/floppy/fdd_86f.c +++ b/src/floppy/fdd_86f.c @@ -2911,6 +2911,7 @@ d86f_decompose_encoded_buffer(int drive, int side) uint16_t temp2; uint32_t len; const uint16_t *dst = dev->track_encoded_data[side]; + const uint16_t *dst_s = dev->track_surface_data[side]; uint16_t *src1 = dev->thin_track_encoded_data[0][side]; uint16_t *src1_s = dev->thin_track_surface_data[0][side]; uint16_t *src2 = dev->thin_track_encoded_data[1][side]; @@ -2922,12 +2923,13 @@ d86f_decompose_encoded_buffer(int drive, int side) if (d86f_has_surface_desc(drive)) { /* Source image has surface description data, so we have some more handling to do. We need hole masks for both buffers. Holes have data bit clear and surface bit set. */ - temp = ~src1[i] & src1_s[i]; - temp2 = ~src2[i] & src2_s[i]; - src1[i] = dst[i] & ~temp; - src1_s[i] = temp; - src2[i] = dst[i] & ~temp2; - src2_s[i] = temp2; + src1_s[i] = src2_s[i] = dst_s[i]; /* Write the new holes and weak bits. */ + temp = ~src1[i] & src1_s[i]; /* Bits that are clear in data and set in surface are holes. */ + temp2 = ~src2[i] & src2_s[i]; /* Bits that are clear in data and set in surface are holes. */ + src1[i] = dst[i] & ~temp; /* Make sure the holes' bits are cleared in the decomposed buffer. */ + src1_s[i] |= temp; /* Make sure the holes' bits are set in the decomposed surface. */ + src2[i] = dst[i] & ~temp2; /* Make sure the holes' bits are cleared in the decomposed buffer. */ + src2_s[i] |= temp2; /* Make sure the holes' bits are set in the decomposed surface. */ } else src1[i] = src2[i] = dst[i]; } From 803c19b4c2c1d62d0e2e80a505f98d40aa6472c8 Mon Sep 17 00:00:00 2001 From: Jose Phillips Date: Sun, 8 Dec 2024 18:10:05 -0500 Subject: [PATCH 21/24] check if libserial exists for unsupported libserial OS --- src/include/86box/snd_opl.h | 4 +++- src/include/86box/sound.h | 2 ++ src/sound/CMakeLists.txt | 36 +++++++++++++++++++++--------------- src/sound/snd_opl.c | 3 ++- src/sound/sound.c | 2 ++ 5 files changed, 30 insertions(+), 17 deletions(-) diff --git a/src/include/86box/snd_opl.h b/src/include/86box/snd_opl.h index 95eec2687..8a6a7d6ef 100644 --- a/src/include/86box/snd_opl.h +++ b/src/include/86box/snd_opl.h @@ -60,8 +60,10 @@ extern const device_t ymf289b_ymfm_device; extern const device_t ymf278b_ymfm_device; extern const device_t esfm_esfmu_device; - +#ifdef USE_LIBSERIALPORT extern const device_t ym_opl2board_device; #endif +#endif + #endif /*SOUND_OPL_H*/ diff --git a/src/include/86box/sound.h b/src/include/86box/sound.h index 428f12932..bcf7f2ae5 100644 --- a/src/include/86box/sound.h +++ b/src/include/86box/sound.h @@ -209,8 +209,10 @@ extern const device_t tndy_device; extern const device_t wss_device; extern const device_t ncr_business_audio_device; +#ifdef USE_LIBSERIALPORT /* External Audio device OPL2Board (Host Connected hardware)*/ extern const device_t opl2board_device; +#endif #endif diff --git a/src/sound/CMakeLists.txt b/src/sound/CMakeLists.txt index 315da61e4..a381051ba 100644 --- a/src/sound/CMakeLists.txt +++ b/src/sound/CMakeLists.txt @@ -31,8 +31,6 @@ add_library(snd OBJECT snd_ps1.c snd_adlib.c snd_adlibgold.c - snd_opl2board.c - snd_opl_opl2board.cpp snd_ad1848.c snd_audiopci.c snd_azt2316a.c @@ -172,20 +170,28 @@ if(OPL4ML) target_compile_definitions(snd PRIVATE USE_OPL4ML) target_sources(snd PRIVATE midi_opl4.c midi_opl4_yrw801.c) endif() - -find_package(PkgConfig REQUIRED) -pkg_check_modules(SERIALPORT REQUIRED libserialport) -if(APPLE) - include_directories(${LIBSERIALPORT_ROOT}/include) - target_link_libraries(86Box ${LIBSERIALPORT_ROOT}/lib/libserialport.dylib) -elseif(WIN32) - include_directories(${SERIALPORT_INCLUDE_DIRS}) - target_link_libraries(86Box ${SERIALPORT_LIBRARIES} SetupAPI) -else() - include_directories(${SERIALPORT_INCLUDE_DIRS}) - target_link_libraries(86Box ${SERIALPORT_LIBRARIES}) -endif() + +find_package(PkgConfig ) +pkg_check_modules(SERIALPORT libserialport) +if(SERIALPORT_FOUND OR DEFINED LIBSERIALPORT_ROOT) + add_compile_definitions(USE_LIBSERIALPORT=1) + + if(APPLE) + include_directories(${LIBSERIALPORT_ROOT}/include) + target_link_libraries(86Box ${LIBSERIALPORT_ROOT}/lib/libserialport.dylib) + elseif(WIN32) + include_directories(${SERIALPORT_INCLUDE_DIRS}) + target_link_libraries(86Box ${SERIALPORT_LIBRARIES} SetupAPI) + else() + include_directories(${SERIALPORT_INCLUDE_DIRS}) + target_link_libraries(86Box ${SERIALPORT_LIBRARIES}) + endif() + target_sources(snd PRIVATE + snd_opl2board.c + snd_opl_opl2board.cpp +) +endif() add_subdirectory(resid-fp) target_link_libraries(86Box resid-fp) diff --git a/src/sound/snd_opl.c b/src/sound/snd_opl.c index 931277332..cddc18119 100644 --- a/src/sound/snd_opl.c +++ b/src/sound/snd_opl.c @@ -58,11 +58,12 @@ fm_driver_get(int chip_id, fm_drv_t *drv) drv->priv = device_add_inst(&ymf262_ymfm_device, fm_dev_inst[fm_driver][chip_id]++); } break; - +#ifdef USE_LIBSERIALPORT case FM_OPL2BOARD: *drv = ymfm_opl2board_drv; drv->priv = device_add_inst(&ym_opl2board_device, fm_dev_inst[fm_driver][chip_id]++); break; +#endif case FM_YMF289B: *drv = ymfm_drv; drv->priv = device_add_inst(&ymf289b_ymfm_device, fm_dev_inst[fm_driver][chip_id]++); diff --git a/src/sound/sound.c b/src/sound/sound.c index 851c849e4..7e6a1ac1c 100644 --- a/src/sound/sound.c +++ b/src/sound/sound.c @@ -153,7 +153,9 @@ static const SOUND_CARD sound_cards[] = { { &ct5880_device }, { &ad1881_device }, { &cs4297a_device }, +#ifdef USE_LIBSERIALPORT /*The following devices required LIBSERIALPORT*/ { &opl2board_device }, +#endif { NULL } // clang-format on }; From 44f7bf3baf57d4ef2b1a09e6aba2db6956751055 Mon Sep 17 00:00:00 2001 From: Jose Phillips Date: Sun, 8 Dec 2024 20:38:12 -0500 Subject: [PATCH 22/24] Fix build for mac and linux --- .ci/build.sh | 5 ++++- cmake/llvm-macos-aarch64.cmake | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.ci/build.sh b/.ci/build.sh index bf23f5d38..5a829646a 100755 --- a/.ci/build.sh +++ b/.ci/build.sh @@ -525,6 +525,9 @@ then cmake_flags_extra="$cmake_flags_extra -D MOLTENVK=ON -D \"MOLTENVK_INCLUDE_DIR=$macports\"" fi + # Enable Libserialport + cmake_flags_extra="$cmake_flags_extra -D \"LIBSERIALPORT_ROOT=$macports\"" + # Install dependencies only if we're in a new build and/or MacPorts prefix. if check_buildtag "$(basename "$macports")" then @@ -622,7 +625,7 @@ else # ...and the ones we do want listed. Non-dev packages fill missing spots on the list. libpkgs="" longest_libpkg=0 - for pkg in libc6-dev libstdc++6 libopenal-dev libfreetype6-dev libx11-dev libsdl2-dev libpng-dev librtmidi-dev qtdeclarative5-dev libwayland-dev libevdev-dev libxkbcommon-x11-dev libglib2.0-dev libslirp-dev libfaudio-dev libaudio-dev libjack-jackd2-dev libpipewire-0.3-dev libsamplerate0-dev libsndio-dev libvdeplug-dev libfluidsynth-dev libsndfile1-dev + for pkg in libc6-dev libstdc++6 libopenal-dev libfreetype6-dev libx11-dev libsdl2-dev libpng-dev librtmidi-dev qtdeclarative5-dev libwayland-dev libevdev-dev libxkbcommon-x11-dev libglib2.0-dev libslirp-dev libfaudio-dev libaudio-dev libjack-jackd2-dev libpipewire-0.3-dev libsamplerate0-dev libsndio-dev libvdeplug-dev libfluidsynth-dev libsndfile1-dev libserialport-dev do libpkgs="$libpkgs $pkg:$arch_deb" length=$(echo -n $pkg | sed 's/-dev$//' | sed "s/qtdeclarative/qt/" | wc -c) diff --git a/cmake/llvm-macos-aarch64.cmake b/cmake/llvm-macos-aarch64.cmake index df67ad45b..05f11b6a1 100644 --- a/cmake/llvm-macos-aarch64.cmake +++ b/cmake/llvm-macos-aarch64.cmake @@ -18,5 +18,6 @@ string(APPEND CMAKE_C_FLAGS_INIT " -march=armv8.5-a+simd") string(APPEND CMAKE_CXX_FLAGS_INIT " -march=armv8.5-a+simd") +string(APPEND ) include(${CMAKE_CURRENT_LIST_DIR}/flags-gcc.cmake) From 8239b2c58719425a979f2e110e42318b5861bc2e Mon Sep 17 00:00:00 2001 From: Jose Phillips Date: Sun, 8 Dec 2024 20:40:00 -0500 Subject: [PATCH 23/24] Update llvm-macos-aarch64.cmake --- cmake/llvm-macos-aarch64.cmake | 1 - 1 file changed, 1 deletion(-) diff --git a/cmake/llvm-macos-aarch64.cmake b/cmake/llvm-macos-aarch64.cmake index 05f11b6a1..df67ad45b 100644 --- a/cmake/llvm-macos-aarch64.cmake +++ b/cmake/llvm-macos-aarch64.cmake @@ -18,6 +18,5 @@ string(APPEND CMAKE_C_FLAGS_INIT " -march=armv8.5-a+simd") string(APPEND CMAKE_CXX_FLAGS_INIT " -march=armv8.5-a+simd") -string(APPEND ) include(${CMAKE_CURRENT_LIST_DIR}/flags-gcc.cmake) From 402d99da5958870f3c0c9f5a7e739c5c56f4b5b9 Mon Sep 17 00:00:00 2001 From: Jose Phillips Date: Sun, 8 Dec 2024 21:53:37 -0500 Subject: [PATCH 24/24] Fix on CI Builds for Windows and Linux --- .ci/AppImageBuilder.yml | 1 + .ci/dependencies_msys.txt | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.ci/AppImageBuilder.yml b/.ci/AppImageBuilder.yml index 64f8f91ed..7f312baae 100644 --- a/.ci/AppImageBuilder.yml +++ b/.ci/AppImageBuilder.yml @@ -72,6 +72,7 @@ AppDir: - libxkbcommon-x11-0 # if QT:BOOL=ON - qtwayland5 # if QT:BOOL=ON - zlib1g + - libserialport0 files: exclude: - etc diff --git a/.ci/dependencies_msys.txt b/.ci/dependencies_msys.txt index 766aadda3..b6c0979e2 100644 --- a/.ci/dependencies_msys.txt +++ b/.ci/dependencies_msys.txt @@ -14,4 +14,4 @@ qt5-static qt5-translations vulkan-headers libsndfile -libserialport \ No newline at end of file +libserialport