Merge pull request #535 from 86Box/feature/midi_in

Feature/midi in
This commit is contained in:
OBattler
2020-01-12 18:57:44 +01:00
committed by GitHub
20 changed files with 2169 additions and 551 deletions

View File

@@ -649,6 +649,12 @@ load_sound(void)
else
midi_device_current = 0;
p = config_get_string(cat, "midi_in_device", NULL);
if (p != NULL)
midi_input_device_current = midi_in_device_get_from_internal_name(p);
else
midi_input_device_current = 0;
mpu401_standalone_enable = !!config_get_int(cat, "mpu401_standalone", 0);
SSI2001 = !!config_get_int(cat, "ssi2001", 0);
@@ -1531,6 +1537,11 @@ save_sound(void)
else
config_set_string(cat, "midi_device", midi_device_get_internal_name(midi_device_current));
if (!strcmp(midi_in_device_get_internal_name(midi_input_device_current), "none"))
config_delete_var(cat, "midi_in_device");
else
config_set_string(cat, "midi_in_device", midi_in_device_get_internal_name(midi_input_device_current));
if (mpu401_standalone_enable == 0)
config_delete_var(cat, "mpu401_standalone");
else

View File

@@ -50,6 +50,7 @@
#define CONFIG_HEX16 7
#define CONFIG_HEX20 8
#define CONFIG_MAC 9
#define CONFIG_MIDI_IN 10
enum {

View File

@@ -7,3 +7,9 @@ extern int plat_midi_write(uint8_t val);
extern int plat_midi_get_num_devs(void);
extern void plat_midi_get_dev_name(int num, char *s);
extern void plat_midi_input_init(void);
extern void plat_midi_input_close(void);
extern int plat_midi_in_get_num_devs(void);
extern void plat_midi_in_get_dev_name(int num, char *s);

View File

@@ -8,7 +8,7 @@
*
* MIDI device core module.
*
* Version: @(#)midi.c 1.0.1 2018/10/10
* Version: @(#)midi.c 1.0.2 2018/12/31
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
@@ -37,28 +37,23 @@
#ifdef USE_MUNT
# include "midi_mt32.h"
#endif
#include "midi_input.h"
#define SYSEX_SIZE 1024
#define RAWBUF 1024
int midi_device_current = 0;
static int midi_device_last = 0;
int midi_input_device_current = 0;
static int midi_input_device_last = 0;
midi_t *midi = NULL, *midi_in = NULL;
typedef struct
{
uint8_t midi_rt_buf[1024], midi_cmd_buf[1024],
midi_status, midi_sysex_data[1026];
int midi_cmd_pos, midi_cmd_len;
unsigned int midi_sysex_start, midi_sysex_delay,
midi_pos;
midi_device_t* m_device;
} midi_t;
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;
static midi_t *midi = NULL;
uint8_t MIDI_InSysexBuf[SYSEX_SIZE];
static uint8_t MIDI_evt_len[256] = {
uint8_t MIDI_evt_len[256] = {
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 0x00 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 0x10 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 0x20 */
@@ -85,7 +80,7 @@ typedef struct
{
const char *name, *internal_name;
const device_t *device;
} MIDI_DEVICE;
} MIDI_DEVICE, MIDI_IN_DEVICE;
static const MIDI_DEVICE devices[] =
{
@@ -101,6 +96,12 @@ static const MIDI_DEVICE devices[] =
{"", "", NULL}
};
static const MIDI_IN_DEVICE midi_in_devices[] =
{
{"None", "none", NULL},
{MIDI_INPUT_NAME, MIDI_INPUT_INTERNAL_NAME, &midi_input_device},
{"", "", NULL}
};
int
midi_device_available(int card)
@@ -172,16 +173,25 @@ midi_init(midi_device_t* device)
midi = (midi_t *) malloc(sizeof(midi_t));
memset(midi, 0, sizeof(midi_t));
midi->m_device = device;
midi->m_out_device = device;
}
void
midi_in_init(midi_device_t* device, midi_t **mididev)
{
*mididev = (midi_t *)malloc(sizeof(midi_t));
memset(*mididev, 0, sizeof(midi_t));
(*mididev)->m_in_device = device;
}
void
midi_close(void)
{
if (midi && midi->m_device) {
free(midi->m_device);
midi->m_device = NULL;
if (midi && midi->m_out_device) {
free(midi->m_out_device);
midi->m_out_device = NULL;
}
if (midi) {
@@ -190,41 +200,137 @@ midi_close(void)
}
}
void
midi_in_close(void)
{
if (midi_in && midi_in->m_in_device) {
free(midi_in->m_in_device);
midi_in->m_in_device = NULL;
}
if (midi_in) {
free(midi_in);
midi_in = NULL;
}
}
void
midi_poll(void)
{
if (midi && midi->m_device && midi->m_device->poll)
midi->m_device->poll();
if (midi && midi->m_out_device && midi->m_out_device->poll)
midi->m_out_device->poll();
}
void
play_msg(uint8_t *msg)
{
if (midi->m_device->play_msg)
midi->m_device->play_msg(msg);
if (midi->m_out_device->play_msg)
midi->m_out_device->play_msg(msg);
}
void
play_sysex(uint8_t *sysex, unsigned int len)
{
if (midi->m_device->play_sysex)
midi->m_device->play_sysex(sysex, len);
if (midi->m_out_device->play_sysex)
midi->m_out_device->play_sysex(sysex, len);
}
int
midi_in_device_available(int card)
{
if (midi_in_devices[card].device)
return device_available(midi_in_devices[card].device);
return 1;
}
char *
midi_in_device_getname(int card)
{
return (char *) midi_in_devices[card].name;
}
const device_t *
midi_in_device_getdevice(int card)
{
return midi_in_devices[card].device;
}
int
midi_in_device_has_config(int card)
{
if (!midi_in_devices[card].device)
return 0;
return midi_in_devices[card].device->config ? 1 : 0;
}
char *
midi_in_device_get_internal_name(int card)
{
return (char *) midi_in_devices[card].internal_name;
}
int
midi_in_device_get_from_internal_name(char *s)
{
int c = 0;
while (strlen(midi_in_devices[c].internal_name)) {
if (!strcmp(midi_in_devices[c].internal_name, s))
return c;
c++;
}
return 0;
}
void
midi_write(uint8_t val)
midi_in_device_init()
{
if (midi_in_devices[midi_input_device_current].device)
device_add(midi_in_devices[midi_input_device_current].device);
midi_input_device_last = midi_input_device_current;
}
void
midi_raw_out_rt_byte(uint8_t val)
{
if (!midi_in->midi_realtime)
return;
if ((!midi_in->midi_clockout && (val == 0xf8)))
return;
midi_in->midi_cmd_r = val << 24;
pclog("Play RT Byte msg\n");
play_msg((uint8_t *)&midi_in->midi_cmd_r);
}
void
midi_raw_out_thru_rt_byte(uint8_t val)
{
if (midi_in->thruchan)
midi_raw_out_rt_byte(val);
}
void
midi_raw_out_byte(uint8_t val)
{
uint32_t passed_ticks;
if (!midi || !midi->m_device)
if (!midi || !midi->m_out_device) {
return;
}
if (midi->m_device->write && midi->m_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;
@@ -289,3 +395,12 @@ midi_write(uint8_t val)
}
}
}
void
midi_clear_buffer(void)
{
midi->midi_pos = 0;
midi->midi_status = 0x00;
midi->midi_cmd_pos = 0;
midi->midi_cmd_len = 0;
}

View File

@@ -2,18 +2,35 @@
# define EMU_SOUND_MIDI_H
extern int midi_device_current;
#define SYSEX_SIZE 8192
extern uint8_t MIDI_InSysexBuf[SYSEX_SIZE];
extern uint8_t MIDI_evt_len[256];
extern int midi_device_current;
extern int midi_input_device_current;
extern void (*input_msg)(void *p, uint8_t *msg);
extern int (*input_sysex)(void *p, uint8_t *buffer, uint32_t len, int abort);
extern void *midi_in_p;
int midi_device_available(int card);
int midi_in_device_available(int card);
char *midi_device_getname(int card);
char *midi_in_device_getname(int card);
#ifdef EMU_DEVICE_H
const device_t *midi_device_getdevice(int card);
const device_t *midi_in_device_getdevice(int card);
#endif
int midi_device_has_config(int card);
int midi_in_device_has_config(int card);
char *midi_device_get_internal_name(int card);
char *midi_in_device_get_internal_name(int card);
int midi_device_get_from_internal_name(char *s);
int midi_in_device_get_from_internal_name(char *s);
void midi_device_init();
void midi_in_device_init();
typedef struct midi_device_t
{
@@ -23,9 +40,27 @@ typedef struct midi_device_t
int (*write)(uint8_t val);
} midi_device_t;
typedef struct midi_t
{
uint8_t midi_rt_buf[8], midi_cmd_buf[8],
midi_status, midi_sysex_data[SYSEX_SIZE];
int midi_cmd_pos, midi_cmd_len, midi_cmd_r,
midi_realtime, thruchan, midi_clockout;
unsigned int midi_sysex_start, midi_sysex_delay,
midi_pos;
midi_device_t *m_out_device, *m_in_device;
} 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_write(uint8_t val);
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();
#if 0
@@ -41,5 +76,7 @@ void midi_poll();
#define SYSTEM_MIDI_INTERNAL_NAME "system_midi"
#endif
#define MIDI_INPUT_NAME "MIDI Input Device"
#define MIDI_INPUT_INTERNAL_NAME "midi_in"
#endif /*EMU_SOUND_MIDI_H*/

1
src/sound/midi_input.h Normal file
View File

@@ -0,0 +1 @@
extern const device_t midi_input_device;

View File

@@ -9,6 +9,7 @@
#include "../plat_midi.h"
#include "midi.h"
#include "midi_system.h"
#include "midi_input.h"
void* system_midi_init(const device_t *info)
@@ -27,6 +28,22 @@ void* system_midi_init(const device_t *info)
return dev;
}
void* midi_input_init(const device_t *info)
{
midi_device_t* dev = malloc(sizeof(midi_device_t));
memset(dev, 0, sizeof(midi_device_t));
plat_midi_input_init();
midi_in_init(dev, &midi_in);
midi_in->midi_realtime = device_get_config_int("realtime");
midi_in->thruchan = device_get_config_int("thruchan");
midi_in->midi_clockout = device_get_config_int("clockout");
return dev;
}
void system_midi_close(void* p)
{
plat_midi_close();
@@ -34,11 +51,23 @@ void system_midi_close(void* p)
midi_close();
}
void midi_input_close(void* p)
{
plat_midi_input_close();
midi_close();
}
int system_midi_available(void)
{
return plat_midi_get_num_devs();
}
int midi_input_available(void)
{
return plat_midi_in_get_num_devs();
}
static const device_config_t system_midi_config[] =
{
{
@@ -52,6 +81,37 @@ static const device_config_t system_midi_config[] =
}
};
static const device_config_t midi_input_config[] =
{
{
.name = "midi_input",
.description = "MIDI in device",
.type = CONFIG_MIDI_IN,
.default_int = 0
},
{
.name = "realtime",
.description = "MIDI Real time",
.type = CONFIG_BINARY,
.default_int = 0
},
{
.name = "thruchan",
.description = "MIDI Thru",
.type = CONFIG_BINARY,
.default_int = 1
},
{
.name = "clockout",
.description = "MIDI Clockout",
.type = CONFIG_BINARY,
.default_int = 1
},
{
.type = -1
}
};
const device_t system_midi_device =
{
SYSTEM_MIDI_NAME,
@@ -64,3 +124,17 @@ const device_t system_midi_device =
NULL,
system_midi_config
};
const device_t midi_input_device =
{
MIDI_INPUT_NAME,
0, 0,
midi_input_init,
midi_input_close,
NULL,
midi_input_available,
NULL,
NULL,
midi_input_config
};

View File

@@ -13,6 +13,8 @@
#include "../pci.h"
#include "../timer.h"
#include "sound.h"
#include "midi.h"
#include "snd_mpu401.h"
#include "snd_audiopci.h"
@@ -23,6 +25,8 @@
static float low_fir_es1371_coef[ES1371_NCoef];
typedef struct {
mpu_t mpu;
uint8_t pci_command, pci_serr;
uint32_t base_addr;
@@ -116,14 +120,21 @@ typedef struct {
#define INT_DAC1_EN (1<<6)
#define INT_DAC2_EN (1<<5)
#define INT_UART_EN (1<<3)
#define SI_P2_INTR_EN (1<<9)
#define SI_P1_INTR_EN (1<<8)
#define INT_STATUS_INTR (1<<31)
#define INT_STATUS_UART (1<<3)
#define INT_STATUS_DAC1 (1<<2)
#define INT_STATUS_DAC2 (1<<1)
#define UART_CTRL_TXINTEN (1<<5)
#define UART_STATUS_TXINT (1<<2)
#define UART_STATUS_TXRDY (1<<1)
#define FORMAT_MONO_8 0
#define FORMAT_STEREO_8 1
#define FORMAT_MONO_16 2
@@ -164,8 +175,13 @@ static void es1371_update_irqs(es1371_t *es1371)
if ((es1371->int_status & INT_STATUS_DAC1) && (es1371->si_cr & SI_P1_INTR_EN))
irq = 1;
if ((es1371->int_status & INT_STATUS_DAC2) && (es1371->si_cr & SI_P2_INTR_EN))
if ((es1371->int_status & INT_STATUS_DAC2) && (es1371->si_cr & SI_P2_INTR_EN)) {
irq = 1;
}
/*MIDI input is unsupported for now*/
if ((es1371->int_status & INT_STATUS_UART) && (es1371->uart_status & UART_STATUS_TXINT)) {
irq = 1;
}
if (irq)
es1371->int_status |= INT_STATUS_INTR;
@@ -219,10 +235,10 @@ static uint8_t es1371_inb(uint16_t port, void *p)
case 0x07:
ret = (es1371->int_status >> 24) & 0xff;
break;
case 0x09:
ret = es1371->uart_status;
ret = es1371->uart_status & 0xc7;
audiopci_log("ES1371 UART Status = %02x\n", es1371->uart_status);
break;
case 0x0c:
@@ -253,7 +269,7 @@ static uint8_t es1371_inb(uint16_t port, void *p)
audiopci_log("Bad es1371_inb: port=%04x\n", port);
}
// audiopci_log("es1371_inb: port=%04x ret=%02x\n", port, ret);
audiopci_log("es1371_inb: port=%04x ret=%02x\n", port, ret);
// output = 3;
return ret;
}
@@ -340,31 +356,51 @@ static uint32_t es1371_inl(uint16_t port, void *p)
ret |= CODEC_READY;
break;
case 0x34:
switch (es1371->mem_page)
{
case 0x30:
switch (es1371->mem_page) {
case 0xe: case 0xf:
audiopci_log("ES1371 0x30 read UART FIFO: val = %02x\n", ret & 0xff);
break;
}
break;
case 0x34:
switch (es1371->mem_page) {
case 0xc:
ret = es1371->dac[0].size | (es1371->dac[0].count << 16);
break;
case 0xd:
ret = es1371->adc.size | (es1371->adc.count << 16);
break;
case 0xe: case 0xf:
audiopci_log("ES1371 0x34 read UART FIFO: val = %02x\n", ret & 0xff);
break;
default:
audiopci_log("Bad es1371_inl: mem_page=%x port=%04x\n", es1371->mem_page, port);
}
break;
case 0x38:
switch (es1371->mem_page) {
case 0xe: case 0xf:
audiopci_log("ES1371 0x38 read UART FIFO: val = %02x\n", ret & 0xff);
break;
}
break;
case 0x3c:
switch (es1371->mem_page)
{
switch (es1371->mem_page) {
case 0xc:
ret = es1371->dac[1].size | (es1371->dac[1].count << 16);
break;
case 0xe: case 0xf:
audiopci_log("ES1371 0x3c read UART FIFO: val = %02x\n", ret & 0xff);
break;
default:
audiopci_log("Bad es1371_inl: mem_page=%x port=%04x\n", es1371->mem_page, port);
}
@@ -374,7 +410,7 @@ static uint32_t es1371_inl(uint16_t port, void *p)
audiopci_log("Bad es1371_inl: port=%04x\n", port);
}
// audiopci_log("es1371_inl: port=%04x ret=%08x %08x\n", port, ret, cpu_state.pc);
audiopci_log("es1371_inl: port=%04x ret=%08x\n", port, ret);
return ret;
}
@@ -382,7 +418,7 @@ static void es1371_outb(uint16_t port, uint8_t val, void *p)
{
es1371_t *es1371 = (es1371_t *)p;
// audiopci_log("es1371_outb: port=%04x val=%02x %04x:%08x\n", port, val, cs, cpu_state.pc);
audiopci_log("es1371_outb: port=%04x val=%02x\n", port, val);
switch (port & 0x3f)
{
case 0x00:
@@ -412,8 +448,13 @@ static void es1371_outb(uint16_t port, uint8_t val, void *p)
es1371->int_ctrl = (es1371->int_ctrl & 0x00ffffff) | (val << 24);
break;
case 0x08:
midi_raw_out_byte(val);
break;
case 0x09:
es1371->uart_ctrl = val;
es1371->uart_ctrl = val & 0xe3;
audiopci_log("ES1371 UART Cntrl = %02x\n", es1371->uart_ctrl);
break;
case 0x0c:
@@ -481,7 +522,7 @@ static void es1371_outl(uint16_t port, uint32_t val, void *p)
{
es1371_t *es1371 = (es1371_t *)p;
// audiopci_log("es1371_outl: port=%04x val=%08x %04x:%08x\n", port, val, CS, cpu_state.pc);
audiopci_log("es1371_outl: port=%04x val=%08x\n", port, val);
switch (port & 0x3f)
{
case 0x04:
@@ -593,6 +634,10 @@ static void es1371_outl(uint16_t port, uint32_t val, void *p)
// audiopci_log("DAC1 addr %08x\n", val);
break;
case 0xe: case 0xf:
audiopci_log("ES1371 0x30 write UART FIFO: val = %02x\n", val & 0xff);
break;
default:
audiopci_log("Bad es1371_outl: mem_page=%x port=%04x val=%08x\n", es1371->mem_page, port, val);
}
@@ -615,6 +660,10 @@ static void es1371_outl(uint16_t port, uint32_t val, void *p)
es1371->adc.count = val >> 16;
break;
case 0xe: case 0xf:
audiopci_log("ES1371 0x34 write UART FIFO: val = %02x\n", val & 0xff);
break;
default:
audiopci_log("Bad es1371_outl: mem_page=%x port=%04x val=%08x\n", es1371->mem_page, port, val);
}
@@ -633,6 +682,10 @@ static void es1371_outl(uint16_t port, uint32_t val, void *p)
case 0xd:
break;
case 0xe: case 0xf:
audiopci_log("ES1371 0x38 write UART FIFO: val = %02x\n", val & 0xff);
break;
default:
audiopci_log("Bad es1371_outl: mem_page=%x port=%04x val=%08x\n", es1371->mem_page, port, val);
@@ -649,6 +702,10 @@ static void es1371_outl(uint16_t port, uint32_t val, void *p)
case 0xc:
es1371->dac[1].size = val & 0xffff;
es1371->dac[1].count = val >> 16;
break;
case 0xe: case 0xf:
audiopci_log("ES1371 0x3c write UART FIFO: val = %02x\n", val & 0xff);
break;
default:
@@ -1107,10 +1164,33 @@ static void es1371_poll(void *p)
timer_advance_u64(&es1371->dac[1].timer, es1371->dac[1].latch);
es1371_update(es1371);
if (es1371->int_ctrl & INT_DAC1_EN)
{
es1371_update(es1371);
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.*/
/*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*/
es1371->int_status |= INT_STATUS_UART;
}
if (es1371->uart_ctrl & 0x80) {
if (es1371->uart_ctrl & UART_CTRL_TXINTEN)
es1371->uart_status |= (UART_STATUS_TXINT | UART_STATUS_TXRDY);
else
es1371->uart_status &= ~(UART_STATUS_TXINT | UART_STATUS_TXRDY);
} else
es1371->uart_status |= (UART_STATUS_TXINT | UART_STATUS_TXRDY);
es1371_update_irqs(es1371);
}
if (es1371->int_ctrl & INT_DAC1_EN) {
int frac = es1371->dac[0].ac & 0x7fff;
int idx = es1371->dac[0].ac >> 15;
int samp1_l = es1371->dac[0].filtered_l[idx];

View File

@@ -13,8 +13,39 @@
#include "../timer.h"
#include "../device.h"
#include "sound.h"
#include "midi.h"
#include "snd_gus.h"
enum
{
MIDI_INT_RECEIVE = 0x01,
MIDI_INT_TRANSMIT = 0x02,
MIDI_INT_MASTER = 0x80
};
enum
{
MIDI_CTRL_TRANSMIT_MASK = 0x60,
MIDI_CTRL_TRANSMIT = 0x20,
MIDI_CTRL_RECEIVE = 0x80
};
enum
{
GUS_INT_MIDI_TRANSMIT = 0x01,
GUS_INT_MIDI_RECEIVE = 0x02
};
enum
{
GUS_TIMER_CTRL_AUTO = 0x01
};
enum
{
GUS_CLASSIC = 0,
GUS_MAX = 1,
};
typedef struct gus_t
{
@@ -51,12 +82,14 @@ typedef struct gus_t
uint64_t samp_latch;
uint8_t *ram;
uint32_t gus_end_ram;
int irqnext;
pc_timer_t timer_1, timer_2;
int irq, dma, irq_midi;
uint16_t base;
int latch_enable;
uint8_t sb_2xa, sb_2xc, sb_2xe;
@@ -68,9 +101,9 @@ typedef struct gus_t
uint8_t ad_status, ad_data;
uint8_t ad_timer_ctrl;
uint8_t midi_ctrl, midi_status;
uint8_t midi_data;
int midi_loopback;
uint8_t midi_ctrl, midi_status, midi_queue[64], midi_data;
int midi_r, midi_w;
int uart_in, uart_out, sysex;
uint8_t gp1, gp2;
uint16_t gp1_addr, gp2_addr;
@@ -78,8 +111,8 @@ typedef struct gus_t
uint8_t usrr;
} gus_t;
static int gus_irqs[8] = {-1, 2, 5, 3, 7, 11, 12, 15};
static int gus_irqs_midi[8] = {-1, 2, 5, 3, 7, 11, 12, 15};
static int gus_gf1_irqs[8] = {0, 2, 5, 3, 7, 11, 12, 15};
static int gus_midi_irqs[8] = {0, 2, 5, 3, 7, 11, 12, 15};
static int gus_dmas[8] = {-1, 1, 3, 5, 6, 7, -1, -1};
int gusfreqs[]=
@@ -102,48 +135,26 @@ void pollgusirqs(gus_t *gus)
gus->irqstatus2=0x60|c;
if (gus->rampirqs[c]) gus->irqstatus2 |= 0x80;
gus->irqstatus|=0x20;
if (gus->irq != -1)
picint(1 << gus->irq);
if (gus->irq != 0)
picint(1 << gus->irq);
return;
}
if (gus->rampirqs[c])
{
gus->irqstatus2=0xA0|c;
gus->irqstatus|=0x40;
if (gus->irq != -1)
picint(1 << gus->irq);
if (gus->irq != 0)
picint(1 << gus->irq);
return;
}
}
gus->irqstatus2=0xE0;
if (!gus->irqstatus && gus->irq != -1) picintc(1 << gus->irq);
if (!gus->irqstatus) {
if (gus->irq != 0)
picintc(1 << gus->irq);
}
}
enum
{
MIDI_INT_RECEIVE = 0x01,
MIDI_INT_TRANSMIT = 0x02,
MIDI_INT_MASTER = 0x80
};
enum
{
MIDI_CTRL_TRANSMIT_MASK = 0x60,
MIDI_CTRL_TRANSMIT = 0x20,
MIDI_CTRL_RECEIVE = 0x80
};
enum
{
GUS_INT_MIDI_TRANSMIT = 0x01,
GUS_INT_MIDI_RECEIVE = 0x02
};
enum
{
GUS_TIMER_CTRL_AUTO = 0x01
};
void gus_midi_update_int_status(gus_t *gus)
{
gus->midi_status &= ~MIDI_INT_MASTER;
@@ -157,57 +168,63 @@ void gus_midi_update_int_status(gus_t *gus)
if ((gus->midi_ctrl & MIDI_CTRL_RECEIVE) && (gus->midi_status & MIDI_INT_RECEIVE))
{
gus->midi_status |= MIDI_INT_MASTER;
gus->irqstatus |= GUS_INT_MIDI_RECEIVE;
gus->midi_status |= MIDI_INT_MASTER;
gus->irqstatus |= GUS_INT_MIDI_RECEIVE;
}
else
gus->irqstatus &= ~GUS_INT_MIDI_RECEIVE;
if ((gus->midi_status & MIDI_INT_MASTER) && (gus->irq_midi != -1))
if ((gus->midi_status & MIDI_INT_MASTER) && (gus->irq_midi != 0))
{
picint(1 << gus->irq_midi);
}
}
void writegus(uint16_t addr, uint8_t val, void *p)
{
gus_t *gus = (gus_t *)p;
int c, d;
int old;
if (gus->latch_enable && addr != 0x24b)
gus->latch_enable = 0;
switch (addr)
uint16_t port;
if ((addr == 0x388) || (addr == 0x389))
port = addr;
else
port = addr & 0xf0f;
switch (port)
{
case 0x340: /*MIDI control*/
case 0x300: /*MIDI control*/
old = gus->midi_ctrl;
gus->midi_ctrl = val;
if ((val & 3) == 3)
gus->midi_status = 0;
else if ((old & 3) == 3)
{
gus->midi_status |= MIDI_INT_TRANSMIT;
}
gus->uart_out = 1;
if ((val & 3) == 3) { /*Master reset*/
gus->uart_in = 0;
gus->midi_status = 0;
gus->midi_r = 0;
gus->midi_w = 0;
} else if ((old & 3) == 3) {
gus->midi_status |= MIDI_INT_TRANSMIT;
} else if (gus->midi_ctrl & MIDI_CTRL_RECEIVE) {
gus->uart_in = 1;
}
gus_midi_update_int_status(gus);
break;
case 0x341: /*MIDI data*/
if (gus->midi_loopback)
{
gus->midi_status |= MIDI_INT_RECEIVE;
gus->midi_data = val;
case 0x301: /*MIDI data*/
gus->midi_data = val;
if (gus->uart_out) {
midi_raw_out_byte(val);
}
else
gus->midi_status |= MIDI_INT_TRANSMIT;
if (gus->latch_enable & 0x20) {
gus->midi_status |= MIDI_INT_RECEIVE;
} else
gus->midi_status |= MIDI_INT_TRANSMIT;
break;
case 0x342: /*Voice select*/
gus->voice=val&31;
break;
case 0x343: /*Global select*/
case 0x303: /*Global select*/
gus->global=val;
break;
case 0x344: /*Global low*/
case 0x304: /*Global low*/
switch (gus->global)
{
case 0: /*Voice control*/
@@ -231,11 +248,11 @@ void writegus(uint16_t addr, uint8_t val, void *p)
gus->end[gus->voice]=(gus->end[gus->voice]&0x1FFFFF00)|val;
break;
case 0x6: /*Ramp frequency*/
case 6: /*Ramp frequency*/
gus->rfreq[gus->voice] = (int)( (double)((val & 63)*512)/(double)(1 << (3*(val >> 6))));
break;
case 0x9: /*Current volume*/
case 9: /*Current volume*/
gus->curvol[gus->voice] = gus->rcur[gus->voice] = (gus->rcur[gus->voice] & ~(0xff << 6)) | (val << 6);
break;
@@ -259,14 +276,10 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xF807F00)|((val<<7)<<8);
break;
}
break;
case 0x345: /*Global high*/
case 0x305: /*Global high*/
switch (gus->global)
{
case 0: /*Voice control*/
if (!(val&1) && gus->ctrl[gus->voice]&1)
{
}
gus->ctrl[gus->voice] = val & 0x7f;
old = gus->waveirqs[gus->voice];
@@ -294,16 +307,16 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xF807F00)|((val<<7)<<8);
gus->end[gus->voice]=(gus->end[gus->voice]&0x1FFF00FF)|(val<<8);
break;
case 0x6: /*Ramp frequency*/
case 6: /*Ramp frequency*/
gus->rfreq[gus->voice] = (int)( (double)((val & 63) * (1 << 10))/(double)(1 << (3 * (val >> 6))));
break;
case 0x7: /*Ramp start*/
case 7: /*Ramp start*/
gus->rstart[gus->voice] = val << 14;
break;
case 0x8: /*Ramp end*/
case 8: /*Ramp end*/
gus->rend[gus->voice] = val << 14;
break;
case 0x9: /*Current volume*/
case 9: /*Current volume*/
gus->curvol[gus->voice] = gus->rcur[gus->voice] = (gus->rcur[gus->voice] & ~(0xff << 14)) | (val << 14);
break;
@@ -449,11 +462,12 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8);
break;
}
break;
case 0x347: /*DRAM access*/
gus->ram[gus->addr]=val;
case 0x307: /*DRAM access*/
gus->addr&=0xFFFFF;
if (gus->addr < gus->gus_end_ram)
gus->ram[gus->addr]=val;
break;
case 0x248: case 0x388:
case 0x208: case 0x388:
gus->adcommand = val;
break;
@@ -466,7 +480,7 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8);
{
if (gus->sb_nmi)
nmi = 1;
else if (gus->irq != -1)
else
picint(1 << gus->irq);
}
}
@@ -493,34 +507,76 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8);
}
break;
case 0x240:
gus->midi_loopback = val & 0x20;
gus->latch_enable = (val & 0x40) ? 2 : 1;
case 0x200:
gus->latch_enable = val;
break;
case 0x24b:
case 0x20b:
switch (gus->reg_ctrl & 0x07)
{
case 0:
if (gus->latch_enable == 1)
gus->dma = gus_dmas[val & 7];
if (gus->latch_enable == 2)
{
gus->irq = gus_irqs[val & 7];
if (val & 0x40)
{
if (gus->irq == -1)
gus->irq = gus->irq_midi = gus_irqs[(val >> 3) & 7];
else
gus->irq_midi = gus->irq;
}
else
gus->irq_midi = gus_irqs_midi[(val >> 3) & 7];
gus->sb_nmi = val & 0x80;
}
gus->latch_enable = 0;
if (gus->latch_enable & 0x40) {
// GUS SDK: IRQ Control Register
// Channel 1 GF1 IRQ selector (bits 2-0)
// 0=reserved, do not use
// 1=IRQ2
// 2=IRQ5
// 3=IRQ3
// 4=IRQ7
// 5=IRQ11
// 6=IRQ12
// 7=IRQ15
// Channel 2 MIDI IRQ selector (bits 5-3)
// 0=no interrupt
// 1=IRQ2
// 2=IRQ5
// 3=IRQ3
// 4=IRQ7
// 5=IRQ11
// 6=IRQ12
// 7=IRQ15
// Combine both IRQs using channel 1 (bit 6)
// Reserved (bit 7)
//
// "If both channels are sharing an IRQ, channel 2's IRQ must be set to 0 and turn on bit 6. A
// bus conflict will occur if both latches are programmed with the same IRQ #."
if ((val & 7) != 0)
gus->irq = gus_gf1_irqs[val & 7];
if (val & 0x40) // "Combine both IRQs"
gus->irq_midi = gus->irq;
else
gus->irq_midi = gus_midi_irqs[(val >> 3) & 7];
gus->sb_nmi = val & 0x80;
} else {
// GUS SDK: DMA Control Register
// Channel 1 (bits 2-0)
// 0=NO DMA
// 1=DMA1
// 2=DMA3
// 3=DMA5
// 4=DMA6
// 5=DMA7
// 6=?
// 7=?
// Channel 2 (bits 5-3)
// 0=NO DMA
// 1=DMA1
// 2=DMA3
// 3=DMA5
// 4=DMA6
// 5=DMA7
// 6=?
// 7=?
// Combine both DMA channels using channel 1 (bit 6)
// Reserved (bit 7)
//
// "If both channels are sharing an DMA, channel 2's DMA must be set to 0 and turn on bit 6. A
// bus conflict will occur if both latches are programmed with the same DMA #."
if (gus_dmas[val & 7] != -1)
gus->dma = gus_dmas[val & 7];
}
break;
case 1:
gus->gp1 = val;
@@ -542,67 +598,97 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8);
}
break;
case 0x246:
gus->ad_status |= 0x08;
if (gus->sb_ctrl & 0x20)
{
case 0x206:
if (gus->sb_ctrl & 0x20) {
gus->ad_status |= 0x08;
if (gus->sb_nmi)
nmi = 1;
else if (gus->irq != -1)
picint(1 << gus->irq);
nmi = 1;
else if (gus->irq != 0)
picint(1 << gus->irq);
}
break;
case 0x24a:
case 0x20a:
gus->sb_2xa = val;
break;
case 0x24c:
case 0x20c:
gus->ad_status |= 0x10;
if (gus->sb_ctrl & 0x20)
{
if (gus->sb_nmi)
nmi = 1;
else if (gus->irq != -1)
else if (gus->irq != 0)
picint(1 << gus->irq);
}
case 0x24d:
case 0x20d:
gus->sb_2xc = val;
break;
case 0x24e:
case 0x20e:
gus->sb_2xe = val;
break;
case 0x24f:
case 0x20f:
gus->reg_ctrl = val;
break;
}
}
uint8_t readgus(uint16_t addr, void *p)
{
gus_t *gus = (gus_t *)p;
uint8_t val = 0xff;
switch (addr)
uint16_t port;
if ((addr == 0x388) || (addr == 0x389))
port = addr;
else
port = addr & 0xf0f;
switch (port)
{
case 0x340: /*MIDI status*/
val = gus->midi_status;
case 0x300: /*MIDI status*/
val = gus->midi_status;
break;
case 0x341: /*MIDI data*/
val = gus->midi_data;
gus->midi_status &= ~MIDI_INT_RECEIVE;
gus_midi_update_int_status(gus);
case 0x301: /*MIDI data*/
val = 0;
if (gus->uart_in) {
if ((gus->midi_data == 0xaa) && (gus->midi_ctrl & MIDI_CTRL_RECEIVE)) /*Handle master reset*/
val = gus->midi_data;
else {
val = gus->midi_queue[gus->midi_r];
if (gus->midi_r != gus->midi_w) {
gus->midi_r++;
gus->midi_r &= 63;
}
}
gus->midi_status &= ~MIDI_INT_RECEIVE;
gus_midi_update_int_status(gus);
}
break;
case 0x240: return 0;
case 0x246: /*IRQ status*/
case 0x200:
val = 0xff;
break;
case 0x206: /*IRQ status*/
val = gus->irqstatus & ~0x10;
if (gus->ad_status & 0x19)
val |= 0x10;
return val;
break;
case 0x24F: return 0;
case 0x342: return gus->voice;
case 0x343: return gus->global;
case 0x344: /*Global low*/
case 0x20F:
val = 0;
break;
case 0x302:
val = gus->voice;
break;
case 0x303:
val = gus->global;
break;
case 0x304: /*Global low*/
switch (gus->global)
{
case 0x82: /*Start addr high*/
@@ -632,7 +718,7 @@ uint8_t readgus(uint16_t addr, void *p)
break;
}
break;
case 0x345: /*Global high*/
case 0x305: /*Global high*/
switch (gus->global)
{
case 0x80: /*Voice control*/
@@ -681,16 +767,20 @@ uint8_t readgus(uint16_t addr, void *p)
break;
}
break;
case 0x346: return 0xff;
case 0x347: /*DRAM access*/
case 0x306: case 0x706: /*Revision level*/
val = 0xff;
break;
case 0x307: /*DRAM access*/
val=gus->ram[gus->addr];
gus->addr&=0xFFFFF;
return val;
case 0x349: return 0;
case 0x746: /*Revision level*/
return 0xff; /*Pre 3.7 - no mixer*/
if (gus->addr < gus->gus_end_ram)
val = gus->ram[gus->addr];
else
val = 0;
break;
case 0x309: return 0;
case 0x24b:
case 0x20b:
switch (gus->reg_ctrl & 0x07)
{
case 1:
@@ -708,15 +798,15 @@ uint8_t readgus(uint16_t addr, void *p)
}
break;
case 0x24c:
case 0x20c:
val = gus->sb_2xc;
if (gus->reg_ctrl & 0x20)
gus->sb_2xc &= 0x80;
break;
case 0x24e:
case 0x20e:
return gus->sb_2xe;
case 0x248: case 0x388:
case 0x208: case 0x388:
if (gus->tctrl & GUS_TIMER_CTRL_AUTO)
val = gus->sb_2xa;
else
@@ -727,14 +817,14 @@ uint8_t readgus(uint16_t addr, void *p)
}
break;
case 0x249:
case 0x209:
gus->ad_status &= ~0x01;
nmi = 0;
case 0x389:
val = gus->ad_data;
break;
case 0x24A:
case 0x20A:
val = gus->adcommand;
break;
@@ -756,9 +846,9 @@ void gus_poll_timer_1(void *p)
gus->ad_status |= 0x40;
if (gus->tctrl&4)
{
if (gus->irq != -1)
picint(1 << gus->irq);
gus->ad_status |= 0x04;
if (gus->irq != 0)
picint(1 << gus->irq);
gus->ad_status |= 0x04;
gus->irqstatus |= 0x04;
}
}
@@ -767,10 +857,11 @@ void gus_poll_timer_1(void *p)
{
gus->irqnext=0;
gus->irqstatus|=0x80;
if (gus->irq != -1)
picint(1 << gus->irq);
if (gus->irq != 0)
picint(1 << gus->irq);
}
gus_midi_update_int_status(gus);
gus_midi_update_int_status(gus);
}
void gus_poll_timer_2(void *p)
@@ -787,8 +878,8 @@ void gus_poll_timer_2(void *p)
gus->ad_status |= 0x20;
if (gus->tctrl&8)
{
if (gus->irq != -1)
picint(1 << gus->irq);
if (gus->irq != 0)
picint(1 << gus->irq);
gus->ad_status |= 0x02;
gus->irqstatus |= 0x08;
}
@@ -798,8 +889,8 @@ void gus_poll_timer_2(void *p)
{
gus->irqnext=0;
gus->irqstatus|=0x80;
if (gus->irq != -1)
picint(1 << gus->irq);
if (gus->irq != 0)
picint(1 << gus->irq);
}
}
@@ -998,16 +1089,57 @@ static void gus_get_buffer(int32_t *buffer, int len, void *p)
gus->pos = 0;
}
static void gus_input_msg(void *p, uint8_t *msg)
{
gus_t *gus = (gus_t *)p;
uint8_t i;
if (gus->sysex)
return;
if (gus->uart_in) {
gus->midi_status |= MIDI_INT_RECEIVE;
for (i=0;i<msg[3];i++) {
gus->midi_queue[gus->midi_w++] = msg[i];
gus->midi_w &= 63;
}
gus_midi_update_int_status(gus);
}
}
static int gus_input_sysex(void *p, uint8_t *buffer, uint32_t len, int abort)
{
gus_t *gus = (gus_t *)p;
uint32_t i;
if (abort) {
gus->sysex = 0;
return 0;
}
gus->sysex = 1;
for (i=0;i<len;i++) {
if (gus->midi_r == gus->midi_w)
return (len-i);
gus->midi_queue[gus->midi_w++] = buffer[i];
gus->midi_w &= 63;
}
gus->sysex = 0;
return 0;
}
void *gus_init(const device_t *info)
{
int c;
double out = 1.0;
uint8_t gus_ram = device_get_config_int("gus_ram");
gus_t *gus = malloc(sizeof(gus_t));
memset(gus, 0, sizeof(gus_t));
gus->ram = malloc(1 << 20);
memset(gus->ram, 0, 1 << 20);
gus->gus_end_ram = 1 << (18 + gus_ram);
gus->ram = (uint8_t *)malloc(gus->gus_end_ram);
memset(gus->ram, 0x00, (gus->gus_end_ram));
for (c=0;c<32;c++)
{
@@ -1026,10 +1158,14 @@ void *gus_init(const device_t *info)
gus->samp_latch = (uint64_t)(TIMER_USEC * (1000000.0 / 44100.0));
gus->t1l = gus->t2l = 0xff;
gus->uart_out = 1;
gus->base = device_get_config_hex16("base");
io_sethandler(0x0240, 0x0010, readgus, NULL, NULL, writegus, NULL, NULL, gus);
io_sethandler(0x0340, 0x0010, readgus, NULL, NULL, writegus, NULL, NULL, gus);
io_sethandler(0x0746, 0x0001, readgus, NULL, NULL, writegus, NULL, NULL, gus);
io_sethandler(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(0x0388, 0x0002, readgus, NULL, NULL, writegus, NULL, NULL, gus);
timer_add(&gus->samp_timer, gus_poll_wave, gus, 1);
timer_add(&gus->timer_1, gus_poll_timer_1, gus, 1);
@@ -1037,6 +1173,10 @@ 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;
return gus;
}
@@ -1058,11 +1198,76 @@ void gus_speed_changed(void *p)
gus->samp_latch = (uint64_t)(TIMER_USEC * (1000000.0 / gusfreqs[gus->voices - 14]));
}
static const device_config_t gus_config[] = {
{
"type", "GUS type", CONFIG_SELECTION, "", 0,
{
{
"Classic", GUS_CLASSIC
},
#if 0
{
"MAX", GUS_MAX
},
#endif
{
NULL
}
},
},
{
"base", "Address", CONFIG_HEX16, "", 0x220,
{
{
"210H", 0x210
},
{
"220H", 0x220
},
{
"230H", 0x230
},
{
"240H", 0x240
},
{
"250H", 0x250
},
{
"260H", 0x260
},
},
},
{
"gus_ram", "Onboard RAM", CONFIG_SELECTION, "", 0,
{
{
"256 KB", 0
},
{
"512 KB", 1
},
{
"1 MB", 2
},
{
NULL
}
}
},
{
"", "", -1
}
};
const device_t gus_device =
{
"Gravis UltraSound",
0, 0,
gus_init, gus_close, NULL, NULL,
gus_speed_changed, NULL,
NULL
DEVICE_ISA,
0,
gus_init, gus_close, NULL,
NULL,
gus_speed_changed,
NULL,
gus_config
};

File diff suppressed because it is too large Load Diff

View File

@@ -8,7 +8,7 @@
*
* Roland MPU-401 emulation.
*
* Version: @(#)sound_mpu401.h 1.0.3 2018/09/11
* Version: @(#)sound_mpu401.h 1.0.4 2018/09/31
*
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
* DOSBox Team,
@@ -22,10 +22,16 @@
#define MPU401_VERSION 0x15
#define MPU401_REVISION 0x01
#define MPU401_QUEUE 32
#define MPU401_QUEUE 64
#define MPU401_INPUT_QUEUE 1024
#define MPU401_TIMECONSTANT (60000000/1000.0f)
#define MPU401_RESETBUSY 27.0f
/*helpers*/
#define M_GETKEY key[key/32]&(1<<(key%32))
#define M_SETKEY key[key/32]|=(1<<(key%32))
#define M_DELKEY key[key/32]&=~(1<<(key%32))
typedef enum MpuMode
{
M_UART,
@@ -43,6 +49,13 @@ typedef enum MpuDataType
T_COMMAND
} MpuDataType;
typedef enum RecState
{
M_RECOFF,
M_RECSTB,
M_RECON
} RecState;
/* Messages sent to MPU-401 from host */
#define MSG_EOX 0xf7
#define MSG_OVERFLOW 0xf8
@@ -57,6 +70,7 @@ typedef enum MpuDataType
typedef struct mpu_t
{
int midi_thru;
int uart_mode, intelligent,
irq,
queue_pos, queue_used;
@@ -64,10 +78,13 @@ typedef struct mpu_t
status,
queue[MPU401_QUEUE], pos_regs[8];
MpuMode mode;
uint8_t rec_queue[MPU401_INPUT_QUEUE];
int rec_queue_pos, rec_queue_used;
uint32_t ch_toref[16];
struct track
{
int counter;
uint8_t value[8], sys_val,
uint8_t value[3], sys_val,
vlength,length;
MpuDataType type;
} playbuf[8], condbuf;
@@ -77,23 +94,50 @@ typedef struct mpu_t
playing, reset,
wsd, wsm, wsd_start,
run_irq, irq_pending,
track_req,
send_now, eoi_scheduled,
data_onoff;
data_onoff, clock_to_host,
sync_in, sysex_in_finished,
rec_copy;
RecState rec;
uint8_t tmask, cmask,
amask,
channel, old_chan;
last_rtcmd;
uint16_t midi_mask, req_mask;
uint32_t command_byte, cmd_pending;
uint32_t command_byte, cmd_pending,
track, old_track;
} state;
struct {
uint8_t timebase, old_timebase,
tempo, old_tempo,
tempo_rel, old_tempo_rel,
tempo_grad,
cth_rate, cth_counter;
int clock_to_host,cth_active;
tempo_grad, cth_rate[4],
cth_mode, midimetro,
metromeas;
uint32_t cth_counter, cth_old,
rec_counter;
int32_t measure_counter, meas_old,
freq;
int ticks_in, active;
float freq_mod;
} clock;
struct {
int all_thru, midi_thru,
sysex_thru, commonmsgs_thru,
modemsgs_in, commonmsgs_in,
bender_in, sysex_in,
allnotesoff_out, rt_affection,
rt_out, rt_in,
timing_in_stop, data_in_stop,
rec_measure_end;
uint8_t prchg_buf[16];
uint16_t prchg_mask;
} filter;
struct {
int on;
uint8_t chan, trmask;
uint32_t key[4];
} chanref[5], inputref[16];
pc_timer_t mpu401_event_callback, mpu401_eoi_callback,
mpu401_reset_callback;
} mpu_t;

View File

@@ -32,6 +32,7 @@
#include "../rom.h"
#include "../device.h"
#include "sound.h"
#include "midi.h"
#include "filters.h"
#include "snd_emu8k.h"
#include "snd_mpu401.h"
@@ -1041,6 +1042,11 @@ void *sb_1_init()
io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl);
}
sound_add_handler(sb_get_buffer_sb2, sb);
input_msg = sb_dsp_input_msg;
input_sysex = sb_dsp_input_sysex;
midi_in_p = &sb->dsp;
return sb;
}
void *sb_15_init()
@@ -1067,6 +1073,11 @@ void *sb_15_init()
io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &sb->opl);
}
sound_add_handler(sb_get_buffer_sb2, sb);
input_msg = sb_dsp_input_msg;
input_sysex = sb_dsp_input_sysex;
midi_in_p = &sb->dsp;
return sb;
}
@@ -1090,6 +1101,11 @@ void *sb_mcv_init()
mca_add(sb_mcv_read, sb_mcv_write, sb_mcv_feedb, sb);
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;
return sb;
}
void *sb_2_init()
@@ -1137,6 +1153,10 @@ 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;
return sb;
}
@@ -1170,6 +1190,10 @@ 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;
return sb;
}
@@ -1202,6 +1226,10 @@ 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;
return sb;
}
@@ -1227,6 +1255,10 @@ 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;
return sb;
}
@@ -1261,6 +1293,11 @@ void *sb_16_init()
} else
sb->mpu = NULL;
input_msg = sb_dsp_input_msg;
input_sysex = sb_dsp_input_sysex;
midi_in_p = &sb->dsp;
return sb;
}
@@ -1305,6 +1342,10 @@ void *sb_awe32_init()
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;
return sb;
}

