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.

This commit is contained in:
OBattler
2020-01-19 05:45:05 +01:00
parent 928010de71
commit 0cb2fa034c
11 changed files with 489 additions and 209 deletions

View File

@@ -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, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* 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 <stdio.h>
#include <stdint.h>
@@ -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];
@@ -290,6 +289,7 @@ midi_in_device_get_from_internal_name(char *s)
return 0;
}
void
midi_in_device_init()
{
@@ -298,6 +298,7 @@ midi_in_device_init()
midi_input_device_last = midi_input_device_current;
}
void
midi_raw_out_rt_byte(uint8_t val)
{
@@ -308,10 +309,11 @@ midi_raw_out_rt_byte(uint8_t val)
return;
midi_in->midi_cmd_r = val << 24;
pclog("Play RT Byte msg\n");
/* 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)
{
@@ -319,18 +321,17 @@ midi_raw_out_thru_rt_byte(uint8_t val)
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;
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;
}
}

View File

@@ -40,6 +40,18 @@ typedef struct midi_device_t
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

View File

@@ -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,6 +880,9 @@ 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*/
@@ -886,10 +894,10 @@ static uint8_t es1371_pci_read(int func, int addr, void *p)
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 0x08: return 0x02; /* Revision ID */
case 0x09: return 0x00; /* Multimedia audio device */
case 0x0a: return 0x01;
case 0x0b: return 0x04;
@@ -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));

View File

@@ -1175,9 +1175,8 @@ void *gus_init(const device_t *info)
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;
}
@@ -1257,6 +1256,9 @@ static const device_config_t gus_config[] = {
}
}
},
{
"receive_input", "Receive input (SB MIDI)", CONFIG_BINARY, "", 1
},
{
"", "", -1
}

View File

@@ -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, <http://pcem-emulator.co.uk/>
* DOSBox Team,
* Miran Grca, <mgrca8@gmail.com>
* TheCollector1995, <mariogplayer@gmail.com>
*
* 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 <stdarg.h>
#include <stdint.h>
@@ -39,9 +39,11 @@
#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};
enum {
STATUS_OUTPUT_NOT_READY = 0x40,
STATUS_INPUT_NOT_READY = 0x80
@@ -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,7 +1286,7 @@ MPU401_NotesOff(mpu_t *mpu, int i)
/*Input handler for SysEx */
static int
int
MPU401_InputSysex(void *p, uint8_t *buffer, uint32_t len, int abort)
{
mpu_t *mpu = (mpu_t *)p;
@@ -1328,7 +1331,7 @@ MPU401_InputSysex(void *p, uint8_t *buffer, uint32_t len, int abort)
/*Input handler for MIDI*/
static void
void
MPU401_InputMsg(void *p, uint8_t *msg)
{
mpu_t *mpu = (mpu_t *)p;
@@ -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;
@@ -1575,6 +1578,9 @@ mpu401_init(mpu_t *mpu, uint16_t addr, int irq, int mode)
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);
}
@@ -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
};

View File

@@ -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, <http://pcem-emulator.co.uk/>
* DOSBox Team,
* Miran Grca, <mgrca8@gmail.com>
* TheCollector1995, <mariogplayer@gmail.com>
* 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);

View File

@@ -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, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* TheCollector1995, <mariogplayer@gmail.com>
*
* Copyright 2008-2019 Sarah Walker.
* Copyright 2016-2019 Miran Grca.
* Copyright 2008-2020 Sarah Walker.
* Copyright 2016-2020 Miran Grca.
*/
#include <stdarg.h>
#include <stdint.h>
@@ -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
@@ -1043,13 +1043,12 @@ void *sb_1_init()
}
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
@@ -1074,14 +1073,13 @@ void *sb_15_init()
}
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
}

View File

@@ -842,6 +842,11 @@ sb_dsp_input_msg(void *p, uint8_t *msg)
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;

View File

@@ -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, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2008-2018 Sarah Walker.
* Copyright 2016-2018 Miran Grca.
* Copyright 2008-2020 Sarah Walker.
* Copyright 2016-2020 Miran Grca.
*/
#include <stdarg.h>
#include <stdint.h>
@@ -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);
}

View File

@@ -137,6 +137,7 @@ 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)
{
@@ -144,37 +145,22 @@ plat_midi_in_callback(HMIDIIN hMidiIn, UINT wMsg, DWORD_PTR dwInstance, DWORD_PT
(((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);
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;
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);
midi_in_sysex(sysex, len);
midiInUnprepareHeader(hMidiIn, hdr, sizeof(*hdr));
hdr->dwBytesRecorded = 0;
@@ -188,6 +174,7 @@ plat_midi_in_callback(HMIDIIN hMidiIn, UINT wMsg, DWORD_PTR dwInstance, DWORD_PT
}
}
void
plat_midi_input_init(void)
{
@@ -221,6 +208,7 @@ plat_midi_input_init(void)
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)
{