Apply FS#9194 - LCD invert for Sansa c200/c200v2
[maemo-rb.git] / apps / codecs / nsf.c
blobf596f9dc68bd293119d61657a83b560dc968bf84
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
9 * Copyright (C) 2006 Adam Gashlin (hcs)
10 * Copyright (C) 2004 Disch
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
23 * This is a perversion of Disch's excellent NotSoFatso.
26 #include "codeclib.h"
27 #include "inttypes.h"
28 #include "system.h"
30 CODEC_HEADER
32 /* arm doesn't benefit from IRAM? */
33 #ifdef CPU_ARM
34 #undef ICODE_ATTR
35 #define ICODE_ATTR
36 #undef IDATA_ATTR
37 #define IDATA_ATTR
38 #else
39 #define ICODE_INSTEAD_OF_INLINE
40 #endif
42 /* Maximum number of bytes to process in one iteration */
43 #define WAV_CHUNK_SIZE (1024*2)
45 static int16_t samples[WAV_CHUNK_SIZE] IBSS_ATTR;
47 #define ZEROMEMORY(addr,size) memset(addr,0,size)
49 /* simple profiling with USEC_TIMER
51 #define NSF_PROFILE
55 #ifdef NSF_PROFILE
57 #define CREATE_TIMER(name) uint32_t nsf_timer_##name##_start,\
58 nsf_timer_##name##_total
59 #define ENTER_TIMER(name) nsf_timer_##name##_start=USEC_TIMER
60 #define EXIT_TIMER(name) nsf_timer_##name##_total+=\
61 (USEC_TIMER-nsf_timer_##name##_start)
62 #define READ_TIMER(name) (nsf_timer_##name##_total)
63 #define RESET_TIMER(name) nsf_timer_##name##_total=0
65 #define PRINT_TIMER_PCT(bname,tname,nstr) ci->fdprintf(
66 logfd,"%10ld ",READ_TIMER(bname));\
67 ci->fdprintf(logfd,"(%3d%%) " nstr "\t",\
68 ((uint64_t)READ_TIMER(bname))*100/READ_TIMER(tname))
70 CREATE_TIMER(total);
71 CREATE_TIMER(cpu);
72 CREATE_TIMER(apu);
73 CREATE_TIMER(squares);
74 CREATE_TIMER(tnd);
75 CREATE_TIMER(tnd_enter);
76 CREATE_TIMER(tnd_tri);
77 CREATE_TIMER(tnd_noise);
78 CREATE_TIMER(tnd_dmc);
79 CREATE_TIMER(fds);
80 CREATE_TIMER(frame);
81 CREATE_TIMER(mix);
83 void reset_profile_timers(void) {
84 RESET_TIMER(total);
85 RESET_TIMER(cpu);
86 RESET_TIMER(apu);
87 RESET_TIMER(squares);
88 RESET_TIMER(tnd);
89 RESET_TIMER(tnd_enter);
90 RESET_TIMER(tnd_tri);
91 RESET_TIMER(tnd_noise);
92 RESET_TIMER(tnd_dmc);
93 RESET_TIMER(fds);
94 RESET_TIMER(frame);
95 RESET_TIMER(mix);
98 int logfd=-1;
100 void print_timers(char * path, int track) {
101 logfd = ci->open("/nsflog.txt",O_WRONLY|O_CREAT|O_APPEND, 0666);
102 ci->fdprintf(logfd,"%s[%d]:\t",path,track);
103 ci->fdprintf(logfd,"%10ld total\t",READ_TIMER(total));
104 PRINT_TIMER_PCT(cpu,total,"CPU");
105 PRINT_TIMER_PCT(apu,total,"APU");
106 ci->fdprintf(logfd,"\n\t");
107 PRINT_TIMER_PCT(squares,apu,"squares");
108 PRINT_TIMER_PCT(frame,apu,"frame");
109 PRINT_TIMER_PCT(mix,apu,"mix");
110 PRINT_TIMER_PCT(fds,apu,"FDS");
111 PRINT_TIMER_PCT(tnd,apu,"tnd");
112 ci->fdprintf(logfd,"\n\t\t");
113 PRINT_TIMER_PCT(tnd_enter,tnd,"enter");
114 PRINT_TIMER_PCT(tnd_tri,tnd,"triangle");
115 PRINT_TIMER_PCT(tnd_noise,tnd,"noise");
116 PRINT_TIMER_PCT(tnd_dmc,tnd,"DMC");
117 ci->fdprintf(logfd,"\n");
119 ci->close(logfd);
120 logfd=-1;
123 #else
125 #define CREATE_TIMER(name)
126 #define ENTER_TIMER(name)
127 #define EXIT_TIMER(name)
128 #define READ_TIMER(name)
129 #define RESET_TIMER(name)
130 #define print_timers(path,track)
131 #define reset_profile_timers()
133 #endif
135 /* proper handling of multibyte values */
136 #ifdef ROCKBOX_LITTLE_ENDIAN
137 union TWIN
139 uint16_t W;
140 struct{ uint8_t l; uint8_t h; } B;
143 union QUAD
145 uint32_t D;
146 struct{ uint8_t l; uint8_t h; uint16_t w; } B;
148 #else
150 union TWIN
152 uint16_t W;
153 struct{ uint8_t h; uint8_t l; } B;
156 union QUAD
158 uint32_t D;
159 struct{uint16_t w; uint8_t h; uint8_t l; } B;
162 #endif
164 #define NTSC_FREQUENCY 1789772.727273f
165 #define PAL_FREQUENCY 1652097.692308f
166 #define NTSC_NMIRATE 60.098814f
167 #define PAL_NMIRATE 50.006982f
169 #define NES_FREQUENCY 21477270
170 #define NTSC_FRAME_COUNTER_FREQ (NTSC_FREQUENCY / (NES_FREQUENCY / 89490.0f))
171 #define PAL_FRAME_COUNTER_FREQ (PAL_FREQUENCY / (NES_FREQUENCY / 89490.0f))
173 /****************** tables */
174 static const int32_t ModulationTable[8] ICONST_ATTR = {0,1,2,4,0,-4,-2,-1};
175 const uint16_t DMC_FREQ_TABLE[2][0x10] = {
176 /* NTSC */
177 {0x1AC,0x17C,0x154,0x140,0x11E,0x0FE,0x0E2,0x0D6,0x0BE,0x0A0,0x08E,0x080,
178 0x06A,0x054,0x048,0x036},
179 /* PAL */
180 {0x18C,0x160,0x13A,0x128,0x108,0x0EA,0x0D0,0x0C6,0x0B0,0x094,0x082,0x076,
181 0x062,0x04E,0x042,0x032}
184 const uint8_t DUTY_CYCLE_TABLE[4] = {2,4,8,12};
186 const uint8_t LENGTH_COUNTER_TABLE[0x20] = {
187 0x0A,0xFE,0x14,0x02,0x28,0x04,0x50,0x06,0xA0,0x08,0x3C,0x0A,0x0E,0x0C,0x1A,
188 0x0E,0x0C,0x10,0x18,0x12,0x30,0x14,0x60,0x16,0xC0,0x18,0x48,0x1A,0x10,0x1C,
189 0x20,0x1E
192 const uint16_t NOISE_FREQ_TABLE[0x10] = {
193 0x004,0x008,0x010,0x020,0x040,0x060,0x080,0x0A0,0x0CA,0x0FE,0x17C,0x1FC,
194 0x2FA,0x3F8,0x7F2,0xFE4
197 /****************** NSF loading ******************/
199 /* file format structs (both are little endian) */
201 struct NESM_HEADER
203 uint32_t nHeader;
204 uint8_t nHeaderExtra;
205 uint8_t nVersion;
206 uint8_t nTrackCount;
207 uint8_t nInitialTrack;
208 uint16_t nLoadAddress;
209 uint16_t nInitAddress;
210 uint16_t nPlayAddress;
211 uint8_t szGameTitle[32];
212 uint8_t szArtist[32];
213 uint8_t szCopyright[32];
214 uint16_t nSpeedNTSC;
215 uint8_t nBankSwitch[8];
216 uint16_t nSpeedPAL;
217 uint8_t nNTSC_PAL;
218 uint8_t nExtraChip;
219 uint8_t nExpansion[4];
222 struct NSFE_INFOCHUNK
224 uint16_t nLoadAddress;
225 uint16_t nInitAddress;
226 uint16_t nPlayAddress;
227 uint8_t nIsPal;
228 uint8_t nExt;
229 uint8_t nTrackCount;
230 uint8_t nStartingTrack;
233 int32_t LoadFile(uint8_t *,size_t);
235 int32_t LoadFile_NESM(uint8_t *,size_t);
236 int32_t LoadFile_NSFE(uint8_t *,size_t);
238 /* NSF file info */
240 /* basic NSF info */
241 int32_t bIsExtended=0; /* 0 = NSF, 1 = NSFE */
242 uint8_t nIsPal=0; /* 0 = NTSC, 1 = PAL,
243 2,3 = mixed NTSC/PAL (interpretted as NTSC) */
244 int32_t nfileLoadAddress=0; /* The address to which the NSF code is
245 loaded */
246 int32_t nfileInitAddress=0; /* The address of the Init routine
247 (called at track change) */
248 int32_t nfilePlayAddress=0; /* The address of the Play routine
249 (called several times a second) */
250 uint8_t nChipExtensions=0; /* Bitwise representation of the external chips
251 used by this NSF. */
253 /* old NESM speed stuff (blarg) */
254 int32_t nNTSC_PlaySpeed=0;
255 int32_t nPAL_PlaySpeed=0;
257 /* track info */
258 /* The number of tracks in the NSF (1 = 1 track, 5 = 5 tracks, etc) */
259 int32_t nTrackCount=0;
260 /* The initial track (ZERO BASED: 0 = 1st track, 4 = 5th track, etc) */
261 int32_t nInitialTrack=0;
263 /* nsf data */
264 uint8_t* pDataBuffer=0; /* the buffer containing NSF code. */
265 int32_t nDataBufferSize=0; /* the size of the above buffer. */
267 /* playlist */
268 uint8_t nPlaylist[256]; /* Each entry is the zero based index of the
269 song to play */
270 int32_t nPlaylistSize=0; /* the number of tracks in the playlist */
272 /* track time / fade */
273 int32_t nTrackTime[256]; /* track times -1 if no track times specified */
274 int32_t nTrackFade[256]; /* track fade times -1 if none are specified */
276 /* string info */
277 uint8_t szGameTitle[0x101];
278 uint8_t szArtist[0x101];
279 uint8_t szCopyright[0x101];
280 uint8_t szRipper[0x101];
282 /* bankswitching info */
283 uint8_t nBankswitch[8]={0}; /* The initial bankswitching registers needed
284 * for some NSFs. If the NSF does not use
285 * bankswitching, these values will all be zero
288 int32_t LoadFile(uint8_t * inbuffer, size_t size)
290 if(!inbuffer) return -1;
292 int32_t ret = -1;
294 if(!memcmp(inbuffer,"NESM",4)) ret = LoadFile_NESM(inbuffer,size);
295 if(!memcmp(inbuffer,"NSFE",4)) ret = LoadFile_NSFE(inbuffer,size);
298 * Snake's revenge puts '00' for the initial track,
299 * which (after subtracting 1) makes it 256 or -1 (bad!)
300 * This prevents that crap
302 if(nInitialTrack >= nTrackCount)
303 nInitialTrack = 0;
304 if(nInitialTrack < 0)
305 nInitialTrack = 0;
307 /* if there's no tracks... this is a crap NSF */
308 if(nTrackCount < 1)
310 return -1;
313 return ret;
316 int32_t LoadFile_NESM(uint8_t* inbuffer, size_t size)
318 uint8_t ignoreversion=1;
319 uint8_t needdata=1;
321 /* read the info */
322 struct NESM_HEADER hdr;
324 memcpy(&hdr,inbuffer,sizeof(hdr));
326 /* confirm the header */
327 if(memcmp("NESM",&(hdr.nHeader),4)) return -1;
328 if(hdr.nHeaderExtra != 0x1A) return -1;
329 /* stupid NSFs claim to be above version 1 >_> */
330 if((!ignoreversion) && (hdr.nVersion != 1)) return -1;
333 * NESM is generally easier to work with (but limited!)
334 * just move the data over from NESM_HEADER over to our member data
337 bIsExtended = 0;
338 nIsPal = hdr.nNTSC_PAL & 0x03;
339 nPAL_PlaySpeed = letoh16(hdr.nSpeedPAL);
340 nNTSC_PlaySpeed = letoh16(hdr.nSpeedNTSC);
341 nfileLoadAddress = letoh16(hdr.nLoadAddress);
342 nfileInitAddress = letoh16(hdr.nInitAddress);
343 nfilePlayAddress = letoh16(hdr.nPlayAddress);
344 nChipExtensions = hdr.nExtraChip;
347 nTrackCount = hdr.nTrackCount;
348 nInitialTrack = hdr.nInitialTrack - 1;
350 memcpy(nBankswitch,hdr.nBankSwitch,8);
352 memcpy(szGameTitle,hdr.szGameTitle,32);
353 memcpy(szArtist ,hdr.szArtist ,32);
354 memcpy(szCopyright,hdr.szCopyright,32);
356 /* read the NSF data */
357 if(needdata)
359 pDataBuffer=inbuffer+0x80;
360 nDataBufferSize=size-0x80;
363 /* if we got this far... it was a successful read */
364 return 0;
367 int32_t LoadFile_NSFE(uint8_t* inbuffer, size_t size)
369 /* the vars we'll be using */
370 uint32_t nChunkType;
371 int32_t nChunkSize;
372 int32_t nChunkUsed;
373 int32_t i;
374 uint8_t * nDataPos = 0;
375 uint8_t bInfoFound = 0;
376 uint8_t bEndFound = 0;
377 uint8_t bBankFound = 0;
378 nPlaylistSize=-1;
380 struct NSFE_INFOCHUNK info;
381 ZEROMEMORY(&info,sizeof(struct NSFE_INFOCHUNK));
382 ZEROMEMORY(nBankswitch,8);
383 info.nTrackCount = 1; /* default values */
385 if (size < 8) return -1; /* must have at least NSFE,NEND */
387 /* confirm the header! */
388 memcpy(&nChunkType,inbuffer,4);
389 inbuffer+=4;
390 if(memcmp(&nChunkType,"NSFE",4)) return -1;
392 for (i=0;i<256;i++) {
393 nTrackTime[i]=-1;
394 nTrackFade[i]=-1;
397 /* begin reading chunks */
398 while(!bEndFound)
400 memcpy(&nChunkSize,inbuffer,4);
401 nChunkSize=letoh32(nChunkSize);
402 inbuffer+=4;
403 memcpy(&nChunkType,inbuffer,4);
404 inbuffer+=4;
406 if(!memcmp(&nChunkType,"INFO",4)) {
407 /* only one info chunk permitted */
408 if(bInfoFound) return -1;
409 if(nChunkSize < 8) return -1; /* minimum size */
411 bInfoFound = 1;
412 nChunkUsed = MIN((int32_t)sizeof(struct NSFE_INFOCHUNK),
413 nChunkSize);
415 memcpy(&info,inbuffer,nChunkUsed);
416 inbuffer+=nChunkSize;
418 bIsExtended = 1;
419 nIsPal = info.nIsPal & 3;
420 nfileLoadAddress = letoh16(info.nLoadAddress);
421 nfileInitAddress = letoh16(info.nInitAddress);
422 nfilePlayAddress = letoh16(info.nPlayAddress);
423 nChipExtensions = info.nExt;
424 nTrackCount = info.nTrackCount;
425 nInitialTrack = info.nStartingTrack;
427 nPAL_PlaySpeed = (uint16_t)(1000000 / PAL_NMIRATE);
428 nNTSC_PlaySpeed = (uint16_t)(1000000 / NTSC_NMIRATE);
429 } else if (!memcmp(&nChunkType,"DATA",4)) {
430 if(!bInfoFound) return -1;
431 if(nDataPos) return -1;
432 if(nChunkSize < 1) return -1;
434 nDataBufferSize = nChunkSize;
435 nDataPos = inbuffer;
437 inbuffer+=nChunkSize;
438 } else if (!memcmp(&nChunkType,"NEND",4)) {
439 bEndFound = 1;
440 } else if (!memcmp(&nChunkType,"time",4)) {
441 if(!bInfoFound) return -1;
442 for (nChunkUsed=0; nChunkUsed < MIN(nChunkSize / 4,nTrackCount);
443 nChunkUsed++,inbuffer+=4) {
444 nTrackTime[nChunkUsed]=
445 ((uint32_t)inbuffer[0])|
446 ((uint32_t)inbuffer[1]<<8)|
447 ((uint32_t)inbuffer[2]<<16)|
448 ((uint32_t)inbuffer[3]<<24);
451 inbuffer+=nChunkSize-(nChunkUsed*4);
453 /* negative signals to use default time */
454 for(; nChunkUsed < nTrackCount; nChunkUsed++)
455 nTrackTime[nChunkUsed] = -1;
456 } else if (!memcmp(&nChunkType,"fade",4)) {
457 if(!bInfoFound) return -1;
458 for (nChunkUsed=0; nChunkUsed < MIN(nChunkSize / 4,nTrackCount);
459 nChunkUsed++,inbuffer+=4) {
460 nTrackFade[nChunkUsed]=
461 ((uint32_t)inbuffer[0])|
462 ((uint32_t)inbuffer[1]<<8)|
463 ((uint32_t)inbuffer[2]<<16)|
464 ((uint32_t)inbuffer[3]<<24);
467 inbuffer+=nChunkSize-(nChunkUsed*4);
469 /* negative signals to use default time */
470 for(; nChunkUsed < nTrackCount; nChunkUsed++)
471 nTrackFade[nChunkUsed] = -1;
472 } else if (!memcmp(&nChunkType,"BANK",4)) {
473 if(bBankFound) return -1;
475 bBankFound = 1;
476 nChunkUsed = MIN(8,nChunkSize);
477 memcpy(nBankswitch,inbuffer,nChunkUsed);
479 inbuffer+=nChunkSize;
480 } else if (!memcmp(&nChunkType,"plst",4)) {
482 nPlaylistSize = nChunkSize;
483 if(nPlaylistSize >= 1) {
485 memcpy(nPlaylist,inbuffer,nChunkSize);
486 inbuffer+=nChunkSize;
488 } else if (!memcmp(&nChunkType,"auth",4)) {
489 uint8_t* ptr;
491 ptr = inbuffer;
493 uint8_t* ar[4] = {szGameTitle,szArtist,szCopyright,szRipper};
494 int32_t i;
495 for(i = 0; (ptr-inbuffer)<nChunkSize && i < 4; i++)
497 nChunkUsed = strlen(ptr) + 1;
498 memcpy(ar[i],ptr,nChunkUsed);
499 ptr += nChunkUsed;
501 inbuffer+=nChunkSize;
502 } else if (!memcmp(&nChunkType,"tlbl",4)) {
503 /* we unfortunately can't use these anyway */
504 inbuffer+=nChunkSize;
505 } else { /* unknown chunk */
506 nChunkType = letoh32(nChunkType)>>24; /* check the first byte */
507 /* chunk is vital... don't continue */
508 if((nChunkType >= 'A') && (nChunkType <= 'Z'))
509 return -1;
510 /* otherwise, just skip it */
511 inbuffer+=nChunkSize;
512 } /* end if series */
513 } /* end while */
516 * if we exited the while loop without a 'return', we must have hit an NEND
517 * chunk if this is the case, the file was layed out as it was expected.
518 * now.. make sure we found both an info chunk, AND a data chunk... since
519 * these are minimum requirements for a valid NSFE file
522 if(!bInfoFound) return -1;
523 if(!nDataPos) return -1;
525 /* if both those chunks existed, this file is valid.
526 Load the data if it's needed */
528 pDataBuffer=nDataPos;
530 /* return success! */
531 return 0;
535 /****************** Audio Device Structures ******************/
537 struct FDSWave
539 /* Envelope Unit */
540 uint8_t bEnvelopeEnable;
541 uint8_t nEnvelopeSpeed;
543 /* Volume Envelope */
544 uint8_t nVolEnv_Mode;
545 uint8_t nVolEnv_Decay;
546 uint8_t nVolEnv_Gain;
547 int32_t nVolEnv_Timer;
548 int32_t nVolEnv_Count;
549 uint8_t nVolume;
550 uint8_t bVolEnv_On;
552 /* Sweep Envenlope */
553 uint8_t nSweep_Mode;
554 uint8_t nSweep_Decay;
555 int32_t nSweep_Timer;
556 int32_t nSweep_Count;
557 uint8_t nSweep_Gain;
558 uint8_t bSweepEnv_On;
560 /* Effector / LFO / Modulation Unit */
561 int32_t nSweepBias;
562 uint8_t bLFO_Enabled;
563 union TWIN nLFO_Freq;
564 /*float fLFO_Timer;*/
565 /*float fLFO_Count;*/
566 int32_t nLFO_Timer; /* -17.14*/
567 int32_t nLFO_Count; /* -17.14*/
568 uint8_t nLFO_Addr;
569 uint8_t nLFO_Table[0x40];
570 uint8_t bLFO_On;
572 /* Main Output */
573 uint8_t nMainVolume;
574 uint8_t bEnabled;
575 union TWIN nFreq;
576 /*float fFreqCount;*/
577 int32_t nFreqCount; /* -17.14 */
578 uint8_t nMainAddr;
579 uint8_t nWaveTable[0x40];
580 uint8_t bWaveWrite;
581 uint8_t bMain_On;
583 /* Output and Downsampling */
584 int32_t nMixL;
586 /* Pop Reducer */
587 uint8_t bPopReducer;
588 uint8_t nPopOutput;
589 int32_t nPopCount;
592 int16_t FDS_nOutputTable_L[4][0x21][0x40];
594 struct FME07Wave
596 /* Frequency Control */
597 union TWIN nFreqTimer;
598 int32_t nFreqCount;
600 /* Channel Disabling */
601 uint8_t bChannelEnabled;
603 /* Volume */
604 uint8_t nVolume;
606 /* Duty Cycle */
607 uint8_t nDutyCount;
609 /* Output and Downsampling */
610 int32_t nMixL;
613 int16_t FME07_nOutputTable_L[0x10] IDATA_ATTR;
615 struct N106Wave
617 /* All Channel Stuff */
619 uint8_t nActiveChannels;
620 uint8_t bAutoIncrement;
621 uint8_t nCurrentAddress;
622 uint8_t nRAM[0x100]; /* internal memory for registers/wave data */
623 int32_t nFrequencyLookupTable[8]; /* lookup tbl for freq conversions */
626 * Individual channel stuff
628 /* Wavelength / Frequency */
629 union QUAD nFreqReg[8];
630 int32_t nFreqTimer[8];
631 int32_t nFreqCount[8];
633 /* Wave data length / remaining */
634 uint8_t nWaveSize[8];
635 uint8_t nWaveRemaining[8];
637 /* Wave data position */
638 uint8_t nWavePosStart[8];
639 uint8_t nWavePos[8];
640 uint8_t nOutput[8];
642 /* Volume */
643 uint8_t nVolume[8];
645 /* Pop Reducer */
646 uint8_t nPreVolume[8];
647 uint8_t nPopCheck[8];
649 /* Mixing */
650 int32_t nMixL[8];
653 int16_t N106_nOutputTable_L[0x10][0x10];
655 struct VRC6PulseWave
658 /* Frequency Control */
659 union TWIN nFreqTimer;
660 int32_t nFreqCount;
662 /* Flags */
663 uint8_t bChannelEnabled;
664 uint8_t bDigitized;
666 /* Volume */
667 uint8_t nVolume;
669 /* Duty Cycle */
670 uint8_t nDutyCycle;
671 uint8_t nDutyCount;
673 /* Output and Downsampling */
674 int32_t nMixL;
678 int16_t VRC6Pulse_nOutputTable_L[0x10] IDATA_ATTR;
680 struct VRC6SawWave
683 /* Frequency Control */
684 union TWIN nFreqTimer;
685 int32_t nFreqCount;
687 /* Flags */
688 uint8_t bChannelEnabled;
690 /* Phase Accumulator */
691 uint8_t nAccumRate;
692 uint8_t nAccum;
693 uint8_t nAccumStep;
695 /* Output and Downsampling */
696 int32_t nMixL;
700 int16_t VRC6Saw_nOutputTable_L[0x20] IDATA_ATTR;
702 struct Wave_Squares
705 /* Programmable Timer */
706 union TWIN nFreqTimer[2];
707 int32_t nFreqCount[2];
709 /* Length Counter */
710 uint8_t nLengthCount[2];
711 uint8_t bLengthEnabled[2];
712 uint8_t bChannelEnabled[2];
714 /* Volume / Decay */
715 uint8_t nVolume[2];
716 uint8_t nDecayVolume[2];
717 uint8_t bDecayEnable[2];
718 uint8_t bDecayLoop[2];
719 uint8_t nDecayTimer[2];
720 uint8_t nDecayCount[2];
722 /* Sweep Unit */
723 uint8_t bSweepEnable[2];
724 uint8_t bSweepMode[2];
725 uint8_t bSweepForceSilence[2];
726 uint8_t nSweepTimer[2];
727 uint8_t nSweepCount[2];
728 uint8_t nSweepShift[2];
730 /* Duty Cycle */
731 uint8_t nDutyCount[2];
732 uint8_t nDutyCycle[2];
734 /* Output and Downsampling */
735 int32_t nMixL;
738 int16_t Squares_nOutputTable_L[0x10][0x10] IDATA_ATTR;
740 struct Wave_TND
744 * Triangle
747 /* Programmable Timer */
748 union TWIN nTriFreqTimer;
749 int32_t nTriFreqCount;
751 /* Length Counter */
752 uint8_t nTriLengthCount;
753 uint8_t bTriLengthEnabled;
754 uint8_t bTriChannelEnabled;
756 /* Linear Counter */
757 uint8_t nTriLinearCount;
758 uint8_t nTriLinearLoad;
759 uint8_t bTriLinearHalt;
760 uint8_t bTriLinearControl;
762 /* Tri-Step Generator / Output */
763 uint8_t nTriStep;
764 uint8_t nTriOutput;
767 * Noise
770 /* Programmable Timer */
771 uint16_t nNoiseFreqTimer;
772 int32_t nNoiseFreqCount;
774 /* Length Counter */
775 uint8_t nNoiseLengthCount;
776 uint8_t bNoiseLengthEnabled;
777 uint8_t bNoiseChannelEnabled;
779 /* Volume / Decay */
780 uint8_t nNoiseVolume;
781 uint8_t nNoiseDecayVolume;
782 uint8_t bNoiseDecayEnable;
783 uint8_t bNoiseDecayLoop;
784 uint8_t nNoiseDecayTimer;
785 uint8_t nNoiseDecayCount;
787 /* Random Number Generator */
788 uint16_t nNoiseRandomShift;
789 uint8_t bNoiseRandomMode; /* 1 = 32k, 6 = 93-bit */
790 uint8_t bNoiseRandomOut;
793 * DMC
796 /* Play Mode */
797 uint8_t bDMCLoop;
798 uint8_t bDMCIRQEnabled;
799 uint8_t bDMCIRQPending;
801 /* Address / DMA */
802 uint8_t nDMCDMABank_Load;
803 uint16_t nDMCDMAAddr_Load;
804 uint8_t nDMCDMABank;
805 uint16_t nDMCDMAAddr;
806 uint8_t* pDMCDMAPtr[8];
808 /* Length / Input */
809 uint16_t nDMCLength;
810 uint16_t nDMCBytesRemaining;
811 uint8_t nDMCDelta;
812 uint8_t nDMCDeltaBit;
813 uint8_t bDMCDeltaSilent;
814 uint8_t nDMCSampleBuffer;
815 uint8_t bDMCSampleBufferEmpty;
817 /* Frequency */
818 uint16_t nDMCFreqTimer;
819 int32_t nDMCFreqCount;
821 /* Output */
822 uint8_t bDMCActive;
823 uint8_t nDMCOutput;
825 int32_t nMixL;
828 /* channels */
829 struct Wave_Squares mWave_Squares IDATA_ATTR; /* Square channels 1 and 2 */
830 struct Wave_TND mWave_TND IDATA_ATTR; /* Triangle/Noise/DMC channels */
831 struct VRC6PulseWave mWave_VRC6Pulse[2] IDATA_ATTR;
832 struct VRC6SawWave mWave_VRC6Saw IDATA_ATTR;
833 struct N106Wave mWave_N106 IDATA_ATTR;
834 struct FDSWave mWave_FDS IDATA_ATTR;
835 struct FME07Wave mWave_FME07[3] IDATA_ATTR; /* FME-07's 3 pulse channels */
838 /****************** MMC5 ******************/
839 /* will include MMC5 sound channels some day,
840 currently only multiply is supported */
842 /****************** N106 (Disch loves this chip) ******************/
844 #ifdef ICODE_INSTEAD_OF_INLINE
845 void Wave_N106_DoTicks(const int32_t ticks) ICODE_ATTR;
846 void Wave_N106_DoTicks(const int32_t ticks)
847 #else
848 inline void Wave_N106_DoTicks(const int32_t ticks);
849 inline void Wave_N106_DoTicks(const int32_t ticks)
850 #endif
852 register int32_t i;
854 for(i = (7 - mWave_N106.nActiveChannels); i < 8; i++)
856 if(!mWave_N106.nFreqReg[i].D)
858 /* written frequency of zero will cause divide by zero error
859 makes me wonder if the formula was supposed to be Reg+1 */
860 mWave_N106.nVolume[i] = mWave_N106.nPreVolume[i];
861 continue;
865 mWave_N106.nMixL[i] =
866 N106_nOutputTable_L[mWave_N106.nVolume[i]]
867 [mWave_N106.nOutput[i]];
869 if(mWave_N106.nFreqTimer[i] < 0)
870 mWave_N106.nFreqTimer[i] =
871 (mWave_N106.nFrequencyLookupTable[mWave_N106.nActiveChannels] /
872 mWave_N106.nFreqReg[i].D);
873 if(mWave_N106.nFreqCount[i] > mWave_N106.nFreqTimer[i])
874 mWave_N106.nFreqCount[i] = mWave_N106.nFreqTimer[i];
876 mWave_N106.nFreqCount[i] -= ticks << 8;
877 while(mWave_N106.nFreqCount[i] <= 0)
879 mWave_N106.nFreqCount[i] += mWave_N106.nFreqTimer[i];
880 if(mWave_N106.nWaveRemaining[i])
882 mWave_N106.nWaveRemaining[i]--;
883 mWave_N106.nWavePos[i]++;
885 if(!mWave_N106.nWaveRemaining[i])
887 mWave_N106.nWaveRemaining[i] = mWave_N106.nWaveSize[i];
888 mWave_N106.nWavePos[i] = mWave_N106.nWavePosStart[i];
889 if(mWave_N106.nVolume[i] != mWave_N106.nPreVolume[i])
891 if(++mWave_N106.nPopCheck[i] >= 2)
893 mWave_N106.nPopCheck[i] = 0;
894 mWave_N106.nVolume[i] = mWave_N106.nPreVolume[i];
899 mWave_N106.nOutput[i] =
900 mWave_N106.nRAM[mWave_N106.nWavePos[i]];
902 if(!mWave_N106.nOutput[i])
904 mWave_N106.nPopCheck[i] = 0;
905 mWave_N106.nVolume[i] = mWave_N106.nPreVolume[i];
912 /****************** VRC6 ******************/
914 #ifdef ICODE_INSTEAD_OF_INLINE
915 void Wave_VRC6_DoTicks(const int32_t ticks) ICODE_ATTR;
916 void Wave_VRC6_DoTicks(const int32_t ticks)
917 #else
918 inline void Wave_VRC6_DoTicks(const int32_t ticks);
919 inline void Wave_VRC6_DoTicks(const int32_t ticks)
920 #endif
922 register int32_t i;
924 for(i = 0; i < 2; i++) {
926 if(mWave_VRC6Pulse[i].bChannelEnabled) {
928 mWave_VRC6Pulse[i].nFreqCount -= ticks;
930 if(mWave_VRC6Pulse[i].nDutyCount <=
931 mWave_VRC6Pulse[i].nDutyCycle)
933 mWave_VRC6Pulse[i].nMixL =
934 VRC6Pulse_nOutputTable_L[mWave_VRC6Pulse[i].nVolume];
936 else
937 mWave_VRC6Pulse[i].nMixL = 0;
939 while(mWave_VRC6Pulse[i].nFreqCount <= 0) {
940 mWave_VRC6Pulse[i].nFreqCount +=
941 mWave_VRC6Pulse[i].nFreqTimer.W + 1;
943 if(!mWave_VRC6Pulse[i].bDigitized)
944 mWave_VRC6Pulse[i].nDutyCount =
945 (mWave_VRC6Pulse[i].nDutyCount + 1) & 0x0F;
950 if(mWave_VRC6Saw.bChannelEnabled) {
952 mWave_VRC6Saw.nFreqCount -= ticks;
954 mWave_VRC6Saw.nMixL =
955 VRC6Saw_nOutputTable_L[mWave_VRC6Saw.nAccum >> 3];
957 while(mWave_VRC6Saw.nFreqCount <= 0) {
959 mWave_VRC6Saw.nFreqCount += mWave_VRC6Saw.nFreqTimer.W + 1;
961 mWave_VRC6Saw.nAccumStep++;
962 if(mWave_VRC6Saw.nAccumStep == 14)
964 mWave_VRC6Saw.nAccumStep = 0;
965 mWave_VRC6Saw.nAccum = 0;
967 else if(!(mWave_VRC6Saw.nAccumStep & 1))
968 mWave_VRC6Saw.nAccum += mWave_VRC6Saw.nAccumRate;
973 /****************** Square waves ******************/
975 /* decay */
976 #ifdef ICODE_INSTEAD_OF_INLINE
977 void Wave_Squares_ClockMajor(void) ICODE_ATTR;
978 void Wave_Squares_ClockMajor()
979 #else
980 inline void Wave_Squares_ClockMajor(void);
981 inline void Wave_Squares_ClockMajor()
982 #endif
984 if(mWave_Squares.nDecayCount[0])
985 mWave_Squares.nDecayCount[0]--;
986 else
988 mWave_Squares.nDecayCount[0] = mWave_Squares.nDecayTimer[0];
989 if(mWave_Squares.nDecayVolume[0])
990 mWave_Squares.nDecayVolume[0]--;
991 else
993 if(mWave_Squares.bDecayLoop[0])
994 mWave_Squares.nDecayVolume[0] = 0x0F;
997 if(mWave_Squares.bDecayEnable[0])
998 mWave_Squares.nVolume[0] = mWave_Squares.nDecayVolume[0];
1001 if(mWave_Squares.nDecayCount[1])
1002 mWave_Squares.nDecayCount[1]--;
1003 else
1005 mWave_Squares.nDecayCount[1] = mWave_Squares.nDecayTimer[1];
1006 if(mWave_Squares.nDecayVolume[1])
1007 mWave_Squares.nDecayVolume[1]--;
1008 else
1010 if(mWave_Squares.bDecayLoop[1])
1011 mWave_Squares.nDecayVolume[1] = 0x0F;
1014 if(mWave_Squares.bDecayEnable[1])
1015 mWave_Squares.nVolume[1] = mWave_Squares.nDecayVolume[1];
1021 #ifdef ICODE_INSTEAD_OF_INLINE
1022 void Wave_Squares_CheckSweepForcedSilence(const int32_t i) ICODE_ATTR;
1023 void Wave_Squares_CheckSweepForcedSilence(const int32_t i)
1024 #else
1025 inline void Wave_Squares_CheckSweepForcedSilence(const int32_t i);
1026 inline void Wave_Squares_CheckSweepForcedSilence(const int32_t i)
1027 #endif
1029 if(mWave_Squares.nFreqTimer[i].W < 8) {
1030 mWave_Squares.bSweepForceSilence[i] = 1; return;
1032 if(!mWave_Squares.bSweepMode[i] &&
1033 (( mWave_Squares.nFreqTimer[i].W +
1034 (mWave_Squares.nFreqTimer[i].W >> mWave_Squares.nSweepShift[i]))
1035 >= 0x0800)) { mWave_Squares.bSweepForceSilence[i] = 1; return; }
1037 mWave_Squares.bSweepForceSilence[i] = 0;
1040 /* sweep / length */
1041 #ifdef ICODE_INSTEAD_OF_INLINE
1042 void Wave_Squares_ClockMinor(void) ICODE_ATTR;
1043 void Wave_Squares_ClockMinor()
1044 #else
1045 inline void Wave_Squares_ClockMinor(void);
1046 inline void Wave_Squares_ClockMinor()
1047 #endif
1049 /* unrolled a little loop
1050 static int i = 0;
1051 for(i = 0; i < 2; i++)
1054 if(mWave_Squares.bLengthEnabled[0] && mWave_Squares.nLengthCount[0])
1055 mWave_Squares.nLengthCount[0]--;
1057 if(!mWave_Squares.bSweepEnable[0] || !mWave_Squares.nLengthCount[0] ||
1058 mWave_Squares.bSweepForceSilence[0] || !mWave_Squares.nSweepShift[0])
1059 goto other_square;
1061 if(mWave_Squares.nSweepCount[0])
1062 mWave_Squares.nSweepCount[0]--;
1063 else
1065 mWave_Squares.nSweepCount[0] = mWave_Squares.nSweepTimer[0];
1066 if(mWave_Squares.bSweepMode[0]) mWave_Squares.nFreqTimer[0].W -=
1067 (mWave_Squares.nFreqTimer[0].W >> mWave_Squares.nSweepShift[0])+1;
1068 else mWave_Squares.nFreqTimer[0].W +=
1069 (mWave_Squares.nFreqTimer[0].W >> mWave_Squares.nSweepShift[0]);
1071 Wave_Squares_CheckSweepForcedSilence(0);
1074 /* */
1075 other_square:
1076 if(mWave_Squares.bLengthEnabled[1] && mWave_Squares.nLengthCount[1])
1077 mWave_Squares.nLengthCount[1]--;
1079 if(!mWave_Squares.bSweepEnable[1] || !mWave_Squares.nLengthCount[1] ||
1080 mWave_Squares.bSweepForceSilence[1] || !mWave_Squares.nSweepShift[1])
1081 return;
1083 if(mWave_Squares.nSweepCount[1])
1084 mWave_Squares.nSweepCount[1]--;
1085 else
1087 mWave_Squares.nSweepCount[1] = mWave_Squares.nSweepTimer[1];
1088 if(mWave_Squares.bSweepMode[1]) mWave_Squares.nFreqTimer[1].W -=
1089 (mWave_Squares.nFreqTimer[1].W >> mWave_Squares.nSweepShift[1]);
1090 else mWave_Squares.nFreqTimer[1].W +=
1091 (mWave_Squares.nFreqTimer[1].W >> mWave_Squares.nSweepShift[1]);
1093 Wave_Squares_CheckSweepForcedSilence(1);
1097 /****************** Triangle/noise/DMC ******************/
1099 /* decay (noise), linear (tri) */
1101 #ifdef ICODE_INSTEAD_OF_INLINE
1102 void Wave_TND_ClockMajor(void) ICODE_ATTR;
1103 void Wave_TND_ClockMajor()
1104 #else
1105 inline void Wave_TND_ClockMajor(void);
1106 inline void Wave_TND_ClockMajor()
1107 #endif
1109 /* noise's decay */
1110 if(mWave_TND.nNoiseDecayCount)
1111 mWave_TND.nNoiseDecayCount--;
1112 else
1114 mWave_TND.nNoiseDecayCount = mWave_TND.nNoiseDecayTimer;
1115 if(mWave_TND.nNoiseDecayVolume)
1116 mWave_TND.nNoiseDecayVolume--;
1117 else
1119 if(mWave_TND.bNoiseDecayLoop)
1120 mWave_TND.nNoiseDecayVolume = 0x0F;
1123 if(mWave_TND.bNoiseDecayEnable)
1124 mWave_TND.nNoiseVolume = mWave_TND.nNoiseDecayVolume;
1127 /* triangle's linear */
1128 if(mWave_TND.bTriLinearHalt)
1129 mWave_TND.nTriLinearCount = mWave_TND.nTriLinearLoad;
1130 else if(mWave_TND.nTriLinearCount)
1131 mWave_TND.nTriLinearCount--;
1133 if(!mWave_TND.bTriLinearControl)
1134 mWave_TND.bTriLinearHalt = 0;
1137 /* length */
1139 #ifdef ICODE_INSTEAD_OF_INLINE
1140 void Wave_TND_ClockMinor(void) ICODE_ATTR;
1141 void Wave_TND_ClockMinor()
1142 #else
1143 inline void Wave_TND_ClockMinor(void);
1144 inline void Wave_TND_ClockMinor()
1145 #endif
1147 if(mWave_TND.bNoiseLengthEnabled && mWave_TND.nNoiseLengthCount)
1148 mWave_TND.nNoiseLengthCount--;
1150 if(mWave_TND.bTriLengthEnabled && mWave_TND.nTriLengthCount)
1151 mWave_TND.nTriLengthCount--;
1154 /*#undef this*/
1156 /****************** NSF Core ******************/
1158 /* start globals */
1161 * Memory
1163 /* RAM: 0x0000 - 0x07FF */
1164 uint8_t pRAM[0x800] IDATA_ATTR;
1165 /* SRAM: 0x6000 - 0x7FFF (non-FDS only) */
1166 uint8_t pSRAM[0x2000];
1167 /* ExRAM: 0x5C00 - 0x5FF5 (MMC5 only)
1168 * Also holds NSF player code (at 0x5000 - 0x500F) */
1169 uint8_t pExRAM[0x1000];
1170 /* Full ROM buffer */
1171 uint8_t* pROM_Full IDATA_ATTR;
1173 uint16_t main_nOutputTable_L[0x8000];
1175 uint8_t* pROM[10] IDATA_ATTR;/* ROM banks (point to areas in pROM_Full) */
1176 /* 0x8000 - 0xFFFF */
1177 /* also includes 0x6000 - 0x7FFF (FDS only) */
1178 uint8_t* pStack; /* the stack (points to areas in pRAM) */
1179 /* 0x0100 - 0x01FF */
1181 int32_t nROMSize; /* size of this ROM file in bytes */
1182 int32_t nROMBankCount; /* max number of 4k banks */
1183 int32_t nROMMaxSize; /* size of allocated pROM_Full buffer */
1186 * Memory Proc Pointers
1189 typedef uint8_t ( *ReadProc)(uint16_t);
1190 typedef void ( *WriteProc)(uint16_t,uint8_t);
1191 ReadProc ReadMemory[0x10] IDATA_ATTR;
1192 WriteProc WriteMemory[0x10] IDATA_ATTR;
1195 * 6502 Registers / Mode
1198 uint8_t regA IDATA_ATTR; /* Accumulator */
1199 uint8_t regX IDATA_ATTR; /* X-Index */
1200 uint8_t regY IDATA_ATTR; /* Y-Index */
1201 uint8_t regP IDATA_ATTR; /* Processor Status */
1202 uint8_t regSP IDATA_ATTR; /* Stack Pointer */
1203 uint16_t regPC IDATA_ATTR; /* Program Counter */
1205 uint8_t bPALMode IDATA_ATTR;/* 1 if in PAL emulation mode, 0 if in NTSC */
1206 uint8_t bCPUJammed IDATA_ATTR; /* 0 = not jammed. 1 = really jammed.
1207 * 2 = 'fake' jammed */
1208 /* fake jam caused by the NSF code to signal
1209 * the end of the play/init routine */
1211 /* Multiplication Register, for MMC5 chip only (5205+5206) */
1212 uint8_t nMultIn_Low;
1213 uint8_t nMultIn_High;
1216 * NSF Preparation Information
1219 uint8_t nBankswitchInitValues[10]; /* banks to swap to on tune init */
1220 uint16_t nPlayAddress; /* Play routine address */
1221 uint16_t nInitAddress; /* Init routine address */
1223 uint8_t nExternalSound; /* external sound chips */
1224 uint8_t nCurTrack;
1226 float fNSFPlaybackSpeed;
1229 * pAPU
1232 uint8_t nFrameCounter; /* Frame Sequence Counter */
1233 uint8_t nFrameCounterMax; /* Frame Sequence Counter Size
1234 (3 or 4 depending on $4017.7) */
1235 uint8_t bFrameIRQEnabled; /* TRUE if frame IRQs are enabled */
1236 uint8_t bFrameIRQPending; /* TRUE if the frame sequencer is holding down
1237 an IRQ */
1239 uint8_t nFME07_Address;
1242 * Timing and Counters
1244 /* fixed point -15.16 */
1246 int32_t nTicksUntilNextFrame;
1247 int32_t nTicksPerPlay;
1248 int32_t nTicksUntilNextPlay;
1249 int32_t nTicksPerSample;
1250 int32_t nTicksUntilNextSample;
1252 uint32_t nCPUCycle IDATA_ATTR;
1253 uint32_t nAPUCycle IDATA_ATTR;
1256 uint32_t nTotalPlays; /* number of times the play subroutine has been called
1257 (for tracking output time) */
1259 * Silence Tracker
1261 int32_t nSilentSamples;
1262 int32_t nSilentSampleMax;
1263 int32_t nSilenceTrackMS;
1264 uint8_t bNoSilenceIfTime;
1265 uint8_t bTimeNotDefault;
1268 * Sound output options
1270 const int32_t nSampleRate=44100;
1273 * Volume/fading/filter tracking
1276 uint32_t nStartFade; /* play call to start fading out */
1277 uint32_t nEndFade; /* play call to stop fading out (song is over) */
1278 uint8_t bFade; /* are we fading? */
1279 float fFadeVolume;
1280 float fFadeChange;
1283 * Designated Output Buffer
1285 uint8_t* pOutput IDATA_ATTR;
1287 const uint8_t bDMCPopReducer=1;
1288 uint8_t nDMCPop_Prev IDATA_ATTR = 0;
1289 uint8_t bDMCPop_Skip IDATA_ATTR = 0;
1290 uint8_t bDMCPop_SamePlay IDATA_ATTR = 0;
1292 const uint8_t nForce4017Write=0;
1293 const uint8_t bN106PopReducer=0;
1294 const uint8_t bIgnore4011Writes=0;
1296 const uint8_t bIgnoreBRK=0;
1297 const uint8_t bIgnoreIllegalOps=0;
1298 const uint8_t bNoWaitForReturn=0;
1299 const uint8_t bPALPreference=0;
1300 const uint8_t bCleanAXY=0;
1301 const uint8_t bResetDuty=0;
1304 * Sound Filter
1307 int64_t nFilterAccL IDATA_ATTR;
1308 int64_t nHighPass IDATA_ATTR;
1310 int32_t nHighPassBase IDATA_ATTR;
1312 uint8_t bHighPassEnabled IDATA_ATTR;
1314 /* end globals */
1316 #define CLOCK_MAJOR() { Wave_Squares_ClockMajor(); Wave_TND_ClockMajor(); }
1317 #define CLOCK_MINOR() { Wave_Squares_ClockMinor(); Wave_TND_ClockMinor(); }
1319 #define EXTSOUND_VRC6 0x01
1320 #define EXTSOUND_VRC7 0x02
1321 #define EXTSOUND_FDS 0x04
1322 #define EXTSOUND_MMC5 0x08
1323 #define EXTSOUND_N106 0x10
1324 #define EXTSOUND_FME07 0x20
1326 #define SILENCE_THRESHOLD 3
1329 * prototypes
1332 uint32_t Emulate6502(uint32_t runto) ICODE_ATTR;
1333 void EmulateAPU(uint8_t bBurnCPUCycles) ICODE_ATTR;
1335 int NSFCore_Initialize(void); /* 1 = initialized ok,
1336 0 = couldn't initialize (memory allocation error) */
1339 * Song Loading
1341 int LoadNSF(int32_t); /* grab data from an existing file
1342 1 = loaded ok, 0 = error loading */
1345 * Track Control
1347 void SetTrack(uint8_t track); /* Change tracks */
1350 * Getting Samples
1352 /* fill a buffer with samples */
1353 int32_t GetSamples(uint8_t* buffer, int32_t buffersize);
1356 * Playback options
1358 /* Set desired playback options (0 = bad options couldn't be set) */
1359 int SetPlaybackOptions(int32_t samplerate);
1360 /* Speed throttling (0 = uses NSF specified speed) */
1361 void SetPlaybackSpeed(float playspersec);
1363 float GetPlaybackSpeed(void);
1364 float GetMasterVolume(void);
1367 * Seeking
1369 /* gets the number of 'play' routine calls executed */
1370 float GetPlayCalls(void);
1372 /* gets the output time (based on the given play rate,
1373 if basedplayspersec is zero, current playback speed is used */
1374 uint32_t GetWrittenTime(float basedplayspersec);
1375 /* sets the number of 'plays' routines executed (for precise seeking) */
1376 void SetPlayCalls(float plays);
1377 /* sets the written time (approx. seeking) */
1378 void SetWrittenTime(uint32_t ms,float basedplays);
1381 * Fading
1384 void StopFade(void); /* stops all fading (plays indefinitely) */
1385 uint8_t SongCompleted(void); /* song has faded out (samples have stopped
1386 being generated) */
1387 /* parameters are play calls */
1388 void SetFade(int32_t fadestart,int32_t fadestop,uint8_t bNotDefault);
1389 void SetFadeTime(uint32_t fadestart,uint32_t fadestop,float basedplays,
1390 uint8_t bNotDefault); /* parameters are in milliseconds */
1393 * Internal Functions
1395 void RebuildOutputTables(void);
1396 void RecalculateFade(void); /* called when fade status is changed. */
1397 void RecalcFilter(void);
1398 void RecalcSilenceTracker(void);
1400 void WriteMemory_VRC6(uint16_t a,uint8_t v) ICODE_ATTR;
1401 void WriteMemory_MMC5(uint16_t a,uint8_t v) ICODE_ATTR;
1402 void WriteMemory_N106(uint16_t a,uint8_t v) ICODE_ATTR;
1403 void WriteMemory_FME07(uint16_t a,uint8_t v) ICODE_ATTR;
1406 * Memory Read/Write routines
1409 uint8_t ReadMemory_RAM(uint16_t a) ICODE_ATTR;
1410 uint8_t ReadMemory_ExRAM(uint16_t a) ICODE_ATTR;
1411 uint8_t ReadMemory_SRAM(uint16_t a) ICODE_ATTR;
1412 uint8_t ReadMemory_pAPU(uint16_t a) ICODE_ATTR;
1413 uint8_t ReadMemory_ROM(uint16_t a) ICODE_ATTR;
1414 uint8_t ReadMemory_Default(uint16_t a) ICODE_ATTR;
1416 uint8_t ReadMemory_N106(uint16_t a) ICODE_ATTR;
1418 void WriteMemory_RAM(uint16_t a,uint8_t v) ICODE_ATTR;
1419 void WriteMemory_ExRAM(uint16_t a,uint8_t v) ICODE_ATTR;
1420 void WriteMemory_SRAM(uint16_t a,uint8_t v) ICODE_ATTR;
1421 void WriteMemory_pAPU(uint16_t a,uint8_t v) ICODE_ATTR;
1422 void WriteMemory_FDSRAM(uint16_t a,uint8_t v) ICODE_ATTR;
1423 void WriteMemory_Default(uint16_t a,uint8_t v) ICODE_ATTR;
1425 uint8_t ReadMemory_RAM(uint16_t a) { return pRAM[a & 0x07FF]; }
1426 uint8_t ReadMemory_ExRAM(uint16_t a) { return pExRAM[a & 0x0FFF]; }
1427 uint8_t ReadMemory_SRAM(uint16_t a) { return pSRAM[a & 0x1FFF]; }
1428 uint8_t ReadMemory_ROM(uint16_t a)
1429 { return pROM[(a >> 12) - 6][a & 0x0FFF]; }
1430 uint8_t ReadMemory_Default(uint16_t a) { return (a >> 8); }
1432 void WriteMemory_RAM(uint16_t a,uint8_t v)
1433 { pRAM[a & 0x07FF] = v; }
1434 void WriteMemory_ExRAM(uint16_t a,uint8_t v);
1435 void WriteMemory_SRAM(uint16_t a,uint8_t v)
1436 { pSRAM[a & 0x1FFF] = v; }
1437 void WriteMemory_FDSRAM(uint16_t a,uint8_t v)
1438 { pROM[(a >> 12) - 6][a & 0x0FFF] = v; }
1439 void WriteMemory_Default(uint16_t a,uint8_t v) { (void)a; (void)v; }
1442 /* Read Memory Procs */
1444 uint8_t ReadMemory_pAPU(uint16_t a)
1446 EmulateAPU(1);
1448 if(a == 0x4015)
1450 uint8_t ret = 0;
1451 if(mWave_Squares.nLengthCount[0]) ret |= 0x01;
1452 if(mWave_Squares.nLengthCount[1]) ret |= 0x02;
1453 if(mWave_TND.nTriLengthCount) ret |= 0x04;
1454 if(mWave_TND.nNoiseLengthCount) ret |= 0x08;
1455 if(mWave_TND.nDMCBytesRemaining) ret |= 0x10;
1457 if(bFrameIRQPending) ret |= 0x40;
1458 if(mWave_TND.bDMCIRQPending) ret |= 0x80;
1460 bFrameIRQPending = 0;
1461 return ret;
1464 if(!(nExternalSound & EXTSOUND_FDS)) return 0x40;
1465 if(bPALMode) return 0x40;
1467 if((a >= 0x4040) && (a <= 0x407F))
1468 return mWave_FDS.nWaveTable[a & 0x3F] | 0x40;
1469 if(a == 0x4090)
1470 return (mWave_FDS.nVolEnv_Gain & 0x3F) | 0x40;
1471 if(a == 0x4092)
1472 return (mWave_FDS.nSweep_Gain & 0x3F) | 0x40;
1474 return 0x40;
1477 uint8_t ReadMemory_N106(uint16_t a)
1479 if(a != 0x4800)
1480 return ReadMemory_pAPU(a);
1482 uint8_t ret = mWave_N106.nRAM[(mWave_N106.nCurrentAddress << 1)] |
1483 (mWave_N106.nRAM[(mWave_N106.nCurrentAddress << 1) + 1] << 4);
1484 if(mWave_N106.bAutoIncrement)
1485 mWave_N106.nCurrentAddress = (mWave_N106.nCurrentAddress + 1) & 0x7F;
1487 return ret;
1491 /* Write Memory Procs */
1493 void WriteMemory_ExRAM(uint16_t a,uint8_t v)
1495 if(a < 0x5FF6) /* Invalid */
1496 return;
1498 a -= 0x5FF6;
1500 /* Swap out banks */
1502 EmulateAPU(1);
1503 /* stop it from swapping to a bank that doesn't exist */
1504 if(v >= nROMBankCount)
1505 v = 0;
1507 pROM[a] = pROM_Full + (v << 12);
1509 /* Update the DMC's DMA pointer, as well */
1510 if(a >= 2)
1511 mWave_TND.pDMCDMAPtr[a - 2] = pROM[a];
1514 void WriteMemory_pAPU(uint16_t a,uint8_t v)
1516 EmulateAPU(1);
1517 switch(a)
1519 /* Square 1 */
1520 case 0x4000:
1521 mWave_Squares.nDutyCycle[0] = DUTY_CYCLE_TABLE[v >> 6];
1522 mWave_Squares.bLengthEnabled[0] =
1523 !(mWave_Squares.bDecayLoop[0] = (v & 0x20));
1524 mWave_Squares.bDecayEnable[0] = !(v & 0x10);
1525 mWave_Squares.nDecayTimer[0] = (v & 0x0F);
1527 if(!mWave_Squares.bDecayEnable[0])
1528 mWave_Squares.nVolume[0] = mWave_Squares.nDecayTimer[0];
1529 break;
1531 case 0x4001:
1532 mWave_Squares.bSweepEnable[0] = (v & 0x80);
1533 mWave_Squares.nSweepTimer[0] = (v & 0x70) >> 4;
1534 mWave_Squares.bSweepMode[0] = v & 0x08;
1535 mWave_Squares.nSweepShift[0] = v & 0x07;
1536 Wave_Squares_CheckSweepForcedSilence(0);
1537 break;
1539 case 0x4002:
1540 mWave_Squares.nFreqTimer[0].B.l = v;
1541 Wave_Squares_CheckSweepForcedSilence(0);
1542 break;
1544 case 0x4003:
1545 mWave_Squares.nFreqTimer[0].B.h = v & 0x07;
1546 Wave_Squares_CheckSweepForcedSilence(0);
1548 mWave_Squares.nDecayVolume[0] = 0x0F;
1550 if(mWave_Squares.bChannelEnabled[0])
1551 mWave_Squares.nLengthCount[0] = LENGTH_COUNTER_TABLE[v >> 3];
1553 if(bResetDuty)
1554 mWave_Squares.nDutyCount[0] = 0;
1555 break;
1558 /* Square 2 */
1559 case 0x4004:
1560 mWave_Squares.nDutyCycle[1] = DUTY_CYCLE_TABLE[v >> 6];
1561 mWave_Squares.bLengthEnabled[1] =
1562 !(mWave_Squares.bDecayLoop[1] = (v & 0x20));
1563 mWave_Squares.bDecayEnable[1] = !(v & 0x10);
1564 mWave_Squares.nDecayTimer[1] = (v & 0x0F);
1566 if(!mWave_Squares.bDecayEnable[1])
1567 mWave_Squares.nVolume[1] = mWave_Squares.nDecayTimer[1];
1568 break;
1570 case 0x4005:
1571 mWave_Squares.bSweepEnable[1] = (v & 0x80);
1572 mWave_Squares.nSweepTimer[1] = (v & 0x70) >> 4;
1573 mWave_Squares.bSweepMode[1] = v & 0x08;
1574 mWave_Squares.nSweepShift[1] = v & 0x07;
1575 Wave_Squares_CheckSweepForcedSilence(1);
1576 break;
1578 case 0x4006:
1579 mWave_Squares.nFreqTimer[1].B.l = v;
1580 Wave_Squares_CheckSweepForcedSilence(1);
1581 break;
1583 case 0x4007:
1584 mWave_Squares.nFreqTimer[1].B.h = v & 0x07;
1585 Wave_Squares_CheckSweepForcedSilence(1);
1587 mWave_Squares.nDecayVolume[1] = 0x0F;
1589 if(mWave_Squares.bChannelEnabled[1])
1590 mWave_Squares.nLengthCount[1] = LENGTH_COUNTER_TABLE[v >> 3];
1592 if(bResetDuty)
1593 mWave_Squares.nDutyCount[1] = 0;
1594 break;
1597 /* Triangle */
1598 case 0x4008:
1599 mWave_TND.nTriLinearLoad = v & 0x7F;
1600 mWave_TND.bTriLinearControl = v & 0x80;
1601 mWave_TND.bTriLengthEnabled = !(v & 0x80);
1602 break;
1604 case 0x400A:
1605 mWave_TND.nTriFreqTimer.B.l = v;
1606 break;
1608 case 0x400B:
1609 mWave_TND.nTriFreqTimer.B.h = v & 0x07;
1610 mWave_TND.bTriLinearHalt = 1;
1612 if(mWave_TND.bTriChannelEnabled)
1613 mWave_TND.nTriLengthCount = LENGTH_COUNTER_TABLE[v >> 3];
1614 break;
1616 /* Noise */
1617 case 0x400C:
1618 mWave_TND.bNoiseLengthEnabled =
1619 !(mWave_TND.bNoiseDecayLoop = (v & 0x20));
1620 mWave_TND.bNoiseDecayEnable = !(v & 0x10);
1621 mWave_TND.nNoiseDecayTimer = (v & 0x0F);
1623 if(mWave_TND.bNoiseDecayEnable)
1624 mWave_TND.nNoiseVolume = mWave_TND.nNoiseDecayVolume;
1625 else
1626 mWave_TND.nNoiseVolume = mWave_TND.nNoiseDecayTimer;
1627 break;
1629 case 0x400E:
1630 mWave_TND.nNoiseFreqTimer = NOISE_FREQ_TABLE[v & 0x0F];
1631 mWave_TND.bNoiseRandomMode = (v & 0x80) ? 6 : 1;
1632 break;
1634 case 0x400F:
1635 if(mWave_TND.bNoiseChannelEnabled)
1636 mWave_TND.nNoiseLengthCount = LENGTH_COUNTER_TABLE[v >> 3];
1638 mWave_TND.nNoiseDecayVolume = 0x0F;
1639 if(mWave_TND.bNoiseDecayEnable)
1640 mWave_TND.nNoiseVolume = 0x0F;
1641 break;
1643 /* DMC */
1644 case 0x4010:
1645 mWave_TND.bDMCLoop = v & 0x40;
1646 mWave_TND.bDMCIRQEnabled = v & 0x80;
1647 /* IRQ can't be pending if disabled */
1648 if(!mWave_TND.bDMCIRQEnabled)
1649 mWave_TND.bDMCIRQPending = 0;
1651 mWave_TND.nDMCFreqTimer = DMC_FREQ_TABLE[bPALMode][v & 0x0F];
1652 break;
1654 case 0x4011:
1655 if(bIgnore4011Writes)
1656 break;
1657 v &= 0x7F;
1658 if(bDMCPopReducer)
1660 if(bDMCPop_SamePlay)
1661 mWave_TND.nDMCOutput = v;
1662 else
1664 if(bDMCPop_Skip)
1666 bDMCPop_Skip = 0;
1667 break;
1669 if(nDMCPop_Prev == v) break;
1670 if(mWave_TND.nDMCOutput == v) break;
1671 mWave_TND.nDMCOutput = nDMCPop_Prev;
1672 nDMCPop_Prev = v;
1673 bDMCPop_SamePlay = 1;
1676 else
1677 mWave_TND.nDMCOutput = v;
1678 break;
1680 case 0x4012:
1681 mWave_TND.nDMCDMABank_Load = (v >> 6) | 0x04;
1682 mWave_TND.nDMCDMAAddr_Load = (v << 6) & 0x0FFF;
1683 break;
1685 case 0x4013:
1686 mWave_TND.nDMCLength = (v << 4) + 1;
1687 break;
1689 /* All / General Purpose */
1690 case 0x4015:
1691 mWave_TND.bDMCIRQPending = 0;
1693 if(v & 0x01){ mWave_Squares.bChannelEnabled[0] = 1; }
1694 else { mWave_Squares.bChannelEnabled[0] =
1695 mWave_Squares.nLengthCount[0] = 0; }
1696 if(v & 0x02){ mWave_Squares.bChannelEnabled[1] = 1; }
1697 else { mWave_Squares.bChannelEnabled[1] =
1698 mWave_Squares.nLengthCount[1] = 0; }
1699 if(v & 0x04){ mWave_TND.bTriChannelEnabled = 1; }
1700 else { mWave_TND.bTriChannelEnabled =
1701 mWave_TND.nTriLengthCount = 0; }
1702 if(v & 0x08){ mWave_TND.bNoiseChannelEnabled = 1; }
1703 else { mWave_TND.bNoiseChannelEnabled =
1704 mWave_TND.nNoiseLengthCount = 0; }
1706 if(v & 0x10)
1708 if(!mWave_TND.nDMCBytesRemaining)
1710 bDMCPop_Skip = 1;
1711 mWave_TND.nDMCDMAAddr = mWave_TND.nDMCDMAAddr_Load;
1712 mWave_TND.nDMCDMABank = mWave_TND.nDMCDMABank_Load;
1713 mWave_TND.nDMCBytesRemaining = mWave_TND.nDMCLength;
1714 mWave_TND.bDMCActive = 1;
1717 else
1718 mWave_TND.nDMCBytesRemaining = 0;
1719 break;
1721 case 0x4017:
1722 bFrameIRQEnabled = !(v & 0x40);
1723 bFrameIRQPending = 0;
1724 nFrameCounter = 0;
1725 nFrameCounterMax = (v & 0x80) ? 4 : 3;
1726 nTicksUntilNextFrame =
1727 (bPALMode ? PAL_FRAME_COUNTER_FREQ : NTSC_FRAME_COUNTER_FREQ)
1728 * 0x10000;
1730 CLOCK_MAJOR();
1731 if(v & 0x80) CLOCK_MINOR();
1732 break;
1735 if(!(nExternalSound & EXTSOUND_FDS)) return;
1736 if(bPALMode) return;
1738 /* FDS Sound registers */
1740 if(a < 0x4040) return;
1742 /* wave table */
1743 if(a <= 0x407F)
1745 if(mWave_FDS.bWaveWrite)
1746 mWave_FDS.nWaveTable[a - 0x4040] = v;
1748 else
1750 switch(a)
1752 case 0x4080:
1753 mWave_FDS.nVolEnv_Mode = (v >> 6);
1754 if(v & 0x80)
1756 mWave_FDS.nVolEnv_Gain = v & 0x3F;
1757 if(!mWave_FDS.nMainAddr)
1759 if(mWave_FDS.nVolEnv_Gain < 0x20)
1760 mWave_FDS.nVolume = mWave_FDS.nVolEnv_Gain;
1761 else mWave_FDS.nVolume = 0x20;
1764 mWave_FDS.nVolEnv_Decay = v & 0x3F;
1765 mWave_FDS.nVolEnv_Timer =
1766 ((mWave_FDS.nVolEnv_Decay + 1) * mWave_FDS.nEnvelopeSpeed * 8);
1768 mWave_FDS.bVolEnv_On = mWave_FDS.bEnvelopeEnable &&
1769 mWave_FDS.nEnvelopeSpeed && !(v & 0x80);
1770 break;
1772 case 0x4082:
1773 mWave_FDS.nFreq.B.l = v;
1774 mWave_FDS.bMain_On = mWave_FDS.nFreq.W && mWave_FDS.bEnabled &&
1775 !mWave_FDS.bWaveWrite;
1776 break;
1778 case 0x4083:
1779 mWave_FDS.bEnabled = !(v & 0x80);
1780 mWave_FDS.bEnvelopeEnable = !(v & 0x40);
1781 if(v & 0x80)
1783 if(mWave_FDS.nVolEnv_Gain < 0x20)
1784 mWave_FDS.nVolume = mWave_FDS.nVolEnv_Gain;
1785 else mWave_FDS.nVolume = 0x20;
1787 mWave_FDS.nFreq.B.h = v & 0x0F;
1788 mWave_FDS.bMain_On = mWave_FDS.nFreq.W && mWave_FDS.bEnabled &&
1789 !mWave_FDS.bWaveWrite;
1791 mWave_FDS.bVolEnv_On = mWave_FDS.bEnvelopeEnable &&
1792 mWave_FDS.nEnvelopeSpeed && !(mWave_FDS.nVolEnv_Mode & 2);
1793 mWave_FDS.bSweepEnv_On = mWave_FDS.bEnvelopeEnable &&
1794 mWave_FDS.nEnvelopeSpeed && !(mWave_FDS.nSweep_Mode & 2);
1795 break;
1798 case 0x4084:
1799 mWave_FDS.nSweep_Mode = v >> 6;
1800 if(v & 0x80)
1801 mWave_FDS.nSweep_Gain = v & 0x3F;
1802 mWave_FDS.nSweep_Decay = v & 0x3F;
1803 mWave_FDS.nSweep_Timer =
1804 ((mWave_FDS.nSweep_Decay + 1) * mWave_FDS.nEnvelopeSpeed * 8);
1805 mWave_FDS.bSweepEnv_On =
1806 mWave_FDS.bEnvelopeEnable && mWave_FDS.nEnvelopeSpeed &&
1807 !(v & 0x80);
1808 break;
1811 case 0x4085:
1812 if(v & 0x40) mWave_FDS.nSweepBias = (v & 0x3F) - 0x40;
1813 else mWave_FDS.nSweepBias = v & 0x3F;
1814 mWave_FDS.nLFO_Addr = 0;
1815 break;
1818 case 0x4086:
1819 mWave_FDS.nLFO_Freq.B.l = v;
1820 mWave_FDS.bLFO_On =
1821 mWave_FDS.bLFO_Enabled && mWave_FDS.nLFO_Freq.W;
1822 if(mWave_FDS.nLFO_Freq.W)
1823 mWave_FDS.nLFO_Timer = (0x10000<<14) / mWave_FDS.nLFO_Freq.W;
1824 break;
1826 case 0x4087:
1827 mWave_FDS.bLFO_Enabled = !(v & 0x80);
1828 mWave_FDS.nLFO_Freq.B.h = v & 0x0F;
1829 mWave_FDS.bLFO_On =
1830 mWave_FDS.bLFO_Enabled && mWave_FDS.nLFO_Freq.W;
1831 if(mWave_FDS.nLFO_Freq.W)
1832 mWave_FDS.nLFO_Timer = (0x10000<<14) / mWave_FDS.nLFO_Freq.W;
1833 break;
1835 case 0x4088:
1836 if(mWave_FDS.bLFO_Enabled) break;
1837 register int32_t i;
1838 for(i = 0; i < 62; i++)
1839 mWave_FDS.nLFO_Table[i] = mWave_FDS.nLFO_Table[i + 2];
1840 mWave_FDS.nLFO_Table[62] = mWave_FDS.nLFO_Table[63] = v & 7;
1841 break;
1843 case 0x4089:
1844 mWave_FDS.nMainVolume = v & 3;
1845 mWave_FDS.bWaveWrite = v & 0x80;
1846 mWave_FDS.bMain_On = mWave_FDS.nFreq.W && mWave_FDS.bEnabled &&
1847 !mWave_FDS.bWaveWrite;
1848 break;
1850 case 0x408A:
1851 mWave_FDS.nEnvelopeSpeed = v;
1852 mWave_FDS.bVolEnv_On =
1853 mWave_FDS.bEnvelopeEnable &&
1854 mWave_FDS.nEnvelopeSpeed && !(mWave_FDS.nVolEnv_Mode & 2);
1855 mWave_FDS.bSweepEnv_On =
1856 mWave_FDS.bEnvelopeEnable &&
1857 mWave_FDS.nEnvelopeSpeed && !(mWave_FDS.nSweep_Mode & 2);
1858 break;
1863 void WriteMemory_VRC6(uint16_t a,uint8_t v)
1865 EmulateAPU(1);
1867 if((a < 0xA000) && (nExternalSound & EXTSOUND_VRC7)) return;
1868 else if(nExternalSound & EXTSOUND_FDS)
1869 WriteMemory_FDSRAM(a,v);
1871 switch(a)
1873 /* Pulse 1 */
1874 case 0x9000:
1875 mWave_VRC6Pulse[0].nVolume = v & 0x0F;
1876 mWave_VRC6Pulse[0].nDutyCycle = (v >> 4) & 0x07;
1877 mWave_VRC6Pulse[0].bDigitized = v & 0x80;
1878 if(mWave_VRC6Pulse[0].bDigitized)
1879 mWave_VRC6Pulse[0].nDutyCount = 0;
1880 break;
1882 case 0x9001:
1883 mWave_VRC6Pulse[0].nFreqTimer.B.l = v;
1884 break;
1886 case 0x9002:
1887 mWave_VRC6Pulse[0].nFreqTimer.B.h = v & 0x0F;
1888 mWave_VRC6Pulse[0].bChannelEnabled = v & 0x80;
1889 break;
1892 /* Pulse 2 */
1893 case 0xA000:
1894 mWave_VRC6Pulse[1].nVolume = v & 0x0F;
1895 mWave_VRC6Pulse[1].nDutyCycle = (v >> 4) & 0x07;
1896 mWave_VRC6Pulse[1].bDigitized = v & 0x80;
1897 if(mWave_VRC6Pulse[1].bDigitized)
1898 mWave_VRC6Pulse[1].nDutyCount = 0;
1899 break;
1901 case 0xA001:
1902 mWave_VRC6Pulse[1].nFreqTimer.B.l = v;
1903 break;
1905 case 0xA002:
1906 mWave_VRC6Pulse[1].nFreqTimer.B.h = v & 0x0F;
1907 mWave_VRC6Pulse[1].bChannelEnabled = v & 0x80;
1908 break;
1910 /* Sawtooth */
1911 case 0xB000:
1912 mWave_VRC6Saw.nAccumRate = (v & 0x3F);
1913 break;
1915 case 0xB001:
1916 mWave_VRC6Saw.nFreqTimer.B.l = v;
1917 break;
1919 case 0xB002:
1920 mWave_VRC6Saw.nFreqTimer.B.h = v & 0x0F;
1921 mWave_VRC6Saw.bChannelEnabled = v & 0x80;
1922 break;
1926 void WriteMemory_MMC5(uint16_t a,uint8_t v)
1928 if((a <= 0x5015) && !bPALMode)
1930 /* no audio emulation */
1931 return;
1934 if(a == 0x5205)
1936 nMultIn_Low = v;
1937 goto multiply;
1939 if(a == 0x5206)
1941 nMultIn_High = v;
1942 multiply:
1943 a = nMultIn_Low * nMultIn_High;
1944 pExRAM[0x205] = a & 0xFF;
1945 pExRAM[0x206] = a >> 8;
1946 return;
1949 if(a < 0x5C00) return;
1951 pExRAM[a & 0x0FFF] = v;
1952 if(a >= 0x5FF6)
1953 WriteMemory_ExRAM(a,v);
1956 void WriteMemory_N106(uint16_t a,uint8_t v)
1958 if(a < 0x4800)
1960 WriteMemory_pAPU(a,v);
1961 return;
1964 if(a == 0xF800)
1966 mWave_N106.nCurrentAddress = v & 0x7F;
1967 mWave_N106.bAutoIncrement = (v & 0x80);
1968 return;
1971 if(a == 0x4800)
1973 EmulateAPU(1);
1974 mWave_N106.nRAM[mWave_N106.nCurrentAddress << 1] = v & 0x0F;
1975 mWave_N106.nRAM[(mWave_N106.nCurrentAddress << 1) + 1] = v >> 4;
1976 a = mWave_N106.nCurrentAddress;
1977 if(mWave_N106.bAutoIncrement)
1978 mWave_N106.nCurrentAddress =
1979 (mWave_N106.nCurrentAddress + 1) & 0x7F;
1981 #define N106REGWRITE(ch,r0,r1,r2,r3,r4) \
1982 case r0: if(mWave_N106.nFreqReg[ch].B.l == v) break; \
1983 mWave_N106.nFreqReg[ch].B.l = v; \
1984 mWave_N106.nFreqTimer[ch] = -1; \
1985 break; \
1986 case r1: if(mWave_N106.nFreqReg[ch].B.h == v) break; \
1987 mWave_N106.nFreqReg[ch].B.h = v; \
1988 mWave_N106.nFreqTimer[ch] = -1; \
1989 break; \
1990 case r2: if(mWave_N106.nFreqReg[ch].B.w != (v & 3)){ \
1991 mWave_N106.nFreqReg[ch].B.w = v & 0x03; \
1992 mWave_N106.nFreqTimer[ch] = -1;} \
1993 mWave_N106.nWaveSize[ch] = 0x20 - (v & 0x1C); \
1994 break; \
1995 case r3: mWave_N106.nWavePosStart[ch] = v; \
1996 break; \
1997 case r4: mWave_N106.nPreVolume[ch] = v & 0x0F; \
1998 if(!bN106PopReducer) \
1999 mWave_N106.nVolume[ch] = v & 0x0F
2001 switch(a)
2003 N106REGWRITE(0,0x40,0x42,0x44,0x46,0x47); break;
2004 N106REGWRITE(1,0x48,0x4A,0x4C,0x4E,0x4F); break;
2005 N106REGWRITE(2,0x50,0x52,0x54,0x56,0x57); break;
2006 N106REGWRITE(3,0x58,0x5A,0x5C,0x5E,0x5F); break;
2007 N106REGWRITE(4,0x60,0x62,0x64,0x66,0x67); break;
2008 N106REGWRITE(5,0x68,0x6A,0x6C,0x6E,0x6F); break;
2009 N106REGWRITE(6,0x70,0x72,0x74,0x76,0x77); break;
2010 N106REGWRITE(7,0x78,0x7A,0x7C,0x7E,0x7F);
2011 v = (v >> 4) & 7;
2012 if(mWave_N106.nActiveChannels == v) break;
2013 mWave_N106.nActiveChannels = v;
2014 mWave_N106.nFreqTimer[0] = -1;
2015 mWave_N106.nFreqTimer[1] = -1;
2016 mWave_N106.nFreqTimer[2] = -1;
2017 mWave_N106.nFreqTimer[3] = -1;
2018 mWave_N106.nFreqTimer[4] = -1;
2019 mWave_N106.nFreqTimer[5] = -1;
2020 mWave_N106.nFreqTimer[6] = -1;
2021 mWave_N106.nFreqTimer[7] = -1;
2022 break;
2024 #undef N106REGWRITE
2028 void WriteMemory_FME07(uint16_t a,uint8_t v)
2030 if((a < 0xD000) && (nExternalSound & EXTSOUND_FDS))
2031 WriteMemory_FDSRAM(a,v);
2033 if(a == 0xC000)
2034 nFME07_Address = v;
2035 if(a == 0xE000)
2037 switch(nFME07_Address)
2039 case 0x00: mWave_FME07[0].nFreqTimer.B.l = v; break;
2040 case 0x01: mWave_FME07[0].nFreqTimer.B.h = v & 0x0F; break;
2041 case 0x02: mWave_FME07[1].nFreqTimer.B.l = v; break;
2042 case 0x03: mWave_FME07[1].nFreqTimer.B.h = v & 0x0F; break;
2043 case 0x04: mWave_FME07[2].nFreqTimer.B.l = v; break;
2044 case 0x05: mWave_FME07[2].nFreqTimer.B.h = v & 0x0F; break;
2045 case 0x07:
2046 mWave_FME07[0].bChannelEnabled = !(v & 0x01);
2047 mWave_FME07[1].bChannelEnabled = !(v & 0x02);
2048 mWave_FME07[2].bChannelEnabled = !(v & 0x03);
2049 break;
2050 case 0x08: mWave_FME07[0].nVolume = v & 0x0F; break;
2051 case 0x09: mWave_FME07[1].nVolume = v & 0x0F; break;
2052 case 0x0A: mWave_FME07[2].nVolume = v & 0x0F; break;
2058 * Emulate APU
2061 int32_t fulltick;
2062 void EmulateAPU(uint8_t bBurnCPUCycles)
2064 int32_t tick;
2065 int64_t diff;
2067 int32_t tnd_out;
2068 int square_out1;
2069 int square_out2;
2071 ENTER_TIMER(apu);
2073 fulltick += (signed)(nCPUCycle - nAPUCycle);
2075 int32_t burned;
2076 int32_t mixL;
2078 if(bFade && nSilentSampleMax && (nSilentSamples >= nSilentSampleMax))
2079 fulltick = 0;
2081 while(fulltick>0)
2083 tick = (nTicksUntilNextSample+0xffff)>>16;
2085 fulltick -= tick;
2088 * Sample Generation
2091 ENTER_TIMER(squares);
2092 /* Square generation */
2094 mWave_Squares.nFreqCount[0] -= tick;
2095 mWave_Squares.nFreqCount[1] -= tick;
2097 if((mWave_Squares.nDutyCount[0] < mWave_Squares.nDutyCycle[0]) &&
2098 mWave_Squares.nLengthCount[0] &&
2099 !mWave_Squares.bSweepForceSilence[0])
2100 square_out1 = mWave_Squares.nVolume[0];
2101 else
2102 square_out1 = 0;
2104 if((mWave_Squares.nDutyCount[1] < mWave_Squares.nDutyCycle[1]) &&
2105 mWave_Squares.nLengthCount[1] &&
2106 !mWave_Squares.bSweepForceSilence[1])
2107 square_out2 = mWave_Squares.nVolume[1];
2108 else
2109 square_out2 = 0;
2111 mWave_Squares.nMixL = Squares_nOutputTable_L[square_out1][square_out2];
2113 if(mWave_Squares.nFreqCount[0]<=0)
2115 int cycles =
2116 (-mWave_Squares.nFreqCount[0])/
2117 (mWave_Squares.nFreqTimer[0].W + 1) + 1;
2118 mWave_Squares.nFreqCount[0] =
2119 (mWave_Squares.nFreqTimer[0].W + 1)-
2120 (-mWave_Squares.nFreqCount[0])%
2121 (mWave_Squares.nFreqTimer[0].W + 1);
2122 mWave_Squares.nDutyCount[0] =
2123 (mWave_Squares.nDutyCount[0]+cycles)%0x10;
2125 if(mWave_Squares.nFreqCount[1]<=0)
2127 int cycles =
2128 (-mWave_Squares.nFreqCount[1])/
2129 (mWave_Squares.nFreqTimer[1].W + 1) + 1;
2130 mWave_Squares.nFreqCount[1] =
2131 (mWave_Squares.nFreqTimer[1].W + 1)-
2132 (-mWave_Squares.nFreqCount[1])%
2133 (mWave_Squares.nFreqTimer[1].W + 1);
2134 mWave_Squares.nDutyCount[1] = (mWave_Squares.nDutyCount[1]+cycles)%
2135 0x10;
2137 /* end of Square generation */
2138 EXIT_TIMER(squares);
2139 ENTER_TIMER(tnd);
2141 ENTER_TIMER(tnd_enter);
2143 burned=0;
2145 /* TND generation */
2147 if(mWave_TND.nNoiseFreqTimer) mWave_TND.nNoiseFreqCount -= tick;
2149 if(mWave_TND.nTriFreqTimer.W > 8)
2150 mWave_TND.nTriFreqCount -= tick;
2152 tnd_out = mWave_TND.nTriOutput << 11;
2154 if(mWave_TND.bNoiseRandomOut && mWave_TND.nNoiseLengthCount)
2155 tnd_out |= mWave_TND.nNoiseVolume << 7;
2157 tnd_out |= mWave_TND.nDMCOutput;
2159 mWave_TND.nMixL = main_nOutputTable_L[tnd_out];
2161 EXIT_TIMER(tnd_enter);
2163 ENTER_TIMER(tnd_tri);
2165 /* Tri */
2167 if(mWave_TND.nTriFreqCount<=0)
2169 if(mWave_TND.nTriLengthCount && mWave_TND.nTriLinearCount)
2171 do mWave_TND.nTriStep++;
2172 while ((mWave_TND.nTriFreqCount +=
2173 mWave_TND.nTriFreqTimer.W + 1) <= 0);
2174 mWave_TND.nTriStep &= 0x1F;
2176 if(mWave_TND.nTriStep & 0x10)
2177 mWave_TND.nTriOutput = mWave_TND.nTriStep ^ 0x1F;
2178 else mWave_TND.nTriOutput = mWave_TND.nTriStep;
2179 } else mWave_TND.nTriFreqCount=mWave_TND.nTriFreqTimer.W+1;
2182 EXIT_TIMER(tnd_tri);
2184 ENTER_TIMER(tnd_noise);
2186 /* Noise */
2188 if(mWave_TND.nNoiseFreqTimer &&
2189 mWave_TND.nNoiseVolume && mWave_TND.nNoiseFreqCount<=0)
2191 mWave_TND.nNoiseFreqCount = mWave_TND.nNoiseFreqTimer;
2192 mWave_TND.nNoiseRandomShift <<= 1;
2193 mWave_TND.bNoiseRandomOut = (((mWave_TND.nNoiseRandomShift <<
2194 mWave_TND.bNoiseRandomMode) ^
2195 mWave_TND.nNoiseRandomShift) & 0x8000 ) ? 1 : 0;
2196 if(mWave_TND.bNoiseRandomOut)
2197 mWave_TND.nNoiseRandomShift |= 0x01;
2200 EXIT_TIMER(tnd_noise);
2202 ENTER_TIMER(tnd_dmc);
2204 /* DMC */
2205 if(mWave_TND.bDMCActive)
2207 mWave_TND.nDMCFreqCount -= tick;
2208 while (mWave_TND.nDMCFreqCount <= 0) {
2209 if (!mWave_TND.bDMCActive) {
2210 mWave_TND.nDMCFreqCount = mWave_TND.nDMCFreqTimer;
2211 break;
2214 mWave_TND.nDMCFreqCount += mWave_TND.nDMCFreqTimer;
2216 if(mWave_TND.bDMCSampleBufferEmpty &&
2217 mWave_TND.nDMCBytesRemaining)
2219 burned += 4; /* 4 cycle burn! */
2220 mWave_TND.nDMCSampleBuffer =
2221 mWave_TND.pDMCDMAPtr[mWave_TND.nDMCDMABank]
2222 [mWave_TND.nDMCDMAAddr];
2223 mWave_TND.nDMCDMAAddr++;
2224 if(mWave_TND.nDMCDMAAddr & 0x1000)
2226 mWave_TND.nDMCDMAAddr &= 0x0FFF;
2227 mWave_TND.nDMCDMABank =
2228 (mWave_TND.nDMCDMABank + 1) & 0x07;
2231 mWave_TND.bDMCSampleBufferEmpty = 0;
2232 mWave_TND.nDMCBytesRemaining--;
2233 if(!mWave_TND.nDMCBytesRemaining)
2235 if(mWave_TND.bDMCLoop)
2237 mWave_TND.nDMCDMABank = mWave_TND.nDMCDMABank_Load;
2238 mWave_TND.nDMCDMAAddr = mWave_TND.nDMCDMAAddr_Load;
2239 mWave_TND.nDMCBytesRemaining =mWave_TND.nDMCLength;
2241 else if(mWave_TND.bDMCIRQEnabled)
2242 mWave_TND.bDMCIRQPending = 1;
2246 if(!mWave_TND.nDMCDeltaBit)
2248 mWave_TND.nDMCDeltaBit = 8;
2249 mWave_TND.bDMCDeltaSilent =mWave_TND.bDMCSampleBufferEmpty;
2250 mWave_TND.nDMCDelta = mWave_TND.nDMCSampleBuffer;
2251 mWave_TND.bDMCSampleBufferEmpty = 1;
2254 if(mWave_TND.nDMCDeltaBit) {
2255 mWave_TND.nDMCDeltaBit--;
2256 if(!mWave_TND.bDMCDeltaSilent)
2258 if(mWave_TND.nDMCDelta & 0x01)
2260 if(mWave_TND.nDMCOutput < 0x7E)
2261 mWave_TND.nDMCOutput += 2;
2263 else if(mWave_TND.nDMCOutput > 1)
2264 mWave_TND.nDMCOutput -= 2;
2266 mWave_TND.nDMCDelta >>= 1;
2269 if(!mWave_TND.nDMCBytesRemaining &&
2270 mWave_TND.bDMCSampleBufferEmpty &&
2271 mWave_TND.bDMCDeltaSilent)
2272 mWave_TND.bDMCActive = mWave_TND.nDMCDeltaBit = 0;
2276 EXIT_TIMER(tnd_dmc);
2278 /* end of TND generation */
2279 EXIT_TIMER(tnd);
2281 if(nExternalSound && !bPALMode)
2283 if(nExternalSound & EXTSOUND_VRC6)
2284 Wave_VRC6_DoTicks(tick);
2285 if(nExternalSound & EXTSOUND_N106)
2286 Wave_N106_DoTicks(tick);
2287 if(nExternalSound & EXTSOUND_FME07)
2289 if (mWave_FME07[0].bChannelEnabled &&
2290 mWave_FME07[0].nFreqTimer.W) {
2291 mWave_FME07[0].nFreqCount -= tick;
2293 if(mWave_FME07[0].nDutyCount < 16)
2295 mWave_FME07[0].nMixL =
2296 FME07_nOutputTable_L[mWave_FME07[0].nVolume];
2297 } else mWave_FME07[0].nMixL = 0;
2298 while(mWave_FME07[0].nFreqCount <= 0) {
2299 mWave_FME07[0].nFreqCount +=
2300 mWave_FME07[0].nFreqTimer.W;
2302 mWave_FME07[0].nDutyCount=
2303 (mWave_FME07[0].nDutyCount+1)&0x1f;
2307 if (mWave_FME07[1].bChannelEnabled &&
2308 mWave_FME07[1].nFreqTimer.W) {
2309 mWave_FME07[1].nFreqCount -= tick;
2311 if(mWave_FME07[1].nDutyCount < 16)
2313 mWave_FME07[1].nMixL =
2314 FME07_nOutputTable_L[mWave_FME07[1].nVolume];
2315 } else mWave_FME07[1].nMixL = 0;
2316 while(mWave_FME07[1].nFreqCount <= 0) {
2317 mWave_FME07[1].nFreqCount +=
2318 mWave_FME07[1].nFreqTimer.W;
2320 mWave_FME07[1].nDutyCount=
2321 (mWave_FME07[1].nDutyCount+1)&0x1f;
2325 if (mWave_FME07[2].bChannelEnabled &&
2326 mWave_FME07[2].nFreqTimer.W) {
2327 mWave_FME07[2].nFreqCount -= tick;
2329 if(mWave_FME07[2].nDutyCount < 16)
2331 mWave_FME07[2].nMixL =
2332 FME07_nOutputTable_L[mWave_FME07[2].nVolume];
2333 } else mWave_FME07[2].nMixL = 0;
2334 while(mWave_FME07[2].nFreqCount <= 0) {
2335 mWave_FME07[2].nFreqCount +=
2336 mWave_FME07[2].nFreqTimer.W;
2338 mWave_FME07[2].nDutyCount=
2339 (mWave_FME07[2].nDutyCount+1)&0x1f;
2343 } /* end FME07 */
2344 ENTER_TIMER(fds);
2345 if(nExternalSound & EXTSOUND_FDS) {
2347 /* Volume Envelope Unit */
2348 if(mWave_FDS.bVolEnv_On)
2350 mWave_FDS.nVolEnv_Count -= tick;
2351 while(mWave_FDS.nVolEnv_Count <= 0)
2353 mWave_FDS.nVolEnv_Count += mWave_FDS.nVolEnv_Timer;
2354 if(mWave_FDS.nVolEnv_Mode) {
2355 if(mWave_FDS.nVolEnv_Gain < 0x20)
2356 mWave_FDS.nVolEnv_Gain++;
2358 else {
2359 if(mWave_FDS.nVolEnv_Gain)
2360 mWave_FDS.nVolEnv_Gain--;
2365 /* Sweep Envelope Unit */
2366 if(mWave_FDS.bSweepEnv_On)
2368 mWave_FDS.nSweep_Count -= tick;
2369 while(mWave_FDS.nSweep_Count <= 0)
2371 mWave_FDS.nSweep_Count += mWave_FDS.nSweep_Timer;
2372 if(mWave_FDS.nSweep_Mode) {
2373 if(mWave_FDS.nSweep_Gain < 0x20)
2374 mWave_FDS.nSweep_Gain++;
2375 } else {
2376 if(mWave_FDS.nSweep_Gain) mWave_FDS.nSweep_Gain--;
2381 /* Effector / LFO */
2382 int32_t subfreq = 0;
2383 if(mWave_FDS.bLFO_On)
2385 mWave_FDS.nLFO_Count -= tick<<14;
2386 while(mWave_FDS.nLFO_Count <= 0)
2388 mWave_FDS.nLFO_Count += mWave_FDS.nLFO_Timer;
2389 if(mWave_FDS.nLFO_Table[mWave_FDS.nLFO_Addr] == 4)
2390 mWave_FDS.nSweepBias = 0;
2391 else
2392 mWave_FDS.nSweepBias +=
2393 ModulationTable[
2394 mWave_FDS.nLFO_Table[mWave_FDS.nLFO_Addr]
2396 mWave_FDS.nLFO_Addr = (mWave_FDS.nLFO_Addr + 1) & 0x3F;
2399 while(mWave_FDS.nSweepBias > 63)
2400 mWave_FDS.nSweepBias -= 128;
2401 while(mWave_FDS.nSweepBias < -64)
2402 mWave_FDS.nSweepBias += 128;
2404 register int32_t temp =
2405 mWave_FDS.nSweepBias * mWave_FDS.nSweep_Gain;
2406 if(temp & 0x0F)
2408 temp /= 16;
2409 if(mWave_FDS.nSweepBias < 0) temp--;
2410 else temp += 2;
2412 else
2413 temp /= 16;
2415 if(temp > 193) temp -= 258;
2416 if(temp < -64) temp += 256;
2418 subfreq = mWave_FDS.nFreq.W * temp / 64;
2421 /* Main Unit */
2422 if(mWave_FDS.bMain_On)
2424 mWave_FDS.nMixL =
2425 FDS_nOutputTable_L[mWave_FDS.nMainVolume]
2426 [mWave_FDS.nVolume]
2427 [mWave_FDS.nWaveTable[mWave_FDS.nMainAddr] ];
2429 if((subfreq + mWave_FDS.nFreq.W) > 0)
2431 int32_t freq = (0x10000<<14) / (subfreq + mWave_FDS.nFreq.W);
2433 mWave_FDS.nFreqCount -= tick<<14;
2434 while(mWave_FDS.nFreqCount <= 0)
2436 mWave_FDS.nFreqCount += freq;
2438 mWave_FDS.nMainAddr =
2439 (mWave_FDS.nMainAddr + 1) & 0x3F;
2440 mWave_FDS.nPopOutput =
2441 mWave_FDS.nWaveTable[mWave_FDS.nMainAddr];
2442 if(!mWave_FDS.nMainAddr)
2444 if(mWave_FDS.nVolEnv_Gain < 0x20)
2445 mWave_FDS.nVolume = mWave_FDS.nVolEnv_Gain;
2446 else mWave_FDS.nVolume = 0x20;
2450 else
2451 mWave_FDS.nFreqCount = mWave_FDS.nLFO_Count;
2453 else if(mWave_FDS.bPopReducer && mWave_FDS.nPopOutput)
2455 mWave_FDS.nMixL = FDS_nOutputTable_L[mWave_FDS.nMainVolume]
2456 [mWave_FDS.nVolume]
2457 [mWave_FDS.nPopOutput];
2459 mWave_FDS.nPopCount -= tick;
2460 while(mWave_FDS.nPopCount <= 0)
2462 mWave_FDS.nPopCount += 500;
2463 mWave_FDS.nPopOutput--;
2464 if(!mWave_FDS.nPopOutput)
2465 mWave_FDS.nMainAddr = 0;
2467 } /* end FDS */
2469 EXIT_TIMER(fds);
2470 } /* end while fulltick */
2472 if(bBurnCPUCycles)
2474 nCPUCycle += burned;
2475 fulltick += burned;
2478 /* Frame Sequencer */
2480 ENTER_TIMER(frame);
2481 nTicksUntilNextFrame -= tick<<16;
2482 while(nTicksUntilNextFrame <= 0)
2484 nTicksUntilNextFrame +=
2485 (bPALMode ? PAL_FRAME_COUNTER_FREQ : NTSC_FRAME_COUNTER_FREQ) *
2486 0x10000;
2487 nFrameCounter++;
2488 if(nFrameCounter > nFrameCounterMax)
2489 nFrameCounter = 0;
2491 if(nFrameCounterMax == 4)
2493 if(nFrameCounter < 4)
2495 CLOCK_MAJOR();
2496 if(!(nFrameCounter & 1))
2497 CLOCK_MINOR();
2500 else
2502 CLOCK_MAJOR();
2503 if(nFrameCounter & 1)
2504 CLOCK_MINOR();
2506 if((nFrameCounter == 3) && bFrameIRQEnabled)
2507 bFrameIRQPending = 1;
2510 EXIT_TIMER(frame);
2512 ENTER_TIMER(mix);
2513 nTicksUntilNextSample -= tick<<16;
2514 if(nTicksUntilNextSample <= 0)
2516 nTicksUntilNextSample += nTicksPerSample;
2518 mixL = mWave_Squares.nMixL;
2519 mixL += mWave_TND.nMixL;
2521 if(nExternalSound && !bPALMode)
2523 if(nExternalSound & EXTSOUND_VRC6)
2525 mixL += (mWave_VRC6Pulse[0].nMixL);
2526 mixL += (mWave_VRC6Pulse[1].nMixL);
2527 mixL += (mWave_VRC6Saw.nMixL);
2529 if(nExternalSound & EXTSOUND_N106) {
2530 mixL += (mWave_N106.nMixL[0]);
2531 mixL += (mWave_N106.nMixL[1]);
2532 mixL += (mWave_N106.nMixL[2]);
2533 mixL += (mWave_N106.nMixL[3]);
2534 mixL += (mWave_N106.nMixL[4]);
2535 mixL += (mWave_N106.nMixL[5]);
2536 mixL += (mWave_N106.nMixL[6]);
2537 mixL += (mWave_N106.nMixL[7]);
2539 if(nExternalSound & EXTSOUND_FME07)
2541 mixL += (mWave_FME07[0].nMixL);
2542 mixL += (mWave_FME07[1].nMixL);
2543 mixL += (mWave_FME07[2].nMixL);
2545 if(nExternalSound & EXTSOUND_FDS)
2546 mixL += mWave_FDS.nMixL;
2549 /* Filter */
2550 diff = ((int64_t)mixL << 25) - nFilterAccL;
2551 nFilterAccL += (diff * nHighPass) >> 16;
2552 mixL = (int32_t)(diff >> 23);
2553 /* End Filter */
2555 if(bFade && (fFadeVolume < 1))
2556 mixL = (int32_t)(mixL * fFadeVolume);
2558 if(mixL < -32768) mixL = -32768;
2559 if(mixL > 32767) mixL = 32767;
2561 *((uint16_t*)pOutput) = (uint16_t)mixL;
2562 pOutput += 2;
2566 EXIT_TIMER(mix);
2568 nAPUCycle = nCPUCycle;
2570 EXIT_TIMER(apu);
2575 * Initialize
2577 * Initializes Memory
2580 int NSFCore_Initialize()
2582 int32_t i;
2583 /* clear globals */
2584 /* why, yes, this was easier when they were in a struct */
2587 * Memory
2590 ZEROMEMORY(pRAM,0x800);
2591 ZEROMEMORY(pSRAM,0x2000);
2592 ZEROMEMORY(pExRAM,0x1000);
2593 pROM_Full=0;
2595 ZEROMEMORY(pROM,10);
2596 pStack=0;
2598 nROMSize=0;
2599 nROMBankCount=0;
2600 nROMMaxSize=0;
2603 * Memory Proc Pointers
2606 ZEROMEMORY(ReadMemory,sizeof(ReadProc)*0x10);
2607 ZEROMEMORY(WriteMemory,sizeof(WriteProc)*0x10);
2610 * 6502 Registers / Mode
2613 regA=0;
2614 regX=0;
2615 regY=0;
2616 regP=0;
2617 regSP=0;
2618 regPC=0;
2620 bPALMode=0;
2621 bCPUJammed=0;
2623 nMultIn_Low=0;
2624 nMultIn_High=0;
2627 * NSF Preparation Information
2630 ZEROMEMORY(nBankswitchInitValues,10);
2631 nPlayAddress=0;
2632 nInitAddress=0;
2634 nExternalSound=0;
2635 nCurTrack=0;
2637 fNSFPlaybackSpeed=0;
2640 * pAPU
2643 nFrameCounter=0;
2644 nFrameCounterMax=0;
2645 bFrameIRQEnabled=0;
2646 bFrameIRQPending=0;
2649 * Timing and Counters
2651 nTicksUntilNextFrame=0;
2653 nTicksPerPlay=0;
2654 nTicksUntilNextPlay=0;
2656 nTicksPerSample=0;
2657 nTicksUntilNextSample=0;
2659 nCPUCycle=0;
2660 nAPUCycle=0;
2661 nTotalPlays=0;
2664 * Silence Tracker
2666 nSilentSamples=0;
2667 nSilentSampleMax=0;
2668 nSilenceTrackMS=0;
2669 bNoSilenceIfTime=0;
2670 bTimeNotDefault=0;
2673 * Volume/fading/filter tracking
2676 nStartFade=0;
2677 nEndFade=0;
2678 bFade=0;
2679 fFadeVolume=0;
2680 fFadeChange=0;
2682 pOutput=0;
2684 nDMCPop_Prev=0;
2685 bDMCPop_Skip=0;
2686 bDMCPop_SamePlay=0;
2689 * Sound Filter
2692 nFilterAccL=0;
2693 nHighPass=0;
2695 nHighPassBase=0;
2697 bHighPassEnabled=0;
2699 /* channels */
2701 ZEROMEMORY(&mWave_Squares,sizeof(struct Wave_Squares));
2702 ZEROMEMORY(&mWave_TND,sizeof(struct Wave_TND));
2703 ZEROMEMORY(mWave_VRC6Pulse,sizeof(struct VRC6PulseWave)*2);
2704 ZEROMEMORY(&mWave_VRC6Saw,sizeof(struct VRC6SawWave));
2705 ZEROMEMORY(&mWave_N106,sizeof(struct N106Wave));
2706 ZEROMEMORY(mWave_FME07,sizeof(struct FME07Wave)*3);
2707 ZEROMEMORY(&mWave_FDS,sizeof(struct FDSWave));
2709 /* end clear globals */
2711 // Default filter bases
2712 nHighPassBase = 150;
2714 bHighPassEnabled = 1;
2716 mWave_TND.nNoiseRandomShift = 1;
2717 for(i = 0; i < 8; i++)
2718 mWave_TND.pDMCDMAPtr[i] = pROM[i + 2];
2721 SetPlaybackOptions(nSampleRate);
2723 for(i = 0; i < 8; i++)
2724 mWave_N106.nFrequencyLookupTable[i] =
2725 ((((i + 1) * 45 * 0x40000) / (float)NES_FREQUENCY) *
2726 (float)NTSC_FREQUENCY) * 256.0;
2728 ZEROMEMORY(pRAM,0x800);
2729 ZEROMEMORY(pSRAM,0x2000);
2730 ZEROMEMORY(pExRAM,0x1000);
2731 pStack = pRAM + 0x100;
2732 return 1;
2736 * LoadNSF
2739 int LoadNSF(int32_t datasize)
2741 if(!pDataBuffer) return 0;
2743 int32_t i;
2745 nExternalSound = nChipExtensions;
2746 if(nIsPal & 2)
2747 bPALMode = bPALPreference;
2748 else
2749 bPALMode = nIsPal & 1;
2751 SetPlaybackOptions(nSampleRate);
2753 int32_t neededsize = datasize + (nfileLoadAddress & 0x0FFF);
2754 if(neededsize & 0x0FFF) neededsize += 0x1000 - (neededsize & 0x0FFF);
2755 if(neededsize < 0x1000) neededsize = 0x1000;
2757 uint8_t specialload = 0;
2759 for(i = 0; (i < 8) && (!nBankswitch[i]); i++);
2760 if(i < 8) /* uses bankswitching */
2762 memcpy(&nBankswitchInitValues[2],nBankswitch,8);
2763 nBankswitchInitValues[0] = nBankswitch[6];
2764 nBankswitchInitValues[1] = nBankswitch[7];
2765 if(nExternalSound & EXTSOUND_FDS)
2767 if(!(nBankswitchInitValues[0] || nBankswitchInitValues[1]))
2770 * FDS sound with '00' specified for both $6000 and $7000 banks.
2771 * point this to an area of fresh RAM (sort of hackish solution
2772 * for those FDS tunes that don't quite follow the nsf specs.
2774 nBankswitchInitValues[0] = (uint8_t)(neededsize >> 12);
2775 nBankswitchInitValues[1] = (uint8_t)(neededsize >> 12) + 1;
2776 neededsize += 0x2000;
2780 else /* doesn't use bankswitching */
2782 if(nExternalSound & EXTSOUND_FDS)
2784 /* bad load address */
2785 if(nfileLoadAddress < 0x6000) return 0;
2787 if(neededsize < 0xA000)
2788 neededsize = 0xA000;
2789 specialload = 1;
2790 for(i = 0; i < 10; i++)
2791 nBankswitchInitValues[i] = (uint8_t)i;
2793 else
2795 /* bad load address */
2796 if(nfileLoadAddress < 0x8000) return 0;
2798 int32_t j = (nfileLoadAddress >> 12) - 6;
2799 for(i = 0; i < j; i++)
2800 nBankswitchInitValues[i] = 0;
2801 for(j = 0; i < 10; i++, j++)
2802 nBankswitchInitValues[i] = (uint8_t)j;
2806 nROMSize = neededsize;
2807 nROMBankCount = neededsize >> 12;
2809 if(specialload)
2810 pROM_Full = pDataBuffer-(nfileLoadAddress-0x6000);
2811 else
2812 pROM_Full = pDataBuffer-(nfileLoadAddress&0x0FFF);
2814 ZEROMEMORY(pRAM,0x0800);
2815 ZEROMEMORY(pExRAM,0x1000);
2816 ZEROMEMORY(pSRAM,0x2000);
2818 nExternalSound = nChipExtensions;
2819 fNSFPlaybackSpeed = (bPALMode ? PAL_NMIRATE : NTSC_NMIRATE);
2821 SetPlaybackSpeed(0);
2823 nPlayAddress = nfilePlayAddress;
2824 nInitAddress = nfileInitAddress;
2826 pExRAM[0x00] = 0x20; /* JSR */
2827 pExRAM[0x01] = nInitAddress&0xff; /* Init Address */
2828 pExRAM[0x02] = (nInitAddress>>8)&0xff;
2829 pExRAM[0x03] = 0xF2; /* JAM */
2830 pExRAM[0x04] = 0x20; /* JSR */
2831 pExRAM[0x05] = nPlayAddress&0xff; /* Play Address */
2832 pExRAM[0x06] = (nPlayAddress>>8)&0xff;
2833 pExRAM[0x07] = 0x4C; /* JMP */
2834 pExRAM[0x08] = 0x03;/* $5003 (JAM right before the JSR to play address) */
2835 pExRAM[0x09] = 0x50;
2837 regA = regX = regY = 0;
2838 regP = 0x04; /* I_FLAG */
2839 regSP = 0xFF;
2841 nFilterAccL = 0;
2843 /* Reset Read/Write Procs */
2845 ReadMemory[0] = ReadMemory[1] = ReadMemory_RAM;
2846 ReadMemory[2] = ReadMemory[3] = ReadMemory_Default;
2847 ReadMemory[4] = ReadMemory_pAPU;
2848 ReadMemory[5] = ReadMemory_ExRAM;
2849 ReadMemory[6] = ReadMemory[7] = ReadMemory_SRAM;
2851 WriteMemory[0] = WriteMemory[1] = WriteMemory_RAM;
2852 WriteMemory[2] = WriteMemory[3] = WriteMemory_Default;
2853 WriteMemory[4] = WriteMemory_pAPU;
2854 WriteMemory[5] = WriteMemory_ExRAM;
2855 WriteMemory[6] = WriteMemory[7] = WriteMemory_SRAM;
2857 for(i = 8; i < 16; i++)
2859 ReadMemory[i] = ReadMemory_ROM;
2860 WriteMemory[i] = WriteMemory_Default;
2863 if(nExternalSound & EXTSOUND_FDS)
2865 WriteMemory[0x06] = WriteMemory_FDSRAM;
2866 WriteMemory[0x07] = WriteMemory_FDSRAM;
2867 WriteMemory[0x08] = WriteMemory_FDSRAM;
2868 WriteMemory[0x09] = WriteMemory_FDSRAM;
2869 WriteMemory[0x0A] = WriteMemory_FDSRAM;
2870 WriteMemory[0x0B] = WriteMemory_FDSRAM;
2871 WriteMemory[0x0C] = WriteMemory_FDSRAM;
2872 WriteMemory[0x0D] = WriteMemory_FDSRAM;
2873 ReadMemory[0x06] = ReadMemory_ROM;
2874 ReadMemory[0x07] = ReadMemory_ROM;
2877 if(!bPALMode) /* no expansion sound available on a PAL system */
2879 if(nExternalSound & EXTSOUND_VRC6)
2881 /* if both VRC6+VRC7... it MUST go to WriteMemory_VRC6
2882 * or register writes will be lost (WriteMemory_VRC6 calls
2883 * WriteMemory_VRC7 if needed) */
2884 WriteMemory[0x09] = WriteMemory_VRC6;
2885 WriteMemory[0x0A] = WriteMemory_VRC6;
2886 WriteMemory[0x0B] = WriteMemory_VRC6;
2888 if(nExternalSound & EXTSOUND_N106)
2890 WriteMemory[0x04] = WriteMemory_N106;
2891 ReadMemory[0x04] = ReadMemory_N106;
2892 WriteMemory[0x0F] = WriteMemory_N106;
2894 if(nExternalSound & EXTSOUND_FME07)
2896 WriteMemory[0x0C] = WriteMemory_FME07;
2897 WriteMemory[0x0E] = WriteMemory_FME07;
2901 /* MMC5 still has a multiplication reg that needs to be available on
2902 PAL tunes */
2903 if(nExternalSound & EXTSOUND_MMC5)
2904 WriteMemory[0x05] = WriteMemory_MMC5;
2906 return 1;
2910 * SetTrack
2913 void SetTrack(uint8_t track)
2915 int32_t i;
2917 nCurTrack = track;
2919 regPC = 0x5000;
2920 regA = track;
2921 regX = bPALMode;
2922 regY = bCleanAXY ? 0 : 0xCD;
2923 regSP = 0xFF;
2924 if(bCleanAXY)
2925 regP = 0x04;
2926 bCPUJammed = 0;
2928 nCPUCycle = nAPUCycle = 0;
2929 nDMCPop_Prev = 0;
2930 bDMCPop_Skip = 0;
2932 for(i = 0x4000; i < 0x400F; i++)
2933 WriteMemory_pAPU(i,0);
2934 WriteMemory_pAPU(0x4010,0);
2935 WriteMemory_pAPU(0x4012,0);
2936 WriteMemory_pAPU(0x4013,0);
2937 WriteMemory_pAPU(0x4014,0);
2938 WriteMemory_pAPU(0x4015,0);
2939 WriteMemory_pAPU(0x4015,0x0F);
2940 WriteMemory_pAPU(0x4017,0);
2942 for(i = 0; i < 10; i++)
2943 WriteMemory_ExRAM(0x5FF6 + i,nBankswitchInitValues[i]);
2945 ZEROMEMORY(pRAM,0x0800);
2946 ZEROMEMORY(pSRAM,0x2000);
2947 ZEROMEMORY(&pExRAM[0x10],0x0FF0);
2948 bFade = 0;
2951 nTicksUntilNextSample = nTicksPerSample;
2952 nTicksUntilNextFrame =
2953 (bPALMode ? PAL_FRAME_COUNTER_FREQ : NTSC_FRAME_COUNTER_FREQ)*0x10000;
2954 nTicksUntilNextPlay = nTicksPerPlay;
2955 nTotalPlays = 0;
2957 /* Clear mixing vals */
2958 mWave_Squares.nMixL = 0;
2959 mWave_TND.nMixL = 0;
2960 mWave_VRC6Pulse[0].nMixL = 0;
2961 mWave_VRC6Pulse[1].nMixL = 0;
2962 mWave_VRC6Saw.nMixL = 0;
2964 /* Reset Tri/Noise/DMC */
2965 mWave_TND.nTriStep = mWave_TND.nTriOutput = 0;
2966 mWave_TND.nDMCOutput = 0;
2967 mWave_TND.bNoiseRandomOut = 0;
2968 mWave_Squares.nDutyCount[0] = mWave_Squares.nDutyCount[1] = 0;
2969 mWave_TND.bDMCActive = 0;
2970 mWave_TND.nDMCBytesRemaining = 0;
2971 mWave_TND.bDMCSampleBufferEmpty = 1;
2972 mWave_TND.bDMCDeltaSilent = 1;
2974 /* Reset VRC6 */
2975 mWave_VRC6Pulse[0].nVolume = 0;
2976 mWave_VRC6Pulse[1].nVolume = 0;
2977 mWave_VRC6Saw.nAccumRate = 0;
2979 /* Reset N106 */
2980 ZEROMEMORY(mWave_N106.nRAM,0x100);
2981 ZEROMEMORY(mWave_N106.nVolume,8);
2982 ZEROMEMORY(mWave_N106.nOutput,8);
2983 ZEROMEMORY(mWave_N106.nMixL,32);
2985 /* Reset FME-07 */
2986 mWave_FME07[0].nVolume = 0;
2987 mWave_FME07[1].nVolume = 0;
2988 mWave_FME07[2].nVolume = 0;
2990 /* Clear FDS crap */
2992 mWave_FDS.bEnvelopeEnable = 0;
2993 mWave_FDS.nEnvelopeSpeed = 0xFF;
2994 mWave_FDS.nVolEnv_Mode = 2;
2995 mWave_FDS.nVolEnv_Decay = 0;
2996 mWave_FDS.nVolEnv_Gain = 0;
2997 mWave_FDS.nVolume = 0;
2998 mWave_FDS.bVolEnv_On = 0;
2999 mWave_FDS.nSweep_Mode = 2;
3000 mWave_FDS.nSweep_Decay = 0;
3001 mWave_FDS.nSweep_Gain = 0;
3002 mWave_FDS.bSweepEnv_On = 0;
3003 mWave_FDS.nSweepBias = 0;
3004 mWave_FDS.bLFO_Enabled = 0;
3005 mWave_FDS.nLFO_Freq.W = 0;
3006 /* mWave_FDS.fLFO_Timer = 0;
3007 mWave_FDS.fLFO_Count = 0;*/
3008 mWave_FDS.nLFO_Timer = 0;
3009 mWave_FDS.nLFO_Count = 0;
3010 mWave_FDS.nLFO_Addr = 0;
3011 mWave_FDS.bLFO_On = 0;
3012 mWave_FDS.nMainVolume = 0;
3013 mWave_FDS.bEnabled = 0;
3014 mWave_FDS.nFreq.W = 0;
3015 /* mWave_FDS.fFreqCount = 0;*/
3016 mWave_FDS.nFreqCount = 0;
3017 mWave_FDS.nMainAddr = 0;
3018 mWave_FDS.bWaveWrite = 0;
3019 mWave_FDS.bMain_On = 0;
3020 mWave_FDS.nMixL = 0;
3021 ZEROMEMORY(mWave_FDS.nWaveTable,0x40);
3022 ZEROMEMORY(mWave_FDS.nLFO_Table,0x40);
3024 mWave_FDS.nSweep_Count = mWave_FDS.nSweep_Timer =
3025 ((mWave_FDS.nSweep_Decay + 1) * mWave_FDS.nEnvelopeSpeed * 8);
3026 mWave_FDS.nVolEnv_Count = mWave_FDS.nVolEnv_Timer =
3027 ((mWave_FDS.nVolEnv_Decay + 1) * mWave_FDS.nEnvelopeSpeed * 8);
3029 nSilentSamples = 0;
3031 nFilterAccL = 0;
3033 nSilentSamples = 0;
3035 fulltick=0;
3039 * SetPlaybackOptions
3042 int SetPlaybackOptions(int32_t samplerate)
3044 if(samplerate < 2000) return 0;
3045 if(samplerate > 96000) return 0;
3047 nTicksPerSample =
3048 (bPALMode ? PAL_FREQUENCY : NTSC_FREQUENCY) / samplerate * 0x10000;
3049 nTicksUntilNextSample = nTicksPerSample;
3051 RecalcFilter();
3052 RecalcSilenceTracker();
3054 return 1;
3058 * SetPlaybackSpeed
3061 void SetPlaybackSpeed(float playspersec)
3063 if(playspersec < 1)
3065 playspersec = fNSFPlaybackSpeed;
3068 nTicksPerPlay = nTicksUntilNextPlay =
3069 (bPALMode ? PAL_FREQUENCY : NTSC_FREQUENCY) / playspersec * 0x10000;
3073 * GetPlaybackSpeed
3076 float GetPlaybackSpeed()
3078 if(nTicksPerPlay <= 0) return 0;
3079 return ((bPALMode ? PAL_FREQUENCY : NTSC_FREQUENCY) / (nTicksPerPlay>>16));
3083 * RecalcFilter
3086 void RecalcFilter()
3088 if(!nSampleRate) return;
3090 nHighPass = ((int64_t)nHighPassBase << 16) / nSampleRate;
3092 if(nHighPass > (1<<16)) nHighPass = 1<<16;
3096 * RecalcSilenceTracker
3099 void RecalcSilenceTracker()
3101 if(nSilenceTrackMS <= 0 || !nSampleRate ||
3102 (bNoSilenceIfTime && bTimeNotDefault))
3104 nSilentSampleMax = 0;
3105 return;
3108 nSilentSampleMax = nSilenceTrackMS * nSampleRate / 500;
3109 nSilentSampleMax /= 2;
3112 void RebuildOutputTables(void) {
3113 int32_t i,j;
3114 float l[3];
3115 int32_t temp;
3116 float ftemp;
3118 /* tnd */
3119 for(i = 0; i < 3; i++)
3121 l[i] = 255;
3124 for(i = 0; i < 0x8000; i++)
3126 ftemp = (l[0] * (i >> 11)) / 2097885;
3127 ftemp += (l[1] * ((i >> 7) & 0x0F)) / 3121455;
3128 ftemp += (l[2] * (i & 0x7F)) / 5772690;
3130 if(!ftemp)
3131 main_nOutputTable_L[i] = 0;
3132 else
3133 main_nOutputTable_L[i] =
3134 (int16_t)(2396850 / ((1.0f / ftemp) + 100));
3137 /* squares */
3138 for(i = 0; i < 2; i++)
3140 l[i] = 255;
3143 for(j = 0; j < 0x10; j++)
3145 for(i = 0; i < 0x10; i++)
3147 temp = (int32_t)(l[0] * j);
3148 temp += (int32_t)(l[1] * i);
3150 if(!temp)
3151 Squares_nOutputTable_L[j][i] = 0;
3152 else
3153 Squares_nOutputTable_L[j][i] = 1438200 / ((2072640 / temp) + 100);
3157 /* VRC6 Pulse 1,2 */
3158 for(i = 0; i < 0x10; i++)
3160 VRC6Pulse_nOutputTable_L[i] =
3161 1875 * i / 0x0F;
3163 /* VRC6 Saw */
3164 for(i = 0; i < 0x20; i++)
3166 VRC6Saw_nOutputTable_L[i] = 3750 * i / 0x1F;
3169 /* N106 channels */
3170 /* this amplitude is just a guess */
3172 for(i = 0; i < 0x10; i++)
3174 for(j = 0; j < 0x10; j++)
3176 N106_nOutputTable_L[i][j] = (3000 * i * j) / 0xE1;
3180 /* FME-07 Square A,B,C */
3181 FME07_nOutputTable_L[15] = 3000;
3182 FME07_nOutputTable_L[0] = 0;
3183 for(i = 14; i > 0; i--)
3185 FME07_nOutputTable_L[i] = FME07_nOutputTable_L[i + 1] * 80 / 100;
3189 * FDS
3191 /* this base volume (4000) is just a guess to what sounds right.
3192 * Given the number of steps available in an FDS wave... it seems like
3193 * it should be much much more... but then it's TOO loud.
3195 for(i = 0; i < 0x21; i++)
3197 for(j = 0; j < 0x40; j++)
3199 FDS_nOutputTable_L[0][i][j] =
3200 (4000 * i * j * 30) / (0x21 * 0x40 * 30);
3201 FDS_nOutputTable_L[1][i][j] =
3202 (4000 * i * j * 20) / (0x21 * 0x40 * 30);
3203 FDS_nOutputTable_L[2][i][j] =
3204 (4000 * i * j * 15) / (0x21 * 0x40 * 30);
3205 FDS_nOutputTable_L[3][i][j] =
3206 (4000 * i * j * 12) / (0x21 * 0x40 * 30);
3212 * GetPlayCalls
3215 float GetPlayCalls()
3217 if(!nTicksPerPlay) return 0;
3219 return ((float)nTotalPlays) +
3220 (1.0f - (nTicksUntilNextPlay*1.0f / nTicksPerPlay));
3224 * GetWrittenTime
3226 uint32_t GetWrittenTime(float basedplayspersec /* = 0 */)
3228 if(basedplayspersec <= 0)
3229 basedplayspersec = GetPlaybackSpeed();
3231 if(basedplayspersec <= 0)
3232 return 0;
3234 return (uint32_t)((GetPlayCalls() * 1000) / basedplayspersec);
3238 * StopFade
3240 void StopFade()
3242 bFade = 0;
3243 fFadeVolume = 1;
3247 * SongCompleted
3250 uint8_t SongCompleted()
3252 if(!bFade) return 0;
3253 if(nTotalPlays >= nEndFade) return 1;
3254 if(nSilentSampleMax) return (nSilentSamples >= nSilentSampleMax);
3256 return 0;
3260 * SetFade
3263 void SetFade(int32_t fadestart,int32_t fadestop,
3264 uint8_t bNotDefault) /* play routine calls */
3266 if(fadestart < 0) fadestart = 0;
3267 if(fadestop < fadestart) fadestop = fadestart;
3269 nStartFade = (uint32_t)fadestart;
3270 nEndFade = (uint32_t)fadestop;
3271 bFade = 1;
3272 bTimeNotDefault = bNotDefault;
3274 RecalcSilenceTracker();
3275 RecalculateFade();
3279 * SetFadeTime
3282 void SetFadeTime(uint32_t fadestart,uint32_t fadestop,float basedplays,
3283 uint8_t bNotDefault) /* time in MS */
3285 if(basedplays <= 0)
3286 basedplays = GetPlaybackSpeed();
3287 if(basedplays <= 0)
3288 return;
3290 SetFade((int32_t)(fadestart * basedplays / 1000),
3291 (int32_t)(fadestop * basedplays / 1000),bNotDefault);
3295 * RecalculateFade
3298 void RecalculateFade()
3300 if(!bFade) return;
3302 /* make it hit silence a little before the song ends...
3303 otherwise we're not really fading OUT, we're just fading umm...
3304 quieter =P */
3305 int32_t temp = (int32_t)(GetPlaybackSpeed() / 4);
3307 if(nEndFade <= nStartFade)
3309 nEndFade = nStartFade;
3310 fFadeChange = 1.0f;
3312 else if((nEndFade - temp) <= nStartFade)
3313 fFadeChange = 1.0f;
3314 else
3315 fFadeChange = 1.0f / (nEndFade - nStartFade - temp);
3317 if(nTotalPlays < nStartFade)
3318 fFadeVolume = 1.0f;
3319 else if(nTotalPlays >= nEndFade)
3320 fFadeVolume = 0.0f;
3321 else
3323 fFadeVolume = 1.0f - ( (nTotalPlays - nStartFade + 1) * fFadeChange );
3324 if(fFadeVolume < 0)
3325 fFadeVolume = 0;
3330 int32_t GetSamples(uint8_t* buffer,int32_t buffersize)
3332 if(!buffer) return 0;
3333 if(buffersize < 16) return 0;
3334 if(bFade && (nTotalPlays >= nEndFade)) return 0;
3336 pOutput = buffer;
3337 uint32_t runtocycle =
3338 (uint32_t)((buffersize / 2) * nTicksPerSample / 0x10000);
3339 nCPUCycle = nAPUCycle = 0;
3340 uint32_t tick;
3342 while(1)
3344 /*tick = (uint32_t)ceil(fTicksUntilNextPlay);*/
3345 tick = (nTicksUntilNextPlay+0xffff)>>16;
3346 if((tick + nCPUCycle) > runtocycle)
3347 tick = runtocycle - nCPUCycle;
3349 if(bCPUJammed)
3351 nCPUCycle += tick;
3352 EmulateAPU(0);
3354 else
3356 tick = Emulate6502(tick + nCPUCycle);
3357 EmulateAPU(1);
3360 nTicksUntilNextPlay -= tick<<16;
3361 if(nTicksUntilNextPlay <= 0)
3363 nTicksUntilNextPlay += nTicksPerPlay;
3364 if((bCPUJammed == 2) || bNoWaitForReturn)
3366 regX = regY = regA = (bCleanAXY ? 0 : 0xCD);
3367 regPC = 0x5004;
3368 nTotalPlays++;
3369 bDMCPop_SamePlay = 0;
3370 bCPUJammed = 0;
3371 if(nForce4017Write == 1) WriteMemory_pAPU(0x4017,0x00);
3372 if(nForce4017Write == 2) WriteMemory_pAPU(0x4017,0x80);
3375 if(bFade && (nTotalPlays >= nStartFade))
3377 fFadeVolume -= fFadeChange;
3378 if(fFadeVolume < 0)
3379 fFadeVolume = 0;
3380 if(nTotalPlays >= nEndFade)
3381 break;
3385 if(nCPUCycle >= runtocycle)
3386 break;
3389 nCPUCycle = nAPUCycle = 0;
3391 if(nSilentSampleMax && bFade)
3393 int16_t* tempbuf = (int16_t*)buffer;
3394 while( ((uint8_t*)tempbuf) < pOutput)
3396 if( (*tempbuf < -SILENCE_THRESHOLD) ||
3397 (*tempbuf > SILENCE_THRESHOLD) )
3398 nSilentSamples = 0;
3399 else
3401 if(++nSilentSamples >= nSilentSampleMax)
3402 return (int32_t)( ((uint8_t*)tempbuf) - buffer);
3404 tempbuf++;
3408 return (int32_t)(pOutput - buffer);
3411 /****************** 6502 emulation ******************/
3413 /* Memory reading/writing and other defines */
3415 /* reads zero page memory */
3416 #define Zp(a) pRAM[a]
3417 /* reads zero page memory in word form */
3418 #define ZpWord(a) (Zp(a) | (Zp((uint8_t)(a + 1)) << 8))
3419 /* reads memory */
3420 #define Rd(a) ((ReadMemory[((uint16_t)(a)) >> 12])(a))
3421 /* reads memory in word form */
3422 #define RdWord(a) (Rd(a) | (Rd(a + 1) << 8))
3423 /* writes memory */
3424 #define Wr(a,v) (WriteMemory[((uint16_t)(a)) >> 12])(a,v)
3425 /* writes zero paged memory */
3426 #define WrZ(a,v) pRAM[a] = v
3427 /* pushes a value onto the stack */
3428 #define PUSH(v) pStack[SP--] = v
3429 /* pulls a value from the stack */
3430 #define PULL(v) v = pStack[++SP]
3432 /* Addressing Modes */
3434 /* first set - gets the value that's being addressed */
3435 /*Immediate*/
3436 #define Ad_VlIm() val = Rd(PC.W); PC.W++
3437 /*Zero Page*/
3438 #define Ad_VlZp() final.W = Rd(PC.W); val = Zp(final.W); PC.W++
3439 /*Zero Page, X*/
3440 #define Ad_VlZx() front.W = final.W = Rd(PC.W); final.B.l += X; \
3441 val = Zp(final.B.l); PC.W++
3442 /*Zero Page, Y*/
3443 #define Ad_VlZy() front.W = final.W = Rd(PC.W); final.B.l += Y; \
3444 val = Zp(final.B.l); PC.W++
3445 /*Absolute*/
3446 #define Ad_VlAb() final.W = RdWord(PC.W); val = Rd(final.W); PC.W += 2
3447 /*Absolute, X [uses extra cycle if crossed page]*/
3448 #define Ad_VlAx() front.W = final.W = RdWord(PC.W); final.W += X; PC.W += 2;\
3449 if(front.B.h != final.B.h) nCPUCycle++; val = Rd(final.W)
3450 /*Absolute, X [uses extra cycle if crossed page]*/
3451 #define Ad_VlAy() front.W = final.W = RdWord(PC.W); final.W += Y; PC.W += 2;\
3452 if(front.B.h != final.B.h) nCPUCycle++; val = Rd(final.W)
3453 /*(Indirect, X)*/
3454 #define Ad_VlIx() front.W = final.W = Rd(PC.W); final.B.l += X; PC.W++; \
3455 final.W = ZpWord(final.B.l); val = Rd(final.W)
3456 /*(Indirect), Y [uses extra cycle if crossed page]*/
3457 #define Ad_VlIy() val = Rd(PC.W); front.W = final.W = ZpWord(val); PC.W++;\
3458 final.W += Y; if(final.B.h != front.B.h) nCPUCycle++; \
3459 front.W = val; val = Rd(final.W)
3461 /* second set - gets the ADDRESS that the mode is referring to (for operators
3462 * that write to memory) note that AbsoluteX, AbsoluteY, and
3463 * IndirectY modes do NOT check for page boundary crossing here
3464 * since that extra cycle isn't added for operators that write to
3465 * memory (it only applies to ones that only read from memory.. in
3466 * which case the 1st set should be used)
3468 /*Zero Page*/
3469 #define Ad_AdZp() final.W = Rd(PC.W); PC.W++
3470 /*Zero Page, X*/
3471 #define Ad_AdZx() final.W = front.W = Rd(PC.W); final.B.l += X; PC.W++
3472 /*Zero Page, Y*/
3473 #define Ad_AdZy() final.W = front.W = Rd(PC.W); final.B.l += Y; PC.W++
3474 /*Absolute*/
3475 #define Ad_AdAb() final.W = RdWord(PC.W); PC.W += 2
3476 /*Absolute, X*/
3477 #define Ad_AdAx() front.W = final.W = RdWord(PC.W); PC.W += 2; \
3478 final.W += X
3479 /*Absolute, Y*/
3480 #define Ad_AdAy() front.W = final.W = RdWord(PC.W); PC.W += 2; \
3481 final.W += Y
3482 /*(Indirect, X)*/
3483 #define Ad_AdIx() front.W = final.W = Rd(PC.W); PC.W++; final.B.l += X; \
3484 final.W = ZpWord(final.B.l)
3485 /*(Indirect), Y*/
3486 #define Ad_AdIy() front.W = Rd(PC.W); final.W = ZpWord(front.W) + Y; \
3487 PC.W++
3489 /* third set - reads memory, performs the desired operation on the value, then
3490 * writes back to memory
3491 * used for operators that directly change memory (ASL, INC, DEC, etc)
3493 /*Zero Page*/
3494 #define MRW_Zp(cmd) Ad_AdZp(); val = Zp(final.W); cmd(val); WrZ(final.W,val)
3495 /*Zero Page, X*/
3496 #define MRW_Zx(cmd) Ad_AdZx(); val = Zp(final.W); cmd(val); WrZ(final.W,val)
3497 /*Zero Page, Y*/
3498 #define MRW_Zy(cmd) Ad_AdZy(); val = Zp(final.W); cmd(val); WrZ(final.W,val)
3499 /*Absolute*/
3500 #define MRW_Ab(cmd) Ad_AdAb(); val = Rd(final.W); cmd(val); Wr(final.W,val)
3501 /*Absolute, X*/
3502 #define MRW_Ax(cmd) Ad_AdAx(); val = Rd(final.W); cmd(val); Wr(final.W,val)
3503 /*Absolute, Y*/
3504 #define MRW_Ay(cmd) Ad_AdAy(); val = Rd(final.W); cmd(val); Wr(final.W,val)
3505 /*(Indirect, X)*/
3506 #define MRW_Ix(cmd) Ad_AdIx(); val = Rd(final.W); cmd(val); Wr(final.W,val)
3507 /*(Indirect), Y*/
3508 #define MRW_Iy(cmd) Ad_AdIy(); val = Rd(final.W); cmd(val); Wr(final.W,val)
3510 /* Relative modes are special in that they're only used by branch commands
3511 * this macro handles the jump, and should only be called if the branch
3512 * condition was true if the branch condition was false, the PC must be
3513 * incremented
3516 #define RelJmp(cond) val = Rd(PC.W); PC.W++; final.W = PC.W + (int8_t)(val);\
3517 if(cond) {\
3518 nCPUCycle += ((final.B.h != PC.B.h) ? 2 : 1);\
3519 PC.W = final.W; }
3521 /* Status Flags */
3523 #define C_FLAG 0x01 /* carry flag */
3524 #define Z_FLAG 0x02 /* zero flag */
3525 #define I_FLAG 0x04 /* mask interrupt flag */
3526 #define D_FLAG 0x08 /* decimal flag (decimal mode is unsupported on
3527 NES) */
3528 #define B_FLAG 0x10 /* break flag (not really in the status register
3529 It's value in ST is never used. When ST is
3530 put in memory (by an interrupt or PHP), this
3531 flag is set only if BRK was called)
3532 ** also when PHP is called due to a bug */
3533 #define R_FLAG 0x20 /* reserved flag (not really in the register.
3534 It's value is never used.
3535 Whenever ST is put in memory,
3536 this flag is always set) */
3537 #define V_FLAG 0x40 /* overflow flag */
3538 #define N_FLAG 0x80 /* sign flag */
3541 /* Lookup Tables */
3543 /* the number of CPU cycles used for each instruction */
3544 static const uint8_t CPU_Cycles[0x100] = {
3545 7,6,0,8,3,3,5,5,3,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,4,2,2,2,4,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,3,2,2,2,3,4,6,6,
3550 2,5,0,8,4,4,6,6,2,4,2,7,4,4,7,7,
3551 6,6,0,8,3,3,5,5,4,2,2,2,5,4,6,6,
3552 2,5,0,8,4,4,6,6,2,4,2,7,4,4,7,7,
3553 2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4,
3554 2,6,0,6,4,4,4,4,2,5,2,5,5,5,5,5,
3555 2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4,
3556 2,5,0,5,4,4,4,4,2,4,2,4,4,4,4,4,
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,
3559 2,6,2,8,3,3,5,5,2,2,2,2,4,4,6,6,
3560 2,5,0,8,4,4,6,6,2,4,2,7,4,4,7,7 };
3562 /* the status of the NZ flags for the given value */
3563 static const uint8_t NZTable[0x100] = {
3564 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,
3565 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,
3566 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,
3567 0,0,0,0,0,0,0,0,0,0,0,
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,N_FLAG,N_FLAG,N_FLAG,N_FLAG,
3578 N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,
3579 N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG };
3581 /* A quick macro for working with the above table */
3582 #define UpdateNZ(v) ST = (ST & ~(N_FLAG|Z_FLAG)) | NZTable[v]
3586 * Opcodes
3588 * These opcodes perform the action with the given value (changing that
3589 * value if necessary). Registers and flags associated with the operation
3590 * are changed accordingly. There are a few exceptions which will be noted
3591 * when they arise
3595 /* ADC
3596 Adds the value to the accumulator with carry
3597 Changes: A, NVZC
3598 - Decimal mode not supported on the NES
3599 - Due to a bug, NVZ flags are not altered if the Decimal flag is on
3600 --(taken out)-- */
3601 #define ADC() \
3602 tw.W = A + val + (ST & C_FLAG); \
3603 ST = (ST & (I_FLAG|D_FLAG)) | tw.B.h | NZTable[tw.B.l] | \
3604 ( (0x80 & ~(A ^ val) & (A ^ tw.B.l)) ? V_FLAG : 0 ); \
3605 A = tw.B.l
3607 /* AND
3608 Combines the value with the accumulator using a bitwise AND operation
3609 Changes: A, NZ */
3610 #define AND() \
3611 A &= val; \
3612 UpdateNZ(A)
3614 /* ASL
3615 Left shifts the value 1 bit. The bit that gets shifted out goes to
3616 the carry flag.
3617 Changes: value, NZC */
3618 #define ASL(value) \
3619 tw.W = value << 1; \
3620 ST = (ST & ~(N_FLAG|Z_FLAG|C_FLAG)) | tw.B.h | NZTable[tw.B.l]; \
3621 value = tw.B.l
3623 /* BIT
3624 Compares memory with the accumulator with an AND operation, but changes
3625 neither.
3626 The two high bits of memory get transferred to the status reg
3627 Z is set if the AND operation yielded zero, otherwise it's cleared
3628 Changes: NVZ */
3629 #define BIT() \
3630 ST = (ST & ~(N_FLAG|V_FLAG|Z_FLAG)) | (val & (N_FLAG|V_FLAG)) | \
3631 ((A & val) ? 0 : Z_FLAG)
3633 /* CMP, CPX, CPY
3634 Compares memory with the given register with a subtraction operation.
3635 Flags are set accordingly depending on the result:
3636 Reg < Memory: Z=0, C=0
3637 Reg = Memory: Z=1, C=1
3638 Reg > Memory: Z=0, C=1
3639 N is set according to the result of the subtraction operation
3640 Changes: NZC
3642 NOTE -- CMP, CPX, CPY all share this same routine, so the desired
3643 register (A, X, or Y respectively) must be given when calling
3644 this macro... as well as the memory to compare it with. */
3645 #define CMP(reg) \
3646 tw.W = reg - val; \
3647 ST = (ST & ~(N_FLAG|Z_FLAG|C_FLAG)) | (tw.B.h ? 0 : C_FLAG) | \
3648 NZTable[tw.B.l]
3650 /* DEC, DEX, DEY
3651 Decriments a value by one.
3652 Changes: value, NZ */
3653 #define DEC(value) \
3654 value--; \
3655 UpdateNZ(value)
3657 /* EOR
3658 Combines a value with the accumulator using a bitwise exclusive-OR
3659 operation
3660 Changes: A, NZ */
3661 #define EOR() \
3662 A ^= val; \
3663 UpdateNZ(A)
3665 /* INC, INX, INY
3666 Incriments a value by one.
3667 Changes: value, NZ */
3668 #define INC(value) \
3669 value++; \
3670 UpdateNZ(value)
3672 /* LSR
3673 Shifts value one bit to the right. Bit that gets shifted out goes to
3674 the Carry flag.
3675 Changes: value, NZC */
3676 #define LSR(value) \
3677 tw.W = value >> 1; \
3678 ST = (ST & ~(N_FLAG|Z_FLAG|C_FLAG)) | NZTable[tw.B.l] | \
3679 (value & 0x01); \
3680 value = tw.B.l
3682 /* ORA
3683 Combines a value with the accumulator using a bitwise inclusive-OR
3684 operation
3685 Changes: A, NZ */
3686 #define ORA() \
3687 A |= val; \
3688 UpdateNZ(A)
3690 /* ROL
3691 Rotates a value one bit to the left:
3692 C <- 7<-6<-5<-4<-3<-2<-1<-0 <- C
3693 Changes: value, NZC */
3694 #define ROL(value) \
3695 tw.W = (value << 1) | (ST & 0x01); \
3696 ST = (ST & ~(N_FLAG|Z_FLAG|C_FLAG)) | NZTable[tw.B.l] | tw.B.h; \
3697 value = tw.B.l
3699 /* ROR
3700 Rotates a value one bit to the right:
3701 C -> 7->6->5->4->3->2->1->0 -> C
3702 Changes: value, NZC */
3703 #define ROR(value) \
3704 tw.W = (value >> 1) | (ST << 7); \
3705 ST = (ST & ~(N_FLAG|Z_FLAG|C_FLAG)) | NZTable[tw.B.l] | \
3706 (value & 0x01); \
3707 value = tw.B.l
3709 /* SBC
3710 Subtracts a value from the accumulator with borrow (inverted carry)
3711 Changes: A, NVZC
3712 - Decimal mode not supported on the NES
3713 - Due to a bug, NVZ flags are not altered if the Decimal flag is on
3714 --(taken out)-- */
3715 #define SBC() \
3716 tw.W = A - val - ((ST & C_FLAG) ? 0 : 1); \
3717 ST = (ST & (I_FLAG|D_FLAG)) | (tw.B.h ? 0 : C_FLAG) | NZTable[tw.B.l] | \
3718 (((A ^ val) & (A ^ tw.B.l) & 0x80) ? V_FLAG : 0); \
3719 A = tw.B.l
3721 /* Undocumented Opcodes
3723 * These opcodes are not included in the official specifications. However,
3724 * some of the unused opcode values perform operations which have since been
3725 * documented.
3729 /* ASO
3730 Left shifts a value, then ORs the result with the accumulator
3731 Changes: value, A, NZC */
3732 #define ASO(value) \
3733 tw.W = value << 1; \
3734 A |= tw.B.l; \
3735 ST = (ST & ~(N_FLAG|Z_FLAG|C_FLAG)) | NZTable[A] | tw.B.h; \
3736 value = tw.B.l
3738 /* RLA
3739 Roll memory left 1 bit, then AND the result with the accumulator
3740 Changes: value, A, NZC */
3741 #define RLA(value) \
3742 tw.W = (value << 1) | (ST & 0x01); \
3743 A &= tw.B.l; \
3744 ST = (ST & ~(N_FLAG|Z_FLAG|C_FLAG)) | NZTable[A] | tw.B.h; \
3745 value = tw.B.l
3747 /* LSE
3748 Right shifts a value one bit, then EORs the result with the accumulator
3749 Changes: value, A, NZC */
3750 #define LSE(value) \
3751 tw.W = value >> 1; \
3752 A ^= tw.B.l; \
3753 ST = (ST & ~(N_FLAG|Z_FLAG|C_FLAG)) | NZTable[A] | (value & 0x01); \
3754 value = tw.B.l
3756 /* RRA
3757 Roll memory right one bit, then ADC the result
3758 Changes: value, A, NVZC */
3759 #define RRA(value) \
3760 tw.W = (value >> 1) | (ST << 7); \
3761 ST = (ST & ~C_FLAG) | (value & 0x01); \
3762 value = tw.B.l; \
3763 ADC()
3765 /* AXS
3766 ANDs the contents of the X and A registers and stores the result
3767 int memory.
3768 Changes: value [DOES NOT CHANGE X, A, or any flags] */
3769 #define AXS(value) \
3770 value = A & X
3772 /* DCM
3773 Decriments a value and compares it with the A register.
3774 Changes: value, NZC */
3775 #define DCM(value) \
3776 value--; \
3777 CMP(A)
3779 /* INS
3780 Incriments a value then SBCs it
3781 Changes: value, A, NVZC */
3782 #define INS(value) \
3783 value++; \
3784 SBC()
3786 /* AXA */
3787 #define AXA(value) \
3788 value = A & X & (Rd(PC.W - 1) + 1)
3791 /* The 6502 emulation function! */
3793 union TWIN front;
3794 union TWIN final;
3795 uint8_t val;
3796 uint8_t op;
3798 uint32_t Emulate6502(uint32_t runto)
3800 /* If the CPU is jammed... don't bother */
3801 if(bCPUJammed == 1)
3802 return 0;
3804 register union TWIN tw; /* used in calculations */
3805 register uint8_t ST = regP;
3806 register union TWIN PC;
3807 uint8_t SP = regSP;
3808 register uint8_t A = regA;
3809 register uint8_t X = regX;
3810 register uint8_t Y = regY;
3811 union TWIN front;
3812 union TWIN final;
3813 PC.W = regPC;
3815 uint32_t ret = nCPUCycle;
3817 ENTER_TIMER(cpu);
3819 /* Start the loop */
3821 while(nCPUCycle < runto)
3823 op = Rd(PC.W);
3824 PC.W++;
3826 nCPUCycle += CPU_Cycles[op];
3827 switch(op)
3829 /* Documented Opcodes first */
3831 /* Flag setting/clearing */
3832 case 0x18: ST &= ~C_FLAG; break; /* CLC */
3833 case 0x38: ST |= C_FLAG; break; /* SEC */
3834 case 0x58: ST &= ~I_FLAG; break; /* CLI */
3835 case 0x78: ST |= I_FLAG; break; /* SEI */
3836 case 0xB8: ST &= ~V_FLAG; break; /* CLV */
3837 case 0xD8: ST &= ~D_FLAG; break; /* CLD */
3838 case 0xF8: ST |= D_FLAG; break; /* SED */
3840 /* Branch commands */
3841 case 0x10: RelJmp(!(ST & N_FLAG)); break; /* BPL */
3842 case 0x30: RelJmp( (ST & N_FLAG)); break; /* BMI */
3843 case 0x50: RelJmp(!(ST & V_FLAG)); break; /* BVC */
3844 case 0x70: RelJmp( (ST & V_FLAG)); break; /* BVS */
3845 case 0x90: RelJmp(!(ST & C_FLAG)); break; /* BCC */
3846 case 0xB0: RelJmp( (ST & C_FLAG)); break; /* BCS */
3847 case 0xD0: RelJmp(!(ST & Z_FLAG)); break; /* BNE */
3848 case 0xF0: RelJmp( (ST & Z_FLAG)); break; /* BEQ */
3850 /* Direct stack alteration commands (push/pull commands) */
3851 case 0x08: PUSH(ST | R_FLAG | B_FLAG); break; /* PHP */
3852 case 0x28: PULL(ST); break; /* PLP */
3853 case 0x48: PUSH(A); break; /* PHA */
3854 case 0x68: PULL(A); UpdateNZ(A); break; /* PLA */
3856 /* Register Transfers */
3857 case 0x8A: A = X; UpdateNZ(A); break; /* TXA */
3858 case 0x98: A = Y; UpdateNZ(A); break; /* TYA */
3859 case 0x9A: SP = X; break; /* TXS */
3860 case 0xA8: Y = A; UpdateNZ(A); break; /* TAY */
3861 case 0xAA: X = A; UpdateNZ(A); break; /* TAX */
3862 case 0xBA: X = SP; UpdateNZ(X); break; /* TSX */
3864 /* Other commands */
3866 /* ADC */
3867 case 0x61: Ad_VlIx(); ADC(); break;
3868 case 0x65: Ad_VlZp(); ADC(); break;
3869 case 0x69: Ad_VlIm(); ADC(); break;
3870 case 0x6D: Ad_VlAb(); ADC(); break;
3871 case 0x71: Ad_VlIy(); ADC(); break;
3872 case 0x75: Ad_VlZx(); ADC(); break;
3873 case 0x79: Ad_VlAy(); ADC(); break;
3874 case 0x7D: Ad_VlAx(); ADC(); break;
3876 /* AND */
3877 case 0x21: Ad_VlIx(); AND(); break;
3878 case 0x25: Ad_VlZp(); AND(); break;
3879 case 0x29: Ad_VlIm(); AND(); break;
3880 case 0x2D: Ad_VlAb(); AND(); break;
3881 case 0x31: Ad_VlIy(); AND(); break;
3882 case 0x35: Ad_VlZx(); AND(); break;
3883 case 0x39: Ad_VlAy(); AND(); break;
3884 case 0x3D: Ad_VlAx(); AND(); break;
3886 /* ASL */
3887 case 0x0A: ASL(A); break;
3888 case 0x06: MRW_Zp(ASL); break;
3889 case 0x0E: MRW_Ab(ASL); break;
3890 case 0x16: MRW_Zx(ASL); break;
3891 case 0x1E: MRW_Ax(ASL); break;
3893 /* BIT */
3894 case 0x24: Ad_VlZp(); BIT(); break;
3895 case 0x2C: Ad_VlAb(); BIT(); break;
3897 /* BRK */
3898 case 0x00:
3899 if(bIgnoreBRK)
3900 break;
3901 PC.W++; /*BRK has a padding byte*/
3902 PUSH(PC.B.h); /*push high byte of the return address*/
3903 PUSH(PC.B.l); /*push low byte of return address*/
3904 PUSH(ST | R_FLAG | B_FLAG); /*push processor status with R|B flags*/
3905 ST |= I_FLAG; /*mask interrupts*/
3906 PC.W = RdWord(0xFFFE); /*read the IRQ vector and jump to it*/
3908 /* extra check to make sure we didn't hit an infinite BRK loop */
3909 if(!Rd(PC.W)) /* next command will be BRK */
3911 /* the CPU will endlessly loop...
3912 just jam it to ease processing power */
3913 bCPUJammed = 1;
3914 goto jammed;
3916 break;
3918 /* CMP */
3919 case 0xC1: Ad_VlIx(); CMP(A); break;
3920 case 0xC5: Ad_VlZp(); CMP(A); break;
3921 case 0xC9: Ad_VlIm(); CMP(A); break;
3922 case 0xCD: Ad_VlAb(); CMP(A); break;
3923 case 0xD1: Ad_VlIy(); CMP(A); break;
3924 case 0xD5: Ad_VlZx(); CMP(A); break;
3925 case 0xD9: Ad_VlAy(); CMP(A); break;
3926 case 0xDD: Ad_VlAx(); CMP(A); break;
3928 /* CPX */
3929 case 0xE0: Ad_VlIm(); CMP(X); break;
3930 case 0xE4: Ad_VlZp(); CMP(X); break;
3931 case 0xEC: Ad_VlAb(); CMP(X); break;
3933 /* CPY */
3934 case 0xC0: Ad_VlIm(); CMP(Y); break;
3935 case 0xC4: Ad_VlZp(); CMP(Y); break;
3936 case 0xCC: Ad_VlAb(); CMP(Y); break;
3938 /* DEC */
3939 case 0xCA: DEC(X); break; /* DEX */
3940 case 0x88: DEC(Y); break; /* DEY */
3941 case 0xC6: MRW_Zp(DEC); break;
3942 case 0xCE: MRW_Ab(DEC); break;
3943 case 0xD6: MRW_Zx(DEC); break;
3944 case 0xDE: MRW_Ax(DEC); break;
3946 /* EOR */
3947 case 0x41: Ad_VlIx(); EOR(); break;
3948 case 0x45: Ad_VlZp(); EOR(); break;
3949 case 0x49: Ad_VlIm(); EOR(); break;
3950 case 0x4D: Ad_VlAb(); EOR(); break;
3951 case 0x51: Ad_VlIy(); EOR(); break;
3952 case 0x55: Ad_VlZx(); EOR(); break;
3953 case 0x59: Ad_VlAy(); EOR(); break;
3954 case 0x5D: Ad_VlAx(); EOR(); break;
3956 /* INC */
3957 case 0xE8: INC(X); break; /* INX */
3958 case 0xC8: INC(Y); break; /* INY */
3959 case 0xE6: MRW_Zp(INC); break;
3960 case 0xEE: MRW_Ab(INC); break;
3961 case 0xF6: MRW_Zx(INC); break;
3962 case 0xFE: MRW_Ax(INC); break;
3964 /* JMP */
3965 /* Absolute JMP */
3966 case 0x4C: final.W = RdWord(PC.W); PC.W = final.W; val = 0; break;
3967 /* Indirect JMP -- must take caution:
3968 Indirection at 01FF will read from 01FF and 0100 (not 0200) */
3969 case 0x6C: front.W = final.W = RdWord(PC.W);
3970 PC.B.l = Rd(final.W); final.B.l++;
3971 PC.B.h = Rd(final.W); final.W = PC.W;
3972 break;
3973 /* JSR */
3974 case 0x20:
3975 val = 0;
3976 final.W = RdWord(PC.W);
3977 PC.W++; /* JSR only increments the return address by one.
3978 It's incremented again upon RTS */
3979 PUSH(PC.B.h); /* push high byte of return address */
3980 PUSH(PC.B.l); /* push low byte of return address */
3981 PC.W = final.W;
3982 break;
3984 /* LDA */
3985 case 0xA1: Ad_VlIx(); A = val; UpdateNZ(A); break;
3986 case 0xA5: Ad_VlZp(); A = val; UpdateNZ(A); break;
3987 case 0xA9: Ad_VlIm(); A = val; UpdateNZ(A); break;
3988 case 0xAD: Ad_VlAb(); A = val; UpdateNZ(A); break;
3989 case 0xB1: Ad_VlIy(); A = val; UpdateNZ(A); break;
3990 case 0xB5: Ad_VlZx(); A = val; UpdateNZ(A); break;
3991 case 0xB9: Ad_VlAy(); A = val; UpdateNZ(A); break;
3992 case 0xBD: Ad_VlAx(); A = val; UpdateNZ(A); break;
3994 /* LDX */
3995 case 0xA2: Ad_VlIm(); X = val; UpdateNZ(X); break;
3996 case 0xA6: Ad_VlZp(); X = val; UpdateNZ(X); break;
3997 case 0xAE: Ad_VlAb(); X = val; UpdateNZ(X); break;
3998 case 0xB6: Ad_VlZy(); X = val; UpdateNZ(X); break;
3999 case 0xBE: Ad_VlAy(); X = val; UpdateNZ(X); break;
4001 /* LDY */
4002 case 0xA0: Ad_VlIm(); Y = val; UpdateNZ(Y); break;
4003 case 0xA4: Ad_VlZp(); Y = val; UpdateNZ(Y); break;
4004 case 0xAC: Ad_VlAb(); Y = val; UpdateNZ(Y); break;
4005 case 0xB4: Ad_VlZx(); Y = val; UpdateNZ(Y); break;
4006 case 0xBC: Ad_VlAx(); Y = val; UpdateNZ(Y); break;
4008 /* LSR */
4009 case 0x4A: LSR(A); break;
4010 case 0x46: MRW_Zp(LSR); break;
4011 case 0x4E: MRW_Ab(LSR); break;
4012 case 0x56: MRW_Zx(LSR); break;
4013 case 0x5E: MRW_Ax(LSR); break;
4015 /* NOP */
4016 case 0xEA:
4018 /* --- Undocumented ---
4019 These opcodes perform the same action as NOP */
4020 case 0x1A: case 0x3A: case 0x5A:
4021 case 0x7A: case 0xDA: case 0xFA: break;
4023 /* ORA */
4024 case 0x01: Ad_VlIx(); ORA(); break;
4025 case 0x05: Ad_VlZp(); ORA(); break;
4026 case 0x09: Ad_VlIm(); ORA(); break;
4027 case 0x0D: Ad_VlAb(); ORA(); break;
4028 case 0x11: Ad_VlIy(); ORA(); break;
4029 case 0x15: Ad_VlZx(); ORA(); break;
4030 case 0x19: Ad_VlAy(); ORA(); break;
4031 case 0x1D: Ad_VlAx(); ORA(); break;
4033 /* ROL */
4034 case 0x2A: ROL(A); break;
4035 case 0x26: MRW_Zp(ROL); break;
4036 case 0x2E: MRW_Ab(ROL); break;
4037 case 0x36: MRW_Zx(ROL); break;
4038 case 0x3E: MRW_Ax(ROL); break;
4040 /* ROR */
4041 case 0x6A: ROR(A); break;
4042 case 0x66: MRW_Zp(ROR); break;
4043 case 0x6E: MRW_Ab(ROR); break;
4044 case 0x76: MRW_Zx(ROR); break;
4045 case 0x7E: MRW_Ax(ROR); break;
4047 /* RTI */
4048 case 0x40:
4049 PULL(ST); /*pull processor status*/
4050 PULL(PC.B.l); /*pull low byte of return address*/
4051 PULL(PC.B.h); /*pull high byte of return address*/
4052 break;
4054 /* RTS */
4055 case 0x60:
4056 PULL(PC.B.l);
4057 PULL(PC.B.h);
4058 PC.W++; /* the return address is one less of what it needs */
4059 break;
4061 /* SBC */
4062 case 0xE1: Ad_VlIx(); SBC(); break;
4063 case 0xE5: Ad_VlZp(); SBC(); break;
4064 /* - Undocumented - EB performs the same operation as SBC immediate */
4065 case 0xEB:
4066 case 0xE9: Ad_VlIm(); SBC(); break;
4067 case 0xED: Ad_VlAb(); SBC(); break;
4068 case 0xF1: Ad_VlIy(); SBC(); break;
4069 case 0xF5: Ad_VlZx(); SBC(); break;
4070 case 0xF9: Ad_VlAy(); SBC(); break;
4071 case 0xFD: Ad_VlAx(); SBC(); break;
4073 /* STA */
4074 case 0x81: Ad_AdIx(); val = A; Wr(final.W,A); break;
4075 case 0x85: Ad_AdZp(); val = A; WrZ(final.W,A); break;
4076 case 0x8D: Ad_AdAb(); val = A; Wr(final.W,A); break;
4077 case 0x91: Ad_AdIy(); val = A; Wr(final.W,A); break;
4078 case 0x95: Ad_AdZx(); val = A; WrZ(final.W,A); break;
4079 case 0x99: Ad_AdAy(); val = A; Wr(final.W,A); break;
4080 case 0x9D: Ad_AdAx(); val = A; Wr(final.W,A); break;
4082 /* STX */
4083 case 0x86: Ad_AdZp(); val = X; WrZ(final.W,X); break;
4084 case 0x8E: Ad_AdAb(); val = X; Wr(final.W,X); break;
4085 case 0x96: Ad_AdZy(); val = X; WrZ(final.W,X); break;
4087 /* STY */
4088 case 0x84: Ad_AdZp(); val = Y; WrZ(final.W,Y); break;
4089 case 0x8C: Ad_AdAb(); val = Y; Wr(final.W,Y); break;
4090 case 0x94: Ad_AdZx(); val = Y; WrZ(final.W,Y); break;
4092 /* Undocumented Opcodes */
4093 /* ASO */
4094 case 0x03: if(bIgnoreIllegalOps) break; MRW_Ix(ASO); break;
4095 case 0x07: if(bIgnoreIllegalOps) break; MRW_Zp(ASO); break;
4096 case 0x0F: if(bIgnoreIllegalOps) break; MRW_Ab(ASO); break;
4097 case 0x13: if(bIgnoreIllegalOps) break; MRW_Iy(ASO); break;
4098 case 0x17: if(bIgnoreIllegalOps) break; MRW_Zx(ASO); break;
4099 case 0x1B: if(bIgnoreIllegalOps) break; MRW_Ay(ASO); break;
4100 case 0x1F: if(bIgnoreIllegalOps) break; MRW_Ax(ASO); break;
4102 /* RLA */
4103 case 0x23: if(bIgnoreIllegalOps) break; MRW_Ix(RLA); break;
4104 case 0x27: if(bIgnoreIllegalOps) break; MRW_Zp(RLA); break;
4105 case 0x2F: if(bIgnoreIllegalOps) break; MRW_Ab(RLA); break;
4106 case 0x33: if(bIgnoreIllegalOps) break; MRW_Iy(RLA); break;
4107 case 0x37: if(bIgnoreIllegalOps) break; MRW_Zx(RLA); break;
4108 case 0x3B: if(bIgnoreIllegalOps) break; MRW_Ay(RLA); break;
4109 case 0x3F: if(bIgnoreIllegalOps) break; MRW_Ax(RLA); break;
4111 /* LSE */
4112 case 0x43: if(bIgnoreIllegalOps) break; MRW_Ix(LSE); break;
4113 case 0x47: if(bIgnoreIllegalOps) break; MRW_Zp(LSE); break;
4114 case 0x4F: if(bIgnoreIllegalOps) break; MRW_Ab(LSE); break;
4115 case 0x53: if(bIgnoreIllegalOps) break; MRW_Iy(LSE); break;
4116 case 0x57: if(bIgnoreIllegalOps) break; MRW_Zx(LSE); break;
4117 case 0x5B: if(bIgnoreIllegalOps) break; MRW_Ay(LSE); break;
4118 case 0x5F: if(bIgnoreIllegalOps) break; MRW_Ax(LSE); break;
4120 /* RRA */
4121 case 0x63: if(bIgnoreIllegalOps) break; MRW_Ix(RRA); break;
4122 case 0x67: if(bIgnoreIllegalOps) break; MRW_Zp(RRA); break;
4123 case 0x6F: if(bIgnoreIllegalOps) break; MRW_Ab(RRA); break;
4124 case 0x73: if(bIgnoreIllegalOps) break; MRW_Iy(RRA); break;
4125 case 0x77: if(bIgnoreIllegalOps) break; MRW_Zx(RRA); break;
4126 case 0x7B: if(bIgnoreIllegalOps) break; MRW_Ay(RRA); break;
4127 case 0x7F: if(bIgnoreIllegalOps) break; MRW_Ax(RRA); break;
4129 /* AXS */
4130 case 0x83: if(bIgnoreIllegalOps) break; MRW_Ix(AXS); break;
4131 case 0x87: if(bIgnoreIllegalOps) break; MRW_Zp(AXS); break;
4132 case 0x8F: if(bIgnoreIllegalOps) break; MRW_Ab(AXS); break;
4133 case 0x97: if(bIgnoreIllegalOps) break; MRW_Zy(AXS); break;
4135 /* LAX */
4136 case 0xA3: if(bIgnoreIllegalOps) break;
4137 Ad_VlIx(); X = A = val; UpdateNZ(A); break;
4138 case 0xA7: if(bIgnoreIllegalOps) break;
4139 Ad_VlZp(); X = A = val; UpdateNZ(A); break;
4140 case 0xAF: if(bIgnoreIllegalOps) break;
4141 Ad_VlAb(); X = A = val; UpdateNZ(A); break;
4142 case 0xB3: if(bIgnoreIllegalOps) break;
4143 Ad_VlIy(); X = A = val; UpdateNZ(A); break;
4144 case 0xB7: if(bIgnoreIllegalOps) break;
4145 Ad_VlZy(); X = A = val; UpdateNZ(A); break;
4146 case 0xBF: if(bIgnoreIllegalOps) break;
4147 Ad_VlAy(); X = A = val; UpdateNZ(A); break;
4149 /* DCM */
4150 case 0xC3: if(bIgnoreIllegalOps) break; MRW_Ix(DCM); break;
4151 case 0xC7: if(bIgnoreIllegalOps) break; MRW_Zp(DCM); break;
4152 case 0xCF: if(bIgnoreIllegalOps) break; MRW_Ab(DCM); break;
4153 case 0xD3: if(bIgnoreIllegalOps) break; MRW_Iy(DCM); break;
4154 case 0xD7: if(bIgnoreIllegalOps) break; MRW_Zx(DCM); break;
4155 case 0xDB: if(bIgnoreIllegalOps) break; MRW_Ay(DCM); break;
4156 case 0xDF: if(bIgnoreIllegalOps) break; MRW_Ax(DCM); break;
4158 /* INS */
4159 case 0xE3: if(bIgnoreIllegalOps) break; MRW_Ix(INS); break;
4160 case 0xE7: if(bIgnoreIllegalOps) break; MRW_Zp(INS); break;
4161 case 0xEF: if(bIgnoreIllegalOps) break; MRW_Ab(INS); break;
4162 case 0xF3: if(bIgnoreIllegalOps) break; MRW_Iy(INS); break;
4163 case 0xF7: if(bIgnoreIllegalOps) break; MRW_Zx(INS); break;
4164 case 0xFB: if(bIgnoreIllegalOps) break; MRW_Ay(INS); break;
4165 case 0xFF: if(bIgnoreIllegalOps) break; MRW_Ax(INS); break;
4167 /* ALR
4168 AND Accumulator with memory and LSR the result */
4169 case 0x4B: if(bIgnoreIllegalOps) break;
4170 Ad_VlIm(); A &= val; LSR(A); break;
4172 /* ARR
4173 ANDs memory with the Accumulator and RORs the result */
4174 case 0x6B: if(bIgnoreIllegalOps) break;
4175 Ad_VlIm(); A &= val; ROR(A); break;
4177 /* XAA
4178 Transfers X -> A, then ANDs A with memory */
4179 case 0x8B: if(bIgnoreIllegalOps) break;
4180 Ad_VlIm(); A = X & val; UpdateNZ(A); break;
4182 /* OAL
4183 OR the Accumulator with #EE, AND Accumulator with Memory,
4184 Transfer A -> X */
4185 case 0xAB: if(bIgnoreIllegalOps) break;
4186 Ad_VlIm(); X = (A &= (val | 0xEE));
4187 UpdateNZ(A); break;
4189 /* SAX
4190 ANDs A and X registers (does not change A), subtracts memory
4191 from result (CMP style, not SBC style) result is stored in X */
4192 case 0xCB: if(bIgnoreIllegalOps) break;
4193 Ad_VlIm(); tw.W = (X & A) - val; X = tw.B.l;
4194 ST = (ST & ~(N_FLAG|Z_FLAG|C_FLAG)) | NZTable[X] |
4195 (tw.B.h ? C_FLAG : 0); break;
4196 /* SKB
4197 Skip Byte... or DOP - Double No-Op
4198 These bytes do nothing, but take a parameter (which can be
4199 ignored) */
4200 case 0x04: case 0x14: case 0x34: case 0x44: case 0x54: case 0x64:
4201 case 0x80: case 0x82: case 0x89: case 0xC2: case 0xD4: case 0xE2:
4202 case 0xF4:
4203 if(bIgnoreIllegalOps) break;
4204 PC.W++; /* skip unused byte */
4205 break;
4207 /* SKW
4208 Swip Word... or TOP - Tripple No-Op
4209 These bytes are the same as SKB, only they take a 2 byte parameter.
4210 This can be ignored in some cases, but the read needs to be
4211 performed in a some cases because an extra clock cycle may be used
4212 in the process */
4213 /* Absolute address... no need for operator */
4214 case 0x0C:
4215 if(bIgnoreIllegalOps) break;
4216 PC.W += 2; break;
4217 /* Absolute X address... may cross page, have to perform the read */
4218 case 0x1C: case 0x3C: case 0x5C: case 0x7C: case 0xDC: case 0xFC:
4219 if(bIgnoreIllegalOps) break;
4220 Ad_VlAx(); break;
4222 /* HLT / JAM
4223 Jams up CPU operation */
4224 case 0x02: case 0x12: case 0x22: case 0x32: case 0x42: case 0x52:
4225 case 0x62: case 0x72: case 0x92: case 0xB2: case 0xD2: case 0xF2:
4226 /*it's not -really- jammed... only the NSF code has ended*/
4227 if(PC.W == 0x5004) bCPUJammed = 2;
4228 else
4230 if(bIgnoreIllegalOps) break;
4231 bCPUJammed = 1;
4233 goto jammed;
4235 /* TAS */
4236 case 0x9B:
4237 if(bIgnoreIllegalOps) break;
4238 Ad_AdAy();
4239 SP = A & X & (Rd(PC.W - 1) + 1);
4240 Wr(final.W,SP);
4241 break;
4243 /* SAY */
4244 case 0x9C:
4245 if(bIgnoreIllegalOps) break;
4246 Ad_AdAx();
4247 Y &= (Rd(PC.W - 1) + 1);
4248 Wr(final.W,Y);
4249 break;
4251 /* XAS */
4252 case 0x9E:
4253 if(bIgnoreIllegalOps) break;
4254 Ad_AdAy();
4255 X &= (Rd(PC.W - 1) + 1);
4256 Wr(final.W,X);
4257 break;
4259 /* AXA */
4260 case 0x93: if(bIgnoreIllegalOps) break; MRW_Iy(AXA); break;
4261 case 0x9F: if(bIgnoreIllegalOps) break; MRW_Ay(AXA); break;
4263 /* ANC */
4264 case 0x0B: case 0x2B:
4265 if(bIgnoreIllegalOps) break;
4266 Ad_VlIm();
4267 A &= val;
4268 ST = (ST & ~(N_FLAG|Z_FLAG|C_FLAG)) |
4269 NZTable[A] | ((A & 0x80) ? C_FLAG : 0);
4270 break;
4272 /* LAS */
4273 case 0xBB:
4274 if(bIgnoreIllegalOps) break;
4275 Ad_VlAy();
4276 X = A = (SP &= val);
4277 UpdateNZ(A);
4278 break;
4282 jammed:
4283 regPC = PC.W;
4284 regA = A;
4285 regX = X;
4286 regY = Y;
4287 regSP = SP;
4288 regP = ST;
4290 EXIT_TIMER(cpu);
4292 return (nCPUCycle - ret);
4295 /****************** rockbox interface ******************/
4297 static void set_codec_track(int t, int d) {
4298 int track,fade,def=0;
4299 SetTrack(t);
4301 /* for REPEAT_ONE we disable track limits */
4302 if (ci->global_settings->repeat_mode!=REPEAT_ONE) {
4303 if (!bIsExtended || nTrackTime[t]==-1) {track=60*2*1000; def=1;}
4304 else track=nTrackTime[t];
4305 if (!bIsExtended || nTrackFade[t]==-1) fade=5*1000;
4306 else fade=nTrackFade[t];
4307 nSilenceTrackMS=5000;
4308 SetFadeTime(track,track+fade, fNSFPlaybackSpeed,def);
4310 ci->id3->elapsed=d*1000; /* d is track no to display */
4313 /* this is the codec entry point */
4314 enum codec_status codec_main(void)
4316 int written;
4317 uint8_t *buf;
4318 size_t n;
4319 int endofstream; /* end of stream flag */
4320 int track;
4321 int dontresettrack;
4322 char last_path[MAX_PATH];
4323 int usingplaylist;
4325 /* we only render 16 bits */
4326 ci->configure(DSP_SET_SAMPLE_DEPTH, 16);
4328 ci->configure(DSP_SET_FREQUENCY, 44100);
4329 ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO);
4331 RebuildOutputTables();
4333 dontresettrack=0;
4334 last_path[0]='\0';
4335 track=0;
4337 next_track:
4338 usingplaylist=0;
4339 DEBUGF("NSF: next_track\n");
4340 if (codec_init()) {
4341 return CODEC_ERROR;
4343 DEBUGF("NSF: after init\n");
4346 /* wait for track info to load */
4347 while (!*ci->taginfo_ready && !ci->stop_codec)
4348 ci->sleep(1);
4350 codec_set_replaygain(ci->id3);
4352 /* Read the entire file */
4353 DEBUGF("NSF: request file\n");
4354 ci->seek_buffer(0);
4355 buf = ci->request_buffer(&n, ci->filesize);
4356 if (!buf || n < (size_t)ci->filesize) {
4357 DEBUGF("NSF: file load failed\n");
4358 return CODEC_ERROR;
4361 init_nsf:
4362 if(!NSFCore_Initialize()) {
4363 DEBUGF("NSF: NSFCore_Initialize failed\n"); return CODEC_ERROR;}
4365 if(LoadFile(buf,ci->filesize)) {
4366 DEBUGF("NSF: LoadFile failed\n"); return CODEC_ERROR;}
4367 if(!SetPlaybackOptions(44100)) {
4368 DEBUGF("NSF: SetPlaybackOptions failed\n"); return CODEC_ERROR;}
4369 if(!LoadNSF(nDataBufferSize)) {
4370 DEBUGF("NSF: LoadNSF failed\n"); return CODEC_ERROR;}
4372 ci->id3->title=szGameTitle;
4373 ci->id3->artist=szArtist;
4374 ci->id3->album=szCopyright;
4375 if (usingplaylist) {
4376 ci->id3->length=nPlaylistSize*1000;
4377 } else {
4378 ci->id3->length=nTrackCount*1000;
4381 if (!dontresettrack||strcmp(ci->id3->path,last_path)) {
4382 /* if this is the first time we're seeing this file, or if we haven't
4383 been asked to preserve the track number, default to the proper
4384 initial track */
4385 if (bIsExtended &&
4386 ci->global_settings->repeat_mode!=REPEAT_ONE && nPlaylistSize>0) {
4387 /* decide to use the playlist */
4388 usingplaylist=1;
4389 track=0;
4390 set_codec_track(nPlaylist[0],0);
4391 } else {
4392 /* simply use the initial track */
4393 track=nInitialTrack;
4394 set_codec_track(track,track);
4396 } else {
4397 /* if we've already been running this file assume track is set
4398 already */
4399 if (usingplaylist) set_codec_track(nPlaylist[track],track);
4400 else set_codec_track(track,track);
4402 strcpy(last_path,ci->id3->path);
4404 /* The main decoder loop */
4406 endofstream = 0;
4408 reset_profile_timers();
4410 while (!endofstream) {
4412 ci->yield();
4413 if (ci->stop_codec || ci->new_track) {
4414 break;
4417 if (ci->seek_time >0) {
4418 track=ci->seek_time/1000;
4419 if (usingplaylist) {
4420 if (track>=nPlaylistSize) break;
4421 } else {
4422 if (track>=nTrackCount) break;
4424 ci->seek_complete();
4425 dontresettrack=1;
4426 goto init_nsf;
4429 ENTER_TIMER(total);
4430 written=GetSamples((uint8_t*)samples,WAV_CHUNK_SIZE/2);
4431 EXIT_TIMER(total);
4433 if (!written || SongCompleted()) {
4434 print_timers(last_path,track);
4435 reset_profile_timers();
4437 track++;
4438 if (usingplaylist) {
4439 if (track>=nPlaylistSize) break;
4440 } else {
4441 if (track>=nTrackCount) break;
4443 dontresettrack=1;
4444 goto init_nsf;
4447 ci->pcmbuf_insert(samples, NULL, written >> 1);
4450 print_timers(last_path,track);
4452 if (ci->request_next_track()) {
4453 if (ci->global_settings->repeat_mode==REPEAT_ONE) {
4454 /* in repeat one mode just advance to the next track */
4455 track++;
4456 if (track>=nTrackCount) track=0;
4457 dontresettrack=1;
4458 /* at this point we can't tell if another file has been selected */
4459 goto next_track;
4460 } else {
4461 /* otherwise do a proper load of the next file */
4462 dontresettrack=0;
4463 last_path[0]='\0';
4465 goto next_track; /* when we fall through here we'll reload the file */
4468 return CODEC_OK;