Merge pull request #86 from Altheos/gus

Gus soundcard changes
This commit is contained in:
Fred N. van Kempen
2019-08-13 13:55:39 -04:00
committed by GitHub

View File

@@ -8,7 +8,7 @@
* *
* Implementation of the Gravis UltraSound sound device. * Implementation of the Gravis UltraSound sound device.
* *
* Version: @(#)snd_gus.c 1.0.15 2019/05/17 * Version: @(#)snd_gus.c 1.0.16 2019/08/13
* *
* Authors: Fred N. van Kempen, <decwiz@yahoo.com> * Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com> * Miran Grca, <mgrca8@gmail.com>
@@ -124,6 +124,7 @@ typedef struct {
samp_latch; samp_latch;
uint8_t *ram; uint8_t *ram;
uint32_t gus_end_ram;
int pos; int pos;
int16_t buffer[2][SOUNDBUFLEN]; int16_t buffer[2][SOUNDBUFLEN];
@@ -136,6 +137,7 @@ typedef struct {
int irq, int irq,
dma, dma,
irq_midi; irq_midi;
uint16_t base;
int latch_enable; int latch_enable;
uint8_t sb_2xa, uint8_t sb_2xa,
@@ -242,15 +244,21 @@ gus_write(uint16_t addr, uint8_t val, priv_t priv)
{ {
gus_t *dev = (gus_t *)priv; gus_t *dev = (gus_t *)priv;
#if defined(DEV_BRANCH) && defined(USE_GUSMAX) #if defined(DEV_BRANCH) && defined(USE_GUSMAX)
uint16_t ioport; uint16_t csioport;
#endif #endif
int c, d, old; int c, d, old;
uint16_t port;
if (dev->latch_enable && addr != 0x24b) if ((addr == 0x388) || (addr == 0x389))
dev->latch_enable = 0; port = addr;
else
port = addr & 0xf0f; /* Bit masking GUS dynamic IO*/
switch (addr) { if (dev->latch_enable && port != 0x20b)
case 0x340: /*MIDI control*/ dev->latch_enable = 0;
switch (port) {
case 0x300: /*MIDI control*/
old = dev->midi_ctrl; old = dev->midi_ctrl;
dev->midi_ctrl = val; dev->midi_ctrl = val;
@@ -261,7 +269,7 @@ gus_write(uint16_t addr, uint8_t val, priv_t priv)
midi_update_int_status(dev); midi_update_int_status(dev);
break; break;
case 0x341: /*MIDI data*/ case 0x301: /*MIDI data*/
if (dev->midi_loopback) { if (dev->midi_loopback) {
dev->midi_status |= MIDI_INT_RECEIVE; dev->midi_status |= MIDI_INT_RECEIVE;
dev->midi_data = val; dev->midi_data = val;
@@ -270,15 +278,15 @@ gus_write(uint16_t addr, uint8_t val, priv_t priv)
dev->midi_status |= MIDI_INT_TRANSMIT; dev->midi_status |= MIDI_INT_TRANSMIT;
break; break;
case 0x342: /*Voice select*/ case 0x302: /*Voice select*/
dev->voice = val & 31; dev->voice = val & 31;
break; break;
case 0x343: /*Global select*/ case 0x303: /*Global select*/
dev->global = val; dev->global = val;
break; break;
case 0x344: /*Global low*/ case 0x304: /*Global low*/
switch (dev->global) { switch (dev->global) {
case 0: /*Voice control*/ case 0: /*Voice control*/
dev->ctrl[dev->voice] = val; dev->ctrl[dev->voice] = val;
@@ -337,7 +345,7 @@ gus_write(uint16_t addr, uint8_t val, priv_t priv)
} }
break; break;
case 0x345: /*Global high*/ case 0x305: /*Global high*/
switch (dev->global) { switch (dev->global) {
case 0: /*Voice control*/ case 0: /*Voice control*/
if (!(val & 1) && dev->ctrl[dev->voice] & 1) { if (!(val & 1) && dev->ctrl[dev->voice] & 1) {
@@ -531,12 +539,13 @@ gus_write(uint16_t addr, uint8_t val, priv_t priv)
} }
break; break;
case 0x347: /*DRAM access*/ case 0x307: /*DRAM access*/
dev->ram[dev->addr] = val;
dev->addr &= 0xfffff; dev->addr &= 0xfffff;
if (dev->addr < dev->gus_end_ram)
dev->ram[dev->addr] = val;
break; break;
case 0x248: case 0x208:
case 0x388: case 0x388:
dev->adcommand = val; dev->adcommand = val;
break; break;
@@ -572,12 +581,12 @@ gus_write(uint16_t addr, uint8_t val, priv_t priv)
} }
break; break;
case 0x240: case 0x200:
dev->midi_loopback = val & 0x20; dev->midi_loopback = val & 0x20;
dev->latch_enable = (val & 0x40) ? 2 : 1; dev->latch_enable = (val & 0x40) ? 2 : 1;
break; break;
case 0x24b: case 0x20b:
switch (dev->reg_ctrl & 0x07) { switch (dev->reg_ctrl & 0x07) {
case 0: case 0:
if (dev->latch_enable == 1) if (dev->latch_enable == 1)
@@ -628,7 +637,7 @@ gus_write(uint16_t addr, uint8_t val, priv_t priv)
} }
break; break;
case 0x246: case 0x206:
dev->ad_status |= 0x08; dev->ad_status |= 0x08;
if (dev->sb_ctrl & 0x20) { if (dev->sb_ctrl & 0x20) {
if (dev->sb_nmi) if (dev->sb_nmi)
@@ -638,11 +647,11 @@ gus_write(uint16_t addr, uint8_t val, priv_t priv)
} }
break; break;
case 0x24a: case 0x20a:
dev->sb_2xa = val; dev->sb_2xa = val;
break; break;
case 0x24c: case 0x20c:
dev->ad_status |= 0x10; dev->ad_status |= 0x10;
if (dev->sb_ctrl & 0x20) { if (dev->sb_ctrl & 0x20) {
if (dev->sb_nmi) if (dev->sb_nmi)
@@ -652,31 +661,31 @@ gus_write(uint16_t addr, uint8_t val, priv_t priv)
} }
/*FALLTHOUGH*/ /*FALLTHOUGH*/
case 0x24d: case 0x20d:
dev->sb_2xc = val; dev->sb_2xc = val;
break; break;
case 0x24e: case 0x20e:
dev->sb_2xe = val; dev->sb_2xe = val;
break; break;
case 0x24f: case 0x20f:
dev->reg_ctrl = val; dev->reg_ctrl = val;
break; break;
case 0x346: case 0x746: case 0x306: case 0x706:
if (dev->dma >= 4) if (dev->dma >= 4)
val |= 0x30; val |= 0x30;
dev->max_ctrl = (val >> 6) & 1; dev->max_ctrl = (val >> 6) & 1;
#if defined(DEV_BRANCH) && defined(USE_GUSMAX) #if defined(DEV_BRANCH) && defined(USE_GUSMAX)
if (val & 0x40) { if (val & 0x40) {
if ((val & 0xF) != ((addr >> 4) & 0xF)) { /* Fix me : why is DOS application attempting to relocate the CODEC ? */ if ((val & 0xF) != ((addr >> 4) & 0xF)) { /* Fix me : why is DOS application attempting to relocate the CODEC ? */
ioport = 0x30c | ((addr >> 4) & 0xf); csioport = 0x30c | ((addr >> 4) & 0xf);
io_removehandler(ioport, 4, io_removehandler(csioport, 4,
cs423x_read,NULL,NULL, cs423x_read,NULL,NULL,
cs423x_write,NULL,NULL,&dev->cs423x); cs423x_write,NULL,NULL,&dev->cs423x);
ioport = 0x30c | ((val & 0xf) << 4); csioport = 0x30c | ((val & 0xf) << 4);
io_sethandler(ioport, 4, io_sethandler(csioport, 4,
cs423x_read,NULL,NULL, cs423x_read,NULL,NULL,
cs423x_write,NULL,NULL, &dev->cs423x); cs423x_write,NULL,NULL, &dev->cs423x);
} }
@@ -692,44 +701,50 @@ gus_read(uint16_t addr, priv_t priv)
{ {
gus_t *dev = (gus_t *)priv; gus_t *dev = (gus_t *)priv;
uint8_t val = 0xff; uint8_t val = 0xff;
uint16_t port;
switch (addr) { if ((addr == 0x388) || (addr == 0x389))
case 0x340: /*MIDI status*/ port = addr;
else
port = addr & 0xf0f; /* Bit masking GUS dynamic IO*/
switch (port) {
case 0x300: /*MIDI status*/
val = dev->midi_status; val = dev->midi_status;
break; break;
case 0x341: /*MIDI data*/ case 0x301: /*MIDI data*/
val = dev->midi_data; val = dev->midi_data;
dev->midi_status &= ~MIDI_INT_RECEIVE; dev->midi_status &= ~MIDI_INT_RECEIVE;
midi_update_int_status(dev); midi_update_int_status(dev);
break; break;
case 0x240: case 0x200:
val = 0x00; val = 0x00;
break; break;
case 0x246: /*IRQ status*/ case 0x206: /*IRQ status*/
val = dev->irqstatus & ~0x10; val = dev->irqstatus & ~0x10;
if (dev->ad_status & 0x19) if (dev->ad_status & 0x19)
val |= 0x10; val |= 0x10;
break; break;
case 0x24F: case 0x20F:
if (dev->max_ctrl) if (dev->max_ctrl)
val = 0x02; val = 0x02;
else else
val = 0x00; val = 0x00;
break; break;
case 0x342: case 0x302: /*GF1 Page Register*/
val = dev->voice; val = dev->voice;
break; break;
case 0x343: case 0x303: /*GF1 Global Register Select*/
val = dev->global; val = dev->global;
break; break;
case 0x344: /*Global low*/ case 0x304: /*Global low*/
switch (dev->global) { switch (dev->global) {
case 0x82: /*Start addr high*/ case 0x82: /*Start addr high*/
val = dev->start[dev->voice] >> 16; val = dev->start[dev->voice] >> 16;
@@ -767,7 +782,7 @@ gus_read(uint16_t addr, priv_t priv)
} }
break; break;
case 0x345: /*Global high*/ case 0x305: /*Global high*/
switch (dev->global) { switch (dev->global) {
case 0x80: /*Voice control*/ case 0x80: /*Voice control*/
val = dev->ctrl[dev->voice] | (dev->waveirqs[dev->voice] ? 0x80 : 0); val = dev->ctrl[dev->voice] | (dev->waveirqs[dev->voice] ? 0x80 : 0);
@@ -830,23 +845,26 @@ gus_read(uint16_t addr, priv_t priv)
} }
break; break;
case 0x346: case 0x746: case 0x306: case 0x706:
if (dev->max_ctrl) if (dev->max_ctrl)
val = 0x0a; /* GUS MAX */ val = 0x0a; /* GUS MAX */
else else
val = 0xff; /*Pre 3.7 - no mixer*/ val = 0xff; /*Pre 3.7 - no mixer*/
break; break;
case 0x347: /*DRAM access*/ case 0x307: /*DRAM access*/
val = dev->ram[dev->addr];
dev->addr &= 0xFFFFF; dev->addr &= 0xFFFFF;
if (dev->addr < dev->gus_end_ram)
val = dev->ram[dev->addr];
else
val = 0;
break; break;
case 0x349: case 0x309:
val = 0x00; val = 0x00;
break; break;
case 0x24b: case 0x20B:
switch (dev->reg_ctrl & 0x07) { switch (dev->reg_ctrl & 0x07) {
case 1: case 1:
val = dev->gp1; val = dev->gp1;
@@ -866,17 +884,17 @@ gus_read(uint16_t addr, priv_t priv)
} }
break; break;
case 0x24c: case 0x20C:
val = dev->sb_2xc; val = dev->sb_2xc;
if (dev->reg_ctrl & 0x20) if (dev->reg_ctrl & 0x20)
dev->sb_2xc &= 0x80; dev->sb_2xc &= 0x80;
break; break;
case 0x24e: case 0x20E:
val = dev->sb_2xe; val = dev->sb_2xe;
break; break;
case 0x248: case 0x208: /* Timer Control Register */
case 0x388: case 0x388:
if (dev->tctrl & GUS_TIMER_CTRL_AUTO) if (dev->tctrl & GUS_TIMER_CTRL_AUTO)
val = dev->sb_2xa; val = dev->sb_2xa;
@@ -887,16 +905,16 @@ gus_read(uint16_t addr, priv_t priv)
} }
break; break;
case 0x249: case 0x209: /* Timer Data */
dev->ad_status &= ~0x01; dev->ad_status &= ~0x01;
nmi = 0; nmi = 0;
/*FALLTHROUGH?*/ /*FALLTHROUGH?*/
case 0x389: case 0x389:/* Adlib port 389 */
val = dev->ad_data; val = dev->ad_data;
break; break;
case 0x24A: case 0x20A:
val = dev->adcommand; val = dev->adcommand;
break; break;
@@ -1161,12 +1179,14 @@ gus_init(const device_t *info, UNUSED(void *parent))
gus_t *dev; gus_t *dev;
double out = 1.0; double out = 1.0;
int c; int c;
uint8_t gus_ram = device_get_config_int("gus_ram");
dev = (gus_t *)mem_alloc(sizeof(gus_t)); dev = (gus_t *)mem_alloc(sizeof(gus_t));
memset(dev, 0x00, sizeof(gus_t)); memset(dev, 0x00, sizeof(gus_t));
dev->ram = (uint8_t *)mem_alloc(1 << 20); dev->gus_end_ram = 1 << (18 + gus_ram);
memset(dev->ram, 0x00, 1 << 20); dev->ram = (uint8_t *)mem_alloc(dev->gus_end_ram);
memset(dev->ram, 0x00, (dev->gus_end_ram));
for (c = 0; c < 32; c++) { for (c = 0; c < 32; c++) {
dev->ctrl[c] = 1; dev->ctrl[c] = 1;
@@ -1187,13 +1207,15 @@ gus_init(const device_t *info, UNUSED(void *parent))
dev->t1l = dev->t2l = 0xff; dev->t1l = dev->t2l = 0xff;
dev->base = device_get_config_hex16("base");
switch(info->local) { switch(info->local) {
case 0: /* Standard GUS */ case 0: /* Standard GUS */
io_sethandler(0x0240, 16, io_sethandler(dev->base, 16,
gus_read,NULL,NULL, gus_write,NULL,NULL, dev); gus_read,NULL,NULL, gus_write,NULL,NULL, dev);
io_sethandler(0x0340, 16, io_sethandler(0x0100+dev->base, 16,
gus_read,NULL,NULL, gus_write,NULL,NULL, dev); gus_read,NULL,NULL, gus_write,NULL,NULL, dev);
io_sethandler(0x0746, 1, io_sethandler(0x0506+dev->base, 1,
gus_read,NULL,NULL, gus_write,NULL,NULL, dev); gus_read,NULL,NULL, gus_write,NULL,NULL, dev);
io_sethandler(0x0388, 2, io_sethandler(0x0388, 2,
gus_read,NULL,NULL, gus_write,NULL,NULL, dev); gus_read,NULL,NULL, gus_write,NULL,NULL, dev);
@@ -1206,15 +1228,15 @@ gus_init(const device_t *info, UNUSED(void *parent))
cs423x_setirq(&dev->cs423x, 5); /*Default irq and dma from GUS SDK*/ cs423x_setirq(&dev->cs423x, 5); /*Default irq and dma from GUS SDK*/
cs423x_setdma(&dev->cs423x, 3); cs423x_setdma(&dev->cs423x, 3);
io_sethandler(0x0240, 16, io_sethandler(dev->base, 16,
gus_read,NULL,NULL, gus_write,NULL, NULL, dev); gus_read,NULL,NULL, gus_write,NULL, NULL, dev);
io_sethandler(0x0340, 9, io_sethandler(0x0100+dev->base, 9,
gus_read,NULL,NULL, gus_write,NULL, NULL, dev); gus_read,NULL,NULL, gus_write,NULL, NULL, dev);
io_sethandler(0x0746, 1, io_sethandler(0x0506+dev->base, 1,
gus_read,NULL,NULL, gus_write,NULL, NULL, dev); gus_read,NULL,NULL, gus_write,NULL, NULL, dev);
io_sethandler(0x0388, 2, io_sethandler(0x0388, 2,
gus_read,NULL,NULL, gus_write,NULL, NULL, dev); gus_read,NULL,NULL, gus_write,NULL, NULL, dev);
io_sethandler(0x034c, 4, io_sethandler(0x10C+dev->base, 4,
cs423x_read,NULL,NULL, cs423x_write,NULL,NULL, &dev->cs423x); cs423x_read,NULL,NULL, cs423x_write,NULL,NULL, &dev->cs423x);
break; break;
@@ -1259,6 +1281,94 @@ speed_changed(priv_t priv)
#endif #endif
} }
static const device_config_t gus_config[] = {
{
"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
}
};
static const device_config_t gus_max_config[] = {
{
"base", "Address", CONFIG_HEX16, "", 0x220,
{
{
"210H", 0x210
},
{
"220H", 0x220
},
{
"230H", 0x230
},
{
"240H", 0x240
},
{
"250H", 0x250
},
{
"260H", 0x260
},
},
},
{
"gus_ram", "Onboard RAM", CONFIG_SELECTION, "", 1,
{
{
"512 KB", 1
},
{
"1 MB", 2
},
{
NULL
}
}
},
{
"", "", -1
}
};
const device_t gus_device = { const device_t gus_device = {
"Gravis UltraSound", "Gravis UltraSound",
@@ -1268,7 +1378,7 @@ const device_t gus_device = {
gus_init, gus_close, NULL, gus_init, gus_close, NULL,
NULL, NULL,
speed_changed, NULL, NULL, speed_changed, NULL, NULL,
NULL gus_config
}; };
#if defined(DEV_BRANCH) && defined(USE_GUSMAX) #if defined(DEV_BRANCH) && defined(USE_GUSMAX)
@@ -1280,6 +1390,6 @@ const device_t gusmax_device = {
gus_init, gus_close, NULL, gus_init, gus_close, NULL,
NULL, NULL,
speed_changed, NULL, NULL, speed_changed, NULL, NULL,
NULL gus_max_config
}; };
#endif #endif