this repo has no description
at main 873 lines 20 kB view raw
1/* 2 ASCEMDEV.c 3 4 Copyright (C) 2008 Paul C. Pratt 5 6 You can redistribute this file and/or modify it under the terms 7 of version 2 of the GNU General Public License as published by 8 the Free Software Foundation. You should have received a copy 9 of the license along with this file; see the file COPYING. 10 11 This file is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 license for more details. 15*/ 16 17/* 18 Apple Sound Chip EMulated DEVice 19*/ 20 21#include "PICOMMON.h" 22 23#if EmASC 24 25#include "VIAEMDEV.h" 26 27#include "ASCEMDEV.h" 28 29/* 30 ReportAbnormalID unused 0x0F0E, 0x0F1E - 0x0FFF 31*/ 32 33LOCALVAR ui3r SoundReg801 = 0; 34LOCALVAR ui3r SoundReg802 = 0; 35LOCALVAR ui3r SoundReg803 = 0; 36LOCALVAR ui3r SoundReg804 = 0; 37LOCALVAR ui3r SoundReg805 = 0; 38LOCALVAR ui3r SoundReg_Volume = 0; /* 0x806 */ 39/* LOCALVAR ui3r SoundReg807 = 0; */ 40 41LOCALVAR ui3b ASC_SampBuff[0x800]; 42 43struct ASC_ChanR { 44 ui3b freq[4]; 45 ui3b phase[4]; 46}; 47typedef struct ASC_ChanR ASC_ChanR; 48 49LOCALVAR ASC_ChanR ASC_ChanA[4]; 50 51LOCALVAR ui4b ASC_FIFO_Out = 0; 52LOCALVAR ui4b ASC_FIFO_InA = 0; 53LOCALVAR ui4b ASC_FIFO_InB = 0; 54LOCALVAR blnr ASC_Playing = falseblnr; 55 56#define ASC_dolog (dbglog_HAVE && 0) 57 58#ifdef ASC_interrupt_PulseNtfy 59IMPORTPROC ASC_interrupt_PulseNtfy(void); 60#endif 61 62LOCALPROC ASC_RecalcStatus(void) 63{ 64 if ((1 == SoundReg801) && ASC_Playing) { 65 if (((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)) >= 0x200) { 66 SoundReg804 &= ~ 0x01; 67 } else { 68 SoundReg804 |= 0x01; 69 } 70 if (((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)) >= 0x400) { 71 SoundReg804 |= 0x02; 72 } else { 73 SoundReg804 &= ~ 0x02; 74 } 75 if (0 != (SoundReg802 & 2)) { 76 if (((ui4b)(ASC_FIFO_InB - ASC_FIFO_Out)) >= 0x200) { 77 SoundReg804 &= ~ 0x04; 78 } else { 79 SoundReg804 |= 0x04; 80 } 81 if (((ui4b)(ASC_FIFO_InB - ASC_FIFO_Out)) >= 0x400) { 82 SoundReg804 |= 0x08; 83 } else { 84 SoundReg804 &= ~ 0x08; 85 } 86 } 87 } 88} 89 90LOCALPROC ASC_ClearFIFO(void) 91{ 92 ASC_FIFO_Out = 0; 93 ASC_FIFO_InA = 0; 94 ASC_FIFO_InB = 0; 95 ASC_Playing = falseblnr; 96 ASC_RecalcStatus(); 97} 98 99GLOBALFUNC ui5b ASC_Access(ui5b Data, blnr WriteMem, CPTR addr) 100{ 101 if (addr < 0x800) { 102 if (WriteMem) { 103 if (1 == SoundReg801) { 104 if (0 == (addr & 0x400)) { 105 if (((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)) >= 0x400) 106 { 107#if 0 /* seems to happen in tetris */ 108 ReportAbnormalID(0x0F01, 109 "ASC - Channel A Overflow"); 110#endif 111 SoundReg804 |= 0x02; 112 } else { 113 114 ASC_SampBuff[ASC_FIFO_InA & 0x3FF] = Data; 115 116 ++ASC_FIFO_InA; 117 if (((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)) >= 0x200) 118 { 119 if (0 != (SoundReg804 & 0x01)) { 120 /* happens normally */ 121 SoundReg804 &= ~ 0x01; 122 } 123 } else { 124#if 0 /* doesn't seem to be necessary, but doesn't hurt either */ 125 SoundReg804 |= 0x01; 126#endif 127 } 128 if (((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)) >= 0x400) 129 { 130 SoundReg804 |= 0x02; 131#if ASC_dolog 132 dbglog_WriteNote("ASC : setting full flag A"); 133#endif 134 } else { 135 if (0 != (SoundReg804 & 0x02)) { 136 ReportAbnormalID(0x0F02, "ASC_Access : " 137 "full flag A not already clear"); 138 SoundReg804 &= ~ 0x02; 139 } 140 } 141 142 } 143 } else { 144 if (0 == (SoundReg802 & 2)) { 145 ReportAbnormalID(0x0F03, 146 "ASC - Channel B for Mono"); 147 } 148 if (((ui4b)(ASC_FIFO_InB - ASC_FIFO_Out)) >= 0x400) 149 { 150 ReportAbnormalID(0x0F04, 151 "ASC - Channel B Overflow"); 152 SoundReg804 |= 0x08; 153 } else { 154 155 ASC_SampBuff[0x400 + (ASC_FIFO_InB & 0x3FF)] = Data; 156 157 ++ASC_FIFO_InB; 158 if (((ui4b)(ASC_FIFO_InB - ASC_FIFO_Out)) >= 0x200) 159 { 160 if (0 != (SoundReg804 & 0x04)) { 161 /* happens normally */ 162 SoundReg804 &= ~ 0x04; 163 } 164 } else { 165#if 0 /* doesn't seem to be necessary, but doesn't hurt either */ 166 SoundReg804 |= 0x04; 167#endif 168 } 169 if (((ui4b)(ASC_FIFO_InB - ASC_FIFO_Out)) >= 0x400) 170 { 171 SoundReg804 |= 0x08; 172#if ASC_dolog 173 dbglog_WriteNote("ASC : setting full flag B"); 174#endif 175 } else { 176 if (0 != (SoundReg804 & 0x08)) { 177 ReportAbnormalID(0x0F05, "ASC_Access : " 178 "full flag B not already clear"); 179 SoundReg804 &= ~ 0x08; 180 } 181 } 182 183 } 184 } 185#if ASC_dolog && 0 186 dbglog_writeCStr("ASC_InputIndex ="); 187 dbglog_writeNum(ASC_InputIndex); 188 dbglog_writeReturn(); 189#endif 190 } else { 191 ASC_SampBuff[addr] = Data; 192 } 193 } else { 194 Data = ASC_SampBuff[addr]; 195 } 196 197#if ASC_dolog && 1 198#if 0 199 if (((addr & 0x1FF) >= 0x04) 200 && ((addr & 0x1FF) < (0x200 - 0x04))) 201 { 202 /* don't report them all */ 203 } else 204#endif 205 { 206 dbglog_AddrAccess("ASC_Access SampBuff", 207 Data, WriteMem, addr); 208 } 209#endif 210 } else if (addr < 0x810) { 211 switch (addr) { 212 case 0x800: /* VERSION */ 213 if (WriteMem) { 214 ReportAbnormalID(0x0F06, "ASC - writing VERSION"); 215 } else { 216 Data = 0; 217 } 218#if ASC_dolog && 1 219 dbglog_AddrAccess("ASC_Access Control (VERSION)", 220 Data, WriteMem, addr); 221#endif 222 break; 223 case 0x801: /* ENABLE */ 224 if (WriteMem) { 225 if (1 == Data) { 226 if (1 != SoundReg801) { 227 ASC_ClearFIFO(); 228 } 229 } else { 230 if (Data > 2) { 231 ReportAbnormalID(0x0F07, 232 "ASC - unexpected ENABLE"); 233 } 234 } 235 SoundReg801 = Data; 236 } else { 237 Data = SoundReg801; 238 /* happens in LodeRunner */ 239 } 240#if ASC_dolog && 1 241 dbglog_AddrAccess("ASC_Access Control (ENABLE)", 242 Data, WriteMem, addr); 243#endif 244 break; 245 case 0x802: /* CONTROL */ 246 if (WriteMem) { 247#if 1 248 if (0 != SoundReg801) { 249 if (SoundReg802 == Data) { 250 /* 251 this happens normally, 252 such as in Lunar Phantom 253 */ 254 } else { 255 if (1 == SoundReg801) { 256/* 257 happens in dark castle, if play other sound first, 258 such as by changing beep sound in sound control panel. 259*/ 260 ASC_ClearFIFO(); 261 } 262 263#if 0 264 ReportAbnormalID(0x0F08, 265 "ASC - changing CONTROL while ENABLEd"); 266#endif 267 } 268 } 269#endif 270 if (0 != (Data & ~ 2)) { 271 ReportAbnormalID(0x0F09, 272 "ASC - unexpected CONTROL value"); 273 } 274 SoundReg802 = Data; 275 } else { 276 Data = SoundReg802; 277 ReportAbnormalID(0x0F0A, 278 "ASC - reading CONTROL value"); 279 } 280#if ASC_dolog && 1 281 dbglog_AddrAccess("ASC_Access Control (CONTROL)", 282 Data, WriteMem, addr); 283#endif 284 break; 285 case 0x803: 286 if (WriteMem) { 287 if (0 != (Data & ~ 0x80)) { 288 ReportAbnormalID(0x0F0B, 289 "ASC - unexpected FIFO MODE"); 290 } 291 if (0 != (Data & 0x80)) { 292 if (0 != (SoundReg803 & 0x80)) { 293 ReportAbnormalID(0x0F0C, 294 "ASC - set clear FIFO again"); 295 } else 296 if (1 != SoundReg801) { 297#if 0 /* happens in system 6, such as with Lunar Phantom */ 298 ReportAbnormalID(0x0F0D, 299 "ASC - clear FIFO when not FIFO mode"); 300#endif 301 } else 302 { 303 ASC_ClearFIFO(); 304 /* 305 ASC_interrupt_PulseNtfy(); 306 Doesn't seem to be needed, 307 but doesn't hurt either. 308 */ 309 } 310 } 311 SoundReg803 = Data; 312 } else { 313 Data = SoundReg803; 314 } 315#if ASC_dolog && 1 316 dbglog_AddrAccess("ASC_Access Control (FIFO MODE)", 317 Data, WriteMem, addr); 318#endif 319 break; 320 case 0x804: 321 if (WriteMem) { 322#if 0 323 if ((0 != SoundReg804) && (0 != Data)) { 324 ReportAbnormalID(0x0F0F, 325 "ASC - set FIFO IRQ STATUS when not 0"); 326 } 327#endif 328 SoundReg804 = Data; 329 if (0 != SoundReg804) { 330#ifdef ASC_interrupt_PulseNtfy 331 ASC_interrupt_PulseNtfy(); 332#endif 333 /* 334 Generating this interrupt seems 335 to be the point of writing to 336 this register. 337 */ 338 } 339#if ASC_dolog && 1 340 dbglog_AddrAccess( 341 "ASC_Access Control (FIFO IRQ STATUS)", 342 Data, WriteMem, addr); 343#endif 344 } else { 345 Data = SoundReg804; 346#if 0 347 if (1 != SoundReg801) { 348 /* no, ok, part of normal interrupt handling */ 349 ReportAbnormalID(0x0F10, 350 "ASC - read STATUS when not FIFO"); 351 } 352#endif 353 /* SoundReg804 = 0; */ 354 SoundReg804 &= ~ 0x01; 355 SoundReg804 &= ~ 0x04; 356 /* 357 In lunar phantom, observe checking 358 full flag before first write, but 359 status was read previous. 360 */ 361#if ASC_dolog && 1 362#if 0 363 if (0 != Data) 364#endif 365 { 366 dbglog_AddrAccess( 367 "ASC_Access Control (FIFO IRQ STATUS)", 368 Data, WriteMem, addr); 369 } 370#endif 371 } 372 break; 373 case 0x805: 374 if (WriteMem) { 375 SoundReg805 = Data; 376 /* cleared in LodeRunner */ 377 } else { 378 Data = SoundReg805; 379 ReportAbnormalID(0x0F11, 380 "ASC - reading WAVE CONTROL register"); 381 } 382#if ASC_dolog && 1 383 dbglog_AddrAccess("ASC_Access Control (WAVE CONTROL)", 384 Data, WriteMem, addr); 385#endif 386 break; 387 case 0x806: /* VOLUME */ 388 if (WriteMem) { 389 SoundReg_Volume = Data >> 5; 390 if (0 != (Data & 0x1F)) { 391 ReportAbnormalID(0x0F12, 392 "ASC - unexpected volume value"); 393 } 394 } else { 395 Data = SoundReg_Volume << 5; 396 ReportAbnormalID(0x0F13, 397 "ASC - reading volume register"); 398 } 399#if ASC_dolog && 1 400 dbglog_AddrAccess("ASC_Access Control (VOLUME)", 401 Data, WriteMem, addr); 402#endif 403 break; 404 case 0x807: /* CLOCK RATE */ 405 if (WriteMem) { 406 /* SoundReg807 = Data; */ 407 if (0 != Data) { 408 ReportAbnormalID(0x0F14, 409 "ASC - nonstandard CLOCK RATE"); 410 } 411 } else { 412 /* Data = SoundReg807; */ 413 ReportAbnormalID(0x0F15, 414 "ASC - reading CLOCK RATE"); 415 } 416#if ASC_dolog && 1 417 dbglog_AddrAccess("ASC_Access Control (CLOCK RATE)", 418 Data, WriteMem, addr); 419#endif 420 break; 421 case 0x808: /* CONTROL */ 422 if (WriteMem) { 423 ReportAbnormalID(0x0F16, "ASC - write to 808"); 424 } else { 425 /* happens on boot System 7.5.5 */ 426 Data = 0; 427 } 428#if ASC_dolog && 1 429 dbglog_AddrAccess("ASC_Access Control (CONTROL)", 430 Data, WriteMem, addr); 431#endif 432 break; 433 case 0x80A: /* ? */ 434 if (WriteMem) { 435 ReportAbnormalID(0x0F17, "ASC - write to 80A"); 436 } else { 437 /* 438 happens in system 6, Lunar Phantom, 439 soon after new game. 440 */ 441 Data = 0; 442 } 443#if ASC_dolog && 1 444 dbglog_AddrAccess("ASC_Access Control (80A)", 445 Data, WriteMem, addr); 446#endif 447 break; 448 default: 449 if (WriteMem) { 450 } else { 451 Data = 0; 452 } 453 ReportAbnormalID(0x0F18, "ASC - unknown ASC reg"); 454#if ASC_dolog && 1 455 dbglog_AddrAccess("ASC_Access Control (?)", 456 Data, WriteMem, addr); 457#endif 458 break; 459 } 460 } else if (addr < 0x830) { 461 ui3r b = addr & 3; 462 ui3r chan = ((addr - 0x810) >> 3) & 3; 463 464 if (0 != (addr & 4)) { 465 466 if (WriteMem) { 467 ASC_ChanA[chan].freq[b] = Data; 468 } else { 469 Data = ASC_ChanA[chan].freq[b]; 470 } 471#if ASC_dolog && 1 472 dbglog_AddrAccess("ASC_Access Control (frequency)", 473 Data, WriteMem, addr); 474#endif 475#if ASC_dolog && 0 476 dbglog_writeCStr("freq b="); 477 dbglog_writeNum(WriteMem); 478 dbglog_writeCStr(", chan="); 479 dbglog_writeNum(chan); 480 dbglog_writeReturn(); 481#endif 482 } else { 483 484 if (WriteMem) { 485 ASC_ChanA[chan].phase[b] = Data; 486 } else { 487 Data = ASC_ChanA[chan].phase[b]; 488 } 489#if ASC_dolog && 1 490 dbglog_AddrAccess("ASC_Access Control (phase)", 491 Data, WriteMem, addr); 492#endif 493 } 494 } else if (addr < 0x838) { 495#if ASC_dolog && 1 496 dbglog_AddrAccess("ASC_Access Control *** unknown reg", 497 Data, WriteMem, addr); 498#endif 499 } else { 500#if ASC_dolog && 1 501 dbglog_AddrAccess("ASC_Access Control ? *** unknown reg", 502 Data, WriteMem, addr); 503#endif 504 505 ReportAbnormalID(0x0F19, "unknown ASC reg"); 506 } 507 508 return Data; 509} 510 511/* 512 approximate volume levels of vMac, so: 513 514 x * vol_mult[SoundVolume] >> 16 515 + vol_offset[SoundVolume] 516 = {approx} (x - kCenterSound) / (8 - SoundVolume) + kCenterSound; 517*/ 518 519LOCALVAR const ui4b vol_mult[] = { 520 8192, 9362, 10922, 13107, 16384, 21845, 32768 521}; 522 523LOCALVAR const trSoundSamp vol_offset[] = { 524#if 3 == kLn2SoundSampSz 525 112, 110, 107, 103, 96, 86, 64, 0 526#elif 4 == kLn2SoundSampSz 527 28672, 28087, 27307, 26215, 24576, 21846, 16384, 0 528#else 529#error "unsupported kLn2SoundSampSz" 530#endif 531}; 532 533LOCALVAR const ui3r SubTick_n[kNumSubTicks] = { 534 23, 23, 23, 23, 23, 23, 23, 24, 535 23, 23, 23, 23, 23, 23, 23, 24 536}; 537 538GLOBALPROC ASC_SubTick(int SubTick) 539{ 540 ui4r actL; 541#if MySoundEnabled 542 tpSoundSamp p; 543#endif 544 ui4r i; 545 ui4r n = SubTick_n[SubTick]; 546#if MySoundEnabled 547 ui3b SoundVolume = SoundReg_Volume; 548#endif 549 550#if MySoundEnabled 551label_retry: 552 p = MySound_BeginWrite(n, &actL); 553#else 554 actL = n; 555#endif 556 if (actL > 0) { 557 558 if (1 == SoundReg801) { 559#if MySoundEnabled 560 ui3p addr; 561#endif 562 563 if (0 != (SoundReg802 & 2)) { 564 565 if (! ASC_Playing) { 566 if (((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)) >= 0x200) { 567 if (((ui4b)(ASC_FIFO_InB - ASC_FIFO_Out)) >= 0x200) 568 { 569 SoundReg804 &= ~ 0x01; 570 SoundReg804 &= ~ 0x04; 571 ASC_Playing = trueblnr; 572#if ASC_dolog 573 dbglog_WriteNote("ASC : start stereo playing"); 574#endif 575 } else { 576 if (((ui4b)(ASC_FIFO_InB - ASC_FIFO_Out)) == 0) 577 if (((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)) 578 >= 370) 579 { 580#if ASC_dolog 581 dbglog_WriteNote("ASC : switch to mono"); 582#endif 583 SoundReg802 &= ~ 2; 584 /* 585 cludge to get Tetris to work, 586 may not actually work on real machine. 587 */ 588 } 589 } 590 } 591 } 592 593 for (i = 0; i < actL; i++) { 594 if (((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)) == 0) { 595 ASC_Playing = falseblnr; 596 } 597 if (((ui4b)(ASC_FIFO_InB - ASC_FIFO_Out)) == 0) { 598 ASC_Playing = falseblnr; 599 } 600 if (! ASC_Playing) { 601#if MySoundEnabled 602 *p++ = 0x80; 603#endif 604 } else 605 { 606 607#if MySoundEnabled 608 addr = ASC_SampBuff + (ASC_FIFO_Out & 0x3FF); 609 610#if ASC_dolog && 1 611 dbglog_StartLine(); 612 dbglog_writeCStr("out sound "); 613 dbglog_writeCStr("["); 614 dbglog_writeHex(ASC_FIFO_Out); 615 dbglog_writeCStr("]"); 616 dbglog_writeCStr(" = "); 617 dbglog_writeHex(*addr); 618 dbglog_writeCStr(" , "); 619 dbglog_writeHex(addr[0x400]); 620 dbglog_writeReturn(); 621#endif 622 623 *p++ = ((addr[0] + addr[0x400]) 624#if 4 == kLn2SoundSampSz 625 << 8 626#endif 627 ) >> 1; 628#endif /* MySoundEnabled */ 629 630 ASC_FIFO_Out += 1; 631 632 } 633 } 634 635 } else { 636 637 /* mono */ 638 639 if (! ASC_Playing) { 640 if (((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)) >= 0x200) 641 { 642 SoundReg804 &= ~ 0x01; 643 ASC_Playing = trueblnr; 644#if ASC_dolog 645 dbglog_WriteNote("ASC : start mono playing"); 646#endif 647 } 648 } 649 650 for (i = 0; i < actL; i++) { 651 if (((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)) == 0) { 652 ASC_Playing = falseblnr; 653 } 654 if (! ASC_Playing) { 655#if MySoundEnabled 656 *p++ = 0x80; 657#endif 658 } else 659 { 660 661#if MySoundEnabled 662 addr = ASC_SampBuff + (ASC_FIFO_Out & 0x3FF); 663 664#if ASC_dolog && 1 665 dbglog_StartLine(); 666 dbglog_writeCStr("out sound "); 667 dbglog_writeCStr("["); 668 dbglog_writeHex(ASC_FIFO_Out); 669 dbglog_writeCStr("]"); 670 dbglog_writeCStr(" = "); 671 dbglog_writeHex(*addr); 672 dbglog_writeCStr(", in buff: "); 673 dbglog_writeHex((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)); 674 dbglog_writeReturn(); 675#endif 676 677 *p++ = (addr[0]) 678#if 4 == kLn2SoundSampSz 679 << 8 680#endif 681 ; 682#endif /* MySoundEnabled */ 683 684 /* Move the address on */ 685 /* *addr = 0x80; */ 686 /* addr += 2; */ 687 ASC_FIFO_Out += 1; 688 689 } 690 } 691 692 } 693 } else if (2 == SoundReg801) { 694#if MySoundEnabled 695 ui4r v; 696 ui4r i0; 697 ui4r i1; 698 ui4r i2; 699 ui4r i3; 700#endif 701 ui5r freq0 = do_get_mem_long(ASC_ChanA[0].freq); 702 ui5r freq1 = do_get_mem_long(ASC_ChanA[1].freq); 703 ui5r freq2 = do_get_mem_long(ASC_ChanA[2].freq); 704 ui5r freq3 = do_get_mem_long(ASC_ChanA[3].freq); 705 ui5r phase0 = do_get_mem_long(ASC_ChanA[0].phase); 706 ui5r phase1 = do_get_mem_long(ASC_ChanA[1].phase); 707 ui5r phase2 = do_get_mem_long(ASC_ChanA[2].phase); 708 ui5r phase3 = do_get_mem_long(ASC_ChanA[3].phase); 709#if ASC_dolog && 1 710 dbglog_writeCStr("freq0="); 711 dbglog_writeNum(freq0); 712 dbglog_writeCStr(", freq1="); 713 dbglog_writeNum(freq1); 714 dbglog_writeCStr(", freq2="); 715 dbglog_writeNum(freq2); 716 dbglog_writeCStr(", freq3="); 717 dbglog_writeNum(freq3); 718 dbglog_writeReturn(); 719#endif 720 for (i = 0; i < actL; i++) { 721 722 phase0 += freq0; 723 phase1 += freq1; 724 phase2 += freq2; 725 phase3 += freq3; 726 727#if MySoundEnabled 728 729#if 1 730 i0 = ((phase0 + 0x4000) >> 15) & 0x1FF; 731 i1 = ((phase1 + 0x4000) >> 15) & 0x1FF; 732 i2 = ((phase2 + 0x4000) >> 15) & 0x1FF; 733 i3 = ((phase3 + 0x4000) >> 15) & 0x1FF; 734#else 735 i0 = ((phase0 + 0x8000) >> 16) & 0x1FF; 736 i1 = ((phase1 + 0x8000) >> 16) & 0x1FF; 737 i2 = ((phase2 + 0x8000) >> 16) & 0x1FF; 738 i3 = ((phase3 + 0x8000) >> 16) & 0x1FF; 739#endif 740 741 v = ASC_SampBuff[i0] 742 + ASC_SampBuff[0x0200 + i1] 743 + ASC_SampBuff[0x0400 + i2] 744 + ASC_SampBuff[0x0600 + i3]; 745 746#if ASC_dolog && 1 747 dbglog_StartLine(); 748 dbglog_writeCStr("i0="); 749 dbglog_writeNum(i0); 750 dbglog_writeCStr(", i1="); 751 dbglog_writeNum(i1); 752 dbglog_writeCStr(", i2="); 753 dbglog_writeNum(i2); 754 dbglog_writeCStr(", i3="); 755 dbglog_writeNum(i3); 756 dbglog_writeCStr(", output sound v="); 757 dbglog_writeNum(v); 758 dbglog_writeReturn(); 759#endif 760 761 *p++ = (v >> 2); 762#endif /* MySoundEnabled */ 763 } 764 765 do_put_mem_long(ASC_ChanA[0].phase, phase0); 766 do_put_mem_long(ASC_ChanA[1].phase, phase1); 767 do_put_mem_long(ASC_ChanA[2].phase, phase2); 768 do_put_mem_long(ASC_ChanA[3].phase, phase3); 769 } else { 770#if MySoundEnabled 771 for (i = 0; i < actL; i++) { 772 *p++ = kCenterSound; 773 } 774#endif 775 } 776 777 778#if MySoundEnabled 779 if (SoundVolume < 7) { 780 /* 781 Usually have volume at 7, so this 782 is just for completeness. 783 */ 784 ui5b mult = (ui5b)vol_mult[SoundVolume]; 785 trSoundSamp offset = vol_offset[SoundVolume]; 786 787 p -= actL; 788 for (i = 0; i < actL; i++) { 789 *p = (trSoundSamp)((ui5b)(*p) * mult >> 16) + offset; 790 ++p; 791 } 792 } 793 794 MySound_EndWrite(actL); 795 n -= actL; 796 if (n > 0) { 797 goto label_retry; 798 } 799#endif 800 } 801 802#if 1 803 if ((1 == SoundReg801) && ASC_Playing) { 804 if (((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)) >= 0x200) { 805 if (0 != (SoundReg804 & 0x01)) { 806 ReportAbnormalID(0x0F1A, 807 "half flag A not already clear"); 808 SoundReg804 &= ~ 0x01; 809 } 810 } else { 811 if (0 != (SoundReg804 & 0x01)) { 812 /* happens in lode runner */ 813 } else { 814#if ASC_dolog 815 dbglog_WriteNote("setting half flag A"); 816#endif 817#ifdef ASC_interrupt_PulseNtfy 818 ASC_interrupt_PulseNtfy(); 819#endif 820 SoundReg804 |= 0x01; 821 } 822 } 823 if (((ui4b)(ASC_FIFO_InA - ASC_FIFO_Out)) >= 0x400) { 824 if (0 == (SoundReg804 & 0x02)) { 825 ReportAbnormalID(0x0F1B, "full flag A not already set"); 826 SoundReg804 |= 0x02; 827 } 828 } else { 829 if (0 != (SoundReg804 & 0x02)) { 830 /* ReportAbnormal("full flag A not already clear"); */ 831 SoundReg804 &= ~ 0x02; 832 } 833 } 834 if (0 != (SoundReg802 & 2)) { 835 if (((ui4b)(ASC_FIFO_InB - ASC_FIFO_Out)) >= 0x200) { 836 if (0 != (SoundReg804 & 0x04)) { 837 ReportAbnormalID(0x0F1C, 838 "half flag B not already clear"); 839 SoundReg804 &= ~ 0x04; 840 } 841 } else { 842 if (0 != (SoundReg804 & 0x04)) { 843 /* happens in Lunar Phantom */ 844 } else { 845#if ASC_dolog 846 dbglog_WriteNote("setting half flag B"); 847#endif 848#ifdef ASC_interrupt_PulseNtfy 849 ASC_interrupt_PulseNtfy(); 850#endif 851 SoundReg804 |= 0x04; 852 } 853 } 854 if (((ui4b)(ASC_FIFO_InB - ASC_FIFO_Out)) >= 0x400) { 855 if (0 == (SoundReg804 & 0x08)) { 856 ReportAbnormalID(0x0F1D, 857 "full flag B not already set"); 858 SoundReg804 |= 0x08; 859 } 860 } else { 861 if (0 != (SoundReg804 & 0x08)) { 862 /* 863 ReportAbnormal("full flag B not already clear"); 864 */ 865 SoundReg804 &= ~ 0x08; 866 } 867 } 868 } 869 } 870#endif 871} 872 873#endif /* EmASC */