Merge pull request #624 from 86Box/feature/azt_snd

Added the Aztech Sound Galaxy 16 cards.
This commit is contained in:
OBattler
2020-03-25 01:12:22 +01:00
committed by GitHub
26 changed files with 2049 additions and 440 deletions

View File

@@ -718,6 +718,8 @@ static void ps2_mca_write(uint16_t port, uint8_t val, void *p)
ps2.setup = val;
break;
case 0x96:
if ((val & 0x80) && !(ps2.adapter_setup & 0x80))
mca_reset();
ps2.adapter_setup = val;
mca_set_index(val & 7);
break;
@@ -856,7 +858,7 @@ static void ps2_mca_mem_fffc_init(int start_mb)
break;
}
mca_add(ps2_mem_expansion_read, ps2_mem_expansion_write, ps2_mem_expansion_feedb, NULL);
mca_add(ps2_mem_expansion_read, ps2_mem_expansion_write, ps2_mem_expansion_feedb, NULL, NULL);
mem_mapping_add(&ps2.expansion_mapping,
expansion_start,
(mem_size - (start_mb << 10)) << 10,

View File

@@ -9,6 +9,7 @@
void (*mca_card_write[8])(int addr, uint8_t val, void *priv);
uint8_t (*mca_card_read[8])(int addr, void *priv);
uint8_t (*mca_card_feedb[8])(void *priv);
void (*mca_card_reset[8])(void *priv);
void *mca_priv[8];
static int mca_index;
@@ -19,10 +20,10 @@ void mca_init(int nr_cards)
{
int c;
for (c = 0; c < 8; c++)
{
for (c = 0; c < 8; c++) {
mca_card_read[c] = NULL;
mca_card_write[c] = NULL;
mca_card_reset[c] = NULL;
mca_priv[c] = NULL;
}
@@ -60,17 +61,27 @@ uint8_t mca_feedb(void)
return 0;
}
void mca_add(uint8_t (*read)(int addr, void *priv), void (*write)(int addr, uint8_t val, void *priv), uint8_t (*feedb)(void *priv), void *priv)
void mca_reset(void)
{
int c;
for (c = 0; c < mca_nr_cards; c++)
{
if (!mca_card_read[c] && !mca_card_write[c])
for (c = 0; c < 8; c++) {
if (mca_card_reset[c])
mca_card_reset[c](mca_priv[c]);
}
}
void mca_add(uint8_t (*read)(int addr, void *priv), void (*write)(int addr, uint8_t val, void *priv), uint8_t (*feedb)(void *priv), void (*reset)(void *priv), void *priv)
{
int c;
for (c = 0; c < mca_nr_cards; c++) {
if (!mca_card_read[c] && !mca_card_write[c]) {
mca_card_read[c] = read;
mca_card_write[c] = write;
mca_card_feedb[c] = feedb;
mca_card_reset[c] = reset;
mca_priv[c] = priv;
return;
}

View File

@@ -1,8 +1,9 @@
extern void mca_init(int nr_cards);
extern void mca_add(uint8_t (*read)(int addr, void *priv), void (*write)(int addr, uint8_t val, void *priv), uint8_t (*feedb)(void *priv), void *priv);
extern void mca_add(uint8_t (*read)(int addr, void *priv), void (*write)(int addr, uint8_t val, void *priv), uint8_t (*feedb)(void *priv), void (*reset)(void *priv), void *priv);
extern void mca_set_index(int index);
extern uint8_t mca_read(uint16_t port);
extern void mca_write(uint16_t port, uint8_t val);
extern uint8_t mca_feedb(void);
extern void mca_reset(void);
extern void ps2_cache_clean(void);

View File

@@ -1238,7 +1238,7 @@ nic_init(const device_t *info)
}
}
else {
mca_add(nic_mca_read, nic_mca_write, nic_mca_feedb, dev);
mca_add(nic_mca_read, nic_mca_write, nic_mca_feedb, NULL, dev);
}
}

View File

@@ -675,7 +675,7 @@ wd_init(const device_t *info)
}
if ((dev->board == WD8003ETA) || (dev->board == WD8003EA))
mca_add(wd_mca_read, wd_mca_write, wd_mca_feedb, dev);
mca_add(wd_mca_read, wd_mca_write, wd_mca_feedb, NULL, dev);
else {
dev->base_address = device_get_config_hex16("base");
dev->irq = device_get_config_int("irq");

View File

@@ -861,7 +861,7 @@ aha_init(const device_t *info)
/* Enable MCA. */
dev->pos_regs[0] = 0x1F; /* MCA board ID */
dev->pos_regs[1] = 0x0F;
mca_add(aha_mca_read, aha_mca_write, aha_mca_feedb, dev);
mca_add(aha_mca_read, aha_mca_write, aha_mca_feedb, NULL, dev);
dev->ha_bps = 5000000.0; /* normal SCSI */
break;
}

View File

@@ -1626,7 +1626,7 @@ buslogic_init(const device_t *info)
dev->flags |= X54X_32BIT;
dev->pos_regs[0] = 0x08; /* MCA board ID */
dev->pos_regs[1] = 0x07;
mca_add(buslogic_mca_read, buslogic_mca_write, buslogic_mca_feedb, dev);
mca_add(buslogic_mca_read, buslogic_mca_write, buslogic_mca_feedb, NULL, dev);
dev->ha_bps = 5000000.0; /* normal SCSI */
dev->max_id = 7; /* narrow SCSI */
break;

View File

@@ -1091,8 +1091,7 @@ spock_init(const device_t *info)
scsi->pos_regs[0] = 0xff;
scsi->pos_regs[1] = 0x8e;
// mca_add(spock_mca_read, spock_mca_write, spock_mca_feedb, spock_mca_reset, scsi);
mca_add(spock_mca_read, spock_mca_write, spock_mca_feedb, scsi);
mca_add(spock_mca_read, spock_mca_write, spock_mca_feedb, spock_mca_reset, scsi);
scsi->in_reset = 2;
scsi->cmd_timer = SPOCK_TIME * 50;

View File

@@ -15,7 +15,8 @@
#include "snd_ad1848.h"
static int ad1848_vols[64];
static int ad1848_vols_6bits[64];
static uint32_t ad1848_vols_5bits_aux_gain[32];
void ad1848_setirq(ad1848_t *ad1848, int irq)
@@ -51,10 +52,14 @@ void ad1848_write(uint16_t addr, uint8_t val, void *p)
{
ad1848_t *ad1848 = (ad1848_t *)p;
double freq;
uint32_t new_cd_vol_l, new_cd_vol_r;
switch (addr & 3)
{
case 0: /*Index*/
ad1848->index = val & 0xf;
if ((ad1848->regs[12] & 0x40) && (ad1848->type == AD1848_TYPE_CS4231))
ad1848->index = val & 0x1f; /* cs4231a extended mode enabled */
else
ad1848->index = val & 0x0f; /* ad1848/cs4248 mode TODO: some variants/clones DO NOT mirror, just ignore the writes? */
ad1848->trd = val & 0x20;
ad1848->mce = val & 0x40;
break;
@@ -93,6 +98,8 @@ void ad1848_write(uint16_t addr, uint8_t val, void *p)
break;
case 12:
if (ad1848->type != AD1848_TYPE_DEFAULT)
ad1848->regs[12] = ((ad1848->regs[12] & 0x0f) + (val & 0xf0)) | 0x80;
return;
case 14:
@@ -100,6 +107,22 @@ void ad1848_write(uint16_t addr, uint8_t val, void *p)
break;
}
ad1848->regs[ad1848->index] = val;
if (ad1848->type == AD1848_TYPE_CS4231) { /* TODO: configure CD volume for CS4248/AD1848 too */
if (ad1848->regs[0x12] & 0x80)
new_cd_vol_l = 0;
else
new_cd_vol_l = ad1848_vols_5bits_aux_gain[ad1848->regs[0x12] & 0x1f];
if (ad1848->regs[0x13] & 0x80)
new_cd_vol_r = 0;
else
new_cd_vol_r = ad1848_vols_5bits_aux_gain[ad1848->regs[0x13] & 0x1f];
/* Apparently there is no master volume to modulate here
(The windows mixer just adjusts all registers at the same
time when the master slider is adjusted) */
sound_set_cd_volume(new_cd_vol_l, new_cd_vol_r);
}
break;
case 2:
ad1848->status &= 0xfe;
@@ -161,12 +184,12 @@ static void ad1848_poll(void *p)
if (ad1848->regs[6] & 0x80)
ad1848->out_l = 0;
else
ad1848->out_l = (ad1848->out_l * ad1848_vols[ad1848->regs[6] & 0x3f]) >> 16;
ad1848->out_l = (ad1848->out_l * ad1848_vols_6bits[ad1848->regs[6] & 0x3f]) >> 16;
if (ad1848->regs[7] & 0x80)
ad1848->out_r = 0;
else
ad1848->out_r = (ad1848->out_r * ad1848_vols[ad1848->regs[7] & 0x3f]) >> 16;
ad1848->out_r = (ad1848->out_r * ad1848_vols_6bits[ad1848->regs[7] & 0x3f]) >> 16;
if (ad1848->count < 0)
{
@@ -184,10 +207,11 @@ static void ad1848_poll(void *p)
else
{
ad1848->out_l = ad1848->out_r = 0;
sound_set_cd_volume(0, 0);
}
}
void ad1848_init(ad1848_t *ad1848)
void ad1848_init(ad1848_t *ad1848, int type)
{
int c;
double attenuation;
@@ -197,21 +221,29 @@ void ad1848_init(ad1848_t *ad1848)
ad1848->mce = 0x40;
ad1848->regs[0] = ad1848->regs[1] = 0;
ad1848->regs[2] = ad1848->regs[3] = 0x80;
ad1848->regs[2] = ad1848->regs[3] = 0x80; /* AZT2316A Line-in */
ad1848->regs[4] = ad1848->regs[5] = 0x80;
ad1848->regs[6] = ad1848->regs[7] = 0x80;
ad1848->regs[6] = ad1848->regs[7] = 0x80; /* AZT2316A Master? */
ad1848->regs[8] = 0;
ad1848->regs[9] = 0x08;
ad1848->regs[10] = ad1848->regs[11] = 0;
if ((type == AD1848_TYPE_CS4248) || (type == AD1848_TYPE_CS4231))
ad1848->regs[12] = 0x8a;
else
ad1848->regs[12] = 0xa;
ad1848->regs[13] = 0;
ad1848->regs[14] = ad1848->regs[15] = 0;
if (type == AD1848_TYPE_CS4231)
{
ad1848->regs[0x12] = ad1848->regs[0x13] = 0x80; // AZT2316A CD
ad1848->regs[0x1A] = 0x80; // AZT2316A Mic
}
ad1848->out_l = 0;
ad1848->out_r = 0;
for (c = 0; c < 64; c++)
{
for (c = 0; c < 64; c++) {
attenuation = 0.0;
if (c & 0x01) attenuation -= 1.5;
if (c & 0x02) attenuation -= 3.0;
@@ -222,8 +254,23 @@ void ad1848_init(ad1848_t *ad1848)
attenuation = pow(10, attenuation / 10);
ad1848_vols[c] = (int)(attenuation * 65536);
ad1848_vols_6bits[c] = (int)(attenuation * 65536);
}
for (c = 0; c < 32; c++) {
attenuation = 12.0;
if (c & 0x01) attenuation -= 1.5;
if (c & 0x02) attenuation -= 3.0;
if (c & 0x04) attenuation -= 6.0;
if (c & 0x08) attenuation -= 12.0;
if (c & 0x10) attenuation -= 24.0;
attenuation = pow(10, attenuation / 10);
ad1848_vols_5bits_aux_gain[c] = (int)(attenuation * 65536);
}
ad1848->type = type;
timer_add(&ad1848->timer_count, ad1848_poll, ad1848, 0);
}

View File

@@ -1,7 +1,11 @@
#define AD1848_TYPE_DEFAULT 0
#define AD1848_TYPE_CS4248 1
#define AD1848_TYPE_CS4231 2
typedef struct ad1848_t
{
int index;
uint8_t regs[16];
uint8_t regs[32]; /* 16 original + 16 CS4231A extensions */
uint8_t status;
int trd;
@@ -22,6 +26,8 @@ typedef struct ad1848_t
int16_t buffer[SOUNDBUFLEN * 2];
int pos;
int type;
} ad1848_t;
void ad1848_setirq(ad1848_t *ad1848, int irq);
@@ -33,4 +39,4 @@ void ad1848_write(uint16_t addr, uint8_t val, void *p);
void ad1848_update(ad1848_t *ad1848);
void ad1848_speed_changed(ad1848_t *ad1848);
void ad1848_init(ad1848_t *ad1848);
void ad1848_init(ad1848_t *ad1848, int type);

1399
src/sound/snd_azt2316a.c Normal file

File diff suppressed because it is too large Load Diff

1
src/sound/snd_azt2316a.h Normal file
View File

@@ -0,0 +1 @@
extern void azt2316a_enable_wss(uint8_t enable, void *p);

View File

@@ -1593,6 +1593,11 @@ MPU401_InputMsg(void *p, uint8_t *msg)
MPU401_QueueByte(mpu, msg[i]);
}
void
mpu401_setirq(mpu_t *mpu, int irq)
{
mpu->irq = irq;
}
void
mpu401_change_addr(mpu_t *mpu, uint16_t addr)
@@ -1711,7 +1716,7 @@ mpu401_standalone_init(const device_t *info)
mpu401_log("mpu_init\n");
if (info->flags & DEVICE_MCA) {
mca_add(mpu401_mca_read, mpu401_mca_write, mpu401_mca_feedb, mpu);
mca_add(mpu401_mca_read, mpu401_mca_write, mpu401_mca_feedb, NULL, mpu);
mpu->pos_regs[0] = 0x0F;
mpu->pos_regs[1] = 0x6C;
base = 0; /* Tell mpu401_init() that this is the MCA variant. */

View File

@@ -150,6 +150,7 @@ extern const device_t mpu401_mca_device;
extern uint8_t MPU401_ReadData(mpu_t *mpu);
extern void mpu401_setirq(mpu_t *mpu, int irq);
extern void mpu401_change_addr(mpu_t *mpu, uint16_t addr);
extern void mpu401_init(mpu_t *mpu, uint16_t addr, int irq, int mode, int receive_input);
extern void mpu401_device_add(void);

View File

@@ -737,7 +737,7 @@ static void *pas16_init(const device_t *info)
memset(pas16, 0, sizeof(pas16_t));
opl3_init(&pas16->opl);
sb_dsp_init(&pas16->dsp, SB2);
sb_dsp_init(&pas16->dsp, SB2, SB_SUBTYPE_DEFAULT, pas16);
io_sethandler(0x9a01, 0x0001, NULL, NULL, NULL, pas16_out_base, NULL, NULL, pas16);

View File

@@ -35,10 +35,7 @@
#include "sound.h"
#include "midi.h"
#include "filters.h"
#include "snd_emu8k.h"
#include "snd_mpu401.h"
#include "snd_opl.h"
#include "snd_sb_dsp.h"
#include "snd_sb.h"
//#define SB_DSP_RECORD_DEBUG
@@ -48,102 +45,6 @@ FILE* soundfsbin = 0/*NULL*/;
#endif
/* SB 2.0 CD version */
typedef struct sb_ct1335_mixer_t
{
int32_t master;
int32_t voice;
int32_t fm;
int32_t cd;
uint8_t index;
uint8_t regs[256];
} sb_ct1335_mixer_t;
/* SB PRO */
typedef struct sb_ct1345_mixer_t
{
int32_t master_l, master_r;
int32_t voice_l, voice_r;
int32_t fm_l, fm_r;
int32_t cd_l, cd_r;
int32_t line_l, line_r;
int32_t mic;
/*see sb_ct1745_mixer for values for input selector*/
int32_t input_selector;
int input_filter;
int in_filter_freq;
int output_filter;
int stereo;
int stereo_isleft;
uint8_t index;
uint8_t regs[256];
} sb_ct1345_mixer_t;
/* SB16 and AWE32 */
typedef struct sb_ct1745_mixer_t
{
int32_t master_l, master_r;
int32_t voice_l, voice_r;
int32_t fm_l, fm_r;
int32_t cd_l, cd_r;
int32_t line_l, line_r;
int32_t mic;
int32_t speaker;
int bass_l, bass_r;
int treble_l, treble_r;
int output_selector;
#define OUTPUT_MIC 1
#define OUTPUT_CD_R 2
#define OUTPUT_CD_L 4
#define OUTPUT_LINE_R 8
#define OUTPUT_LINE_L 16
int input_selector_left;
int input_selector_right;
#define INPUT_MIC 1
#define INPUT_CD_R 2
#define INPUT_CD_L 4
#define INPUT_LINE_R 8
#define INPUT_LINE_L 16
#define INPUT_MIDI_R 32
#define INPUT_MIDI_L 64
int mic_agc;
int32_t input_gain_L;
int32_t input_gain_R;
int32_t output_gain_L;
int32_t output_gain_R;
uint8_t index;
uint8_t regs[256];
} sb_ct1745_mixer_t;
typedef struct sb_t
{
uint8_t opl_enabled;
opl_t opl;
sb_dsp_t dsp;
union {
sb_ct1335_mixer_t mixer_sb2;
sb_ct1345_mixer_t mixer_sbpro;
sb_ct1745_mixer_t mixer_sb16;
};
mpu_t *mpu;
emu8k_t emu8k;
int pos;
uint8_t pos_regs[8];
int opl_emu;
} sb_t;
/* 0 to 7 -> -14dB to 0dB i 2dB steps. 8 to 15 -> 0 to +14dB in 2dB steps.
Note that for positive dB values, this is not amplitude, it is amplitude-1. */
const float sb_bass_treble_4bits[]= {
@@ -247,7 +148,7 @@ static void sb_get_buffer_sb2_mixer(int32_t *buffer, int len, void *p)
sb->dsp.pos = 0;
}
static void sb_get_buffer_sbpro(int32_t *buffer, int len, void *p)
void sb_get_buffer_sbpro(int32_t *buffer, int len, void *p)
{
sb_t *sb = (sb_t *)p;
sb_ct1345_mixer_t *mixer = &sb->mixer_sbpro;
@@ -871,8 +772,7 @@ uint8_t sb_ct1745_mixer_read(uint16_t addr, void *p)
if (mixer->index>=0x30 && mixer->index<=0x47)
ret = mixer->regs[mixer->index];
else switch (mixer->index)
{
else switch (mixer->index) {
case 0x00:
ret = mixer->regs[mixer->index];
break;
@@ -918,8 +818,7 @@ uint8_t sb_ct1745_mixer_read(uint16_t addr, void *p)
* Enabling multiple bits enables multiple IRQs.
*/
switch (sb->dsp.sb_irqnum)
{
switch (sb->dsp.sb_irqnum) {
case 2: ret = 1; break;
case 5: ret = 2; break;
case 7: ret = 4; break;
@@ -941,8 +840,7 @@ uint8_t sb_ct1745_mixer_read(uint16_t addr, void *p)
case 1: ret |= 2; break;
case 3: ret |= 8; break;
}
switch (sb->dsp.sb_16_dmanum)
{
switch (sb->dsp.sb_16_dmanum) {
case 5: ret |= 0x20; break;
case 6: ret |= 0x40; break;
case 7: ret |= 0x80; break;
@@ -1002,6 +900,7 @@ uint8_t sb_ct1745_mixer_read(uint16_t addr, void *p)
break;
}
sb_log("CT1745: read REG%02X: %02X\n", mixer->index, ret);
return ret;
}
@@ -1126,7 +1025,7 @@ void *sb_1_init(const device_t *info)
sb->opl_enabled = device_get_config_int("opl");
if (sb->opl_enabled)
opl2_init(&sb->opl);
sb_dsp_init(&sb->dsp, SB1);
sb_dsp_init(&sb->dsp, SB1, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_setaddr(&sb->dsp, addr);
sb_dsp_setirq(&sb->dsp, device_get_config_int("irq"));
sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma"));
@@ -1156,7 +1055,7 @@ void *sb_15_init(const device_t *info)
sb->opl_enabled = device_get_config_int("opl");
if (sb->opl_enabled)
opl2_init(&sb->opl);
sb_dsp_init(&sb->dsp, SB15);
sb_dsp_init(&sb->dsp, SB15, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_setaddr(&sb->dsp, addr);
sb_dsp_setirq(&sb->dsp, device_get_config_int("irq"));
sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma"));
@@ -1185,13 +1084,13 @@ void *sb_mcv_init(const device_t *info)
sb->opl_enabled = device_get_config_int("opl");
if (sb->opl_enabled)
opl2_init(&sb->opl);
sb_dsp_init(&sb->dsp, SB15);
sb_dsp_init(&sb->dsp, SB15, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_setaddr(&sb->dsp, 0);//addr);
sb_dsp_setirq(&sb->dsp, device_get_config_int("irq"));
sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma"));
sound_add_handler(sb_get_buffer_sb2, sb);
/* I/O handlers activated in sb_mcv_write */
mca_add(sb_mcv_read, sb_mcv_write, sb_mcv_feedb, sb);
mca_add(sb_mcv_read, sb_mcv_write, sb_mcv_feedb, NULL, sb);
sb->pos_regs[0] = 0x84;
sb->pos_regs[1] = 0x50;
@@ -1222,7 +1121,7 @@ void *sb_2_init(const device_t *info)
sb->opl_enabled = device_get_config_int("opl");
if (sb->opl_enabled)
opl2_init(&sb->opl);
sb_dsp_init(&sb->dsp, SB2);
sb_dsp_init(&sb->dsp, SB2, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_setaddr(&sb->dsp, addr);
sb_dsp_setirq(&sb->dsp, device_get_config_int("irq"));
sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma"));
@@ -1266,7 +1165,7 @@ void *sb_pro_v1_init(const device_t *info)
sb->opl_enabled = device_get_config_int("opl");
if (sb->opl_enabled)
opl2_init(&sb->opl);
sb_dsp_init(&sb->dsp, SBPRO);
sb_dsp_init(&sb->dsp, SBPRO, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_setaddr(&sb->dsp, addr);
sb_dsp_setirq(&sb->dsp, device_get_config_int("irq"));
sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma"));
@@ -1302,7 +1201,7 @@ void *sb_pro_v2_init(const device_t *info)
sb->opl_enabled = device_get_config_int("opl");
if (sb->opl_enabled)
opl3_init(&sb->opl);
sb_dsp_init(&sb->dsp, SBPRO2);
sb_dsp_init(&sb->dsp, SBPRO2, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_setaddr(&sb->dsp, addr);
sb_dsp_setirq(&sb->dsp, device_get_config_int("irq"));
sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma"));
@@ -1334,13 +1233,13 @@ void *sb_pro_mcv_init(const device_t *info)
sb->opl_enabled = 1;
opl3_init(&sb->opl);
sb_dsp_init(&sb->dsp, SBPRO2);
sb_dsp_init(&sb->dsp, SBPRO2, SB_SUBTYPE_DEFAULT, sb);
sb_ct1345_mixer_reset(sb);
/* I/O handlers activated in sb_mcv_write */
sound_add_handler(sb_get_buffer_sbpro, sb);
/* I/O handlers activated in sb_pro_mcv_write */
mca_add(sb_pro_mcv_read, sb_pro_mcv_write, sb_mcv_feedb, sb);
mca_add(sb_pro_mcv_read, sb_pro_mcv_write, sb_mcv_feedb, NULL, sb);
sb->pos_regs[0] = 0x03;
sb->pos_regs[1] = 0x51;
@@ -1360,7 +1259,7 @@ void *sb_16_init(const device_t *info)
sb->opl_enabled = device_get_config_int("opl");
if (sb->opl_enabled)
opl3_init(&sb->opl);
sb_dsp_init(&sb->dsp, SB16);
sb_dsp_init(&sb->dsp, SB16, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_setaddr(&sb->dsp, addr);
sb_dsp_setirq(&sb->dsp, device_get_config_int("irq"));
sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma"));
@@ -1406,7 +1305,7 @@ void *sb_awe32_init(const device_t *info)
if (sb->opl_enabled)
opl3_init(&sb->opl);
sb_dsp_init(&sb->dsp, SB16 + 1);
sb_dsp_init(&sb->dsp, SB16 + 1, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_setaddr(&sb->dsp, addr);
sb_dsp_setirq(&sb->dsp, device_get_config_int("irq"));
sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma"));

143
src/sound/snd_sb.h Normal file
View File

@@ -0,0 +1,143 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Sound Blaster emulation.
*
* Version: @(#)sound_sb.h 1.0.4 2020/02/17
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* TheCollector1995, <mariogplayer@gmail.com>
*
* Copyright 2008-2018 Sarah Walker.
* Copyright 2016-2018 Miran Grca.
*/
#ifndef SOUND_SND_SB_H
# define SOUND_SND_SB_H
#include "snd_emu8k.h"
#include "snd_mpu401.h"
#include "snd_opl.h"
#include "snd_sb_dsp.h"
#define SADLIB 1 /* No DSP */
#define SB1 2 /* DSP v1.05 */
#define SB15 3 /* DSP v2.00 */
#define SB2 4 /* DSP v2.01 - needed for high-speed DMA */
#define SBPRO 5 /* DSP v3.00 */
#define SBPRO2 6 /* DSP v3.02 + OPL3 */
#define SB16 7 /* DSP v4.05 + OPL3 */
#define SADGOLD 8 /* AdLib Gold */
#define SND_WSS 9 /* Windows Sound System */
#define SND_PAS16 10 /* Pro Audio Spectrum 16 */
/* SB 2.0 CD version */
typedef struct sb_ct1335_mixer_t
{
int32_t master;
int32_t voice;
int32_t fm;
int32_t cd;
uint8_t index;
uint8_t regs[256];
} sb_ct1335_mixer_t;
/* SB PRO */
typedef struct sb_ct1345_mixer_t
{
int32_t master_l, master_r;
int32_t voice_l, voice_r;
int32_t fm_l, fm_r;
int32_t cd_l, cd_r;
int32_t line_l, line_r;
int32_t mic;
/*see sb_ct1745_mixer for values for input selector*/
int32_t input_selector;
int input_filter;
int in_filter_freq;
int output_filter;
int stereo;
int stereo_isleft;
uint8_t index;
uint8_t regs[256];
} sb_ct1345_mixer_t;
/* SB16 and AWE32 */
typedef struct sb_ct1745_mixer_t
{
int32_t master_l, master_r;
int32_t voice_l, voice_r;
int32_t fm_l, fm_r;
int32_t cd_l, cd_r;
int32_t line_l, line_r;
int32_t mic;
int32_t speaker;
int bass_l, bass_r;
int treble_l, treble_r;
int output_selector;
#define OUTPUT_MIC 1
#define OUTPUT_CD_R 2
#define OUTPUT_CD_L 4
#define OUTPUT_LINE_R 8
#define OUTPUT_LINE_L 16
int input_selector_left;
int input_selector_right;
#define INPUT_MIC 1
#define INPUT_CD_R 2
#define INPUT_CD_L 4
#define INPUT_LINE_R 8
#define INPUT_LINE_L 16
#define INPUT_MIDI_R 32
#define INPUT_MIDI_L 64
int mic_agc;
int32_t input_gain_L;
int32_t input_gain_R;
int32_t output_gain_L;
int32_t output_gain_R;
uint8_t index;
uint8_t regs[256];
} sb_ct1745_mixer_t;
typedef struct sb_t
{
uint8_t opl_enabled;
opl_t opl;
sb_dsp_t dsp;
union {
sb_ct1335_mixer_t mixer_sb2;
sb_ct1345_mixer_t mixer_sbpro;
sb_ct1745_mixer_t mixer_sb16;
};
mpu_t *mpu;
emu8k_t emu8k;
int pos;
uint8_t pos_regs[8];
int opl_emu;
} sb_t;
extern void sb_ct1345_mixer_write(uint16_t addr, uint8_t val, void *p);
extern uint8_t sb_ct1345_mixer_read(uint16_t addr, void *p);
extern void sb_ct1345_mixer_reset(sb_t* sb);
extern void sb_get_buffer_sbpro(int32_t *buffer, int len, void *p);
extern void sb_close(void *p);
extern void sb_speed_changed(void *p);
#endif /*SOUND_SND_SB_H*/

View File

@@ -22,8 +22,8 @@
#include "sound.h"
#include "midi.h"
#include "sound.h"
#include "snd_mpu401.h"
#include "snd_sb_dsp.h"
#include "snd_azt2316a.h"
#include "snd_sb.h"
#define ADPCM_4 1
@@ -244,10 +244,16 @@ sb_doreset(sb_dsp_t *dsp)
sb_dsp_reset(dsp);
if (IS_AZTECH(dsp)) {
sb_commands[8] = 1;
sb_commands[9] = 1;
} else {
if (dsp->sb_type==SB16)
sb_commands[8] = 1;
else
sb_commands[8] = -1;
}
for (c = 0; c < 256; c++)
dsp->sb_asp_regs[c] = 0;
@@ -648,6 +654,16 @@ sb_exec_command(sb_dsp_t *dsp)
sb_add_data(dsp, ~dsp->sb_data[0]);
break;
case 0xE1: /* Get DSP version */
if (IS_AZTECH(dsp)) {
if (dsp->sb_subtype == SB_SUBTYPE_CLONE_AZT2316A_0X11) {
sb_add_data(dsp, 0x3);
sb_add_data(dsp, 0x1);
} else if (dsp->sb_subtype == SB_SUBTYPE_CLONE_AZT1605_0X0C) {
sb_add_data(dsp, 0x2);
sb_add_data(dsp, 0x1);
}
break;
}
sb_add_data(dsp, sb_dsp_versions[dsp->sb_type] >> 8);
sb_add_data(dsp, sb_dsp_versions[dsp->sb_type] & 0xff);
break;
@@ -687,6 +703,29 @@ sb_exec_command(sb_dsp_t *dsp)
case 0x07: case 0xFF: /* No, that's not how you program auto-init DMA */
break;
case 0x08: /* ASP get version */
if (IS_AZTECH(dsp)) {
if ((dsp->sb_data[0] == 0x05 || dsp->sb_data[0] == 0x55)&& dsp->sb_subtype == SB_SUBTYPE_CLONE_AZT2316A_0X11)
sb_add_data(dsp, 0x11); /* AZTECH get type, WASHINGTON/latest - according to devkit. E.g.: The one in the Itautec Infoway Multimidia */
else if ((dsp->sb_data[0] == 0x05 || dsp->sb_data[0] == 0x55) && dsp->sb_subtype == SB_SUBTYPE_CLONE_AZT1605_0X0C)
sb_add_data(dsp, 0x0C); /* AZTECH get type, CLINTON - according to devkit. E.g.: The one in the Packard Bell Legend 100CD */
else if (dsp->sb_data[0] == 0x08) {
/* EEPROM address to write followed by byte */
if (dsp->sb_data[1] < 0 || dsp->sb_data[1] >= AZTECH_EEPROM_SIZE)
fatal("AZT EEPROM: out of bounds write to %02X\n", dsp->sb_data[1]);
sb_dsp_log("EEPROM write = %02x\n", dsp->sb_data[2]);
dsp->azt_eeprom[dsp->sb_data[1]] = dsp->sb_data[2];
break;
} else if (dsp->sb_data[0] == 0x07) {
/* EEPROM address to read */
if (dsp->sb_data[1] < 0 || dsp->sb_data[1] >= AZTECH_EEPROM_SIZE)
fatal("AZT EEPROM: out of bounds read to %02X\n", dsp->sb_data[1]);
sb_dsp_log("EEPROM read = %02x\n", dsp->azt_eeprom[dsp->sb_data[1]]);
sb_add_data(dsp, dsp->azt_eeprom[dsp->sb_data[1]]);
break;
} else
sb_dsp_log("AZT2316A: UNKNOWN 0x08 COMMAND: %02X\n", dsp->sb_data[0]); /* 0x08 (when shutting down, driver tries to read 1 byte of response), 0x55, 0x0D, 0x08D seen */
break;
}
if (dsp->sb_type >= SB16)
sb_add_data(dsp, 0x18);
break;
@@ -716,6 +755,17 @@ sb_exec_command(sb_dsp_t *dsp)
case 0x04: case 0x05:
break;
case 0x09: /*AZTECH mode set*/
if (dsp->sb_data[0] == 0x00) {
sb_dsp_log("AZT2316A: WSS MODE!\n");
azt2316a_enable_wss(1, dsp->parent);
} else if (dsp->sb_data[0] == 0x01) {
sb_dsp_log("AZT2316A: SB8PROV2 MODE!\n");
azt2316a_enable_wss(0, dsp->parent);
} else
sb_dsp_log("AZT2316A: UNKNOWN MODE! = %02x\n", dsp->sb_data[0]); // sequences 0x02->0xFF, 0x04->0xFF seen
break;
/* TODO: Some more data about the DSP registeres
* http://the.earth.li/~tfm/oldpage/sb_dsp.html
* http://www.synchrondata.com/pheaven/www/area19.htm
@@ -770,11 +820,24 @@ sb_write(uint16_t a, uint8_t v, void *priv)
if (v == 0x01)
sb_add_data(dsp, 0);
dsp->sb_data_stat++;
} else
} else {
dsp->sb_data[dsp->sb_data_stat++] = v;
if (IS_AZTECH(dsp)) {
/* variable length commands */
if (dsp->sb_command == 0x08 && dsp->sb_data_stat == 1 && dsp->sb_data[0] == 0x08)
sb_commands[dsp->sb_command] = 3;
else if (dsp->sb_command == 0x08 && dsp->sb_data_stat == 1 && dsp->sb_data[0] == 0x07)
sb_commands[dsp->sb_command] = 2;
}
}
if (dsp->sb_data_stat == sb_commands[dsp->sb_command] || sb_commands[dsp->sb_command] == -1) {
sb_exec_command(dsp);
dsp->sb_data_stat = -1;
if (IS_AZTECH(dsp)) {
/* variable length commands */
if (dsp->sb_command == 0x08)
sb_commands[dsp->sb_command] = 1;
}
}
break;
}
@@ -807,19 +870,39 @@ sb_read(uint16_t a, void *priv)
dsp->busy_count = 0;
if (dsp->wb_full || (dsp->busy_count & 2)) {
dsp->wb_full = timer_is_enabled(&dsp->wb_timer);
if (IS_AZTECH(dsp)) {
sb_dsp_log("SB Write Data Aztech read 0x80\n");
return 0x80;
} else {
sb_dsp_log("SB Write Data Creative read 0xff\n");
return 0xff;
}
}
if (IS_AZTECH(dsp)) {
sb_dsp_log("SB Write Data Aztech read 0x00\n");
ret = 0x00;
} else {
sb_dsp_log("SB Write Data Creative read 0x7f\n");
ret = 0x7f;
}
break;
case 0xE: /* Read data ready */
picintc(1 << dsp->sb_irqnum);
dsp->sb_irq8 = dsp->sb_irq16 = 0;
/* Only bit 7 is defined but aztech diagnostics fail if the others are set. Keep the original behavior to not interfere with what's already working. */
if (IS_AZTECH(dsp)) {
sb_dsp_log("SB Read Data Aztech read %02X, Read RP = %d, Read WP = %d\n",(dsp->sb_read_rp == dsp->sb_read_wp) ? 0x00 : 0x80, dsp->sb_read_rp, dsp->sb_read_wp);
ret = (dsp->sb_read_rp == dsp->sb_read_wp) ? 0x00 : 0x80;
} else {
sb_dsp_log("SB Read Data Creative read %02X\n",(dsp->sb_read_rp == dsp->sb_read_wp) ? 0x7f : 0xff);
ret = (dsp->sb_read_rp == dsp->sb_read_wp) ? 0x7f : 0xff;
}
break;
case 0xF: /* 16-bit ack */
dsp->sb_irq16 = 0;
if (!dsp->sb_irq8)
picintc(1 << dsp->sb_irqnum);
sb_dsp_log("SB 16-bit ACK read 0xFF\n");
ret = 0xff;
break;
}
@@ -892,9 +975,11 @@ sb_dsp_input_sysex(void *p, uint8_t *buffer, uint32_t len, int abort)
}
void
sb_dsp_init(sb_dsp_t *dsp, int type)
sb_dsp_init(sb_dsp_t *dsp, int type, int subtype, void *parent)
{
dsp->sb_type = type;
dsp->sb_subtype = subtype;
dsp->parent = parent;
/* Default values. Use sb_dsp_setxxx() methods to change. */
dsp->sb_irqnum = 7;

View File

@@ -1,18 +1,20 @@
#define SADLIB 1 /* No DSP */
#define SB1 2 /* DSP v1.05 */
#define SB15 3 /* DSP v2.00 */
#define SB2 4 /* DSP v2.01 - needed for high-speed DMA */
#define SBPRO 5 /* DSP v3.00 */
#define SBPRO2 6 /* DSP v3.02 + OPL3 */
#define SB16 7 /* DSP v4.05 + OPL3 */
#define SADGOLD 8 /* AdLib Gold */
#define SND_WSS 9 /* Windows Sound System */
#define SND_PAS16 10 /* Pro Audio Spectrum 16 */
#ifndef SOUND_SND_SB_DSP_H
#define SOUND_SND_SB_DSP_H
/*Sound Blaster Clones, for quirks*/
#define SB_SUBTYPE_DEFAULT 0 /*Handle as a Creative card*/
#define SB_SUBTYPE_CLONE_AZT2316A_0X11 1 /*Aztech Sound Galaxy Pro 16 AB, DSP 3.1 - SBPRO2 clone*/
#define SB_SUBTYPE_CLONE_AZT1605_0X0C 2 /*Aztech Sound Galaxy Nova 16 Extra / Packard Bell Forte 16, DSP 2.1 - SBPRO2 clone*/
/* aztech-related */
#define IS_AZTECH(dsp) ((dsp)->sb_subtype == SB_SUBTYPE_CLONE_AZT2316A_0X11 || (dsp)->sb_subtype == SB_SUBTYPE_CLONE_AZT1605_0X0C) /* check for future AZT cards here */
#define AZTECH_EEPROM_SIZE 16
typedef struct sb_dsp_t
{
int sb_type;
int sb_subtype; /* which clone */
void *parent; /* "sb_t *" if default subtype, "azt2316a_t *" if aztech. */
int sb_8_length, sb_8_format, sb_8_autoinit, sb_8_pause, sb_8_enable, sb_8_autolen, sb_8_output;
int sb_8_dmanum;
@@ -87,6 +89,8 @@ typedef struct sb_dsp_t
int16_t record_buffer[0xFFFF];
int16_t buffer[SOUNDBUFLEN * 2];
int pos;
uint8_t azt_eeprom[AZTECH_EEPROM_SIZE]; /* the eeprom in the Aztech cards is attached to the DSP */
} sb_dsp_t;
@@ -96,7 +100,7 @@ int sb_dsp_input_sysex(void *p, uint8_t *buffer, uint32_t len, int abort);
void sb_dsp_set_mpu(mpu_t *src_mpu);
void sb_dsp_init(sb_dsp_t *dsp, int type);
void sb_dsp_init(sb_dsp_t *dsp, int type, int subtype, void *parent);
void sb_dsp_close(sb_dsp_t *dsp);
void sb_dsp_setirq(sb_dsp_t *dsp, int irq);
@@ -111,4 +115,5 @@ void sb_dsp_poll(sb_dsp_t *dsp, int16_t *l, int16_t *r);
void sb_dsp_set_stereo(sb_dsp_t *dsp, int stereo);
void sb_dsp_update(sb_dsp_t *dsp);
void sb_irqc(sb_dsp_t *dsp, int irq8);
#endif /* SOUND_SND_SB_DSP_H */

View File

@@ -48,7 +48,6 @@
static int wss_dma[4] = {0, 0, 1, 3};
static int wss_irq[8] = {5, 7, 9, 10, 11, 12, 14, 15}; /*W95 only uses 7-9, others may be wrong*/
typedef struct wss_t
{
uint8_t config;
@@ -80,13 +79,11 @@ void wss_write(uint16_t addr, uint8_t val, void *p)
static void wss_get_buffer(int32_t *buffer, int len, void *p)
{
wss_t *wss = (wss_t *)p;
int c;
opl3_update2(&wss->opl);
ad1848_update(&wss->ad1848);
for (c = 0; c < len * 2; c++)
{
for (c = 0; c < len * 2; c++) {
buffer[c] += wss->opl.buffer[c];
buffer[c] += (wss->ad1848.buffer[c] / 2);
}
@@ -103,8 +100,10 @@ void *wss_init(const device_t *info)
uint16_t addr = device_get_config_hex16("base");
wss->opl_enabled = device_get_config_int("opl");
if (wss->opl_enabled)
opl3_init(&wss->opl);
ad1848_init(&wss->ad1848);
ad1848_init(&wss->ad1848, AD1848_TYPE_DEFAULT);
ad1848_setirq(&wss->ad1848, 7);
ad1848_setdma(&wss->ad1848, 3);
@@ -143,12 +142,9 @@ static void ncr_audio_mca_write(int port, uint8_t val, void *p)
io_removehandler(addr, 0x0004, wss_read, NULL, NULL, wss_write, NULL, NULL, wss);
io_removehandler(addr+4, 0x0004, ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &wss->ad1848);
//pclog("WSS MCA: opl=%d, addr=%03x\n", wss->opl_enabled, addr);
wss->pos_regs[port & 7] = val;
if (wss->pos_regs[2] & 1)
{
if (wss->pos_regs[2] & 1) {
addr = ports[(wss->pos_regs[2] & 0x18) >> 3];
if (wss->opl_enabled)
@@ -173,12 +169,12 @@ void *ncr_audio_init(const device_t *info)
memset(wss, 0, sizeof(wss_t));
opl3_init(&wss->opl);
ad1848_init(&wss->ad1848);
ad1848_init(&wss->ad1848, AD1848_TYPE_DEFAULT);
ad1848_setirq(&wss->ad1848, 7);
ad1848_setdma(&wss->ad1848, 3);
mca_add(ncr_audio_mca_read, ncr_audio_mca_write, ncr_audio_mca_feedb, wss);
mca_add(ncr_audio_mca_read, ncr_audio_mca_write, ncr_audio_mca_feedb, NULL, wss);
wss->pos_regs[0] = 0x16;
wss->pos_regs[1] = 0x51;

View File

@@ -34,6 +34,7 @@
#include "snd_opl.h"
#include "snd_mpu401.h"
#include "snd_sb_dsp.h"
#include "snd_azt2316a.h"
#include "filters.h"
@@ -80,6 +81,8 @@ static const SOUND_CARD sound_cards[] =
{ "None", "none", NULL },
{ "[ISA] Adlib", "adlib", &adlib_device },
{ "[ISA] Adlib Gold", "adlibgold", &adgold_device },
{ "[ISA] Aztech Sound Galaxy Pro 16 AB (Washington)", "azt2316a", &azt2316a_device },
{ "[ISA] Aztech Sound Galaxy Nova 16 Extra (Clinton)", "azt1605", &azt1605_device },
{ "[ISA] Sound Blaster 1.0", "sb", &sb_1_device },
{ "[ISA] Sound Blaster 1.5", "sb1.5", &sb_15_device },
{ "[ISA] Sound Blaster 2.0", "sb2.0", &sb_2_device },

View File

@@ -73,6 +73,10 @@ extern const device_t adlib_device;
extern const device_t adlib_mca_device;
extern const device_t adgold_device;
/* Aztech Sound Galaxy 16 */
extern const device_t azt2316a_device;
extern const device_t azt1605_device;
/* Ensoniq AudioPCI */
extern const device_t es1371_device;

View File

@@ -3127,7 +3127,7 @@ static void
if (gd54xx->mca) {
gd54xx->pos_regs[0] = 0x7b;
gd54xx->pos_regs[1] = 0x91;
mca_add(gd5428_mca_read, gd5428_mca_write, gd5428_mca_feedb, gd54xx);
mca_add(gd5428_mca_read, gd5428_mca_write, gd5428_mca_feedb, NULL, gd54xx);
}
return gd54xx;

View File

@@ -512,7 +512,7 @@ et4000_init(const device_t *info)
et4000_in,NULL,NULL, et4000_out,NULL,NULL, dev);
dev->pos_regs[0] = 0xf2; /* ET4000 MCA board ID */
dev->pos_regs[1] = 0x80;
mca_add(et4000_mca_read, et4000_mca_write, et4000_mca_feedb, dev);
mca_add(et4000_mca_read, et4000_mca_write, et4000_mca_feedb, NULL, dev);
break;
case 2: /* Korean ET4000 */

View File

@@ -673,6 +673,7 @@ SNDOBJ := sound.o \
snd_pssj.o \
snd_lpt_dac.o snd_lpt_dss.o \
snd_adlib.o snd_adlibgold.o snd_ad1848.o snd_audiopci.o \
snd_azt2316a.o \
snd_cms.o \
snd_gus.o \
snd_sb.o snd_sb_dsp.o \

View File

@@ -678,6 +678,7 @@ SNDOBJ := sound.o \
snd_pssj.o \
snd_lpt_dac.o snd_lpt_dss.o \
snd_adlib.o snd_adlibgold.o snd_ad1848.o snd_audiopci.o \
snd_azt2316a.o \
snd_cms.o \
snd_gus.o \
snd_sb.o snd_sb_dsp.o \