ESS: implement mixer regs and fix ESS-specific DMA
This commit is contained in:
@@ -22,6 +22,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <wchar.h>
|
||||
#define HAVE_STDARG_H
|
||||
|
||||
@@ -122,6 +123,11 @@ static inline uint8_t expand16to32(const uint8_t t) {
|
||||
return (t << 1) | (t >> 3);
|
||||
}
|
||||
|
||||
static double ess_mixer_get_vol_4bit(uint8_t vol)
|
||||
{
|
||||
return (48.0 + (20.0 * log((vol & 0xF) / 15.0))) / 48.0;
|
||||
}
|
||||
|
||||
void
|
||||
ess_mixer_write(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
@@ -142,6 +148,14 @@ ess_mixer_write(uint16_t addr, uint8_t val, void *priv)
|
||||
mixer->regs[0x04] = mixer->regs[0x22] = 0xee;
|
||||
mixer->regs[0x26] = mixer->regs[0x28] = 0xee;
|
||||
mixer->regs[0x2e] = 0x00;
|
||||
|
||||
/* Initialize ESS regs. */
|
||||
mixer->regs[0x14] = mixer->regs[0x32] = 0x88;
|
||||
mixer->regs[0x36] = 0x88;
|
||||
mixer->regs[0x38] = 0x00;
|
||||
mixer->regs[0x3a] = 0x00;
|
||||
mixer->regs[0x3e] = 0x00;
|
||||
|
||||
sb_dsp_set_stereo(&ess->dsp, mixer->regs[0x0e] & 2);
|
||||
} else {
|
||||
mixer->regs[mixer->index] = val;
|
||||
@@ -153,20 +167,29 @@ ess_mixer_write(uint16_t addr, uint8_t val, void *priv)
|
||||
case 0x08:
|
||||
mixer->regs[mixer->index + 0x20] = ((val & 0xe) << 4) | (val & 0xe);
|
||||
break;
|
||||
|
||||
case 0x14:
|
||||
mixer->regs[0x4] = val & 0xee;
|
||||
break;
|
||||
|
||||
case 0x22:
|
||||
case 0x26:
|
||||
case 0x28:
|
||||
case 0x2E:
|
||||
mixer->regs[mixer->index - 0x20] = (val & 0xe);
|
||||
mixer->regs[mixer->index + 0x10] = val;
|
||||
break;
|
||||
|
||||
/* More compatibility:
|
||||
SoundBlaster Pro selects register 020h for 030h, 022h for 032h,
|
||||
026h for 036h, and 028h for 038h. */
|
||||
case 0x30:
|
||||
mixer->regs[mixer->index - 0x10] = (val & 0xee);
|
||||
break;
|
||||
case 0x32:
|
||||
case 0x36:
|
||||
case 0x38:
|
||||
case 0x3e:
|
||||
mixer->regs[mixer->index - 0x10] = (val & 0xee);
|
||||
break;
|
||||
|
||||
@@ -175,25 +198,75 @@ ess_mixer_write(uint16_t addr, uint8_t val, void *priv)
|
||||
case 0x0a:
|
||||
case 0x0c:
|
||||
case 0x0e:
|
||||
case 0x2e:
|
||||
break;
|
||||
|
||||
case 0x40: {
|
||||
uint16_t mpu401_base_addr = 0x300 | ((mixer->regs[0x40] & 0x38) << 1);
|
||||
gameport_remap(ess->gameport, !(mixer->regs[0x40] & 0x2) ? 0x00 : 0x200);
|
||||
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);
|
||||
}
|
||||
|
||||
switch ((mixer->regs[0x40] >> 5) & 7) {
|
||||
case 0:
|
||||
mpu401_change_addr(ess->mpu, 0x00);
|
||||
mpu401_setirq(ess->mpu, -1);
|
||||
break;
|
||||
case 1:
|
||||
mpu401_change_addr(ess->mpu, mpu401_base_addr);
|
||||
mpu401_setirq(ess->mpu, -1);
|
||||
break;
|
||||
case 2:
|
||||
mpu401_change_addr(ess->mpu, mpu401_base_addr);
|
||||
mpu401_setirq(ess->mpu, ess->dsp.sb_irqnum);
|
||||
break;
|
||||
case 3:
|
||||
mpu401_change_addr(ess->mpu, mpu401_base_addr);
|
||||
mpu401_setirq(ess->mpu, 0xE);
|
||||
break;
|
||||
case 4:
|
||||
mpu401_change_addr(ess->mpu, mpu401_base_addr);
|
||||
mpu401_setirq(ess->mpu, 0xA);
|
||||
break;
|
||||
case 5:
|
||||
mpu401_change_addr(ess->mpu, mpu401_base_addr);
|
||||
mpu401_setirq(ess->mpu, 0xB);
|
||||
break;
|
||||
case 6:
|
||||
mpu401_change_addr(ess->mpu, mpu401_base_addr);
|
||||
mpu401_setirq(ess->mpu, 0xC);
|
||||
break;
|
||||
case 7:
|
||||
mpu401_change_addr(ess->mpu, mpu401_base_addr);
|
||||
mpu401_setirq(ess->mpu, 0xD);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
//sb_log("ess: Unknown register WRITE: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mixer->voice_l = sb_att_4dbstep_3bits[(mixer->regs[0x04] >> 5) & 0x7] / 32768.0;
|
||||
mixer->voice_r = sb_att_4dbstep_3bits[(mixer->regs[0x04] >> 1) & 0x7] / 32768.0;
|
||||
mixer->master_l = sb_att_4dbstep_3bits[(mixer->regs[0x22] >> 5) & 0x7] / 32768.0;
|
||||
mixer->master_r = sb_att_4dbstep_3bits[(mixer->regs[0x22] >> 1) & 0x7] / 32768.0;
|
||||
mixer->fm_l = sb_att_4dbstep_3bits[(mixer->regs[0x26] >> 5) & 0x7] / 32768.0;
|
||||
mixer->fm_r = sb_att_4dbstep_3bits[(mixer->regs[0x26] >> 1) & 0x7] / 32768.0;
|
||||
mixer->cd_l = sb_att_4dbstep_3bits[(mixer->regs[0x28] >> 5) & 0x7] / 32768.0;
|
||||
mixer->cd_r = sb_att_4dbstep_3bits[(mixer->regs[0x28] >> 1) & 0x7] / 32768.0;
|
||||
mixer->line_l = sb_att_4dbstep_3bits[(mixer->regs[0x2e] >> 5) & 0x7] / 32768.0;
|
||||
mixer->line_r = sb_att_4dbstep_3bits[(mixer->regs[0x2e] >> 1) & 0x7] / 32768.0;
|
||||
mixer->voice_l = ess_mixer_get_vol_4bit(mixer->regs[0x14]);
|
||||
mixer->voice_r = ess_mixer_get_vol_4bit(mixer->regs[0x14] >> 4);
|
||||
mixer->master_l = ess_mixer_get_vol_4bit(mixer->regs[0x32]);
|
||||
mixer->master_r = ess_mixer_get_vol_4bit(mixer->regs[0x32] >> 4);
|
||||
mixer->fm_l = ess_mixer_get_vol_4bit(mixer->regs[0x36]);
|
||||
mixer->fm_r = ess_mixer_get_vol_4bit(mixer->regs[0x36] >> 4);
|
||||
mixer->cd_l = ess_mixer_get_vol_4bit(mixer->regs[0x38]);
|
||||
mixer->cd_r = ess_mixer_get_vol_4bit(mixer->regs[0x38] >> 4);
|
||||
mixer->line_l = ess_mixer_get_vol_4bit(mixer->regs[0x3e]);
|
||||
mixer->line_r = ess_mixer_get_vol_4bit(mixer->regs[0x3e] >> 4);
|
||||
|
||||
mixer->mic = sb_att_7dbstep_2bits[(mixer->regs[0x0a] >> 1) & 0x3] / 32768.0;
|
||||
|
||||
@@ -372,6 +445,8 @@ ess_1688_init(UNUSED(const device_t *info))
|
||||
sb_dsp_setaddr(&ess->dsp, addr);
|
||||
sb_dsp_setirq(&ess->dsp, device_get_config_int("irq"));
|
||||
sb_dsp_setdma8(&ess->dsp, device_get_config_int("dma"));
|
||||
sb_dsp_setdma16_8(&ess->dsp, device_get_config_int("dma"));
|
||||
sb_dsp_setdma16_supported(&ess->dsp, 0);
|
||||
ess_mixer_reset(ess);
|
||||
/* DSP I/O handler is activated in sb_dsp_setaddr */
|
||||
{
|
||||
@@ -408,6 +483,14 @@ ess_1688_init(UNUSED(const device_t *info))
|
||||
ess->mixer_sbpro.ess_id_str[3] = addr & 0xff;
|
||||
}
|
||||
|
||||
ess->mpu = (mpu_t *) calloc(1, sizeof(mpu_t));
|
||||
mpu401_init(ess->mpu, 0, 0, M_UART, 1);
|
||||
sb_dsp_set_mpu(&ess->dsp, ess->mpu);
|
||||
|
||||
ess->gameport = gameport_add(&gameport_pnp_device);
|
||||
ess->gameport_addr = 0x000;
|
||||
gameport_remap(ess->gameport, ess->gameport_addr);
|
||||
|
||||
return ess;
|
||||
}
|
||||
|
||||
|
@@ -437,7 +437,7 @@ sb_start_dma_ess(sb_dsp_t* dsp)
|
||||
uint8_t real_format = 0;
|
||||
uint32_t len = !(ESSreg(0xB7) & 4) ? dsp->sb_8_length : dsp->sb_16_length;
|
||||
|
||||
if (dsp->ess_reload_len) {
|
||||
if (dsp->ess_reload_len || len <= 0) {
|
||||
len = sb_ess_get_dma_len(dsp);
|
||||
dsp->ess_reload_len = 0;
|
||||
}
|
||||
@@ -449,9 +449,9 @@ sb_start_dma_ess(sb_dsp_t* dsp)
|
||||
real_format |= !!(ESSreg(0xB7) & 0x20) ? 0x10 : 0;
|
||||
real_format |= !!(ESSreg(0xB7) & 0x8) ? 0x20 : 0;
|
||||
if (!!(ESSreg(0xB8) & 8))
|
||||
sb_start_dma_i(dsp, !(ESSreg(0xB7) & 4), (ESSreg(0xB8) >> 2) & 1, real_format, sb_ess_get_dma_len(dsp));
|
||||
sb_start_dma_i(dsp, !(ESSreg(0xB7) & 4), (ESSreg(0xB8) >> 2) & 1, real_format, len);
|
||||
else
|
||||
sb_start_dma(dsp, !(ESSreg(0xB7) & 4), (ESSreg(0xB8) >> 2) & 1, real_format, sb_ess_get_dma_len(dsp));
|
||||
sb_start_dma(dsp, !(ESSreg(0xB7) & 4), (ESSreg(0xB8) >> 2) & 1, real_format, len);
|
||||
dsp->ess_playback_mode = 1;
|
||||
dma_set_drq(dsp->sb_8_dmanum, 1);
|
||||
dma_set_drq(dsp->sb_16_8_dmanum, 1);
|
||||
@@ -748,8 +748,15 @@ static void sb_ess_write_reg(sb_dsp_t *dsp, uint8_t reg, uint8_t data)
|
||||
chg = ESSreg(reg) ^ data;
|
||||
ESSreg(reg) = data;
|
||||
|
||||
if (chg & 1)
|
||||
dsp->ess_reload_len = 1;
|
||||
if (chg & 1) {
|
||||
if (dsp->sb_16_enable || dsp->sb_8_enable) {
|
||||
if (dsp->sb_16_enable)
|
||||
dsp->sb_16_length = sb_ess_get_dma_len(dsp);
|
||||
if (dsp->sb_8_enable)
|
||||
dsp->sb_8_length = sb_ess_get_dma_len(dsp);
|
||||
} else
|
||||
dsp->ess_reload_len = 1;
|
||||
}
|
||||
|
||||
if (chg & 0xB) {
|
||||
if (chg & 0xA) sb_stop_dma_ess(dsp); /* changing capture/playback direction? stop DMA to reinit */
|
||||
|
Reference in New Issue
Block a user