Rebase on upstream midi_in branch

This commit is contained in:
Altheos
2020-01-10 10:49:59 +01:00

View File

@@ -101,8 +101,8 @@ typedef struct gus_t
uint8_t ad_status, ad_data;
uint8_t ad_timer_ctrl;
uint8_t uart_queue[64];
int uart_pos, uart_used;
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;
@@ -111,7 +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_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[]=
@@ -134,21 +135,49 @@ 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);
}
}
void gus_midi_update_int_status(gus_t *gus)
{
gus->midi_status &= ~MIDI_INT_MASTER;
if ((gus->midi_ctrl & MIDI_CTRL_TRANSMIT_MASK) == MIDI_CTRL_TRANSMIT && (gus->midi_status & MIDI_INT_TRANSMIT))
{
gus->midi_status |= MIDI_INT_MASTER;
gus->irqstatus |= GUS_INT_MIDI_TRANSMIT;
}
else
gus->irqstatus &= ~GUS_INT_MIDI_TRANSMIT;
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;
}
else
gus->irqstatus &= ~GUS_INT_MIDI_RECEIVE;
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)
@@ -166,33 +195,30 @@ void writegus(uint16_t addr, uint8_t val, void *p)
switch (port)
{
case 0x300: /*MIDI control*/
gus->uart_out = 1;
if (val == 3 || !val) {
gus->uart_in = 0;
gus->irqstatus &= ~0x03;
gus->uart_used = 0;
return;
}
gus->midi_ctrl = val;
gus->uart_out = 1;
if (val & 0x20) {
gus->irqstatus |= 0x01;
} else {
gus->irqstatus &= ~0x01;
}
if (val & 0x80)
gus->uart_in = 1;
else
gus->uart_in = 0;
if (((gus->midi_ctrl & 3) == 3) || !gus->midi_ctrl) { /*Master reset*/
gus->uart_in = 0;
gus->midi_status = 0;
gus->midi_r = 0;
gus->midi_w = 0;
} else if (gus->midi_ctrl & MIDI_CTRL_TRANSMIT) {
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 0x301: /*MIDI data*/
gus->midi_data = val;
if (gus->uart_out) {
midi_raw_out_byte(val);
picint(1 << gus->irq_midi);
midi_raw_out_byte(val);
}
break;
case 0x302: /*Voice select*/
gus->voice=val&31;
if (gus->latch_enable & 0x20) {
gus->midi_status |= MIDI_INT_RECEIVE;
} else
gus->midi_status |= MIDI_INT_TRANSMIT;
break;
case 0x303: /*Global select*/
gus->global=val;
@@ -453,7 +479,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);
}
}
@@ -513,14 +539,14 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8);
//
// "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 (gus_irqs[val & 7] != -1)
gus->irq = gus_irqs[val & 7];
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_irqs[(val >> 3) & 7];
gus->irq_midi = gus_midi_irqs[(val >> 3) & 7];
gus->sb_nmi = val & 0x80;
} else {
// GUS SDK: DMA Control Register
@@ -576,7 +602,7 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8);
gus->ad_status |= 0x08;
if (gus->sb_nmi)
nmi = 1;
else if (gus->irq != -1)
else if (gus->irq != 0)
picint(1 << gus->irq);
}
break;
@@ -589,7 +615,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 if (gus->irq != 0)
picint(1 << gus->irq);
}
case 0x20d:
@@ -619,23 +645,23 @@ uint8_t readgus(uint16_t addr, void *p)
switch (port)
{
case 0x300: /*MIDI status*/
val = ((gus->irqstatus & 0x03 ? 0x80 : 0) |
(gus->uart_in && gus->uart_used >= 64 ? 0x20:0) |
((gus->uart_used && gus->uart_in) ? 1 : 0) | (gus->uart_out ? 2 : 0));
val = gus->midi_status;
break;
case 0x301: /*MIDI data*/
val = 0;
if (gus->uart_in) {
if (gus->uart_used) {
if (gus->uart_pos >= 64)
gus->uart_pos -= 64;
val = gus->uart_queue[gus->uart_pos];
gus->uart_pos++;
gus->uart_used--;
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;
}
}
if (!gus->uart_used)
gus->irqstatus &= ~0x02;
gus->midi_status &= ~MIDI_INT_RECEIVE;
gus_midi_update_int_status(gus);
}
break;
@@ -819,9 +845,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;
}
}
@@ -830,9 +856,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);
}
void gus_poll_timer_2(void *p)
@@ -849,8 +877,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;
}
@@ -860,8 +888,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);
}
}
@@ -1060,19 +1088,6 @@ static void gus_get_buffer(int32_t *buffer, int len, void *p)
gus->pos = 0;
}
static void gus_queue(gus_t *gus, uint8_t val)
{
int pos;
if (gus->uart_used < 64) {
pos = gus->uart_used + gus->uart_pos;
if (pos >= 64)
pos -= 64;
gus->uart_queue[pos] = val;
gus->uart_used++;
}
}
static void gus_input_msg(void *p, uint8_t *msg)
{
gus_t *gus = (gus_t *)p;
@@ -1082,10 +1097,14 @@ static void gus_input_msg(void *p, uint8_t *msg)
return;
if (gus->uart_in) {
gus->irqstatus |= 0x02;
for (i=0;i<msg[3];i++)
gus_queue(gus, msg[i]);
picint(1 << gus->irq_midi);
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);
}
}
@@ -1095,16 +1114,15 @@ static int gus_input_sysex(void *p, uint8_t *buffer, uint32_t len, int abort)
uint32_t i;
if (abort) {
gus->uart_used = 0;
gus->sysex = 0;
return 0;
}
gus->sysex = 1;
for (i=0;i<len;i++) {
if (gus->uart_used >= 64) {
if (gus->midi_r == gus->midi_w)
return (len-i);
}
gus_queue(gus, buffer[i]);
gus->midi_queue[gus->midi_w++] = buffer[i];
gus->midi_w &= 63;
}
gus->sysex = 0;
return 0;
@@ -1140,12 +1158,13 @@ void *gus_init(const device_t *info)
gus->t1l = gus->t2l = 0xff;
gus->uart_out = 1;
gus->base = device_get_config_hex16("base");
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);