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:
@@ -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,
|
||||
|
87
src/mca.c
87
src/mca.c
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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);
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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");
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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
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
1
src/sound/snd_azt2316a.h
Normal file
@@ -0,0 +1 @@
|
||||
extern void azt2316a_enable_wss(uint8_t enable, void *p);
|
@@ -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. */
|
||||
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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
143
src/sound/snd_sb.h
Normal 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*/
|
@@ -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;
|
||||
|
@@ -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 */
|
@@ -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[] =
|
||||
|
@@ -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 },
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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 */
|
||||
|
@@ -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 \
|
||||
|
@@ -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 \
|
||||
|
Reference in New Issue
Block a user