11
src/config.c
11
src/config.c
@@ -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
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
#define CONFIG_HEX16 7
|
||||
#define CONFIG_HEX20 8
|
||||
#define CONFIG_MAC 9
|
||||
#define CONFIG_MIDI_IN 10
|
||||
|
||||
|
||||
enum {
|
||||
|
||||
@@ -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);
|
||||
|
||||
173
src/sound/midi.c
173
src/sound/midi.c
@@ -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;
|
||||
}
|
||||
@@ -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
1
src/sound/midi_input.h
Normal file
@@ -0,0 +1 @@
|
||||
extern const device_t midi_input_device;
|
||||
@@ -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
|
||||
};
|
||||
@@ -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];
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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*/
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user