Merge pull request #572 from 86Box/bugfix/gus

Fixed the GUS and added configuration addresses and OPL for the WSS I…
This commit is contained in:
OBattler
2020-01-20 21:41:01 +01:00
committed by GitHub
2 changed files with 90 additions and 105 deletions

View File

@@ -111,8 +111,8 @@ typedef struct gus_t
uint8_t usrr; uint8_t usrr;
} gus_t; } gus_t;
static int gus_gf1_irqs[8] = {0, 2, 5, 3, 7, 11, 12, 15}; static int gus_gf1_irqs[8] = {-1, 2, 5, 3, 7, 11, 12, 15};
static int gus_midi_irqs[8] = {0, 2, 5, 3, 7, 11, 12, 15}; static int gus_midi_irqs[8] = {-1, 2, 5, 3, 7, 11, 12, 15};
static int gus_dmas[8] = {-1, 1, 3, 5, 6, 7, -1, -1}; static int gus_dmas[8] = {-1, 1, 3, 5, 6, 7, -1, -1};
int gusfreqs[]= int gusfreqs[]=
@@ -135,7 +135,7 @@ void pollgusirqs(gus_t *gus)
gus->irqstatus2=0x60|c; gus->irqstatus2=0x60|c;
if (gus->rampirqs[c]) gus->irqstatus2 |= 0x80; if (gus->rampirqs[c]) gus->irqstatus2 |= 0x80;
gus->irqstatus|=0x20; gus->irqstatus|=0x20;
if (gus->irq != 0) if (gus->irq != -1)
picint(1 << gus->irq); picint(1 << gus->irq);
return; return;
} }
@@ -143,16 +143,13 @@ void pollgusirqs(gus_t *gus)
{ {
gus->irqstatus2=0xA0|c; gus->irqstatus2=0xA0|c;
gus->irqstatus|=0x40; gus->irqstatus|=0x40;
if (gus->irq != 0) if (gus->irq != -1)
picint(1 << gus->irq); picint(1 << gus->irq);
return; return;
} }
} }
gus->irqstatus2=0xE0; gus->irqstatus2=0xE0;
if (!gus->irqstatus) { if (!gus->irqstatus && gus->irq != -1) picintc(1 << gus->irq);
if (gus->irq != 0)
picintc(1 << gus->irq);
}
} }
void gus_midi_update_int_status(gus_t *gus) void gus_midi_update_int_status(gus_t *gus)
@@ -174,7 +171,7 @@ void gus_midi_update_int_status(gus_t *gus)
else else
gus->irqstatus &= ~GUS_INT_MIDI_RECEIVE; gus->irqstatus &= ~GUS_INT_MIDI_RECEIVE;
if ((gus->midi_status & MIDI_INT_MASTER) && (gus->irq_midi != 0)) if ((gus->midi_status & MIDI_INT_MASTER) && (gus->irq_midi != -1))
{ {
picint(1 << gus->irq_midi); picint(1 << gus->irq_midi);
} }
@@ -221,6 +218,9 @@ void writegus(uint16_t addr, uint8_t val, void *p)
} else } else
gus->midi_status |= MIDI_INT_TRANSMIT; gus->midi_status |= MIDI_INT_TRANSMIT;
break; break;
case 0x302: /*Voice select*/
gus->voice=val&31;
break;
case 0x303: /*Global select*/ case 0x303: /*Global select*/
gus->global=val; gus->global=val;
break; break;
@@ -463,9 +463,9 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8);
} }
break; break;
case 0x307: /*DRAM access*/ case 0x307: /*DRAM access*/
gus->addr&=0xFFFFF;
if (gus->addr < gus->gus_end_ram) if (gus->addr < gus->gus_end_ram)
gus->ram[gus->addr]=val; gus->ram[gus->addr]=val;
gus->addr&=0xFFFFF;
break; break;
case 0x208: case 0x388: case 0x208: case 0x388:
gus->adcommand = val; gus->adcommand = val;
@@ -480,7 +480,7 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8);
{ {
if (gus->sb_nmi) if (gus->sb_nmi)
nmi = 1; nmi = 1;
else else if (gus->irq != -1)
picint(1 << gus->irq); picint(1 << gus->irq);
} }
} }
@@ -515,68 +515,23 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8);
switch (gus->reg_ctrl & 0x07) switch (gus->reg_ctrl & 0x07)
{ {
case 0: case 0:
if (gus->latch_enable & 0x40) { if (gus->latch_enable & 0x40) {
// GUS SDK: IRQ Control Register gus->irq = gus_gf1_irqs[val & 7];
// 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" if (val & 0x40)
gus->irq_midi = gus->irq; {
else if (gus->irq == -1)
gus->irq_midi = gus_midi_irqs[(val >> 3) & 7]; gus->irq = gus->irq_midi = gus_gf1_irqs[(val >> 3) & 7];
else
gus->irq_midi = gus->irq;
}
else
gus->irq_midi = gus_midi_irqs[(val >> 3) & 7];
gus->sb_nmi = val & 0x80; gus->sb_nmi = val & 0x80;
} else { } else {
// GUS SDK: DMA Control Register gus->dma = gus_dmas[val & 7];
// 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; break;
case 1: case 1:
gus->gp1 = val; gus->gp1 = val;
@@ -599,12 +554,13 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8);
break; break;
case 0x206: case 0x206:
if (gus->sb_ctrl & 0x20) { gus->ad_status |= 0x08;
gus->ad_status |= 0x08; if (gus->sb_ctrl & 0x20)
{
if (gus->sb_nmi) if (gus->sb_nmi)
nmi = 1; nmi = 1;
else if (gus->irq != 0) else if (gus->irq != -1)
picint(1 << gus->irq); picint(1 << gus->irq);
} }
break; break;
case 0x20a: case 0x20a:
@@ -616,7 +572,7 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8);
{ {
if (gus->sb_nmi) if (gus->sb_nmi)
nmi = 1; nmi = 1;
else if (gus->irq != 0) else if (gus->irq != -1)
picint(1 << gus->irq); picint(1 << gus->irq);
} }
/*FALLTHROUGH*/ /*FALLTHROUGH*/
@@ -668,26 +624,22 @@ uint8_t readgus(uint16_t addr, void *p)
break; break;
case 0x200: case 0x200:
val = 0xff; return 0;
break;
case 0x206: /*IRQ status*/ case 0x206: /*IRQ status*/
val = gus->irqstatus & ~0x10; val = gus->irqstatus & ~0x10;
if (gus->ad_status & 0x19) if (gus->ad_status & 0x19)
val |= 0x10; val |= 0x10;
break; return val;
case 0x20F: case 0x20F:
val = 0; return 0;
break;
case 0x302: case 0x302:
val = gus->voice; return gus->voice;
break;
case 0x303: case 0x303:
val = gus->global; return gus->global;
break;
case 0x304: /*Global low*/ case 0x304: /*Global low*/
switch (gus->global) switch (gus->global)
@@ -769,8 +721,7 @@ uint8_t readgus(uint16_t addr, void *p)
} }
break; break;
case 0x306: case 0x706: /*Revision level*/ case 0x306: case 0x706: /*Revision level*/
val = 0xff; return 0xff; /*Pre 3.7 - no mixer*/
break;
case 0x307: /*DRAM access*/ case 0x307: /*DRAM access*/
val=gus->ram[gus->addr]; val=gus->ram[gus->addr];
gus->addr&=0xFFFFF; gus->addr&=0xFFFFF;
@@ -778,7 +729,7 @@ uint8_t readgus(uint16_t addr, void *p)
val = gus->ram[gus->addr]; val = gus->ram[gus->addr];
else else
val = 0; val = 0;
break; return val;
case 0x309: return 0; case 0x309: return 0;
case 0x20b: case 0x20b:
@@ -848,7 +799,7 @@ void gus_poll_timer_1(void *p)
gus->ad_status |= 0x40; gus->ad_status |= 0x40;
if (gus->tctrl&4) if (gus->tctrl&4)
{ {
if (gus->irq != 0) if (gus->irq != -1)
picint(1 << gus->irq); picint(1 << gus->irq);
gus->ad_status |= 0x04; gus->ad_status |= 0x04;
gus->irqstatus |= 0x04; gus->irqstatus |= 0x04;
@@ -859,7 +810,7 @@ void gus_poll_timer_1(void *p)
{ {
gus->irqnext=0; gus->irqnext=0;
gus->irqstatus|=0x80; gus->irqstatus|=0x80;
if (gus->irq != 0) if (gus->irq != -1)
picint(1 << gus->irq); picint(1 << gus->irq);
} }
@@ -880,7 +831,7 @@ void gus_poll_timer_2(void *p)
gus->ad_status |= 0x20; gus->ad_status |= 0x20;
if (gus->tctrl&8) if (gus->tctrl&8)
{ {
if (gus->irq != 0) if (gus->irq != -1)
picint(1 << gus->irq); picint(1 << gus->irq);
gus->ad_status |= 0x02; gus->ad_status |= 0x02;
gus->irqstatus |= 0x08; gus->irqstatus |= 0x08;
@@ -891,7 +842,7 @@ void gus_poll_timer_2(void *p)
{ {
gus->irqnext=0; gus->irqnext=0;
gus->irqstatus|=0x80; gus->irqstatus|=0x80;
if (gus->irq != 0) if (gus->irq != -1)
picint(1 << gus->irq); picint(1 << gus->irq);
} }
} }

View File

@@ -99,18 +99,22 @@ static void wss_get_buffer(int32_t *buffer, int len, void *p)
void *wss_init(const device_t *info) void *wss_init(const device_t *info)
{ {
wss_t *wss = malloc(sizeof(wss_t)); wss_t *wss = malloc(sizeof(wss_t));
memset(wss, 0, sizeof(wss_t)); memset(wss, 0, sizeof(wss_t));
uint16_t addr = device_get_config_hex16("base");
wss->opl_enabled = device_get_config_int("opl");
opl3_init(&wss->opl); opl3_init(&wss->opl);
ad1848_init(&wss->ad1848); ad1848_init(&wss->ad1848);
ad1848_setirq(&wss->ad1848, 7); ad1848_setirq(&wss->ad1848, 7);
ad1848_setdma(&wss->ad1848, 3); ad1848_setdma(&wss->ad1848, 3);
io_sethandler(0x0388, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &wss->opl); if (wss->opl_enabled)
io_sethandler(0x0530, 0x0004, wss_read, NULL, NULL, wss_write, NULL, NULL, wss); io_sethandler(0x0388, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &wss->opl);
io_sethandler(0x0534, 0x0004, ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &wss->ad1848);
io_sethandler(addr, 0x0004, wss_read, NULL, NULL, wss_write, NULL, NULL, wss);
io_sethandler(addr+4, 0x0004, ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &wss->ad1848);
sound_add_handler(wss_get_buffer, wss); sound_add_handler(wss_get_buffer, wss);
@@ -198,15 +202,45 @@ void wss_speed_changed(void *p)
ad1848_speed_changed(&wss->ad1848); ad1848_speed_changed(&wss->ad1848);
} }
static const device_config_t wss_config[] =
{
{
"base", "Address", CONFIG_HEX16, "", 0x530,
{
{
"0x530", 0x530
},
{
"0x604", 0x604
},
{
"0xe80", 0xe80
},
{
"0xf40", 0xf40
},
{
""
}
}
},
{
"opl", "Enable OPL", CONFIG_BINARY, "", 1
},
{
"", "", -1
}
};
const device_t wss_device = const device_t wss_device =
{ {
"Windows Sound System", "Windows Sound System",
DEVICE_ISA, 0, DEVICE_ISA | DEVICE_AT, 0,
wss_init, wss_close, NULL, wss_init, wss_close, NULL,
NULL, NULL,
wss_speed_changed, wss_speed_changed,
NULL, NULL,
NULL wss_config
}; };
const device_t ncr_business_audio_device = const device_t ncr_business_audio_device =