diff --git a/src/sound/snd_ess.c b/src/sound/snd_ess.c
index a97d5e244..0193c69c9 100644
--- a/src/sound/snd_ess.c
+++ b/src/sound/snd_ess.c
@@ -6,16 +6,20 @@
*
* This file is part of the 86Box distribution.
*
- * Sound Blaster emulation.
+ * ESS AudioDrive emulation.
*
*
*
* Authors: Sarah Walker,
* Miran Grca,
* TheCollector1995,
+ * Cacodemon345,
+ * Kagamiin~,
*
* Copyright 2008-2020 Sarah Walker.
* Copyright 2016-2020 Miran Grca.
+ * Copyright 2024 Cacodemon345
+ * Copyright 2024 Kagamiin~
*/
#include
#include
@@ -79,7 +83,7 @@ typedef struct ess_mixer_t {
uint8_t regs[256];
uint8_t ess_id_str[256];
- uint8_t ess_id_str_pos : 2;
+ uint8_t ess_id_str_pos;
} ess_mixer_t;
typedef struct ess_t {
@@ -130,7 +134,10 @@ ess_mixer_write(uint16_t addr, uint8_t val, void *priv)
mixer->index = val;
mixer->regs[0x01] = val;
if (val == 0x40)
+ {
+ pclog("ess: Mixer addr 0x40 selected, ID string offset reset\n");
mixer->ess_id_str_pos = 0;
+ }
} else {
if (mixer->index == 0) {
/* Reset */
@@ -151,7 +158,7 @@ ess_mixer_write(uint16_t addr, uint8_t val, void *priv)
sb_dsp_set_stereo(&ess->dsp, mixer->regs[0x0e] & 2);
} else {
mixer->regs[mixer->index] = val;
- pclog("ess: Register WRITE: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]);
+ pclog("ess: Mixer Register WRITE: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]);
switch (mixer->index) {
/* Compatibility: chain registers 0x02 and 0x22 as well as 0x06 and 0x26 */
@@ -198,23 +205,27 @@ ess_mixer_write(uint16_t addr, uint8_t val, void *priv)
break;
case 0x40: {
- break;
- uint16_t mpu401_base_addr = 0x300 | ((mixer->regs[0x40] & 0x38) << 1);
- gameport_remap(ess->gameport, !(mixer->regs[0x40] & 0x2) ? 0x00 : 0x200);
- /* This doesn't work yet. */
- /*
- io_removehandler(0x0388, 0x0004,
- ess->opl.read, NULL, NULL,
- ess->opl.write, NULL, NULL,
- ess->opl.priv);
- if (mixer->regs[0x40] & 1) {
- io_sethandler(0x0388, 0x0004,
- ess->opl.read, NULL, NULL,
- ess->opl.write, NULL, NULL,
- ess->opl.priv);
- }*/
+ /* TODO: Implement "Read-Sequence-Key" method of software address selection
+ * (needed for ESSCFG.EXE to work properly) */
- switch ((mixer->regs[0x40] >> 5) & 7) {
+ uint16_t mpu401_base_addr = 0x300 | ((mixer->regs[0x40] << 1) & 0x30);
+ gameport_remap(ess->gameport, !(mixer->regs[0x40] & 0x2) ? 0x00 : 0x200);
+
+ /* This doesn't work yet. */
+#if 1
+ io_removehandler(0x0388, 0x0004,
+ ess->opl.read, NULL, NULL,
+ ess->opl.write, NULL, NULL,
+ ess->opl.priv);
+ if ((mixer->regs[0x40] & 0x1) != 0)
+ {
+ io_sethandler(0x0388, 0x0004,
+ ess->opl.read, NULL, NULL,
+ ess->opl.write, NULL, NULL,
+ ess->opl.priv);
+ }
+#endif
+ switch ((mixer->regs[0x40] >> 5) & 0x7) {
case 0:
mpu401_change_addr(ess->mpu, 0x00);
mpu401_setirq(ess->mpu, -1);
@@ -252,7 +263,7 @@ ess_mixer_write(uint16_t addr, uint8_t val, void *priv)
}
default:
- pclog("ess: Unknown register WRITE: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]);
+ pclog("ess: Unknown mixer register WRITE: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]);
break;
}
}
@@ -320,21 +331,22 @@ ess_mixer_read(uint16_t addr, void *priv)
case 0x36:
case 0x38:
case 0x3e:
- pclog("ess: Register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]);
+ pclog("ess: Mixer Register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]);
return mixer->regs[mixer->index];
case 0x40:
{
uint8_t val = mixer->ess_id_str[mixer->ess_id_str_pos];
+ uint8_t pos_log = mixer->ess_id_str_pos; /* TODO remove */
mixer->ess_id_str_pos++;
if (mixer->ess_id_str_pos >= 4)
mixer->ess_id_str_pos = 0;
- pclog("ess: ID READ: %02X (pos %d)\n", val, mixer->ess_id_str_pos);
+ pclog("ess: ID READ: %02X (pos %d)\n", val, pos_log);
return val;
}
default:
- pclog("ess: Unknown register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]);
+ pclog("ess: Unknown mixer register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]);
break;
}
@@ -491,7 +503,7 @@ ess_1688_init(UNUSED(const device_t *info))
}
ess->mpu = (mpu_t *) calloc(1, sizeof(mpu_t));
- mpu401_init(ess->mpu, 0, 0, M_UART, 1);
+ mpu401_init(ess->mpu, 0, -1, M_UART, 1);
sb_dsp_set_mpu(&ess->dsp, ess->mpu);
ess->gameport = gameport_add(&gameport_pnp_device);
@@ -620,4 +632,4 @@ const device_t ess_1688_device = {
.speed_changed = ess_speed_changed,
.force_redraw = NULL,
.config = ess_config
-};
\ No newline at end of file
+};
diff --git a/src/sound/snd_sb_dsp.c b/src/sound/snd_sb_dsp.c
index 44d9d0950..d14b41d9e 100644
--- a/src/sound/snd_sb_dsp.c
+++ b/src/sound/snd_sb_dsp.c
@@ -582,6 +582,37 @@ sb_16_write_dma(void *priv, uint16_t val)
return ret;
}
+void
+sb_ess_update_irq_drq_readback_regs(sb_dsp_t *dsp, bool legacy)
+{
+ uint8_t t = 0x00;
+ /* IRQ control */
+ if (legacy)
+ {
+ t |= 0x80;
+ }
+ switch (dsp->sb_irqnum) {
+ case 5: t |= 0x5; break;
+ case 7: t |= 0xA; break;
+ case 10: t |= 0xF; break;
+ }
+ pclog("ESSreg 0xB1 was %02X, irqnum is %d, t is %02X; new 0xB1 is %02X\n", ESSreg(0xB1), dsp->sb_irqnum, t, (ESSreg(0xB1) & 0xF0) | t);
+ ESSreg(0xB1) = (ESSreg(0xB1) & 0xF0) | t;
+
+ /* DRQ control */
+ t = 0x00;
+ if (legacy)
+ {
+ t |= 0x80;
+ }
+ switch (dsp->sb_8_dmanum) {
+ case 0: t |= 0x5; break;
+ case 1: t |= 0xA; break;
+ case 3: t |= 0xF; break;
+ }
+ ESSreg(0xB2) = (ESSreg(0xB2) & 0xF0) | t;
+}
+
void
sb_dsp_setirq(sb_dsp_t *dsp, int irq)
{
@@ -589,23 +620,7 @@ sb_dsp_setirq(sb_dsp_t *dsp, int irq)
sb_dsp_log("IRQ now: %i\n", irq);
dsp->sb_irqnum = irq;
- /* legacy audio interrupt control */
- t = 0x80;/*game compatible IRQ*/
- switch (dsp->sb_irqnum) {
- case 5: t |= 0x5; break;
- case 7: t |= 0xA; break;
- case 10: t |= 0xF; break;
- }
- ESSreg(0xB1) = t;
-
- /* DRQ control */
- t = 0x80;/*game compatible DRQ */
- switch (dsp->sb_8_dmanum) {
- case 0: t |= 0x5; break;
- case 1: t |= 0xA; break;
- case 3: t |= 0xF; break;
- }
- ESSreg(0xB2) = t;
+ sb_ess_update_irq_drq_readback_regs(dsp, true);
}
void
@@ -615,23 +630,7 @@ sb_dsp_setdma8(sb_dsp_t *dsp, int dma)
sb_dsp_log("8-bit DMA now: %i\n", dma);
dsp->sb_8_dmanum = dma;
- /* legacy audio interrupt control */
- t = 0x80;/*game compatible IRQ*/
- switch (dsp->sb_irqnum) {
- case 5: t |= 0x5; break;
- case 7: t |= 0xA; break;
- case 10: t |= 0xF; break;
- }
- ESSreg(0xB1) = t;
-
- /* DRQ control */
- t = 0x80;/*game compatible DRQ */
- switch (dsp->sb_8_dmanum) {
- case 0: t |= 0x5; break;
- case 1: t |= 0xA; break;
- case 3: t |= 0xF; break;
- }
- ESSreg(0xB2) = t;
+ sb_ess_update_irq_drq_readback_regs(dsp, true);
}
void
@@ -686,6 +685,7 @@ static uint8_t sb_ess_read_reg(sb_dsp_t *dsp, uint8_t reg)
{
switch (reg) {
default:
+ pclog("ESS register read reg=%02xh val=%02xh\n",reg, ESSreg(reg));
return ESSreg(reg);
}
@@ -752,9 +752,43 @@ static void sb_ess_write_reg(sb_dsp_t *dsp, uint8_t reg, uint8_t data)
break;
case 0xB1: /* Legacy Audio Interrupt Control */
+ ESSreg(reg) = (ESSreg(reg) & 0x0F) + (data & 0xF0); // lower 4 bits not writeable
+ switch (data & 0x0C)
+ {
+ case 0x00:
+ dsp->sb_irqnum = 2;
+ break;
+ case 0x04:
+ dsp->sb_irqnum = 5;
+ break;
+ case 0x08:
+ dsp->sb_irqnum = 7;
+ break;
+ case 0x0C:
+ dsp->sb_irqnum = 10;
+ break;
+ }
+ sb_ess_update_irq_drq_readback_regs(dsp, false);
+ break;
case 0xB2: /* DRQ Control */
chg = ESSreg(reg) ^ data;
ESSreg(reg) = (ESSreg(reg) & 0x0F) + (data & 0xF0); // lower 4 bits not writeable
+ switch (data & 0x0C)
+ {
+ case 0x00:
+ dsp->sb_8_dmanum = -1;
+ break;
+ case 0x04:
+ dsp->sb_8_dmanum = 0;
+ break;
+ case 0x08:
+ dsp->sb_8_dmanum = 1;
+ break;
+ case 0x0C:
+ dsp->sb_8_dmanum = 3;
+ break;
+ }
+ sb_ess_update_irq_drq_readback_regs(dsp, false);
if (chg & 0x40) sb_ess_update_dma_status(dsp);
break;
case 0xB5: /* DAC Direct Access Holding (low) */