Merge branch 'master' of ssh://github.com/86Box/86Box into version/4.1

# Conflicts:
#	CMakeLists.txt
#	debian/changelog
#	src/include_make/86box/version.h
#	src/unix/assets/86Box.spec
#	src/unix/assets/net.86box.86Box.metainfo.xml
#	vcpkg.json
This commit is contained in:
RichardG867
2023-10-23 15:42:06 -03:00
75 changed files with 1890 additions and 1123 deletions

View File

@@ -175,7 +175,7 @@ midi_out_device_get_from_internal_name(char *s)
void
midi_out_device_init(void)
{
if (devices[midi_output_device_current].device)
if ((midi_output_device_current > 0) && devices[midi_output_device_current].device)
device_add(devices[midi_output_device_current].device);
midi_output_device_last = midi_output_device_current;
}
@@ -293,7 +293,7 @@ midi_in_device_get_from_internal_name(char *s)
void
midi_in_device_init(void)
{
if (midi_in_devices[midi_input_device_current].device)
if ((midi_input_device_current > 0) && midi_in_devices[midi_input_device_current].device)
device_add(midi_in_devices[midi_input_device_current].device);
midi_input_device_last = midi_input_device_current;
}

View File

@@ -182,18 +182,18 @@ adgold_update_irq_status(adgold_t *adgold)
adgold->adgold_irq_status = adgold->adgold_status ^ 0xf;
}
void
int
adgold_getsamp_dma(adgold_t *adgold, int channel)
{
int temp;
dma_set_drq(adgold->dma, 1);
if ((adgold->adgold_mma_regs[channel][0xc] & 0x60) && (((adgold->adgold_mma_fifo_end[channel] - adgold->adgold_mma_fifo_start[channel]) & 255) >= 127))
return;
return 2;
temp = dma_channel_read(adgold->dma);
if (temp == DMA_NODATA) {
return;
return 1;
}
adgold->adgold_mma_fifo[channel][adgold->adgold_mma_fifo_end[channel]] = temp;
adgold->adgold_mma_fifo_end[channel] = (adgold->adgold_mma_fifo_end[channel] + 1) & 255;
@@ -207,6 +207,8 @@ adgold_getsamp_dma(adgold_t *adgold, int channel)
adgold_update_irq_status(adgold);
dma_set_drq(adgold->dma, 0);
}
return 0;
}
void
@@ -377,8 +379,16 @@ adgold_write(uint16_t addr, uint8_t val, void *priv)
adgold->adgold_mma.voice_count[1] = adgold->adgold_mma.voice_latch[1];
while (((adgold->adgold_mma_fifo_end[0] - adgold->adgold_mma_fifo_start[0]) & 255) < 128) {
adgold_getsamp_dma(adgold, 0);
adgold_getsamp_dma(adgold, 1);
if (adgold_getsamp_dma(adgold, 0)) {
adgold->adgold_mma_fifo_end[0] = 0;
adgold->adgold_mma_fifo_start[0] = 0;
break;
}
if (adgold_getsamp_dma(adgold, 1)) {
adgold->adgold_mma_fifo_end[1] = 0;
adgold->adgold_mma_fifo_start[1] = 0;
break;
}
}
if (((adgold->adgold_mma_fifo_end[0] - adgold->adgold_mma_fifo_start[0]) & 255) >= adgold->adgold_mma_intpos[0]) {
adgold->adgold_mma_status &= ~0x01;
@@ -392,7 +402,11 @@ adgold_write(uint16_t addr, uint8_t val, void *priv)
}
} else {
while (((adgold->adgold_mma_fifo_end[0] - adgold->adgold_mma_fifo_start[0]) & 255) < 128) {
adgold_getsamp_dma(adgold, 0);
if (adgold_getsamp_dma(adgold, 0)) {
adgold->adgold_mma_fifo_end[0] = 0;
adgold->adgold_mma_fifo_start[0] = 0;
break;
}
}
if (((adgold->adgold_mma_fifo_end[0] - adgold->adgold_mma_fifo_start[0]) & 255) >= adgold->adgold_mma_intpos[0]) {
adgold->adgold_mma_status &= ~0x01;
@@ -502,7 +516,11 @@ adgold_write(uint16_t addr, uint8_t val, void *priv)
if (adgold->adgold_mma_regs[1][0xc] & 1) {
while (((adgold->adgold_mma_fifo_end[1] - adgold->adgold_mma_fifo_start[1]) & 255) < 128) {
adgold_getsamp_dma(adgold, 1);
if (adgold_getsamp_dma(adgold, 1)) {
adgold->adgold_mma_fifo_end[1] = 0;
adgold->adgold_mma_fifo_start[1] = 0;
break;
}
}
}
}
@@ -675,10 +693,14 @@ adgold_mma_poll(adgold_t *adgold, int channel)
}
if (adgold->adgold_mma_regs[channel][0xc] & 1) {
adgold_getsamp_dma(adgold, channel);
if (adgold_getsamp_dma(adgold, channel)) {
adgold->adgold_mma_fifo_end[channel] = 0;
adgold->adgold_mma_fifo_start[channel] = 0;
return;
}
}
if (((adgold->adgold_mma_fifo_end[channel] - adgold->adgold_mma_fifo_start[channel]) & 255) < adgold->adgold_mma_intpos[channel] && !(adgold->adgold_mma_status & 0x01)) {
adgold->adgold_mma_status |= 1 << channel;
adgold->adgold_mma_status |= (1 << channel);
adgold_update_irq_status(adgold);
}
}
@@ -693,7 +715,7 @@ adgold_timer_poll(void *priv)
adgold_t *adgold = (adgold_t *) priv;
/*A small timer period will result in hangs.*/
timer_on_auto(&adgold->adgold_mma_timer_count, 4.88964);
timer_advance_u64(&adgold->adgold_mma_timer_count, (uint64_t) ((double) TIMER_USEC * 1.88964));
if (adgold->adgold_midi_ctrl & 0x3f) {
if ((adgold->adgold_midi_ctrl & 0x3f) != 0x3f) {

View File

@@ -450,7 +450,7 @@ const device_t ymf289b_ymfm_device = {
const device_t ymf278b_ymfm_device = {
.name = "Yamaha YMF278B OPL4 (YMFM)",
.internal_name = "ymf289b_ymfm",
.internal_name = "ymf278b_ymfm",
.flags = 0,
.local = FM_YMF278B,
.init = ymfm_drv_init,

View File

@@ -158,6 +158,7 @@ static uint8_t sb_16_pnp_rom[] = {
// clang-format on
};
// #define ENABLE_SB_LOG 1
#ifdef ENABLE_SB_LOG
int sb_do_log = ENABLE_SB_LOG;
@@ -520,6 +521,48 @@ sb16_awe32_filter_cd_audio(int channel, double *buffer, void *priv)
*buffer = c * output_gain;
}
void
sb16_awe32_filter_pc_speaker(int channel, double *buffer, void *priv)
{
const sb_t *sb = (sb_t *) priv;
const sb_ct1745_mixer_t *mixer = &sb->mixer_sb16;
double c;
double spk = mixer->speaker;
double master = channel ? mixer->master_r : mixer->master_l;
int32_t bass = channel ? mixer->bass_r : mixer->bass_l;
int32_t treble = channel ? mixer->treble_r : mixer->treble_l;
double bass_treble;
double output_gain = (channel ? mixer->output_gain_R : mixer->output_gain_L);
if (mixer->output_filter)
c = (low_fir_sb16(2, channel, *buffer) * spk) / 3.0;
else
c = ((*buffer) * spk) / 3.0;
c *= master;
/* This is not exactly how one does bass/treble controls, but the end result is like it.
A better implementation would reduce the CPU usage. */
if (bass != 8) {
bass_treble = sb_bass_treble_4bits[bass];
if (bass > 8)
c += (low_iir(2, channel, c) * bass_treble);
else if (bass < 8)
c = (c * bass_treble + low_cut_iir(1, channel, c) * (1.0 - bass_treble));
}
if (treble != 8) {
bass_treble = sb_bass_treble_4bits[treble];
if (treble > 8)
c += (high_iir(2, channel, c) * bass_treble);
else if (treble < 8)
c = (c * bass_treble + high_cut_iir(1, channel, c) * (1.0 - bass_treble));
}
*buffer = c * output_gain;
}
void
sb_ct1335_mixer_write(uint16_t addr, uint8_t val, void *priv)
{
@@ -743,6 +786,8 @@ sb_ct1745_mixer_write(uint16_t addr, uint8_t val, void *priv)
SoundBlaster 16 sets bit 7 if previous mixer index invalid.
Status bytes initially 080h on startup for all but level bytes (SB16). */
sb_log("CT1745: [W] %02X = %02X\n", mixer->index, val);
if (mixer->index == 0) {
/* Reset: Changed defaults from -14dB to 0dB */
@@ -764,8 +809,13 @@ sb_ct1745_mixer_write(uint16_t addr, uint8_t val, void *priv)
mixer->regs[0x44] = mixer->regs[0x45] = 0x80;
mixer->regs[0x46] = mixer->regs[0x47] = 0x80;
/* 0x43 = Mic AGC (Automatic Gain Control?) according to Linux's sb.h.
NSC LM4560 datasheet: Bit 0: 1 = Enable, 0 = Disable;
Another source says this: Bit 0: 0 = AGC on (default), 1 = Fixed gain of 20 dB. */
mixer->regs[0x43] = 0x00;
mixer->regs[0x49] = mixer->regs[0x4a] = 0x80;
mixer->regs[0x83] = 0xff;
sb->dsp.sb_irqm8 = 0;
sb->dsp.sb_irqm16 = 0;
@@ -820,31 +870,37 @@ sb_ct1745_mixer_write(uint16_t addr, uint8_t val, void *priv)
Note: Registers 80h and 81h are Read-only for PnP boards. */
case 0x80:
if (val & 0x01)
sb_dsp_setirq(&sb->dsp, 2);
if (val & 0x02)
sb_dsp_setirq(&sb->dsp, 5);
if (val & 0x04)
sb_dsp_setirq(&sb->dsp, 7);
if (val & 0x08)
sb_dsp_setirq(&sb->dsp, 10);
if (!sb->pnp) {
if (val & 0x01)
sb_dsp_setirq(&sb->dsp, 2);
if (val & 0x02)
sb_dsp_setirq(&sb->dsp, 5);
if (val & 0x04)
sb_dsp_setirq(&sb->dsp, 7);
if (val & 0x08)
sb_dsp_setirq(&sb->dsp, 10);
}
break;
case 0x81:
/* The documentation is confusing. sounds as if multple dma8 channels could
be set. */
if (val & 0x01)
sb_dsp_setdma8(&sb->dsp, 0);
if (val & 0x02)
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->pnp) {
if (val & 0x01)
sb_dsp_setdma8(&sb->dsp, 0);
else if (val & 0x02)
sb_dsp_setdma8(&sb->dsp, 1);
else if (val & 0x08)
sb_dsp_setdma8(&sb->dsp, 3);
sb_dsp_setdma16(&sb->dsp, 4);
if (val & 0x20)
sb_dsp_setdma16(&sb->dsp, 5);
else if (val & 0x40)
sb_dsp_setdma16(&sb->dsp, 6);
else if (val & 0x80)
sb_dsp_setdma16(&sb->dsp, 7);
}
break;
case 0x83:
@@ -863,19 +919,30 @@ sb_ct1745_mixer_write(uint16_t addr, uint8_t val, void *priv)
0, 0 = 200-207h;
0, 1 = Disabled
*/
if (sb->mpu != NULL) {
if ((val & 0x06) == 0x00)
mpu401_change_addr(sb->mpu, 0x330);
else if ((val & 0x06) == 0x04)
mpu401_change_addr(sb->mpu, 0x300);
else if ((val & 0x06) == 0x02)
mpu401_change_addr(sb->mpu, 0);
if (!sb->pnp) {
if (sb->mpu != NULL) {
if ((val & 0x06) == 0x00)
mpu401_change_addr(sb->mpu, 0x330);
else if ((val & 0x06) == 0x04)
mpu401_change_addr(sb->mpu, 0x300);
else if ((val & 0x06) == 0x02)
mpu401_change_addr(sb->mpu, 0);
}
sb->gameport_addr = 0;
gameport_remap(sb->gameport, 0);
if (!(val & 0x01)) {
sb->gameport_addr = 0x200;
gameport_remap(sb->gameport, 0x200);
}
}
sb->gameport_addr = 0;
gameport_remap(sb->gameport, 0);
if (!(val & 0x01)) {
sb->gameport_addr = 0x200;
gameport_remap(sb->gameport, 0x200);
break;
case 0xff:
if (sb->dsp.sb_type >= SBAWE32) {
if (val != ISAPNP_DMA_DISABLED)
sb_dsp_setdma16_8(&sb->dsp, val & 0x07);
sb_dsp_setdma16_enabled(&sb->dsp, !(val & 0x20));
sb_dsp_setdma16_translate(&sb->dsp, val != ISAPNP_DMA_DISABLED);
}
break;
@@ -931,7 +998,7 @@ sb_ct1745_mixer_read(uint16_t addr, void *priv)
if ((mixer->index >= 0x30) && (mixer->index <= 0x47))
ret = mixer->regs[mixer->index];
else
else {
switch (mixer->index) {
case 0x00:
ret = mixer->regs[mixer->index];
@@ -1033,22 +1100,24 @@ sb_ct1745_mixer_read(uint16_t addr, void *priv)
case 7:
ret |= 0x80;
break;
default:
break;
}
break;
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. */
/* If QEMU is any indication, then the values are actually 0x20, 0x40, and 0x80. */
temp = ((sb->dsp.sb_irq8) ? 1 : 0) | ((sb->dsp.sb_irq16) ? 2 : 0) | ((sb->dsp.sb_irq401) ? 4 : 0) | 0x40;
ret = temp;
/* http://the.earth.li/~tfm/oldpage/sb_mixer.html - 0x10, 0x20, 0x80. */
temp = ((sb->dsp.sb_irq8) ? 1 : 0) | ((sb->dsp.sb_irq16) ? 2 : 0) |
((sb->dsp.sb_irq401) ? 4 : 0);
if (sb->dsp.sb_type >= SBAWE32)
ret = temp | 0x80;
else
ret = temp | 0x40;
break;
case 0x83:
@@ -1074,18 +1143,24 @@ sb_ct1745_mixer_read(uint16_t addr, void *priv)
ret |= 0x01;
break;
case 0x90:
/* 3D Enhancement switch. */
case 0x49: /* Undocumented register used by some Creative drivers. */
case 0x4a: /* Undocumented register used by some Creative drivers. */
case 0x8c: /* Undocumented register used by some Creative drivers. */
case 0x8e: /* Undocumented register used by some Creative drivers. */
case 0x90: /* 3D Enhancement switch. */
case 0xfd: /* Undocumented register used by some Creative drivers. */
case 0xfe: /* Undocumented register used by some Creative drivers. */
ret = mixer->regs[mixer->index];
break;
/* TODO: creative drivers read and write on 0xFE and 0xFF. not sure what they are supposed to be. */
case 0xfd:
ret = 16;
break;
case 0xfe:
ret = 6;
case 0xff: /* Undocumented register used by some Creative drivers.
This and the upper bits of 0x82 seem to affect the
playback volume:
- Register FF = FF: Volume playback normal.
- Register FF = Not FF: Volume playback low unless
bit 6 of 82h is set. */
if (sb->dsp.sb_type >= SBAWE32)
ret = mixer->regs[mixer->index];
break;
default:
@@ -1093,6 +1168,9 @@ sb_ct1745_mixer_read(uint16_t addr, void *priv)
break;
}
sb_log("CT1745: [R] %02X = %02X\n", mixer->index, ret);
}
sb_log("CT1745: read REG%02X: %02X\n", mixer->index, ret);
return ret;
@@ -1103,9 +1181,6 @@ sb_ct1745_mixer_reset(sb_t *sb)
{
sb_ct1745_mixer_write(4, 0, sb);
sb_ct1745_mixer_write(5, 0, sb);
sb->mixer_sb16.regs[0xfd] = 16;
sb->mixer_sb16.regs[0xfe] = 6;
}
uint8_t
@@ -1616,8 +1691,14 @@ sb_vibra16_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *
sb_dsp_setdma8(&sb->dsp, val);
val = config->dma[1].dma;
if (val != ISAPNP_DMA_DISABLED)
sb_dsp_setdma16(&sb->dsp, val);
sb_dsp_setdma16_enabled(&sb->dsp, val != ISAPNP_DMA_DISABLED);
sb_dsp_setdma16_translate(&sb->dsp, val < ISAPNP_DMA_DISABLED);
if (val != ISAPNP_DMA_DISABLED) {
if (sb->dsp.sb_16_dma_supported)
sb_dsp_setdma16(&sb->dsp, val);
else
sb_dsp_setdma16_8(&sb->dsp, val);
}
}
break;
@@ -2078,11 +2159,12 @@ 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"));
sb_dsp_setdma16(&sb->dsp, device_get_config_int("dma16"));
sb_dsp_setdma16_supported(&sb->dsp, 1);
sb_ct1745_mixer_reset(sb);
if (sb->opl_enabled) {
@@ -2106,6 +2188,8 @@ sb_16_init(UNUSED(const device_t *info))
sb_ct1745_mixer_write, NULL, NULL, sb);
sound_add_handler(sb_get_buffer_sb16_awe32, sb);
sound_set_cd_audio_filter(sb16_awe32_filter_cd_audio, sb);
if (device_get_config_int("control_pc_speaker"))
sound_set_pc_speaker_filter(sb16_awe32_filter_pc_speaker, sb);
if (mpu_addr) {
sb->mpu = (mpu_t *) malloc(sizeof(mpu_t));
@@ -2134,12 +2218,15 @@ sb_16_reply_mca_init(UNUSED(const device_t *info))
fm_driver_get(FM_YMF262, &sb->opl);
sb_dsp_init(&sb->dsp, SB16, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_setdma16_supported(&sb->dsp, 1);
sb_ct1745_mixer_reset(sb);
sb->mixer_enabled = 1;
sb->mixer_sb16.output_filter = 1;
sound_add_handler(sb_get_buffer_sb16_awe32, sb);
sound_set_cd_audio_filter(sb16_awe32_filter_cd_audio, sb);
if (device_get_config_int("control_pc_speaker"))
sound_set_pc_speaker_filter(sb16_awe32_filter_pc_speaker, sb);
sb->mpu = (mpu_t *) malloc(sizeof(mpu_t));
memset(sb->mpu, 0, sizeof(mpu_t));
@@ -2167,16 +2254,21 @@ sb_16_pnp_init(UNUSED(const device_t *info))
sb_t *sb = malloc(sizeof(sb_t));
memset(sb, 0x00, sizeof(sb_t));
sb->pnp = 1;
sb->opl_enabled = 1;
fm_driver_get(FM_YMF262, &sb->opl);
sb_dsp_init(&sb->dsp, SB16, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_setdma16_supported(&sb->dsp, 1);
sb_ct1745_mixer_reset(sb);
sb->mixer_enabled = 1;
sb->mixer_sb16.output_filter = 1;
sound_add_handler(sb_get_buffer_sb16_awe32, sb);
sound_set_cd_audio_filter(sb16_awe32_filter_cd_audio, sb);
if (device_get_config_int("control_pc_speaker"))
sound_set_pc_speaker_filter(sb16_awe32_filter_pc_speaker, sb);
sb->mpu = (mpu_t *) malloc(sizeof(mpu_t));
memset(sb->mpu, 0, sizeof(mpu_t));
@@ -2224,16 +2316,22 @@ sb_vibra16_pnp_init(UNUSED(const device_t *info))
sb_t *sb = malloc(sizeof(sb_t));
memset(sb, 0x00, sizeof(sb_t));
sb->pnp = 1;
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. */
sb_dsp_setdma16_supported(&sb->dsp, info->local != 0);
sb_ct1745_mixer_reset(sb);
sb->mixer_enabled = 1;
sb->mixer_sb16.output_filter = 1;
sound_add_handler(sb_get_buffer_sb16_awe32, sb);
sound_set_cd_audio_filter(sb16_awe32_filter_cd_audio, sb);
if (device_get_config_int("control_pc_speaker"))
sound_set_pc_speaker_filter(sb16_awe32_filter_pc_speaker, sb);
sb->mpu = (mpu_t *) malloc(sizeof(mpu_t));
memset(sb->mpu, 0, sizeof(mpu_t));
@@ -2302,6 +2400,7 @@ sb_16_compat_init(const device_t *info)
fm_driver_get(FM_YMF262, &sb->opl);
sb_dsp_init(&sb->dsp, SB16, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_setdma16_supported(&sb->dsp, 1);
sb_ct1745_mixer_reset(sb);
sb->mixer_enabled = 1;
@@ -2374,6 +2473,7 @@ sb_awe32_init(UNUSED(const device_t *info))
sb_dsp_setirq(&sb->dsp, device_get_config_int("irq"));
sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma"));
sb_dsp_setdma16(&sb->dsp, device_get_config_int("dma16"));
sb_dsp_setdma16_supported(&sb->dsp, 1);
sb_ct1745_mixer_reset(sb);
if (sb->opl_enabled) {
@@ -2397,6 +2497,8 @@ sb_awe32_init(UNUSED(const device_t *info))
sb_ct1745_mixer_write, NULL, NULL, sb);
sound_add_handler(sb_get_buffer_sb16_awe32, sb);
sound_set_cd_audio_filter(sb16_awe32_filter_cd_audio, sb);
if (device_get_config_int("control_pc_speaker"))
sound_set_pc_speaker_filter(sb16_awe32_filter_pc_speaker, sb);
if (mpu_addr) {
sb->mpu = (mpu_t *) malloc(sizeof(mpu_t));
@@ -2425,16 +2527,22 @@ sb_awe32_pnp_init(const device_t *info)
memset(sb, 0x00, sizeof(sb_t));
sb->pnp = 1;
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_dsp_setdma16_supported(&sb->dsp, 1);
sb_ct1745_mixer_reset(sb);
sb->mixer_enabled = 1;
sb->mixer_sb16.output_filter = 1;
sound_add_handler(sb_get_buffer_sb16_awe32, sb);
sound_set_cd_audio_filter(sb16_awe32_filter_cd_audio, sb);
if (device_get_config_int("control_pc_speaker"))
sound_set_pc_speaker_filter(sb16_awe32_filter_pc_speaker, sb);
sb->mpu = (mpu_t *) malloc(sizeof(mpu_t));
memset(sb->mpu, 0, sizeof(mpu_t));
@@ -3191,6 +3299,13 @@ static const device_config_t sb_16_config[] = {
.default_string = "",
.default_int = 1
},
{
.name = "control_pc_speaker",
.description = "Control PC speaker",
.type = CONFIG_BINARY,
.default_string = "",
.default_int = 0
},
{
.name = "receive_input",
.description = "Receive input (SB MIDI)",
@@ -3209,6 +3324,13 @@ static const device_config_t sb_16_config[] = {
};
static const device_config_t sb_16_pnp_config[] = {
{
.name = "control_pc_speaker",
.description = "Control PC speaker",
.type = CONFIG_BINARY,
.default_string = "",
.default_int = 0
},
{
.name = "receive_input",
.description = "Receive input (SB MIDI)",
@@ -3259,6 +3381,13 @@ static const device_config_t sb_32_pnp_config[] = {
{ .description = "" }
}
},
{
.name = "control_pc_speaker",
.description = "Control PC speaker",
.type = CONFIG_BINARY,
.default_string = "",
.default_int = 0
},
{
.name = "receive_input",
.description = "Receive input (SB MIDI)",
@@ -3472,6 +3601,13 @@ static const device_config_t sb_awe32_config[] = {
.default_string = "",
.default_int = 1
},
{
.name = "control_pc_speaker",
.description = "Control PC speaker",
.type = CONFIG_BINARY,
.default_string = "",
.default_int = 0
},
{
.name = "receive_input",
.description = "Receive input (SB MIDI)",
@@ -3522,6 +3658,13 @@ static const device_config_t sb_awe32_pnp_config[] = {
{ .description = "" }
}
},
{
.name = "control_pc_speaker",
.description = "Control PC speaker",
.type = CONFIG_BINARY,
.default_string = "",
.default_int = 0
},
{
.name = "receive_input",
.description = "Receive input (SB MIDI)",
@@ -3592,6 +3735,13 @@ static const device_config_t sb_awe64_value_config[] = {
{ .description = "" }
}
},
{
.name = "control_pc_speaker",
.description = "Control PC speaker",
.type = CONFIG_BINARY,
.default_string = "",
.default_int = 0
},
{
.name = "receive_input",
.description = "Receive input (SB MIDI)",
@@ -3658,6 +3808,13 @@ static const device_config_t sb_awe64_config[] = {
{ .description = "" }
}
},
{
.name = "control_pc_speaker",
.description = "Control PC speaker",
.type = CONFIG_BINARY,
.default_string = "",
.default_int = 0
},
{
.name = "receive_input",
.description = "Receive input (SB MIDI)",
@@ -3716,6 +3873,13 @@ static const device_config_t sb_awe64_gold_config[] = {
{ .description = "" }
}
},
{
.name = "control_pc_speaker",
.description = "Control PC speaker",
.type = CONFIG_BINARY,
.default_string = "",
.default_int = 0
},
{
.name = "receive_input",
.description = "Receive input (SB MIDI)",

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] = {
@@ -115,7 +115,7 @@ uint8_t adjustMap2[24] = {
252, 0, 252, 0
};
double low_fir_sb16_coef[2][SB16_NCoef];
double low_fir_sb16_coef[3][SB16_NCoef];
#ifdef ENABLE_SB_DSP_LOG
int sb_dsp_do_log = ENABLE_SB_DSP_LOG;
@@ -423,20 +423,80 @@ sb_8_write_dma(void *priv, uint8_t val)
return dma_channel_write(dsp->sb_8_dmanum, val) == DMA_NODATA;
}
/*
Supported High DMA Translation Channel
----------------------------------------------------
0 0 0 First 8-bit
0 0 1 First 8-bit
0 1 0 Second 8-bit
0 1 1 Second 8-bit
1 0 0 First 8-bit
1 0 1 First 8-bit
1 1 0 16-bit
1 1 1 Second 8-bit
*/
int
sb_16_read_dma(void *priv)
{
const sb_dsp_t *dsp = (sb_dsp_t *) priv;
int temp, ret = 0;
int dma_flags, dma_ch = dsp->sb_16_dmanum;
return dma_channel_read(dsp->sb_16_dmanum);
if (dsp->sb_16_dma_enabled && dsp->sb_16_dma_supported && !dsp->sb_16_dma_translate)
ret = dma_channel_read(dma_ch);
else {
if (dsp->sb_16_dma_enabled) {
/* High DMA channel enabled, either translation is enabled or
16-bit transfers are not supported. */
if (dsp->sb_16_dma_translate || !dsp->sb_16_dma_supported)
dma_ch = dsp->sb_16_8_dmanum;
} else
/* High DMA channel disabled, always use the first 8-bit channel. */
dma_ch = dsp->sb_8_dmanum;
temp = dma_channel_read(dma_ch);
ret = temp;
if ((temp != DMA_NODATA) && !(temp & DMA_OVER)) {
temp = dma_channel_read(dma_ch);
if (temp == DMA_NODATA)
ret = DMA_NODATA;
else {
dma_flags = temp & DMA_OVER;
temp &= ~DMA_OVER;
ret |= (temp << 8) | dma_flags;
}
}
}
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;
int dma_ch = dsp->sb_16_dmanum;
if (dsp->sb_16_dma_enabled && dsp->sb_16_dma_supported && !dsp->sb_16_dma_translate)
ret = dma_channel_write(dma_ch, val) == DMA_NODATA;
else {
if (dsp->sb_16_dma_enabled) {
/* High DMA channel enabled, either translation is enabled or
16-bit transfers are not supported. */
if (dsp->sb_16_dma_translate || !dsp->sb_16_dma_supported)
dma_ch = dsp->sb_16_8_dmanum;
} else
/* High DMA channel disabled, always use the first 8-bit channel. */
dma_ch = dsp->sb_8_dmanum;
temp = dma_channel_write(dma_ch, val & 0xff);
ret = temp;
if ((temp != DMA_NODATA) && (temp != DMA_OVER)) {
temp = dma_channel_write(dma_ch, val >> 8);
ret = temp;
}
}
return dma_channel_write(dsp->sb_16_dmanum, val) == DMA_NODATA;
return ret;
}
void
@@ -448,15 +508,45 @@ sb_dsp_setirq(sb_dsp_t *dsp, int irq)
void
sb_dsp_setdma8(sb_dsp_t *dsp, int dma)
{
sb_dsp_log("8-bit DMA now: %i\n", dma);
dsp->sb_8_dmanum = dma;
}
void
sb_dsp_setdma16(sb_dsp_t *dsp, int dma)
{
sb_dsp_log("16-bit DMA now: %i\n", dma);
dsp->sb_16_dmanum = dma;
}
void
sb_dsp_setdma16_8(sb_dsp_t *dsp, int dma)
{
sb_dsp_log("16-bit to 8-bit translation DMA now: %i\n", dma);
dsp->sb_16_8_dmanum = dma;
}
void
sb_dsp_setdma16_enabled(sb_dsp_t *dsp, int enabled)
{
sb_dsp_log("16-bit DMA now: %sabled\n", enabled ? "en" : "dis");
dsp->sb_16_dma_enabled = enabled;
}
void
sb_dsp_setdma16_supported(sb_dsp_t *dsp, int supported)
{
sb_dsp_log("16-bit DMA now: %ssupported\n", supported ? "" : "not ");
dsp->sb_16_dma_supported = supported;
}
void
sb_dsp_setdma16_translate(sb_dsp_t *dsp, int translate)
{
sb_dsp_log("16-bit to 8-bit translation now: %sabled\n", translate ? "en" : "dis");
dsp->sb_16_dma_translate = translate;
}
void
sb_exec_command(sb_dsp_t *dsp)
{
@@ -479,6 +569,100 @@ sb_exec_command(sb_dsp_t *dsp)
if (dsp->sb_type >= SB16)
sb_add_data(dsp, 0);
break;
case 0x04: /* ASP set mode register */
if (dsp->sb_type >= SB16) {
dsp->sb_asp_mode = dsp->sb_data[0];
if (dsp->sb_asp_mode & 4)
dsp->sb_asp_ram_index = 0;
sb_dsp_log("SB16 ASP set mode %02X\n", dsp->sb_asp_mode);
} /* else DSP Status (Obsolete) */
break;
case 0x05: /* ASP set codec parameter */
if (dsp->sb_type >= SB16)
sb_dsp_log("SB16 ASP unknown codec params %02X, %02X\n", dsp->sb_data[0], dsp->sb_data[1]);
break;
case 0x07:
break;
case 0x08: /* ASP get version / AZTECH type/EEPROM access */
if (IS_AZTECH(dsp)) {
if ((dsp->sb_data[0] == 0x05 || dsp->sb_data[0] == 0x55) && dsp->sb_subtype == SB_SUBTYPE_CLONE_AZT2316A_0X11)
sb_add_data(dsp, 0x11); /* AZTECH get type, WASHINGTON/latest - according to devkit. E.g.: The one in the Itautec Infoway Multimidia */
else if ((dsp->sb_data[0] == 0x05 || dsp->sb_data[0] == 0x55) && dsp->sb_subtype == SB_SUBTYPE_CLONE_AZT1605_0X0C)
sb_add_data(dsp, 0x0C); /* AZTECH get type, CLINTON - according to devkit. E.g.: The one in the Packard Bell Legend 100CD */
else if (dsp->sb_data[0] == 0x08) {
/* EEPROM address to write followed by byte */
if (dsp->sb_data[1] < 0 || dsp->sb_data[1] >= AZTECH_EEPROM_SIZE)
fatal("AZT EEPROM: out of bounds write to %02X\n", dsp->sb_data[1]);
sb_dsp_log("EEPROM write = %02x\n", dsp->sb_data[2]);
dsp->azt_eeprom[dsp->sb_data[1]] = dsp->sb_data[2];
break;
} else if (dsp->sb_data[0] == 0x07) {
/* EEPROM address to read */
if (dsp->sb_data[1] < 0 || dsp->sb_data[1] >= AZTECH_EEPROM_SIZE)
fatal("AZT EEPROM: out of bounds read to %02X\n", dsp->sb_data[1]);
sb_dsp_log("EEPROM read = %02x\n", dsp->azt_eeprom[dsp->sb_data[1]]);
sb_add_data(dsp, dsp->azt_eeprom[dsp->sb_data[1]]);
break;
} else
sb_dsp_log("AZT2316A: UNKNOWN 0x08 COMMAND: %02X\n", dsp->sb_data[0]); /* 0x08 (when shutting down, driver tries to read 1 byte of response), 0x55, 0x0D, 0x08D seen */
break;
}
if (dsp->sb_type == SBAWE64) /* AWE64 has no ASP or a socket for it */
sb_add_data(dsp, 0xFF);
else if (dsp->sb_type >= SB16)
sb_add_data(dsp, 0x18);
break;
case 0x09: /* AZTECH mode set */
if (IS_AZTECH(dsp)) {
if (dsp->sb_data[0] == 0x00) {
sb_dsp_log("AZT2316A: WSS MODE!\n");
azt2316a_enable_wss(1, dsp->parent);
} else if (dsp->sb_data[0] == 0x01) {
sb_dsp_log("AZT2316A: SB8PROV2 MODE!\n");
azt2316a_enable_wss(0, dsp->parent);
} else
sb_dsp_log("AZT2316A: UNKNOWN MODE! = %02x\n", dsp->sb_data[0]); // sequences 0x02->0xFF, 0x04->0xFF seen
}
break;
case 0x0E: /* ASP set register */
if (dsp->sb_type >= SB16) {
dsp->sb_asp_regs[dsp->sb_data[0]] = dsp->sb_data[1];
if ((dsp->sb_data[0] == 0x83) && (dsp->sb_asp_mode & 128) && (dsp->sb_asp_mode & 8)) { /* ASP memory write */
if (dsp->sb_asp_mode & 8)
dsp->sb_asp_ram_index = 0;
dsp->sb_asp_ram[dsp->sb_asp_ram_index] = dsp->sb_data[1];
if (dsp->sb_asp_mode & 2) {
dsp->sb_asp_ram_index++;
if (dsp->sb_asp_ram_index >= 2048)
dsp->sb_asp_ram_index = 0;
}
}
sb_dsp_log("SB16 ASP write reg %02X, val %02X\n", dsp->sb_data[0], dsp->sb_data[1]);
}
break;
case 0x0F: /* ASP get register */
if (dsp->sb_type >= SB16) {
if ((dsp->sb_data[0] == 0x83) && (dsp->sb_asp_mode & 128) && (dsp->sb_asp_mode & 8)) { /* ASP memory read */
if (dsp->sb_asp_mode & 8)
dsp->sb_asp_ram_index = 0;
dsp->sb_asp_regs[0x83] = dsp->sb_asp_ram[dsp->sb_asp_ram_index];
if (dsp->sb_asp_mode & 1) {
dsp->sb_asp_ram_index++;
if (dsp->sb_asp_ram_index >= 2048)
dsp->sb_asp_ram_index = 0;
}
} else if (dsp->sb_data[0] == 0x83) {
dsp->sb_asp_regs[0x83] = 0x18;
}
sb_add_data(dsp, dsp->sb_asp_regs[dsp->sb_data[0]]);
sb_dsp_log("SB16 ASP read reg %02X, val %02X\n", dsp->sb_data[0], dsp->sb_asp_regs[dsp->sb_data[0]]);
}
break;
case 0x10: /* 8-bit direct mode */
sb_dsp_update(dsp);
dsp->sbdat = dsp->sbdatl = dsp->sbdatr = (dsp->sb_data[0] ^ 0x80) << 8;
@@ -670,7 +854,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 +868,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 +882,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 +896,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;
@@ -788,6 +976,8 @@ sb_exec_command(sb_dsp_t *dsp)
case 0xE4: /* Write test register */
dsp->sb_test = dsp->sb_data[0];
break;
case 0xE7: /* ???? */
break;
case 0xE8: /* Read test register */
sb_add_data(dsp, dsp->sb_test);
break;
@@ -799,79 +989,6 @@ sb_exec_command(sb_dsp_t *dsp)
sb_dsp_log("Trigger IRQ\n");
sb_irq(dsp, 0);
break;
case 0xE7: /* ???? */
break;
case 0x07:
case 0xFF: /* No, that's not how you program auto-init DMA */
break;
case 0x08: /* ASP get version / AZTECH type/EEPROM access */
if (IS_AZTECH(dsp)) {
if ((dsp->sb_data[0] == 0x05 || dsp->sb_data[0] == 0x55) && dsp->sb_subtype == SB_SUBTYPE_CLONE_AZT2316A_0X11)
sb_add_data(dsp, 0x11); /* AZTECH get type, WASHINGTON/latest - according to devkit. E.g.: The one in the Itautec Infoway Multimidia */
else if ((dsp->sb_data[0] == 0x05 || dsp->sb_data[0] == 0x55) && dsp->sb_subtype == SB_SUBTYPE_CLONE_AZT1605_0X0C)
sb_add_data(dsp, 0x0C); /* AZTECH get type, CLINTON - according to devkit. E.g.: The one in the Packard Bell Legend 100CD */
else if (dsp->sb_data[0] == 0x08) {
/* EEPROM address to write followed by byte */
if (dsp->sb_data[1] < 0 || dsp->sb_data[1] >= AZTECH_EEPROM_SIZE)
fatal("AZT EEPROM: out of bounds write to %02X\n", dsp->sb_data[1]);
sb_dsp_log("EEPROM write = %02x\n", dsp->sb_data[2]);
dsp->azt_eeprom[dsp->sb_data[1]] = dsp->sb_data[2];
break;
} else if (dsp->sb_data[0] == 0x07) {
/* EEPROM address to read */
if (dsp->sb_data[1] < 0 || dsp->sb_data[1] >= AZTECH_EEPROM_SIZE)
fatal("AZT EEPROM: out of bounds read to %02X\n", dsp->sb_data[1]);
sb_dsp_log("EEPROM read = %02x\n", dsp->azt_eeprom[dsp->sb_data[1]]);
sb_add_data(dsp, dsp->azt_eeprom[dsp->sb_data[1]]);
break;
} else
sb_dsp_log("AZT2316A: UNKNOWN 0x08 COMMAND: %02X\n", dsp->sb_data[0]); /* 0x08 (when shutting down, driver tries to read 1 byte of response), 0x55, 0x0D, 0x08D seen */
break;
}
if (dsp->sb_type == SBAWE64) /* AWE64 has no ASP or a socket for it */
sb_add_data(dsp, 0xFF);
else if (dsp->sb_type >= SB16)
sb_add_data(dsp, 0x18);
break;
case 0x0E: /* ASP set register */
if (dsp->sb_type >= SB16) {
dsp->sb_asp_regs[dsp->sb_data[0]] = dsp->sb_data[1];
if ((dsp->sb_data[0] == 0x83) && (dsp->sb_asp_mode & 128) && (dsp->sb_asp_mode & 8)) { /* ASP memory write */
if (dsp->sb_asp_mode & 8)
dsp->sb_asp_ram_index = 0;
dsp->sb_asp_ram[dsp->sb_asp_ram_index] = dsp->sb_data[1];
if (dsp->sb_asp_mode & 2) {
dsp->sb_asp_ram_index++;
if (dsp->sb_asp_ram_index >= 2048)
dsp->sb_asp_ram_index = 0;
}
}
sb_dsp_log("SB16 ASP write reg %02X, val %02X\n", dsp->sb_data[0], dsp->sb_data[1]);
}
break;
case 0x0F: /* ASP get register */
if (dsp->sb_type >= SB16) {
if ((dsp->sb_data[0] == 0x83) && (dsp->sb_asp_mode & 128) && (dsp->sb_asp_mode & 8)) { /* ASP memory read */
if (dsp->sb_asp_mode & 8)
dsp->sb_asp_ram_index = 0;
dsp->sb_asp_regs[0x83] = dsp->sb_asp_ram[dsp->sb_asp_ram_index];
if (dsp->sb_asp_mode & 1) {
dsp->sb_asp_ram_index++;
if (dsp->sb_asp_ram_index >= 2048)
dsp->sb_asp_ram_index = 0;
}
} else if (dsp->sb_data[0] == 0x83) {
dsp->sb_asp_regs[0x83] = 0x18;
}
sb_add_data(dsp, dsp->sb_asp_regs[dsp->sb_data[0]]);
sb_dsp_log("SB16 ASP read reg %02X, val %02X\n", dsp->sb_data[0], dsp->sb_asp_regs[dsp->sb_data[0]]);
}
break;
case 0xF8:
if (dsp->sb_type < SB16)
sb_add_data(dsp, 0);
@@ -884,30 +1001,7 @@ sb_exec_command(sb_dsp_t *dsp)
if (dsp->sb_type >= SB16)
dsp->sb_8051_ram[dsp->sb_data[0]] = dsp->sb_data[1];
break;
case 0x04: /* ASP set mode register */
if (dsp->sb_type >= SB16) {
dsp->sb_asp_mode = dsp->sb_data[0];
if (dsp->sb_asp_mode & 4)
dsp->sb_asp_ram_index = 0;
sb_dsp_log("SB16 ASP set mode %02X\n", dsp->sb_asp_mode);
} /* else DSP Status (Obsolete) */
break;
case 0x05: /* ASP set codec parameter */
if (dsp->sb_type >= SB16)
sb_dsp_log("SB16 ASP unknown codec params %02X, %02X\n", dsp->sb_data[0], dsp->sb_data[1]);
break;
case 0x09: /* AZTECH mode set */
if (IS_AZTECH(dsp)) {
if (dsp->sb_data[0] == 0x00) {
sb_dsp_log("AZT2316A: WSS MODE!\n");
azt2316a_enable_wss(1, dsp->parent);
} else if (dsp->sb_data[0] == 0x01) {
sb_dsp_log("AZT2316A: SB8PROV2 MODE!\n");
azt2316a_enable_wss(0, dsp->parent);
} else
sb_dsp_log("AZT2316A: UNKNOWN MODE! = %02x\n", dsp->sb_data[0]); // sequences 0x02->0xFF, 0x04->0xFF seen
}
case 0xFF: /* No, that's not how you program auto-init DMA */
break;
/* TODO: Some more data about the DSP registeres
@@ -925,6 +1019,7 @@ sb_exec_command(sb_dsp_t *dsp)
*/
default:
sb_dsp_log("Unknown DSP command: %02X\n", dsp->sb_command);
break;
}
@@ -939,6 +1034,10 @@ sb_write(uint16_t a, uint8_t v, void *priv)
{
sb_dsp_t *dsp = (sb_dsp_t *) priv;
/* Sound Blasters prior to Sound Blaster 16 alias the I/O ports. */
if (dsp->sb_type < SB16)
a &= 0xfffe;
switch (a & 0xF) {
case 6: /* Reset */
if (!dsp->uart_midi) {
@@ -1003,6 +1102,10 @@ sb_read(uint16_t a, void *priv)
sb_dsp_t *dsp = (sb_dsp_t *) priv;
uint8_t ret = 0x00;
/* Sound Blasters prior to Sound Blaster 16 alias the I/O ports. */
if (dsp->sb_type < SB16)
a &= 0xfffe;
switch (a & 0xf) {
case 0xA: /* Read data */
if (dsp->mpu && dsp->uart_midi) {
@@ -1153,6 +1256,7 @@ sb_dsp_init(sb_dsp_t *dsp, int type, int subtype, void *parent)
a set frequency command is sent. */
recalc_sb16_filter(0, 3200 * 2);
recalc_sb16_filter(1, FREQ_44100);
recalc_sb16_filter(2, 18939);
/* Initialize SB16 8051 RAM and ASP internal RAM */
memset(dsp->sb_8051_ram, 0x00, sizeof(dsp->sb_8051_ram));

View File

@@ -88,15 +88,20 @@ speaker_update(void)
void
speaker_get_buffer(int32_t *buffer, int len, UNUSED(void *priv))
{
int32_t val;
double val_l, val_r;
speaker_update();
if (!speaker_mute) {
for (int c = 0; c < len * 2; c += 2) {
val = speaker_buffer[c >> 1];
buffer[c] += val;
buffer[c + 1] += val;
val_l = val_r = (double) speaker_buffer[c >> 1];
/* Apply PC speaker volume and filters */
if (filter_pc_speaker != NULL) {
filter_pc_speaker(0, &val_l, filter_pc_speaker_p);
filter_pc_speaker(1, &val_r, filter_pc_speaker_p);
}
buffer[c] += (int32_t) val_l;
buffer[c + 1] += (int32_t) val_r;
}
}

View File

@@ -77,7 +77,10 @@ static volatile int cdaudioon = 0;
static int cd_thread_enable = 0;
static void (*filter_cd_audio)(int channel, double *buffer, void *priv) = NULL;
static void *filter_cd_audio_p = NULL;
static void *filter_cd_audio_p = NULL;
void (*filter_pc_speaker)(int channel, double *buffer, void *priv) = NULL;
void *filter_pc_speaker_p = NULL;
static const device_t sound_none_device = {
.name = "None",
@@ -222,13 +225,13 @@ sound_card_get_from_internal_name(const char *s)
void
sound_card_init(void)
{
if ((sound_card_current[0] != SOUND_INTERNAL) && (sound_cards[sound_card_current[0]].device))
if ((sound_card_current[0] > SOUND_INTERNAL) && (sound_cards[sound_card_current[0]].device))
device_add(sound_cards[sound_card_current[0]].device);
if (sound_cards[sound_card_current[1]].device)
if ((sound_card_current[1] > SOUND_INTERNAL) && (sound_cards[sound_card_current[1]].device))
device_add(sound_cards[sound_card_current[1]].device);
if (sound_cards[sound_card_current[2]].device)
if ((sound_card_current[2] > SOUND_INTERNAL) && (sound_cards[sound_card_current[2]].device))
device_add(sound_cards[sound_card_current[2]].device);
if (sound_cards[sound_card_current[3]].device)
if ((sound_card_current[3] > SOUND_INTERNAL) && (sound_cards[sound_card_current[3]].device))
device_add(sound_cards[sound_card_current[3]].device);
}
@@ -444,6 +447,15 @@ sound_set_cd_audio_filter(void (*filter)(int channel, double *buffer, void *priv
}
}
void
sound_set_pc_speaker_filter(void (*filter)(int channel, double *buffer, void *priv), void *priv)
{
if ((filter_pc_speaker == NULL) || (filter == NULL)) {
filter_pc_speaker = filter;
filter_pc_speaker_p = priv;
}
}
void
sound_poll(UNUSED(void *priv))
{
@@ -514,6 +526,9 @@ sound_reset(void)
filter_cd_audio = NULL;
filter_cd_audio_p = NULL;
filter_pc_speaker = NULL;
filter_pc_speaker_p = NULL;
sound_set_cd_volume(65535, 65535);
/* Reset the MPU-401 already loaded flag and the chain of input/output handlers. */