Fixed the MCA MPU-401 and gave it its correct name;
Sound Blaster 16/AWE32 MPU-401 is now always the less-functional variant like it would be on real hardware and its IRQ is always shared with the sound card; Standalone MPU-401 is now always the fully functional intelligent mode variant; Standalone MPU-401 is now always available, even when Sound Blaster 16/AWE32 is in use; Cleaned up sound/midi.c and win/win_midi.c.
This commit is contained in:
@@ -1,8 +1,9 @@
|
|||||||
extern void plat_midi_init(void);
|
extern void plat_midi_init(void);
|
||||||
extern void plat_midi_close(void);
|
extern void plat_midi_close(void);
|
||||||
|
|
||||||
extern void plat_midi_play_msg(uint8_t* val);
|
extern void plat_midi_play_msg(uint8_t *msg);
|
||||||
extern void plat_midi_play_sysex(uint8_t* data, unsigned int len);
|
extern void plat_midi_play_sysex(uint8_t *sysex, unsigned int len);
|
||||||
extern int plat_midi_write(uint8_t val);
|
extern int plat_midi_write(uint8_t val);
|
||||||
extern int plat_midi_get_num_devs();
|
|
||||||
|
extern int plat_midi_get_num_devs(void);
|
||||||
extern void plat_midi_get_dev_name(int num, char *s);
|
extern void plat_midi_get_dev_name(int num, char *s);
|
||||||
|
394
src/sound/midi.c
394
src/sound/midi.c
@@ -1,3 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||||
|
* running old operating systems and software designed for IBM
|
||||||
|
* PC systems and compatibles from 1981 through fairly recent
|
||||||
|
* system designs based on the PCI bus.
|
||||||
|
*
|
||||||
|
* This file is part of the 86Box distribution.
|
||||||
|
*
|
||||||
|
* MIDI device core module.
|
||||||
|
*
|
||||||
|
* Version: @(#)midi.c 1.0.0 2018/09/06
|
||||||
|
*
|
||||||
|
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||||
|
* Miran Grca, <mgrca8@gmail.com>
|
||||||
|
* Bit,
|
||||||
|
* DOSBox Team,
|
||||||
|
*
|
||||||
|
* Copyright 2008-2018 Sarah Walker.
|
||||||
|
* Copyright 2016-2018 Miran Grca.
|
||||||
|
* Copyright 2016-2018 Bit.
|
||||||
|
* Copyright 2008-2018 DOSBox Team.
|
||||||
|
*/
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -17,244 +39,248 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#define SYSEX_SIZE 1024
|
||||||
|
#define RAWBUF 1024
|
||||||
|
|
||||||
int midi_device_current = 0;
|
int midi_device_current = 0;
|
||||||
static int midi_device_last = 0;
|
static int midi_device_last = 0;
|
||||||
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
const char *name;
|
uint8_t midi_rt_buf[1024], midi_cmd_buf[1024],
|
||||||
const char *internal_name;
|
midi_status, midi_sysex_data[1026];
|
||||||
const device_t *device;
|
int midi_cmd_pos, midi_cmd_len;
|
||||||
|
unsigned int midi_sysex_start, midi_sysex_delay,
|
||||||
|
midi_pos;
|
||||||
|
midi_device_t* m_device;
|
||||||
|
} midi_t;
|
||||||
|
|
||||||
|
static midi_t *midi = NULL;
|
||||||
|
|
||||||
|
static 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 */
|
||||||
|
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 0x30 */
|
||||||
|
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 0x40 */
|
||||||
|
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 0x50 */
|
||||||
|
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 0x60 */
|
||||||
|
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 0x70 */
|
||||||
|
|
||||||
|
3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3, /* 0x80 */
|
||||||
|
3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3, /* 0x90 */
|
||||||
|
3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3, /* 0xa0 */
|
||||||
|
3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3, /* 0xb0 */
|
||||||
|
|
||||||
|
2,2,2,2, 2,2,2,2, 2,2,2,2, 2,2,2,2, /* 0xc0 */
|
||||||
|
2,2,2,2, 2,2,2,2, 2,2,2,2, 2,2,2,2, /* 0xd0 */
|
||||||
|
|
||||||
|
3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3, /* 0xe0 */
|
||||||
|
|
||||||
|
0,2,3,2, 0,0,1,0, 1,0,1,1, 1,0,1,0 /* 0xf0 */
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
const char *name, *internal_name;
|
||||||
|
const device_t *device;
|
||||||
} MIDI_DEVICE;
|
} MIDI_DEVICE;
|
||||||
|
|
||||||
static const MIDI_DEVICE devices[] =
|
static const MIDI_DEVICE devices[] =
|
||||||
{
|
{
|
||||||
{"None", "none", NULL},
|
{"None", "none", NULL},
|
||||||
#ifdef USE_FLUIDSYNTH
|
#ifdef USE_FLUIDSYNTH
|
||||||
{"FluidSynth", "fluidsynth", &fluidsynth_device},
|
{"FluidSynth", "fluidsynth", &fluidsynth_device},
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_MUNT
|
#ifdef USE_MUNT
|
||||||
{"Roland MT-32 Emulation", "mt32", &mt32_device},
|
{"Roland MT-32 Emulation", "mt32", &mt32_device},
|
||||||
{"Roland CM-32L Emulation", "cm32l", &cm32l_device},
|
{"Roland CM-32L Emulation", "cm32l", &cm32l_device},
|
||||||
#endif
|
#endif
|
||||||
{SYSTEM_MIDI_NAME, SYSTEM_MIDI_INTERNAL_NAME, &system_midi_device},
|
{SYSTEM_MIDI_NAME, SYSTEM_MIDI_INTERNAL_NAME, &system_midi_device},
|
||||||
{"", "", NULL}
|
{"", "", NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
static midi_device_t* m_device = NULL;
|
|
||||||
|
|
||||||
int midi_device_available(int card)
|
int
|
||||||
|
midi_device_available(int card)
|
||||||
{
|
{
|
||||||
if (devices[card].device)
|
if (devices[card].device)
|
||||||
return device_available(devices[card].device);
|
return device_available(devices[card].device);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *midi_device_getname(int card)
|
|
||||||
|
char *
|
||||||
|
midi_device_getname(int card)
|
||||||
{
|
{
|
||||||
return (char *) devices[card].name;
|
return (char *) devices[card].name;
|
||||||
}
|
}
|
||||||
|
|
||||||
const device_t *midi_device_getdevice(int card)
|
|
||||||
|
const device_t *
|
||||||
|
midi_device_getdevice(int card)
|
||||||
{
|
{
|
||||||
return devices[card].device;
|
return devices[card].device;
|
||||||
}
|
}
|
||||||
|
|
||||||
int midi_device_has_config(int card)
|
|
||||||
{
|
|
||||||
if (!devices[card].device)
|
|
||||||
return 0;
|
|
||||||
return devices[card].device->config ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *midi_device_get_internal_name(int card)
|
int
|
||||||
|
midi_device_has_config(int card)
|
||||||
{
|
{
|
||||||
return (char *) devices[card].internal_name;
|
if (!devices[card].device)
|
||||||
}
|
|
||||||
|
|
||||||
int midi_device_get_from_internal_name(char *s)
|
|
||||||
{
|
|
||||||
int c = 0;
|
|
||||||
|
|
||||||
while (strlen(devices[c].internal_name))
|
|
||||||
{
|
|
||||||
if (!strcmp(devices[c].internal_name, s))
|
|
||||||
return c;
|
|
||||||
c++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
return devices[card].device->config ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void midi_device_init()
|
|
||||||
|
char *
|
||||||
|
midi_device_get_internal_name(int card)
|
||||||
{
|
{
|
||||||
if (devices[midi_device_current].device)
|
return (char *) devices[card].internal_name;
|
||||||
device_add(devices[midi_device_current].device);
|
|
||||||
midi_device_last = midi_device_current;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t midi_rt_buf[1024];
|
|
||||||
static uint8_t midi_cmd_buf[1024];
|
|
||||||
static int midi_cmd_pos = 0;
|
|
||||||
static int midi_cmd_len = 0;
|
|
||||||
static uint8_t midi_status = 0;
|
|
||||||
static unsigned int midi_sysex_start = 0;
|
|
||||||
static unsigned int midi_sysex_delay = 0;
|
|
||||||
|
|
||||||
uint8_t MIDI_evt_len[256] = {
|
int
|
||||||
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x00
|
midi_device_get_from_internal_name(char *s)
|
||||||
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
|
|
||||||
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x30
|
|
||||||
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x40
|
|
||||||
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x50
|
|
||||||
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x60
|
|
||||||
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, // 0x70
|
|
||||||
|
|
||||||
3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3, // 0x80
|
|
||||||
3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3, // 0x90
|
|
||||||
3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3, // 0xa0
|
|
||||||
3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3, // 0xb0
|
|
||||||
|
|
||||||
2,2,2,2, 2,2,2,2, 2,2,2,2, 2,2,2,2, // 0xc0
|
|
||||||
2,2,2,2, 2,2,2,2, 2,2,2,2, 2,2,2,2, // 0xd0
|
|
||||||
|
|
||||||
3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3, // 0xe0
|
|
||||||
|
|
||||||
0,2,3,2, 0,0,1,0, 1,0,1,1, 1,0,1,0 // 0xf0
|
|
||||||
};
|
|
||||||
|
|
||||||
static unsigned int midi_pos;
|
|
||||||
static uint8_t midi_sysex_data[1024+2];
|
|
||||||
|
|
||||||
void midi_init(midi_device_t* device)
|
|
||||||
{
|
{
|
||||||
memset(midi_rt_buf, 0, sizeof(midi_rt_buf));
|
int c = 0;
|
||||||
memset(midi_cmd_buf, 0, sizeof(midi_cmd_buf));
|
|
||||||
|
|
||||||
midi_cmd_pos = midi_cmd_len = 0;
|
while (strlen(devices[c].internal_name)) {
|
||||||
midi_status = 0;
|
if (!strcmp(devices[c].internal_name, s))
|
||||||
|
return c;
|
||||||
midi_sysex_start = midi_sysex_delay = 0;
|
c++;
|
||||||
|
}
|
||||||
m_device = device;
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void midi_close()
|
|
||||||
|
void
|
||||||
|
midi_device_init()
|
||||||
{
|
{
|
||||||
m_device = NULL;
|
if (devices[midi_device_current].device)
|
||||||
|
device_add(devices[midi_device_current].device);
|
||||||
|
midi_device_last = midi_device_current;
|
||||||
}
|
}
|
||||||
|
|
||||||
void midi_poll()
|
|
||||||
|
void
|
||||||
|
midi_init(midi_device_t* device)
|
||||||
{
|
{
|
||||||
if (m_device && m_device->poll) m_device->poll();
|
midi = (midi_t *) malloc(sizeof(midi_t));
|
||||||
|
memset(midi, 0, sizeof(midi_t));
|
||||||
|
|
||||||
|
midi->m_device = device;
|
||||||
}
|
}
|
||||||
|
|
||||||
void play_msg(uint8_t *msg)
|
|
||||||
|
void
|
||||||
|
midi_close(void)
|
||||||
{
|
{
|
||||||
if (m_device->play_msg) m_device->play_msg(msg);
|
if (midi) {
|
||||||
|
free(midi);
|
||||||
|
midi = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void play_sysex(uint8_t *sysex, unsigned int len)
|
void
|
||||||
|
midi_poll(void)
|
||||||
{
|
{
|
||||||
if (m_device->play_sysex) m_device->play_sysex(sysex, len);
|
if (midi && midi->m_device && midi->m_device->poll)
|
||||||
|
midi->m_device->poll();
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SYSEX_SIZE 1024
|
|
||||||
#define RAWBUF 1024
|
|
||||||
|
|
||||||
void midi_write(uint8_t val)
|
void
|
||||||
|
play_msg(uint8_t *msg)
|
||||||
{
|
{
|
||||||
if (!m_device) return;
|
if (midi->m_device->play_msg)
|
||||||
|
midi->m_device->play_msg(msg);
|
||||||
if (m_device->write && m_device->write(val)) return;
|
}
|
||||||
|
|
||||||
uint32_t passed_ticks;
|
|
||||||
|
void
|
||||||
if (midi_sysex_start)
|
play_sysex(uint8_t *sysex, unsigned int len)
|
||||||
{
|
{
|
||||||
passed_ticks = plat_get_ticks() - midi_sysex_start;
|
if (midi->m_device->play_sysex)
|
||||||
if (passed_ticks < midi_sysex_delay)
|
midi->m_device->play_sysex(sysex, len);
|
||||||
{
|
}
|
||||||
plat_delay_ms(midi_sysex_delay - passed_ticks);
|
|
||||||
}
|
|
||||||
}
|
void
|
||||||
|
midi_write(uint8_t val)
|
||||||
/* Test for a realtime MIDI message */
|
{
|
||||||
if (val >= 0xf8)
|
uint32_t passed_ticks;
|
||||||
{
|
|
||||||
midi_rt_buf[0] = val;
|
if (!midi || !midi->m_device)
|
||||||
play_msg(midi_rt_buf);
|
return;
|
||||||
return;
|
|
||||||
}
|
if (midi->m_device->write && midi->m_device->write(val))
|
||||||
|
return;
|
||||||
/* Test for a active sysex transfer */
|
|
||||||
|
if (midi->midi_sysex_start) {
|
||||||
if (midi_status == 0xf0)
|
passed_ticks = plat_get_ticks() - midi->midi_sysex_start;
|
||||||
{
|
if (passed_ticks < midi->midi_sysex_delay)
|
||||||
if (!(val & 0x80))
|
plat_delay_ms(midi->midi_sysex_delay - passed_ticks);
|
||||||
{
|
}
|
||||||
if (midi_pos < (SYSEX_SIZE-1)) midi_sysex_data[midi_pos++] = val;
|
|
||||||
return;
|
/* Test for a realtime MIDI message */
|
||||||
}
|
if (val >= 0xf8) {
|
||||||
else
|
midi->midi_rt_buf[0] = val;
|
||||||
{
|
play_msg(midi->midi_rt_buf);
|
||||||
midi_sysex_data[midi_pos++] = 0xf7;
|
return;
|
||||||
|
}
|
||||||
if ((midi_sysex_start) && (midi_pos >= 4) && (midi_pos <= 9) && (midi_sysex_data[1] == 0x41) && (midi_sysex_data[3] == 0x16))
|
|
||||||
{
|
/* Test for a active sysex transfer */
|
||||||
/* pclog("MIDI: Skipping invalid MT-32 SysEx MIDI message\n"); */
|
if (midi->midi_status == 0xf0) {
|
||||||
}
|
if (!(val & 0x80)) {
|
||||||
else
|
if (midi->midi_pos < (SYSEX_SIZE-1))
|
||||||
{
|
midi->midi_sysex_data[midi->midi_pos++] = val;
|
||||||
play_sysex(midi_sysex_data, midi_pos);
|
return;
|
||||||
if (midi_sysex_start)
|
} else {
|
||||||
{
|
midi->midi_sysex_data[midi->midi_pos++] = 0xf7;
|
||||||
if (midi_sysex_data[5] == 0x7f)
|
|
||||||
{
|
if ((midi->midi_sysex_start) && (midi->midi_pos >= 4) && (midi->midi_pos <= 9) &&
|
||||||
midi_sysex_delay = 290; /* All parameters reset */
|
(midi->midi_sysex_data[1] == 0x41) && (midi->midi_sysex_data[3] == 0x16)) {
|
||||||
}
|
/* pclog("MIDI: Skipping invalid MT-32 SysEx MIDI message\n"); */
|
||||||
else if ((midi_sysex_data[5] == 0x10) && (midi_sysex_data[6] == 0x00) && (midi_sysex_data[7] == 0x04))
|
} else {
|
||||||
{
|
play_sysex(midi->midi_sysex_data, midi->midi_pos);
|
||||||
midi_sysex_delay = 145; /* Viking Child */
|
if (midi->midi_sysex_start) {
|
||||||
}
|
if (midi-> midi_sysex_data[5] == 0x7f)
|
||||||
else if ((midi_sysex_data[5] == 0x10) && (midi_sysex_data[6] == 0x00) && (midi_sysex_data[7] == 0x01))
|
midi->midi_sysex_delay = 290; /* All parameters reset */
|
||||||
{
|
else if ((midi->midi_sysex_data[5] == 0x10) && (midi->midi_sysex_data[6] == 0x00) &&
|
||||||
midi_sysex_delay = 30; /* Dark Sun 1 */
|
(midi->midi_sysex_data[7] == 0x04))
|
||||||
}
|
midi->midi_sysex_delay = 145; /* Viking Child */
|
||||||
else
|
else if ((midi->midi_sysex_data[5] == 0x10) && (midi->midi_sysex_data[6] == 0x00) &&
|
||||||
midi_sysex_delay = (unsigned int) (((float) (midi_pos) * 1.25f) * 1000.0f / 3125.0f) + 2;
|
(midi->midi_sysex_data[7] == 0x01))
|
||||||
|
midi->midi_sysex_delay = 30; /* Dark Sun 1 */
|
||||||
midi_sysex_start = plat_get_ticks();
|
else
|
||||||
}
|
midi->midi_sysex_delay = (unsigned int) (((float) (midi->midi_pos) * 1.25f) * 1000.0f / 3125.0f) + 2;
|
||||||
}
|
|
||||||
}
|
midi->midi_sysex_start = plat_get_ticks();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (val & 0x80)
|
}
|
||||||
{
|
|
||||||
midi_status = val;
|
if (val & 0x80) {
|
||||||
midi_cmd_pos = 0;
|
midi->midi_status = val;
|
||||||
midi_cmd_len = MIDI_evt_len[val];
|
midi->midi_cmd_pos = 0;
|
||||||
if (midi_status == 0xf0)
|
midi->midi_cmd_len = MIDI_evt_len[val];
|
||||||
{
|
if (midi->midi_status == 0xf0) {
|
||||||
midi_sysex_data[0] = 0xf0;
|
midi->midi_sysex_data[0] = 0xf0;
|
||||||
midi_pos = 1;
|
midi->midi_pos = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (midi_cmd_len)
|
if (midi->midi_cmd_len) {
|
||||||
{
|
midi->midi_cmd_buf[midi->midi_cmd_pos++] = val;
|
||||||
midi_cmd_buf[midi_cmd_pos++] = val;
|
if (midi->midi_cmd_pos >= midi->midi_cmd_len) {
|
||||||
if (midi_cmd_pos >= midi_cmd_len)
|
play_msg(midi->midi_cmd_buf);
|
||||||
{
|
midi->midi_cmd_pos = 1;
|
||||||
play_msg(midi_cmd_buf);
|
}
|
||||||
midi_cmd_pos = 1;
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
* Roland MPU-401 emulation.
|
* Roland MPU-401 emulation.
|
||||||
*
|
*
|
||||||
* Version: @(#)snd_mpu401.c 1.0.12 2018/09/04
|
* Version: @(#)snd_mpu401.c 1.0.14 2018/09/11
|
||||||
*
|
*
|
||||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||||
* DOSBox Team,
|
* DOSBox Team,
|
||||||
@@ -80,13 +80,12 @@ static void
|
|||||||
QueueByte(mpu_t *mpu, uint8_t data)
|
QueueByte(mpu_t *mpu, uint8_t data)
|
||||||
{
|
{
|
||||||
if (mpu->state.block_ack) {
|
if (mpu->state.block_ack) {
|
||||||
mpu->state.block_ack=0;
|
mpu->state.block_ack = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((mpu->queue_used == 0) && (mpu->mode == M_INTELLIGENT)) {
|
if ((mpu->queue_used == 0) && (mpu->mode == M_INTELLIGENT)) {
|
||||||
// if (mpu->queue_used == 0 && mpu->intelligent) {
|
mpu->state.irq_pending = 1;
|
||||||
mpu->state.irq_pending=1;
|
|
||||||
picint(1 << mpu->irq);
|
picint(1 << mpu->irq);
|
||||||
}
|
}
|
||||||
if (mpu->queue_used < MPU401_QUEUE) {
|
if (mpu->queue_used < MPU401_QUEUE) {
|
||||||
@@ -99,7 +98,7 @@ QueueByte(mpu_t *mpu, uint8_t data)
|
|||||||
pos-=MPU401_QUEUE;
|
pos-=MPU401_QUEUE;
|
||||||
|
|
||||||
mpu->queue_used++;
|
mpu->queue_used++;
|
||||||
mpu->queue[pos]=data;
|
mpu->queue[pos] = data;
|
||||||
} else
|
} else
|
||||||
mpu401_log("MPU401:Data queue full\n");
|
mpu401_log("MPU401:Data queue full\n");
|
||||||
}
|
}
|
||||||
@@ -120,7 +119,7 @@ MPU401_Reset(mpu_t *mpu)
|
|||||||
|
|
||||||
picintc(1 << mpu->irq);
|
picintc(1 << mpu->irq);
|
||||||
|
|
||||||
mpu->mode = (mpu->intelligent ? M_INTELLIGENT : M_UART);
|
mpu->mode = M_INTELLIGENT;
|
||||||
mpu->state.eoi_scheduled = 0;
|
mpu->state.eoi_scheduled = 0;
|
||||||
mpu->state.wsd = 0;
|
mpu->state.wsd = 0;
|
||||||
mpu->state.wsm = 0;
|
mpu->state.wsm = 0;
|
||||||
@@ -166,10 +165,10 @@ MPU401_ResetDone(void *priv)
|
|||||||
|
|
||||||
mpu401_reset_callback = 0LL;
|
mpu401_reset_callback = 0LL;
|
||||||
|
|
||||||
mpu->state.reset=0;
|
mpu->state.reset = 0;
|
||||||
if (mpu->state.cmd_pending) {
|
if (mpu->state.cmd_pending) {
|
||||||
MPU401_WriteCommand(mpu, mpu->state.cmd_pending-1);
|
MPU401_WriteCommand(mpu, mpu->state.cmd_pending - 1);
|
||||||
mpu->state.cmd_pending=0;
|
mpu->state.cmd_pending = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,11 +176,13 @@ MPU401_ResetDone(void *priv)
|
|||||||
static void
|
static void
|
||||||
MPU401_WriteCommand(mpu_t *mpu, uint8_t val)
|
MPU401_WriteCommand(mpu_t *mpu, uint8_t val)
|
||||||
{
|
{
|
||||||
uint8_t i;
|
uint8_t i, was_uart;
|
||||||
|
|
||||||
if (mpu->state.reset) {
|
if (mpu->state.reset)
|
||||||
mpu->state.cmd_pending=val+1;
|
mpu->state.cmd_pending = val + 1;
|
||||||
}
|
|
||||||
|
if ((val != 0x3f) && (val != 0xff) && !mpu->intelligent)
|
||||||
|
return;
|
||||||
|
|
||||||
if (val <= 0x2f) {
|
if (val <= 0x2f) {
|
||||||
switch (val&3) { /* MIDI stop, start, continue */
|
switch (val&3) { /* MIDI stop, start, continue */
|
||||||
@@ -203,7 +204,7 @@ MPU401_WriteCommand(mpu_t *mpu, uint8_t val)
|
|||||||
mpu->state.playing = 0;
|
mpu->state.playing = 0;
|
||||||
mpu401_event_callback = 0LL;
|
mpu401_event_callback = 0LL;
|
||||||
|
|
||||||
for (i=0xb0; i<0xbf; i++) {
|
for (i = 0xb0; i < 0xbf; i++) {
|
||||||
/* All notes off */
|
/* All notes off */
|
||||||
midi_write(i);
|
midi_write(i);
|
||||||
midi_write(0x7b);
|
midi_write(0x7b);
|
||||||
@@ -217,9 +218,10 @@ MPU401_WriteCommand(mpu_t *mpu, uint8_t val)
|
|||||||
ClrQueue(mpu);
|
ClrQueue(mpu);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (val>=0xa0 && val<=0xa7) { /* Request play counter */
|
} else if ((val >= 0xa0) && (val <= 0xa7)) { /* Request play counter */
|
||||||
if (mpu->state.cmask&(1<<(val&7))) QueueByte(mpu, mpu->playbuf[val&7].counter);
|
if (mpu->state.cmask & (1 << (val&7)))
|
||||||
} else if (val>=0xd0 && val<=0xd7) { /* Send data */
|
QueueByte(mpu, mpu->playbuf[val&7].counter);
|
||||||
|
} else if ((val >= 0xd0) && (val <= 0xd7)) { /* Send data */
|
||||||
mpu->state.old_chan = mpu->state.channel;
|
mpu->state.old_chan = mpu->state.channel;
|
||||||
mpu->state.channel= val & 7;
|
mpu->state.channel= val & 7;
|
||||||
mpu->state.wsd = 1;
|
mpu->state.wsd = 1;
|
||||||
@@ -241,44 +243,44 @@ MPU401_WriteCommand(mpu_t *mpu, uint8_t val)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x94: /* Clock to host */
|
case 0x94: /* Clock to host */
|
||||||
mpu->clock.clock_to_host=0;
|
mpu->clock.clock_to_host = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x95:
|
case 0x95:
|
||||||
mpu->clock.clock_to_host=1;
|
mpu->clock.clock_to_host = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xc2: /* Internal timebase */
|
case 0xc2: /* Internal timebase */
|
||||||
mpu->clock.timebase=48;
|
mpu->clock.timebase = 48;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xc3:
|
case 0xc3:
|
||||||
mpu->clock.timebase=72;
|
mpu->clock.timebase = 72;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xc4:
|
case 0xc4:
|
||||||
mpu->clock.timebase=96;
|
mpu->clock.timebase = 96;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xc5:
|
case 0xc5:
|
||||||
mpu->clock.timebase=120;
|
mpu->clock.timebase = 120;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xc6:
|
case 0xc6:
|
||||||
mpu->clock.timebase=144;
|
mpu->clock.timebase = 144;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xc7:
|
case 0xc7:
|
||||||
mpu->clock.timebase=168;
|
mpu->clock.timebase = 168;
|
||||||
break;
|
break;
|
||||||
case 0xc8:
|
case 0xc8:
|
||||||
mpu->clock.timebase=192;
|
mpu->clock.timebase = 192;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Commands with data byte */
|
/* Commands with data byte */
|
||||||
case 0xe0: case 0xe1: case 0xe2: case 0xe4: case 0xe6:
|
case 0xe0: case 0xe1: case 0xe2: case 0xe4: case 0xe6:
|
||||||
case 0xe7: case 0xec: case 0xed: case 0xee: case 0xef:
|
case 0xe7: case 0xec: case 0xed: case 0xee: case 0xef:
|
||||||
mpu->state.command_byte=val;
|
mpu->state.command_byte = val;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Commands 0xa# returning data */
|
/* Commands 0xa# returning data */
|
||||||
@@ -303,49 +305,49 @@ MPU401_WriteCommand(mpu_t *mpu, uint8_t val)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
case 0xb1: /* Reset relative tempo */
|
case 0xb1: /* Reset relative tempo */
|
||||||
mpu->clock.old_tempo_rel=mpu->clock.tempo_rel;
|
mpu->clock.old_tempo_rel = mpu->clock.tempo_rel;
|
||||||
mpu->clock.tempo_rel=40;
|
mpu->clock.tempo_rel = 40;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xb9: /* Clear play map */
|
case 0xb9: /* Clear play map */
|
||||||
case 0xb8: /* Clear play counters */
|
case 0xb8: /* Clear play counters */
|
||||||
for (i=0xb0;i<0xbf;i++) {
|
for (i = 0xb0; i < 0xbf; i++) {
|
||||||
/* All notes off */
|
/* All notes off */
|
||||||
midi_write(i);
|
midi_write(i);
|
||||||
midi_write(0x7b);
|
midi_write(0x7b);
|
||||||
midi_write(0);
|
midi_write(0);
|
||||||
}
|
}
|
||||||
for (i=0;i<8;i++) {
|
for (i = 0; i < 8; i++) {
|
||||||
mpu->playbuf[i].counter=0;
|
mpu->playbuf[i].counter = 0;
|
||||||
mpu->playbuf[i].type=T_OVERFLOW;
|
mpu->playbuf[i].type = T_OVERFLOW;
|
||||||
}
|
}
|
||||||
mpu->condbuf.counter=0;
|
mpu->condbuf.counter = 0;
|
||||||
mpu->condbuf.type=T_OVERFLOW;
|
mpu->condbuf.type = T_OVERFLOW;
|
||||||
if (!(mpu->state.conductor=mpu->state.cond_set))
|
if (!(mpu->state.conductor=mpu->state.cond_set))
|
||||||
mpu->state.cond_req=0;
|
mpu->state.cond_req = 0;
|
||||||
mpu->state.amask=mpu->state.tmask;
|
mpu->state.amask = mpu->state.tmask;
|
||||||
mpu->state.req_mask=0;
|
mpu->state.req_mask = 0;
|
||||||
mpu->state.irq_pending=1;
|
mpu->state.irq_pending = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xff: /* Reset MPU-401 */
|
case 0xff: /* Reset MPU-401 */
|
||||||
mpu401_log("MPU-401:Reset %X\n",val);
|
mpu401_log("MPU-401:Reset %X\n",val);
|
||||||
mpu401_reset_callback = MPU401_RESETBUSY * 33LL * TIMER_USEC;
|
mpu401_reset_callback = MPU401_RESETBUSY * 33LL * TIMER_USEC;
|
||||||
mpu->state.reset=1;
|
mpu->state.reset = 1;
|
||||||
|
was_uart = (mpu->mode == M_UART);
|
||||||
MPU401_Reset(mpu);
|
MPU401_Reset(mpu);
|
||||||
#if 0
|
if (was_uart)
|
||||||
if (mpu->mode==M_UART) return;//do not send ack in UART mode
|
return; /* do not send ack in UART mode */
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x3f: /* UART mode */
|
case 0x3f: /* UART mode */
|
||||||
mpu401_log("MPU-401:Set UART mode %X\n",val);
|
mpu401_log("MPU-401:Set UART mode %X\n",val);
|
||||||
QueueByte(mpu, MSG_MPU_ACK);
|
QueueByte(mpu, MSG_MPU_ACK);
|
||||||
mpu->mode=M_UART;
|
mpu->mode = M_UART;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
default:;
|
/* default:
|
||||||
//mpu401_log("MPU-401:Unhandled command %X",val);
|
mpu401_log("MPU-401:Unhandled command %X",val); */
|
||||||
}
|
}
|
||||||
|
|
||||||
QueueByte(mpu, MSG_MPU_ACK);
|
QueueByte(mpu, MSG_MPU_ACK);
|
||||||
@@ -355,80 +357,85 @@ MPU401_WriteCommand(mpu_t *mpu, uint8_t val)
|
|||||||
static void
|
static void
|
||||||
MPU401_WriteData(mpu_t *mpu, uint8_t val)
|
MPU401_WriteData(mpu_t *mpu, uint8_t val)
|
||||||
{
|
{
|
||||||
if (mpu->mode==M_UART) {midi_write(val); return;}
|
static int length, cnt, posd;
|
||||||
|
|
||||||
|
if (mpu->mode == M_UART) {
|
||||||
|
midi_write(val);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mpu->intelligent) {
|
||||||
|
mpu->state.command_byte = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (mpu->state.command_byte) { /* 0xe# command data */
|
switch (mpu->state.command_byte) { /* 0xe# command data */
|
||||||
case 0x00:
|
case 0x00:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xe0: /* Set tempo */
|
case 0xe0: /* Set tempo */
|
||||||
mpu->state.command_byte=0;
|
mpu->state.command_byte = 0;
|
||||||
mpu->clock.tempo=val;
|
mpu->clock.tempo = val;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0xe1: /* Set relative tempo */
|
case 0xe1: /* Set relative tempo */
|
||||||
mpu->state.command_byte=0;
|
mpu->state.command_byte = 0;
|
||||||
mpu->clock.old_tempo_rel=mpu->clock.tempo_rel;
|
mpu->clock.old_tempo_rel = mpu->clock.tempo_rel;
|
||||||
mpu->clock.tempo_rel=val;
|
mpu->clock.tempo_rel = val;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0xe7: /* Set internal clock to host interval */
|
case 0xe7: /* Set internal clock to host interval */
|
||||||
mpu->state.command_byte=0;
|
mpu->state.command_byte = 0;
|
||||||
mpu->clock.cth_rate=val>>2;
|
mpu->clock.cth_rate = val >> 2;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0xec: /* Set active track mask */
|
case 0xec: /* Set active track mask */
|
||||||
mpu->state.command_byte=0;
|
mpu->state.command_byte = 0;
|
||||||
mpu->state.tmask=val;
|
mpu->state.tmask = val;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0xed: /* Set play counter mask */
|
case 0xed: /* Set play counter mask */
|
||||||
mpu->state.command_byte=0;
|
mpu->state.command_byte = 0;
|
||||||
mpu->state.cmask=val;
|
mpu->state.cmask = val;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0xee: /* Set 1-8 MIDI channel mask */
|
case 0xee: /* Set 1-8 MIDI channel mask */
|
||||||
mpu->state.command_byte=0;
|
mpu->state.command_byte = 0;
|
||||||
mpu->state.midi_mask&=0xff00;
|
mpu->state.midi_mask &= 0xff00;
|
||||||
mpu->state.midi_mask|=val;
|
mpu->state.midi_mask |= val;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0xef: /* Set 9-16 MIDI channel mask */
|
case 0xef: /* Set 9-16 MIDI channel mask */
|
||||||
mpu->state.command_byte=0;
|
mpu->state.command_byte = 0;
|
||||||
mpu->state.midi_mask&=0x00ff;
|
mpu->state.midi_mask &= 0x00ff;
|
||||||
mpu->state.midi_mask|=((uint16_t)val)<<8;
|
mpu->state.midi_mask |= ((uint16_t) val) << 8;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
//case 0xe2: /* Set graduation for relative tempo */
|
|
||||||
//case 0xe4: /* Set metronome */
|
|
||||||
//case 0xe6: /* Set metronome measure length */
|
|
||||||
default:
|
default:
|
||||||
mpu->state.command_byte=0;
|
mpu->state.command_byte = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int length,cnt,posd;
|
|
||||||
|
|
||||||
if (mpu->state.wsd) {
|
if (mpu->state.wsd) {
|
||||||
/* Directly send MIDI message */
|
/* Directly send MIDI message */
|
||||||
if (mpu->state.wsd_start) {
|
if (mpu->state.wsd_start) {
|
||||||
mpu->state.wsd_start=0;
|
mpu->state.wsd_start = 0;
|
||||||
cnt=0;
|
cnt = 0;
|
||||||
switch (val&0xf0) {
|
switch (val & 0xf0) {
|
||||||
case 0xc0:case 0xd0:
|
case 0xc0: case 0xd0:
|
||||||
mpu->playbuf[mpu->state.channel].value[0]=val;
|
mpu->playbuf[mpu->state.channel].value[0] = val;
|
||||||
length=2;
|
length = 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x80:case 0x90:case 0xa0:case 0xb0:case 0xe0:
|
case 0x80: case 0x90: case 0xa0: case 0xb0:case 0xe0:
|
||||||
mpu->playbuf[mpu->state.channel].value[0]=val;
|
mpu->playbuf[mpu->state.channel].value[0] = val;
|
||||||
length=3;
|
length = 3;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xf0:
|
case 0xf0:
|
||||||
//mpu401_log("MPU-401:Illegal WSD byte\n");
|
/* mpu401_log("MPU-401:Illegal WSD byte\n"); */
|
||||||
mpu->state.wsd=0;
|
mpu->state.wsd = 0;
|
||||||
mpu->state.channel=mpu->state.old_chan;
|
mpu->state.channel = mpu->state.old_chan;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
default: /* MIDI with running status */
|
default: /* MIDI with running status */
|
||||||
@@ -437,49 +444,57 @@ MPU401_WriteData(mpu_t *mpu, uint8_t val)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cnt<length) {midi_write(val);cnt++;}
|
if (cnt < length) {
|
||||||
|
midi_write(val);
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
|
||||||
if (cnt==length) {
|
if (cnt == length) {
|
||||||
mpu->state.wsd=0;
|
mpu->state.wsd = 0;
|
||||||
mpu->state.channel=mpu->state.old_chan;
|
mpu->state.channel = mpu->state.old_chan;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mpu->state.wsm) { /* Directly send system message */
|
if (mpu->state.wsm) { /* Directly send system message */
|
||||||
if (val==MSG_EOX) {midi_write(MSG_EOX);mpu->state.wsm=0;return;}
|
if (val == MSG_EOX) {
|
||||||
|
midi_write(MSG_EOX);
|
||||||
|
mpu->state.wsm = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (mpu->state.wsd_start) {
|
if (mpu->state.wsd_start) {
|
||||||
mpu->state.wsd_start=0;
|
mpu->state.wsd_start = 0;
|
||||||
cnt=0;
|
cnt = 0;
|
||||||
switch (val) {
|
switch (val) {
|
||||||
case 0xf2:
|
case 0xf2:
|
||||||
length=3;
|
length = 3;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xf3:
|
case 0xf3:
|
||||||
length=2;
|
length = 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xf6:
|
case 0xf6:
|
||||||
length=1;
|
length = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xf0:
|
case 0xf0:
|
||||||
length=0;
|
length = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
length=0;
|
length = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!length || cnt<length) {
|
if (!length || (cnt < length)) {
|
||||||
midi_write(val);
|
midi_write(val);
|
||||||
cnt++;
|
cnt++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cnt==length) mpu->state.wsm=0;
|
if (cnt == length)
|
||||||
|
mpu->state.wsm = 0;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -491,27 +506,29 @@ MPU401_WriteData(mpu_t *mpu, uint8_t val)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
case 0: /* Timing byte */
|
case 0: /* Timing byte */
|
||||||
mpu->condbuf.vlength=0;
|
mpu->condbuf.vlength = 0;
|
||||||
if (val<0xf0) mpu->state.data_onoff++;
|
if (val < 0xf0)
|
||||||
else {
|
mpu->state.data_onoff++;
|
||||||
mpu->state.data_onoff=-1;
|
else {
|
||||||
|
mpu->state.data_onoff = -1;
|
||||||
MPU401_EOIHandlerDispatch(mpu);
|
MPU401_EOIHandlerDispatch(mpu);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (val==0) mpu->state.send_now=1;
|
mpu->state.send_now = !val ? 1 : 0;
|
||||||
else mpu->state.send_now=0;
|
mpu->condbuf.counter = val;
|
||||||
mpu->condbuf.counter=val;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1: /* Command byte #1 */
|
case 1: /* Command byte #1 */
|
||||||
mpu->condbuf.type=T_COMMAND;
|
mpu->condbuf.type = T_COMMAND;
|
||||||
if (val==0xf8 || val==0xf9)
|
if ((val == 0xf8) || (val == 0xf9))
|
||||||
mpu->condbuf.type=T_OVERFLOW;
|
mpu->condbuf.type = T_OVERFLOW;
|
||||||
mpu->condbuf.value[mpu->condbuf.vlength]=val;
|
mpu->condbuf.value[mpu->condbuf.vlength] = val;
|
||||||
mpu->condbuf.vlength++;
|
mpu->condbuf.vlength++;
|
||||||
if ((val&0xf0)!=0xe0) MPU401_EOIHandlerDispatch(mpu);
|
if ((val & 0xf0) != 0xe0)
|
||||||
else mpu->state.data_onoff++;
|
MPU401_EOIHandlerDispatch(mpu);
|
||||||
|
else
|
||||||
|
mpu->state.data_onoff++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:/* Command byte #2 */
|
case 2:/* Command byte #2 */
|
||||||
@@ -529,55 +546,55 @@ MPU401_WriteData(mpu_t *mpu, uint8_t val)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
case 0: /* Timing byte */
|
case 0: /* Timing byte */
|
||||||
if (val<0xf0) mpu->state.data_onoff=1;
|
if (val < 0xf0)
|
||||||
else {
|
mpu->state.data_onoff = 1;
|
||||||
mpu->state.data_onoff=-1;
|
else {
|
||||||
|
mpu->state.data_onoff = -1;
|
||||||
MPU401_EOIHandlerDispatch(mpu);
|
MPU401_EOIHandlerDispatch(mpu);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (val==0) mpu->state.send_now=1;
|
mpu->state.send_now = !val ? 1 : 0;
|
||||||
else mpu->state.send_now=0;
|
mpu->playbuf[mpu->state.channel].counter = val;
|
||||||
mpu->playbuf[mpu->state.channel].counter=val;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1: /* MIDI */
|
case 1: /* MIDI */
|
||||||
mpu->playbuf[mpu->state.channel].vlength++;
|
mpu->playbuf[mpu->state.channel].vlength++;
|
||||||
posd=mpu->playbuf[mpu->state.channel].vlength;
|
posd=mpu->playbuf[mpu->state.channel].vlength;
|
||||||
if (posd==1) switch (val&0xf0) {
|
if (posd == 1) switch (val&0xf0) {
|
||||||
case 0xf0: /* System message or mark */
|
case 0xf0: /* System message or mark */
|
||||||
if (val>0xf7) {
|
if (val > 0xf7) {
|
||||||
mpu->playbuf[mpu->state.channel].type=T_MARK;
|
mpu->playbuf[mpu->state.channel].type = T_MARK;
|
||||||
mpu->playbuf[mpu->state.channel].sys_val=val;
|
mpu->playbuf[mpu->state.channel].sys_val = val;
|
||||||
length=1;
|
|
||||||
} else {
|
} else {
|
||||||
//LOG(LOG_MISC,LOG_ERROR)("MPU-401:Illegal message");
|
/* mpu401_log("MPU-401:Illegal message"); */
|
||||||
mpu->playbuf[mpu->state.channel].type=T_MIDI_SYS;
|
mpu->playbuf[mpu->state.channel].type = T_MIDI_SYS;
|
||||||
mpu->playbuf[mpu->state.channel].sys_val=val;
|
mpu->playbuf[mpu->state.channel].sys_val = val;
|
||||||
length=1;
|
|
||||||
}
|
}
|
||||||
|
length = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xc0: case 0xd0: /* MIDI Message */
|
case 0xc0: case 0xd0: /* MIDI Message */
|
||||||
mpu->playbuf[mpu->state.channel].type=T_MIDI_NORM;
|
mpu->playbuf[mpu->state.channel].type = T_MIDI_NORM;
|
||||||
length=mpu->playbuf[mpu->state.channel].length=2;
|
length = mpu->playbuf[mpu->state.channel].length = 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x80: case 0x90: case 0xa0: case 0xb0: case 0xe0:
|
case 0x80: case 0x90: case 0xa0: case 0xb0: case 0xe0:
|
||||||
mpu->playbuf[mpu->state.channel].type=T_MIDI_NORM;
|
mpu->playbuf[mpu->state.channel].type = T_MIDI_NORM;
|
||||||
length=mpu->playbuf[mpu->state.channel].length=3;
|
length = mpu->playbuf[mpu->state.channel].length = 3;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: /* MIDI data with running status */
|
default: /* MIDI data with running status */
|
||||||
posd++;
|
posd++;
|
||||||
mpu->playbuf[mpu->state.channel].vlength++;
|
mpu->playbuf[mpu->state.channel].vlength++;
|
||||||
mpu->playbuf[mpu->state.channel].type=T_MIDI_NORM;
|
mpu->playbuf[mpu->state.channel].type = T_MIDI_NORM;
|
||||||
length=mpu->playbuf[mpu->state.channel].length;
|
length = mpu->playbuf[mpu->state.channel].length;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(posd==1 && val>=0xf0))
|
if (!((posd == 1) && (val >= 0xf0)))
|
||||||
mpu->playbuf[mpu->state.channel].value[posd-1]=val;
|
mpu->playbuf[mpu->state.channel].value[posd-1] = val;
|
||||||
if (posd==length) MPU401_EOIHandlerDispatch(mpu);
|
if (posd == length)
|
||||||
|
MPU401_EOIHandlerDispatch(mpu);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -596,13 +613,13 @@ MPU401_IntelligentOut(mpu_t *mpu, uint8_t chan)
|
|||||||
val=mpu->playbuf[chan].sys_val;
|
val=mpu->playbuf[chan].sys_val;
|
||||||
if (val==0xfc) {
|
if (val==0xfc) {
|
||||||
midi_write(val);
|
midi_write(val);
|
||||||
mpu->state.amask&=~(1<<chan);
|
mpu->state.amask &= ~(1<<chan);
|
||||||
mpu->state.req_mask&=~(1<<chan);
|
mpu->state.req_mask &= ~(1<<chan);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_MIDI_NORM:
|
case T_MIDI_NORM:
|
||||||
for (i=0;i<mpu->playbuf[chan].vlength;i++)
|
for (i = 0; i < mpu->playbuf[chan].vlength; i++)
|
||||||
midi_write(mpu->playbuf[chan].value[i]);
|
midi_write(mpu->playbuf[chan].value[i]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -618,13 +635,13 @@ UpdateTrack(mpu_t *mpu, uint8_t chan)
|
|||||||
MPU401_IntelligentOut(mpu, chan);
|
MPU401_IntelligentOut(mpu, chan);
|
||||||
|
|
||||||
if (mpu->state.amask&(1<<chan)) {
|
if (mpu->state.amask&(1<<chan)) {
|
||||||
mpu->playbuf[chan].vlength=0;
|
mpu->playbuf[chan].vlength = 0;
|
||||||
mpu->playbuf[chan].type=T_OVERFLOW;
|
mpu->playbuf[chan].type = T_OVERFLOW;
|
||||||
mpu->playbuf[chan].counter=0xf0;
|
mpu->playbuf[chan].counter = 0xf0;
|
||||||
mpu->state.req_mask|=(1<<chan);
|
mpu->state.req_mask |= (1 << chan);
|
||||||
} else {
|
} else {
|
||||||
if (mpu->state.amask==0 && !mpu->state.conductor)
|
if ((mpu->state.amask == 0) && !mpu->state.conductor)
|
||||||
mpu->state.req_mask|=(1<<12);
|
mpu->state.req_mask |= (1 << 12);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -632,22 +649,22 @@ UpdateTrack(mpu_t *mpu, uint8_t chan)
|
|||||||
static void
|
static void
|
||||||
UpdateConductor(mpu_t *mpu)
|
UpdateConductor(mpu_t *mpu)
|
||||||
{
|
{
|
||||||
if (mpu->condbuf.value[0]==0xfc) {
|
if (mpu->condbuf.value[0] == 0xfc) {
|
||||||
mpu->condbuf.value[0]=0;
|
mpu->condbuf.value[0] = 0;
|
||||||
mpu->state.conductor=0;
|
mpu->state.conductor = 0;
|
||||||
mpu->state.req_mask&=~(1<<9);
|
mpu->state.req_mask &= ~(1 << 9);
|
||||||
if (mpu->state.amask==0)
|
if (mpu->state.amask == 0)
|
||||||
mpu->state.req_mask|=(1<<12);
|
mpu->state.req_mask |= (1 << 12);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mpu->condbuf.vlength=0;
|
mpu->condbuf.vlength = 0;
|
||||||
mpu->condbuf.counter=0xf0;
|
mpu->condbuf.counter = 0xf0;
|
||||||
mpu->state.req_mask|=(1<<9);
|
mpu->state.req_mask |= (1 << 9);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//Updates counters and requests new data on "End of Input"
|
/* Updates counters and requests new data on "End of Input" */
|
||||||
static void
|
static void
|
||||||
MPU401_EOIHandler(void *priv)
|
MPU401_EOIHandler(void *priv)
|
||||||
{
|
{
|
||||||
@@ -657,25 +674,26 @@ MPU401_EOIHandler(void *priv)
|
|||||||
mpu401_log("MPU-401 end of input callback\n");
|
mpu401_log("MPU-401 end of input callback\n");
|
||||||
|
|
||||||
mpu401_eoi_callback = 0LL;
|
mpu401_eoi_callback = 0LL;
|
||||||
mpu->state.eoi_scheduled=0;
|
mpu->state.eoi_scheduled = 0;
|
||||||
if (mpu->state.send_now) {
|
if (mpu->state.send_now) {
|
||||||
mpu->state.send_now=0;
|
mpu->state.send_now = 0;
|
||||||
if (mpu->state.cond_req) UpdateConductor(mpu);
|
if (mpu->state.cond_req) UpdateConductor(mpu);
|
||||||
else UpdateTrack(mpu, mpu->state.channel);
|
else UpdateTrack(mpu, mpu->state.channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
mpu->state.irq_pending=0;
|
mpu->state.irq_pending = 0;
|
||||||
|
|
||||||
if (!mpu->state.playing || !mpu->state.req_mask) return;
|
if (!mpu->state.playing || !mpu->state.req_mask)
|
||||||
|
return;
|
||||||
|
|
||||||
i=0;
|
i = 0;
|
||||||
do {
|
do {
|
||||||
if (mpu->state.req_mask&(1<<i)) {
|
if (mpu->state.req_mask & (1 << i)) {
|
||||||
QueueByte(mpu, 0xf0+i);
|
QueueByte(mpu, 0xf0 + i);
|
||||||
mpu->state.req_mask&=~(1<<i);
|
mpu->state.req_mask &= ~(1 << i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} while ((i++)<16);
|
} while ((i++) < 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -686,7 +704,7 @@ MPU401_EOIHandlerDispatch(void *priv)
|
|||||||
|
|
||||||
mpu401_log("EOI handler dispatch\n");
|
mpu401_log("EOI handler dispatch\n");
|
||||||
if (mpu->state.send_now) {
|
if (mpu->state.send_now) {
|
||||||
mpu->state.eoi_scheduled=1;
|
mpu->state.eoi_scheduled = 1;
|
||||||
mpu401_eoi_callback = 60LL * TIMER_USEC; /* Possible a bit longer */
|
mpu401_eoi_callback = 60LL * TIMER_USEC; /* Possible a bit longer */
|
||||||
} else if (!mpu->state.eoi_scheduled)
|
} else if (!mpu->state.eoi_scheduled)
|
||||||
MPU401_EOIHandler(mpu);
|
MPU401_EOIHandler(mpu);
|
||||||
@@ -707,36 +725,41 @@ MPU401_ReadData(mpu_t *mpu)
|
|||||||
|
|
||||||
ret = MSG_MPU_ACK;
|
ret = MSG_MPU_ACK;
|
||||||
if (mpu->queue_used) {
|
if (mpu->queue_used) {
|
||||||
if (mpu->queue_pos>=MPU401_QUEUE) mpu->queue_pos-=MPU401_QUEUE;
|
if (mpu->queue_pos >= MPU401_QUEUE)
|
||||||
ret=mpu->queue[mpu->queue_pos];
|
mpu->queue_pos -= MPU401_QUEUE;
|
||||||
mpu->queue_pos++;mpu->queue_used--;
|
ret = mpu->queue[mpu->queue_pos];
|
||||||
|
mpu->queue_pos++;
|
||||||
|
mpu->queue_used--;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mpu->intelligent) return ret;
|
/* Shouldn't this check mpu->mode? */
|
||||||
|
if (mpu->mode == M_UART)
|
||||||
|
return ret;
|
||||||
|
|
||||||
if (mpu->queue_used == 0) picintc(1 << mpu->irq);
|
if (mpu->queue_used == 0)
|
||||||
|
picintc(1 << mpu->irq);
|
||||||
|
|
||||||
if (ret>=0xf0 && ret<=0xf7) {
|
if ((ret >= 0xf0) && (ret <= 0xf7)) {
|
||||||
/* MIDI data request */
|
/* MIDI data request */
|
||||||
mpu->state.channel=ret&7;
|
mpu->state.channel = ret & 7;
|
||||||
mpu->state.data_onoff=0;
|
mpu->state.data_onoff = 0;
|
||||||
mpu->state.cond_req=0;
|
mpu->state.cond_req = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret==MSG_MPU_COMMAND_REQ) {
|
if (ret == MSG_MPU_COMMAND_REQ) {
|
||||||
mpu->state.data_onoff=0;
|
mpu->state.data_onoff = 0;
|
||||||
mpu->state.cond_req=1;
|
mpu->state.cond_req = 1;
|
||||||
if (mpu->condbuf.type!=T_OVERFLOW) {
|
if (mpu->condbuf.type != T_OVERFLOW) {
|
||||||
mpu->state.block_ack=1;
|
mpu->state.block_ack = 1;
|
||||||
MPU401_WriteCommand(mpu, mpu->condbuf.value[0]);
|
MPU401_WriteCommand(mpu, mpu->condbuf.value[0]);
|
||||||
if (mpu->state.command_byte)
|
if (mpu->state.command_byte)
|
||||||
MPU401_WriteData(mpu, mpu->condbuf.value[1]);
|
MPU401_WriteData(mpu, mpu->condbuf.value[1]);
|
||||||
}
|
}
|
||||||
mpu->condbuf.type=T_OVERFLOW;
|
mpu->condbuf.type = T_OVERFLOW;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret==MSG_MPU_END || ret==MSG_MPU_CLOCK || ret==MSG_MPU_ACK) {
|
if ((ret == MSG_MPU_END) || (ret == MSG_MPU_CLOCK) || (ret == MSG_MPU_ACK)) {
|
||||||
mpu->state.data_onoff=-1;
|
mpu->state.data_onoff = -1;
|
||||||
MPU401_EOIHandlerDispatch(mpu);
|
MPU401_EOIHandlerDispatch(mpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -771,12 +794,12 @@ mpu401_read(uint16_t addr, void *priv)
|
|||||||
uint8_t ret = 0;
|
uint8_t ret = 0;
|
||||||
|
|
||||||
switch (addr & 1) {
|
switch (addr & 1) {
|
||||||
case 0: //Read Data
|
case 0: /* Read Data */
|
||||||
ret = MPU401_ReadData(mpu);
|
ret = MPU401_ReadData(mpu);
|
||||||
mpu401_log("Read Data (0x330) %X\n", ret);
|
mpu401_log("Read Data (0x330) %X\n", ret);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1: //Read Status
|
case 1: /* Read Status */
|
||||||
if (mpu->state.cmd_pending) ret=STATUS_OUTPUT_NOT_READY;
|
if (mpu->state.cmd_pending) ret=STATUS_OUTPUT_NOT_READY;
|
||||||
if (!mpu->queue_used) ret=STATUS_INPUT_NOT_READY;
|
if (!mpu->queue_used) ret=STATUS_INPUT_NOT_READY;
|
||||||
ret |= 0x3f;
|
ret |= 0x3f;
|
||||||
@@ -799,44 +822,43 @@ MPU401_Event(void *priv)
|
|||||||
|
|
||||||
mpu401_log("MPU-401 event callback\n");
|
mpu401_log("MPU-401 event callback\n");
|
||||||
|
|
||||||
if (mpu->mode==M_UART) {
|
if (mpu->mode == M_UART) {
|
||||||
mpu401_event_callback = 0LL;
|
mpu401_event_callback = 0LL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mpu->state.irq_pending) goto next_event;
|
if (mpu->state.irq_pending) goto next_event;
|
||||||
|
|
||||||
for (i=0;i<8;i++) { /* Decrease counters */
|
for (i = 0; i < 8; i++) { /* Decrease counters */
|
||||||
if (mpu->state.amask&(1<<i)) {
|
if (mpu->state.amask & (1 << i)) {
|
||||||
mpu->playbuf[i].counter--;
|
mpu->playbuf[i].counter--;
|
||||||
if (mpu->playbuf[i].counter<=0) UpdateTrack(mpu, i);
|
if (mpu->playbuf[i].counter <= 0) UpdateTrack(mpu, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mpu->state.conductor) {
|
if (mpu->state.conductor) {
|
||||||
mpu->condbuf.counter--;
|
mpu->condbuf.counter--;
|
||||||
if (mpu->condbuf.counter<=0) UpdateConductor(mpu);
|
if (mpu->condbuf.counter <= 0) UpdateConductor(mpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mpu->clock.clock_to_host) {
|
if (mpu->clock.clock_to_host) {
|
||||||
mpu->clock.cth_counter++;
|
mpu->clock.cth_counter++;
|
||||||
if (mpu->clock.cth_counter >= mpu->clock.cth_rate) {
|
if (mpu->clock.cth_counter >= mpu->clock.cth_rate) {
|
||||||
mpu->clock.cth_counter=0;
|
mpu->clock.cth_counter = 0;
|
||||||
mpu->state.req_mask|=(1<<13);
|
mpu->state.req_mask |= (1 << 13);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mpu->state.irq_pending && mpu->state.req_mask)
|
if (!mpu->state.irq_pending && mpu->state.req_mask)
|
||||||
MPU401_EOIHandler(mpu);
|
MPU401_EOIHandler(mpu);
|
||||||
|
|
||||||
next_event:
|
next_event:
|
||||||
/* mpu401_event_callback = 0LL; */
|
new_time = ((mpu->clock.tempo * mpu->clock.timebase * mpu->clock.tempo_rel) / 0x40);
|
||||||
new_time = ((mpu->clock.tempo * mpu->clock.timebase * mpu->clock.tempo_rel)/0x40);
|
|
||||||
if (new_time == 0) {
|
if (new_time == 0) {
|
||||||
mpu401_event_callback = 0LL;
|
mpu401_event_callback = 0LL;
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
mpu401_event_callback += (MPU401_TIMECONSTANT/new_time) * 1000LL * TIMER_USEC;
|
mpu401_event_callback += (MPU401_TIMECONSTANT / new_time) * 1000LL * TIMER_USEC;
|
||||||
mpu401_log("Next event after %i us (time constant: %i)\n", (int) ((MPU401_TIMECONSTANT/new_time) * 1000 * TIMER_USEC), (int) MPU401_TIMECONSTANT);
|
mpu401_log("Next event after %i us (time constant: %i)\n", (int) ((MPU401_TIMECONSTANT/new_time) * 1000 * TIMER_USEC), (int) MPU401_TIMECONSTANT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -851,6 +873,10 @@ mpu401_init(mpu_t *mpu, uint16_t addr, int irq, int mode)
|
|||||||
mpu->queue_pos = 0;
|
mpu->queue_pos = 0;
|
||||||
mpu->mode = M_UART;
|
mpu->mode = M_UART;
|
||||||
|
|
||||||
|
/* Expalantion:
|
||||||
|
MPU-401 starting in intelligent mode = Full MPU-401 intelligent mode capability;
|
||||||
|
MPU-401 starting in UART mode = Reduced MPU-401 intelligent mode capability seen on the Sound Blaster 16/AWE32,
|
||||||
|
only supporting commands 3F (set UART mode) and FF (reset). */
|
||||||
mpu->intelligent = (mode == M_INTELLIGENT) ? 1 : 0;
|
mpu->intelligent = (mode == M_INTELLIGENT) ? 1 : 0;
|
||||||
mpu401_log("Starting as %s (mode is %s)\n", mpu->intelligent ? "INTELLIGENT" : "UART", (mode == M_INTELLIGENT) ? "INTELLIGENT" : "UART");
|
mpu401_log("Starting as %s (mode is %s)\n", mpu->intelligent ? "INTELLIGENT" : "UART", (mode == M_INTELLIGENT) ? "INTELLIGENT" : "UART");
|
||||||
|
|
||||||
@@ -858,8 +884,9 @@ mpu401_init(mpu_t *mpu, uint16_t addr, int irq, int mode)
|
|||||||
mpu401_eoi_callback = 0LL;
|
mpu401_eoi_callback = 0LL;
|
||||||
mpu401_reset_callback = 0LL;
|
mpu401_reset_callback = 0LL;
|
||||||
|
|
||||||
io_sethandler(addr, 2,
|
if (addr)
|
||||||
mpu401_read, NULL, NULL, mpu401_write, NULL, NULL, mpu);
|
io_sethandler(addr, 2,
|
||||||
|
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(MPU401_Event, &mpu401_event_callback, &mpu401_event_callback, mpu);
|
timer_add(MPU401_Event, &mpu401_event_callback, &mpu401_event_callback, mpu);
|
||||||
@@ -878,52 +905,55 @@ mpu401_device_add(void)
|
|||||||
if (!mpu401_standalone_enable) return;
|
if (!mpu401_standalone_enable) return;
|
||||||
|
|
||||||
n = sound_card_get_internal_name(sound_card_current);
|
n = sound_card_get_internal_name(sound_card_current);
|
||||||
if (n != NULL)
|
if (n != NULL) {
|
||||||
{
|
if (!strcmp(n, "ncraudio"))
|
||||||
if (!strcmp(n, "ncraudio"))
|
mca_version = 1;
|
||||||
mca_version = 1;
|
else
|
||||||
else
|
mca_version = 0;
|
||||||
mca_version = 0;
|
|
||||||
|
if (!strcmp(n, "sb16") || !strcmp(n, "sbawe32") || !strcmp(n, "replysb16")) return;
|
||||||
if (!strcmp(n, "sb16") || !strcmp(n, "sbawe32") || !strcmp(n, "replysb16")) return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mca_version)
|
if (mca_version)
|
||||||
device_add(&mpu401_mca_device);
|
device_add(&mpu401_mca_device);
|
||||||
else
|
else
|
||||||
device_add(&mpu401_device);
|
device_add(&mpu401_device);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t mpu401_mca_read(int port, void *p)
|
|
||||||
{
|
|
||||||
mpu_t *mpu = (mpu_t *)p;
|
|
||||||
|
|
||||||
return mpu->pos_regs[port & 7];
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mpu401_mca_write(int port, uint8_t val, void *p)
|
static uint8_t
|
||||||
|
mpu401_mca_read(int port, void *p)
|
||||||
{
|
{
|
||||||
mpu_t *mpu = (mpu_t *)p;
|
mpu_t *mpu = (mpu_t *)p;
|
||||||
uint16_t addr;
|
|
||||||
|
return mpu->pos_regs[port & 7];
|
||||||
if (port < 0x102)
|
}
|
||||||
return;
|
|
||||||
|
|
||||||
addr = (mpu->pos_regs[2] & 2) ? 0x0330 : 0x1330;
|
static void
|
||||||
|
mpu401_mca_write(int port, uint8_t val, void *p)
|
||||||
io_removehandler(addr, 2,
|
{
|
||||||
mpu401_read, NULL, NULL, mpu401_write, NULL, NULL, mpu);
|
mpu_t *mpu = (mpu_t *)p;
|
||||||
io_removehandler(0x2A20, 16,
|
uint16_t addr;
|
||||||
NULL, NULL, NULL, imf_write, NULL, NULL, mpu);
|
|
||||||
|
if (port < 0x102)
|
||||||
mpu->pos_regs[port & 7] = val;
|
return;
|
||||||
|
|
||||||
if (mpu->pos_regs[2] & 1)
|
addr = (mpu->pos_regs[2] & 2) ? 0x0330 : 0x1330;
|
||||||
{
|
|
||||||
addr = (mpu->pos_regs[2] & 2) ? 0x0330 : 0x1330;
|
port &= 7;
|
||||||
|
|
||||||
mpu401_init(mpu, addr, device_get_config_int("irq"), device_get_config_int("mode"));
|
mpu->pos_regs[port] = val;
|
||||||
}
|
|
||||||
|
if (port == 2) {
|
||||||
|
io_removehandler(addr, 2,
|
||||||
|
mpu401_read, NULL, NULL, mpu401_write, NULL, NULL, mpu);
|
||||||
|
|
||||||
|
addr = (mpu->pos_regs[2] & 2) ? 0x1330 : 0x0330;
|
||||||
|
|
||||||
|
io_sethandler(addr, 2,
|
||||||
|
mpu401_read, NULL, NULL, mpu401_write, NULL, NULL, mpu);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -931,22 +961,28 @@ static void *
|
|||||||
mpu401_standalone_init(const device_t *info)
|
mpu401_standalone_init(const device_t *info)
|
||||||
{
|
{
|
||||||
mpu_t *mpu;
|
mpu_t *mpu;
|
||||||
|
int irq;
|
||||||
|
uint16_t base;
|
||||||
|
|
||||||
mpu = malloc(sizeof(mpu_t));
|
mpu = malloc(sizeof(mpu_t));
|
||||||
memset(mpu, 0, sizeof(mpu_t));
|
memset(mpu, 0, sizeof(mpu_t));
|
||||||
|
|
||||||
mpu401_log("mpu_init\n");
|
mpu401_log("mpu_init\n");
|
||||||
|
|
||||||
if (info->flags & DEVICE_MCA)
|
|
||||||
{
|
|
||||||
mca_add(mpu401_mca_read, mpu401_mca_write, mpu);
|
|
||||||
mpu->pos_regs[0] = 0x0F;
|
|
||||||
mpu->pos_regs[1] = 0x6C;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
mpu401_init(mpu, device_get_config_hex16("base"), device_get_config_int("irq"), device_get_config_int("mode"));
|
|
||||||
|
|
||||||
return(mpu);
|
if (info->flags & DEVICE_MCA) {
|
||||||
|
mca_add(mpu401_mca_read, mpu401_mca_write, mpu);
|
||||||
|
mpu->pos_regs[0] = 0x0F;
|
||||||
|
mpu->pos_regs[1] = 0x6C;
|
||||||
|
base = 0; /* Tell mpu401_init() that this is the MCA variant. */
|
||||||
|
irq = 2; /* According to @6c0f.adf, the IRQ is fixed to 2. */
|
||||||
|
} else {
|
||||||
|
base = device_get_config_hex16("base");
|
||||||
|
irq = device_get_config_int("irq");
|
||||||
|
}
|
||||||
|
|
||||||
|
mpu401_init(mpu, base, irq, M_INTELLIGENT);
|
||||||
|
|
||||||
|
return(mpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1001,73 +1037,12 @@ static const device_config_t mpu401_standalone_config[] =
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"mode", "Mode", CONFIG_SELECTION, "", 1,
|
|
||||||
{
|
|
||||||
{
|
|
||||||
"UART", M_UART
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Intelligent", M_INTELLIGENT
|
|
||||||
},
|
|
||||||
{
|
|
||||||
""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"", "", -1
|
"", "", -1
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static const device_config_t mpu401_mca_standalone_config[] =
|
|
||||||
{
|
|
||||||
{
|
|
||||||
"irq", "MPU-401 IRQ", CONFIG_SELECTION, "", 9,
|
|
||||||
{
|
|
||||||
{
|
|
||||||
"IRQ 9", 9
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"IRQ 3", 3
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"IRQ 4", 4
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"IRQ 5", 5
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"IRQ 7", 7
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"IRQ 10", 10
|
|
||||||
},
|
|
||||||
{
|
|
||||||
""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"mode", "Mode", CONFIG_SELECTION, "", 1,
|
|
||||||
{
|
|
||||||
{
|
|
||||||
"UART", M_UART
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Intelligent", M_INTELLIGENT
|
|
||||||
},
|
|
||||||
{
|
|
||||||
""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"", "", -1
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const device_t mpu401_device = {
|
const device_t mpu401_device = {
|
||||||
"MPU-401 (Standalone)",
|
"MPU-401 (Standalone)",
|
||||||
DEVICE_ISA, 0,
|
DEVICE_ISA, 0,
|
||||||
@@ -1079,11 +1054,11 @@ const device_t mpu401_device = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const device_t mpu401_mca_device = {
|
const device_t mpu401_mca_device = {
|
||||||
"MPU-401 MCA (Standalone)",
|
"Roland MPU-IMC",
|
||||||
DEVICE_MCA, 0,
|
DEVICE_MCA, 0,
|
||||||
mpu401_standalone_init, mpu401_standalone_close, NULL,
|
mpu401_standalone_init, mpu401_standalone_close, NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
mpu401_mca_standalone_config
|
NULL
|
||||||
};
|
};
|
||||||
|
@@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
* Roland MPU-401 emulation.
|
* Roland MPU-401 emulation.
|
||||||
*
|
*
|
||||||
* Version: @(#)sound_mpu401.h 1.0.1 2018/03/18
|
* Version: @(#)sound_mpu401.h 1.0.2 2018/09/16
|
||||||
*
|
*
|
||||||
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
|
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||||
* DOSBox Team,
|
* DOSBox Team,
|
||||||
@@ -26,8 +26,22 @@
|
|||||||
#define MPU401_TIMECONSTANT (60000000/1000.0f)
|
#define MPU401_TIMECONSTANT (60000000/1000.0f)
|
||||||
#define MPU401_RESETBUSY 27.0f
|
#define MPU401_RESETBUSY 27.0f
|
||||||
|
|
||||||
typedef enum MpuMode { M_UART,M_INTELLIGENT } MpuMode;
|
typedef enum MpuMode
|
||||||
typedef enum MpuDataType {T_OVERFLOW,T_MARK,T_MIDI_SYS,T_MIDI_NORM,T_COMMAND} MpuDataType;
|
{
|
||||||
|
M_UART,
|
||||||
|
M_INTELLIGENT
|
||||||
|
} MpuMode;
|
||||||
|
|
||||||
|
#define M_MCA 0x10
|
||||||
|
|
||||||
|
typedef enum MpuDataType
|
||||||
|
{
|
||||||
|
T_OVERFLOW,
|
||||||
|
T_MARK,
|
||||||
|
T_MIDI_SYS,
|
||||||
|
T_MIDI_NORM,
|
||||||
|
T_COMMAND
|
||||||
|
} MpuDataType;
|
||||||
|
|
||||||
/* Messages sent to MPU-401 from host */
|
/* Messages sent to MPU-401 from host */
|
||||||
#define MSG_EOX 0xf7
|
#define MSG_EOX 0xf7
|
||||||
@@ -43,55 +57,50 @@ typedef enum MpuDataType {T_OVERFLOW,T_MARK,T_MIDI_SYS,T_MIDI_NORM,T_COMMAND} Mp
|
|||||||
|
|
||||||
typedef struct mpu_t
|
typedef struct mpu_t
|
||||||
{
|
{
|
||||||
int uart_mode;
|
int uart_mode, intelligent,
|
||||||
uint8_t rx_data;
|
irq,
|
||||||
int intelligent;
|
queue_pos, queue_used;
|
||||||
MpuMode mode;
|
uint8_t rx_data, is_mca,
|
||||||
int irq;
|
status,
|
||||||
uint8_t status;
|
queue[MPU401_QUEUE], pos_regs[8];
|
||||||
uint8_t queue[MPU401_QUEUE];
|
MpuMode mode;
|
||||||
int queue_pos,queue_used;
|
struct track
|
||||||
struct track
|
{
|
||||||
{
|
int counter;
|
||||||
int counter;
|
uint8_t value[8], sys_val,
|
||||||
uint8_t value[8],sys_val;
|
vlength,length;
|
||||||
uint8_t vlength,length;
|
MpuDataType type;
|
||||||
MpuDataType type;
|
} playbuf[8], condbuf;
|
||||||
} playbuf[8],condbuf;
|
struct {
|
||||||
struct {
|
int conductor, cond_req,
|
||||||
int conductor,cond_req,cond_set, block_ack;
|
cond_set, block_ack,
|
||||||
int playing,reset;
|
playing, reset,
|
||||||
int wsd,wsm,wsd_start;
|
wsd, wsm, wsd_start,
|
||||||
int run_irq,irq_pending;
|
run_irq, irq_pending,
|
||||||
int send_now;
|
send_now, eoi_scheduled,
|
||||||
int eoi_scheduled;
|
data_onoff;
|
||||||
int data_onoff;
|
uint8_t tmask, cmask,
|
||||||
uint32_t command_byte,cmd_pending;
|
amask,
|
||||||
uint8_t tmask,cmask,amask;
|
channel, old_chan;
|
||||||
uint16_t midi_mask;
|
uint16_t midi_mask, req_mask;
|
||||||
uint16_t req_mask;
|
uint32_t command_byte, cmd_pending;
|
||||||
uint8_t channel,old_chan;
|
} state;
|
||||||
} state;
|
struct {
|
||||||
struct {
|
uint8_t timebase, old_timebase,
|
||||||
uint8_t timebase,old_timebase;
|
tempo, old_tempo,
|
||||||
uint8_t tempo,old_tempo;
|
tempo_rel, old_tempo_rel,
|
||||||
uint8_t tempo_rel,old_tempo_rel;
|
tempo_grad,
|
||||||
uint8_t tempo_grad;
|
cth_rate, cth_counter;
|
||||||
uint8_t cth_rate,cth_counter;
|
int clock_to_host,cth_active;
|
||||||
int clock_to_host,cth_active;
|
} clock;
|
||||||
} clock;
|
|
||||||
|
|
||||||
uint8_t pos_regs[8];
|
|
||||||
} mpu_t;
|
} mpu_t;
|
||||||
|
|
||||||
uint8_t MPU401_ReadData(mpu_t *mpu);
|
extern int mca_version;
|
||||||
|
extern int mpu401_standalone_enable;
|
||||||
|
extern const device_t mpu401_device;
|
||||||
|
extern const device_t mpu401_mca_device;
|
||||||
|
|
||||||
void mpu401_init(mpu_t *mpu, uint16_t addr, int irq, int mode);
|
|
||||||
|
|
||||||
extern int mca_version;
|
|
||||||
extern int mpu401_standalone_enable;
|
|
||||||
|
|
||||||
void mpu401_device_add(void);
|
|
||||||
const device_t mpu401_device;
|
|
||||||
const device_t mpu401_mca_device;
|
|
||||||
|
|
||||||
|
extern uint8_t MPU401_ReadData(mpu_t *mpu);
|
||||||
|
extern void mpu401_init(mpu_t *mpu, uint16_t addr, int irq, int mode);
|
||||||
|
extern void mpu401_device_add(void);
|
||||||
|
@@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
* Sound Blaster emulation.
|
* Sound Blaster emulation.
|
||||||
*
|
*
|
||||||
* Version: @(#)sound_sb.c 1.0.10 2018/09/04
|
* Version: @(#)sound_sb.c 1.0.11 2018/09/11
|
||||||
*
|
*
|
||||||
* 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>
|
||||||
@@ -1272,7 +1272,6 @@ void *sb_pro_mcv_init()
|
|||||||
|
|
||||||
void *sb_16_init()
|
void *sb_16_init()
|
||||||
{
|
{
|
||||||
int mpu_irq;
|
|
||||||
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");
|
||||||
memset(sb, 0, sizeof(sb_t));
|
memset(sb, 0, sizeof(sb_t));
|
||||||
@@ -1296,10 +1295,7 @@ void *sb_16_init()
|
|||||||
#if 0
|
#if 0
|
||||||
sound_add_process_handler(sb_process_buffer_sb16, sb);
|
sound_add_process_handler(sb_process_buffer_sb16, sb);
|
||||||
#endif
|
#endif
|
||||||
mpu_irq = device_get_config_int("irq401");
|
mpu401_init(&sb->mpu, device_get_config_hex16("base401"), device_get_config_int("irq"), M_UART);
|
||||||
if (mpu_irq == 255)
|
|
||||||
mpu_irq = device_get_config_int("irq");
|
|
||||||
mpu401_init(&sb->mpu, device_get_config_hex16("base401"), mpu_irq, device_get_config_int("mode401"));
|
|
||||||
sb_dsp_set_mpu(&sb->mpu);
|
sb_dsp_set_mpu(&sb->mpu);
|
||||||
#if 0
|
#if 0
|
||||||
memcpy(&sb->temp_mixer_sb16, &sb->mixer_sb16, sizeof(sb_ct1745_mixer_t));
|
memcpy(&sb->temp_mixer_sb16, &sb->mixer_sb16, sizeof(sb_ct1745_mixer_t));
|
||||||
@@ -1315,7 +1311,6 @@ int sb_awe32_available()
|
|||||||
|
|
||||||
void *sb_awe32_init()
|
void *sb_awe32_init()
|
||||||
{
|
{
|
||||||
int mpu_irq;
|
|
||||||
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");
|
||||||
uint16_t emu_addr = device_get_config_hex16("emu_base");
|
uint16_t emu_addr = device_get_config_hex16("emu_base");
|
||||||
@@ -1344,10 +1339,7 @@ void *sb_awe32_init()
|
|||||||
#if 0
|
#if 0
|
||||||
sound_add_process_handler(sb_process_buffer_sb16, sb);
|
sound_add_process_handler(sb_process_buffer_sb16, sb);
|
||||||
#endif
|
#endif
|
||||||
mpu_irq = device_get_config_int("irq401");
|
mpu401_init(&sb->mpu, device_get_config_hex16("base401"), device_get_config_int("irq"), M_UART);
|
||||||
if (mpu_irq == 255)
|
|
||||||
mpu_irq = device_get_config_int("irq");
|
|
||||||
mpu401_init(&sb->mpu, device_get_config_hex16("base401"), mpu_irq, device_get_config_int("mode401"));
|
|
||||||
sb_dsp_set_mpu(&sb->mpu);
|
sb_dsp_set_mpu(&sb->mpu);
|
||||||
emu8k_init(&sb->emu8k, emu_addr, onboard_ram);
|
emu8k_init(&sb->emu8k, emu_addr, onboard_ram);
|
||||||
#if 0
|
#if 0
|
||||||
@@ -1606,35 +1598,6 @@ static const device_config_t sb_16_config[] =
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"irq401", "MPU-401 IRQ", CONFIG_SELECTION, "", 9,
|
|
||||||
{
|
|
||||||
{
|
|
||||||
"Use main IRQ", 255
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"IRQ 9", 9
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"IRQ 3", 3
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"IRQ 4", 4
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"IRQ 5", 5
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"IRQ 7", 7
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"IRQ 10", 10
|
|
||||||
},
|
|
||||||
{
|
|
||||||
""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"dma", "Low DMA channel", CONFIG_SELECTION, "", 1,
|
"dma", "Low DMA channel", CONFIG_SELECTION, "", 1,
|
||||||
{
|
{
|
||||||
@@ -1669,20 +1632,6 @@ static const device_config_t sb_16_config[] =
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"mode401", "MPU-401 mode", CONFIG_SELECTION, "", 1,
|
|
||||||
{
|
|
||||||
{
|
|
||||||
"UART", M_UART
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Intelligent", M_INTELLIGENT
|
|
||||||
},
|
|
||||||
{
|
|
||||||
""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"opl", "Enable OPL", CONFIG_BINARY, "", 1
|
"opl", "Enable OPL", CONFIG_BINARY, "", 1
|
||||||
},
|
},
|
||||||
@@ -1767,35 +1716,6 @@ static const device_config_t sb_awe32_config[] =
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"irq401", "MPU-401 IRQ", CONFIG_SELECTION, "", 9,
|
|
||||||
{
|
|
||||||
{
|
|
||||||
"Use main IRQ", 255
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"IRQ 9", 9
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"IRQ 3", 3
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"IRQ 4", 4
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"IRQ 5", 5
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"IRQ 7", 7
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"IRQ 10", 10
|
|
||||||
},
|
|
||||||
{
|
|
||||||
""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"dma", "Low DMA channel", CONFIG_SELECTION, "", 1,
|
"dma", "Low DMA channel", CONFIG_SELECTION, "", 1,
|
||||||
{
|
{
|
||||||
@@ -1830,20 +1750,6 @@ static const device_config_t sb_awe32_config[] =
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"mode401", "MPU-401 mode", CONFIG_SELECTION, "", 1,
|
|
||||||
{
|
|
||||||
{
|
|
||||||
"UART", M_UART
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Intelligent", M_INTELLIGENT
|
|
||||||
},
|
|
||||||
{
|
|
||||||
""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"onboard_ram", "Onboard RAM", CONFIG_SELECTION, "", 512,
|
"onboard_ram", "Onboard RAM", CONFIG_SELECTION, "", 512,
|
||||||
{
|
{
|
||||||
|
@@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
* Sound emulation core.
|
* Sound emulation core.
|
||||||
*
|
*
|
||||||
* Version: @(#)sound.c 1.0.18 2018/08/11
|
* Version: @(#)sound.c 1.0.19 2018/09/11
|
||||||
*
|
*
|
||||||
* 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>
|
||||||
@@ -85,27 +85,27 @@ static volatile int cdaudioon = 0;
|
|||||||
|
|
||||||
static const SOUND_CARD sound_cards[] =
|
static const SOUND_CARD sound_cards[] =
|
||||||
{
|
{
|
||||||
{ "None", "none", NULL },
|
{ "None", "none", NULL },
|
||||||
{ "[ISA] Adlib", "adlib", &adlib_device },
|
{ "[ISA] Adlib", "adlib", &adlib_device },
|
||||||
{ "[ISA] Adlib Gold", "adlibgold",&adgold_device },
|
{ "[ISA] Adlib Gold", "adlibgold", &adgold_device },
|
||||||
{ "[ISA] Sound Blaster 1.0", "sb", &sb_1_device },
|
{ "[ISA] Sound Blaster 1.0", "sb", &sb_1_device },
|
||||||
{ "[ISA] Sound Blaster 1.5", "sb1.5", &sb_15_device },
|
{ "[ISA] Sound Blaster 1.5", "sb1.5", &sb_15_device },
|
||||||
{ "[ISA] Sound Blaster 2.0", "sb2.0", &sb_2_device },
|
{ "[ISA] Sound Blaster 2.0", "sb2.0", &sb_2_device },
|
||||||
{ "[ISA] Sound Blaster Pro v1", "sbprov1", &sb_pro_v1_device },
|
{ "[ISA] Sound Blaster Pro v1", "sbprov1", &sb_pro_v1_device },
|
||||||
{ "[ISA] Sound Blaster Pro v2", "sbprov2", &sb_pro_v2_device },
|
{ "[ISA] Sound Blaster Pro v2", "sbprov2", &sb_pro_v2_device },
|
||||||
{ "[ISA] Sound Blaster 16", "sb16", &sb_16_device },
|
{ "[ISA] Sound Blaster 16", "sb16", &sb_16_device },
|
||||||
{ "[ISA] Sound Blaster AWE32", "sbawe32", &sb_awe32_device },
|
{ "[ISA] Sound Blaster AWE32", "sbawe32", &sb_awe32_device },
|
||||||
#if defined(DEV_BRANCH) && defined(USE_PAS16)
|
#if defined(DEV_BRANCH) && defined(USE_PAS16)
|
||||||
{ "[ISA] Pro Audio Spectrum 16","pas16", &pas16_device },
|
{ "[ISA] Pro Audio Spectrum 16", "pas16", &pas16_device },
|
||||||
#endif
|
#endif
|
||||||
{ "[ISA] Windows Sound System", "wss", &wss_device },
|
{ "[ISA] Windows Sound System", "wss", &wss_device },
|
||||||
{ "[MCA] Adlib", "adlib_mca", &adlib_mca_device },
|
{ "[MCA] Adlib", "adlib_mca", &adlib_mca_device },
|
||||||
{ "[MCA] NCR Business Audio","ncraudio", &ncr_business_audio_device },
|
{ "[MCA] NCR Business Audio", "ncraudio", &ncr_business_audio_device },
|
||||||
{ "[MCA] Sound Blaster MCV", "sbmcv", &sb_mcv_device },
|
{ "[MCA] Sound Blaster MCV", "sbmcv", &sb_mcv_device },
|
||||||
{ "[MCA] Sound Blaster Pro MCV","sbpromcv", &sb_pro_mcv_device },
|
{ "[MCA] Sound Blaster Pro MCV", "sbpromcv", &sb_pro_mcv_device },
|
||||||
{ "[PCI] Ensoniq AudioPCI (ES1371)","es1371", &es1371_device},
|
{ "[PCI] Ensoniq AudioPCI (ES1371)", "es1371", &es1371_device },
|
||||||
{ "[PCI] Sound Blaster PCI 128", "sbpci128", &es1371_device},
|
{ "[PCI] Sound Blaster PCI 128", "sbpci128", &es1371_device },
|
||||||
{ "", "", NULL }
|
{ "", "", NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@@ -11,117 +11,127 @@
|
|||||||
#include "../plat_midi.h"
|
#include "../plat_midi.h"
|
||||||
|
|
||||||
|
|
||||||
int midi_id = 0;
|
typedef struct
|
||||||
HANDLE m_event;
|
|
||||||
|
|
||||||
static HMIDIOUT midi_out_device = NULL;
|
|
||||||
static uint8_t midi_rt_buf[1024];
|
|
||||||
static uint8_t midi_cmd_buf[1024];
|
|
||||||
static int midi_cmd_pos = 0;
|
|
||||||
static int midi_cmd_len = 0;
|
|
||||||
static uint8_t midi_status = 0;
|
|
||||||
static unsigned int midi_sysex_start = 0;
|
|
||||||
static unsigned int midi_sysex_delay = 0;
|
|
||||||
|
|
||||||
void plat_midi_init()
|
|
||||||
{
|
{
|
||||||
/* This is for compatibility with old configuration files. */
|
int midi_id;
|
||||||
midi_id = config_get_int("Sound", "midi_host_device", -1);
|
|
||||||
if (midi_id == -1)
|
|
||||||
{
|
|
||||||
midi_id = config_get_int(SYSTEM_MIDI_NAME, "midi", 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
config_delete_var("Sound", "midi_host_device");
|
|
||||||
config_set_int(SYSTEM_MIDI_NAME, "midi", midi_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
MMRESULT hr = MMSYSERR_NOERROR;
|
HANDLE m_event;
|
||||||
|
|
||||||
memset(midi_rt_buf, 0, sizeof(midi_rt_buf));
|
HMIDIOUT midi_out_device;
|
||||||
memset(midi_cmd_buf, 0, sizeof(midi_cmd_buf));
|
|
||||||
|
|
||||||
midi_cmd_pos = midi_cmd_len = 0;
|
MIDIHDR m_hdr;
|
||||||
midi_status = 0;
|
} plat_midi_t;
|
||||||
|
|
||||||
midi_sysex_start = midi_sysex_delay = 0;
|
plat_midi_t *pm = NULL;
|
||||||
|
|
||||||
m_event = CreateEvent(NULL, TRUE, TRUE, NULL);
|
|
||||||
|
|
||||||
hr = midiOutOpen(&midi_out_device, midi_id, (uintptr_t) m_event,
|
void
|
||||||
0, CALLBACK_EVENT);
|
plat_midi_init(void)
|
||||||
if (hr != MMSYSERR_NOERROR) {
|
|
||||||
printf("midiOutOpen error - %08X\n",hr);
|
|
||||||
midi_id = 0;
|
|
||||||
hr = midiOutOpen(&midi_out_device, midi_id, (uintptr_t) m_event,
|
|
||||||
0, CALLBACK_EVENT);
|
|
||||||
if (hr != MMSYSERR_NOERROR) {
|
|
||||||
printf("midiOutOpen error - %08X\n",hr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
midiOutReset(midi_out_device);
|
|
||||||
}
|
|
||||||
|
|
||||||
void plat_midi_close()
|
|
||||||
{
|
{
|
||||||
if (midi_out_device != NULL)
|
MMRESULT hr;
|
||||||
{
|
|
||||||
midiOutReset(midi_out_device);
|
|
||||||
midiOutClose(midi_out_device);
|
|
||||||
/* midi_out_device = NULL; */
|
|
||||||
CloseHandle(m_event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int plat_midi_get_num_devs()
|
pm = (plat_midi_t *) malloc(sizeof(plat_midi_t));
|
||||||
{
|
memset(pm, 0, sizeof(plat_midi_t));
|
||||||
return midiOutGetNumDevs();
|
|
||||||
}
|
|
||||||
void plat_midi_get_dev_name(int num, char *s)
|
|
||||||
{
|
|
||||||
MIDIOUTCAPS caps;
|
|
||||||
|
|
||||||
midiOutGetDevCaps(num, &caps, sizeof(caps));
|
pm->midi_id = config_get_int(SYSTEM_MIDI_NAME, "midi", 0);
|
||||||
strcpy(s, caps.szPname);
|
|
||||||
}
|
|
||||||
|
|
||||||
void plat_midi_play_msg(uint8_t *msg)
|
hr = MMSYSERR_NOERROR;
|
||||||
{
|
|
||||||
midiOutShortMsg(midi_out_device, *(uint32_t *) msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
MIDIHDR m_hdr;
|
pm->m_event = CreateEvent(NULL, TRUE, TRUE, NULL);
|
||||||
|
|
||||||
void plat_midi_play_sysex(uint8_t *sysex, unsigned int len)
|
hr = midiOutOpen(&pm->midi_out_device, pm->midi_id,
|
||||||
{
|
(uintptr_t) pm->m_event, 0, CALLBACK_EVENT);
|
||||||
MMRESULT result;
|
if (hr != MMSYSERR_NOERROR) {
|
||||||
|
printf("midiOutOpen error - %08X\n", hr);
|
||||||
if (WaitForSingleObject(m_event, 2000) == WAIT_TIMEOUT)
|
pm->midi_id = 0;
|
||||||
return;
|
hr = midiOutOpen(&pm->midi_out_device, pm->midi_id,
|
||||||
|
(uintptr_t) pm->m_event, 0, CALLBACK_EVENT);
|
||||||
midiOutUnprepareHeader(midi_out_device, &m_hdr, sizeof(m_hdr));
|
if (hr != MMSYSERR_NOERROR) {
|
||||||
|
printf("midiOutOpen error - %08X\n", hr);
|
||||||
m_hdr.lpData = (char *) sysex;
|
|
||||||
m_hdr.dwBufferLength = len;
|
|
||||||
m_hdr.dwBytesRecorded = len;
|
|
||||||
m_hdr.dwUser = 0;
|
|
||||||
|
|
||||||
result = midiOutPrepareHeader(midi_out_device, &m_hdr, sizeof(m_hdr));
|
|
||||||
|
|
||||||
if (result != MMSYSERR_NOERROR) return;
|
|
||||||
ResetEvent(m_event);
|
|
||||||
result = midiOutLongMsg(midi_out_device, &m_hdr, sizeof(m_hdr));
|
|
||||||
if (result != MMSYSERR_NOERROR)
|
|
||||||
{
|
|
||||||
SetEvent(m_event);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
midiOutReset(pm->midi_out_device);
|
||||||
}
|
}
|
||||||
|
|
||||||
int plat_midi_write(uint8_t val)
|
|
||||||
|
void
|
||||||
|
plat_midi_close(void)
|
||||||
{
|
{
|
||||||
return 0;
|
if (pm) {
|
||||||
|
if (pm->midi_out_device != NULL) {
|
||||||
|
midiOutReset(pm->midi_out_device);
|
||||||
|
midiOutClose(pm->midi_out_device);
|
||||||
|
CloseHandle(pm->m_event);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(pm);
|
||||||
|
pm = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
plat_midi_get_num_devs(void)
|
||||||
|
{
|
||||||
|
return midiOutGetNumDevs();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
plat_midi_get_dev_name(int num, char *s)
|
||||||
|
{
|
||||||
|
MIDIOUTCAPS caps;
|
||||||
|
|
||||||
|
midiOutGetDevCaps(num, &caps, sizeof(caps));
|
||||||
|
strcpy(s, caps.szPname);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
plat_midi_play_msg(uint8_t *msg)
|
||||||
|
{
|
||||||
|
if (!pm)
|
||||||
|
return;
|
||||||
|
|
||||||
|
midiOutShortMsg(pm->midi_out_device, *(uint32_t *) msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
plat_midi_play_sysex(uint8_t *sysex, unsigned int len)
|
||||||
|
{
|
||||||
|
MMRESULT result;
|
||||||
|
|
||||||
|
if (!pm)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (WaitForSingleObject(pm->m_event, 2000) == WAIT_TIMEOUT)
|
||||||
|
return;
|
||||||
|
|
||||||
|
midiOutUnprepareHeader(pm->midi_out_device, &pm->m_hdr, sizeof(pm->m_hdr));
|
||||||
|
|
||||||
|
pm->m_hdr.lpData = (char *) sysex;
|
||||||
|
pm->m_hdr.dwBufferLength = len;
|
||||||
|
pm->m_hdr.dwBytesRecorded = len;
|
||||||
|
pm->m_hdr.dwUser = 0;
|
||||||
|
|
||||||
|
result = midiOutPrepareHeader(pm->midi_out_device, &pm->m_hdr, sizeof(pm->m_hdr));
|
||||||
|
|
||||||
|
if (result != MMSYSERR_NOERROR)
|
||||||
|
return;
|
||||||
|
ResetEvent(pm->m_event);
|
||||||
|
result = midiOutLongMsg(pm->midi_out_device, &pm->m_hdr, sizeof(pm->m_hdr));
|
||||||
|
if (result != MMSYSERR_NOERROR) {
|
||||||
|
SetEvent(pm->m_event);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
plat_midi_write(uint8_t val)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
* Windows 86Box Settings dialog handler.
|
* Windows 86Box Settings dialog handler.
|
||||||
*
|
*
|
||||||
* Version: @(#)win_settings.c 1.0.57 2018/09/06
|
* Version: @(#)win_settings.c 1.0.58 2018/09/11
|
||||||
*
|
*
|
||||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||||
* David Hrdlička, <hrdlickadavid@outlook.com>
|
* David Hrdlička, <hrdlickadavid@outlook.com>
|
||||||
@@ -1092,13 +1092,15 @@ win_settings_input_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|||||||
static int
|
static int
|
||||||
mpu401_present(void)
|
mpu401_present(void)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
char *n;
|
char *n;
|
||||||
|
|
||||||
n = sound_card_get_internal_name(temp_sound_card);
|
n = sound_card_get_internal_name(temp_sound_card);
|
||||||
if (n != NULL) {
|
if (n != NULL) {
|
||||||
if (!strcmp(n, "sb16") || !strcmp(n, "sbawe32") || !strcmp(n, "replysb16"))
|
if (!strcmp(n, "sb16") || !strcmp(n, "sbawe32"))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return temp_mpu401 ? 1 : 0;
|
return temp_mpu401 ? 1 : 0;
|
||||||
}
|
}
|
||||||
@@ -1107,14 +1109,22 @@ mpu401_present(void)
|
|||||||
int
|
int
|
||||||
mpu401_standalone_allow(void)
|
mpu401_standalone_allow(void)
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
char *n, *md;
|
char *n, *md;
|
||||||
|
#else
|
||||||
|
char *md;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
n = sound_card_get_internal_name(temp_sound_card);
|
n = sound_card_get_internal_name(temp_sound_card);
|
||||||
|
#endif
|
||||||
md = midi_device_get_internal_name(temp_midi_device);
|
md = midi_device_get_internal_name(temp_midi_device);
|
||||||
|
#if 0
|
||||||
if (n != NULL) {
|
if (n != NULL) {
|
||||||
if (!strcmp(n, "sb16") || !strcmp(n, "sbawe32") || !strcmp(n, "replysb16"))
|
if (!strcmp(n, "sb16") || !strcmp(n, "sbawe32"))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (md != NULL) {
|
if (md != NULL) {
|
||||||
if (!strcmp(md, "none"))
|
if (!strcmp(md, "none"))
|
||||||
@@ -1294,22 +1304,10 @@ win_settings_sound_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case IDC_CONFIGURE_MPU401:
|
case IDC_CONFIGURE_MPU401:
|
||||||
{
|
mca_version = !!(machines[temp_machine].flags & MACHINE_MCA);
|
||||||
char *n;
|
|
||||||
|
|
||||||
n = sound_card_get_internal_name(sound_card_current);
|
|
||||||
|
|
||||||
if (n != NULL)
|
|
||||||
{
|
|
||||||
if (!strcmp(n, "ncraudio"))
|
|
||||||
mca_version = 1;
|
|
||||||
else
|
|
||||||
mca_version = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
temp_deviceconfig |= deviceconfig_open(hdlg, mca_version ? (void *)&mpu401_mca_device : (void *)&mpu401_device);
|
temp_deviceconfig |= deviceconfig_open(hdlg, mca_version ? (void *)&mpu401_mca_device : (void *)&mpu401_device);
|
||||||
}
|
break;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user