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:
268
src/sound/midi.c
268
src/sound/midi.c
@@ -8,17 +8,17 @@
|
|||||||
*
|
*
|
||||||
* MIDI device core module.
|
* 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/>
|
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||||
* Miran Grca, <mgrca8@gmail.com>
|
* Miran Grca, <mgrca8@gmail.com>
|
||||||
* Bit,
|
* Bit,
|
||||||
* DOSBox Team,
|
* DOSBox Team,
|
||||||
*
|
*
|
||||||
* Copyright 2008-2018 Sarah Walker.
|
* Copyright 2008-2020 Sarah Walker.
|
||||||
* Copyright 2016-2018 Miran Grca.
|
* Copyright 2016-2020 Miran Grca.
|
||||||
* Copyright 2016-2018 Bit.
|
* Copyright 2016-2020 Bit.
|
||||||
* Copyright 2008-2018 DOSBox Team.
|
* Copyright 2008-2020 DOSBox Team.
|
||||||
*/
|
*/
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@@ -47,9 +47,8 @@ static int midi_input_device_last = 0;
|
|||||||
|
|
||||||
midi_t *midi = NULL, *midi_in = NULL;
|
midi_t *midi = NULL, *midi_in = NULL;
|
||||||
|
|
||||||
void (*input_msg)(void *p, uint8_t *msg);
|
midi_in_handler_t *mih_first = NULL, *mih_last = NULL,
|
||||||
int (*input_sysex)(void *p, uint8_t *buffer, uint32_t len, int abort);
|
*mih_cur = NULL;
|
||||||
void *midi_in_p;
|
|
||||||
|
|
||||||
uint8_t MIDI_InSysexBuf[SYSEX_SIZE];
|
uint8_t MIDI_InSysexBuf[SYSEX_SIZE];
|
||||||
|
|
||||||
@@ -227,7 +226,7 @@ void
|
|||||||
play_msg(uint8_t *msg)
|
play_msg(uint8_t *msg)
|
||||||
{
|
{
|
||||||
if (midi->m_out_device->play_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)
|
play_sysex(uint8_t *sysex, unsigned int len)
|
||||||
{
|
{
|
||||||
if (midi->m_out_device->play_sysex)
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
midi_in_device_init()
|
midi_in_device_init()
|
||||||
{
|
{
|
||||||
@@ -298,39 +298,40 @@ midi_in_device_init()
|
|||||||
midi_input_device_last = midi_input_device_current;
|
midi_input_device_last = midi_input_device_current;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
midi_raw_out_rt_byte(uint8_t val)
|
midi_raw_out_rt_byte(uint8_t val)
|
||||||
{
|
{
|
||||||
if (!midi_in->midi_realtime)
|
if (!midi_in->midi_realtime)
|
||||||
return;
|
|
||||||
|
|
||||||
if ((!midi_in->midi_clockout && (val == 0xf8)))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
midi_in->midi_cmd_r = val << 24;
|
if ((!midi_in->midi_clockout && (val == 0xf8)))
|
||||||
pclog("Play RT Byte msg\n");
|
return;
|
||||||
play_msg((uint8_t *)&midi_in->midi_cmd_r);
|
|
||||||
|
midi_in->midi_cmd_r = val << 24;
|
||||||
|
/* pclog("Play RT Byte msg\n"); */
|
||||||
|
play_msg((uint8_t *)&midi_in->midi_cmd_r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
midi_raw_out_thru_rt_byte(uint8_t val)
|
midi_raw_out_thru_rt_byte(uint8_t val)
|
||||||
{
|
{
|
||||||
if (midi_in->thruchan)
|
if (midi_in->thruchan)
|
||||||
midi_raw_out_rt_byte(val);
|
midi_raw_out_rt_byte(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
midi_raw_out_byte(uint8_t val)
|
midi_raw_out_byte(uint8_t val)
|
||||||
{
|
{
|
||||||
uint32_t passed_ticks;
|
uint32_t passed_ticks;
|
||||||
|
|
||||||
if (!midi || !midi->m_out_device) {
|
if (!midi || !midi->m_out_device)
|
||||||
return;
|
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;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
if (midi->midi_sysex_start) {
|
if (midi->midi_sysex_start) {
|
||||||
passed_ticks = plat_get_ticks() - 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
|
void
|
||||||
midi_clear_buffer(void)
|
midi_clear_buffer(void)
|
||||||
{
|
{
|
||||||
if (!midi) return;
|
if (!midi)
|
||||||
midi->midi_pos = 0;
|
return;
|
||||||
midi->midi_status = 0x00;
|
|
||||||
midi->midi_cmd_pos = 0;
|
midi->midi_pos = 0;
|
||||||
midi->midi_cmd_len = 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -34,12 +34,24 @@ void midi_in_device_init();
|
|||||||
|
|
||||||
typedef struct midi_device_t
|
typedef struct midi_device_t
|
||||||
{
|
{
|
||||||
void (*play_sysex)(uint8_t *sysex, unsigned int len);
|
void (*play_sysex)(uint8_t *sysex, unsigned int len);
|
||||||
void (*play_msg)(uint8_t *msg);
|
void (*play_msg)(uint8_t *msg);
|
||||||
void (*poll)();
|
void (*poll)();
|
||||||
int (*write)(uint8_t val);
|
int (*write)(uint8_t val);
|
||||||
} midi_device_t;
|
} 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
|
typedef struct midi_t
|
||||||
{
|
{
|
||||||
uint8_t midi_rt_buf[8], midi_cmd_buf[8],
|
uint8_t midi_rt_buf[8], midi_cmd_buf[8],
|
||||||
@@ -53,15 +65,20 @@ typedef struct midi_t
|
|||||||
|
|
||||||
extern midi_t *midi, *midi_in;
|
extern midi_t *midi, *midi_in;
|
||||||
|
|
||||||
void midi_init(midi_device_t* device);
|
extern void midi_init(midi_device_t* device);
|
||||||
void midi_in_init(midi_device_t* device, midi_t **mididev);
|
extern void midi_in_init(midi_device_t* device, midi_t **mididev);
|
||||||
void midi_close();
|
extern void midi_close();
|
||||||
void midi_in_close(void);
|
extern void midi_in_close(void);
|
||||||
void midi_raw_out_rt_byte(uint8_t val);
|
extern void midi_raw_out_rt_byte(uint8_t val);
|
||||||
void midi_raw_out_thru_rt_byte(uint8_t val);
|
extern void midi_raw_out_thru_rt_byte(uint8_t val);
|
||||||
void midi_raw_out_byte(uint8_t val);
|
extern void midi_raw_out_byte(uint8_t val);
|
||||||
void midi_clear_buffer(void);
|
extern void midi_clear_buffer(void);
|
||||||
void midi_poll();
|
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
|
#if 0
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
static float low_fir_es1371_coef[ES1371_NCoef];
|
static float low_fir_es1371_coef[ES1371_NCoef];
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
mpu_t mpu;
|
mpu_t mpu;
|
||||||
|
|
||||||
uint8_t pci_command, pci_serr;
|
uint8_t pci_command, pci_serr;
|
||||||
|
|
||||||
@@ -84,6 +84,8 @@ typedef struct {
|
|||||||
|
|
||||||
int pos;
|
int pos;
|
||||||
int16_t buffer[SOUNDBUFLEN * 2];
|
int16_t buffer[SOUNDBUFLEN * 2];
|
||||||
|
|
||||||
|
int type;
|
||||||
} es1371_t;
|
} es1371_t;
|
||||||
|
|
||||||
|
|
||||||
@@ -130,10 +132,13 @@ typedef struct {
|
|||||||
#define INT_STATUS_DAC1 (1<<2)
|
#define INT_STATUS_DAC1 (1<<2)
|
||||||
#define INT_STATUS_DAC2 (1<<1)
|
#define INT_STATUS_DAC2 (1<<1)
|
||||||
|
|
||||||
|
#define UART_CTRL_RXINTEN (1<<7)
|
||||||
#define UART_CTRL_TXINTEN (1<<5)
|
#define UART_CTRL_TXINTEN (1<<5)
|
||||||
|
|
||||||
|
#define UART_STATUS_RXINT (1<<7)
|
||||||
#define UART_STATUS_TXINT (1<<2)
|
#define UART_STATUS_TXINT (1<<2)
|
||||||
#define UART_STATUS_TXRDY (1<<1)
|
#define UART_STATUS_TXRDY (1<<1)
|
||||||
|
#define UART_STATUS_RXRDY (1<<0)
|
||||||
|
|
||||||
#define FORMAT_MONO_8 0
|
#define FORMAT_MONO_8 0
|
||||||
#define FORMAT_STEREO_8 1
|
#define FORMAT_STEREO_8 1
|
||||||
@@ -875,31 +880,34 @@ 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);
|
//audiopci_log("ES1371 PCI read %08X PC=%08x\n", addr, cpu_state.pc);
|
||||||
|
|
||||||
|
if (addr > 0x3f)
|
||||||
|
return 0x00;
|
||||||
|
|
||||||
switch (addr)
|
switch (addr)
|
||||||
{
|
{
|
||||||
case 0x00: return 0x74; /*Ensoniq*/
|
case 0x00: return 0x74; /*Ensoniq*/
|
||||||
case 0x01: return 0x12;
|
case 0x01: return 0x12;
|
||||||
|
|
||||||
case 0x02: return 0x71; /*ES1371*/
|
case 0x02: return 0x71; /* ES1371 */
|
||||||
case 0x03: return 0x13;
|
case 0x03: return 0x13;
|
||||||
|
|
||||||
case 0x04: return es1371->pci_command;
|
case 0x04: return es1371->pci_command;
|
||||||
case 0x05: return es1371->pci_serr;
|
case 0x05: return es1371->pci_serr;
|
||||||
|
|
||||||
case 0x06: return 0x10; /*Supports ACPI*/
|
case 0x06: return 0x10; /* Supports support ACPI */
|
||||||
case 0x07: return 0;
|
case 0x07: return 0x00;
|
||||||
|
|
||||||
case 0x08: return 2; /*Revision ID*/
|
case 0x08: return 0x02; /* Revision ID */
|
||||||
case 0x09: return 0x00; /*Multimedia audio device*/
|
case 0x09: return 0x00; /* Multimedia audio device */
|
||||||
case 0x0a: return 0x01;
|
case 0x0a: return 0x01;
|
||||||
case 0x0b: return 0x04;
|
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 0x11: return es1371->base_addr >> 8;
|
||||||
case 0x12: return es1371->base_addr >> 16;
|
case 0x12: return es1371->base_addr >> 16;
|
||||||
case 0x13: return es1371->base_addr >> 24;
|
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 0x2d: return 0x12;
|
||||||
case 0x2e: return 0x71;
|
case 0x2e: return 0x71;
|
||||||
case 0x2f: return 0x13;
|
case 0x2f: return 0x13;
|
||||||
@@ -1168,18 +1176,18 @@ static void es1371_poll(void *p)
|
|||||||
|
|
||||||
if (es1371->int_ctrl & INT_UART_EN) {
|
if (es1371->int_ctrl & INT_UART_EN) {
|
||||||
audiopci_log("UART INT Enabled\n");
|
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
|
/*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*/
|
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)
|
if (es1371->uart_ctrl & UART_CTRL_TXINTEN)
|
||||||
es1371->int_status |= INT_STATUS_UART;
|
es1371->int_status |= INT_STATUS_UART;
|
||||||
else
|
else
|
||||||
es1371->int_status &= ~INT_STATUS_UART;
|
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;
|
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)
|
if (es1371->uart_ctrl & UART_CTRL_TXINTEN)
|
||||||
es1371->uart_status |= (UART_STATUS_TXINT | UART_STATUS_TXRDY);
|
es1371->uart_status |= (UART_STATUS_TXINT | UART_STATUS_TXRDY);
|
||||||
else
|
else
|
||||||
@@ -1295,7 +1303,7 @@ static void generate_es1371_filter()
|
|||||||
low_fir_es1371_coef[n] /= gain;
|
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));
|
es1371_t *es1371 = malloc(sizeof(es1371_t));
|
||||||
memset(es1371, 0, sizeof(es1371_t));
|
memset(es1371, 0, sizeof(es1371_t));
|
||||||
|
|||||||
@@ -1169,15 +1169,14 @@ void *gus_init(const device_t *info)
|
|||||||
io_sethandler(0x0100+gus->base, 0x0010, readgus, NULL, NULL, writegus, NULL, NULL, gus);
|
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(0x0506+gus->base, 0x0001, readgus, NULL, NULL, writegus, NULL, NULL, gus);
|
||||||
io_sethandler(0x0388, 0x0002, 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->samp_timer, gus_poll_wave, gus, 1);
|
||||||
timer_add(&gus->timer_1, gus_poll_timer_1, 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->timer_2, gus_poll_timer_2, gus, 1);
|
||||||
|
|
||||||
sound_add_handler(gus_get_buffer, gus);
|
sound_add_handler(gus_get_buffer, gus);
|
||||||
|
|
||||||
input_msg = gus_input_msg;
|
if (device_get_config_int("receive_input"))
|
||||||
input_sysex = gus_input_sysex;
|
midi_in_handler(1, gus_input_msg, gus_input_sysex, gus);
|
||||||
midi_in_p = gus;
|
|
||||||
|
|
||||||
return gus;
|
return gus;
|
||||||
}
|
}
|
||||||
@@ -1256,7 +1255,10 @@ static const device_config_t gus_config[] = {
|
|||||||
NULL
|
NULL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"receive_input", "Receive input (SB MIDI)", CONFIG_BINARY, "", 1
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"", "", -1
|
"", "", -1
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,16 +8,16 @@
|
|||||||
*
|
*
|
||||||
* Roland MPU-401 emulation.
|
* 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/>
|
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||||
* DOSBox Team,
|
* DOSBox Team,
|
||||||
* Miran Grca, <mgrca8@gmail.com>
|
* Miran Grca, <mgrca8@gmail.com>
|
||||||
* TheCollector1995, <mariogplayer@gmail.com>
|
* TheCollector1995, <mariogplayer@gmail.com>
|
||||||
*
|
*
|
||||||
* Copyright 2008-2018 Sarah Walker.
|
* Copyright 2008-2020 Sarah Walker.
|
||||||
* Copyright 2008-2018 DOSBox Team.
|
* Copyright 2008-2020 DOSBox Team.
|
||||||
* Copyright 2016-2018 Miran Grca.
|
* Copyright 2016-2020 Miran Grca.
|
||||||
*/
|
*/
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@@ -39,8 +39,10 @@
|
|||||||
#include "snd_mpu401.h"
|
#include "snd_mpu401.h"
|
||||||
#include "midi.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 {
|
enum {
|
||||||
STATUS_OUTPUT_NOT_READY = 0x40,
|
STATUS_OUTPUT_NOT_READY = 0x40,
|
||||||
@@ -50,6 +52,7 @@ enum {
|
|||||||
|
|
||||||
int mpu401_standalone_enable = 0;
|
int mpu401_standalone_enable = 0;
|
||||||
|
|
||||||
|
|
||||||
static void MPU401_WriteCommand(mpu_t *mpu, uint8_t val);
|
static void MPU401_WriteCommand(mpu_t *mpu, uint8_t val);
|
||||||
static void MPU401_IntelligentOut(mpu_t *mpu, uint8_t track);
|
static void MPU401_IntelligentOut(mpu_t *mpu, uint8_t track);
|
||||||
static void MPU401_EOIHandler(void *priv);
|
static void MPU401_EOIHandler(void *priv);
|
||||||
@@ -1283,7 +1286,7 @@ MPU401_NotesOff(mpu_t *mpu, int i)
|
|||||||
|
|
||||||
|
|
||||||
/*Input handler for SysEx */
|
/*Input handler for SysEx */
|
||||||
static int
|
int
|
||||||
MPU401_InputSysex(void *p, uint8_t *buffer, uint32_t len, int abort)
|
MPU401_InputSysex(void *p, uint8_t *buffer, uint32_t len, int abort)
|
||||||
{
|
{
|
||||||
mpu_t *mpu = (mpu_t *)p;
|
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*/
|
/*Input handler for MIDI*/
|
||||||
static void
|
void
|
||||||
MPU401_InputMsg(void *p, uint8_t *msg)
|
MPU401_InputMsg(void *p, uint8_t *msg)
|
||||||
{
|
{
|
||||||
mpu_t *mpu = (mpu_t *)p;
|
mpu_t *mpu = (mpu_t *)p;
|
||||||
@@ -1550,7 +1553,7 @@ MPU401_InputMsg(void *p, uint8_t *msg)
|
|||||||
|
|
||||||
|
|
||||||
void
|
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->status = STATUS_INPUT_NOT_READY;
|
||||||
mpu->irq = irq;
|
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);
|
mpu401_read, NULL, NULL, mpu401_write, NULL, NULL, mpu);
|
||||||
io_sethandler(0x2A20, 16,
|
io_sethandler(0x2A20, 16,
|
||||||
NULL, NULL, NULL, imf_write, NULL, NULL, mpu);
|
NULL, NULL, NULL, imf_write, NULL, NULL, mpu);
|
||||||
timer_add(&mpu->mpu401_event_callback, MPU401_Event, 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_eoi_callback, MPU401_EOIHandler, mpu, 0);
|
||||||
timer_add(&mpu->mpu401_reset_callback, MPU401_ResetDone, mpu, 0);
|
timer_add(&mpu->mpu401_reset_callback, MPU401_ResetDone, mpu, 0);
|
||||||
|
|
||||||
MPU401_Reset(mpu);
|
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");
|
irq = device_get_config_int("irq");
|
||||||
}
|
}
|
||||||
|
|
||||||
input_msg = MPU401_InputMsg;
|
mpu401_init(mpu, base, irq, M_INTELLIGENT, device_get_config_int("receive_input"));
|
||||||
input_sysex = MPU401_InputSysex;
|
|
||||||
midi_in_p = mpu;
|
|
||||||
|
|
||||||
mpu401_init(mpu, base, irq, M_INTELLIGENT);
|
|
||||||
|
|
||||||
return(mpu);
|
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
|
"", "", -1
|
||||||
}
|
}
|
||||||
@@ -1741,5 +1763,5 @@ const device_t mpu401_mca_device = {
|
|||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL
|
mpu401_standalone_mca_config
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -8,16 +8,16 @@
|
|||||||
*
|
*
|
||||||
* Roland MPU-401 emulation.
|
* 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/>
|
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||||
* DOSBox Team,
|
* DOSBox Team,
|
||||||
* Miran Grca, <mgrca8@gmail.com>
|
* Miran Grca, <mgrca8@gmail.com>
|
||||||
* TheCollector1995, <mariogplayer@gmail.com>
|
* TheCollector1995, <mariogplayer@gmail.com>
|
||||||
* Copyright 2008-2018 Sarah Walker.
|
* Copyright 2008-2020 Sarah Walker.
|
||||||
* Copyright 2008-2018 DOSBox Team.
|
* Copyright 2008-2020 DOSBox Team.
|
||||||
* Copyright 2016-2018 Miran Grca.
|
* Copyright 2016-2020 Miran Grca.
|
||||||
* Copyright 2016-2018 TheCollector1995.
|
* Copyright 2016-2020 TheCollector1995.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define MPU401_VERSION 0x15
|
#define MPU401_VERSION 0x15
|
||||||
@@ -142,11 +142,15 @@ typedef struct mpu_t
|
|||||||
mpu401_reset_callback;
|
mpu401_reset_callback;
|
||||||
} mpu_t;
|
} 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_device;
|
||||||
extern const device_t mpu401_mca_device;
|
extern const device_t mpu401_mca_device;
|
||||||
|
|
||||||
|
|
||||||
extern uint8_t MPU401_ReadData(mpu_t *mpu);
|
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 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.
|
* 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/>
|
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||||
* Miran Grca, <mgrca8@gmail.com>
|
* Miran Grca, <mgrca8@gmail.com>
|
||||||
* TheCollector1995, <mariogplayer@gmail.com>
|
* TheCollector1995, <mariogplayer@gmail.com>
|
||||||
*
|
*
|
||||||
* Copyright 2008-2019 Sarah Walker.
|
* Copyright 2008-2020 Sarah Walker.
|
||||||
* Copyright 2016-2019 Miran Grca.
|
* Copyright 2016-2020 Miran Grca.
|
||||||
*/
|
*/
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdint.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);
|
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
|
/*sb1/2 port mappings, 210h to 260h in 10h steps
|
||||||
2x0 to 2x3 -> CMS chip
|
2x0 to 2x3 -> CMS chip
|
||||||
@@ -1043,13 +1043,12 @@ void *sb_1_init()
|
|||||||
}
|
}
|
||||||
sound_add_handler(sb_get_buffer_sb2, sb);
|
sound_add_handler(sb_get_buffer_sb2, sb);
|
||||||
|
|
||||||
input_msg = sb_dsp_input_msg;
|
if (device_get_config_int("receive_input"))
|
||||||
input_sysex = sb_dsp_input_sysex;
|
midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp);
|
||||||
midi_in_p = &sb->dsp;
|
|
||||||
|
|
||||||
return sb;
|
return sb;
|
||||||
}
|
}
|
||||||
void *sb_15_init()
|
void *sb_15_init(const device_t *info)
|
||||||
{
|
{
|
||||||
/*sb1/2 port mappings, 210h to 260h in 10h steps
|
/*sb1/2 port mappings, 210h to 260h in 10h steps
|
||||||
2x0 to 2x3 -> CMS chip
|
2x0 to 2x3 -> CMS chip
|
||||||
@@ -1074,14 +1073,13 @@ void *sb_15_init()
|
|||||||
}
|
}
|
||||||
sound_add_handler(sb_get_buffer_sb2, sb);
|
sound_add_handler(sb_get_buffer_sb2, sb);
|
||||||
|
|
||||||
input_msg = sb_dsp_input_msg;
|
if (device_get_config_int("receive_input"))
|
||||||
input_sysex = sb_dsp_input_sysex;
|
midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp);
|
||||||
midi_in_p = &sb->dsp;
|
|
||||||
|
|
||||||
return sb;
|
return sb;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *sb_mcv_init()
|
void *sb_mcv_init(const device_t *info)
|
||||||
{
|
{
|
||||||
/*sb1/2 port mappings, 210h to 260h in 10h steps
|
/*sb1/2 port mappings, 210h to 260h in 10h steps
|
||||||
2x6, 2xA, 2xC, 2xE -> DSP chip
|
2x6, 2xA, 2xC, 2xE -> DSP chip
|
||||||
@@ -1102,13 +1100,12 @@ void *sb_mcv_init()
|
|||||||
sb->pos_regs[0] = 0x84;
|
sb->pos_regs[0] = 0x84;
|
||||||
sb->pos_regs[1] = 0x50;
|
sb->pos_regs[1] = 0x50;
|
||||||
|
|
||||||
input_msg = sb_dsp_input_msg;
|
if (device_get_config_int("receive_input"))
|
||||||
input_sysex = sb_dsp_input_sysex;
|
midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp);
|
||||||
midi_in_p = &sb->dsp;
|
|
||||||
|
|
||||||
return sb;
|
return sb;
|
||||||
}
|
}
|
||||||
void *sb_2_init()
|
void *sb_2_init(const device_t *info)
|
||||||
{
|
{
|
||||||
/*sb2 port mappings. 220h or 240h.
|
/*sb2 port mappings. 220h or 240h.
|
||||||
2x0 to 2x3 -> CMS chip
|
2x0 to 2x3 -> CMS chip
|
||||||
@@ -1153,14 +1150,13 @@ void *sb_2_init()
|
|||||||
else
|
else
|
||||||
sound_add_handler(sb_get_buffer_sb2, sb);
|
sound_add_handler(sb_get_buffer_sb2, sb);
|
||||||
|
|
||||||
input_msg = sb_dsp_input_msg;
|
if (device_get_config_int("receive_input"))
|
||||||
input_sysex = sb_dsp_input_sysex;
|
midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp);
|
||||||
midi_in_p = &sb->dsp;
|
|
||||||
|
|
||||||
return sb;
|
return sb;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *sb_pro_v1_init()
|
void *sb_pro_v1_init(const device_t *info)
|
||||||
{
|
{
|
||||||
/*sbpro port mappings. 220h or 240h.
|
/*sbpro port mappings. 220h or 240h.
|
||||||
2x0 to 2x3 -> FM chip, Left and Right (9*2 voices)
|
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);
|
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);
|
sound_add_handler(sb_get_buffer_sbpro, sb);
|
||||||
|
|
||||||
input_msg = sb_dsp_input_msg;
|
if (device_get_config_int("receive_input"))
|
||||||
input_sysex = sb_dsp_input_sysex;
|
midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp);
|
||||||
midi_in_p = &sb->dsp;
|
|
||||||
|
|
||||||
return sb;
|
return sb;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *sb_pro_v2_init()
|
void *sb_pro_v2_init(const device_t *info)
|
||||||
{
|
{
|
||||||
/*sbpro port mappings. 220h or 240h.
|
/*sbpro port mappings. 220h or 240h.
|
||||||
2x0 to 2x3 -> FM chip (18 voices)
|
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);
|
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);
|
sound_add_handler(sb_get_buffer_sbpro, sb);
|
||||||
|
|
||||||
input_msg = sb_dsp_input_msg;
|
if (device_get_config_int("receive_input"))
|
||||||
input_sysex = sb_dsp_input_sysex;
|
midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp);
|
||||||
midi_in_p = &sb->dsp;
|
|
||||||
|
|
||||||
return sb;
|
return sb;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *sb_pro_mcv_init()
|
void *sb_pro_mcv_init(const device_t *info)
|
||||||
{
|
{
|
||||||
/*sbpro port mappings. 220h or 240h.
|
/*sbpro port mappings. 220h or 240h.
|
||||||
2x0 to 2x3 -> FM chip, Left and Right (18 voices)
|
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[0] = 0x03;
|
||||||
sb->pos_regs[1] = 0x51;
|
sb->pos_regs[1] = 0x51;
|
||||||
|
|
||||||
input_msg = sb_dsp_input_msg;
|
if (device_get_config_int("receive_input"))
|
||||||
input_sysex = sb_dsp_input_sysex;
|
midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp);
|
||||||
midi_in_p = &sb->dsp;
|
|
||||||
|
|
||||||
return sb;
|
return sb;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *sb_16_init()
|
void *sb_16_init(const device_t *info)
|
||||||
{
|
{
|
||||||
sb_t *sb = malloc(sizeof(sb_t));
|
sb_t *sb = malloc(sizeof(sb_t));
|
||||||
uint16_t addr = device_get_config_hex16("base");
|
uint16_t addr = device_get_config_hex16("base");
|
||||||
@@ -1288,15 +1281,13 @@ void *sb_16_init()
|
|||||||
if (mpu_addr) {
|
if (mpu_addr) {
|
||||||
sb->mpu = (mpu_t *) malloc(sizeof(mpu_t));
|
sb->mpu = (mpu_t *) malloc(sizeof(mpu_t));
|
||||||
memset(sb->mpu, 0, 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
|
} else
|
||||||
sb->mpu = NULL;
|
sb->mpu = NULL;
|
||||||
|
sb_dsp_set_mpu(sb->mpu);
|
||||||
|
|
||||||
|
if (device_get_config_int("receive_input"))
|
||||||
input_msg = sb_dsp_input_msg;
|
midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp);
|
||||||
input_sysex = sb_dsp_input_sysex;
|
|
||||||
midi_in_p = &sb->dsp;
|
|
||||||
|
|
||||||
return sb;
|
return sb;
|
||||||
}
|
}
|
||||||
@@ -1306,7 +1297,7 @@ int sb_awe32_available()
|
|||||||
return rom_present(L"roms/sound/awe32.raw");
|
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));
|
sb_t *sb = malloc(sizeof(sb_t));
|
||||||
uint16_t addr = device_get_config_hex16("base");
|
uint16_t addr = device_get_config_hex16("base");
|
||||||
@@ -1336,15 +1327,14 @@ void *sb_awe32_init()
|
|||||||
if (mpu_addr) {
|
if (mpu_addr) {
|
||||||
sb->mpu = (mpu_t *) malloc(sizeof(mpu_t));
|
sb->mpu = (mpu_t *) malloc(sizeof(mpu_t));
|
||||||
memset(sb->mpu, 0, 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);
|
sb_dsp_set_mpu(sb->mpu);
|
||||||
} else
|
} else
|
||||||
sb->mpu = NULL;
|
sb->mpu = NULL;
|
||||||
emu8k_init(&sb->emu8k, emu_addr, onboard_ram);
|
emu8k_init(&sb->emu8k, emu_addr, onboard_ram);
|
||||||
|
|
||||||
input_msg = sb_dsp_input_msg;
|
if (device_get_config_int("receive_input"))
|
||||||
input_sysex = sb_dsp_input_sysex;
|
midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &sb->dsp);
|
||||||
midi_in_p = &sb->dsp;
|
|
||||||
|
|
||||||
return sb;
|
return sb;
|
||||||
}
|
}
|
||||||
@@ -1438,6 +1428,9 @@ static const device_config_t sb_config[] =
|
|||||||
{
|
{
|
||||||
"opl", "Enable OPL", CONFIG_BINARY, "", 1
|
"opl", "Enable OPL", CONFIG_BINARY, "", 1
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"receive_input", "Receive input (SB MIDI)", CONFIG_BINARY, "", 1
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"", "", -1
|
"", "", -1
|
||||||
}
|
}
|
||||||
@@ -1479,6 +1472,9 @@ static const device_config_t sb_mcv_config[] =
|
|||||||
{
|
{
|
||||||
"opl", "Enable OPL", CONFIG_BINARY, "", 1
|
"opl", "Enable OPL", CONFIG_BINARY, "", 1
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"receive_input", "Receive input (SB MIDI)", CONFIG_BINARY, "", 1
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"", "", -1
|
"", "", -1
|
||||||
}
|
}
|
||||||
@@ -1537,6 +1533,9 @@ static const device_config_t sb_pro_config[] =
|
|||||||
{
|
{
|
||||||
"opl", "Enable OPL", CONFIG_BINARY, "", 1
|
"opl", "Enable OPL", CONFIG_BINARY, "", 1
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"receive_input", "Receive input (SB MIDI)", CONFIG_BINARY, "", 1
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"", "", -1
|
"", "", -1
|
||||||
}
|
}
|
||||||
@@ -1638,6 +1637,12 @@ static const device_config_t sb_16_config[] =
|
|||||||
{
|
{
|
||||||
"opl", "Enable OPL", CONFIG_BINARY, "", 1
|
"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
|
"", "", -1
|
||||||
}
|
}
|
||||||
@@ -1782,6 +1787,12 @@ static const device_config_t sb_awe32_config[] =
|
|||||||
{
|
{
|
||||||
"opl", "Enable OPL", CONFIG_BINARY, "", 1
|
"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
|
"", "", -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]);
|
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) {
|
if (dsp->midi_in_sysex) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -867,6 +872,9 @@ sb_dsp_input_sysex(void *p, uint8_t *buffer, uint32_t len, int abort)
|
|||||||
|
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
|
|
||||||
|
if (!dsp->uart_irq && !dsp->midi_in_poll && (mpu != NULL))
|
||||||
|
return MPU401_InputSysex(mpu, buffer, len, abort);
|
||||||
|
|
||||||
if (abort) {
|
if (abort) {
|
||||||
dsp->midi_in_sysex = 0;
|
dsp->midi_in_sysex = 0;
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -8,13 +8,13 @@
|
|||||||
*
|
*
|
||||||
* Sound emulation core.
|
* 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/>
|
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||||
* Miran Grca, <mgrca8@gmail.com>
|
* Miran Grca, <mgrca8@gmail.com>
|
||||||
*
|
*
|
||||||
* Copyright 2008-2018 Sarah Walker.
|
* Copyright 2008-2020 Sarah Walker.
|
||||||
* Copyright 2016-2018 Miran Grca.
|
* Copyright 2016-2020 Miran Grca.
|
||||||
*/
|
*/
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@@ -441,7 +441,7 @@ sound_reset(void)
|
|||||||
sound_realloc_buffers();
|
sound_realloc_buffers();
|
||||||
|
|
||||||
midi_device_init();
|
midi_device_init();
|
||||||
midi_in_device_init();
|
midi_in_device_init();
|
||||||
inital();
|
inital();
|
||||||
|
|
||||||
timer_add(&sound_poll_timer, sound_poll, NULL, 1);
|
timer_add(&sound_poll_timer, sound_poll, NULL, 1);
|
||||||
@@ -455,13 +455,20 @@ sound_reset(void)
|
|||||||
void
|
void
|
||||||
sound_card_reset(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();
|
sound_card_init();
|
||||||
|
|
||||||
if (mpu401_standalone_enable)
|
if (mpu401_standalone_enable)
|
||||||
mpu401_device_add();
|
mpu401_device_add();
|
||||||
|
|
||||||
if (GUS)
|
if (GUS)
|
||||||
device_add(&gus_device);
|
device_add(&gus_device);
|
||||||
|
|
||||||
if (GAMEBLASTER)
|
if (GAMEBLASTER)
|
||||||
device_add(&cms_device);
|
device_add(&cms_device);
|
||||||
|
|
||||||
if (SSI2001)
|
if (SSI2001)
|
||||||
device_add(&ssi2001_device);
|
device_add(&ssi2001_device);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -701,10 +701,10 @@ svga_poll(void *p)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
svga->hsync_divisor = !svga->hsync_divisor;
|
svga->hsync_divisor = !svga->hsync_divisor;
|
||||||
|
|
||||||
if (svga->hsync_divisor && (svga->crtc[0x17] & 4))
|
if (svga->hsync_divisor && (svga->crtc[0x17] & 4))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
svga->vc++;
|
svga->vc++;
|
||||||
svga->vc &= 2047;
|
svga->vc &= 2047;
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ typedef struct
|
|||||||
HANDLE m_event;
|
HANDLE m_event;
|
||||||
|
|
||||||
HMIDIOUT midi_out_device;
|
HMIDIOUT midi_out_device;
|
||||||
HMIDIIN midi_in_device;
|
HMIDIIN midi_in_device;
|
||||||
|
|
||||||
MIDIHDR m_hdr;
|
MIDIHDR m_hdr;
|
||||||
} plat_midi_t;
|
} plat_midi_t;
|
||||||
@@ -137,57 +137,44 @@ plat_midi_write(uint8_t val)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CALLBACK
|
void CALLBACK
|
||||||
plat_midi_in_callback(HMIDIIN hMidiIn, UINT wMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
|
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)),
|
uint8_t msg[4] = { ((dwParam1 & 0xff)), (((dwParam1 & 0xff00) >> 8)),
|
||||||
(((dwParam1&0xff0000)>>16)),MIDI_evt_len[((dwParam1&0xff))]};
|
(((dwParam1 & 0xff0000) >> 16)), MIDI_evt_len[((dwParam1 & 0xff))]};
|
||||||
uint8_t *sysex;
|
uint8_t *sysex;
|
||||||
uint32_t len;
|
uint32_t len;
|
||||||
int cnt;
|
MIDIHDR *hdr;
|
||||||
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));
|
switch (wMsg) {
|
||||||
hdr->dwBytesRecorded = 0;
|
case MM_MIM_DATA: /* 0x3C3 - midi message */
|
||||||
midiInPrepareHeader(hMidiIn, hdr, sizeof(*hdr));
|
midi_in_msg(msg);
|
||||||
break;
|
break;
|
||||||
case MM_MIM_ERROR:
|
case MM_MIM_OPEN: /* 0x3C1 */
|
||||||
case MM_MIM_LONGERROR:
|
break;
|
||||||
break;
|
case MM_MIM_CLOSE: /* 0x3C2 */
|
||||||
default:
|
break;
|
||||||
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
|
void
|
||||||
plat_midi_input_init(void)
|
plat_midi_input_init(void)
|
||||||
{
|
{
|
||||||
@@ -198,10 +185,10 @@ plat_midi_input_init(void)
|
|||||||
|
|
||||||
pm_in->midi_input_id = config_get_int(MIDI_INPUT_NAME, "midi_input", 0);
|
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,
|
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) {
|
if (hr != MMSYSERR_NOERROR) {
|
||||||
printf("midiInOpen error - %08X\n", hr);
|
printf("midiInOpen error - %08X\n", hr);
|
||||||
pm_in->midi_input_id = 0;
|
pm_in->midi_input_id = 0;
|
||||||
@@ -213,14 +200,15 @@ plat_midi_input_init(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pm_in->m_hdr.lpData = (char*)&MIDI_InSysexBuf[0];
|
pm_in->m_hdr.lpData = (char*)&MIDI_InSysexBuf[0];
|
||||||
pm_in->m_hdr.dwBufferLength = SYSEX_SIZE;
|
pm_in->m_hdr.dwBufferLength = SYSEX_SIZE;
|
||||||
pm_in->m_hdr.dwBytesRecorded = 0;
|
pm_in->m_hdr.dwBytesRecorded = 0;
|
||||||
pm_in->m_hdr.dwUser = 0;
|
pm_in->m_hdr.dwUser = 0;
|
||||||
midiInPrepareHeader(pm_in->midi_in_device,&pm_in->m_hdr,sizeof(pm_in->m_hdr));
|
midiInPrepareHeader(pm_in->midi_in_device,&pm_in->m_hdr,sizeof(pm_in->m_hdr));
|
||||||
midiInStart(pm_in->midi_in_device);
|
midiInStart(pm_in->midi_in_device);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
plat_midi_input_close(void)
|
plat_midi_input_close(void)
|
||||||
{
|
{
|
||||||
@@ -235,6 +223,7 @@ plat_midi_input_close(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
plat_midi_in_get_num_devs(void)
|
plat_midi_in_get_num_devs(void)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user