View File

@@ -147,7 +147,6 @@ sinc(double x)
return sin(M_PI * x) / (M_PI * x);
}
static void
recalc_sb16_filter(int playback_freq)
{
@@ -207,6 +206,8 @@ sb_irqc(sb_dsp_t *dsp, int irq8)
void
sb_dsp_reset(sb_dsp_t *dsp)
{
midi_clear_buffer();
timer_disable(&dsp->output_timer);
timer_disable(&dsp->input_timer);
@@ -218,7 +219,7 @@ sb_dsp_reset(sb_dsp_t *dsp)
sb_irqc(dsp, 0);
sb_irqc(dsp, 1);
dsp->sb_16_pause = 0;
dsp->sb_read_wp = dsp->sb_read_rp = 0;
dsp->sb_read_wp = dsp->sb_read_rp = 0;
dsp->sb_data_stat = -1;
dsp->sb_speaker = 0;
dsp->sb_pausetime = -1LL;
@@ -393,7 +394,6 @@ sb_dsp_setdma16(sb_dsp_t *dsp, int dma)
dsp->sb_16_dmanum = dma;
}
void
sb_exec_command(sb_dsp_t *dsp)
{
@@ -457,19 +457,35 @@ sb_exec_command(sb_dsp_t *dsp)
if (dsp->sb_type >= SB15)
sb_start_dma_i(dsp, 1, 1, 0, dsp->sb_data[0] + (dsp->sb_data[1] << 8));
break;
case 0x30: case 0x31:
case 0x30: /* MIDI Polling mode input */
sb_dsp_log("MIDI polling mode input\n");
dsp->midi_in_poll = 1;
dsp->uart_irq = 0;
break;
case 0x34: /* MIDI (UART mode) */
case 0x31: /* MIDI Interrupt mode input */
sb_dsp_log("MIDI interrupt mode input\n");
dsp->midi_in_poll = 0;
dsp->uart_irq = 1;
break;
case 0x34: /* MIDI In poll */
if (dsp->sb_type < SB2)
break;
sb_dsp_log("MIDI poll in\n");
dsp->midi_in_poll = 1;
dsp->uart_midi = 1;
dsp->uart_irq = 0;
break;
case 0x35: /* MIDI (UART mode) */
case 0x35: /* MIDI In irq */
if (dsp->sb_type < SB2)
break;
sb_dsp_log("MIDI irq in\n");
dsp->midi_in_poll = 0;
dsp->uart_midi = 1;
dsp->uart_irq = 1;
break;
case 0x36: case 0x37:
case 0x36: case 0x37: /* MIDI timestamps */
break;
case 0x38: /* MIDI (Normal mode) */
case 0x38: /* Write to SB MIDI Output (Raw) */
dsp->onebyte_midi = 1;
break;
case 0x40: /* Set time constant */
@@ -724,17 +740,22 @@ sb_write(uint16_t a, uint8_t v, void *priv)
switch (a & 0xF) {
case 6: /* Reset */
if (!(v & 1) && (dsp->sbreset & 1)) {
sb_dsp_reset(dsp);
sb_add_data(dsp, 0xAA);
if (!dsp->uart_midi) {
if (!(v & 1) && (dsp->sbreset & 1)) {
sb_dsp_reset(dsp);
sb_add_data(dsp, 0xAA);
}
dsp->sbreset = v;
}
dsp->sbreset = v;
dsp->uart_midi = 0;
dsp->uart_irq = 0;
dsp->onebyte_midi = 0;
return;
case 0xC: /* Command/data write */
if (dsp->uart_midi || dsp->onebyte_midi) {
midi_write(v);
if (dsp->uart_midi || dsp->onebyte_midi ) {
midi_raw_out_byte(v);
dsp->onebyte_midi = 0;
return;
return;
}
timer_set_delay_u64(&dsp->wb_timer, TIMER_USEC * 1);
if (dsp->asp_data_len) {
@@ -768,9 +789,9 @@ sb_read(uint16_t a, void *priv)
switch (a & 0xf) {
case 0xA: /* Read data */
if (mpu && dsp->uart_midi)
if (mpu && dsp->uart_midi) {
ret = MPU401_ReadData(mpu);
else {
} else {
dsp->sbreaddat = dsp->sb_read_data[dsp->sb_read_rp];
if (dsp->sb_read_rp != dsp->sb_read_wp) {
dsp->sb_read_rp++;
@@ -814,6 +835,53 @@ sb_dsp_set_mpu(mpu_t *src_mpu)
mpu = src_mpu;
}
void
sb_dsp_input_msg(void *p, uint8_t *msg)
{
sb_dsp_t *dsp = (sb_dsp_t *) p;
sb_dsp_log("MIDI in sysex = %d, uart irq = %d, msg = %d\n", dsp->midi_in_sysex, dsp->uart_irq, msg[3]);
if (dsp->midi_in_sysex) {
return;
}
uint8_t len = msg[3];
uint8_t i = 0;
if (dsp->uart_irq) {
for (i=0;i<len;i++)
sb_add_data(dsp, msg[i]);
sb_dsp_log("SB IRQ8 = %d\n", dsp->sb_irq8);
if (!dsp->sb_irq8)
picint(1 << dsp->sb_irqnum);
} else if (dsp->midi_in_poll) {
for (i=0;i<len;i++)
sb_add_data(dsp, msg[i]);
}
}
int
sb_dsp_input_sysex(void *p, uint8_t *buffer, uint32_t len, int abort)
{
sb_dsp_t *dsp = (sb_dsp_t *) p;
uint32_t i;
if (abort) {
dsp->midi_in_sysex = 0;
return 0;
}
dsp->midi_in_sysex = 1;
for (i=0;i<len;i++) {
if (dsp->sb_read_rp == dsp->sb_read_wp) {
sb_dsp_log("Length sysex SB = %d\n", len-i);
return (len-i);
}
sb_add_data(dsp, buffer[i]);
}
dsp->midi_in_sysex = 0;
return 0;
}
void
sb_dsp_init(sb_dsp_t *dsp, int type)
@@ -881,7 +949,7 @@ pollsb(void *p)
break;
dsp->sbdat = (data[0] ^ 0x80) << 8;
if ((dsp->sb_type >= SBPRO) && (dsp->sb_type < SB16) && dsp->stereo) {
pclog("pollsb: Mono unsigned, dsp->stereo, %s channel, %04X\n",
sb_dsp_log("pollsb: Mono unsigned, dsp->stereo, %s channel, %04X\n",
dsp->sbleftright ? "left" : "right", dsp->sbdat);
if (dsp->sbleftright)
dsp->sbdatl = dsp->sbdat;
@@ -898,7 +966,7 @@ pollsb(void *p)
break;
dsp->sbdat = data[0] << 8;
if ((dsp->sb_type >= SBPRO) && (dsp->sb_type < SB16) && dsp->stereo) {
pclog("pollsb: Mono signed, dsp->stereo, %s channel, %04X\n",
sb_dsp_log("pollsb: Mono signed, dsp->stereo, %s channel, %04X\n",
dsp->sbleftright ? "left" : "right", data[0], dsp->sbdat);
if (dsp->sbleftright)
dsp->sbdatl = dsp->sbdat;
@@ -958,7 +1026,7 @@ pollsb(void *p)
}
if ((dsp->sb_type >= SBPRO) && (dsp->sb_type < SB16) && dsp->stereo) {
pclog("pollsb: ADPCM 4, dsp->stereo, %s channel, %04X\n",
sb_dsp_log("pollsb: ADPCM 4, dsp->stereo, %s channel, %04X\n",
dsp->sbleftright ? "left" : "right", dsp->sbdat);
if (dsp->sbleftright)
dsp->sbdatl = dsp->sbdat;
@@ -1001,7 +1069,7 @@ pollsb(void *p)
}
if ((dsp->sb_type >= SBPRO) && (dsp->sb_type < SB16) && dsp->stereo) {
pclog("pollsb: ADPCM 26, dsp->stereo, %s channel, %04X\n",
sb_dsp_log("pollsb: ADPCM 26, dsp->stereo, %s channel, %04X\n",
dsp->sbleftright ? "left" : "right", dsp->sbdat);
if (dsp->sbleftright)
dsp->sbdatl = dsp->sbdat;
@@ -1037,7 +1105,7 @@ pollsb(void *p)
}
if ((dsp->sb_type >= SBPRO) && (dsp->sb_type < SB16) && dsp->stereo) {
pclog("pollsb: ADPCM 2, dsp->stereo, %s channel, %04X\n",
sb_dsp_log("pollsb: ADPCM 2, dsp->stereo, %s channel, %04X\n",
dsp->sbleftright ? "left" : "right", dsp->sbdat);
if (dsp->sbleftright)
dsp->sbdatl = dsp->sbdat;

View File

@@ -9,14 +9,18 @@ typedef struct sb_dsp_t
int sb_pausetime;
uint8_t sb_read_data[256];
int sb_read_wp, sb_read_rp;
int sb_read_wp, sb_read_rp;
int sb_speaker;
int muted;
int sb_data_stat;
int uart_midi;
int uart_irq;
int onebyte_midi;
int midi_in_sysex;
int midi_in_poll;
int uart_midi;
int uart_irq;
int onebyte_midi;
int midi_in_timestamp;
int sb_irqnum;
@@ -72,6 +76,11 @@ typedef struct sb_dsp_t
int pos;
} sb_dsp_t;
void sb_dsp_input_msg(void *p, uint8_t *msg);
int sb_dsp_input_sysex(void *p, uint8_t *buffer, uint32_t len, int abort);
void sb_dsp_set_mpu(mpu_t *src_mpu);
void sb_dsp_init(sb_dsp_t *dsp, int type);

View File

@@ -107,7 +107,6 @@ static const SOUND_CARD sound_cards[] =
{ "[MCA] Sound Blaster MCV", "sbmcv", &sb_mcv_device },
{ "[MCA] Sound Blaster Pro MCV", "sbpromcv", &sb_pro_mcv_device },
{ "[PCI] Ensoniq AudioPCI (ES1371)", "es1371", &es1371_device },
{ "[PCI] Sound Blaster PCI 128", "sbpci128", &es1371_device },
{ "", "", NULL }
};
@@ -442,6 +441,7 @@ sound_reset(void)
sound_realloc_buffers();
midi_device_init();
midi_in_device_init();
inital();
timer_add(&sound_poll_timer, sound_poll, NULL, 1);

View File

@@ -366,7 +366,7 @@ BEGIN
PUSHBUTTON "Joystick 4...",IDC_JOY4,209,44,50,14
END
DLG_CFG_SOUND DIALOG DISCARDABLE 97, 0, 267, 116
DLG_CFG_SOUND DIALOG DISCARDABLE 97, 0, 267, 199
STYLE DS_CONTROL | WS_CHILD
FONT 9, "Segoe UI"
BEGIN
@@ -380,34 +380,41 @@ BEGIN
LTEXT "MIDI Out Device:",IDT_1712,7,26,59,10
PUSHBUTTON "Configure",IDC_CONFIGURE_MIDI,214,25,46,12
COMBOBOX IDC_COMBO_MIDI_IN,71,43,140,120,CBS_DROPDOWNLIST | WS_VSCROLL |
WS_TABSTOP
LTEXT "MIDI In Device:",IDT_1713,7,44,59,10
PUSHBUTTON "Configure",IDC_CONFIGURE_MIDI_IN,214,43,46,12
CONTROL "Standalone MPU-401",IDC_CHECK_MPU401,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,7,45,199,10
PUSHBUTTON "Configure",IDC_CONFIGURE_MPU401,214,44,46,12
BS_AUTOCHECKBOX | WS_TABSTOP,7,65,199,10
PUSHBUTTON "Configure",IDC_CONFIGURE_MPU401,214,64,46,12
CONTROL "Innovation SSI-2001",IDC_CHECK_SSI,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,7,63,94,10
BS_AUTOCHECKBOX | WS_TABSTOP,7,83,94,10
CONTROL "CMS / Game Blaster",IDC_CHECK_CMS,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,147,63,94,10
BS_AUTOCHECKBOX | WS_TABSTOP,147,83,94,10
CONTROL "Gravis Ultrasound",IDC_CHECK_GUS,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,7,81,94,10
BS_AUTOCHECKBOX | WS_TABSTOP,7,99,94,10
PUSHBUTTON "Configure",IDC_CONFIGURE_GUS,214,99,46,12
CONTROL "Use FLOAT32 sound",IDC_CHECK_FLOAT,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,147,81,94,10
BS_AUTOCHECKBOX | WS_TABSTOP,7,115,94,10
END
DLG_CFG_NETWORK DIALOG DISCARDABLE 97, 0, 267, 63
STYLE DS_CONTROL | WS_CHILD
FONT 9, "Segoe UI"
BEGIN
LTEXT "Network type:",IDT_1713,7,8,59,10
LTEXT "Network type:",IDT_1714,7,8,59,10
COMBOBOX IDC_COMBO_NET_TYPE,71,7,189,120,CBS_DROPDOWNLIST | WS_VSCROLL |
WS_TABSTOP
LTEXT "PCap device:",IDT_1714,7,26,59,10
LTEXT "PCap device:",IDT_1715,7,26,59,10
COMBOBOX IDC_COMBO_PCAP,71,25,189,120,CBS_DROPDOWNLIST | WS_VSCROLL |
WS_TABSTOP
LTEXT "Network adapter:",IDT_1715,7,44,59,10
LTEXT "Network adapter:",IDT_1716,7,44,59,10
COMBOBOX IDC_COMBO_NET,71,43,140,120,CBS_DROPDOWNLIST | WS_VSCROLL |
WS_TABSTOP
PUSHBUTTON "Configure",IDC_CONFIGURE_NET,214,43,46,12
@@ -417,15 +424,15 @@ DLG_CFG_PORTS DIALOG DISCARDABLE 97, 0, 267, 117
STYLE DS_CONTROL | WS_CHILD
FONT 9, "Segoe UI"
BEGIN
LTEXT "LPT1 Device:",IDT_1716,7,8,61,10
LTEXT "LPT1 Device:",IDT_1717,7,8,61,10
COMBOBOX IDC_COMBO_LPT1,71,7,189,120,CBS_DROPDOWNLIST |
WS_VSCROLL | WS_TABSTOP
LTEXT "LPT2 Device:",IDT_1717,7,27,61,10
LTEXT "LPT2 Device:",IDT_1718,7,27,61,10
COMBOBOX IDC_COMBO_LPT2,71,26,189,120,CBS_DROPDOWNLIST |
WS_VSCROLL | WS_TABSTOP
LTEXT "LPT3 Device:",IDT_1718,7,46,61,10
LTEXT "LPT3 Device:",IDT_1719,7,46,61,10
COMBOBOX IDC_COMBO_LPT3,71,45,189,120,CBS_DROPDOWNLIST |
WS_VSCROLL | WS_TABSTOP
@@ -446,12 +453,12 @@ DLG_CFG_PERIPHERALS DIALOG DISCARDABLE 97, 0, 267, 200
STYLE DS_CONTROL | WS_CHILD
FONT 9, "Segoe UI"
BEGIN
LTEXT "SCSI Controller:",IDT_1716,7,8,48,10
LTEXT "SCSI Controller:",IDT_1717,7,8,48,10
COMBOBOX IDC_COMBO_SCSI,64,7,155,120,CBS_DROPDOWNLIST |
WS_VSCROLL | WS_TABSTOP
PUSHBUTTON "Configure",IDC_CONFIGURE_SCSI,222,7,38,12
LTEXT "HD Controller:",IDT_1717,7,26,48,10
LTEXT "HD Controller:",IDT_1718,7,26,48,10
COMBOBOX IDC_COMBO_HDC,64,25,155,120,CBS_DROPDOWNLIST |
WS_VSCROLL | WS_TABSTOP
PUSHBUTTON "Configure",IDC_CONFIGURE_HDC,222,25,38,12

View File

@@ -54,12 +54,13 @@
#define IDT_1710 1710 /* Joystick: */
#define IDT_1711 1711 /* Sound card: */
#define IDT_1712 1712 /* MIDI Out Device: */
#define IDT_1713 1713 /* Network type: */
#define IDT_1714 1714 /* PCap device: */
#define IDT_1715 1715 /* Network adapter: */
#define IDT_1716 1716 /* SCSI Controller: */
#define IDT_1717 1717 /* HD Controller: */
#define IDT_1718 1718
#define IDT_1713 1713 /* MIDI In Device: */
#define IDT_1714 1714 /* Network type: */
#define IDT_1715 1715 /* PCap device: */
#define IDT_1716 1716 /* Network adapter: */
#define IDT_1717 1717 /* SCSI Controller: */
#define IDT_1718 1718 /* HD Controller: */
#define IDT_1719 1719
#define IDT_1720 1720 /* Hard disks: */
#define IDT_1721 1721 /* Bus: */
#define IDT_1722 1722 /* Channel: */
@@ -148,7 +149,8 @@
#define IDC_CHECK_MPU401 1076
#define IDC_CONFIGURE_MPU401 1077
#define IDC_CHECK_FLOAT 1078
#define IDC_CHECK_GUSMAX 1079
#define IDC_CONFIGURE_GUS 1079
#define IDC_COMBO_MIDI_IN 1080
#define IDC_COMBO_NET_TYPE 1090 /* network config */
#define IDC_COMBO_PCAP 1091
@@ -241,6 +243,7 @@
#define IDC_CONFIGURE_PCAP 1306
#define IDC_CONFIGURE_NET 1307
#define IDC_CONFIGURE_MIDI 1308
#define IDC_CONFIGURE_MIDI_IN 1309
#define IDC_JOY1 1310
#define IDC_JOY2 1311
#define IDC_JOY3 1312

View File

@@ -108,6 +108,21 @@ deviceconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam)
id += 2;
break;
case CONFIG_MIDI_IN:
val_int = config_get_int((char *) config_device.name,
(char *) config->name, config->default_int);
num = plat_midi_in_get_num_devs();
for (c = 0; c < num; c++) {
plat_midi_in_get_dev_name(c, s);
mbstowcs(lptsTemp, s, strlen(s) + 1);
SendMessage(h, CB_ADDSTRING, 0, (LPARAM)(LPCSTR)lptsTemp);
if (val_int == c)
SendMessage(h, CB_SETCURSEL, c, 0);
}
id += 2;
break;
case CONFIG_SPINNER:
val_int = config_get_int((char *) config_device.name,
(char *) config->name, config->default_int);
@@ -205,6 +220,17 @@ deviceconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam)
c = SendMessage(h, CB_GETCURSEL, 0, 0);
if (val_int != c)
changed = 1;
id += 2;
break;
case CONFIG_MIDI_IN:
val_int = config_get_int((char *) config_device.name,
(char *) config->name, config->default_int);
c = SendMessage(h, CB_GETCURSEL, 0, 0);
if (val_int != c)
changed = 1;
@@ -302,6 +328,12 @@ deviceconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam)
c = SendMessage(h, CB_GETCURSEL, 0, 0);
config_set_int((char *) config_device.name, (char *) config->name, c);
id += 2;
break;
case CONFIG_MIDI_IN:
c = SendMessage(h, CB_GETCURSEL, 0, 0);
config_set_int((char *) config_device.name, (char *) config->name, c);
id += 2;
break;
case CONFIG_FNAME:
@@ -358,6 +390,7 @@ deviceconfig_dlgproc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam)
break;
case CONFIG_SELECTION:
case CONFIG_MIDI:
case CONFIG_MIDI_IN:
case CONFIG_SPINNER:
id += 2;
break;
@@ -478,6 +511,7 @@ deviceconfig_inst_open(HWND hwnd, const device_t *device, int inst)
case CONFIG_SELECTION:
case CONFIG_MIDI:
case CONFIG_MIDI_IN:
case CONFIG_HEX16:
case CONFIG_HEX20:
/*Combo box*/

View File

@@ -13,16 +13,17 @@
typedef struct
{
int midi_id;
int midi_id, midi_input_id;
HANDLE m_event;
HMIDIOUT midi_out_device;
HMIDIIN midi_in_device;
MIDIHDR m_hdr;
} plat_midi_t;
plat_midi_t *pm = NULL;
plat_midi_t *pm = NULL, *pm_in = NULL;
void
@@ -65,7 +66,7 @@ plat_midi_close(void)
midiOutClose(pm->midi_out_device);
CloseHandle(pm->m_event);
}
free(pm);
pm = NULL;
}
@@ -135,3 +136,117 @@ plat_midi_write(uint8_t val)
{
return 0;
}
void CALLBACK
plat_midi_in_callback(HMIDIIN hMidiIn, UINT wMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
{
uint8_t msg[4] = {((dwParam1&0xff)),(((dwParam1&0xff00)>>8)),
(((dwParam1&0xff0000)>>16)),MIDI_evt_len[((dwParam1&0xff))]};
uint8_t *sysex;
uint32_t len;
int cnt;
MIDIHDR *hdr;
switch (wMsg) {
case MM_MIM_DATA: /* 0x3C3 - midi message */
input_msg(midi_in_p, msg);
break;
case MM_MIM_OPEN: /* 0x3C1 */
break;
case MM_MIM_CLOSE: /* 0x3C2 */
break;
case MM_MIM_LONGDATA: /* 0x3C4 - sysex */
hdr = (MIDIHDR *)dwParam1;
sysex = (uint8_t *)hdr->lpData;
len = (uint32_t)hdr->dwBytesRecorded;
cnt = 5;
while (cnt) { /*abort if timed out*/
int ret = input_sysex(midi_in_p, sysex, len, 0);
if (!ret) {
len = 0;
break;
}
if (len==ret)
cnt--;
else
cnt = 5;
sysex += len-ret;
len = ret;
Sleep(5);/*msec*/
}
if (len)
input_sysex(midi_in_p, sysex, 0, 0);
midiInUnprepareHeader(hMidiIn, hdr, sizeof(*hdr));
hdr->dwBytesRecorded = 0;
midiInPrepareHeader(hMidiIn, hdr, sizeof(*hdr));
break;
case MM_MIM_ERROR:
case MM_MIM_LONGERROR:
break;
default:
break;
}
}
void
plat_midi_input_init(void)
{
MMRESULT hr;
pm_in = (plat_midi_t *) malloc(sizeof(plat_midi_t));
memset(pm_in, 0, sizeof(plat_midi_t));
pm_in->midi_input_id = config_get_int(MIDI_INPUT_NAME, "midi_input", 0);
hr = MMSYSERR_NOERROR;
hr = midiInOpen(&pm_in->midi_in_device, pm_in->midi_input_id,
(uintptr_t) plat_midi_in_callback, 0, CALLBACK_FUNCTION);
if (hr != MMSYSERR_NOERROR) {
printf("midiInOpen error - %08X\n", hr);
pm_in->midi_input_id = 0;
hr = midiInOpen(&pm_in->midi_in_device, pm_in->midi_input_id,
(uintptr_t) plat_midi_in_callback, 0, CALLBACK_FUNCTION);
if (hr != MMSYSERR_NOERROR) {
printf("midiInOpen error - %08X\n", hr);
return;
}
}
pm_in->m_hdr.lpData = (char*)&MIDI_InSysexBuf[0];
pm_in->m_hdr.dwBufferLength = SYSEX_SIZE;
pm_in->m_hdr.dwBytesRecorded = 0;
pm_in->m_hdr.dwUser = 0;
midiInPrepareHeader(pm_in->midi_in_device,&pm_in->m_hdr,sizeof(pm_in->m_hdr));
midiInStart(pm_in->midi_in_device);
}
void
plat_midi_input_close(void)
{
if (pm_in) {
if (pm_in->midi_in_device != NULL) {
midiInStop(pm_in->midi_in_device);
midiInClose(pm_in->midi_in_device);
}
free(pm_in);
pm_in = NULL;
}
}
int
plat_midi_in_get_num_devs(void)
{
return midiInGetNumDevs();
}
void
plat_midi_in_get_dev_name(int num, char *s)
{
MIDIINCAPS caps;
midiInGetDevCaps(num, &caps, sizeof(caps));
strcpy(s, caps.szPname);
}

View File

@@ -56,6 +56,7 @@
#include "../sound/sound.h"
#include "../sound/midi.h"
#include "../sound/snd_mpu401.h"
#include "../sound/snd_gus.h"
#include "../video/video.h"
#include "../video/vid_voodoo.h"
#include "../plat.h"
@@ -84,7 +85,7 @@ static int temp_gfxcard, temp_voodoo;
static int temp_mouse, temp_joystick;
/* Sound category */
static int temp_sound_card, temp_midi_device, temp_mpu401, temp_SSI2001, temp_GAMEBLASTER, temp_GUS;
static int temp_sound_card, temp_midi_device, temp_midi_input_device, temp_mpu401, temp_SSI2001, temp_GAMEBLASTER, temp_GUS;
static int temp_float;
/* Network category */
@@ -123,6 +124,7 @@ extern int is486;
static int listtomachine[256], machinetolist[256];
static int settings_device_to_list[2][20], settings_list_to_device[2][20];
static int settings_midi_to_list[20], settings_list_to_midi[20];
static int settings_midi_in_to_list[20], settings_list_to_midi_in[20];
static int max_spt = 63, max_hpc = 255, max_tracks = 266305;
static uint64_t mfm_tracking, esdi_tracking, xta_tracking, ide_tracking, scsi_tracking[2];
@@ -218,6 +220,7 @@ win_settings_init(void)
/* Sound category */
temp_sound_card = sound_card_current;
temp_midi_device = midi_device_current;
temp_midi_input_device = midi_input_device_current;
temp_mpu401 = mpu401_standalone_enable;
temp_SSI2001 = SSI2001;
temp_GAMEBLASTER = GAMEBLASTER;
@@ -329,6 +332,7 @@ win_settings_changed(void)
/* Sound category */
i = i || (sound_card_current != temp_sound_card);
i = i || (midi_device_current != temp_midi_device);
i = i || (midi_input_device_current != temp_midi_input_device);
i = i || (mpu401_standalone_enable != temp_mpu401);
i = i || (SSI2001 != temp_SSI2001);
i = i || (GAMEBLASTER != temp_GAMEBLASTER);
@@ -431,6 +435,7 @@ win_settings_save(void)
/* Sound category */
sound_card_current = temp_sound_card;
midi_device_current = temp_midi_device;
midi_input_device_current = temp_midi_input_device;
mpu401_standalone_enable = temp_mpu401;
SSI2001 = temp_SSI2001;
GAMEBLASTER = temp_GAMEBLASTER;
@@ -1100,19 +1105,19 @@ mpu401_present(void)
int
mpu401_standalone_allow(void)
{
char *md;
char *md, *mdin;
md = midi_device_get_internal_name(temp_midi_device);
mdin = midi_in_device_get_internal_name(temp_midi_input_device);
if (md != NULL) {
if (!strcmp(md, "none"))
if (!strcmp(md, "none") && !strcmp(mdin, "none"))
return 0;
}
return 1;
}
#if defined(__amd64__) || defined(__aarch64__)
static LRESULT CALLBACK
#else
@@ -1195,19 +1200,55 @@ win_settings_sound_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam)
else
EnableWindow(h, FALSE);
h = GetDlgItem(hdlg, IDC_COMBO_MIDI_IN);
c = d = 0;
while (1) {
s = midi_in_device_getname(c);
if (!s[0])
break;
settings_midi_in_to_list[c] = d;
if (midi_in_device_available(c)) {
if (c == 0)
SendMessage(h, CB_ADDSTRING, 0, win_get_string(IDS_2112));
else {
mbstowcs(lptsTemp, s, strlen(s) + 1);
SendMessage(h, CB_ADDSTRING, 0, (LPARAM) lptsTemp);
}
settings_list_to_midi_in[d] = c;
d++;
}
c++;
}
SendMessage(h, CB_SETCURSEL, settings_midi_in_to_list[temp_midi_input_device], 0);
h = GetDlgItem(hdlg, IDC_CONFIGURE_MIDI_IN);
if (midi_in_device_has_config(temp_midi_input_device))
EnableWindow(h, TRUE);
else
EnableWindow(h, FALSE);
h = GetDlgItem(hdlg, IDC_CHECK_MPU401);
SendMessage(h, BM_SETCHECK, temp_mpu401, 0);
EnableWindow(h, mpu401_standalone_allow() ? TRUE : FALSE);
h = GetDlgItem(hdlg, IDC_CONFIGURE_MPU401);
EnableWindow(h, (mpu401_standalone_allow() && temp_mpu401) ? TRUE : FALSE);
h=GetDlgItem(hdlg, IDC_CHECK_CMS);
SendMessage(h, BM_SETCHECK, temp_GAMEBLASTER, 0);
h=GetDlgItem(hdlg, IDC_CHECK_GUS);
SendMessage(h, BM_SETCHECK, temp_GUS, 0);
h = GetDlgItem(hdlg, IDC_CONFIGURE_GUS);
EnableWindow(h, (temp_GUS) ? TRUE : FALSE);
h=GetDlgItem(hdlg, IDC_CHECK_SSI);
SendMessage(h, BM_SETCHECK, temp_SSI2001, 0);
@@ -1270,6 +1311,31 @@ win_settings_sound_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam)
temp_deviceconfig |= deviceconfig_open(hdlg, (void *)midi_device_getdevice(temp_midi_device));
break;
case IDC_COMBO_MIDI_IN:
h = GetDlgItem(hdlg, IDC_COMBO_MIDI_IN);
temp_midi_input_device = settings_list_to_midi_in[SendMessage(h, CB_GETCURSEL, 0, 0)];
h = GetDlgItem(hdlg, IDC_CONFIGURE_MIDI_IN);
if (midi_in_device_has_config(temp_midi_input_device))
EnableWindow(h, TRUE);
else
EnableWindow(h, FALSE);
h = GetDlgItem(hdlg, IDC_CHECK_MPU401);
SendMessage(h, BM_SETCHECK, temp_mpu401, 0);
EnableWindow(h, mpu401_standalone_allow() ? TRUE : FALSE);
h = GetDlgItem(hdlg, IDC_CONFIGURE_MPU401);
EnableWindow(h, (mpu401_standalone_allow() && temp_mpu401) ? TRUE : FALSE);
break;
case IDC_CONFIGURE_MIDI_IN:
h = GetDlgItem(hdlg, IDC_COMBO_MIDI_IN);
temp_midi_input_device = settings_list_to_midi_in[SendMessage(h, CB_GETCURSEL, 0, 0)];
temp_deviceconfig |= deviceconfig_open(hdlg, (void *)midi_in_device_getdevice(temp_midi_input_device));
break;
case IDC_CHECK_MPU401:
h = GetDlgItem(hdlg, IDC_CHECK_MPU401);
temp_mpu401 = SendMessage(h, BM_GETCHECK, 0, 0);
@@ -1282,6 +1348,18 @@ win_settings_sound_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam)
temp_deviceconfig |= deviceconfig_open(hdlg, (machines[temp_machine].flags & MACHINE_MCA) ?
(void *)&mpu401_mca_device : (void *)&mpu401_device);
break;
case IDC_CHECK_GUS:
h = GetDlgItem(hdlg, IDC_CHECK_GUS);
temp_GUS = SendMessage(h, BM_GETCHECK, 0, 0);
h = GetDlgItem(hdlg, IDC_CONFIGURE_GUS);
EnableWindow(h, temp_GUS ? TRUE : FALSE);
break;
case IDC_CONFIGURE_GUS:
temp_deviceconfig |= deviceconfig_open(hdlg, (void *)&gus_device);
break;
}
return FALSE;
@@ -1292,6 +1370,9 @@ win_settings_sound_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam)
h = GetDlgItem(hdlg, IDC_COMBO_MIDI);
temp_midi_device = settings_list_to_midi[SendMessage(h, CB_GETCURSEL, 0, 0)];
h = GetDlgItem(hdlg, IDC_COMBO_MIDI_IN);
temp_midi_input_device = settings_list_to_midi_in[SendMessage(h, CB_GETCURSEL, 0, 0)];
h = GetDlgItem(hdlg, IDC_CHECK_MPU401);
temp_mpu401 = SendMessage(h, BM_GETCHECK, 0, 0);