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:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)",
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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. */
|
||||
|
||||
Reference in New Issue
Block a user