26 |
#define LENOFA(a) ((int) (sizeof(a)/sizeof(a[0]))) |
#define LENOFA(a) ((int) (sizeof(a)/sizeof(a[0]))) |
27 |
|
|
28 |
#define dolog(...) AUD_log ("sb16", __VA_ARGS__) |
#define dolog(...) AUD_log ("sb16", __VA_ARGS__) |
29 |
|
|
30 |
|
/* #define DEBUG */ |
31 |
|
/* #define DEBUG_SB16_MOST */ |
32 |
|
|
33 |
#ifdef DEBUG |
#ifdef DEBUG |
34 |
#define ldebug(...) dolog (__VA_ARGS__) |
#define ldebug(...) dolog (__VA_ARGS__) |
35 |
#else |
#else |
36 |
#define ldebug(...) |
#define ldebug(...) |
37 |
#endif |
#endif |
38 |
|
|
|
/* #define DEBUG */ |
|
|
/* #define DEBUG_SB16_MOST */ |
|
|
|
|
39 |
#define IO_READ_PROTO(name) \ |
#define IO_READ_PROTO(name) \ |
40 |
uint32_t name (void *opaque, uint32_t nport) |
uint32_t name (void *opaque, uint32_t nport) |
41 |
#define IO_WRITE_PROTO(name) \ |
#define IO_WRITE_PROTO(name) \ |
207 |
s->freq = (1000000 + (tmp / 2)) / tmp; |
s->freq = (1000000 + (tmp / 2)) / tmp; |
208 |
} |
} |
209 |
|
|
210 |
if (-1 != dma_len) |
if (dma_len != -1) |
211 |
s->block_size = dma_len + 1; |
s->block_size = dma_len << s->fmt_stereo; |
212 |
|
else { |
213 |
|
/* This is apparently the only way to make both Act1/PL |
214 |
|
and SecondReality/FC work |
215 |
|
|
216 |
|
Act1 sets block size via command 0x48 and it's an odd number |
217 |
|
SR does the same with even number |
218 |
|
Both use stereo, and Creatives own documentation states that |
219 |
|
0x48 sets block size in bytes less one.. go figure */ |
220 |
|
s->block_size &= ~s->fmt_stereo; |
221 |
|
} |
222 |
|
|
223 |
s->freq >>= s->fmt_stereo; |
s->freq >>= s->fmt_stereo; |
224 |
s->left_till_irq = s->block_size; |
s->left_till_irq = s->block_size; |
227 |
s->dma_auto = (mask & DMA8_AUTO) != 0; |
s->dma_auto = (mask & DMA8_AUTO) != 0; |
228 |
s->align = (1 << s->fmt_stereo) - 1; |
s->align = (1 << s->fmt_stereo) - 1; |
229 |
|
|
230 |
|
if (s->block_size & s->align) |
231 |
|
dolog ("warning: unaligned buffer\n"); |
232 |
|
|
233 |
ldebug ("freq %d, stereo %d, sign %d, bits %d, " |
ldebug ("freq %d, stereo %d, sign %d, bits %d, " |
234 |
"dma %d, auto %d, fifo %d, high %d\n", |
"dma %d, auto %d, fifo %d, high %d\n", |
235 |
s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits, |
s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits, |
274 |
|
|
275 |
s->block_size = dma_len + 1; |
s->block_size = dma_len + 1; |
276 |
s->block_size <<= (s->fmt_bits == 16); |
s->block_size <<= (s->fmt_bits == 16); |
277 |
if (!s->dma_auto) /* Miles Sound System ? */ |
if (!s->dma_auto) { |
278 |
|
/* It is clear that for DOOM and auto-init this value |
279 |
|
shouldn't take stereo into account, while Miles Sound Systems |
280 |
|
setsound.exe with single transfer mode wouldn't work without it |
281 |
|
wonders of SB16 yet again */ |
282 |
s->block_size <<= s->fmt_stereo; |
s->block_size <<= s->fmt_stereo; |
283 |
|
} |
284 |
|
|
285 |
ldebug ("freq %d, stereo %d, sign %d, bits %d, " |
ldebug ("freq %d, stereo %d, sign %d, bits %d, " |
286 |
"dma %d, auto %d, fifo %d, high %d\n", |
"dma %d, auto %d, fifo %d, high %d\n", |
309 |
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); |
310 |
s->highspeed = 0; |
s->highspeed = 0; |
311 |
s->align = (1 << (s->fmt_stereo + (s->fmt_bits == 16))) - 1; |
s->align = (1 << (s->fmt_stereo + (s->fmt_bits == 16))) - 1; |
312 |
|
if (s->block_size & s->align) |
313 |
|
dolog ("warning: unaligned buffer\n"); |
314 |
|
|
315 |
if (s->freq) |
if (s->freq) |
316 |
s->voice = AUD_open (s->voice, "sb16", s->freq, |
s->voice = AUD_open (s->voice, "sb16", s->freq, |
394 |
s->block_size = 0; |
s->block_size = 0; |
395 |
break; |
break; |
396 |
|
|
397 |
|
case 0x1c: /* Auto-Initialize DMA DAC, 8-bit */ |
398 |
|
control (s, 1); |
399 |
|
break; |
400 |
|
|
401 |
case 0x20: /* Direct ADC, Juice/PL */ |
case 0x20: /* Direct ADC, Juice/PL */ |
402 |
dsp_out_data (s, 0xff); |
dsp_out_data (s, 0xff); |
403 |
goto warn; |
goto warn; |
632 |
break; |
break; |
633 |
|
|
634 |
case 0x14: |
case 0x14: |
635 |
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); */ |
|
636 |
break; |
break; |
637 |
|
|
638 |
case 0x40: |
case 0x40: |
649 |
break; |
break; |
650 |
|
|
651 |
case 0x48: |
case 0x48: |
652 |
s->block_size = dsp_get_lohi (s); |
s->block_size = dsp_get_lohi (s) + 1; |
|
/* s->highspeed = 1; */ |
|
653 |
ldebug ("set dma block len %d\n", s->block_size); |
ldebug ("set dma block len %d\n", s->block_size); |
654 |
break; |
break; |
655 |
|
|
656 |
case 0x80: |
case 0x80: |
657 |
{ |
{ |
658 |
int samples, bytes; |
int freq, samples, bytes; |
659 |
int64_t ticks; |
int64_t ticks; |
660 |
|
|
661 |
if (-1 == s->freq) |
freq = s->freq > 0 ? s->freq : 11025; |
662 |
s->freq = 11025; |
samples = dsp_get_lohi (s) + 1; |
|
samples = dsp_get_lohi (s); |
|
663 |
bytes = samples << s->fmt_stereo << (s->fmt_bits == 16); |
bytes = samples << s->fmt_stereo << (s->fmt_bits == 16); |
664 |
ticks = bytes ? (ticks_per_sec / (s->freq / bytes)) : 0; |
ticks = (bytes * ticks_per_sec) / freq; |
665 |
if (!bytes || ticks < ticks_per_sec / 1024) |
if (ticks < ticks_per_sec / 1024) |
666 |
pic_set_irq (s->irq, 1); |
pic_set_irq (s->irq, 1); |
667 |
else |
else |
668 |
qemu_mod_timer (s->aux_ts, qemu_get_clock (vm_clock) + ticks); |
qemu_mod_timer (s->aux_ts, qemu_get_clock (vm_clock) + ticks); |
679 |
|
|
680 |
case 0xe2: |
case 0xe2: |
681 |
d0 = dsp_get_data (s); |
d0 = dsp_get_data (s); |
682 |
dolog ("E2 = %#x\n", d0); |
ldebug ("E2 = %#x\n", d0); |
683 |
break; |
break; |
684 |
|
|
685 |
case 0xe4: |
case 0xe4: |
988 |
static IO_READ_PROTO(mixer_read) |
static IO_READ_PROTO(mixer_read) |
989 |
{ |
{ |
990 |
SB16State *s = opaque; |
SB16State *s = opaque; |
991 |
|
#ifndef DEBUG_SB16_MOST |
992 |
|
if (s->mixer_nreg != 0x82) |
993 |
|
#endif |
994 |
ldebug ("mixer_read[%#x] -> %#x\n", |
ldebug ("mixer_read[%#x] -> %#x\n", |
995 |
s->mixer_nreg, s->mixer_regs[s->mixer_nreg]); |
s->mixer_nreg, s->mixer_regs[s->mixer_nreg]); |
996 |
return s->mixer_regs[s->mixer_nreg]; |
return s->mixer_regs[s->mixer_nreg]; |
1073 |
} |
} |
1074 |
|
|
1075 |
#ifdef DEBUG_SB16_MOST |
#ifdef DEBUG_SB16_MOST |
1076 |
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", |
1077 |
dma_pos, free, dma_len, s->left_till_irq, copy, s->block_size); |
dma_pos, free, dma_len, s->left_till_irq, copy, written, |
1078 |
|
s->block_size); |
1079 |
#endif |
#endif |
1080 |
|
|
1081 |
while (s->left_till_irq <= 0) { |
while (s->left_till_irq <= 0) { |