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,15 +26,16 @@ | ||
| 26 | #define LENOFA(a) ((int) (sizeof(a)/sizeof(a[0]))) | 26 | #define LENOFA(a) ((int) (sizeof(a)/sizeof(a[0]))) |
| 27 | 27 | ||
| 28 | #define dolog(...) AUD_log ("sb16", __VA_ARGS__) | 28 | #define dolog(...) AUD_log ("sb16", __VA_ARGS__) |
| 29 | + | ||
| 30 | +/* #define DEBUG */ | ||
| 31 | +/* #define DEBUG_SB16_MOST */ | ||
| 32 | + | ||
| 29 | #ifdef DEBUG | 33 | #ifdef DEBUG |
| 30 | #define ldebug(...) dolog (__VA_ARGS__) | 34 | #define ldebug(...) dolog (__VA_ARGS__) |
| 31 | #else | 35 | #else |
| 32 | #define ldebug(...) | 36 | #define ldebug(...) |
| 33 | #endif | 37 | #endif |
| 34 | 38 | ||
| 35 | -/* #define DEBUG */ | ||
| 36 | -/* #define DEBUG_SB16_MOST */ | ||
| 37 | - | ||
| 38 | #define IO_READ_PROTO(name) \ | 39 | #define IO_READ_PROTO(name) \ |
| 39 | uint32_t name (void *opaque, uint32_t nport) | 40 | uint32_t name (void *opaque, uint32_t nport) |
| 40 | #define IO_WRITE_PROTO(name) \ | 41 | #define IO_WRITE_PROTO(name) \ |
| @@ -206,8 +207,18 @@ static void dma_cmd8 (SB16State *s, int mask, int dma_len) | @@ -206,8 +207,18 @@ static void dma_cmd8 (SB16State *s, int mask, int dma_len) | ||
| 206 | s->freq = (1000000 + (tmp / 2)) / tmp; | 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 | s->freq >>= s->fmt_stereo; | 223 | s->freq >>= s->fmt_stereo; |
| 213 | s->left_till_irq = s->block_size; | 224 | s->left_till_irq = s->block_size; |
| @@ -216,6 +227,9 @@ static void dma_cmd8 (SB16State *s, int mask, int dma_len) | @@ -216,6 +227,9 @@ static void dma_cmd8 (SB16State *s, int mask, int dma_len) | ||
| 216 | s->dma_auto = (mask & DMA8_AUTO) != 0; | 227 | s->dma_auto = (mask & DMA8_AUTO) != 0; |
| 217 | s->align = (1 << s->fmt_stereo) - 1; | 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 | ldebug ("freq %d, stereo %d, sign %d, bits %d, " | 233 | ldebug ("freq %d, stereo %d, sign %d, bits %d, " |
| 220 | "dma %d, auto %d, fifo %d, high %d\n", | 234 | "dma %d, auto %d, fifo %d, high %d\n", |
| 221 | s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits, | 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,8 +274,13 @@ static void dma_cmd (SB16State *s, uint8_t cmd, uint8_t d0, int dma_len) | ||
| 260 | 274 | ||
| 261 | s->block_size = dma_len + 1; | 275 | s->block_size = dma_len + 1; |
| 262 | s->block_size <<= (s->fmt_bits == 16); | 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 | s->block_size <<= s->fmt_stereo; | 282 | s->block_size <<= s->fmt_stereo; |
| 283 | + } | ||
| 265 | 284 | ||
| 266 | ldebug ("freq %d, stereo %d, sign %d, bits %d, " | 285 | ldebug ("freq %d, stereo %d, sign %d, bits %d, " |
| 267 | "dma %d, auto %d, fifo %d, high %d\n", | 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,6 +309,8 @@ static void dma_cmd (SB16State *s, uint8_t cmd, uint8_t d0, int dma_len) | ||
| 290 | s->bytes_per_second = (s->freq << s->fmt_stereo) << (s->fmt_bits == 16); | 309 | s->bytes_per_second = (s->freq << s->fmt_stereo) << (s->fmt_bits == 16); |
| 291 | s->highspeed = 0; | 310 | s->highspeed = 0; |
| 292 | s->align = (1 << (s->fmt_stereo + (s->fmt_bits == 16))) - 1; | 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 | if (s->freq) | 315 | if (s->freq) |
| 295 | s->voice = AUD_open (s->voice, "sb16", s->freq, | 316 | s->voice = AUD_open (s->voice, "sb16", s->freq, |
| @@ -373,6 +394,10 @@ static void command (SB16State *s, uint8_t cmd) | @@ -373,6 +394,10 @@ static void command (SB16State *s, uint8_t cmd) | ||
| 373 | s->block_size = 0; | 394 | s->block_size = 0; |
| 374 | break; | 395 | break; |
| 375 | 396 | ||
| 397 | + case 0x1c: /* Auto-Initialize DMA DAC, 8-bit */ | ||
| 398 | + control (s, 1); | ||
| 399 | + break; | ||
| 400 | + | ||
| 376 | case 0x20: /* Direct ADC, Juice/PL */ | 401 | case 0x20: /* Direct ADC, Juice/PL */ |
| 377 | dsp_out_data (s, 0xff); | 402 | dsp_out_data (s, 0xff); |
| 378 | goto warn; | 403 | goto warn; |
| @@ -607,9 +632,7 @@ static void complete (SB16State *s) | @@ -607,9 +632,7 @@ static void complete (SB16State *s) | ||
| 607 | break; | 632 | break; |
| 608 | 633 | ||
| 609 | case 0x14: | 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 | break; | 636 | break; |
| 614 | 637 | ||
| 615 | case 0x40: | 638 | case 0x40: |
| @@ -626,22 +649,20 @@ static void complete (SB16State *s) | @@ -626,22 +649,20 @@ static void complete (SB16State *s) | ||
| 626 | break; | 649 | break; |
| 627 | 650 | ||
| 628 | case 0x48: | 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 | ldebug ("set dma block len %d\n", s->block_size); | 653 | ldebug ("set dma block len %d\n", s->block_size); |
| 632 | break; | 654 | break; |
| 633 | 655 | ||
| 634 | case 0x80: | 656 | case 0x80: |
| 635 | { | 657 | { |
| 636 | - int samples, bytes; | 658 | + int freq, samples, bytes; |
| 637 | int64_t ticks; | 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 | bytes = samples << s->fmt_stereo << (s->fmt_bits == 16); | 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 | pic_set_irq (s->irq, 1); | 666 | pic_set_irq (s->irq, 1); |
| 646 | else | 667 | else |
| 647 | qemu_mod_timer (s->aux_ts, qemu_get_clock (vm_clock) + ticks); | 668 | qemu_mod_timer (s->aux_ts, qemu_get_clock (vm_clock) + ticks); |
| @@ -658,7 +679,7 @@ static void complete (SB16State *s) | @@ -658,7 +679,7 @@ static void complete (SB16State *s) | ||
| 658 | 679 | ||
| 659 | case 0xe2: | 680 | case 0xe2: |
| 660 | d0 = dsp_get_data (s); | 681 | d0 = dsp_get_data (s); |
| 661 | - dolog ("E2 = %#x\n", d0); | 682 | + ldebug ("E2 = %#x\n", d0); |
| 662 | break; | 683 | break; |
| 663 | 684 | ||
| 664 | case 0xe4: | 685 | case 0xe4: |
| @@ -967,6 +988,9 @@ static IO_WRITE_PROTO(mixer_write_indexw) | @@ -967,6 +988,9 @@ static IO_WRITE_PROTO(mixer_write_indexw) | ||
| 967 | static IO_READ_PROTO(mixer_read) | 988 | static IO_READ_PROTO(mixer_read) |
| 968 | { | 989 | { |
| 969 | SB16State *s = opaque; | 990 | SB16State *s = opaque; |
| 991 | +#ifndef DEBUG_SB16_MOST | ||
| 992 | + if (s->mixer_nreg != 0x82) | ||
| 993 | +#endif | ||
| 970 | ldebug ("mixer_read[%#x] -> %#x\n", | 994 | ldebug ("mixer_read[%#x] -> %#x\n", |
| 971 | s->mixer_nreg, s->mixer_regs[s->mixer_nreg]); | 995 | s->mixer_nreg, s->mixer_regs[s->mixer_nreg]); |
| 972 | return s->mixer_regs[s->mixer_nreg]; | 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,8 +1073,9 @@ static int SB_read_DMA (void *opaque, int nchan, int dma_pos, int dma_len) | ||
| 1049 | } | 1073 | } |
| 1050 | 1074 | ||
| 1051 | #ifdef DEBUG_SB16_MOST | 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 | #endif | 1079 | #endif |
| 1055 | 1080 | ||
| 1056 | while (s->left_till_irq <= 0) { | 1081 | while (s->left_till_irq <= 0) { |