this repo has no description
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 */