From 0cb2fa034c7e8871d4b789021c6bf89ef7ea1e49 Mon Sep 17 00:00:00 2001 From: OBattler Date: Sun, 19 Jan 2020 05:45:05 +0100 Subject: [PATCH] Fixed some bugs and warnings, and cleaned-up and reworked the MIDI input stuff so that MIDI input can go to multiple devices at a time (each device allows configuring, whether or not it should receive MIDI input), and fixed MIDI input on the Sound Blaster 16/AWE32's built-in MPU-401. --- src/sound/midi.c | 270 ++++++++++++++++++++++++++++++++++----- src/sound/midi.h | 43 +++++-- src/sound/snd_audiopci.c | 40 +++--- src/sound/snd_gus.c | 18 +-- src/sound/snd_mpu401.c | 64 +++++++--- src/sound/snd_mpu401.h | 18 ++- src/sound/snd_sb.c | 105 ++++++++------- src/sound/snd_sb_dsp.c | 10 +- src/sound/sound.c | 15 ++- src/video/vid_svga.c | 8 +- src/win/win_midi.c | 107 +++++++--------- 11 files changed, 489 insertions(+), 209 deletions(-) diff --git a/src/sound/midi.c b/src/sound/midi.c index 31a8b86bf..709b83faa 100644 --- a/src/sound/midi.c +++ b/src/sound/midi.c @@ -8,17 +8,17 @@ * * MIDI device core module. * - * Version: @(#)midi.c 1.0.2 2018/12/31 + * Version: @(#)midi.c 1.0.3 2020/01/19 * * Authors: Sarah Walker, * Miran Grca, * Bit, * DOSBox Team, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. - * Copyright 2016-2018 Bit. - * Copyright 2008-2018 DOSBox Team. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. + * Copyright 2016-2020 Bit. + * Copyright 2008-2020 DOSBox Team. */ #include #include @@ -47,9 +47,8 @@ static int midi_input_device_last = 0; midi_t *midi = NULL, *midi_in = NULL; -void (*input_msg)(void *p, uint8_t *msg); -int (*input_sysex)(void *p, uint8_t *buffer, uint32_t len, int abort); -void *midi_in_p; +midi_in_handler_t *mih_first = NULL, *mih_last = NULL, + *mih_cur = NULL; uint8_t MIDI_InSysexBuf[SYSEX_SIZE]; @@ -227,7 +226,7 @@ void play_msg(uint8_t *msg) { if (midi->m_out_device->play_msg) - midi->m_out_device->play_msg(msg); + midi->m_out_device->play_msg(msg); } @@ -235,7 +234,7 @@ void play_sysex(uint8_t *sysex, unsigned int len) { if (midi->m_out_device->play_sysex) - midi->m_out_device->play_sysex(sysex, len); + midi->m_out_device->play_sysex(sysex, len); } @@ -290,6 +289,7 @@ midi_in_device_get_from_internal_name(char *s) return 0; } + void midi_in_device_init() { @@ -298,39 +298,40 @@ midi_in_device_init() midi_input_device_last = midi_input_device_current; } + void midi_raw_out_rt_byte(uint8_t val) { - if (!midi_in->midi_realtime) - return; - - if ((!midi_in->midi_clockout && (val == 0xf8))) + if (!midi_in->midi_realtime) return; - midi_in->midi_cmd_r = val << 24; - pclog("Play RT Byte msg\n"); - play_msg((uint8_t *)&midi_in->midi_cmd_r); + if ((!midi_in->midi_clockout && (val == 0xf8))) + return; + + midi_in->midi_cmd_r = val << 24; + /* pclog("Play RT Byte msg\n"); */ + play_msg((uint8_t *)&midi_in->midi_cmd_r); } + void midi_raw_out_thru_rt_byte(uint8_t val) { - if (midi_in->thruchan) - midi_raw_out_rt_byte(val); + if (midi_in->thruchan) + midi_raw_out_rt_byte(val); } + void midi_raw_out_byte(uint8_t val) { uint32_t passed_ticks; - if (!midi || !midi->m_out_device) { + if (!midi || !midi->m_out_device) return; - } - if ((midi->m_out_device->write && midi->m_out_device->write(val))) { + if ((midi->m_out_device->write && midi->m_out_device->write(val))) return; - } if (midi->midi_sysex_start) { passed_ticks = plat_get_ticks() - midi->midi_sysex_start; @@ -396,12 +397,223 @@ midi_raw_out_byte(uint8_t val) } } + void midi_clear_buffer(void) { - if (!midi) return; - midi->midi_pos = 0; - midi->midi_status = 0x00; - midi->midi_cmd_pos = 0; - midi->midi_cmd_len = 0; -} \ No newline at end of file + if (!midi) + return; + + midi->midi_pos = 0; + midi->midi_status = 0x00; + midi->midi_cmd_pos = 0; + midi->midi_cmd_len = 0; +} + + +void +midi_in_handler(int set, void (*msg)(void *p, uint8_t *msg), int (*sysex)(void *p, uint8_t *buffer, uint32_t len, int abort), void *p) +{ + midi_in_handler_t *temp = NULL, *next; + + if (set) { + /* Add MIDI IN handler. */ + if ((mih_first == NULL) && (mih_last != NULL)) + fatal("Last MIDI IN handler present with no first MIDI IN handler\n"); + + if ((mih_first != NULL) && (mih_last == NULL)) + fatal("First MIDI IN handler present with no last MIDI IN handler\n"); + + temp = (midi_in_handler_t *) malloc(sizeof(midi_in_handler_t)); + memset(temp, 0, sizeof(midi_in_handler_t)); + temp->msg = msg; + temp->sysex = sysex; + temp->p = p; + + if (mih_last == NULL) + mih_first = mih_last = temp; + else { + temp->prev = mih_last; + mih_last = temp; + } + } else if ((mih_first != NULL) && (mih_last != NULL)) { + temp = mih_first; + + while(1) { + if (temp == NULL) + break; + + if ((temp->msg == msg) && (temp->sysex == sysex) && (temp->p == p)) { + if (temp->prev != NULL) + temp->prev->next = temp->next; + + if (temp->next != NULL) + temp->next->prev = temp->prev; + + next = temp->next; + + if (temp == mih_first) { + mih_first = NULL; + if (next == NULL) + mih_last = NULL; + } + + if (temp == mih_last) + mih_last = NULL; + + free(temp); + temp = next; + + if (next == NULL) + break; + } + } + } +} + + +void +midi_in_handlers_clear(void) +{ + midi_in_handler_t *temp = mih_first, *next; + + while(1) { + if (temp == NULL) + break; + + next = temp->next; + free(temp); + + temp = next; + + if (next == NULL) + break; + } + + mih_first = mih_last = NULL; +} + + +void +midi_in_msg(uint8_t *msg) +{ + midi_in_handler_t *temp = mih_first; + + while(1) { + if (temp == NULL) + break; + + if (temp->msg) + temp->msg(temp->p, msg); + + temp = temp->next; + + if (temp == NULL) + break; + } +} + + +static void +midi_start_sysex(uint8_t *buffer, uint32_t len) +{ + midi_in_handler_t *temp = mih_first; + + while(1) { + if (temp == NULL) + break; + + temp->cnt = 5; + temp->buf = buffer; + temp->len = len; + + temp = temp->next; + + if (temp == NULL) + break; + } +} + + +/* Returns: + 0 = All handlers have returnd 0; + 1 = There are still handlers to go. */ +static int +midi_do_sysex(void) +{ + midi_in_handler_t *temp = mih_first; + int ret, cnt_acc = 0; + + while(1) { + if (temp == NULL) + break; + + /* Do nothing if the handler has a zero count. */ + if ((temp->cnt > 0) || (temp->len > 0)) { + ret = 0; + if (temp->sysex) { + if (temp->cnt == 0) + ret = temp->sysex(temp->p, temp->buf, 0, 0); + else + ret = temp->sysex(temp->p, temp->buf, temp->len, 0); + } + + /* If count is 0 and length is 0, then this is just a finishing + call to temp->sysex(), so skip this entire block. */ + if (temp->cnt > 0) { + if (ret) { + /* Decrease or reset the counter. */ + if (temp->len == ret) + temp->cnt--; + else + temp->cnt = 5; + + /* Advance the buffer pointer and remember the + remaining length. */ + temp->buf += (temp->len - ret); + temp->len = ret; + } else { + /* Set count to 0 so that this handler will be + ignored on the next interation. */ + temp->cnt = 0; + + /* Reset the buffer pointer and length. */ + temp->buf = NULL; + temp->len = 0; + } + + /* If the remaining count is above zero, add it to the + accumulator. */ + if (temp->cnt > 0) + cnt_acc |= temp->cnt; + } + } + + temp = temp->next; + + if (temp == NULL) + break; + } + + /* Return 0 if all handlers have returned 0 or all the counts are otherwise 0. */ + if (cnt_acc == 0) + return 0; + else + return 1; +} + + +void +midi_in_sysex(uint8_t *buffer, uint32_t len) +{ + midi_start_sysex(buffer, len); + + while (1) { + /* This will return 0 if all theh handlers have either + timed out or otherwise indicated it is time to stop. */ + if (midi_do_sysex()) + plat_delay_ms(5); /* msec */ + else + break; + } +} diff --git a/src/sound/midi.h b/src/sound/midi.h index 8e516c2a3..a0e89a50d 100644 --- a/src/sound/midi.h +++ b/src/sound/midi.h @@ -34,12 +34,24 @@ void midi_in_device_init(); typedef struct midi_device_t { - void (*play_sysex)(uint8_t *sysex, unsigned int len); - void (*play_msg)(uint8_t *msg); - void (*poll)(); - int (*write)(uint8_t val); + void (*play_sysex)(uint8_t *sysex, unsigned int len); + void (*play_msg)(uint8_t *msg); + void (*poll)(); + int (*write)(uint8_t val); } midi_device_t; +typedef struct midi_in_handler_t +{ + uint8_t *buf; + int cnt; + uint32_t len; + + void (*msg)(void *p, uint8_t *msg); + int (*sysex)(void *p, uint8_t *buffer, uint32_t len, int abort); + struct midi_in_handler_t *p; + struct midi_in_handler_t *prev, *next; +} midi_in_handler_t; + typedef struct midi_t { uint8_t midi_rt_buf[8], midi_cmd_buf[8], @@ -53,15 +65,20 @@ typedef struct midi_t extern midi_t *midi, *midi_in; -void midi_init(midi_device_t* device); -void midi_in_init(midi_device_t* device, midi_t **mididev); -void midi_close(); -void midi_in_close(void); -void midi_raw_out_rt_byte(uint8_t val); -void midi_raw_out_thru_rt_byte(uint8_t val); -void midi_raw_out_byte(uint8_t val); -void midi_clear_buffer(void); -void midi_poll(); +extern void midi_init(midi_device_t* device); +extern void midi_in_init(midi_device_t* device, midi_t **mididev); +extern void midi_close(); +extern void midi_in_close(void); +extern void midi_raw_out_rt_byte(uint8_t val); +extern void midi_raw_out_thru_rt_byte(uint8_t val); +extern void midi_raw_out_byte(uint8_t val); +extern void midi_clear_buffer(void); +extern void midi_poll(); + +extern void midi_in_handler(int set, void (*msg)(void *p, uint8_t *msg), int (*sysex)(void *p, uint8_t *buffer, uint32_t len, int abort), void *p); +extern void midi_in_handlers_clear(void); +extern void midi_in_msg(uint8_t *msg); +extern void midi_in_sysex(uint8_t *buffer, uint32_t len); #if 0 #ifdef _WIN32 diff --git a/src/sound/snd_audiopci.c b/src/sound/snd_audiopci.c index f24a383d3..2068710a9 100644 --- a/src/sound/snd_audiopci.c +++ b/src/sound/snd_audiopci.c @@ -25,7 +25,7 @@ static float low_fir_es1371_coef[ES1371_NCoef]; typedef struct { - mpu_t mpu; + mpu_t mpu; uint8_t pci_command, pci_serr; @@ -84,6 +84,8 @@ typedef struct { int pos; int16_t buffer[SOUNDBUFLEN * 2]; + + int type; } es1371_t; @@ -130,10 +132,13 @@ typedef struct { #define INT_STATUS_DAC1 (1<<2) #define INT_STATUS_DAC2 (1<<1) +#define UART_CTRL_RXINTEN (1<<7) #define UART_CTRL_TXINTEN (1<<5) +#define UART_STATUS_RXINT (1<<7) #define UART_STATUS_TXINT (1<<2) #define UART_STATUS_TXRDY (1<<1) +#define UART_STATUS_RXRDY (1<<0) #define FORMAT_MONO_8 0 #define FORMAT_STEREO_8 1 @@ -875,40 +880,43 @@ static uint8_t es1371_pci_read(int func, int addr, void *p) //audiopci_log("ES1371 PCI read %08X PC=%08x\n", addr, cpu_state.pc); + if (addr > 0x3f) + return 0x00; + switch (addr) { case 0x00: return 0x74; /*Ensoniq*/ case 0x01: return 0x12; - case 0x02: return 0x71; /*ES1371*/ + case 0x02: return 0x71; /* ES1371 */ case 0x03: return 0x13; - + case 0x04: return es1371->pci_command; case 0x05: return es1371->pci_serr; - case 0x06: return 0x10; /*Supports ACPI*/ - case 0x07: return 0; + case 0x06: return 0x10; /* Supports support ACPI */ + case 0x07: return 0x00; - case 0x08: return 2; /*Revision ID*/ - case 0x09: return 0x00; /*Multimedia audio device*/ + case 0x08: return 0x02; /* Revision ID */ + case 0x09: return 0x00; /* Multimedia audio device */ case 0x0a: return 0x01; case 0x0b: return 0x04; - case 0x10: return 0x01 | (es1371->base_addr & 0xc0); /*memBaseAddr*/ + case 0x10: return 0x01 | (es1371->base_addr & 0xc0); /* memBaseAddr */ case 0x11: return es1371->base_addr >> 8; case 0x12: return es1371->base_addr >> 16; case 0x13: return es1371->base_addr >> 24; - case 0x2c: return 0x74; /*Subsystem vendor ID*/ + case 0x2c: return 0x74; /* Subsystem vendor ID */ case 0x2d: return 0x12; case 0x2e: return 0x71; case 0x2f: return 0x13; - + case 0x34: return 0xdc; /*Capabilites pointer*/ - + case 0x3c: return es1371->int_line; case 0x3d: return 0x01; /*INTA*/ - + case 0x3e: return 0xc; /*Minimum grant*/ case 0x3f: return 0x80; /*Maximum latency*/ @@ -1168,18 +1176,18 @@ static void es1371_poll(void *p) if (es1371->int_ctrl & INT_UART_EN) { audiopci_log("UART INT Enabled\n"); - if (es1371->uart_ctrl & 0x80) { /*We currently don't implement MIDI Input.*/ + if (es1371->uart_ctrl & UART_CTRL_RXINTEN) { /*We currently don't implement MIDI Input.*/ /*But if anything sets MIDI Input and Output together we'd have to take account of the MIDI Output case, and disable IRQ's and RX bits when MIDI Input is enabled as well but not in the MIDI Output portion*/ if (es1371->uart_ctrl & UART_CTRL_TXINTEN) es1371->int_status |= INT_STATUS_UART; else es1371->int_status &= ~INT_STATUS_UART; - } else if (!(es1371->uart_ctrl & 0x80) && ((es1371->uart_ctrl & UART_CTRL_TXINTEN))) { /*Or enable the UART IRQ and the respective TX bits only when the MIDI Output is enabled*/ + } else if (!(es1371->uart_ctrl & UART_CTRL_RXINTEN) && ((es1371->uart_ctrl & UART_CTRL_TXINTEN))) { /*Or enable the UART IRQ and the respective TX bits only when the MIDI Output is enabled*/ es1371->int_status |= INT_STATUS_UART; } - if (es1371->uart_ctrl & 0x80) { + if (es1371->uart_ctrl & UART_CTRL_RXINTEN) { if (es1371->uart_ctrl & UART_CTRL_TXINTEN) es1371->uart_status |= (UART_STATUS_TXINT | UART_STATUS_TXRDY); else @@ -1295,7 +1303,7 @@ static void generate_es1371_filter() low_fir_es1371_coef[n] /= gain; } -static void *es1371_init() +static void *es1371_init(const device_t *info) { es1371_t *es1371 = malloc(sizeof(es1371_t)); memset(es1371, 0, sizeof(es1371_t)); diff --git a/src/sound/snd_gus.c b/src/sound/snd_gus.c index 3df40d2a0..4bfb7e61a 100644 --- a/src/sound/snd_gus.c +++ b/src/sound/snd_gus.c @@ -1169,16 +1169,15 @@ void *gus_init(const device_t *info) io_sethandler(0x0100+gus->base, 0x0010, readgus, NULL, NULL, writegus, NULL, NULL, gus); io_sethandler(0x0506+gus->base, 0x0001, readgus, NULL, NULL, writegus, NULL, NULL, gus); io_sethandler(0x0388, 0x0002, readgus, NULL, NULL, writegus, NULL, NULL, gus); - timer_add(&gus->samp_timer, gus_poll_wave, gus, 1); - timer_add(&gus->timer_1, gus_poll_timer_1, gus, 1); - timer_add(&gus->timer_2, gus_poll_timer_2, gus, 1); + timer_add(&gus->samp_timer, gus_poll_wave, gus, 1); + timer_add(&gus->timer_1, gus_poll_timer_1, gus, 1); + timer_add(&gus->timer_2, gus_poll_timer_2, gus, 1); sound_add_handler(gus_get_buffer, gus); - input_msg = gus_input_msg; - input_sysex = gus_input_sysex; - midi_in_p = gus; - + if (device_get_config_int("receive_input")) + midi_in_handler(1, gus_input_msg, gus_input_sysex, gus); + return gus; } @@ -1256,7 +1255,10 @@ static const device_config_t gus_config[] = { NULL } } - }, + }, + { + "receive_input", "Receive input (SB MIDI)", CONFIG_BINARY, "", 1 + }, { "", "", -1 } diff --git a/src/sound/snd_mpu401.c b/src/sound/snd_mpu401.c index b2be5e1cd..58602fc6f 100644 --- a/src/sound/snd_mpu401.c +++ b/src/sound/snd_mpu401.c @@ -8,16 +8,16 @@ * * Roland MPU-401 emulation. * - * Version: @(#)snd_mpu401.c 1.0.18 2018/10/18 + * Version: @(#)snd_mpu401.c 1.0.19 2020/01/19 * * Authors: Sarah Walker, * DOSBox Team, * Miran Grca, * TheCollector1995, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2008-2018 DOSBox Team. - * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2008-2020 DOSBox Team. + * Copyright 2016-2020 Miran Grca. */ #include #include @@ -39,8 +39,10 @@ #include "snd_mpu401.h" #include "midi.h" -static uint32_t MPUClockBase[8] = {48,72,96,120,144,168,192}; -static uint8_t cth_data[16] = {0,0,0,0,1,0,0,0,1,0,1,0,1,1,1,0}; + +static uint32_t MPUClockBase[8] = {48,72,96,120,144,168,192}; +static uint8_t cth_data[16] = {0,0,0,0,1,0,0,0,1,0,1,0,1,1,1,0}; + enum { STATUS_OUTPUT_NOT_READY = 0x40, @@ -50,6 +52,7 @@ enum { int mpu401_standalone_enable = 0; + static void MPU401_WriteCommand(mpu_t *mpu, uint8_t val); static void MPU401_IntelligentOut(mpu_t *mpu, uint8_t track); static void MPU401_EOIHandler(void *priv); @@ -1283,8 +1286,8 @@ MPU401_NotesOff(mpu_t *mpu, int i) /*Input handler for SysEx */ -static int -MPU401_InputSysex(void *p, uint8_t *buffer, uint32_t len, int abort) +int +MPU401_InputSysex(void *p, uint8_t *buffer, uint32_t len, int abort) { mpu_t *mpu = (mpu_t *)p; int i; @@ -1328,8 +1331,8 @@ MPU401_InputSysex(void *p, uint8_t *buffer, uint32_t len, int abort) /*Input handler for MIDI*/ -static void -MPU401_InputMsg(void *p, uint8_t *msg) +void +MPU401_InputMsg(void *p, uint8_t *msg) { mpu_t *mpu = (mpu_t *)p; int i, tick; @@ -1550,7 +1553,7 @@ MPU401_InputMsg(void *p, uint8_t *msg) void -mpu401_init(mpu_t *mpu, uint16_t addr, int irq, int mode) +mpu401_init(mpu_t *mpu, uint16_t addr, int irq, int mode, int receive_input) { mpu->status = STATUS_INPUT_NOT_READY; mpu->irq = irq; @@ -1570,11 +1573,14 @@ mpu401_init(mpu_t *mpu, uint16_t addr, int irq, int mode) mpu401_read, NULL, NULL, mpu401_write, NULL, NULL, mpu); io_sethandler(0x2A20, 16, NULL, NULL, NULL, imf_write, NULL, NULL, mpu); - timer_add(&mpu->mpu401_event_callback, MPU401_Event, mpu, 0); - timer_add(&mpu->mpu401_eoi_callback, MPU401_EOIHandler, mpu, 0); - timer_add(&mpu->mpu401_reset_callback, MPU401_ResetDone, mpu, 0); + timer_add(&mpu->mpu401_event_callback, MPU401_Event, mpu, 0); + timer_add(&mpu->mpu401_eoi_callback, MPU401_EOIHandler, mpu, 0); + timer_add(&mpu->mpu401_reset_callback, MPU401_ResetDone, mpu, 0); MPU401_Reset(mpu); + + if (receive_input) + midi_in_handler(1, MPU401_InputMsg, MPU401_InputSysex, mpu); } @@ -1643,7 +1649,7 @@ mpu401_standalone_init(const device_t *info) mpu = malloc(sizeof(mpu_t)); memset(mpu, 0, sizeof(mpu_t)); - + mpu401_log("mpu_init\n"); if (info->flags & DEVICE_MCA) { @@ -1657,11 +1663,7 @@ mpu401_standalone_init(const device_t *info) irq = device_get_config_int("irq"); } - input_msg = MPU401_InputMsg; - input_sysex = MPU401_InputSysex; - midi_in_p = mpu; - - mpu401_init(mpu, base, irq, M_INTELLIGENT); + mpu401_init(mpu, base, irq, M_INTELLIGENT, device_get_config_int("receive_input")); return(mpu); } @@ -1718,6 +1720,26 @@ static const device_config_t mpu401_standalone_config[] = } } }, + { + .name = "receive_input", + .description = "Receive input", + .type = CONFIG_BINARY, + .default_int = 1 + }, + { + "", "", -1 + } +}; + + +static const device_config_t mpu401_standalone_mca_config[] = +{ + { + .name = "receive_input", + .description = "Receive input", + .type = CONFIG_BINARY, + .default_int = 1 + }, { "", "", -1 } @@ -1741,5 +1763,5 @@ const device_t mpu401_mca_device = { NULL, NULL, NULL, - NULL + mpu401_standalone_mca_config }; diff --git a/src/sound/snd_mpu401.h b/src/sound/snd_mpu401.h index ce2ce54bf..43ccc9bdb 100644 --- a/src/sound/snd_mpu401.h +++ b/src/sound/snd_mpu401.h @@ -8,16 +8,16 @@ * * Roland MPU-401 emulation. * - * Version: @(#)sound_mpu401.h 1.0.4 2018/09/31 + * Version: @(#)sound_mpu401.h 1.0.5 2020/01/19 * * Author: Sarah Walker, * DOSBox Team, * Miran Grca, * TheCollector1995, - * Copyright 2008-2018 Sarah Walker. - * Copyright 2008-2018 DOSBox Team. - * Copyright 2016-2018 Miran Grca. - * Copyright 2016-2018 TheCollector1995. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2008-2020 DOSBox Team. + * Copyright 2016-2020 Miran Grca. + * Copyright 2016-2020 TheCollector1995. */ #define MPU401_VERSION 0x15 @@ -142,11 +142,15 @@ typedef struct mpu_t mpu401_reset_callback; } mpu_t; -extern int mpu401_standalone_enable; +extern int mpu401_standalone_enable, mpu401_already_loaded; + extern const device_t mpu401_device; extern const device_t mpu401_mca_device; extern uint8_t MPU401_ReadData(mpu_t *mpu); -extern void mpu401_init(mpu_t *mpu, uint16_t addr, int irq, int mode); +extern void mpu401_init(mpu_t *mpu, uint16_t addr, int irq, int mode, int receive_input); extern void mpu401_device_add(void); + +extern int MPU401_InputSysex(void *p, uint8_t *buffer, uint32_t len, int abort); +extern void MPU401_InputMsg(void *p, uint8_t *msg); diff --git a/src/sound/snd_sb.c b/src/sound/snd_sb.c index f86e85cd9..d1d43b3d4 100644 --- a/src/sound/snd_sb.c +++ b/src/sound/snd_sb.c @@ -8,14 +8,14 @@ * * Sound Blaster emulation. * - * Version: @(#)sound_sb.c 1.0.16 2019/09/27 + * Version: @(#)sound_sb.c 1.0.17 2020/01/19 * * Authors: Sarah Walker, * Miran Grca, * TheCollector1995, * - * Copyright 2008-2019 Sarah Walker. - * Copyright 2016-2019 Miran Grca. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. */ #include #include @@ -1018,7 +1018,7 @@ void sb_pro_mcv_write(int port, uint8_t val, void *p) sb_dsp_setdma8(&sb->dsp, sb->pos_regs[4] & 3); } -void *sb_1_init() +void *sb_1_init(const device_t *info) { /*sb1/2 port mappings, 210h to 260h in 10h steps 2x0 to 2x3 -> CMS chip @@ -1042,14 +1042,13 @@ void *sb_1_init() io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); } sound_add_handler(sb_get_buffer_sb2, sb); - - input_msg = sb_dsp_input_msg; - input_sysex = sb_dsp_input_sysex; - midi_in_p = &sb->dsp; + + if (device_get_config_int("receive_input")) + midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); return sb; } -void *sb_15_init() +void *sb_15_init(const device_t *info) { /*sb1/2 port mappings, 210h to 260h in 10h steps 2x0 to 2x3 -> CMS chip @@ -1073,15 +1072,14 @@ void *sb_15_init() io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl); } sound_add_handler(sb_get_buffer_sb2, sb); - - input_msg = sb_dsp_input_msg; - input_sysex = sb_dsp_input_sysex; - midi_in_p = &sb->dsp; - + + if (device_get_config_int("receive_input")) + midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); + return sb; } -void *sb_mcv_init() +void *sb_mcv_init(const device_t *info) { /*sb1/2 port mappings, 210h to 260h in 10h steps 2x6, 2xA, 2xC, 2xE -> DSP chip @@ -1102,13 +1100,12 @@ void *sb_mcv_init() sb->pos_regs[0] = 0x84; sb->pos_regs[1] = 0x50; - input_msg = sb_dsp_input_msg; - input_sysex = sb_dsp_input_sysex; - midi_in_p = &sb->dsp; - + if (device_get_config_int("receive_input")) + midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); + return sb; } -void *sb_2_init() +void *sb_2_init(const device_t *info) { /*sb2 port mappings. 220h or 240h. 2x0 to 2x3 -> CMS chip @@ -1153,14 +1150,13 @@ void *sb_2_init() else sound_add_handler(sb_get_buffer_sb2, sb); - input_msg = sb_dsp_input_msg; - input_sysex = sb_dsp_input_sysex; - midi_in_p = &sb->dsp; + if (device_get_config_int("receive_input")) + midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); return sb; } -void *sb_pro_v1_init() +void *sb_pro_v1_init(const device_t *info) { /*sbpro port mappings. 220h or 240h. 2x0 to 2x3 -> FM chip, Left and Right (9*2 voices) @@ -1190,14 +1186,13 @@ void *sb_pro_v1_init() io_sethandler(addr+4, 0x0002, sb_ct1345_mixer_read, NULL, NULL, sb_ct1345_mixer_write, NULL, NULL, sb); sound_add_handler(sb_get_buffer_sbpro, sb); - input_msg = sb_dsp_input_msg; - input_sysex = sb_dsp_input_sysex; - midi_in_p = &sb->dsp; + if (device_get_config_int("receive_input")) + midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); return sb; } -void *sb_pro_v2_init() +void *sb_pro_v2_init(const device_t *info) { /*sbpro port mappings. 220h or 240h. 2x0 to 2x3 -> FM chip (18 voices) @@ -1226,14 +1221,13 @@ void *sb_pro_v2_init() io_sethandler(addr+4, 0x0002, sb_ct1345_mixer_read, NULL, NULL, sb_ct1345_mixer_write, NULL, NULL, sb); sound_add_handler(sb_get_buffer_sbpro, sb); - input_msg = sb_dsp_input_msg; - input_sysex = sb_dsp_input_sysex; - midi_in_p = &sb->dsp; + if (device_get_config_int("receive_input")) + midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); return sb; } -void *sb_pro_mcv_init() +void *sb_pro_mcv_init(const device_t *info) { /*sbpro port mappings. 220h or 240h. 2x0 to 2x3 -> FM chip, Left and Right (18 voices) @@ -1255,14 +1249,13 @@ void *sb_pro_mcv_init() sb->pos_regs[0] = 0x03; sb->pos_regs[1] = 0x51; - input_msg = sb_dsp_input_msg; - input_sysex = sb_dsp_input_sysex; - midi_in_p = &sb->dsp; + if (device_get_config_int("receive_input")) + midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); return sb; } -void *sb_16_init() +void *sb_16_init(const device_t *info) { sb_t *sb = malloc(sizeof(sb_t)); uint16_t addr = device_get_config_hex16("base"); @@ -1288,15 +1281,13 @@ void *sb_16_init() if (mpu_addr) { sb->mpu = (mpu_t *) malloc(sizeof(mpu_t)); memset(sb->mpu, 0, sizeof(mpu_t)); - mpu401_init(sb->mpu, device_get_config_hex16("base401"), device_get_config_int("irq"), M_UART); - sb_dsp_set_mpu(sb->mpu); + mpu401_init(sb->mpu, device_get_config_hex16("base401"), device_get_config_int("irq"), M_UART, device_get_config_int("receive_input401")); } else sb->mpu = NULL; + sb_dsp_set_mpu(sb->mpu); - - input_msg = sb_dsp_input_msg; - input_sysex = sb_dsp_input_sysex; - midi_in_p = &sb->dsp; + if (device_get_config_int("receive_input")) + midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); return sb; } @@ -1306,7 +1297,7 @@ int sb_awe32_available() return rom_present(L"roms/sound/awe32.raw"); } -void *sb_awe32_init() +void *sb_awe32_init(const device_t *info) { sb_t *sb = malloc(sizeof(sb_t)); uint16_t addr = device_get_config_hex16("base"); @@ -1336,15 +1327,14 @@ void *sb_awe32_init() if (mpu_addr) { sb->mpu = (mpu_t *) malloc(sizeof(mpu_t)); memset(sb->mpu, 0, sizeof(mpu_t)); - mpu401_init(sb->mpu, device_get_config_hex16("base401"), device_get_config_int("irq"), M_UART); + mpu401_init(sb->mpu, device_get_config_hex16("base401"), device_get_config_int("irq"), M_UART, device_get_config_int("receive_input401")); sb_dsp_set_mpu(sb->mpu); } else sb->mpu = NULL; emu8k_init(&sb->emu8k, emu_addr, onboard_ram); - input_msg = sb_dsp_input_msg; - input_sysex = sb_dsp_input_sysex; - midi_in_p = &sb->dsp; + if (device_get_config_int("receive_input")) + midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp); return sb; } @@ -1438,6 +1428,9 @@ static const device_config_t sb_config[] = { "opl", "Enable OPL", CONFIG_BINARY, "", 1 }, + { + "receive_input", "Receive input (SB MIDI)", CONFIG_BINARY, "", 1 + }, { "", "", -1 } @@ -1479,6 +1472,9 @@ static const device_config_t sb_mcv_config[] = { "opl", "Enable OPL", CONFIG_BINARY, "", 1 }, + { + "receive_input", "Receive input (SB MIDI)", CONFIG_BINARY, "", 1 + }, { "", "", -1 } @@ -1537,6 +1533,9 @@ static const device_config_t sb_pro_config[] = { "opl", "Enable OPL", CONFIG_BINARY, "", 1 }, + { + "receive_input", "Receive input (SB MIDI)", CONFIG_BINARY, "", 1 + }, { "", "", -1 } @@ -1638,6 +1637,12 @@ static const device_config_t sb_16_config[] = { "opl", "Enable OPL", CONFIG_BINARY, "", 1 }, + { + "receive_input", "Receive input (SB MIDI)", CONFIG_BINARY, "", 1 + }, + { + "receive_input401", "Receive input (MPU-401)", CONFIG_BINARY, "", 0 + }, { "", "", -1 } @@ -1782,6 +1787,12 @@ static const device_config_t sb_awe32_config[] = { "opl", "Enable OPL", CONFIG_BINARY, "", 1 }, + { + "receive_input", "Receive input (SB MIDI)", CONFIG_BINARY, "", 1 + }, + { + "receive_input401", "Receive input (MPU-401)", CONFIG_BINARY, "", 0 + }, { "", "", -1 } diff --git a/src/sound/snd_sb_dsp.c b/src/sound/snd_sb_dsp.c index dc40de587..7ce08bfb9 100644 --- a/src/sound/snd_sb_dsp.c +++ b/src/sound/snd_sb_dsp.c @@ -841,7 +841,12 @@ sb_dsp_input_msg(void *p, uint8_t *msg) sb_dsp_t *dsp = (sb_dsp_t *) p; sb_dsp_log("MIDI in sysex = %d, uart irq = %d, msg = %d\n", dsp->midi_in_sysex, dsp->uart_irq, msg[3]); - + + if (!dsp->uart_irq && !dsp->midi_in_poll && (mpu != NULL)) { + MPU401_InputMsg(mpu, msg); + return; + } + if (dsp->midi_in_sysex) { return; } @@ -867,6 +872,9 @@ sb_dsp_input_sysex(void *p, uint8_t *buffer, uint32_t len, int abort) uint32_t i; + if (!dsp->uart_irq && !dsp->midi_in_poll && (mpu != NULL)) + return MPU401_InputSysex(mpu, buffer, len, abort); + if (abort) { dsp->midi_in_sysex = 0; return 0; diff --git a/src/sound/sound.c b/src/sound/sound.c index d3de46351..9ccdefa99 100644 --- a/src/sound/sound.c +++ b/src/sound/sound.c @@ -8,13 +8,13 @@ * * Sound emulation core. * - * Version: @(#)sound.c 1.0.27 2019/02/06 + * Version: @(#)sound.c 1.0.28 2020/01/19 * * Authors: Sarah Walker, * Miran Grca, * - * Copyright 2008-2018 Sarah Walker. - * Copyright 2016-2018 Miran Grca. + * Copyright 2008-2020 Sarah Walker. + * Copyright 2016-2020 Miran Grca. */ #include #include @@ -441,7 +441,7 @@ sound_reset(void) sound_realloc_buffers(); midi_device_init(); - midi_in_device_init(); + midi_in_device_init(); inital(); timer_add(&sound_poll_timer, sound_poll, NULL, 1); @@ -455,13 +455,20 @@ sound_reset(void) void sound_card_reset(void) { + /* Reset the MPU-401 already loaded flag and the chain of input/output handlers. */ + midi_in_handlers_clear(); + sound_card_init(); + if (mpu401_standalone_enable) mpu401_device_add(); + if (GUS) device_add(&gus_device); + if (GAMEBLASTER) device_add(&cms_device); + if (SSI2001) device_add(&ssi2001_device); } diff --git a/src/video/vid_svga.c b/src/video/vid_svga.c index 6b3044aef..d37f62a16 100644 --- a/src/video/vid_svga.c +++ b/src/video/vid_svga.c @@ -700,11 +700,11 @@ svga_poll(void *p) svga->ma = svga->maback; } } - - svga->hsync_divisor = !svga->hsync_divisor; - if (svga->hsync_divisor && (svga->crtc[0x17] & 4)) - return; + svga->hsync_divisor = !svga->hsync_divisor; + + if (svga->hsync_divisor && (svga->crtc[0x17] & 4)) + return; svga->vc++; svga->vc &= 2047; diff --git a/src/win/win_midi.c b/src/win/win_midi.c index 256ab6a5e..dace62b0e 100644 --- a/src/win/win_midi.c +++ b/src/win/win_midi.c @@ -18,7 +18,7 @@ typedef struct HANDLE m_event; HMIDIOUT midi_out_device; - HMIDIIN midi_in_device; + HMIDIIN midi_in_device; MIDIHDR m_hdr; } plat_midi_t; @@ -137,57 +137,44 @@ plat_midi_write(uint8_t val) return 0; } + void CALLBACK plat_midi_in_callback(HMIDIIN hMidiIn, UINT wMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) { - uint8_t msg[4] = {((dwParam1&0xff)),(((dwParam1&0xff00)>>8)), - (((dwParam1&0xff0000)>>16)),MIDI_evt_len[((dwParam1&0xff))]}; - uint8_t *sysex; - uint32_t len; - int cnt; - MIDIHDR *hdr; - switch (wMsg) { - case MM_MIM_DATA: /* 0x3C3 - midi message */ - input_msg(midi_in_p, msg); - break; - case MM_MIM_OPEN: /* 0x3C1 */ - break; - case MM_MIM_CLOSE: /* 0x3C2 */ - break; - case MM_MIM_LONGDATA: /* 0x3C4 - sysex */ - hdr = (MIDIHDR *)dwParam1; - sysex = (uint8_t *)hdr->lpData; - len = (uint32_t)hdr->dwBytesRecorded; - cnt = 5; - while (cnt) { /*abort if timed out*/ - int ret = input_sysex(midi_in_p, sysex, len, 0); - if (!ret) { - len = 0; - break; - } - if (len==ret) - cnt--; - else - cnt = 5; - sysex += len-ret; - len = ret; - Sleep(5);/*msec*/ - } - if (len) - input_sysex(midi_in_p, sysex, 0, 0); - - midiInUnprepareHeader(hMidiIn, hdr, sizeof(*hdr)); - hdr->dwBytesRecorded = 0; - midiInPrepareHeader(hMidiIn, hdr, sizeof(*hdr)); - break; - case MM_MIM_ERROR: - case MM_MIM_LONGERROR: - break; - default: - break; - } + uint8_t msg[4] = { ((dwParam1 & 0xff)), (((dwParam1 & 0xff00) >> 8)), + (((dwParam1 & 0xff0000) >> 16)), MIDI_evt_len[((dwParam1 & 0xff))]}; + uint8_t *sysex; + uint32_t len; + MIDIHDR *hdr; + + switch (wMsg) { + case MM_MIM_DATA: /* 0x3C3 - midi message */ + midi_in_msg(msg); + break; + case MM_MIM_OPEN: /* 0x3C1 */ + break; + case MM_MIM_CLOSE: /* 0x3C2 */ + break; + case MM_MIM_LONGDATA: /* 0x3C4 - sysex */ + /* It is midi_in_sysex() that now does the loop. */ + hdr = (MIDIHDR *) dwParam1; + sysex = (uint8_t *) hdr->lpData; + len = (uint32_t) hdr->dwBytesRecorded; + midi_in_sysex(sysex, len); + + midiInUnprepareHeader(hMidiIn, hdr, sizeof(*hdr)); + hdr->dwBytesRecorded = 0; + midiInPrepareHeader(hMidiIn, hdr, sizeof(*hdr)); + break; + case MM_MIM_ERROR: + case MM_MIM_LONGERROR: + break; + default: + break; + } } + void plat_midi_input_init(void) { @@ -197,11 +184,11 @@ plat_midi_input_init(void) memset(pm_in, 0, sizeof(plat_midi_t)); pm_in->midi_input_id = config_get_int(MIDI_INPUT_NAME, "midi_input", 0); - - hr = MMSYSERR_NOERROR; - + + hr = MMSYSERR_NOERROR; + hr = midiInOpen(&pm_in->midi_in_device, pm_in->midi_input_id, - (uintptr_t) plat_midi_in_callback, 0, CALLBACK_FUNCTION); + (uintptr_t) plat_midi_in_callback, 0, CALLBACK_FUNCTION); if (hr != MMSYSERR_NOERROR) { printf("midiInOpen error - %08X\n", hr); pm_in->midi_input_id = 0; @@ -212,15 +199,16 @@ plat_midi_input_init(void) return; } } - - pm_in->m_hdr.lpData = (char*)&MIDI_InSysexBuf[0]; - pm_in->m_hdr.dwBufferLength = SYSEX_SIZE; - pm_in->m_hdr.dwBytesRecorded = 0; - pm_in->m_hdr.dwUser = 0; - midiInPrepareHeader(pm_in->midi_in_device,&pm_in->m_hdr,sizeof(pm_in->m_hdr)); - midiInStart(pm_in->midi_in_device); + + pm_in->m_hdr.lpData = (char*)&MIDI_InSysexBuf[0]; + pm_in->m_hdr.dwBufferLength = SYSEX_SIZE; + pm_in->m_hdr.dwBytesRecorded = 0; + pm_in->m_hdr.dwUser = 0; + midiInPrepareHeader(pm_in->midi_in_device,&pm_in->m_hdr,sizeof(pm_in->m_hdr)); + midiInStart(pm_in->midi_in_device); } + void plat_midi_input_close(void) { @@ -235,6 +223,7 @@ plat_midi_input_close(void) } } + int plat_midi_in_get_num_devs(void) { @@ -249,4 +238,4 @@ plat_midi_in_get_dev_name(int num, char *s) midiInGetDevCaps(num, &caps, sizeof(caps)); strcpy(s, caps.szPname); -} \ No newline at end of file +}