Some cleanup, implementing IRQ and DMA channel register update

This commit is contained in:
Kagamiin~
2024-03-05 21:22:15 -03:00
parent b8ff131996
commit c76ada30b7
2 changed files with 105 additions and 59 deletions

View File

@@ -6,16 +6,20 @@
*
* This file is part of the 86Box distribution.
*
* Sound Blaster emulation.
* ESS AudioDrive emulation.
*
*
*
* Authors: Sarah Walker, <https://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* TheCollector1995, <mariogplayer@gmail.com>
* Cacodemon345,
* Kagamiin~, <kagamiin@riseup.net>
*
* Copyright 2008-2020 Sarah Walker.
* Copyright 2016-2020 Miran Grca.
* Copyright 2024 Cacodemon345
* Copyright 2024 Kagamiin~
*/
#include <stdarg.h>
#include <stdint.h>
@@ -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
};
};

View File

@@ -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) */