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