Merge pull request #787 from Altheos/feature/gusmax

Preliminary GUS MAX support
This commit is contained in:
OBattler
2020-06-07 00:14:54 +02:00
committed by GitHub
4 changed files with 128 additions and 15 deletions

View File

@@ -1,6 +1,5 @@
/*PCem v0.8 by Tom Walker /*
AD1848 / CS4248 / CS4231 CODEC emulation (Windows Sound System compatible)*/
AD1848 CODEC emulation (Windows Sound System compatible)*/
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
@@ -14,6 +13,7 @@
#include <86box/sound.h> #include <86box/sound.h>
#include <86box/snd_ad1848.h> #include <86box/snd_ad1848.h>
#define CS4231 0x80
static int ad1848_vols_6bits[64]; static int ad1848_vols_6bits[64];
static uint32_t ad1848_vols_5bits_aux_gain[32]; static uint32_t ad1848_vols_5bits_aux_gain[32];
@@ -40,7 +40,11 @@ uint8_t ad1848_read(uint16_t addr, void *p)
break; break;
case 1: case 1:
temp = ad1848->regs[ad1848->index]; temp = ad1848->regs[ad1848->index];
break; if (ad1848->index == 0x0b) {
temp ^= 0x20;
ad1848->regs[ad1848->index] = temp;
}
break;
case 2: case 2:
temp = ad1848->status; temp = ad1848->status;
break; break;
@@ -97,6 +101,10 @@ void ad1848_write(uint16_t addr, uint8_t val, void *p)
} }
break; break;
case 11:
break;
case 12: case 12:
if (ad1848->type != AD1848_TYPE_DEFAULT) if (ad1848->type != AD1848_TYPE_DEFAULT)
ad1848->regs[12] = ((ad1848->regs[12] & 0x0f) + (val & 0xf0)) | 0x80; ad1848->regs[12] = ((ad1848->regs[12] & 0x0f) + (val & 0xf0)) | 0x80;
@@ -105,6 +113,14 @@ void ad1848_write(uint16_t addr, uint8_t val, void *p)
case 14: case 14:
ad1848->count = ad1848->regs[15] | (val << 8); ad1848->count = ad1848->regs[15] | (val << 8);
break; break;
case 24:
if (! (val & 0x70))
ad1848->status &= 0xfe;
break;
case 25:
break;
} }
ad1848->regs[ad1848->index] = val; ad1848->regs[ad1848->index] = val;
@@ -197,7 +213,7 @@ static void ad1848_poll(void *p)
if (!(ad1848->status & 0x01)) if (!(ad1848->status & 0x01))
{ {
ad1848->status |= 0x01; ad1848->status |= 0x01;
if (ad1848->regs[0xa] & 2) if (ad1848->regs[10] & 2)
picint(1 << ad1848->irq); picint(1 << ad1848->irq);
} }
} }
@@ -221,9 +237,9 @@ void ad1848_init(ad1848_t *ad1848, int type)
ad1848->mce = 0x40; ad1848->mce = 0x40;
ad1848->regs[0] = ad1848->regs[1] = 0; ad1848->regs[0] = ad1848->regs[1] = 0;
ad1848->regs[2] = ad1848->regs[3] = 0x80; /* AZT2316A Line-in */ ad1848->regs[2] = ad1848->regs[3] = 0x80; /* Line-in */
ad1848->regs[4] = ad1848->regs[5] = 0x80; ad1848->regs[4] = ad1848->regs[5] = 0x80;
ad1848->regs[6] = ad1848->regs[7] = 0x80; /* AZT2316A Master? */ ad1848->regs[6] = ad1848->regs[7] = 0x80; /* Left/right Output */
ad1848->regs[8] = 0; ad1848->regs[8] = 0;
ad1848->regs[9] = 0x08; ad1848->regs[9] = 0x08;
ad1848->regs[10] = ad1848->regs[11] = 0; ad1848->regs[10] = ad1848->regs[11] = 0;
@@ -236,8 +252,13 @@ void ad1848_init(ad1848_t *ad1848, int type)
if (type == AD1848_TYPE_CS4231) if (type == AD1848_TYPE_CS4231)
{ {
ad1848->regs[0x12] = ad1848->regs[0x13] = 0x80; // AZT2316A CD ad1848->regs[16] = ad1848->regs[17] = 0;
ad1848->regs[0x1A] = 0x80; // AZT2316A Mic ad1848->regs[18] = ad1848->regs[19] = 0x88;
ad1848->regs[22] = 0x80;
ad1848->regs[24] = 0;
ad1848->regs[25] = CS4231;
ad1848->regs[26] = 0x80;
ad1848->regs[29] = 0x80;
} }
ad1848->out_l = 0; ad1848->out_l = 0;

View File

