Merge branch 'master' into audio

This commit is contained in:
Jasmine Iwanek
2022-01-26 19:59:37 -05:00
25 changed files with 1583 additions and 215 deletions

View File

@@ -9,9 +9,11 @@
#include <86box/dma.h>
#include <86box/pic.h>
#include <86box/device.h>
#include <86box/gameport.h>
#include <86box/nvr.h>
#include <86box/sound.h>
#include <86box/filters.h>
#include <86box/midi.h>
#include <86box/snd_opl.h>
#include <86box/snd_ym7128.h>
@@ -38,6 +40,10 @@ typedef struct adgold_t
int adgold_mma_intpos[2];
pc_timer_t adgold_mma_timer_count;
uint8_t adgold_midi_ctrl, midi_queue[16];
int midi_r, midi_w;
int uart_in, uart_out, sysex;
struct
{
@@ -54,6 +60,7 @@ typedef struct adgold_t
int fm_vol_l, fm_vol_r;
int samp_vol_l, samp_vol_r;
int aux_vol_l, aux_vol_r;
int vol_l, vol_r;
int treble, bass;
@@ -61,7 +68,9 @@ typedef struct adgold_t
int16_t mma_buffer[2][SOUNDBUFLEN];
int pos;
int gameport_enabled;
int surround_enabled;
} adgold_t;
@@ -134,12 +143,17 @@ void adgold_update_irq_status(adgold_t *adgold)
uint8_t temp = 0xf;
if (!(adgold->adgold_mma_regs[0][8] & 0x10) && (adgold->adgold_mma_status & 0x10)) /*Timer 0*/
temp &= ~2;
temp &= ~2;
if (!(adgold->adgold_mma_regs[0][8] & 0x20) && (adgold->adgold_mma_status & 0x20)) /*Timer 1*/
temp &= ~2;
temp &= ~2;
if (!(adgold->adgold_mma_regs[0][8] & 0x40) && (adgold->adgold_mma_status & 0x40)) /*Timer 2*/
temp &= ~2;
temp &= ~2;
if (!(adgold->adgold_mma_regs[0][0xd] & 0x01) && (adgold->adgold_mma_status & 0x04))
temp &= ~2;
if (!(adgold->adgold_mma_regs[0][0xd] & 0x04) && (adgold->adgold_mma_status & 0x08))
temp &= ~2;
if (!(adgold->adgold_mma_regs[0][0xd] & 0x10) && (adgold->adgold_mma_status & 0x80))
temp &= ~2;
if ((adgold->adgold_mma_status & 0x01) && !(adgold->adgold_mma_regs[0][0xc] & 2))
temp &= ~2;
if ((adgold->adgold_mma_status & 0x02) && !(adgold->adgold_mma_regs[1][0xc] & 2))
@@ -249,11 +263,19 @@ void adgold_write(uint16_t addr, uint8_t val, void *p)
adgold->adgold_38x_regs[0x0c] = val;
adgold->samp_vol_r = (int)(int8_t)(val - 128);
break;
case 0x0d: /*Aux volume left*/
adgold->adgold_38x_regs[0x0d] = val;
adgold->aux_vol_l = (int)(int8_t)(val - 128);
break;
case 0x0e: /*Aux volume right*/
adgold->adgold_38x_regs[0x0e] = val;
adgold->aux_vol_r = (int)(int8_t)(val - 128);
break;
case 0x18: /*Surround*/
adgold->adgold_38x_regs[0x18] = val;
ym7128_write(&adgold->ym7128, val);
break;
break;
default:
adgold->adgold_38x_regs[adgold->adgold_38x_addr] = val;
@@ -380,6 +402,45 @@ void adgold_write(uint16_t addr, uint8_t val, void *p)
case 0xc:
adgold->adgold_mma_intpos[0] = (7 - ((val >> 2) & 7)) * 8;
break;
case 0xd:
adgold->adgold_midi_ctrl = val & 0x3f;
if ((adgold->adgold_midi_ctrl & 0x0f) != 0x0f) {
if ((adgold->adgold_midi_ctrl & 0x0f) == 0x00) {
adgold->uart_out = 0;
adgold->uart_in = 0;
adgold->midi_w = 0;
adgold->midi_r = 0;
adgold->adgold_mma_status &= ~0x8c;
} else {
if (adgold->adgold_midi_ctrl & 0x01)
adgold->uart_in = 1;
if (adgold->adgold_midi_ctrl & 0x04)
adgold->uart_out = 1;
if (adgold->adgold_midi_ctrl & 0x02) {
adgold->uart_in = 0;
adgold->midi_w = 0;
adgold->midi_r = 0;
}
if (adgold->adgold_midi_ctrl & 0x08)
adgold->uart_out = 0;
adgold->adgold_mma_status &= ~0x80;
}
} else
adgold->adgold_mma_status &= ~0x8c;
adgold_update_irq_status(adgold);
break;
case 0xe:
if (adgold->uart_out) {
midi_raw_out_byte(val);
adgold->adgold_mma_status &= ~0x08;
adgold_update_irq_status(adgold);
}
break;
}
adgold->adgold_mma_regs[0][adgold->adgold_mma_addr] = val;
break;
@@ -467,9 +528,9 @@ uint8_t adgold_read(uint16_t addr, void *p)
{
case 0x00: /*Control/ID*/
if (adgold->surround_enabled)
temp = 0x50; /*16-bit ISA, surround module, no telephone/CDROM*/
temp = 0x51; /*8-bit ISA, surround module, no telephone/CD-ROM*/
else
temp = 0x70; /*16-bit ISA, no telephone/surround/CD-ROM*/
temp = 0x71; /*8-bit ISA, no telephone/surround/CD-ROM*/
break;
default:
@@ -482,7 +543,7 @@ uint8_t adgold_read(uint16_t addr, void *p)
case 4: case 6:
temp = adgold->adgold_mma_status;
adgold->adgold_mma_status = 0; /*JUKEGOLD expects timer status flags to auto-clear*/
adgold->adgold_mma_status &= ~0xf3; /*JUKEGOLD expects timer status flags to auto-clear*/
adgold_update_irq_status(adgold);
break;
case 5:
@@ -491,12 +552,26 @@ uint8_t adgold_read(uint16_t addr, void *p)
{
case 6: /*Timer 2 low*/
adgold->adgold_mma.timer2_read = adgold->adgold_mma.timer2_count;
adgold->adgold_mma_status |= 0x40;
temp = adgold->adgold_mma.timer2_read & 0xff;
break;
case 7: /*Timer 2 high*/
temp = adgold->adgold_mma.timer2_read >> 8;
break;
case 0xe:
temp = 0;
if (adgold->uart_in) {
temp = adgold->midi_queue[adgold->midi_r];
if (adgold->midi_r != adgold->midi_w) {
adgold->midi_r++;
adgold->midi_r &= 0x0f;
}
adgold->adgold_mma_status &= ~0x04;
adgold_update_irq_status(adgold);
}
break;
default:
temp = adgold->adgold_mma_regs[0][adgold->adgold_mma_addr];
break;
@@ -579,6 +654,17 @@ void adgold_timer_poll(void *p)
adgold_t *adgold = (adgold_t *)p;
timer_advance_u64(&adgold->adgold_mma_timer_count, (uint64_t)((double)TIMER_USEC * 1.88964));
if (adgold->adgold_midi_ctrl & 0x3f) {
if ((adgold->adgold_midi_ctrl & 0x3f) != 0x3f) {
if (adgold->uart_out)
adgold->adgold_mma_status |= 0x08;
if (adgold->adgold_midi_ctrl & 0x10)
adgold->adgold_mma_status |= 0x80;
}
adgold_update_irq_status(adgold);
}
if (adgold->adgold_mma_regs[0][8] & 0x01) /*Timer 0*/
{
adgold->adgold_mma.timer0_count--;
@@ -752,6 +838,59 @@ static void adgold_get_buffer(int32_t *buffer, int len, void *p)
free(adgold_buffer);
}
static void
adgold_filter_cd_audio(int channel, double *buffer, void *p)
{
adgold_t *adgold = (adgold_t *)p;
double c;
int aux = channel ? adgold->aux_vol_r : adgold->aux_vol_l;
int vol = channel ? adgold->vol_r : adgold->vol_l;
c = ((((*buffer) * aux) / 4096.0) * vol) / 4096.0;
*buffer = c;
}
static void adgold_input_msg(void *p, uint8_t *msg, uint32_t len)
{
adgold_t *adgold = (adgold_t *)p;
uint8_t i;
if (adgold->sysex)
return;
if (adgold->uart_in) {
adgold->adgold_mma_status |= 0x04;
for (i=0; i < len; i++) {
adgold->midi_queue[adgold->midi_w++] = msg[i];
adgold->midi_w &= 0x0f;
}
adgold_update_irq_status(adgold);
}
}
static int adgold_input_sysex(void *p, uint8_t *buffer, uint32_t len, int abort)
{
adgold_t *adgold = (adgold_t *)p;
uint32_t i;
if (abort) {
adgold->sysex = 0;
return 0;
}
adgold->sysex = 1;
for (i=0;i<len;i++) {
if (adgold->midi_r == adgold->midi_w)
return (len-i);
adgold->midi_queue[adgold->midi_w++] = buffer[i];
adgold->midi_w &= 0x0f;
}
adgold->sysex = 0;
return 0;
}
void *adgold_init(const device_t *info)
{
@@ -762,6 +901,8 @@ void *adgold_init(const device_t *info)
memset(adgold, 0, sizeof(adgold_t));
adgold->surround_enabled = device_get_config_int("surround");
adgold->gameport_enabled = device_get_config_int("gameport");
opl3_init(&adgold->opl);
if (adgold->surround_enabled)
@@ -798,6 +939,8 @@ void *adgold_init(const device_t *info)
adgold->fm_vol_r = (int)(int8_t)(adgold->adgold_eeprom[0x0a] - 128);
adgold->samp_vol_l = (int)(int8_t)(adgold->adgold_eeprom[0x0b] - 128);
adgold->samp_vol_r = (int)(int8_t)(adgold->adgold_eeprom[0x0c] - 128);
adgold->aux_vol_l = (int)(int8_t)(adgold->adgold_eeprom[0x0d] - 128);
adgold->aux_vol_r = (int)(int8_t)(adgold->adgold_eeprom[0x0e] - 128);
adgold->adgold_mma_enable[0] = 0;
adgold->adgold_mma_fifo_start[0] = adgold->adgold_mma_fifo_end[0] = 0;
@@ -805,10 +948,17 @@ void *adgold_init(const device_t *info)
/*388/389 are handled by adlib_init*/
io_sethandler(0x0388, 0x0008, adgold_read, NULL, NULL, adgold_write, NULL, NULL, adgold);
if (adgold->gameport_enabled)
gameport_remap(gameport_add(&gameport_201_device), 0x201);
timer_add(&adgold->adgold_mma_timer_count, adgold_timer_poll, adgold, 1);
sound_add_handler(adgold_get_buffer, adgold);
sound_set_cd_audio_filter(adgold_filter_cd_audio, adgold);
if (device_get_config_int("receive_input"))
midi_in_handler(1, adgold_input_msg, adgold_input_sysex, adgold);
return adgold;
}
@@ -829,9 +979,15 @@ void adgold_close(void *p)
static const device_config_t adgold_config[] =
{
{
"gameport", "Enable Game port", CONFIG_BINARY, "", 1
},
{
"surround", "Surround module", CONFIG_BINARY, "", 1
},
{
"receive_input", "Receive input (MIDI)", CONFIG_BINARY, "", 1
},
{
"", "", -1
}

View File

@@ -67,9 +67,10 @@ typedef struct {
uint32_t sr_cir;
uint16_t sr_ram[128];
uint8_t uart_ctrl, uart_status,
uart_res;
uint32_t uart_fifo;
uint8_t uart_data, uart_ctrl,
uart_status, uart_res;
uint32_t uart_fifo[8];
uint8_t read_fifo_pos, write_fifo_pos;
ac97_codec_t * codec;
uint32_t codec_ctrl;
@@ -165,6 +166,8 @@ typedef struct {
#define UART_STATUS_TXRDY (1<<1)
#define UART_STATUS_RXRDY (1<<0)
#define UART_FIFO_BYTE_VALID 0x00000100
#define FORMAT_MONO_8 0
#define FORMAT_STEREO_8 1
#define FORMAT_MONO_16 2
@@ -174,7 +177,6 @@ typedef struct {
static void es1371_fetch(es1371_t *dev, int dac_nr);
static void update_legacy(es1371_t *dev, uint32_t old_legacy_ctrl);
#ifdef ENABLE_AUDIOPCI_LOG
int audiopci_do_log = ENABLE_AUDIOPCI_LOG;
@@ -205,10 +207,12 @@ es1371_update_irqs(es1371_t *dev)
if ((dev->int_status & INT_STATUS_DAC2) && (dev->si_cr & SI_P2_INTR_EN))
irq = 1;
/* MIDI input is unsupported for now */
if ((dev->int_status & INT_STATUS_UART) && (dev->uart_status & UART_STATUS_TXINT) &&
((dev->uart_ctrl & UART_CTRL_TXINTEN) != 0x20))
dev->int_status &= ~INT_STATUS_UART;
if ((dev->uart_status & UART_STATUS_TXINT) || (dev->uart_status & UART_STATUS_RXINT)) {
dev->int_status |= INT_STATUS_UART;
irq = 1;
}
if (irq)
dev->int_status |= INT_STATUS_INTR;
@@ -225,10 +229,96 @@ es1371_update_irqs(es1371_t *dev)
}
static void
es1371_update_tx_irq(es1371_t *dev)
{
dev->uart_status &= ~UART_STATUS_TXINT;
if (((dev->uart_ctrl & UART_CTRL_TXINTEN) == 0x20) && (dev->uart_status & UART_STATUS_TXRDY))
dev->uart_status |= UART_STATUS_TXINT;
es1371_update_irqs(dev);
}
static void
es1371_set_tx_irq(es1371_t *dev, int set)
{
dev->uart_status &= ~UART_STATUS_TXRDY;
if (set)
dev->uart_status |= UART_STATUS_TXRDY;
es1371_update_tx_irq(dev);
}
static void
es1371_update_rx_irq(es1371_t *dev)
{
dev->uart_status &= ~UART_STATUS_RXINT;
if ((dev->uart_ctrl & UART_CTRL_RXINTEN) && (dev->uart_status & UART_STATUS_RXRDY))
dev->uart_status |= UART_STATUS_RXINT;
es1371_update_irqs(dev);
}
static void
es1371_set_rx_irq(es1371_t *dev, int set)
{
dev->uart_status &= ~UART_STATUS_RXRDY;
if (set)
dev->uart_status |= UART_STATUS_RXRDY;
es1371_update_rx_irq(dev);
}
static void
es1371_scan_fifo(es1371_t *dev)
{
if (dev->read_fifo_pos != dev->write_fifo_pos) {
dev->uart_data = dev->uart_fifo[dev->read_fifo_pos];
dev->read_fifo_pos = (dev->read_fifo_pos + 1) & 7;
es1371_set_rx_irq(dev, 1);
} else
es1371_set_rx_irq(dev, 0);
}
static void
es1371_write_fifo(es1371_t *dev, uint8_t val)
{
if (dev->write_fifo_pos < 8) {
dev->uart_fifo[dev->write_fifo_pos] = val | UART_FIFO_BYTE_VALID;
dev->write_fifo_pos = (dev->write_fifo_pos + 1) & 7;
}
}
static void
es1371_reset_fifo(es1371_t *dev)
{
int i;
for (i = 0; i < 8; i++)
dev->uart_fifo[i] = 0x00000000;
dev->read_fifo_pos = dev->write_fifo_pos = 0;
es1371_set_rx_irq(dev, 0);
}
static void
es1371_reset(void *p)
{
es1371_t *dev = (es1371_t *) p;
int i;
nmi = 0;
@@ -316,7 +406,14 @@ es1371_reset(void *p)
/* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b
Addressable as longword only */
dev->uart_fifo = 0xfffffe00;
for (i = 0; i < 8; i++)
dev->uart_fifo[i] = 0xffff0000;
/* Reset the UART TX. */
es1371_set_tx_irq(dev, 0);
/* Reset the UART (RX) FIFO. */
es1371_reset_fifo(dev);
/* Update interrupts to ensure they're all correctly cleared. */
es1371_update_irqs(dev);
@@ -344,7 +441,10 @@ es1371_read_frame_reg(es1371_t *dev, int frame, int page)
/* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b
Addressable as longword only */
case 0xe: case 0xf:
ret = dev->uart_fifo;
audiopci_log("[30:%02X] ret = dev->uart_fifo[%02X] = %08X\n", page,
((page & 0x01) << 2) + ((frame >> 2) & 0x03),
dev->uart_fifo[((page & 0x01) << 2) + ((frame >> 2) & 0x03)]);
ret = dev->uart_fifo[((page & 0x01) << 2) + ((frame >> 2) & 0x03)];
break;
}
break;
@@ -363,7 +463,10 @@ es1371_read_frame_reg(es1371_t *dev, int frame, int page)
/* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b
Addressable as longword only */
case 0xe: case 0xf:
ret = dev->uart_fifo;
audiopci_log("[34:%02X] ret = dev->uart_fifo[%02X] = %08X\n", page,
((page & 0x01) << 2) + ((frame >> 2) & 0x03),
dev->uart_fifo[((page & 0x01) << 2) + ((frame >> 2) & 0x03)]);
ret = dev->uart_fifo[((page & 0x01) << 2) + ((frame >> 2) & 0x03)];
break;
}
break;
@@ -377,7 +480,10 @@ es1371_read_frame_reg(es1371_t *dev, int frame, int page)
/* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b
Addressable as longword only */
case 0xe: case 0xf:
ret = dev->uart_fifo;
audiopci_log("[38:%02X] ret = dev->uart_fifo[%02X] = %08X\n", page,
((page & 0x01) << 2) + ((frame >> 2) & 0x03),
dev->uart_fifo[((page & 0x01) << 2) + ((frame >> 2) & 0x03)]);
ret = dev->uart_fifo[((page & 0x01) << 2) + ((frame >> 2) & 0x03)];
break;
}
break;
@@ -391,12 +497,19 @@ es1371_read_frame_reg(es1371_t *dev, int frame, int page)
/* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b
Addressable as longword only */
case 0xe: case 0xf:
ret = dev->uart_fifo;
audiopci_log("[3C:%02X] ret = dev->uart_fifo[%02X] = %08X\n", page,
((page & 0x01) << 2) + ((frame >> 2) & 0x03),
dev->uart_fifo[((page & 0x01) << 2) + ((frame >> 2) & 0x03)]);
ret = dev->uart_fifo[((page & 0x01) << 2) + ((frame >> 2) & 0x03)];
break;
}
break;
}
if (page == 0x0e || page == 0x0f) {
audiopci_log("Read frame = %02x, page = %02x, uart fifo valid = %02x, temp = %03x\n", frame, page, dev->valid, ret);
}
return ret;
}
@@ -420,7 +533,9 @@ es1371_write_frame_reg(es1371_t *dev, int frame, int page, uint32_t val)
/* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b
Addressable as longword only */
case 0xe: case 0xf:
dev->uart_fifo = (dev->uart_fifo & 0xfffffe00) | (val & 0x000001ff);
audiopci_log("[30:%02X] dev->uart_fifo[%02X] = %08X\n", page,
((page & 0x01) << 2) + ((frame >> 2) & 0x03), val);
dev->uart_fifo[((page & 0x01) << 2) + ((frame >> 2) & 0x03)] = val;
break;
}
break;
@@ -441,7 +556,9 @@ es1371_write_frame_reg(es1371_t *dev, int frame, int page, uint32_t val)
/* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b
Addressable as longword only */
case 0xe: case 0xf:
dev->uart_fifo = (dev->uart_fifo & 0xfffffe00) | (val & 0x000001ff);
audiopci_log("[34:%02X] dev->uart_fifo[%02X] = %08X\n", page,
((page & 0x01) << 2) + ((frame >> 2) & 0x03), val);
dev->uart_fifo[((page & 0x01) << 2) + ((frame >> 2) & 0x03)] = val;
break;
}
break;
@@ -455,7 +572,9 @@ es1371_write_frame_reg(es1371_t *dev, int frame, int page, uint32_t val)
/* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b
Addressable as longword only */
case 0xe: case 0xf:
dev->uart_fifo = (dev->uart_fifo & 0xfffffe00) | (val & 0x000001ff);
audiopci_log("[38:%02X] dev->uart_fifo[%02X] = %08X\n", page,
((page & 0x01) << 2) + ((frame >> 2) & 0x03), val);
dev->uart_fifo[((page & 0x01) << 2) + ((frame >> 2) & 0x03)] = val;
break;
}
break;
@@ -470,11 +589,17 @@ es1371_write_frame_reg(es1371_t *dev, int frame, int page, uint32_t val)
/* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b
Addressable as longword only */
case 0xe: case 0xf:
dev->uart_fifo = (dev->uart_fifo & 0xfffffe00) | (val & 0x000001ff);
audiopci_log("[3C:%02X] dev->uart_fifo[%02X] = %08X\n", page,
((page & 0x01) << 2) + ((frame >> 2) & 0x03), val);
dev->uart_fifo[((page & 0x01) << 2) + ((frame >> 2) & 0x03)] = val;
break;
}
break;
}
if (page == 0x0e || page == 0x0f) {
audiopci_log("Write frame = %02x, page = %02x, uart fifo = %08x, val = %02x\n", frame, page, dev->uart_fifo, val);
}
}
@@ -505,21 +630,27 @@ es1371_inb(uint16_t port, void *p)
must be for a reason */
case 0x04:
ret = dev->int_status & 0xff;
audiopci_log("[R] STATUS 0- 7 = %02X\n", ret);
break;
case 0x05:
ret = (dev->int_status >> 8) & 0xff;
audiopci_log("[R] STATUS 8-15 = %02X\n", ret);
break;
case 0x06:
ret = (dev->int_status >> 16) & 0x0f;
audiopci_log("[R] STATUS 16-23 = %02X\n", ret);
break;
case 0x07:
ret = ((dev->int_status >> 24) & 0x03) | 0xfc;
audiopci_log("[R] STATUS 24-31 = %02X\n", ret);
break;
/* UART Data Register, Address 08H
Addressable as byte only */
case 0x08:
ret = 0x00;
ret = dev->uart_data;
es1371_set_rx_irq(dev, 0);
audiopci_log("[R] UART DATA = %02X\n", ret);
break;
/* UART Status Register, Address 09H
@@ -533,6 +664,7 @@ es1371_inb(uint16_t port, void *p)
Addressable as byte only */
case 0x0a:
ret = dev->uart_res & 0x01;
audiopci_log("[R] UART RES = %02X\n", ret);
break;
/* Memory Page Register, Address 0CH
@@ -661,6 +793,8 @@ es1371_inw(uint16_t port, void *p)
break;
}
audiopci_log("es1371_inw: port=%04x ret=%04x\n", port, ret);
return ret;
}
@@ -682,6 +816,7 @@ es1371_inl(uint16_t port, void *p)
Addressable as longword only */
case 0x04:
ret = dev->int_status;
audiopci_log("[R] STATUS = %08X\n", ret);
break;
/* Memory Page Register, Address 0CH
@@ -783,22 +918,36 @@ es1371_outb(uint16_t port, uint8_t val, void *p)
/* UART Data Register, Address 08H
Addressable as byte only */
case 0x08:
audiopci_log("MIDI data = %02x\n", val);
/* TX does not use FIFO. */
midi_raw_out_byte(val);
es1371_set_tx_irq(dev, 1);
break;
/* UART Control Register, Address 09H
Addressable as byte only */
case 0x09:
audiopci_log("[W] UART CTRL = %02X\n", val);
dev->uart_ctrl = val & 0xe3;
if ((dev->uart_ctrl & UART_CTRL_TXINTEN) != 0x20)
dev->int_status &= ~INT_STATUS_UART;
es1371_update_irqs(dev);
audiopci_log("ES1371 UART Cntrl = %02x\n", dev->uart_ctrl);
if ((val & 0x03) == 0x03) {
/* Reset TX */
es1371_set_tx_irq(dev, 1);
/* Software reset */
es1371_reset_fifo(dev);
} else {
es1371_set_tx_irq(dev, 1);
es1371_update_tx_irq(dev);
es1371_update_rx_irq(dev);
}
break;
/* UART Reserved Register, Address 0AH
Addressable as byte only */
case 0x0a:
audiopci_log("[W] UART RES = %02X\n", val);
dev->uart_res = val & 0x01;
break;
@@ -965,6 +1114,7 @@ es1371_outl(uint16_t port, uint32_t val, void *p)
/* Interrupt/Chip Select Status Register, Address 04H
Addressable as longword only */
case 0x04:
audiopci_log("[W] STATUS = %08X\n", val);
break;
/* Memory Page Register, Address 0CH
@@ -1704,29 +1854,10 @@ es1371_poll(void *p)
timer_advance_u64(&dev->dac[1].timer, dev->dac[1].latch);
es1371_scan_fifo(dev);
es1371_update(dev);
if (dev->int_ctrl & INT_UART_EN) {
//audiopci_log("UART INT Enabled\n");
if (dev->uart_ctrl & UART_CTRL_RXINTEN) {
/* We currently don't implement MIDI Input.
But if anything sets MIDI Input and Output together we'd have to take account
of the MIDI Output case, and disable IRQ's and RX bits when MIDI Input is
enabled as well but not in the MIDI Output portion */
dev->int_status &= ~INT_STATUS_UART;
dev->uart_status |= (UART_STATUS_TXINT | UART_STATUS_TXRDY);
} else if (!(dev->uart_ctrl & UART_CTRL_RXINTEN) && ((dev->uart_ctrl & UART_CTRL_TXINTEN))) {
/* Or enable the UART IRQ and the respective TX bits only when the MIDI Output is
enabled */
dev->int_status |= INT_STATUS_UART;
} else {
dev->uart_status |= (UART_STATUS_TXINT | UART_STATUS_TXRDY);
}
//audiopci_log("UART control = %02x\n", dev->uart_ctrl & (UART_CTRL_RXINTEN | UART_CTRL_TXINTEN));
es1371_update_irqs(dev);
}
if (dev->int_ctrl & INT_DAC1_EN) {
frac = dev->dac[0].ac & 0x7fff;
idx = dev->dac[0].ac >> 15;
@@ -1846,12 +1977,51 @@ generate_es1371_filter(void)
}
static void
es1371_input_msg(void *p, uint8_t *msg, uint32_t len)
{
es1371_t *dev = (es1371_t *)p;
uint8_t i;
for (i = 0; i < len; i++)
es1371_write_fifo(dev, msg[i]);
}
static int
es1371_input_sysex(void *p, uint8_t *buffer, uint32_t len, int abort)
{
es1371_t *dev = (es1371_t *)p;
uint32_t i = -1;
audiopci_log("Abort = %i\n", abort);
if (dev->uart_status & UART_STATUS_RXRDY)
abort = 1;
if (!abort) {
for (i = 0; i < len; i++) {
es1371_write_fifo(dev, buffer[i]);
if (dev->uart_status & UART_STATUS_RXRDY)
break;
}
}
/* The last sent position is in i. Return 7 - i. */
return 7 - i;
}
static void *
es1371_init(const device_t *info)
{
es1371_t *dev = malloc(sizeof(es1371_t));
memset(dev, 0x00, sizeof(es1371_t));
if (device_get_config_int("receive_input"))
midi_in_handler(1, es1371_input_msg, es1371_input_sysex, dev);
sound_add_handler(es1371_get_buffer, dev);
sound_set_cd_audio_filter(es1371_filter_cd_audio, dev);
@@ -1920,7 +2090,11 @@ static const device_config_t es1371_config[] =
}
},
.default_int = AC97_CODEC_CS4297A
}, {
},
{
"receive_input", "Receive input (MIDI)", CONFIG_BINARY, "", 1
},
{
"", "", -1
}
};

