ESS AudioDrive: Fix some mixer register and DSP command readouts to match the probing of real cards, also fixes Windows 3.1 ES688 drivers.
This commit is contained in:
@@ -1452,9 +1452,6 @@ ess_mixer_write(uint16_t addr, uint8_t val, void *priv)
|
||||
if (!(addr & 1)) {
|
||||
mixer->index = val;
|
||||
mixer->regs[0x01] = val;
|
||||
if (val == 0x40) {
|
||||
mixer->ess_id_str_pos = 0;
|
||||
}
|
||||
} else {
|
||||
if (mixer->index == 0) {
|
||||
/* Reset */
|
||||
@@ -1473,6 +1470,8 @@ ess_mixer_write(uint16_t addr, uint8_t val, void *priv)
|
||||
mixer->regs[0x3c] = 0x05;
|
||||
mixer->regs[0x3e] = 0x00;
|
||||
|
||||
mixer->regs[0x64] = 0x08;
|
||||
|
||||
sb_dsp_set_stereo(&ess->dsp, mixer->regs[0x0e] & 2);
|
||||
} else {
|
||||
mixer->regs[mixer->index] = val;
|
||||
@@ -1525,6 +1524,7 @@ ess_mixer_write(uint16_t addr, uint8_t val, void *priv)
|
||||
break;
|
||||
|
||||
case 0x1C:
|
||||
mixer->regs[mixer->index] = val & 0x2f;
|
||||
if ((mixer->regs[0x1C] & 0x07) == 0x07) {
|
||||
mixer->input_selector = INPUT_MIXER_L | INPUT_MIXER_R;
|
||||
} else if ((mixer->regs[0x1C] & 0x07) == 0x06) {
|
||||
@@ -1556,12 +1556,12 @@ ess_mixer_write(uint16_t addr, uint8_t val, void *priv)
|
||||
break;
|
||||
|
||||
case 0x64:
|
||||
mixer->regs[mixer->index] = (mixer->regs[mixer->index] & 0xf7) | 0x20;
|
||||
// mixer->regs[mixer->index] &= ~0x8;
|
||||
if (ess->dsp.sb_subtype > SB_SUBTYPE_ESS_ES1688)
|
||||
mixer->regs[mixer->index] = (mixer->regs[mixer->index] & 0xf7) | 0x20;
|
||||
break;
|
||||
|
||||
case 0x40:
|
||||
{
|
||||
if (ess->dsp.sb_subtype >= SB_SUBTYPE_ESS_ES1688) {
|
||||
uint16_t mpu401_base_addr = 0x300 | ((mixer->regs[0x40] << 1) & 0x30);
|
||||
sb_log("mpu401_base_addr = %04X\n", mpu401_base_addr);
|
||||
|
||||
@@ -1572,7 +1572,7 @@ ess_mixer_write(uint16_t addr, uint8_t val, void *priv)
|
||||
|
||||
gameport_remap(ess->gameport, !(mixer->regs[0x40] & 0x2) ? 0x00 : 0x200);
|
||||
|
||||
if (ess->dsp.sb_subtype != SB_SUBTYPE_ESS_ES1688) {
|
||||
if (ess->dsp.sb_subtype > SB_SUBTYPE_ESS_ES1688) {
|
||||
/* Not on ES1688. */
|
||||
io_removehandler(0x0388, 0x0004,
|
||||
ess->opl.read, NULL, NULL,
|
||||
@@ -1585,6 +1585,7 @@ ess_mixer_write(uint16_t addr, uint8_t val, void *priv)
|
||||
ess->opl.priv);
|
||||
}
|
||||
}
|
||||
|
||||
if (ess->mpu != NULL) switch ((mixer->regs[0x40] >> 5) & 0x7) {
|
||||
default:
|
||||
break;
|
||||
@@ -1627,11 +1628,12 @@ ess_mixer_write(uint16_t addr, uint8_t val, void *priv)
|
||||
ess_fm_midi_read, NULL, NULL,
|
||||
ess_fm_midi_write, NULL, NULL,
|
||||
ess);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
sb_log("ess: Unknown mixer register WRITE: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]);
|
||||
sb_log("ess: Unknown mixer register WRITE: %02X\t%02X\n",
|
||||
mixer->index, mixer->regs[mixer->index]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1667,6 +1669,7 @@ ess_mixer_read(uint16_t addr, void *priv)
|
||||
case 0x0c:
|
||||
case 0x0e:
|
||||
case 0x14:
|
||||
case 0x1a:
|
||||
case 0x02:
|
||||
case 0x06:
|
||||
case 0x30:
|
||||
@@ -1685,28 +1688,56 @@ ess_mixer_read(uint16_t addr, void *priv)
|
||||
ret = mixer->regs[mixer->index] | 0x11;
|
||||
break;
|
||||
|
||||
case 0x40:
|
||||
if (ess->dsp.sb_subtype == SB_SUBTYPE_ESS_ES1688)
|
||||
ret = mixer->regs[mixer->index];
|
||||
else
|
||||
ret = 0x0a;
|
||||
/* Bit 1 always set, bits 7-6 always clear on both the real ES688 and ES1688. */
|
||||
case 0x1c:
|
||||
ret = mixer->regs[mixer->index] | 0x10;
|
||||
break;
|
||||
|
||||
case 0x48:
|
||||
ret = mixer->regs[mixer->index];
|
||||
break;
|
||||
/*
|
||||
Real ES688: Always 0x00;
|
||||
Real ES1688: Bit 2 always clear.
|
||||
*/
|
||||
case 0x40:
|
||||
if (ess->dsp.sb_subtype > SB_SUBTYPE_ESS_ES1688)
|
||||
ret = mixer->regs[mixer->index];
|
||||
else if (ess->dsp.sb_subtype >= SB_SUBTYPE_ESS_ES1688)
|
||||
ret = mixer->regs[mixer->index] & 0xfb;
|
||||
else
|
||||
ret = 0x00;
|
||||
break;
|
||||
|
||||
/* Return 0x00 so it has bit 3 clear, so NT 5.x drivers don't misdetect it as ES1788. */
|
||||
/*
|
||||
Real ES688: Always 0x00;
|
||||
Real ES1688: All bits writable.
|
||||
*/
|
||||
case 0x48:
|
||||
if (ess->dsp.sb_subtype >= SB_SUBTYPE_ESS_ES1688)
|
||||
ret = mixer->regs[mixer->index];
|
||||
else
|
||||
ret = 0x00;
|
||||
break;
|
||||
|
||||
/*
|
||||
Return 0x00 so it has bit 3 clear, so NT 5.x drivers don't misdetect it as ES1788.
|
||||
Bit 3 set and writable: ESSCFG detects the card as ES1788 if register 70h is read-only,
|
||||
otherwise, as ES1887.
|
||||
Bit 3 set and read-only: ESSCFG detects the card as ES1788 if register 70h is read-only,
|
||||
otherwise, as ES1888.
|
||||
Real ES688 and ES1688: Always 0x00.
|
||||
*/
|
||||
case 0x64:
|
||||
ret = (mixer->regs[mixer->index] & 0xf7) | 0x20;
|
||||
if (ess->dsp.sb_subtype > SB_SUBTYPE_ESS_ES1688)
|
||||
ret = (mixer->regs[mixer->index] & 0xf7) | 0x20;
|
||||
else
|
||||
ret = 0x00;
|
||||
break;
|
||||
|
||||
default:
|
||||
sb_log("ess: Unknown mixer register READ: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]);
|
||||
sb_log("ess: Unknown mixer register READ: %02X\t%02X\n", mixer->index, mixer->regs[miwinxer->index]);
|
||||
break;
|
||||
}
|
||||
|
||||
sb_log("[%04X:%08X] [R] %04X = %02X\n", CS, cpu_state.pc, addr, ret);
|
||||
sb_log("[%04X:%08X] [R] %04X = %02X (%02X)\n", CS, cpu_state.pc, addr, ret, mixer->index);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -2268,9 +2299,6 @@ ess_x688_pnp_config_changed(UNUSED(const uint8_t ld), isapnp_device_config_t *co
|
||||
ess_base_write, NULL, NULL,
|
||||
ess);
|
||||
|
||||
ess->mixer_ess.ess_id_str[2] = 0x00;
|
||||
ess->mixer_ess.ess_id_str[3] = 0x00;
|
||||
|
||||
addr = ess->opl_pnp_addr;
|
||||
if (addr) {
|
||||
ess->opl_pnp_addr = 0;
|
||||
@@ -2337,9 +2365,6 @@ ess_x688_pnp_config_changed(UNUSED(const uint8_t ld), isapnp_device_config_t *co
|
||||
ess_base_read, NULL, NULL,
|
||||
ess_base_write, NULL, NULL,
|
||||
ess);
|
||||
|
||||
ess->mixer_ess.ess_id_str[2] = (addr >> 8) & 0xff;
|
||||
ess->mixer_ess.ess_id_str[3] = addr & 0xff;
|
||||
}
|
||||
|
||||
addr = config->io[1].base;
|
||||
@@ -3748,11 +3773,6 @@ ess_x688_init(UNUSED(const device_t *info))
|
||||
midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &ess->dsp);
|
||||
|
||||
if (info->local) {
|
||||
ess->mixer_ess.ess_id_str[0] = 0x16;
|
||||
ess->mixer_ess.ess_id_str[1] = 0x88;
|
||||
ess->mixer_ess.ess_id_str[2] = (addr >> 8) & 0xff;
|
||||
ess->mixer_ess.ess_id_str[3] = addr & 0xff;
|
||||
|
||||
ess->mpu = (mpu_t *) calloc(1, sizeof(mpu_t));
|
||||
/* NOTE: The MPU is initialized disabled and with no IRQ assigned.
|
||||
* It will be later initialized by the guest OS's drivers. */
|
||||
@@ -3818,12 +3838,6 @@ ess_x688_pnp_init(UNUSED(const device_t *info))
|
||||
if (device_get_config_int("receive_input"))
|
||||
midi_in_handler(1, sb_dsp_input_msg, sb_dsp_input_sysex, &ess->dsp);
|
||||
|
||||
/* Not on ES688. */
|
||||
ess->mixer_ess.ess_id_str[0] = 0x16;
|
||||
ess->mixer_ess.ess_id_str[1] = 0x88;
|
||||
ess->mixer_ess.ess_id_str[2] = 0x00;
|
||||
ess->mixer_ess.ess_id_str[3] = 0x00;
|
||||
|
||||
ess->mpu = (mpu_t *) calloc(1, sizeof(mpu_t));
|
||||
/* NOTE: The MPU is initialized disabled and with no IRQ assigned.
|
||||
* It will be later initialized by the guest OS's drivers. */
|
||||
|
||||
@@ -1687,6 +1687,10 @@ sb_exec_command(sb_dsp_t *dsp)
|
||||
break;
|
||||
case 0xE1: /* Get DSP version */
|
||||
if (IS_ESS(dsp)) {
|
||||
/*
|
||||
0x03 0x01 (Sound Blaster Pro compatibility) confirmed by both the
|
||||
ES1888 datasheet and the probing of the real ES688 and ES1688 cards.
|
||||
*/
|
||||
sb_add_data(dsp, 0x3);
|
||||
sb_add_data(dsp, 0x1);
|
||||
break;
|
||||
@@ -1722,9 +1726,12 @@ sb_exec_command(sb_dsp_t *dsp)
|
||||
while (sb16_copyright[c])
|
||||
sb_add_data(dsp, sb16_copyright[c++]);
|
||||
sb_add_data(dsp, 0);
|
||||
} else if (IS_ESS(dsp)) {
|
||||
sb_add_data(dsp, 0);
|
||||
}
|
||||
} /* else if (IS_ESS(dsp))
|
||||
sb_add_data(dsp, 0); */
|
||||
/*
|
||||
TODO: What ESS card returns 0x00 here? Probing of the real ES688 and ES1688 cards
|
||||
revealed that they in fact return nothing on this command.
|
||||
*/
|
||||
break;
|
||||
case 0xE4: /* Write test register */
|
||||
dsp->sb_test = dsp->sb_data[0];
|
||||
@@ -1736,12 +1743,26 @@ sb_exec_command(sb_dsp_t *dsp)
|
||||
break;
|
||||
case SB_SUBTYPE_ESS_ES688:
|
||||
sb_add_data(dsp, 0x68);
|
||||
sb_add_data(dsp, 0x80 | 0x04);
|
||||
/*
|
||||
80h: ESSCFG fails to detect the AudioDrive;
|
||||
81h-83h: ES??88, Windows 3.1 driver expects MPU-401 and gives a legacy mixer error;
|
||||
84h: ES688, Windows 3.1 driver expects MPU-401, returned by DOSBox-X;
|
||||
85h-87h: ES688, Windows 3.1 driver does not expect MPU-401:
|
||||
85h: Returned by MSDOS622's real ESS688,
|
||||
86h: Returned by Dizzy's real ES688.
|
||||
We return 86h if MPU is absent, 84h otherwise, who knows what the actual
|
||||
PnP ES688 returns here.
|
||||
*/
|
||||
sb_add_data(dsp, 0x80 | ((dsp->mpu != NULL) ? 0x04 : 0x06));
|
||||
break;
|
||||
case SB_SUBTYPE_ESS_ES1688:
|
||||
// Determined via Windows driver debugging.
|
||||
sb_add_data(dsp, 0x68);
|
||||
sb_add_data(dsp, 0x80 | 0x09);
|
||||
/*
|
||||
89h: ES1688, returned by DOSBox-X, determined via Windows driver
|
||||
debugging;
|
||||
8Bh: ES1688, returned by both MSDOS622's and Dizzy's real ES1688's.
|
||||
*/
|
||||
sb_add_data(dsp, 0x80 | 0x0b);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user