summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorAdam Gashlin <agashlin@gmail.com>2007-01-25 18:06:17 +0000
committerAdam Gashlin <agashlin@gmail.com>2007-01-25 18:06:17 +0000
commit5d20c9d1216f1ccce1921884bfa4c0737a6f69ee (patch)
tree00b7db687a040a03db99bf983c148bb1ff69bc2e /apps
parent2e020e6e1e12dc471c99399cdbc85006b482f6be (diff)
downloadrockbox-5d20c9d1216f1ccce1921884bfa4c0737a6f69ee.tar.gz
rockbox-5d20c9d1216f1ccce1921884bfa4c0737a6f69ee.zip
adding NSF (NES music) codec
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@12112 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps')
-rw-r--r--apps/codecs/Makefile1
-rw-r--r--apps/codecs/SOURCES1
-rw-r--r--apps/codecs/nsf.c4513
-rw-r--r--apps/metadata.c11
-rw-r--r--apps/tree.c2
5 files changed, 4528 insertions, 0 deletions
diff --git a/apps/codecs/Makefile b/apps/codecs/Makefile
index 56e56403fd..f491a5be7f 100644
--- a/apps/codecs/Makefile
+++ b/apps/codecs/Makefile
@@ -51,6 +51,7 @@ $(BUILDDIR)/%.a : % $(CODECDEPS)
51$(OBJDIR)/wav.elf : $(OBJDIR)/wav.o 51$(OBJDIR)/wav.elf : $(OBJDIR)/wav.o
52$(OBJDIR)/sid.elf : $(OBJDIR)/sid.o 52$(OBJDIR)/sid.elf : $(OBJDIR)/sid.o
53$(OBJDIR)/adx.elf : $(OBJDIR)/adx.o 53$(OBJDIR)/adx.elf : $(OBJDIR)/adx.o
54$(OBJDIR)/nsf.elf : $(OBJDIR)/nsf.o
54$(OBJDIR)/aiff.elf : $(OBJDIR)/aiff.o 55$(OBJDIR)/aiff.elf : $(OBJDIR)/aiff.o
55$(OBJDIR)/mpa.elf : $(OBJDIR)/mpa.o $(BUILDDIR)/libmad.a 56$(OBJDIR)/mpa.elf : $(OBJDIR)/mpa.o $(BUILDDIR)/libmad.a
56$(OBJDIR)/a52.elf : $(OBJDIR)/a52.o $(BUILDDIR)/liba52.a 57$(OBJDIR)/a52.elf : $(OBJDIR)/a52.o $(BUILDDIR)/liba52.a
diff --git a/apps/codecs/SOURCES b/apps/codecs/SOURCES
index 68bb04f926..51ccd2a2b6 100644
--- a/apps/codecs/SOURCES
+++ b/apps/codecs/SOURCES
@@ -15,6 +15,7 @@ shorten.c
15aiff.c 15aiff.c
16sid.c 16sid.c
17adx.c 17adx.c
18nsf.c
18#if defined(HAVE_RECORDING) && !defined(SIMULATOR) 19#if defined(HAVE_RECORDING) && !defined(SIMULATOR)
19/* encoders */ 20/* encoders */
20aiff_enc.c 21aiff_enc.c
diff --git a/apps/codecs/nsf.c b/apps/codecs/nsf.c
new file mode 100644
index 0000000000..8ea7047177
--- /dev/null
+++ b/apps/codecs/nsf.c
@@ -0,0 +1,4513 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2006 Adam Gashlin (hcs)
10 * Copyright (C) 2004 Disch
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20/*
21 * This is a perversion of Disch's excellent NotSoFatso.
22 */
23
24#include "codeclib.h"
25#include "inttypes.h"
26#include "system.h"
27
28CODEC_HEADER
29
30/* arm doesn't benefit from IRAM? */
31#ifdef CPU_ARM
32#undef ICODE_ATTR
33#define ICODE_ATTR
34#undef IDATA_ATTR
35#define IDATA_ATTR
36#else
37#define ICODE_INSTEAD_OF_INLINE
38#endif
39
40/* Maximum number of bytes to process in one iteration */
41#define WAV_CHUNK_SIZE (1024*2)
42
43static int16_t samples[WAV_CHUNK_SIZE] IBSS_ATTR;
44
45#define ZEROMEMORY(addr,size) memset(addr,0,size)
46
47/* simple profiling with USEC_TIMER
48
49#define NSF_PROFILE
50
51*/
52
53#ifdef NSF_PROFILE
54
55#define CREATE_TIMER(name) uint32_t nsf_timer_##name##_start,\
56 nsf_timer_##name##_total
57#define ENTER_TIMER(name) nsf_timer_##name##_start=USEC_TIMER
58#define EXIT_TIMER(name) nsf_timer_##name##_total+=\
59 (USEC_TIMER-nsf_timer_##name##_start)
60#define READ_TIMER(name) (nsf_timer_##name##_total)
61#define RESET_TIMER(name) nsf_timer_##name##_total=0
62
63#define PRINT_TIMER_PCT(bname,tname,nstr) ci->fdprintf(
64 logfd,"%10ld ",READ_TIMER(bname));\
65 ci->fdprintf(logfd,"(%3d%%) " nstr "\t",\
66 ((uint64_t)READ_TIMER(bname))*100/READ_TIMER(tname))
67
68CREATE_TIMER(total);
69CREATE_TIMER(cpu);
70CREATE_TIMER(apu);
71CREATE_TIMER(squares);
72CREATE_TIMER(tnd);
73CREATE_TIMER(tnd_enter);
74CREATE_TIMER(tnd_tri);
75CREATE_TIMER(tnd_noise);
76CREATE_TIMER(tnd_dmc);
77CREATE_TIMER(fds);
78CREATE_TIMER(frame);
79CREATE_TIMER(mix);
80
81void reset_profile_timers(void) {
82 RESET_TIMER(total);
83 RESET_TIMER(cpu);
84 RESET_TIMER(apu);
85 RESET_TIMER(squares);
86 RESET_TIMER(tnd);
87 RESET_TIMER(tnd_enter);
88 RESET_TIMER(tnd_tri);
89 RESET_TIMER(tnd_noise);
90 RESET_TIMER(tnd_dmc);
91 RESET_TIMER(fds);
92 RESET_TIMER(frame);
93 RESET_TIMER(mix);
94}
95
96int logfd=-1;
97
98void print_timers(char * path, int track) {
99 logfd = ci->open("/nsflog.txt",O_WRONLY|O_CREAT|O_APPEND);
100 ci->fdprintf(logfd,"%s[%d]:\t",path,track);
101 ci->fdprintf(logfd,"%10ld total\t",READ_TIMER(total));
102 PRINT_TIMER_PCT(cpu,total,"CPU");
103 PRINT_TIMER_PCT(apu,total,"APU");
104 ci->fdprintf(logfd,"\n\t");
105 PRINT_TIMER_PCT(squares,apu,"squares");
106 PRINT_TIMER_PCT(frame,apu,"frame");
107 PRINT_TIMER_PCT(mix,apu,"mix");
108 PRINT_TIMER_PCT(fds,apu,"FDS");
109 PRINT_TIMER_PCT(tnd,apu,"tnd");
110 ci->fdprintf(logfd,"\n\t\t");
111 PRINT_TIMER_PCT(tnd_enter,tnd,"enter");
112 PRINT_TIMER_PCT(tnd_tri,tnd,"triangle");
113 PRINT_TIMER_PCT(tnd_noise,tnd,"noise");
114 PRINT_TIMER_PCT(tnd_dmc,tnd,"DMC");
115 ci->fdprintf(logfd,"\n");
116
117 ci->close(logfd);
118 logfd=-1;
119}
120
121#else
122
123#define CREATE_TIMER(name)
124#define ENTER_TIMER(name)
125#define EXIT_TIMER(name)
126#define READ_TIMER(name)
127#define RESET_TIMER(name)
128#define print_timers(path,track)
129#define reset_profile_timers()
130
131#endif
132
133/* proper handling of multibyte values */
134#ifdef ROCKBOX_LITTLE_ENDIAN
135union TWIN
136{
137 uint16_t W;
138 struct{ uint8_t l; uint8_t h; } B;
139};
140
141union QUAD
142{
143 uint32_t D;
144 struct{ uint8_t l; uint8_t h; uint16_t w; } B;
145};
146#else
147
148union TWIN
149{
150 uint16_t W;
151 struct{ uint8_t h; uint8_t l; } B;
152};
153
154union QUAD
155{
156 uint32_t D;
157 struct{uint16_t w; uint8_t h; uint8_t l; } B;
158};
159
160#endif
161
162#define NTSC_FREQUENCY 1789772.727273f
163#define PAL_FREQUENCY 1652097.692308f
164#define NTSC_NMIRATE 60.098814f
165#define PAL_NMIRATE 50.006982f
166
167#define NES_FREQUENCY 21477270
168#define NTSC_FRAME_COUNTER_FREQ (NTSC_FREQUENCY / (NES_FREQUENCY / 89490.0f))
169#define PAL_FRAME_COUNTER_FREQ (PAL_FREQUENCY / (NES_FREQUENCY / 89490.0f))
170
171/****************** tables */
172static const int32_t ModulationTable[8] ICONST_ATTR = {0,1,2,4,0,-4,-2,-1};
173const uint16_t DMC_FREQ_TABLE[2][0x10] = {
174 /* NTSC */
175 {0x1AC,0x17C,0x154,0x140,0x11E,0x0FE,0x0E2,0x0D6,0x0BE,0x0A0,0x08E,0x080,
176 0x06A,0x054,0x048,0x036},
177 /* PAL */
178 {0x18C,0x160,0x13A,0x128,0x108,0x0EA,0x0D0,0x0C6,0x0B0,0x094,0x082,0x076,
179 0x062,0x04E,0x042,0x032}
180};
181
182const uint8_t DUTY_CYCLE_TABLE[4] = {2,4,8,12};
183
184const uint8_t LENGTH_COUNTER_TABLE[0x20] = {
185 0x0A,0xFE,0x14,0x02,0x28,0x04,0x50,0x06,0xA0,0x08,0x3C,0x0A,0x0E,0x0C,0x1A,
186 0x0E,0x0C,0x10,0x18,0x12,0x30,0x14,0x60,0x16,0xC0,0x18,0x48,0x1A,0x10,0x1C,
187 0x20,0x1E
188};
189
190const uint16_t NOISE_FREQ_TABLE[0x10] = {
191 0x004,0x008,0x010,0x020,0x040,0x060,0x080,0x0A0,0x0CA,0x0FE,0x17C,0x1FC,
192 0x2FA,0x3F8,0x7F2,0xFE4
193};
194
195/****************** NSF loading ******************/
196
197/* file format structs (both are little endian) */
198
199struct NESM_HEADER
200{
201 uint32_t nHeader;
202 uint8_t nHeaderExtra;
203 uint8_t nVersion;
204 uint8_t nTrackCount;
205 uint8_t nInitialTrack;
206 uint16_t nLoadAddress;
207 uint16_t nInitAddress;
208 uint16_t nPlayAddress;
209 uint8_t szGameTitle[32];
210 uint8_t szArtist[32];
211 uint8_t szCopyright[32];
212 uint16_t nSpeedNTSC;
213 uint8_t nBankSwitch[8];
214 uint16_t nSpeedPAL;
215 uint8_t nNTSC_PAL;
216 uint8_t nExtraChip;
217 uint8_t nExpansion[4];
218};
219
220struct NSFE_INFOCHUNK
221{
222 uint16_t nLoadAddress;
223 uint16_t nInitAddress;
224 uint16_t nPlayAddress;
225 uint8_t nIsPal;
226 uint8_t nExt;
227 uint8_t nTrackCount;
228 uint8_t nStartingTrack;
229};
230
231int32_t LoadFile(uint8_t *,size_t);
232
233int32_t LoadFile_NESM(uint8_t *,size_t);
234int32_t LoadFile_NSFE(uint8_t *,size_t);
235
236/* NSF file info */
237
238/* basic NSF info */
239int32_t bIsExtended=0; /* 0 = NSF, 1 = NSFE */
240uint8_t nIsPal=0; /* 0 = NTSC, 1 = PAL,
241 2,3 = mixed NTSC/PAL (interpretted as NTSC) */
242int32_t nfileLoadAddress=0; /* The address to which the NSF code is
243 loaded */
244int32_t nfileInitAddress=0; /* The address of the Init routine
245 (called at track change) */
246int32_t nfilePlayAddress=0; /* The address of the Play routine
247 (called several times a second) */
248uint8_t nChipExtensions=0; /* Bitwise representation of the external chips
249 used by this NSF. */
250
251/* old NESM speed stuff (blarg) */
252int32_t nNTSC_PlaySpeed=0;
253int32_t nPAL_PlaySpeed=0;
254
255/* track info */
256/* The number of tracks in the NSF (1 = 1 track, 5 = 5 tracks, etc) */
257int32_t nTrackCount=0;
258/* The initial track (ZERO BASED: 0 = 1st track, 4 = 5th track, etc) */
259int32_t nInitialTrack=0;
260
261/* nsf data */
262uint8_t* pDataBuffer=0; /* the buffer containing NSF code. */
263int32_t nDataBufferSize=0; /* the size of the above buffer. */
264
265/* playlist */
266uint8_t nPlaylist[256]; /* Each entry is the zero based index of the
267 song to play */
268int32_t nPlaylistSize=0; /* the number of tracks in the playlist */
269
270/* track time / fade */
271int32_t nTrackTime[256]; /* track times -1 if no track times specified */
272int32_t nTrackFade[256]; /* track fade times -1 if none are specified */
273
274/* string info */
275uint8_t szGameTitle[0x101];
276uint8_t szArtist[0x101];
277uint8_t szCopyright[0x101];
278uint8_t szRipper[0x101];
279
280/* bankswitching info */
281uint8_t nBankswitch[8]={0}; /* The initial bankswitching registers needed
282 * for some NSFs. If the NSF does not use
283 * bankswitching, these values will all be zero
284 */
285
286int32_t LoadFile(uint8_t * inbuffer, size_t size)
287{
288 if(!inbuffer) return -1;
289
290 int32_t ret = -1;
291
292 if(!memcmp(inbuffer,"NESM",4)) ret = LoadFile_NESM(inbuffer,size);
293 if(!memcmp(inbuffer,"NSFE",4)) ret = LoadFile_NSFE(inbuffer,size);
294
295 /*
296 * Snake's revenge puts '00' for the initial track,
297 * which (after subtracting 1) makes it 256 or -1 (bad!)
298 * This prevents that crap
299 */
300 if(nInitialTrack >= nTrackCount)
301 nInitialTrack = 0;
302 if(nInitialTrack < 0)
303 nInitialTrack = 0;
304
305 /* if there's no tracks... this is a crap NSF */
306 if(nTrackCount < 1)
307 {
308 return -1;
309 }
310
311 return ret;
312}
313
314int32_t LoadFile_NESM(uint8_t* inbuffer, size_t size)
315{
316 uint8_t ignoreversion=1;
317 uint8_t needdata=1;
318
319 /* read the info */
320 struct NESM_HEADER hdr;
321
322 memcpy(&hdr,inbuffer,sizeof(hdr));
323
324 /* confirm the header */
325 if(memcmp("NESM",&(hdr.nHeader),4)) return -1;
326 if(hdr.nHeaderExtra != 0x1A) return -1;
327 /* stupid NSFs claim to be above version 1 >_> */
328 if((!ignoreversion) && (hdr.nVersion != 1)) return -1;
329
330 /*
331 * NESM is generally easier to work with (but limited!)
332 * just move the data over from NESM_HEADER over to our member data
333 */
334
335 bIsExtended = 0;
336 nIsPal = hdr.nNTSC_PAL & 0x03;
337 nPAL_PlaySpeed = letoh16(hdr.nSpeedPAL);
338 nNTSC_PlaySpeed = letoh16(hdr.nSpeedNTSC);
339 nfileLoadAddress = letoh16(hdr.nLoadAddress);
340 nfileInitAddress = letoh16(hdr.nInitAddress);
341 nfilePlayAddress = letoh16(hdr.nPlayAddress);
342 nChipExtensions = hdr.nExtraChip;
343
344
345 nTrackCount = hdr.nTrackCount;
346 nInitialTrack = hdr.nInitialTrack - 1;
347
348 memcpy(nBankswitch,hdr.nBankSwitch,8);
349
350 memcpy(szGameTitle,hdr.szGameTitle,32);
351 memcpy(szArtist ,hdr.szArtist ,32);
352 memcpy(szCopyright,hdr.szCopyright,32);
353
354 /* read the NSF data */
355 if(needdata)
356 {
357 pDataBuffer=inbuffer+0x80;
358 nDataBufferSize=size-0x80;
359 }
360
361 /* if we got this far... it was a successful read */
362 return 0;
363}
364
365int32_t LoadFile_NSFE(uint8_t* inbuffer, size_t size)
366{
367 /* the vars we'll be using */
368 uint32_t nChunkType;
369 int32_t nChunkSize;
370 int32_t nChunkUsed;
371 int32_t i;
372 uint8_t * nDataPos = 0;
373 uint8_t bInfoFound = 0;
374 uint8_t bEndFound = 0;
375 uint8_t bBankFound = 0;
376 nPlaylistSize=-1;
377
378 struct NSFE_INFOCHUNK info;
379 ZEROMEMORY(&info,sizeof(struct NSFE_INFOCHUNK));
380 ZEROMEMORY(nBankswitch,8);
381 info.nTrackCount = 1; /* default values */
382
383 if (size < 8) return -1; /* must have at least NSFE,NEND */
384
385 /* confirm the header! */
386 memcpy(&nChunkType,inbuffer,4);
387 inbuffer+=4;
388 if(memcmp(&nChunkType,"NSFE",4)) return -1;
389
390 for (i=0;i<256;i++) {
391 nTrackTime[i]=-1;
392 nTrackFade[i]=-1;
393 }
394
395 /* begin reading chunks */
396 while(!bEndFound)
397 {
398 memcpy(&nChunkSize,inbuffer,4);
399 nChunkSize=letoh32(nChunkSize);
400 inbuffer+=4;
401 memcpy(&nChunkType,inbuffer,4);
402 inbuffer+=4;
403
404 if(!memcmp(&nChunkType,"INFO",4)) {
405 /* only one info chunk permitted */
406 if(bInfoFound) return -1;
407 if(nChunkSize < 8) return -1; /* minimum size */
408
409 bInfoFound = 1;
410 nChunkUsed = MIN((int32_t)sizeof(struct NSFE_INFOCHUNK),
411 nChunkSize);
412
413 memcpy(&info,inbuffer,nChunkUsed);
414 inbuffer+=nChunkSize;
415
416 bIsExtended = 1;
417 nIsPal = info.nIsPal & 3;
418 nfileLoadAddress = letoh16(info.nLoadAddress);
419 nfileInitAddress = letoh16(info.nInitAddress);
420 nfilePlayAddress = letoh16(info.nPlayAddress);
421 nChipExtensions = info.nExt;
422 nTrackCount = info.nTrackCount;
423 nInitialTrack = info.nStartingTrack;
424
425 nPAL_PlaySpeed = (uint16_t)(1000000 / PAL_NMIRATE);
426 nNTSC_PlaySpeed = (uint16_t)(1000000 / NTSC_NMIRATE);
427 } else if (!memcmp(&nChunkType,"DATA",4)) {
428 if(!bInfoFound) return -1;
429 if(nDataPos) return -1;
430 if(nChunkSize < 1) return -1;
431
432 nDataBufferSize = nChunkSize;
433 nDataPos = inbuffer;
434
435 inbuffer+=nChunkSize;
436 } else if (!memcmp(&nChunkType,"NEND",4)) {
437 bEndFound = 1;
438 } else if (!memcmp(&nChunkType,"time",4)) {
439 if(!bInfoFound) return -1;
440 for (nChunkUsed=0; nChunkUsed < MIN(nChunkSize / 4,nTrackCount);
441 nChunkUsed++,inbuffer+=4) {
442 nTrackTime[nChunkUsed]=
443 ((uint32_t)inbuffer[0])|
444 ((uint32_t)inbuffer[1]<<8)|
445 ((uint32_t)inbuffer[2]<<16)|
446 ((uint32_t)inbuffer[3]<<24);
447 }
448
449 inbuffer+=nChunkSize-(nChunkUsed*4);
450
451 /* negative signals to use default time */
452 for(; nChunkUsed < nTrackCount; nChunkUsed++)
453 nTrackTime[nChunkUsed] = -1;
454 } else if (!memcmp(&nChunkType,"fade",4)) {
455 if(!bInfoFound) return -1;
456 for (nChunkUsed=0; nChunkUsed < MIN(nChunkSize / 4,nTrackCount);
457 nChunkUsed++,inbuffer+=4) {
458 nTrackFade[nChunkUsed]=
459 ((uint32_t)inbuffer[0])|
460 ((uint32_t)inbuffer[1]<<8)|
461 ((uint32_t)inbuffer[2]<<16)|
462 ((uint32_t)inbuffer[3]<<24);
463 }
464
465 inbuffer+=nChunkSize-(nChunkUsed*4);
466
467 /* negative signals to use default time */
468 for(; nChunkUsed < nTrackCount; nChunkUsed++)
469 nTrackFade[nChunkUsed] = -1;
470 } else if (!memcmp(&nChunkType,"BANK",4)) {
471 if(bBankFound) return -1;
472
473 bBankFound = 1;
474 nChunkUsed = MIN(8,nChunkSize);
475 memcpy(nBankswitch,inbuffer,nChunkUsed);
476
477 inbuffer+=nChunkSize;
478 } else if (!memcmp(&nChunkType,"plst",4)) {
479
480 nPlaylistSize = nChunkSize;
481 if(nPlaylistSize >= 1) {
482
483 memcpy(nPlaylist,inbuffer,nChunkSize);
484 inbuffer+=nChunkSize;
485 }
486 } else if (!memcmp(&nChunkType,"auth",4)) {
487 uint8_t* ptr;
488
489 ptr = inbuffer;
490
491 uint8_t* ar[4] = {szGameTitle,szArtist,szCopyright,szRipper};
492 int32_t i;
493 for(i = 0; (ptr-inbuffer)<nChunkSize && i < 4; i++)
494 {
495 nChunkUsed = strlen(ptr) + 1;
496 memcpy(ar[i],ptr,nChunkUsed);
497 ptr += nChunkUsed;
498 }
499 inbuffer+=nChunkSize;
500 } else if (!memcmp(&nChunkType,"tlbl",4)) {
501 /* we unfortunately can't use these anyway */
502 inbuffer+=nChunkSize;
503 } else { /* unknown chunk */
504 nChunkType = letoh32(nChunkType)>>24; /* check the first byte */
505 /* chunk is vital... don't continue */
506 if((nChunkType >= 'A') && (nChunkType <= 'Z'))
507 return -1;
508 /* otherwise, just skip it */
509 inbuffer+=nChunkSize;
510 } /* end if series */
511 } /* end while */
512
513 /*
514 * if we exited the while loop without a 'return', we must have hit an NEND
515 * chunk if this is the case, the file was layed out as it was expected.
516 * now.. make sure we found both an info chunk, AND a data chunk... since
517 * these are minimum requirements for a valid NSFE file
518 */
519
520 if(!bInfoFound) return -1;
521 if(!nDataPos) return -1;
522
523 /* if both those chunks existed, this file is valid.
524 Load the data if it's needed */
525
526 pDataBuffer=nDataPos;
527
528 /* return success! */
529 return 0;
530}
531
532
533/****************** Audio Device Structures ******************/
534
535struct FDSWave
536{
537 /* Envelope Unit */
538 uint8_t bEnvelopeEnable;
539 uint8_t nEnvelopeSpeed;
540
541 /* Volume Envelope */
542 uint8_t nVolEnv_Mode;
543 uint8_t nVolEnv_Decay;
544 uint8_t nVolEnv_Gain;
545 int32_t nVolEnv_Timer;
546 int32_t nVolEnv_Count;
547 uint8_t nVolume;
548 uint8_t bVolEnv_On;
549
550 /* Sweep Envenlope */
551 uint8_t nSweep_Mode;
552 uint8_t nSweep_Decay;
553 int32_t nSweep_Timer;
554 int32_t nSweep_Count;
555 uint8_t nSweep_Gain;
556 uint8_t bSweepEnv_On;
557
558 /* Effector / LFO / Modulation Unit */
559 int32_t nSweepBias;
560 uint8_t bLFO_Enabled;
561 union TWIN nLFO_Freq;
562 /*float fLFO_Timer;*/
563 /*float fLFO_Count;*/
564 int32_t nLFO_Timer; /* -17.14*/
565 int32_t nLFO_Count; /* -17.14*/
566 uint8_t nLFO_Addr;
567 uint8_t nLFO_Table[0x40];
568 uint8_t bLFO_On;
569
570 /* Main Output */
571 uint8_t nMainVolume;
572 uint8_t bEnabled;
573 union TWIN nFreq;
574 /*float fFreqCount;*/
575 int32_t nFreqCount; /* -17.14 */
576 uint8_t nMainAddr;
577 uint8_t nWaveTable[0x40];
578 uint8_t bWaveWrite;
579 uint8_t bMain_On;
580
581 /* Output and Downsampling */
582 int32_t nMixL;
583
584 /* Pop Reducer */
585 uint8_t bPopReducer;
586 uint8_t nPopOutput;
587 int32_t nPopCount;
588
589};
590int16_t FDS_nOutputTable_L[4][0x21][0x40];
591
592struct FME07Wave
593{
594 /* Frequency Control */
595 union TWIN nFreqTimer;
596 int32_t nFreqCount;
597
598 /* Channel Disabling */
599 uint8_t bChannelEnabled;
600
601 /* Volume */
602 uint8_t nVolume;
603
604 /* Duty Cycle */
605 uint8_t nDutyCount;
606
607 /* Output and Downsampling */
608 int32_t nMixL;
609};
610
611int16_t FME07_nOutputTable_L[3][0x10] IDATA_ATTR;
612
613struct N106Wave
614{
615 /* All Channel Stuff */
616
617 uint8_t nActiveChannels;
618 uint8_t bAutoIncrement;
619 uint8_t nCurrentAddress;
620 uint8_t nRAM[0x100]; /* internal memory for registers/wave data */
621 float fFrequencyLookupTable[8]; /* lookup tbl for freq conversions */
622
623 /*
624 * Individual channel stuff
625 */
626 /* Wavelength / Frequency */
627 union QUAD nFreqReg[8];
628 float fFreqTimer[8];
629 float fFreqCount[8];
630
631 /* Wave data length / remaining */
632 uint8_t nWaveSize[8];
633 uint8_t nWaveRemaining[8];
634
635 /* Wave data position */
636 uint8_t nWavePosStart[8];
637 uint8_t nWavePos[8];
638 uint8_t nOutput[8];
639
640 /* Volume */
641 uint8_t nVolume[8];
642
643 /* Pop Reducer */
644 uint8_t nPreVolume[8];
645 uint8_t nPopCheck[8];
646
647 /* Mixing */
648 int32_t nMixL[8];
649};
650
651int16_t N106_nOutputTable_L[8][0x10][0x10];
652
653struct VRC6PulseWave
654{
655
656 /* Frequency Control */
657 union TWIN nFreqTimer;
658 int32_t nFreqCount;
659
660 /* Flags */
661 uint8_t bChannelEnabled;
662 uint8_t bDigitized;
663
664 /* Volume */
665 uint8_t nVolume;
666
667 /* Duty Cycle */
668 uint8_t nDutyCycle;
669 uint8_t nDutyCount;
670
671 /* Output and Downsampling */
672 int32_t nMixL;
673
674};
675
676int16_t VRC6Pulse_nOutputTable_L[2][0x10] IDATA_ATTR;
677
678struct VRC6SawWave
679{
680
681 /* Frequency Control */
682 union TWIN nFreqTimer;
683 int32_t nFreqCount;
684
685 /* Flags */
686 uint8_t bChannelEnabled;
687
688 /* Phase Accumulator */
689 uint8_t nAccumRate;
690 uint8_t nAccum;
691 uint8_t nAccumStep;
692
693 /* Output and Downsampling */
694 int32_t nMixL;
695
696};
697
698int16_t VRC6Saw_nOutputTable_L[0x20] IDATA_ATTR;
699
700struct Wave_Squares
701{
702
703 /* Programmable Timer */
704 union TWIN nFreqTimer[2];
705 int32_t nFreqCount[2];
706
707 /* Length Counter */
708 uint8_t nLengthCount[2];
709 uint8_t bLengthEnabled[2];
710 uint8_t bChannelEnabled[2];
711
712 /* Volume / Decay */
713 uint8_t nVolume[2];
714 uint8_t nDecayVolume[2];
715 uint8_t bDecayEnable[2];
716 uint8_t bDecayLoop[2];
717 uint8_t nDecayTimer[2];
718 uint8_t nDecayCount[2];
719
720 /* Sweep Unit */
721 uint8_t bSweepEnable[2];
722 uint8_t bSweepMode[2];
723 uint8_t bSweepForceSilence[2];
724 uint8_t nSweepTimer[2];
725 uint8_t nSweepCount[2];
726 uint8_t nSweepShift[2];
727
728 /* Duty Cycle */
729 uint8_t nDutyCount[2];
730 uint8_t nDutyCycle[2];
731
732 /* Output and Downsampling */
733 int32_t nMixL;
734};
735
736int16_t Squares_nOutputTable_L[0x100] IDATA_ATTR;
737
738struct Wave_TND
739{
740
741 /*
742 * Triangle
743 */
744
745 /* Programmable Timer */
746 union TWIN nTriFreqTimer;
747 int32_t nTriFreqCount;
748
749 /* Length Counter */
750 uint8_t nTriLengthCount;
751 uint8_t bTriLengthEnabled;
752 uint8_t bTriChannelEnabled;
753
754 /* Linear Counter */
755 uint8_t nTriLinearCount;
756 uint8_t nTriLinearLoad;
757 uint8_t bTriLinearHalt;
758 uint8_t bTriLinearControl;
759
760 /* Tri-Step Generator / Output */
761 uint8_t nTriStep;
762 uint8_t nTriOutput;
763
764 /*
765 * Noise
766 */
767
768 /* Programmable Timer */
769 uint16_t nNoiseFreqTimer;
770 int32_t nNoiseFreqCount;
771
772 /* Length Counter */
773 uint8_t nNoiseLengthCount;
774 uint8_t bNoiseLengthEnabled;
775 uint8_t bNoiseChannelEnabled;
776
777 /* Volume / Decay */
778 uint8_t nNoiseVolume;
779 uint8_t nNoiseDecayVolume;
780 uint8_t bNoiseDecayEnable;
781 uint8_t bNoiseDecayLoop;
782 uint8_t nNoiseDecayTimer;
783 uint8_t nNoiseDecayCount;
784
785 /* Random Number Generator */
786 uint16_t nNoiseRandomShift;
787 uint8_t bNoiseRandomMode; /* 1 = 32k, 6 = 93-bit */
788 uint8_t bNoiseRandomOut;
789
790 /*
791 * DMC
792 */
793
794 /* Play Mode */
795 uint8_t bDMCLoop;
796 uint8_t bDMCIRQEnabled;
797 uint8_t bDMCIRQPending;
798
799 /* Address / DMA */
800 uint8_t nDMCDMABank_Load;
801 uint16_t nDMCDMAAddr_Load;
802 uint8_t nDMCDMABank;
803 uint16_t nDMCDMAAddr;
804 uint8_t* pDMCDMAPtr[8];
805
806 /* Length / Input */
807 uint16_t nDMCLength;
808 uint16_t nDMCBytesRemaining;
809 uint8_t nDMCDelta;
810 uint8_t nDMCDeltaBit;
811 uint8_t bDMCDeltaSilent;
812 uint8_t nDMCSampleBuffer;
813 uint8_t bDMCSampleBufferEmpty;
814
815 /* Frequency */
816 uint16_t nDMCFreqTimer;
817 int32_t nDMCFreqCount;
818
819 /* Output */
820 uint8_t bDMCActive;
821 uint8_t nDMCOutput;
822
823 int32_t nMixL;
824};
825
826/* channels */
827struct Wave_Squares mWave_Squares IDATA_ATTR; /* Square channels 1 and 2 */
828struct Wave_TND mWave_TND IDATA_ATTR; /* Triangle/Noise/DMC channels */
829struct VRC6PulseWave mWave_VRC6Pulse[2] IDATA_ATTR;
830struct VRC6SawWave mWave_VRC6Saw IDATA_ATTR;
831struct N106Wave mWave_N106;
832struct FDSWave mWave_FDS IDATA_ATTR;
833struct FME07Wave mWave_FME07[3] IDATA_ATTR; /* FME-07's 3 pulse channels */
834
835
836/****************** MMC5 ******************/
837/* will include MMC5 sound channels some day,
838 currently only multiply is supported */
839
840/****************** N106 (Disch loves this chip) ******************/
841
842#ifdef ICODE_INSTEAD_OF_INLINE
843void Wave_N106_DoTicks(const int32_t ticks) ICODE_ATTR;
844void Wave_N106_DoTicks(const int32_t ticks)
845#else
846inline void Wave_N106_DoTicks(const int32_t ticks);
847inline void Wave_N106_DoTicks(const int32_t ticks)
848#endif
849{
850 register int32_t i;
851
852 for(i = (7 - mWave_N106.nActiveChannels); i < 8; i++)
853 {
854 if(!mWave_N106.nFreqReg[i].D)
855 {
856 /* written frequency of zero will cause divide by zero error
857 makes me wonder if the formula was supposed to be Reg+1 */
858 mWave_N106.nVolume[i] = mWave_N106.nPreVolume[i];
859 continue;
860 }
861
862 {
863 mWave_N106.nMixL[i] =
864 N106_nOutputTable_L[i][mWave_N106.nVolume[i]]
865 [mWave_N106.nOutput[i]];
866
867 if(mWave_N106.fFreqTimer[i] < 0)
868 mWave_N106.fFreqTimer[i] =
869 (mWave_N106.fFrequencyLookupTable[mWave_N106.nActiveChannels] /
870 mWave_N106.nFreqReg[i].D);
871 if(mWave_N106.fFreqCount[i] > mWave_N106.fFreqTimer[i])
872 mWave_N106.fFreqCount[i] = mWave_N106.fFreqTimer[i];
873
874 mWave_N106.fFreqCount[i] -= ticks;
875 while(mWave_N106.fFreqCount[i] <= 0)
876 {
877 mWave_N106.fFreqCount[i] += mWave_N106.fFreqTimer[i];
878 if(mWave_N106.nWaveRemaining[i])
879 {
880 mWave_N106.nWaveRemaining[i]--;
881 mWave_N106.nWavePos[i]++;
882 }
883 if(!mWave_N106.nWaveRemaining[i])
884 {
885 mWave_N106.nWaveRemaining[i] = mWave_N106.nWaveSize[i];
886 mWave_N106.nWavePos[i] = mWave_N106.nWavePosStart[i];
887 if(mWave_N106.nVolume[i] != mWave_N106.nPreVolume[i])
888 {
889 if(++mWave_N106.nPopCheck[i] >= 2)
890 {
891 mWave_N106.nPopCheck[i] = 0;
892 mWave_N106.nVolume[i] = mWave_N106.nPreVolume[i];
893 }
894 }
895 }
896
897 mWave_N106.nOutput[i] =
898 mWave_N106.nRAM[mWave_N106.nWavePos[i]];
899
900 if(!mWave_N106.nOutput[i])
901 {
902 mWave_N106.nPopCheck[i] = 0;
903 mWave_N106.nVolume[i] = mWave_N106.nPreVolume[i];
904 }
905
906 }
907 }
908 }
909}
910
911/****************** Square waves ******************/
912
913/* decay */
914#ifdef ICODE_INSTEAD_OF_INLINE
915void Wave_Squares_ClockMajor(void) ICODE_ATTR;
916void Wave_Squares_ClockMajor()
917#else
918inline void Wave_Squares_ClockMajor(void);
919inline void Wave_Squares_ClockMajor()
920#endif
921{
922 if(mWave_Squares.nDecayCount[0])
923 mWave_Squares.nDecayCount[0]--;
924 else
925 {
926 mWave_Squares.nDecayCount[0] = mWave_Squares.nDecayTimer[0];
927 if(mWave_Squares.nDecayVolume[0])
928 mWave_Squares.nDecayVolume[0]--;
929 else
930 {
931 if(mWave_Squares.bDecayLoop[0])
932 mWave_Squares.nDecayVolume[0] = 0x0F;
933 }
934
935 if(mWave_Squares.bDecayEnable[0])
936 mWave_Squares.nVolume[0] = mWave_Squares.nDecayVolume[0];
937 }
938
939 if(mWave_Squares.nDecayCount[1])
940 mWave_Squares.nDecayCount[1]--;
941 else
942 {
943 mWave_Squares.nDecayCount[1] = mWave_Squares.nDecayTimer[1];
944 if(mWave_Squares.nDecayVolume[1])
945 mWave_Squares.nDecayVolume[1]--;
946 else
947 {
948 if(mWave_Squares.bDecayLoop[1])
949 mWave_Squares.nDecayVolume[1] = 0x0F;
950 }
951
952 if(mWave_Squares.bDecayEnable[1])
953 mWave_Squares.nVolume[1] = mWave_Squares.nDecayVolume[1];
954 }
955
956}
957
958
959#ifdef ICODE_INSTEAD_OF_INLINE
960void Wave_Squares_CheckSweepForcedSilence(const int32_t i) ICODE_ATTR;
961void Wave_Squares_CheckSweepForcedSilence(const int32_t i)
962#else
963inline void Wave_Squares_CheckSweepForcedSilence(const int32_t i);
964inline void Wave_Squares_CheckSweepForcedSilence(const int32_t i)
965#endif
966{
967 if(mWave_Squares.nFreqTimer[i].W < 8) {
968 mWave_Squares.bSweepForceSilence[i] = 1; return;
969 }
970 if(!mWave_Squares.bSweepMode[i] &&
971 (( mWave_Squares.nFreqTimer[i].W +
972 (mWave_Squares.nFreqTimer[i].W >> mWave_Squares.nSweepShift[i]))
973 >= 0x0800)) { mWave_Squares.bSweepForceSilence[i] = 1; return; }
974
975 mWave_Squares.bSweepForceSilence[i] = 0;
976}
977
978/* sweep / length */
979#ifdef ICODE_INSTEAD_OF_INLINE
980void Wave_Squares_ClockMinor(void) ICODE_ATTR;
981void Wave_Squares_ClockMinor()
982#else
983inline void Wave_Squares_ClockMinor(void);
984inline void Wave_Squares_ClockMinor()
985#endif
986{
987/* unrolled a little loop
988 static int i = 0;
989 for(i = 0; i < 2; i++)
990 {
991*/
992 if(mWave_Squares.bLengthEnabled[0] && mWave_Squares.nLengthCount[0])
993 mWave_Squares.nLengthCount[0]--;
994
995 if(!mWave_Squares.bSweepEnable[0] || !mWave_Squares.nLengthCount[0] ||
996 mWave_Squares.bSweepForceSilence[0] || !mWave_Squares.nSweepShift[0])
997 goto other_square;
998
999 if(mWave_Squares.nSweepCount[0])
1000 mWave_Squares.nSweepCount[0]--;
1001 else
1002 {
1003 mWave_Squares.nSweepCount[0] = mWave_Squares.nSweepTimer[0];
1004 if(mWave_Squares.bSweepMode[0]) mWave_Squares.nFreqTimer[0].W -=
1005 (mWave_Squares.nFreqTimer[0].W >> mWave_Squares.nSweepShift[0])+1;
1006 else mWave_Squares.nFreqTimer[0].W +=
1007 (mWave_Squares.nFreqTimer[0].W >> mWave_Squares.nSweepShift[0]);
1008
1009 Wave_Squares_CheckSweepForcedSilence(0);
1010 }
1011
1012 /* */
1013other_square:
1014 if(mWave_Squares.bLengthEnabled[1] && mWave_Squares.nLengthCount[1])
1015 mWave_Squares.nLengthCount[1]--;
1016
1017 if(!mWave_Squares.bSweepEnable[1] || !mWave_Squares.nLengthCount[1] ||
1018 mWave_Squares.bSweepForceSilence[1] || !mWave_Squares.nSweepShift[1])
1019 return;
1020
1021 if(mWave_Squares.nSweepCount[1])
1022 mWave_Squares.nSweepCount[1]--;
1023 else
1024 {
1025 mWave_Squares.nSweepCount[1] = mWave_Squares.nSweepTimer[1];
1026 if(mWave_Squares.bSweepMode[1]) mWave_Squares.nFreqTimer[1].W -=
1027 (mWave_Squares.nFreqTimer[1].W >> mWave_Squares.nSweepShift[1]);
1028 else mWave_Squares.nFreqTimer[1].W +=
1029 (mWave_Squares.nFreqTimer[1].W >> mWave_Squares.nSweepShift[1]);
1030
1031 Wave_Squares_CheckSweepForcedSilence(1);
1032 }
1033}
1034
1035/****************** Triangle/noise/DMC ******************/
1036
1037/* decay (noise), linear (tri) */
1038
1039#ifdef ICODE_INSTEAD_OF_INLINE
1040void Wave_TND_ClockMajor(void) ICODE_ATTR;
1041void Wave_TND_ClockMajor()
1042#else
1043inline void Wave_TND_ClockMajor(void);
1044inline void Wave_TND_ClockMajor()
1045#endif
1046{
1047 /* noise's decay */
1048 if(mWave_TND.nNoiseDecayCount)
1049 mWave_TND.nNoiseDecayCount--;
1050 else
1051 {
1052 mWave_TND.nNoiseDecayCount = mWave_TND.nNoiseDecayTimer;
1053 if(mWave_TND.nNoiseDecayVolume)
1054 mWave_TND.nNoiseDecayVolume--;
1055 else
1056 {
1057 if(mWave_TND.bNoiseDecayLoop)
1058 mWave_TND.nNoiseDecayVolume = 0x0F;
1059 }
1060
1061 if(mWave_TND.bNoiseDecayEnable)
1062 mWave_TND.nNoiseVolume = mWave_TND.nNoiseDecayVolume;
1063 }
1064
1065 /* triangle's linear */
1066 if(mWave_TND.bTriLinearHalt)
1067 mWave_TND.nTriLinearCount = mWave_TND.nTriLinearLoad;
1068 else if(mWave_TND.nTriLinearCount)
1069 mWave_TND.nTriLinearCount--;
1070
1071 if(!mWave_TND.bTriLinearControl)
1072 mWave_TND.bTriLinearHalt = 0;
1073}
1074
1075/* length */
1076
1077#ifdef ICODE_INSTEAD_OF_INLINE
1078void Wave_TND_ClockMinor(void) ICODE_ATTR;
1079void Wave_TND_ClockMinor()
1080#else
1081inline void Wave_TND_ClockMinor(void);
1082inline void Wave_TND_ClockMinor()
1083#endif
1084{
1085 if(mWave_TND.bNoiseLengthEnabled && mWave_TND.nNoiseLengthCount)
1086 mWave_TND.nNoiseLengthCount--;
1087
1088 if(mWave_TND.bTriLengthEnabled && mWave_TND.nTriLengthCount)
1089 mWave_TND.nTriLengthCount--;
1090}
1091
1092/*#undef this*/
1093
1094/****************** NSF Core ******************/
1095
1096/* start globals */
1097/*
1098 * Initialization flags (TODO: make extinct)
1099 */
1100uint8_t bMemoryOK; /* did memory get allocated ok? */
1101uint8_t bFileLoaded; /* is a file loaded? */
1102uint8_t bTrackSelected; /* did they select a track? */
1103uint8_t bIsGeneratingSamples; /* currently generating samples... */
1104
1105/*
1106 * Memory
1107 */
1108/* RAM: 0x0000 - 0x07FF */
1109uint8_t pRAM[0x800] IDATA_ATTR;
1110/* SRAM: 0x6000 - 0x7FFF (non-FDS only) */
1111uint8_t pSRAM[0x2000];
1112/* ExRAM: 0x5C00 - 0x5FF5 (MMC5 only)
1113 * Also holds NSF player code (at 0x5000 - 0x500F) */
1114uint8_t pExRAM[0x1000];
1115/* Full ROM buffer */
1116uint8_t* pROM_Full IDATA_ATTR;
1117
1118uint16_t main_nOutputTable_L[0x8000];
1119
1120uint8_t* pROM[10] IDATA_ATTR;/* ROM banks (point to areas in pROM_Full) */
1121 /* 0x8000 - 0xFFFF */
1122 /* also includes 0x6000 - 0x7FFF (FDS only) */
1123uint8_t* pStack; /* the stack (points to areas in pRAM) */
1124 /* 0x0100 - 0x01FF */
1125
1126int32_t nROMSize; /* size of this ROM file in bytes */
1127int32_t nROMBankCount; /* max number of 4k banks */
1128int32_t nROMMaxSize; /* size of allocated pROM_Full buffer */
1129
1130/*
1131 * Memory Proc Pointers
1132 */
1133
1134typedef uint8_t ( *ReadProc)(uint16_t);
1135typedef void ( *WriteProc)(uint16_t,uint8_t);
1136ReadProc ReadMemory[0x10] IDATA_ATTR;
1137WriteProc WriteMemory[0x10] IDATA_ATTR;
1138
1139/*
1140 * 6502 Registers / Mode
1141 */
1142
1143uint8_t regA IDATA_ATTR; /* Accumulator */
1144uint8_t regX IDATA_ATTR; /* X-Index */
1145uint8_t regY IDATA_ATTR; /* Y-Index */
1146uint8_t regP IDATA_ATTR; /* Processor Status */
1147uint8_t regSP IDATA_ATTR; /* Stack Pointer */
1148uint16_t regPC IDATA_ATTR; /* Program Counter */
1149
1150uint8_t bPALMode IDATA_ATTR;/* 1 if in PAL emulation mode, 0 if in NTSC */
1151uint8_t bCPUJammed IDATA_ATTR; /* 0 = not jammed. 1 = really jammed.
1152 * 2 = 'fake' jammed */
1153 /* fake jam caused by the NSF code to signal
1154 * the end of the play/init routine */
1155
1156/* Multiplication Register, for MMC5 chip only (5205+5206) */
1157uint8_t nMultIn_Low;
1158uint8_t nMultIn_High;
1159
1160/*
1161 * NSF Preparation Information
1162 */
1163
1164uint8_t nBankswitchInitValues[10]; /* banks to swap to on tune init */
1165uint16_t nPlayAddress; /* Play routine address */
1166uint16_t nInitAddress; /* Init routine address */
1167
1168uint8_t nExternalSound; /* external sound chips */
1169uint8_t nCurTrack;
1170
1171float fNSFPlaybackSpeed;
1172
1173/*
1174 * pAPU
1175 */
1176
1177uint8_t nFrameCounter; /* Frame Sequence Counter */
1178uint8_t nFrameCounterMax; /* Frame Sequence Counter Size
1179 (3 or 4 depending on $4017.7) */
1180uint8_t bFrameIRQEnabled; /* TRUE if frame IRQs are enabled */
1181uint8_t bFrameIRQPending; /* TRUE if the frame sequencer is holding down
1182 an IRQ */
1183
1184uint8_t nFME07_Address;
1185
1186/*
1187 * Timing and Counters
1188 */
1189/* fixed point -15.16 */
1190
1191int32_t nTicksUntilNextFrame;
1192int32_t nTicksPerPlay;
1193int32_t nTicksUntilNextPlay;
1194int32_t nTicksPerSample;
1195int32_t nTicksUntilNextSample;
1196
1197uint32_t nCPUCycle IDATA_ATTR;
1198uint32_t nAPUCycle IDATA_ATTR;
1199
1200
1201uint32_t nTotalPlays; /* number of times the play subroutine has been called
1202 (for tracking output time) */
1203/*
1204 * Silence Tracker
1205 */
1206int32_t nSilentSamples;
1207int32_t nSilentSampleMax;
1208int32_t nSilenceTrackMS;
1209uint8_t bNoSilenceIfTime;
1210uint8_t bTimeNotDefault;
1211
1212/*
1213 * Sound output options
1214 */
1215const int32_t nSampleRate=44100;
1216
1217/*
1218 * Volume/fading/filter tracking
1219 */
1220
1221uint32_t nStartFade; /* play call to start fading out */
1222uint32_t nEndFade; /* play call to stop fading out (song is over) */
1223uint8_t bFade; /* are we fading? */
1224float fFadeVolume;
1225float fFadeChange;
1226
1227/*
1228 * Designated Output Buffer
1229 */
1230uint8_t* pOutput IDATA_ATTR;
1231
1232const uint8_t bDMCPopReducer=1;
1233uint8_t nDMCPop_Prev IDATA_ATTR = 0;
1234uint8_t bDMCPop_Skip IDATA_ATTR = 0;
1235uint8_t bDMCPop_SamePlay IDATA_ATTR = 0;
1236
1237const uint8_t nForce4017Write=0;
1238const uint8_t bN106PopReducer=0;
1239const uint8_t bIgnore4011Writes=0;
1240
1241const uint8_t bIgnoreBRK=0;
1242const uint8_t bIgnoreIllegalOps=0;
1243const uint8_t bNoWaitForReturn=0;
1244const uint8_t bPALPreference=0;
1245const uint8_t bCleanAXY=0;
1246const uint8_t bResetDuty=0;
1247
1248/*
1249 * Sound Filter
1250 */
1251
1252int64_t nFilterAccL IDATA_ATTR;
1253int64_t nHighPass IDATA_ATTR;
1254
1255int32_t nHighPassBase IDATA_ATTR;
1256
1257uint8_t bHighPassEnabled IDATA_ATTR;
1258
1259/* end globals */
1260
1261#define CLOCK_MAJOR() { Wave_Squares_ClockMajor(); Wave_TND_ClockMajor(); }
1262#define CLOCK_MINOR() { Wave_Squares_ClockMinor(); Wave_TND_ClockMinor(); }
1263
1264#define EXTSOUND_VRC6 0x01
1265#define EXTSOUND_VRC7 0x02
1266#define EXTSOUND_FDS 0x04
1267#define EXTSOUND_MMC5 0x08
1268#define EXTSOUND_N106 0x10
1269#define EXTSOUND_FME07 0x20
1270
1271#define SILENCE_THRESHOLD 3
1272
1273/*
1274 * prototypes
1275 */
1276
1277uint32_t Emulate6502(uint32_t runto) ICODE_ATTR;
1278void EmulateAPU(uint8_t bBurnCPUCycles) ICODE_ATTR;
1279
1280int NSFCore_Initialize(void); /* 1 = initialized ok,
1281 0 = couldn't initialize (memory allocation error) */
1282
1283/*
1284 * Song Loading
1285 */
1286int LoadNSF(int32_t); /* grab data from an existing file
1287 1 = loaded ok, 0 = error loading */
1288
1289/*
1290 * Track Control
1291 */
1292void SetTrack(uint8_t track); /* Change tracks */
1293
1294/*
1295 * Getting Samples
1296 */
1297/* fill a buffer with samples */
1298int32_t GetSamples(uint8_t* buffer, int32_t buffersize);
1299
1300/*
1301 * Playback options
1302 */
1303/* Set desired playback options (0 = bad options couldn't be set) */
1304int SetPlaybackOptions(int32_t samplerate);
1305/* Speed throttling (0 = uses NSF specified speed) */
1306void SetPlaybackSpeed(float playspersec);
1307
1308float GetPlaybackSpeed(void);
1309float GetMasterVolume(void);
1310
1311/*
1312 * Seeking
1313 */
1314/* gets the number of 'play' routine calls executed */
1315float GetPlayCalls(void);
1316
1317/* gets the output time (based on the given play rate,
1318 if basedplayspersec is zero, current playback speed is used */
1319uint32_t GetWrittenTime(float basedplayspersec);
1320/* sets the number of 'plays' routines executed (for precise seeking) */
1321void SetPlayCalls(float plays);
1322/* sets the written time (approx. seeking) */
1323void SetWrittenTime(uint32_t ms,float basedplays);
1324
1325/*
1326 * Fading
1327 */
1328
1329void StopFade(void); /* stops all fading (plays indefinitely) */
1330uint8_t SongCompleted(void); /* song has faded out (samples have stopped
1331 being generated) */
1332/* parameters are play calls */
1333void SetFade(int32_t fadestart,int32_t fadestop,uint8_t bNotDefault);
1334void SetFadeTime(uint32_t fadestart,uint32_t fadestop,float basedplays,
1335 uint8_t bNotDefault); /* parameters are in milliseconds */
1336
1337/*
1338 * Internal Functions
1339 */
1340void RebuildOutputTables(void);
1341void RecalculateFade(void); /* called when fade status is changed. */
1342void RecalcFilter(void);
1343void RecalcSilenceTracker(void);
1344
1345void WriteMemory_VRC6(uint16_t a,uint8_t v) ICODE_ATTR;
1346void WriteMemory_MMC5(uint16_t a,uint8_t v) ICODE_ATTR;
1347void WriteMemory_N106(uint16_t a,uint8_t v) ICODE_ATTR;
1348void WriteMemory_FME07(uint16_t a,uint8_t v) ICODE_ATTR;
1349
1350/*
1351 * Memory Read/Write routines
1352 */
1353
1354uint8_t ReadMemory_RAM(uint16_t a) ICODE_ATTR;
1355uint8_t ReadMemory_ExRAM(uint16_t a) ICODE_ATTR;
1356uint8_t ReadMemory_SRAM(uint16_t a) ICODE_ATTR;
1357uint8_t ReadMemory_pAPU(uint16_t a) ICODE_ATTR;
1358uint8_t ReadMemory_ROM(uint16_t a) ICODE_ATTR;
1359uint8_t ReadMemory_Default(uint16_t a) ICODE_ATTR;
1360
1361uint8_t ReadMemory_N106(uint16_t a) ICODE_ATTR;
1362
1363void WriteMemory_RAM(uint16_t a,uint8_t v) ICODE_ATTR;
1364void WriteMemory_ExRAM(uint16_t a,uint8_t v) ICODE_ATTR;
1365void WriteMemory_SRAM(uint16_t a,uint8_t v) ICODE_ATTR;
1366void WriteMemory_pAPU(uint16_t a,uint8_t v) ICODE_ATTR;
1367void WriteMemory_FDSRAM(uint16_t a,uint8_t v) ICODE_ATTR;
1368void WriteMemory_Default(uint16_t a,uint8_t v) ICODE_ATTR;
1369
1370uint8_t ReadMemory_RAM(uint16_t a) { return pRAM[a & 0x07FF]; }
1371uint8_t ReadMemory_ExRAM(uint16_t a) { return pExRAM[a & 0x0FFF]; }
1372uint8_t ReadMemory_SRAM(uint16_t a) { return pSRAM[a & 0x1FFF]; }
1373uint8_t ReadMemory_ROM(uint16_t a)
1374 { return pROM[(a >> 12) - 6][a & 0x0FFF]; }
1375uint8_t ReadMemory_Default(uint16_t a) { return (a >> 8); }
1376
1377void WriteMemory_RAM(uint16_t a,uint8_t v)
1378 { pRAM[a & 0x07FF] = v; }
1379void WriteMemory_ExRAM(uint16_t a,uint8_t v);
1380void WriteMemory_SRAM(uint16_t a,uint8_t v)
1381 { pSRAM[a & 0x1FFF] = v; }
1382void WriteMemory_FDSRAM(uint16_t a,uint8_t v)
1383 { pROM[(a >> 12) - 6][a & 0x0FFF] = v; }
1384void WriteMemory_Default(uint16_t a,uint8_t v) { (void)a; (void)v; }
1385
1386
1387/* Read Memory Procs */
1388
1389uint8_t ReadMemory_pAPU(uint16_t a)
1390{
1391 EmulateAPU(1);
1392
1393 if(a == 0x4015)
1394 {
1395 uint8_t ret = 0;
1396 if(mWave_Squares.nLengthCount[0]) ret |= 0x01;
1397 if(mWave_Squares.nLengthCount[1]) ret |= 0x02;
1398 if(mWave_TND.nTriLengthCount) ret |= 0x04;
1399 if(mWave_TND.nNoiseLengthCount) ret |= 0x08;
1400 if(mWave_TND.nDMCBytesRemaining) ret |= 0x10;
1401
1402 if(bFrameIRQPending) ret |= 0x40;
1403 if(mWave_TND.bDMCIRQPending) ret |= 0x80;
1404
1405 bFrameIRQPending = 0;
1406 return ret;
1407 }
1408
1409 if(!(nExternalSound & EXTSOUND_FDS)) return 0x40;
1410 if(bPALMode) return 0x40;
1411
1412 if((a >= 0x4040) && (a <= 0x407F))
1413 return mWave_FDS.nWaveTable[a & 0x3F] | 0x40;
1414 if(a == 0x4090)
1415 return (mWave_FDS.nVolEnv_Gain & 0x3F) | 0x40;
1416 if(a == 0x4092)
1417 return (mWave_FDS.nSweep_Gain & 0x3F) | 0x40;
1418
1419 return 0x40;
1420}
1421
1422uint8_t ReadMemory_N106(uint16_t a)
1423{
1424 if(a != 0x4800)
1425 return ReadMemory_pAPU(a);
1426
1427 uint8_t ret = mWave_N106.nRAM[(mWave_N106.nCurrentAddress << 1)] |
1428 (mWave_N106.nRAM[(mWave_N106.nCurrentAddress << 1) + 1] << 4);
1429 if(mWave_N106.bAutoIncrement)
1430 mWave_N106.nCurrentAddress = (mWave_N106.nCurrentAddress + 1) & 0x7F;
1431
1432 return ret;
1433}
1434
1435
1436/* Write Memory Procs */
1437
1438void WriteMemory_ExRAM(uint16_t a,uint8_t v)
1439{
1440 if(a < 0x5FF6) /* Invalid */
1441 return;
1442
1443 a -= 0x5FF6;
1444
1445 /* Swap out banks */
1446
1447 EmulateAPU(1);
1448 /* stop it from swapping to a bank that doesn't exist */
1449 if(v >= nROMBankCount)
1450 v = 0;
1451
1452 pROM[a] = pROM_Full + (v << 12);
1453
1454 /* Update the DMC's DMA pointer, as well */
1455 if(a >= 2)
1456 mWave_TND.pDMCDMAPtr[a - 2] = pROM[a];
1457}
1458
1459void WriteMemory_pAPU(uint16_t a,uint8_t v)
1460{
1461 EmulateAPU(1);
1462 switch(a)
1463 {
1464 /* Square 1 */
1465 case 0x4000:
1466 mWave_Squares.nDutyCycle[0] = DUTY_CYCLE_TABLE[v >> 6];
1467 mWave_Squares.bLengthEnabled[0] =
1468 !(mWave_Squares.bDecayLoop[0] = (v & 0x20));
1469 mWave_Squares.bDecayEnable[0] = !(v & 0x10);
1470 mWave_Squares.nDecayTimer[0] = (v & 0x0F);
1471
1472 if(!mWave_Squares.bDecayEnable[0])
1473 mWave_Squares.nVolume[0] = mWave_Squares.nDecayTimer[0];
1474 break;
1475
1476 case 0x4001:
1477 mWave_Squares.bSweepEnable[0] = (v & 0x80);
1478 mWave_Squares.nSweepTimer[0] = (v & 0x70) >> 4;
1479 mWave_Squares.bSweepMode[0] = v & 0x08;
1480 mWave_Squares.nSweepShift[0] = v & 0x07;
1481 Wave_Squares_CheckSweepForcedSilence(0);
1482 break;
1483
1484 case 0x4002:
1485 mWave_Squares.nFreqTimer[0].B.l = v;
1486 Wave_Squares_CheckSweepForcedSilence(0);
1487 break;
1488
1489 case 0x4003:
1490 mWave_Squares.nFreqTimer[0].B.h = v & 0x07;
1491 Wave_Squares_CheckSweepForcedSilence(0);
1492
1493 mWave_Squares.nDecayVolume[0] = 0x0F;
1494
1495 if(mWave_Squares.bChannelEnabled[0])
1496 mWave_Squares.nLengthCount[0] = LENGTH_COUNTER_TABLE[v >> 3];
1497
1498 if(bResetDuty)
1499 mWave_Squares.nDutyCount[0] = 0;
1500 break;
1501
1502
1503 /* Square 2 */
1504 case 0x4004:
1505 mWave_Squares.nDutyCycle[1] = DUTY_CYCLE_TABLE[v >> 6];
1506 mWave_Squares.bLengthEnabled[1] =
1507 !(mWave_Squares.bDecayLoop[1] = (v & 0x20));
1508 mWave_Squares.bDecayEnable[1] = !(v & 0x10);
1509 mWave_Squares.nDecayTimer[1] = (v & 0x0F);
1510
1511 if(!mWave_Squares.bDecayEnable[1])
1512 mWave_Squares.nVolume[1] = mWave_Squares.nDecayTimer[1];
1513 break;
1514
1515 case 0x4005:
1516 mWave_Squares.bSweepEnable[1] = (v & 0x80);
1517 mWave_Squares.nSweepTimer[1] = (v & 0x70) >> 4;
1518 mWave_Squares.bSweepMode[1] = v & 0x08;
1519 mWave_Squares.nSweepShift[1] = v & 0x07;
1520 Wave_Squares_CheckSweepForcedSilence(1);
1521 break;
1522
1523 case 0x4006:
1524 mWave_Squares.nFreqTimer[1].B.l = v;
1525 Wave_Squares_CheckSweepForcedSilence(1);
1526 break;
1527
1528 case 0x4007:
1529 mWave_Squares.nFreqTimer[1].B.h = v & 0x07;
1530 Wave_Squares_CheckSweepForcedSilence(1);
1531
1532 mWave_Squares.nDecayVolume[1] = 0x0F;
1533
1534 if(mWave_Squares.bChannelEnabled[1])
1535 mWave_Squares.nLengthCount[1] = LENGTH_COUNTER_TABLE[v >> 3];
1536
1537 if(bResetDuty)
1538 mWave_Squares.nDutyCount[1] = 0;
1539 break;
1540
1541
1542 /* Triangle */
1543 case 0x4008:
1544 mWave_TND.nTriLinearLoad = v & 0x7F;
1545 mWave_TND.bTriLinearControl = v & 0x80;
1546 mWave_TND.bTriLengthEnabled = !(v & 0x80);
1547 break;
1548
1549 case 0x400A:
1550 mWave_TND.nTriFreqTimer.B.l = v;
1551 break;
1552
1553 case 0x400B:
1554 mWave_TND.nTriFreqTimer.B.h = v & 0x07;
1555 mWave_TND.bTriLinearHalt = 1;
1556
1557 if(mWave_TND.bTriChannelEnabled)
1558 mWave_TND.nTriLengthCount = LENGTH_COUNTER_TABLE[v >> 3];
1559 break;
1560
1561 /* Noise */
1562 case 0x400C:
1563 mWave_TND.bNoiseLengthEnabled =
1564 !(mWave_TND.bNoiseDecayLoop = (v & 0x20));
1565 mWave_TND.bNoiseDecayEnable = !(v & 0x10);
1566 mWave_TND.nNoiseDecayTimer = (v & 0x0F);
1567
1568 if(mWave_TND.bNoiseDecayEnable)
1569 mWave_TND.nNoiseVolume = mWave_TND.nNoiseDecayVolume;
1570 else
1571 mWave_TND.nNoiseVolume = mWave_TND.nNoiseDecayTimer;
1572 break;
1573
1574 case 0x400E:
1575 mWave_TND.nNoiseFreqTimer = NOISE_FREQ_TABLE[v & 0x0F];
1576 mWave_TND.bNoiseRandomMode = (v & 0x80) ? 6 : 1;
1577 break;
1578
1579 case 0x400F:
1580 if(mWave_TND.bNoiseChannelEnabled)
1581 mWave_TND.nNoiseLengthCount = LENGTH_COUNTER_TABLE[v >> 3];
1582
1583 mWave_TND.nNoiseDecayVolume = 0x0F;
1584 if(mWave_TND.bNoiseDecayEnable)
1585 mWave_TND.nNoiseVolume = 0x0F;
1586 break;
1587
1588 /* DMC */
1589 case 0x4010:
1590 mWave_TND.bDMCLoop = v & 0x40;
1591 mWave_TND.bDMCIRQEnabled = v & 0x80;
1592 /* IRQ can't be pending if disabled */
1593 if(!mWave_TND.bDMCIRQEnabled)
1594 mWave_TND.bDMCIRQPending = 0;
1595
1596 mWave_TND.nDMCFreqTimer = DMC_FREQ_TABLE[bPALMode][v & 0x0F];
1597 break;
1598
1599 case 0x4011:
1600 if(bIgnore4011Writes)
1601 break;
1602 v &= 0x7F;
1603 if(bDMCPopReducer)
1604 {
1605 if(bDMCPop_SamePlay)
1606 mWave_TND.nDMCOutput = v;
1607 else
1608 {
1609 if(bDMCPop_Skip)
1610 {
1611 bDMCPop_Skip = 0;
1612 break;
1613 }
1614 if(nDMCPop_Prev == v) break;
1615 if(mWave_TND.nDMCOutput == v) break;
1616 mWave_TND.nDMCOutput = nDMCPop_Prev;
1617 nDMCPop_Prev = v;
1618 bDMCPop_SamePlay = 1;
1619 }
1620 }
1621 else
1622 mWave_TND.nDMCOutput = v;
1623 break;
1624
1625 case 0x4012:
1626 mWave_TND.nDMCDMABank_Load = (v >> 6) | 0x04;
1627 mWave_TND.nDMCDMAAddr_Load = (v << 6) & 0x0FFF;
1628 break;
1629
1630 case 0x4013:
1631 mWave_TND.nDMCLength = (v << 4) + 1;
1632 break;
1633
1634 /* All / General Purpose */
1635 case 0x4015:
1636 mWave_TND.bDMCIRQPending = 0;
1637
1638 if(v & 0x01){ mWave_Squares.bChannelEnabled[0] = 1; }
1639 else { mWave_Squares.bChannelEnabled[0] =
1640 mWave_Squares.nLengthCount[0] = 0; }
1641 if(v & 0x02){ mWave_Squares.bChannelEnabled[1] = 1; }
1642 else { mWave_Squares.bChannelEnabled[1] =
1643 mWave_Squares.nLengthCount[1] = 0; }
1644 if(v & 0x04){ mWave_TND.bTriChannelEnabled = 1; }
1645 else { mWave_TND.bTriChannelEnabled =
1646 mWave_TND.nTriLengthCount = 0; }
1647 if(v & 0x08){ mWave_TND.bNoiseChannelEnabled = 1; }
1648 else { mWave_TND.bNoiseChannelEnabled =
1649 mWave_TND.nNoiseLengthCount = 0; }
1650
1651 if(v & 0x10)
1652 {
1653 if(!mWave_TND.nDMCBytesRemaining)
1654 {
1655 bDMCPop_Skip = 1;
1656 mWave_TND.nDMCDMAAddr = mWave_TND.nDMCDMAAddr_Load;
1657 mWave_TND.nDMCDMABank = mWave_TND.nDMCDMABank_Load;
1658 mWave_TND.nDMCBytesRemaining = mWave_TND.nDMCLength;
1659 mWave_TND.bDMCActive = 1;
1660 }
1661 }
1662 else
1663 mWave_TND.nDMCBytesRemaining = 0;
1664 break;
1665
1666 case 0x4017:
1667 bFrameIRQEnabled = !(v & 0x40);
1668 bFrameIRQPending = 0;
1669 nFrameCounter = 0;
1670 nFrameCounterMax = (v & 0x80) ? 4 : 3;
1671 nTicksUntilNextFrame =
1672 (bPALMode ? PAL_FRAME_COUNTER_FREQ : NTSC_FRAME_COUNTER_FREQ)
1673 * 0x10000;
1674
1675 CLOCK_MAJOR();
1676 if(v & 0x80) CLOCK_MINOR();
1677 break;
1678 }
1679
1680 if(!(nExternalSound & EXTSOUND_FDS)) return;
1681 if(bPALMode) return;
1682
1683 /* FDS Sound registers */
1684
1685 if(a < 0x4040) return;
1686
1687 /* wave table */
1688 if(a <= 0x407F)
1689 {
1690 if(mWave_FDS.bWaveWrite)
1691 mWave_FDS.nWaveTable[a - 0x4040] = v;
1692 }
1693 else
1694 {
1695 switch(a)
1696 {
1697 case 0x4080:
1698 mWave_FDS.nVolEnv_Mode = (v >> 6);
1699 if(v & 0x80)
1700 {
1701 mWave_FDS.nVolEnv_Gain = v & 0x3F;
1702 if(!mWave_FDS.nMainAddr)
1703 {
1704 if(mWave_FDS.nVolEnv_Gain < 0x20)
1705 mWave_FDS.nVolume = mWave_FDS.nVolEnv_Gain;
1706 else mWave_FDS.nVolume = 0x20;
1707 }
1708 }
1709 mWave_FDS.nVolEnv_Decay = v & 0x3F;
1710 mWave_FDS.nVolEnv_Timer =
1711 ((mWave_FDS.nVolEnv_Decay + 1) * mWave_FDS.nEnvelopeSpeed * 8);
1712
1713 mWave_FDS.bVolEnv_On = mWave_FDS.bEnvelopeEnable &&
1714 mWave_FDS.nEnvelopeSpeed && !(v & 0x80);
1715 break;
1716
1717 case 0x4082:
1718 mWave_FDS.nFreq.B.l = v;
1719 mWave_FDS.bMain_On = mWave_FDS.nFreq.W && mWave_FDS.bEnabled &&
1720 !mWave_FDS.bWaveWrite;
1721 break;
1722
1723 case 0x4083:
1724 mWave_FDS.bEnabled = !(v & 0x80);
1725 mWave_FDS.bEnvelopeEnable = !(v & 0x40);
1726 if(v & 0x80)
1727 {
1728 if(mWave_FDS.nVolEnv_Gain < 0x20)
1729 mWave_FDS.nVolume = mWave_FDS.nVolEnv_Gain;
1730 else mWave_FDS.nVolume = 0x20;
1731 }
1732 mWave_FDS.nFreq.B.h = v & 0x0F;
1733 mWave_FDS.bMain_On = mWave_FDS.nFreq.W && mWave_FDS.bEnabled &&
1734 !mWave_FDS.bWaveWrite;
1735
1736 mWave_FDS.bVolEnv_On = mWave_FDS.bEnvelopeEnable &&
1737 mWave_FDS.nEnvelopeSpeed && !(mWave_FDS.nVolEnv_Mode & 2);
1738 mWave_FDS.bSweepEnv_On = mWave_FDS.bEnvelopeEnable &&
1739 mWave_FDS.nEnvelopeSpeed && !(mWave_FDS.nSweep_Mode & 2);
1740 break;
1741
1742
1743 case 0x4084:
1744 mWave_FDS.nSweep_Mode = v >> 6;
1745 if(v & 0x80)
1746 mWave_FDS.nSweep_Gain = v & 0x3F;
1747 mWave_FDS.nSweep_Decay = v & 0x3F;
1748 mWave_FDS.nSweep_Timer =
1749 ((mWave_FDS.nSweep_Decay + 1) * mWave_FDS.nEnvelopeSpeed * 8);
1750 mWave_FDS.bSweepEnv_On =
1751 mWave_FDS.bEnvelopeEnable && mWave_FDS.nEnvelopeSpeed &&
1752 !(v & 0x80);
1753 break;
1754
1755
1756 case 0x4085:
1757 if(v & 0x40) mWave_FDS.nSweepBias = (v & 0x3F) - 0x40;
1758 else mWave_FDS.nSweepBias = v & 0x3F;
1759 mWave_FDS.nLFO_Addr = 0;
1760 break;
1761
1762
1763 case 0x4086:
1764 mWave_FDS.nLFO_Freq.B.l = v;
1765 mWave_FDS.bLFO_On =
1766 mWave_FDS.bLFO_Enabled && mWave_FDS.nLFO_Freq.W;
1767 if(mWave_FDS.nLFO_Freq.W)
1768 mWave_FDS.nLFO_Timer = (0x10000<<14) / mWave_FDS.nLFO_Freq.W;
1769 break;
1770
1771 case 0x4087:
1772 mWave_FDS.bLFO_Enabled = !(v & 0x80);
1773 mWave_FDS.nLFO_Freq.B.h = v & 0x0F;
1774 mWave_FDS.bLFO_On =
1775 mWave_FDS.bLFO_Enabled && mWave_FDS.nLFO_Freq.W;
1776 if(mWave_FDS.nLFO_Freq.W)
1777 mWave_FDS.nLFO_Timer = (0x10000<<14) / mWave_FDS.nLFO_Freq.W;
1778 break;
1779
1780 case 0x4088:
1781 if(mWave_FDS.bLFO_Enabled) break;
1782 register int32_t i;
1783 for(i = 0; i < 62; i++)
1784 mWave_FDS.nLFO_Table[i] = mWave_FDS.nLFO_Table[i + 2];
1785 mWave_FDS.nLFO_Table[62] = mWave_FDS.nLFO_Table[63] = v & 7;
1786 break;
1787
1788 case 0x4089:
1789 mWave_FDS.nMainVolume = v & 3;
1790 mWave_FDS.bWaveWrite = v & 0x80;
1791 mWave_FDS.bMain_On = mWave_FDS.nFreq.W && mWave_FDS.bEnabled &&
1792 !mWave_FDS.bWaveWrite;
1793 break;
1794
1795 case 0x408A:
1796 mWave_FDS.nEnvelopeSpeed = v;
1797 mWave_FDS.bVolEnv_On =
1798 mWave_FDS.bEnvelopeEnable &&
1799 mWave_FDS.nEnvelopeSpeed && !(mWave_FDS.nVolEnv_Mode & 2);
1800 mWave_FDS.bSweepEnv_On =
1801 mWave_FDS.bEnvelopeEnable &&
1802 mWave_FDS.nEnvelopeSpeed && !(mWave_FDS.nSweep_Mode & 2);
1803 break;
1804 }
1805 }
1806}
1807
1808void WriteMemory_VRC6(uint16_t a,uint8_t v)
1809{
1810 EmulateAPU(1);
1811
1812 if((a < 0xA000) && (nExternalSound & EXTSOUND_VRC7)) return;
1813 else if(nExternalSound & EXTSOUND_FDS)
1814 WriteMemory_FDSRAM(a,v);
1815
1816 switch(a)
1817 {
1818 /* Pulse 1 */
1819 case 0x9000:
1820 mWave_VRC6Pulse[0].nVolume = v & 0x0F;
1821 mWave_VRC6Pulse[0].nDutyCycle = (v >> 4) & 0x07;
1822 mWave_VRC6Pulse[0].bDigitized = v & 0x80;
1823 if(mWave_VRC6Pulse[0].bDigitized)
1824 mWave_VRC6Pulse[0].nDutyCount = 0;
1825 break;
1826
1827 case 0x9001:
1828 mWave_VRC6Pulse[0].nFreqTimer.B.l = v;
1829 break;
1830
1831 case 0x9002:
1832 mWave_VRC6Pulse[0].nFreqTimer.B.h = v & 0x0F;
1833 mWave_VRC6Pulse[0].bChannelEnabled = v & 0x80;
1834 break;
1835
1836
1837 /* Pulse 2 */
1838 case 0xA000:
1839 mWave_VRC6Pulse[1].nVolume = v & 0x0F;
1840 mWave_VRC6Pulse[1].nDutyCycle = (v >> 4) & 0x07;
1841 mWave_VRC6Pulse[1].bDigitized = v & 0x80;
1842 if(mWave_VRC6Pulse[1].bDigitized)
1843 mWave_VRC6Pulse[1].nDutyCount = 0;
1844 break;
1845
1846 case 0xA001:
1847 mWave_VRC6Pulse[1].nFreqTimer.B.l = v;
1848 break;
1849
1850 case 0xA002:
1851 mWave_VRC6Pulse[1].nFreqTimer.B.h = v & 0x0F;
1852 mWave_VRC6Pulse[1].bChannelEnabled = v & 0x80;
1853 break;
1854
1855 /* Sawtooth */
1856 case 0xB000:
1857 mWave_VRC6Saw.nAccumRate = (v & 0x3F);
1858 break;
1859
1860 case 0xB001:
1861 mWave_VRC6Saw.nFreqTimer.B.l = v;
1862 break;
1863
1864 case 0xB002:
1865 mWave_VRC6Saw.nFreqTimer.B.h = v & 0x0F;
1866 mWave_VRC6Saw.bChannelEnabled = v & 0x80;
1867 break;
1868 }
1869}
1870
1871void WriteMemory_MMC5(uint16_t a,uint8_t v)
1872{
1873 if((a <= 0x5015) && !bPALMode)
1874 {
1875 /* no audio emulation */
1876 return;
1877 }
1878
1879 if(a == 0x5205)
1880 {
1881 nMultIn_Low = v;
1882 goto multiply;
1883 }
1884 if(a == 0x5206)
1885 {
1886 nMultIn_High = v;
1887multiply:
1888 a = nMultIn_Low * nMultIn_High;
1889 pExRAM[0x205] = a & 0xFF;
1890 pExRAM[0x206] = a >> 8;
1891 return;
1892 }
1893
1894 if(a < 0x5C00) return;
1895
1896 pExRAM[a & 0x0FFF] = v;
1897 if(a >= 0x5FF6)
1898 WriteMemory_ExRAM(a,v);
1899}
1900
1901void WriteMemory_N106(uint16_t a,uint8_t v)
1902{
1903 if(a < 0x4800)
1904 {
1905 WriteMemory_pAPU(a,v);
1906 return;
1907 }
1908
1909 if(a == 0xF800)
1910 {
1911 mWave_N106.nCurrentAddress = v & 0x7F;
1912 mWave_N106.bAutoIncrement = (v & 0x80);
1913 return;
1914 }
1915
1916 if(a == 0x4800)
1917 {
1918 EmulateAPU(1);
1919 mWave_N106.nRAM[mWave_N106.nCurrentAddress << 1] = v & 0x0F;
1920 mWave_N106.nRAM[(mWave_N106.nCurrentAddress << 1) + 1] = v >> 4;
1921 a = mWave_N106.nCurrentAddress;
1922 if(mWave_N106.bAutoIncrement)
1923 mWave_N106.nCurrentAddress =
1924 (mWave_N106.nCurrentAddress + 1) & 0x7F;
1925
1926#define N106REGWRITE(ch,r0,r1,r2,r3,r4) \
1927 case r0: if(mWave_N106.nFreqReg[ch].B.l == v) break; \
1928 mWave_N106.nFreqReg[ch].B.l = v; \
1929 mWave_N106.fFreqTimer[ch] = -1.0f; \
1930 break; \
1931 case r1: if(mWave_N106.nFreqReg[ch].B.h == v) break; \
1932 mWave_N106.nFreqReg[ch].B.h = v; \
1933 mWave_N106.fFreqTimer[ch] = -1.0f; \
1934 break; \
1935 case r2: if(mWave_N106.nFreqReg[ch].B.w != (v & 3)){ \
1936 mWave_N106.nFreqReg[ch].B.w = v & 0x03; \
1937 mWave_N106.fFreqTimer[ch] = -1.0f;} \
1938 mWave_N106.nWaveSize[ch] = 0x20 - (v & 0x1C); \
1939 break; \
1940 case r3: mWave_N106.nWavePosStart[ch] = v; \
1941 break; \
1942 case r4: mWave_N106.nPreVolume[ch] = v & 0x0F; \
1943 if(!bN106PopReducer) \
1944 mWave_N106.nVolume[ch] = v & 0x0F
1945
1946 switch(a)
1947 {
1948 N106REGWRITE(0,0x40,0x42,0x44,0x46,0x47); break;
1949 N106REGWRITE(1,0x48,0x4A,0x4C,0x4E,0x4F); break;
1950 N106REGWRITE(2,0x50,0x52,0x54,0x56,0x57); break;
1951 N106REGWRITE(3,0x58,0x5A,0x5C,0x5E,0x5F); break;
1952 N106REGWRITE(4,0x60,0x62,0x64,0x66,0x67); break;
1953 N106REGWRITE(5,0x68,0x6A,0x6C,0x6E,0x6F); break;
1954 N106REGWRITE(6,0x70,0x72,0x74,0x76,0x77); break;
1955 N106REGWRITE(7,0x78,0x7A,0x7C,0x7E,0x7F);
1956 v = (v >> 4) & 7;
1957 if(mWave_N106.nActiveChannels == v) break;
1958 mWave_N106.nActiveChannels = v;
1959 mWave_N106.fFreqTimer[0] = -1.0f;
1960 mWave_N106.fFreqTimer[1] = -1.0f;
1961 mWave_N106.fFreqTimer[2] = -1.0f;
1962 mWave_N106.fFreqTimer[3] = -1.0f;
1963 mWave_N106.fFreqTimer[4] = -1.0f;
1964 mWave_N106.fFreqTimer[5] = -1.0f;
1965 mWave_N106.fFreqTimer[6] = -1.0f;
1966 mWave_N106.fFreqTimer[7] = -1.0f;
1967 break;
1968 }
1969#undef N106REGWRITE
1970 }
1971}
1972
1973void WriteMemory_FME07(uint16_t a,uint8_t v)
1974{
1975 if((a < 0xD000) && (nExternalSound & EXTSOUND_FDS))
1976 WriteMemory_FDSRAM(a,v);
1977
1978 if(a == 0xC000)
1979 nFME07_Address = v;
1980 if(a == 0xE000)
1981 {
1982 switch(nFME07_Address)
1983 {
1984 case 0x00: mWave_FME07[0].nFreqTimer.B.l = v; break;
1985 case 0x01: mWave_FME07[0].nFreqTimer.B.h = v & 0x0F; break;
1986 case 0x02: mWave_FME07[1].nFreqTimer.B.l = v; break;
1987 case 0x03: mWave_FME07[1].nFreqTimer.B.h = v & 0x0F; break;
1988 case 0x04: mWave_FME07[2].nFreqTimer.B.l = v; break;
1989 case 0x05: mWave_FME07[2].nFreqTimer.B.h = v & 0x0F; break;
1990 case 0x07:
1991 mWave_FME07[0].bChannelEnabled = !(v & 0x01);
1992 mWave_FME07[1].bChannelEnabled = !(v & 0x02);
1993 mWave_FME07[2].bChannelEnabled = !(v & 0x03);
1994 break;
1995 case 0x08: mWave_FME07[0].nVolume = v & 0x0F; break;
1996 case 0x09: mWave_FME07[1].nVolume = v & 0x0F; break;
1997 case 0x0A: mWave_FME07[2].nVolume = v & 0x0F; break;
1998 }
1999 }
2000}
2001
2002/*
2003 * Emulate APU
2004 */
2005
2006int32_t fulltick;
2007void EmulateAPU(uint8_t bBurnCPUCycles)
2008{
2009 int32_t tick;
2010 int64_t diff;
2011
2012 int32_t tnd_out;
2013 uint8_t square_out;
2014
2015 ENTER_TIMER(apu);
2016
2017 fulltick += (signed)(nCPUCycle - nAPUCycle);
2018
2019 int32_t burned;
2020 int32_t mixL;
2021
2022 if(bFade && nSilentSampleMax && (nSilentSamples >= nSilentSampleMax))
2023 fulltick = 0;
2024
2025 while(fulltick>0)
2026 {
2027 tick = (nTicksUntilNextSample+0xffff)>>16;
2028
2029 fulltick -= tick;
2030
2031 /*
2032 * Sample Generation
2033 */
2034
2035 ENTER_TIMER(squares);
2036 /* Square generation */
2037
2038 mWave_Squares.nFreqCount[0] -= tick;
2039 mWave_Squares.nFreqCount[1] -= tick;
2040
2041 if((mWave_Squares.nDutyCount[0] < mWave_Squares.nDutyCycle[0]) &&
2042 mWave_Squares.nLengthCount[0] &&
2043 !mWave_Squares.bSweepForceSilence[0])
2044 square_out = (mWave_Squares.nVolume[0] << 4);
2045 else
2046 square_out = 0;
2047
2048 if((mWave_Squares.nDutyCount[1] < mWave_Squares.nDutyCycle[1]) &&
2049 mWave_Squares.nLengthCount[1] &&
2050 !mWave_Squares.bSweepForceSilence[1])
2051 square_out |= mWave_Squares.nVolume[1];
2052
2053 mWave_Squares.nMixL = Squares_nOutputTable_L[square_out];
2054
2055 if(mWave_Squares.nFreqCount[0]<=0)
2056 {
2057 int cycles =
2058 (-mWave_Squares.nFreqCount[0])/
2059 (mWave_Squares.nFreqTimer[0].W + 1) + 1;
2060 mWave_Squares.nFreqCount[0] =
2061 (mWave_Squares.nFreqTimer[0].W + 1)-
2062 (-mWave_Squares.nFreqCount[0])%
2063 (mWave_Squares.nFreqTimer[0].W + 1);
2064 mWave_Squares.nDutyCount[0] =
2065 (mWave_Squares.nDutyCount[0]+cycles)%0x10;
2066 }
2067 if(mWave_Squares.nFreqCount[1]<=0)
2068 {
2069 int cycles =
2070 (-mWave_Squares.nFreqCount[1])/
2071 (mWave_Squares.nFreqTimer[1].W + 1) + 1;
2072 mWave_Squares.nFreqCount[1] =
2073 (mWave_Squares.nFreqTimer[1].W + 1)-
2074 (-mWave_Squares.nFreqCount[1])%
2075 (mWave_Squares.nFreqTimer[1].W + 1);
2076 mWave_Squares.nDutyCount[1] = (mWave_Squares.nDutyCount[1]+cycles)%
2077 0x10;
2078 }
2079 /* end of Square generation */
2080 EXIT_TIMER(squares);
2081 ENTER_TIMER(tnd);
2082
2083 ENTER_TIMER(tnd_enter);
2084
2085 burned=0;
2086
2087 /* TND generation */
2088
2089 if(mWave_TND.nNoiseFreqTimer) mWave_TND.nNoiseFreqCount -= tick;
2090
2091 if(mWave_TND.nTriFreqTimer.W > 8)
2092 mWave_TND.nTriFreqCount -= tick;
2093
2094 tnd_out = mWave_TND.nTriOutput << 11;
2095
2096 if(mWave_TND.bNoiseRandomOut && mWave_TND.nNoiseLengthCount)
2097 tnd_out |= mWave_TND.nNoiseVolume << 7;
2098
2099 tnd_out |= mWave_TND.nDMCOutput;
2100
2101 mWave_TND.nMixL = main_nOutputTable_L[tnd_out];
2102
2103 EXIT_TIMER(tnd_enter);
2104
2105 ENTER_TIMER(tnd_tri);
2106
2107 /* Tri */
2108
2109 if(mWave_TND.nTriFreqCount<=0)
2110 {
2111 if(mWave_TND.nTriLengthCount && mWave_TND.nTriLinearCount)
2112 {
2113 do mWave_TND.nTriStep++;
2114 while ((mWave_TND.nTriFreqCount +=
2115 mWave_TND.nTriFreqTimer.W + 1) <= 0);
2116 mWave_TND.nTriStep &= 0x1F;
2117
2118 if(mWave_TND.nTriStep & 0x10)
2119 mWave_TND.nTriOutput = mWave_TND.nTriStep ^ 0x1F;
2120 else mWave_TND.nTriOutput = mWave_TND.nTriStep;
2121 } else mWave_TND.nTriFreqCount=mWave_TND.nTriFreqTimer.W+1;
2122 }
2123
2124 EXIT_TIMER(tnd_tri);
2125
2126 ENTER_TIMER(tnd_noise);
2127
2128 /* Noise */
2129
2130 if(mWave_TND.nNoiseFreqTimer &&
2131 mWave_TND.nNoiseVolume && mWave_TND.nNoiseFreqCount<=0)
2132 {
2133 mWave_TND.nNoiseFreqCount = mWave_TND.nNoiseFreqTimer;
2134 mWave_TND.nNoiseRandomShift <<= 1;
2135 mWave_TND.bNoiseRandomOut = (((mWave_TND.nNoiseRandomShift <<
2136 mWave_TND.bNoiseRandomMode) ^
2137 mWave_TND.nNoiseRandomShift) & 0x8000 ) ? 1 : 0;
2138 if(mWave_TND.bNoiseRandomOut)
2139 mWave_TND.nNoiseRandomShift |= 0x01;
2140 }
2141
2142 EXIT_TIMER(tnd_noise);
2143
2144 ENTER_TIMER(tnd_dmc);
2145
2146 /* DMC */
2147 if(mWave_TND.bDMCActive)
2148 {
2149 mWave_TND.nDMCFreqCount -= tick;
2150 while (mWave_TND.nDMCFreqCount <= 0) {
2151 if (!mWave_TND.bDMCActive) {
2152 mWave_TND.nDMCFreqCount = mWave_TND.nDMCFreqTimer;
2153 break;
2154 }
2155
2156 mWave_TND.nDMCFreqCount += mWave_TND.nDMCFreqTimer;
2157
2158 if(mWave_TND.bDMCSampleBufferEmpty &&
2159 mWave_TND.nDMCBytesRemaining)
2160 {
2161 burned += 4; /* 4 cycle burn! */
2162 mWave_TND.nDMCSampleBuffer =
2163 mWave_TND.pDMCDMAPtr[mWave_TND.nDMCDMABank]
2164 [mWave_TND.nDMCDMAAddr];
2165 mWave_TND.nDMCDMAAddr++;
2166 if(mWave_TND.nDMCDMAAddr & 0x1000)
2167 {
2168 mWave_TND.nDMCDMAAddr &= 0x0FFF;
2169 mWave_TND.nDMCDMABank =
2170 (mWave_TND.nDMCDMABank + 1) & 0x07;
2171 }
2172
2173 mWave_TND.bDMCSampleBufferEmpty = 0;
2174 mWave_TND.nDMCBytesRemaining--;
2175 if(!mWave_TND.nDMCBytesRemaining)
2176 {
2177 if(mWave_TND.bDMCLoop)
2178 {
2179 mWave_TND.nDMCDMABank = mWave_TND.nDMCDMABank_Load;
2180 mWave_TND.nDMCDMAAddr = mWave_TND.nDMCDMAAddr_Load;
2181 mWave_TND.nDMCBytesRemaining =mWave_TND.nDMCLength;
2182 }
2183 else if(mWave_TND.bDMCIRQEnabled)
2184 mWave_TND.bDMCIRQPending = 1;
2185 }
2186 }
2187
2188 if(!mWave_TND.nDMCDeltaBit)
2189 {
2190 mWave_TND.nDMCDeltaBit = 8;
2191 mWave_TND.bDMCDeltaSilent =mWave_TND.bDMCSampleBufferEmpty;
2192 mWave_TND.nDMCDelta = mWave_TND.nDMCSampleBuffer;
2193 mWave_TND.bDMCSampleBufferEmpty = 1;
2194 }
2195
2196 if(mWave_TND.nDMCDeltaBit) {
2197 mWave_TND.nDMCDeltaBit--;
2198 if(!mWave_TND.bDMCDeltaSilent)
2199 {
2200 if(mWave_TND.nDMCDelta & 0x01)
2201 {
2202 if(mWave_TND.nDMCOutput < 0x7E)
2203 mWave_TND.nDMCOutput += 2;
2204 }
2205 else if(mWave_TND.nDMCOutput > 1)
2206 mWave_TND.nDMCOutput -= 2;
2207 }
2208 mWave_TND.nDMCDelta >>= 1;
2209 }
2210
2211 if(!mWave_TND.nDMCBytesRemaining &&
2212 mWave_TND.bDMCSampleBufferEmpty &&
2213 mWave_TND.bDMCDeltaSilent)
2214 mWave_TND.bDMCActive = mWave_TND.nDMCDeltaBit = 0;
2215 }
2216 }
2217
2218 EXIT_TIMER(tnd_dmc);
2219
2220 /* end of TND generation */
2221 EXIT_TIMER(tnd);
2222
2223 if(nExternalSound && !bPALMode)
2224 {
2225 if(nExternalSound & EXTSOUND_VRC6)
2226 {
2227
2228 if(mWave_VRC6Pulse[0].bChannelEnabled) {
2229
2230 mWave_VRC6Pulse[0].nFreqCount -= tick;
2231
2232 if(mWave_VRC6Pulse[0].nDutyCount <=
2233 mWave_VRC6Pulse[0].nDutyCycle)
2234 {
2235 mWave_VRC6Pulse[0].nMixL =
2236 VRC6Pulse_nOutputTable_L[0]
2237 [mWave_VRC6Pulse[0].nVolume];
2238 } else mWave_VRC6Pulse[0].nMixL = 0;
2239
2240 while(mWave_VRC6Pulse[0].nFreqCount <= 0) {
2241 mWave_VRC6Pulse[0].nFreqCount +=
2242 mWave_VRC6Pulse[0].nFreqTimer.W + 1;
2243
2244 if(!mWave_VRC6Pulse[0].bDigitized)
2245 mWave_VRC6Pulse[0].nDutyCount =
2246 (mWave_VRC6Pulse[0].nDutyCount + 1) & 0x0F;
2247 }
2248 }
2249
2250 if(mWave_VRC6Pulse[1].bChannelEnabled) {
2251
2252 mWave_VRC6Pulse[1].nFreqCount -= tick;
2253
2254 if(mWave_VRC6Pulse[1].nDutyCount <=
2255 mWave_VRC6Pulse[1].nDutyCycle)
2256 {
2257 mWave_VRC6Pulse[1].nMixL =
2258 VRC6Pulse_nOutputTable_L[1]
2259 [mWave_VRC6Pulse[1].nVolume];
2260 } else mWave_VRC6Pulse[1].nMixL = 0;
2261
2262 while(mWave_VRC6Pulse[1].nFreqCount <= 0) {
2263 mWave_VRC6Pulse[1].nFreqCount +=
2264 mWave_VRC6Pulse[1].nFreqTimer.W + 1;
2265
2266 if(!mWave_VRC6Pulse[1].bDigitized)
2267 mWave_VRC6Pulse[1].nDutyCount =
2268 (mWave_VRC6Pulse[1].nDutyCount + 1) & 0x0F;
2269 }
2270 }
2271
2272 mWave_VRC6Saw.nFreqCount -= tick;
2273
2274 mWave_VRC6Saw.nMixL =
2275 VRC6Saw_nOutputTable_L[mWave_VRC6Saw.nAccum >> 3];
2276
2277 while(mWave_VRC6Saw.nFreqCount <= 0) {
2278
2279 mWave_VRC6Saw.nFreqCount += mWave_VRC6Saw.nFreqTimer.W + 1;
2280
2281 mWave_VRC6Saw.nAccumStep++;
2282 if(mWave_VRC6Saw.nAccumStep == 14)
2283 {
2284 mWave_VRC6Saw.nAccumStep = 0;
2285 mWave_VRC6Saw.nAccum = 0;
2286 }
2287 else if(!(mWave_VRC6Saw.nAccumStep & 1))
2288 mWave_VRC6Saw.nAccum += mWave_VRC6Saw.nAccumRate;
2289 }
2290
2291 } /* end VRC6 */
2292 if(nExternalSound & EXTSOUND_N106)
2293 Wave_N106_DoTicks(tick);
2294 if(nExternalSound & EXTSOUND_FME07)
2295 {
2296 if (mWave_FME07[0].bChannelEnabled &&
2297 mWave_FME07[0].nFreqTimer.W) {
2298 mWave_FME07[0].nFreqCount -= tick;
2299
2300 if(mWave_FME07[0].nDutyCount < 16)
2301 {
2302 mWave_FME07[0].nMixL =
2303 FME07_nOutputTable_L[0][mWave_FME07[0].nVolume];
2304 } else mWave_FME07[0].nMixL = 0;
2305 while(mWave_FME07[0].nFreqCount <= 0) {
2306 mWave_FME07[0].nFreqCount +=
2307 mWave_FME07[0].nFreqTimer.W;
2308
2309 mWave_FME07[0].nDutyCount=
2310 (mWave_FME07[0].nDutyCount+1)&0x1f;
2311 }
2312 }
2313
2314 if (mWave_FME07[1].bChannelEnabled &&
2315 mWave_FME07[1].nFreqTimer.W) {
2316 mWave_FME07[1].nFreqCount -= tick;
2317
2318 if(mWave_FME07[1].nDutyCount < 16)
2319 {
2320 mWave_FME07[1].nMixL =
2321 FME07_nOutputTable_L[1][mWave_FME07[1].nVolume];
2322 } else mWave_FME07[1].nMixL = 0;
2323 while(mWave_FME07[1].nFreqCount <= 0) {
2324 mWave_FME07[1].nFreqCount +=
2325 mWave_FME07[1].nFreqTimer.W;
2326
2327 mWave_FME07[1].nDutyCount=
2328 (mWave_FME07[1].nDutyCount+1)&0x1f;
2329 }
2330 }
2331
2332 if (mWave_FME07[2].bChannelEnabled &&
2333 mWave_FME07[2].nFreqTimer.W) {
2334 mWave_FME07[2].nFreqCount -= tick;
2335
2336 if(mWave_FME07[2].nDutyCount < 16)
2337 {
2338 mWave_FME07[2].nMixL =
2339 FME07_nOutputTable_L[2][mWave_FME07[2].nVolume];
2340 } else mWave_FME07[2].nMixL = 0;
2341 while(mWave_FME07[2].nFreqCount <= 0) {
2342 mWave_FME07[2].nFreqCount +=
2343 mWave_FME07[2].nFreqTimer.W;
2344
2345 mWave_FME07[2].nDutyCount=
2346 (mWave_FME07[2].nDutyCount+1)&0x1f;
2347 }
2348 }
2349
2350 } /* end FME07 */
2351 ENTER_TIMER(fds);
2352 if(nExternalSound & EXTSOUND_FDS) {
2353
2354 /* Volume Envelope Unit */
2355 if(mWave_FDS.bVolEnv_On)
2356 {
2357 mWave_FDS.nVolEnv_Count -= tick;
2358 while(mWave_FDS.nVolEnv_Count <= 0)
2359 {
2360 mWave_FDS.nVolEnv_Count += mWave_FDS.nVolEnv_Timer;
2361 if(mWave_FDS.nVolEnv_Mode) {
2362 if(mWave_FDS.nVolEnv_Gain < 0x20)
2363 mWave_FDS.nVolEnv_Gain++;
2364 }
2365 else {
2366 if(mWave_FDS.nVolEnv_Gain)
2367 mWave_FDS.nVolEnv_Gain--;
2368 }
2369 }
2370 }
2371
2372 /* Sweep Envelope Unit */
2373 if(mWave_FDS.bSweepEnv_On)
2374 {
2375 mWave_FDS.nSweep_Count -= tick;
2376 while(mWave_FDS.nSweep_Count <= 0)
2377 {
2378 mWave_FDS.nSweep_Count += mWave_FDS.nSweep_Timer;
2379 if(mWave_FDS.nSweep_Mode) {
2380 if(mWave_FDS.nSweep_Gain < 0x20)
2381 mWave_FDS.nSweep_Gain++;
2382 } else {
2383 if(mWave_FDS.nSweep_Gain) mWave_FDS.nSweep_Gain--;
2384 }
2385 }
2386 }
2387
2388 /* Effector / LFO */
2389 int32_t subfreq = 0;
2390 if(mWave_FDS.bLFO_On)
2391 {
2392 mWave_FDS.nLFO_Count -= tick<<14;
2393 while(mWave_FDS.nLFO_Count <= 0)
2394 {
2395 mWave_FDS.nLFO_Count += mWave_FDS.nLFO_Timer;
2396 if(mWave_FDS.nLFO_Table[mWave_FDS.nLFO_Addr] == 4)
2397 mWave_FDS.nSweepBias = 0;
2398 else
2399 mWave_FDS.nSweepBias +=
2400 ModulationTable[
2401 mWave_FDS.nLFO_Table[mWave_FDS.nLFO_Addr]
2402 ];
2403 mWave_FDS.nLFO_Addr = (mWave_FDS.nLFO_Addr + 1) & 0x3F;
2404 }
2405
2406 while(mWave_FDS.nSweepBias > 63)
2407 mWave_FDS.nSweepBias -= 128;
2408 while(mWave_FDS.nSweepBias < -64)
2409 mWave_FDS.nSweepBias += 128;
2410
2411 register int32_t temp =
2412 mWave_FDS.nSweepBias * mWave_FDS.nSweep_Gain;
2413 if(temp & 0x0F)
2414 {
2415 temp /= 16;
2416 if(mWave_FDS.nSweepBias < 0) temp--;
2417 else temp += 2;
2418 }
2419 else
2420 temp /= 16;
2421
2422 if(temp > 193) temp -= 258;
2423 if(temp < -64) temp += 256;
2424
2425 subfreq = mWave_FDS.nFreq.W * temp / 64;
2426 }
2427
2428 /* Main Unit */
2429 if(mWave_FDS.bMain_On)
2430 {
2431 mWave_FDS.nMixL =
2432 FDS_nOutputTable_L[mWave_FDS.nMainVolume]
2433 [mWave_FDS.nVolume]
2434 [mWave_FDS.nWaveTable[mWave_FDS.nMainAddr] ];
2435
2436 if((subfreq + mWave_FDS.nFreq.W) > 0)
2437 {
2438 int32_t freq = (0x10000<<14) / (subfreq + mWave_FDS.nFreq.W);
2439
2440 mWave_FDS.nFreqCount -= tick<<14;
2441 while(mWave_FDS.nFreqCount <= 0)
2442 {
2443 mWave_FDS.nFreqCount += freq;
2444
2445 mWave_FDS.nMainAddr =
2446 (mWave_FDS.nMainAddr + 1) & 0x3F;
2447 mWave_FDS.nPopOutput =
2448 mWave_FDS.nWaveTable[mWave_FDS.nMainAddr];
2449 if(!mWave_FDS.nMainAddr)
2450 {
2451 if(mWave_FDS.nVolEnv_Gain < 0x20)
2452 mWave_FDS.nVolume = mWave_FDS.nVolEnv_Gain;
2453 else mWave_FDS.nVolume = 0x20;
2454 }
2455 }
2456 }
2457 else
2458 mWave_FDS.nFreqCount = mWave_FDS.nLFO_Count;
2459 }
2460 else if(mWave_FDS.bPopReducer && mWave_FDS.nPopOutput)
2461 {
2462 mWave_FDS.nMixL = FDS_nOutputTable_L[mWave_FDS.nMainVolume]
2463 [mWave_FDS.nVolume]
2464 [mWave_FDS.nPopOutput];
2465
2466 mWave_FDS.nPopCount -= tick;
2467 while(mWave_FDS.nPopCount <= 0)
2468 {
2469 mWave_FDS.nPopCount += 500;
2470 mWave_FDS.nPopOutput--;
2471 if(!mWave_FDS.nPopOutput)
2472 mWave_FDS.nMainAddr = 0;
2473 }
2474 } /* end FDS */
2475 }
2476 EXIT_TIMER(fds);
2477 } /* end while fulltick */
2478
2479 if(bBurnCPUCycles)
2480 {
2481 nCPUCycle += burned;
2482 fulltick += burned;
2483 }
2484
2485 /* Frame Sequencer */
2486
2487 ENTER_TIMER(frame);
2488 nTicksUntilNextFrame -= tick<<16;
2489 while(nTicksUntilNextFrame <= 0)
2490 {
2491 nTicksUntilNextFrame +=
2492 (bPALMode ? PAL_FRAME_COUNTER_FREQ : NTSC_FRAME_COUNTER_FREQ) *
2493 0x10000;
2494 nFrameCounter++;
2495 if(nFrameCounter > nFrameCounterMax)
2496 nFrameCounter = 0;
2497
2498 if(nFrameCounterMax == 4)
2499 {
2500 if(nFrameCounter < 4)
2501 {
2502 CLOCK_MAJOR();
2503 if(!(nFrameCounter & 1))
2504 CLOCK_MINOR();
2505 }
2506 }
2507 else
2508 {
2509 CLOCK_MAJOR();
2510 if(nFrameCounter & 1)
2511 CLOCK_MINOR();
2512
2513 if((nFrameCounter == 3) && bFrameIRQEnabled)
2514 bFrameIRQPending = 1;
2515 }
2516 }
2517 EXIT_TIMER(frame);
2518
2519 ENTER_TIMER(mix);
2520 nTicksUntilNextSample -= tick<<16;
2521 if(nTicksUntilNextSample <= 0)
2522 {
2523 nTicksUntilNextSample += nTicksPerSample;
2524
2525 mixL = mWave_Squares.nMixL;
2526 mixL += mWave_TND.nMixL;
2527
2528 if(nExternalSound && !bPALMode)
2529 {
2530 if(nExternalSound & EXTSOUND_VRC6)
2531 {
2532 mixL += (mWave_VRC6Pulse[0].nMixL);
2533 mixL += (mWave_VRC6Pulse[1].nMixL);
2534 mixL += (mWave_VRC6Saw.nMixL);
2535 }
2536 if(nExternalSound & EXTSOUND_N106) {
2537 mixL += (mWave_N106.nMixL[0]);
2538 mixL += (mWave_N106.nMixL[1]);
2539 mixL += (mWave_N106.nMixL[2]);
2540 mixL += (mWave_N106.nMixL[3]);
2541 mixL += (mWave_N106.nMixL[4]);
2542 mixL += (mWave_N106.nMixL[5]);
2543 mixL += (mWave_N106.nMixL[6]);
2544 mixL += (mWave_N106.nMixL[7]);
2545 }
2546 if(nExternalSound & EXTSOUND_FME07)
2547 {
2548 mixL += (mWave_FME07[0].nMixL);
2549 mixL += (mWave_FME07[1].nMixL);
2550 mixL += (mWave_FME07[2].nMixL);
2551 }
2552 if(nExternalSound & EXTSOUND_FDS)
2553 mixL += mWave_FDS.nMixL;
2554 }
2555
2556 /* Filter */
2557 diff = ((int64_t)mixL << 25) - nFilterAccL;
2558 nFilterAccL += (diff * nHighPass) >> 16;
2559 mixL = (int32_t)(diff >> 23);
2560 /* End Filter */
2561
2562 if(bFade && (fFadeVolume < 1))
2563 mixL = (int32_t)(mixL * fFadeVolume);
2564
2565 if(mixL < -32768) mixL = -32768;
2566 if(mixL > 32767) mixL = 32767;
2567
2568 *((uint16_t*)pOutput) = (uint16_t)mixL;
2569 pOutput += 2;
2570 }
2571
2572 }
2573 EXIT_TIMER(mix);
2574
2575 nAPUCycle = nCPUCycle;
2576
2577 EXIT_TIMER(apu);
2578}
2579
2580
2581/*
2582 * Initialize
2583 *
2584 * Initializes Memory
2585 */
2586
2587int NSFCore_Initialize()
2588{
2589 int32_t i;
2590 /* clear globals */
2591 /* why, yes, this was easier when they were in a struct */
2592
2593 /* Initialization flags */
2594 bMemoryOK=0;
2595 bFileLoaded=0;
2596 bTrackSelected=0;
2597 bIsGeneratingSamples=0;
2598
2599 /*
2600 * Memory
2601 */
2602
2603 ZEROMEMORY(pRAM,0x800);
2604 ZEROMEMORY(pSRAM,0x2000);
2605 ZEROMEMORY(pExRAM,0x1000);
2606 pROM_Full=0;
2607
2608 ZEROMEMORY(pROM,10);
2609 pStack=0;
2610
2611 nROMSize=0;
2612 nROMBankCount=0;
2613 nROMMaxSize=0;
2614
2615 /*
2616 * Memory Proc Pointers
2617 */
2618
2619 ZEROMEMORY(ReadMemory,sizeof(ReadProc)*0x10);
2620 ZEROMEMORY(WriteMemory,sizeof(WriteProc)*0x10);
2621
2622 /*
2623 * 6502 Registers / Mode
2624 */
2625
2626 regA=0;
2627 regX=0;
2628 regY=0;
2629 regP=0;
2630 regSP=0;
2631 regPC=0;
2632
2633 bPALMode=0;
2634 bCPUJammed=0;
2635
2636 nMultIn_Low=0;
2637 nMultIn_High=0;
2638
2639 /*
2640 * NSF Preparation Information
2641 */
2642
2643 ZEROMEMORY(nBankswitchInitValues,10);
2644 nPlayAddress=0;
2645 nInitAddress=0;
2646
2647 nExternalSound=0;
2648 nCurTrack=0;
2649
2650 fNSFPlaybackSpeed=0;
2651
2652 /*
2653 * pAPU
2654 */
2655
2656 nFrameCounter=0;
2657 nFrameCounterMax=0;
2658 bFrameIRQEnabled=0;
2659 bFrameIRQPending=0;
2660
2661 /*
2662 * Timing and Counters
2663 */
2664 nTicksUntilNextFrame=0;
2665
2666 nTicksPerPlay=0;
2667 nTicksUntilNextPlay=0;
2668
2669 nTicksPerSample=0;
2670 nTicksUntilNextSample=0;
2671
2672 nCPUCycle=0;
2673 nAPUCycle=0;
2674 nTotalPlays=0;
2675
2676 /*
2677 * Silence Tracker
2678 */
2679 nSilentSamples=0;
2680 nSilentSampleMax=0;
2681 nSilenceTrackMS=0;
2682 bNoSilenceIfTime=0;
2683 bTimeNotDefault=0;
2684
2685 /*
2686 * Volume/fading/filter tracking
2687 */
2688
2689 nStartFade=0;
2690 nEndFade=0;
2691 bFade=0;
2692 fFadeVolume=0;
2693 fFadeChange=0;
2694
2695 pOutput=0;
2696
2697 nDMCPop_Prev=0;
2698 bDMCPop_Skip=0;
2699 bDMCPop_SamePlay=0;
2700
2701 /*
2702 * Sound Filter
2703 */
2704
2705 nFilterAccL=0;
2706 nHighPass=0;
2707
2708 nHighPassBase=0;
2709
2710 bHighPassEnabled=0;
2711
2712 /* channels */
2713
2714 ZEROMEMORY(&mWave_Squares,sizeof(struct Wave_Squares));
2715 ZEROMEMORY(&mWave_TND,sizeof(struct Wave_TND));
2716 ZEROMEMORY(mWave_VRC6Pulse,sizeof(struct VRC6PulseWave)*2);
2717 ZEROMEMORY(&mWave_VRC6Saw,sizeof(struct VRC6SawWave));
2718 ZEROMEMORY(&mWave_N106,sizeof(struct N106Wave));
2719 ZEROMEMORY(mWave_FME07,sizeof(struct FME07Wave)*3);
2720 ZEROMEMORY(&mWave_FDS,sizeof(struct FDSWave));
2721
2722 /* end clear globals */
2723
2724 // Default filter bases
2725 nHighPassBase = 150;
2726
2727 bHighPassEnabled = 1;
2728
2729 mWave_TND.nNoiseRandomShift = 1;
2730 for(i = 0; i < 8; i++)
2731 mWave_TND.pDMCDMAPtr[i] = pROM[i + 2];
2732
2733
2734 SetPlaybackOptions(nSampleRate);
2735
2736 for(i = 0; i < 8; i++)
2737 mWave_N106.fFrequencyLookupTable[i] =
2738 (((i + 1) * 45 * 0x40000) / (float)NES_FREQUENCY) *
2739 (float)NTSC_FREQUENCY;
2740
2741 if(bMemoryOK) return 1;
2742
2743 ZEROMEMORY(pRAM,0x800);
2744 ZEROMEMORY(pSRAM,0x2000);
2745 ZEROMEMORY(pExRAM,0x1000);
2746 pStack = pRAM + 0x100;
2747 bMemoryOK = 1;
2748 return 1;
2749}
2750
2751/*
2752 * LoadNSF
2753 */
2754
2755int LoadNSF(int32_t datasize)
2756{
2757 if(!bMemoryOK) return 0;
2758
2759 if(!pDataBuffer) return 0;
2760
2761 int32_t i;
2762
2763 bFileLoaded = 0;
2764 bTrackSelected = 0;
2765 nExternalSound = nChipExtensions;
2766 if(nIsPal & 2)
2767 bPALMode = bPALPreference;
2768 else
2769 bPALMode = nIsPal & 1;
2770
2771 SetPlaybackOptions(nSampleRate);
2772
2773 int32_t neededsize = datasize + (nfileLoadAddress & 0x0FFF);
2774 if(neededsize & 0x0FFF) neededsize += 0x1000 - (neededsize & 0x0FFF);
2775 if(neededsize < 0x1000) neededsize = 0x1000;
2776
2777 uint8_t specialload = 0;
2778
2779 for(i = 0; (i < 8) && (!nBankswitch[i]); i++);
2780 if(i < 8) /* uses bankswitching */
2781 {
2782 memcpy(&nBankswitchInitValues[2],nBankswitch,8);
2783 nBankswitchInitValues[0] = nBankswitch[6];
2784 nBankswitchInitValues[1] = nBankswitch[7];
2785 if(nExternalSound & EXTSOUND_FDS)
2786 {
2787 if(!(nBankswitchInitValues[0] || nBankswitchInitValues[1]))
2788 {
2789 /*
2790 * FDS sound with '00' specified for both $6000 and $7000 banks.
2791 * point this to an area of fresh RAM (sort of hackish solution
2792 * for those FDS tunes that don't quite follow the nsf specs.
2793 */
2794 nBankswitchInitValues[0] = (uint8_t)(neededsize >> 12);
2795 nBankswitchInitValues[1] = (uint8_t)(neededsize >> 12) + 1;
2796 neededsize += 0x2000;
2797 }
2798 }
2799 }
2800 else /* doesn't use bankswitching */
2801 {
2802 if(nExternalSound & EXTSOUND_FDS)
2803 {
2804 /* bad load address */
2805 if(nfileLoadAddress < 0x6000) return 0;
2806
2807 if(neededsize < 0xA000)
2808 neededsize = 0xA000;
2809 specialload = 1;
2810 for(i = 0; i < 10; i++)
2811 nBankswitchInitValues[i] = (uint8_t)i;
2812 }
2813 else
2814 {
2815 /* bad load address */
2816 if(nfileLoadAddress < 0x8000) return 0;
2817
2818 int32_t j = (nfileLoadAddress >> 12) - 6;
2819 for(i = 0; i < j; i++)
2820 nBankswitchInitValues[i] = 0;
2821 for(j = 0; i < 10; i++, j++)
2822 nBankswitchInitValues[i] = (uint8_t)j;
2823 }
2824 }
2825
2826 nROMSize = neededsize;
2827 nROMBankCount = neededsize >> 12;
2828
2829 if(specialload)
2830 pROM_Full = pDataBuffer-(nfileLoadAddress-0x6000);
2831 else
2832 pROM_Full = pDataBuffer-(nfileLoadAddress&0x0FFF);
2833
2834 ZEROMEMORY(pRAM,0x0800);
2835 ZEROMEMORY(pExRAM,0x1000);
2836 ZEROMEMORY(pSRAM,0x2000);
2837
2838 nExternalSound = nChipExtensions;
2839 fNSFPlaybackSpeed = (bPALMode ? PAL_NMIRATE : NTSC_NMIRATE);
2840
2841 bFileLoaded = 1;
2842
2843 SetPlaybackSpeed(0);
2844
2845 nPlayAddress = nfilePlayAddress;
2846 nInitAddress = nfileInitAddress;
2847
2848 pExRAM[0x00] = 0x20; /* JSR */
2849 pExRAM[0x01] = nInitAddress&0xff; /* Init Address */
2850 pExRAM[0x02] = (nInitAddress>>8)&0xff;
2851 pExRAM[0x03] = 0xF2; /* JAM */
2852 pExRAM[0x04] = 0x20; /* JSR */
2853 pExRAM[0x05] = nPlayAddress&0xff; /* Play Address */
2854 pExRAM[0x06] = (nPlayAddress>>8)&0xff;
2855 pExRAM[0x07] = 0x4C; /* JMP */
2856 pExRAM[0x08] = 0x03;/* $5003 (JAM right before the JSR to play address) */
2857 pExRAM[0x09] = 0x50;
2858
2859 regA = regX = regY = 0;
2860 regP = 0x04; /* I_FLAG */
2861 regSP = 0xFF;
2862
2863 nFilterAccL = 0;
2864
2865 /* Reset Read/Write Procs */
2866
2867 ReadMemory[0] = ReadMemory[1] = ReadMemory_RAM;
2868 ReadMemory[2] = ReadMemory[3] = ReadMemory_Default;
2869 ReadMemory[4] = ReadMemory_pAPU;
2870 ReadMemory[5] = ReadMemory_ExRAM;
2871 ReadMemory[6] = ReadMemory[7] = ReadMemory_SRAM;
2872
2873 WriteMemory[0] = WriteMemory[1] = WriteMemory_RAM;
2874 WriteMemory[2] = WriteMemory[3] = WriteMemory_Default;
2875 WriteMemory[4] = WriteMemory_pAPU;
2876 WriteMemory[5] = WriteMemory_ExRAM;
2877 WriteMemory[6] = WriteMemory[7] = WriteMemory_SRAM;
2878
2879 for(i = 8; i < 16; i++)
2880 {
2881 ReadMemory[i] = ReadMemory_ROM;
2882 WriteMemory[i] = WriteMemory_Default;
2883 }
2884
2885 if(nExternalSound & EXTSOUND_FDS)
2886 {
2887 WriteMemory[0x06] = WriteMemory_FDSRAM;
2888 WriteMemory[0x07] = WriteMemory_FDSRAM;
2889 WriteMemory[0x08] = WriteMemory_FDSRAM;
2890 WriteMemory[0x09] = WriteMemory_FDSRAM;
2891 WriteMemory[0x0A] = WriteMemory_FDSRAM;
2892 WriteMemory[0x0B] = WriteMemory_FDSRAM;
2893 WriteMemory[0x0C] = WriteMemory_FDSRAM;
2894 WriteMemory[0x0D] = WriteMemory_FDSRAM;
2895 ReadMemory[0x06] = ReadMemory_ROM;
2896 ReadMemory[0x07] = ReadMemory_ROM;
2897 }
2898
2899 if(!bPALMode) /* no expansion sound available on a PAL system */
2900 {
2901 if(nExternalSound & EXTSOUND_VRC6)
2902 {
2903 /* if both VRC6+VRC7... it MUST go to WriteMemory_VRC6
2904 * or register writes will be lost (WriteMemory_VRC6 calls
2905 * WriteMemory_VRC7 if needed) */
2906 WriteMemory[0x09] = WriteMemory_VRC6;
2907 WriteMemory[0x0A] = WriteMemory_VRC6;
2908 WriteMemory[0x0B] = WriteMemory_VRC6;
2909 }
2910 if(nExternalSound & EXTSOUND_N106)
2911 {
2912 WriteMemory[0x04] = WriteMemory_N106;
2913 ReadMemory[0x04] = ReadMemory_N106;
2914 WriteMemory[0x0F] = WriteMemory_N106;
2915 }
2916 if(nExternalSound & EXTSOUND_FME07)
2917 {
2918 WriteMemory[0x0C] = WriteMemory_FME07;
2919 WriteMemory[0x0E] = WriteMemory_FME07;
2920 }
2921 }
2922
2923 /* MMC5 still has a multiplication reg that needs to be available on
2924 PAL tunes */
2925 if(nExternalSound & EXTSOUND_MMC5)
2926 WriteMemory[0x05] = WriteMemory_MMC5;
2927
2928 return 1;
2929}
2930
2931/*
2932 * SetTrack
2933 */
2934
2935void SetTrack(uint8_t track)
2936{
2937 int32_t i;
2938 if(!bFileLoaded) return;
2939
2940 bTrackSelected = 1;
2941 nCurTrack = track;
2942
2943 regPC = 0x5000;
2944 regA = track;
2945 regX = bPALMode;
2946 regY = bCleanAXY ? 0 : 0xCD;
2947 regSP = 0xFF;
2948 if(bCleanAXY)
2949 regP = 0x04;
2950 bCPUJammed = 0;
2951
2952 nCPUCycle = nAPUCycle = 0;
2953 nDMCPop_Prev = 0;
2954 bDMCPop_Skip = 0;
2955
2956 for(i = 0x4000; i < 0x400F; i++)
2957 WriteMemory_pAPU(i,0);
2958 WriteMemory_pAPU(0x4010,0);
2959 WriteMemory_pAPU(0x4012,0);
2960 WriteMemory_pAPU(0x4013,0);
2961 WriteMemory_pAPU(0x4014,0);
2962 WriteMemory_pAPU(0x4015,0);
2963 WriteMemory_pAPU(0x4015,0x0F);
2964 WriteMemory_pAPU(0x4017,0);
2965
2966 for(i = 0; i < 10; i++)
2967 WriteMemory_ExRAM(0x5FF6 + i,nBankswitchInitValues[i]);
2968
2969 ZEROMEMORY(pRAM,0x0800);
2970 ZEROMEMORY(pSRAM,0x2000);
2971 ZEROMEMORY(&pExRAM[0x10],0x0FF0);
2972 bFade = 0;
2973
2974
2975 nTicksUntilNextSample = nTicksPerSample;
2976 nTicksUntilNextFrame =
2977 (bPALMode ? PAL_FRAME_COUNTER_FREQ : NTSC_FRAME_COUNTER_FREQ)*0x10000;
2978 nTicksUntilNextPlay = nTicksPerPlay;
2979 nTotalPlays = 0;
2980
2981 /* Clear mixing vals */
2982 mWave_Squares.nMixL = 0;
2983 mWave_TND.nMixL = 0;
2984 mWave_VRC6Pulse[0].nMixL = 0;
2985 mWave_VRC6Pulse[1].nMixL = 0;
2986 mWave_VRC6Saw.nMixL = 0;
2987
2988 /* Reset Tri/Noise/DMC */
2989 mWave_TND.nTriStep = mWave_TND.nTriOutput = 0;
2990 mWave_TND.nDMCOutput = 0;
2991 mWave_TND.bNoiseRandomOut = 0;
2992 mWave_Squares.nDutyCount[0] = mWave_Squares.nDutyCount[1] = 0;
2993 mWave_TND.bDMCActive = 0;
2994 mWave_TND.nDMCBytesRemaining = 0;
2995 mWave_TND.bDMCSampleBufferEmpty = 1;
2996 mWave_TND.bDMCDeltaSilent = 1;
2997
2998 /* Reset VRC6 */
2999 mWave_VRC6Pulse[0].nVolume = 0;
3000 mWave_VRC6Pulse[1].nVolume = 0;
3001 mWave_VRC6Saw.nAccumRate = 0;
3002
3003 /* Reset N106 */
3004 ZEROMEMORY(mWave_N106.nRAM,0x100);
3005 ZEROMEMORY(mWave_N106.nVolume,8);
3006 ZEROMEMORY(mWave_N106.nOutput,8);
3007 ZEROMEMORY(mWave_N106.nMixL,32);
3008
3009 /* Reset FME-07 */
3010 mWave_FME07[0].nVolume = 0;
3011 mWave_FME07[1].nVolume = 0;
3012 mWave_FME07[2].nVolume = 0;
3013
3014 /* Clear FDS crap */
3015
3016 mWave_FDS.bEnvelopeEnable = 0;
3017 mWave_FDS.nEnvelopeSpeed = 0xFF;
3018 mWave_FDS.nVolEnv_Mode = 2;
3019 mWave_FDS.nVolEnv_Decay = 0;
3020 mWave_FDS.nVolEnv_Gain = 0;
3021 mWave_FDS.nVolume = 0;
3022 mWave_FDS.bVolEnv_On = 0;
3023 mWave_FDS.nSweep_Mode = 2;
3024 mWave_FDS.nSweep_Decay = 0;
3025 mWave_FDS.nSweep_Gain = 0;
3026 mWave_FDS.bSweepEnv_On = 0;
3027 mWave_FDS.nSweepBias = 0;
3028 mWave_FDS.bLFO_Enabled = 0;
3029 mWave_FDS.nLFO_Freq.W = 0;
3030/* mWave_FDS.fLFO_Timer = 0;
3031 mWave_FDS.fLFO_Count = 0;*/
3032 mWave_FDS.nLFO_Timer = 0;
3033 mWave_FDS.nLFO_Count = 0;
3034 mWave_FDS.nLFO_Addr = 0;
3035 mWave_FDS.bLFO_On = 0;
3036 mWave_FDS.nMainVolume = 0;
3037 mWave_FDS.bEnabled = 0;
3038 mWave_FDS.nFreq.W = 0;
3039/* mWave_FDS.fFreqCount = 0;*/
3040 mWave_FDS.nFreqCount = 0;
3041 mWave_FDS.nMainAddr = 0;
3042 mWave_FDS.bWaveWrite = 0;
3043 mWave_FDS.bMain_On = 0;
3044 mWave_FDS.nMixL = 0;
3045 ZEROMEMORY(mWave_FDS.nWaveTable,0x40);
3046 ZEROMEMORY(mWave_FDS.nLFO_Table,0x40);
3047
3048 mWave_FDS.nSweep_Count = mWave_FDS.nSweep_Timer =
3049 ((mWave_FDS.nSweep_Decay + 1) * mWave_FDS.nEnvelopeSpeed * 8);
3050 mWave_FDS.nVolEnv_Count = mWave_FDS.nVolEnv_Timer =
3051 ((mWave_FDS.nVolEnv_Decay + 1) * mWave_FDS.nEnvelopeSpeed * 8);
3052
3053 nSilentSamples = 0;
3054
3055 nFilterAccL = 0;
3056
3057 nSilentSamples = 0;
3058
3059 fulltick=0;
3060}
3061
3062/*
3063 * SetPlaybackOptions
3064 */
3065
3066int SetPlaybackOptions(int32_t samplerate)
3067{
3068 if(samplerate < 2000) return 0;
3069 if(samplerate > 96000) return 0;
3070
3071 nTicksPerSample =
3072 (bPALMode ? PAL_FREQUENCY : NTSC_FREQUENCY) / samplerate * 0x10000;
3073 nTicksUntilNextSample = nTicksPerSample;
3074
3075 RecalcFilter();
3076 RecalcSilenceTracker();
3077
3078 return 1;
3079}
3080
3081/*
3082 * SetPlaybackSpeed
3083 */
3084
3085void SetPlaybackSpeed(float playspersec)
3086{
3087 if(playspersec < 1)
3088 {
3089 if(!bFileLoaded) return;
3090 playspersec = fNSFPlaybackSpeed;
3091 }
3092
3093 nTicksPerPlay = nTicksUntilNextPlay =
3094 (bPALMode ? PAL_FREQUENCY : NTSC_FREQUENCY) / playspersec * 0x10000;
3095}
3096
3097/*
3098* GetPlaybackSpeed
3099*/
3100
3101float GetPlaybackSpeed()
3102{
3103 if(nTicksPerPlay <= 0) return 0;
3104 return ((bPALMode ? PAL_FREQUENCY : NTSC_FREQUENCY) / (nTicksPerPlay>>16));
3105}
3106
3107/*
3108 * RecalcFilter
3109 */
3110
3111void RecalcFilter()
3112{
3113 if(!nSampleRate) return;
3114
3115 nHighPass = ((int64_t)nHighPassBase << 16) / nSampleRate;
3116
3117 if(nHighPass > (1<<16)) nHighPass = 1<<16;
3118}
3119
3120/*
3121 * RecalcSilenceTracker
3122 */
3123
3124void RecalcSilenceTracker()
3125{
3126 if(nSilenceTrackMS <= 0 || !nSampleRate ||
3127 (bNoSilenceIfTime && bTimeNotDefault))
3128 {
3129 nSilentSampleMax = 0;
3130 return;
3131 }
3132
3133 nSilentSampleMax = nSilenceTrackMS * nSampleRate / 500;
3134 nSilentSampleMax /= 2;
3135}
3136
3137void RebuildOutputTables(void) {
3138 int32_t i,j;
3139 float l[3];
3140 int32_t v;
3141 int32_t temp;
3142 float ftemp;
3143
3144 /* tnd */
3145 for(i = 0; i < 3; i++)
3146 {
3147 l[i] = 255;
3148 }
3149
3150 for(i = 0; i < 0x8000; i++)
3151 {
3152 ftemp = (l[0] * (i >> 11)) / 2097885;
3153 ftemp += (l[1] * ((i >> 7) & 0x0F)) / 3121455;
3154 ftemp += (l[2] * (i & 0x7F)) / 5772690;
3155
3156 if(!ftemp)
3157 main_nOutputTable_L[i] = 0;
3158 else
3159 main_nOutputTable_L[i] =
3160 (int16_t)(2396850 / ((1.0f / ftemp) + 100));
3161 }
3162
3163 /* squares */
3164 for(i = 0; i < 2; i++)
3165 {
3166 l[i] = 255;
3167 }
3168
3169 for(i = 0; i < 0x100; i++)
3170 {
3171 temp = (int32_t)(l[0] * (i >> 4));
3172 temp += (int32_t)(l[1] * (i & 0x0F));
3173
3174 if(!temp)
3175 Squares_nOutputTable_L[i] = 0;
3176 else
3177 Squares_nOutputTable_L[i] = 1438200 / ((2072640 / temp) + 100);
3178
3179 }
3180
3181 /* TODO: only one table needed for both */
3182 /* VRC6 Pulse 1,2 */
3183 /*CalculateChannelVolume(1875,&tl,255);*/
3184 for(i = 0; i < 0x10; i++)
3185 {
3186 VRC6Pulse_nOutputTable_L[0][i] = VRC6Pulse_nOutputTable_L[1][i] =
3187 1875 * i / 0x0F;
3188 }
3189 /* VRC6 Saw */
3190 /*CalculateChannelVolume(3750,&tl,255);*/
3191 for(i = 0; i < 0x20; i++)
3192 {
3193 VRC6Saw_nOutputTable_L[i] = 3750 * i / 0x1F;
3194 }
3195
3196 /* TODO: only one table needed for all 8 */
3197 /* N106 channels */
3198 for(v = 0; v < 8; v++)
3199 {
3200 /*CalculateChannelVolume(3000,&tl,255);
3201 this amplitude is just a guess */
3202
3203 for(i = 0; i < 0x10; i++)
3204 {
3205 for(j = 0; j < 0x10; j++)
3206 {
3207 N106_nOutputTable_L[v][i][j] = (3000 * i * j) / 0xE1;
3208 }
3209 }
3210 }
3211
3212 /* TODO: only one table needed for all 3 */
3213 /* FME-07 Square A,B,C */
3214 /*CalculateChannelVolume(3000,&tl,255);*/
3215 FME07_nOutputTable_L[0][15] = FME07_nOutputTable_L[1][15] =
3216 FME07_nOutputTable_L[2][15] = 3000;
3217 FME07_nOutputTable_L[0][0] = FME07_nOutputTable_L[1][0] =
3218 FME07_nOutputTable_L[2][0] = 0;
3219 for(i = 14; i > 0; i--)
3220 {
3221 FME07_nOutputTable_L[0][i] = FME07_nOutputTable_L[1][i] =
3222 FME07_nOutputTable_L[2][i] = FME07_nOutputTable_L[0][i + 1] * 80 / 100;
3223 }
3224
3225 /*
3226 * FDS
3227 */
3228 /* this base volume (4000) is just a guess to what sounds right.
3229 * Given the number of steps available in an FDS wave... it seems like
3230 * it should be much much more... but then it's TOO loud.
3231 */
3232 /*CalculateChannelVolume(4000,&tl,255);*/
3233 for(i = 0; i < 0x21; i++)
3234 {
3235 for(j = 0; j < 0x40; j++)
3236 {
3237 FDS_nOutputTable_L[0][i][j] =
3238 (4000 * i * j * 30) / (0x21 * 0x40 * 30);
3239 FDS_nOutputTable_L[1][i][j] =
3240 (4000 * i * j * 20) / (0x21 * 0x40 * 30);
3241 FDS_nOutputTable_L[2][i][j] =
3242 (4000 * i * j * 15) / (0x21 * 0x40 * 30);
3243 FDS_nOutputTable_L[3][i][j] =
3244 (4000 * i * j * 12) / (0x21 * 0x40 * 30);
3245 }
3246 }
3247}
3248
3249/*
3250 * GetPlayCalls
3251 */
3252
3253float GetPlayCalls()
3254{
3255 if(!nTicksPerPlay) return 0;
3256
3257 return ((float)nTotalPlays) +
3258 (1.0f - (nTicksUntilNextPlay*1.0f / nTicksPerPlay));
3259}
3260
3261/*
3262 * GetWrittenTime
3263 */
3264uint32_t GetWrittenTime(float basedplayspersec /* = 0 */)
3265{
3266 if(basedplayspersec <= 0)
3267 basedplayspersec = GetPlaybackSpeed();
3268
3269 if(basedplayspersec <= 0)
3270 return 0;
3271
3272 return (uint32_t)((GetPlayCalls() * 1000) / basedplayspersec);
3273}
3274
3275/*
3276 * StopFade
3277 */
3278void StopFade()
3279{
3280 bFade = 0;
3281 fFadeVolume = 1;
3282}
3283
3284/*
3285 * SongCompleted
3286 */
3287
3288uint8_t SongCompleted()
3289{
3290 if(!bFade) return 0;
3291 if(nTotalPlays >= nEndFade) return 1;
3292 if(nSilentSampleMax) return (nSilentSamples >= nSilentSampleMax);
3293
3294 return 0;
3295}
3296
3297/*
3298 * SetFade
3299 */
3300
3301void SetFade(int32_t fadestart,int32_t fadestop,
3302 uint8_t bNotDefault) /* play routine calls */
3303{
3304 if(fadestart < 0) fadestart = 0;
3305 if(fadestop < fadestart) fadestop = fadestart;
3306
3307 nStartFade = (uint32_t)fadestart;
3308 nEndFade = (uint32_t)fadestop;
3309 bFade = 1;
3310 bTimeNotDefault = bNotDefault;
3311
3312 RecalcSilenceTracker();
3313 RecalculateFade();
3314}
3315
3316/*
3317 * SetFadeTime
3318 */
3319
3320void SetFadeTime(uint32_t fadestart,uint32_t fadestop,float basedplays,
3321 uint8_t bNotDefault) /* time in MS */
3322{
3323 if(basedplays <= 0)
3324 basedplays = GetPlaybackSpeed();
3325 if(basedplays <= 0)
3326 return;
3327
3328 SetFade((int32_t)(fadestart * basedplays / 1000),
3329 (int32_t)(fadestop * basedplays / 1000),bNotDefault);
3330}
3331
3332/*
3333 * RecalculateFade
3334 */
3335
3336void RecalculateFade()
3337{
3338 if(!bFade) return;
3339
3340 /* make it hit silence a little before the song ends...
3341 otherwise we're not really fading OUT, we're just fading umm...
3342 quieter =P */
3343 int32_t temp = (int32_t)(GetPlaybackSpeed() / 4);
3344
3345 if(nEndFade <= nStartFade)
3346 {
3347 nEndFade = nStartFade;
3348 fFadeChange = 1.0f;
3349 }
3350 else if((nEndFade - temp) <= nStartFade)
3351 fFadeChange = 1.0f;
3352 else
3353 fFadeChange = 1.0f / (nEndFade - nStartFade - temp);
3354
3355 if(nTotalPlays < nStartFade)
3356 fFadeVolume = 1.0f;
3357 else if(nTotalPlays >= nEndFade)
3358 fFadeVolume = 0.0f;
3359 else
3360 {
3361 fFadeVolume = 1.0f - ( (nTotalPlays - nStartFade + 1) * fFadeChange );
3362 if(fFadeVolume < 0)
3363 fFadeVolume = 0;
3364 }
3365
3366}
3367
3368int32_t GetSamples(uint8_t* buffer,int32_t buffersize)
3369{
3370 if(!buffer) return 0;
3371 if(buffersize < 16) return 0;
3372 if(!bTrackSelected) return 0;
3373 if(bFade && (nTotalPlays >= nEndFade)) return 0;
3374 if(bIsGeneratingSamples) return 0;
3375
3376 bIsGeneratingSamples = 1;
3377
3378
3379 pOutput = buffer;
3380 uint32_t runtocycle =
3381 (uint32_t)((buffersize / 2) * nTicksPerSample / 0x10000);
3382 nCPUCycle = nAPUCycle = 0;
3383 uint32_t tick;
3384
3385 while(1)
3386 {
3387 /*tick = (uint32_t)ceil(fTicksUntilNextPlay);*/
3388 tick = (nTicksUntilNextPlay+0xffff)>>16;
3389 if((tick + nCPUCycle) > runtocycle)
3390 tick = runtocycle - nCPUCycle;
3391
3392 if(bCPUJammed)
3393 {
3394 nCPUCycle += tick;
3395 EmulateAPU(0);
3396 }
3397 else
3398 {
3399 tick = Emulate6502(tick + nCPUCycle);
3400 EmulateAPU(1);
3401 }
3402
3403 nTicksUntilNextPlay -= tick<<16;
3404 if(nTicksUntilNextPlay <= 0)
3405 {
3406 nTicksUntilNextPlay += nTicksPerPlay;
3407 if((bCPUJammed == 2) || bNoWaitForReturn)
3408 {
3409 regX = regY = regA = (bCleanAXY ? 0 : 0xCD);
3410 regPC = 0x5004;
3411 nTotalPlays++;
3412 bDMCPop_SamePlay = 0;
3413 bCPUJammed = 0;
3414 if(nForce4017Write == 1) WriteMemory_pAPU(0x4017,0x00);
3415 if(nForce4017Write == 2) WriteMemory_pAPU(0x4017,0x80);
3416 }
3417
3418 if(bFade && (nTotalPlays >= nStartFade))
3419 {
3420 fFadeVolume -= fFadeChange;
3421 if(fFadeVolume < 0)
3422 fFadeVolume = 0;
3423 if(nTotalPlays >= nEndFade)
3424 break;
3425 }
3426 }
3427
3428 if(nCPUCycle >= runtocycle)
3429 break;
3430 }
3431
3432 nCPUCycle = nAPUCycle = 0;
3433 bIsGeneratingSamples = 0;
3434
3435 if(nSilentSampleMax && bFade)
3436 {
3437 int16_t* tempbuf = (int16_t*)buffer;
3438 while( ((uint8_t*)tempbuf) < pOutput)
3439 {
3440 if( (*tempbuf < -SILENCE_THRESHOLD) ||
3441 (*tempbuf > SILENCE_THRESHOLD) )
3442 nSilentSamples = 0;
3443 else
3444 {
3445 if(++nSilentSamples >= nSilentSampleMax)
3446 return (int32_t)( ((uint8_t*)tempbuf) - buffer);
3447 }
3448 tempbuf++;
3449 }
3450 }
3451
3452 return (int32_t)(pOutput - buffer);
3453}
3454
3455/****************** 6502 emulation ******************/
3456
3457/* Memory reading/writing and other defines */
3458
3459/* reads zero page memory */
3460#define Zp(a) pRAM[a]
3461/* reads zero page memory in word form */
3462#define ZpWord(a) (Zp(a) | (Zp((uint8_t)(a + 1)) << 8))
3463/* reads memory */
3464#define Rd(a) ((ReadMemory[((uint16_t)(a)) >> 12])(a))
3465/* reads memory in word form */
3466#define RdWord(a) (Rd(a) | (Rd(a + 1) << 8))
3467/* writes memory */
3468#define Wr(a,v) (WriteMemory[((uint16_t)(a)) >> 12])(a,v)
3469/* writes zero paged memory */
3470#define WrZ(a,v) pRAM[a] = v
3471/* pushes a value onto the stack */
3472#define PUSH(v) pStack[SP--] = v
3473/* pulls a value from the stack */
3474#define PULL(v) v = pStack[++SP]
3475
3476/* Addressing Modes */
3477
3478/* first set - gets the value that's being addressed */
3479/*Immediate*/
3480#define Ad_VlIm() val = Rd(PC.W); PC.W++
3481/*Zero Page*/
3482#define Ad_VlZp() final.W = Rd(PC.W); val = Zp(final.W); PC.W++
3483/*Zero Page, X*/
3484#define Ad_VlZx() front.W = final.W = Rd(PC.W); final.B.l += X; \
3485 val = Zp(final.B.l); PC.W++
3486/*Zero Page, Y*/
3487#define Ad_VlZy() front.W = final.W = Rd(PC.W); final.B.l += Y; \
3488 val = Zp(final.B.l); PC.W++
3489/*Absolute*/
3490#define Ad_VlAb() final.W = RdWord(PC.W); val = Rd(final.W); PC.W += 2
3491/*Absolute, X [uses extra cycle if crossed page]*/
3492#define Ad_VlAx() front.W = final.W = RdWord(PC.W); final.W += X; PC.W += 2;\
3493 if(front.B.h != final.B.h) nCPUCycle++; val = Rd(final.W)
3494/*Absolute, X [uses extra cycle if crossed page]*/
3495#define Ad_VlAy() front.W = final.W = RdWord(PC.W); final.W += Y; PC.W += 2;\
3496 if(front.B.h != final.B.h) nCPUCycle++; val = Rd(final.W)
3497/*(Indirect, X)*/
3498#define Ad_VlIx() front.W = final.W = Rd(PC.W); final.B.l += X; PC.W++; \
3499 final.W = ZpWord(final.B.l); val = Rd(final.W)
3500/*(Indirect), Y [uses extra cycle if crossed page]*/
3501#define Ad_VlIy() val = Rd(PC.W); front.W = final.W = ZpWord(val); PC.W++;\
3502 final.W += Y; if(final.B.h != front.B.h) nCPUCycle++; \
3503 front.W = val; val = Rd(final.W)
3504
3505/* second set - gets the ADDRESS that the mode is referring to (for operators
3506 * that write to memory) note that AbsoluteX, AbsoluteY, and
3507 * IndirectY modes do NOT check for page boundary crossing here
3508 * since that extra cycle isn't added for operators that write to
3509 * memory (it only applies to ones that only read from memory.. in
3510 * which case the 1st set should be used)
3511 */
3512/*Zero Page*/
3513#define Ad_AdZp() final.W = Rd(PC.W); PC.W++
3514/*Zero Page, X*/
3515#define Ad_AdZx() final.W = front.W = Rd(PC.W); final.B.l += X; PC.W++
3516/*Zero Page, Y*/
3517#define Ad_AdZy() final.W = front.W = Rd(PC.W); final.B.l += Y; PC.W++
3518/*Absolute*/
3519#define Ad_AdAb() final.W = RdWord(PC.W); PC.W += 2
3520/*Absolute, X*/
3521#define Ad_AdAx() front.W = final.W = RdWord(PC.W); PC.W += 2; \
3522 final.W += X
3523/*Absolute, Y*/
3524#define Ad_AdAy() front.W = final.W = RdWord(PC.W); PC.W += 2; \
3525 final.W += Y
3526/*(Indirect, X)*/
3527#define Ad_AdIx() front.W = final.W = Rd(PC.W); PC.W++; final.B.l += X; \
3528 final.W = ZpWord(final.B.l)
3529/*(Indirect), Y*/
3530#define Ad_AdIy() front.W = Rd(PC.W); final.W = ZpWord(front.W) + Y; \
3531 PC.W++
3532
3533/* third set - reads memory, performs the desired operation on the value, then
3534 * writes back to memory
3535 * used for operators that directly change memory (ASL, INC, DEC, etc)
3536 */
3537/*Zero Page*/
3538#define MRW_Zp(cmd) Ad_AdZp(); val = Zp(final.W); cmd(val); WrZ(final.W,val)
3539/*Zero Page, X*/
3540#define MRW_Zx(cmd) Ad_AdZx(); val = Zp(final.W); cmd(val); WrZ(final.W,val)
3541/*Zero Page, Y*/
3542#define MRW_Zy(cmd) Ad_AdZy(); val = Zp(final.W); cmd(val); WrZ(final.W,val)
3543/*Absolute*/
3544#define MRW_Ab(cmd) Ad_AdAb(); val = Rd(final.W); cmd(val); Wr(final.W,val)
3545/*Absolute, X*/
3546#define MRW_Ax(cmd) Ad_AdAx(); val = Rd(final.W); cmd(val); Wr(final.W,val)
3547/*Absolute, Y*/
3548#define MRW_Ay(cmd) Ad_AdAy(); val = Rd(final.W); cmd(val); Wr(final.W,val)
3549/*(Indirect, X)*/
3550#define MRW_Ix(cmd) Ad_AdIx(); val = Rd(final.W); cmd(val); Wr(final.W,val)
3551/*(Indirect), Y*/
3552#define MRW_Iy(cmd) Ad_AdIy(); val = Rd(final.W); cmd(val); Wr(final.W,val)
3553
3554/* Relative modes are special in that they're only used by branch commands
3555 * this macro handles the jump, and should only be called if the branch
3556 * condition was true if the branch condition was false, the PC must be
3557 * incremented
3558 */
3559
3560#define RelJmp(cond) val = Rd(PC.W); PC.W++; final.W = PC.W + (int8_t)(val);\
3561 if(cond) {\
3562 nCPUCycle += ((final.B.h != PC.B.h) ? 2 : 1);\
3563 PC.W = final.W; }
3564
3565/* Status Flags */
3566
3567#define C_FLAG 0x01 /* carry flag */
3568#define Z_FLAG 0x02 /* zero flag */
3569#define I_FLAG 0x04 /* mask interrupt flag */
3570#define D_FLAG 0x08 /* decimal flag (decimal mode is unsupported on
3571 NES) */
3572#define B_FLAG 0x10 /* break flag (not really in the status register
3573 It's value in ST is never used. When ST is
3574 put in memory (by an interrupt or PHP), this
3575 flag is set only if BRK was called)
3576 ** also when PHP is called due to a bug */
3577#define R_FLAG 0x20 /* reserved flag (not really in the register.
3578 It's value is never used.
3579 Whenever ST is put in memory,
3580 this flag is always set) */
3581#define V_FLAG 0x40 /* overflow flag */
3582#define N_FLAG 0x80 /* sign flag */
3583
3584
3585/* Lookup Tables */
3586
3587/* the number of CPU cycles used for each instruction */
3588static const uint8_t CPU_Cycles[0x100] = {
35897,6,0,8,3,3,5,5,3,2,2,2,4,4,6,6,
35902,5,0,8,4,4,6,6,2,4,2,7,4,4,7,7,
35916,6,0,8,3,3,5,5,4,2,2,2,4,4,6,6,
35922,5,0,8,4,4,6,6,2,4,2,7,4,4,7,7,
35936,6,0,8,3,3,5,5,3,2,2,2,3,4,6,6,
35942,5,0,8,4,4,6,6,2,4,2,7,4,4,7,7,
35956,6,0,8,3,3,5,5,4,2,2,2,5,4,6,6,
35962,5,0,8,4,4,6,6,2,4,2,7,4,4,7,7,
35972,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4,
35982,6,0,6,4,4,4,4,2,5,2,5,5,5,5,5,
35992,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4,
36002,5,0,5,4,4,4,4,2,4,2,4,4,4,4,4,
36012,6,2,8,3,3,5,5,2,2,2,2,4,4,6,6,
36022,5,0,8,4,4,6,6,2,4,2,7,4,4,7,7,
36032,6,2,8,3,3,5,5,2,2,2,2,4,4,6,6,
36042,5,0,8,4,4,6,6,2,4,2,7,4,4,7,7 };
3605
3606/* the status of the NZ flags for the given value */
3607static const uint8_t NZTable[0x100] = {
3608Z_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,
36090,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,
36100,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,
36110,0,0,0,0,0,0,0,0,0,0,
3612N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,
3613N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,
3614N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,
3615N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,
3616N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,
3617N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,
3618N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,
3619N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,
3620N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,
3621N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,
3622N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,
3623N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG };
3624
3625/* A quick macro for working with the above table */
3626#define UpdateNZ(v) ST = (ST & ~(N_FLAG|Z_FLAG)) | NZTable[v]
3627
3628
3629/*
3630 * Opcodes
3631 *
3632 * These opcodes perform the action with the given value (changing that
3633 * value if necessary). Registers and flags associated with the operation
3634 * are changed accordingly. There are a few exceptions which will be noted
3635 * when they arise
3636 */
3637
3638
3639/* ADC
3640 Adds the value to the accumulator with carry
3641 Changes: A, NVZC
3642 - Decimal mode not supported on the NES
3643 - Due to a bug, NVZ flags are not altered if the Decimal flag is on
3644 --(taken out)-- */
3645#define ADC() \
3646 tw.W = A + val + (ST & C_FLAG); \
3647 ST = (ST & (I_FLAG|D_FLAG)) | tw.B.h | NZTable[tw.B.l] | \
3648 ( (0x80 & ~(A ^ val) & (A ^ tw.B.l)) ? V_FLAG : 0 ); \
3649 A = tw.B.l
3650
3651/* AND
3652 Combines the value with the accumulator using a bitwise AND operation
3653 Changes: A, NZ */
3654#define AND() \
3655 A &= val; \
3656 UpdateNZ(A)
3657
3658/* ASL
3659 Left shifts the value 1 bit. The bit that gets shifted out goes to
3660 the carry flag.
3661 Changes: value, NZC */
3662#define ASL(value) \
3663 tw.W = value << 1; \
3664 ST = (ST & ~(N_FLAG|Z_FLAG|C_FLAG)) | tw.B.h | NZTable[tw.B.l]; \
3665 value = tw.B.l
3666
3667/* BIT
3668 Compares memory with the accumulator with an AND operation, but changes
3669 neither.
3670 The two high bits of memory get transferred to the status reg
3671 Z is set if the AND operation yielded zero, otherwise it's cleared
3672 Changes: NVZ */
3673#define BIT() \
3674 ST = (ST & ~(N_FLAG|V_FLAG|Z_FLAG)) | (val & (N_FLAG|V_FLAG)) | \
3675 ((A & val) ? 0 : Z_FLAG)
3676
3677/* CMP, CPX, CPY
3678 Compares memory with the given register with a subtraction operation.
3679 Flags are set accordingly depending on the result:
3680 Reg < Memory: Z=0, C=0
3681 Reg = Memory: Z=1, C=1
3682 Reg > Memory: Z=0, C=1
3683 N is set according to the result of the subtraction operation
3684 Changes: NZC
3685
3686 NOTE -- CMP, CPX, CPY all share this same routine, so the desired
3687 register (A, X, or Y respectively) must be given when calling
3688 this macro... as well as the memory to compare it with. */
3689#define CMP(reg) \
3690 tw.W = reg - val; \
3691 ST = (ST & ~(N_FLAG|Z_FLAG|C_FLAG)) | (tw.B.h ? 0 : C_FLAG) | \
3692 NZTable[tw.B.l]
3693
3694/* DEC, DEX, DEY
3695 Decriments a value by one.
3696 Changes: value, NZ */
3697#define DEC(value) \
3698 value--; \
3699 UpdateNZ(value)
3700
3701/* EOR
3702 Combines a value with the accumulator using a bitwise exclusive-OR
3703 operation
3704 Changes: A, NZ */
3705#define EOR() \
3706 A ^= val; \
3707 UpdateNZ(A)
3708
3709/* INC, INX, INY
3710 Incriments a value by one.
3711 Changes: value, NZ */
3712#define INC(value) \
3713 value++; \
3714 UpdateNZ(value)
3715
3716/* LSR
3717 Shifts value one bit to the right. Bit that gets shifted out goes to
3718 the Carry flag.
3719 Changes: value, NZC */
3720#define LSR(value) \
3721 tw.W = value >> 1; \
3722 ST = (ST & ~(N_FLAG|Z_FLAG|C_FLAG)) | NZTable[tw.B.l] | \
3723 (value & 0x01); \
3724 value = tw.B.l
3725
3726/* ORA
3727 Combines a value with the accumulator using a bitwise inclusive-OR
3728 operation
3729 Changes: A, NZ */
3730#define ORA() \
3731 A |= val; \
3732 UpdateNZ(A)
3733
3734/* ROL
3735 Rotates a value one bit to the left:
3736 C <- 7<-6<-5<-4<-3<-2<-1<-0 <- C
3737 Changes: value, NZC */
3738#define ROL(value) \
3739 tw.W = (value << 1) | (ST & 0x01); \
3740 ST = (ST & ~(N_FLAG|Z_FLAG|C_FLAG)) | NZTable[tw.B.l] | tw.B.h; \
3741 value = tw.B.l
3742
3743/* ROR
3744 Rotates a value one bit to the right:
3745 C -> 7->6->5->4->3->2->1->0 -> C
3746 Changes: value, NZC */
3747#define ROR(value) \
3748 tw.W = (value >> 1) | (ST << 7); \
3749 ST = (ST & ~(N_FLAG|Z_FLAG|C_FLAG)) | NZTable[tw.B.l] | \
3750 (value & 0x01); \
3751 value = tw.B.l
3752
3753/* SBC
3754 Subtracts a value from the accumulator with borrow (inverted carry)
3755 Changes: A, NVZC
3756 - Decimal mode not supported on the NES
3757 - Due to a bug, NVZ flags are not altered if the Decimal flag is on
3758 --(taken out)-- */
3759#define SBC() \
3760 tw.W = A - val - ((ST & C_FLAG) ? 0 : 1); \
3761 ST = (ST & (I_FLAG|D_FLAG)) | (tw.B.h ? 0 : C_FLAG) | NZTable[tw.B.l] | \
3762 (((A ^ val) & (A ^ tw.B.l) & 0x80) ? V_FLAG : 0); \
3763 A = tw.B.l
3764
3765/* Undocumented Opcodes
3766 *
3767 * These opcodes are not included in the official specifications. However,
3768 * some of the unused opcode values perform operations which have since been
3769 * documented.
3770 */
3771
3772
3773/* ASO
3774 Left shifts a value, then ORs the result with the accumulator
3775 Changes: value, A, NZC */
3776#define ASO(value) \
3777 tw.W = value << 1; \
3778 A |= tw.B.l; \
3779 ST = (ST & ~(N_FLAG|Z_FLAG|C_FLAG)) | NZTable[A] | tw.B.h; \
3780 value = tw.B.l
3781
3782/* RLA
3783 Roll memory left 1 bit, then AND the result with the accumulator
3784 Changes: value, A, NZC */
3785#define RLA(value) \
3786 tw.W = (value << 1) | (ST & 0x01); \
3787 A &= tw.B.l; \
3788 ST = (ST & ~(N_FLAG|Z_FLAG|C_FLAG)) | NZTable[A] | tw.B.h; \
3789 value = tw.B.l
3790
3791/* LSE
3792 Right shifts a value one bit, then EORs the result with the accumulator
3793 Changes: value, A, NZC */
3794#define LSE(value) \
3795 tw.W = value >> 1; \
3796 A ^= tw.B.l; \
3797 ST = (ST & ~(N_FLAG|Z_FLAG|C_FLAG)) | NZTable[A] | (value & 0x01); \
3798 value = tw.B.l
3799
3800/* RRA
3801 Roll memory right one bit, then ADC the result
3802 Changes: value, A, NVZC */
3803#define RRA(value) \
3804 tw.W = (value >> 1) | (ST << 7); \
3805 ST = (ST & ~C_FLAG) | (value & 0x01); \
3806 value = tw.B.l; \
3807 ADC()
3808
3809/* AXS
3810 ANDs the contents of the X and A registers and stores the result
3811 int memory.
3812 Changes: value [DOES NOT CHANGE X, A, or any flags] */
3813#define AXS(value) \
3814 value = A & X
3815
3816/* DCM
3817 Decriments a value and compares it with the A register.
3818 Changes: value, NZC */
3819#define DCM(value) \
3820 value--; \
3821 CMP(A)
3822
3823/* INS
3824 Incriments a value then SBCs it
3825 Changes: value, A, NVZC */
3826#define INS(value) \
3827 value++; \
3828 SBC()
3829
3830/* AXA */
3831#define AXA(value) \
3832 value = A & X & (Rd(PC.W - 1) + 1)
3833
3834
3835/* The 6502 emulation function! */
3836
3837union TWIN front;
3838union TWIN final;
3839uint8_t val;
3840uint8_t op;
3841
3842uint32_t Emulate6502(uint32_t runto)
3843{
3844 /* If the CPU is jammed... don't bother */
3845 if(bCPUJammed == 1)
3846 return 0;
3847
3848 register union TWIN tw; /* used in calculations */
3849 register uint8_t ST = regP;
3850 register union TWIN PC;
3851 uint8_t SP = regSP;
3852 register uint8_t A = regA;
3853 register uint8_t X = regX;
3854 register uint8_t Y = regY;
3855 union TWIN front;
3856 union TWIN final;
3857 PC.W = regPC;
3858
3859 uint32_t ret = nCPUCycle;
3860
3861 ENTER_TIMER(cpu);
3862
3863 /* Start the loop */
3864
3865 while(nCPUCycle < runto)
3866 {
3867 op = Rd(PC.W);
3868 PC.W++;
3869
3870 nCPUCycle += CPU_Cycles[op];
3871 switch(op)
3872 {
3873 /* Documented Opcodes first */
3874
3875 /* Flag setting/clearing */
3876 case 0x18: ST &= ~C_FLAG; break; /* CLC */
3877 case 0x38: ST |= C_FLAG; break; /* SEC */
3878 case 0x58: ST &= ~I_FLAG; break; /* CLI */
3879 case 0x78: ST |= I_FLAG; break; /* SEI */
3880 case 0xB8: ST &= ~V_FLAG; break; /* CLV */
3881 case 0xD8: ST &= ~D_FLAG; break; /* CLD */
3882 case 0xF8: ST |= D_FLAG; break; /* SED */
3883
3884 /* Branch commands */
3885 case 0x10: RelJmp(!(ST & N_FLAG)); break; /* BPL */
3886 case 0x30: RelJmp( (ST & N_FLAG)); break; /* BMI */
3887 case 0x50: RelJmp(!(ST & V_FLAG)); break; /* BVC */
3888 case 0x70: RelJmp( (ST & V_FLAG)); break; /* BVS */
3889 case 0x90: RelJmp(!(ST & C_FLAG)); break; /* BCC */
3890 case 0xB0: RelJmp( (ST & C_FLAG)); break; /* BCS */
3891 case 0xD0: RelJmp(!(ST & Z_FLAG)); break; /* BNE */
3892 case 0xF0: RelJmp( (ST & Z_FLAG)); break; /* BEQ */
3893
3894 /* Direct stack alteration commands (push/pull commands) */
3895 case 0x08: PUSH(ST | R_FLAG | B_FLAG); break; /* PHP */
3896 case 0x28: PULL(ST); break; /* PLP */
3897 case 0x48: PUSH(A); break; /* PHA */
3898 case 0x68: PULL(A); UpdateNZ(A); break; /* PLA */
3899
3900 /* Register Transfers */
3901 case 0x8A: A = X; UpdateNZ(A); break; /* TXA */
3902 case 0x98: A = Y; UpdateNZ(A); break; /* TYA */
3903 case 0x9A: SP = X; break; /* TXS */
3904 case 0xA8: Y = A; UpdateNZ(A); break; /* TAY */
3905 case 0xAA: X = A; UpdateNZ(A); break; /* TAX */
3906 case 0xBA: X = SP; UpdateNZ(X); break; /* TSX */
3907
3908 /* Other commands */
3909
3910 /* ADC */
3911 case 0x61: Ad_VlIx(); ADC(); break;
3912 case 0x65: Ad_VlZp(); ADC(); break;
3913 case 0x69: Ad_VlIm(); ADC(); break;
3914 case 0x6D: Ad_VlAb(); ADC(); break;
3915 case 0x71: Ad_VlIy(); ADC(); break;
3916 case 0x75: Ad_VlZx(); ADC(); break;
3917 case 0x79: Ad_VlAy(); ADC(); break;
3918 case 0x7D: Ad_VlAx(); ADC(); break;
3919
3920 /* AND */
3921 case 0x21: Ad_VlIx(); AND(); break;
3922 case 0x25: Ad_VlZp(); AND(); break;
3923 case 0x29: Ad_VlIm(); AND(); break;
3924 case 0x2D: Ad_VlAb(); AND(); break;
3925 case 0x31: Ad_VlIy(); AND(); break;
3926 case 0x35: Ad_VlZx(); AND(); break;
3927 case 0x39: Ad_VlAy(); AND(); break;
3928 case 0x3D: Ad_VlAx(); AND(); break;
3929
3930 /* ASL */
3931 case 0x0A: ASL(A); break;
3932 case 0x06: MRW_Zp(ASL); break;
3933 case 0x0E: MRW_Ab(ASL); break;
3934 case 0x16: MRW_Zx(ASL); break;
3935 case 0x1E: MRW_Ax(ASL); break;
3936
3937 /* BIT */
3938 case 0x24: Ad_VlZp(); BIT(); break;
3939 case 0x2C: Ad_VlAb(); BIT(); break;
3940
3941 /* BRK */
3942 case 0x00:
3943 if(bIgnoreBRK)
3944 break;
3945 PC.W++; /*BRK has a padding byte*/
3946 PUSH(PC.B.h); /*push high byte of the return address*/
3947 PUSH(PC.B.l); /*push low byte of return address*/
3948 PUSH(ST | R_FLAG | B_FLAG); /*push processor status with R|B flags*/
3949 ST |= I_FLAG; /*mask interrupts*/
3950 PC.W = RdWord(0xFFFE); /*read the IRQ vector and jump to it*/
3951
3952 /* extra check to make sure we didn't hit an infinite BRK loop */
3953 if(!Rd(PC.W)) /* next command will be BRK */
3954 {
3955 /* the CPU will endlessly loop...
3956 just jam it to ease processing power */
3957 bCPUJammed = 1;
3958 goto jammed;
3959 }
3960 break;
3961
3962 /* CMP */
3963 case 0xC1: Ad_VlIx(); CMP(A); break;
3964 case 0xC5: Ad_VlZp(); CMP(A); break;
3965 case 0xC9: Ad_VlIm(); CMP(A); break;
3966 case 0xCD: Ad_VlAb(); CMP(A); break;
3967 case 0xD1: Ad_VlIy(); CMP(A); break;
3968 case 0xD5: Ad_VlZx(); CMP(A); break;
3969 case 0xD9: Ad_VlAy(); CMP(A); break;
3970 case 0xDD: Ad_VlAx(); CMP(A); break;
3971
3972 /* CPX */
3973 case 0xE0: Ad_VlIm(); CMP(X); break;
3974 case 0xE4: Ad_VlZp(); CMP(X); break;
3975 case 0xEC: Ad_VlAb(); CMP(X); break;
3976
3977 /* CPY */
3978 case 0xC0: Ad_VlIm(); CMP(Y); break;
3979 case 0xC4: Ad_VlZp(); CMP(Y); break;
3980 case 0xCC: Ad_VlAb(); CMP(Y); break;
3981
3982 /* DEC */
3983 case 0xCA: DEC(X); break; /* DEX */
3984 case 0x88: DEC(Y); break; /* DEY */
3985 case 0xC6: MRW_Zp(DEC); break;
3986 case 0xCE: MRW_Ab(DEC); break;
3987 case 0xD6: MRW_Zx(DEC); break;
3988 case 0xDE: MRW_Ax(DEC); break;
3989
3990 /* EOR */
3991 case 0x41: Ad_VlIx(); EOR(); break;
3992 case 0x45: Ad_VlZp(); EOR(); break;
3993 case 0x49: Ad_VlIm(); EOR(); break;
3994 case 0x4D: Ad_VlAb(); EOR(); break;
3995 case 0x51: Ad_VlIy(); EOR(); break;
3996 case 0x55: Ad_VlZx(); EOR(); break;
3997 case 0x59: Ad_VlAy(); EOR(); break;
3998 case 0x5D: Ad_VlAx(); EOR(); break;
3999
4000 /* INC */
4001 case 0xE8: INC(X); break; /* INX */
4002 case 0xC8: INC(Y); break; /* INY */
4003 case 0xE6: MRW_Zp(INC); break;
4004 case 0xEE: MRW_Ab(INC); break;
4005 case 0xF6: MRW_Zx(INC); break;
4006 case 0xFE: MRW_Ax(INC); break;
4007
4008 /* JMP */
4009 /* Absolute JMP */
4010 case 0x4C: final.W = RdWord(PC.W); PC.W = final.W; val = 0; break;
4011 /* Indirect JMP -- must take caution:
4012 Indirection at 01FF will read from 01FF and 0100 (not 0200) */
4013 case 0x6C: front.W = final.W = RdWord(PC.W);
4014 PC.B.l = Rd(final.W); final.B.l++;
4015 PC.B.h = Rd(final.W); final.W = PC.W;
4016 break;
4017 /* JSR */
4018 case 0x20:
4019 val = 0;
4020 final.W = RdWord(PC.W);
4021 PC.W++; /* JSR only increments the return address by one.
4022 It's incremented again upon RTS */
4023 PUSH(PC.B.h); /* push high byte of return address */
4024 PUSH(PC.B.l); /* push low byte of return address */
4025 PC.W = final.W;
4026 break;
4027
4028 /* LDA */
4029 case 0xA1: Ad_VlIx(); A = val; UpdateNZ(A); break;
4030 case 0xA5: Ad_VlZp(); A = val; UpdateNZ(A); break;
4031 case 0xA9: Ad_VlIm(); A = val; UpdateNZ(A); break;
4032 case 0xAD: Ad_VlAb(); A = val; UpdateNZ(A); break;
4033 case 0xB1: Ad_VlIy(); A = val; UpdateNZ(A); break;
4034 case 0xB5: Ad_VlZx(); A = val; UpdateNZ(A); break;
4035 case 0xB9: Ad_VlAy(); A = val; UpdateNZ(A); break;
4036 case 0xBD: Ad_VlAx(); A = val; UpdateNZ(A); break;
4037
4038 /* LDX */
4039 case 0xA2: Ad_VlIm(); X = val; UpdateNZ(X); break;
4040 case 0xA6: Ad_VlZp(); X = val; UpdateNZ(X); break;
4041 case 0xAE: Ad_VlAb(); X = val; UpdateNZ(X); break;
4042 case 0xB6: Ad_VlZy(); X = val; UpdateNZ(X); break;
4043 case 0xBE: Ad_VlAy(); X = val; UpdateNZ(X); break;
4044
4045 /* LDY */
4046 case 0xA0: Ad_VlIm(); Y = val; UpdateNZ(Y); break;
4047 case 0xA4: Ad_VlZp(); Y = val; UpdateNZ(Y); break;
4048 case 0xAC: Ad_VlAb(); Y = val; UpdateNZ(Y); break;
4049 case 0xB4: Ad_VlZx(); Y = val; UpdateNZ(Y); break;
4050 case 0xBC: Ad_VlAx(); Y = val; UpdateNZ(Y); break;
4051
4052 /* LSR */
4053 case 0x4A: LSR(A); break;
4054 case 0x46: MRW_Zp(LSR); break;
4055 case 0x4E: MRW_Ab(LSR); break;
4056 case 0x56: MRW_Zx(LSR); break;
4057 case 0x5E: MRW_Ax(LSR); break;
4058
4059 /* NOP */
4060 case 0xEA:
4061
4062 /* --- Undocumented ---
4063 These opcodes perform the same action as NOP */
4064 case 0x1A: case 0x3A: case 0x5A:
4065 case 0x7A: case 0xDA: case 0xFA: break;
4066
4067 /* ORA */
4068 case 0x01: Ad_VlIx(); ORA(); break;
4069 case 0x05: Ad_VlZp(); ORA(); break;
4070 case 0x09: Ad_VlIm(); ORA(); break;
4071 case 0x0D: Ad_VlAb(); ORA(); break;
4072 case 0x11: Ad_VlIy(); ORA(); break;
4073 case 0x15: Ad_VlZx(); ORA(); break;
4074 case 0x19: Ad_VlAy(); ORA(); break;
4075 case 0x1D: Ad_VlAx(); ORA(); break;
4076
4077 /* ROL */
4078 case 0x2A: ROL(A); break;
4079 case 0x26: MRW_Zp(ROL); break;
4080 case 0x2E: MRW_Ab(ROL); break;
4081 case 0x36: MRW_Zx(ROL); break;
4082 case 0x3E: MRW_Ax(ROL); break;
4083
4084 /* ROR */
4085 case 0x6A: ROR(A); break;
4086 case 0x66: MRW_Zp(ROR); break;
4087 case 0x6E: MRW_Ab(ROR); break;
4088 case 0x76: MRW_Zx(ROR); break;
4089 case 0x7E: MRW_Ax(ROR); break;
4090
4091 /* RTI */
4092 case 0x40:
4093 PULL(ST); /*pull processor status*/
4094 PULL(PC.B.l); /*pull low byte of return address*/
4095 PULL(PC.B.h); /*pull high byte of return address*/
4096 break;
4097
4098 /* RTS */
4099 case 0x60:
4100 PULL(PC.B.l);
4101 PULL(PC.B.h);
4102 PC.W++; /* the return address is one less of what it needs */
4103 break;
4104
4105 /* SBC */
4106 case 0xE1: Ad_VlIx(); SBC(); break;
4107 case 0xE5: Ad_VlZp(); SBC(); break;
4108 /* - Undocumented - EB performs the same operation as SBC immediate */
4109 case 0xEB:
4110 case 0xE9: Ad_VlIm(); SBC(); break;
4111 case 0xED: Ad_VlAb(); SBC(); break;
4112 case 0xF1: Ad_VlIy(); SBC(); break;
4113 case 0xF5: Ad_VlZx(); SBC(); break;
4114 case 0xF9: Ad_VlAy(); SBC(); break;
4115 case 0xFD: Ad_VlAx(); SBC(); break;
4116
4117 /* STA */
4118 case 0x81: Ad_AdIx(); val = A; Wr(final.W,A); break;
4119 case 0x85: Ad_AdZp(); val = A; WrZ(final.W,A); break;
4120 case 0x8D: Ad_AdAb(); val = A; Wr(final.W,A); break;
4121 case 0x91: Ad_AdIy(); val = A; Wr(final.W,A); break;
4122 case 0x95: Ad_AdZx(); val = A; WrZ(final.W,A); break;
4123 case 0x99: Ad_AdAy(); val = A; Wr(final.W,A); break;
4124 case 0x9D: Ad_AdAx(); val = A; Wr(final.W,A); break;
4125
4126 /* STX */
4127 case 0x86: Ad_AdZp(); val = X; WrZ(final.W,X); break;
4128 case 0x8E: Ad_AdAb(); val = X; Wr(final.W,X); break;
4129 case 0x96: Ad_AdZy(); val = X; WrZ(final.W,X); break;
4130
4131 /* STY */
4132 case 0x84: Ad_AdZp(); val = Y; WrZ(final.W,Y); break;
4133 case 0x8C: Ad_AdAb(); val = Y; Wr(final.W,Y); break;
4134 case 0x94: Ad_AdZx(); val = Y; WrZ(final.W,Y); break;
4135
4136 /* Undocumented Opcodes */
4137 /* ASO */
4138 case 0x03: if(bIgnoreIllegalOps) break; MRW_Ix(ASO); break;
4139 case 0x07: if(bIgnoreIllegalOps) break; MRW_Zp(ASO); break;
4140 case 0x0F: if(bIgnoreIllegalOps) break; MRW_Ab(ASO); break;
4141 case 0x13: if(bIgnoreIllegalOps) break; MRW_Iy(ASO); break;
4142 case 0x17: if(bIgnoreIllegalOps) break; MRW_Zx(ASO); break;
4143 case 0x1B: if(bIgnoreIllegalOps) break; MRW_Ay(ASO); break;
4144 case 0x1F: if(bIgnoreIllegalOps) break; MRW_Ax(ASO); break;
4145
4146 /* RLA */
4147 case 0x23: if(bIgnoreIllegalOps) break; MRW_Ix(RLA); break;
4148 case 0x27: if(bIgnoreIllegalOps) break; MRW_Zp(RLA); break;
4149 case 0x2F: if(bIgnoreIllegalOps) break; MRW_Ab(RLA); break;
4150 case 0x33: if(bIgnoreIllegalOps) break; MRW_Iy(RLA); break;
4151 case 0x37: if(bIgnoreIllegalOps) break; MRW_Zx(RLA); break;
4152 case 0x3B: if(bIgnoreIllegalOps) break; MRW_Ay(RLA); break;
4153 case 0x3F: if(bIgnoreIllegalOps) break; MRW_Ax(RLA); break;
4154
4155 /* LSE */
4156 case 0x43: if(bIgnoreIllegalOps) break; MRW_Ix(LSE); break;
4157 case 0x47: if(bIgnoreIllegalOps) break; MRW_Zp(LSE); break;
4158 case 0x4F: if(bIgnoreIllegalOps) break; MRW_Ab(LSE); break;
4159 case 0x53: if(bIgnoreIllegalOps) break; MRW_Iy(LSE); break;
4160 case 0x57: if(bIgnoreIllegalOps) break; MRW_Zx(LSE); break;
4161 case 0x5B: if(bIgnoreIllegalOps) break; MRW_Ay(LSE); break;
4162 case 0x5F: if(bIgnoreIllegalOps) break; MRW_Ax(LSE); break;
4163
4164 /* RRA */
4165 case 0x63: if(bIgnoreIllegalOps) break; MRW_Ix(RRA); break;
4166 case 0x67: if(bIgnoreIllegalOps) break; MRW_Zp(RRA); break;
4167 case 0x6F: if(bIgnoreIllegalOps) break; MRW_Ab(RRA); break;
4168 case 0x73: if(bIgnoreIllegalOps) break; MRW_Iy(RRA); break;
4169 case 0x77: if(bIgnoreIllegalOps) break; MRW_Zx(RRA); break;
4170 case 0x7B: if(bIgnoreIllegalOps) break; MRW_Ay(RRA); break;
4171 case 0x7F: if(bIgnoreIllegalOps) break; MRW_Ax(RRA); break;
4172
4173 /* AXS */
4174 case 0x83: if(bIgnoreIllegalOps) break; MRW_Ix(AXS); break;
4175 case 0x87: if(bIgnoreIllegalOps) break; MRW_Zp(AXS); break;
4176 case 0x8F: if(bIgnoreIllegalOps) break; MRW_Ab(AXS); break;
4177 case 0x97: if(bIgnoreIllegalOps) break; MRW_Zy(AXS); break;
4178
4179 /* LAX */
4180 case 0xA3: if(bIgnoreIllegalOps) break;
4181 Ad_VlIx(); X = A = val; UpdateNZ(A); break;
4182 case 0xA7: if(bIgnoreIllegalOps) break;
4183 Ad_VlZp(); X = A = val; UpdateNZ(A); break;
4184 case 0xAF: if(bIgnoreIllegalOps) break;
4185 Ad_VlAb(); X = A = val; UpdateNZ(A); break;
4186 case 0xB3: if(bIgnoreIllegalOps) break;
4187 Ad_VlIy(); X = A = val; UpdateNZ(A); break;
4188 case 0xB7: if(bIgnoreIllegalOps) break;
4189 Ad_VlZy(); X = A = val; UpdateNZ(A); break;
4190 case 0xBF: if(bIgnoreIllegalOps) break;
4191 Ad_VlAy(); X = A = val; UpdateNZ(A); break;
4192
4193 /* DCM */
4194 case 0xC3: if(bIgnoreIllegalOps) break; MRW_Ix(DCM); break;
4195 case 0xC7: if(bIgnoreIllegalOps) break; MRW_Zp(DCM); break;
4196 case 0xCF: if(bIgnoreIllegalOps) break; MRW_Ab(DCM); break;
4197 case 0xD3: if(bIgnoreIllegalOps) break; MRW_Iy(DCM); break;
4198 case 0xD7: if(bIgnoreIllegalOps) break; MRW_Zx(DCM); break;
4199 case 0xDB: if(bIgnoreIllegalOps) break; MRW_Ay(DCM); break;
4200 case 0xDF: if(bIgnoreIllegalOps) break; MRW_Ax(DCM); break;
4201
4202 /* INS */
4203 case 0xE3: if(bIgnoreIllegalOps) break; MRW_Ix(INS); break;
4204 case 0xE7: if(bIgnoreIllegalOps) break; MRW_Zp(INS); break;
4205 case 0xEF: if(bIgnoreIllegalOps) break; MRW_Ab(INS); break;
4206 case 0xF3: if(bIgnoreIllegalOps) break; MRW_Iy(INS); break;
4207 case 0xF7: if(bIgnoreIllegalOps) break; MRW_Zx(INS); break;
4208 case 0xFB: if(bIgnoreIllegalOps) break; MRW_Ay(INS); break;
4209 case 0xFF: if(bIgnoreIllegalOps) break; MRW_Ax(INS); break;
4210
4211 /* ALR
4212 AND Accumulator with memory and LSR the result */
4213 case 0x4B: if(bIgnoreIllegalOps) break;
4214 Ad_VlIm(); A &= val; LSR(A); break;
4215
4216 /* ARR
4217 ANDs memory with the Accumulator and RORs the result */
4218 case 0x6B: if(bIgnoreIllegalOps) break;
4219 Ad_VlIm(); A &= val; ROR(A); break;
4220
4221 /* XAA
4222 Transfers X -> A, then ANDs A with memory */
4223 case 0x8B: if(bIgnoreIllegalOps) break;
4224 Ad_VlIm(); A = X & val; UpdateNZ(A); break;
4225
4226 /* OAL
4227 OR the Accumulator with #EE, AND Accumulator with Memory,
4228 Transfer A -> X */
4229 case 0xAB: if(bIgnoreIllegalOps) break;
4230 Ad_VlIm(); X = (A &= (val | 0xEE));
4231 UpdateNZ(A); break;
4232
4233 /* SAX
4234 ANDs A and X registers (does not change A), subtracts memory
4235 from result (CMP style, not SBC style) result is stored in X */
4236 case 0xCB: if(bIgnoreIllegalOps) break;
4237 Ad_VlIm(); tw.W = (X & A) - val; X = tw.B.l;
4238 ST = (ST & ~(N_FLAG|Z_FLAG|C_FLAG)) | NZTable[X] |
4239 (tw.B.h ? C_FLAG : 0); break;
4240 /* SKB
4241 Skip Byte... or DOP - Double No-Op
4242 These bytes do nothing, but take a parameter (which can be
4243 ignored) */
4244 case 0x04: case 0x14: case 0x34: case 0x44: case 0x54: case 0x64:
4245 case 0x80: case 0x82: case 0x89: case 0xC2: case 0xD4: case 0xE2:
4246 case 0xF4:
4247 if(bIgnoreIllegalOps) break;
4248 PC.W++; /* skip unused byte */
4249 break;
4250
4251 /* SKW
4252 Swip Word... or TOP - Tripple No-Op
4253 These bytes are the same as SKB, only they take a 2 byte parameter.
4254 This can be ignored in some cases, but the read needs to be
4255 performed in a some cases because an extra clock cycle may be used
4256 in the process */
4257 /* Absolute address... no need for operator */
4258 case 0x0C:
4259 if(bIgnoreIllegalOps) break;
4260 PC.W += 2; break;
4261 /* Absolute X address... may cross page, have to perform the read */
4262 case 0x1C: case 0x3C: case 0x5C: case 0x7C: case 0xDC: case 0xFC:
4263 if(bIgnoreIllegalOps) break;
4264 Ad_VlAx(); break;
4265
4266 /* HLT / JAM
4267 Jams up CPU operation */
4268 case 0x02: case 0x12: case 0x22: case 0x32: case 0x42: case 0x52:
4269 case 0x62: case 0x72: case 0x92: case 0xB2: case 0xD2: case 0xF2:
4270 /*it's not -really- jammed... only the NSF code has ended*/
4271 if(PC.W == 0x5004) bCPUJammed = 2;
4272 else
4273 {
4274 if(bIgnoreIllegalOps) break;
4275 bCPUJammed = 1;
4276 }
4277 goto jammed;
4278
4279 /* TAS */
4280 case 0x9B:
4281 if(bIgnoreIllegalOps) break;
4282 Ad_AdAy();
4283 SP = A & X & (Rd(PC.W - 1) + 1);
4284 Wr(final.W,SP);
4285 break;
4286
4287 /* SAY */
4288 case 0x9C:
4289 if(bIgnoreIllegalOps) break;
4290 Ad_AdAx();
4291 Y &= (Rd(PC.W - 1) + 1);
4292 Wr(final.W,Y);
4293 break;
4294
4295 /* XAS */
4296 case 0x9E:
4297 if(bIgnoreIllegalOps) break;
4298 Ad_AdAy();
4299 X &= (Rd(PC.W - 1) + 1);
4300 Wr(final.W,X);
4301 break;
4302
4303 /* AXA */
4304 case 0x93: if(bIgnoreIllegalOps) break; MRW_Iy(AXA); break;
4305 case 0x9F: if(bIgnoreIllegalOps) break; MRW_Ay(AXA); break;
4306
4307 /* ANC */
4308 case 0x0B: case 0x2B:
4309 if(bIgnoreIllegalOps) break;
4310 Ad_VlIm();
4311 A &= val;
4312 ST = (ST & ~(N_FLAG|Z_FLAG|C_FLAG)) |
4313 NZTable[A] | ((A & 0x80) ? C_FLAG : 0);
4314 break;
4315
4316 /* LAS */
4317 case 0xBB:
4318 if(bIgnoreIllegalOps) break;
4319 Ad_VlAy();
4320 X = A = (SP &= val);
4321 UpdateNZ(A);
4322 break;
4323 }
4324 }
4325
4326jammed:
4327 regPC = PC.W;
4328 regA = A;
4329 regX = X;
4330 regY = Y;
4331 regSP = SP;
4332 regP = ST;
4333
4334 EXIT_TIMER(cpu);
4335
4336 return (nCPUCycle - ret);
4337}
4338
4339/****************** rockbox interface ******************/
4340
4341void set_codec_track(int t, int d) {
4342 int track,fade,def=0;
4343 SetTrack(t);
4344
4345 /* for REPEAT_ONE we disable track limits */
4346 if (ci->global_settings->repeat_mode!=REPEAT_ONE) {
4347 if (!bIsExtended || nTrackTime[t]==-1) {track=60*2*1000; def=1;}
4348 else track=nTrackTime[t];
4349 if (!bIsExtended || nTrackFade[t]==-1) fade=5*1000;
4350 else fade=nTrackFade[t];
4351 nSilenceTrackMS=5000;
4352 SetFadeTime(track,track+fade, fNSFPlaybackSpeed,def);
4353 }
4354 ci->id3->elapsed=d*1000; /* d is track no to display */
4355}
4356
4357/* this is the codec entry point */
4358enum codec_status codec_main(void)
4359{
4360 int written;
4361 uint8_t *buf;
4362 size_t n;
4363 int endofstream; /* end of stream flag */
4364 int track;
4365 int dontresettrack;
4366 char last_path[MAX_PATH];
4367 int usingplaylist;
4368
4369 /* we only render 16 bits */
4370 ci->configure(DSP_SET_SAMPLE_DEPTH, (long *)16);
4371
4372 ci->configure(DSP_SET_FREQUENCY, (long*)44100);
4373 ci->configure(DSP_SET_STEREO_MODE, (long *)STEREO_MONO);
4374
4375 RebuildOutputTables();
4376
4377 dontresettrack=0;
4378 last_path[0]='\0';
4379 track=0;
4380
4381next_track:
4382 usingplaylist=0;
4383 DEBUGF("NSF: next_track\n");
4384 if (codec_init()) {
4385 return CODEC_ERROR;
4386 }
4387 DEBUGF("NSF: after init\n");
4388
4389
4390 /* wait for track info to load */
4391 while (!*ci->taginfo_ready && !ci->stop_codec)
4392 ci->sleep(1);
4393
4394 /* Read the entire file */
4395 DEBUGF("NSF: request file\n");
4396 ci->seek_buffer(0);
4397 buf = ci->request_buffer(&n, ci->filesize);
4398 if (!buf || n < (size_t)ci->filesize) {
4399 DEBUGF("NSF: file load failed\n");
4400 return CODEC_ERROR;
4401 }
4402
4403init_nsf:
4404 if(!NSFCore_Initialize()) {
4405 DEBUGF("NSF: NSFCore_Initialize failed\n"); return CODEC_ERROR;}
4406
4407 if(LoadFile(buf,ci->filesize)) {
4408 DEBUGF("NSF: LoadFile failed\n"); return CODEC_ERROR;}
4409 if(!SetPlaybackOptions(44100)) {
4410 DEBUGF("NSF: SetPlaybackOptions failed\n"); return CODEC_ERROR;}
4411 if(!LoadNSF(nDataBufferSize)) {
4412 DEBUGF("NSF: LoadNSF failed\n"); return CODEC_ERROR;}
4413
4414 ci->id3->title=szGameTitle;
4415 ci->id3->artist=szArtist;
4416 ci->id3->album=szCopyright;
4417 if (usingplaylist) {
4418 ci->id3->length=nPlaylistSize*1000;
4419 } else {
4420 ci->id3->length=nTrackCount*1000;
4421 }
4422
4423 if (!dontresettrack||strcmp(ci->id3->path,last_path)) {
4424 /* if this is the first time we're seeing this file, or if we haven't
4425 been asked to preserve the track number, default to the proper
4426 initial track */
4427 if (bIsExtended &&
4428 ci->global_settings->repeat_mode!=REPEAT_ONE && nPlaylistSize>0) {
4429 /* decide to use the playlist */
4430 usingplaylist=1;
4431 track=0;
4432 set_codec_track(nPlaylist[0],0);
4433 } else {
4434 /* simply use the initial track */
4435 track=nInitialTrack;
4436 set_codec_track(track,track);
4437 }
4438 } else {
4439 /* if we've already been running this file assume track is set
4440 already */
4441 if (usingplaylist) set_codec_track(nPlaylist[track],track);
4442 else set_codec_track(track,track);
4443 }
4444 strcpy(last_path,ci->id3->path);
4445
4446 /* The main decoder loop */
4447
4448 endofstream = 0;
4449
4450 reset_profile_timers();
4451
4452 while (!endofstream) {
4453
4454 ci->yield();
4455 if (ci->stop_codec || ci->new_track) {
4456 break;
4457 }
4458
4459 if (ci->seek_time >0) {
4460 track=ci->seek_time/1000;
4461 if (usingplaylist) {
4462 if (track>=nPlaylistSize) break;
4463 } else {
4464 if (track>=nTrackCount) break;
4465 }
4466 ci->seek_complete();
4467 dontresettrack=1;
4468 goto init_nsf;
4469 }
4470
4471 ENTER_TIMER(total);
4472 written=GetSamples((uint8_t*)samples,WAV_CHUNK_SIZE/2);
4473 EXIT_TIMER(total);
4474
4475 if (!written || SongCompleted()) {
4476 print_timers(last_path,track);
4477 reset_profile_timers();
4478
4479 track++;
4480 if (usingplaylist) {
4481 if (track>=nPlaylistSize) break;
4482 } else {
4483 if (track>=nTrackCount) break;
4484 }
4485 dontresettrack=1;
4486 goto init_nsf;
4487 }
4488
4489 while (!ci->pcmbuf_insert((char *)samples, written))
4490 ci->yield();
4491
4492 }
4493
4494 print_timers(last_path,track);
4495
4496 if (ci->request_next_track()) {
4497 if (ci->global_settings->repeat_mode==REPEAT_ONE) {
4498 /* in repeat one mode just advance to the next track */
4499 track++;
4500 if (track>=nTrackCount) track=0;
4501 dontresettrack=1;
4502 /* at this point we can't tell if another file has been selected */
4503 goto next_track;
4504 } else {
4505 /* otherwise do a proper load of the next file */
4506 dontresettrack=0;
4507 last_path[0]='\0';
4508 }
4509 goto next_track; /* when we fall through here we'll reload the file */
4510 }
4511
4512 return CODEC_OK;
4513}
diff --git a/apps/metadata.c b/apps/metadata.c
index acd8de38e3..d02e81a014 100644
--- a/apps/metadata.c
+++ b/apps/metadata.c
@@ -2012,6 +2012,17 @@ bool get_metadata(struct track_info* track, int fd, const char* trackname,
2012 } 2012 }
2013 2013
2014 break; 2014 break;
2015 case AFMT_NSF:
2016 buf = track->id3.path;
2017 if ((lseek(fd, 0, SEEK_SET) < 0) || ((read(fd, buf, 8)) < 8))
2018 {
2019 DEBUGF("lseek or read failed\n");
2020 return false;
2021 }
2022 track->id3.vbr = false;
2023 track->id3.filesize = filesize(fd);
2024 if (memcmp(buf,"NESM",4) && memcmp(buf,"NSFE",4)) return false;
2025 break;
2015 2026
2016 case AFMT_AIFF: 2027 case AFMT_AIFF:
2017 if (!get_aiff_metadata(fd, &(track->id3))) 2028 if (!get_aiff_metadata(fd, &(track->id3)))
diff --git a/apps/tree.c b/apps/tree.c
index edd238a3b0..7869696514 100644
--- a/apps/tree.c
+++ b/apps/tree.c
@@ -108,6 +108,8 @@ const struct filetype filetypes[] = {
108 { "aiff",TREE_ATTR_MPA, Icon_Audio, VOICE_EXT_MPA }, 108 { "aiff",TREE_ATTR_MPA, Icon_Audio, VOICE_EXT_MPA },
109 { "sid", TREE_ATTR_MPA, Icon_Audio, VOICE_EXT_MPA }, 109 { "sid", TREE_ATTR_MPA, Icon_Audio, VOICE_EXT_MPA },
110 { "adx", TREE_ATTR_MPA, Icon_Audio, VOICE_EXT_MPA }, 110 { "adx", TREE_ATTR_MPA, Icon_Audio, VOICE_EXT_MPA },
111 { "nsf", TREE_ATTR_MPA, Icon_Audio, VOICE_EXT_MPA },
112 { "nsfe", TREE_ATTR_MPA, Icon_Audio, VOICE_EXT_MPA },
111#endif 113#endif
112 { "m3u", TREE_ATTR_M3U, Icon_Playlist, LANG_PLAYLIST }, 114 { "m3u", TREE_ATTR_M3U, Icon_Playlist, LANG_PLAYLIST },
113 { "m3u8", TREE_ATTR_M3U, Icon_Playlist, LANG_PLAYLIST }, 115 { "m3u8", TREE_ATTR_M3U, Icon_Playlist, LANG_PLAYLIST },