View File

@@ -17,6 +17,7 @@
#include <86box/filters.h>
#include <86box/snd_mpu401.h>
#include <86box/snd_opl.h>
#include <86box/snd_sb.h>
#include <86box/snd_sb_dsp.h>
@@ -413,7 +414,7 @@ static void pas16_pit_out(uint16_t port, uint8_t val, void *p)
{
if (!(val & 0x20))
{
if (val & 2) pas16->pit.rl[0] = timer_get_remaining_u64(&pit.timer[0]) / PITCONST;;
if (val & 2) pas16->pit.rl[0] = timer_get_remaining_u64(&pas16->pit.timer[0]) / PITCONST;;
if (val & 4) pas16->pit.rl[1] = pas16->pit.c[1];
if (val & 8) pas16->pit.rl[2] = pas16->pit.c[2];
}
@@ -429,7 +430,7 @@ static void pas16_pit_out(uint16_t port, uint8_t val, void *p)
if (!(pas16->pit.ctrl & 0x30))
{
if (!t)
pas16->pit.rl[t] = timer_get_remaining_u64(&pit.timer[t]) / PITCONST;
pas16->pit.rl[t] = timer_get_remaining_u64(&pas16->pit.timer[t]) / PITCONST;
else
{
pas16->pit.rl[t] = pas16->pit.c[t];
@@ -450,7 +451,7 @@ static void pas16_pit_out(uint16_t port, uint8_t val, void *p)
{
pas16->pit.rm[t] = 3;
if (!t)
pas16->pit.rl[t] = timer_get_remaining_u64(&pit.timer[t]) / PITCONST;
pas16->pit.rl[t] = timer_get_remaining_u64(&pas16->pit.timer[t]) / PITCONST;
else
pas16->pit.rl[t] = pas16->pit.c[t];
}
@@ -519,8 +520,8 @@ static uint8_t pas16_pit_in(uint16_t port, void *p)
pas16->pit.rereadlatch[t] = 0;
if (!t)
{
pas16->pit.rl[t] = timer_get_remaining_u64(&pit.timer[t]) / PITCONST;
if ((timer_get_remaining_u64(&pit.timer[t]) / PITCONST) > 65536)
pas16->pit.rl[t] = timer_get_remaining_u64(&pas16->pit.timer[t]) / PITCONST;
if ((timer_get_remaining_u64(&pas16->pit.timer[t]) / PITCONST) > 65536)
pas16->pit.rl[t] = 0xFFFF;
}
else