mirror of https://github.com/xqemu/xqemu.git
audio fix (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1137 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
9e89a4be8e
commit
15b6147000
65
hw/sb16.c
65
hw/sb16.c
|
@ -26,15 +26,16 @@
|
||||||
#define LENOFA(a) ((int) (sizeof(a)/sizeof(a[0])))
|
#define LENOFA(a) ((int) (sizeof(a)/sizeof(a[0])))
|
||||||
|
|
||||||
#define dolog(...) AUD_log ("sb16", __VA_ARGS__)
|
#define dolog(...) AUD_log ("sb16", __VA_ARGS__)
|
||||||
|
|
||||||
|
/* #define DEBUG */
|
||||||
|
/* #define DEBUG_SB16_MOST */
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
#define ldebug(...) dolog (__VA_ARGS__)
|
#define ldebug(...) dolog (__VA_ARGS__)
|
||||||
#else
|
#else
|
||||||
#define ldebug(...)
|
#define ldebug(...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* #define DEBUG */
|
|
||||||
/* #define DEBUG_SB16_MOST */
|
|
||||||
|
|
||||||
#define IO_READ_PROTO(name) \
|
#define IO_READ_PROTO(name) \
|
||||||
uint32_t name (void *opaque, uint32_t nport)
|
uint32_t name (void *opaque, uint32_t nport)
|
||||||
#define IO_WRITE_PROTO(name) \
|
#define IO_WRITE_PROTO(name) \
|
||||||
|
@ -206,8 +207,18 @@ static void dma_cmd8 (SB16State *s, int mask, int dma_len)
|
||||||
s->freq = (1000000 + (tmp / 2)) / tmp;
|
s->freq = (1000000 + (tmp / 2)) / tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (-1 != dma_len)
|
if (dma_len != -1)
|
||||||
s->block_size = dma_len + 1;
|
s->block_size = dma_len << s->fmt_stereo;
|
||||||
|
else {
|
||||||
|
/* This is apparently the only way to make both Act1/PL
|
||||||
|
and SecondReality/FC work
|
||||||
|
|
||||||
|
Act1 sets block size via command 0x48 and it's an odd number
|
||||||
|
SR does the same with even number
|
||||||
|
Both use stereo, and Creatives own documentation states that
|
||||||
|
0x48 sets block size in bytes less one.. go figure */
|
||||||
|
s->block_size &= ~s->fmt_stereo;
|
||||||
|
}
|
||||||
|
|
||||||
s->freq >>= s->fmt_stereo;
|
s->freq >>= s->fmt_stereo;
|
||||||
s->left_till_irq = s->block_size;
|
s->left_till_irq = s->block_size;
|
||||||
|
@ -216,6 +227,9 @@ static void dma_cmd8 (SB16State *s, int mask, int dma_len)
|
||||||
s->dma_auto = (mask & DMA8_AUTO) != 0;
|
s->dma_auto = (mask & DMA8_AUTO) != 0;
|
||||||
s->align = (1 << s->fmt_stereo) - 1;
|
s->align = (1 << s->fmt_stereo) - 1;
|
||||||
|
|
||||||
|
if (s->block_size & s->align)
|
||||||
|
dolog ("warning: unaligned buffer\n");
|
||||||
|
|
||||||
ldebug ("freq %d, stereo %d, sign %d, bits %d, "
|
ldebug ("freq %d, stereo %d, sign %d, bits %d, "
|
||||||
"dma %d, auto %d, fifo %d, high %d\n",
|
"dma %d, auto %d, fifo %d, high %d\n",
|
||||||
s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits,
|
s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits,
|
||||||
|
@ -260,8 +274,13 @@ static void dma_cmd (SB16State *s, uint8_t cmd, uint8_t d0, int dma_len)
|
||||||
|
|
||||||
s->block_size = dma_len + 1;
|
s->block_size = dma_len + 1;
|
||||||
s->block_size <<= (s->fmt_bits == 16);
|
s->block_size <<= (s->fmt_bits == 16);
|
||||||
if (!s->dma_auto) /* Miles Sound System ? */
|
if (!s->dma_auto) {
|
||||||
|
/* It is clear that for DOOM and auto-init this value
|
||||||
|
shouldn't take stereo into account, while Miles Sound Systems
|
||||||
|
setsound.exe with single transfer mode wouldn't work without it
|
||||||
|
wonders of SB16 yet again */
|
||||||
s->block_size <<= s->fmt_stereo;
|
s->block_size <<= s->fmt_stereo;
|
||||||
|
}
|
||||||
|
|
||||||
ldebug ("freq %d, stereo %d, sign %d, bits %d, "
|
ldebug ("freq %d, stereo %d, sign %d, bits %d, "
|
||||||
"dma %d, auto %d, fifo %d, high %d\n",
|
"dma %d, auto %d, fifo %d, high %d\n",
|
||||||
|
@ -290,6 +309,8 @@ static void dma_cmd (SB16State *s, uint8_t cmd, uint8_t d0, int dma_len)
|
||||||
s->bytes_per_second = (s->freq << s->fmt_stereo) << (s->fmt_bits == 16);
|
s->bytes_per_second = (s->freq << s->fmt_stereo) << (s->fmt_bits == 16);
|
||||||
s->highspeed = 0;
|
s->highspeed = 0;
|
||||||
s->align = (1 << (s->fmt_stereo + (s->fmt_bits == 16))) - 1;
|
s->align = (1 << (s->fmt_stereo + (s->fmt_bits == 16))) - 1;
|
||||||
|
if (s->block_size & s->align)
|
||||||
|
dolog ("warning: unaligned buffer\n");
|
||||||
|
|
||||||
if (s->freq)
|
if (s->freq)
|
||||||
s->voice = AUD_open (s->voice, "sb16", s->freq,
|
s->voice = AUD_open (s->voice, "sb16", s->freq,
|
||||||
|
@ -373,6 +394,10 @@ static void command (SB16State *s, uint8_t cmd)
|
||||||
s->block_size = 0;
|
s->block_size = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 0x1c: /* Auto-Initialize DMA DAC, 8-bit */
|
||||||
|
control (s, 1);
|
||||||
|
break;
|
||||||
|
|
||||||
case 0x20: /* Direct ADC, Juice/PL */
|
case 0x20: /* Direct ADC, Juice/PL */
|
||||||
dsp_out_data (s, 0xff);
|
dsp_out_data (s, 0xff);
|
||||||
goto warn;
|
goto warn;
|
||||||
|
@ -607,9 +632,7 @@ static void complete (SB16State *s)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x14:
|
case 0x14:
|
||||||
dma_cmd8 (s, 0, dsp_get_lohi (s));
|
dma_cmd8 (s, 0, dsp_get_lohi (s) + 1);
|
||||||
/* s->can_write = 0; */
|
|
||||||
/* qemu_mod_timer (s->aux_ts, qemu_get_clock (vm_clock) + (ticks_per_sec * 320) / 1000000); */
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x40:
|
case 0x40:
|
||||||
|
@ -626,22 +649,20 @@ static void complete (SB16State *s)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x48:
|
case 0x48:
|
||||||
s->block_size = dsp_get_lohi (s);
|
s->block_size = dsp_get_lohi (s) + 1;
|
||||||
/* s->highspeed = 1; */
|
|
||||||
ldebug ("set dma block len %d\n", s->block_size);
|
ldebug ("set dma block len %d\n", s->block_size);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x80:
|
case 0x80:
|
||||||
{
|
{
|
||||||
int samples, bytes;
|
int freq, samples, bytes;
|
||||||
int64_t ticks;
|
int64_t ticks;
|
||||||
|
|
||||||
if (-1 == s->freq)
|
freq = s->freq > 0 ? s->freq : 11025;
|
||||||
s->freq = 11025;
|
samples = dsp_get_lohi (s) + 1;
|
||||||
samples = dsp_get_lohi (s);
|
|
||||||
bytes = samples << s->fmt_stereo << (s->fmt_bits == 16);
|
bytes = samples << s->fmt_stereo << (s->fmt_bits == 16);
|
||||||
ticks = bytes ? (ticks_per_sec / (s->freq / bytes)) : 0;
|
ticks = (bytes * ticks_per_sec) / freq;
|
||||||
if (!bytes || ticks < ticks_per_sec / 1024)
|
if (ticks < ticks_per_sec / 1024)
|
||||||
pic_set_irq (s->irq, 1);
|
pic_set_irq (s->irq, 1);
|
||||||
else
|
else
|
||||||
qemu_mod_timer (s->aux_ts, qemu_get_clock (vm_clock) + ticks);
|
qemu_mod_timer (s->aux_ts, qemu_get_clock (vm_clock) + ticks);
|
||||||
|
@ -658,7 +679,7 @@ static void complete (SB16State *s)
|
||||||
|
|
||||||
case 0xe2:
|
case 0xe2:
|
||||||
d0 = dsp_get_data (s);
|
d0 = dsp_get_data (s);
|
||||||
dolog ("E2 = %#x\n", d0);
|
ldebug ("E2 = %#x\n", d0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xe4:
|
case 0xe4:
|
||||||
|
@ -967,6 +988,9 @@ static IO_WRITE_PROTO(mixer_write_indexw)
|
||||||
static IO_READ_PROTO(mixer_read)
|
static IO_READ_PROTO(mixer_read)
|
||||||
{
|
{
|
||||||
SB16State *s = opaque;
|
SB16State *s = opaque;
|
||||||
|
#ifndef DEBUG_SB16_MOST
|
||||||
|
if (s->mixer_nreg != 0x82)
|
||||||
|
#endif
|
||||||
ldebug ("mixer_read[%#x] -> %#x\n",
|
ldebug ("mixer_read[%#x] -> %#x\n",
|
||||||
s->mixer_nreg, s->mixer_regs[s->mixer_nreg]);
|
s->mixer_nreg, s->mixer_regs[s->mixer_nreg]);
|
||||||
return s->mixer_regs[s->mixer_nreg];
|
return s->mixer_regs[s->mixer_nreg];
|
||||||
|
@ -1049,8 +1073,9 @@ static int SB_read_DMA (void *opaque, int nchan, int dma_pos, int dma_len)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_SB16_MOST
|
#ifdef DEBUG_SB16_MOST
|
||||||
ldebug ("pos %5d free %5d size %5d till % 5d copy %5d dma size %5d\n",
|
ldebug ("pos %5d free %5d size %5d till % 5d copy %5d written %5d size %5d\n",
|
||||||
dma_pos, free, dma_len, s->left_till_irq, copy, s->block_size);
|
dma_pos, free, dma_len, s->left_till_irq, copy, written,
|
||||||
|
s->block_size);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
while (s->left_till_irq <= 0) {
|
while (s->left_till_irq <= 0) {
|
||||||
|
|
Loading…
Reference in New Issue