FS#6948 - Fix the broken 'follow playlist' feature
[Rockbox.git] / apps / codecs / nsf.c
blob6f81c6a4bc471651d4ded01661f916b0f340284a
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
9 * Copyright (C) 2006 Adam Gashlin (hcs)
10 * Copyright (C) 2004 Disch
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
21 * This is a perversion of Disch's excellent NotSoFatso.
24 #include "codeclib.h"
25 #include "inttypes.h"
26 #include "system.h"
28 CODEC_HEADER
30 /* arm doesn't benefit from IRAM? */
31 #ifdef CPU_ARM
32 #undef ICODE_ATTR
33 #define ICODE_ATTR
34 #undef IDATA_ATTR
35 #define IDATA_ATTR
36 #else
37 #define ICODE_INSTEAD_OF_INLINE
38 #endif
40 /* Maximum number of bytes to process in one iteration */
41 #define WAV_CHUNK_SIZE (1024*2)
43 static int16_t samples[WAV_CHUNK_SIZE] IBSS_ATTR;
45 #define ZEROMEMORY(addr,size) memset(addr,0,size)
47 /* simple profiling with USEC_TIMER
49 #define NSF_PROFILE
53 #ifdef NSF_PROFILE
55 #define CREATE_TIMER(name) uint32_t nsf_timer_##name##_start,\
56 nsf_timer_##name##_total
57 #define ENTER_TIMER(name) nsf_timer_##name##_start=USEC_TIMER
58 #define EXIT_TIMER(name) nsf_timer_##name##_total+=\
59 (USEC_TIMER-nsf_timer_##name##_start)
60 #define READ_TIMER(name) (nsf_timer_##name##_total)
61 #define RESET_TIMER(name) nsf_timer_##name##_total=0
63 #define PRINT_TIMER_PCT(bname,tname,nstr) ci->fdprintf(
64 logfd,"%10ld ",READ_TIMER(bname));\
65 ci->fdprintf(logfd,"(%3d%%) " nstr "\t",\
66 ((uint64_t)READ_TIMER(bname))*100/READ_TIMER(tname))
68 CREATE_TIMER(total);
69 CREATE_TIMER(cpu);
70 CREATE_TIMER(apu);
71 CREATE_TIMER(squares);
72 CREATE_TIMER(tnd);
73 CREATE_TIMER(tnd_enter);
74 CREATE_TIMER(tnd_tri);
75 CREATE_TIMER(tnd_noise);
76 CREATE_TIMER(tnd_dmc);
77 CREATE_TIMER(fds);
78 CREATE_TIMER(frame);
79 CREATE_TIMER(mix);
81 void reset_profile_timers(void) {
82 RESET_TIMER(total);
83 RESET_TIMER(cpu);
84 RESET_TIMER(apu);
85 RESET_TIMER(squares);
86 RESET_TIMER(tnd);
87 RESET_TIMER(tnd_enter);
88 RESET_TIMER(tnd_tri);
89 RESET_TIMER(tnd_noise);
90 RESET_TIMER(tnd_dmc);
91 RESET_TIMER(fds);
92 RESET_TIMER(frame);
93 RESET_TIMER(mix);
96 int logfd=-1;
98 void print_timers(char * path, int track) {
99 logfd = ci->open("/nsflog.txt",O_WRONLY|O_CREAT|O_APPEND);
100 ci->fdprintf(logfd,"%s[%d]:\t",path,track);
101 ci->fdprintf(logfd,"%10ld total\t",READ_TIMER(total));
102 PRINT_TIMER_PCT(cpu,total,"CPU");
103 PRINT_TIMER_PCT(apu,total,"APU");
104 ci->fdprintf(logfd,"\n\t");
105 PRINT_TIMER_PCT(squares,apu,"squares");
106 PRINT_TIMER_PCT(frame,apu,"frame");
107 PRINT_TIMER_PCT(mix,apu,"mix");
108 PRINT_TIMER_PCT(fds,apu,"FDS");
109 PRINT_TIMER_PCT(tnd,apu,"tnd");
110 ci->fdprintf(logfd,"\n\t\t");
111 PRINT_TIMER_PCT(tnd_enter,tnd,"enter");
112 PRINT_TIMER_PCT(tnd_tri,tnd,"triangle");
113 PRINT_TIMER_PCT(tnd_noise,tnd,"noise");
114 PRINT_TIMER_PCT(tnd_dmc,tnd,"DMC");
115 ci->fdprintf(logfd,"\n");
117 ci->close(logfd);
118 logfd=-1;
121 #else
123 #define CREATE_TIMER(name)
124 #define ENTER_TIMER(name)
125 #define EXIT_TIMER(name)
126 #define READ_TIMER(name)
127 #define RESET_TIMER(name)
128 #define print_timers(path,track)
129 #define reset_profile_timers()
131 #endif
133 /* proper handling of multibyte values */
134 #ifdef ROCKBOX_LITTLE_ENDIAN
135 union TWIN
137 uint16_t W;
138 struct{ uint8_t l; uint8_t h; } B;
141 union QUAD
143 uint32_t D;
144 struct{ uint8_t l; uint8_t h; uint16_t w; } B;
146 #else
148 union TWIN
150 uint16_t W;
151 struct{ uint8_t h; uint8_t l; } B;
154 union QUAD
156 uint32_t D;
157 struct{uint16_t w; uint8_t h; uint8_t l; } B;
160 #endif
162 #define NTSC_FREQUENCY 1789772.727273f
163 #define PAL_FREQUENCY 1652097.692308f
164 #define NTSC_NMIRATE 60.098814f
165 #define PAL_NMIRATE 50.006982f
167 #define NES_FREQUENCY 21477270
168 #define NTSC_FRAME_COUNTER_FREQ (NTSC_FREQUENCY / (NES_FREQUENCY / 89490.0f))
169 #define PAL_FRAME_COUNTER_FREQ (PAL_FREQUENCY / (NES_FREQUENCY / 89490.0f))
171 /****************** tables */
172 static const int32_t ModulationTable[8] ICONST_ATTR = {0,1,2,4,0,-4,-2,-1};
173 const uint16_t DMC_FREQ_TABLE[2][0x10] = {
174 /* NTSC */
175 {0x1AC,0x17C,0x154,0x140,0x11E,0x0FE,0x0E2,0x0D6,0x0BE,0x0A0,0x08E,0x080,
176 0x06A,0x054,0x048,0x036},
177 /* PAL */
178 {0x18C,0x160,0x13A,0x128,0x108,0x0EA,0x0D0,0x0C6,0x0B0,0x094,0x082,0x076,
179 0x062,0x04E,0x042,0x032}
182 const uint8_t DUTY_CYCLE_TABLE[4] = {2,4,8,12};
184 const uint8_t LENGTH_COUNTER_TABLE[0x20] = {
185 0x0A,0xFE,0x14,0x02,0x28,0x04,0x50,0x06,0xA0,0x08,0x3C,0x0A,0x0E,0x0C,0x1A,
186 0x0E,0x0C,0x10,0x18,0x12,0x30,0x14,0x60,0x16,0xC0,0x18,0x48,0x1A,0x10,0x1C,
187 0x20,0x1E
190 const uint16_t NOISE_FREQ_TABLE[0x10] = {
191 0x004,0x008,0x010,0x020,0x040,0x060,0x080,0x0A0,0x0CA,0x0FE,0x17C,0x1FC,
192 0x2FA,0x3F8,0x7F2,0xFE4
195 /****************** NSF loading ******************/
197 /* file format structs (both are little endian) */
199 struct NESM_HEADER
201 uint32_t nHeader;
202 uint8_t nHeaderExtra;
203 uint8_t nVersion;
204 uint8_t nTrackCount;
205 uint8_t nInitialTrack;
206 uint16_t nLoadAddress;
207 uint16_t nInitAddress;
208 uint16_t nPlayAddress;
209 uint8_t szGameTitle[32];
210 uint8_t szArtist[32];
211 uint8_t szCopyright[32];
212 uint16_t nSpeedNTSC;
213 uint8_t nBankSwitch[8];
214 uint16_t nSpeedPAL;
215 uint8_t nNTSC_PAL;
216 uint8_t nExtraChip;
217 uint8_t nExpansion[4];
220 struct NSFE_INFOCHUNK
222 uint16_t nLoadAddress;
223 uint16_t nInitAddress;
224 uint16_t nPlayAddress;
225 uint8_t nIsPal;
226 uint8_t nExt;
227 uint8_t nTrackCount;
228 uint8_t nStartingTrack;
231 int32_t LoadFile(uint8_t *,size_t);
233 int32_t LoadFile_NESM(uint8_t *,size_t);
234 int32_t LoadFile_NSFE(uint8_t *,size_t);
236 /* NSF file info */
238 /* basic NSF info */
239 int32_t bIsExtended=0; /* 0 = NSF, 1 = NSFE */
240 uint8_t nIsPal=0; /* 0 = NTSC, 1 = PAL,
241 2,3 = mixed NTSC/PAL (interpretted as NTSC) */
242 int32_t nfileLoadAddress=0; /* The address to which the NSF code is
243 loaded */
244 int32_t nfileInitAddress=0; /* The address of the Init routine
245 (called at track change) */
246 int32_t nfilePlayAddress=0; /* The address of the Play routine
247 (called several times a second) */
248 uint8_t nChipExtensions=0; /* Bitwise representation of the external chips
249 used by this NSF. */
251 /* old NESM speed stuff (blarg) */
252 int32_t nNTSC_PlaySpeed=0;
253 int32_t nPAL_PlaySpeed=0;
255 /* track info */
256 /* The number of tracks in the NSF (1 = 1 track, 5 = 5 tracks, etc) */
257 int32_t nTrackCount=0;
258 /* The initial track (ZERO BASED: 0 = 1st track, 4 = 5th track, etc) */
259 int32_t nInitialTrack=0;
261 /* nsf data */
262 uint8_t* pDataBuffer=0; /* the buffer containing NSF code. */
263 int32_t nDataBufferSize=0; /* the size of the above buffer. */
265 /* playlist */
266 uint8_t nPlaylist[256]; /* Each entry is the zero based index of the
267 song to play */
268 int32_t nPlaylistSize=0; /* the number of tracks in the playlist */
270 /* track time / fade */
271 int32_t nTrackTime[256]; /* track times -1 if no track times specified */
272 int32_t nTrackFade[256]; /* track fade times -1 if none are specified */
274 /* string info */
275 uint8_t szGameTitle[0x101];
276 uint8_t szArtist[0x101];
277 uint8_t szCopyright[0x101];
278 uint8_t szRipper[0x101];
280 /* bankswitching info */
281 uint8_t nBankswitch[8]={0}; /* The initial bankswitching registers needed
282 * for some NSFs. If the NSF does not use
283 * bankswitching, these values will all be zero
286 int32_t LoadFile(uint8_t * inbuffer, size_t size)
288 if(!inbuffer) return -1;
290 int32_t ret = -1;
292 if(!memcmp(inbuffer,"NESM",4)) ret = LoadFile_NESM(inbuffer,size);
293 if(!memcmp(inbuffer,"NSFE",4)) ret = LoadFile_NSFE(inbuffer,size);
296 * Snake's revenge puts '00' for the initial track,
297 * which (after subtracting 1) makes it 256 or -1 (bad!)
298 * This prevents that crap
300 if(nInitialTrack >= nTrackCount)
301 nInitialTrack = 0;
302 if(nInitialTrack < 0)
303 nInitialTrack = 0;
305 /* if there's no tracks... this is a crap NSF */
306 if(nTrackCount < 1)
308 return -1;
311 return ret;
314 int32_t LoadFile_NESM(uint8_t* inbuffer, size_t size)
316 uint8_t ignoreversion=1;
317 uint8_t needdata=1;
319 /* read the info */
320 struct NESM_HEADER hdr;
322 memcpy(&hdr,inbuffer,sizeof(hdr));
324 /* confirm the header */
325 if(memcmp("NESM",&(hdr.nHeader),4)) return -1;
326 if(hdr.nHeaderExtra != 0x1A) return -1;
327 /* stupid NSFs claim to be above version 1 >_> */
328 if((!ignoreversion) && (hdr.nVersion != 1)) return -1;
331 * NESM is generally easier to work with (but limited!)
332 * just move the data over from NESM_HEADER over to our member data
335 bIsExtended = 0;
336 nIsPal = hdr.nNTSC_PAL & 0x03;
337 nPAL_PlaySpeed = letoh16(hdr.nSpeedPAL);
338 nNTSC_PlaySpeed = letoh16(hdr.nSpeedNTSC);
339 nfileLoadAddress = letoh16(hdr.nLoadAddress);
340 nfileInitAddress = letoh16(hdr.nInitAddress);
341 nfilePlayAddress = letoh16(hdr.nPlayAddress);
342 nChipExtensions = hdr.nExtraChip;
345 nTrackCount = hdr.nTrackCount;
346 nInitialTrack = hdr.nInitialTrack - 1;
348 memcpy(nBankswitch,hdr.nBankSwitch,8);
350 memcpy(szGameTitle,hdr.szGameTitle,32);
351 memcpy(szArtist ,hdr.szArtist ,32);
352 memcpy(szCopyright,hdr.szCopyright,32);
354 /* read the NSF data */
355 if(needdata)
357 pDataBuffer=inbuffer+0x80;
358 nDataBufferSize=size-0x80;
361 /* if we got this far... it was a successful read */
362 return 0;
365 int32_t LoadFile_NSFE(uint8_t* inbuffer, size_t size)
367 /* the vars we'll be using */
368 uint32_t nChunkType;
369 int32_t nChunkSize;
370 int32_t nChunkUsed;
371 int32_t i;
372 uint8_t * nDataPos = 0;
373 uint8_t bInfoFound = 0;
374 uint8_t bEndFound = 0;
375 uint8_t bBankFound = 0;
376 nPlaylistSize=-1;
378 struct NSFE_INFOCHUNK info;
379 ZEROMEMORY(&info,sizeof(struct NSFE_INFOCHUNK));
380 ZEROMEMORY(nBankswitch,8);
381 info.nTrackCount = 1; /* default values */
383 if (size < 8) return -1; /* must have at least NSFE,NEND */
385 /* confirm the header! */
386 memcpy(&nChunkType,inbuffer,4);
387 inbuffer+=4;
388 if(memcmp(&nChunkType,"NSFE",4)) return -1;
390 for (i=0;i<256;i++) {
391 nTrackTime[i]=-1;
392 nTrackFade[i]=-1;
395 /* begin reading chunks */
396 while(!bEndFound)
398 memcpy(&nChunkSize,inbuffer,4);
399 nChunkSize=letoh32(nChunkSize);
400 inbuffer+=4;
401 memcpy(&nChunkType,inbuffer,4);
402 inbuffer+=4;
404 if(!memcmp(&nChunkType,"INFO",4)) {
405 /* only one info chunk permitted */
406 if(bInfoFound) return -1;
407 if(nChunkSize < 8) return -1; /* minimum size */
409 bInfoFound = 1;
410 nChunkUsed = MIN((int32_t)sizeof(struct NSFE_INFOCHUNK),
411 nChunkSize);
413 memcpy(&info,inbuffer,nChunkUsed);
414 inbuffer+=nChunkSize;
416 bIsExtended = 1;
417 nIsPal = info.nIsPal & 3;
418 nfileLoadAddress = letoh16(info.nLoadAddress);
419 nfileInitAddress = letoh16(info.nInitAddress);
420 nfilePlayAddress = letoh16(info.nPlayAddress);
421 nChipExtensions = info.nExt;
422 nTrackCount = info.nTrackCount;
423 nInitialTrack = info.nStartingTrack;
425 nPAL_PlaySpeed = (uint16_t)(1000000 / PAL_NMIRATE);
426 nNTSC_PlaySpeed = (uint16_t)(1000000 / NTSC_NMIRATE);
427 } else if (!memcmp(&nChunkType,"DATA",4)) {
428 if(!bInfoFound) return -1;
429 if(nDataPos) return -1;
430 if(nChunkSize < 1) return -1;
432 nDataBufferSize = nChunkSize;
433 nDataPos = inbuffer;
435 inbuffer+=nChunkSize;
436 } else if (!memcmp(&nChunkType,"NEND",4)) {
437 bEndFound = 1;
438 } else if (!memcmp(&nChunkType,"time",4)) {
439 if(!bInfoFound) return -1;
440 for (nChunkUsed=0; nChunkUsed < MIN(nChunkSize / 4,nTrackCount);
441 nChunkUsed++,inbuffer+=4) {
442 nTrackTime[nChunkUsed]=
443 ((uint32_t)inbuffer[0])|
444 ((uint32_t)inbuffer[1]<<8)|
445 ((uint32_t)inbuffer[2]<<16)|
446 ((uint32_t)inbuffer[3]<<24);
449 inbuffer+=nChunkSize-(nChunkUsed*4);
451 /* negative signals to use default time */
452 for(; nChunkUsed < nTrackCount; nChunkUsed++)
453 nTrackTime[nChunkUsed] = -1;
454 } else if (!memcmp(&nChunkType,"fade",4)) {
455 if(!bInfoFound) return -1;
456 for (nChunkUsed=0; nChunkUsed < MIN(nChunkSize / 4,nTrackCount);
457 nChunkUsed++,inbuffer+=4) {
458 nTrackFade[nChunkUsed]=
459 ((uint32_t)inbuffer[0])|
460 ((uint32_t)inbuffer[1]<<8)|
461 ((uint32_t)inbuffer[2]<<16)|
462 ((uint32_t)inbuffer[3]<<24);
465 inbuffer+=nChunkSize-(nChunkUsed*4);
467 /* negative signals to use default time */
468 for(; nChunkUsed < nTrackCount; nChunkUsed++)
469 nTrackFade[nChunkUsed] = -1;
470 } else if (!memcmp(&nChunkType,"BANK",4)) {
471 if(bBankFound) return -1;
473 bBankFound = 1;
474 nChunkUsed = MIN(8,nChunkSize);
475 memcpy(nBankswitch,inbuffer,nChunkUsed);
477 inbuffer+=nChunkSize;
478 } else if (!memcmp(&nChunkType,"plst",4)) {
480 nPlaylistSize = nChunkSize;
481 if(nPlaylistSize >= 1) {
483 memcpy(nPlaylist,inbuffer,nChunkSize);
484 inbuffer+=nChunkSize;
486 } else if (!memcmp(&nChunkType,"auth",4)) {
487 uint8_t* ptr;
489 ptr = inbuffer;
491 uint8_t* ar[4] = {szGameTitle,szArtist,szCopyright,szRipper};
492 int32_t i;
493 for(i = 0; (ptr-inbuffer)<nChunkSize && i < 4; i++)
495 nChunkUsed = strlen(ptr) + 1;
496 memcpy(ar[i],ptr,nChunkUsed);
497 ptr += nChunkUsed;
499 inbuffer+=nChunkSize;
500 } else if (!memcmp(&nChunkType,"tlbl",4)) {
501 /* we unfortunately can't use these anyway */
502 inbuffer+=nChunkSize;
503 } else { /* unknown chunk */
504 nChunkType = letoh32(nChunkType)>>24; /* check the first byte */
505 /* chunk is vital... don't continue */
506 if((nChunkType >= 'A') && (nChunkType <= 'Z'))
507 return -1;
508 /* otherwise, just skip it */
509 inbuffer+=nChunkSize;
510 } /* end if series */
511 } /* end while */
514 * if we exited the while loop without a 'return', we must have hit an NEND
515 * chunk if this is the case, the file was layed out as it was expected.
516 * now.. make sure we found both an info chunk, AND a data chunk... since
517 * these are minimum requirements for a valid NSFE file
520 if(!bInfoFound) return -1;
521 if(!nDataPos) return -1;
523 /* if both those chunks existed, this file is valid.
524 Load the data if it's needed */
526 pDataBuffer=nDataPos;
528 /* return success! */
529 return 0;
533 /****************** Audio Device Structures ******************/
535 struct FDSWave
537 /* Envelope Unit */
538 uint8_t bEnvelopeEnable;
539 uint8_t nEnvelopeSpeed;
541 /* Volume Envelope */
542 uint8_t nVolEnv_Mode;
543 uint8_t nVolEnv_Decay;
544 uint8_t nVolEnv_Gain;
545 int32_t nVolEnv_Timer;
546 int32_t nVolEnv_Count;
547 uint8_t nVolume;
548 uint8_t bVolEnv_On;
550 /* Sweep Envenlope */
551 uint8_t nSweep_Mode;
552 uint8_t nSweep_Decay;
553 int32_t nSweep_Timer;
554 int32_t nSweep_Count;
555 uint8_t nSweep_Gain;
556 uint8_t bSweepEnv_On;
558 /* Effector / LFO / Modulation Unit */
559 int32_t nSweepBias;
560 uint8_t bLFO_Enabled;
561 union TWIN nLFO_Freq;
562 /*float fLFO_Timer;*/
563 /*float fLFO_Count;*/
564 int32_t nLFO_Timer; /* -17.14*/
565 int32_t nLFO_Count; /* -17.14*/
566 uint8_t nLFO_Addr;
567 uint8_t nLFO_Table[0x40];
568 uint8_t bLFO_On;
570 /* Main Output */
571 uint8_t nMainVolume;
572 uint8_t bEnabled;
573 union TWIN nFreq;
574 /*float fFreqCount;*/
575 int32_t nFreqCount; /* -17.14 */
576 uint8_t nMainAddr;
577 uint8_t nWaveTable[0x40];
578 uint8_t bWaveWrite;
579 uint8_t bMain_On;
581 /* Output and Downsampling */
582 int32_t nMixL;
584 /* Pop Reducer */
585 uint8_t bPopReducer;
586 uint8_t nPopOutput;
587 int32_t nPopCount;
590 int16_t FDS_nOutputTable_L[4][0x21][0x40];
592 struct FME07Wave
594 /* Frequency Control */
595 union TWIN nFreqTimer;
596 int32_t nFreqCount;
598 /* Channel Disabling */
599 uint8_t bChannelEnabled;
601 /* Volume */
602 uint8_t nVolume;
604 /* Duty Cycle */
605 uint8_t nDutyCount;
607 /* Output and Downsampling */
608 int32_t nMixL;
611 int16_t FME07_nOutputTable_L[0x10] IDATA_ATTR;
613 struct N106Wave
615 /* All Channel Stuff */
617 uint8_t nActiveChannels;
618 uint8_t bAutoIncrement;
619 uint8_t nCurrentAddress;
620 uint8_t nRAM[0x100]; /* internal memory for registers/wave data */
621 int32_t nFrequencyLookupTable[8]; /* lookup tbl for freq conversions */
624 * Individual channel stuff
626 /* Wavelength / Frequency */
627 union QUAD nFreqReg[8];
628 int32_t nFreqTimer[8];
629 int32_t nFreqCount[8];
631 /* Wave data length / remaining */
632 uint8_t nWaveSize[8];
633 uint8_t nWaveRemaining[8];
635 /* Wave data position */
636 uint8_t nWavePosStart[8];
637 uint8_t nWavePos[8];
638 uint8_t nOutput[8];
640 /* Volume */
641 uint8_t nVolume[8];
643 /* Pop Reducer */
644 uint8_t nPreVolume[8];
645 uint8_t nPopCheck[8];
647 /* Mixing */
648 int32_t nMixL[8];
651 int16_t N106_nOutputTable_L[0x10][0x10];
653 struct VRC6PulseWave
656 /* Frequency Control */
657 union TWIN nFreqTimer;
658 int32_t nFreqCount;
660 /* Flags */
661 uint8_t bChannelEnabled;
662 uint8_t bDigitized;
664 /* Volume */
665 uint8_t nVolume;
667 /* Duty Cycle */
668 uint8_t nDutyCycle;
669 uint8_t nDutyCount;
671 /* Output and Downsampling */
672 int32_t nMixL;
676 int16_t VRC6Pulse_nOutputTable_L[0x10] IDATA_ATTR;
678 struct VRC6SawWave
681 /* Frequency Control */
682 union TWIN nFreqTimer;
683 int32_t nFreqCount;
685 /* Flags */
686 uint8_t bChannelEnabled;
688 /* Phase Accumulator */
689 uint8_t nAccumRate;
690 uint8_t nAccum;
691 uint8_t nAccumStep;
693 /* Output and Downsampling */
694 int32_t nMixL;
698 int16_t VRC6Saw_nOutputTable_L[0x20] IDATA_ATTR;
700 struct Wave_Squares
703 /* Programmable Timer */
704 union TWIN nFreqTimer[2];
705 int32_t nFreqCount[2];
707 /* Length Counter */
708 uint8_t nLengthCount[2];
709 uint8_t bLengthEnabled[2];
710 uint8_t bChannelEnabled[2];
712 /* Volume / Decay */
713 uint8_t nVolume[2];
714 uint8_t nDecayVolume[2];
715 uint8_t bDecayEnable[2];
716 uint8_t bDecayLoop[2];
717 uint8_t nDecayTimer[2];
718 uint8_t nDecayCount[2];
720 /* Sweep Unit */
721 uint8_t bSweepEnable[2];
722 uint8_t bSweepMode[2];
723 uint8_t bSweepForceSilence[2];
724 uint8_t nSweepTimer[2];
725 uint8_t nSweepCount[2];
726 uint8_t nSweepShift[2];
728 /* Duty Cycle */
729 uint8_t nDutyCount[2];
730 uint8_t nDutyCycle[2];
732 /* Output and Downsampling */
733 int32_t nMixL;
736 int16_t Squares_nOutputTable_L[0x10][0x10] IDATA_ATTR;
738 struct Wave_TND
742 * Triangle
745 /* Programmable Timer */
746 union TWIN nTriFreqTimer;
747 int32_t nTriFreqCount;
749 /* Length Counter */
750 uint8_t nTriLengthCount;
751 uint8_t bTriLengthEnabled;
752 uint8_t bTriChannelEnabled;
754 /* Linear Counter */
755 uint8_t nTriLinearCount;
756 uint8_t nTriLinearLoad;
757 uint8_t bTriLinearHalt;
758 uint8_t bTriLinearControl;
760 /* Tri-Step Generator / Output */
761 uint8_t nTriStep;
762 uint8_t nTriOutput;
765 * Noise
768 /* Programmable Timer */
769 uint16_t nNoiseFreqTimer;
770 int32_t nNoiseFreqCount;
772 /* Length Counter */
773 uint8_t nNoiseLengthCount;
774 uint8_t bNoiseLengthEnabled;
775 uint8_t bNoiseChannelEnabled;
777 /* Volume / Decay */
778 uint8_t nNoiseVolume;
779 uint8_t nNoiseDecayVolume;
780 uint8_t bNoiseDecayEnable;
781 uint8_t bNoiseDecayLoop;
782 uint8_t nNoiseDecayTimer;
783 uint8_t nNoiseDecayCount;
785 /* Random Number Generator */
786 uint16_t nNoiseRandomShift;
787 uint8_t bNoiseRandomMode; /* 1 = 32k, 6 = 93-bit */
788 uint8_t bNoiseRandomOut;
791 * DMC
794 /* Play Mode */
795 uint8_t bDMCLoop;
796 uint8_t bDMCIRQEnabled;
797 uint8_t bDMCIRQPending;
799 /* Address / DMA */
800 uint8_t nDMCDMABank_Load;
801 uint16_t nDMCDMAAddr_Load;
802 uint8_t nDMCDMABank;
803 uint16_t nDMCDMAAddr;
804 uint8_t* pDMCDMAPtr[8];
806 /* Length / Input */
807 uint16_t nDMCLength;
808 uint16_t nDMCBytesRemaining;
809 uint8_t nDMCDelta;
810 uint8_t nDMCDeltaBit;
811 uint8_t bDMCDeltaSilent;
812 uint8_t nDMCSampleBuffer;
813 uint8_t bDMCSampleBufferEmpty;
815 /* Frequency */
816 uint16_t nDMCFreqTimer;
817 int32_t nDMCFreqCount;
819 /* Output */
820 uint8_t bDMCActive;
821 uint8_t nDMCOutput;
823 int32_t nMixL;
826 /* channels */
827 struct Wave_Squares mWave_Squares IDATA_ATTR; /* Square channels 1 and 2 */
828 struct Wave_TND mWave_TND IDATA_ATTR; /* Triangle/Noise/DMC channels */
829 struct VRC6PulseWave mWave_VRC6Pulse[2] IDATA_ATTR;
830 struct VRC6SawWave mWave_VRC6Saw IDATA_ATTR;
831 struct N106Wave mWave_N106 IDATA_ATTR;
832 struct FDSWave mWave_FDS IDATA_ATTR;
833 struct FME07Wave mWave_FME07[3] IDATA_ATTR; /* FME-07's 3 pulse channels */
836 /****************** MMC5 ******************/
837 /* will include MMC5 sound channels some day,
838 currently only multiply is supported */
840 /****************** N106 (Disch loves this chip) ******************/
842 #ifdef ICODE_INSTEAD_OF_INLINE
843 void Wave_N106_DoTicks(const int32_t ticks) ICODE_ATTR;
844 void Wave_N106_DoTicks(const int32_t ticks)
845 #else
846 inline void Wave_N106_DoTicks(const int32_t ticks);
847 inline void Wave_N106_DoTicks(const int32_t ticks)
848 #endif
850 register int32_t i;
852 for(i = (7 - mWave_N106.nActiveChannels); i < 8; i++)
854 if(!mWave_N106.nFreqReg[i].D)
856 /* written frequency of zero will cause divide by zero error
857 makes me wonder if the formula was supposed to be Reg+1 */
858 mWave_N106.nVolume[i] = mWave_N106.nPreVolume[i];
859 continue;
863 mWave_N106.nMixL[i] =
864 N106_nOutputTable_L[mWave_N106.nVolume[i]]
865 [mWave_N106.nOutput[i]];
867 if(mWave_N106.nFreqTimer[i] < 0)
868 mWave_N106.nFreqTimer[i] =
869 (mWave_N106.nFrequencyLookupTable[mWave_N106.nActiveChannels] /
870 mWave_N106.nFreqReg[i].D);
871 if(mWave_N106.nFreqCount[i] > mWave_N106.nFreqTimer[i])
872 mWave_N106.nFreqCount[i] = mWave_N106.nFreqTimer[i];
874 mWave_N106.nFreqCount[i] -= ticks << 8;
875 while(mWave_N106.nFreqCount[i] <= 0)
877 mWave_N106.nFreqCount[i] += mWave_N106.nFreqTimer[i];
878 if(mWave_N106.nWaveRemaining[i])
880 mWave_N106.nWaveRemaining[i]--;
881 mWave_N106.nWavePos[i]++;
883 if(!mWave_N106.nWaveRemaining[i])
885 mWave_N106.nWaveRemaining[i] = mWave_N106.nWaveSize[i];
886 mWave_N106.nWavePos[i] = mWave_N106.nWavePosStart[i];
887 if(mWave_N106.nVolume[i] != mWave_N106.nPreVolume[i])
889 if(++mWave_N106.nPopCheck[i] >= 2)
891 mWave_N106.nPopCheck[i] = 0;
892 mWave_N106.nVolume[i] = mWave_N106.nPreVolume[i];
897 mWave_N106.nOutput[i] =
898 mWave_N106.nRAM[mWave_N106.nWavePos[i]];
900 if(!mWave_N106.nOutput[i])
902 mWave_N106.nPopCheck[i] = 0;
903 mWave_N106.nVolume[i] = mWave_N106.nPreVolume[i];
910 /****************** VRC6 ******************/
912 #ifdef ICODE_INSTEAD_OF_INLINE
913 void Wave_VRC6_DoTicks(const int32_t ticks) ICODE_ATTR;
914 void Wave_VRC6_DoTicks(const int32_t ticks)
915 #else
916 inline void Wave_VRC6_DoTicks(const int32_t ticks);
917 inline void Wave_VRC6_DoTicks(const int32_t ticks)
918 #endif
920 register int32_t i;
922 for(i = 0; i < 2; i++) {
924 if(mWave_VRC6Pulse[i].bChannelEnabled) {
926 mWave_VRC6Pulse[i].nFreqCount -= ticks;
928 if(mWave_VRC6Pulse[i].nDutyCount <=
929 mWave_VRC6Pulse[i].nDutyCycle)
931 mWave_VRC6Pulse[i].nMixL =
932 VRC6Pulse_nOutputTable_L[mWave_VRC6Pulse[i].nVolume];
934 else
935 mWave_VRC6Pulse[i].nMixL = 0;
937 while(mWave_VRC6Pulse[i].nFreqCount <= 0) {
938 mWave_VRC6Pulse[i].nFreqCount +=
939 mWave_VRC6Pulse[i].nFreqTimer.W + 1;
941 if(!mWave_VRC6Pulse[i].bDigitized)
942 mWave_VRC6Pulse[i].nDutyCount =
943 (mWave_VRC6Pulse[i].nDutyCount + 1) & 0x0F;
948 if(mWave_VRC6Saw.bChannelEnabled) {
950 mWave_VRC6Saw.nFreqCount -= ticks;
952 mWave_VRC6Saw.nMixL =
953 VRC6Saw_nOutputTable_L[mWave_VRC6Saw.nAccum >> 3];
955 while(mWave_VRC6Saw.nFreqCount <= 0) {
957 mWave_VRC6Saw.nFreqCount += mWave_VRC6Saw.nFreqTimer.W + 1;
959 mWave_VRC6Saw.nAccumStep++;
960 if(mWave_VRC6Saw.nAccumStep == 14)
962 mWave_VRC6Saw.nAccumStep = 0;
963 mWave_VRC6Saw.nAccum = 0;
965 else if(!(mWave_VRC6Saw.nAccumStep & 1))
966 mWave_VRC6Saw.nAccum += mWave_VRC6Saw.nAccumRate;
971 /****************** Square waves ******************/
973 /* decay */
974 #ifdef ICODE_INSTEAD_OF_INLINE
975 void Wave_Squares_ClockMajor(void) ICODE_ATTR;
976 void Wave_Squares_ClockMajor()
977 #else
978 inline void Wave_Squares_ClockMajor(void);
979 inline void Wave_Squares_ClockMajor()
980 #endif
982 if(mWave_Squares.nDecayCount[0])
983 mWave_Squares.nDecayCount[0]--;
984 else
986 mWave_Squares.nDecayCount[0] = mWave_Squares.nDecayTimer[0];
987 if(mWave_Squares.nDecayVolume[0])
988 mWave_Squares.nDecayVolume[0]--;
989 else
991 if(mWave_Squares.bDecayLoop[0])
992 mWave_Squares.nDecayVolume[0] = 0x0F;
995 if(mWave_Squares.bDecayEnable[0])
996 mWave_Squares.nVolume[0] = mWave_Squares.nDecayVolume[0];
999 if(mWave_Squares.nDecayCount[1])
1000 mWave_Squares.nDecayCount[1]--;
1001 else
1003 mWave_Squares.nDecayCount[1] = mWave_Squares.nDecayTimer[1];
1004 if(mWave_Squares.nDecayVolume[1])
1005 mWave_Squares.nDecayVolume[1]--;
1006 else
1008 if(mWave_Squares.bDecayLoop[1])
1009 mWave_Squares.nDecayVolume[1] = 0x0F;
1012 if(mWave_Squares.bDecayEnable[1])
1013 mWave_Squares.nVolume[1] = mWave_Squares.nDecayVolume[1];
1019 #ifdef ICODE_INSTEAD_OF_INLINE
1020 void Wave_Squares_CheckSweepForcedSilence(const int32_t i) ICODE_ATTR;
1021 void Wave_Squares_CheckSweepForcedSilence(const int32_t i)
1022 #else
1023 inline void Wave_Squares_CheckSweepForcedSilence(const int32_t i);
1024 inline void Wave_Squares_CheckSweepForcedSilence(const int32_t i)
1025 #endif
1027 if(mWave_Squares.nFreqTimer[i].W < 8) {
1028 mWave_Squares.bSweepForceSilence[i] = 1; return;
1030 if(!mWave_Squares.bSweepMode[i] &&
1031 (( mWave_Squares.nFreqTimer[i].W +
1032 (mWave_Squares.nFreqTimer[i].W >> mWave_Squares.nSweepShift[i]))
1033 >= 0x0800)) { mWave_Squares.bSweepForceSilence[i] = 1; return; }
1035 mWave_Squares.bSweepForceSilence[i] = 0;
1038 /* sweep / length */
1039 #ifdef ICODE_INSTEAD_OF_INLINE
1040 void Wave_Squares_ClockMinor(void) ICODE_ATTR;
1041 void Wave_Squares_ClockMinor()
1042 #else
1043 inline void Wave_Squares_ClockMinor(void);
1044 inline void Wave_Squares_ClockMinor()
1045 #endif
1047 /* unrolled a little loop
1048 static int i = 0;
1049 for(i = 0; i < 2; i++)
1052 if(mWave_Squares.bLengthEnabled[0] && mWave_Squares.nLengthCount[0])
1053 mWave_Squares.nLengthCount[0]--;
1055 if(!mWave_Squares.bSweepEnable[0] || !mWave_Squares.nLengthCount[0] ||
1056 mWave_Squares.bSweepForceSilence[0] || !mWave_Squares.nSweepShift[0])
1057 goto other_square;
1059 if(mWave_Squares.nSweepCount[0])
1060 mWave_Squares.nSweepCount[0]--;
1061 else
1063 mWave_Squares.nSweepCount[0] = mWave_Squares.nSweepTimer[0];
1064 if(mWave_Squares.bSweepMode[0]) mWave_Squares.nFreqTimer[0].W -=
1065 (mWave_Squares.nFreqTimer[0].W >> mWave_Squares.nSweepShift[0])+1;
1066 else mWave_Squares.nFreqTimer[0].W +=
1067 (mWave_Squares.nFreqTimer[0].W >> mWave_Squares.nSweepShift[0]);
1069 Wave_Squares_CheckSweepForcedSilence(0);
1072 /* */
1073 other_square:
1074 if(mWave_Squares.bLengthEnabled[1] && mWave_Squares.nLengthCount[1])
1075 mWave_Squares.nLengthCount[1]--;
1077 if(!mWave_Squares.bSweepEnable[1] || !mWave_Squares.nLengthCount[1] ||
1078 mWave_Squares.bSweepForceSilence[1] || !mWave_Squares.nSweepShift[1])
1079 return;
1081 if(mWave_Squares.nSweepCount[1])
1082 mWave_Squares.nSweepCount[1]--;
1083 else
1085 mWave_Squares.nSweepCount[1] = mWave_Squares.nSweepTimer[1];
1086 if(mWave_Squares.bSweepMode[1]) mWave_Squares.nFreqTimer[1].W -=
1087 (mWave_Squares.nFreqTimer[1].W >> mWave_Squares.nSweepShift[1]);
1088 else mWave_Squares.nFreqTimer[1].W +=
1089 (mWave_Squares.nFreqTimer[1].W >> mWave_Squares.nSweepShift[1]);
1091 Wave_Squares_CheckSweepForcedSilence(1);
1095 /****************** Triangle/noise/DMC ******************/
1097 /* decay (noise), linear (tri) */
1099 #ifdef ICODE_INSTEAD_OF_INLINE
1100 void Wave_TND_ClockMajor(void) ICODE_ATTR;
1101 void Wave_TND_ClockMajor()
1102 #else
1103 inline void Wave_TND_ClockMajor(void);
1104 inline void Wave_TND_ClockMajor()
1105 #endif
1107 /* noise's decay */
1108 if(mWave_TND.nNoiseDecayCount)
1109 mWave_TND.nNoiseDecayCount--;
1110 else
1112 mWave_TND.nNoiseDecayCount = mWave_TND.nNoiseDecayTimer;
1113 if(mWave_TND.nNoiseDecayVolume)
1114 mWave_TND.nNoiseDecayVolume--;
1115 else
1117 if(mWave_TND.bNoiseDecayLoop)
1118 mWave_TND.nNoiseDecayVolume = 0x0F;
1121 if(mWave_TND.bNoiseDecayEnable)
1122 mWave_TND.nNoiseVolume = mWave_TND.nNoiseDecayVolume;
1125 /* triangle's linear */
1126 if(mWave_TND.bTriLinearHalt)
1127 mWave_TND.nTriLinearCount = mWave_TND.nTriLinearLoad;
1128 else if(mWave_TND.nTriLinearCount)
1129 mWave_TND.nTriLinearCount--;
1131 if(!mWave_TND.bTriLinearControl)
1132 mWave_TND.bTriLinearHalt = 0;
1135 /* length */
1137 #ifdef ICODE_INSTEAD_OF_INLINE
1138 void Wave_TND_ClockMinor(void) ICODE_ATTR;
1139 void Wave_TND_ClockMinor()
1140 #else
1141 inline void Wave_TND_ClockMinor(void);
1142 inline void Wave_TND_ClockMinor()
1143 #endif
1145 if(mWave_TND.bNoiseLengthEnabled && mWave_TND.nNoiseLengthCount)
1146 mWave_TND.nNoiseLengthCount--;
1148 if(mWave_TND.bTriLengthEnabled && mWave_TND.nTriLengthCount)
1149 mWave_TND.nTriLengthCount--;
1152 /*#undef this*/
1154 /****************** NSF Core ******************/
1156 /* start globals */
1159 * Memory
1161 /* RAM: 0x0000 - 0x07FF */
1162 uint8_t pRAM[0x800] IDATA_ATTR;
1163 /* SRAM: 0x6000 - 0x7FFF (non-FDS only) */
1164 uint8_t pSRAM[0x2000];
1165 /* ExRAM: 0x5C00 - 0x5FF5 (MMC5 only)
1166 * Also holds NSF player code (at 0x5000 - 0x500F) */
1167 uint8_t pExRAM[0x1000];
1168 /* Full ROM buffer */
1169 uint8_t* pROM_Full IDATA_ATTR;
1171 uint16_t main_nOutputTable_L[0x8000];
1173 uint8_t* pROM[10] IDATA_ATTR;/* ROM banks (point to areas in pROM_Full) */
1174 /* 0x8000 - 0xFFFF */
1175 /* also includes 0x6000 - 0x7FFF (FDS only) */
1176 uint8_t* pStack; /* the stack (points to areas in pRAM) */
1177 /* 0x0100 - 0x01FF */
1179 int32_t nROMSize; /* size of this ROM file in bytes */
1180 int32_t nROMBankCount; /* max number of 4k banks */
1181 int32_t nROMMaxSize; /* size of allocated pROM_Full buffer */
1184 * Memory Proc Pointers
1187 typedef uint8_t ( *ReadProc)(uint16_t);
1188 typedef void ( *WriteProc)(uint16_t,uint8_t);
1189 ReadProc ReadMemory[0x10] IDATA_ATTR;
1190 WriteProc WriteMemory[0x10] IDATA_ATTR;
1193 * 6502 Registers / Mode
1196 uint8_t regA IDATA_ATTR; /* Accumulator */
1197 uint8_t regX IDATA_ATTR; /* X-Index */
1198 uint8_t regY IDATA_ATTR; /* Y-Index */
1199 uint8_t regP IDATA_ATTR; /* Processor Status */
1200 uint8_t regSP IDATA_ATTR; /* Stack Pointer */
1201 uint16_t regPC IDATA_ATTR; /* Program Counter */
1203 uint8_t bPALMode IDATA_ATTR;/* 1 if in PAL emulation mode, 0 if in NTSC */
1204 uint8_t bCPUJammed IDATA_ATTR; /* 0 = not jammed. 1 = really jammed.
1205 * 2 = 'fake' jammed */
1206 /* fake jam caused by the NSF code to signal
1207 * the end of the play/init routine */
1209 /* Multiplication Register, for MMC5 chip only (5205+5206) */
1210 uint8_t nMultIn_Low;
1211 uint8_t nMultIn_High;
1214 * NSF Preparation Information
1217 uint8_t nBankswitchInitValues[10]; /* banks to swap to on tune init */
1218 uint16_t nPlayAddress; /* Play routine address */
1219 uint16_t nInitAddress; /* Init routine address */
1221 uint8_t nExternalSound; /* external sound chips */
1222 uint8_t nCurTrack;
1224 float fNSFPlaybackSpeed;
1227 * pAPU
1230 uint8_t nFrameCounter; /* Frame Sequence Counter */
1231 uint8_t nFrameCounterMax; /* Frame Sequence Counter Size
1232 (3 or 4 depending on $4017.7) */
1233 uint8_t bFrameIRQEnabled; /* TRUE if frame IRQs are enabled */
1234 uint8_t bFrameIRQPending; /* TRUE if the frame sequencer is holding down
1235 an IRQ */
1237 uint8_t nFME07_Address;
1240 * Timing and Counters
1242 /* fixed point -15.16 */
1244 int32_t nTicksUntilNextFrame;
1245 int32_t nTicksPerPlay;
1246 int32_t nTicksUntilNextPlay;
1247 int32_t nTicksPerSample;
1248 int32_t nTicksUntilNextSample;
1250 uint32_t nCPUCycle IDATA_ATTR;
1251 uint32_t nAPUCycle IDATA_ATTR;
1254 uint32_t nTotalPlays; /* number of times the play subroutine has been called
1255 (for tracking output time) */
1257 * Silence Tracker
1259 int32_t nSilentSamples;
1260 int32_t nSilentSampleMax;
1261 int32_t nSilenceTrackMS;
1262 uint8_t bNoSilenceIfTime;
1263 uint8_t bTimeNotDefault;
1266 * Sound output options
1268 const int32_t nSampleRate=44100;
1271 * Volume/fading/filter tracking
1274 uint32_t nStartFade; /* play call to start fading out */
1275 uint32_t nEndFade; /* play call to stop fading out (song is over) */
1276 uint8_t bFade; /* are we fading? */
1277 float fFadeVolume;
1278 float fFadeChange;
1281 * Designated Output Buffer
1283 uint8_t* pOutput IDATA_ATTR;
1285 const uint8_t bDMCPopReducer=1;
1286 uint8_t nDMCPop_Prev IDATA_ATTR = 0;
1287 uint8_t bDMCPop_Skip IDATA_ATTR = 0;
1288 uint8_t bDMCPop_SamePlay IDATA_ATTR = 0;
1290 const uint8_t nForce4017Write=0;
1291 const uint8_t bN106PopReducer=0;
1292 const uint8_t bIgnore4011Writes=0;
1294 const uint8_t bIgnoreBRK=0;
1295 const uint8_t bIgnoreIllegalOps=0;
1296 const uint8_t bNoWaitForReturn=0;
1297 const uint8_t bPALPreference=0;
1298 const uint8_t bCleanAXY=0;
1299 const uint8_t bResetDuty=0;
1302 * Sound Filter
1305 int64_t nFilterAccL IDATA_ATTR;
1306 int64_t nHighPass IDATA_ATTR;
1308 int32_t nHighPassBase IDATA_ATTR;
1310 uint8_t bHighPassEnabled IDATA_ATTR;
1312 /* end globals */
1314 #define CLOCK_MAJOR() { Wave_Squares_ClockMajor(); Wave_TND_ClockMajor(); }
1315 #define CLOCK_MINOR() { Wave_Squares_ClockMinor(); Wave_TND_ClockMinor(); }
1317 #define EXTSOUND_VRC6 0x01
1318 #define EXTSOUND_VRC7 0x02
1319 #define EXTSOUND_FDS 0x04
1320 #define EXTSOUND_MMC5 0x08
1321 #define EXTSOUND_N106 0x10
1322 #define EXTSOUND_FME07 0x20
1324 #define SILENCE_THRESHOLD 3
1327 * prototypes
1330 uint32_t Emulate6502(uint32_t runto) ICODE_ATTR;
1331 void EmulateAPU(uint8_t bBurnCPUCycles) ICODE_ATTR;
1333 int NSFCore_Initialize(void); /* 1 = initialized ok,
1334 0 = couldn't initialize (memory allocation error) */
1337 * Song Loading
1339 int LoadNSF(int32_t); /* grab data from an existing file
1340 1 = loaded ok, 0 = error loading */
1343 * Track Control
1345 void SetTrack(uint8_t track); /* Change tracks */
1348 * Getting Samples
1350 /* fill a buffer with samples */
1351 int32_t GetSamples(uint8_t* buffer, int32_t buffersize);
1354 * Playback options
1356 /* Set desired playback options (0 = bad options couldn't be set) */
1357 int SetPlaybackOptions(int32_t samplerate);
1358 /* Speed throttling (0 = uses NSF specified speed) */
1359 void SetPlaybackSpeed(float playspersec);
1361 float GetPlaybackSpeed(void);
1362 float GetMasterVolume(void);
1365 * Seeking
1367 /* gets the number of 'play' routine calls executed */
1368 float GetPlayCalls(void);
1370 /* gets the output time (based on the given play rate,
1371 if basedplayspersec is zero, current playback speed is used */
1372 uint32_t GetWrittenTime(float basedplayspersec);
1373 /* sets the number of 'plays' routines executed (for precise seeking) */
1374 void SetPlayCalls(float plays);
1375 /* sets the written time (approx. seeking) */
1376 void SetWrittenTime(uint32_t ms,float basedplays);
1379 * Fading
1382 void StopFade(void); /* stops all fading (plays indefinitely) */
1383 uint8_t SongCompleted(void); /* song has faded out (samples have stopped
1384 being generated) */
1385 /* parameters are play calls */
1386 void SetFade(int32_t fadestart,int32_t fadestop,uint8_t bNotDefault);
1387 void SetFadeTime(uint32_t fadestart,uint32_t fadestop,float basedplays,
1388 uint8_t bNotDefault); /* parameters are in milliseconds */
1391 * Internal Functions
1393 void RebuildOutputTables(void);
1394 void RecalculateFade(void); /* called when fade status is changed. */
1395 void RecalcFilter(void);
1396 void RecalcSilenceTracker(void);
1398 void WriteMemory_VRC6(uint16_t a,uint8_t v) ICODE_ATTR;
1399 void WriteMemory_MMC5(uint16_t a,uint8_t v) ICODE_ATTR;
1400 void WriteMemory_N106(uint16_t a,uint8_t v) ICODE_ATTR;
1401 void WriteMemory_FME07(uint16_t a,uint8_t v) ICODE_ATTR;
1404 * Memory Read/Write routines
1407 uint8_t ReadMemory_RAM(uint16_t a) ICODE_ATTR;
1408 uint8_t ReadMemory_ExRAM(uint16_t a) ICODE_ATTR;
1409 uint8_t ReadMemory_SRAM(uint16_t a) ICODE_ATTR;
1410 uint8_t ReadMemory_pAPU(uint16_t a) ICODE_ATTR;
1411 uint8_t ReadMemory_ROM(uint16_t a) ICODE_ATTR;
1412 uint8_t ReadMemory_Default(uint16_t a) ICODE_ATTR;
1414 uint8_t ReadMemory_N106(uint16_t a) ICODE_ATTR;
1416 void WriteMemory_RAM(uint16_t a,uint8_t v) ICODE_ATTR;
1417 void WriteMemory_ExRAM(uint16_t a,uint8_t v) ICODE_ATTR;
1418 void WriteMemory_SRAM(uint16_t a,uint8_t v) ICODE_ATTR;
1419 void WriteMemory_pAPU(uint16_t a,uint8_t v) ICODE_ATTR;
1420 void WriteMemory_FDSRAM(uint16_t a,uint8_t v) ICODE_ATTR;
1421 void WriteMemory_Default(uint16_t a,uint8_t v) ICODE_ATTR;
1423 uint8_t ReadMemory_RAM(uint16_t a) { return pRAM[a & 0x07FF]; }
1424 uint8_t ReadMemory_ExRAM(uint16_t a) { return pExRAM[a & 0x0FFF]; }
1425 uint8_t ReadMemory_SRAM(uint16_t a) { return pSRAM[a & 0x1FFF]; }
1426 uint8_t ReadMemory_ROM(uint16_t a)
1427 { return pROM[(a >> 12) - 6][a & 0x0FFF]; }
1428 uint8_t ReadMemory_Default(uint16_t a) { return (a >> 8); }
1430 void WriteMemory_RAM(uint16_t a,uint8_t v)
1431 { pRAM[a & 0x07FF] = v; }
1432 void WriteMemory_ExRAM(uint16_t a,uint8_t v);
1433 void WriteMemory_SRAM(uint16_t a,uint8_t v)
1434 { pSRAM[a & 0x1FFF] = v; }
1435 void WriteMemory_FDSRAM(uint16_t a,uint8_t v)
1436 { pROM[(a >> 12) - 6][a & 0x0FFF] = v; }
1437 void WriteMemory_Default(uint16_t a,uint8_t v) { (void)a; (void)v; }
1440 /* Read Memory Procs */
1442 uint8_t ReadMemory_pAPU(uint16_t a)
1444 EmulateAPU(1);
1446 if(a == 0x4015)
1448 uint8_t ret = 0;
1449 if(mWave_Squares.nLengthCount[0]) ret |= 0x01;
1450 if(mWave_Squares.nLengthCount[1]) ret |= 0x02;
1451 if(mWave_TND.nTriLengthCount) ret |= 0x04;
1452 if(mWave_TND.nNoiseLengthCount) ret |= 0x08;
1453 if(mWave_TND.nDMCBytesRemaining) ret |= 0x10;
1455 if(bFrameIRQPending) ret |= 0x40;
1456 if(mWave_TND.bDMCIRQPending) ret |= 0x80;
1458 bFrameIRQPending = 0;
1459 return ret;
1462 if(!(nExternalSound & EXTSOUND_FDS)) return 0x40;
1463 if(bPALMode) return 0x40;
1465 if((a >= 0x4040) && (a <= 0x407F))
1466 return mWave_FDS.nWaveTable[a & 0x3F] | 0x40;
1467 if(a == 0x4090)
1468 return (mWave_FDS.nVolEnv_Gain & 0x3F) | 0x40;
1469 if(a == 0x4092)
1470 return (mWave_FDS.nSweep_Gain & 0x3F) | 0x40;
1472 return 0x40;
1475 uint8_t ReadMemory_N106(uint16_t a)
1477 if(a != 0x4800)
1478 return ReadMemory_pAPU(a);
1480 uint8_t ret = mWave_N106.nRAM[(mWave_N106.nCurrentAddress << 1)] |
1481 (mWave_N106.nRAM[(mWave_N106.nCurrentAddress << 1) + 1] << 4);
1482 if(mWave_N106.bAutoIncrement)
1483 mWave_N106.nCurrentAddress = (mWave_N106.nCurrentAddress + 1) & 0x7F;
1485 return ret;
1489 /* Write Memory Procs */
1491 void WriteMemory_ExRAM(uint16_t a,uint8_t v)
1493 if(a < 0x5FF6) /* Invalid */
1494 return;
1496 a -= 0x5FF6;
1498 /* Swap out banks */
1500 EmulateAPU(1);
1501 /* stop it from swapping to a bank that doesn't exist */
1502 if(v >= nROMBankCount)
1503 v = 0;
1505 pROM[a] = pROM_Full + (v << 12);
1507 /* Update the DMC's DMA pointer, as well */
1508 if(a >= 2)
1509 mWave_TND.pDMCDMAPtr[a - 2] = pROM[a];
1512 void WriteMemory_pAPU(uint16_t a,uint8_t v)
1514 EmulateAPU(1);
1515 switch(a)
1517 /* Square 1 */
1518 case 0x4000:
1519 mWave_Squares.nDutyCycle[0] = DUTY_CYCLE_TABLE[v >> 6];
1520 mWave_Squares.bLengthEnabled[0] =
1521 !(mWave_Squares.bDecayLoop[0] = (v & 0x20));
1522 mWave_Squares.bDecayEnable[0] = !(v & 0x10);
1523 mWave_Squares.nDecayTimer[0] = (v & 0x0F);
1525 if(!mWave_Squares.bDecayEnable[0])
1526 mWave_Squares.nVolume[0] = mWave_Squares.nDecayTimer[0];
1527 break;
1529 case 0x4001:
1530 mWave_Squares.bSweepEnable[0] = (v & 0x80);
1531 mWave_Squares.nSweepTimer[0] = (v & 0x70) >> 4;
1532 mWave_Squares.bSweepMode[0] = v & 0x08;
1533 mWave_Squares.nSweepShift[0] = v & 0x07;
1534 Wave_Squares_CheckSweepForcedSilence(0);
1535 break;
1537 case 0x4002:
1538 mWave_Squares.nFreqTimer[0].B.l = v;
1539 Wave_Squares_CheckSweepForcedSilence(0);
1540 break;
1542 case 0x4003:
1543 mWave_Squares.nFreqTimer[0].B.h = v & 0x07;
1544 Wave_Squares_CheckSweepForcedSilence(0);
1546 mWave_Squares.nDecayVolume[0] = 0x0F;
1548 if(mWave_Squares.bChannelEnabled[0])
1549 mWave_Squares.nLengthCount[0] = LENGTH_COUNTER_TABLE[v >> 3];
1551 if(bResetDuty)
1552 mWave_Squares.nDutyCount[0] = 0;
1553 break;
1556 /* Square 2 */
1557 case 0x4004:
1558 mWave_Squares.nDutyCycle[1] = DUTY_CYCLE_TABLE[v >> 6];
1559 mWave_Squares.bLengthEnabled[1] =
1560 !(mWave_Squares.bDecayLoop[1] = (v & 0x20));
1561 mWave_Squares.bDecayEnable[1] = !(v & 0x10);
1562 mWave_Squares.nDecayTimer[1] = (v & 0x0F);
1564 if(!mWave_Squares.bDecayEnable[1])
1565 mWave_Squares.nVolume[1] = mWave_Squares.nDecayTimer[1];
1566 break;
1568 case 0x4005:
1569 mWave_Squares.bSweepEnable[1] = (v & 0x80);
1570 mWave_Squares.nSweepTimer[1] = (v & 0x70) >> 4;
1571 mWave_Squares.bSweepMode[1] = v & 0x08;
1572 mWave_Squares.nSweepShift[1] = v & 0x07;
1573 Wave_Squares_CheckSweepForcedSilence(1);
1574 break;
1576 case 0x4006:
1577 mWave_Squares.nFreqTimer[1].B.l = v;
1578 Wave_Squares_CheckSweepForcedSilence(1);
1579 break;
1581 case 0x4007:
1582 mWave_Squares.nFreqTimer[1].B.h = v & 0x07;
1583 Wave_Squares_CheckSweepForcedSilence(1);
1585 mWave_Squares.nDecayVolume[1] = 0x0F;
1587 if(mWave_Squares.bChannelEnabled[1])
1588 mWave_Squares.nLengthCount[1] = LENGTH_COUNTER_TABLE[v >> 3];
1590 if(bResetDuty)
1591 mWave_Squares.nDutyCount[1] = 0;
1592 break;
1595 /* Triangle */
1596 case 0x4008:
1597 mWave_TND.nTriLinearLoad = v & 0x7F;
1598 mWave_TND.bTriLinearControl = v & 0x80;
1599 mWave_TND.bTriLengthEnabled = !(v & 0x80);
1600 break;
1602 case 0x400A:
1603 mWave_TND.nTriFreqTimer.B.l = v;
1604 break;
1606 case 0x400B:
1607 mWave_TND.nTriFreqTimer.B.h = v & 0x07;
1608 mWave_TND.bTriLinearHalt = 1;
1610 if(mWave_TND.bTriChannelEnabled)
1611 mWave_TND.nTriLengthCount = LENGTH_COUNTER_TABLE[v >> 3];
1612 break;
1614 /* Noise */
1615 case 0x400C:
1616 mWave_TND.bNoiseLengthEnabled =
1617 !(mWave_TND.bNoiseDecayLoop = (v & 0x20));
1618 mWave_TND.bNoiseDecayEnable = !(v & 0x10);
1619 mWave_TND.nNoiseDecayTimer = (v & 0x0F);
1621 if(mWave_TND.bNoiseDecayEnable)
1622 mWave_TND.nNoiseVolume = mWave_TND.nNoiseDecayVolume;
1623 else
1624 mWave_TND.nNoiseVolume = mWave_TND.nNoiseDecayTimer;
1625 break;
1627 case 0x400E:
1628 mWave_TND.nNoiseFreqTimer = NOISE_FREQ_TABLE[v & 0x0F];
1629 mWave_TND.bNoiseRandomMode = (v & 0x80) ? 6 : 1;
1630 break;
1632 case 0x400F:
1633 if(mWave_TND.bNoiseChannelEnabled)
1634 mWave_TND.nNoiseLengthCount = LENGTH_COUNTER_TABLE[v >> 3];
1636 mWave_TND.nNoiseDecayVolume = 0x0F;
1637 if(mWave_TND.bNoiseDecayEnable)
1638 mWave_TND.nNoiseVolume = 0x0F;
1639 break;
1641 /* DMC */
1642 case 0x4010:
1643 mWave_TND.bDMCLoop = v & 0x40;
1644 mWave_TND.bDMCIRQEnabled = v & 0x80;
1645 /* IRQ can't be pending if disabled */
1646 if(!mWave_TND.bDMCIRQEnabled)
1647 mWave_TND.bDMCIRQPending = 0;
1649 mWave_TND.nDMCFreqTimer = DMC_FREQ_TABLE[bPALMode][v & 0x0F];
1650 break;
1652 case 0x4011:
1653 if(bIgnore4011Writes)
1654 break;
1655 v &= 0x7F;
1656 if(bDMCPopReducer)
1658 if(bDMCPop_SamePlay)
1659 mWave_TND.nDMCOutput = v;
1660 else
1662 if(bDMCPop_Skip)
1664 bDMCPop_Skip = 0;
1665 break;
1667 if(nDMCPop_Prev == v) break;
1668 if(mWave_TND.nDMCOutput == v) break;
1669 mWave_TND.nDMCOutput = nDMCPop_Prev;
1670 nDMCPop_Prev = v;
1671 bDMCPop_SamePlay = 1;
1674 else
1675 mWave_TND.nDMCOutput = v;
1676 break;
1678 case 0x4012:
1679 mWave_TND.nDMCDMABank_Load = (v >> 6) | 0x04;
1680 mWave_TND.nDMCDMAAddr_Load = (v << 6) & 0x0FFF;
1681 break;
1683 case 0x4013:
1684 mWave_TND.nDMCLength = (v << 4) + 1;
1685 break;
1687 /* All / General Purpose */
1688 case 0x4015:
1689 mWave_TND.bDMCIRQPending = 0;
1691 if(v & 0x01){ mWave_Squares.bChannelEnabled[0] = 1; }
1692 else { mWave_Squares.bChannelEnabled[0] =
1693 mWave_Squares.nLengthCount[0] = 0; }
1694 if(v & 0x02){ mWave_Squares.bChannelEnabled[1] = 1; }
1695 else { mWave_Squares.bChannelEnabled[1] =
1696 mWave_Squares.nLengthCount[1] = 0; }
1697 if(v & 0x04){ mWave_TND.bTriChannelEnabled = 1; }
1698 else { mWave_TND.bTriChannelEnabled =
1699 mWave_TND.nTriLengthCount = 0; }
1700 if(v & 0x08){ mWave_TND.bNoiseChannelEnabled = 1; }
1701 else { mWave_TND.bNoiseChannelEnabled =
1702 mWave_TND.nNoiseLengthCount = 0; }
1704 if(v & 0x10)
1706 if(!mWave_TND.nDMCBytesRemaining)
1708 bDMCPop_Skip = 1;
1709 mWave_TND.nDMCDMAAddr = mWave_TND.nDMCDMAAddr_Load;
1710 mWave_TND.nDMCDMABank = mWave_TND.nDMCDMABank_Load;
1711 mWave_TND.nDMCBytesRemaining = mWave_TND.nDMCLength;
1712 mWave_TND.bDMCActive = 1;
1715 else
1716 mWave_TND.nDMCBytesRemaining = 0;
1717 break;
1719 case 0x4017:
1720 bFrameIRQEnabled = !(v & 0x40);
1721 bFrameIRQPending = 0;
1722 nFrameCounter = 0;
1723 nFrameCounterMax = (v & 0x80) ? 4 : 3;
1724 nTicksUntilNextFrame =
1725 (bPALMode ? PAL_FRAME_COUNTER_FREQ : NTSC_FRAME_COUNTER_FREQ)
1726 * 0x10000;
1728 CLOCK_MAJOR();
1729 if(v & 0x80) CLOCK_MINOR();
1730 break;
1733 if(!(nExternalSound & EXTSOUND_FDS)) return;
1734 if(bPALMode) return;
1736 /* FDS Sound registers */
1738 if(a < 0x4040) return;
1740 /* wave table */
1741 if(a <= 0x407F)
1743 if(mWave_FDS.bWaveWrite)
1744 mWave_FDS.nWaveTable[a - 0x4040] = v;
1746 else
1748 switch(a)
1750 case 0x4080:
1751 mWave_FDS.nVolEnv_Mode = (v >> 6);
1752 if(v & 0x80)
1754 mWave_FDS.nVolEnv_Gain = v & 0x3F;
1755 if(!mWave_FDS.nMainAddr)
1757 if(mWave_FDS.nVolEnv_Gain < 0x20)
1758 mWave_FDS.nVolume = mWave_FDS.nVolEnv_Gain;
1759 else mWave_FDS.nVolume = 0x20;
1762 mWave_FDS.nVolEnv_Decay = v & 0x3F;
1763 mWave_FDS.nVolEnv_Timer =
1764 ((mWave_FDS.nVolEnv_Decay + 1) * mWave_FDS.nEnvelopeSpeed * 8);
1766 mWave_FDS.bVolEnv_On = mWave_FDS.bEnvelopeEnable &&
1767 mWave_FDS.nEnvelopeSpeed && !(v & 0x80);
1768 break;
1770 case 0x4082:
1771 mWave_FDS.nFreq.B.l = v;
1772 mWave_FDS.bMain_On = mWave_FDS.nFreq.W && mWave_FDS.bEnabled &&
1773 !mWave_FDS.bWaveWrite;
1774 break;
1776 case 0x4083:
1777 mWave_FDS.bEnabled = !(v & 0x80);
1778 mWave_FDS.bEnvelopeEnable = !(v & 0x40);
1779 if(v & 0x80)
1781 if(mWave_FDS.nVolEnv_Gain < 0x20)
1782 mWave_FDS.nVolume = mWave_FDS.nVolEnv_Gain;
1783 else mWave_FDS.nVolume = 0x20;
1785 mWave_FDS.nFreq.B.h = v & 0x0F;
1786 mWave_FDS.bMain_On = mWave_FDS.nFreq.W && mWave_FDS.bEnabled &&
1787 !mWave_FDS.bWaveWrite;
1789 mWave_FDS.bVolEnv_On = mWave_FDS.bEnvelopeEnable &&
1790 mWave_FDS.nEnvelopeSpeed && !(mWave_FDS.nVolEnv_Mode & 2);
1791 mWave_FDS.bSweepEnv_On = mWave_FDS.bEnvelopeEnable &&
1792 mWave_FDS.nEnvelopeSpeed && !(mWave_FDS.nSweep_Mode & 2);
1793 break;
1796 case 0x4084:
1797 mWave_FDS.nSweep_Mode = v >> 6;
1798 if(v & 0x80)
1799 mWave_FDS.nSweep_Gain = v & 0x3F;
1800 mWave_FDS.nSweep_Decay = v & 0x3F;
1801 mWave_FDS.nSweep_Timer =
1802 ((mWave_FDS.nSweep_Decay + 1) * mWave_FDS.nEnvelopeSpeed * 8);
1803 mWave_FDS.bSweepEnv_On =
1804 mWave_FDS.bEnvelopeEnable && mWave_FDS.nEnvelopeSpeed &&
1805 !(v & 0x80);
1806 break;
1809 case 0x4085:
1810 if(v & 0x40) mWave_FDS.nSweepBias = (v & 0x3F) - 0x40;
1811 else mWave_FDS.nSweepBias = v & 0x3F;
1812 mWave_FDS.nLFO_Addr = 0;
1813 break;
1816 case 0x4086:
1817 mWave_FDS.nLFO_Freq.B.l = v;
1818 mWave_FDS.bLFO_On =
1819 mWave_FDS.bLFO_Enabled && mWave_FDS.nLFO_Freq.W;
1820 if(mWave_FDS.nLFO_Freq.W)
1821 mWave_FDS.nLFO_Timer = (0x10000<<14) / mWave_FDS.nLFO_Freq.W;
1822 break;
1824 case 0x4087:
1825 mWave_FDS.bLFO_Enabled = !(v & 0x80);
1826 mWave_FDS.nLFO_Freq.B.h = v & 0x0F;
1827 mWave_FDS.bLFO_On =
1828 mWave_FDS.bLFO_Enabled && mWave_FDS.nLFO_Freq.W;
1829 if(mWave_FDS.nLFO_Freq.W)
1830 mWave_FDS.nLFO_Timer = (0x10000<<14) / mWave_FDS.nLFO_Freq.W;
1831 break;
1833 case 0x4088:
1834 if(mWave_FDS.bLFO_Enabled) break;
1835 register int32_t i;
1836 for(i = 0; i < 62; i++)
1837 mWave_FDS.nLFO_Table[i] = mWave_FDS.nLFO_Table[i + 2];
1838 mWave_FDS.nLFO_Table[62] = mWave_FDS.nLFO_Table[63] = v & 7;
1839 break;
1841 case 0x4089:
1842 mWave_FDS.nMainVolume = v & 3;
1843 mWave_FDS.bWaveWrite = v & 0x80;
1844 mWave_FDS.bMain_On = mWave_FDS.nFreq.W && mWave_FDS.bEnabled &&
1845 !mWave_FDS.bWaveWrite;
1846 break;
1848 case 0x408A:
1849 mWave_FDS.nEnvelopeSpeed = v;
1850 mWave_FDS.bVolEnv_On =
1851 mWave_FDS.bEnvelopeEnable &&
1852 mWave_FDS.nEnvelopeSpeed && !(mWave_FDS.nVolEnv_Mode & 2);
1853 mWave_FDS.bSweepEnv_On =
1854 mWave_FDS.bEnvelopeEnable &&
1855 mWave_FDS.nEnvelopeSpeed && !(mWave_FDS.nSweep_Mode & 2);
1856 break;
1861 void WriteMemory_VRC6(uint16_t a,uint8_t v)
1863 EmulateAPU(1);
1865 if((a < 0xA000) && (nExternalSound & EXTSOUND_VRC7)) return;
1866 else if(nExternalSound & EXTSOUND_FDS)
1867 WriteMemory_FDSRAM(a,v);
1869 switch(a)
1871 /* Pulse 1 */
1872 case 0x9000:
1873 mWave_VRC6Pulse[0].nVolume = v & 0x0F;
1874 mWave_VRC6Pulse[0].nDutyCycle = (v >> 4) & 0x07;
1875 mWave_VRC6Pulse[0].bDigitized = v & 0x80;
1876 if(mWave_VRC6Pulse[0].bDigitized)
1877 mWave_VRC6Pulse[0].nDutyCount = 0;
1878 break;
1880 case 0x9001:
1881 mWave_VRC6Pulse[0].nFreqTimer.B.l = v;
1882 break;
1884 case 0x9002:
1885 mWave_VRC6Pulse[0].nFreqTimer.B.h = v & 0x0F;
1886 mWave_VRC6Pulse[0].bChannelEnabled = v & 0x80;
1887 break;
1890 /* Pulse 2 */
1891 case 0xA000:
1892 mWave_VRC6Pulse[1].nVolume = v & 0x0F;
1893 mWave_VRC6Pulse[1].nDutyCycle = (v >> 4) & 0x07;
1894 mWave_VRC6Pulse[1].bDigitized = v & 0x80;
1895 if(mWave_VRC6Pulse[1].bDigitized)
1896 mWave_VRC6Pulse[1].nDutyCount = 0;
1897 break;
1899 case 0xA001:
1900 mWave_VRC6Pulse[1].nFreqTimer.B.l = v;
1901 break;
1903 case 0xA002:
1904 mWave_VRC6Pulse[1].nFreqTimer.B.h = v & 0x0F;
1905 mWave_VRC6Pulse[1].bChannelEnabled = v & 0x80;
1906 break;
1908 /* Sawtooth */
1909 case 0xB000:
1910 mWave_VRC6Saw.nAccumRate = (v & 0x3F);
1911 break;
1913 case 0xB001:
1914 mWave_VRC6Saw.nFreqTimer.B.l = v;
1915 break;
1917 case 0xB002:
1918 mWave_VRC6Saw.nFreqTimer.B.h = v & 0x0F;
1919 mWave_VRC6Saw.bChannelEnabled = v & 0x80;
1920 break;
1924 void WriteMemory_MMC5(uint16_t a,uint8_t v)
1926 if((a <= 0x5015) && !bPALMode)
1928 /* no audio emulation */
1929 return;
1932 if(a == 0x5205)
1934 nMultIn_Low = v;
1935 goto multiply;
1937 if(a == 0x5206)
1939 nMultIn_High = v;
1940 multiply:
1941 a = nMultIn_Low * nMultIn_High;
1942 pExRAM[0x205] = a & 0xFF;
1943 pExRAM[0x206] = a >> 8;
1944 return;
1947 if(a < 0x5C00) return;
1949 pExRAM[a & 0x0FFF] = v;
1950 if(a >= 0x5FF6)
1951 WriteMemory_ExRAM(a,v);
1954 void WriteMemory_N106(uint16_t a,uint8_t v)
1956 if(a < 0x4800)
1958 WriteMemory_pAPU(a,v);
1959 return;
1962 if(a == 0xF800)
1964 mWave_N106.nCurrentAddress = v & 0x7F;
1965 mWave_N106.bAutoIncrement = (v & 0x80);
1966 return;
1969 if(a == 0x4800)
1971 EmulateAPU(1);
1972 mWave_N106.nRAM[mWave_N106.nCurrentAddress << 1] = v & 0x0F;
1973 mWave_N106.nRAM[(mWave_N106.nCurrentAddress << 1) + 1] = v >> 4;
1974 a = mWave_N106.nCurrentAddress;
1975 if(mWave_N106.bAutoIncrement)
1976 mWave_N106.nCurrentAddress =
1977 (mWave_N106.nCurrentAddress + 1) & 0x7F;
1979 #define N106REGWRITE(ch,r0,r1,r2,r3,r4) \
1980 case r0: if(mWave_N106.nFreqReg[ch].B.l == v) break; \
1981 mWave_N106.nFreqReg[ch].B.l = v; \
1982 mWave_N106.nFreqTimer[ch] = -1; \
1983 break; \
1984 case r1: if(mWave_N106.nFreqReg[ch].B.h == v) break; \
1985 mWave_N106.nFreqReg[ch].B.h = v; \
1986 mWave_N106.nFreqTimer[ch] = -1; \
1987 break; \
1988 case r2: if(mWave_N106.nFreqReg[ch].B.w != (v & 3)){ \
1989 mWave_N106.nFreqReg[ch].B.w = v & 0x03; \
1990 mWave_N106.nFreqTimer[ch] = -1;} \
1991 mWave_N106.nWaveSize[ch] = 0x20 - (v & 0x1C); \
1992 break; \
1993 case r3: mWave_N106.nWavePosStart[ch] = v; \
1994 break; \
1995 case r4: mWave_N106.nPreVolume[ch] = v & 0x0F; \
1996 if(!bN106PopReducer) \
1997 mWave_N106.nVolume[ch] = v & 0x0F
1999 switch(a)
2001 N106REGWRITE(0,0x40,0x42,0x44,0x46,0x47); break;
2002 N106REGWRITE(1,0x48,0x4A,0x4C,0x4E,0x4F); break;
2003 N106REGWRITE(2,0x50,0x52,0x54,0x56,0x57); break;
2004 N106REGWRITE(3,0x58,0x5A,0x5C,0x5E,0x5F); break;
2005 N106REGWRITE(4,0x60,0x62,0x64,0x66,0x67); break;
2006 N106REGWRITE(5,0x68,0x6A,0x6C,0x6E,0x6F); break;
2007 N106REGWRITE(6,0x70,0x72,0x74,0x76,0x77); break;
2008 N106REGWRITE(7,0x78,0x7A,0x7C,0x7E,0x7F);
2009 v = (v >> 4) & 7;
2010 if(mWave_N106.nActiveChannels == v) break;
2011 mWave_N106.nActiveChannels = v;
2012 mWave_N106.nFreqTimer[0] = -1;
2013 mWave_N106.nFreqTimer[1] = -1;
2014 mWave_N106.nFreqTimer[2] = -1;
2015 mWave_N106.nFreqTimer[3] = -1;
2016 mWave_N106.nFreqTimer[4] = -1;
2017 mWave_N106.nFreqTimer[5] = -1;
2018 mWave_N106.nFreqTimer[6] = -1;
2019 mWave_N106.nFreqTimer[7] = -1;
2020 break;
2022 #undef N106REGWRITE
2026 void WriteMemory_FME07(uint16_t a,uint8_t v)
2028 if((a < 0xD000) && (nExternalSound & EXTSOUND_FDS))
2029 WriteMemory_FDSRAM(a,v);
2031 if(a == 0xC000)
2032 nFME07_Address = v;
2033 if(a == 0xE000)
2035 switch(nFME07_Address)
2037 case 0x00: mWave_FME07[0].nFreqTimer.B.l = v; break;
2038 case 0x01: mWave_FME07[0].nFreqTimer.B.h = v & 0x0F; break;
2039 case 0x02: mWave_FME07[1].nFreqTimer.B.l = v; break;
2040 case 0x03: mWave_FME07[1].nFreqTimer.B.h = v & 0x0F; break;
2041 case 0x04: mWave_FME07[2].nFreqTimer.B.l = v; break;
2042 case 0x05: mWave_FME07[2].nFreqTimer.B.h = v & 0x0F; break;
2043 case 0x07:
2044 mWave_FME07[0].bChannelEnabled = !(v & 0x01);
2045 mWave_FME07[1].bChannelEnabled = !(v & 0x02);
2046 mWave_FME07[2].bChannelEnabled = !(v & 0x03);
2047 break;
2048 case 0x08: mWave_FME07[0].nVolume = v & 0x0F; break;
2049 case 0x09: mWave_FME07[1].nVolume = v & 0x0F; break;
2050 case 0x0A: mWave_FME07[2].nVolume = v & 0x0F; break;
2056 * Emulate APU
2059 int32_t fulltick;
2060 void EmulateAPU(uint8_t bBurnCPUCycles)
2062 int32_t tick;
2063 int64_t diff;
2065 int32_t tnd_out;
2066 int square_out1;
2067 int square_out2;
2069 ENTER_TIMER(apu);
2071 fulltick += (signed)(nCPUCycle - nAPUCycle);
2073 int32_t burned;
2074 int32_t mixL;
2076 if(bFade && nSilentSampleMax && (nSilentSamples >= nSilentSampleMax))
2077 fulltick = 0;
2079 while(fulltick>0)
2081 tick = (nTicksUntilNextSample+0xffff)>>16;
2083 fulltick -= tick;
2086 * Sample Generation
2089 ENTER_TIMER(squares);
2090 /* Square generation */
2092 mWave_Squares.nFreqCount[0] -= tick;
2093 mWave_Squares.nFreqCount[1] -= tick;
2095 if((mWave_Squares.nDutyCount[0] < mWave_Squares.nDutyCycle[0]) &&
2096 mWave_Squares.nLengthCount[0] &&
2097 !mWave_Squares.bSweepForceSilence[0])
2098 square_out1 = mWave_Squares.nVolume[0];
2099 else
2100 square_out1 = 0;
2102 if((mWave_Squares.nDutyCount[1] < mWave_Squares.nDutyCycle[1]) &&
2103 mWave_Squares.nLengthCount[1] &&
2104 !mWave_Squares.bSweepForceSilence[1])
2105 square_out2 = mWave_Squares.nVolume[1];
2106 else
2107 square_out2 = 0;
2109 mWave_Squares.nMixL = Squares_nOutputTable_L[square_out1][square_out2];
2111 if(mWave_Squares.nFreqCount[0]<=0)
2113 int cycles =
2114 (-mWave_Squares.nFreqCount[0])/
2115 (mWave_Squares.nFreqTimer[0].W + 1) + 1;
2116 mWave_Squares.nFreqCount[0] =
2117 (mWave_Squares.nFreqTimer[0].W + 1)-
2118 (-mWave_Squares.nFreqCount[0])%
2119 (mWave_Squares.nFreqTimer[0].W + 1);
2120 mWave_Squares.nDutyCount[0] =
2121 (mWave_Squares.nDutyCount[0]+cycles)%0x10;
2123 if(mWave_Squares.nFreqCount[1]<=0)
2125 int cycles =
2126 (-mWave_Squares.nFreqCount[1])/
2127 (mWave_Squares.nFreqTimer[1].W + 1) + 1;
2128 mWave_Squares.nFreqCount[1] =
2129 (mWave_Squares.nFreqTimer[1].W + 1)-
2130 (-mWave_Squares.nFreqCount[1])%
2131 (mWave_Squares.nFreqTimer[1].W + 1);
2132 mWave_Squares.nDutyCount[1] = (mWave_Squares.nDutyCount[1]+cycles)%
2133 0x10;
2135 /* end of Square generation */
2136 EXIT_TIMER(squares);
2137 ENTER_TIMER(tnd);
2139 ENTER_TIMER(tnd_enter);
2141 burned=0;
2143 /* TND generation */
2145 if(mWave_TND.nNoiseFreqTimer) mWave_TND.nNoiseFreqCount -= tick;
2147 if(mWave_TND.nTriFreqTimer.W > 8)
2148 mWave_TND.nTriFreqCount -= tick;
2150 tnd_out = mWave_TND.nTriOutput << 11;
2152 if(mWave_TND.bNoiseRandomOut && mWave_TND.nNoiseLengthCount)
2153 tnd_out |= mWave_TND.nNoiseVolume << 7;
2155 tnd_out |= mWave_TND.nDMCOutput;
2157 mWave_TND.nMixL = main_nOutputTable_L[tnd_out];
2159 EXIT_TIMER(tnd_enter);
2161 ENTER_TIMER(tnd_tri);
2163 /* Tri */
2165 if(mWave_TND.nTriFreqCount<=0)
2167 if(mWave_TND.nTriLengthCount && mWave_TND.nTriLinearCount)
2169 do mWave_TND.nTriStep++;
2170 while ((mWave_TND.nTriFreqCount +=
2171 mWave_TND.nTriFreqTimer.W + 1) <= 0);
2172 mWave_TND.nTriStep &= 0x1F;
2174 if(mWave_TND.nTriStep & 0x10)
2175 mWave_TND.nTriOutput = mWave_TND.nTriStep ^ 0x1F;
2176 else mWave_TND.nTriOutput = mWave_TND.nTriStep;
2177 } else mWave_TND.nTriFreqCount=mWave_TND.nTriFreqTimer.W+1;
2180 EXIT_TIMER(tnd_tri);
2182 ENTER_TIMER(tnd_noise);
2184 /* Noise */
2186 if(mWave_TND.nNoiseFreqTimer &&
2187 mWave_TND.nNoiseVolume && mWave_TND.nNoiseFreqCount<=0)
2189 mWave_TND.nNoiseFreqCount = mWave_TND.nNoiseFreqTimer;
2190 mWave_TND.nNoiseRandomShift <<= 1;
2191 mWave_TND.bNoiseRandomOut = (((mWave_TND.nNoiseRandomShift <<
2192 mWave_TND.bNoiseRandomMode) ^
2193 mWave_TND.nNoiseRandomShift) & 0x8000 ) ? 1 : 0;
2194 if(mWave_TND.bNoiseRandomOut)
2195 mWave_TND.nNoiseRandomShift |= 0x01;
2198 EXIT_TIMER(tnd_noise);
2200 ENTER_TIMER(tnd_dmc);
2202 /* DMC */
2203 if(mWave_TND.bDMCActive)
2205 mWave_TND.nDMCFreqCount -= tick;
2206 while (mWave_TND.nDMCFreqCount <= 0) {
2207 if (!mWave_TND.bDMCActive) {
2208 mWave_TND.nDMCFreqCount = mWave_TND.nDMCFreqTimer;
2209 break;
2212 mWave_TND.nDMCFreqCount += mWave_TND.nDMCFreqTimer;
2214 if(mWave_TND.bDMCSampleBufferEmpty &&
2215 mWave_TND.nDMCBytesRemaining)
2217 burned += 4; /* 4 cycle burn! */
2218 mWave_TND.nDMCSampleBuffer =
2219 mWave_TND.pDMCDMAPtr[mWave_TND.nDMCDMABank]
2220 [mWave_TND.nDMCDMAAddr];
2221 mWave_TND.nDMCDMAAddr++;
2222 if(mWave_TND.nDMCDMAAddr & 0x1000)
2224 mWave_TND.nDMCDMAAddr &= 0x0FFF;
2225 mWave_TND.nDMCDMABank =
2226 (mWave_TND.nDMCDMABank + 1) & 0x07;
2229 mWave_TND.bDMCSampleBufferEmpty = 0;
2230 mWave_TND.nDMCBytesRemaining--;
2231 if(!mWave_TND.nDMCBytesRemaining)
2233 if(mWave_TND.bDMCLoop)
2235 mWave_TND.nDMCDMABank = mWave_TND.nDMCDMABank_Load;
2236 mWave_TND.nDMCDMAAddr = mWave_TND.nDMCDMAAddr_Load;
2237 mWave_TND.nDMCBytesRemaining =mWave_TND.nDMCLength;
2239 else if(mWave_TND.bDMCIRQEnabled)
2240 mWave_TND.bDMCIRQPending = 1;
2244 if(!mWave_TND.nDMCDeltaBit)
2246 mWave_TND.nDMCDeltaBit = 8;
2247 mWave_TND.bDMCDeltaSilent =mWave_TND.bDMCSampleBufferEmpty;
2248 mWave_TND.nDMCDelta = mWave_TND.nDMCSampleBuffer;
2249 mWave_TND.bDMCSampleBufferEmpty = 1;
2252 if(mWave_TND.nDMCDeltaBit) {
2253 mWave_TND.nDMCDeltaBit--;
2254 if(!mWave_TND.bDMCDeltaSilent)
2256 if(mWave_TND.nDMCDelta & 0x01)
2258 if(mWave_TND.nDMCOutput < 0x7E)
2259 mWave_TND.nDMCOutput += 2;
2261 else if(mWave_TND.nDMCOutput > 1)
2262 mWave_TND.nDMCOutput -= 2;
2264 mWave_TND.nDMCDelta >>= 1;
2267 if(!mWave_TND.nDMCBytesRemaining &&
2268 mWave_TND.bDMCSampleBufferEmpty &&
2269 mWave_TND.bDMCDeltaSilent)
2270 mWave_TND.bDMCActive = mWave_TND.nDMCDeltaBit = 0;
2274 EXIT_TIMER(tnd_dmc);
2276 /* end of TND generation */
2277 EXIT_TIMER(tnd);
2279 if(nExternalSound && !bPALMode)
2281 if(nExternalSound & EXTSOUND_VRC6)
2282 Wave_VRC6_DoTicks(tick);
2283 if(nExternalSound & EXTSOUND_N106)
2284 Wave_N106_DoTicks(tick);
2285 if(nExternalSound & EXTSOUND_FME07)
2287 if (mWave_FME07[0].bChannelEnabled &&
2288 mWave_FME07[0].nFreqTimer.W) {
2289 mWave_FME07[0].nFreqCount -= tick;
2291 if(mWave_FME07[0].nDutyCount < 16)
2293 mWave_FME07[0].nMixL =
2294 FME07_nOutputTable_L[mWave_FME07[0].nVolume];
2295 } else mWave_FME07[0].nMixL = 0;
2296 while(mWave_FME07[0].nFreqCount <= 0) {
2297 mWave_FME07[0].nFreqCount +=
2298 mWave_FME07[0].nFreqTimer.W;
2300 mWave_FME07[0].nDutyCount=
2301 (mWave_FME07[0].nDutyCount+1)&0x1f;
2305 if (mWave_FME07[1].bChannelEnabled &&
2306 mWave_FME07[1].nFreqTimer.W) {
2307 mWave_FME07[1].nFreqCount -= tick;
2309 if(mWave_FME07[1].nDutyCount < 16)
2311 mWave_FME07[1].nMixL =
2312 FME07_nOutputTable_L[mWave_FME07[1].nVolume];
2313 } else mWave_FME07[1].nMixL = 0;
2314 while(mWave_FME07[1].nFreqCount <= 0) {
2315 mWave_FME07[1].nFreqCount +=
2316 mWave_FME07[1].nFreqTimer.W;
2318 mWave_FME07[1].nDutyCount=
2319 (mWave_FME07[1].nDutyCount+1)&0x1f;
2323 if (mWave_FME07[2].bChannelEnabled &&
2324 mWave_FME07[2].nFreqTimer.W) {
2325 mWave_FME07[2].nFreqCount -= tick;
2327 if(mWave_FME07[2].nDutyCount < 16)
2329 mWave_FME07[2].nMixL =
2330 FME07_nOutputTable_L[mWave_FME07[2].nVolume];
2331 } else mWave_FME07[2].nMixL = 0;
2332 while(mWave_FME07[2].nFreqCount <= 0) {
2333 mWave_FME07[2].nFreqCount +=
2334 mWave_FME07[2].nFreqTimer.W;
2336 mWave_FME07[2].nDutyCount=
2337 (mWave_FME07[2].nDutyCount+1)&0x1f;
2341 } /* end FME07 */
2342 ENTER_TIMER(fds);
2343 if(nExternalSound & EXTSOUND_FDS) {
2345 /* Volume Envelope Unit */
2346 if(mWave_FDS.bVolEnv_On)
2348 mWave_FDS.nVolEnv_Count -= tick;
2349 while(mWave_FDS.nVolEnv_Count <= 0)
2351 mWave_FDS.nVolEnv_Count += mWave_FDS.nVolEnv_Timer;
2352 if(mWave_FDS.nVolEnv_Mode) {
2353 if(mWave_FDS.nVolEnv_Gain < 0x20)
2354 mWave_FDS.nVolEnv_Gain++;
2356 else {
2357 if(mWave_FDS.nVolEnv_Gain)
2358 mWave_FDS.nVolEnv_Gain--;
2363 /* Sweep Envelope Unit */
2364 if(mWave_FDS.bSweepEnv_On)
2366 mWave_FDS.nSweep_Count -= tick;
2367 while(mWave_FDS.nSweep_Count <= 0)
2369 mWave_FDS.nSweep_Count += mWave_FDS.nSweep_Timer;
2370 if(mWave_FDS.nSweep_Mode) {
2371 if(mWave_FDS.nSweep_Gain < 0x20)
2372 mWave_FDS.nSweep_Gain++;
2373 } else {
2374 if(mWave_FDS.nSweep_Gain) mWave_FDS.nSweep_Gain--;
2379 /* Effector / LFO */
2380 int32_t subfreq = 0;
2381 if(mWave_FDS.bLFO_On)
2383 mWave_FDS.nLFO_Count -= tick<<14;
2384 while(mWave_FDS.nLFO_Count <= 0)
2386 mWave_FDS.nLFO_Count += mWave_FDS.nLFO_Timer;
2387 if(mWave_FDS.nLFO_Table[mWave_FDS.nLFO_Addr] == 4)
2388 mWave_FDS.nSweepBias = 0;
2389 else
2390 mWave_FDS.nSweepBias +=
2391 ModulationTable[
2392 mWave_FDS.nLFO_Table[mWave_FDS.nLFO_Addr]
2394 mWave_FDS.nLFO_Addr = (mWave_FDS.nLFO_Addr + 1) & 0x3F;
2397 while(mWave_FDS.nSweepBias > 63)
2398 mWave_FDS.nSweepBias -= 128;
2399 while(mWave_FDS.nSweepBias < -64)
2400 mWave_FDS.nSweepBias += 128;
2402 register int32_t temp =
2403 mWave_FDS.nSweepBias * mWave_FDS.nSweep_Gain;
2404 if(temp & 0x0F)
2406 temp /= 16;
2407 if(mWave_FDS.nSweepBias < 0) temp--;
2408 else temp += 2;
2410 else
2411 temp /= 16;
2413 if(temp > 193) temp -= 258;
2414 if(temp < -64) temp += 256;
2416 subfreq = mWave_FDS.nFreq.W * temp / 64;
2419 /* Main Unit */
2420 if(mWave_FDS.bMain_On)
2422 mWave_FDS.nMixL =
2423 FDS_nOutputTable_L[mWave_FDS.nMainVolume]
2424 [mWave_FDS.nVolume]
2425 [mWave_FDS.nWaveTable[mWave_FDS.nMainAddr] ];
2427 if((subfreq + mWave_FDS.nFreq.W) > 0)
2429 int32_t freq = (0x10000<<14) / (subfreq + mWave_FDS.nFreq.W);
2431 mWave_FDS.nFreqCount -= tick<<14;
2432 while(mWave_FDS.nFreqCount <= 0)
2434 mWave_FDS.nFreqCount += freq;
2436 mWave_FDS.nMainAddr =
2437 (mWave_FDS.nMainAddr + 1) & 0x3F;
2438 mWave_FDS.nPopOutput =
2439 mWave_FDS.nWaveTable[mWave_FDS.nMainAddr];
2440 if(!mWave_FDS.nMainAddr)
2442 if(mWave_FDS.nVolEnv_Gain < 0x20)
2443 mWave_FDS.nVolume = mWave_FDS.nVolEnv_Gain;
2444 else mWave_FDS.nVolume = 0x20;
2448 else
2449 mWave_FDS.nFreqCount = mWave_FDS.nLFO_Count;
2451 else if(mWave_FDS.bPopReducer && mWave_FDS.nPopOutput)
2453 mWave_FDS.nMixL = FDS_nOutputTable_L[mWave_FDS.nMainVolume]
2454 [mWave_FDS.nVolume]
2455 [mWave_FDS.nPopOutput];
2457 mWave_FDS.nPopCount -= tick;
2458 while(mWave_FDS.nPopCount <= 0)
2460 mWave_FDS.nPopCount += 500;
2461 mWave_FDS.nPopOutput--;
2462 if(!mWave_FDS.nPopOutput)
2463 mWave_FDS.nMainAddr = 0;
2465 } /* end FDS */
2467 EXIT_TIMER(fds);
2468 } /* end while fulltick */
2470 if(bBurnCPUCycles)
2472 nCPUCycle += burned;
2473 fulltick += burned;
2476 /* Frame Sequencer */
2478 ENTER_TIMER(frame);
2479 nTicksUntilNextFrame -= tick<<16;
2480 while(nTicksUntilNextFrame <= 0)
2482 nTicksUntilNextFrame +=
2483 (bPALMode ? PAL_FRAME_COUNTER_FREQ : NTSC_FRAME_COUNTER_FREQ) *
2484 0x10000;
2485 nFrameCounter++;
2486 if(nFrameCounter > nFrameCounterMax)
2487 nFrameCounter = 0;
2489 if(nFrameCounterMax == 4)
2491 if(nFrameCounter < 4)
2493 CLOCK_MAJOR();
2494 if(!(nFrameCounter & 1))
2495 CLOCK_MINOR();
2498 else
2500 CLOCK_MAJOR();
2501 if(nFrameCounter & 1)
2502 CLOCK_MINOR();
2504 if((nFrameCounter == 3) && bFrameIRQEnabled)
2505 bFrameIRQPending = 1;
2508 EXIT_TIMER(frame);
2510 ENTER_TIMER(mix);
2511 nTicksUntilNextSample -= tick<<16;
2512 if(nTicksUntilNextSample <= 0)
2514 nTicksUntilNextSample += nTicksPerSample;
2516 mixL = mWave_Squares.nMixL;
2517 mixL += mWave_TND.nMixL;
2519 if(nExternalSound && !bPALMode)
2521 if(nExternalSound & EXTSOUND_VRC6)
2523 mixL += (mWave_VRC6Pulse[0].nMixL);
2524 mixL += (mWave_VRC6Pulse[1].nMixL);
2525 mixL += (mWave_VRC6Saw.nMixL);
2527 if(nExternalSound & EXTSOUND_N106) {
2528 mixL += (mWave_N106.nMixL[0]);
2529 mixL += (mWave_N106.nMixL[1]);
2530 mixL += (mWave_N106.nMixL[2]);
2531 mixL += (mWave_N106.nMixL[3]);
2532 mixL += (mWave_N106.nMixL[4]);
2533 mixL += (mWave_N106.nMixL[5]);
2534 mixL += (mWave_N106.nMixL[6]);
2535 mixL += (mWave_N106.nMixL[7]);
2537 if(nExternalSound & EXTSOUND_FME07)
2539 mixL += (mWave_FME07[0].nMixL);
2540 mixL += (mWave_FME07[1].nMixL);
2541 mixL += (mWave_FME07[2].nMixL);
2543 if(nExternalSound & EXTSOUND_FDS)
2544 mixL += mWave_FDS.nMixL;
2547 /* Filter */
2548 diff = ((int64_t)mixL << 25) - nFilterAccL;
2549 nFilterAccL += (diff * nHighPass) >> 16;
2550 mixL = (int32_t)(diff >> 23);
2551 /* End Filter */
2553 if(bFade && (fFadeVolume < 1))
2554 mixL = (int32_t)(mixL * fFadeVolume);
2556 if(mixL < -32768) mixL = -32768;
2557 if(mixL > 32767) mixL = 32767;
2559 *((uint16_t*)pOutput) = (uint16_t)mixL;
2560 pOutput += 2;
2564 EXIT_TIMER(mix);
2566 nAPUCycle = nCPUCycle;
2568 EXIT_TIMER(apu);
2573 * Initialize
2575 * Initializes Memory
2578 int NSFCore_Initialize()
2580 int32_t i;
2581 /* clear globals */
2582 /* why, yes, this was easier when they were in a struct */
2585 * Memory
2588 ZEROMEMORY(pRAM,0x800);
2589 ZEROMEMORY(pSRAM,0x2000);
2590 ZEROMEMORY(pExRAM,0x1000);
2591 pROM_Full=0;
2593 ZEROMEMORY(pROM,10);
2594 pStack=0;
2596 nROMSize=0;
2597 nROMBankCount=0;
2598 nROMMaxSize=0;
2601 * Memory Proc Pointers
2604 ZEROMEMORY(ReadMemory,sizeof(ReadProc)*0x10);
2605 ZEROMEMORY(WriteMemory,sizeof(WriteProc)*0x10);
2608 * 6502 Registers / Mode
2611 regA=0;
2612 regX=0;
2613 regY=0;
2614 regP=0;
2615 regSP=0;
2616 regPC=0;
2618 bPALMode=0;
2619 bCPUJammed=0;
2621 nMultIn_Low=0;
2622 nMultIn_High=0;
2625 * NSF Preparation Information
2628 ZEROMEMORY(nBankswitchInitValues,10);
2629 nPlayAddress=0;
2630 nInitAddress=0;
2632 nExternalSound=0;
2633 nCurTrack=0;
2635 fNSFPlaybackSpeed=0;
2638 * pAPU
2641 nFrameCounter=0;
2642 nFrameCounterMax=0;
2643 bFrameIRQEnabled=0;
2644 bFrameIRQPending=0;
2647 * Timing and Counters
2649 nTicksUntilNextFrame=0;
2651 nTicksPerPlay=0;
2652 nTicksUntilNextPlay=0;
2654 nTicksPerSample=0;
2655 nTicksUntilNextSample=0;
2657 nCPUCycle=0;
2658 nAPUCycle=0;
2659 nTotalPlays=0;
2662 * Silence Tracker
2664 nSilentSamples=0;
2665 nSilentSampleMax=0;
2666 nSilenceTrackMS=0;
2667 bNoSilenceIfTime=0;
2668 bTimeNotDefault=0;
2671 * Volume/fading/filter tracking
2674 nStartFade=0;
2675 nEndFade=0;
2676 bFade=0;
2677 fFadeVolume=0;
2678 fFadeChange=0;
2680 pOutput=0;
2682 nDMCPop_Prev=0;
2683 bDMCPop_Skip=0;
2684 bDMCPop_SamePlay=0;
2687 * Sound Filter
2690 nFilterAccL=0;
2691 nHighPass=0;
2693 nHighPassBase=0;
2695 bHighPassEnabled=0;
2697 /* channels */
2699 ZEROMEMORY(&mWave_Squares,sizeof(struct Wave_Squares));
2700 ZEROMEMORY(&mWave_TND,sizeof(struct Wave_TND));
2701 ZEROMEMORY(mWave_VRC6Pulse,sizeof(struct VRC6PulseWave)*2);
2702 ZEROMEMORY(&mWave_VRC6Saw,sizeof(struct VRC6SawWave));
2703 ZEROMEMORY(&mWave_N106,sizeof(struct N106Wave));
2704 ZEROMEMORY(mWave_FME07,sizeof(struct FME07Wave)*3);
2705 ZEROMEMORY(&mWave_FDS,sizeof(struct FDSWave));
2707 /* end clear globals */
2709 // Default filter bases
2710 nHighPassBase = 150;
2712 bHighPassEnabled = 1;
2714 mWave_TND.nNoiseRandomShift = 1;
2715 for(i = 0; i < 8; i++)
2716 mWave_TND.pDMCDMAPtr[i] = pROM[i + 2];
2719 SetPlaybackOptions(nSampleRate);
2721 for(i = 0; i < 8; i++)
2722 mWave_N106.nFrequencyLookupTable[i] =
2723 ((((i + 1) * 45 * 0x40000) / (float)NES_FREQUENCY) *
2724 (float)NTSC_FREQUENCY) * 256.0;
2726 ZEROMEMORY(pRAM,0x800);
2727 ZEROMEMORY(pSRAM,0x2000);
2728 ZEROMEMORY(pExRAM,0x1000);
2729 pStack = pRAM + 0x100;
2730 return 1;
2734 * LoadNSF
2737 int LoadNSF(int32_t datasize)
2739 if(!pDataBuffer) return 0;
2741 int32_t i;
2743 nExternalSound = nChipExtensions;
2744 if(nIsPal & 2)
2745 bPALMode = bPALPreference;
2746 else
2747 bPALMode = nIsPal & 1;
2749 SetPlaybackOptions(nSampleRate);
2751 int32_t neededsize = datasize + (nfileLoadAddress & 0x0FFF);
2752 if(neededsize & 0x0FFF) neededsize += 0x1000 - (neededsize & 0x0FFF);
2753 if(neededsize < 0x1000) neededsize = 0x1000;
2755 uint8_t specialload = 0;
2757 for(i = 0; (i < 8) && (!nBankswitch[i]); i++);
2758 if(i < 8) /* uses bankswitching */
2760 memcpy(&nBankswitchInitValues[2],nBankswitch,8);
2761 nBankswitchInitValues[0] = nBankswitch[6];
2762 nBankswitchInitValues[1] = nBankswitch[7];
2763 if(nExternalSound & EXTSOUND_FDS)
2765 if(!(nBankswitchInitValues[0] || nBankswitchInitValues[1]))
2768 * FDS sound with '00' specified for both $6000 and $7000 banks.
2769 * point this to an area of fresh RAM (sort of hackish solution
2770 * for those FDS tunes that don't quite follow the nsf specs.
2772 nBankswitchInitValues[0] = (uint8_t)(neededsize >> 12);
2773 nBankswitchInitValues[1] = (uint8_t)(neededsize >> 12) + 1;
2774 neededsize += 0x2000;
2778 else /* doesn't use bankswitching */
2780 if(nExternalSound & EXTSOUND_FDS)
2782 /* bad load address */
2783 if(nfileLoadAddress < 0x6000) return 0;
2785 if(neededsize < 0xA000)
2786 neededsize = 0xA000;
2787 specialload = 1;
2788 for(i = 0; i < 10; i++)
2789 nBankswitchInitValues[i] = (uint8_t)i;
2791 else
2793 /* bad load address */
2794 if(nfileLoadAddress < 0x8000) return 0;
2796 int32_t j = (nfileLoadAddress >> 12) - 6;
2797 for(i = 0; i < j; i++)
2798 nBankswitchInitValues[i] = 0;
2799 for(j = 0; i < 10; i++, j++)
2800 nBankswitchInitValues[i] = (uint8_t)j;
2804 nROMSize = neededsize;
2805 nROMBankCount = neededsize >> 12;
2807 if(specialload)
2808 pROM_Full = pDataBuffer-(nfileLoadAddress-0x6000);
2809 else
2810 pROM_Full = pDataBuffer-(nfileLoadAddress&0x0FFF);
2812 ZEROMEMORY(pRAM,0x0800);
2813 ZEROMEMORY(pExRAM,0x1000);
2814 ZEROMEMORY(pSRAM,0x2000);
2816 nExternalSound = nChipExtensions;
2817 fNSFPlaybackSpeed = (bPALMode ? PAL_NMIRATE : NTSC_NMIRATE);
2819 SetPlaybackSpeed(0);
2821 nPlayAddress = nfilePlayAddress;
2822 nInitAddress = nfileInitAddress;
2824 pExRAM[0x00] = 0x20; /* JSR */
2825 pExRAM[0x01] = nInitAddress&0xff; /* Init Address */
2826 pExRAM[0x02] = (nInitAddress>>8)&0xff;
2827 pExRAM[0x03] = 0xF2; /* JAM */
2828 pExRAM[0x04] = 0x20; /* JSR */
2829 pExRAM[0x05] = nPlayAddress&0xff; /* Play Address */
2830 pExRAM[0x06] = (nPlayAddress>>8)&0xff;
2831 pExRAM[0x07] = 0x4C; /* JMP */
2832 pExRAM[0x08] = 0x03;/* $5003 (JAM right before the JSR to play address) */
2833 pExRAM[0x09] = 0x50;
2835 regA = regX = regY = 0;
2836 regP = 0x04; /* I_FLAG */
2837 regSP = 0xFF;
2839 nFilterAccL = 0;
2841 /* Reset Read/Write Procs */
2843 ReadMemory[0] = ReadMemory[1] = ReadMemory_RAM;
2844 ReadMemory[2] = ReadMemory[3] = ReadMemory_Default;
2845 ReadMemory[4] = ReadMemory_pAPU;
2846 ReadMemory[5] = ReadMemory_ExRAM;
2847 ReadMemory[6] = ReadMemory[7] = ReadMemory_SRAM;
2849 WriteMemory[0] = WriteMemory[1] = WriteMemory_RAM;
2850 WriteMemory[2] = WriteMemory[3] = WriteMemory_Default;
2851 WriteMemory[4] = WriteMemory_pAPU;
2852 WriteMemory[5] = WriteMemory_ExRAM;
2853 WriteMemory[6] = WriteMemory[7] = WriteMemory_SRAM;
2855 for(i = 8; i < 16; i++)
2857 ReadMemory[i] = ReadMemory_ROM;
2858 WriteMemory[i] = WriteMemory_Default;
2861 if(nExternalSound & EXTSOUND_FDS)
2863 WriteMemory[0x06] = WriteMemory_FDSRAM;
2864 WriteMemory[0x07] = WriteMemory_FDSRAM;
2865 WriteMemory[0x08] = WriteMemory_FDSRAM;
2866 WriteMemory[0x09] = WriteMemory_FDSRAM;
2867 WriteMemory[0x0A] = WriteMemory_FDSRAM;
2868 WriteMemory[0x0B] = WriteMemory_FDSRAM;
2869 WriteMemory[0x0C] = WriteMemory_FDSRAM;
2870 WriteMemory[0x0D] = WriteMemory_FDSRAM;
2871 ReadMemory[0x06] = ReadMemory_ROM;
2872 ReadMemory[0x07] = ReadMemory_ROM;
2875 if(!bPALMode) /* no expansion sound available on a PAL system */
2877 if(nExternalSound & EXTSOUND_VRC6)
2879 /* if both VRC6+VRC7... it MUST go to WriteMemory_VRC6
2880 * or register writes will be lost (WriteMemory_VRC6 calls
2881 * WriteMemory_VRC7 if needed) */
2882 WriteMemory[0x09] = WriteMemory_VRC6;
2883 WriteMemory[0x0A] = WriteMemory_VRC6;
2884 WriteMemory[0x0B] = WriteMemory_VRC6;
2886 if(nExternalSound & EXTSOUND_N106)
2888 WriteMemory[0x04] = WriteMemory_N106;
2889 ReadMemory[0x04] = ReadMemory_N106;
2890 WriteMemory[0x0F] = WriteMemory_N106;
2892 if(nExternalSound & EXTSOUND_FME07)
2894 WriteMemory[0x0C] = WriteMemory_FME07;
2895 WriteMemory[0x0E] = WriteMemory_FME07;
2899 /* MMC5 still has a multiplication reg that needs to be available on
2900 PAL tunes */
2901 if(nExternalSound & EXTSOUND_MMC5)
2902 WriteMemory[0x05] = WriteMemory_MMC5;
2904 return 1;
2908 * SetTrack
2911 void SetTrack(uint8_t track)
2913 int32_t i;
2915 nCurTrack = track;
2917 regPC = 0x5000;
2918 regA = track;
2919 regX = bPALMode;
2920 regY = bCleanAXY ? 0 : 0xCD;
2921 regSP = 0xFF;
2922 if(bCleanAXY)
2923 regP = 0x04;
2924 bCPUJammed = 0;
2926 nCPUCycle = nAPUCycle = 0;
2927 nDMCPop_Prev = 0;
2928 bDMCPop_Skip = 0;
2930 for(i = 0x4000; i < 0x400F; i++)
2931 WriteMemory_pAPU(i,0);
2932 WriteMemory_pAPU(0x4010,0);
2933 WriteMemory_pAPU(0x4012,0);
2934 WriteMemory_pAPU(0x4013,0);
2935 WriteMemory_pAPU(0x4014,0);
2936 WriteMemory_pAPU(0x4015,0);
2937 WriteMemory_pAPU(0x4015,0x0F);
2938 WriteMemory_pAPU(0x4017,0);
2940 for(i = 0; i < 10; i++)
2941 WriteMemory_ExRAM(0x5FF6 + i,nBankswitchInitValues[i]);
2943 ZEROMEMORY(pRAM,0x0800);
2944 ZEROMEMORY(pSRAM,0x2000);
2945 ZEROMEMORY(&pExRAM[0x10],0x0FF0);
2946 bFade = 0;
2949 nTicksUntilNextSample = nTicksPerSample;
2950 nTicksUntilNextFrame =
2951 (bPALMode ? PAL_FRAME_COUNTER_FREQ : NTSC_FRAME_COUNTER_FREQ)*0x10000;
2952 nTicksUntilNextPlay = nTicksPerPlay;
2953 nTotalPlays = 0;
2955 /* Clear mixing vals */
2956 mWave_Squares.nMixL = 0;
2957 mWave_TND.nMixL = 0;
2958 mWave_VRC6Pulse[0].nMixL = 0;
2959 mWave_VRC6Pulse[1].nMixL = 0;
2960 mWave_VRC6Saw.nMixL = 0;
2962 /* Reset Tri/Noise/DMC */
2963 mWave_TND.nTriStep = mWave_TND.nTriOutput = 0;
2964 mWave_TND.nDMCOutput = 0;
2965 mWave_TND.bNoiseRandomOut = 0;
2966 mWave_Squares.nDutyCount[0] = mWave_Squares.nDutyCount[1] = 0;
2967 mWave_TND.bDMCActive = 0;
2968 mWave_TND.nDMCBytesRemaining = 0;
2969 mWave_TND.bDMCSampleBufferEmpty = 1;
2970 mWave_TND.bDMCDeltaSilent = 1;
2972 /* Reset VRC6 */
2973 mWave_VRC6Pulse[0].nVolume = 0;
2974 mWave_VRC6Pulse[1].nVolume = 0;
2975 mWave_VRC6Saw.nAccumRate = 0;
2977 /* Reset N106 */
2978 ZEROMEMORY(mWave_N106.nRAM,0x100);
2979 ZEROMEMORY(mWave_N106.nVolume,8);
2980 ZEROMEMORY(mWave_N106.nOutput,8);
2981 ZEROMEMORY(mWave_N106.nMixL,32);
2983 /* Reset FME-07 */
2984 mWave_FME07[0].nVolume = 0;
2985 mWave_FME07[1].nVolume = 0;
2986 mWave_FME07[2].nVolume = 0;
2988 /* Clear FDS crap */
2990 mWave_FDS.bEnvelopeEnable = 0;
2991 mWave_FDS.nEnvelopeSpeed = 0xFF;
2992 mWave_FDS.nVolEnv_Mode = 2;
2993 mWave_FDS.nVolEnv_Decay = 0;
2994 mWave_FDS.nVolEnv_Gain = 0;
2995 mWave_FDS.nVolume = 0;
2996 mWave_FDS.bVolEnv_On = 0;
2997 mWave_FDS.nSweep_Mode = 2;
2998 mWave_FDS.nSweep_Decay = 0;
2999 mWave_FDS.nSweep_Gain = 0;
3000 mWave_FDS.bSweepEnv_On = 0;
3001 mWave_FDS.nSweepBias = 0;
3002 mWave_FDS.bLFO_Enabled = 0;
3003 mWave_FDS.nLFO_Freq.W = 0;
3004 /* mWave_FDS.fLFO_Timer = 0;
3005 mWave_FDS.fLFO_Count = 0;*/
3006 mWave_FDS.nLFO_Timer = 0;
3007 mWave_FDS.nLFO_Count = 0;
3008 mWave_FDS.nLFO_Addr = 0;
3009 mWave_FDS.bLFO_On = 0;
3010 mWave_FDS.nMainVolume = 0;
3011 mWave_FDS.bEnabled = 0;
3012 mWave_FDS.nFreq.W = 0;
3013 /* mWave_FDS.fFreqCount = 0;*/
3014 mWave_FDS.nFreqCount = 0;
3015 mWave_FDS.nMainAddr = 0;
3016 mWave_FDS.bWaveWrite = 0;
3017 mWave_FDS.bMain_On = 0;
3018 mWave_FDS.nMixL = 0;
3019 ZEROMEMORY(mWave_FDS.nWaveTable,0x40);
3020 ZEROMEMORY(mWave_FDS.nLFO_Table,0x40);
3022 mWave_FDS.nSweep_Count = mWave_FDS.nSweep_Timer =
3023 ((mWave_FDS.nSweep_Decay + 1) * mWave_FDS.nEnvelopeSpeed * 8);
3024 mWave_FDS.nVolEnv_Count = mWave_FDS.nVolEnv_Timer =
3025 ((mWave_FDS.nVolEnv_Decay + 1) * mWave_FDS.nEnvelopeSpeed * 8);
3027 nSilentSamples = 0;
3029 nFilterAccL = 0;
3031 nSilentSamples = 0;
3033 fulltick=0;
3037 * SetPlaybackOptions
3040 int SetPlaybackOptions(int32_t samplerate)
3042 if(samplerate < 2000) return 0;
3043 if(samplerate > 96000) return 0;
3045 nTicksPerSample =
3046 (bPALMode ? PAL_FREQUENCY : NTSC_FREQUENCY) / samplerate * 0x10000;
3047 nTicksUntilNextSample = nTicksPerSample;
3049 RecalcFilter();
3050 RecalcSilenceTracker();
3052 return 1;
3056 * SetPlaybackSpeed
3059 void SetPlaybackSpeed(float playspersec)
3061 if(playspersec < 1)
3063 playspersec = fNSFPlaybackSpeed;
3066 nTicksPerPlay = nTicksUntilNextPlay =
3067 (bPALMode ? PAL_FREQUENCY : NTSC_FREQUENCY) / playspersec * 0x10000;
3071 * GetPlaybackSpeed
3074 float GetPlaybackSpeed()
3076 if(nTicksPerPlay <= 0) return 0;
3077 return ((bPALMode ? PAL_FREQUENCY : NTSC_FREQUENCY) / (nTicksPerPlay>>16));
3081 * RecalcFilter
3084 void RecalcFilter()
3086 if(!nSampleRate) return;
3088 nHighPass = ((int64_t)nHighPassBase << 16) / nSampleRate;
3090 if(nHighPass > (1<<16)) nHighPass = 1<<16;
3094 * RecalcSilenceTracker
3097 void RecalcSilenceTracker()
3099 if(nSilenceTrackMS <= 0 || !nSampleRate ||
3100 (bNoSilenceIfTime && bTimeNotDefault))
3102 nSilentSampleMax = 0;
3103 return;
3106 nSilentSampleMax = nSilenceTrackMS * nSampleRate / 500;
3107 nSilentSampleMax /= 2;
3110 void RebuildOutputTables(void) {
3111 int32_t i,j;
3112 float l[3];
3113 int32_t temp;
3114 float ftemp;
3116 /* tnd */
3117 for(i = 0; i < 3; i++)
3119 l[i] = 255;
3122 for(i = 0; i < 0x8000; i++)
3124 ftemp = (l[0] * (i >> 11)) / 2097885;
3125 ftemp += (l[1] * ((i >> 7) & 0x0F)) / 3121455;
3126 ftemp += (l[2] * (i & 0x7F)) / 5772690;
3128 if(!ftemp)
3129 main_nOutputTable_L[i] = 0;
3130 else
3131 main_nOutputTable_L[i] =
3132 (int16_t)(2396850 / ((1.0f / ftemp) + 100));
3135 /* squares */
3136 for(i = 0; i < 2; i++)
3138 l[i] = 255;
3141 for(j = 0; j < 0x10; j++)
3143 for(i = 0; i < 0x10; i++)
3145 temp = (int32_t)(l[0] * j);
3146 temp += (int32_t)(l[1] * i);
3148 if(!temp)
3149 Squares_nOutputTable_L[j][i] = 0;
3150 else
3151 Squares_nOutputTable_L[j][i] = 1438200 / ((2072640 / temp) + 100);
3155 /* VRC6 Pulse 1,2 */
3156 for(i = 0; i < 0x10; i++)
3158 VRC6Pulse_nOutputTable_L[i] =
3159 1875 * i / 0x0F;
3161 /* VRC6 Saw */
3162 for(i = 0; i < 0x20; i++)
3164 VRC6Saw_nOutputTable_L[i] = 3750 * i / 0x1F;
3167 /* N106 channels */
3168 /* this amplitude is just a guess */
3170 for(i = 0; i < 0x10; i++)
3172 for(j = 0; j < 0x10; j++)
3174 N106_nOutputTable_L[i][j] = (3000 * i * j) / 0xE1;
3178 /* FME-07 Square A,B,C */
3179 FME07_nOutputTable_L[15] = 3000;
3180 FME07_nOutputTable_L[0] = 0;
3181 for(i = 14; i > 0; i--)
3183 FME07_nOutputTable_L[i] = FME07_nOutputTable_L[i + 1] * 80 / 100;
3187 * FDS
3189 /* this base volume (4000) is just a guess to what sounds right.
3190 * Given the number of steps available in an FDS wave... it seems like
3191 * it should be much much more... but then it's TOO loud.
3193 for(i = 0; i < 0x21; i++)
3195 for(j = 0; j < 0x40; j++)
3197 FDS_nOutputTable_L[0][i][j] =
3198 (4000 * i * j * 30) / (0x21 * 0x40 * 30);
3199 FDS_nOutputTable_L[1][i][j] =
3200 (4000 * i * j * 20) / (0x21 * 0x40 * 30);
3201 FDS_nOutputTable_L[2][i][j] =
3202 (4000 * i * j * 15) / (0x21 * 0x40 * 30);
3203 FDS_nOutputTable_L[3][i][j] =
3204 (4000 * i * j * 12) / (0x21 * 0x40 * 30);
3210 * GetPlayCalls
3213 float GetPlayCalls()
3215 if(!nTicksPerPlay) return 0;
3217 return ((float)nTotalPlays) +
3218 (1.0f - (nTicksUntilNextPlay*1.0f / nTicksPerPlay));
3222 * GetWrittenTime
3224 uint32_t GetWrittenTime(float basedplayspersec /* = 0 */)
3226 if(basedplayspersec <= 0)
3227 basedplayspersec = GetPlaybackSpeed();
3229 if(basedplayspersec <= 0)
3230 return 0;
3232 return (uint32_t)((GetPlayCalls() * 1000) / basedplayspersec);
3236 * StopFade
3238 void StopFade()
3240 bFade = 0;
3241 fFadeVolume = 1;
3245 * SongCompleted
3248 uint8_t SongCompleted()
3250 if(!bFade) return 0;
3251 if(nTotalPlays >= nEndFade) return 1;
3252 if(nSilentSampleMax) return (nSilentSamples >= nSilentSampleMax);
3254 return 0;
3258 * SetFade
3261 void SetFade(int32_t fadestart,int32_t fadestop,
3262 uint8_t bNotDefault) /* play routine calls */
3264 if(fadestart < 0) fadestart = 0;
3265 if(fadestop < fadestart) fadestop = fadestart;
3267 nStartFade = (uint32_t)fadestart;
3268 nEndFade = (uint32_t)fadestop;
3269 bFade = 1;
3270 bTimeNotDefault = bNotDefault;
3272 RecalcSilenceTracker();
3273 RecalculateFade();
3277 * SetFadeTime
3280 void SetFadeTime(uint32_t fadestart,uint32_t fadestop,float basedplays,
3281 uint8_t bNotDefault) /* time in MS */
3283 if(basedplays <= 0)
3284 basedplays = GetPlaybackSpeed();
3285 if(basedplays <= 0)
3286 return;
3288 SetFade((int32_t)(fadestart * basedplays / 1000),
3289 (int32_t)(fadestop * basedplays / 1000),bNotDefault);
3293 * RecalculateFade
3296 void RecalculateFade()
3298 if(!bFade) return;
3300 /* make it hit silence a little before the song ends...
3301 otherwise we're not really fading OUT, we're just fading umm...
3302 quieter =P */
3303 int32_t temp = (int32_t)(GetPlaybackSpeed() / 4);
3305 if(nEndFade <= nStartFade)
3307 nEndFade = nStartFade;
3308 fFadeChange = 1.0f;
3310 else if((nEndFade - temp) <= nStartFade)
3311 fFadeChange = 1.0f;
3312 else
3313 fFadeChange = 1.0f / (nEndFade - nStartFade - temp);
3315 if(nTotalPlays < nStartFade)
3316 fFadeVolume = 1.0f;
3317 else if(nTotalPlays >= nEndFade)
3318 fFadeVolume = 0.0f;
3319 else
3321 fFadeVolume = 1.0f - ( (nTotalPlays - nStartFade + 1) * fFadeChange );
3322 if(fFadeVolume < 0)
3323 fFadeVolume = 0;
3328 int32_t GetSamples(uint8_t* buffer,int32_t buffersize)
3330 if(!buffer) return 0;
3331 if(buffersize < 16) return 0;
3332 if(bFade && (nTotalPlays >= nEndFade)) return 0;
3334 pOutput = buffer;
3335 uint32_t runtocycle =
3336 (uint32_t)((buffersize / 2) * nTicksPerSample / 0x10000);
3337 nCPUCycle = nAPUCycle = 0;
3338 uint32_t tick;
3340 while(1)
3342 /*tick = (uint32_t)ceil(fTicksUntilNextPlay);*/
3343 tick = (nTicksUntilNextPlay+0xffff)>>16;
3344 if((tick + nCPUCycle) > runtocycle)
3345 tick = runtocycle - nCPUCycle;
3347 if(bCPUJammed)
3349 nCPUCycle += tick;
3350 EmulateAPU(0);
3352 else
3354 tick = Emulate6502(tick + nCPUCycle);
3355 EmulateAPU(1);
3358 nTicksUntilNextPlay -= tick<<16;
3359 if(nTicksUntilNextPlay <= 0)
3361 nTicksUntilNextPlay += nTicksPerPlay;
3362 if((bCPUJammed == 2) || bNoWaitForReturn)
3364 regX = regY = regA = (bCleanAXY ? 0 : 0xCD);
3365 regPC = 0x5004;
3366 nTotalPlays++;
3367 bDMCPop_SamePlay = 0;
3368 bCPUJammed = 0;
3369 if(nForce4017Write == 1) WriteMemory_pAPU(0x4017,0x00);
3370 if(nForce4017Write == 2) WriteMemory_pAPU(0x4017,0x80);
3373 if(bFade && (nTotalPlays >= nStartFade))
3375 fFadeVolume -= fFadeChange;
3376 if(fFadeVolume < 0)
3377 fFadeVolume = 0;
3378 if(nTotalPlays >= nEndFade)
3379 break;
3383 if(nCPUCycle >= runtocycle)
3384 break;
3387 nCPUCycle = nAPUCycle = 0;
3389 if(nSilentSampleMax && bFade)
3391 int16_t* tempbuf = (int16_t*)buffer;
3392 while( ((uint8_t*)tempbuf) < pOutput)
3394 if( (*tempbuf < -SILENCE_THRESHOLD) ||
3395 (*tempbuf > SILENCE_THRESHOLD) )
3396 nSilentSamples = 0;
3397 else
3399 if(++nSilentSamples >= nSilentSampleMax)
3400 return (int32_t)( ((uint8_t*)tempbuf) - buffer);
3402 tempbuf++;
3406 return (int32_t)(pOutput - buffer);
3409 /****************** 6502 emulation ******************/
3411 /* Memory reading/writing and other defines */
3413 /* reads zero page memory */
3414 #define Zp(a) pRAM[a]
3415 /* reads zero page memory in word form */
3416 #define ZpWord(a) (Zp(a) | (Zp((uint8_t)(a + 1)) << 8))
3417 /* reads memory */
3418 #define Rd(a) ((ReadMemory[((uint16_t)(a)) >> 12])(a))
3419 /* reads memory in word form */
3420 #define RdWord(a) (Rd(a) | (Rd(a + 1) << 8))
3421 /* writes memory */
3422 #define Wr(a,v) (WriteMemory[((uint16_t)(a)) >> 12])(a,v)
3423 /* writes zero paged memory */
3424 #define WrZ(a,v) pRAM[a] = v
3425 /* pushes a value onto the stack */
3426 #define PUSH(v) pStack[SP--] = v
3427 /* pulls a value from the stack */
3428 #define PULL(v) v = pStack[++SP]
3430 /* Addressing Modes */
3432 /* first set - gets the value that's being addressed */
3433 /*Immediate*/
3434 #define Ad_VlIm() val = Rd(PC.W); PC.W++
3435 /*Zero Page*/
3436 #define Ad_VlZp() final.W = Rd(PC.W); val = Zp(final.W); PC.W++
3437 /*Zero Page, X*/
3438 #define Ad_VlZx() front.W = final.W = Rd(PC.W); final.B.l += X; \
3439 val = Zp(final.B.l); PC.W++
3440 /*Zero Page, Y*/
3441 #define Ad_VlZy() front.W = final.W = Rd(PC.W); final.B.l += Y; \
3442 val = Zp(final.B.l); PC.W++
3443 /*Absolute*/
3444 #define Ad_VlAb() final.W = RdWord(PC.W); val = Rd(final.W); PC.W += 2
3445 /*Absolute, X [uses extra cycle if crossed page]*/
3446 #define Ad_VlAx() front.W = final.W = RdWord(PC.W); final.W += X; PC.W += 2;\
3447 if(front.B.h != final.B.h) nCPUCycle++; val = Rd(final.W)
3448 /*Absolute, X [uses extra cycle if crossed page]*/
3449 #define Ad_VlAy() front.W = final.W = RdWord(PC.W); final.W += Y; PC.W += 2;\
3450 if(front.B.h != final.B.h) nCPUCycle++; val = Rd(final.W)
3451 /*(Indirect, X)*/
3452 #define Ad_VlIx() front.W = final.W = Rd(PC.W); final.B.l += X; PC.W++; \
3453 final.W = ZpWord(final.B.l); val = Rd(final.W)
3454 /*(Indirect), Y [uses extra cycle if crossed page]*/
3455 #define Ad_VlIy() val = Rd(PC.W); front.W = final.W = ZpWord(val); PC.W++;\
3456 final.W += Y; if(final.B.h != front.B.h) nCPUCycle++; \
3457 front.W = val; val = Rd(final.W)
3459 /* second set - gets the ADDRESS that the mode is referring to (for operators
3460 * that write to memory) note that AbsoluteX, AbsoluteY, and
3461 * IndirectY modes do NOT check for page boundary crossing here
3462 * since that extra cycle isn't added for operators that write to
3463 * memory (it only applies to ones that only read from memory.. in
3464 * which case the 1st set should be used)
3466 /*Zero Page*/
3467 #define Ad_AdZp() final.W = Rd(PC.W); PC.W++
3468 /*Zero Page, X*/
3469 #define Ad_AdZx() final.W = front.W = Rd(PC.W); final.B.l += X; PC.W++
3470 /*Zero Page, Y*/
3471 #define Ad_AdZy() final.W = front.W = Rd(PC.W); final.B.l += Y; PC.W++
3472 /*Absolute*/
3473 #define Ad_AdAb() final.W = RdWord(PC.W); PC.W += 2
3474 /*Absolute, X*/
3475 #define Ad_AdAx() front.W = final.W = RdWord(PC.W); PC.W += 2; \
3476 final.W += X
3477 /*Absolute, Y*/
3478 #define Ad_AdAy() front.W = final.W = RdWord(PC.W); PC.W += 2; \
3479 final.W += Y
3480 /*(Indirect, X)*/
3481 #define Ad_AdIx() front.W = final.W = Rd(PC.W); PC.W++; final.B.l += X; \
3482 final.W = ZpWord(final.B.l)
3483 /*(Indirect), Y*/
3484 #define Ad_AdIy() front.W = Rd(PC.W); final.W = ZpWord(front.W) + Y; \
3485 PC.W++
3487 /* third set - reads memory, performs the desired operation on the value, then
3488 * writes back to memory
3489 * used for operators that directly change memory (ASL, INC, DEC, etc)
3491 /*Zero Page*/
3492 #define MRW_Zp(cmd) Ad_AdZp(); val = Zp(final.W); cmd(val); WrZ(final.W,val)
3493 /*Zero Page, X*/
3494 #define MRW_Zx(cmd) Ad_AdZx(); val = Zp(final.W); cmd(val); WrZ(final.W,val)
3495 /*Zero Page, Y*/
3496 #define MRW_Zy(cmd) Ad_AdZy(); val = Zp(final.W); cmd(val); WrZ(final.W,val)
3497 /*Absolute*/
3498 #define MRW_Ab(cmd) Ad_AdAb(); val = Rd(final.W); cmd(val); Wr(final.W,val)
3499 /*Absolute, X*/
3500 #define MRW_Ax(cmd) Ad_AdAx(); val = Rd(final.W); cmd(val); Wr(final.W,val)
3501 /*Absolute, Y*/
3502 #define MRW_Ay(cmd) Ad_AdAy(); val = Rd(final.W); cmd(val); Wr(final.W,val)
3503 /*(Indirect, X)*/
3504 #define MRW_Ix(cmd) Ad_AdIx(); val = Rd(final.W); cmd(val); Wr(final.W,val)
3505 /*(Indirect), Y*/
3506 #define MRW_Iy(cmd) Ad_AdIy(); val = Rd(final.W); cmd(val); Wr(final.W,val)
3508 /* Relative modes are special in that they're only used by branch commands
3509 * this macro handles the jump, and should only be called if the branch
3510 * condition was true if the branch condition was false, the PC must be
3511 * incremented
3514 #define RelJmp(cond) val = Rd(PC.W); PC.W++; final.W = PC.W + (int8_t)(val);\
3515 if(cond) {\
3516 nCPUCycle += ((final.B.h != PC.B.h) ? 2 : 1);\
3517 PC.W = final.W; }
3519 /* Status Flags */
3521 #define C_FLAG 0x01 /* carry flag */
3522 #define Z_FLAG 0x02 /* zero flag */
3523 #define I_FLAG 0x04 /* mask interrupt flag */
3524 #define D_FLAG 0x08 /* decimal flag (decimal mode is unsupported on
3525 NES) */
3526 #define B_FLAG 0x10 /* break flag (not really in the status register
3527 It's value in ST is never used. When ST is
3528 put in memory (by an interrupt or PHP), this
3529 flag is set only if BRK was called)
3530 ** also when PHP is called due to a bug */
3531 #define R_FLAG 0x20 /* reserved flag (not really in the register.
3532 It's value is never used.
3533 Whenever ST is put in memory,
3534 this flag is always set) */
3535 #define V_FLAG 0x40 /* overflow flag */
3536 #define N_FLAG 0x80 /* sign flag */
3539 /* Lookup Tables */
3541 /* the number of CPU cycles used for each instruction */
3542 static const uint8_t CPU_Cycles[0x100] = {
3543 7,6,0,8,3,3,5,5,3,2,2,2,4,4,6,6,
3544 2,5,0,8,4,4,6,6,2,4,2,7,4,4,7,7,
3545 6,6,0,8,3,3,5,5,4,2,2,2,4,4,6,6,
3546 2,5,0,8,4,4,6,6,2,4,2,7,4,4,7,7,
3547 6,6,0,8,3,3,5,5,3,2,2,2,3,4,6,6,
3548 2,5,0,8,4,4,6,6,2,4,2,7,4,4,7,7,
3549 6,6,0,8,3,3,5,5,4,2,2,2,5,4,6,6,
3550 2,5,0,8,4,4,6,6,2,4,2,7,4,4,7,7,
3551 2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4,
3552 2,6,0,6,4,4,4,4,2,5,2,5,5,5,5,5,
3553 2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4,
3554 2,5,0,5,4,4,4,4,2,4,2,4,4,4,4,4,
3555 2,6,2,8,3,3,5,5,2,2,2,2,4,4,6,6,
3556 2,5,0,8,4,4,6,6,2,4,2,7,4,4,7,7,
3557 2,6,2,8,3,3,5,5,2,2,2,2,4,4,6,6,
3558 2,5,0,8,4,4,6,6,2,4,2,7,4,4,7,7 };
3560 /* the status of the NZ flags for the given value */
3561 static const uint8_t NZTable[0x100] = {
3562 Z_FLAG,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
3563 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
3564 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
3565 0,0,0,0,0,0,0,0,0,0,0,
3566 N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,
3567 N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,
3568 N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,
3569 N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,
3570 N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,
3571 N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,
3572 N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,
3573 N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,
3574 N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,
3575 N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,
3576 N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,
3577 N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG };
3579 /* A quick macro for working with the above table */
3580 #define UpdateNZ(v) ST = (ST & ~(N_FLAG|Z_FLAG)) | NZTable[v]
3584 * Opcodes
3586 * These opcodes perform the action with the given value (changing that
3587 * value if necessary). Registers and flags associated with the operation
3588 * are changed accordingly. There are a few exceptions which will be noted
3589 * when they arise
3593 /* ADC
3594 Adds the value to the accumulator with carry
3595 Changes: A, NVZC
3596 - Decimal mode not supported on the NES
3597 - Due to a bug, NVZ flags are not altered if the Decimal flag is on
3598 --(taken out)-- */
3599 #define ADC() \
3600 tw.W = A + val + (ST & C_FLAG); \
3601 ST = (ST & (I_FLAG|D_FLAG)) | tw.B.h | NZTable[tw.B.l] | \
3602 ( (0x80 & ~(A ^ val) & (A ^ tw.B.l)) ? V_FLAG : 0 ); \
3603 A = tw.B.l
3605 /* AND
3606 Combines the value with the accumulator using a bitwise AND operation
3607 Changes: A, NZ */
3608 #define AND() \
3609 A &= val; \
3610 UpdateNZ(A)
3612 /* ASL
3613 Left shifts the value 1 bit. The bit that gets shifted out goes to
3614 the carry flag.
3615 Changes: value, NZC */
3616 #define ASL(value) \
3617 tw.W = value << 1; \
3618 ST = (ST & ~(N_FLAG|Z_FLAG|C_FLAG)) | tw.B.h | NZTable[tw.B.l]; \
3619 value = tw.B.l
3621 /* BIT
3622 Compares memory with the accumulator with an AND operation, but changes
3623 neither.
3624 The two high bits of memory get transferred to the status reg
3625 Z is set if the AND operation yielded zero, otherwise it's cleared
3626 Changes: NVZ */
3627 #define BIT() \
3628 ST = (ST & ~(N_FLAG|V_FLAG|Z_FLAG)) | (val & (N_FLAG|V_FLAG)) | \
3629 ((A & val) ? 0 : Z_FLAG)
3631 /* CMP, CPX, CPY
3632 Compares memory with the given register with a subtraction operation.
3633 Flags are set accordingly depending on the result:
3634 Reg < Memory: Z=0, C=0
3635 Reg = Memory: Z=1, C=1
3636 Reg > Memory: Z=0, C=1
3637 N is set according to the result of the subtraction operation
3638 Changes: NZC
3640 NOTE -- CMP, CPX, CPY all share this same routine, so the desired
3641 register (A, X, or Y respectively) must be given when calling
3642 this macro... as well as the memory to compare it with. */
3643 #define CMP(reg) \
3644 tw.W = reg - val; \
3645 ST = (ST & ~(N_FLAG|Z_FLAG|C_FLAG)) | (tw.B.h ? 0 : C_FLAG) | \
3646 NZTable[tw.B.l]
3648 /* DEC, DEX, DEY
3649 Decriments a value by one.
3650 Changes: value, NZ */
3651 #define DEC(value) \
3652 value--; \
3653 UpdateNZ(value)
3655 /* EOR
3656 Combines a value with the accumulator using a bitwise exclusive-OR
3657 operation
3658 Changes: A, NZ */
3659 #define EOR() \
3660 A ^= val; \
3661 UpdateNZ(A)
3663 /* INC, INX, INY
3664 Incriments a value by one.
3665 Changes: value, NZ */
3666 #define INC(value) \
3667 value++; \
3668 UpdateNZ(value)
3670 /* LSR
3671 Shifts value one bit to the right. Bit that gets shifted out goes to
3672 the Carry flag.
3673 Changes: value, NZC */
3674 #define LSR(value) \
3675 tw.W = value >> 1; \
3676 ST = (ST & ~(N_FLAG|Z_FLAG|C_FLAG)) | NZTable[tw.B.l] | \
3677 (value & 0x01); \
3678 value = tw.B.l
3680 /* ORA
3681 Combines a value with the accumulator using a bitwise inclusive-OR
3682 operation
3683 Changes: A, NZ */
3684 #define ORA() \
3685 A |= val; \
3686 UpdateNZ(A)
3688 /* ROL
3689 Rotates a value one bit to the left:
3690 C <- 7<-6<-5<-4<-3<-2<-1<-0 <- C
3691 Changes: value, NZC */
3692 #define ROL(value) \
3693 tw.W = (value << 1) | (ST & 0x01); \
3694 ST = (ST & ~(N_FLAG|Z_FLAG|C_FLAG)) | NZTable[tw.B.l] | tw.B.h; \
3695 value = tw.B.l
3697 /* ROR
3698 Rotates a value one bit to the right:
3699 C -> 7->6->5->4->3->2->1->0 -> C
3700 Changes: value, NZC */
3701 #define ROR(value) \
3702 tw.W = (value >> 1) | (ST << 7); \
3703 ST = (ST & ~(N_FLAG|Z_FLAG|C_FLAG)) | NZTable[tw.B.l] | \
3704 (value & 0x01); \
3705 value = tw.B.l
3707 /* SBC
3708 Subtracts a value from the accumulator with borrow (inverted carry)
3709 Changes: A, NVZC
3710 - Decimal mode not supported on the NES
3711 - Due to a bug, NVZ flags are not altered if the Decimal flag is on
3712 --(taken out)-- */
3713 #define SBC() \
3714 tw.W = A - val - ((ST & C_FLAG) ? 0 : 1); \
3715 ST = (ST & (I_FLAG|D_FLAG)) | (tw.B.h ? 0 : C_FLAG) | NZTable[tw.B.l] | \
3716 (((A ^ val) & (A ^ tw.B.l) & 0x80) ? V_FLAG : 0); \
3717 A = tw.B.l
3719 /* Undocumented Opcodes
3721 * These opcodes are not included in the official specifications. However,
3722 * some of the unused opcode values perform operations which have since been
3723 * documented.
3727 /* ASO
3728 Left shifts a value, then ORs the result with the accumulator
3729 Changes: value, A, NZC */
3730 #define ASO(value) \
3731 tw.W = value << 1; \
3732 A |= tw.B.l; \
3733 ST = (ST & ~(N_FLAG|Z_FLAG|C_FLAG)) | NZTable[A] | tw.B.h; \
3734 value = tw.B.l
3736 /* RLA
3737 Roll memory left 1 bit, then AND the result with the accumulator
3738 Changes: value, A, NZC */
3739 #define RLA(value) \
3740 tw.W = (value << 1) | (ST & 0x01); \
3741 A &= tw.B.l; \
3742 ST = (ST & ~(N_FLAG|Z_FLAG|C_FLAG)) | NZTable[A] | tw.B.h; \
3743 value = tw.B.l
3745 /* LSE
3746 Right shifts a value one bit, then EORs the result with the accumulator
3747 Changes: value, A, NZC */
3748 #define LSE(value) \
3749 tw.W = value >> 1; \
3750 A ^= tw.B.l; \
3751 ST = (ST & ~(N_FLAG|Z_FLAG|C_FLAG)) | NZTable[A] | (value & 0x01); \
3752 value = tw.B.l
3754 /* RRA
3755 Roll memory right one bit, then ADC the result
3756 Changes: value, A, NVZC */
3757 #define RRA(value) \
3758 tw.W = (value >> 1) | (ST << 7); \
3759 ST = (ST & ~C_FLAG) | (value & 0x01); \
3760 value = tw.B.l; \
3761 ADC()
3763 /* AXS
3764 ANDs the contents of the X and A registers and stores the result
3765 int memory.
3766 Changes: value [DOES NOT CHANGE X, A, or any flags] */
3767 #define AXS(value) \
3768 value = A & X
3770 /* DCM
3771 Decriments a value and compares it with the A register.
3772 Changes: value, NZC */
3773 #define DCM(value) \
3774 value--; \
3775 CMP(A)
3777 /* INS
3778 Incriments a value then SBCs it
3779 Changes: value, A, NVZC */
3780 #define INS(value) \
3781 value++; \
3782 SBC()
3784 /* AXA */
3785 #define AXA(value) \
3786 value = A & X & (Rd(PC.W - 1) + 1)
3789 /* The 6502 emulation function! */
3791 union TWIN front;
3792 union TWIN final;
3793 uint8_t val;
3794 uint8_t op;
3796 uint32_t Emulate6502(uint32_t runto)
3798 /* If the CPU is jammed... don't bother */
3799 if(bCPUJammed == 1)
3800 return 0;
3802 register union TWIN tw; /* used in calculations */
3803 register uint8_t ST = regP;
3804 register union TWIN PC;
3805 uint8_t SP = regSP;
3806 register uint8_t A = regA;
3807 register uint8_t X = regX;
3808 register uint8_t Y = regY;
3809 union TWIN front;
3810 union TWIN final;
3811 PC.W = regPC;
3813 uint32_t ret = nCPUCycle;
3815 ENTER_TIMER(cpu);
3817 /* Start the loop */
3819 while(nCPUCycle < runto)
3821 op = Rd(PC.W);
3822 PC.W++;
3824 nCPUCycle += CPU_Cycles[op];
3825 switch(op)
3827 /* Documented Opcodes first */
3829 /* Flag setting/clearing */
3830 case 0x18: ST &= ~C_FLAG; break; /* CLC */
3831 case 0x38: ST |= C_FLAG; break; /* SEC */
3832 case 0x58: ST &= ~I_FLAG; break; /* CLI */
3833 case 0x78: ST |= I_FLAG; break; /* SEI */
3834 case 0xB8: ST &= ~V_FLAG; break; /* CLV */
3835 case 0xD8: ST &= ~D_FLAG; break; /* CLD */
3836 case 0xF8: ST |= D_FLAG; break; /* SED */
3838 /* Branch commands */
3839 case 0x10: RelJmp(!(ST & N_FLAG)); break; /* BPL */
3840 case 0x30: RelJmp( (ST & N_FLAG)); break; /* BMI */
3841 case 0x50: RelJmp(!(ST & V_FLAG)); break; /* BVC */
3842 case 0x70: RelJmp( (ST & V_FLAG)); break; /* BVS */
3843 case 0x90: RelJmp(!(ST & C_FLAG)); break; /* BCC */
3844 case 0xB0: RelJmp( (ST & C_FLAG)); break; /* BCS */
3845 case 0xD0: RelJmp(!(ST & Z_FLAG)); break; /* BNE */
3846 case 0xF0: RelJmp( (ST & Z_FLAG)); break; /* BEQ */
3848 /* Direct stack alteration commands (push/pull commands) */
3849 case 0x08: PUSH(ST | R_FLAG | B_FLAG); break; /* PHP */
3850 case 0x28: PULL(ST); break; /* PLP */
3851 case 0x48: PUSH(A); break; /* PHA */
3852 case 0x68: PULL(A); UpdateNZ(A); break; /* PLA */
3854 /* Register Transfers */
3855 case 0x8A: A = X; UpdateNZ(A); break; /* TXA */
3856 case 0x98: A = Y; UpdateNZ(A); break; /* TYA */
3857 case 0x9A: SP = X; break; /* TXS */
3858 case 0xA8: Y = A; UpdateNZ(A); break; /* TAY */
3859 case 0xAA: X = A; UpdateNZ(A); break; /* TAX */
3860 case 0xBA: X = SP; UpdateNZ(X); break; /* TSX */
3862 /* Other commands */
3864 /* ADC */
3865 case 0x61: Ad_VlIx(); ADC(); break;
3866 case 0x65: Ad_VlZp(); ADC(); break;
3867 case 0x69: Ad_VlIm(); ADC(); break;
3868 case 0x6D: Ad_VlAb(); ADC(); break;
3869 case 0x71: Ad_VlIy(); ADC(); break;
3870 case 0x75: Ad_VlZx(); ADC(); break;
3871 case 0x79: Ad_VlAy(); ADC(); break;
3872 case 0x7D: Ad_VlAx(); ADC(); break;
3874 /* AND */
3875 case 0x21: Ad_VlIx(); AND(); break;
3876 case 0x25: Ad_VlZp(); AND(); break;
3877 case 0x29: Ad_VlIm(); AND(); break;
3878 case 0x2D: Ad_VlAb(); AND(); break;
3879 case 0x31: Ad_VlIy(); AND(); break;
3880 case 0x35: Ad_VlZx(); AND(); break;
3881 case 0x39: Ad_VlAy(); AND(); break;
3882 case 0x3D: Ad_VlAx(); AND(); break;
3884 /* ASL */
3885 case 0x0A: ASL(A); break;
3886 case 0x06: MRW_Zp(ASL); break;
3887 case 0x0E: MRW_Ab(ASL); break;
3888 case 0x16: MRW_Zx(ASL); break;
3889 case 0x1E: MRW_Ax(ASL); break;
3891 /* BIT */
3892 case 0x24: Ad_VlZp(); BIT(); break;
3893 case 0x2C: Ad_VlAb(); BIT(); break;
3895 /* BRK */
3896 case 0x00:
3897 if(bIgnoreBRK)
3898 break;
3899 PC.W++; /*BRK has a padding byte*/
3900 PUSH(PC.B.h); /*push high byte of the return address*/
3901 PUSH(PC.B.l); /*push low byte of return address*/
3902 PUSH(ST | R_FLAG | B_FLAG); /*push processor status with R|B flags*/
3903 ST |= I_FLAG; /*mask interrupts*/
3904 PC.W = RdWord(0xFFFE); /*read the IRQ vector and jump to it*/
3906 /* extra check to make sure we didn't hit an infinite BRK loop */
3907 if(!Rd(PC.W)) /* next command will be BRK */
3909 /* the CPU will endlessly loop...
3910 just jam it to ease processing power */
3911 bCPUJammed = 1;
3912 goto jammed;
3914 break;
3916 /* CMP */
3917 case 0xC1: Ad_VlIx(); CMP(A); break;
3918 case 0xC5: Ad_VlZp(); CMP(A); break;
3919 case 0xC9: Ad_VlIm(); CMP(A); break;
3920 case 0xCD: Ad_VlAb(); CMP(A); break;
3921 case 0xD1: Ad_VlIy(); CMP(A); break;
3922 case 0xD5: Ad_VlZx(); CMP(A); break;
3923 case 0xD9: Ad_VlAy(); CMP(A); break;
3924 case 0xDD: Ad_VlAx(); CMP(A); break;
3926 /* CPX */
3927 case 0xE0: Ad_VlIm(); CMP(X); break;
3928 case 0xE4: Ad_VlZp(); CMP(X); break;
3929 case 0xEC: Ad_VlAb(); CMP(X); break;
3931 /* CPY */
3932 case 0xC0: Ad_VlIm(); CMP(Y); break;
3933 case 0xC4: Ad_VlZp(); CMP(Y); break;
3934 case 0xCC: Ad_VlAb(); CMP(Y); break;
3936 /* DEC */
3937 case 0xCA: DEC(X); break; /* DEX */
3938 case 0x88: DEC(Y); break; /* DEY */
3939 case 0xC6: MRW_Zp(DEC); break;
3940 case 0xCE: MRW_Ab(DEC); break;
3941 case 0xD6: MRW_Zx(DEC); break;
3942 case 0xDE: MRW_Ax(DEC); break;
3944 /* EOR */
3945 case 0x41: Ad_VlIx(); EOR(); break;
3946 case 0x45: Ad_VlZp(); EOR(); break;
3947 case 0x49: Ad_VlIm(); EOR(); break;
3948 case 0x4D: Ad_VlAb(); EOR(); break;
3949 case 0x51: Ad_VlIy(); EOR(); break;
3950 case 0x55: Ad_VlZx(); EOR(); break;
3951 case 0x59: Ad_VlAy(); EOR(); break;
3952 case 0x5D: Ad_VlAx(); EOR(); break;
3954 /* INC */
3955 case 0xE8: INC(X); break; /* INX */
3956 case 0xC8: INC(Y); break; /* INY */
3957 case 0xE6: MRW_Zp(INC); break;
3958 case 0xEE: MRW_Ab(INC); break;
3959 case 0xF6: MRW_Zx(INC); break;
3960 case 0xFE: MRW_Ax(INC); break;
3962 /* JMP */
3963 /* Absolute JMP */
3964 case 0x4C: final.W = RdWord(PC.W); PC.W = final.W; val = 0; break;
3965 /* Indirect JMP -- must take caution:
3966 Indirection at 01FF will read from 01FF and 0100 (not 0200) */
3967 case 0x6C: front.W = final.W = RdWord(PC.W);
3968 PC.B.l = Rd(final.W); final.B.l++;
3969 PC.B.h = Rd(final.W); final.W = PC.W;
3970 break;
3971 /* JSR */
3972 case 0x20:
3973 val = 0;
3974 final.W = RdWord(PC.W);
3975 PC.W++; /* JSR only increments the return address by one.
3976 It's incremented again upon RTS */
3977 PUSH(PC.B.h); /* push high byte of return address */
3978 PUSH(PC.B.l); /* push low byte of return address */
3979 PC.W = final.W;
3980 break;
3982 /* LDA */
3983 case 0xA1: Ad_VlIx(); A = val; UpdateNZ(A); break;
3984 case 0xA5: Ad_VlZp(); A = val; UpdateNZ(A); break;
3985 case 0xA9: Ad_VlIm(); A = val; UpdateNZ(A); break;
3986 case 0xAD: Ad_VlAb(); A = val; UpdateNZ(A); break;
3987 case 0xB1: Ad_VlIy(); A = val; UpdateNZ(A); break;
3988 case 0xB5: Ad_VlZx(); A = val; UpdateNZ(A); break;
3989 case 0xB9: Ad_VlAy(); A = val; UpdateNZ(A); break;
3990 case 0xBD: Ad_VlAx(); A = val; UpdateNZ(A); break;
3992 /* LDX */
3993 case 0xA2: Ad_VlIm(); X = val; UpdateNZ(X); break;
3994 case 0xA6: Ad_VlZp(); X = val; UpdateNZ(X); break;
3995 case 0xAE: Ad_VlAb(); X = val; UpdateNZ(X); break;
3996 case 0xB6: Ad_VlZy(); X = val; UpdateNZ(X); break;
3997 case 0xBE: Ad_VlAy(); X = val; UpdateNZ(X); break;
3999 /* LDY */
4000 case 0xA0: Ad_VlIm(); Y = val; UpdateNZ(Y); break;
4001 case 0xA4: Ad_VlZp(); Y = val; UpdateNZ(Y); break;
4002 case 0xAC: Ad_VlAb(); Y = val; UpdateNZ(Y); break;
4003 case 0xB4: Ad_VlZx(); Y = val; UpdateNZ(Y); break;
4004 case 0xBC: Ad_VlAx(); Y = val; UpdateNZ(Y); break;
4006 /* LSR */
4007 case 0x4A: LSR(A); break;
4008 case 0x46: MRW_Zp(LSR); break;
4009 case 0x4E: MRW_Ab(LSR); break;
4010 case 0x56: MRW_Zx(LSR); break;
4011 case 0x5E: MRW_Ax(LSR); break;
4013 /* NOP */
4014 case 0xEA:
4016 /* --- Undocumented ---
4017 These opcodes perform the same action as NOP */
4018 case 0x1A: case 0x3A: case 0x5A:
4019 case 0x7A: case 0xDA: case 0xFA: break;
4021 /* ORA */
4022 case 0x01: Ad_VlIx(); ORA(); break;
4023 case 0x05: Ad_VlZp(); ORA(); break;
4024 case 0x09: Ad_VlIm(); ORA(); break;
4025 case 0x0D: Ad_VlAb(); ORA(); break;
4026 case 0x11: Ad_VlIy(); ORA(); break;
4027 case 0x15: Ad_VlZx(); ORA(); break;
4028 case 0x19: Ad_VlAy(); ORA(); break;
4029 case 0x1D: Ad_VlAx(); ORA(); break;
4031 /* ROL */
4032 case 0x2A: ROL(A); break;
4033 case 0x26: MRW_Zp(ROL); break;
4034 case 0x2E: MRW_Ab(ROL); break;
4035 case 0x36: MRW_Zx(ROL); break;
4036 case 0x3E: MRW_Ax(ROL); break;
4038 /* ROR */
4039 case 0x6A: ROR(A); break;
4040 case 0x66: MRW_Zp(ROR); break;
4041 case 0x6E: MRW_Ab(ROR); break;
4042 case 0x76: MRW_Zx(ROR); break;
4043 case 0x7E: MRW_Ax(ROR); break;
4045 /* RTI */
4046 case 0x40:
4047 PULL(ST); /*pull processor status*/
4048 PULL(PC.B.l); /*pull low byte of return address*/
4049 PULL(PC.B.h); /*pull high byte of return address*/
4050 break;
4052 /* RTS */
4053 case 0x60:
4054 PULL(PC.B.l);
4055 PULL(PC.B.h);
4056 PC.W++; /* the return address is one less of what it needs */
4057 break;
4059 /* SBC */
4060 case 0xE1: Ad_VlIx(); SBC(); break;
4061 case 0xE5: Ad_VlZp(); SBC(); break;
4062 /* - Undocumented - EB performs the same operation as SBC immediate */
4063 case 0xEB:
4064 case 0xE9: Ad_VlIm(); SBC(); break;
4065 case 0xED: Ad_VlAb(); SBC(); break;
4066 case 0xF1: Ad_VlIy(); SBC(); break;
4067 case 0xF5: Ad_VlZx(); SBC(); break;
4068 case 0xF9: Ad_VlAy(); SBC(); break;
4069 case 0xFD: Ad_VlAx(); SBC(); break;
4071 /* STA */
4072 case 0x81: Ad_AdIx(); val = A; Wr(final.W,A); break;
4073 case 0x85: Ad_AdZp(); val = A; WrZ(final.W,A); break;
4074 case 0x8D: Ad_AdAb(); val = A; Wr(final.W,A); break;
4075 case 0x91: Ad_AdIy(); val = A; Wr(final.W,A); break;
4076 case 0x95: Ad_AdZx(); val = A; WrZ(final.W,A); break;
4077 case 0x99: Ad_AdAy(); val = A; Wr(final.W,A); break;
4078 case 0x9D: Ad_AdAx(); val = A; Wr(final.W,A); break;
4080 /* STX */
4081 case 0x86: Ad_AdZp(); val = X; WrZ(final.W,X); break;
4082 case 0x8E: Ad_AdAb(); val = X; Wr(final.W,X); break;
4083 case 0x96: Ad_AdZy(); val = X; WrZ(final.W,X); break;
4085 /* STY */
4086 case 0x84: Ad_AdZp(); val = Y; WrZ(final.W,Y); break;
4087 case 0x8C: Ad_AdAb(); val = Y; Wr(final.W,Y); break;
4088 case 0x94: Ad_AdZx(); val = Y; WrZ(final.W,Y); break;
4090 /* Undocumented Opcodes */
4091 /* ASO */
4092 case 0x03: if(bIgnoreIllegalOps) break; MRW_Ix(ASO); break;
4093 case 0x07: if(bIgnoreIllegalOps) break; MRW_Zp(ASO); break;
4094 case 0x0F: if(bIgnoreIllegalOps) break; MRW_Ab(ASO); break;
4095 case 0x13: if(bIgnoreIllegalOps) break; MRW_Iy(ASO); break;
4096 case 0x17: if(bIgnoreIllegalOps) break; MRW_Zx(ASO); break;
4097 case 0x1B: if(bIgnoreIllegalOps) break; MRW_Ay(ASO); break;
4098 case 0x1F: if(bIgnoreIllegalOps) break; MRW_Ax(ASO); break;
4100 /* RLA */
4101 case 0x23: if(bIgnoreIllegalOps) break; MRW_Ix(RLA); break;
4102 case 0x27: if(bIgnoreIllegalOps) break; MRW_Zp(RLA); break;
4103 case 0x2F: if(bIgnoreIllegalOps) break; MRW_Ab(RLA); break;
4104 case 0x33: if(bIgnoreIllegalOps) break; MRW_Iy(RLA); break;
4105 case 0x37: if(bIgnoreIllegalOps) break; MRW_Zx(RLA); break;
4106 case 0x3B: if(bIgnoreIllegalOps) break; MRW_Ay(RLA); break;
4107 case 0x3F: if(bIgnoreIllegalOps) break; MRW_Ax(RLA); break;
4109 /* LSE */
4110 case 0x43: if(bIgnoreIllegalOps) break; MRW_Ix(LSE); break;
4111 case 0x47: if(bIgnoreIllegalOps) break; MRW_Zp(LSE); break;
4112 case 0x4F: if(bIgnoreIllegalOps) break; MRW_Ab(LSE); break;
4113 case 0x53: if(bIgnoreIllegalOps) break; MRW_Iy(LSE); break;
4114 case 0x57: if(bIgnoreIllegalOps) break; MRW_Zx(LSE); break;
4115 case 0x5B: if(bIgnoreIllegalOps) break; MRW_Ay(LSE); break;
4116 case 0x5F: if(bIgnoreIllegalOps) break; MRW_Ax(LSE); break;
4118 /* RRA */
4119 case 0x63: if(bIgnoreIllegalOps) break; MRW_Ix(RRA); break;
4120 case 0x67: if(bIgnoreIllegalOps) break; MRW_Zp(RRA); break;
4121 case 0x6F: if(bIgnoreIllegalOps) break; MRW_Ab(RRA); break;
4122 case 0x73: if(bIgnoreIllegalOps) break; MRW_Iy(RRA); break;
4123 case 0x77: if(bIgnoreIllegalOps) break; MRW_Zx(RRA); break;
4124 case 0x7B: if(bIgnoreIllegalOps) break; MRW_Ay(RRA); break;
4125 case 0x7F: if(bIgnoreIllegalOps) break; MRW_Ax(RRA); break;
4127 /* AXS */
4128 case 0x83: if(bIgnoreIllegalOps) break; MRW_Ix(AXS); break;
4129 case 0x87: if(bIgnoreIllegalOps) break; MRW_Zp(AXS); break;
4130 case 0x8F: if(bIgnoreIllegalOps) break; MRW_Ab(AXS); break;
4131 case 0x97: if(bIgnoreIllegalOps) break; MRW_Zy(AXS); break;
4133 /* LAX */
4134 case 0xA3: if(bIgnoreIllegalOps) break;
4135 Ad_VlIx(); X = A = val; UpdateNZ(A); break;
4136 case 0xA7: if(bIgnoreIllegalOps) break;
4137 Ad_VlZp(); X = A = val; UpdateNZ(A); break;
4138 case 0xAF: if(bIgnoreIllegalOps) break;
4139 Ad_VlAb(); X = A = val; UpdateNZ(A); break;
4140 case 0xB3: if(bIgnoreIllegalOps) break;
4141 Ad_VlIy(); X = A = val; UpdateNZ(A); break;
4142 case 0xB7: if(bIgnoreIllegalOps) break;
4143 Ad_VlZy(); X = A = val; UpdateNZ(A); break;
4144 case 0xBF: if(bIgnoreIllegalOps) break;
4145 Ad_VlAy(); X = A = val; UpdateNZ(A); break;
4147 /* DCM */
4148 case 0xC3: if(bIgnoreIllegalOps) break; MRW_Ix(DCM); break;
4149 case 0xC7: if(bIgnoreIllegalOps) break; MRW_Zp(DCM); break;
4150 case 0xCF: if(bIgnoreIllegalOps) break; MRW_Ab(DCM); break;
4151 case 0xD3: if(bIgnoreIllegalOps) break; MRW_Iy(DCM); break;
4152 case 0xD7: if(bIgnoreIllegalOps) break; MRW_Zx(DCM); break;
4153 case 0xDB: if(bIgnoreIllegalOps) break; MRW_Ay(DCM); break;
4154 case 0xDF: if(bIgnoreIllegalOps) break; MRW_Ax(DCM); break;
4156 /* INS */
4157 case 0xE3: if(bIgnoreIllegalOps) break; MRW_Ix(INS); break;
4158 case 0xE7: if(bIgnoreIllegalOps) break; MRW_Zp(INS); break;
4159 case 0xEF: if(bIgnoreIllegalOps) break; MRW_Ab(INS); break;
4160 case 0xF3: if(bIgnoreIllegalOps) break; MRW_Iy(INS); break;
4161 case 0xF7: if(bIgnoreIllegalOps) break; MRW_Zx(INS); break;
4162 case 0xFB: if(bIgnoreIllegalOps) break; MRW_Ay(INS); break;
4163 case 0xFF: if(bIgnoreIllegalOps) break; MRW_Ax(INS); break;
4165 /* ALR
4166 AND Accumulator with memory and LSR the result */
4167 case 0x4B: if(bIgnoreIllegalOps) break;
4168 Ad_VlIm(); A &= val; LSR(A); break;
4170 /* ARR
4171 ANDs memory with the Accumulator and RORs the result */
4172 case 0x6B: if(bIgnoreIllegalOps) break;
4173 Ad_VlIm(); A &= val; ROR(A); break;
4175 /* XAA
4176 Transfers X -> A, then ANDs A with memory */
4177 case 0x8B: if(bIgnoreIllegalOps) break;
4178 Ad_VlIm(); A = X & val; UpdateNZ(A); break;
4180 /* OAL
4181 OR the Accumulator with #EE, AND Accumulator with Memory,
4182 Transfer A -> X */
4183 case 0xAB: if(bIgnoreIllegalOps) break;
4184 Ad_VlIm(); X = (A &= (val | 0xEE));
4185 UpdateNZ(A); break;
4187 /* SAX
4188 ANDs A and X registers (does not change A), subtracts memory
4189 from result (CMP style, not SBC style) result is stored in X */
4190 case 0xCB: if(bIgnoreIllegalOps) break;
4191 Ad_VlIm(); tw.W = (X & A) - val; X = tw.B.l;
4192 ST = (ST & ~(N_FLAG|Z_FLAG|C_FLAG)) | NZTable[X] |
4193 (tw.B.h ? C_FLAG : 0); break;
4194 /* SKB
4195 Skip Byte... or DOP - Double No-Op
4196 These bytes do nothing, but take a parameter (which can be
4197 ignored) */
4198 case 0x04: case 0x14: case 0x34: case 0x44: case 0x54: case 0x64:
4199 case 0x80: case 0x82: case 0x89: case 0xC2: case 0xD4: case 0xE2:
4200 case 0xF4:
4201 if(bIgnoreIllegalOps) break;
4202 PC.W++; /* skip unused byte */
4203 break;
4205 /* SKW
4206 Swip Word... or TOP - Tripple No-Op
4207 These bytes are the same as SKB, only they take a 2 byte parameter.
4208 This can be ignored in some cases, but the read needs to be
4209 performed in a some cases because an extra clock cycle may be used
4210 in the process */
4211 /* Absolute address... no need for operator */
4212 case 0x0C:
4213 if(bIgnoreIllegalOps) break;
4214 PC.W += 2; break;
4215 /* Absolute X address... may cross page, have to perform the read */
4216 case 0x1C: case 0x3C: case 0x5C: case 0x7C: case 0xDC: case 0xFC:
4217 if(bIgnoreIllegalOps) break;
4218 Ad_VlAx(); break;
4220 /* HLT / JAM
4221 Jams up CPU operation */
4222 case 0x02: case 0x12: case 0x22: case 0x32: case 0x42: case 0x52:
4223 case 0x62: case 0x72: case 0x92: case 0xB2: case 0xD2: case 0xF2:
4224 /*it's not -really- jammed... only the NSF code has ended*/
4225 if(PC.W == 0x5004) bCPUJammed = 2;
4226 else
4228 if(bIgnoreIllegalOps) break;
4229 bCPUJammed = 1;
4231 goto jammed;
4233 /* TAS */
4234 case 0x9B:
4235 if(bIgnoreIllegalOps) break;
4236 Ad_AdAy();
4237 SP = A & X & (Rd(PC.W - 1) + 1);
4238 Wr(final.W,SP);
4239 break;
4241 /* SAY */
4242 case 0x9C:
4243 if(bIgnoreIllegalOps) break;
4244 Ad_AdAx();
4245 Y &= (Rd(PC.W - 1) + 1);
4246 Wr(final.W,Y);
4247 break;
4249 /* XAS */
4250 case 0x9E:
4251 if(bIgnoreIllegalOps) break;
4252 Ad_AdAy();
4253 X &= (Rd(PC.W - 1) + 1);
4254 Wr(final.W,X);
4255 break;
4257 /* AXA */
4258 case 0x93: if(bIgnoreIllegalOps) break; MRW_Iy(AXA); break;
4259 case 0x9F: if(bIgnoreIllegalOps) break; MRW_Ay(AXA); break;
4261 /* ANC */
4262 case 0x0B: case 0x2B:
4263 if(bIgnoreIllegalOps) break;
4264 Ad_VlIm();
4265 A &= val;
4266 ST = (ST & ~(N_FLAG|Z_FLAG|C_FLAG)) |
4267 NZTable[A] | ((A & 0x80) ? C_FLAG : 0);
4268 break;
4270 /* LAS */
4271 case 0xBB:
4272 if(bIgnoreIllegalOps) break;
4273 Ad_VlAy();
4274 X = A = (SP &= val);
4275 UpdateNZ(A);
4276 break;
4280 jammed:
4281 regPC = PC.W;
4282 regA = A;
4283 regX = X;
4284 regY = Y;
4285 regSP = SP;
4286 regP = ST;
4288 EXIT_TIMER(cpu);
4290 return (nCPUCycle - ret);
4293 /****************** rockbox interface ******************/
4295 void set_codec_track(int t, int d) {
4296 int track,fade,def=0;
4297 SetTrack(t);
4299 /* for REPEAT_ONE we disable track limits */
4300 if (ci->global_settings->repeat_mode!=REPEAT_ONE) {
4301 if (!bIsExtended || nTrackTime[t]==-1) {track=60*2*1000; def=1;}
4302 else track=nTrackTime[t];
4303 if (!bIsExtended || nTrackFade[t]==-1) fade=5*1000;
4304 else fade=nTrackFade[t];
4305 nSilenceTrackMS=5000;
4306 SetFadeTime(track,track+fade, fNSFPlaybackSpeed,def);
4308 ci->id3->elapsed=d*1000; /* d is track no to display */
4311 /* this is the codec entry point */
4312 enum codec_status codec_main(void)
4314 int written;
4315 uint8_t *buf;
4316 size_t n;
4317 int endofstream; /* end of stream flag */
4318 int track;
4319 int dontresettrack;
4320 char last_path[MAX_PATH];
4321 int usingplaylist;
4323 /* we only render 16 bits */
4324 ci->configure(DSP_SET_SAMPLE_DEPTH, 16);
4326 ci->configure(DSP_SET_FREQUENCY, 44100);
4327 ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO);
4329 RebuildOutputTables();
4331 dontresettrack=0;
4332 last_path[0]='\0';
4333 track=0;
4335 next_track:
4336 usingplaylist=0;
4337 DEBUGF("NSF: next_track\n");
4338 if (codec_init()) {
4339 return CODEC_ERROR;
4341 DEBUGF("NSF: after init\n");
4344 /* wait for track info to load */
4345 while (!*ci->taginfo_ready && !ci->stop_codec)
4346 ci->sleep(1);
4348 codec_set_replaygain(ci->id3);
4350 /* Read the entire file */
4351 DEBUGF("NSF: request file\n");
4352 ci->seek_buffer(0);
4353 buf = ci->request_buffer(&n, ci->filesize);
4354 if (!buf || n < (size_t)ci->filesize) {
4355 DEBUGF("NSF: file load failed\n");
4356 return CODEC_ERROR;
4359 init_nsf:
4360 if(!NSFCore_Initialize()) {
4361 DEBUGF("NSF: NSFCore_Initialize failed\n"); return CODEC_ERROR;}
4363 if(LoadFile(buf,ci->filesize)) {
4364 DEBUGF("NSF: LoadFile failed\n"); return CODEC_ERROR;}
4365 if(!SetPlaybackOptions(44100)) {
4366 DEBUGF("NSF: SetPlaybackOptions failed\n"); return CODEC_ERROR;}
4367 if(!LoadNSF(nDataBufferSize)) {
4368 DEBUGF("NSF: LoadNSF failed\n"); return CODEC_ERROR;}
4370 ci->id3->title=szGameTitle;
4371 ci->id3->artist=szArtist;
4372 ci->id3->album=szCopyright;
4373 if (usingplaylist) {
4374 ci->id3->length=nPlaylistSize*1000;
4375 } else {
4376 ci->id3->length=nTrackCount*1000;
4379 if (!dontresettrack||strcmp(ci->id3->path,last_path)) {
4380 /* if this is the first time we're seeing this file, or if we haven't
4381 been asked to preserve the track number, default to the proper
4382 initial track */
4383 if (bIsExtended &&
4384 ci->global_settings->repeat_mode!=REPEAT_ONE && nPlaylistSize>0) {
4385 /* decide to use the playlist */
4386 usingplaylist=1;
4387 track=0;
4388 set_codec_track(nPlaylist[0],0);
4389 } else {
4390 /* simply use the initial track */
4391 track=nInitialTrack;
4392 set_codec_track(track,track);
4394 } else {
4395 /* if we've already been running this file assume track is set
4396 already */
4397 if (usingplaylist) set_codec_track(nPlaylist[track],track);
4398 else set_codec_track(track,track);
4400 strcpy(last_path,ci->id3->path);
4402 /* The main decoder loop */
4404 endofstream = 0;
4406 reset_profile_timers();
4408 while (!endofstream) {
4410 ci->yield();
4411 if (ci->stop_codec || ci->new_track) {
4412 break;
4415 if (ci->seek_time >0) {
4416 track=ci->seek_time/1000;
4417 if (usingplaylist) {
4418 if (track>=nPlaylistSize) break;
4419 } else {
4420 if (track>=nTrackCount) break;
4422 ci->seek_complete();
4423 dontresettrack=1;
4424 goto init_nsf;
4427 ENTER_TIMER(total);
4428 written=GetSamples((uint8_t*)samples,WAV_CHUNK_SIZE/2);
4429 EXIT_TIMER(total);
4431 if (!written || SongCompleted()) {
4432 print_timers(last_path,track);
4433 reset_profile_timers();
4435 track++;
4436 if (usingplaylist) {
4437 if (track>=nPlaylistSize) break;
4438 } else {
4439 if (track>=nTrackCount) break;
4441 dontresettrack=1;
4442 goto init_nsf;
4445 ci->pcmbuf_insert(samples, NULL, written >> 1);
4448 print_timers(last_path,track);
4450 if (ci->request_next_track()) {
4451 if (ci->global_settings->repeat_mode==REPEAT_ONE) {
4452 /* in repeat one mode just advance to the next track */
4453 track++;
4454 if (track>=nTrackCount) track=0;
4455 dontresettrack=1;
4456 /* at this point we can't tell if another file has been selected */
4457 goto next_track;
4458 } else {
4459 /* otherwise do a proper load of the next file */
4460 dontresettrack=0;
4461 last_path[0]='\0';
4463 goto next_track; /* when we fall through here we'll reload the file */
4466 return CODEC_OK;