@@ -14,6 +14,8 @@
#include <86box/device.h> #include <86box/device.h>
#include <86box/sound.h> #include <86box/sound.h>
#include <86box/midi.h> #include <86box/midi.h>
#include <86Box/snd_ad1848.h>
#include <math.h>
enum enum
{ {
@@ -108,6 +110,12 @@ typedef struct gus_t
uint16_t gp1_addr, gp2_addr; uint16_t gp1_addr, gp2_addr;
uint8_t usrr; uint8_t usrr;
uint8_t max_ctrl;
#if defined(DEV_BRANCH) && defined(USE_GUSMAX)
ad1848_t ad1848;
#endif
} gus_t; } gus_t;
static int gus_gf1_irqs[8] = {-1, 2, 5, 3, 7, 11, 12, 15}; static int gus_gf1_irqs[8] = {-1, 2, 5, 3, 7, 11, 12, 15};
@@ -182,6 +190,9 @@ void writegus(uint16_t addr, uint8_t val, void *p)
int c, d; int c, d;
int old; int old;
uint16_t port; uint16_t port;
#if defined(DEV_BRANCH) && defined(USE_GUSMAX)
uint16_t csioport;
#endif
if ((addr == 0x388) || (addr == 0x389)) if ((addr == 0x388) || (addr == 0x389))
port = addr; port = addr;
@@ -526,10 +537,16 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8);
} }
else else
gus->irq_midi = gus_midi_irqs[(val >> 3) & 7]; gus->irq_midi = gus_midi_irqs[(val >> 3) & 7];
#if defined(DEV_BRANCH) && defined(USE_GUSMAX)
ad1848_setirq(&gus->ad1848, gus->irq);
#endif
gus->sb_nmi = val & 0x80; gus->sb_nmi = val & 0x80;
} else { } else {
gus->dma = gus_dmas[val & 7]; gus->dma = gus_dmas[val & 7];
#if defined(DEV_BRANCH) && defined(USE_GUSMAX)
ad1848_setdma(&gus->ad1848, gus->dma);
#endif
} }
break; break;
case 1: case 1:
@@ -584,6 +601,25 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8);
case 0x20f: case 0x20f:
gus->reg_ctrl = val; gus->reg_ctrl = val;
break; break;
case 0x306: case 0x706:
if (gus->dma >= 4)
val |= 0x30;
gus->max_ctrl = (val >> 6) & 1;
#if defined(DEV_BRANCH) && defined(USE_GUSMAX)
if (val & 0x40) {
if ((val & 0xF) != ((addr >> 4) & 0xF)) {
csioport = 0x30c | ((addr >> 4) & 0xf);
io_removehandler(csioport, 4,
ad1848_read,NULL,NULL,
ad1848_write,NULL,NULL,&gus->ad1848);
csioport = 0x30c | ((val & 0xf) << 4);
io_sethandler(csioport, 4,
ad1848_read,NULL,NULL,
ad1848_write,NULL,NULL, &gus->ad1848);
}
}
#endif
break;
} }
} }
@@ -632,7 +668,11 @@ uint8_t readgus(uint16_t addr, void *p)
return val; return val;
case 0x20F: case 0x20F:
return 0; if (gus->max_ctrl)
val = 0x02;
else
val = 0x00;
break;
case 0x302: case 0x302:
return gus->voice; return gus->voice;
@@ -719,8 +759,14 @@ uint8_t readgus(uint16_t addr, void *p)
break; break;
} }
break; break;
case 0x306: case 0x706: /*Revision level*/ case 0x306: case 0x706:
return 0xff; /*Pre 3.7 - no mixer*/ if (gus->max_ctrl)
val = 0x0a; /* GUS MAX */
else
val = 0xff; /*Pre 3.7 - no mixer*/
break;
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;
@@ -1031,13 +1077,25 @@ static void gus_get_buffer(int32_t *buffer, int len, void *p)
gus_t *gus = (gus_t *)p; gus_t *gus = (gus_t *)p;
int c; int c;
#if defined(DEV_BRANCH) && defined(USE_GUSMAX)
if (gus->max_ctrl)
ad1848_update(&gus->ad1848);
#endif
gus_update(gus); gus_update(gus);
for (c = 0; c < len * 2; c++) for (c = 0; c < len * 2; c++)
{ {
#if defined(DEV_BRANCH) && defined(USE_GUSMAX)
if (gus->max_ctrl)
buffer[c] += (int32_t)(gus->ad1848.buffer[c] / 2);
#endif
buffer[c] += (int32_t)gus->buffer[c & 1][c >> 1]; buffer[c] += (int32_t)gus->buffer[c & 1][c >> 1];
} }
#if defined(DEV_BRANCH) && defined(USE_GUSMAX)
if (gus->max_ctrl)
gus->ad1848.pos = 0;
#endif
gus->pos = 0; gus->pos = 0;
} }
@@ -1119,6 +1177,15 @@ void *gus_init(const device_t *info)
io_sethandler(0x0100+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(0x0506+gus->base, 0x0001, readgus, NULL, NULL, writegus, NULL, NULL, gus);
io_sethandler(0x0388, 0x0002, readgus, NULL, NULL, writegus, NULL, NULL, gus); io_sethandler(0x0388, 0x0002, readgus, NULL, NULL, writegus, NULL, NULL, gus);
#if defined(DEV_BRANCH) && defined(USE_GUSMAX)
ad1848_init(&gus->ad1848, AD1848_TYPE_CS4231);
ad1848_setirq(&gus->ad1848, 5);
ad1848_setdma(&gus->ad1848, 3);
io_sethandler(0x10C+gus->base, 4,
ad1848_read,NULL,NULL, ad1848_write,NULL,NULL, &gus->ad1848);
#endif
timer_add(&gus->samp_timer, gus_poll_wave, gus, 1); timer_add(&gus->samp_timer, gus_poll_wave, gus, 1);
timer_add(&gus->timer_1, gus_poll_timer_1, gus, 1); timer_add(&gus->timer_1, gus_poll_timer_1, gus, 1);
timer_add(&gus->timer_2, gus_poll_timer_2, gus, 1); timer_add(&gus->timer_2, gus_poll_timer_2, gus, 1);
@@ -1147,6 +1214,11 @@ void gus_speed_changed(void *p)
gus->samp_latch = (uint64_t)(TIMER_USEC * (1000000.0 / 44100.0)); gus->samp_latch = (uint64_t)(TIMER_USEC * (1000000.0 / 44100.0));
else else
gus->samp_latch = (uint64_t)(TIMER_USEC * (1000000.0 / gusfreqs[gus->voices - 14])); gus->samp_latch = (uint64_t)(TIMER_USEC * (1000000.0 / gusfreqs[gus->voices - 14]));
#if defined(DEV_BRANCH) && defined(USE_GUSMAX)
if (gus->max_ctrl)
ad1848_speed_changed(&gus->ad1848);
#endif
} }
static const device_config_t gus_config[] = { static const device_config_t gus_config[] = {
@@ -1156,7 +1228,7 @@ static const device_config_t gus_config[] = {
{ {
"Classic", GUS_CLASSIC "Classic", GUS_CLASSIC
}, },
#if 0 #if defined(DEV_BRANCH) && defined(USE_GUSMAX)
{ {
"MAX", GUS_MAX "MAX", GUS_MAX
}, },

View File

@@ -8,7 +8,7 @@
# #
# Makefile for Win32 (MinGW32) environment. # Makefile for Win32 (MinGW32) environment.
# #
# Version: @(#)Makefile.mingw 1.0.143 2020/01/25 # Version: @(#)Makefile.mingw 1.0.144 2020/06/06
# #
# Authors: Miran Grca, <mgrca8@gmail.com> # Authors: Miran Grca, <mgrca8@gmail.com>
# Fred N. van Kempen, <decwiz@yahoo.com> # Fred N. van Kempen, <decwiz@yahoo.com>
@@ -86,6 +86,9 @@ ifeq ($(DEV_BUILD), y)
ifndef NO_SIO ifndef NO_SIO
NO_SIO := y NO_SIO := y
endif endif
ifndef GUSMAX
GUSMAX := y
endif
else else
ifndef DEBUG ifndef DEBUG
DEBUG := n DEBUG := n
@@ -141,6 +144,9 @@ else
ifndef NO_SIO ifndef NO_SIO
NO_SIO := n NO_SIO := n
endif endif
ifndef GUSMAX
GUSMAX := n
endif
endif endif
# Defaults for several build options (possibly defined in a chained file.) # Defaults for several build options (possibly defined in a chained file.)
@@ -471,6 +477,10 @@ ifeq ($(NO_SIO), y)
OPTS += -DNO_SIO OPTS += -DNO_SIO
endif endif
ifeq ($(GUSMAX), y)
OPTS += -DUSE_GUSMAX
endif
endif endif

View File

@@ -8,7 +8,7 @@
# #
# Makefile for Win32 (MinGW32) environment. # Makefile for Win32 (MinGW32) environment.
# #
# Version: @(#)Makefile.mingw 1.0.142 2020/01/25 # Version: @(#)Makefile.mingw 1.0.143 2020/06/06
# #
# Authors: Miran Grca, <mgrca8@gmail.com> # Authors: Miran Grca, <mgrca8@gmail.com>
# Fred N. van Kempen, <decwiz@yahoo.com> # Fred N. van Kempen, <decwiz@yahoo.com>
@@ -86,6 +86,9 @@ ifeq ($(DEV_BUILD), y)
ifndef NO_SIO ifndef NO_SIO
NO_SIO := y NO_SIO := y
endif endif
ifndef GUSMAX
GUSMAX := y
endif
else else
ifndef DEBUG ifndef DEBUG
DEBUG := n DEBUG := n
@@ -144,6 +147,9 @@ else
ifndef NO_SIO ifndef NO_SIO
NO_SIO := n NO_SIO := n
endif endif
ifndef GUSMAX
GUSMAX := n
endif
endif endif
# Defaults for several build options (possibly defined in a chained file.) # Defaults for several build options (possibly defined in a chained file.)
@@ -480,6 +486,10 @@ ifeq ($(NO_SIO), y)
OPTS += -DNO_SIO OPTS += -DNO_SIO
endif endif
ifeq ($(GUSMAX), y)
OPTS += -DUSE_GUSMAX
endif
endif endif