Revision 15b61470
b/hw/sb16.c | ||
---|---|---|
26 | 26 |
#define LENOFA(a) ((int) (sizeof(a)/sizeof(a[0]))) |
27 | 27 |
|
28 | 28 |
#define dolog(...) AUD_log ("sb16", __VA_ARGS__) |
29 |
|
|
30 |
/* #define DEBUG */ |
|
31 |
/* #define DEBUG_SB16_MOST */ |
|
32 |
|
|
29 | 33 |
#ifdef DEBUG |
30 | 34 |
#define ldebug(...) dolog (__VA_ARGS__) |
31 | 35 |
#else |
32 | 36 |
#define ldebug(...) |
33 | 37 |
#endif |
34 | 38 |
|
35 |
/* #define DEBUG */ |
|
36 |
/* #define DEBUG_SB16_MOST */ |
|
37 |
|
|
38 | 39 |
#define IO_READ_PROTO(name) \ |
39 | 40 |
uint32_t name (void *opaque, uint32_t nport) |
40 | 41 |
#define IO_WRITE_PROTO(name) \ |
... | ... | |
206 | 207 |
s->freq = (1000000 + (tmp / 2)) / tmp; |
207 | 208 |
} |
208 | 209 |
|
209 |
if (-1 != dma_len) |
|
210 |
s->block_size = dma_len + 1; |
|
210 |
if (dma_len != -1) |
|
211 |
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 |
} |
|
211 | 222 |
|
212 | 223 |
s->freq >>= s->fmt_stereo; |
213 | 224 |
s->left_till_irq = s->block_size; |
... | ... | |
216 | 227 |
s->dma_auto = (mask & DMA8_AUTO) != 0; |
217 | 228 |
s->align = (1 << s->fmt_stereo) - 1; |
218 | 229 |
|
230 |
if (s->block_size & s->align) |
|
231 |
dolog ("warning: unaligned buffer\n"); |
|
232 |
|
|
219 | 233 |
ldebug ("freq %d, stereo %d, sign %d, bits %d, " |
220 | 234 |
"dma %d, auto %d, fifo %d, high %d\n", |
221 | 235 |
s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits, |
... | ... | |
260 | 274 |
|
261 | 275 |
s->block_size = dma_len + 1; |
262 | 276 |
s->block_size <<= (s->fmt_bits == 16); |
263 |
if (!s->dma_auto) /* Miles Sound System ? */ |
|
277 |
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 */ |
|
264 | 282 |
s->block_size <<= s->fmt_stereo; |
283 |
} |
|
265 | 284 |
|
266 | 285 |
ldebug ("freq %d, stereo %d, sign %d, bits %d, " |
267 | 286 |
"dma %d, auto %d, fifo %d, high %d\n", |
... | ... | |
290 | 309 |
s->bytes_per_second = (s->freq << s->fmt_stereo) << (s->fmt_bits == 16); |
291 | 310 |
s->highspeed = 0; |
292 | 311 |
s->align = (1 << (s->fmt_stereo + (s->fmt_bits == 16))) - 1; |
312 |
if (s->block_size & s->align) |
|
313 |
dolog ("warning: unaligned buffer\n"); |
|
293 | 314 |
|
294 | 315 |
if (s->freq) |
295 | 316 |
s->voice = AUD_open (s->voice, "sb16", s->freq, |
... | ... | |
373 | 394 |
s->block_size = 0; |
374 | 395 |
break; |
375 | 396 |
|
397 |
case 0x1c: /* Auto-Initialize DMA DAC, 8-bit */ |
|
398 |
control (s, 1); |
|
399 |
break; |
|
400 |
|
|
376 | 401 |
case 0x20: /* Direct ADC, Juice/PL */ |
377 | 402 |
dsp_out_data (s, 0xff); |
378 | 403 |
goto warn; |
... | ... | |
607 | 632 |
break; |
608 | 633 |
|
609 | 634 |
case 0x14: |
610 |
dma_cmd8 (s, 0, dsp_get_lohi (s)); |
|
611 |
/* s->can_write = 0; */ |
|
612 |
/* qemu_mod_timer (s->aux_ts, qemu_get_clock (vm_clock) + (ticks_per_sec * 320) / 1000000); */ |
|
635 |
dma_cmd8 (s, 0, dsp_get_lohi (s) + 1); |
|
613 | 636 |
break; |
614 | 637 |
|
615 | 638 |
case 0x40: |
... | ... | |
626 | 649 |
break; |
627 | 650 |
|
628 | 651 |
case 0x48: |
629 |
s->block_size = dsp_get_lohi (s); |
|
630 |
/* s->highspeed = 1; */ |
|
652 |
s->block_size = dsp_get_lohi (s) + 1; |
|
631 | 653 |
ldebug ("set dma block len %d\n", s->block_size); |
632 | 654 |
break; |
633 | 655 |
|
634 | 656 |
case 0x80: |
635 | 657 |
{ |
636 |
int samples, bytes; |
|
658 |
int freq, samples, bytes;
|
|
637 | 659 |
int64_t ticks; |
638 | 660 |
|
639 |
if (-1 == s->freq) |
|
640 |
s->freq = 11025; |
|
641 |
samples = dsp_get_lohi (s); |
|
661 |
freq = s->freq > 0 ? s->freq : 11025; |
|
662 |
samples = dsp_get_lohi (s) + 1; |
|
642 | 663 |
bytes = samples << s->fmt_stereo << (s->fmt_bits == 16); |
643 |
ticks = bytes ? (ticks_per_sec / (s->freq / bytes)) : 0;
|
|
644 |
if (!bytes || ticks < ticks_per_sec / 1024)
|
|
664 |
ticks = (bytes * ticks_per_sec) / freq;
|
|
665 |
if (ticks < ticks_per_sec / 1024) |
|
645 | 666 |
pic_set_irq (s->irq, 1); |
646 | 667 |
else |
647 | 668 |
qemu_mod_timer (s->aux_ts, qemu_get_clock (vm_clock) + ticks); |
... | ... | |
658 | 679 |
|
659 | 680 |
case 0xe2: |
660 | 681 |
d0 = dsp_get_data (s); |
661 |
dolog ("E2 = %#x\n", d0);
|
|
682 |
ldebug ("E2 = %#x\n", d0);
|
|
662 | 683 |
break; |
663 | 684 |
|
664 | 685 |
case 0xe4: |
... | ... | |
967 | 988 |
static IO_READ_PROTO(mixer_read) |
968 | 989 |
{ |
969 | 990 |
SB16State *s = opaque; |
991 |
#ifndef DEBUG_SB16_MOST |
|
992 |
if (s->mixer_nreg != 0x82) |
|
993 |
#endif |
|
970 | 994 |
ldebug ("mixer_read[%#x] -> %#x\n", |
971 | 995 |
s->mixer_nreg, s->mixer_regs[s->mixer_nreg]); |
972 | 996 |
return s->mixer_regs[s->mixer_nreg]; |
... | ... | |
1049 | 1073 |
} |
1050 | 1074 |
|
1051 | 1075 |
#ifdef DEBUG_SB16_MOST |
1052 |
ldebug ("pos %5d free %5d size %5d till % 5d copy %5d dma size %5d\n", |
|
1053 |
dma_pos, free, dma_len, s->left_till_irq, copy, s->block_size); |
|
1076 |
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, written, |
|
1078 |
s->block_size); |
|
1054 | 1079 |
#endif |
1055 | 1080 |
|
1056 | 1081 |
while (s->left_till_irq <= 0) { |
Also available in: Unified diff