2 * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
4 * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and
5 * Jerremy Koot (jkoot@snes9x.com)
7 * Super FX C emulator code
8 * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and
10 * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_.
12 * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson.
13 * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_.
14 * C4 C code (c) Copyright 2001 Gary Henderson (gary.henderson@ntlworld.com).
16 * DOS port code contains the works of other authors. See headers in
19 * Snes9x homepage: http://www.snes9x.com
21 * Permission to use, copy, modify and distribute Snes9x in both binary and
22 * source form, for non-commercial purposes, is hereby granted without fee,
23 * providing that this license information and copyright notice appear with
24 * all copies and any derived work.
26 * This software is provided 'as-is', without any express or implied
27 * warranty. In no event shall the authors be held liable for any damages
28 * arising from the use of this software.
30 * Snes9x is freeware for PERSONAL USE only. Commercial users should
31 * seek permission of the copyright holders first. Commercial use includes
32 * charging money for Snes9x or software derived from Snes9x.
34 * The copyright holders request that bug fixes and improvements to the code
35 * should be forwarded to them so everyone can benefit from the modifications
38 * Super NES and Super Nintendo Entertainment System are trademarks of
39 * Nintendo Co., Limited and its subsidiary companies.
48 //extern int NoiseFreq [32];
50 void S9xTraceSoundDSP (const char *s, int i1 = 0, int i2 = 0, int i3 = 0,
51 int i4 = 0, int i5 = 0, int i6 = 0, int i7 = 0);
55 #define ABS(a) ((a) < 0 ? -(a) : (a))
59 unsigned long AttackRate [16] = {
60 4100, 2600, 1500, 1000, 640, 380, 260, 160,
61 96, 64, 40, 24, 16, 10, 6, 1
64 unsigned long DecayRate [8] = {
65 1200, 740, 440, 290, 180, 110, 74, 37
68 unsigned long SustainRate [32] = {
69 /*~0*/0xFFFFFFFF, 38000, 28000, 24000, 19000, 14000, 12000, 9400,
70 7100, 5900, 4700, 3500, 2900, 2400, 1800, 1500,
71 1200, 880, 740, 590, 440, 370, 290, 220,
72 180, 150, 110, 92, 74, 55, 37, 18
75 unsigned long IncreaseRate [32] = {
76 /*~0*/0xFFFFFFFF, 4100, 3100, 2600, 2000, 1500, 1300, 1000,
77 770, 640, 510, 380, 320, 260, 190, 160,
78 130, 96, 80, 64, 48, 40, 32, 24,
79 20, 16, 12, 10, 8, 6, 4, 2
82 unsigned long DecreaseRateExp [32] = {
83 /*~0*/0xFFFFFFFF, 38000, 28000, 24000, 19000, 14000, 12000, 9400,
84 7100, 5900, 4700, 3500, 2900, 2400, 1800, 1500,
85 1200, 880, 740, 590, 440, 370, 290, 220,
86 180, 150, 110, 92, 74, 55, 37, 18
89 // precalculated env rates for S9xSetEnvRate
90 unsigned long AttackERate [16][10];
91 unsigned long DecayERate [8][10];
92 unsigned long SustainERate [32][10];
93 unsigned long IncreaseERate [32][10];
94 unsigned long DecreaseERateExp[32][10];
95 unsigned long KeyOffERate[10];
98 static inline void S9xSetEnvelopeRate (int channel, unsigned long rate, int direction, int target, unsigned int mode)
100 S9xSetEnvRate (&SoundData.channels [channel], rate, direction, target, mode);
103 static inline void S9xSetSoundADSR (int channel, int attack_ind, int decay_ind,
104 int sustain_ind, int sustain_level, int release_rate)
106 int attack_rate = AttackRate [attack_ind];
107 int decay_rate = DecayRate [decay_ind];
108 int sustain_rate = SustainRate [sustain_ind];
110 // Hack for ROMs that use a very short attack rate, key on a
111 // channel, then switch to decay mode. e.g. Final Fantasy II.
112 if (attack_rate == 1)
115 SoundData.channels[channel].env_ind_attack = attack_ind;
116 SoundData.channels[channel].env_ind_decay = decay_ind;
117 SoundData.channels[channel].env_ind_sustain = sustain_ind;
119 SoundData.channels[channel].attack_rate = attack_rate;
120 SoundData.channels[channel].decay_rate = decay_rate;
121 SoundData.channels[channel].sustain_rate = sustain_rate;
122 SoundData.channels[channel].release_rate = release_rate;
123 SoundData.channels[channel].sustain_level = sustain_level + 1;
125 switch (SoundData.channels[channel].state)
128 S9xSetEnvelopeRate (channel, attack_rate, 1, 127, 0);
132 S9xSetEnvelopeRate (channel, decay_rate, -1,
133 (MAX_ENVELOPE_HEIGHT * (sustain_level + 1)) >> 3, 1<<28);
136 S9xSetEnvelopeRate (channel, sustain_rate, -1, 0, 2<<28);
141 static inline void S9xSetSoundVolume (int channel, short volume_left, short volume_right)
143 Channel *ch = &SoundData.channels[channel];
145 volume_left = (ABS(volume_right) + ABS(volume_left)) / 2;
147 ch->volume_left = volume_left;
148 ch->volume_right = volume_right;
149 ch-> left_vol_level = (ch->envx * volume_left) / 128;
150 ch->right_vol_level = (ch->envx * volume_right) / 128;
153 static inline void S9xSetMasterVolume (short volume_left, short volume_right)
155 if (Settings.DisableMasterVolume)
157 SoundData.master_volume_left = 127;
158 SoundData.master_volume_right = 127;
159 SoundData.master_volume [0] = SoundData.master_volume [1] = 127;
164 volume_left = (ABS (volume_right) + ABS (volume_left)) / 2;
165 SoundData.master_volume_left = volume_left;
166 SoundData.master_volume_right = volume_right;
167 SoundData.master_volume [0] = volume_left;
168 SoundData.master_volume [1] = volume_right;
172 static inline void S9xSetEchoVolume (short volume_left, short volume_right)
175 volume_left = (ABS (volume_right) + ABS (volume_left)) / 2;
176 SoundData.echo_volume_left = volume_left;
177 SoundData.echo_volume_right = volume_right;
178 SoundData.echo_volume [0] = volume_left;
179 SoundData.echo_volume [1] = volume_right;
182 static inline void S9xSetEchoWriteEnable (uint8 byte)
184 SoundData.echo_write_enabled = byte;
185 S9xSetEchoDelay (APU.DSP [APU_EDL] & 15);
188 static inline void S9xSetFrequencyModulationEnable (uint8 byte)
190 SoundData.pitch_mod = byte & (0xFE);//~1;
193 static inline int S9xGetEnvelopeHeight (int channel)
195 if ((Settings.SoundEnvelopeHeightReading ||
196 SNESGameFixes.SoundEnvelopeHeightReading2) &&
197 SoundData.channels[channel].state != SOUND_SILENT &&
198 SoundData.channels[channel].state != SOUND_GAIN)
200 return (SoundData.channels[channel].envx);
204 if (SNESGameFixes.SoundEnvelopeHeightReading2 &&
205 SoundData.channels[channel].state != SOUND_SILENT)
207 return (SoundData.channels[channel].envx);
213 static inline void S9xSetSoundHertz (int channel, int hertz)
215 SoundData.channels[channel].hertz = hertz;
216 S9xSetSoundFrequency (channel, hertz);
219 static inline void S9xSetSoundType (int channel, int type_of_sound)
221 SoundData.channels[channel].type = type_of_sound;
224 static inline bool8 S9xSetSoundMode (int channel, int mode)
226 Channel *ch = &SoundData.channels[channel];
231 if (ch->mode != MODE_NONE)
233 ch->mode = MODE_RELEASE;
238 case MODE_DECREASE_LINEAR:
239 case MODE_DECREASE_EXPONENTIAL:
241 if (ch->mode != MODE_RELEASE)
244 if (ch->state != SOUND_SILENT)
251 case MODE_INCREASE_LINEAR:
252 case MODE_INCREASE_BENT_LINE:
253 if (ch->mode != MODE_RELEASE)
256 if (ch->state != SOUND_SILENT)
264 if (ch->mode == MODE_NONE || ch->mode == MODE_ADSR)
274 static inline void S9xPlaySample (int channel)
276 Channel *ch = &SoundData.channels[channel];
278 ch->state = SOUND_SILENT;
279 ch->mode = MODE_NONE;
284 ch->gaussian[0]=ch->gaussian[1]=ch->gaussian[2]=ch->gaussian[3]=0;
286 S9xFixEnvelope (channel,
287 APU.DSP [APU_GAIN + (channel << 4)],
288 APU.DSP [APU_ADSR1 + (channel << 4)],
289 APU.DSP [APU_ADSR2 + (channel << 4)]);
291 ch->sample_number = APU.DSP [APU_SRCN + channel * 0x10];
292 if (APU.DSP [APU_NON] & (1 << channel))
293 ch->type = SOUND_NOISE;
295 ch->type = SOUND_SAMPLE;
297 S9xSetSoundFrequency (channel, ch->hertz);
299 ch->needs_decode = TRUE;
300 ch->last_block = FALSE;
301 ch->previous [0] = ch->previous[1] = 0;
302 ch->block_pointer = *S9xGetSampleAddress(ch->sample_number);
303 ch->sample_pointer = 0;
307 ch->last_valid_header=0;
311 if (ch->attack_rate == 0)
313 if (ch->decay_rate == 0 || ch->sustain_level == 8)
315 ch->state = SOUND_SUSTAIN;
316 ch->envx = (MAX_ENVELOPE_HEIGHT * ch->sustain_level) >> 3;
317 S9xSetEnvRate (ch, ch->sustain_rate, -1, 0, 2<<28);
321 ch->state = SOUND_DECAY;
322 ch->envx = MAX_ENVELOPE_HEIGHT;
323 S9xSetEnvRate (ch, ch->decay_rate, -1,
324 (MAX_ENVELOPE_HEIGHT * ch->sustain_level) >> 3, 1<<28);
326 ch-> left_vol_level = (ch->envx * ch->volume_left) / 128;
327 ch->right_vol_level = (ch->envx * ch->volume_right) / 128;
331 ch->state = SOUND_ATTACK;
333 ch->left_vol_level = 0;
334 ch->right_vol_level = 0;
335 S9xSetEnvRate (ch, ch->attack_rate, 1, MAX_ENVELOPE_HEIGHT, 0);
337 ch->envxx = ch->envx << ENVX_SHIFT;
341 ch->state = SOUND_GAIN;
344 case MODE_INCREASE_LINEAR:
345 ch->state = SOUND_INCREASE_LINEAR;
348 case MODE_INCREASE_BENT_LINE:
349 ch->state = SOUND_INCREASE_BENT_LINE;
352 case MODE_DECREASE_LINEAR:
353 ch->state = SOUND_DECREASE_LINEAR;
356 case MODE_DECREASE_EXPONENTIAL:
357 ch->state = SOUND_DECREASE_EXPONENTIAL;
364 S9xFixEnvelope (channel,
365 APU.DSP [APU_GAIN + (channel << 4)],
366 APU.DSP [APU_ADSR1 + (channel << 4)],
367 APU.DSP [APU_ADSR2 + (channel << 4)]);
371 extern "C" uint32 Spc700JumpTab;
377 memset(&IAPU, 0, sizeof(IAPU));
378 IAPU.ExtraRAM = APU.ExtraRAM;
380 IAPU.asmJumpTab = &Spc700JumpTab;
383 IAPU.RAM = (uint8 *) malloc (0x10000);
384 IAPU.ShadowRAM = NULL;//(uint8 *) malloc (0x10000);
385 IAPU.CachedSamples = NULL;//(uint8 *) malloc (0x40000);
387 if (!IAPU.RAM /*|| !IAPU.ShadowRAM || !IAPU.CachedSamples*/)
400 free ((char *) IAPU.RAM);
405 free ((char *) IAPU.ShadowRAM);
406 IAPU.ShadowRAM = NULL;
408 if (IAPU.CachedSamples)
410 free ((char *) IAPU.CachedSamples);
411 IAPU.CachedSamples = NULL;
415 EXTERN_C uint8 APUROM [64];
419 memset (IAPU.RAM, Settings.APURAMInitialValue, 0x10000);
420 //memset (IAPU.ShadowRAM, Settings.APURAMInitialValue, 0x10000);
422 //ZeroMemory (IAPU.CachedSamples, 0x40000);
423 ZeroMemory (APU.OutPorts, 4);
424 IAPU.DirectPage = IAPU.RAM;
425 memmove (&IAPU.RAM [0xffc0], APUROM, sizeof (APUROM));
426 memmove (APU.ExtraRAM, APUROM, sizeof (APUROM));
427 IAPU.PC = IAPU.RAM + IAPU.RAM [0xfffe] + (IAPU.RAM [0xffff] << 8);
433 S9xAPUUnpackStatus ();
434 CPU.APU_APUExecuting = Settings.APUEnabled;
435 #ifdef SPC700_SHUTDOWN
436 IAPU.WaitAddress1 = NULL;
437 IAPU.WaitAddress2 = NULL;
438 IAPU.WaitCounter = 0;
441 IAPU.RAM [0xf1] = 0x80;
445 for (i = 0; i < 3; i++)
447 APU.TimerEnabled [i] = FALSE;
448 APU.TimerValueWritten [i] = 0;
449 APU.TimerTarget [i] = 0;
452 for (int j = 0; j < 0x80; j++)
455 IAPU.TwoCycles = IAPU.OneCycle * 2;
457 for (i = 0; i < 256; i++)
458 S9xAPUCycles [i] = S9xAPUCycleLengths [i] * IAPU.OneCycle;
460 APU.DSP [APU_ENDX] = 0;
461 APU.DSP [APU_KOFF] = 0;
462 APU.DSP [APU_KON] = 0;
463 APU.DSP [APU_FLG] = APU_MUTE | APU_ECHO_DISABLED;
464 APU.KeyedChannels = 0;
466 S9xResetSound (TRUE);
467 S9xSetEchoEnable (0);
470 extern int framecpto;
471 void S9xSetAPUDSP (uint8 byte)
473 uint8 reg = IAPU.RAM [0xf2];
475 static uint8 KeyOnPrev;
481 if (byte & APU_SOFT_RESET)
483 APU.DSP [reg] = APU_MUTE | APU_ECHO_DISABLED | (byte & 0x1f);
484 APU.DSP [APU_ENDX] = 0;
485 APU.DSP [APU_KOFF] = 0;
486 APU.DSP [APU_KON] = 0;
487 S9xSetEchoWriteEnable (FALSE);
489 if (Settings.TraceSoundDSP)
490 S9xTraceSoundDSP ("[%d] DSP reset\n", ICPU.Scanline);
493 S9xResetSound (FALSE);
497 S9xSetEchoWriteEnable (!(byte & APU_ECHO_DISABLED));
501 if (Settings.TraceSoundDSP)
502 S9xTraceSoundDSP ("[%d] Mute sound\n", ICPU.Scanline);
504 S9xSetSoundMute (TRUE);
507 S9xSetSoundMute (FALSE);
509 SoundData.noise_hertz = NoiseFreq [byte & 0x1f];
510 for (i = 0; i < 8; i++)
512 if (SoundData.channels [i].type == SOUND_NOISE)
513 S9xSetSoundFrequency (i, SoundData.noise_hertz);
518 if (byte != APU.DSP [APU_NON])
521 if (Settings.TraceSoundDSP)
522 S9xTraceSoundDSP ("[%d] Noise:", ICPU.Scanline);
525 for (int c = 0; c < 8; c++, mask <<= 1)
527 uint8 bit = byte & mask;
531 if (Settings.TraceSoundDSP)
533 if (APU.DSP [reg] & mask)
534 S9xTraceSoundDSP ("%d,", c);
536 S9xTraceSoundDSP ("%d(on),", c);
539 S9xSetSoundType(c, SOUND_NOISE);
544 if (Settings.TraceSoundDSP)
546 if (APU.DSP [reg] & mask)
547 S9xTraceSoundDSP ("%d(off),", c);
550 S9xSetSoundType(c, SOUND_SAMPLE);
554 if (Settings.TraceSoundDSP)
555 S9xTraceSoundDSP ("\n");
560 if (byte != APU.DSP [APU_MVOL_LEFT])
563 if (Settings.TraceSoundDSP)
564 S9xTraceSoundDSP ("[%d] Master volume left:%d\n",
565 ICPU.Scanline, (signed char) byte);
567 S9xSetMasterVolume ((signed char) byte,
568 (signed char) APU.DSP [APU_MVOL_RIGHT]);
572 if (byte != APU.DSP [APU_MVOL_RIGHT])
575 if (Settings.TraceSoundDSP)
576 S9xTraceSoundDSP ("[%d] Master volume right:%d\n",
577 ICPU.Scanline, (signed char) byte);
579 S9xSetMasterVolume ((signed char) APU.DSP [APU_MVOL_LEFT],
584 if (byte != APU.DSP [APU_EVOL_LEFT])
587 if (Settings.TraceSoundDSP)
588 S9xTraceSoundDSP ("[%d] Echo volume left:%d\n",
589 ICPU.Scanline, (signed char) byte);
591 S9xSetEchoVolume ((signed char) byte,
592 (signed char) APU.DSP [APU_EVOL_RIGHT]);
596 if (byte != APU.DSP [APU_EVOL_RIGHT])
599 if (Settings.TraceSoundDSP)
600 S9xTraceSoundDSP ("[%d] Echo volume right:%d\n",
601 ICPU.Scanline, (signed char) byte);
603 S9xSetEchoVolume ((signed char) APU.DSP [APU_EVOL_LEFT],
609 if (Settings.TraceSoundDSP)
610 S9xTraceSoundDSP ("[%d] Reset ENDX\n", ICPU.Scanline);
620 if (Settings.TraceSoundDSP)
621 S9xTraceSoundDSP ("[%d] Key off:", ICPU.Scanline);
623 for (int c = 0; c < 8; c++, mask <<= 1)
625 if ((byte & mask) != 0)
629 if (Settings.TraceSoundDSP)
630 S9xTraceSoundDSP ("%d,", c);
632 if (APU.KeyedChannels & mask)
636 APU.KeyedChannels &= ~mask;
637 APU.DSP [APU_KON] &= ~mask;
638 //APU.DSP [APU_KOFF] |= mask;
639 S9xSetSoundKeyOff (c);
643 else if((KeyOnPrev&mask)!=0)
646 APU.KeyedChannels |= mask;
647 //APU.DSP [APU_KON] |= mask;
648 APU.DSP [APU_KOFF] &= ~mask;
649 APU.DSP [APU_ENDX] &= ~mask;
654 if (Settings.TraceSoundDSP)
655 S9xTraceSoundDSP ("\n");
659 APU.DSP [APU_KOFF] = byte;
668 if (Settings.TraceSoundDSP)
669 S9xTraceSoundDSP ("[%d] Key on:", ICPU.Scanline);
671 for (int c = 0; c < 8; c++, mask <<= 1)
673 if ((byte & mask) != 0)
676 if (Settings.TraceSoundDSP)
677 S9xTraceSoundDSP ("%d,", c);
679 // Pac-In-Time requires that channels can be key-on
680 // regardeless of their current state.
681 if((APU.DSP [APU_KOFF] & mask) ==0)
684 APU.KeyedChannels |= mask;
685 //APU.DSP [APU_KON] |= mask;
686 //APU.DSP [APU_KOFF] &= ~mask;
687 APU.DSP [APU_ENDX] &= ~mask;
694 if (Settings.TraceSoundDSP)
695 S9xTraceSoundDSP ("\n");
701 case APU_VOL_LEFT + 0x00:
702 case APU_VOL_LEFT + 0x10:
703 case APU_VOL_LEFT + 0x20:
704 case APU_VOL_LEFT + 0x30:
705 case APU_VOL_LEFT + 0x40:
706 case APU_VOL_LEFT + 0x50:
707 case APU_VOL_LEFT + 0x60:
708 case APU_VOL_LEFT + 0x70:
709 // At Shin Megami Tensei suggestion 6/11/00
710 // if (byte != APU.DSP [reg])
713 if (Settings.TraceSoundDSP)
714 S9xTraceSoundDSP ("[%d] %d volume left: %d\n",
715 ICPU.Scanline, reg>>4, (signed char) byte);
717 S9xSetSoundVolume (reg >> 4, (signed char) byte,
718 (signed char) APU.DSP [reg + 1]);
721 case APU_VOL_RIGHT + 0x00:
722 case APU_VOL_RIGHT + 0x10:
723 case APU_VOL_RIGHT + 0x20:
724 case APU_VOL_RIGHT + 0x30:
725 case APU_VOL_RIGHT + 0x40:
726 case APU_VOL_RIGHT + 0x50:
727 case APU_VOL_RIGHT + 0x60:
728 case APU_VOL_RIGHT + 0x70:
729 // At Shin Megami Tensei suggestion 6/11/00
730 // if (byte != APU.DSP [reg])
733 if (Settings.TraceSoundDSP)
734 S9xTraceSoundDSP ("[%d] %d volume right: %d\n",
735 ICPU.Scanline, reg >>4, (signed char) byte);
737 S9xSetSoundVolume (reg >> 4, (signed char) APU.DSP [reg - 1],
742 case APU_P_LOW + 0x00:
743 case APU_P_LOW + 0x10:
744 case APU_P_LOW + 0x20:
745 case APU_P_LOW + 0x30:
746 case APU_P_LOW + 0x40:
747 case APU_P_LOW + 0x50:
748 case APU_P_LOW + 0x60:
749 case APU_P_LOW + 0x70:
751 if (Settings.TraceSoundDSP)
752 S9xTraceSoundDSP ("[%d] %d freq low: %d\n",
753 ICPU.Scanline, reg>>4, byte);
755 S9xSetSoundHertz (reg >> 4, (((byte + (APU.DSP [reg + 1] << 8)) & FREQUENCY_MASK) * 32000) >> 12);
758 case APU_P_HIGH + 0x00:
759 case APU_P_HIGH + 0x10:
760 case APU_P_HIGH + 0x20:
761 case APU_P_HIGH + 0x30:
762 case APU_P_HIGH + 0x40:
763 case APU_P_HIGH + 0x50:
764 case APU_P_HIGH + 0x60:
765 case APU_P_HIGH + 0x70:
767 if (Settings.TraceSoundDSP)
768 S9xTraceSoundDSP ("[%d] %d freq high: %d\n",
769 ICPU.Scanline, reg>>4, byte);
771 S9xSetSoundHertz (reg >> 4,
772 (((byte << 8) + APU.DSP [reg - 1]) & FREQUENCY_MASK) * 8);
775 case APU_SRCN + 0x00:
776 case APU_SRCN + 0x10:
777 case APU_SRCN + 0x20:
778 case APU_SRCN + 0x30:
779 case APU_SRCN + 0x40:
780 case APU_SRCN + 0x50:
781 case APU_SRCN + 0x60:
782 case APU_SRCN + 0x70:
783 if (byte != APU.DSP [reg])
786 if (Settings.TraceSoundDSP)
787 S9xTraceSoundDSP ("[%d] %d sample number: %d\n",
788 ICPU.Scanline, reg>>4, byte);
790 //S9xSetSoundSample (reg >> 4, byte); // notaz: seems to be unused?
794 case APU_ADSR1 + 0x00:
795 case APU_ADSR1 + 0x10:
796 case APU_ADSR1 + 0x20:
797 case APU_ADSR1 + 0x30:
798 case APU_ADSR1 + 0x40:
799 case APU_ADSR1 + 0x50:
800 case APU_ADSR1 + 0x60:
801 case APU_ADSR1 + 0x70:
802 if (byte != APU.DSP [reg])
805 if (Settings.TraceSoundDSP)
806 S9xTraceSoundDSP ("[%d] %d adsr1: %02x\n",
807 ICPU.Scanline, reg>>4, byte);
810 S9xFixEnvelope (reg >> 4, APU.DSP [reg + 2], byte,
816 case APU_ADSR2 + 0x00:
817 case APU_ADSR2 + 0x10:
818 case APU_ADSR2 + 0x20:
819 case APU_ADSR2 + 0x30:
820 case APU_ADSR2 + 0x40:
821 case APU_ADSR2 + 0x50:
822 case APU_ADSR2 + 0x60:
823 case APU_ADSR2 + 0x70:
824 if (byte != APU.DSP [reg])
827 if (Settings.TraceSoundDSP)
828 S9xTraceSoundDSP ("[%d] %d adsr2: %02x\n",
829 ICPU.Scanline, reg>>4, byte);
832 S9xFixEnvelope (reg >> 4, APU.DSP [reg + 1], APU.DSP [reg - 1],
838 case APU_GAIN + 0x00:
839 case APU_GAIN + 0x10:
840 case APU_GAIN + 0x20:
841 case APU_GAIN + 0x30:
842 case APU_GAIN + 0x40:
843 case APU_GAIN + 0x50:
844 case APU_GAIN + 0x60:
845 case APU_GAIN + 0x70:
846 if (byte != APU.DSP [reg])
849 if (Settings.TraceSoundDSP)
850 S9xTraceSoundDSP ("[%d] %d gain: %02x\n",
851 ICPU.Scanline, reg>>4, byte);
854 S9xFixEnvelope (reg >> 4, byte, APU.DSP [reg - 2],
860 case APU_ENVX + 0x00:
861 case APU_ENVX + 0x10:
862 case APU_ENVX + 0x20:
863 case APU_ENVX + 0x30:
864 case APU_ENVX + 0x40:
865 case APU_ENVX + 0x50:
866 case APU_ENVX + 0x60:
867 case APU_ENVX + 0x70:
870 case APU_OUTX + 0x00:
871 case APU_OUTX + 0x10:
872 case APU_OUTX + 0x20:
873 case APU_OUTX + 0x30:
874 case APU_OUTX + 0x40:
875 case APU_OUTX + 0x50:
876 case APU_OUTX + 0x60:
877 case APU_OUTX + 0x70:
882 if (Settings.TraceSoundDSP)
883 S9xTraceSoundDSP ("[%d] Sample directory to: %02x\n",
884 ICPU.Scanline, byte);
889 if (byte != APU.DSP [APU_PMON])
892 if (Settings.TraceSoundDSP)
894 S9xTraceSoundDSP ("[%d] FreqMod:", ICPU.Scanline);
896 for (int c = 0; c < 8; c++, mask <<= 1)
900 if (APU.DSP [reg] & mask)
901 S9xTraceSoundDSP ("%d", c);
903 S9xTraceSoundDSP ("%d(on),", c);
907 if (APU.DSP [reg] & mask)
908 S9xTraceSoundDSP ("%d(off),", c);
911 S9xTraceSoundDSP ("\n");
914 S9xSetFrequencyModulationEnable (byte);
919 if (byte != APU.DSP [APU_EON])
922 if (Settings.TraceSoundDSP)
924 S9xTraceSoundDSP ("[%d] Echo:", ICPU.Scanline);
926 for (int c = 0; c < 8; c++, mask <<= 1)
930 if (APU.DSP [reg] & mask)
931 S9xTraceSoundDSP ("%d", c);
933 S9xTraceSoundDSP ("%d(on),", c);
937 if (APU.DSP [reg] & mask)
938 S9xTraceSoundDSP ("%d(off),", c);
941 S9xTraceSoundDSP ("\n");
944 S9xSetEchoEnable (byte);
949 S9xSetEchoFeedback ((signed char) byte);
956 S9xSetEchoDelay (byte & 0xf);
967 S9xSetFilterCoefficient (reg >> 4, (signed char) byte);
971 //printf ("Write %02x to unknown APU register %02x\n", byte, reg);
979 APU.DSP [reg] = byte;
982 void S9xFixEnvelope (int channel, uint8 gain, uint8 adsr1, uint8 adsr2)
988 // XXX: can DSP be switched to ADSR mode directly from GAIN/INCREASE/
989 // DECREASE mode? And if so, what stage of the sequence does it start
991 if (S9xSetSoundMode (channel, MODE_ADSR))
993 S9xSetSoundADSR (channel, adsr1 & 0xf, (adsr1 >> 4) & 7, adsr2 & 0x1f, (adsr2 >> 5) & 7, 8);
999 if ((gain & 0x80) == 0)
1001 if (S9xSetSoundMode (channel, MODE_GAIN))
1003 S9xSetEnvelopeRate (channel, 0, 0, gain & 0x7f, 0);
1004 S9xSetEnvelopeHeight (channel, gain & 0x7f);
1013 if (S9xSetSoundMode (channel, (gain & 0x20) ?
1014 MODE_INCREASE_BENT_LINE :
1015 MODE_INCREASE_LINEAR))
1017 S9xSetEnvelopeRate (channel, IncreaseRate [gain & 0x1f], 1, 127, (3<<28)|gain);
1023 if (S9xSetSoundMode (channel, MODE_DECREASE_EXPONENTIAL))
1024 S9xSetEnvelopeRate (channel, DecreaseRateExp [gain & 0x1f] / 2, -1, 0, (4<<28)|gain);
1026 if (S9xSetSoundMode (channel, MODE_DECREASE_LINEAR))
1027 S9xSetEnvelopeRate (channel, IncreaseRate [gain & 0x1f], -1, 0, (3<<28)|gain);
1034 void S9xSetAPUControl (uint8 byte)
1037 //printf ("*** Special SPC700 timing enabled\n");
1038 if ((byte & 1) != 0 && !APU.TimerEnabled [0])
1041 IAPU.RAM [0xfd] = 0;
1042 if ((APU.TimerTarget [0] = IAPU.RAM [0xfa]) == 0)
1043 APU.TimerTarget [0] = 0x100;
1045 if ((byte & 2) != 0 && !APU.TimerEnabled [1])
1048 IAPU.RAM [0xfe] = 0;
1049 if ((APU.TimerTarget [1] = IAPU.RAM [0xfb]) == 0)
1050 APU.TimerTarget [1] = 0x100;
1052 if ((byte & 4) != 0 && !APU.TimerEnabled [2])
1055 IAPU.RAM [0xff] = 0;
1056 if ((APU.TimerTarget [2] = IAPU.RAM [0xfc]) == 0)
1057 APU.TimerTarget [2] = 0x100;
1059 APU.TimerEnabled [0] = byte & 1;
1060 APU.TimerEnabled [1] = (byte & 2) >> 1;
1061 APU.TimerEnabled [2] = (byte & 4) >> 2;
1064 IAPU.RAM [0xF4] = IAPU.RAM [0xF5] = 0;
1067 IAPU.RAM [0xF6] = IAPU.RAM [0xF7] = 0;
1073 memmove (&IAPU.RAM [0xffc0], APUROM, sizeof (APUROM));
1081 APU.ShowROM = FALSE;
1082 memmove (&IAPU.RAM [0xffc0], APU.ExtraRAM, sizeof (APUROM));
1085 IAPU.RAM [0xf1] = byte;
1088 void S9xSetAPUTimer (uint16 Address, uint8 byte)
1090 IAPU.RAM [Address] = byte;
1095 if ((APU.TimerTarget [0] = IAPU.RAM [0xfa]) == 0)
1096 APU.TimerTarget [0] = 0x100;
1097 APU.TimerValueWritten [0] = TRUE;
1100 if ((APU.TimerTarget [1] = IAPU.RAM [0xfb]) == 0)
1101 APU.TimerTarget [1] = 0x100;
1102 APU.TimerValueWritten [1] = TRUE;
1105 if ((APU.TimerTarget [2] = IAPU.RAM [0xfc]) == 0)
1106 APU.TimerTarget [2] = 0x100;
1107 APU.TimerValueWritten [2] = TRUE;
1112 uint8 S9xGetAPUDSP ()
1114 uint8 reg = IAPU.RAM [0xf2] & 0x7f;
1115 uint8 byte = APU.DSP [reg];
1123 case APU_OUTX + 0x00:
1124 case APU_OUTX + 0x10:
1125 case APU_OUTX + 0x20:
1126 case APU_OUTX + 0x30:
1127 case APU_OUTX + 0x40:
1128 case APU_OUTX + 0x50:
1129 case APU_OUTX + 0x60:
1130 case APU_OUTX + 0x70:
1131 if (SoundData.channels [reg >> 4].state == SOUND_SILENT)
1133 return ((SoundData.channels [reg >> 4].sample >> 8) |
1134 (SoundData.channels [reg >> 4].sample & 0xff));
1136 case APU_ENVX + 0x00:
1137 case APU_ENVX + 0x10:
1138 case APU_ENVX + 0x20:
1139 case APU_ENVX + 0x30:
1140 case APU_ENVX + 0x40:
1141 case APU_ENVX + 0x50:
1142 case APU_ENVX + 0x60:
1143 case APU_ENVX + 0x70:
1145 // return ((uint8) S9xGetEnvelopeHeight (reg >> 4));
1148 // To fix speech in Magical Drop 2 6/11/00
1149 // APU.DSP [APU_ENDX] = 0;