adding screenshot to savestate files
[drnoksnes] / apu.cpp
1 /*
2  * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
3  *
4  * (c) Copyright 1996 - 2001 Gary Henderson (gary.henderson@ntlworld.com) and
5  *                           Jerremy Koot (jkoot@snes9x.com)
6  *
7  * Super FX C emulator code 
8  * (c) Copyright 1997 - 1999 Ivar (ivar@snes9x.com) and
9  *                           Gary Henderson.
10  * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_.
11  *
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).
15  *
16  * DOS port code contains the works of other authors. See headers in
17  * individual files.
18  *
19  * Snes9x homepage: http://www.snes9x.com
20  *
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.
25  *
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.
29  *
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.
33  *
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
36  * in future versions.
37  *
38  * Super NES and Super Nintendo Entertainment System are trademarks of
39  * Nintendo Co., Limited and its subsidiary companies.
40  */
41
42 #include "snes9x.h"
43 #include "spc700.h"
44 #include "apu.h"
45 #include "soundux.h"
46 #include "cpuexec.h"
47
48 //extern int NoiseFreq [32];
49 #ifdef DEBUGGER
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);
52 #endif
53
54 #undef ABS
55 #define ABS(a) ((a) < 0 ? -(a) : (a))
56 #define ENVX_SHIFT 24
57
58
59 unsigned long AttackRate [16] = {
60         4100, 2600, 1500, 1000, 640, 380, 260, 160,
61         96, 64, 40, 24, 16, 10, 6, 1
62 };
63
64 unsigned long DecayRate [8] = {
65         1200, 740, 440, 290, 180, 110, 74, 37
66 };
67
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
73 };
74         
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
80 };
81
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
87 };      
88
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];
96
97
98 static inline void S9xSetEnvelopeRate (int channel, unsigned long rate, int direction, int target, unsigned int mode)
99 {
100     S9xSetEnvRate (&SoundData.channels [channel], rate, direction, target, mode);
101 }
102
103 static inline void S9xSetSoundADSR (int channel, int attack_ind, int decay_ind,
104                       int sustain_ind, int sustain_level, int release_rate)
105 {
106         int attack_rate = AttackRate [attack_ind];
107         int decay_rate = DecayRate [decay_ind];
108         int sustain_rate = SustainRate [sustain_ind];
109         
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)
113                 attack_rate = 0;
114
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;
118
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;
124
125     switch (SoundData.channels[channel].state)
126     {
127     case SOUND_ATTACK:
128         S9xSetEnvelopeRate (channel, attack_rate, 1, 127, 0);
129         break;
130
131     case SOUND_DECAY:
132         S9xSetEnvelopeRate (channel, decay_rate, -1,
133                             (MAX_ENVELOPE_HEIGHT * (sustain_level + 1)) >> 3, 1<<28);
134         break;
135     case SOUND_SUSTAIN:
136         S9xSetEnvelopeRate (channel, sustain_rate, -1, 0, 2<<28);
137         break;
138     }
139 }
140
141 static inline void S9xSetSoundVolume (int channel, short volume_left, short volume_right)
142 {
143     Channel *ch = &SoundData.channels[channel];
144     if (!so.stereo)
145         volume_left = (ABS(volume_right) + ABS(volume_left)) / 2;
146
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;
151 }
152
153 static inline void S9xSetMasterVolume (short volume_left, short volume_right)
154 {
155     if (Settings.DisableMasterVolume)
156     {
157         SoundData.master_volume_left = 127;
158         SoundData.master_volume_right = 127;
159         SoundData.master_volume [0] = SoundData.master_volume [1] = 127;
160     }
161     else
162     {
163         if (!so.stereo)
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;
169     }
170 }
171
172 static inline void S9xSetEchoVolume (short volume_left, short volume_right)
173 {
174     if (!so.stereo)
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;
180 }
181
182 static inline void S9xSetEchoWriteEnable (uint8 byte)
183 {
184     SoundData.echo_write_enabled = byte;
185     S9xSetEchoDelay (APU.DSP [APU_EDL] & 15);
186 }
187
188 static inline void S9xSetFrequencyModulationEnable (uint8 byte)
189 {
190     SoundData.pitch_mod = byte & (0xFE);//~1;
191 }
192
193 static inline int S9xGetEnvelopeHeight (int channel)
194 {
195     if ((Settings.SoundEnvelopeHeightReading ||
196          SNESGameFixes.SoundEnvelopeHeightReading2) &&
197         SoundData.channels[channel].state != SOUND_SILENT &&
198         SoundData.channels[channel].state != SOUND_GAIN)
199     {
200         return (SoundData.channels[channel].envx);
201     }
202
203     //siren fix from XPP
204     if (SNESGameFixes.SoundEnvelopeHeightReading2 &&
205         SoundData.channels[channel].state != SOUND_SILENT)
206     {
207         return (SoundData.channels[channel].envx);
208     }
209
210     return (0);
211 }
212
213 static inline void S9xSetSoundHertz (int channel, int hertz)
214 {
215     SoundData.channels[channel].hertz = hertz;
216     S9xSetSoundFrequency (channel, hertz);
217 }
218
219 static inline void S9xSetSoundType (int channel, int type_of_sound)
220 {
221     SoundData.channels[channel].type = type_of_sound;
222 }
223
224 static inline bool8 S9xSetSoundMode (int channel, int mode)
225 {
226     Channel *ch = &SoundData.channels[channel];
227
228     switch (mode)
229     {
230     case MODE_RELEASE:
231         if (ch->mode != MODE_NONE)
232         {
233             ch->mode = MODE_RELEASE;
234             return (TRUE);
235         }
236         break;
237         
238     case MODE_DECREASE_LINEAR:
239     case MODE_DECREASE_EXPONENTIAL:
240     case MODE_GAIN:
241         if (ch->mode != MODE_RELEASE)
242         {
243             ch->mode = mode;
244             if (ch->state != SOUND_SILENT)
245                 ch->state = mode;
246
247             return (TRUE);
248         }
249         break;
250
251     case MODE_INCREASE_LINEAR:
252     case MODE_INCREASE_BENT_LINE:
253         if (ch->mode != MODE_RELEASE)
254         {
255             ch->mode = mode;
256             if (ch->state != SOUND_SILENT)
257                 ch->state = mode;
258
259             return (TRUE);
260         }
261         break;
262
263     case MODE_ADSR:
264         if (ch->mode == MODE_NONE || ch->mode == MODE_ADSR)
265         {
266             ch->mode = mode;
267             return (TRUE);
268         }
269     }
270
271     return (FALSE);
272 }
273
274 static inline void S9xPlaySample (int channel)
275 {
276     Channel *ch = &SoundData.channels[channel];
277     
278     ch->state = SOUND_SILENT;
279     ch->mode = MODE_NONE;
280     ch->envx = 0;
281     ch->envxx = 0;
282
283         ch->g_index=0;
284         ch->gaussian[0]=ch->gaussian[1]=ch->gaussian[2]=ch->gaussian[3]=0;
285
286     S9xFixEnvelope (channel,
287                     APU.DSP [APU_GAIN  + (channel << 4)], 
288                     APU.DSP [APU_ADSR1 + (channel << 4)],
289                     APU.DSP [APU_ADSR2 + (channel << 4)]);
290
291     ch->sample_number = APU.DSP [APU_SRCN + channel * 0x10];
292     if (APU.DSP [APU_NON] & (1 << channel))
293         ch->type = SOUND_NOISE;
294     else
295         ch->type = SOUND_SAMPLE;
296
297     S9xSetSoundFrequency (channel, ch->hertz);
298     ch->loop = FALSE;
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;
304     ch->env_error = 0;
305     ch->next_sample = 0;
306     ch->interpolate = 0;
307     ch->last_valid_header=0;
308     switch (ch->mode)
309     {
310     case MODE_ADSR:
311         if (ch->attack_rate == 0)
312         {
313             if (ch->decay_rate == 0 || ch->sustain_level == 8)
314             {
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);
318             }
319             else
320             {
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);
325             }
326             ch-> left_vol_level = (ch->envx * ch->volume_left) / 128;
327             ch->right_vol_level = (ch->envx * ch->volume_right) / 128;
328         }
329         else
330         {
331             ch->state = SOUND_ATTACK;
332             ch->envx = 0;
333             ch->left_vol_level = 0;
334             ch->right_vol_level = 0;
335             S9xSetEnvRate (ch, ch->attack_rate, 1, MAX_ENVELOPE_HEIGHT, 0);
336         }
337         ch->envxx = ch->envx << ENVX_SHIFT;
338         break;
339
340     case MODE_GAIN:
341         ch->state = SOUND_GAIN;
342         break;
343
344     case MODE_INCREASE_LINEAR:
345         ch->state = SOUND_INCREASE_LINEAR;
346         break;
347
348     case MODE_INCREASE_BENT_LINE:
349         ch->state = SOUND_INCREASE_BENT_LINE;
350         break;
351
352     case MODE_DECREASE_LINEAR:
353         ch->state = SOUND_DECREASE_LINEAR;
354         break;
355
356     case MODE_DECREASE_EXPONENTIAL:
357         ch->state = SOUND_DECREASE_EXPONENTIAL;
358         break;
359
360     default:
361         break;
362     }
363
364     S9xFixEnvelope (channel,
365                     APU.DSP [APU_GAIN  + (channel << 4)], 
366                     APU.DSP [APU_ADSR1 + (channel << 4)],
367                     APU.DSP [APU_ADSR2 + (channel << 4)]);
368 }
369
370 #ifdef ASM_SPC700
371 extern "C" uint32 Spc700JumpTab;
372 #endif
373
374 bool8 S9xInitAPU ()
375 {
376         // notaz
377         memset(&IAPU, 0, sizeof(IAPU));
378         IAPU.ExtraRAM = APU.ExtraRAM;
379 #ifdef ASM_SPC700
380         IAPU.asmJumpTab = &Spc700JumpTab;
381 #endif
382
383         IAPU.RAM = (uint8 *) malloc (0x10000);
384     IAPU.ShadowRAM = NULL;//(uint8 *) malloc (0x10000);
385     IAPU.CachedSamples = NULL;//(uint8 *) malloc (0x40000);
386     
387     if (!IAPU.RAM /*|| !IAPU.ShadowRAM || !IAPU.CachedSamples*/)
388     {
389         S9xDeinitAPU ();
390         return (FALSE);
391     }
392
393     return (TRUE);
394 }
395
396 void S9xDeinitAPU ()
397 {
398     if (IAPU.RAM)
399     {
400         free ((char *) IAPU.RAM);
401         IAPU.RAM = NULL;
402     }
403     if (IAPU.ShadowRAM)
404     {
405         free ((char *) IAPU.ShadowRAM);
406         IAPU.ShadowRAM = NULL;
407     }
408     if (IAPU.CachedSamples)
409     {
410         free ((char *) IAPU.CachedSamples);
411         IAPU.CachedSamples = NULL;
412     }
413 }
414
415 EXTERN_C uint8 APUROM [64];
416
417 void S9xResetAPU ()
418 {
419 //    Settings.APUEnabled = Settings.NextAPUEnabled;
420
421     memset (IAPU.RAM, Settings.APURAMInitialValue, 0x10000);
422     //memset (IAPU.ShadowRAM, Settings.APURAMInitialValue, 0x10000);
423     
424     //ZeroMemory (IAPU.CachedSamples, 0x40000);
425     ZeroMemory (APU.OutPorts, 4);
426     IAPU.DirectPage = IAPU.RAM;
427     memmove (&IAPU.RAM [0xffc0], APUROM, sizeof (APUROM));
428     memmove (APU.ExtraRAM, APUROM, sizeof (APUROM));
429     IAPU.PC = IAPU.RAM + IAPU.RAM [0xfffe] + (IAPU.RAM [0xffff] << 8);
430     CPU.APU_Cycles = 0;
431     IAPU.YA.W = 0;
432     IAPU.X = 0;
433     IAPU.S = 0xff;
434     IAPU.P = 0;
435     S9xAPUUnpackStatus ();
436     CPU.APU_APUExecuting = Settings.APUEnabled;
437 #ifdef SPC700_SHUTDOWN
438     IAPU.WaitAddress1 = NULL;
439     IAPU.WaitAddress2 = NULL;
440     IAPU.WaitCounter = 0;
441 #endif
442     APU.ShowROM = TRUE;
443     IAPU.RAM [0xf1] = 0x80;
444
445     int i;
446
447     for (i = 0; i < 3; i++)
448     {
449         APU.TimerEnabled [i] = FALSE;
450         APU.TimerValueWritten [i] = 0;
451         APU.TimerTarget [i] = 0;
452         APU.Timer [i] = 0;
453     }
454     for (int j = 0; j < 0x80; j++)
455         APU.DSP [j] = 0;
456
457     IAPU.TwoCycles = IAPU.OneCycle * 2;
458
459     for (i = 0; i < 256; i++)
460         S9xAPUCycles [i] = S9xAPUCycleLengths [i] * IAPU.OneCycle;
461
462     APU.DSP [APU_ENDX] = 0;
463     APU.DSP [APU_KOFF] = 0;
464     APU.DSP [APU_KON] = 0;
465     APU.DSP [APU_FLG] = APU_MUTE | APU_ECHO_DISABLED;
466     APU.KeyedChannels = 0;
467
468     S9xResetSound (TRUE);
469     S9xSetEchoEnable (0);
470 }
471
472 extern int framecpto;
473 void S9xSetAPUDSP (uint8 byte)
474 {
475     uint8 reg = IAPU.RAM [0xf2];
476         static uint8 KeyOn;
477         static uint8 KeyOnPrev;
478     int i;
479
480     switch (reg)
481     {
482     case APU_FLG:
483         if (byte & APU_SOFT_RESET)
484         {
485             APU.DSP [reg] = APU_MUTE | APU_ECHO_DISABLED | (byte & 0x1f);
486             APU.DSP [APU_ENDX] = 0;
487             APU.DSP [APU_KOFF] = 0;
488             APU.DSP [APU_KON] = 0;
489             S9xSetEchoWriteEnable (FALSE);
490 #ifdef DEBUGGER
491             if (Settings.TraceSoundDSP)
492                 S9xTraceSoundDSP ("[%d] DSP reset\n", ICPU.Scanline);
493 #endif
494             // Kill sound
495             S9xResetSound (FALSE);
496         }
497         else
498         {
499             S9xSetEchoWriteEnable (!(byte & APU_ECHO_DISABLED));
500             if (byte & APU_MUTE)
501             {
502 #ifdef DEBUGGER
503                 if (Settings.TraceSoundDSP)
504                     S9xTraceSoundDSP ("[%d] Mute sound\n", ICPU.Scanline);
505 #endif
506                 S9xSetSoundMute (TRUE);
507             }
508             else
509                 S9xSetSoundMute (FALSE);
510
511             SoundData.noise_hertz = NoiseFreq [byte & 0x1f];
512             for (i = 0; i < 8; i++)
513             {
514                 if (SoundData.channels [i].type == SOUND_NOISE)
515                     S9xSetSoundFrequency (i, SoundData.noise_hertz);
516             }
517         }
518         break;
519     case APU_NON:
520         if (byte != APU.DSP [APU_NON])
521         {
522 #ifdef DEBUGGER
523             if (Settings.TraceSoundDSP)
524                 S9xTraceSoundDSP ("[%d] Noise:", ICPU.Scanline);
525 #endif
526             uint8 mask = 1;
527             for (int c = 0; c < 8; c++, mask <<= 1)
528             {
529                 int type;
530                 if (byte & mask)
531                 {
532                     type = SOUND_NOISE;
533 #ifdef DEBUGGER
534                     if (Settings.TraceSoundDSP)
535                     {
536                         if (APU.DSP [reg] & mask)
537                             S9xTraceSoundDSP ("%d,", c);
538                         else
539                             S9xTraceSoundDSP ("%d(on),", c);
540                     }
541 #endif
542                 }
543                 else
544                 {
545                     type = SOUND_SAMPLE;
546 #ifdef DEBUGGER
547                     if (Settings.TraceSoundDSP)
548                     {
549                         if (APU.DSP [reg] & mask)
550                             S9xTraceSoundDSP ("%d(off),", c);
551                     }
552 #endif
553                 }
554                 S9xSetSoundType (c, type);
555             }
556 #ifdef DEBUGGER
557             if (Settings.TraceSoundDSP)
558                 S9xTraceSoundDSP ("\n");
559 #endif
560         }
561         break;
562     case APU_MVOL_LEFT:
563         if (byte != APU.DSP [APU_MVOL_LEFT])
564         {
565 #ifdef DEBUGGER
566             if (Settings.TraceSoundDSP)
567                 S9xTraceSoundDSP ("[%d] Master volume left:%d\n", 
568                                   ICPU.Scanline, (signed char) byte);
569 #endif
570                 S9xSetMasterVolume ((signed char) byte,
571                                     (signed char) APU.DSP [APU_MVOL_RIGHT]);
572         }
573         break;
574     case APU_MVOL_RIGHT:
575         if (byte != APU.DSP [APU_MVOL_RIGHT])
576         {
577 #ifdef DEBUGGER
578             if (Settings.TraceSoundDSP)
579                 S9xTraceSoundDSP ("[%d] Master volume right:%d\n",
580                                   ICPU.Scanline, (signed char) byte);
581 #endif
582                 S9xSetMasterVolume ((signed char) APU.DSP [APU_MVOL_LEFT],
583                                     (signed char) byte);
584         }
585         break;
586     case APU_EVOL_LEFT:
587         if (byte != APU.DSP [APU_EVOL_LEFT])
588         {
589 #ifdef DEBUGGER
590             if (Settings.TraceSoundDSP)
591                 S9xTraceSoundDSP ("[%d] Echo volume left:%d\n",
592                                   ICPU.Scanline, (signed char) byte);
593 #endif
594                 S9xSetEchoVolume ((signed char) byte,
595                                   (signed char) APU.DSP [APU_EVOL_RIGHT]);
596         }
597         break;
598     case APU_EVOL_RIGHT:
599         if (byte != APU.DSP [APU_EVOL_RIGHT])
600         {
601 #ifdef DEBUGGER
602             if (Settings.TraceSoundDSP)
603                 S9xTraceSoundDSP ("[%d] Echo volume right:%d\n",
604                                   ICPU.Scanline, (signed char) byte);
605 #endif
606                 S9xSetEchoVolume ((signed char) APU.DSP [APU_EVOL_LEFT],
607                                   (signed char) byte);
608         }
609         break;
610     case APU_ENDX:
611 #ifdef DEBUGGER
612         if (Settings.TraceSoundDSP)
613             S9xTraceSoundDSP ("[%d] Reset ENDX\n", ICPU.Scanline);
614 #endif
615         byte = 0;
616         break;
617
618     case APU_KOFF:
619                 //              if (byte)
620         {
621             uint8 mask = 1;
622 #ifdef DEBUGGER
623             if (Settings.TraceSoundDSP)
624                 S9xTraceSoundDSP ("[%d] Key off:", ICPU.Scanline);
625 #endif
626             for (int c = 0; c < 8; c++, mask <<= 1)
627             {
628                 if ((byte & mask) != 0)
629                 {
630 #ifdef DEBUGGER
631
632                     if (Settings.TraceSoundDSP)
633                         S9xTraceSoundDSP ("%d,", c);
634 #endif              
635                     if (APU.KeyedChannels & mask)
636                     {
637                         {
638                                                         KeyOnPrev&=~mask;
639                             APU.KeyedChannels &= ~mask;
640                             APU.DSP [APU_KON] &= ~mask;
641                             //APU.DSP [APU_KOFF] |= mask;
642                             S9xSetSoundKeyOff (c);
643                         }
644                     }
645                 }
646                                 else if((KeyOnPrev&mask)!=0)
647                                 {
648                                         KeyOnPrev&=~mask;
649                                         APU.KeyedChannels |= mask;
650                                         //APU.DSP [APU_KON] |= mask;
651                                         APU.DSP [APU_KOFF] &= ~mask;
652                                         APU.DSP [APU_ENDX] &= ~mask;
653                                         S9xPlaySample (c);
654                                 }
655             }
656 #ifdef DEBUGGER
657             if (Settings.TraceSoundDSP)
658                 S9xTraceSoundDSP ("\n");
659 #endif
660         }
661                 //KeyOnPrev=0;
662         APU.DSP [APU_KOFF] = byte;
663         return;
664     case APU_KON:
665
666         if (byte)
667         {
668             uint8 mask = 1;
669 #ifdef DEBUGGER
670
671             if (Settings.TraceSoundDSP)
672                 S9xTraceSoundDSP ("[%d] Key on:", ICPU.Scanline);
673 #endif
674             for (int c = 0; c < 8; c++, mask <<= 1)
675             {
676                 if ((byte & mask) != 0)
677                 {
678 #ifdef DEBUGGER
679                     if (Settings.TraceSoundDSP)
680                         S9xTraceSoundDSP ("%d,", c);
681 #endif              
682                     // Pac-In-Time requires that channels can be key-on
683                     // regardeless of their current state.
684                                         if((APU.DSP [APU_KOFF] & mask) ==0)
685                                         {
686                                                 KeyOnPrev&=~mask;
687                     APU.KeyedChannels |= mask;
688                                                 //APU.DSP [APU_KON] |= mask;
689                                                 //APU.DSP [APU_KOFF] &= ~mask;
690                     APU.DSP [APU_ENDX] &= ~mask;
691                     S9xPlaySample (c);
692                 }
693                                         else KeyOn|=mask;
694                                 }
695             }
696 #ifdef DEBUGGER
697             if (Settings.TraceSoundDSP)
698                 S9xTraceSoundDSP ("\n");
699 #endif
700         }
701
702         return;
703         
704     case APU_VOL_LEFT + 0x00:
705     case APU_VOL_LEFT + 0x10:
706     case APU_VOL_LEFT + 0x20:
707     case APU_VOL_LEFT + 0x30:
708     case APU_VOL_LEFT + 0x40:
709     case APU_VOL_LEFT + 0x50:
710     case APU_VOL_LEFT + 0x60:
711     case APU_VOL_LEFT + 0x70:
712 // At Shin Megami Tensei suggestion 6/11/00
713 //      if (byte != APU.DSP [reg])
714         {
715 #ifdef DEBUGGER
716             if (Settings.TraceSoundDSP)
717                 S9xTraceSoundDSP ("[%d] %d volume left: %d\n", 
718                                   ICPU.Scanline, reg>>4, (signed char) byte);
719 #endif
720                 S9xSetSoundVolume (reg >> 4, (signed char) byte,
721                                    (signed char) APU.DSP [reg + 1]);
722         }
723         break;
724     case APU_VOL_RIGHT + 0x00:
725     case APU_VOL_RIGHT + 0x10:
726     case APU_VOL_RIGHT + 0x20:
727     case APU_VOL_RIGHT + 0x30:
728     case APU_VOL_RIGHT + 0x40:
729     case APU_VOL_RIGHT + 0x50:
730     case APU_VOL_RIGHT + 0x60:
731     case APU_VOL_RIGHT + 0x70:
732 // At Shin Megami Tensei suggestion 6/11/00
733 //      if (byte != APU.DSP [reg])
734         {
735 #ifdef DEBUGGER
736             if (Settings.TraceSoundDSP)
737                 S9xTraceSoundDSP ("[%d] %d volume right: %d\n", 
738                                   ICPU.Scanline, reg >>4, (signed char) byte);
739 #endif
740                 S9xSetSoundVolume (reg >> 4, (signed char) APU.DSP [reg - 1],
741                                    (signed char) byte);
742         }
743         break;
744
745     case APU_P_LOW + 0x00:
746     case APU_P_LOW + 0x10:
747     case APU_P_LOW + 0x20:
748     case APU_P_LOW + 0x30:
749     case APU_P_LOW + 0x40:
750     case APU_P_LOW + 0x50:
751     case APU_P_LOW + 0x60:
752     case APU_P_LOW + 0x70:
753 #ifdef DEBUGGER
754         if (Settings.TraceSoundDSP)
755             S9xTraceSoundDSP ("[%d] %d freq low: %d\n",
756                               ICPU.Scanline, reg>>4, byte);
757 #endif
758             S9xSetSoundHertz (reg >> 4, (((byte + (APU.DSP [reg + 1] << 8)) & FREQUENCY_MASK) * 32000) >> 12);
759         break;
760
761     case APU_P_HIGH + 0x00:
762     case APU_P_HIGH + 0x10:
763     case APU_P_HIGH + 0x20:
764     case APU_P_HIGH + 0x30:
765     case APU_P_HIGH + 0x40:
766     case APU_P_HIGH + 0x50:
767     case APU_P_HIGH + 0x60:
768     case APU_P_HIGH + 0x70:
769 #ifdef DEBUGGER
770         if (Settings.TraceSoundDSP)
771             S9xTraceSoundDSP ("[%d] %d freq high: %d\n",
772                               ICPU.Scanline, reg>>4, byte);
773 #endif
774             S9xSetSoundHertz (reg >> 4, 
775                         (((byte << 8) + APU.DSP [reg - 1]) & FREQUENCY_MASK) * 8);
776         break;
777
778     case APU_SRCN + 0x00:
779     case APU_SRCN + 0x10:
780     case APU_SRCN + 0x20:
781     case APU_SRCN + 0x30:
782     case APU_SRCN + 0x40:
783     case APU_SRCN + 0x50:
784     case APU_SRCN + 0x60:
785     case APU_SRCN + 0x70:
786         if (byte != APU.DSP [reg])
787         {
788 #ifdef DEBUGGER
789             if (Settings.TraceSoundDSP)
790                 S9xTraceSoundDSP ("[%d] %d sample number: %d\n",
791                                   ICPU.Scanline, reg>>4, byte);
792 #endif
793             //S9xSetSoundSample (reg >> 4, byte); // notaz: seems to be unused?
794         }
795         break;
796         
797     case APU_ADSR1 + 0x00:
798     case APU_ADSR1 + 0x10:
799     case APU_ADSR1 + 0x20:
800     case APU_ADSR1 + 0x30:
801     case APU_ADSR1 + 0x40:
802     case APU_ADSR1 + 0x50:
803     case APU_ADSR1 + 0x60:
804     case APU_ADSR1 + 0x70:
805         if (byte != APU.DSP [reg])
806         {
807 #ifdef DEBUGGER
808             if (Settings.TraceSoundDSP)
809                 S9xTraceSoundDSP ("[%d] %d adsr1: %02x\n",
810                                   ICPU.Scanline, reg>>4, byte);
811 #endif
812             {
813                 S9xFixEnvelope (reg >> 4, APU.DSP [reg + 2], byte, 
814                              APU.DSP [reg + 1]);
815             }
816         }
817         break;
818
819     case APU_ADSR2 + 0x00:
820     case APU_ADSR2 + 0x10:
821     case APU_ADSR2 + 0x20:
822     case APU_ADSR2 + 0x30:
823     case APU_ADSR2 + 0x40:
824     case APU_ADSR2 + 0x50:
825     case APU_ADSR2 + 0x60:
826     case APU_ADSR2 + 0x70:
827         if (byte != APU.DSP [reg])
828         {
829 #ifdef DEBUGGER
830             if (Settings.TraceSoundDSP)
831                 S9xTraceSoundDSP ("[%d] %d adsr2: %02x\n", 
832                                   ICPU.Scanline, reg>>4, byte);
833 #endif
834             {
835                 S9xFixEnvelope (reg >> 4, APU.DSP [reg + 1], APU.DSP [reg - 1],
836                              byte);
837             }
838         }
839         break;
840
841     case APU_GAIN + 0x00:
842     case APU_GAIN + 0x10:
843     case APU_GAIN + 0x20:
844     case APU_GAIN + 0x30:
845     case APU_GAIN + 0x40:
846     case APU_GAIN + 0x50:
847     case APU_GAIN + 0x60:
848     case APU_GAIN + 0x70:
849         if (byte != APU.DSP [reg])
850         {
851 #ifdef DEBUGGER
852             if (Settings.TraceSoundDSP)
853                 S9xTraceSoundDSP ("[%d] %d gain: %02x\n",
854                                   ICPU.Scanline, reg>>4, byte);
855 #endif
856             {
857                 S9xFixEnvelope (reg >> 4, byte, APU.DSP [reg - 2],
858                              APU.DSP [reg - 1]);
859             }
860         }
861         break;
862
863     case APU_ENVX + 0x00:
864     case APU_ENVX + 0x10:
865     case APU_ENVX + 0x20:
866     case APU_ENVX + 0x30:
867     case APU_ENVX + 0x40:
868     case APU_ENVX + 0x50:
869     case APU_ENVX + 0x60:
870     case APU_ENVX + 0x70:
871         break;
872
873     case APU_OUTX + 0x00:
874     case APU_OUTX + 0x10:
875     case APU_OUTX + 0x20:
876     case APU_OUTX + 0x30:
877     case APU_OUTX + 0x40:
878     case APU_OUTX + 0x50:
879     case APU_OUTX + 0x60:
880     case APU_OUTX + 0x70:
881         break;
882     
883     case APU_DIR:
884 #ifdef DEBUGGER
885         if (Settings.TraceSoundDSP)
886             S9xTraceSoundDSP ("[%d] Sample directory to: %02x\n",
887                               ICPU.Scanline, byte);
888 #endif
889         break;
890
891     case APU_PMON:
892         if (byte != APU.DSP [APU_PMON])
893         {
894 #ifdef DEBUGGER
895             if (Settings.TraceSoundDSP)
896             {
897                 S9xTraceSoundDSP ("[%d] FreqMod:", ICPU.Scanline);
898                 uint8 mask = 1;
899                 for (int c = 0; c < 8; c++, mask <<= 1)
900                 {
901                     if (byte & mask)
902                     {
903                         if (APU.DSP [reg] & mask)
904                             S9xTraceSoundDSP ("%d", c);
905                         else
906                             S9xTraceSoundDSP ("%d(on),", c);
907                     }
908                     else
909                     {
910                         if (APU.DSP [reg] & mask)
911                             S9xTraceSoundDSP ("%d(off),", c);
912                     }
913                 }
914                 S9xTraceSoundDSP ("\n");
915             }
916 #endif
917                 S9xSetFrequencyModulationEnable (byte);
918         }
919         break;
920
921     case APU_EON:
922         if (byte != APU.DSP [APU_EON])
923         {
924 #ifdef DEBUGGER
925             if (Settings.TraceSoundDSP)
926             {
927                 S9xTraceSoundDSP ("[%d] Echo:", ICPU.Scanline);
928                 uint8 mask = 1;
929                 for (int c = 0; c < 8; c++, mask <<= 1)
930                 {
931                     if (byte & mask)
932                     {
933                         if (APU.DSP [reg] & mask)
934                             S9xTraceSoundDSP ("%d", c);
935                         else
936                             S9xTraceSoundDSP ("%d(on),", c);
937                     }
938                     else
939                     {
940                         if (APU.DSP [reg] & mask)
941                             S9xTraceSoundDSP ("%d(off),", c);
942                     }
943                 }
944                 S9xTraceSoundDSP ("\n");
945             }
946 #endif
947                 S9xSetEchoEnable (byte);
948         }
949         break;
950
951     case APU_EFB:
952         S9xSetEchoFeedback ((signed char) byte);
953         break;
954
955     case APU_ESA:
956         break;
957
958     case APU_EDL:
959         S9xSetEchoDelay (byte & 0xf);
960         break;
961
962     case APU_C0:
963     case APU_C1:
964     case APU_C2:
965     case APU_C3:
966     case APU_C4:
967     case APU_C5:
968     case APU_C6:
969     case APU_C7:
970         S9xSetFilterCoefficient (reg >> 4, (signed char) byte);
971         break;
972     default:
973 // XXX
974 //printf ("Write %02x to unknown APU register %02x\n", byte, reg);
975         break;
976     }
977
978         KeyOnPrev|=KeyOn;
979         KeyOn=0;
980         
981     if (reg < 0x80)
982         APU.DSP [reg] = byte;
983 }
984
985 void S9xFixEnvelope (int channel, uint8 gain, uint8 adsr1, uint8 adsr2)
986 {
987     if (adsr1 & 0x80)
988     {
989                 // ADSR mode
990                 
991                 // XXX: can DSP be switched to ADSR mode directly from GAIN/INCREASE/
992                 // DECREASE mode? And if so, what stage of the sequence does it start
993                 // at?
994                 if (S9xSetSoundMode (channel, MODE_ADSR))
995                 {
996                         S9xSetSoundADSR (channel, adsr1 & 0xf, (adsr1 >> 4) & 7, adsr2 & 0x1f, (adsr2 >> 5) & 7, 8);
997                 }
998     }
999     else
1000     {
1001                 // Gain mode
1002                 if ((gain & 0x80) == 0)
1003                 {
1004                         if (S9xSetSoundMode (channel, MODE_GAIN))
1005                         {
1006                         S9xSetEnvelopeRate (channel, 0, 0, gain & 0x7f, 0);
1007                         S9xSetEnvelopeHeight (channel, gain & 0x7f);
1008                         }
1009                 }
1010                 else
1011                 {
1012                         
1013                         if (gain & 0x40)
1014                         {
1015                                 // Increase mode
1016                                 if (S9xSetSoundMode (channel, (gain & 0x20) ?
1017                                                           MODE_INCREASE_BENT_LINE :
1018                                                           MODE_INCREASE_LINEAR))
1019                                 {
1020                                         S9xSetEnvelopeRate (channel, IncreaseRate [gain & 0x1f], 1, 127, (3<<28)|gain);
1021                                 }
1022                         }
1023                         else
1024                         {
1025                                 if(gain & 0x20) {
1026                                         if (S9xSetSoundMode (channel, MODE_DECREASE_EXPONENTIAL))
1027                                                 S9xSetEnvelopeRate (channel, DecreaseRateExp [gain & 0x1f] / 2, -1, 0, (4<<28)|gain);
1028                                 } else {
1029                                         if (S9xSetSoundMode (channel, MODE_DECREASE_LINEAR))
1030                                                 S9xSetEnvelopeRate (channel, IncreaseRate [gain & 0x1f], -1, 0, (3<<28)|gain);
1031                                 }
1032                         }
1033                 }
1034     }
1035 }
1036
1037 void S9xSetAPUControl (uint8 byte)
1038 {
1039 //if (byte & 0x40)
1040 //printf ("*** Special SPC700 timing enabled\n");
1041     if ((byte & 1) != 0 && !APU.TimerEnabled [0])
1042     {
1043         APU.Timer [0] = 0;
1044         IAPU.RAM [0xfd] = 0;
1045         if ((APU.TimerTarget [0] = IAPU.RAM [0xfa]) == 0)
1046             APU.TimerTarget [0] = 0x100;
1047     }
1048     if ((byte & 2) != 0 && !APU.TimerEnabled [1])
1049     {
1050         APU.Timer [1] = 0;
1051         IAPU.RAM [0xfe] = 0;
1052         if ((APU.TimerTarget [1] = IAPU.RAM [0xfb]) == 0)
1053             APU.TimerTarget [1] = 0x100;
1054     }
1055     if ((byte & 4) != 0 && !APU.TimerEnabled [2])
1056     {
1057         APU.Timer [2] = 0;
1058         IAPU.RAM [0xff] = 0;
1059         if ((APU.TimerTarget [2] = IAPU.RAM [0xfc]) == 0)
1060             APU.TimerTarget [2] = 0x100;
1061     }
1062     APU.TimerEnabled [0] = byte & 1;
1063     APU.TimerEnabled [1] = (byte & 2) >> 1;
1064     APU.TimerEnabled [2] = (byte & 4) >> 2;
1065
1066     if (byte & 0x10)
1067         IAPU.RAM [0xF4] = IAPU.RAM [0xF5] = 0;
1068
1069     if (byte & 0x20)
1070         IAPU.RAM [0xF6] = IAPU.RAM [0xF7] = 0;
1071
1072     if (byte & 0x80)
1073     {
1074         if (!APU.ShowROM)
1075         {
1076             memmove (&IAPU.RAM [0xffc0], APUROM, sizeof (APUROM));
1077             APU.ShowROM = TRUE;
1078         }
1079     }
1080     else
1081     {
1082         if (APU.ShowROM)
1083         {
1084             APU.ShowROM = FALSE;
1085             memmove (&IAPU.RAM [0xffc0], APU.ExtraRAM, sizeof (APUROM));
1086         }
1087     }
1088     IAPU.RAM [0xf1] = byte;
1089 }
1090
1091 void S9xSetAPUTimer (uint16 Address, uint8 byte)
1092 {
1093     IAPU.RAM [Address] = byte;
1094
1095     switch (Address)
1096     {
1097     case 0xfa:
1098         if ((APU.TimerTarget [0] = IAPU.RAM [0xfa]) == 0)
1099             APU.TimerTarget [0] = 0x100;
1100         APU.TimerValueWritten [0] = TRUE;
1101         break;
1102     case 0xfb:
1103         if ((APU.TimerTarget [1] = IAPU.RAM [0xfb]) == 0)
1104             APU.TimerTarget [1] = 0x100;
1105         APU.TimerValueWritten [1] = TRUE;
1106         break;
1107     case 0xfc:
1108         if ((APU.TimerTarget [2] = IAPU.RAM [0xfc]) == 0)
1109             APU.TimerTarget [2] = 0x100;
1110         APU.TimerValueWritten [2] = TRUE;
1111         break;
1112     }
1113 }
1114
1115 uint8 S9xGetAPUDSP ()
1116 {
1117     uint8 reg = IAPU.RAM [0xf2] & 0x7f;
1118     uint8 byte = APU.DSP [reg];
1119
1120     switch (reg)
1121     {
1122     case APU_KON:
1123         break;
1124     case APU_KOFF:
1125         break;
1126     case APU_OUTX + 0x00:
1127     case APU_OUTX + 0x10:
1128     case APU_OUTX + 0x20:
1129     case APU_OUTX + 0x30:
1130     case APU_OUTX + 0x40:
1131     case APU_OUTX + 0x50:
1132     case APU_OUTX + 0x60:
1133     case APU_OUTX + 0x70:
1134         if (SoundData.channels [reg >> 4].state == SOUND_SILENT)
1135             return (0);
1136         return ((SoundData.channels [reg >> 4].sample >> 8) |
1137                 (SoundData.channels [reg >> 4].sample & 0xff));
1138
1139     case APU_ENVX + 0x00:
1140     case APU_ENVX + 0x10:
1141     case APU_ENVX + 0x20:
1142     case APU_ENVX + 0x30:
1143     case APU_ENVX + 0x40:
1144     case APU_ENVX + 0x50:
1145     case APU_ENVX + 0x60:
1146     case APU_ENVX + 0x70:
1147                 return 0;
1148 //              return ((uint8) S9xGetEnvelopeHeight (reg >> 4));
1149
1150     case APU_ENDX:
1151 // To fix speech in Magical Drop 2 6/11/00
1152 //      APU.DSP [APU_ENDX] = 0;
1153         break;
1154     default:
1155         break;
1156     }
1157     return (byte);
1158 }