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:
240
src/sound/midi.c
240
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, <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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user