The ViBRA 16 XV now correctly does 16-bit DMA over 8-bit channels and fixed the DSP versions as well.

This commit is contained in:
OBattler
2023-10-20 21:02:35 +02:00
parent b53a81019d
commit 9c434f4ed0
4 changed files with 120 additions and 49 deletions

View File

@@ -25,15 +25,18 @@
#include <86box/snd_opl.h>
#include <86box/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 SBAWE32 8 /* DSP v4.13 + OPL3 */
#define SBAWE64 9 /* DSP v4.16 + OPL3 */
enum {
SADLIB = 1, /* No DSP */
SB1, /* DSP v1.05 */
SB15, /* DSP v2.00 */
SB2, /* DSP v2.01 - needed for high-speed DMA */
SBPRO, /* DSP v3.00 */
SBPRO2, /* DSP v3.02 + OPL3 */
SB16, /* DSP v4.05 + OPL3 */
SBAWE32, /* DSP v4.12 + OPL3 */
SBAWE32PNP, /* DSP v4.13 + OPL3 */
SBAWE64 /* DSP v4.16 + OPL3 */
};
/* SB 2.0 CD version */
typedef struct sb_ct1335_mixer_t {

View File

@@ -127,40 +127,43 @@ typedef struct sb_dsp_t {
int16_t buffer[SOUNDBUFLEN * 2];
int pos;
uint8_t dma16through8;
uint8_t azt_eeprom[AZTECH_EEPROM_SIZE]; /* the eeprom in the Aztech cards is attached to the DSP */
mpu_t *mpu;
} sb_dsp_t;
void sb_dsp_input_msg(void *priv, uint8_t *msg, uint32_t len);
extern void sb_dsp_input_msg(void *priv, uint8_t *msg, uint32_t len);
int sb_dsp_input_sysex(void *priv, uint8_t *buffer, uint32_t len, int abort);
extern int sb_dsp_input_sysex(void *priv, uint8_t *buffer, uint32_t len, int abort);
void sb_dsp_set_mpu(sb_dsp_t *dsp, mpu_t *src_mpu);
extern void sb_dsp_set_mpu(sb_dsp_t *dsp, mpu_t *src_mpu);
void sb_dsp_init(sb_dsp_t *dsp, int type, int subtype, void *parent);
void sb_dsp_close(sb_dsp_t *dsp);
extern void sb_dsp_init(sb_dsp_t *dsp, int type, int subtype, void *parent);
extern void sb_dsp_close(sb_dsp_t *dsp);
void sb_dsp_setirq(sb_dsp_t *dsp, int irq);
void sb_dsp_setdma8(sb_dsp_t *dsp, int dma);
void sb_dsp_setdma16(sb_dsp_t *dsp, int dma);
void sb_dsp_setaddr(sb_dsp_t *dsp, uint16_t addr);
extern void sb_dsp_setirq(sb_dsp_t *dsp, int irq);
extern void sb_dsp_setdma8(sb_dsp_t *dsp, int dma);
extern void sb_dsp_setdma16(sb_dsp_t *dsp, int dma);
extern void sb_dsp_setdma16through8(sb_dsp_t *dsp, int dma16through8);
extern void sb_dsp_setaddr(sb_dsp_t *dsp, uint16_t addr);
void sb_dsp_speed_changed(sb_dsp_t *dsp);
extern void sb_dsp_speed_changed(sb_dsp_t *dsp);
void sb_dsp_poll(sb_dsp_t *dsp, int16_t *l, int16_t *r);
extern 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);
extern void sb_dsp_set_stereo(sb_dsp_t *dsp, int stereo);
void sb_dsp_update(sb_dsp_t *dsp);
void sb_update_mask(sb_dsp_t *dsp, int irqm8, int irqm16, int irqm401);
extern void sb_dsp_update(sb_dsp_t *dsp);
extern void sb_update_mask(sb_dsp_t *dsp, int irqm8, int irqm16, int irqm401);
void sb_dsp_irq_attach(sb_dsp_t *dsp, void (*irq_update)(void *priv, int set), void *priv);
void sb_dsp_dma_attach(sb_dsp_t *dsp,
int (*dma_readb)(void *priv),
int (*dma_readw)(void *priv),
int (*dma_writeb)(void *priv, uint8_t val),
int (*dma_writew)(void *priv, uint16_t val),
void *priv);
extern void sb_dsp_irq_attach(sb_dsp_t *dsp, void (*irq_update)(void *priv, int set), void *priv);
extern void sb_dsp_dma_attach(sb_dsp_t *dsp,
int (*dma_readb)(void *priv),
int (*dma_readw)(void *priv),
int (*dma_writeb)(void *priv, uint8_t val),
int (*dma_writew)(void *priv, uint16_t val),
void *priv);
#endif /* SOUND_SND_SB_DSP_H */

