Commit 15b614700062dde8801762b1cfd4717a63a2cfd9
1 parent
9e89a4be
audio fix (malc)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1137 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
45 additions
and
20 deletions
hw/sb16.c
... | ... | @@ -26,15 +26,16 @@ |
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,8 +207,18 @@ static void dma_cmd8 (SB16State *s, int mask, int dma_len) |
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,6 +227,9 @@ static void dma_cmd8 (SB16State *s, int mask, int dma_len) |
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,8 +274,13 @@ static void dma_cmd (SB16State *s, uint8_t cmd, uint8_t d0, int dma_len) |
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,6 +309,8 @@ static void dma_cmd (SB16State *s, uint8_t cmd, uint8_t d0, int dma_len) |
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,6 +394,10 @@ static void command (SB16State *s, uint8_t cmd) |
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,9 +632,7 @@ static void complete (SB16State *s) |
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,22 +649,20 @@ static void complete (SB16State *s) |
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,7 +679,7 @@ static void complete (SB16State *s) |
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,6 +988,9 @@ static IO_WRITE_PROTO(mixer_write_indexw) |
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,8 +1073,9 @@ static int SB_read_DMA (void *opaque, int nchan, int dma_pos, int dma_len) |
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) { | ... | ... |