Added the Aztech Sound Galaxy 16 cards.

Added the reset function of MCA from PCem.
Made the MCA devices use the reset parameter if available.
This commit is contained in:
TC1995
2020-03-25 00:49:25 +01:00
parent 1fd4040945
commit 6f4ac0de35
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;
@@ -17,62 +18,72 @@ static int mca_nr_cards;
void mca_init(int nr_cards)
{
int c;
int 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;
}
for (c = 0; c < 8; c++)
{
mca_card_read[c] = NULL;
mca_card_write[c] = NULL;
mca_priv[c] = NULL;
}
mca_index = 0;
mca_nr_cards = nr_cards;
mca_index = 0;
mca_nr_cards = nr_cards;
}
void mca_set_index(int index)
{
mca_index = index;
mca_index = index;
}
uint8_t mca_read(uint16_t port)
{
if (mca_index >= mca_nr_cards)
return 0xff;
if (!mca_card_read[mca_index])
return 0xff;
return mca_card_read[mca_index](port, mca_priv[mca_index]);
if (mca_index >= mca_nr_cards)
return 0xff;
if (!mca_card_read[mca_index])
return 0xff;
return mca_card_read[mca_index](port, mca_priv[mca_index]);
}
void mca_write(uint16_t port, uint8_t val)
{
if (mca_index >= mca_nr_cards)
return;
if (mca_card_write[mca_index])
mca_card_write[mca_index](port, val, mca_priv[mca_index]);
if (mca_index >= mca_nr_cards)
return;
if (mca_card_write[mca_index])
mca_card_write[mca_index](port, val, mca_priv[mca_index]);
}
uint8_t mca_feedb(void)
{
if (mca_card_feedb[mca_index])
return !!(mca_card_feedb[mca_index](mca_priv[mca_index]));
else
return 0;
if (mca_card_feedb[mca_index])
return !!(mca_card_feedb[mca_index](mca_priv[mca_index]));
else
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])
{
mca_card_read[c] = read;
mca_card_write[c] = write;
mca_card_feedb[c] = feedb;
mca_priv[c] = priv;
return;
}
}
int 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;
ad1848->regs[12] = 0xa;
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);
}
timer_add(&ad1848->timer_count, ad1848_poll, ad1848, 0);
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;
@@ -860,149 +761,147 @@ void sb_ct1745_mixer_write(uint16_t addr, uint8_t val, void *p)
uint8_t sb_ct1745_mixer_read(uint16_t addr, void *p)
{
sb_t *sb = (sb_t *)p;
sb_ct1745_mixer_t *mixer = &sb->mixer_sb16;
sb_t *sb = (sb_t *)p;
sb_ct1745_mixer_t *mixer = &sb->mixer_sb16;
uint8_t temp, ret = 0xff;
if (!(addr & 1))
ret = mixer->index;
if (!(addr & 1))
ret = mixer->index;
sb_log("sb_ct1745: received register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]);
sb_log("sb_ct1745: received register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]);
if (mixer->index>=0x30 && mixer->index<=0x47)
ret = mixer->regs[mixer->index];
else switch (mixer->index)
{
case 0x00:
ret = mixer->regs[mixer->index];
break;
if (mixer->index>=0x30 && mixer->index<=0x47)
ret = mixer->regs[mixer->index];
else switch (mixer->index) {
case 0x00:
ret = mixer->regs[mixer->index];
break;
/*SB Pro compatibility*/
case 0x04:
ret = ((mixer->regs[0x33] >> 4) & 0x0f) | (mixer->regs[0x32] & 0xf0);
break;
case 0x0a:
// ret = (mixer->regs[0x3a] - 10) / 3;
ret = (mixer->regs[0x3a] >> 5);
break;
case 0x02:
ret = ((mixer->regs[0x30] >> 4) & 0x0f);
break;
case 0x06:
ret = ((mixer->regs[0x34] >> 4) & 0x0f);
break;
case 0x08:
ret = ((mixer->regs[0x36] >> 4) & 0x0f);
break;
case 0x22:
ret = ((mixer->regs[0x31] >> 4) & 0x0f) | (mixer->regs[0x30] & 0xf0);
break;
case 0x26:
ret = ((mixer->regs[0x35] >> 4) & 0x0f) | (mixer->regs[0x34] & 0xf0);
break;
case 0x28:
ret = ((mixer->regs[0x37] >> 4) & 0x0f) | (mixer->regs[0x36] & 0xf0);
break;
case 0x2e:
ret = ((mixer->regs[0x39] >> 4) & 0x0f) | (mixer->regs[0x38] & 0xf0);
break;
/*SB Pro compatibility*/
case 0x04:
ret = ((mixer->regs[0x33] >> 4) & 0x0f) | (mixer->regs[0x32] & 0xf0);
break;
case 0x0a:
// ret = (mixer->regs[0x3a] - 10) / 3;
ret = (mixer->regs[0x3a] >> 5);
break;
case 0x02:
ret = ((mixer->regs[0x30] >> 4) & 0x0f);
break;
case 0x06:
ret = ((mixer->regs[0x34] >> 4) & 0x0f);
break;
case 0x08:
ret = ((mixer->regs[0x36] >> 4) & 0x0f);
break;
case 0x22:
ret = ((mixer->regs[0x31] >> 4) & 0x0f) | (mixer->regs[0x30] & 0xf0);
break;
case 0x26:
ret = ((mixer->regs[0x35] >> 4) & 0x0f) | (mixer->regs[0x34] & 0xf0);
break;
case 0x28:
ret = ((mixer->regs[0x37] >> 4) & 0x0f) | (mixer->regs[0x36] & 0xf0);
break;
case 0x2e:
ret = ((mixer->regs[0x39] >> 4) & 0x0f) | (mixer->regs[0x38] & 0xf0);
break;
case 0x48:
// Undocumented. The Creative Windows Mixer calls this after calling 3C (input selector). even when writing.
// Also, the version I have (5.17) does not use the MIDI.L/R input selectors. it uses the volume to mute (Affecting the output, obviously)
ret = mixer->regs[mixer->index];
break;
case 0x48:
// Undocumented. The Creative Windows Mixer calls this after calling 3C (input selector). even when writing.
// Also, the version I have (5.17) does not use the MIDI.L/R input selectors. it uses the volume to mute (Affecting the output, obviously)
ret = mixer->regs[mixer->index];
break;
case 0x80:
/*TODO: Unaffected by mixer reset or soft reboot.
* Enabling multiple bits enables multiple IRQs.
*/
case 0x80:
/*TODO: Unaffected by mixer reset or soft reboot.
* Enabling multiple bits enables multiple IRQs.
*/
switch (sb->dsp.sb_irqnum)
{
case 2: ret = 1; break;
case 5: ret = 2; break;
case 7: ret = 4; break;
case 10: ret = 8; break;
}
break;
switch (sb->dsp.sb_irqnum) {
case 2: ret = 1; break;
case 5: ret = 2; break;
case 7: ret = 4; break;
case 10: ret = 8; break;
}
break;
case 0x81:
/* TODO: Unaffected by mixer reset or soft reboot.
* Enabling multiple 8 or 16-bit DMA bits enables multiple DMA channels.
* Disabling all 8-bit DMA channel bits disables 8-bit DMA requests,
including translated 16-bit DMA requests.
* Disabling all 16-bit DMA channel bits enables translation of 16-bit DMA
requests to 8-bit ones, using the selected 8-bit DMA channel.*/
case 0x81:
/* TODO: Unaffected by mixer reset or soft reboot.
* Enabling multiple 8 or 16-bit DMA bits enables multiple DMA channels.
* Disabling all 8-bit DMA channel bits disables 8-bit DMA requests,
including translated 16-bit DMA requests.
* Disabling all 16-bit DMA channel bits enables translation of 16-bit DMA
requests to 8-bit ones, using the selected 8-bit DMA channel.*/
ret = 0;
switch (sb->dsp.sb_8_dmanum) {
case 0: ret |= 1; break;
case 1: ret |= 2; break;
case 3: ret |= 8; break;
}
switch (sb->dsp.sb_16_dmanum)
{
case 5: ret |= 0x20; break;
case 6: ret |= 0x40; break;
case 7: ret |= 0x80; break;
}
break;
ret = 0;
switch (sb->dsp.sb_8_dmanum) {
case 0: ret |= 1; break;
case 1: ret |= 2; break;
case 3: ret |= 8; break;
}
switch (sb->dsp.sb_16_dmanum) {
case 5: ret |= 0x20; break;
case 6: ret |= 0x40; break;
case 7: ret |= 0x80; break;
}
break;
/* The Interrupt status register, addressed as register 82h on the Mixer register map,
/* The Interrupt status register, addressed as register 82h on the Mixer register map,
is used by the ISR to determine whether the interrupt is meant for it or for some other ISR,
in which case it should chain to the previous routine.
*/
case 0x82:
/* 0 = none, 1 = digital 8bit or SBMIDI, 2 = digital 16bit, 4 = MPU-401 */
/* 0x02000 DSP v4.04, 0x4000 DSP v4.05 0x8000 DSP v4.12. I haven't seen this making any difference, but I'm keeping it for now. */
temp = ((sb->dsp.sb_irq8) ? 1 : 0) | ((sb->dsp.sb_irq16) ? 2 : 0) | 0x4000;
if (sb->mpu)
temp |= ((sb->mpu->state.irq_pending) ? 4 : 0);
ret = temp;
break;
in which case it should chain to the previous routine.
*/
case 0x82:
/* 0 = none, 1 = digital 8bit or SBMIDI, 2 = digital 16bit, 4 = MPU-401 */
/* 0x02000 DSP v4.04, 0x4000 DSP v4.05 0x8000 DSP v4.12. I haven't seen this making any difference, but I'm keeping it for now. */
temp = ((sb->dsp.sb_irq8) ? 1 : 0) | ((sb->dsp.sb_irq16) ? 2 : 0) | 0x4000;
if (sb->mpu)
temp |= ((sb->mpu->state.irq_pending) ? 4 : 0);
ret = temp;
break;
case 0x83:
/* Interrupt mask. */
ret = mixer->regs[mixer->index];
break;
/* Interrupt mask. */
ret = mixer->regs[mixer->index];
break;
case 0x84:
/* MPU Control. */
if (sb->mpu == NULL)
ret = 0x02;
else {
if (sb->mpu->addr == 0x330)
ret = 0x00;
else if (sb->mpu->addr == 0x300)
ret = 0x04;
else if (sb->mpu->addr == 0)
/* MPU Control. */
if (sb->mpu == NULL)
ret = 0x02;
else
ret = 0x06; /* Should never happen. */
}
break;
else {
if (sb->mpu->addr == 0x330)
ret = 0x00;
else if (sb->mpu->addr == 0x300)
ret = 0x04;
else if (sb->mpu->addr == 0)
ret = 0x02;
else
ret = 0x06; /* Should never happen. */
}
break;
case 0x90:
/* 3D Enhancement switch. */
ret = mixer->regs[mixer->index];
break;
/* 3D Enhancement switch. */
ret = mixer->regs[mixer->index];
break;
/* TODO: creative drivers read and write on 0xFE and 0xFF. not sure what they are supposed to be. */
case 0xfd:
ret = 16;
break;
case 0xfd:
ret = 16;
break;
case 0xfe:
ret = 6;
break;
ret = 6;
break;
default:
sb_log("sb_ct1745: Unknown register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]);
break;
}
default:
sb_log("sb_ct1745: Unknown register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]);
break;
}
return ret;
sb_log("CT1745: read REG%02X: %02X\n", mixer->index, ret);
return ret;
}
void sb_ct1745_mixer_reset(sb_t* sb)
@@ -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 (dsp->sb_type==SB16)
sb_commands[8] = 1;
else
sb_commands[8] = -1;
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);
return 0xff;
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;
}
ret = 0x7f;
break;
case 0xE: /* Read data ready */
picintc(1 << dsp->sb_irqnum);
dsp->sb_irq8 = dsp->sb_irq16 = 0;
ret = (dsp->sb_read_rp == dsp->sb_read_wp) ? 0x7f : 0xff;
/* 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,92 +1,96 @@
#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_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;
int sb_16_length, sb_16_format, sb_16_autoinit, sb_16_pause, sb_16_enable, sb_16_autolen, sb_16_output;
int sb_16_dmanum;
int sb_pausetime;
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;
int sb_16_length, sb_16_format, sb_16_autoinit, sb_16_pause, sb_16_enable, sb_16_autolen, sb_16_output;
int sb_16_dmanum;
int sb_pausetime;
uint8_t sb_read_data[256];
int sb_read_wp, sb_read_rp;
int sb_speaker;
int muted;
uint8_t sb_read_data[256];
int sb_read_wp, sb_read_rp;
int sb_speaker;
int muted;
int sb_data_stat;
int midi_in_sysex;
int midi_in_poll;
int uart_midi;
int uart_irq;
int onebyte_midi;
int midi_in_timestamp;
int sb_data_stat;
int sb_irqnum;
int midi_in_sysex;
int midi_in_poll;
int uart_midi;
int uart_irq;
int onebyte_midi;
int midi_in_timestamp;
uint8_t sbe2;
int sbe2count;
int sb_irqnum;
uint8_t sb_data[8];
uint8_t sbe2;
int sbe2count;
int sb_freq;
uint8_t sb_data[8];
int sb_freq;
int16_t sbdat;
int sbdat2;
int16_t sbdatl, sbdatr;
int16_t sbdat;
int sbdat2;
int16_t sbdatl, sbdatr;
uint8_t sbref;
int8_t sbstep;
uint8_t sbref;
int8_t sbstep;
int sbdacpos;
int sbdacpos;
int sbleftright;
int sbleftright;
int sbreset;
uint8_t sbreaddat;
uint8_t sb_command;
uint8_t sb_test;
int sb_timei, sb_timeo;
int sbreset;
uint8_t sbreaddat;
uint8_t sb_command;
uint8_t sb_test;
int sb_timei, sb_timeo;
int sb_irq8, sb_irq16;
int sb_irqm8, sb_irqm16;
int sb_irq8, sb_irq16;
int sb_irqm8, sb_irqm16;
uint8_t sb_asp_regs[256];
uint8_t sb_asp_regs[256];
int sbenable, sb_enable_i;
int sbenable, sb_enable_i;
pc_timer_t output_timer, input_timer;
pc_timer_t output_timer, input_timer;
uint64_t sblatcho, sblatchi;
uint16_t sb_addr;
int stereo;
int asp_data_len;
pc_timer_t wb_timer;
int wb_full;
uint64_t sblatcho, sblatchi;
uint16_t sb_addr;
int stereo;
int asp_data_len;
pc_timer_t wb_timer;
int wb_full;
int busy_count;
int record_pos_read;
int record_pos_write;
int16_t record_buffer[0xFFFF];
int16_t buffer[SOUNDBUFLEN * 2];
int pos;
int record_pos_read;
int record_pos_write;
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,76 +48,75 @@
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;
uint8_t config;
ad1848_t ad1848;
opl_t opl;
int opl_enabled;
uint8_t pos_regs[8];
ad1848_t ad1848;
opl_t opl;
int opl_enabled;
uint8_t pos_regs[8];
} wss_t;
uint8_t wss_read(uint16_t addr, void *p)
{
wss_t *wss = (wss_t *)p;
uint8_t temp;
temp = 4 | (wss->config & 0x40);
return temp;
wss_t *wss = (wss_t *)p;
uint8_t temp;
temp = 4 | (wss->config & 0x40);
return temp;
}
void wss_write(uint16_t addr, uint8_t val, void *p)
{
wss_t *wss = (wss_t *)p;
wss_t *wss = (wss_t *)p;
wss->config = val;
ad1848_setdma(&wss->ad1848, wss_dma[val & 3]);
ad1848_setirq(&wss->ad1848, wss_irq[(val >> 3) & 7]);
wss->config = val;
ad1848_setdma(&wss->ad1848, wss_dma[val & 3]);
ad1848_setirq(&wss->ad1848, wss_irq[(val >> 3) & 7]);
}
static void wss_get_buffer(int32_t *buffer, int len, void *p)
{
wss_t *wss = (wss_t *)p;
wss_t *wss = (wss_t *)p;
int c;
opl3_update2(&wss->opl);
ad1848_update(&wss->ad1848);
for (c = 0; c < len * 2; c++)
{
buffer[c] += wss->opl.buffer[c];
buffer[c] += (wss->ad1848.buffer[c] / 2);
}
opl3_update2(&wss->opl);
ad1848_update(&wss->ad1848);
for (c = 0; c < len * 2; c++) {
buffer[c] += wss->opl.buffer[c];
buffer[c] += (wss->ad1848.buffer[c] / 2);
}
wss->opl.pos = 0;
wss->ad1848.pos = 0;
wss->opl.pos = 0;
wss->ad1848.pos = 0;
}
void *wss_init(const device_t *info)
{
wss_t *wss = malloc(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);
ad1848_init(&wss->ad1848);
ad1848_setirq(&wss->ad1848, 7);
ad1848_setdma(&wss->ad1848, 3);
wss_t *wss = malloc(sizeof(wss_t));
memset(wss, 0, sizeof(wss_t));
if (wss->opl_enabled)
io_sethandler(0x0388, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &wss->opl);
uint16_t addr = device_get_config_hex16("base");
wss->opl_enabled = device_get_config_int("opl");
if (wss->opl_enabled)
opl3_init(&wss->opl);
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);
ad1848_init(&wss->ad1848, AD1848_TYPE_DEFAULT);
ad1848_setirq(&wss->ad1848, 7);
ad1848_setdma(&wss->ad1848, 3);
if (wss->opl_enabled)
io_sethandler(0x0388, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &wss->opl);
return wss;
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);
return wss;
}
static uint8_t ncr_audio_mca_read(int port, void *p)
@@ -129,10 +128,10 @@ static uint8_t ncr_audio_mca_read(int port, void *p)
static void ncr_audio_mca_write(int port, uint8_t val, void *p)
{
wss_t *wss = (wss_t *)p;
wss_t *wss = (wss_t *)p;
uint16_t ports[4] = {0x530, 0xE80, 0xF40, 0x604};
uint16_t addr;
if (port < 0x102)
return;
@@ -142,15 +141,12 @@ static void ncr_audio_mca_write(int port, uint8_t val, void *p)
io_removehandler(0x0388, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &wss->opl);
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)
io_sethandler(0x0388, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &wss->opl);
@@ -168,37 +164,37 @@ static uint8_t ncr_audio_mca_feedb(void *p)
void *ncr_audio_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));
opl3_init(&wss->opl);
ad1848_init(&wss->ad1848);
opl3_init(&wss->opl);
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;
sound_add_handler(wss_get_buffer, wss);
return wss;
sound_add_handler(wss_get_buffer, wss);
return wss;
}
void wss_close(void *p)
{
wss_t *wss = (wss_t *)p;
free(wss);
wss_t *wss = (wss_t *)p;
free(wss);
}
void wss_speed_changed(void *p)
{
wss_t *wss = (wss_t *)p;
ad1848_speed_changed(&wss->ad1848);
wss_t *wss = (wss_t *)p;
ad1848_speed_changed(&wss->ad1848);
}
static const device_config_t wss_config[] =

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 \