View File

@@ -839,12 +839,21 @@ sb_ct1745_mixer_write(uint16_t addr, uint8_t val, void *priv)
sb_dsp_setdma8(&sb->dsp, 1);
if (val & 0x08)
sb_dsp_setdma8(&sb->dsp, 3);
if (val & 0x20)
sb_dsp_setdma16(&sb->dsp, 5);
if (val & 0x40)
sb_dsp_setdma16(&sb->dsp, 6);
if (val & 0x80)
sb_dsp_setdma16(&sb->dsp, 7);
if (sb->dsp.dma16through8) {
if (val & 0x10)
sb_dsp_setdma16(&sb->dsp, 0);
if (val & 0x20)
sb_dsp_setdma16(&sb->dsp, 1);
if (val & 0x80)
sb_dsp_setdma16(&sb->dsp, 3);
} else {
if (val & 0x20)
sb_dsp_setdma16(&sb->dsp, 5);
if (val & 0x40)
sb_dsp_setdma16(&sb->dsp, 6);
if (val & 0x80)
sb_dsp_setdma16(&sb->dsp, 7);
}
break;
case 0x83:
@@ -1023,7 +1032,20 @@ sb_ct1745_mixer_read(uint16_t addr, void *priv)
default:
break;
}
switch (sb->dsp.sb_16_dmanum) {
if (sb->dsp.dma16through8) switch (sb->dsp.sb_16_dmanum) {
case 0:
ret |= 0x10;
break;
case 1:
ret |= 0x20;
break;
case 3:
ret |= 0x80;
break;
default:
break;
} else switch (sb->dsp.sb_16_dmanum) {
case 5:
ret |= 0x20;
break;
@@ -1041,8 +1063,8 @@ sb_ct1745_mixer_read(uint16_t addr, void *priv)
case 0x82:
/* 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. */
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. */
/* 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. */
@@ -2078,7 +2100,7 @@ sb_16_init(UNUSED(const device_t *info))
if (sb->opl_enabled)
fm_driver_get(info->local, &sb->opl);
sb_dsp_init(&sb->dsp, SB16, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_init(&sb->dsp, (info->local == FM_YMF289B) ? SBAWE32PNP : 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"));
@@ -2227,7 +2249,10 @@ sb_vibra16_pnp_init(UNUSED(const device_t *info))
sb->opl_enabled = 1;
fm_driver_get(FM_YMF262, &sb->opl);
sb_dsp_init(&sb->dsp, SB16, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_init(&sb->dsp, (info->local == 0) ? SBAWE64 : SBAWE32PNP, SB_SUBTYPE_DEFAULT, sb);
/* The ViBRA 16XV does 16-bit DMA through 8-bit DMA. */
if (info->local == 0)
sb_dsp_setdma16through8(&sb->dsp, 1);
sb_ct1745_mixer_reset(sb);
sb->mixer_enabled = 1;
@@ -2428,7 +2453,8 @@ sb_awe32_pnp_init(const device_t *info)
sb->opl_enabled = 1;
fm_driver_get(FM_YMF262, &sb->opl);
sb_dsp_init(&sb->dsp, ((info->local == 2) || (info->local == 3) || (info->local == 4)) ? SBAWE64 : SBAWE32, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_init(&sb->dsp, ((info->local == 2) || (info->local == 3) || (info->local == 4)) ?
SBAWE64 : SBAWE32PNP, SB_SUBTYPE_DEFAULT, sb);
sb_ct1745_mixer_reset(sb);
sb->mixer_enabled = 1;

View File

@@ -65,7 +65,7 @@ static int sb_commands[256] = {
};
char sb16_copyright[] = "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992.";
uint16_t sb_dsp_versions[] = { 0, 0, 0x105, 0x200, 0x201, 0x300, 0x302, 0x405, 0x40d, 0x410 };
uint16_t sb_dsp_versions[] = { 0, 0, 0x105, 0x200, 0x201, 0x300, 0x302, 0x405, 0x40c, 0x40d, 0x410 };
/*These tables were 'borrowed' from DOSBox*/
int8_t scaleMap4[64] = {
@@ -427,16 +427,45 @@ int
sb_16_read_dma(void *priv)
{
const sb_dsp_t *dsp = (sb_dsp_t *) priv;
int temp, ret = 0;
int dma_flags;
return dma_channel_read(dsp->sb_16_dmanum);
if (dsp->dma16through8) {
temp = dma_channel_read(dsp->sb_16_dmanum);
ret = temp;
if ((temp != DMA_NODATA) && !(temp & DMA_OVER)) {
temp = dma_channel_read(dsp->sb_16_dmanum);
if (temp == DMA_NODATA)
ret = DMA_NODATA;
else {
dma_flags = temp & DMA_OVER;
temp &= ~DMA_OVER;
ret |= (temp << 8) | dma_flags;
}
}
} else
ret = dma_channel_read(dsp->sb_16_dmanum);
return ret;
}
int
sb_16_write_dma(void *priv, uint16_t val)
{
const sb_dsp_t *dsp = (sb_dsp_t *) priv;
int temp, ret = 0;
if (dsp->dma16through8) {
temp = dma_channel_write(dsp->sb_16_dmanum, val & 0xff);
ret = temp;
if ((temp != DMA_NODATA) && (temp != DMA_OVER)) {
temp = dma_channel_write(dsp->sb_16_dmanum, val >> 8);
ret = temp;
}
} else
ret = dma_channel_write(dsp->sb_16_dmanum, val) == DMA_NODATA;
return dma_channel_write(dsp->sb_16_dmanum, val) == DMA_NODATA;
return ret;
}
void
@@ -445,6 +474,12 @@ sb_dsp_setirq(sb_dsp_t *dsp, int irq)
dsp->sb_irqnum = irq;
}
void
sb_dsp_setdma16through8(sb_dsp_t *dsp, int dma16through8)
{
dsp->dma16through8 = dma16through8;
}
void
sb_dsp_setdma8(sb_dsp_t *dsp, int dma)
{
@@ -670,7 +705,8 @@ sb_exec_command(sb_dsp_t *dsp)
case 0xB6:
case 0xB7: /* 16-bit DMA output */
if (dsp->sb_type >= SB16) {
sb_start_dma(dsp, 0, dsp->sb_command & 4, dsp->sb_data[0], dsp->sb_data[1] + (dsp->sb_data[2] << 8));
sb_start_dma(dsp, 0, dsp->sb_command & 4, dsp->sb_data[0],
dsp->sb_data[1] + (dsp->sb_data[2] << 8));
dsp->sb_16_autolen = dsp->sb_data[1] + (dsp->sb_data[2] << 8);
}
break;
@@ -683,7 +719,8 @@ sb_exec_command(sb_dsp_t *dsp)
case 0xBE:
case 0xBF: /* 16-bit DMA input */
if (dsp->sb_type >= SB16) {
sb_start_dma_i(dsp, 0, dsp->sb_command & 4, dsp->sb_data[0], dsp->sb_data[1] + (dsp->sb_data[2] << 8));
sb_start_dma_i(dsp, 0, dsp->sb_command & 4, dsp->sb_data[0],
dsp->sb_data[1] + (dsp->sb_data[2] << 8));
dsp->sb_16_autolen = dsp->sb_data[1] + (dsp->sb_data[2] << 8);
}
break;
@@ -696,7 +733,8 @@ sb_exec_command(sb_dsp_t *dsp)
case 0xC6:
case 0xC7: /* 8-bit DMA output */
if (dsp->sb_type >= SB16) {
sb_start_dma(dsp, 1, dsp->sb_command & 4, dsp->sb_data[0], dsp->sb_data[1] + (dsp->sb_data[2] << 8));
sb_start_dma(dsp, 1, dsp->sb_command & 4, dsp->sb_data[0],
dsp->sb_data[1] + (dsp->sb_data[2] << 8));
dsp->sb_8_autolen = dsp->sb_data[1] + (dsp->sb_data[2] << 8);
}
break;
@@ -709,7 +747,8 @@ sb_exec_command(sb_dsp_t *dsp)
case 0xCE:
case 0xCF: /* 8-bit DMA input */
if (dsp->sb_type >= SB16) {
sb_start_dma_i(dsp, 1, dsp->sb_command & 4, dsp->sb_data[0], dsp->sb_data[1] + (dsp->sb_data[2] << 8));
sb_start_dma_i(dsp, 1, dsp->sb_command & 4, dsp->sb_data[0],
dsp->sb_data[1] + (dsp->sb_data[2] << 8));
dsp->sb_8_autolen = dsp->sb_data[1] + (dsp->sb_data[2] << 8);
}
break;