Index: apps/codecs.c
===================================================================
--- apps/codecs.c	(revision 29484)
+++ apps/codecs.c	(working copy)
@@ -70,7 +70,7 @@
 
 extern void* plugin_get_audio_buffer(size_t *buffer_size);
 
-#if (CONFIG_PLATFORM & PLATFORM_NATIVE) && defined(HAVE_RECORDING)
+#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
 #undef open
 static int open(const char* pathname, int flags, ...)
 {
@@ -154,6 +154,7 @@
     enc_finish_chunk,
     enc_get_pcm_data,
     enc_unget_pcm_data,
+#endif /* HAVE_RECORDING */
 
     /* file */
     (open_func)PREFIX(open),
@@ -163,10 +164,11 @@
     (write_func)PREFIX(write),
     round_value_to_list32,
 
-#endif /* HAVE_RECORDING */
-
     /* new stuff at the end, sort into place next time
        the API gets incompatible */
+    strlcpy,
+    strrchr,
+    strcasecmp,
 };
 
 void codec_get_full_path(char *path, const char *codec_root_fn)
Index: apps/codecs.h
===================================================================
--- apps/codecs.h	(revision 29484)
+++ apps/codecs.h	(working copy)
@@ -213,6 +213,7 @@
     void            (*enc_finish_chunk)(void);
     unsigned char * (*enc_get_pcm_data)(size_t size);
     size_t          (*enc_unget_pcm_data)(size_t size);
+#endif
 
     /* file */
     int (*open)(const char* pathname, int flags, ...);
@@ -224,10 +225,12 @@
                                  const unsigned long list[],
                                  int count,
                                  bool signd);
-#endif
 
     /* new stuff at the end, sort into place next time
        the API gets incompatible */
+    size_t (*strlcpy)(char *dst, const char *src, size_t length);
+    char * (*strrchr)(const char *s, int c);
+    int (*strcasecmp)(const char *, const char *);
 };
 
 /* codec header */
Index: apps/codecs/libnsf/nes_vrc6_apu.h
===================================================================
--- apps/codecs/libnsf/nes_vrc6_apu.h	(revision 0)
+++ apps/codecs/libnsf/nes_vrc6_apu.h	(revision 0)
@@ -0,0 +1,62 @@
+// Konami VRC6 sound chip emulator
+
+// Nes_Snd_Emu 0.1.8
+#ifndef NES_VRC6_APU_H
+#define NES_VRC6_APU_H
+
+#include "blargg_common.h"
+#include "blip_buffer.h"
+
+enum { vrc6_osc_count = 3 };
+enum { vrc6_reg_count = 3 };
+enum { vrc6_base_addr = 0x9000 };
+enum { vrc6_addr_step = 0x1000 };
+
+struct Vrc6_Osc
+{
+	uint8_t regs [vrc6_reg_count];
+	struct Blip_Buffer* output;
+	int delay;
+	int last_amp;
+	int phase;
+	int amp; // only used by saw
+};
+
+static inline int Vrc6_osc_period( struct Vrc6_Osc* this )
+{
+	return (this->regs [2] & 0x0F) * 0x100 + this->regs [1] + 1;
+}
+
+struct Nes_Vrc6_Apu {
+	struct Vrc6_Osc oscs [vrc6_osc_count];
+	blip_time_t last_time;
+	
+	struct Blip_Synth saw_synth;
+	struct Blip_Synth square_synth;
+};
+
+// See Nes_Apu.h for reference
+void Vrc6_init( struct Nes_Vrc6_Apu* this );
+void Vrc6_reset( struct Nes_Vrc6_Apu* this );
+void Vrc6_output( struct Nes_Vrc6_Apu* this, struct Blip_Buffer* );
+void Vrc6_end_frame( struct Nes_Vrc6_Apu* this, blip_time_t ); ICODE_ATTR
+	
+// Oscillator 0 write-only registers are at $9000-$9002
+// Oscillator 1 write-only registers are at $A000-$A002
+// Oscillator 2 write-only registers are at $B000-$B002
+void Vrc6_write_osc( struct Nes_Vrc6_Apu* this, blip_time_t, int osc, int reg, int data ); ICODE_ATTR
+
+static inline void Vrc6_osc_output( struct Nes_Vrc6_Apu* this, int i, struct Blip_Buffer* buf )
+{
+	assert( (unsigned) i < vrc6_osc_count );
+	this->oscs [i].output = buf;
+}
+
+static inline void Vrc6_volume( struct Nes_Vrc6_Apu* this, double v )
+{
+	double const factor = 0.0967 * 2;
+	Synth_volume( &this->saw_synth, factor / 31 * v );
+	Synth_volume( &this->square_synth, factor * 0.5 / 15 * v );
+}
+
+#endif
Index: apps/codecs/libnsf/nes_apu.h
===================================================================
--- apps/codecs/libnsf/nes_apu.h	(revision 0)
+++ apps/codecs/libnsf/nes_apu.h	(revision 0)
@@ -0,0 +1,134 @@
+// NES 2A03 APU sound chip emulator
+
+// Nes_Snd_Emu 0.1.8
+#ifndef NES_APU_H
+#define NES_APU_H
+
+#include "blargg_common.h"
+#include "nes_oscs.h"
+
+enum { apu_status_addr = 0x4015 };
+enum { apu_osc_count = 5 };
+enum { apu_no_irq = INT_MAX / 2 + 1 };
+enum { apu_irq_waiting = 0 };
+
+enum { apu_io_addr = 0x4000 };
+enum { apu_io_size = 0x18 };
+
+struct apu_state_t;
+
+struct Nes_Apu {	
+	nes_time_t last_dmc_time;	
+	int osc_enables;
+	
+	struct Nes_Osc*            oscs [apu_osc_count];
+	struct Nes_Square          square1;
+	struct Nes_Square          square2;
+	struct Nes_Noise           noise;
+	struct Nes_Triangle        triangle;
+	struct Nes_Dmc             dmc;
+	
+	double tempo_;
+	nes_time_t last_time; // has been run until this time in current frame
+	nes_time_t earliest_irq_;
+	nes_time_t next_irq;
+	int frame_period;
+	int frame_delay; // cycles until frame counter runs next
+	int frame; // current frame (0-3)
+	int frame_mode;
+	bool irq_flag;
+	
+	void (*irq_notifier_)( void* user_data );
+	void* irq_data;
+	
+	Synth square_synth; // shared by squares
+};
+
+// Init Nes apu
+void Apu_init( struct Nes_Apu* this );
+
+// Set buffer to generate all sound into, or disable sound if NULL
+void Apu_output( struct Nes_Apu* this, struct Blip_Buffer* ); ICODE_ATTR
+	
+// All time values are the number of cpu clock cycles relative to the
+// beginning of the current time frame. Before resetting the cpu clock
+// count, call end_frame( last_cpu_time ).
+
+// Write to register (0x4000-0x4017, except 0x4014 and 0x4016)
+void Apu_write_register( struct Nes_Apu* this, nes_time_t, addr_t, int data ); ICODE_ATTR
+	
+// Read from status register at 0x4015
+int Apu_read_status( struct Nes_Apu* this, nes_time_t ); ICODE_ATTR
+	
+// Run all oscillators up to specified time, end current time frame, then
+// start a new time frame at time 0. Time frames have no effect on emulation
+// and each can be whatever length is convenient.
+void Apu_end_frame( struct Nes_Apu* this, nes_time_t ); ICODE_ATTR
+	
+// Additional optional features (can be ignored without any problem)
+
+// Reset internal frame counter, registers, and all oscillators.
+// Use PAL timing if pal_timing is true, otherwise use NTSC timing.
+// Set the DMC oscillator's initial DAC value to initial_dmc_dac without
+// any audible click.
+void Apu_reset( struct Nes_Apu* this, bool pal_mode, int initial_dmc_dac );
+	
+// Adjust frame period
+void Apu_set_tempo( struct Nes_Apu* this, double );
+	
+// Set overall volume (default is 1.0)
+void Apu_volume( struct Nes_Apu* this, double );
+	
+// Run DMC until specified time, so that any DMC memory reads can be
+// accounted for (i.e. inserting cpu wait states).
+void Apu_run_until( struct Nes_Apu* this, nes_time_t ); ICODE_ATTR
+
+// Set sound output of specific oscillator to buffer. If buffer is NULL,
+// the specified oscillator is muted and emulation accuracy is reduced.
+// The oscillators are indexed as follows: 0) Square 1, 1) Square 2,
+// 2) Triangle, 3) Noise, 4) DMC.
+static inline void Apu_osc_output( struct Nes_Apu* this, int osc, struct Blip_Buffer* buf )
+{
+	assert( (unsigned) osc < apu_osc_count );
+	this->oscs [osc]->output = buf;
+}
+
+// Set memory reader callback used by DMC oscillator to fetch samples.
+// When callback is invoked, 'user_data' is passed unchanged as the
+// first parameter.
+static inline void Apu_dmc_reader( struct Nes_Apu* this, int (*func)( void*, addr_t ), void* user_data )
+{
+	this->dmc.prg_reader_data = user_data;
+	this->dmc.prg_reader = func;
+}
+
+// Set IRQ time callback that is invoked when the time of earliest IRQ
+// may have changed, or NULL to disable. When callback is invoked,
+// 'user_data' is passed unchanged as the first parameter.
+static inline void Apu_irq_notifier( struct Nes_Apu* this, void (*func)( void* user_data ), void* user_data )
+{
+	this->irq_notifier_ = func;
+	this->irq_data = user_data;
+}
+
+// Count number of DMC reads that would occur if 'run_until( t )' were executed.
+// If last_read is not NULL, set *last_read to the earliest time that
+// 'count_dmc_reads( time )' would result in the same result.
+static inline int Apu_count_dmc_reads( struct Nes_Apu* this, nes_time_t time, nes_time_t* last_read )
+{
+	return Dmc_count_reads( &this->dmc, time, last_read );
+}
+
+static inline nes_time_t Dmc_next_read_time( struct Nes_Dmc* this )
+{
+	if ( this->osc.length_counter == 0 )
+		return apu_no_irq; // not reading
+	
+	return this->apu->last_dmc_time + this->osc.delay + (long) (this->bits_remain - 1) * this->period;
+}
+
+// Time when next DMC memory read will occur
+static inline nes_time_t Apu_next_dmc_read_time( struct Nes_Apu* this ) { return Dmc_next_read_time( &this->dmc ); }
+void Apu_irq_changed( struct Nes_Apu* this ); ICODE_ATTR
+
+#endif
Index: apps/codecs/libnsf/ym2413.c
===================================================================
--- apps/codecs/libnsf/ym2413.c	(revision 0)
+++ apps/codecs/libnsf/ym2413.c	(revision 0)
@@ -0,0 +1,1960 @@
+/*
+**
+** File: ym2413.c - software implementation of YM2413
+**                  FM sound generator type OPLL
+**
+** Copyright Jarek Burczynski
+**
+** Version 1.0
+**
+
+   Features as listed in LSI-212413A2 data sheet:
+    1. FM Sound Generator for real sound creation.
+    2. Two Selectable modes: 9 simultaneous sounds or 6 melody sounds plus 5 rhythm sounds
+       (different tones can be used together in either case).
+    3. Built-in Instruments data (15 melody tones, 5 rhythm tones, "CAPTAIN and TELETEXT applicalbe tones).
+    4. Built-in DA Converter.
+    5. Built-in Quartz Oscillator.
+    6. Built-in Vibrato Oscillator/AM Oscillator
+    7. TTL Compatible Input.
+    8. Si-Gate NMOS LSI
+    9. A single 5V power source.
+
+to do:
+
+- make sure of the sinus amplitude bits
+
+- make sure of the EG resolution bits (looks like the biggest
+  modulation index generated by the modulator is 123, 124 = no modulation)
+- find proper algorithm for attack phase of EG
+
+- tune up instruments ROM
+
+- support sample replay in test mode (it is NOT as simple as setting bit 0
+  in register 0x0f and using register 0x10 for sample data).
+  Which games use this feature ?
+
+  ** Modified to use static memory ~ gama
+
+*/
+
+#if defined(ROCKBOX)
+	#include "ym_tables.h"
+#else
+	#define YM2413_CALCUL_TABLES
+#endif
+
+#define _USE_MATH_DEFINES
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include "ym2413.h"
+
+#define INLINE __inline
+#ifndef NULL
+	#define NULL ((void *)0)
+#endif
+#define logerror (void)
+
+#ifndef M_PI
+	#define M_PI 3.14159265358979323846
+#endif
+
+/* output final shift */
+#if (SAMPLE_BITS==16)
+	#define FINAL_SH	(0)
+	#define MAXOUT		(+32767)
+	#define MINOUT		(-32768)
+#else
+	#define FINAL_SH	(8)
+	#define MAXOUT		(+127)
+	#define MINOUT		(-128)
+#endif
+
+
+#define FREQ_SH			16  /* 16.16 fixed point (frequency calculations) */
+#define EG_SH			16  /* 16.16 fixed point (EG timing)              */
+#define LFO_SH			24  /*  8.24 fixed point (LFO calculations)       */
+
+#define FREQ_MASK		((1<<FREQ_SH)-1)
+
+/* envelope output entries */
+#define ENV_BITS		10
+#define ENV_LEN			(1<<ENV_BITS)
+#define ENV_STEP		(128.0/ENV_LEN)
+
+#define MAX_ATT_INDEX	((1<<(ENV_BITS-2))-1) /*255*/
+#define MIN_ATT_INDEX	(0)
+
+/* sinwave entries */
+#define SIN_BITS		10
+#define SIN_LEN			(1<<SIN_BITS)
+#define SIN_MASK		(SIN_LEN-1)
+
+#define TL_RES_LEN		(256)	/* 8 bits addressing (real chip) */
+
+/* register number to channel number , slot offset */
+#define SLOT1 0
+#define SLOT2 1
+
+/* Envelope Generator phases */
+
+#define EG_DMP			5
+#define EG_ATT			4
+#define EG_DEC			3
+#define EG_SUS			2
+#define EG_REL			1
+#define EG_OFF			0
+
+#define OPLL_MASK_CH(x) (1<<(x))
+#define OPLL_MASK_HH (1<<(9))
+#define OPLL_MASK_CYM (1<<(10))
+#define OPLL_MASK_TOM (1<<(11))
+#define OPLL_MASK_SD (1<<(12))
+#define OPLL_MASK_BD (1<<(13))
+#define OPLL_MASK_RHYTHM ( OPLL_MASK_HH | OPLL_MASK_CYM | OPLL_MASK_TOM | OPLL_MASK_SD | OPLL_MASK_BD )
+
+/* key scale level */
+/* table is 3dB/octave, DV converts this into 6dB/octave */
+/* 0.1875 is bit 0 weight of the envelope counter (volume) expressed in the 'decibel' scale */
+#define DV(db) (UINT32) ( db / (0.1875/1.0) )
+static const UINT32 ksl_tab[8*16] ICONST_ATTR =
+{
+	/* OCT 0 */
+	 DV( 0.000), DV( 0.000),DV(  0.000),DV(  0.000),
+	 DV( 0.000), DV( 0.000),DV(  0.000),DV(  0.000),
+	 DV( 0.000), DV( 0.000),DV(  0.000),DV(  0.000),
+	 DV( 0.000), DV( 0.000),DV(  0.000),DV(  0.000),
+	/* OCT 1 */
+	 DV( 0.000), DV( 0.000),DV(  0.000),DV(  0.000),
+	 DV( 0.000), DV( 0.000),DV(  0.000),DV(  0.000),
+	 DV( 0.000), DV( 0.750),DV(  1.125),DV(  1.500),
+	 DV( 1.875), DV( 2.250),DV(  2.625),DV(  3.000),
+	/* OCT 2 */
+	 DV( 0.000), DV( 0.000),DV(  0.000),DV(  0.000),
+	 DV( 0.000), DV( 1.125),DV(  1.875),DV(  2.625),
+	 DV( 3.000), DV( 3.750),DV(  4.125),DV(  4.500),
+	 DV( 4.875), DV( 5.250),DV(  5.625),DV(  6.000),
+	/* OCT 3 */
+	 DV( 0.000), DV( 0.000),DV(  0.000),DV(  1.875),
+	 DV( 3.000), DV( 4.125),DV(  4.875),DV(  5.625),
+	 DV( 6.000), DV( 6.750),DV(  7.125),DV(  7.500),
+	 DV( 7.875), DV( 8.250),DV(  8.625),DV(  9.000),
+	/* OCT 4 */
+	 DV( 0.000), DV( 0.000),DV(  3.000),DV(  4.875),
+	 DV( 6.000), DV( 7.125),DV(  7.875),DV(  8.625),
+	 DV( 9.000), DV( 9.750),DV( 10.125),DV( 10.500),
+	DV( 10.875),DV( 11.250),DV( 11.625),DV( 12.000),
+	/* OCT 5 */
+	 DV( 0.000),DV(  3.000),DV(  6.000),DV(  7.875),
+	 DV( 9.000),DV( 10.125),DV( 10.875),DV( 11.625),
+	DV( 12.000),DV( 12.750),DV( 13.125),DV( 13.500),
+	DV( 13.875),DV( 14.250),DV( 14.625),DV( 15.000),
+	/* OCT 6 */
+	DV(  0.000),DV(  6.000),DV(  9.000),DV( 10.875),
+	DV( 12.000),DV( 13.125),DV( 13.875),DV( 14.625),
+	DV( 15.000),DV( 15.750),DV( 16.125),DV( 16.500),
+	DV( 16.875),DV( 17.250),DV( 17.625),DV( 18.000),
+	/* OCT 7 */
+	DV(  0.000),DV(  9.000),DV( 12.000),DV( 13.875),
+	DV( 15.000),DV( 16.125),DV( 16.875),DV( 17.625),
+	DV( 18.000),DV( 18.750),DV( 19.125),DV( 19.500),
+	DV( 19.875),DV( 20.250),DV( 20.625),DV( 21.000)
+};
+#undef DV
+#undef KSL
+
+/* sustain level table (3dB per step) */
+/* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,45 (dB)*/
+#define SC(db) (UINT32) ( db * (1.0/ENV_STEP) )
+static const UINT32 sl_tab[16] ICONST_ATTR ={
+ SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7),
+ SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(15)
+};
+#undef SC
+
+
+#define RATE_STEPS (8)
+static const unsigned char eg_inc[15*RATE_STEPS]={
+
+/*cycle:0 1  2 3  4 5  6 7*/
+
+/* 0 */ 0,1, 0,1, 0,1, 0,1, /* rates 00..12 0 (increment by 0 or 1) */
+/* 1 */ 0,1, 0,1, 1,1, 0,1, /* rates 00..12 1 */
+/* 2 */ 0,1, 1,1, 0,1, 1,1, /* rates 00..12 2 */
+/* 3 */ 0,1, 1,1, 1,1, 1,1, /* rates 00..12 3 */
+
+/* 4 */ 1,1, 1,1, 1,1, 1,1, /* rate 13 0 (increment by 1) */
+/* 5 */ 1,1, 1,2, 1,1, 1,2, /* rate 13 1 */
+/* 6 */ 1,2, 1,2, 1,2, 1,2, /* rate 13 2 */
+/* 7 */ 1,2, 2,2, 1,2, 2,2, /* rate 13 3 */
+
+/* 8 */ 2,2, 2,2, 2,2, 2,2, /* rate 14 0 (increment by 2) */
+/* 9 */ 2,2, 2,4, 2,2, 2,4, /* rate 14 1 */
+/*10 */ 2,4, 2,4, 2,4, 2,4, /* rate 14 2 */
+/*11 */ 2,4, 4,4, 2,4, 4,4, /* rate 14 3 */
+
+/*12 */ 4,4, 4,4, 4,4, 4,4, /* rates 15 0, 15 1, 15 2, 15 3 (increment by 4) */
+/*13 */ 8,8, 8,8, 8,8, 8,8, /* rates 15 2, 15 3 for attack */
+/*14 */ 0,0, 0,0, 0,0, 0,0, /* infinity rates for attack and decay(s) */
+};
+
+
+#define O(a) (a*RATE_STEPS)
+
+/*note that there is no O(13) in this table - it's directly in the code */
+static const unsigned char eg_rate_select[16+64+16] ICONST_ATTR ={	/* Envelope Generator rates (16 + 64 rates + 16 RKS) */
+/* 16 infinite time rates */
+O(14),O(14),O(14),O(14),O(14),O(14),O(14),O(14),
+O(14),O(14),O(14),O(14),O(14),O(14),O(14),O(14),
+
+/* rates 00-12 */
+O( 0),O( 1),O( 2),O( 3),
+O( 0),O( 1),O( 2),O( 3),
+O( 0),O( 1),O( 2),O( 3),
+O( 0),O( 1),O( 2),O( 3),
+O( 0),O( 1),O( 2),O( 3),
+O( 0),O( 1),O( 2),O( 3),
+O( 0),O( 1),O( 2),O( 3),
+O( 0),O( 1),O( 2),O( 3),
+O( 0),O( 1),O( 2),O( 3),
+O( 0),O( 1),O( 2),O( 3),
+O( 0),O( 1),O( 2),O( 3),
+O( 0),O( 1),O( 2),O( 3),
+O( 0),O( 1),O( 2),O( 3),
+
+/* rate 13 */
+O( 4),O( 5),O( 6),O( 7),
+
+/* rate 14 */
+O( 8),O( 9),O(10),O(11),
+
+/* rate 15 */
+O(12),O(12),O(12),O(12),
+
+/* 16 dummy rates (same as 15 3) */
+O(12),O(12),O(12),O(12),O(12),O(12),O(12),O(12),
+O(12),O(12),O(12),O(12),O(12),O(12),O(12),O(12),
+
+};
+#undef O
+
+/*rate  0,    1,    2,    3,    4,   5,   6,   7,  8,  9, 10, 11, 12, 13, 14, 15 */
+/*shift 13,   12,   11,   10,   9,   8,   7,   6,  5,  4,  3,  2,  1,  0,  0,  0 */
+/*mask  8191, 4095, 2047, 1023, 511, 255, 127, 63, 31, 15, 7,  3,  1,  0,  0,  0 */
+
+#define O(a) (a*1)
+static const unsigned char eg_rate_shift[16+64+16] ICONST_ATTR ={	/* Envelope Generator counter shifts (16 + 64 rates + 16 RKS) */
+/* 16 infinite time rates */
+O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),
+O(0),O(0),O(0),O(0),O(0),O(0),O(0),O(0),
+
+/* rates 00-12 */
+O(13),O(13),O(13),O(13),
+O(12),O(12),O(12),O(12),
+O(11),O(11),O(11),O(11),
+O(10),O(10),O(10),O(10),
+O( 9),O( 9),O( 9),O( 9),
+O( 8),O( 8),O( 8),O( 8),
+O( 7),O( 7),O( 7),O( 7),
+O( 6),O( 6),O( 6),O( 6),
+O( 5),O( 5),O( 5),O( 5),
+O( 4),O( 4),O( 4),O( 4),
+O( 3),O( 3),O( 3),O( 3),
+O( 2),O( 2),O( 2),O( 2),
+O( 1),O( 1),O( 1),O( 1),
+
+/* rate 13 */
+O( 0),O( 0),O( 0),O( 0),
+
+/* rate 14 */
+O( 0),O( 0),O( 0),O( 0),
+
+/* rate 15 */
+O( 0),O( 0),O( 0),O( 0),
+
+/* 16 dummy rates (same as 15 3) */
+O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),
+O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),O( 0),
+
+};
+#undef O
+
+
+/* multiple table */
+#define ML(db) (UINT8) ( db * 2.0 )
+static const UINT8 mul_tab[16] ICONST_ATTR = {
+/* 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,10,12,12,15,15 */
+   ML(0.50), ML(1.00),ML( 2.00),ML( 3.00),ML( 4.00),ML( 5.00),ML( 6.00),ML( 7.00),
+   ML(8.00), ML(9.00),ML(10.00),ML(10.00),ML(12.00),ML(12.00),ML(15.00),ML(15.00)
+};
+#undef ML
+
+/*  TL_TAB_LEN is calculated as:
+*   11 - sinus amplitude bits     (Y axis)
+*   2  - sinus sign bit           (Y axis)
+*   TL_RES_LEN - sinus resolution (X axis)
+*/
+#define TL_TAB_LEN (11*2*TL_RES_LEN)
+static signed int tl_tab[TL_TAB_LEN];
+
+#define ENV_QUIET		(TL_TAB_LEN>>5)
+
+/* sin waveform table in 'decibel' scale */
+/* two waveforms on OPLL type chips */
+static unsigned int sin_tab[SIN_LEN * 2];
+
+
+/* LFO Amplitude Modulation table (verified on real YM3812)
+   27 output levels (triangle waveform); 1 level takes one of: 192, 256 or 448 samples
+
+   Length: 210 elements.
+
+    Each of the elements has to be repeated
+    exactly 64 times (on 64 consecutive samples).
+    The whole table takes: 64 * 210 = 13440 samples.
+
+We use data>>1, until we find what it really is on real chip...
+
+*/
+
+#define LFO_AM_TAB_ELEMENTS 210
+
+static const UINT8 lfo_am_table[LFO_AM_TAB_ELEMENTS] ICONST_ATTR = {
+0,0,0,0,0,0,0,
+1,1,1,1,
+2,2,2,2,
+3,3,3,3,
+4,4,4,4,
+5,5,5,5,
+6,6,6,6,
+7,7,7,7,
+8,8,8,8,
+9,9,9,9,
+10,10,10,10,
+11,11,11,11,
+12,12,12,12,
+13,13,13,13,
+14,14,14,14,
+15,15,15,15,
+16,16,16,16,
+17,17,17,17,
+18,18,18,18,
+19,19,19,19,
+20,20,20,20,
+21,21,21,21,
+22,22,22,22,
+23,23,23,23,
+24,24,24,24,
+25,25,25,25,
+26,26,26,
+25,25,25,25,
+24,24,24,24,
+23,23,23,23,
+22,22,22,22,
+21,21,21,21,
+20,20,20,20,
+19,19,19,19,
+18,18,18,18,
+17,17,17,17,
+16,16,16,16,
+15,15,15,15,
+14,14,14,14,
+13,13,13,13,
+12,12,12,12,
+11,11,11,11,
+10,10,10,10,
+9,9,9,9,
+8,8,8,8,
+7,7,7,7,
+6,6,6,6,
+5,5,5,5,
+4,4,4,4,
+3,3,3,3,
+2,2,2,2,
+1,1,1,1
+};
+
+/* LFO Phase Modulation table (verified on real YM2413) */
+static const INT8 lfo_pm_table[8*8] ICONST_ATTR = {
+
+/* FNUM2/FNUM = 0 00xxxxxx (0x0000) */
+0, 0, 0, 0, 0, 0, 0, 0,
+
+/* FNUM2/FNUM = 0 01xxxxxx (0x0040) */
+1, 0, 0, 0,-1, 0, 0, 0,
+
+/* FNUM2/FNUM = 0 10xxxxxx (0x0080) */
+2, 1, 0,-1,-2,-1, 0, 1,
+
+/* FNUM2/FNUM = 0 11xxxxxx (0x00C0) */
+3, 1, 0,-1,-3,-1, 0, 1,
+
+/* FNUM2/FNUM = 1 00xxxxxx (0x0100) */
+4, 2, 0,-2,-4,-2, 0, 2,
+
+/* FNUM2/FNUM = 1 01xxxxxx (0x0140) */
+5, 2, 0,-2,-5,-2, 0, 2,
+
+/* FNUM2/FNUM = 1 10xxxxxx (0x0180) */
+6, 3, 0,-3,-6,-3, 0, 3,
+
+/* FNUM2/FNUM = 1 11xxxxxx (0x01C0) */
+7, 3, 0,-3,-7,-3, 0, 3,
+};
+
+
+
+
+
+
+/* This is not 100% perfect yet but very close */
+/*
+ - multi parameters are 100% correct (instruments and drums)
+ - LFO PM and AM enable are 100% correct
+ - waveform DC and DM select are 100% correct
+*/
+
+static const unsigned char table[19][8] ICONST_ATTR = {
+/* MULT  MULT modTL DcDmFb AR/DR AR/DR SL/RR SL/RR */
+/*   0     1     2     3     4     5     6    7    */
+  {0x49, 0x4c, 0x4c, 0x12, 0x00, 0x00, 0x00, 0x00 },	/* 0 */
+
+  {0x61, 0x61, 0x1e, 0x17, 0xf0, 0x78, 0x00, 0x17 },	/* 1 */
+  {0x13, 0x41, 0x1e, 0x0d, 0xd7, 0xf7, 0x13, 0x13 },	/* 2 */
+  {0x13, 0x01, 0x99, 0x04, 0xf2, 0xf4, 0x11, 0x23 },	/* 3 */
+  {0x21, 0x61, 0x1b, 0x07, 0xaf, 0x64, 0x40, 0x27 },	/* 4 */
+
+/* {0x22, 0x21, 0x1e, 0x09, 0xf0, 0x76, 0x08, 0x28 },    //5 */
+  {0x22, 0x21, 0x1e, 0x06, 0xf0, 0x75, 0x08, 0x18 },	/* 5 */
+
+/* {0x31, 0x22, 0x16, 0x09, 0x90, 0x7f, 0x00, 0x08 },    //6 */
+  {0x31, 0x22, 0x16, 0x05, 0x90, 0x71, 0x00, 0x13 },	/* 6 */
+
+  {0x21, 0x61, 0x1d, 0x07, 0x82, 0x80, 0x10, 0x17 },	/* 7 */
+  {0x23, 0x21, 0x2d, 0x16, 0xc0, 0x70, 0x07, 0x07 },	/* 8 */
+  {0x61, 0x61, 0x1b, 0x06, 0x64, 0x65, 0x10, 0x17 },	/* 9 */
+
+/* {0x61, 0x61, 0x0c, 0x08, 0x85, 0xa0, 0x79, 0x07 },    //A */
+  {0x61, 0x61, 0x0c, 0x18, 0x85, 0xf0, 0x70, 0x07 },	/* A */
+
+  {0x23, 0x01, 0x07, 0x11, 0xf0, 0xa4, 0x00, 0x22 },	/* B */
+  {0x97, 0xc1, 0x24, 0x07, 0xff, 0xf8, 0x22, 0x12 },	/* C */
+
+/* {0x61, 0x10, 0x0c, 0x08, 0xf2, 0xc4, 0x40, 0xc8 },    //D */
+  {0x61, 0x10, 0x0c, 0x05, 0xf2, 0xf4, 0x40, 0x44 },	/* D */
+
+  {0x01, 0x01, 0x55, 0x03, 0xf3, 0x92, 0xf3, 0xf3 },	/* E */
+  {0x61, 0x41, 0x89, 0x03, 0xf1, 0xf4, 0xf0, 0x13 },	/* F */
+
+/* drum instruments definitions */
+/* MULTI MULTI modTL  xxx  AR/DR AR/DR SL/RR SL/RR */
+/*   0     1     2     3     4     5     6    7    */
+  {0x01, 0x01, 0x16, 0x00, 0xfd, 0xf8, 0x2f, 0x6d },/* BD(multi verified, modTL verified, mod env - verified(close), carr. env verifed) */
+  {0x01, 0x01, 0x00, 0x00, 0xd8, 0xd8, 0xf9, 0xf8 },/* HH(multi verified), SD(multi not used) */
+  {0x05, 0x01, 0x00, 0x00, 0xf8, 0xba, 0x49, 0x55 },/* TOM(multi,env verified), TOP CYM(multi verified, env verified) */
+};
+
+static const unsigned char table_vrc7[15][8] ICONST_ATTR =
+{
+/* VRC7 instruments, January 17, 2004 update -Xodnizel */
+    {0x03, 0x21, 0x04, 0x06, 0x8D, 0xF2, 0x42, 0x17}, 
+    {0x13, 0x41, 0x05, 0x0E, 0x99, 0x96, 0x63, 0x12}, 
+    {0x31, 0x11, 0x10, 0x0A, 0xF0, 0x9C, 0x32, 0x02}, 
+    {0x21, 0x61, 0x1D, 0x07, 0x9F, 0x64, 0x20, 0x27}, 
+    {0x22, 0x21, 0x1E, 0x06, 0xF0, 0x76, 0x08, 0x28}, 
+    {0x02, 0x01, 0x06, 0x00, 0xF0, 0xF2, 0x03, 0x95}, 
+    {0x21, 0x61, 0x1C, 0x07, 0x82, 0x81, 0x16, 0x07}, 
+    {0x23, 0x21, 0x1A, 0x17, 0xEF, 0x82, 0x25, 0x15}, 
+    {0x25, 0x11, 0x1F, 0x00, 0x86, 0x41, 0x20, 0x11}, 
+    {0x85, 0x01, 0x1F, 0x0F, 0xE4, 0xA2, 0x11, 0x12}, 
+    {0x07, 0xC1, 0x2B, 0x45, 0xB4, 0xF1, 0x24, 0xF4},
+    {0x61, 0x23, 0x11, 0x06, 0x96, 0x96, 0x13, 0x16}, 
+    {0x01, 0x02, 0xD3, 0x05, 0x82, 0xA2, 0x31, 0x51}, 
+    {0x61, 0x22, 0x0D, 0x02, 0xC3, 0x7F, 0x24, 0x05},
+    {0x21, 0x62, 0x0E, 0x00, 0xA1, 0xA0, 0x44, 0x17},
+
+};
+
+INLINE int limit( int val, int max, int min ) {
+	if ( val > max )
+		val = max;
+	else if ( val < min )
+		val = min;
+
+	return val;
+}
+
+
+/* advance LFO to next sample */
+static INLINE void advance_lfo(YM2413 *chip)
+{
+	/* LFO */
+	chip->lfo_am_cnt += chip->lfo_am_inc;
+	if (chip->lfo_am_cnt >= ((UINT32)LFO_AM_TAB_ELEMENTS<<LFO_SH) )	/* lfo_am_table is 210 elements long */
+		chip->lfo_am_cnt -= ((UINT32)LFO_AM_TAB_ELEMENTS<<LFO_SH);
+
+	chip->LFO_AM = lfo_am_table[ chip->lfo_am_cnt >> LFO_SH ] >> 1;
+
+	chip->lfo_pm_cnt += chip->lfo_pm_inc;
+	chip->LFO_PM = (chip->lfo_pm_cnt>>LFO_SH) & 7;
+}
+
+/* advance to next sample */
+static INLINE void advance(YM2413 *chip)
+{
+	OPLL_CH *CH;
+	OPLL_SLOT *op;
+	unsigned int i;
+
+	/* Envelope Generator */
+	chip->eg_timer += chip->eg_timer_add;
+
+	while (chip->eg_timer >= chip->eg_timer_overflow)
+	{
+		chip->eg_timer -= chip->eg_timer_overflow;
+
+		chip->eg_cnt++;
+
+		for (i=0; i<9*2; i++)
+		{
+			CH  = &chip->P_CH[i/2];
+
+			op  = &CH->SLOT[i&1];
+
+			switch(op->state)
+			{
+
+			case EG_DMP:		/* dump phase */
+			/*dump phase is performed by both operators in each channel*/
+			/*when CARRIER envelope gets down to zero level,
+            **  phases in BOTH opearators are reset (at the same time ?)
+            */
+				if ( !(chip->eg_cnt & ((1<<op->eg_sh_dp)-1) ) )
+				{
+					op->volume += eg_inc[op->eg_sel_dp + ((chip->eg_cnt>>op->eg_sh_dp)&7)];
+
+					if ( op->volume >= MAX_ATT_INDEX )
+					{
+						op->volume = MAX_ATT_INDEX;
+						op->state = EG_ATT;
+						/* restart Phase Generator  */
+						op->phase = 0;
+					}
+				}
+			break;
+
+			case EG_ATT:		/* attack phase */
+				if ( !(chip->eg_cnt & ((1<<op->eg_sh_ar)-1) ) )
+				{
+					op->volume += (~op->volume *
+	                        		           (eg_inc[op->eg_sel_ar + ((chip->eg_cnt>>op->eg_sh_ar)&7)])
+        			                          ) >>2;
+
+					if (op->volume <= MIN_ATT_INDEX)
+					{
+						op->volume = MIN_ATT_INDEX;
+						op->state = EG_DEC;
+					}
+				}
+			break;
+
+			case EG_DEC:	/* decay phase */
+				if ( !(chip->eg_cnt & ((1<<op->eg_sh_dr)-1) ) )
+				{
+					op->volume += eg_inc[op->eg_sel_dr + ((chip->eg_cnt>>op->eg_sh_dr)&7)];
+
+					if ( (unsigned) op->volume >= op->sl )
+						op->state = EG_SUS;
+				}
+			break;
+
+			case EG_SUS:	/* sustain phase */
+				/* this is important behaviour:
+                one can change percusive/non-percussive modes on the fly and
+                the chip will remain in sustain phase - verified on real YM3812 */
+
+				if(op->eg_type)		/* non-percussive mode (sustained tone) */
+				{
+									/* do nothing */
+				}
+				else				/* percussive mode */
+				{
+					/* during sustain phase chip adds Release Rate (in percussive mode) */
+					if ( !(chip->eg_cnt & ((1<<op->eg_sh_rr)-1) ) )
+					{
+						op->volume += eg_inc[op->eg_sel_rr + ((chip->eg_cnt>>op->eg_sh_rr)&7)];
+
+						if ( op->volume >= MAX_ATT_INDEX )
+							op->volume = MAX_ATT_INDEX;
+					}
+					/* else do nothing in sustain phase */
+				}
+			break;
+
+			case EG_REL:	/* release phase */
+			/* exclude modulators in melody channels from performing anything in this mode*/
+			/* allowed are only carriers in melody mode and rhythm slots in rhythm mode */
+
+			/*This table shows which operators and on what conditions are allowed to perform EG_REL:
+            (a) - always perform EG_REL
+            (n) - never perform EG_REL
+            (r) - perform EG_REL in Rhythm mode ONLY
+                0: 0 (n),  1 (a)
+                1: 2 (n),  3 (a)
+                2: 4 (n),  5 (a)
+                3: 6 (n),  7 (a)
+                4: 8 (n),  9 (a)
+                5: 10(n),  11(a)
+                6: 12(r),  13(a)
+                7: 14(r),  15(a)
+                8: 16(r),  17(a)
+            */
+				if ( (i&1) || ((chip->rhythm&0x20) && (i>=12)) )/* exclude modulators */
+				{
+					if(op->eg_type)		/* non-percussive mode (sustained tone) */
+					/*this is correct: use RR when SUS = OFF*/
+					/*and use RS when SUS = ON*/
+					{
+						if (CH->sus)
+						{
+							if ( !(chip->eg_cnt & ((1<<op->eg_sh_rs)-1) ) )
+							{
+								op->volume += eg_inc[op->eg_sel_rs + ((chip->eg_cnt>>op->eg_sh_rs)&7)];
+								if ( op->volume >= MAX_ATT_INDEX )
+								{
+									op->volume = MAX_ATT_INDEX;
+									op->state = EG_OFF;
+								}
+							}
+						}
+						else
+						{
+							if ( !(chip->eg_cnt & ((1<<op->eg_sh_rr)-1) ) )
+							{
+								op->volume += eg_inc[op->eg_sel_rr + ((chip->eg_cnt>>op->eg_sh_rr)&7)];
+								if ( op->volume >= MAX_ATT_INDEX )
+								{
+									op->volume = MAX_ATT_INDEX;
+									op->state = EG_OFF;
+								}
+							}
+						}
+					}
+					else				/* percussive mode */
+					{
+						if ( !(chip->eg_cnt & ((1<<op->eg_sh_rs)-1) ) )
+						{
+							op->volume += eg_inc[op->eg_sel_rs + ((chip->eg_cnt>>op->eg_sh_rs)&7)];
+							if ( op->volume >= MAX_ATT_INDEX )
+							{
+								op->volume = MAX_ATT_INDEX;
+								op->state = EG_OFF;
+							}
+						}
+					}
+				}
+			break;
+
+			default:
+			break;
+			}
+		}
+	}
+
+	for (i=0; i<9*2; i++)
+	{
+		CH  = &chip->P_CH[i/2];
+		op  = &CH->SLOT[i&1];
+
+		/* Phase Generator */
+		if(op->vib)
+		{
+			UINT8 block;
+
+			unsigned int fnum_lfo   = 8*((CH->block_fnum&0x01c0) >> 6);
+			unsigned int block_fnum = CH->block_fnum * 2;
+			signed int lfo_fn_table_index_offset = lfo_pm_table[chip->LFO_PM + fnum_lfo ];
+
+			if (lfo_fn_table_index_offset)	/* LFO phase modulation active */
+			{
+				block_fnum += lfo_fn_table_index_offset;
+				block = (block_fnum&0x1c00) >> 10;
+				op->phase += (chip->fn_tab[block_fnum&0x03ff] >> (7-block)) * op->mul;
+			}
+			else	/* LFO phase modulation  = zero */
+			{
+				op->phase += op->freq;
+			}
+		}
+		else	/* LFO phase modulation disabled for this operator */
+		{
+			op->phase += op->freq;
+		}
+	}
+
+	/*  The Noise Generator of the YM3812 is 23-bit shift register.
+    *   Period is equal to 2^23-2 samples.
+    *   Register works at sampling frequency of the chip, so output
+    *   can change on every sample.
+    *
+    *   Output of the register and input to the bit 22 is:
+    *   bit0 XOR bit14 XOR bit15 XOR bit22
+    *
+    *   Simply use bit 22 as the noise output.
+    */
+
+	chip->noise_p += chip->noise_f;
+	i = chip->noise_p >> FREQ_SH;		/* number of events (shifts of the shift register) */
+	chip->noise_p &= FREQ_MASK;
+	while (i)
+	{
+		/*
+        UINT32 j;
+        j = ( (chip->noise_rng) ^ (chip->noise_rng>>14) ^ (chip->noise_rng>>15) ^ (chip->noise_rng>>22) ) & 1;
+        chip->noise_rng = (j<<22) | (chip->noise_rng>>1);
+        */
+
+		/*
+            Instead of doing all the logic operations above, we
+            use a trick here (and use bit 0 as the noise output).
+            The difference is only that the noise bit changes one
+            step ahead. This doesn't matter since we don't know
+            what is real state of the noise_rng after the reset.
+        */
+
+		if (chip->noise_rng & 1) chip->noise_rng ^= 0x800302;
+		chip->noise_rng >>= 1;
+
+		i--;
+	}
+}
+
+
+static INLINE signed int op_calc(UINT32 phase, unsigned int env, signed int pm, unsigned int wave_tab)
+{
+	UINT32 p;
+
+	p = (env<<5) + sin_tab[wave_tab + ((((signed int)((phase & ~FREQ_MASK) + (pm<<17))) >> FREQ_SH ) & SIN_MASK) ];
+
+	if (p >= TL_TAB_LEN)
+		return 0;
+	return tl_tab[p];
+}
+
+static INLINE signed int op_calc1(UINT32 phase, unsigned int env, signed int pm, unsigned int wave_tab)
+{
+	UINT32 p;
+	INT32  i;
+
+	i = (phase & ~FREQ_MASK) + pm;
+
+/*logerror("i=%08x (i>>16)&511=%8i phase=%i [pm=%08x] ",i, (i>>16)&511, phase>>FREQ_SH, pm);*/
+
+	p = (env<<5) + sin_tab[ wave_tab + ((i>>FREQ_SH) & SIN_MASK)];
+
+/*logerror("(p&255=%i p>>8=%i) out= %i\n", p&255,p>>8, tl_tab[p&255]>>(p>>8) );*/
+
+	if (p >= TL_TAB_LEN)
+		return 0;
+	return tl_tab[p];
+}
+
+
+#define volume_calc(OP) ((OP)->TLL + ((UINT32)(OP)->volume) + (chip->LFO_AM & (OP)->AMmask))
+
+/* calculate output */
+static INLINE void chan_calc( YM2413 *chip, OPLL_CH *CH )
+{
+	OPLL_SLOT *SLOT;
+	unsigned int env;
+	signed int out;
+	signed int phase_modulation;	/* phase modulation input (SLOT 2) */
+
+
+	/* SLOT 1 */
+	SLOT = &CH->SLOT[SLOT1];
+	env  = volume_calc(SLOT);
+	out  = SLOT->op1_out[0] + SLOT->op1_out[1];
+
+	SLOT->op1_out[0] = SLOT->op1_out[1];
+	phase_modulation = SLOT->op1_out[0];
+
+	SLOT->op1_out[1] = 0;
+
+	if( env < ENV_QUIET )
+	{
+		if (!SLOT->fb_shift)
+			out = 0;
+		SLOT->op1_out[1] = op_calc1(SLOT->phase, env, (out<<SLOT->fb_shift), SLOT->wavetable );
+	}
+
+	/* SLOT 2 */
+
+	SLOT++;
+	env = volume_calc(SLOT);
+	if( env < ENV_QUIET )
+	{
+		signed int outp = op_calc(SLOT->phase, env, phase_modulation, SLOT->wavetable);
+		chip->output[0] += outp;
+		/* output[0] += op_calc(SLOT->phase, env, phase_modulation, SLOT->wavetable); */
+	}
+}
+
+/*
+    operators used in the rhythm sounds generation process:
+
+    Envelope Generator:
+
+channel  operator  register number   Bass  High  Snare Tom  Top
+/ slot   number    TL ARDR SLRR Wave Drum  Hat   Drum  Tom  Cymbal
+ 6 / 0   12        50  70   90   f0  +
+ 6 / 1   15        53  73   93   f3  +
+ 7 / 0   13        51  71   91   f1        +
+ 7 / 1   16        54  74   94   f4              +
+ 8 / 0   14        52  72   92   f2                    +
+ 8 / 1   17        55  75   95   f5                          +
+
+    Phase Generator:
+
+channel  operator  register number   Bass  High  Snare Tom  Top
+/ slot   number    MULTIPLE          Drum  Hat   Drum  Tom  Cymbal
+ 6 / 0   12        30                +
+ 6 / 1   15        33                +
+ 7 / 0   13        31                      +     +           +
+ 7 / 1   16        34                -----  n o t  u s e d -----
+ 8 / 0   14        32                                  +
+ 8 / 1   17        35                      +                 +
+
+channel  operator  register number   Bass  High  Snare Tom  Top
+number   number    BLK/FNUM2 FNUM    Drum  Hat   Drum  Tom  Cymbal
+   6     12,15     B6        A6      +
+
+   7     13,16     B7        A7            +     +           +
+
+   8     14,17     B8        A8            +           +     +
+
+*/
+
+/* calculate rhythm */
+
+static INLINE void rhythm_calc( YM2413 *chip, OPLL_CH *CH, unsigned int noise )
+{
+	OPLL_SLOT *SLOT;
+	signed int out;
+	unsigned int env;
+	signed int phase_modulation;	/* phase modulation input (SLOT 2) */
+
+
+	/* Bass Drum (verified on real YM3812):
+      - depends on the channel 6 'connect' register:
+          when connect = 0 it works the same as in normal (non-rhythm) mode (op1->op2->out)
+          when connect = 1 _only_ operator 2 is present on output (op2->out), operator 1 is ignored
+      - output sample always is multiplied by 2
+    */
+
+
+	/* SLOT 1 */
+	if ( !(chip->mask & OPLL_MASK_BD) )
+	{
+		SLOT = &CH[6].SLOT[SLOT1];
+		env = volume_calc(SLOT);
+
+		out = SLOT->op1_out[0] + SLOT->op1_out[1];
+		SLOT->op1_out[0] = SLOT->op1_out[1];
+
+		phase_modulation = SLOT->op1_out[0];
+
+		SLOT->op1_out[1] = 0;
+		if( env < ENV_QUIET )
+		{
+			if (!SLOT->fb_shift)
+				out = 0;
+			SLOT->op1_out[1] = op_calc1(SLOT->phase, env, (out<<SLOT->fb_shift), SLOT->wavetable );
+		}
+
+		/* SLOT 2 */
+		SLOT++;
+		env = volume_calc(SLOT);
+		if( env < ENV_QUIET )
+			chip->output[1] += op_calc(SLOT->phase, env, phase_modulation, SLOT->wavetable) * 2;
+	}
+
+
+	/* Phase generation is based on:
+	HH  (13) channel 7->slot 1 combined with channel 8->slot 2 (same combination as TOP CYMBAL but different output phases)
+	SD  (16) channel 7->slot 1
+	TOM (14) channel 8->slot 1
+	TOP (17) channel 7->slot 1 combined with channel 8->slot 2 (same combination as HIGH HAT but different output phases) */
+
+	/* Envelope generation based on:
+	HH  channel 7->slot1
+	SD  channel 7->slot2
+	TOM channel 8->slot1
+	TOP channel 8->slot2 */
+
+
+	/* The following formulas can be well optimized.
+       I leave them in direct form for now (in case I've missed something).
+    */
+
+	/* High Hat (verified on real YM3812) */
+	if ( !(chip->mask & OPLL_MASK_HH) )
+	{
+		env = volume_calc(chip->SLOT7_1);
+		if( env < ENV_QUIET )
+		{
+
+			/* high hat phase generation:
+			phase = d0 or 234 (based on frequency only)
+			phase = 34 or 2d0 (based on noise)
+			*/
+
+			/* base frequency derived from operator 1 in channel 7 */
+			unsigned char bit7 = ((chip->SLOT7_1->phase>>FREQ_SH)>>7)&1;
+			unsigned char bit3 = ((chip->SLOT7_1->phase>>FREQ_SH)>>3)&1;
+			unsigned char bit2 = ((chip->SLOT7_1->phase>>FREQ_SH)>>2)&1;
+
+			unsigned char res1 = (bit2 ^ bit7) | bit3;
+
+			/* when res1 = 0 phase = 0x000 | 0xd0; */
+			/* when res1 = 1 phase = 0x200 | (0xd0>>2); */
+			UINT32 phase = res1 ? (0x200|(0xd0>>2)) : 0xd0;
+
+			/* enable gate based on frequency of operator 2 in channel 8 */
+			unsigned char bit5e= ((chip->SLOT8_2->phase>>FREQ_SH)>>5)&1;
+			unsigned char bit3e= ((chip->SLOT8_2->phase>>FREQ_SH)>>3)&1;
+
+			unsigned char res2 = (bit3e | bit5e);
+
+			/* when res2 = 0 pass the phase from calculation above (res1); */
+			/* when res2 = 1 phase = 0x200 | (0xd0>>2); */
+			if (res2)
+				phase = (0x200|(0xd0>>2));
+
+
+			/* when phase & 0x200 is set and noise=1 then phase = 0x200|0xd0 */
+			/* when phase & 0x200 is set and noise=0 then phase = 0x200|(0xd0>>2), ie no change */
+			if (phase&0x200)
+			{
+				if (noise)
+					phase = 0x200|0xd0;
+			}
+			else
+				/* when phase & 0x200 is clear and noise=1 then phase = 0xd0>>2 */
+				/* when phase & 0x200 is clear and noise=0 then phase = 0xd0, ie no change */
+			{
+				if (noise)
+					phase = 0xd0>>2;
+			}
+
+			chip->output[1] += op_calc(phase<<FREQ_SH, env, 0, chip->SLOT7_1->wavetable) * 2;
+		}
+	}
+
+	/* Snare Drum (verified on real YM3812) */
+	if ( !(chip->mask & OPLL_MASK_SD) )
+	{
+		env = volume_calc(chip->SLOT7_2);
+		if( env < ENV_QUIET )
+		{
+			/* base frequency derived from operator 1 in channel 7 */
+			unsigned char bit8 = ((chip->SLOT7_1->phase>>FREQ_SH)>>8)&1;
+
+			/* when bit8 = 0 phase = 0x100; */
+			/* when bit8 = 1 phase = 0x200; */
+			UINT32 phase = bit8 ? 0x200 : 0x100;
+
+			/* Noise bit XOR'es phase by 0x100 */
+			/* when noisebit = 0 pass the phase from calculation above */
+			/* when noisebit = 1 phase ^= 0x100; */
+			/* in other words: phase ^= (noisebit<<8); */
+			if (noise)
+				phase ^= 0x100;
+
+			chip->output[1] += op_calc(phase<<FREQ_SH, env, 0, chip->SLOT7_2->wavetable) * 2;
+		}
+	}
+
+	/* Tom Tom (verified on real YM3812) */
+	if ( !(chip->mask & OPLL_MASK_TOM) )
+	{
+		env = volume_calc(chip->SLOT8_1);
+		if( env < ENV_QUIET )
+			chip->output[1] += op_calc(chip->SLOT8_1->phase, env, 0, chip->SLOT8_1->wavetable) * 2;
+	}
+
+	/* Top Cymbal (verified on real YM2413) */
+	if ( !(chip->mask & OPLL_MASK_CYM) )
+	{
+		env = volume_calc(chip->SLOT8_2);
+		if( env < ENV_QUIET )
+		{
+			/* base frequency derived from operator 1 in channel 7 */
+			unsigned char bit7 = ((chip->SLOT7_1->phase>>FREQ_SH)>>7)&1;
+			unsigned char bit3 = ((chip->SLOT7_1->phase>>FREQ_SH)>>3)&1;
+			unsigned char bit2 = ((chip->SLOT7_1->phase>>FREQ_SH)>>2)&1;
+
+			unsigned char res1 = (bit2 ^ bit7) | bit3;
+
+			/* when res1 = 0 phase = 0x000 | 0x100; */
+			/* when res1 = 1 phase = 0x200 | 0x100; */
+			UINT32 phase = res1 ? 0x300 : 0x100;
+
+			/* enable gate based on frequency of operator 2 in channel 8 */
+			unsigned char bit5e= ((chip->SLOT8_2->phase>>FREQ_SH)>>5)&1;
+			unsigned char bit3e= ((chip->SLOT8_2->phase>>FREQ_SH)>>3)&1;
+
+			unsigned char res2 = (bit3e | bit5e);
+			/* when res2 = 0 pass the phase from calculation above (res1); */
+			/* when res2 = 1 phase = 0x200 | 0x100; */
+			if (res2)
+				phase = 0x300;
+
+			chip->output[1] += op_calc(phase<<FREQ_SH, env, 0, chip->SLOT8_2->wavetable) * 2;
+		}
+	}
+}
+
+/* generic table initialize */
+static int init_tables(void)
+{
+#ifndef YM2413_CALCUL_TABLES
+	int i;
+	for (i=0; i<TL_TAB_LEN; i++) {
+		tl_tab[ i ] = get_le32( &tl_table_2413[ i ] ); 
+	}
+
+	for (i=0; i<SIN_LEN * 2; i++) {
+		sin_tab[ i ] = get_le32( &sin_table[ i ] ); 
+	}
+#else
+	signed int i,x;
+	signed int n;
+	double o,m;
+
+	for (x=0; x<TL_RES_LEN; x++)
+	{
+		m = (1<<16) / pow(2, (x+1) * (ENV_STEP/4.0) / 8.0);
+		m = floor(m);
+
+		/* we never reach (1<<16) here due to the (x+1) */
+		/* result fits within 16 bits at maximum */
+
+		n = (int)m;		/* 16 bits here */
+		n >>= 4;		/* 12 bits here */
+		if (n&1)		/* round to nearest */
+			n = (n>>1)+1;
+		else
+			n = n>>1;
+						/* 11 bits here (rounded) */
+		tl_tab[ x*2 + 0 ] = n;
+		tl_tab[ x*2 + 1 ] = -tl_tab[ x*2 + 0 ];
+
+		for (i=1; i<11; i++)
+		{
+			tl_tab[ x*2+0 + i*2*TL_RES_LEN ] =  tl_tab[ x*2+0 ]>>i;
+			tl_tab[ x*2+1 + i*2*TL_RES_LEN ] = -tl_tab[ x*2+0 + i*2*TL_RES_LEN ];
+		}
+	#if 0
+			logerror("tl %04i", x*2);
+			for (i=0; i<11; i++)
+				logerror(", [%02i] %5i", i*2, tl_tab[ x*2 /*+1*/ + i*2*TL_RES_LEN ] );
+			logerror("\n");
+	#endif
+	}
+	
+	/*logerror("ym2413.c: TL_TAB_LEN = %i elements (%i bytes)\n",TL_TAB_LEN, (int)sizeof(tl_tab));*/
+
+	for (i=0; i<SIN_LEN; i++)
+	{
+		/* non-standard sinus */
+		m = sin( ((i*2)+1) * M_PI / SIN_LEN ); /* checked against the real chip */
+
+		/* we never reach zero here due to ((i*2)+1) */
+
+		if (m>0.0)
+			o = 8*log(1.0/m)/log(2.0);	/* convert to 'decibels' */
+		else
+			o = 8*log(-1.0/m)/log(2.0);	/* convert to 'decibels' */
+
+		o = o / (ENV_STEP/4);
+
+		n = (int)(2.0*o);
+		if (n&1)						/* round to nearest */
+			n = (n>>1)+1;
+		else
+			n = n>>1;
+
+		/* waveform 0: standard sinus  */
+		sin_tab[ i ] = n*2 + (m>=0.0? 0: 1 );
+
+		/*logerror("ym2413.c: sin [%4i (hex=%03x)]= %4i (tl_tab value=%5i)\n", i, i, sin_tab[i], tl_tab[sin_tab[i]] );*/
+
+
+		/* waveform 1:  __      __     */
+		/*             /  \____/  \____*/
+		/* output only first half of the sinus waveform (positive one) */
+		if (i & (1<<(SIN_BITS-1)) )
+			sin_tab[1*SIN_LEN+i] = TL_TAB_LEN;
+		else
+			sin_tab[1*SIN_LEN+i] = sin_tab[i];
+
+		/*logerror("ym2413.c: sin1[%4i]= %4i (tl_tab value=%5i)\n", i, sin_tab[1*SIN_LEN+i], tl_tab[sin_tab[1*SIN_LEN+i]] );*/
+	}
+
+#if 0
+	logerror("YM2413.C: ENV_QUIET= %08x (*32=%08x)\n", ENV_QUIET, ENV_QUIET*32 );
+	for (i=0; i<ENV_QUIET; i++)
+	{
+		logerror("tl_tb[%4x(%4i)]=%8x\n", i<<5, i, tl_tab[i<<5] );
+	}
+#endif
+#ifdef SAVE_SAMPLE
+	sample[0]=fopen("sampsum.pcm","wb");
+#endif
+
+#endif // YM2413_CALCUL_TABLES
+	return 1;
+}
+
+#if defined(ROCKBOX)
+	#define fabs(x) (x < 0.0 ? x * -1.0 : x)
+#endif
+
+static void OPLL_initalize(YM2413 *chip)
+{
+	int i;
+
+	/* frequency base */
+	chip->freqbase  = (chip->rate) ? ((double)chip->clock / 72.0) / chip->rate  : 0;
+	if ( fabs( chip->freqbase - 1.0 ) < 0.0000001 )
+		chip->freqbase = 1.0;
+#if 0
+	chip->rate = (double)chip->clock / 72.0;
+	chip->freqbase  = 1.0;
+	logerror("freqbase=%f\n", chip->freqbase);
+#endif
+
+
+
+	/* make fnumber -> increment counter table */
+	for( i = 0 ; i < 1024; i++ )
+	{
+		/* OPLL (YM2413) phase increment counter = 18bit */
+
+		chip->fn_tab[i] = (UINT32)( (double)i * 64 * chip->freqbase * (1<<(FREQ_SH-10)) ); /* -10 because chip works with 10.10 fixed point, while we use 16.16 */
+#if 0
+		logerror("ym2413.c: fn_tab[%4i] = %08x (dec=%8i)\n",
+				 i, chip->fn_tab[i]>>6, chip->fn_tab[i]>>6 );
+#endif
+	}
+
+#if 0
+	for( i=0 ; i < 16 ; i++ )
+	{
+		logerror("ym2413.c: sl_tab[%i] = %08x\n", i, sl_tab[i] );
+	}
+	for( i=0 ; i < 8 ; i++ )
+	{
+		int j;
+		logerror("ym2413.c: ksl_tab[oct=%2i] =",i);
+		for (j=0; j<16; j++)
+		{
+			logerror("%08x ", ksl_tab[i*16+j] );
+		}
+		logerror("\n");
+	}
+#endif
+
+
+	/* Amplitude modulation: 27 output levels (triangle waveform); 1 level takes one of: 192, 256 or 448 samples */
+	/* One entry from LFO_AM_TABLE lasts for 64 samples */
+	chip->lfo_am_inc = (UINT32) ((1.0 / 64.0 ) * (1<<LFO_SH) * chip->freqbase);
+
+	/* Vibrato: 8 output levels (triangle waveform); 1 level takes 1024 samples */
+	chip->lfo_pm_inc = (UINT32) ((1.0 / 1024.0) * (1<<LFO_SH) * chip->freqbase);
+
+	/*logerror ("chip->lfo_am_inc = %8x ; chip->lfo_pm_inc = %8x\n", chip->lfo_am_inc, chip->lfo_pm_inc);*/
+
+	/* Noise generator: a step takes 1 sample */
+	chip->noise_f = (UINT32) ((1.0 / 1.0) * (1<<FREQ_SH) * chip->freqbase);
+	/*logerror("YM2413init noise_f=%8x\n", chip->noise_f);*/
+
+	chip->eg_timer_add  = (UINT32) ((1<<EG_SH)  * chip->freqbase);
+	chip->eg_timer_overflow = ( 1 ) * (1<<EG_SH);
+	/*logerror("YM2413init eg_timer_add=%8x eg_timer_overflow=%8x\n", chip->eg_timer_add, chip->eg_timer_overflow);*/
+}
+
+INLINE void KEY_ON(OPLL_SLOT *SLOT, UINT32 key_set)
+{
+	if( !SLOT->key )
+	{
+		/* do NOT restart Phase Generator (verified on real YM2413)*/
+		/* phase -> Dump */
+		SLOT->state = EG_DMP;
+	}
+	SLOT->key |= key_set;
+}
+
+INLINE void KEY_OFF(OPLL_SLOT *SLOT, UINT32 key_clr)
+{
+	if( SLOT->key )
+	{
+		SLOT->key &= key_clr;
+
+		if( !SLOT->key )
+		{
+			/* phase -> Release */
+			if (SLOT->state>EG_REL)
+				SLOT->state = EG_REL;
+		}
+	}
+}
+
+/* update phase increment counter of operator (also update the EG rates if necessary) */
+static INLINE void CALC_FCSLOT(OPLL_CH *CH,OPLL_SLOT *SLOT)
+{
+	int ksr;
+	UINT32 SLOT_rs;
+	UINT32 SLOT_dp;
+
+	/* (frequency) phase increment counter */
+	SLOT->freq = CH->fc * SLOT->mul;
+	ksr = CH->kcode >> SLOT->KSR;
+
+	if( SLOT->ksr != ksr )
+	{
+		SLOT->ksr = ksr;
+
+		/* calculate envelope generator rates */
+		if ((SLOT->ar + SLOT->ksr) < 16+62)
+		{
+			SLOT->eg_sh_ar  = eg_rate_shift [SLOT->ar + SLOT->ksr ];
+			SLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ];
+		}
+		else
+		{
+			SLOT->eg_sh_ar  = 0;
+			SLOT->eg_sel_ar = 13*RATE_STEPS;
+		}
+		SLOT->eg_sh_dr  = eg_rate_shift [SLOT->dr + SLOT->ksr ];
+		SLOT->eg_sel_dr = eg_rate_select[SLOT->dr + SLOT->ksr ];
+		SLOT->eg_sh_rr  = eg_rate_shift [SLOT->rr + SLOT->ksr ];
+		SLOT->eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr ];
+
+	}
+
+	if (CH->sus)
+		SLOT_rs  = 16 + (5<<2);
+	else
+		SLOT_rs  = 16 + (7<<2);
+
+	SLOT->eg_sh_rs  = eg_rate_shift [SLOT_rs + SLOT->ksr ];
+	SLOT->eg_sel_rs = eg_rate_select[SLOT_rs + SLOT->ksr ];
+
+	SLOT_dp  = 16 + (13<<2);
+	SLOT->eg_sh_dp  = eg_rate_shift [SLOT_dp + SLOT->ksr ];
+	SLOT->eg_sel_dp = eg_rate_select[SLOT_dp + SLOT->ksr ];
+}
+
+/* set multi,am,vib,EG-TYP,KSR,mul */
+static INLINE void set_mul(YM2413 *chip,int slot,int v)
+{
+	OPLL_CH   *CH   = &chip->P_CH[slot/2];
+	OPLL_SLOT *SLOT = &CH->SLOT[slot&1];
+
+	SLOT->mul     = mul_tab[v&0x0f];
+	SLOT->KSR     = (v&0x10) ? 0 : 2;
+	SLOT->eg_type = (v&0x20);
+	SLOT->vib     = (v&0x40);
+	SLOT->AMmask  = (v&0x80) ? ~0 : 0;
+	CALC_FCSLOT(CH,SLOT);
+}
+
+/* set ksl, tl */
+static INLINE void set_ksl_tl(YM2413 *chip,int chan,int v)
+{
+	int ksl;
+	OPLL_CH   *CH   = &chip->P_CH[chan];
+/* modulator */
+	OPLL_SLOT *SLOT = &CH->SLOT[SLOT1];
+
+	ksl = v>>6; /* 0 / 1.5 / 3.0 / 6.0 dB/OCT */
+
+	SLOT->ksl = ksl ? 3-ksl : 31;
+	SLOT->TL  = (v&0x3f)<<(ENV_BITS-2-7); /* 7 bits TL (bit 6 = always 0) */
+	SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);
+}
+
+/* set ksl , waveforms, feedback */
+static INLINE void set_ksl_wave_fb(YM2413 *chip,int chan,int v)
+{
+	int ksl;
+	OPLL_CH   *CH   = &chip->P_CH[chan];
+/* modulator */
+	OPLL_SLOT *SLOT = &CH->SLOT[SLOT1];
+	SLOT->wavetable = ((v&0x08)>>3)*SIN_LEN;
+	SLOT->fb_shift  = (v&7) ? (v&7) + 8 : 0;
+
+/*carrier*/
+	SLOT = &CH->SLOT[SLOT2];
+	ksl = v>>6; /* 0 / 1.5 / 3.0 / 6.0 dB/OCT */
+
+	SLOT->ksl = ksl ? 3-ksl : 31;
+	SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);
+
+	SLOT->wavetable = ((v&0x10)>>4)*SIN_LEN;
+}
+
+/* set attack rate & decay rate  */
+static INLINE void set_ar_dr(YM2413 *chip,int slot,int v)
+{
+	OPLL_CH   *CH   = &chip->P_CH[slot/2];
+	OPLL_SLOT *SLOT = &CH->SLOT[slot&1];
+
+	SLOT->ar = (v>>4)  ? 16 + ((v>>4)  <<2) : 0;
+
+	if ((SLOT->ar + SLOT->ksr) < 16+62)
+	{
+		SLOT->eg_sh_ar  = eg_rate_shift [SLOT->ar + SLOT->ksr ];
+		SLOT->eg_sel_ar = eg_rate_select[SLOT->ar + SLOT->ksr ];
+	}
+	else
+	{
+		SLOT->eg_sh_ar  = 0;
+		SLOT->eg_sel_ar = 13*RATE_STEPS;
+	}
+
+	SLOT->dr    = (v&0x0f)? 16 + ((v&0x0f)<<2) : 0;
+	SLOT->eg_sh_dr  = eg_rate_shift [SLOT->dr + SLOT->ksr ];
+	SLOT->eg_sel_dr = eg_rate_select[SLOT->dr + SLOT->ksr ];
+}
+
+/* set sustain level & release rate */
+static INLINE void set_sl_rr(YM2413 *chip,int slot,int v)
+{
+	OPLL_CH   *CH   = &chip->P_CH[slot/2];
+	OPLL_SLOT *SLOT = &CH->SLOT[slot&1];
+
+	SLOT->sl  = sl_tab[ v>>4 ];
+
+	SLOT->rr  = (v&0x0f)? 16 + ((v&0x0f)<<2) : 0;
+	SLOT->eg_sh_rr  = eg_rate_shift [SLOT->rr + SLOT->ksr ];
+	SLOT->eg_sel_rr = eg_rate_select[SLOT->rr + SLOT->ksr ];
+}
+
+static void load_instrument(YM2413 *chip, UINT32 chan, UINT32 slot, UINT8* inst )
+{
+	set_mul			(chip, slot,   inst[0]);
+	set_mul			(chip, slot+1, inst[1]);
+	set_ksl_tl		(chip, chan,   inst[2]);
+	set_ksl_wave_fb	(chip, chan,   inst[3]);
+	set_ar_dr		(chip, slot,   inst[4]);
+	set_ar_dr		(chip, slot+1, inst[5]);
+	set_sl_rr		(chip, slot,   inst[6]);
+	set_sl_rr		(chip, slot+1, inst[7]);
+}
+static void update_instrument_zero(YM2413 *chip, UINT8 r )
+{
+	UINT8* inst = &chip->inst_tab[0][0]; /* point to user instrument */
+	UINT32 chan;
+	UINT32 chan_max;
+
+	chan_max = 9;
+	if (chip->rhythm & 0x20)
+		chan_max=6;
+
+	switch(r)
+	{
+	case 0:
+		for (chan=0; chan<chan_max; chan++)
+		{
+			if ((chip->instvol_r[chan]&0xf0)==0)
+			{
+				set_mul			(chip, chan*2, inst[0]);
+			}
+		}
+        break;
+	case 1:
+		for (chan=0; chan<chan_max; chan++)
+		{
+			if ((chip->instvol_r[chan]&0xf0)==0)
+			{
+				set_mul			(chip, chan*2+1,inst[1]);
+			}
+		}
+        break;
+	case 2:
+		for (chan=0; chan<chan_max; chan++)
+		{
+			if ((chip->instvol_r[chan]&0xf0)==0)
+			{
+				set_ksl_tl		(chip, chan,   inst[2]);
+			}
+		}
+        break;
+	case 3:
+		for (chan=0; chan<chan_max; chan++)
+		{
+			if ((chip->instvol_r[chan]&0xf0)==0)
+			{
+				set_ksl_wave_fb	(chip, chan,   inst[3]);
+			}
+		}
+        break;
+	case 4:
+		for (chan=0; chan<chan_max; chan++)
+		{
+			if ((chip->instvol_r[chan]&0xf0)==0)
+			{
+				set_ar_dr		(chip, chan*2, inst[4]);
+			}
+		}
+        break;
+	case 5:
+		for (chan=0; chan<chan_max; chan++)
+		{
+			if ((chip->instvol_r[chan]&0xf0)==0)
+			{
+				set_ar_dr		(chip, chan*2+1,inst[5]);
+			}
+		}
+        break;
+	case 6:
+		for (chan=0; chan<chan_max; chan++)
+		{
+			if ((chip->instvol_r[chan]&0xf0)==0)
+			{
+				set_sl_rr		(chip, chan*2, inst[6]);
+			}
+		}
+        break;
+	case 7:
+		for (chan=0; chan<chan_max; chan++)
+		{
+			if ((chip->instvol_r[chan]&0xf0)==0)
+			{
+				set_sl_rr		(chip, chan*2+1,inst[7]);
+			}
+		}
+        break;
+    }
+}
+
+/* write a value v to register r on chip chip */
+static void OPLLWriteReg(YM2413 *chip, int r, int v)
+{
+	OPLL_CH *CH;
+	OPLL_SLOT *SLOT;
+	UINT8 *inst;
+	int chan;
+	int slot;
+
+	/* adjust bus to 8 bits */
+	r &= 0xff;
+	v &= 0xff;
+
+
+	switch(r&0xf0)
+	{
+	case 0x00:	/* 00-0f:control */
+	{
+		switch(r&0x0f)
+		{
+		case 0x00:	/* AM/VIB/EGTYP/KSR/MULTI (modulator) */
+		case 0x01:	/* AM/VIB/EGTYP/KSR/MULTI (carrier) */
+		case 0x02:	/* Key Scale Level, Total Level (modulator) */
+		case 0x03:	/* Key Scale Level, carrier waveform, modulator waveform, Feedback */
+		case 0x04:	/* Attack, Decay (modulator) */
+		case 0x05:	/* Attack, Decay (carrier) */
+		case 0x06:	/* Sustain, Release (modulator) */
+		case 0x07:	/* Sustain, Release (carrier) */
+			chip->inst_tab[0][r & 0x07] = v;
+			update_instrument_zero(chip,r&7);
+		break;
+
+		case 0x0e:	/* x, x, r,bd,sd,tom,tc,hh */
+		{
+			if(v&0x20)
+			{
+				if ((chip->rhythm&0x20)==0)
+				/*rhythm off to on*/
+				{
+					logerror("YM2413: Rhythm mode enable\n");
+
+	/* Load instrument settings for channel seven(chan=6 since we're zero based). (Bass drum) */
+					chan = 6;
+					inst = &chip->inst_tab[16][0];
+					slot = chan*2;
+
+					load_instrument(chip, chan, slot, inst);
+
+	/* Load instrument settings for channel eight. (High hat and snare drum) */
+					chan = 7;
+					inst = &chip->inst_tab[17][0];
+					slot = chan*2;
+
+					load_instrument(chip, chan, slot, inst);
+
+					CH   = &chip->P_CH[chan];
+					SLOT = &CH->SLOT[SLOT1]; /* modulator envelope is HH */
+					SLOT->TL  = ((chip->instvol_r[chan]>>4)<<2)<<(ENV_BITS-2-7); /* 7 bits TL (bit 6 = always 0) */
+					SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);
+
+	/* Load instrument settings for channel nine. (Tom-tom and top cymbal) */
+					chan = 8;
+					inst = &chip->inst_tab[18][0];
+					slot = chan*2;
+
+					load_instrument(chip, chan, slot, inst);
+
+					CH   = &chip->P_CH[chan];
+					SLOT = &CH->SLOT[SLOT1]; /* modulator envelope is TOM */
+					SLOT->TL  = ((chip->instvol_r[chan]>>4)<<2)<<(ENV_BITS-2-7); /* 7 bits TL (bit 6 = always 0) */
+					SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);
+				}
+				/* BD key on/off */
+				if(v&0x10)
+				{
+					KEY_ON (&chip->P_CH[6].SLOT[SLOT1], 2);
+					KEY_ON (&chip->P_CH[6].SLOT[SLOT2], 2);
+				}
+				else
+				{
+					KEY_OFF(&chip->P_CH[6].SLOT[SLOT1],~2);
+					KEY_OFF(&chip->P_CH[6].SLOT[SLOT2],~2);
+				}
+				/* HH key on/off */
+				if(v&0x01) KEY_ON (&chip->P_CH[7].SLOT[SLOT1], 2);
+				else       KEY_OFF(&chip->P_CH[7].SLOT[SLOT1],~2);
+				/* SD key on/off */
+				if(v&0x08) KEY_ON (&chip->P_CH[7].SLOT[SLOT2], 2);
+				else       KEY_OFF(&chip->P_CH[7].SLOT[SLOT2],~2);
+				/* TOM key on/off */
+				if(v&0x04) KEY_ON (&chip->P_CH[8].SLOT[SLOT1], 2);
+				else       KEY_OFF(&chip->P_CH[8].SLOT[SLOT1],~2);
+				/* TOP-CY key on/off */
+				if(v&0x02) KEY_ON (&chip->P_CH[8].SLOT[SLOT2], 2);
+				else       KEY_OFF(&chip->P_CH[8].SLOT[SLOT2],~2);
+			}
+			else
+			{
+				if ((chip->rhythm&0x20)==1)
+				/*rhythm on to off*/
+				{
+					logerror("YM2413: Rhythm mode disable\n");
+	/* Load instrument settings for channel seven(chan=6 since we're zero based).*/
+					chan = 6;
+					inst = &chip->inst_tab[chip->instvol_r[chan]>>4][0];
+					slot = chan*2;
+
+					load_instrument(chip, chan, slot, inst);
+
+	/* Load instrument settings for channel eight.*/
+					chan = 7;
+					inst = &chip->inst_tab[chip->instvol_r[chan]>>4][0];
+					slot = chan*2;
+
+					load_instrument(chip, chan, slot, inst);
+
+	/* Load instrument settings for channel nine.*/
+					chan = 8;
+					inst = &chip->inst_tab[chip->instvol_r[chan]>>4][0];
+					slot = chan*2;
+
+					load_instrument(chip, chan, slot, inst);
+				}
+				/* BD key off */
+				KEY_OFF(&chip->P_CH[6].SLOT[SLOT1],~2);
+				KEY_OFF(&chip->P_CH[6].SLOT[SLOT2],~2);
+				/* HH key off */
+				KEY_OFF(&chip->P_CH[7].SLOT[SLOT1],~2);
+				/* SD key off */
+				KEY_OFF(&chip->P_CH[7].SLOT[SLOT2],~2);
+				/* TOM key off */
+				KEY_OFF(&chip->P_CH[8].SLOT[SLOT1],~2);
+				/* TOP-CY off */
+				KEY_OFF(&chip->P_CH[8].SLOT[SLOT2],~2);
+			}
+			chip->rhythm  = v&0x3f;
+		}
+		break;
+		}
+	}
+	break;
+
+	case 0x10:
+	case 0x20:
+	{
+		int block_fnum;
+
+		chan = r&0x0f;
+
+		if (chan >= 9)
+			chan -= 9;	/* verified on real YM2413 */
+
+		CH = &chip->P_CH[chan];
+
+		if(r&0x10)
+		{	/* 10-18: FNUM 0-7 */
+			block_fnum  = (CH->block_fnum&0x0f00) | v;
+		}
+		else
+		{	/* 20-28: suson, keyon, block, FNUM 8 */
+			block_fnum = ((v&0x0f)<<8) | (CH->block_fnum&0xff);
+
+			if(v&0x10)
+			{
+				KEY_ON (&CH->SLOT[SLOT1], 1);
+				KEY_ON (&CH->SLOT[SLOT2], 1);
+			}
+			else
+			{
+				KEY_OFF(&CH->SLOT[SLOT1],~1);
+				KEY_OFF(&CH->SLOT[SLOT2],~1);
+			}
+
+
+			/* if (CH->sus!=(v&0x20))
+				logerror("chan=%i sus=%2x\n",chan,v&0x20); */
+
+			CH->sus = v & 0x20;
+		}
+		/* update */
+		if(CH->block_fnum != (unsigned) block_fnum)
+		{
+			UINT8 block;
+
+			CH->block_fnum = block_fnum;
+
+			/* BLK 2,1,0 bits -> bits 3,2,1 of kcode, FNUM MSB -> kcode LSB */
+			CH->kcode    = (block_fnum&0x0f00)>>8;
+
+			CH->ksl_base = ksl_tab[block_fnum>>5];
+
+			block_fnum   = block_fnum * 2;
+			block        = (block_fnum&0x1c00) >> 10;
+			CH->fc       = chip->fn_tab[block_fnum&0x03ff] >> (7-block);
+
+			/* refresh Total Level in both SLOTs of this channel */
+			CH->SLOT[SLOT1].TLL = CH->SLOT[SLOT1].TL + (CH->ksl_base>>CH->SLOT[SLOT1].ksl);
+			CH->SLOT[SLOT2].TLL = CH->SLOT[SLOT2].TL + (CH->ksl_base>>CH->SLOT[SLOT2].ksl);
+
+			/* refresh frequency counter in both SLOTs of this channel */
+			CALC_FCSLOT(CH,&CH->SLOT[SLOT1]);
+			CALC_FCSLOT(CH,&CH->SLOT[SLOT2]);
+		}
+	}
+	break;
+
+	case 0x30:	/* inst 4 MSBs, VOL 4 LSBs */
+	{
+		UINT8 old_instvol;
+
+		chan = r&0x0f;
+
+		if (chan >= 9)
+			chan -= 9;	/* verified on real YM2413 */
+
+		old_instvol = chip->instvol_r[chan];
+		chip->instvol_r[chan] = v;	/* store for later use */
+
+		CH   = &chip->P_CH[chan];
+		SLOT = &CH->SLOT[SLOT2]; /* carrier */
+		SLOT->TL  = ((v&0x0f)<<2)<<(ENV_BITS-2-7); /* 7 bits TL (bit 6 = always 0) */
+		SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);
+
+
+		/*check wether we are in rhythm mode and handle instrument/volume register accordingly*/
+		if ((chan>=6) && (chip->rhythm&0x20))
+		{
+			/* we're in rhythm mode*/
+
+			if (chan>=7) /* only for channel 7 and 8 (channel 6 is handled in usual way)*/
+			{
+				SLOT = &CH->SLOT[SLOT1]; /* modulator envelope is HH(chan=7) or TOM(chan=8) */
+				SLOT->TL  = ((chip->instvol_r[chan]>>4)<<2)<<(ENV_BITS-2-7); /* 7 bits TL (bit 6 = always 0) */
+				SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);
+			}
+		}
+		else
+		{
+			if ( (old_instvol&0xf0) == (v&0xf0) )
+				return;
+
+			inst = &chip->inst_tab[chip->instvol_r[chan]>>4][0];
+			slot = chan*2;
+
+			load_instrument(chip, chan, slot, inst);
+
+		#if 0
+			logerror("YM2413: chan#%02i inst=%02i:  (r=%2x, v=%2x)\n",chan,v>>4,r,v);
+			logerror("  0:%2x  1:%2x\n",inst[0],inst[1]);	logerror("  2:%2x  3:%2x\n",inst[2],inst[3]);
+			logerror("  4:%2x  5:%2x\n",inst[4],inst[5]);	logerror("  6:%2x  7:%2x\n",inst[6],inst[7]);
+		#endif
+		}
+	}
+	break;
+
+	default:
+	break;
+	}
+}
+
+/* lock/unlock for common table */
+static void OPLLResetChip(YM2413 *chip)
+{
+	int c,s;
+	int i;
+
+	chip->eg_timer = 0;
+	chip->eg_cnt   = 0;
+
+	chip->noise_rng = 1;	/* noise shift register */
+
+	chip->mask = 0;
+
+	/* setup instruments table */
+	if (!chip->chip_type)
+	{
+		for (i=0; i<19; i++)
+		{
+			for (c=0; c<8; c++)
+			{
+				chip->inst_tab[i][c] = table[i][c];
+			}
+		}
+	}
+	else
+	{
+		memset( &chip->inst_tab, 0, sizeof(chip->inst_tab) );
+
+		for (i=0; i<15; i++)
+		{
+			for (c=0; c<8; c++)
+			{
+				chip->inst_tab[i+1][c] = table_vrc7[i][c];
+			}
+		}
+	}
+
+
+	/* reset with register write */
+	OPLLWriteReg(chip,0x0f,0); /*test reg*/
+	for(i = 0x3f ; i >= 0x10 ; i-- ) OPLLWriteReg(chip,i,0x00);
+
+	/* reset operator parameters */
+	for( c = 0 ; c < 9 ; c++ )
+	{
+		OPLL_CH *CH = &chip->P_CH[c];
+		for(s = 0 ; s < 2 ; s++ )
+		{
+			/* wave table */
+			CH->SLOT[s].wavetable = 0;
+			CH->SLOT[s].state     = EG_OFF;
+			CH->SLOT[s].volume    = MAX_ATT_INDEX;
+		}
+	}
+}
+
+/* Create one of virtual YM2413 */
+/* 'clock' is chip clock in Hz  */
+/* 'rate'  is sampling rate  */
+static void OPLLCreate(YM2413 *ptr, int clock, int rate, int type)
+{
+	YM2413 *chip;
+	int state_size;
+
+	init_tables();
+
+	/* calculate chip state size */
+	state_size  = sizeof(YM2413);
+
+	/* clear */
+	memset(ptr,0,state_size);
+
+	chip  = (YM2413 *)ptr;
+
+	chip->clock = clock;
+	chip->rate  = rate;
+
+	chip->chip_type = type;
+
+	chip->mask = 0;
+
+	/* init global tables */
+	OPLL_initalize(chip);
+
+	/* reset chip */
+	OPLLResetChip(chip);
+}
+
+/* YM3812 I/O interface */
+static void OPLLWrite(YM2413 *chip,int a,int v)
+{
+	if( !(a&1) )
+	{	/* address port */
+		chip->address = v & 0xff;
+	}
+	else
+	{	/* data port */
+		OPLLWriteReg(chip,chip->address,v);
+	}
+}
+
+static unsigned char OPLLRead(YM2413 *chip,int a)
+{
+	if( !(a&1) )
+	{
+		/* status port */
+		return chip->status;
+	}
+	return 0xff;
+}
+
+void ym2413_init(YM2413 *chip, int clock, int rate, int type)
+{
+	/* emulator create */
+	OPLLCreate(chip, clock, rate, type);
+}
+
+void ym2413_reset_chip(YM2413 *chip)
+{
+	OPLLResetChip(chip);
+}
+
+void ym2413_write(YM2413 *chip, int a, int v)
+{
+	OPLLWrite(chip, a, v);
+}
+
+unsigned char ym2413_read(YM2413 *chip, int a)
+{
+	return OPLLRead(chip, a) & 0x03 ;
+}
+
+/*
+** Generate samples for one of the YM2413's
+**
+** 'which' is the virtual YM2413 number
+** '*buffer' is the output buffer pointer
+** 'length' is the number of samples that should be generated
+*/
+void ym2413_update_one(YM2413 *chip, SAMP **buffers, int length)
+{
+	UINT8		rhythm = chip->rhythm&0x20;
+	SAMP		*bufMO = buffers[0];
+	SAMP		*bufRO = buffers[1];
+
+	int i,j;
+
+	chip->SLOT7_1 = &chip->P_CH[7].SLOT[SLOT1];
+	chip->SLOT7_2 = &chip->P_CH[7].SLOT[SLOT2];
+	chip->SLOT8_1 = &chip->P_CH[8].SLOT[SLOT1];
+	chip->SLOT8_2 = &chip->P_CH[8].SLOT[SLOT2];
+
+
+	for( i=0; i < length ; i++ )
+	{
+		int mo,ro;
+
+		chip->output[0] = 0;
+		chip->output[1] = 0;
+
+		advance_lfo(chip);
+
+#if 0
+		/* FM part */
+		chan_calc(chip,&chip->P_CH[0]);
+/* SAVE_SEPARATE_CHANNEL(0); */
+		chan_calc(chip,&chip->P_CH[1]);
+		chan_calc(chip,&chip->P_CH[2]);
+		chan_calc(chip,&chip->P_CH[3]);
+		chan_calc(chip,&chip->P_CH[4]);
+		chan_calc(chip,&chip->P_CH[5]);
+#else
+		for ( j=0; j < 6; j++ )
+		{
+			if (!(chip->mask & OPLL_MASK_CH(j))) chan_calc(chip, &chip->P_CH[j]);
+		}
+#endif
+
+		if(!rhythm)
+		{
+#if 0
+			chan_calc(chip,&chip->P_CH[6]);
+			chan_calc(chip,&chip->P_CH[7]);
+			chan_calc(chip,&chip->P_CH[8]);
+#else
+			for ( j=6; j < 9; j++ )
+			{
+				if (!(chip->mask & OPLL_MASK_CH(j))) chan_calc(chip, &chip->P_CH[j]);
+			}
+#endif
+		}
+		else		/* Rhythm part */
+		{
+			if ( ( chip->mask & OPLL_MASK_RHYTHM ) != OPLL_MASK_RHYTHM )
+				rhythm_calc(chip,&chip->P_CH[0], (chip->noise_rng>>0)&1 );
+		}
+
+		mo = chip->output[0];
+		ro = chip->output[1];
+
+		mo >>= FINAL_SH;
+		ro >>= FINAL_SH;
+
+		/* limit check */
+		mo = limit( mo , MAXOUT, MINOUT );
+		ro = limit( ro , MAXOUT, MINOUT );
+
+		/* store to sound buffer */
+		bufMO[i] = mo;
+		bufRO[i] = ro;
+
+		advance(chip);
+	}
+
+}
+
+void ym2413_advance_lfo(YM2413 *chip)
+{
+	advance_lfo(chip);
+}
+
+void ym2413_advance(YM2413 *chip)
+{
+	advance(chip);
+}
+
+SAMP ym2413_calcch(YM2413 *chip, int ch)
+{
+	int output;
+
+	chip->output[0] = 0;
+	chip->output[1] = 0;
+
+	if (ch >= 0 && ch < 6) chan_calc( chip, &chip->P_CH[ch] );
+	else if (ch >= 6 && ch < 9)
+	{
+		UINT8		rhythm = chip->rhythm&0x20;
+		if (!rhythm) chan_calc( chip, &chip->P_CH[ch] );
+		else if (ch == 6) rhythm_calc(chip,&chip->P_CH[0], (chip->noise_rng>>0)&1 );
+	}
+
+	output = chip->output[0];
+	output += chip->output[1];
+
+	return output;
+}
+
+void * ym2413_get_inst0(YM2413 *chip)
+{
+	return &chip->inst_tab;
+}
+
+void ym2413_set_mask(YM2413 *chip, UINT32 mask)
+{
+	chip->mask = mask;
+}
Index: apps/codecs/libnsf/nes_vrc7_apu.h
===================================================================
--- apps/codecs/libnsf/nes_vrc7_apu.h	(revision 0)
+++ apps/codecs/libnsf/nes_vrc7_apu.h	(revision 0)
@@ -0,0 +1,53 @@
+// Konami VRC7 sound chip emulator
+
+#ifndef NES_VRC7_APU_H
+#define NES_VRC7_APU_H
+
+#include "blargg_common.h"
+#include "blip_buffer.h"
+
+#include "ym2413.h"
+
+enum { vrc7_osc_count = 6 };
+
+struct Vrc7_Osc
+{
+	uint8_t regs [3];
+	struct Blip_Buffer* output;
+	int last_amp;
+};
+
+struct mono_t {
+	struct Blip_Buffer* output;
+	int last_amp;
+};
+
+struct Nes_Vrc7_Apu {
+	struct Vrc7_Osc oscs [vrc7_osc_count];
+	YM2413 opll;
+	int addr;
+	blip_time_t next_time;
+	struct mono_t mono;
+	struct Blip_Synth synth;
+};
+
+// See Nes_Apu.h for reference
+void Vrc7_init( struct Nes_Vrc7_Apu* this );
+void Vrc7_reset( struct Nes_Vrc7_Apu* this );
+void Vrc7_end_frame( struct Nes_Vrc7_Apu* this, blip_time_t ); ICODE_ATTR
+
+void Vrc7_write_reg( struct Nes_Vrc7_Apu* this, int reg ); ICODE_ATTR
+void Vrc7_write_data( struct Nes_Vrc7_Apu* this, blip_time_t, int data ); ICODE_ATTR
+
+void output_changed( struct Nes_Vrc7_Apu* this );
+static inline void Vrc7_set_output( struct Nes_Vrc7_Apu* this, int i, struct Blip_Buffer* buf )
+{
+	assert( (unsigned) i < vrc7_osc_count );
+	this->oscs [i].output = buf;
+	output_changed( this );
+}
+
+// DB2LIN_AMP_BITS == 11, * 2
+static inline void Vrc7_volume( struct Nes_Vrc7_Apu* this, double v ) { Synth_volume( &this->synth, 1.0 / 3 / 4096 * v ); }
+
+#endif
Index: apps/codecs/libnsf/nes_cpu.h
===================================================================
--- apps/codecs/libnsf/nes_cpu.h	(revision 0)
+++ apps/codecs/libnsf/nes_cpu.h	(revision 0)
@@ -0,0 +1,106 @@
+// NES cpu emulator
+
+// Game_Music_Emu 0.6-pre
+#ifndef NES_CPU_H
+#define NES_CPU_H
+
+#include "blargg_source.h"
+#include "blargg_common.h"
+
+typedef int nes_time_t;
+typedef int addr_t;
+
+enum { page_bits = 11 };
+enum { page_size = 1 << page_bits };
+enum { page_count = 0x10000 >> page_bits };
+
+// Unmapped page should be filled with this
+enum { halt_opcode = 0x22 };
+
+enum { future_time = INT_MAX/2 + 1 };
+enum { irq_inhibit_mask = 0x04 };
+	
+// Can read this many bytes past end of a page
+enum { cpu_padding = 8 };
+
+struct registers_t {
+	uint16_t pc;
+	uint8_t a;
+	uint8_t x;
+	uint8_t y;
+	uint8_t flags;
+	uint8_t sp;
+};
+
+struct cpu_state_t {
+	uint8_t const* code_map [page_count + 1];
+	nes_time_t base;
+	int time;
+};
+
+struct Nes_Cpu {
+	// NES 6502 registers. NOT kept updated during emulation.
+	struct registers_t r;
+	
+	struct cpu_state_t* cpu_state; // points to cpu_state_ or a local copy
+	struct cpu_state_t cpu_state_;
+	nes_time_t irq_time;
+	nes_time_t end_time;
+};
+
+static inline void Cpu_init( struct Nes_Cpu* this ) { this->cpu_state = &this->cpu_state_; }
+
+// Clears registers and maps all pages to unmapped_page
+void Cpu_reset( struct Nes_Cpu* this, void const* unmapped_page );
+	
+// Maps code memory (memory accessed via the program counter). Start and size
+// must be multiple of page_size. If mirror_size is non-zero, the first
+// mirror_size bytes are repeated over the range. mirror_size must be a
+// multiple of page_size.
+void Cpu_map_code( struct Nes_Cpu* this, addr_t start, int size, void const* code, int mirror_size );
+	
+// Time of beginning of next instruction to be executed
+static inline nes_time_t Cpu_time( struct Nes_Cpu* this ) { return this->cpu_state->time + this->cpu_state->base; }
+static inline void Cpu_set_time( struct Nes_Cpu* this, nes_time_t t ) { this->cpu_state->time = t - this->cpu_state->base; }
+static inline void Cpu_adjust_time( struct Nes_Cpu* this, int delta ) { this->cpu_state->time += delta; }
+	
+// Clocks past end (negative if before)
+static inline int Cpu_time_past_end( struct Nes_Cpu* this ) { return this->cpu_state->time; }
+			
+#define NES_CPU_PAGE( addr ) ((unsigned) (addr) >> page_bits)
+
+#ifdef BLARGG_NONPORTABLE
+	#define NES_CPU_OFFSET( addr ) (addr)
+#else
+	#define NES_CPU_OFFSET( addr ) ((addr) & (page_size - 1))
+#endif
+
+// Accesses emulated memory as cpu does
+static inline uint8_t const* Cpu_get_code( struct Nes_Cpu* this, addr_t addr )
+{
+	return this->cpu_state_.code_map [NES_CPU_PAGE( addr )] + NES_CPU_OFFSET( addr );
+}
+
+static inline void Cpu_update_end_time( struct Nes_Cpu* this, nes_time_t end, nes_time_t irq )
+{
+	if ( end > irq && !(this->r.flags & irq_inhibit_mask) )
+		end = irq;
+	
+	this->cpu_state->time += this->cpu_state->base - end;
+	this->cpu_state->base = end;
+}
+
+// Time of next IRQ
+static inline void Cpu_set_irq_time( struct Nes_Cpu* this, nes_time_t t )
+{
+	this->irq_time = t;
+	Cpu_update_end_time( this, this->end_time, t );
+}
+
+static inline void Cpu_set_end_time( struct Nes_Cpu* this, nes_time_t t )
+{
+	this->end_time = t;
+	Cpu_update_end_time( this, t, this->irq_time );
+}   
+
+#endif
Index: apps/codecs/libnsf/ym2413.h
===================================================================
--- apps/codecs/libnsf/ym2413.h	(revision 0)
+++ apps/codecs/libnsf/ym2413.h	(revision 0)
@@ -0,0 +1,157 @@
+#pragma once
+
+#ifndef __YM2413_H__
+#define __YM2413_H__
+
+#include "blargg_common.h"
+#include "blargg_endian.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* select output bits size of output : 8 or 16 */
+#define SAMPLE_BITS 16
+
+/* compiler dependence */
+#ifndef __OSDCOMM_H__
+#define __OSDCOMM_H__
+typedef unsigned char	UINT8;   /* unsigned  8bit */
+typedef unsigned short	UINT16;  /* unsigned 16bit */
+typedef unsigned int	UINT32;  /* unsigned 32bit */
+typedef signed char		INT8;    /* signed  8bit   */
+typedef signed short	INT16;   /* signed 16bit   */
+typedef signed int		INT32;   /* signed 32bit   */
+
+typedef INT32           stream_sample_t;
+#endif
+
+typedef stream_sample_t SAMP;
+
+typedef struct{
+	UINT32	ar;			/* attack rate: AR<<2           */
+	UINT32	dr;			/* decay rate:  DR<<2           */
+	UINT32	rr;			/* release rate:RR<<2           */
+	UINT8	KSR;		/* key scale rate               */
+	UINT8	ksl;		/* keyscale level               */
+	UINT8	ksr;		/* key scale rate: kcode>>KSR   */
+	UINT8	mul;		/* multiple: mul_tab[ML]        */
+
+	/* Phase Generator */
+	UINT32	phase;		/* frequency counter            */
+	UINT32	freq;		/* frequency counter step       */
+	UINT8   fb_shift;	/* feedback shift value         */
+	INT32   op1_out[2];	/* slot1 output for feedback    */
+
+	/* Envelope Generator */
+	UINT8	eg_type;	/* percussive/nonpercussive mode*/
+	UINT8	state;		/* phase type                   */
+	UINT32	TL;			/* total level: TL << 2         */
+	INT32	TLL;		/* adjusted now TL              */
+	INT32	volume;		/* envelope counter             */
+	UINT32	sl;			/* sustain level: sl_tab[SL]    */
+
+	UINT8	eg_sh_dp;	/* (dump state)                 */
+	UINT8	eg_sel_dp;	/* (dump state)                 */
+	UINT8	eg_sh_ar;	/* (attack state)               */
+	UINT8	eg_sel_ar;	/* (attack state)               */
+	UINT8	eg_sh_dr;	/* (decay state)                */
+	UINT8	eg_sel_dr;	/* (decay state)                */
+	UINT8	eg_sh_rr;	/* (release state for non-perc.)*/
+	UINT8	eg_sel_rr;	/* (release state for non-perc.)*/
+	UINT8	eg_sh_rs;	/* (release state for perc.mode)*/
+	UINT8	eg_sel_rs;	/* (release state for perc.mode)*/
+
+	UINT32	key;		/* 0 = KEY OFF, >0 = KEY ON     */
+
+	/* LFO */
+	UINT32	AMmask;		/* LFO Amplitude Modulation enable mask */
+	UINT8	vib;		/* LFO Phase Modulation enable flag (active high)*/
+
+	/* waveform select */
+	unsigned int wavetable;
+} OPLL_SLOT;
+
+typedef struct{
+	OPLL_SLOT SLOT[2];
+	/* phase generator state */
+	UINT32  block_fnum;	/* block+fnum                   */
+	UINT32  fc;			/* Freq. freqement base         */
+	UINT32  ksl_base;	/* KeyScaleLevel Base step      */
+	UINT8   kcode;		/* key code (for key scaling)   */
+	UINT8   sus;		/* sus on/off (release speed in percussive mode)*/
+} OPLL_CH;
+
+/* chip state */
+typedef struct {
+	OPLL_CH	P_CH[9];				/* OPLL chips have 9 channels*/
+	UINT8	instvol_r[9];			/* instrument/volume (or volume/volume in percussive mode)*/
+
+	UINT32	eg_cnt;					/* global envelope generator counter    */
+	UINT32	eg_timer;				/* global envelope generator counter works at frequency = chipclock/72 */
+	UINT32	eg_timer_add;			/* step of eg_timer                     */
+	UINT32	eg_timer_overflow;		/* envelope generator timer overlfows every 1 sample (on real chip) */
+
+	UINT8	rhythm;					/* Rhythm mode                  */
+
+	/* LFO */
+	UINT32	lfo_am_cnt;
+	UINT32	lfo_am_inc;
+	UINT32	lfo_pm_cnt;
+	UINT32	lfo_pm_inc;
+
+	UINT32	noise_rng;				/* 23 bit noise shift register  */
+	UINT32	noise_p;				/* current noise 'phase'        */
+	UINT32	noise_f;				/* current noise period         */
+
+
+/* instrument settings */
+/*
+    0-user instrument
+    1-15 - fixed instruments
+    16 -bass drum settings
+    17,18 - other percussion instruments
+*/
+	UINT8 inst_tab[19][8];
+
+	UINT32	fn_tab[1024];			/* fnumber->increment counter   */
+
+	UINT8 address;					/* address register             */
+	UINT8 status;					/* status flag                  */
+
+	int clock;						/* master clock  (Hz)           */
+	int rate;						/* sampling rate (Hz)           */
+	double freqbase;				/* frequency base               */
+
+	/* work table */
+	OPLL_SLOT *SLOT7_1,*SLOT7_2,*SLOT8_1,*SLOT8_2;
+
+	signed int output[2];
+
+	UINT32	LFO_AM;
+	INT32	LFO_PM;
+
+	int chip_type;
+	UINT32 mask;
+} YM2413;
+
+
+void ym2413_init(YM2413 *chip, int clock, int rate, int type);
+void ym2413_reset_chip(YM2413 *chip);
+void ym2413_write(YM2413 *chip, int a, int v); ICODE_ATTR
+unsigned char ym2413_read(YM2413 *chip, int a); ICODE_ATTR
+void ym2413_update_one(YM2413 *chip, SAMP **buffers, int length); ICODE_ATTR
+
+void ym2413_advance_lfo(YM2413 *chip); ICODE_ATTR    /* call this once */
+SAMP ym2413_calcch(YM2413 *chip, int ch); ICODE_ATTR /* then call this for each channel */
+void ym2413_advance(YM2413 *chip); ICODE_ATTR        /* then call this */
+
+void * ym2413_get_inst0(YM2413 *chip); ICODE_ATTR
+
+void ym2413_set_mask(YM2413 *chip, UINT32 mask); ICODE_ATTR
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*__YM2413_H__*/
Index: apps/codecs/libnsf/nes_namco_apu.c
===================================================================
--- apps/codecs/libnsf/nes_namco_apu.c	(revision 0)
+++ apps/codecs/libnsf/nes_namco_apu.c	(revision 0)
@@ -0,0 +1,133 @@
+// Nes_Snd_Emu 0.1.8. http://www.slack.net/~ant/
+
+#include "nes_namco_apu.h"
+
+/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
+can redistribute it and/or modify it under the terms of the GNU Lesser
+General Public License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version. This
+module is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+details. You should have received a copy of the GNU Lesser General Public
+License along with this module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+void Namco_init( struct Nes_Namco_Apu* this )
+{
+	Synth_init( &this->synth );
+	
+	Namco_output( this, NULL );
+	Namco_volume( this, 1.0 );
+	Namco_reset( this );
+}
+
+void Namco_reset( struct Nes_Namco_Apu* this )
+{
+	this->last_time = 0;
+	this->addr_reg = 0;
+	
+	int i;
+	for ( i = 0; i < namco_reg_count; i++ )
+		this->reg [i] = 0;
+	
+	for ( i = 0; i < namco_osc_count; i++ )
+	{
+		struct Namco_Osc* osc = &this->oscs [i];
+		osc->delay = 0;
+		osc->last_amp = 0;
+		osc->wave_pos = 0;
+	}
+}
+
+void Namco_output( struct Nes_Namco_Apu* this, struct Blip_Buffer* buf )
+{
+	int i;
+	for ( i = 0; i < namco_osc_count; i++ )
+		Namco_osc_output( this, i, buf );
+}
+
+void Namco_end_frame( struct Nes_Namco_Apu* this, blip_time_t time )
+{
+	if ( time > this->last_time )
+		Namco_run_until( this, time );
+	
+	assert( this->last_time >= time );
+	this->last_time -= time;
+}
+
+void Namco_run_until( struct Nes_Namco_Apu* this, blip_time_t nes_end_time )
+{
+	int active_oscs = (this->reg [0x7F] >> 4 & 7) + 1;
+	int i;
+	for ( i = namco_osc_count - active_oscs; i < namco_osc_count; i++ )
+	{
+		struct Namco_Osc* osc = &this->oscs [i];
+		struct Blip_Buffer* output = osc->output;
+		if ( !output )
+			continue;
+		/* output->set_modified(); */
+		Blip_set_modified( output );
+		
+		blip_resampled_time_t time =
+				Blip_resampled_time( output, this->last_time ) + osc->delay;
+		blip_resampled_time_t end_time = Blip_resampled_time( output, nes_end_time );
+		osc->delay = 0;
+		if ( time < end_time )
+		{
+			const uint8_t* osc_reg = &this->reg [i * 8 + 0x40];
+			if ( !(osc_reg [4] & 0xE0) )
+				continue;
+			
+			int volume = osc_reg [7] & 15;
+			if ( !volume )
+				continue;
+			
+			blargg_long freq = (osc_reg [4] & 3) * 0x10000 + osc_reg [2] * 0x100L + osc_reg [0];
+			if ( freq < 64 * active_oscs )
+				continue; // prevent low frequencies from excessively delaying freq changes
+			blip_resampled_time_t period =
+					/* output->resampled_duration( 983040 ) / freq * active_oscs; */
+					Blip_resampled_duration( output, 983040 ) / freq * active_oscs;
+			
+			int wave_size = 32 - (osc_reg [4] >> 2 & 7) * 4;
+			if ( !wave_size )
+				continue;
+			
+			int last_amp = osc->last_amp;
+			int wave_pos = osc->wave_pos;
+			
+			do
+			{
+				// read wave sample
+				int addr = wave_pos + osc_reg [6];
+				int sample = this->reg [addr >> 1] >> (addr << 2 & 4);
+				wave_pos++;
+				sample = (sample & 15) * volume;
+				
+				// output impulse if amplitude changed
+				int delta = sample - last_amp;
+				if ( delta )
+				{
+					last_amp = sample;
+					Synth_offset_resampled( &this->synth, time, delta, output );
+				}
+				
+				// next sample
+				time += period;
+				if ( wave_pos >= wave_size )
+					wave_pos = 0;
+			}
+			while ( time < end_time );
+			
+			osc->wave_pos = wave_pos;
+			osc->last_amp = last_amp;
+		}
+		osc->delay = time - end_time;
+	}
+	
+	this->last_time = nes_end_time;
+}
+
Index: apps/codecs/libnsf/nes_oscs.c
===================================================================
--- apps/codecs/libnsf/nes_oscs.c	(revision 0)
+++ apps/codecs/libnsf/nes_oscs.c	(revision 0)
@@ -0,0 +1,583 @@
+// Nes_Snd_Emu 0.1.8. http://www.slack.net/~ant/
+
+#include "nes_apu.h"
+
+/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
+can redistribute it and/or modify it under the terms of the GNU Lesser
+General Public License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version. This
+module is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+details. You should have received a copy of the GNU Lesser General Public
+License along with this module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+// Nes_Osc
+
+void Osc_clock_length( struct Nes_Osc* this, int halt_mask )
+{
+	if ( this->length_counter && !(this->regs [0] & halt_mask) )
+		this->length_counter--;
+}
+
+// Nes_Square
+
+void Square_clock_envelope( struct Nes_Square* this )
+{
+	struct Nes_Osc* osc = &this->osc;
+	int period = osc->regs [0] & 15;
+	if ( osc->reg_written [3] ) {
+		osc->reg_written [3] = false;
+		this->env_delay = period;
+		this->envelope = 15;
+	}
+	else if ( --this->env_delay < 0 ) {
+		this->env_delay = period;
+		if ( this->envelope | (osc->regs [0] & 0x20) )
+			this->envelope = (this->envelope - 1) & 15;
+	}
+}
+
+int Square_volume( struct Nes_Square* this )
+{
+	struct Nes_Osc* osc = &this->osc;
+	return osc->length_counter == 0 ? 0 : (osc->regs [0] & 0x10) ? (osc->regs [0] & 15) : this->envelope;
+}
+
+void Square_clock_sweep( struct Nes_Square* this, int negative_adjust )
+{
+	struct Nes_Osc* osc = &this->osc;
+	int sweep = osc->regs [1];
+	
+	if ( --this->sweep_delay < 0 )
+	{
+		osc->reg_written [1] = true;
+		
+		int period = Osc_period( osc );
+		int shift = sweep & shift_mask;
+		if ( shift && (sweep & 0x80) && period >= 8 )
+		{
+			int offset = period >> shift;
+			
+			if ( sweep & negate_flag )
+				offset = negative_adjust - offset;
+			
+			if ( period + offset < 0x800 )
+			{
+				period += offset;
+				// rewrite period
+				osc->regs [2] = period & 0xFF;
+				osc->regs [3] = (osc->regs [3] & ~7) | ((period >> 8) & 7);
+			}
+		}
+	}
+	
+	if ( osc->reg_written [1] ) {
+		osc->reg_written [1] = false;
+		this->sweep_delay = (sweep >> 4) & 7;
+	}
+}
+
+// TODO: clean up
+inline nes_time_t Square_maintain_phase( struct Nes_Square* this, nes_time_t time, nes_time_t end_time,
+		nes_time_t timer_period )
+{
+	nes_time_t remain = end_time - time;
+	if ( remain > 0 )
+	{
+		int count = (remain + timer_period - 1) / timer_period;
+		this->phase = (this->phase + count) & (square_phase_range - 1);
+		time += (blargg_long) count * timer_period;
+	}
+	return time;
+}
+
+void Square_run( struct Nes_Square* this, nes_time_t time, nes_time_t end_time )
+{
+	struct Nes_Osc* osc = &this->osc;
+	const int period = Osc_period( osc );
+	const int timer_period = (period + 1) * 2;
+	
+	if ( !osc->output )
+	{
+		osc->delay = Square_maintain_phase( this, time + osc->delay, end_time, timer_period ) - end_time;
+		return;
+	}
+	
+	Blip_set_modified( osc->output );
+	
+	int offset = period >> (osc->regs [1] & shift_mask);
+	if ( osc->regs [1] & negate_flag )
+		offset = 0;
+	
+	const int volume = Square_volume( this );
+	if ( volume == 0 || period < 8 || (period + offset) >= 0x800 )
+	{
+		if ( osc->last_amp ) {
+			Synth_offset( this->synth, time, -osc->last_amp, osc->output );
+			osc->last_amp = 0;
+		}
+		
+		time += osc->delay;
+		time = Square_maintain_phase( this, time, end_time, timer_period );
+	}
+	else
+	{
+		// handle duty select
+		int duty_select = (osc->regs [0] >> 6) & 3;
+		int duty = 1 << duty_select; // 1, 2, 4, 2
+		int amp = 0;
+		if ( duty_select == 3 ) {
+			duty = 2; // negated 25%
+			amp = volume;
+		}
+		if ( this->phase < duty )
+			amp ^= volume;
+		
+		{
+			int delta = Osc_update_amp( osc, amp );
+			if ( delta )
+				Synth_offset( this->synth, time, delta, osc->output );
+		}
+		
+		time += osc->delay;
+		if ( time < end_time )
+		{
+			struct Blip_Buffer* const output = osc->output;
+			Synth* synth = this->synth;
+			int delta = amp * 2 - volume;
+			int phase = this->phase;
+			
+			do {
+				phase = (phase + 1) & (square_phase_range - 1);
+				if ( phase == 0 || phase == duty ) {
+					delta = -delta;
+					Synth_offset_inline( synth, time, delta, output );
+				}
+				time += timer_period;
+			}
+			while ( time < end_time );
+			
+			osc->last_amp = (delta + volume) >> 1;
+			this->phase = phase;
+		}
+	}
+	
+	osc->delay = time - end_time;
+}
+
+// Nes_Triangle
+
+void Triangle_clock_linear_counter( struct Nes_Triangle* this )
+{
+	struct Nes_Osc* osc = &this->osc;
+	if ( osc->reg_written [3] )
+		this->linear_counter = osc->regs [0] & 0x7F;
+	else if ( this->linear_counter )
+		this->linear_counter--;
+	
+	if ( !(osc->regs [0] & 0x80) )
+		osc->reg_written [3] = false;
+}
+
+inline int Triangle_calc_amp( struct Nes_Triangle* this )
+{
+	int amp = Triangle_phase_range - this->phase;
+	if ( amp < 0 )
+		amp = this->phase - (Triangle_phase_range + 1);
+	return amp;
+}
+
+// TODO: clean up
+inline nes_time_t Triangle_maintain_phase( struct Nes_Triangle* this, nes_time_t time, nes_time_t end_time,
+		nes_time_t timer_period )
+{
+	nes_time_t remain = end_time - time;
+	if ( remain > 0 )
+	{
+		int count = (remain + timer_period - 1) / timer_period;
+		this->phase = ((unsigned) this->phase + 1 - count) & (Triangle_phase_range * 2 - 1);
+		this->phase++;
+		time += (blargg_long) count * timer_period;
+	}
+	return time;
+}
+
+void Triangle_run( struct Nes_Triangle* this, nes_time_t time, nes_time_t end_time )
+{
+	struct Nes_Osc* osc = &this->osc;
+	const int timer_period = Osc_period( osc ) + 1;
+	if ( !osc->output )
+	{
+		time += osc->delay;
+		osc->delay = 0;
+		if ( osc->length_counter && this->linear_counter && timer_period >= 3 )
+			osc->delay = Triangle_maintain_phase( this, time, end_time, timer_period ) - end_time;
+		return;
+	}
+	
+	Blip_set_modified( osc->output );
+	
+	// to do: track phase when period < 3
+	// to do: Output 7.5 on dac when period < 2? More accurate, but results in more clicks.
+	
+	int delta = Osc_update_amp( osc, Triangle_calc_amp( this ) );
+	if ( delta )
+		Synth_offset( &this->synth, time, delta, osc->output );
+	
+	time += osc->delay;
+	if ( osc->length_counter == 0 || this->linear_counter == 0 || timer_period < 3 )
+	{
+		time = end_time;
+	}
+	else if ( time < end_time )
+	{
+		struct Blip_Buffer* const output = osc->output;
+		
+		int phase = this->phase;
+		int volume = 1;
+		if ( phase > Triangle_phase_range ) {
+			phase -= Triangle_phase_range;
+			volume = -volume;
+		}
+		
+		do {
+			if ( --phase == 0 ) {
+				phase = Triangle_phase_range;
+				volume = -volume;
+			}
+			else {
+				Synth_offset_inline( &this->synth, time, volume, output );
+			}
+			
+			time += timer_period;
+		}
+		while ( time < end_time );
+		
+		if ( volume < 0 )
+			phase += Triangle_phase_range;
+		this->phase = phase;
+		osc->last_amp = Triangle_calc_amp( this );
+ 	}
+	osc->delay = time - end_time;
+}
+
+// Nes_Dmc
+
+void Dmc_reset( struct Nes_Dmc* this )
+{
+	this->address = 0;
+	this->dac = 0;
+	this->buf = 0;
+	this->bits_remain = 1;
+	this->bits = 0;
+	this->buf_full = false;
+	this->silence = true;
+	this->next_irq = apu_no_irq;
+	this->irq_flag = false;
+	this->irq_enabled = false;
+	
+	Osc_reset( &this->osc );
+	this->period = 0x1AC;
+}
+
+void Dmc_recalc_irq( struct Nes_Dmc* this )
+{
+	struct Nes_Osc* osc = &this->osc;
+	nes_time_t irq = apu_no_irq;
+	if ( this->irq_enabled && osc->length_counter )
+		irq = this->apu->last_dmc_time + osc->delay +
+				((osc->length_counter - 1) * 8 + this->bits_remain - 1) * (nes_time_t) (this->period) + 1;
+	if ( irq != this->next_irq ) {
+		this->next_irq = irq;
+		Apu_irq_changed( this->apu );
+	}
+}
+
+int Dmc_count_reads( struct Nes_Dmc* this, nes_time_t time, nes_time_t* last_read )
+{
+	struct Nes_Osc* osc = &this->osc;
+	if ( last_read )
+		*last_read = time;
+	
+	if ( osc->length_counter == 0 )
+		return 0; // not reading
+	
+	nes_time_t first_read = Dmc_next_read_time( this );
+	nes_time_t avail = time - first_read;
+	if ( avail <= 0 )
+		return 0;
+	
+	int count = (avail - 1) / (this->period * 8) + 1;
+	if ( !(osc->regs [0] & loop_flag) && count > osc->length_counter )
+		count = osc->length_counter;
+	
+	if ( last_read )
+	{
+		*last_read = first_read + (count - 1) * (this->period * 8) + 1;
+		check( *last_read <= time );
+		check( count == count_reads( *last_read, NULL ) );
+		check( count - 1 == count_reads( *last_read - 1, NULL ) );
+	}
+	
+	return count;
+}
+
+static short const dmc_period_table [2] [16] ICONST_ATTR = {
+	{428, 380, 340, 320, 286, 254, 226, 214, // NTSC
+	190, 160, 142, 128, 106,  84,  72,  54},
+
+	{398, 354, 316, 298, 276, 236, 210, 198, // PAL
+	176, 148, 132, 118,  98,  78,  66,  50}
+};
+
+inline void Dmc_reload_sample( struct Nes_Dmc* this )
+{
+	this->address = 0x4000 + this->osc.regs [2] * 0x40;
+	this->osc.length_counter = this->osc.regs [3] * 0x10 + 1;
+}
+
+static byte const dac_table [128] ICONST_ATTR =
+{
+	 0, 1, 2, 3, 4, 5, 6, 7, 7, 8, 9,10,11,12,13,14,
+	15,15,16,17,18,19,20,20,21,22,23,24,24,25,26,27,
+	27,28,29,30,31,31,32,33,33,34,35,36,36,37,38,38,
+	39,40,41,41,42,43,43,44,45,45,46,47,47,48,48,49,
+	50,50,51,52,52,53,53,54,55,55,56,56,57,58,58,59,
+	59,60,60,61,61,62,63,63,64,64,65,65,66,66,67,67,
+	68,68,69,70,70,71,71,72,72,73,73,74,74,75,75,75,
+	76,76,77,77,78,78,79,79,80,80,81,81,82,82,82,83,
+};
+
+void Dmc_write_register( struct Nes_Dmc* this, int addr, int data )
+{
+	if ( addr == 0 )
+	{
+		this->period = dmc_period_table [this->pal_mode] [data & 15];
+		this->irq_enabled = (data & 0xC0) == 0x80; // enabled only if loop disabled
+		this->irq_flag &= this->irq_enabled;
+		Dmc_recalc_irq( this );
+	}
+	else if ( addr == 1 )
+	{
+		int old_dac = this->dac;
+		this->dac = data & 0x7F;
+		
+		// adjust last_amp so that "pop" amplitude will be properly non-linear
+		// with respect to change in dac
+		int faked_nonlinear = this->dac - (dac_table [this->dac] - dac_table [old_dac]);
+		if ( !this->nonlinear )
+			this->osc.last_amp = faked_nonlinear;
+	}
+}
+
+void Dmc_start( struct Nes_Dmc* this )
+{
+	Dmc_reload_sample( this );
+	Dmc_fill_buffer( this );
+	Dmc_recalc_irq( this );
+}
+
+void Dmc_fill_buffer( struct Nes_Dmc* this )
+{
+	if ( !this->buf_full && this->osc.length_counter )
+	{
+		require( this->prg_reader ); // prg_reader must be set
+		this->buf = this->prg_reader( this->prg_reader_data, 0x8000u + this->address );
+		this->address = (this->address + 1) & 0x7FFF;
+		this->buf_full = true;
+		if ( --this->osc.length_counter == 0 )
+		{
+			if ( this->osc.regs [0] & loop_flag ) {
+				Dmc_reload_sample( this );
+			}
+			else {
+				this->apu->osc_enables &= ~0x10;
+				this->irq_flag = this->irq_enabled;
+				this->next_irq = apu_no_irq;
+				Apu_irq_changed( this->apu );
+			}
+		}
+	}
+}
+
+void Dmc_run( struct Nes_Dmc* this, nes_time_t time, nes_time_t end_time )
+{
+	struct Nes_Osc* osc = &this->osc;
+	int delta = Osc_update_amp( osc, this->dac );
+	if ( !osc->output )
+	{
+		this->silence = true;
+	}
+	else
+	{
+		Blip_set_modified( osc->output );
+		if ( delta )
+			Synth_offset( &this->synth, time, delta, osc->output );
+	}
+	
+	time += osc->delay;
+	if ( time < end_time )
+	{
+		int bits_remain = this->bits_remain;
+		if ( this->silence && !this->buf_full )
+		{
+			int count = (end_time - time + this->period - 1) / this->period;
+			bits_remain = (bits_remain - 1 + 8 - (count % 8)) % 8 + 1;
+			time += count * this->period;
+		}
+		else
+		{
+			struct Blip_Buffer* const output = osc->output;
+			const int period = this->period;
+			int bits = this->bits;
+			int dac = this->dac;
+			
+			do
+			{
+				if ( !this->silence )
+				{
+					int step = (bits & 1) * 4 - 2;
+					bits >>= 1;
+					if ( (unsigned) (dac + step) <= 0x7F ) {
+						dac += step;
+						Synth_offset_inline( &this->synth, time, step, output );
+					}
+				}
+				
+				time += period;
+				
+				if ( --bits_remain == 0 )
+				{
+					bits_remain = 8;
+					if ( !this->buf_full ) {
+						this->silence = true;
+					}
+					else {
+						this->silence = false;
+						bits = this->buf;
+						this->buf_full = false;
+						if ( !output )
+							this->silence = true;
+						Dmc_fill_buffer( this );
+					}
+				}
+			}
+			while ( time < end_time );
+			
+			this->dac = dac;
+			osc->last_amp = dac;
+			this->bits = bits;
+		}
+		this->bits_remain = bits_remain;
+	}
+	osc->delay = time - end_time;
+}
+
+// Nes_Noise
+
+static short const noise_period_table [16] ICONST_ATTR = {
+	0x004, 0x008, 0x010, 0x020, 0x040, 0x060, 0x080, 0x0A0,
+	0x0CA, 0x0FE, 0x17C, 0x1FC, 0x2FA, 0x3F8, 0x7F2, 0xFE4
+};
+
+void Noise_clock_envelope( struct Nes_Noise* this )
+{
+	struct Nes_Osc* osc = &this->osc;
+	int period = osc->regs [0] & 15;
+	if ( osc->reg_written [3] ) {
+		osc->reg_written [3] = false;
+		this->env_delay = period;
+		this->envelope = 15;
+	}
+	else if ( --this->env_delay < 0 ) {
+		this->env_delay = period;
+		if ( this->envelope | (osc->regs [0] & 0x20) )
+			this->envelope = (this->envelope - 1) & 15;
+	}
+}
+
+int Noise_volume( struct Nes_Noise* this )
+{
+	struct Nes_Osc* osc = &this->osc;
+	return osc->length_counter == 0 ? 0 : (osc->regs [0] & 0x10) ? (osc->regs [0] & 15) : this->envelope;
+}
+
+void Noise_run( struct Nes_Noise* this, nes_time_t time, nes_time_t end_time )
+{
+	struct Nes_Osc* osc = &this->osc;
+	int period = noise_period_table [osc->regs [2] & 15];
+	
+	if ( !osc->output )
+	{
+		// TODO: clean up
+		time += osc->delay;
+		osc->delay = time + (end_time - time + period - 1) / period * period - end_time;
+		return;
+	}
+	
+	Blip_set_modified( osc->output );
+	
+	const int volume = Noise_volume( this );
+	int amp = (this->noise & 1) ? volume : 0;
+	{
+		int delta = Osc_update_amp( osc, amp );
+		if ( delta )
+			Synth_offset( &this->synth, time, delta, osc->output );
+	}
+	
+	time += osc->delay;
+	if ( time < end_time )
+	{
+		const int mode_flag = 0x80;
+		
+		if ( !volume )
+		{
+			// round to next multiple of period
+			time += (end_time - time + period - 1) / period * period;
+			
+			// approximate noise cycling while muted, by shuffling up noise register
+			// to do: precise muted noise cycling?
+			if ( !(osc->regs [2] & mode_flag) ) {
+				int feedback = (this->noise << 13) ^ (this->noise << 14);
+				this->noise = (feedback & 0x4000) | (this->noise >> 1);
+			}
+		}
+		else
+		{
+			struct Blip_Buffer* const output = osc->output;
+			
+			// using resampled time avoids conversion in synth.offset()
+			blip_resampled_time_t rperiod = Blip_resampled_duration( output, period );
+			blip_resampled_time_t rtime = Blip_resampled_time( output, time );
+			
+			int noise = this->noise;
+			int delta = amp * 2 - volume;
+			const int tap = (osc->regs [2] & mode_flag ? 8 : 13);
+			
+			do {
+				int feedback = (noise << tap) ^ (noise << 14);
+				time += period;
+				
+				if ( (noise + 1) & 2 ) {
+					// bits 0 and 1 of noise differ
+					delta = -delta;
+					Synth_offset_resampled( &this->synth, rtime, delta, output );
+				}
+				
+				rtime += rperiod;
+				noise = (feedback & 0x4000) | (noise >> 1);
+			}
+			while ( time < end_time );
+			
+			osc->last_amp = (delta + volume) >> 1;
+			this->noise = noise;
+		}
+	}
+	
+	osc->delay = time - end_time;
+}
+
Index: apps/codecs/libnsf/nes_namco_apu.h
===================================================================
--- apps/codecs/libnsf/nes_namco_apu.h	(revision 0)
+++ apps/codecs/libnsf/nes_namco_apu.h	(revision 0)
@@ -0,0 +1,71 @@
+// Namco 106 sound chip emulator
+
+// Nes_Snd_Emu 0.1.8
+#ifndef NES_NAMCO_APU_H
+#define NES_NAMCO_APU_H
+
+#include "blargg_common.h"
+#include "blip_buffer.h"
+
+struct namco_state_t;
+
+enum { namco_osc_count = 8 };
+enum { namco_addr_reg_addr = 0xF800 };
+enum { namco_data_reg_addr = 0x4800 };
+enum { namco_reg_count = 0x80 };
+
+struct Namco_Osc {
+	blargg_long delay;
+	struct Blip_Buffer* output;
+	short last_amp;
+	short wave_pos;
+};
+
+struct Nes_Namco_Apu {	
+	struct Namco_Osc oscs [namco_osc_count];
+	
+	blip_time_t last_time;
+	int addr_reg;
+	
+	uint8_t reg [namco_reg_count];
+
+	struct Blip_Synth synth;
+};
+
+// See Nes_Apu.h for reference.
+void Namco_init( struct Nes_Namco_Apu* this );
+void Namco_output( struct Nes_Namco_Apu* this, struct Blip_Buffer* );
+	
+void Namco_reset( struct Nes_Namco_Apu* this );
+void Namco_end_frame( struct Nes_Namco_Apu* this, blip_time_t ); ICODE_ATTR
+	
+static inline uint8_t* namco_access( struct Nes_Namco_Apu* this )
+{
+	int addr = this->addr_reg & 0x7F;
+	if ( this->addr_reg & 0x80 )
+		this->addr_reg = (addr + 1) | 0x80;
+	return &this->reg [addr];
+}
+
+static inline void Namco_volume( struct Nes_Namco_Apu* this, double v ) { Synth_volume( &this->synth, 0.10 / namco_osc_count * v / 15.0 ); }
+
+// Write-only address register is at 0xF800
+static inline void Namco_write_addr( struct Nes_Namco_Apu* this, int v ) { this->addr_reg = v; }
+
+static inline int Namco_read_data( struct Nes_Namco_Apu* this ) { return *namco_access( this ); }
+
+static inline void Namco_osc_output( struct Nes_Namco_Apu* this, int i, struct Blip_Buffer* buf )
+{
+	assert( (unsigned) i < namco_osc_count );
+	this->oscs [i].output = buf;
+}
+
+// Read/write data register is at 0x4800
+void Namco_run_until( struct Nes_Namco_Apu* this, blip_time_t ); ICODE_ATTR
+static inline void Namco_write_data( struct Nes_Namco_Apu* this, blip_time_t time, int data )
+{
+	Namco_run_until( this, time );
+	*namco_access( this ) = data;
+}
+
+#endif
Index: apps/codecs/libnsf/nes_mmc5_apu.h
===================================================================
--- apps/codecs/libnsf/nes_mmc5_apu.h	(revision 0)
+++ apps/codecs/libnsf/nes_mmc5_apu.h	(revision 0)
@@ -0,0 +1,61 @@
+// NES MMC5 sound chip emulator
+
+// Nes_Snd_Emu 0.2.0-pre
+#ifndef NES_MMC5_APU_H
+#define NES_MMC5_APU_H
+
+#include "blargg_common.h"
+#include "nes_apu.h"
+
+enum { mmc5_regs_addr = 0x5000 };
+enum { mmc5_regs_size = 0x16 };
+enum { mmc5_osc_count  = 3 };
+enum { mmc5_exram_size = 1024 };
+
+struct Nes_Mmc5_Apu {
+	struct Nes_Apu apu;
+	unsigned char exram [mmc5_exram_size];
+};
+
+static inline void Mmc5_init( struct Nes_Mmc5_Apu* this )
+{
+	Apu_init( &this->apu );
+}
+
+static inline void Mmc5_set_output( struct Nes_Mmc5_Apu* this, int i, struct Blip_Buffer* b )
+{
+	// in: square 1, square 2, PCM
+	// out: square 1, square 2, skipped, skipped, PCM
+	if ( i > 1 )
+		i += 2;
+	Apu_osc_output( &this->apu, i, b );
+}
+
+static inline void Mmc5_write_register( struct Nes_Mmc5_Apu* this, blip_time_t time, unsigned addr, int data )
+{
+	switch ( addr )
+	{
+	case 0x5015: // channel enables
+		data &= 0x03; // enable the square waves only
+		// fall through
+	case 0x5000: // Square 1
+	case 0x5002:
+	case 0x5003:
+	case 0x5004: // Square 2
+	case 0x5006:
+	case 0x5007:
+	case 0x5011: // DAC
+		Apu_write_register( &this->apu, time, addr - 0x1000, data );
+		break;
+	
+	case 0x5010: // some things write to this for some reason
+		break;
+	
+#ifdef BLARGG_DEBUG_H
+	default:
+			dprintf( "Unmapped MMC5 APU write: $%04X <- $%02X\n", addr, data );
+#endif
+	}
+}
+
+#endif
Index: apps/codecs/libnsf/nes_oscs.h
===================================================================
--- apps/codecs/libnsf/nes_oscs.h	(revision 0)
+++ apps/codecs/libnsf/nes_oscs.h	(revision 0)
@@ -0,0 +1,165 @@
+// Private oscillators used by Nes_Apu
+
+// Nes_Snd_Emu 0.1.8
+#ifndef NES_OSCS_H
+#define NES_OSCS_H
+
+#include "blargg_common.h"
+#include "blip_buffer.h"
+#include "nes_cpu.h"
+
+struct Nes_Apu;
+
+struct Nes_Osc
+{
+	unsigned char regs [4];
+	bool reg_written [4];
+	struct Blip_Buffer* output;
+	int length_counter;// length counter (0 if unused by oscillator)
+	int delay;      // delay until next (potential) transition
+	int last_amp;   // last amplitude oscillator was outputting
+};
+
+void Osc_clock_length( struct Nes_Osc* this, int halt_mask );
+static inline int Osc_period( struct Nes_Osc* this ) 
+{
+	return (this->regs [3] & 7) * 0x100 + (this->regs [2] & 0xFF);
+}
+
+static inline void Osc_reset( struct Nes_Osc* this ) 
+{
+	this->delay = 0;
+	this->last_amp = 0;
+}
+
+static inline int Osc_update_amp( struct Nes_Osc* this, int amp ) 
+{
+	int delta = amp - this->last_amp;
+	this->last_amp = amp;
+	return delta;
+}
+
+// Nes_Square
+
+enum { negate_flag = 0x08 };
+enum { shift_mask = 0x07 };
+enum { square_phase_range = 8 };
+
+typedef struct Blip_Synth Synth;
+	
+struct Nes_Square
+{
+	struct Nes_Osc osc;
+	int envelope;
+	int env_delay;
+	int phase;
+	int sweep_delay;
+		
+	Synth* synth; // shared between squares
+};
+
+static inline void Square_set_synth( struct Nes_Square* this, Synth* s ) { this->synth = s; }
+	
+void Square_clock_sweep( struct Nes_Square* this, int adjust );
+void Square_run( struct Nes_Square* this, nes_time_t, nes_time_t );
+
+static inline void Square_reset( struct Nes_Square* this ) 
+{
+	this->sweep_delay = 0;
+	this->envelope = 0;
+	this->env_delay = 0;
+	Osc_reset( &this->osc );
+}
+
+void Square_clock_envelope( struct Nes_Square* this );
+int Square_volume( struct Nes_Square* this );
+		
+// Nes_Triangle
+
+enum { Triangle_phase_range = 16 };
+	
+struct Nes_Triangle
+{
+	struct Nes_Osc osc;
+		
+	int phase;
+	int linear_counter;
+	struct Blip_Synth synth;
+};
+
+void Triangle_run( struct Nes_Triangle* this, nes_time_t, nes_time_t );
+void Triangle_clock_linear_counter( struct Nes_Triangle* this );
+
+static inline void Triangle_reset( struct Nes_Triangle* this )
+{
+	this->linear_counter = 0;
+	this->phase = 1;
+	Osc_reset( &this->osc );
+}
+
+// Nes_Noise
+struct Nes_Noise
+{
+	struct Nes_Osc osc;
+	
+	int envelope;
+	int env_delay;
+	int noise;
+	struct Blip_Synth synth;
+};
+
+void Noise_clock_envelope( struct Nes_Noise* this );
+int Noise_volume( struct Nes_Noise* this );
+void Noise_run( struct Nes_Noise* this, nes_time_t, nes_time_t );
+
+static inline void Noise_reset( struct Nes_Noise* this )
+{
+	this->noise = 1 << 14;
+	this->envelope = 0;
+	this->env_delay = 0;
+	Osc_reset( &this->osc );
+}
+
+// Nes_Dmc
+
+enum { loop_flag = 0x40 };
+	
+struct Nes_Dmc
+{
+	struct Nes_Osc osc;
+		
+	int address;    // address of next byte to read
+	int period;
+	int buf;
+	int bits_remain;
+	int bits;
+	bool buf_full;
+	bool silence;
+	
+	int dac;
+	
+	nes_time_t next_irq;
+	bool irq_enabled;
+	bool irq_flag;
+	bool pal_mode;
+	bool nonlinear;
+	
+ 	int (*prg_reader)( void*, addr_t ); // needs to be initialized to prg read function
+	void* prg_reader_data;
+	
+	struct Nes_Apu* apu;
+	
+	struct Blip_Synth synth;
+};
+
+void Dmc_start( struct Nes_Dmc* this );
+void Dmc_write_register( struct Nes_Dmc* this, int, int ); ICODE_ATTR
+void Dmc_run( struct Nes_Dmc* this, nes_time_t, nes_time_t ); ICODE_ATTR
+void Dmc_recalc_irq( struct Nes_Dmc* this ); ICODE_ATTR
+void Dmc_fill_buffer( struct Nes_Dmc* this ); ICODE_ATTR
+void Dmc_reload_sample( struct Nes_Dmc* this ); ICODE_ATTR
+void Dmc_reset( struct Nes_Dmc* this ); ICODE_ATTR
+
+int Dmc_count_reads( struct Nes_Dmc* this, nes_time_t, nes_time_t* ); ICODE_ATTR
+
+#endif
Index: apps/codecs/libnsf/ym_tables.h
===================================================================
--- apps/codecs/libnsf/ym_tables.h	(revision 0)
+++ apps/codecs/libnsf/ym_tables.h	(revision 0)
@@ -0,0 +1,1292 @@
+#ifndef YM_TABLES_H
+#define YM_TABLES_H
+
+signed int tl_table_2413[5632] =
+{
+	0x000007fa, 0xfffff806, 0x000007f5, 0xfffff80b, 0x000007ef, 0xfffff811, 0x000007ea, 
+	0xfffff816, 0x000007e4, 0xfffff81c, 0x000007df, 0xfffff821, 0x000007da, 
+	0xfffff826, 0x000007d4, 0xfffff82c, 0x000007cf, 0xfffff831, 0x000007c9, 
+	0xfffff837, 0x000007c4, 0xfffff83c, 0x000007bf, 0xfffff841, 0x000007b9, 
+	0xfffff847, 0x000007b4, 0xfffff84c, 0x000007ae, 0xfffff852, 0x000007a9, 
+	0xfffff857, 0x000007a4, 0xfffff85c, 0x0000079f, 0xfffff861, 0x00000799, 
+	0xfffff867, 0x00000794, 0xfffff86c, 0x0000078f, 0xfffff871, 0x0000078a, 
+	0xfffff876, 0x00000784, 0xfffff87c, 0x0000077f, 0xfffff881, 0x0000077a, 
+	0xfffff886, 0x00000775, 0xfffff88b, 0x00000770, 0xfffff890, 0x0000076a, 
+	0xfffff896, 0x00000765, 0xfffff89b, 0x00000760, 0xfffff8a0, 0x0000075b, 
+	0xfffff8a5, 0x00000756, 0xfffff8aa, 0x00000751, 0xfffff8af, 0x0000074c, 
+	0xfffff8b4, 0x00000747, 0xfffff8b9, 0x00000742, 0xfffff8be, 0x0000073d, 
+	0xfffff8c3, 0x00000738, 0xfffff8c8, 0x00000733, 0xfffff8cd, 0x0000072e, 
+	0xfffff8d2, 0x00000729, 0xfffff8d7, 0x00000724, 0xfffff8dc, 0x0000071f, 
+	0xfffff8e1, 0x0000071a, 0xfffff8e6, 0x00000715, 0xfffff8eb, 0x00000710, 
+	0xfffff8f0, 0x0000070b, 0xfffff8f5, 0x00000706, 0xfffff8fa, 0x00000702, 
+	0xfffff8fe, 0x000006fd, 0xfffff903, 0x000006f8, 0xfffff908, 0x000006f3, 
+	0xfffff90d, 0x000006ee, 0xfffff912, 0x000006e9, 0xfffff917, 0x000006e5, 
+	0xfffff91b, 0x000006e0, 0xfffff920, 0x000006db, 0xfffff925, 0x000006d6, 
+	0xfffff92a, 0x000006d2, 0xfffff92e, 0x000006cd, 0xfffff933, 0x000006c8, 
+	0xfffff938, 0x000006c4, 0xfffff93c, 0x000006bf, 0xfffff941, 0x000006ba, 
+	0xfffff946, 0x000006b5, 0xfffff94b, 0x000006b1, 0xfffff94f, 0x000006ac, 
+	0xfffff954, 0x000006a8, 0xfffff958, 0x000006a3, 0xfffff95d, 0x0000069e, 
+	0xfffff962, 0x0000069a, 0xfffff966, 0x00000695, 0xfffff96b, 0x00000691, 
+	0xfffff96f, 0x0000068c, 0xfffff974, 0x00000688, 0xfffff978, 0x00000683, 
+	0xfffff97d, 0x0000067f, 0xfffff981, 0x0000067a, 0xfffff986, 0x00000676, 
+	0xfffff98a, 0x00000671, 0xfffff98f, 0x0000066d, 0xfffff993, 0x00000668, 
+	0xfffff998, 0x00000664, 0xfffff99c, 0x0000065f, 0xfffff9a1, 0x0000065b, 
+	0xfffff9a5, 0x00000657, 0xfffff9a9, 0x00000652, 0xfffff9ae, 0x0000064e, 
+	0xfffff9b2, 0x00000649, 0xfffff9b7, 0x00000645, 0xfffff9bb, 0x00000641, 
+	0xfffff9bf, 0x0000063c, 0xfffff9c4, 0x00000638, 0xfffff9c8, 0x00000634, 
+	0xfffff9cc, 0x00000630, 0xfffff9d0, 0x0000062b, 0xfffff9d5, 0x00000627, 
+	0xfffff9d9, 0x00000623, 0xfffff9dd, 0x0000061e, 0xfffff9e2, 0x0000061a, 
+	0xfffff9e6, 0x00000616, 0xfffff9ea, 0x00000612, 0xfffff9ee, 0x0000060e, 
+	0xfffff9f2, 0x00000609, 0xfffff9f7, 0x00000605, 0xfffff9fb, 0x00000601, 
+	0xfffff9ff, 0x000005fd, 0xfffffa03, 0x000005f9, 0xfffffa07, 0x000005f5, 
+	0xfffffa0b, 0x000005f0, 0xfffffa10, 0x000005ec, 0xfffffa14, 0x000005e8, 
+	0xfffffa18, 0x000005e4, 0xfffffa1c, 0x000005e0, 0xfffffa20, 0x000005dc, 
+	0xfffffa24, 0x000005d8, 0xfffffa28, 0x000005d4, 0xfffffa2c, 0x000005d0, 
+	0xfffffa30, 0x000005cc, 0xfffffa34, 0x000005c8, 0xfffffa38, 0x000005c4, 
+	0xfffffa3c, 0x000005c0, 0xfffffa40, 0x000005bc, 0xfffffa44, 0x000005b8, 
+	0xfffffa48, 0x000005b4, 0xfffffa4c, 0x000005b0, 0xfffffa50, 0x000005ac, 
+	0xfffffa54, 0x000005a8, 0xfffffa58, 0x000005a4, 0xfffffa5c, 0x000005a0, 
+	0xfffffa60, 0x0000059c, 0xfffffa64, 0x00000599, 0xfffffa67, 0x00000595, 
+	0xfffffa6b, 0x00000591, 0xfffffa6f, 0x0000058d, 0xfffffa73, 0x00000589, 
+	0xfffffa77, 0x00000585, 0xfffffa7b, 0x00000581, 0xfffffa7f, 0x0000057e, 
+	0xfffffa82, 0x0000057a, 0xfffffa86, 0x00000576, 0xfffffa8a, 0x00000572, 
+	0xfffffa8e, 0x0000056f, 0xfffffa91, 0x0000056b, 0xfffffa95, 0x00000567, 
+	0xfffffa99, 0x00000563, 0xfffffa9d, 0x00000560, 0xfffffaa0, 0x0000055c, 
+	0xfffffaa4, 0x00000558, 0xfffffaa8, 0x00000554, 0xfffffaac, 0x00000551, 
+	0xfffffaaf, 0x0000054d, 0xfffffab3, 0x00000549, 0xfffffab7, 0x00000546, 
+	0xfffffaba, 0x00000542, 0xfffffabe, 0x0000053e, 0xfffffac2, 0x0000053b, 
+	0xfffffac5, 0x00000537, 0xfffffac9, 0x00000534, 0xfffffacc, 0x00000530, 
+	0xfffffad0, 0x0000052c, 0xfffffad4, 0x00000529, 0xfffffad7, 0x00000525, 
+	0xfffffadb, 0x00000522, 0xfffffade, 0x0000051e, 0xfffffae2, 0x0000051b, 
+	0xfffffae5, 0x00000517, 0xfffffae9, 0x00000514, 0xfffffaec, 0x00000510, 
+	0xfffffaf0, 0x0000050c, 0xfffffaf4, 0x00000509, 0xfffffaf7, 0x00000506, 
+	0xfffffafa, 0x00000502, 0xfffffafe, 0x000004ff, 0xfffffb01, 0x000004fb, 
+	0xfffffb05, 0x000004f8, 0xfffffb08, 0x000004f4, 0xfffffb0c, 0x000004f1, 
+	0xfffffb0f, 0x000004ed, 0xfffffb13, 0x000004ea, 0xfffffb16, 0x000004e7, 
+	0xfffffb19, 0x000004e3, 0xfffffb1d, 0x000004e0, 0xfffffb20, 0x000004dc, 
+	0xfffffb24, 0x000004d9, 0xfffffb27, 0x000004d6, 0xfffffb2a, 0x000004d2, 
+	0xfffffb2e, 0x000004cf, 0xfffffb31, 0x000004cc, 0xfffffb34, 0x000004c8, 
+	0xfffffb38, 0x000004c5, 0xfffffb3b, 0x000004c2, 0xfffffb3e, 0x000004be, 
+	0xfffffb42, 0x000004bb, 0xfffffb45, 0x000004b8, 0xfffffb48, 0x000004b5, 
+	0xfffffb4b, 0x000004b1, 0xfffffb4f, 0x000004ae, 0xfffffb52, 0x000004ab, 
+	0xfffffb55, 0x000004a8, 0xfffffb58, 0x000004a4, 0xfffffb5c, 0x000004a1, 
+	0xfffffb5f, 0x0000049e, 0xfffffb62, 0x0000049b, 0xfffffb65, 0x00000498, 
+	0xfffffb68, 0x00000494, 0xfffffb6c, 0x00000491, 0xfffffb6f, 0x0000048e, 
+	0xfffffb72, 0x0000048b, 0xfffffb75, 0x00000488, 0xfffffb78, 0x00000485, 
+	0xfffffb7b, 0x00000482, 0xfffffb7e, 0x0000047e, 0xfffffb82, 0x0000047b, 
+	0xfffffb85, 0x00000478, 0xfffffb88, 0x00000475, 0xfffffb8b, 0x00000472, 
+	0xfffffb8e, 0x0000046f, 0xfffffb91, 0x0000046c, 0xfffffb94, 0x00000469, 
+	0xfffffb97, 0x00000466, 0xfffffb9a, 0x00000463, 0xfffffb9d, 0x00000460, 
+	0xfffffba0, 0x0000045d, 0xfffffba3, 0x0000045a, 0xfffffba6, 0x00000457, 
+	0xfffffba9, 0x00000454, 0xfffffbac, 0x00000451, 0xfffffbaf, 0x0000044e, 
+	0xfffffbb2, 0x0000044b, 0xfffffbb5, 0x00000448, 0xfffffbb8, 0x00000445, 
+	0xfffffbbb, 0x00000442, 0xfffffbbe, 0x0000043f, 0xfffffbc1, 0x0000043c, 
+	0xfffffbc4, 0x00000439, 0xfffffbc7, 0x00000436, 0xfffffbca, 0x00000433, 
+	0xfffffbcd, 0x00000430, 0xfffffbd0, 0x0000042d, 0xfffffbd3, 0x0000042a, 
+	0xfffffbd6, 0x00000428, 0xfffffbd8, 0x00000425, 0xfffffbdb, 0x00000422, 
+	0xfffffbde, 0x0000041f, 0xfffffbe1, 0x0000041c, 0xfffffbe4, 0x00000419, 
+	0xfffffbe7, 0x00000416, 0xfffffbea, 0x00000414, 0xfffffbec, 0x00000411, 
+	0xfffffbef, 0x0000040e, 0xfffffbf2, 0x0000040b, 0xfffffbf5, 0x00000408, 
+	0xfffffbf8, 0x00000406, 0xfffffbfa, 0x00000403, 0xfffffbfd, 0x00000400, 
+	0xfffffc00, 0x000003fd, 0xfffffc03, 0x000003fa, 0xfffffc06, 0x000003f7, 
+	0xfffffc09, 0x000003f5, 0xfffffc0b, 0x000003f2, 0xfffffc0e, 0x000003ef, 
+	0xfffffc11, 0x000003ed, 0xfffffc13, 0x000003ea, 0xfffffc16, 0x000003e7, 
+	0xfffffc19, 0x000003e4, 0xfffffc1c, 0x000003e2, 0xfffffc1e, 0x000003df, 
+	0xfffffc21, 0x000003dc, 0xfffffc24, 0x000003da, 0xfffffc26, 0x000003d7, 
+	0xfffffc29, 0x000003d4, 0xfffffc2c, 0x000003d2, 0xfffffc2e, 0x000003cf, 
+	0xfffffc31, 0x000003cc, 0xfffffc34, 0x000003ca, 0xfffffc36, 0x000003c7, 
+	0xfffffc39, 0x000003c5, 0xfffffc3b, 0x000003c2, 0xfffffc3e, 0x000003bf, 
+	0xfffffc41, 0x000003bd, 0xfffffc43, 0x000003ba, 0xfffffc46, 0x000003b8, 
+	0xfffffc48, 0x000003b5, 0xfffffc4b, 0x000003b2, 0xfffffc4e, 0x000003b0, 
+	0xfffffc50, 0x000003ad, 0xfffffc53, 0x000003ab, 0xfffffc55, 0x000003a8, 
+	0xfffffc58, 0x000003a6, 0xfffffc5a, 0x000003a3, 0xfffffc5d, 0x000003a1, 
+	0xfffffc5f, 0x0000039e, 0xfffffc62, 0x0000039c, 0xfffffc64, 0x00000399, 
+	0xfffffc67, 0x00000397, 0xfffffc69, 0x00000394, 0xfffffc6c, 0x00000392, 
+	0xfffffc6e, 0x0000038f, 0xfffffc71, 0x0000038d, 0xfffffc73, 0x0000038a, 
+	0xfffffc76, 0x00000388, 0xfffffc78, 0x00000385, 0xfffffc7b, 0x00000383, 
+	0xfffffc7d, 0x00000381, 0xfffffc7f, 0x0000037e, 0xfffffc82, 0x0000037c, 
+	0xfffffc84, 0x00000379, 0xfffffc87, 0x00000377, 0xfffffc89, 0x00000374, 
+	0xfffffc8c, 0x00000372, 0xfffffc8e, 0x00000370, 0xfffffc90, 0x0000036d, 
+	0xfffffc93, 0x0000036b, 0xfffffc95, 0x00000369, 0xfffffc97, 0x00000366, 
+	0xfffffc9a, 0x00000364, 0xfffffc9c, 0x00000362, 0xfffffc9e, 0x0000035f, 
+	0xfffffca1, 0x0000035d, 0xfffffca3, 0x0000035a, 0xfffffca6, 0x00000358, 
+	0xfffffca8, 0x00000356, 0xfffffcaa, 0x00000354, 0xfffffcac, 0x00000351, 
+	0xfffffcaf, 0x0000034f, 0xfffffcb1, 0x0000034d, 0xfffffcb3, 0x0000034a, 
+	0xfffffcb6, 0x00000348, 0xfffffcb8, 0x00000346, 0xfffffcba, 0x00000344, 
+	0xfffffcbc, 0x00000341, 0xfffffcbf, 0x0000033f, 0xfffffcc1, 0x0000033d, 
+	0xfffffcc3, 0x0000033b, 0xfffffcc5, 0x00000338, 0xfffffcc8, 0x00000336, 
+	0xfffffcca, 0x00000334, 0xfffffccc, 0x00000332, 0xfffffcce, 0x0000032f, 
+	0xfffffcd1, 0x0000032d, 0xfffffcd3, 0x0000032b, 0xfffffcd5, 0x00000329, 
+	0xfffffcd7, 0x00000327, 0xfffffcd9, 0x00000324, 0xfffffcdc, 0x00000322, 
+	0xfffffcde, 0x00000320, 0xfffffce0, 0x0000031e, 0xfffffce2, 0x0000031c, 
+	0xfffffce4, 0x0000031a, 0xfffffce6, 0x00000318, 0xfffffce8, 0x00000315, 
+	0xfffffceb, 0x00000313, 0xfffffced, 0x00000311, 0xfffffcef, 0x0000030f, 
+	0xfffffcf1, 0x0000030d, 0xfffffcf3, 0x0000030b, 0xfffffcf5, 0x00000309, 
+	0xfffffcf7, 0x00000307, 0xfffffcf9, 0x00000304, 0xfffffcfc, 0x00000302, 
+	0xfffffcfe, 0x00000300, 0xfffffd00, 0x000002fe, 0xfffffd02, 0x000002fc, 
+	0xfffffd04, 0x000002fa, 0xfffffd06, 0x000002f8, 0xfffffd08, 0x000002f6, 
+	0xfffffd0a, 0x000002f4, 0xfffffd0c, 0x000002f2, 0xfffffd0e, 0x000002f0, 
+	0xfffffd10, 0x000002ee, 0xfffffd12, 0x000002ec, 0xfffffd14, 0x000002ea, 
+	0xfffffd16, 0x000002e8, 0xfffffd18, 0x000002e6, 0xfffffd1a, 0x000002e4, 
+	0xfffffd1c, 0x000002e2, 0xfffffd1e, 0x000002e0, 0xfffffd20, 0x000002de, 
+	0xfffffd22, 0x000002dc, 0xfffffd24, 0x000002da, 0xfffffd26, 0x000002d8, 
+	0xfffffd28, 0x000002d6, 0xfffffd2a, 0x000002d4, 0xfffffd2c, 0x000002d2, 
+	0xfffffd2e, 0x000002d0, 0xfffffd30, 0x000002ce, 0xfffffd32, 0x000002cc, 
+	0xfffffd34, 0x000002ca, 0xfffffd36, 0x000002c8, 0xfffffd38, 0x000002c6, 
+	0xfffffd3a, 0x000002c4, 0xfffffd3c, 0x000002c2, 0xfffffd3e, 0x000002c0, 
+	0xfffffd40, 0x000002bf, 0xfffffd41, 0x000002bd, 0xfffffd43, 0x000002bb, 
+	0xfffffd45, 0x000002b9, 0xfffffd47, 0x000002b7, 0xfffffd49, 0x000002b5, 
+	0xfffffd4b, 0x000002b3, 0xfffffd4d, 0x000002b1, 0xfffffd4f, 0x000002b0, 
+	0xfffffd50, 0x000002ae, 0xfffffd52, 0x000002ac, 0xfffffd54, 0x000002aa, 
+	0xfffffd56, 0x000002a8, 0xfffffd58, 0x000002a6, 0xfffffd5a, 0x000002a4, 
+	0xfffffd5c, 0x000002a3, 0xfffffd5d, 0x000002a1, 0xfffffd5f, 0x0000029f, 
+	0xfffffd61, 0x0000029d, 0xfffffd63, 0x0000029b, 0xfffffd65, 0x0000029a, 
+	0xfffffd66, 0x00000298, 0xfffffd68, 0x00000296, 0xfffffd6a, 0x00000294, 
+	0xfffffd6c, 0x00000292, 0xfffffd6e, 0x00000291, 0xfffffd6f, 0x0000028f, 
+	0xfffffd71, 0x0000028d, 0xfffffd73, 0x0000028b, 0xfffffd75, 0x0000028a, 
+	0xfffffd76, 0x00000288, 0xfffffd78, 0x00000286, 0xfffffd7a, 0x00000284, 
+	0xfffffd7c, 0x00000283, 0xfffffd7d, 0x00000281, 0xfffffd7f, 0x0000027f, 
+	0xfffffd81, 0x0000027d, 0xfffffd83, 0x0000027c, 0xfffffd84, 0x0000027a, 
+	0xfffffd86, 0x00000278, 0xfffffd88, 0x00000276, 0xfffffd8a, 0x00000275, 
+	0xfffffd8b, 0x00000273, 0xfffffd8d, 0x00000271, 0xfffffd8f, 0x00000270, 
+	0xfffffd90, 0x0000026e, 0xfffffd92, 0x0000026c, 0xfffffd94, 0x0000026b, 
+	0xfffffd95, 0x00000269, 0xfffffd97, 0x00000267, 0xfffffd99, 0x00000266, 
+	0xfffffd9a, 0x00000264, 0xfffffd9c, 0x00000262, 0xfffffd9e, 0x00000261, 
+	0xfffffd9f, 0x0000025f, 0xfffffda1, 0x0000025d, 0xfffffda3, 0x0000025c, 
+	0xfffffda4, 0x0000025a, 0xfffffda6, 0x00000258, 0xfffffda8, 0x00000257, 
+	0xfffffda9, 0x00000255, 0xfffffdab, 0x00000254, 0xfffffdac, 0x00000252, 
+	0xfffffdae, 0x00000250, 0xfffffdb0, 0x0000024f, 0xfffffdb1, 0x0000024d, 
+	0xfffffdb3, 0x0000024c, 0xfffffdb4, 0x0000024a, 0xfffffdb6, 0x00000248, 
+	0xfffffdb8, 0x00000247, 0xfffffdb9, 0x00000245, 0xfffffdbb, 0x00000244, 
+	0xfffffdbc, 0x00000242, 0xfffffdbe, 0x00000241, 0xfffffdbf, 0x0000023f, 
+	0xfffffdc1, 0x0000023d, 0xfffffdc3, 0x0000023c, 0xfffffdc4, 0x0000023a, 
+	0xfffffdc6, 0x00000239, 0xfffffdc7, 0x00000237, 0xfffffdc9, 0x00000236, 
+	0xfffffdca, 0x00000234, 0xfffffdcc, 0x00000233, 0xfffffdcd, 0x00000231, 
+	0xfffffdcf, 0x00000230, 0xfffffdd0, 0x0000022e, 0xfffffdd2, 0x0000022d, 
+	0xfffffdd3, 0x0000022b, 0xfffffdd5, 0x0000022a, 0xfffffdd6, 0x00000228, 
+	0xfffffdd8, 0x00000227, 0xfffffdd9, 0x00000225, 0xfffffddb, 0x00000224, 
+	0xfffffddc, 0x00000222, 0xfffffdde, 0x00000221, 0xfffffddf, 0x0000021f, 
+	0xfffffde1, 0x0000021e, 0xfffffde2, 0x0000021c, 0xfffffde4, 0x0000021b, 
+	0xfffffde5, 0x00000219, 0xfffffde7, 0x00000218, 0xfffffde8, 0x00000216, 
+	0xfffffdea, 0x00000215, 0xfffffdeb, 0x00000214, 0xfffffdec, 0x00000212, 
+	0xfffffdee, 0x00000211, 0xfffffdef, 0x0000020f, 0xfffffdf1, 0x0000020e, 
+	0xfffffdf2, 0x0000020c, 0xfffffdf4, 0x0000020b, 0xfffffdf5, 0x0000020a, 
+	0xfffffdf6, 0x00000208, 0xfffffdf8, 0x00000207, 0xfffffdf9, 0x00000205, 
+	0xfffffdfb, 0x00000204, 0xfffffdfc, 0x00000203, 0xfffffdfd, 0x00000201, 
+	0xfffffdff, 0x00000200, 0xfffffe00, 0x000001fe, 0xfffffe02, 0x000001fd, 
+	0xfffffe03, 0x000001fb, 0xfffffe05, 0x000001fa, 0xfffffe06, 0x000001f9, 
+	0xfffffe07, 0x000001f7, 0xfffffe09, 0x000001f6, 0xfffffe0a, 0x000001f5, 
+	0xfffffe0b, 0x000001f3, 0xfffffe0d, 0x000001f2, 0xfffffe0e, 0x000001f1, 
+	0xfffffe0f, 0x000001ef, 0xfffffe11, 0x000001ee, 0xfffffe12, 0x000001ed, 
+	0xfffffe13, 0x000001eb, 0xfffffe15, 0x000001ea, 0xfffffe16, 0x000001e9, 
+	0xfffffe17, 0x000001e7, 0xfffffe19, 0x000001e6, 0xfffffe1a, 0x000001e5, 
+	0xfffffe1b, 0x000001e3, 0xfffffe1d, 0x000001e2, 0xfffffe1e, 0x000001e1, 
+	0xfffffe1f, 0x000001df, 0xfffffe21, 0x000001de, 0xfffffe22, 0x000001dd, 
+	0xfffffe23, 0x000001dc, 0xfffffe24, 0x000001da, 0xfffffe26, 0x000001d9, 
+	0xfffffe27, 0x000001d8, 0xfffffe28, 0x000001d6, 0xfffffe2a, 0x000001d5, 
+	0xfffffe2b, 0x000001d4, 0xfffffe2c, 0x000001d3, 0xfffffe2d, 0x000001d1, 
+	0xfffffe2f, 0x000001d0, 0xfffffe30, 0x000001cf, 0xfffffe31, 0x000001ce, 
+	0xfffffe32, 0x000001cc, 0xfffffe34, 0x000001cb, 0xfffffe35, 0x000001ca, 
+	0xfffffe36, 0x000001c9, 0xfffffe37, 0x000001c7, 0xfffffe39, 0x000001c6, 
+	0xfffffe3a, 0x000001c5, 0xfffffe3b, 0x000001c4, 0xfffffe3c, 0x000001c2, 
+	0xfffffe3e, 0x000001c1, 0xfffffe3f, 0x000001c0, 0xfffffe40, 0x000001bf, 
+	0xfffffe41, 0x000001be, 0xfffffe42, 0x000001bc, 0xfffffe44, 0x000001bb, 
+	0xfffffe45, 0x000001ba, 0xfffffe46, 0x000001b9, 0xfffffe47, 0x000001b8, 
+	0xfffffe48, 0x000001b6, 0xfffffe4a, 0x000001b5, 0xfffffe4b, 0x000001b4, 
+	0xfffffe4c, 0x000001b3, 0xfffffe4d, 0x000001b2, 0xfffffe4e, 0x000001b1, 
+	0xfffffe4f, 0x000001af, 0xfffffe51, 0x000001ae, 0xfffffe52, 0x000001ad, 
+	0xfffffe53, 0x000001ac, 0xfffffe54, 0x000001ab, 0xfffffe55, 0x000001aa, 
+	0xfffffe56, 0x000001a8, 0xfffffe58, 0x000001a7, 0xfffffe59, 0x000001a6, 
+	0xfffffe5a, 0x000001a5, 0xfffffe5b, 0x000001a4, 0xfffffe5c, 0x000001a3, 
+	0xfffffe5d, 0x000001a2, 0xfffffe5e, 0x000001a0, 0xfffffe60, 0x0000019f, 
+	0xfffffe61, 0x0000019e, 0xfffffe62, 0x0000019d, 0xfffffe63, 0x0000019c, 
+	0xfffffe64, 0x0000019b, 0xfffffe65, 0x0000019a, 0xfffffe66, 0x00000199, 
+	0xfffffe67, 0x00000197, 0xfffffe69, 0x00000196, 0xfffffe6a, 0x00000195, 
+	0xfffffe6b, 0x00000194, 0xfffffe6c, 0x00000193, 0xfffffe6d, 0x00000192, 
+	0xfffffe6e, 0x00000191, 0xfffffe6f, 0x00000190, 0xfffffe70, 0x0000018f, 
+	0xfffffe71, 0x0000018e, 0xfffffe72, 0x0000018d, 0xfffffe73, 0x0000018c, 
+	0xfffffe74, 0x0000018a, 0xfffffe76, 0x00000189, 0xfffffe77, 0x00000188, 
+	0xfffffe78, 0x00000187, 0xfffffe79, 0x00000186, 0xfffffe7a, 0x00000185, 
+	0xfffffe7b, 0x00000184, 0xfffffe7c, 0x00000183, 0xfffffe7d, 0x00000182, 
+	0xfffffe7e, 0x00000181, 0xfffffe7f, 0x00000180, 0xfffffe80, 0x0000017f, 
+	0xfffffe81, 0x0000017e, 0xfffffe82, 0x0000017d, 0xfffffe83, 0x0000017c, 
+	0xfffffe84, 0x0000017b, 0xfffffe85, 0x0000017a, 0xfffffe86, 0x00000179, 
+	0xfffffe87, 0x00000178, 0xfffffe88, 0x00000177, 0xfffffe89, 0x00000176, 
+	0xfffffe8a, 0x00000175, 0xfffffe8b, 0x00000174, 0xfffffe8c, 0x00000173, 
+	0xfffffe8d, 0x00000172, 0xfffffe8e, 0x00000171, 0xfffffe8f, 0x00000170, 
+	0xfffffe90, 0x0000016f, 0xfffffe91, 0x0000016e, 0xfffffe92, 0x0000016d, 
+	0xfffffe93, 0x0000016c, 0xfffffe94, 0x0000016b, 0xfffffe95, 0x0000016a, 
+	0xfffffe96, 0x00000169, 0xfffffe97, 0x00000168, 0xfffffe98, 0x00000167, 
+	0xfffffe99, 0x00000166, 0xfffffe9a, 0x00000165, 0xfffffe9b, 0x00000164, 
+	0xfffffe9c, 0x00000163, 0xfffffe9d, 0x00000162, 0xfffffe9e, 0x00000161, 
+	0xfffffe9f, 0x00000160, 0xfffffea0, 0x0000015f, 0xfffffea1, 0x0000015e, 
+	0xfffffea2, 0x0000015d, 0xfffffea3, 0x0000015c, 0xfffffea4, 0x0000015b, 
+	0xfffffea5, 0x0000015a, 0xfffffea6, 0x00000159, 0xfffffea7, 0x00000158, 
+	0xfffffea8, 0x00000158, 0xfffffea8, 0x00000157, 0xfffffea9, 0x00000156, 
+	0xfffffeaa, 0x00000155, 0xfffffeab, 0x00000154, 0xfffffeac, 0x00000153, 
+	0xfffffead, 0x00000152, 0xfffffeae, 0x00000151, 0xfffffeaf, 0x00000150, 
+	0xfffffeb0, 0x0000014f, 0xfffffeb1, 0x0000014e, 0xfffffeb2, 0x0000014d, 
+	0xfffffeb3, 0x0000014d, 0xfffffeb3, 0x0000014c, 0xfffffeb4, 0x0000014b, 
+	0xfffffeb5, 0x0000014a, 0xfffffeb6, 0x00000149, 0xfffffeb7, 0x00000148, 
+	0xfffffeb8, 0x00000147, 0xfffffeb9, 0x00000146, 0xfffffeba, 0x00000145, 
+	0xfffffebb, 0x00000145, 0xfffffebb, 0x00000144, 0xfffffebc, 0x00000143, 
+	0xfffffebd, 0x00000142, 0xfffffebe, 0x00000141, 0xfffffebf, 0x00000140, 
+	0xfffffec0, 0x0000013f, 0xfffffec1, 0x0000013e, 0xfffffec2, 0x0000013e, 
+	0xfffffec2, 0x0000013d, 0xfffffec3, 0x0000013c, 0xfffffec4, 0x0000013b, 
+	0xfffffec5, 0x0000013a, 0xfffffec6, 0x00000139, 0xfffffec7, 0x00000138, 
+	0xfffffec8, 0x00000138, 0xfffffec8, 0x00000137, 0xfffffec9, 0x00000136, 
+	0xfffffeca, 0x00000135, 0xfffffecb, 0x00000134, 0xfffffecc, 0x00000133, 
+	0xfffffecd, 0x00000133, 0xfffffecd, 0x00000132, 0xfffffece, 0x00000131, 
+	0xfffffecf, 0x00000130, 0xfffffed0, 0x0000012f, 0xfffffed1, 0x0000012e, 
+	0xfffffed2, 0x0000012e, 0xfffffed2, 0x0000012d, 0xfffffed3, 0x0000012c, 
+	0xfffffed4, 0x0000012b, 0xfffffed5, 0x0000012a, 0xfffffed6, 0x0000012a, 
+	0xfffffed6, 0x00000129, 0xfffffed7, 0x00000128, 0xfffffed8, 0x00000127, 
+	0xfffffed9, 0x00000126, 0xfffffeda, 0x00000126, 0xfffffeda, 0x00000125, 
+	0xfffffedb, 0x00000124, 0xfffffedc, 0x00000123, 0xfffffedd, 0x00000122, 
+	0xfffffede, 0x00000122, 0xfffffede, 0x00000121, 0xfffffedf, 0x00000120, 
+	0xfffffee0, 0x0000011f, 0xfffffee1, 0x0000011e, 0xfffffee2, 0x0000011e, 
+	0xfffffee2, 0x0000011d, 0xfffffee3, 0x0000011c, 0xfffffee4, 0x0000011b, 
+	0xfffffee5, 0x0000011b, 0xfffffee5, 0x0000011a, 0xfffffee6, 0x00000119, 
+	0xfffffee7, 0x00000118, 0xfffffee8, 0x00000118, 0xfffffee8, 0x00000117, 
+	0xfffffee9, 0x00000116, 0xfffffeea, 0x00000115, 0xfffffeeb, 0x00000115, 
+	0xfffffeeb, 0x00000114, 0xfffffeec, 0x00000113, 0xfffffeed, 0x00000112, 
+	0xfffffeee, 0x00000112, 0xfffffeee, 0x00000111, 0xfffffeef, 0x00000110, 
+	0xfffffef0, 0x0000010f, 0xfffffef1, 0x0000010f, 0xfffffef1, 0x0000010e, 
+	0xfffffef2, 0x0000010d, 0xfffffef3, 0x0000010c, 0xfffffef4, 0x0000010c, 
+	0xfffffef4, 0x0000010b, 0xfffffef5, 0x0000010a, 0xfffffef6, 0x0000010a, 
+	0xfffffef6, 0x00000109, 0xfffffef7, 0x00000108, 0xfffffef8, 0x00000107, 
+	0xfffffef9, 0x00000107, 0xfffffef9, 0x00000106, 0xfffffefa, 0x00000105, 
+	0xfffffefb, 0x00000105, 0xfffffefb, 0x00000104, 0xfffffefc, 0x00000103, 
+	0xfffffefd, 0x00000102, 0xfffffefe, 0x00000102, 0xfffffefe, 0x00000101, 
+	0xfffffeff, 0x00000100, 0xffffff00, 0x00000100, 0xffffff00, 0x000000ff, 
+	0xffffff01, 0x000000fe, 0xffffff02, 0x000000fd, 0xffffff03, 0x000000fd, 
+	0xffffff03, 0x000000fc, 0xffffff04, 0x000000fb, 0xffffff05, 0x000000fb, 
+	0xffffff05, 0x000000fa, 0xffffff06, 0x000000f9, 0xffffff07, 0x000000f9, 
+	0xffffff07, 0x000000f8, 0xffffff08, 0x000000f7, 0xffffff09, 0x000000f7, 
+	0xffffff09, 0x000000f6, 0xffffff0a, 0x000000f5, 0xffffff0b, 0x000000f5, 
+	0xffffff0b, 0x000000f4, 0xffffff0c, 0x000000f3, 0xffffff0d, 0x000000f3, 
+	0xffffff0d, 0x000000f2, 0xffffff0e, 0x000000f1, 0xffffff0f, 0x000000f1, 
+	0xffffff0f, 0x000000f0, 0xffffff10, 0x000000ef, 0xffffff11, 0x000000ef, 
+	0xffffff11, 0x000000ee, 0xffffff12, 0x000000ee, 0xffffff12, 0x000000ed, 
+	0xffffff13, 0x000000ec, 0xffffff14, 0x000000ec, 0xffffff14, 0x000000eb, 
+	0xffffff15, 0x000000ea, 0xffffff16, 0x000000ea, 0xffffff16, 0x000000e9, 
+	0xffffff17, 0x000000e8, 0xffffff18, 0x000000e8, 0xffffff18, 0x000000e7, 
+	0xffffff19, 0x000000e7, 0xffffff19, 0x000000e6, 0xffffff1a, 0x000000e5, 
+	0xffffff1b, 0x000000e5, 0xffffff1b, 0x000000e4, 0xffffff1c, 0x000000e3, 
+	0xffffff1d, 0x000000e3, 0xffffff1d, 0x000000e2, 0xffffff1e, 0x000000e2, 
+	0xffffff1e, 0x000000e1, 0xffffff1f, 0x000000e0, 0xffffff20, 0x000000e0, 
+	0xffffff20, 0x000000df, 0xffffff21, 0x000000df, 0xffffff21, 0x000000de, 
+	0xffffff22, 0x000000dd, 0xffffff23, 0x000000dd, 0xffffff23, 0x000000dc, 
+	0xffffff24, 0x000000dc, 0xffffff24, 0x000000db, 0xffffff25, 0x000000da, 
+	0xffffff26, 0x000000da, 0xffffff26, 0x000000d9, 0xffffff27, 0x000000d9, 
+	0xffffff27, 0x000000d8, 0xffffff28, 0x000000d7, 0xffffff29, 0x000000d7, 
+	0xffffff29, 0x000000d6, 0xffffff2a, 0x000000d6, 0xffffff2a, 0x000000d5, 
+	0xffffff2b, 0x000000d5, 0xffffff2b, 0x000000d4, 0xffffff2c, 0x000000d3, 
+	0xffffff2d, 0x000000d3, 0xffffff2d, 0x000000d2, 0xffffff2e, 0x000000d2, 
+	0xffffff2e, 0x000000d1, 0xffffff2f, 0x000000d1, 0xffffff2f, 0x000000d0, 
+	0xffffff30, 0x000000cf, 0xffffff31, 0x000000cf, 0xffffff31, 0x000000ce, 
+	0xffffff32, 0x000000ce, 0xffffff32, 0x000000cd, 0xffffff33, 0x000000cd, 
+	0xffffff33, 0x000000cc, 0xffffff34, 0x000000cb, 0xffffff35, 0x000000cb, 
+	0xffffff35, 0x000000ca, 0xffffff36, 0x000000ca, 0xffffff36, 0x000000c9, 
+	0xffffff37, 0x000000c9, 0xffffff37, 0x000000c8, 0xffffff38, 0x000000c8, 
+	0xffffff38, 0x000000c7, 0xffffff39, 0x000000c7, 0xffffff39, 0x000000c6, 
+	0xffffff3a, 0x000000c6, 0xffffff3a, 0x000000c5, 0xffffff3b, 0x000000c4, 
+	0xffffff3c, 0x000000c4, 0xffffff3c, 0x000000c3, 0xffffff3d, 0x000000c3, 
+	0xffffff3d, 0x000000c2, 0xffffff3e, 0x000000c2, 0xffffff3e, 0x000000c1, 
+	0xffffff3f, 0x000000c1, 0xffffff3f, 0x000000c0, 0xffffff40, 0x000000c0, 
+	0xffffff40, 0x000000bf, 0xffffff41, 0x000000bf, 0xffffff41, 0x000000be, 
+	0xffffff42, 0x000000be, 0xffffff42, 0x000000bd, 0xffffff43, 0x000000bd, 
+	0xffffff43, 0x000000bc, 0xffffff44, 0x000000bc, 0xffffff44, 0x000000bb, 
+	0xffffff45, 0x000000bb, 0xffffff45, 0x000000ba, 0xffffff46, 0x000000ba, 
+	0xffffff46, 0x000000b9, 0xffffff47, 0x000000b9, 0xffffff47, 0x000000b8, 
+	0xffffff48, 0x000000b8, 0xffffff48, 0x000000b7, 0xffffff49, 0x000000b7, 
+	0xffffff49, 0x000000b6, 0xffffff4a, 0x000000b6, 0xffffff4a, 0x000000b5, 
+	0xffffff4b, 0x000000b5, 0xffffff4b, 0x000000b4, 0xffffff4c, 0x000000b4, 
+	0xffffff4c, 0x000000b3, 0xffffff4d, 0x000000b3, 0xffffff4d, 0x000000b2, 
+	0xffffff4e, 0x000000b2, 0xffffff4e, 0x000000b1, 0xffffff4f, 0x000000b1, 
+	0xffffff4f, 0x000000b0, 0xffffff50, 0x000000b0, 0xffffff50, 0x000000af, 
+	0xffffff51, 0x000000af, 0xffffff51, 0x000000ae, 0xffffff52, 0x000000ae, 
+	0xffffff52, 0x000000ad, 0xffffff53, 0x000000ad, 0xffffff53, 0x000000ac, 
+	0xffffff54, 0x000000ac, 0xffffff54, 0x000000ac, 0xffffff54, 0x000000ab, 
+	0xffffff55, 0x000000ab, 0xffffff55, 0x000000aa, 0xffffff56, 0x000000aa, 
+	0xffffff56, 0x000000a9, 0xffffff57, 0x000000a9, 0xffffff57, 0x000000a8, 
+	0xffffff58, 0x000000a8, 0xffffff58, 0x000000a7, 0xffffff59, 0x000000a7, 
+	0xffffff59, 0x000000a6, 0xffffff5a, 0x000000a6, 0xffffff5a, 0x000000a6, 
+	0xffffff5a, 0x000000a5, 0xffffff5b, 0x000000a5, 0xffffff5b, 0x000000a4, 
+	0xffffff5c, 0x000000a4, 0xffffff5c, 0x000000a3, 0xffffff5d, 0x000000a3, 
+	0xffffff5d, 0x000000a2, 0xffffff5e, 0x000000a2, 0xffffff5e, 0x000000a2, 
+	0xffffff5e, 0x000000a1, 0xffffff5f, 0x000000a1, 0xffffff5f, 0x000000a0, 
+	0xffffff60, 0x000000a0, 0xffffff60, 0x0000009f, 0xffffff61, 0x0000009f, 
+	0xffffff61, 0x0000009f, 0xffffff61, 0x0000009e, 0xffffff62, 0x0000009e, 
+	0xffffff62, 0x0000009d, 0xffffff63, 0x0000009d, 0xffffff63, 0x0000009c, 
+	0xffffff64, 0x0000009c, 0xffffff64, 0x0000009c, 0xffffff64, 0x0000009b, 
+	0xffffff65, 0x0000009b, 0xffffff65, 0x0000009a, 0xffffff66, 0x0000009a, 
+	0xffffff66, 0x00000099, 0xffffff67, 0x00000099, 0xffffff67, 0x00000099, 
+	0xffffff67, 0x00000098, 0xffffff68, 0x00000098, 0xffffff68, 0x00000097, 
+	0xffffff69, 0x00000097, 0xffffff69, 0x00000097, 0xffffff69, 0x00000096, 
+	0xffffff6a, 0x00000096, 0xffffff6a, 0x00000095, 0xffffff6b, 0x00000095, 
+	0xffffff6b, 0x00000095, 0xffffff6b, 0x00000094, 0xffffff6c, 0x00000094, 
+	0xffffff6c, 0x00000093, 0xffffff6d, 0x00000093, 0xffffff6d, 0x00000093, 
+	0xffffff6d, 0x00000092, 0xffffff6e, 0x00000092, 0xffffff6e, 0x00000091, 
+	0xffffff6f, 0x00000091, 0xffffff6f, 0x00000091, 0xffffff6f, 0x00000090, 
+	0xffffff70, 0x00000090, 0xffffff70, 0x0000008f, 0xffffff71, 0x0000008f, 
+	0xffffff71, 0x0000008f, 0xffffff71, 0x0000008e, 0xffffff72, 0x0000008e, 
+	0xffffff72, 0x0000008d, 0xffffff73, 0x0000008d, 0xffffff73, 0x0000008d, 
+	0xffffff73, 0x0000008c, 0xffffff74, 0x0000008c, 0xffffff74, 0x0000008c, 
+	0xffffff74, 0x0000008b, 0xffffff75, 0x0000008b, 0xffffff75, 0x0000008a, 
+	0xffffff76, 0x0000008a, 0xffffff76, 0x0000008a, 0xffffff76, 0x00000089, 
+	0xffffff77, 0x00000089, 0xffffff77, 0x00000089, 0xffffff77, 0x00000088, 
+	0xffffff78, 0x00000088, 0xffffff78, 0x00000087, 0xffffff79, 0x00000087, 
+	0xffffff79, 0x00000087, 0xffffff79, 0x00000086, 0xffffff7a, 0x00000086, 
+	0xffffff7a, 0x00000086, 0xffffff7a, 0x00000085, 0xffffff7b, 0x00000085, 
+	0xffffff7b, 0x00000085, 0xffffff7b, 0x00000084, 0xffffff7c, 0x00000084, 
+	0xffffff7c, 0x00000083, 0xffffff7d, 0x00000083, 0xffffff7d, 0x00000083, 
+	0xffffff7d, 0x00000082, 0xffffff7e, 0x00000082, 0xffffff7e, 0x00000082, 
+	0xffffff7e, 0x00000081, 0xffffff7f, 0x00000081, 0xffffff7f, 0x00000081, 
+	0xffffff7f, 0x00000080, 0xffffff80, 0x00000080, 0xffffff80, 0x00000080, 
+	0xffffff80, 0x0000007f, 0xffffff81, 0x0000007f, 0xffffff81, 0x0000007e, 
+	0xffffff82, 0x0000007e, 0xffffff82, 0x0000007e, 0xffffff82, 0x0000007d, 
+	0xffffff83, 0x0000007d, 0xffffff83, 0x0000007d, 0xffffff83, 0x0000007c, 
+	0xffffff84, 0x0000007c, 0xffffff84, 0x0000007c, 0xffffff84, 0x0000007b, 
+	0xffffff85, 0x0000007b, 0xffffff85, 0x0000007b, 0xffffff85, 0x0000007a, 
+	0xffffff86, 0x0000007a, 0xffffff86, 0x0000007a, 0xffffff86, 0x00000079, 
+	0xffffff87, 0x00000079, 0xffffff87, 0x00000079, 0xffffff87, 0x00000078, 
+	0xffffff88, 0x00000078, 0xffffff88, 0x00000078, 0xffffff88, 0x00000077, 
+	0xffffff89, 0x00000077, 0xffffff89, 0x00000077, 0xffffff89, 0x00000077, 
+	0xffffff89, 0x00000076, 0xffffff8a, 0x00000076, 0xffffff8a, 0x00000076, 
+	0xffffff8a, 0x00000075, 0xffffff8b, 0x00000075, 0xffffff8b, 0x00000075, 
+	0xffffff8b, 0x00000074, 0xffffff8c, 0x00000074, 0xffffff8c, 0x00000074, 
+	0xffffff8c, 0x00000073, 0xffffff8d, 0x00000073, 0xffffff8d, 0x00000073, 
+	0xffffff8d, 0x00000072, 0xffffff8e, 0x00000072, 0xffffff8e, 0x00000072, 
+	0xffffff8e, 0x00000071, 0xffffff8f, 0x00000071, 0xffffff8f, 0x00000071, 
+	0xffffff8f, 0x00000071, 0xffffff8f, 0x00000070, 0xffffff90, 0x00000070, 
+	0xffffff90, 0x00000070, 0xffffff90, 0x0000006f, 0xffffff91, 0x0000006f, 
+	0xffffff91, 0x0000006f, 0xffffff91, 0x0000006e, 0xffffff92, 0x0000006e, 
+	0xffffff92, 0x0000006e, 0xffffff92, 0x0000006e, 0xffffff92, 0x0000006d, 
+	0xffffff93, 0x0000006d, 0xffffff93, 0x0000006d, 0xffffff93, 0x0000006c, 
+	0xffffff94, 0x0000006c, 0xffffff94, 0x0000006c, 0xffffff94, 0x0000006b, 
+	0xffffff95, 0x0000006b, 0xffffff95, 0x0000006b, 0xffffff95, 0x0000006b, 
+	0xffffff95, 0x0000006a, 0xffffff96, 0x0000006a, 0xffffff96, 0x0000006a, 
+	0xffffff96, 0x00000069, 0xffffff97, 0x00000069, 0xffffff97, 0x00000069, 
+	0xffffff97, 0x00000069, 0xffffff97, 0x00000068, 0xffffff98, 0x00000068, 
+	0xffffff98, 0x00000068, 0xffffff98, 0x00000067, 0xffffff99, 0x00000067, 
+	0xffffff99, 0x00000067, 0xffffff99, 0x00000067, 0xffffff99, 0x00000066, 
+	0xffffff9a, 0x00000066, 0xffffff9a, 0x00000066, 0xffffff9a, 0x00000065, 
+	0xffffff9b, 0x00000065, 0xffffff9b, 0x00000065, 0xffffff9b, 0x00000065, 
+	0xffffff9b, 0x00000064, 0xffffff9c, 0x00000064, 0xffffff9c, 0x00000064, 
+	0xffffff9c, 0x00000064, 0xffffff9c, 0x00000063, 0xffffff9d, 0x00000063, 
+	0xffffff9d, 0x00000063, 0xffffff9d, 0x00000063, 0xffffff9d, 0x00000062, 
+	0xffffff9e, 0x00000062, 0xffffff9e, 0x00000062, 0xffffff9e, 0x00000061, 
+	0xffffff9f, 0x00000061, 0xffffff9f, 0x00000061, 0xffffff9f, 0x00000061, 
+	0xffffff9f, 0x00000060, 0xffffffa0, 0x00000060, 0xffffffa0, 0x00000060, 
+	0xffffffa0, 0x00000060, 0xffffffa0, 0x0000005f, 0xffffffa1, 0x0000005f, 
+	0xffffffa1, 0x0000005f, 0xffffffa1, 0x0000005f, 0xffffffa1, 0x0000005e, 
+	0xffffffa2, 0x0000005e, 0xffffffa2, 0x0000005e, 0xffffffa2, 0x0000005e, 
+	0xffffffa2, 0x0000005d, 0xffffffa3, 0x0000005d, 0xffffffa3, 0x0000005d, 
+	0xffffffa3, 0x0000005d, 0xffffffa3, 0x0000005c, 0xffffffa4, 0x0000005c, 
+	0xffffffa4, 0x0000005c, 0xffffffa4, 0x0000005c, 0xffffffa4, 0x0000005b, 
+	0xffffffa5, 0x0000005b, 0xffffffa5, 0x0000005b, 0xffffffa5, 0x0000005b, 
+	0xffffffa5, 0x0000005a, 0xffffffa6, 0x0000005a, 0xffffffa6, 0x0000005a, 
+	0xffffffa6, 0x0000005a, 0xffffffa6, 0x00000059, 0xffffffa7, 0x00000059, 
+	0xffffffa7, 0x00000059, 0xffffffa7, 0x00000059, 0xffffffa7, 0x00000058, 
+	0xffffffa8, 0x00000058, 0xffffffa8, 0x00000058, 0xffffffa8, 0x00000058, 
+	0xffffffa8, 0x00000057, 0xffffffa9, 0x00000057, 0xffffffa9, 0x00000057, 
+	0xffffffa9, 0x00000057, 0xffffffa9, 0x00000056, 0xffffffaa, 0x00000056, 
+	0xffffffaa, 0x00000056, 0xffffffaa, 0x00000056, 0xffffffaa, 0x00000056, 
+	0xffffffaa, 0x00000055, 0xffffffab, 0x00000055, 0xffffffab, 0x00000055, 
+	0xffffffab, 0x00000055, 0xffffffab, 0x00000054, 0xffffffac, 0x00000054, 
+	0xffffffac, 0x00000054, 0xffffffac, 0x00000054, 0xffffffac, 0x00000053, 
+	0xffffffad, 0x00000053, 0xffffffad, 0x00000053, 0xffffffad, 0x00000053, 
+	0xffffffad, 0x00000053, 0xffffffad, 0x00000052, 0xffffffae, 0x00000052, 
+	0xffffffae, 0x00000052, 0xffffffae, 0x00000052, 0xffffffae, 0x00000051, 
+	0xffffffaf, 0x00000051, 0xffffffaf, 0x00000051, 0xffffffaf, 0x00000051, 
+	0xffffffaf, 0x00000051, 0xffffffaf, 0x00000050, 0xffffffb0, 0x00000050, 
+	0xffffffb0, 0x00000050, 0xffffffb0, 0x00000050, 0xffffffb0, 0x0000004f, 
+	0xffffffb1, 0x0000004f, 0xffffffb1, 0x0000004f, 0xffffffb1, 0x0000004f, 
+	0xffffffb1, 0x0000004f, 0xffffffb1, 0x0000004e, 0xffffffb2, 0x0000004e, 
+	0xffffffb2, 0x0000004e, 0xffffffb2, 0x0000004e, 0xffffffb2, 0x0000004e, 
+	0xffffffb2, 0x0000004d, 0xffffffb3, 0x0000004d, 0xffffffb3, 0x0000004d, 
+	0xffffffb3, 0x0000004d, 0xffffffb3, 0x0000004c, 0xffffffb4, 0x0000004c, 
+	0xffffffb4, 0x0000004c, 0xffffffb4, 0x0000004c, 0xffffffb4, 0x0000004c, 
+	0xffffffb4, 0x0000004b, 0xffffffb5, 0x0000004b, 0xffffffb5, 0x0000004b, 
+	0xffffffb5, 0x0000004b, 0xffffffb5, 0x0000004b, 0xffffffb5, 0x0000004a, 
+	0xffffffb6, 0x0000004a, 0xffffffb6, 0x0000004a, 0xffffffb6, 0x0000004a, 
+	0xffffffb6, 0x0000004a, 0xffffffb6, 0x00000049, 0xffffffb7, 0x00000049, 
+	0xffffffb7, 0x00000049, 0xffffffb7, 0x00000049, 0xffffffb7, 0x00000049, 
+	0xffffffb7, 0x00000048, 0xffffffb8, 0x00000048, 0xffffffb8, 0x00000048, 
+	0xffffffb8, 0x00000048, 0xffffffb8, 0x00000048, 0xffffffb8, 0x00000047, 
+	0xffffffb9, 0x00000047, 0xffffffb9, 0x00000047, 0xffffffb9, 0x00000047, 
+	0xffffffb9, 0x00000047, 0xffffffb9, 0x00000046, 0xffffffba, 0x00000046, 
+	0xffffffba, 0x00000046, 0xffffffba, 0x00000046, 0xffffffba, 0x00000046, 
+	0xffffffba, 0x00000046, 0xffffffba, 0x00000045, 0xffffffbb, 0x00000045, 
+	0xffffffbb, 0x00000045, 0xffffffbb, 0x00000045, 0xffffffbb, 0x00000045, 
+	0xffffffbb, 0x00000044, 0xffffffbc, 0x00000044, 0xffffffbc, 0x00000044, 
+	0xffffffbc, 0x00000044, 0xffffffbc, 0x00000044, 0xffffffbc, 0x00000043, 
+	0xffffffbd, 0x00000043, 0xffffffbd, 0x00000043, 0xffffffbd, 0x00000043, 
+	0xffffffbd, 0x00000043, 0xffffffbd, 0x00000043, 0xffffffbd, 0x00000042, 
+	0xffffffbe, 0x00000042, 0xffffffbe, 0x00000042, 0xffffffbe, 0x00000042, 
+	0xffffffbe, 0x00000042, 0xffffffbe, 0x00000041, 0xffffffbf, 0x00000041, 
+	0xffffffbf, 0x00000041, 0xffffffbf, 0x00000041, 0xffffffbf, 0x00000041, 
+	0xffffffbf, 0x00000041, 0xffffffbf, 0x00000040, 0xffffffc0, 0x00000040, 
+	0xffffffc0, 0x00000040, 0xffffffc0, 0x00000040, 0xffffffc0, 0x00000040, 
+	0xffffffc0, 0x00000040, 0xffffffc0, 0x0000003f, 0xffffffc1, 0x0000003f, 
+	0xffffffc1, 0x0000003f, 0xffffffc1, 0x0000003f, 0xffffffc1, 0x0000003f, 
+	0xffffffc1, 0x0000003e, 0xffffffc2, 0x0000003e, 0xffffffc2, 0x0000003e, 
+	0xffffffc2, 0x0000003e, 0xffffffc2, 0x0000003e, 0xffffffc2, 0x0000003e, 
+	0xffffffc2, 0x0000003d, 0xffffffc3, 0x0000003d, 0xffffffc3, 0x0000003d, 
+	0xffffffc3, 0x0000003d, 0xffffffc3, 0x0000003d, 0xffffffc3, 0x0000003d, 
+	0xffffffc3, 0x0000003c, 0xffffffc4, 0x0000003c, 0xffffffc4, 0x0000003c, 
+	0xffffffc4, 0x0000003c, 0xffffffc4, 0x0000003c, 0xffffffc4, 0x0000003c, 
+	0xffffffc4, 0x0000003b, 0xffffffc5, 0x0000003b, 0xffffffc5, 0x0000003b, 
+	0xffffffc5, 0x0000003b, 0xffffffc5, 0x0000003b, 0xffffffc5, 0x0000003b, 
+	0xffffffc5, 0x0000003b, 0xffffffc5, 0x0000003a, 0xffffffc6, 0x0000003a, 
+	0xffffffc6, 0x0000003a, 0xffffffc6, 0x0000003a, 0xffffffc6, 0x0000003a, 
+	0xffffffc6, 0x0000003a, 0xffffffc6, 0x00000039, 0xffffffc7, 0x00000039, 
+	0xffffffc7, 0x00000039, 0xffffffc7, 0x00000039, 0xffffffc7, 0x00000039, 
+	0xffffffc7, 0x00000039, 0xffffffc7, 0x00000038, 0xffffffc8, 0x00000038, 
+	0xffffffc8, 0x00000038, 0xffffffc8, 0x00000038, 0xffffffc8, 0x00000038, 
+	0xffffffc8, 0x00000038, 0xffffffc8, 0x00000038, 0xffffffc8, 0x00000037, 
+	0xffffffc9, 0x00000037, 0xffffffc9, 0x00000037, 0xffffffc9, 0x00000037, 
+	0xffffffc9, 0x00000037, 0xffffffc9, 0x00000037, 0xffffffc9, 0x00000037, 
+	0xffffffc9, 0x00000036, 0xffffffca, 0x00000036, 0xffffffca, 0x00000036, 
+	0xffffffca, 0x00000036, 0xffffffca, 0x00000036, 0xffffffca, 0x00000036, 
+	0xffffffca, 0x00000035, 0xffffffcb, 0x00000035, 0xffffffcb, 0x00000035, 
+	0xffffffcb, 0x00000035, 0xffffffcb, 0x00000035, 0xffffffcb, 0x00000035, 
+	0xffffffcb, 0x00000035, 0xffffffcb, 0x00000034, 0xffffffcc, 0x00000034, 
+	0xffffffcc, 0x00000034, 0xffffffcc, 0x00000034, 0xffffffcc, 0x00000034, 
+	0xffffffcc, 0x00000034, 0xffffffcc, 0x00000034, 0xffffffcc, 0x00000033, 
+	0xffffffcd, 0x00000033, 0xffffffcd, 0x00000033, 0xffffffcd, 0x00000033, 
+	0xffffffcd, 0x00000033, 0xffffffcd, 0x00000033, 0xffffffcd, 0x00000033, 
+	0xffffffcd, 0x00000032, 0xffffffce, 0x00000032, 0xffffffce, 0x00000032, 
+	0xffffffce, 0x00000032, 0xffffffce, 0x00000032, 0xffffffce, 0x00000032, 
+	0xffffffce, 0x00000032, 0xffffffce, 0x00000032, 0xffffffce, 0x00000031, 
+	0xffffffcf, 0x00000031, 0xffffffcf, 0x00000031, 0xffffffcf, 0x00000031, 
+	0xffffffcf, 0x00000031, 0xffffffcf, 0x00000031, 0xffffffcf, 0x00000031, 
+	0xffffffcf, 0x00000030, 0xffffffd0, 0x00000030, 0xffffffd0, 0x00000030, 
+	0xffffffd0, 0x00000030, 0xffffffd0, 0x00000030, 0xffffffd0, 0x00000030, 
+	0xffffffd0, 0x00000030, 0xffffffd0, 0x00000030, 0xffffffd0, 0x0000002f, 
+	0xffffffd1, 0x0000002f, 0xffffffd1, 0x0000002f, 0xffffffd1, 0x0000002f, 
+	0xffffffd1, 0x0000002f, 0xffffffd1, 0x0000002f, 0xffffffd1, 0x0000002f, 
+	0xffffffd1, 0x0000002f, 0xffffffd1, 0x0000002e, 0xffffffd2, 0x0000002e, 
+	0xffffffd2, 0x0000002e, 0xffffffd2, 0x0000002e, 0xffffffd2, 0x0000002e, 
+	0xffffffd2, 0x0000002e, 0xffffffd2, 0x0000002e, 0xffffffd2, 0x0000002e, 
+	0xffffffd2, 0x0000002d, 0xffffffd3, 0x0000002d, 0xffffffd3, 0x0000002d, 
+	0xffffffd3, 0x0000002d, 0xffffffd3, 0x0000002d, 0xffffffd3, 0x0000002d, 
+	0xffffffd3, 0x0000002d, 0xffffffd3, 0x0000002d, 0xffffffd3, 0x0000002c, 
+	0xffffffd4, 0x0000002c, 0xffffffd4, 0x0000002c, 0xffffffd4, 0x0000002c, 
+	0xffffffd4, 0x0000002c, 0xffffffd4, 0x0000002c, 0xffffffd4, 0x0000002c, 
+	0xffffffd4, 0x0000002c, 0xffffffd4, 0x0000002b, 0xffffffd5, 0x0000002b, 
+	0xffffffd5, 0x0000002b, 0xffffffd5, 0x0000002b, 0xffffffd5, 0x0000002b, 
+	0xffffffd5, 0x0000002b, 0xffffffd5, 0x0000002b, 0xffffffd5, 0x0000002b, 
+	0xffffffd5, 0x0000002b, 0xffffffd5, 0x0000002a, 0xffffffd6, 0x0000002a, 
+	0xffffffd6, 0x0000002a, 0xffffffd6, 0x0000002a, 0xffffffd6, 0x0000002a, 
+	0xffffffd6, 0x0000002a, 0xffffffd6, 0x0000002a, 0xffffffd6, 0x0000002a, 
+	0xffffffd6, 0x00000029, 0xffffffd7, 0x00000029, 0xffffffd7, 0x00000029, 
+	0xffffffd7, 0x00000029, 0xffffffd7, 0x00000029, 0xffffffd7, 0x00000029, 
+	0xffffffd7, 0x00000029, 0xffffffd7, 0x00000029, 0xffffffd7, 0x00000029, 
+	0xffffffd7, 0x00000028, 0xffffffd8, 0x00000028, 0xffffffd8, 0x00000028, 
+	0xffffffd8, 0x00000028, 0xffffffd8, 0x00000028, 0xffffffd8, 0x00000028, 
+	0xffffffd8, 0x00000028, 0xffffffd8, 0x00000028, 0xffffffd8, 0x00000028, 
+	0xffffffd8, 0x00000027, 0xffffffd9, 0x00000027, 0xffffffd9, 0x00000027, 
+	0xffffffd9, 0x00000027, 0xffffffd9, 0x00000027, 0xffffffd9, 0x00000027, 
+	0xffffffd9, 0x00000027, 0xffffffd9, 0x00000027, 0xffffffd9, 0x00000027, 
+	0xffffffd9, 0x00000027, 0xffffffd9, 0x00000026, 0xffffffda, 0x00000026, 
+	0xffffffda, 0x00000026, 0xffffffda, 0x00000026, 0xffffffda, 0x00000026, 
+	0xffffffda, 0x00000026, 0xffffffda, 0x00000026, 0xffffffda, 0x00000026, 
+	0xffffffda, 0x00000026, 0xffffffda, 0x00000025, 0xffffffdb, 0x00000025, 
+	0xffffffdb, 0x00000025, 0xffffffdb, 0x00000025, 0xffffffdb, 0x00000025, 
+	0xffffffdb, 0x00000025, 0xffffffdb, 0x00000025, 0xffffffdb, 0x00000025, 
+	0xffffffdb, 0x00000025, 0xffffffdb, 0x00000025, 0xffffffdb, 0x00000024, 
+	0xffffffdc, 0x00000024, 0xffffffdc, 0x00000024, 0xffffffdc, 0x00000024, 
+	0xffffffdc, 0x00000024, 0xffffffdc, 0x00000024, 0xffffffdc, 0x00000024, 
+	0xffffffdc, 0x00000024, 0xffffffdc, 0x00000024, 0xffffffdc, 0x00000024, 
+	0xffffffdc, 0x00000023, 0xffffffdd, 0x00000023, 0xffffffdd, 0x00000023, 
+	0xffffffdd, 0x00000023, 0xffffffdd, 0x00000023, 0xffffffdd, 0x00000023, 
+	0xffffffdd, 0x00000023, 0xffffffdd, 0x00000023, 0xffffffdd, 0x00000023, 
+	0xffffffdd, 0x00000023, 0xffffffdd, 0x00000023, 0xffffffdd, 0x00000022, 
+	0xffffffde, 0x00000022, 0xffffffde, 0x00000022, 0xffffffde, 0x00000022, 
+	0xffffffde, 0x00000022, 0xffffffde, 0x00000022, 0xffffffde, 0x00000022, 
+	0xffffffde, 0x00000022, 0xffffffde, 0x00000022, 0xffffffde, 0x00000022, 
+	0xffffffde, 0x00000021, 0xffffffdf, 0x00000021, 0xffffffdf, 0x00000021, 
+	0xffffffdf, 0x00000021, 0xffffffdf, 0x00000021, 0xffffffdf, 0x00000021, 
+	0xffffffdf, 0x00000021, 0xffffffdf, 0x00000021, 0xffffffdf, 0x00000021, 
+	0xffffffdf, 0x00000021, 0xffffffdf, 0x00000021, 0xffffffdf, 0x00000020, 
+	0xffffffe0, 0x00000020, 0xffffffe0, 0x00000020, 0xffffffe0, 0x00000020, 
+	0xffffffe0, 0x00000020, 0xffffffe0, 0x00000020, 0xffffffe0, 0x00000020, 
+	0xffffffe0, 0x00000020, 0xffffffe0, 0x00000020, 0xffffffe0, 0x00000020, 
+	0xffffffe0, 0x00000020, 0xffffffe0, 0x00000020, 0xffffffe0, 0x0000001f, 
+	0xffffffe1, 0x0000001f, 0xffffffe1, 0x0000001f, 0xffffffe1, 0x0000001f, 
+	0xffffffe1, 0x0000001f, 0xffffffe1, 0x0000001f, 0xffffffe1, 0x0000001f, 
+	0xffffffe1, 0x0000001f, 0xffffffe1, 0x0000001f, 0xffffffe1, 0x0000001f, 
+	0xffffffe1, 0x0000001f, 0xffffffe1, 0x0000001e, 0xffffffe2, 0x0000001e, 
+	0xffffffe2, 0x0000001e, 0xffffffe2, 0x0000001e, 0xffffffe2, 0x0000001e, 
+	0xffffffe2, 0x0000001e, 0xffffffe2, 0x0000001e, 0xffffffe2, 0x0000001e, 
+	0xffffffe2, 0x0000001e, 0xffffffe2, 0x0000001e, 0xffffffe2, 0x0000001e, 
+	0xffffffe2, 0x0000001e, 0xffffffe2, 0x0000001d, 0xffffffe3, 0x0000001d, 
+	0xffffffe3, 0x0000001d, 0xffffffe3, 0x0000001d, 0xffffffe3, 0x0000001d, 
+	0xffffffe3, 0x0000001d, 0xffffffe3, 0x0000001d, 0xffffffe3, 0x0000001d, 
+	0xffffffe3, 0x0000001d, 0xffffffe3, 0x0000001d, 0xffffffe3, 0x0000001d, 
+	0xffffffe3, 0x0000001d, 0xffffffe3, 0x0000001d, 0xffffffe3, 0x0000001c, 
+	0xffffffe4, 0x0000001c, 0xffffffe4, 0x0000001c, 0xffffffe4, 0x0000001c, 
+	0xffffffe4, 0x0000001c, 0xffffffe4, 0x0000001c, 0xffffffe4, 0x0000001c, 
+	0xffffffe4, 0x0000001c, 0xffffffe4, 0x0000001c, 0xffffffe4, 0x0000001c, 
+	0xffffffe4, 0x0000001c, 0xffffffe4, 0x0000001c, 0xffffffe4, 0x0000001c, 
+	0xffffffe4, 0x0000001b, 0xffffffe5, 0x0000001b, 0xffffffe5, 0x0000001b, 
+	0xffffffe5, 0x0000001b, 0xffffffe5, 0x0000001b, 0xffffffe5, 0x0000001b, 
+	0xffffffe5, 0x0000001b, 0xffffffe5, 0x0000001b, 0xffffffe5, 0x0000001b, 
+	0xffffffe5, 0x0000001b, 0xffffffe5, 0x0000001b, 0xffffffe5, 0x0000001b, 
+	0xffffffe5, 0x0000001b, 0xffffffe5, 0x0000001a, 0xffffffe6, 0x0000001a, 
+	0xffffffe6, 0x0000001a, 0xffffffe6, 0x0000001a, 0xffffffe6, 0x0000001a, 
+	0xffffffe6, 0x0000001a, 0xffffffe6, 0x0000001a, 0xffffffe6, 0x0000001a, 
+	0xffffffe6, 0x0000001a, 0xffffffe6, 0x0000001a, 0xffffffe6, 0x0000001a, 
+	0xffffffe6, 0x0000001a, 0xffffffe6, 0x0000001a, 0xffffffe6, 0x0000001a, 
+	0xffffffe6, 0x00000019, 0xffffffe7, 0x00000019, 0xffffffe7, 0x00000019, 
+	0xffffffe7, 0x00000019, 0xffffffe7, 0x00000019, 0xffffffe7, 0x00000019, 
+	0xffffffe7, 0x00000019, 0xffffffe7, 0x00000019, 0xffffffe7, 0x00000019, 
+	0xffffffe7, 0x00000019, 0xffffffe7, 0x00000019, 0xffffffe7, 0x00000019, 
+	0xffffffe7, 0x00000019, 0xffffffe7, 0x00000019, 0xffffffe7, 0x00000019, 
+	0xffffffe7, 0x00000018, 0xffffffe8, 0x00000018, 0xffffffe8, 0x00000018, 
+	0xffffffe8, 0x00000018, 0xffffffe8, 0x00000018, 0xffffffe8, 0x00000018, 
+	0xffffffe8, 0x00000018, 0xffffffe8, 0x00000018, 0xffffffe8, 0x00000018, 
+	0xffffffe8, 0x00000018, 0xffffffe8, 0x00000018, 0xffffffe8, 0x00000018, 
+	0xffffffe8, 0x00000018, 0xffffffe8, 0x00000018, 0xffffffe8, 0x00000018, 
+	0xffffffe8, 0x00000017, 0xffffffe9, 0x00000017, 0xffffffe9, 0x00000017, 
+	0xffffffe9, 0x00000017, 0xffffffe9, 0x00000017, 0xffffffe9, 0x00000017, 
+	0xffffffe9, 0x00000017, 0xffffffe9, 0x00000017, 0xffffffe9, 0x00000017, 
+	0xffffffe9, 0x00000017, 0xffffffe9, 0x00000017, 0xffffffe9, 0x00000017, 
+	0xffffffe9, 0x00000017, 0xffffffe9, 0x00000017, 0xffffffe9, 0x00000017, 
+	0xffffffe9, 0x00000017, 0xffffffe9, 0x00000016, 0xffffffea, 0x00000016, 
+	0xffffffea, 0x00000016, 0xffffffea, 0x00000016, 0xffffffea, 0x00000016, 
+	0xffffffea, 0x00000016, 0xffffffea, 0x00000016, 0xffffffea, 0x00000016, 
+	0xffffffea, 0x00000016, 0xffffffea, 0x00000016, 0xffffffea, 0x00000016, 
+	0xffffffea, 0x00000016, 0xffffffea, 0x00000016, 0xffffffea, 0x00000016, 
+	0xffffffea, 0x00000016, 0xffffffea, 0x00000016, 0xffffffea, 0x00000015, 
+	0xffffffeb, 0x00000015, 0xffffffeb, 0x00000015, 0xffffffeb, 0x00000015, 
+	0xffffffeb, 0x00000015, 0xffffffeb, 0x00000015, 0xffffffeb, 0x00000015, 
+	0xffffffeb, 0x00000015, 0xffffffeb, 0x00000015, 0xffffffeb, 0x00000015, 
+	0xffffffeb, 0x00000015, 0xffffffeb, 0x00000015, 0xffffffeb, 0x00000015, 
+	0xffffffeb, 0x00000015, 0xffffffeb, 0x00000015, 0xffffffeb, 0x00000015, 
+	0xffffffeb, 0x00000015, 0xffffffeb, 0x00000014, 0xffffffec, 0x00000014, 
+	0xffffffec, 0x00000014, 0xffffffec, 0x00000014, 0xffffffec, 0x00000014, 
+	0xffffffec, 0x00000014, 0xffffffec, 0x00000014, 0xffffffec, 0x00000014, 
+	0xffffffec, 0x00000014, 0xffffffec, 0x00000014, 0xffffffec, 0x00000014, 
+	0xffffffec, 0x00000014, 0xffffffec, 0x00000014, 0xffffffec, 0x00000014, 
+	0xffffffec, 0x00000014, 0xffffffec, 0x00000014, 0xffffffec, 0x00000014, 
+	0xffffffec, 0x00000014, 0xffffffec, 0x00000013, 0xffffffed, 0x00000013, 
+	0xffffffed, 0x00000013, 0xffffffed, 0x00000013, 0xffffffed, 0x00000013, 
+	0xffffffed, 0x00000013, 0xffffffed, 0x00000013, 0xffffffed, 0x00000013, 
+	0xffffffed, 0x00000013, 0xffffffed, 0x00000013, 0xffffffed, 0x00000013, 
+	0xffffffed, 0x00000013, 0xffffffed, 0x00000013, 0xffffffed, 0x00000013, 
+	0xffffffed, 0x00000013, 0xffffffed, 0x00000013, 0xffffffed, 0x00000013, 
+	0xffffffed, 0x00000013, 0xffffffed, 0x00000013, 0xffffffed, 0x00000012, 
+	0xffffffee, 0x00000012, 0xffffffee, 0x00000012, 0xffffffee, 0x00000012, 
+	0xffffffee, 0x00000012, 0xffffffee, 0x00000012, 0xffffffee, 0x00000012, 
+	0xffffffee, 0x00000012, 0xffffffee, 0x00000012, 0xffffffee, 0x00000012, 
+	0xffffffee, 0x00000012, 0xffffffee, 0x00000012, 0xffffffee, 0x00000012, 
+	0xffffffee, 0x00000012, 0xffffffee, 0x00000012, 0xffffffee, 0x00000012, 
+	0xffffffee, 0x00000012, 0xffffffee, 0x00000012, 0xffffffee, 0x00000012, 
+	0xffffffee, 0x00000012, 0xffffffee, 0x00000011, 0xffffffef, 0x00000011, 
+	0xffffffef, 0x00000011, 0xffffffef, 0x00000011, 0xffffffef, 0x00000011, 
+	0xffffffef, 0x00000011, 0xffffffef, 0x00000011, 0xffffffef, 0x00000011, 
+	0xffffffef, 0x00000011, 0xffffffef, 0x00000011, 0xffffffef, 0x00000011, 
+	0xffffffef, 0x00000011, 0xffffffef, 0x00000011, 0xffffffef, 0x00000011, 
+	0xffffffef, 0x00000011, 0xffffffef, 0x00000011, 0xffffffef, 0x00000011, 
+	0xffffffef, 0x00000011, 0xffffffef, 0x00000011, 0xffffffef, 0x00000011, 
+	0xffffffef, 0x00000011, 0xffffffef, 0x00000010, 0xfffffff0, 0x00000010, 
+	0xfffffff0, 0x00000010, 0xfffffff0, 0x00000010, 0xfffffff0, 0x00000010, 
+	0xfffffff0, 0x00000010, 0xfffffff0, 0x00000010, 0xfffffff0, 0x00000010, 
+	0xfffffff0, 0x00000010, 0xfffffff0, 0x00000010, 0xfffffff0, 0x00000010, 
+	0xfffffff0, 0x00000010, 0xfffffff0, 0x00000010, 0xfffffff0, 0x00000010, 
+	0xfffffff0, 0x00000010, 0xfffffff0, 0x00000010, 0xfffffff0, 0x00000010, 
+	0xfffffff0, 0x00000010, 0xfffffff0, 0x00000010, 0xfffffff0, 0x00000010, 
+	0xfffffff0, 0x00000010, 0xfffffff0, 0x00000010, 0xfffffff0, 0x00000010, 
+	0xfffffff0, 0x0000000f, 0xfffffff1, 0x0000000f, 0xfffffff1, 0x0000000f, 
+	0xfffffff1, 0x0000000f, 0xfffffff1, 0x0000000f, 0xfffffff1, 0x0000000f, 
+	0xfffffff1, 0x0000000f, 0xfffffff1, 0x0000000f, 0xfffffff1, 0x0000000f, 
+	0xfffffff1, 0x0000000f, 0xfffffff1, 0x0000000f, 0xfffffff1, 0x0000000f, 
+	0xfffffff1, 0x0000000f, 0xfffffff1, 0x0000000f, 0xfffffff1, 0x0000000f, 
+	0xfffffff1, 0x0000000f, 0xfffffff1, 0x0000000f, 0xfffffff1, 0x0000000f, 
+	0xfffffff1, 0x0000000f, 0xfffffff1, 0x0000000f, 0xfffffff1, 0x0000000f, 
+	0xfffffff1, 0x0000000f, 0xfffffff1, 0x0000000f, 0xfffffff1, 0x0000000e, 
+	0xfffffff2, 0x0000000e, 0xfffffff2, 0x0000000e, 0xfffffff2, 0x0000000e, 
+	0xfffffff2, 0x0000000e, 0xfffffff2, 0x0000000e, 0xfffffff2, 0x0000000e, 
+	0xfffffff2, 0x0000000e, 0xfffffff2, 0x0000000e, 0xfffffff2, 0x0000000e, 
+	0xfffffff2, 0x0000000e, 0xfffffff2, 0x0000000e, 0xfffffff2, 0x0000000e, 
+	0xfffffff2, 0x0000000e, 0xfffffff2, 0x0000000e, 0xfffffff2, 0x0000000e, 
+	0xfffffff2, 0x0000000e, 0xfffffff2, 0x0000000e, 0xfffffff2, 0x0000000e, 
+	0xfffffff2, 0x0000000e, 0xfffffff2, 0x0000000e, 0xfffffff2, 0x0000000e, 
+	0xfffffff2, 0x0000000e, 0xfffffff2, 0x0000000e, 0xfffffff2, 0x0000000e, 
+	0xfffffff2, 0x0000000e, 0xfffffff2, 0x0000000d, 0xfffffff3, 0x0000000d, 
+	0xfffffff3, 0x0000000d, 0xfffffff3, 0x0000000d, 0xfffffff3, 0x0000000d, 
+	0xfffffff3, 0x0000000d, 0xfffffff3, 0x0000000d, 0xfffffff3, 0x0000000d, 
+	0xfffffff3, 0x0000000d, 0xfffffff3, 0x0000000d, 0xfffffff3, 0x0000000d, 
+	0xfffffff3, 0x0000000d, 0xfffffff3, 0x0000000d, 0xfffffff3, 0x0000000d, 
+	0xfffffff3, 0x0000000d, 0xfffffff3, 0x0000000d, 0xfffffff3, 0x0000000d, 
+	0xfffffff3, 0x0000000d, 0xfffffff3, 0x0000000d, 0xfffffff3, 0x0000000d, 
+	0xfffffff3, 0x0000000d, 0xfffffff3, 0x0000000d, 0xfffffff3, 0x0000000d, 
+	0xfffffff3, 0x0000000d, 0xfffffff3, 0x0000000d, 0xfffffff3, 0x0000000d, 
+	0xfffffff3, 0x0000000d, 0xfffffff3, 0x0000000c, 0xfffffff4, 0x0000000c, 
+	0xfffffff4, 0x0000000c, 0xfffffff4, 0x0000000c, 0xfffffff4, 0x0000000c, 
+	0xfffffff4, 0x0000000c, 0xfffffff4, 0x0000000c, 0xfffffff4, 0x0000000c, 
+	0xfffffff4, 0x0000000c, 0xfffffff4, 0x0000000c, 0xfffffff4, 0x0000000c, 
+	0xfffffff4, 0x0000000c, 0xfffffff4, 0x0000000c, 0xfffffff4, 0x0000000c, 
+	0xfffffff4, 0x0000000c, 0xfffffff4, 0x0000000c, 0xfffffff4, 0x0000000c, 
+	0xfffffff4, 0x0000000c, 0xfffffff4, 0x0000000c, 0xfffffff4, 0x0000000c, 
+	0xfffffff4, 0x0000000c, 0xfffffff4, 0x0000000c, 0xfffffff4, 0x0000000c, 
+	0xfffffff4, 0x0000000c, 0xfffffff4, 0x0000000c, 0xfffffff4, 0x0000000c, 
+	0xfffffff4, 0x0000000c, 0xfffffff4, 0x0000000c, 0xfffffff4, 0x0000000c, 
+	0xfffffff4, 0x0000000c, 0xfffffff4, 0x0000000b, 0xfffffff5, 0x0000000b, 
+	0xfffffff5, 0x0000000b, 0xfffffff5, 0x0000000b, 0xfffffff5, 0x0000000b, 
+	0xfffffff5, 0x0000000b, 0xfffffff5, 0x0000000b, 0xfffffff5, 0x0000000b, 
+	0xfffffff5, 0x0000000b, 0xfffffff5, 0x0000000b, 0xfffffff5, 0x0000000b, 
+	0xfffffff5, 0x0000000b, 0xfffffff5, 0x0000000b, 0xfffffff5, 0x0000000b, 
+	0xfffffff5, 0x0000000b, 0xfffffff5, 0x0000000b, 0xfffffff5, 0x0000000b, 
+	0xfffffff5, 0x0000000b, 0xfffffff5, 0x0000000b, 0xfffffff5, 0x0000000b, 
+	0xfffffff5, 0x0000000b, 0xfffffff5, 0x0000000b, 0xfffffff5, 0x0000000b, 
+	0xfffffff5, 0x0000000b, 0xfffffff5, 0x0000000b, 0xfffffff5, 0x0000000b, 
+	0xfffffff5, 0x0000000b, 0xfffffff5, 0x0000000b, 0xfffffff5, 0x0000000b, 
+	0xfffffff5, 0x0000000b, 0xfffffff5, 0x0000000b, 0xfffffff5, 0x0000000b, 
+	0xfffffff5, 0x0000000a, 0xfffffff6, 0x0000000a, 0xfffffff6, 0x0000000a, 
+	0xfffffff6, 0x0000000a, 0xfffffff6, 0x0000000a, 0xfffffff6, 0x0000000a, 
+	0xfffffff6, 0x0000000a, 0xfffffff6, 0x0000000a, 0xfffffff6, 0x0000000a, 
+	0xfffffff6, 0x0000000a, 0xfffffff6, 0x0000000a, 0xfffffff6, 0x0000000a, 
+	0xfffffff6, 0x0000000a, 0xfffffff6, 0x0000000a, 0xfffffff6, 0x0000000a, 
+	0xfffffff6, 0x0000000a, 0xfffffff6, 0x0000000a, 0xfffffff6, 0x0000000a, 
+	0xfffffff6, 0x0000000a, 0xfffffff6, 0x0000000a, 0xfffffff6, 0x0000000a, 
+	0xfffffff6, 0x0000000a, 0xfffffff6, 0x0000000a, 0xfffffff6, 0x0000000a, 
+	0xfffffff6, 0x0000000a, 0xfffffff6, 0x0000000a, 0xfffffff6, 0x0000000a, 
+	0xfffffff6, 0x0000000a, 0xfffffff6, 0x0000000a, 0xfffffff6, 0x0000000a, 
+	0xfffffff6, 0x0000000a, 0xfffffff6, 0x0000000a, 0xfffffff6, 0x0000000a, 
+	0xfffffff6, 0x0000000a, 0xfffffff6, 0x0000000a, 0xfffffff6, 0x00000009, 
+	0xfffffff7, 0x00000009, 0xfffffff7, 0x00000009, 0xfffffff7, 0x00000009, 
+	0xfffffff7, 0x00000009, 0xfffffff7, 0x00000009, 0xfffffff7, 0x00000009, 
+	0xfffffff7, 0x00000009, 0xfffffff7, 0x00000009, 0xfffffff7, 0x00000009, 
+	0xfffffff7, 0x00000009, 0xfffffff7, 0x00000009, 0xfffffff7, 0x00000009, 
+	0xfffffff7, 0x00000009, 0xfffffff7, 0x00000009, 0xfffffff7, 0x00000009, 
+	0xfffffff7, 0x00000009, 0xfffffff7, 0x00000009, 0xfffffff7, 0x00000009, 
+	0xfffffff7, 0x00000009, 0xfffffff7, 0x00000009, 0xfffffff7, 0x00000009, 
+	0xfffffff7, 0x00000009, 0xfffffff7, 0x00000009, 0xfffffff7, 0x00000009, 
+	0xfffffff7, 0x00000009, 0xfffffff7, 0x00000009, 0xfffffff7, 0x00000009, 
+	0xfffffff7, 0x00000009, 0xfffffff7, 0x00000009, 0xfffffff7, 0x00000009, 
+	0xfffffff7, 0x00000009, 0xfffffff7, 0x00000009, 0xfffffff7, 0x00000009, 
+	0xfffffff7, 0x00000009, 0xfffffff7, 0x00000009, 0xfffffff7, 0x00000009, 
+	0xfffffff7, 0x00000009, 0xfffffff7, 0x00000009, 0xfffffff7, 0x00000008, 
+	0xfffffff8, 0x00000008, 0xfffffff8, 0x00000008, 0xfffffff8, 0x00000008, 
+	0xfffffff8, 0x00000008, 0xfffffff8, 0x00000008, 0xfffffff8, 0x00000008, 
+	0xfffffff8, 0x00000008, 0xfffffff8, 0x00000008, 0xfffffff8, 0x00000008, 
+	0xfffffff8, 0x00000008, 0xfffffff8, 0x00000008, 0xfffffff8, 0x00000008, 
+	0xfffffff8, 0x00000008, 0xfffffff8, 0x00000008, 0xfffffff8, 0x00000008, 
+	0xfffffff8, 0x00000008, 0xfffffff8, 0x00000008, 0xfffffff8, 0x00000008, 
+	0xfffffff8, 0x00000008, 0xfffffff8, 0x00000008, 0xfffffff8, 0x00000008, 
+	0xfffffff8, 0x00000008, 0xfffffff8, 0x00000008, 0xfffffff8, 0x00000008, 
+	0xfffffff8, 0x00000008, 0xfffffff8, 0x00000008, 0xfffffff8, 0x00000008, 
+	0xfffffff8, 0x00000008, 0xfffffff8, 0x00000008, 0xfffffff8, 0x00000008, 
+	0xfffffff8, 0x00000008, 0xfffffff8, 0x00000008, 0xfffffff8, 0x00000008, 
+	0xfffffff8, 0x00000008, 0xfffffff8, 0x00000008, 0xfffffff8, 0x00000008, 
+	0xfffffff8, 0x00000008, 0xfffffff8, 0x00000008, 0xfffffff8, 0x00000008, 
+	0xfffffff8, 0x00000008, 0xfffffff8, 0x00000008, 0xfffffff8, 0x00000008, 
+	0xfffffff8, 0x00000008, 0xfffffff8, 0x00000007, 0xfffffff9, 0x00000007, 
+	0xfffffff9, 0x00000007, 0xfffffff9, 0x00000007, 0xfffffff9, 0x00000007, 
+	0xfffffff9, 0x00000007, 0xfffffff9, 0x00000007, 0xfffffff9, 0x00000007, 
+	0xfffffff9, 0x00000007, 0xfffffff9, 0x00000007, 0xfffffff9, 0x00000007, 
+	0xfffffff9, 0x00000007, 0xfffffff9, 0x00000007, 0xfffffff9, 0x00000007, 
+	0xfffffff9, 0x00000007, 0xfffffff9, 0x00000007, 0xfffffff9, 0x00000007, 
+	0xfffffff9, 0x00000007, 0xfffffff9, 0x00000007, 0xfffffff9, 0x00000007, 
+	0xfffffff9, 0x00000007, 0xfffffff9, 0x00000007, 0xfffffff9, 0x00000007, 
+	0xfffffff9, 0x00000007, 0xfffffff9, 0x00000007, 0xfffffff9, 0x00000007, 
+	0xfffffff9, 0x00000007, 0xfffffff9, 0x00000007, 0xfffffff9, 0x00000007, 
+	0xfffffff9, 0x00000007, 0xfffffff9, 0x00000007, 0xfffffff9, 0x00000007, 
+	0xfffffff9, 0x00000007, 0xfffffff9, 0x00000007, 0xfffffff9, 0x00000007, 
+	0xfffffff9, 0x00000007, 0xfffffff9, 0x00000007, 0xfffffff9, 0x00000007, 
+	0xfffffff9, 0x00000007, 0xfffffff9, 0x00000007, 0xfffffff9, 0x00000007, 
+	0xfffffff9, 0x00000007, 0xfffffff9, 0x00000007, 0xfffffff9, 0x00000007, 
+	0xfffffff9, 0x00000007, 0xfffffff9, 0x00000007, 0xfffffff9, 0x00000007, 
+	0xfffffff9, 0x00000007, 0xfffffff9, 0x00000007, 0xfffffff9, 0x00000006, 
+	0xfffffffa, 0x00000006, 0xfffffffa, 0x00000006, 0xfffffffa, 0x00000006, 
+	0xfffffffa, 0x00000006, 0xfffffffa, 0x00000006, 0xfffffffa, 0x00000006, 
+	0xfffffffa, 0x00000006, 0xfffffffa, 0x00000006, 0xfffffffa, 0x00000006, 
+	0xfffffffa, 0x00000006, 0xfffffffa, 0x00000006, 0xfffffffa, 0x00000006, 
+	0xfffffffa, 0x00000006, 0xfffffffa, 0x00000006, 0xfffffffa, 0x00000006, 
+	0xfffffffa, 0x00000006, 0xfffffffa, 0x00000006, 0xfffffffa, 0x00000006, 
+	0xfffffffa, 0x00000006, 0xfffffffa, 0x00000006, 0xfffffffa, 0x00000006, 
+	0xfffffffa, 0x00000006, 0xfffffffa, 0x00000006, 0xfffffffa, 0x00000006, 
+	0xfffffffa, 0x00000006, 0xfffffffa, 0x00000006, 0xfffffffa, 0x00000006, 
+	0xfffffffa, 0x00000006, 0xfffffffa, 0x00000006, 0xfffffffa, 0x00000006, 
+	0xfffffffa, 0x00000006, 0xfffffffa, 0x00000006, 0xfffffffa, 0x00000006, 
+	0xfffffffa, 0x00000006, 0xfffffffa, 0x00000006, 0xfffffffa, 0x00000006, 
+	0xfffffffa, 0x00000006, 0xfffffffa, 0x00000006, 0xfffffffa, 0x00000006, 
+	0xfffffffa, 0x00000006, 0xfffffffa, 0x00000006, 0xfffffffa, 0x00000006, 
+	0xfffffffa, 0x00000006, 0xfffffffa, 0x00000006, 0xfffffffa, 0x00000006, 
+	0xfffffffa, 0x00000006, 0xfffffffa, 0x00000006, 0xfffffffa, 0x00000006, 
+	0xfffffffa, 0x00000006, 0xfffffffa, 0x00000006, 0xfffffffa, 0x00000006, 
+	0xfffffffa, 0x00000006, 0xfffffffa, 0x00000006, 0xfffffffa, 0x00000006, 
+	0xfffffffa, 0x00000006, 0xfffffffa, 0x00000006, 0xfffffffa, 0x00000005, 
+	0xfffffffb, 0x00000005, 0xfffffffb, 0x00000005, 0xfffffffb, 0x00000005, 
+	0xfffffffb, 0x00000005, 0xfffffffb, 0x00000005, 0xfffffffb, 0x00000005, 
+	0xfffffffb, 0x00000005, 0xfffffffb, 0x00000005, 0xfffffffb, 0x00000005, 
+	0xfffffffb, 0x00000005, 0xfffffffb, 0x00000005, 0xfffffffb, 0x00000005, 
+	0xfffffffb, 0x00000005, 0xfffffffb, 0x00000005, 0xfffffffb, 0x00000005, 
+	0xfffffffb, 0x00000005, 0xfffffffb, 0x00000005, 0xfffffffb, 0x00000005, 
+	0xfffffffb, 0x00000005, 0xfffffffb, 0x00000005, 0xfffffffb, 0x00000005, 
+	0xfffffffb, 0x00000005, 0xfffffffb, 0x00000005, 0xfffffffb, 0x00000005, 
+	0xfffffffb, 0x00000005, 0xfffffffb, 0x00000005, 0xfffffffb, 0x00000005, 
+	0xfffffffb, 0x00000005, 0xfffffffb, 0x00000005, 0xfffffffb, 0x00000005, 
+	0xfffffffb, 0x00000005, 0xfffffffb, 0x00000005, 0xfffffffb, 0x00000005, 
+	0xfffffffb, 0x00000005, 0xfffffffb, 0x00000005, 0xfffffffb, 0x00000005, 
+	0xfffffffb, 0x00000005, 0xfffffffb, 0x00000005, 0xfffffffb, 0x00000005, 
+	0xfffffffb, 0x00000005, 0xfffffffb, 0x00000005, 0xfffffffb, 0x00000005, 
+	0xfffffffb, 0x00000005, 0xfffffffb, 0x00000005, 0xfffffffb, 0x00000005, 
+	0xfffffffb, 0x00000005, 0xfffffffb, 0x00000005, 0xfffffffb, 0x00000005, 
+	0xfffffffb, 0x00000005, 0xfffffffb, 0x00000005, 0xfffffffb, 0x00000005, 
+	0xfffffffb, 0x00000005, 0xfffffffb, 0x00000005, 0xfffffffb, 0x00000005, 
+	0xfffffffb, 0x00000005, 0xfffffffb, 0x00000005, 0xfffffffb, 0x00000005, 
+	0xfffffffb, 0x00000005, 0xfffffffb, 0x00000005, 0xfffffffb, 0x00000005, 
+	0xfffffffb, 0x00000005, 0xfffffffb, 0x00000005, 0xfffffffb, 0x00000005, 
+	0xfffffffb, 0x00000005, 0xfffffffb, 0x00000005, 0xfffffffb, 0x00000005, 
+	0xfffffffb, 0x00000004, 0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 
+	0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 
+	0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 
+	0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 
+	0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 
+	0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 
+	0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 
+	0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 
+	0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 
+	0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 
+	0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 
+	0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 
+	0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 
+	0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 
+	0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 
+	0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 
+	0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 
+	0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 
+	0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 
+	0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 
+	0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 
+	0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 
+	0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 
+	0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 
+	0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 
+	0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 
+	0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 
+	0xfffffffc, 0x00000004, 0xfffffffc, 0x00000004, 0xfffffffc, 0x00000003, 
+	0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 
+	0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 
+	0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 
+	0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 
+	0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 
+	0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 
+	0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 
+	0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 
+	0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 
+	0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 
+	0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 
+	0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 
+	0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 
+	0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 
+	0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 
+	0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 
+	0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 
+	0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 
+	0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 
+	0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 
+	0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 
+	0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 
+	0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 
+	0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 
+	0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 
+	0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 
+	0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 
+	0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 
+	0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 
+	0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 
+	0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 
+	0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 
+	0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 
+	0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 
+	0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 0xfffffffd, 0x00000003, 
+	0xfffffffd, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 0xfffffffe, 0x00000002, 
+	0xfffffffe, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 0xffffffff, 0x00000001, 
+	0xffffffff, 0x00000001, 0xffffffff,
+};
+
+unsigned int sin_table[2054] = {
+	0x10b2, 0x0d86, 0x0c0e, 0x0b16, 0x0a5c, 0x09c8, 0x094c, 
+	0x08e2, 0x0886, 0x0834, 0x07ea, 0x07a6, 0x076a, 
+	0x0730, 0x06fc, 0x06ca, 0x069c, 0x0672, 0x0648, 
+	0x0622, 0x05fe, 0x05da, 0x05b8, 0x059a, 0x057a, 
+	0x055e, 0x0540, 0x0526, 0x050c, 0x04f2, 0x04da, 
+	0x04c2, 0x04ac, 0x0496, 0x0480, 0x046c, 0x0458, 
+	0x0444, 0x0430, 0x041e, 0x040c, 0x03fa, 0x03ea, 
+	0x03d8, 0x03c8, 0x03b8, 0x03a8, 0x039a, 0x038a, 
+	0x037c, 0x036e, 0x0360, 0x0352, 0x0344, 0x0336, 
+	0x032a, 0x031e, 0x0310, 0x0304, 0x02f8, 0x02ee, 
+	0x02e2, 0x02d6, 0x02cc, 0x02c0, 0x02b6, 0x02aa, 
+	0x02a0, 0x0296, 0x028c, 0x0282, 0x0278, 0x026e, 
+	0x0266, 0x025c, 0x0252, 0x024a, 0x0242, 0x0238, 
+	0x0230, 0x0228, 0x021e, 0x0216, 0x020e, 0x0206, 
+	0x01fe, 0x01f6, 0x01f0, 0x01e8, 0x01e0, 0x01d8, 
+	0x01d2, 0x01ca, 0x01c4, 0x01bc, 0x01b6, 0x01ae, 
+	0x01a8, 0x01a2, 0x019a, 0x0194, 0x018e, 0x0188, 
+	0x0182, 0x017c, 0x0176, 0x0170, 0x016a, 0x0164, 
+	0x015e, 0x0158, 0x0152, 0x014e, 0x0148, 0x0142, 
+	0x013e, 0x0138, 0x0132, 0x012e, 0x0128, 0x0124, 
+	0x011e, 0x011a, 0x0114, 0x0110, 0x010c, 0x0106, 
+	0x0102, 0x00fe, 0x00fa, 0x00f4, 0x00f0, 0x00ec, 
+	0x00e8, 0x00e4, 0x00e0, 0x00dc, 0x00d8, 0x00d4, 
+	0x00d0, 0x00cc, 0x00c8, 0x00c4, 0x00c0, 0x00bc, 
+	0x00b8, 0x00b6, 0x00b2, 0x00ae, 0x00aa, 0x00a6, 
+	0x00a4, 0x00a0, 0x009c, 0x009a, 0x0096, 0x0094, 
+	0x0090, 0x008c, 0x008a, 0x0086, 0x0084, 0x0080, 
+	0x007e, 0x007c, 0x0078, 0x0076, 0x0072, 0x0070, 
+	0x006e, 0x006a, 0x0068, 0x0066, 0x0062, 0x0060, 
+	0x005e, 0x005c, 0x005a, 0x0056, 0x0054, 0x0052, 
+	0x0050, 0x004e, 0x004c, 0x004a, 0x0048, 0x0046, 
+	0x0044, 0x0042, 0x0040, 0x003e, 0x003c, 0x003a, 
+	0x0038, 0x0036, 0x0034, 0x0032, 0x0030, 0x002e, 
+	0x002e, 0x002c, 0x002a, 0x0028, 0x0028, 0x0026, 
+	0x0024, 0x0022, 0x0022, 0x0020, 0x001e, 0x001e, 
+	0x001c, 0x001a, 0x001a, 0x0018, 0x0018, 0x0016, 
+	0x0014, 0x0014, 0x0012, 0x0012, 0x0010, 0x0010, 
+	0x000e, 0x000e, 0x000e, 0x000c, 0x000c, 0x000a, 
+	0x000a, 0x000a, 0x0008, 0x0008, 0x0008, 0x0006, 
+	0x0006, 0x0006, 0x0004, 0x0004, 0x0004, 0x0004, 
+	0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 
+	0x0002, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0002, 
+	0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 
+	0x0004, 0x0004, 0x0004, 0x0004, 0x0006, 0x0006, 
+	0x0006, 0x0008, 0x0008, 0x0008, 0x000a, 0x000a, 
+	0x000a, 0x000c, 0x000c, 0x000e, 0x000e, 0x000e, 
+	0x0010, 0x0010, 0x0012, 0x0012, 0x0014, 0x0014, 
+	0x0016, 0x0018, 0x0018, 0x001a, 0x001a, 0x001c, 
+	0x001e, 0x001e, 0x0020, 0x0022, 0x0022, 0x0024, 
+	0x0026, 0x0028, 0x0028, 0x002a, 0x002c, 0x002e, 
+	0x002e, 0x0030, 0x0032, 0x0034, 0x0036, 0x0038, 
+	0x003a, 0x003c, 0x003e, 0x0040, 0x0042, 0x0044, 
+	0x0046, 0x0048, 0x004a, 0x004c, 0x004e, 0x0050, 
+	0x0052, 0x0054, 0x0056, 0x005a, 0x005c, 0x005e, 
+	0x0060, 0x0062, 0x0066, 0x0068, 0x006a, 0x006e, 
+	0x0070, 0x0072, 0x0076, 0x0078, 0x007c, 0x007e, 
+	0x0080, 0x0084, 0x0086, 0x008a, 0x008c, 0x0090, 
+	0x0094, 0x0096, 0x009a, 0x009c, 0x00a0, 0x00a4, 
+	0x00a6, 0x00aa, 0x00ae, 0x00b2, 0x00b6, 0x00b8, 
+	0x00bc, 0x00c0, 0x00c4, 0x00c8, 0x00cc, 0x00d0, 
+	0x00d4, 0x00d8, 0x00dc, 0x00e0, 0x00e4, 0x00e8, 
+	0x00ec, 0x00f0, 0x00f4, 0x00fa, 0x00fe, 0x0102, 
+	0x0106, 0x010c, 0x0110, 0x0114, 0x011a, 0x011e, 
+	0x0124, 0x0128, 0x012e, 0x0132, 0x0138, 0x013e, 
+	0x0142, 0x0148, 0x014e, 0x0152, 0x0158, 0x015e, 
+	0x0164, 0x016a, 0x0170, 0x0176, 0x017c, 0x0182, 
+	0x0188, 0x018e, 0x0194, 0x019a, 0x01a2, 0x01a8, 
+	0x01ae, 0x01b6, 0x01bc, 0x01c4, 0x01ca, 0x01d2, 
+	0x01d8, 0x01e0, 0x01e8, 0x01f0, 0x01f6, 0x01fe, 
+	0x0206, 0x020e, 0x0216, 0x021e, 0x0228, 0x0230, 
+	0x0238, 0x0242, 0x024a, 0x0252, 0x025c, 0x0266, 
+	0x026e, 0x0278, 0x0282, 0x028c, 0x0296, 0x02a0, 
+	0x02aa, 0x02b6, 0x02c0, 0x02cc, 0x02d6, 0x02e2, 
+	0x02ee, 0x02f8, 0x0304, 0x0310, 0x031e, 0x032a, 
+	0x0336, 0x0344, 0x0352, 0x0360, 0x036e, 0x037c, 
+	0x038a, 0x039a, 0x03a8, 0x03b8, 0x03c8, 0x03d8, 
+	0x03ea, 0x03fa, 0x040c, 0x041e, 0x0430, 0x0444, 
+	0x0458, 0x046c, 0x0480, 0x0496, 0x04ac, 0x04c2, 
+	0x04da, 0x04f2, 0x050c, 0x0526, 0x0540, 0x055e, 
+	0x057a, 0x059a, 0x05b8, 0x05da, 0x05fe, 0x0622, 
+	0x0648, 0x0672, 0x069c, 0x06ca, 0x06fc, 0x0730, 
+	0x076a, 0x07a6, 0x07ea, 0x0834, 0x0886, 0x08e2, 
+	0x094c, 0x09c8, 0x0a5c, 0x0b16, 0x0c0e, 0x0d86, 
+	0x10b2, 0x10b3, 0x0d87, 0x0c0f, 0x0b17, 0x0a5d, 
+	0x09c9, 0x094d, 0x08e3, 0x0887, 0x0835, 0x07eb, 
+	0x07a7, 0x076b, 0x0731, 0x06fd, 0x06cb, 0x069d, 
+	0x0673, 0x0649, 0x0623, 0x05ff, 0x05db, 0x05b9, 
+	0x059b, 0x057b, 0x055f, 0x0541, 0x0527, 0x050d, 
+	0x04f3, 0x04db, 0x04c3, 0x04ad, 0x0497, 0x0481, 
+	0x046d, 0x0459, 0x0445, 0x0431, 0x041f, 0x040d, 
+	0x03fb, 0x03eb, 0x03d9, 0x03c9, 0x03b9, 0x03a9, 
+	0x039b, 0x038b, 0x037d, 0x036f, 0x0361, 0x0353, 
+	0x0345, 0x0337, 0x032b, 0x031f, 0x0311, 0x0305, 
+	0x02f9, 0x02ef, 0x02e3, 0x02d7, 0x02cd, 0x02c1, 
+	0x02b7, 0x02ab, 0x02a1, 0x0297, 0x028d, 0x0283, 
+	0x0279, 0x026f, 0x0267, 0x025d, 0x0253, 0x024b, 
+	0x0243, 0x0239, 0x0231, 0x0229, 0x021f, 0x0217, 
+	0x020f, 0x0207, 0x01ff, 0x01f7, 0x01f1, 0x01e9, 
+	0x01e1, 0x01d9, 0x01d3, 0x01cb, 0x01c5, 0x01bd, 
+	0x01b7, 0x01af, 0x01a9, 0x01a3, 0x019b, 0x0195, 
+	0x018f, 0x0189, 0x0183, 0x017d, 0x0177, 0x0171, 
+	0x016b, 0x0165, 0x015f, 0x0159, 0x0153, 0x014f, 
+	0x0149, 0x0143, 0x013f, 0x0139, 0x0133, 0x012f, 
+	0x0129, 0x0125, 0x011f, 0x011b, 0x0115, 0x0111, 
+	0x010d, 0x0107, 0x0103, 0x00ff, 0x00fb, 0x00f5, 
+	0x00f1, 0x00ed, 0x00e9, 0x00e5, 0x00e1, 0x00dd, 
+	0x00d9, 0x00d5, 0x00d1, 0x00cd, 0x00c9, 0x00c5, 
+	0x00c1, 0x00bd, 0x00b9, 0x00b7, 0x00b3, 0x00af, 
+	0x00ab, 0x00a7, 0x00a5, 0x00a1, 0x009d, 0x009b, 
+	0x0097, 0x0095, 0x0091, 0x008d, 0x008b, 0x0087, 
+	0x0085, 0x0081, 0x007f, 0x007d, 0x0079, 0x0077, 
+	0x0073, 0x0071, 0x006f, 0x006b, 0x0069, 0x0067, 
+	0x0063, 0x0061, 0x005f, 0x005d, 0x005b, 0x0057, 
+	0x0055, 0x0053, 0x0051, 0x004f, 0x004d, 0x004b, 
+	0x0049, 0x0047, 0x0045, 0x0043, 0x0041, 0x003f, 
+	0x003d, 0x003b, 0x0039, 0x0037, 0x0035, 0x0033, 
+	0x0031, 0x002f, 0x002f, 0x002d, 0x002b, 0x0029, 
+	0x0029, 0x0027, 0x0025, 0x0023, 0x0023, 0x0021, 
+	0x001f, 0x001f, 0x001d, 0x001b, 0x001b, 0x0019, 
+	0x0019, 0x0017, 0x0015, 0x0015, 0x0013, 0x0013, 
+	0x0011, 0x0011, 0x000f, 0x000f, 0x000f, 0x000d, 
+	0x000d, 0x000b, 0x000b, 0x000b, 0x0009, 0x0009, 
+	0x0009, 0x0007, 0x0007, 0x0007, 0x0005, 0x0005, 
+	0x0005, 0x0005, 0x0003, 0x0003, 0x0003, 0x0003, 
+	0x0003, 0x0003, 0x0003, 0x0001, 0x0001, 0x0001, 
+	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 
+	0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 
+	0x0001, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 
+	0x0003, 0x0003, 0x0005, 0x0005, 0x0005, 0x0005, 
+	0x0007, 0x0007, 0x0007, 0x0009, 0x0009, 0x0009, 
+	0x000b, 0x000b, 0x000b, 0x000d, 0x000d, 0x000f, 
+	0x000f, 0x000f, 0x0011, 0x0011, 0x0013, 0x0013, 
+	0x0015, 0x0015, 0x0017, 0x0019, 0x0019, 0x001b, 
+	0x001b, 0x001d, 0x001f, 0x001f, 0x0021, 0x0023, 
+	0x0023, 0x0025, 0x0027, 0x0029, 0x0029, 0x002b, 
+	0x002d, 0x002f, 0x002f, 0x0031, 0x0033, 0x0035, 
+	0x0037, 0x0039, 0x003b, 0x003d, 0x003f, 0x0041, 
+	0x0043, 0x0045, 0x0047, 0x0049, 0x004b, 0x004d, 
+	0x004f, 0x0051, 0x0053, 0x0055, 0x0057, 0x005b, 
+	0x005d, 0x005f, 0x0061, 0x0063, 0x0067, 0x0069, 
+	0x006b, 0x006f, 0x0071, 0x0073, 0x0077, 0x0079, 
+	0x007d, 0x007f, 0x0081, 0x0085, 0x0087, 0x008b, 
+	0x008d, 0x0091, 0x0095, 0x0097, 0x009b, 0x009d, 
+	0x00a1, 0x00a5, 0x00a7, 0x00ab, 0x00af, 0x00b3, 
+	0x00b7, 0x00b9, 0x00bd, 0x00c1, 0x00c5, 0x00c9, 
+	0x00cd, 0x00d1, 0x00d5, 0x00d9, 0x00dd, 0x00e1, 
+	0x00e5, 0x00e9, 0x00ed, 0x00f1, 0x00f5, 0x00fb, 
+	0x00ff, 0x0103, 0x0107, 0x010d, 0x0111, 0x0115, 
+	0x011b, 0x011f, 0x0125, 0x0129, 0x012f, 0x0133, 
+	0x0139, 0x013f, 0x0143, 0x0149, 0x014f, 0x0153, 
+	0x0159, 0x015f, 0x0165, 0x016b, 0x0171, 0x0177, 
+	0x017d, 0x0183, 0x0189, 0x018f, 0x0195, 0x019b, 
+	0x01a3, 0x01a9, 0x01af, 0x01b7, 0x01bd, 0x01c5, 
+	0x01cb, 0x01d3, 0x01d9, 0x01e1, 0x01e9, 0x01f1, 
+	0x01f7, 0x01ff, 0x0207, 0x020f, 0x0217, 0x021f, 
+	0x0229, 0x0231, 0x0239, 0x0243, 0x024b, 0x0253, 
+	0x025d, 0x0267, 0x026f, 0x0279, 0x0283, 0x028d, 
+	0x0297, 0x02a1, 0x02ab, 0x02b7, 0x02c1, 0x02cd, 
+	0x02d7, 0x02e3, 0x02ef, 0x02f9, 0x0305, 0x0311, 
+	0x031f, 0x032b, 0x0337, 0x0345, 0x0353, 0x0361, 
+	0x036f, 0x037d, 0x038b, 0x039b, 0x03a9, 0x03b9, 
+	0x03c9, 0x03d9, 0x03eb, 0x03fb, 0x040d, 0x041f, 
+	0x0431, 0x0445, 0x0459, 0x046d, 0x0481, 0x0497, 
+	0x04ad, 0x04c3, 0x04db, 0x04f3, 0x050d, 0x0527, 
+	0x0541, 0x055f, 0x057b, 0x059b, 0x05b9, 0x05db, 
+	0x05ff, 0x0623, 0x0649, 0x0673, 0x069d, 0x06cb, 
+	0x06fd, 0x0731, 0x076b, 0x07a7, 0x07eb, 0x0835, 
+	0x0887, 0x08e3, 0x094d, 0x09c9, 0x0a5d, 0x0b17, 
+	0x0c0f, 0x0d87, 0x10b3, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+	0x0000,
+};
+
+#endif
Index: apps/codecs/libnsf/nsf_emu.c
===================================================================
--- apps/codecs/libnsf/nsf_emu.c	(revision 0)
+++ apps/codecs/libnsf/nsf_emu.c	(revision 0)
@@ -0,0 +1,1125 @@
+// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
+
+#include "nsf_emu.h"
+#include "multi_buffer.h"
+
+#include "blargg_endian.h"
+
+/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
+can redistribute it and/or modify it under the terms of the GNU Lesser
+General Public License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version. This
+module is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+details. You should have received a copy of the GNU Lesser General Public
+License along with this module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+const char gme_wrong_file_type [] ICONST_ATTR = "Wrong file type for this emulator";
+long const clock_divisor = 12;
+
+int const stereo = 2; // number of channels for stereo
+int const silence_max = 6; // seconds
+int const silence_threshold = 0x10;
+long const fade_block_size = 512;
+int const fade_shift = 8; // fade ends with gain at 1.0 / (1 << fade_shift)
+
+// number of frames until play interrupts init
+int const initial_play_delay = 7; // KikiKaikai needed this to work
+int const rom_addr  = 0x8000;
+
+void clear_track_vars( struct Nsf_Emu* this )
+{
+	this->current_track    = -1;
+	this->out_time         = 0;
+	this->emu_time         = 0;
+	this->emu_track_ended_ = true;
+	this->track_ended      = true;
+	this->fade_start       = INT_MAX / 2 + 1;
+	this->fade_step        = 1;
+	this->silence_time     = 0;
+	this->silence_count    = 0;
+	this->buf_remain       = 0;
+}
+
+static int pcm_read( void* emu, addr_t addr )
+{
+	return *Cpu_get_code( &((struct Nsf_Emu*) emu)->cpu, addr );
+}
+
+void Nsf_init( struct Nsf_Emu* this )
+{	
+	this->sample_rate = 0;
+	this->mute_mask_   = 0;
+	this->tempo        = 1.0;
+	this->gain         = 1.0;
+	this->is_extended  = 0;
+	
+	// defaults
+	this->max_initial_silence = 2;
+	this->ignore_silence     = false;
+	this->voice_count = 0;
+	
+	// Set sound gain
+	Sound_set_gain( this, 1.4 );
+	
+	// Unload
+	clear_track_vars( this );
+	
+	// Init & clear nsfe info
+	Info_init( &this->info );
+	Info_unload( &this->info ); // TODO: extremely hacky!
+	
+	Cpu_init( &this->cpu );
+	Apu_init( &this->apu );
+	Apu_dmc_reader( &this->apu, pcm_read, this );
+	
+	// Clear m3u playlist
+	M3u_clear( &this->m3u );
+}
+
+// Setup
+
+blargg_err_t init_sound( struct Nsf_Emu* this )
+{
+	/* if ( header_.chip_flags & ~(fds_flag | namco_flag | vrc6_flag | fme7_flag) )
+		warning( "Uses unsupported audio expansion hardware" ); **/
+	
+	this->voice_count = apu_osc_count;
+	
+	double adjusted_gain = 1.0 / 0.75 * this->gain;
+	
+	#ifdef NSF_EMU_APU_ONLY
+	{
+		if ( this->header_.chip_flags )
+			set_warning( "Uses unsupported audio expansion hardware" );
+	}
+	#else
+	{
+		if ( vrc6_enabled( this ) )
+		{
+			Vrc6_init( &this->vrc6 );
+			adjusted_gain *= 0.75;
+			
+			this->voice_count += vrc6_osc_count;
+		}
+			
+		if ( fme7_enabled( this ) )
+		{
+			Fme7_init( &this->fme7 );
+			adjusted_gain *= 0.75;
+			
+			this->voice_count += fme7_osc_count;
+		}
+		
+		if ( mmc5_enabled( this ) )
+		{
+			Mmc5_init( &this->mmc5 );
+			adjusted_gain *= 0.75;
+			
+			this->voice_count += mmc5_osc_count;
+		}
+		
+		if ( fds_enabled( this ) )
+		{
+			Fds_init( &this->fds );
+			adjusted_gain *= 0.75;
+			
+			this->voice_count += fds_osc_count ;
+		}
+		
+		if ( namco_enabled( this ) )
+		{
+			Namco_init( &this->namco );
+			adjusted_gain *= 0.75;
+			
+			this->voice_count += namco_osc_count;
+		}
+		
+		if ( vrc7_enabled( this ) )
+		{
+			#ifndef NSF_EMU_NO_VRC7
+				Vrc7_init( &this->vrc7 );
+			#endif
+
+			adjusted_gain *= 0.75;
+			
+			this->voice_count += vrc7_osc_count;
+		}
+		
+		if ( vrc7_enabled( this )  ) Vrc7_volume( &this->vrc7, adjusted_gain );
+		if ( namco_enabled( this ) ) Namco_volume( &this->namco, adjusted_gain );
+		if ( vrc6_enabled( this )  ) Vrc6_volume( &this->vrc6, adjusted_gain );
+		if ( fme7_enabled( this )  ) Fme7_volume( &this->fme7, adjusted_gain );
+		if ( mmc5_enabled( this )  ) Apu_volume( &this->mmc5.apu, adjusted_gain );
+		if ( fds_enabled( this )   ) Fds_volume( &this->fds, adjusted_gain );
+	}
+	#endif
+	
+	if ( adjusted_gain > this->gain )
+		adjusted_gain = this->gain;
+	
+	Apu_volume( &this->apu, adjusted_gain );
+	
+	return 0;
+}
+
+// Header stuff
+bool valid_tag( struct header_t* this )
+{
+	return 0 == memcmp( this->tag, "NESM\x1A", 5 );
+}
+
+// True if file supports only PAL speed
+static bool pal_only( struct header_t* this )
+{
+	return (this->speed_flags & 3) == 1;
+}
+	
+static double clock_rate( struct header_t* this )
+{
+	return pal_only( this ) ? 1662607.125 : 1789772.727272727;
+}
+
+int play_period( struct header_t* this )
+{
+	// NTSC
+	int         clocks   = 29780;
+	int         value    = 0x411A;
+	byte const* rate_ptr = this->ntsc_speed;
+	
+	// PAL
+	if ( pal_only( this ) )
+	{
+		clocks   = 33247;
+		value    = 0x4E20;
+		rate_ptr = this->pal_speed;
+	}
+	
+	// Default rate
+	int rate = get_le16( rate_ptr );
+	if ( rate == 0 )
+		rate = value;
+	
+	// Custom rate
+	if ( rate != value )
+		clocks = (int) (rate * clock_rate( this ) * (1.0/1000000.0));
+	
+	return clocks;
+}
+
+// Gets address, given pointer to it in file header. If zero, returns rom_addr.
+addr_t get_addr( byte const in [] )
+{
+	addr_t addr = get_le16( in );
+	if ( addr == 0 )
+		addr = rom_addr;
+	return addr;
+}
+
+static blargg_err_t check_nsf_header( struct header_t* h )
+{
+	if ( !valid_tag( h ) )
+		return gme_wrong_file_type;
+	return 0;
+}
+
+blargg_err_t Nsf_load( struct Nsf_Emu* this, void* data, long size )
+{
+	// Unload
+	Info_unload( &this->info ); // TODO: extremely hacky!
+		
+	this->voice_count = 0;
+	clear_track_vars( this );
+	
+	assert( offsetof (struct header_t,unused [4]) == header_size );
+	
+	if ( !memcmp( data, "NESM\x1A", 5 ) ) {
+		this->is_extended = 0;
+		Nsf_disable_playlist( this, true );
+		
+		RETURN_ERR( Rom_load( &this->rom, data, size, header_size, &this->header, 0 ) );
+		return Nsf_post_load( this );
+	}
+	
+	this->is_extended = 1;
+	blargg_err_t err = Info_load( &this->info, data, size, this );
+	Nsf_disable_playlist( this, false );
+	return err;
+}
+
+blargg_err_t Nsf_post_load( struct Nsf_Emu* this )
+{
+	RETURN_ERR( check_nsf_header( &this->header ) );
+	
+	/* if ( header_.vers != 1 )
+		warning( "Unknown file version" ); */
+	
+	// set up data
+	addr_t load_addr = get_le16( this->header.load_addr );
+	
+	/* if ( load_addr < (fds_enabled() ? sram_addr : rom_addr) )
+		warning( "Load address is too low" ); */
+		
+	Rom_set_addr( &this->rom, load_addr % bank_size );
+	
+	/* if ( header_.vers != 1 )
+		warning( "Unknown file version" ); */
+		
+	set_play_period( this, play_period( &this->header ) );
+		
+	// sound and memory
+	blargg_err_t err = init_sound( this );
+	if ( err )
+		return err;
+	
+	// Post load
+	Sound_set_tempo( this, this->tempo );
+	
+	// Remute voices
+	Sound_mute_voices( this, this->mute_mask_ );
+
+	// Set track_count	
+	this->track_count = this->header.track_count;
+	
+	// Change clock rate & setup buffer
+	this->clock_rate__ = (long) (clock_rate( &this->header ) + 0.5);
+	Buffer_clock_rate( &this->buf, this->clock_rate__ );
+	this->buf_changed_count = Buffer_channels_changed_count( &this->buf );
+	
+	// Clear m3u playlist
+	M3u_clear( &this->m3u );
+	return 0;
+}
+
+void Nsf_disable_playlist( struct Nsf_Emu* this, bool b )
+{
+	Info_disable_playlist( &this->info, b );
+	this->track_count = this->info.track_count;
+}
+
+void Nsf_clear_playlist( struct Nsf_Emu* this )
+{
+	Nsf_disable_playlist( this, true );
+	M3u_clear( &this->m3u );
+}
+
+void write_bank( struct Nsf_Emu* this, int bank, int data )
+{
+	// Find bank in ROM
+	int offset = mask_addr( data * bank_size, this->rom.mask );
+	/* if ( offset >= rom.size() )
+		warning( "invalid bank" ); */
+	void const* rom_data = Rom_at_addr( &this->rom, offset );
+	
+	#ifndef NSF_EMU_APU_ONLY
+		if ( bank < bank_count - fds_banks && fds_enabled( this ) )
+		{
+			// TODO: FDS bank switching is kind of hacky, might need to
+			// treat ROM as RAM so changes won't get lost when switching.
+			byte* out = sram( this );
+			if ( bank >= fds_banks )
+			{
+				out = fdsram( this );
+				bank -= fds_banks;
+			}
+			memcpy( &out [bank * bank_size], rom_data, bank_size );
+			return;
+		}
+	#endif
+	
+	if ( bank >= fds_banks )
+		Cpu_map_code( &this->cpu, (bank + 6) * bank_size, bank_size, rom_data, false );
+}
+
+void map_memory( struct Nsf_Emu* this )
+{
+	// Map standard things
+	Cpu_reset( &this->cpu, unmapped_code( this ) );
+	Cpu_map_code( &this->cpu, 0, 0x2000, this->low_ram, low_ram_size ); // mirrored four times
+	Cpu_map_code( &this->cpu, sram_addr, sram_size, sram( this ), 0 );
+	
+	// Determine initial banks
+	byte banks [bank_count];
+	static byte const zero_banks [sizeof this->header.banks] = { 0 };
+	if ( memcmp( this->header.banks, zero_banks, sizeof zero_banks ) )
+	{
+		banks [0] = this->header.banks [6];
+		banks [1] = this->header.banks [7];
+		memcpy( banks + fds_banks, this->header.banks, sizeof this->header.banks );
+	}
+	else
+	{
+		// No initial banks, so assign them based on load_addr
+		int i, first_bank = (get_addr( this->header.load_addr ) - sram_addr) / bank_size;
+		unsigned total_banks = this->rom.size / bank_size;
+		for ( i = bank_count; --i >= 0; )
+		{
+			int bank = i - first_bank;
+			if ( (unsigned) bank >= total_banks )
+				bank = 0;
+			banks [i] = bank;
+		}
+	}
+	
+	// Map banks
+	int i;
+	for ( i = (fds_enabled( this ) ? 0 : fds_banks); i < bank_count; ++i )
+		write_bank( this, i, banks [i] );
+	
+	// Map FDS RAM
+	if ( fds_enabled( this ) )
+		Cpu_map_code( &this->cpu, rom_addr, fdsram_size, fdsram( this ), 0 );
+}
+
+void set_voice( struct Nsf_Emu* this, int i, struct Blip_Buffer* buf, struct Blip_Buffer* left, struct Blip_Buffer* right)
+{
+#if defined(ROCKBOX)
+	(void) left;
+	(void) right;
+#endif
+
+	if ( i < apu_osc_count )
+	{
+		Apu_osc_output( &this->apu, i, buf );
+		return;
+	}
+	i -= apu_osc_count;
+	
+	#ifndef NSF_EMU_APU_ONLY
+	{	
+		if ( vrc6_enabled( this ) && (i -= vrc6_osc_count) < 0 )
+		{
+			Vrc6_osc_output( &this->vrc6, i + vrc6_osc_count, buf );
+			return;
+		}
+		
+		if ( fme7_enabled( this ) && (i -= fme7_osc_count) < 0 )
+		{
+			Fme7_osc_output( &this->fme7, i + fme7_osc_count, buf );
+			return;
+		}
+		
+		if ( mmc5_enabled( this ) && (i -= mmc5_osc_count) < 0 )
+		{
+			Mmc5_set_output( &this->mmc5, i + mmc5_osc_count, buf );
+			return;
+		}
+		
+		if ( fds_enabled( this ) && (i -= fds_osc_count) < 0 )
+		{
+			Fds_set_output( &this->fds, i + fds_osc_count, buf );
+			return;
+		}
+		
+		if ( namco_enabled( this ) && (i -= namco_osc_count) < 0 )
+		{
+			Namco_osc_output( &this->namco, i + namco_osc_count, buf );
+			return;
+		}
+		
+		if ( vrc7_enabled( this ) && (i -= vrc7_osc_count) < 0 )
+		{
+			Vrc7_set_output( &this->vrc7, i + vrc7_osc_count, buf );
+			return;
+		}
+	}
+	#endif
+}
+
+// Emulation
+
+// Music Emu
+
+blargg_err_t Nsf_set_sample_rate( struct Nsf_Emu* this, long rate )
+{
+	require( !this->sample_rate ); // sample rate can't be changed once set
+	Buffer_init( &this->buf );
+	RETURN_ERR( Buffer_set_sample_rate( &this->buf, rate, 1000 / 20 ) );
+	
+	// Set bass frequency
+	Buffer_bass_freq( &this->buf, 80 );
+	
+	this->sample_rate = rate;
+	return 0;
+}
+
+void Sound_mute_voice( struct Nsf_Emu* this, int index, bool mute )
+{
+	require( (unsigned) index < (unsigned) this->voice_count );
+	int bit = 1 << index;
+	int mask = this->mute_mask_ | bit;
+	if ( !mute )
+		mask ^= bit;
+	Sound_mute_voices( this, mask );
+}
+
+void Sound_mute_voices( struct Nsf_Emu* this, int mask )
+{
+	require( this->sample_rate ); // sample rate must be set first
+	this->mute_mask_ = mask;
+	
+	int i;
+	for ( i = this->voice_count; i--; )
+	{
+		if ( mask & (1 << i) )
+		{
+			set_voice( this, i, 0, 0, 0 );
+		}
+		else
+		{
+			struct channel_t ch = Buffer_channel( &this->buf );
+			assert( (ch.center && ch.left && ch.right) ||
+					(!ch.center && !ch.left && !ch.right) ); // all or nothing
+			set_voice( this, i, ch.center, ch.left, ch.right );
+		}
+	}
+}
+
+void Sound_set_tempo( struct Nsf_Emu* this, double t )
+{
+	require( this->sample_rate ); // sample rate must be set first
+	double const min = 0.02;
+	double const max = 4.00;
+	if ( t < min ) t = min;
+	if ( t > max ) t = max;
+	this->tempo = t;
+	
+	set_play_period( this, (int) (play_period( &this->header ) / t) );
+
+	Apu_set_tempo( &this->apu, t );
+	
+#ifndef NSF_EMU_APU_ONLY
+	if ( fds_enabled( this ) )
+		Fds_set_tempo( &this->fds, t );
+#endif
+}
+
+inline void push_byte( struct Nsf_Emu* this, int b )
+{
+	this->low_ram [0x100 + this->cpu.r.sp--] = b;
+}
+
+// Jumps to routine, given pointer to address in file header. Pushes idle_addr
+// as return address, NOT old PC.
+void jsr_then_stop( struct Nsf_Emu* this, byte const addr [] )
+{
+	this->cpu.r.pc = get_addr( addr );
+	push_byte( this, (idle_addr - 1) >> 8 );
+	push_byte( this, (idle_addr - 1) );
+}
+
+int cpu_read( struct Nsf_Emu* this, addr_t addr )
+{
+	#ifndef NSF_EMU_APU_ONLY
+	{
+		if ( namco_enabled( this ) && addr == namco_data_reg_addr )
+			return Namco_read_data( &this->namco );
+		
+		if ( fds_enabled( this ) && (unsigned) (addr - fds_io_addr) < fds_io_size )
+			return Fds_read( &this->fds, Cpu_time( &this->cpu ), addr );
+		
+		if ( mmc5_enabled( this ) ) {
+			int i = addr - 0x5C00;
+			if ( (unsigned) i < mmc5_exram_size )
+				return this->mmc5.exram [i];
+		
+			int m = addr - 0x5205;
+			if ( (unsigned) m < 2 )
+				return (this->mmc5_mul [0] * this->mmc5_mul [1]) >> (m * 8) & 0xFF;
+		}	
+	}
+	#endif
+	
+	/* Unmapped read */
+	return addr >> 8;
+}
+
+int unmapped_read( struct Nsf_Emu* this, addr_t addr )
+{
+	(void) this;
+	
+	switch ( addr )
+	{
+	case 0x2002:
+	case 0x4016:
+	case 0x4017:
+		return addr >> 8;
+	}
+
+	// Unmapped read
+	return addr >> 8;
+}
+
+void cpu_write( struct Nsf_Emu* this, addr_t addr, int data )
+{
+	#ifndef NSF_EMU_APU_ONLY
+	{
+		nes_time_t time = Cpu_time( &this->cpu );
+		if ( fds_enabled( this) && (unsigned) (addr - fds_io_addr) < fds_io_size )
+		{
+			Fds_write( &this->fds, time, addr, data );
+			return;
+		}
+		
+		if ( namco_enabled( this) )
+		{
+			if ( addr == namco_addr_reg_addr )
+			{
+				Namco_write_addr( &this->namco, data );
+				return;
+			}
+			
+			if ( addr == namco_data_reg_addr )
+			{
+				Namco_write_data( &this->namco, time, data );
+				return;
+			}
+		}
+		
+		if ( vrc6_enabled( this) )
+		{
+			int reg = addr & (vrc6_addr_step - 1);
+			int osc = (unsigned) (addr - vrc6_base_addr) / vrc6_addr_step;
+			if ( (unsigned) osc < vrc6_osc_count && (unsigned) reg < vrc6_reg_count )
+			{
+				Vrc6_write_osc( &this->vrc6, time, osc, reg, data );
+				return;
+			}
+		}
+		
+		if ( fme7_enabled( this) && addr >= fme7_latch_addr )
+		{
+			switch ( addr & fme7_addr_mask )
+			{
+			case fme7_latch_addr:
+				Fme7_write_latch( &this->fme7, data );
+				return;
+			
+			case fme7_data_addr:
+				Fme7_write_data( &this->fme7, time, data );
+				return;
+			}
+		}
+		
+		if ( mmc5_enabled( this) )
+		{
+			if ( (unsigned) (addr - mmc5_regs_addr) < mmc5_regs_size )
+			{
+				Mmc5_write_register( &this->mmc5, time, addr, data );
+				return;
+			}
+			
+			int m = addr - 0x5205;
+			if ( (unsigned) m < 2 )
+			{
+				this->mmc5_mul [m] = data;
+				return;
+			}
+			
+			int i = addr - 0x5C00;
+			if ( (unsigned) i < mmc5_exram_size )
+			{
+				this->mmc5.exram [i] = data;
+				return;
+			}
+		}
+		
+		if ( vrc7_enabled( this) )
+		{
+			if ( addr == 0x9010 )
+			{
+				Vrc7_write_reg( &this->vrc7, data );
+				return;
+			}
+			
+			if ( (unsigned) (addr - 0x9028) <= 0x08 )
+			{
+				Vrc7_write_data( &this->vrc7, time, data );
+				return;
+			}
+		}
+	}
+	#endif
+	
+	// Unmapped_write
+}
+
+void unmapped_write( struct Nsf_Emu* this, addr_t addr, int data )
+{
+	(void) data;
+	
+	switch ( addr )
+	{
+	case 0x8000: // some write to $8000 and $8001 repeatedly
+	case 0x8001:
+	case 0x4800: // probably namco sound mistakenly turned on in MCK
+	case 0xF800:
+	case 0xFFF8: // memory mapper?
+		return;
+	}
+	
+	if ( mmc5_enabled( this ) && addr == 0x5115 ) return;
+	
+	// FDS memory
+	if ( fds_enabled( this ) && (unsigned) (addr - 0x8000) < 0x6000 ) return;
+}
+
+void fill_buf( struct Nsf_Emu* this );
+blargg_err_t Nsf_start_track( struct Nsf_Emu* this, int track )
+{
+	clear_track_vars( this );
+	
+	// Remap track if playlist available
+	if ( this->m3u.size > 0 ) {
+		struct entry_t* e = &this->m3u.entries[track];
+		if ( e->track >= 0 )
+		{
+			track = e->track;
+			/* TODO: Is this necessary?*/
+			/* if ( !(this->m3u.type_->flags_ & 0x02) )
+				track -= e.decimal_track; */
+		}
+		
+		if ( track >= this->header.track_count )
+			track = 0;
+	}
+	// Else try with nsfe playlist
+	else
+		track = Info_remap_track( &this->info, track );
+	
+	this->current_track = track;
+	
+	Buffer_clear( &this->buf );
+	
+	#ifndef NSF_EMU_APU_ONLY
+		if ( mmc5_enabled( this ) )
+		{
+			this->mmc5_mul [0] = 0;
+			this->mmc5_mul [1] = 0;
+			memset( this->mmc5.exram, 0, mmc5_exram_size );
+		}
+
+		if ( fds_enabled( this )   ) Fds_reset( &this->fds );
+		if ( namco_enabled( this ) ) Namco_reset( &this->namco );
+		if ( vrc6_enabled( this )  ) Vrc6_reset( &this->vrc6 );
+		if ( fme7_enabled( this )  ) Fme7_reset( &this->fme7 );
+		if ( mmc5_enabled( this )  ) Apu_reset( &this->mmc5.apu, false, 0 );
+		if ( vrc7_enabled( this )  ) Vrc7_reset( &this->vrc7 );
+	#endif
+	
+	int speed_flags = 0;
+	#ifdef NSF_EMU_EXTRA_FLAGS
+		speed_flags = this->header.speed_flags;
+	#endif
+	
+	Apu_reset( &this->apu, pal_only( &this->header ), (speed_flags & 0x20) ? 0x3F : 0 );
+	Apu_write_register( &this->apu, 0, 0x4015, 0x0F );
+	Apu_write_register( &this->apu, 0, 0x4017, (speed_flags & 0x10) ? 0x80 : 0 );
+	
+	memset( unmapped_code( this ), halt_opcode, unmapped_size );
+	memset( this->low_ram, 0, low_ram_size );
+	memset( sram( this ), 0, sram_size );
+	
+	map_memory( this );
+	
+	// Arrange time of first call to play routine
+	this->play_extra = 0;
+	this->next_play  = this->play_period;
+	
+	this->play_delay = initial_play_delay;
+	this->saved_state.pc = idle_addr;
+	
+	// Setup for call to init routine
+	this->cpu.r.a  = track;
+	this->cpu.r.x  = pal_only( &this->header );
+	this->cpu.r.sp = 0xFF;
+	jsr_then_stop( this, this->header.init_addr );
+	/* if ( this->cpu.r.pc < get_addr( header.load_addr ) )
+		warning( "Init address < load address" ); */
+	
+	this->emu_track_ended_ = false;
+	this->track_ended     = false;
+	
+	if ( !this->ignore_silence )
+	{
+		// play until non-silence or end of track
+		long end;
+		for ( end = this->max_initial_silence * stereo * this->sample_rate; this->emu_time < end; )
+		{
+			fill_buf( this );
+			if ( this->buf_remain | (int) this->emu_track_ended_ )
+				break;
+		}
+		
+		this->emu_time      = this->buf_remain;
+		this->out_time      = 0;
+		this->silence_time  = 0;
+		this->silence_count = 0;
+	}
+	/* return track_ended() ? warning() : 0; */
+	return 0;
+}
+
+void run_once( struct Nsf_Emu* this, nes_time_t end )
+{
+	// Emulate until next play call if possible
+	if ( run_cpu_until( this, min( this->next_play, end ) ) )
+	{
+		// Halt instruction encountered
+		
+		if ( this->cpu.r.pc != idle_addr )
+		{
+			// special_event( "illegal instruction" );
+			Cpu_set_time( &this->cpu, this->cpu.end_time );
+			return;
+		}
+
+		// Init/play routine returned
+		this->play_delay = 1; // play can now be called regularly
+		
+		if ( this->saved_state.pc == idle_addr )
+		{
+			// nothing to run
+			nes_time_t t = this->cpu.end_time;
+			if ( Cpu_time( &this->cpu ) < t )
+				Cpu_set_time( &this->cpu, t );
+		}
+		else
+		{
+			// continue init routine that was interrupted by play routine
+			this->cpu.r = this->saved_state;
+			this->saved_state.pc = idle_addr;
+		}
+	}
+	
+	if ( Cpu_time( &this->cpu ) >= this->next_play )
+	{
+		// Calculate time of next call to play routine
+		this->play_extra ^= 1; // extra clock every other call
+		this->next_play += this->play_period + this->play_extra;
+		
+		// Call routine if ready
+		if ( this->play_delay && !--this->play_delay )
+		{
+			// Save state if init routine is still running
+			if ( this->cpu.r.pc != idle_addr )
+			{
+				check( this->saved_state.pc == idle_addr );
+				this->saved_state = this->cpu.r;
+				// special_event( "play called during init" );
+			}
+			
+			jsr_then_stop( this, this->header.play_addr );
+		}
+	}
+}
+
+void run_until( struct Nsf_Emu* this, nes_time_t end )
+{
+	while ( Cpu_time( &this->cpu ) < end )
+		run_once( this, end );
+}
+
+void end_frame( struct Nsf_Emu* this, nes_time_t end )
+{
+	if ( Cpu_time( &this->cpu ) < end )
+		run_until( this, end );
+	Cpu_adjust_time( &this->cpu, -end );
+	
+	// Localize to new time frame
+	this->next_play -= end;
+	check( this->next_play >= 0 );
+	if ( this->next_play < 0 )
+		this->next_play = 0;
+	
+	Apu_end_frame( &this->apu, end );
+	
+	#ifndef NSF_EMU_APU_ONLY
+		if ( fds_enabled( this )   ) Fds_end_frame( &this->fds, end );
+		if ( fme7_enabled( this )  ) Fme7_end_frame( &this->fme7, end );
+		if ( mmc5_enabled( this )  ) Apu_end_frame( &this->mmc5.apu, end );
+		if ( namco_enabled( this ) ) Namco_end_frame( &this->namco, end );
+		if ( vrc6_enabled( this )  ) Vrc6_end_frame( &this->vrc6, end );
+		if ( vrc7_enabled( this )  ) Vrc7_end_frame( &this->vrc7, end );
+	#endif
+}
+
+// Tell/Seek
+
+blargg_long msec_to_samples( long sample_rate, blargg_long msec )
+{
+	blargg_long sec = msec / 1000;
+	msec -= sec * 1000;
+	return (sec * sample_rate + msec * sample_rate / 1000) * stereo;
+}
+
+long Track_tell( struct Nsf_Emu* this )
+{
+	blargg_long rate = this->sample_rate * stereo;
+	blargg_long sec = this->out_time / rate;
+	return sec * 1000 + (this->out_time - sec * rate) * 1000 / rate;
+}
+
+blargg_err_t Track_seek( struct Nsf_Emu* this, long msec )
+{
+	blargg_long time = msec_to_samples( this->sample_rate, msec );
+	if ( time < this->out_time )
+		RETURN_ERR( Nsf_start_track( this, this->current_track ) );
+	return Track_skip( this, time - this->out_time );
+}
+
+blargg_err_t skip_( struct Nsf_Emu* this, long count ); ICODE_ATTR
+blargg_err_t Track_skip( struct Nsf_Emu* this, long count )
+{
+	require( this->current_track >= 0 ); // start_track() must have been called already
+	this->out_time += count;
+	
+	// remove from silence and buf first
+	{
+		long n = min( count, this->silence_count );
+		this->silence_count -= n;
+		count -= n;
+		
+		n = min( count, this->buf_remain );
+		this->buf_remain -= n;
+		count -= n;
+	}
+		
+	if ( count && !this->emu_track_ended_ )
+	{
+		this->emu_time += count;
+		// End track if error
+		if ( skip_( this, count ) ) 
+			this->emu_track_ended_ = true;
+	}
+	
+	if ( !(this->silence_count | this->buf_remain) ) // caught up to emulator, so update track ended
+		this->track_ended |= this->emu_track_ended_;
+	
+	return 0;
+}
+
+blargg_err_t play_( struct Nsf_Emu* this, long count, sample_t* out ); ICODE_ATTR
+blargg_err_t skip_( struct Nsf_Emu* this, long count )
+{
+	// for long skip, mute sound
+	const long threshold = 30000;
+	if ( count > threshold )
+	{
+		int saved_mute = this->mute_mask_;
+		Sound_mute_voices( this, ~0 );
+		
+		while ( count > threshold / 2 && !this->emu_track_ended_ )
+		{
+			RETURN_ERR( play_( this, buf_size, this->buf_ ) );
+			count -= buf_size;
+		}
+		
+		Sound_mute_voices( this, saved_mute );
+	}
+	
+	while ( count && !this->emu_track_ended_ )
+	{
+		long n = buf_size;
+		if ( n > count )
+			n = count;
+		count -= n;
+		RETURN_ERR( play_( this, n, this->buf_ ) );
+	}
+	return 0;
+}
+
+// Fading
+
+void Track_set_fade( struct Nsf_Emu* this, long start_msec, long length_msec )
+{
+	this->fade_step = this->sample_rate * length_msec / (fade_block_size * fade_shift * 1000 / stereo);
+	this->fade_start = msec_to_samples( this->sample_rate, start_msec );
+}
+
+// unit / pow( 2.0, (double) x / step )
+static int int_log( blargg_long x, int step, int unit )
+{
+	int shift = x / step;
+	int fraction = (x - shift * step) * unit / step;
+	return ((unit - fraction) + (fraction >> 1)) >> shift;
+}
+
+void handle_fade( struct Nsf_Emu* this, long out_count, sample_t* out )
+{
+	int i;
+	for ( i = 0; i < out_count; i += fade_block_size )
+	{
+		int const shift = 14;
+		int const unit = 1 << shift;
+		int gain = int_log( (this->out_time + i - this->fade_start) / fade_block_size,
+				this->fade_step, unit );
+		if ( gain < (unit >> fade_shift) )
+			this->track_ended = this->emu_track_ended_ = true;
+		
+		sample_t* io = &out [i];
+		int count;
+		for ( count = min( fade_block_size, out_count - i ); count; --count )
+		{
+			*io = (sample_t) ((*io * gain) >> shift);
+			++io;
+		}
+	}
+}
+
+// Silence detection
+
+void emu_play( struct Nsf_Emu* this, long count, sample_t* out ); ICODE_ATTR
+void emu_play( struct Nsf_Emu* this, long count, sample_t* out )
+{
+	check( current_track_ >= 0 );
+	this->emu_time += count;
+	if ( this->current_track >= 0 && !this->emu_track_ended_ ) {
+		
+		// End track if error
+		if ( play_( this, count, out ) )
+			this->emu_track_ended_ = true;
+	}
+	else
+		memset( out, 0, count * sizeof *out );
+}
+
+// number of consecutive silent samples at end
+static long count_silence( sample_t* begin, long size )
+{
+	sample_t first = *begin;
+	*begin = silence_threshold; // sentinel
+	sample_t* p = begin + size;
+	while ( (unsigned) (*--p + silence_threshold / 2) <= (unsigned) silence_threshold ) { }
+	*begin = first;
+	return size - (p - begin);
+}
+
+// fill internal buffer and check it for silence
+void fill_buf( struct Nsf_Emu* this )
+{
+	assert( !this->buf_remain );
+	if ( !this->emu_track_ended_ )
+	{
+		emu_play( this, buf_size, this->buf_ );
+		long silence = count_silence( this->buf_, buf_size );
+		if ( silence < buf_size )
+		{
+			this->silence_time = this->emu_time - silence;
+			this->buf_remain   = buf_size;
+			return;
+		}
+	}
+	this->silence_count += buf_size;
+}
+
+blargg_err_t Nsf_play( struct Nsf_Emu* this, long out_count, sample_t* out )
+{
+	if ( this->track_ended )
+	{
+		memset( out, 0, out_count * sizeof *out );
+	}
+	else
+	{
+		require( this->current_track >= 0 );
+		require( out_count % stereo == 0 );
+		
+		assert( this->emu_time >= this->out_time );
+		
+		// prints nifty graph of how far ahead we are when searching for silence
+		//debug_printf( "%*s \n", int ((emu_time - out_time) * 7 / sample_rate()), "*" );
+		
+		long pos = 0;
+		if ( this->silence_count )
+		{
+			// during a run of silence, run emulator at >=2x speed so it gets ahead
+			long ahead_time = this->silence_lookahead * (this->out_time + out_count - this->silence_time) + this->silence_time;
+			while ( this->emu_time < ahead_time && !(this->buf_remain | this->emu_track_ended_) )
+				fill_buf( this );
+			
+			// fill with silence
+			pos = min( this->silence_count, out_count );
+			memset( out, 0, pos * sizeof *out );
+			this->silence_count -= pos;
+			
+			if ( this->emu_time - this->silence_time > silence_max * stereo * this->sample_rate )
+			{
+				this->track_ended  = this->emu_track_ended_ = true;
+				this->silence_count = 0;
+				this->buf_remain    = 0;
+			}
+		}
+		
+		if ( this->buf_remain )
+		{
+			// empty silence buf
+			long n = min( this->buf_remain, out_count - pos );
+			memcpy( &out [pos], this->buf_ + (buf_size - this->buf_remain), n * sizeof *out );
+			this->buf_remain -= n;
+			pos += n;
+		}
+		
+		// generate remaining samples normally
+		long remain = out_count - pos;
+		if ( remain )
+		{
+			emu_play( this, remain, out + pos );
+			this->track_ended |= this->emu_track_ended_;
+			
+			if ( !this->ignore_silence || this->out_time > this->fade_start )
+			{
+				// check end for a new run of silence
+				long silence = count_silence( out + pos, remain );
+				if ( silence < remain )
+					this->silence_time = this->emu_time - silence;
+				
+				if ( this->emu_time - this->silence_time >= buf_size )
+					fill_buf( this ); // cause silence detection on next play()
+			}
+		}
+		
+		if ( this->out_time > this->fade_start )
+			handle_fade( this, out_count, out );
+	}
+	this->out_time += out_count;
+	return 0;
+}
+
+blargg_err_t play_( struct Nsf_Emu* this, long count, sample_t* out )
+{
+	long remain = count;
+	while ( remain )
+	{
+		remain -= Buffer_read_samples( &this->buf, &out [count - remain], remain );
+		if ( remain )
+		{
+			if ( this->buf_changed_count != Buffer_channels_changed_count( &this->buf ) )
+			{
+				this->buf_changed_count = Buffer_channels_changed_count( &this->buf );
+
+				// Remute voices
+				Sound_mute_voices( this, this->mute_mask_ );
+			}
+			int msec = Buffer_length( &this->buf );
+			blip_time_t clocks_emulated = (blargg_long) msec * this->clock_rate__ / 1000 - 100;
+			RETURN_ERR( run_clocks( this, &clocks_emulated, msec ) );
+			assert( clocks_emulated );
+			Buffer_end_frame( &this->buf, clocks_emulated );
+		}
+	}
+	return 0;
+}
+
+blargg_err_t run_clocks( struct Nsf_Emu* this, blip_time_t* duration, int msec )
+{
+#if defined(ROCKBOX)
+	(void) msec;
+#endif
+
+	end_frame( this, *duration );
+	return 0;
+}
Index: apps/codecs/libnsf/gme_types.h
===================================================================
--- apps/codecs/libnsf/gme_types.h	(revision 0)
+++ apps/codecs/libnsf/gme_types.h	(revision 0)
@@ -0,0 +1,21 @@
+#ifndef GME_TYPES_H
+#define GME_TYPES_H
+
+/*
+ * This is a default gme_types.h for use when *not* using
+ * CMake.  If CMake is in use gme_types.h.in will be
+ * processed instead.
+ */
+#define USE_GME_AY
+#define USE_GME_GBS
+#define USE_GME_GYM
+#define USE_GME_HES
+#define USE_GME_KSS
+#define USE_GME_NSF
+#define USE_GME_NSFE
+#define USE_GME_SAP
+#define USE_GME_SPC
+/* VGM and VGZ are a package deal */
+#define USE_GME_VGM
+
+#endif /* GME_TYPES_H */
Index: apps/codecs/libnsf/nsf_emu.h
===================================================================
--- apps/codecs/libnsf/nsf_emu.h	(revision 0)
+++ apps/codecs/libnsf/nsf_emu.h	(revision 0)
@@ -0,0 +1,264 @@
+// Nintendo NES/Famicom NSF music file emulator
+
+// Game_Music_Emu 0.5.5
+#ifndef NSF_EMU_H
+#define NSF_EMU_H
+
+#include "rom_data.h"
+#include "multi_buffer.h"
+#include "nes_apu.h"
+#include "nes_cpu.h"
+#include "nsfe_info.h"
+#include "m3u_playlist.h"
+
+#ifndef NSF_EMU_APU_ONLY
+	#include "nes_namco_apu.h"
+	#include "nes_vrc6_apu.h"
+	#include "nes_fme7_apu.h"
+	#include "nes_fds_apu.h"
+	#include "nes_mmc5_apu.h"
+	#include "nes_vrc7_apu.h"
+#endif
+
+typedef short sample_t;
+
+// Sound chip flags
+enum {
+	vrc6_flag  = 1 << 0,
+	vrc7_flag  = 1 << 1,
+	fds_flag   = 1 << 2,
+	mmc5_flag  = 1 << 3,
+	namco_flag = 1 << 4,
+	fme7_flag  = 1 << 5
+};
+
+enum { fds_banks    = 2 };
+enum { bank_count   = fds_banks + 8 };
+
+enum { rom_begin = 0x8000 };
+enum { bank_select_addr = 0x5FF8 };
+enum { mem_size  = 0x10000 };	
+	
+// cpu sits here when waiting for next call to play routine
+enum { idle_addr = 0x5FF6 };
+enum { banks_addr = idle_addr };
+enum { badop_addr = bank_select_addr };
+
+enum { low_ram_size = 0x800 };
+enum { sram_size    = 0x2000 };
+enum { fdsram_size  = 0x6000 };
+enum { fdsram_offset = 0x2000 + page_size + 8 };
+enum { sram_addr = 0x6000 };
+enum { unmapped_size= page_size + 8 };
+
+enum { buf_size = 2048 };
+
+// NSF file header
+enum { header_size = 0x80 };
+struct header_t
+{
+	char tag [5];
+	byte vers;
+	byte track_count;
+	byte first_track;
+	byte load_addr [2];
+	byte init_addr [2];
+	byte play_addr [2];
+	char game [32];
+	char author [32];
+	char copyright [32];
+	byte ntsc_speed [2];
+	byte banks [8];
+	byte pal_speed [2];
+	byte speed_flags;
+	byte chip_flags;
+	byte unused [4];
+};
+
+struct Nsf_Emu {
+	// Header for currently loaded file
+	struct header_t header;
+	
+	// M3u Playlist
+	struct M3u_Playlist m3u;
+	
+	byte high_ram[fdsram_size + fdsram_offset];
+	byte low_ram [low_ram_size];
+	struct Rom_Data rom;
+	
+	// Play routine timing
+	nes_time_t next_play;
+	nes_time_t play_period;
+	int play_extra;
+	int play_delay;
+	struct registers_t saved_state; // of interrupted init routine
+	
+	struct Nes_Cpu cpu;
+	struct Nes_Apu apu;
+
+	#ifndef NSF_EMU_APU_ONLY
+		byte mmc5_mul [2];
+		
+		struct Nes_Fds_Apu   fds;
+		struct Nes_Mmc5_Apu  mmc5;
+		struct Nes_Namco_Apu namco;
+		struct Nes_Vrc6_Apu  vrc6;
+		struct Nes_Fme7_Apu  fme7;
+		struct Nes_Vrc7_Apu  vrc7;
+	#endif
+	
+	int track_count;
+
+	// general
+	int max_initial_silence;
+	int voice_count;
+	int mute_mask_;
+	double tempo;
+	double gain;
+	
+	long sample_rate;
+	
+	// track-specific
+	int current_track;
+	blargg_long out_time;  // number of samples played since start of track
+	blargg_long emu_time;  // number of samples emulator has generated since start of track
+	bool emu_track_ended_; // emulator has reached end of track
+	volatile bool track_ended;
+	
+	// fading
+	blargg_long fade_start;
+	int fade_step;
+	
+	// silence detection
+	int silence_lookahead; // speed to run emulator when looking ahead for silence
+	bool ignore_silence;
+	long silence_time;     // number of samples where most recent silence began
+	long silence_count;    // number of samples of silence to play before using buf
+	long buf_remain;       // number of samples left in silence buffer
+	sample_t buf_ [buf_size];	
+
+	struct Stereo_Buffer buf;
+	double clock_rate_;
+	long clock_rate__;
+	unsigned buf_changed_count;
+
+	// Nsfe related
+	int is_extended;
+	struct Nsfe_Info info;
+};
+
+// Basic functionality (see Gme_File.h for file loading/track info functions)
+
+void Nsf_init( struct Nsf_Emu* this );
+blargg_err_t Nsf_load( struct Nsf_Emu* this, void* data, long size );
+blargg_err_t Nsf_post_load( struct Nsf_Emu* this );
+
+// Set output sample rate. Must be called only once before loading file.
+blargg_err_t Nsf_set_sample_rate( struct Nsf_Emu* this, long sample_rate );
+	
+// Start a track, where 0 is the first track. Also clears warning string.
+blargg_err_t Nsf_start_track( struct Nsf_Emu* this , int );
+	
+// Generate 'count' samples info 'buf'. Output is in stereo. Any emulation
+// errors set warning string, and major errors also end track.
+blargg_err_t Nsf_play( struct Nsf_Emu* this, long count, sample_t* buf );
+
+// Load extended m3u playlist
+blargg_err_t Nsf_load_m3u( struct Nsf_Emu* this, const char* path );
+
+void Nsf_clear_playlist( struct Nsf_Emu* this );
+void Nsf_disable_playlist( struct Nsf_Emu* this, bool b ); // use clear_playlist()
+
+// Track status/control
+
+// Number of milliseconds (1000 msec = 1 second) played since beginning of track
+long Track_tell( struct Nsf_Emu* this );
+	
+// Seek to new time in track. Seeking backwards or far forward can take a while.
+blargg_err_t Track_seek( struct Nsf_Emu* this, long msec );
+	
+// Skip n samples
+blargg_err_t Track_skip( struct Nsf_Emu* this, long n );
+		
+// Set start time and length of track fade out. Once fade ends track_ended() returns
+// true. Fade time can be changed while track is playing.
+void Track_set_fade( struct Nsf_Emu* this, long start_msec, long length_msec );
+
+// Get track length in milliseconds
+long Track_length( struct Nsf_Emu* this, int n );
+
+// Sound customization
+	
+// Adjust song tempo, where 1.0 = normal, 0.5 = half speed, 2.0 = double speed.
+// Track length as returned by track_info() assumes a tempo of 1.0.
+void Sound_set_tempo( struct Nsf_Emu* this, double t );
+	
+// Mute/unmute voice i, where voice 0 is first voice
+void Sound_mute_voice( struct Nsf_Emu* this, int index, bool mute );
+	
+// Set muting state of all voices at once using a bit mask, where -1 mutes them all,
+// 0 unmutes them all, 0x01 mutes just the first voice, etc.
+void Sound_mute_voices( struct Nsf_Emu* this, int mask );
+	
+// Change overall output amplitude, where 1.0 results in minimal clamping.
+// Must be called before set_sample_rate().
+static inline void Sound_set_gain( struct Nsf_Emu* this, double g )
+{
+	assert( !this->sample_rate ); // you must set gain before setting sample rate
+	this->gain = g;
+}
+
+// Emulation (You shouldn't touch these)
+
+blargg_err_t run_clocks( struct Nsf_Emu* this, blip_time_t* duration, int );
+	
+void map_memory( struct Nsf_Emu* this ); ICODE_ATTR
+void write_bank( struct Nsf_Emu* this, int index, int data ); ICODE_ATTR
+int cpu_read( struct Nsf_Emu* this, addr_t ); ICODE_ATTR
+void cpu_write( struct Nsf_Emu* this, addr_t, int ); ICODE_ATTR
+void push_byte( struct Nsf_Emu* this, int ); ICODE_ATTR
+addr_t get_addr( byte const [] ); ICODE_ATTR
+bool run_cpu_until( struct Nsf_Emu* this, nes_time_t end ); ICODE_ATTR
+
+// Sets clocks between calls to play routine to p + 1/2 clock
+static inline void set_play_period( struct Nsf_Emu* this, int p ) { this->play_period = p; }
+	
+// Time play routine will next be called
+static inline nes_time_t play_time( struct Nsf_Emu* this ) { return this->next_play; }
+	
+// Emulates to at least time t. Might emulate a few clocks extra.
+void run_until( struct Nsf_Emu* this, nes_time_t t ); ICODE_ATTR
+	
+// Runs cpu to at least time t and returns false, or returns true
+// if it encounters illegal instruction (halt).
+bool run_cpu_until( struct Nsf_Emu* this, nes_time_t t ); ICODE_ATTR
+	
+// cpu calls through to these to access memory (except instructions)
+int  read_mem(  struct Nsf_Emu* this, addr_t ); ICODE_ATTR
+void write_mem( struct Nsf_Emu* this, addr_t, int ); ICODE_ATTR
+	
+// Address of play routine
+static inline addr_t play_addr( struct Nsf_Emu* this ) { return get_addr( this->header.play_addr ); }
+	
+// Same as run_until, except emulation stops for any event (routine returned,
+// play routine called, illegal instruction).
+void run_once( struct Nsf_Emu* this, nes_time_t ); ICODE_ATTR
+	
+// Reads byte as cpu would when executing code. Only works for RAM/ROM,
+// NOT I/O like sound chips.
+int  read_code( struct Nsf_Emu* this, addr_t addr ); ICODE_ATTR
+
+static inline byte* fdsram( struct Nsf_Emu* this )          { return &this->high_ram [fdsram_offset]; }
+static inline byte* sram( struct Nsf_Emu* this )            { return this->high_ram; }
+static inline byte* unmapped_code( struct Nsf_Emu* this )   { return &this->high_ram [sram_size]; }
+
+#ifndef NSF_EMU_APU_ONLY
+static inline int fds_enabled( struct Nsf_Emu* this )   { return this->header.chip_flags & fds_flag;   }
+static inline int vrc6_enabled( struct Nsf_Emu* this )  { return this->header.chip_flags & vrc6_flag;  }
+static inline int vrc7_enabled( struct Nsf_Emu* this )  { return this->header.chip_flags & vrc7_flag;  }
+static inline int mmc5_enabled( struct Nsf_Emu* this )  { return this->header.chip_flags & mmc5_flag;  }
+static inline int namco_enabled( struct Nsf_Emu* this ) { return this->header.chip_flags & namco_flag; }
+static inline int fme7_enabled( struct Nsf_Emu* this )  { return this->header.chip_flags & fme7_flag;  }
+#endif
+	
+#endif
Index: apps/codecs/libnsf/SOURCES
===================================================================
--- apps/codecs/libnsf/SOURCES	(revision 0)
+++ apps/codecs/libnsf/SOURCES	(revision 0)
@@ -0,0 +1,16 @@
+blip_buffer.c
+multi_buffer.c
+rom_data.c
+m3u_playlist.c
+nes_apu.c
+nes_cpu.c
+nes_fds_apu.c
+nes_fme7_apu.c
+nes_namco_apu.c
+nes_oscs.c
+nes_vrc6_apu.c
+nes_vrc7_apu.c
+nsf_cpu.c
+nsf_emu.c
+nsfe_info.c
+ym2413.c
Index: apps/codecs/libnsf/nsfe_info.c
===================================================================
--- apps/codecs/libnsf/nsfe_info.c	(revision 0)
+++ apps/codecs/libnsf/nsfe_info.c	(revision 0)
@@ -0,0 +1,301 @@
+// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
+
+#include "nsf_emu.h"
+
+#include "blargg_endian.h"
+#include <string.h>
+
+/* Copyright (C) 2005-2006 Shay Green. This module is free software; you
+can redistribute it and/or modify it under the terms of the GNU Lesser
+General Public License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version. This
+module is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+details. You should have received a copy of the GNU Lesser General Public
+License along with this module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+void Info_init( struct Nsfe_Info* this )
+{ 
+	this->playlist_disabled = false; 
+}
+
+void Info_unload( struct Nsfe_Info* this )
+{
+	/* TODO: clear track_names */
+	
+	memset(&this->auth, 0, sizeof this->auth);
+	
+	memset(this->playlist, 0, 256);
+	memset(this->track_times, 0, 256 * sizeof(int32_t));
+	
+	this->playlist_size = 0;
+	this->track_times_size = 0;
+}
+
+// TODO: if no playlist, treat as if there is a playlist that is just 1,2,3,4,5... ?
+void Info_disable_playlist( struct Nsfe_Info* this, bool b )
+{
+	this->playlist_disabled = b;
+	this->track_count = this->playlist_size;
+	if ( !this->track_count || this->playlist_disabled )
+		this->track_count = this->actual_track_count_;
+}
+
+int Info_remap_track( struct Nsfe_Info* this, int track )
+{
+	if ( !this->playlist_disabled && (unsigned) track < (unsigned) this->playlist_size )
+		track = this->playlist [track];
+	return track;
+}
+
+const char eof_error [] = "Unexpected end of file";
+
+// Read n bytes from memory buffer
+static blargg_err_t in_read( void* dst, long bytes, void* data, long* offset, long size )
+{
+	if ((*offset + bytes) > size) return eof_error;
+	
+	memcpy(dst, (char*) data + *offset, bytes);
+	*offset += bytes;
+	return 0;
+}
+
+static blargg_err_t in_skip( long bytes, long *offset, long size )
+{
+	if ((*offset + bytes) > size) return eof_error;
+	
+	*offset += bytes;
+	return 0;
+}
+
+// Skip n bytes from memory buffer
+
+// Read multiple strings and separate into individual strings
+static int read_strs( void* data, long bytes, long* offset, long size,
+		const char* strs [4] )
+{
+	char* chars = (char*) data + *offset;
+	chars [bytes - 1] = 0; // in case last string doesn't have terminator
+	
+	if ( in_skip( bytes, offset, size) )
+		return -1;
+
+	int count = 0, i;
+	for ( i = 0; i < bytes; i++ )
+	{
+		strs [count] = &chars [i];
+		while ( i < bytes && chars [i] )
+			i++;
+		
+		count++;
+		if (count >= 4) 
+			break;
+	}
+	
+	return count;
+}
+
+// Copy in to out, where out has out_max characters allocated. Truncate to
+// out_max - 1 characters.
+static void copy_str( const char* in, char* out, int out_max )
+{
+	out [out_max - 1] = 0;
+	strlcpy( out, in, out_max - 1 );
+}
+
+struct nsfe_info_t
+{
+	byte load_addr [2];
+	byte init_addr [2];
+	byte play_addr [2];
+	byte speed_flags;
+	byte chip_flags;
+	byte track_count;
+	byte first_track;
+	byte unused [6];
+};
+
+blargg_err_t Info_load( struct Nsfe_Info* this, void* data, long size, struct Nsf_Emu* nsf_emu )
+{
+	long offset = 0;
+	int const nsfe_info_size = 16;
+	assert( offsetof (struct nsfe_info_t,unused [6]) == nsfe_info_size );
+	
+	// check header
+	byte signature [4];
+	blargg_err_t err = in_read( signature, sizeof signature, data, &offset, size );
+	if ( err )
+		return (err == eof_error ? gme_wrong_file_type : err);
+	if ( memcmp( signature, "NSFE", 4 ) ) {
+	}
+	
+	// free previous info
+	/* TODO: clear track_names */
+	memset(this->playlist, 0, 256);
+	memset(this->track_times, 0, 256 * sizeof(int32_t));
+	
+	this->playlist_size = 0;
+	this->track_times_size = 0;
+	
+	// default nsf header
+	static const struct header_t base_header =
+	{
+		{'N','E','S','M','\x1A'},// tag
+		1,                  // version
+		1, 1,               // track count, first track
+		{0,0},{0,0},{0,0},  // addresses
+		"","","",           // strings
+		{0x1A, 0x41},       // NTSC rate
+		{0,0,0,0,0,0,0,0},  // banks
+		{0x20, 0x4E},       // PAL rate
+		0, 0,               // flags
+		{0,0,0,0}           // unused
+	};
+	
+	memcpy( &nsf_emu->header, &base_header, sizeof base_header );
+	
+	// parse tags
+	int phase = 0;
+	while ( phase != 3 )
+	{
+		// read size and tag
+		byte block_header [2] [4];
+		RETURN_ERR( in_read( block_header, sizeof block_header, data, &offset, size ) );
+		
+		blargg_long chunk_size = get_le32( block_header [0] );
+		blargg_long tag  = get_le32( block_header [1] );
+		
+		switch ( tag )
+		{
+			case BLARGG_4CHAR('O','F','N','I'): {
+				check( phase == 0 );
+				if ( chunk_size < 8 )
+					return "Corrupt file";
+				
+				struct nsfe_info_t finfo;
+				finfo.track_count = 1;
+				finfo.first_track = 0;
+				
+				RETURN_ERR( in_read( &finfo, min( chunk_size, (blargg_long) nsfe_info_size ), 
+					(char*) data, &offset, size ) );
+				
+				if ( chunk_size > nsfe_info_size )
+					RETURN_ERR( in_skip( chunk_size - nsfe_info_size, &offset, size ) );
+					
+				phase = 1;
+				nsf_emu->header.speed_flags = finfo.speed_flags;
+				nsf_emu->header.chip_flags  = finfo.chip_flags;
+				nsf_emu->header.track_count = finfo.track_count;
+				this->actual_track_count_ = finfo.track_count;
+				nsf_emu->header.first_track = finfo.first_track;
+				memcpy( nsf_emu->header.load_addr, finfo.load_addr, 2 * 3 );
+				break;
+			}
+			
+			case BLARGG_4CHAR('K','N','A','B'):
+				if ( chunk_size > (int) sizeof nsf_emu->header.banks )
+					return "Corrupt file";
+				RETURN_ERR( in_read( nsf_emu->header.banks, chunk_size, data, &offset, size ) );
+				break;
+			
+			case BLARGG_4CHAR('h','t','u','a'): {
+				const char* strs [4];
+				int n = read_strs( data, chunk_size, &offset, size, strs );
+			
+				if ( n > 3 )
+					copy_str( strs [3], this->auth.dumper, sizeof this-> auth.dumper );
+					
+				if ( n > 2 )
+					copy_str( strs [2], this->auth.copyright, sizeof this->auth.copyright );
+				
+				if ( n > 1 )
+					copy_str( strs [1], this->auth.author, sizeof this->auth.author );
+				
+				if ( n > 0 )
+					copy_str( strs [0], this->auth.game, sizeof this->auth.game );
+				
+				if ( n < 0 ) 
+					return eof_error;
+				break;
+			}
+			
+			case BLARGG_4CHAR('e','m','i','t'):
+				this->track_times_size = chunk_size / 4;
+				RETURN_ERR( in_read( this->track_times, this->track_times_size * 4, data, &offset, size ) );
+				break;
+			
+			case BLARGG_4CHAR('l','b','l','t'):
+				RETURN_ERR( in_skip( chunk_size, &offset, size ) );
+				/* RETURN_ERR( read_strs( data, chunk_size, &offset, size, track_names ) ); */
+				break;
+			
+			case BLARGG_4CHAR('t','s','l','p'):
+				this->playlist_size = chunk_size;
+				RETURN_ERR( in_read( &this->playlist [0], chunk_size, data, &offset, size ) );
+				break;
+			
+			case BLARGG_4CHAR('A','T','A','D'): {
+				check( phase == 1 );
+				phase = 2;
+				if ( !nsf_emu )
+				{
+					RETURN_ERR( in_skip( chunk_size, &offset, size ) );
+				}
+				else
+				{
+					// Avoid unexpected end of file
+					if ( (offset + chunk_size) > size )
+						return eof_error;
+						
+					RETURN_ERR( Rom_load( &nsf_emu->rom, (char*) data + offset, chunk_size, 0, 0, 0 ) );
+					RETURN_ERR( Nsf_post_load( nsf_emu ) );
+					offset += chunk_size;
+				}
+				break;
+			}
+			
+			case BLARGG_4CHAR('D','N','E','N'):
+				check( phase == 2 );
+				phase = 3;
+				break;
+			
+			default:
+				// tags that can be skipped start with a lowercase character
+				check( islower( (tag >> 24) & 0xFF ) );
+				RETURN_ERR( in_skip( chunk_size, &offset, size ) );
+				break;
+		}
+	}
+	
+	return 0;
+}
+
+long Track_length( struct Nsf_Emu* this, int n )
+{
+    long length = 60 * 5 * 1000;  /* 5 minutes */ 
+	if ( (this->m3u.size > 0) && (n < this->m3u.size) ) {
+		struct entry_t* entry = &this->m3u.entries [n];
+		length = entry->length;
+		if ( length <= 0 ) {
+			long intro = entry->intro > 0 ? entry->intro : 60 * 5 * 1000;;
+			long loop = entry->loop > 0 ? entry->loop : 0;
+			length = intro + 2 * loop; /* intro + 2 loops */
+		}
+	} 
+	else if ( (this->info.playlist_size > 0) && (n < this->info.playlist_size) ) {
+		int remapped = Info_remap_track( &this->info, n );
+		if ( (unsigned) remapped < (unsigned) this->info.track_times_size )
+		{
+			length = (int32_t) get_le32( &this->info.track_times [remapped] );
+		}
+	}
+	
+	if ( length <= 0 )
+		length = 60 * 5 * 1000;
+	
+	return length;
+}
Index: apps/codecs/libnsf/libnsf.make
===================================================================
--- apps/codecs/libnsf/libnsf.make	(revision 0)
+++ apps/codecs/libnsf/libnsf.make	(revision 0)
@@ -0,0 +1,21 @@
+
+# libnsf
+NSFLIB := $(CODECDIR)/libnsf.a
+NSFLIB_SRC := $(call preprocess, $(APPSDIR)/codecs/libnsf/SOURCES)
+NSFLIB_OBJ := $(call c2obj, $(NSFLIB_SRC))
+OTHER_SRC += $(NSFLIB_SRC)
+
+$(NSFLIB): $(NSFLIB_OBJ)
+	$(SILENT)$(shell rm -f $@)
+	$(call PRINTS,AR $(@F))$(AR) rcs $@ $^ >/dev/null
+
+NSFFLAGS = $(filter-out -O%,$(CODECFLAGS)) -fno-strict-aliasing
+ifeq ($(CPU),arm)
+   NSFFLAGS += -O1
+else
+   NSFFLAGS += -O2
+endif
+
+$(CODECDIR)/libnsf/%.o: $(ROOTDIR)/apps/codecs/libnsf/%.c
+	$(SILENT)mkdir -p $(dir $@)
+	$(call PRINTS,CC $(subst $(ROOTDIR)/,,$<))$(CC) $(NSFFLAGS) -c $< -o $@
Index: apps/codecs/libnsf/nes_fme7_apu.c
===================================================================
--- apps/codecs/libnsf/nes_fme7_apu.c	(revision 0)
+++ apps/codecs/libnsf/nes_fme7_apu.c	(revision 0)
@@ -0,0 +1,135 @@
+// Game_Music_Emu 0.5.5. http://www.slack.net/~ant/
+
+#include "nes_fme7_apu.h"
+
+#include <string.h>
+
+/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
+can redistribute it and/or modify it under the terms of the GNU Lesser
+General Public License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version. This
+module is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+details. You should have received a copy of the GNU Lesser General Public
+License along with this module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+void Fme7_init( struct Nes_Fme7_Apu* this )
+{
+	Synth_init( &this->synth );
+	
+	Fme7_output( this, NULL );
+	Fme7_volume( this, 1.0 );
+	Fme7_reset( this );
+}
+
+void Fme7_reset( struct Nes_Fme7_Apu* this )
+{
+	this->last_time = 0;
+	
+	int i;
+	for ( i = 0; i < fme7_osc_count; i++ )
+		this->oscs [i].last_amp = 0;
+	
+	this->latch = 0;
+	memset( this->regs, 0, sizeof this->regs);
+	memset( this->phases, 0, sizeof this->phases );
+	memset( this->delays, 0, sizeof this->delays );
+}
+
+static unsigned char const amp_table [16] ICONST_ATTR =
+{
+	#define ENTRY( n ) (unsigned char) (n * amp_range + 0.5)
+	ENTRY(0.0000), ENTRY(0.0078), ENTRY(0.0110), ENTRY(0.0156),
+	ENTRY(0.0221), ENTRY(0.0312), ENTRY(0.0441), ENTRY(0.0624),
+	ENTRY(0.0883), ENTRY(0.1249), ENTRY(0.1766), ENTRY(0.2498),
+	ENTRY(0.3534), ENTRY(0.4998), ENTRY(0.7070), ENTRY(1.0000)
+	#undef ENTRY
+};
+
+void Fme7_run_until( struct Nes_Fme7_Apu* this, blip_time_t end_time )
+{
+	require( end_time >= this->last_time );
+	
+	int index;
+	for ( index = 0; index < fme7_osc_count; index++ )
+	{
+		int mode = this->regs [7] >> index;
+		int vol_mode = this->regs [010 + index];
+		int volume = amp_table [vol_mode & 0x0F];
+		
+		struct Blip_Buffer* const osc_output = this->oscs [index].output;
+		if ( !osc_output )
+			continue;
+		/* osc_output->set_modified(); */
+		Blip_set_modified( osc_output );
+		
+		// check for unsupported mode
+		#ifndef NDEBUG
+			if ( (mode & 011) <= 001 && vol_mode & 0x1F )
+				debug_printf( "FME7 used unimplemented sound mode: %02X, vol_mode: %02X\n",
+						mode, vol_mode & 0x1F );
+		#endif
+		
+		if ( (mode & 001) | (vol_mode & 0x10) )
+			volume = 0; // noise and envelope aren't supported
+		
+		// period
+		int const period_factor = 16;
+		unsigned period = (this->regs [index * 2 + 1] & 0x0F) * 0x100 * period_factor +
+				this->regs [index * 2] * period_factor;
+		if ( period < 50 ) // around 22 kHz
+		{
+			volume = 0;
+			if ( !period ) // on my AY-3-8910A, period doesn't have extra one added
+				period = period_factor;
+		}
+		
+		// current amplitude
+		int amp = volume;
+		if ( !this->phases [index] )
+			amp = 0;
+		{
+			int delta = amp - this->oscs [index].last_amp;
+			if ( delta )
+			{
+				this->oscs [index].last_amp = amp;
+				Synth_offset( &this->synth, this->last_time, delta, osc_output );
+			}
+		}
+		
+		blip_time_t time = this->last_time + this->delays [index];
+		if ( time < end_time )
+		{
+			int delta = amp * 2 - volume;
+			if ( volume )
+			{
+				do
+				{
+					delta = -delta;
+					Synth_offset_inline( &this->synth, time, delta, osc_output );
+					time += period;
+				}
+				while ( time < end_time );
+				
+				this->oscs [index].last_amp = (delta + volume) >> 1;
+				this->phases [index] = (delta > 0);
+			}
+			else
+			{
+				// maintain phase when silent
+				int count = (end_time - time + period - 1) / period;
+				this->phases [index] ^= count & 1;
+				time += (blargg_long) count * period;
+			}
+		}
+		
+		this->delays [index] = time - end_time;
+	}
+	
+	this->last_time = end_time;
+}
+
Index: apps/codecs/libnsf/nsfe_info.h
===================================================================
--- apps/codecs/libnsf/nsfe_info.h	(revision 0)
+++ apps/codecs/libnsf/nsfe_info.h	(revision 0)
@@ -0,0 +1,39 @@
+// Nintendo NES/Famicom NSFE file info parser
+
+// Game_Music_Emu 0.5.5
+#ifndef NSFE_INFO_H
+#define NSFE_INFO_H
+
+#include "blargg_common.h"
+
+struct Nsf_Emu;
+
+struct auth_chunk_t
+{
+	char game      [256];
+	char author    [256];
+	char copyright [256];
+	char dumper    [256];
+};
+
+// Allows reading info from NSFE file without creating emulator
+struct Nsfe_Info {	
+	struct auth_chunk_t auth;
+	const char* track_names [256];
+	unsigned char playlist [256];
+	int playlist_size;
+	int32_t track_times [256];
+	int track_times_size;
+	int track_count;
+	int actual_track_count_;
+	bool playlist_disabled;
+};
+
+void Info_init( struct Nsfe_Info* this );
+blargg_err_t Info_load( struct Nsfe_Info* this, void *data, long size, struct Nsf_Emu* );
+void Info_disable_playlist( struct Nsfe_Info* this, bool b );
+int Info_remap_track( struct Nsfe_Info* this, int i );
+void Info_unload( struct Nsfe_Info* this );
+
+
+#endif
Index: apps/codecs/libnsf/blargg_common.h
===================================================================
--- apps/codecs/libnsf/blargg_common.h	(revision 0)
+++ apps/codecs/libnsf/blargg_common.h	(revision 0)
@@ -0,0 +1,150 @@
+// Sets up common environment for Shay Green's libraries.
+// To change configuration options, modify blargg_config.h, not this file.
+
+#ifndef BLARGG_COMMON_H
+#define BLARGG_COMMON_H
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <limits.h>
+
+#undef BLARGG_COMMON_H
+// allow blargg_config.h to #include blargg_common.h
+#include "blargg_config.h"
+#ifndef BLARGG_COMMON_H
+#define BLARGG_COMMON_H
+
+#if defined(CPU_ARM) || !defined(ROCKBOX)
+#if (CONFIG_CPU != PP5002) || defined(WIN32)
+    #undef  ICODE_ATTR
+    #define ICODE_ATTR
+
+    #undef  IDATA_ATTR
+    #define IDATA_ATTR
+
+    #undef  ICONST_ATTR
+    #define ICONST_ATTR
+
+    #undef  IBSS_ATTR
+    #define IBSS_ATTR
+#endif
+#endif
+
+// STATIC_CAST(T,expr): Used in place of static_cast<T> (expr)
+#ifndef STATIC_CAST
+	#define STATIC_CAST(T,expr) ((T) (expr))
+#endif
+
+// blargg_err_t (0 on success, otherwise error string)
+#ifndef blargg_err_t
+	typedef const char* blargg_err_t;
+#endif
+
+#define BLARGG_4CHAR( a, b, c, d ) \
+	((a&0xFF)*0x1000000L + (b&0xFF)*0x10000L + (c&0xFF)*0x100L + (d&0xFF))
+
+// BOOST_STATIC_ASSERT( expr ): Generates compile error if expr is 0.
+#ifndef BOOST_STATIC_ASSERT
+	#ifdef _MSC_VER
+		// MSVC6 (_MSC_VER < 1300) fails for use of __LINE__ when /Zl is specified
+		#define BOOST_STATIC_ASSERT( expr ) \
+			void blargg_failed_( int (*arg) [2 / (int) !!(expr) - 1] )
+	#else
+		// Some other compilers fail when declaring same function multiple times in class,
+		// so differentiate them by line
+		#define BOOST_STATIC_ASSERT( expr ) \
+			void blargg_failed_( int (*arg) [2 / !!(expr) - 1] [__LINE__] )
+	#endif
+#endif
+
+// BLARGG_COMPILER_HAS_BOOL: If 0, provides bool support for old compiler. If 1,
+// compiler is assumed to support bool. If undefined, availability is determined.
+#ifndef BLARGG_COMPILER_HAS_BOOL
+	#if defined (__MWERKS__)
+		#if !__option(bool)
+			#define BLARGG_COMPILER_HAS_BOOL 0
+		#endif
+	#elif defined (_MSC_VER)
+		#if _MSC_VER < 1100
+			#define BLARGG_COMPILER_HAS_BOOL 0
+		#endif
+	#elif defined (__GNUC__)
+		// supports bool
+	#elif __cplusplus < 199711
+		#define BLARGG_COMPILER_HAS_BOOL 0
+	#endif
+#endif
+#if defined (BLARGG_COMPILER_HAS_BOOL) && !BLARGG_COMPILER_HAS_BOOL
+	// If you get errors here, modify your blargg_config.h file
+	typedef int bool;
+	static bool true  = 1;
+	static bool false = 0;
+#endif
+
+// blargg_long/blargg_ulong = at least 32 bits, int if it's big enough
+#include <limits.h>
+
+#if INT_MAX >= 0x7FFFFFFF
+	typedef int blargg_long;
+#else
+	typedef long blargg_long;
+#endif
+
+#if UINT_MAX >= 0xFFFFFFFF
+	typedef unsigned blargg_ulong;
+#else
+	typedef unsigned long blargg_ulong;
+#endif
+
+// int8_t etc.
+
+
+// ROCKBOX: If defined, use <codeclib.h> for int_8_t etc
+#if defined (ROCKBOX)
+	#include <codecs/lib/codeclib.h>
+// HAVE_STDINT_H: If defined, use <stdint.h> for int8_t etc.
+#elif defined (HAVE_STDINT_H)
+	#include <stdint.h>
+	#define BOOST
+
+// HAVE_INTTYPES_H: If defined, use <stdint.h> for int8_t etc.
+#elif defined (HAVE_INTTYPES_H)
+	#include <inttypes.h>
+	#define BOOST
+
+#else
+	#if UCHAR_MAX == 0xFF && SCHAR_MAX == 0x7F
+		typedef signed char     int8_t;
+		typedef unsigned char   uint8_t;
+	#else
+		// No suitable 8-bit type available
+		typedef struct see_blargg_common_h int8_t;
+		typedef struct see_blargg_common_h uint8_t;
+	#endif
+		
+	#if USHRT_MAX == 0xFFFF
+		typedef short           int16_t;
+		typedef unsigned short  uint16_t;
+	#else
+		// No suitable 16-bit type available
+		typedef struct see_blargg_common_h int16_t;
+		typedef struct see_blargg_common_h uint16_t;
+	#endif
+		
+	#if ULONG_MAX == 0xFFFFFFFF
+		typedef long            int32_t;
+		typedef unsigned long   uint32_t;
+	#elif UINT_MAX == 0xFFFFFFFF
+		typedef int             int32_t;
+		typedef unsigned int    uint32_t;
+	#else
+		// No suitable 32-bit type available
+		typedef struct see_blargg_common_h int32_t;
+		typedef struct see_blargg_common_h uint32_t;
+	#endif
+#endif
+
+#endif
+#endif
Index: apps/codecs/libnsf/GME.H
===================================================================
--- apps/codecs/libnsf/GME.H	(revision 0)
+++ apps/codecs/libnsf/GME.H	(revision 0)
@@ -0,0 +1,18 @@
+/* Game music emulator library C interface (also usable from C++) */
+
+/* Game_Music_Emu 0.5.2 */
+#ifndef GME_H
+#define GME_H
+
+#ifdef __cplusplus
+	extern "C" {
+#endif
+
+/* Error string returned by library functions, or NULL if no error (success) */
+typedef const char* gme_err_t;
+
+#ifdef __cplusplus
+	}
+#endif
+
+#endif
Index: apps/codecs/libnsf/nes_fme7_apu.h
===================================================================
--- apps/codecs/libnsf/nes_fme7_apu.h	(revision 0)
+++ apps/codecs/libnsf/nes_fme7_apu.h	(revision 0)
@@ -0,0 +1,90 @@
+// Sunsoft FME-7 sound emulator
+
+// Game_Music_Emu 0.5.5
+#ifndef NES_FME7_APU_H
+#define NES_FME7_APU_H
+
+#include "blargg_common.h"
+#include "blip_buffer.h"
+
+enum { fme7_reg_count = 14 };
+
+// Mask and addresses of registers
+enum { fme7_addr_mask = 0xE000 };
+enum { fme7_data_addr = 0xE000 };
+enum { fme7_latch_addr = 0xC000 };
+enum { fme7_osc_count = 3 };
+
+enum { amp_range = 192 }; // can be any value; this gives best error/quality tradeoff
+
+struct osc_t {
+	struct Blip_Buffer* output;
+	int last_amp;
+};
+
+// static unsigned char const amp_table [16];
+
+struct Nes_Fme7_Apu {
+	// fme7 apu state
+	uint8_t regs [fme7_reg_count];
+	uint8_t phases [3]; // 0 or 1
+	uint8_t latch;
+	uint16_t delays [3]; // a, b, c
+	
+	struct osc_t oscs [fme7_osc_count];
+	blip_time_t last_time;
+	
+	struct Blip_Synth synth;
+};
+
+// See Nes_Apu.h for reference
+void Fme7_init( struct Nes_Fme7_Apu* this );
+void Fme7_reset( struct Nes_Fme7_Apu* this );
+	
+static inline void Fme7_volume( struct Nes_Fme7_Apu* this, double v )
+{
+	Synth_volume( &this->synth, 0.38 / amp_range * v ); // to do: fine-tune
+}
+
+static inline void Fme7_osc_output( struct Nes_Fme7_Apu* this, int i, struct Blip_Buffer* buf )
+{
+	assert( (unsigned) i < fme7_osc_count );
+	this->oscs [i].output = buf;
+}
+
+static inline void Fme7_output( struct Nes_Fme7_Apu* this, struct Blip_Buffer* buf )
+{
+	int i;
+	for ( i = 0; i < fme7_osc_count; i++ )
+		Fme7_osc_output( this, i, buf );
+}
+
+// (addr & addr_mask) == latch_addr
+static inline void Fme7_write_latch( struct Nes_Fme7_Apu* this, int data ) { this->latch = data; }
+
+// (addr & addr_mask) == data_addr
+void Fme7_run_until( struct Nes_Fme7_Apu* this, blip_time_t end_time ); ICODE_ATTR
+static inline void Fme7_write_data( struct Nes_Fme7_Apu* this, blip_time_t time, int data )
+{
+	if ( (unsigned) this->latch >= fme7_reg_count )
+	{
+		#ifdef debug_printf
+			debug_printf( "FME7 write to %02X (past end of sound registers)\n", (int) latch );
+		#endif
+		return;
+	}
+	
+	Fme7_run_until( this, time );
+	this->regs [this->latch] = data;
+}
+
+static inline void Fme7_end_frame( struct Nes_Fme7_Apu* this, blip_time_t time )
+{
+	if ( time > this->last_time )
+		Fme7_run_until( this, time );
+	
+	assert( this->last_time >= time );
+	this->last_time -= time;
+}
+
+#endif
Index: apps/codecs/libnsf/blip_buffer.c
===================================================================
--- apps/codecs/libnsf/blip_buffer.c	(revision 0)
+++ apps/codecs/libnsf/blip_buffer.c	(revision 0)
@@ -0,0 +1,282 @@
+// Blip_Buffer 0.4.1. http://www.slack.net/~ant/
+
+#include "blip_buffer.h"
+
+#include <assert.h>
+#include <limits.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+
+/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
+can redistribute it and/or modify it under the terms of the GNU Lesser
+General Public License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version. This
+module is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+details. You should have received a copy of the GNU Lesser General Public
+License along with this module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#ifdef BLARGG_ENABLE_OPTIMIZER
+	#include BLARGG_ENABLE_OPTIMIZER
+#endif
+
+int const silent_buf_size = 1; // size used for Silent_Blip_Buffer
+
+void Blip_init( struct Blip_Buffer* this )
+{
+	this->factor_       = LONG_MAX;
+	this->offset_       = 0;
+	this->buffer_size_  = 0;
+	this->sample_rate_  = 0;
+	this->reader_accum_ = 0;
+	this->bass_shift_   = 0;
+	this->clock_rate_   = 0;
+	this->bass_freq_    = 16;
+	this->length_       = 0;
+	
+	// assumptions code makes about implementation-defined features
+	#ifndef NDEBUG
+		// right shift of negative value preserves sign
+		buf_t_ i = -0x7FFFFFFE;
+		assert( (i >> 1) == -0x3FFFFFFF );
+		
+		// casting to short truncates to 16 bits and sign-extends
+		i = 0x18000;
+		assert( (short) i == -0x8000 );
+	#endif
+}
+
+void Blip_stop( struct Blip_Buffer* this )
+{
+	if ( this->buffer_size_ != silent_buf_size )
+		free( this->buffer_ );
+}
+
+void Blip_clear( struct Blip_Buffer* this, int entire_buffer )
+{
+	this->offset_      = 0;
+	this->reader_accum_ = 0;
+	this->modified_    = 0;
+	if ( this->buffer_ )
+	{
+		long count = (entire_buffer ? this->buffer_size_ : Blip_samples_avail( this ));
+		memset( this->buffer_, 0, (count + blip_buffer_extra_) * sizeof (buf_t_) );
+	}
+}
+
+blargg_err_t Blip_set_sample_rate( struct Blip_Buffer* this, long new_rate, int msec )
+{
+	if ( this->buffer_size_ == silent_buf_size )
+	{
+		assert( 0 );
+		return "Internal (tried to resize Silent_Blip_Buffer)";
+	}
+	
+	// start with maximum length that resampled time can represent
+	long new_size = (ULONG_MAX >> BLIP_BUFFER_ACCURACY) - blip_buffer_extra_ - 64;
+	if ( msec != blip_max_length )
+	{
+		long s = (new_rate * (msec + 1) + 999) / 1000;
+		if ( s < new_size )
+			new_size = s;
+		else
+			assert( 0 ); // fails if requested buffer length exceeds limit
+	}
+	
+	if ( new_size > blip_buffer_max )
+		return "Out of memory";
+	
+	this->buffer_size_ = new_size;
+	assert( this->buffer_size_ != silent_buf_size );
+	
+	// update things based on the sample rate
+	this->sample_rate_ = new_rate;
+	this->length_ = new_size * 1000 / new_rate - 1;
+	if ( msec )
+		assert( this->length_ == msec ); // ensure length is same as that passed in
+	if ( this->clock_rate_ )
+		Blip_set_clock_rate( this, this->clock_rate_ );
+	Blip_bass_freq( this, this->bass_freq_ );
+	
+	Blip_clear( this, 1 );
+	
+	return 0; // success
+}
+
+/* Not sure if this affects sound quality */
+#if defined(ROCKBOX)
+  #define floor
+#endif
+
+blip_resampled_time_t Blip_clock_rate_factor( struct Blip_Buffer* this, long rate )
+{
+	double ratio = (double) this->sample_rate_ / rate;
+	blip_long factor = (blip_long) floor( ratio * (1L << BLIP_BUFFER_ACCURACY) + 0.5 );
+	assert( factor > 0 || !this->sample_rate_ ); // fails if clock/output ratio is too large
+	return (blip_resampled_time_t) factor;
+}
+
+void Blip_bass_freq( struct Blip_Buffer* this, int freq )
+{
+	this->bass_freq_ = freq;
+	int shift = 31;
+	if ( freq > 0 )
+	{
+		shift = 13;
+		long f = (freq << 16) / this->sample_rate_;
+		while ( (f >>= 1) && --shift ) { }
+	}
+	this->bass_shift_ = shift;
+}
+
+void Blip_end_frame( struct Blip_Buffer* this, blip_time_t t )
+{
+	this->offset_ += t * this->factor_;
+	assert( Blip_samples_avail( this ) <= (long) this->buffer_size_ ); // time outside buffer length
+}
+
+void Blip_remove_silence( struct Blip_Buffer* this, long count )
+{
+	assert( count <= Blip_samples_avail( this ) ); // tried to remove more samples than available
+	this->offset_ -= (blip_resampled_time_t) count << BLIP_BUFFER_ACCURACY;
+}
+
+long Blip_count_samples( struct Blip_Buffer* this, blip_time_t t )
+{
+	unsigned long last_sample  = Blip_resampled_time( this, t ) >> BLIP_BUFFER_ACCURACY;
+	unsigned long first_sample = this->offset_ >> BLIP_BUFFER_ACCURACY;
+	return (long) (last_sample - first_sample);
+}
+
+blip_time_t Blip_count_clocks( struct Blip_Buffer* this, long count )
+{
+	if ( !this->factor_ )
+	{
+		assert( 0 ); // sample rate and clock rates must be set first
+		return 0;
+	}
+	
+	if ( count > this->buffer_size_ )
+		count = this->buffer_size_;
+	blip_resampled_time_t time = (blip_resampled_time_t) count << BLIP_BUFFER_ACCURACY;
+	return (blip_time_t) ((time - this->offset_ + this->factor_ - 1) / this->factor_);
+}
+
+void Blip_remove_samples( struct Blip_Buffer* this, long count )
+{
+	if ( count )
+	{
+		Blip_remove_silence( this, count );
+		
+		// copy remaining samples to beginning and clear old samples
+		long remain = Blip_samples_avail( this ) + blip_buffer_extra_;
+		memmove( this->buffer_, this->buffer_ + count, remain * sizeof *this->buffer_ );
+		memset( this->buffer_ + remain, 0, count * sizeof *this->buffer_ );
+	}
+}
+
+long Blip_read_samples( struct Blip_Buffer* this, blip_sample_t* BLIP_RESTRICT out, long max_samples, int stereo )
+{
+	long count = Blip_samples_avail( this );
+	if ( count > max_samples )
+		count = max_samples;
+	
+	if ( count )
+	{
+		int const bass = BLIP_READER_BASS( *this );
+		BLIP_READER_BEGIN( reader, *this );
+		
+		if ( !stereo )
+		{
+			blip_long n;
+			for ( n = count; n; --n )
+			{
+				blip_long s = BLIP_READER_READ( reader );
+				if ( (blip_sample_t) s != s )
+					s = 0x7FFF - (s >> 24);
+				*out++ = (blip_sample_t) s;
+				BLIP_READER_NEXT( reader, bass );
+			}
+		}
+		else
+		{
+			blip_long n;
+			for ( n = count; n; --n )
+			{
+				blip_long s = BLIP_READER_READ( reader );
+				if ( (blip_sample_t) s != s )
+					s = 0x7FFF - (s >> 24);
+				*out = (blip_sample_t) s;
+				out += 2;
+				BLIP_READER_NEXT( reader, bass );
+			}
+		}
+		BLIP_READER_END( reader, *this );
+		
+		Blip_remove_samples( this, count );
+	}
+	return count;
+}
+
+void Blip_mix_samples( struct Blip_Buffer* this,  blip_sample_t const* in, long count )
+{
+	if ( this->buffer_size_ == silent_buf_size )
+	{
+		assert( 0 );
+		return;
+	}
+	
+	buf_t_* out = this->buffer_ + (this->offset_ >> BLIP_BUFFER_ACCURACY) + blip_widest_impulse_ / 2;
+	
+	int const sample_shift = blip_sample_bits - 16;
+	int prev = 0;
+	while ( count-- )
+	{
+		blip_long s = (blip_long) *in++ << sample_shift;
+		*out += s - prev;
+		prev = s;
+		++out;
+	}
+	*out -= prev;
+}
+
+void Blip_set_modified( struct Blip_Buffer* this ) 
+{ 
+	this->modified_ = 1; 
+}
+
+int Blip_clear_modified( struct Blip_Buffer* this )
+{ 
+	int b = this->modified_;
+	this->modified_ = 0;
+	return b; 
+}
+
+blip_resampled_time_t Blip_resampled_duration( struct Blip_Buffer* this, int t )
+{
+	return t * this->factor_;
+}
+
+blip_resampled_time_t Blip_resampled_time( struct Blip_Buffer* this, blip_time_t t )
+{
+	return t * this->factor_ + this->offset_;
+}
+
+
+// Blip_Synth
+
+void Synth_init( struct Blip_Synth* this )
+{
+	this->buf = 0;
+	this->last_amp = 0;
+	this->delta_factor = 0;
+}
+
+// Set overall volume of waveform
+void Synth_volume( struct Blip_Synth* this, double v )
+{
+	this->delta_factor = (int) (v * (1L << blip_sample_bits) + 0.5);
+}
Index: apps/codecs/libnsf/blargg_endian.h
===================================================================
--- apps/codecs/libnsf/blargg_endian.h	(revision 0)
+++ apps/codecs/libnsf/blargg_endian.h	(revision 0)
@@ -0,0 +1,147 @@
+// cpu Byte Order Utilities
+
+// Game_Music_Emu 0.5.2
+#ifndef BLARGG_ENDIAN
+#define BLARGG_ENDIAN
+
+#include "blargg_common.h"
+
+// BLARGG_CPU_CISC: Defined if cpu has very few general-purpose registers (< 16)
+#if defined (_M_IX86) || defined (_M_IA64) || defined (__i486__) || \
+		defined (__x86_64__) || defined (__ia64__) || defined (__i386__)
+	#define BLARGG_CPU_X86 1
+	#define BLARGG_CPU_CISC 1
+#endif
+
+#if defined (__powerpc__) || defined (__ppc__) || defined (__POWERPC__) || defined (__powerc)
+	#define BLARGG_CPU_POWERPC 1
+#endif
+
+// BLARGG_BIG_ENDIAN, BLARGG_LITTLE_ENDIAN: Determined automatically, otherwise only
+// one may be #defined to 1. Only needed if something actually depends on byte order.
+#if !defined (BLARGG_BIG_ENDIAN) && !defined (BLARGG_LITTLE_ENDIAN)
+#ifdef __GLIBC__
+	// GCC handles this for us
+	#include <endian.h>
+	#if __BYTE_ORDER == __LITTLE_ENDIAN
+		#define BLARGG_LITTLE_ENDIAN 1
+	#elif __BYTE_ORDER == __BIG_ENDIAN
+		#define BLARGG_BIG_ENDIAN 1
+	#endif
+#else
+
+#if defined (LSB_FIRST) || defined (__LITTLE_ENDIAN__) || defined (BLARGG_CPU_X86) || \
+		(defined (LITTLE_ENDIAN) && LITTLE_ENDIAN+0 != 1234)
+	#define BLARGG_LITTLE_ENDIAN 1
+#endif
+
+#if defined (MSB_FIRST)     || defined (__BIG_ENDIAN__) || defined (WORDS_BIGENDIAN) || \
+	defined (__mips__)      || defined (__sparc__)      ||  defined (BLARGG_CPU_POWERPC) || \
+	(defined (BIG_ENDIAN) && BIG_ENDIAN+0 != 4321)
+	#define BLARGG_BIG_ENDIAN 1
+#else
+	// No endian specified; assume little-endian, since it's most common
+	#define BLARGG_LITTLE_ENDIAN 1
+#endif
+#endif
+#endif
+
+#if defined (BLARGG_LITTLE_ENDIAN) && defined(BLARGG_BIG_ENDIAN)
+	#undef BLARGG_LITTLE_ENDIAN
+	#undef BLARGG_BIG_ENDIAN
+#endif
+
+static inline void blargg_verify_byte_order( void )
+{
+	#ifndef NDEBUG
+		#if BLARGG_BIG_ENDIAN
+			volatile int i = 1;
+			assert( *(volatile char*) &i == 0 );
+		#elif BLARGG_LITTLE_ENDIAN
+			volatile int i = 1;
+			assert( *(volatile char*) &i != 0 );
+		#endif
+	#endif
+}
+
+static inline unsigned get_le16( void const* p ) {
+	return  ((unsigned char const*) p) [1] * 0x100u +
+			((unsigned char const*) p) [0];
+}
+static inline unsigned get_be16( void const* p ) {
+	return  ((unsigned char const*) p) [0] * 0x100u +
+			((unsigned char const*) p) [1];
+}
+static inline blargg_ulong get_le32( void const* p ) {
+	return  ((unsigned char const*) p) [3] * 0x01000000u +
+			((unsigned char const*) p) [2] * 0x00010000u +
+			((unsigned char const*) p) [1] * 0x00000100u +
+			((unsigned char const*) p) [0];
+}
+static inline blargg_ulong get_be32( void const* p ) {
+	return  ((unsigned char const*) p) [0] * 0x01000000u +
+			((unsigned char const*) p) [1] * 0x00010000u +
+			((unsigned char const*) p) [2] * 0x00000100u +
+			((unsigned char const*) p) [3];
+}
+static inline void set_le16( void* p, unsigned n ) {
+	((unsigned char*) p) [1] = (unsigned char) (n >> 8);
+	((unsigned char*) p) [0] = (unsigned char) n;
+}
+static inline void set_be16( void* p, unsigned n ) {
+	((unsigned char*) p) [0] = (unsigned char) (n >> 8);
+	((unsigned char*) p) [1] = (unsigned char) n;
+}
+static inline void set_le32( void* p, blargg_ulong n ) {
+	((unsigned char*) p) [3] = (unsigned char) (n >> 24);
+	((unsigned char*) p) [2] = (unsigned char) (n >> 16);
+	((unsigned char*) p) [1] = (unsigned char) (n >> 8);
+	((unsigned char*) p) [0] = (unsigned char) n;
+}
+static inline void set_be32( void* p, blargg_ulong n ) {
+	((unsigned char*) p) [0] = (unsigned char) (n >> 24);
+	((unsigned char*) p) [1] = (unsigned char) (n >> 16);
+	((unsigned char*) p) [2] = (unsigned char) (n >> 8);
+	((unsigned char*) p) [3] = (unsigned char) n;
+}
+
+#if defined(BLARGG_NONPORTABLE)
+	// Optimized implementation if byte order is known
+	#if defined(BLARGG_LITTLE_ENDIAN)
+		#define GET_LE16( addr )        (*(BOOST::uint16_t*) (addr))
+		#define GET_LE32( addr )        (*(BOOST::uint32_t*) (addr))
+		#define SET_LE16( addr, data )  (void) (*(BOOST::uint16_t*) (addr) = (data))
+		#define SET_LE32( addr, data )  (void) (*(BOOST::uint32_t*) (addr) = (data))
+	#elif defined(BLARGG_BIG_ENDIAN)
+		#define GET_BE16( addr )        (*(BOOST::uint16_t*) (addr))
+		#define GET_BE32( addr )        (*(BOOST::uint32_t*) (addr))
+		#define SET_BE16( addr, data )  (void) (*(BOOST::uint16_t*) (addr) = (data))
+		#define SET_BE32( addr, data )  (void) (*(BOOST::uint32_t*) (addr) = (data))
+	#endif
+	
+	#if defined(BLARGG_CPU_POWERPC) && defined (__MWERKS__)
+		// PowerPC has special byte-reversed instructions
+		// to do: assumes that PowerPC is running in big-endian mode
+		// to do: implement for other compilers which don't support these macros
+		#define GET_LE16( addr )        (__lhbrx( (addr), 0 ))
+		#define GET_LE32( addr )        (__lwbrx( (addr), 0 ))
+		#define SET_LE16( addr, data )  (__sthbrx( (data), (addr), 0 ))
+		#define SET_LE32( addr, data )  (__stwbrx( (data), (addr), 0 ))
+	#endif
+#endif
+
+#ifndef GET_LE16
+	#define GET_LE16( addr )        get_le16( addr )
+	#define GET_LE32( addr )        get_le32( addr )
+	#define SET_LE16( addr, data )  set_le16( addr, data )
+	#define SET_LE32( addr, data )  set_le32( addr, data )
+#endif
+
+#ifndef GET_BE16
+	#define GET_BE16( addr )        get_be16( addr )
+	#define GET_BE32( addr )        get_be32( addr )
+	#define SET_BE16( addr, data )  set_be16( addr, data )
+	#define SET_BE32( addr, data )  set_be32( addr, data )
+#endif
+
+#endif
Index: apps/codecs/libnsf/multi_buffer.c
===================================================================
--- apps/codecs/libnsf/multi_buffer.c	(revision 0)
+++ apps/codecs/libnsf/multi_buffer.c	(revision 0)
@@ -0,0 +1,226 @@
+// Blip_Buffer 0.4.1. http://www.slack.net/~ant/
+
+#include "multi_buffer.h"
+
+/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
+can redistribute it and/or modify it under the terms of the GNU Lesser
+General Public License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version. This
+module is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+details. You should have received a copy of the GNU Lesser General Public
+License along with this module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+#ifdef BLARGG_ENABLE_OPTIMIZER
+	#include BLARGG_ENABLE_OPTIMIZER
+#endif
+
+// Stereo_Buffer
+ 
+void Buffer_init( struct Stereo_Buffer* this )
+{
+	Blip_init( &this->bufs [0] );
+	Blip_init( &this->bufs [1] );
+	Blip_init( &this->bufs [2] );
+			
+	this->chan.center = &this->bufs [0];
+	this->chan.left = &this->bufs [1];
+	this->chan.right = &this->bufs [2];
+	
+	this->length_ = 0;
+	this->sample_rate_ = 0;
+	this->channels_changed_count_ = 1;
+	this->samples_per_frame_ = 2;
+}
+
+blargg_err_t Buffer_set_sample_rate( struct Stereo_Buffer* this, long rate, int msec )
+{
+	int i;
+	for ( i = 0; i < buf_count; i++ )
+		RETURN_ERR( Blip_set_sample_rate( &this->bufs[i], rate, msec ) );
+		
+	this->sample_rate_ = Blip_sample_rate( &this->bufs [0] );
+	this->length_ = Blip_length( &this->bufs [0] );
+	return 0;
+}
+
+void Buffer_clock_rate( struct Stereo_Buffer* this, long rate )
+{
+	int i;
+	for ( i = 0; i < buf_count; i++ )
+		Blip_set_clock_rate( &this->bufs [i], rate );
+}
+
+void Buffer_bass_freq( struct Stereo_Buffer* this, int bass )
+{
+	unsigned i;
+	for ( i = 0; i < buf_count; i++ )
+		Blip_bass_freq( &this->bufs [i], bass );
+}
+
+struct channel_t Buffer_channel( struct Stereo_Buffer* this )
+{
+	return this->chan;
+}
+
+void Buffer_clear( struct Stereo_Buffer* this )
+{
+	this->stereo_added = 0;
+	this->was_stereo   = false;
+	int i;
+	for ( i = 0; i < buf_count; i++ )
+		Blip_clear( &this->bufs [i], 1 );
+}
+
+void Buffer_end_frame( struct Stereo_Buffer* this, blip_time_t clock_count )
+{
+	this->stereo_added = 0;
+	unsigned i;
+	for ( i = 0; i < buf_count; i++ )
+	{
+		this->stereo_added |= Blip_clear_modified( &this->bufs [i] ) << i;
+		Blip_end_frame( &this->bufs [i], clock_count );
+	}
+}
+
+long Buffer_read_samples( struct Stereo_Buffer* this, blip_sample_t* out, long count )
+{
+	require( !(count & 1) ); // count must be even
+	count = (unsigned) count / 2;
+	
+	long avail = Blip_samples_avail( &this->bufs [0] );
+	if ( count > avail )
+		count = avail;
+	if ( count )
+	{
+		int bufs_used = this->stereo_added | this->was_stereo;
+		//dprintf( "%X\n", bufs_used );
+		if ( bufs_used <= 1 )
+		{
+			Buffer_mix_mono( this, out, count );
+			Blip_remove_samples( &this->bufs [0], count );
+			Blip_remove_silence( &this->bufs [1], count );
+			Blip_remove_silence( &this->bufs [2], count );
+		}
+		else if ( bufs_used & 1 )
+		{
+			Buffer_mix_stereo( this, out, count );
+			Blip_remove_samples( &this->bufs [0], count );
+			Blip_remove_samples( &this->bufs [1], count );
+			Blip_remove_samples( &this->bufs [2], count );
+		}
+		else
+		{
+			Buffer_mix_stereo_no_center( this, out, count );
+			Blip_remove_silence( &this->bufs [0], count );
+			Blip_remove_samples( &this->bufs [1], count );
+			Blip_remove_samples( &this->bufs [2], count );
+		}
+		
+		// to do: this might miss opportunities for optimization
+		if ( !Blip_samples_avail( &this->bufs [0] ) )
+		{
+			this->was_stereo   = this->stereo_added;
+			this->stereo_added = 0;
+		}
+	}
+	
+	return count * 2;
+}
+
+unsigned Buffer_channels_changed_count( struct Stereo_Buffer* this )
+{
+	return this->channels_changed_count_;
+}
+
+void Buffer_channels_changed( struct Stereo_Buffer* this )
+{
+	this->channels_changed_count_++;
+}
+
+void Buffer_mix_stereo( struct Stereo_Buffer* this, blip_sample_t* out_, blargg_long count )
+{
+	blip_sample_t* BLIP_RESTRICT out = out_;
+	int const bass = BLIP_READER_BASS( this->bufs [1] );
+	BLIP_READER_BEGIN( left, this->bufs [1] );
+	BLIP_READER_BEGIN( right, this->bufs [2] );
+	BLIP_READER_BEGIN( center, this->bufs [0] );
+	
+	for ( ; count; --count )
+	{
+		int c = BLIP_READER_READ( center );
+		blargg_long l = c + BLIP_READER_READ( left );
+		blargg_long r = c + BLIP_READER_READ( right );
+		if ( (int16_t) l != l )
+			l = 0x7FFF - (l >> 24);
+		
+		BLIP_READER_NEXT( center, bass );
+		if ( (int16_t) r != r )
+			r = 0x7FFF - (r >> 24);
+		
+		BLIP_READER_NEXT( left, bass );
+		BLIP_READER_NEXT( right, bass );
+		
+		out [0] = l;
+		out [1] = r;
+		out += 2;
+	}
+	
+	BLIP_READER_END( center, this->bufs [0] );
+	BLIP_READER_END( right, this->bufs [2] );
+	BLIP_READER_END( left, this->bufs [1] );
+}
+
+void Buffer_mix_stereo_no_center( struct Stereo_Buffer* this, blip_sample_t* out_, blargg_long count )
+{
+	blip_sample_t* BLIP_RESTRICT out = out_;
+	int const bass = BLIP_READER_BASS( this->bufs [1] );
+	BLIP_READER_BEGIN( left, this->bufs [1] );
+	BLIP_READER_BEGIN( right, this->bufs [2] );
+	
+	for ( ; count; --count )
+	{
+		blargg_long l = BLIP_READER_READ( left );
+		if ( (int16_t) l != l )
+			l = 0x7FFF - (l >> 24);
+		
+		blargg_long r = BLIP_READER_READ( right );
+		if ( (int16_t) r != r )
+			r = 0x7FFF - (r >> 24);
+		
+		BLIP_READER_NEXT( left, bass );
+		BLIP_READER_NEXT( right, bass );
+		
+		out [0] = l;
+		out [1] = r;
+		out += 2;
+	}
+	
+	BLIP_READER_END( right, this->bufs [2] );
+	BLIP_READER_END( left, this->bufs [1] );
+}
+
+void Buffer_mix_mono( struct Stereo_Buffer* this, blip_sample_t* out_, blargg_long count )
+{
+	blip_sample_t* BLIP_RESTRICT out = out_;
+	int const bass = BLIP_READER_BASS( this->bufs [0] );
+	BLIP_READER_BEGIN( center, this->bufs [0] );
+	
+	for ( ; count; --count )
+	{
+		blargg_long s = BLIP_READER_READ( center );
+		if ( (int16_t) s != s )
+			s = 0x7FFF - (s >> 24);
+		
+		BLIP_READER_NEXT( center, bass );
+		out [0] = s;
+		out [1] = s;
+		out += 2;
+	}
+	
+	BLIP_READER_END( center, this->bufs [0] );
+}
Index: apps/codecs/libnsf/blargg_source.h
===================================================================
--- apps/codecs/libnsf/blargg_source.h	(revision 0)
+++ apps/codecs/libnsf/blargg_source.h	(revision 0)
@@ -0,0 +1,66 @@
+// Included at the beginning of library source files, after all other #include lines
+#ifndef BLARGG_SOURCE_H
+#define BLARGG_SOURCE_H
+
+// If debugging is enabled, abort program if expr is false. Meant for checking
+// internal state and consistency. A failed assertion indicates a bug in the module.
+// void assert( bool expr );
+#include <assert.h>
+
+// If debugging is enabled and expr is false, abort program. Meant for checking
+// caller-supplied parameters and operations that are outside the control of the
+// module. A failed requirement indicates a bug outside the module.
+// void require( bool expr );
+#undef require
+#define require( expr ) assert( expr )
+
+// Like printf() except output goes to debug log file. Might be defined to do
+// nothing (not even evaluate its arguments).
+// void dprintf( const char* format, ... );
+#if defined(ROCKBOX)
+#define dprintf DEBUGF
+#else
+static inline void blargg_dprintf_( const char* fmt, ... ) { }
+#undef dprintf
+#define dprintf (1) ? (void) 0 : blargg_dprintf_
+#endif
+
+// If enabled, evaluate expr and if false, make debug log entry with source file
+// and line. Meant for finding situations that should be examined further, but that
+// don't indicate a problem. In all cases, execution continues normally.
+#undef check
+#define check( expr ) ((void) 0)
+
+// If expr yields error string, return it from current function, otherwise continue.
+#undef RETURN_ERR
+#define RETURN_ERR( expr ) do {                         \
+		blargg_err_t blargg_return_err_ = (expr);               \
+		if ( blargg_return_err_ ) return blargg_return_err_;    \
+	} while ( 0 )
+
+// If ptr is 0, return out of memory error string.
+#undef CHECK_ALLOC
+#define CHECK_ALLOC( ptr ) do { if ( (ptr) == 0 ) return "Out of memory"; } while ( 0 )
+
+#ifndef max
+	#define max(a,b) (((a) > (b)) ? (a) : (b))
+#endif
+#ifndef min
+	#define min(a,b) (((a) < (b)) ? (a) : (b))
+#endif
+
+// TODO: good idea? bad idea?
+#undef byte
+#define byte byte_
+typedef unsigned char byte;
+
+// deprecated
+#define BLARGG_CHECK_ALLOC CHECK_ALLOC
+#define BLARGG_RETURN_ERR RETURN_ERR
+
+// BLARGG_SOURCE_BEGIN: If defined, #included, allowing redefition of dprintf and check
+#ifdef BLARGG_SOURCE_BEGIN
+	#include BLARGG_SOURCE_BEGIN
+#endif
+
+#endif
Index: apps/codecs/libnsf/blip_buffer.h
===================================================================
--- apps/codecs/libnsf/blip_buffer.h	(revision 0)
+++ apps/codecs/libnsf/blip_buffer.h	(revision 0)
@@ -0,0 +1,268 @@
+// Band-limited sound synthesis buffer
+
+// Blip_Buffer 0.4.1
+#ifndef BLIP_BUFFER_H
+#define BLIP_BUFFER_H
+
+#include <assert.h>
+
+	// internal
+	#include "blargg_common.h"
+	#if INT_MAX >= 0x7FFFFFFF
+		typedef int blip_long;
+		typedef unsigned blip_ulong;
+	#else
+		typedef long blip_long;
+		typedef unsigned long blip_ulong;
+	#endif
+
+// Time unit at source clock rate
+typedef blip_long blip_time_t;
+
+// Number of bits in resample ratio fraction. Higher values give a more accurate ratio
+// but reduce maximum buffer size.
+#ifndef BLIP_BUFFER_ACCURACY
+	#define BLIP_BUFFER_ACCURACY 16
+#endif
+
+// Number bits in phase offset. Fewer than 6 bits (64 phase offsets) results in
+// noticeable broadband noise when synthesizing high frequency square waves.
+// Affects size of Blip_Synth objects since they store the waveform directly.
+#ifndef BLIP_PHASE_BITS
+	#define BLIP_PHASE_BITS 8
+#endif
+
+// Output samples are 16-bit signed, with a range of -32768 to 32767
+typedef short blip_sample_t;
+enum { blip_sample_max = 32767 };
+enum { blip_widest_impulse_ = 16 };
+enum { blip_buffer_extra_ = blip_widest_impulse_ + 2 };
+enum { blip_res = 1 << BLIP_PHASE_BITS };
+enum { blip_max_length = 0 };
+enum { blip_default_length = 250 };
+
+// Maximun buffer size (48Khz, 50 ms)
+enum { blip_buffer_max = 2466 };
+enum { blip_sample_bits = 30 };
+
+typedef blip_time_t buf_t_;
+/* typedef const char* blargg_err_t; */
+typedef blip_ulong blip_resampled_time_t;
+
+struct Blip_Buffer {
+	blip_ulong factor_;
+	blip_resampled_time_t offset_;
+	buf_t_ buffer_ [blip_buffer_max];
+	blip_long buffer_size_;
+	blip_long reader_accum_;
+	int bass_shift_;
+
+	long sample_rate_;
+	long clock_rate_;
+	int bass_freq_;
+	int length_;
+	int modified_;
+};
+
+// not documented yet
+void Blip_set_modified( struct Blip_Buffer* this ); ICODE_ATTR
+int Blip_clear_modified( struct Blip_Buffer* this ); ICODE_ATTR
+void Blip_remove_silence( struct Blip_Buffer* this, long count ); ICODE_ATTR
+blip_resampled_time_t Blip_resampled_duration( struct Blip_Buffer* this, int t ); ICODE_ATTR
+blip_resampled_time_t Blip_resampled_time( struct Blip_Buffer* this, blip_time_t t ); ICODE_ATTR
+blip_resampled_time_t Blip_clock_rate_factor( struct Blip_Buffer* this, long clock_rate ); ICODE_ATTR
+
+// Initializes Blip_Buffer structure
+void Blip_init( struct Blip_Buffer* this );
+
+// Stops (clear) Blip_Buffer structure
+void Blip_stop( struct Blip_Buffer* this );
+
+// Set output sample rate and buffer length in milliseconds (1/1000 sec, defaults
+// to 1/4 second), then clear buffer. Returns NULL on success, otherwise if there
+// isn't enough memory, returns error without affecting current buffer setup.
+blargg_err_t Blip_set_sample_rate( struct Blip_Buffer* this, long samples_per_sec, int msec_length );
+
+// Set number of source time units per second
+static inline void Blip_set_clock_rate( struct Blip_Buffer* this, long cps )
+{
+	this->factor_ = Blip_clock_rate_factor( this, this->clock_rate_ = cps );
+}
+
+// End current time frame of specified duration and make its samples available
+// (along with any still-unread samples) for reading with read_samples(). Begins
+// a new time frame at the end of the current frame.
+void Blip_end_frame( struct Blip_Buffer* this, blip_time_t time ); ICODE_ATTR
+
+// Read at most 'max_samples' out of buffer into 'dest', removing them from from
+// the buffer. Returns number of samples actually read and removed. If stereo is
+// true, increments 'dest' one extra time after writing each sample, to allow
+// easy interleving of two channels into a stereo output buffer.
+long Blip_read_samples( struct Blip_Buffer* this, blip_sample_t* dest, long max_samples, int stereo ); ICODE_ATTR
+
+// Additional optional features
+
+// Current output sample rate
+static inline long Blip_sample_rate( struct Blip_Buffer* this )
+{
+	return this->sample_rate_;
+}
+
+// Length of buffer, in milliseconds
+static inline int  Blip_length( struct Blip_Buffer* this )
+{
+	return this->length_;
+}
+
+// Number of source time units per second
+static inline long Blip_clock_rate( struct Blip_Buffer* this )
+{
+	return this->clock_rate_;
+}
+
+
+// Set frequency high-pass filter frequency, where higher values reduce bass more
+void Blip_bass_freq( struct Blip_Buffer* this, int frequency );
+
+// Number of samples delay from synthesis to samples read out
+static inline int  Blip_output_latency( void )
+{ 
+	return blip_widest_impulse_ / 2;
+}
+
+// Remove all available samples and clear buffer to silence. If 'entire_buffer' is
+// false, just clears out any samples waiting rather than the entire buffer.
+void Blip_clear( struct Blip_Buffer* this, int entire_buffer );
+
+// Number of samples available for reading with read_samples()
+static inline long Blip_samples_avail( struct Blip_Buffer* this )
+{ 
+	return (long) (this->offset_ >> BLIP_BUFFER_ACCURACY);
+}
+
+// Remove 'count' samples from those waiting to be read
+void Blip_remove_samples( struct Blip_Buffer* this, long count ); ICODE_ATTR
+
+// Experimental features
+
+// Count number of clocks needed until 'count' samples will be available.
+// If buffer can't even hold 'count' samples, returns number of clocks until
+// buffer becomes full.
+blip_time_t Blip_count_clocks( struct Blip_Buffer* this, long count ); ICODE_ATTR
+
+// Number of raw samples that can be mixed within frame of specified duration.
+long Blip_count_samples( struct Blip_Buffer* this, blip_time_t duration ); ICODE_ATTR
+
+// Mix 'count' samples from 'buf' into buffer.
+void Blip_mix_samples( struct Blip_Buffer* this, blip_sample_t const* buf, long count ); ICODE_ATTR
+
+// Range specifies the greatest expected change in amplitude. Calculate it
+// by finding the difference between the maximum and minimum expected
+// amplitudes (max - min).
+
+struct Blip_Synth {
+	struct Blip_Buffer* buf;
+	int last_amp;
+	int delta_factor;
+};
+
+// Initializes Blip_Synth structure
+void Synth_init( struct Blip_Synth* this );
+
+// Set overall volume of waveform
+void Synth_volume( struct Blip_Synth* this, double v ); ICODE_ATTR
+
+// Get/set Blip_Buffer used for output
+const struct Blip_Buffer* Synth_output( struct Blip_Synth* this ); ICODE_ATTR
+
+// Low-level interface
+
+	#if defined (__GNUC__) || _MSC_VER >= 1100
+		#define BLIP_RESTRICT __restrict
+	#else
+		#define BLIP_RESTRICT
+	#endif
+
+// Works directly in terms of fractional output samples. Contact author for more info.
+static inline void Synth_offset_resampled( struct Blip_Synth* this, blip_resampled_time_t time,
+	int delta, struct Blip_Buffer* blip_buf )
+{
+	// Fails if time is beyond end of Blip_Buffer, due to a bug in caller code or the
+	// need for a longer buffer as set by set_sample_rate().
+	assert( (blip_long) (time >> BLIP_BUFFER_ACCURACY) < blip_buf->buffer_size_ );
+	delta *= this->delta_factor;
+	blip_long* BLIP_RESTRICT buf = blip_buf->buffer_ + (time >> BLIP_BUFFER_ACCURACY);
+	int phase = (int) (time >> (BLIP_BUFFER_ACCURACY - BLIP_PHASE_BITS) & (blip_res - 1));
+
+	blip_long left = buf [0] + delta;
+
+	// Kind of crappy, but doing shift after multiply results in overflow.
+	// Alternate way of delaying multiply by delta_factor results in worse
+	// sub-sample resolution.
+	blip_long right = (delta >> BLIP_PHASE_BITS) * phase;
+	left  -= right;
+	right += buf [1];
+
+	buf [0] = left;
+	buf [1] = right;
+}
+
+// Update amplitude of waveform at given time. Using this requires a separate
+// Blip_Synth for each waveform.
+static inline void Synth_update( struct Blip_Synth* this, blip_time_t t, int amp )
+{
+	int delta = amp - this->last_amp;
+	this->last_amp = amp;
+	Synth_offset_resampled( this, t * this->buf->factor_ + this->buf->offset_, delta, this->buf );
+}
+
+// Add an amplitude transition of specified delta, optionally into specified buffer
+// rather than the one set with output(). Delta can be positive or negative.
+// The actual change in amplitude is delta * (volume / range)
+static inline void Synth_offset( struct Blip_Synth* this, blip_time_t t, int delta, struct Blip_Buffer* buf )
+{
+	Synth_offset_resampled( this, t * buf->factor_ + buf->offset_, delta, buf );
+}
+/* void Synth_offset( struct Blip_Synth* this, blip_time_t t, int delta ) {
+	Synth_offset( this, t, delta, this->buf ); } */
+
+// Same as offset(), except code is inlined for higher performance
+static inline void Synth_offset_inline( struct Blip_Synth* this, blip_time_t t, int delta, struct Blip_Buffer* buf )
+{
+	Synth_offset_resampled( this, t * buf->factor_ + buf->offset_, delta, buf );
+}
+/* void offset_inline( struct Blip_Synth* this, blip_time_t t, int delta ) const {
+	offset_resampled( t * this->buf->factor_ + this->buf->offset_, delta, this->buf );
+} */
+
+
+// Optimized reading from Blip_Buffer, for use in custom sample output
+
+// Begin reading from buffer. Name should be unique to the current block.
+#define BLIP_READER_BEGIN( name, blip_buffer ) \
+	buf_t_* BLIP_RESTRICT name##_reader_buf = (blip_buffer).buffer_;\
+	blip_long name##_reader_accum = (blip_buffer).reader_accum_
+
+// Get value to pass to BLIP_READER_NEXT()
+#define BLIP_READER_BASS( blip_buffer ) ((blip_buffer).bass_shift_)
+
+// Constant value to use instead of BLIP_READER_BASS(), for slightly more optimal
+// code at the cost of having no bass control
+/* static int blip_reader_default_bass = 9; */
+
+// Current sample
+#define BLIP_READER_READ( name )        (name##_reader_accum >> (blip_sample_bits - 16))
+
+// Current raw sample in full internal resolution
+#define BLIP_READER_READ_RAW( name )    (name##_reader_accum)
+
+// Advance to next sample
+#define BLIP_READER_NEXT( name, bass ) \
+	(void) (name##_reader_accum += *name##_reader_buf++ - (name##_reader_accum >> (bass)))
+
+// End reading samples from buffer. The number of samples read must now be removed
+// using Blip_remove_samples().
+#define BLIP_READER_END( name, blip_buffer ) \
+	(void) ((blip_buffer).reader_accum_ = name##_reader_accum)
+
+#endif
Index: apps/codecs/libnsf/m3u_playlist.c
===================================================================
--- apps/codecs/libnsf/m3u_playlist.c	(revision 0)
+++ apps/codecs/libnsf/m3u_playlist.c	(revision 0)
@@ -0,0 +1,413 @@
+// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
+
+#include "m3u_playlist.h"
+#include "nsf_emu.h"
+
+#include <string.h>
+#if defined (ROCKBOX)
+#include <codecs/lib/codeclib.h>
+#else
+#include <fcntl.h>
+#endif
+
+/* Copyright (C) 2006 Shay Green. this module is free software; you
+can redistribute it and/or modify it under the terms of the GNU Lesser
+General Public License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version. this
+module is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+details. You should have received a copy of the GNU Lesser General Public
+License along with this module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+static char* skip_white( char* in )
+{
+	while ( *in == ' ' || *in == '\t' )
+		in++;
+	return in;
+}
+
+inline unsigned from_dec( unsigned n ) { return n - '0'; }
+
+static char* parse_filename( char* in, struct entry_t* entry )
+{
+	entry->file = in;
+	entry->type = "";
+	char* out = in;
+	while ( 1 )
+	{
+		int c = *in;
+		if ( !c ) break;
+		in++;
+		
+		if ( c == ',' ) // commas in filename
+		{
+			char* p = skip_white( in );
+			if ( *p == '$' || from_dec( *p ) <= 9 )
+			{
+				in = p;
+				break;
+			}
+		}
+		
+		if ( c == ':' && in [0] == ':' && in [1] && in [2] != ',' ) // ::type suffix
+		{
+			entry->type = ++in;
+			while ( (c = *in) != 0 && c != ',' )
+				in++;
+			if ( c == ',' )
+			{
+				*in++ = 0; // terminate type
+				in = skip_white( in );
+			}
+			break;
+		}
+		
+		if ( c == '\\' ) // \ prefix for special characters
+		{
+			c = *in;
+			if ( !c ) break;
+			in++;
+		}
+		*out++ = (char) c;
+	}
+	*out = 0; // terminate string
+	return in;
+}
+
+static char* next_field( char* in, int* result )
+{
+	while ( 1 )
+	{
+		in = skip_white( in );
+		
+		if ( !*in )
+			break;
+		
+		if ( *in == ',' )
+		{
+			in++;
+			break;
+		}
+		
+		*result = 1;
+		in++;
+	}
+	return skip_white( in );
+}
+
+static char* parse_int_( char* in, int* out )
+{
+	int n = 0;
+	while ( 1 )
+	{
+		unsigned d = from_dec( *in );
+		if ( d > 9 )
+			break;
+		in++;
+		n = n * 10 + d;
+		*out = n;
+	}
+	return in;
+}
+
+static char* parse_int( char* in, int* out, int* result )
+{
+	return next_field( parse_int_( in, out ), result );
+}
+
+// Returns 16 or greater if not hex
+inline int from_hex_char( int h )
+{
+	h -= 0x30;
+	if ( (unsigned) h > 9 )
+		h = ((h - 0x11) & 0xDF) + 10;
+	return h;
+}
+
+static char* parse_track( char* in, struct entry_t* entry, int* result )
+{
+	if ( *in == '$' )
+	{
+		in++;
+		int n = 0;
+		while ( 1 )
+		{
+			int h = from_hex_char( *in );
+			if ( h > 15 )
+				break;
+			in++;
+			n = n * 16 + h;
+			entry->track = n;
+		}
+	}
+	else
+	{
+		in = parse_int_( in, &entry->track );
+		if ( entry->track >= 0 )
+			entry->decimal_track = 1;
+	}
+	return next_field( in, result );
+}
+
+static char* parse_time_( char* in, int* out )
+{
+	*out = -1;
+	int n = -1;
+	in = parse_int_( in, &n );
+	if ( n >= 0 )
+	{
+		*out = n;
+		while ( *in == ':' )
+		{
+			n = -1;
+			in = parse_int_( in + 1, &n );
+			if ( n >= 0 )
+				*out = *out * 60 + n;
+		}
+		*out *= 1000;
+		if ( *in == '.' )
+		{
+			n = -1;
+			in = parse_int_( in + 1, &n );
+			if ( n >= 0 )
+				*out = *out + n; 
+		}
+	}
+	return in;
+}
+
+static char* parse_time( char* in, int* out, int* result )
+{
+	return next_field( parse_time_( in, out ), result );
+}
+
+static char* parse_name( char* in )
+{
+	char* out = in;
+	while ( 1 )
+	{
+		int c = *in;
+		if ( !c ) break;
+		in++;
+		
+		if ( c == ',' ) // commas in string
+		{
+			char* p = skip_white( in );
+			if ( *p == ',' || *p == '-' || from_dec( *p ) <= 9 )
+			{
+				in = p;
+				break;
+			}
+		}
+		
+		if ( c == '\\' ) // \ prefix for special characters
+		{
+			c = *in;
+			if ( !c ) break;
+			in++;
+		}
+		*out++ = (char) c;
+	}
+	*out = 0; // terminate string
+	return in;
+}
+
+static int parse_line( char* in, struct entry_t* entry )
+{
+	int result = 0;
+	
+	// file
+	entry->file = in;
+	entry->type = "";
+	in = parse_filename( in, entry );
+	
+	// track
+	entry->track = -1;
+	entry->decimal_track = 0;
+	in = parse_track( in, entry, &result );
+	
+	// name
+	entry->name = in;
+	in = parse_name( in );
+	
+	// time
+	entry->length = -1;
+	in = parse_time( in, &entry->length, &result );
+	
+	// loop
+	entry->intro = -1;
+	entry->loop  = -1;
+	if ( *in == '-' )
+	{
+		entry->loop = entry->length;
+		in++;
+	}
+	else
+	{
+		in = parse_time_( in, &entry->loop );
+		if ( entry->loop >= 0 )
+		{
+			entry->intro = 0;
+			if ( *in == '-' ) // trailing '-' means that intro length was specified 
+			{
+				in++;
+				entry->intro = entry->loop;
+				entry->loop  = entry->length - entry->intro;
+			}
+		}
+	}
+	in = next_field( in, &result );
+	
+	// fade
+	entry->fade = -1;
+	in = parse_time( in, &entry->fade, &result );
+	
+	// repeat
+	entry->repeat = -1;
+	in = parse_int( in, &entry->repeat, &result );
+	
+	return result;
+}
+
+static void parse_comment( char* in, struct info_t* info, bool first )
+{
+	in = skip_white( in + 1 );
+	char* field = in;
+	while ( *in && *in != ':' && *in != '@' )
+		in++;
+		
+	/* Support Kaminari playlist format */
+    if ( *in == '@' ) {
+        field = in + 1;
+		
+        while ( *in && *in != ' ' && *in != '\t' )
+            in++;
+		
+        char* text = skip_white( in + 1 );
+		if ( *text )
+		{
+			*in = 0;
+			     if ( !stricmp( "Title"   , field ) ) info->title = text;
+			else if ( !stricmp( "Composer", field ) ) info->composer = text;
+			else if ( !stricmp( "Artist", field ) 
+			       || !stricmp( "Sequencer", field) 
+				   || !stricmp( "Date",      field) 
+				   || !stricmp( "Copyright", field) ) info->engineer = text;
+			else if ( !stricmp( "Ripping" , field ) ) info->ripping  = text;
+			else if ( !stricmp( "Tagging" , field ) ) info->tagging  = text;
+			else
+				text = 0;
+			if ( text )
+				return;
+			*in = ':';
+		}
+		
+		return;
+    }
+	
+	if ( *in == ':' )
+	{
+		char* text = skip_white( in + 1 );
+		if ( *text )
+		{
+			*in = 0;
+			     if ( !strcmp( "Composer", field ) ) info->composer = text;
+			else if ( !strcmp( "Engineer", field ) ) info->engineer = text;
+			else if ( !strcmp( "Ripping" , field ) ) info->ripping  = text;
+			else if ( !strcmp( "Tagging" , field ) ) info->tagging  = text;
+			else
+				text = 0;
+			if ( text )
+				return;
+			*in = ':';
+		}
+	}
+	
+	if ( first )
+		info->title = field;
+}
+
+blargg_err_t parse( struct M3u_Playlist* this )
+{
+	int const CR = 13;
+	int const LF = 10;
+	
+    *((this->data + this->raw_size - 1)) = LF; // terminate input
+	
+	this->first_error = 0;
+	bool first_comment = true;
+	int line  = 0;
+	int count = 0;
+	char* in = this->data;
+	while ( in < (this->data + this->raw_size) )
+	{
+		// find end of line and terminate it
+		line++;
+		char* begin = in;
+		while ( *in != CR && *in != LF )
+		{
+			if ( !*in )
+				return "Not an m3u playlist";
+			in++;
+		}
+		if ( in [0] == CR && in [1] == LF ) // treat CR,LF as a single line
+			*in++ = 0;
+		*in++ = 0;
+		
+		// parse line
+		if ( *begin == '#' )
+		{
+			parse_comment( begin, &this->info, first_comment );
+			first_comment = false;
+		}
+		else if ( *begin )
+		{
+			if ( (int) this->size <= count )
+				this->size = count * 2 + 64;
+			
+			if ( !parse_line( begin, &this->entries [count] ) )
+				count++;
+			else if ( !this->first_error )
+				this->first_error = line;
+			first_comment = false;
+		}
+	}
+	if ( count <= 0 )
+		return "Not an m3u playlist";
+
+	this->size = count;
+	return 0;
+}
+
+blargg_err_t Nsf_load_m3u( struct Nsf_Emu* this, const char* path )
+{
+#ifndef GME_DISABLE_M3U_PLAYLIST
+	#if defined (ROCKBOX)
+		int fd = ci->open( path, O_RDONLY );
+	#else
+		int fd = open( path, O_RDONLY );
+	#endif
+		if ( fd < 0 ) return "Error when loading file";
+
+	#if defined (ROCKBOX)
+		this->m3u.raw_size = ci->read( fd, this->m3u.data, max_size );
+		ci->close( fd );
+	#else
+		this->m3u.raw_size = read( fd, this->m3u.data, max_size );
+		close( fd );
+	#endif
+
+		blargg_err_t err = parse( &this->m3u );
+		if ( err ) 
+			return err;
+
+		if ( this->m3u.size > 0 ) 
+			this->track_count = (byte) this->m3u.size; 
+#endif
+
+	return 0;
+}
Index: apps/codecs/libnsf/rom_data.c
===================================================================
--- apps/codecs/libnsf/rom_data.c	(revision 0)
+++ apps/codecs/libnsf/rom_data.c	(revision 0)
@@ -0,0 +1,77 @@
+// Game_Music_Emu 0.5.2. http://www.slack.net/~ant/
+
+#include "rom_data.h"
+
+/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
+can redistribute it and/or modify it under the terms of the GNU Lesser
+General Public License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version. This
+module is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+details. You should have received a copy of the GNU Lesser General Public
+License along with this module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include <string.h>
+#include "blargg_source.h"
+
+// Rom_Data
+
+blargg_err_t Rom_load( struct Rom_Data* this, void* data, long size,
+		int header_size, void* header_out, int fill )
+{
+	long file_offset = pad_size;
+	
+	this->rom_addr = 0;
+	this->mask     = 0;
+	this->size    = 0;
+	
+	if ( size <= header_size ) // <= because there must be data after header
+		return gme_wrong_file_type;
+	
+	// Read header
+	if ( header_size > 0 ) 
+		memcpy( header_out, data, header_size );
+	
+	this->file_size = size - header_size;
+	this->file_data = (byte*) data + header_size;
+	
+	memset( this->unmapped, fill, rom_size );
+	memcpy( &this->unmapped [file_offset], this->file_data, 
+		this->file_size < pad_size ? this->file_size : pad_size );
+	
+	return 0;
+}
+
+void Rom_set_addr( struct Rom_Data* this, long addr )
+{
+	this->rom_addr = addr - bank_size - pad_extra;
+	
+	long rounded = (addr + this->file_size + bank_size - 1) / bank_size * bank_size;
+	if ( rounded <= 0 )
+	{
+		rounded = 0;
+	}
+	else
+	{
+		int shift = 0;
+		unsigned long max_addr = (unsigned long) (rounded - 1);
+		while ( max_addr >> shift )
+			shift++;
+		this->mask = (1L << shift) - 1;
+	}
+	
+	if ( addr < 0 )
+		addr = 0;
+	this->size = rounded;
+	this->rsize_ = rounded - this->rom_addr + pad_extra;
+
+	if ( 0 )
+	{
+		dprintf( "addr: %X\n", addr );
+		dprintf( "file_size: %d\n", this->file_size );
+		dprintf( "rounded: %d\n", rounded );
+		dprintf( "mask: $%X\n", this->mask );
+	}
+}
Index: apps/codecs/libnsf/nes_fds_apu.c
===================================================================
--- apps/codecs/libnsf/nes_fds_apu.c	(revision 0)
+++ apps/codecs/libnsf/nes_fds_apu.c	(revision 0)
@@ -0,0 +1,291 @@
+// Game_Music_Emu 0.6-pre. http://www.slack.net/~ant/
+
+#include "nes_fds_apu.h"
+
+/* Copyright (C) 2006 Shay Green. This module is free software; you
+can redistribute it and/or modify it under the terms of the GNU Lesser
+General Public License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version. This
+module is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+details. You should have received a copy of the GNU Lesser General Public
+License along with this module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+int const fract_range = 65536;
+
+void Fds_init( struct Nes_Fds_Apu* this )
+{
+	Synth_init( &this->synth );
+		
+	this->lfo_tempo = lfo_base_tempo;
+	Fds_set_output( this, 0, NULL );
+	Fds_volume( this, 1.0 );
+	Fds_reset( this );
+}
+
+void Fds_reset( struct Nes_Fds_Apu* this )
+{
+	memset( this->regs_, 0, sizeof this->regs_ );
+	memset( this->mod_wave, 0, sizeof this->mod_wave );
+	
+	this->last_time     = 0;
+	this->env_delay     = 0;
+	this->sweep_delay   = 0;
+	this->wave_pos      = 0;
+	this->last_amp      = 0;
+	this->wave_fract    = fract_range;
+	this->mod_fract     = fract_range;
+	this->mod_pos       = 0;
+	this->mod_write_pos = 0;
+	
+	static byte const initial_regs [0x0B] ICONST_ATTR = {
+		0x80,       // disable envelope
+		0, 0, 0xC0, // disable wave and lfo
+		0x80,       // disable sweep
+		0, 0, 0x80, // disable modulation
+		0, 0, 0xFF  // LFO period // TODO: use 0xE8 as FDS ROM does?
+	};
+	int i;
+	for ( i = 0; i < (int) sizeof initial_regs; i++ )
+	{
+		// two writes to set both gain and period for envelope registers
+		Fds_write_( this, fds_io_addr + fds_wave_size + i, 0 );
+		Fds_write_( this, fds_io_addr + fds_wave_size + i, initial_regs [i] );
+	}
+}
+
+void Fds_write_( struct Nes_Fds_Apu* this, unsigned addr, int data )
+{
+	unsigned reg = addr - fds_io_addr;
+	if ( reg < fds_io_size )
+	{
+		if ( reg < fds_wave_size )
+		{
+			if ( *regs (this, 0x4089) & 0x80 )
+				this->regs_ [reg] = data & fds_wave_sample_max;
+		}
+		else
+		{
+			this->regs_ [reg] = data;
+			switch ( addr )
+			{
+			case 0x4080:
+				if ( data & 0x80 )
+					this->env_gain = data & 0x3F;
+				else
+					this->env_speed = (data & 0x3F) + 1;
+				break;
+			
+			case 0x4084:
+				if ( data & 0x80 )
+					this->sweep_gain = data & 0x3F;
+				else
+					this->sweep_speed = (data & 0x3F) + 1;
+				break;
+			
+			case 0x4085:
+				this->mod_pos = this->mod_write_pos;
+				*regs (this, 0x4085) = data & 0x7F;
+				break;
+			
+			case 0x4088:
+				if ( *regs (this, 0x4087) & 0x80 )
+				{
+					int pos = this->mod_write_pos;
+					data &= 0x07;
+					this->mod_wave [pos    ] = data;
+					this->mod_wave [pos + 1] = data;
+					this->mod_write_pos = (pos     + 2) & (fds_wave_size - 1);
+					this->mod_pos       = (this->mod_pos + 2) & (fds_wave_size - 1);
+				}
+				break;
+			}
+		}
+	}
+}
+
+void Fds_set_tempo( struct Nes_Fds_Apu* this, double t )
+{
+	this->lfo_tempo = lfo_base_tempo;
+	if ( t != 1.0 )
+	{
+		this->lfo_tempo = (int) ((double) lfo_base_tempo / t + 0.5);
+		if ( this->lfo_tempo <= 0 )
+			this->lfo_tempo = 1;
+	}
+}
+
+void Fds_run_until( struct Nes_Fds_Apu* this, blip_time_t final_end_time )
+{
+	int const wave_freq = (*regs (this, 0x4083) & 0x0F) * 0x100 + *regs (this, 0x4082);
+	struct Blip_Buffer* const output_ = this->output_;
+	if ( wave_freq && output_ && !((*regs (this, 0x4089) | *regs (this, 0x4083)) & 0x80) )
+	{
+		Blip_set_modified( output_ );
+		
+		// master_volume
+		#define MVOL_ENTRY( percent ) (fds_master_vol_max * percent + 50) / 100
+		static unsigned char const master_volumes [4] = {
+			MVOL_ENTRY( 100 ), MVOL_ENTRY( 67 ), MVOL_ENTRY( 50 ), MVOL_ENTRY( 40 )
+		};
+		int const master_volume = master_volumes [*regs (this, 0x4089) & 0x03];
+		
+		// lfo_period
+		blip_time_t lfo_period = *regs (this, 0x408A) * this->lfo_tempo;
+		if ( *regs (this, 0x4083) & 0x40 )
+			lfo_period = 0;
+		
+		// sweep setup
+		blip_time_t sweep_time = this->last_time + this->sweep_delay;
+		blip_time_t const sweep_period = lfo_period * this->sweep_speed;
+		if ( !sweep_period || *regs (this, 0x4084) & 0x80 )
+			sweep_time = final_end_time;
+		
+		// envelope setup
+		blip_time_t env_time = this->last_time + this->env_delay;
+		blip_time_t const env_period = lfo_period * this->env_speed;
+		if ( !env_period || *regs (this, 0x4080) & 0x80 )
+			env_time = final_end_time;
+		
+		// modulation
+		int mod_freq = 0;
+		if ( !(*regs (this, 0x4087) & 0x80) )
+			mod_freq = (*regs (this, 0x4087) & 0x0F) * 0x100 + *regs (this, 0x4086);
+		
+		blip_time_t end_time = this->last_time;
+		do
+		{
+			// sweep
+			if ( sweep_time <= end_time )
+			{
+				sweep_time += sweep_period;
+				int mode = *regs (this, 0x4084) >> 5 & 2;
+				int new_sweep_gain = this->sweep_gain + mode - 1;
+				if ( (unsigned) new_sweep_gain <= (unsigned) 0x80 >> mode )
+					this->sweep_gain = new_sweep_gain;
+				else
+					*regs (this, 0x4084) |= 0x80; // optimization only
+			}
+			
+			// envelope
+			if ( env_time <= end_time )
+			{
+				env_time += env_period;
+				int mode = *regs (this, 0x4080) >> 5 & 2;
+				int new_env_gain = this->env_gain + mode - 1;
+				if ( (unsigned) new_env_gain <= (unsigned) 0x80 >> mode )
+					this->env_gain = new_env_gain;
+				else
+					*regs (this, 0x4080) |= 0x80; // optimization only
+			}
+			
+			// new end_time
+			blip_time_t const start_time = end_time;
+			end_time = final_end_time;
+			if ( end_time > env_time   ) end_time = env_time;
+			if ( end_time > sweep_time ) end_time = sweep_time;
+			
+			// frequency modulation
+			int freq = wave_freq;
+			if ( mod_freq )
+			{
+				// time of next modulation clock
+				blip_time_t mod_time = start_time + (this->mod_fract + mod_freq - 1) / mod_freq;
+				if ( end_time > mod_time )
+					end_time = mod_time;
+				
+				// run modulator up to next clock and save old sweep_bias
+				int sweep_bias = *regs (this, 0x4085);
+				this->mod_fract -= (end_time - start_time) * mod_freq;
+				if ( this->mod_fract <= 0 )
+				{
+					this->mod_fract += fract_range;
+					check( (unsigned) this->mod_fract <= fract_range );
+					
+					static short const mod_table [8] = { 0, +1, +2, +4, 0, -4, -2, -1 };
+					int mod = this->mod_wave [this->mod_pos];
+					this->mod_pos = (this->mod_pos + 1) & (fds_wave_size - 1);
+					int new_sweep_bias = (sweep_bias + mod_table [mod]) & 0x7F;
+					if ( mod == 4 )
+						new_sweep_bias = 0;
+					*regs (this, 0x4085) = new_sweep_bias;
+				}
+				
+				// apply frequency modulation
+				sweep_bias = (sweep_bias ^ 0x40) - 0x40;
+				int factor = sweep_bias * this->sweep_gain;
+				int extra = factor & 0x0F;
+				factor >>= 4;
+				if ( extra )
+				{
+					factor--;
+					if ( sweep_bias >= 0 )
+						factor += 3;
+				}
+				if ( factor > 193 ) factor -= 258;
+				if ( factor < -64 ) factor += 256;
+				freq += (freq * factor) >> 6;
+				if ( freq <= 0 )
+					continue;
+			}
+			
+			// wave
+			int wave_fract = this->wave_fract;
+			blip_time_t delay = (wave_fract + freq - 1) / freq;
+			blip_time_t time = start_time + delay;
+			
+			if ( time <= end_time )
+			{
+				// at least one wave clock within start_time...end_time
+				
+				blip_time_t const min_delay = fract_range / freq;
+				int wave_pos = this->wave_pos;
+				
+				int volume = this->env_gain;
+				if ( volume > fds_vol_max )
+					volume = fds_vol_max;
+				volume *= master_volume;
+				
+				int const min_fract = min_delay * freq;
+				
+				do
+				{
+					// clock wave
+					int amp = this->regs_ [wave_pos] * volume;
+					wave_pos = (wave_pos + 1) & (fds_wave_size - 1);
+					int delta = amp - this->last_amp;
+					if ( delta )
+					{
+						this->last_amp = amp;
+						Synth_offset_inline( &this->synth, time, delta, output_ );
+					}
+					
+					wave_fract += fract_range - delay * freq;
+					check( unsigned (fract_range - wave_fract) < freq );
+					
+					// delay until next clock
+					delay = min_delay;
+					if ( wave_fract > min_fract )
+						delay++;
+					check( delay && delay == (wave_fract + freq - 1) / freq );
+					
+					time += delay;
+				}
+				while ( time <= end_time ); // TODO: using < breaks things, but <= is wrong
+				
+				this->wave_pos = wave_pos;
+			}
+			this->wave_fract = wave_fract - (end_time - (time - delay)) * freq;
+			check( this->wave_fract > 0 );
+		}
+		while ( end_time < final_end_time );
+		
+		this->env_delay   = env_time   - final_end_time; check( env_delay >= 0 );
+		this->sweep_delay = sweep_time - final_end_time; check( sweep_delay >= 0 );
+	}
+	this->last_time = final_end_time;
+}
Index: apps/codecs/libnsf/nes_cpu_io.h
===================================================================
--- apps/codecs/libnsf/nes_cpu_io.h	(revision 0)
+++ apps/codecs/libnsf/nes_cpu_io.h	(revision 0)
@@ -0,0 +1,94 @@
+
+#include "nsf_emu.h"
+
+#ifndef NSF_EMU_APU_ONLY
+	#include "nes_namco_apu.h"
+	#include "nes_fds_apu.h"
+	#include "nes_mmc5_apu.h"
+#endif
+
+#include "blargg_source.h"
+
+int Cpu_read( struct Nsf_Emu* this, nes_addr_t addr )
+{
+	int result = this->cpu.low_mem [addr & 0x7FF];
+	if ( addr & 0xE000 )
+	{
+		result = *Cpu_get_code( &this->cpu, addr );
+		if ( addr < sram_addr ) 
+		{
+			if ( addr == status_addr )
+				result = Apu_read_status( &this->apu, Cpu_time( &this->cpu ) );
+			else 
+			{
+				#ifndef NSF_EMU_APU_ONLY
+					if ( namco_enabled( this ) && addr == namco_data_reg_addr )
+						return Namco_read_data( &this->namco );
+			
+					if ( fds_enabled( this ) && (unsigned) (addr - fds_io_addr) < fds_io_size )
+						return Fds_read( &this->fds, Cpu_time( &this->cpu ), addr );
+			
+					if ( mmc5_enabled( this ) ) {
+						int i = addr - 0x5C00;
+						if ( (unsigned) i < mmc5_exram_size )
+							return this->mmc5.exram [i];
+		
+						int m = addr - 0x5205;
+						if ( (unsigned) m < 2 )
+							return (this->mmc5_mul [0] * this->mmc5_mul [1]) >> (m * 8) & 0xFF;
+					}
+				#endif
+				result = addr >> 8; // simulate open bus
+			}
+		}
+	}
+	
+	/* if ( addr != 0x2002 )
+		debug_printf( "Read unmapped $%.4X\n", (unsigned) addr ); */
+	
+	return result;
+}
+
+void Cpu_write( struct Nsf_Emu* this, nes_addr_t addr, int data )
+{	
+	int offset = addr - sram_addr;
+	if ( (unsigned) offset < sram_size )
+	{
+		this->sram [offset] = data;
+	}
+	else
+	{
+		// after sram because cpu handles most low_ram accesses internally already
+		int temp = addr & (low_ram_size-1); // also handles wrap-around
+		if ( !(addr & 0xE000) )
+		{
+			this->cpu.low_mem [temp] = data;
+		}
+		else
+		{
+			int bank = addr - banks_addr;
+			if ( (unsigned) bank < bank_count )
+			{
+				Write_bank( this, bank, data );
+			}
+			else if ( (unsigned) (addr - start_addr) <= end_addr - start_addr )
+			{
+				Apu_write_register(  &this->apu, Cpu_time( &this->cpu ), addr, data );
+			}
+			else
+			{
+			#ifndef NSF_EMU_APU_ONLY
+				// 0x8000-0xDFFF is writable
+				int i = addr - 0x8000;
+				if ( fds_enabled( this ) && (unsigned) i < fdsram_size )
+					fdsram( this ) [i] = data;
+				else
+			#endif
+				Cpu_write_misc( this, addr, data );
+			}
+		}
+	}
+}
+
+#define CPU_READ( emu, addr, time )         Cpu_read( emu, addr )
+#define CPU_WRITE( emu, addr, data, time )  Cpu_write( emu, addr, data )
Index: apps/codecs/libnsf/blargg_config.h
===================================================================
--- apps/codecs/libnsf/blargg_config.h	(revision 0)
+++ apps/codecs/libnsf/blargg_config.h	(revision 0)
@@ -0,0 +1,66 @@
+// Library configuration. Modify this file as necessary.
+
+#ifndef BLARGG_CONFIG_H
+#define BLARGG_CONFIG_H
+
+// Uncomment to enable platform-specific optimizations
+//#define BLARGG_NONPORTABLE 1
+
+// Uncomment if automatic byte-order determination doesn't work
+#ifdef ROCKBOX_BIG_ENDIAN
+	#define BLARGG_BIG_ENDIAN 1
+#endif
+
+// Uncomment if you get errors in the bool section of blargg_common.h
+#define BLARGG_COMPILER_HAS_BOOL 1
+
+// Uncomment to disable m3u playlist support
+// #define GME_DISABLE_M3U_PLAYLIST 1
+
+// To handle undefined reference to assert
+#define NDEBUG 1
+
+// Uncomment to emulate only nes apu
+// #define NSF_EMU_APU_ONLY 1
+
+// Uncomment to remove vrc7 apu support
+// #define NSF_EMU_NO_VRC7 1
+
+// Use standard config.h if present
+#define HAVE_CONFIG_H 1
+
+#ifdef HAVE_CONFIG_H
+	#include "config.h"
+#endif
+
+#endif
+// Library configuration. Modify this file as necessary.
+
+#ifndef BLARGG_CONFIG_H
+#define BLARGG_CONFIG_H
+
+// Uncomment to enable platform-specific optimizations
+//#define BLARGG_NONPORTABLE 1
+
+// Uncomment if automatic byte-order determination doesn't work
+#ifdef ROCKBOX_BIG_ENDIAN
+	#define BLARGG_BIG_ENDIAN 1
+#endif
+
+// Uncomment if you get errors in the bool section of blargg_common.h
+#define BLARGG_COMPILER_HAS_BOOL 1
+
+// To handle undefined reference to assert
+#define NDEBUG 1
+
+// Uncomment to remove vrc7 apu support
+// #define NSF_EMU_NO_VRC7 1
+
+// Use standard config.h if present
+#define HAVE_CONFIG_H 1
+
+#ifdef HAVE_CONFIG_H
+	#include "config.h"
+#endif
+
+#endif
Index: apps/codecs/libnsf/multi_buffer.h
===================================================================
--- apps/codecs/libnsf/multi_buffer.h	(revision 0)
+++ apps/codecs/libnsf/multi_buffer.h	(revision 0)
@@ -0,0 +1,72 @@
+// Multi-channel sound buffer interface, and basic mono and stereo buffers
+
+// Blip_Buffer 0.4.1
+#ifndef MULTI_BUFFER_H
+#define MULTI_BUFFER_H
+
+#include "blargg_common.h"
+#include "blip_buffer.h"
+
+// Get indexed channel, from 0 to channel count - 1
+struct channel_t {
+	struct Blip_Buffer* center;
+	struct Blip_Buffer* left;
+	struct Blip_Buffer* right;
+};
+
+enum { type_index_mask = 0xFF };
+enum { wave_type = 0x100, noise_type = 0x200, mixed_type = wave_type | noise_type };
+enum { buf_count = 3 };
+	
+struct Stereo_Buffer {
+	struct Blip_Buffer bufs [buf_count];
+	struct channel_t chan;
+	int stereo_added;
+	int was_stereo;
+	
+	unsigned channels_changed_count_;
+	long sample_rate_;
+	int length_;
+	int samples_per_frame_;
+};
+
+// Initializes Stereo_Buffer structure
+void Buffer_init( struct Stereo_Buffer* this );
+
+blargg_err_t Buffer_set_sample_rate( struct Stereo_Buffer* this, long, int msec );
+void Buffer_clock_rate( struct Stereo_Buffer* this, long );
+void Buffer_bass_freq( struct Stereo_Buffer* this, int );
+void Buffer_clear( struct Stereo_Buffer* this );
+struct channel_t Buffer_channel( struct Stereo_Buffer* this );
+void Buffer_end_frame( struct Stereo_Buffer* this, blip_time_t ); ICODE_ATTR
+	
+long Buffer_read_samples( struct Stereo_Buffer* this, blip_sample_t*, long ); ICODE_ATTR
+	
+// Count of changes to channel configuration. Incremented whenever
+// a change is made to any of the Blip_Buffers for any channel.
+unsigned Buffer_channels_changed_count( struct Stereo_Buffer* this ); ICODE_ATTR
+void Buffer_channels_changed( struct Stereo_Buffer* this ); ICODE_ATTR
+	
+void Buffer_mix_stereo_no_center( struct Stereo_Buffer* this, blip_sample_t*, blargg_long ); ICODE_ATTR
+void Buffer_mix_stereo( struct Stereo_Buffer* this, blip_sample_t*, blargg_long ); ICODE_ATTR
+void Buffer_mix_mono( struct Stereo_Buffer* this, blip_sample_t*, blargg_long ); ICODE_ATTR
+
+// Number of samples per output frame (1 = mono, 2 = stereo)
+static inline int Buffer_samples_per_frame( struct Stereo_Buffer* this )
+{
+	return this->samples_per_frame_;
+}
+
+// See Blip_Buffer.h
+static inline long Buffer_sample_rate( struct Stereo_Buffer* this )
+{
+	return this->sample_rate_;
+}
+
+// Length of buffer, in milliseconds
+static inline int Buffer_length( struct Stereo_Buffer* this )
+{
+	return this->length_;
+}
+
+#endif
Index: apps/codecs/libnsf/nes_vrc6_apu.c
===================================================================
--- apps/codecs/libnsf/nes_vrc6_apu.c	(revision 0)
+++ apps/codecs/libnsf/nes_vrc6_apu.c	(revision 0)
@@ -0,0 +1,191 @@
+// Nes_Snd_Emu 0.1.8. http://www.slack.net/~ant/
+
+#include "nes_vrc6_apu.h"
+
+/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
+can redistribute it and/or modify it under the terms of the GNU Lesser
+General Public License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version. This
+module is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+details. You should have received a copy of the GNU Lesser General Public
+License along with this module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+void Vrc6_init( struct Nes_Vrc6_Apu* this )
+{
+	Synth_init( &this->saw_synth );
+	Synth_init( &this->square_synth );
+	
+	Vrc6_output( this, NULL );
+	Vrc6_volume( this, 1.0 );
+	Vrc6_reset( this );
+}
+
+void Vrc6_reset( struct Nes_Vrc6_Apu* this )
+{
+	this->last_time = 0;
+	int i;
+	for ( i = 0; i < vrc6_osc_count; i++ )
+	{
+		struct Vrc6_Osc* osc = &this->oscs [i];
+		int j;
+		for ( j = 0; j < vrc6_reg_count; j++ )
+			osc->regs [j] = 0;
+		osc->delay = 0;
+		osc->last_amp = 0;
+		osc->phase = 1;
+		osc->amp = 0;
+	}
+}
+
+void Vrc6_output( struct Nes_Vrc6_Apu* this, struct Blip_Buffer* buf )
+{
+	int i;
+	for ( i = 0; i < vrc6_osc_count; i++ )
+		Vrc6_osc_output( this, i, buf );
+}
+
+void run_square( struct Nes_Vrc6_Apu* this, struct Vrc6_Osc* osc, blip_time_t end_time );
+void run_saw( struct Nes_Vrc6_Apu* this, blip_time_t end_time );
+void Vrc6_run_until( struct Nes_Vrc6_Apu* this, blip_time_t time )
+{
+	require( time >= this->last_time );
+	run_square( this, &this->oscs [0], time );
+	run_square( this, &this->oscs [1], time );
+	run_saw( this, time );
+	this->last_time = time;
+}
+
+void Vrc6_write_osc( struct Nes_Vrc6_Apu* this, blip_time_t time, int osc_index, int reg, int data )
+{
+	require( (unsigned) osc_index < vrc6_osc_count );
+	require( (unsigned) reg < vrc6_reg_count );
+	
+	Vrc6_run_until( this, time );
+	this->oscs [osc_index].regs [reg] = data;
+}
+
+void Vrc6_end_frame( struct Nes_Vrc6_Apu* this, blip_time_t time )
+{
+	if ( time > this->last_time )
+		Vrc6_run_until( this, time );
+	
+	assert( this->last_time >= time );
+	this->last_time -= time;
+}
+
+void run_square( struct Nes_Vrc6_Apu* this, struct Vrc6_Osc* osc, blip_time_t end_time )
+{
+	struct Blip_Buffer* output = osc->output;
+	if ( !output )
+		return;
+	Blip_set_modified( output );
+	
+	int volume = osc->regs [0] & 15;
+	if ( !(osc->regs [2] & 0x80) )
+		volume = 0;
+	
+	int gate = osc->regs [0] & 0x80;
+	int duty = ((osc->regs [0] >> 4) & 7) + 1;
+	int delta = ((gate || osc->phase < duty) ? volume : 0) - osc->last_amp;
+	blip_time_t time = this->last_time;
+	if ( delta )
+	{
+		osc->last_amp += delta;
+		Synth_offset( &this->square_synth, time, delta, output );
+	}
+	
+	time += osc->delay;
+	osc->delay = 0;
+	int period = Vrc6_osc_period( osc );
+	if ( volume && !gate && period > 4 )
+	{
+		if ( time < end_time )
+		{
+			int phase = osc->phase;
+			
+			do
+			{
+				phase++;
+				if ( phase == 16 )
+				{
+					phase = 0;
+					osc->last_amp = volume;
+					Synth_offset( &this->square_synth, time, volume, output );
+				}
+				if ( phase == duty )
+				{
+					osc->last_amp = 0;
+					Synth_offset( &this->square_synth, time, -volume, output );
+				}
+				time += period;
+			}
+			while ( time < end_time );
+			
+			osc->phase = phase;
+		}
+		osc->delay = time - end_time;
+	}
+}
+
+void run_saw( struct Nes_Vrc6_Apu* this, blip_time_t end_time )
+{
+	struct Vrc6_Osc* osc = &this->oscs [2];
+	struct Blip_Buffer* output = osc->output;
+	if ( !output )
+		return;
+	Blip_set_modified( output );
+	
+	int amp = osc->amp;
+	int amp_step = osc->regs [0] & 0x3F;
+	blip_time_t time = this->last_time;
+	int last_amp = osc->last_amp;
+	if ( !(osc->regs [2] & 0x80) || !(amp_step | amp) )
+	{
+		osc->delay = 0;
+		int delta = (amp >> 3) - last_amp;
+		last_amp = amp >> 3;
+		Synth_offset( &this->saw_synth, time, delta, output );
+	}
+	else
+	{
+		time += osc->delay;
+		if ( time < end_time )
+		{
+			int period = Vrc6_osc_period( osc ) * 2;
+			int phase = osc->phase;
+			
+			do
+			{
+				if ( --phase == 0 )
+				{
+					phase = 7;
+					amp = 0;
+				}
+				
+				int delta = (amp >> 3) - last_amp;
+				if ( delta )
+				{
+					last_amp = amp >> 3;
+					Synth_offset( &this->saw_synth, time, delta, output );
+				}
+				
+				time += period;
+				amp = (amp + amp_step) & 0xFF;
+			}
+			while ( time < end_time );
+			
+			osc->phase = phase;
+			osc->amp = amp;
+		}
+		
+		osc->delay = time - end_time;
+	}
+	
+	osc->last_amp = last_amp;
+}
+
Index: apps/codecs/libnsf/m3u_playlist.h
===================================================================
--- apps/codecs/libnsf/m3u_playlist.h	(revision 0)
+++ apps/codecs/libnsf/m3u_playlist.h	(revision 0)
@@ -0,0 +1,57 @@
+// M3U playlist file parser, with support for subtrack information
+
+// Game_Music_Emu 0.5.2
+#ifndef M3U_PLAYLIST_H
+#define M3U_PLAYLIST_H
+
+#include "blargg_common.h"
+
+enum { max_entries = 255 };
+enum { max_size = 0x1000 };
+
+struct info_t
+{
+	char* title;
+	char* composer;
+	char* engineer;
+	char* ripping;
+	char* tagging;
+};
+
+struct entry_t
+{
+	const char* file; // filename without stupid ::TYPE suffix
+	const char* type; // if filename has ::TYPE suffix, this will be "TYPE". "" if none.
+	const char* name;
+	bool decimal_track; // true if track was specified in hex
+	                    // integers are -1 if not present
+	int track;  // 1-based
+	int length; // milliseconds
+	int intro;
+	int loop;
+	int fade;
+	int repeat; // count
+};
+
+struct M3u_Playlist {
+	int size;	
+	long raw_size;
+	int first_error;
+	
+	struct info_t info;
+	struct entry_t entries [max_entries];
+	char data [max_size];
+};
+
+// Initialize M3u_Playlist structure
+static inline void M3u_clear( struct M3u_Playlist* this )
+{
+	this->first_error = 0;
+	memset( this->entries, 0, sizeof this->entries );
+	memset( this->data, 0, sizeof this->data );
+	memset( &this->info, 0, sizeof this->info );
+	this->raw_size = 0;
+	this->size = 0;
+}
+
+#endif
Index: apps/codecs/libnsf/nes_apu.c
===================================================================
--- apps/codecs/libnsf/nes_apu.c	(revision 0)
+++ apps/codecs/libnsf/nes_apu.c	(revision 0)
@@ -0,0 +1,393 @@
+// Nes_Snd_Emu 0.1.8. http://www.slack.net/~ant/
+
+#include "nes_apu.h"
+
+/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
+can redistribute it and/or modify it under the terms of the GNU Lesser
+General Public License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version. This
+module is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+details. You should have received a copy of the GNU Lesser General Public
+License along with this module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+int const amp_range = 15;
+
+void Apu_init( struct Nes_Apu* this )
+{
+	this->tempo_ = 1.0;
+	this->dmc.apu = this;
+	this->dmc.prg_reader = NULL;
+	this->irq_notifier_ = NULL;
+	
+	Synth_init( &this->square_synth );
+	Synth_init( &this->triangle.synth );
+	Synth_init( &this->noise.synth );
+	Synth_init( &this->dmc.synth );
+	
+	Square_set_synth( &this->square1, &this->square_synth );
+	Square_set_synth( &this->square2, &this->square_synth );
+	
+	this->oscs [0] = &this->square1.osc;
+	this->oscs [1] = &this->square2.osc;
+	this->oscs [2] = &this->triangle.osc;
+	this->oscs [3] = &this->noise.osc;
+	this->oscs [4] = &this->dmc.osc;
+	
+	Apu_output( this, NULL );
+	Apu_volume( this, 1.0 );
+	Apu_reset( this, false, 0 );
+}
+
+static double nonlinear_tnd_gain( void ) { return 0.75; }
+void Apu_enable_nonlinear( struct Nes_Apu* this, double v )
+{
+	this->dmc.nonlinear = true;
+	Synth_volume( &this->square_synth, 1.3 * 0.25751258 / 0.742467605 * 0.25 / amp_range * v );
+	
+	const double tnd = 0.48 / 202 * nonlinear_tnd_gain();
+	Synth_volume( &this->triangle.synth, 3.0 * tnd );
+	Synth_volume( &this->noise.synth, 2.0 * tnd );
+	Synth_volume( &this->dmc.synth, tnd );
+	
+	this->square1 .osc.last_amp = 0;
+	this->square2 .osc.last_amp = 0;
+	this->triangle.osc.last_amp = 0;
+	this->noise   .osc.last_amp = 0;
+	this->dmc     .osc.last_amp = 0;
+}
+
+void Apu_volume( struct Nes_Apu* this, double v )
+{
+	this->dmc.nonlinear = false;
+	Synth_volume( &this->square_synth,  0.1128  / amp_range * v );
+	Synth_volume( &this->triangle.synth,0.12765 / amp_range * v );
+	Synth_volume( &this->noise.synth,   0.0741  / amp_range * v );
+	Synth_volume( &this->dmc.synth,     0.42545 / 127 * v );
+}
+
+void Apu_output( struct Nes_Apu* this, struct Blip_Buffer* buffer )
+{
+	int i;
+	for ( i = 0; i < apu_osc_count; i++ )
+		Apu_osc_output( this, i, buffer );
+}
+
+void Apu_set_tempo( struct Nes_Apu* this, double t )
+{
+	this->tempo_ = t;
+	this->frame_period = (this->dmc.pal_mode ? 8314 : 7458);
+	if ( t != 1.0 )
+		this->frame_period = (int) (this->frame_period / t) & ~1; // must be even
+}
+
+void Apu_reset( struct Nes_Apu* this, bool pal_mode, int initial_dmc_dac )
+{
+	this->dmc.pal_mode = pal_mode;
+	Apu_set_tempo( this, this->tempo_ );
+	
+	Square_reset( &this->square1 );
+	Square_reset( &this->square2 );
+	Triangle_reset( &this->triangle );
+	Noise_reset( &this->noise );
+	Dmc_reset( &this->dmc );
+	
+	this->last_time = 0;
+	this->last_dmc_time = 0;
+	this->osc_enables = 0;
+	this->irq_flag = false;
+	this->earliest_irq_ = apu_no_irq;
+	this->frame_delay = 1;
+	Apu_write_register( this, 0, 0x4017, 0x00 );
+	Apu_write_register( this, 0, 0x4015, 0x00 );
+	
+	addr_t addr;
+	for ( addr = apu_io_addr; addr <= 0x4013; addr++ )
+		Apu_write_register( this, 0, addr, (addr & 3) ? 0x00 : 0x10 );
+	
+	this->dmc.dac = initial_dmc_dac;
+	if ( !this->dmc.nonlinear )
+		this->triangle.osc.last_amp = 15;
+	if ( !this->dmc.nonlinear ) // TODO: remove?
+		this->dmc.osc.last_amp = initial_dmc_dac; // prevent output transition
+}
+
+void Apu_irq_changed( struct Nes_Apu* this )
+{
+	nes_time_t new_irq = this->dmc.next_irq;
+	if ( this->dmc.irq_flag | this->irq_flag ) {
+		new_irq = 0;
+	}
+	else if ( new_irq > this->next_irq ) {
+		new_irq = this->next_irq;
+	}
+	
+	if ( new_irq != this->earliest_irq_ ) {
+		this->earliest_irq_ = new_irq;
+		if ( this->irq_notifier_ )
+			this->irq_notifier_( this->irq_data );
+	}
+}
+
+// frames
+
+void Apu_run_until( struct Nes_Apu* this, nes_time_t end_time )
+{
+	require( end_time >= this->last_dmc_time );
+	if ( end_time > Apu_next_dmc_read_time( this ) )
+	{
+		nes_time_t start = this->last_dmc_time;
+		this->last_dmc_time = end_time;
+		Dmc_run( &this->dmc, start, end_time );
+	}
+}
+
+void run_until_( struct Nes_Apu* this, nes_time_t end_time )
+{
+	require( end_time >= this->last_time );
+	
+	if ( end_time == this->last_time )
+		return;
+	
+	if ( this->last_dmc_time < end_time )
+	{
+		nes_time_t start = this->last_dmc_time;
+		this->last_dmc_time = end_time;
+		Dmc_run( &this->dmc, start, end_time );
+	}
+	
+	while ( true )
+	{
+		// earlier of next frame time or end time
+		nes_time_t time = this->last_time + this->frame_delay;
+		if ( time > end_time )
+			time = end_time;
+		this->frame_delay -= time - this->last_time;
+		
+		// run oscs to present
+		Square_run( &this->square1, this->last_time, time );
+		Square_run( &this->square2, this->last_time, time );
+		Triangle_run( &this->triangle, this->last_time, time );
+		Noise_run( &this->noise, this->last_time, time );
+		this->last_time = time;
+		
+		if ( time == end_time )
+			break; // no more frames to run
+		
+		// take frame-specific actions
+		this->frame_delay = this->frame_period;
+		switch ( this->frame++ )
+		{
+			case 0:
+				if ( !(this->frame_mode & 0xC0) ) {
+		 			this->next_irq = time + this->frame_period * 4 + 2;
+		 			this->irq_flag = true;
+		 		}
+		 		// fall through
+		 	case 2:
+		 		// clock length and sweep on frames 0 and 2
+				Osc_clock_length( &this->square1.osc, 0x20 );
+				Osc_clock_length( &this->square2.osc, 0x20 );
+				Osc_clock_length( &this->noise.osc, 0x20 );
+				Osc_clock_length( &this->triangle.osc, 0x80 ); // different bit for halt flag on triangle
+				
+				Square_clock_sweep( &this->square1, -1 );
+				Square_clock_sweep( &this->square2, 0 );
+				
+				// frame 2 is slightly shorter in mode 1
+				if ( this->dmc.pal_mode && this->frame == 3 )
+					this->frame_delay -= 2;
+		 		break;
+		 	
+			case 1:
+				// frame 1 is slightly shorter in mode 0
+				if ( !this->dmc.pal_mode )
+					this->frame_delay -= 2;
+				break;
+			
+		 	case 3:
+		 		this->frame = 0;
+		 		
+		 		// frame 3 is almost twice as long in mode 1
+		 		if ( this->frame_mode & 0x80 )
+					this->frame_delay += this->frame_period - (this->dmc.pal_mode ? 2 : 6);
+				break;
+		}
+		
+		// clock envelopes and linear counter every frame
+		Triangle_clock_linear_counter( &this->triangle );
+		Square_clock_envelope( &this->square1 );
+		Square_clock_envelope( &this->square2 );
+		Noise_clock_envelope( &this->noise );
+	}
+}
+
+static inline void zero_apu_osc( struct Nes_Osc* osc, struct Blip_Synth* synth, nes_time_t time )
+{
+	struct Blip_Buffer* output = osc->output;
+	int last_amp = osc->last_amp;
+	osc->last_amp = 0;
+	if ( output && last_amp )
+		Synth_offset( synth, time, -osc->last_amp, output );
+}
+
+void Apu_end_frame( struct Nes_Apu* this, nes_time_t end_time )
+{
+	if ( end_time > this->last_time )
+		run_until_( this, end_time );
+	
+	if ( this->dmc.nonlinear )
+	{
+		zero_apu_osc( &this->square1.osc, this->square1.synth, this->last_time );
+		zero_apu_osc( &this->square2.osc, this->square2.synth, this->last_time );
+		zero_apu_osc( &this->triangle.osc, &this->triangle.synth, this->last_time );
+		zero_apu_osc( &this->noise.osc, &this->noise.synth, this->last_time );
+		zero_apu_osc( &this->dmc.osc, &this->dmc.synth, this->last_time );
+	}
+	
+	// make times relative to new frame
+	this->last_time -= end_time;
+	require( this->last_time >= 0 );
+	
+	this->last_dmc_time -= end_time;
+	require( this->last_dmc_time >= 0 );
+	
+	if ( this->next_irq != apu_no_irq ) {
+		this->next_irq -= end_time;
+		check( this->next_irq >= 0 );
+	}
+	if ( this->dmc.next_irq != apu_no_irq ) {
+		this->dmc.next_irq -= end_time;
+		check( this->dmc.next_irq >= 0 );
+	}
+	if ( this->earliest_irq_ != apu_no_irq ) {
+		this->earliest_irq_ -= end_time;
+		if ( this->earliest_irq_ < 0 )
+			this->earliest_irq_ = 0;
+	}
+}
+
+// registers
+
+static const unsigned char length_table [0x20] ICONST_ATTR = {
+	0x0A, 0xFE, 0x14, 0x02, 0x28, 0x04, 0x50, 0x06,
+	0xA0, 0x08, 0x3C, 0x0A, 0x0E, 0x0C, 0x1A, 0x0E, 
+	0x0C, 0x10, 0x18, 0x12, 0x30, 0x14, 0x60, 0x16,
+	0xC0, 0x18, 0x48, 0x1A, 0x10, 0x1C, 0x20, 0x1E
+};
+
+void Apu_write_register( struct Nes_Apu* this, nes_time_t time, addr_t addr, int data )
+{
+	require( addr > 0x20 ); // addr must be actual address (i.e. 0x40xx)
+	require( (unsigned) data <= 0xFF );
+	
+	// Ignore addresses outside range
+	if ( (unsigned) (addr - apu_io_addr) >= apu_io_size )
+		return;
+	
+	run_until_( this, time );
+	
+	if ( addr < 0x4014 )
+	{
+		// Write to channel
+		int osc_index = (addr - apu_io_addr) >> 2;
+		struct Nes_Osc* osc = this->oscs [osc_index];
+		
+		int reg = addr & 3;
+		osc->regs [reg] = data;
+		osc->reg_written [reg] = true;
+		
+		if ( osc_index == 4 )
+		{
+			// handle DMC specially
+			Dmc_write_register( &this->dmc, reg, data );
+		}
+		else if ( reg == 3 )
+		{
+			// load length counter
+			if ( (this->osc_enables >> osc_index) & 1 )
+				osc->length_counter = length_table [(data >> 3) & 0x1F];
+			
+			// reset square phase
+			if ( osc_index == 0 ) this->square1.phase = square_phase_range - 1;
+			else if ( osc_index == 1 )	this->square2.phase = square_phase_range - 1;
+		}
+	}
+	else if ( addr == 0x4015 )
+	{
+		// Channel enables
+		int i;
+		for ( i = apu_osc_count; i--; )
+			if ( !((data >> i) & 1) )
+				this->oscs [i]->length_counter = 0;
+		
+		bool recalc_irq = this->dmc.irq_flag;
+		this->dmc.irq_flag = false;
+		
+		int old_enables = this->osc_enables;
+		this->osc_enables = data;
+		if ( !(data & 0x10) ) {
+			this->dmc.next_irq = apu_no_irq;
+			recalc_irq = true;
+		}
+		else if ( !(old_enables & 0x10) ) {
+			Dmc_start( &this->dmc ); // dmc just enabled
+		}
+		
+		if ( recalc_irq )
+			Apu_irq_changed( this );
+	}
+	else if ( addr == 0x4017 )
+	{
+		// Frame mode
+		this->frame_mode = data;
+		
+		bool irq_enabled = !(data & 0x40);
+		this->irq_flag &= irq_enabled;
+		this->next_irq = apu_no_irq;
+		
+		// mode 1
+		this->frame_delay = (this->frame_delay & 1);
+		this->frame = 0;
+		
+		if ( !(data & 0x80) )
+		{
+			// mode 0
+			this->frame = 1;
+			this->frame_delay += this->frame_period;
+			if ( irq_enabled )
+				this->next_irq = time + this->frame_delay + this->frame_period * 3 + 1;
+		}
+		
+		Apu_irq_changed( this );
+	}
+}
+
+int Apu_read_status( struct Nes_Apu* this, nes_time_t time )
+{
+	run_until_( this, time - 1 );
+	
+	int result = (this->dmc.irq_flag << 7) | (this->irq_flag << 6);
+	
+	int i;
+	for ( i = 0; i < apu_osc_count; i++ )
+		if ( this->oscs [i]->length_counter )
+			result |= 1 << i;
+	
+	run_until_( this, time );
+	
+	if ( this->irq_flag )
+	{
+		result |= 0x40;
+		this->irq_flag = false;
+		Apu_irq_changed( this );
+	}
+	
+	//debug_printf( "%6d/%d Read $4015->$%02X\n", frame_delay, frame, result );
+	
+	return result;
+}
Index: apps/codecs/libnsf/nes_vrc7_apu.c
===================================================================
--- apps/codecs/libnsf/nes_vrc7_apu.c	(revision 0)
+++ apps/codecs/libnsf/nes_vrc7_apu.c	(revision 0)
@@ -0,0 +1,153 @@
+
+#include "nes_vrc7_apu.h"
+#include "blargg_source.h"
+
+int const period = 36; // NES cpu clocks per FM clock
+
+void Vrc7_init( struct Nes_Vrc7_Apu* this )
+{
+	Synth_init( &this->synth );
+	ym2413_init( &this->opll, 3579545, 3579545 / 72, 1 );
+	
+	int i;
+	for ( i = 0; i < vrc7_osc_count; i++ )
+		Vrc7_set_output( this, i, 0 );
+
+	Vrc7_volume( this, 1.0 );
+	Vrc7_reset( this );
+}
+
+void output_changed( struct Nes_Vrc7_Apu* this )
+{
+	this->mono.output = this->oscs [0].output;
+	int i;
+	for ( i = vrc7_osc_count; --i; )
+	{
+		if ( this->mono.output != this->oscs [i].output )
+		{
+			this->mono.output = 0;
+			break;
+		}
+	}
+	
+	if ( this->mono.output )
+	{
+		int i;
+		for ( i = vrc7_osc_count; --i; )
+		{
+			this->mono.last_amp += this->oscs [i].last_amp;
+			this->oscs [i].last_amp = 0;
+		}
+	}
+}
+
+void Vrc7_reset( struct Nes_Vrc7_Apu* this )
+{
+	this->addr      = 0;
+	this->next_time = 0;
+	this->mono.last_amp = 0;
+	
+	int i;
+	for ( i = vrc7_osc_count; --i >= 0; )
+	{
+		struct Vrc7_Osc* osc = &this->oscs [i];
+		osc->last_amp = 0;
+		int j;
+		for ( j = 0; j < 3; ++j )
+			osc->regs [j] = 0;
+	}
+
+	ym2413_reset_chip( &this->opll );
+}
+
+void Vrc7_write_reg( struct Nes_Vrc7_Apu* this, int data )
+{
+	this->addr = data;
+}
+
+void Vrc7_run_until( struct Nes_Vrc7_Apu* this, blip_time_t end_time );
+void Vrc7_write_data( struct Nes_Vrc7_Apu* this, blip_time_t time, int data )
+{
+	int type = (this->addr >> 4) - 1;
+	int chan = this->addr & 15;
+	if ( (unsigned) type < 3 && chan < vrc7_osc_count )
+		this->oscs [chan].regs [type] = data;
+	
+	if ( time > this->next_time )
+		Vrc7_run_until( this, time );
+	ym2413_write( &this->opll, 0, this->addr );
+	ym2413_write( &this->opll, 1, data );
+}
+
+void Vrc7_end_frame( struct Nes_Vrc7_Apu* this, blip_time_t time )
+{
+	if ( time > this->next_time )
+		Vrc7_run_until( this, time );
+	
+	this->next_time -= time;
+	assert( this->next_time >= 0 );
+	
+	int i;
+	for ( i = vrc7_osc_count; --i >= 0; )
+	{
+		struct Blip_Buffer* output = this->oscs [i].output;
+		if ( output )
+			Blip_set_modified( output );
+	}
+}
+
+void Vrc7_run_until( struct Nes_Vrc7_Apu* this, blip_time_t end_time )
+{
+	require( end_time > this->next_time );
+
+	blip_time_t time = this->next_time;
+	YM2413* opll = &this->opll; // cache
+	struct Blip_Buffer* const mono_output = this-> mono.output;
+	if ( mono_output )
+	{
+		// optimal case
+		do
+		{
+			ym2413_advance_lfo( opll );
+			int amp = 0, i;
+			for ( i = 0; i < vrc7_osc_count; i++ )
+				amp += ym2413_calcch( opll, i );
+			ym2413_advance( opll );
+			int delta = amp - this->mono.last_amp;
+			if ( delta )
+			{
+				this->mono.last_amp = amp;
+				Synth_offset_inline( &this->synth, time, delta, mono_output );
+			}
+			time += period;
+		}
+		while ( time < end_time );
+	}
+	else
+	{
+		this->mono.last_amp = 0;
+		do
+		{
+			ym2413_advance_lfo( opll );
+			int i;
+			for ( i = 0; i < vrc7_osc_count; ++i )
+			{
+				struct Vrc7_Osc* osc = &this->oscs [i];
+				if ( osc->output )
+				{
+					int amp = ym2413_calcch( opll, i );
+					int delta = amp - osc->last_amp;
+					if ( delta )
+					{
+						osc->last_amp = amp;
+						Synth_offset( &this->synth, time, delta, osc->output );
+					}
+				}
+			}
+			ym2413_advance( opll );
+			time += period;
+		}
+		while ( time < end_time );
+	}
+	this->next_time = time;
+}
Index: apps/codecs/libnsf/nes_fds_apu.h
===================================================================
--- apps/codecs/libnsf/nes_fds_apu.h	(revision 0)
+++ apps/codecs/libnsf/nes_fds_apu.h	(revision 0)
@@ -0,0 +1,116 @@
+// NES FDS sound chip emulator
+
+// Game_Music_Emu 0.6-pre
+#ifndef NES_FDS_APU_H
+#define NES_FDS_APU_H
+
+#include "blargg_common.h"
+#include "blip_buffer.h"
+
+enum { lfo_base_tempo = 8 };
+enum { fds_osc_count = 1 };
+
+enum { fds_io_addr = 0x4040 };
+enum { fds_io_size = 0x53 };
+
+enum { fds_wave_size       = 0x40 };
+enum { fds_master_vol_max  =   10 };
+enum { fds_vol_max         = 0x20 };
+enum { fds_wave_sample_max = 0x3F };
+
+struct Nes_Fds_Apu {
+	unsigned char regs_ [fds_io_size];// last written value to registers
+	int lfo_tempo; // normally 8; adjusted by set_tempo()   
+	
+	int env_delay;
+	int env_speed;
+	int env_gain;
+	
+	int sweep_delay;
+	int sweep_speed;
+	int sweep_gain;
+	
+	int wave_pos;
+	int last_amp;
+	blip_time_t wave_fract;
+	
+	int mod_fract;
+	int mod_pos;
+	int mod_write_pos;
+	unsigned char mod_wave [fds_wave_size];
+	
+	// synthesis
+	blip_time_t last_time;
+	struct Blip_Buffer* output_;
+	struct Blip_Synth synth;
+};
+
+// init
+void Fds_init( struct Nes_Fds_Apu* this );
+// setup
+void Fds_set_tempo( struct Nes_Fds_Apu* this, double t );
+	
+// emulation
+void Fds_reset( struct Nes_Fds_Apu* this );
+
+static inline void Fds_volume( struct Nes_Fds_Apu* this, double v )
+{
+	Synth_volume( &this->synth, 0.14 / fds_master_vol_max / fds_vol_max / fds_wave_sample_max * v );
+}
+
+static inline void Fds_set_output( struct Nes_Fds_Apu* this, int i, struct Blip_Buffer* b )
+{
+#if defined(ROCKBOX)
+	(void) i;
+#endif
+
+	assert( (unsigned) i < fds_osc_count );
+	this->output_ = b;
+}
+
+void Fds_run_until( struct Nes_Fds_Apu* this, blip_time_t ); ICODE_ATTR
+static inline void Fds_end_frame( struct Nes_Fds_Apu* this, blip_time_t end_time )
+{
+	if ( end_time > this->last_time )
+		Fds_run_until( this, end_time );
+	this->last_time -= end_time;
+	assert( this->last_time >= 0 );
+}
+
+void Fds_write_( struct Nes_Fds_Apu* this, unsigned addr, int data ); ICODE_ATTR
+static inline void Fds_write( struct Nes_Fds_Apu* this, blip_time_t time, unsigned addr, int data )
+{
+	Fds_run_until( this, time );
+	Fds_write_( this, addr, data );
+}
+
+static inline int Fds_read( struct Nes_Fds_Apu* this, blip_time_t time, unsigned addr )
+{
+	Fds_run_until( this, time );
+	
+	int result = 0xFF;
+	switch ( addr )
+	{
+	case 0x4090:
+		result = this->env_gain;
+		break;
+	
+	case 0x4092:
+		result = this->sweep_gain;
+		break;
+	
+	default:
+		{
+			unsigned i = addr - fds_io_addr;
+			if ( i < fds_wave_size )
+				result = this->regs_ [i];
+		}
+	}
+	
+	return result | 0x40;
+}
+
+// allow access to registers by absolute address (i.e. 0x4080)
+static inline unsigned char* regs( struct Nes_Fds_Apu* this, unsigned addr ) { return &this->regs_ [addr - fds_io_addr]; }
+
+#endif
Index: apps/codecs/libnsf/rom_data.h
===================================================================
--- apps/codecs/libnsf/rom_data.h	(revision 0)
+++ apps/codecs/libnsf/rom_data.h	(revision 0)
@@ -0,0 +1,72 @@
+// Common aspects of emulators which use rom data
+
+// Game_Music_Emu 0.5.2
+#ifndef ROM_DATA_H
+#define ROM_DATA_H
+
+#include "blargg_common.h"
+#include "blargg_source.h"
+
+// ROM data handler, used by several Classic_Emu derivitives. Loads file data
+// with padding on both sides, allowing direct use in bank mapping. The main purpose
+// is to allow all file data to be loaded with only one read() call (for efficiency).
+
+extern const char gme_wrong_file_type []; // declared in gme.h
+
+enum { bank_size = 0x1000 };
+enum { pad_extra = 8 };
+enum { pad_size = bank_size + pad_extra };
+enum { rom_size = 2 * pad_size };
+
+struct  Rom_Data {	
+	byte* file_data;
+	long file_size;
+	
+	blargg_long rom_addr;
+	blargg_long mask;
+	blargg_long size; // TODO: eliminate
+	blargg_long rsize_;
+	
+	// Unmapped space
+	byte unmapped [rom_size];
+};
+
+// Load file data, using already-loaded header 'h' if not NULL. Copy header
+// from loaded file data into *out and fill unmapped bytes with 'fill'.
+blargg_err_t Rom_load( struct Rom_Data* this, void* data, long size, int header_size, void* header_out, int fill );
+
+// Set address that file data should start at
+void Rom_set_addr( struct Rom_Data* this, long addr );
+
+// Mask address to nearest power of two greater than size()
+static inline blargg_long mask_addr( blargg_long addr, blargg_long mask )
+{
+	#ifdef check
+		check( addr <= mask );
+	#endif
+	return addr & mask;
+}
+
+// Pointer to page starting at addr. Returns unmapped() if outside data.
+static inline byte* Rom_at_addr( struct Rom_Data* this, blargg_long addr )
+{
+	blargg_ulong offset = mask_addr( addr, this->mask ) - this->rom_addr;
+	if ( offset > (blargg_ulong) (this->rsize_ - pad_size) )
+		offset = 0; // unmapped
+			
+	if ( offset < pad_size	) return &this->unmapped [offset];
+	else return &this->file_data [offset - pad_size];
+}
+
+
+#ifndef GME_APU_HOOK
+	#define GME_APU_HOOK( emu, addr, data ) ((void) 0)
+#endif
+
+#ifndef GME_FRAME_HOOK
+	#define GME_FRAME_HOOK( emu ) ((void) 0)
+#else
+	#define GME_FRAME_HOOK_DEFINED 1
+#endif
+
+#endif
Index: apps/codecs/libnsf/nes_cpu.c
===================================================================
--- apps/codecs/libnsf/nes_cpu.c	(revision 0)
+++ apps/codecs/libnsf/nes_cpu.c	(revision 0)
@@ -0,0 +1,62 @@
+// Game_Music_Emu 0.6-pre. http://www.slack.net/~ant/
+
+#include "nes_cpu.h"
+
+#include "blargg_endian.h"
+
+/* Copyright (C) 2003-2008 Shay Green. This module is free software; you
+can redistribute it and/or modify it under the terms of the GNU Lesser
+General Public License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version. This
+module is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+details. You should have received a copy of the GNU Lesser General Public
+License along with this module; if not, write to the Free Software Foundation,
+Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
+#include "blargg_source.h"
+
+inline void set_code_page( struct Nes_Cpu* this, int i, void const* p )
+{
+	byte const* p2 = STATIC_CAST(byte const*,p) - NES_CPU_OFFSET( i * page_size );
+	this->cpu_state->code_map [i] = p2;
+	this->cpu_state_.code_map [i] = p2;
+}
+
+void Cpu_map_code( struct Nes_Cpu* this, addr_t start, int size, void const* data, int mirror_size )
+{
+	// address range must begin and end on page boundaries
+	require( start % page_size == 0 );
+	require( size  % page_size == 0 );
+	require( start + size <= 0x10000 );
+	require( mirror_size % page_size == 0 );
+	
+	int offset;
+	for ( offset = 0; offset < size; offset += page_size )
+		set_code_page( this, NES_CPU_PAGE( start + offset ),
+				STATIC_CAST(char const*,data) + (offset & ((unsigned) mirror_size - 1)) );
+}
+
+void Cpu_reset( struct Nes_Cpu* this, void const* unmapped_page )
+{
+	check( this->cpu_state == &this->cpu_state_ );
+	this->cpu_state = &this->cpu_state_;
+	
+	this->r.flags = irq_inhibit_mask;
+	this->r.sp = 0xFF;
+	this->r.pc = 0;
+	this->r.a  = 0;
+	this->r.x  = 0;
+	this->r.y  = 0;
+	
+	this->cpu_state_.time = 0;
+	this->cpu_state_.base = 0;
+	this->irq_time = future_time;
+	this->end_time = future_time;
+	
+	set_code_page( this, page_count, unmapped_page );
+	Cpu_map_code( this, 0, 0x10000, unmapped_page, page_size );
+	
+	blargg_verify_byte_order();
+}
Index: apps/codecs/nsf.c
===================================================================
--- apps/codecs/nsf.c	(revision 29484)
+++ apps/codecs/nsf.c	(working copy)
@@ -1,4352 +1,62 @@
-/***************************************************************************
- *             __________               __   ___.
- *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
- *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
- *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
- *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
- *                     \/            \/     \/    \/            \/
- *
- * Copyright (C) 2006 Adam Gashlin (hcs)
- * Copyright (C) 2004 Disch
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ****************************************************************************/
 
-/*
- * This is a perversion of Disch's excellent NotSoFatso.
- */
+/* Ripped off from Game_Music_Emu 0.5.2. http://www.slack.net/~ant/ */
 
-#include "codeclib.h"
-#include "inttypes.h"
-#include "system.h"
+#include <codecs/lib/codeclib.h>
+#include "libnsf/nsf_emu.h" 
 
 CODEC_HEADER
 
-/* arm doesn't benefit from IRAM? */
-#ifdef CPU_ARM
-#undef ICODE_ATTR
-#define ICODE_ATTR
-#undef IDATA_ATTR
-#define IDATA_ATTR
-#else
-#define ICODE_INSTEAD_OF_INLINE
-#endif
-
 /* Maximum number of bytes to process in one iteration */
-#define WAV_CHUNK_SIZE (1024*2)
+#define CHUNK_SIZE (1024*2)
 
-static int16_t samples[WAV_CHUNK_SIZE] IBSS_ATTR;
+static int16_t samples[CHUNK_SIZE] IBSS_ATTR;
+static struct Nsf_Emu nsf_emu IDATA_ATTR CACHEALIGN_ATTR;
 
-#define ZEROMEMORY(addr,size) memset(addr,0,size)
-
-/* simple profiling with USEC_TIMER
-
-#define NSF_PROFILE
-
-*/
-
-#ifdef NSF_PROFILE
-
-#define CREATE_TIMER(name) uint32_t nsf_timer_##name##_start,\
-    nsf_timer_##name##_total
-#define ENTER_TIMER(name) nsf_timer_##name##_start=USEC_TIMER
-#define EXIT_TIMER(name) nsf_timer_##name##_total+=\
-    (USEC_TIMER-nsf_timer_##name##_start)
-#define READ_TIMER(name) (nsf_timer_##name##_total)
-#define RESET_TIMER(name) nsf_timer_##name##_total=0
-
-#define PRINT_TIMER_PCT(bname,tname,nstr) ci->fdprintf(
-    logfd,"%10ld ",READ_TIMER(bname));\
-    ci->fdprintf(logfd,"(%3d%%) " nstr "\t",\
-    ((uint64_t)READ_TIMER(bname))*100/READ_TIMER(tname))
-
-CREATE_TIMER(total);
-CREATE_TIMER(cpu);
-CREATE_TIMER(apu);
-CREATE_TIMER(squares);
-CREATE_TIMER(tnd);
-CREATE_TIMER(tnd_enter);
-CREATE_TIMER(tnd_tri);
-CREATE_TIMER(tnd_noise);
-CREATE_TIMER(tnd_dmc);
-CREATE_TIMER(fds);
-CREATE_TIMER(frame);
-CREATE_TIMER(mix);
-
-void reset_profile_timers(void) {
-    RESET_TIMER(total);
-    RESET_TIMER(cpu);
-    RESET_TIMER(apu);
-    RESET_TIMER(squares);
-    RESET_TIMER(tnd);
-    RESET_TIMER(tnd_enter);
-    RESET_TIMER(tnd_tri);
-    RESET_TIMER(tnd_noise);
-    RESET_TIMER(tnd_dmc);
-    RESET_TIMER(fds);
-    RESET_TIMER(frame);
-    RESET_TIMER(mix);
-}
-
-int logfd=-1;
-
-void print_timers(char * path, int track) {
-    logfd = ci->open("/nsflog.txt",O_WRONLY|O_CREAT|O_APPEND, 0666);
-    ci->fdprintf(logfd,"%s[%d]:\t",path,track);
-    ci->fdprintf(logfd,"%10ld total\t",READ_TIMER(total));
-    PRINT_TIMER_PCT(cpu,total,"CPU");
-    PRINT_TIMER_PCT(apu,total,"APU");
-    ci->fdprintf(logfd,"\n\t");
-    PRINT_TIMER_PCT(squares,apu,"squares");
-    PRINT_TIMER_PCT(frame,apu,"frame");
-    PRINT_TIMER_PCT(mix,apu,"mix");
-    PRINT_TIMER_PCT(fds,apu,"FDS");
-    PRINT_TIMER_PCT(tnd,apu,"tnd");
-    ci->fdprintf(logfd,"\n\t\t");
-    PRINT_TIMER_PCT(tnd_enter,tnd,"enter");
-    PRINT_TIMER_PCT(tnd_tri,tnd,"triangle");
-    PRINT_TIMER_PCT(tnd_noise,tnd,"noise");
-    PRINT_TIMER_PCT(tnd_dmc,tnd,"DMC");
-    ci->fdprintf(logfd,"\n");
-
-    ci->close(logfd);
-    logfd=-1;
-}
-
-#else
-
-#define CREATE_TIMER(name)
-#define ENTER_TIMER(name)
-#define EXIT_TIMER(name)
-#define READ_TIMER(name)
-#define RESET_TIMER(name)
-#define print_timers(path,track)
-#define reset_profile_timers()
-
-#endif
-
-/* proper handling of multibyte values */
-#ifdef ROCKBOX_LITTLE_ENDIAN
-union TWIN
-{
-    uint16_t                        W;
-    struct{ uint8_t l; uint8_t h; } B;
-};
-
-union QUAD
-{
-    uint32_t                                    D;
-    struct{ uint8_t l; uint8_t h; uint16_t w; } B;
-};
-#else
-
-union TWIN
-{
-    uint16_t                        W;
-    struct{ uint8_t h; uint8_t l; } B;
-};
-
-union QUAD
-{
-    uint32_t                                    D;
-    struct{uint16_t w; uint8_t h; uint8_t l; }  B;
-};
-
-#endif
-
-#define NTSC_FREQUENCY           1789772.727273f
-#define PAL_FREQUENCY            1652097.692308f
-#define NTSC_NMIRATE                  60.098814f
-#define PAL_NMIRATE                   50.006982f
-
-#define NES_FREQUENCY           21477270
-#define NTSC_FRAME_COUNTER_FREQ (NTSC_FREQUENCY / (NES_FREQUENCY / 89490.0f))
-#define PAL_FRAME_COUNTER_FREQ  (PAL_FREQUENCY / (NES_FREQUENCY / 89490.0f))
-
-/****************** tables */
-static const int32_t ModulationTable[8] ICONST_ATTR = {0,1,2,4,0,-4,-2,-1};
-const uint16_t  DMC_FREQ_TABLE[2][0x10] = {
-    /* NTSC */
-    {0x1AC,0x17C,0x154,0x140,0x11E,0x0FE,0x0E2,0x0D6,0x0BE,0x0A0,0x08E,0x080,
-    0x06A,0x054,0x048,0x036},
-    /* PAL */
-    {0x18C,0x160,0x13A,0x128,0x108,0x0EA,0x0D0,0x0C6,0x0B0,0x094,0x082,0x076,
-    0x062,0x04E,0x042,0x032}
-};
-
-const uint8_t DUTY_CYCLE_TABLE[4] = {2,4,8,12};
-
-const uint8_t LENGTH_COUNTER_TABLE[0x20] = {
-    0x0A,0xFE,0x14,0x02,0x28,0x04,0x50,0x06,0xA0,0x08,0x3C,0x0A,0x0E,0x0C,0x1A,
-    0x0E,0x0C,0x10,0x18,0x12,0x30,0x14,0x60,0x16,0xC0,0x18,0x48,0x1A,0x10,0x1C,
-    0x20,0x1E
-};
-
-const uint16_t NOISE_FREQ_TABLE[0x10] = {
-    0x004,0x008,0x010,0x020,0x040,0x060,0x080,0x0A0,0x0CA,0x0FE,0x17C,0x1FC,
-    0x2FA,0x3F8,0x7F2,0xFE4
-};
-
-/****************** NSF loading ******************/
-
-/* file format structs (both are little endian) */
-
-struct NESM_HEADER
-{
-    uint32_t        nHeader;
-    uint8_t         nHeaderExtra;
-    uint8_t         nVersion;
-    uint8_t         nTrackCount;
-    uint8_t         nInitialTrack;
-    uint16_t        nLoadAddress;
-    uint16_t        nInitAddress;
-    uint16_t        nPlayAddress;
-    uint8_t         szGameTitle[32];
-    uint8_t         szArtist[32];
-    uint8_t         szCopyright[32];
-    uint16_t        nSpeedNTSC;
-    uint8_t         nBankSwitch[8];
-    uint16_t        nSpeedPAL;
-    uint8_t         nNTSC_PAL;
-    uint8_t         nExtraChip;
-    uint8_t         nExpansion[4];
-};
-
-struct NSFE_INFOCHUNK
-{
-    uint16_t        nLoadAddress;
-    uint16_t        nInitAddress;
-    uint16_t        nPlayAddress;
-    uint8_t         nIsPal;
-    uint8_t         nExt;
-    uint8_t         nTrackCount;
-    uint8_t         nStartingTrack;
-};
-
-int32_t     LoadFile(uint8_t *,size_t);
-
-int32_t     LoadFile_NESM(uint8_t *,size_t);
-int32_t     LoadFile_NSFE(uint8_t *,size_t);
-
-/* NSF file info */
-
-/* basic NSF info */
-int32_t     bIsExtended=0;      /* 0 = NSF, 1 = NSFE */
-uint8_t     nIsPal=0;           /* 0 = NTSC, 1 = PAL,
-                                 2,3 = mixed NTSC/PAL (interpretted as NTSC) */
-int32_t     nfileLoadAddress=0; /* The address to which the NSF code is
-                                   loaded */
-int32_t     nfileInitAddress=0; /* The address of the Init routine
-                                   (called at track change) */
-int32_t     nfilePlayAddress=0; /* The address of the Play routine
-                                   (called several times a second) */
-uint8_t     nChipExtensions=0;  /* Bitwise representation of the external chips
-                                   used by this NSF.  */
-    
-/* old NESM speed stuff (blarg) */
-int32_t     nNTSC_PlaySpeed=0;
-int32_t     nPAL_PlaySpeed=0;
-
-/* track info */
-/* The number of tracks in the NSF (1 = 1 track, 5 = 5 tracks, etc) */
-int32_t     nTrackCount=0;
-/* The initial track (ZERO BASED:  0 = 1st track, 4 = 5th track, etc) */
-int32_t     nInitialTrack=0;
-
-/* nsf data */
-uint8_t*    pDataBuffer=0;      /* the buffer containing NSF code. */
-int32_t     nDataBufferSize=0;  /* the size of the above buffer. */
-
-/* playlist */
-uint8_t     nPlaylist[256];     /* Each entry is the zero based index of the
-                                   song to play */
-int32_t     nPlaylistSize=0;    /* the number of tracks in the playlist */
-
-/* track time / fade */
-int32_t     nTrackTime[256];    /* track times -1 if no track times specified */
-int32_t     nTrackFade[256];    /* track fade times -1 if none are specified */
-
-/* string info */
-uint8_t     szGameTitle[0x101];
-uint8_t     szArtist[0x101];
-uint8_t     szCopyright[0x101];
-uint8_t     szRipper[0x101];
-
-/* bankswitching info */
-uint8_t     nBankswitch[8]={0}; /* The initial bankswitching registers needed
-                                 * for some NSFs.  If the NSF does not use
-                                 * bankswitching, these values will all be zero
-                                 */
-
-int32_t     LoadFile(uint8_t * inbuffer, size_t size)
-{
-    if(!inbuffer) return -1;
-
-    int32_t ret = -1;
-
-    if(!memcmp(inbuffer,"NESM",4)) ret = LoadFile_NESM(inbuffer,size);
-    if(!memcmp(inbuffer,"NSFE",4)) ret = LoadFile_NSFE(inbuffer,size);
-
-    /*
-     * Snake's revenge puts '00' for the initial track,
-     * which (after subtracting 1) makes it 256 or -1 (bad!)
-     * This prevents that crap
-     */
-    if(nInitialTrack >= nTrackCount)
-        nInitialTrack = 0;
-    if(nInitialTrack < 0)
-        nInitialTrack = 0;
-
-    /* if there's no tracks... this is a crap NSF */
-    if(nTrackCount < 1)
-    {
-        return -1;
-    }
-
-    return ret;
-}
-
-int32_t LoadFile_NESM(uint8_t* inbuffer, size_t size)
-{
-    uint8_t ignoreversion=1;
-    uint8_t needdata=1;
-
-    /* read the info */
-    struct NESM_HEADER hdr;
-    
-    memcpy(&hdr,inbuffer,sizeof(hdr));
-
-    /* confirm the header */
-    if(memcmp("NESM",&(hdr.nHeader),4))         return -1;
-    if(hdr.nHeaderExtra != 0x1A)                return -1;
-    /* stupid NSFs claim to be above version 1  >_> */
-    if((!ignoreversion) && (hdr.nVersion != 1)) return -1;
-
-    /* 
-     * NESM is generally easier to work with (but limited!)
-     * just move the data over from NESM_HEADER over to our member data
-     */
-
-    bIsExtended =               0;
-    nIsPal =                    hdr.nNTSC_PAL & 0x03;
-    nPAL_PlaySpeed =            letoh16(hdr.nSpeedPAL);
-    nNTSC_PlaySpeed =           letoh16(hdr.nSpeedNTSC);
-    nfileLoadAddress =          letoh16(hdr.nLoadAddress);
-    nfileInitAddress =          letoh16(hdr.nInitAddress);
-    nfilePlayAddress =          letoh16(hdr.nPlayAddress);
-    nChipExtensions =           hdr.nExtraChip;
-
-
-    nTrackCount =               hdr.nTrackCount;
-    nInitialTrack =             hdr.nInitialTrack - 1;
-
-    memcpy(nBankswitch,hdr.nBankSwitch,8);
-
-    memcpy(szGameTitle,hdr.szGameTitle,32);
-    memcpy(szArtist   ,hdr.szArtist   ,32);
-    memcpy(szCopyright,hdr.szCopyright,32);
-
-    /* read the NSF data */
-    if(needdata)
-    {
-        pDataBuffer=inbuffer+0x80;
-        nDataBufferSize=size-0x80;
-    }
-
-    /* if we got this far... it was a successful read */
-    return 0;
-}
-
-int32_t LoadFile_NSFE(uint8_t* inbuffer, size_t size)
-{
-    /* the vars we'll be using */
-    uint32_t nChunkType;
-    int32_t  nChunkSize;
-    int32_t  nChunkUsed;
-    int32_t i;
-    uint8_t *  nDataPos = 0;
-    uint8_t bInfoFound = 0;
-    uint8_t bEndFound = 0;
-    uint8_t bBankFound = 0;
-    nPlaylistSize=-1;
-
-    struct NSFE_INFOCHUNK   info;
-    ZEROMEMORY(&info,sizeof(struct NSFE_INFOCHUNK));
-    ZEROMEMORY(nBankswitch,8);
-    info.nTrackCount = 1;       /* default values */
-    
-    if (size < 8) return -1;    /* must have at least NSFE,NEND */
-
-    /* confirm the header! */
-    memcpy(&nChunkType,inbuffer,4);
-    inbuffer+=4;
-    if(memcmp(&nChunkType,"NSFE",4))            return -1;
-
-    for (i=0;i<256;i++) {
-        nTrackTime[i]=-1;
-        nTrackFade[i]=-1;
-    }
-
-    /* begin reading chunks */
-    while(!bEndFound)
-    {
-        memcpy(&nChunkSize,inbuffer,4);
-        nChunkSize=letoh32(nChunkSize);
-        inbuffer+=4;
-        memcpy(&nChunkType,inbuffer,4);
-        inbuffer+=4;
-
-        if(!memcmp(&nChunkType,"INFO",4)) {
-            /* only one info chunk permitted */
-            if(bInfoFound)                      return -1;
-            if(nChunkSize < 8)                  return -1;  /* minimum size */
-
-            bInfoFound = 1;
-            nChunkUsed = MIN((int32_t)sizeof(struct NSFE_INFOCHUNK),
-                             nChunkSize);
-
-            memcpy(&info,inbuffer,nChunkUsed);
-            inbuffer+=nChunkSize;
-
-            bIsExtended =           1;
-            nIsPal =                info.nIsPal & 3;
-            nfileLoadAddress =      letoh16(info.nLoadAddress);
-            nfileInitAddress =      letoh16(info.nInitAddress);
-            nfilePlayAddress =      letoh16(info.nPlayAddress);
-            nChipExtensions =       info.nExt;
-            nTrackCount =           info.nTrackCount;
-            nInitialTrack =         info.nStartingTrack;
-
-            nPAL_PlaySpeed =        (uint16_t)(1000000 / PAL_NMIRATE);
-            nNTSC_PlaySpeed =       (uint16_t)(1000000 / NTSC_NMIRATE);
-        } else if (!memcmp(&nChunkType,"DATA",4)) {
-            if(!bInfoFound)                     return -1;
-            if(nDataPos)                        return -1;
-            if(nChunkSize < 1)                  return -1;
-
-            nDataBufferSize = nChunkSize;
-            nDataPos = inbuffer;
-
-            inbuffer+=nChunkSize;
-        } else if (!memcmp(&nChunkType,"NEND",4)) {
-            bEndFound = 1;
-        } else if (!memcmp(&nChunkType,"time",4)) {
-            if(!bInfoFound)                     return -1;
-            for (nChunkUsed=0; nChunkUsed < MIN(nChunkSize / 4,nTrackCount);
-                 nChunkUsed++,inbuffer+=4) {
-                nTrackTime[nChunkUsed]=
-                    ((uint32_t)inbuffer[0])|
-                    ((uint32_t)inbuffer[1]<<8)|
-                    ((uint32_t)inbuffer[2]<<16)|
-                    ((uint32_t)inbuffer[3]<<24);
-            }
-
-            inbuffer+=nChunkSize-(nChunkUsed*4);
-
-            /* negative signals to use default time */
-            for(; nChunkUsed < nTrackCount; nChunkUsed++)
-                nTrackTime[nChunkUsed] = -1;
-        } else if (!memcmp(&nChunkType,"fade",4)) {
-            if(!bInfoFound)                     return -1;
-            for (nChunkUsed=0; nChunkUsed < MIN(nChunkSize / 4,nTrackCount);
-                 nChunkUsed++,inbuffer+=4) {
-                nTrackFade[nChunkUsed]=
-                    ((uint32_t)inbuffer[0])|
-                    ((uint32_t)inbuffer[1]<<8)|
-                    ((uint32_t)inbuffer[2]<<16)|
-                    ((uint32_t)inbuffer[3]<<24);
-            }
-
-            inbuffer+=nChunkSize-(nChunkUsed*4);
-
-            /* negative signals to use default time */
-            for(; nChunkUsed < nTrackCount; nChunkUsed++)
-                nTrackFade[nChunkUsed] = -1;
-        } else if (!memcmp(&nChunkType,"BANK",4)) {
-            if(bBankFound)                      return -1;
-
-            bBankFound = 1;
-            nChunkUsed = MIN(8,nChunkSize);
-            memcpy(nBankswitch,inbuffer,nChunkUsed);
-
-            inbuffer+=nChunkSize;
-        } else if (!memcmp(&nChunkType,"plst",4)) {
-
-            nPlaylistSize = nChunkSize;
-            if(nPlaylistSize >= 1) {
-
-                memcpy(nPlaylist,inbuffer,nChunkSize);
-                inbuffer+=nChunkSize;
-            }
-        } else if (!memcmp(&nChunkType,"auth",4)) {
-            uint8_t*        ptr;
-
-            ptr = inbuffer;
-
-            uint8_t*    ar[4] = {szGameTitle,szArtist,szCopyright,szRipper};
-            int32_t     i;
-            for(i = 0; (ptr-inbuffer)<nChunkSize && i < 4; i++)
-            {
-                nChunkUsed = strlen(ptr) + 1;
-                memcpy(ar[i],ptr,nChunkUsed);
-                ptr += nChunkUsed;
-            }
-            inbuffer+=nChunkSize;
-        } else if (!memcmp(&nChunkType,"tlbl",4)) {
-            /* we unfortunately can't use these anyway */
-            inbuffer+=nChunkSize;
-        } else { /* unknown chunk */
-            nChunkType = letoh32(nChunkType)>>24;  /* check the first byte */
-            /* chunk is vital... don't continue */
-            if((nChunkType >= 'A') && (nChunkType <= 'Z'))
-                return -1;
-            /* otherwise, just skip it */
-            inbuffer+=nChunkSize;
-        }       /* end if series */
-    }           /* end while */
-
-    /*
-     * if we exited the while loop without a 'return', we must have hit an NEND
-     *  chunk if this is the case, the file was layed out as it was expected.
-     *  now.. make sure we found both an info chunk, AND a data chunk... since
-     *  these are minimum requirements for a valid NSFE file
-     */
-
-    if(!bInfoFound)         return -1;
-    if(!nDataPos)           return -1;
-
-    /* if both those chunks existed, this file is valid.
-       Load the data if it's needed */
-
-    pDataBuffer=nDataPos;
-
-    /* return success! */
-    return 0;
-}
-
-
-/****************** Audio Device Structures ******************/
-
-struct FDSWave
-{
-    /*  Envelope Unit   */
-    uint8_t     bEnvelopeEnable;
-    uint8_t     nEnvelopeSpeed;
-
-    /*  Volume Envelope */
-    uint8_t     nVolEnv_Mode;
-    uint8_t     nVolEnv_Decay;
-    uint8_t     nVolEnv_Gain;
-    int32_t     nVolEnv_Timer;
-    int32_t     nVolEnv_Count;
-    uint8_t     nVolume;
-    uint8_t     bVolEnv_On;
-
-    /*  Sweep Envenlope */
-    uint8_t     nSweep_Mode;
-    uint8_t     nSweep_Decay;
-    int32_t     nSweep_Timer;
-    int32_t     nSweep_Count;
-    uint8_t     nSweep_Gain;
-    uint8_t     bSweepEnv_On;
-
-    /*  Effector / LFO / Modulation Unit    */
-    int32_t     nSweepBias;
-    uint8_t     bLFO_Enabled;
-    union TWIN  nLFO_Freq;
-    /*float       fLFO_Timer;*/
-    /*float       fLFO_Count;*/
-    int32_t    nLFO_Timer; /* -17.14*/
-    int32_t    nLFO_Count; /* -17.14*/
-    uint8_t     nLFO_Addr;
-    uint8_t     nLFO_Table[0x40];
-    uint8_t     bLFO_On;
-
-    /*  Main Output     */
-    uint8_t     nMainVolume;
-    uint8_t     bEnabled;
-    union TWIN  nFreq;
-    /*float       fFreqCount;*/
-    int32_t    nFreqCount; /* -17.14 */
-    uint8_t     nMainAddr;
-    uint8_t     nWaveTable[0x40];
-    uint8_t     bWaveWrite;
-    uint8_t     bMain_On;
-
-    /*  Output and Downsampling */
-    int32_t     nMixL;
-    
-    /*  Pop Reducer             */
-    uint8_t     bPopReducer;
-    uint8_t     nPopOutput;
-    int32_t     nPopCount;
-    
-};
-int16_t     FDS_nOutputTable_L[4][0x21][0x40];
-
-struct FME07Wave
-{
-    /* Frequency Control */
-    union TWIN  nFreqTimer;
-    int32_t     nFreqCount;
-
-    /* Channel Disabling */
-    uint8_t     bChannelEnabled;
-
-    /* Volume */
-    uint8_t     nVolume;
-
-    /* Duty Cycle */
-    uint8_t     nDutyCount;
-
-    /* Output and Downsampling */
-    int32_t     nMixL;
-};
-
-int16_t     FME07_nOutputTable_L[0x10] IDATA_ATTR;
-
-struct N106Wave
-{
-    /*  All Channel Stuff */
-
-    uint8_t     nActiveChannels;
-    uint8_t     bAutoIncrement;
-    uint8_t     nCurrentAddress;
-    uint8_t     nRAM[0x100];      /* internal memory for registers/wave data */
-    int32_t     nFrequencyLookupTable[8]; /* lookup tbl for freq conversions */
-
-    /*
-     *  Individual channel stuff
-     */
-    /*  Wavelength / Frequency */
-    union QUAD  nFreqReg[8];
-    int32_t     nFreqTimer[8];
-    int32_t     nFreqCount[8];
-
-    /*  Wave data length / remaining */
-    uint8_t     nWaveSize[8];
-    uint8_t     nWaveRemaining[8];
-
-    /*  Wave data position */
-    uint8_t     nWavePosStart[8];
-    uint8_t     nWavePos[8];
-    uint8_t     nOutput[8];
-
-    /*  Volume */
-    uint8_t     nVolume[8];
-
-    /*  Pop Reducer */
-    uint8_t     nPreVolume[8];
-    uint8_t     nPopCheck[8];
-
-    /* Mixing */
-    int32_t     nMixL[8];
-};
-
-int16_t     N106_nOutputTable_L[0x10][0x10];
-
-struct VRC6PulseWave
-{
-
-    /* Frequency Control */
-    union TWIN  nFreqTimer;
-    int32_t     nFreqCount;
-
-    /* Flags */
-    uint8_t     bChannelEnabled;
-    uint8_t     bDigitized;
-
-    /* Volume */
-    uint8_t     nVolume;
-
-    /* Duty Cycle */
-    uint8_t     nDutyCycle;
-    uint8_t     nDutyCount;
-
-    /* Output and Downsampling */
-    int32_t     nMixL;
-    
-};
-
-int16_t     VRC6Pulse_nOutputTable_L[0x10] IDATA_ATTR;
-
-struct VRC6SawWave
-{
-
-    /* Frequency Control */
-    union TWIN  nFreqTimer;
-    int32_t     nFreqCount;
-
-    /* Flags */
-    uint8_t     bChannelEnabled;
-
-    /* Phase Accumulator */
-    uint8_t     nAccumRate;
-    uint8_t     nAccum;
-    uint8_t     nAccumStep;
-
-    /* Output and Downsampling */
-    int32_t     nMixL;
-    
-};
-
-int16_t     VRC6Saw_nOutputTable_L[0x20] IDATA_ATTR;
-
-struct Wave_Squares
-{
-
-    /* Programmable Timer */
-    union TWIN  nFreqTimer[2];
-    int32_t     nFreqCount[2];
-
-    /* Length Counter */
-    uint8_t     nLengthCount[2];
-    uint8_t     bLengthEnabled[2];
-    uint8_t     bChannelEnabled[2];
-
-    /* Volume / Decay */
-    uint8_t     nVolume[2];
-    uint8_t     nDecayVolume[2];
-    uint8_t     bDecayEnable[2];
-    uint8_t     bDecayLoop[2];
-    uint8_t     nDecayTimer[2];
-    uint8_t     nDecayCount[2];
-
-    /* Sweep Unit */
-    uint8_t     bSweepEnable[2];
-    uint8_t     bSweepMode[2];
-    uint8_t     bSweepForceSilence[2];
-    uint8_t     nSweepTimer[2];
-    uint8_t     nSweepCount[2];
-    uint8_t     nSweepShift[2];
-
-    /* Duty Cycle */
-    uint8_t     nDutyCount[2];
-    uint8_t     nDutyCycle[2];
-
-    /* Output and Downsampling */
-    int32_t         nMixL;
-};
-
-int16_t     Squares_nOutputTable_L[0x10][0x10] IDATA_ATTR;
-
-struct Wave_TND
-{
-
-    /*
-     * Triangle
-     */
-
-    /* Programmable Timer */
-    union TWIN  nTriFreqTimer;
-    int32_t     nTriFreqCount;
-
-    /* Length Counter */
-    uint8_t     nTriLengthCount;
-    uint8_t     bTriLengthEnabled;
-    uint8_t     bTriChannelEnabled;
-
-    /* Linear Counter */
-    uint8_t     nTriLinearCount;
-    uint8_t     nTriLinearLoad;
-    uint8_t     bTriLinearHalt;
-    uint8_t     bTriLinearControl;
-
-    /* Tri-Step Generator / Output */
-    uint8_t     nTriStep;
-    uint8_t     nTriOutput;
-
-    /*
-     * Noise
-     */
-
-    /* Programmable Timer */
-    uint16_t    nNoiseFreqTimer;
-    int32_t     nNoiseFreqCount;
-
-    /* Length Counter */
-    uint8_t     nNoiseLengthCount;
-    uint8_t     bNoiseLengthEnabled;
-    uint8_t     bNoiseChannelEnabled;
-
-    /* Volume / Decay */
-    uint8_t     nNoiseVolume;
-    uint8_t     nNoiseDecayVolume;
-    uint8_t     bNoiseDecayEnable;
-    uint8_t     bNoiseDecayLoop;
-    uint8_t     nNoiseDecayTimer;
-    uint8_t     nNoiseDecayCount;
-
-    /* Random Number Generator */
-    uint16_t    nNoiseRandomShift;
-    uint8_t     bNoiseRandomMode;           /* 1 = 32k, 6 = 93-bit */
-    uint8_t     bNoiseRandomOut;
-
-    /*
-     * DMC
-     */
-
-    /* Play Mode */
-    uint8_t     bDMCLoop;
-    uint8_t     bDMCIRQEnabled;
-    uint8_t     bDMCIRQPending;
-
-    /* Address / DMA */
-    uint8_t     nDMCDMABank_Load;
-    uint16_t    nDMCDMAAddr_Load;
-    uint8_t     nDMCDMABank;
-    uint16_t    nDMCDMAAddr;
-    uint8_t*    pDMCDMAPtr[8];
-
-    /* Length / Input */
-    uint16_t    nDMCLength;
-    uint16_t    nDMCBytesRemaining;
-    uint8_t     nDMCDelta;
-    uint8_t     nDMCDeltaBit;
-    uint8_t     bDMCDeltaSilent;
-    uint8_t     nDMCSampleBuffer;
-    uint8_t     bDMCSampleBufferEmpty;
-
-    /* Frequency */
-    uint16_t    nDMCFreqTimer;
-    int32_t     nDMCFreqCount;
-
-    /* Output */
-    uint8_t     bDMCActive;
-    uint8_t     nDMCOutput;
-
-    int32_t     nMixL;
-};
-
-/* channels */
-struct Wave_Squares mWave_Squares IDATA_ATTR; /* Square channels 1 and 2 */
-struct Wave_TND     mWave_TND IDATA_ATTR;     /* Triangle/Noise/DMC channels */
-struct VRC6PulseWave    mWave_VRC6Pulse[2] IDATA_ATTR;
-struct VRC6SawWave  mWave_VRC6Saw IDATA_ATTR;
-struct N106Wave     mWave_N106 IDATA_ATTR;
-struct FDSWave      mWave_FDS IDATA_ATTR;
-struct FME07Wave    mWave_FME07[3] IDATA_ATTR; /* FME-07's 3 pulse channels */
-
-
-/****************** MMC5 ******************/
-/* will include MMC5 sound channels some day,
-   currently only multiply is supported */
-
-/****************** N106 (Disch loves this chip) ******************/
-
-#ifdef ICODE_INSTEAD_OF_INLINE
-void Wave_N106_DoTicks(const int32_t ticks) ICODE_ATTR;
-void Wave_N106_DoTicks(const int32_t ticks)
-#else
-inline void Wave_N106_DoTicks(const int32_t ticks);
-inline void Wave_N106_DoTicks(const int32_t ticks)
-#endif
-{
-    register int32_t i;
-
-    for(i = (7 - mWave_N106.nActiveChannels); i < 8; i++)
-    {
-        if(!mWave_N106.nFreqReg[i].D)
-        {
-            /* written frequency of zero will cause divide by zero error
-               makes me wonder if the formula was supposed to be Reg+1 */
-            mWave_N106.nVolume[i] = mWave_N106.nPreVolume[i];
-            continue;
-        }
-
-        {
-            mWave_N106.nMixL[i] = 
-                N106_nOutputTable_L[mWave_N106.nVolume[i]]
-                                      [mWave_N106.nOutput[i]];
-            
-            if(mWave_N106.nFreqTimer[i] < 0)
-                mWave_N106.nFreqTimer[i] =
-                 (mWave_N106.nFrequencyLookupTable[mWave_N106.nActiveChannels] /
-                 mWave_N106.nFreqReg[i].D);
-            if(mWave_N106.nFreqCount[i] > mWave_N106.nFreqTimer[i])
-                mWave_N106.nFreqCount[i] = mWave_N106.nFreqTimer[i];
-
-            mWave_N106.nFreqCount[i] -= ticks << 8;
-            while(mWave_N106.nFreqCount[i] <= 0)
-            {
-                mWave_N106.nFreqCount[i] += mWave_N106.nFreqTimer[i];
-                if(mWave_N106.nWaveRemaining[i])
-                {
-                    mWave_N106.nWaveRemaining[i]--;
-                    mWave_N106.nWavePos[i]++;
-                }
-                if(!mWave_N106.nWaveRemaining[i])
-                {
-                    mWave_N106.nWaveRemaining[i] = mWave_N106.nWaveSize[i];
-                    mWave_N106.nWavePos[i] = mWave_N106.nWavePosStart[i];
-                    if(mWave_N106.nVolume[i] != mWave_N106.nPreVolume[i])
-                    {
-                        if(++mWave_N106.nPopCheck[i] >= 2)
-                        {
-                            mWave_N106.nPopCheck[i] = 0;
-                            mWave_N106.nVolume[i] = mWave_N106.nPreVolume[i];
-                        }
-                    }
-                }
-
-                mWave_N106.nOutput[i] =
-                    mWave_N106.nRAM[mWave_N106.nWavePos[i]];
-                    
-                if(!mWave_N106.nOutput[i])
-                {
-                    mWave_N106.nPopCheck[i] = 0;
-                    mWave_N106.nVolume[i] = mWave_N106.nPreVolume[i];
-                }
-                    
-            }
-        }
-    }
-}
-/****************** VRC6 ******************/
-
-#ifdef ICODE_INSTEAD_OF_INLINE
-void Wave_VRC6_DoTicks(const int32_t ticks) ICODE_ATTR;
-void Wave_VRC6_DoTicks(const int32_t ticks)
-#else
-inline void Wave_VRC6_DoTicks(const int32_t ticks);
-inline void Wave_VRC6_DoTicks(const int32_t ticks)
-#endif
-{
-    register int32_t i;
-
-    for(i = 0; i < 2; i++) {
-
-        if(mWave_VRC6Pulse[i].bChannelEnabled) {
-
-            mWave_VRC6Pulse[i].nFreqCount -= ticks;
-
-            if(mWave_VRC6Pulse[i].nDutyCount <=
-               mWave_VRC6Pulse[i].nDutyCycle)
-            {
-                mWave_VRC6Pulse[i].nMixL =
-                    VRC6Pulse_nOutputTable_L[mWave_VRC6Pulse[i].nVolume];
-            }
-            else
-                mWave_VRC6Pulse[i].nMixL = 0;
-
-            while(mWave_VRC6Pulse[i].nFreqCount <= 0) {
-                mWave_VRC6Pulse[i].nFreqCount +=
-                    mWave_VRC6Pulse[i].nFreqTimer.W + 1;
-
-                if(!mWave_VRC6Pulse[i].bDigitized)
-                    mWave_VRC6Pulse[i].nDutyCount =
-                        (mWave_VRC6Pulse[i].nDutyCount + 1) & 0x0F;
-            }
-        }
-    }
-
-    if(mWave_VRC6Saw.bChannelEnabled) {
-
-        mWave_VRC6Saw.nFreqCount -= ticks;
-
-        mWave_VRC6Saw.nMixL =
-            VRC6Saw_nOutputTable_L[mWave_VRC6Saw.nAccum >> 3];
-
-        while(mWave_VRC6Saw.nFreqCount <= 0) {
-
-            mWave_VRC6Saw.nFreqCount += mWave_VRC6Saw.nFreqTimer.W + 1;
-
-            mWave_VRC6Saw.nAccumStep++;
-            if(mWave_VRC6Saw.nAccumStep == 14)
-            {
-                mWave_VRC6Saw.nAccumStep = 0;
-                mWave_VRC6Saw.nAccum = 0;
-            }
-            else if(!(mWave_VRC6Saw.nAccumStep & 1))
-                mWave_VRC6Saw.nAccum += mWave_VRC6Saw.nAccumRate;
-        }
-    }
-}
-
-/****************** Square waves ******************/
-
-/* decay */
-#ifdef ICODE_INSTEAD_OF_INLINE
-void Wave_Squares_ClockMajor(void) ICODE_ATTR;
-void Wave_Squares_ClockMajor()
-#else
-inline void Wave_Squares_ClockMajor(void);
-inline void Wave_Squares_ClockMajor()
-#endif
-{
-    if(mWave_Squares.nDecayCount[0])
-        mWave_Squares.nDecayCount[0]--;
-    else
-    {
-        mWave_Squares.nDecayCount[0] = mWave_Squares.nDecayTimer[0];
-        if(mWave_Squares.nDecayVolume[0])
-            mWave_Squares.nDecayVolume[0]--;
-        else
-        {
-            if(mWave_Squares.bDecayLoop[0])
-                mWave_Squares.nDecayVolume[0] = 0x0F;
-        }
-
-        if(mWave_Squares.bDecayEnable[0])
-            mWave_Squares.nVolume[0] = mWave_Squares.nDecayVolume[0];
-    }
-        
-    if(mWave_Squares.nDecayCount[1])
-        mWave_Squares.nDecayCount[1]--;
-    else
-        {
-        mWave_Squares.nDecayCount[1] = mWave_Squares.nDecayTimer[1];
-        if(mWave_Squares.nDecayVolume[1])
-            mWave_Squares.nDecayVolume[1]--;
-        else
-        {
-            if(mWave_Squares.bDecayLoop[1])
-                mWave_Squares.nDecayVolume[1] = 0x0F;
-        }
-
-        if(mWave_Squares.bDecayEnable[1])
-            mWave_Squares.nVolume[1] = mWave_Squares.nDecayVolume[1];
-    }
-        
-}
-
-
-#ifdef ICODE_INSTEAD_OF_INLINE
-void Wave_Squares_CheckSweepForcedSilence(const int32_t i) ICODE_ATTR;
-void Wave_Squares_CheckSweepForcedSilence(const int32_t i)
-#else
-inline void Wave_Squares_CheckSweepForcedSilence(const int32_t i);
-inline void Wave_Squares_CheckSweepForcedSilence(const int32_t i)
-#endif
-{
-    if(mWave_Squares.nFreqTimer[i].W < 8) {
-        mWave_Squares.bSweepForceSilence[i] = 1; return;
-    }
-    if(!mWave_Squares.bSweepMode[i] &&
-       (( mWave_Squares.nFreqTimer[i].W +
-          (mWave_Squares.nFreqTimer[i].W >> mWave_Squares.nSweepShift[i]))
-       >= 0x0800)) { mWave_Squares.bSweepForceSilence[i] = 1; return; }
-
-    mWave_Squares.bSweepForceSilence[i] = 0;
-}
-
-/* sweep / length */
-#ifdef ICODE_INSTEAD_OF_INLINE
-void Wave_Squares_ClockMinor(void) ICODE_ATTR;
-void Wave_Squares_ClockMinor()
-#else
-inline void Wave_Squares_ClockMinor(void);
-inline void Wave_Squares_ClockMinor()
-#endif
-{
-/* unrolled a little loop
-   static int i = 0;
-  for(i = 0; i < 2; i++)
-  {
-*/
-    if(mWave_Squares.bLengthEnabled[0] && mWave_Squares.nLengthCount[0])
-            mWave_Squares.nLengthCount[0]--;
-
-    if(!mWave_Squares.bSweepEnable[0] || !mWave_Squares.nLengthCount[0] ||
-        mWave_Squares.bSweepForceSilence[0] || !mWave_Squares.nSweepShift[0])
-        goto other_square;
-
-    if(mWave_Squares.nSweepCount[0])
-        mWave_Squares.nSweepCount[0]--;
-    else
-    {
-        mWave_Squares.nSweepCount[0] = mWave_Squares.nSweepTimer[0];
-        if(mWave_Squares.bSweepMode[0])  mWave_Squares.nFreqTimer[0].W -=
-            (mWave_Squares.nFreqTimer[0].W >> mWave_Squares.nSweepShift[0])+1;
-        else mWave_Squares.nFreqTimer[0].W +=
-            (mWave_Squares.nFreqTimer[0].W >> mWave_Squares.nSweepShift[0]);
-
-        Wave_Squares_CheckSweepForcedSilence(0);
-    }
-        
-    /* */
-other_square:
-    if(mWave_Squares.bLengthEnabled[1] && mWave_Squares.nLengthCount[1])
-        mWave_Squares.nLengthCount[1]--;
-
-    if(!mWave_Squares.bSweepEnable[1] || !mWave_Squares.nLengthCount[1] ||
-        mWave_Squares.bSweepForceSilence[1] || !mWave_Squares.nSweepShift[1])
-        return;
-
-    if(mWave_Squares.nSweepCount[1])
-        mWave_Squares.nSweepCount[1]--;
-    else
-    {
-        mWave_Squares.nSweepCount[1] = mWave_Squares.nSweepTimer[1];
-        if(mWave_Squares.bSweepMode[1])  mWave_Squares.nFreqTimer[1].W -=
-            (mWave_Squares.nFreqTimer[1].W >> mWave_Squares.nSweepShift[1]);
-        else mWave_Squares.nFreqTimer[1].W +=
-            (mWave_Squares.nFreqTimer[1].W >> mWave_Squares.nSweepShift[1]);
-
-        Wave_Squares_CheckSweepForcedSilence(1);
-    }
-}
-
-/****************** Triangle/noise/DMC ******************/
-
-/* decay (noise), linear (tri) */
-
-#ifdef ICODE_INSTEAD_OF_INLINE
-void Wave_TND_ClockMajor(void) ICODE_ATTR;
-void Wave_TND_ClockMajor()
-#else
-inline void Wave_TND_ClockMajor(void);
-inline void Wave_TND_ClockMajor()
-#endif
-{
-    /* noise's decay */
-    if(mWave_TND.nNoiseDecayCount)
-        mWave_TND.nNoiseDecayCount--;
-    else
-    {
-        mWave_TND.nNoiseDecayCount = mWave_TND.nNoiseDecayTimer;
-        if(mWave_TND.nNoiseDecayVolume)
-            mWave_TND.nNoiseDecayVolume--;
-        else
-        {
-            if(mWave_TND.bNoiseDecayLoop)
-                mWave_TND.nNoiseDecayVolume = 0x0F;
-        }
-
-        if(mWave_TND.bNoiseDecayEnable)
-            mWave_TND.nNoiseVolume = mWave_TND.nNoiseDecayVolume;
-    }
-
-    /* triangle's linear */
-    if(mWave_TND.bTriLinearHalt)
-        mWave_TND.nTriLinearCount = mWave_TND.nTriLinearLoad;
-    else if(mWave_TND.nTriLinearCount)
-        mWave_TND.nTriLinearCount--;
-
-    if(!mWave_TND.bTriLinearControl)
-        mWave_TND.bTriLinearHalt = 0;
-}
-
-/* length */
-
-#ifdef ICODE_INSTEAD_OF_INLINE
-void Wave_TND_ClockMinor(void) ICODE_ATTR;
-void Wave_TND_ClockMinor()
-#else
-inline void Wave_TND_ClockMinor(void);
-inline void Wave_TND_ClockMinor()
-#endif
-{
-    if(mWave_TND.bNoiseLengthEnabled && mWave_TND.nNoiseLengthCount)
-        mWave_TND.nNoiseLengthCount--;
-        
-    if(mWave_TND.bTriLengthEnabled && mWave_TND.nTriLengthCount)
-        mWave_TND.nTriLengthCount--;
-}
-
-/*#undef this*/
-
-/****************** NSF Core ******************/
-
-/* start globals */
-
-/*
- *  Memory
- */
-/* RAM:      0x0000 - 0x07FF */
-uint8_t     pRAM[0x800] IDATA_ATTR;
-/* SRAM:     0x6000 - 0x7FFF (non-FDS only) */
-uint8_t     pSRAM[0x2000];
-/* ExRAM:    0x5C00 - 0x5FF5 (MMC5 only)
- * Also holds NSF player code (at 0x5000 - 0x500F) */
-uint8_t     pExRAM[0x1000];
-/* Full ROM buffer */
-uint8_t*    pROM_Full IDATA_ATTR;
-
-uint16_t    main_nOutputTable_L[0x8000];
-
-uint8_t*    pROM[10] IDATA_ATTR;/* ROM banks (point to areas in pROM_Full) */
-                                /* 0x8000 - 0xFFFF */
-                                /* also includes 0x6000 - 0x7FFF (FDS only) */
-uint8_t*        pStack;         /* the stack (points to areas in pRAM) */
-                                /* 0x0100 - 0x01FF */
-
-int32_t         nROMSize;       /* size of this ROM file in bytes */
-int32_t         nROMBankCount;  /* max number of 4k banks */
-int32_t         nROMMaxSize;    /* size of allocated pROM_Full buffer */
-
-/*
- *  Memory Proc Pointers
- */
- 
-typedef uint8_t ( *ReadProc)(uint16_t);
-typedef void ( *WriteProc)(uint16_t,uint8_t);
-ReadProc    ReadMemory[0x10] IDATA_ATTR;
-WriteProc   WriteMemory[0x10] IDATA_ATTR;
-
-/*
- *  6502 Registers / Mode
- */
-
-uint8_t     regA IDATA_ATTR;        /* Accumulator */
-uint8_t     regX IDATA_ATTR;        /* X-Index */
-uint8_t     regY IDATA_ATTR;        /* Y-Index */
-uint8_t     regP IDATA_ATTR;        /* Processor Status */
-uint8_t     regSP IDATA_ATTR;       /* Stack Pointer */
-uint16_t    regPC IDATA_ATTR;       /* Program Counter */
-
-uint8_t     bPALMode IDATA_ATTR;/* 1 if in PAL emulation mode, 0 if in NTSC */
-uint8_t     bCPUJammed IDATA_ATTR;  /* 0 = not jammed.  1 = really jammed.
-                                     * 2 = 'fake' jammed */
-                                  /* fake jam caused by the NSF code to signal
-                                   * the end of the play/init routine */
-
-/* Multiplication Register, for MMC5 chip only (5205+5206) */
-uint8_t     nMultIn_Low;
-uint8_t     nMultIn_High;
-
-/*
- *  NSF Preparation Information
- */
-
-uint8_t     nBankswitchInitValues[10];  /* banks to swap to on tune init */
-uint16_t    nPlayAddress;               /* Play routine address */
-uint16_t    nInitAddress;               /* Init routine address */
-
-uint8_t     nExternalSound;             /* external sound chips */
-uint8_t     nCurTrack;
-
-float       fNSFPlaybackSpeed;
-
-/*
- *  pAPU
- */
-
-uint8_t     nFrameCounter;      /* Frame Sequence Counter */
-uint8_t     nFrameCounterMax;   /* Frame Sequence Counter Size
-                                   (3 or 4 depending on $4017.7) */
-uint8_t     bFrameIRQEnabled;   /* TRUE if frame IRQs are enabled */
-uint8_t     bFrameIRQPending;   /* TRUE if the frame sequencer is holding down
-                                   an IRQ */
-
-uint8_t         nFME07_Address;
-
-/*
- *  Timing and Counters
- */
-/* fixed point -15.16 */
-
-int32_t     nTicksUntilNextFrame;
-int32_t     nTicksPerPlay;
-int32_t     nTicksUntilNextPlay;
-int32_t     nTicksPerSample;
-int32_t     nTicksUntilNextSample;
-
-uint32_t    nCPUCycle IDATA_ATTR;
-uint32_t    nAPUCycle IDATA_ATTR;
-
-   
-uint32_t    nTotalPlays; /* number of times the play subroutine has been called
-                            (for tracking output time) */
-/*
- *  Silence Tracker
- */
-int32_t     nSilentSamples;
-int32_t     nSilentSampleMax;
-int32_t     nSilenceTrackMS;
-uint8_t     bNoSilenceIfTime;
-uint8_t     bTimeNotDefault;
-
-/*
- *  Sound output options
- */
-const int32_t       nSampleRate=44100;
-
-/*
- *  Volume/fading/filter tracking
- */
-
-uint32_t        nStartFade; /* play call to start fading out */
-uint32_t        nEndFade;   /* play call to stop fading out (song is over) */
-uint8_t         bFade;      /* are we fading? */
-float           fFadeVolume;
-float           fFadeChange;
-
-/*
- *  Designated Output Buffer
- */
-uint8_t*        pOutput IDATA_ATTR;
-
-const uint8_t   bDMCPopReducer=1;
-uint8_t         nDMCPop_Prev IDATA_ATTR = 0;
-uint8_t         bDMCPop_Skip IDATA_ATTR = 0;
-uint8_t         bDMCPop_SamePlay IDATA_ATTR = 0;
-
-const uint8_t   nForce4017Write=0;
-const uint8_t   bN106PopReducer=0;
-const uint8_t   bIgnore4011Writes=0;
-    
-const uint8_t   bIgnoreBRK=0;
-const uint8_t   bIgnoreIllegalOps=0;
-const uint8_t   bNoWaitForReturn=0;
-const uint8_t   bPALPreference=0;
-const uint8_t   bCleanAXY=0;
-const uint8_t   bResetDuty=0;
-
-/*
- *  Sound Filter
- */
-
-int64_t     nFilterAccL IDATA_ATTR;
-int64_t     nHighPass IDATA_ATTR;
-
-int32_t     nHighPassBase IDATA_ATTR;
-
-uint8_t     bHighPassEnabled IDATA_ATTR;
-
-/* end globals */
-
-#define CLOCK_MAJOR() { Wave_Squares_ClockMajor(); Wave_TND_ClockMajor(); }
-#define CLOCK_MINOR() { Wave_Squares_ClockMinor(); Wave_TND_ClockMinor(); }
-
-#define EXTSOUND_VRC6           0x01
-#define EXTSOUND_VRC7           0x02
-#define EXTSOUND_FDS            0x04
-#define EXTSOUND_MMC5           0x08
-#define EXTSOUND_N106           0x10
-#define EXTSOUND_FME07          0x20
-
-#define SILENCE_THRESHOLD       3
-
-/*
- *  prototypes
- */
- 
-uint32_t Emulate6502(uint32_t runto) ICODE_ATTR;
-void EmulateAPU(uint8_t bBurnCPUCycles) ICODE_ATTR;
-
-int     NSFCore_Initialize(void); /* 1 = initialized ok,
-                           0 = couldn't initialize (memory allocation error) */
-
-/*
- *  Song Loading
- */
-int     LoadNSF(int32_t);   /* grab data from an existing file
-                               1 = loaded ok, 0 = error loading */
-
-/*
- *  Track Control
- */
-void    SetTrack(uint8_t track);  /* Change tracks */
-
-/*
- *  Getting Samples
- */
-/* fill a buffer with samples */
-int32_t     GetSamples(uint8_t* buffer, int32_t buffersize);
-
-/*
- *  Playback options
- */
-/* Set desired playback options (0 = bad options couldn't be set) */
-int     SetPlaybackOptions(int32_t samplerate);
-/* Speed throttling (0 = uses NSF specified speed) */
-void    SetPlaybackSpeed(float playspersec);
-
-float   GetPlaybackSpeed(void);
-float   GetMasterVolume(void);
-
-/*
- *  Seeking
- */
-/* gets the number of 'play' routine calls executed */
-float   GetPlayCalls(void);
-
-/* gets the output time (based on the given play rate,
-   if basedplayspersec is zero, current playback speed is used */
-uint32_t    GetWrittenTime(float basedplayspersec);
-/* sets the number of 'plays' routines executed (for precise seeking) */
-void    SetPlayCalls(float plays);
-/* sets the written time (approx. seeking) */
-void    SetWrittenTime(uint32_t ms,float basedplays);
-
-/*
- *  Fading
- */
-
-void    StopFade(void);         /* stops all fading (plays indefinitely) */
-uint8_t SongCompleted(void);    /* song has faded out (samples have stopped
-                                   being generated) */
-/* parameters are play calls */
-void    SetFade(int32_t fadestart,int32_t fadestop,uint8_t bNotDefault);
-void    SetFadeTime(uint32_t fadestart,uint32_t fadestop,float basedplays,
-            uint8_t bNotDefault); /* parameters are in milliseconds */
-
-/*
- *  Internal Functions
- */
-void    RebuildOutputTables(void);
-void    RecalculateFade(void);  /* called when fade status is changed. */
-void    RecalcFilter(void);
-void    RecalcSilenceTracker(void);
-
-void    WriteMemory_VRC6(uint16_t a,uint8_t v) ICODE_ATTR;
-void    WriteMemory_MMC5(uint16_t a,uint8_t v) ICODE_ATTR;
-void    WriteMemory_N106(uint16_t a,uint8_t v) ICODE_ATTR;
-void    WriteMemory_FME07(uint16_t a,uint8_t v) ICODE_ATTR;
-
-/*
- *  Memory Read/Write routines
- */
-
-uint8_t     ReadMemory_RAM(uint16_t a) ICODE_ATTR;
-uint8_t     ReadMemory_ExRAM(uint16_t a) ICODE_ATTR;
-uint8_t     ReadMemory_SRAM(uint16_t a) ICODE_ATTR;
-uint8_t     ReadMemory_pAPU(uint16_t a) ICODE_ATTR;
-uint8_t     ReadMemory_ROM(uint16_t a) ICODE_ATTR;
-uint8_t     ReadMemory_Default(uint16_t a) ICODE_ATTR;
-
-uint8_t     ReadMemory_N106(uint16_t a) ICODE_ATTR;
-
-void        WriteMemory_RAM(uint16_t a,uint8_t v) ICODE_ATTR;
-void        WriteMemory_ExRAM(uint16_t a,uint8_t v) ICODE_ATTR;
-void        WriteMemory_SRAM(uint16_t a,uint8_t v) ICODE_ATTR;
-void        WriteMemory_pAPU(uint16_t a,uint8_t v) ICODE_ATTR;
-void        WriteMemory_FDSRAM(uint16_t a,uint8_t v) ICODE_ATTR;
-void        WriteMemory_Default(uint16_t a,uint8_t v) ICODE_ATTR;
-
-uint8_t         ReadMemory_RAM(uint16_t a)      { return pRAM[a & 0x07FF]; }
-uint8_t         ReadMemory_ExRAM(uint16_t a)    { return pExRAM[a & 0x0FFF]; }
-uint8_t         ReadMemory_SRAM(uint16_t a)     { return pSRAM[a & 0x1FFF]; }
-uint8_t         ReadMemory_ROM(uint16_t a)
-    { return pROM[(a >> 12) - 6][a & 0x0FFF]; }
-uint8_t         ReadMemory_Default(uint16_t a)  { return (a >> 8); }
-
-void        WriteMemory_RAM(uint16_t a,uint8_t v)
-    { pRAM[a & 0x07FF] = v; }
-void        WriteMemory_ExRAM(uint16_t a,uint8_t v);
-void        WriteMemory_SRAM(uint16_t a,uint8_t v)
-    { pSRAM[a & 0x1FFF] = v; }
-void        WriteMemory_FDSRAM(uint16_t a,uint8_t v)
-    { pROM[(a >> 12) - 6][a & 0x0FFF] = v; }
-void        WriteMemory_Default(uint16_t a,uint8_t v)   { (void)a; (void)v; }
-
-
-/* Read Memory Procs */
-
-uint8_t  ReadMemory_pAPU(uint16_t a)
-{
-    EmulateAPU(1);
-
-    if(a == 0x4015)
-    {
-        uint8_t ret = 0;
-        if(mWave_Squares.nLengthCount[0])       ret |= 0x01;
-        if(mWave_Squares.nLengthCount[1])       ret |= 0x02;
-        if(mWave_TND.nTriLengthCount)           ret |= 0x04;
-        if(mWave_TND.nNoiseLengthCount)         ret |= 0x08;
-        if(mWave_TND.nDMCBytesRemaining)        ret |= 0x10;
-
-        if(bFrameIRQPending)            ret |= 0x40;
-        if(mWave_TND.bDMCIRQPending)            ret |= 0x80;
-
-        bFrameIRQPending = 0;
-        return ret;
-    }
-
-    if(!(nExternalSound & EXTSOUND_FDS))        return 0x40;
-    if(bPALMode)                                return 0x40;
-
-    if((a >= 0x4040) && (a <= 0x407F))
-        return mWave_FDS.nWaveTable[a & 0x3F] | 0x40;
-    if(a == 0x4090)
-        return (mWave_FDS.nVolEnv_Gain & 0x3F) | 0x40;
-    if(a == 0x4092)
-        return (mWave_FDS.nSweep_Gain & 0x3F) | 0x40;
-
-    return 0x40;
-}
-
-uint8_t  ReadMemory_N106(uint16_t a)
-{
-    if(a != 0x4800)
-        return ReadMemory_pAPU(a);
-
-    uint8_t ret = mWave_N106.nRAM[(mWave_N106.nCurrentAddress << 1)] |
-        (mWave_N106.nRAM[(mWave_N106.nCurrentAddress << 1) + 1] << 4);
-    if(mWave_N106.bAutoIncrement)
-        mWave_N106.nCurrentAddress = (mWave_N106.nCurrentAddress + 1) & 0x7F;
-
-    return ret;
-}
-
-
-/* Write Memory Procs */
-
-void  WriteMemory_ExRAM(uint16_t a,uint8_t v)
-{
-    if(a < 0x5FF6)              /* Invalid */
-        return;
-
-    a -= 0x5FF6;
-
-    /* Swap out banks */
-
-    EmulateAPU(1);
-    /* stop it from swapping to a bank that doesn't exist */
-    if(v >= nROMBankCount)
-        v = 0;
-
-    pROM[a] = pROM_Full + (v << 12);
-
-    /* Update the DMC's DMA pointer, as well */
-    if(a >= 2)
-        mWave_TND.pDMCDMAPtr[a - 2] = pROM[a];
-}
-
-void  WriteMemory_pAPU(uint16_t a,uint8_t v)
-{
-    EmulateAPU(1);
-    switch(a)
-    {
-    /* Square 1 */
-    case 0x4000:
-        mWave_Squares.nDutyCycle[0] = DUTY_CYCLE_TABLE[v >> 6];
-        mWave_Squares.bLengthEnabled[0] =
-            !(mWave_Squares.bDecayLoop[0] = (v & 0x20));
-        mWave_Squares.bDecayEnable[0] = !(v & 0x10);
-        mWave_Squares.nDecayTimer[0] = (v & 0x0F);
-
-        if(!mWave_Squares.bDecayEnable[0])
-            mWave_Squares.nVolume[0] = mWave_Squares.nDecayTimer[0];
-        break;
-
-    case 0x4001:
-        mWave_Squares.bSweepEnable[0] = (v & 0x80);
-        mWave_Squares.nSweepTimer[0] = (v & 0x70) >> 4;
-        mWave_Squares.bSweepMode[0] = v & 0x08;
-        mWave_Squares.nSweepShift[0] = v & 0x07;
-        Wave_Squares_CheckSweepForcedSilence(0);
-        break;
-        
-    case 0x4002:
-        mWave_Squares.nFreqTimer[0].B.l = v;
-        Wave_Squares_CheckSweepForcedSilence(0);
-        break;
-        
-    case 0x4003:
-        mWave_Squares.nFreqTimer[0].B.h = v & 0x07;
-        Wave_Squares_CheckSweepForcedSilence(0);
-
-        mWave_Squares.nDecayVolume[0] = 0x0F;
-
-        if(mWave_Squares.bChannelEnabled[0])
-            mWave_Squares.nLengthCount[0] = LENGTH_COUNTER_TABLE[v >> 3];
-
-        if(bResetDuty)
-            mWave_Squares.nDutyCount[0] = 0;
-        break;
-        
-
-    /* Square 2 */
-    case 0x4004:
-        mWave_Squares.nDutyCycle[1] = DUTY_CYCLE_TABLE[v >> 6];
-        mWave_Squares.bLengthEnabled[1] =
-            !(mWave_Squares.bDecayLoop[1] = (v & 0x20));
-        mWave_Squares.bDecayEnable[1] = !(v & 0x10);
-        mWave_Squares.nDecayTimer[1] = (v & 0x0F);
-
-        if(!mWave_Squares.bDecayEnable[1])
-            mWave_Squares.nVolume[1] = mWave_Squares.nDecayTimer[1];
-        break;
-
-    case 0x4005:
-        mWave_Squares.bSweepEnable[1] = (v & 0x80);
-        mWave_Squares.nSweepTimer[1] = (v & 0x70) >> 4;
-        mWave_Squares.bSweepMode[1] = v & 0x08;
-        mWave_Squares.nSweepShift[1] = v & 0x07;
-        Wave_Squares_CheckSweepForcedSilence(1);
-        break;
-        
-    case 0x4006:
-        mWave_Squares.nFreqTimer[1].B.l = v;
-        Wave_Squares_CheckSweepForcedSilence(1);
-        break;
-        
-    case 0x4007:
-        mWave_Squares.nFreqTimer[1].B.h = v & 0x07;
-        Wave_Squares_CheckSweepForcedSilence(1);
-
-        mWave_Squares.nDecayVolume[1] = 0x0F;
-
-        if(mWave_Squares.bChannelEnabled[1])
-            mWave_Squares.nLengthCount[1] = LENGTH_COUNTER_TABLE[v >> 3];
-
-        if(bResetDuty)
-            mWave_Squares.nDutyCount[1] = 0;
-        break;
-
-        
-    /* Triangle */
-    case 0x4008:
-        mWave_TND.nTriLinearLoad = v & 0x7F;
-        mWave_TND.bTriLinearControl = v & 0x80;
-        mWave_TND.bTriLengthEnabled = !(v & 0x80);
-        break;
-
-    case 0x400A:
-        mWave_TND.nTriFreqTimer.B.l = v;
-        break;
-
-    case 0x400B:
-        mWave_TND.nTriFreqTimer.B.h = v & 0x07;
-        mWave_TND.bTriLinearHalt = 1;
-        
-        if(mWave_TND.bTriChannelEnabled)
-            mWave_TND.nTriLengthCount = LENGTH_COUNTER_TABLE[v >> 3];
-        break;
-
-    /* Noise */
-    case 0x400C:
-        mWave_TND.bNoiseLengthEnabled =
-            !(mWave_TND.bNoiseDecayLoop = (v & 0x20));
-        mWave_TND.bNoiseDecayEnable = !(v & 0x10);
-        mWave_TND.nNoiseDecayTimer = (v & 0x0F);
-
-        if(mWave_TND.bNoiseDecayEnable)
-            mWave_TND.nNoiseVolume = mWave_TND.nNoiseDecayVolume;
-        else
-            mWave_TND.nNoiseVolume = mWave_TND.nNoiseDecayTimer;
-        break;
-
-    case 0x400E:
-        mWave_TND.nNoiseFreqTimer = NOISE_FREQ_TABLE[v & 0x0F];
-        mWave_TND.bNoiseRandomMode = (v & 0x80) ? 6 : 1;
-        break;
-
-    case 0x400F:
-        if(mWave_TND.bNoiseChannelEnabled)
-            mWave_TND.nNoiseLengthCount = LENGTH_COUNTER_TABLE[v >> 3];
-
-        mWave_TND.nNoiseDecayVolume = 0x0F;
-        if(mWave_TND.bNoiseDecayEnable)
-            mWave_TND.nNoiseVolume = 0x0F;
-        break;
-
-    /* DMC */
-    case 0x4010:
-        mWave_TND.bDMCLoop = v & 0x40;
-        mWave_TND.bDMCIRQEnabled = v & 0x80;
-        /* IRQ can't be pending if disabled */
-        if(!mWave_TND.bDMCIRQEnabled)
-            mWave_TND.bDMCIRQPending = 0;
-
-        mWave_TND.nDMCFreqTimer = DMC_FREQ_TABLE[bPALMode][v & 0x0F];
-        break;
-
-    case 0x4011:
-        if(bIgnore4011Writes)
-            break;
-        v &= 0x7F;
-        if(bDMCPopReducer)
-        {
-            if(bDMCPop_SamePlay)
-                mWave_TND.nDMCOutput = v;
-            else
-            {
-                if(bDMCPop_Skip)
-                {
-                    bDMCPop_Skip = 0;
-                    break;
-                }
-                if(nDMCPop_Prev == v) break;
-                if(mWave_TND.nDMCOutput == v) break;
-                mWave_TND.nDMCOutput = nDMCPop_Prev;
-                nDMCPop_Prev = v;
-                bDMCPop_SamePlay = 1;
-            }
-        }
-        else
-            mWave_TND.nDMCOutput = v;
-        break;
-
-    case 0x4012:
-        mWave_TND.nDMCDMABank_Load = (v >> 6) | 0x04;
-        mWave_TND.nDMCDMAAddr_Load = (v << 6) & 0x0FFF;
-        break;
-
-    case 0x4013:
-        mWave_TND.nDMCLength = (v << 4) + 1;
-        break;
-
-    /* All / General Purpose */
-    case 0x4015:
-        mWave_TND.bDMCIRQPending = 0;
-
-        if(v & 0x01){   mWave_Squares.bChannelEnabled[0] =  1;  }
-        else        {   mWave_Squares.bChannelEnabled[0] =
-                        mWave_Squares.nLengthCount[0] =     0;  }
-        if(v & 0x02){   mWave_Squares.bChannelEnabled[1] =  1;  }
-        else        {   mWave_Squares.bChannelEnabled[1] =
-                        mWave_Squares.nLengthCount[1] =     0;  }
-        if(v & 0x04){   mWave_TND.bTriChannelEnabled =      1;  }
-        else        {   mWave_TND.bTriChannelEnabled =
-                        mWave_TND.nTriLengthCount =         0;  }
-        if(v & 0x08){   mWave_TND.bNoiseChannelEnabled =    1;  }
-        else        {   mWave_TND.bNoiseChannelEnabled =
-                        mWave_TND.nNoiseLengthCount =       0;  }
-
-        if(v & 0x10)
-        {
-            if(!mWave_TND.nDMCBytesRemaining)
-            {
-                bDMCPop_Skip = 1;
-                mWave_TND.nDMCDMAAddr = mWave_TND.nDMCDMAAddr_Load;
-                mWave_TND.nDMCDMABank = mWave_TND.nDMCDMABank_Load;
-                mWave_TND.nDMCBytesRemaining = mWave_TND.nDMCLength;
-                mWave_TND.bDMCActive = 1;
-            }
-        }
-        else
-            mWave_TND.nDMCBytesRemaining = 0;
-        break;
-
-    case 0x4017:
-        bFrameIRQEnabled = !(v & 0x40);
-        bFrameIRQPending = 0;
-        nFrameCounter = 0;
-        nFrameCounterMax = (v & 0x80) ? 4 : 3;
-        nTicksUntilNextFrame =
-            (bPALMode ? PAL_FRAME_COUNTER_FREQ : NTSC_FRAME_COUNTER_FREQ)
-            * 0x10000;
-
-        CLOCK_MAJOR();
-        if(v & 0x80) CLOCK_MINOR();
-        break;
-    }
-
-    if(!(nExternalSound & EXTSOUND_FDS))        return;
-    if(bPALMode)                                return;
-
-    /* FDS Sound registers */
-
-    if(a < 0x4040)      return;
-
-    /* wave table */
-    if(a <= 0x407F)
-    {
-        if(mWave_FDS.bWaveWrite)
-            mWave_FDS.nWaveTable[a - 0x4040] = v;
-    }
-    else
-    {
-        switch(a)
-        {
-        case 0x4080:
-            mWave_FDS.nVolEnv_Mode = (v >> 6);
-            if(v & 0x80)
-            {
-                mWave_FDS.nVolEnv_Gain = v & 0x3F;
-                if(!mWave_FDS.nMainAddr)
-                {
-                    if(mWave_FDS.nVolEnv_Gain < 0x20)
-                        mWave_FDS.nVolume = mWave_FDS.nVolEnv_Gain;
-                    else mWave_FDS.nVolume = 0x20;
-                }
-            }
-            mWave_FDS.nVolEnv_Decay = v & 0x3F;
-            mWave_FDS.nVolEnv_Timer =
-                ((mWave_FDS.nVolEnv_Decay + 1) * mWave_FDS.nEnvelopeSpeed * 8);
-
-            mWave_FDS.bVolEnv_On = mWave_FDS.bEnvelopeEnable &&
-                mWave_FDS.nEnvelopeSpeed && !(v & 0x80);
-            break;
-
-        case 0x4082:
-            mWave_FDS.nFreq.B.l = v;
-            mWave_FDS.bMain_On = mWave_FDS.nFreq.W && mWave_FDS.bEnabled &&
-                !mWave_FDS.bWaveWrite;
-            break;
-
-        case 0x4083:
-            mWave_FDS.bEnabled =        !(v & 0x80);
-            mWave_FDS.bEnvelopeEnable = !(v & 0x40);
-            if(v & 0x80)
-            {
-                if(mWave_FDS.nVolEnv_Gain < 0x20)
-                    mWave_FDS.nVolume = mWave_FDS.nVolEnv_Gain;
-                else mWave_FDS.nVolume = 0x20;
-            }
-            mWave_FDS.nFreq.B.h = v & 0x0F;
-            mWave_FDS.bMain_On = mWave_FDS.nFreq.W && mWave_FDS.bEnabled &&
-                !mWave_FDS.bWaveWrite;
-
-            mWave_FDS.bVolEnv_On = mWave_FDS.bEnvelopeEnable &&
-                mWave_FDS.nEnvelopeSpeed && !(mWave_FDS.nVolEnv_Mode & 2);
-            mWave_FDS.bSweepEnv_On = mWave_FDS.bEnvelopeEnable &&
-                mWave_FDS.nEnvelopeSpeed && !(mWave_FDS.nSweep_Mode & 2);
-            break;
-
-
-        case 0x4084:
-            mWave_FDS.nSweep_Mode = v >> 6;
-            if(v & 0x80)
-                mWave_FDS.nSweep_Gain = v & 0x3F;
-            mWave_FDS.nSweep_Decay = v & 0x3F;
-            mWave_FDS.nSweep_Timer =
-                ((mWave_FDS.nSweep_Decay + 1) * mWave_FDS.nEnvelopeSpeed * 8);
-            mWave_FDS.bSweepEnv_On =
-                mWave_FDS.bEnvelopeEnable && mWave_FDS.nEnvelopeSpeed &&
-                !(v & 0x80);
-            break;
-
-
-        case 0x4085:
-            if(v & 0x40)    mWave_FDS.nSweepBias = (v & 0x3F) - 0x40;
-            else            mWave_FDS.nSweepBias = v & 0x3F;
-            mWave_FDS.nLFO_Addr = 0;
-            break;
-
-
-        case 0x4086:
-            mWave_FDS.nLFO_Freq.B.l = v;
-            mWave_FDS.bLFO_On =
-                mWave_FDS.bLFO_Enabled && mWave_FDS.nLFO_Freq.W;
-            if(mWave_FDS.nLFO_Freq.W)
-                mWave_FDS.nLFO_Timer = (0x10000<<14) / mWave_FDS.nLFO_Freq.W;
-            break;
-
-        case 0x4087:
-            mWave_FDS.bLFO_Enabled = !(v & 0x80);
-            mWave_FDS.nLFO_Freq.B.h = v & 0x0F;
-            mWave_FDS.bLFO_On =
-                mWave_FDS.bLFO_Enabled && mWave_FDS.nLFO_Freq.W;
-            if(mWave_FDS.nLFO_Freq.W)
-                mWave_FDS.nLFO_Timer = (0x10000<<14) / mWave_FDS.nLFO_Freq.W;
-            break;
-
-        case 0x4088:
-            if(mWave_FDS.bLFO_Enabled)  break;
-            register int32_t i;
-            for(i = 0; i < 62; i++)
-                mWave_FDS.nLFO_Table[i] = mWave_FDS.nLFO_Table[i + 2];
-            mWave_FDS.nLFO_Table[62] = mWave_FDS.nLFO_Table[63] = v & 7;
-            break;
-
-        case 0x4089:
-            mWave_FDS.nMainVolume = v & 3;
-            mWave_FDS.bWaveWrite = v & 0x80;
-            mWave_FDS.bMain_On = mWave_FDS.nFreq.W && mWave_FDS.bEnabled &&
-                !mWave_FDS.bWaveWrite;
-            break;
-
-        case 0x408A:
-            mWave_FDS.nEnvelopeSpeed = v;
-            mWave_FDS.bVolEnv_On =
-                mWave_FDS.bEnvelopeEnable &&
-                mWave_FDS.nEnvelopeSpeed && !(mWave_FDS.nVolEnv_Mode & 2);
-            mWave_FDS.bSweepEnv_On =
-                mWave_FDS.bEnvelopeEnable &&
-                mWave_FDS.nEnvelopeSpeed && !(mWave_FDS.nSweep_Mode & 2);
-            break;
-        }
-    }
-}
-
-void  WriteMemory_VRC6(uint16_t a,uint8_t v)
-{
-    EmulateAPU(1);
-
-    if((a < 0xA000) && (nExternalSound & EXTSOUND_VRC7)) return;
-    else if(nExternalSound & EXTSOUND_FDS)
-        WriteMemory_FDSRAM(a,v);
-
-    switch(a)
-    {
-    /* Pulse 1 */
-    case 0x9000:
-        mWave_VRC6Pulse[0].nVolume = v & 0x0F;
-        mWave_VRC6Pulse[0].nDutyCycle = (v >> 4) & 0x07;
-        mWave_VRC6Pulse[0].bDigitized = v & 0x80;
-        if(mWave_VRC6Pulse[0].bDigitized)
-            mWave_VRC6Pulse[0].nDutyCount = 0;
-        break;
-
-    case 0x9001:
-        mWave_VRC6Pulse[0].nFreqTimer.B.l = v;
-        break;
-
-    case 0x9002:
-        mWave_VRC6Pulse[0].nFreqTimer.B.h = v & 0x0F;
-        mWave_VRC6Pulse[0].bChannelEnabled = v & 0x80;
-        break;
-        
-
-    /* Pulse 2 */
-    case 0xA000:
-        mWave_VRC6Pulse[1].nVolume = v & 0x0F;
-        mWave_VRC6Pulse[1].nDutyCycle = (v >> 4) & 0x07;
-        mWave_VRC6Pulse[1].bDigitized = v & 0x80;
-        if(mWave_VRC6Pulse[1].bDigitized)
-            mWave_VRC6Pulse[1].nDutyCount = 0;
-        break;
-
-    case 0xA001:
-        mWave_VRC6Pulse[1].nFreqTimer.B.l = v;
-        break;
-
-    case 0xA002:
-        mWave_VRC6Pulse[1].nFreqTimer.B.h = v & 0x0F;
-        mWave_VRC6Pulse[1].bChannelEnabled = v & 0x80;
-        break;
-        
-    /* Sawtooth */
-    case 0xB000:
-        mWave_VRC6Saw.nAccumRate = (v & 0x3F);
-        break;
-
-    case 0xB001:
-        mWave_VRC6Saw.nFreqTimer.B.l = v;
-        break;
-
-    case 0xB002:
-        mWave_VRC6Saw.nFreqTimer.B.h = v & 0x0F;
-        mWave_VRC6Saw.bChannelEnabled = v & 0x80;
-        break;
-    }
-}
-
-void  WriteMemory_MMC5(uint16_t a,uint8_t v)
-{
-    if((a <= 0x5015) && !bPALMode)
-    {
-        /* no audio emulation */
-        return;
-    }
-
-    if(a == 0x5205)
-    {
-        nMultIn_Low = v;
-        goto multiply;
-    }
-    if(a == 0x5206)
-    {
-        nMultIn_High = v;
-multiply:
-        a = nMultIn_Low * nMultIn_High;
-        pExRAM[0x205] = a & 0xFF;
-        pExRAM[0x206] = a >> 8;
-        return;
-    }
-
-    if(a < 0x5C00) return;
-
-    pExRAM[a & 0x0FFF] = v;
-    if(a >= 0x5FF6)
-        WriteMemory_ExRAM(a,v);
-}
-
-void  WriteMemory_N106(uint16_t a,uint8_t v)
-{
-    if(a < 0x4800)
-    {
-        WriteMemory_pAPU(a,v);
-        return;
-    }
-
-    if(a == 0xF800)
-    {
-        mWave_N106.nCurrentAddress = v & 0x7F;
-        mWave_N106.bAutoIncrement = (v & 0x80);
-        return;
-    }
-
-    if(a == 0x4800)
-    {
-        EmulateAPU(1);
-        mWave_N106.nRAM[mWave_N106.nCurrentAddress << 1] = v & 0x0F;
-        mWave_N106.nRAM[(mWave_N106.nCurrentAddress << 1) + 1] = v >> 4;
-        a = mWave_N106.nCurrentAddress;
-        if(mWave_N106.bAutoIncrement)
-            mWave_N106.nCurrentAddress =
-                (mWave_N106.nCurrentAddress + 1) & 0x7F;
-
-#define N106REGWRITE(ch,r0,r1,r2,r3,r4)                         \
-    case r0:    if(mWave_N106.nFreqReg[ch].B.l == v) break;     \
-                mWave_N106.nFreqReg[ch].B.l = v;                \
-                mWave_N106.nFreqTimer[ch] = -1;              \
-                break;                                          \
-    case r1:    if(mWave_N106.nFreqReg[ch].B.h == v) break;     \
-                mWave_N106.nFreqReg[ch].B.h = v;                \
-                mWave_N106.nFreqTimer[ch] = -1;              \
-                break;                                          \
-    case r2:    if(mWave_N106.nFreqReg[ch].B.w != (v & 3)){     \
-                    mWave_N106.nFreqReg[ch].B.w = v & 0x03;     \
-                    mWave_N106.nFreqTimer[ch] = -1;}         \
-                mWave_N106.nWaveSize[ch] = 0x20 - (v & 0x1C);   \
-                break;                                          \
-    case r3:    mWave_N106.nWavePosStart[ch] = v;               \
-                break;                                          \
-    case r4:    mWave_N106.nPreVolume[ch] = v & 0x0F;           \
-                if(!bN106PopReducer)                            \
-                    mWave_N106.nVolume[ch] = v & 0x0F
-
-        switch(a)
-        {
-            N106REGWRITE(0,0x40,0x42,0x44,0x46,0x47); break;
-            N106REGWRITE(1,0x48,0x4A,0x4C,0x4E,0x4F); break;
-            N106REGWRITE(2,0x50,0x52,0x54,0x56,0x57); break;
-            N106REGWRITE(3,0x58,0x5A,0x5C,0x5E,0x5F); break;
-            N106REGWRITE(4,0x60,0x62,0x64,0x66,0x67); break;
-            N106REGWRITE(5,0x68,0x6A,0x6C,0x6E,0x6F); break;
-            N106REGWRITE(6,0x70,0x72,0x74,0x76,0x77); break;
-            N106REGWRITE(7,0x78,0x7A,0x7C,0x7E,0x7F);
-                v = (v >> 4) & 7;
-                if(mWave_N106.nActiveChannels == v) break;
-                mWave_N106.nActiveChannels = v;
-                mWave_N106.nFreqTimer[0] = -1;
-                mWave_N106.nFreqTimer[1] = -1;
-                mWave_N106.nFreqTimer[2] = -1;
-                mWave_N106.nFreqTimer[3] = -1;
-                mWave_N106.nFreqTimer[4] = -1;
-                mWave_N106.nFreqTimer[5] = -1;
-                mWave_N106.nFreqTimer[6] = -1;
-                mWave_N106.nFreqTimer[7] = -1;
-                break;
-        }
-#undef N106REGWRITE
-    }
-}
-
-void WriteMemory_FME07(uint16_t a,uint8_t v)
-{
-    if((a < 0xD000) && (nExternalSound & EXTSOUND_FDS))
-        WriteMemory_FDSRAM(a,v);
-
-    if(a == 0xC000)
-        nFME07_Address = v;
-    if(a == 0xE000)
-    {
-        switch(nFME07_Address)
-        {
-        case 0x00:  mWave_FME07[0].nFreqTimer.B.l = v;          break;
-        case 0x01:  mWave_FME07[0].nFreqTimer.B.h = v & 0x0F;   break;
-        case 0x02:  mWave_FME07[1].nFreqTimer.B.l = v;          break;
-        case 0x03:  mWave_FME07[1].nFreqTimer.B.h = v & 0x0F;   break;
-        case 0x04:  mWave_FME07[2].nFreqTimer.B.l = v;          break;
-        case 0x05:  mWave_FME07[2].nFreqTimer.B.h = v & 0x0F;   break;
-        case 0x07:
-            mWave_FME07[0].bChannelEnabled = !(v & 0x01);
-            mWave_FME07[1].bChannelEnabled = !(v & 0x02);
-            mWave_FME07[2].bChannelEnabled = !(v & 0x03);
-            break;
-        case 0x08:  mWave_FME07[0].nVolume = v & 0x0F; break;
-        case 0x09:  mWave_FME07[1].nVolume = v & 0x0F; break;
-        case 0x0A:  mWave_FME07[2].nVolume = v & 0x0F; break;
-        }
-    }
-}
-
-/*
- * Emulate APU
- */
-
-int32_t fulltick;
-void EmulateAPU(uint8_t bBurnCPUCycles)
-{
-    int32_t tick;
-    int64_t diff;
-    
-    int32_t tnd_out;
-    int square_out1;
-    int square_out2;
-    
-    ENTER_TIMER(apu);
-    
-    fulltick += (signed)(nCPUCycle - nAPUCycle);
-
-    int32_t burned;
-    int32_t mixL;
-
-    if(bFade && nSilentSampleMax && (nSilentSamples >= nSilentSampleMax))
-        fulltick = 0;
-
-    while(fulltick>0)
-    {
-        tick = (nTicksUntilNextSample+0xffff)>>16;
-
-        fulltick -= tick;
-
-        /*
-         * Sample Generation
-         */
-
-        ENTER_TIMER(squares);
-        /* Square generation */
-
-        mWave_Squares.nFreqCount[0] -= tick;
-        mWave_Squares.nFreqCount[1] -= tick;
-
-        if((mWave_Squares.nDutyCount[0] < mWave_Squares.nDutyCycle[0]) &&
-            mWave_Squares.nLengthCount[0] &&
-            !mWave_Squares.bSweepForceSilence[0])
-            square_out1 = mWave_Squares.nVolume[0];
-        else
-            square_out1 = 0;
-
-        if((mWave_Squares.nDutyCount[1] < mWave_Squares.nDutyCycle[1]) &&
-            mWave_Squares.nLengthCount[1] &&
-            !mWave_Squares.bSweepForceSilence[1])
-            square_out2 = mWave_Squares.nVolume[1];
-        else
-            square_out2 = 0;
-
-        mWave_Squares.nMixL = Squares_nOutputTable_L[square_out1][square_out2];
-
-        if(mWave_Squares.nFreqCount[0]<=0)
-        {
-            int cycles =
-                (-mWave_Squares.nFreqCount[0])/
-                (mWave_Squares.nFreqTimer[0].W + 1) + 1;
-            mWave_Squares.nFreqCount[0] =
-                (mWave_Squares.nFreqTimer[0].W + 1)-
-                (-mWave_Squares.nFreqCount[0])%
-                (mWave_Squares.nFreqTimer[0].W + 1);
-            mWave_Squares.nDutyCount[0] =
-                (mWave_Squares.nDutyCount[0]+cycles)%0x10;
-        }
-        if(mWave_Squares.nFreqCount[1]<=0)
-        {
-            int cycles =
-                (-mWave_Squares.nFreqCount[1])/
-                (mWave_Squares.nFreqTimer[1].W + 1) + 1;
-            mWave_Squares.nFreqCount[1] = 
-                (mWave_Squares.nFreqTimer[1].W + 1)-
-                (-mWave_Squares.nFreqCount[1])%
-                (mWave_Squares.nFreqTimer[1].W + 1);
-            mWave_Squares.nDutyCount[1] = (mWave_Squares.nDutyCount[1]+cycles)%
-                0x10;
-        }
-        /* end of Square generation */
-        EXIT_TIMER(squares);
-        ENTER_TIMER(tnd);
-        
-        ENTER_TIMER(tnd_enter);
-    
-        burned=0;
-    
-        /* TND generation */
-    
-        if(mWave_TND.nNoiseFreqTimer) mWave_TND.nNoiseFreqCount -= tick;
-            
-        if(mWave_TND.nTriFreqTimer.W > 8)
-            mWave_TND.nTriFreqCount -= tick;
-
-        tnd_out = mWave_TND.nTriOutput << 11;
-
-        if(mWave_TND.bNoiseRandomOut && mWave_TND.nNoiseLengthCount)
-            tnd_out |= mWave_TND.nNoiseVolume << 7;
-
-        tnd_out |= mWave_TND.nDMCOutput;
-
-        mWave_TND.nMixL = main_nOutputTable_L[tnd_out];
-
-        EXIT_TIMER(tnd_enter);
-    
-        ENTER_TIMER(tnd_tri);
-    
-        /* Tri */
-
-        if(mWave_TND.nTriFreqCount<=0)
-        {
-            if(mWave_TND.nTriLengthCount && mWave_TND.nTriLinearCount)
-            {
-                do mWave_TND.nTriStep++;
-                while ((mWave_TND.nTriFreqCount +=
-                    mWave_TND.nTriFreqTimer.W + 1) <= 0);
-                mWave_TND.nTriStep &= 0x1F;
-
-                if(mWave_TND.nTriStep & 0x10)
-                    mWave_TND.nTriOutput = mWave_TND.nTriStep ^ 0x1F;
-                else mWave_TND.nTriOutput = mWave_TND.nTriStep;
-            } else mWave_TND.nTriFreqCount=mWave_TND.nTriFreqTimer.W+1;
-        }
-
-        EXIT_TIMER(tnd_tri);
-    
-        ENTER_TIMER(tnd_noise);
-    
-        /* Noise */
-
-        if(mWave_TND.nNoiseFreqTimer &&
-           mWave_TND.nNoiseVolume && mWave_TND.nNoiseFreqCount<=0)
-        {
-            mWave_TND.nNoiseFreqCount = mWave_TND.nNoiseFreqTimer;
-            mWave_TND.nNoiseRandomShift <<= 1;
-            mWave_TND.bNoiseRandomOut = (((mWave_TND.nNoiseRandomShift <<
-                mWave_TND.bNoiseRandomMode) ^
-                mWave_TND.nNoiseRandomShift) & 0x8000 ) ? 1 : 0;
-            if(mWave_TND.bNoiseRandomOut)
-                mWave_TND.nNoiseRandomShift |= 0x01;
-        }
-    
-        EXIT_TIMER(tnd_noise);
-    
-        ENTER_TIMER(tnd_dmc);
-
-        /* DMC */
-        if(mWave_TND.bDMCActive)
-        {
-            mWave_TND.nDMCFreqCount -= tick;
-            while (mWave_TND.nDMCFreqCount <= 0) {
-                if (!mWave_TND.bDMCActive) {
-                    mWave_TND.nDMCFreqCount = mWave_TND.nDMCFreqTimer;
-                    break;
-                }
-
-                mWave_TND.nDMCFreqCount += mWave_TND.nDMCFreqTimer;
-
-                if(mWave_TND.bDMCSampleBufferEmpty &&
-                   mWave_TND.nDMCBytesRemaining)
-                {
-                    burned += 4;        /* 4 cycle burn! */
-                    mWave_TND.nDMCSampleBuffer =
-                        mWave_TND.pDMCDMAPtr[mWave_TND.nDMCDMABank]
-                                            [mWave_TND.nDMCDMAAddr];
-                    mWave_TND.nDMCDMAAddr++;
-                    if(mWave_TND.nDMCDMAAddr & 0x1000)
-                    {
-                        mWave_TND.nDMCDMAAddr &= 0x0FFF;
-                        mWave_TND.nDMCDMABank =
-                            (mWave_TND.nDMCDMABank + 1) & 0x07;
-                    }
-
-                    mWave_TND.bDMCSampleBufferEmpty = 0;
-                    mWave_TND.nDMCBytesRemaining--;
-                    if(!mWave_TND.nDMCBytesRemaining)
-                    {
-                        if(mWave_TND.bDMCLoop)
-                        {
-                            mWave_TND.nDMCDMABank = mWave_TND.nDMCDMABank_Load;
-                            mWave_TND.nDMCDMAAddr = mWave_TND.nDMCDMAAddr_Load;
-                            mWave_TND.nDMCBytesRemaining =mWave_TND.nDMCLength;
-                        }
-                        else if(mWave_TND.bDMCIRQEnabled)
-                            mWave_TND.bDMCIRQPending = 1;
-                    }
-                }
-
-                if(!mWave_TND.nDMCDeltaBit)
-                {
-                    mWave_TND.nDMCDeltaBit = 8;
-                    mWave_TND.bDMCDeltaSilent =mWave_TND.bDMCSampleBufferEmpty;
-                    mWave_TND.nDMCDelta = mWave_TND.nDMCSampleBuffer;
-                    mWave_TND.bDMCSampleBufferEmpty = 1;
-                }
-                
-                if(mWave_TND.nDMCDeltaBit) {
-                    mWave_TND.nDMCDeltaBit--;
-                    if(!mWave_TND.bDMCDeltaSilent)
-                    {
-                        if(mWave_TND.nDMCDelta & 0x01)
-                        {
-                            if(mWave_TND.nDMCOutput < 0x7E)
-                                mWave_TND.nDMCOutput += 2;
-                        }
-                        else if(mWave_TND.nDMCOutput > 1)
-                            mWave_TND.nDMCOutput -= 2;
-                    }
-                    mWave_TND.nDMCDelta >>= 1;
-                }
-
-                if(!mWave_TND.nDMCBytesRemaining &&
-                    mWave_TND.bDMCSampleBufferEmpty &&
-                    mWave_TND.bDMCDeltaSilent)
-                    mWave_TND.bDMCActive = mWave_TND.nDMCDeltaBit = 0;
-            }
-        }
-    
-        EXIT_TIMER(tnd_dmc);
-   
-        /* end of TND generation */
-        EXIT_TIMER(tnd);
-
-        if(nExternalSound && !bPALMode)
-        {
-            if(nExternalSound & EXTSOUND_VRC6)
-                Wave_VRC6_DoTicks(tick);
-            if(nExternalSound & EXTSOUND_N106)
-                Wave_N106_DoTicks(tick);
-            if(nExternalSound & EXTSOUND_FME07)
-            {
-                if (mWave_FME07[0].bChannelEnabled &&
-                    mWave_FME07[0].nFreqTimer.W) {
-                    mWave_FME07[0].nFreqCount -= tick;
-
-                    if(mWave_FME07[0].nDutyCount < 16)
-                    {
-                        mWave_FME07[0].nMixL =
-                            FME07_nOutputTable_L[mWave_FME07[0].nVolume];
-                    } else mWave_FME07[0].nMixL = 0;
-                    while(mWave_FME07[0].nFreqCount <= 0) {
-                        mWave_FME07[0].nFreqCount +=
-                            mWave_FME07[0].nFreqTimer.W;
-
-                        mWave_FME07[0].nDutyCount=
-                            (mWave_FME07[0].nDutyCount+1)&0x1f;
-                    }
-                }
-
-                if (mWave_FME07[1].bChannelEnabled &&
-                    mWave_FME07[1].nFreqTimer.W) {
-                    mWave_FME07[1].nFreqCount -= tick;
-
-                    if(mWave_FME07[1].nDutyCount < 16)
-                    {
-                        mWave_FME07[1].nMixL =
-                            FME07_nOutputTable_L[mWave_FME07[1].nVolume];
-                    } else mWave_FME07[1].nMixL = 0;
-                    while(mWave_FME07[1].nFreqCount <= 0) {
-                        mWave_FME07[1].nFreqCount +=
-                            mWave_FME07[1].nFreqTimer.W;
-
-                        mWave_FME07[1].nDutyCount=
-                            (mWave_FME07[1].nDutyCount+1)&0x1f;
-                    }
-                }
-
-                if (mWave_FME07[2].bChannelEnabled &&
-                    mWave_FME07[2].nFreqTimer.W) {
-                    mWave_FME07[2].nFreqCount -= tick;
-
-                    if(mWave_FME07[2].nDutyCount < 16)
-                    {
-                        mWave_FME07[2].nMixL =
-                            FME07_nOutputTable_L[mWave_FME07[2].nVolume];
-                    } else mWave_FME07[2].nMixL = 0;
-                    while(mWave_FME07[2].nFreqCount <= 0) {
-                        mWave_FME07[2].nFreqCount +=
-                            mWave_FME07[2].nFreqTimer.W;
-
-                        mWave_FME07[2].nDutyCount=
-                            (mWave_FME07[2].nDutyCount+1)&0x1f;
-                    }
-                }
-
-            } /* end FME07 */
-            ENTER_TIMER(fds);
-            if(nExternalSound & EXTSOUND_FDS) {
-
-                /*  Volume Envelope Unit    */
-                if(mWave_FDS.bVolEnv_On)
-                {
-                    mWave_FDS.nVolEnv_Count -= tick;
-                    while(mWave_FDS.nVolEnv_Count <= 0)
-                    {
-                        mWave_FDS.nVolEnv_Count += mWave_FDS.nVolEnv_Timer;
-                        if(mWave_FDS.nVolEnv_Mode) {
-                            if(mWave_FDS.nVolEnv_Gain < 0x20)
-                                mWave_FDS.nVolEnv_Gain++;
-                            }
-                        else {
-                            if(mWave_FDS.nVolEnv_Gain)
-                                mWave_FDS.nVolEnv_Gain--;
-                        }
-                    }
-                }
-    
-                /*  Sweep Envelope Unit */
-                if(mWave_FDS.bSweepEnv_On)
-                {
-                    mWave_FDS.nSweep_Count -= tick;
-                    while(mWave_FDS.nSweep_Count <= 0)
-                    {
-                        mWave_FDS.nSweep_Count += mWave_FDS.nSweep_Timer;
-                        if(mWave_FDS.nSweep_Mode)    {
-                            if(mWave_FDS.nSweep_Gain < 0x20)
-                                mWave_FDS.nSweep_Gain++;
-                        } else {
-                            if(mWave_FDS.nSweep_Gain) mWave_FDS.nSweep_Gain--;
-                        }
-                    }
-                }
-            
-                /*  Effector / LFO      */
-                int32_t     subfreq = 0;
-                if(mWave_FDS.bLFO_On)
-                {
-                    mWave_FDS.nLFO_Count -= tick<<14;
-                    while(mWave_FDS.nLFO_Count <= 0)
-                    {
-                        mWave_FDS.nLFO_Count += mWave_FDS.nLFO_Timer;
-                        if(mWave_FDS.nLFO_Table[mWave_FDS.nLFO_Addr] == 4)
-                            mWave_FDS.nSweepBias = 0;
-                        else 
-                            mWave_FDS.nSweepBias +=
-                                ModulationTable[ 
-                                    mWave_FDS.nLFO_Table[mWave_FDS.nLFO_Addr]
-                                ];
-                        mWave_FDS.nLFO_Addr = (mWave_FDS.nLFO_Addr + 1) & 0x3F;
-                    }
-            
-                    while(mWave_FDS.nSweepBias >  63)
-                        mWave_FDS.nSweepBias -= 128;
-                    while(mWave_FDS.nSweepBias < -64)
-                        mWave_FDS.nSweepBias += 128;
-            
-                    register int32_t temp =
-                        mWave_FDS.nSweepBias * mWave_FDS.nSweep_Gain;
-                    if(temp & 0x0F)
-                    {
-                        temp /= 16;
-                        if(mWave_FDS.nSweepBias < 0) temp--;
-                        else                temp += 2;
-                    }
-                    else
-                        temp /= 16;
-            
-                    if(temp > 193)  temp -= 258;
-                    if(temp < -64)  temp += 256;
-            
-                    subfreq = mWave_FDS.nFreq.W * temp / 64;
-                }
-            
-                /*  Main Unit       */
-                if(mWave_FDS.bMain_On)
-                {
-                    mWave_FDS.nMixL =
-                        FDS_nOutputTable_L[mWave_FDS.nMainVolume]
-                                          [mWave_FDS.nVolume]
-                                 [mWave_FDS.nWaveTable[mWave_FDS.nMainAddr] ];
-            
-                    if((subfreq + mWave_FDS.nFreq.W) > 0)
-                    {
-                        int32_t freq = (0x10000<<14) / (subfreq + mWave_FDS.nFreq.W);
-            
-                        mWave_FDS.nFreqCount -= tick<<14;
-                        while(mWave_FDS.nFreqCount <= 0)
-                        {
-                            mWave_FDS.nFreqCount += freq;
-            
-                            mWave_FDS.nMainAddr =
-                                (mWave_FDS.nMainAddr + 1) & 0x3F;
-                            mWave_FDS.nPopOutput =
-                                mWave_FDS.nWaveTable[mWave_FDS.nMainAddr];
-                            if(!mWave_FDS.nMainAddr)
-                            {
-                                if(mWave_FDS.nVolEnv_Gain < 0x20)
-                                    mWave_FDS.nVolume = mWave_FDS.nVolEnv_Gain;
-                                else mWave_FDS.nVolume = 0x20;
-                            }
-                        }
-                    }
-                    else
-                        mWave_FDS.nFreqCount = mWave_FDS.nLFO_Count;
-                }
-                else if(mWave_FDS.bPopReducer && mWave_FDS.nPopOutput)
-                {
-                    mWave_FDS.nMixL = FDS_nOutputTable_L[mWave_FDS.nMainVolume]
-                                                        [mWave_FDS.nVolume]
-                                                        [mWave_FDS.nPopOutput];
-            
-                    mWave_FDS.nPopCount -= tick;
-                    while(mWave_FDS.nPopCount <= 0)
-                    {
-                        mWave_FDS.nPopCount += 500;
-                        mWave_FDS.nPopOutput--;
-                        if(!mWave_FDS.nPopOutput)
-                            mWave_FDS.nMainAddr = 0;
-                    }
-                } /* end FDS */
-            }
-            EXIT_TIMER(fds);
-        } /* end while fulltick */
-
-        if(bBurnCPUCycles)
-        {
-            nCPUCycle += burned;
-            fulltick += burned;
-        }
-        
-        /* Frame Sequencer */
-
-        ENTER_TIMER(frame);
-        nTicksUntilNextFrame -= tick<<16;
-        while(nTicksUntilNextFrame <= 0)
-        {
-            nTicksUntilNextFrame +=
-                (bPALMode ? PAL_FRAME_COUNTER_FREQ : NTSC_FRAME_COUNTER_FREQ) *
-                0x10000;
-            nFrameCounter++;
-            if(nFrameCounter > nFrameCounterMax)
-                nFrameCounter = 0;
-
-            if(nFrameCounterMax == 4)
-            {
-                if(nFrameCounter < 4)
-                {
-                    CLOCK_MAJOR();
-                    if(!(nFrameCounter & 1))
-                        CLOCK_MINOR();
-                }
-            }
-            else
-            {
-                CLOCK_MAJOR();
-                if(nFrameCounter & 1)
-                    CLOCK_MINOR();
-
-                if((nFrameCounter == 3) && bFrameIRQEnabled)
-                    bFrameIRQPending = 1;
-            }
-        }
-        EXIT_TIMER(frame);
-
-        ENTER_TIMER(mix);
-        nTicksUntilNextSample -= tick<<16;
-        if(nTicksUntilNextSample <= 0)
-        {
-            nTicksUntilNextSample += nTicksPerSample;
-            
-            mixL = mWave_Squares.nMixL;
-            mixL += mWave_TND.nMixL;
-
-            if(nExternalSound && !bPALMode)
-            {
-                if(nExternalSound & EXTSOUND_VRC6)
-                {
-                    mixL += (mWave_VRC6Pulse[0].nMixL);
-                    mixL += (mWave_VRC6Pulse[1].nMixL);
-                    mixL += (mWave_VRC6Saw.nMixL);
-                }
-                if(nExternalSound & EXTSOUND_N106) {
-                    mixL += (mWave_N106.nMixL[0]);
-                    mixL += (mWave_N106.nMixL[1]);
-                    mixL += (mWave_N106.nMixL[2]);
-                    mixL += (mWave_N106.nMixL[3]);
-                    mixL += (mWave_N106.nMixL[4]);
-                    mixL += (mWave_N106.nMixL[5]);
-                    mixL += (mWave_N106.nMixL[6]);
-                    mixL += (mWave_N106.nMixL[7]);
-                }
-                if(nExternalSound & EXTSOUND_FME07)
-                {
-                    mixL += (mWave_FME07[0].nMixL);
-                    mixL += (mWave_FME07[1].nMixL);
-                    mixL += (mWave_FME07[2].nMixL);
-                }
-                if(nExternalSound & EXTSOUND_FDS)
-                    mixL += mWave_FDS.nMixL;
-            }
-
-            /*  Filter  */
-            diff = ((int64_t)mixL << 25) - nFilterAccL;
-            nFilterAccL += (diff * nHighPass) >> 16;
-            mixL = (int32_t)(diff >> 23);
-            /*  End Filter  */
-                
-            if(bFade && (fFadeVolume < 1))
-                mixL = (int32_t)(mixL * fFadeVolume);
-
-            if(mixL < -32768)   mixL = -32768;
-            if(mixL >  32767)   mixL =  32767;
-
-            *((uint16_t*)pOutput) = (uint16_t)mixL;
-            pOutput += 2;
-        }
-        
-    }
-    EXIT_TIMER(mix);
-
-    nAPUCycle = nCPUCycle;
-    
-    EXIT_TIMER(apu);
-}
-
-
-/*
- *  Initialize
- *
- *      Initializes Memory
- */
-
-int NSFCore_Initialize()
-{
-    int32_t i;
-    /* clear globals */
-    /* why, yes, this was easier when they were in a struct */
-
-    /*
-     *  Memory
-     */
-
-    ZEROMEMORY(pRAM,0x800);
-    ZEROMEMORY(pSRAM,0x2000);
-    ZEROMEMORY(pExRAM,0x1000);
-    pROM_Full=0;
-
-    ZEROMEMORY(pROM,10);
-    pStack=0;
-
-    nROMSize=0;
-    nROMBankCount=0;
-    nROMMaxSize=0;
-
-    /*
-     *  Memory Proc Pointers
-     */
-
-    ZEROMEMORY(ReadMemory,sizeof(ReadProc)*0x10);
-    ZEROMEMORY(WriteMemory,sizeof(WriteProc)*0x10);
-    
-    /*
-     *  6502 Registers / Mode
-     */
-
-    regA=0;
-    regX=0;
-    regY=0;
-    regP=0;
-    regSP=0;
-    regPC=0;
-
-    bPALMode=0;
-    bCPUJammed=0;
-
-    nMultIn_Low=0;
-    nMultIn_High=0;
-
-    /*
-     *  NSF Preparation Information
-     */
-
-    ZEROMEMORY(nBankswitchInitValues,10);
-    nPlayAddress=0;
-    nInitAddress=0;
-
-    nExternalSound=0;
-    nCurTrack=0;
-
-    fNSFPlaybackSpeed=0;
-
-    /*
-     * pAPU
-     */
-
-    nFrameCounter=0;
-    nFrameCounterMax=0;
-    bFrameIRQEnabled=0;
-    bFrameIRQPending=0;
-
-    /*
-     *  Timing and Counters
-     */
-    nTicksUntilNextFrame=0;
-
-    nTicksPerPlay=0;
-    nTicksUntilNextPlay=0;
-
-    nTicksPerSample=0;
-    nTicksUntilNextSample=0;
-
-    nCPUCycle=0;
-    nAPUCycle=0;
-    nTotalPlays=0;
-
-    /*
-     * Silence Tracker
-     */
-    nSilentSamples=0;
-    nSilentSampleMax=0;
-    nSilenceTrackMS=0;
-    bNoSilenceIfTime=0;
-    bTimeNotDefault=0;
-
-    /*
-     * Volume/fading/filter tracking
-     */
-
-    nStartFade=0;
-    nEndFade=0;
-    bFade=0;
-    fFadeVolume=0;
-    fFadeChange=0;
-
-    pOutput=0;
-
-    nDMCPop_Prev=0;
-    bDMCPop_Skip=0;
-    bDMCPop_SamePlay=0;
-
-    /*
-     * Sound Filter
-     */
-
-    nFilterAccL=0;
-    nHighPass=0;
-
-    nHighPassBase=0;
-
-    bHighPassEnabled=0;
-
-    /* channels */
-    
-    ZEROMEMORY(&mWave_Squares,sizeof(struct Wave_Squares));
-    ZEROMEMORY(&mWave_TND,sizeof(struct Wave_TND));
-    ZEROMEMORY(mWave_VRC6Pulse,sizeof(struct VRC6PulseWave)*2);
-    ZEROMEMORY(&mWave_VRC6Saw,sizeof(struct VRC6SawWave));
-    ZEROMEMORY(&mWave_N106,sizeof(struct N106Wave));
-    ZEROMEMORY(mWave_FME07,sizeof(struct FME07Wave)*3);
-    ZEROMEMORY(&mWave_FDS,sizeof(struct FDSWave));
-    
-    /* end clear globals */
-
-    // Default filter bases
-    nHighPassBase = 150;
-
-    bHighPassEnabled = 1;
-
-    mWave_TND.nNoiseRandomShift =   1;
-    for(i = 0; i < 8; i++)
-        mWave_TND.pDMCDMAPtr[i] = pROM[i + 2];
-
-
-    SetPlaybackOptions(nSampleRate);
-
-    for(i = 0; i < 8; i++)
-        mWave_N106.nFrequencyLookupTable[i] =
-            ((((i + 1) * 45 * 0x40000) / (float)NES_FREQUENCY) *
-            (float)NTSC_FREQUENCY) * 256.0;
-
-    ZEROMEMORY(pRAM,0x800);
-    ZEROMEMORY(pSRAM,0x2000);
-    ZEROMEMORY(pExRAM,0x1000);
-    pStack = pRAM + 0x100;
-    return 1;
-}
-
-/*
- *  LoadNSF
- */
-
-int LoadNSF(int32_t datasize)
-{
-    if(!pDataBuffer)                return 0;
-
-    int32_t i;
-
-    nExternalSound = nChipExtensions;
-    if(nIsPal & 2)
-        bPALMode = bPALPreference;
-    else
-        bPALMode = nIsPal & 1;
-
-    SetPlaybackOptions(nSampleRate);
-    
-    int32_t neededsize = datasize + (nfileLoadAddress & 0x0FFF);
-    if(neededsize & 0x0FFF)     neededsize += 0x1000 - (neededsize & 0x0FFF);
-    if(neededsize < 0x1000)     neededsize = 0x1000;
-
-    uint8_t specialload = 0;
-    
-    for(i = 0; (i < 8) && (!nBankswitch[i]); i++);
-    if(i < 8)       /* uses bankswitching */
-    {
-        memcpy(&nBankswitchInitValues[2],nBankswitch,8);
-        nBankswitchInitValues[0] = nBankswitch[6];
-        nBankswitchInitValues[1] = nBankswitch[7];
-        if(nExternalSound & EXTSOUND_FDS)
-        {
-            if(!(nBankswitchInitValues[0] || nBankswitchInitValues[1]))
-            {
-                /*
-                 * FDS sound with '00' specified for both $6000 and $7000 banks.
-                 * point this to an area of fresh RAM (sort of hackish solution
-                 * for those FDS tunes that don't quite follow the nsf specs.
-                 */
-                nBankswitchInitValues[0] = (uint8_t)(neededsize >> 12);
-                nBankswitchInitValues[1] = (uint8_t)(neededsize >> 12) + 1;
-                neededsize += 0x2000;
-            }
-        }
-    }
-    else            /* doesn't use bankswitching */
-    {
-        if(nExternalSound & EXTSOUND_FDS)
-        {
-            /* bad load address */
-            if(nfileLoadAddress < 0x6000)       return 0;
-
-            if(neededsize < 0xA000)
-                neededsize = 0xA000;
-            specialload = 1;
-            for(i = 0; i < 10; i++)
-                nBankswitchInitValues[i] = (uint8_t)i;
-        }
-        else
-        {
-            /* bad load address */
-            if(nfileLoadAddress < 0x8000)       return 0;
-
-            int32_t j = (nfileLoadAddress >> 12) - 6;
-            for(i = 0; i < j; i++)
-                nBankswitchInitValues[i] = 0;
-            for(j = 0; i < 10; i++, j++)
-                nBankswitchInitValues[i] = (uint8_t)j;
-        }
-    }
-
-    nROMSize = neededsize;
-    nROMBankCount = neededsize >> 12;
-
-    if(specialload)
-        pROM_Full = pDataBuffer-(nfileLoadAddress-0x6000);
-    else
-        pROM_Full = pDataBuffer-(nfileLoadAddress&0x0FFF);
-
-    ZEROMEMORY(pRAM,0x0800);
-    ZEROMEMORY(pExRAM,0x1000);
-    ZEROMEMORY(pSRAM,0x2000);
-
-    nExternalSound = nChipExtensions;
-    fNSFPlaybackSpeed = (bPALMode ? PAL_NMIRATE : NTSC_NMIRATE);
-    
-    SetPlaybackSpeed(0);
-
-    nPlayAddress = nfilePlayAddress;
-    nInitAddress = nfileInitAddress;
-
-    pExRAM[0x00] = 0x20;                        /* JSR */
-    pExRAM[0x01] = nInitAddress&0xff;           /* Init Address */
-    pExRAM[0x02] = (nInitAddress>>8)&0xff;
-    pExRAM[0x03] = 0xF2;                        /* JAM */
-    pExRAM[0x04] = 0x20;                        /* JSR */
-    pExRAM[0x05] = nPlayAddress&0xff;           /* Play Address */
-    pExRAM[0x06] = (nPlayAddress>>8)&0xff;
-    pExRAM[0x07] = 0x4C;                        /* JMP */
-    pExRAM[0x08] = 0x03;/* $5003  (JAM right before the JSR to play address) */
-    pExRAM[0x09] = 0x50;
-
-    regA = regX = regY = 0;
-    regP = 0x04;            /* I_FLAG */
-    regSP = 0xFF;
-
-    nFilterAccL = 0;
-
-    /*  Reset Read/Write Procs          */
-    
-    ReadMemory[0] = ReadMemory[1] = ReadMemory_RAM;
-    ReadMemory[2] = ReadMemory[3] = ReadMemory_Default;
-    ReadMemory[4] =                 ReadMemory_pAPU;
-    ReadMemory[5] =                 ReadMemory_ExRAM;
-    ReadMemory[6] = ReadMemory[7] = ReadMemory_SRAM;
-
-    WriteMemory[0] = WriteMemory[1] =   WriteMemory_RAM;
-    WriteMemory[2] = WriteMemory[3] =   WriteMemory_Default;
-    WriteMemory[4] =                    WriteMemory_pAPU;
-    WriteMemory[5] =                    WriteMemory_ExRAM;
-    WriteMemory[6] = WriteMemory[7] =   WriteMemory_SRAM;
-
-    for(i = 8; i < 16; i++)
-    {
-        ReadMemory[i] = ReadMemory_ROM;
-        WriteMemory[i] = WriteMemory_Default;
-    }
-
-    if(nExternalSound & EXTSOUND_FDS)
-    {
-        WriteMemory[0x06] = WriteMemory_FDSRAM;
-        WriteMemory[0x07] = WriteMemory_FDSRAM;
-        WriteMemory[0x08] = WriteMemory_FDSRAM;
-        WriteMemory[0x09] = WriteMemory_FDSRAM;
-        WriteMemory[0x0A] = WriteMemory_FDSRAM;
-        WriteMemory[0x0B] = WriteMemory_FDSRAM;
-        WriteMemory[0x0C] = WriteMemory_FDSRAM;
-        WriteMemory[0x0D] = WriteMemory_FDSRAM;
-        ReadMemory[0x06] = ReadMemory_ROM;
-        ReadMemory[0x07] = ReadMemory_ROM;
-    }
-
-    if(!bPALMode)   /* no expansion sound available on a PAL system */
-    {
-        if(nExternalSound & EXTSOUND_VRC6)
-        {
-            /* if both VRC6+VRC7... it MUST go to WriteMemory_VRC6
-             * or register writes will be lost (WriteMemory_VRC6 calls
-             * WriteMemory_VRC7 if needed) */
-            WriteMemory[0x09] = WriteMemory_VRC6;   
-            WriteMemory[0x0A] = WriteMemory_VRC6;   
-            WriteMemory[0x0B] = WriteMemory_VRC6;   
-        }
-        if(nExternalSound & EXTSOUND_N106)
-        {
-            WriteMemory[0x04] = WriteMemory_N106;
-            ReadMemory[0x04] = ReadMemory_N106;
-            WriteMemory[0x0F] = WriteMemory_N106;
-        }
-        if(nExternalSound & EXTSOUND_FME07)
-        {
-            WriteMemory[0x0C] = WriteMemory_FME07;
-            WriteMemory[0x0E] = WriteMemory_FME07;
-        }
-    }
-    
-    /* MMC5 still has a multiplication reg that needs to be available on
-       PAL tunes */
-    if(nExternalSound & EXTSOUND_MMC5)
-        WriteMemory[0x05] = WriteMemory_MMC5;
-
-    return 1;
-}
-
-/*
- *  SetTrack
- */
-
-void SetTrack(uint8_t track)
-{
-    int32_t i;
-    
-    nCurTrack = track;
-
-    regPC = 0x5000;
-    regA = track;
-    regX = bPALMode;
-    regY = bCleanAXY ? 0 : 0xCD;
-    regSP = 0xFF;
-    if(bCleanAXY)
-        regP = 0x04;
-    bCPUJammed = 0;
-
-    nCPUCycle = nAPUCycle = 0;
-    nDMCPop_Prev = 0;
-    bDMCPop_Skip = 0;
-
-    for(i = 0x4000; i < 0x400F; i++)
-        WriteMemory_pAPU(i,0);
-    WriteMemory_pAPU(0x4010,0);
-    WriteMemory_pAPU(0x4012,0);
-    WriteMemory_pAPU(0x4013,0);
-    WriteMemory_pAPU(0x4014,0);
-    WriteMemory_pAPU(0x4015,0);
-    WriteMemory_pAPU(0x4015,0x0F);
-    WriteMemory_pAPU(0x4017,0);
-
-    for(i = 0; i < 10; i++)
-        WriteMemory_ExRAM(0x5FF6 + i,nBankswitchInitValues[i]);
-
-    ZEROMEMORY(pRAM,0x0800);
-    ZEROMEMORY(pSRAM,0x2000);
-    ZEROMEMORY(&pExRAM[0x10],0x0FF0);
-    bFade = 0;
-
-
-    nTicksUntilNextSample = nTicksPerSample;
-    nTicksUntilNextFrame =
-        (bPALMode ? PAL_FRAME_COUNTER_FREQ : NTSC_FRAME_COUNTER_FREQ)*0x10000;
-    nTicksUntilNextPlay = nTicksPerPlay;
-    nTotalPlays = 0;
-    
-    /*  Clear mixing vals   */
-    mWave_Squares.nMixL = 0;
-    mWave_TND.nMixL = 0;
-    mWave_VRC6Pulse[0].nMixL = 0;
-    mWave_VRC6Pulse[1].nMixL = 0;
-    mWave_VRC6Saw.nMixL = 0;
-
-    /*  Reset Tri/Noise/DMC */
-    mWave_TND.nTriStep = mWave_TND.nTriOutput = 0;
-    mWave_TND.nDMCOutput = 0;
-    mWave_TND.bNoiseRandomOut = 0;
-    mWave_Squares.nDutyCount[0] = mWave_Squares.nDutyCount[1] = 0;
-    mWave_TND.bDMCActive = 0;
-    mWave_TND.nDMCBytesRemaining = 0;
-    mWave_TND.bDMCSampleBufferEmpty = 1;
-    mWave_TND.bDMCDeltaSilent = 1;
-
-    /*  Reset VRC6  */
-    mWave_VRC6Pulse[0].nVolume = 0;
-    mWave_VRC6Pulse[1].nVolume = 0;
-    mWave_VRC6Saw.nAccumRate = 0;
-
-    /*  Reset N106  */
-    ZEROMEMORY(mWave_N106.nRAM,0x100);
-    ZEROMEMORY(mWave_N106.nVolume,8);
-    ZEROMEMORY(mWave_N106.nOutput,8);
-    ZEROMEMORY(mWave_N106.nMixL,32);
-
-    /*  Reset FME-07    */
-    mWave_FME07[0].nVolume = 0;
-    mWave_FME07[1].nVolume = 0;
-    mWave_FME07[2].nVolume = 0;
-
-    /*  Clear FDS crap      */
-
-    mWave_FDS.bEnvelopeEnable = 0;
-    mWave_FDS.nEnvelopeSpeed = 0xFF;
-    mWave_FDS.nVolEnv_Mode = 2;
-    mWave_FDS.nVolEnv_Decay = 0;
-    mWave_FDS.nVolEnv_Gain = 0;
-    mWave_FDS.nVolume = 0;
-    mWave_FDS.bVolEnv_On = 0;
-    mWave_FDS.nSweep_Mode = 2;
-    mWave_FDS.nSweep_Decay = 0;
-    mWave_FDS.nSweep_Gain = 0;
-    mWave_FDS.bSweepEnv_On = 0;
-    mWave_FDS.nSweepBias = 0;
-    mWave_FDS.bLFO_Enabled = 0;
-    mWave_FDS.nLFO_Freq.W = 0;
-/*    mWave_FDS.fLFO_Timer = 0;
-    mWave_FDS.fLFO_Count = 0;*/
-    mWave_FDS.nLFO_Timer = 0;
-    mWave_FDS.nLFO_Count = 0;
-    mWave_FDS.nLFO_Addr = 0;
-    mWave_FDS.bLFO_On = 0;
-    mWave_FDS.nMainVolume = 0;
-    mWave_FDS.bEnabled = 0;
-    mWave_FDS.nFreq.W = 0;
-/*    mWave_FDS.fFreqCount = 0;*/
-    mWave_FDS.nFreqCount = 0;
-    mWave_FDS.nMainAddr = 0;
-    mWave_FDS.bWaveWrite = 0;
-    mWave_FDS.bMain_On = 0;
-    mWave_FDS.nMixL = 0;
-    ZEROMEMORY(mWave_FDS.nWaveTable,0x40);
-    ZEROMEMORY(mWave_FDS.nLFO_Table,0x40);
-
-    mWave_FDS.nSweep_Count = mWave_FDS.nSweep_Timer =
-        ((mWave_FDS.nSweep_Decay + 1) * mWave_FDS.nEnvelopeSpeed * 8);
-    mWave_FDS.nVolEnv_Count = mWave_FDS.nVolEnv_Timer =
-        ((mWave_FDS.nVolEnv_Decay + 1) * mWave_FDS.nEnvelopeSpeed * 8);
-
-    nSilentSamples = 0;
-
-    nFilterAccL = 0;
-
-    nSilentSamples = 0;
-
-    fulltick=0;
-}
-
-/*
- *  SetPlaybackOptions
- */
-
-int SetPlaybackOptions(int32_t samplerate)
-{
-    if(samplerate < 2000)                   return 0;
-    if(samplerate > 96000)                  return 0;
-
-    nTicksPerSample =
-        (bPALMode ? PAL_FREQUENCY : NTSC_FREQUENCY) / samplerate * 0x10000;
-    nTicksUntilNextSample = nTicksPerSample;
-
-    RecalcFilter();
-    RecalcSilenceTracker();
-
-    return 1;
-}
-
-/*
- *  SetPlaybackSpeed
- */
-
-void SetPlaybackSpeed(float playspersec)
-{
-    if(playspersec < 1)
-    {
-        playspersec = fNSFPlaybackSpeed;
-    }
-
-    nTicksPerPlay = nTicksUntilNextPlay =
-        (bPALMode ? PAL_FREQUENCY : NTSC_FREQUENCY) / playspersec * 0x10000;
-}
-
-/*
-*   GetPlaybackSpeed
-*/
-
-float GetPlaybackSpeed()
-{
-    if(nTicksPerPlay <= 0)  return 0;
-    return ((bPALMode ? PAL_FREQUENCY : NTSC_FREQUENCY) / (nTicksPerPlay>>16));
-}
-
-/*
- *  RecalcFilter
- */
-
-void RecalcFilter()
-{
-    if(!nSampleRate) return;
-
-    nHighPass = ((int64_t)nHighPassBase << 16) / nSampleRate;
-
-    if(nHighPass > (1<<16)) nHighPass = 1<<16;
-}
-
-/*
- *  RecalcSilenceTracker
- */
-
-void RecalcSilenceTracker()
-{
-    if(nSilenceTrackMS <= 0 || !nSampleRate ||
-       (bNoSilenceIfTime && bTimeNotDefault))
-    {
-        nSilentSampleMax = 0;
-        return;
-    }
-
-    nSilentSampleMax = nSilenceTrackMS * nSampleRate / 500;
-    nSilentSampleMax /= 2;
-}
-
-void RebuildOutputTables(void) {
-    int32_t i,j;
-    float l[3];
-    int32_t temp;
-    float ftemp;
-    
-    /* tnd */
-    for(i = 0; i < 3; i++)
-    {
-        l[i] = 255;
-    }
-
-    for(i = 0; i < 0x8000; i++)
-    {
-        ftemp = (l[0] * (i >> 11)) / 2097885;
-        ftemp += (l[1] * ((i >> 7) & 0x0F)) / 3121455;
-        ftemp += (l[2] * (i & 0x7F)) / 5772690;
-
-        if(!ftemp)
-            main_nOutputTable_L[i] = 0;
-        else
-            main_nOutputTable_L[i] =
-                (int16_t)(2396850 / ((1.0f / ftemp) + 100));
-    }
-    
-    /* squares */
-    for(i = 0; i < 2; i++)
-    {
-        l[i] = 255;
-    }
-
-    for(j = 0; j < 0x10; j++)
-    {
-        for(i = 0; i < 0x10; i++)
-        {
-            temp = (int32_t)(l[0] * j);
-            temp += (int32_t)(l[1] * i);
-
-            if(!temp)
-                Squares_nOutputTable_L[j][i] = 0;
-            else
-                Squares_nOutputTable_L[j][i] = 1438200 / ((2072640 / temp) + 100);
-        }
-    }
-
-    /* VRC6 Pulse 1,2 */
-    for(i = 0; i < 0x10; i++)
-    {
-        VRC6Pulse_nOutputTable_L[i] =
-            1875 * i / 0x0F;
-    }
-    /* VRC6 Saw */
-    for(i = 0; i < 0x20; i++)
-    {
-        VRC6Saw_nOutputTable_L[i] = 3750 * i / 0x1F;
-    }
-
-    /* N106 channels */
-    /* this amplitude is just a guess */
-
-    for(i = 0; i < 0x10; i++)
-    {
-        for(j = 0; j < 0x10; j++)
-        {
-            N106_nOutputTable_L[i][j] = (3000 * i * j) / 0xE1;
-        }
-    }
-    
-    /* FME-07 Square A,B,C */
-    FME07_nOutputTable_L[15] = 3000;
-    FME07_nOutputTable_L[0] = 0;
-    for(i = 14; i > 0; i--)
-    {
-        FME07_nOutputTable_L[i] = FME07_nOutputTable_L[i + 1] * 80 / 100;
-    }
-
-    /*
-     *  FDS
-     */
-    /*  this base volume (4000) is just a guess to what sounds right.
-     *  Given the number of steps available in an FDS wave... it seems like
-     *  it should be much much more... but then it's TOO loud.
-     */
-    for(i = 0; i < 0x21; i++)
-    {
-        for(j = 0; j < 0x40; j++)
-        {
-            FDS_nOutputTable_L[0][i][j] =
-                (4000 * i * j * 30) / (0x21 * 0x40 * 30);
-            FDS_nOutputTable_L[1][i][j] =
-                (4000 * i * j * 20) / (0x21 * 0x40 * 30);
-            FDS_nOutputTable_L[2][i][j] =
-                (4000 * i * j * 15) / (0x21 * 0x40 * 30);
-            FDS_nOutputTable_L[3][i][j] =
-                (4000 * i * j * 12) / (0x21 * 0x40 * 30);
-        }
-    }
-}
-
-/*
- *  GetPlayCalls
- */
-
-float GetPlayCalls()
-{
-    if(!nTicksPerPlay)  return 0;
-
-    return ((float)nTotalPlays) +
-        (1.0f - (nTicksUntilNextPlay*1.0f / nTicksPerPlay));
-}
-
-/*
- *  GetWrittenTime
- */
-uint32_t GetWrittenTime(float basedplayspersec /* = 0 */)
-{
-    if(basedplayspersec <= 0)
-        basedplayspersec = GetPlaybackSpeed();
-
-    if(basedplayspersec <= 0)
-        return 0;
-
-    return (uint32_t)((GetPlayCalls() * 1000) / basedplayspersec);
-}
-
-/*
- *  StopFade
- */
-void StopFade()
-{
-    bFade = 0;
-    fFadeVolume = 1;
-}
-
-/*
- *  SongCompleted
- */
-
-uint8_t SongCompleted()
-{
-    if(!bFade)                      return 0;
-    if(nTotalPlays >= nEndFade)     return 1;
-    if(nSilentSampleMax)            return (nSilentSamples >= nSilentSampleMax);
-
-    return 0;
-}
-
-/*
- *  SetFade
- */
-
-void SetFade(int32_t fadestart,int32_t fadestop,
-             uint8_t bNotDefault) /* play routine calls */
-{
-    if(fadestart < 0)   fadestart = 0;
-    if(fadestop < fadestart) fadestop = fadestart;
-
-    nStartFade = (uint32_t)fadestart;
-    nEndFade = (uint32_t)fadestop;
-    bFade = 1;
-    bTimeNotDefault = bNotDefault;
-
-    RecalcSilenceTracker();
-    RecalculateFade();
-}
-
-/*
- *  SetFadeTime
- */
-
-void SetFadeTime(uint32_t fadestart,uint32_t fadestop,float basedplays,
-                 uint8_t bNotDefault) /* time in MS */
-{
-    if(basedplays <= 0)
-        basedplays = GetPlaybackSpeed();
-    if(basedplays <= 0)
-        return;
-
-    SetFade((int32_t)(fadestart * basedplays / 1000),
-           (int32_t)(fadestop * basedplays / 1000),bNotDefault);
-}
-
-/*
- *  RecalculateFade
- */
-
-void RecalculateFade()
-{
-    if(!bFade)  return;
-
-    /* make it hit silence a little before the song ends...
-       otherwise we're not really fading OUT, we're just fading umm...
-       quieter =P */
-    int32_t temp = (int32_t)(GetPlaybackSpeed() / 4);
-
-    if(nEndFade <= nStartFade)
-    {
-        nEndFade = nStartFade;
-        fFadeChange = 1.0f;
-    }
-    else if((nEndFade - temp) <= nStartFade)
-        fFadeChange = 1.0f;
-    else
-        fFadeChange = 1.0f / (nEndFade - nStartFade - temp);
-
-    if(nTotalPlays < nStartFade)
-        fFadeVolume = 1.0f;
-    else if(nTotalPlays >= nEndFade)
-        fFadeVolume = 0.0f;
-    else
-    {
-        fFadeVolume = 1.0f - ( (nTotalPlays - nStartFade + 1) * fFadeChange );
-        if(fFadeVolume < 0)
-            fFadeVolume = 0;
-    }
-
-}
-
-int32_t GetSamples(uint8_t* buffer,int32_t buffersize)
-{
-    if(!buffer)                             return 0;
-    if(buffersize < 16)                     return 0;
-    if(bFade && (nTotalPlays >= nEndFade))  return 0;
-    
-    pOutput = buffer;
-    uint32_t runtocycle =
-        (uint32_t)((buffersize / 2) * nTicksPerSample / 0x10000);
-    nCPUCycle = nAPUCycle = 0;
-    uint32_t tick;
-
-    while(1)
-    {
-        /*tick = (uint32_t)ceil(fTicksUntilNextPlay);*/
-        tick = (nTicksUntilNextPlay+0xffff)>>16;
-        if((tick + nCPUCycle) > runtocycle)
-            tick = runtocycle - nCPUCycle;
-
-        if(bCPUJammed)
-        {
-            nCPUCycle += tick;
-            EmulateAPU(0);
-        }
-        else
-        {
-            tick = Emulate6502(tick + nCPUCycle);
-            EmulateAPU(1);
-        }
-
-        nTicksUntilNextPlay -= tick<<16;
-        if(nTicksUntilNextPlay <= 0)
-        {
-            nTicksUntilNextPlay += nTicksPerPlay;
-            if((bCPUJammed == 2) || bNoWaitForReturn)
-            {
-                regX = regY = regA = (bCleanAXY ? 0 : 0xCD);
-                regPC = 0x5004;
-                nTotalPlays++;
-                bDMCPop_SamePlay = 0;
-                bCPUJammed = 0;
-                if(nForce4017Write == 1)    WriteMemory_pAPU(0x4017,0x00);
-                if(nForce4017Write == 2)    WriteMemory_pAPU(0x4017,0x80);
-            }
-            
-            if(bFade && (nTotalPlays >= nStartFade))
-            {
-                fFadeVolume -= fFadeChange;
-                if(fFadeVolume < 0)
-                    fFadeVolume = 0;
-                if(nTotalPlays >= nEndFade)
-                    break;
-            }
-        }
-
-        if(nCPUCycle >= runtocycle)
-            break;
-    }
-
-    nCPUCycle = nAPUCycle = 0;
-
-    if(nSilentSampleMax && bFade)
-    {
-        int16_t* tempbuf = (int16_t*)buffer;
-        while( ((uint8_t*)tempbuf) < pOutput)
-        {
-            if( (*tempbuf < -SILENCE_THRESHOLD) ||
-                (*tempbuf > SILENCE_THRESHOLD) )
-                nSilentSamples = 0;
-            else
-            {
-                if(++nSilentSamples >= nSilentSampleMax)
-                    return (int32_t)( ((uint8_t*)tempbuf) - buffer);
-            }
-            tempbuf++;
-        }
-    }
-
-    return (int32_t)(pOutput - buffer);
-}
-
-/****************** 6502 emulation ******************/
-
-/*  Memory reading/writing and other defines */
-
-/* reads zero page memory */
-#define     Zp(a)           pRAM[a]
-/* reads zero page memory in word form */
-#define     ZpWord(a)       (Zp(a) | (Zp((uint8_t)(a + 1)) << 8))
-/* reads memory */
-#define     Rd(a)           ((ReadMemory[((uint16_t)(a)) >> 12])(a))
-/* reads memory in word form */
-#define     RdWord(a)       (Rd(a) | (Rd(a + 1) << 8))
-/* writes memory */
-#define     Wr(a,v)         (WriteMemory[((uint16_t)(a)) >> 12])(a,v)
-/* writes zero paged memory */
-#define     WrZ(a,v)        pRAM[a] = v
-/* pushes a value onto the stack */
-#define     PUSH(v)         pStack[SP--] = v
-/* pulls a value from the stack */
-#define     PULL(v)         v = pStack[++SP]
-
-/*  Addressing Modes */
-
-/* first set - gets the value that's being addressed */
-/*Immediate*/
-#define Ad_VlIm()   val = Rd(PC.W); PC.W++
-/*Zero Page*/
-#define Ad_VlZp()   final.W = Rd(PC.W); val = Zp(final.W); PC.W++
-/*Zero Page, X*/
-#define Ad_VlZx()   front.W = final.W = Rd(PC.W); final.B.l += X;           \
-                    val = Zp(final.B.l); PC.W++
-/*Zero Page, Y*/
-#define Ad_VlZy()   front.W = final.W = Rd(PC.W); final.B.l += Y;           \
-                    val = Zp(final.B.l); PC.W++
-/*Absolute*/
-#define Ad_VlAb()   final.W = RdWord(PC.W); val = Rd(final.W); PC.W += 2
-/*Absolute, X [uses extra cycle if crossed page]*/
-#define Ad_VlAx()   front.W = final.W = RdWord(PC.W); final.W += X; PC.W += 2;\
-                    if(front.B.h != final.B.h) nCPUCycle++; val = Rd(final.W)
-/*Absolute, X [uses extra cycle if crossed page]*/
-#define Ad_VlAy()   front.W = final.W = RdWord(PC.W); final.W += Y; PC.W += 2;\
-                    if(front.B.h != final.B.h) nCPUCycle++; val = Rd(final.W)
-/*(Indirect, X)*/
-#define Ad_VlIx()   front.W = final.W = Rd(PC.W); final.B.l += X; PC.W++;   \
-                    final.W = ZpWord(final.B.l); val = Rd(final.W)
-/*(Indirect), Y [uses extra cycle if crossed page]*/
-#define Ad_VlIy()   val = Rd(PC.W); front.W = final.W = ZpWord(val); PC.W++;\
-                    final.W += Y; if(final.B.h != front.B.h) nCPUCycle++;    \
-                    front.W = val; val = Rd(final.W)
-
-/* second set - gets the ADDRESS that the mode is referring to (for operators
- *              that write to memory) note that AbsoluteX, AbsoluteY, and
- *              IndirectY modes do NOT check for page boundary crossing here
- *              since that extra cycle isn't added for operators that write to
- *              memory (it only applies to ones that only read from memory.. in
- *              which case the 1st set should be used)
- */
-/*Zero Page*/
-#define Ad_AdZp()   final.W = Rd(PC.W); PC.W++
-/*Zero Page, X*/
-#define Ad_AdZx()   final.W = front.W = Rd(PC.W); final.B.l += X; PC.W++
-/*Zero Page, Y*/
-#define Ad_AdZy()   final.W = front.W = Rd(PC.W); final.B.l += Y; PC.W++
-/*Absolute*/
-#define Ad_AdAb()   final.W = RdWord(PC.W); PC.W += 2
-/*Absolute, X*/
-#define Ad_AdAx()   front.W = final.W = RdWord(PC.W); PC.W += 2;            \
-                    final.W += X
-/*Absolute, Y*/
-#define Ad_AdAy()   front.W = final.W = RdWord(PC.W); PC.W += 2;            \
-                    final.W += Y
-/*(Indirect, X)*/
-#define Ad_AdIx()   front.W = final.W = Rd(PC.W); PC.W++; final.B.l += X;   \
-                    final.W = ZpWord(final.B.l)
-/*(Indirect), Y*/
-#define Ad_AdIy()   front.W = Rd(PC.W); final.W = ZpWord(front.W) + Y;      \
-                    PC.W++
-
-/* third set - reads memory, performs the desired operation on the value, then
- * writes back to memory
- *       used for operators that directly change memory (ASL, INC, DEC, etc)
- */
-/*Zero Page*/
-#define MRW_Zp(cmd) Ad_AdZp(); val = Zp(final.W); cmd(val); WrZ(final.W,val)
-/*Zero Page, X*/
-#define MRW_Zx(cmd) Ad_AdZx(); val = Zp(final.W); cmd(val); WrZ(final.W,val)
-/*Zero Page, Y*/
-#define MRW_Zy(cmd) Ad_AdZy(); val = Zp(final.W); cmd(val); WrZ(final.W,val)
-/*Absolute*/
-#define MRW_Ab(cmd) Ad_AdAb(); val = Rd(final.W); cmd(val); Wr(final.W,val)
-/*Absolute, X*/
-#define MRW_Ax(cmd) Ad_AdAx(); val = Rd(final.W); cmd(val); Wr(final.W,val)
-/*Absolute, Y*/
-#define MRW_Ay(cmd) Ad_AdAy(); val = Rd(final.W); cmd(val); Wr(final.W,val)
-/*(Indirect, X)*/
-#define MRW_Ix(cmd) Ad_AdIx(); val = Rd(final.W); cmd(val); Wr(final.W,val)
-/*(Indirect), Y*/
-#define MRW_Iy(cmd) Ad_AdIy(); val = Rd(final.W); cmd(val); Wr(final.W,val)
-
-/* Relative modes are special in that they're only used by branch commands
- *  this macro handles the jump, and should only be called if the branch
- *  condition was true if the branch condition was false, the PC must be
- *  incremented
- */
-
-#define RelJmp(cond)    val = Rd(PC.W); PC.W++; final.W = PC.W + (int8_t)(val);\
-                        if(cond) {\
-                        nCPUCycle += ((final.B.h != PC.B.h) ? 2 : 1);\
-                        PC.W = final.W; }
-
-/* Status Flags */
-
-#define     C_FLAG      0x01    /* carry flag */
-#define     Z_FLAG      0x02    /* zero flag */
-#define     I_FLAG      0x04    /* mask interrupt flag */
-#define     D_FLAG      0x08    /* decimal flag (decimal mode is unsupported on
-                                   NES) */
-#define     B_FLAG      0x10    /* break flag (not really in the status register
-                                   It's value in ST is never used.  When ST is
-                                   put in memory (by an interrupt or PHP), this
-                                   flag is set only if BRK was called)
-                                   ** also when PHP is called due to a bug */
-#define     R_FLAG      0x20    /* reserved flag (not really in the register.
-                                   It's value is never used.
-                                   Whenever ST is put in memory,
-                                   this flag is always set) */
-#define     V_FLAG      0x40    /* overflow flag */
-#define     N_FLAG      0x80    /* sign flag */
-
-
-/*  Lookup Tables */
-
-/* the number of CPU cycles used for each instruction */
-static const uint8_t CPU_Cycles[0x100] = {
-7,6,0,8,3,3,5,5,3,2,2,2,4,4,6,6,
-2,5,0,8,4,4,6,6,2,4,2,7,4,4,7,7,
-6,6,0,8,3,3,5,5,4,2,2,2,4,4,6,6,
-2,5,0,8,4,4,6,6,2,4,2,7,4,4,7,7,
-6,6,0,8,3,3,5,5,3,2,2,2,3,4,6,6,
-2,5,0,8,4,4,6,6,2,4,2,7,4,4,7,7,
-6,6,0,8,3,3,5,5,4,2,2,2,5,4,6,6,
-2,5,0,8,4,4,6,6,2,4,2,7,4,4,7,7,
-2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4,
-2,6,0,6,4,4,4,4,2,5,2,5,5,5,5,5,
-2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4,
-2,5,0,5,4,4,4,4,2,4,2,4,4,4,4,4,
-2,6,2,8,3,3,5,5,2,2,2,2,4,4,6,6,
-2,5,0,8,4,4,6,6,2,4,2,7,4,4,7,7,
-2,6,2,8,3,3,5,5,2,2,2,2,4,4,6,6,
-2,5,0,8,4,4,6,6,2,4,2,7,4,4,7,7     };
-
-/* the status of the NZ flags for the given value */
-static const uint8_t NZTable[0x100] = {
-Z_FLAG,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,
-N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,
-N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,
-N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,
-N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,
-N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,
-N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,
-N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,
-N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,
-N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,
-N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,
-N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,
-N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG };
-
-/* A quick macro for working with the above table */
-#define UpdateNZ(v) ST = (ST & ~(N_FLAG|Z_FLAG)) | NZTable[v]
-
-
-/*
- *  Opcodes
- *
- *      These opcodes perform the action with the given value (changing that
- *  value if necessary).  Registers and flags associated with the operation
- *  are changed accordingly.  There are a few exceptions which will be noted
- *  when they arise
- */
-
-
-/*  ADC
-        Adds the value to the accumulator with carry
-        Changes:  A, NVZC
-        - Decimal mode not supported on the NES
-        - Due to a bug, NVZ flags are not altered if the Decimal flag is on
-          --(taken out)-- */
-#define ADC()                                                           \
-    tw.W = A + val + (ST & C_FLAG);                                     \
-    ST = (ST & (I_FLAG|D_FLAG)) | tw.B.h | NZTable[tw.B.l] |            \
-        ( (0x80 & ~(A ^ val) & (A ^ tw.B.l)) ? V_FLAG : 0 );            \
-    A = tw.B.l
-
-/*  AND
-        Combines the value with the accumulator using a bitwise AND operation
-        Changes:  A, NZ     */
-#define AND()                                                           \
-    A &= val;                                                           \
-    UpdateNZ(A)
-
-/*  ASL
-        Left shifts the value 1 bit.  The bit that gets shifted out goes to
-        the carry flag.
-        Changes:  value, NZC        */
-#define ASL(value)                                                      \
-    tw.W = value << 1;                                                  \
-    ST = (ST & ~(N_FLAG|Z_FLAG|C_FLAG)) | tw.B.h | NZTable[tw.B.l];     \
-    value = tw.B.l
-
-/*  BIT
-        Compares memory with the accumulator with an AND operation, but changes
-        neither.
-        The two high bits of memory get transferred to the status reg
-        Z is set if the AND operation yielded zero, otherwise it's cleared
-        Changes:  NVZ               */
-#define BIT()                                                           \
-    ST = (ST & ~(N_FLAG|V_FLAG|Z_FLAG)) | (val & (N_FLAG|V_FLAG)) |     \
-            ((A & val) ? 0 : Z_FLAG)
-
-/*  CMP, CPX, CPY
-        Compares memory with the given register with a subtraction operation.
-        Flags are set accordingly depending on the result:
-        Reg < Memory:  Z=0, C=0
-        Reg = Memory:  Z=1, C=1
-        Reg > Memory:  Z=0, C=1
-        N is set according to the result of the subtraction operation
-        Changes:  NZC
-
-        NOTE -- CMP, CPX, CPY all share this same routine, so the desired
-                register (A, X, or Y respectively) must be given when calling
-                this macro... as well as the memory to compare it with. */
-#define CMP(reg)                                                        \
-    tw.W = reg - val;                                                   \
-    ST = (ST & ~(N_FLAG|Z_FLAG|C_FLAG)) | (tw.B.h ? 0 : C_FLAG) |       \
-            NZTable[tw.B.l]
-
-/*  DEC, DEX, DEY
-        Decriments a value by one.
-        Changes:  value, NZ             */
-#define DEC(value)                                                      \
-    value--;                                                            \
-    UpdateNZ(value)
-
-/*  EOR
-        Combines a value with the accumulator using a bitwise exclusive-OR
-        operation
-        Changes:  A, NZ                 */
-#define EOR()                                                           \
-    A ^= val;                                                           \
-    UpdateNZ(A)
-
-/*  INC, INX, INY
-        Incriments a value by one.
-        Changes:  value, NZ             */
-#define INC(value)                                                      \
-    value++;                                                            \
-    UpdateNZ(value)
-
-/*  LSR
-        Shifts value one bit to the right.  Bit that gets shifted out goes to
-        the Carry flag.
-        Changes:  value, NZC            */
-#define LSR(value)                                                      \
-    tw.W = value >> 1;                                                  \
-    ST = (ST & ~(N_FLAG|Z_FLAG|C_FLAG)) | NZTable[tw.B.l] |             \
-        (value & 0x01);                                                 \
-    value = tw.B.l
-
-/*  ORA
-        Combines a value with the accumulator using a bitwise inclusive-OR
-        operation
-        Changes:  A, NZ                 */
-#define ORA()                                                           \
-    A |= val;                                                           \
-    UpdateNZ(A)
-
-/*  ROL
-        Rotates a value one bit to the left:
-        C <-   7<-6<-5<-4<-3<-2<-1<-0    <- C
-        Changes:  value, NZC            */
-#define ROL(value)                                                      \
-    tw.W = (value << 1) | (ST & 0x01);                                  \
-    ST = (ST & ~(N_FLAG|Z_FLAG|C_FLAG)) | NZTable[tw.B.l] | tw.B.h;     \
-    value = tw.B.l
-
-/*  ROR
-        Rotates a value one bit to the right:
-        C ->   7->6->5->4->3->2->1->0   -> C
-        Changes:  value, NZC            */
-#define ROR(value)                                                      \
-    tw.W = (value >> 1) | (ST << 7);                                    \
-    ST = (ST & ~(N_FLAG|Z_FLAG|C_FLAG)) | NZTable[tw.B.l] |             \
-        (value & 0x01);                                                 \
-    value = tw.B.l
-
-/*  SBC
-        Subtracts a value from the accumulator with borrow (inverted carry)
-        Changes:  A, NVZC
-        - Decimal mode not supported on the NES
-        - Due to a bug, NVZ flags are not altered if the Decimal flag is on
-           --(taken out)-- */
-#define SBC()                                                               \
-    tw.W = A - val - ((ST & C_FLAG) ? 0 : 1);                               \
-    ST = (ST & (I_FLAG|D_FLAG)) | (tw.B.h ? 0 : C_FLAG) | NZTable[tw.B.l] | \
-                    (((A ^ val) & (A ^ tw.B.l) & 0x80) ? V_FLAG : 0);       \
-    A = tw.B.l
-
-/*  Undocumented Opcodes
- *
- *      These opcodes are not included in the official specifications.  However,
- *  some of the unused opcode values perform operations which have since been
- *  documented.
- */
-
-
-/*  ASO
-        Left shifts a value, then ORs the result with the accumulator
-        Changes:  value, A, NZC                                         */
-#define ASO(value)                                                      \
-    tw.W = value << 1;                                                  \
-    A |= tw.B.l;                                                        \
-    ST = (ST & ~(N_FLAG|Z_FLAG|C_FLAG)) | NZTable[A] | tw.B.h;          \
-    value = tw.B.l
-
-/*  RLA
-        Roll memory left 1 bit, then AND the result with the accumulator
-        Changes:  value, A, NZC                                         */
-#define RLA(value)                                                      \
-    tw.W = (value << 1) | (ST & 0x01);                                  \
-    A &= tw.B.l;                                                        \
-    ST = (ST & ~(N_FLAG|Z_FLAG|C_FLAG)) | NZTable[A] | tw.B.h;          \
-    value = tw.B.l
-
-/*  LSE
-        Right shifts a value one bit, then EORs the result with the accumulator
-        Changes:  value, A, NZC                                         */
-#define LSE(value)                                                      \
-    tw.W = value >> 1;                                                  \
-    A ^= tw.B.l;                                                        \
-    ST = (ST & ~(N_FLAG|Z_FLAG|C_FLAG)) | NZTable[A] | (value & 0x01);  \
-    value = tw.B.l
-
-/*  RRA
-        Roll memory right one bit, then ADC the result
-        Changes:  value, A, NVZC                                        */
-#define RRA(value)                                                      \
-    tw.W = (value >> 1) | (ST << 7);                                    \
-    ST = (ST & ~C_FLAG) | (value & 0x01);                               \
-    value = tw.B.l;                                                     \
-    ADC()
-
-/*  AXS
-        ANDs the contents of the X and A registers and stores the result
-        int memory.
-        Changes:  value  [DOES NOT CHANGE X, A, or any flags]           */
-#define AXS(value)                                                      \
-    value = A & X
-
-/*  DCM
-        Decriments a value and compares it with the A register.
-        Changes:  value, NZC                                            */
-#define DCM(value)                                                          \
-    value--;                                                                \
-    CMP(A)
-
-/*  INS
-        Incriments a value then SBCs it
-        Changes:  value, A, NVZC                                        */
-#define INS(value)                                                      \
-    value++;                                                            \
-    SBC()
-
-/*  AXA     */
-#define AXA(value)                                                      \
-    value = A & X & (Rd(PC.W - 1) + 1)
-
-
-/* The 6502 emulation function! */
-
-union TWIN front;
-union TWIN final;
-uint8_t val;
-uint8_t op;
-
-uint32_t Emulate6502(uint32_t runto)
-{
-    /* If the CPU is jammed... don't bother */
-    if(bCPUJammed == 1)
-        return 0;
-
-    register union TWIN tw;     /* used in calculations */
-    register uint8_t    ST = regP;
-    register union TWIN PC;
-    uint8_t         SP = regSP;
-    register uint8_t    A = regA;
-    register uint8_t    X = regX;
-    register uint8_t    Y = regY;
-    union TWIN          front;
-    union TWIN          final;
-    PC.W = regPC;
-
-    uint32_t ret = nCPUCycle;
-    
-    ENTER_TIMER(cpu);
-    
-    /*  Start the loop */
-    
-    while(nCPUCycle < runto)
-    {
-        op = Rd(PC.W);
-        PC.W++;
-
-        nCPUCycle += CPU_Cycles[op];
-        switch(op)
-        {
-            /* Documented Opcodes first */
-            
-        /*  Flag setting/clearing */
-        case 0x18:  ST &= ~C_FLAG;  break;      /* CLC  */
-        case 0x38:  ST |=  C_FLAG;  break;      /* SEC  */
-        case 0x58:  ST &= ~I_FLAG;  break;      /* CLI  */
-        case 0x78:  ST |=  I_FLAG;  break;      /* SEI  */
-        case 0xB8:  ST &= ~V_FLAG;  break;      /* CLV  */
-        case 0xD8:  ST &= ~D_FLAG;  break;      /* CLD  */
-        case 0xF8:  ST |=  D_FLAG;  break;      /* SED  */
-
-        /* Branch commands */
-        case 0x10:  RelJmp(!(ST & N_FLAG)); break;  /* BPL  */
-        case 0x30:  RelJmp( (ST & N_FLAG)); break;  /* BMI  */
-        case 0x50:  RelJmp(!(ST & V_FLAG)); break;  /* BVC  */
-        case 0x70:  RelJmp( (ST & V_FLAG)); break;  /* BVS  */
-        case 0x90:  RelJmp(!(ST & C_FLAG)); break;  /* BCC  */
-        case 0xB0:  RelJmp( (ST & C_FLAG)); break;  /* BCS  */
-        case 0xD0:  RelJmp(!(ST & Z_FLAG)); break;  /* BNE  */
-        case 0xF0:  RelJmp( (ST & Z_FLAG)); break;  /* BEQ  */
-
-        /* Direct stack alteration commands (push/pull commands) */
-        case 0x08:  PUSH(ST | R_FLAG | B_FLAG); break;  /* PHP  */
-        case 0x28:  PULL(ST);                   break;  /* PLP  */
-        case 0x48:  PUSH(A);                    break;  /* PHA  */
-        case 0x68:  PULL(A); UpdateNZ(A);       break;  /* PLA  */
-
-        /* Register Transfers */
-        case 0x8A:  A = X;  UpdateNZ(A);    break;  /* TXA  */
-        case 0x98:  A = Y;  UpdateNZ(A);    break;  /* TYA  */
-        case 0x9A:  SP = X;                 break;  /* TXS  */
-        case 0xA8:  Y = A;  UpdateNZ(A);    break;  /* TAY  */
-        case 0xAA:  X = A;  UpdateNZ(A);    break;  /* TAX  */
-        case 0xBA:  X = SP; UpdateNZ(X);    break;  /* TSX  */
-
-        /*  Other commands */
-
-        /* ADC  */
-        case 0x61:  Ad_VlIx();  ADC();  break;
-        case 0x65:  Ad_VlZp();  ADC();  break;
-        case 0x69:  Ad_VlIm();  ADC();  break;
-        case 0x6D:  Ad_VlAb();  ADC();  break;
-        case 0x71:  Ad_VlIy();  ADC();  break;
-        case 0x75:  Ad_VlZx();  ADC();  break;
-        case 0x79:  Ad_VlAy();  ADC();  break;
-        case 0x7D:  Ad_VlAx();  ADC();  break;
-
-        /* AND  */
-        case 0x21:  Ad_VlIx();  AND();  break;
-        case 0x25:  Ad_VlZp();  AND();  break;
-        case 0x29:  Ad_VlIm();  AND();  break;
-        case 0x2D:  Ad_VlAb();  AND();  break;
-        case 0x31:  Ad_VlIy();  AND();  break;
-        case 0x35:  Ad_VlZx();  AND();  break;
-        case 0x39:  Ad_VlAy();  AND();  break;
-        case 0x3D:  Ad_VlAx();  AND();  break;
-
-        /* ASL  */
-        case 0x0A:  ASL(A);             break;
-        case 0x06:  MRW_Zp(ASL);        break;
-        case 0x0E:  MRW_Ab(ASL);        break;
-        case 0x16:  MRW_Zx(ASL);        break;
-        case 0x1E:  MRW_Ax(ASL);        break;
-
-        /* BIT  */
-        case 0x24:  Ad_VlZp();  BIT();  break;
-        case 0x2C:  Ad_VlAb();  BIT();  break;
-
-        /* BRK  */
-        case 0x00:
-            if(bIgnoreBRK)
-                break;
-            PC.W++;                     /*BRK has a padding byte*/
-            PUSH(PC.B.h);               /*push high byte of the return address*/
-            PUSH(PC.B.l);               /*push low byte of return address*/
-            PUSH(ST | R_FLAG | B_FLAG); /*push processor status with R|B flags*/
-            ST |= I_FLAG;               /*mask interrupts*/
-            PC.W = RdWord(0xFFFE);      /*read the IRQ vector and jump to it*/
-
-            /* extra check to make sure we didn't hit an infinite BRK loop */
-            if(!Rd(PC.W))                   /* next command will be BRK */
-            {
-                /* the CPU will endlessly loop...
-                   just jam it to ease processing power */
-                bCPUJammed = 1;
-                goto jammed;
-            }
-            break;
-
-        /* CMP  */
-        case 0xC1:  Ad_VlIx();  CMP(A); break;
-        case 0xC5:  Ad_VlZp();  CMP(A); break;
-        case 0xC9:  Ad_VlIm();  CMP(A); break;
-        case 0xCD:  Ad_VlAb();  CMP(A); break;
-        case 0xD1:  Ad_VlIy();  CMP(A); break;
-        case 0xD5:  Ad_VlZx();  CMP(A); break;
-        case 0xD9:  Ad_VlAy();  CMP(A); break;
-        case 0xDD:  Ad_VlAx();  CMP(A); break;
-
-        /* CPX  */
-        case 0xE0:  Ad_VlIm();  CMP(X); break;
-        case 0xE4:  Ad_VlZp();  CMP(X); break;
-        case 0xEC:  Ad_VlAb();  CMP(X); break;
-
-        /* CPY  */
-        case 0xC0:  Ad_VlIm();  CMP(Y); break;
-        case 0xC4:  Ad_VlZp();  CMP(Y); break;
-        case 0xCC:  Ad_VlAb();  CMP(Y); break;
-
-        /* DEC  */
-        case 0xCA:  DEC(X);             break;      /* DEX  */
-        case 0x88:  DEC(Y);             break;      /* DEY  */
-        case 0xC6:  MRW_Zp(DEC);        break;
-        case 0xCE:  MRW_Ab(DEC);        break;
-        case 0xD6:  MRW_Zx(DEC);        break;
-        case 0xDE:  MRW_Ax(DEC);        break;
-
-        /* EOR  */
-        case 0x41:  Ad_VlIx();  EOR();  break;
-        case 0x45:  Ad_VlZp();  EOR();  break;
-        case 0x49:  Ad_VlIm();  EOR();  break;
-        case 0x4D:  Ad_VlAb();  EOR();  break;
-        case 0x51:  Ad_VlIy();  EOR();  break;
-        case 0x55:  Ad_VlZx();  EOR();  break;
-        case 0x59:  Ad_VlAy();  EOR();  break;
-        case 0x5D:  Ad_VlAx();  EOR();  break;
-
-        /* INC  */
-        case 0xE8:  INC(X);             break;      /* INX  */
-        case 0xC8:  INC(Y);             break;      /* INY  */
-        case 0xE6:  MRW_Zp(INC);        break;
-        case 0xEE:  MRW_Ab(INC);        break;
-        case 0xF6:  MRW_Zx(INC);        break;
-        case 0xFE:  MRW_Ax(INC);        break;
-
-        /* JMP  */
-        /* Absolute JMP */
-        case 0x4C:  final.W = RdWord(PC.W);  PC.W = final.W; val = 0;   break;
-        /* Indirect JMP -- must take caution:
-           Indirection at 01FF will read from 01FF and 0100 (not 0200) */
-        case 0x6C:  front.W = final.W = RdWord(PC.W);
-                    PC.B.l = Rd(final.W); final.B.l++;
-                    PC.B.h = Rd(final.W); final.W = PC.W;
-                    break;      
-        /* JSR  */
-        case 0x20:
-            val = 0;
-            final.W = RdWord(PC.W);
-            PC.W++;         /* JSR only increments the return address by one.
-                               It's incremented again upon RTS */
-            PUSH(PC.B.h);   /* push high byte of return address */
-            PUSH(PC.B.l);   /* push low byte of return address */
-            PC.W = final.W;
-            break;
-
-        /* LDA  */
-        case 0xA1:  Ad_VlIx(); A = val; UpdateNZ(A);    break;
-        case 0xA5:  Ad_VlZp(); A = val; UpdateNZ(A);    break;
-        case 0xA9:  Ad_VlIm(); A = val; UpdateNZ(A);    break;
-        case 0xAD:  Ad_VlAb(); A = val; UpdateNZ(A);    break;
-        case 0xB1:  Ad_VlIy(); A = val; UpdateNZ(A);    break;
-        case 0xB5:  Ad_VlZx(); A = val; UpdateNZ(A);    break;
-        case 0xB9:  Ad_VlAy(); A = val; UpdateNZ(A);    break;
-        case 0xBD:  Ad_VlAx(); A = val; UpdateNZ(A);    break;
-
-        /* LDX  */
-        case 0xA2:  Ad_VlIm(); X = val; UpdateNZ(X);    break;
-        case 0xA6:  Ad_VlZp(); X = val; UpdateNZ(X);    break;
-        case 0xAE:  Ad_VlAb(); X = val; UpdateNZ(X);    break;
-        case 0xB6:  Ad_VlZy(); X = val; UpdateNZ(X);    break;
-        case 0xBE:  Ad_VlAy(); X = val; UpdateNZ(X);    break;
-
-        /* LDY  */
-        case 0xA0:  Ad_VlIm(); Y = val; UpdateNZ(Y);    break;
-        case 0xA4:  Ad_VlZp(); Y = val; UpdateNZ(Y);    break;
-        case 0xAC:  Ad_VlAb(); Y = val; UpdateNZ(Y);    break;
-        case 0xB4:  Ad_VlZx(); Y = val; UpdateNZ(Y);    break;
-        case 0xBC:  Ad_VlAx(); Y = val; UpdateNZ(Y);    break;
-
-        /* LSR  */
-        case 0x4A:  LSR(A);             break;
-        case 0x46:  MRW_Zp(LSR);        break;
-        case 0x4E:  MRW_Ab(LSR);        break;
-        case 0x56:  MRW_Zx(LSR);        break;
-        case 0x5E:  MRW_Ax(LSR);        break;
-
-        /* NOP  */
-        case 0xEA:
-
-        /* --- Undocumented ---
-            These opcodes perform the same action as NOP    */
-        case 0x1A:  case 0x3A:  case 0x5A:
-        case 0x7A:  case 0xDA:  case 0xFA:      break;
-
-        /* ORA  */
-        case 0x01:  Ad_VlIx();  ORA();  break;
-        case 0x05:  Ad_VlZp();  ORA();  break;
-        case 0x09:  Ad_VlIm();  ORA();  break;
-        case 0x0D:  Ad_VlAb();  ORA();  break;
-        case 0x11:  Ad_VlIy();  ORA();  break;
-        case 0x15:  Ad_VlZx();  ORA();  break;
-        case 0x19:  Ad_VlAy();  ORA();  break;
-        case 0x1D:  Ad_VlAx();  ORA();  break;
-
-        /* ROL  */
-        case 0x2A:  ROL(A);             break;
-        case 0x26:  MRW_Zp(ROL);        break;
-        case 0x2E:  MRW_Ab(ROL);        break;
-        case 0x36:  MRW_Zx(ROL);        break;
-        case 0x3E:  MRW_Ax(ROL);        break;
-
-        /* ROR  */
-        case 0x6A:  ROR(A);             break;
-        case 0x66:  MRW_Zp(ROR);        break;
-        case 0x6E:  MRW_Ab(ROR);        break;
-        case 0x76:  MRW_Zx(ROR);        break;
-        case 0x7E:  MRW_Ax(ROR);        break;
-
-        /* RTI  */
-        case 0x40:
-            PULL(ST);                   /*pull processor status*/
-            PULL(PC.B.l);               /*pull low byte of return address*/
-            PULL(PC.B.h);               /*pull high byte of return address*/
-            break;
-
-        /* RTS  */
-        case 0x60:
-            PULL(PC.B.l);
-            PULL(PC.B.h);
-            PC.W++; /* the return address is one less of what it needs */
-            break;
-
-        /* SBC  */
-        case 0xE1:  Ad_VlIx();  SBC();  break;
-        case 0xE5:  Ad_VlZp();  SBC();  break;
-        /* - Undocumented -  EB performs the same operation as SBC immediate */
-        case 0xEB:
-        case 0xE9:  Ad_VlIm();  SBC();  break;
-        case 0xED:  Ad_VlAb();  SBC();  break;
-        case 0xF1:  Ad_VlIy();  SBC();  break;
-        case 0xF5:  Ad_VlZx();  SBC();  break;
-        case 0xF9:  Ad_VlAy();  SBC();  break;
-        case 0xFD:  Ad_VlAx();  SBC();  break;
-
-        /* STA  */
-        case 0x81:  Ad_AdIx(); val = A; Wr(final.W,A);  break;
-        case 0x85:  Ad_AdZp(); val = A; WrZ(final.W,A); break;
-        case 0x8D:  Ad_AdAb(); val = A; Wr(final.W,A);  break;
-        case 0x91:  Ad_AdIy(); val = A; Wr(final.W,A);  break;
-        case 0x95:  Ad_AdZx(); val = A; WrZ(final.W,A); break;
-        case 0x99:  Ad_AdAy(); val = A; Wr(final.W,A);  break;
-        case 0x9D:  Ad_AdAx(); val = A; Wr(final.W,A);  break;
-
-        /* STX  */
-        case 0x86:  Ad_AdZp(); val = X; WrZ(final.W,X); break;
-        case 0x8E:  Ad_AdAb(); val = X; Wr(final.W,X);  break;
-        case 0x96:  Ad_AdZy(); val = X; WrZ(final.W,X); break;
-
-        /* STY  */
-        case 0x84:  Ad_AdZp(); val = Y; WrZ(final.W,Y); break;
-        case 0x8C:  Ad_AdAb(); val = Y; Wr(final.W,Y);  break;
-        case 0x94:  Ad_AdZx(); val = Y; WrZ(final.W,Y); break;
-
-        /*  Undocumented Opcodes */
-        /* ASO  */
-        case 0x03:  if(bIgnoreIllegalOps) break;    MRW_Ix(ASO);    break;
-        case 0x07:  if(bIgnoreIllegalOps) break;    MRW_Zp(ASO);    break;
-        case 0x0F:  if(bIgnoreIllegalOps) break;    MRW_Ab(ASO);    break;
-        case 0x13:  if(bIgnoreIllegalOps) break;    MRW_Iy(ASO);    break;
-        case 0x17:  if(bIgnoreIllegalOps) break;    MRW_Zx(ASO);    break;
-        case 0x1B:  if(bIgnoreIllegalOps) break;    MRW_Ay(ASO);    break;
-        case 0x1F:  if(bIgnoreIllegalOps) break;    MRW_Ax(ASO);    break;
-
-        /* RLA  */
-        case 0x23:  if(bIgnoreIllegalOps) break;    MRW_Ix(RLA);    break;
-        case 0x27:  if(bIgnoreIllegalOps) break;    MRW_Zp(RLA);    break;
-        case 0x2F:  if(bIgnoreIllegalOps) break;    MRW_Ab(RLA);    break;
-        case 0x33:  if(bIgnoreIllegalOps) break;    MRW_Iy(RLA);    break;
-        case 0x37:  if(bIgnoreIllegalOps) break;    MRW_Zx(RLA);    break;
-        case 0x3B:  if(bIgnoreIllegalOps) break;    MRW_Ay(RLA);    break;
-        case 0x3F:  if(bIgnoreIllegalOps) break;    MRW_Ax(RLA);    break;
-
-        /* LSE  */
-        case 0x43:  if(bIgnoreIllegalOps) break;    MRW_Ix(LSE);    break;
-        case 0x47:  if(bIgnoreIllegalOps) break;    MRW_Zp(LSE);    break;
-        case 0x4F:  if(bIgnoreIllegalOps) break;    MRW_Ab(LSE);    break;
-        case 0x53:  if(bIgnoreIllegalOps) break;    MRW_Iy(LSE);    break;
-        case 0x57:  if(bIgnoreIllegalOps) break;    MRW_Zx(LSE);    break;
-        case 0x5B:  if(bIgnoreIllegalOps) break;    MRW_Ay(LSE);    break;
-        case 0x5F:  if(bIgnoreIllegalOps) break;    MRW_Ax(LSE);    break;
-
-        /* RRA  */
-        case 0x63:  if(bIgnoreIllegalOps) break;    MRW_Ix(RRA);    break;
-        case 0x67:  if(bIgnoreIllegalOps) break;    MRW_Zp(RRA);    break;
-        case 0x6F:  if(bIgnoreIllegalOps) break;    MRW_Ab(RRA);    break;
-        case 0x73:  if(bIgnoreIllegalOps) break;    MRW_Iy(RRA);    break;
-        case 0x77:  if(bIgnoreIllegalOps) break;    MRW_Zx(RRA);    break;
-        case 0x7B:  if(bIgnoreIllegalOps) break;    MRW_Ay(RRA);    break;
-        case 0x7F:  if(bIgnoreIllegalOps) break;    MRW_Ax(RRA);    break;
-
-        /* AXS  */
-        case 0x83:  if(bIgnoreIllegalOps) break;    MRW_Ix(AXS);    break;
-        case 0x87:  if(bIgnoreIllegalOps) break;    MRW_Zp(AXS);    break;
-        case 0x8F:  if(bIgnoreIllegalOps) break;    MRW_Ab(AXS);    break;
-        case 0x97:  if(bIgnoreIllegalOps) break;    MRW_Zy(AXS);    break;
-
-        /* LAX  */
-        case 0xA3:  if(bIgnoreIllegalOps) break;
-            Ad_VlIx();  X = A = val; UpdateNZ(A);   break;
-        case 0xA7:  if(bIgnoreIllegalOps) break;
-            Ad_VlZp();  X = A = val; UpdateNZ(A);   break;
-        case 0xAF:  if(bIgnoreIllegalOps) break;
-            Ad_VlAb();  X = A = val; UpdateNZ(A);   break;
-        case 0xB3:  if(bIgnoreIllegalOps) break;
-            Ad_VlIy();  X = A = val; UpdateNZ(A);   break;
-        case 0xB7:  if(bIgnoreIllegalOps) break;
-            Ad_VlZy();  X = A = val; UpdateNZ(A);   break;
-        case 0xBF:  if(bIgnoreIllegalOps) break;
-            Ad_VlAy();  X = A = val; UpdateNZ(A);   break;
-
-        /* DCM  */
-        case 0xC3:  if(bIgnoreIllegalOps) break;    MRW_Ix(DCM);    break;
-        case 0xC7:  if(bIgnoreIllegalOps) break;    MRW_Zp(DCM);    break;
-        case 0xCF:  if(bIgnoreIllegalOps) break;    MRW_Ab(DCM);    break;
-        case 0xD3:  if(bIgnoreIllegalOps) break;    MRW_Iy(DCM);    break;
-        case 0xD7:  if(bIgnoreIllegalOps) break;    MRW_Zx(DCM);    break;
-        case 0xDB:  if(bIgnoreIllegalOps) break;    MRW_Ay(DCM);    break;
-        case 0xDF:  if(bIgnoreIllegalOps) break;    MRW_Ax(DCM);    break;
-
-        /* INS  */
-        case 0xE3:  if(bIgnoreIllegalOps) break;    MRW_Ix(INS);    break;
-        case 0xE7:  if(bIgnoreIllegalOps) break;    MRW_Zp(INS);    break;
-        case 0xEF:  if(bIgnoreIllegalOps) break;    MRW_Ab(INS);    break;
-        case 0xF3:  if(bIgnoreIllegalOps) break;    MRW_Iy(INS);    break;
-        case 0xF7:  if(bIgnoreIllegalOps) break;    MRW_Zx(INS);    break;
-        case 0xFB:  if(bIgnoreIllegalOps) break;    MRW_Ay(INS);    break;
-        case 0xFF:  if(bIgnoreIllegalOps) break;    MRW_Ax(INS);    break;
-
-        /* ALR
-                AND Accumulator with memory and LSR the result  */
-        case 0x4B:  if(bIgnoreIllegalOps) break;
-                    Ad_VlIm();  A &= val;   LSR(A); break;
-
-        /* ARR
-                ANDs memory with the Accumulator and RORs the result    */
-        case 0x6B:  if(bIgnoreIllegalOps) break;
-                    Ad_VlIm();  A &= val;   ROR(A); break;
-
-        /* XAA
-                Transfers X -> A, then ANDs A with memory               */
-        case 0x8B:  if(bIgnoreIllegalOps) break;
-                    Ad_VlIm();  A = X & val; UpdateNZ(A);   break;
-
-        /* OAL
-                OR the Accumulator with #EE, AND Accumulator with Memory,
-                Transfer A -> X   */
-        case 0xAB:  if(bIgnoreIllegalOps) break;
-                    Ad_VlIm();  X = (A &= (val | 0xEE));
-                    UpdateNZ(A);    break;
-
-        /* SAX
-                ANDs A and X registers (does not change A), subtracts memory
-                from result (CMP style, not SBC style) result is stored in X */
-        case 0xCB:  if(bIgnoreIllegalOps) break;
-                Ad_VlIm();  tw.W = (X & A) - val; X = tw.B.l;
-                    ST = (ST & ~(N_FLAG|Z_FLAG|C_FLAG)) | NZTable[X] |
-                        (tw.B.h ? C_FLAG : 0);   break;
-        /* SKB
-                Skip Byte... or DOP - Double No-Op
-                These bytes do nothing, but take a parameter (which can be
-                ignored) */
-        case 0x04:  case 0x14:  case 0x34:  case 0x44:  case 0x54:  case 0x64:
-        case 0x80:  case 0x82:  case 0x89:  case 0xC2:  case 0xD4:  case 0xE2:
-        case 0xF4:
-            if(bIgnoreIllegalOps) break;
-            PC.W++;     /* skip unused byte */
-            break;
-
-        /* SKW
-                Swip Word... or TOP - Tripple No-Op
-            These bytes are the same as SKB, only they take a 2 byte parameter.
-            This can be ignored in some cases, but the read needs to be
-            performed in a some cases because an extra clock cycle may be used
-            in the process     */
-        /* Absolute address... no need for operator */
-        case 0x0C:
-            if(bIgnoreIllegalOps) break;
-            PC.W += 2;  break;
-        /* Absolute X address... may cross page, have to perform the read */
-        case 0x1C:  case 0x3C:  case 0x5C:  case 0x7C:  case 0xDC:  case 0xFC:
-            if(bIgnoreIllegalOps) break;
-            Ad_VlAx(); break;
-
-        /* HLT / JAM
-                Jams up CPU operation           */
-        case 0x02:  case 0x12:  case 0x22:  case 0x32:  case 0x42:  case 0x52:
-        case 0x62:  case 0x72:  case 0x92:  case 0xB2:  case 0xD2:  case 0xF2:
-            /*it's not -really- jammed... only the NSF code has ended*/
-            if(PC.W == 0x5004)  bCPUJammed = 2;
-            else
-            {
-                if(bIgnoreIllegalOps) break;
-                bCPUJammed = 1;
-            }
-            goto jammed;
-
-        /* TAS  */
-        case 0x9B:
-            if(bIgnoreIllegalOps) break;
-            Ad_AdAy();
-            SP = A & X & (Rd(PC.W - 1) + 1);
-            Wr(final.W,SP);
-            break;
-
-        /* SAY  */
-        case 0x9C:
-            if(bIgnoreIllegalOps) break;
-            Ad_AdAx();
-            Y &= (Rd(PC.W - 1) + 1);
-            Wr(final.W,Y);
-            break;
-
-        /* XAS  */
-        case 0x9E:
-            if(bIgnoreIllegalOps) break;
-            Ad_AdAy();
-            X &= (Rd(PC.W - 1) + 1);
-            Wr(final.W,X);
-            break;
-
-        /* AXA  */
-        case 0x93:  if(bIgnoreIllegalOps) break;    MRW_Iy(AXA);    break;
-        case 0x9F:  if(bIgnoreIllegalOps) break;    MRW_Ay(AXA);    break;
-
-        /* ANC  */
-        case 0x0B:  case 0x2B:
-            if(bIgnoreIllegalOps) break;
-            Ad_VlIm();
-            A &= val;
-            ST = (ST & ~(N_FLAG|Z_FLAG|C_FLAG)) |
-                NZTable[A] | ((A & 0x80) ? C_FLAG : 0);
-            break;
-
-        /* LAS  */
-        case 0xBB:
-            if(bIgnoreIllegalOps) break;
-            Ad_VlAy();
-            X = A = (SP &= val);
-            UpdateNZ(A);
-            break;
-        }
-    }
-
-jammed:
-    regPC = PC.W;
-    regA = A;
-    regX = X;
-    regY = Y;
-    regSP = SP;
-    regP = ST;
-    
-    EXIT_TIMER(cpu);
-    
-    return (nCPUCycle - ret);
-}
-
 /****************** rockbox interface ******************/
 
-static void set_codec_track(int t, int d) {
-    int track,fade,def=0;
-    SetTrack(t);
+static void set_codec_track(int t, int multitrack) {
+    Nsf_start_track(&nsf_emu, t); 
 
     /* for REPEAT_ONE we disable track limits */
-    if (ci->global_settings->repeat_mode!=REPEAT_ONE) {
-        if (!bIsExtended || nTrackTime[t]==-1) {track=60*2*1000; def=1;}
-        else track=nTrackTime[t];
-        if (!bIsExtended || nTrackFade[t]==-1) fade=5*1000;
-        else fade=nTrackFade[t];
-        nSilenceTrackMS=5000;
-        SetFadeTime(track,track+fade, fNSFPlaybackSpeed,def);
+    if (ci->global_settings->repeat_mode != REPEAT_ONE) {
+        Track_set_fade(&nsf_emu, Track_length( &nsf_emu, t ), 4000);
     }
-    ci->id3->elapsed=d*1000; /* d is track no to display */
+    if (multitrack) ci->id3->elapsed = t*1000; /* t is track no to display */
+    else ci->set_elapsed(0);
 }
 
 /* this is the codec entry point */
 enum codec_status codec_main(void)
 {
-    int written;
+    blargg_err_t err;
     uint8_t *buf;
     size_t n;
-    int endofstream; /* end of stream flag */
-    int track;
-    int dontresettrack;
-    char last_path[MAX_PATH];
-    int usingplaylist;
+    int track, multitrack;
+    uint32_t elapsed_time;
 
     /* we only render 16 bits */
     ci->configure(DSP_SET_SAMPLE_DEPTH, 16);
 
+    /* 44 Khz, Interleaved stereo */
     ci->configure(DSP_SET_FREQUENCY, 44100);
-    ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO);
-    
-    RebuildOutputTables();
+    ci->configure(DSP_SET_STEREO_MODE, STEREO_INTERLEAVED);
 
-    dontresettrack=0;
-    last_path[0]='\0';
-    track=0;
-    
+    Nsf_init(&nsf_emu);
+    Nsf_set_sample_rate(&nsf_emu, 44100);
+
 next_track:
-    usingplaylist=0;
+    track = multitrack = 0;
+    elapsed_time = 0;
+
     DEBUGF("NSF: next_track\n");
     if (codec_init()) {
         return CODEC_ERROR;
-    }
-    DEBUGF("NSF: after init\n");
-    
+    }  
 
     /* wait for track info to load */
     if (codec_wait_taginfo() != 0)
         goto request_next_track;
-        
+
     codec_set_replaygain(ci->id3);
         
     /* Read the entire file */
@@ -4357,114 +67,83 @@
         DEBUGF("NSF: file load failed\n");
         return CODEC_ERROR;
     }
-    
-init_nsf:    
-    if(!NSFCore_Initialize()) {
-        DEBUGF("NSF: NSFCore_Initialize failed\n"); return CODEC_ERROR;}
+   
+    if ((err = Nsf_load(&nsf_emu, buf, ci->filesize))) {
+        DEBUGF("NSF: Nsf_load failed (%s)\n", err);
+        return CODEC_ERROR;
+    }
 
-    if(LoadFile(buf,ci->filesize)) {
-        DEBUGF("NSF: LoadFile failed\n"); return CODEC_ERROR;}
-    if(!SetPlaybackOptions(44100)) {
-        DEBUGF("NSF: SetPlaybackOptions failed\n"); return CODEC_ERROR;}
-    if(!LoadNSF(nDataBufferSize)) {
-        DEBUGF("NSF: LoadNSF failed\n"); return CODEC_ERROR;}
+    /* Load m3u playlist */
+    char *p = strrchr(ci->id3->path, '.');
+    if (p) {
+        strcpy(p, ".m3u");
+        Nsf_load_m3u(&nsf_emu, ci->id3->path);
 
-    ci->id3->title=szGameTitle;
-    ci->id3->artist=szArtist;
-    ci->id3->album=szCopyright;
-    if (usingplaylist) {
-        ci->id3->length=nPlaylistSize*1000;
-    } else {
-        ci->id3->length=nTrackCount*1000;
+        // Copy back nsf extension
+        if (nsf_emu.is_extended) strcpy(p, ".nsfe");
+        else strcpy(p, ".nsf");
     }
 
-    if (!dontresettrack||strcmp(ci->id3->path,last_path)) {
-        /* if this is the first time we're seeing this file, or if we haven't
-           been asked to preserve the track number, default to the proper
-           initial track */
-        if (bIsExtended &&
-            ci->global_settings->repeat_mode!=REPEAT_ONE && nPlaylistSize>0) {
-            /* decide to use the playlist */
-            usingplaylist=1;
-            track=0;
-            set_codec_track(nPlaylist[0],0);
-        } else {
-            /* simply use the initial track */
-            track=nInitialTrack;
-            set_codec_track(track,track);
-        }
-    } else {
-        /* if we've already been running this file assume track is set
-           already */
-        if (usingplaylist) set_codec_track(nPlaylist[track],track);
-        else set_codec_track(track,track);
-    }
-    strcpy(last_path,ci->id3->path);
+    /* Priority: m3u playlist > nsfe playlist > header info */
 
-    /* The main decoder loop */
+    struct info_t* info = &nsf_emu.m3u.info;
+    struct auth_chunk_t* auth = &nsf_emu.info.auth;
+    ci->id3->title = info->title ? info->title : 
+                     *auth->game ? auth->game : nsf_emu.header.game;
+    ci->id3->artist = info->composer ? info->composer : 
+                     *auth->author ? auth->author : nsf_emu.header.author;
+    ci->id3->album = info->engineer ? info->engineer : 
+                     *auth->copyright ? auth->copyright : nsf_emu.header.copyright;
     
-    endofstream = 0;
-    
-    reset_profile_timers();
-    
-    while (!endofstream) {
+    if (nsf_emu.track_count > 1) {
+        multitrack = 1;
+        ci->id3->length = nsf_emu.track_count*1000;
+    }
+    else ci->id3->length = Track_length( &nsf_emu, track );
 
+next_tune:
+    set_codec_track(track, multitrack);
+
+    /* The main decoder loop */
+    while (1) {
         ci->yield();
-        if (ci->stop_codec || ci->new_track) {
+        if (ci->stop_codec || ci->new_track)
             break;
-        }
 
-        if (ci->seek_time >0) {
-            track=ci->seek_time/1000;
-            if (usingplaylist) {
-                if (track>=nPlaylistSize) break;
-            } else {
-                if (track>=nTrackCount) break;
+        if (ci->seek_time) {
+            if (multitrack) {
+                track = ci->seek_time/1000;
+                ci->seek_complete();
+                if (track >= nsf_emu.track_count) break;
+                goto next_tune;
             }
+
+            ci->set_elapsed(ci->seek_time);
+            elapsed_time = ci->seek_time;
+            Track_seek(&nsf_emu, ci->seek_time);
             ci->seek_complete();
-            dontresettrack=1;
-            goto init_nsf;
         }
 
-        ENTER_TIMER(total);
-        written=GetSamples((uint8_t*)samples,WAV_CHUNK_SIZE/2);
-        EXIT_TIMER(total);
-        
-        if (!written || SongCompleted()) {
-            print_timers(last_path,track);
-            reset_profile_timers();
-            
+        /* Generate audio buffer */
+        err = Nsf_play(&nsf_emu, CHUNK_SIZE, samples);
+        if (err || nsf_emu.track_ended) {
             track++;
-            if (usingplaylist) {
-               if (track>=nPlaylistSize) break;
-            } else {
-               if (track>=nTrackCount) break;
-            }
-            dontresettrack=1;
-            goto init_nsf;
+            if (track >= nsf_emu.track_count) break;
+            goto next_tune;
         }
 
-        ci->pcmbuf_insert(samples, NULL, written >> 1);
+        ci->pcmbuf_insert(samples, NULL, CHUNK_SIZE >> 1);
+
+        /* Set elapsed time for one track files */
+        if (!multitrack) {
+            elapsed_time += (CHUNK_SIZE / 2) / 44.1;
+            ci->set_elapsed(elapsed_time);
+        }
     }
-    
-    print_timers(last_path,track);
 
 request_next_track:
-    if (ci->request_next_track()) {
-    if (ci->global_settings->repeat_mode==REPEAT_ONE) {
-        /* in repeat one mode just advance to the next track */
-        track++;
-        if (track>=nTrackCount) track=0;
-        dontresettrack=1;
-        /* at this point we can't tell if another file has been selected */
-        goto next_track;
-    } else {
-        /* otherwise do a proper load of the next file */
-        dontresettrack=0;
-        last_path[0]='\0';
-    }
-    goto next_track; /* when we fall through here we'll reload the file */
-    }
-    
+    if (ci->request_next_track())
+        goto next_track; /* when we fall through here we'll reload the file */
+
     return CODEC_OK;
 }
Index: apps/codecs/lib/codeclib.c
===================================================================
--- apps/codecs/lib/codeclib.c	(revision 29484)
+++ apps/codecs/lib/codeclib.c	(working copy)
@@ -105,11 +105,21 @@
     return(ci->strlen(s));
 }
 
+char *strrchr(const char *s, int c)
+{
+    return(ci->strrchr(s, c));
+}
+
 char *strcpy(char *dest, const char *src)
 {
     return(ci->strcpy(dest,src));
 }
 
+size_t strlcpy(char *dst, const char *src, size_t length)
+{
+    return(ci->strlcpy(dst,src,length));
+}
+
 char *strcat(char *dest, const char *src)
 {
     return(ci->strcat(dest,src));
@@ -120,6 +130,11 @@
     return(ci->strcmp(s1,s2));
 }
 
+int strcasecmp(const char *s1, const char *s2)
+{
+    return(ci->strcasecmp(s1, s2));
+}
+
 void *memcpy(void *dest, const void *src, size_t n)
 {
     return(ci->memcpy(dest,src,n));
Index: apps/codecs/lib/codeclib.h
===================================================================
--- apps/codecs/lib/codeclib.h	(revision 29484)
+++ apps/codecs/lib/codeclib.h	(working copy)
@@ -59,13 +59,16 @@
 void *memmove(void *s1, const void *s2, size_t n);
 
 size_t strlen(const char *s);
+char *strrchr(const char *s, int c);
 char *strcpy(char *dest, const char *src);
+size_t strlcpy(char *dst, const char *src, size_t length);
 char *strcat(char *dest, const char *src);
 
 /* on some platforms strcmp() seems to be a tricky define which
  * breaks if we write down strcmp's prototype */
 #undef strcmp
 int strcmp(const char *s1, const char *s2);
+int strcasecmp(const char *s1, const char *s2);
 
 void qsort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *));
 
Index: apps/codecs/codecs.make
===================================================================
--- apps/codecs/codecs.make	(revision 29484)
+++ apps/codecs/codecs.make	(working copy)
@@ -43,6 +43,7 @@
 include $(APPSDIR)/codecs/libatrac/libatrac.make
 include $(APPSDIR)/codecs/libpcm/libpcm.make
 include $(APPSDIR)/codecs/libtta/libtta.make
+include $(APPSDIR)/codecs/libnsf/libnsf.make
 
 # compile flags for codecs
 CODECFLAGS = $(CFLAGS) -fstrict-aliasing -I$(APPSDIR)/codecs \
@@ -93,6 +94,7 @@
 $(CODECDIR)/vox.codec : $(CODECDIR)/libpcm.a
 $(CODECDIR)/wav64.codec : $(CODECDIR)/libpcm.a
 $(CODECDIR)/tta.codec : $(CODECDIR)/libtta.a
+$(CODECDIR)/nsf.codec : $(CODECDIR)/libnsf.a
 
 $(CODECS): $(CODECLIB) # this must be last in codec dependency list
 
