[SNSF] Massive code cleanup, as well as removing as much unused code/variables as possible.
[SNSF] Massive code cleanup, as well as removing as much unused code/variables as possible.

--- a/src/in_snsf/XSFPlayer_SNSF.cpp
+++ b/src/in_snsf/XSFPlayer_SNSF.cpp
@@ -93,7 +93,7 @@
 			return;
 		if (bytes > bleft)
 			bytes = bleft;
-		memset(&this->buf[this->fil], 0, bytes);
+		std::fill(&this->buf[this->fil], &this->buf[this->fil + bytes], 0);
 		S9xMixSamples(&this->buf[this->fil], bytes >> 1);
 		this->fil += bytes;
 	}
@@ -122,7 +122,7 @@
 		data.resize(finalSize, 0);
 	else if (data.size() < size + offset)
 		data.resize(offset + finalSize);
-	memcpy(&data[offset], &section[8], size);
+	std::copy(&section[8], &section[8 + size], &data[offset]);
 }
 
 static bool Map2SF(XSFFile *xSF, int level)
@@ -148,7 +148,7 @@
 				if (size > 4 && loaderwork.sram.size() > offset)
 				{
 					auto len = std::min(size - 4, loaderwork.sram.size() - offset);
-					memcpy(&loaderwork.sram[offset], &reservedSection[reservedPosition + 12], len);
+					std::copy(&reservedSection[reservedPosition + 12], &reservedSection[reservedPosition + 12 + len], &loaderwork.sram[offset]);
 				}
 			}
 			reservedPosition += size + 8;
@@ -276,7 +276,7 @@
 		unsigned len = remain;
 		if (len > bytes)
 			len = bytes;
-		memcpy(&buf[offset], &buffer.buf[buffer.cur], len);
+		std::copy(&buffer.buf[buffer.cur], &buffer.buf[buffer.cur + len], &buf[offset]);
 		bytes -= len;
 		offset += len;
 		buffer.cur += len;

--- a/src/in_snsf/in_snsf.vcxproj
+++ b/src/in_snsf/in_snsf.vcxproj
@@ -83,7 +83,6 @@
     <ClCompile Include="snes9x\apu\apu.cpp" />
     <ClCompile Include="snes9x\apu\SNES_SPC.cpp" />
     <ClCompile Include="snes9x\apu\SNES_SPC_misc.cpp" />
-    <ClCompile Include="snes9x\apu\SNES_SPC_state.cpp" />
     <ClCompile Include="snes9x\apu\SPC_DSP.cpp" />
     <ClCompile Include="snes9x\cpu.cpp" />
     <ClCompile Include="snes9x\cpuexec.cpp" />
@@ -105,7 +104,6 @@
     <ClInclude Include="snes9x\apu\blargg_common.h" />
     <ClInclude Include="snes9x\apu\blargg_config.h" />
     <ClInclude Include="snes9x\apu\blargg_endian.h" />
-    <ClInclude Include="snes9x\apu\blargg_source.h" />
     <ClInclude Include="snes9x\apu\hermite_resampler.h" />
     <ClInclude Include="snes9x\apu\linear_resampler.h" />
     <ClInclude Include="snes9x\apu\resampler.h" />

--- a/src/in_snsf/in_snsf.vcxproj.filters
+++ b/src/in_snsf/in_snsf.vcxproj.filters
@@ -60,9 +60,6 @@
     <ClCompile Include="snes9x\apu\SNES_SPC_misc.cpp">
       <Filter>Source Files\snes9x\apu</Filter>
     </ClCompile>
-    <ClCompile Include="snes9x\apu\SNES_SPC_state.cpp">
-      <Filter>Source Files\snes9x\apu</Filter>
-    </ClCompile>
     <ClCompile Include="snes9x\apu\SPC_DSP.cpp">
       <Filter>Source Files\snes9x\apu</Filter>
     </ClCompile>
@@ -84,9 +81,6 @@
       <Filter>Header Files\snes9x\apu</Filter>
     </ClInclude>
     <ClInclude Include="snes9x\apu\blargg_endian.h">
-      <Filter>Header Files\snes9x\apu</Filter>
-    </ClInclude>
-    <ClInclude Include="snes9x\apu\blargg_source.h">
       <Filter>Header Files\snes9x\apu</Filter>
     </ClInclude>
     <ClInclude Include="snes9x\apu\hermite_resampler.h">

--- a/src/in_snsf/snes9x/65c816.h
+++ b/src/in_snsf/snes9x/65c816.h
@@ -175,104 +175,76 @@
   Nintendo Co., Limited and its subsidiary companies.
  ***********************************************************************************/
 
-
 #ifndef _65C816_H_
 #define _65C816_H_
 
-#define Carry		1
-#define Zero		2
-#define IRQ			4
-#define Decimal		8
-#define IndexFlag	16
-#define MemoryFlag	32
-#define Overflow	64
-#define Negative	128
-#define Emulation	256
-
-#define SetCarry()			(ICPU._Carry = 1)
-#define ClearCarry()		(ICPU._Carry = 0)
-#define SetZero()			(ICPU._Zero = 0)
-#define ClearZero()			(ICPU._Zero = 1)
-#define SetIRQ()			(Registers.PL |= IRQ)
-#define ClearIRQ()			(Registers.PL &= ~IRQ)
-#define SetDecimal()		(Registers.PL |= Decimal)
-#define ClearDecimal()		(Registers.PL &= ~Decimal)
-#define SetIndex()			(Registers.PL |= IndexFlag)
-#define ClearIndex()		(Registers.PL &= ~IndexFlag)
-#define SetMemory()			(Registers.PL |= MemoryFlag)
-#define ClearMemory()		(Registers.PL &= ~MemoryFlag)
-#define SetOverflow()		(ICPU._Overflow = 1)
-#define ClearOverflow()		(ICPU._Overflow = 0)
-#define SetNegative()		(ICPU._Negative = 0x80)
-#define ClearNegative()		(ICPU._Negative = 0)
-
-#define CheckCarry()		(ICPU._Carry)
-#define CheckZero()			(ICPU._Zero == 0)
-#define CheckIRQ()			(Registers.PL & IRQ)
-#define CheckDecimal()		(Registers.PL & Decimal)
-#define CheckIndex()		(Registers.PL & IndexFlag)
-#define CheckMemory()		(Registers.PL & MemoryFlag)
-#define CheckOverflow()		(ICPU._Overflow)
-#define CheckNegative()		(ICPU._Negative & 0x80)
-#define CheckEmulation()	(Registers.P.W & Emulation)
-
-#define SetFlags(f)			(Registers.P.W |= (f))
-#define ClearFlags(f)		(Registers.P.W &= ~(f))
-#define CheckFlag(f)		(Registers.PL & (f))
-
-typedef union
+const uint16_t Carry = 1;
+const uint16_t Zero = 2;
+const uint16_t IRQ = 4;
+const uint16_t Decimal = 8;
+const uint16_t IndexFlag = 16;
+const uint16_t MemoryFlag = 32;
+const uint16_t Overflow = 64;
+const uint16_t Negative = 128;
+const uint16_t Emulation = 256;
+
+union pair
 {
 #ifdef LSB_FIRST
-	struct { uint8_t	l, h; } B;
+	struct { uint8_t l, h; } B;
 #else
-	struct { uint8_t	h, l; } B;
+	struct { uint8_t h, l; } B;
 #endif
-	uint16_t	W;
-}	pair;
-
-typedef union
+	uint16_t W;
+};
+
+union PC_t
 {
 #ifdef LSB_FIRST
-	struct { uint8_t	xPCl, xPCh, xPB, z; } B;
-	struct { uint16_t	xPC, d; } W;
+	struct { uint8_t xPCl, xPCh, xPB, z; } B;
+	struct { uint16_t xPC, d; } W;
 #else
-	struct { uint8_t	z, xPB, xPCh, xPCl; } B;
-	struct { uint16_t	d, xPC; } W;
+	struct { uint8_t z, xPB, xPCh, xPCl; } B;
+	struct { uint16_t d, xPC; } W;
 #endif
-    uint32_t	xPBPC;
-}	PC_t;
+	uint32_t xPBPC;
+};
 
 struct SRegisters
 {
-	uint8_t	DB;
-	pair	P;
-	pair	A;
-	pair	D;
-	pair	S;
-	pair	X;
-	pair	Y;
-	PC_t	PC;
+	uint8_t DB;
+	pair P;
+	pair A;
+	pair D;
+	pair S;
+	pair X;
+	pair Y;
+	PC_t PC;
 };
 
-#define AL		A.B.l
-#define AH		A.B.h
-#define XL		X.B.l
-#define XH		X.B.h
-#define YL		Y.B.l
-#define YH		Y.B.h
-#define SL		S.B.l
-#define SH		S.B.h
-#define DL		D.B.l
-#define DH		D.B.h
-#define PL		P.B.l
-#define PH		P.B.h
-#define PBPC	PC.xPBPC
-#define PCw		PC.W.xPC
-#define PCh		PC.B.xPCh
-#define PCl		PC.B.xPCl
-#define PB		PC.B.xPB
-
-extern struct SRegisters	Registers;
+extern SRegisters Registers;
+
+inline void SetCarry() { ICPU._Carry = 1; }
+inline void ClearCarry() { ICPU._Carry = 0; }
+inline void SetIRQ() { Registers.P.B.l |= IRQ; }
+inline void ClearIRQ() { Registers.P.B.l &= ~IRQ; }
+inline void SetDecimal() { Registers.P.B.l |= Decimal; }
+inline void ClearDecimal() { Registers.P.B.l &= ~Decimal; }
+inline void SetOverflow() { ICPU._Overflow = 1; }
+inline void ClearOverflow() { ICPU._Overflow = 0; }
+
+inline bool CheckCarry() { return !!ICPU._Carry; }
+inline bool CheckZero() { return !ICPU._Zero; }
+inline bool CheckDecimal() { return !!(Registers.P.B.l & Decimal); }
+inline bool CheckIndex() { return !!(Registers.P.B.l & IndexFlag); }
+inline bool CheckMemory() { return !!(Registers.P.B.l & MemoryFlag); }
+inline bool CheckOverflow() { return !!(ICPU._Overflow); }
+inline bool CheckNegative() { return !!(ICPU._Negative & 0x80); }
+inline bool CheckEmulation() { return !!(Registers.P.W & Emulation); }
+
+inline void SetFlags(uint16_t f) { Registers.P.W |= f; }
+inline void ClearFlags(uint16_t f) { Registers.P.W &= ~f; }
+inline bool CheckFlag(uint16_t f) { return !!(Registers.P.W & f); }
 
 #endif
 

--- a/src/in_snsf/snes9x/apu/SNES_SPC.cpp
+++ b/src/in_snsf/snes9x/apu/SNES_SPC.cpp
@@ -2,9 +2,9 @@
 
 // snes_spc 0.9.0. http://www.slack.net/~ant/
 
+#include <algorithm>
+#include <cstring>
 #include "SNES_SPC.h"
-
-#include <string.h>
 
 /* Copyright (C) 2004-2007 Shay Green. This module is free software; you
 can redistribute it and/or modify it under the terms of the GNU Lesser
@@ -17,547 +17,335 @@
 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"
-
-#define RAM         (m.ram.ram)
-#define REGS        (m.smp_regs [0])
-#define REGS_IN     (m.smp_regs [1])
-
-// (n ? n : 256)
-#define IF_0_THEN_256( n ) ((uint8_t) ((n) - 1) + 1)
-
-// Note: SPC_MORE_ACCURACY exists mainly so I can run my validation tests, which
-// do crazy echo buffer accesses.
-#ifndef SPC_MORE_ACCURACY
-	#define SPC_MORE_ACCURACY 0
+//// Timers
+
+#if SPC_DISABLE_TEMPO
+template<typename T> static inline T TIMER_DIV(SNES_SPC::Timer *t, const T &n) { return n >> t->prescaler; }
+template<typename T> static inline T TIMER_MUL(SNES_SPC::Timer *t, const T &n) { return n << t->prescaler; }
+#else
+template<typename T> static inline T TIMER_DIV(SNES_SPC::Timer *t, const T &n) { return n / t->prescaler; }
+template<typename T> static inline T TIMER_MUL(SNES_SPC::Timer *t, const T &n) { return n * t->prescaler; }
 #endif
 
-#ifdef BLARGG_ENABLE_OPTIMIZER
-	#include BLARGG_ENABLE_OPTIMIZER
-#endif
-
-
-//// Timers
-
-#if SPC_DISABLE_TEMPO
-	#define TIMER_DIV( t, n ) ((n) >> t->prescaler)
-	#define TIMER_MUL( t, n ) ((n) << t->prescaler)
-#else
-	#define TIMER_DIV( t, n ) ((n) / t->prescaler)
-	#define TIMER_MUL( t, n ) ((n) * t->prescaler)
-#endif
-
-SNES_SPC::Timer* SNES_SPC::run_timer_( Timer* t, rel_time_t time )
-{
-	int elapsed = TIMER_DIV( t, time - t->next_time ) + 1;
-	t->next_time += TIMER_MUL( t, elapsed );
-	
-	if ( t->enabled )
-	{
-		int remain = IF_0_THEN_256( t->period - t->divider );
+auto SNES_SPC::run_timer_(Timer *t, rel_time_t time) -> Timer *
+{
+	int elapsed = TIMER_DIV(t, time - t->next_time) + 1;
+	t->next_time += TIMER_MUL(t, elapsed);
+
+	if (t->enabled)
+	{
+		int remain = IF_0_THEN_256(t->period - t->divider);
 		int divider = t->divider + elapsed;
 		int over = elapsed - remain;
-		if ( over >= 0 )
+		if (over >= 0)
 		{
 			int n = over / t->period;
 			t->counter = (t->counter + 1 + n) & 0x0F;
 			divider = over - n * t->period;
 		}
-		t->divider = (uint8_t) divider;
+		t->divider = static_cast<uint8_t>(divider);
 	}
 	return t;
 }
 
-inline SNES_SPC::Timer* SNES_SPC::run_timer( Timer* t, rel_time_t time )
-{
-	if ( time >= t->next_time )
-		t = run_timer_( t, time );
+auto SNES_SPC::run_timer(Timer *t, rel_time_t time) -> Timer *
+{
+	if (time >= t->next_time)
+		t = this->run_timer_(t, time);
 	return t;
 }
 
-
 //// ROM
 
-void SNES_SPC::enable_rom( int enable )
-{
-	if ( m.rom_enabled != enable )
-	{
-		m.rom_enabled = dsp.rom_enabled = enable;
-		if ( enable )
-			memcpy( m.hi_ram, &RAM [rom_addr], sizeof m.hi_ram );
-		memcpy( &RAM [rom_addr], (enable ? m.rom : m.hi_ram), rom_size );
+void SNES_SPC::enable_rom(bool enable)
+{
+	if (this->m.rom_enabled != enable)
+	{
+		this->m.rom_enabled = this->dsp.rom_enabled = enable;
+		if (enable)
+			std::copy(&this->m.ram.ram[rom_addr], &this->m.ram.ram[rom_addr + rom_size], &this->m.hi_ram[0]);
+		auto data = enable ? &this->m.rom[0] : &this->m.hi_ram[0];
+		std::copy(&data[0], &data[rom_size], &this->m.ram.ram[rom_addr]);
 		// TODO: ROM can still get overwritten when DSP writes to echo buffer
 	}
 }
 
-
 //// DSP
 
-#if SPC_LESS_ACCURATE
-	int const max_reg_time = 29;
-	
-	signed char const SNES_SPC::reg_times_ [256] =
-	{
-		 -1,  0,-11,-10,-15,-11, -2, -2,  4,  3, 14, 14, 26, 26, 14, 22,
-		  2,  3,  0,  1,-12,  0,  1,  1,  7,  6, 14, 14, 27, 14, 14, 23,
-		  5,  6,  3,  4, -1,  3,  4,  4, 10,  9, 14, 14, 26, -5, 14, 23,
-		  8,  9,  6,  7,  2,  6,  7,  7, 13, 12, 14, 14, 27, -4, 14, 24,
-		 11, 12,  9, 10,  5,  9, 10, 10, 16, 15, 14, 14, -2, -4, 14, 24,
-		 14, 15, 12, 13,  8, 12, 13, 13, 19, 18, 14, 14, -2,-36, 14, 24,
-		 17, 18, 15, 16, 11, 15, 16, 16, 22, 21, 14, 14, 28, -3, 14, 25,
-		 20, 21, 18, 19, 14, 18, 19, 19, 25, 24, 14, 14, 14, 29, 14, 25,
-		 
-		 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
-		 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
-		 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
-		 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
-		 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
-		 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
-		 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
-		 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
-	};
-	
-	#define RUN_DSP( time, offset ) \
-		int count = (time) - (offset) - m.dsp_time;\
-		if ( count >= 0 )\
-		{\
-			int clock_count = (count & ~(clocks_per_sample - 1)) + clocks_per_sample;\
-			m.dsp_time += clock_count;\
-			dsp.run( clock_count );\
-		}
-#else
-	#define RUN_DSP( time, offset ) \
-		{\
-			int count = (time) - m.dsp_time;\
-			if ( !SPC_MORE_ACCURACY || count )\
-			{\
-				assert( count > 0 );\
-				m.dsp_time = (time);\
-				dsp.run( count );\
-			}\
-		}
+void SNES_SPC::RUN_DSP(rel_time_t time)
+{
+	int count = time - this->m.dsp_time;
+	if (count)
+	{
+		assert(count > 0);
+		this->m.dsp_time = time;
+		this->dsp.run(count);
+	}
+}
+
+int SNES_SPC::dsp_read(rel_time_t time)
+{
+	this->RUN_DSP(time);
+
+	int result = this->dsp.read(this->m.smp_regs[0][r_dspaddr] & 0x7F);
+
+#ifdef SPC_DSP_READ_HOOK
+	SPC_DSP_READ_HOOK(spc_time + time, this->m.smp_regs[0][r_dspaddr] & 0x7F, result);
 #endif
 
-int SNES_SPC::dsp_read( rel_time_t time )
-{
-	RUN_DSP( time, reg_times [REGS [r_dspaddr] & 0x7F] );
-	
-	int result = dsp.read( REGS [r_dspaddr] & 0x7F );
-	
-	#ifdef SPC_DSP_READ_HOOK
-		SPC_DSP_READ_HOOK( spc_time + time, (REGS [r_dspaddr] & 0x7F), result );
-	#endif
-	
 	return result;
 }
 
-inline void SNES_SPC::dsp_write( int data, rel_time_t time )
-{
-	RUN_DSP( time, reg_times [REGS [r_dspaddr]] )
-	#if SPC_LESS_ACCURATE
-		else if ( m.dsp_time == skipping_time )
-		{
-			int r = REGS [r_dspaddr];
-			if ( r == SPC_DSP::r_kon )
-				m.skipped_kon |= data & ~dsp.read( SPC_DSP::r_koff );
-			
-			if ( r == SPC_DSP::r_koff )
-			{
-				m.skipped_koff |= data;
-				m.skipped_kon &= ~data;
-			}
-		}
-	#endif
-	
-	#ifdef SPC_DSP_WRITE_HOOK
-		SPC_DSP_WRITE_HOOK( m.spc_time + time, REGS [r_dspaddr], (uint8_t) data );
-	#endif
-	
-	if ( REGS [r_dspaddr] <= 0x7F )
-		dsp.write( REGS [r_dspaddr], data );
-	else if ( !SPC_MORE_ACCURACY )
-		dprintf( "SPC wrote to DSP register > $7F\n" );
-}
-
-
-//// Memory access extras
-
-#if SPC_MORE_ACCURACY
-	#define MEM_ACCESS( time, addr ) \
-	{\
-		if ( time >= m.dsp_time )\
-		{\
-			RUN_DSP( time, max_reg_time );\
-		}\
-	}
-#elif !defined (NDEBUG)
-	// Debug-only check for read/write within echo buffer, since this might result in
-	// inaccurate emulation due to the DSP not being caught up to the present.
-	
-	bool SNES_SPC::check_echo_access( int addr )
-	{
-		if ( !(dsp.read( SPC_DSP::r_flg ) & 0x20) )
-		{
-			int start = 0x100 * dsp.read( SPC_DSP::r_esa );
-			int size  = 0x800 * (dsp.read( SPC_DSP::r_edl ) & 0x0F);
-			int end   = start + (size ? size : 4);
-			if ( start <= addr && addr < end )
-			{
-				if ( !m.echo_accessed )
-				{
-					m.echo_accessed = 1;
-					return true;
-				}
-			}
-		}
-		return false;
-	}
-	
-	#define MEM_ACCESS( time, addr ) check( !check_echo_access( (uint16_t) addr ) );
-#else
-	#define MEM_ACCESS( time, addr )
+void SNES_SPC::dsp_write(int data, rel_time_t time)
+{
+	this->RUN_DSP(time);
+
+#ifdef SPC_DSP_WRITE_HOOK
+	SPC_DSP_WRITE_HOOK(this->m.spc_time + time, this->m.smp_regs[0][r_dspaddr], static_cast<uint8_t>(data));
 #endif
 
+	if (this->m.smp_regs[0][r_dspaddr] <= 0x7F)
+		this->dsp.write(this->m.smp_regs[0][r_dspaddr], data);
+}
 
 //// CPU write
-
-#if SPC_MORE_ACCURACY
-static unsigned char const glitch_probs [3] [256] =
-{
-	0xC3,0x92,0x5B,0x1C,0xD1,0x92,0x5B,0x1C,0xDB,0x9C,0x72,0x18,0xCD,0x5C,0x38,0x0B,
-	0xE1,0x9C,0x74,0x17,0xCF,0x75,0x45,0x0C,0xCF,0x6E,0x4A,0x0D,0xA3,0x3A,0x1D,0x08,
-	0xDB,0xA0,0x82,0x19,0xD9,0x73,0x3C,0x0E,0xCB,0x76,0x52,0x0B,0xA5,0x46,0x1D,0x09,
-	0xDA,0x74,0x55,0x0F,0xA2,0x3F,0x21,0x05,0x9A,0x40,0x20,0x07,0x63,0x1E,0x10,0x01,
-	0xDF,0xA9,0x85,0x1D,0xD3,0x84,0x4B,0x0E,0xCF,0x6F,0x49,0x0F,0xB3,0x48,0x1E,0x05,
-	0xD8,0x77,0x52,0x12,0xB7,0x49,0x23,0x06,0xAA,0x45,0x28,0x07,0x7D,0x28,0x0F,0x07,
-	0xCC,0x7B,0x4A,0x0E,0xB2,0x4F,0x24,0x07,0xAD,0x43,0x2C,0x06,0x86,0x29,0x11,0x07,
-	0xAE,0x48,0x1F,0x0A,0x76,0x21,0x19,0x05,0x76,0x21,0x14,0x05,0x44,0x11,0x0B,0x01,
-	0xE7,0xAD,0x96,0x23,0xDC,0x86,0x59,0x0E,0xDC,0x7C,0x5F,0x15,0xBB,0x53,0x2E,0x09,
-	0xD6,0x7C,0x4A,0x16,0xBB,0x4A,0x25,0x08,0xB3,0x4F,0x28,0x0B,0x8E,0x23,0x15,0x08,
-	0xCF,0x7F,0x57,0x11,0xB5,0x4A,0x23,0x0A,0xAA,0x42,0x28,0x05,0x7D,0x22,0x12,0x03,
-	0xA6,0x49,0x28,0x09,0x82,0x2B,0x0D,0x04,0x7A,0x20,0x0F,0x04,0x3D,0x0F,0x09,0x03,
-	0xD1,0x7C,0x4C,0x0F,0xAF,0x4E,0x21,0x09,0xA8,0x46,0x2A,0x07,0x85,0x1F,0x0E,0x07,
-	0xA6,0x3F,0x26,0x07,0x7C,0x24,0x14,0x07,0x78,0x22,0x16,0x04,0x46,0x12,0x0A,0x02,
-	0xA6,0x41,0x2C,0x0A,0x7E,0x28,0x11,0x05,0x73,0x1B,0x14,0x05,0x3D,0x11,0x0A,0x02,
-	0x70,0x22,0x17,0x05,0x48,0x13,0x08,0x03,0x3C,0x07,0x0D,0x07,0x26,0x07,0x06,0x01,
-	
-	0xE0,0x9F,0xDA,0x7C,0x4F,0x18,0x28,0x0D,0xE9,0x9F,0xDA,0x7C,0x4F,0x18,0x1F,0x07,
-	0xE6,0x97,0xD8,0x72,0x64,0x13,0x26,0x09,0xDC,0x67,0xA9,0x38,0x21,0x07,0x15,0x06,
-	0xE9,0x91,0xD2,0x6B,0x63,0x14,0x2B,0x0E,0xD6,0x61,0xB7,0x41,0x2B,0x0E,0x10,0x09,
-	0xCF,0x59,0xB0,0x2F,0x35,0x08,0x0F,0x07,0xB6,0x30,0x7A,0x21,0x17,0x07,0x09,0x03,
-	0xE7,0xA3,0xE5,0x6B,0x65,0x1F,0x34,0x09,0xD8,0x6B,0xBE,0x45,0x27,0x07,0x10,0x07,
-	0xDA,0x54,0xB1,0x39,0x2E,0x0E,0x17,0x08,0xA9,0x3C,0x86,0x22,0x16,0x06,0x07,0x03,
-	0xD4,0x51,0xBC,0x3D,0x38,0x0A,0x13,0x06,0xB2,0x37,0x79,0x1C,0x17,0x05,0x0E,0x06,
-	0xA7,0x31,0x74,0x1C,0x11,0x06,0x0C,0x02,0x6D,0x1A,0x38,0x10,0x0B,0x05,0x06,0x03,
-	0xEB,0x9A,0xE1,0x7A,0x6F,0x13,0x34,0x0E,0xE6,0x75,0xC5,0x45,0x3E,0x0B,0x1A,0x05,
-	0xD8,0x63,0xC1,0x40,0x3C,0x1B,0x19,0x06,0xB3,0x42,0x83,0x29,0x18,0x0A,0x08,0x04,
-	0xD4,0x58,0xBA,0x43,0x3F,0x0A,0x1F,0x09,0xB1,0x33,0x8A,0x1F,0x1F,0x06,0x0D,0x05,
-	0xAF,0x3C,0x7A,0x1F,0x16,0x08,0x0A,0x01,0x72,0x1B,0x52,0x0D,0x0B,0x09,0x06,0x01,
-	0xCF,0x63,0xB7,0x47,0x40,0x10,0x14,0x06,0xC0,0x41,0x96,0x20,0x1C,0x09,0x10,0x05,
-	0xA6,0x35,0x82,0x1A,0x20,0x0C,0x0E,0x04,0x80,0x1F,0x53,0x0F,0x0B,0x02,0x06,0x01,
-	0xA6,0x31,0x81,0x1B,0x1D,0x01,0x08,0x08,0x7B,0x20,0x4D,0x19,0x0E,0x05,0x07,0x03,
-	0x6B,0x17,0x49,0x07,0x0E,0x03,0x0A,0x05,0x37,0x0B,0x1F,0x06,0x04,0x02,0x07,0x01,
-	
-	0xF0,0xD6,0xED,0xAD,0xEC,0xB1,0xEB,0x79,0xAC,0x22,0x47,0x1E,0x6E,0x1B,0x32,0x0A,
-	0xF0,0xD6,0xEA,0xA4,0xED,0xC4,0xDE,0x82,0x98,0x1F,0x50,0x13,0x52,0x15,0x2A,0x0A,
-	0xF1,0xD1,0xEB,0xA2,0xEB,0xB7,0xD8,0x69,0xA2,0x1F,0x5B,0x18,0x55,0x18,0x2C,0x0A,
-	0xED,0xB5,0xDE,0x7E,0xE6,0x85,0xD3,0x59,0x59,0x0F,0x2C,0x09,0x24,0x07,0x15,0x09,
-	0xF1,0xD6,0xEA,0xA0,0xEC,0xBB,0xDA,0x77,0xA9,0x23,0x58,0x14,0x5D,0x12,0x2F,0x09,
-	0xF1,0xC1,0xE3,0x86,0xE4,0x87,0xD2,0x4E,0x68,0x15,0x26,0x0B,0x27,0x09,0x15,0x02,
-	0xEE,0xA6,0xE0,0x5C,0xE0,0x77,0xC3,0x41,0x67,0x1B,0x3C,0x07,0x2A,0x06,0x19,0x07,
-	0xE4,0x75,0xC6,0x43,0xCC,0x50,0x95,0x23,0x35,0x09,0x14,0x04,0x15,0x05,0x0B,0x04,
-	0xEE,0xD6,0xED,0xAD,0xEC,0xB1,0xEB,0x79,0xAC,0x22,0x56,0x14,0x5A,0x12,0x26,0x0A,
-	0xEE,0xBB,0xE7,0x7E,0xE9,0x8D,0xCB,0x49,0x67,0x11,0x34,0x07,0x2B,0x0B,0x14,0x07,
-	0xED,0xA7,0xE5,0x76,0xE3,0x7E,0xC4,0x4B,0x77,0x14,0x34,0x08,0x27,0x07,0x14,0x04,
-	0xE7,0x8B,0xD2,0x4C,0xCA,0x56,0x9E,0x31,0x36,0x0C,0x11,0x07,0x14,0x04,0x0A,0x02,
-	0xF0,0x9B,0xEA,0x6F,0xE5,0x81,0xC4,0x43,0x74,0x10,0x30,0x0B,0x2D,0x08,0x1B,0x06,
-	0xE6,0x83,0xCA,0x48,0xD9,0x56,0xA7,0x23,0x3B,0x09,0x12,0x09,0x15,0x07,0x0A,0x03,
-	0xE5,0x5F,0xCB,0x3C,0xCF,0x48,0x91,0x22,0x31,0x0A,0x17,0x08,0x15,0x04,0x0D,0x02,
-	0xD1,0x43,0x91,0x20,0xA9,0x2D,0x54,0x12,0x17,0x07,0x09,0x02,0x0C,0x04,0x05,0x03,
-};
-#endif
 
 // divided into multiple functions to keep rarely-used functionality separate
 // so often-used functionality can be optimized better by compiler
 
 // If write isn't preceded by read, data has this added to it
-int const no_read_before_write = 0x2000;
-
-void SNES_SPC::cpu_write_smp_reg_( int data, rel_time_t time, int addr )
-{
-	switch ( addr )
-	{
-	case r_t0target:
-	case r_t1target:
-	case r_t2target: {
-		Timer* t = &m.timers [addr - r_t0target];
-		int period = IF_0_THEN_256( data );
-		if ( t->period != period )
-		{
-			t = run_timer( t, time );
-			#if SPC_MORE_ACCURACY
-				// Insane behavior when target is written just after counter is
-				// clocked and counter matches new period and new period isn't 1, 2, 4, or 8
-				if ( t->divider == (period & 0xFF) &&
-						t->next_time == time + TIMER_MUL( t, 1 ) &&
-						((period - 1) | ~0x0F) & period )
+static const int no_read_before_write = 0x2000;
+
+void SNES_SPC::cpu_write_smp_reg_(int data, rel_time_t time, int addr)
+{
+	switch (addr)
+	{
+		case r_t0target:
+		case r_t1target:
+		case r_t2target:
+		{
+			auto t = &this->m.timers[addr - r_t0target];
+			int period = IF_0_THEN_256(data);
+			if (t->period != period)
+			{
+				t = this->run_timer(t, time);
+				t->period = period;
+			}
+			break;
+		}
+
+		case r_t0out:
+		case r_t1out:
+		case r_t2out:
+			if (data < no_read_before_write  / 2)
+				this->run_timer(&this->m.timers[addr - r_t0out], time - 1)->counter = 0;
+			break;
+
+		// Registers that act like RAM
+		case 0x8:
+		case 0x9:
+			this->m.smp_regs[1][addr] = static_cast<uint8_t>(data);
+			break;
+
+		case r_test:
+			break;
+
+		case r_control:
+			// port clears
+			if (data & 0x10)
+			{
+				this->m.smp_regs[1][r_cpuio0] = 0;
+				this->m.smp_regs[1][r_cpuio1] = 0;
+			}
+			if (data & 0x20)
+			{
+				this->m.smp_regs[1][r_cpuio2] = 0;
+				this->m.smp_regs[1][r_cpuio3] = 0;
+			}
+
+			// timers
+			for (int i = 0; i < timer_count; ++i)
+			{
+				auto t = &this->m.timers[i];
+				bool enabled = !!((data >> i) & 1);
+				if (t->enabled != enabled)
 				{
-					//dprintf( "SPC pathological timer target write\n" );
-					
-					// If the period is 3, 5, or 9, there's a probability this behavior won't occur,
-					// based on the previous period
-					int prob = 0xFF;
-					int old_period = t->period & 0xFF;
-					if ( period == 3 ) prob = glitch_probs [0] [old_period];
-					if ( period == 5 ) prob = glitch_probs [1] [old_period];
-					if ( period == 9 ) prob = glitch_probs [2] [old_period];
-					
-					// The glitch suppresses incrementing of one of the counter bits, based on
-					// the lowest set bit in the new period
-					int b = 1;
-					while ( !(period & b) )
-						b <<= 1;
-					
-					if ( (rand() >> 4 & 0xFF) <= prob )
-						t->divider = (t->divider - b) & 0xFF;
-				}
-			#endif
-			t->period = period;
-		}
-		break;
-	}
-	
-	case r_t0out:
-	case r_t1out:
-	case r_t2out:
-		if ( !SPC_MORE_ACCURACY )
-			dprintf( "SPC wrote to counter %d\n", (int) addr - r_t0out );
-		
-		if ( data < no_read_before_write  / 2 )
-			run_timer( &m.timers [addr - r_t0out], time - 1 )->counter = 0;
-		break;
-	
-	// Registers that act like RAM
-	case 0x8:
-	case 0x9:
-		REGS_IN [addr] = (uint8_t) data;
-		break;
-	
-	case r_test:
-		if ( (uint8_t) data != 0x0A )
-			dprintf( "SPC wrote to test register\n" );
-		break;
-	
-	case r_control:
-		// port clears
-		if ( data & 0x10 )
-		{
-			REGS_IN [r_cpuio0] = 0;
-			REGS_IN [r_cpuio1] = 0;
-		}
-		if ( data & 0x20 )
-		{
-			REGS_IN [r_cpuio2] = 0;
-			REGS_IN [r_cpuio3] = 0;
-		}
-		
-		// timers
-		{
-			for ( int i = 0; i < timer_count; i++ )
-			{
-				Timer* t = &m.timers [i];
-				int enabled = data >> i & 1;
-				if ( t->enabled != enabled )
-				{
-					t = run_timer( t, time );
+					t = this->run_timer(t, time);
 					t->enabled = enabled;
-					if ( enabled )
+					if (enabled)
 					{
 						t->divider = 0;
 						t->counter = 0;
 					}
 				}
 			}
-		}
-		enable_rom( data & 0x80 );
-		break;
-	}
-}
-
-void SNES_SPC::cpu_write_smp_reg( int data, rel_time_t time, int addr )
-{
-	if ( addr == r_dspdata ) // 99%
-		dsp_write( data, time );
+			this->enable_rom(!!(data & 0x80));
+	}
+}
+
+void SNES_SPC::cpu_write_smp_reg(int data, rel_time_t time, int addr)
+{
+	if (addr == r_dspdata) // 99%
+		this->dsp_write(data, time);
 	else
-		cpu_write_smp_reg_( data, time, addr );
-}
-
-void SNES_SPC::cpu_write_high( int data, int i, rel_time_t time )
-{
-	if ( i < rom_size )
-	{
-		m.hi_ram [i] = (uint8_t) data;
-		if ( m.rom_enabled )
-			RAM [i + rom_addr] = m.rom [i]; // restore overwritten ROM
+		this->cpu_write_smp_reg_(data, time, addr);
+}
+
+void SNES_SPC::cpu_write_high(int data, int i, rel_time_t time)
+{
+	if (i < rom_size)
+	{
+		this->m.hi_ram [i] = static_cast<uint8_t>(data);
+		if (this->m.rom_enabled)
+			this->m.ram.ram[i + rom_addr] = this->m.rom[i]; // restore overwritten ROM
 	}
 	else
 	{
-		assert( *(&(RAM [0]) + i + rom_addr) == (uint8_t) data );
-		*(&(RAM [0]) + i + rom_addr) = cpu_pad_fill; // restore overwritten padding
-		cpu_write( data, i + rom_addr - 0x10000, time );
-	}
-}
-
-int const bits_in_int = CHAR_BIT * sizeof (int);
-
-void SNES_SPC::cpu_write( int data, int addr, rel_time_t time )
-{
-	MEM_ACCESS( time, addr )
-	
+		assert(this->m.ram.ram[i + rom_addr] == static_cast<uint8_t>(data));
+		this->m.ram.ram[i + rom_addr] = cpu_pad_fill; // restore overwritten padding
+		this->cpu_write(data, i + rom_addr - 0x10000, time);
+	}
+}
+
+static const int bits_in_int = CHAR_BIT * sizeof(int);
+
+void SNES_SPC::cpu_write(int data, int addr, rel_time_t time)
+{
 	// RAM
-	RAM [addr] = (uint8_t) data;
+	this->m.ram.ram[addr] = static_cast<uint8_t>(data);
 	int reg = addr - 0xF0;
-	if ( reg >= 0 ) // 64%
+	if (reg >= 0) // 64%
 	{
 		// $F0-$FF
-		if ( reg < reg_count ) // 87%
-		{
-			REGS [reg] = (uint8_t) data;
-			
+		if (reg < reg_count) // 87%
+		{
+			this->m.smp_regs[0][reg] = static_cast<uint8_t>(data);
+
 			// Ports
-			#ifdef SPC_PORT_WRITE_HOOK
-				if ( (unsigned) (reg - r_cpuio0) < port_count )
-					SPC_PORT_WRITE_HOOK( m.spc_time + time, (reg - r_cpuio0),
-							(uint8_t) data, &REGS [r_cpuio0] );
-			#endif
-			
+#ifdef SPC_PORT_WRITE_HOOK
+			if (static_cast<unsigned>(reg - r_cpuio0) < port_count)
+				SPC_PORT_WRITE_HOOK(this->m.spc_time + time, (reg - r_cpuio0), static_cast<uint8_t>(data), &this->m.smp_regs[0][r_cpuio0]);
+#endif
+
 			// Registers other than $F2 and $F4-$F7
 			//if ( reg != 2 && reg != 4 && reg != 5 && reg != 6 && reg != 7 )
 			// TODO: this is a bit on the fragile side
-			if ( ((~0x2F00 << (bits_in_int - 16)) << reg) < 0 ) // 36%
-				cpu_write_smp_reg( data, time, reg );
+			if (((~0x2F00 << (bits_in_int - 16)) << reg) < 0) // 36%
+				this->cpu_write_smp_reg(data, time, reg);
 		}
 		// High mem/address wrap-around
 		else
 		{
 			reg -= rom_addr - 0xF0;
-			if ( reg >= 0 ) // 1% in IPL ROM area or address wrapped around
-				cpu_write_high( data, reg, time );
-		}
-	}
-}
-
+			if (reg >= 0) // 1% in IPL ROM area or address wrapped around
+				this->cpu_write_high(data, reg, time);
+		}
+	}
+}
 
 //// CPU read
 
-inline int SNES_SPC::cpu_read_smp_reg( int reg, rel_time_t time )
-{
-	int result = REGS_IN [reg];
+int SNES_SPC::cpu_read_smp_reg(int reg, rel_time_t time)
+{
+	int result = this->m.smp_regs[1][reg];
 	reg -= r_dspaddr;
 	// DSP addr and data
-	if ( (unsigned) reg <= 1 ) // 4% 0xF2 and 0xF3
-	{
-		result = REGS [r_dspaddr];
-		if ( (unsigned) reg == 1 )
-			result = dsp_read( time ); // 0xF3
+	if (static_cast<unsigned>(reg) <= 1) // 4% 0xF2 and 0xF3
+	{
+		result = this->m.smp_regs[0][r_dspaddr];
+		if (static_cast<unsigned>(reg) == 1)
+			result = this->dsp_read(time); // 0xF3
 	}
 	return result;
 }
 
-int SNES_SPC::cpu_read( int addr, rel_time_t time )
-{
-	MEM_ACCESS( time, addr )
-	
+int SNES_SPC::cpu_read(int addr, rel_time_t time)
+{
 	// RAM
-	int result = RAM [addr];
+	int result = this->m.ram.ram[addr];
 	int reg = addr - 0xF0;
-	if ( reg >= 0 ) // 40%
+	if (reg >= 0) // 40%
 	{
 		reg -= 0x10;
-		if ( (unsigned) reg >= 0xFF00 ) // 21%
+		if (static_cast<unsigned>(reg) >= 0xFF00) // 21%
 		{
 			reg += 0x10 - r_t0out;
-			
+
 			// Timers
-			if ( (unsigned) reg < timer_count ) // 90%
-			{
-				Timer* t = &m.timers [reg];
-				if ( time >= t->next_time )
-					t = run_timer_( t, time );
+			if (static_cast<unsigned>(reg) < timer_count) // 90%
+			{
+				auto t = &this->m.timers[reg];
+				if (time >= t->next_time)
+					t = this->run_timer_(t, time);
 				result = t->counter;
 				t->counter = 0;
 			}
 			// Other registers
-			else if ( reg < 0 ) // 10%
-			{
-				result = cpu_read_smp_reg( reg + r_t0out, time );
-			}
+			else if (reg < 0) // 10%
+				result = this->cpu_read_smp_reg(reg + r_t0out, time);
 			else // 1%
 			{
-				assert( reg + (r_t0out + 0xF0 - 0x10000) < 0x100 );
-				result = cpu_read( reg + (r_t0out + 0xF0 - 0x10000), time );
-			}
-		}
-	}
-	
+				assert(reg + (r_t0out + 0xF0 - 0x10000) < 0x100);
+				result = this->cpu_read(reg + (r_t0out + 0xF0 - 0x10000), time);
+			}
+		}
+	}
+
 	return result;
 }
-
 
 //// Run
 
 // Prefix and suffix for CPU emulator function
 #define SPC_CPU_RUN_FUNC \
-BOOST::uint8_t* SNES_SPC::run_until_( time_t end_time )\
-{\
-	rel_time_t rel_time = m.spc_time - end_time;\
-	/*assert( rel_time <= 0 );*/\
-	m.spc_time = end_time;\
-	m.dsp_time += rel_time;\
-	m.timers [0].next_time += rel_time;\
-	m.timers [1].next_time += rel_time;\
-	m.timers [2].next_time += rel_time;
+uint8_t *SNES_SPC::run_until_(time_t end_time) \
+{ \
+	rel_time_t rel_time = this->m.spc_time - end_time; \
+	/*assert( rel_time <= 0 );*/ \
+	this->m.spc_time = end_time; \
+	this->m.dsp_time += rel_time; \
+	this->m.timers[0].next_time += rel_time; \
+	this->m.timers[1].next_time += rel_time; \
+	this->m.timers[2].next_time += rel_time;
 
 #define SPC_CPU_RUN_FUNC_END \
-	m.spc_time += rel_time;\
-	m.dsp_time -= rel_time;\
-	m.timers [0].next_time -= rel_time;\
-	m.timers [1].next_time -= rel_time;\
-	m.timers [2].next_time -= rel_time;\
-	/*assert( m.spc_time >= end_time );*/\
-	return &REGS [r_cpuio0];\
-}
-
-int const cpu_lag_max = 12 - 1; // DIV YA,X takes 12 clocks
-
-void SNES_SPC::end_frame( time_t end_time )
+	this->m.spc_time += rel_time; \
+	this->m.dsp_time -= rel_time; \
+	this->m.timers[0].next_time -= rel_time; \
+	this->m.timers[1].next_time -= rel_time; \
+	this->m.timers[2].next_time -= rel_time; \
+	/*assert( m.spc_time >= end_time );*/ \
+	return &this->m.smp_regs[0][r_cpuio0]; \
+}
+
+static const int cpu_lag_max = 12 - 1; // DIV YA,X takes 12 clocks
+
+void SNES_SPC::end_frame(time_t end_time)
 {
 	// Catch CPU up to as close to end as possible. If final instruction
 	// would exceed end, does NOT execute it and leaves m.spc_time < end.
-	if ( end_time > m.spc_time )
-		run_until_( end_time );
-	
-	m.spc_time     -= end_time;
-	m.extra_clocks += end_time;
-	
+	if (end_time > this->m.spc_time)
+		this->run_until_(end_time);
+
+	this->m.spc_time -= end_time;
+	this->m.extra_clocks += end_time;
+
 	// Greatest number of clocks early that emulation can stop early due to
 	// not being able to execute current instruction without going over
 	// allowed time.
-	assert( -cpu_lag_max <= m.spc_time && m.spc_time <= cpu_lag_max );
-	
+	assert(-cpu_lag_max <= this->m.spc_time && this->m.spc_time <= cpu_lag_max);
+
 	// Catch timers up to CPU
-	for ( int i = 0; i < timer_count; i++ )
-		run_timer( &m.timers [i], 0 );
-	
+	for (int i = 0; i < timer_count; ++i)
+		this->run_timer(&this->m.timers [i], 0);
+
 	// Catch DSP up to CPU
-	if ( m.dsp_time < 0 )
-	{
-		RUN_DSP( 0, max_reg_time );
-	}
-	
+	if (this->m.dsp_time < 0)
+		this->RUN_DSP(0);
+
 	// Save any extra samples beyond what should be generated
-	if ( m.buf_begin )
-		save_extra();
+	if (this->m.buf_begin)
+		this->save_extra();
 }
 
 // Inclusion here allows static memory access functions and better optimization

--- a/src/in_snsf/snes9x/apu/SNES_SPC.h
+++ b/src/in_snsf/snes9x/apu/SNES_SPC.h
@@ -7,32 +7,28 @@
 #include "SPC_DSP.h"
 #include "blargg_endian.h"
 
-#ifdef DEBUGGER
-#include "snes9x.h"
-#include "display.h"
-#include "debug.h"
-#endif
-
-struct SNES_SPC {
+// (n ? n : 256)
+template<typename T> inline T IF_0_THEN_256(const T &n) { return static_cast<uint8_t>(n - 1) + 1; }
+
+struct SNES_SPC
+{
 public:
-	typedef BOOST::uint8_t uint8_t;
-	
 	// Must be called once before using
-	blargg_err_t init();
-	
+	void init();
+
 	// Sample pairs generated per second
 	enum { sample_rate = 32000 };
-	
-// Emulator use
-	
+
+	// Emulator use
+
 	// Sets IPL ROM data. Library does not include ROM data. Most SPC music files
 	// don't need ROM, but a full emulator must provide this.
 	enum { rom_size = 0x40 };
-	void init_rom( uint8_t const rom [rom_size] );
+	void init_rom(const uint8_t rom[rom_size]);
 
 	// Sets destination for output samples
 	typedef short sample_t;
-	void set_output( sample_t* out, int out_size );
+	void set_output(sample_t *out, int out_size);
 
 	// Number of samples written to output since last set
 	int sample_count() const;
@@ -49,126 +45,78 @@
 	typedef int time_t;
 	enum { clock_rate = 1024000 };
 	enum { clocks_per_sample = 32 };
-	
+
 	// Emulated port read/write at specified time
 	enum { port_count = 4 };
-	int  read_port ( time_t, int port );
-	void write_port( time_t, int port, int data );
+	int read_port(time_t, int port);
+	void write_port(time_t, int port, int data);
 
 	// Runs SPC to end_time and starts a new time frame at 0
-	void end_frame( time_t end_time );
-	
-// Sound control
-	
+	void end_frame(time_t end_time);
+
+	// Sound control
+
 	// Mutes voices corresponding to non-zero bits in mask (issues repeated KOFF events).
 	// Reduces emulation accuracy.
 	enum { voice_count = 8 };
-	void mute_voices( int mask );
-	
+	void mute_voices(int mask);
+
 	// If true, prevents channels and global volumes from being phase-negated.
 	// Only supported by fast DSP.
-	void disable_surround( bool disable = true );
-	
+	void disable_surround(bool disable = true );
+
 	// Sets tempo, where tempo_unit = normal, tempo_unit / 2 = half speed, etc.
 	enum { tempo_unit = 0x100 };
-	void set_tempo( int );
-
-// SPC music files
-
-	// Loads SPC data into emulator
-	enum { spc_min_file_size = 0x10180 };
-	enum { spc_file_size     = 0x10200 };
-	blargg_err_t load_spc( void const* in, long size );
-	
+	void set_tempo(int);
+
+	// SPC music files
+
 	// Clears echo region. Useful after loading an SPC as many have garbage in echo.
 	void clear_echo();
 
 	// Plays for count samples and write samples to out. Discards samples if out
 	// is NULL. Count must be a multiple of 2 since output is stereo.
-	blargg_err_t play( int count, sample_t* out );
-	
+	void play(int count, sample_t *out);
+
 	// Skips count samples. Several times faster than play() when using fast DSP.
-	blargg_err_t skip( int count );
-	
-// State save/load (only available with accurate DSP)
-
-#if !SPC_NO_COPY_STATE_FUNCS
-	// Saves/loads state
-	enum { state_size = 68 * 1024L }; // maximum space needed when saving
-	typedef SPC_DSP::copy_func_t copy_func_t;
-	void copy_state( unsigned char** io, copy_func_t );
-	
-	// Writes minimal header to spc_out
-	static void init_header( void* spc_out );
-
-	// Saves emulator state as SPC file data. Writes spc_file_size bytes to spc_out.
-	// Does not set up SPC header; use init_header() for that.
-	void save_spc( void* spc_out );
-
-	// Returns true if new key-on events occurred since last check. Useful for
-	// trimming silence while saving an SPC.
-	bool check_kon();
-#endif
-
-//// Snes9x Accessor
-
-	void	spc_allow_time_overflow( bool );
-
-	void    dsp_set_spc_snapshot_callback(void (*callback)());
-	void    dsp_dump_spc_snapshot();
-	void    dsp_set_stereo_switch( int );
-	uint8_t dsp_reg_value( int, int );
-	int     dsp_envx_value( int );
-
-//// Snes9x Debugger
-
-#ifdef DEBUGGER
-	void	debug_toggle_trace();
-	bool    debug_is_enabled();
-	void	debug_do_trace( int, int, int, uint8_t const *, uint8_t *, int, int, int, int );
-	void	debug_op_print( char *, int, int, int, uint8_t const *, uint8_t *, int, int, int, int );
-	void	debug_io_print( char * );
-#endif
+	void skip(int count);
+
+	//// Snes9x Accessor
+
+	void spc_allow_time_overflow(bool);
+
+	void dsp_set_stereo_switch(int);
+	uint8_t dsp_reg_value(int, int);
+	int dsp_envx_value(int);
 
 public:
-	BLARGG_DISABLE_NOTHROW
-	
-	typedef BOOST::uint16_t uint16_t;
-	
 	// Time relative to m_spc_time. Speeds up code a bit by eliminating need to
 	// constantly add m_spc_time to time from CPU. CPU uses time that ends at
 	// 0 to eliminate reloading end time every instruction. It pays off.
 	typedef int rel_time_t;
-	
+
 	struct Timer
 	{
 		rel_time_t next_time; // time of next event
 		int prescaler;
 		int period;
 		int divider;
-		int enabled;
+		bool enabled;
 		int counter;
 	};
 	enum { reg_count = 0x10 };
 	enum { timer_count = 3 };
 	enum { extra_size = SPC_DSP::extra_size };
-	
-	enum { signature_size = 35 };
-	
+
 private:
 	SPC_DSP dsp;
-	
-	#if SPC_LESS_ACCURATE
-		static signed char const reg_times_ [256];
-		signed char reg_times [256];
-	#endif
-	
+
 	struct state_t
 	{
-		Timer timers [timer_count];
-		
-		uint8_t smp_regs [2] [reg_count];
-		
+		Timer timers[timer_count];
+
+		uint8_t smp_regs[2][reg_count];
+
 		struct
 		{
 			int pc;
@@ -178,140 +126,115 @@
 			int psw;
 			int sp;
 		} cpu_regs;
-		
-		rel_time_t  dsp_time;
-		time_t      spc_time;
-		bool        echo_accessed;
-		
-		int         tempo;
-		int         skipped_kon;
-		int         skipped_koff;
-		const char* cpu_error;
-		
-		int         extra_clocks;
-		sample_t*   buf_begin;
-		sample_t const* buf_end;
-		sample_t*   extra_pos;
-		sample_t    extra_buf [extra_size];
-		
-		int         rom_enabled;
-		uint8_t     rom    [rom_size];
-		uint8_t     hi_ram [rom_size];
-		
-		unsigned char cycle_table [256];
-		
+
+		rel_time_t dsp_time;
+		time_t spc_time;
+
+		int tempo;
+
+		int extra_clocks;
+		sample_t *buf_begin;
+		const sample_t *buf_end;
+		sample_t *extra_pos;
+		sample_t extra_buf[extra_size];
+
+		bool rom_enabled;
+		uint8_t rom[rom_size];
+		uint8_t hi_ram[rom_size];
+
+		unsigned char cycle_table[256];
+
 		struct
 		{
 			// padding to neutralize address overflow
-			union {
-				uint8_t padding1 [0x100];
+			union
+			{
+				uint8_t padding1[0x100];
 				uint16_t align; // makes compiler align data for 16-bit access
-			} padding1 [1];
-			uint8_t ram      [0x10000];
-			uint8_t padding2 [0x100];
+			} padding1[1];
+			uint8_t ram[0x10000];
+			uint8_t padding2[0x100];
 		} ram;
 	};
 	state_t m;
-	
+
 	enum { rom_addr = 0xFFC0 };
-	
+
 	enum { skipping_time = 127 };
-	
+
 	// Value that padding should be filled with
 	enum { cpu_pad_fill = 0xFF };
-	
-	enum {
-        r_test     = 0x0, r_control  = 0x1,
-        r_dspaddr  = 0x2, r_dspdata  = 0x3,
-        r_cpuio0   = 0x4, r_cpuio1   = 0x5,
-        r_cpuio2   = 0x6, r_cpuio3   = 0x7,
-        r_f8       = 0x8, r_f9       = 0x9,
-        r_t0target = 0xA, r_t1target = 0xB, r_t2target = 0xC,
-        r_t0out    = 0xD, r_t1out    = 0xE, r_t2out    = 0xF
+
+	enum
+	{
+		r_test = 0x0,
+		r_control = 0x1,
+		r_dspaddr = 0x2,
+		r_dspdata = 0x3,
+		r_cpuio0 = 0x4,
+		r_cpuio1 = 0x5,
+		r_cpuio2 = 0x6,
+		r_cpuio3 = 0x7,
+		r_f8 = 0x8,
+		r_f9 = 0x9,
+		r_t0target = 0xA,
+		r_t1target = 0xB,
+		r_t2target = 0xC,
+		r_t0out = 0xD,
+		r_t1out = 0xE,
+		r_t2out = 0xF
 	};
-	
+
 	void timers_loaded();
-	void enable_rom( int enable );
+	void enable_rom(bool enable);
 	void reset_buf();
 	void save_extra();
-	void load_regs( uint8_t const in [reg_count] );
+	void load_regs(const uint8_t in[reg_count]);
 	void ram_loaded();
 	void regs_loaded();
 	void reset_time_regs();
-	void reset_common( int timer_counter_init );
+	void reset_common(int timer_counter_init);
+
+	Timer *run_timer_(Timer *t, rel_time_t);
+	Timer *run_timer(Timer *t, rel_time_t);
+	void RUN_DSP(rel_time_t);
+	int dsp_read(rel_time_t);
+	void dsp_write(int data, rel_time_t);
+	void cpu_write_smp_reg_(int data, rel_time_t, int addr);
+	void cpu_write_smp_reg(int data, rel_time_t, int addr);
+	void cpu_write_high(int data, int i, rel_time_t);
+	void cpu_write(int data, int addr, rel_time_t);
+	int cpu_read_smp_reg(int i, rel_time_t);
+	int cpu_read(int addr, rel_time_t);
+	unsigned CPU_mem_bit(const uint8_t *pc, rel_time_t);
+
+	bool check_echo_access(int addr);
+	uint8_t *run_until_(time_t end_time);
+
+	// Snes9x timing hack
+	bool allow_time_overflow;
+};
+
+inline int SNES_SPC::sample_count() const { return (this->m.extra_clocks >> 5) * 2; }
+
+inline int SNES_SPC::read_port(time_t t, int port)
+{
+	assert(static_cast<unsigned>(port) < port_count);
+	return this->run_until_(t)[port];
+}
+
+inline void SNES_SPC::write_port(time_t t, int port, int data)
+{
+	assert(static_cast<unsigned>(port) < port_count);
+	this->run_until_(t)[0x10 + port] = data;
+	this->m.ram.ram[0xF4 + port] = data;
+}
+
+inline void SNES_SPC::mute_voices(int mask) { this->dsp.mute_voices(mask); }
 	
-	Timer* run_timer_      ( Timer* t, rel_time_t );
-	Timer* run_timer       ( Timer* t, rel_time_t );
-	int dsp_read           ( rel_time_t );
-	void dsp_write         ( int data, rel_time_t );
-	void cpu_write_smp_reg_( int data, rel_time_t, int addr );
-	void cpu_write_smp_reg ( int data, rel_time_t, int addr );
-	void cpu_write_high    ( int data, int i, rel_time_t );
-	void cpu_write         ( int data, int addr, rel_time_t );
-	int cpu_read_smp_reg   ( int i, rel_time_t );
-	int cpu_read           ( int addr, rel_time_t );
-	unsigned CPU_mem_bit   ( uint8_t const* pc, rel_time_t );
-	
-	bool check_echo_access ( int addr );
-	uint8_t* run_until_( time_t end_time );
-	
-	struct spc_file_t
-	{
-		char    signature [signature_size];
-		uint8_t has_id666;
-		uint8_t version;
-		uint8_t pcl, pch;
-		uint8_t a;
-		uint8_t x;
-		uint8_t y;
-		uint8_t psw;
-		uint8_t sp;
-		char    text [212];
-		uint8_t ram [0x10000];
-		uint8_t dsp [128];
-		uint8_t unused [0x40];
-		uint8_t ipl_rom [0x40];
-	};
-
-	static char const signature [signature_size + 1];
-	
-	void save_regs( uint8_t out [reg_count] );
-
-// Snes9x timing hack
-	bool allow_time_overflow;
-// Snes9x debugger
-#ifdef DEBUGGER
-	FILE *apu_trace;
-	bool debug_trace;
+inline void SNES_SPC::disable_surround(bool disable) { this->dsp.disable_surround(disable); }
+
+inline void SNES_SPC::spc_allow_time_overflow(bool allow) { this->allow_time_overflow = allow; }
+
 #endif
-};
-
-#include <assert.h>
-
-inline int SNES_SPC::sample_count() const { return (m.extra_clocks >> 5) * 2; }
-
-inline int SNES_SPC::read_port( time_t t, int port )
-{
-	assert( (unsigned) port < port_count );
-	return run_until_( t ) [port];
-}
-
-inline void SNES_SPC::write_port( time_t t, int port, int data )
-{
-	assert( (unsigned) port < port_count );
-	run_until_( t ) [0x10 + port] = data;
-	m.ram.ram [0xF4 + port] = data;
-}
-
-inline void SNES_SPC::mute_voices( int mask ) { dsp.mute_voices( mask ); }
-	
-inline void SNES_SPC::disable_surround( bool disable ) { dsp.disable_surround( disable ); }
-
-#if !SPC_NO_COPY_STATE_FUNCS
-inline bool SNES_SPC::check_kon() { return dsp.check_kon(); }
-#endif
-
-inline void SNES_SPC::spc_allow_time_overflow( bool allow ) { allow_time_overflow = allow; }
-
-#endif
-
+

--- a/src/in_snsf/snes9x/apu/SNES_SPC_misc.cpp
+++ b/src/in_snsf/snes9x/apu/SNES_SPC_misc.cpp
@@ -2,9 +2,9 @@
 
 // snes_spc 0.9.0. http://www.slack.net/~ant/
 
+#include <algorithm>
+#include <cstring>
 #include "SNES_SPC.h"
-
-#include <string.h>
 
 /* Copyright (C) 2004-2007 Shay Green. This module is free software; you
 can redistribute it and/or modify it under the terms of the GNU Lesser
@@ -17,840 +17,294 @@
 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"
-
-#define RAM         (m.ram.ram)
-#define REGS        (m.smp_regs [0])
-#define REGS_IN     (m.smp_regs [1])
-
-// (n ? n : 256)
-#define IF_0_THEN_256( n ) ((uint8_t) ((n) - 1) + 1)
-
-
 //// Init
 
-blargg_err_t SNES_SPC::init()
-{
-	memset( &m, 0, sizeof m );
-	dsp.init( RAM );
-	
-	m.tempo = tempo_unit;
-	
+void SNES_SPC::init()
+{
+	memset(&this->m, 0, sizeof(this->m));
+	this->dsp.init(this->m.ram.ram);
+
+	this->m.tempo = tempo_unit;
+
 	// Most SPC music doesn't need ROM, and almost all the rest only rely
 	// on these two bytes
-	m.rom [0x3E] = 0xFF;
-	m.rom [0x3F] = 0xC0;
-	
-	static unsigned char const cycle_table [128] =
-	{//   01   23   45   67   89   AB   CD   EF
-	    0x28,0x47,0x34,0x36,0x26,0x54,0x54,0x68, // 0
-	    0x48,0x47,0x45,0x56,0x55,0x65,0x22,0x46, // 1
-	    0x28,0x47,0x34,0x36,0x26,0x54,0x54,0x74, // 2
-	    0x48,0x47,0x45,0x56,0x55,0x65,0x22,0x38, // 3
-	    0x28,0x47,0x34,0x36,0x26,0x44,0x54,0x66, // 4
-	    0x48,0x47,0x45,0x56,0x55,0x45,0x22,0x43, // 5
-	    0x28,0x47,0x34,0x36,0x26,0x44,0x54,0x75, // 6
-	    0x48,0x47,0x45,0x56,0x55,0x55,0x22,0x36, // 7
-	    0x28,0x47,0x34,0x36,0x26,0x54,0x52,0x45, // 8
-	    0x48,0x47,0x45,0x56,0x55,0x55,0x22,0xC5, // 9
-	    0x38,0x47,0x34,0x36,0x26,0x44,0x52,0x44, // A
-	    0x48,0x47,0x45,0x56,0x55,0x55,0x22,0x34, // B
-	    0x38,0x47,0x45,0x47,0x25,0x64,0x52,0x49, // C
-	    0x48,0x47,0x56,0x67,0x45,0x55,0x22,0x83, // D
-	    0x28,0x47,0x34,0x36,0x24,0x53,0x43,0x40, // E
-	    0x48,0x47,0x45,0x56,0x34,0x54,0x22,0x60, // F
+	this->m.rom[0x3E] = 0xFF;
+	this->m.rom[0x3F] = 0xC0;
+
+	static const unsigned char cycle_table[] =
+	{
+		//01    23    45    67    89    AB    CD    EF
+		0x28, 0x47, 0x34, 0x36, 0x26, 0x54, 0x54, 0x68, // 0
+		0x48, 0x47, 0x45, 0x56, 0x55, 0x65, 0x22, 0x46, // 1
+		0x28, 0x47, 0x34, 0x36, 0x26, 0x54, 0x54, 0x74, // 2
+		0x48, 0x47, 0x45, 0x56, 0x55, 0x65, 0x22, 0x38, // 3
+		0x28, 0x47, 0x34, 0x36, 0x26, 0x44, 0x54, 0x66, // 4
+		0x48, 0x47, 0x45, 0x56, 0x55, 0x45, 0x22, 0x43, // 5
+		0x28, 0x47, 0x34, 0x36, 0x26, 0x44, 0x54, 0x75, // 6
+		0x48, 0x47, 0x45, 0x56, 0x55, 0x55, 0x22, 0x36, // 7
+		0x28, 0x47, 0x34, 0x36, 0x26, 0x54, 0x52, 0x45, // 8
+		0x48, 0x47, 0x45, 0x56, 0x55, 0x55, 0x22, 0xC5, // 9
+		0x38, 0x47, 0x34, 0x36, 0x26, 0x44, 0x52, 0x44, // A
+		0x48, 0x47, 0x45, 0x56, 0x55, 0x55, 0x22, 0x34, // B
+		0x38, 0x47, 0x45, 0x47, 0x25, 0x64, 0x52, 0x49, // C
+		0x48, 0x47, 0x56, 0x67, 0x45, 0x55, 0x22, 0x83, // D
+		0x28, 0x47, 0x34, 0x36, 0x24, 0x53, 0x43, 0x40, // E
+		0x48, 0x47, 0x45, 0x56, 0x34, 0x54, 0x22, 0x60  // F
 	};
-	
+
 	// unpack cycle table
-	for ( int i = 0; i < 128; i++ )
-	{
-		int n = cycle_table [i];
-		m.cycle_table [i * 2 + 0] = n >> 4;
-		m.cycle_table [i * 2 + 1] = n & 0x0F;
-	}
-
-	allow_time_overflow = false;
-
-	dsp.rom = m.rom;
-	dsp.hi_ram = m.hi_ram;
-
-#ifdef DEBUGGER
-	apu_trace = NULL;
-	debug_trace = false;
+	for (int i = 0; i < 128; ++i)
+	{
+		int n = cycle_table[i];
+		this->m.cycle_table[i * 2] = n >> 4;
+		this->m.cycle_table[i * 2 + 1] = n & 0x0F;
+	}
+
+	this->allow_time_overflow = false;
+
+	this->dsp.rom = this->m.rom;
+	this->dsp.hi_ram = this->m.hi_ram;
+
+	this->reset();
+}
+
+void SNES_SPC::init_rom(const uint8_t in[rom_size])
+{
+	std::copy(&in[0], &in[rom_size], &this->m.rom[0]);
+}
+
+void SNES_SPC::set_tempo(int t)
+{
+	this->m.tempo = t;
+	static const int timer2_shift = 4; // 64 kHz
+	static const int other_shift = 3; //  8 kHz
+
+#if SPC_DISABLE_TEMPO
+	this->m.timers[2].prescaler = timer2_shift;
+	this->m.timers[1].prescaler = timer2_shift + other_shift;
+	this->m.timers[0].prescaler = timer2_shift + other_shift;
+#else
+	if (!t)
+		t = 1;
+	static const int timer2_rate = 1 << timer2_shift;
+	int rate = (timer2_rate * tempo_unit + (t >> 1)) / t;
+	if (rate < timer2_rate / 4)
+		rate = timer2_rate / 4; // max 4x tempo
+	this->m.timers[2].prescaler = rate;
+	this->m.timers[1].prescaler = rate << other_shift;
+	this->m.timers[0].prescaler = rate << other_shift;
 #endif
-
-	#if SPC_LESS_ACCURATE
-		memcpy( reg_times, reg_times_, sizeof reg_times );
-	#endif
-	
-	reset();
-	return 0;
-}
-
-void SNES_SPC::init_rom( uint8_t const in [rom_size] )
-{
-	memcpy( m.rom, in, sizeof m.rom );
-}
-
-void SNES_SPC::set_tempo( int t )
-{
-	m.tempo = t;
-	int const timer2_shift = 4; // 64 kHz
-	int const other_shift  = 3; //  8 kHz
-	
-	#if SPC_DISABLE_TEMPO
-		m.timers [2].prescaler = timer2_shift;
-		m.timers [1].prescaler = timer2_shift + other_shift;
-		m.timers [0].prescaler = timer2_shift + other_shift;
-	#else
-		if ( !t )
-			t = 1;
-		int const timer2_rate  = 1 << timer2_shift;
-		int rate = (timer2_rate * tempo_unit + (t >> 1)) / t;
-		if ( rate < timer2_rate / 4 )
-			rate = timer2_rate / 4; // max 4x tempo
-		m.timers [2].prescaler = rate;
-		m.timers [1].prescaler = rate << other_shift;
-		m.timers [0].prescaler = rate << other_shift;
-	#endif
 }
 
 // Timer registers have been loaded. Applies these to the timers. Does not
 // reset timer prescalers or dividers.
 void SNES_SPC::timers_loaded()
 {
-	int i;
-	for ( i = 0; i < timer_count; i++ )
-	{
-		Timer* t = &m.timers [i];
-		t->period  = IF_0_THEN_256( REGS [r_t0target + i] );
-		t->enabled = REGS [r_control] >> i & 1;
-		t->counter = REGS_IN [r_t0out + i] & 0x0F;
-	}
-	
-	set_tempo( m.tempo );
+	for (int  i = 0; i < timer_count; ++i)
+	{
+		auto &t = this->m.timers[i];
+		t.period = IF_0_THEN_256(this->m.smp_regs[0][r_t0target + i]);
+		t.enabled = !!((this->m.smp_regs[0][r_control] >> i) & 1);
+		t.counter = this->m.smp_regs[1][r_t0out + i] & 0x0F;
+	}
+
+	this->set_tempo(this->m.tempo);
 }
 
 // Loads registers from unified 16-byte format
-void SNES_SPC::load_regs( uint8_t const in [reg_count] )
-{
-	memcpy( REGS, in, reg_count );
-	memcpy( REGS_IN, REGS, reg_count );
-	
+void SNES_SPC::load_regs(const uint8_t in[reg_count])
+{
+	std::copy(&in[0], &in[reg_count], &this->m.smp_regs[0][0]);
+	std::copy(&this->m.smp_regs[0][0], &this->m.smp_regs[0][reg_count], &this->m.smp_regs[1][0]);
+
 	// These always read back as 0
-	REGS_IN [r_test    ] = 0;
-	REGS_IN [r_control ] = 0;
-	REGS_IN [r_t0target] = 0;
-	REGS_IN [r_t1target] = 0;
-	REGS_IN [r_t2target] = 0;
+	this->m.smp_regs[1][r_test] = this->m.smp_regs[1][r_control] = this->m.smp_regs[1][r_t0target] = this->m.smp_regs[1][r_t1target] = this->m.smp_regs[1][r_t2target] = 0;
 }
 
 // RAM was just loaded from SPC, with $F0-$FF containing SMP registers
 // and timer counts. Copies these to proper registers.
 void SNES_SPC::ram_loaded()
 {
-	m.rom_enabled = dsp.rom_enabled = 0;
-	load_regs( &RAM [0xF0] );
-	
+	this->m.rom_enabled = this->dsp.rom_enabled = false;
+	this->load_regs(&this->m.ram.ram[0xF0]);
+
 	// Put STOP instruction around memory to catch PC underflow/overflow
-	memset( m.ram.padding1, cpu_pad_fill, sizeof m.ram.padding1 );
-	memset( m.ram.padding2, cpu_pad_fill, sizeof m.ram.padding2 );
+	memset(this->m.ram.padding1, cpu_pad_fill, sizeof(this->m.ram.padding1));
+	memset(this->m.ram.padding2, cpu_pad_fill, sizeof(this->m.ram.padding2));
 }
 
 // Registers were just loaded. Applies these new values.
 void SNES_SPC::regs_loaded()
 {
-	enable_rom( REGS [r_control] & 0x80 );
-	timers_loaded();
+	this->enable_rom(!!(this->m.smp_regs[0][r_control] & 0x80));
+	this->timers_loaded();
 }
 
 void SNES_SPC::reset_time_regs()
 {
-	m.cpu_error     = 0;
-	m.echo_accessed = 0;
-	m.spc_time      = 0;
-	m.dsp_time      = 0;
-	#if SPC_LESS_ACCURATE
-		m.dsp_time = clocks_per_sample + 1;
-	#endif
-	
-	for ( int i = 0; i < timer_count; i++ )
-	{
-		Timer* t = &m.timers [i];
-		t->next_time = 1;
-		t->divider   = 0;
-	}
-	
-	regs_loaded();
-	
-	m.extra_clocks = 0;
-	reset_buf();
-}
-
-void SNES_SPC::reset_common( int timer_counter_init )
-{
-	int i;
-	for ( i = 0; i < timer_count; i++ )
-		REGS_IN [r_t0out + i] = timer_counter_init;
-	
+	this->m.spc_time = 0;
+	this->m.dsp_time = 0;
+
+	for (int i = 0; i < timer_count; ++i)
+	{
+		auto &t = this->m.timers[i];
+		t.next_time = 1;
+		t.divider = 0;
+	}
+
+	this->regs_loaded();
+
+	this->m.extra_clocks = 0;
+	this->reset_buf();
+}
+
+void SNES_SPC::reset_common(int timer_counter_init)
+{
+	for (int i = 0; i < timer_count; ++i)
+		this->m.smp_regs[1][r_t0out + i] = timer_counter_init;
+
 	// Run IPL ROM
-	memset( &m.cpu_regs, 0, sizeof m.cpu_regs );
-	m.cpu_regs.pc = rom_addr;
-	
-	REGS [r_test   ] = 0x0A;
-	REGS [r_control] = 0xB0; // ROM enabled, clear ports
-	for ( i = 0; i < port_count; i++ )
-		REGS_IN [r_cpuio0 + i] = 0;
-	
-	reset_time_regs();
+	memset(&this->m.cpu_regs, 0, sizeof(this->m.cpu_regs));
+	this->m.cpu_regs.pc = rom_addr;
+
+	this->m.smp_regs[0][r_test] = 0x0A;
+	this->m.smp_regs[0][r_control] = 0xB0; // ROM enabled, clear ports
+	std::fill(&this->m.smp_regs[1][r_cpuio0], &this->m.smp_regs[1][r_cpuio0 + port_count], 0);
+
+	this->reset_time_regs();
 }
 
 void SNES_SPC::soft_reset()
 {
-	reset_common( 0 );
-	dsp.soft_reset();
+	this->reset_common(0);
+	this->dsp.soft_reset();
 }
 
 void SNES_SPC::reset()
 {
-	m.cpu_regs.pc  = 0xFFC0;
-	m.cpu_regs.a   = 0x00;
-	m.cpu_regs.x   = 0x00;
-	m.cpu_regs.y   = 0x00;
-	m.cpu_regs.psw = 0x02;
-	m.cpu_regs.sp  = 0xEF;
-	memset( RAM, 0x00, 0x10000 );
-	ram_loaded();
-	reset_common( 0x0F );
-	dsp.reset();
-}
-
-char const SNES_SPC::signature [signature_size + 1] =
-		"SNES-SPC700 Sound File Data v0.30\x1A\x1A";
-
-blargg_err_t SNES_SPC::load_spc( void const* data, long size )
-{
-	spc_file_t const* const spc = (spc_file_t const*) data;
-	
-	// be sure compiler didn't insert any padding into fle_t
-	assert( sizeof (spc_file_t) == spc_min_file_size + 0x80 );
-	
-	// Check signature and file size
-	if ( size < signature_size || memcmp( spc, signature, 27 ) )
-		return "Not an SPC file";
-	
-	if ( size < spc_min_file_size )
-		return "Corrupt SPC file";
-	
-	// CPU registers
-	m.cpu_regs.pc  = spc->pch * 0x100 + spc->pcl;
-	m.cpu_regs.a   = spc->a;
-	m.cpu_regs.x   = spc->x;
-	m.cpu_regs.y   = spc->y;
-	m.cpu_regs.psw = spc->psw;
-	m.cpu_regs.sp  = spc->sp;
-	
-	// RAM and registers
-	memcpy( RAM, spc->ram, 0x10000 );
-	ram_loaded();
-	
-	// DSP registers
-	dsp.load( spc->dsp );
-	
-	reset_time_regs();
-	
-	return 0;
+	this->m.cpu_regs.pc = 0xFFC0;
+	this->m.cpu_regs.a = this->m.cpu_regs.x = this->m.cpu_regs.y = 0x00;
+	this->m.cpu_regs.psw = 0x02;
+	this->m.cpu_regs.sp = 0xEF;
+	std::fill(&this->m.ram.ram[0], &this->m.ram.ram[0x10000], 0);
+	this->ram_loaded();
+	this->reset_common(0x0F);
+	this->dsp.reset();
 }
 
 void SNES_SPC::clear_echo()
 {
-	if ( !(dsp.read( SPC_DSP::r_flg ) & 0x20) )
-	{
-		int addr = 0x100 * dsp.read( SPC_DSP::r_esa );
-		int end  = addr + 0x800 * (dsp.read( SPC_DSP::r_edl ) & 0x0F);
-		if ( end > 0x10000 )
+	if (!(this->dsp.read(SPC_DSP::r_flg) & 0x20))
+	{
+		int addr = 0x100 * this->dsp.read(SPC_DSP::r_esa);
+		int end  = addr + 0x800 * (this->dsp.read(SPC_DSP::r_edl) & 0x0F);
+		if (end > 0x10000)
 			end = 0x10000;
-		memset( &RAM [addr], 0xFF, end - addr );
-	}
-}
-
+		std::fill(&this->m.ram.ram[addr], &this->m.ram.ram[end], 0xFF);
+	}
+}
 
 //// Sample output
 
 void SNES_SPC::reset_buf()
 {
 	// Start with half extra buffer of silence
-	sample_t* out = m.extra_buf;
-	while ( out < &m.extra_buf [extra_size / 2] )
+	sample_t *out = this->m.extra_buf;
+	while (out < &this->m.extra_buf[extra_size / 2])
 		*out++ = 0;
-	
-	m.extra_pos = out;
-	m.buf_begin = 0;
-	
-	dsp.set_output( 0, 0 );
-}
-
-void SNES_SPC::set_output( sample_t* out, int size )
-{
-	require( (size & 1) == 0 ); // size must be even
-	
-	m.extra_clocks &= clocks_per_sample - 1;
-	if ( out )
-	{
-		sample_t const* out_end = out + size;
-		m.buf_begin = out;
-		m.buf_end   = out_end;
-		
+
+	this->m.extra_pos = out;
+	this->m.buf_begin = nullptr;
+
+	this->dsp.set_output(nullptr, 0);
+}
+
+void SNES_SPC::set_output(sample_t *out, int size)
+{
+	assert(!(size & 1)); // size must be even
+
+	this->m.extra_clocks &= clocks_per_sample - 1;
+	if (out)
+	{
+		auto out_end = out + size;
+		this->m.buf_begin = out;
+		this->m.buf_end = out_end;
+
 		// Copy extra to output
-		sample_t const* in = m.extra_buf;
-		while ( in < m.extra_pos && out < out_end )
+		auto in = this->m.extra_buf;
+		while (in < this->m.extra_pos && out < out_end)
 			*out++ = *in++;
-		
+
 		// Handle output being full already
-		if ( out >= out_end )
+		if (out >= out_end)
 		{
 			// Have DSP write to remaining extra space
-			out     = dsp.extra();
-			out_end = &dsp.extra() [extra_size];
-			
+			out = this->dsp.extra();
+			out_end = &this->dsp.extra()[extra_size];
+
 			// Copy any remaining extra samples as if DSP wrote them
-			while ( in < m.extra_pos )
+			while (in < m.extra_pos)
 				*out++ = *in++;
-			assert( out <= out_end );
+			assert(out <= out_end);
 		}
-		
-		dsp.set_output( out, out_end - out );
+
+		this->dsp.set_output(out, out_end - out);
 	}
 	else
-	{
-		reset_buf();
-	}
+		this->reset_buf();
 }
 
 void SNES_SPC::save_extra()
 {
 	// Get end pointers
-	sample_t const* main_end = m.buf_end;     // end of data written to buf
-	sample_t const* dsp_end  = dsp.out_pos(); // end of data written to dsp.extra()
-	if ( m.buf_begin <= dsp_end && dsp_end <= main_end )
+	auto main_end = this->m.buf_end; // end of data written to buf
+	auto dsp_end = this->dsp.out_pos(); // end of data written to dsp.extra()
+	if (this->m.buf_begin <= dsp_end && dsp_end <= main_end)
 	{
 		main_end = dsp_end;
-		dsp_end  = dsp.extra(); // nothing in DSP's extra
-	}
-	
+		dsp_end = this->dsp.extra(); // nothing in DSP's extra
+	}
+
 	// Copy any extra samples at these ends into extra_buf
-	sample_t* out = m.extra_buf;
-	sample_t const* in;
-	for ( in = m.buf_begin + sample_count(); in < main_end; in++ )
+	auto out = this->m.extra_buf;
+	for (auto in = this->m.buf_begin + this->sample_count(); in < main_end; ++in)
 		*out++ = *in;
-	for ( in = dsp.extra(); in < dsp_end ; in++ )
+	for (auto in = this->dsp.extra(); in < dsp_end; ++in)
 		*out++ = *in;
-	
-	m.extra_pos = out;
-	assert( out <= &m.extra_buf [extra_size] );
-}
-
-blargg_err_t SNES_SPC::play( int count, sample_t* out )
-{
-	require( (count & 1) == 0 ); // must be even
-	if ( count )
-	{
-		set_output( out, count );
-		end_frame( count * (clocks_per_sample / 2) );
-	}
-	
-	const char* err = m.cpu_error;
-	m.cpu_error = 0;
-	return err;
-}
-
-blargg_err_t SNES_SPC::skip( int count )
-{
-	#if SPC_LESS_ACCURATE
-	if ( count > 2 * sample_rate * 2 )
-	{
-		set_output( 0, 0 );
-		
-		// Skip a multiple of 4 samples
-		time_t end = count;
-		count = (count & 3) + 1 * sample_rate * 2;
-		end = (end - count) * (clocks_per_sample / 2);
-		
-		m.skipped_kon  = 0;
-		m.skipped_koff = 0;
-		
-		// Preserve DSP and timer synchronization
-		// TODO: verify that this really preserves it
-		int old_dsp_time = m.dsp_time + m.spc_time;
-		m.dsp_time = end - m.spc_time + skipping_time;
-		end_frame( end );
-		m.dsp_time = m.dsp_time - skipping_time + old_dsp_time;
-		
-		dsp.write( SPC_DSP::r_koff, m.skipped_koff & ~m.skipped_kon );
-		dsp.write( SPC_DSP::r_kon , m.skipped_kon );
-		clear_echo();
-	}
-	#endif
-	
-	return play( count, 0 );
+
+	this->m.extra_pos = out;
+	assert(out <= &this->m.extra_buf[extra_size]);
+}
+
+void SNES_SPC::play(int count, sample_t *out)
+{
+	assert(!(count & 1)); // must be even
+	if (count)
+	{
+		this->set_output(out, count);
+		this->end_frame(count * (clocks_per_sample / 2));
+	}
+}
+
+void SNES_SPC::skip(int count)
+{
+	this->play(count, nullptr);
 }
 
 //// Snes9x Accessor
 
-void SNES_SPC::dsp_set_spc_snapshot_callback(void (*callback)())
-{
-	dsp.set_spc_snapshot_callback( callback );
-}
-
-void SNES_SPC::dsp_dump_spc_snapshot()
-{
-	dsp.dump_spc_snapshot();
-}
-
-void SNES_SPC::dsp_set_stereo_switch( int value )
-{
-	dsp.set_stereo_switch( value );
-}
-
-SNES_SPC::uint8_t SNES_SPC::dsp_reg_value( int ch, int addr )
-{
-	return dsp.reg_value( ch, addr );
-}
-
-int SNES_SPC::dsp_envx_value( int ch )
-{
-	return dsp.envx_value( ch );
-}
-
-//// Snes9x debugger
-
-#ifdef DEBUGGER
-
-void SNES_SPC::debug_toggle_trace()
-{
-	debug_trace = !debug_trace;
-
-	if (debug_trace)
-	{
-		printf("APU tracing enabled.\n");
-		ENSURE_TRACE_OPEN(apu_trace, "apu_trace.log", "wb")
-	}
-	else
-	{
-		printf("APU tracing disabled.\n");
-		fclose(apu_trace);
-		apu_trace = NULL;
-	}
-}
-
-bool SNES_SPC::debug_is_enabled() { return debug_trace; }
-
-void SNES_SPC::debug_do_trace( int a, int x, int y, uint8_t const *pc, uint8_t *sp, int psw, int c, int nz, int dp )
-{
-	char	msg[512];
-
-	ENSURE_TRACE_OPEN(apu_trace, "apu_trace.log", "a")
-
-	debug_op_print(msg, a, x, y, pc, sp, psw, c, nz, dp);
-	fprintf(apu_trace, "%s  ", msg);
-	debug_io_print(msg);
-	fprintf(apu_trace, "%s  ", msg);
-	S9xPrintHVPosition(msg);
-	fprintf(apu_trace, "%s\n", msg);
-}
-
-void SNES_SPC::debug_op_print( char *buffer, int a, int x, int y, uint8_t const *pc, uint8_t *sp, int psw, int c, int nz, int dp )
-{
-	static char	mnemonics[256][20] =
-	{
-		"NOP",
-		"TCALL 0",
-		"SET1 $%02X.0",
-		"BBS $%02X.0,$%04X",
-		"OR A,$%02X",
-		"OR A,!$%04X",
-		"OR A,(X)",
-		"OR A,[$%02X+X]",
-		"OR A,#$%02X",
-		"OR $%02X,$%02X",
-		"OR1 C,$%04X.%d",
-		"ASL $%02X",
-		"MOV !$%04X,Y",
-		"PUSH PSW",
-		"TSET1 !$%04X",
-		"BRK",
-		"BPL $%04X",
-		"TCALL 1",
-		"CLR1 $%02X.0",
-		"BBC $%02X.0,$%04X",
-		"OR A,$%02X+X",
-		"OR A,!$%04X+X",
-		"OR A,!$%04X+Y",
-		"OR A,[$%02X]+Y",
-		"OR $%02X,#$%02X",
-		"OR (X),(Y)",
-		"DECW $%02X",
-		"ASL $%02X+X",
-		"ASL A",
-		"DEC X",
-		"CMP X,!$%04X",
-		"JMP [!$%04X+X]",
-		"CLRP",
-		"TCALL 2",
-		"SET1 $%02X.1",
-		"BBS $%02X.1,$%04X",
-		"AND A,$%02X",
-		"AND A,!$%04X",
-		"AND A,(X)",
-		"AND A,[$%02X+X]",
-		"AND A,#$%02X",
-		"AND $%02X,$%02X",
-		"OR1 C,/$%04X.%d",
-		"ROL $%02X",
-		"ROL !$%04X",
-		"PUSH A",
-		"CBNE $%02X,$%04X",
-		"BRA $%04X",
-		"BMI $%04X",
-		"TCALL 3",
-		"CLR1 $%02X.1",
-		"BBC $%02X.1,$%04X",
-		"AND A,$%02X+X",
-		"AND A,!$%04X+X",
-		"AND A,!$%04X+Y",
-		"AND A,[$%02X]+Y",
-		"AND $%02X,#$%02X",
-		"AND (X),(Y)",
-		"INCW $%02X",
-		"ROL $%02X+X",
-		"ROL A",
-		"INC X",
-		"CMP X,$%02X",
-		"CALL !$%04X",
-		"SETP",
-		"TCALL 4",
-		"SET1 $%02X.2",
-		"BBS $%02X.2,$%04X",
-		"EOR A,$%02X",
-		"EOR A,!$%04X",
-		"EOR A,(X)",
-		"EOR A,[$%02X+X]",
-		"EOR A,#$%02X",
-		"EOR $%02X,$%02X",
-		"AND1 C,$%04X.%d",
-		"LSR $%02X",
-		"LSR !$%04X",
-		"PUSH X",
-		"TCLR1 !$%04X",
-		"PCALL $%02X",
-		"BVC $%04X",
-		"TCALL 5",
-		"CLR1 $%02X.2",
-		"BBC $%02X.2,$%04X",
-		"EOR A,$%02X+X",
-		"EOR A,!$%04X+X",
-		"EOR A,!$%04X+Y",
-		"EOR A,[$%02X]+Y",
-		"EOR $%02X,#$%02X",
-		"EOR (X),(Y)",
-		"CMPW YA,$%02X",
-		"LSR $%02X+X",
-		"LSR A",
-		"MOV X,A",
-		"CMP Y,!$%04X",
-		"JMP !$%04X",
-		"CLRC",
-		"TCALL 6",
-		"SET1 $%02X.3",
-		"BBS $%02X.3,$%04X",
-		"CMP A,$%02X",
-		"CMP A,!$%04X",
-		"CMP A,(X)",
-		"CMP A,[$%02X+X]",
-		"CMP A,#$%02X",
-		"CMP $%02X,$%02X",
-		"AND1 C,/$%04X.%d",
-		"ROR $%02X",
-		"ROR !$%04X",
-		"PUSH Y",
-		"DBNZ $%02X,$%04X",
-		"RET",
-		"BVS $%04X",
-		"TCALL 7",
-		"CLR1 $%02X.3",
-		"BBC $%02X.3,$%04X",
-		"CMP A,$%02X+X",
-		"CMP A,!$%04X+X",
-		"CMP A,!$%04X+Y",
-		"CMP A,[$%02X]+Y",
-		"CMP $%02X,#$%02X",
-		"CMP (X),(Y)",
-		"ADDW YA,$%02X",
-		"ROR $%02X+X",
-		"ROR A",
-		"MOV A,X",
-		"CMP Y,$%02X",
-		"RET1",
-		"SETC",
-		"TCALL 8",
-		"SET1 $%02X.4",
-		"BBS $%02X.4,$%04X",
-		"ADC A,$%02X",
-		"ADC A,!$%04X",
-		"ADC A,(X)",
-		"ADC A,[$%02X+X]",
-		"ADC A,#$%02X",
-		"ADC $%02X,$%02X",
-		"EOR1 C,$%04X.%d",
-		"DEC $%02X",
-		"DEC !$%04X",
-		"MOV Y,#$%02X",
-		"POP PSW",
-		"MOV $%02X,#$%02X",
-		"BCC $%04X",
-		"TCALL 9",
-		"CLR1 $%02X.4",
-		"BBC $%02X.4,$%04X",
-		"ADC A,$%02X+X",
-		"ADC A,!$%04X+X",
-		"ADC A,!$%04X+Y",
-		"ADC A,[$%02X]+Y",
-		"ADC $%02X,#$%02X",
-		"ADC (X),(Y)",
-		"SUBW YA,$%02X",
-		"DEC $%02X+X",
-		"DEC A",
-		"MOV X,SP",
-		"DIV YA,X",
-		"XCN A",
-		"EI",
-		"TCALL 10",
-		"SET1 $%02X.5",
-		"BBS $%02X.5,$%04X",
-		"SBC A,$%02X",
-		"SBC A,!$%04X",
-		"SBC A,(X)",
-		"SBC A,[$%02X+X]",
-		"SBC A,#$%02X",
-		"SBC $%02X,$%02X",
-		"MOV1 C,$%04X.%d",
-		"INC $%02X",
-		"INC !$%04X",
-		"CMP Y,#$%02X",
-		"POP A",
-		"MOV (X)+,A",
-		"BCS $%04X",
-		"TCALL 11",
-		"CLR1 $%02X.5",
-		"BBC $%02X.5,$%04X",
-		"SBC A,$%02X+X",
-		"SBC A,!$%04X+X",
-		"SBC A,!$%04X+Y",
-		"SBC A,[$%02X]+Y",
-		"SBC $%02X,#$%02X",
-		"SBC (X),(Y)",
-		"MOVW YA,$%02X",
-		"INC $%02X+X",
-		"INC A",
-		"MOV SP,X",
-		"DAS A",
-		"MOV A,(X)+",
-		"DI",
-		"TCALL 12",
-		"SET1 $%02X.6",
-		"BBS $%02X.6,$%04X",
-		"MOV $%02X,A",
-		"MOV !$%04X,A",
-		"MOV (X),A",
-		"MOV [$%02X+X],A",
-		"CMP X,#$%02X",
-		"MOV !$%04X,X",
-		"MOV1 $%04X.%d,C",
-		"MOV $%02X,Y",
-		"ASL !$%04X",
-		"MOV X,#$%02X",
-		"POP X",
-		"MUL YA",
-		"BNE $%04X",
-		"TCALL 13",
-		"CLR1 $%02X.6",
-		"BBC $%02X.6,$%04X",
-		"MOV $%02X+X,A",
-		"MOV !$%04X+X,A",
-		"MOV !$%04X+Y,A",
-		"MOV [$%02X]+Y,A",
-		"MOV $%02X,X",
-		"MOV $%02X+Y,X",
-		"MOVW $%02X,YA",
-		"MOV $%02X+X,Y",
-		"DEC Y",
-		"MOV A,Y",
-		"CBNE $%02X+X,$%04X",
-		"DAA A",
-		"CLRV",
-		"TCALL 14",
-		"SET1 $%02X.7",
-		"BBS $%02X.7,$%04X",
-		"MOV A,$%02X",
-		"MOV A,!$%04X",
-		"MOV A,(X)",
-		"MOV A,[$%02X+X]",
-		"MOV A,#$%02X",
-		"MOV X,!$%04X",
-		"NOT1 $%04X.%d",
-		"MOV Y,$%02X",
-		"MOV Y,!$%04X",
-		"NOTC",
-		"POP Y",
-		"SLEEP",
-		"BEQ $%04X",
-		"TCALL 15",
-		"CLR1 $%02X.7",
-		"BBC $%02X.7,$%04X",
-		"MOV A,$%02X+X",
-		"MOV A,!$%04X+X",
-		"MOV A,!$%04X+Y",
-		"MOV A,[$%02X]+Y",
-		"MOV X,$%02X",
-		"MOV X,$%02X+Y",
-		"MOV $%02X,$%02X",
-		"MOV Y,$%02X+X",
-		"INC Y",
-		"MOV Y,A",
-		"DBNZ Y,$%04X",
-		"STOP"
-	};
-
-	static int modes[256] =
-	{
-		2, 2, 0, 5, 0, 1, 2, 0, 0, 3, 6, 0, 1, 2, 1, 2,
-		7, 2, 0, 5, 0, 1, 1, 0, 4, 2, 0, 0, 2, 2, 1, 1,
-		2, 2, 0, 5, 0, 1, 2, 0, 0, 3, 6, 0, 1, 2, 5, 7,
-		7, 2, 0, 5, 0, 1, 1, 0, 4, 2, 0, 0, 2, 2, 0, 1,
-		2, 2, 0, 5, 0, 1, 2, 0, 0, 3, 6, 0, 1, 2, 1, 0,
-		7, 2, 0, 5, 0, 1, 1, 0, 4, 2, 0, 0, 2, 2, 1, 1,
-		2, 2, 0, 5, 0, 1, 2, 0, 0, 3, 6, 0, 1, 2, 5, 2,
-		7, 2, 0, 5, 0, 1, 1, 0, 4, 2, 0, 0, 2, 2, 0, 2,
-		2, 2, 0, 5, 0, 1, 2, 0, 0, 3, 6, 0, 1, 0, 2, 4,
-		7, 2, 0, 5, 0, 1, 1, 0, 4, 2, 0, 0, 2, 2, 2, 2,
-		2, 2, 0, 5, 0, 1, 2, 0, 0, 3, 6, 0, 1, 0, 2, 2,
-		7, 2, 0, 5, 0, 1, 1, 0, 4, 2, 0, 0, 2, 2, 2, 2,
-		2, 2, 0, 5, 0, 1, 2, 0, 0, 1, 6, 0, 1, 0, 2, 2,
-		7, 2, 0, 5, 0, 1, 1, 0, 0, 0, 0, 0, 2, 2, 5, 2,
-		2, 2, 0, 5, 0, 1, 2, 0, 0, 1, 6, 0, 1, 2, 2, 2,
-		7, 2, 0, 5, 0, 1, 1, 0, 0, 0, 3, 0, 2, 2, 7, 2
-	};
-
-	static int modesToBytes[] =
-	{
-		2, 3, 1, 3, 3, 3, 3, 2
-	};
-
-	int const	n80 = 0x80; // nz
-	int const	p20 = 0x20; // dp
-	int const	z02 = 0x02; // nz
-	int const	c01 = 0x01; // c
-
-	#define GET_PC()	(pc - ram)
-	#define GET_SP()	(sp - 0x101 - ram)
-	#define GET_PSW( out )\
-	{\
-		out = psw & ~(n80 | p20 | z02 | c01);\
-		out |= c  >> 8 & c01;\
-		out |= dp >> 3 & p20;\
-		out |= ((nz >> 4) | nz) & n80;\
-		if ( !(uint8_t) nz ) out |= z02;\
-	}
-
-	uint8_t const	*ram = RAM;
-
-	int		addr;
-	int		tsp, tpsw;
-	uint8_t	d0, d1, d2;
-
-	addr = GET_PC();
-	tsp  = GET_SP();
-	GET_PSW(tpsw);
-
-	d0 = *pc;
-	d1 = (addr < 0xffff) ? *(pc + 1) : 0;
-	d2 = (addr < 0xfffe) ? *(pc + 2) : 0;
-
-	int		mode  = modes[d0];
-	int		bytes = modesToBytes[mode];
-	char	mnem[100];
-
-	switch (bytes)
-	{
-		case 1:
-			sprintf(buffer, "%04X %02X       ",     addr, d0);
-			break;
-
-		case 2:
-			sprintf(buffer, "%04X %02X %02X    ",   addr, d0, d1);
-			break;
-
-		case 3:
-			sprintf(buffer, "%04X %02X %02X %02X ", addr, d0, d1, d2);
-			break;
-	}
-
-	switch (mode)
-	{
-		case 0:
-			sprintf(mnem, mnemonics[d0], d1);
-			break;
-
-		case 1:
-			sprintf(mnem, mnemonics[d0], d1 + (d2 << 8));
-			break;
-
-		case 2:
-			strcpy (mnem, mnemonics[d0]);
-			break;
-
-		case 3:
-			sprintf(mnem, mnemonics[d0], d2, d1);
-			break;
-
-		case 4:
-			sprintf(mnem, mnemonics[d0], d2, d1);
-			break;
-
-		case 5:
-			sprintf(mnem, mnemonics[d0], d1, addr + 3 + (int8_t) d2);
-			break;
-
-		case 6:
-			sprintf(mnem, mnemonics[d0], (d1 + (d2 << 8)) & 0x1fff, d2 >> 5);
-			break;
-
-		case 7:
-			sprintf(mnem, mnemonics[d0], addr + 2 + (int8_t) d1);
-			break;
-	}
-
-	sprintf(buffer, "%s %-20s A:%02X X:%02X Y:%02X S:%02X P:%c%c%c%c%c%c%c%c ROM:%d",
-		buffer, mnem, a, x, y, tsp,
-		(tpsw & 0x80) ? 'N' : 'n',
-		(tpsw & 0x40) ? 'V' : 'v',
-		(tpsw & 0x20) ? 'P' : 'p',
-		(tpsw & 0x10) ? 'B' : 'b',
-		(tpsw & 0x08) ? 'H' : 'h',
-		(tpsw & 0x04) ? 'I' : 'i',
-		(tpsw & 0x02) ? 'Z' : 'z',
-		(tpsw & 0x01) ? 'C' : 'c',
-		m.rom_enabled ? 1 : 0);
-}
-
-void SNES_SPC::debug_io_print( char *buffer )
-{
-	sprintf(buffer, "i/o %02X/%02X %02X/%02X %02X/%02X %02X/%02X",
-		m.smp_regs[1][r_cpuio0], m.smp_regs[0][r_cpuio0],
-		m.smp_regs[1][r_cpuio1], m.smp_regs[0][r_cpuio1],
-		m.smp_regs[1][r_cpuio2], m.smp_regs[0][r_cpuio2],
-		m.smp_regs[1][r_cpuio3], m.smp_regs[0][r_cpuio3]);
-}
-
-#endif
-
+void SNES_SPC::dsp_set_stereo_switch(int value)
+{
+	this->dsp.set_stereo_switch(value);
+}
+
+uint8_t SNES_SPC::dsp_reg_value(int ch, int addr)
+{
+	return this->dsp.reg_value(ch, addr);
+}
+
+int SNES_SPC::dsp_envx_value(int ch)
+{
+	return this->dsp.envx_value(ch);
+}
+

--- a/src/in_snsf/snes9x/apu/SNES_SPC_state.cpp
+++ /dev/null
@@ -1,143 +1,1 @@
-// SPC emulation state save/load: copy_state(), save_spc()
-// Separate file to avoid linking in unless needed
 
-// snes_spc 0.9.0. http://www.slack.net/‾ant/
-
-#include "SNES_SPC.h"
-
-#if !SPC_NO_COPY_STATE_FUNCS
-
-#include <string.h>
-
-/* Copyright (C) 2004-2007 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 <stdio.h>
-#include "blargg_source.h"
-
-#define RAM         (m.ram.ram)
-#define REGS        (m.smp_regs [0])
-#define REGS_IN     (m.smp_regs [1])
-
-void SNES_SPC::save_regs( uint8_t out [reg_count] )
-{
-	// Use current timer counter values
-	for ( int i = 0; i < timer_count; i++ )
-			out [r_t0out + i] = m.timers [i].counter;
-
-	// Last written values
-	memcpy( out, REGS, r_t0out );
-}
-
-void SNES_SPC::init_header( void* spc_out )
-{
-	spc_file_t* const spc = (spc_file_t*) spc_out;
-	
-	spc->has_id666 = 26; // has none
-	spc->version   = 30;
-	memcpy( spc, signature, sizeof spc->signature );
-	memset( spc->text, 0, sizeof spc->text );
-}
-
-void SNES_SPC::save_spc( void* spc_out )
-{
-	spc_file_t* const spc = (spc_file_t*) spc_out;
-	
-	// CPU
-	spc->pcl = (uint8_t) (m.cpu_regs.pc >> 0);
-	spc->pch = (uint8_t) (m.cpu_regs.pc >> 8);
-	spc->a   = m.cpu_regs.a;
-	spc->x   = m.cpu_regs.x;
-	spc->y   = m.cpu_regs.y;
-	spc->psw = m.cpu_regs.psw;
-	spc->sp  = m.cpu_regs.sp;
-	
-	// RAM, ROM
-	memcpy( spc->ram, RAM, sizeof spc->ram );
-	if ( m.rom_enabled )
-		memcpy( spc->ram + rom_addr, m.hi_ram, sizeof m.hi_ram );
-	memset( spc->unused, 0, sizeof spc->unused );
-	memcpy( spc->ipl_rom, m.rom, sizeof spc->ipl_rom );
-	
-	// SMP registers
-	save_regs( &spc->ram [0xF0] );
-	int i;
-	for ( i = 0; i < port_count; i++ )
-		spc->ram [0xF0 + r_cpuio0 + i] = REGS_IN [r_cpuio0 + i];
-	
-	// DSP registers
-	for ( i = 0; i < SPC_DSP::register_count; i++ )
-		spc->dsp [i] = dsp.read( i );
-}
-
-#undef IF_0_THEN_256
-#define IF_0_THEN_256( n ) ((uint8_t) ((n) - 1) + 1)
-void SNES_SPC::copy_state( unsigned char** io, copy_func_t copy )
-{
-	SPC_State_Copier copier( io, copy );
-	
-	// Make state data more readable by putting 64K RAM, 16 SMP registers,
-	// then DSP (with its 128 registers) first
-
-	// RAM
-	enable_rom( 0 ); // will get re-enabled if necessary in regs_loaded() below
-	copier.copy( RAM, 0x10000 );
-	
-	{
-		// SMP registers
-		uint8_t regs [reg_count];
-		uint8_t regs_in [reg_count];
-
-		memcpy( regs, REGS, reg_count );
-		memcpy( regs_in, REGS_IN, reg_count );
-
-		copier.copy( regs, sizeof regs );
-		copier.copy( regs_in, sizeof regs_in );
-
-		memcpy( REGS, regs, reg_count);
-		memcpy( REGS_IN, regs_in, reg_count );
-
-		enable_rom( REGS [r_control] & 0x80 );
-	}
-	
-	// CPU registers
-	SPC_COPY( uint16_t, m.cpu_regs.pc );
-	SPC_COPY(  uint8_t, m.cpu_regs.a );
-	SPC_COPY(  uint8_t, m.cpu_regs.x );
-	SPC_COPY(  uint8_t, m.cpu_regs.y );
-	SPC_COPY(  uint8_t, m.cpu_regs.psw );
-	SPC_COPY(  uint8_t, m.cpu_regs.sp );
-	copier.extra();
-	
-	SPC_COPY( int16_t, m.spc_time );
-	SPC_COPY( int16_t, m.dsp_time );
-
-	// DSP
-	dsp.copy_state( io, copy );
-	
-	// Timers
-	for ( int i = 0; i < timer_count; i++ )
-	{
-		Timer* t = &m.timers [i];
-		t->period  = IF_0_THEN_256( REGS [r_t0target + i] );
-		t->enabled = REGS [r_control] >> i & 1;
-		SPC_COPY( int16_t, t->next_time );
-		SPC_COPY( uint8_t, t->divider );
-		SPC_COPY( uint8_t, t->counter );
-		copier.extra();
-	}
-
-	set_tempo( m.tempo );
-
-	copier.extra();
-}
-#endif
-

--- a/src/in_snsf/snes9x/apu/SPC_CPU.h
+++ b/src/in_snsf/snes9x/apu/SPC_CPU.h
@@ -13,197 +13,160 @@
 
 //// Memory access
 
-#if SPC_MORE_ACCURACY
-	#define SUSPICIOUS_OPCODE( name ) ((void) 0)
-#else
-	#define SUSPICIOUS_OPCODE( name ) dprintf( "SPC: suspicious opcode: " name "\n" )
-#endif
-
-#define CPU_READ( time, offset, addr )\
-	cpu_read( addr, time + offset )
-
-#define CPU_WRITE( time, offset, addr, data )\
-	cpu_write( data, addr, time + offset )
-
-#if SPC_MORE_ACCURACY
-	#define CPU_READ_TIMER( time, offset, addr, out )\
-		{ out = CPU_READ( time, offset, addr ); }
-
-#else
-	// timers are by far the most common thing read from dp
-	#define CPU_READ_TIMER( time, offset, addr_, out )\
-	{\
-		rel_time_t adj_time = time + offset;\
-		int dp_addr = addr_;\
-		int ti = dp_addr - (r_t0out + 0xF0);\
-		if ( (unsigned) ti < timer_count )\
-		{\
-			Timer* t = &m.timers [ti];\
-			if ( adj_time >= t->next_time )\
-				t = run_timer_( t, adj_time );\
-			out = t->counter;\
-			t->counter = 0;\
-		}\
-		else\
-		{\
-			out = ram [dp_addr];\
-			int i = dp_addr - 0xF0;\
-			if ( (unsigned) i < 0x10 )\
-				out = cpu_read_smp_reg( i, adj_time );\
-		}\
-	}
-#endif
-
-#define TIME_ADJ( n )   (n)
-
-#define READ_TIMER( time, addr, out )       CPU_READ_TIMER( rel_time, TIME_ADJ(time), (addr), out )
-#define READ(  time, addr )                 CPU_READ ( rel_time, TIME_ADJ(time), (addr) )
-#define WRITE( time, addr, data )           CPU_WRITE( rel_time, TIME_ADJ(time), (addr), (data) )
-
-#define DP_ADDR( addr )                     (dp + (addr))
-
-#define READ_DP_TIMER(  time, addr, out )   CPU_READ_TIMER( rel_time, TIME_ADJ(time), DP_ADDR( addr ), out )
-#define READ_DP(  time, addr )              READ ( time, DP_ADDR( addr ) )
-#define WRITE_DP( time, addr, data )        WRITE( time, DP_ADDR( addr ), data )
-
-#define READ_PROG16( addr )                 GET_LE16( ram + (addr) )
-
-#define SET_PC( n )     (pc = ram + (n))
-#define GET_PC()        (pc - ram)
-#define READ_PC( pc )   (*(pc))
-#define READ_PC16( pc ) GET_LE16( pc )
-
 // TODO: remove non-wrapping versions?
 #define SPC_NO_SP_WRAPAROUND 0
 
-#define SET_SP( v )     (sp = ram + 0x101 + (v))
-#define GET_SP()        (sp - 0x101 - ram)
-
-#if SPC_NO_SP_WRAPAROUND
-#define PUSH16( v )     (sp -= 2, SET_LE16( sp, v ))
-#define PUSH( v )       (void) (*--sp = (uint8_t) (v))
-#define POP( out )      (void) ((out) = *sp++)
-
-#else
-#define PUSH16( data )\
-{\
-	int addr = (sp -= 2) - ram;\
-	if ( addr > 0x100 )\
-	{\
-		SET_LE16( sp, data );\
-	}\
-	else\
-	{\
-		ram [(uint8_t) addr + 0x100] = (uint8_t) data;\
-		sp [1] = (uint8_t) (data >> 8);\
-		sp += 0x100;\
-	}\
-}
-
-#define PUSH( data )\
-{\
-	*--sp = (uint8_t) (data);\
-	if ( sp - ram == 0x100 )\
-		sp += 0x100;\
-}
-
-#define POP( out )\
-{\
-	out = *sp++;\
-	if ( sp - ram == 0x201 )\
-	{\
-		out = sp [-0x101];\
-		sp -= 0x100;\
-	}\
-}
-
-#endif
-
-#define MEM_BIT( rel ) CPU_mem_bit( pc, rel_time + rel )
-
-unsigned SNES_SPC::CPU_mem_bit( uint8_t const* pc, rel_time_t rel_time )
+unsigned SNES_SPC::CPU_mem_bit(const uint8_t *pc, rel_time_t rel_time)
 {
-	unsigned addr = READ_PC16( pc );
-	unsigned t = READ( 0, addr & 0x1FFF ) >> (addr >> 13);
-	return t << 8 & 0x100;
+	unsigned addr = get_le16(pc);
+	unsigned t = this->cpu_read(addr & 0x1FFF, rel_time) >> (addr >> 13);
+	return (t << 8) & 0x100;
 }
 
 //// Status flag handling
 
 // Hex value in name to clarify code and bit shifting.
 // Flag stored in indicated variable during emulation
-int const n80 = 0x80; // nz
-int const v40 = 0x40; // psw
-int const p20 = 0x20; // dp
-int const b10 = 0x10; // psw
-int const h08 = 0x08; // psw
-int const i04 = 0x04; // psw
-int const z02 = 0x02; // nz
-int const c01 = 0x01; // c
-
-int const nz_neg_mask = 0x880; // either bit set indicates N flag set
-
-#define GET_PSW( out )\
-{\
-	out = psw & ~(n80 | p20 | z02 | c01);\
-	out |= c  >> 8 & c01;\
-	out |= dp >> 3 & p20;\
-	out |= ((nz >> 4) | nz) & n80;\
-	if ( !(uint8_t) nz ) out |= z02;\
-}
-
-#define SET_PSW( in )\
-{\
-	psw = in;\
-	c   = in << 8;\
-	dp  = in << 3 & 0x100;\
-	nz  = (in << 4 & 0x800) | (~in & z02);\
-}
+const int n80 = 0x80; // nz
+const int v40 = 0x40; // psw
+const int p20 = 0x20; // dp
+const int b10 = 0x10; // psw
+const int h08 = 0x08; // psw
+const int i04 = 0x04; // psw
+const int z02 = 0x02; // nz
+const int c01 = 0x01; // c
+
+const int nz_neg_mask = 0x880; // either bit set indicates N flag set
 
 SPC_CPU_RUN_FUNC
 {
-	uint8_t* const ram = RAM;
-	int a = m.cpu_regs.a;
-	int x = m.cpu_regs.x;
-	int y = m.cpu_regs.y;
-	uint8_t const* pc;
-	uint8_t* sp;
+	auto ram = this->m.ram.ram;
+	int a = this->m.cpu_regs.a;
+	int x = this->m.cpu_regs.x;
+	int y = this->m.cpu_regs.y;
+	const uint8_t *pc;
+	uint8_t *sp;
 	int psw;
 	int c;
 	int nz;
 	int dp;
-	
-	SET_PC( m.cpu_regs.pc );
-	SET_SP( m.cpu_regs.sp );
-	SET_PSW( m.cpu_regs.psw );
-	
+
+	// timers are by far the most common thing read from dp
+	auto CPU_READ_TIMER = [&](rel_time_t offset, int addr_) -> int
+	{
+		int out;
+		rel_time_t adj_time = rel_time + offset;
+		int dp_addr = addr_;
+		int ti = dp_addr - (r_t0out + 0xF0);
+		if (static_cast<unsigned>(ti) < timer_count)
+		{
+			auto t = &this->m.timers[ti];
+			if (adj_time >= t->next_time)
+				t = this->run_timer_(t, adj_time);
+			out = t->counter;
+			t->counter = 0;
+		}
+		else
+		{
+			out = ram[dp_addr];
+			int i = dp_addr - 0xF0;
+			if (static_cast<unsigned>(i) < 0x10)
+				out = this->cpu_read_smp_reg(i, adj_time);
+		}
+		return out;
+	};
+
+	auto DP_ADDR = [&](int addr) { return dp + addr; };
+
+	auto READ_PROG16 = [&](int addr) { return get_le16(ram + addr); };
+
+	auto SET_PC = [&](int n) { pc = ram + n; };
+	auto GET_PC = [&]() { return pc - ram; };
+
+	auto SET_SP = [&](int v) { sp = ram + 0x101 + v; };
+	auto GET_SP = [&]() { return sp - 0x101 - ram; };
+
+	auto PUSH16 = [&](int data)
+	{
+		sp -= 2;
+#if !SPC_NO_SP_WRAPAROUND
+		int addr = sp - ram;
+		if (addr > 0x100)
+#endif
+			set_le16(sp, data);
+#if !SPC_NO_SP_WRAPAROUND
+		else
+		{
+			ram[static_cast<uint8_t>(addr) + 0x100] = static_cast<uint8_t>(data);
+			sp[1] = static_cast<uint8_t>(data >> 8);
+			sp += 0x100;
+		}
+#endif
+	};
+	auto PUSH = [&](int data)
+	{
+		*--sp = static_cast<uint8_t>(data);
+#if !SPC_NO_SP_WRAPAROUND
+		if (sp - ram == 0x100)
+			sp += 0x100;
+#endif
+	};
+	auto POP = [&](int &out)
+	{
+		out = *sp++;
+#if !SPC_NO_SP_WRAPAROUND
+		if (sp - ram == 0x201)
+		{
+			out = sp[-0x101];
+			sp -= 0x100;
+		}
+#endif
+	};
+
+	auto MEM_BIT = [&](rel_time_t rel) { return this->CPU_mem_bit(pc, rel_time + rel); };
+
+	auto GET_PSW = [&](int &out)
+	{
+		out = psw & ~(n80 | p20 | z02 | c01);
+		out |= (c >> 8) & c01;
+		out |= (dp >> 3) & p20;
+		out |= ((nz >> 4) | nz) & n80;
+		if (!static_cast<uint8_t>(nz))
+			out |= z02;
+	};
+	auto SET_PSW = [&](int in)
+	{
+		psw = in;
+		c = in << 8;
+		dp = (in << 3) & 0x100;
+		nz = ((in << 4) & 0x800) | (~in & z02);
+	};
+
+	SET_PC(this->m.cpu_regs.pc);
+	SET_SP(this->m.cpu_regs.sp);
+	SET_PSW(this->m.cpu_regs.psw);
+
 	goto loop;
-	
-	
+
 	// Main loop
-	
+
 cbranch_taken_loop:
-	pc += *(BOOST::int8_t const*) pc;
+	pc += *reinterpret_cast<const int8_t *>(pc);
 inc_pc_loop:
-	pc++;
+	++pc;
 loop:
 {
-	unsigned opcode;
 	unsigned data;
-	
-	check( (unsigned) a < 0x100 );
-	check( (unsigned) x < 0x100 );
-	check( (unsigned) y < 0x100 );
-	
-	opcode = *pc;
-	if (allow_time_overflow && rel_time >= 0 )
+
+	unsigned opcode = *pc;
+	if (this->allow_time_overflow && rel_time >= 0)
 		goto stop;
-	if ( (rel_time += m.cycle_table [opcode]) > 0 && !allow_time_overflow)
+	if ((rel_time += this->m.cycle_table[opcode]) > 0 && !this->allow_time_overflow)
 		goto out_of_time;
 	
-	#ifdef SPC_CPU_OPCODE_HOOK
-		SPC_CPU_OPCODE_HOOK( GET_PC(), opcode );
-	#endif
+#ifdef SPC_CPU_OPCODE_HOOK
+	SPC_CPU_OPCODE_HOOK(GET_PC(), opcode);
+#endif
 	/*
 	//SUB_CASE_COUNTER( 1 );
 	#define PROFILE_TIMER_LOOP( op, addr, len )\
@@ -214,1015 +177,1001 @@
 		SUB_CASE_COUNTER( op && cond );\
 	}
 	
-	PROFILE_TIMER_LOOP( 0xEC, GET_LE16( pc + 1 ), 3 );
+	PROFILE_TIMER_LOOP( 0xEC, get_le16( pc + 1 ), 3 );
 	PROFILE_TIMER_LOOP( 0xEB, pc [1], 2 );
 	PROFILE_TIMER_LOOP( 0xE4, pc [1], 2 );
 	*/
 
-#ifdef DEBUGGER
-	if (debug_trace)
-		debug_do_trace(a, x, y, pc, sp, psw, c, nz, dp);
-#endif
-
-
 	// TODO: if PC is at end of memory, this will get wrong operand (very obscure)
 	data = *++pc;
-	switch ( opcode )
+	switch (opcode)
 	{
-	
-// Common instructions
-
-#define BRANCH( cond )\
-{\
-	pc++;\
-	pc += (BOOST::int8_t) data;\
-	if ( cond )\
-		goto loop;\
-	pc -= (BOOST::int8_t) data;\
-	rel_time -= 2;\
-	goto loop;\
+		// Common instructions
+
+#define BRANCH(cond) \
+{ \
+	++pc; \
+	pc += static_cast<int8_t>(data); \
+	if (cond) \
+		goto loop; \
+	pc -= static_cast<int8_t>(data); \
+	rel_time -= 2; \
+	goto loop; \
 }
 
-	case 0xF0: // BEQ
-		BRANCH( !(uint8_t) nz ) // 89% taken
-	
-	case 0xD0: // BNE
-		BRANCH( (uint8_t) nz )
-	
-	case 0x3F:{// CALL
-		int old_addr = GET_PC() + 2;
-		SET_PC( READ_PC16( pc ) );
-		PUSH16( old_addr );
-		goto loop;
-	}
-	
-	case 0x6F:// RET
-		#if SPC_NO_SP_WRAPAROUND
-		{
-			SET_PC( GET_LE16( sp ) );
+		case 0xF0: // BEQ
+			BRANCH(!static_cast<uint8_t>(nz)) // 89% taken
+
+		case 0xD0: // BNE
+			BRANCH(static_cast<uint8_t>(nz))
+
+		case 0x3F: // CALL
+		{
+			int old_addr = GET_PC() + 2;
+			SET_PC(get_le16(pc));
+			PUSH16(old_addr);
+			goto loop;
+		}
+
+		case 0x6F:// RET
+#if SPC_NO_SP_WRAPAROUND
+			SET_PC(get_le16(sp));
 			sp += 2;
-		}
-		#else
-		{
-			int addr = sp - ram;
-			SET_PC( GET_LE16( sp ) );
-			sp += 2;
-			if ( addr < 0x1FF )
-				goto loop;
-			
-			SET_PC( sp [-0x101] * 0x100 + ram [(uint8_t) addr + 0x100] );
-			sp -= 0x100;
-		}
-		#endif
-		goto loop;
-	
-	case 0xE4: // MOV a,dp
-		++pc;
-		// 80% from timer
-		READ_DP_TIMER( 0, data, a = nz );
-		goto loop;
-	
-	case 0xFA:{// MOV dp,dp
-		int temp;
-		READ_DP_TIMER( -2, data, temp );
-		data = temp + no_read_before_write ;
-	}
-	// fall through
-	case 0x8F:{// MOV dp,#imm
-		int temp = READ_PC( pc + 1 );
-		pc += 2;
-		
-		#if !SPC_MORE_ACCURACY
-		{
-			int i = dp + temp;
-			ram [i] = (uint8_t) data;
-			i -= 0xF0;
-			if ( (unsigned) i < 0x10 ) // 76%
-			{
-				REGS [i] = (uint8_t) data;
-				
-				// Registers other than $F2 and $F4-$F7
-				//if ( i != 2 && i != 4 && i != 5 && i != 6 && i != 7 )
-				if ( ((~0x2F00 << (bits_in_int - 16)) << i) < 0 ) // 12%
-					cpu_write_smp_reg( data, rel_time, i );
-			}
-		}
-		#else
-			WRITE_DP( 0, temp, data );
-		#endif
-		goto loop;
-	}
-	
-	case 0xC4: // MOV dp,a
-		++pc;
-		#if !SPC_MORE_ACCURACY
-		{
-			int i = dp + data;
-			ram [i] = (uint8_t) a;
-			i -= 0xF0;
-			if ( (unsigned) i < 0x10 ) // 39%
-			{
-				unsigned sel = i - 2;
-				REGS [i] = (uint8_t) a;
-				
-				if ( sel == 1 ) // 51% $F3
-					dsp_write( a, rel_time );
-				else if ( sel > 1 ) // 1% not $F2 or $F3
-					cpu_write_smp_reg_( a, rel_time, i );
-			}
-		}
-		#else
-			WRITE_DP( 0, data, a );
-		#endif
-		goto loop;
-	
-#define CASE( n )   case n:
+#else
+			{
+				int addr = sp - ram;
+				SET_PC(get_le16(sp));
+				sp += 2;
+				if (addr < 0x1FF)
+					goto loop;
+
+				SET_PC(sp[-0x101] * 0x100 + ram[static_cast<uint8_t>(addr) + 0x100]);
+				sp -= 0x100;
+			}
+#endif
+			goto loop;
+
+		case 0xE4: // MOV a,dp
+			++pc;
+			// 80% from timer
+			a = nz = CPU_READ_TIMER(0, DP_ADDR(data));
+			goto loop;
+
+		case 0xFA: // MOV dp,dp
+		{
+			int temp = CPU_READ_TIMER(-2, DP_ADDR(data));
+			data = temp + no_read_before_write;
+		}
+		// fall through
+		case 0x8F: // MOV dp,#imm
+		{
+			int temp = *(pc + 1);
+			pc += 2;
+			{
+				int i = dp + temp;
+				ram[i] = static_cast<uint8_t>(data);
+				i -= 0xF0;
+				if (static_cast<unsigned>(i) < 0x10) // 76%
+				{
+					this->m.smp_regs[0][i] = static_cast<uint8_t>(data);
+
+					// Registers other than $F2 and $F4-$F7
+					//if ( i != 2 && i != 4 && i != 5 && i != 6 && i != 7 )
+					if (((~0x2F00 << (bits_in_int - 16)) << i) < 0) // 12%
+						this->cpu_write_smp_reg(data, rel_time, i);
+				}
+			}
+			goto loop;
+		}
+
+		case 0xC4: // MOV dp,a
+			++pc;
+			{
+				int i = dp + data;
+				ram [i] = static_cast<uint8_t>(a);
+				i -= 0xF0;
+				if (static_cast<unsigned>(i) < 0x10) // 39%
+				{
+					unsigned sel = i - 2;
+					this->m.smp_regs[0][i] = static_cast<uint8_t>(a);
+
+					if (sel == 1) // 51% $F3
+						this->dsp_write(a, rel_time);
+					else if (sel > 1) // 1% not $F2 or $F3
+						this->cpu_write_smp_reg_(a, rel_time, i);
+				}
+			}
+			goto loop;
+
+#define CASE(n) case n:
 
 // Define common address modes based on opcode for immediate mode. Execution
 // ends with data set to the address of the operand.
-#define ADDR_MODES_( op )\
-	CASE( op - 0x02 ) /* (X) */\
-		data = x + dp;\
-		pc--;\
-		goto end_##op;\
-	CASE( op + 0x0F ) /* (dp)+Y */\
-		data = READ_PROG16( data + dp ) + y;\
-		goto end_##op;\
-	CASE( op - 0x01 ) /* (dp+X) */\
-		data = READ_PROG16( ((uint8_t) (data + x)) + dp );\
-		goto end_##op;\
-	CASE( op + 0x0E ) /* abs+Y */\
-		data += y;\
-		goto abs_##op;\
-	CASE( op + 0x0D ) /* abs+X */\
-		data += x;\
-	CASE( op - 0x03 ) /* abs */\
-	abs_##op:\
-		data += 0x100 * READ_PC( ++pc );\
-		goto end_##op;\
-	CASE( op + 0x0C ) /* dp+X */\
-		data = (uint8_t) (data + x);
-
-#define ADDR_MODES_NO_DP( op )\
-	ADDR_MODES_( op )\
-		data += dp;\
+#define ADDR_MODES_(op) \
+	CASE(op - 0x02) /* (X) */ \
+		data = x + dp; \
+		--pc; \
+		goto end_##op; \
+	CASE(op + 0x0F) /* (dp)+Y */ \
+		data = READ_PROG16(data + dp) + y; \
+		goto end_##op; \
+	CASE(op - 0x01) /* (dp+X) */ \
+		data = READ_PROG16(static_cast<uint8_t>(data + x) + dp); \
+		goto end_##op; \
+	CASE(op + 0x0E) /* abs+Y */ \
+		data += y; \
+		goto abs_##op; \
+	CASE(op + 0x0D) /* abs+X */ \
+		data += x; \
+	CASE(op - 0x03) /* abs */ \
+	abs_##op: \
+		data += 0x100 * *(++pc); \
+		goto end_##op; \
+	CASE(op + 0x0C) /* dp+X */ \
+		data = static_cast<uint8_t>(data + x);
+
+#define ADDR_MODES_NO_DP(op) \
+	ADDR_MODES_(op) \
+		data += dp; \
 	end_##op:
 
-#define ADDR_MODES( op )\
-	ADDR_MODES_( op )\
-	CASE( op - 0x04 ) /* dp */\
-		data += dp;\
+#define ADDR_MODES(op) \
+	ADDR_MODES_(op) \
+	CASE(op - 0x04) /* dp */ \
+		data += dp; \
 	end_##op:
 
-// 1. 8-bit Data Transmission Commands. Group I
-
-	ADDR_MODES_NO_DP( 0xE8 ) // MOV A,addr
-		a = nz = READ( 0, data );
-		goto inc_pc_loop;
-	
-	case 0xBF:{// MOV A,(X)+
-		int temp = x + dp;
-		x = (uint8_t) (x + 1);
-		a = nz = READ( -1, temp );
-		goto loop;
-	}
-	
-	case 0xE8: // MOV A,imm
-		a  = data;
-		nz = data;
-		goto inc_pc_loop;
-	
-	case 0xF9: // MOV X,dp+Y
-		data = (uint8_t) (data + y);
-	case 0xF8: // MOV X,dp
-		READ_DP_TIMER( 0, data, x = nz );
-		goto inc_pc_loop;
-	
-	case 0xE9: // MOV X,abs
-		data = READ_PC16( pc );
-		++pc;
-		data = READ( 0, data );
-	case 0xCD: // MOV X,imm
-		x  = data;
-		nz = data;
-		goto inc_pc_loop;
-	
-	case 0xFB: // MOV Y,dp+X
-		data = (uint8_t) (data + x);
-	case 0xEB: // MOV Y,dp
-		// 70% from timer
-		pc++;
-		READ_DP_TIMER( 0, data, y = nz );
-		goto loop;
-	
-	case 0xEC:{// MOV Y,abs
-		int temp = READ_PC16( pc );
-		pc += 2;
-		READ_TIMER( 0, temp, y = nz );
-		//y = nz = READ( 0, temp );
-		goto loop;
-	}
-	
-	case 0x8D: // MOV Y,imm
-		y  = data;
-		nz = data;
-		goto inc_pc_loop;
-	
-// 2. 8-BIT DATA TRANSMISSION COMMANDS, GROUP 2
-
-	ADDR_MODES_NO_DP( 0xC8 ) // MOV addr,A
-		WRITE( 0, data, a );
-		goto inc_pc_loop;
-	
+		// 1. 8-bit Data Transmission Commands. Group I
+
+		ADDR_MODES_NO_DP(0xE8) // MOV A,addr
+			a = nz = this->cpu_read(data, rel_time);
+			goto inc_pc_loop;
+
+		case 0xBF: // MOV A,(X)+
+		{
+			int temp = x + dp;
+			x = static_cast<uint8_t>(x + 1);
+			a = nz = this->cpu_read(temp, rel_time - 1);
+			goto loop;
+		}
+
+		case 0xE8: // MOV A,imm
+			a  = data;
+			nz = data;
+			goto inc_pc_loop;
+
+		case 0xF9: // MOV X,dp+Y
+			data = static_cast<uint8_t>(data + y);
+		case 0xF8: // MOV X,dp
+			x = nz = CPU_READ_TIMER(0, DP_ADDR(data));
+			goto inc_pc_loop;
+
+		case 0xE9: // MOV X,abs
+			data = get_le16(pc);
+			++pc;
+			data = this->cpu_read(data, rel_time);
+		case 0xCD: // MOV X,imm
+			x  = data;
+			nz = data;
+			goto inc_pc_loop;
+
+		case 0xFB: // MOV Y,dp+X
+			data = static_cast<uint8_t>(data + x);
+		case 0xEB: // MOV Y,dp
+			// 70% from timer
+			++pc;
+			y = nz = CPU_READ_TIMER(0, DP_ADDR(data));
+			goto loop;
+
+		case 0xEC: // MOV Y,abs
+		{
+			int temp = get_le16(pc);
+			pc += 2;
+			y = nz = CPU_READ_TIMER(0, temp);
+			//y = nz = this->cpu_read(temp, rel_time);
+			goto loop;
+		}
+
+		case 0x8D: // MOV Y,imm
+			y  = data;
+			nz = data;
+			goto inc_pc_loop;
+
+		// 2. 8-BIT DATA TRANSMISSION COMMANDS, GROUP 2
+
+		ADDR_MODES_NO_DP(0xC8) // MOV addr,A
+			this->cpu_write(a, data, rel_time);
+			goto inc_pc_loop;
+
+		{
+			int temp;
+			case 0xCC: // MOV abs,Y
+				temp = y;
+				goto mov_abs_temp;
+			case 0xC9: // MOV abs,X
+				temp = x;
+			mov_abs_temp:
+				this->cpu_write(temp, get_le16(pc), rel_time);
+				pc += 2;
+				goto loop;
+		}
+
+		case 0xD9: // MOV dp+Y,X
+			data = static_cast<uint8_t>(data + y);
+		case 0xD8: // MOV dp,X
+			this->cpu_write(x, data + dp, rel_time);
+			goto inc_pc_loop;
+
+		case 0xDB: // MOV dp+X,Y
+			data = static_cast<uint8_t>(data + x);
+		case 0xCB: // MOV dp,Y
+			this->cpu_write(y, data + dp, rel_time);
+			goto inc_pc_loop;
+
+		// 3. 8-BIT DATA TRANSMISSIN COMMANDS, GROUP 3.
+
+		case 0x7D: // MOV A,X
+			a  = x;
+			nz = x;
+			goto loop;
+
+		case 0xDD: // MOV A,Y
+			a  = y;
+			nz = y;
+			goto loop;
+
+		case 0x5D: // MOV X,A
+			x  = a;
+			nz = a;
+			goto loop;
+
+		case 0xFD: // MOV Y,A
+			y  = a;
+			nz = a;
+			goto loop;
+
+		case 0x9D: // MOV X,SP
+			x = nz = GET_SP();
+			goto loop;
+
+		case 0xBD: // MOV SP,X
+			SET_SP(x);
+			goto loop;
+
+		//case 0xC6: // MOV (X),A (handled by MOV addr,A in group 2)
+
+		case 0xAF: // MOV (X)+,A
+			this->cpu_write(a + no_read_before_write, DP_ADDR(x), rel_time);
+			++x;
+			goto loop;
+
+		// 5. 8-BIT LOGIC OPERATION COMMANDS
+
+#define LOGICAL_OP(op, func) \
+	ADDR_MODES(op) /* addr */ \
+		data = this->cpu_read(data, rel_time); \
+	case op: /* imm */ \
+		nz = a func##= data; \
+		goto inc_pc_loop; \
+		{ \
+			unsigned addr; \
+			case op + 0x11: /* X,Y */ \
+				data = this->cpu_read(DP_ADDR(y), rel_time - 2); \
+				addr = x + dp; \
+				goto addr_##op; \
+			case op + 0x01: /* dp,dp */ \
+				data = this->cpu_read(DP_ADDR(data), rel_time - 3); \
+			case op + 0x10: /*dp,imm*/ \
+			{ \
+				auto addr2 = pc + 1; \
+				pc += 2; \
+				addr = *addr2 + dp; \
+			} \
+			addr_##op: \
+				nz = data func this->cpu_read(addr, rel_time - 1); \
+				this->cpu_write(nz, addr, rel_time); \
+				goto loop; \
+		}
+
+		LOGICAL_OP(0x28, &); // AND
+
+		LOGICAL_OP(0x08, |); // OR
+
+		LOGICAL_OP(0x48, ^); // EOR
+
+		// 4. 8-BIT ARITHMETIC OPERATION COMMANDS
+
+		ADDR_MODES(0x68) // CMP addr
+			data = this->cpu_read(data, rel_time);
+		case 0x68: // CMP imm
+			nz = a - data;
+			c = ~nz;
+			nz &= 0xFF;
+			goto inc_pc_loop;
+
+		case 0x79: // CMP (X),(Y)
+			data = this->cpu_read(DP_ADDR(y), rel_time - 2);
+			nz = this->cpu_read(DP_ADDR(x), rel_time - 1) - data;
+			c = ~nz;
+			nz &= 0xFF;
+			goto loop;
+
+		case 0x69: // CMP dp,dp
+			data = this->cpu_read(DP_ADDR(data), rel_time - 3);
+		case 0x78: // CMP dp,imm
+			nz = this->cpu_read(DP_ADDR(*(++pc)), rel_time - 1) - data;
+			c = ~nz;
+			nz &= 0xFF;
+			goto inc_pc_loop;
+
+		case 0x3E: // CMP X,dp
+			data += dp;
+			goto cmp_x_addr;
+		case 0x1E: // CMP X,abs
+			data = get_le16(pc);
+			++pc;
+		cmp_x_addr:
+			data = this->cpu_read(data, rel_time);
+		case 0xC8: // CMP X,imm
+			nz = x - data;
+			c = ~nz;
+			nz &= 0xFF;
+			goto inc_pc_loop;
+
+		case 0x7E: // CMP Y,dp
+			data += dp;
+			goto cmp_y_addr;
+		case 0x5E: // CMP Y,abs
+			data = get_le16(pc);
+			++pc;
+		cmp_y_addr:
+			data = this->cpu_read(data, rel_time);
+		case 0xAD: // CMP Y,imm
+			nz = y - data;
+			c = ~nz;
+			nz &= 0xFF;
+			goto inc_pc_loop;
+
+		{
+			int addr;
+			case 0xB9: // SBC (x),(y)
+			case 0x99: // ADC (x),(y)
+				--pc; // compensate for inc later
+				data = this->cpu_read(DP_ADDR(y), rel_time - 2);
+				addr = x + dp;
+				goto adc_addr;
+			case 0xA9: // SBC dp,dp
+			case 0x89: // ADC dp,dp
+				data = this->cpu_read(DP_ADDR(data), rel_time - 3);
+			case 0xB8: // SBC dp,imm
+			case 0x98: // ADC dp,imm
+				addr = *(++pc) + dp;
+			adc_addr:
+				nz = this->cpu_read(addr, rel_time - 1);
+				goto adc_data;
+
+			// catch ADC and SBC together, then decode later based on operand
+#undef CASE
+#define CASE(n) case n: case (n) + 0x20:
+				ADDR_MODES(0x88) // ADC/SBC addr
+				data = this->cpu_read(data, rel_time);
+			case 0xA8: // SBC imm
+			case 0x88: // ADC imm
+				addr = -1; // A
+				nz = a;
+			adc_data:
+			{
+				int flags;
+				if (opcode >= 0xA0) // SBC
+					data ^= 0xFF;
+
+				flags = data ^ nz;
+				nz += data + (c >> 8 & 1);
+				flags ^= nz;
+
+				psw = (psw & ~(v40 | h08)) | ((flags >> 1) & h08) | (((flags + 0x80) >> 2) & v40);
+				c = nz;
+				if (addr < 0)
+				{
+					a = static_cast<uint8_t>(nz);
+					goto inc_pc_loop;
+				}
+				this->cpu_write(/*(uint8_t)*/nz, addr, rel_time);
+				goto inc_pc_loop;
+			}
+		}
+
+		// 6. ADDITION & SUBTRACTION COMMANDS
+
+#define INC_DEC_REG(reg, op) \
+	nz = reg op; \
+	reg = static_cast<uint8_t>(nz); \
+	goto loop;
+
+		case 0xBC: INC_DEC_REG(a, + 1) // INC A
+		case 0x3D: INC_DEC_REG(x, + 1) // INC X
+		case 0xFC: INC_DEC_REG(y, + 1) // INC Y
+
+		case 0x9C: INC_DEC_REG(a, - 1) // DEC A
+		case 0x1D: INC_DEC_REG(x, - 1) // DEC X
+		case 0xDC: INC_DEC_REG(y, - 1) // DEC Y
+
+		case 0x9B: // DEC dp+X
+		case 0xBB: // INC dp+X
+			data = static_cast<uint8_t>(data + x);
+		case 0x8B: // DEC dp
+		case 0xAB: // INC dp
+			data += dp;
+			goto inc_abs;
+		case 0x8C: // DEC abs
+		case 0xAC: // INC abs
+			data = get_le16(pc);
+			++pc;
+		inc_abs:
+			nz = ((opcode >> 4) & 2) - 1;
+			nz += this->cpu_read(data, rel_time - 1);
+			this->cpu_write(/*(uint8_t)*/ nz, data, rel_time);
+			goto inc_pc_loop;
+
+		// 7. SHIFT, ROTATION COMMANDS
+
+		case 0x5C: // LSR A
+			c = 0;
+		case 0x7C: // ROR A
+		{
+			nz = ((c >> 1) & 0x80) | (a >> 1);
+			c = a << 8;
+			a = nz;
+			goto loop;
+		}
+
+		case 0x1C: // ASL A
+			c = 0;
+		case 0x3C: // ROL A
+		{
+			int temp = c >> 8 & 1;
+			c = a << 1;
+			nz = c | temp;
+			a = static_cast<uint8_t>(nz);
+			goto loop;
+		}
+
+		case 0x0B: // ASL dp
+			c = 0;
+			data += dp;
+			goto rol_mem;
+		case 0x1B: // ASL dp+X
+			c = 0;
+		case 0x3B: // ROL dp+X
+			data = static_cast<uint8_t>(data + x);
+		case 0x2B: // ROL dp
+			data += dp;
+			goto rol_mem;
+		case 0x0C: // ASL abs
+			c = 0;
+		case 0x2C: // ROL abs
+			data = get_le16(pc);
+			++pc;
+		rol_mem:
+			nz = c >> 8 & 1;
+			nz |= (c = this->cpu_read(data, rel_time - 1) << 1);
+			this->cpu_write(/*(uint8_t)*/ nz, data, rel_time);
+			goto inc_pc_loop;
+
+		case 0x4B: // LSR dp
+			c = 0;
+			data += dp;
+			goto ror_mem;
+		case 0x5B: // LSR dp+X
+			c = 0;
+		case 0x7B: // ROR dp+X
+			data = static_cast<uint8_t>(data + x);
+		case 0x6B: // ROR dp
+			data += dp;
+			goto ror_mem;
+		case 0x4C: // LSR abs
+			c = 0;
+		case 0x6C: // ROR abs
+			data = get_le16(pc);
+			++pc;
+		ror_mem:
+		{
+			int temp = this->cpu_read(data, rel_time - 1);
+			nz = (c >> 1 & 0x80) | (temp >> 1);
+			c = temp << 8;
+			this->cpu_write(nz, data, rel_time);
+			goto inc_pc_loop;
+		}
+
+		case 0x9F: // XCN
+			nz = a = (a >> 4) | static_cast<uint8_t>(a << 4);
+			goto loop;
+
+		// 8. 16-BIT TRANSMISION COMMANDS
+
+		case 0xBA: // MOVW YA,dp
+			a = this->cpu_read(DP_ADDR(data), rel_time - 2);
+			nz = (a & 0x7F) | (a >> 1);
+			y = this->cpu_read(DP_ADDR(static_cast<uint8_t>(data + 1)), rel_time);
+			nz |= y;
+			goto inc_pc_loop;
+
+		case 0xDA: // MOVW dp,YA
+			this->cpu_write(a, DP_ADDR(data), rel_time - 1);
+			this->cpu_write(y + no_read_before_write, DP_ADDR(static_cast<uint8_t>(data + 1)), rel_time);
+			goto inc_pc_loop;
+
+		// 9. 16-BIT OPERATION COMMANDS
+
+		case 0x3A: // INCW dp
+		case 0x1A: // DECW dp
+		{
+			int temp;
+			// low byte
+			data += dp;
+			temp = this->cpu_read(data, rel_time - 3);
+			temp += (opcode >> 4 & 2) - 1; // +1 for INCW, -1 for DECW
+			nz = ((temp >> 1) | temp) & 0x7F;
+			this->cpu_write(/*(uint8_t)*/ temp, data, rel_time - 2);
+
+			// high byte
+			data = static_cast<uint8_t>(data + 1) + dp;
+			temp = static_cast<uint8_t>((temp >> 8) + this->cpu_read(data, rel_time - 1));
+			nz |= temp;
+			this->cpu_write(temp, data, rel_time);
+
+			goto inc_pc_loop;
+		}
+
+		case 0x7A: // ADDW YA,dp
+		case 0x9A: // SUBW YA,dp
+		{
+			int lo = this->cpu_read(DP_ADDR(data), rel_time - 2);
+			int hi = this->cpu_read(DP_ADDR(static_cast<uint8_t>(data + 1)), rel_time);
+
+			if (opcode == 0x9A) // SUBW
+			{
+				lo = (lo ^ 0xFF) + 1;
+				hi ^= 0xFF;
+			}
+
+			lo += a;
+			int result = y + hi + (lo >> 8);
+			int flags = hi ^ y ^ result;
+
+			psw = (psw & ~(v40 | h08)) | (flags >> 1 & h08) | ((flags + 0x80) >> 2 & v40);
+			c = result;
+			a = static_cast<uint8_t>(lo);
+			result = static_cast<uint8_t>(result);
+			y = result;
+			nz = (((lo >> 1) | lo) & 0x7F) | result;
+
+			goto inc_pc_loop;
+		}
+
+		case 0x5A: // CMPW YA,dp
+		{
+			int temp = a - this->cpu_read(DP_ADDR(data), rel_time - 1);
+			nz = ((temp >> 1) | temp) & 0x7F;
+			temp = y + (temp >> 8);
+			temp -= this->cpu_read(DP_ADDR(static_cast<uint8_t>(data + 1)), rel_time);
+			nz |= temp;
+			c  = ~temp;
+			nz &= 0xFF;
+			goto inc_pc_loop;
+		}
+
+		// 10. MULTIPLICATION & DIVISON COMMANDS
+
+		case 0xCF: // MUL YA
+		{
+			unsigned temp = y * a;
+			a = static_cast<uint8_t>(temp);
+			nz = ((temp >> 1) | temp) & 0x7F;
+			y = temp >> 8;
+			nz |= y;
+			goto loop;
+		}
+
+		case 0x9E: // DIV YA,X
+		{
+			unsigned ya = y * 0x100 + a;
+
+			psw &= ~(h08 | v40);
+
+			if (y >= x)
+				psw |= v40;
+
+			if ((y & 15) >= (x & 15))
+				psw |= h08;
+
+			if (y < x * 2)
+			{
+				a = ya / x;
+				y = ya - a * x;
+			}
+			else
+			{
+				a = 255 - (ya - x * 0x200) / (256 - x);
+				y = x + (ya - x * 0x200) % (256 - x);
+			}
+
+			nz = static_cast<uint8_t>(a);
+			a = static_cast<uint8_t>(a);
+
+			goto loop;
+		}
+
+		// 11. DECIMAL COMPENSATION COMMANDS
+
+		case 0xDF: // DAA
+			if (a > 0x99 || c & 0x100)
+			{
+				a += 0x60;
+				c = 0x100;
+			}
+
+			if ((a & 0x0F) > 9 || psw & h08)
+				a += 0x06;
+
+			nz = a;
+			a = static_cast<uint8_t>(a);
+			goto loop;
+
+		case 0xBE: // DAS
+			if (a > 0x99 || !(c & 0x100))
+			{
+				a -= 0x60;
+				c = 0;
+			}
+
+			if ((a & 0x0F) > 9 || !(psw & h08))
+				a -= 0x06;
+
+			nz = a;
+			a = static_cast<uint8_t>(a);
+			goto loop;
+
+		// 12. BRANCHING COMMANDS
+
+		case 0x2F: // BRA rel
+			pc += static_cast<int8_t>(data);
+			goto inc_pc_loop;
+
+		case 0x30: // BMI
+			BRANCH(nz & nz_neg_mask)
+
+		case 0x10: // BPL
+			BRANCH(!(nz & nz_neg_mask))
+
+		case 0xB0: // BCS
+			BRANCH(c & 0x100)
+
+		case 0x90: // BCC
+			BRANCH(!(c & 0x100))
+
+		case 0x70: // BVS
+			BRANCH(psw & v40)
+
+		case 0x50: // BVC
+			BRANCH(!(psw & v40))
+
+#define CBRANCH(cond) \
+{ \
+	++pc; \
+	if (cond) \
+		goto cbranch_taken_loop; \
+	rel_time -= 2; \
+	goto inc_pc_loop; \
+}
+
+		case 0x03: // BBS dp.bit,rel
+		case 0x23:
+		case 0x43:
+		case 0x63:
+		case 0x83:
+		case 0xA3:
+		case 0xC3:
+		case 0xE3:
+			CBRANCH((this->cpu_read(DP_ADDR(data), rel_time - 4) >> (opcode >> 5)) & 1)
+
+		case 0x13: // BBC dp.bit,rel
+		case 0x33:
+		case 0x53:
+		case 0x73:
+		case 0x93:
+		case 0xB3:
+		case 0xD3:
+		case 0xF3:
+			CBRANCH(!((this->cpu_read(DP_ADDR(data), rel_time - 4) >> (opcode >> 5)) & 1))
+
+		case 0xDE: // CBNE dp+X,rel
+			data = static_cast<uint8_t>(data + x);
+			// fall through
+		case 0x2E: // CBNE dp,rel
+		{
+			// 61% from timer
+			int temp = CPU_READ_TIMER(-4, DP_ADDR(data));
+			CBRANCH(temp != a)
+		}
+
+		case 0x6E: // DBNZ dp,rel
+		{
+			unsigned temp = this->cpu_read(DP_ADDR(data), rel_time - 4) - 1;
+			this->cpu_write(/*(uint8_t)*/ temp + no_read_before_write, DP_ADDR(static_cast<uint8_t>(data)), rel_time - 3);
+			CBRANCH(temp)
+		}
+
+		case 0xFE: // DBNZ Y,rel
+			y = static_cast<uint8_t>(y - 1);
+			BRANCH(y)
+
+		case 0x1F: // JMP [abs+X]
+			SET_PC(get_le16(pc) + x);
+			// fall through
+		case 0x5F: // JMP abs
+			SET_PC(get_le16(pc));
+			goto loop;
+
+		// 13. SUB-ROUTINE CALL RETURN COMMANDS
+
+		case 0x0F: // BRK
+		{
+			int temp;
+			int ret_addr = GET_PC();
+			SET_PC(READ_PROG16(0xFFDE)); // vector address verified
+			PUSH16(ret_addr);
+			GET_PSW(temp);
+			psw = (psw | b10) & ~i04;
+			PUSH(temp);
+			goto loop;
+		}
+
+		case 0x4F: // PCALL offset
+		{
+			int ret_addr = GET_PC() + 1;
+			SET_PC(0xFF00 | data);
+			PUSH16(ret_addr);
+			goto loop;
+		}
+
+		case 0x01: // TCALL n
+		case 0x11:
+		case 0x21:
+		case 0x31:
+		case 0x41:
+		case 0x51:
+		case 0x61:
+		case 0x71:
+		case 0x81:
+		case 0x91:
+		case 0xA1:
+		case 0xB1:
+		case 0xC1:
+		case 0xD1:
+		case 0xE1:
+		case 0xF1:
+		{
+			int ret_addr = GET_PC();
+			SET_PC(READ_PROG16(0xFFDE - (opcode >> 3)));
+			PUSH16(ret_addr);
+			goto loop;
+		}
+
+		// 14. STACK OPERATION COMMANDS
+
+		{
+			int temp;
+		case 0x7F: // RET1
+			temp = *sp;
+			SET_PC(get_le16(sp + 1));
+			sp += 3;
+			goto set_psw;
+		case 0x8E: // POP PSW
+			POP(temp);
+		set_psw:
+			SET_PSW(temp);
+			goto loop;
+		}
+
+		case 0x0D: // PUSH PSW
+		{
+			int temp;
+			GET_PSW(temp);
+			PUSH(temp);
+			goto loop;
+		}
+
+		case 0x2D: // PUSH A
+			PUSH(a);
+			goto loop;
+
+		case 0x4D: // PUSH X
+			PUSH(x);
+			goto loop;
+
+		case 0x6D: // PUSH Y
+			PUSH(y);
+			goto loop;
+
+		case 0xAE: // POP A
+			POP(a);
+			goto loop;
+
+		case 0xCE: // POP X
+			POP(x);
+			goto loop;
+
+		case 0xEE: // POP Y
+			POP(y);
+			goto loop;
+
+		// 15. BIT OPERATION COMMANDS
+
+		case 0x02: // SET1
+		case 0x22:
+		case 0x42:
+		case 0x62:
+		case 0x82:
+		case 0xA2:
+		case 0xC2:
+		case 0xE2:
+		case 0x12: // CLR1
+		case 0x32:
+		case 0x52:
+		case 0x72:
+		case 0x92:
+		case 0xB2:
+		case 0xD2:
+		case 0xF2:
+		{
+			int bit = 1 << (opcode >> 5);
+			int mask = ~bit;
+			if (opcode & 0x10)
+				bit = 0;
+			data += dp;
+			this->cpu_write((this->cpu_read(data, rel_time - 1) & mask) | bit, data, rel_time);
+			goto inc_pc_loop;
+		}
+
+		case 0x0E: // TSET1 abs
+		case 0x4E: // TCLR1 abs
+			data = get_le16(pc);
+			pc += 2;
+			{
+				unsigned temp = this->cpu_read(data, rel_time - 2);
+				nz = static_cast<uint8_t>(a - temp);
+				temp &= ~a;
+				if (opcode == 0x0E)
+					temp |= a;
+				this->cpu_write(temp, data, rel_time);
+			}
+			goto loop;
+
+		case 0x4A: // AND1 C,mem.bit
+			c &= MEM_BIT(0);
+			pc += 2;
+			goto loop;
+
+		case 0x6A: // AND1 C,/mem.bit
+			c &= ~MEM_BIT(0);
+			pc += 2;
+			goto loop;
+
+		case 0x0A: // OR1 C,mem.bit
+			c |= MEM_BIT(-1);
+			pc += 2;
+			goto loop;
+
+		case 0x2A: // OR1 C,/mem.bit
+			c |= ~MEM_BIT(-1);
+			pc += 2;
+			goto loop;
+
+		case 0x8A: // EOR1 C,mem.bit
+			c ^= MEM_BIT(-1);
+			pc += 2;
+			goto loop;
+
+		case 0xEA: // NOT1 mem.bit
+			data = get_le16(pc);
+			pc += 2;
+			{
+				unsigned temp = this->cpu_read(data & 0x1FFF, rel_time - 1);
+				temp ^= 1 << (data >> 13);
+				this->cpu_write(temp, data & 0x1FFF, rel_time);
+			}
+			goto loop;
+
+		case 0xCA: // MOV1 mem.bit,C
+			data = get_le16(pc);
+			pc += 2;
+			{
+				unsigned temp = this->cpu_read(data & 0x1FFF, rel_time - 2);
+				unsigned bit = data >> 13;
+				temp = (temp & ~(1 << bit)) | ((c >> 8 & 1) << bit);
+				this->cpu_write(temp + no_read_before_write, data & 0x1FFF, rel_time);
+			}
+			goto loop;
+
+		case 0xAA: // MOV1 C,mem.bit
+			c = MEM_BIT(0);
+			pc += 2;
+			goto loop;
+
+		// 16. PROGRAM PSW FLAG OPERATION COMMANDS
+
+		case 0x60: // CLRC
+			c = 0;
+			goto loop;
+
+		case 0x80: // SETC
+			c = ~0;
+			goto loop;
+
+		case 0xED: // NOTC
+			c ^= 0x100;
+			goto loop;
+
+		case 0xE0: // CLRV
+			psw &= ~(v40 | h08);
+			goto loop;
+
+		case 0x20: // CLRP
+			dp = 0;
+			goto loop;
+
+		case 0x40: // SETP
+			dp = 0x100;
+			goto loop;
+
+		case 0xA0: // EI
+			psw |= i04;
+			goto loop;
+
+		case 0xC0: // DI
+			psw &= ~i04;
+			goto loop;
+
+		// 17. OTHER COMMANDS
+
+		case 0x00: // NOP
+			goto loop;
+
+		case 0xFF: // STOP
+		{
+			// handle PC wrap-around
+			unsigned addr = GET_PC() - 1;
+			if (addr >= 0x10000)
+			{
+				addr &= 0xFFFF;
+				SET_PC(addr);
+				goto loop;
+			}
+		}
+		// fall through
+		case 0xEF: // SLEEP
+			--pc;
+			rel_time = 0;
+			goto stop;
+	} // switch
+
+	assert(0); // catch any unhandled instructions
+}
+out_of_time:
+	rel_time -= this->m.cycle_table[*pc]; // undo partial execution of opcode
+stop:
+
+	// Uncache registers
+	m.cpu_regs.pc = static_cast<uint16_t>(GET_PC());
+	m.cpu_regs.sp = static_cast<uint8_t>(GET_SP());
+	m.cpu_regs.a = static_cast<uint8_t>(a);
+	m.cpu_regs.x = static_cast<uint8_t>(x);
+	m.cpu_regs.y = static_cast<uint8_t>(y);
 	{
 		int temp;
-	case 0xCC: // MOV abs,Y
-		temp = y;
-		goto mov_abs_temp;
-	case 0xC9: // MOV abs,X
-		temp = x;
-	mov_abs_temp:
-		WRITE( 0, READ_PC16( pc ), temp );
-		pc += 2;
-		goto loop;
-	}
-	
-	case 0xD9: // MOV dp+Y,X
-		data = (uint8_t) (data + y);
-	case 0xD8: // MOV dp,X
-		WRITE( 0, data + dp, x );
-		goto inc_pc_loop;
-	
-	case 0xDB: // MOV dp+X,Y
-		data = (uint8_t) (data + x);
-	case 0xCB: // MOV dp,Y
-		WRITE( 0, data + dp, y );
-		goto inc_pc_loop;
-
-// 3. 8-BIT DATA TRANSMISSIN COMMANDS, GROUP 3.
-	
-	case 0x7D: // MOV A,X
-		a  = x;
-		nz = x;
-		goto loop;
-	
-	case 0xDD: // MOV A,Y
-		a  = y;
-		nz = y;
-		goto loop;
-	
-	case 0x5D: // MOV X,A
-		x  = a;
-		nz = a;
-		goto loop;
-	
-	case 0xFD: // MOV Y,A
-		y  = a;
-		nz = a;
-		goto loop;
-	
-	case 0x9D: // MOV X,SP
-		x = nz = GET_SP();
-		goto loop;
-	
-	case 0xBD: // MOV SP,X
-		SET_SP( x );
-		goto loop;
-	
-	//case 0xC6: // MOV (X),A (handled by MOV addr,A in group 2)
-	
-	case 0xAF: // MOV (X)+,A
-		WRITE_DP( 0, x, a + no_read_before_write  );
-		x++;
-		goto loop;
-	
-// 5. 8-BIT LOGIC OPERATION COMMANDS
-	
-#define LOGICAL_OP( op, func )\
-	ADDR_MODES( op ) /* addr */\
-		data = READ( 0, data );\
-	case op: /* imm */\
-		nz = a func##= data;\
-		goto inc_pc_loop;\
-	{   unsigned addr;\
-	case op + 0x11: /* X,Y */\
-		data = READ_DP( -2, y );\
-		addr = x + dp;\
-		goto addr_##op;\
-	case op + 0x01: /* dp,dp */\
-		data = READ_DP( -3, data );\
-	case op + 0x10:{/*dp,imm*/\
-		uint8_t const* addr2 = pc + 1;\
-		pc += 2;\
-		addr = READ_PC( addr2 ) + dp;\
-	}\
-	addr_##op:\
-		nz = data func READ( -1, addr );\
-		WRITE( 0, addr, nz );\
-		goto loop;\
-	}
-	
-	LOGICAL_OP( 0x28, & ); // AND
-	
-	LOGICAL_OP( 0x08, | ); // OR
-	
-	LOGICAL_OP( 0x48, ^ ); // EOR
-	
-// 4. 8-BIT ARITHMETIC OPERATION COMMANDS
-
-	ADDR_MODES( 0x68 ) // CMP addr
-		data = READ( 0, data );
-	case 0x68: // CMP imm
-		nz = a - data;
-		c = ~nz;
-		nz &= 0xFF;
-		goto inc_pc_loop;
-	
-	case 0x79: // CMP (X),(Y)
-		data = READ_DP( -2, y );
-		nz = READ_DP( -1, x ) - data;
-		c = ~nz;
-		nz &= 0xFF;
-		goto loop;
-	
-	case 0x69: // CMP dp,dp
-		data = READ_DP( -3, data );
-	case 0x78: // CMP dp,imm
-		nz = READ_DP( -1, READ_PC( ++pc ) ) - data;
-		c = ~nz;
-		nz &= 0xFF;
-		goto inc_pc_loop;
-	
-	case 0x3E: // CMP X,dp
-		data += dp;
-		goto cmp_x_addr;
-	case 0x1E: // CMP X,abs
-		data = READ_PC16( pc );
-		pc++;
-	cmp_x_addr:
-		data = READ( 0, data );
-	case 0xC8: // CMP X,imm
-		nz = x - data;
-		c = ~nz;
-		nz &= 0xFF;
-		goto inc_pc_loop;
-	
-	case 0x7E: // CMP Y,dp
-		data += dp;
-		goto cmp_y_addr;
-	case 0x5E: // CMP Y,abs
-		data = READ_PC16( pc );
-		pc++;
-	cmp_y_addr:
-		data = READ( 0, data );
-	case 0xAD: // CMP Y,imm
-		nz = y - data;
-		c = ~nz;
-		nz &= 0xFF;
-		goto inc_pc_loop;
-	
-	{
-		int addr;
-	case 0xB9: // SBC (x),(y)
-	case 0x99: // ADC (x),(y)
-		pc--; // compensate for inc later
-		data = READ_DP( -2, y );
-		addr = x + dp;
-		goto adc_addr;
-	case 0xA9: // SBC dp,dp
-	case 0x89: // ADC dp,dp
-		data = READ_DP( -3, data );
-	case 0xB8: // SBC dp,imm
-	case 0x98: // ADC dp,imm
-		addr = READ_PC( ++pc ) + dp;
-	adc_addr:
-		nz = READ( -1, addr );
-		goto adc_data;
-		
-// catch ADC and SBC together, then decode later based on operand
-#undef CASE
-#define CASE( n ) case n: case (n) + 0x20:
-	ADDR_MODES( 0x88 ) // ADC/SBC addr
-		data = READ( 0, data );
-	case 0xA8: // SBC imm
-	case 0x88: // ADC imm
-		addr = -1; // A
-		nz = a;
-	adc_data: {
-		int flags;
-		if ( opcode >= 0xA0 ) // SBC
-			data ^= 0xFF;
-		
-		flags = data ^ nz;
-		nz += data + (c >> 8 & 1);
-		flags ^= nz;
-		
-		psw = (psw & ~(v40 | h08)) |
-				(flags >> 1 & h08) |
-				((flags + 0x80) >> 2 & v40);
-		c = nz;
-		if ( addr < 0 )
-		{
-			a = (uint8_t) nz;
-			goto inc_pc_loop;
-		}
-		WRITE( 0, addr, /*(uint8_t)*/ nz );
-		goto inc_pc_loop;
-	}
-	
-	}
-	
-// 6. ADDITION & SUBTRACTION COMMANDS
-
-#define INC_DEC_REG( reg, op )\
-		nz  = reg op;\
-		reg = (uint8_t) nz;\
-		goto loop;
-
-	case 0xBC: INC_DEC_REG( a, + 1 ) // INC A
-	case 0x3D: INC_DEC_REG( x, + 1 ) // INC X
-	case 0xFC: INC_DEC_REG( y, + 1 ) // INC Y
-	
-	case 0x9C: INC_DEC_REG( a, - 1 ) // DEC A
-	case 0x1D: INC_DEC_REG( x, - 1 ) // DEC X
-	case 0xDC: INC_DEC_REG( y, - 1 ) // DEC Y
-
-	case 0x9B: // DEC dp+X
-	case 0xBB: // INC dp+X
-		data = (uint8_t) (data + x);
-	case 0x8B: // DEC dp
-	case 0xAB: // INC dp
-		data += dp;
-		goto inc_abs;
-	case 0x8C: // DEC abs
-	case 0xAC: // INC abs
-		data = READ_PC16( pc );
-		pc++;
-	inc_abs:
-		nz = (opcode >> 4 & 2) - 1;
-		nz += READ( -1, data );
-		WRITE( 0, data, /*(uint8_t)*/ nz );
-		goto inc_pc_loop;
-	
-// 7. SHIFT, ROTATION COMMANDS
-
-	case 0x5C: // LSR A
-		c = 0;
-	case 0x7C:{// ROR A
-		nz = (c >> 1 & 0x80) | (a >> 1);
-		c = a << 8;
-		a = nz;
-		goto loop;
-	}
-	
-	case 0x1C: // ASL A
-		c = 0;
-	case 0x3C:{// ROL A
-		int temp = c >> 8 & 1;
-		c = a << 1;
-		nz = c | temp;
-		a = (uint8_t) nz;
-		goto loop;
-	}
-	
-	case 0x0B: // ASL dp
-		c = 0;
-		data += dp;
-		goto rol_mem;
-	case 0x1B: // ASL dp+X
-		c = 0;
-	case 0x3B: // ROL dp+X
-		data = (uint8_t) (data + x);
-	case 0x2B: // ROL dp
-		data += dp;
-		goto rol_mem;
-	case 0x0C: // ASL abs
-		c = 0;
-	case 0x2C: // ROL abs
-		data = READ_PC16( pc );
-		pc++;
-	rol_mem:
-		nz = c >> 8 & 1;
-		nz |= (c = READ( -1, data ) << 1);
-		WRITE( 0, data, /*(uint8_t)*/ nz );
-		goto inc_pc_loop;
-	
-	case 0x4B: // LSR dp
-		c = 0;
-		data += dp;
-		goto ror_mem;
-	case 0x5B: // LSR dp+X
-		c = 0;
-	case 0x7B: // ROR dp+X
-		data = (uint8_t) (data + x);
-	case 0x6B: // ROR dp
-		data += dp;
-		goto ror_mem;
-	case 0x4C: // LSR abs
-		c = 0;
-	case 0x6C: // ROR abs
-		data = READ_PC16( pc );
-		pc++;
-	ror_mem: {
-		int temp = READ( -1, data );
-		nz = (c >> 1 & 0x80) | (temp >> 1);
-		c = temp << 8;
-		WRITE( 0, data, nz );
-		goto inc_pc_loop;
-	}
-
-	case 0x9F: // XCN
-		nz = a = (a >> 4) | (uint8_t) (a << 4);
-		goto loop;
-
-// 8. 16-BIT TRANSMISION COMMANDS
-
-	case 0xBA: // MOVW YA,dp
-		a = READ_DP( -2, data );
-		nz = (a & 0x7F) | (a >> 1);
-		y = READ_DP( 0, (uint8_t) (data + 1) );
-		nz |= y;
-		goto inc_pc_loop;
-	
-	case 0xDA: // MOVW dp,YA
-		WRITE_DP( -1, data, a );
-		WRITE_DP( 0, (uint8_t) (data + 1), y + no_read_before_write  );
-		goto inc_pc_loop;
-	
-// 9. 16-BIT OPERATION COMMANDS
-
-	case 0x3A: // INCW dp
-	case 0x1A:{// DECW dp
-		int temp;
-		// low byte
-		data += dp;
-		temp = READ( -3, data );
-		temp += (opcode >> 4 & 2) - 1; // +1 for INCW, -1 for DECW
-		nz = ((temp >> 1) | temp) & 0x7F;
-		WRITE( -2, data, /*(uint8_t)*/ temp );
-		
-		// high byte
-		data = (uint8_t) (data + 1) + dp;
-		temp = (uint8_t) ((temp >> 8) + READ( -1, data ));
-		nz |= temp;
-		WRITE( 0, data, temp );
-		
-		goto inc_pc_loop;
-	}
-		
-	case 0x7A: // ADDW YA,dp
-	case 0x9A:{// SUBW YA,dp
-		int lo = READ_DP( -2, data );
-		int hi = READ_DP( 0, (uint8_t) (data + 1) );
-		int result;
-		int flags;
-		
-		if ( opcode == 0x9A ) // SUBW
-		{
-			lo = (lo ^ 0xFF) + 1;
-			hi ^= 0xFF;
-		}
-		
-		lo += a;
-		result = y + hi + (lo >> 8);
-		flags = hi ^ y ^ result;
-		
-		psw = (psw & ~(v40 | h08)) |
-				(flags >> 1 & h08) |
-				((flags + 0x80) >> 2 & v40);
-		c = result;
-		a = (uint8_t) lo;
-		result = (uint8_t) result;
-		y = result;
-		nz = (((lo >> 1) | lo) & 0x7F) | result;
-		
-		goto inc_pc_loop;
-	}
-	
-	case 0x5A: { // CMPW YA,dp
-		int temp = a - READ_DP( -1, data );
-		nz = ((temp >> 1) | temp) & 0x7F;
-		temp = y + (temp >> 8);
-		temp -= READ_DP( 0, (uint8_t) (data + 1) );
-		nz |= temp;
-		c  = ~temp;
-		nz &= 0xFF;
-		goto inc_pc_loop;
-	}
-	
-// 10. MULTIPLICATION & DIVISON COMMANDS
-
-	case 0xCF: { // MUL YA
-		unsigned temp = y * a;
-		a = (uint8_t) temp;
-		nz = ((temp >> 1) | temp) & 0x7F;
-		y = temp >> 8;
-		nz |= y;
-		goto loop;
-	}
-	
-	case 0x9E: // DIV YA,X
-	{
-		unsigned ya = y * 0x100 + a;
-		
-		psw &= ~(h08 | v40);
-		
-		if ( y >= x )
-			psw |= v40;
-		
-		if ( (y & 15) >= (x & 15) )
-			psw |= h08;
-		
-		if ( y < x * 2 )
-		{
-			a = ya / x;
-			y = ya - a * x;
-		}
-		else
-		{
-			a = 255 - (ya - x * 0x200) / (256 - x);
-			y = x   + (ya - x * 0x200) % (256 - x);
-		}
-		
-		nz = (uint8_t) a;
-		a = (uint8_t) a;
-		
-		goto loop;
-	}
-	
-// 11. DECIMAL COMPENSATION COMMANDS
-	
-	case 0xDF: // DAA
-		SUSPICIOUS_OPCODE( "DAA" );
-		if ( a > 0x99 || c & 0x100 )
-		{
-			a += 0x60;
-			c = 0x100;
-		}
-		
-		if ( (a & 0x0F) > 9 || psw & h08 )
-			a += 0x06;
-		
-		nz = a;
-		a = (uint8_t) a;
-		goto loop;
-	
-	case 0xBE: // DAS
-		SUSPICIOUS_OPCODE( "DAS" );
-		if ( a > 0x99 || !(c & 0x100) )
-		{
-			a -= 0x60;
-			c = 0;
-		}
-		
-		if ( (a & 0x0F) > 9 || !(psw & h08) )
-			a -= 0x06;
-		
-		nz = a;
-		a = (uint8_t) a;
-		goto loop;
-	
-// 12. BRANCHING COMMANDS
-
-	case 0x2F: // BRA rel
-		pc += (BOOST::int8_t) data;
-		goto inc_pc_loop;
-	
-	case 0x30: // BMI
-		BRANCH( (nz & nz_neg_mask) )
-	
-	case 0x10: // BPL
-		BRANCH( !(nz & nz_neg_mask) )
-	
-	case 0xB0: // BCS
-		BRANCH( c & 0x100 )
-	
-	case 0x90: // BCC
-		BRANCH( !(c & 0x100) )
-	
-	case 0x70: // BVS
-		BRANCH( psw & v40 )
-	
-	case 0x50: // BVC
-		BRANCH( !(psw & v40) )
-	
-	#define CBRANCH( cond )\
-	{\
-		pc++;\
-		if ( cond )\
-			goto cbranch_taken_loop;\
-		rel_time -= 2;\
-		goto inc_pc_loop;\
-	}
-	
-	case 0x03: // BBS dp.bit,rel
-	case 0x23:
-	case 0x43:
-	case 0x63:
-	case 0x83:
-	case 0xA3:
-	case 0xC3:
-	case 0xE3:
-		CBRANCH( READ_DP( -4, data ) >> (opcode >> 5) & 1 )
-	
-	case 0x13: // BBC dp.bit,rel
-	case 0x33:
-	case 0x53:
-	case 0x73:
-	case 0x93:
-	case 0xB3:
-	case 0xD3:
-	case 0xF3:
-		CBRANCH( !(READ_DP( -4, data ) >> (opcode >> 5) & 1) )
-	
-	case 0xDE: // CBNE dp+X,rel
-		data = (uint8_t) (data + x);
-		// fall through
-	case 0x2E:{// CBNE dp,rel
-		int temp;
-		// 61% from timer
-		READ_DP_TIMER( -4, data, temp );
-		CBRANCH( temp != a )
-	}
-	
-	case 0x6E: { // DBNZ dp,rel
-		unsigned temp = READ_DP( -4, data ) - 1;
-		WRITE_DP( -3, (uint8_t) data, /*(uint8_t)*/ temp + no_read_before_write  );
-		CBRANCH( temp )
-	}
-	
-	case 0xFE: // DBNZ Y,rel
-		y = (uint8_t) (y - 1);
-		BRANCH( y )
-	
-	case 0x1F: // JMP [abs+X]
-		SET_PC( READ_PC16( pc ) + x );
-		// fall through
-	case 0x5F: // JMP abs
-		SET_PC( READ_PC16( pc ) );
-		goto loop;
-	
-// 13. SUB-ROUTINE CALL RETURN COMMANDS
-	
-	case 0x0F:{// BRK
-		int temp;
-		int ret_addr = GET_PC();
-		SUSPICIOUS_OPCODE( "BRK" );
-		SET_PC( READ_PROG16( 0xFFDE ) ); // vector address verified
-		PUSH16( ret_addr );
-		GET_PSW( temp );
-		psw = (psw | b10) & ~i04;
-		PUSH( temp );
-		goto loop;
-	}
-	
-	case 0x4F:{// PCALL offset
-		int ret_addr = GET_PC() + 1;
-		SET_PC( 0xFF00 | data );
-		PUSH16( ret_addr );
-		goto loop;
-	}
-	
-	case 0x01: // TCALL n
-	case 0x11:
-	case 0x21:
-	case 0x31:
-	case 0x41:
-	case 0x51:
-	case 0x61:
-	case 0x71:
-	case 0x81:
-	case 0x91:
-	case 0xA1:
-	case 0xB1:
-	case 0xC1:
-	case 0xD1:
-	case 0xE1:
-	case 0xF1: {
-		int ret_addr = GET_PC();
-		SET_PC( READ_PROG16( 0xFFDE - (opcode >> 3) ) );
-		PUSH16( ret_addr );
-		goto loop;
-	}
-	
-// 14. STACK OPERATION COMMANDS
-
-	{
-		int temp;
-	case 0x7F: // RET1
-		temp = *sp;
-		SET_PC( GET_LE16( sp + 1 ) );
-		sp += 3;
-		goto set_psw;
-	case 0x8E: // POP PSW
-		POP( temp );
-	set_psw:
-		SET_PSW( temp );
-		goto loop;
-	}
-	
-	case 0x0D: { // PUSH PSW
-		int temp;
-		GET_PSW( temp );
-		PUSH( temp );
-		goto loop;
-	}
-
-	case 0x2D: // PUSH A
-		PUSH( a );
-		goto loop;
-	
-	case 0x4D: // PUSH X
-		PUSH( x );
-		goto loop;
-	
-	case 0x6D: // PUSH Y
-		PUSH( y );
-		goto loop;
-	
-	case 0xAE: // POP A
-		POP( a );
-		goto loop;
-	
-	case 0xCE: // POP X
-		POP( x );
-		goto loop;
-	
-	case 0xEE: // POP Y
-		POP( y );
-		goto loop;
-	
-// 15. BIT OPERATION COMMANDS
-
-	case 0x02: // SET1
-	case 0x22:
-	case 0x42:
-	case 0x62:
-	case 0x82:
-	case 0xA2:
-	case 0xC2:
-	case 0xE2:
-	case 0x12: // CLR1
-	case 0x32:
-	case 0x52:
-	case 0x72:
-	case 0x92:
-	case 0xB2:
-	case 0xD2:
-	case 0xF2: {
-		int bit = 1 << (opcode >> 5);
-		int mask = ~bit;
-		if ( opcode & 0x10 )
-			bit = 0;
-		data += dp;
-		WRITE( 0, data, (READ( -1, data ) & mask) | bit );
-		goto inc_pc_loop;
-	}
-		
-	case 0x0E: // TSET1 abs
-	case 0x4E: // TCLR1 abs
-		data = READ_PC16( pc );
-		pc += 2;
-		{
-			unsigned temp = READ( -2, data );
-			nz = (uint8_t) (a - temp);
-			temp &= ~a;
-			if ( opcode == 0x0E )
-				temp |= a;
-			WRITE( 0, data, temp );
-		}
-		goto loop;
-	
-	case 0x4A: // AND1 C,mem.bit
-		c &= MEM_BIT( 0 );
-		pc += 2;
-		goto loop;
-	
-	case 0x6A: // AND1 C,/mem.bit
-		c &= ~MEM_BIT( 0 );
-		pc += 2;
-		goto loop;
-	
-	case 0x0A: // OR1 C,mem.bit
-		c |= MEM_BIT( -1 );
-		pc += 2;
-		goto loop;
-	
-	case 0x2A: // OR1 C,/mem.bit
-		c |= ~MEM_BIT( -1 );
-		pc += 2;
-		goto loop;
-	
-	case 0x8A: // EOR1 C,mem.bit
-		c ^= MEM_BIT( -1 );
-		pc += 2;
-		goto loop;
-	
-	case 0xEA: // NOT1 mem.bit
-		data = READ_PC16( pc );
-		pc += 2;
-		{
-			unsigned temp = READ( -1, data & 0x1FFF );
-			temp ^= 1 << (data >> 13);
-			WRITE( 0, data & 0x1FFF, temp );
-		}
-		goto loop;
-	
-	case 0xCA: // MOV1 mem.bit,C
-		data = READ_PC16( pc );
-		pc += 2;
-		{
-			unsigned temp = READ( -2, data & 0x1FFF );
-			unsigned bit = data >> 13;
-			temp = (temp & ~(1 << bit)) | ((c >> 8 & 1) << bit);
-			WRITE( 0, data & 0x1FFF, temp + no_read_before_write  );
-		}
-		goto loop;
-	
-	case 0xAA: // MOV1 C,mem.bit
-		c = MEM_BIT( 0 );
-		pc += 2;
-		goto loop;
-	
-// 16. PROGRAM PSW FLAG OPERATION COMMANDS
-
-	case 0x60: // CLRC
-		c = 0;
-		goto loop;
-		
-	case 0x80: // SETC
-		c = ~0;
-		goto loop;
-	
-	case 0xED: // NOTC
-		c ^= 0x100;
-		goto loop;
-		
-	case 0xE0: // CLRV
-		psw &= ~(v40 | h08);
-		goto loop;
-	
-	case 0x20: // CLRP
-		dp = 0;
-		goto loop;
-	
-	case 0x40: // SETP
-		dp = 0x100;
-		goto loop;
-	
-	case 0xA0: // EI
-		SUSPICIOUS_OPCODE( "EI" );
-		psw |= i04;
-		goto loop;
-	
-	case 0xC0: // DI
-		SUSPICIOUS_OPCODE( "DI" );
-		psw &= ~i04;
-		goto loop;
-	
-// 17. OTHER COMMANDS
-
-	case 0x00: // NOP
-		goto loop;
-	
-	case 0xFF:{// STOP
-		// handle PC wrap-around
-		unsigned addr = GET_PC() - 1;
-		if ( addr >= 0x10000 )
-		{
-			addr &= 0xFFFF;
-			SET_PC( addr );
-			dprintf( "SPC: PC wrapped around\n" );
-			goto loop;
-		}
-	}
-	// fall through
-	case 0xEF: // SLEEP
-		SUSPICIOUS_OPCODE( "STOP/SLEEP" );
-		--pc;
-		rel_time = 0;
-		m.cpu_error = "SPC emulation error";
-		goto stop;
-	} // switch
-	
-	assert( 0 ); // catch any unhandled instructions
-}   
-out_of_time:
-	rel_time -= m.cycle_table [*pc]; // undo partial execution of opcode
-stop:
-	
-	// Uncache registers
-	if ( GET_PC() >= 0x10000 )
-		dprintf( "SPC: PC wrapped around\n" );
-	m.cpu_regs.pc = (uint16_t) GET_PC();
-	m.cpu_regs.sp = ( uint8_t) GET_SP();
-	m.cpu_regs.a  = ( uint8_t) a;
-	m.cpu_regs.x  = ( uint8_t) x;
-	m.cpu_regs.y  = ( uint8_t) y;
-	{
-		int temp;
-		GET_PSW( temp );
-		m.cpu_regs.psw = (uint8_t) temp;
+		GET_PSW(temp);
+		m.cpu_regs.psw = static_cast<uint8_t>(temp);
 	}
 }
 SPC_CPU_RUN_FUNC_END

--- a/src/in_snsf/snes9x/apu/SPC_DSP.cpp
+++ b/src/in_snsf/snes9x/apu/SPC_DSP.cpp
@@ -1,9 +1,10 @@
 // snes_spc 0.9.0. http://www.slack.net/~ant/
 
+#include <algorithm>
+#include <cstring>
 #include "SPC_DSP.h"
 
 #include "blargg_endian.h"
-#include <string.h>
 
 /* Copyright (C) 2007 Shay Green. This module is free software; you
 can redistribute it and/or modify it under the terms of the GNU Lesser
@@ -16,73 +17,40 @@
 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
+#if INT_MAX < 0x7FFFFFFF
+# error "Requires that int type have at least 32 bits"
 #endif
 
-#if INT_MAX < 0x7FFFFFFF
-	#error "Requires that int type have at least 32 bits"
-#endif
-
-// TODO: add to blargg_endian.h
-#define GET_LE16SA( addr )      ((BOOST::int16_t) GET_LE16( addr ))
-#define GET_LE16A( addr )       GET_LE16( addr )
-#define SET_LE16A( addr, data ) SET_LE16( addr, data )
-
-static BOOST::uint8_t const initial_regs [SPC_DSP::register_count] =
-{
-	0x45,0x8B,0x5A,0x9A,0xE4,0x82,0x1B,0x78,0x00,0x00,0xAA,0x96,0x89,0x0E,0xE0,0x80,
-	0x2A,0x49,0x3D,0xBA,0x14,0xA0,0xAC,0xC5,0x00,0x00,0x51,0xBB,0x9C,0x4E,0x7B,0xFF,
-	0xF4,0xFD,0x57,0x32,0x37,0xD9,0x42,0x22,0x00,0x00,0x5B,0x3C,0x9F,0x1B,0x87,0x9A,
-	0x6F,0x27,0xAF,0x7B,0xE5,0x68,0x0A,0xD9,0x00,0x00,0x9A,0xC5,0x9C,0x4E,0x7B,0xFF,
-	0xEA,0x21,0x78,0x4F,0xDD,0xED,0x24,0x14,0x00,0x00,0x77,0xB1,0xD1,0x36,0xC1,0x67,
-	0x52,0x57,0x46,0x3D,0x59,0xF4,0x87,0xA4,0x00,0x00,0x7E,0x44,0x00,0x4E,0x7B,0xFF,
-	0x75,0xF5,0x06,0x97,0x10,0xC3,0x24,0xBB,0x00,0x00,0x7B,0x7A,0xE0,0x60,0x12,0x0F,
-	0xF7,0x74,0x1C,0xE5,0x39,0x3D,0x73,0xC1,0x00,0x00,0x7A,0xB3,0xFF,0x4E,0x7B,0xFF
+static const uint8_t initial_regs[] =
+{
+	0x45, 0x8B, 0x5A, 0x9A, 0xE4, 0x82, 0x1B, 0x78, 0x00, 0x00, 0xAA, 0x96, 0x89, 0x0E, 0xE0, 0x80,
+	0x2A, 0x49, 0x3D, 0xBA, 0x14, 0xA0, 0xAC, 0xC5, 0x00, 0x00, 0x51, 0xBB, 0x9C, 0x4E, 0x7B, 0xFF,
+	0xF4, 0xFD, 0x57, 0x32, 0x37, 0xD9, 0x42, 0x22, 0x00, 0x00, 0x5B, 0x3C, 0x9F, 0x1B, 0x87, 0x9A,
+	0x6F, 0x27, 0xAF, 0x7B, 0xE5, 0x68, 0x0A, 0xD9, 0x00, 0x00, 0x9A, 0xC5, 0x9C, 0x4E, 0x7B, 0xFF,
+	0xEA, 0x21, 0x78, 0x4F, 0xDD, 0xED, 0x24, 0x14, 0x00, 0x00, 0x77, 0xB1, 0xD1, 0x36, 0xC1, 0x67,
+	0x52, 0x57, 0x46, 0x3D, 0x59, 0xF4, 0x87, 0xA4, 0x00, 0x00, 0x7E, 0x44, 0x00, 0x4E, 0x7B, 0xFF,
+	0x75, 0xF5, 0x06, 0x97, 0x10, 0xC3, 0x24, 0xBB, 0x00, 0x00, 0x7B, 0x7A, 0xE0, 0x60, 0x12, 0x0F,
+	0xF7, 0x74, 0x1C, 0xE5, 0x39, 0x3D, 0x73, 0xC1, 0x00, 0x00, 0x7A, 0xB3, 0xFF, 0x4E, 0x7B, 0xFF
 };
 
 // if ( io < -32768 ) io = -32768;
 // if ( io >  32767 ) io =  32767;
-#define CLAMP16( io )\
-{\
-	if ( (int16_t) io != io )\
-		io = (io >> 31) ^ 0x7FFF;\
-}
-
-// Access global DSP register
-#define REG(n)      m.regs [r_##n]
-
-// Access voice DSP register
-#define VREG(r,n)   r [v_##n]
-
-#define WRITE_SAMPLES( l, r, out ) \
-{\
-	out [0] = l;\
-	out [1] = r;\
-	out += 2;\
-	if ( out >= m.out_end )\
-	{\
-		check( out == m.out_end );\
-		check( m.out_end != &m.extra [extra_size] || \
-			(m.extra <= m.out_begin && m.extra < &m.extra [extra_size]) );\
-		out       = m.extra;\
-		m.out_end = &m.extra [extra_size];\
-	}\
-}\
-
-void SPC_DSP::set_output( sample_t* out, int size )
-{
-	require( (size & 1) == 0 ); // must be even
-	if ( !out )
-	{
-		out  = m.extra;
+template<typename T> static inline void CLAMP16(T &io)
+{
+	if (static_cast<int16_t>(io) != io)
+		io = (io >> 31) ^ 0x7FFF;
+}
+
+void SPC_DSP::set_output(sample_t *out, int size)
+{
+	assert(!(size & 1)); // must be even
+	if (!out)
+	{
+		out = this->m.extra;
 		size = extra_size;
 	}
-	m.out_begin = out;
-	m.out       = out;
-	m.out_end   = out + size;
+	this->m.out_begin = this->m.out = out;
+	this->m.out_end = out + size;
 }
 
 // Volume registers and efb are signed! Easy to forget int8_t cast.
@@ -90,87 +58,85 @@
 
 // Gaussian interpolation
 
-static short const gauss [512] =
-{
-   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
-   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   2,   2,   2,   2,   2,
-   2,   2,   3,   3,   3,   3,   3,   4,   4,   4,   4,   4,   5,   5,   5,   5,
-   6,   6,   6,   6,   7,   7,   7,   8,   8,   8,   9,   9,   9,  10,  10,  10,
-  11,  11,  11,  12,  12,  13,  13,  14,  14,  15,  15,  15,  16,  16,  17,  17,
-  18,  19,  19,  20,  20,  21,  21,  22,  23,  23,  24,  24,  25,  26,  27,  27,
-  28,  29,  29,  30,  31,  32,  32,  33,  34,  35,  36,  36,  37,  38,  39,  40,
-  41,  42,  43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,
-  58,  59,  60,  61,  62,  64,  65,  66,  67,  69,  70,  71,  73,  74,  76,  77,
-  78,  80,  81,  83,  84,  86,  87,  89,  90,  92,  94,  95,  97,  99, 100, 102,
- 104, 106, 107, 109, 111, 113, 115, 117, 118, 120, 122, 124, 126, 128, 130, 132,
- 134, 137, 139, 141, 143, 145, 147, 150, 152, 154, 156, 159, 161, 163, 166, 168,
- 171, 173, 175, 178, 180, 183, 186, 188, 191, 193, 196, 199, 201, 204, 207, 210,
- 212, 215, 218, 221, 224, 227, 230, 233, 236, 239, 242, 245, 248, 251, 254, 257,
- 260, 263, 267, 270, 273, 276, 280, 283, 286, 290, 293, 297, 300, 304, 307, 311,
- 314, 318, 321, 325, 328, 332, 336, 339, 343, 347, 351, 354, 358, 362, 366, 370,
- 374, 378, 381, 385, 389, 393, 397, 401, 405, 410, 414, 418, 422, 426, 430, 434,
- 439, 443, 447, 451, 456, 460, 464, 469, 473, 477, 482, 486, 491, 495, 499, 504,
- 508, 513, 517, 522, 527, 531, 536, 540, 545, 550, 554, 559, 563, 568, 573, 577,
- 582, 587, 592, 596, 601, 606, 611, 615, 620, 625, 630, 635, 640, 644, 649, 654,
- 659, 664, 669, 674, 678, 683, 688, 693, 698, 703, 708, 713, 718, 723, 728, 732,
- 737, 742, 747, 752, 757, 762, 767, 772, 777, 782, 787, 792, 797, 802, 806, 811,
- 816, 821, 826, 831, 836, 841, 846, 851, 855, 860, 865, 870, 875, 880, 884, 889,
- 894, 899, 904, 908, 913, 918, 923, 927, 932, 937, 941, 946, 951, 955, 960, 965,
- 969, 974, 978, 983, 988, 992, 997,1001,1005,1010,1014,1019,1023,1027,1032,1036,
-1040,1045,1049,1053,1057,1061,1066,1070,1074,1078,1082,1086,1090,1094,1098,1102,
-1106,1109,1113,1117,1121,1125,1128,1132,1136,1139,1143,1146,1150,1153,1157,1160,
-1164,1167,1170,1174,1177,1180,1183,1186,1190,1193,1196,1199,1202,1205,1207,1210,
-1213,1216,1219,1221,1224,1227,1229,1232,1234,1237,1239,1241,1244,1246,1248,1251,
-1253,1255,1257,1259,1261,1263,1265,1267,1269,1270,1272,1274,1275,1277,1279,1280,
-1282,1283,1284,1286,1287,1288,1290,1291,1292,1293,1294,1295,1296,1297,1297,1298,
-1299,1300,1300,1301,1302,1302,1303,1303,1303,1304,1304,1304,1304,1304,1305,1305,
+static const short gauss[] =
+{
+	   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
+	   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   1,   2,   2,   2,   2,   2,
+	   2,   2,   3,   3,   3,   3,   3,   4,   4,   4,   4,   4,   5,   5,   5,   5,
+	   6,   6,   6,   6,   7,   7,   7,   8,   8,   8,   9,   9,   9,  10,  10,  10,
+	  11,  11,  11,  12,  12,  13,  13,  14,  14,  15,  15,  15,  16,  16,  17,  17,
+	  18,  19,  19,  20,  20,  21,  21,  22,  23,  23,  24,  24,  25,  26,  27,  27,
+	  28,  29,  29,  30,  31,  32,  32,  33,  34,  35,  36,  36,  37,  38,  39,  40,
+	  41,  42,  43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,
+	  58,  59,  60,  61,  62,  64,  65,  66,  67,  69,  70,  71,  73,  74,  76,  77,
+	  78,  80,  81,  83,  84,  86,  87,  89,  90,  92,  94,  95,  97,  99, 100, 102,
+	 104, 106, 107, 109, 111, 113, 115, 117, 118, 120, 122, 124, 126, 128, 130, 132,
+	 134, 137, 139, 141, 143, 145, 147, 150, 152, 154, 156, 159, 161, 163, 166, 168,
+	 171, 173, 175, 178, 180, 183, 186, 188, 191, 193, 196, 199, 201, 204, 207, 210,
+	 212, 215, 218, 221, 224, 227, 230, 233, 236, 239, 242, 245, 248, 251, 254, 257,
+	 260, 263, 267, 270, 273, 276, 280, 283, 286, 290, 293, 297, 300, 304, 307, 311,
+	 314, 318, 321, 325, 328, 332, 336, 339, 343, 347, 351, 354, 358, 362, 366, 370,
+	 374, 378, 381, 385, 389, 393, 397, 401, 405, 410, 414, 418, 422, 426, 430, 434,
+	 439, 443, 447, 451, 456, 460, 464, 469, 473, 477, 482, 486, 491, 495, 499, 504,
+	 508, 513, 517, 522, 527, 531, 536, 540, 545, 550, 554, 559, 563, 568, 573, 577,
+	 582, 587, 592, 596, 601, 606, 611, 615, 620, 625, 630, 635, 640, 644, 649, 654,
+	 659, 664, 669, 674, 678, 683, 688, 693, 698, 703, 708, 713, 718, 723, 728, 732,
+	 737, 742, 747, 752, 757, 762, 767, 772, 777, 782, 787, 792, 797, 802, 806, 811,
+	 816, 821, 826, 831, 836, 841, 846, 851, 855, 860, 865, 870, 875, 880, 884, 889,
+	 894, 899, 904, 908, 913, 918, 923, 927, 932, 937, 941, 946, 951, 955, 960, 965,
+	 969, 974, 978, 983, 988, 992, 997,1001,1005,1010,1014,1019,1023,1027,1032,1036,
+	1040,1045,1049,1053,1057,1061,1066,1070,1074,1078,1082,1086,1090,1094,1098,1102,
+	1106,1109,1113,1117,1121,1125,1128,1132,1136,1139,1143,1146,1150,1153,1157,1160,
+	1164,1167,1170,1174,1177,1180,1183,1186,1190,1193,1196,1199,1202,1205,1207,1210,
+	1213,1216,1219,1221,1224,1227,1229,1232,1234,1237,1239,1241,1244,1246,1248,1251,
+	1253,1255,1257,1259,1261,1263,1265,1267,1269,1270,1272,1274,1275,1277,1279,1280,
+	1282,1283,1284,1286,1287,1288,1290,1291,1292,1293,1294,1295,1296,1297,1297,1298,
+	1299,1300,1300,1301,1302,1302,1303,1303,1303,1304,1304,1304,1304,1304,1305,1305,
 };
 
-inline int SPC_DSP::interpolate( voice_t const* v )
+int SPC_DSP::interpolate(const voice_t *v)
 {
 	// Make pointers into gaussian based on fractional position between samples
-	int offset = v->interp_pos >> 4 & 0xFF;
-	short const* fwd = gauss + 255 - offset;
-	short const* rev = gauss       + offset; // mirror left half of gaussian
-	
-	int const* in = &v->buf [(v->interp_pos >> 12) + v->buf_pos];
-	int out;
-	out  = (fwd [  0] * in [0]) >> 11;
-	out += (fwd [256] * in [1]) >> 11;
-	out += (rev [256] * in [2]) >> 11;
-	out = (int16_t) out;
-	out += (rev [  0] * in [3]) >> 11;
-	
-	CLAMP16( out );
+	int offset = (v->interp_pos >> 4) & 0xFF;
+	auto fwd = gauss + 255 - offset;
+	auto rev = gauss + offset; // mirror left half of gaussian
+
+	auto in = &v->buf[(v->interp_pos >> 12) + v->buf_pos];
+	int out = (fwd[0] * in[0]) >> 11;
+	out += (fwd[256] * in[1]) >> 11;
+	out += (rev[256] * in[2]) >> 11;
+	out = static_cast<int16_t>(out);
+	out += (rev[0] * in[3]) >> 11;
+
+	CLAMP16(out);
 	out &= ~1;
 	return out;
 }
 
-
 //// Counters
 
-int const simple_counter_range = 2048 * 5 * 3; // 30720
-
-static unsigned const counter_rates [32] =
-{
-   simple_counter_range + 1, // never fires
-          2048, 1536,
-	1280, 1024,  768,
-	 640,  512,  384,
-	 320,  256,  192,
-	 160,  128,   96,
-	  80,   64,   48,
-	  40,   32,   24,
-	  20,   16,   12,
-	  10,    8,    6,
-	   5,    4,    3,
-	         2,
+static const int simple_counter_range = 2048 * 5 * 3; // 30720
+
+static const unsigned counter_rates[] =
+{
+	simple_counter_range + 1, // never fires
+	2048, 1536,
+	1280, 1024, 768,
+	640, 512, 384,
+	320, 256, 192,
+	160, 128, 96,
+	80, 64, 48,
+	40, 32, 24,
+	20, 16, 12,
+	10, 8, 6,
+	5, 4, 3,
+	2,
 	         1
 };
 
-static unsigned const counter_offsets [32] =
-{
-	  1, 0, 1040,
+static const unsigned counter_offsets[] =
+{
+	1, 0, 1040,
 	536, 0, 1040,
 	536, 0, 1040,
 	536, 0, 1040,
@@ -180,64 +146,62 @@
 	536, 0, 1040,
 	536, 0, 1040,
 	536, 0, 1040,
-	     0,
+	0,
 	     0
 };
 
-inline void SPC_DSP::init_counter()
-{
-	m.counter = 0;
-}
-
-inline void SPC_DSP::run_counters()
-{
-	if ( --m.counter < 0 )
-		m.counter = simple_counter_range - 1;
-}
-
-inline unsigned SPC_DSP::read_counter( int rate )
-{
-	return ((unsigned) m.counter + counter_offsets [rate]) % counter_rates [rate];
-}
-
+void SPC_DSP::init_counter()
+{
+	this->m.counter = 0;
+}
+
+void SPC_DSP::run_counters()
+{
+	if (--this->m.counter < 0)
+		this->m.counter = simple_counter_range - 1;
+}
+
+unsigned SPC_DSP::read_counter(int rate)
+{
+	return (static_cast<unsigned>(this->m.counter) + counter_offsets[rate]) % counter_rates[rate];
+}
 
 //// Envelope
 
-inline void SPC_DSP::run_envelope( voice_t* const v )
+void SPC_DSP::run_envelope(voice_t *const v)
 {
 	int env = v->env;
-	if ( v->env_mode == env_release ) // 60%
-	{
-		if ( (env -= 0x8) < 0 )
+	if (v->env_mode == env_release) // 60%
+	{
+		if ((env -= 0x8) < 0)
 			env = 0;
 		v->env = env;
 	}
 	else
 	{
 		int rate;
-		int env_data = VREG(v->regs,adsr1);
-		if ( m.t_adsr0 & 0x80 ) // 99% ADSR
+		int env_data = v->regs[v_adsr1];
+		if (this->m.t_adsr0 & 0x80) // 99% ADSR
 		{
-			if ( v->env_mode >= env_decay ) // 99%
+			if (v->env_mode >= env_decay) // 99%
 			{
-				env--;
+				--env;
 				env -= env >> 8;
 				rate = env_data & 0x1F;
-				if ( v->env_mode == env_decay ) // 1%
-					rate = (m.t_adsr0 >> 3 & 0x0E) + 0x10;
+				if (v->env_mode == env_decay) // 1%
+					rate = ((this->m.t_adsr0 >> 3) & 0x0E) + 0x10;
 			}
 			else // env_attack
 			{
-				rate = (m.t_adsr0 & 0x0F) * 2 + 1;
+				rate = (this->m.t_adsr0 & 0x0F) * 2 + 1;
 				env += rate < 31 ? 0x20 : 0x400;
 			}
 		}
 		else // GAIN
 		{
-			int mode;
-			env_data = VREG(v->regs,gain);
-			mode = env_data >> 5;
-			if ( mode < 4 ) // direct
+			env_data = v->regs[v_gain];
+			int mode = env_data >> 5;
+			if (mode < 4) // direct
 			{
 				env = env_data * 0x10;
 				rate = 31;
@@ -245,80 +209,77 @@
 			else
 			{
 				rate = env_data & 0x1F;
-				if ( mode == 4 ) // 4: linear decrease
+				if (mode == 4) // 4: linear decrease
+					env -= 0x20;
+				else if (mode < 6) // 5: exponential decrease
 				{
-					env -= 0x20;
-				}
-				else if ( mode < 6 ) // 5: exponential decrease
-				{
-					env--;
+					--env;
 					env -= env >> 8;
 				}
 				else // 6,7: linear increase
 				{
 					env += 0x20;
-					if ( mode > 6 && (unsigned) v->hidden_env >= 0x600 )
+					if (mode > 6 && static_cast<unsigned>(v->hidden_env) >= 0x600)
 						env += 0x8 - 0x20; // 7: two-slope linear increase
 				}
 			}
 		}
-		
+
 		// Sustain level
-		if ( (env >> 8) == (env_data >> 5) && v->env_mode == env_decay )
+		if ((env >> 8) == (env_data >> 5) && v->env_mode == env_decay)
 			v->env_mode = env_sustain;
-		
+
 		v->hidden_env = env;
-		
+
 		// unsigned cast because linear decrease going negative also triggers this
-		if ( (unsigned) env > 0x7FF )
+		if (static_cast<unsigned>(env) > 0x7FF)
 		{
-			env = (env < 0 ? 0 : 0x7FF);
-			if ( v->env_mode == env_attack )
+			env = env < 0 ? 0 : 0x7FF;
+			if (v->env_mode == env_attack)
 				v->env_mode = env_decay;
 		}
 		
-		if ( !read_counter( rate ) )
+		if (!this->read_counter(rate))
 			v->env = env; // nothing else is controlled by the counter
 	}
 }
 
-
 //// BRR Decoding
 
-inline void SPC_DSP::decode_brr( voice_t* v )
+void SPC_DSP::decode_brr(voice_t *v)
 {
 	// Arrange the four input nybbles in 0xABCD order for easy decoding
-	int nybbles = m.t_brr_byte * 0x100 + m.ram [(v->brr_addr + v->brr_offset + 1) & 0xFFFF];
-	
-	int const header = m.t_brr_header;
-	
+	int nybbles = this->m.t_brr_byte * 0x100 + this->m.ram[(v->brr_addr + v->brr_offset + 1) & 0xFFFF];
+
+	int header = this->m.t_brr_header;
+
 	// Write to next four samples in circular buffer
-	int* pos = &v->buf [v->buf_pos];
-	int* end;
-	if ( (v->buf_pos += 4) >= brr_buf_size )
+	int *pos = &v->buf[v->buf_pos];
+	int *end;
+	if ((v->buf_pos += 4) >= brr_buf_size)
 		v->buf_pos = 0;
-	
+
 	// Decode four samples
-	for ( end = pos + 4; pos < end; pos++, nybbles <<= 4 )
+	for (end = pos + 4; pos < end; ++pos, nybbles <<= 4)
 	{
 		// Extract nybble and sign-extend
-		int s = (int16_t) nybbles >> 12;
-		
+		int s = static_cast<int16_t>(nybbles) >> 12;
+
 		// Shift sample based on header
-		int const shift = header >> 4;
+		int shift = header >> 4;
 		s = (s << shift) >> 1;
-		if ( shift >= 0xD ) // handle invalid range
+		if (shift >= 0xD) // handle invalid range
 			s = (s >> 25) << 11; // same as: s = (s < 0 ? -0x800 : 0)
-		
+
 		// Apply IIR filter (8 is the most commonly used)
-		int const filter = header & 0x0C;
-		int const p1 = pos [brr_buf_size - 1];
-		int const p2 = pos [brr_buf_size - 2] >> 1;
-		if ( filter >= 8 )
+		int filter = header & 0x0C;
+		int p1 = pos[brr_buf_size - 1];
+		int p2 = pos[brr_buf_size - 2] >> 1;
+		if (filter >= 8)
 		{
 			s += p1;
 			s -= p2;
-			if ( filter == 8 ) // s += p1 * 0.953125 - p2 * 0.46875
+			if (filter == 8) // s += p1 * 0.953125 - p2 * 0.46875
 			{
 				s += p2 >> 4;
 				s += (p1 * -3) >> 6;
@@ -329,429 +290,402 @@
 				s += (p2 * 3) >> 4;
 			}
 		}
-		else if ( filter ) // s += p1 * 0.46875
+		else if (filter) // s += p1 * 0.46875
 		{
 			s += p1 >> 1;
-			s += (-p1) >> 5;
+			s += -p1 >> 5;
 		}
-		
+
 		// Adjust and write sample
-		CLAMP16( s );
-		s = (int16_t) (s * 2);
-		pos [brr_buf_size] = pos [0] = s; // second copy simplifies wrap-around
-	}
-}
-
+		CLAMP16(s);
+		s = static_cast<int16_t>(s * 2);
+		pos[brr_buf_size] = pos[0] = s; // second copy simplifies wrap-around
+	}
+}
 
 //// Misc
 
-#define MISC_CLOCK( n ) inline void SPC_DSP::misc_##n()
-
-MISC_CLOCK( 27 )
-{
-	m.t_pmon = REG(pmon) & 0xFE; // voice 0 doesn't support PMON
-}
-MISC_CLOCK( 28 )
-{
-	m.t_non = REG(non);
-	m.t_eon = REG(eon);
-	m.t_dir = REG(dir);
-}
-MISC_CLOCK( 29 )
-{
-	if ( (m.every_other_sample ^= 1) != 0 )
-		m.new_kon &= ~m.kon; // clears KON 63 clocks after it was last read
-}
-MISC_CLOCK( 30 )
-{
-	if ( m.every_other_sample )
-	{
-		m.kon    = m.new_kon;
-		m.t_koff = REG(koff) | m.mute_mask; 
-	}
-	
-	run_counters();
-	
+void SPC_DSP::misc_27()
+{
+	this->m.t_pmon = this->m.regs[r_pmon] & 0xFE; // voice 0 doesn't support PMON
+}
+void SPC_DSP::misc_28()
+{
+	this->m.t_non = this->m.regs[r_non];
+	this->m.t_eon = this->m.regs[r_eon];
+	this->m.t_dir = this->m.regs[r_dir];
+}
+void SPC_DSP::misc_29()
+{
+	if ((this->m.every_other_sample = !this->m.every_other_sample))
+		this->m.new_kon &= ~this->m.kon; // clears KON 63 clocks after it was last read
+}
+void SPC_DSP::misc_30()
+{
+	if (this->m.every_other_sample)
+	{
+		this->m.kon = this->m.new_kon;
+		this->m.t_koff = this->m.regs[r_koff] | this->m.mute_mask; 
+	}
+
+	this->run_counters();
+
 	// Noise
-	if ( !read_counter( REG(flg) & 0x1F ) )
-	{
-		int feedback = (m.noise << 13) ^ (m.noise << 14);
-		m.noise = (feedback & 0x4000) ^ (m.noise >> 1);
-	}
-}
-
+	if (!this->read_counter(this->m.regs[r_flg] & 0x1F))
+	{
+		int feedback = (this->m.noise << 13) ^ (this->m.noise << 14);
+		this->m.noise = (feedback & 0x4000) ^ (this->m.noise >> 1);
+	}
+}
 
 //// Voices
 
-#define VOICE_CLOCK( n ) void SPC_DSP::voice_##n( voice_t* const v )
-
-inline VOICE_CLOCK( V1 )
-{
-	m.t_dir_addr = m.t_dir * 0x100 + m.t_srcn * 4;
-	m.t_srcn = VREG(v->regs,srcn);
-}
-inline VOICE_CLOCK( V2 )
+void SPC_DSP::voice_V1(voice_t *const v)
+{
+	this->m.t_dir_addr = this->m.t_dir * 0x100 + this->m.t_srcn * 4;
+	this->m.t_srcn = v->regs[v_srcn];
+}
+void SPC_DSP::voice_V2(voice_t *const v)
 {
 	// Read sample pointer (ignored if not needed)
-	uint8_t const* entry = &m.ram [m.t_dir_addr];
-	if ( !v->kon_delay )
+	auto entry = &this->m.ram[m.t_dir_addr];
+	if (!v->kon_delay)
 		entry += 2;
-	m.t_brr_next_addr = GET_LE16A( entry );
-	
-	m.t_adsr0 = VREG(v->regs,adsr0);
-	
+	this->m.t_brr_next_addr = get_le16(entry);
+
+	this->m.t_adsr0 = v->regs[v_adsr0];
+
 	// Read pitch, spread over two clocks
-	m.t_pitch = VREG(v->regs,pitchl);
-}
-inline VOICE_CLOCK( V3a )
-{
-	m.t_pitch += (VREG(v->regs,pitchh) & 0x3F) << 8;
-}
-inline VOICE_CLOCK( V3b )
+	this->m.t_pitch = v->regs[v_pitchl];
+}
+void SPC_DSP::voice_V3a(voice_t *const v)
+{
+	this->m.t_pitch += (v->regs[v_pitchh] & 0x3F) << 8;
+}
+void SPC_DSP::voice_V3b(voice_t *const v)
 {
 	// Read BRR header and byte
-	m.t_brr_byte   = m.ram [(v->brr_addr + v->brr_offset) & 0xFFFF];
-	m.t_brr_header = m.ram [v->brr_addr]; // brr_addr doesn't need masking
-}
-VOICE_CLOCK( V3c )
+	this->m.t_brr_byte = this->m.ram[(v->brr_addr + v->brr_offset) & 0xFFFF];
+	this->m.t_brr_header = this->m.ram[v->brr_addr]; // brr_addr doesn't need masking
+}
+void SPC_DSP::voice_V3c(voice_t *const v)
 {
 	// Pitch modulation using previous voice's output
-	if ( m.t_pmon & v->vbit )
-		m.t_pitch += ((m.t_output >> 5) * m.t_pitch) >> 10;
-	
-	if ( v->kon_delay )
+	if (this->m.t_pmon & v->vbit)
+		this->m.t_pitch += ((this->m.t_output >> 5) * this->m.t_pitch) >> 10;
+
+	if (v->kon_delay)
 	{
 		// Get ready to start BRR decoding on next sample
-		if ( v->kon_delay == 5 )
+		if (v->kon_delay == 5)
 		{
-			v->brr_addr    = m.t_brr_next_addr;
-			v->brr_offset  = 1;
-			v->buf_pos     = 0;
-			m.t_brr_header = 0; // header is ignored on this sample
-			m.kon_check    = true;
-
-			if (take_spc_snapshot)
-			{
-				take_spc_snapshot = 0;
-				if (spc_snapshot_callback)
-					spc_snapshot_callback();
-			}
+			v->brr_addr = this->m.t_brr_next_addr;
+			v->brr_offset = 1;
+			v->buf_pos = 0;
+			this->m.t_brr_header = 0; // header is ignored on this sample
 		}
-		
+
 		// Envelope is never run during KON
-		v->env        = 0;
+		v->env = 0;
 		v->hidden_env = 0;
-		
+
 		// Disable BRR decoding until last three samples
 		v->interp_pos = 0;
-		if ( --v->kon_delay & 3 )
+		if (--v->kon_delay & 3)
 			v->interp_pos = 0x4000;
-		
+
 		// Pitch is never added during KON
-		m.t_pitch = 0;
-	}
-	
+		this->m.t_pitch = 0;
+	}
+
 	// Gaussian interpolation
-	{
-		int output = interpolate( v );
-		
-		// Noise
-		if ( m.t_non & v->vbit )
-			output = (int16_t) (m.noise * 2);
-		
-		// Apply envelope
-		m.t_output = (output * v->env) >> 11 & ~1;
-		v->t_envx_out = (uint8_t) (v->env >> 4);
-	}
-	
+	int output = this->interpolate(v);
+
+	// Noise
+	if (this->m.t_non & v->vbit)
+		output = static_cast<int16_t>(this->m.noise * 2);
+
+	// Apply envelope
+	this->m.t_output = (output * v->env) >> 11 & ~1;
+	v->t_envx_out = static_cast<uint8_t>(v->env >> 4);
+
 	// Immediate silence due to end of sample or soft reset
-	if ( REG(flg) & 0x80 || (m.t_brr_header & 3) == 1 )
+	if (this->m.regs[r_flg] & 0x80 || (this->m.t_brr_header & 3) == 1)
 	{
 		v->env_mode = env_release;
-		v->env      = 0;
-	}
-	
-	if ( m.every_other_sample )
+		v->env = 0;
+	}
+
+	if (this->m.every_other_sample)
 	{
 		// KOFF
-		if ( m.t_koff & v->vbit )
+		if (this->m.t_koff & v->vbit)
 			v->env_mode = env_release;
-		
+
 		// KON
-		if ( m.kon & v->vbit )
+		if (this->m.kon & v->vbit)
 		{
 			v->kon_delay = 5;
 			v->env_mode  = env_attack;
 		}
 	}
-	
+
 	// Run envelope for next sample
-	if ( !v->kon_delay )
-		run_envelope( v );
-}
-
-inline void SPC_DSP::voice_output( voice_t const* v, int ch )
+	if (!v->kon_delay)
+		this->run_envelope(v);
+}
+
+void SPC_DSP::voice_output(const voice_t *v, int ch)
 {
 	// Apply left/right volume
-	int amp = (m.t_output * (int8_t) VREG(v->regs,voll + ch)) >> 7;
-	amp *= ((stereo_switch & (1 << (v->voice_number + ch * voice_count))) ? 1 : 0);
+	int amp = (this->m.t_output * static_cast<int8_t>(v->regs[v_voll + ch])) >> 7;
+	amp *= (this->stereo_switch & (1 << (v->voice_number + ch * voice_count))) ? 1 : 0;
 
 	// Add to output total
-	m.t_main_out [ch] += amp;
-	CLAMP16( m.t_main_out [ch] );
-	
+	this->m.t_main_out[ch] += amp;
+	CLAMP16(this->m.t_main_out[ch]);
+
 	// Optionally add to echo total
-	if ( m.t_eon & v->vbit )
-	{
-		m.t_echo_out [ch] += amp;
-		CLAMP16( m.t_echo_out [ch] );
-	}
-}
-VOICE_CLOCK( V4 )
+	if (this->m.t_eon & v->vbit)
+	{
+		this->m.t_echo_out[ch] += amp;
+		CLAMP16(this->m.t_echo_out[ch]);
+	}
+}
+void SPC_DSP::voice_V4(voice_t *const v)
 {
 	// Decode BRR
-	m.t_looped = 0;
-	if ( v->interp_pos >= 0x4000 )
-	{
-		decode_brr( v );
-		
-		if ( (v->brr_offset += 2) >= brr_block_size )
+	this->m.t_looped = 0;
+	if (v->interp_pos >= 0x4000)
+	{
+		this->decode_brr(v);
+
+		if ((v->brr_offset += 2) >= brr_block_size)
 		{
 			// Start decoding next BRR block
-			assert( v->brr_offset == brr_block_size );
+			assert(v->brr_offset == brr_block_size);
 			v->brr_addr = (v->brr_addr + brr_block_size) & 0xFFFF;
-			if ( m.t_brr_header & 1 )
+			if (this->m.t_brr_header & 1)
 			{
-				v->brr_addr = m.t_brr_next_addr;
-				m.t_looped = v->vbit;
+				v->brr_addr = this->m.t_brr_next_addr;
+				this->m.t_looped = v->vbit;
 			}
 			v->brr_offset = 1;
 		}
 	}
-	
+
 	// Apply pitch
 	v->interp_pos = (v->interp_pos & 0x3FFF) + m.t_pitch;
-	
+
 	// Keep from getting too far ahead (when using pitch modulation)
-	if ( v->interp_pos > 0x7FFF )
+	if (v->interp_pos > 0x7FFF)
 		v->interp_pos = 0x7FFF;
-	
+
 	// Output left
-	voice_output( v, 0 );
-}
-inline VOICE_CLOCK( V5 )
+	this->voice_output(v, 0);
+}
+void SPC_DSP::voice_V5(voice_t *const v)
 {
 	// Output right
-	voice_output( v, 1 );
-	
+	this->voice_output(v, 1);
+
 	// ENDX, OUTX, and ENVX won't update if you wrote to them 1-2 clocks earlier
-	int endx_buf = REG(endx) | m.t_looped;
-	
+	int endx_buf = this->m.regs[r_endx] | this->m.t_looped;
+
 	// Clear bit in ENDX if KON just began
-	if ( v->kon_delay == 5 )
+	if (v->kon_delay == 5)
 		endx_buf &= ~v->vbit;
-	m.endx_buf = (uint8_t) endx_buf;
-}
-inline VOICE_CLOCK( V6 )
-{
-	(void) v; // avoid compiler warning about unused v
-	m.outx_buf = (uint8_t) (m.t_output >> 8);
-}
-inline VOICE_CLOCK( V7 )
+	this->m.endx_buf = static_cast<uint8_t>(endx_buf);
+}
+void SPC_DSP::voice_V6(voice_t *const)
+{
+	this->m.outx_buf = static_cast<uint8_t>(this->m.t_output >> 8);
+}
+void SPC_DSP::voice_V7(voice_t *const v)
 {
 	// Update ENDX
-	REG(endx) = m.endx_buf;
-	
-	m.envx_buf = v->t_envx_out;
-}
-inline VOICE_CLOCK( V8 )
+	this->m.regs[r_endx] = this->m.endx_buf;
+
+	this->m.envx_buf = v->t_envx_out;
+}
+void SPC_DSP::voice_V8(voice_t *const v)
 {
 	// Update OUTX
-	VREG(v->regs,outx) = m.outx_buf;
-}
-inline VOICE_CLOCK( V9 )
+	v->regs[v_outx] = this->m.outx_buf;
+}
+void SPC_DSP::voice_V9(voice_t *const v)
 {
 	// Update ENVX
-	VREG(v->regs,envx) = m.envx_buf;
+	v->regs[v_envx] = this->m.envx_buf;
 }
 
 // Most voices do all these in one clock, so make a handy composite
-inline VOICE_CLOCK( V3 )
-{
-	voice_V3a( v );
-	voice_V3b( v );
-	voice_V3c( v );
+void SPC_DSP::voice_V3(voice_t *const v)
+{
+	this->voice_V3a(v);
+	this->voice_V3b(v);
+	this->voice_V3c(v);
 }
 
 // Common combinations of voice steps on different voices. This greatly reduces
 // code size and allows everything to be inlined in these functions.
-VOICE_CLOCK(V7_V4_V1) { voice_V7(v); voice_V1(v+3); voice_V4(v+1); }
-VOICE_CLOCK(V8_V5_V2) { voice_V8(v); voice_V5(v+1); voice_V2(v+2); }
-VOICE_CLOCK(V9_V6_V3) { voice_V9(v); voice_V6(v+1); voice_V3(v+2); }
-
+void SPC_DSP::voice_V7_V4_V1(voice_t *const v) { this->voice_V7(v); this->voice_V1(v + 3); this->voice_V4(v + 1); }
+void SPC_DSP::voice_V8_V5_V2(voice_t *const v) { this->voice_V8(v); this->voice_V5(v + 1); this->voice_V2(v + 2); }
+void SPC_DSP::voice_V9_V6_V3(voice_t *const v) { this->voice_V9(v); this->voice_V6(v + 1); this->voice_V3(v + 2); }
 
 //// Echo
 
-// Current echo buffer pointer for left/right channel
-#define ECHO_PTR( ch )      (&m.ram [m.t_echo_ptr + ch * 2])
-
-// Sample in echo history buffer, where 0 is the oldest
-#define ECHO_FIR( i )       (m.echo_hist_pos [i])
-
-// Calculate FIR point for left/right channel
-#define CALC_FIR( i, ch )   ((ECHO_FIR( i + 1 ) [ch] * (int8_t) REG(fir + i * 0x10)) >> 6)
-
-#define ECHO_CLOCK( n ) inline void SPC_DSP::echo_##n()
-
-inline void SPC_DSP::echo_read( int ch )
-{
-	int s = GET_LE16SA( ECHO_PTR( ch ) );
+void SPC_DSP::echo_read(int ch)
+{
+	int s = static_cast<int16_t>(get_le16(this->ECHO_PTR(ch)));
 	// second copy simplifies wrap-around handling
-	ECHO_FIR( 0 ) [ch] = ECHO_FIR( 8 ) [ch] = s >> 1;
-}
-
-ECHO_CLOCK( 22 )
+	this->ECHO_FIR(0)[ch] = this->ECHO_FIR(8)[ch] = s >> 1;
+}
+
+void SPC_DSP::echo_22()
 {
 	// History
-	if ( ++m.echo_hist_pos >= &m.echo_hist [echo_hist_size] )
-		m.echo_hist_pos = m.echo_hist;
-	
-	m.t_echo_ptr = (m.t_esa * 0x100 + m.echo_offset) & 0xFFFF;
-	echo_read( 0 );
-	
+	if (++this->m.echo_hist_pos >= &this->m.echo_hist[echo_hist_size])
+		this->m.echo_hist_pos = this->m.echo_hist;
+
+	this->m.t_echo_ptr = (this->m.t_esa * 0x100 + this->m.echo_offset) & 0xFFFF;
+	this->echo_read(0);
+
 	// FIR (using l and r temporaries below helps compiler optimize)
-	int l = CALC_FIR( 0, 0 );
-	int r = CALC_FIR( 0, 1 );
-	
-	m.t_echo_in [0] = l;
-	m.t_echo_in [1] = r;
-}
-ECHO_CLOCK( 23 )
-{
-	int l = CALC_FIR( 1, 0 ) + CALC_FIR( 2, 0 );
-	int r = CALC_FIR( 1, 1 ) + CALC_FIR( 2, 1 );
-	
-	m.t_echo_in [0] += l;
-	m.t_echo_in [1] += r;
-	
-	echo_read( 1 );
-}
-ECHO_CLOCK( 24 )
-{
-	int l = CALC_FIR( 3, 0 ) + CALC_FIR( 4, 0 ) + CALC_FIR( 5, 0 );
-	int r = CALC_FIR( 3, 1 ) + CALC_FIR( 4, 1 ) + CALC_FIR( 5, 1 );
-	
-	m.t_echo_in [0] += l;
-	m.t_echo_in [1] += r;
-}
-ECHO_CLOCK( 25 )
-{
-	int l = m.t_echo_in [0] + CALC_FIR( 6, 0 );
-	int r = m.t_echo_in [1] + CALC_FIR( 6, 1 );
-	
-	l = (int16_t) l;
-	r = (int16_t) r;
-	
-	l += (int16_t) CALC_FIR( 7, 0 );
-	r += (int16_t) CALC_FIR( 7, 1 );
-	
-	CLAMP16( l );
-	CLAMP16( r );
-	
-	m.t_echo_in [0] = l & ~1;
-	m.t_echo_in [1] = r & ~1;
-}
-inline int SPC_DSP::echo_output( int ch )
-{
-	int out = (int16_t) ((m.t_main_out [ch] * (int8_t) REG(mvoll + ch * 0x10)) >> 7) +
-			(int16_t) ((m.t_echo_in [ch] * (int8_t) REG(evoll + ch * 0x10)) >> 7);
-	CLAMP16( out );
+	int l = this->CALC_FIR(0, 0);
+	int r = this->CALC_FIR(0, 1);
+
+	this->m.t_echo_in[0] = l;
+	this->m.t_echo_in[1] = r;
+}
+void SPC_DSP::echo_23()
+{
+	int l = this->CALC_FIR(1, 0) + this->CALC_FIR(2, 0);
+	int r = this->CALC_FIR(1, 1) + this->CALC_FIR(2, 1);
+
+	this->m.t_echo_in[0] += l;
+	this->m.t_echo_in[1] += r;
+
+	echo_read(1);
+}
+void SPC_DSP::echo_24()
+{
+	int l = this->CALC_FIR(3, 0) + this->CALC_FIR(4, 0) + this->CALC_FIR(5, 0);
+	int r = this->CALC_FIR(3, 1) + this->CALC_FIR(4, 1) + this->CALC_FIR(5, 1);
+
+	this->m.t_echo_in[0] += l;
+	this->m.t_echo_in[1] += r;
+}
+void SPC_DSP::echo_25()
+{
+	int l = this->m.t_echo_in[0] + this->CALC_FIR(6, 0);
+	int r = this->m.t_echo_in[1] + this->CALC_FIR(6, 1);
+
+	l = static_cast<int16_t>(l);
+	r = static_cast<int16_t>(r);
+
+	l += static_cast<int16_t>(this->CALC_FIR(7, 0));
+	r += static_cast<int16_t>(this->CALC_FIR(7, 1));
+
+	CLAMP16(l);
+	CLAMP16(r);
+
+	this->m.t_echo_in[0] = l & ~1;
+	this->m.t_echo_in[1] = r & ~1;
+}
+int SPC_DSP::echo_output(int ch)
+{
+	int out = static_cast<int16_t>((this->m.t_main_out [ch] * static_cast<int8_t>(this->m.regs[r_mvoll + ch * 0x10])) >> 7) +
+		static_cast<int16_t>((this->m.t_echo_in [ch] * static_cast<int8_t>(this->m.regs[r_evoll + ch * 0x10])) >> 7);
+	CLAMP16(out);
 	return out;
 }
-ECHO_CLOCK( 26 )
+void SPC_DSP::echo_26()
 {
 	// Left output volumes
 	// (save sample for next clock so we can output both together)
-	m.t_main_out [0] = echo_output( 0 );
+	this->m.t_main_out[0] = echo_output(0);
 	
 	// Echo feedback
-	int l = m.t_echo_out [0] + (int16_t) ((m.t_echo_in [0] * (int8_t) REG(efb)) >> 7);
-	int r = m.t_echo_out [1] + (int16_t) ((m.t_echo_in [1] * (int8_t) REG(efb)) >> 7);
-	
-	CLAMP16( l );
-	CLAMP16( r );
-	
-	m.t_echo_out [0] = l & ~1;
-	m.t_echo_out [1] = r & ~1;
-}
-ECHO_CLOCK( 27 )
+	int l = this->m.t_echo_out[0] + static_cast<int16_t>((this->m.t_echo_in[0] * static_cast<int8_t>(this->m.regs[r_efb])) >> 7);
+	int r = this->m.t_echo_out[1] + static_cast<int16_t>((this->m.t_echo_in[1] * static_cast<int8_t>(this->m.regs[r_efb])) >> 7);
+
+	CLAMP16(l);
+	CLAMP16(r);
+
+	this->m.t_echo_out[0] = l & ~1;
+	this->m.t_echo_out[1] = r & ~1;
+}
+void SPC_DSP::echo_27()
 {
 	// Output
-	int l = m.t_main_out [0];
-	int r = echo_output( 1 );
-	m.t_main_out [0] = 0;
-	m.t_main_out [1] = 0;
-	
+	int l = this->m.t_main_out[0];
+	int r = echo_output(1);
+	this->m.t_main_out[0] = this->m.t_main_out[1] = 0;
+
 	// TODO: global muting isn't this simple (turns DAC on and off
 	// or something, causing small ~37-sample pulse when first muted)
-	if ( REG(flg) & 0x40 )
-	{
-		l = 0;
-		r = 0;
-	}
-	
+	if (this->m.regs[r_flg] & 0x40)
+		l = r = 0;
+
 	// Output sample to DAC
-	#ifdef SPC_DSP_OUT_HOOK
-		SPC_DSP_OUT_HOOK( l, r );
-	#else
-		sample_t* out = m.out;
-		WRITE_SAMPLES( l, r, out );
-		m.out = out;
-	#endif
-}
-ECHO_CLOCK( 28 )
-{
-	m.t_echo_enabled = REG(flg);
-}
-inline void SPC_DSP::echo_write( int ch )
-{
-	if ( !(m.t_echo_enabled & 0x20) )
-	{
-		if ( m.t_echo_ptr >= 0xffc0 && rom_enabled )
-			SET_LE16A( &hi_ram [m.t_echo_ptr + ch * 2 - 0xffc0], m.t_echo_out [ch] );
+#ifdef SPC_DSP_OUT_HOOK
+	SPC_DSP_OUT_HOOK(l, r);
+#else
+	sample_t *out = this->m.out;
+	out[0] = l;
+	out[1] = r;
+	out += 2;
+	if (out >= m.out_end)
+	{
+		out = this->m.extra;
+		this->m.out_end = &this->m.extra[extra_size];
+	}
+	this->m.out = out;
+#endif
+}
+void SPC_DSP::echo_28()
+{
+	this->m.t_echo_enabled = this->m.regs[r_flg];
+}
+void SPC_DSP::echo_write(int ch)
+{
+	if (!(this->m.t_echo_enabled & 0x20))
+	{
+		if (this->m.t_echo_ptr >= 0xffc0 && this->rom_enabled)
+			set_le16(&this->hi_ram[this->m.t_echo_ptr + ch * 2 - 0xffc0], this->m.t_echo_out [ch]);
 		else
-			SET_LE16A( ECHO_PTR( ch ), m.t_echo_out [ch] );
-	}
-
-	m.t_echo_out [ch] = 0;
-}
-ECHO_CLOCK( 29 )
-{
-	m.t_esa = REG(esa);
-	
-	if ( !m.echo_offset )
-		m.echo_length = (REG(edl) & 0x0F) * 0x800;
-	
-	m.echo_offset += 4;
-	if ( m.echo_offset >= m.echo_length )
-		m.echo_offset = 0;
-	
+			set_le16(this->ECHO_PTR(ch), this->m.t_echo_out[ch]);
+	}
+
+	this->m.t_echo_out[ch] = 0;
+}
+void SPC_DSP::echo_29()
+{
+	this->m.t_esa = this->m.regs[r_esa];
+
+	if (!this->m.echo_offset)
+		this->m.echo_length = (this->m.regs[r_edl] & 0x0F) * 0x800;
+
+	this->m.echo_offset += 4;
+	if (this->m.echo_offset >= this->m.echo_length)
+		this->m.echo_offset = 0;
+
 	// Write left echo
-	echo_write( 0 );
-	
-	m.t_echo_enabled = REG(flg);
-}
-ECHO_CLOCK( 30 )
+	this->echo_write(0);
+
+	this->m.t_echo_enabled = this->m.regs[r_flg];
+}
+void SPC_DSP::echo_30()
 {
 	// Write right echo
-	echo_write( 1 );
-}
-
+	this->echo_write(1);
+}
 
 //// Timing
 
 // Execute clock for a particular voice
-#define V( clock, voice )   voice_##clock( &m.voices [voice] );
+#define V(clock, voice) voice_##clock(&this->m.voices[voice]);
 
 /* The most common sequence of clocks uses composite operations
 for efficiency. For example, the following are equivalent to the
@@ -797,273 +731,119 @@
 PHASE(31)  V(V4,0)       V(V1,2)\
 
 #if !SPC_DSP_CUSTOM_RUN
-
-void SPC_DSP::run( int clocks_remain )
-{
-	require( clocks_remain > 0 );
+void SPC_DSP::run(int clocks_remain)
+{
+	assert(clocks_remain > 0);
+
+	int phase = this->m.phase;
+	this->m.phase = (phase + clocks_remain) & 31;
+	switch (phase)
+	{
+		loop:
+#define PHASE(n) if (n && !--clocks_remain) break; case n:
+		GEN_DSP_TIMING
+#undef PHASE
 	
-	int const phase = m.phase;
-	m.phase = (phase + clocks_remain) & 31;
-	switch ( phase )
-	{
-	loop:
-	
-		#define PHASE( n ) if ( n && !--clocks_remain ) break; case n:
-		GEN_DSP_TIMING
-		#undef PHASE
-	
-		if ( --clocks_remain )
+		if (--clocks_remain)
 			goto loop;
 	}
 }
 
 #endif
 
-
 //// Setup
 
-void SPC_DSP::init( void* ram_64k )
-{
-	m.ram = (uint8_t*) ram_64k;
-	mute_voices( 0 );
-	disable_surround( false );
-	set_output( 0, 0 );
-	reset();
-
-	stereo_switch = 0xffff;
-	take_spc_snapshot = 0;
-	spc_snapshot_callback = 0;
-
-	#ifndef NDEBUG
-		// be sure this sign-extends
-		assert( (int16_t) 0x8000 == -0x8000 );
-		
-		// be sure right shift preserves sign
-		assert( (-1 >> 1) == -1 );
-		
-		// check clamp macro
-		int i;
-		i = +0x8000; CLAMP16( i ); assert( i == +0x7FFF );
-		i = -0x8001; CLAMP16( i ); assert( i == -0x8000 );
-		
-		blargg_verify_byte_order();
-	#endif
+void SPC_DSP::init(uint8_t *ram_64k)
+{
+	this->m.ram = ram_64k;
+	this->mute_voices(0);
+	this->disable_surround(false);
+	this->set_output(nullptr, 0);
+	this->reset();
+
+	this->stereo_switch = 0xffff;
+
+#ifndef NDEBUG
+	// be sure this sign-extends
+	assert(static_cast<int16_t>(0x8000) == -0x8000);
+
+	// be sure right shift preserves sign
+	assert((-1 >> 1) == -1);
+
+	// check clamp macro
+	int i = 0x8000;
+	CLAMP16(i);
+	assert(i == 0x7FFF);
+
+	i = -0x8001;
+	CLAMP16(i);
+	assert(i == -0x8000);
+
+	blargg_verify_byte_order();
+#endif
 }
 
 void SPC_DSP::soft_reset_common()
 {
-	require( m.ram ); // init() must have been called already
-	
-	m.noise              = 0x4000;
-	m.echo_hist_pos      = m.echo_hist;
-	m.every_other_sample = 1;
-	m.echo_offset        = 0;
-	m.phase              = 0;
-	
-	init_counter();
-
-	for (int i = 0; i < voice_count; i++)
-		m.voices[i].voice_number = i;
+	assert(this->m.ram); // init() must have been called already
+
+	this->m.noise = 0x4000;
+	this->m.echo_hist_pos = this->m.echo_hist;
+	this->m.every_other_sample = true;
+	this->m.echo_offset = 0;
+	this->m.phase = 0;
+
+	this->init_counter();
+
+	for (int i = 0; i < voice_count; ++i)
+		this->m.voices[i].voice_number = i;
 }
 
 void SPC_DSP::soft_reset()
 {
-	REG(flg) = 0xE0;
-	soft_reset_common();
-}
-
-void SPC_DSP::load( uint8_t const regs [register_count] )
-{
-	memcpy( m.regs, regs, sizeof m.regs );
-	memset( &m.regs [register_count], 0, offsetof (state_t,ram) - register_count );
-	
+	this->m.regs[r_flg] = 0xE0;
+	this->soft_reset_common();
+}
+
+void SPC_DSP::load(const uint8_t regs[register_count])
+{
+	std::copy(&regs[0], &regs[register_count], &this->m.regs[0]);
+	memset(&this->m.regs[register_count], 0, offsetof(state_t, ram) - register_count);
+
 	// Internal state
-	for ( int i = voice_count; --i >= 0; )
-	{
-		voice_t* v = &m.voices [i];
-		v->brr_offset = 1;
-		v->vbit       = 1 << i;
-		v->regs       = &m.regs [i * 0x10];
-	}
-	m.new_kon = REG(kon);
-	m.t_dir   = REG(dir);
-	m.t_esa   = REG(esa);
-	
-	soft_reset_common();
-}
-
-void SPC_DSP::reset() { load( initial_regs ); }
-
-
-//// State save/load
-
-#if !SPC_NO_COPY_STATE_FUNCS
-
-void SPC_State_Copier::copy( void* state, size_t size )
-{
-	func( buf, state, size );
-}
-
-int SPC_State_Copier::copy_int( int state, int size )
-{
-	BOOST::uint8_t s [2];
-	SET_LE16( s, state );
-	func( buf, &s, size );
-	return GET_LE16( s );
-}
-
-void SPC_State_Copier::skip( int count )
-{
-	if ( count > 0 )
-	{
-		char temp [64];
-		memset( temp, 0, sizeof temp );
-		do
-		{
-			int n = sizeof temp;
-			if ( n > count )
-				n = count;
-			count -= n;
-			func( buf, temp, n );
-		}
-		while ( count );
-	}
-}
-
-void SPC_State_Copier::extra()
-{
-	int n = 0;
-	SPC_State_Copier& copier = *this;
-	SPC_COPY( uint8_t, n );
-	skip( n );
-}
-
-void SPC_DSP::copy_state( unsigned char** io, copy_func_t copy )
-{
-	SPC_State_Copier copier( io, copy );
-	
-	// DSP registers
-	copier.copy( m.regs, register_count );
-	
-	// Internal state
-	
-	// Voices
-	int i;
-	for ( i = 0; i < voice_count; i++ )
-	{
-		voice_t* v = &m.voices [i];
-		
-		// BRR buffer
-		int i;
-		for ( i = 0; i < brr_buf_size; i++ )
-		{
-			int s = v->buf [i];
-			SPC_COPY(  int16_t, s );
-			v->buf [i] = v->buf [i + brr_buf_size] = s;
-		}
-		
-		SPC_COPY( uint16_t, v->interp_pos );
-		SPC_COPY( uint16_t, v->brr_addr );
-		SPC_COPY( uint16_t, v->env );
-		SPC_COPY(  int16_t, v->hidden_env );
-		SPC_COPY(  uint8_t, v->buf_pos );
-		SPC_COPY(  uint8_t, v->brr_offset );
-		SPC_COPY(  uint8_t, v->kon_delay );
-		{
-			int m = v->env_mode;
-			SPC_COPY(  uint8_t, m );
-			v->env_mode = (enum env_mode_t) m;
-		}
-		SPC_COPY(  uint8_t, v->t_envx_out );
-		
-		copier.extra();
-	}
-	
-	// Echo history
-	for ( i = 0; i < echo_hist_size; i++ )
-	{
-		int j;
-		for ( j = 0; j < 2; j++ )
-		{
-			int s = m.echo_hist_pos [i] [j];
-			SPC_COPY( int16_t, s );
-			m.echo_hist [i] [j] = s; // write back at offset 0
-		}
-	}
-	m.echo_hist_pos = m.echo_hist;
-	memcpy( &m.echo_hist [echo_hist_size], m.echo_hist, echo_hist_size * sizeof m.echo_hist [0] );
-	
-	// Misc
-	SPC_COPY(  uint8_t, m.every_other_sample );
-	SPC_COPY(  uint8_t, m.kon );
-	
-	SPC_COPY( uint16_t, m.noise );
-	SPC_COPY( uint16_t, m.counter );
-	SPC_COPY( uint16_t, m.echo_offset );
-	SPC_COPY( uint16_t, m.echo_length );
-	SPC_COPY(  uint8_t, m.phase );
-	
-	SPC_COPY(  uint8_t, m.new_kon );
-	SPC_COPY(  uint8_t, m.endx_buf );
-	SPC_COPY(  uint8_t, m.envx_buf );
-	SPC_COPY(  uint8_t, m.outx_buf );
-	
-	SPC_COPY(  uint8_t, m.t_pmon );
-	SPC_COPY(  uint8_t, m.t_non );
-	SPC_COPY(  uint8_t, m.t_eon );
-	SPC_COPY(  uint8_t, m.t_dir );
-	SPC_COPY(  uint8_t, m.t_koff );
-	
-	SPC_COPY( uint16_t, m.t_brr_next_addr );
-	SPC_COPY(  uint8_t, m.t_adsr0 );
-	SPC_COPY(  uint8_t, m.t_brr_header );
-	SPC_COPY(  uint8_t, m.t_brr_byte );
-	SPC_COPY(  uint8_t, m.t_srcn );
-	SPC_COPY(  uint8_t, m.t_esa );
-	SPC_COPY(  uint8_t, m.t_echo_enabled );
-	
-	SPC_COPY(  int16_t, m.t_main_out [0] );
-	SPC_COPY(  int16_t, m.t_main_out [1] );
-	SPC_COPY(  int16_t, m.t_echo_out [0] );
-	SPC_COPY(  int16_t, m.t_echo_out [1] );
-	SPC_COPY(  int16_t, m.t_echo_in  [0] );
-	SPC_COPY(  int16_t, m.t_echo_in  [1] );
-	
-	SPC_COPY( uint16_t, m.t_dir_addr );
-	SPC_COPY( uint16_t, m.t_pitch );
-	SPC_COPY(  int16_t, m.t_output );
-	SPC_COPY( uint16_t, m.t_echo_ptr );
-	SPC_COPY(  uint8_t, m.t_looped );
-	
-	copier.extra();
-}
-#endif
-
+	for (int i = voice_count; --i >= 0;)
+	{
+		auto &v = this->m.voices[i];
+		v.brr_offset = 1;
+		v.vbit = 1 << i;
+		v.regs = &this->m.regs[i * 0x10];
+	}
+	this->m.new_kon = this->m.regs[r_kon];
+	this->m.t_dir = this->m.regs[r_dir];
+	this->m.t_esa = this->m.regs[r_esa];
+
+	this->soft_reset_common();
+}
+
+void SPC_DSP::reset()
+{
+	this->load(initial_regs);
+}
 
 //// Snes9x Accessor
 
-void SPC_DSP::set_spc_snapshot_callback(void (*callback)())
-{
-	spc_snapshot_callback = callback;
-}
-
-void SPC_DSP::dump_spc_snapshot()
-{
-	take_spc_snapshot = 1;
-}
-
-void SPC_DSP::set_stereo_switch( int value )
-{
-	stereo_switch = value;
-}
-
-SPC_DSP::uint8_t SPC_DSP::reg_value( int ch, int addr )
-{
-	return m.voices[ch].regs[addr];
-}
-
-int SPC_DSP::envx_value( int ch )
-{
-	return m.voices[ch].env;
-}
-
+void SPC_DSP::set_stereo_switch(int value)
+{
+	this->stereo_switch = value;
+}
+
+uint8_t SPC_DSP::reg_value(int ch, int addr)
+{
+	return this->m.voices[ch].regs[addr];
+}
+
+int SPC_DSP::envx_value(int ch)
+{
+	return this->m.voices[ch].env;
+}
+

--- a/src/in_snsf/snes9x/apu/SPC_DSP.h
+++ b/src/in_snsf/snes9x/apu/SPC_DSP.h
@@ -6,169 +6,162 @@
 
 #include "blargg_common.h"
 
-extern "C" { typedef void (*dsp_copy_func_t)( unsigned char** io, void* state, size_t ); }
-
-class SPC_DSP {
+class SPC_DSP
+{
 public:
-	typedef BOOST::uint8_t uint8_t;
-	
-// Setup
+	// Setup
 
 	// Initializes DSP and has it use the 64K RAM provided
-	void init( void* ram_64k );
+	void init(uint8_t *ram_64k);
 
 	// Sets destination for output samples. If out is NULL or out_size is 0,
 	// doesn't generate any.
 	typedef short sample_t;
-	void set_output( sample_t* out, int out_size );
+	void set_output(sample_t *out, int out_size);
 
 	// Number of samples written to output since it was last set, always
 	// a multiple of 2. Undefined if more samples were generated than
 	// output buffer could hold.
 	int sample_count() const;
 
-// Emulation
+	// Emulation
 
 	// Resets DSP to power-on state
 	void reset();
 
 	// Emulates pressing reset switch on SNES
 	void soft_reset();
-	
+
 	// Reads/writes DSP registers. For accuracy, you must first call run()
 	// to catch the DSP up to present.
-	int  read ( int addr ) const;
-	void write( int addr, int data );
+	int  read(int addr) const;
+	void write(int addr, int data);
 
 	// Runs DSP for specified number of clocks (~1024000 per second). Every 32 clocks
 	// a pair of samples is be generated.
-	void run( int clock_count );
-	
-// Sound control
+	void run(int clock_count);
+
+	// Sound control
 
 	// Mutes voices corresponding to non-zero bits in mask (issues repeated KOFF events).
 	// Reduces emulation accuracy.
 	enum { voice_count = 8 };
-	void mute_voices( int mask );
-
-// State
-	
+	void mute_voices(int mask);
+
+	// State
+
 	// Resets DSP and uses supplied values to initialize registers
 	enum { register_count = 128 };
-	void load( uint8_t const regs [register_count] );
-
-	// Saves/loads exact emulator state
-	enum { state_size = 640 }; // maximum space needed when saving
-	typedef dsp_copy_func_t copy_func_t;
-	void copy_state( unsigned char** io, copy_func_t );
-
-	// Returns non-zero if new key-on events occurred since last call
-	bool check_kon();
-
-// Snes9x Accessor
-
-	int     stereo_switch;
-	int     take_spc_snapshot;
-	int     rom_enabled;   // mirror
+	void load(const uint8_t regs[register_count]);
+
+	// Snes9x Accessor
+
+	int stereo_switch;
+	bool rom_enabled; // mirror
 	uint8_t *rom, *hi_ram; // mirror
-	void    (*spc_snapshot_callback)();
-
-	void    set_spc_snapshot_callback(void (*callback)());
-	void    dump_spc_snapshot();
-	void    set_stereo_switch( int );
-	uint8_t reg_value( int, int );
-	int     envx_value( int );
-
-// DSP register addresses
+
+	void set_stereo_switch(int);
+	uint8_t reg_value(int, int);
+	int envx_value(int);
+
+	// DSP register addresses
 
 	// Global registers
-	enum {
-	    r_mvoll = 0x0C, r_mvolr = 0x1C,
-	    r_evoll = 0x2C, r_evolr = 0x3C,
-	    r_kon   = 0x4C, r_koff  = 0x5C,
-	    r_flg   = 0x6C, r_endx  = 0x7C,
-	    r_efb   = 0x0D, r_pmon  = 0x2D,
-	    r_non   = 0x3D, r_eon   = 0x4D,
-	    r_dir   = 0x5D, r_esa   = 0x6D,
-	    r_edl   = 0x7D,
-	    r_fir   = 0x0F // 8 coefficients at 0x0F, 0x1F ... 0x7F
+	enum
+	{
+		r_mvoll = 0x0C,
+		r_mvolr = 0x1C,
+		r_evoll = 0x2C,
+		r_evolr = 0x3C,
+		r_kon = 0x4C,
+		r_koff = 0x5C,
+		r_flg = 0x6C,
+		r_endx = 0x7C,
+		r_efb = 0x0D,
+		r_pmon = 0x2D,
+		r_non = 0x3D,
+		r_eon = 0x4D,
+		r_dir = 0x5D,
+		r_esa = 0x6D,
+		r_edl = 0x7D,
+		r_fir = 0x0F // 8 coefficients at 0x0F, 0x1F ... 0x7F
 	};
 
 	// Voice registers
-	enum {
-		v_voll   = 0x00, v_volr   = 0x01,
-		v_pitchl = 0x02, v_pitchh = 0x03,
-		v_srcn   = 0x04, v_adsr0  = 0x05,
-		v_adsr1  = 0x06, v_gain   = 0x07,
-		v_envx   = 0x08, v_outx   = 0x09
+	enum
+	{
+		v_voll = 0x00,
+		v_volr = 0x01,
+		v_pitchl = 0x02,
+		v_pitchh = 0x03,
+		v_srcn = 0x04,
+		v_adsr0 = 0x05,
+		v_adsr1 = 0x06,
+		v_gain = 0x07,
+		v_envx = 0x08,
+		v_outx = 0x09
 	};
 
 public:
 	enum { extra_size = 16 };
-	sample_t* extra()               { return m.extra; }
-	sample_t const* out_pos() const { return m.out; }
-	void disable_surround( bool ) { } // not supported
+	sample_t *extra() { return this->m.extra; }
+	const sample_t *out_pos() const { return this->m.out; }
+	void disable_surround(bool) { } // not supported
 public:
-	BLARGG_DISABLE_NOTHROW
-	
-	typedef BOOST::int8_t   int8_t;
-	typedef BOOST::int16_t int16_t;
-	
 	enum { echo_hist_size = 8 };
-	
+
 	enum env_mode_t { env_release, env_attack, env_decay, env_sustain };
 	enum { brr_buf_size = 12 };
 	struct voice_t
 	{
-		int buf [brr_buf_size*2];// decoded samples (twice the size to simplify wrap handling)
-		int buf_pos;            // place in buffer where next samples will be decoded
-		int interp_pos;         // relative fractional position in sample (0x1000 = 1.0)
-		int brr_addr;           // address of current BRR block
-		int brr_offset;         // current decoding offset in BRR block
-		uint8_t* regs;          // pointer to voice's DSP registers
-		int vbit;               // bitmask for voice: 0x01 for voice 0, 0x02 for voice 1, etc.
-		int kon_delay;          // KON delay/current setup phase
+		int buf[brr_buf_size * 2]; // decoded samples (twice the size to simplify wrap handling)
+		int buf_pos; // place in buffer where next samples will be decoded
+		int interp_pos; // relative fractional position in sample (0x1000 = 1.0)
+		int brr_addr; // address of current BRR block
+		int brr_offset; // current decoding offset in BRR block
+		uint8_t *regs; // pointer to voice's DSP registers
+		int vbit; // bitmask for voice: 0x01 for voice 0, 0x02 for voice 1, etc.
+		int kon_delay; // KON delay/current setup phase
 		env_mode_t env_mode;
-		int env;                // current envelope level
-		int hidden_env;         // used by GAIN mode 7, very obscure quirk
+		int env; // current envelope level
+		int hidden_env; // used by GAIN mode 7, very obscure quirk
 		uint8_t t_envx_out;
 		int voice_number;
 	};
 private:
 	enum { brr_block_size = 9 };
-	
+
 	struct state_t
 	{
-		uint8_t regs [register_count];
-		
+		uint8_t regs[register_count];
+
 		// Echo history keeps most recent 8 samples (twice the size to simplify wrap handling)
-		int echo_hist [echo_hist_size * 2] [2];
-		int (*echo_hist_pos) [2]; // &echo_hist [0 to 7]
-		
-		int every_other_sample; // toggles every sample
-		int kon;                // KON value when last checked
+		int echo_hist[echo_hist_size * 2][2];
+		int (*echo_hist_pos)[2]; // &echo_hist [0 to 7]
+
+		bool every_other_sample; // toggles every sample
+		int kon; // KON value when last checked
 		int noise;
 		int counter;
-		int echo_offset;        // offset from ESA in echo buffer
-		int echo_length;        // number of bytes that echo_offset will stop at
-		int phase;              // next clock cycle to run (0-31)
-		bool kon_check;         // set when a new KON occurs
-		
+		int echo_offset; // offset from ESA in echo buffer
+		int echo_length; // number of bytes that echo_offset will stop at
+		int phase; // next clock cycle to run (0-31)
+
 		// Hidden registers also written to when main register is written to
 		int new_kon;
 		uint8_t endx_buf;
 		uint8_t envx_buf;
 		uint8_t outx_buf;
-		
+
 		// Temporary state between clocks
-		
+
 		// read once per sample
 		int t_pmon;
 		int t_non;
 		int t_eon;
 		int t_dir;
 		int t_koff;
-		
+
 		// read a few clocks ahead then used
 		int t_brr_next_addr;
 		int t_adsr0;
@@ -177,64 +170,71 @@
 		int t_srcn;
 		int t_esa;
 		int t_echo_enabled;
-		
+
 		// internal state that is recalculated every sample
 		int t_dir_addr;
 		int t_pitch;
 		int t_output;
 		int t_looped;
 		int t_echo_ptr;
-		
+
 		// left/right sums
-		int t_main_out [2];
-		int t_echo_out [2];
-		int t_echo_in  [2];
-		
-		voice_t voices [voice_count];
-		
+		int t_main_out[2];
+		int t_echo_out[2];
+		int t_echo_in[2];
+
+		voice_t voices[voice_count];
+
 		// non-emulation state
-		uint8_t* ram; // 64K shared RAM between DSP and SMP
+		uint8_t *ram; // 64K shared RAM between DSP and SMP
 		int mute_mask;
-		sample_t* out;
-		sample_t* out_end;
-		sample_t* out_begin;
-		sample_t extra [extra_size];
+		sample_t *out;
+		sample_t *out_end;
+		sample_t *out_begin;
+		sample_t extra[extra_size];
 	};
 	state_t m;
-	
+
 	void init_counter();
 	void run_counters();
-	unsigned read_counter( int rate );
-	
-	int  interpolate( voice_t const* v );
-	void run_envelope( voice_t* const v );
-	void decode_brr( voice_t* v );
+	unsigned read_counter(int rate);
+
+	int interpolate(const voice_t *v);
+	void run_envelope(voice_t *const v);
+	void decode_brr(voice_t *v);
 
 	void misc_27();
 	void misc_28();
 	void misc_29();
 	void misc_30();
 
-	void voice_output( voice_t const* v, int ch );
-	void voice_V1( voice_t* const );
-	void voice_V2( voice_t* const );
-	void voice_V3( voice_t* const );
-	void voice_V3a( voice_t* const );
-	void voice_V3b( voice_t* const );
-	void voice_V3c( voice_t* const );
-	void voice_V4( voice_t* const );
-	void voice_V5( voice_t* const );
-	void voice_V6( voice_t* const );
-	void voice_V7( voice_t* const );
-	void voice_V8( voice_t* const );
-	void voice_V9( voice_t* const );
-	void voice_V7_V4_V1( voice_t* const );
-	void voice_V8_V5_V2( voice_t* const );
-	void voice_V9_V6_V3( voice_t* const );
-
-	void echo_read( int ch );
-	int  echo_output( int ch );
-	void echo_write( int ch );
+	void voice_output(const voice_t *v, int ch);
+	void voice_V1(voice_t *const);
+	void voice_V2(voice_t *const);
+	void voice_V3(voice_t *const);
+	void voice_V3a(voice_t *const);
+	void voice_V3b(voice_t *const);
+	void voice_V3c(voice_t *const);
+	void voice_V4(voice_t *const);
+	void voice_V5(voice_t *const);
+	void voice_V6(voice_t *const);
+	void voice_V7(voice_t *const);
+	void voice_V8(voice_t *const);
+	void voice_V9(voice_t *const);
+	void voice_V7_V4_V1(voice_t *const);
+	void voice_V8_V5_V2(voice_t *const);
+	void voice_V9_V6_V3(voice_t *const);
+
+	// Current echo buffer pointer for left/right channel
+	uint8_t *ECHO_PTR(int ch) { return &this->m.ram[this->m.t_echo_ptr + ch * 2]; }
+	// Sample in echo history buffer, where 0 is the oldest
+	int *ECHO_FIR(size_t i) { return this->m.echo_hist_pos[i]; }
+	// Calculate FIR point for left/right channel
+	int CALC_FIR(size_t i, int ch) { return (this->ECHO_FIR(i + 1)[ch] * static_cast<int8_t>(this->m.regs[r_fir + i * 0x10])) >> 6; }
+
+	void echo_read(int ch);
+	int echo_output(int ch);
+	void echo_write(int ch);
 	void echo_22();
 	void echo_23();
 	void echo_24();
@@ -248,73 +248,42 @@
 	void soft_reset_common();
 };
 
-#include <assert.h>
-
-inline int SPC_DSP::sample_count() const { return m.out - m.out_begin; }
-
-inline int SPC_DSP::read( int addr ) const
+inline int SPC_DSP::sample_count() const { return this->m.out - this->m.out_begin; }
+
+inline int SPC_DSP::read(int addr) const
 {
-	assert( (unsigned) addr < register_count );
-	return m.regs [addr];
+	assert(static_cast<unsigned>(addr) < register_count);
+	return this->m.regs[addr];
 }
 
-inline void SPC_DSP::write( int addr, int data )
+inline void SPC_DSP::write(int addr, int data)
 {
-	assert( (unsigned) addr < register_count );
-	
-	m.regs [addr] = (uint8_t) data;
-	switch ( addr & 0x0F )
-	{
-	case v_envx:
-		m.envx_buf = (uint8_t) data;
-		break;
-		
-	case v_outx:
-		m.outx_buf = (uint8_t) data;
-		break;
-	
-	case 0x0C:
-		if ( addr == r_kon )
-			m.new_kon = (uint8_t) data;
-		
-		if ( addr == r_endx ) // always cleared, regardless of data written
-		{
-			m.endx_buf = 0;
-			m.regs [r_endx] = 0;
-		}
-		break;
+	assert(static_cast<unsigned>(addr) < register_count);
+
+	this->m.regs[addr] = static_cast<uint8_t>(data);
+	switch (addr & 0x0F)
+	{
+		case v_envx:
+			this->m.envx_buf = static_cast<uint8_t>(data);
+			break;
+
+		case v_outx:
+			this->m.outx_buf = static_cast<uint8_t>(data);
+			break;
+
+		case 0x0C:
+			if (addr == r_kon)
+				this->m.new_kon = static_cast<uint8_t>(data);
+
+			if (addr == r_endx) // always cleared, regardless of data written
+			{
+				this->m.endx_buf = 0;
+				this->m.regs[r_endx] = 0;
+			}
 	}
 }
 
-inline void SPC_DSP::mute_voices( int mask ) { m.mute_mask = mask; }
-
-inline bool SPC_DSP::check_kon()
-{
-	bool old = m.kon_check;
-	m.kon_check = 0;
-	return old;
-}
-
-#if !SPC_NO_COPY_STATE_FUNCS
-
-class SPC_State_Copier {
-	SPC_DSP::copy_func_t func;
-	unsigned char** buf;
-public:
-	SPC_State_Copier( unsigned char** p, SPC_DSP::copy_func_t f ) { func = f; buf = p; }
-	void copy( void* state, size_t size );
-	int copy_int( int state, int size );
-	void skip( int count );
-	void extra();
-};
-
-#define SPC_COPY( type, state )\
-{\
-	state = (BOOST::type) copier.copy_int( state, sizeof (BOOST::type) );\
-	assert( (BOOST::type) state == state );\
-}
+inline void SPC_DSP::mute_voices(int mask) { this->m.mute_mask = mask; }
 
 #endif
 
-#endif
-

--- a/src/in_snsf/snes9x/apu/apu.cpp
+++ b/src/in_snsf/snes9x/apu/apu.cpp
@@ -175,11 +175,8 @@
   Nintendo Co., Limited and its subsidiary companies.
  ***********************************************************************************/
 
-
-#include <math.h>
+#include <memory>
 #include "apu.h"
-//#include "snapshot.h"
-//#include "display.h"
 #include "linear_resampler.h"
 #include "hermite_resampler.h"
 #include "bspline_resampler.h"
@@ -189,18 +186,17 @@
 bool SincResampler::initializedLUTs = false;
 double SincResampler::sinc_lut[SincResampler::SINC_SAMPLES + 1];
 
-#define APU_DEFAULT_INPUT_RATE		32000
-#define APU_MINIMUM_SAMPLE_COUNT	512
-#define APU_MINIMUM_SAMPLE_BLOCK	128
-#define APU_NUMERATOR_NTSC			15664
-#define APU_DENOMINATOR_NTSC		328125
-#define APU_NUMERATOR_PAL			34176
-#define APU_DENOMINATOR_PAL			709379
-#define APU_DEFAULT_RESAMPLER		HermiteResampler
-
-SNES_SPC	*spc_core = NULL;
-
-static uint8_t APUROM[64] =
+static const uint32_t APU_DEFAULT_INPUT_RATE = 32000;
+static const int APU_MINIMUM_SAMPLE_COUNT = 512;
+static const int APU_MINIMUM_SAMPLE_BLOCK = 128;
+static const uint32_t APU_NUMERATOR_NTSC = 15664;
+static const uint32_t APU_DENOMINATOR_NTSC = 328125;
+static const uint32_t APU_NUMERATOR_PAL = 34176;
+static const uint32_t APU_DENOMINATOR_PAL = 709379;
+
+static std::unique_ptr<SNES_SPC> spc_core;
+
+static const uint8_t APUROM[] =
 {
 	0xCD, 0xEF, 0xBD, 0xE8, 0x00, 0xC6, 0x1D, 0xD0,
 	0xFC, 0x8F, 0xAA, 0xF4, 0x8F, 0xBB, 0xF5, 0x78,
@@ -214,81 +210,62 @@
 
 namespace spc
 {
-	static apu_callback	sa_callback     = NULL;
-	static void			*extra_data     = NULL;
-
-	static bool		sound_in_sync   = true;
-	static bool		sound_enabled   = false;
-
-	static int			buffer_size;
-	static int			lag_master      = 0;
-	static int			lag             = 0;
-
-	static uint8_t		*landing_buffer = NULL;
-	static uint8_t		*shrink_buffer  = NULL;
-
-	static Resampler	*resampler      = NULL;
-
-	static int32_t		reference_time;
-	static uint32_t		remainder;
-
-	static const int	timing_hack_numerator   = SNES_SPC::tempo_unit;
-	static int			timing_hack_denominator = SNES_SPC::tempo_unit;
+	static bool sound_in_sync = true;
+	static bool sound_enabled = false;
+
+	static int buffer_size;
+	static int lag_master = 0;
+	static int lag = 0;
+
+	static std::unique_ptr<uint8_t[]> landing_buffer;
+	static std::unique_ptr<uint8_t[]> shrink_buffer;
+
+	static std::unique_ptr<Resampler> resampler;
+
+	static int32_t reference_time;
+	static uint32_t remainder;
+
+	static const int timing_hack_numerator = SNES_SPC::tempo_unit;
+	static int timing_hack_denominator = SNES_SPC::tempo_unit;
 	/* Set these to NTSC for now. Will change to PAL in S9xAPUTimingSetSpeedup
 	   if necessary on game load. */
-	static uint32_t		ratio_numerator = APU_NUMERATOR_NTSC;
-	static uint32_t		ratio_denominator = APU_DENOMINATOR_NTSC;
-}
-
-static void EightBitize (uint8_t *, int);
-static void DeStereo (uint8_t *, int);
-static void ReverseStereo (uint8_t *, int);
-static void UpdatePlaybackRate();
-static void from_apu_to_state (uint8_t **, void *, size_t);
-static void to_apu_from_state (uint8_t **, void *, size_t);
-//static void SPCSnapshotCallback();
-static inline int S9xAPUGetClock (int32_t);
-static inline int S9xAPUGetClockRemainder (int32_t);
-
-
-static void EightBitize (uint8_t *buffer, int sample_count)
-{
-	uint8_t	*buf8  = (uint8_t *) buffer;
-	int16_t	*buf16 = (int16_t *) buffer;
-
-	for (int i = 0; i < sample_count; i++)
-		buf8[i] = (uint8_t) ((buf16[i] / 256) + 128);
-}
-
-static void DeStereo (uint8_t *buffer, int sample_count)
-{
-	int16_t	*buf = (int16_t *) buffer;
-	int32_t	s1, s2;
-
-	for (int i = 0; i < sample_count >> 1; i++)
-	{
-		s1 = (int32_t) buf[2 * i];
-		s2 = (int32_t) buf[2 * i + 1];
-		buf[i] = (int16_t) ((s1 + s2) >> 1);
-	}
-}
-
-static void ReverseStereo (uint8_t *src_buffer, int sample_count)
-{
-	int16_t	*buffer = (int16_t *) src_buffer;
+	static uint32_t ratio_numerator = APU_NUMERATOR_NTSC;
+	static uint32_t ratio_denominator = APU_DENOMINATOR_NTSC;
+}
+
+static void EightBitize(uint8_t *buffer, int sample_count)
+{
+	uint8_t *buf8 = buffer;
+	int16_t *buf16 = reinterpret_cast<int16_t *>(buffer);
+
+	for (int i = 0; i < sample_count; ++i)
+		buf8[i] = static_cast<uint8_t>((buf16[i] / 256) + 128);
+}
+
+static void DeStereo(uint8_t *buffer, int sample_count)
+{
+	int16_t *buf = reinterpret_cast<int16_t *>(buffer);
+
+	for (int i = 0; i < sample_count >> 1; ++i)
+	{
+		int32_t s1 = static_cast<int32_t>(buf[2 * i]);
+		int32_t s2 = static_cast<int32_t>(buf[2 * i + 1]);
+		buf[i] = static_cast<int16_t>((s1 + s2) >> 1);
+	}
+}
+
+static void ReverseStereo(uint8_t *src_buffer, int sample_count)
+{
+	int16_t *buffer = reinterpret_cast<int16_t *>(src_buffer);
 
 	for (int i = 0; i < sample_count; i += 2)
-	{
-		buffer[i + 1] ^= buffer[i];
-		buffer[i] ^= buffer[i + 1];
-		buffer[i + 1] ^= buffer[i];
-	}
-}
-
-bool S9xMixSamples (uint8_t *buffer, int sample_count)
-{
-	static int	shrink_buffer_size = -1;
-	uint8_t		*dest;
+		std::swap(buffer[i], buffer[i + 1]);
+}
+
+bool S9xMixSamples(uint8_t *buffer, int sample_count)
+{
+	static int shrink_buffer_size = -1;
+	uint8_t *dest;
 
 	if (!Settings.SixteenBitSound || !Settings.Stereo)
 	{
@@ -299,35 +276,34 @@
 		/* We still have to generate 16-bit samples for bit-dropping, too */
 		if (shrink_buffer_size < (sample_count << 1))
 		{
-			delete[] spc::shrink_buffer;
-			spc::shrink_buffer = new uint8_t[sample_count << 1];
+			spc::shrink_buffer.reset(new uint8_t[sample_count << 1]);
 			shrink_buffer_size = sample_count << 1;
 		}
 
-		dest = spc::shrink_buffer;
+		dest = spc::shrink_buffer.get();
 	}
 	else
 		dest = buffer;
 
 	if (Settings.Mute)
 	{
-		memset(dest, 0, sample_count << 1);
+		std::fill(&dest[0], &dest[sample_count << 1], 0);
 		spc::resampler->clear();
 
 		return false;
 	}
 	else
 	{
-		if (spc::resampler->avail() >= (sample_count + spc::lag))
+		if (spc::resampler->avail() >= sample_count + spc::lag)
 		{
-			spc::resampler->read((short *) dest, sample_count);
+			spc::resampler->read(reinterpret_cast<short *>(dest), sample_count);
 			if (spc::lag == spc::lag_master)
 				spc::lag = 0;
 		}
 		else
 		{
-			memset(buffer, (Settings.SixteenBitSound ? 0 : 128), (sample_count << (Settings.SixteenBitSound ? 1 : 0)) >> (Settings.Stereo ? 0 : 1));
-			if (spc::lag == 0)
+			std::fill(&buffer[0], &buffer[(sample_count << (Settings.SixteenBitSound ? 1 : 0)) >> (Settings.Stereo ? 0 : 1)], Settings.SixteenBitSound ? 0 : 128);
+			if (!spc::lag)
 				spc::lag = spc::lag_master;
 
 			return false;
@@ -348,7 +324,7 @@
 		if (!Settings.SixteenBitSound)
 			EightBitize(dest, sample_count);
 
-		memcpy(buffer, dest, (sample_count << (Settings.SixteenBitSound ? 1 : 0)));
+		std::copy(&dest[0], &dest[sample_count << (Settings.SixteenBitSound ? 1 : 0)], &buffer[0]);
 	}
 
 	return true;
@@ -363,7 +339,7 @@
 {
 	if (!Settings.Mute)
 	{
-		if (!spc::resampler->push((short *) spc::landing_buffer, spc_core->sample_count()))
+		if (!spc::resampler->push(reinterpret_cast<short *>(spc::landing_buffer.get()), spc_core->sample_count()))
 		{
 			/* We weren't able to process the entire buffer. Potential overrun. */
 			spc::sound_in_sync = false;
@@ -375,27 +351,17 @@
 
 	if (!Settings.SoundSync || Settings.TurboMode || Settings.Mute)
 		spc::sound_in_sync = true;
-	else
-	if (spc::resampler->space_empty() >= spc::resampler->space_filled())
+	else if (spc::resampler->space_empty() >= spc::resampler->space_filled())
 		spc::sound_in_sync = true;
 	else
 		spc::sound_in_sync = false;
 
-	spc_core->set_output((SNES_SPC::sample_t *) spc::landing_buffer, spc::buffer_size >> 1);
+	spc_core->set_output(reinterpret_cast<SNES_SPC::sample_t *>(spc::landing_buffer.get()), spc::buffer_size >> 1);
 }
 
 void S9xLandSamples()
 {
-	if (spc::sa_callback != NULL)
-		spc::sa_callback(spc::extra_data);
-	else
-		S9xFinalizeSamples();
-}
-
-void S9xClearSamples()
-{
-	spc::resampler->clear();
-	spc::lag = spc::lag_master;
+	S9xFinalizeSamples();
 }
 
 bool S9xSyncSound()
@@ -408,28 +374,22 @@
 	return spc::sound_in_sync;
 }
 
-void S9xSetSamplesAvailableCallback (apu_callback callback, void *data)
-{
-	spc::sa_callback = callback;
-	spc::extra_data  = data;
-}
-
 static void UpdatePlaybackRate()
 {
-	if (Settings.SoundInputRate == 0)
+	if (!Settings.SoundInputRate)
 		Settings.SoundInputRate = APU_DEFAULT_INPUT_RATE;
 
-	double time_ratio = (double) Settings.SoundInputRate * spc::timing_hack_numerator / (Settings.SoundPlaybackRate * spc::timing_hack_denominator);
+	double time_ratio = static_cast<double>(Settings.SoundInputRate) * spc::timing_hack_numerator / (Settings.SoundPlaybackRate * spc::timing_hack_denominator);
 	spc::resampler->time_ratio(time_ratio);
 }
 
-template<class ResamplerClass> bool S9xInitSound (int buffer_ms, int lag_ms)
+template<class ResamplerClass> bool S9xInitSound(int buffer_ms, int lag_ms)
 {
 	// buffer_ms : buffer size given in millisecond
 	// lag_ms    : allowable time-lag given in millisecond
 
-	int	sample_count     = buffer_ms * 32000 / 1000;
-	int	lag_sample_count = lag_ms    * 32000 / 1000;
+	int sample_count = buffer_ms * 32000 / 1000;
+	int lag_sample_count = lag_ms * 32000 / 1000;
 
 	spc::lag_master = lag_sample_count;
 	if (Settings.Stereo)
@@ -445,32 +405,20 @@
 	if (Settings.SixteenBitSound)
 		spc::buffer_size <<= 1;
 
-	printf("Sound buffer size: %d (%d samples)\n", spc::buffer_size, sample_count);
-
-	if (spc::landing_buffer)
-		delete[] spc::landing_buffer;
-	spc::landing_buffer = new uint8_t[spc::buffer_size * 2];
+	spc::landing_buffer.reset(new uint8_t[spc::buffer_size * 2]);
 	if (!spc::landing_buffer)
 		return false;
 
 	/* The resampler and spc unit use samples (16-bit short) as
 	/*   arguments. Use 2x in the resampler for buffer leveling with SoundSync */
-	/*if (!spc::resampler)
-	{*/
-	if (spc::resampler)
-		delete spc::resampler;
-
-		spc::resampler = new ResamplerClass(spc::buffer_size >> (Settings.SoundSync ? 0 : 1));
-		if (!spc::resampler)
-		{
-			delete[] spc::landing_buffer;
-			return false;
-		}
-	/*}
-	else
-		spc::resampler->resize(spc::buffer_size >> (Settings.SoundSync ? 0 : 1));*/
-
-	spc_core->set_output((SNES_SPC::sample_t *) spc::landing_buffer, spc::buffer_size >> 1);
+	spc::resampler.reset(new ResamplerClass(spc::buffer_size >> (Settings.SoundSync ? 0 : 1)));
+	if (!spc::resampler)
+	{
+		spc::landing_buffer.reset();
+		return false;
+	}
+
+	spc_core->set_output(reinterpret_cast<SNES_SPC::sample_t *>(spc::landing_buffer.get()), spc::buffer_size >> 1);
 
 	UpdatePlaybackRate();
 
@@ -485,97 +433,63 @@
 template bool S9xInitSound<OsculatingResampler>(int, int);
 template bool S9xInitSound<SincResampler>(int, int);
 
-void S9xSetSoundControl (uint8_t voice_switch)
-{
-	spc_core->dsp_set_stereo_switch(voice_switch << 8 | voice_switch);
-}
-
-void S9xSetSoundMute (bool mute)
+void S9xSetSoundControl(uint8_t voice_switch)
+{
+	spc_core->dsp_set_stereo_switch((voice_switch << 8) | voice_switch);
+}
+
+void S9xSetSoundMute(bool mute)
 {
 	Settings.Mute = mute;
 	if (!spc::sound_enabled)
 		Settings.Mute = true;
 }
 
-void S9xDumpSPCSnapshot()
-{
-	spc_core->dsp_dump_spc_snapshot();
-}
-
-/*static void SPCSnapshotCallback()
-{
-	S9xSPCDump(S9xGetFilenameInc((".spc"), SPC_DIR));
-	printf("Dumped key-on triggered spc snapshot.\n");
-}*/
-
 bool S9xInitAPU()
 {
-	spc_core = new SNES_SPC;
+	spc_core.reset(new SNES_SPC);
 	if (!spc_core)
 		return false;
 
 	spc_core->init();
 	spc_core->init_rom(APUROM);
 
-	//spc_core->dsp_set_spc_snapshot_callback(SPCSnapshotCallback);
-
-	spc::landing_buffer = NULL;
-	spc::shrink_buffer  = NULL;
-	spc::resampler      = NULL;
+	spc::landing_buffer.reset();
+	spc::shrink_buffer.reset();
+	spc::resampler.reset();
 
 	return true;
 }
 
 void S9xDeinitAPU()
 {
-	if (spc_core)
-	{
-		delete spc_core;
-		spc_core = NULL;
-	}
-
-	if (spc::resampler)
-	{
-		delete spc::resampler;
-		spc::resampler = NULL;
-	}
-
-	if (spc::landing_buffer)
-	{
-		delete[] spc::landing_buffer;
-		spc::landing_buffer = NULL;
-	}
-
-	if (spc::shrink_buffer)
-	{
-		delete[] spc::shrink_buffer;
-		spc::shrink_buffer = NULL;
-	}
-}
-
-static inline int S9xAPUGetClock (int32_t cpucycles)
-{
-	return (spc::ratio_numerator * (cpucycles - spc::reference_time) + spc::remainder) /
-			spc::ratio_denominator;
-}
-
-static inline int S9xAPUGetClockRemainder (int32_t cpucycles)
-{
-	return (spc::ratio_numerator * (cpucycles - spc::reference_time) + spc::remainder) %
-			spc::ratio_denominator;
-}
-
-uint8_t S9xAPUReadPort (int port)
-{
-	return (uint8_t) spc_core->read_port(S9xAPUGetClock(CPU.Cycles), port);
-}
-
-void S9xAPUWritePort (int port, uint8_t byte)
+	spc_core.reset();
+	spc::resampler.reset();
+	spc::landing_buffer.reset();
+	spc::shrink_buffer.reset();
+}
+
+static inline int S9xAPUGetClock(int32_t cpucycles)
+{
+	return (spc::ratio_numerator * (cpucycles - spc::reference_time) + spc::remainder) / spc::ratio_denominator;
+}
+
+static inline int S9xAPUGetClockRemainder(int32_t cpucycles)
+{
+	return (spc::ratio_numerator * (cpucycles - spc::reference_time) + spc::remainder) % spc::ratio_denominator;
+}
+
+uint8_t S9xAPUReadPort(int port)
+{
+	return static_cast<uint8_t>(spc_core->read_port(S9xAPUGetClock(CPU.Cycles), port));
+}
+
+void S9xAPUWritePort(int port, uint8_t byte)
 {
 	spc_core->write_port(S9xAPUGetClock(CPU.Cycles), port, byte);
 }
 
-void S9xAPUSetReferenceTime (int32_t cpucycles)
+void S9xAPUSetReferenceTime(int32_t cpucycles)
 {
 	spc::reference_time = cpucycles;
 }
@@ -598,26 +512,19 @@
 		S9xLandSamples();
 }
 
-void S9xAPUTimingSetSpeedup (int ticks)
-{
-	if (ticks != 0)
-		printf("APU speedup hack: %d\n", ticks);
-
+void S9xAPUTimingSetSpeedup(int ticks)
+{
 	spc::timing_hack_denominator = SNES_SPC::tempo_unit - ticks;
 	spc_core->set_tempo(spc::timing_hack_denominator);
 
 	spc::ratio_numerator = Settings.PAL ? APU_NUMERATOR_PAL : APU_NUMERATOR_NTSC;
-	spc::ratio_denominator = Settings.PAL ? APU_DENOMINATOR_PAL : APU_DENOMINATOR_NTSC;
-	spc::ratio_denominator = spc::ratio_denominator * spc::timing_hack_denominator / spc::timing_hack_numerator;
+	spc::ratio_denominator = (Settings.PAL ? APU_DENOMINATOR_PAL : APU_DENOMINATOR_NTSC) * spc::timing_hack_denominator / spc::timing_hack_numerator;
 
 	UpdatePlaybackRate();
 }
 
-void S9xAPUAllowTimeOverflow (bool allow)
-{
-	if (allow)
-		printf("APU time overflow allowed\n");
-
+void S9xAPUAllowTimeOverflow(bool allow)
+{
 	spc_core->spc_allow_time_overflow(allow);
 }
 
@@ -626,54 +533,8 @@
 	spc::reference_time = 0;
 	spc::remainder = 0;
 	spc_core->reset();
-	spc_core->set_output((SNES_SPC::sample_t *) spc::landing_buffer, spc::buffer_size >> 1);
+	spc_core->set_output(reinterpret_cast<SNES_SPC::sample_t *>(spc::landing_buffer.get()), spc::buffer_size >> 1);
 
 	spc::resampler->clear();
 }
 
-void S9xSoftResetAPU()
-{
-	spc::reference_time = 0;
-	spc::remainder = 0;
-	spc_core->soft_reset();
-	spc_core->set_output((SNES_SPC::sample_t *) spc::landing_buffer, spc::buffer_size >> 1);
-
-	spc::resampler->clear();
-}
-
-static void from_apu_to_state (uint8_t **buf, void *var, size_t size)
-{
-	memcpy(*buf, var, size);
-	*buf += size;
-}
-
-static void to_apu_from_state (uint8_t **buf, void *var, size_t size)
-{
-	memcpy(var, *buf, size);
-	*buf += size;
-}
-
-void S9xAPUSaveState (uint8_t *block)
-{
-	uint8_t	*ptr = block;
-
-	spc_core->copy_state(&ptr, from_apu_to_state);
-
-	SET_LE32(ptr, spc::reference_time);
-	ptr += sizeof(int32_t);
-	SET_LE32(ptr, spc::remainder);
-}
-
-void S9xAPULoadState (uint8_t *block)
-{
-	uint8_t	*ptr = block;
-
-	S9xResetAPU();
-
-	spc_core->copy_state(&ptr, to_apu_from_state);
-
-	spc::reference_time = GET_LE32(ptr);
-	ptr += sizeof(int32_t);
-	spc::remainder = GET_LE32(ptr);
-}
-

--- a/src/in_snsf/snes9x/apu/apu.h
+++ b/src/in_snsf/snes9x/apu/apu.h
@@ -175,46 +175,30 @@
   Nintendo Co., Limited and its subsidiary companies.
  ***********************************************************************************/
 
-
 #ifndef _APU_H_
 #define _APU_H_
 
 #include "../snes9x.h"
 #include "SNES_SPC.h"
-
-typedef void (*apu_callback) (void *);
-
-#define SPC_SAVE_STATE_BLOCK_SIZE	(SNES_SPC::state_size + 8)
 
 bool S9xInitAPU();
 void S9xDeinitAPU();
 void S9xResetAPU();
-void S9xSoftResetAPU();
-uint8_t S9xAPUReadPort (int);
-void S9xAPUWritePort (int, uint8_t);
-void S9xAPUExecute();
+uint8_t S9xAPUReadPort(int);
+void S9xAPUWritePort(int, uint8_t);
 void S9xAPUEndScanline();
-void S9xAPUSetReferenceTime (int32_t);
-void S9xAPUTimingSetSpeedup (int);
-void S9xAPUAllowTimeOverflow (bool);
-void S9xAPULoadState (uint8_t *);
-void S9xAPUSaveState (uint8_t *);
-void S9xDumpSPCSnapshot();
-
-template<class ResamplerClass> bool S9xInitSound (int, int);
+void S9xAPUSetReferenceTime(int32_t);
+void S9xAPUTimingSetSpeedup(int);
+void S9xAPUAllowTimeOverflow(bool);
+
+template<class ResamplerClass> bool S9xInitSound(int, int);
 bool S9xOpenSoundDevice();
 
 bool S9xSyncSound();
 int S9xGetSampleCount();
-void S9xSetSoundControl (uint8_t);
-void S9xSetSoundMute (bool);
-void S9xLandSamples();
-void S9xFinalizeSamples();
-void S9xClearSamples();
-bool S9xMixSamples (uint8_t *, int);
-void S9xSetSamplesAvailableCallback (apu_callback, void *);
-
-extern SNES_SPC	*spc_core;
+void S9xSetSoundControl(uint8_t);
+void S9xSetSoundMute(bool);
+bool S9xMixSamples(uint8_t *, int);
 
 #endif
 

--- a/src/in_snsf/snes9x/apu/blargg_common.h
+++ b/src/in_snsf/snes9x/apu/blargg_common.h
@@ -5,10 +5,10 @@
 #ifndef BLARGG_COMMON_H
 #define BLARGG_COMMON_H
 
-#include <stddef.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <limits.h>
+#include <cstddef>
+#include <cstdlib>
+#include <cassert>
+#include <climits>
 
 #undef BLARGG_COMMON_H
 // allow blargg_config.h to #include blargg_common.h
@@ -16,171 +16,31 @@
 #ifndef BLARGG_COMMON_H
 #define BLARGG_COMMON_H
 
-// BLARGG_RESTRICT: equivalent to restrict, where supported
-#if defined (__GNUC__) || _MSC_VER >= 1100
-	#define BLARGG_RESTRICT __restrict
-#else
-	#define BLARGG_RESTRICT
-#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
-
-// blargg_vector - very lightweight vector of POD types (no constructor/destructor)
-template<class T>
-class blargg_vector {
-	T* begin_;
-	size_t size_;
-public:
-	blargg_vector() : begin_( 0 ), size_( 0 ) { }
-	~blargg_vector() { free( begin_ ); }
-	size_t size() const { return size_; }
-	T* begin() const { return begin_; }
-	T* end() const { return begin_ + size_; }
-	blargg_err_t resize( size_t n )
-	{
-		// TODO: blargg_common.cpp to hold this as an outline function, ugh
-		void* p = realloc( begin_, n * sizeof (T) );
-		if ( p )
-			begin_ = (T*) p;
-		else if ( n > size_ ) // realloc failure only a problem if expanding
-			return "Out of memory";
-		size_ = n;
-		return 0;
-	}
-	void clear() { void* p = begin_; begin_ = 0; size_ = 0; free( p ); }
-	T& operator [] ( size_t n ) const
-	{
-		assert( n <= size_ ); // <= to allow past-the-end value
-		return begin_ [n];
-	}
-};
-
-#ifndef BLARGG_DISABLE_NOTHROW
-	// throw spec mandatory in ISO C++ if operator new can return NULL
-	#if __cplusplus >= 199711 || defined (__GNUC__)
-		#define BLARGG_THROWS( spec ) throw spec
-	#else
-		#define BLARGG_THROWS( spec )
-	#endif
-	#define BLARGG_DISABLE_NOTHROW \
-		void* operator new ( size_t s ) BLARGG_THROWS(()) { return malloc( s ); }\
-		void operator delete ( void* p ) { free( p ); }
-	#define BLARGG_NEW new
-#else
-	#include <new>
-	#define BLARGG_NEW new (std::nothrow)
-#endif
-
-// BLARGG_4CHAR('a','b','c','d') = 'abcd' (four character integer constant)
-#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
+# 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;
-	const bool true  = 1;
-	const bool false = 0;
+#if defined(BLARGG_COMPILER_HAS_BOOL) && !BLARGG_COMPILER_HAS_BOOL
+// If you get errors here, modify your blargg_config.h file
+typedef int bool;
+const bool true = 1;
+const bool false = 0;
 #endif
 
-// blargg_long/blargg_ulong = at least 32 bits, int if it's big enough
-
-#if INT_MAX < 0x7FFFFFFF || LONG_MAX == 0x7FFFFFFF
-	typedef long blargg_long;
-#else
-	typedef int blargg_long;
-#endif
-
-#if UINT_MAX < 0xFFFFFFFF || ULONG_MAX == 0xFFFFFFFF
-	typedef unsigned long blargg_ulong;
-#else
-	typedef unsigned blargg_ulong;
-#endif
-
-// BOOST::int8_t etc.
-
-// HAVE_STDINT_H: If defined, use <stdint.h> for int8_t etc.
-#if 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
-	struct BOOST
-	{
-		#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
+#include <cstdint>
 
 #endif
 #endif

--- a/src/in_snsf/snes9x/apu/blargg_config.h
+++ b/src/in_snsf/snes9x/apu/blargg_config.h
@@ -3,12 +3,6 @@
 // snes_spc 0.9.0
 #ifndef BLARGG_CONFIG_H
 #define BLARGG_CONFIG_H
-
-// Uncomment to disable debugging checks
-//#define NDEBUG 1
-
-// Uncomment to enable platform-specific (and possibly non-portable) optimizations
-//#define BLARGG_NONPORTABLE 1
 
 // Uncomment if automatic byte-order determination doesn't work
 //#define BLARGG_BIG_ENDIAN 1
@@ -16,10 +10,5 @@
 // Uncomment if you get errors in the bool section of blargg_common.h
 //#define BLARGG_COMPILER_HAS_BOOL 1
 
-// Use standard config.h if present
-#ifdef HAVE_CONFIG_H
-	#include "config.h"
 #endif
 
-#endif
-

--- a/src/in_snsf/snes9x/apu/blargg_endian.h
+++ b/src/in_snsf/snes9x/apu/blargg_endian.h
@@ -7,180 +7,63 @@
 #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
+#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
-	#define BLARGG_CPU_RISC 1
+#if defined(__powerpc__) || defined(__ppc__) || defined(__POWERPC__) || defined(__powerc)
+# define BLARGG_CPU_POWERPC 1
+# define BLARGG_CPU_RISC 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__) || 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 (__sparc__)     ||  BLARGG_CPU_POWERPC || \
-	(defined (BIG_ENDIAN) && BIG_ENDIAN+0 != 4321)
-	#define BLARGG_BIG_ENDIAN 1
-#elif !defined (__mips__)
-	// No endian specified; assume little-endian, since it's most common
-	#define BLARGG_LITTLE_ENDIAN 1
-#endif
-#endif
+#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__) || 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 (__sparc__) || BLARGG_CPU_POWERPC || (defined(BIG_ENDIAN) && BIG_ENDIAN + 0 != 4321)
+#   define BLARGG_BIG_ENDIAN 1
+#  elif !defined (__mips__)
+// No endian specified; assume little-endian, since it's most common
+#   define BLARGG_LITTLE_ENDIAN 1
+#  endif
+# endif
 #endif
 
 #if BLARGG_LITTLE_ENDIAN && BLARGG_BIG_ENDIAN
-	#undef BLARGG_LITTLE_ENDIAN
-	#undef BLARGG_BIG_ENDIAN
+# undef BLARGG_LITTLE_ENDIAN
+# undef BLARGG_BIG_ENDIAN
 #endif
 
 inline void blargg_verify_byte_order()
 {
-	#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
+#ifndef NDEBUG
+	volatile int i = 1;
+	assert(*reinterpret_cast<volatile char *>(&i));
+#endif
 }
 
-inline unsigned get_le16( void const* p )
+inline unsigned get_le16(const uint8_t *p)
 {
-	return  (unsigned) ((unsigned char const*) p) [1] << 8 |
-			(unsigned) ((unsigned char const*) p) [0];
+	return static_cast<unsigned>(p[1] << 8) | static_cast<unsigned>(p[0]);
 }
 
-inline unsigned get_be16( void const* p )
+inline void set_le16(uint8_t *p, unsigned n)
 {
-	return  (unsigned) ((unsigned char const*) p) [0] << 8 |
-			(unsigned) ((unsigned char const*) p) [1];
+	p[1] = static_cast<unsigned char>(n >> 8);
+	p[0] = static_cast<unsigned char>(n);
 }
-
-inline blargg_ulong get_le32( void const* p )
-{
-	return  (blargg_ulong) ((unsigned char const*) p) [3] << 24 |
-			(blargg_ulong) ((unsigned char const*) p) [2] << 16 |
-			(blargg_ulong) ((unsigned char const*) p) [1] <<  8 |
-			(blargg_ulong) ((unsigned char const*) p) [0];
-}
-
-inline blargg_ulong get_be32( void const* p )
-{
-	return  (blargg_ulong) ((unsigned char const*) p) [0] << 24 |
-			(blargg_ulong) ((unsigned char const*) p) [1] << 16 |
-			(blargg_ulong) ((unsigned char const*) p) [2] <<  8 |
-			(blargg_ulong) ((unsigned char const*) p) [3];
-}
-
-inline void set_le16( void* p, unsigned n )
-{
-	((unsigned char*) p) [1] = (unsigned char) (n >> 8);
-	((unsigned char*) p) [0] = (unsigned char) n;
-}
-
-inline void set_be16( void* p, unsigned n )
-{
-	((unsigned char*) p) [0] = (unsigned char) (n >> 8);
-	((unsigned char*) p) [1] = (unsigned char) n;
-}
-
-inline void set_le32( void* p, blargg_ulong n )
-{
-	((unsigned char*) p) [0] = (unsigned char) n;
-	((unsigned char*) p) [1] = (unsigned char) (n >> 8);
-	((unsigned char*) p) [2] = (unsigned char) (n >> 16);
-	((unsigned char*) p) [3] = (unsigned char) (n >> 24);
-}
-
-inline void set_be32( void* p, blargg_ulong n )
-{
-	((unsigned char*) p) [3] = (unsigned char) n;
-	((unsigned char*) p) [2] = (unsigned char) (n >> 8);
-	((unsigned char*) p) [1] = (unsigned char) (n >> 16);
-	((unsigned char*) p) [0] = (unsigned char) (n >> 24);
-}
-
-#if BLARGG_NONPORTABLE
-	// Optimized implementation if byte order is known
-	#if 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 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))
-		
-		#if BLARGG_CPU_POWERPC
-			// PowerPC has special byte-reversed instructions
-			#if defined (__MWERKS__)
-				#define GET_LE16( addr )        (__lhbrx( addr, 0 ))
-				#define GET_LE32( addr )        (__lwbrx( addr, 0 ))
-				#define SET_LE16( addr, in )    (__sthbrx( in, addr, 0 ))
-				#define SET_LE32( addr, in )    (__stwbrx( in, addr, 0 ))
-			#elif defined (__GNUC__)
-				#define GET_LE16( addr )        ({unsigned ppc_lhbrx_; asm( "lhbrx %0,0,%1" : "=r" (ppc_lhbrx_) : "r" (addr), "0" (ppc_lhbrx_) ); ppc_lhbrx_;})
-				#define GET_LE32( addr )        ({unsigned ppc_lwbrx_; asm( "lwbrx %0,0,%1" : "=r" (ppc_lwbrx_) : "r" (addr), "0" (ppc_lwbrx_) ); ppc_lwbrx_;})
-				#define SET_LE16( addr, in )    ({asm( "sthbrx %0,0,%1" : : "r" (in), "r" (addr) );})
-				#define SET_LE32( addr, in )    ({asm( "stwbrx %0,0,%1" : : "r" (in), "r" (addr) );})
-			#endif
-		#endif
-	#endif
-#endif
-
-#ifndef GET_LE16
-	#define GET_LE16( addr )        get_le16( addr )
-	#define SET_LE16( addr, data )  set_le16( addr, data )
-#endif
-
-#ifndef GET_LE32
-	#define GET_LE32( addr )        get_le32( addr )
-	#define SET_LE32( addr, data )  set_le32( addr, data )
-#endif
-
-#ifndef GET_BE16
-	#define GET_BE16( addr )        get_be16( addr )
-	#define SET_BE16( addr, data )  set_be16( addr, data )
-#endif
-
-#ifndef GET_BE32
-	#define GET_BE32( addr )        get_be32( addr )
-	#define SET_BE32( addr, data )  set_be32( addr, data )
-#endif
-
-// auto-selecting versions
-
-inline void set_le( BOOST::uint16_t* p, unsigned     n ) { SET_LE16( p, n ); }
-inline void set_le( BOOST::uint32_t* p, blargg_ulong n ) { SET_LE32( p, n ); }
-inline void set_be( BOOST::uint16_t* p, unsigned     n ) { SET_BE16( p, n ); }
-inline void set_be( BOOST::uint32_t* p, blargg_ulong n ) { SET_BE32( p, n ); }
-inline unsigned     get_le( BOOST::uint16_t* p ) { return GET_LE16( p ); }
-inline blargg_ulong get_le( BOOST::uint32_t* p ) { return GET_LE32( p ); }
-inline unsigned     get_be( BOOST::uint16_t* p ) { return GET_BE16( p ); }
-inline blargg_ulong get_be( BOOST::uint32_t* p ) { return GET_BE32( p ); }
 
 #endif
 

--- a/src/in_snsf/snes9x/apu/blargg_source.h
+++ /dev/null
@@ -1,101 +1,1 @@
-/* Included at the beginning of library source files, after all other #include lines.
-Sets up helpful macros and services used in my source code. They don't need
-module an annoying module prefix on their names since they are defined after
-all other #include lines. */
 
-// snes_spc 0.9.0
-#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, ... );
-static inline void blargg_dprintf_( const char*, ... ) { }
-#undef dprintf
-#define dprintf (1) ? (void) 0 : blargg_dprintf_
-
-// 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 )
-
-// Avoid any macros which evaluate their arguments multiple times
-#undef min
-#undef max
-
-#define DEF_MIN_MAX( type ) \
-	static inline type min( type x, type y ) { if ( x < y ) return x; return y; }\
-	static inline type max( type x, type y ) { if ( y < x ) return x; return y; }
-
-DEF_MIN_MAX( int )
-DEF_MIN_MAX( unsigned )
-DEF_MIN_MAX( long )
-DEF_MIN_MAX( unsigned long )
-DEF_MIN_MAX( float )
-DEF_MIN_MAX( double )
-
-#undef DEF_MIN_MAX
-
-/*
-// using const references generates crappy code, and I am currenly only using these
-// for built-in types, so they take arguments by value
-
-// TODO: remove
-inline int min( int x, int y ) 
-template<class T>
-inline T min( T x, T y )
-{
-	if ( x < y )
-		return x;
-	return y;
-}
-
-template<class T>
-inline T max( T x, T y )
-{
-	if ( x < y )
-		return y;
-	return x;
-}
-*/
-
-// 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
-

--- a/src/in_snsf/snes9x/apu/bspline_resampler.h
+++ b/src/in_snsf/snes9x/apu/bspline_resampler.h
@@ -5,9 +5,6 @@
 
 #include <cmath>
 #include "resampler.h"
-
-#undef CLAMP
-#undef SHORT_CLAMP
 
 class BsplineResampler : public Resampler
 {
@@ -47,7 +44,7 @@
 
 	void clear()
 	{
-		ring_buffer::clear ();
+		ring_buffer::clear();
 		this->r_frac = 1.0;
 		this->r_left[0] = this->r_left[1] = this->r_left[2] = this->r_left[3] = this->r_left[4] = this->r_left[5] = 0;
 		this->r_right[0] = this->r_right[1] = this->r_right[2] = this->r_right[3] = this->r_right[4] = this->r_right[5] = 0;
@@ -65,7 +62,7 @@
 			int s_left = internal_buffer[i_position];
 			int s_right = internal_buffer[i_position + 1];
 			int max_samples = this->buffer_size >> 1;
-			const double margin_of_error = 1.0e-10;
+			static const double margin_of_error = 1.0e-10;
 
 			if (std::abs(this->r_step - 1.0) < margin_of_error)
 			{
@@ -122,7 +119,7 @@
 			this->start -= this->buffer_size;
 	}
 
-	inline int avail()
+	int avail()
 	{
 		return static_cast<int>(std::floor(((this->size >> 2) - this->r_frac) / this->r_step) * 2);
 	}

--- a/src/in_snsf/snes9x/apu/hermite_resampler.h
+++ b/src/in_snsf/snes9x/apu/hermite_resampler.h
@@ -3,142 +3,131 @@
 #ifndef __HERMITE_RESAMPLER_H
 #define __HERMITE_RESAMPLER_H
 
+#include <cmath>
 #include "resampler.h"
-
-#undef CLAMP
-#undef SHORT_CLAMP
-#define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
-#define SHORT_CLAMP(n) ((short) CLAMP((n), -32768, 32767))
 
 class HermiteResampler : public Resampler
 {
-    protected:
+protected:
+	double r_step;
+	double r_frac;
+	int r_left[4], r_right[4];
 
-        double r_step;
-        double r_frac;
-        int    r_left[4], r_right[4];
+	template<typename T1, typename T2> static T1 CLAMP(T1 x, T2 low, T2 high) { return x > high ? high : (x < low ? low : x); }
+	template<typename T> static short SHORT_CLAMP(T n) { return static_cast<short>(CLAMP(n, -32768, 32767)); }
 
-        double
-        hermite (double mu1, double a, double b, double c, double d)
-        {
-            const double tension = 0.0; //-1 = low, 0 = normal, 1 = high
-            const double bias    = 0.0; //-1 = left, 0 = even, 1 = right
+	double hermite(double mu1, double a, double b, double c, double d)
+	{
+		static const double tension = 0.0; //-1 = low, 0 = normal, 1 = high
+		static const double bias = 0.0; //-1 = left, 0 = even, 1 = right
 
-            double mu2, mu3, m0, m1, a0, a1, a2, a3;
+		double mu2, mu3, m0, m1, a0, a1, a2, a3;
 
-            mu2 = mu1 * mu1;
-            mu3 = mu2 * mu1;
+		mu2 = mu1 * mu1;
+		mu3 = mu2 * mu1;
 
-            m0  = (b - a) * (1 + bias) * (1 - tension) / 2;
-            m0 += (c - b) * (1 - bias) * (1 - tension) / 2;
-            m1  = (c - b) * (1 + bias) * (1 - tension) / 2;
-            m1 += (d - c) * (1 - bias) * (1 - tension) / 2;
+		m0  = (b - a) * (1 + bias) * (1 - tension) / 2;
+		m0 += (c - b) * (1 - bias) * (1 - tension) / 2;
+		m1  = (c - b) * (1 + bias) * (1 - tension) / 2;
+		m1 += (d - c) * (1 - bias) * (1 - tension) / 2;
 
-            a0 = +2 * mu3 - 3 * mu2 + 1;
-            a1 =      mu3 - 2 * mu2 + mu1;
-            a2 =      mu3 -     mu2;
-            a3 = -2 * mu3 + 3 * mu2;
+		a0 = 2 * mu3 - 3 * mu2 + 1;
+		a1 = mu3 - 2 * mu2 + mu1;
+		a2 = mu3 - mu2;
+		a3 = -2 * mu3 + 3 * mu2;
 
-            return (a0 * b) + (a1 * m0) + (a2 * m1) + (a3 * c);
-        }
+		return (a0 * b) + (a1 * m0) + (a2 * m1) + (a3 * c);
+	}
 
-    public:
-        HermiteResampler (int num_samples) : Resampler (num_samples)
-        {
-            clear ();
-        }
+public:
+	HermiteResampler(int num_samples) : Resampler(num_samples)
+	{
+		this->clear();
+	}
 
-        ~HermiteResampler ()
-        {
-        }
+	void time_ratio(double ratio)
+	{
+		this->r_step = ratio;
+		this->clear();
+	}
 
-        void
-        time_ratio (double ratio)
-        {
-            r_step = ratio;
-            clear ();
-        }
+	void clear()
+	{
+		ring_buffer::clear();
+		this->r_frac = 1.0;
+		this->r_left[0] = this->r_left[1] = this->r_left[2] = this->r_left[3] = 0;
+		this->r_right[0] = this->r_right[1] = this->r_right[2] = this->r_right[3] = 0;
+	}
 
-        void
-        clear()
-        {
-            ring_buffer::clear ();
-            r_frac = 1.0;
-            r_left [0] = r_left [1] = r_left [2] = r_left [3] = 0;
-            r_right[0] = r_right[1] = r_right[2] = r_right[3] = 0;
-        }
+	void read(short *data, int num_samples)
+	{
+		int i_position = this->start >> 1;
+		short *internal_buffer = reinterpret_cast<short *>(this->buffer);
+		int o_position = 0;
+		int consumed = 0;
 
-        void
-        read (short *data, int num_samples)
-        {
-            int i_position = start >> 1;
-            short *internal_buffer = (short *) buffer;
-            int o_position = 0;
-            int consumed = 0;
+		while (o_position < num_samples && consumed < this->buffer_size)
+		{
+			int s_left = internal_buffer[i_position];
+			int s_right = internal_buffer[i_position + 1];
+			int max_samples = this->buffer_size >> 1;
+			static const double margin_of_error = 1.0e-10;
 
-            while (o_position < num_samples && consumed < buffer_size)
-            {
-                int s_left = internal_buffer[i_position];
-                int s_right = internal_buffer[i_position + 1];
-                int max_samples = buffer_size >> 1;
-                const double margin_of_error = 1.0e-10;
+			if (std::abs(this->r_step - 1.0) < margin_of_error)
+			{
+				data[o_position] = static_cast<short>(s_left);
+				data[o_position + 1] = static_cast<short>(s_right);
 
-                if (fabs(r_step - 1.0) < margin_of_error)
-                {
-                    data[o_position] = (short) s_left;
-                    data[o_position + 1] = (short) s_right;
+				o_position += 2;
+				i_position += 2;
+				if (i_position >= max_samples)
+					i_position -= max_samples;
+				consumed += 2;
 
-                    o_position += 2;
-                    i_position += 2;
-                    if (i_position >= max_samples)
-                        i_position -= max_samples;
-                    consumed += 2;
+				continue;
+			}
 
-                    continue;
-                }
+			while (this->r_frac <= 1.0 && o_position < num_samples)
+			{
+				data[o_position] = SHORT_CLAMP(hermite(this->r_frac, this->r_left[0], this->r_left[1], this->r_left[2], this->r_left[3]));
+				data[o_position + 1] = SHORT_CLAMP(hermite(this->r_frac, this->r_right[0], this->r_right[1], this->r_right[2], this->r_right[3]));
 
-                while (r_frac <= 1.0 && o_position < num_samples)
-                {
-                    data[o_position]     = SHORT_CLAMP (hermite (r_frac, r_left [0], r_left [1], r_left [2], r_left [3]));
-                    data[o_position + 1] = SHORT_CLAMP (hermite (r_frac, r_right[0], r_right[1], r_right[2], r_right[3]));
+				o_position += 2;
 
-                    o_position += 2;
+				this->r_frac += this->r_step;
+			}
 
-                    r_frac += r_step;
-                }
+			if (this->r_frac > 1.0)
+			{
+				this->r_left[0] = this->r_left[1];
+				this->r_left[1] = this->r_left[2];
+				this->r_left[2] = this->r_left[3];
+				this->r_left[3] = s_left;
 
-                if (r_frac > 1.0)
-                {
-                    r_left [0] = r_left [1];
-                    r_left [1] = r_left [2];
-                    r_left [2] = r_left [3];
-                    r_left [3] = s_left;
-    
-                    r_right[0] = r_right[1];
-                    r_right[1] = r_right[2];
-                    r_right[2] = r_right[3];
-                    r_right[3] = s_right;                    
-                    
-                    r_frac -= 1.0;
-                    
-                    i_position += 2;
-                    if (i_position >= max_samples)
-                        i_position -= max_samples;
-                    consumed += 2;
-                }
-            }
+				this->r_right[0] = this->r_right[1];
+				this->r_right[1] = this->r_right[2];
+				this->r_right[2] = this->r_right[3];
+				this->r_right[3] = s_right;
 
-            size -= consumed << 1;
-            start += consumed << 1;
-            if (start >= buffer_size)
-                start -= buffer_size;
-        }
+				this->r_frac -= 1.0;
 
-        inline int
-        avail()
-        {
-            return (int) floor (((size >> 2) - r_frac) / r_step) * 2;
-        }
+				i_position += 2;
+				if (i_position >= max_samples)
+					i_position -= max_samples;
+				consumed += 2;
+			}
+		}
+
+		this->size -= consumed << 1;
+		this->start += consumed << 1;
+		if (this->start >= this->buffer_size)
+			this->start -= this->buffer_size;
+	}
+
+	int avail()
+	{
+		return static_cast<int>(std::floor(((this->size >> 2) - this->r_frac) / this->r_step) * 2);
+	}
 };
 
 #endif /* __HERMITE_RESAMPLER_H */

--- a/src/in_snsf/snes9x/apu/linear_resampler.h
+++ b/src/in_snsf/snes9x/apu/linear_resampler.h
@@ -4,112 +4,99 @@
 #define __LINEAR_RESAMPLER_H
 
 #include "resampler.h"
-#include "../snes9x.h"
 
-static const int    f_prec = 15;
-static const uint32_t f__one = (1 << f_prec);
-
-#define lerp(t, a, b) (((((b) - (a)) * (t)) >> f_prec) + (a))
+const int f_prec = 15;
+const uint32_t f__one = 1 << f_prec;
 
 class LinearResampler : public Resampler
 {
-    protected:
-        uint32_t f__r_step;
-        uint32_t f__inv_r_step;
-        uint32_t f__r_frac;
-        int    r_left, r_right;
+protected:
+	uint32_t f__r_step;
+	uint32_t f__inv_r_step;
+	uint32_t f__r_frac;
+	int r_left, r_right;
 
-    public:
-        LinearResampler (int num_samples) : Resampler (num_samples)
-        {
-            f__r_frac = 0;
-        }
+	static short lerp(uint32_t t, int a, short b) { return (((b - a) * t) >> f_prec) + a; }
 
-        ~LinearResampler ()
-        {
-        }
+public:
+	LinearResampler(int num_samples) : Resampler(num_samples)
+	{
+		this->f__r_frac = 0;
+	}
 
-        void
-        time_ratio (double ratio)
-        {
-            if (ratio == 0.0)
-                ratio = 1.0;
-            f__r_step = (uint32_t) (ratio * f__one);
-            f__inv_r_step = (uint32_t) (f__one / ratio);
-            clear ();
-        }
+	void time_ratio(double ratio)
+	{
+		if (!ratio)
+			ratio = 1.0;
+		this->f__r_step = static_cast<uint32_t>(ratio * f__one);
+		this->f__inv_r_step = static_cast<uint32_t>(f__one / ratio);
+		this->clear();
+	}
 
-        void
-        clear()
-        {
-            ring_buffer::clear ();
-            f__r_frac = 0;
-            r_left = 0;
-            r_right = 0;
-        }
+	void clear()
+	{
+		ring_buffer::clear();
+		this->f__r_frac = 0;
+		this->r_left = 0;
+		this->r_right = 0;
+	}
 
-        void
-        read (short *data, int num_samples)
-        {
-            int i_position = start >> 1;
-            short *internal_buffer = (short *) buffer;
-            int o_position = 0;
-            int consumed = 0;
-            int max_samples = (buffer_size >> 1);
+	void read(short *data, int num_samples)
+	{
+		int i_position = this->start >> 1;
+		short *internal_buffer = reinterpret_cast<short *>(this->buffer);
+		int o_position = 0;
+		int consumed = 0;
+		int max_samples = this->buffer_size >> 1;
 
-            while (o_position < num_samples && consumed < buffer_size)
-            {
-                if (f__r_step == f__one)
-                {
-                    data[o_position] = internal_buffer[i_position];
-                    data[o_position + 1] = internal_buffer[i_position + 1];
+		while (o_position < num_samples && consumed < this->buffer_size)
+		{
+			if (this->f__r_step == f__one)
+			{
+				data[o_position] = internal_buffer[i_position];
+				data[o_position + 1] = internal_buffer[i_position + 1];
 
-                    o_position += 2;
-                    i_position += 2;
-                    if (i_position >= max_samples)
-                        i_position -= max_samples;
-                    consumed += 2;
+				o_position += 2;
+				i_position += 2;
+				if (i_position >= max_samples)
+					i_position -= max_samples;
+				consumed += 2;
 
-                    continue;
-                }
+				continue;
+			}
 
-                while (f__r_frac <= f__one  && o_position < num_samples)
-                {
-                    data[o_position]     = lerp (f__r_frac,
-                                                 r_left,
-                                                 internal_buffer[i_position]);
-                    data[o_position + 1] = lerp (f__r_frac,
-                                                 r_right,
-                                                 internal_buffer[i_position + 1]);
+			while (this->f__r_frac <= f__one && o_position < num_samples)
+			{
+				data[o_position] = lerp(this->f__r_frac, this->r_left, internal_buffer[i_position]);
+				data[o_position + 1] = lerp(this->f__r_frac, this->r_right, internal_buffer[i_position + 1]);
 
-                    o_position += 2;
+				o_position += 2;
 
-                    f__r_frac += f__r_step;
-                }
+				this->f__r_frac += this->f__r_step;
+			}
 
-                if (f__r_frac > f__one)
-                {
-                    f__r_frac -= f__one;
-                    r_left = internal_buffer[i_position];
-                    r_right = internal_buffer[i_position + 1];
-                    i_position += 2;
-                    if (i_position >= max_samples)
-                        i_position -= max_samples;
-                    consumed += 2;
-                }
-            }
+			if (this->f__r_frac > f__one)
+			{
+				this->f__r_frac -= f__one;
+				this->r_left = internal_buffer[i_position];
+				this->r_right = internal_buffer[i_position + 1];
+				i_position += 2;
+				if (i_position >= max_samples)
+					i_position -= max_samples;
+				consumed += 2;
+			}
+		}
 
-            size -= consumed << 1;
-            start += consumed << 1;
-            if (start >= buffer_size)
-                start -= buffer_size;
-        }
+		this->size -= consumed << 1;
+		this->start += consumed << 1;
+		if (this->start >= this->buffer_size)
+			this->start -= this->buffer_size;
+	}
 
-        inline int
-        avail()
-        {
-            return (((size >> 2) * f__inv_r_step) - ((f__r_frac * f__inv_r_step) >> f_prec)) >> (f_prec - 1);
-        }
+	int avail()
+	{
+		return (((this->size >> 2) * this->f__inv_r_step) - ((this->f__r_frac * this->f__inv_r_step) >> f_prec)) >> (f_prec - 1);
+	}
 };
 
 #endif /* __LINEAR_RESAMPLER_H */

--- a/src/in_snsf/snes9x/apu/osculating_resampler.h
+++ b/src/in_snsf/snes9x/apu/osculating_resampler.h
@@ -5,9 +5,6 @@
 
 #include <cmath>
 #include "resampler.h"
-
-#undef CLAMP
-#undef SHORT_CLAMP
 
 class OsculatingResampler : public Resampler
 {
@@ -48,7 +45,7 @@
 
 	void clear()
 	{
-		ring_buffer::clear ();
+		ring_buffer::clear();
 		this->r_frac = 1.0;
 		this->r_left[0] = this->r_left[1] = this->r_left[2] = this->r_left[3] = this->r_left[4] = this->r_left[5] = 0;
 		this->r_right[0] = this->r_right[1] = this->r_right[2] = this->r_right[3] = this->r_right[4] = this->r_right[5] = 0;
@@ -66,7 +63,7 @@
 			int s_left = internal_buffer[i_position];
 			int s_right = internal_buffer[i_position + 1];
 			int max_samples = this->buffer_size >> 1;
-			const double margin_of_error = 1.0e-10;
+			static const double margin_of_error = 1.0e-10;
 
 			if (std::abs(this->r_step - 1.0) < margin_of_error)
 			{
@@ -123,7 +120,7 @@
 			this->start -= this->buffer_size;
 	}
 
-	inline int avail()
+	int avail()
 	{
 		return static_cast<int>(std::floor(((this->size >> 2) - this->r_frac) / this->r_step) * 2);
 	}

--- a/src/in_snsf/snes9x/apu/resampler.h
+++ b/src/in_snsf/snes9x/apu/resampler.h
@@ -7,54 +7,39 @@
 
 class Resampler : public ring_buffer
 {
-    public:
-        virtual void clear()        = 0;
-        virtual void time_ratio (double) = 0;
-        virtual void read (short *, int) = 0;
-        virtual int  avail()        = 0;
-    
-        Resampler (int num_samples) : ring_buffer (num_samples << 1)
-        {
-        }
+public:
+	virtual void clear() = 0;
+	virtual void time_ratio(double) = 0;
+	virtual void read(short *, int) = 0;
+	virtual int avail() = 0;
 
-        ~Resampler ()
-        {
-        }
+	Resampler(int num_samples) : ring_buffer(num_samples << 1)
+	{
+	}
 
-        inline bool
-        push (short *src, int num_samples)
-        {
-            if (max_write () < num_samples)
-                return false;
+	virtual ~Resampler()
+	{
+	}
 
-            !num_samples || ring_buffer::push ((unsigned char *) src, num_samples << 1);
+	bool push(short *src, int num_samples)
+	{
+		if (this->max_write() < num_samples)
+			return false;
 
-            return true;
-        }
+		!num_samples || ring_buffer::push(reinterpret_cast<unsigned char *>(src), num_samples << 1);
 
-        inline int
-        space_empty()
-        {
-            return buffer_size - size;
-        }
-    
-        inline int
-        space_filled()
-        {
-            return size;
-        }
-        
-        inline int
-        max_write()
-        {
-            return space_empty () >> 1;
-        }
+		return true;
+	}
 
-        inline void
-        resize (int num_samples)
-        {
-            ring_buffer::resize (num_samples << 1);
-        }
+	int max_write()
+	{
+		return this->space_empty () >> 1;
+	}
+
+	void resize(int num_samples)
+	{
+		ring_buffer::resize(num_samples << 1);
+	}
 };
 
 #endif /* __RESAMPLER_H */

--- a/src/in_snsf/snes9x/apu/ring_buffer.h
+++ b/src/in_snsf/snes9x/apu/ring_buffer.h
@@ -3,109 +3,75 @@
 #ifndef __RING_BUFFER_H
 #define __RING_BUFFER_H
 
-#include <string.h>
-
-#undef MIN
-#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#include <algorithm>
+#include <cstring>
 
 class ring_buffer
 {
 protected:
-    int size;
-    int buffer_size;
-    int start;
-    unsigned char *buffer;
+	int size;
+	int buffer_size;
+	int start;
+	unsigned char *buffer;
 
 public:
-    ring_buffer (int buffer_size)
-    {
-        this->buffer_size = buffer_size;
-        buffer = new unsigned char[this->buffer_size];
-        memset (buffer, 0, this->buffer_size);
+	ring_buffer(int buffer_size)
+	{
+		this->buffer_size = buffer_size;
+		this->buffer = new unsigned char[this->buffer_size];
+		std::fill(&this->buffer[0], &this->buffer[this->buffer_size], 0);
 
-        size = 0;
-        start = 0;
-    }
+		this->size = this->start = 0;
+	}
 
-    ~ring_buffer()
-    {
-        delete[] buffer;
-    }
+	~ring_buffer()
+	{
+		delete[] buffer;
+	}
 
-    bool
-    push (unsigned char *src, int bytes)
-    {
-        if (space_empty () < bytes)
-            return false;
+	bool push(unsigned char *src, int bytes)
+	{
+		if (this->space_empty() < bytes)
+			return false;
 
-        int end = (start + size) % buffer_size;
-        int first_write_size = MIN (bytes, buffer_size - end);
+		int end = (this->start + this->size) % this->buffer_size;
+		int first_write_size = std::min(bytes, this->buffer_size - end);
 
-        memcpy (buffer + end, src, first_write_size);
+		std::copy(&src[0], &src[first_write_size], &this->buffer[end]);
 
-        if (bytes > first_write_size)
-            memcpy (buffer, src + first_write_size, bytes - first_write_size);
+		if (bytes > first_write_size)
+			std::copy(&src[first_write_size], &src[bytes], &this->buffer[0]);
 
-        size += bytes;
+		this->size += bytes;
 
-        return true;
-    }
+		return true;
+	}
 
-    bool
-    pull (unsigned char *dst, int bytes)
-    {
-        if (space_filled () < bytes)
-            return false;
+	int space_empty()
+	{
+		return this->buffer_size - this->size;
+	}
 
-        memcpy (dst, buffer + start, MIN (bytes, buffer_size - start));
+	int space_filled()
+	{
+		return this->size;
+	}
 
-        if (bytes > (buffer_size - start))
-            memcpy (dst + (buffer_size - start), buffer, bytes - (buffer_size - start));
+	void clear()
+	{
+		this->start = this->size = 0;
+		std::fill(&this->buffer[0], &this->buffer[this->buffer_size], 0);
+	}
 
-        start = (start + bytes) % buffer_size;
-        size -= bytes;
+	void resize(int size)
+	{
+		delete[] this->buffer;
+		this->buffer_size = size;
+		this->buffer = new unsigned char[this->buffer_size];
+		std::fill(&this->buffer[0], &this->buffer[this->buffer_size], 0);
 
-        return true;
-    }
-
-    inline int
-    space_empty()
-    {
-        return buffer_size - size;
-    }
-
-    inline int
-    space_filled()
-    {
-        return size;
-    }
-
-    void
-    clear()
-    {
-        start = 0;
-        size = 0;
-        memset (buffer, 0, buffer_size);
-    }
-
-    void
-    resize (int size)
-    {
-        delete[] buffer;
-        buffer_size = size;
-        buffer = new unsigned char[buffer_size];
-        memset (buffer, 0, this->buffer_size);
-
-        size = 0;
-        start = 0;
-    }
-
-    inline void
-    cache_silence()
-    {
-        clear ();
-        size = buffer_size;
-    }
+		this->size = this->start = 0;
+	}
 };
 
 #endif

--- a/src/in_snsf/snes9x/apu/sinc_resampler.h
+++ b/src/in_snsf/snes9x/apu/sinc_resampler.h
@@ -7,9 +7,6 @@
 #define _USE_MATH_DEFINES
 #include <cmath>
 #include "resampler.h"
-
-#undef CLAMP
-#undef SHORT_CLAMP
 
 #ifndef M_PI
 const double M_PI = 3.14159265358979323846;
@@ -82,7 +79,7 @@
 
 	void clear()
 	{
-		ring_buffer::clear ();
+		ring_buffer::clear();
 		this->r_frac = 1.0;
 		std::fill(&this->r_left[0], &this->r_left[SINC_WIDTH * 2], 0);
 		std::fill(&this->r_right[0], &this->r_right[SINC_WIDTH * 2], 0);
@@ -100,7 +97,7 @@
 			int s_left = internal_buffer[i_position];
 			int s_right = internal_buffer[i_position + 1];
 			int max_samples = this->buffer_size >> 1;
-			const double margin_of_error = 1.0e-10;
+			static const double margin_of_error = 1.0e-10;
 
 			if (std::abs(this->r_step - 1.0) < margin_of_error)
 			{
@@ -149,7 +146,7 @@
 			this->start -= this->buffer_size;
 	}
 
-	inline int avail()
+	int avail()
 	{
 		return static_cast<int>(std::floor(((this->size >> 2) - this->r_frac) / this->r_step) * 2);
 	}

--- a/src/in_snsf/snes9x/cpu.cpp
+++ b/src/in_snsf/snes9x/cpu.cpp
@@ -175,64 +175,42 @@
   Nintendo Co., Limited and its subsidiary companies.
  ***********************************************************************************/
 
+#include <algorithm>
 #include "snes9x.h"
 #include "memmap.h"
 #include "dma.h"
 #include "apu/apu.h"
-//#include "fxemu.h"
-#include "sdd1.h"
-//#include "srtc.h"
-//#include "snapshot.h"
-//#include "cheats.h"
-//#include "logger.h"
-#ifdef DEBUGGER
-#include "debug.h"
-#endif
-
-//static void S9xResetCPU();
-//static void S9xSoftResetCPU();
 
 static void S9xSoftResetCPU()
 {
 	CPU.Cycles = 182; // Or 188. This is the cycle count just after the jump to the Reset Vector.
 	CPU.PrevCycles = CPU.Cycles;
 	CPU.V_Counter = 0;
-	CPU.Flags = CPU.Flags & (DEBUG_MODE_FLAG | TRACE_FLAG);
-	CPU.PCBase = NULL;
-	CPU.NMILine = false;
-	CPU.IRQLine = false;
-	CPU.IRQTransition = false;
-	CPU.IRQLastState = false;
-	CPU.IRQExternal = false;
+	CPU.Flags &= DEBUG_MODE_FLAG | TRACE_FLAG;
+	CPU.PCBase = nullptr;
+	CPU.NMILine = CPU.IRQLine = CPU.IRQTransition = CPU.IRQLastState = false;
 	CPU.IRQPending = Timings.IRQPendCount;
 	CPU.MemSpeed = SLOW_ONE_CYCLE;
 	CPU.MemSpeedx2 = SLOW_ONE_CYCLE * 2;
 	CPU.FastROMSpeed = SLOW_ONE_CYCLE;
-	CPU.InDMA = false;
-	CPU.InHDMA = false;
-	CPU.InDMAorHDMA = false;
-	CPU.InWRAMDMAorHDMA = false;
+	CPU.InDMA = CPU.InHDMA = CPU.InDMAorHDMA = CPU.InWRAMDMAorHDMA = false;
 	CPU.HDMARanInDMA = 0;
 	CPU.CurrentDMAorHDMAChannel = -1;
 	CPU.WhichEvent = HC_RENDER_EVENT;
 	CPU.NextEvent  = Timings.RenderPos;
 	CPU.WaitingForInterrupt = false;
-	CPU.AutoSaveTimer = 0;
-	CPU.SRAMModified = false;
-
-	Registers.PBPC = 0;
-	Registers.PB = 0;
-	Registers.PCw = S9xGetWord(0xfffc);
-	OpenBus = Registers.PCh;
+
+	Registers.PC.xPBPC = 0;
+	Registers.PC.B.xPB = 0;
+	Registers.PC.W.xPC = S9xGetWord(0xfffc);
+	OpenBus = Registers.PC.B.xPCh;
 	Registers.D.W = 0;
 	Registers.DB = 0;
-	Registers.SH = 1;
-	Registers.SL -= 3;
-	Registers.XH = 0;
-	Registers.YH = 0;
-
-	ICPU.ShiftedPB = 0;
-	ICPU.ShiftedDB = 0;
+	Registers.S.B.h = 1;
+	Registers.S.B.l -= 3;
+	Registers.X.B.h = Registers.Y.B.h = 0;
+
+	ICPU.ShiftedPB = ICPU.ShiftedDB = 0;
 	SetFlags(MemoryFlag | IndexFlag | IRQ | Emulation);
 	ClearFlags(Decimal);
 
@@ -245,7 +223,7 @@
 	else
 		Timings.WRAMRefreshPos = SNES_WRAM_REFRESH_HC_v1;
 
-	S9xSetPCBase(Registers.PBPC);
+	S9xSetPCBase(Registers.PC.xPBPC);
 
 	ICPU.S9xOpcodes = S9xOpcodesE1;
 	ICPU.S9xOpLengths = S9xOpLengthsM1X1;
@@ -256,83 +234,21 @@
 static void S9xResetCPU()
 {
 	S9xSoftResetCPU();
-	Registers.SL = 0xff;
-	Registers.P.W = 0;
-	Registers.A.W = 0;
-	Registers.X.W = 0;
-	Registers.Y.W = 0;
+	Registers.S.B.l = 0xff;
+	Registers.P.W = Registers.A.W = Registers.X.W = Registers.Y.W = 0;
 	SetFlags(MemoryFlag | IndexFlag | IRQ | Emulation);
 	ClearFlags(Decimal);
 }
 
 void S9xReset()
 {
-	/*S9xResetSaveTimer(false);
-	S9xResetLogger();*/
-
-	memset(Memory.RAM, 0x55, 0x20000);
-	memset(Memory.VRAM, 0x00, 0x10000);
-	ZeroMemory(Memory.FillRAM, 0x8000);
-
-	/*if (Settings.BS)
-		S9xResetBSX();*/
+	std::fill(&Memory.RAM[0], &Memory.RAM[0x20000], 0x55);
+	std::fill(&Memory.VRAM[0], &Memory.VRAM[0x10000], 0);
+	std::fill(&Memory.FillRAM[0], &Memory.FillRAM[0x8000], 0);
 
 	S9xResetCPU();
 	S9xResetPPU();
 	S9xResetDMA();
 	S9xResetAPU();
-
-	/*if (Settings.DSP)
-		S9xResetDSP();
-	if (Settings.SuperFX)
-		S9xResetSuperFX();
-	if (Settings.SA1)
-		S9xSA1Init();*/
-	if (Settings.SDD1)
-		S9xResetSDD1();
-	/*if (Settings.SPC7110)
-		S9xResetSPC7110();
-	if (Settings.C4)
-		S9xInitC4();
-	if (Settings.OBC1)
-		S9xResetOBC1();
-	if (Settings.SRTC)
-		S9xResetSRTC();
-
-	S9xInitCheatData();*/
 }
 
-void S9xSoftReset()
-{
-	//S9xResetSaveTimer(false);
-
-	ZeroMemory(Memory.FillRAM, 0x8000);
-
-	/*if (Settings.BS)
-		S9xResetBSX();*/
-
-	S9xSoftResetCPU();
-	S9xSoftResetPPU();
-	S9xResetDMA();
-	S9xSoftResetAPU();
-
-	/*if (Settings.DSP)
-		S9xResetDSP();
-	if (Settings.SuperFX)
-		S9xResetSuperFX();
-	if (Settings.SA1)
-		S9xSA1Init();*/
-	if (Settings.SDD1)
-		S9xResetSDD1();
-	/*if (Settings.SPC7110)
-		S9xResetSPC7110();
-	if (Settings.C4)
-		S9xInitC4();
-	if (Settings.OBC1)
-		S9xResetOBC1();
-	if (Settings.SRTC)
-		S9xResetSRTC();
-
-	S9xInitCheatData();*/
-}
-

--- a/src/in_snsf/snes9x/cpuaddr.h
+++ b/src/in_snsf/snes9x/cpuaddr.h
@@ -175,93 +175,92 @@
   Nintendo Co., Limited and its subsidiary companies.
  ***********************************************************************************/
 
-
 #ifndef _CPUADDR_H_
 #define _CPUADDR_H_
 
-typedef enum
-{
-	NONE   = 0,
-	READ   = 1,
-	WRITE  = 2,
+enum AccessMode
+{
+	NONE = 0,
+	READ = 1,
+	WRITE = 2,
 	MODIFY = 3,
-	JUMP   = 5,
-	JSR    = 8
-}	AccessMode;
-
-static inline uint8_t Immediate8Slow (AccessMode a)
-{
-	uint8_t	val = S9xGetByte(Registers.PBPC);
+	JUMP = 5,
+	JSR = 8
+};
+
+inline uint8_t Immediate8Slow(AccessMode a)
+{
+	uint8_t val = S9xGetByte(Registers.PC.xPBPC);
 	if (a & READ)
 		OpenBus = val;
-	Registers.PCw++;
+	++Registers.PC.W.xPC;
 
 	return val;
 }
 
-static inline uint8_t Immediate8 (AccessMode a)
-{
-	uint8_t	val = CPU.PCBase[Registers.PCw];
+inline uint8_t Immediate8(AccessMode a)
+{
+	uint8_t val = CPU.PCBase[Registers.PC.W.xPC];
 	if (a & READ)
 		OpenBus = val;
 	AddCycles(CPU.MemSpeed);
-	Registers.PCw++;
+	++Registers.PC.W.xPC;
 
 	return val;
 }
 
-static inline uint16_t Immediate16Slow (AccessMode a)
-{
-	uint16_t	val = S9xGetWord(Registers.PBPC, WRAP_BANK);
-	if (a & READ)
-		OpenBus = (uint8_t) (val >> 8);
-	Registers.PCw += 2;
+inline uint16_t Immediate16Slow(AccessMode a)
+{
+	uint16_t val = S9xGetWord(Registers.PC.xPBPC, WRAP_BANK);
+	if (a & READ)
+		OpenBus = static_cast<uint8_t>(val >> 8);
+	Registers.PC.W.xPC += 2;
 
 	return val;
 }
 
-static inline uint16_t Immediate16 (AccessMode a)
-{
-	uint16_t	val = READ_WORD(CPU.PCBase + Registers.PCw);
-	if (a & READ)
-		OpenBus = (uint8_t) (val >> 8);
+inline uint16_t Immediate16(AccessMode a)
+{
+	uint16_t val = READ_WORD(CPU.PCBase + Registers.PC.W.xPC);
+	if (a & READ)
+		OpenBus = static_cast<uint8_t>(val >> 8);
 	AddCycles(CPU.MemSpeedx2);
-	Registers.PCw += 2;
+	Registers.PC.W.xPC += 2;
 
 	return val;
 }
 
-static inline uint32_t RelativeSlow (AccessMode a)						// branch $xx
-{
-	int8_t	offset = Immediate8Slow(a);
-
-	return ((int16_t) Registers.PCw + offset) & 0xffff;
-}
-
-static inline uint32_t Relative (AccessMode a)							// branch $xx
-{
-	int8_t	offset = Immediate8(a);
-
-	return ((int16_t) Registers.PCw + offset) & 0xffff;
-}
-
-static inline uint32_t RelativeLongSlow (AccessMode a)					// BRL $xxxx
-{
-	int16_t	offset = Immediate16Slow(a);
-
-	return ((int32_t) Registers.PCw + offset) & 0xffff;
-}
-
-static inline uint32_t RelativeLong (AccessMode a)						// BRL $xxxx
-{
-	int16_t	offset = Immediate16(a);
-
-	return ((int32_t) Registers.PCw + offset) & 0xffff;
-}
-
-static inline uint32_t AbsoluteIndexedIndirectSlow (AccessMode a)			// (a,X)
-{
-	uint16_t	addr;
+inline uint32_t RelativeSlow(AccessMode a) // branch $xx
+{
+	int8_t offset = Immediate8Slow(a);
+
+	return (static_cast<int16_t>(Registers.PC.W.xPC) + offset) & 0xffff;
+}
+
+inline uint32_t Relative(AccessMode a) // branch $xx
+{
+	int8_t offset = Immediate8(a);
+
+	return (static_cast<int16_t>(Registers.PC.W.xPC) + offset) & 0xffff;
+}
+
+inline uint32_t RelativeLongSlow(AccessMode a) // BRL $xxxx
+{
+	int16_t offset = Immediate16Slow(a);
+
+	return (static_cast<int32_t>(Registers.PC.W.xPC) + offset) & 0xffff;
+}
+
+inline uint32_t RelativeLong(AccessMode a) // BRL $xxxx
+{
+	int16_t offset = Immediate16(a);
+
+	return (static_cast<int32_t>(Registers.PC.W.xPC) + offset) & 0xffff;
+}
+
+inline uint32_t AbsoluteIndexedIndirectSlow(AccessMode a) // (a,X)
+{
+	uint16_t addr;
 
 	if (a & JSR)
 	{
@@ -269,7 +268,7 @@
 		// OpenBus needs to be set to account for this.
 		addr = Immediate8Slow(READ);
 		if (a == JSR)
-			OpenBus = Registers.PCl;
+			OpenBus = Registers.PC.B.xPCl;
 		addr |= Immediate8Slow(READ) << 8;
 	}
 	else
@@ -279,413 +278,429 @@
 	addr += Registers.X.W;
 
 	// Address load wraps within the bank
-	uint16_t	addr2 = S9xGetWord(ICPU.ShiftedPB | addr, WRAP_BANK);
+	uint16_t addr2 = S9xGetWord(ICPU.ShiftedPB | addr, WRAP_BANK);
 	OpenBus = addr2 >> 8;
 
 	return addr2;
 }
 
-static inline uint32_t AbsoluteIndexedIndirect (AccessMode a)				// (a,X)
-{
-	uint16_t	addr = Immediate16Slow(READ);
+inline uint32_t AbsoluteIndexedIndirect(AccessMode a) // (a,X)
+{
+	uint16_t addr = Immediate16Slow(READ);
 	addr += Registers.X.W;
 
 	// Address load wraps within the bank
-	uint16_t	addr2 = S9xGetWord(ICPU.ShiftedPB | addr, WRAP_BANK);
+	uint16_t addr2 = S9xGetWord(ICPU.ShiftedPB | addr, WRAP_BANK);
 	OpenBus = addr2 >> 8;
 
 	return addr2;
 }
 
-static inline uint32_t AbsoluteIndirectLongSlow (AccessMode a)			// [a]
-{
-	uint16_t	addr = Immediate16Slow(READ);
+template<typename F> inline uint32_t AbsoluteIndirectLongWrapper(F f, AccessMode a)
+{
+	uint16_t addr = f(READ);
 
 	// No info on wrapping, but it doesn't matter anyway due to mirroring
-	uint32_t	addr2 = S9xGetWord(addr);
+	uint32_t addr2 = S9xGetWord(addr);
 	OpenBus = addr2 >> 8;
 	addr2 |= (OpenBus = S9xGetByte(addr + 2)) << 16;
 
 	return addr2;
 }
 
-static inline uint32_t AbsoluteIndirectLong (AccessMode a)				// [a]
-{
-	uint16_t	addr = Immediate16(READ);
-
+inline uint32_t AbsoluteIndirectLongSlow(AccessMode a) // [a]
+{
+	return AbsoluteIndirectLongWrapper(Immediate16Slow, a);
+}
+
+inline uint32_t AbsoluteIndirectLong(AccessMode a) // [a]
+{
+	return AbsoluteIndirectLongWrapper(Immediate16, a);
+}
+
+template<typename F> inline uint32_t AbsoluteIndirectWrapper(F f, AccessMode a)
+{
 	// No info on wrapping, but it doesn't matter anyway due to mirroring
-	uint32_t	addr2 = S9xGetWord(addr);
+	uint16_t addr2 = S9xGetWord(f(READ));
 	OpenBus = addr2 >> 8;
-	addr2 |= (OpenBus = S9xGetByte(addr + 2)) << 16;
 
 	return addr2;
 }
 
-static inline uint32_t AbsoluteIndirectSlow (AccessMode a)				// (a)
-{
-	// No info on wrapping, but it doesn't matter anyway due to mirroring
-	uint16_t	addr2 = S9xGetWord(Immediate16Slow(READ));
-	OpenBus = addr2 >> 8;
-
-	return addr2;
-}
-
-static inline uint32_t AbsoluteIndirect (AccessMode a)					// (a)
-{
-	// No info on wrapping, but it doesn't matter anyway due to mirroring
-	uint16_t	addr2 = S9xGetWord(Immediate16(READ));
-	OpenBus = addr2 >> 8;
-
-	return addr2;
-}
-
-static inline uint32_t AbsoluteSlow (AccessMode a)						// a
-{
-	return ICPU.ShiftedDB | Immediate16Slow(a);
-}
-
-static inline uint32_t Absolute (AccessMode a)							// a
-{
-	return ICPU.ShiftedDB | Immediate16(a);
-}
-
-static inline uint32_t AbsoluteLongSlow (AccessMode a)					// l
-{
-	uint32_t	addr = Immediate16Slow(READ);
+inline uint32_t AbsoluteIndirectSlow(AccessMode a) // (a)
+{
+	return AbsoluteIndirectWrapper(Immediate16Slow, a);
+}
+
+inline uint32_t AbsoluteIndirect(AccessMode a) // (a)
+{
+	return AbsoluteIndirectWrapper(Immediate16, a);
+}
+
+template<typename F> inline uint32_t AbsoluteWrapper(F f, AccessMode a)
+{
+	return ICPU.ShiftedDB | f(a);
+}
+
+inline uint32_t AbsoluteSlow(AccessMode a) // a
+{
+	return AbsoluteWrapper(Immediate16Slow, a);
+}
+
+inline uint32_t Absolute(AccessMode a) // a
+{
+	return AbsoluteWrapper(Immediate16, a);
+}
+
+inline uint32_t AbsoluteLongSlow(AccessMode a) // l
+{
+	uint32_t addr = Immediate16Slow(READ);
 
 	// JSR l pushes the old bank in the middle of loading the new.
 	// OpenBus needs to be set to account for this.
 	if (a == JSR)
-		OpenBus = Registers.PB;
+		OpenBus = Registers.PC.B.xPB;
 
 	addr |= Immediate8Slow(a) << 16;
 
 	return addr;
 }
 
-static inline uint32_t AbsoluteLong (AccessMode a)						// l
-{
-	uint32_t	addr = READ_3WORD(CPU.PCBase + Registers.PCw);
+inline uint32_t AbsoluteLong(AccessMode a) // l
+{
+	uint32_t addr = READ_3WORD(CPU.PCBase + Registers.PC.W.xPC);
 	AddCycles(CPU.MemSpeedx2 + CPU.MemSpeed);
 	if (a & READ)
 		OpenBus = addr >> 16;
-	Registers.PCw += 3;
-
-	return addr;
-}
-
-static inline uint32_t DirectSlow (AccessMode a)							// d
-{
-	uint16_t	addr = Immediate8Slow(a) + Registers.D.W;
-	if (Registers.DL != 0)
-		AddCycles(ONE_CYCLE);
-
-	return addr;
-}
-
-static inline uint32_t Direct (AccessMode a)								// d
-{
-	uint16_t	addr = Immediate8(a) + Registers.D.W;
-	if (Registers.DL != 0)
-		AddCycles(ONE_CYCLE);
-
-	return addr;
-}
-
-static inline uint32_t DirectIndirectSlow (AccessMode a)					// (d)
-{
-	uint32_t	addr = S9xGetWord(DirectSlow(READ), (!CheckEmulation() || Registers.DL) ? WRAP_BANK : WRAP_PAGE);
-	if (a & READ)
-		OpenBus = (uint8_t) (addr >> 8);
+	Registers.PC.W.xPC += 3;
+
+	return addr;
+}
+
+template<typename F> inline uint32_t DirectWrapper(F f, AccessMode a)
+{
+	uint16_t addr = f(a) + Registers.D.W;
+	if (Registers.D.B.l)
+		AddCycles(ONE_CYCLE);
+
+	return addr;
+}
+
+inline uint32_t DirectSlow(AccessMode a) // d
+{
+	return DirectWrapper(Immediate8Slow, a);
+}
+
+inline uint32_t Direct(AccessMode a) // d
+{
+	return DirectWrapper(Immediate8, a);
+}
+
+inline uint32_t DirectIndirectSlow(AccessMode a) // (d)
+{
+	uint32_t addr = S9xGetWord(DirectSlow(READ), !CheckEmulation() || Registers.D.B.l ? WRAP_BANK : WRAP_PAGE);
+	if (a & READ)
+		OpenBus = static_cast<uint8_t>(addr >> 8);
 	addr |= ICPU.ShiftedDB;
 
 	return addr;
 }
 
-static inline uint32_t DirectIndirectE0 (AccessMode a)					// (d)
-{
-	uint32_t	addr = S9xGetWord(Direct(READ));
-	if (a & READ)
-		OpenBus = (uint8_t) (addr >> 8);
+inline uint32_t DirectIndirectE0(AccessMode a) // (d)
+{
+	uint32_t addr = S9xGetWord(Direct(READ));
+	if (a & READ)
+		OpenBus = static_cast<uint8_t>(addr >> 8);
 	addr |= ICPU.ShiftedDB;
 
 	return addr;
 }
 
-static inline uint32_t DirectIndirectE1 (AccessMode a)					// (d)
-{
-	uint32_t	addr = S9xGetWord(DirectSlow(READ), Registers.DL ? WRAP_BANK : WRAP_PAGE);
-	if (a & READ)
-		OpenBus = (uint8_t) (addr >> 8);
+inline uint32_t DirectIndirectE1(AccessMode a) // (d)
+{
+	uint32_t addr = S9xGetWord(DirectSlow(READ), Registers.D.B.l ? WRAP_BANK : WRAP_PAGE);
+	if (a & READ)
+		OpenBus = static_cast<uint8_t>(addr >> 8);
 	addr |= ICPU.ShiftedDB;
 
 	return addr;
 }
 
-static inline uint32_t DirectIndirectIndexedSlow (AccessMode a)			// (d),Y
-{
-	uint32_t	addr = DirectIndirectSlow(a);
-	if (a & WRITE || !CheckIndex() || (addr & 0xff) + Registers.YL >= 0x100)
+inline uint32_t DirectIndirectIndexedSlow(AccessMode a) // (d),Y
+{
+	uint32_t addr = DirectIndirectSlow(a);
+	if ((a & WRITE) || !CheckIndex() || (addr & 0xff) + Registers.Y.B.l >= 0x100)
 		AddCycles(ONE_CYCLE);
 
 	return addr + Registers.Y.W;
 }
 
-static inline uint32_t DirectIndirectIndexedE0X0 (AccessMode a)			// (d),Y
-{
-	uint32_t	addr = DirectIndirectE0(a);
+inline uint32_t DirectIndirectIndexedE0X0(AccessMode a) // (d),Y
+{
+	uint32_t addr = DirectIndirectE0(a);
 	AddCycles(ONE_CYCLE);
 
 	return addr + Registers.Y.W;
 }
 
-static inline uint32_t DirectIndirectIndexedE0X1 (AccessMode a)			// (d),Y
-{
-	uint32_t	addr = DirectIndirectE0(a);
-	if (a & WRITE || (addr & 0xff) + Registers.YL >= 0x100)
+inline uint32_t DirectIndirectIndexedE0X1(AccessMode a) // (d),Y
+{
+	uint32_t addr = DirectIndirectE0(a);
+	if ((a & WRITE) || (addr & 0xff) + Registers.Y.B.l >= 0x100)
 		AddCycles(ONE_CYCLE);
 
 	return addr + Registers.Y.W;
 }
 
-static inline uint32_t DirectIndirectIndexedE1 (AccessMode a)				// (d),Y
-{
-	uint32_t	addr = DirectIndirectE1(a);
-	if (a & WRITE || (addr & 0xff) + Registers.YL >= 0x100)
+inline uint32_t DirectIndirectIndexedE1(AccessMode a) // (d),Y
+{
+	uint32_t addr = DirectIndirectE1(a);
+	if ((a & WRITE) || (addr & 0xff) + Registers.Y.B.l >= 0x100)
 		AddCycles(ONE_CYCLE);
 
 	return addr + Registers.Y.W;
 }
 
-static inline uint32_t DirectIndirectLongSlow (AccessMode a)				// [d]
-{
-	uint16_t	addr = DirectSlow(READ);
-	uint32_t	addr2 = S9xGetWord(addr);
+template<typename F> inline uint32_t DirectIndirectLongWrapper(F f, AccessMode a)
+{
+	uint16_t addr = f(READ);
+	uint32_t addr2 = S9xGetWord(addr);
 	OpenBus = addr2 >> 8;
 	addr2 |= (OpenBus = S9xGetByte(addr + 2)) << 16;
 
 	return addr2;
 }
 
-static inline uint32_t DirectIndirectLong (AccessMode a)					// [d]
-{
-	uint16_t	addr = Direct(READ);
-	uint32_t	addr2 = S9xGetWord(addr);
-	OpenBus = addr2 >> 8;
-	addr2 |= (OpenBus = S9xGetByte(addr + 2)) << 16;
-
-	return addr2;
-}
-
-static inline uint32_t DirectIndirectIndexedLongSlow (AccessMode a)		// [d],Y
-{
-	return DirectIndirectLongSlow(a) + Registers.Y.W;
-}
-
-static inline uint32_t DirectIndirectIndexedLong (AccessMode a)			// [d],Y
-{
-	return DirectIndirectLong(a) + Registers.Y.W;
-}
-
-static inline uint32_t DirectIndexedXSlow (AccessMode a)					// d,X
-{
-	pair	addr;
+inline uint32_t DirectIndirectLongSlow(AccessMode a) // [d]
+{
+	return DirectIndirectLongWrapper(DirectSlow, a);
+}
+
+inline uint32_t DirectIndirectLong(AccessMode a) // [d]
+{
+	return DirectIndirectLongWrapper(Direct, a);
+}
+
+template<typename F> inline uint32_t DirectIndirectIndexedLongWrapper(F f, AccessMode a)
+{
+	return f(a) + Registers.Y.W;
+}
+
+inline uint32_t DirectIndirectIndexedLongSlow(AccessMode a) // [d],Y
+{
+	return DirectIndirectIndexedLongWrapper(DirectIndirectLongSlow, a);
+}
+
+inline uint32_t DirectIndirectIndexedLong(AccessMode a) // [d],Y
+{
+	return DirectIndirectIndexedLongWrapper(DirectIndirectLong, a);
+}
+
+inline uint32_t DirectIndexedXSlow(AccessMode a) // d,X
+{
+	pair addr;
 	addr.W = DirectSlow(a);
-	if (!CheckEmulation() || Registers.DL)
+	if (!CheckEmulation() || Registers.D.B.l)
 		addr.W += Registers.X.W;
 	else
-		addr.B.l += Registers.XL;
+		addr.B.l += Registers.X.B.l;
 
 	AddCycles(ONE_CYCLE);
 
 	return addr.W;
 }
 
-static inline uint32_t DirectIndexedXE0 (AccessMode a)					// d,X
-{
-	uint16_t	addr = Direct(a) + Registers.X.W;
-	AddCycles(ONE_CYCLE);
-
-	return addr;
-}
-
-static inline uint32_t DirectIndexedXE1 (AccessMode a)					// d,X
-{
-	if (Registers.DL)
+inline uint32_t DirectIndexedXE0(AccessMode a) // d,X
+{
+	uint16_t addr = Direct(a) + Registers.X.W;
+	AddCycles(ONE_CYCLE);
+
+	return addr;
+}
+
+inline uint32_t DirectIndexedXE1(AccessMode a) // d,X
+{
+	if (Registers.D.B.l)
 		return DirectIndexedXE0(a);
 	else
 	{
-		pair	addr;
+		pair addr;
 		addr.W = Direct(a);
-		addr.B.l += Registers.XL;
+		addr.B.l += Registers.X.B.l;
 		AddCycles(ONE_CYCLE);
 
 		return addr.W;
 	}
 }
 
-static inline uint32_t DirectIndexedYSlow (AccessMode a)					// d,Y
-{
-	pair	addr;
+inline uint32_t DirectIndexedYSlow(AccessMode a) // d,Y
+{
+	pair addr;
 	addr.W = DirectSlow(a);
-	if (!CheckEmulation() || Registers.DL)
+	if (!CheckEmulation() || Registers.D.B.l)
 		addr.W += Registers.Y.W;
 	else
-		addr.B.l += Registers.YL;
+		addr.B.l += Registers.Y.B.l;
 
 	AddCycles(ONE_CYCLE);
 
 	return addr.W;
 }
 
-static inline uint32_t DirectIndexedYE0 (AccessMode a)					// d,Y
-{
-	uint16_t	addr = Direct(a) + Registers.Y.W;
-	AddCycles(ONE_CYCLE);
-
-	return addr;
-}
-
-static inline uint32_t DirectIndexedYE1 (AccessMode a)					// d,Y
-{
-	if (Registers.DL)
+inline uint32_t DirectIndexedYE0(AccessMode a) // d,Y
+{
+	uint16_t addr = Direct(a) + Registers.Y.W;
+	AddCycles(ONE_CYCLE);
+
+	return addr;
+}
+
+inline uint32_t DirectIndexedYE1(AccessMode a) // d,Y
+{
+	if (Registers.D.B.l)
 		return DirectIndexedYE0(a);
 	else
 	{
-		pair	addr;
+		pair addr;
 		addr.W = Direct(a);
-		addr.B.l += Registers.YL;
+		addr.B.l += Registers.Y.B.l;
 		AddCycles(ONE_CYCLE);
 
 		return addr.W;
 	}
 }
 
-static inline uint32_t DirectIndexedIndirectSlow (AccessMode a)			// (d,X)
-{
-	uint32_t	addr = S9xGetWord(DirectIndexedXSlow(READ), (!CheckEmulation() || Registers.DL) ? WRAP_BANK : WRAP_PAGE);
-	if (a & READ)
-		OpenBus = (uint8_t) (addr >> 8);
+inline uint32_t DirectIndexedIndirectSlow(AccessMode a) // (d,X)
+{
+	uint32_t addr = S9xGetWord(DirectIndexedXSlow(READ), !CheckEmulation() || Registers.D.B.l ? WRAP_BANK : WRAP_PAGE);
+	if (a & READ)
+		OpenBus = static_cast<uint8_t>(addr >> 8);
 
 	return ICPU.ShiftedDB | addr;
 }
 
-static inline uint32_t DirectIndexedIndirectE0 (AccessMode a)				// (d,X)
-{
-	uint32_t	addr = S9xGetWord(DirectIndexedXE0(READ));
-	if (a & READ)
-		OpenBus = (uint8_t) (addr >> 8);
+inline uint32_t DirectIndexedIndirectE0(AccessMode a) // (d,X)
+{
+	uint32_t addr = S9xGetWord(DirectIndexedXE0(READ));
+	if (a & READ)
+		OpenBus = static_cast<uint8_t>(addr >> 8);
 
 	return ICPU.ShiftedDB | addr;
 }
 
-static inline uint32_t DirectIndexedIndirectE1 (AccessMode a)				// (d,X)
-{
-	uint32_t	addr = S9xGetWord(DirectIndexedXE1(READ), Registers.DL ? WRAP_BANK : WRAP_PAGE);
-	if (a & READ)
-		OpenBus = (uint8_t) (addr >> 8);
+inline uint32_t DirectIndexedIndirectE1(AccessMode a) // (d,X)
+{
+	uint32_t addr = S9xGetWord(DirectIndexedXE1(READ), Registers.D.B.l ? WRAP_BANK : WRAP_PAGE);
+	if (a & READ)
+		OpenBus = static_cast<uint8_t>(addr >> 8);
 
 	return ICPU.ShiftedDB | addr;
 }
 
-static inline uint32_t AbsoluteIndexedXSlow (AccessMode a)				// a,X
-{
-	uint32_t	addr = AbsoluteSlow(a);
-	if (a & WRITE || !CheckIndex() || (addr & 0xff) + Registers.XL >= 0x100)
+inline uint32_t AbsoluteIndexedXSlow(AccessMode a) // a,X
+{
+	uint32_t addr = AbsoluteSlow(a);
+	if ((a & WRITE) || !CheckIndex() || (addr & 0xff) + Registers.X.B.l >= 0x100)
 		AddCycles(ONE_CYCLE);
 
 	return addr + Registers.X.W;
 }
 
-static inline uint32_t AbsoluteIndexedXX0 (AccessMode a)					// a,X
-{
-	uint32_t	addr = Absolute(a);
+inline uint32_t AbsoluteIndexedXX0(AccessMode a) // a,X
+{
+	uint32_t addr = Absolute(a);
 	AddCycles(ONE_CYCLE);
 
 	return addr + Registers.X.W;
 }
 
-static inline uint32_t AbsoluteIndexedXX1 (AccessMode a)					// a,X
-{
-	uint32_t	addr = Absolute(a);
-	if (a & WRITE || (addr & 0xff) + Registers.XL >= 0x100)
+inline uint32_t AbsoluteIndexedXX1(AccessMode a) // a,X
+{
+	uint32_t addr = Absolute(a);
+	if ((a & WRITE) || (addr & 0xff) + Registers.X.B.l >= 0x100)
 		AddCycles(ONE_CYCLE);
 
 	return addr + Registers.X.W;
 }
 
-static inline uint32_t AbsoluteIndexedYSlow (AccessMode a)				// a,Y
-{
-	uint32_t	addr = AbsoluteSlow(a);
-	if (a & WRITE || !CheckIndex() || (addr & 0xff) + Registers.YL >= 0x100)
+inline uint32_t AbsoluteIndexedYSlow(AccessMode a) // a,Y
+{
+	uint32_t addr = AbsoluteSlow(a);
+	if ((a & WRITE) || !CheckIndex() || (addr & 0xff) + Registers.Y.B.l >= 0x100)
 		AddCycles(ONE_CYCLE);
 
 	return addr + Registers.Y.W;
 }
 
-static inline uint32_t AbsoluteIndexedYX0 (AccessMode a)					// a,Y
-{
-	uint32_t	addr = Absolute(a);
+inline uint32_t AbsoluteIndexedYX0(AccessMode a) // a,Y
+{
+	uint32_t addr = Absolute(a);
 	AddCycles(ONE_CYCLE);
 
 	return addr + Registers.Y.W;
 }
 
-static inline uint32_t AbsoluteIndexedYX1 (AccessMode a)					// a,Y
-{
-	uint32_t	addr = Absolute(a);
-	if (a & WRITE || (addr & 0xff) + Registers.YL >= 0x100)
+inline uint32_t AbsoluteIndexedYX1(AccessMode a) // a,Y
+{
+	uint32_t addr = Absolute(a);
+	if ((a & WRITE) || (addr & 0xff) + Registers.Y.B.l >= 0x100)
 		AddCycles(ONE_CYCLE);
 
 	return addr + Registers.Y.W;
 }
 
-static inline uint32_t AbsoluteLongIndexedXSlow (AccessMode a)			// l,X
-{
-	return AbsoluteLongSlow(a) + Registers.X.W;
-}
-
-static inline uint32_t AbsoluteLongIndexedX (AccessMode a)				// l,X
-{
-	return AbsoluteLong(a) + Registers.X.W;
-}
-
-static inline uint32_t StackRelativeSlow (AccessMode a)					// d,S
-{
-	uint16_t	addr = Immediate8Slow(a) + Registers.S.W;
-	AddCycles(ONE_CYCLE);
-
-	return addr;
-}
-
-static inline uint32_t StackRelative (AccessMode a)						// d,S
-{
-	uint16_t	addr = Immediate8(a) + Registers.S.W;
-	AddCycles(ONE_CYCLE);
-
-	return addr;
-}
-
-static inline uint32_t StackRelativeIndirectIndexedSlow (AccessMode a)	// (d,S),Y
-{
-	uint32_t	addr = S9xGetWord(StackRelativeSlow(READ));
-	if (a & READ)
-		OpenBus = (uint8_t) (addr >> 8);
+template<typename F> inline uint32_t AbsoluteLongIndexedXWrapper(F f, AccessMode a)
+{
+	return f(a) + Registers.X.W;
+}
+
+inline uint32_t AbsoluteLongIndexedXSlow(AccessMode a) // l,X
+{
+	return AbsoluteLongIndexedXWrapper(AbsoluteLongSlow, a);
+}
+
+inline uint32_t AbsoluteLongIndexedX(AccessMode a) // l,X
+{
+	return AbsoluteLongIndexedXWrapper(AbsoluteLong, a);
+}
+
+template<typename F> inline uint32_t StackRelativeWrapper(F f, AccessMode a)
+{
+	uint16_t addr = f(a) + Registers.S.W;
+	AddCycles(ONE_CYCLE);
+
+	return addr;
+}
+
+inline uint32_t StackRelativeSlow(AccessMode a) // d,S
+{
+	return StackRelativeWrapper(Immediate8Slow, a);
+}
+
+inline uint32_t StackRelative(AccessMode a) // d,S
+{
+	return StackRelativeWrapper(Immediate8, a);
+}
+
+template<typename F> inline uint32_t StackRelativeIndirectIndexedWrapper(F f, AccessMode a)
+{
+	uint32_t addr = S9xGetWord(f(READ));
+	if (a & READ)
+		OpenBus = static_cast<uint8_t>(addr >> 8);
 	addr = (addr + Registers.Y.W + ICPU.ShiftedDB) & 0xffffff;
 	AddCycles(ONE_CYCLE);
 
 	return addr;
 }
 
-static inline uint32_t StackRelativeIndirectIndexed (AccessMode a)		// (d,S),Y
-{
-	uint32_t	addr = S9xGetWord(StackRelative(READ));
-	if (a & READ)
-		OpenBus = (uint8_t) (addr >> 8);
-	addr = (addr + Registers.Y.W + ICPU.ShiftedDB) & 0xffffff;
-	AddCycles(ONE_CYCLE);
-
-	return addr;
+inline uint32_t StackRelativeIndirectIndexedSlow(AccessMode a) // (d,S),Y
+{
+	return StackRelativeIndirectIndexedWrapper(StackRelativeSlow, a);
+}
+
+inline uint32_t StackRelativeIndirectIndexed(AccessMode a) // (d,S),Y
+{
+	return StackRelativeIndirectIndexedWrapper(StackRelative, a);
 }
 
 #endif

--- a/src/in_snsf/snes9x/cpuexec.cpp
+++ b/src/in_snsf/snes9x/cpuexec.cpp
@@ -180,12 +180,6 @@
 #include "cpuops.h"
 #include "dma.h"
 #include "apu/apu.h"
-//#include "fxemu.h"
-//#include "snapshot.h"
-#ifdef DEBUGGER
-#include "debug.h"
-#include "missing.h"
-#endif
 
 static inline void S9xReschedule()
 {
@@ -193,33 +187,32 @@
 	{
 		case HC_HBLANK_START_EVENT:
 			CPU.WhichEvent = HC_HDMA_START_EVENT;
-			CPU.NextEvent  = Timings.HDMAStart;
+			CPU.NextEvent = Timings.HDMAStart;
 			break;
 
 		case HC_HDMA_START_EVENT:
 			CPU.WhichEvent = HC_HCOUNTER_MAX_EVENT;
-			CPU.NextEvent  = Timings.H_Max;
+			CPU.NextEvent = Timings.H_Max;
 			break;
 
 		case HC_HCOUNTER_MAX_EVENT:
 			CPU.WhichEvent = HC_HDMA_INIT_EVENT;
-			CPU.NextEvent  = Timings.HDMAInit;
+			CPU.NextEvent = Timings.HDMAInit;
 			break;
 
 		case HC_HDMA_INIT_EVENT:
 			CPU.WhichEvent = HC_RENDER_EVENT;
-			CPU.NextEvent  = Timings.RenderPos;
+			CPU.NextEvent = Timings.RenderPos;
 			break;
 
 		case HC_RENDER_EVENT:
 			CPU.WhichEvent = HC_WRAM_REFRESH_EVENT;
-			CPU.NextEvent  = Timings.WRAMRefreshPos;
+			CPU.NextEvent = Timings.WRAMRefreshPos;
 			break;
 
 		case HC_WRAM_REFRESH_EVENT:
 			CPU.WhichEvent = HC_HBLANK_START_EVENT;
-			CPU.NextEvent  = Timings.HBlankStart;
-			break;
+			CPU.NextEvent = Timings.HBlankStart;
 	}
 }
 
@@ -236,23 +229,23 @@
 				if (CPU.WaitingForInterrupt)
 				{
 					CPU.WaitingForInterrupt = false;
-					Registers.PCw++;
+					++Registers.PC.W.xPC;
 				}
 
 				S9xOpcode_NMI();
 			}
 		}
 
-		if (CPU.IRQTransition || CPU.IRQExternal)
+		if (CPU.IRQTransition)
 		{
 			if (CPU.IRQPending)
-				CPU.IRQPending--;
+				--CPU.IRQPending;
 			else
 			{
 				if (CPU.WaitingForInterrupt)
 				{
 					CPU.WaitingForInterrupt = false;
-					Registers.PCw++;
+					++Registers.PC.W.xPC;
 				}
 
 				CPU.IRQTransition = false;
@@ -263,45 +256,15 @@
 			}
 		}
 
-	#ifdef DEBUGGER
-		if ((CPU.Flags & BREAK_FLAG) && !(CPU.Flags & SINGLE_STEP_FLAG))
-		{
-			for (int Break = 0; Break != 6; Break++)
-			{
-				if (S9xBreakpoint[Break].Enabled &&
-					S9xBreakpoint[Break].Bank == Registers.PB &&
-					S9xBreakpoint[Break].Address == Registers.PCw)
-				{
-					if (S9xBreakpoint[Break].Enabled == 2)
-						S9xBreakpoint[Break].Enabled = true;
-					else
-						CPU.Flags |= DEBUG_MODE_FLAG;
-				}
-			}
-		}
-
-		if (CPU.Flags & DEBUG_MODE_FLAG)
-			break;
-
-		if (CPU.Flags & TRACE_FLAG)
-			S9xTrace();
-
-		if (CPU.Flags & SINGLE_STEP_FLAG)
-		{
-			CPU.Flags &= ~SINGLE_STEP_FLAG;
-			CPU.Flags |= DEBUG_MODE_FLAG;
-		}
-	#endif
-
 		if (CPU.Flags & SCAN_KEYS_FLAG)
 			break;
 
-		register uint8_t				Op;
-		register struct	SOpcodes	*Opcodes;
+		register uint8_t Op;
+		register SOpcodes *Opcodes;
 
 		if (CPU.PCBase)
 		{
-			Op = CPU.PCBase[Registers.PCw];
+			Op = CPU.PCBase[Registers.PC.W.xPC];
 			CPU.PrevCycles = CPU.Cycles;
 			CPU.Cycles += CPU.MemSpeed;
 			S9xCheckInterrupts();
@@ -309,60 +272,32 @@
 		}
 		else
 		{
-			Op = S9xGetByte(Registers.PBPC);
+			Op = S9xGetByte(Registers.PC.xPBPC);
 			OpenBus = Op;
 			Opcodes = S9xOpcodesSlow;
 		}
 
-		if ((Registers.PCw & MEMMAP_MASK) + ICPU.S9xOpLengths[Op] >= MEMMAP_BLOCK_SIZE)
+		if ((Registers.PC.W.xPC & MEMMAP_MASK) + ICPU.S9xOpLengths[Op] >= MEMMAP_BLOCK_SIZE)
 		{
-			uint8_t	*oldPCBase = CPU.PCBase;
-
-			CPU.PCBase = S9xGetBasePointer(ICPU.ShiftedPB + ((uint16_t) (Registers.PCw + 4)));
-			if (oldPCBase != CPU.PCBase || (Registers.PCw & ~MEMMAP_MASK) == (0xffff & ~MEMMAP_MASK))
+			uint8_t *oldPCBase = CPU.PCBase;
+
+			CPU.PCBase = S9xGetBasePointer(ICPU.ShiftedPB + (static_cast<uint16_t>(Registers.PC.W.xPC + 4)));
+			if (oldPCBase != CPU.PCBase || (Registers.PC.W.xPC & ~MEMMAP_MASK) == (0xffff & ~MEMMAP_MASK))
 				Opcodes = S9xOpcodesSlow;
 		}
 
-		Registers.PCw++;
+		++Registers.PC.W.xPC;
 		(*Opcodes[Op].S9xOpcode)();
-
-		/*if (Settings.SA1)
-			S9xSA1MainLoop();*/
 	}
 
 	S9xPackStatus();
 
 	if (CPU.Flags & SCAN_KEYS_FLAG)
-	{
-	/*#ifdef DEBUGGER
-		if (!(CPU.Flags & FRAME_ADVANCE_FLAG))
-	#endif
-		S9xSyncSpeed();*/
 		CPU.Flags &= ~SCAN_KEYS_FLAG;
-	}
 }
 
 void S9xDoHEventProcessing()
 {
-#ifdef DEBUGGER
-	static char	eventname[7][32] =
-	{
-		"",
-		"HC_HBLANK_START_EVENT",
-		"HC_HDMA_START_EVENT  ",
-		"HC_HCOUNTER_MAX_EVENT",
-		"HC_HDMA_INIT_EVENT   ",
-		"HC_RENDER_EVENT      ",
-		"HC_WRAM_REFRESH_EVENT"
-	};
-#endif
-
-#ifdef DEBUGGER
-	if (Settings.TraceHCEvent)
-		S9xTraceFormattedMessage("--- HC event processing  (%s)  expected HC:%04d  executed HC:%04d",
-			eventname[CPU.WhichEvent], CPU.NextEvent, CPU.Cycles);
-#endif
-
 	switch (CPU.WhichEvent)
 	{
 		case HC_HBLANK_START_EVENT:
@@ -373,23 +308,11 @@
 			S9xReschedule();
 
 			if (PPU.HDMA && CPU.V_Counter <= PPU.ScreenHeight)
-			{
-			#ifdef DEBUGGER
-				S9xTraceFormattedMessage("*** HDMA Transfer HC:%04d, Channel:%02x", CPU.Cycles, PPU.HDMA);
-			#endif
 				PPU.HDMA = S9xDoHDMA(PPU.HDMA);
-			}
 
 			break;
 
 		case HC_HCOUNTER_MAX_EVENT:
-			/*if (Settings.SuperFX)
-			{
-				if (!SuperFX.oneLineDone)
-					S9xSuperFXExec();
-				SuperFX.oneLineDone = false;
-			}*/
-
 			S9xAPUEndScanline();
 			CPU.Cycles -= Timings.H_Max;
 			CPU.PrevCycles -= Timings.H_Max;
@@ -398,11 +321,11 @@
 			if ((Timings.NMITriggerPos != 0xffff) && (Timings.NMITriggerPos >= Timings.H_Max))
 				Timings.NMITriggerPos -= Timings.H_Max;
 
-			CPU.V_Counter++;
-			if (CPU.V_Counter >= Timings.V_Max)	// V ranges from 0 to Timings.V_Max - 1
+			++CPU.V_Counter;
+			if (CPU.V_Counter >= Timings.V_Max) // V ranges from 0 to Timings.V_Max - 1
 			{
 				CPU.V_Counter = 0;
-				Timings.InterlaceField ^= 1;
+				Timings.InterlaceField = !Timings.InterlaceField;
 
 				// From byuu:
 				// [NTSC]
@@ -412,20 +335,17 @@
 				// interlace mode has 625 scanlines: 313 on the even frame, and 312 on the odd.
 				// non-interlace mode has 624 scanlines: 312 scanlines on both even and odd frames.
 				if (IPPU.Interlace && !Timings.InterlaceField)
-					Timings.V_Max = Timings.V_Max_Master + 1;	// 263 (NTSC), 313?(PAL)
+					Timings.V_Max = Timings.V_Max_Master + 1; // 263 (NTSC), 313?(PAL)
 				else
-					Timings.V_Max = Timings.V_Max_Master;		// 262 (NTSC), 312?(PAL)
+					Timings.V_Max = Timings.V_Max_Master; // 262 (NTSC), 312?(PAL)
 
 				Memory.FillRAM[0x213F] ^= 0x80;
-				PPU.RangeTimeOver = 0;
 
 				// FIXME: reading $4210 will wait 2 cycles, then perform reading, then wait 4 more cycles.
 				Memory.FillRAM[0x4210] = Model->_5A22;
 				CPU.NMILine = false;
 				Timings.NMITriggerPos = 0xffff;
 
-				ICPU.Frame++;
-				PPU.HVBeamCounterLatched = 0;
 				CPU.Flags |= SCAN_KEYS_FLAG;
 			}
 
@@ -435,48 +355,40 @@
 			// In interlace mode, there are always 341 dots per scanline. Even frames have 263 scanlines,
 			// and odd frames have 262 scanlines.
 			// Interlace mode scanline 240 on odd frames is not missing a dot.
-			if (CPU.V_Counter == 240 && !IPPU.Interlace && Timings.InterlaceField)	// V=240
-				Timings.H_Max = Timings.H_Max_Master - ONE_DOT_CYCLE;	// HC=1360
+			if (CPU.V_Counter == 240 && !IPPU.Interlace && Timings.InterlaceField) // V=240
+				Timings.H_Max = Timings.H_Max_Master - ONE_DOT_CYCLE; // HC=1360
 			else
-				Timings.H_Max = Timings.H_Max_Master;					// HC=1364
+				Timings.H_Max = Timings.H_Max_Master; // HC=1364
 
 			if (Model->_5A22 == 2)
 			{
 				if (CPU.V_Counter != 240 || IPPU.Interlace || !Timings.InterlaceField)	// V=240
 				{
-					if (Timings.WRAMRefreshPos == SNES_WRAM_REFRESH_HC_v2 - ONE_DOT_CYCLE)	// HC=534
-						Timings.WRAMRefreshPos = SNES_WRAM_REFRESH_HC_v2;					// HC=538
+					if (Timings.WRAMRefreshPos == SNES_WRAM_REFRESH_HC_v2 - ONE_DOT_CYCLE) // HC=534
+						Timings.WRAMRefreshPos = SNES_WRAM_REFRESH_HC_v2; // HC=538
 					else
-						Timings.WRAMRefreshPos = SNES_WRAM_REFRESH_HC_v2 - ONE_DOT_CYCLE;	// HC=534
+						Timings.WRAMRefreshPos = SNES_WRAM_REFRESH_HC_v2 - ONE_DOT_CYCLE; // HC=534
 				}
 			}
 			else
 				Timings.WRAMRefreshPos = SNES_WRAM_REFRESH_HC_v1;
 
-			if (CPU.V_Counter == PPU.ScreenHeight + FIRST_VISIBLE_LINE)	// VBlank starts from V=225(240).
+			if (CPU.V_Counter == PPU.ScreenHeight + FIRST_VISIBLE_LINE) // VBlank starts from V=225(240).
 			{
-				//S9xEndScreenRefresh();
 				PPU.HDMA = 0;
 				// Bits 7 and 6 of $4212 are computed when read in S9xGetPPU.
-			#ifdef DEBUGGER
-				missing.dma_this_frame = 0;
-			#endif
-				IPPU.MaxBrightness = PPU.Brightness;
-				PPU.ForcedBlanking = (Memory.FillRAM[0x2100] >> 7) & 1;
+				PPU.ForcedBlanking = !!((Memory.FillRAM[0x2100] >> 7) & 1);
 
 				if (!PPU.ForcedBlanking)
 				{
 					PPU.OAMAddr = PPU.SavedOAMAddr;
 
-					uint8_t	tmp = 0;
+					uint8_t tmp = 0;
 
 					if (PPU.OAMPriorityRotation)
 						tmp = (PPU.OAMAddr & 0xFE) >> 1;
 					if ((PPU.OAMFlip & 1) || PPU.FirstSprite != tmp)
-					{
 						PPU.FirstSprite = tmp;
-						IPPU.OBJChanged = true;
-					}
 
 					PPU.OAMFlip = 0;
 				}
@@ -490,18 +402,8 @@
 					CPU.NMILine = true;
 					Timings.NMITriggerPos = 6 + 6;
 				}
-
 			}
 
-			/*if (CPU.V_Counter == PPU.ScreenHeight + 3)	// FIXME: not true
-			{
-				if (Memory.FillRAM[0x4200] & 1)
-					S9xDoAutoJoypad();
-			}*/
-
-			/*if (CPU.V_Counter == FIRST_VISIBLE_LINE)	// V=1
-				S9xStartScreenRefresh();*/
-
 			S9xReschedule();
 
 			break;
@@ -509,42 +411,22 @@
 		case HC_HDMA_INIT_EVENT:
 			S9xReschedule();
 
-			if (CPU.V_Counter == 0)
-			{
-			#ifdef DEBUGGER
-				S9xTraceFormattedMessage("*** HDMA Init     HC:%04d, Channel:%02x", CPU.Cycles, PPU.HDMA);
-			#endif
+			if (!CPU.V_Counter)
 				S9xStartHDMA();
-			}
 
 			break;
 
 		case HC_RENDER_EVENT:
-			/*if (CPU.V_Counter >= FIRST_VISIBLE_LINE && CPU.V_Counter <= PPU.ScreenHeight)
-				RenderLine((uint8_t) (CPU.V_Counter - FIRST_VISIBLE_LINE));*/
-
 			S9xReschedule();
 
 			break;
 
 		case HC_WRAM_REFRESH_EVENT:
-		#ifdef DEBUGGER
-			S9xTraceFormattedMessage("*** WRAM Refresh  HC:%04d", CPU.Cycles);
-		#endif
-
 			CPU.PrevCycles = CPU.Cycles;
 			CPU.Cycles += SNES_WRAM_REFRESH_CYCLES;
 			S9xCheckInterrupts();
 
 			S9xReschedule();
-
-			break;
 	}
-
-#ifdef DEBUGGER
-	if (Settings.TraceHCEvent)
-		S9xTraceFormattedMessage("--- HC event rescheduled (%s)  expected HC:%04d  current  HC:%04d",
-			eventname[CPU.WhichEvent], CPU.NextEvent, CPU.Cycles);
-#endif
 }
 

--- a/src/in_snsf/snes9x/cpuexec.h
+++ b/src/in_snsf/snes9x/cpuexec.h
@@ -175,14 +175,10 @@
   Nintendo Co., Limited and its subsidiary companies.
  ***********************************************************************************/
 
-
 #ifndef _CPUEXEC_H_
 #define _CPUEXEC_H_
 
 #include "ppu.h"
-#ifdef DEBUGGER
-#include "debug.h"
-#endif
 
 struct SOpcodes
 {
@@ -191,59 +187,57 @@
 
 struct SICPU
 {
-	struct SOpcodes	*S9xOpcodes;
-	uint8_t	*S9xOpLengths;
-	uint8_t	_Carry;
-	uint8_t	_Zero;
-	uint8_t	_Negative;
-	uint8_t	_Overflow;
-	uint32_t	ShiftedPB;
-	uint32_t	ShiftedDB;
-	uint32_t	Frame;
-	uint32_t	FrameAdvanceCount;
+	SOpcodes *S9xOpcodes;
+	uint8_t *S9xOpLengths;
+	uint8_t _Carry;
+	uint8_t _Zero;
+	uint8_t _Negative;
+	uint8_t _Overflow;
+	uint32_t ShiftedPB;
+	uint32_t ShiftedDB;
 };
 
-extern struct SICPU		ICPU;
-
-extern struct SOpcodes	S9xOpcodesE1[256];
-extern struct SOpcodes	S9xOpcodesM1X1[256];
-extern struct SOpcodes	S9xOpcodesM1X0[256];
-extern struct SOpcodes	S9xOpcodesM0X1[256];
-extern struct SOpcodes	S9xOpcodesM0X0[256];
-extern struct SOpcodes	S9xOpcodesSlow[256];
-extern uint8_t			S9xOpLengthsM1X1[256];
-extern uint8_t			S9xOpLengthsM1X0[256];
-extern uint8_t			S9xOpLengthsM0X1[256];
-extern uint8_t			S9xOpLengthsM0X0[256];
+extern SICPU ICPU;
+
+extern SOpcodes S9xOpcodesE1[256];
+extern SOpcodes S9xOpcodesM1X1[256];
+extern SOpcodes S9xOpcodesM1X0[256];
+extern SOpcodes S9xOpcodesM0X1[256];
+extern SOpcodes S9xOpcodesM0X0[256];
+extern SOpcodes S9xOpcodesSlow[256];
+extern uint8_t S9xOpLengthsM1X1[256];
+extern uint8_t S9xOpLengthsM1X0[256];
+extern uint8_t S9xOpLengthsM0X1[256];
+extern uint8_t S9xOpLengthsM0X0[256];
 
 void S9xMainLoop();
 void S9xReset();
-void S9xSoftReset();
 void S9xDoHEventProcessing();
 
-static inline void S9xUnpackStatus()
-{
-	ICPU._Zero = (Registers.PL & Zero) == 0;
-	ICPU._Negative = (Registers.PL & Negative);
-	ICPU._Carry = (Registers.PL & Carry);
-	ICPU._Overflow = (Registers.PL & Overflow) >> 6;
+#include "65c816.h"
+
+inline void S9xUnpackStatus()
+{
+	ICPU._Zero = !(Registers.P.B.l & Zero);
+	ICPU._Negative = Registers.P.B.l & Negative;
+	ICPU._Carry = Registers.P.B.l & Carry;
+	ICPU._Overflow = (Registers.P.B.l & Overflow) >> 6;
 }
 
-static inline void S9xPackStatus()
-{
-	Registers.PL &= ~(Zero | Negative | Carry | Overflow);
-	Registers.PL |= ICPU._Carry | ((ICPU._Zero == 0) << 1) | (ICPU._Negative & 0x80) | (ICPU._Overflow << 6);
+inline void S9xPackStatus()
+{
+	Registers.P.B.l &= ~(Zero | Negative | Carry | Overflow);
+	Registers.P.B.l |= ICPU._Carry | ((!ICPU._Zero) << 1) | (ICPU._Negative & 0x80) | (ICPU._Overflow << 6);
 }
 
-static inline void S9xFixCycles()
+inline void S9xFixCycles()
 {
 	if (CheckEmulation())
 	{
 		ICPU.S9xOpcodes = S9xOpcodesE1;
 		ICPU.S9xOpLengths = S9xOpLengthsM1X1;
 	}
-	else
-	if (CheckMemory())
+	else if (CheckMemory())
 	{
 		if (CheckIndex())
 		{
@@ -271,16 +265,16 @@
 	}
 }
 
-static inline void S9xCheckInterrupts()
-{
-	bool	thisIRQ = PPU.HTimerEnabled || PPU.VTimerEnabled;
+inline void S9xCheckInterrupts()
+{
+	bool thisIRQ = PPU.HTimerEnabled || PPU.VTimerEnabled;
 
 	if (CPU.IRQLine && thisIRQ)
 		CPU.IRQTransition = true;
 
 	if (PPU.HTimerEnabled)
 	{
-		int32_t	htimepos = PPU.HTimerPosition;
+		int32_t htimepos = PPU.HTimerPosition;
 		if (CPU.Cycles >= Timings.H_Max)
 			htimepos += Timings.H_Max;
 
@@ -290,22 +284,16 @@
 
 	if (PPU.VTimerEnabled)
 	{
-		int32_t	vcounter = CPU.V_Counter;
+		int32_t vcounter = CPU.V_Counter;
 		if (CPU.Cycles >= Timings.H_Max)
-			vcounter++;
+			++vcounter;
 
 		if (vcounter != PPU.VTimerPosition)
 			thisIRQ = false;
 	}
 
 	if (!CPU.IRQLastState && thisIRQ)
-	{
-#ifdef DEBUGGER
-		S9xTraceFormattedMessage("--- /IRQ High->Low  prev HC:%04d  curr HC:%04d  HTimer:%d Pos:%04d  VTimer:%d Pos:%03d",
-			CPU.PrevCycles, CPU.Cycles, PPU.HTimerEnabled, PPU.HTimerPosition, PPU.VTimerEnabled, PPU.VTimerPosition);
-#endif
 		CPU.IRQLine = true;
-	}
 
 	CPU.IRQLastState = thisIRQ;
 }

--- a/src/in_snsf/snes9x/cpumacro.h
+++ b/src/in_snsf/snes9x/cpumacro.h
@@ -175,140 +175,131 @@
   Nintendo Co., Limited and its subsidiary companies.
  ***********************************************************************************/
 
-
 #ifndef _CPUMACRO_H_
 #define _CPUMACRO_H_
 
-#define rOP8(OP, ADDR, WRAP, FUNC) \
-static void Op##OP() \
-{ \
-	uint8_t	val = OpenBus = S9xGetByte(ADDR(READ)); \
-	FUNC(val); \
-}
-
-#define rOP16(OP, ADDR, WRAP, FUNC) \
-static void Op##OP() \
-{ \
-	uint16_t	val = S9xGetWord(ADDR(READ), WRAP); \
-	OpenBus = (uint8_t) (val >> 8); \
-	FUNC(val); \
-}
-
-#define rOPC(OP, COND, ADDR, WRAP, FUNC) \
-static void Op##OP() \
-{ \
-	if (Check##COND()) \
-	{ \
-		uint8_t	val = OpenBus = S9xGetByte(ADDR(READ)); \
-		FUNC(val); \
-	} \
-	else \
-	{ \
-		uint16_t	val = S9xGetWord(ADDR(READ), WRAP); \
-		OpenBus = (uint8_t) (val >> 8); \
-		FUNC(val); \
-	} \
-}
-
-#define rOPM(OP, ADDR, WRAP, FUNC) \
-rOPC(OP, Memory, ADDR, WRAP, FUNC)
-
-#define rOPX(OP, ADDR, WRAP, FUNC) \
-rOPC(OP, Index, ADDR, WRAP, FUNC)
-
-#define wOP8(OP, ADDR, WRAP, FUNC) \
-static void Op##OP() \
-{ \
-	FUNC##8(ADDR(WRITE)); \
-}
-
-#define wOP16(OP, ADDR, WRAP, FUNC) \
-static void Op##OP() \
-{ \
-	FUNC##16(ADDR(WRITE), WRAP); \
-}
-
-#define wOPC(OP, COND, ADDR, WRAP, FUNC) \
-static void Op##OP() \
-{ \
-	if (Check##COND()) \
-		FUNC##8(ADDR(WRITE)); \
-	else \
-		FUNC##16(ADDR(WRITE), WRAP); \
-}
-
-#define wOPM(OP, ADDR, WRAP, FUNC) \
-wOPC(OP, Memory, ADDR, WRAP, FUNC)
-
-#define wOPX(OP, ADDR, WRAP, FUNC) \
-wOPC(OP, Index, ADDR, WRAP, FUNC)
-
-#define mOP8(OP, ADDR, WRAP, FUNC) \
-static void Op##OP() \
-{ \
-	FUNC##8(ADDR(MODIFY)); \
-}
-
-#define mOP16(OP, ADDR, WRAP, FUNC) \
-static void Op##OP() \
-{ \
-	FUNC##16(ADDR(MODIFY), WRAP); \
-}
-
-#define mOPC(OP, COND, ADDR, WRAP, FUNC) \
-static void Op##OP() \
-{ \
-	if (Check##COND()) \
-		FUNC##8(ADDR(MODIFY)); \
-	else \
-		FUNC##16(ADDR(MODIFY), WRAP); \
-}
-
-#define mOPM(OP, ADDR, WRAP, FUNC) \
-mOPC(OP, Memory, ADDR, WRAP, FUNC)
-
-#define bOP(OP, REL, COND, CHK, E) \
-static void Op##OP() \
-{ \
-	pair	newPC; \
-	newPC.W = REL(JUMP); \
-	if (COND) \
-	{ \
-		AddCycles(ONE_CYCLE); \
-		if (E && Registers.PCh != newPC.B.h) \
-			AddCycles(ONE_CYCLE); \
-		if ((Registers.PCw & ~MEMMAP_MASK) != (newPC.W & ~MEMMAP_MASK)) \
-			S9xSetPCBase(ICPU.ShiftedPB + newPC.W); \
-		else \
-			Registers.PCw = newPC.W; \
-	} \
-}
-
-
-static inline void SetZN (uint16_t Work16)
-{
-	ICPU._Zero = Work16 != 0;
-	ICPU._Negative = (uint8_t) (Work16 >> 8);
-}
-
-static inline void SetZN (uint8_t Work8)
+template<typename Fa, typename Ff> inline void rOP8(Fa addr, Ff func)
+{
+	uint8_t val = OpenBus = S9xGetByte(addr(READ));
+	func(val);
+}
+
+template<typename Fa, typename Ff> inline void rOP16(Fa addr, Ff func, s9xwrap_t wrap = WRAP_NONE)
+{
+	uint16_t val = S9xGetWord(addr(READ), wrap);
+	OpenBus = static_cast<uint8_t>(val >> 8);
+	func(val);
+}
+
+template<typename Fa, typename Ff8, typename Ff16> inline void rOPC(bool cond, Fa addr, Ff8 func8, Ff16 func16, s9xwrap_t wrap = WRAP_NONE)
+{
+	if (cond)
+		rOP8(addr, func8);
+	else
+		rOP16(addr, func16, wrap);
+}
+
+template<typename Fa, typename Ff8, typename Ff16> inline void rOPM(Fa addr, Ff8 func8, Ff16 func16, s9xwrap_t wrap = WRAP_NONE)
+{
+	rOPC(CheckMemory(), addr, func8, func16, wrap);
+}
+
+template<typename Fa, typename Ff8, typename Ff16> inline void rOPX(Fa addr, Ff8 func8, Ff16 func16, s9xwrap_t wrap = WRAP_NONE)
+{
+	rOPC(CheckIndex(), addr, func8, func16, wrap);
+}
+
+template<typename Fa, typename Ff> inline void wOP8(Fa addr, Ff func)
+{
+	func(addr(WRITE));
+}
+
+template<typename Fa, typename Ff> inline void wOP16(Fa addr, Ff func, s9xwrap_t wrap = WRAP_NONE)
+{
+	func(addr(WRITE), wrap);
+}
+
+template<typename Fa, typename Ff8, typename Ff16> inline void wOPC(bool cond, Fa addr, Ff8 func8, Ff16 func16, s9xwrap_t wrap = WRAP_NONE)
+{
+	if (cond)
+		wOP8(addr, func8);
+	else
+		wOP16(addr, func16, wrap);
+}
+
+template<typename Fa, typename Ff8, typename Ff16> inline void wOPM(Fa addr, Ff8 func8, Ff16 func16, s9xwrap_t wrap = WRAP_NONE)
+{
+	wOPC(CheckMemory(), addr, func8, func16, wrap);
+}
+
+template<typename Fa, typename Ff8, typename Ff16> inline void wOPX(Fa addr, Ff8 func8, Ff16 func16, s9xwrap_t wrap = WRAP_NONE)
+{
+	wOPC(CheckIndex(), addr, func8, func16, wrap);
+}
+
+template<typename Fa, typename Ff> inline void mOP8(Fa addr, Ff func)
+{
+	func(addr(MODIFY));
+}
+
+template<typename Fa, typename Ff> inline void mOP16(Fa addr, Ff func, s9xwrap_t wrap = WRAP_NONE)
+{
+	func(addr(MODIFY), wrap);
+}
+
+template<typename Fa, typename Ff8, typename Ff16> inline void mOPC(bool cond, Fa addr, Ff8 func8, Ff16 func16, s9xwrap_t wrap = WRAP_NONE)
+{
+	if (cond)
+		mOP8(addr, func8);
+	else
+		mOP16(addr, func16, wrap);
+}
+
+template<typename Fa, typename Ff8, typename Ff16> inline void mOPM(Fa addr, Ff8 func8, Ff16 func16, s9xwrap_t wrap = WRAP_NONE)
+{
+	mOPC(CheckMemory(), addr, func8, func16, wrap);
+}
+
+template<typename F> inline void bOP(F rel, bool cond, bool e)
+{
+	pair newPC;
+	newPC.W = rel(JUMP);
+	if (cond)
+	{
+		AddCycles(ONE_CYCLE);
+		if (e && Registers.PC.B.xPCh != newPC.B.h)
+			AddCycles(ONE_CYCLE);
+		if ((Registers.PC.W.xPC & ~MEMMAP_MASK) != (newPC.W & ~MEMMAP_MASK))
+			S9xSetPCBase(ICPU.ShiftedPB + newPC.W);
+		else
+			Registers.PC.W.xPC = newPC.W;
+	}
+}
+
+inline void SetZN(uint16_t Work16)
+{
+	ICPU._Zero = !!Work16;
+	ICPU._Negative = static_cast<uint8_t>(Work16 >> 8);
+}
+
+inline void SetZN(uint8_t Work8)
 {
 	ICPU._Zero = Work8;
 	ICPU._Negative = Work8;
 }
 
-static inline void ADC (uint16_t Work16)
+inline void ADC16(uint16_t Work16)
 {
 	if (CheckDecimal())
 	{
-		uint16_t	A1 = Registers.A.W & 0x000F;
-		uint16_t	A2 = Registers.A.W & 0x00F0;
-		uint16_t	A3 = Registers.A.W & 0x0F00;
-		uint32_t	A4 = Registers.A.W & 0xF000;
-		uint16_t	W1 = Work16 & 0x000F;
-		uint16_t	W2 = Work16 & 0x00F0;
-		uint16_t	W3 = Work16 & 0x0F00;
-		uint16_t	W4 = Work16 & 0xF000;
+		uint16_t A1 = Registers.A.W & 0x000F;
+		uint16_t A2 = Registers.A.W & 0x00F0;
+		uint16_t A3 = Registers.A.W & 0x0F00;
+		uint32_t A4 = Registers.A.W & 0xF000;
+		uint16_t W1 = Work16 & 0x000F;
+		uint16_t W2 = Work16 & 0x00F0;
+		uint16_t W3 = Work16 & 0x0F00;
+		uint16_t W4 = Work16 & 0xF000;
 
 		A1 += W1 + CheckCarry();
 		if (A1 > 0x0009)
@@ -344,7 +335,7 @@
 		else
 			ClearCarry();
 
-		uint16_t	Ans16 = A4 | A3 | A2 | A1;
+		uint16_t Ans16 = A4 | A3 | A2 | A1;
 
 		if (~(Registers.A.W ^ Work16) & (Work16 ^ Ans16) & 0x8000)
 			SetOverflow();
@@ -356,28 +347,28 @@
 	}
 	else
 	{
-		uint32_t	Ans32 = Registers.A.W + Work16 + CheckCarry();
+		uint32_t Ans32 = Registers.A.W + Work16 + CheckCarry();
 
 		ICPU._Carry = Ans32 >= 0x10000;
 
-		if (~(Registers.A.W ^ Work16) & (Work16 ^ (uint16_t) Ans32) & 0x8000)
+		if (~(Registers.A.W ^ Work16) & (Work16 ^ static_cast<uint16_t>(Ans32)) & 0x8000)
 			SetOverflow();
 		else
 			ClearOverflow();
 
-		Registers.A.W = (uint16_t) Ans32;
+		Registers.A.W = static_cast<uint16_t>(Ans32);
 		SetZN(Registers.A.W);
 	}
 }
 
-static inline void ADC (uint8_t Work8)
+inline void ADC8(uint8_t Work8)
 {
 	if (CheckDecimal())
 	{
-		uint8_t	A1 = Registers.A.W & 0x0F;
-		uint16_t	A2 = Registers.A.W & 0xF0;
-		uint8_t	W1 = Work8 & 0x0F;
-		uint8_t	W2 = Work8 & 0xF0;
+		uint8_t A1 = Registers.A.W & 0x0F;
+		uint16_t A2 = Registers.A.W & 0xF0;
+		uint8_t W1 = Work8 & 0x0F;
+		uint8_t W2 = Work8 & 0xF0;
 
 		A1 += W1 + CheckCarry();
 		if (A1 > 0x09)
@@ -397,48 +388,48 @@
 		else
 			ClearCarry();
 
-		uint8_t	Ans8 = A2 | A1;
-
-		if (~(Registers.AL ^ Work8) & (Work8 ^ Ans8) & 0x80)
+		uint8_t Ans8 = A2 | A1;
+
+		if (~(Registers.A.B.l ^ Work8) & (Work8 ^ Ans8) & 0x80)
 			SetOverflow();
 		else
 			ClearOverflow();
 
-		Registers.AL = Ans8;
-		SetZN(Registers.AL);
+		Registers.A.B.l = Ans8;
+		SetZN(Registers.A.B.l);
 	}
 	else
 	{
-		uint16_t	Ans16 = Registers.AL + Work8 + CheckCarry();
+		uint16_t Ans16 = Registers.A.B.l + Work8 + CheckCarry();
 
 		ICPU._Carry = Ans16 >= 0x100;
 
-		if (~(Registers.AL ^ Work8) & (Work8 ^ (uint8_t) Ans16) & 0x80)
+		if (~(Registers.A.B.l ^ Work8) & (Work8 ^ static_cast<uint8_t>(Ans16)) & 0x80)
 			SetOverflow();
 		else
 			ClearOverflow();
 
-		Registers.AL = (uint8_t) Ans16;
-		SetZN(Registers.AL);
+		Registers.A.B.l = static_cast<uint8_t>(Ans16);
+		SetZN(Registers.A.B.l);
 	}
 }
 
-static inline void AND (uint16_t Work16)
+inline void AND16(uint16_t Work16)
 {
 	Registers.A.W &= Work16;
 	SetZN(Registers.A.W);
 }
 
-static inline void AND (uint8_t Work8)
-{
-	Registers.AL &= Work8;
-	SetZN(Registers.AL);
-}
-
-static inline void ASL16 (uint32_t OpAddress, s9xwrap_t w)
-{
-	uint16_t	Work16 = S9xGetWord(OpAddress, w);
-	ICPU._Carry = (Work16 & 0x8000) != 0;
+inline void AND8(uint8_t Work8)
+{
+	Registers.A.B.l &= Work8;
+	SetZN(Registers.A.B.l);
+}
+
+inline void ASL16(uint32_t OpAddress, s9xwrap_t w)
+{
+	uint16_t Work16 = S9xGetWord(OpAddress, w);
+	ICPU._Carry = !!(Work16 & 0x8000);
 	Work16 <<= 1;
 	AddCycles(ONE_CYCLE);
 	S9xSetWord(Work16, OpAddress, w, WRITE_10);
@@ -446,10 +437,10 @@
 	SetZN(Work16);
 }
 
-static inline void ASL8 (uint32_t OpAddress)
-{
-	uint8_t	Work8 = S9xGetByte(OpAddress);
-	ICPU._Carry = (Work8 & 0x80) != 0;
+inline void ASL8(uint32_t OpAddress)
+{
+	uint8_t Work8 = S9xGetByte(OpAddress);
+	ICPU._Carry = !!(Work8 & 0x80);
 	Work8 <<= 1;
 	AddCycles(ONE_CYCLE);
 	S9xSetByte(Work8, OpAddress);
@@ -457,149 +448,149 @@
 	SetZN(Work8);
 }
 
-static inline void BIT (uint16_t Work16)
-{
-	ICPU._Overflow = (Work16 & 0x4000) != 0;
-	ICPU._Negative = (uint8_t) (Work16 >> 8);
-	ICPU._Zero = (Work16 & Registers.A.W) != 0;
-}
-
-static inline void BIT (uint8_t Work8)
-{
-	ICPU._Overflow = (Work8 & 0x40) != 0;
+inline void BIT16(uint16_t Work16)
+{
+	ICPU._Overflow = !!(Work16 & 0x4000);
+	ICPU._Negative = static_cast<uint8_t>(Work16 >> 8);
+	ICPU._Zero = !!(Work16 & Registers.A.W);
+}
+
+inline void BIT8(uint8_t Work8)
+{
+	ICPU._Overflow = !!(Work8 & 0x40);
 	ICPU._Negative = Work8;
-	ICPU._Zero = Work8 & Registers.AL;
-}
-
-static inline void CMP (uint16_t val)
-{
-	int32_t	Int32 = (int32_t) Registers.A.W - (int32_t) val;
+	ICPU._Zero = !!(Work8 & Registers.A.B.l);
+}
+
+inline void CMP16(uint16_t val)
+{
+	int32_t Int32 = static_cast<int32_t>(Registers.A.W) - static_cast<int32_t>(val);
 	ICPU._Carry = Int32 >= 0;
-	SetZN((uint16_t) Int32);
-}
-
-static inline void CMP (uint8_t val)
-{
-	int16_t	Int16 = (int16_t) Registers.AL - (int16_t) val;
+	SetZN(static_cast<uint16_t>(Int32));
+}
+
+inline void CMP8(uint8_t val)
+{
+	int16_t Int16 = static_cast<int16_t>(Registers.A.B.l) - static_cast<int16_t>(val);
 	ICPU._Carry = Int16 >= 0;
-	SetZN((uint8_t) Int16);
-}
-
-static inline void CPX (uint16_t val)
-{
-	int32_t	Int32 = (int32_t) Registers.X.W - (int32_t) val;
+	SetZN(static_cast<uint8_t>(Int16));
+}
+
+inline void CPX16(uint16_t val)
+{
+	int32_t Int32 = static_cast<int32_t>(Registers.X.W) - static_cast<int32_t>(val);
 	ICPU._Carry = Int32 >= 0;
-	SetZN((uint16_t) Int32);
-}
-
-static inline void CPX (uint8_t val)
-{
-	int16_t	Int16 = (int16_t) Registers.XL - (int16_t) val;
+	SetZN(static_cast<uint16_t>(Int32));
+}
+
+inline void CPX8(uint8_t val)
+{
+	int16_t Int16 = static_cast<int16_t>(Registers.X.B.l) - static_cast<int16_t>(val);
 	ICPU._Carry = Int16 >= 0;
-	SetZN((uint8_t) Int16);
-}
-
-static inline void CPY (uint16_t val)
-{
-	int32_t	Int32 = (int32_t) Registers.Y.W - (int32_t) val;
+	SetZN(static_cast<uint8_t>(Int16));
+}
+
+inline void CPY16(uint16_t val)
+{
+	int32_t Int32 = static_cast<int32_t>(Registers.Y.W) - static_cast<int32_t>(val);
 	ICPU._Carry = Int32 >= 0;
-	SetZN((uint16_t) Int32);
-}
-
-static inline void CPY (uint8_t val)
-{
-	int16_t	Int16 = (int16_t) Registers.YL - (int16_t) val;
+	SetZN(static_cast<uint16_t>(Int32));
+}
+
+inline void CPY8(uint8_t val)
+{
+	int16_t Int16 = static_cast<int16_t>(Registers.Y.B.l) - static_cast<int16_t>(val);
 	ICPU._Carry = Int16 >= 0;
-	SetZN((uint8_t) Int16);
-}
-
-static inline void DEC16 (uint32_t OpAddress, s9xwrap_t w)
-{
-	uint16_t	Work16 = S9xGetWord(OpAddress, w) - 1;
+	SetZN(static_cast<uint8_t>(Int16));
+}
+
+inline void DEC16(uint32_t OpAddress, s9xwrap_t w)
+{
+	uint16_t Work16 = S9xGetWord(OpAddress, w) - 1;
 	AddCycles(ONE_CYCLE);
 	S9xSetWord(Work16, OpAddress, w, WRITE_10);
 	OpenBus = Work16 & 0xff;
 	SetZN(Work16);
 }
 
-static inline void DEC8 (uint32_t OpAddress)
-{
-	uint8_t	Work8 = S9xGetByte(OpAddress) - 1;
+inline void DEC8(uint32_t OpAddress)
+{
+	uint8_t Work8 = S9xGetByte(OpAddress) - 1;
 	AddCycles(ONE_CYCLE);
 	S9xSetByte(Work8, OpAddress);
 	OpenBus = Work8;
 	SetZN(Work8);
 }
 
-static inline void EOR (uint16_t val)
+inline void EOR16(uint16_t val)
 {
 	Registers.A.W ^= val;
 	SetZN(Registers.A.W);
 }
 
-static inline void EOR (uint8_t val)
-{
-	Registers.AL ^= val;
-	SetZN(Registers.AL);
-}
-
-static inline void INC16 (uint32_t OpAddress, s9xwrap_t w)
-{
-	uint16_t	Work16 = S9xGetWord(OpAddress, w) + 1;
+inline void EOR8(uint8_t val)
+{
+	Registers.A.B.l ^= val;
+	SetZN(Registers.A.B.l);
+}
+
+inline void INC16(uint32_t OpAddress, s9xwrap_t w)
+{
+	uint16_t Work16 = S9xGetWord(OpAddress, w) + 1;
 	AddCycles(ONE_CYCLE);
 	S9xSetWord(Work16, OpAddress, w, WRITE_10);
 	OpenBus = Work16 & 0xff;
 	SetZN(Work16);
 }
 
-static inline void INC8 (uint32_t OpAddress)
-{
-	uint8_t	Work8 = S9xGetByte(OpAddress) + 1;
+inline void INC8(uint32_t OpAddress)
+{
+	uint8_t Work8 = S9xGetByte(OpAddress) + 1;
 	AddCycles(ONE_CYCLE);
 	S9xSetByte(Work8, OpAddress);
 	OpenBus = Work8;
 	SetZN(Work8);
 }
 
-static inline void LDA (uint16_t val)
+inline void LDA16(uint16_t val)
 {
 	Registers.A.W = val;
 	SetZN(Registers.A.W);
 }
 
-static inline void LDA (uint8_t val)
-{
-	Registers.AL = val;
-	SetZN(Registers.AL);
-}
-
-static inline void LDX (uint16_t val)
+inline void LDA8(uint8_t val)
+{
+	Registers.A.B.l = val;
+	SetZN(Registers.A.B.l);
+}
+
+inline void LDX16(uint16_t val)
 {
 	Registers.X.W = val;
 	SetZN(Registers.X.W);
 }
 
-static inline void LDX (uint8_t val)
-{
-	Registers.XL = val;
-	SetZN(Registers.XL);
-}
-
-static inline void LDY (uint16_t val)
+inline void LDX8(uint8_t val)
+{
+	Registers.X.B.l = val;
+	SetZN(Registers.X.B.l);
+}
+
+inline void LDY16(uint16_t val)
 {
 	Registers.Y.W = val;
 	SetZN(Registers.Y.W);
 }
 
-static inline void LDY (uint8_t val)
-{
-	Registers.YL = val;
-	SetZN(Registers.YL);
-}
-
-static inline void LSR16 (uint32_t OpAddress, s9xwrap_t w)
-{
-	uint16_t	Work16 = S9xGetWord(OpAddress, w);
+inline void LDY8(uint8_t val)
+{
+	Registers.Y.B.l = val;
+	SetZN(Registers.Y.B.l);
+}
+
+inline void LSR16(uint32_t OpAddress, s9xwrap_t w)
+{
+	uint16_t Work16 = S9xGetWord(OpAddress, w);
 	ICPU._Carry = Work16 & 1;
 	Work16 >>= 1;
 	AddCycles(ONE_CYCLE);
@@ -608,9 +599,9 @@
 	SetZN(Work16);
 }
 
-static inline void LSR8 (uint32_t OpAddress)
-{
-	uint8_t	Work8 = S9xGetByte(OpAddress);
+inline void LSR8(uint32_t OpAddress)
+{
+	uint8_t Work8 = S9xGetByte(OpAddress);
 	ICPU._Carry = Work8 & 1;
 	Work8 >>= 1;
 	AddCycles(ONE_CYCLE);
@@ -619,72 +610,72 @@
 	SetZN(Work8);
 }
 
-static inline void ORA (uint16_t val)
+inline void ORA16(uint16_t val)
 {
 	Registers.A.W |= val;
 	SetZN(Registers.A.W);
 }
 
-static inline void ORA (uint8_t val)
-{
-	Registers.AL |= val;
-	SetZN(Registers.AL);
-}
-
-static inline void ROL16 (uint32_t OpAddress, s9xwrap_t w)
-{
-	uint32_t	Work32 = (((uint32_t) S9xGetWord(OpAddress, w)) << 1) | CheckCarry();
+inline void ORA8(uint8_t val)
+{
+	Registers.A.B.l |= val;
+	SetZN(Registers.A.B.l);
+}
+
+inline void ROL16(uint32_t OpAddress, s9xwrap_t w)
+{
+	uint32_t Work32 = (static_cast<uint32_t>(S9xGetWord(OpAddress, w)) << 1) | static_cast<uint32_t>(CheckCarry());
 	ICPU._Carry = Work32 >= 0x10000;
 	AddCycles(ONE_CYCLE);
-	S9xSetWord((uint16_t) Work32, OpAddress, w, WRITE_10);
+	S9xSetWord(static_cast<uint16_t>(Work32), OpAddress, w, WRITE_10);
 	OpenBus = Work32 & 0xff;
-	SetZN((uint16_t) Work32);
-}
-
-static inline void ROL8 (uint32_t OpAddress)
-{
-	uint16_t	Work16 = (((uint16_t) S9xGetByte(OpAddress)) << 1) | CheckCarry();
+	SetZN(static_cast<uint16_t>(Work32));
+}
+
+inline void ROL8(uint32_t OpAddress)
+{
+	uint16_t Work16 = (static_cast<uint16_t>(S9xGetByte(OpAddress)) << 1) | static_cast<uint16_t>(CheckCarry());
 	ICPU._Carry = Work16 >= 0x100;
 	AddCycles(ONE_CYCLE);
-	S9xSetByte((uint8_t) Work16, OpAddress);
+	S9xSetByte(static_cast<uint8_t>(Work16), OpAddress);
 	OpenBus = Work16 & 0xff;
-	SetZN((uint8_t) Work16);
-}
-
-static inline void ROR16 (uint32_t OpAddress, s9xwrap_t w)
-{
-	uint32_t	Work32 = ((uint32_t) S9xGetWord(OpAddress, w)) | (((uint32_t) CheckCarry()) << 16);
+	SetZN(static_cast<uint8_t>(Work16));
+}
+
+inline void ROR16(uint32_t OpAddress, s9xwrap_t w)
+{
+	uint32_t Work32 = static_cast<uint32_t>(S9xGetWord(OpAddress, w)) | (static_cast<uint32_t>(CheckCarry()) << 16);
 	ICPU._Carry = Work32 & 1;
 	Work32 >>= 1;
 	AddCycles(ONE_CYCLE);
-	S9xSetWord((uint16_t) Work32, OpAddress, w, WRITE_10);
+	S9xSetWord(static_cast<uint16_t>(Work32), OpAddress, w, WRITE_10);
 	OpenBus = Work32 & 0xff;
-	SetZN((uint16_t) Work32);
-}
-
-static inline void ROR8 (uint32_t OpAddress)
-{
-	uint16_t	Work16 = ((uint16_t) S9xGetByte(OpAddress)) | (((uint16_t) CheckCarry()) << 8);
+	SetZN(static_cast<uint16_t>(Work32));
+}
+
+inline void ROR8(uint32_t OpAddress)
+{
+	uint16_t Work16 = static_cast<uint16_t>(S9xGetByte(OpAddress)) | (static_cast<uint16_t>(CheckCarry()) << 8);
 	ICPU._Carry = Work16 & 1;
 	Work16 >>= 1;
 	AddCycles(ONE_CYCLE);
-	S9xSetByte((uint8_t) Work16, OpAddress);
+	S9xSetByte(static_cast<uint8_t>(Work16), OpAddress);
 	OpenBus = Work16 & 0xff;
-	SetZN((uint8_t) Work16);
-}
-
-static inline void SBC (uint16_t Work16)
+	SetZN(static_cast<uint8_t>(Work16));
+}
+
+inline void SBC16(uint16_t Work16)
 {
 	if (CheckDecimal())
 	{
-		uint16_t	A1 = Registers.A.W & 0x000F;
-		uint16_t	A2 = Registers.A.W & 0x00F0;
-		uint16_t	A3 = Registers.A.W & 0x0F00;
-		uint32_t	A4 = Registers.A.W & 0xF000;
-		uint16_t	W1 = Work16 & 0x000F;
-		uint16_t	W2 = Work16 & 0x00F0;
-		uint16_t	W3 = Work16 & 0x0F00;
-		uint16_t	W4 = Work16 & 0xF000;
+		uint16_t A1 = Registers.A.W & 0x000F;
+		uint16_t A2 = Registers.A.W & 0x00F0;
+		uint16_t A3 = Registers.A.W & 0x0F00;
+		uint32_t A4 = Registers.A.W & 0xF000;
+		uint16_t W1 = Work16 & 0x000F;
+		uint16_t W2 = Work16 & 0x00F0;
+		uint16_t W3 = Work16 & 0x0F00;
+		uint16_t W4 = Work16 & 0xF000;
 
 		A1 -= W1 + !CheckCarry();
 		A2 -= W2;
@@ -721,7 +712,7 @@
 		else
 			SetCarry();
 
-		uint16_t	Ans16 = A4 | A3 | A2 | A1;
+		uint16_t Ans16 = A4 | A3 | A2 | A1;
 
 		if ((Registers.A.W ^ Work16) & (Registers.A.W ^ Ans16) & 0x8000)
 			SetOverflow();
@@ -733,28 +724,28 @@
 	}
 	else
 	{
-		int32_t	Int32 = (int32_t) Registers.A.W - (int32_t) Work16 + (int32_t) CheckCarry() - 1;
+		int32_t Int32 = static_cast<int32_t>(Registers.A.W) - static_cast<int32_t>(Work16) + static_cast<int32_t>(CheckCarry()) - 1;
 
 		ICPU._Carry = Int32 >= 0;
 
-		if ((Registers.A.W ^ Work16) & (Registers.A.W ^ (uint16_t) Int32) & 0x8000)
+		if ((Registers.A.W ^ Work16) & (Registers.A.W ^ static_cast<uint16_t>(Int32)) & 0x8000)
 			SetOverflow();
 		else
 			ClearOverflow();
 
-		Registers.A.W = (uint16_t) Int32;
+		Registers.A.W = static_cast<uint16_t>(Int32);
 		SetZN(Registers.A.W);
 	}
 }
 
-static inline void SBC (uint8_t Work8)
+inline void SBC8(uint8_t Work8)
 {
 	if (CheckDecimal())
 	{
-		uint8_t	A1 = Registers.A.W & 0x0F;
-		uint16_t	A2 = Registers.A.W & 0xF0;
-		uint8_t	W1 = Work8 & 0x0F;
-		uint8_t	W2 = Work8 & 0xF0;
+		uint8_t A1 = Registers.A.W & 0x0F;
+		uint16_t A2 = Registers.A.W & 0xF0;
+		uint8_t W1 = Work8 & 0x0F;
+		uint8_t W2 = Work8 & 0xF0;
 
 		A1 -= W1 + !CheckCarry();
 		A2 -= W2;
@@ -775,115 +766,115 @@
 		else
 			SetCarry();
 
-		uint8_t	Ans8 = A2 | A1;
-
-		if ((Registers.AL ^ Work8) & (Registers.AL ^ Ans8) & 0x80)
+		uint8_t Ans8 = A2 | A1;
+
+		if ((Registers.A.B.l ^ Work8) & (Registers.A.B.l ^ Ans8) & 0x80)
 			SetOverflow();
 		else
 			ClearOverflow();
 
-		Registers.AL = Ans8;
-		SetZN(Registers.AL);
+		Registers.A.B.l = Ans8;
+		SetZN(Registers.A.B.l);
 	}
 	else
 	{
-		int16_t	Int16 = (int16_t) Registers.AL - (int16_t) Work8 + (int16_t) CheckCarry() - 1;
+		int16_t Int16 = static_cast<int16_t>(Registers.A.B.l) - static_cast<int16_t>(Work8) + static_cast<int16_t>(CheckCarry()) - 1;
 
 		ICPU._Carry = Int16 >= 0;
 
-		if ((Registers.AL ^ Work8) & (Registers.AL ^ (uint8_t) Int16) & 0x80)
+		if ((Registers.A.B.l ^ Work8) & (Registers.A.B.l ^ static_cast<uint8_t>(Int16)) & 0x80)
 			SetOverflow();
 		else
 			ClearOverflow();
 
-		Registers.AL = (uint8_t) Int16;
-		SetZN(Registers.AL);
+		Registers.A.B.l = static_cast<uint8_t>(Int16);
+		SetZN(Registers.A.B.l);
 	}
 }
 
-static inline void STA16 (uint32_t OpAddress, enum s9xwrap_t w)
+inline void STA16(uint32_t OpAddress, s9xwrap_t w)
 {
 	S9xSetWord(Registers.A.W, OpAddress, w);
-	OpenBus = Registers.AH;
-}
-
-static inline void STA8 (uint32_t OpAddress)
-{
-	S9xSetByte(Registers.AL, OpAddress);
-	OpenBus = Registers.AL;
-}
-
-static inline void STX16 (uint32_t OpAddress, enum s9xwrap_t w)
+	OpenBus = Registers.A.B.h;
+}
+
+inline void STA8(uint32_t OpAddress)
+{
+	S9xSetByte(Registers.A.B.l, OpAddress);
+	OpenBus = Registers.A.B.l;
+}
+
+inline void STX16(uint32_t OpAddress, s9xwrap_t w)
 {
 	S9xSetWord(Registers.X.W, OpAddress, w);
-	OpenBus = Registers.XH;
-}
-
-static inline void STX8 (uint32_t OpAddress)
-{
-	S9xSetByte(Registers.XL, OpAddress);
-	OpenBus = Registers.XL;
-}
-
-static inline void STY16 (uint32_t OpAddress, enum s9xwrap_t w)
+	OpenBus = Registers.X.B.h;
+}
+
+inline void STX8(uint32_t OpAddress)
+{
+	S9xSetByte(Registers.X.B.l, OpAddress);
+	OpenBus = Registers.X.B.l;
+}
+
+inline void STY16(uint32_t OpAddress, s9xwrap_t w)
 {
 	S9xSetWord(Registers.Y.W, OpAddress, w);
-	OpenBus = Registers.YH;
-}
-
-static inline void STY8 (uint32_t OpAddress)
-{
-	S9xSetByte(Registers.YL, OpAddress);
-	OpenBus = Registers.YL;
-}
-
-static inline void STZ16 (uint32_t OpAddress, enum s9xwrap_t w)
+	OpenBus = Registers.Y.B.h;
+}
+
+inline void STY8(uint32_t OpAddress)
+{
+	S9xSetByte(Registers.Y.B.l, OpAddress);
+	OpenBus = Registers.Y.B.l;
+}
+
+inline void STZ16(uint32_t OpAddress, s9xwrap_t w)
 {
 	S9xSetWord(0, OpAddress, w);
 	OpenBus = 0;
 }
 
-static inline void STZ8 (uint32_t OpAddress)
+inline void STZ8(uint32_t OpAddress)
 {
 	S9xSetByte(0, OpAddress);
 	OpenBus = 0;
 }
 
-static inline void TSB16 (uint32_t OpAddress, enum s9xwrap_t w)
-{
-	uint16_t	Work16 = S9xGetWord(OpAddress, w);
-	ICPU._Zero = (Work16 & Registers.A.W) != 0;
-	Work16 |= Registers.A.W;
+inline void TRB16(uint32_t OpAddress, s9xwrap_t w)
+{
+	uint16_t Work16 = S9xGetWord(OpAddress, w);
+	ICPU._Zero = !!(Work16 & Registers.A.W);
+	Work16 &= ~Registers.A.W;
 	AddCycles(ONE_CYCLE);
 	S9xSetWord(Work16, OpAddress, w, WRITE_10);
 	OpenBus = Work16 & 0xff;
 }
 
-static inline void TSB8 (uint32_t OpAddress)
-{
-	uint8_t	Work8 = S9xGetByte(OpAddress);
-	ICPU._Zero = Work8 & Registers.AL;
-	Work8 |= Registers.AL;
+inline void TRB8(uint32_t OpAddress)
+{
+	uint8_t Work8 = S9xGetByte(OpAddress);
+	ICPU._Zero = Work8 & Registers.A.B.l;
+	Work8 &= ~Registers.A.B.l;
 	AddCycles(ONE_CYCLE);
 	S9xSetByte(Work8, OpAddress);
 	OpenBus = Work8;
 }
 
-static inline void TRB16 (uint32_t OpAddress, enum s9xwrap_t w)
-{
-	uint16_t	Work16 = S9xGetWord(OpAddress, w);
-	ICPU._Zero = (Work16 & Registers.A.W) != 0;
-	Work16 &= ~Registers.A.W;
+inline void TSB16(uint32_t OpAddress, s9xwrap_t w)
+{
+	uint16_t Work16 = S9xGetWord(OpAddress, w);
+	ICPU._Zero = !!(Work16 & Registers.A.W);
+	Work16 |= Registers.A.W;
 	AddCycles(ONE_CYCLE);
 	S9xSetWord(Work16, OpAddress, w, WRITE_10);
 	OpenBus = Work16 & 0xff;
 }
 
-static inline void TRB8 (uint32_t OpAddress)
-{
-	uint8_t	Work8 = S9xGetByte(OpAddress);
-	ICPU._Zero = Work8 & Registers.AL;
-	Work8 &= ~Registers.AL;
+inline void TSB8(uint32_t OpAddress)
+{
+	uint8_t Work8 = S9xGetByte(OpAddress);
+	ICPU._Zero = Work8 & Registers.A.B.l;
+	Work8 |= Registers.A.B.l;
 	AddCycles(ONE_CYCLE);
 	S9xSetByte(Work8, OpAddress);
 	OpenBus = Work8;

--- a/src/in_snsf/snes9x/cpuops.cpp
+++ b/src/in_snsf/snes9x/cpuops.cpp
@@ -179,21 +179,7 @@
 #include "memmap.h"
 #include "apu/apu.h"
 
-// for "Magic WDM" features
-#ifdef DEBUGGER	
-#include "snapshot.h"
-#include "display.h"
-#include "debug.h"
-#include "missing.h"
-#endif
-
-#ifdef SA1_OPCODES
-//#define AddCycles(n)	{ SA1.Cycles += (n); }
-static inline void AddCycles(int32_t n) { SA1.Cycles += n; }
-#else
-//#define AddCycles(n)	{ CPU.PrevCycles = CPU.Cycles; CPU.Cycles += (n); S9xCheckInterrupts(); while (CPU.Cycles >= CPU.NextEvent) S9xDoHEventProcessing(); }
 static inline void AddCycles(int32_t n) { CPU.PrevCycles = CPU.Cycles; CPU.Cycles += n; S9xCheckInterrupts(); while (CPU.Cycles >= CPU.NextEvent) S9xDoHEventProcessing(); }
-#endif
 
 #include "cpuaddr.h"
 #include "cpuops.h"
@@ -201,847 +187,794 @@
 
 /* ADC ********************************************************************* */
 
+template<typename T> static inline void ADC(T Work)
+{
+}
+
+template<> static inline void ADC<uint16_t>(uint16_t Work16)
+{
+	ADC16(Work16);
+}
+
+template<> static inline void ADC<uint8_t>(uint8_t Work8)
+{
+	ADC8(Work8);
+}
+
+template<typename F> static inline void Op69Wrapper(F f)
+{
+	ADC(f(READ));
+}
+
 static void Op69M1()
 {
-	ADC(Immediate8(READ));
+	Op69Wrapper(Immediate8);
 }
 
 static void Op69M0()
 {
-	ADC(Immediate16(READ));
+	Op69Wrapper(Immediate16);
 }
 
 static void Op69Slow()
 {
 	if (CheckMemory())
-		ADC(Immediate8Slow(READ));
-	else
-		ADC(Immediate16Slow(READ));
-}
-
-rOP8 (65M1,     Direct,                           WRAP_BANK, ADC)
-rOP16(65M0,     Direct,                           WRAP_BANK, ADC)
-rOPM (65Slow,   DirectSlow,                       WRAP_BANK, ADC)
-
-rOP8 (75E1,     DirectIndexedXE1,                 WRAP_BANK, ADC)
-rOP8 (75E0M1,   DirectIndexedXE0,                 WRAP_BANK, ADC)
-rOP16(75E0M0,   DirectIndexedXE0,                 WRAP_BANK, ADC)
-rOPM (75Slow,   DirectIndexedXSlow,               WRAP_BANK, ADC)
-
-rOP8 (72E1,     DirectIndirectE1,                 WRAP_NONE, ADC)
-rOP8 (72E0M1,   DirectIndirectE0,                 WRAP_NONE, ADC)
-rOP16(72E0M0,   DirectIndirectE0,                 WRAP_NONE, ADC)
-rOPM (72Slow,   DirectIndirectSlow,               WRAP_NONE, ADC)
-
-rOP8 (61E1,     DirectIndexedIndirectE1,          WRAP_NONE, ADC)
-rOP8 (61E0M1,   DirectIndexedIndirectE0,          WRAP_NONE, ADC)
-rOP16(61E0M0,   DirectIndexedIndirectE0,          WRAP_NONE, ADC)
-rOPM (61Slow,   DirectIndexedIndirectSlow,        WRAP_NONE, ADC)
-
-rOP8 (71E1,     DirectIndirectIndexedE1,          WRAP_NONE, ADC)
-rOP8 (71E0M1X1, DirectIndirectIndexedE0X1,        WRAP_NONE, ADC)
-rOP16(71E0M0X1, DirectIndirectIndexedE0X1,        WRAP_NONE, ADC)
-rOP8 (71E0M1X0, DirectIndirectIndexedE0X0,        WRAP_NONE, ADC)
-rOP16(71E0M0X0, DirectIndirectIndexedE0X0,        WRAP_NONE, ADC)
-rOPM (71Slow,   DirectIndirectIndexedSlow,        WRAP_NONE, ADC)
-
-rOP8 (67M1,     DirectIndirectLong,               WRAP_NONE, ADC)
-rOP16(67M0,     DirectIndirectLong,               WRAP_NONE, ADC)
-rOPM (67Slow,   DirectIndirectLongSlow,           WRAP_NONE, ADC)
-
-rOP8 (77M1,     DirectIndirectIndexedLong,        WRAP_NONE, ADC)
-rOP16(77M0,     DirectIndirectIndexedLong,        WRAP_NONE, ADC)
-rOPM (77Slow,   DirectIndirectIndexedLongSlow,    WRAP_NONE, ADC)
-
-rOP8 (6DM1,     Absolute,                         WRAP_NONE, ADC)
-rOP16(6DM0,     Absolute,                         WRAP_NONE, ADC)
-rOPM (6DSlow,   AbsoluteSlow,                     WRAP_NONE, ADC)
-
-rOP8 (7DM1X1,   AbsoluteIndexedXX1,               WRAP_NONE, ADC)
-rOP16(7DM0X1,   AbsoluteIndexedXX1,               WRAP_NONE, ADC)
-rOP8 (7DM1X0,   AbsoluteIndexedXX0,               WRAP_NONE, ADC)
-rOP16(7DM0X0,   AbsoluteIndexedXX0,               WRAP_NONE, ADC)
-rOPM (7DSlow,   AbsoluteIndexedXSlow,             WRAP_NONE, ADC)
-
-rOP8 (79M1X1,   AbsoluteIndexedYX1,               WRAP_NONE, ADC)
-rOP16(79M0X1,   AbsoluteIndexedYX1,               WRAP_NONE, ADC)
-rOP8 (79M1X0,   AbsoluteIndexedYX0,               WRAP_NONE, ADC)
-rOP16(79M0X0,   AbsoluteIndexedYX0,               WRAP_NONE, ADC)
-rOPM (79Slow,   AbsoluteIndexedYSlow,             WRAP_NONE, ADC)
-
-rOP8 (6FM1,     AbsoluteLong,                     WRAP_NONE, ADC)
-rOP16(6FM0,     AbsoluteLong,                     WRAP_NONE, ADC)
-rOPM (6FSlow,   AbsoluteLongSlow,                 WRAP_NONE, ADC)
-
-rOP8 (7FM1,     AbsoluteLongIndexedX,             WRAP_NONE, ADC)
-rOP16(7FM0,     AbsoluteLongIndexedX,             WRAP_NONE, ADC)
-rOPM (7FSlow,   AbsoluteLongIndexedXSlow,         WRAP_NONE, ADC)
-
-rOP8 (63M1,     StackRelative,                    WRAP_NONE, ADC)
-rOP16(63M0,     StackRelative,                    WRAP_NONE, ADC)
-rOPM (63Slow,   StackRelativeSlow,                WRAP_NONE, ADC)
-
-rOP8 (73M1,     StackRelativeIndirectIndexed,     WRAP_NONE, ADC)
-rOP16(73M0,     StackRelativeIndirectIndexed,     WRAP_NONE, ADC)
-rOPM (73Slow,   StackRelativeIndirectIndexedSlow, WRAP_NONE, ADC)
+		Op69Wrapper(Immediate8Slow);
+	else
+		Op69Wrapper(Immediate16Slow);
+}
+
+static void Op65M1() { rOP8(Direct, ADC8); }
+static void Op65M0() { rOP16(Direct, ADC16, WRAP_BANK); }
+static void Op65Slow() { rOPM(DirectSlow, ADC8, ADC16, WRAP_BANK); }
+
+static void Op75E1() { rOP8(DirectIndexedXE1, ADC8); }
+static void Op75E0M1() { rOP8(DirectIndexedXE0, ADC8); }
+static void Op75E0M0() { rOP16(DirectIndexedXE0, ADC16, WRAP_BANK); }
+static void Op75Slow() { rOPM(DirectIndexedXSlow, ADC8, ADC16, WRAP_BANK); }
+
+static void Op72E1() { rOP8(DirectIndirectE1, ADC8); }
+static void Op72E0M1() { rOP8(DirectIndirectE0, ADC8); }
+static void Op72E0M0() { rOP16(DirectIndirectE0, ADC16); }
+static void Op72Slow() { rOPM(DirectIndirectSlow, ADC8, ADC16); }
+
+static void Op61E1() { rOP8(DirectIndexedIndirectE1, ADC8); }
+static void Op61E0M1() { rOP8(DirectIndexedIndirectE0, ADC8); }
+static void Op61E0M0() { rOP16(DirectIndexedIndirectE0, ADC16); }
+static void Op61Slow() { rOPM(DirectIndexedIndirectSlow, ADC8, ADC16); }
+
+static void Op71E1() { rOP8(DirectIndirectIndexedE1, ADC8); }
+static void Op71E0M1X1() { rOP8(DirectIndirectIndexedE0X1, ADC8); }
+static void Op71E0M0X1() { rOP16(DirectIndirectIndexedE0X1, ADC16); }
+static void Op71E0M1X0() { rOP8(DirectIndirectIndexedE0X0, ADC8); }
+static void Op71E0M0X0() { rOP16(DirectIndirectIndexedE0X0, ADC16); }
+static void Op71Slow() { rOPM(DirectIndirectIndexedSlow, ADC8, ADC16); }
+
+static void Op67M1() { rOP8(DirectIndirectLong, ADC8); }
+static void Op67M0() { rOP16(DirectIndirectLong, ADC16); }
+static void Op67Slow() { rOPM(DirectIndirectLongSlow, ADC8, ADC16); }
+
+static void Op77M1() { rOP8(DirectIndirectIndexedLong, ADC8); }
+static void Op77M0() { rOP16(DirectIndirectIndexedLong, ADC16); }
+static void Op77Slow() { rOPM(DirectIndirectIndexedLongSlow, ADC8, ADC16); }
+
+static void Op6DM1() { rOP8(Absolute, ADC8); }
+static void Op6DM0() { rOP16(Absolute, ADC16); }
+static void Op6DSlow() { rOPM(AbsoluteSlow, ADC8, ADC16); }
+
+static void Op7DM1X1() { rOP8(AbsoluteIndexedXX1, ADC8); }
+static void Op7DM0X1() { rOP16(AbsoluteIndexedXX1, ADC16); }
+static void Op7DM1X0() { rOP8(AbsoluteIndexedXX0, ADC8); }
+static void Op7DM0X0() { rOP16(AbsoluteIndexedXX0, ADC16); }
+static void Op7DSlow() { rOPM(AbsoluteIndexedXSlow, ADC8, ADC16); }
+
+static void Op79M1X1() { rOP8(AbsoluteIndexedYX1, ADC8); }
+static void Op79M0X1() { rOP16(AbsoluteIndexedYX1, ADC16); }
+static void Op79M1X0() { rOP8(AbsoluteIndexedYX0, ADC8); }
+static void Op79M0X0() { rOP16(AbsoluteIndexedYX0, ADC16); }
+static void Op79Slow() { rOPM(AbsoluteIndexedYSlow, ADC8, ADC16); }
+
+static void Op6FM1() { rOP8(AbsoluteLong, ADC8); }
+static void Op6FM0() { rOP16(AbsoluteLong, ADC16); }
+static void Op6FSlow() { rOPM(AbsoluteLongSlow, ADC8, ADC16); }
+
+static void Op7FM1() { rOP8(AbsoluteLongIndexedX, ADC8); }
+static void Op7FM0() { rOP16(AbsoluteLongIndexedX, ADC16); }
+static void Op7FSlow() { rOPM(AbsoluteLongIndexedXSlow, ADC8, ADC16); }
+
+static void Op63M1() { rOP8(StackRelative, ADC8); }
+static void Op63M0() { rOP16(StackRelative, ADC16); }
+static void Op63Slow() { rOPM(StackRelativeSlow, ADC8, ADC16); }
+
+static void Op73M1() { rOP8(StackRelativeIndirectIndexed, ADC8); }
+static void Op73M0() { rOP16(StackRelativeIndirectIndexed, ADC16); }
+static void Op73Slow() { rOPM(StackRelativeIndirectIndexedSlow, ADC8, ADC16); }
 
 /* AND ********************************************************************* */
 
+template<typename T, typename F> static inline void Op29Wrapper(T &reg, F f)
+{
+	reg &= f(READ);
+	SetZN(reg);
+}
+
 static void Op29M1()
 {
-	Registers.AL &= Immediate8(READ);
-	SetZN(Registers.AL);
+	Op29Wrapper(Registers.A.B.l, Immediate8);
 }
 
 static void Op29M0()
 {
-	Registers.A.W &= Immediate16(READ);
-	SetZN(Registers.A.W);
+	Op29Wrapper(Registers.A.W, Immediate16);
 }
 
 static void Op29Slow()
 {
 	if (CheckMemory())
-	{
-		Registers.AL &= Immediate8Slow(READ);
-		SetZN(Registers.AL);
-	}
-	else
-	{
-		Registers.A.W &= Immediate16Slow(READ);
-		SetZN(Registers.A.W);
-	}
-}
-
-rOP8 (25M1,     Direct,                           WRAP_BANK, AND)
-rOP16(25M0,     Direct,                           WRAP_BANK, AND)
-rOPM (25Slow,   DirectSlow,                       WRAP_BANK, AND)
-
-rOP8 (35E1,     DirectIndexedXE1,                 WRAP_BANK, AND)
-rOP8 (35E0M1,   DirectIndexedXE0,                 WRAP_BANK, AND)
-rOP16(35E0M0,   DirectIndexedXE0,                 WRAP_BANK, AND)
-rOPM (35Slow,   DirectIndexedXSlow,               WRAP_BANK, AND)
-
-rOP8 (32E1,     DirectIndirectE1,                 WRAP_NONE, AND)
-rOP8 (32E0M1,   DirectIndirectE0,                 WRAP_NONE, AND)
-rOP16(32E0M0,   DirectIndirectE0,                 WRAP_NONE, AND)
-rOPM (32Slow,   DirectIndirectSlow,               WRAP_NONE, AND)
-
-rOP8 (21E1,     DirectIndexedIndirectE1,          WRAP_NONE, AND)
-rOP8 (21E0M1,   DirectIndexedIndirectE0,          WRAP_NONE, AND)
-rOP16(21E0M0,   DirectIndexedIndirectE0,          WRAP_NONE, AND)
-rOPM (21Slow,   DirectIndexedIndirectSlow,        WRAP_NONE, AND)
-
-rOP8 (31E1,     DirectIndirectIndexedE1,          WRAP_NONE, AND)
-rOP8 (31E0M1X1, DirectIndirectIndexedE0X1,        WRAP_NONE, AND)
-rOP16(31E0M0X1, DirectIndirectIndexedE0X1,        WRAP_NONE, AND)
-rOP8 (31E0M1X0, DirectIndirectIndexedE0X0,        WRAP_NONE, AND)
-rOP16(31E0M0X0, DirectIndirectIndexedE0X0,        WRAP_NONE, AND)
-rOPM (31Slow,   DirectIndirectIndexedSlow,        WRAP_NONE, AND)
-
-rOP8 (27M1,     DirectIndirectLong,               WRAP_NONE, AND)
-rOP16(27M0,     DirectIndirectLong,               WRAP_NONE, AND)
-rOPM (27Slow,   DirectIndirectLongSlow,           WRAP_NONE, AND)
-
-rOP8 (37M1,     DirectIndirectIndexedLong,        WRAP_NONE, AND)
-rOP16(37M0,     DirectIndirectIndexedLong,        WRAP_NONE, AND)
-rOPM (37Slow,   DirectIndirectIndexedLongSlow,    WRAP_NONE, AND)
-
-rOP8 (2DM1,     Absolute,                         WRAP_NONE, AND)
-rOP16(2DM0,     Absolute,                         WRAP_NONE, AND)
-rOPM (2DSlow,   AbsoluteSlow,                     WRAP_NONE, AND)
-
-rOP8 (3DM1X1,   AbsoluteIndexedXX1,               WRAP_NONE, AND)
-rOP16(3DM0X1,   AbsoluteIndexedXX1,               WRAP_NONE, AND)
-rOP8 (3DM1X0,   AbsoluteIndexedXX0,               WRAP_NONE, AND)
-rOP16(3DM0X0,   AbsoluteIndexedXX0,               WRAP_NONE, AND)
-rOPM (3DSlow,   AbsoluteIndexedXSlow,             WRAP_NONE, AND)
-
-rOP8 (39M1X1,   AbsoluteIndexedYX1,               WRAP_NONE, AND)
-rOP16(39M0X1,   AbsoluteIndexedYX1,               WRAP_NONE, AND)
-rOP8 (39M1X0,   AbsoluteIndexedYX0,               WRAP_NONE, AND)
-rOP16(39M0X0,   AbsoluteIndexedYX0,               WRAP_NONE, AND)
-rOPM (39Slow,   AbsoluteIndexedYSlow,             WRAP_NONE, AND)
-
-rOP8 (2FM1,     AbsoluteLong,                     WRAP_NONE, AND)
-rOP16(2FM0,     AbsoluteLong,                     WRAP_NONE, AND)
-rOPM (2FSlow,   AbsoluteLongSlow,                 WRAP_NONE, AND)
-
-rOP8 (3FM1,     AbsoluteLongIndexedX,             WRAP_NONE, AND)
-rOP16(3FM0,     AbsoluteLongIndexedX,             WRAP_NONE, AND)
-rOPM (3FSlow,   AbsoluteLongIndexedXSlow,         WRAP_NONE, AND)
-
-rOP8 (23M1,     StackRelative,                    WRAP_NONE, AND)
-rOP16(23M0,     StackRelative,                    WRAP_NONE, AND)
-rOPM (23Slow,   StackRelativeSlow,                WRAP_NONE, AND)
-
-rOP8 (33M1,     StackRelativeIndirectIndexed,     WRAP_NONE, AND)
-rOP16(33M0,     StackRelativeIndirectIndexed,     WRAP_NONE, AND)
-rOPM (33Slow,   StackRelativeIndirectIndexedSlow, WRAP_NONE, AND)
+		Op29Wrapper(Registers.A.B.l, Immediate8Slow);
+	else
+		Op29Wrapper(Registers.A.W, Immediate16Slow);
+}
+
+static void Op25M1() { rOP8(Direct, AND8); }
+static void Op25M0() { rOP16(Direct, AND16, WRAP_BANK); }
+static void Op25Slow() { rOPM(DirectSlow, AND8, AND16, WRAP_BANK); }
+
+static void Op35E1() { rOP8(DirectIndexedXE1, AND8); }
+static void Op35E0M1() { rOP8(DirectIndexedXE0, AND8); }
+static void Op35E0M0() { rOP16(DirectIndexedXE0, AND16, WRAP_BANK); }
+static void Op35Slow() { rOPM(DirectIndexedXSlow, AND8, AND16, WRAP_BANK); }
+
+static void Op32E1() { rOP8(DirectIndirectE1, AND8); }
+static void Op32E0M1() { rOP8(DirectIndirectE0, AND8); }
+static void Op32E0M0() { rOP16(DirectIndirectE0, AND16); }
+static void Op32Slow() { rOPM(DirectIndirectSlow, AND8, AND16); }
+
+static void Op21E1() { rOP8(DirectIndexedIndirectE1, AND8); }
+static void Op21E0M1() { rOP8(DirectIndexedIndirectE0, AND8); }
+static void Op21E0M0() { rOP16(DirectIndexedIndirectE0, AND16); }
+static void Op21Slow() { rOPM(DirectIndexedIndirectSlow, AND8, AND16); }
+
+static void Op31E1() { rOP8(DirectIndirectIndexedE1, AND8); }
+static void Op31E0M1X1() { rOP8(DirectIndirectIndexedE0X1, AND8); }
+static void Op31E0M0X1() { rOP16(DirectIndirectIndexedE0X1, AND16); }
+static void Op31E0M1X0() { rOP8(DirectIndirectIndexedE0X0, AND8); }
+static void Op31E0M0X0() { rOP16(DirectIndirectIndexedE0X0, AND16); }
+static void Op31Slow() { rOPM(DirectIndirectIndexedSlow, AND8, AND16); }
+
+static void Op27M1() { rOP8(DirectIndirectLong, AND8); }
+static void Op27M0() { rOP16(DirectIndirectLong, AND16); }
+static void Op27Slow() { rOPM(DirectIndirectLongSlow, AND8, AND16); }
+
+static void Op37M1() { rOP8(DirectIndirectIndexedLong, AND8); }
+static void Op37M0() { rOP16(DirectIndirectIndexedLong, AND16); }
+static void Op37Slow() { rOPM(DirectIndirectIndexedLongSlow, AND8, AND16); }
+
+static void Op2DM1() { rOP8(Absolute, AND8); }
+static void Op2DM0() { rOP16(Absolute, AND16); }
+static void Op2DSlow() { rOPM(AbsoluteSlow, AND8, AND16); }
+
+static void Op3DM1X1() { rOP8(AbsoluteIndexedXX1, AND8); }
+static void Op3DM0X1() { rOP16(AbsoluteIndexedXX1, AND16); }
+static void Op3DM1X0() { rOP8(AbsoluteIndexedXX0, AND8); }
+static void Op3DM0X0() { rOP16(AbsoluteIndexedXX0, AND16); }
+static void Op3DSlow() { rOPM(AbsoluteIndexedXSlow, AND8, AND16); }
+
+static void Op39M1X1() { rOP8(AbsoluteIndexedYX1, AND8); }
+static void Op39M0X1() { rOP16(AbsoluteIndexedYX1, AND16); }
+static void Op39M1X0() { rOP8(AbsoluteIndexedYX0, AND8); }
+static void Op39M0X0() { rOP16(AbsoluteIndexedYX0, AND16); }
+static void Op39Slow() { rOPM(AbsoluteIndexedYSlow, AND8, AND16); }
+
+static void Op2FM1() { rOP8(AbsoluteLong, AND8); }
+static void Op2FM0() { rOP16(AbsoluteLong, AND16); }
+static void Op2FSlow() { rOPM(AbsoluteLongSlow, AND8, AND16); }
+
+static void Op3FM1() { rOP8(AbsoluteLongIndexedX, AND8); }
+static void Op3FM0() { rOP16(AbsoluteLongIndexedX, AND16); }
+static void Op3FSlow() { rOPM(AbsoluteLongIndexedXSlow, AND8, AND16); }
+
+static void Op23M1() { rOP8(StackRelative, AND8); }
+static void Op23M0() { rOP16(StackRelative, AND16); }
+static void Op23Slow() { rOPM(StackRelativeSlow, AND8, AND16); }
+
+static void Op33M1() { rOP8(StackRelativeIndirectIndexed, AND8); }
+static void Op33M0() { rOP16(StackRelativeIndirectIndexed, AND16); }
+static void Op33Slow() { rOPM(StackRelativeIndirectIndexedSlow, AND8, AND16); }
 
 /* ASL ********************************************************************* */
 
-static void Op0AM1()
+static inline void Op0AM1()
 {
 	AddCycles(ONE_CYCLE);
-	ICPU._Carry = (Registers.AL & 0x80) != 0;
-	Registers.AL <<= 1;
-	SetZN(Registers.AL);
-}
-
-static void Op0AM0()
+	ICPU._Carry = !!(Registers.A.B.l & 0x80);
+	Registers.A.B.l <<= 1;
+	SetZN(Registers.A.B.l);
+}
+
+static inline void Op0AM0()
 {
 	AddCycles(ONE_CYCLE);
-	ICPU._Carry = (Registers.AH & 0x80) != 0;
+	ICPU._Carry = !!(Registers.A.B.h & 0x80);
 	Registers.A.W <<= 1;
 	SetZN(Registers.A.W);
 }
 
 static void Op0ASlow()
 {
+	if (CheckMemory())
+		Op0AM1();
+	else
+		Op0AM0();
+}
+
+static void Op06M1() { mOP8(Direct, ASL8); }
+static void Op06M0() { mOP16(Direct, ASL16, WRAP_BANK); }
+static void Op06Slow() { mOPM(DirectSlow, ASL8, ASL16, WRAP_BANK); }
+
+static void Op16E1() { mOP8(DirectIndexedXE1, ASL8); }
+static void Op16E0M1() { mOP8(DirectIndexedXE0, ASL8); }
+static void Op16E0M0() { mOP16(DirectIndexedXE0, ASL16, WRAP_BANK); }
+static void Op16Slow() { mOPM(DirectIndexedXSlow, ASL8, ASL16, WRAP_BANK); }
+
+static void Op0EM1() { mOP8(Absolute, ASL8); }
+static void Op0EM0() { mOP16(Absolute, ASL16); }
+static void Op0ESlow() { mOPM(AbsoluteSlow, ASL8, ASL16); }
+
+static void Op1EM1X1() { mOP8(AbsoluteIndexedXX1, ASL8); }
+static void Op1EM0X1() { mOP16(AbsoluteIndexedXX1, ASL16); }
+static void Op1EM1X0() { mOP8(AbsoluteIndexedXX0, ASL8); }
+static void Op1EM0X0() { mOP16(AbsoluteIndexedXX0, ASL16); }
+static void Op1ESlow() { mOPM(AbsoluteIndexedXSlow, ASL8, ASL16); }
+
+/* BIT ********************************************************************* */
+
+template<typename T, typename F> static inline void Op89Wrapper(const T &reg, F f)
+{
+	ICPU._Zero = !!(reg & f(READ));
+}
+
+static void Op89M1()
+{
+	Op89Wrapper(Registers.A.B.l, Immediate8);
+}
+
+static void Op89M0()
+{
+	Op89Wrapper(Registers.A.W, Immediate16);
+}
+
+static void Op89Slow()
+{
+	if (CheckMemory())
+		Op89Wrapper(Registers.A.B.l, Immediate8Slow);
+	else
+		Op89Wrapper(Registers.A.W, Immediate16Slow);
+}
+
+static void Op24M1() { rOP8(Direct, BIT8); }
+static void Op24M0() { rOP16(Direct, BIT16, WRAP_BANK); }
+static void Op24Slow() { rOPM(DirectSlow, BIT8, BIT16, WRAP_BANK); }
+
+static void Op34E1() { rOP8(DirectIndexedXE1, BIT8); }
+static void Op34E0M1() { rOP8(DirectIndexedXE0, BIT8); }
+static void Op34E0M0() { rOP16(DirectIndexedXE0, BIT16, WRAP_BANK); }
+static void Op34Slow() { rOPM(DirectIndexedXSlow, BIT8, BIT16, WRAP_BANK); }
+
+static void Op2CM1() { rOP8(Absolute, BIT8); }
+static void Op2CM0() { rOP16(Absolute, BIT16); }
+static void Op2CSlow() { rOPM(AbsoluteSlow, BIT8, BIT16); }
+
+static void Op3CM1X1() { rOP8(AbsoluteIndexedXX1, BIT8); }
+static void Op3CM0X1() { rOP16(AbsoluteIndexedXX1, BIT16); }
+static void Op3CM1X0() { rOP8(AbsoluteIndexedXX0, BIT8); }
+static void Op3CM0X0() { rOP16(AbsoluteIndexedXX0, BIT16); }
+static void Op3CSlow() { rOPM(AbsoluteIndexedXSlow, BIT8, BIT16); }
+
+/* CMP ********************************************************************* */
+
+template<typename Tint, typename Treg, typename F> static inline void CxPxWrapper(const Treg &reg, F f)
+{
+	Tint intVal = static_cast<Tint>(reg) - static_cast<Tint>(f(READ));
+	ICPU._Carry = intVal >= 0;
+	SetZN(static_cast<Treg>(intVal));
+}
+
+static void OpC9M1()
+{
+	CxPxWrapper<int16_t>(Registers.A.B.l, Immediate8);
+}
+
+static void OpC9M0()
+{
+	CxPxWrapper<int32_t>(Registers.A.W, Immediate16);
+}
+
+static void OpC9Slow()
+{
+	if (CheckMemory())
+		CxPxWrapper<int16_t>(Registers.A.B.l, Immediate8Slow);
+	else
+		CxPxWrapper<int32_t>(Registers.A.W, Immediate16Slow);
+}
+
+static void OpC5M1() { rOP8(Direct, CMP8); }
+static void OpC5M0() { rOP16(Direct, CMP16, WRAP_BANK); }
+static void OpC5Slow() { rOPM(DirectSlow, CMP8, CMP16, WRAP_BANK); }
+
+static void OpD5E1() { rOP8(DirectIndexedXE1, CMP8); }
+static void OpD5E0M1() { rOP8(DirectIndexedXE0, CMP8); }
+static void OpD5E0M0() { rOP16(DirectIndexedXE0, CMP16, WRAP_BANK); }
+static void OpD5Slow() { rOPM(DirectIndexedXSlow, CMP8, CMP16, WRAP_BANK); }
+
+static void OpD2E1() { rOP8(DirectIndirectE1, CMP8); }
+static void OpD2E0M1() { rOP8(DirectIndirectE0, CMP8); }
+static void OpD2E0M0() { rOP16(DirectIndirectE0, CMP16); }
+static void OpD2Slow() { rOPM(DirectIndirectSlow, CMP8, CMP16); }
+
+static void OpC1E1() { rOP8(DirectIndexedIndirectE1, CMP8); }
+static void OpC1E0M1() { rOP8(DirectIndexedIndirectE0, CMP8); }
+static void OpC1E0M0() { rOP16(DirectIndexedIndirectE0, CMP16); }
+static void OpC1Slow() { rOPM(DirectIndexedIndirectSlow, CMP8, CMP16); }
+
+static void OpD1E1() { rOP8(DirectIndirectIndexedE1, CMP8); }
+static void OpD1E0M1X1() { rOP8(DirectIndirectIndexedE0X1, CMP8); }
+static void OpD1E0M0X1() { rOP16(DirectIndirectIndexedE0X1, CMP16); }
+static void OpD1E0M1X0() { rOP8(DirectIndirectIndexedE0X0, CMP8); }
+static void OpD1E0M0X0() { rOP16(DirectIndirectIndexedE0X0, CMP16); }
+static void OpD1Slow() { rOPM(DirectIndirectIndexedSlow, CMP8, CMP16); }
+
+static void OpC7M1() { rOP8(DirectIndirectLong, CMP8); }
+static void OpC7M0() { rOP16(DirectIndirectLong, CMP16); }
+static void OpC7Slow() { rOPM(DirectIndirectLongSlow, CMP8, CMP16); }
+
+static void OpD7M1() { rOP8(DirectIndirectIndexedLong, CMP8); }
+static void OpD7M0() { rOP16(DirectIndirectIndexedLong, CMP16); }
+static void OpD7Slow() { rOPM(DirectIndirectIndexedLongSlow, CMP8, CMP16); }
+
+static void OpCDM1() { rOP8(Absolute, CMP8); }
+static void OpCDM0() { rOP16(Absolute, CMP16); }
+static void OpCDSlow() { rOPM(AbsoluteSlow, CMP8, CMP16); }
+
+static void OpDDM1X1() { rOP8(AbsoluteIndexedXX1, CMP8); }
+static void OpDDM0X1() { rOP16(AbsoluteIndexedXX1, CMP16); }
+static void OpDDM1X0() { rOP8(AbsoluteIndexedXX0, CMP8); }
+static void OpDDM0X0() { rOP16(AbsoluteIndexedXX0, CMP16); }
+static void OpDDSlow() { rOPM(AbsoluteIndexedXSlow, CMP8, CMP16); }
+
+static void OpD9M1X1() { rOP8(AbsoluteIndexedYX1, CMP8); }
+static void OpD9M0X1() { rOP16(AbsoluteIndexedYX1, CMP16); }
+static void OpD9M1X0() { rOP8(AbsoluteIndexedYX0, CMP8); }
+static void OpD9M0X0() { rOP16(AbsoluteIndexedYX0, CMP16); }
+static void OpD9Slow() { rOPM(AbsoluteIndexedYSlow, CMP8, CMP16); }
+
+static void OpCFM1() { rOP8(AbsoluteLong, CMP8); }
+static void OpCFM0() { rOP16(AbsoluteLong, CMP16); }
+static void OpCFSlow() { rOPM(AbsoluteLongSlow, CMP8, CMP16); }
+
+static void OpDFM1() { rOP8(AbsoluteLongIndexedX, CMP8); }
+static void OpDFM0() { rOP16(AbsoluteLongIndexedX, CMP16); }
+static void OpDFSlow() { rOPM(AbsoluteLongIndexedXSlow, CMP8, CMP16); }
+
+static void OpC3M1() { rOP8(StackRelative, CMP8); }
+static void OpC3M0() { rOP16(StackRelative, CMP16); }
+static void OpC3Slow() { rOPM(StackRelativeSlow, CMP8, CMP16); }
+
+static void OpD3M1() { rOP8(StackRelativeIndirectIndexed, CMP8); }
+static void OpD3M0() { rOP16(StackRelativeIndirectIndexed, CMP16); }
+static void OpD3Slow() { rOPM(StackRelativeIndirectIndexedSlow, CMP8, CMP16); }
+
+/* CPX ********************************************************************* */
+
+static void OpE0X1()
+{
+	CxPxWrapper<int16_t>(Registers.X.B.l, Immediate8);
+}
+
+static void OpE0X0()
+{
+	CxPxWrapper<int32_t>(Registers.X.W, Immediate16);
+}
+
+static void OpE0Slow()
+{
+	if (CheckIndex())
+		CxPxWrapper<int16_t>(Registers.X.B.l, Immediate8Slow);
+	else
+		CxPxWrapper<int32_t>(Registers.X.W, Immediate16Slow);
+}
+
+static void OpE4X1() { rOP8(Direct, CPX8); }
+static void OpE4X0() { rOP16(Direct, CPX16, WRAP_BANK); }
+static void OpE4Slow() { rOPX(DirectSlow, CPX8, CPX16, WRAP_BANK); }
+
+static void OpECX1() { rOP8(Absolute, CPX8); }
+static void OpECX0() { rOP16(Absolute, CPX16); }
+static void OpECSlow() { rOPX(AbsoluteSlow, CPX8, CPX16); }
+
+/* CPY ********************************************************************* */
+
+static void OpC0X1()
+{
+	CxPxWrapper<int16_t>(Registers.Y.B.l, Immediate8);
+}
+
+static void OpC0X0()
+{
+	CxPxWrapper<int32_t>(Registers.Y.W, Immediate16);
+}
+
+static void OpC0Slow()
+{
+	if (CheckIndex())
+		CxPxWrapper<int16_t>(Registers.Y.B.l, Immediate8Slow);
+	else
+		CxPxWrapper<int32_t>(Registers.Y.W, Immediate16Slow);
+}
+
+static void OpC4X1() { rOP8(Direct, CPY8); }
+static void OpC4X0() { rOP16(Direct, CPY16, WRAP_BANK); }
+static void OpC4Slow() { rOPX(DirectSlow, CPY8, CPY16, WRAP_BANK); }
+
+static void OpCCX1() { rOP8(Absolute, CPY8); }
+static void OpCCX0() { rOP16(Absolute, CPY16); }
+static void OpCCSlow() { rOPX(AbsoluteSlow, CPY8, CPY16); }
+
+/* DEC ********************************************************************* */
+
+static inline void Op3AM1()
+{
 	AddCycles(ONE_CYCLE);
-
+	--Registers.A.B.l;
+	SetZN(Registers.A.B.l);
+}
+
+static inline void Op3AM0()
+{
+	AddCycles(ONE_CYCLE);
+	--Registers.A.W;
+	SetZN(Registers.A.W);
+}
+
+static void Op3ASlow()
+{
 	if (CheckMemory())
-	{
-		ICPU._Carry = (Registers.AL & 0x80) != 0;
-		Registers.AL <<= 1;
-		SetZN(Registers.AL);
-	}
-	else
-	{
-		ICPU._Carry = (Registers.AH & 0x80) != 0;
-		Registers.A.W <<= 1;
-		SetZN(Registers.A.W);
-	}
-}
-
-mOP8 (06M1,     Direct,                           WRAP_BANK, ASL)
-mOP16(06M0,     Direct,                           WRAP_BANK, ASL)
-mOPM (06Slow,   DirectSlow,                       WRAP_BANK, ASL)
-
-mOP8 (16E1,     DirectIndexedXE1,                 WRAP_BANK, ASL)
-mOP8 (16E0M1,   DirectIndexedXE0,                 WRAP_BANK, ASL)
-mOP16(16E0M0,   DirectIndexedXE0,                 WRAP_BANK, ASL)
-mOPM (16Slow,   DirectIndexedXSlow,               WRAP_BANK, ASL)
-
-mOP8 (0EM1,     Absolute,                         WRAP_NONE, ASL)
-mOP16(0EM0,     Absolute,                         WRAP_NONE, ASL)
-mOPM (0ESlow,   AbsoluteSlow,                     WRAP_NONE, ASL)
-
-mOP8 (1EM1X1,   AbsoluteIndexedXX1,               WRAP_NONE, ASL)
-mOP16(1EM0X1,   AbsoluteIndexedXX1,               WRAP_NONE, ASL)
-mOP8 (1EM1X0,   AbsoluteIndexedXX0,               WRAP_NONE, ASL)
-mOP16(1EM0X0,   AbsoluteIndexedXX0,               WRAP_NONE, ASL)
-mOPM (1ESlow,   AbsoluteIndexedXSlow,             WRAP_NONE, ASL)
-
-/* BIT ********************************************************************* */
-
-static void Op89M1()
-{
-	ICPU._Zero = Registers.AL & Immediate8(READ);
-}
-
-static void Op89M0()
-{
-	ICPU._Zero = (Registers.A.W & Immediate16(READ)) != 0;
-}
-
-static void Op89Slow()
+		Op3AM1();
+	else
+		Op3AM0();
+}
+
+static void OpC6M1() { mOP8(Direct, DEC8); }
+static void OpC6M0() { mOP16(Direct, DEC16, WRAP_BANK); }
+static void OpC6Slow() { mOPM(DirectSlow, DEC8, DEC16, WRAP_BANK); }
+
+static void OpD6E1() { mOP8(DirectIndexedXE1, DEC8); }
+static void OpD6E0M1() { mOP8(DirectIndexedXE0, DEC8); }
+static void OpD6E0M0() { mOP16(DirectIndexedXE0, DEC16, WRAP_BANK); }
+static void OpD6Slow() { mOPM(DirectIndexedXSlow, DEC8, DEC16, WRAP_BANK); }
+
+static void OpCEM1() { mOP8(Absolute, DEC8); }
+static void OpCEM0() { mOP16(Absolute, DEC16); }
+static void OpCESlow() { mOPM(AbsoluteSlow, DEC8, DEC16); }
+
+static void OpDEM1X1() { mOP8(AbsoluteIndexedXX1, DEC8); }
+static void OpDEM0X1() { mOP16(AbsoluteIndexedXX1, DEC16); }
+static void OpDEM1X0() { mOP8(AbsoluteIndexedXX0, DEC8); }
+static void OpDEM0X0() { mOP16(AbsoluteIndexedXX0, DEC16); }
+static void OpDESlow() { mOPM(AbsoluteIndexedXSlow, DEC8, DEC16); }
+
+/* EOR ********************************************************************* */
+
+template<typename T, typename F> static inline void Op49Wrapper(T &reg, F f)
+{
+	reg ^= f(READ);
+	SetZN(reg);
+}
+
+static void Op49M1()
+{
+	Op49Wrapper(Registers.A.B.l, Immediate8);
+}
+
+static void Op49M0()
+{
+	Op49Wrapper(Registers.A.W, Immediate16);
+}
+
+static void Op49Slow()
 {
 	if (CheckMemory())
-		ICPU._Zero = Registers.AL & Immediate8Slow(READ);
-	else
-		ICPU._Zero = (Registers.A.W & Immediate16Slow(READ)) != 0;
-}
-
-rOP8 (24M1,     Direct,                           WRAP_BANK, BIT)
-rOP16(24M0,     Direct,                           WRAP_BANK, BIT)
-rOPM (24Slow,   DirectSlow,                       WRAP_BANK, BIT)
-
-rOP8 (34E1,     DirectIndexedXE1,                 WRAP_BANK, BIT)
-rOP8 (34E0M1,   DirectIndexedXE0,                 WRAP_BANK, BIT)
-rOP16(34E0M0,   DirectIndexedXE0,                 WRAP_BANK, BIT)
-rOPM (34Slow,   DirectIndexedXSlow,               WRAP_BANK, BIT)
-
-rOP8 (2CM1,     Absolute,                         WRAP_NONE, BIT)
-rOP16(2CM0,     Absolute,                         WRAP_NONE, BIT)
-rOPM (2CSlow,   AbsoluteSlow,                     WRAP_NONE, BIT)
-
-rOP8 (3CM1X1,   AbsoluteIndexedXX1,               WRAP_NONE, BIT)
-rOP16(3CM0X1,   AbsoluteIndexedXX1,               WRAP_NONE, BIT)
-rOP8 (3CM1X0,   AbsoluteIndexedXX0,               WRAP_NONE, BIT)
-rOP16(3CM0X0,   AbsoluteIndexedXX0,               WRAP_NONE, BIT)
-rOPM (3CSlow,   AbsoluteIndexedXSlow,             WRAP_NONE, BIT)
-
-/* CMP ********************************************************************* */
-
-static void OpC9M1()
-{
-	int16_t	Int16 = (int16_t) Registers.AL - (int16_t) Immediate8(READ);
-	ICPU._Carry = Int16 >= 0;
-	SetZN((uint8_t) Int16);
-}
-
-static void OpC9M0()
-{
-	int32_t	Int32 = (int32_t) Registers.A.W - (int32_t) Immediate16(READ);
-	ICPU._Carry = Int32 >= 0;
-	SetZN((uint16_t) Int32);
-}
-
-static void OpC9Slow()
+		Op49Wrapper(Registers.A.B.l, Immediate8Slow);
+	else
+		Op49Wrapper(Registers.A.W, Immediate16Slow);
+}
+
+static void Op45M1() { rOP8(Direct, EOR8); }
+static void Op45M0() { rOP16(Direct, EOR16, WRAP_BANK); }
+static void Op45Slow() { rOPM(DirectSlow, EOR8, EOR16, WRAP_BANK); }
+
+static void Op55E1() { rOP8(DirectIndexedXE1, EOR8); }
+static void Op55E0M1() { rOP8(DirectIndexedXE0, EOR8); }
+static void Op55E0M0() { rOP16(DirectIndexedXE0, EOR16, WRAP_BANK); }
+static void Op55Slow() { rOPM(DirectIndexedXSlow, EOR8, EOR16, WRAP_BANK); }
+
+static void Op52E1() { rOP8(DirectIndirectE1, EOR8); }
+static void Op52E0M1() { rOP8(DirectIndirectE0, EOR8); }
+static void Op52E0M0() { rOP16(DirectIndirectE0, EOR16); }
+static void Op52Slow() { rOPM(DirectIndirectSlow, EOR8, EOR16); }
+
+static void Op41E1() { rOP8(DirectIndexedIndirectE1, EOR8); }
+static void Op41E0M1() { rOP8(DirectIndexedIndirectE0, EOR8); }
+static void Op41E0M0() { rOP16(DirectIndexedIndirectE0, EOR16); }
+static void Op41Slow() { rOPM(DirectIndexedIndirectSlow, EOR8, EOR16); }
+
+static void Op51E1() { rOP8(DirectIndirectIndexedE1, EOR8); }
+static void Op51E0M1X1() { rOP8(DirectIndirectIndexedE0X1, EOR8); }
+static void Op51E0M0X1() { rOP16(DirectIndirectIndexedE0X1, EOR16); }
+static void Op51E0M1X0() { rOP8(DirectIndirectIndexedE0X0, EOR8); }
+static void Op51E0M0X0() { rOP16(DirectIndirectIndexedE0X0, EOR16); }
+static void Op51Slow() { rOPM(DirectIndirectIndexedSlow, EOR8, EOR16); }
+
+static void Op47M1() { rOP8(DirectIndirectLong, EOR8); }
+static void Op47M0() { rOP16(DirectIndirectLong, EOR16); }
+static void Op47Slow() { rOPM(DirectIndirectLongSlow, EOR8, EOR16); }
+
+static void Op57M1() { rOP8(DirectIndirectIndexedLong, EOR8); }
+static void Op57M0() { rOP16(DirectIndirectIndexedLong, EOR16); }
+static void Op57Slow() { rOPM(DirectIndirectIndexedLongSlow, EOR8, EOR16); }
+
+static void Op4DM1() { rOP8(Absolute, EOR8); }
+static void Op4DM0() { rOP16(Absolute, EOR16); }
+static void Op4DSlow() { rOPM(AbsoluteSlow, EOR8, EOR16); }
+
+static void Op5DM1X1() { rOP8(AbsoluteIndexedXX1, EOR8); }
+static void Op5DM0X1() { rOP16(AbsoluteIndexedXX1, EOR16); }
+static void Op5DM1X0() { rOP8(AbsoluteIndexedXX0, EOR8); }
+static void Op5DM0X0() { rOP16(AbsoluteIndexedXX0, EOR16); }
+static void Op5DSlow() { rOPM(AbsoluteIndexedXSlow, EOR8, EOR16); }
+
+static void Op59M1X1() { rOP8(AbsoluteIndexedYX1, EOR8); }
+static void Op59M0X1() { rOP16(AbsoluteIndexedYX1, EOR16); }
+static void Op59M1X0() { rOP8(AbsoluteIndexedYX0, EOR8); }
+static void Op59M0X0() { rOP16(AbsoluteIndexedYX0, EOR16); }
+static void Op59Slow() { rOPM(AbsoluteIndexedYSlow, EOR8, EOR16); }
+
+static void Op4FM1() { rOP8(AbsoluteLong, EOR8); }
+static void Op4FM0() { rOP16(AbsoluteLong, EOR16); }
+static void Op4FSlow() { rOPM(AbsoluteLongSlow, EOR8, EOR16); }
+
+static void Op5FM1() { rOP8(AbsoluteLongIndexedX, EOR8); }
+static void Op5FM0() { rOP16(AbsoluteLongIndexedX, EOR16); }
+static void Op5FSlow() { rOPM(AbsoluteLongIndexedXSlow, EOR8, EOR16); }
+
+static void Op43M1() { rOP8(StackRelative, EOR8); }
+static void Op43M0() { rOP16(StackRelative, EOR16); }
+static void Op43Slow() { rOPM(StackRelativeSlow, EOR8, EOR16); }
+
+static void Op53M1() { rOP8(StackRelativeIndirectIndexed, EOR8); }
+static void Op53M0() { rOP16(StackRelativeIndirectIndexed, EOR16); }
+static void Op53Slow() { rOPM(StackRelativeIndirectIndexedSlow, EOR8, EOR16); }
+
+/* INC ********************************************************************* */
+
+static inline void Op1AM1()
+{
+	AddCycles(ONE_CYCLE);
+	++Registers.A.B.l;
+	SetZN(Registers.A.B.l);
+}
+
+static inline void Op1AM0()
+{
+	AddCycles(ONE_CYCLE);
+	++Registers.A.W;
+	SetZN(Registers.A.W);
+}
+
+static void Op1ASlow()
 {
 	if (CheckMemory())
-	{
-		int16_t	Int16 = (int16_t) Registers.AL - (int16_t) Immediate8Slow(READ);
-		ICPU._Carry = Int16 >= 0;
-		SetZN((uint8_t) Int16);
-	}
-	else
-	{
-		int32_t	Int32 = (int32_t) Registers.A.W - (int32_t) Immediate16Slow(READ);
-		ICPU._Carry = Int32 >= 0;
-		SetZN((uint16_t) Int32);
-	}
-}
-
-rOP8 (C5M1,     Direct,                           WRAP_BANK, CMP)
-rOP16(C5M0,     Direct,                           WRAP_BANK, CMP)
-rOPM (C5Slow,   DirectSlow,                       WRAP_BANK, CMP)
-
-rOP8 (D5E1,     DirectIndexedXE1,                 WRAP_BANK, CMP)
-rOP8 (D5E0M1,   DirectIndexedXE0,                 WRAP_BANK, CMP)
-rOP16(D5E0M0,   DirectIndexedXE0,                 WRAP_BANK, CMP)
-rOPM (D5Slow,   DirectIndexedXSlow,               WRAP_BANK, CMP)
-
-rOP8 (D2E1,     DirectIndirectE1,                 WRAP_NONE, CMP)
-rOP8 (D2E0M1,   DirectIndirectE0,                 WRAP_NONE, CMP)
-rOP16(D2E0M0,   DirectIndirectE0,                 WRAP_NONE, CMP)
-rOPM (D2Slow,   DirectIndirectSlow,               WRAP_NONE, CMP)
-
-rOP8 (C1E1,     DirectIndexedIndirectE1,          WRAP_NONE, CMP)
-rOP8 (C1E0M1,   DirectIndexedIndirectE0,          WRAP_NONE, CMP)
-rOP16(C1E0M0,   DirectIndexedIndirectE0,          WRAP_NONE, CMP)
-rOPM (C1Slow,   DirectIndexedIndirectSlow,        WRAP_NONE, CMP)
-
-rOP8 (D1E1,     DirectIndirectIndexedE1,          WRAP_NONE, CMP)
-rOP8 (D1E0M1X1, DirectIndirectIndexedE0X1,        WRAP_NONE, CMP)
-rOP16(D1E0M0X1, DirectIndirectIndexedE0X1,        WRAP_NONE, CMP)
-rOP8 (D1E0M1X0, DirectIndirectIndexedE0X0,        WRAP_NONE, CMP)
-rOP16(D1E0M0X0, DirectIndirectIndexedE0X0,        WRAP_NONE, CMP)
-rOPM (D1Slow,   DirectIndirectIndexedSlow,        WRAP_NONE, CMP)
-
-rOP8 (C7M1,     DirectIndirectLong,               WRAP_NONE, CMP)
-rOP16(C7M0,     DirectIndirectLong,               WRAP_NONE, CMP)
-rOPM (C7Slow,   DirectIndirectLongSlow,           WRAP_NONE, CMP)
-
-rOP8 (D7M1,     DirectIndirectIndexedLong,        WRAP_NONE, CMP)
-rOP16(D7M0,     DirectIndirectIndexedLong,        WRAP_NONE, CMP)
-rOPM (D7Slow,   DirectIndirectIndexedLongSlow,    WRAP_NONE, CMP)
-
-rOP8 (CDM1,     Absolute,                         WRAP_NONE, CMP)
-rOP16(CDM0,     Absolute,                         WRAP_NONE, CMP)
-rOPM (CDSlow,   AbsoluteSlow,                     WRAP_NONE, CMP)
-
-rOP8 (DDM1X1,   AbsoluteIndexedXX1,               WRAP_NONE, CMP)
-rOP16(DDM0X1,   AbsoluteIndexedXX1,               WRAP_NONE, CMP)
-rOP8 (DDM1X0,   AbsoluteIndexedXX0,               WRAP_NONE, CMP)
-rOP16(DDM0X0,   AbsoluteIndexedXX0,               WRAP_NONE, CMP)
-rOPM (DDSlow,   AbsoluteIndexedXSlow,             WRAP_NONE, CMP)
-
-rOP8 (D9M1X1,   AbsoluteIndexedYX1,               WRAP_NONE, CMP)
-rOP16(D9M0X1,   AbsoluteIndexedYX1,               WRAP_NONE, CMP)
-rOP8 (D9M1X0,   AbsoluteIndexedYX0,               WRAP_NONE, CMP)
-rOP16(D9M0X0,   AbsoluteIndexedYX0,               WRAP_NONE, CMP)
-rOPM (D9Slow,   AbsoluteIndexedYSlow,             WRAP_NONE, CMP)
-
-rOP8 (CFM1,     AbsoluteLong,                     WRAP_NONE, CMP)
-rOP16(CFM0,     AbsoluteLong,                     WRAP_NONE, CMP)
-rOPM (CFSlow,   AbsoluteLongSlow,                 WRAP_NONE, CMP)
-
-rOP8 (DFM1,     AbsoluteLongIndexedX,             WRAP_NONE, CMP)
-rOP16(DFM0,     AbsoluteLongIndexedX,             WRAP_NONE, CMP)
-rOPM (DFSlow,   AbsoluteLongIndexedXSlow,         WRAP_NONE, CMP)
-
-rOP8 (C3M1,     StackRelative,                    WRAP_NONE, CMP)
-rOP16(C3M0,     StackRelative,                    WRAP_NONE, CMP)
-rOPM (C3Slow,   StackRelativeSlow,                WRAP_NONE, CMP)
-
-rOP8 (D3M1,     StackRelativeIndirectIndexed,     WRAP_NONE, CMP)
-rOP16(D3M0,     StackRelativeIndirectIndexed,     WRAP_NONE, CMP)
-rOPM (D3Slow,   StackRelativeIndirectIndexedSlow, WRAP_NONE, CMP)
-
-/* CPX ********************************************************************* */
-
-static void OpE0X1()
-{
-	int16_t	Int16 = (int16_t) Registers.XL - (int16_t) Immediate8(READ);
-	ICPU._Carry = Int16 >= 0;
-	SetZN((uint8_t) Int16);
-}
-
-static void OpE0X0()
-{
-	int32_t	Int32 = (int32_t) Registers.X.W - (int32_t) Immediate16(READ);
-	ICPU._Carry = Int32 >= 0;
-	SetZN((uint16_t) Int32);
-}
-
-static void OpE0Slow()
+		Op1AM1();
+	else
+		Op1AM0();
+}
+
+static void OpE6M1() { mOP8(Direct, INC8); }
+static void OpE6M0() { mOP16(Direct, INC16, WRAP_BANK); }
+static void OpE6Slow() { mOPM(DirectSlow, INC8, INC16, WRAP_BANK); }
+
+static void OpF6E1() { mOP8(DirectIndexedXE1, INC8); }
+static void OpF6E0M1() { mOP8(DirectIndexedXE0, INC8); }
+static void OpF6E0M0() { mOP16(DirectIndexedXE0, INC16, WRAP_BANK); }
+static void OpF6Slow() { mOPM(DirectIndexedXSlow, INC8, INC16, WRAP_BANK); }
+
+static void OpEEM1() { mOP8(Absolute, INC8); }
+static void OpEEM0() { mOP16(Absolute, INC16); }
+static void OpEESlow() { mOPM(AbsoluteSlow, INC8, INC16); }
+
+static void OpFEM1X1() { mOP8(AbsoluteIndexedXX1, INC8); }
+static void OpFEM0X1() { mOP16(AbsoluteIndexedXX1, INC16); }
+static void OpFEM1X0() { mOP8(AbsoluteIndexedXX0, INC8); }
+static void OpFEM0X0() { mOP16(AbsoluteIndexedXX0, INC16); }
+static void OpFESlow() { mOPM(AbsoluteIndexedXSlow, INC8, INC16); }
+
+/* LDA ********************************************************************* */
+
+template<typename T, typename F> static inline void LDWrapper(T &reg, F f)
+{
+	reg = f(READ);
+	SetZN(reg);
+}
+
+static void OpA9M1()
+{
+	LDWrapper(Registers.A.B.l, Immediate8);
+}
+
+static void OpA9M0()
+{
+	LDWrapper(Registers.A.W, Immediate16);
+}
+
+static void OpA9Slow()
+{
+	if (CheckMemory())
+		LDWrapper(Registers.A.B.l, Immediate8Slow);
+	else
+		LDWrapper(Registers.A.W, Immediate16Slow);
+}
+
+static void OpA5M1() { rOP8(Direct, LDA8); }
+static void OpA5M0() { rOP16(Direct, LDA16, WRAP_BANK); }
+static void OpA5Slow() { rOPM(DirectSlow, LDA8, LDA16, WRAP_BANK); }
+
+static void OpB5E1() { rOP8(DirectIndexedXE1, LDA8); }
+static void OpB5E0M1() { rOP8(DirectIndexedXE0, LDA8); }
+static void OpB5E0M0() { rOP16(DirectIndexedXE0, LDA16, WRAP_BANK); }
+static void OpB5Slow() { rOPM(DirectIndexedXSlow, LDA8, LDA16, WRAP_BANK); }
+
+static void OpB2E1() { rOP8(DirectIndirectE1, LDA8); }
+static void OpB2E0M1() { rOP8(DirectIndirectE0, LDA8); }
+static void OpB2E0M0() { rOP16(DirectIndirectE0, LDA16); }
+static void OpB2Slow() { rOPM(DirectIndirectSlow, LDA8, LDA16); }
+
+static void OpA1E1() { rOP8(DirectIndexedIndirectE1, LDA8); }
+static void OpA1E0M1() { rOP8(DirectIndexedIndirectE0, LDA8); }
+static void OpA1E0M0() { rOP16(DirectIndexedIndirectE0, LDA16); }
+static void OpA1Slow() { rOPM(DirectIndexedIndirectSlow, LDA8, LDA16); }
+
+static void OpB1E1() { rOP8(DirectIndirectIndexedE1, LDA8); }
+static void OpB1E0M1X1() { rOP8(DirectIndirectIndexedE0X1, LDA8); }
+static void OpB1E0M0X1() { rOP16(DirectIndirectIndexedE0X1, LDA16); }
+static void OpB1E0M1X0() { rOP8(DirectIndirectIndexedE0X0, LDA8); }
+static void OpB1E0M0X0() { rOP16(DirectIndirectIndexedE0X0, LDA16); }
+static void OpB1Slow() { rOPM(DirectIndirectIndexedSlow, LDA8, LDA16); }
+
+static void OpA7M1() { rOP8(DirectIndirectLong, LDA8); }
+static void OpA7M0() { rOP16(DirectIndirectLong, LDA16); }
+static void OpA7Slow() { rOPM(DirectIndirectLongSlow, LDA8, LDA16); }
+
+static void OpB7M1() { rOP8(DirectIndirectIndexedLong, LDA8); }
+static void OpB7M0() { rOP16(DirectIndirectIndexedLong, LDA16); }
+static void OpB7Slow() { rOPM(DirectIndirectIndexedLongSlow, LDA8, LDA16); }
+
+static void OpADM1() { rOP8(Absolute, LDA8); }
+static void OpADM0() { rOP16(Absolute, LDA16); }
+static void OpADSlow() { rOPM(AbsoluteSlow, LDA8, LDA16); }
+
+static void OpBDM1X1() { rOP8(AbsoluteIndexedXX1, LDA8); }
+static void OpBDM0X1() { rOP16(AbsoluteIndexedXX1, LDA16); }
+static void OpBDM1X0() { rOP8(AbsoluteIndexedXX0, LDA8); }
+static void OpBDM0X0() { rOP16(AbsoluteIndexedXX0, LDA16); }
+static void OpBDSlow() { rOPM(AbsoluteIndexedXSlow, LDA8, LDA16); }
+
+static void OpB9M1X1() { rOP8(AbsoluteIndexedYX1, LDA8); }
+static void OpB9M0X1() { rOP16(AbsoluteIndexedYX1, LDA16); }
+static void OpB9M1X0() { rOP8(AbsoluteIndexedYX0, LDA8); }
+static void OpB9M0X0() { rOP16(AbsoluteIndexedYX0, LDA16); }
+static void OpB9Slow() { rOPM(AbsoluteIndexedYSlow, LDA8, LDA16); }
+
+static void OpAFM1() { rOP8(AbsoluteLong, LDA8); }
+static void OpAFM0() { rOP16(AbsoluteLong, LDA16); }
+static void OpAFSlow() { rOPM(AbsoluteLongSlow, LDA8, LDA16); }
+
+static void OpBFM1() { rOP8(AbsoluteLongIndexedX, LDA8); }
+static void OpBFM0() { rOP16(AbsoluteLongIndexedX, LDA16); }
+static void OpBFSlow() { rOPM(AbsoluteLongIndexedXSlow, LDA8, LDA16); }
+
+static void OpA3M1() { rOP8(StackRelative, LDA8); }
+static void OpA3M0() { rOP16(StackRelative, LDA16); }
+static void OpA3Slow() { rOPM(StackRelativeSlow, LDA8, LDA16); }
+
+static void OpB3M1() { rOP8(StackRelativeIndirectIndexed, LDA8); }
+static void OpB3M0() { rOP16(StackRelativeIndirectIndexed, LDA16); }
+static void OpB3Slow() { rOPM(StackRelativeIndirectIndexedSlow, LDA8, LDA16); }
+
+/* LDX ********************************************************************* */
+
+static void OpA2X1()
+{
+	LDWrapper(Registers.X.B.l, Immediate8);
+}
+
+static void OpA2X0()
+{
+	LDWrapper(Registers.X.W, Immediate16);
+}
+
+static void OpA2Slow()
 {
 	if (CheckIndex())
-	{
-		int16_t	Int16 = (int16_t) Registers.XL - (int16_t) Immediate8Slow(READ);
-		ICPU._Carry = Int16 >= 0;
-		SetZN((uint8_t) Int16);
-	}
-	else
-	{
-		int32_t	Int32 = (int32_t) Registers.X.W - (int32_t) Immediate16Slow(READ);
-		ICPU._Carry = Int32 >= 0;
-		SetZN((uint16_t) Int32);
-	}
-}
-
-rOP8 (E4X1,     Direct,                           WRAP_BANK, CPX)
-rOP16(E4X0,     Direct,                           WRAP_BANK, CPX)
-rOPX (E4Slow,   DirectSlow,                       WRAP_BANK, CPX)
-
-rOP8 (ECX1,     Absolute,                         WRAP_NONE, CPX)
-rOP16(ECX0,     Absolute,                         WRAP_NONE, CPX)
-rOPX (ECSlow,   AbsoluteSlow,                     WRAP_NONE, CPX)
-
-/* CPY ********************************************************************* */
-
-static void OpC0X1()
-{
-	int16_t	Int16 = (int16_t) Registers.YL - (int16_t) Immediate8(READ);
-	ICPU._Carry = Int16 >= 0;
-	SetZN((uint8_t) Int16);
-}
-
-static void OpC0X0()
-{
-	int32_t	Int32 = (int32_t) Registers.Y.W - (int32_t) Immediate16(READ);
-	ICPU._Carry = Int32 >= 0;
-	SetZN((uint16_t) Int32);
-}
-
-static void OpC0Slow()
+		LDWrapper(Registers.X.B.l, Immediate8Slow);
+	else
+		LDWrapper(Registers.X.W, Immediate16Slow);
+}
+
+static void OpA6X1() { rOP8(Direct, LDX8); }
+static void OpA6X0() { rOP16(Direct, LDX16, WRAP_BANK); }
+static void OpA6Slow() { rOPX(DirectSlow, LDX8, LDX16, WRAP_BANK); }
+
+static void OpB6E1() { rOP8(DirectIndexedYE1, LDX8); }
+static void OpB6E0X1() { rOP8(DirectIndexedYE0, LDX8); }
+static void OpB6E0X0() { rOP16(DirectIndexedYE0, LDX16, WRAP_BANK); }
+static void OpB6Slow() { rOPX(DirectIndexedYSlow, LDX8, LDX16, WRAP_BANK); }
+
+static void OpAEX1() { rOP8(Absolute, LDX8); }
+static void OpAEX0() { rOP16(Absolute, LDX16, WRAP_BANK); }
+static void OpAESlow() { rOPX(AbsoluteSlow, LDX8, LDX16, WRAP_BANK); }
+
+static void OpBEX1() { rOP8(AbsoluteIndexedYX1, LDX8); }
+static void OpBEX0() { rOP16(AbsoluteIndexedYX0, LDX16, WRAP_BANK); }
+static void OpBESlow() { rOPX(AbsoluteIndexedYSlow, LDX8, LDX16, WRAP_BANK); }
+
+/* LDY ********************************************************************* */
+
+static void OpA0X1()
+{
+	LDWrapper(Registers.Y.B.l, Immediate8);
+}
+
+static void OpA0X0()
+{
+	LDWrapper(Registers.Y.W, Immediate16);
+}
+
+static void OpA0Slow()
 {
 	if (CheckIndex())
-	{
-		int16_t	Int16 = (int16_t) Registers.YL - (int16_t) Immediate8Slow(READ);
-		ICPU._Carry = Int16 >= 0;
-		SetZN((uint8_t) Int16);
-	}
-	else
-	{
-		int32_t	Int32 = (int32_t) Registers.Y.W - (int32_t) Immediate16Slow(READ);
-		ICPU._Carry = Int32 >= 0;
-		SetZN((uint16_t) Int32);
-	}
-}
-
-rOP8 (C4X1,     Direct,                           WRAP_BANK, CPY)
-rOP16(C4X0,     Direct,                           WRAP_BANK, CPY)
-rOPX (C4Slow,   DirectSlow,                       WRAP_BANK, CPY)
-
-rOP8 (CCX1,     Absolute,                         WRAP_NONE, CPY)
-rOP16(CCX0,     Absolute,                         WRAP_NONE, CPY)
-rOPX (CCSlow,   AbsoluteSlow,                     WRAP_NONE, CPY)
-
-/* DEC ********************************************************************* */
-
-static void Op3AM1()
+		LDWrapper(Registers.Y.B.l, Immediate8Slow);
+	else
+		LDWrapper(Registers.Y.W, Immediate16Slow);
+}
+
+static void OpA4X1() { rOP8(Direct, LDY8); }
+static void OpA4X0() { rOP16(Direct, LDY16, WRAP_BANK); }
+static void OpA4Slow() { rOPX(DirectSlow, LDY8, LDY16, WRAP_BANK); }
+
+static void OpB4E1() { rOP8(DirectIndexedXE1, LDY8); }
+static void OpB4E0X1() { rOP8(DirectIndexedXE0, LDY8); }
+static void OpB4E0X0() { rOP16(DirectIndexedXE0, LDY16, WRAP_BANK); }
+static void OpB4Slow() { rOPX(DirectIndexedXSlow, LDY8, LDY16, WRAP_BANK); }
+
+static void OpACX1() { rOP8(Absolute, LDY8); }
+static void OpACX0() { rOP16(Absolute, LDY16, WRAP_BANK); }
+static void OpACSlow() { rOPX(AbsoluteSlow, LDY8, LDY16, WRAP_BANK); }
+
+static void OpBCX1() { rOP8(AbsoluteIndexedXX1, LDY8); }
+static void OpBCX0() { rOP16(AbsoluteIndexedXX0, LDY16, WRAP_BANK); }
+static void OpBCSlow() { rOPX(AbsoluteIndexedXSlow, LDY8, LDY16, WRAP_BANK); }
+
+/* LSR ********************************************************************* */
+
+static inline void Op4AM1()
 {
 	AddCycles(ONE_CYCLE);
-	Registers.AL--;
-	SetZN(Registers.AL);
-}
-
-static void Op3AM0()
-{
-	AddCycles(ONE_CYCLE);
-	Registers.A.W--;
-	SetZN(Registers.A.W);
-}
-
-static void Op3ASlow()
-{
-	AddCycles(ONE_CYCLE);
-
-	if (CheckMemory())
-	{
-		Registers.AL--;
-		SetZN(Registers.AL);
-	}
-	else
-	{
-		Registers.A.W--;
-		SetZN(Registers.A.W);
-	}
-}
-
-mOP8 (C6M1,     Direct,                           WRAP_BANK, DEC)
-mOP16(C6M0,     Direct,                           WRAP_BANK, DEC)
-mOPM (C6Slow,   DirectSlow,                       WRAP_BANK, DEC)
-
-mOP8 (D6E1,     DirectIndexedXE1,                 WRAP_BANK, DEC)
-mOP8 (D6E0M1,   DirectIndexedXE0,                 WRAP_BANK, DEC)
-mOP16(D6E0M0,   DirectIndexedXE0,                 WRAP_BANK, DEC)
-mOPM (D6Slow,   DirectIndexedXSlow,               WRAP_BANK, DEC)
-
-mOP8 (CEM1,     Absolute,                         WRAP_NONE, DEC)
-mOP16(CEM0,     Absolute,                         WRAP_NONE, DEC)
-mOPM (CESlow,   AbsoluteSlow,                     WRAP_NONE, DEC)
-
-mOP8 (DEM1X1,   AbsoluteIndexedXX1,               WRAP_NONE, DEC)
-mOP16(DEM0X1,   AbsoluteIndexedXX1,               WRAP_NONE, DEC)
-mOP8 (DEM1X0,   AbsoluteIndexedXX0,               WRAP_NONE, DEC)
-mOP16(DEM0X0,   AbsoluteIndexedXX0,               WRAP_NONE, DEC)
-mOPM (DESlow,   AbsoluteIndexedXSlow,             WRAP_NONE, DEC)
-
-/* EOR ********************************************************************* */
-
-static void Op49M1()
-{
-	Registers.AL ^= Immediate8(READ);
-	SetZN(Registers.AL);
-}
-
-static void Op49M0()
-{
-	Registers.A.W ^= Immediate16(READ);
-	SetZN(Registers.A.W);
-}
-
-static void Op49Slow()
-{
-	if (CheckMemory())
-	{
-		Registers.AL ^= Immediate8Slow(READ);
-		SetZN(Registers.AL);
-	}
-	else
-	{
-		Registers.A.W ^= Immediate16Slow(READ);
-		SetZN(Registers.A.W);
-	}
-}
-
-rOP8 (45M1,     Direct,                           WRAP_BANK, EOR)
-rOP16(45M0,     Direct,                           WRAP_BANK, EOR)
-rOPM (45Slow,   DirectSlow,                       WRAP_BANK, EOR)
-
-rOP8 (55E1,     DirectIndexedXE1,                 WRAP_BANK, EOR)
-rOP8 (55E0M1,   DirectIndexedXE0,                 WRAP_BANK, EOR)
-rOP16(55E0M0,   DirectIndexedXE0,                 WRAP_BANK, EOR)
-rOPM (55Slow,   DirectIndexedXSlow,               WRAP_BANK, EOR)
-
-rOP8 (52E1,     DirectIndirectE1,                 WRAP_NONE, EOR)
-rOP8 (52E0M1,   DirectIndirectE0,                 WRAP_NONE, EOR)
-rOP16(52E0M0,   DirectIndirectE0,                 WRAP_NONE, EOR)
-rOPM (52Slow,   DirectIndirectSlow,               WRAP_NONE, EOR)
-
-rOP8 (41E1,     DirectIndexedIndirectE1,          WRAP_NONE, EOR)
-rOP8 (41E0M1,   DirectIndexedIndirectE0,          WRAP_NONE, EOR)
-rOP16(41E0M0,   DirectIndexedIndirectE0,          WRAP_NONE, EOR)
-rOPM (41Slow,   DirectIndexedIndirectSlow,        WRAP_NONE, EOR)
-
-rOP8 (51E1,     DirectIndirectIndexedE1,          WRAP_NONE, EOR)
-rOP8 (51E0M1X1, DirectIndirectIndexedE0X1,        WRAP_NONE, EOR)
-rOP16(51E0M0X1, DirectIndirectIndexedE0X1,        WRAP_NONE, EOR)
-rOP8 (51E0M1X0, DirectIndirectIndexedE0X0,        WRAP_NONE, EOR)
-rOP16(51E0M0X0, DirectIndirectIndexedE0X0,        WRAP_NONE, EOR)
-rOPM (51Slow,   DirectIndirectIndexedSlow,        WRAP_NONE, EOR)
-
-rOP8 (47M1,     DirectIndirectLong,               WRAP_NONE, EOR)
-rOP16(47M0,     DirectIndirectLong,               WRAP_NONE, EOR)
-rOPM (47Slow,   DirectIndirectLongSlow,           WRAP_NONE, EOR)
-
-rOP8 (57M1,     DirectIndirectIndexedLong,        WRAP_NONE, EOR)
-rOP16(57M0,     DirectIndirectIndexedLong,        WRAP_NONE, EOR)
-rOPM (57Slow,   DirectIndirectIndexedLongSlow,    WRAP_NONE, EOR)
-
-rOP8 (4DM1,     Absolute,                         WRAP_NONE, EOR)
-rOP16(4DM0,     Absolute,                         WRAP_NONE, EOR)
-rOPM (4DSlow,   AbsoluteSlow,                     WRAP_NONE, EOR)
-
-rOP8 (5DM1X1,   AbsoluteIndexedXX1,               WRAP_NONE, EOR)
-rOP16(5DM0X1,   AbsoluteIndexedXX1,               WRAP_NONE, EOR)
-rOP8 (5DM1X0,   AbsoluteIndexedXX0,               WRAP_NONE, EOR)
-rOP16(5DM0X0,   AbsoluteIndexedXX0,               WRAP_NONE, EOR)
-rOPM (5DSlow,   AbsoluteIndexedXSlow,             WRAP_NONE, EOR)
-
-rOP8 (59M1X1,   AbsoluteIndexedYX1,               WRAP_NONE, EOR)
-rOP16(59M0X1,   AbsoluteIndexedYX1,               WRAP_NONE, EOR)
-rOP8 (59M1X0,   AbsoluteIndexedYX0,               WRAP_NONE, EOR)
-rOP16(59M0X0,   AbsoluteIndexedYX0,               WRAP_NONE, EOR)
-rOPM (59Slow,   AbsoluteIndexedYSlow,             WRAP_NONE, EOR)
-
-rOP8 (4FM1,     AbsoluteLong,                     WRAP_NONE, EOR)
-rOP16(4FM0,     AbsoluteLong,                     WRAP_NONE, EOR)
-rOPM (4FSlow,   AbsoluteLongSlow,                 WRAP_NONE, EOR)
-
-rOP8 (5FM1,     AbsoluteLongIndexedX,             WRAP_NONE, EOR)
-rOP16(5FM0,     AbsoluteLongIndexedX,             WRAP_NONE, EOR)
-rOPM (5FSlow,   AbsoluteLongIndexedXSlow,         WRAP_NONE, EOR)
-
-rOP8 (43M1,     StackRelative,                    WRAP_NONE, EOR)
-rOP16(43M0,     StackRelative,                    WRAP_NONE, EOR)
-rOPM (43Slow,   StackRelativeSlow,                WRAP_NONE, EOR)
-
-rOP8 (53M1,     StackRelativeIndirectIndexed,     WRAP_NONE, EOR)
-rOP16(53M0,     StackRelativeIndirectIndexed,     WRAP_NONE, EOR)
-rOPM (53Slow,   StackRelativeIndirectIndexedSlow, WRAP_NONE, EOR)
-
-/* INC ********************************************************************* */
-
-static void Op1AM1()
-{
-	AddCycles(ONE_CYCLE);
-	Registers.AL++;
-	SetZN(Registers.AL);
-}
-
-static void Op1AM0()
-{
-	AddCycles(ONE_CYCLE);
-	Registers.A.W++;
-	SetZN(Registers.A.W);
-}
-
-static void Op1ASlow()
-{
-	AddCycles(ONE_CYCLE);
-
-	if (CheckMemory())
-	{
-		Registers.AL++;
-		SetZN(Registers.AL);
-	}
-	else
-	{
-		Registers.A.W++;
-		SetZN(Registers.A.W);
-	}
-}
-
-mOP8 (E6M1,     Direct,                           WRAP_BANK, INC)
-mOP16(E6M0,     Direct,                           WRAP_BANK, INC)
-mOPM (E6Slow,   DirectSlow,                       WRAP_BANK, INC)
-
-mOP8 (F6E1,     DirectIndexedXE1,                 WRAP_BANK, INC)
-mOP8 (F6E0M1,   DirectIndexedXE0,                 WRAP_BANK, INC)
-mOP16(F6E0M0,   DirectIndexedXE0,                 WRAP_BANK, INC)
-mOPM (F6Slow,   DirectIndexedXSlow,               WRAP_BANK, INC)
-
-mOP8 (EEM1,     Absolute,                         WRAP_NONE, INC)
-mOP16(EEM0,     Absolute,                         WRAP_NONE, INC)
-mOPM (EESlow,   AbsoluteSlow,                     WRAP_NONE, INC)
-
-mOP8 (FEM1X1,   AbsoluteIndexedXX1,               WRAP_NONE, INC)
-mOP16(FEM0X1,   AbsoluteIndexedXX1,               WRAP_NONE, INC)
-mOP8 (FEM1X0,   AbsoluteIndexedXX0,               WRAP_NONE, INC)
-mOP16(FEM0X0,   AbsoluteIndexedXX0,               WRAP_NONE, INC)
-mOPM (FESlow,   AbsoluteIndexedXSlow,             WRAP_NONE, INC)
-
-/* LDA ********************************************************************* */
-
-static void OpA9M1()
-{
-	Registers.AL = Immediate8(READ);
-	SetZN(Registers.AL);
-}
-
-static void OpA9M0()
-{
-	Registers.A.W = Immediate16(READ);
-	SetZN(Registers.A.W);
-}
-
-static void OpA9Slow()
-{
-	if (CheckMemory())
-	{
-		Registers.AL = Immediate8Slow(READ);
-		SetZN(Registers.AL);
-	}
-	else
-	{
-		Registers.A.W = Immediate16Slow(READ);
-		SetZN(Registers.A.W);
-	}
-}
-
-rOP8 (A5M1,     Direct,                           WRAP_BANK, LDA)
-rOP16(A5M0,     Direct,                           WRAP_BANK, LDA)
-rOPM (A5Slow,   DirectSlow,                       WRAP_BANK, LDA)
-
-rOP8 (B5E1,     DirectIndexedXE1,                 WRAP_BANK, LDA)
-rOP8 (B5E0M1,   DirectIndexedXE0,                 WRAP_BANK, LDA)
-rOP16(B5E0M0,   DirectIndexedXE0,                 WRAP_BANK, LDA)
-rOPM (B5Slow,   DirectIndexedXSlow,               WRAP_BANK, LDA)
-
-rOP8 (B2E1,     DirectIndirectE1,                 WRAP_NONE, LDA)
-rOP8 (B2E0M1,   DirectIndirectE0,                 WRAP_NONE, LDA)
-rOP16(B2E0M0,   DirectIndirectE0,                 WRAP_NONE, LDA)
-rOPM (B2Slow,   DirectIndirectSlow,               WRAP_NONE, LDA)
-
-rOP8 (A1E1,     DirectIndexedIndirectE1,          WRAP_NONE, LDA)
-rOP8 (A1E0M1,   DirectIndexedIndirectE0,          WRAP_NONE, LDA)
-rOP16(A1E0M0,   DirectIndexedIndirectE0,          WRAP_NONE, LDA)
-rOPM (A1Slow,   DirectIndexedIndirectSlow,        WRAP_NONE, LDA)
-
-rOP8 (B1E1,     DirectIndirectIndexedE1,          WRAP_NONE, LDA)
-rOP8 (B1E0M1X1, DirectIndirectIndexedE0X1,        WRAP_NONE, LDA)
-rOP16(B1E0M0X1, DirectIndirectIndexedE0X1,        WRAP_NONE, LDA)
-rOP8 (B1E0M1X0, DirectIndirectIndexedE0X0,        WRAP_NONE, LDA)
-rOP16(B1E0M0X0, DirectIndirectIndexedE0X0,        WRAP_NONE, LDA)
-rOPM (B1Slow,   DirectIndirectIndexedSlow,        WRAP_NONE, LDA)
-
-rOP8 (A7M1,     DirectIndirectLong,               WRAP_NONE, LDA)
-rOP16(A7M0,     DirectIndirectLong,               WRAP_NONE, LDA)
-rOPM (A7Slow,   DirectIndirectLongSlow,           WRAP_NONE, LDA)
-
-rOP8 (B7M1,     DirectIndirectIndexedLong,        WRAP_NONE, LDA)
-rOP16(B7M0,     DirectIndirectIndexedLong,        WRAP_NONE, LDA)
-rOPM (B7Slow,   DirectIndirectIndexedLongSlow,    WRAP_NONE, LDA)
-
-rOP8 (ADM1,     Absolute,                         WRAP_NONE, LDA)
-rOP16(ADM0,     Absolute,                         WRAP_NONE, LDA)
-rOPM (ADSlow,   AbsoluteSlow,                     WRAP_NONE, LDA)
-
-rOP8 (BDM1X1,   AbsoluteIndexedXX1,               WRAP_NONE, LDA)
-rOP16(BDM0X1,   AbsoluteIndexedXX1,               WRAP_NONE, LDA)
-rOP8 (BDM1X0,   AbsoluteIndexedXX0,               WRAP_NONE, LDA)
-rOP16(BDM0X0,   AbsoluteIndexedXX0,               WRAP_NONE, LDA)
-rOPM (BDSlow,   AbsoluteIndexedXSlow,             WRAP_NONE, LDA)
-
-rOP8 (B9M1X1,   AbsoluteIndexedYX1,               WRAP_NONE, LDA)
-rOP16(B9M0X1,   AbsoluteIndexedYX1,               WRAP_NONE, LDA)
-rOP8 (B9M1X0,   AbsoluteIndexedYX0,               WRAP_NONE, LDA)
-rOP16(B9M0X0,   AbsoluteIndexedYX0,               WRAP_NONE, LDA)
-rOPM (B9Slow,   AbsoluteIndexedYSlow,             WRAP_NONE, LDA)
-
-rOP8 (AFM1,     AbsoluteLong,                     WRAP_NONE, LDA)
-rOP16(AFM0,     AbsoluteLong,                     WRAP_NONE, LDA)
-rOPM (AFSlow,   AbsoluteLongSlow,                 WRAP_NONE, LDA)
-
-rOP8 (BFM1,     AbsoluteLongIndexedX,             WRAP_NONE, LDA)
-rOP16(BFM0,     AbsoluteLongIndexedX,             WRAP_NONE, LDA)
-rOPM (BFSlow,   AbsoluteLongIndexedXSlow,         WRAP_NONE, LDA)
-
-rOP8 (A3M1,     StackRelative,                    WRAP_NONE, LDA)
-rOP16(A3M0,     StackRelative,                    WRAP_NONE, LDA)
-rOPM (A3Slow,   StackRelativeSlow,                WRAP_NONE, LDA)
-
-rOP8 (B3M1,     StackRelativeIndirectIndexed,     WRAP_NONE, LDA)
-rOP16(B3M0,     StackRelativeIndirectIndexed,     WRAP_NONE, LDA)
-rOPM (B3Slow,   StackRelativeIndirectIndexedSlow, WRAP_NONE, LDA)
-
-/* LDX ********************************************************************* */
-
-static void OpA2X1()
-{
-	Registers.XL = Immediate8(READ);
-	SetZN(Registers.XL);
-}
-
-static void OpA2X0()
-{
-	Registers.X.W = Immediate16(READ);
-	SetZN(Registers.X.W);
-}
-
-static void OpA2Slow()
-{
-	if (CheckIndex())
-	{
-		Registers.XL = Immediate8Slow(READ);
-		SetZN(Registers.XL);
-	}
-	else
-	{
-		Registers.X.W = Immediate16Slow(READ);
-		SetZN(Registers.X.W);
-	}
-}
-
-rOP8 (A6X1,     Direct,                           WRAP_BANK, LDX)
-rOP16(A6X0,     Direct,                           WRAP_BANK, LDX)
-rOPX (A6Slow,   DirectSlow,                       WRAP_BANK, LDX)
-
-rOP8 (B6E1,     DirectIndexedYE1,                 WRAP_BANK, LDX)
-rOP8 (B6E0X1,   DirectIndexedYE0,                 WRAP_BANK, LDX)
-rOP16(B6E0X0,   DirectIndexedYE0,                 WRAP_BANK, LDX)
-rOPX (B6Slow,   DirectIndexedYSlow,               WRAP_BANK, LDX)
-
-rOP8 (AEX1,     Absolute,                         WRAP_BANK, LDX)
-rOP16(AEX0,     Absolute,                         WRAP_BANK, LDX)
-rOPX (AESlow,   AbsoluteSlow,                     WRAP_BANK, LDX)
-
-rOP8 (BEX1,     AbsoluteIndexedYX1,               WRAP_BANK, LDX)
-rOP16(BEX0,     AbsoluteIndexedYX0,               WRAP_BANK, LDX)
-rOPX (BESlow,   AbsoluteIndexedYSlow,             WRAP_BANK, LDX)
-
-/* LDY ********************************************************************* */
-
-static void OpA0X1()
-{
-	Registers.YL = Immediate8(READ);
-	SetZN(Registers.YL);
-}
-
-static void OpA0X0()
-{
-	Registers.Y.W = Immediate16(READ);
-	SetZN(Registers.Y.W);
-}
-
-static void OpA0Slow()
-{
-	if (CheckIndex())
-	{
-		Registers.YL = Immediate8Slow(READ);
-		SetZN(Registers.YL);
-	}
-	else
-	{
-		Registers.Y.W = Immediate16Slow(READ);
-		SetZN(Registers.Y.W);
-	}
-}
-
-rOP8 (A4X1,     Direct,                           WRAP_BANK, LDY)
-rOP16(A4X0,     Direct,                           WRAP_BANK, LDY)
-rOPX (A4Slow,   DirectSlow,                       WRAP_BANK, LDY)
-
-rOP8 (B4E1,     DirectIndexedXE1,                 WRAP_BANK, LDY)
-rOP8 (B4E0X1,   DirectIndexedXE0,                 WRAP_BANK, LDY)
-rOP16(B4E0X0,   DirectIndexedXE0,                 WRAP_BANK, LDY)
-rOPX (B4Slow,   DirectIndexedXSlow,               WRAP_BANK, LDY)
-
-rOP8 (ACX1,     Absolute,                         WRAP_BANK, LDY)
-rOP16(ACX0,     Absolute,                         WRAP_BANK, LDY)
-rOPX (ACSlow,   AbsoluteSlow,                     WRAP_BANK, LDY)
-
-rOP8 (BCX1,     AbsoluteIndexedXX1,               WRAP_BANK, LDY)
-rOP16(BCX0,     AbsoluteIndexedXX0,               WRAP_BANK, LDY)
-rOPX (BCSlow,   AbsoluteIndexedXSlow,             WRAP_BANK, LDY)
-
-/* LSR ********************************************************************* */
-
-static void Op4AM1()
-{
-	AddCycles(ONE_CYCLE);
-	ICPU._Carry = Registers.AL & 1;
-	Registers.AL >>= 1;
-	SetZN(Registers.AL);
-}
-
-static void Op4AM0()
+	ICPU._Carry = Registers.A.B.l & 1;
+	Registers.A.B.l >>= 1;
+	SetZN(Registers.A.B.l);
+}
+
+static inline void Op4AM0()
 {
 	AddCycles(ONE_CYCLE);
 	ICPU._Carry = Registers.A.W & 1;
@@ -1051,538 +984,524 @@
 
 static void Op4ASlow()
 {
+	if (CheckMemory())
+		Op4AM1();
+	else
+		Op4AM0();
+}
+
+static void Op46M1() { mOP8(Direct, LSR8); }
+static void Op46M0() { mOP16(Direct, LSR16, WRAP_BANK); }
+static void Op46Slow() { mOPM(DirectSlow, LSR8, LSR16, WRAP_BANK); }
+
+static void Op56E1() { mOP8(DirectIndexedXE1, LSR8); }
+static void Op56E0M1() { mOP8(DirectIndexedXE0, LSR8); }
+static void Op56E0M0() { mOP16(DirectIndexedXE0, LSR16, WRAP_BANK); }
+static void Op56Slow() { mOPM(DirectIndexedXSlow, LSR8, LSR16, WRAP_BANK); }
+
+static void Op4EM1() { mOP8(Absolute, LSR8); }
+static void Op4EM0() { mOP16(Absolute, LSR16); }
+static void Op4ESlow() { mOPM(AbsoluteSlow, LSR8, LSR16); }
+
+static void Op5EM1X1() { mOP8(AbsoluteIndexedXX1, LSR8); }
+static void Op5EM0X1() { mOP16(AbsoluteIndexedXX1, LSR16); }
+static void Op5EM1X0() { mOP8(AbsoluteIndexedXX0, LSR8); }
+static void Op5EM0X0() { mOP16(AbsoluteIndexedXX0, LSR16); }
+static void Op5ESlow() { mOPM(AbsoluteIndexedXSlow, LSR8, LSR16); }
+
+/* ORA ********************************************************************* */
+
+template<typename T, typename F> static inline void Op09Wrapper(T &reg, F f)
+{
+	reg |= f(READ);
+	SetZN(reg);
+}
+
+static void Op09M1()
+{
+	Op09Wrapper(Registers.A.B.l, Immediate8);
+}
+
+static void Op09M0()
+{
+	Op09Wrapper(Registers.A.W, Immediate16);
+}
+
+static void Op09Slow()
+{
+	if (CheckMemory())
+		Op09Wrapper(Registers.A.B.l, Immediate8Slow);
+	else
+		Op09Wrapper(Registers.A.W, Immediate16Slow);
+}
+
+static void Op05M1() { rOP8(Direct, ORA8); }
+static void Op05M0() { rOP16(Direct, ORA16, WRAP_BANK); }
+static void Op05Slow() { rOPM(DirectSlow, ORA8, ORA16, WRAP_BANK); }
+
+static void Op15E1() { rOP8(DirectIndexedXE1, ORA8); }
+static void Op15E0M1() { rOP8(DirectIndexedXE0, ORA8); }
+static void Op15E0M0() { rOP16(DirectIndexedXE0, ORA16, WRAP_BANK); }
+static void Op15Slow() { rOPM(DirectIndexedXSlow, ORA8, ORA16, WRAP_BANK); }
+
+static void Op12E1() { rOP8(DirectIndirectE1, ORA8); }
+static void Op12E0M1() { rOP8(DirectIndirectE0, ORA8); }
+static void Op12E0M0() { rOP16(DirectIndirectE0, ORA16); }
+static void Op12Slow() { rOPM(DirectIndirectSlow, ORA8, ORA16); }
+
+static void Op01E1() { rOP8(DirectIndexedIndirectE1, ORA8); }
+static void Op01E0M1() { rOP8(DirectIndexedIndirectE0, ORA8); }
+static void Op01E0M0() { rOP16(DirectIndexedIndirectE0, ORA16); }
+static void Op01Slow() { rOPM(DirectIndexedIndirectSlow, ORA8, ORA16); }
+
+static void Op11E1() { rOP8(DirectIndirectIndexedE1, ORA8); }
+static void Op11E0M1X1() { rOP8(DirectIndirectIndexedE0X1, ORA8); }
+static void Op11E0M0X1() { rOP16(DirectIndirectIndexedE0X1, ORA16); }
+static void Op11E0M1X0() { rOP8(DirectIndirectIndexedE0X0, ORA8); }
+static void Op11E0M0X0() { rOP16(DirectIndirectIndexedE0X0, ORA16); }
+static void Op11Slow() { rOPM(DirectIndirectIndexedSlow, ORA8, ORA16); }
+
+static void Op07M1() { rOP8(DirectIndirectLong, ORA8); }
+static void Op07M0() { rOP16(DirectIndirectLong, ORA16); }
+static void Op07Slow() { rOPM(DirectIndirectLongSlow, ORA8, ORA16); }
+
+static void Op17M1() { rOP8(DirectIndirectIndexedLong, ORA8); }
+static void Op17M0() { rOP16(DirectIndirectIndexedLong, ORA16); }
+static void Op17Slow() { rOPM(DirectIndirectIndexedLongSlow, ORA8, ORA16); }
+
+static void Op0DM1() { rOP8(Absolute, ORA8); }
+static void Op0DM0() { rOP16(Absolute, ORA16); }
+static void Op0DSlow() { rOPM(AbsoluteSlow, ORA8, ORA16); }
+
+static void Op1DM1X1() { rOP8(AbsoluteIndexedXX1, ORA8); }
+static void Op1DM0X1() { rOP16(AbsoluteIndexedXX1, ORA16); }
+static void Op1DM1X0() { rOP8(AbsoluteIndexedXX0, ORA8); }
+static void Op1DM0X0() { rOP16(AbsoluteIndexedXX0, ORA16); }
+static void Op1DSlow() { rOPM(AbsoluteIndexedXSlow, ORA8, ORA16); }
+
+static void Op19M1X1() { rOP8(AbsoluteIndexedYX1, ORA8); }
+static void Op19M0X1() { rOP16(AbsoluteIndexedYX1, ORA16); }
+static void Op19M1X0() { rOP8(AbsoluteIndexedYX0, ORA8); }
+static void Op19M0X0() { rOP16(AbsoluteIndexedYX0, ORA16); }
+static void Op19Slow() { rOPM(AbsoluteIndexedYSlow, ORA8, ORA16); }
+
+static void Op0FM1() { rOP8(AbsoluteLong, ORA8); }
+static void Op0FM0() { rOP16(AbsoluteLong, ORA16); }
+static void Op0FSlow() { rOPM(AbsoluteLongSlow, ORA8, ORA16); }
+
+static void Op1FM1() { rOP8(AbsoluteLongIndexedX, ORA8); }
+static void Op1FM0() { rOP16(AbsoluteLongIndexedX, ORA16); }
+static void Op1FSlow() { rOPM(AbsoluteLongIndexedXSlow, ORA8, ORA16); }
+
+static void Op03M1() { rOP8(StackRelative, ORA8); }
+static void Op03M0() { rOP16(StackRelative, ORA16); }
+static void Op03Slow() { rOPM(StackRelativeSlow, ORA8, ORA16); }
+
+static void Op13M1() { rOP8(StackRelativeIndirectIndexed, ORA8); }
+static void Op13M0() { rOP16(StackRelativeIndirectIndexed, ORA16); }
+static void Op13Slow() { rOPM(StackRelativeIndirectIndexedSlow, ORA8, ORA16); }
+
+/* ROL ********************************************************************* */
+
+static inline void Op2AM1()
+{
 	AddCycles(ONE_CYCLE);
-
+	uint16_t w = (static_cast<uint16_t>(Registers.A.B.l) << 1) | static_cast<uint16_t>(CheckCarry());
+	ICPU._Carry = w >= 0x100;
+	Registers.A.B.l = static_cast<uint8_t>(w);
+	SetZN(Registers.A.B.l);
+}
+
+static inline void Op2AM0()
+{
+	AddCycles(ONE_CYCLE);
+	uint32_t w = (static_cast<uint32_t>(Registers.A.W) << 1) | static_cast<uint32_t>(CheckCarry());
+	ICPU._Carry = w >= 0x10000;
+	Registers.A.W = static_cast<uint16_t>(w);
+	SetZN(Registers.A.W);
+}
+
+static void Op2ASlow()
+{
 	if (CheckMemory())
-	{
-		ICPU._Carry = Registers.AL & 1;
-		Registers.AL >>= 1;
-		SetZN(Registers.AL);
-	}
-	else
-	{
-		ICPU._Carry = Registers.A.W & 1;
-		Registers.A.W >>= 1;
-		SetZN(Registers.A.W);
-	}
-}
-
-mOP8 (46M1,     Direct,                           WRAP_BANK, LSR)
-mOP16(46M0,     Direct,                           WRAP_BANK, LSR)
-mOPM (46Slow,   DirectSlow,                       WRAP_BANK, LSR)
-
-mOP8 (56E1,     DirectIndexedXE1,                 WRAP_BANK, LSR)
-mOP8 (56E0M1,   DirectIndexedXE0,                 WRAP_BANK, LSR)
-mOP16(56E0M0,   DirectIndexedXE0,                 WRAP_BANK, LSR)
-mOPM (56Slow,   DirectIndexedXSlow,               WRAP_BANK, LSR)
-
-mOP8 (4EM1,     Absolute,                         WRAP_NONE, LSR)
-mOP16(4EM0,     Absolute,                         WRAP_NONE, LSR)
-mOPM (4ESlow,   AbsoluteSlow,                     WRAP_NONE, LSR)
-
-mOP8 (5EM1X1,   AbsoluteIndexedXX1,               WRAP_NONE, LSR)
-mOP16(5EM0X1,   AbsoluteIndexedXX1,               WRAP_NONE, LSR)
-mOP8 (5EM1X0,   AbsoluteIndexedXX0,               WRAP_NONE, LSR)
-mOP16(5EM0X0,   AbsoluteIndexedXX0,               WRAP_NONE, LSR)
-mOPM (5ESlow,   AbsoluteIndexedXSlow,             WRAP_NONE, LSR)
-
-/* ORA ********************************************************************* */
-
-static void Op09M1()
-{
-	Registers.AL |= Immediate8(READ);
-	SetZN(Registers.AL);
-}
-
-static void Op09M0()
-{
-	Registers.A.W |= Immediate16(READ);
-	SetZN(Registers.A.W);
-}
-
-static void Op09Slow()
-{
-	if (CheckMemory())
-	{
-		Registers.AL |= Immediate8Slow(READ);
-		SetZN(Registers.AL);
-	}
-	else
-	{
-		Registers.A.W |= Immediate16Slow(READ);
-		SetZN(Registers.A.W);
-	}
-}
-
-rOP8 (05M1,     Direct,                           WRAP_BANK, ORA)
-rOP16(05M0,     Direct,                           WRAP_BANK, ORA)
-rOPM (05Slow,   DirectSlow,                       WRAP_BANK, ORA)
-
-rOP8 (15E1,     DirectIndexedXE1,                 WRAP_BANK, ORA)
-rOP8 (15E0M1,   DirectIndexedXE0,                 WRAP_BANK, ORA)
-rOP16(15E0M0,   DirectIndexedXE0,                 WRAP_BANK, ORA)
-rOPM (15Slow,   DirectIndexedXSlow,               WRAP_BANK, ORA)
-
-rOP8 (12E1,     DirectIndirectE1,                 WRAP_NONE, ORA)
-rOP8 (12E0M1,   DirectIndirectE0,                 WRAP_NONE, ORA)
-rOP16(12E0M0,   DirectIndirectE0,                 WRAP_NONE, ORA)
-rOPM (12Slow,   DirectIndirectSlow,               WRAP_NONE, ORA)
-
-rOP8 (01E1,     DirectIndexedIndirectE1,          WRAP_NONE, ORA)
-rOP8 (01E0M1,   DirectIndexedIndirectE0,          WRAP_NONE, ORA)
-rOP16(01E0M0,   DirectIndexedIndirectE0,          WRAP_NONE, ORA)
-rOPM (01Slow,   DirectIndexedIndirectSlow,        WRAP_NONE, ORA)
-
-rOP8 (11E1,     DirectIndirectIndexedE1,          WRAP_NONE, ORA)
-rOP8 (11E0M1X1, DirectIndirectIndexedE0X1,        WRAP_NONE, ORA)
-rOP16(11E0M0X1, DirectIndirectIndexedE0X1,        WRAP_NONE, ORA)
-rOP8 (11E0M1X0, DirectIndirectIndexedE0X0,        WRAP_NONE, ORA)
-rOP16(11E0M0X0, DirectIndirectIndexedE0X0,        WRAP_NONE, ORA)
-rOPM (11Slow,   DirectIndirectIndexedSlow,        WRAP_NONE, ORA)
-
-rOP8 (07M1,     DirectIndirectLong,               WRAP_NONE, ORA)
-rOP16(07M0,     DirectIndirectLong,               WRAP_NONE, ORA)
-rOPM (07Slow,   DirectIndirectLongSlow,           WRAP_NONE, ORA)
-
-rOP8 (17M1,     DirectIndirectIndexedLong,        WRAP_NONE, ORA)
-rOP16(17M0,     DirectIndirectIndexedLong,        WRAP_NONE, ORA)
-rOPM (17Slow,   DirectIndirectIndexedLongSlow,    WRAP_NONE, ORA)
-
-rOP8 (0DM1,     Absolute,                         WRAP_NONE, ORA)
-rOP16(0DM0,     Absolute,                         WRAP_NONE, ORA)
-rOPM (0DSlow,   AbsoluteSlow,                     WRAP_NONE, ORA)
-
-rOP8 (1DM1X1,   AbsoluteIndexedXX1,               WRAP_NONE, ORA)
-rOP16(1DM0X1,   AbsoluteIndexedXX1,               WRAP_NONE, ORA)
-rOP8 (1DM1X0,   AbsoluteIndexedXX0,               WRAP_NONE, ORA)
-rOP16(1DM0X0,   AbsoluteIndexedXX0,               WRAP_NONE, ORA)
-rOPM (1DSlow,   AbsoluteIndexedXSlow,             WRAP_NONE, ORA)
-
-rOP8 (19M1X1,   AbsoluteIndexedYX1,               WRAP_NONE, ORA)
-rOP16(19M0X1,   AbsoluteIndexedYX1,               WRAP_NONE, ORA)
-rOP8 (19M1X0,   AbsoluteIndexedYX0,               WRAP_NONE, ORA)
-rOP16(19M0X0,   AbsoluteIndexedYX0,               WRAP_NONE, ORA)
-rOPM (19Slow,   AbsoluteIndexedYSlow,             WRAP_NONE, ORA)
-
-rOP8 (0FM1,     AbsoluteLong,                     WRAP_NONE, ORA)
-rOP16(0FM0,     AbsoluteLong,                     WRAP_NONE, ORA)
-rOPM (0FSlow,   AbsoluteLongSlow,                 WRAP_NONE, ORA)
-
-rOP8 (1FM1,     AbsoluteLongIndexedX,             WRAP_NONE, ORA)
-rOP16(1FM0,     AbsoluteLongIndexedX,             WRAP_NONE, ORA)
-rOPM (1FSlow,   AbsoluteLongIndexedXSlow,         WRAP_NONE, ORA)
-
-rOP8 (03M1,     StackRelative,                    WRAP_NONE, ORA)
-rOP16(03M0,     StackRelative,                    WRAP_NONE, ORA)
-rOPM (03Slow,   StackRelativeSlow,                WRAP_NONE, ORA)
-
-rOP8 (13M1,     StackRelativeIndirectIndexed,     WRAP_NONE, ORA)
-rOP16(13M0,     StackRelativeIndirectIndexed,     WRAP_NONE, ORA)
-rOPM (13Slow,   StackRelativeIndirectIndexedSlow, WRAP_NONE, ORA)
-
-/* ROL ********************************************************************* */
-
-static void Op2AM1()
+		Op2AM1();
+	else
+		Op2AM0();
+}
+
+static void Op26M1() { mOP8(Direct, ROL8); }
+static void Op26M0() { mOP16(Direct, ROL16, WRAP_BANK); }
+static void Op26Slow() { mOPM(DirectSlow, ROL8, ROL16, WRAP_BANK); }
+
+static void Op36E1() { mOP8(DirectIndexedXE1, ROL8); }
+static void Op36E0M1() { mOP8(DirectIndexedXE0, ROL8); }
+static void Op36E0M0() { mOP16(DirectIndexedXE0, ROL16, WRAP_BANK); }
+static void Op36Slow() { mOPM(DirectIndexedXSlow, ROL8, ROL16, WRAP_BANK); }
+
+static void Op2EM1() { mOP8(Absolute, ROL8); }
+static void Op2EM0() { mOP16(Absolute, ROL16); }
+static void Op2ESlow() { mOPM(AbsoluteSlow, ROL8, ROL16); }
+
+static void Op3EM1X1() { mOP8(AbsoluteIndexedXX1, ROL8); }
+static void Op3EM0X1() { mOP16(AbsoluteIndexedXX1, ROL16); }
+static void Op3EM1X0() { mOP8(AbsoluteIndexedXX0, ROL8); }
+static void Op3EM0X0() { mOP16(AbsoluteIndexedXX0, ROL16); }
+static void Op3ESlow() { mOPM(AbsoluteIndexedXSlow, ROL8, ROL16); }
+
+/* ROR ********************************************************************* */
+
+static inline void Op6AM1()
 {
 	AddCycles(ONE_CYCLE);
-	uint16_t	w = (((uint16_t) Registers.AL) << 1) | CheckCarry();
-	ICPU._Carry = w >= 0x100;
-	Registers.AL = (uint8_t) w;
-	SetZN(Registers.AL);
-}
-
-static void Op2AM0()
-{
-	AddCycles(ONE_CYCLE);
-	uint32_t	w = (((uint32_t) Registers.A.W) << 1) | CheckCarry();
-	ICPU._Carry = w >= 0x10000;
-	Registers.A.W = (uint16_t) w;
-	SetZN(Registers.A.W);
-}
-
-static void Op2ASlow()
-{
-	AddCycles(ONE_CYCLE);
-
-	if (CheckMemory())
-	{
-		uint16_t	w = (((uint16_t) Registers.AL) << 1) | CheckCarry();
-		ICPU._Carry = w >= 0x100;
-		Registers.AL = (uint8_t) w;
-		SetZN(Registers.AL);
-	}
-	else
-	{
-		uint32_t	w = (((uint32_t) Registers.A.W) << 1) | CheckCarry();
-		ICPU._Carry = w >= 0x10000;
-		Registers.A.W = (uint16_t) w;
-		SetZN(Registers.A.W);
-	}
-}
-
-mOP8 (26M1,     Direct,                           WRAP_BANK, ROL)
-mOP16(26M0,     Direct,                           WRAP_BANK, ROL)
-mOPM (26Slow,   DirectSlow,                       WRAP_BANK, ROL)
-
-mOP8 (36E1,     DirectIndexedXE1,                 WRAP_BANK, ROL)
-mOP8 (36E0M1,   DirectIndexedXE0,                 WRAP_BANK, ROL)
-mOP16(36E0M0,   DirectIndexedXE0,                 WRAP_BANK, ROL)
-mOPM (36Slow,   DirectIndexedXSlow,               WRAP_BANK, ROL)
-
-mOP8 (2EM1,     Absolute,                         WRAP_NONE, ROL)
-mOP16(2EM0,     Absolute,                         WRAP_NONE, ROL)
-mOPM (2ESlow,   AbsoluteSlow,                     WRAP_NONE, ROL)
-
-mOP8 (3EM1X1,   AbsoluteIndexedXX1,               WRAP_NONE, ROL)
-mOP16(3EM0X1,   AbsoluteIndexedXX1,               WRAP_NONE, ROL)
-mOP8 (3EM1X0,   AbsoluteIndexedXX0,               WRAP_NONE, ROL)
-mOP16(3EM0X0,   AbsoluteIndexedXX0,               WRAP_NONE, ROL)
-mOPM (3ESlow,   AbsoluteIndexedXSlow,             WRAP_NONE, ROL)
-
-/* ROR ********************************************************************* */
-
-static void Op6AM1()
-{
-	AddCycles(ONE_CYCLE);
-	uint16_t	w = ((uint16_t) Registers.AL) | (((uint16_t) CheckCarry()) << 8);
+	uint16_t w = static_cast<uint16_t>(Registers.A.B.l) | (static_cast<uint16_t>(CheckCarry()) << 8);
 	ICPU._Carry = w & 1;
 	w >>= 1;
-	Registers.AL = (uint8_t) w;
-	SetZN(Registers.AL);
-}
-
-static void Op6AM0()
+	Registers.A.B.l = static_cast<uint8_t>(w);
+	SetZN(Registers.A.B.l);
+}
+
+static inline void Op6AM0()
 {
 	AddCycles(ONE_CYCLE);
-	uint32_t	w = ((uint32_t) Registers.A.W) | (((uint32_t) CheckCarry()) << 16);
+	uint32_t w = static_cast<uint32_t>(Registers.A.W) | (static_cast<uint32_t>(CheckCarry()) << 16);
 	ICPU._Carry = w & 1;
 	w >>= 1;
-	Registers.A.W = (uint16_t) w;
+	Registers.A.W = static_cast<uint16_t>(w);
 	SetZN(Registers.A.W);
 }
 
 static void Op6ASlow()
 {
-	AddCycles(ONE_CYCLE);
-
 	if (CheckMemory())
-	{
-		uint16_t	w = ((uint16_t) Registers.AL) | (((uint16_t) CheckCarry()) << 8);
-		ICPU._Carry = w & 1;
-		w >>= 1;
-		Registers.AL = (uint8_t) w;
-		SetZN(Registers.AL);
-	}
-	else
-	{
-		uint32_t	w = ((uint32_t) Registers.A.W) | (((uint32_t) CheckCarry()) << 16);
-		ICPU._Carry = w & 1;
-		w >>= 1;
-		Registers.A.W = (uint16_t) w;
-		SetZN(Registers.A.W);
-	}
-}
-
-mOP8 (66M1,     Direct,                           WRAP_BANK, ROR)
-mOP16(66M0,     Direct,                           WRAP_BANK, ROR)
-mOPM (66Slow,   DirectSlow,                       WRAP_BANK, ROR)
-
-mOP8 (76E1,     DirectIndexedXE1,                 WRAP_BANK, ROR)
-mOP8 (76E0M1,   DirectIndexedXE0,                 WRAP_BANK, ROR)
-mOP16(76E0M0,   DirectIndexedXE0,                 WRAP_BANK, ROR)
-mOPM (76Slow,   DirectIndexedXSlow,               WRAP_BANK, ROR)
-
-mOP8 (6EM1,     Absolute,                         WRAP_NONE, ROR)
-mOP16(6EM0,     Absolute,                         WRAP_NONE, ROR)
-mOPM (6ESlow,   AbsoluteSlow,                     WRAP_NONE, ROR)
-
-mOP8 (7EM1X1,   AbsoluteIndexedXX1,               WRAP_NONE, ROR)
-mOP16(7EM0X1,   AbsoluteIndexedXX1,               WRAP_NONE, ROR)
-mOP8 (7EM1X0,   AbsoluteIndexedXX0,               WRAP_NONE, ROR)
-mOP16(7EM0X0,   AbsoluteIndexedXX0,               WRAP_NONE, ROR)
-mOPM (7ESlow,   AbsoluteIndexedXSlow,             WRAP_NONE, ROR)
+		Op6AM1();
+	else
+		Op6AM0();
+}
+
+static void Op66M1() { mOP8(Direct, ROR8); }
+static void Op66M0() { mOP16(Direct, ROR16, WRAP_BANK); }
+static void Op66Slow() { mOPM(DirectSlow, ROR8, ROR16, WRAP_BANK); }
+
+static void Op76E1() { mOP8(DirectIndexedXE1, ROR8); }
+static void Op76E0M1() { mOP8(DirectIndexedXE0, ROR8); }
+static void Op76E0M0() { mOP16(DirectIndexedXE0, ROR16, WRAP_BANK); }
+static void Op76Slow() { mOPM(DirectIndexedXSlow, ROR8, ROR16, WRAP_BANK); }
+
+static void Op6EM1() { mOP8(Absolute, ROR8); }
+static void Op6EM0() { mOP16(Absolute, ROR16); }
+static void Op6ESlow() { mOPM(AbsoluteSlow, ROR8, ROR16); }
+
+static void Op7EM1X1() { mOP8(AbsoluteIndexedXX1, ROR8); }
+static void Op7EM0X1() { mOP16(AbsoluteIndexedXX1, ROR16); }
+static void Op7EM1X0() { mOP8(AbsoluteIndexedXX0, ROR8); }
+static void Op7EM0X0() { mOP16(AbsoluteIndexedXX0, ROR16); }
+static void Op7ESlow() { mOPM(AbsoluteIndexedXSlow, ROR8, ROR16); }
 
 /* SBC ********************************************************************* */
 
+template<typename T> static inline void SBC(T Work)
+{
+}
+
+template<> static inline void SBC<uint16_t>(uint16_t Work16)
+{
+	SBC16(Work16);
+}
+
+template<> static inline void SBC<uint8_t>(uint8_t Work8)
+{
+	SBC8(Work8);
+}
+
+template<typename F> static inline void OpE9Wrapper(F f)
+{
+	SBC(f(READ));
+}
+
 static void OpE9M1()
 {
-	SBC(Immediate8(READ));
+	OpE9Wrapper(Immediate8);
 }
 
 static void OpE9M0()
 {
-	SBC(Immediate16(READ));
+	OpE9Wrapper(Immediate16);
 }
 
 static void OpE9Slow()
 {
 	if (CheckMemory())
-		SBC(Immediate8Slow(READ));
-	else
-		SBC(Immediate16Slow(READ));
-}
-
-rOP8 (E5M1,     Direct,                           WRAP_BANK, SBC)
-rOP16(E5M0,     Direct,                           WRAP_BANK, SBC)
-rOPM (E5Slow,   DirectSlow,                       WRAP_BANK, SBC)
-
-rOP8 (F5E1,     DirectIndexedXE1,                 WRAP_BANK, SBC)
-rOP8 (F5E0M1,   DirectIndexedXE0,                 WRAP_BANK, SBC)
-rOP16(F5E0M0,   DirectIndexedXE0,                 WRAP_BANK, SBC)
-rOPM (F5Slow,   DirectIndexedXSlow,               WRAP_BANK, SBC)
-
-rOP8 (F2E1,     DirectIndirectE1,                 WRAP_NONE, SBC)
-rOP8 (F2E0M1,   DirectIndirectE0,                 WRAP_NONE, SBC)
-rOP16(F2E0M0,   DirectIndirectE0,                 WRAP_NONE, SBC)
-rOPM (F2Slow,   DirectIndirectSlow,               WRAP_NONE, SBC)
-
-rOP8 (E1E1,     DirectIndexedIndirectE1,          WRAP_NONE, SBC)
-rOP8 (E1E0M1,   DirectIndexedIndirectE0,          WRAP_NONE, SBC)
-rOP16(E1E0M0,   DirectIndexedIndirectE0,          WRAP_NONE, SBC)
-rOPM (E1Slow,   DirectIndexedIndirectSlow,        WRAP_NONE, SBC)
-
-rOP8 (F1E1,     DirectIndirectIndexedE1,          WRAP_NONE, SBC)
-rOP8 (F1E0M1X1, DirectIndirectIndexedE0X1,        WRAP_NONE, SBC)
-rOP16(F1E0M0X1, DirectIndirectIndexedE0X1,        WRAP_NONE, SBC)
-rOP8 (F1E0M1X0, DirectIndirectIndexedE0X0,        WRAP_NONE, SBC)
-rOP16(F1E0M0X0, DirectIndirectIndexedE0X0,        WRAP_NONE, SBC)
-rOPM (F1Slow,   DirectIndirectIndexedSlow,        WRAP_NONE, SBC)
-
-rOP8 (E7M1,     DirectIndirectLong,               WRAP_NONE, SBC)
-rOP16(E7M0,     DirectIndirectLong,               WRAP_NONE, SBC)
-rOPM (E7Slow,   DirectIndirectLongSlow,           WRAP_NONE, SBC)
-
-rOP8 (F7M1,     DirectIndirectIndexedLong,        WRAP_NONE, SBC)
-rOP16(F7M0,     DirectIndirectIndexedLong,        WRAP_NONE, SBC)
-rOPM (F7Slow,   DirectIndirectIndexedLongSlow,    WRAP_NONE, SBC)
-
-rOP8 (EDM1,     Absolute,                         WRAP_NONE, SBC)
-rOP16(EDM0,     Absolute,                         WRAP_NONE, SBC)
-rOPM (EDSlow,   AbsoluteSlow,                     WRAP_NONE, SBC)
-
-rOP8 (FDM1X1,   AbsoluteIndexedXX1,               WRAP_NONE, SBC)
-rOP16(FDM0X1,   AbsoluteIndexedXX1,               WRAP_NONE, SBC)
-rOP8 (FDM1X0,   AbsoluteIndexedXX0,               WRAP_NONE, SBC)
-rOP16(FDM0X0,   AbsoluteIndexedXX0,               WRAP_NONE, SBC)
-rOPM (FDSlow,   AbsoluteIndexedXSlow,             WRAP_NONE, SBC)
-
-rOP8 (F9M1X1,   AbsoluteIndexedYX1,               WRAP_NONE, SBC)
-rOP16(F9M0X1,   AbsoluteIndexedYX1,               WRAP_NONE, SBC)
-rOP8 (F9M1X0,   AbsoluteIndexedYX0,               WRAP_NONE, SBC)
-rOP16(F9M0X0,   AbsoluteIndexedYX0,               WRAP_NONE, SBC)
-rOPM (F9Slow,   AbsoluteIndexedYSlow,             WRAP_NONE, SBC)
-
-rOP8 (EFM1,     AbsoluteLong,                     WRAP_NONE, SBC)
-rOP16(EFM0,     AbsoluteLong,                     WRAP_NONE, SBC)
-rOPM (EFSlow,   AbsoluteLongSlow,                 WRAP_NONE, SBC)
-
-rOP8 (FFM1,     AbsoluteLongIndexedX,             WRAP_NONE, SBC)
-rOP16(FFM0,     AbsoluteLongIndexedX,             WRAP_NONE, SBC)
-rOPM (FFSlow,   AbsoluteLongIndexedXSlow,         WRAP_NONE, SBC)
-
-rOP8 (E3M1,     StackRelative,                    WRAP_NONE, SBC)
-rOP16(E3M0,     StackRelative,                    WRAP_NONE, SBC)
-rOPM (E3Slow,   StackRelativeSlow,                WRAP_NONE, SBC)
-
-rOP8 (F3M1,     StackRelativeIndirectIndexed,     WRAP_NONE, SBC)
-rOP16(F3M0,     StackRelativeIndirectIndexed,     WRAP_NONE, SBC)
-rOPM (F3Slow,   StackRelativeIndirectIndexedSlow, WRAP_NONE, SBC)
+		OpE9Wrapper(Immediate8Slow);
+	else
+		OpE9Wrapper(Immediate16Slow);
+}
+
+static void OpE5M1() { rOP8(Direct, SBC8); }
+static void OpE5M0() { rOP16(Direct, SBC16, WRAP_BANK); }
+static void OpE5Slow() { rOPM(DirectSlow, SBC8, SBC16, WRAP_BANK); }
+
+static void OpF5E1() { rOP8(DirectIndexedXE1, SBC8); }
+static void OpF5E0M1() { rOP8(DirectIndexedXE0, SBC8); }
+static void OpF5E0M0() { rOP16(DirectIndexedXE0, SBC16, WRAP_BANK); }
+static void OpF5Slow() { rOPM(DirectIndexedXSlow, SBC8, SBC16, WRAP_BANK); }
+
+static void OpF2E1() { rOP8(DirectIndirectE1, SBC8); }
+static void OpF2E0M1() { rOP8(DirectIndirectE0, SBC8); }
+static void OpF2E0M0() { rOP16(DirectIndirectE0, SBC16); }
+static void OpF2Slow() { rOPM(DirectIndirectSlow, SBC8, SBC16); }
+
+static void OpE1E1() { rOP8(DirectIndexedIndirectE1, SBC8); }
+static void OpE1E0M1() { rOP8(DirectIndexedIndirectE0, SBC8); }
+static void OpE1E0M0() { rOP16(DirectIndexedIndirectE0, SBC16); }
+static void OpE1Slow() { rOPM(DirectIndexedIndirectSlow, SBC8, SBC16); }
+
+static void OpF1E1() { rOP8(DirectIndirectIndexedE1, SBC8); }
+static void OpF1E0M1X1() { rOP8(DirectIndirectIndexedE0X1, SBC8); }
+static void OpF1E0M0X1() { rOP16(DirectIndirectIndexedE0X1, SBC16); }
+static void OpF1E0M1X0() { rOP8(DirectIndirectIndexedE0X0, SBC8); }
+static void OpF1E0M0X0() { rOP16(DirectIndirectIndexedE0X0, SBC16); }
+static void OpF1Slow() { rOPM(DirectIndirectIndexedSlow, SBC8, SBC16); }
+
+static void OpE7M1() { rOP8(DirectIndirectLong, SBC8); }
+static void OpE7M0() { rOP16(DirectIndirectLong, SBC16); }
+static void OpE7Slow() { rOPM(DirectIndirectLongSlow, SBC8, SBC16); }
+
+static void OpF7M1() { rOP8(DirectIndirectIndexedLong, SBC8); }
+static void OpF7M0() { rOP16(DirectIndirectIndexedLong, SBC16); }
+static void OpF7Slow() { rOPM(DirectIndirectIndexedLongSlow, SBC8, SBC16); }
+
+static void OpEDM1() { rOP8(Absolute, SBC8); }
+static void OpEDM0() { rOP16(Absolute, SBC16); }
+static void OpEDSlow() { rOPM(AbsoluteSlow, SBC8, SBC16); }
+
+static void OpFDM1X1() { rOP8(AbsoluteIndexedXX1, SBC8); }
+static void OpFDM0X1() { rOP16(AbsoluteIndexedXX1, SBC16); }
+static void OpFDM1X0() { rOP8(AbsoluteIndexedXX0, SBC8); }
+static void OpFDM0X0() { rOP16(AbsoluteIndexedXX0, SBC16); }
+static void OpFDSlow() { rOPM(AbsoluteIndexedXSlow, SBC8, SBC16); }
+
+static void OpF9M1X1() { rOP8(AbsoluteIndexedYX1, SBC8); }
+static void OpF9M0X1() { rOP16(AbsoluteIndexedYX1, SBC16); }
+static void OpF9M1X0() { rOP8(AbsoluteIndexedYX0, SBC8); }
+static void OpF9M0X0() { rOP16(AbsoluteIndexedYX0, SBC16); }
+static void OpF9Slow() { rOPM(AbsoluteIndexedYSlow, SBC8, SBC16); }
+
+static void OpEFM1() { rOP8(AbsoluteLong, SBC8); }
+static void OpEFM0() { rOP16(AbsoluteLong, SBC16); }
+static void OpEFSlow() { rOPM(AbsoluteLongSlow, SBC8, SBC16); }
+
+static void OpFFM1() { rOP8(AbsoluteLongIndexedX, SBC8); }
+static void OpFFM0() { rOP16(AbsoluteLongIndexedX, SBC16); }
+static void OpFFSlow() { rOPM(AbsoluteLongIndexedXSlow, SBC8, SBC16); }
+
+static void OpE3M1() { rOP8(StackRelative, SBC8); }
+static void OpE3M0() { rOP16(StackRelative, SBC16); }
+static void OpE3Slow() { rOPM(StackRelativeSlow, SBC8, SBC16); }
+
+static void OpF3M1() { rOP8(StackRelativeIndirectIndexed, SBC8); }
+static void OpF3M0() { rOP16(StackRelativeIndirectIndexed, SBC16); }
+static void OpF3Slow() { rOPM(StackRelativeIndirectIndexedSlow, SBC8, SBC16); }
 
 /* STA ********************************************************************* */
 
-wOP8 (85M1,     Direct,                           WRAP_BANK, STA)
-wOP16(85M0,     Direct,                           WRAP_BANK, STA)
-wOPM (85Slow,   DirectSlow,                       WRAP_BANK, STA)
-
-wOP8 (95E1,     DirectIndexedXE1,                 WRAP_BANK, STA)
-wOP8 (95E0M1,   DirectIndexedXE0,                 WRAP_BANK, STA)
-wOP16(95E0M0,   DirectIndexedXE0,                 WRAP_BANK, STA)
-wOPM (95Slow,   DirectIndexedXSlow,               WRAP_BANK, STA)
-
-wOP8 (92E1,     DirectIndirectE1,                 WRAP_NONE, STA)
-wOP8 (92E0M1,   DirectIndirectE0,                 WRAP_NONE, STA)
-wOP16(92E0M0,   DirectIndirectE0,                 WRAP_NONE, STA)
-wOPM (92Slow,   DirectIndirectSlow,               WRAP_NONE, STA)
-
-wOP8 (81E1,     DirectIndexedIndirectE1,          WRAP_NONE, STA)
-wOP8 (81E0M1,   DirectIndexedIndirectE0,          WRAP_NONE, STA)
-wOP16(81E0M0,   DirectIndexedIndirectE0,          WRAP_NONE, STA)
-wOPM (81Slow,   DirectIndexedIndirectSlow,        WRAP_NONE, STA)
-
-wOP8 (91E1,     DirectIndirectIndexedE1,          WRAP_NONE, STA)
-wOP8 (91E0M1X1, DirectIndirectIndexedE0X1,        WRAP_NONE, STA)
-wOP16(91E0M0X1, DirectIndirectIndexedE0X1,        WRAP_NONE, STA)
-wOP8 (91E0M1X0, DirectIndirectIndexedE0X0,        WRAP_NONE, STA)
-wOP16(91E0M0X0, DirectIndirectIndexedE0X0,        WRAP_NONE, STA)
-wOPM (91Slow,   DirectIndirectIndexedSlow,        WRAP_NONE, STA)
-
-wOP8 (87M1,     DirectIndirectLong,               WRAP_NONE, STA)
-wOP16(87M0,     DirectIndirectLong,               WRAP_NONE, STA)
-wOPM (87Slow,   DirectIndirectLongSlow,           WRAP_NONE, STA)
-
-wOP8 (97M1,     DirectIndirectIndexedLong,        WRAP_NONE, STA)
-wOP16(97M0,     DirectIndirectIndexedLong,        WRAP_NONE, STA)
-wOPM (97Slow,   DirectIndirectIndexedLongSlow,    WRAP_NONE, STA)
-
-wOP8 (8DM1,     Absolute,                         WRAP_NONE, STA)
-wOP16(8DM0,     Absolute,                         WRAP_NONE, STA)
-wOPM (8DSlow,   AbsoluteSlow,                     WRAP_NONE, STA)
-
-wOP8 (9DM1X1,   AbsoluteIndexedXX1,               WRAP_NONE, STA)
-wOP16(9DM0X1,   AbsoluteIndexedXX1,               WRAP_NONE, STA)
-wOP8 (9DM1X0,   AbsoluteIndexedXX0,               WRAP_NONE, STA)
-wOP16(9DM0X0,   AbsoluteIndexedXX0,               WRAP_NONE, STA)
-wOPM (9DSlow,   AbsoluteIndexedXSlow,             WRAP_NONE, STA)
-
-wOP8 (99M1X1,   AbsoluteIndexedYX1,               WRAP_NONE, STA)
-wOP16(99M0X1,   AbsoluteIndexedYX1,               WRAP_NONE, STA)
-wOP8 (99M1X0,   AbsoluteIndexedYX0,               WRAP_NONE, STA)
-wOP16(99M0X0,   AbsoluteIndexedYX0,               WRAP_NONE, STA)
-wOPM (99Slow,   AbsoluteIndexedYSlow,             WRAP_NONE, STA)
-
-wOP8 (8FM1,     AbsoluteLong,                     WRAP_NONE, STA)
-wOP16(8FM0,     AbsoluteLong,                     WRAP_NONE, STA)
-wOPM (8FSlow,   AbsoluteLongSlow,                 WRAP_NONE, STA)
-
-wOP8 (9FM1,     AbsoluteLongIndexedX,             WRAP_NONE, STA)
-wOP16(9FM0,     AbsoluteLongIndexedX,             WRAP_NONE, STA)
-wOPM (9FSlow,   AbsoluteLongIndexedXSlow,         WRAP_NONE, STA)
-
-wOP8 (83M1,     StackRelative,                    WRAP_NONE, STA)
-wOP16(83M0,     StackRelative,                    WRAP_NONE, STA)
-wOPM (83Slow,   StackRelativeSlow,                WRAP_NONE, STA)
-
-wOP8 (93M1,     StackRelativeIndirectIndexed,     WRAP_NONE, STA)
-wOP16(93M0,     StackRelativeIndirectIndexed,     WRAP_NONE, STA)
-wOPM (93Slow,   StackRelativeIndirectIndexedSlow, WRAP_NONE, STA)
+static void Op85M1() { wOP8(Direct, STA8); }
+static void Op85M0() { wOP16(Direct, STA16, WRAP_BANK); }
+static void Op85Slow() { wOPM(DirectSlow, STA8, STA16, WRAP_BANK); }
+
+static void Op95E1() { wOP8(DirectIndexedXE1, STA8); }
+static void Op95E0M1() { wOP8(DirectIndexedXE0, STA8); }
+static void Op95E0M0() { wOP16(DirectIndexedXE0, STA16, WRAP_BANK); }
+static void Op95Slow() { wOPM(DirectIndexedXSlow, STA8, STA16, WRAP_BANK); }
+
+static void Op92E1() { wOP8(DirectIndirectE1, STA8); }
+static void Op92E0M1() { wOP8(DirectIndirectE0, STA8); }
+static void Op92E0M0() { wOP16(DirectIndirectE0, STA16); }
+static void Op92Slow() { wOPM(DirectIndirectSlow, STA8, STA16); }
+
+static void Op81E1() { wOP8(DirectIndexedIndirectE1, STA8); }
+static void Op81E0M1() { wOP8(DirectIndexedIndirectE0, STA8); }
+static void Op81E0M0() { wOP16(DirectIndexedIndirectE0, STA16); }
+static void Op81Slow() { wOPM(DirectIndexedIndirectSlow, STA8, STA16); }
+
+static void Op91E1() { wOP8(DirectIndirectIndexedE1, STA8); }
+static void Op91E0M1X1() { wOP8(DirectIndirectIndexedE0X1, STA8); }
+static void Op91E0M0X1() { wOP16(DirectIndirectIndexedE0X1, STA16); }
+static void Op91E0M1X0() { wOP8(DirectIndirectIndexedE0X0, STA8); }
+static void Op91E0M0X0() { wOP16(DirectIndirectIndexedE0X0, STA16); }
+static void Op91Slow() { wOPM(DirectIndirectIndexedSlow, STA8, STA16); }
+
+static void Op87M1() { wOP8(DirectIndirectLong, STA8); }
+static void Op87M0() { wOP16(DirectIndirectLong, STA16); }
+static void Op87Slow() { wOPM(DirectIndirectLongSlow, STA8, STA16); }
+
+static void Op97M1() { wOP8(DirectIndirectIndexedLong, STA8); }
+static void Op97M0() { wOP16(DirectIndirectIndexedLong, STA16); }
+static void Op97Slow() { wOPM(DirectIndirectIndexedLongSlow, STA8, STA16); }
+
+static void Op8DM1() { wOP8(Absolute, STA8); }
+static void Op8DM0() { wOP16(Absolute, STA16); }
+static void Op8DSlow() { wOPM(AbsoluteSlow, STA8, STA16); }
+
+static void Op9DM1X1() { wOP8(AbsoluteIndexedXX1, STA8); }
+static void Op9DM0X1() { wOP16(AbsoluteIndexedXX1, STA16); }
+static void Op9DM1X0() { wOP8(AbsoluteIndexedXX0, STA8); }
+static void Op9DM0X0() { wOP16(AbsoluteIndexedXX0, STA16); }
+static void Op9DSlow() { wOPM(AbsoluteIndexedXSlow, STA8, STA16); }
+
+static void Op99M1X1() { wOP8(AbsoluteIndexedYX1, STA8); }
+static void Op99M0X1() { wOP16(AbsoluteIndexedYX1, STA16); }
+static void Op99M1X0() { wOP8(AbsoluteIndexedYX0, STA8); }
+static void Op99M0X0() { wOP16(AbsoluteIndexedYX0, STA16); }
+static void Op99Slow() { wOPM(AbsoluteIndexedYSlow, STA8, STA16); }
+
+static void Op8FM1() { wOP8(AbsoluteLong, STA8); }
+static void Op8FM0() { wOP16(AbsoluteLong, STA16); }
+static void Op8FSlow() { wOPM(AbsoluteLongSlow, STA8, STA16); }
+
+static void Op9FM1() { wOP8(AbsoluteLongIndexedX, STA8); }
+static void Op9FM0() { wOP16(AbsoluteLongIndexedX, STA16); }
+static void Op9FSlow() { wOPM(AbsoluteLongIndexedXSlow, STA8, STA16); }
+
+static void Op83M1() { wOP8(StackRelative, STA8); }
+static void Op83M0() { wOP16(StackRelative, STA16); }
+static void Op83Slow() { wOPM(StackRelativeSlow, STA8, STA16); }
+
+static void Op93M1() { wOP8(StackRelativeIndirectIndexed, STA8); }
+static void Op93M0() { wOP16(StackRelativeIndirectIndexed, STA16); }
+static void Op93Slow() { wOPM(StackRelativeIndirectIndexedSlow, STA8, STA16); }
 
 /* STX ********************************************************************* */
 
-wOP8 (86X1,     Direct,                           WRAP_BANK, STX)
-wOP16(86X0,     Direct,                           WRAP_BANK, STX)
-wOPX (86Slow,   DirectSlow,                       WRAP_BANK, STX)
-
-wOP8 (96E1,     DirectIndexedYE1,                 WRAP_BANK, STX)
-wOP8 (96E0X1,   DirectIndexedYE0,                 WRAP_BANK, STX)
-wOP16(96E0X0,   DirectIndexedYE0,                 WRAP_BANK, STX)
-wOPX (96Slow,   DirectIndexedYSlow,               WRAP_BANK, STX)
-
-wOP8 (8EX1,     Absolute,                         WRAP_BANK, STX)
-wOP16(8EX0,     Absolute,                         WRAP_BANK, STX)
-wOPX (8ESlow,   AbsoluteSlow,                     WRAP_BANK, STX)
+static void Op86X1() { wOP8(Direct, STX8); }
+static void Op86X0() { wOP16(Direct, STX16, WRAP_BANK); }
+static void Op86Slow() { wOPX(DirectSlow, STX8, STX16, WRAP_BANK); }
+
+static void Op96E1() { wOP8(DirectIndexedYE1, STX8); }
+static void Op96E0X1() { wOP8(DirectIndexedYE0, STX8); }
+static void Op96E0X0() { wOP16(DirectIndexedYE0, STX16, WRAP_BANK); }
+static void Op96Slow() { wOPX(DirectIndexedYSlow, STX8, STX16, WRAP_BANK); }
+
+static void Op8EX1() { wOP8(Absolute, STX8); }
+static void Op8EX0() { wOP16(Absolute, STX16, WRAP_BANK); }
+static void Op8ESlow() { wOPX(AbsoluteSlow, STX8, STX16, WRAP_BANK); }
 
 /* STY ********************************************************************* */
 
-wOP8 (84X1,     Direct,                           WRAP_BANK, STY)
-wOP16(84X0,     Direct,                           WRAP_BANK, STY)
-wOPX (84Slow,   DirectSlow,                       WRAP_BANK, STY)
-
-wOP8 (94E1,     DirectIndexedXE1,                 WRAP_BANK, STY)
-wOP8 (94E0X1,   DirectIndexedXE0,                 WRAP_BANK, STY)
-wOP16(94E0X0,   DirectIndexedXE0,                 WRAP_BANK, STY)
-wOPX (94Slow,   DirectIndexedXSlow,               WRAP_BANK, STY)
-
-wOP8 (8CX1,     Absolute,                         WRAP_BANK, STY)
-wOP16(8CX0,     Absolute,                         WRAP_BANK, STY)
-wOPX (8CSlow,   AbsoluteSlow,                     WRAP_BANK, STY)
+static void Op84X1() { wOP8(Direct, STY8); }
+static void Op84X0() { wOP16(Direct, STY16, WRAP_BANK); }
+static void Op84Slow() { wOPX(DirectSlow, STY8, STY16, WRAP_BANK); }
+
+static void Op94E1() { wOP8(DirectIndexedXE1, STY8); }
+static void Op94E0X1() { wOP8(DirectIndexedXE0, STY8); }
+static void Op94E0X0() { wOP16(DirectIndexedXE0, STY16, WRAP_BANK); }
+static void Op94Slow() { wOPX(DirectIndexedXSlow, STY8, STY16, WRAP_BANK); }
+
+static void Op8CX1() { wOP8(Absolute, STY8); }
+static void Op8CX0() { wOP16(Absolute, STY16, WRAP_BANK); }
+static void Op8CSlow() { wOPX(AbsoluteSlow, STY8, STY16, WRAP_BANK); }
 
 /* STZ ********************************************************************* */
 
-wOP8 (64M1,     Direct,                           WRAP_BANK, STZ)
-wOP16(64M0,     Direct,                           WRAP_BANK, STZ)
-wOPM (64Slow,   DirectSlow,                       WRAP_BANK, STZ)
-
-wOP8 (74E1,     DirectIndexedXE1,                 WRAP_BANK, STZ)
-wOP8 (74E0M1,   DirectIndexedXE0,                 WRAP_BANK, STZ)
-wOP16(74E0M0,   DirectIndexedXE0,                 WRAP_BANK, STZ)
-wOPM (74Slow,   DirectIndexedXSlow,               WRAP_BANK, STZ)
-
-wOP8 (9CM1,     Absolute,                         WRAP_NONE, STZ)
-wOP16(9CM0,     Absolute,                         WRAP_NONE, STZ)
-wOPM (9CSlow,   AbsoluteSlow,                     WRAP_NONE, STZ)
-
-wOP8 (9EM1X1,   AbsoluteIndexedXX1,               WRAP_NONE, STZ)
-wOP16(9EM0X1,   AbsoluteIndexedXX1,               WRAP_NONE, STZ)
-wOP8 (9EM1X0,   AbsoluteIndexedXX0,               WRAP_NONE, STZ)
-wOP16(9EM0X0,   AbsoluteIndexedXX0,               WRAP_NONE, STZ)
-wOPM (9ESlow,   AbsoluteIndexedXSlow,             WRAP_NONE, STZ)
+static void Op64M1() { wOP8(Direct, STZ8); }
+static void Op64M0() { wOP16(Direct, STZ16, WRAP_BANK); }
+static void Op64Slow() { wOPM(DirectSlow, STZ8, STZ16, WRAP_BANK); }
+
+static void Op74E1() { wOP8(DirectIndexedXE1, STZ8); }
+static void Op74E0M1() { wOP8(DirectIndexedXE0, STZ8); }
+static void Op74E0M0() { wOP16(DirectIndexedXE0, STZ16, WRAP_BANK); }
+static void Op74Slow() { wOPM(DirectIndexedXSlow, STZ8, STZ16, WRAP_BANK); }
+
+static void Op9CM1() { wOP8(Absolute, STZ8); }
+static void Op9CM0() { wOP16(Absolute, STZ16); }
+static void Op9CSlow() { wOPM(AbsoluteSlow, STZ8, STZ16); }
+
+static void Op9EM1X1() { wOP8(AbsoluteIndexedXX1, STZ8); }
+static void Op9EM0X1() { wOP16(AbsoluteIndexedXX1, STZ16); }
+static void Op9EM1X0() { wOP8(AbsoluteIndexedXX0, STZ8); }
+static void Op9EM0X0() { wOP16(AbsoluteIndexedXX0, STZ16); }
+static void Op9ESlow() { wOPM(AbsoluteIndexedXSlow, STZ8, STZ16); }
 
 /* TRB ********************************************************************* */
 
-mOP8 (14M1,     Direct,                           WRAP_BANK, TRB)
-mOP16(14M0,     Direct,                           WRAP_BANK, TRB)
-mOPM (14Slow,   DirectSlow,                       WRAP_BANK, TRB)
-
-mOP8 (1CM1,     Absolute,                         WRAP_BANK, TRB)
-mOP16(1CM0,     Absolute,                         WRAP_BANK, TRB)
-mOPM (1CSlow,   AbsoluteSlow,                     WRAP_BANK, TRB)
+static void Op14M1() { mOP8(Direct, TRB8); }
+static void Op14M0() { mOP16(Direct, TRB16, WRAP_BANK); }
+static void Op14Slow() { mOPM(DirectSlow, TRB8, TRB16, WRAP_BANK); }
+
+static void Op1CM1() { mOP8(Absolute, TRB8); }
+static void Op1CM0() { mOP16(Absolute, TRB16, WRAP_BANK); }
+static void Op1CSlow() { mOPM(AbsoluteSlow, TRB8, TRB16, WRAP_BANK); }
 
 /* TSB ********************************************************************* */
 
-mOP8 (04M1,     Direct,                           WRAP_BANK, TSB)
-mOP16(04M0,     Direct,                           WRAP_BANK, TSB)
-mOPM (04Slow,   DirectSlow,                       WRAP_BANK, TSB)
-
-mOP8 (0CM1,     Absolute,                         WRAP_BANK, TSB)
-mOP16(0CM0,     Absolute,                         WRAP_BANK, TSB)
-mOPM (0CSlow,   AbsoluteSlow,                     WRAP_BANK, TSB)
+static void Op04M1() { mOP8(Direct, TSB8); }
+static void Op04M0() { mOP16(Direct, TSB16, WRAP_BANK); }
+static void Op04Slow() { mOPM(DirectSlow, TSB8, TSB16, WRAP_BANK); }
+
+static void Op0CM1() { mOP8(Absolute, TSB8); }
+static void Op0CM0() { mOP16(Absolute, TSB16, WRAP_BANK); }
+static void Op0CSlow() { mOPM(AbsoluteSlow, TSB8, TSB16, WRAP_BANK); }
 
 /* Branch Instructions ***************************************************** */
 
 // BCC
-bOP(90E0,   Relative,     !CheckCarry(),    0, 0)
-bOP(90E1,   Relative,     !CheckCarry(),    0, 1)
-bOP(90Slow, RelativeSlow, !CheckCarry(),    0, CheckEmulation())
+static void Op90E0() { bOP(Relative, !CheckCarry(), false); }
+static void Op90E1() { bOP(Relative, !CheckCarry(), true); }
+static void Op90Slow() { bOP(RelativeSlow, !CheckCarry(), CheckEmulation()); }
 
 // BCS
-bOP(B0E0,   Relative,      CheckCarry(),    0, 0)
-bOP(B0E1,   Relative,      CheckCarry(),    0, 1)
-bOP(B0Slow, RelativeSlow,  CheckCarry(),    0, CheckEmulation())
+static void OpB0E0() { bOP(Relative, CheckCarry(), false); }
+static void OpB0E1() { bOP(Relative, CheckCarry(), true); }
+static void OpB0Slow() { bOP(RelativeSlow, CheckCarry(), CheckEmulation()); }
 
 // BEQ
-bOP(F0E0,   Relative,      CheckZero(),     2, 0)
-bOP(F0E1,   Relative,      CheckZero(),     2, 1)
-bOP(F0Slow, RelativeSlow,  CheckZero(),     2, CheckEmulation())
+static void OpF0E0() { bOP(Relative, CheckZero(), false); }
+static void OpF0E1() { bOP(Relative, CheckZero(), true); }
+static void OpF0Slow() { bOP(RelativeSlow, CheckZero(), CheckEmulation()); }
 
 // BMI
-bOP(30E0,   Relative,      CheckNegative(), 1, 0)
-bOP(30E1,   Relative,      CheckNegative(), 1, 1)
-bOP(30Slow, RelativeSlow,  CheckNegative(), 1, CheckEmulation())
+static void Op30E0() { bOP(Relative, CheckNegative(), false); }
+static void Op30E1() { bOP(Relative, CheckNegative(), true); }
+static void Op30Slow() { bOP(RelativeSlow, CheckNegative(), CheckEmulation()); }
 
 // BNE
-bOP(D0E0,   Relative,     !CheckZero(),     1, 0)
-bOP(D0E1,   Relative,     !CheckZero(),     1, 1)
-bOP(D0Slow, RelativeSlow, !CheckZero(),     1, CheckEmulation())
+static void OpD0E0() { bOP(Relative, !CheckZero(), false); }
+static void OpD0E1() { bOP(Relative, !CheckZero(), true); }
+static void OpD0Slow() { bOP(RelativeSlow, !CheckZero(), CheckEmulation()); }
 
 // BPL
-bOP(10E0,   Relative,     !CheckNegative(), 1, 0)
-bOP(10E1,   Relative,     !CheckNegative(), 1, 1)
-bOP(10Slow, RelativeSlow, !CheckNegative(), 1, CheckEmulation())
+static void Op10E0() { bOP(Relative, !CheckNegative(), false); }
+static void Op10E1() { bOP(Relative, !CheckNegative(), true); }
+static void Op10Slow() { bOP(RelativeSlow, !CheckNegative(), CheckEmulation()); }
 
 // BRA
-bOP(80E0,   Relative,     1,                X, 0)
-bOP(80E1,   Relative,     1,                X, 1)
-bOP(80Slow, RelativeSlow, 1,                X, CheckEmulation())
+static void Op80E0() { bOP(Relative, true, false); }
+static void Op80E1() { bOP(Relative, true, true); }
+static void Op80Slow() { bOP(RelativeSlow, true, CheckEmulation()); }
 
 // BVC
-bOP(50E0,   Relative,     !CheckOverflow(), 0, 0)
-bOP(50E1,   Relative,     !CheckOverflow(), 0, 1)
-bOP(50Slow, RelativeSlow, !CheckOverflow(), 0, CheckEmulation())
+static void Op50E0() { bOP(Relative, !CheckOverflow(), false); }
+static void Op50E1() { bOP(Relative, !CheckOverflow(), true); }
+static void Op50Slow() { bOP(RelativeSlow, !CheckOverflow(), CheckEmulation()); }
 
 // BVS
-bOP(70E0,   Relative,      CheckOverflow(), 0, 0)
-bOP(70E1,   Relative,      CheckOverflow(), 0, 1)
-bOP(70Slow, RelativeSlow,  CheckOverflow(), 0, CheckEmulation())
+static void Op70E0() { bOP(Relative, CheckOverflow(), false); }
+static void Op70E1() { bOP(Relative, CheckOverflow(), true); }
+static void Op70Slow() { bOP(RelativeSlow, CheckOverflow(), CheckEmulation()); }
 
 // BRL
+template<typename F> static inline void Op82Wrapper(F f)
+{
+	S9xSetPCBase(ICPU.ShiftedPB + f(JUMP));
+}
+
 static void Op82()
 {
-	S9xSetPCBase(ICPU.ShiftedPB + RelativeLong(JUMP));
+	Op82Wrapper(RelativeLong);
 }
 
 static void Op82Slow()
 {
-	S9xSetPCBase(ICPU.ShiftedPB + RelativeLongSlow(JUMP));
+	Op82Wrapper(RelativeLongSlow);
 }
 
 /* Flag Instructions ******************************************************* */
@@ -1613,9 +1532,6 @@
 {
 	SetDecimal();
 	AddCycles(ONE_CYCLE);
-#ifdef DEBUGGER
-	missing.decimal_mode = 1;
-#endif
 }
 
 // CLI
@@ -1623,7 +1539,6 @@
 {
 	ClearIRQ();
 	AddCycles(ONE_CYCLE);
-	CHECK_FOR_IRQ();
 }
 
 // SEI
@@ -1642,648 +1557,492 @@
 
 /* DEX/DEY ***************************************************************** */
 
-static void OpCAX1()
+template<typename T> static inline void DEWrapper(T &reg)
 {
 	AddCycles(ONE_CYCLE);
-	Registers.XL--;
-	SetZN(Registers.XL);
-}
-
-static void OpCAX0()
+	--reg;
+	SetZN(reg);
+}
+
+static inline void OpCAX1()
+{
+	DEWrapper(Registers.X.B.l);
+}
+
+static inline void OpCAX0()
+{
+	DEWrapper(Registers.X.W);
+}
+
+static void OpCASlow()
+{
+	if (CheckIndex())
+		OpCAX1();
+	else
+		OpCAX0();
+}
+
+static inline void Op88X1()
+{
+	DEWrapper(Registers.Y.B.l);
+}
+
+static inline void Op88X0()
+{
+	DEWrapper(Registers.Y.W);
+}
+
+static void Op88Slow()
+{
+	if (CheckIndex())
+		Op88X1();
+	else
+		Op88X0();
+}
+
+/* INX/INY ***************************************************************** */
+
+template<typename T> static inline void INWrapper(T &reg)
 {
 	AddCycles(ONE_CYCLE);
-	Registers.X.W--;
-	SetZN(Registers.X.W);
-}
-
-static void OpCASlow()
+	++reg;
+	SetZN(reg);
+}
+
+static inline void OpE8X1()
+{
+	INWrapper(Registers.X.B.l);
+}
+
+static inline void OpE8X0()
+{
+	INWrapper(Registers.X.W);
+}
+
+static void OpE8Slow()
+{
+	if (CheckIndex())
+		OpE8X1();
+	else
+		OpE8X0();
+}
+
+static inline void OpC8X1()
+{
+	INWrapper(Registers.Y.B.l);
+}
+
+static inline void OpC8X0()
+{
+	INWrapper(Registers.Y.W);
+}
+
+static void OpC8Slow()
+{
+	if (CheckIndex())
+		OpC8X1();
+	else
+		OpC8X0();
+}
+
+/* NOP ********************************************************************* */
+
+static void OpEA()
 {
 	AddCycles(ONE_CYCLE);
-
-	if (CheckIndex())
-	{
-		Registers.XL--;
-		SetZN(Registers.XL);
-	}
-	else
-	{
-		Registers.X.W--;
-		SetZN(Registers.X.W);
-	}
-}
-
-static void Op88X1()
-{
-	AddCycles(ONE_CYCLE);
-	Registers.YL--;
-	SetZN(Registers.YL);
-}
-
-static void Op88X0()
-{
-	AddCycles(ONE_CYCLE);
-	Registers.Y.W--;
-	SetZN(Registers.Y.W);
-}
-
-static void Op88Slow()
-{
-	AddCycles(ONE_CYCLE);
-
-	if (CheckIndex())
-	{
-		Registers.YL--;
-		SetZN(Registers.YL);
-	}
-	else
-	{
-		Registers.Y.W--;
-		SetZN(Registers.Y.W);
-	}
-}
-
-/* INX/INY ***************************************************************** */
-
-static void OpE8X1()
-{
-	AddCycles(ONE_CYCLE);
-	Registers.XL++;
-	SetZN(Registers.XL);
-}
-
-static void OpE8X0()
-{
-	AddCycles(ONE_CYCLE);
-	Registers.X.W++;
-	SetZN(Registers.X.W);
-}
-
-static void OpE8Slow()
-{
-	AddCycles(ONE_CYCLE);
-
-	if (CheckIndex())
-	{
-		Registers.XL++;
-		SetZN(Registers.XL);
-	}
-	else
-	{
-		Registers.X.W++;
-		SetZN(Registers.X.W);
-	}
-}
-
-static void OpC8X1()
-{
-	AddCycles(ONE_CYCLE);
-	Registers.YL++;
-	SetZN(Registers.YL);
-}
-
-static void OpC8X0()
-{
-	AddCycles(ONE_CYCLE);
-	Registers.Y.W++;
-	SetZN(Registers.Y.W);
-}
-
-static void OpC8Slow()
-{
-	AddCycles(ONE_CYCLE);
-
-	if (CheckIndex())
-	{
-		Registers.YL--;
-		SetZN(Registers.YL);
-	}
-	else
-	{
-		Registers.Y.W--;
-		SetZN(Registers.Y.W);
-	}
-}
-
-/* NOP ********************************************************************* */
-
-static void OpEA()
-{
-	AddCycles(ONE_CYCLE);
 }
 
 /* PUSH Instructions ******************************************************* */
 
-#define PushW(w) \
-	S9xSetWord(w, Registers.S.W - 1, WRAP_BANK, WRITE_10); \
+static inline void PushW(uint16_t w)
+{
+	S9xSetWord(w, Registers.S.W - 1, WRAP_BANK, WRITE_10);
 	Registers.S.W -= 2;
-
-#define PushWE(w) \
-	Registers.SL--; \
-	S9xSetWord(w, Registers.S.W, WRAP_PAGE, WRITE_10); \
-	Registers.SL--;
-
-#define PushB(b) \
+}
+
+static inline void PushWE(uint16_t w)
+{
+	--Registers.S.B.l;
+	S9xSetWord(w, Registers.S.W, WRAP_PAGE, WRITE_10);
+	--Registers.S.B.l;
+}
+
+static inline void PushB(uint8_t b)
+{
 	S9xSetByte(b, Registers.S.W--);
-
-#define PushBE(b) \
-	S9xSetByte(b, Registers.S.W); \
-	Registers.SL--;
+}
+
+static inline void PushBE(uint8_t b)
+{
+	S9xSetByte(b, Registers.S.W);
+	--Registers.S.B.l;
+}
+
+template<typename F> static inline void PEWrapper(F f, bool cond)
+{
+	uint16_t val = static_cast<uint16_t>(f(NONE));
+	PushW(val);
+	OpenBus = val & 0xff;
+	if (cond)
+		Registers.S.B.h = 1;
+}
 
 // PEA
 static void OpF4E0()
 {
-	uint16_t	val = (uint16_t) Absolute(NONE);
-	PushW(val);
-	OpenBus = val & 0xff;
+	PEWrapper(Absolute, false);
 }
 
 static void OpF4E1()
 {
 	// Note: PEA is a new instruction,
 	// and so doesn't respect the emu-mode stack bounds.
-	uint16_t	val = (uint16_t) Absolute(NONE);
-	PushW(val);
-	OpenBus = val & 0xff;
-	Registers.SH = 1;
+	PEWrapper(Absolute, true);
 }
 
 static void OpF4Slow()
 {
-	uint16_t	val = (uint16_t) AbsoluteSlow(NONE);
-	PushW(val);
-	OpenBus = val & 0xff;
-	if (CheckEmulation())
-		Registers.SH = 1;
+	PEWrapper(AbsoluteSlow, CheckEmulation());
 }
 
 // PEI
 static void OpD4E0()
 {
-	uint16_t	val = (uint16_t) DirectIndirectE0(NONE);
-	PushW(val);
-	OpenBus = val & 0xff;
+	PEWrapper(DirectIndirectE0, false);
 }
 
 static void OpD4E1()
 {
 	// Note: PEI is a new instruction,
 	// and so doesn't respect the emu-mode stack bounds.
-	uint16_t	val = (uint16_t) DirectIndirectE1(NONE);
-	PushW(val);
-	OpenBus = val & 0xff;
-	Registers.SH = 1;
+	PEWrapper(DirectIndirectE1, true);
 }
 
 static void OpD4Slow()
 {
-	uint16_t	val = (uint16_t) DirectIndirectSlow(NONE);
-	PushW(val);
-	OpenBus = val & 0xff;
-	if (CheckEmulation())
-		Registers.SH = 1;
+	PEWrapper(DirectIndirectSlow, CheckEmulation());
 }
 
 // PER
 static void Op62E0()
 {
-	uint16_t	val = (uint16_t) RelativeLong(NONE);
-	PushW(val);
-	OpenBus = val & 0xff;
+	PEWrapper(RelativeLong, false);
 }
 
 static void Op62E1()
 {
 	// Note: PER is a new instruction,
 	// and so doesn't respect the emu-mode stack bounds.
-	uint16_t	val = (uint16_t) RelativeLong(NONE);
-	PushW(val);
-	OpenBus = val & 0xff;
-	Registers.SH = 1;
+	PEWrapper(RelativeLong, true);
 }
 
 static void Op62Slow()
 {
-	uint16_t	val = (uint16_t) RelativeLongSlow(NONE);
-	PushW(val);
-	OpenBus = val & 0xff;
+	PEWrapper(RelativeLongSlow, CheckEmulation());
+}
+
+template<typename Treg, typename Tob, typename F> static inline void PHWrapper(const Treg &pushReg, const Tob &obReg, F f, bool cond)
+{
+	AddCycles(ONE_CYCLE);
+	f(pushReg);
+	OpenBus = obReg;
+	if (cond)
+		Registers.S.B.h = 1;
+}
+
+// PHA
+static inline void Op48E1()
+{
+	PHWrapper(Registers.A.B.l, Registers.A.B.l, PushBE, false);
+}
+
+static inline void Op48E0M1()
+{
+	PHWrapper(Registers.A.B.l, Registers.A.B.l, PushB, false);
+}
+
+static inline void Op48E0M0()
+{
+	PHWrapper(Registers.A.W, Registers.A.B.l, PushW, false);
+}
+
+static void Op48Slow()
+{
 	if (CheckEmulation())
-		Registers.SH = 1;
-}
-
-// PHA
-static void Op48E1()
-{
-	AddCycles(ONE_CYCLE);
-	PushBE(Registers.AL);
-	OpenBus = Registers.AL;
-}
-
-static void Op48E0M1()
-{
-	AddCycles(ONE_CYCLE);
-	PushB(Registers.AL);
-	OpenBus = Registers.AL;
-}
-
-static void Op48E0M0()
-{
-	AddCycles(ONE_CYCLE);
-	PushW(Registers.A.W);
-	OpenBus = Registers.AL;
-}
-
-static void Op48Slow()
-{
-	AddCycles(ONE_CYCLE);
-
+		Op48E1();
+	else if (CheckMemory())
+		Op48E0M1();
+	else
+		Op48E0M0();
+}
+
+// PHB
+static inline void Op8BE1()
+{
+	PHWrapper(Registers.DB, Registers.DB, PushBE, false);
+}
+
+static inline void Op8BE0()
+{
+	PHWrapper(Registers.DB, Registers.DB, PushB, false);
+}
+
+static void Op8BSlow()
+{
 	if (CheckEmulation())
-	{
-		PushBE(Registers.AL);
-	}
-	else
-	if (CheckMemory())
-	{
-		PushB(Registers.AL);
-	}
-	else
-	{
-		PushW(Registers.A.W);
-	}
-
-	OpenBus = Registers.AL;
-}
-
-// PHB
-static void Op8BE1()
-{
-	AddCycles(ONE_CYCLE);
-	PushBE(Registers.DB);
-	OpenBus = Registers.DB;
-}
-
-static void Op8BE0()
-{
-	AddCycles(ONE_CYCLE);
-	PushB(Registers.DB);
-	OpenBus = Registers.DB;
-}
-
-static void Op8BSlow()
-{
-	AddCycles(ONE_CYCLE);
-
-	if (CheckEmulation())
-	{
-		PushBE(Registers.DB);
-	}
-	else
-	{
-		PushB(Registers.DB);
-	}
-
-	OpenBus = Registers.DB;
+		Op8BE1();
+	else
+		Op8BE0();
 }
 
 // PHD
 static void Op0BE0()
 {
-	AddCycles(ONE_CYCLE);
-	PushW(Registers.D.W);
-	OpenBus = Registers.DL;
+	PHWrapper(Registers.D.W, Registers.D.B.l, PushW, false);
 }
 
 static void Op0BE1()
 {
 	// Note: PHD is a new instruction,
 	// and so doesn't respect the emu-mode stack bounds.
-	AddCycles(ONE_CYCLE);
-	PushW(Registers.D.W);
-	OpenBus = Registers.DL;
-	Registers.SH = 1;
+	PHWrapper(Registers.D.W, Registers.D.B.l, PushW, true);
 }
 
 static void Op0BSlow()
 {
-	AddCycles(ONE_CYCLE);
-	PushW(Registers.D.W);
-	OpenBus = Registers.DL;
+	PHWrapper(Registers.D.W, Registers.D.B.l, PushW, CheckEmulation());
+}
+
+// PHK
+static inline void Op4BE1()
+{
+	PHWrapper(Registers.PC.B.xPB, Registers.PC.B.xPB, PushBE, false);
+}
+
+static inline void Op4BE0()
+{
+	PHWrapper(Registers.PC.B.xPB, Registers.PC.B.xPB, PushB, false);
+}
+
+static void Op4BSlow()
+{
 	if (CheckEmulation())
-		Registers.SH = 1;
-}
-
-// PHK
-static void Op4BE1()
-{
-	AddCycles(ONE_CYCLE);
-	PushBE(Registers.PB);
-	OpenBus = Registers.PB;
-}
-
-static void Op4BE0()
-{
-	AddCycles(ONE_CYCLE);
-	PushB(Registers.PB);
-	OpenBus = Registers.PB;
-}
-
-static void Op4BSlow()
-{
-	AddCycles(ONE_CYCLE);
-
+		Op4BE1();
+	else
+		Op4BE0();
+}
+
+// PHP
+static inline void Op08E1()
+{
+	S9xPackStatus();
+	PHWrapper(Registers.P.B.l, Registers.P.B.l, PushBE, false);
+}
+
+static inline void Op08E0()
+{
+	S9xPackStatus();
+	PHWrapper(Registers.P.B.l, Registers.P.B.l, PushB, false);
+}
+
+static void Op08Slow()
+{
 	if (CheckEmulation())
-	{
-		PushBE(Registers.PB);
-	}
-	else
-	{
-		PushB(Registers.PB);
-	}
-
-	OpenBus = Registers.PB;
-}
-
-// PHP
-static void Op08E0()
-{
-	S9xPackStatus();
-	AddCycles(ONE_CYCLE);
-	PushB(Registers.PL);
-	OpenBus = Registers.PL;
-}
-
-static void Op08E1()
-{
-	S9xPackStatus();
-	AddCycles(ONE_CYCLE);
-	PushBE(Registers.PL);
-	OpenBus = Registers.PL;
-}
-
-static void Op08Slow()
-{
-	S9xPackStatus();
-	AddCycles(ONE_CYCLE);
-
+		Op08E1();
+	else
+		Op08E0();
+}
+
+// PHX
+static inline void OpDAE1()
+{
+	PHWrapper(Registers.X.B.l, Registers.X.B.l, PushBE, false);
+}
+
+static inline void OpDAE0X1()
+{
+	PHWrapper(Registers.X.B.l, Registers.X.B.l, PushB, false);
+}
+
+static inline void OpDAE0X0()
+{
+	PHWrapper(Registers.X.W, Registers.X.B.l, PushW, false);
+}
+
+static void OpDASlow()
+{
 	if (CheckEmulation())
-	{
-		PushBE(Registers.PL);
-	}
-	else
-	{
-		PushB(Registers.PL);
-	}
-
-	OpenBus = Registers.PL;
-}
-
-// PHX
-static void OpDAE1()
-{
-	AddCycles(ONE_CYCLE);
-	PushBE(Registers.XL);
-	OpenBus = Registers.XL;
-}
-
-static void OpDAE0X1()
-{
-	AddCycles(ONE_CYCLE);
-	PushB(Registers.XL);
-	OpenBus = Registers.XL;
-}
-
-static void OpDAE0X0()
-{
-	AddCycles(ONE_CYCLE);
-	PushW(Registers.X.W);
-	OpenBus = Registers.XL;
-}
-
-static void OpDASlow()
-{
-	AddCycles(ONE_CYCLE);
-
+		OpDAE1();
+	else if (CheckIndex())
+		OpDAE0X1();
+	else
+		OpDAE0X0();
+}
+
+// PHY
+static inline void Op5AE1()
+{
+	PHWrapper(Registers.Y.B.l, Registers.Y.B.l, PushBE, false);
+}
+
+static inline void Op5AE0X1()
+{
+	PHWrapper(Registers.Y.B.l, Registers.Y.B.l, PushB, false);
+}
+
+static inline void Op5AE0X0()
+{
+	PHWrapper(Registers.Y.W, Registers.Y.B.l, PushW, false);
+}
+
+static void Op5ASlow()
+{
 	if (CheckEmulation())
-	{
-		PushBE(Registers.XL);
-	}
-	else
-	if (CheckIndex())
-	{
-		PushB(Registers.XL);
-	}
-	else
-	{
-		PushW(Registers.X.W);
-	}
-
-	OpenBus = Registers.XL;
-}
-
-// PHY
-static void Op5AE1()
-{
-	AddCycles(ONE_CYCLE);
-	PushBE(Registers.YL);
-	OpenBus = Registers.YL;
-}
-
-static void Op5AE0X1()
-{
-	AddCycles(ONE_CYCLE);
-	PushB(Registers.YL);
-	OpenBus = Registers.YL;
-}
-
-static void Op5AE0X0()
-{
-	AddCycles(ONE_CYCLE);
-	PushW(Registers.Y.W);
-	OpenBus = Registers.YL;
-}
-
-static void Op5ASlow()
-{
-	AddCycles(ONE_CYCLE);
-
+		Op5AE1();
+	else if (CheckIndex())
+		Op5AE0X1();
+	else
+		Op5AE0X0();
+}
+
+/* PULL Instructions ******************************************************* */
+
+static inline void PullW(uint16_t &w)
+{
+	w = S9xGetWord(Registers.S.W + 1, WRAP_BANK);
+	Registers.S.W += 2;
+}
+
+static inline void PullWE(uint16_t &w)
+{
+	++Registers.S.B.l;
+	w = S9xGetWord(Registers.S.W, WRAP_PAGE);
+	++Registers.S.B.l;
+}
+
+static inline void PullB(uint8_t &b)
+{
+	b = S9xGetByte(++Registers.S.W);
+}
+
+static inline void PullBE(uint8_t &b)
+{
+	++Registers.S.B.l;
+	b = S9xGetByte(Registers.S.W);
+}
+
+// PLA
+template<typename Treg, typename Tob, typename F> static inline void Op68Wrapper(Treg &pullReg, const Tob &obReg, F f)
+{
+	AddCycles(TWO_CYCLES);
+	f(pullReg);
+	SetZN(pullReg);
+	OpenBus = obReg;
+}
+
+static inline void Op68E1()
+{
+	Op68Wrapper(Registers.A.B.l, Registers.A.B.l, PullBE);
+}
+
+static inline void Op68E0M1()
+{
+	Op68Wrapper(Registers.A.B.l, Registers.A.B.l, PullB);
+}
+
+static inline void Op68E0M0()
+{
+	Op68Wrapper(Registers.A.W, Registers.A.B.h, PullW);
+}
+
+static void Op68Slow()
+{
 	if (CheckEmulation())
-	{
-		PushBE(Registers.YL);
-	}
-	else
-	if (CheckIndex())
-	{
-		PushB(Registers.YL);
-	}
-	else
-	{
-		PushW(Registers.Y.W);
-	}
-
-	OpenBus = Registers.YL;
-}
-
-/* PULL Instructions ******************************************************* */
-
-#define PullW(w) \
-	w = S9xGetWord(Registers.S.W + 1, WRAP_BANK); \
-	Registers.S.W += 2;
-
-#define PullWE(w) \
-	Registers.SL++; \
-	w = S9xGetWord(Registers.S.W, WRAP_PAGE); \
-	Registers.SL++;
-
-#define PullB(b) \
-	b = S9xGetByte(++Registers.S.W);
-
-#define PullBE(b) \
-	Registers.SL++; \
-	b = S9xGetByte(Registers.S.W);
-
-// PLA
-static void Op68E1()
+		Op68E1();
+	else if (CheckMemory())
+		Op68E0M1();
+	else
+		Op68E0M0();
+}
+
+// PLB
+template<typename F> static inline void OpABWrapper(F f)
 {
 	AddCycles(TWO_CYCLES);
-	PullBE(Registers.AL);
-	SetZN(Registers.AL);
-	OpenBus = Registers.AL;
-}
-
-static void Op68E0M1()
-{
-	AddCycles(TWO_CYCLES);
-	PullB(Registers.AL);
-	SetZN(Registers.AL);
-	OpenBus = Registers.AL;
-}
-
-static void Op68E0M0()
-{
-	AddCycles(TWO_CYCLES);
-	PullW(Registers.A.W);
-	SetZN(Registers.A.W);
-	OpenBus = Registers.AH;
-}
-
-static void Op68Slow()
-{
-	AddCycles(TWO_CYCLES);
-
-	if (CheckEmulation())
-	{
-		PullBE(Registers.AL);
-		SetZN(Registers.AL);
-		OpenBus = Registers.AL;
-	}
-	else
-	if (CheckMemory())
-	{
-		PullB(Registers.AL);
-		SetZN(Registers.AL);
-		OpenBus = Registers.AL;
-	}
-	else
-	{
-		PullW(Registers.A.W);
-		SetZN(Registers.A.W);
-		OpenBus = Registers.AH;
-	}
-}
-
-// PLB
-static void OpABE1()
-{
-	AddCycles(TWO_CYCLES);
-	PullBE(Registers.DB);
+	f(Registers.DB);
 	SetZN(Registers.DB);
 	ICPU.ShiftedDB = Registers.DB << 16;
 	OpenBus = Registers.DB;
 }
 
-static void OpABE0()
-{
-	AddCycles(TWO_CYCLES);
-	PullB(Registers.DB);
-	SetZN(Registers.DB);
-	ICPU.ShiftedDB = Registers.DB << 16;
-	OpenBus = Registers.DB;
+static inline void OpABE1()
+{
+	OpABWrapper(PullBE);
+}
+
+static inline void OpABE0()
+{
+	OpABWrapper(PullB);
 }
 
 static void OpABSlow()
 {
-	AddCycles(TWO_CYCLES);
-
 	if (CheckEmulation())
-	{
-		PullBE(Registers.DB);
-	}
-	else
-	{
-		PullB(Registers.DB);
-	}
-
-	SetZN(Registers.DB);
-	ICPU.ShiftedDB = Registers.DB << 16;
-	OpenBus = Registers.DB;
+		OpABE1();
+	else
+		OpABE0();
 }
 
 // PLD
-static void Op2BE0()
+static inline void Op2BWrapper(bool cond)
 {
 	AddCycles(TWO_CYCLES);
 	PullW(Registers.D.W);
 	SetZN(Registers.D.W);
-	OpenBus = Registers.DH;
+	OpenBus = Registers.D.B.h;
+	if (cond)
+		Registers.S.B.h = 1;
+}
+
+static void Op2BE0()
+{
+	Op2BWrapper(false);
 }
 
 static void Op2BE1()
 {
 	// Note: PLD is a new instruction,
 	// and so doesn't respect the emu-mode stack bounds.
-	AddCycles(TWO_CYCLES);
-	PullW(Registers.D.W);
-	SetZN(Registers.D.W);
-	OpenBus = Registers.DH;
-	Registers.SH = 1;
+	Op2BWrapper(true);
 }
 
 static void Op2BSlow()
 {
-	AddCycles(TWO_CYCLES);
-	PullW(Registers.D.W);
-	SetZN(Registers.D.W);
-	OpenBus = Registers.DH;
-	if (CheckEmulation())
-		Registers.SH = 1;
+	Op2BWrapper(CheckEmulation());
 }
 
 // PLP
 static void Op28E1()
 {
 	AddCycles(TWO_CYCLES);
-	PullBE(Registers.PL);
-	OpenBus = Registers.PL;
+	PullBE(Registers.P.B.l);
+	OpenBus = Registers.P.B.l;
 	SetFlags(MemoryFlag | IndexFlag);
 	S9xUnpackStatus();
 	S9xFixCycles();
-	CHECK_FOR_IRQ();
 }
 
 static void Op28E0()
 {
 	AddCycles(TWO_CYCLES);
-	PullB(Registers.PL);
-	OpenBus = Registers.PL;
+	PullB(Registers.P.B.l);
+	OpenBus = Registers.P.B.l;
 	S9xUnpackStatus();
 
 	if (CheckIndex())
-	{
-		Registers.XH = 0;
-		Registers.YH = 0;
-	}
+		Registers.X.B.h = Registers.Y.B.h = 0;
 
 	S9xFixCycles();
-	CHECK_FOR_IRQ();
 }
 
 static void Op28Slow()
@@ -2292,198 +2051,145 @@
 
 	if (CheckEmulation())
 	{
-		PullBE(Registers.PL);
-		OpenBus = Registers.PL;
+		PullBE(Registers.P.B.l);
+		OpenBus = Registers.P.B.l;
 		SetFlags(MemoryFlag | IndexFlag);
 	}
 	else
 	{
-		PullB(Registers.PL);
-		OpenBus = Registers.PL;
+		PullB(Registers.P.B.l);
+		OpenBus = Registers.P.B.l;
 	}
 
 	S9xUnpackStatus();
 
 	if (CheckIndex())
-	{
-		Registers.XH = 0;
-		Registers.YH = 0;
-	}
+		Registers.X.B.h = Registers.Y.B.h = 0;
 
 	S9xFixCycles();
-	CHECK_FOR_IRQ();
 }
 
 // PLX
-static void OpFAE1()
+static inline void OpFAE1()
 {
 	AddCycles(TWO_CYCLES);
-	PullBE(Registers.XL);
-	SetZN(Registers.XL);
-	OpenBus = Registers.XL;
-}
-
-static void OpFAE0X1()
+	PullBE(Registers.X.B.l);
+	SetZN(Registers.X.B.l);
+	OpenBus = Registers.X.B.l;
+}
+
+static inline void OpFAE0X1()
 {
 	AddCycles(TWO_CYCLES);
-	PullB(Registers.XL);
-	SetZN(Registers.XL);
-	OpenBus = Registers.XL;
-}
-
-static void OpFAE0X0()
+	PullB(Registers.X.B.l);
+	SetZN(Registers.X.B.l);
+	OpenBus = Registers.X.B.l;
+}
+
+static inline void OpFAE0X0()
 {
 	AddCycles(TWO_CYCLES);
 	PullW(Registers.X.W);
 	SetZN(Registers.X.W);
-	OpenBus = Registers.XH;
+	OpenBus = Registers.X.B.h;
 }
 
 static void OpFASlow()
 {
+	if (CheckEmulation())
+		OpFAE1();
+	else if (CheckIndex())
+		OpFAE0X1();
+	else
+		OpFAE0X0();
+}
+
+// PLY
+static inline void Op7AE1()
+{
 	AddCycles(TWO_CYCLES);
-
-	if (CheckEmulation())
-	{
-		PullBE(Registers.XL);
-		SetZN(Registers.XL);
-		OpenBus = Registers.XL;
-	}
-	else
-	if (CheckIndex())
-	{
-		PullB(Registers.XL);
-		SetZN(Registers.XL);
-		OpenBus = Registers.XL;
-	}
-	else
-	{
-		PullW(Registers.X.W);
-		SetZN(Registers.X.W);
-		OpenBus = Registers.XH;
-	}
-}
-
-// PLY
-static void Op7AE1()
+	PullBE(Registers.Y.B.l);
+	SetZN(Registers.Y.B.l);
+	OpenBus = Registers.Y.B.l;
+}
+
+static inline void Op7AE0X1()
 {
 	AddCycles(TWO_CYCLES);
-	PullBE(Registers.YL);
-	SetZN(Registers.YL);
-	OpenBus = Registers.YL;
-}
-
-static void Op7AE0X1()
-{
-	AddCycles(TWO_CYCLES);
-	PullB(Registers.YL);
-	SetZN(Registers.YL);
-	OpenBus = Registers.YL;
-}
-
-static void Op7AE0X0()
+	PullB(Registers.Y.B.l);
+	SetZN(Registers.Y.B.l);
+	OpenBus = Registers.Y.B.l;
+}
+
+static inline void Op7AE0X0()
 {
 	AddCycles(TWO_CYCLES);
 	PullW(Registers.Y.W);
 	SetZN(Registers.Y.W);
-	OpenBus = Registers.YH;
+	OpenBus = Registers.Y.B.h;
 }
 
 static void Op7ASlow()
 {
-	AddCycles(TWO_CYCLES);
-
 	if (CheckEmulation())
-	{
-		PullBE(Registers.YL);
-		SetZN(Registers.YL);
-		OpenBus = Registers.YL;
-	}
-	else
+		Op7AE1();
+	else if (CheckIndex())
+		Op7AE0X1();
+	else
+		Op7AE0X0();
+}
+
+/* Transfer Instructions *************************************************** */
+
+template<typename T> static inline void TransferWrapper(T &reg1, const T &reg2)
+{
+	AddCycles(ONE_CYCLE);
+	reg1 = reg2;
+	SetZN(reg1);
+}
+
+// TAX
+static inline void OpAAX1()
+{
+	TransferWrapper(Registers.X.B.l, Registers.A.B.l);
+}
+
+static inline void OpAAX0()
+{
+	TransferWrapper(Registers.X.W, Registers.A.W);
+}
+
+static void OpAASlow()
+{
 	if (CheckIndex())
-	{
-		PullB(Registers.YL);
-		SetZN(Registers.YL);
-		OpenBus = Registers.YL;
-	}
-	else
-	{
-		PullW(Registers.Y.W);
-		SetZN(Registers.Y.W);
-		OpenBus = Registers.YH;
-	}
-}
-
-/* Transfer Instructions *************************************************** */
-
-// TAX
-static void OpAAX1()
-{
-	AddCycles(ONE_CYCLE);
-	Registers.XL = Registers.AL;
-	SetZN(Registers.XL);
-}
-
-static void OpAAX0()
-{
-	AddCycles(ONE_CYCLE);
-	Registers.X.W = Registers.A.W;
-	SetZN(Registers.X.W);
-}
-
-static void OpAASlow()
-{
-	AddCycles(ONE_CYCLE);
-
+		OpAAX1();
+	else
+		OpAAX0();
+}
+
+// TAY
+static inline void OpA8X1()
+{
+	TransferWrapper(Registers.Y.B.l, Registers.A.B.l);
+}
+
+static inline void OpA8X0()
+{
+	TransferWrapper(Registers.Y.W, Registers.A.W);
+}
+
+static void OpA8Slow()
+{
 	if (CheckIndex())
-	{
-		Registers.XL = Registers.AL;
-		SetZN(Registers.XL);
-	}
-	else
-	{
-		Registers.X.W = Registers.A.W;
-		SetZN(Registers.X.W);
-	}
-}
-
-// TAY
-static void OpA8X1()
-{
-	AddCycles(ONE_CYCLE);
-	Registers.YL = Registers.AL;
-	SetZN(Registers.YL);
-}
-
-static void OpA8X0()
-{
-	AddCycles(ONE_CYCLE);
-	Registers.Y.W = Registers.A.W;
-	SetZN(Registers.Y.W);
-}
-
-static void OpA8Slow()
-{
-	AddCycles(ONE_CYCLE);
-
-	if (CheckIndex())
-	{
-		Registers.YL = Registers.AL;
-		SetZN(Registers.YL);
-	}
-	else
-	{
-		Registers.Y.W = Registers.A.W;
-		SetZN(Registers.Y.W);
-	}
+		OpA8X1();
+	else
+		OpA8X0();
 }
 
 // TCD
 static void Op5B()
 {
-	AddCycles(ONE_CYCLE);
-	Registers.D.W = Registers.A.W;
-	SetZN(Registers.D.W);
+	TransferWrapper(Registers.D.W, Registers.A.W);
 }
 
 // TCS
@@ -2492,85 +2198,57 @@
 	AddCycles(ONE_CYCLE);
 	Registers.S.W = Registers.A.W;
 	if (CheckEmulation())
-		Registers.SH = 1;
+		Registers.S.B.h = 1;
 }
 
 // TDC
 static void Op7B()
 {
-	AddCycles(ONE_CYCLE);
-	Registers.A.W = Registers.D.W;
-	SetZN(Registers.A.W);
+	TransferWrapper(Registers.A.W, Registers.D.W);
 }
 
 // TSC
 static void Op3B()
 {
-	AddCycles(ONE_CYCLE);
-	Registers.A.W = Registers.S.W;
-	SetZN(Registers.A.W);
+	TransferWrapper(Registers.A.W, Registers.S.W);
 }
 
 // TSX
-static void OpBAX1()
-{
-	AddCycles(ONE_CYCLE);
-	Registers.XL = Registers.SL;
-	SetZN(Registers.XL);
-}
-
-static void OpBAX0()
-{
-	AddCycles(ONE_CYCLE);
-	Registers.X.W = Registers.S.W;
-	SetZN(Registers.X.W);
+static inline void OpBAX1()
+{
+	TransferWrapper(Registers.X.B.l, Registers.S.B.l);
+}
+
+static inline void OpBAX0()
+{
+	TransferWrapper(Registers.X.W, Registers.S.W);
 }
 
 static void OpBASlow()
 {
-	AddCycles(ONE_CYCLE);
-
 	if (CheckIndex())
-	{
-		Registers.XL = Registers.SL;
-		SetZN(Registers.XL);
-	}
-	else
-	{
-		Registers.X.W = Registers.S.W;
-		SetZN(Registers.X.W);
-	}
+		OpBAX1();
+	else
+		OpBAX0();
 }
 
 // TXA
-static void Op8AM1()
-{
-	AddCycles(ONE_CYCLE);
-	Registers.AL = Registers.XL;
-	SetZN(Registers.AL);
-}
-
-static void Op8AM0()
-{
-	AddCycles(ONE_CYCLE);
-	Registers.A.W = Registers.X.W;
-	SetZN(Registers.A.W);
+static inline void Op8AM1()
+{
+	TransferWrapper(Registers.A.B.l, Registers.X.B.l);
+}
+
+static inline void Op8AM0()
+{
+	TransferWrapper(Registers.A.W, Registers.X.W);
 }
 
 static void Op8ASlow()
 {
-	AddCycles(ONE_CYCLE);
-
 	if (CheckMemory())
-	{
-		Registers.AL = Registers.XL;
-		SetZN(Registers.AL);
-	}
-	else
-	{
-		Registers.A.W = Registers.X.W;
-		SetZN(Registers.A.W);
-	}
+		Op8AM1();
+	else
+		Op8AM0();
 }
 
 // TXS
@@ -2579,128 +2257,86 @@
 	AddCycles(ONE_CYCLE);
 	Registers.S.W = Registers.X.W;
 	if (CheckEmulation())
-		Registers.SH = 1;
+		Registers.S.B.h = 1;
 }
 
 // TXY
-static void Op9BX1()
+static inline void Op9BX1()
+{
+	TransferWrapper(Registers.Y.B.l, Registers.X.B.l);
+}
+
+static inline void Op9BX0()
+{
+	TransferWrapper(Registers.Y.W, Registers.X.W);
+}
+
+static void Op9BSlow()
+{
+	if (CheckIndex())
+		Op9BX1();
+	else
+		Op9BX0();
+}
+
+// TYA
+static inline void Op98M1()
+{
+	TransferWrapper(Registers.A.B.l, Registers.Y.B.l);
+}
+
+static inline void Op98M0()
+{
+	TransferWrapper(Registers.A.W, Registers.Y.W);
+}
+
+static void Op98Slow()
+{
+	if (CheckMemory())
+		Op98M1();
+	else
+		Op98M0();
+}
+
+// TYX
+static inline void OpBBX1()
+{
+	TransferWrapper(Registers.X.B.l, Registers.Y.B.l);
+}
+
+static inline void OpBBX0()
+{
+	TransferWrapper(Registers.X.W, Registers.Y.W);
+}
+
+static void OpBBSlow()
+{
+	if (CheckIndex())
+		OpBBX1();
+	else
+		OpBBX0();
+}
+
+/* XCE ********************************************************************* */
+
+static void OpFB()
 {
 	AddCycles(ONE_CYCLE);
-	Registers.YL = Registers.XL;
-	SetZN(Registers.YL);
-}
-
-static void Op9BX0()
-{
-	AddCycles(ONE_CYCLE);
-	Registers.Y.W = Registers.X.W;
-	SetZN(Registers.Y.W);
-}
-
-static void Op9BSlow()
-{
-	AddCycles(ONE_CYCLE);
-
-	if (CheckIndex())
-	{
-		Registers.YL = Registers.XL;
-		SetZN(Registers.YL);
-	}
-	else
-	{
-		Registers.Y.W = Registers.X.W;
-		SetZN(Registers.Y.W);
-	}
-}
-
-// TYA
-static void Op98M1()
-{
-	AddCycles(ONE_CYCLE);
-	Registers.AL = Registers.YL;
-	SetZN(Registers.AL);
-}
-
-static void Op98M0()
-{
-	AddCycles(ONE_CYCLE);
-	Registers.A.W = Registers.Y.W;
-	SetZN(Registers.A.W);
-}
-
-static void Op98Slow()
-{
-	AddCycles(ONE_CYCLE);
-
-	if (CheckMemory())
-	{
-		Registers.AL = Registers.YL;
-		SetZN(Registers.AL);
-	}
-	else
-	{
-		Registers.A.W = Registers.Y.W;
-		SetZN(Registers.A.W);
-	}
-}
-
-// TYX
-static void OpBBX1()
-{
-	AddCycles(ONE_CYCLE);
-	Registers.XL = Registers.YL;
-	SetZN(Registers.XL);
-}
-
-static void OpBBX0()
-{
-	AddCycles(ONE_CYCLE);
-	Registers.X.W = Registers.Y.W;
-	SetZN(Registers.X.W);
-}
-
-static void OpBBSlow()
-{
-	AddCycles(ONE_CYCLE);
-
-	if (CheckIndex())
-	{
-		Registers.XL = Registers.YL;
-		SetZN(Registers.XL);
-	}
-	else
-	{
-		Registers.X.W = Registers.Y.W;
-		SetZN(Registers.X.W);
-	}
-}
-
-/* XCE ********************************************************************* */
-
-static void OpFB()
-{
-	AddCycles(ONE_CYCLE);
-
-	uint8_t	A1 = ICPU._Carry;
-	uint8_t	A2 = Registers.PH;
+
+	uint8_t A1 = ICPU._Carry;
+	uint8_t A2 = Registers.P.B.h;
 
 	ICPU._Carry = A2 & 1;
-	Registers.PH = A1;
+	Registers.P.B.h = A1;
 
 	if (CheckEmulation())
 	{
 		SetFlags(MemoryFlag | IndexFlag);
-		Registers.SH = 1;
-	#ifdef DEBUGGER
-		missing.emulate6502 = 1;
-	#endif
+		Registers.S.B.h = 1;
 	}
 
 	if (CheckIndex())
-	{
-		Registers.XH = 0;
-		Registers.YH = 0;
-	}
+		Registers.X.B.h = Registers.Y.B.h = 0;
 
 	S9xFixCycles();
 }
@@ -2709,647 +2345,430 @@
 
 static void Op00()
 {
-#ifdef DEBUGGER
-	if (CPU.Flags & TRACE_FLAG)
-		S9xTraceMessage("*** BRK");
-#endif
-
 	AddCycles(CPU.MemSpeed);
-
-	uint16_t	addr;
 
 	if (!CheckEmulation())
 	{
-		PushB(Registers.PB);
-		PushW(Registers.PCw + 1);
+		PushB(Registers.PC.B.xPB);
+		PushW(Registers.PC.W.xPC + 1);
 		S9xPackStatus();
-		PushB(Registers.PL);
-		OpenBus = Registers.PL;
+		PushB(Registers.P.B.l);
+	}
+	else
+	{
+		PushWE(Registers.PC.W.xPC + 1);
+		S9xPackStatus();
+		PushBE(Registers.P.B.l);
+	}
+	OpenBus = Registers.P.B.l;
+	ClearDecimal();
+	SetIRQ();
+
+	uint16_t addr = S9xGetWord(0xFFFE);
+
+	S9xSetPCBase(addr);
+	OpenBus = addr >> 8;
+}
+
+/* IRQ ********************************************************************* */
+
+void S9xOpcode_IRQ()
+{
+	// IRQ and NMI do an opcode fetch as their first "IO" cycle.
+	AddCycles(CPU.MemSpeed + ONE_CYCLE);
+
+	uint16_t addr;
+	if (!CheckEmulation())
+	{
+		PushB(Registers.PC.B.xPB);
+		PushW(Registers.PC.W.xPC);
+		S9xPackStatus();
+		PushB(Registers.P.B.l);
+		OpenBus = Registers.P.B.l;
 		ClearDecimal();
 		SetIRQ();
 
-		addr = S9xGetWord(0xFFE6);
+		addr = S9xGetWord(0xFFEE);
 	}
 	else
 	{
-		PushWE(Registers.PCw + 1);
+		PushWE(Registers.PC.W.xPC);
 		S9xPackStatus();
-		PushBE(Registers.PL);
-		OpenBus = Registers.PL;
+		PushBE(Registers.P.B.l);
+		OpenBus = Registers.P.B.l;
 		ClearDecimal();
 		SetIRQ();
 
 		addr = S9xGetWord(0xFFFE);
 	}
+	OpenBus = addr >> 8;
+	S9xSetPCBase(addr);
+}
+
+/* NMI ********************************************************************* */
+
+void S9xOpcode_NMI()
+{
+	// IRQ and NMI do an opcode fetch as their first "IO" cycle.
+	AddCycles(CPU.MemSpeed + ONE_CYCLE);
+
+	uint16_t addr;
+	if (!CheckEmulation())
+	{
+		PushB(Registers.PC.B.xPB);
+		PushW(Registers.PC.W.xPC);
+		S9xPackStatus();
+		PushB(Registers.P.B.l);
+		OpenBus = Registers.P.B.l;
+		ClearDecimal();
+		SetIRQ();
+
+		addr = S9xGetWord(0xFFEA);
+	}
+	else
+	{
+		PushWE(Registers.PC.W.xPC);
+		S9xPackStatus();
+		PushBE(Registers.P.B.l);
+		OpenBus = Registers.P.B.l;
+		ClearDecimal();
+		SetIRQ();
+
+		addr = S9xGetWord(0xFFFA);
+	}
+	OpenBus = addr >> 8;
+	S9xSetPCBase(addr);
+}
+
+/* COP ********************************************************************* */
+
+static void Op02()
+{
+	AddCycles(CPU.MemSpeed);
+
+	if (!CheckEmulation())
+	{
+		PushB(Registers.PC.B.xPB);
+		PushW(Registers.PC.W.xPC + 1);
+		S9xPackStatus();
+		PushB(Registers.P.B.l);
+	}
+	else
+	{
+		PushWE(Registers.PC.W.xPC + 1);
+		S9xPackStatus();
+		PushBE(Registers.P.B.l);
+	}
+	OpenBus = Registers.P.B.l;
+	ClearDecimal();
+	SetIRQ();
+
+	uint16_t addr = S9xGetWord(0xFFF4);
 
 	S9xSetPCBase(addr);
 	OpenBus = addr >> 8;
 }
 
-/* IRQ ********************************************************************* */
-
-void S9xOpcode_IRQ()
-{
-#ifdef DEBUGGER
-	if (CPU.Flags & TRACE_FLAG)
-	#ifdef SA1_OPCODES
-		S9xTraceMessage("*** SA1 IRQ");
-	#else
-		S9xTraceMessage("*** IRQ");
-	#endif
-#endif
-
-	// IRQ and NMI do an opcode fetch as their first "IO" cycle.
-	AddCycles(CPU.MemSpeed + ONE_CYCLE);
-
-	if (!CheckEmulation())
-	{
-		PushB(Registers.PB);
-		PushW(Registers.PCw);
-		S9xPackStatus();
-		PushB(Registers.PL);
-		OpenBus = Registers.PL;
-		ClearDecimal();
-		SetIRQ();
-
-	#ifdef SA1_OPCODES
-		OpenBus = Memory.FillRAM[0x2208];
-		AddCycles(2 * SLOW_ONE_CYCLE);
-		S9xSA1SetPCBase(Memory.FillRAM[0x2207] | (Memory.FillRAM[0x2208] << 8));
-	#else
-		if (Settings.SA1 && (Memory.FillRAM[0x2209] & 0x40))
-		{
-			OpenBus = Memory.FillRAM[0x220f];
-			AddCycles(2 * SLOW_ONE_CYCLE);
-			S9xSetPCBase(Memory.FillRAM[0x220e] | (Memory.FillRAM[0x220f] << 8));
-		}
-		else
-		{
-			uint16_t	addr = S9xGetWord(0xFFEE);
-			OpenBus = addr >> 8;
-			S9xSetPCBase(addr);
-		}
-	#endif
-	}
-	else
-	{
-		PushWE(Registers.PCw);
-		S9xPackStatus();
-		PushBE(Registers.PL);
-		OpenBus = Registers.PL;
-		ClearDecimal();
-		SetIRQ();
-
-	#ifdef SA1_OPCODES
-		OpenBus = Memory.FillRAM[0x2208];
-		AddCycles(2 * SLOW_ONE_CYCLE);
-		S9xSA1SetPCBase(Memory.FillRAM[0x2207] | (Memory.FillRAM[0x2208] << 8));
-	#else
-		if (Settings.SA1 && (Memory.FillRAM[0x2209] & 0x40))
-		{
-			OpenBus = Memory.FillRAM[0x220f];
-			AddCycles(2 * SLOW_ONE_CYCLE);
-			S9xSetPCBase(Memory.FillRAM[0x220e] | (Memory.FillRAM[0x220f] << 8));
-		}
-		else
-		{
-			uint16_t	addr = S9xGetWord(0xFFFE);
-			OpenBus = addr >> 8;
-			S9xSetPCBase(addr);
-		}
-	#endif
-	}
-}
-
-/* NMI ********************************************************************* */
-
-void S9xOpcode_NMI()
-{
-#ifdef DEBUGGER
-	if (CPU.Flags & TRACE_FLAG)
-	#ifdef SA1_OPCODES
-		S9xTraceMessage("*** SA1 NMI");
-	#else
-		S9xTraceMessage("*** NMI");
-	#endif
-#endif
-
-	// IRQ and NMI do an opcode fetch as their first "IO" cycle.
-	AddCycles(CPU.MemSpeed + ONE_CYCLE);
-
-	if (!CheckEmulation())
-	{
-		PushB(Registers.PB);
-		PushW(Registers.PCw);
-		S9xPackStatus();
-		PushB(Registers.PL);
-		OpenBus = Registers.PL;
-		ClearDecimal();
-		SetIRQ();
-
-	#ifdef SA1_OPCODES
-		OpenBus = Memory.FillRAM[0x2206];
-		AddCycles(2 * SLOW_ONE_CYCLE);
-		S9xSA1SetPCBase(Memory.FillRAM[0x2205] | (Memory.FillRAM[0x2206] << 8));
-	#else
-		if (Settings.SA1 && (Memory.FillRAM[0x2209] & 0x10))
-		{
-			OpenBus = Memory.FillRAM[0x220d];
-			AddCycles(2 * SLOW_ONE_CYCLE);
-			S9xSetPCBase(Memory.FillRAM[0x220c] | (Memory.FillRAM[0x220d] << 8));
-		}
-		else
-		{
-			uint16_t	addr = S9xGetWord(0xFFEA);
-			OpenBus = addr >> 8;
-			S9xSetPCBase(addr);
-		}
-	#endif
-	}
-	else
-	{
-		PushWE(Registers.PCw);
-		S9xPackStatus();
-		PushBE(Registers.PL);
-		OpenBus = Registers.PL;
-		ClearDecimal();
-		SetIRQ();
-
-	#ifdef SA1_OPCODES
-		OpenBus = Memory.FillRAM[0x2206];
-		AddCycles(2 * SLOW_ONE_CYCLE);
-		S9xSA1SetPCBase(Memory.FillRAM[0x2205] | (Memory.FillRAM[0x2206] << 8));
-	#else
-		if (Settings.SA1 && (Memory.FillRAM[0x2209] & 0x10))
-		{
-			OpenBus = Memory.FillRAM[0x220d];
-			AddCycles(2 * SLOW_ONE_CYCLE);
-			S9xSetPCBase(Memory.FillRAM[0x220c] | (Memory.FillRAM[0x220d] << 8));
-		}
-		else
-		{
-			uint16_t	addr = S9xGetWord(0xFFFA);
-			OpenBus = addr >> 8;
-			S9xSetPCBase(addr);
-		}
-	#endif
-	}
-}
-
-/* COP ********************************************************************* */
-
-static void Op02()
-{
-#ifdef DEBUGGER
-	if (CPU.Flags & TRACE_FLAG)
-		S9xTraceMessage("*** COP");
-#endif
-
-	AddCycles(CPU.MemSpeed);
-
-	uint16_t	addr;
-
-	if (!CheckEmulation())
-	{
-		PushB(Registers.PB);
-		PushW(Registers.PCw + 1);
-		S9xPackStatus();
-		PushB(Registers.PL);
-		OpenBus = Registers.PL;
-		ClearDecimal();
-		SetIRQ();
-
-		addr = S9xGetWord(0xFFE4);
-	}
-	else
-	{
-		PushWE(Registers.PCw + 1);
-		S9xPackStatus();
-		PushBE(Registers.PL);
-		OpenBus = Registers.PL;
-		ClearDecimal();
-		SetIRQ();
-
-		addr = S9xGetWord(0xFFF4);
-	}
-
+/* JML ********************************************************************* */
+
+template<typename F> static inline void JMLWrapper(F f)
+{
+	S9xSetPCBase(f(JUMP));
+}
+
+static void OpDC()
+{
+	JMLWrapper(AbsoluteIndirectLong);
+}
+
+static void OpDCSlow()
+{
+	JMLWrapper(AbsoluteIndirectLongSlow);
+}
+
+static void Op5C()
+{
+	JMLWrapper(AbsoluteLong);
+}
+
+static void Op5CSlow()
+{
+	JMLWrapper(AbsoluteLongSlow);
+}
+
+/* JMP ********************************************************************* */
+
+template<typename F> static inline void JMPWrapper(F f)
+{
+	S9xSetPCBase(ICPU.ShiftedPB + static_cast<uint16_t>(f(JUMP)));
+}
+
+static void Op4C()
+{
+	JMPWrapper(Absolute);
+}
+
+static void Op4CSlow()
+{
+	JMPWrapper(AbsoluteSlow);
+}
+
+static void Op6C()
+{
+	JMPWrapper(AbsoluteIndirect);
+}
+
+static void Op6CSlow()
+{
+	JMPWrapper(AbsoluteIndirectSlow);
+}
+
+static void Op7C()
+{
+	JMPWrapper(AbsoluteIndexedIndirect);
+}
+
+static void Op7CSlow()
+{
+	JMPWrapper(AbsoluteIndexedIndirectSlow);
+}
+
+/* JSL/RTL ***************************************************************** */
+
+template<typename F> static inline void Op22Wrapper(F f, bool cond)
+{
+	uint32_t addr = f(JSR);
+	PushB(Registers.PC.B.xPB);
+	PushW(Registers.PC.W.xPC - 1);
+	if (cond)
+		Registers.S.B.h = 1;
 	S9xSetPCBase(addr);
-	OpenBus = addr >> 8;
-}
-
-/* JML ********************************************************************* */
-
-static void OpDC()
-{
-	S9xSetPCBase(AbsoluteIndirectLong(JUMP));
-}
-
-static void OpDCSlow()
-{
-	S9xSetPCBase(AbsoluteIndirectLongSlow(JUMP));
-}
-
-static void Op5C()
-{
-	S9xSetPCBase(AbsoluteLong(JUMP));
-}
-
-static void Op5CSlow()
-{
-	S9xSetPCBase(AbsoluteLongSlow(JUMP));
-}
-
-/* JMP ********************************************************************* */
-
-static void Op4C()
-{
-	S9xSetPCBase(ICPU.ShiftedPB + ((uint16_t) Absolute(JUMP)));
-}
-
-static void Op4CSlow()
-{
-	S9xSetPCBase(ICPU.ShiftedPB + ((uint16_t) AbsoluteSlow(JUMP)));
-}
-
-static void Op6C()
-{
-	S9xSetPCBase(ICPU.ShiftedPB + ((uint16_t) AbsoluteIndirect(JUMP)));
-}
-
-static void Op6CSlow()
-{
-	S9xSetPCBase(ICPU.ShiftedPB + ((uint16_t) AbsoluteIndirectSlow(JUMP)));
-}
-
-static void Op7C()
-{
-	S9xSetPCBase(ICPU.ShiftedPB + ((uint16_t) AbsoluteIndexedIndirect(JUMP)));
-}
-
-static void Op7CSlow()
-{
-	S9xSetPCBase(ICPU.ShiftedPB + ((uint16_t) AbsoluteIndexedIndirectSlow(JUMP)));
-}
-
-/* JSL/RTL ***************************************************************** */
+}
+
+static void Op22E0()
+{
+	Op22Wrapper(AbsoluteLong, false);
+}
 
 static void Op22E1()
 {
 	// Note: JSL is a new instruction,
 	// and so doesn't respect the emu-mode stack bounds.
-	uint32_t	addr = AbsoluteLong(JSR);
-	PushB(Registers.PB);
-	PushW(Registers.PCw - 1);
-	Registers.SH = 1;
-	S9xSetPCBase(addr);
-}
-
-static void Op22E0()
-{
-	uint32_t	addr = AbsoluteLong(JSR);
-	PushB(Registers.PB);
-	PushW(Registers.PCw - 1);
-	S9xSetPCBase(addr);
+	Op22Wrapper(AbsoluteLong, true);
 }
 
 static void Op22Slow()
 {
-	uint32_t	addr = AbsoluteLongSlow(JSR);
-	PushB(Registers.PB);
-	PushW(Registers.PCw - 1);
-	if (CheckEmulation())
-		Registers.SH = 1;
-	S9xSetPCBase(addr);
+	Op22Wrapper(AbsoluteLongSlow, CheckEmulation());
+}
+
+static inline void Op6BWrapper(bool cond)
+{
+	AddCycles(TWO_CYCLES);
+	PullW(Registers.PC.W.xPC);
+	PullB(Registers.PC.B.xPB);
+	if (cond)
+		Registers.S.B.h = 1;
+	++Registers.PC.W.xPC;
+	S9xSetPCBase(Registers.PC.xPBPC);
+}
+
+static void Op6BE0()
+{
+	Op6BWrapper(false);
 }
 
 static void Op6BE1()
 {
 	// Note: RTL is a new instruction,
 	// and so doesn't respect the emu-mode stack bounds.
-	AddCycles(TWO_CYCLES);
-	PullW(Registers.PCw);
-	PullB(Registers.PB);
-	Registers.SH = 1;
-	Registers.PCw++;
-	S9xSetPCBase(Registers.PBPC);
-}
-
-static void Op6BE0()
-{
-	AddCycles(TWO_CYCLES);
-	PullW(Registers.PCw);
-	PullB(Registers.PB);
-	Registers.PCw++;
-	S9xSetPCBase(Registers.PBPC);
+	Op6BWrapper(true);
 }
 
 static void Op6BSlow()
 {
-	AddCycles(TWO_CYCLES);
-	PullW(Registers.PCw);
-	PullB(Registers.PB);
+	Op6BWrapper(CheckEmulation());
+}
+
+/* JSR/RTS ***************************************************************** */
+
+template<typename F> static inline void Op20Wrapper(F f)
+{
+	uint16_t addr = Absolute(JSR);
+	AddCycles(ONE_CYCLE);
+	f(Registers.PC.W.xPC - 1);
+	S9xSetPCBase(ICPU.ShiftedPB + addr);
+}
+
+static inline void Op20E1()
+{
+	Op20Wrapper(PushWE);
+}
+
+static void Op20E0()
+{
+	Op20Wrapper(PushW);
+}
+
+static inline void Op20Slow()
+{
 	if (CheckEmulation())
-		Registers.SH = 1;
-	Registers.PCw++;
-	S9xSetPCBase(Registers.PBPC);
-}
-
-/* JSR/RTS ***************************************************************** */
-
-static void Op20E1()
-{
-	uint16_t	addr = Absolute(JSR);
-	AddCycles(ONE_CYCLE);
-	PushWE(Registers.PCw - 1);
+		Op20E1();
+	else
+		Op20E0();
+}
+
+template<typename F> static inline void OpFCWrapper(F f, bool cond)
+{
+	uint16_t addr = f(JSR);
+	PushW(Registers.PC.W.xPC - 1);
+	if (cond)
+		Registers.S.B.h = 1;
 	S9xSetPCBase(ICPU.ShiftedPB + addr);
 }
 
-static void Op20E0()
-{
-	uint16_t	addr = Absolute(JSR);
-	AddCycles(ONE_CYCLE);
-	PushW(Registers.PCw - 1);
-	S9xSetPCBase(ICPU.ShiftedPB + addr);
-}
-
-static void Op20Slow()
-{
-	uint16_t	addr = AbsoluteSlow(JSR);
-
-	AddCycles(ONE_CYCLE);
-
-	if (CheckEmulation())
-	{
-		PushWE(Registers.PCw - 1);
-	}
-	else
-	{
-		PushW(Registers.PCw - 1);
-	}
-
-	S9xSetPCBase(ICPU.ShiftedPB + addr);
+static void OpFCE0()
+{
+	OpFCWrapper(AbsoluteIndexedIndirect, false);
 }
 
 static void OpFCE1()
 {
 	// Note: JSR (a,X) is a new instruction,
 	// and so doesn't respect the emu-mode stack bounds.
-	uint16_t	addr = AbsoluteIndexedIndirect(JSR);
-	PushW(Registers.PCw - 1);
-	Registers.SH = 1;
-	S9xSetPCBase(ICPU.ShiftedPB + addr);
-}
-
-static void OpFCE0()
-{
-	uint16_t	addr = AbsoluteIndexedIndirect(JSR);
-	PushW(Registers.PCw - 1);
-	S9xSetPCBase(ICPU.ShiftedPB + addr);
+	OpFCWrapper(AbsoluteIndexedIndirect, true);
 }
 
 static void OpFCSlow()
 {
-	uint16_t	addr = AbsoluteIndexedIndirectSlow(JSR);
-	PushW(Registers.PCw - 1);
+	OpFCWrapper(AbsoluteIndexedIndirectSlow, CheckEmulation());
+}
+
+template<typename F> static inline void Op60Wrapper(F f)
+{
+	AddCycles(TWO_CYCLES);
+	f(Registers.PC.W.xPC);
+	AddCycles(ONE_CYCLE);
+	++Registers.PC.W.xPC;
+	S9xSetPCBase(Registers.PC.xPBPC);
+}
+
+static inline void Op60E1()
+{
+	Op60Wrapper(PullWE);
+}
+
+static inline void Op60E0()
+{
+	Op60Wrapper(PullW);
+}
+
+static void Op60Slow()
+{
 	if (CheckEmulation())
-		Registers.SH = 1;
-	S9xSetPCBase(ICPU.ShiftedPB + addr);
-}
-
-static void Op60E1()
-{
+		Op60E1();
+	else
+		Op60E0();
+}
+
+/* MVN/MVP ***************************************************************** */
+
+template<typename F> static inline void MVWrapper(F f, bool cond, int inc, bool setOpenBusOnFirstF = false)
+{
+	uint32_t SrcBank;
+
+	Registers.DB = f(NONE);
+	if (setOpenBusOnFirstF)
+		OpenBus = Registers.DB;
+	ICPU.ShiftedDB = Registers.DB << 16;
+	OpenBus = SrcBank = f(NONE);
+
+	S9xSetByte(OpenBus = S9xGetByte((SrcBank << 16) + Registers.X.W), ICPU.ShiftedDB + Registers.Y.W);
+
+	if (cond)
+	{
+		Registers.X.B.l += inc;
+		Registers.Y.B.l += inc;
+	}
+	else
+	{
+		Registers.X.W += inc;
+		Registers.Y.W += inc;
+	}
+
+	--Registers.A.W;
+	if (Registers.A.W != 0xffff)
+		Registers.PC.W.xPC -= 3;
+
 	AddCycles(TWO_CYCLES);
-	PullWE(Registers.PCw);
-	AddCycles(ONE_CYCLE);
-	Registers.PCw++;
-	S9xSetPCBase(Registers.PBPC);
-}
-
-static void Op60E0()
-{
-	AddCycles(TWO_CYCLES);
-	PullW(Registers.PCw);
-	AddCycles(ONE_CYCLE);
-	Registers.PCw++;
-	S9xSetPCBase(Registers.PBPC);
-}
-
-static void Op60Slow()
-{
-	AddCycles(TWO_CYCLES);
-
-	if (CheckEmulation())
-	{
-		PullWE(Registers.PCw);
-	}
-	else
-	{
-		PullW(Registers.PCw);
-	}
-
-	AddCycles(ONE_CYCLE);
-	Registers.PCw++;
-	S9xSetPCBase(Registers.PBPC);
-}
-
-/* MVN/MVP ***************************************************************** */
+}
 
 static void Op54X1()
 {
-	uint32_t	SrcBank;
-
-	Registers.DB = Immediate8(NONE);
-	ICPU.ShiftedDB = Registers.DB << 16;
-	OpenBus = SrcBank = Immediate8(NONE);
-
-	S9xSetByte(OpenBus = S9xGetByte((SrcBank << 16) + Registers.X.W), ICPU.ShiftedDB + Registers.Y.W);
-
-	Registers.XL++;
-	Registers.YL++;
-	Registers.A.W--;
-	if (Registers.A.W != 0xffff)
-		Registers.PCw -= 3;
-
-	AddCycles(TWO_CYCLES);
+	MVWrapper(Immediate8, true, 1);
 }
 
 static void Op54X0()
 {
-	uint32_t	SrcBank;
-
-	Registers.DB = Immediate8(NONE);
-	ICPU.ShiftedDB = Registers.DB << 16;
-	OpenBus = SrcBank = Immediate8(NONE);
-
-	S9xSetByte(OpenBus = S9xGetByte((SrcBank << 16) + Registers.X.W), ICPU.ShiftedDB + Registers.Y.W);
-
-	Registers.X.W++;
-	Registers.Y.W++;
-	Registers.A.W--;
-	if (Registers.A.W != 0xffff)
-		Registers.PCw -= 3;
-
-	AddCycles(TWO_CYCLES);
+	MVWrapper(Immediate8, false, 1);
 }
 
 static void Op54Slow()
 {
-	uint32_t	SrcBank;
-
-	OpenBus = Registers.DB = Immediate8Slow(NONE);
-	ICPU.ShiftedDB = Registers.DB << 16;
-	OpenBus = SrcBank = Immediate8Slow(NONE);
-
-	S9xSetByte(OpenBus = S9xGetByte((SrcBank << 16) + Registers.X.W), ICPU.ShiftedDB + Registers.Y.W);
-
-	if (CheckIndex())
-	{
-		Registers.XL++;
-		Registers.YL++;
-	}
-	else
-	{
-		Registers.X.W++;
-		Registers.Y.W++;
-	}
-
-	Registers.A.W--;
-	if (Registers.A.W != 0xffff)
-		Registers.PCw -= 3;
-
-	AddCycles(TWO_CYCLES);
+	MVWrapper(Immediate8Slow, CheckIndex(), 1, true);
 }
 
 static void Op44X1()
 {
-	uint32_t	SrcBank;
-
-	Registers.DB = Immediate8(NONE);
-	ICPU.ShiftedDB = Registers.DB << 16;
-	OpenBus = SrcBank = Immediate8(NONE);
-
-	S9xSetByte(OpenBus = S9xGetByte((SrcBank << 16) + Registers.X.W), ICPU.ShiftedDB + Registers.Y.W);
-
-	Registers.XL--;
-	Registers.YL--;
-	Registers.A.W--;
-	if (Registers.A.W != 0xffff)
-		Registers.PCw -= 3;
-
-	AddCycles(TWO_CYCLES);
+	MVWrapper(Immediate8, true, -1);
 }
 
 static void Op44X0()
 {
-	uint32_t	SrcBank;
-
-	Registers.DB = Immediate8(NONE);
-	ICPU.ShiftedDB = Registers.DB << 16;
-	OpenBus = SrcBank = Immediate8(NONE);
-
-	S9xSetByte(OpenBus = S9xGetByte((SrcBank << 16) + Registers.X.W), ICPU.ShiftedDB + Registers.Y.W);
-
-	Registers.X.W--;
-	Registers.Y.W--;
-	Registers.A.W--;
-	if (Registers.A.W != 0xffff)
-		Registers.PCw -= 3;
-
-	AddCycles(TWO_CYCLES);
+	MVWrapper(Immediate8, false, -1);
 }
 
 static void Op44Slow()
 {
-	uint32_t	SrcBank;
-
-	OpenBus = Registers.DB = Immediate8Slow(NONE);
-	ICPU.ShiftedDB = Registers.DB << 16;
-	OpenBus = SrcBank = Immediate8Slow(NONE);
-
-	S9xSetByte(OpenBus = S9xGetByte((SrcBank << 16) + Registers.X.W), ICPU.ShiftedDB + Registers.Y.W);
-
-	if (CheckIndex())
-	{
-		Registers.XL--;
-		Registers.YL--;
-	}
-	else
-	{
-		Registers.X.W--;
-		Registers.Y.W--;
-	}
-
-	Registers.A.W--;
-	if (Registers.A.W != 0xffff)
-		Registers.PCw -= 3;
-
-	AddCycles(TWO_CYCLES);
+	MVWrapper(Immediate8Slow, CheckIndex(), -1, true);
 }
 
 /* REP/SEP ***************************************************************** */
 
-static void OpC2()
-{
-	uint8_t	Work8 = ~Immediate8(READ);
-	Registers.PL &= Work8;
+template<typename F> static inline void OpC2Wrapper(F f)
+{
+	uint8_t Work8 = ~f(READ);
+	Registers.P.B.l &= Work8;
 	ICPU._Carry &= Work8;
-	ICPU._Overflow &= (Work8 >> 6);
+	ICPU._Overflow &= Work8 >> 6;
 	ICPU._Negative &= Work8;
 	ICPU._Zero |= ~Work8 & Zero;
 
 	AddCycles(ONE_CYCLE);
 
 	if (CheckEmulation())
-	{
 		SetFlags(MemoryFlag | IndexFlag);
-	#ifdef DEBUGGER
-		missing.emulate6502 = 1;
-	#endif
-	}
 
 	if (CheckIndex())
-	{
-		Registers.XH = 0;
-		Registers.YH = 0;
-	}
+		Registers.X.B.h = Registers.Y.B.h = 0;
 
 	S9xFixCycles();
-	CHECK_FOR_IRQ();
+}
+
+static void OpC2()
+{
+	OpC2Wrapper(Immediate8);
 }
 
 static void OpC2Slow()
 {
-	uint8_t	Work8 = ~Immediate8Slow(READ);
-	Registers.PL &= Work8;
-	ICPU._Carry &= Work8;
-	ICPU._Overflow &= (Work8 >> 6);
-	ICPU._Negative &= Work8;
-	ICPU._Zero |= ~Work8 & Zero;
-
-	AddCycles(ONE_CYCLE);
-
-	if (CheckEmulation())
-	{
-		SetFlags(MemoryFlag | IndexFlag);
-	#ifdef DEBUGGER
-		missing.emulate6502 = 1;
-	#endif
-	}
-
-	if (CheckIndex())
-	{
-		Registers.XH = 0;
-		Registers.YH = 0;
-	}
-
-	S9xFixCycles();
-	CHECK_FOR_IRQ();
-}
-
-static void OpE2()
-{
-	uint8_t	Work8 = Immediate8(READ);
-	Registers.PL |= Work8;
+	OpC2Wrapper(Immediate8Slow);
+}
+
+template<typename F> static inline void OpE2Wrapper(F f)
+{
+	uint8_t Work8 = f(READ);
+	Registers.P.B.l |= Work8;
 	ICPU._Carry |= Work8 & 1;
 	ICPU._Overflow |= (Work8 >> 6) & 1;
 	ICPU._Negative |= Work8;
@@ -3359,59 +2778,30 @@
 	AddCycles(ONE_CYCLE);
 
 	if (CheckEmulation())
-	{
 		SetFlags(MemoryFlag | IndexFlag);
-	#ifdef DEBUGGER
-		missing.emulate6502 = 1;
-	#endif
-	}
 
 	if (CheckIndex())
-	{
-		Registers.XH = 0;
-		Registers.YH = 0;
-	}
+		Registers.X.B.h = Registers.Y.B.h = 0;
 
 	S9xFixCycles();
 }
 
+static void OpE2()
+{
+	OpE2Wrapper(Immediate8);
+}
+
 static void OpE2Slow()
 {
-	uint8_t	Work8 = Immediate8Slow(READ);
-	Registers.PL |= Work8;
-	ICPU._Carry |= Work8 & 1;
-	ICPU._Overflow |= (Work8 >> 6) & 1;
-	ICPU._Negative |= Work8;
-	if (Work8 & Zero)
-		ICPU._Zero = 0;
-
-	AddCycles(ONE_CYCLE);
-
-	if (CheckEmulation())
-	{
-		SetFlags(MemoryFlag | IndexFlag);
-	#ifdef DEBUGGER
-		missing.emulate6502 = 1;
-	#endif
-	}
-
-	if (CheckIndex())
-	{
-		Registers.XH = 0;
-		Registers.YH = 0;
-	}
-
-	S9xFixCycles();
+	OpE2Wrapper(Immediate8Slow);
 }
 
 /* XBA ********************************************************************* */
 
 static void OpEB()
 {
-	uint8_t	Work8 = Registers.AL;
-	Registers.AL = Registers.AH;
-	Registers.AH = Work8;
-	SetZN(Registers.AL);
+	std::swap(Registers.A.B.l, Registers.A.B.h);
+	SetZN(Registers.A.B.l);
 	AddCycles(TWO_CYCLES);
 }
 
@@ -3423,35 +2813,28 @@
 
 	if (!CheckEmulation())
 	{
-		PullB(Registers.PL);
+		PullB(Registers.P.B.l);
 		S9xUnpackStatus();
-		PullW(Registers.PCw);
-		PullB(Registers.PB);
-		OpenBus = Registers.PB;
-		ICPU.ShiftedPB = Registers.PB << 16;
+		PullW(Registers.PC.W.xPC);
+		PullB(Registers.PC.B.xPB);
+		OpenBus = Registers.PC.B.xPB;
+		ICPU.ShiftedPB = Registers.PC.B.xPB << 16;
 	}
 	else
 	{
-		PullBE(Registers.PL);
+		PullBE(Registers.P.B.l);
 		S9xUnpackStatus();
-		PullWE(Registers.PCw);
-		OpenBus = Registers.PCh;
+		PullWE(Registers.PC.W.xPC);
+		OpenBus = Registers.PC.B.xPCh;
 		SetFlags(MemoryFlag | IndexFlag);
-	#ifdef DEBUGGER
-		missing.emulate6502 = 1;
-	#endif
 	}
 
-	S9xSetPCBase(Registers.PBPC);
+	S9xSetPCBase(Registers.PC.xPBPC);
 
 	if (CheckIndex())
-	{
-		Registers.XH = 0;
-		Registers.YH = 0;
-	}
+		Registers.X.B.h = Registers.Y.B.h = 0;
 
 	S9xFixCycles();
-	CHECK_FOR_IRQ();
 }
 
 /* STP/WAI ***************************************************************** */
@@ -3459,92 +2842,24 @@
 // WAI
 static void OpCB()
 {
-#ifdef SA1_OPCODES
-	SA1.WaitingForInterrupt = true;
-	Registers.PCw--;
+	CPU.WaitingForInterrupt = true;
+	--Registers.PC.W.xPC;
 	AddCycles(TWO_CYCLES);
-#else
-	CPU.WaitingForInterrupt = true;
-	Registers.PCw--;
-	AddCycles(TWO_CYCLES);
-#endif
 }
 
 // STP
 static void OpDB()
 {
-	Registers.PCw--;
+	--Registers.PC.W.xPC;
 	CPU.Flags |= DEBUG_MODE_FLAG | HALTED_FLAG;
 }
 
 /* WDM (Reserved S9xOpcode) ************************************************ */
 
-#ifdef DEBUGGER
-extern FILE	*trace, *trace2;
-#endif
-
 static void Op42()
 {
-#ifdef DEBUGGER
-	uint8_t	byte = (uint8_t) S9xGetWord(Registers.PBPC);
-#else
-	S9xGetWord(Registers.PBPC);
-#endif
-	Registers.PCw++;
-
-#ifdef DEBUGGER
-	// Hey, let's use this to trigger debug modes.
-	switch (byte)
-	{
-		case 0xdb: // "STP" = Enter debug mode
-			CPU.Flags |= DEBUG_MODE_FLAG;
-			break;
-
-	#ifndef SA1_OPCODES
-		case 0xe2: // "SEP" = Trace on
-			if (!(CPU.Flags & TRACE_FLAG))
-			{
-				char	buf[25];
-				CPU.Flags |= TRACE_FLAG;
-				snprintf(buf, 25, "WDM trace on at $%02X:%04X", Registers.PB, Registers.PCw);
-				S9xMessage(S9X_DEBUG, S9X_DEBUG_OUTPUT, buf);
-				if (trace != NULL)
-					fclose(trace);
-				ENSURE_TRACE_OPEN(trace, "WDMtrace.log", "ab")
-			}
-
-			break;
-
-		case 0xc2: // "REP" = Trace off
-			if (CPU.Flags & TRACE_FLAG)
-			{
-				char	buf[26];
-				CPU.Flags &= ~TRACE_FLAG;
-				snprintf(buf, 26, "WDM trace off at $%02X:%04X", Registers.PB, Registers.PCw);
-				S9xMessage(S9X_DEBUG, S9X_DEBUG_OUTPUT, buf);
-				if (trace != NULL)
-					fclose(trace);
-				trace = NULL;
-			}
-
-			break;
-	#endif
-
-		case 0x42: // "WDM" = Snapshot
-			char	filename[PATH_MAX + 1], drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], def[PATH_MAX + 1], ext[_MAX_EXT + 1];
-
-			_splitpath(Memory.ROMFilename, drive, dir, def, ext);
-			snprintf(filename, PATH_MAX, "%s%s%s-%06X.wdm", S9xGetDirectory(SNAPSHOT_DIR), SLASH_STR, def, Registers.PBPC & 0xffffff);
-			sprintf(def, "WDM Snapshot at $%02X:%04X: %s", Registers.PB, Registers.PCw, filename);
-			S9xMessage(S9X_DEBUG, S9X_DEBUG_OUTPUT, def);
-			S9xFreezeGame(filename);
-
-			break;
-
-		default:
-			break;
-	}
-#endif
+	S9xGetWord(Registers.PC.xPBPC);
+	++Registers.PC.W.xPC;
 }
 
 /* CPU-S9xOpcodes Definitions ************************************************/

--- a/src/in_snsf/snes9x/cpuops.h
+++ b/src/in_snsf/snes9x/cpuops.h
@@ -182,10 +182,5 @@
 void S9xOpcode_NMI();
 void S9xOpcode_IRQ();
 
-#ifndef SA1_OPCODES
-#define CHECK_FOR_IRQ() {} // if (CPU.IRQLine) S9xOpcode_IRQ(); }
-#else
-#define CHECK_FOR_IRQ()	{}
-#endif
 #endif
 

--- a/src/in_snsf/snes9x/dma.cpp
+++ b/src/in_snsf/snes9x/dma.cpp
@@ -179,26 +179,15 @@
 #include "memmap.h"
 #include "dma.h"
 #include "apu/apu.h"
-//#include "sdd1emu.h"
-//#include "spc7110emu.h"
-#ifdef DEBUGGER
-#include "missing.h"
-#endif
-
-//#define ADD_CYCLES(n)	{ CPU.PrevCycles = CPU.Cycles; CPU.Cycles += (n); S9xCheckInterrupts(); }
+
 static inline void ADD_CYCLES(int32_t n) { CPU.PrevCycles = CPU.Cycles; CPU.Cycles += n; S9xCheckInterrupts(); }
 
-extern uint8_t	*HDMAMemPointers[8];
-extern int		HDMA_ModeByteCounts[8];
-//extern SPC7110	s7emu;
-
-static uint8_t	sdd1_decode_buffer[0x10000];
-
-//static inline bool addCyclesInDMA (uint8_t);
-//static inline bool HDMAReadLineCount (int);
-
-
-static inline bool addCyclesInDMA (uint8_t dma_channel)
+extern uint8_t *HDMAMemPointers[8];
+extern int HDMA_ModeByteCounts[8];
+
+static uint8_t sdd1_decode_buffer[0x10000];
+
+static inline bool addCyclesInDMA(uint8_t dma_channel)
 {
 	// Add 8 cycles per byte, sync APU, and do HC related events.
 	// If HDMA was done in S9xDoHEventProcessing(), check if it used the same channel as DMA.
@@ -209,9 +198,6 @@
 	if (CPU.HDMARanInDMA & (1 << dma_channel))
 	{
 		CPU.HDMARanInDMA = 0;
-	#ifdef DEBUGGER
-		printf("HDMA and DMA use the same channel %d!\n", dma_channel);
-	#endif
 		// If HDMA triggers in the middle of DMA transfer and it uses the same channel,
 		// it kills the DMA transfer immediately. $43x2 and $43x5 stop updating.
 		return false;
@@ -221,13 +207,13 @@
 	return true;
 }
 
-bool S9xDoDMA (uint8_t Channel)
+bool S9xDoDMA(uint8_t Channel)
 {
 	CPU.InDMA = true;
-    CPU.InDMAorHDMA = true;
+	CPU.InDMAorHDMA = true;
 	CPU.CurrentDMAorHDMAChannel = Channel;
 
-    SDMA	*d = &DMA[Channel];
+	SDMA *d = &DMA[Channel];
 
 	// Check invalid DMA first
 	if ((d->ABank == 0x7E || d->ABank == 0x7F) && d->BAddress == 0x80 && !d->ReverseTransfer)
@@ -242,9 +228,9 @@
 		// not being able to read and write itself at the same time
 		// And no, PPU.WRAM should not be updated.
 
-		int32_t	c = d->TransferBytes;
+		int32_t c = d->DMACount_Or_HDMAIndirectAddress;
 		// Writing $0000 to $43x5 actually results in a transfer of $10000 bytes, not 0.
-		if (c == 0)
+		if (!c)
 			c = 0x10000;
 
 		// 8 cycles per channel
@@ -252,9 +238,9 @@
 		// 8 cycles per byte
 		while (c)
 		{
-			d->TransferBytes--;
-			d->AAddress++;
-			c--;
+			--d->DMACount_Or_HDMAIndirectAddress;
+			++d->AAddress;
+			--c;
 			if (!addCyclesInDMA(Channel))
 			{
 				CPU.InDMA = false;
@@ -264,14 +250,6 @@
 			}
 		}
 
-	#ifdef DEBUGGER
-		if (Settings.TraceDMA)
-		{
-			sprintf(String, "DMA[%d]: WRAM Bank:%02X->$2180", Channel, d->ABank);
-			S9xMessage(S9X_TRACE, S9X_DMA_TRACE, String);
-		}
-	#endif
-
 		CPU.InDMA = false;
 		CPU.InDMAorHDMA = false;
 		CPU.CurrentDMAorHDMAChannel = -1;
@@ -279,26 +257,18 @@
 	}
 
 	// Prepare for accessing $2118-2119
-	/*switch (d->BAddress)
-	{
-		case 0x18:
-		case 0x19:
-			if (IPPU.RenderThisFrame)
-				FLUSH_REDRAW();
-			break;
-	}*/
-
-	int32_t	inc = d->AAddressFixed ? 0 : (!d->AAddressDecrement ? 1 : -1);
-	int32_t	count = d->TransferBytes;
+
+	int32_t inc = d->AAddressFixed ? 0 : (!d->AAddressDecrement ? 1 : -1);
+	int32_t count = d->DMACount_Or_HDMAIndirectAddress;
 	// Writing $0000 to $43x5 actually results in a transfer of $10000 bytes, not 0.
-	if (count == 0)
+	if (!count)
 		count = 0x10000;
 
 	// Prepare for custom chip DMA
 
 	// S-DD1
 
-	uint8_t	*in_sdd1_dma = NULL;
+	uint8_t *in_sdd1_dma = nullptr;
 
 	if (Settings.SDD1)
 	{
@@ -309,19 +279,9 @@
 			// Hacky support for pre-decompressed S-DD1 data
 			inc = !d->AAddressDecrement ? 1 : -1;
 
-			uint8_t	*in_ptr = S9xGetBasePointer(((d->ABank << 16) | d->AAddress));
+			uint8_t *in_ptr = S9xGetBasePointer((d->ABank << 16) | d->AAddress);
 			if (in_ptr)
-			{
 				in_ptr += d->AAddress;
-				//SDD1_decompress(sdd1_decode_buffer, in_ptr, d->TransferBytes);
-			}
-		#ifdef DEBUGGER
-			else
-			{
-				sprintf(String, "S-DD1: DMA from non-block address $%02X:%04X", d->ABank, d->AAddress);
-				S9xMessage(S9X_WARNING, S9X_DMA_TRACE, String);
-			}
-		#endif
 
 			in_sdd1_dma = sdd1_decode_buffer;
 		}
@@ -329,242 +289,50 @@
 		Memory.FillRAM[0x4801] = 0;
 	}
 
-	// SPC7110
-
-	//uint8_t	*spc7110_dma = NULL;
-
-	/*if (Settings.SPC7110)
-	{
-		if (d->AAddress == 0x4800 || d->ABank == 0x50)
-		{
-			spc7110_dma = new uint8_t[d->TransferBytes];
-			for (int i = 0; i < d->TransferBytes; i++)
-				spc7110_dma[i] = s7emu.decomp.read();
-
-			int32_t	icount = s7emu.r4809 | (s7emu.r480a << 8);
-			icount -= d->TransferBytes;
-			s7emu.r4809 =  icount & 0x00ff;
-			s7emu.r480a = (icount & 0xff00) >> 8;
-
-			inc = 1;
-			d->AAddress -= count;
-		}
-	}*/
-
-	// SA-1
-
-	//bool	in_sa1_dma = false;
-
-	/*if (Settings.SA1)
-	{
-		if (SA1.in_char_dma && d->BAddress == 0x18 && (d->ABank & 0xf0) == 0x40)
-		{
-			// Perform packed bitmap to PPU character format conversion on the data
-			// before transmitting it to V-RAM via-DMA.
-			int32_t	num_chars = 1 << ((Memory.FillRAM[0x2231] >> 2) & 7);
-			int32_t	depth = (Memory.FillRAM[0x2231] & 3) == 0 ? 8 : (Memory.FillRAM[0x2231] & 3) == 1 ? 4 : 2;
-			int32_t	bytes_per_char = 8 * depth;
-			int32_t	bytes_per_line = depth * num_chars;
-			int32_t	char_line_bytes = bytes_per_char * num_chars;
-			uint32_t	addr = (d->AAddress / char_line_bytes) * char_line_bytes;
-
-			uint8_t	*base = S9xGetBasePointer((d->ABank << 16) + addr);
-			if (!base)
-			{
-				sprintf(String, "SA-1: DMA from non-block address $%02X:%04X", d->ABank, addr);
-				S9xMessage(S9X_WARNING, S9X_DMA_TRACE, String);
-				base = Memory.ROM;
-			}
-
-			base += addr;
-
-			uint8_t	*buffer = &Memory.ROM[CMemory::MAX_ROM_SIZE - 0x10000];
-			uint8_t	*p = buffer;
-			uint32_t	inc_sa1 = char_line_bytes - (d->AAddress % char_line_bytes);
-			uint32_t	char_count = inc_sa1 / bytes_per_char;
-
-			in_sa1_dma = true;
-
-		#if 0
-			printf("SA-1 DMA: %08x,", base);
-			printf("depth = %d, count = %d, bytes_per_char = %d, bytes_per_line = %d, num_chars = %d, char_line_bytes = %d\n",
-				depth, count, bytes_per_char, bytes_per_line, num_chars, char_line_bytes);
-		#endif
-
-			switch (depth)
-			{
-				case 2:
-					for (int32_t i = 0; i < count; i += inc_sa1, base += char_line_bytes, inc_sa1 = char_line_bytes, char_count = num_chars)
-					{
-						uint8_t	*line = base + (num_chars - char_count) * 2;
-						for (uint32_t j = 0; j < char_count && p - buffer < count; j++, line += 2)
-						{
-							uint8_t	*q = line;
-							for (int32_t l = 0; l < 8; l++, q += bytes_per_line)
-							{
-								for (int32_t b = 0; b < 2; b++)
-								{
-									uint8_t	r = *(q + b);
-									*(p + 0) = (*(p + 0) << 1) | ((r >> 0) & 1);
-									*(p + 1) = (*(p + 1) << 1) | ((r >> 1) & 1);
-									*(p + 0) = (*(p + 0) << 1) | ((r >> 2) & 1);
-									*(p + 1) = (*(p + 1) << 1) | ((r >> 3) & 1);
-									*(p + 0) = (*(p + 0) << 1) | ((r >> 4) & 1);
-									*(p + 1) = (*(p + 1) << 1) | ((r >> 5) & 1);
-									*(p + 0) = (*(p + 0) << 1) | ((r >> 6) & 1);
-									*(p + 1) = (*(p + 1) << 1) | ((r >> 7) & 1);
-								}
-
-								p += 2;
-							}
-						}
-					}
-
-					break;
-
-				case 4:
-					for (int32_t i = 0; i < count; i += inc_sa1, base += char_line_bytes, inc_sa1 = char_line_bytes, char_count = num_chars)
-					{
-						uint8_t	*line = base + (num_chars - char_count) * 4;
-						for (uint32_t j = 0; j < char_count && p - buffer < count; j++, line += 4)
-						{
-							uint8_t	*q = line;
-							for (int32_t l = 0; l < 8; l++, q += bytes_per_line)
-							{
-								for (int32_t b = 0; b < 4; b++)
-								{
-									uint8_t	r = *(q + b);
-									*(p +  0) = (*(p +  0) << 1) | ((r >> 0) & 1);
-									*(p +  1) = (*(p +  1) << 1) | ((r >> 1) & 1);
-									*(p + 16) = (*(p + 16) << 1) | ((r >> 2) & 1);
-									*(p + 17) = (*(p + 17) << 1) | ((r >> 3) & 1);
-									*(p +  0) = (*(p +  0) << 1) | ((r >> 4) & 1);
-									*(p +  1) = (*(p +  1) << 1) | ((r >> 5) & 1);
-									*(p + 16) = (*(p + 16) << 1) | ((r >> 6) & 1);
-									*(p + 17) = (*(p + 17) << 1) | ((r >> 7) & 1);
-								}
-
-								p += 2;
-							}
-
-							p += 32 - 16;
-						}
-					}
-
-					break;
-
-				case 8:
-					for (int32_t i = 0; i < count; i += inc_sa1, base += char_line_bytes, inc_sa1 = char_line_bytes, char_count = num_chars)
-					{
-						uint8_t	*line = base + (num_chars - char_count) * 8;
-						for (uint32_t j = 0; j < char_count && p - buffer < count; j++, line += 8)
-						{
-							uint8_t	*q = line;
-							for (int32_t l = 0; l < 8; l++, q += bytes_per_line)
-							{
-								for (int32_t b = 0; b < 8; b++)
-								{
-									uint8_t	r = *(q + b);
-									*(p +  0) = (*(p +  0) << 1) | ((r >> 0) & 1);
-									*(p +  1) = (*(p +  1) << 1) | ((r >> 1) & 1);
-									*(p + 16) = (*(p + 16) << 1) | ((r >> 2) & 1);
-									*(p + 17) = (*(p + 17) << 1) | ((r >> 3) & 1);
-									*(p + 32) = (*(p + 32) << 1) | ((r >> 4) & 1);
-									*(p + 33) = (*(p + 33) << 1) | ((r >> 5) & 1);
-									*(p + 48) = (*(p + 48) << 1) | ((r >> 6) & 1);
-									*(p + 49) = (*(p + 49) << 1) | ((r >> 7) & 1);
-								}
-
-								p += 2;
-							}
-
-							p += 64 - 16;
-						}
-					}
-
-					break;
-			}
-		}
-	}*/
-
-#ifdef DEBUGGER
-	if (Settings.TraceDMA)
-	{
-		sprintf(String, "DMA[%d]: %s Mode:%d 0x%02X%04X->0x21%02X Bytes:%d (%s) V:%03d",
-			Channel, d->ReverseTransfer ? "PPU->CPU" : "CPU->PPU", d->TransferMode, d->ABank, d->AAddress, d->BAddress,
-			d->TransferBytes, d->AAddressFixed ? "fixed" : (d->AAddressDecrement ? "dec" : "inc"), CPU.V_Counter);
-
-		if (d->BAddress == 0x18 || d->BAddress == 0x19 || d->BAddress == 0x39 || d->BAddress == 0x3a)
-			sprintf(String, "%s VRAM: %04X (%d,%d) %s", String,
-				PPU.VMA.Address, PPU.VMA.Increment, PPU.VMA.FullGraphicCount, PPU.VMA.High ? "word" : "byte");
-		else
-		if (d->BAddress == 0x22 || d->BAddress == 0x3b)
-			sprintf(String, "%s CGRAM: %02X (%x)", String, PPU.CGADD, PPU.CGFLIP);
-		else
-		if (d->BAddress == 0x04 || d->BAddress == 0x38)
-			sprintf(String, "%s OBJADDR: %04X", String, PPU.OAMAddr);
-
-		S9xMessage(S9X_TRACE, S9X_DMA_TRACE, String);
-	}
-#endif
-
 	// Do Transfer
 
-	uint8_t	Work;
+	uint8_t Work;
 
 	// 8 cycles per channel
 	ADD_CYCLES(SLOW_ONE_CYCLE);
 
 	if (!d->ReverseTransfer)
-    {
+	{
 		// CPU -> PPU
-		int32_t	b = 0;
-		uint16_t	p = d->AAddress;
-		uint8_t	*base = S9xGetBasePointer((d->ABank << 16) + d->AAddress);
-		bool	inWRAM_DMA;
-
-		int32_t	rem = count;
+		int32_t b = 0;
+		uint16_t p = d->AAddress;
+		uint8_t *base = S9xGetBasePointer((d->ABank << 16) + d->AAddress);
+
+		int32_t rem = count;
 		// Transfer per block if d->AAdressFixed is false
 		count = d->AAddressFixed ? rem : (d->AAddressDecrement ? ((p & MEMMAP_MASK) + 1) : (MEMMAP_BLOCK_SIZE - (p & MEMMAP_MASK)));
 
 		// Settings for custom chip DMA
-		/*if (in_sa1_dma)
-		{
-			base = &Memory.ROM[CMemory::MAX_ROM_SIZE - 0x10000];
-			p = 0;
-			count = rem;
-		}
-		else*/
 		if (in_sdd1_dma)
 		{
 			base = in_sdd1_dma;
 			p = 0;
 			count = rem;
 		}
-		/*else
-		if (spc7110_dma)
+
+		bool inWRAM_DMA = !in_sdd1_dma && (d->ABank == 0x7e || d->ABank == 0x7f || (!(d->ABank & 0x40) && d->AAddress < 0x2000));
+
+		// 8 cycles per byte
+		auto UPDATE_COUNTERS = [&]() -> bool
 		{
-			base = spc7110_dma;
-			p = 0;
-			count = rem;
-		}*/
-
-		inWRAM_DMA = ((/*!in_sa1_dma && */!in_sdd1_dma/* && !spc7110_dma*/) &&
-			(d->ABank == 0x7e || d->ABank == 0x7f || (!(d->ABank & 0x40) && d->AAddress < 0x2000)));
-
-		// 8 cycles per byte
-		#define	UPDATE_COUNTERS \
-			d->TransferBytes--; \
-			d->AAddress += inc; \
-			p += inc; \
-			if (!addCyclesInDMA(Channel)) \
-			{ \
-				CPU.InDMA = false; \
-				CPU.InDMAorHDMA = false; \
-				CPU.InWRAMDMAorHDMA = false; \
-				CPU.CurrentDMAorHDMAChannel = -1; \
-				return false; \
+			--d->DMACount_Or_HDMAIndirectAddress;
+			d->AAddress += inc;
+			p += inc;
+			if (!addCyclesInDMA(Channel))
+			{
+				CPU.InDMA = false;
+				CPU.InDMAorHDMA = false;
+				CPU.InWRAMDMAorHDMA = false;
+				CPU.CurrentDMAorHDMAChannel = -1;
+				return false;
 			}
+			return true;
+		};
 
 		while (1)
 		{
@@ -577,17 +345,17 @@
 			if (!base)
 			{
 				// DMA SLOW PATH
-				if (d->TransferMode == 0 || d->TransferMode == 2 || d->TransferMode == 6)
+				if (!d->TransferMode || d->TransferMode == 2 || d->TransferMode == 6)
 				{
 					do
 					{
 						Work = S9xGetByte((d->ABank << 16) + p);
 						S9xSetPPU(Work, 0x2100 + d->BAddress);
-						UPDATE_COUNTERS;
+						if (!UPDATE_COUNTERS())
+							return false;
 					} while (--count > 0);
 				}
-				else
-				if (d->TransferMode == 1 || d->TransferMode == 5)
+				else if (d->TransferMode == 1 || d->TransferMode == 5)
 				{
 					// This is a variation on Duff's Device. It is legal C/C++.
 					switch (b)
@@ -597,14 +365,16 @@
 						{
 							Work = S9xGetByte((d->ABank << 16) + p);
 							S9xSetPPU(Work, 0x2100 + d->BAddress);
-							UPDATE_COUNTERS;
-							count--;
+							if (!UPDATE_COUNTERS())
+								return false;
+							--count;
 
 						case 1:
 							Work = S9xGetByte((d->ABank << 16) + p);
 							S9xSetPPU(Work, 0x2101 + d->BAddress);
-							UPDATE_COUNTERS;
-							count--;
+							if (!UPDATE_COUNTERS())
+								return false;
+							--count;
 						}
 					}
 
@@ -612,14 +382,14 @@
 					{
 						Work = S9xGetByte((d->ABank << 16) + p);
 						S9xSetPPU(Work, 0x2100 + d->BAddress);
-						UPDATE_COUNTERS;
+						if (!UPDATE_COUNTERS())
+							return false;
 						b = 1;
 					}
 					else
 						b = 0;
 				}
-				else
-				if (d->TransferMode == 3 || d->TransferMode == 7)
+				else if (d->TransferMode == 3 || d->TransferMode == 7)
 				{
 					switch (b)
 					{
@@ -628,7 +398,8 @@
 						{
 							Work = S9xGetByte((d->ABank << 16) + p);
 							S9xSetPPU(Work, 0x2100 + d->BAddress);
-							UPDATE_COUNTERS;
+							if (!UPDATE_COUNTERS())
+								return false;
 							if (--count <= 0)
 							{
 								b = 1;
@@ -638,7 +409,8 @@
 						case 1:
 							Work = S9xGetByte((d->ABank << 16) + p);
 							S9xSetPPU(Work, 0x2100 + d->BAddress);
-							UPDATE_COUNTERS;
+							if (!UPDATE_COUNTERS())
+								return false;
 							if (--count <= 0)
 							{
 								b = 2;
@@ -648,7 +420,8 @@
 						case 2:
 							Work = S9xGetByte((d->ABank << 16) + p);
 							S9xSetPPU(Work, 0x2101 + d->BAddress);
-							UPDATE_COUNTERS;
+							if (!UPDATE_COUNTERS())
+								return false;
 							if (--count <= 0)
 							{
 								b = 3;
@@ -658,7 +431,8 @@
 						case 3:
 							Work = S9xGetByte((d->ABank << 16) + p);
 							S9xSetPPU(Work, 0x2101 + d->BAddress);
-							UPDATE_COUNTERS;
+							if (!UPDATE_COUNTERS())
+								return false;
 							if (--count <= 0)
 							{
 								b = 0;
@@ -667,8 +441,7 @@
 						} while (1);
 					}
 				}
-				else
-				if (d->TransferMode == 4)
+				else if (d->TransferMode == 4)
 				{
 					switch (b)
 					{
@@ -677,7 +450,8 @@
 						{
 							Work = S9xGetByte((d->ABank << 16) + p);
 							S9xSetPPU(Work, 0x2100 + d->BAddress);
-							UPDATE_COUNTERS;
+							if (!UPDATE_COUNTERS())
+								return false;
 							if (--count <= 0)
 							{
 								b = 1;
@@ -687,7 +461,8 @@
 						case 1:
 							Work = S9xGetByte((d->ABank << 16) + p);
 							S9xSetPPU(Work, 0x2101 + d->BAddress);
-							UPDATE_COUNTERS;
+							if (!UPDATE_COUNTERS())
+								return false;
 							if (--count <= 0)
 							{
 								b = 2;
@@ -697,7 +472,8 @@
 						case 2:
 							Work = S9xGetByte((d->ABank << 16) + p);
 							S9xSetPPU(Work, 0x2102 + d->BAddress);
-							UPDATE_COUNTERS;
+							if (!UPDATE_COUNTERS())
+								return false;
 							if (--count <= 0)
 							{
 								b = 3;
@@ -707,7 +483,8 @@
 						case 3:
 							Work = S9xGetByte((d->ABank << 16) + p);
 							S9xSetPPU(Work, 0x2103 + d->BAddress);
-							UPDATE_COUNTERS;
+							if (!UPDATE_COUNTERS())
+								return false;
 							if (--count <= 0)
 							{
 								b = 0;
@@ -716,18 +493,11 @@
 						} while (1);
 					}
 				}
-			#ifdef DEBUGGER
-				else
-				{
-					sprintf(String, "Unknown DMA transfer mode: %d on channel %d\n", d->TransferMode, Channel);
-					S9xMessage(S9X_TRACE, S9X_DMA_TRACE, String);
-				}
-			#endif
 			}
 			else
 			{
 				// DMA FAST PATH
-				if (d->TransferMode == 0 || d->TransferMode == 2 || d->TransferMode == 6)
+				if (!d->TransferMode || d->TransferMode == 2 || d->TransferMode == 6)
 				{
 					switch (d->BAddress)
 					{
@@ -736,7 +506,8 @@
 							{
 								Work = *(base + p);
 								REGISTER_2104(Work);
-								UPDATE_COUNTERS;
+								if (!UPDATE_COUNTERS())
+									return false;
 							} while (--count > 0);
 
 							break;
@@ -748,7 +519,8 @@
 								{
 									Work = *(base + p);
 									REGISTER_2118_linear(Work);
-									UPDATE_COUNTERS;
+									if (!UPDATE_COUNTERS())
+										return false;
 								} while (--count > 0);
 							}
 							else
@@ -757,7 +529,8 @@
 								{
 									Work = *(base + p);
 									REGISTER_2118_tile(Work);
-									UPDATE_COUNTERS;
+									if (!UPDATE_COUNTERS())
+										return false;
 								} while (--count > 0);
 							}
 
@@ -770,7 +543,8 @@
 								{
 									Work = *(base + p);
 									REGISTER_2119_linear(Work);
-									UPDATE_COUNTERS;
+									if (!UPDATE_COUNTERS())
+										return false;
 								} while (--count > 0);
 							}
 							else
@@ -779,7 +553,8 @@
 								{
 									Work = *(base + p);
 									REGISTER_2119_tile(Work);
-									UPDATE_COUNTERS;
+									if (!UPDATE_COUNTERS())
+										return false;
 								} while (--count > 0);
 							}
 
@@ -789,8 +564,8 @@
 							do
 							{
 								Work = *(base + p);
-								//REGISTER_2122(Work);
-								UPDATE_COUNTERS;
+								if (!UPDATE_COUNTERS())
+									return false;
 							} while (--count > 0);
 
 							break;
@@ -802,14 +577,16 @@
 								{
 									Work = *(base + p);
 									REGISTER_2180(Work);
-									UPDATE_COUNTERS;
+									if (!UPDATE_COUNTERS())
+										return false;
 								} while (--count > 0);
 							}
 							else
 							{
 								do
 								{
-									UPDATE_COUNTERS;
+									if (!UPDATE_COUNTERS())
+										return false;
 								} while (--count > 0);
 							}
 
@@ -820,14 +597,14 @@
 							{
 								Work = *(base + p);
 								S9xSetPPU(Work, 0x2100 + d->BAddress);
-								UPDATE_COUNTERS;
+								if (!UPDATE_COUNTERS())
+									return false;
 							} while (--count > 0);
 
 							break;
 					}
 				}
-				else
-				if (d->TransferMode == 1 || d->TransferMode == 5)
+				else if (d->TransferMode == 1 || d->TransferMode == 5)
 				{
 					if (d->BAddress == 0x18)
 					{
@@ -841,14 +618,16 @@
 								{
 									Work = *(base + p);
 									REGISTER_2118_linear(Work);
-									UPDATE_COUNTERS;
-									count--;
+									if (!UPDATE_COUNTERS())
+										return false;
+									--count;
 
 								case 1:
 									Work = *(base + p);
 									REGISTER_2119_linear(Work);
-									UPDATE_COUNTERS;
-									count--;
+									if (!UPDATE_COUNTERS())
+										return false;
+									--count;
 								}
 							}
 
@@ -856,7 +635,8 @@
 							{
 								Work = *(base + p);
 								REGISTER_2118_linear(Work);
-								UPDATE_COUNTERS;
+								if (!UPDATE_COUNTERS())
+									return false;
 								b = 1;
 							}
 							else
@@ -871,14 +651,16 @@
 								{
 									Work = *(base + p);
 									REGISTER_2118_tile(Work);
-									UPDATE_COUNTERS;
-									count--;
+									if (!UPDATE_COUNTERS())
+										return false;
+									--count;
 
 								case 1:
 									Work = *(base + p);
 									REGISTER_2119_tile(Work);
-									UPDATE_COUNTERS;
-									count--;
+									if (!UPDATE_COUNTERS())
+										return false;
+									--count;
 								}
 							}
 
@@ -886,7 +668,8 @@
 							{
 								Work = *(base + p);
 								REGISTER_2118_tile(Work);
-								UPDATE_COUNTERS;
+								if (!UPDATE_COUNTERS())
+									return false;
 								b = 1;
 							}
 							else
@@ -903,14 +686,16 @@
 							{
 								Work = *(base + p);
 								S9xSetPPU(Work, 0x2100 + d->BAddress);
-								UPDATE_COUNTERS;
-								count--;
+								if (!UPDATE_COUNTERS())
+									return false;
+								--count;
 
 							case 1:
 								Work = *(base + p);
 								S9xSetPPU(Work, 0x2101 + d->BAddress);
-								UPDATE_COUNTERS;
-								count--;
+								if (!UPDATE_COUNTERS())
+									return false;
+								--count;
 							}
 						}
 
@@ -918,15 +703,15 @@
 						{
 							Work = *(base + p);
 							S9xSetPPU(Work, 0x2100 + d->BAddress);
-							UPDATE_COUNTERS;
+							if (!UPDATE_COUNTERS())
+								return false;
 							b = 1;
 						}
 						else
 							b = 0;
 					}
 				}
-				else
-				if (d->TransferMode == 3 || d->TransferMode == 7)
+				else if (d->TransferMode == 3 || d->TransferMode == 7)
 				{
 					switch (b)
 					{
@@ -935,7 +720,8 @@
 						{
 							Work = *(base + p);
 							S9xSetPPU(Work, 0x2100 + d->BAddress);
-							UPDATE_COUNTERS;
+							if (!UPDATE_COUNTERS())
+								return false;
 							if (--count <= 0)
 							{
 								b = 1;
@@ -945,7 +731,8 @@
 						case 1:
 							Work = *(base + p);
 							S9xSetPPU(Work, 0x2100 + d->BAddress);
-							UPDATE_COUNTERS;
+							if (!UPDATE_COUNTERS())
+								return false;
 							if (--count <= 0)
 							{
 								b = 2;
@@ -955,7 +742,8 @@
 						case 2:
 							Work = *(base + p);
 							S9xSetPPU(Work, 0x2101 + d->BAddress);
-							UPDATE_COUNTERS;
+							if (!UPDATE_COUNTERS())
+								return false;
 							if (--count <= 0)
 							{
 								b = 3;
@@ -965,7 +753,8 @@
 						case 3:
 							Work = *(base + p);
 							S9xSetPPU(Work, 0x2101 + d->BAddress);
-							UPDATE_COUNTERS;
+							if (!UPDATE_COUNTERS())
+								return false;
 							if (--count <= 0)
 							{
 								b = 0;
@@ -974,8 +763,7 @@
 						} while (1);
 					}
 				}
-				else
-				if (d->TransferMode == 4)
+				else if (d->TransferMode == 4)
 				{
 					switch (b)
 					{
@@ -984,7 +772,8 @@
 						{
 							Work = *(base + p);
 							S9xSetPPU(Work, 0x2100 + d->BAddress);
-							UPDATE_COUNTERS;
+							if (!UPDATE_COUNTERS())
+								return false;
 							if (--count <= 0)
 							{
 								b = 1;
@@ -994,7 +783,8 @@
 						case 1:
 							Work = *(base + p);
 							S9xSetPPU(Work, 0x2101 + d->BAddress);
-							UPDATE_COUNTERS;
+							if (!UPDATE_COUNTERS())
+								return false;
 							if (--count <= 0)
 							{
 								b = 2;
@@ -1004,7 +794,8 @@
 						case 2:
 							Work = *(base + p);
 							S9xSetPPU(Work, 0x2102 + d->BAddress);
-							UPDATE_COUNTERS;
+							if (!UPDATE_COUNTERS())
+								return false;
 							if (--count <= 0)
 							{
 								b = 3;
@@ -1014,7 +805,8 @@
 						case 3:
 							Work = *(base + p);
 							S9xSetPPU(Work, 0x2103 + d->BAddress);
-							UPDATE_COUNTERS;
+							if (!UPDATE_COUNTERS())
+								return false;
 							if (--count <= 0)
 							{
 								b = 0;
@@ -1023,13 +815,6 @@
 						} while (1);
 					}
 				}
-			#ifdef DEBUGGER
-				else
-				{
-					sprintf(String, "Unknown DMA transfer mode: %d on channel %d\n", d->TransferMode, Channel);
-					S9xMessage(S9X_TRACE, S9X_DMA_TRACE, String);
-				}
-			#endif
 			}
 
 			if (rem <= 0)
@@ -1037,28 +822,28 @@
 
 			base = S9xGetBasePointer((d->ABank << 16) + d->AAddress);
 			count = MEMMAP_BLOCK_SIZE;
-			inWRAM_DMA = ((/*!in_sa1_dma && */!in_sdd1_dma/* && !spc7110_dma*/) &&
-				(d->ABank == 0x7e || d->ABank == 0x7f || (!(d->ABank & 0x40) && d->AAddress < 0x2000)));
+			inWRAM_DMA = !in_sdd1_dma && (d->ABank == 0x7e || d->ABank == 0x7f || (!(d->ABank & 0x40) && d->AAddress < 0x2000));
 		}
-
-		#undef UPDATE_COUNTERS
 	}
-    else
-    {
+	else
+	{
 		// PPU -> CPU
 
 		// 8 cycles per byte
-		#define	UPDATE_COUNTERS \
-			d->TransferBytes--; \
-			d->AAddress += inc; \
-			if (!addCyclesInDMA(Channel)) \
-			{ \
-				CPU.InDMA = false; \
-				CPU.InDMAorHDMA = false; \
-				CPU.InWRAMDMAorHDMA = false; \
-				CPU.CurrentDMAorHDMAChannel = -1; \
-				return false; \
+		auto UPDATE_COUNTERS = [&]() -> bool
+		{
+			--d->DMACount_Or_HDMAIndirectAddress;
+			d->AAddress += inc;
+			if (!addCyclesInDMA(Channel))
+			{
+				CPU.InDMA = false;
+				CPU.InDMAorHDMA = false;
+				CPU.InWRAMDMAorHDMA = false;
+				CPU.CurrentDMAorHDMAChannel = -1;
+				return false;
 			}
+			return true;
+		};
 
 		if (d->BAddress > 0x80 - 4 && d->BAddress <= 0x83 && !(d->ABank & 0x40))
 		{
@@ -1070,111 +855,117 @@
 					case 0:
 					case 2:
 					case 6:
-						CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000);
+						CPU.InWRAMDMAorHDMA = d->AAddress < 0x2000;
 						Work = S9xGetPPU(0x2100 + d->BAddress);
 						S9xSetByte(Work, (d->ABank << 16) + d->AAddress);
-						UPDATE_COUNTERS;
-						count--;
+						if (!UPDATE_COUNTERS())
+							return false;
+						--count;
 
 						break;
 
 					case 1:
 					case 5:
-						CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000);
+						CPU.InWRAMDMAorHDMA = d->AAddress < 0x2000;
 						Work = S9xGetPPU(0x2100 + d->BAddress);
 						S9xSetByte(Work, (d->ABank << 16) + d->AAddress);
-						UPDATE_COUNTERS;
+						if (!UPDATE_COUNTERS())
+							return false;
 						if (!--count)
 							break;
 
-						CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000);
+						CPU.InWRAMDMAorHDMA = d->AAddress < 0x2000;
 						Work = S9xGetPPU(0x2101 + d->BAddress);
 						S9xSetByte(Work, (d->ABank << 16) + d->AAddress);
-						UPDATE_COUNTERS;
-						count--;
+						if (!UPDATE_COUNTERS())
+							return false;
+						--count;
 
 						break;
 
 					case 3:
 					case 7:
-						CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000);
+						CPU.InWRAMDMAorHDMA = d->AAddress < 0x2000;
 						Work = S9xGetPPU(0x2100 + d->BAddress);
 						S9xSetByte(Work, (d->ABank << 16) + d->AAddress);
-						UPDATE_COUNTERS;
+						if (!UPDATE_COUNTERS())
+							return false;
 						if (!--count)
 							break;
 
-						CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000);
+						CPU.InWRAMDMAorHDMA = d->AAddress < 0x2000;
 						Work = S9xGetPPU(0x2100 + d->BAddress);
 						S9xSetByte(Work, (d->ABank << 16) + d->AAddress);
-						UPDATE_COUNTERS;
+						if (!UPDATE_COUNTERS())
+							return false;
 						if (!--count)
 							break;
 
-						CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000);
+						CPU.InWRAMDMAorHDMA = d->AAddress < 0x2000;
 						Work = S9xGetPPU(0x2101 + d->BAddress);
 						S9xSetByte(Work, (d->ABank << 16) + d->AAddress);
-						UPDATE_COUNTERS;
+						if (!UPDATE_COUNTERS())
+							return false;
 						if (!--count)
 							break;
 
-						CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000);
+						CPU.InWRAMDMAorHDMA = d->AAddress < 0x2000;
 						Work = S9xGetPPU(0x2101 + d->BAddress);
 						S9xSetByte(Work, (d->ABank << 16) + d->AAddress);
-						UPDATE_COUNTERS;
-						count--;
+						if (!UPDATE_COUNTERS())
+							return false;
+						--count;
 
 						break;
 
 					case 4:
-						CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000);
+						CPU.InWRAMDMAorHDMA = d->AAddress < 0x2000;
 						Work = S9xGetPPU(0x2100 + d->BAddress);
 						S9xSetByte(Work, (d->ABank << 16) + d->AAddress);
-						UPDATE_COUNTERS;
+						if (!UPDATE_COUNTERS())
+							return false;
 						if (!--count)
 							break;
 
-						CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000);
+						CPU.InWRAMDMAorHDMA = d->AAddress < 0x2000;
 						Work = S9xGetPPU(0x2101 + d->BAddress);
 						S9xSetByte(Work, (d->ABank << 16) + d->AAddress);
-						UPDATE_COUNTERS;
+						if (!UPDATE_COUNTERS())
+							return false;
 						if (!--count)
 							break;
 
-						CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000);
+						CPU.InWRAMDMAorHDMA = d->AAddress < 0x2000;
 						Work = S9xGetPPU(0x2102 + d->BAddress);
 						S9xSetByte(Work, (d->ABank << 16) + d->AAddress);
-						UPDATE_COUNTERS;
+						if (!UPDATE_COUNTERS())
+							return false;
 						if (!--count)
 							break;
 
-						CPU.InWRAMDMAorHDMA = (d->AAddress < 0x2000);
+						CPU.InWRAMDMAorHDMA = d->AAddress < 0x2000;
 						Work = S9xGetPPU(0x2103 + d->BAddress);
 						S9xSetByte(Work, (d->ABank << 16) + d->AAddress);
-						UPDATE_COUNTERS;
-						count--;
+						if (!UPDATE_COUNTERS())
+							return false;
+						--count;
 
 						break;
 
 					default:
-					#ifdef DEBUGGER
-						sprintf(String, "Unknown DMA transfer mode: %d on channel %d\n", d->TransferMode, Channel);
-						S9xMessage(S9X_TRACE, S9X_DMA_TRACE, String);
-					#endif
 						while (count)
 						{
-							UPDATE_COUNTERS;
-							count--;
+							if (!UPDATE_COUNTERS())
+								return false;
+							--count;
 						}
-
-						break;
 				}
 			} while (count);
 		}
 		else
 		{
 			// REVERSE-DMA FASTER PATH
-			CPU.InWRAMDMAorHDMA = (d->ABank == 0x7e || d->ABank == 0x7f);
+			CPU.InWRAMDMAorHDMA = d->ABank == 0x7e || d->ABank == 0x7f;
 			do
 			{
 				switch (d->TransferMode)
@@ -1184,8 +975,9 @@
 					case 6:
 						Work = S9xGetPPU(0x2100 + d->BAddress);
 						S9xSetByte(Work, (d->ABank << 16) + d->AAddress);
-						UPDATE_COUNTERS;
-						count--;
+						if (!UPDATE_COUNTERS())
+							return false;
+						--count;
 
 						break;
 
@@ -1193,14 +985,16 @@
 					case 5:
 						Work = S9xGetPPU(0x2100 + d->BAddress);
 						S9xSetByte(Work, (d->ABank << 16) + d->AAddress);
-						UPDATE_COUNTERS;
+						if (!UPDATE_COUNTERS())
+							return false;
 						if (!--count)
 							break;
 
 						Work = S9xGetPPU(0x2101 + d->BAddress);
 						S9xSetByte(Work, (d->ABank << 16) + d->AAddress);
-						UPDATE_COUNTERS;
-						count--;
+						if (!UPDATE_COUNTERS())
+							return false;
+						--count;
 
 						break;
 
@@ -1208,67 +1002,70 @@
 					case 7:
 						Work = S9xGetPPU(0x2100 + d->BAddress);
 						S9xSetByte(Work, (d->ABank << 16) + d->AAddress);
-						UPDATE_COUNTERS;
+						if (!UPDATE_COUNTERS())
+							return false;
 						if (!--count)
 							break;
 
 						Work = S9xGetPPU(0x2100 + d->BAddress);
 						S9xSetByte(Work, (d->ABank << 16) + d->AAddress);
-						UPDATE_COUNTERS;
+						if (!UPDATE_COUNTERS())
+							return false;
 						if (!--count)
 							break;
 
 						Work = S9xGetPPU(0x2101 + d->BAddress);
 						S9xSetByte(Work, (d->ABank << 16) + d->AAddress);
-						UPDATE_COUNTERS;
+						if (!UPDATE_COUNTERS())
+							return false;
 						if (!--count)
 							break;
 
 						Work = S9xGetPPU(0x2101 + d->BAddress);
 						S9xSetByte(Work, (d->ABank << 16) + d->AAddress);
-						UPDATE_COUNTERS;
-						count--;
+						if (!UPDATE_COUNTERS())
+							return false;
+						--count;
 
 						break;
 
 					case 4:
 						Work = S9xGetPPU(0x2100 + d->BAddress);
 						S9xSetByte(Work, (d->ABank << 16) + d->AAddress);
-						UPDATE_COUNTERS;
+						if (!UPDATE_COUNTERS())
+							return false;
 						if (!--count)
 							break;
 
 						Work = S9xGetPPU(0x2101 + d->BAddress);
 						S9xSetByte(Work, (d->ABank << 16) + d->AAddress);
-						UPDATE_COUNTERS;
+						if (!UPDATE_COUNTERS())
+							return false;
 						if (!--count)
 							break;
 
 						Work = S9xGetPPU(0x2102 + d->BAddress);
 						S9xSetByte(Work, (d->ABank << 16) + d->AAddress);
-						UPDATE_COUNTERS;
+						if (!UPDATE_COUNTERS())
+							return false;
 						if (!--count)
 							break;
 
 						Work = S9xGetPPU(0x2103 + d->BAddress);
 						S9xSetByte(Work, (d->ABank << 16) + d->AAddress);
-						UPDATE_COUNTERS;
-						count--;
+						if (!UPDATE_COUNTERS())
+							return false;
+						--count;
 
 						break;
 
 					default:
-					#ifdef DEBUGGER
-						sprintf(String, "Unknown DMA transfer mode: %d on channel %d\n", d->TransferMode, Channel);
-						S9xMessage(S9X_TRACE, S9X_DMA_TRACE, String);
-					#endif
 						while (count)
 						{
-							UPDATE_COUNTERS;
-							count--;
+							if (!UPDATE_COUNTERS())
+								return false;
+							--count;
 						}
-
-						break;
 				}
 			} while (count);
 		}
@@ -1281,34 +1078,17 @@
 			Timings.NMITriggerPos -= Timings.H_Max;
 	}
 
-	// Release the memory used in SPC7110 DMA
-    /*if (Settings.SPC7110)
-    {
-        if (spc7110_dma)
-            delete [] spc7110_dma;
-    }*/
-
-#if 0
-	// sanity check
-    if (d->TransferBytes != 0)
-		fprintf(stderr,"DMA[%d] TransferBytes not 0! $21%02x Reverse:%d %04x\n", Channel, d->BAddress, d->ReverseTransfer, d->TransferBytes);
-#endif
-
-	CPU.InDMA = false;
-	CPU.InDMAorHDMA = false;
-	CPU.InWRAMDMAorHDMA = false;
+	CPU.InDMA = CPU.InDMAorHDMA = CPU.InWRAMDMAorHDMA = false;
 	CPU.CurrentDMAorHDMAChannel = -1;
 
 	return true;
 }
 
-static inline bool HDMAReadLineCount (int d)
+static inline bool HDMAReadLineCount(int d)
 {
 	// CPU.InDMA is set, so S9xGetXXX() / S9xSetXXX() incur no charges.
 
-	uint8_t	line;
-
-	line = S9xGetByte((DMA[d].ABank << 16) + DMA[d].Address);
+	uint8_t line = S9xGetByte((DMA[d].ABank << 16) + DMA[d].Address);
 	ADD_CYCLES(SLOW_ONE_CYCLE);
 
 	if (!line)
@@ -1320,23 +1100,22 @@
 		{
 			if (PPU.HDMA & (0xfe << d))
 			{
-				DMA[d].Address++;
+				++DMA[d].Address;
 				ADD_CYCLES(SLOW_ONE_CYCLE << 1);
 			}
 			else
 				ADD_CYCLES(SLOW_ONE_CYCLE);
 
-			DMA[d].IndirectAddress = S9xGetWord((DMA[d].ABank << 16) + DMA[d].Address);
-			DMA[d].Address++;
+			DMA[d].DMACount_Or_HDMAIndirectAddress = S9xGetWord((DMA[d].ABank << 16) + DMA[d].Address);
+			++DMA[d].Address;
 		}
 
-		DMA[d].Address++;
-		HDMAMemPointers[d] = NULL;
+		++DMA[d].Address;
+		HDMAMemPointers[d] = nullptr;
 
 		return false;
 	}
-	else
-	if (line == 0x80)
+	else if (line == 0x80)
 	{
 		DMA[d].Repeat = true;
 		DMA[d].LineCount = 128;
@@ -1347,15 +1126,15 @@
 		DMA[d].LineCount = line & 0x7f;
 	}
 
-	DMA[d].Address++;
+	++DMA[d].Address;
 	DMA[d].DoTransfer = true;
 
 	if (DMA[d].HDMAIndirectAddressing)
 	{
 		ADD_CYCLES(SLOW_ONE_CYCLE << 1);
-		DMA[d].IndirectAddress = S9xGetWord((DMA[d].ABank << 16) + DMA[d].Address);
+		DMA[d].DMACount_Or_HDMAIndirectAddress = S9xGetWord((DMA[d].ABank << 16) + DMA[d].Address);
 		DMA[d].Address += 2;
-		HDMAMemPointers[d] = S9xGetMemPointer((DMA[d].IndirectBank << 16) + DMA[d].IndirectAddress);
+		HDMAMemPointers[d] = S9xGetMemPointer((DMA[d].IndirectBank << 16) + DMA[d].DMACount_Or_HDMAIndirectAddress);
 	}
 	else
 		HDMAMemPointers[d] = S9xGetMemPointer((DMA[d].ABank << 16) + DMA[d].Address);
@@ -1367,23 +1146,17 @@
 {
 	PPU.HDMA = Memory.FillRAM[0x420c];
 
-#ifdef DEBUGGER
-	missing.hdma_this_frame = PPU.HDMA;
-#endif
-
 	PPU.HDMAEnded = 0;
-
-	int32_t	tmpch;
 
 	CPU.InHDMA = true;
 	CPU.InDMAorHDMA = true;
-	tmpch = CPU.CurrentDMAorHDMAChannel;
+	int32_t tmpch = CPU.CurrentDMAorHDMAChannel;
 
 	// XXX: Not quite right...
-	if (PPU.HDMA != 0)
+	if (PPU.HDMA)
 		ADD_CYCLES(Timings.DMACPUSync);
 
-	for (uint8_t i = 0; i < 8; i++)
+	for (uint8_t i = 0; i < 8; ++i)
 	{
 		if (PPU.HDMA & (1 << i))
 		{
@@ -1394,7 +1167,7 @@
 			if (!HDMAReadLineCount(i))
 			{
 				PPU.HDMA &= ~(1 << i);
-				PPU.HDMAEnded |= (1 << i);
+				PPU.HDMAEnded |= 1 << i;
 			}
 		}
 		else
@@ -1407,40 +1180,38 @@
 	CPU.CurrentDMAorHDMAChannel = tmpch;
 }
 
-uint8_t S9xDoHDMA (uint8_t byte)
+uint8_t S9xDoHDMA(uint8_t byte)
 {
-	struct SDMA	*p = &DMA[0];
-
-	uint32_t	ShiftedIBank;
-	uint16_t	IAddr;
-	bool	temp;
-	int32_t	tmpch;
-	int		d = 0;
+	SDMA *p = &DMA[0];
+
+	int d = 0;
 
 	CPU.InHDMA = true;
 	CPU.InDMAorHDMA = true;
 	CPU.HDMARanInDMA = CPU.InDMA ? byte : 0;
-	temp = CPU.InWRAMDMAorHDMA;
-	tmpch = CPU.CurrentDMAorHDMAChannel;
+	bool temp = CPU.InWRAMDMAorHDMA;
+	int32_t tmpch = CPU.CurrentDMAorHDMAChannel;
 
 	// XXX: Not quite right...
 	ADD_CYCLES(Timings.DMACPUSync);
 
-	for (uint8_t mask = 1; mask; mask <<= 1, p++, d++)
+	for (uint8_t mask = 1; mask; mask <<= 1, ++p, ++d)
 	{
 		if (byte & mask)
 		{
 			CPU.InWRAMDMAorHDMA = false;
 			CPU.CurrentDMAorHDMAChannel = d;
 
+			uint32_t ShiftedIBank;
+			uint16_t IAddr;
 			if (p->HDMAIndirectAddressing)
 			{
-				ShiftedIBank = (p->IndirectBank << 16);
-				IAddr = p->IndirectAddress;
+				ShiftedIBank = p->IndirectBank << 16;
+				IAddr = p->DMACount_Or_HDMAIndirectAddress;
 			}
 			else
 			{
-				ShiftedIBank = (p->ABank << 16);
+				ShiftedIBank = p->ABank << 16;
 				IAddr = p->Address;
 			}
 
@@ -1460,31 +1231,18 @@
 					}
 				}
 
-			#ifdef DEBUGGER
-				if (Settings.TraceHDMA && p->DoTransfer)
-				{
-					sprintf(String, "H-DMA[%d] %s (%d) 0x%06X->0x21%02X %s, Count: %3d, Rep: %s, V-LINE: %3ld %02X%04X",
-							p-DMA, p->ReverseTransfer? "read" : "write",
-							p->TransferMode, ShiftedIBank+IAddr, p->BAddress,
-							p->HDMAIndirectAddressing ? "ind" : "abs",
-							p->LineCount,
-							p->Repeat ? "yes" : "no ", (long) CPU.V_Counter,
-							p->ABank, p->Address);
-					S9xMessage(S9X_TRACE, S9X_HDMA_TRACE, String);
-				}
-			#endif
-
 				if (!p->ReverseTransfer)
 				{
 					if ((IAddr & MEMMAP_MASK) + HDMA_ModeByteCounts[p->TransferMode] >= MEMMAP_BLOCK_SIZE)
 					{
 						// HDMA REALLY-SLOW PATH
-						HDMAMemPointers[d] = NULL;
-
-						#define DOBYTE(Addr, RegOff) \
-							CPU.InWRAMDMAorHDMA = (ShiftedIBank == 0x7e0000 || ShiftedIBank == 0x7f0000 || \
-								(!(ShiftedIBank & 0x400000) && ((uint16_t) (Addr)) < 0x2000)); \
-							S9xSetPPU(S9xGetByte(ShiftedIBank + ((uint16_t) (Addr))), 0x2100 + p->BAddress + (RegOff));
+						HDMAMemPointers[d] = nullptr;
+
+						auto DOBYTE = [&](uint16_t Addr, uint16_t RegOff)
+						{
+							CPU.InWRAMDMAorHDMA = ShiftedIBank == 0x7e0000 || ShiftedIBank == 0x7f0000 || (!(ShiftedIBank & 0x400000) && Addr < 0x2000);
+							S9xSetPPU(S9xGetByte(ShiftedIBank + Addr), 0x2100 + p->BAddress + RegOff);
+						};
 
 						switch (p->TransferMode)
 						{
@@ -1494,7 +1252,7 @@
 								break;
 
 							case 5:
-								DOBYTE(IAddr + 0, 0);
+								DOBYTE(IAddr, 0);
 								ADD_CYCLES(SLOW_ONE_CYCLE);
 								DOBYTE(IAddr + 1, 1);
 								ADD_CYCLES(SLOW_ONE_CYCLE);
@@ -1505,7 +1263,7 @@
 								break;
 
 							case 1:
-								DOBYTE(IAddr + 0, 0);
+								DOBYTE(IAddr, 0);
 								ADD_CYCLES(SLOW_ONE_CYCLE);
 								DOBYTE(IAddr + 1, 1);
 								ADD_CYCLES(SLOW_ONE_CYCLE);
@@ -1513,7 +1271,7 @@
 
 							case 2:
 							case 6:
-								DOBYTE(IAddr + 0, 0);
+								DOBYTE(IAddr, 0);
 								ADD_CYCLES(SLOW_ONE_CYCLE);
 								DOBYTE(IAddr + 1, 0);
 								ADD_CYCLES(SLOW_ONE_CYCLE);
@@ -1521,7 +1279,7 @@
 
 							case 3:
 							case 7:
-								DOBYTE(IAddr + 0, 0);
+								DOBYTE(IAddr, 0);
 								ADD_CYCLES(SLOW_ONE_CYCLE);
 								DOBYTE(IAddr + 1, 0);
 								ADD_CYCLES(SLOW_ONE_CYCLE);
@@ -1532,7 +1290,7 @@
 								break;
 
 							case 4:
-								DOBYTE(IAddr + 0, 0);
+								DOBYTE(IAddr, 0);
 								ADD_CYCLES(SLOW_ONE_CYCLE);
 								DOBYTE(IAddr + 1, 1);
 								ADD_CYCLES(SLOW_ONE_CYCLE);
@@ -1540,20 +1298,16 @@
 								ADD_CYCLES(SLOW_ONE_CYCLE);
 								DOBYTE(IAddr + 3, 3);
 								ADD_CYCLES(SLOW_ONE_CYCLE);
-								break;
 						}
-
-						#undef DOBYTE
 					}
 					else
 					{
-						CPU.InWRAMDMAorHDMA = (ShiftedIBank == 0x7e0000 || ShiftedIBank == 0x7f0000 ||
-							(!(ShiftedIBank & 0x400000) && IAddr < 0x2000));
+						CPU.InWRAMDMAorHDMA = ShiftedIBank == 0x7e0000 || ShiftedIBank == 0x7f0000 || (!(ShiftedIBank & 0x400000) && IAddr < 0x2000);
 
 						if (!HDMAMemPointers[d])
 						{
 							// HDMA SLOW PATH
-							uint32_t	Addr = ShiftedIBank + IAddr;
+							uint32_t Addr = ShiftedIBank + IAddr;
 
 							switch (p->TransferMode)
 							{
@@ -1563,14 +1317,14 @@
 									break;
 
 								case 5:
-									S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress);
+									S9xSetPPU(S9xGetByte(Addr), 0x2100 + p->BAddress);
 									ADD_CYCLES(SLOW_ONE_CYCLE);
 									S9xSetPPU(S9xGetByte(Addr + 1), 0x2101 + p->BAddress);
 									ADD_CYCLES(SLOW_ONE_CYCLE);
 									Addr += 2;
 									/* fall through */
 								case 1:
-									S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress);
+									S9xSetPPU(S9xGetByte(Addr), 0x2100 + p->BAddress);
 									ADD_CYCLES(SLOW_ONE_CYCLE);
 									S9xSetPPU(S9xGetByte(Addr + 1), 0x2101 + p->BAddress);
 									ADD_CYCLES(SLOW_ONE_CYCLE);
@@ -1578,7 +1332,7 @@
 
 								case 2:
 								case 6:
-									S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress);
+									S9xSetPPU(S9xGetByte(Addr), 0x2100 + p->BAddress);
 									ADD_CYCLES(SLOW_ONE_CYCLE);
 									S9xSetPPU(S9xGetByte(Addr + 1), 0x2100 + p->BAddress);
 									ADD_CYCLES(SLOW_ONE_CYCLE);
@@ -1586,7 +1340,7 @@
 
 								case 3:
 								case 7:
-									S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress);
+									S9xSetPPU(S9xGetByte(Addr), 0x2100 + p->BAddress);
 									ADD_CYCLES(SLOW_ONE_CYCLE);
 									S9xSetPPU(S9xGetByte(Addr + 1), 0x2100 + p->BAddress);
 									ADD_CYCLES(SLOW_ONE_CYCLE);
@@ -1597,7 +1351,7 @@
 									break;
 
 								case 4:
-									S9xSetPPU(S9xGetByte(Addr + 0), 0x2100 + p->BAddress);
+									S9xSetPPU(S9xGetByte(Addr), 0x2100 + p->BAddress);
 									ADD_CYCLES(SLOW_ONE_CYCLE);
 									S9xSetPPU(S9xGetByte(Addr + 1), 0x2101 + p->BAddress);
 									ADD_CYCLES(SLOW_ONE_CYCLE);
@@ -1605,7 +1359,6 @@
 									ADD_CYCLES(SLOW_ONE_CYCLE);
 									S9xSetPPU(S9xGetByte(Addr + 3), 0x2103 + p->BAddress);
 									ADD_CYCLES(SLOW_ONE_CYCLE);
-									break;
 							}
 						}
 						else
@@ -1619,14 +1372,14 @@
 									break;
 
 								case 5:
-									S9xSetPPU(*(HDMAMemPointers[d] + 0), 0x2100 + p->BAddress);
+									S9xSetPPU(*HDMAMemPointers[d], 0x2100 + p->BAddress);
 									ADD_CYCLES(SLOW_ONE_CYCLE);
 									S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2101 + p->BAddress);
 									ADD_CYCLES(SLOW_ONE_CYCLE);
 									HDMAMemPointers[d] += 2;
 									/* fall through */
 								case 1:
-									S9xSetPPU(*(HDMAMemPointers[d] + 0), 0x2100 + p->BAddress);
+									S9xSetPPU(*HDMAMemPointers[d], 0x2100 + p->BAddress);
 									ADD_CYCLES(SLOW_ONE_CYCLE);
 									S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2101 + p->BAddress);
 									ADD_CYCLES(SLOW_ONE_CYCLE);
@@ -1635,7 +1388,7 @@
 
 								case 2:
 								case 6:
-									S9xSetPPU(*(HDMAMemPointers[d] + 0), 0x2100 + p->BAddress);
+									S9xSetPPU(*HDMAMemPointers[d], 0x2100 + p->BAddress);
 									ADD_CYCLES(SLOW_ONE_CYCLE);
 									S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2100 + p->BAddress);
 									ADD_CYCLES(SLOW_ONE_CYCLE);
@@ -1644,7 +1397,7 @@
 
 								case 3:
 								case 7:
-									S9xSetPPU(*(HDMAMemPointers[d] + 0), 0x2100 + p->BAddress);
+									S9xSetPPU(*HDMAMemPointers[d], 0x2100 + p->BAddress);
 									ADD_CYCLES(SLOW_ONE_CYCLE);
 									S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2100 + p->BAddress);
 									ADD_CYCLES(SLOW_ONE_CYCLE);
@@ -1656,7 +1409,7 @@
 									break;
 
 								case 4:
-									S9xSetPPU(*(HDMAMemPointers[d] + 0), 0x2100 + p->BAddress);
+									S9xSetPPU(*HDMAMemPointers[d], 0x2100 + p->BAddress);
 									ADD_CYCLES(SLOW_ONE_CYCLE);
 									S9xSetPPU(*(HDMAMemPointers[d] + 1), 0x2101 + p->BAddress);
 									ADD_CYCLES(SLOW_ONE_CYCLE);
@@ -1665,7 +1418,6 @@
 									S9xSetPPU(*(HDMAMemPointers[d] + 3), 0x2103 + p->BAddress);
 									ADD_CYCLES(SLOW_ONE_CYCLE);
 									HDMAMemPointers[d] += 4;
-									break;
 							}
 						}
 					}
@@ -1675,12 +1427,13 @@
 					// REVERSE HDMA REALLY-SLOW PATH
 					// anomie says: Since this is apparently never used
 					// (otherwise we would have noticed before now), let's not bother with faster paths.
-					HDMAMemPointers[d] = NULL;
-
-					#define DOBYTE(Addr, RegOff) \
-						CPU.InWRAMDMAorHDMA = (ShiftedIBank == 0x7e0000 || ShiftedIBank == 0x7f0000 || \
-							(!(ShiftedIBank & 0x400000) && ((uint16_t) (Addr)) < 0x2000)); \
-						S9xSetByte(S9xGetPPU(0x2100 + p->BAddress + (RegOff)), ShiftedIBank + ((uint16_t) (Addr)));
+					HDMAMemPointers[d] = nullptr;
+
+					auto DOBYTE = [&](uint16_t Addr, uint16_t RegOff)
+					{
+						CPU.InWRAMDMAorHDMA = ShiftedIBank == 0x7e0000 || ShiftedIBank == 0x7f0000 || (!(ShiftedIBank & 0x400000) && Addr < 0x2000);
+						S9xSetByte(S9xGetPPU(0x2100 + p->BAddress + RegOff), ShiftedIBank + Addr);
+					};
 
 					switch (p->TransferMode)
 					{
@@ -1690,7 +1443,7 @@
 							break;
 
 						case 5:
-							DOBYTE(IAddr + 0, 0);
+							DOBYTE(IAddr, 0);
 							ADD_CYCLES(SLOW_ONE_CYCLE);
 							DOBYTE(IAddr + 1, 1);
 							ADD_CYCLES(SLOW_ONE_CYCLE);
@@ -1701,7 +1454,7 @@
 							break;
 
 						case 1:
-							DOBYTE(IAddr + 0, 0);
+							DOBYTE(IAddr, 0);
 							ADD_CYCLES(SLOW_ONE_CYCLE);
 							DOBYTE(IAddr + 1, 1);
 							ADD_CYCLES(SLOW_ONE_CYCLE);
@@ -1709,7 +1462,7 @@
 
 						case 2:
 						case 6:
-							DOBYTE(IAddr + 0, 0);
+							DOBYTE(IAddr, 0);
 							ADD_CYCLES(SLOW_ONE_CYCLE);
 							DOBYTE(IAddr + 1, 0);
 							ADD_CYCLES(SLOW_ONE_CYCLE);
@@ -1717,7 +1470,7 @@
 
 						case 3:
 						case 7:
-							DOBYTE(IAddr + 0, 0);
+							DOBYTE(IAddr, 0);
 							ADD_CYCLES(SLOW_ONE_CYCLE);
 							DOBYTE(IAddr + 1, 0);
 							ADD_CYCLES(SLOW_ONE_CYCLE);
@@ -1728,7 +1481,7 @@
 							break;
 
 						case 4:
-							DOBYTE(IAddr + 0, 0);
+							DOBYTE(IAddr, 0);
 							ADD_CYCLES(SLOW_ONE_CYCLE);
 							DOBYTE(IAddr + 1, 1);
 							ADD_CYCLES(SLOW_ONE_CYCLE);
@@ -1736,14 +1489,11 @@
 							ADD_CYCLES(SLOW_ONE_CYCLE);
 							DOBYTE(IAddr + 3, 3);
 							ADD_CYCLES(SLOW_ONE_CYCLE);
-							break;
 					}
-
-					#undef DOBYTE
 				}
 
 				if (p->HDMAIndirectAddressing)
-					p->IndirectAddress += HDMA_ModeByteCounts[p->TransferMode];
+					p->DMACount_Or_HDMAIndirectAddress += HDMA_ModeByteCounts[p->TransferMode];
 				else
 					p->Address += HDMA_ModeByteCounts[p->TransferMode];
 			}
@@ -1775,12 +1525,9 @@
 
 void S9xResetDMA()
 {
-	for (int d = 0; d < 8; d++)
+	for (int d = 0; d < 8; ++d)
 	{
-		DMA[d].ReverseTransfer = true;
-		DMA[d].HDMAIndirectAddressing = true;
-		DMA[d].AAddressFixed = true;
-		DMA[d].AAddressDecrement = true;
+		DMA[d].ReverseTransfer = DMA[d].HDMAIndirectAddressing = DMA[d].AAddressFixed = DMA[d].AAddressDecrement = true;
 		DMA[d].TransferMode = 7;
 		DMA[d].BAddress = 0xff;
 		DMA[d].AAddress = 0xffff;
@@ -1792,7 +1539,7 @@
 		DMA[d].LineCount = 0x7f;
 		DMA[d].UnknownByte = 0xff;
 		DMA[d].DoTransfer = false;
-		DMA[d].UnusedBit43x0 = 1;
+		DMA[d].UnusedBit43x0 = true;
 	}
 }
 

--- a/src/in_snsf/snes9x/dma.h
+++ b/src/in_snsf/snes9x/dma.h
@@ -175,38 +175,34 @@
   Nintendo Co., Limited and its subsidiary companies.
  ***********************************************************************************/
 
-
 #ifndef _DMA_H_
 #define _DMA_H_
 
 struct SDMA
 {
-	bool	ReverseTransfer;
-	bool	HDMAIndirectAddressing;
-	bool	UnusedBit43x0;
-	bool	AAddressFixed;
-	bool	AAddressDecrement;
-	uint8_t	TransferMode;
-	uint8_t	BAddress;
-	uint16_t	AAddress;
-	uint8_t	ABank;
-	uint16_t	DMACount_Or_HDMAIndirectAddress;
-	uint8_t	IndirectBank;
-	uint16_t	Address;
-	uint8_t	Repeat;
-	uint8_t	LineCount;
-	uint8_t	UnknownByte;
-	uint8_t	DoTransfer;
+	bool ReverseTransfer;
+	bool HDMAIndirectAddressing;
+	bool UnusedBit43x0;
+	bool AAddressFixed;
+	bool AAddressDecrement;
+	uint8_t TransferMode;
+	uint8_t BAddress;
+	uint16_t AAddress;
+	uint8_t ABank;
+	uint16_t DMACount_Or_HDMAIndirectAddress;
+	uint8_t IndirectBank;
+	uint16_t Address;
+	bool Repeat;
+	uint8_t LineCount;
+	uint8_t UnknownByte;
+	bool DoTransfer;
 };
 
-#define TransferBytes	DMACount_Or_HDMAIndirectAddress
-#define IndirectAddress	DMACount_Or_HDMAIndirectAddress
-
-extern struct SDMA	DMA[8];
-
-bool S9xDoDMA (uint8_t);
+extern SDMA DMA[8];
+
+bool S9xDoDMA(uint8_t);
 void S9xStartHDMA();
-uint8_t S9xDoHDMA (uint8_t);
+uint8_t S9xDoHDMA(uint8_t);
 void S9xResetDMA();
 
 #endif

--- a/src/in_snsf/snes9x/getset.h
+++ b/src/in_snsf/snes9x/getset.h
@@ -175,42 +175,38 @@
   Nintendo Co., Limited and its subsidiary companies.
  ***********************************************************************************/
 
-
 #ifndef _GETSET_H_
 #define _GETSET_H_
 
 #include "cpuexec.h"
-//#include "dsp.h"
-//#include "sa1.h"
-//#include "spc7110.h"
-//#include "c4.h"
-//#include "obc1.h"
-//#include "seta.h"
-//#include "bsx.h"
-
-#define addCyclesInMemoryAccess \
-	if (!CPU.InDMAorHDMA) \
-	{ \
-		CPU.PrevCycles = CPU.Cycles; \
-		CPU.Cycles += speed; \
-		S9xCheckInterrupts(); \
-		while (CPU.Cycles >= CPU.NextEvent) \
-			S9xDoHEventProcessing(); \
-	}
-
-#define addCyclesInMemoryAccess_x2 \
-	if (!CPU.InDMAorHDMA) \
-	{ \
-		CPU.PrevCycles = CPU.Cycles; \
-		CPU.Cycles += speed << 1; \
-		S9xCheckInterrupts(); \
-		while (CPU.Cycles >= CPU.NextEvent) \
-			S9xDoHEventProcessing(); \
-	}
-
-extern uint8_t	OpenBus;
-
-static inline int32_t memory_speed (uint32_t address)
+
+inline void addCyclesInMemoryAccess(int32_t speed)
+{
+	if (!CPU.InDMAorHDMA)
+	{
+		CPU.PrevCycles = CPU.Cycles;
+		CPU.Cycles += speed;
+		S9xCheckInterrupts();
+		while (CPU.Cycles >= CPU.NextEvent)
+			S9xDoHEventProcessing();
+	}
+}
+
+inline void addCyclesInMemoryAccess_x2(int32_t speed)
+{
+	if (!CPU.InDMAorHDMA)
+	{
+		CPU.PrevCycles = CPU.Cycles;
+		CPU.Cycles += speed << 1;
+		S9xCheckInterrupts();
+		while (CPU.Cycles >= CPU.NextEvent)
+			S9xDoHEventProcessing();
+	}
+}
+
+extern uint8_t OpenBus;
+
+inline int32_t memory_speed(uint32_t address)
 {
 	if (address & 0x408000)
 	{
@@ -229,25 +225,25 @@
 	return TWO_CYCLES;
 }
 
-inline uint8_t S9xGetByte (uint32_t Address)
-{
-	int		block = (Address & 0xffffff) >> MEMMAP_SHIFT;
-	uint8_t	*GetAddress = Memory.Map[block];
-	int32_t	speed = memory_speed(Address);
-	uint8_t	byte;
-
-	if (GetAddress >= (uint8_t *) CMemory::MAP_LAST)
-	{
-		byte = *(GetAddress + (Address & 0xffff));
-		addCyclesInMemoryAccess;
+inline uint8_t S9xGetByte(uint32_t Address)
+{
+	int block = (Address & 0xffffff) >> MEMMAP_SHIFT;
+	uint8_t *GetAddress = Memory.Map[block];
+	int32_t speed = memory_speed(Address);
+	uint8_t byte;
+
+	if (GetAddress >= reinterpret_cast<uint8_t *>(CMemory::MAP_LAST))
+	{
+		byte = GetAddress[Address & 0xffff];
+		addCyclesInMemoryAccess(speed);
 		return byte;
 	}
 
-	switch ((intptr_t) GetAddress)
+	switch (reinterpret_cast<intptr_t>(GetAddress))
 	{
 		case CMemory::MAP_CPU:
 			byte = S9xGetCPU(Address & 0xffff);
-			addCyclesInMemoryAccess;
+			addCyclesInMemoryAccess(speed);
 			return byte;
 
 		case CMemory::MAP_PPU:
@@ -255,7 +251,7 @@
 				return OpenBus;
 
 			byte = S9xGetPPU(Address & 0xffff);
-			addCyclesInMemoryAccess;
+			addCyclesInMemoryAccess(speed);
 			return byte;
 
 		case CMemory::MAP_LOROM_SRAM:
@@ -264,80 +260,29 @@
 			// Address & 0xff0000 : bank
 			// bank >> 1 | offset : SRAM address, unbound
 			// unbound & SRAMMask : SRAM offset
-			byte = *(Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask));
-			addCyclesInMemoryAccess;
-			return byte;
-
-		case CMemory::MAP_LOROM_SRAM_B:
-			byte = *(Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB));
-			addCyclesInMemoryAccess;
+			byte = Memory.SRAM[(((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask];
+			addCyclesInMemoryAccess(speed);
 			return byte;
 
 		case CMemory::MAP_HIROM_SRAM:
 		case CMemory::MAP_RONLY_SRAM:
-			byte = *(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask));
-			addCyclesInMemoryAccess;
+			byte = Memory.SRAM[((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask];
+			addCyclesInMemoryAccess(speed);
 			return byte;
 
-		case CMemory::MAP_BWRAM:
-			byte = *(Memory.BWRAM + ((Address & 0x7fff) - 0x6000));
-			addCyclesInMemoryAccess;
-			return byte;
-
-		/*case CMemory::MAP_DSP:
-			byte = S9xGetDSP(Address & 0xffff);
-			addCyclesInMemoryAccess;
-			return byte;
-
-		case CMemory::MAP_SPC7110_ROM:
-			byte = S9xGetSPC7110Byte(Address);
-			addCyclesInMemoryAccess;
-			return byte;
-
-		case CMemory::MAP_SPC7110_DRAM:
-			byte = S9xGetSPC7110(0x4800);
-			addCyclesInMemoryAccess;
-			return byte;
-
-		case CMemory::MAP_C4:
-			byte = S9xGetC4(Address & 0xffff);
-			addCyclesInMemoryAccess;
-			return byte;
-
-		case CMemory::MAP_OBC_RAM:
-			byte = S9xGetOBC1(Address & 0xffff);
-			addCyclesInMemoryAccess;
-			return byte;
-
-		case CMemory::MAP_SETA_DSP:
-			byte = S9xGetSetaDSP(Address);
-			addCyclesInMemoryAccess;
-			return byte;
-
-		case CMemory::MAP_SETA_RISC:
-			byte = S9xGetST018(Address);
-			addCyclesInMemoryAccess;
-			return byte;
-
-		case CMemory::MAP_BSX:
-			byte = S9xGetBSX(Address);
-			addCyclesInMemoryAccess;
-			return byte;*/
-
-		case CMemory::MAP_NONE:
 		default:
 			byte = OpenBus;
-			addCyclesInMemoryAccess;
+			addCyclesInMemoryAccess(speed);
 			return byte;
 	}
 }
 
-inline uint16_t S9xGetWord (uint32_t Address, enum s9xwrap_t w = WRAP_NONE)
-{
-	uint32_t	mask = MEMMAP_MASK & (w == WRAP_PAGE ? 0xff : (w == WRAP_BANK ? 0xffff : 0xffffff));
+inline uint16_t S9xGetWord(uint32_t Address, s9xwrap_t w = WRAP_NONE)
+{
+	uint32_t mask = MEMMAP_MASK & (w == WRAP_PAGE ? 0xff : (w == WRAP_BANK ? 0xffff : 0xffffff));
 	if ((Address & mask) == mask)
 	{
-		PC_t	a;
+		PC_t a;
 
 		OpenBus = S9xGetByte(Address);
 
@@ -345,39 +290,38 @@
 		{
 			case WRAP_PAGE:
 				a.xPBPC = Address;
-				a.B.xPCl++;
+				++a.B.xPCl;
 				return OpenBus | (S9xGetByte(a.xPBPC) << 8);
 
 			case WRAP_BANK:
 				a.xPBPC = Address;
-				a.W.xPC++;
+				++a.W.xPC;
 				return OpenBus | (S9xGetByte(a.xPBPC) << 8);
 
-			case WRAP_NONE:
 			default:
 				return OpenBus | (S9xGetByte(Address + 1) << 8);
 		}
 	}
 
-	int		block = (Address & 0xffffff) >> MEMMAP_SHIFT;
-	uint8_t	*GetAddress = Memory.Map[block];
-	int32_t	speed = memory_speed(Address);
-	uint16_t	word;
-
-	if (GetAddress >= (uint8_t *) CMemory::MAP_LAST)
-	{
-		word = READ_WORD(GetAddress + (Address & 0xffff));
-		addCyclesInMemoryAccess_x2;
+	int block = (Address & 0xffffff) >> MEMMAP_SHIFT;
+	uint8_t *GetAddress = Memory.Map[block];
+	int32_t speed = memory_speed(Address);
+	uint16_t word;
+
+	if (GetAddress >= reinterpret_cast<uint8_t *>(CMemory::MAP_LAST))
+	{
+		word = READ_WORD(&GetAddress[Address & 0xffff]);
+		addCyclesInMemoryAccess_x2(speed);
 		return word;
 	}
 
-	switch ((intptr_t) GetAddress)
+	switch (reinterpret_cast<intptr_t>(GetAddress))
 	{
 		case CMemory::MAP_CPU:
 			word  = S9xGetCPU(Address & 0xffff);
-			addCyclesInMemoryAccess;
+			addCyclesInMemoryAccess(speed);
 			word |= S9xGetCPU((Address + 1) & 0xffff) << 8;
-			addCyclesInMemoryAccess;
+			addCyclesInMemoryAccess(speed);
 			return word;
 
 		case CMemory::MAP_PPU:
@@ -388,644 +332,313 @@
 			}
 
 			word  = S9xGetPPU(Address & 0xffff);
-			addCyclesInMemoryAccess;
+			addCyclesInMemoryAccess(speed);
 			word |= S9xGetPPU((Address + 1) & 0xffff) << 8;
-			addCyclesInMemoryAccess;
-			return (word);
+			addCyclesInMemoryAccess(speed);
+			return word;
 
 		case CMemory::MAP_LOROM_SRAM:
 		case CMemory::MAP_SA1RAM:
 			if (Memory.SRAMMask >= MEMMAP_MASK)
-				word = READ_WORD(Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask));
+				word = READ_WORD(&Memory.SRAM[(((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask]);
 			else
-				word = (*(Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask))) |
-					  ((*(Memory.SRAM + (((((Address + 1) & 0xff0000) >> 1) | ((Address + 1) & 0x7fff)) & Memory.SRAMMask))) << 8);
-			addCyclesInMemoryAccess_x2;
-			return word;
-
-		case CMemory::MAP_LOROM_SRAM_B:
-			if (Multi.sramMaskB >= MEMMAP_MASK)
-				word = READ_WORD(Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB));
-			else
-				word = (*(Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB))) |
-					  ((*(Multi.sramB + (((((Address + 1) & 0xff0000) >> 1) | ((Address + 1) & 0x7fff)) & Multi.sramMaskB))) << 8);
-			addCyclesInMemoryAccess_x2;
+				word = Memory.SRAM[(((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask] |
+					(Memory.SRAM[((((Address + 1) & 0xff0000) >> 1) | ((Address + 1) & 0x7fff)) & Memory.SRAMMask] << 8);
+			addCyclesInMemoryAccess_x2(speed);
 			return word;
 
 		case CMemory::MAP_HIROM_SRAM:
 		case CMemory::MAP_RONLY_SRAM:
 			if (Memory.SRAMMask >= MEMMAP_MASK)
-				word = READ_WORD(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask));
+				word = READ_WORD(&Memory.SRAM[((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask]);
 			else
-				word = (*(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask)) |
-					   (*(Memory.SRAM + ((((Address + 1) & 0x7fff) - 0x6000 + (((Address + 1) & 0xf0000) >> 3)) & Memory.SRAMMask)) << 8));
-			addCyclesInMemoryAccess_x2;
+				word = Memory.SRAM[((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask] |
+					(Memory.SRAM[(((Address + 1) & 0x7fff) - 0x6000 + (((Address + 1) & 0xf0000) >> 3)) & Memory.SRAMMask] << 8);
+			addCyclesInMemoryAccess_x2(speed);
 			return word;
 
-		case CMemory::MAP_BWRAM:
-			word = READ_WORD(Memory.BWRAM + ((Address & 0x7fff) - 0x6000));
-			addCyclesInMemoryAccess_x2;
-			return word;
-
-		/*case CMemory::MAP_DSP:
-			word  = S9xGetDSP(Address & 0xffff);
-			addCyclesInMemoryAccess;
-			word |= S9xGetDSP((Address + 1) & 0xffff) << 8;
-			addCyclesInMemoryAccess;
-			return word;
-
-		case CMemory::MAP_SPC7110_ROM:
-			word  = S9xGetSPC7110Byte(Address);
-			addCyclesInMemoryAccess;
-			word |= S9xGetSPC7110Byte(Address + 1) << 8;
-			addCyclesInMemoryAccess;
-			return word;
-
-		case CMemory::MAP_SPC7110_DRAM:
-			word  = S9xGetSPC7110(0x4800);
-			addCyclesInMemoryAccess;
-			word |= S9xGetSPC7110(0x4800) << 8;
-			addCyclesInMemoryAccess;
-			return word;
-
-		case CMemory::MAP_C4:
-			word  = S9xGetC4(Address & 0xffff);
-			addCyclesInMemoryAccess;
-			word |= S9xGetC4((Address + 1) & 0xffff) << 8;
-			addCyclesInMemoryAccess;
-			return word;
-
-		case CMemory::MAP_OBC_RAM:
-			word  = S9xGetOBC1(Address & 0xffff);
-			addCyclesInMemoryAccess;
-			word |= S9xGetOBC1((Address + 1) & 0xffff) << 8;
-			addCyclesInMemoryAccess;
-			return word;
-
-		case CMemory::MAP_SETA_DSP:
-			word  = S9xGetSetaDSP(Address);
-			addCyclesInMemoryAccess;
-			word |= S9xGetSetaDSP(Address + 1) << 8;
-			addCyclesInMemoryAccess;
-			return word;
-
-		case CMemory::MAP_SETA_RISC:
-			word  = S9xGetST018(Address);
-			addCyclesInMemoryAccess;
-			word |= S9xGetST018(Address + 1) << 8;
-			addCyclesInMemoryAccess;
-			return word;
-
-		case CMemory::MAP_BSX:
-			word  = S9xGetBSX(Address);
-			addCyclesInMemoryAccess;
-			word |= S9xGetBSX(Address + 1) << 8;
-			addCyclesInMemoryAccess;
-			return word;*/
-
-		case CMemory::MAP_NONE:
 		default:
 			word = OpenBus | (OpenBus << 8);
-			addCyclesInMemoryAccess_x2;
+			addCyclesInMemoryAccess_x2(speed);
 			return word;
 	}
 }
 
-inline void S9xSetByte (uint8_t Byte, uint32_t Address)
-{
-	int		block = (Address & 0xffffff) >> MEMMAP_SHIFT;
-	uint8_t	*SetAddress = Memory.WriteMap[block];
-	int32_t	speed = memory_speed(Address);
-
-	if (SetAddress >= (uint8_t *) CMemory::MAP_LAST)
-	{
-		*(SetAddress + (Address & 0xffff)) = Byte;
-		addCyclesInMemoryAccess;
+inline void S9xSetByte(uint8_t Byte, uint32_t Address)
+{
+	int block = (Address & 0xffffff) >> MEMMAP_SHIFT;
+	uint8_t *SetAddress = Memory.WriteMap[block];
+	int32_t speed = memory_speed(Address);
+
+	if (SetAddress >= reinterpret_cast<uint8_t *>(CMemory::MAP_LAST))
+	{
+		SetAddress[Address & 0xffff] = Byte;
+		addCyclesInMemoryAccess(speed);
 		return;
 	}
 
-	switch ((intptr_t) SetAddress)
+	switch (reinterpret_cast<intptr_t>(SetAddress))
 	{
 		case CMemory::MAP_CPU:
 			S9xSetCPU(Byte, Address & 0xffff);
-			addCyclesInMemoryAccess;
-			return;
+			addCyclesInMemoryAccess(speed);
+			break;
 
 		case CMemory::MAP_PPU:
 			if (CPU.InDMAorHDMA && (Address & 0xff00) == 0x2100)
 				return;
 
 			S9xSetPPU(Byte, Address & 0xffff);
-			addCyclesInMemoryAccess;
-			return;
+			addCyclesInMemoryAccess(speed);
+			break;
 
 		case CMemory::MAP_LOROM_SRAM:
 			if (Memory.SRAMMask)
-			{
-				*(Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask)) = Byte;
-				CPU.SRAMModified = true;
-			}
-
-			addCyclesInMemoryAccess;
-			return;
-
-		case CMemory::MAP_LOROM_SRAM_B:
-			if (Multi.sramMaskB)
-			{
-				*(Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB)) = Byte;
-				CPU.SRAMModified = true;
-			}
-
-			addCyclesInMemoryAccess;
-			return;
+				Memory.SRAM[(((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask] = Byte;
+
+			addCyclesInMemoryAccess(speed);
+			break;
 
 		case CMemory::MAP_HIROM_SRAM:
 			if (Memory.SRAMMask)
-			{
-				*(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask)) = Byte;
-				CPU.SRAMModified = true;
-			}
-
-			addCyclesInMemoryAccess;
-			return;
-
-		case CMemory::MAP_BWRAM:
-			*(Memory.BWRAM + ((Address & 0x7fff) - 0x6000)) = Byte;
-			CPU.SRAMModified = true;
-			addCyclesInMemoryAccess;
-			return;
+				Memory.SRAM[((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask] = Byte;
+
+			addCyclesInMemoryAccess(speed);
+			break;
 
 		case CMemory::MAP_SA1RAM:
-			*(Memory.SRAM + (Address & 0xffff)) = Byte;
-			addCyclesInMemoryAccess;
-			return;
-
-		/*case CMemory::MAP_DSP:
-			S9xSetDSP(Byte, Address & 0xffff);
-			addCyclesInMemoryAccess;
-			return;
-
-		case CMemory::MAP_C4:
-			S9xSetC4(Byte, Address & 0xffff);
-			addCyclesInMemoryAccess;
-			return;
-
-		case CMemory::MAP_OBC_RAM:
-			S9xSetOBC1(Byte, Address & 0xffff);
-			addCyclesInMemoryAccess;
-			return;
-
-		case CMemory::MAP_SETA_DSP:
-			S9xSetSetaDSP(Byte, Address);
-			addCyclesInMemoryAccess;
-			return;
-
-		case CMemory::MAP_SETA_RISC:
-			S9xSetST018(Byte, Address);
-			addCyclesInMemoryAccess;
-			return;
-
-		case CMemory::MAP_BSX:
-			S9xSetBSX(Byte, Address);
-			addCyclesInMemoryAccess;
-			return;*/
-
-		case CMemory::MAP_NONE:
+			Memory.SRAM[Address & 0xffff] = Byte;
+			addCyclesInMemoryAccess(speed);
+			break;
+
 		default:
-			addCyclesInMemoryAccess;
-			return;
-	}
-}
-
-inline void S9xSetWord (uint16_t Word, uint32_t Address, enum s9xwrap_t w = WRAP_NONE, enum s9xwriteorder_t o = WRITE_01)
-{
-	uint32_t	mask = MEMMAP_MASK & (w == WRAP_PAGE ? 0xff : (w == WRAP_BANK ? 0xffff : 0xffffff));
+			addCyclesInMemoryAccess(speed);
+	}
+}
+
+inline void S9xSetWord(uint16_t Word, uint32_t Address, s9xwrap_t w = WRAP_NONE, s9xwriteorder_t o = WRITE_01)
+{
+	uint32_t mask = MEMMAP_MASK & (w == WRAP_PAGE ? 0xff : (w == WRAP_BANK ? 0xffff : 0xffffff));
 	if ((Address & mask) == mask)
 	{
-		PC_t	a;
+		PC_t a;
 
 		if (!o)
-			S9xSetByte((uint8_t) Word, Address);
+			S9xSetByte(static_cast<uint8_t>(Word), Address);
 
 		switch (w)
 		{
 			case WRAP_PAGE:
 				a.xPBPC = Address;
-				a.B.xPCl++;
+				++a.B.xPCl;
 				S9xSetByte(Word >> 8, a.xPBPC);
 				break;
 
 			case WRAP_BANK:
 				a.xPBPC = Address;
-				a.W.xPC++;
+				++a.W.xPC;
 				S9xSetByte(Word >> 8, a.xPBPC);
 				break;
 
-			case WRAP_NONE:
 			default:
 				S9xSetByte(Word >> 8, Address + 1);
-				break;
 		}
 
 		if (o)
-			S9xSetByte((uint8_t) Word, Address);
+			S9xSetByte(static_cast<uint8_t>(Word), Address);
 
 		return;
 	}
 
-	int		block = (Address & 0xffffff) >> MEMMAP_SHIFT;
-	uint8_t	*SetAddress = Memory.WriteMap[block];
-	int32_t	speed = memory_speed(Address);
-
-	if (SetAddress >= (uint8_t *) CMemory::MAP_LAST)
-	{
-		WRITE_WORD(SetAddress + (Address & 0xffff), Word);
-		addCyclesInMemoryAccess_x2;
+	int block = (Address & 0xffffff) >> MEMMAP_SHIFT;
+	uint8_t *SetAddress = Memory.WriteMap[block];
+	int32_t speed = memory_speed(Address);
+
+	if (SetAddress >= reinterpret_cast<uint8_t *>(CMemory::MAP_LAST))
+	{
+		WRITE_WORD(&SetAddress[Address & 0xffff], Word);
+		addCyclesInMemoryAccess_x2(speed);
 		return;
 	}
 
-	switch ((intptr_t) SetAddress)
+	switch (reinterpret_cast<intptr_t>(SetAddress))
 	{
 		case CMemory::MAP_CPU:
 			if (o)
 			{
 				S9xSetCPU(Word >> 8, (Address + 1) & 0xffff);
-				addCyclesInMemoryAccess;
-				S9xSetCPU((uint8_t) Word, Address & 0xffff);
-				addCyclesInMemoryAccess;
-				return;
+				addCyclesInMemoryAccess(speed);
+				S9xSetCPU(static_cast<uint8_t>(Word), Address & 0xffff);
+				addCyclesInMemoryAccess(speed);
 			}
 			else
 			{
-				S9xSetCPU((uint8_t) Word, Address & 0xffff);
-				addCyclesInMemoryAccess;
+				S9xSetCPU(static_cast<uint8_t>(Word), Address & 0xffff);
+				addCyclesInMemoryAccess(speed);
 				S9xSetCPU(Word >> 8, (Address + 1) & 0xffff);
-				addCyclesInMemoryAccess;
-				return;
-			}
+				addCyclesInMemoryAccess(speed);
+			}
+			break;
 
 		case CMemory::MAP_PPU:
 			if (CPU.InDMAorHDMA)
 			{
 				if ((Address & 0xff00) != 0x2100)
-					S9xSetPPU((uint8_t) Word, Address & 0xffff);
+					S9xSetPPU(static_cast<uint8_t>(Word), Address & 0xffff);
 				if (((Address + 1) & 0xff00) != 0x2100)
 					S9xSetPPU(Word >> 8, (Address + 1) & 0xffff);
-				return;
+				break;
 			}
 
 			if (o)
 			{
 				S9xSetPPU(Word >> 8, (Address + 1) & 0xffff);
-				addCyclesInMemoryAccess;
-				S9xSetPPU((uint8_t) Word, Address & 0xffff);
-				addCyclesInMemoryAccess;
-				return;
+				addCyclesInMemoryAccess(speed);
+				S9xSetPPU(static_cast<uint8_t>(Word), Address & 0xffff);
+				addCyclesInMemoryAccess(speed);
 			}
 			else
 			{
-				S9xSetPPU((uint8_t) Word, Address & 0xffff);
-				addCyclesInMemoryAccess;
+				S9xSetPPU(static_cast<uint8_t>(Word), Address & 0xffff);
+				addCyclesInMemoryAccess(speed);
 				S9xSetPPU(Word >> 8, (Address + 1) & 0xffff);
-				addCyclesInMemoryAccess;
-				return;
-			}
+				addCyclesInMemoryAccess(speed);
+			}
+			break;
 
 		case CMemory::MAP_LOROM_SRAM:
 			if (Memory.SRAMMask)
 			{
 				if (Memory.SRAMMask >= MEMMAP_MASK)
-					WRITE_WORD(Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask), Word);
+					WRITE_WORD(&Memory.SRAM[(((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask], Word);
 				else
 				{
-					*(Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask)) = (uint8_t) Word;
-					*(Memory.SRAM + (((((Address + 1) & 0xff0000) >> 1) | ((Address + 1) & 0x7fff)) & Memory.SRAMMask)) = Word >> 8;
+					Memory.SRAM[(((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask] = static_cast<uint8_t>(Word);
+					Memory.SRAM[((((Address + 1) & 0xff0000) >> 1) | ((Address + 1) & 0x7fff)) & Memory.SRAMMask] = Word >> 8;
 				}
-
-				CPU.SRAMModified = true;
-			}
-
-			addCyclesInMemoryAccess_x2;
-			return;
-
-		case CMemory::MAP_LOROM_SRAM_B:
-			if (Multi.sramMaskB)
-			{
-				if (Multi.sramMaskB >= MEMMAP_MASK)
-					WRITE_WORD(Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB), Word);
+			}
+
+			addCyclesInMemoryAccess_x2(speed);
+			break;
+
+		case CMemory::MAP_HIROM_SRAM:
+			if (Memory.SRAMMask)
+			{
+				if (Memory.SRAMMask >= MEMMAP_MASK)
+					WRITE_WORD(&Memory.SRAM[((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask], Word);
 				else
 				{
-					*(Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB)) = (uint8_t) Word;
-					*(Multi.sramB + (((((Address + 1) & 0xff0000) >> 1) | ((Address + 1) & 0x7fff)) & Multi.sramMaskB)) = Word >> 8;
+					Memory.SRAM[((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask] = static_cast<uint8_t>(Word);
+					Memory.SRAM[(((Address + 1) & 0x7fff) - 0x6000 + (((Address + 1) & 0xf0000) >> 3)) & Memory.SRAMMask] = Word >> 8;
 				}
-
-				CPU.SRAMModified = true;
-			}
-
-			addCyclesInMemoryAccess_x2;
-			return;
-
-		case CMemory::MAP_HIROM_SRAM:
-			if (Memory.SRAMMask)
-			{
-				if (Memory.SRAMMask >= MEMMAP_MASK)
-					WRITE_WORD(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask), Word);
-				else
-				{
-					*(Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask)) = (uint8_t) Word;
-					*(Memory.SRAM + ((((Address + 1) & 0x7fff) - 0x6000 + (((Address + 1) & 0xf0000) >> 3)) & Memory.SRAMMask)) = Word >> 8;
-				}
-
-				CPU.SRAMModified = true;
-			}
-
-			addCyclesInMemoryAccess_x2;
-			return;
-
-		case CMemory::MAP_BWRAM:
-			WRITE_WORD(Memory.BWRAM + ((Address & 0x7fff) - 0x6000), Word);
-			CPU.SRAMModified = true;
-			addCyclesInMemoryAccess_x2;
-			return;
+			}
+
+			addCyclesInMemoryAccess_x2(speed);
+			break;
 
 		case CMemory::MAP_SA1RAM:
-			WRITE_WORD(Memory.SRAM + (Address & 0xffff), Word);
-			addCyclesInMemoryAccess_x2;
-			return;
-
-		/*case CMemory::MAP_DSP:
-			if (o)
-			{
-				S9xSetDSP(Word >> 8, (Address + 1) & 0xffff);
-				addCyclesInMemoryAccess;
-				S9xSetDSP((uint8_t) Word, Address & 0xffff);
-				addCyclesInMemoryAccess;
-				return;
-			}
-			else
-			{
-				S9xSetDSP((uint8_t) Word, Address & 0xffff);
-				addCyclesInMemoryAccess;
-				S9xSetDSP(Word >> 8, (Address + 1) & 0xffff);
-				addCyclesInMemoryAccess;
-				return;
-			}
-
-		case CMemory::MAP_C4:
-			if (o)
-			{
-				S9xSetC4(Word >> 8, (Address + 1) & 0xffff);
-				addCyclesInMemoryAccess;
-				S9xSetC4((uint8_t) Word, Address & 0xffff);
-				addCyclesInMemoryAccess;
-				return;
-			}
-			else
-			{
-				S9xSetC4((uint8_t) Word, Address & 0xffff);
-				addCyclesInMemoryAccess;
-				S9xSetC4(Word >> 8, (Address + 1) & 0xffff);
-				addCyclesInMemoryAccess;
-				return;
-			}
-
-		case CMemory::MAP_OBC_RAM:
-			if (o)
-			{
-				S9xSetOBC1(Word >> 8, (Address + 1) & 0xffff);
-				addCyclesInMemoryAccess;
-				S9xSetOBC1((uint8_t) Word, Address & 0xffff);
-				addCyclesInMemoryAccess;
-				return;
-			}
-			else
-			{
-				S9xSetOBC1((uint8_t) Word, Address & 0xffff);
-				addCyclesInMemoryAccess;
-				S9xSetOBC1(Word >> 8, (Address + 1) & 0xffff);
-				addCyclesInMemoryAccess;
-				return;
-			}
-
-		case CMemory::MAP_SETA_DSP:
-			if (o)
-			{
-				S9xSetSetaDSP(Word >> 8, Address + 1);
-				addCyclesInMemoryAccess;
-				S9xSetSetaDSP((uint8_t) Word, Address);
-				addCyclesInMemoryAccess;
-				return;
-			}
-			else
-			{
-				S9xSetSetaDSP((uint8_t) Word, Address);
-				addCyclesInMemoryAccess;
-				S9xSetSetaDSP(Word >> 8, Address + 1);
-				addCyclesInMemoryAccess;
-				return;
-			}
-
-		case CMemory::MAP_SETA_RISC:
-			if (o)
-			{
-				S9xSetST018(Word >> 8, Address + 1);
-				addCyclesInMemoryAccess;
-				S9xSetST018((uint8_t) Word, Address);
-				addCyclesInMemoryAccess;
-				return;
-			}
-			else
-			{
-				S9xSetST018((uint8_t) Word, Address);
-				addCyclesInMemoryAccess;
-				S9xSetST018(Word >> 8, Address + 1);
-				addCyclesInMemoryAccess;
-				return;
-			}
-
-		case CMemory::MAP_BSX:
-			if (o)
-			{
-				S9xSetBSX(Word >> 8, Address + 1);
-				addCyclesInMemoryAccess;
-				S9xSetBSX((uint8_t) Word, Address);
-				addCyclesInMemoryAccess;
-				return;
-			}
-			else
-			{
-				S9xSetBSX((uint8_t) Word, Address);
-				addCyclesInMemoryAccess;
-				S9xSetBSX(Word >> 8, Address + 1);
-				addCyclesInMemoryAccess;
-				return;
-			}*/
-
-		case CMemory::MAP_NONE:
+			WRITE_WORD(&Memory.SRAM[Address & 0xffff], Word);
+			addCyclesInMemoryAccess_x2(speed);
+			break;
+
 		default:
-			addCyclesInMemoryAccess_x2;
-			return;
-	}
-}
-
-inline void S9xSetPCBase (uint32_t Address)
-{
-	Registers.PBPC = Address & 0xffffff;
+			addCyclesInMemoryAccess_x2(speed);
+	}
+}
+
+inline void S9xSetPCBase(uint32_t Address)
+{
+	Registers.PC.xPBPC = Address & 0xffffff;
 	ICPU.ShiftedPB = Address & 0xff0000;
 
-	int		block;
-	uint8_t	*GetAddress = Memory.Map[block = ((Address & 0xffffff) >> MEMMAP_SHIFT)];
+	int block;
+	uint8_t *GetAddress = Memory.Map[block = ((Address & 0xffffff) >> MEMMAP_SHIFT)];
 
 	CPU.MemSpeed = memory_speed(Address);
 	CPU.MemSpeedx2 = CPU.MemSpeed << 1;
 
-	if (GetAddress >= (uint8_t *) CMemory::MAP_LAST)
+	if (GetAddress >= reinterpret_cast<uint8_t *>(CMemory::MAP_LAST))
 	{
 		CPU.PCBase = GetAddress;
 		return;
 	}
 
-	switch ((intptr_t) GetAddress)
+	switch (reinterpret_cast<intptr_t>(GetAddress))
 	{
 		case CMemory::MAP_LOROM_SRAM:
 			if ((Memory.SRAMMask & MEMMAP_MASK) != MEMMAP_MASK)
-				CPU.PCBase = NULL;
+				CPU.PCBase = nullptr;
 			else
-				CPU.PCBase = Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask) - (Address & 0xffff);
-			return;
-
-		case CMemory::MAP_LOROM_SRAM_B:
-			if ((Multi.sramMaskB & MEMMAP_MASK) != MEMMAP_MASK)
-				CPU.PCBase = NULL;
-			else
-				CPU.PCBase = Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB) - (Address & 0xffff);
-			return;
+				CPU.PCBase = &Memory.SRAM[((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask) - (Address & 0xffff)];
+			break;
 
 		case CMemory::MAP_HIROM_SRAM:
 			if ((Memory.SRAMMask & MEMMAP_MASK) != MEMMAP_MASK)
-				CPU.PCBase = NULL;
+				CPU.PCBase = nullptr;
 			else
-				CPU.PCBase = Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask) - (Address & 0xffff);
-			return;
-
-		case CMemory::MAP_BWRAM:
-			CPU.PCBase = Memory.BWRAM - 0x6000 - (Address & 0x8000);
-			return;
+				CPU.PCBase = &Memory.SRAM[(((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask) - (Address & 0xffff)];
+			break;
 
 		case CMemory::MAP_SA1RAM:
-			CPU.PCBase = Memory.SRAM;
-			return;
-
-		/*case CMemory::MAP_SPC7110_ROM:
-			CPU.PCBase = S9xGetBasePointerSPC7110(Address);
-			return;
-
-		case CMemory::MAP_C4:
-			CPU.PCBase = S9xGetBasePointerC4(Address & 0xffff);
-			return;
-
-		case CMemory::MAP_OBC_RAM:
-			CPU.PCBase = S9xGetBasePointerOBC1(Address & 0xffff);
-			return;
-
-		case CMemory::MAP_BSX:
-			CPU.PCBase = S9xGetBasePointerBSX(Address);
-			return;*/
-
-		case CMemory::MAP_NONE:
+			CPU.PCBase = &Memory.SRAM[0];
+			break;
+
 		default:
-			CPU.PCBase = NULL;
-			return;
-	}
-}
-
-inline uint8_t * S9xGetBasePointer (uint32_t Address)
-{
-	uint8_t	*GetAddress = Memory.Map[(Address & 0xffffff) >> MEMMAP_SHIFT];
-
-	if (GetAddress >= (uint8_t *) CMemory::MAP_LAST)
+			CPU.PCBase = nullptr;
+	}
+}
+
+inline uint8_t *S9xGetBasePointer(uint32_t Address)
+{
+	uint8_t *GetAddress = Memory.Map[(Address & 0xffffff) >> MEMMAP_SHIFT];
+
+	if (GetAddress >= reinterpret_cast<uint8_t *>(CMemory::MAP_LAST))
 		return GetAddress;
 
-	switch ((intptr_t) GetAddress)
+	switch (reinterpret_cast<intptr_t>(GetAddress))
 	{
 		case CMemory::MAP_LOROM_SRAM:
 			if ((Memory.SRAMMask & MEMMAP_MASK) != MEMMAP_MASK)
-				return NULL;
-			return Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask) - (Address & 0xffff);
-
-		case CMemory::MAP_LOROM_SRAM_B:
-			if ((Multi.sramMaskB & MEMMAP_MASK) != MEMMAP_MASK)
-				return NULL;
-			return Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB) - (Address & 0xffff);
+				return nullptr;
+			return &Memory.SRAM[((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask) - (Address & 0xffff)];
 
 		case CMemory::MAP_HIROM_SRAM:
 			if ((Memory.SRAMMask & MEMMAP_MASK) != MEMMAP_MASK)
-				return NULL;
-			return Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask) - (Address & 0xffff);
-
-		case CMemory::MAP_BWRAM:
-			return Memory.BWRAM - 0x6000 - (Address & 0x8000);
+				return nullptr;
+			return &Memory.SRAM[(((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask) - (Address & 0xffff)];
 
 		case CMemory::MAP_SA1RAM:
-			return Memory.SRAM;
-
-		/*case CMemory::MAP_SPC7110_ROM:
-			return S9xGetBasePointerSPC7110(Address);
-
-		case CMemory::MAP_C4:
-			return S9xGetBasePointerC4(Address & 0xffff);
-
-		case CMemory::MAP_OBC_RAM:
-			return S9xGetBasePointerOBC1(Address & 0xffff);*/
-
-		case CMemory::MAP_NONE:
+			return &Memory.SRAM[0];
+
 		default:
-			return NULL;
-	}
-}
-
-inline uint8_t * S9xGetMemPointer (uint32_t Address)
-{
-	uint8_t	*GetAddress = Memory.Map[(Address & 0xffffff) >> MEMMAP_SHIFT];
-
-	if (GetAddress >= (uint8_t *) CMemory::MAP_LAST)
-		return GetAddress + (Address & 0xffff);
-
-	switch ((intptr_t) GetAddress)
+			return nullptr;
+	}
+}
+
+inline uint8_t *S9xGetMemPointer(uint32_t Address)
+{
+	uint8_t *GetAddress = Memory.Map[(Address & 0xffffff) >> MEMMAP_SHIFT];
+
+	if (GetAddress >= reinterpret_cast<uint8_t *>(CMemory::MAP_LAST))
+		return &GetAddress[Address & 0xffff];
+
+	switch (reinterpret_cast<intptr_t>(GetAddress))
 	{
 		case CMemory::MAP_LOROM_SRAM:
 			if ((Memory.SRAMMask & MEMMAP_MASK) != MEMMAP_MASK)
-				return NULL;
-			return Memory.SRAM + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask);
-
-		case CMemory::MAP_LOROM_SRAM_B:
-			if ((Multi.sramMaskB & MEMMAP_MASK) != MEMMAP_MASK)
-				return NULL;
-			return Multi.sramB + ((((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Multi.sramMaskB);
+				return nullptr;
+			return &Memory.SRAM[(((Address & 0xff0000) >> 1) | (Address & 0x7fff)) & Memory.SRAMMask];
 
 		case CMemory::MAP_HIROM_SRAM:
 			if ((Memory.SRAMMask & MEMMAP_MASK) != MEMMAP_MASK)
-				return NULL;
-			return Memory.SRAM + (((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask);
-
-		case CMemory::MAP_BWRAM:
-			return Memory.BWRAM - 0x6000 + (Address & 0x7fff);
+				return nullptr;
+			return &Memory.SRAM[((Address & 0x7fff) - 0x6000 + ((Address & 0xf0000) >> 3)) & Memory.SRAMMask];
 
 		case CMemory::MAP_SA1RAM:
-			return Memory.SRAM + (Address & 0xffff);
-
-		/*case CMemory::MAP_SPC7110_ROM:
-			return S9xGetBasePointerSPC7110(Address) + (Address & 0xffff);
-
-		case CMemory::MAP_C4:
-			return S9xGetMemPointerC4(Address & 0xffff);
-
-		case CMemory::MAP_OBC_RAM:
-			return S9xGetMemPointerOBC1(Address & 0xffff);*/
-
-		case CMemory::MAP_NONE:
+			return &Memory.SRAM[Address & 0xffff];
+
 		default:
-			return NULL;
+			return nullptr;
 	}
 }
 

--- a/src/in_snsf/snes9x/globals.cpp
+++ b/src/in_snsf/snes9x/globals.cpp
@@ -175,147 +175,40 @@
   Nintendo Co., Limited and its subsidiary companies.
  ***********************************************************************************/
 
-
 #include "snes9x.h"
 #include "memmap.h"
 #include "dma.h"
 #include "apu/apu.h"
-//#include "fxinst.h"
-//#include "fxemu.h"
-//#include "srtc.h"
-//#include "cheats.h"
-#ifdef NETPLAY_SUPPORT
-#include "netplay.h"
-#endif
-#ifdef DEBUGGER
-#include "debug.h"
-#include "missing.h"
-#endif
-
-struct SCPUState		CPU;
-struct SICPU			ICPU;
-struct SRegisters		Registers;
-struct SPPU				PPU;
-struct InternalPPU		IPPU;
-struct SDMA				DMA[8];
-struct STimings			Timings;
-/*struct SGFX				GFX;
-struct SBG				BG;
-struct SLineData		LineData[240];
-struct SLineMatrixData	LineMatrixData[240];
-struct SDSP0			DSP0;
-struct SDSP1			DSP1;
-struct SDSP2			DSP2;
-struct SDSP3			DSP3;
-struct SDSP4			DSP4;
-struct SSA1				SA1;
-struct SSA1Registers	SA1Registers;
-struct FxRegs_s			GSU;
-struct FxInfo_s			SuperFX;
-struct SST010			ST010;
-struct SST011			ST011;
-struct SST018			ST018;
-struct SOBC1			OBC1;
-struct SSPC7110Snapshot	s7snap;
-struct SSRTCSnapshot	srtcsnap;
-struct SRTCData			RTCData;
-struct SBSX				BSX;*/
-struct SMulti			Multi;
-struct SSettings		Settings;
-struct SSNESGameFixes	SNESGameFixes;
-#ifdef NETPLAY_SUPPORT
-struct SNetPlay			NetPlay;
-#endif
-#ifdef DEBUGGER
-struct Missing			missing;
-#endif
-/*struct SCheatData		Cheat;
-struct Watch			watches[16];*/
-CMemory					Memory;
-
-//char	String[513];
-uint8_t	OpenBus = 0;
-uint8_t	*HDMAMemPointers[8];
-uint16_t	BlackColourMap[256];
-uint16_t	DirectColourMaps[8][256];
-
-SnesModel	M1SNES = { 1, 3, 2 };
-//SnesModel	M2SNES = { 2, 4, 3 };
-SnesModel	*Model = &M1SNES;
-
-#ifdef GFX_MULTI_FORMAT
-uint32_t	RED_LOW_BIT_MASK           = RED_LOW_BIT_MASK_RGB565;
-uint32_t	GREEN_LOW_BIT_MASK         = GREEN_LOW_BIT_MASK_RGB565;
-uint32_t	BLUE_LOW_BIT_MASK          = BLUE_LOW_BIT_MASK_RGB565;
-uint32_t	RED_HI_BIT_MASK            = RED_HI_BIT_MASK_RGB565;
-uint32_t	GREEN_HI_BIT_MASK          = GREEN_HI_BIT_MASK_RGB565;
-uint32_t	BLUE_HI_BIT_MASK           = BLUE_HI_BIT_MASK_RGB565;
-uint32_t	MAX_RED                    = MAX_RED_RGB565;
-uint32_t	MAX_GREEN                  = MAX_GREEN_RGB565;
-uint32_t	MAX_BLUE                   = MAX_BLUE_RGB565;
-uint32_t	SPARE_RGB_BIT_MASK         = SPARE_RGB_BIT_MASK_RGB565;
-uint32_t	GREEN_HI_BIT               = (MAX_GREEN_RGB565 + 1) >> 1;
-uint32_t	RGB_LOW_BITS_MASK          = (RED_LOW_BIT_MASK_RGB565 | GREEN_LOW_BIT_MASK_RGB565 | BLUE_LOW_BIT_MASK_RGB565);
-uint32_t	RGB_HI_BITS_MASK           = (RED_HI_BIT_MASK_RGB565  | GREEN_HI_BIT_MASK_RGB565  | BLUE_HI_BIT_MASK_RGB565);
-uint32_t	RGB_HI_BITS_MASKx2         = (RED_HI_BIT_MASK_RGB565  | GREEN_HI_BIT_MASK_RGB565  | BLUE_HI_BIT_MASK_RGB565) << 1;
-uint32_t	RGB_REMOVE_LOW_BITS_MASK   = ~RGB_LOW_BITS_MASK;
-uint32_t	FIRST_COLOR_MASK           = FIRST_COLOR_MASK_RGB565;
-uint32_t	SECOND_COLOR_MASK          = SECOND_COLOR_MASK_RGB565;
-uint32_t	THIRD_COLOR_MASK           = THIRD_COLOR_MASK_RGB565;
-uint32_t	ALPHA_BITS_MASK            = ALPHA_BITS_MASK_RGB565;
-uint32_t	FIRST_THIRD_COLOR_MASK     = 0;
-uint32_t	TWO_LOW_BITS_MASK          = 0;
-uint32_t	HIGH_BITS_SHIFTED_TWO_MASK = 0;
-#endif
-
-uint16_t SignExtend[2] =
+
+SCPUState CPU;
+SICPU ICPU;
+SRegisters Registers;
+SPPU PPU;
+InternalPPU IPPU;
+SDMA DMA[8];
+STimings Timings;
+SSettings Settings;
+SSNESGameFixes SNESGameFixes;
+CMemory Memory;
+
+uint8_t OpenBus = 0;
+uint8_t *HDMAMemPointers[8];
+
+SnesModel M1SNES = { 1, 3, 2 };
+SnesModel *Model = &M1SNES;
+
+uint16_t SignExtend[] =
 {
 	0x0000,
 	0xff00
 };
 
-int HDMA_ModeByteCounts[8] =
+int HDMA_ModeByteCounts[] =
 {
 	1, 2, 2, 4, 4, 4, 2, 4
 };
 
-/*uint8_t mul_brightness[16][32] =
-{
-	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
-	{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
-	  0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02 },
-	{ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02,
-	  0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04 },
-	{ 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03,
-	  0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06 },
-	{ 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04,
-	  0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08 },
-	{ 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05,
-	  0x05, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x0a, 0x0a, 0x0a },
-	{ 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06,
-	  0x06, 0x07, 0x07, 0x08, 0x08, 0x08, 0x09, 0x09, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0c, 0x0c, 0x0c },
-	{ 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x07, 0x07,
-	  0x07, 0x08, 0x08, 0x09, 0x09, 0x0a, 0x0a, 0x0b, 0x0b, 0x0c, 0x0c, 0x0d, 0x0d, 0x0e, 0x0e, 0x0e },
-	{ 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 0x04, 0x05, 0x05, 0x06, 0x06, 0x07, 0x07, 0x08,
-	  0x09, 0x09, 0x0a, 0x0a, 0x0b, 0x0b, 0x0c, 0x0c, 0x0d, 0x0d, 0x0e, 0x0e, 0x0f, 0x0f, 0x10, 0x11 },
-	{ 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x04, 0x04, 0x05, 0x05, 0x06, 0x07, 0x07, 0x08, 0x08, 0x09,
-	  0x0a, 0x0a, 0x0b, 0x0b, 0x0c, 0x0d, 0x0d, 0x0e, 0x0e, 0x0f, 0x10, 0x10, 0x11, 0x11, 0x12, 0x13 },
-	{ 0x00, 0x01, 0x01, 0x02, 0x03, 0x03, 0x04, 0x05, 0x05, 0x06, 0x07, 0x07, 0x08, 0x09, 0x09, 0x0a,
-	  0x0b, 0x0b, 0x0c, 0x0d, 0x0d, 0x0e, 0x0f, 0x0f, 0x10, 0x11, 0x11, 0x12, 0x13, 0x13, 0x14, 0x15 },
-	{ 0x00, 0x01, 0x01, 0x02, 0x03, 0x04, 0x04, 0x05, 0x06, 0x07, 0x07, 0x08, 0x09, 0x0a, 0x0a, 0x0b,
-	  0x0c, 0x0c, 0x0d, 0x0e, 0x0f, 0x0f, 0x10, 0x11, 0x12, 0x12, 0x13, 0x14, 0x15, 0x15, 0x16, 0x17 },
-	{ 0x00, 0x01, 0x02, 0x02, 0x03, 0x04, 0x05, 0x06, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0a, 0x0b, 0x0c,
-	  0x0d, 0x0e, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x12, 0x13, 0x14, 0x15, 0x16, 0x16, 0x17, 0x18, 0x19 },
-	{ 0x00, 0x01, 0x02, 0x03, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0a, 0x0b, 0x0c, 0x0d,
-	  0x0e, 0x0f, 0x10, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x17, 0x18, 0x19, 0x1a, 0x1b },
-	{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
-	  0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d },
-	{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-	  0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }
-};*/
-
-uint8_t S9xOpLengthsM0X0[256] =
+uint8_t S9xOpLengthsM0X0[] =
 {
 //  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
 	2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 0
@@ -336,7 +229,7 @@
 	2, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4  // F
 };
 
-uint8_t S9xOpLengthsM0X1[256] =
+uint8_t S9xOpLengthsM0X1[] =
 {
 //  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
 	2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4, // 0
@@ -357,7 +250,7 @@
 	2, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4  // F
 };
 
-uint8_t S9xOpLengthsM1X0[256] =
+uint8_t S9xOpLengthsM1X0[] =
 {
 //  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
 	2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 0
@@ -378,7 +271,7 @@
 	2, 2, 2, 2, 3, 2, 2, 2, 1, 3, 1, 1, 3, 3, 3, 4  // F
 };
 
-uint8_t S9xOpLengthsM1X1[256] =
+uint8_t S9xOpLengthsM1X1[] =
 {
 //  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
 	2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 1, 1, 3, 3, 3, 4, // 0

--- a/src/in_snsf/snes9x/memmap.cpp
+++ b/src/in_snsf/snes9x/memmap.cpp
@@ -175,718 +175,17 @@
   Nintendo Co., Limited and its subsidiary companies.
  ***********************************************************************************/
 
+#include <vector>
 #include <algorithm>
 #include <string>
 #include <numeric>
-#include <assert.h>
-
-#ifdef UNZIP_SUPPORT
-#include "unzip/unzip.h"
-#endif
-
-#ifdef JMA_SUPPORT
-#include "jma/s9x-jma.h"
-#endif
-
+#include <cassert>
 #include "snes9x.h"
 #include "memmap.h"
 #include "apu/apu.h"
-//#include "fxemu.h"
 #include "sdd1.h"
-//#include "srtc.h"
-//#include "controls.h"
-//#include "cheats.h"
-//#include "movie.h"
-//#include "reader.h"
-//#include "display.h"
-
-/*#ifndef SET_UI_COLOR
-#define SET_UI_COLOR(r, g, b) ;
-#endif*/
-
-/*#ifndef max
-#define max(a, b) (((a) > (b)) ? (a) : (b))
-#endif*/
-
-/*#ifndef min
-#define min(a, b) (((a) < (b)) ? (a) : (b))
-#endif*/
-
-//static bool	stopMovie = true;
-//static char		LastRomFilename[PATH_MAX + 1] = "";
-
-// from NSRT
-/*static const char	*nintendo_licensees[] =
-{
-	"Unlicensed",
-	"Nintendo",
-	"Rocket Games/Ajinomoto",
-	"Imagineer-Zoom",
-	"Gray Matter",
-	"Zamuse",
-	"Falcom",
-	NULL,
-	"Capcom",
-	"Hot B Co.",
-	"Jaleco",
-	"Coconuts Japan",
-	"Coconuts Japan/G.X.Media",
-	"Micronet",
-	"Technos",
-	"Mebio Software",
-	"Shouei System",
-	"Starfish",
-	NULL,
-	"Mitsui Fudosan/Dentsu",
-	NULL,
-	"Warashi Inc.",
-	NULL,
-	"Nowpro",
-	NULL,
-	"Game Village",
-	"IE Institute",
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	"Banarex",
-	"Starfish",
-	"Infocom",
-	"Electronic Arts Japan",
-	NULL,
-	"Cobra Team",
-	"Human/Field",
-	"KOEI",
-	"Hudson Soft",
-	"S.C.P./Game Village",
-	"Yanoman",
-	NULL,
-	"Tecmo Products",
-	"Japan Glary Business",
-	"Forum/OpenSystem",
-	"Virgin Games (Japan)",
-	"SMDE",
-	"Yojigen",
-	NULL,
-	"Daikokudenki",
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	"Creatures Inc.",
-	"TDK Deep Impresion",
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	"Destination Software/KSS",
-	"Sunsoft/Tokai Engineering",
-	"POW (Planning Office Wada)/VR 1 Japan",
-	"Micro World",
-	NULL,
-	"San-X",
-	"Enix",
-	"Loriciel/Electro Brain",
-	"Kemco Japan",
-	"Seta Co.,Ltd.",
-	"Culture Brain",
-	"Irem Corp.",
-	"Palsoft",
-	"Visit Co., Ltd.",
-	"Intec",
-	"System Sacom",
-	"Poppo",
-	"Ubisoft Japan",
-	NULL,
-	"Media Works",
-	"NEC InterChannel",
-	"Tam",
-	"Gajin/Jordan",
-	"Smilesoft",
-	NULL,
-	NULL,
-	"Mediakite",
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	"Viacom",
-	"Carrozzeria",
-	"Dynamic",
-	NULL,
-	"Magifact",
-	"Hect",
-	"Codemasters",
-	"Taito/GAGA Communications",
-	"Laguna",
-	"Telstar Fun & Games/Event/Taito",
-	NULL,
-	"Arcade Zone Ltd.",
-	"Entertainment International/Empire Software",
-	"Loriciel",
-	"Gremlin Graphics",
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	"Seika Corp.",
-	"UBI SOFT Entertainment Software",
-	"Sunsoft US",
-	NULL,
-	"Life Fitness",
-	NULL,
-	"System 3",
-	"Spectrum Holobyte",
-	NULL,
-	"Irem",
-	NULL,
-	"Raya Systems",
-	"Renovation Products",
-	"Malibu Games",
-	NULL,
-	"Eidos/U.S. Gold",
-	"Playmates Interactive",
-	NULL,
-	NULL,
-	"Fox Interactive",
-	"Time Warner Interactive",
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	"Disney Interactive",
-	NULL,
-	"Black Pearl",
-	NULL,
-	"Advanced Productions",
-	NULL,
-	NULL,
-	"GT Interactive",
-	"RARE",
-	"Crave Entertainment",
-	"Absolute Entertainment",
-	"Acclaim",
-	"Activision",
-	"American Sammy",
-	"Take 2/GameTek",
-	"Hi Tech",
-	"LJN Ltd.",
-	NULL,
-	"Mattel",
-	NULL,
-	"Mindscape/Red Orb Entertainment",
-	"Romstar",
-	"Taxan",
-	"Midway/Tradewest",
-	NULL,
-	"American Softworks Corp.",
-	"Majesco Sales Inc.",
-	"3DO",
-	NULL,
-	NULL,
-	"Hasbro",
-	"NewKidCo",
-	"Telegames",
-	"Metro3D",
-	NULL,
-	"Vatical Entertainment",
-	"LEGO Media",
-	NULL,
-	"Xicat Interactive",
-	"Cryo Interactive",
-	NULL,
-	NULL,
-	"Red Storm Entertainment",
-	"Microids",
-	NULL,
-	"Conspiracy/Swing",
-	"Titus",
-	"Virgin Interactive",
-	"Maxis",
-	NULL,
-	"LucasArts Entertainment",
-	NULL,
-	NULL,
-	"Ocean",
-	NULL,
-	"Electronic Arts",
-	NULL,
-	"Laser Beam",
-	NULL,
-	NULL,
-	"Elite Systems",
-	"Electro Brain",
-	"The Learning Company",
-	"BBC",
-	NULL,
-	"Software 2000",
-	NULL,
-	"BAM! Entertainment",
-	"Studio 3",
-	NULL,
-	NULL,
-	NULL,
-	"Classified Games",
-	NULL,
-	"TDK Mediactive",
-	NULL,
-	"DreamCatcher",
-	"JoWood Produtions",
-	"SEGA",
-	"Wannado Edition",
-	"LSP (Light & Shadow Prod.)",
-	"ITE Media",
-	"Infogrames",
-	"Interplay",
-	"JVC (US)",
-	"Parker Brothers",
-	NULL,
-	"SCI (Sales Curve Interactive)/Storm",
-	NULL,
-	NULL,
-	"THQ Software",
-	"Accolade Inc.",
-	"Triffix Entertainment",
-	NULL,
-	"Microprose Software",
-	"Universal Interactive/Sierra/Simon & Schuster",
-	NULL,
-	"Kemco",
-	"Rage Software",
-	"Encore",
-	NULL,
-	"Zoo",
-	"Kiddinx",
-	"Simon & Schuster Interactive",
-	"Asmik Ace Entertainment Inc./AIA",
-	"Empire Interactive",
-	NULL,
-	NULL,
-	"Jester Interactive",
-	NULL,
-	"Rockstar Games",
-	"Scholastic",
-	"Ignition Entertainment",
-	"Summitsoft",
-	"Stadlbauer",
-	NULL,
-	NULL,
-	NULL,
-	"Misawa",
-	"Teichiku",
-	"Namco Ltd.",
-	"LOZC",
-	"KOEI",
-	NULL,
-	"Tokuma Shoten Intermedia",
-	"Tsukuda Original",
-	"DATAM-Polystar",
-	NULL,
-	NULL,
-	"Bullet-Proof Software",
-	"Vic Tokai Inc.",
-	NULL,
-	"Character Soft",
-	"I'Max",
-	"Saurus",
-	NULL,
-	NULL,
-	"General Entertainment",
-	NULL,
-	NULL,
-	"I'Max",
-	"Success",
-	NULL,
-	"SEGA Japan",
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	"Takara",
-	"Chun Soft",
-	"Video System Co., Ltd./McO'River",
-	"BEC",
-	NULL,
-	"Varie",
-	"Yonezawa/S'pal",
-	"Kaneko",
-	NULL,
-	"Victor Interactive Software/Pack-in-Video",
-	"Nichibutsu/Nihon Bussan",
-	"Tecmo",
-	"Imagineer",
-	NULL,
-	NULL,
-	"Nova",
-	"Den'Z",
-	"Bottom Up",
-	NULL,
-	"TGL (Technical Group Laboratory)",
-	NULL,
-	"Hasbro Japan",
-	NULL,
-	"Marvelous Entertainment",
-	NULL,
-	"Keynet Inc.",
-	"Hands-On Entertainment",
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	"Telenet",
-	"Hori",
-	NULL,
-	NULL,
-	"Konami",
-	"K.Amusement Leasing Co.",
-	"Kawada",
-	"Takara",
-	NULL,
-	"Technos Japan Corp.",
-	"JVC (Europe/Japan)/Victor Musical Industries",
-	NULL,
-	"Toei Animation",
-	"Toho",
-	NULL,
-	"Namco",
-	"Media Rings Corp.",
-	"J-Wing",
-	NULL,
-	"Pioneer LDC",
-	"KID",
-	"Mediafactory",
-	NULL,
-	NULL,
-	NULL,
-	"Infogrames Hudson",
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	"Acclaim Japan",
-	"ASCII Co./Nexoft",
-	"Bandai",
-	NULL,
-	"Enix",
-	NULL,
-	"HAL Laboratory/Halken",
-	"SNK",
-	NULL,
-	"Pony Canyon Hanbai",
-	"Culture Brain",
-	"Sunsoft",
-	"Toshiba EMI",
-	"Sony Imagesoft",
-	NULL,
-	"Sammy",
-	"Magical",
-	"Visco",
-	NULL,
-	"Compile",
-	NULL,
-	"MTO Inc.",
-	NULL,
-	"Sunrise Interactive",
-	NULL,
-	"Global A Entertainment",
-	"Fuuki",
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	"Taito",
-	NULL,
-	"Kemco",
-	"Square",
-	"Tokuma Shoten",
-	"Data East",
-	"Tonkin House",
-	NULL,
-	"KOEI",
-	NULL,
-	"Konami/Ultra/Palcom",
-	"NTVIC/VAP",
-	"Use Co., Ltd.",
-	"Meldac",
-	"Pony Canyon (Japan)/FCI (US)",
-	"Angel/Sotsu Agency/Sunrise",
-	"Yumedia/Aroma Co., Ltd.",
-	NULL,
-	NULL,
-	"Boss",
-	"Axela/Crea-Tech",
-	"Sekaibunka-Sha/Sumire kobo/Marigul Management Inc.",
-	"Konami Computer Entertainment Osaka",
-	NULL,
-	NULL,
-	"Enterbrain",
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	"Taito/Disco",
-	"Sofel",
-	"Quest Corp.",
-	"Sigma",
-	"Ask Kodansha",
-	NULL,
-	"Naxat",
-	"Copya System",
-	"Capcom Co., Ltd.",
-	"Banpresto",
-	"TOMY",
-	"Acclaim/LJN Japan",
-	NULL,
-	"NCS",
-	"Human Entertainment",
-	"Altron",
-	"Jaleco",
-	"Gaps Inc.",
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	"Elf",
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	"Jaleco",
-	NULL,
-	"Yutaka",
-	"Varie",
-	"T&ESoft",
-	"Epoch Co., Ltd.",
-	NULL,
-	"Athena",
-	"Asmik",
-	"Natsume",
-	"King Records",
-	"Atlus",
-	"Epic/Sony Records (Japan)",
-	NULL,
-	"IGS (Information Global Service)",
-	NULL,
-	"Chatnoir",
-	"Right Stuff",
-	NULL,
-	"NTT COMWARE",
-	NULL,
-	"Spike",
-	"Konami Computer Entertainment Tokyo",
-	"Alphadream Corp.",
-	NULL,
-	"Sting",
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	"A Wave",
-	"Motown Software",
-	"Left Field Entertainment",
-	"Extreme Entertainment Group",
-	"TecMagik",
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	"Cybersoft",
-	NULL,
-	"Psygnosis",
-	NULL,
-	NULL,
-	"Davidson/Western Tech.",
-	"Unlicensed",
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	"The Game Factory Europe",
-	"Hip Games",
-	"Aspyr",
-	NULL,
-	NULL,
-	"Mastiff",
-	"iQue",
-	"Digital Tainment Pool",
-	"XS Games",
-	"Daiwon",
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	"PCCW Japan",
-	NULL,
-	NULL,
-	"KiKi Co. Ltd.",
-	"Open Sesame Inc.",
-	"Sims",
-	"Broccoli",
-	"Avex",
-	"D3 Publisher",
-	NULL,
-	"Konami Computer Entertainment Japan",
-	NULL,
-	"Square-Enix",
-	"KSG",
-	"Micott & Basara Inc.",
-	NULL,
-	"Orbital Media",
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	"The Game Factory USA",
-	NULL,
-	NULL,
-	"Treasure",
-	"Aruze",
-	"Ertain",
-	"SNK Playmore",
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	"Yojigen"
-};*/
-
-static const uint32_t	crc32Table[256] =
+
+static const uint32_t crc32Table[] =
 {
 	0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
 	0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
@@ -933,316 +232,88 @@
 	0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
 };
 
-//static void S9xDeinterleaveType1 (int, uint8_t *);
-//static void S9xDeinterleaveType2 (int, uint8_t *);
-//static void S9xDeinterleaveGD24 (int, uint8_t *);
-//static bool allASCII (uint8_t *, int);
-//static bool is_SufamiTurbo_BIOS (uint8_t *, uint32_t);
-//static bool is_SufamiTurbo_Cart (uint8_t *, uint32_t);
-//static bool is_SameGame_BIOS (uint8_t *, uint32_t);
-//static bool is_SameGame_Add_On (uint8_t *, uint32_t);
-//static uint32_t caCRC32 (uint8_t *, uint32_t, uint32_t crc32 = 0xffffffff);
-/*static uint32_t ReadUPSPointer (const uint8_t *, unsigned &, unsigned);
-static bool ReadUPSPatch (Reader *, long, int32_t &);
-static long ReadInt (Reader *, unsigned);
-static bool ReadIPSPatch (Reader *, long, int32_t &);*/
-#ifdef UNZIP_SUPPORT
-static int unzFindExtension (unzFile &, const char *, bool restart = true, bool print = true);
-#endif
-
 // deinterleave
 
-static void S9xDeinterleaveType1 (int size, uint8_t *base)
-{
-	//Settings.DisplayColor = BUILD_PIXEL(0, 31, 0);
-	//SET_UI_COLOR(0, 255, 0);
-
-	uint8_t	blocks[256];
-	int		nblocks = size >> 16;
-
-	for (int i = 0; i < nblocks; i++)
+static void S9xDeinterleaveType1(int size, uint8_t *base)
+{
+	uint8_t blocks[256];
+	int nblocks = size >> 16;
+
+	for (int i = 0; i < nblocks; ++i)
 	{
 		blocks[i * 2] = i + nblocks;
 		blocks[i * 2 + 1] = i;
 	}
 
-	uint8_t	*tmp = (uint8_t *) malloc(0x8000);
-	if (tmp)
-	{
-		for (int i = 0; i < nblocks * 2; i++)
-		{
-			for (int j = i; j < nblocks * 2; j++)
+	for (int i = 0; i < nblocks * 2; ++i)
+		for (int j = i; j < nblocks * 2; ++j)
+			if (blocks[j] == i)
 			{
-				if (blocks[j] == i)
-				{
-					memmove(tmp, &base[blocks[j] * 0x8000], 0x8000);
-					memmove(&base[blocks[j] * 0x8000], &base[blocks[i] * 0x8000], 0x8000);
-					memmove(&base[blocks[i] * 0x8000], tmp, 0x8000);
-					uint8_t	b = blocks[j];
-					blocks[j] = blocks[i];
-					blocks[i] = b;
-					break;
-				}
+				std::swap_ranges(&base[blocks[i] * 0x8000], &base[(blocks[i] + 1) * 0x8000], &base[blocks[j] * 0x8000]);
+				std::swap(blocks[i], blocks[j]);
+				break;
 			}
-		}
-
-		free(tmp);
-	}
-}
-
-static void S9xDeinterleaveType2 (int size, uint8_t *base)
-{
-	// for odd Super FX images
-	//Settings.DisplayColor = BUILD_PIXEL(31, 14, 6);
-	//SET_UI_COLOR(255, 119, 25);
-
-	uint8_t	blocks[256];
-	int		nblocks = size >> 16;
-	int		step = 64;
-
-	while (nblocks <= step)
-		step >>= 1;
-	nblocks = step;
-
-	for (int i = 0; i < nblocks * 2; i++)
-		blocks[i] = (i & ~0xf) | ((i & 3) << 2) | ((i & 12) >> 2);
-
-	uint8_t	*tmp = (uint8_t *) malloc(0x10000);
-	if (tmp)
-	{
-		for (int i = 0; i < nblocks * 2; i++)
-		{
-			for (int j = i; j < nblocks * 2; j++)
-			{
-				if (blocks[j] == i)
-				{
-					memmove(tmp, &base[blocks[j] * 0x10000], 0x10000);
-					memmove(&base[blocks[j] * 0x10000], &base[blocks[i] * 0x10000], 0x10000);
-					memmove(&base[blocks[i] * 0x10000], tmp, 0x10000);
-					uint8_t	b = blocks[j];
-					blocks[j] = blocks[i];
-					blocks[i] = b;
-					break;
-				}
-			}
-		}
-
-		free(tmp);
-	}
-}
-
-static void S9xDeinterleaveGD24 (int size, uint8_t *base)
-{
-	// for 24Mb images dumped with Game Doctor
-	if (size != 0x300000)
-		return;
-
-	//Settings.DisplayColor = BUILD_PIXEL(0, 31, 31);
-	//SET_UI_COLOR(0, 255, 255);
-
-	uint8_t	*tmp = (uint8_t *) malloc(0x80000);
-	if (tmp)
-	{
-		memmove(tmp, &base[0x180000], 0x80000);
-		memmove(&base[0x180000], &base[0x200000], 0x80000);
-		memmove(&base[0x200000], &base[0x280000], 0x80000);
-		memmove(&base[0x280000], tmp, 0x80000);
-
-		free(tmp);
-
-		S9xDeinterleaveType1(size, base);
-	}
 }
 
 // allocation and deallocation
 
 bool CMemory::Init()
 {
-    RAM	 = (uint8_t *) malloc(0x20000);
-    SRAM = (uint8_t *) malloc(0x20000);
-    VRAM = (uint8_t *) malloc(0x10000);
-    ROM  = (uint8_t *) malloc(MAX_ROM_SIZE + 0x200 + 0x8000);
-
-	IPPU.TileCache[TILE_2BIT]       = (uint8_t *) malloc(MAX_2BIT_TILES * 64);
-	IPPU.TileCache[TILE_4BIT]       = (uint8_t *) malloc(MAX_4BIT_TILES * 64);
-	IPPU.TileCache[TILE_8BIT]       = (uint8_t *) malloc(MAX_8BIT_TILES * 64);
-	IPPU.TileCache[TILE_2BIT_EVEN]  = (uint8_t *) malloc(MAX_2BIT_TILES * 64);
-	IPPU.TileCache[TILE_2BIT_ODD]   = (uint8_t *) malloc(MAX_2BIT_TILES * 64);
-	IPPU.TileCache[TILE_4BIT_EVEN]  = (uint8_t *) malloc(MAX_4BIT_TILES * 64);
-	IPPU.TileCache[TILE_4BIT_ODD]   = (uint8_t *) malloc(MAX_4BIT_TILES * 64);
-
-	IPPU.TileCached[TILE_2BIT]      = (uint8_t *) malloc(MAX_2BIT_TILES);
-	IPPU.TileCached[TILE_4BIT]      = (uint8_t *) malloc(MAX_4BIT_TILES);
-	IPPU.TileCached[TILE_8BIT]      = (uint8_t *) malloc(MAX_8BIT_TILES);
-	IPPU.TileCached[TILE_2BIT_EVEN] = (uint8_t *) malloc(MAX_2BIT_TILES);
-	IPPU.TileCached[TILE_2BIT_ODD]  = (uint8_t *) malloc(MAX_2BIT_TILES);
-	IPPU.TileCached[TILE_4BIT_EVEN] = (uint8_t *) malloc(MAX_4BIT_TILES);
-	IPPU.TileCached[TILE_4BIT_ODD]  = (uint8_t *) malloc(MAX_4BIT_TILES);
-
-	if (!RAM || !SRAM || !VRAM || !ROM ||
-		!IPPU.TileCache[TILE_2BIT]       ||
-		!IPPU.TileCache[TILE_4BIT]       ||
-		!IPPU.TileCache[TILE_8BIT]       ||
-		!IPPU.TileCache[TILE_2BIT_EVEN]  ||
-		!IPPU.TileCache[TILE_2BIT_ODD]   ||
-		!IPPU.TileCache[TILE_4BIT_EVEN]  ||
-		!IPPU.TileCache[TILE_4BIT_ODD]   ||
-		!IPPU.TileCached[TILE_2BIT]      ||
-		!IPPU.TileCached[TILE_4BIT]      ||
-		!IPPU.TileCached[TILE_8BIT]      ||
-		!IPPU.TileCached[TILE_2BIT_EVEN] ||
-		!IPPU.TileCached[TILE_2BIT_ODD]  ||
-		!IPPU.TileCached[TILE_4BIT_EVEN] ||
-		!IPPU.TileCached[TILE_4BIT_ODD])
-    {
-		Deinit();
+	this->RAM.reset(new uint8_t[0x20000]);
+	this->SRAM.reset(new uint8_t[0x20000]);
+	this->VRAM.reset(new uint8_t[0x10000]);
+	this->RealROM.reset(new uint8_t[MAX_ROM_SIZE + 0x200 + 0x8000]);
+
+	if (!this->RAM || !this->SRAM || !this->VRAM || !this->RealROM)
+	{
+		this->Deinit();
 		return false;
-    }
-
-	ZeroMemory(RAM,  0x20000);
-	ZeroMemory(SRAM, 0x20000);
-	ZeroMemory(VRAM, 0x10000);
-	ZeroMemory(ROM,  MAX_ROM_SIZE + 0x200 + 0x8000);
-
-	ZeroMemory(IPPU.TileCache[TILE_2BIT],       MAX_2BIT_TILES * 64);
-	ZeroMemory(IPPU.TileCache[TILE_4BIT],       MAX_4BIT_TILES * 64);
-	ZeroMemory(IPPU.TileCache[TILE_8BIT],       MAX_8BIT_TILES * 64);
-	ZeroMemory(IPPU.TileCache[TILE_2BIT_EVEN],  MAX_2BIT_TILES * 64);
-	ZeroMemory(IPPU.TileCache[TILE_2BIT_ODD],   MAX_2BIT_TILES * 64);
-	ZeroMemory(IPPU.TileCache[TILE_4BIT_EVEN],  MAX_4BIT_TILES * 64);
-	ZeroMemory(IPPU.TileCache[TILE_4BIT_ODD],   MAX_4BIT_TILES * 64);
-
-	ZeroMemory(IPPU.TileCached[TILE_2BIT],      MAX_2BIT_TILES);
-	ZeroMemory(IPPU.TileCached[TILE_4BIT],      MAX_4BIT_TILES);
-	ZeroMemory(IPPU.TileCached[TILE_8BIT],      MAX_8BIT_TILES);
-	ZeroMemory(IPPU.TileCached[TILE_2BIT_EVEN], MAX_2BIT_TILES);
-	ZeroMemory(IPPU.TileCached[TILE_2BIT_ODD],  MAX_2BIT_TILES);
-	ZeroMemory(IPPU.TileCached[TILE_4BIT_EVEN], MAX_4BIT_TILES);
-	ZeroMemory(IPPU.TileCached[TILE_4BIT_ODD],  MAX_4BIT_TILES);
+	}
+
+	std::fill(&this->RAM[0], &this->RAM[0x20000], 0);
+	std::fill(&this->SRAM[0], &this->SRAM[0x20000], 0);
+	std::fill(&this->VRAM[0], &this->VRAM[0x10000], 0);
+	std::fill(&this->RealROM[0], &this->RealROM[MAX_ROM_SIZE + 0x200 + 0x8000], 0);
 
 	// FillRAM uses first 32K of ROM image area, otherwise space just
 	// wasted. Might be read by the SuperFX code.
 
-	FillRAM = ROM;
+	this->FillRAM = &this->RealROM[0];
 
 	// Add 0x8000 to ROM image pointer to stop SuperFX code accessing
 	// unallocated memory (can cause crash on some ports).
 
-	ROM += 0x8000;
-
-	C4RAM   = ROM + 0x400000 + 8192 * 8; // C4
-	OBC1RAM = ROM + 0x400000; // OBC1
-	BIOSROM = ROM + 0x300000; // BS
-	BSRAM   = ROM + 0x400000; // BS
-
-	/*SuperFX.pvRegisters = FillRAM + 0x3000;
-	SuperFX.nRamBanks   = 2; // Most only use 1.  1=64KB=512Mb, 2=128KB=1024Mb
-	SuperFX.pvRam       = SRAM;
-	SuperFX.nRomBanks   = (2 * 1024 * 1024) / (32 * 1024);
-	SuperFX.pvRom       = (uint8_t *) ROM;*/
-
-	PostRomInitFunc = NULL;
+	this->ROM = &this->RealROM[0x8000];
 
 	return true;
 }
 
 void CMemory::Deinit()
 {
-	if (RAM)
-	{
-		free(RAM);
-		RAM = NULL;
-	}
-
-	if (SRAM)
-	{
-		free(SRAM);
-		SRAM = NULL;
-	}
-
-	if (VRAM)
-	{
-		free(VRAM);
-		VRAM = NULL;
-	}
-
-	if (ROM)
-	{
-		ROM -= 0x8000;
-		free(ROM);
-		ROM = NULL;
-	}
-
-	for (int t = 0; t < 7; t++)
-	{
-		if (IPPU.TileCache[t])
-		{
-			free(IPPU.TileCache[t]);
-			IPPU.TileCache[t] = NULL;
-		}
-
-		if (IPPU.TileCached[t])
-		{
-			free(IPPU.TileCached[t]);
-			IPPU.TileCached[t] = NULL;
-		}
-	}
-
-	Safe(NULL);
-	SafeANK(NULL);
+	this->RAM.reset();
+	this->SRAM.reset();
+	this->VRAM.reset();
+	this->ROM = nullptr;
+	this->RealROM.reset();
+
+	this->Safe(nullptr);
 }
 
 // file management and ROM detection
 
-static bool allASCII (uint8_t *b, int size)
-{
-	for (int i = 0; i < size; i++)
-	{
+static bool allASCII(uint8_t *b, int size)
+{
+	for (int i = 0; i < size; ++i)
 		if (b[i] < 32 || b[i] > 126)
 			return false;
-	}
 
 	return true;
 }
 
-/*static bool is_SufamiTurbo_BIOS (uint8_t *data, uint32_t size)
-{
-	if (size == 0x40000 &&
-		strncmp((char *) data, "BANDAI SFC-ADX", 14) == 0 && strncmp((char * ) (data + 0x10), "SFC-ADX BACKUP", 14) == 0)
-		return true;
-	else
-		return false;
-}*/
-
-/*static bool is_SufamiTurbo_Cart (uint8_t *data, uint32_t size)
-{
-	if (size >= 0x80000 && size <= 0x100000 &&
-		strncmp((char *) data, "BANDAI SFC-ADX", 14) == 0 && strncmp((char * ) (data + 0x10), "SFC-ADX BACKUP", 14) != 0)
-		return true;
-	else
-		return false;
-}*/
-
-/*static bool is_SameGame_BIOS (uint8_t *data, uint32_t size)
-{
-	if (size == 0x100000 && strncmp((char *) (data + 0xffc0), "Same Game Tsume Game", 20) == 0)
-		return true;
-	else
-		return false;
-}*/
-
-/*static bool is_SameGame_Add_On (uint8_t *data, uint32_t size)
-{
-	if (size == 0x80000)
-		return true;
-	else
-		return false;
-}*/
-
-int CMemory::ScoreHiROM (bool skip_header, int32_t romoff)
-{
-	uint8_t	*buf = ROM + 0xff00 + romoff + (skip_header ? 0x200 : 0);
-	int		score = 0;
+int CMemory::ScoreHiROM(bool skip_header, int32_t romoff)
+{
+	uint8_t *buf = &this->ROM[0xff00 + romoff + (skip_header ? 0x200 : 0)];
+	int score = 0;
 
 	if (buf[0xd5] & 0x1)
 		score += 2;
@@ -1257,8 +328,8 @@
 	if ((buf[0xdc] + (buf[0xdd] << 8)) + (buf[0xde] + (buf[0xdf] << 8)) == 0xffff)
 	{
 		score += 2;
-		if (0 != (buf[0xde] + (buf[0xdf] << 8)))
-			score++;
+		if (buf[0xde] + (buf[0xdf] << 8))
+			++score;
 	}
 
 	if (buf[0xda] == 0x33)
@@ -1273,25 +344,25 @@
 	if ((buf[0xfc] + (buf[0xfd] << 8)) > 0xffb0)
 		score -= 2; // reduced after looking at a scan by Cowering
 
-	if (CalculatedSize > 1024 * 1024 * 3)
+	if (this->CalculatedSize > 1024 * 1024 * 3)
 		score += 4;
 
 	if ((1 << (buf[0xd7] - 7)) > 48)
-		score -= 1;
+		--score;
 
 	if (!allASCII(&buf[0xb0], 6))
-		score -= 1;
+		--score;
 
 	if (!allASCII(&buf[0xc0], ROM_NAME_LEN - 1))
-		score -= 1;
+		--score;
 
 	return score;
 }
 
-int CMemory::ScoreLoROM (bool skip_header, int32_t romoff)
-{
-	uint8_t	*buf = ROM + 0x7f00 + romoff + (skip_header ? 0x200 : 0);
-	int		score = 0;
+int CMemory::ScoreLoROM(bool skip_header, int32_t romoff)
+{
+	uint8_t *buf = &this->ROM[0x7f00 + romoff + (skip_header ? 0x200 : 0)];
+	int score = 0;
 
 	if (!(buf[0xd5] & 0x1))
 		score += 3;
@@ -1303,8 +374,8 @@
 	if ((buf[0xdc] + (buf[0xdd] << 8)) + (buf[0xde] + (buf[0xdf] << 8)) == 0xffff)
 	{
 		score += 2;
-		if (0 != (buf[0xde] + (buf[0xdf] << 8)))
-			score++;
+		if (buf[0xde] + (buf[0xdf] << 8))
+			++score;
 	}
 
 	if (buf[0xda] == 0x33)
@@ -1319,281 +390,99 @@
 	if ((buf[0xfc] + (buf[0xfd] << 8)) > 0xffb0)
 		score -= 2; // reduced per Cowering suggestion
 
-	if (CalculatedSize <= 1024 * 1024 * 16)
+	if (this->CalculatedSize <= 1024 * 1024 * 16)
 		score += 2;
 
 	if ((1 << (buf[0xd7] - 7)) > 48)
-		score -= 1;
+		--score;
 
 	if (!allASCII(&buf[0xb0], 6))
-		score -= 1;
+		--score;
 
 	if (!allASCII(&buf[0xc0], ROM_NAME_LEN - 1))
-		score -= 1;
+		--score;
 
 	return score;
 }
 
-/*uint32_t CMemory::HeaderRemove (uint32_t size, int32_t &headerCount, uint8_t *buf)
-{
-	uint32_t	calc_size = (size / 0x2000) * 0x2000;
-
-	if ((size - calc_size == 512 && !Settings.ForceNoHeader) || Settings.ForceHeader)
-	{
-		uint8_t	*NSRTHead = buf + 0x1D0; // NSRT Header Location
-
-		// detect NSRT header
-		if (!strncmp("NSRT", (char *) &NSRTHead[24], 4))
-		{
-			if (NSRTHead[28] == 22)
-			{
-				if (((std::accumulate(NSRTHead, NSRTHead + sizeof(NSRTHeader), 0) & 0xFF) == NSRTHead[30]) &&
-					(NSRTHead[30] + NSRTHead[31] == 255) && ((NSRTHead[0] & 0x0F) <= 13) &&
-					(((NSRTHead[0] & 0xF0) >> 4) <= 3) && ((NSRTHead[0] & 0xF0) >> 4))
-					memcpy(NSRTHeader, NSRTHead, sizeof(NSRTHeader));
-			}
-		}
-
-		memmove(buf, buf + 512, calc_size);
-		headerCount++;
-		size -= 512;
-	}
-
-	return size;
-}*/
-
-/*uint32_t CMemory::FileLoader (uint8_t *buffer, const char *filename, int32_t maxsize)
-{
-	// <- ROM size without header
-	// ** Memory.HeaderCount
-	// ** Memory.ROMFilename
-
-	int32_t	totalSize = 0;
-    char	fname[PATH_MAX + 1];
-    char	drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], name[_MAX_FNAME + 1], exts[_MAX_EXT + 1];
-	char	*ext;
-
-#if defined(_WIN32) || defined(__MACOSX__)
-	ext = &exts[1];
-#else
-	ext = &exts[0];
-#endif
-
-	memset(NSRTHeader, 0, sizeof(NSRTHeader));
-	HeaderCount = 0;
-
-	_splitpath(filename, drive, dir, name, exts);
-	_makepath(fname, drive, dir, name, exts);
-
-	int	nFormat = FILE_DEFAULT;
-	if (strcasecmp(ext, "zip") == 0)
-		nFormat = FILE_ZIP;
-	else
-	if (strcasecmp(ext, "jma") == 0)
-		nFormat = FILE_JMA;
-
-	switch (nFormat)
-	{
-		case FILE_ZIP:
-		{
-		#ifdef UNZIP_SUPPORT
-			if (!LoadZip(fname, &totalSize, &HeaderCount, buffer))
-			{
-			 	S9xMessage(S9X_ERROR, S9X_ROM_INFO, "Invalid Zip archive.");
-				return 0;
-			}
-
-			strcpy(ROMFilename, fname);
-		#else
-			//S9xMessage(S9X_ERROR, S9X_ROM_INFO, "This binary was not created with Zip support.");
-			return 0;
-		#endif
-			break;
-		}
-
-		case FILE_JMA:
-		{
-		#ifdef JMA_SUPPORT
-			size_t	size = load_jma_file(fname, buffer);
-			if (!size)
-			{
-			 	S9xMessage(S9X_ERROR, S9X_ROM_INFO, "Invalid JMA archive.");
-				return 0;
-			}
-
-			totalSize = HeaderRemove(size, HeaderCount, buffer);
-
-			strcpy(ROMFilename, fname);
-		#else
-			//S9xMessage(S9X_ERROR, S9X_ROM_INFO, "This binary was not created with JMA support.");
-			return 0;
-		#endif
-			break;
-		}
-
-		case FILE_DEFAULT:
-		default:
-		{
-			STREAM	fp = OPEN_STREAM(fname, "rb");
-			if (!fp)
-				return 0;
-
-			strcpy(ROMFilename, fname);
-
-			int 	len  = 0;
-			uint32_t	size = 0;
-			bool	more = false;
-			uint8_t	*ptr = buffer;
-
-			do
-			{
-				size = READ_STREAM(ptr, maxsize + 0x200 - (ptr - buffer), fp);
-				CLOSE_STREAM(fp);
-
-				size = HeaderRemove(size, HeaderCount, ptr);
-				totalSize += size;
-				ptr += size;
-
-				// check for multi file roms
-				if (ptr - buffer < maxsize + 0x200 &&
-					(isdigit(ext[0]) && ext[1] == 0 && ext[0] < '9'))
-				{
-					more = true;
-					ext[0]++;
-					_makepath(fname, drive, dir, name, exts);
-				}
-				else
-				if (ptr - buffer < maxsize + 0x200 &&
-					(((len = strlen(name)) == 7 || len == 8) &&
-					strncasecmp(name, "sf", 2) == 0 &&
-					isdigit(name[2]) && isdigit(name[3]) && isdigit(name[4]) && isdigit(name[5]) &&
-					isalpha(name[len - 1])))
-				{
-					more = true;
-					name[len - 1]++;
-					_makepath(fname, drive, dir, name, exts);
-				}
-				else
-					more = false;
-
-			}	while (more && (fp = OPEN_STREAM(fname, "rb")) != NULL);
-
-			break;
-		}
-	}
-
-    if (HeaderCount == 0)
-		S9xMessage(S9X_INFO, S9X_HEADERS_INFO, "No ROM file header found.");
-    else
-    if (HeaderCount == 1)
-		S9xMessage(S9X_INFO, S9X_HEADERS_INFO, "Found ROM file header (and ignored it).");
-	else
-		S9xMessage(S9X_INFO, S9X_HEADERS_INFO, "Found multiple ROM file headers (and ignored them).");
-
-	return (uint32_t) totalSize;
-}*/
-
-//bool CMemory::LoadROM (const char *filename)
-bool CMemory::LoadROMSNSF(const unsigned char *lrombuf, int32_t lromsize, const unsigned char *srambuf, int32_t sramsize)
-{
-	int	retry_count = 0;
-
-	/*if (!filename || !*filename)
-		return false;*/
-
-	ZeroMemory(ROM, MAX_ROM_SIZE);
-	ZeroMemory(&Multi, sizeof(Multi));
+bool CMemory::LoadROMSNSF(const uint8_t *lrombuf, int32_t lromsize, const uint8_t *srambuf, int32_t sramsize)
+{
+	int retry_count = 0;
+
+	std::fill(&this->ROM[0], &this->ROM[MAX_ROM_SIZE], 0);
 
 again:
-	//Settings.DisplayColor = BUILD_PIXEL(31, 31, 31);
-	//SET_UI_COLOR(255, 255, 255);
-
-	CalculatedSize = 0;
-	ExtendedFormat = NOPE;
-
-	int32_t totalFileSize;
-
-	//totalFileSize = FileLoader(ROM, filename, MAX_ROM_SIZE);
-	totalFileSize  = std::min<int32_t>(MAX_ROM_SIZE, lromsize);
+	this->CalculatedSize = 0;
+	this->ExtendedFormat = NOPE;
+
+	int32_t totalFileSize = std::min<int32_t>(MAX_ROM_SIZE, lromsize);
 	if (!totalFileSize)
 		return false;
-	memcpy(ROM, lrombuf, totalFileSize);
+	std::copy(&lrombuf[0], &lrombuf[totalFileSize], &this->ROM[0]);
 	SNESGameFixes.SRAMInitialValue = 0xff;
-	memset(SRAM, SNESGameFixes.SRAMInitialValue, 0x20000);
+	std::fill(&this->SRAM[0], &this->SRAM[0x20000], SNESGameFixes.SRAMInitialValue);
 	if (srambuf && sramsize)
-		memcpy(SRAM, srambuf, sramsize);
-
-	/*if (!Settings.NoPatch)
-		CheckForAnyPatch(filename, HeaderCount != 0, totalFileSize);*/
-
-	int	hi_score, lo_score;
-
-	hi_score = ScoreHiROM(false);
-	lo_score = ScoreLoROM(false);
-
-	if (HeaderCount == 0 && !Settings.ForceNoHeader &&
-		((hi_score >  lo_score && ScoreHiROM(true) > hi_score) ||
-		 (hi_score <= lo_score && ScoreLoROM(true) > lo_score)))
-	{
-		memmove(ROM, ROM + 512, totalFileSize - 512);
+		std::copy(&srambuf[0], &srambuf[sramsize], &this->SRAM[0]);
+
+	int hi_score = this->ScoreHiROM(false);
+	int lo_score = this->ScoreLoROM(false);
+
+	if (((hi_score > lo_score && this->ScoreHiROM(true) > hi_score) || (hi_score <= lo_score && this->ScoreLoROM(true) > lo_score)))
+	{
+		memmove(&this->ROM[0], &this->ROM[512], totalFileSize - 512);
 		totalFileSize -= 512;
-		//S9xMessage(S9X_INFO, S9X_HEADER_WARNING, "Try 'force no-header' option if the game doesn't work");
 		// modifying ROM, so we need to rescore
-		hi_score = ScoreHiROM(false);
-		lo_score = ScoreLoROM(false);
-	}
-
-	CalculatedSize = (totalFileSize / 0x2000) * 0x2000;
-
-	if (CalculatedSize > 0x400000 &&
-		(ROM[0x7fd5] + (ROM[0x7fd6] << 8)) != 0x4332 && // exclude S-DD1
-		(ROM[0x7fd5] + (ROM[0x7fd6] << 8)) != 0x4532 &&
-		(ROM[0xffd5] + (ROM[0xffd6] << 8)) != 0xF93a && // exclude SPC7110
-		(ROM[0xffd5] + (ROM[0xffd6] << 8)) != 0xF53a)
-		ExtendedFormat = YEAH;
+		hi_score = this->ScoreHiROM(false);
+		lo_score = this->ScoreLoROM(false);
+	}
+
+	this->CalculatedSize = (totalFileSize / 0x2000) * 0x2000;
+
+	if (this->CalculatedSize > 0x400000 &&
+		this->ROM[0x7fd5] + (this->ROM[0x7fd6] << 8) != 0x4332 && // exclude S-DD1
+		this->ROM[0x7fd5] + (this->ROM[0x7fd6] << 8) != 0x4532 &&
+		this->ROM[0xffd5] + (this->ROM[0xffd6] << 8) != 0xF93a && // exclude SPC7110
+		this->ROM[0xffd5] + (this->ROM[0xffd6] << 8) != 0xF53a)
+		this->ExtendedFormat = YEAH;
 
 	// if both vectors are invalid, it's type 1 interleaved LoROM
-	if (ExtendedFormat == NOPE &&
-		((ROM[0x7ffc] + (ROM[0x7ffd] << 8)) < 0x8000) &&
-		((ROM[0xfffc] + (ROM[0xfffd] << 8)) < 0x8000))
-	{
-		if (!Settings.ForceInterleaved && !Settings.ForceNotInterleaved)
-			S9xDeinterleaveType1(totalFileSize, ROM);
+	if (this->ExtendedFormat == NOPE && this->ROM[0x7ffc] + (this->ROM[0x7ffd] << 8) < 0x8000 && this->ROM[0xfffc] + (this->ROM[0xfffd] << 8) < 0x8000)
+	{
+		if (!Settings.ForceNotInterleaved)
+			S9xDeinterleaveType1(totalFileSize, &this->ROM[0]);
 	}
 
 	// CalculatedSize is now set, so rescore
-	hi_score = ScoreHiROM(false);
-	lo_score = ScoreLoROM(false);
-
-	uint8_t	*RomHeader = ROM;
-
-	if (ExtendedFormat != NOPE)
-	{
-		int	swappedhirom, swappedlorom;
-
-		swappedhirom = ScoreHiROM(false, 0x400000);
-		swappedlorom = ScoreLoROM(false, 0x400000);
+	hi_score = this->ScoreHiROM(false);
+	lo_score = this->ScoreLoROM(false);
+
+	uint8_t *RomHeader = &this->ROM[0];
+
+	if (this->ExtendedFormat != NOPE)
+	{
+		int swappedhirom = this->ScoreHiROM(false, 0x400000);
+		int swappedlorom = this->ScoreLoROM(false, 0x400000);
 
 		// set swapped here
 		if (std::max(swappedlorom, swappedhirom) >= std::max(lo_score, hi_score))
 		{
-			ExtendedFormat = BIGFIRST;
+			this->ExtendedFormat = BIGFIRST;
 			hi_score = swappedhirom;
 			lo_score = swappedlorom;
 			RomHeader += 0x400000;
 		}
 		else
-			ExtendedFormat = SMALLFIRST;
-	}
-
-	bool	interleaved, tales = false;
-
-    interleaved = Settings.ForceInterleaved || Settings.ForceInterleaved2 || Settings.ForceInterleaveGD24;
-
-	if (Settings.ForceLoROM || (!Settings.ForceHiROM && lo_score >= hi_score))
-	{
-		LoROM = true;
-		HiROM = false;
+			this->ExtendedFormat = SMALLFIRST;
+	}
+
+	bool tales = false;
+
+	bool interleaved = false;
+
+	if (lo_score >= hi_score)
+	{
+		this->LoROM = true;
+		this->HiROM = false;
 
 		// ignore map type byte if not 0x2x or 0x3x
 		if ((RomHeader[0x7fd5] & 0xf0) == 0x20 || (RomHeader[0x7fd5] & 0xf0) == 0x30)
@@ -1613,8 +502,8 @@
 	}
 	else
 	{
-		LoROM = false;
-		HiROM = true;
+		this->LoROM = false;
+		this->HiROM = true;
 
 		if ((RomHeader[0xffd5] & 0xf0) == 0x20 || (RomHeader[0xffd5] & 0xf0) == 0x30)
 		{
@@ -1629,524 +518,93 @@
 	}
 
 	// this two games fail to be detected
-	if (!Settings.ForceHiROM && !Settings.ForceLoROM)
-	{
-		if (strncmp((char *) &ROM[0x7fc0], "YUYU NO QUIZ DE GO!GO!", 22) == 0 ||
-		   (strncmp((char *) &ROM[0xffc0], "BATMAN--REVENGE JOKER",  21) == 0))
-		{
-			LoROM = true;
-			HiROM = false;
-			interleaved = false;
-			tales = false;
-		}
+	if (!strncmp(reinterpret_cast<char *>(&this->ROM[0x7fc0]), "YUYU NO QUIZ DE GO!GO!", 22) || !strncmp(reinterpret_cast<char *>(&this->ROM[0xffc0]), "BATMAN--REVENGE JOKER",  21))
+	{
+		this->LoROM = true;
+		this->HiROM = false;
+		interleaved = false;
+		tales = false;
 	}
 
 	if (!Settings.ForceNotInterleaved && interleaved)
 	{
-		//S9xMessage(S9X_INFO, S9X_ROM_INTERLEAVED_INFO, "ROM image is in interleaved format - converting...");
-
 		if (tales)
 		{
-			if (ExtendedFormat == BIGFIRST)
+			if (this->ExtendedFormat == BIGFIRST)
 			{
-				S9xDeinterleaveType1(0x400000, ROM);
-				S9xDeinterleaveType1(CalculatedSize - 0x400000, ROM + 0x400000);
+				S9xDeinterleaveType1(0x400000, &this->ROM[0]);
+				S9xDeinterleaveType1(this->CalculatedSize - 0x400000, &this->ROM[0x400000]);
 			}
 			else
 			{
-				S9xDeinterleaveType1(CalculatedSize - 0x400000, ROM);
-				S9xDeinterleaveType1(0x400000, ROM + CalculatedSize - 0x400000);
+				S9xDeinterleaveType1(this->CalculatedSize - 0x400000, &this->ROM[0]);
+				S9xDeinterleaveType1(0x400000, &this->ROM[this->CalculatedSize - 0x400000]);
 			}
 
-			LoROM = false;
-			HiROM = true;
+			this->LoROM = false;
+			this->HiROM = true;
 		}
 		else
-		if (Settings.ForceInterleaveGD24 && CalculatedSize == 0x300000)
-		{
-			bool	t = LoROM;
-			LoROM = HiROM;
-			HiROM = t;
-			S9xDeinterleaveGD24(CalculatedSize, ROM);
-		}
-		else
-		if (Settings.ForceInterleaved2)
-			S9xDeinterleaveType2(CalculatedSize, ROM);
-		else
-		{
-			bool	t = LoROM;
-			LoROM = HiROM;
-			HiROM = t;
-			S9xDeinterleaveType1(CalculatedSize, ROM);
-		}
-
-		hi_score = ScoreHiROM(false);
-		lo_score = ScoreLoROM(false);
-
-		if ((HiROM && (lo_score >= hi_score || hi_score < 0)) ||
-			(LoROM && (hi_score >  lo_score || lo_score < 0)))
-		{
-			if (retry_count == 0)
-			{
-				//S9xMessage(S9X_INFO, S9X_ROM_CONFUSING_FORMAT_INFO, "ROM lied about its type! Trying again.");
-				Settings.ForceNotInterleaved = true;
-				Settings.ForceInterleaved = false;
-				retry_count++;
-				goto again;
-			}
-		}
-    }
-
-	if (ExtendedFormat == SMALLFIRST)
+		{
+			std::swap(this->LoROM, this->HiROM);
+			S9xDeinterleaveType1(this->CalculatedSize, &this->ROM[0]);
+		}
+
+		hi_score = this->ScoreHiROM(false);
+		lo_score = this->ScoreLoROM(false);
+
+		if (((this->HiROM && (lo_score >= hi_score || hi_score < 0)) || (this->LoROM && (hi_score > lo_score || lo_score < 0))) && !retry_count)
+		{
+			Settings.ForceNotInterleaved = true;
+			++retry_count;
+			goto again;
+		}
+	}
+
+	if (this->ExtendedFormat == SMALLFIRST)
 		tales = true;
 
 	if (tales)
 	{
-		uint8_t	*tmp = (uint8_t *) malloc(CalculatedSize - 0x400000);
-		if (tmp)
-		{
-			//S9xMessage(S9X_INFO, S9X_ROM_INTERLEAVED_INFO, "Fixing swapped ExHiROM...");
-			memmove(tmp, ROM, CalculatedSize - 0x400000);
-			memmove(ROM, ROM + CalculatedSize - 0x400000, 0x400000);
-			memmove(ROM + 0x400000, tmp, CalculatedSize - 0x400000);
-			free(tmp);
-		}
-	}
-
-	/*if (strncmp(LastRomFilename, filename, PATH_MAX + 1))
-	{
-		strncpy(LastRomFilename, filename, PATH_MAX + 1);
-		LastRomFilename[PATH_MAX] = 0;
-	}*/
-
-	ZeroMemory(&SNESGameFixes, sizeof(SNESGameFixes));
+		auto tmp = std::vector<uint8_t>(this->CalculatedSize - 0x400000);
+		memmove(&tmp[0], &this->ROM[0], this->CalculatedSize - 0x400000);
+		memmove(&this->ROM[0], &this->ROM[this->CalculatedSize - 0x400000], 0x400000);
+		memmove(&this->ROM[0x400000], &tmp[0], this->CalculatedSize - 0x400000);
+	}
+
+	memset(&SNESGameFixes, 0, sizeof(SNESGameFixes));
 	SNESGameFixes.SRAMInitialValue = 0x60;
 
-	//S9xLoadCheatFile(S9xGetFilename(".cht", CHEAT_DIR));
-
-	InitROM();
-
-	/*S9xInitCheatData();
-	S9xApplyCheats();*/
+	this->InitROM();
 
 	S9xReset();
 
-    return true;
-}
-
-/*bool CMemory::LoadMultiCart (const char *cartA, const char *cartB)
-{
-	bool	r = true;
-
-	ZeroMemory(ROM, MAX_ROM_SIZE);
-	ZeroMemory(&Multi, sizeof(Multi));
-
-	Settings.DisplayColor = BUILD_PIXEL(31, 31, 31);
-	SET_UI_COLOR(255, 255, 255);
-
-	CalculatedSize = 0;
-	ExtendedFormat = NOPE;
-
-	if (cartA && cartA[0])
-		Multi.cartSizeA = FileLoader(ROM, cartA, MAX_ROM_SIZE);
-
-	if (Multi.cartSizeA == 0)
-	{
-		if (cartB && cartB[0])
-			Multi.cartSizeB = FileLoader(ROM, cartB, MAX_ROM_SIZE);
-	}
-
-	if (Multi.cartSizeA)
-	{
-		if (is_SufamiTurbo_Cart(ROM, Multi.cartSizeA))
-			Multi.cartType = 4;
-		else
-		if (is_SameGame_BIOS(ROM, Multi.cartSizeA))
-			Multi.cartType = 3;
-	}
-	else
-	if (Multi.cartSizeB)
-	{
-		if (is_SufamiTurbo_Cart(ROM, Multi.cartSizeB))
-			Multi.cartType = 4;
-	}
-	else
-		Multi.cartType = 4; // assuming BIOS only
-
-	switch (Multi.cartType)
-	{
-		case 4:
-			r = LoadSufamiTurbo(cartA, cartB);
-			break;
-
-		case 3:
-			r = LoadSameGame(cartA, cartB);
-			break;
-
-		default:
-			r = false;
-	}
-
-	if (!r)
-	{
-		ZeroMemory(&Multi, sizeof(Multi));
-		return false;
-	}
-
-	ZeroMemory(&SNESGameFixes, sizeof(SNESGameFixes));
-	SNESGameFixes.SRAMInitialValue = 0x60;
-
-	S9xLoadCheatFile(S9xGetFilename(".cht", CHEAT_DIR));
-
-	InitROM();
-
-	S9xInitCheatData();
-	S9xApplyCheats();
-
-	S9xReset();
-
 	return true;
 }
 
-bool CMemory::LoadSufamiTurbo (const char *cartA, const char *cartB)
-{
-	Multi.cartOffsetA = 0x100000;
-	Multi.cartOffsetB = 0x200000;
-	Multi.sramA = SRAM;
-	Multi.sramB = SRAM + 0x10000;
-
-	if (Multi.cartSizeA)
-	{
-		Multi.sramSizeA = 4; // ROM[0x37]?
-		Multi.sramMaskA = Multi.sramSizeA ? ((1 << (Multi.sramSizeA + 3)) * 128 - 1) : 0;
-
-		if (!Settings.NoPatch)
-			CheckForAnyPatch(cartA, HeaderCount != 0, Multi.cartSizeA);
-
-		strcpy(Multi.fileNameA, cartA);
-		memcpy(ROM + Multi.cartOffsetA, ROM, Multi.cartSizeA);
-	}
-
-	if (Multi.cartSizeA && !Multi.cartSizeB)
-	{
-		if (cartB && cartB[0])
-			Multi.cartSizeB = FileLoader(ROM, cartB, MAX_ROM_SIZE);
-
-		if (Multi.cartSizeB)
-		{
-			if (!is_SufamiTurbo_Cart(ROM, Multi.cartSizeB))
-				Multi.cartSizeB = 0;
-		}
-	}
-
-	if (Multi.cartSizeB)
-	{
-		Multi.sramSizeB = 4; // ROM[0x37]?
-		Multi.sramMaskB = Multi.sramSizeB ? ((1 << (Multi.sramSizeB + 3)) * 128 - 1) : 0;
-
-		if (!Settings.NoPatch)
-			CheckForAnyPatch(cartB, HeaderCount != 0, Multi.cartSizeB);
-
-		strcpy(Multi.fileNameB, cartB);
-		memcpy(ROM + Multi.cartOffsetB, ROM, Multi.cartSizeB);
-	}
-
-	FILE	*fp;
-	size_t	size;
-	char	path[PATH_MAX + 1];
-
-	strcpy(path, S9xGetDirectory(BIOS_DIR));
-	strcat(path, SLASH_STR);
-	strcat(path, "STBIOS.bin");
-
-	fp = fopen(path, "rb");
-	if (fp)
-	{
-		size = fread((void *) ROM, 1, 0x40000, fp);
-		fclose(fp);
-		if (!is_SufamiTurbo_BIOS(ROM, size))
-			return false;
-	}
-	else
-		return false;
-
-	if (Multi.cartSizeA)
-		strcpy(ROMFilename, Multi.fileNameA);
-	else
-	if (Multi.cartSizeB)
-		strcpy(ROMFilename, Multi.fileNameB);
-	else
-		strcpy(ROMFilename, path);
-
-	LoROM = true;
-	HiROM = false;
-	CalculatedSize = 0x40000;
-
-	return true;
-}
-
-bool CMemory::LoadSameGame (const char *cartA, const char *cartB)
-{
-	Multi.cartOffsetA = 0;
-	Multi.cartOffsetB = 0x200000;
-	Multi.sramA = SRAM;
-	Multi.sramB = NULL;
-
-	Multi.sramSizeA = ROM[0xffd8];
-	Multi.sramMaskA = Multi.sramSizeA ? ((1 << (Multi.sramSizeA + 3)) * 128 - 1) : 0;
-	Multi.sramSizeB = 0;
-	Multi.sramMaskB = 0;
-
-	if (!Settings.NoPatch)
-		CheckForAnyPatch(cartA, HeaderCount != 0, Multi.cartSizeA);
-
-	strcpy(Multi.fileNameA, cartA);
-
-	if (cartB && cartB[0])
-		Multi.cartSizeB = FileLoader(ROM + Multi.cartOffsetB, cartB, MAX_ROM_SIZE - Multi.cartOffsetB);
-
-	if (Multi.cartSizeB)
-	{
-		if (!is_SameGame_Add_On(ROM + Multi.cartOffsetB, Multi.cartSizeB))
-			Multi.cartSizeB = 0;
-		else
-			strcpy(Multi.fileNameB, cartB);
-	}
-
-	strcpy(ROMFilename, Multi.fileNameA);
-
-	LoROM = false;
-	HiROM = true;
-	CalculatedSize = Multi.cartSizeA;
-
-	return true;
-}
-
-bool CMemory::LoadSRTC()
-{
-	FILE	*fp;
-	size_t	ignore;
-
-	fp = fopen(S9xGetFilename(".rtc", SRAM_DIR), "rb");
-	if (!fp)
-		return false;
-
-	ignore = fread(RTCData.reg, 1, 20, fp);
-	fclose(fp);
-
-	return true;
-}
-
-bool CMemory::SaveSRTC()
-{
-	FILE	*fp;
-	size_t	ignore;
-
-	fp = fopen(S9xGetFilename(".rtc", SRAM_DIR), "wb");
-	if (!fp)
-		return false;
-
-	ignore = fwrite(RTCData.reg, 1, 20, fp);
-	fclose(fp);
-
-	return true;
-}
-
-void CMemory::ClearSRAM (bool onlyNonSavedSRAM)
-{
-	if (onlyNonSavedSRAM)
-		if (!(Settings.SuperFX && ROMType < 0x15) && !(Settings.SA1 && ROMType == 0x34)) // can have SRAM
-			return;
-
-	memset(SRAM, SNESGameFixes.SRAMInitialValue, 0x20000);
-}
-
-bool CMemory::LoadSRAM (const char *filename)
-{
-	FILE	*file;
-	int		size, len;
-	char	sramName[PATH_MAX + 1];
-
-	strcpy(sramName, filename);
-
-	ClearSRAM();
-
-	if (Multi.cartType && Multi.sramSizeB)
-	{
-		char	temp[PATH_MAX + 1];
-
-		strcpy(temp, ROMFilename);
-		strcpy(ROMFilename, Multi.fileNameB);
-
-		size = (1 << (Multi.sramSizeB + 3)) * 128;
-
-		file = fopen(S9xGetFilename(".srm", SRAM_DIR), "rb");
-		if (file)
-		{
-			len = fread((char *) Multi.sramB, 1, 0x10000, file);
-			fclose(file);
-			if (len - size == 512)
-				memmove(Multi.sramB, Multi.sramB + 512, size);
-		}
-
-		strcpy(ROMFilename, temp);
-	}
-
-	size = SRAMSize ? (1 << (SRAMSize + 3)) * 128 : 0;
-	if (size > 0x20000)
-		size = 0x20000;
-
-	if (size)
-	{
-		file = fopen(sramName, "rb");
-		if (file)
-		{
-			len = fread((char *) SRAM, 1, 0x20000, file);
-			fclose(file);
-			if (len - size == 512)
-				memmove(SRAM, SRAM + 512, size);
-
-			if (Settings.SRTC || Settings.SPC7110RTC)
-				LoadSRTC();
-
-			return true;
-		}
-		else
-		if (Settings.BS && !Settings.BSXItself)
-		{
-			// The BS game's SRAM was not found
-			// Try to read BS-X.srm instead
-			char	path[PATH_MAX + 1];
-
-			strcpy(path, S9xGetDirectory(SRAM_DIR));
-			strcat(path, SLASH_STR);
-			strcat(path, "BS-X.srm");
-
-			file = fopen(path, "rb");
-			if (file)
-			{
-				len = fread((char *) SRAM, 1, 0x20000, file);
-				fclose(file);
-				if (len - size == 512)
-					memmove(SRAM, SRAM + 512, size);
-
-				S9xMessage(S9X_INFO, S9X_ROM_INFO, "The SRAM file wasn't found: BS-X.srm was read instead.");
-				return true;
-			}
-			else
-			{
-				S9xMessage(S9X_INFO, S9X_ROM_INFO, "The SRAM file wasn't found, BS-X.srm wasn't found either.");
-				return false;
-			}
-		}
-
-		return false;
-	}
-
-	return true;
-}
-
-bool CMemory::SaveSRAM (const char *filename)
-{
-	if (Settings.SuperFX && ROMType < 0x15) // doesn't have SRAM
-		return true;
-
-	if (Settings.SA1 && ROMType == 0x34)    // doesn't have SRAM
-		return true;
-
-	FILE	*file;
-	int		size;
-	char	sramName[PATH_MAX + 1];
-
-	strcpy(sramName, filename);
-
-	if (Multi.cartType && Multi.sramSizeB)
-	{
-		char	name[PATH_MAX + 1], temp[PATH_MAX + 1];
-
-		strcpy(temp, ROMFilename);
-		strcpy(ROMFilename, Multi.fileNameB);
-		strcpy(name, S9xGetFilename(".srm", SRAM_DIR));
-
-		size = (1 << (Multi.sramSizeB + 3)) * 128;
-
-		file = fopen(name, "wb");
-		if (file)
-		{
-			size_t	ignore;
-			ignore = fwrite((char *) Multi.sramB, size, 1, file);
-			fclose(file);
-		#ifdef __linux
-			ignore = chown(name, getuid(), getgid());
-		#endif
-		}
-
-		strcpy(ROMFilename, temp);
-    }
-
-    size = SRAMSize ? (1 << (SRAMSize + 3)) * 128 : 0;
-	if (size > 0x20000)
-		size = 0x20000;
-
-	if (size)
-	{
-		file = fopen(sramName, "wb");
-		if (file)
-		{
-			size_t	ignore;
-			ignore = fwrite((char *) SRAM, size, 1, file);
-			fclose(file);
-		#ifdef __linux
-			ignore = chown(sramName, getuid(), getgid());
-		#endif
-
-			if (Settings.SRTC || Settings.SPC7110RTC)
-				SaveSRTC();
-
-			return true;
-		}
-	}
-
-	return false;
-}*/
-
 // initialization
 
-static uint32_t caCRC32 (uint8_t *array, uint32_t size, uint32_t crc32 = 0xffffffff)
-{
-	for (uint32_t i = 0; i < size; i++)
-		crc32 = ((crc32 >> 8) & 0x00FFFFFF) ^ crc32Table[(crc32 ^ array[i]) & 0xFF];
-
-	return ~crc32;
-}
-
-char * CMemory::Safe (const char *s)
-{
-	static char	*safe = NULL;
-	static int	safe_len = 0;
-
-	if (s == NULL)
+char *CMemory::Safe(const char *s)
+{
+	static std::unique_ptr<char[]> safe;
+	static int safe_len = 0;
+
+	if (!s)
 	{
 		if (safe)
-		{
-			free(safe);
-			safe = NULL;
-		}
-
-		return NULL;
-	}
-
-	int	len = strlen(s);
+			safe.reset();
+
+		return nullptr;
+	}
+
+	int len = strlen(s);
 	if (!safe || len + 1 > safe_len)
 	{
-		if (safe)
-			free(safe);
-
 		safe_len = len + 1;
-		safe = (char *) malloc(safe_len);
-	}
-
-	for (int i = 0; i < len; i++)
+		safe.reset(new char[safe_len]);
+	}
+
+	for (int i = 0; i < len; ++i)
 	{
 		if (s[i] >= 32 && s[i] < 127)
 			safe[i] = s[i];
@@ -2156,1352 +614,420 @@
 
 	safe[len] = 0;
 
-	return safe;
-}
-
-char * CMemory::SafeANK (const char *s)
-{
-	static char	*safe = NULL;
-	static int	safe_len = 0;
-
-	if (s == NULL)
-	{
-		if (safe)
-		{
-			free(safe);
-			safe = NULL;
-		}
-
-		return NULL;
-	}
-
-	int	len = strlen(s);
-	if (!safe || len + 1 > safe_len)
-	{
-		if (safe)
-			free(safe);
-
-		safe_len = len + 1;
-		safe = (char *) malloc(safe_len);
-	}
-
-	for (int i = 0; i < len; i++)
-	{
-		if (s[i] >= 32 && s[i] < 127) // ASCII
-			safe [i] = s[i];
-		else
-		if (ROMRegion == 0 && ((uint8_t) s[i] >= 0xa0 && (uint8_t) s[i] < 0xe0)) // JIS X 201 - Katakana
-			safe [i] = s[i];
-		else
-			safe [i] = '_';
-	}
-
-	safe [len] = 0;
-
-	return safe;
-}
-
-void CMemory::ParseSNESHeader (uint8_t *RomHeader)
-{
-	bool	bs = Settings.BS & !Settings.BSXItself;
-
-	strncpy(ROMName, (char *) &RomHeader[0x10], ROM_NAME_LEN - 1);
-	if (bs)
-		memset(ROMName + 16, 0x20, ROM_NAME_LEN - 17);
-
-	if (bs)
-	{
-		if (!(((RomHeader[0x29] & 0x20) && CalculatedSize <  0x100000) ||
-			 (!(RomHeader[0x29] & 0x20) && CalculatedSize == 0x100000)))
-			printf("BS: Size mismatch\n");
-
-		// FIXME
-		int	p = 0;
-		while ((1 << p) < (int) CalculatedSize)
-			p++;
-		ROMSize = p - 10;
-	}
-	else
-		ROMSize = RomHeader[0x27];
-
-	SRAMSize  = bs ? 5 /* BS-X */    : RomHeader[0x28];
-	ROMSpeed  = bs ? RomHeader[0x28] : RomHeader[0x25];
-	ROMType   = bs ? 0xE5 /* BS-X */ : RomHeader[0x26];
-	ROMRegion = bs ? 0               : RomHeader[0x29];
-
-	ROMChecksum           = RomHeader[0x2E] + (RomHeader[0x2F] << 8);
-	ROMComplementChecksum = RomHeader[0x2C] + (RomHeader[0x2D] << 8);
-
-	memmove(ROMId, &RomHeader[0x02], 4);
-
-	if (RomHeader[0x2A] != 0x33)
-		CompanyId = ((RomHeader[0x2A] >> 4) & 0x0F) * 36 + (RomHeader[0x2A] & 0x0F);
-	else
-	if (isalnum(RomHeader[0x00]) && isalnum(RomHeader[0x01]))
-	{
-		int	l, r, l2, r2;
-		l = toupper(RomHeader[0x00]);
-		r = toupper(RomHeader[0x01]);
-		l2 = (l > '9') ? l - '7' : l - '0';
-		r2 = (r > '9') ? r - '7' : r - '0';
-		CompanyId = l2 * 36 + r2;
-	}
+	return safe.get();
+}
+
+void CMemory::ParseSNESHeader(uint8_t *RomHeader)
+{
+	strncpy(this->ROMName, reinterpret_cast<char *>(&RomHeader[0x10]), ROM_NAME_LEN - 1);
+
+	this->SRAMSize = RomHeader[0x28];
+	this->ROMSpeed = RomHeader[0x25];
+	this->ROMType = RomHeader[0x26];
+	this->ROMRegion = RomHeader[0x29];
+
+	std::copy(&RomHeader[0x02], &RomHeader[0x06], &this->ROMId[0]);
 }
 
 void CMemory::InitROM()
 {
-	Settings.SuperFX = false;
-	Settings.DSP = 0;
-	Settings.SA1 = false;
-	Settings.C4 = false;
-	Settings.SDD1 = false;
-	Settings.SPC7110 = false;
-	Settings.SPC7110RTC = false;
-	Settings.OBC1 = false;
-	Settings.SETA = 0;
-	Settings.SRTC = false;
-	Settings.BS = false;
-
-	//SuperFX.nRomBanks = CalculatedSize >> 15;
-
 	//// Parse ROM header and read ROM informatoin
 
-	CompanyId = -1;
-	memset(ROMId, 0, 5);
-
-	uint8_t	*RomHeader = ROM + 0x7FB0;
-	if (ExtendedFormat == BIGFIRST)
+	std::fill(&this->ROMId[0], &this->ROMId[5], 0);
+
+	uint8_t *RomHeader = &this->ROM[0x7FB0];
+	if (this->ExtendedFormat == BIGFIRST)
 		RomHeader += 0x400000;
-	if (HiROM)
+	if (this->HiROM)
 		RomHeader += 0x8000;
 
-	//S9xInitBSX(); // Set BS header before parsing
-
-	ParseSNESHeader(RomHeader);
+	this->ParseSNESHeader(RomHeader);
 
 	//// Detect and initialize chips
 	//// detection codes are compatible with NSRT
 
-	// DSP1/2/3/4
-	if (ROMType == 0x03)
-	{
-		if (ROMSpeed == 0x30)
-			Settings.DSP = 4; // DSP4
+	uint32_t identifier = ((this->ROMType & 0xff) << 8) + (this->ROMSpeed & 0xff);
+
+	Settings.SDD1 = identifier == 0x4332 || identifier == 0x4532;
+
+	//// Map memory and calculate checksum
+
+	this->Map_Initialize();
+
+	if (this->HiROM)
+	{
+		if (this->ExtendedFormat != NOPE)
+			this->Map_ExtendedHiROMMap();
 		else
-			Settings.DSP = 1; // DSP1
+			this->Map_HiROMMap();
 	}
 	else
-	if (ROMType == 0x05)
-	{
-		if (ROMSpeed == 0x20)
-			Settings.DSP = 2; // DSP2
+	{
+		if (Settings.SDD1)
+			this->Map_SDD1LoROMMap();
+		else if (this->ExtendedFormat != NOPE)
+			this->Map_JumboLoROMMap();
+		else if (!strncmp(this->ROMName, "WANDERERS FROM YS", 17))
+			this->Map_NoMAD1LoROMMap();
+		else if (!strncmp(this->ROMName, "SOUND NOVEL-TCOOL", 17) || !strncmp(this->ROMName, "DERBY STALLION 96", 17))
+			this->Map_ROM24MBSLoROMMap();
+		else if (!strncmp(this->ROMName, "THOROUGHBRED BREEDER3", 21) || !strncmp(this->ROMName, "RPG-TCOOL 2", 11))
+			this->Map_SRAM512KLoROMMap();
 		else
-		if (ROMSpeed == 0x30 && RomHeader[0x2a] == 0xb2)
-			Settings.DSP = 3; // DSP3
-		else
-			Settings.DSP = 1; // DSP1
-	}
-
-	/*switch (Settings.DSP)
-	{
-		case 1:	// DSP1
-			if (HiROM)
-			{
-				DSP0.boundary = 0x7000;
-				DSP0.maptype = M_DSP1_HIROM;
-			}
-			else
-			if (CalculatedSize > 0x100000)
-			{
-				DSP0.boundary = 0x4000;
-				DSP0.maptype = M_DSP1_LOROM_L;
-			}
-			else
-			{
-				DSP0.boundary = 0xc000;
-				DSP0.maptype = M_DSP1_LOROM_S;
-			}
-
-			SetDSP = &DSP1SetByte;
-			GetDSP = &DSP1GetByte;
-			break;
-
-		case 2: // DSP2
-			DSP0.boundary = 0x10000;
-			DSP0.maptype = M_DSP2_LOROM;
-			SetDSP = &DSP2SetByte;
-			GetDSP = &DSP2GetByte;
-			break;
-
-		case 3: // DSP3
-			DSP0.boundary = 0xc000;
-			DSP0.maptype = M_DSP3_LOROM;
-			SetDSP = &DSP3SetByte;
-			GetDSP = &DSP3GetByte;
-			break;
-
-		case 4: // DSP4
-			DSP0.boundary = 0xc000;
-			DSP0.maptype = M_DSP4_LOROM;
-			SetDSP = &DSP4SetByte;
-			GetDSP = &DSP4GetByte;
-			break;
-
-		default:
-			SetDSP = NULL;
-			GetDSP = NULL;
-			break;
-	}*/
-
-	uint32_t	identifier = ((ROMType & 0xff) << 8) + (ROMSpeed & 0xff);
-
-	switch (identifier)
-	{
-	    // SRTC
-		/*case 0x5535:
-			Settings.SRTC = true;
-			S9xInitSRTC();
-			break;
-
-		// SPC7110
-		case 0xF93A:
-			Settings.SPC7110RTC = true;
-		case 0xF53A:
-			Settings.SPC7110 = true;
-			S9xInitSPC7110();
-			break;
-
-		// OBC1
-		case 0x2530:
-			Settings.OBC1 = true;
-			break;
-
-		// SA1
-		case 0x3423:
-		case 0x3523:
-			Settings.SA1 = true;
-			break;
-
-		// SuperFX
-		case 0x1320:
-		case 0x1420:
-		case 0x1520:
-		case 0x1A20:
-			Settings.SuperFX = true;
-			S9xInitSuperFX();
-			if (ROM[0x7FDA] == 0x33)
-				SRAMSize = ROM[0x7FBD];
-			else
-				SRAMSize = 5;
-			break;*/
-
-		// SDD1
-		case 0x4332:
-		case 0x4532:
-			Settings.SDD1 = true;
-			break;
-
-		// ST018
-		/*case 0xF530:
-			Settings.SETA = ST_018;
-			SetSETA = NULL;
-			GetSETA = NULL;
-			SRAMSize = 2;
-			SNESGameFixes.SRAMInitialValue = 0x00;
-			break;
-
-		// ST010/011
-		case 0xF630:
-			if (ROM[0x7FD7] == 0x09)
-			{
-				Settings.SETA = ST_011;
-				SetSETA = &S9xSetST011;
-				GetSETA = &S9xGetST011;
-			}
-			else
-			{
-				Settings.SETA = ST_010;
-				SetSETA = &S9xSetST010;
-				GetSETA = &S9xGetST010;
-			}
-
-			SRAMSize = 2;
-			SNESGameFixes.SRAMInitialValue = 0x00;
-			break;
-
-		// C4
-		case 0xF320:
-			Settings.C4 = true;
-			break;*/
-	}
-
-	//// Map memory and calculate checksum
-
-	Map_Initialize();
-	CalculatedChecksum = 0;
-
-	if (HiROM)
-    {
-		if (Settings.BS)
-			/* Do nothing */;
-		else
-		/*if (Settings.SPC7110)
-			Map_SPC7110HiROMMap();
-		else*/
-		if (ExtendedFormat != NOPE)
-			Map_ExtendedHiROMMap();
-		/*else
-		if (Multi.cartType == 3)
-			Map_SameGameHiROMMap();*/
-		else
-			Map_HiROMMap();
-    }
-    else
-    {
-		if (Settings.BS)
-			/* Do nothing */;
-		else
-		/*if (Settings.SETA && Settings.SETA != ST_018)
-			Map_SetaDSPLoROMMap();
-		else
-		if (Settings.SuperFX)
-			Map_SuperFXLoROMMap();
-		else
-		if (Settings.SA1)
-			Map_SA1LoROMMap();
-		else*/
-		if (Settings.SDD1)
-			Map_SDD1LoROMMap();
-		else
-		if (ExtendedFormat != NOPE)
-			Map_JumboLoROMMap();
-		else
-		if (strncmp(ROMName, "WANDERERS FROM YS", 17) == 0)
-			Map_NoMAD1LoROMMap();
-		else
-		if (strncmp(ROMName, "SOUND NOVEL-TCOOL", 17) == 0 ||
-			strncmp(ROMName, "DERBY STALLION 96", 17) == 0)
-			Map_ROM24MBSLoROMMap();
-		else
-		if (strncmp(ROMName, "THOROUGHBRED BREEDER3", 21) == 0 ||
-			strncmp(ROMName, "RPG-TCOOL 2", 11) == 0)
-			Map_SRAM512KLoROMMap();
-		/*else
-		if (strncmp(ROMName, "ADD-ON BASE CASSETE", 19) == 0)
-		{
-			if (Multi.cartType == 4)
-			{
-				SRAMSize = Multi.sramSizeA;
-				Map_SufamiTurboLoROMMap();
-			}
-			else
-			{
-				SRAMSize = 5;
-				Map_SufamiTurboPseudoLoROMMap();
-			}
-		}*/
-		else
-			Map_LoROMMap();
-    }
-
-	Checksum_Calculate();
-
-	/*bool isChecksumOK = (ROMChecksum + ROMComplementChecksum == 0xffff) &
-						 (ROMChecksum == CalculatedChecksum);*/
+			this->Map_LoROMMap();
+	}
 
 	//// Build more ROM information
 
-	// CRC32
-	if (!Settings.BS || Settings.BSXItself) // Not BS Dump
-		ROMCRC32 = caCRC32(ROM, CalculatedSize);
-	else // Convert to correct format before scan
-	{
-		int offset = HiROM ? 0xffc0 : 0x7fc0;
-		// Backup
-		uint8_t BSMagic0 = ROM[offset + 22],
-			  BSMagic1 = ROM[offset + 23];
-		// uCONSRT standard
-		ROM[offset + 22] = 0x42;
-		ROM[offset + 23] = 0x00;
-		// Calc
-		ROMCRC32 = caCRC32(ROM, CalculatedSize);
-		// Convert back
-		ROM[offset + 22] = BSMagic0;
-		ROM[offset + 23] = BSMagic1;
-	}
-
 	// NTSC/PAL
-	if (Settings.ForceNTSC)
-		Settings.PAL = false;
-	else
-	if (Settings.ForcePAL)
-		Settings.PAL = true;
-	else
-	if (!Settings.BS && (ROMRegion >= 2) && (ROMRegion <= 12))
-		Settings.PAL = true;
-	else
-		Settings.PAL = false;
-
-	if (Settings.PAL)
-	{
-		Settings.FrameTime = Settings.FrameTimePAL;
-		ROMFramesPerSecond = 50;
-	}
-	else
-	{
-		Settings.FrameTime = Settings.FrameTimeNTSC;
-		ROMFramesPerSecond = 60;
-	}
+	Settings.PAL = this->ROMRegion >= 2 && this->ROMRegion <= 12;
 
 	// truncate cart name
-	ROMName[ROM_NAME_LEN - 1] = 0;
-	if (strlen(ROMName))
-	{
-		char *p = ROMName + strlen(ROMName);
-		if (p > ROMName + 21 && ROMName[20] == ' ')
-			p = ROMName + 21;
-		while (p > ROMName && *(p - 1) == ' ')
-			p--;
+	this->ROMName[ROM_NAME_LEN - 1] = 0;
+	if (strlen(this->ROMName))
+	{
+		char *p = this->ROMName + strlen(this->ROMName);
+		if (p > this->ROMName + 21 && this->ROMName[20] == ' ')
+			p = this->ROMName + 21;
+		while (p > this->ROMName && *(p - 1) == ' ')
+			--p;
 		*p = 0;
 	}
 
 	// SRAM size
-	SRAMMask = SRAMSize ? ((1 << (SRAMSize + 3)) * 128) - 1 : 0;
-
-	// checksum
-	/*if (!isChecksumOK || ((uint32_t) CalculatedSize > (uint32_t) (((1 << (ROMSize - 7)) * 128) * 1024)))
-	{
-		Settings.DisplayColor = BUILD_PIXEL(31, 31, 0);
-		SET_UI_COLOR(255, 255, 0);
-	}*/
-
-	/*if (Multi.cartType == 4)
-	{
-		Settings.DisplayColor = BUILD_PIXEL(0, 16, 31);
-		SET_UI_COLOR(0, 128, 255);
-	}*/
+	this->SRAMMask = this->SRAMSize ? ((1 << (this->SRAMSize + 3)) * 128) - 1 : 0;
 
 	//// Initialize emulation
 
 	Timings.H_Max_Master = SNES_CYCLES_PER_SCANLINE;
-	Timings.H_Max        = Timings.H_Max_Master;
-	Timings.HBlankStart  = SNES_HBLANK_START_HC;
-	Timings.HBlankEnd    = SNES_HBLANK_END_HC;
-	Timings.HDMAInit     = SNES_HDMA_INIT_HC;
-	Timings.HDMAStart    = SNES_HDMA_START_HC;
-	Timings.RenderPos    = SNES_RENDER_START_HC;
+	Timings.H_Max = Timings.H_Max_Master;
+	Timings.HBlankStart = SNES_HBLANK_START_HC;
+	Timings.HBlankEnd = SNES_HBLANK_END_HC;
+	Timings.HDMAInit = SNES_HDMA_INIT_HC;
+	Timings.HDMAStart = SNES_HDMA_START_HC;
+	Timings.RenderPos = SNES_RENDER_START_HC;
 	Timings.V_Max_Master = Settings.PAL ? SNES_MAX_PAL_VCOUNTER : SNES_MAX_NTSC_VCOUNTER;
-	Timings.V_Max        = Timings.V_Max_Master;
+	Timings.V_Max = Timings.V_Max_Master;
 	/* From byuu: The total delay time for both the initial (H)DMA sync (to the DMA clock),
 	   and the end (H)DMA sync (back to the last CPU cycle's mcycle rate (6, 8, or 12)) always takes between 12-24 mcycles.
 	   Possible delays: { 12, 14, 16, 18, 20, 22, 24 }
 	   XXX: Snes9x can't emulate this timing :( so let's use the average value... */
-	Timings.DMACPUSync   = 18;
+	Timings.DMACPUSync = 18;
 	/* If the CPU is halted (i.e. for DMA) while /NMI goes low, the NMI will trigger
 	   after the DMA completes (even if /NMI goes high again before the DMA
 	   completes). In this case, there is a 24-30 cycle delay between the end of DMA
 	   and the NMI handler, time enough for an instruction or two. */
 	// Wild Guns, Mighty Morphin Power Rangers - The Fighting Edition
-	Timings.NMIDMADelay  = 24;
+	Timings.NMIDMADelay = 24;
 	Timings.IRQPendCount = 0;
 
-	IPPU.TotalEmulatedFrames = 0;
-
 	//// Hack games
 
-	ApplyROMFixes();
-
-	//// Show ROM information
-	//char displayName[ROM_NAME_LEN];
-
-	strcpy(RawROMName, ROMName);
-	//sprintf(displayName, "%s", SafeANK(ROMName));
-	sprintf(ROMName, "%s", Safe(ROMName));
-	sprintf(ROMId, "%s", Safe(ROMId));
-
-	/*sprintf(String, "\"%s\" [%s] %s, %s, %s, %s, SRAM:%s, ID:%s, CRC32:%08X",
-		displayName, isChecksumOK ? "checksum ok" : ((Multi.cartType == 4) ? "no checksum" : "bad checksum"),
-		MapType(), Size(), KartContents(), Settings.PAL ? "PAL" : "NTSC", StaticRAMSize(), ROMId, ROMCRC32);*/
-	//S9xMessage(S9X_INFO, S9X_ROM_INFO, String);
-
-	Settings.ForceLoROM = false;
-	Settings.ForceHiROM = false;
-	Settings.ForceHeader = false;
-	Settings.ForceNoHeader = false;
-	Settings.ForceInterleaved = false;
-	Settings.ForceInterleaved2 = false;
-	Settings.ForceInterleaveGD24 = false;
+	this->ApplyROMFixes();
+
+	sprintf(this->ROMName, "%s", Safe(this->ROMName));
+	sprintf(this->ROMId, "%s", Safe(this->ROMId));
+
 	Settings.ForceNotInterleaved = false;
-	Settings.ForcePAL = false;
-	Settings.ForceNTSC = false;
-
-	Settings.TakeScreenshot = false;
-
-	/*if (stopMovie)
-		S9xMovieStop(true);*/
-
-	if (PostRomInitFunc)
-		PostRomInitFunc();
-
-    //S9xVerifyControllers();
 }
 
 // memory map
 
-uint32_t CMemory::map_mirror (uint32_t size, uint32_t pos)
+uint32_t CMemory::map_mirror(uint32_t size, uint32_t pos)
 {
 	// from bsnes
-	if (size == 0)
+	if (!size)
 		return 0;
 	if (pos < size)
 		return pos;
 
-	uint32_t	mask = 1 << 31;
+	uint32_t mask = 1 << 31;
 	while (!(pos & mask))
 		mask >>= 1;
 
 	if (size <= (pos & mask))
-		return map_mirror(size, pos - mask);
+		return this->map_mirror(size, pos - mask);
 	else
-		return mask + map_mirror(size - mask, pos - mask);
-}
-
-void CMemory::map_lorom (uint32_t bank_s, uint32_t bank_e, uint32_t addr_s, uint32_t addr_e, uint32_t size)
-{
-	uint32_t	c, i, p, addr;
-
-	for (c = bank_s; c <= bank_e; c++)
-	{
-		for (i = addr_s; i <= addr_e; i += 0x1000)
-		{
-			p = (c << 4) | (i >> 12);
-			addr = (c & 0x7f) * 0x8000;
-			Map[p] = ROM + map_mirror(size, addr) - (i & 0x8000);
-			BlockIsROM[p] = true;
-			BlockIsRAM[p] = false;
-		}
-	}
-}
-
-void CMemory::map_hirom (uint32_t bank_s, uint32_t bank_e, uint32_t addr_s, uint32_t addr_e, uint32_t size)
-{
-	uint32_t	c, i, p, addr;
-
-	for (c = bank_s; c <= bank_e; c++)
-	{
-		for (i = addr_s; i <= addr_e; i += 0x1000)
-		{
-			p = (c << 4) | (i >> 12);
-			addr = c << 16;
-			Map[p] = ROM + map_mirror(size, addr);
-			BlockIsROM[p] = true;
-			BlockIsRAM[p] = false;
-		}
-	}
-}
-
-void CMemory::map_lorom_offset (uint32_t bank_s, uint32_t bank_e, uint32_t addr_s, uint32_t addr_e, uint32_t size, uint32_t offset)
-{
-	uint32_t	c, i, p, addr;
-
-	for (c = bank_s; c <= bank_e; c++)
-	{
-		for (i = addr_s; i <= addr_e; i += 0x1000)
-		{
-			p = (c << 4) | (i >> 12);
-			addr = ((c - bank_s) & 0x7f) * 0x8000;
-			Map[p] = ROM + offset + map_mirror(size, addr) - (i & 0x8000);
-			BlockIsROM[p] = true;
-			BlockIsRAM[p] = false;
-		}
-	}
-}
-
-void CMemory::map_hirom_offset (uint32_t bank_s, uint32_t bank_e, uint32_t addr_s, uint32_t addr_e, uint32_t size, uint32_t offset)
-{
-	uint32_t	c, i, p, addr;
-
-	for (c = bank_s; c <= bank_e; c++)
-	{
-		for (i = addr_s; i <= addr_e; i += 0x1000)
-		{
-			p = (c << 4) | (i >> 12);
-			addr = (c - bank_s) << 16;
-			Map[p] = ROM + offset + map_mirror(size, addr);
-			BlockIsROM[p] = true;
-			BlockIsRAM[p] = false;
-		}
-	}
-}
-
-void CMemory::map_space (uint32_t bank_s, uint32_t bank_e, uint32_t addr_s, uint32_t addr_e, uint8_t *data)
-{
-	uint32_t	c, i, p;
-
-	for (c = bank_s; c <= bank_e; c++)
-	{
-		for (i = addr_s; i <= addr_e; i += 0x1000)
-		{
-			p = (c << 4) | (i >> 12);
-			Map[p] = data;
-			BlockIsROM[p] = false;
-			BlockIsRAM[p] = true;
-		}
-	}
-}
-
-void CMemory::map_index (uint32_t bank_s, uint32_t bank_e, uint32_t addr_s, uint32_t addr_e, int index, int type)
-{
-	uint32_t	c, i, p;
-	bool	isROM, isRAM;
-
-	isROM = ((type == MAP_TYPE_I_O) || (type == MAP_TYPE_RAM)) ? false : true;
-	isRAM = ((type == MAP_TYPE_I_O) || (type == MAP_TYPE_ROM)) ? false : true;
-
-	for (c = bank_s; c <= bank_e; c++)
-	{
-		for (i = addr_s; i <= addr_e; i += 0x1000)
-		{
-			p = (c << 4) | (i >> 12);
-			Map[p] = (uint8_t *) index;
-			BlockIsROM[p] = isROM;
-			BlockIsRAM[p] = isRAM;
-		}
-	}
+		return mask + this->map_mirror(size - mask, pos - mask);
+}
+
+void CMemory::map_lorom(uint32_t bank_s, uint32_t bank_e, uint32_t addr_s, uint32_t addr_e, uint32_t size)
+{
+	for (uint32_t c = bank_s; c <= bank_e; ++c)
+		for (uint32_t i = addr_s; i <= addr_e; i += 0x1000)
+		{
+			uint32_t p = (c << 4) | (i >> 12);
+			uint32_t addr = (c & 0x7f) * 0x8000;
+			this->Map[p] = &this->ROM[this->map_mirror(size, addr) - (i & 0x8000)];
+			this->BlockIsROM[p] = true;
+			this->BlockIsRAM[p] = false;
+		}
+}
+
+void CMemory::map_hirom(uint32_t bank_s, uint32_t bank_e, uint32_t addr_s, uint32_t addr_e, uint32_t size)
+{
+	for (uint32_t c = bank_s; c <= bank_e; ++c)
+		for (uint32_t i = addr_s; i <= addr_e; i += 0x1000)
+		{
+			uint32_t p = (c << 4) | (i >> 12);
+			uint32_t addr = c << 16;
+			this->Map[p] = &this->ROM[this->map_mirror(size, addr)];
+			this->BlockIsROM[p] = true;
+			this->BlockIsRAM[p] = false;
+		}
+}
+
+void CMemory::map_lorom_offset(uint32_t bank_s, uint32_t bank_e, uint32_t addr_s, uint32_t addr_e, uint32_t size, uint32_t offset)
+{
+	for (uint32_t c = bank_s; c <= bank_e; ++c)
+		for (uint32_t i = addr_s; i <= addr_e; i += 0x1000)
+		{
+			uint32_t p = (c << 4) | (i >> 12);
+			uint32_t addr = ((c - bank_s) & 0x7f) * 0x8000;
+			this->Map[p] = &this->ROM[offset + this->map_mirror(size, addr) - (i & 0x8000)];
+			this->BlockIsROM[p] = true;
+			this->BlockIsRAM[p] = false;
+		}
+}
+
+void CMemory::map_hirom_offset(uint32_t bank_s, uint32_t bank_e, uint32_t addr_s, uint32_t addr_e, uint32_t size, uint32_t offset)
+{
+	for (uint32_t c = bank_s; c <= bank_e; ++c)
+		for (uint32_t i = addr_s; i <= addr_e; i += 0x1000)
+		{
+			uint32_t p = (c << 4) | (i >> 12);
+			uint32_t addr = (c - bank_s) << 16;
+			this->Map[p] = &this->ROM[offset + this->map_mirror(size, addr)];
+			this->BlockIsROM[p] = true;
+			this->BlockIsRAM[p] = false;
+		}
+}
+
+void CMemory::map_space(uint32_t bank_s, uint32_t bank_e, uint32_t addr_s, uint32_t addr_e, uint8_t *data)
+{
+	for (uint32_t c = bank_s; c <= bank_e; ++c)
+		for (uint32_t i = addr_s; i <= addr_e; i += 0x1000)
+		{
+			uint32_t p = (c << 4) | (i >> 12);
+			this->Map[p] = data;
+			this->BlockIsROM[p] = false;
+			this->BlockIsRAM[p] = true;
+		}
+}
+
+void CMemory::map_index(uint32_t bank_s, uint32_t bank_e, uint32_t addr_s, uint32_t addr_e, int index, int type)
+{
+	bool isROM = !(type == MAP_TYPE_I_O || type == MAP_TYPE_RAM);
+	bool isRAM = type != MAP_TYPE_I_O;
+
+	for (uint32_t c = bank_s; c <= bank_e; ++c)
+		for (uint32_t i = addr_s; i <= addr_e; i += 0x1000)
+		{
+			uint32_t p = (c << 4) | (i >> 12);
+			this->Map[p] = reinterpret_cast<uint8_t *>(index);
+			this->BlockIsROM[p] = isROM;
+			this->BlockIsRAM[p] = isRAM;
+		}
 }
 
 void CMemory::map_System()
 {
 	// will be overwritten
-	map_space(0x00, 0x3f, 0x0000, 0x1fff, RAM);
-	map_index(0x00, 0x3f, 0x2000, 0x3fff, MAP_PPU, MAP_TYPE_I_O);
-	map_index(0x00, 0x3f, 0x4000, 0x5fff, MAP_CPU, MAP_TYPE_I_O);
-	map_space(0x80, 0xbf, 0x0000, 0x1fff, RAM);
-	map_index(0x80, 0xbf, 0x2000, 0x3fff, MAP_PPU, MAP_TYPE_I_O);
-	map_index(0x80, 0xbf, 0x4000, 0x5fff, MAP_CPU, MAP_TYPE_I_O);
+	this->map_space(0x00, 0x3f, 0x0000, 0x1fff, &this->RAM[0]);
+	this->map_index(0x00, 0x3f, 0x2000, 0x3fff, MAP_PPU, MAP_TYPE_I_O);
+	this->map_index(0x00, 0x3f, 0x4000, 0x5fff, MAP_CPU, MAP_TYPE_I_O);
+	this->map_space(0x80, 0xbf, 0x0000, 0x1fff, &this->RAM[0]);
+	this->map_index(0x80, 0xbf, 0x2000, 0x3fff, MAP_PPU, MAP_TYPE_I_O);
+	this->map_index(0x80, 0xbf, 0x4000, 0x5fff, MAP_CPU, MAP_TYPE_I_O);
 }
 
 void CMemory::map_WRAM()
 {
 	// will overwrite others
-	map_space(0x7e, 0x7e, 0x0000, 0xffff, RAM);
-	map_space(0x7f, 0x7f, 0x0000, 0xffff, RAM + 0x10000);
+	this->map_space(0x7e, 0x7e, 0x0000, 0xffff, &this->RAM[0]);
+	this->map_space(0x7f, 0x7f, 0x0000, 0xffff, &this->RAM[0x10000]);
 }
 
 void CMemory::map_LoROMSRAM()
 {
-	map_index(0x70, 0x7f, 0x0000, 0x7fff, MAP_LOROM_SRAM, MAP_TYPE_RAM);
-	map_index(0xf0, 0xff, 0x0000, 0x7fff, MAP_LOROM_SRAM, MAP_TYPE_RAM);
+	this->map_index(0x70, 0x7f, 0x0000, 0x7fff, MAP_LOROM_SRAM, MAP_TYPE_RAM);
+	this->map_index(0xf0, 0xff, 0x0000, 0x7fff, MAP_LOROM_SRAM, MAP_TYPE_RAM);
 }
 
 void CMemory::map_HiROMSRAM()
 {
-	map_index(0x20, 0x3f, 0x6000, 0x7fff, MAP_HIROM_SRAM, MAP_TYPE_RAM);
-	map_index(0xa0, 0xbf, 0x6000, 0x7fff, MAP_HIROM_SRAM, MAP_TYPE_RAM);
-}
-
-/*void CMemory::map_DSP()
-{
-	switch (DSP0.maptype)
-	{
-		case M_DSP1_LOROM_S:
-			map_index(0x20, 0x3f, 0x8000, 0xffff, MAP_DSP, MAP_TYPE_I_O);
-			map_index(0xa0, 0xbf, 0x8000, 0xffff, MAP_DSP, MAP_TYPE_I_O);
-			break;
-
-		case M_DSP1_LOROM_L:
-			map_index(0x60, 0x6f, 0x0000, 0x7fff, MAP_DSP, MAP_TYPE_I_O);
-			map_index(0xe0, 0xef, 0x0000, 0x7fff, MAP_DSP, MAP_TYPE_I_O);
-			break;
-
-		case M_DSP1_HIROM:
-			map_index(0x00, 0x1f, 0x6000, 0x7fff, MAP_DSP, MAP_TYPE_I_O);
-			map_index(0x80, 0x9f, 0x6000, 0x7fff, MAP_DSP, MAP_TYPE_I_O);
-			break;
-
-		case M_DSP2_LOROM:
-			map_index(0x20, 0x3f, 0x6000, 0x6fff, MAP_DSP, MAP_TYPE_I_O);
-			map_index(0x20, 0x3f, 0x8000, 0xbfff, MAP_DSP, MAP_TYPE_I_O);
-			map_index(0xa0, 0xbf, 0x6000, 0x6fff, MAP_DSP, MAP_TYPE_I_O);
-			map_index(0xa0, 0xbf, 0x8000, 0xbfff, MAP_DSP, MAP_TYPE_I_O);
-			break;
-
-		case M_DSP3_LOROM:
-			map_index(0x20, 0x3f, 0x8000, 0xffff, MAP_DSP, MAP_TYPE_I_O);
-			map_index(0xa0, 0xbf, 0x8000, 0xffff, MAP_DSP, MAP_TYPE_I_O);
-			break;
-
-		case M_DSP4_LOROM:
-			map_index(0x30, 0x3f, 0x8000, 0xffff, MAP_DSP, MAP_TYPE_I_O);
-			map_index(0xb0, 0xbf, 0x8000, 0xffff, MAP_DSP, MAP_TYPE_I_O);
-			break;
-	}
-}*/
-
-/*void CMemory::map_C4()
-{
-	map_index(0x00, 0x3f, 0x6000, 0x7fff, MAP_C4, MAP_TYPE_I_O);
-	map_index(0x80, 0xbf, 0x6000, 0x7fff, MAP_C4, MAP_TYPE_I_O);
-}*/
-
-/*void CMemory::map_OBC1()
-{
-	map_index(0x00, 0x3f, 0x6000, 0x7fff, MAP_OBC_RAM, MAP_TYPE_I_O);
-	map_index(0x80, 0xbf, 0x6000, 0x7fff, MAP_OBC_RAM, MAP_TYPE_I_O);
-}*/
-
-/*void CMemory::map_SetaRISC()
-{
-	map_index(0x00, 0x3f, 0x3000, 0x3fff, MAP_SETA_RISC, MAP_TYPE_I_O);
-	map_index(0x80, 0xbf, 0x3000, 0x3fff, MAP_SETA_RISC, MAP_TYPE_I_O);
-}*/
-
-/*void CMemory::map_SetaDSP()
-{
-	// where does the SETA chip access, anyway?
-	// please confirm this?
-	map_index(0x68, 0x6f, 0x0000, 0x7fff, MAP_SETA_DSP, MAP_TYPE_RAM);
-	// and this!
-	map_index(0x60, 0x67, 0x0000, 0x3fff, MAP_SETA_DSP, MAP_TYPE_I_O);
-
-	// ST-0010:
-	// map_index(0x68, 0x6f, 0x0000, 0x0fff, MAP_SETA_DSP, ?);
-}*/
+	this->map_index(0x20, 0x3f, 0x6000, 0x7fff, MAP_HIROM_SRAM, MAP_TYPE_RAM);
+	this->map_index(0xa0, 0xbf, 0x6000, 0x7fff, MAP_HIROM_SRAM, MAP_TYPE_RAM);
+}
 
 void CMemory::map_WriteProtectROM()
 {
-	memmove((void *) WriteMap, (void *) Map, sizeof(Map));
-
-	for (int c = 0; c < 0x1000; c++)
-	{
-		if (BlockIsROM[c])
-			WriteMap[c] = (uint8_t *) MAP_NONE;
-	}
+	std::copy(&this->Map[0], &this->Map[0x1000], &this->WriteMap[0]);
+
+	for (int c = 0; c < 0x1000; ++c)
+		if (this->BlockIsROM[c])
+			this->WriteMap[c] = reinterpret_cast<uint8_t *>(MAP_NONE);
 }
 
 void CMemory::Map_Initialize()
 {
-	for (int c = 0; c < 0x1000; c++)
-	{
-		Map[c]      = (uint8_t *) MAP_NONE;
-		WriteMap[c] = (uint8_t *) MAP_NONE;
-		BlockIsROM[c] = false;
-		BlockIsRAM[c] = false;
+	for (int c = 0; c < 0x1000; ++c)
+	{
+		this->Map[c] = this->WriteMap[c] = reinterpret_cast<uint8_t *>(MAP_NONE);
+		this->BlockIsROM[c] = this->BlockIsRAM[c] = false;
 	}
 }
 
 void CMemory::Map_LoROMMap()
 {
-	printf("Map_LoROMMap\n");
-	map_System();
-
-	map_lorom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize);
-	map_lorom(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize);
-	map_lorom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize);
-	map_lorom(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize);
-
-	/*if (Settings.DSP)
-		map_DSP();
-	else
-	if (Settings.C4)
-		map_C4();
-	else
-	if (Settings.OBC1)
-		map_OBC1();
-	else
-	if (Settings.SETA == ST_018)
-		map_SetaRISC();*/
-
-    map_LoROMSRAM();
-	map_WRAM();
-
-	map_WriteProtectROM();
+	this->map_System();
+
+	this->map_lorom(0x00, 0x3f, 0x8000, 0xffff, this->CalculatedSize);
+	this->map_lorom(0x40, 0x7f, 0x0000, 0xffff, this->CalculatedSize);
+	this->map_lorom(0x80, 0xbf, 0x8000, 0xffff, this->CalculatedSize);
+	this->map_lorom(0xc0, 0xff, 0x0000, 0xffff, this->CalculatedSize);
+
+	this->map_LoROMSRAM();
+	this->map_WRAM();
+
+	this->map_WriteProtectROM();
 }
 
 void CMemory::Map_NoMAD1LoROMMap()
 {
-	printf("Map_NoMAD1LoROMMap\n");
-	map_System();
-
-	map_lorom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize);
-	map_lorom(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize);
-	map_lorom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize);
-	map_lorom(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize);
-
-	map_index(0x70, 0x7f, 0x0000, 0xffff, MAP_LOROM_SRAM, MAP_TYPE_RAM);
-	map_index(0xf0, 0xff, 0x0000, 0xffff, MAP_LOROM_SRAM, MAP_TYPE_RAM);
-
-	map_WRAM();
-
-	map_WriteProtectROM();
+	this->map_System();
+
+	this->map_lorom(0x00, 0x3f, 0x8000, 0xffff, this->CalculatedSize);
+	this->map_lorom(0x40, 0x7f, 0x0000, 0xffff, this->CalculatedSize);
+	this->map_lorom(0x80, 0xbf, 0x8000, 0xffff, this->CalculatedSize);
+	this->map_lorom(0xc0, 0xff, 0x0000, 0xffff, this->CalculatedSize);
+
+	this->map_index(0x70, 0x7f, 0x0000, 0xffff, MAP_LOROM_SRAM, MAP_TYPE_RAM);
+	this->map_index(0xf0, 0xff, 0x0000, 0xffff, MAP_LOROM_SRAM, MAP_TYPE_RAM);
+
+	this->map_WRAM();
+
+	this->map_WriteProtectROM();
 }
 
 void CMemory::Map_JumboLoROMMap()
 {
 	// XXX: Which game uses this?
-	printf("Map_JumboLoROMMap\n");
-	map_System();
-
-	map_lorom_offset(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize - 0x400000, 0x400000);
-	map_lorom_offset(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize - 0x400000, 0x400000);
-	map_lorom_offset(0x80, 0xbf, 0x8000, 0xffff, 0x400000, 0);
-	map_lorom_offset(0xc0, 0xff, 0x0000, 0xffff, 0x400000, 0x200000);
-
-	map_LoROMSRAM();
-	map_WRAM();
-
-	map_WriteProtectROM();
+	this->map_System();
+
+	this->map_lorom_offset(0x00, 0x3f, 0x8000, 0xffff, this->CalculatedSize - 0x400000, 0x400000);
+	this->map_lorom_offset(0x40, 0x7f, 0x0000, 0xffff, this->CalculatedSize - 0x400000, 0x400000);
+	this->map_lorom_offset(0x80, 0xbf, 0x8000, 0xffff, 0x400000, 0);
+	this->map_lorom_offset(0xc0, 0xff, 0x0000, 0xffff, 0x400000, 0x200000);
+
+	this->map_LoROMSRAM();
+	this->map_WRAM();
+
+	this->map_WriteProtectROM();
 }
 
 void CMemory::Map_ROM24MBSLoROMMap()
 {
 	// PCB: BSC-1A5M-01, BSC-1A7M-10
-	printf("Map_ROM24MBSLoROMMap\n");
-	map_System();
-
-	map_lorom_offset(0x00, 0x1f, 0x8000, 0xffff, 0x100000, 0);
-	map_lorom_offset(0x20, 0x3f, 0x8000, 0xffff, 0x100000, 0x100000);
-	map_lorom_offset(0x80, 0x9f, 0x8000, 0xffff, 0x100000, 0x200000);
-	map_lorom_offset(0xa0, 0xbf, 0x8000, 0xffff, 0x100000, 0x100000);
-
-	map_LoROMSRAM();
-	map_WRAM();
-
-	map_WriteProtectROM();
+	this->map_System();
+
+	this->map_lorom_offset(0x00, 0x1f, 0x8000, 0xffff, 0x100000, 0);
+	this->map_lorom_offset(0x20, 0x3f, 0x8000, 0xffff, 0x100000, 0x100000);
+	this->map_lorom_offset(0x80, 0x9f, 0x8000, 0xffff, 0x100000, 0x200000);
+	this->map_lorom_offset(0xa0, 0xbf, 0x8000, 0xffff, 0x100000, 0x100000);
+
+	this->map_LoROMSRAM();
+	this->map_WRAM();
+
+	this->map_WriteProtectROM();
 }
 
 void CMemory::Map_SRAM512KLoROMMap()
 {
-	printf("Map_SRAM512KLoROMMap\n");
-	map_System();
-
-	map_lorom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize);
-	map_lorom(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize);
-	map_lorom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize);
-	map_lorom(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize);
-
-	map_space(0x70, 0x70, 0x0000, 0xffff, SRAM);
-	map_space(0x71, 0x71, 0x0000, 0xffff, SRAM + 0x8000);
-	map_space(0x72, 0x72, 0x0000, 0xffff, SRAM + 0x10000);
-	map_space(0x73, 0x73, 0x0000, 0xffff, SRAM + 0x18000);
-
-	map_WRAM();
-
-	map_WriteProtectROM();
-}
-
-/*void CMemory::Map_SufamiTurboLoROMMap()
-{
-	printf("Map_SufamiTurboLoROMMap\n");
-	map_System();
-
-	map_lorom_offset(0x00, 0x1f, 0x8000, 0xffff, 0x40000, 0);
-	map_lorom_offset(0x20, 0x3f, 0x8000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA);
-	map_lorom_offset(0x40, 0x5f, 0x8000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB);
-	map_lorom_offset(0x80, 0x9f, 0x8000, 0xffff, 0x40000, 0);
-	map_lorom_offset(0xa0, 0xbf, 0x8000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA);
-	map_lorom_offset(0xc0, 0xdf, 0x8000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB);
-
-	if (Multi.sramSizeA)
-	{
-		map_index(0x60, 0x63, 0x8000, 0xffff, MAP_LOROM_SRAM, MAP_TYPE_RAM);
-		map_index(0xe0, 0xe3, 0x8000, 0xffff, MAP_LOROM_SRAM, MAP_TYPE_RAM);
-	}
-
-	if (Multi.sramSizeB)
-	{
-		map_index(0x70, 0x73, 0x8000, 0xffff, MAP_LOROM_SRAM_B, MAP_TYPE_RAM);
-		map_index(0xf0, 0xf3, 0x8000, 0xffff, MAP_LOROM_SRAM_B, MAP_TYPE_RAM);
-	}
-
-	map_WRAM();
-
-	map_WriteProtectROM();
-}*/
-
-/*void CMemory::Map_SufamiTurboPseudoLoROMMap()
-{
-	// for combined images
-	printf("Map_SufamiTurboPseudoLoROMMap\n");
-	map_System();
-
-	map_lorom_offset(0x00, 0x1f, 0x8000, 0xffff, 0x40000, 0);
-	map_lorom_offset(0x20, 0x3f, 0x8000, 0xffff, 0x100000, 0x100000);
-	map_lorom_offset(0x40, 0x5f, 0x8000, 0xffff, 0x100000, 0x200000);
-	map_lorom_offset(0x80, 0x9f, 0x8000, 0xffff, 0x40000, 0);
-	map_lorom_offset(0xa0, 0xbf, 0x8000, 0xffff, 0x100000, 0x100000);
-	map_lorom_offset(0xc0, 0xdf, 0x8000, 0xffff, 0x100000, 0x200000);
-
-	// I don't care :P
-	map_space(0x60, 0x63, 0x8000, 0xffff, SRAM - 0x8000);
-	map_space(0xe0, 0xe3, 0x8000, 0xffff, SRAM - 0x8000);
-	map_space(0x70, 0x73, 0x8000, 0xffff, SRAM + 0x4000 - 0x8000);
-	map_space(0xf0, 0xf3, 0x8000, 0xffff, SRAM + 0x4000 - 0x8000);
-
-	map_WRAM();
-
-	map_WriteProtectROM();
-}*/
-
-/*void CMemory::Map_SuperFXLoROMMap()
-{
-	printf("Map_SuperFXLoROMMap\n");
-	map_System();
-
-	// Replicate the first 2Mb of the ROM at ROM + 2MB such that each 32K
-	// block is repeated twice in each 64K block.
-	for (int c = 0; c < 64; c++)
-	{
-		memmove(&ROM[0x200000 + c * 0x10000], &ROM[c * 0x8000], 0x8000);
-		memmove(&ROM[0x208000 + c * 0x10000], &ROM[c * 0x8000], 0x8000);
-	}
-
-	map_lorom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize);
-	map_lorom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize);
-
-	map_hirom_offset(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize, 0);
-	map_hirom_offset(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize, 0);
-
-	map_space(0x00, 0x3f, 0x6000, 0x7fff, SRAM - 0x6000);
-	map_space(0x80, 0xbf, 0x6000, 0x7fff, SRAM - 0x6000);
-	map_space(0x70, 0x70, 0x0000, 0xffff, SRAM);
-	map_space(0x71, 0x71, 0x0000, 0xffff, SRAM + 0x10000);
-
-	map_WRAM();
-
-	map_WriteProtectROM();
-}*/
-
-/*void CMemory::Map_SetaDSPLoROMMap()
-{
-	printf("Map_SetaDSPLoROMMap\n");
-	map_System();
-
-	map_lorom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize);
-	map_lorom(0x40, 0x7f, 0x8000, 0xffff, CalculatedSize);
-	map_lorom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize);
-	map_lorom(0xc0, 0xff, 0x8000, 0xffff, CalculatedSize);
-
-	map_SetaDSP();
-
-    map_LoROMSRAM();
-	map_WRAM();
-
-	map_WriteProtectROM();
-}*/
+	this->map_System();
+
+	this->map_lorom(0x00, 0x3f, 0x8000, 0xffff, this->CalculatedSize);
+	this->map_lorom(0x40, 0x7f, 0x0000, 0xffff, this->CalculatedSize);
+	this->map_lorom(0x80, 0xbf, 0x8000, 0xffff, this->CalculatedSize);
+	this->map_lorom(0xc0, 0xff, 0x0000, 0xffff, this->CalculatedSize);
+
+	this->map_space(0x70, 0x70, 0x0000, 0xffff, &this->SRAM[0]);
+	this->map_space(0x71, 0x71, 0x0000, 0xffff, &this->SRAM[0x8000]);
+	this->map_space(0x72, 0x72, 0x0000, 0xffff, &this->SRAM[0x10000]);
+	this->map_space(0x73, 0x73, 0x0000, 0xffff, &this->SRAM[0x18000]);
+
+	this->map_WRAM();
+
+	this->map_WriteProtectROM();
+}
 
 void CMemory::Map_SDD1LoROMMap()
 {
-	printf("Map_SDD1LoROMMap\n");
-	map_System();
-
-	map_lorom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize);
-	map_lorom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize);
-
-	map_hirom_offset(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize, 0);
-	map_hirom_offset(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize, 0); // will be overwritten dynamically
-
-	map_index(0x70, 0x7f, 0x0000, 0x7fff, MAP_LOROM_SRAM, MAP_TYPE_RAM);
-
-	map_WRAM();
-
-	map_WriteProtectROM();
-}
-
-/*void CMemory::Map_SA1LoROMMap()
-{
-	printf("Map_SA1LoROMMap\n");
-	map_System();
-
-	map_lorom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize);
-	map_lorom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize);
-
-	map_hirom_offset(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize, 0);
-
-	map_space(0x00, 0x3f, 0x3000, 0x3fff, FillRAM);
-	map_space(0x80, 0xbf, 0x3000, 0x3fff, FillRAM);
-	map_index(0x00, 0x3f, 0x6000, 0x7fff, MAP_BWRAM, MAP_TYPE_I_O);
-	map_index(0x80, 0xbf, 0x6000, 0x7fff, MAP_BWRAM, MAP_TYPE_I_O);
-
-	for (int c = 0x40; c < 0x80; c++)
-		map_space(c, c, 0x0000, 0xffff, SRAM + (c & 1) * 0x10000);
-
-	map_WRAM();
-
-	map_WriteProtectROM();
-
-	// Now copy the map and correct it for the SA1 CPU.
-	memmove((void *) SA1.Map, (void *) Map, sizeof(Map));
-	memmove((void *) SA1.WriteMap, (void *) WriteMap, sizeof(WriteMap));
-
-	// SA-1 Banks 00->3f and 80->bf
-	for (int c = 0x000; c < 0x400; c += 0x10)
-	{
-		SA1.Map[c + 0] = SA1.Map[c + 0x800] = FillRAM + 0x3000;
-		SA1.Map[c + 1] = SA1.Map[c + 0x801] = (uint8_t *) MAP_NONE;
-		SA1.WriteMap[c + 0] = SA1.WriteMap[c + 0x800] = FillRAM + 0x3000;
-		SA1.WriteMap[c + 1] = SA1.WriteMap[c + 0x801] = (uint8_t *) MAP_NONE;
-	}
-
-	// SA-1 Banks 60->6f
-	for (int c = 0x600; c < 0x700; c++)
-		SA1.Map[c] = SA1.WriteMap[c] = (uint8_t *) MAP_BWRAM_BITMAP;
-
-	BWRAM = SRAM;
-}*/
+	this->map_System();
+
+	this->map_lorom(0x00, 0x3f, 0x8000, 0xffff, this->CalculatedSize);
+	this->map_lorom(0x80, 0xbf, 0x8000, 0xffff, this->CalculatedSize);
+
+	this->map_hirom_offset(0x40, 0x7f, 0x0000, 0xffff, this->CalculatedSize, 0);
+	this->map_hirom_offset(0xc0, 0xff, 0x0000, 0xffff, this->CalculatedSize, 0); // will be overwritten dynamically
+
+	this->map_index(0x70, 0x7f, 0x0000, 0x7fff, MAP_LOROM_SRAM, MAP_TYPE_RAM);
+
+	this->map_WRAM();
+
+	this->map_WriteProtectROM();
+}
 
 void CMemory::Map_HiROMMap()
 {
-	printf("Map_HiROMMap\n");
-	map_System();
-
-	map_hirom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize);
-	map_hirom(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize);
-	map_hirom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize);
-	map_hirom(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize);
-
-	/*if (Settings.DSP)
-		map_DSP();*/
-
-	map_HiROMSRAM();
-	map_WRAM();
-
-	map_WriteProtectROM();
+	this->map_System();
+
+	this->map_hirom(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize);
+	this->map_hirom(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize);
+	this->map_hirom(0x80, 0xbf, 0x8000, 0xffff, CalculatedSize);
+	this->map_hirom(0xc0, 0xff, 0x0000, 0xffff, CalculatedSize);
+
+	this->map_HiROMSRAM();
+	this->map_WRAM();
+
+	this->map_WriteProtectROM();
 }
 
 void CMemory::Map_ExtendedHiROMMap()
 {
-	printf("Map_ExtendedHiROMMap\n");
-	map_System();
-
-	map_hirom_offset(0x00, 0x3f, 0x8000, 0xffff, CalculatedSize - 0x400000, 0x400000);
-	map_hirom_offset(0x40, 0x7f, 0x0000, 0xffff, CalculatedSize - 0x400000, 0x400000);
-	map_hirom_offset(0x80, 0xbf, 0x8000, 0xffff, 0x400000, 0);
-	map_hirom_offset(0xc0, 0xff, 0x0000, 0xffff, 0x400000, 0);
-
-	map_HiROMSRAM();
-	map_WRAM();
-
-	map_WriteProtectROM();
-}
-
-/*void CMemory::Map_SameGameHiROMMap()
-{
-	printf("Map_SameGameHiROMMap\n");
-	map_System();
-
-	map_hirom_offset(0x00, 0x1f, 0x8000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA);
-	map_hirom_offset(0x20, 0x3f, 0x8000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB);
-	map_hirom_offset(0x40, 0x5f, 0x0000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA);
-	map_hirom_offset(0x60, 0x7f, 0x0000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB);
-	map_hirom_offset(0x80, 0x9f, 0x8000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA);
-	map_hirom_offset(0xa0, 0xbf, 0x8000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB);
-	map_hirom_offset(0xc0, 0xdf, 0x0000, 0xffff, Multi.cartSizeA, Multi.cartOffsetA);
-	map_hirom_offset(0xe0, 0xff, 0x0000, 0xffff, Multi.cartSizeB, Multi.cartOffsetB);
-
-	map_HiROMSRAM();
-	map_WRAM();
-
-	map_WriteProtectROM();
-}*/
-
-/*void CMemory::Map_SPC7110HiROMMap()
-{
-	printf("Map_SPC7110HiROMMap\n");
-	map_System();
-
-	map_index(0x00, 0x00, 0x6000, 0x7fff, MAP_HIROM_SRAM, MAP_TYPE_RAM);
-	map_hirom(0x00, 0x0f, 0x8000, 0xffff, CalculatedSize);
-	map_index(0x30, 0x30, 0x6000, 0x7fff, MAP_HIROM_SRAM, MAP_TYPE_RAM);
-	map_index(0x50, 0x50, 0x0000, 0xffff, MAP_SPC7110_DRAM, MAP_TYPE_ROM);
-	map_hirom(0x80, 0x8f, 0x8000, 0xffff, CalculatedSize);
-	map_hirom_offset(0xc0, 0xcf, 0x0000, 0xffff, CalculatedSize, 0);
-	map_index(0xd0, 0xff, 0x0000, 0xffff, MAP_SPC7110_ROM,  MAP_TYPE_ROM);
-
-	map_WRAM();
-
-	map_WriteProtectROM();
-}*/
-
-// checksum
-
-uint16_t CMemory::checksum_calc_sum (uint8_t *data, uint32_t length)
-{
-	uint16_t	sum = 0;
-
-	for (uint32_t i = 0; i < length; i++)
-		sum += data[i];
-
-	return sum;
-}
-
-uint16_t CMemory::checksum_mirror_sum (uint8_t *start, uint32_t &length, uint32_t mask)
-{
-	// from NSRT
-	while (!(length & mask))
-		mask >>= 1;
-
-	uint16_t	part1 = checksum_calc_sum(start, mask);
-	uint16_t	part2 = 0;
-
-	uint32_t	next_length = length - mask;
-	if (next_length)
-	{
-		part2 = checksum_mirror_sum(start + mask, next_length, mask >> 1);
-
-		while (next_length < mask)
-		{
-			next_length += next_length;
-			part2 += part2;
-		}
-
-		length = mask + mask;
-	}
-
-	return part1 + part2;
-}
-
-void CMemory::Checksum_Calculate()
-{
-	// from NSRT
-	uint16_t	sum = 0;
-
-	if (Settings.BS && !Settings.BSXItself)
-		sum = checksum_calc_sum(ROM, CalculatedSize) - checksum_calc_sum(ROM + (HiROM ? 0xffb0 : 0x7fb0), 48);
-	else
-	if (Settings.SPC7110)
-	{
-		sum = checksum_calc_sum(ROM, CalculatedSize);
-		if (CalculatedSize == 0x300000)
-			sum += sum;
-	}
-	else
-	{
-		if (CalculatedSize & 0x7fff)
-			sum = checksum_calc_sum(ROM, CalculatedSize);
-		else
-		{
-			uint32_t	length = CalculatedSize;
-			sum = checksum_mirror_sum(ROM, length);
-		}
-	}
-
-	CalculatedChecksum = sum;
-}
-
-// information
-
-/*const char * CMemory::MapType()
-{
-	return HiROM ? ((ExtendedFormat != NOPE) ? "ExHiROM": "HiROM") : "LoROM";
-}*/
-
-/*const char * CMemory::StaticRAMSize()
-{
-	static char	str[20];
-
-	if (SRAMSize > 16)
-		strcpy(str, "Corrupt");
-	else
-		sprintf(str, "%dKbits", 8 * (SRAMMask + 1) / 1024);
-
-	return str;
-}*/
-
-/*const char * CMemory::Size()
-{
-	static char	str[20];
-
-	if (Multi.cartType == 4)
-		strcpy(str, "N/A");
-	else
-	if (ROMSize < 7 || ROMSize - 7 > 23)
-		strcpy(str, "Corrupt");
-	else
-		sprintf(str, "%dMbits", 1 << (ROMSize - 7));
-
-	return str;
-}*/
-
-/*const char * CMemory::Revision()
-{
-	static char	str[20];
-
-	sprintf(str, "1.%d", HiROM ? ((ExtendedFormat != NOPE) ? ROM[0x40ffdb] : ROM[0xffdb]) : ROM[0x7fdb]);
-
-	return str;
-}*/
-
-/*const char * CMemory::KartContents()
-{
-	static char			str[64];
-	static const char	*contents[3] = { "ROM", "ROM+RAM", "ROM+RAM+BAT" };
-
-	char	chip[16];
-
-	if (ROMType == 0 && !Settings.BS)
-		return "ROM";
-
-	if (Settings.BS)
-		strcpy(chip, "+BS");
-	else
-	if (Settings.SuperFX)
-		strcpy(chip, "+Super FX");
-	else
-	if (Settings.SDD1)
-		strcpy(chip, "+S-DD1");
-	else
-	if (Settings.OBC1)
-		strcpy(chip, "+OBC1");
-	else
-	if (Settings.SA1)
-		strcpy(chip, "+SA-1");
-	else
-	if (Settings.SPC7110RTC)
-		strcpy(chip, "+SPC7110+RTC");
-	else
-	if (Settings.SPC7110)
-		strcpy(chip, "+SPC7110");
-	else
-	if (Settings.SRTC)
-		strcpy(chip, "+S-RTC");
-	else
-	if (Settings.C4)
-		strcpy(chip, "+C4");
-	else
-	if (Settings.SETA == ST_010)
-		strcpy(chip, "+ST-010");
-	else
-	if (Settings.SETA == ST_011)
-		strcpy(chip, "+ST-011");
-	else
-	if (Settings.SETA == ST_018)
-		strcpy(chip, "+ST-018");
-	else
-	if (Settings.DSP)
-		sprintf(chip, "+DSP-%d", Settings.DSP);
-	else
-		strcpy(chip, "");
-
-	sprintf(str, "%s%s", contents[(ROMType & 0xf) % 3], chip);
-
-	return str;
-}*/
-
-/*const char * CMemory::Country()
-{
-	switch (ROMRegion)
-	{
-		case 0:		return "Japan";
-		case 1:		return "USA and Canada";
-		case 2:		return "Oceania, Europe and Asia";
-		case 3:		return "Sweden";
-		case 4:		return "Finland";
-		case 5:		return "Denmark";
-		case 6:		return "France";
-		case 7:		return "Holland";
-		case 8:		return "Spain";
-		case 9:		return "Germany, Austria and Switzerland";
-		case 10:	return "Italy";
-		case 11:	return "Hong Kong and China";
-		case 12:	return "Indonesia";
-		case 13:	return "South Korea";
-		default:	return "Unknown";
-	}
-}*/
-
-/*const char * CMemory::PublishingCompany()
-{
-	if (CompanyId >= (int) (sizeof(nintendo_licensees) / sizeof(nintendo_licensees[0])) || CompanyId < 0)
-		return "Unknown";
-
-	if (nintendo_licensees[CompanyId] == NULL)
-		return "Unknown";
-
-	return nintendo_licensees[CompanyId];
-}*/
-
-/*void CMemory::MakeRomInfoText (char *romtext)
-{
-	char	temp[256];
-
-	romtext[0] = 0;
-
-	sprintf(temp,   "            Cart Name: %s", ROMName);
-	strcat(romtext, temp);
-	sprintf(temp, "\n            Game Code: %s", ROMId);
-	strcat(romtext, temp);
-	sprintf(temp, "\n             Contents: %s", KartContents());
-	strcat(romtext, temp);
-	sprintf(temp, "\n                  Map: %s", MapType());
-	strcat(romtext, temp);
-	sprintf(temp, "\n                Speed: 0x%02X (%s)", ROMSpeed, (ROMSpeed & 0x10) ? "FastROM" : "SlowROM");
-	strcat(romtext, temp);
-	sprintf(temp, "\n                 Type: 0x%02X", ROMType);
-	strcat(romtext, temp);
-	sprintf(temp, "\n    Size (calculated): %dMbits", CalculatedSize / 0x20000);
-	strcat(romtext, temp);
-	sprintf(temp, "\n        Size (header): %s", Size());
-	strcat(romtext, temp);
-	sprintf(temp, "\n            SRAM size: %s", StaticRAMSize());
-	strcat(romtext, temp);
-	sprintf(temp, "\nChecksum (calculated): 0x%04X", CalculatedChecksum);
-	strcat(romtext, temp);
-	sprintf(temp, "\n    Checksum (header): 0x%04X", ROMChecksum);
-	strcat(romtext, temp);
-	sprintf(temp, "\n  Complement (header): 0x%04X", ROMComplementChecksum);
-	strcat(romtext, temp);
-	sprintf(temp, "\n         Video Output: %s", (ROMRegion > 12 || ROMRegion < 2) ? "NTSC 60Hz" : "PAL 50Hz");
-	strcat(romtext, temp);
-	sprintf(temp, "\n             Revision: %s", Revision());
-	strcat(romtext, temp);
-	sprintf(temp, "\n             Licensee: %s", PublishingCompany());
-	strcat(romtext, temp);
-	sprintf(temp, "\n               Region: %s", Country());
-	strcat(romtext, temp);
-	sprintf(temp, "\n                CRC32: 0x%08X", ROMCRC32);
-	strcat(romtext, temp);
-}*/
+	this->map_System();
+
+	this->map_hirom_offset(0x00, 0x3f, 0x8000, 0xffff, this->CalculatedSize - 0x400000, 0x400000);
+	this->map_hirom_offset(0x40, 0x7f, 0x0000, 0xffff, this->CalculatedSize - 0x400000, 0x400000);
+	this->map_hirom_offset(0x80, 0xbf, 0x8000, 0xffff, 0x400000, 0);
+	this->map_hirom_offset(0xc0, 0xff, 0x0000, 0xffff, 0x400000, 0);
+
+	this->map_HiROMSRAM();
+	this->map_WRAM();
+
+	this->map_WriteProtectROM();
+}
 
 // hack
 
-bool CMemory::match_na (const char *str)
-{
-	return strcmp(ROMName, str) == 0;
-}
-
-bool CMemory::match_nn (const char *str)
-{
-	return strncmp(ROMName, str, strlen(str)) == 0;
-}
-
-/*bool CMemory::match_nc (const char *str)
-{
-	return strncasecmp(ROMName, str, strlen(str)) == 0;
-}*/
-
-bool CMemory::match_id (const char *str)
-{
-	return strncmp(ROMId, str, strlen(str)) == 0;
+bool CMemory::match_na(const char *str)
+{
+	return !strcmp(this->ROMName, str);
+}
+
+bool CMemory::match_nn(const char *str)
+{
+	return !strncmp(this->ROMName, str, strlen(str));
+}
+
+bool CMemory::match_id(const char *str)
+{
+	return !strncmp(this->ROMId, str, strlen(str));
 }
 
 void CMemory::ApplyROMFixes()
 {
 	Settings.BlockInvalidVRAMAccess = Settings.BlockInvalidVRAMAccessMaster;
-
-	//// Warnings
-
-	// Reject strange hacked games
-	/*if ((ROMCRC32 == 0x6810aa95) ||
-		(ROMCRC32 == 0x340f23e5) ||
-		(ROMCRC32 == 0x77fd806a) ||
-		(match_nn("HIGHWAY BATTLE 2")) ||
-		(match_na("FX SKIING NINTENDO 96") && (ROM[0x7fda] == 0)) ||
-		(match_nn("HONKAKUHA IGO GOSEI")   && (ROM[0xffd5] != 0x31)))
-	{
-		Settings.DisplayColor = BUILD_PIXEL(31, 0, 0);
-		SET_UI_COLOR(255, 0, 0);
-	}*/
 
 	//// APU timing hacks :(
 
@@ -3510,51 +1036,51 @@
 
 	if (!Settings.DisableGameSpecificHacks)
 	{
-		if (match_id("AVCJ"))                                      // Rendering Ranger R2
+		if (this->match_id("AVCJ")) // Rendering Ranger R2
 			Timings.APUSpeedup = 4;
 
-		if (match_na("GAIA GENSOUKI 1 JPN")                     || // Gaia Gensouki
-			match_id("JG  ")                                    || // Illusion of Gaia
-			match_id("CQ  ")                                    || // Stunt Race FX
-			match_na("SOULBLADER - 1")                          || // Soul Blader
-			match_na("SOULBLAZER - 1 USA")                      || // Soul Blazer
-			match_na("SLAP STICK 1 JPN")                        || // Slap Stick
-			match_id("E9 ")                                     || // Robotrek
-			match_nn("ACTRAISER")                               || // Actraiser
-			match_nn("ActRaiser-2")                             || // Actraiser 2
-			match_id("AQT")                                     || // Tenchi Souzou, Terranigma
-			match_id("ATV")                                     || // Tales of Phantasia
-			match_id("ARF")                                     || // Star Ocean
-			match_id("APR")                                     || // Zen-Nippon Pro Wrestling 2 - 3-4 Budoukan
-			match_id("A4B")                                     || // Super Bomberman 4
-			match_id("Y7 ")                                     || // U.F.O. Kamen Yakisoban - Present Ban
-			match_id("Y9 ")                                     || // U.F.O. Kamen Yakisoban - Shihan Ban
-			match_id("APB")                                     || // Super Bomberman - Panic Bomber W
-			match_na("DARK KINGDOM")                            || // Dark Kingdom
-			match_na("ZAN3 SFC")                                || // Zan III Spirits
-			match_na("HIOUDEN")                                 || // Hiouden - Mamono-tachi Tono Chikai
-			match_na("\xC3\xDD\xBC\xC9\xB3\xC0")                || // Tenshi no Uta
-			match_na("FORTUNE QUEST")                           || // Fortune Quest - Dice wo Korogase
-			match_na("FISHING TO BASSING")                      || // Shimono Masaki no Fishing To Bassing
-			match_na("OHMONO BLACKBASS")                        || // Oomono Black Bass Fishing - Jinzouko Hen
-			match_na("MASTERS")                                 || // Harukanaru Augusta 2 - Masters
-			match_na("SFC \xB6\xD2\xDD\xD7\xB2\xC0\xDE\xB0")    || // Kamen Rider
-			match_na("ZENKI TENCHIMEIDOU")					    || // Kishin Douji Zenki - Tenchi Meidou
-			match_nn("TokyoDome '95Battle 7")                   || // Shin Nippon Pro Wrestling Kounin '95 - Tokyo Dome Battle 7
-			match_nn("SWORD WORLD SFC")                         || // Sword World SFC/2
-			match_nn("LETs PACHINKO(")                          || // BS Lets Pachinko Nante Gindama 1/2/3/4
-			match_nn("THE FISHING MASTER")                      || // Mark Davis The Fishing Master
-			match_nn("Parlor")                                  || // Parlor mini/2/3/4/5/6/7, Parlor Parlor!/2/3/4/5
-			match_na("HEIWA Parlor!Mini8")                      || // Parlor mini 8
-			match_nn("SANKYO Fever! \xCC\xA8\xB0\xCA\xDE\xB0!"))   // SANKYO Fever! Fever!
+		if (this->match_na("GAIA GENSOUKI 1 JPN") || // Gaia Gensouki
+			this->match_id("JG  ") || // Illusion of Gaia
+			this->match_id("CQ  ") || // Stunt Race FX
+			this->match_na("SOULBLADER - 1") || // Soul Blader
+			this->match_na("SOULBLAZER - 1 USA") || // Soul Blazer
+			this->match_na("SLAP STICK 1 JPN") || // Slap Stick
+			this->match_id("E9 ") || // Robotrek
+			this->match_nn("ACTRAISER") || // Actraiser
+			this->match_nn("ActRaiser-2") || // Actraiser 2
+			this->match_id("AQT") || // Tenchi Souzou, Terranigma
+			this->match_id("ATV") || // Tales of Phantasia
+			this->match_id("ARF") || // Star Ocean
+			this->match_id("APR") || // Zen-Nippon Pro Wrestling 2 - 3-4 Budoukan
+			this->match_id("A4B") || // Super Bomberman 4
+			this->match_id("Y7 ") || // U.F.O. Kamen Yakisoban - Present Ban
+			this->match_id("Y9 ") || // U.F.O. Kamen Yakisoban - Shihan Ban
+			this->match_id("APB") || // Super Bomberman - Panic Bomber W
+			this->match_na("DARK KINGDOM") || // Dark Kingdom
+			this->match_na("ZAN3 SFC") || // Zan III Spirits
+			this->match_na("HIOUDEN") || // Hiouden - Mamono-tachi Tono Chikai
+			this->match_na("\xC3\xDD\xBC\xC9\xB3\xC0") || // Tenshi no Uta
+			this->match_na("FORTUNE QUEST") || // Fortune Quest - Dice wo Korogase
+			this->match_na("FISHING TO BASSING") || // Shimono Masaki no Fishing To Bassing
+			this->match_na("OHMONO BLACKBASS") || // Oomono Black Bass Fishing - Jinzouko Hen
+			this->match_na("MASTERS") || // Harukanaru Augusta 2 - Masters
+			this->match_na("SFC \xB6\xD2\xDD\xD7\xB2\xC0\xDE\xB0") || // Kamen Rider
+			this->match_na("ZENKI TENCHIMEIDOU") || // Kishin Douji Zenki - Tenchi Meidou
+			this->match_nn("TokyoDome '95Battle 7") || // Shin Nippon Pro Wrestling Kounin '95 - Tokyo Dome Battle 7
+			this->match_nn("SWORD WORLD SFC") || // Sword World SFC/2
+			this->match_nn("LETs PACHINKO(") || // BS Lets Pachinko Nante Gindama 1/2/3/4
+			this->match_nn("THE FISHING MASTER") || // Mark Davis The Fishing Master
+			this->match_nn("Parlor") || // Parlor mini/2/3/4/5/6/7, Parlor Parlor!/2/3/4/5
+			this->match_na("HEIWA Parlor!Mini8") || // Parlor mini 8
+			this->match_nn("SANKYO Fever! \xCC\xA8\xB0\xCA\xDE\xB0!")) // SANKYO Fever! Fever!
 			Timings.APUSpeedup = 1;
 
-		if (match_na ("EARTHWORM JIM 2")						|| // Earthworm Jim 2
-			match_na ("NBA Hangtime")							|| // NBA Hang Time
-			match_na ("MSPACMAN")								|| // Ms Pacman
-			match_na ("THE MASK")								|| // The Mask
-			match_na ("PRIMAL RAGE")							|| // Primal Rage
-			match_na ("DOOM TROOPERS"))							   // Doom Troopers
+		if (this->match_na("EARTHWORM JIM 2") || // Earthworm Jim 2
+			this->match_na("NBA Hangtime") || // NBA Hang Time
+			this->match_na("MSPACMAN") || // Ms Pacman
+			this->match_na("THE MASK") || // The Mask
+			this->match_na("PRIMAL RAGE") || // Primal Rage
+			this->match_na("DOOM TROOPERS")) // Doom Troopers
 			Timings.APUAllowTimeOverflow = true;
 	}
 
@@ -3563,7 +1089,7 @@
 
 	//// Other timing hacks :(
 
-	Timings.HDMAStart   = SNES_HDMA_START_HC + Settings.HDMATimingHack - 100;
+	Timings.HDMAStart = SNES_HDMA_START_HC + Settings.HDMATimingHack - 100;
 	Timings.HBlankStart = SNES_HBLANK_START_HC + Timings.HDMAStart - SNES_HDMA_START_HC;
 	Timings.IRQTriggerCycles = 10;
 
@@ -3571,757 +1097,48 @@
 	{
 		// The delay to sync CPU and DMA which Snes9x cannot emulate.
 		// Some games need really severe delay timing...
-		if (match_na("BATTLE GRANDPRIX")) // Battle Grandprix
-		{
+		if (this->match_na("BATTLE GRANDPRIX")) // Battle Grandprix
 			Timings.DMACPUSync = 20;
-			printf("DMA sync: %d\n", Timings.DMACPUSync);
-		}
-	}
-
-	if (!Settings.DisableGameSpecificHacks)
-	{
+
 		// An infinite loop reads $4212 and waits V-blank end, whereas VIRQ is set V=0.
 		// If Snes9x succeeds to escape from the loop before jumping into the IRQ handler, the game goes further.
 		// If Snes9x jumps into the IRQ handler before escaping from the loop,
 		// Snes9x cannot escape from the loop permanently because the RTI is in the next V-blank.
-		if (match_na("Aero the AcroBat 2"))
-		{
+		if (this->match_na("Aero the AcroBat 2"))
 			Timings.IRQPendCount = 2;
-			printf("IRQ count hack: %d\n", Timings.IRQPendCount);
-		}
-	}
-
-	if (!Settings.DisableGameSpecificHacks)
-	{
+
 		// XXX: What's happening?
-		if (match_na("X-MEN")) // Spider-Man and the X-Men
-		{
+		if (this->match_na("X-MEN")) // Spider-Man and the X-Men
 			Settings.BlockInvalidVRAMAccess = false;
-			printf("Invalid VRAM access hack\n");
-		}
-	}
-
-	//// SRAM initial value
-
-	if (!Settings.DisableGameSpecificHacks)
-	{
-		if (match_na("HITOMI3"))
+
+		//// SRAM initial value
+
+		if (this->match_na("HITOMI3"))
 		{
 			SRAMSize = 1;
 			SRAMMask = ((1 << (SRAMSize + 3)) * 128) - 1;
 		}
 
 		// SRAM value fixes
-		if (match_na("SUPER DRIFT OUT")      || // Super Drift Out
-			match_na("SATAN IS OUR FATHER!") ||
-			match_na("goemon 4"))               // Ganbare Goemon Kirakira Douchuu
+		if (this->match_na("SUPER DRIFT OUT") || // Super Drift Out
+			this->match_na("SATAN IS OUR FATHER!") ||
+			this->match_na("goemon 4")) // Ganbare Goemon Kirakira Douchuu
 			SNESGameFixes.SRAMInitialValue = 0x00;
 
 		// Additional game fixes by sanmaiwashi ...
 		// XXX: unnecessary?
-		if (match_na("SFX \xC5\xB2\xC4\xB6\xDE\xDD\xC0\xDE\xD1\xD3\xC9\xB6\xDE\xC0\xD8 1")) // SD Gundam Gaiden - Knight Gundam Monogatari
+		if (this->match_na("SFX \xC5\xB2\xC4\xB6\xDE\xDD\xC0\xDE\xD1\xD3\xC9\xB6\xDE\xC0\xD8 1")) // SD Gundam Gaiden - Knight Gundam Monogatari
 			SNESGameFixes.SRAMInitialValue = 0x6b;
 
 		// others: BS and ST-01x games are 0x00.
-	}
-
-	//// OAM hacks :(
-
-	if (!Settings.DisableGameSpecificHacks)
-	{
+
+		//// OAM hacks :(
+
 		// OAM hacks because we don't fully understand the behavior of the SNES.
 		// Totally wacky display in 2P mode...
 		// seems to need a disproven behavior, so we're definitely overlooking some other bug?
 		if (match_nn("UNIRACERS")) // Uniracers
-		{
 			SNESGameFixes.Uniracers = true;
-			printf("Applied Uniracers hack.\n");
-		}
-	}
-}
-
-// UPS % IPS
-
-/*static uint32_t ReadUPSPointer (const uint8_t *data, unsigned &addr, unsigned size)
-{
-	uint32_t offset = 0, shift = 1;
-	while(addr < size) {
-		uint8_t x = data[addr++];
-		offset += (x & 0x7f) * shift;
-		if(x & 0x80) break;
-		shift <<= 7;
-		offset += shift;
-	}
-	return offset;
-}
-
-//NOTE: UPS patches are *never* created against a headered ROM!
-//this is per the UPS file specification. however, do note that it is
-//technically possible for a non-compliant patcher to ignore this requirement.
-//therefore, it is *imperative* that no emulator support such patches.
-//thusly, we ignore the "long offset" parameter below. failure to do so would
-//completely invalidate the purpose of UPS; which is to avoid header vs
-//no-header patching errors that result in IPS patches having a 50/50 chance of
-//being applied correctly.
-
-static bool ReadUPSPatch (Reader *r, long, int32_t &rom_size)
-{
-	//Reader lacks size() and rewind(), so we need to read in the file to get its size
-	uint8_t *data = new uint8_t[8 * 1024 * 1024];  //allocate a lot of memory, better safe than sorry ...
-	uint32_t size = 0;
-	while(true) {
-		int value = r->get_char();
-		if(value == EOF) break;
-		data[size++] = value;
-		if(size >= 8 * 1024 * 1024) {
-			//prevent buffer overflow: SNES-made UPS patches should never be this big anyway ...
-			delete[] data;
-			return false;
-		}
-	}
-
-	//4-byte header + 1-byte input size + 1-byte output size + 4-byte patch CRC32 + 4-byte unpatched CRC32 + 4-byte patched CRC32
-	if(size < 18) { delete[] data; return false; }  //patch is too small
-
-	uint32_t addr = 0;
-	if(data[addr++] != 'U') { delete[] data; return false; }  //patch has an invalid header
-	if(data[addr++] != 'P') { delete[] data; return false; }  //...
-	if(data[addr++] != 'S') { delete[] data; return false; }  //...
-	if(data[addr++] != '1') { delete[] data; return false; }  //...
-
-	uint32_t patch_crc32 = caCRC32(data, size - 4);  //don't include patch CRC32 itself in CRC32 calculation
-	uint32_t rom_crc32 = caCRC32(Memory.ROM, rom_size);
-	uint32_t px_crc32 = (data[size - 12] << 0) + (data[size - 11] << 8) + (data[size - 10] << 16) + (data[size -  9] << 24);
-	uint32_t py_crc32 = (data[size -  8] << 0) + (data[size -  7] << 8) + (data[size -  6] << 16) + (data[size -  5] << 24);
-	uint32_t pp_crc32 = (data[size -  4] << 0) + (data[size -  3] << 8) + (data[size -  2] << 16) + (data[size -  1] << 24);
-	if(patch_crc32 != pp_crc32) { delete[] data; return false; }  //patch is corrupted
-	if((rom_crc32 != px_crc32) && (rom_crc32 != py_crc32)) { delete[] data; return false; }  //patch is for a different ROM
-
-	uint32_t px_size = ReadUPSPointer(data, addr, size);
-	uint32_t py_size = ReadUPSPointer(data, addr, size);
-	uint32_t out_size = ((uint32_t) rom_size == px_size) ? py_size : px_size;
-	if(out_size > CMemory::MAX_ROM_SIZE) { delete[] data; return false; }  //applying this patch will overflow Memory.ROM buffer
-
-	//fill expanded area with 0x00s; so that XORing works as expected below.
-	//note that this is needed (and works) whether output ROM is larger or smaller than pre-patched ROM
-	for(unsigned i = min((uint32_t) rom_size, out_size); i < max((uint32_t) rom_size, out_size); i++) {
-		Memory.ROM[i] = 0x00;
-	}
-
-	uint32_t relative = 0;
-	while(addr < size - 12) {
-		relative += ReadUPSPointer(data, addr, size);
-		while(addr < size - 12) {
-			uint8_t x = data[addr++];
-			Memory.ROM[relative++] ^= x;
-			if(!x) break;
-		}
-	}
-
-	rom_size = out_size;
-	delete[] data;
-
-	uint32_t out_crc32 = caCRC32(Memory.ROM, rom_size);
-	if(((rom_crc32 == px_crc32) && (out_crc32 == py_crc32))
-	|| ((rom_crc32 == py_crc32) && (out_crc32 == px_crc32))
-	) {
-		return true;
-	} else {
-		//technically, reaching here means that patching has failed.
-		//we should return false, but unfortunately Memory.ROM has already
-		//been modified above and cannot be undone. to do this properly, we
-		//would need to make a copy of Memory.ROM, apply the patch, and then
-		//copy that back to Memory.ROM.
-		//
-		//however, the only way for this case to happen is if the UPS patch file
-		//itself is corrupted, which should be detected by the patch CRC32 check
-		//above anyway. errors due to the wrong ROM or patch file being used are
-		//already caught above.
-		fprintf(stderr, "WARNING: UPS patching appears to have failed.\nGame may not be playable.\n");
-		return true;
-	}
-}
-
-static long ReadInt (Reader *r, unsigned nbytes)
-{
-	long	v = 0;
-
-	while (nbytes--)
-	{
-		int	c = r->get_char();
-		if (c == EOF)
-			return -1;
-		v = (v << 8) | (c & 0xFF);
-	}
-
-	return v;
-}
-
-static bool ReadIPSPatch (Reader *r, long offset, int32_t &rom_size)
-{
-	const int32_t	IPS_EOF = 0x00454F46l;
-	int32_t		ofs;
-	char		fname[6];
-
-	fname[5] = 0;
-	for (int i = 0; i < 5; i++)
-	{
-		int	c = r->get_char();
-		if (c == EOF)
-			return 0;
-		fname[i] = (char) c;
-	}
-
-	if (strncmp(fname, "PATCH", 5))
-		return 0;
-
-	for (;;)
-	{
-		long	len, rlen;
-		int		rchar;
-
-		ofs = ReadInt(r, 3);
-		if (ofs == -1)
-			return 0;
-
-		if (ofs == IPS_EOF)
-			break;
-
-		ofs -= offset;
-
-		len = ReadInt(r, 2);
-		if (len == -1)
-			return 0;
-
-		if (len)
-		{
-			if (ofs + len > CMemory::MAX_ROM_SIZE)
-				return 0;
-
-			while (len--)
-			{
-				rchar = r->get_char();
-				if (rchar == EOF)
-					return 0;
-				Memory.ROM[ofs++] = (uint8_t) rchar;
-			}
-
-			if (ofs > rom_size)
-				rom_size = ofs;
-		}
-		else
-		{
-			rlen = ReadInt(r, 2);
-			if (rlen == -1)
-				return 0;
-
-			rchar = r->get_char();
-			if (rchar == EOF)
-				return 0;
-
-			if (ofs + rlen > CMemory::MAX_ROM_SIZE)
-				return 0;
-
-			while (rlen--)
-				Memory.ROM[ofs++] = (uint8_t) rchar;
-
-			if (ofs > rom_size)
-				rom_size = ofs;
-		}
-	}
-
-	ofs = ReadInt(r, 3);
-	if (ofs != -1 && ofs - offset < rom_size)
-		rom_size = ofs - offset;
-
-	return 1;
-}*/
-
-#ifdef UNZIP_SUPPORT
-static int unzFindExtension (unzFile &file, const char *ext, bool restart, bool print)
-{
-	unz_file_info	info;
-	int				port, l = strlen(ext);
-
-	if (restart)
-		port = unzGoToFirstFile(file);
-	else
-		port = unzGoToNextFile(file);
-
-	while (port == UNZ_OK)
-	{
-		int		len;
-		char	name[132];
-
-		unzGetCurrentFileInfo(file, &info, name, 128, NULL, 0, NULL, 0);
-		len = strlen(name);
-
-		if (len >= l + 1 && name[len - l - 1] == '.' && strcasecmp(name + len - l, ext) == 0 && unzOpenCurrentFile(file) == UNZ_OK)
-		{
-			if (print)
-				printf("Using IPS or UPS patch %s", name);
-
-			return port;
-		}
-
-		port = unzGoToNextFile(file);
-	}
-
-	return port;
-}
-#endif
-
-/*void CMemory::CheckForAnyPatch (const char *rom_filename, bool header, int32_t &rom_size)
-{
-	if (Settings.NoPatch)
-		return;
-
-	STREAM		patch_file  = NULL;
-	uint32_t		i;
-	long		offset = header ? 512 : 0;
-	int			ret;
-	bool		flag;
-	char		dir[_MAX_DIR + 1], drive[_MAX_DRIVE + 1], name[_MAX_FNAME + 1], ext[_MAX_EXT + 1], ips[_MAX_EXT + 3], fname[PATH_MAX + 1];
-	const char	*n;
-
-	// UPS
-
-	_splitpath(rom_filename, drive, dir, name, ext);
-	_makepath(fname, drive, dir, name, "ups");
-
-	if ((patch_file = OPEN_STREAM(fname, "rb")) != NULL)
-	{
-		printf("Using UPS patch %s", fname);
-
-		ret = ReadUPSPatch(new fReader(patch_file), 0, rom_size);
-		CLOSE_STREAM(patch_file);
-
-		if (ret)
-		{
-			printf("!\n");
-			return;
-		}
-		else
-			printf(" failed!\n");
-	}
-
-#ifdef UNZIP_SUPPORT
-	if (!strcasecmp(ext, "zip") || !strcasecmp(ext, ".zip"))
-	{
-		unzFile	file = unzOpen(rom_filename);
-		if (file)
-		{
-			int	port = unzFindExtension(file, "ups");
-			if (port == UNZ_OK)
-			{
-				printf(" in %s", rom_filename);
-
-				ret = ReadUPSPatch(new unzReader(file), offset, rom_size);
-				unzCloseCurrentFile(file);
-
-				if (ret)
-					printf("!\n");
-				else
-					printf(" failed!\n");
-			}
-		}
-	}
-#endif
-
-	n = S9xGetFilename(".ups", IPS_DIR);
-
-	if ((patch_file = OPEN_STREAM(n, "rb")) != NULL)
-	{
-		printf("Using UPS patch %s", n);
-
-		ret = ReadUPSPatch(new fReader(patch_file), 0, rom_size);
-		CLOSE_STREAM(patch_file);
-
-		if (ret)
-		{
-			printf("!\n");
-			return;
-		}
-		else
-			printf(" failed!\n");
-	}
-
-	// IPS
-
-	_splitpath(rom_filename, drive, dir, name, ext);
-	_makepath(fname, drive, dir, name, "ips");
-
-	if ((patch_file = OPEN_STREAM(fname, "rb")) != NULL)
-	{
-		printf("Using IPS patch %s", fname);
-
-		ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size);
-		CLOSE_STREAM(patch_file);
-
-		if (ret)
-		{
-			printf("!\n");
-			return;
-		}
-		else
-			printf(" failed!\n");
-	}
-
-	if (_MAX_EXT > 6)
-	{
-		i = 0;
-		flag = false;
-
-		do
-		{
-			snprintf(ips, 8, "%03d.ips", i);
-			_makepath(fname, drive, dir, name, ips);
-
-			if (!(patch_file = OPEN_STREAM(fname, "rb")))
-				break;
-
-			printf("Using IPS patch %s", fname);
-
-			ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size);
-			CLOSE_STREAM(patch_file);
-
-			if (ret)
-			{
-				printf("!\n");
-				flag = true;
-			}
-			else
-			{
-				printf(" failed!\n");
-				break;
-			}
-		} while (++i < 1000);
-
-		if (flag)
-			return;
-	}
-
-	if (_MAX_EXT > 3)
-	{
-		i = 0;
-		flag = false;
-
-		do
-		{
-			snprintf(ips, _MAX_EXT + 2, "ips%d", i);
-			if (strlen(ips) > _MAX_EXT)
-				break;
-			_makepath(fname, drive, dir, name, ips);
-
-			if (!(patch_file = OPEN_STREAM(fname, "rb")))
-				break;
-
-			printf("Using IPS patch %s", fname);
-
-			ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size);
-			CLOSE_STREAM(patch_file);
-
-			if (ret)
-			{
-				printf("!\n");
-				flag = true;
-			}
-			else
-			{
-				printf(" failed!\n");
-				break;
-			}
-		} while (++i != 0);
-
-		if (flag)
-			return;
-	}
-
-	if (_MAX_EXT > 2)
-	{
-		i = 0;
-		flag = false;
-
-		do
-		{
-			snprintf(ips, 4, "ip%d", i);
-			_makepath(fname, drive, dir, name, ips);
-
-			if (!(patch_file = OPEN_STREAM(fname, "rb")))
-				break;
-
-			printf("Using IPS patch %s", fname);
-
-			ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size);
-			CLOSE_STREAM(patch_file);
-
-			if (ret)
-			{
-				printf("!\n");
-				flag = true;
-			}
-			else
-			{
-				printf(" failed!\n");
-				break;
-			}
-		} while (++i < 10);
-
-		if (flag)
-			return;
-	}
-
-#ifdef UNZIP_SUPPORT
-	if (!strcasecmp(ext, "zip") || !strcasecmp(ext, ".zip"))
-	{
-		unzFile	file = unzOpen(rom_filename);
-		if (file)
-		{
-			int	port = unzFindExtension(file, "ips");
-			while (port == UNZ_OK)
-			{
-				printf(" in %s", rom_filename);
-
-				ret = ReadIPSPatch(new unzReader(file), offset, rom_size);
-				unzCloseCurrentFile(file);
-
-				if (ret)
-				{
-					printf("!\n");
-					flag = true;
-				}
-				else
-					printf(" failed!\n");
-
-				port = unzFindExtension(file, "ips", false);
-			}
-
-			if (!flag)
-			{
-				i = 0;
-
-				do
-				{
-					snprintf(ips, 8, "%03d.ips", i);
-
-					if (unzFindExtension(file, ips) != UNZ_OK)
-						break;
-
-					printf(" in %s", rom_filename);
-
-					ret = ReadIPSPatch(new unzReader(file), offset, rom_size);
-					unzCloseCurrentFile(file);
-
-					if (ret)
-					{
-						printf("!\n");
-						flag = true;
-					}
-					else
-					{
-						printf(" failed!\n");
-						break;
-					}
-
-					if (unzFindExtension(file, ips, false, false) == UNZ_OK)
-						printf("WARNING: Ignoring extra .%s files!\n", ips);
-				} while (++i < 1000);
-			}
-
-			if (!flag)
-			{
-				i = 0;
-
-				do
-				{
-					snprintf(ips, _MAX_EXT + 2, "ips%d", i);
-					if (strlen(ips) > _MAX_EXT)
-						break;
-
-					if (unzFindExtension(file, ips) != UNZ_OK)
-						break;
-
-					printf(" in %s", rom_filename);
-
-					ret = ReadIPSPatch(new unzReader(file), offset, rom_size);
-					unzCloseCurrentFile(file);
-
-					if (ret)
-					{
-						printf("!\n");
-						flag = true;
-					}
-					else
-					{
-						printf(" failed!\n");
-						break;
-					}
-
-					if (unzFindExtension(file, ips, false, false) == UNZ_OK)
-						printf("WARNING: Ignoring extra .%s files!\n", ips);
-				} while (++i != 0);
-			}
-
-			if (!flag)
-			{
-				i = 0;
-
-				do
-				{
-					snprintf(ips, 4, "ip%d", i);
-
-					if (unzFindExtension(file, ips) != UNZ_OK)
-						break;
-
-					printf(" in %s", rom_filename);
-
-					ret = ReadIPSPatch(new unzReader(file), offset, rom_size);
-					unzCloseCurrentFile(file);
-
-					if (ret)
-					{
-						printf("!\n");
-						flag = true;
-					}
-					else
-					{
-						printf(" failed!\n");
-						break;
-					}
-
-					if (unzFindExtension(file, ips, false, false) == UNZ_OK)
-						printf("WARNING: Ignoring extra .%s files!\n", ips);
-				} while (++i < 10);
-			}
-
-			assert(unzClose(file) == UNZ_OK);
-
-			if (flag)
-				return;
-		}
-	}
-#endif
-
-	n = S9xGetFilename(".ips", IPS_DIR);
-
-	if ((patch_file = OPEN_STREAM(n, "rb")) != NULL)
-	{
-		printf("Using IPS patch %s", n);
-
-		ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size);
-		CLOSE_STREAM(patch_file);
-
-		if (ret)
-		{
-			printf("!\n");
-			return;
-		}
-		else
-			printf(" failed!\n");
-	}
-
-	if (_MAX_EXT > 6)
-	{
-		i = 0;
-		flag = false;
-
-		do
-		{
-			snprintf(ips, 9, ".%03d.ips", i);
-			n = S9xGetFilename(ips, IPS_DIR);
-
-			if (!(patch_file = OPEN_STREAM(n, "rb")))
-				break;
-
-			printf("Using IPS patch %s", n);
-
-			ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size);
-			CLOSE_STREAM(patch_file);
-
-			if (ret)
-			{
-				printf("!\n");
-				flag = true;
-			}
-			else
-			{
-				printf(" failed!\n");
-				break;
-			}
-		} while (++i < 1000);
-
-		if (flag)
-			return;
-	}
-
-	if (_MAX_EXT > 3)
-	{
-		i = 0;
-		flag = false;
-
-		do
-		{
-			snprintf(ips, _MAX_EXT + 3, ".ips%d", i);
-			if (strlen(ips) > _MAX_EXT + 1)
-				break;
-			n = S9xGetFilename(ips, IPS_DIR);
-
-			if (!(patch_file = OPEN_STREAM(n, "rb")))
-				break;
-
-			printf("Using IPS patch %s", n);
-
-			ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size);
-			CLOSE_STREAM(patch_file);
-
-			if (ret)
-			{
-				printf("!\n");
-				flag = true;
-			}
-			else
-			{
-				printf(" failed!\n");
-				break;
-			}
-		} while (++i != 0);
-
-		if (flag)
-			return;
-	}
-
-	if (_MAX_EXT > 2)
-	{
-		i = 0;
-		flag = false;
-
-		do
-		{
-			snprintf(ips, 5, ".ip%d", i);
-			n = S9xGetFilename(ips, IPS_DIR);
-
-			if (!(patch_file = OPEN_STREAM(n, "rb")))
-				break;
-
-			printf("Using IPS patch %s", n);
-
-			ret = ReadIPSPatch(new fReader(patch_file), offset, rom_size);
-			CLOSE_STREAM(patch_file);
-
-			if (ret)
-			{
-				printf("!\n");
-				flag = true;
-			}
-			else
-			{
-				printf(" failed!\n");
-				break;
-			}
-		} while (++i < 10);
-
-		if (flag)
-			return;
-	}
-}*/
-
+	}
+}
+

--- a/src/in_snsf/snes9x/memmap.h
+++ b/src/in_snsf/snes9x/memmap.h
@@ -175,192 +175,112 @@
   Nintendo Co., Limited and its subsidiary companies.
  ***********************************************************************************/
 
-
 #ifndef _MEMMAP_H_
 #define _MEMMAP_H_
 
-#define MEMMAP_BLOCK_SIZE	(0x1000)
-#define MEMMAP_NUM_BLOCKS	(0x1000000 / MEMMAP_BLOCK_SIZE)
-#define MEMMAP_SHIFT		(12)
-#define MEMMAP_MASK			(MEMMAP_BLOCK_SIZE - 1)
+#include <memory>
+#include <cstdint>
+
+const int32_t MEMMAP_BLOCK_SIZE = 0x1000;
+const size_t MEMMAP_NUM_BLOCKS = 0x1000000 / MEMMAP_BLOCK_SIZE;
+const uint32_t MEMMAP_SHIFT = 12;
+const uint32_t MEMMAP_MASK = MEMMAP_BLOCK_SIZE - 1;
 
 struct CMemory
 {
+	enum { MAX_ROM_SIZE = 0x800000 };
+
 	enum
-	{ MAX_ROM_SIZE = 0x800000 };
-
-	enum file_formats
-	{ FILE_ZIP, FILE_JMA, FILE_DEFAULT };
+	{
+		NOPE,
+		YEAH,
+		BIGFIRST,
+		SMALLFIRST
+	};
 
 	enum
-	{ NOPE, YEAH, BIGFIRST, SMALLFIRST };
-
-	enum
-	{ MAP_TYPE_I_O, MAP_TYPE_ROM, MAP_TYPE_RAM };
+	{
+		MAP_TYPE_I_O,
+		MAP_TYPE_RAM
+	};
 
 	enum
 	{
 		MAP_CPU,
 		MAP_PPU,
 		MAP_LOROM_SRAM,
-		MAP_LOROM_SRAM_B,
 		MAP_HIROM_SRAM,
-		MAP_DSP,
 		MAP_SA1RAM,
-		MAP_BWRAM,
-		MAP_BWRAM_BITMAP,
-		MAP_BWRAM_BITMAP2,
-		MAP_SPC7110_ROM,
-		MAP_SPC7110_DRAM,
 		MAP_RONLY_SRAM,
-		MAP_C4,
-		MAP_OBC_RAM,
-		MAP_SETA_DSP,
-		MAP_SETA_RISC,
-		MAP_BSX,
 		MAP_NONE,
 		MAP_LAST
 	};
 
-	uint8_t	NSRTHeader[32];
-	int32_t	HeaderCount;
-
-	uint8_t	*RAM;
-	uint8_t	*ROM;
-	uint8_t	*SRAM;
-	uint8_t	*VRAM;
-	uint8_t	*FillRAM;
-	uint8_t	*BWRAM;
-	uint8_t	*C4RAM;
-	uint8_t	*OBC1RAM;
-	uint8_t	*BSRAM;
-	uint8_t	*BIOSROM;
-
-	uint8_t	*Map[MEMMAP_NUM_BLOCKS];
-	uint8_t	*WriteMap[MEMMAP_NUM_BLOCKS];
-	uint8_t	BlockIsRAM[MEMMAP_NUM_BLOCKS];
-	uint8_t	BlockIsROM[MEMMAP_NUM_BLOCKS];
-	uint8_t	ExtendedFormat;
-
-	char	ROMFilename[PATH_MAX + 1];
-	char	ROMName[ROM_NAME_LEN];
-	char	RawROMName[ROM_NAME_LEN];
-	char	ROMId[5];
-	int32_t	CompanyId;
-	uint8_t	ROMRegion;
-	uint8_t	ROMSpeed;
-	uint8_t	ROMType;
-	uint8_t	ROMSize;
-	uint32_t	ROMChecksum;
-	uint32_t	ROMComplementChecksum;
-	uint32_t	ROMCRC32;
-	int32_t	ROMFramesPerSecond;
-
-	bool	HiROM;
-	bool	LoROM;
-	uint8_t	SRAMSize;
-	uint32_t	SRAMMask;
-	uint32_t	CalculatedSize;
-	uint32_t	CalculatedChecksum;
-
-	// ports can assign this to perform some custom action upon loading a ROM (such as adjusting controls)
-	void	(*PostRomInitFunc)();
-
-	bool	Init();
-	void	Deinit();
-
-	int		ScoreHiROM (bool, int32_t romoff = 0);
-	int		ScoreLoROM (bool, int32_t romoff = 0);
-	//uint32_t	HeaderRemove (uint32_t, int32_t &, uint8_t *);
-	//uint32_t	FileLoader (uint8_t *, const char *, int32_t);
-	/*bool	LoadROM (const char *);
-	bool	LoadMultiCart (const char *, const char *);
-	bool	LoadSufamiTurbo (const char *, const char *);
-	bool	LoadSameGame (const char *, const char *);
-	bool	LoadSRAM (const char *);
-	bool	SaveSRAM (const char *);
-	void	ClearSRAM (bool onlyNonSavedSRAM = 0);
-	bool	LoadSRTC();
-	bool	SaveSRTC();*/
-	bool LoadROMSNSF(const unsigned char *, int32_t, const unsigned char *, int32_t);
-
-	char *	Safe (const char *);
-	char *	SafeANK (const char *);
-	void	ParseSNESHeader (uint8_t *);
-	void	InitROM();
-
-	uint32_t	map_mirror (uint32_t, uint32_t);
-	void	map_lorom (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t);
-	void	map_hirom (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t);
-	void	map_lorom_offset (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t);
-	void	map_hirom_offset (uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t);
-	void	map_space (uint32_t, uint32_t, uint32_t, uint32_t, uint8_t *);
-	void	map_index (uint32_t, uint32_t, uint32_t, uint32_t, int, int);
-	void	map_System();
-	void	map_WRAM();
-	void	map_LoROMSRAM();
-	void	map_HiROMSRAM();
-	//void	map_DSP();
-	//void	map_C4();
-	//void	map_OBC1();
-	//void	map_SetaRISC();
-	//void	map_SetaDSP();
-	void	map_WriteProtectROM();
-	void	Map_Initialize();
-	void	Map_LoROMMap();
-	void	Map_NoMAD1LoROMMap();
-	void	Map_JumboLoROMMap();
-	void	Map_ROM24MBSLoROMMap();
-	void	Map_SRAM512KLoROMMap();
-	//void	Map_SufamiTurboLoROMMap();
-	//void	Map_SufamiTurboPseudoLoROMMap();
-	//void	Map_SuperFXLoROMMap();
-	//void	Map_SetaDSPLoROMMap();
-	void	Map_SDD1LoROMMap();
-	//void	Map_SA1LoROMMap();
-	void	Map_HiROMMap();
-	void	Map_ExtendedHiROMMap();
-	//void	Map_SameGameHiROMMap();
-	//void	Map_SPC7110HiROMMap();
-
-	uint16_t	checksum_calc_sum (uint8_t *, uint32_t);
-	uint16_t	checksum_mirror_sum (uint8_t *, uint32_t &, uint32_t mask = 0x800000);
-	void	Checksum_Calculate();
-
-	bool	match_na (const char *);
-	bool	match_nn (const char *);
-	//bool	match_nc (const char *);
-	bool	match_id (const char *);
-	void	ApplyROMFixes();
-	//void	CheckForAnyPatch (const char *, bool, int32_t &);
-
-	//void	MakeRomInfoText (char *);
-
-	//const char *	MapType();
-	//const char *	StaticRAMSize();
-	//const char *	Size();
-	//const char *	Revision();
-	//const char *	KartContents();
-	//const char *	Country();
-	//const char *	PublishingCompany();
+	std::unique_ptr<uint8_t[]> RAM;
+	std::unique_ptr<uint8_t[]> RealROM;
+	uint8_t *ROM;
+	std::unique_ptr<uint8_t[]> SRAM;
+	std::unique_ptr<uint8_t[]> VRAM;
+	uint8_t *FillRAM;
+
+	uint8_t *Map[MEMMAP_NUM_BLOCKS];
+	uint8_t *WriteMap[MEMMAP_NUM_BLOCKS];
+	uint8_t BlockIsRAM[MEMMAP_NUM_BLOCKS];
+	uint8_t BlockIsROM[MEMMAP_NUM_BLOCKS];
+	uint8_t ExtendedFormat;
+
+	char ROMName[ROM_NAME_LEN];
+	char ROMId[5];
+	uint8_t ROMRegion;
+	uint8_t ROMSpeed;
+	uint8_t ROMType;
+
+	bool HiROM;
+	bool LoROM;
+	uint8_t SRAMSize;
+	uint32_t SRAMMask;
+	uint32_t CalculatedSize;
+
+	bool Init();
+	void Deinit();
+
+	int ScoreHiROM(bool, int32_t romoff = 0);
+	int ScoreLoROM(bool, int32_t romoff = 0);
+	bool LoadROMSNSF(const uint8_t *, int32_t, const uint8_t *, int32_t);
+
+	char *Safe(const char *);
+	void ParseSNESHeader(uint8_t *);
+	void InitROM();
+
+	uint32_t map_mirror(uint32_t, uint32_t);
+	void map_lorom(uint32_t, uint32_t, uint32_t, uint32_t, uint32_t);
+	void map_hirom(uint32_t, uint32_t, uint32_t, uint32_t, uint32_t);
+	void map_lorom_offset(uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t);
+	void map_hirom_offset(uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t);
+	void map_space(uint32_t, uint32_t, uint32_t, uint32_t, uint8_t *);
+	void map_index(uint32_t, uint32_t, uint32_t, uint32_t, int, int);
+	void map_System();
+	void map_WRAM();
+	void map_LoROMSRAM();
+	void map_HiROMSRAM();
+	void map_WriteProtectROM();
+	void Map_Initialize();
+	void Map_LoROMMap();
+	void Map_NoMAD1LoROMMap();
+	void Map_JumboLoROMMap();
+	void Map_ROM24MBSLoROMMap();
+	void Map_SRAM512KLoROMMap();
+	void Map_SDD1LoROMMap();
+	void Map_HiROMMap();
+	void Map_ExtendedHiROMMap();
+
+	bool match_na(const char *);
+	bool match_nn(const char *);
+	bool match_id(const char *);
+	void ApplyROMFixes();
 };
 
-struct SMulti
-{
-	int		cartType;
-	int32_t	cartSizeA, cartSizeB;
-	int32_t	sramSizeA, sramSizeB;
-	uint32_t	sramMaskA, sramMaskB;
-	uint32_t	cartOffsetA, cartOffsetB;
-	uint8_t	*sramA, *sramB;
-	char	fileNameA[PATH_MAX + 1], fileNameB[PATH_MAX + 1];
-};
-
-extern CMemory	Memory;
-extern SMulti	Multi;
-
-void S9xAutoSaveSRAM();
-bool LoadZip(const char *, int32_t *, int32_t *, uint8_t *);
+extern CMemory Memory;
 
 enum s9xwrap_t
 {

--- a/src/in_snsf/snes9x/port.h
+++ b/src/in_snsf/snes9x/port.h
@@ -175,197 +175,56 @@
   Nintendo Co., Limited and its subsidiary companies.
  ***********************************************************************************/
 
-
 #ifndef _PORT_H_
 #define _PORT_H_
 
 #include <cstdio>
 #include <cstdlib>
 #include <climits>
-//#include <memory.h>
 #include <ctime>
 #include <cstring>
-/*#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif*/
+#include <cstdint>
 #include <sys/types.h>
 
 #ifdef _WIN32
-//#define NOMINMAX
-//#include <windows.h>
-#include "windowsh_wrapper.h"
-#endif
-
-//#define GFX_MULTI_FORMAT
-
-/*#ifdef _WIN32
-//#define RIGHTSHIFT_IS_SAR
-#define RIGHTSHIFT_int8_IS_SAR
-#define RIGHTSHIFT_int16_IS_SAR
-#define RIGHTSHIFT_int32_IS_SAR
-//#define SNES_JOY_READ_CALLBACKS
-#endif*/
-
-#ifdef __MACOSX__
-#undef GFX_MULTI_FORMAT
-#define PIXEL_FORMAT RGB555
-#endif
-
-#include <cstdint>
-/*#ifndef snes9x_types_defined
-#define snes9x_types_defined
-typedef unsigned char		bool8;
-#ifdef HAVE_STDINT_H
-#include <stdint.h>
-typedef intptr_t			pint;
-typedef int8_t				int8;
-typedef uint8_t				uint8;
-typedef int16_t				int16;
-typedef uint16_t			uint16;
-typedef int32_t				int32;
-typedef uint32_t			uint32;
-typedef int64_t				int64;
-typedef uint64_t			uint64;
-#else	// HAVE_STDINT_H
+# include "windowsh_wrapper.h"
+#endif
+
+#ifndef _WIN32
+# ifndef PATH_MAX
+#  define PATH_MAX 1024
+# endif
+# define _MAX_DRIVE 1
+# define _MAX_DIR PATH_MAX
+# define _MAX_FNAME PATH_MAX
+# define _MAX_EXT PATH_MAX
+# define _MAX_PATH PATH_MAX
+#else
+# ifndef PATH_MAX
+#  define PATH_MAX _MAX_PATH
+# endif
+#endif
+
 #ifdef _WIN32
-typedef intptr_t			pint;
-#else	// __WIN32__
-#ifdef PTR_NOT_INT
-typedef long				pint;
+# define strcasecmp stricmp
+#endif
+
+#if defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) || defined(__x86_64__) || defined(__alpha__) || defined(__MIPSEL__) || defined(_M_IX86) || defined(_M_X64)
+# define LSB_FIRST
+# define FAST_LSB_WORD_ACCESS
 #else
-typedef int					pint;
-#endif
-#endif	// __WIN32__
-#ifdef _WIN32
-#ifdef __BORLANDC__
-#include <systypes.h>
+# define MSB_FIRST
+#endif
+
+#ifdef FAST_LSB_WORD_ACCESS
+inline uint16_t READ_WORD(uint8_t *s) { return *reinterpret_cast<uint16_t *>(s); }
+inline uint32_t READ_3WORD(uint8_t *s) { return *reinterpret_cast<uint32_t *>(s) & 0x00FFFFFF; }
+inline void WRITE_WORD(uint8_t *s, uint16_t d) { *reinterpret_cast<uint16_t *>(s) = d; }
 #else
-typedef signed char			int8;
-typedef unsigned char		uint8;
-typedef signed short		int16;
-typedef unsigned short		uint16;
-#ifndef WSAAP
-// winsock2.h typedefs int32 as well
-typedef signed int			int32;
-#endif
-typedef unsigned int		uint32;
-#endif
-typedef unsigned char		uint8_t;
-typedef signed char         int8_t;
-typedef signed __int64		int64;
-typedef unsigned __int64	uint64;
-typedef int					socklen_t;
-#else	// __WIN32__
-typedef signed char			int8;
-typedef unsigned char		uint8;
-typedef signed short		int16;
-typedef unsigned short		uint16;
-typedef signed int			int32;
-typedef unsigned int		uint32;
-#ifdef __GNUC__
-// long long is not part of ISO C++ 
-__extension__
-#endif
-typedef long long			int64;
-typedef unsigned long long	uint64;
-#endif	//  __WIN32__
-#endif	// HAVE_STDINT_H
-#endif	// snes9x_types_defined
-
-#ifndef TRUE
-#define TRUE	1
-#endif
-#ifndef FALSE
-#define FALSE	0
-#endif*/
-
-/*#define START_EXTERN_C	extern "C" {
-#define END_EXTERN_C	}*/
-
-#ifndef _WIN32
-#ifndef PATH_MAX
-#define PATH_MAX	1024
-#endif
-#define _MAX_DRIVE	1
-#define _MAX_DIR	PATH_MAX
-#define _MAX_FNAME	PATH_MAX
-#define _MAX_EXT	PATH_MAX
-#define _MAX_PATH	PATH_MAX
-#else
-#ifndef PATH_MAX
-#define PATH_MAX	_MAX_PATH
-#endif
-#endif
-
-#ifndef _WIN32
-#define ZeroMemory(a, b)	memset((a), 0, (b))
-void _splitpath (const char *, char *, char *, char *, char *);
-void _makepath (char *, const char *, const char *, const char *, const char *);
-//#define S9xDisplayString	DisplayStringFromBottom
-#else
-#define snprintf _snprintf
-#define strcasecmp	stricmp
-#define strncasecmp	_strnicmp
-//void WinDisplayStringFromBottom(const char *string, int linesFromBottom, int pixelsFromLeft, bool allowWrap);
-//#define S9xDisplayString	WinDisplayStringFromBottom
-//void SetInfoDlgColor(unsigned char, unsigned char, unsigned char);
-//#define SET_UI_COLOR(r,g,b) SetInfoDlgColor(r,g,b)
-#endif
-
-/*#ifdef __DJGPP
-#define SLASH_STR	"\\"
-#define SLASH_CHAR	'\\'
-#else
-#define SLASH_STR	"/"
-#define SLASH_CHAR	'/'
-#endif*/
-
-/*#ifndef SIG_PF
-#define SIG_PF	void (*) (int)
-#endif*/
-
-/*#ifdef __linux
-#define TITLE "Snes9x: Linux"
-#define SYS_CONFIG_FILE "/etc/snes9x/snes9x.conf"
-#endif
-
-#ifndef TITLE
-#define TITLE "Snes9x"
-#endif*/
-
-#if defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) || defined(__x86_64__) || defined(__alpha__) || defined(__MIPSEL__) || defined(_M_IX86) || defined(_M_X64)
-#define LSB_FIRST
-#define FAST_LSB_WORD_ACCESS
-#else
-#define MSB_FIRST
-#endif
-
-#ifdef FAST_LSB_WORD_ACCESS
-//#define READ_WORD(s)		(*(uint16_t *) (s))
-static inline uint16_t READ_WORD(uint8_t *s) { return *reinterpret_cast<uint16_t *>(s); }
-//#define READ_3WORD(s)		(*(uint32_t *) (s) & 0x00ffffff)
-static inline uint32_t READ_3WORD(uint8_t *s) { return *reinterpret_cast<uint32_t *>(s) & 0x00FFFFFF; }
-//#define READ_DWORD(s)		(*(uint32_t *) (s))
-//#define WRITE_WORD(s, d)	*(uint16_t *) (s) = (d)
-static inline void WRITE_WORD(uint8_t *s, uint16_t d) { *reinterpret_cast<uint16_t *>(s) = d; }
-//#define WRITE_3WORD(s, d)	*(uint16_t *) (s) = (uint16_t) (d), *((uint8_t *) (s) + 2) = (uint8_t) ((d) >> 16)
-//#define WRITE_DWORD(s, d)	*(uint32_t *) (s) = (d)
-#else
-//#define READ_WORD(s)		(*(uint8_t *) (s) | (*((uint8_t *) (s) + 1) << 8))
-static inline uint16_t READ_WORD(uint8_t *s) { return s | ((s + 1) << 8); }
-//#define READ_3WORD(s)		(*(uint8_t *) (s) | (*((uint8_t *) (s) + 1) << 8) | (*((uint8_t *) (s) + 2) << 16))
-static inline uint32-t READ_3WORD(uint8_t *s) { return s | ((s + 1) << 8) | ((s + 2) << 16); }
-//#define READ_DWORD(s)		(*(uint8_t *) (s) | (*((uint8_t *) (s) + 1) << 8) | (*((uint8_t *) (s) + 2) << 16) | (*((uint8_t *) (s) + 3) << 24))
-//#define WRITE_WORD(s, d)	*(uint8_t *) (s) = (uint8_t) (d), *((uint8_t *) (s) + 1) = (uint8_t) ((d) >> 8)
-static inline void WRITE_WORD(uint8_t *s, uint16_t) { *s = static_cast<uint8_t>(d); *(s + 1) = static_cast<uint8_t>(d >> 8); }
-//#define WRITE_3WORD(s, d)	*(uint8_t *) (s) = (uint8_t) (d), *((uint8_t *) (s) + 1) = (uint8_t) ((d) >> 8), *((uint8_t *) (s) + 2) = (uint8_t) ((d) >> 16)
-//#define WRITE_DWORD(s, d)	*(uint8_t *) (s) = (uint8_t) (d), *((uint8_t *) (s) + 1) = (uint8_t) ((d) >> 8), *((uint8_t *) (s) + 2) = (uint8_t) ((d) >> 16), *((uint8_t *) (s) + 3) = (uint8_t) ((d) >> 24)
-#endif
-
-//#define SWAP_WORD(s)		(s) = (((s) & 0xff) <<  8) | (((s) & 0xff00) >> 8)
-//#define SWAP_DWORD(s)		(s) = (((s) & 0xff) << 24) | (((s) & 0xff00) << 8) | (((s) & 0xff0000) >> 8) | (((s) & 0xff000000) >> 24)
-
-//#include "pixform.h"
-
-#endif
-
+inline uint16_t READ_WORD(uint8_t *s) { return s | ((s + 1) << 8); }
+inline uint32-t READ_3WORD(uint8_t *s) { return s | ((s + 1) << 8) | ((s + 2) << 16); }
+inline void WRITE_WORD(uint8_t *s, uint16_t d) { *s = static_cast<uint8_t>(d); *(s + 1) = static_cast<uint8_t>(d >> 8); }
+#endif
+
+#endif
+

--- a/src/in_snsf/snes9x/ppu.cpp
+++ b/src/in_snsf/snes9x/ppu.cpp
@@ -175,147 +175,47 @@
   Nintendo Co., Limited and its subsidiary companies.
  ***********************************************************************************/
 
+#include <algorithm>
 #include "snes9x.h"
 #include "memmap.h"
 #include "dma.h"
 #include "apu/apu.h"
-//#include "fxemu.h"
 #include "sdd1.h"
-//#include "srtc.h"
-//#include "controls.h"
-//#include "movie.h"
-//#include "display.h"
-#ifdef NETPLAY_SUPPORT
-#include "netplay.h"
-#endif
-#ifdef DEBUGGER
-#include "debug.h"
-#include "missing.h"
-#endif
-
-extern uint8_t	*HDMAMemPointers[8];
-
-static inline void S9xLatchCounters (bool force)
-{
-	if (force || (Memory.FillRAM[0x4213] & 0x80))
-	{
-		// Latch h and v counters, like the gun
-	#ifdef DEBUGGER
-		missing.h_v_latch = 1;
-	#endif
-
-		PPU.HVBeamCounterLatched = 1;
-		PPU.VBeamPosLatched = (uint16_t) CPU.V_Counter;
-
-		// From byuu:
-		// All dots are 4 cycles long, except dots 322 and 326. dots 322 and 326 are 6 cycles long.
-		// This holds true for all scanlines except scanline 240 on non-interlace odd frames.
-		// The reason for this is because this scanline is only 1360 cycles long,
-		// instead of 1364 like all other scanlines.
-		// This makes the effective range of hscan_pos 0-339 at all times.
-		int32_t	hc = CPU.Cycles;
-
-		if (Timings.H_Max == Timings.H_Max_Master) // 1364
-		{
-			if (hc >= 1292)
-				hc -= (ONE_DOT_CYCLE / 2);
-			if (hc >= 1308)
-				hc -= (ONE_DOT_CYCLE / 2);
-		}
-
-		PPU.HBeamPosLatched = (uint16_t) (hc / ONE_DOT_CYCLE);
-
-		Memory.FillRAM[0x213f] |= 0x40;
-	}
-
-	if (CPU.V_Counter >  PPU.GunVLatch || (CPU.V_Counter == PPU.GunVLatch && CPU.Cycles >= PPU.GunHLatch * ONE_DOT_CYCLE))
-		PPU.GunVLatch = 1000;
-}
-
-static inline void S9xTryGunLatch (bool force)
-{
-	if (CPU.V_Counter >  PPU.GunVLatch || (CPU.V_Counter == PPU.GunVLatch && CPU.Cycles >= PPU.GunHLatch * ONE_DOT_CYCLE))
-	{
-		if (force || (Memory.FillRAM[0x4213] & 0x80))
-		{
-		#ifdef DEBUGGER
-			missing.h_v_latch = 1;
-		#endif
-
-			PPU.HVBeamCounterLatched = 1;
-			PPU.VBeamPosLatched = (uint16_t) PPU.GunVLatch;
-			PPU.HBeamPosLatched = (uint16_t) PPU.GunHLatch;
-
-			Memory.FillRAM[0x213f] |= 0x40;
-		}
-
-		PPU.GunVLatch = 1000;
-	}
-}
+
+extern uint8_t *HDMAMemPointers[8];
 
 void S9xUpdateHVTimerPosition()
 {
 	PPU.HTimerPosition = PPU.IRQHBeamPos * ONE_DOT_CYCLE + Timings.IRQTriggerCycles;
-	if (Timings.H_Max == Timings.H_Max_Master)	// 1364
+	if (Timings.H_Max == Timings.H_Max_Master) // 1364
 	{
 		if (PPU.IRQHBeamPos > 322)
-			PPU.HTimerPosition += (ONE_DOT_CYCLE / 2);
+			PPU.HTimerPosition += ONE_DOT_CYCLE / 2;
 		if (PPU.IRQHBeamPos > 326)
-			PPU.HTimerPosition += (ONE_DOT_CYCLE / 2);
+			PPU.HTimerPosition += ONE_DOT_CYCLE / 2;
 	}
 
 	PPU.VTimerPosition = PPU.IRQVBeamPos;
 
-	if ((PPU.HTimerPosition >= Timings.H_Max) && (PPU.IRQHBeamPos < 340))
+	if (PPU.HTimerPosition >= Timings.H_Max && PPU.IRQHBeamPos < 340)
 	{
 		PPU.HTimerPosition -= Timings.H_Max;
-		PPU.VTimerPosition++;
+		++PPU.VTimerPosition;
 		// FIXME
 		if (PPU.VTimerPosition >= Timings.V_Max)
 			PPU.VTimerPosition = 0;
 	}
-
-#ifdef DEBUGGER
-	S9xTraceFormattedMessage("--- IRQ Timer set  HTimer:%d Pos:%04d  VTimer:%d Pos:%03d",
-		PPU.HTimerEnabled, PPU.HTimerPosition, PPU.VTimerEnabled, PPU.VTimerPosition);
-#endif
 }
 
-/*void S9xFixColourBrightness()
-{
-	IPPU.XB = mul_brightness[PPU.Brightness];
-
-	for (int i = 0; i < 256; i++)
-	{
-		IPPU.Red[i]   = IPPU.XB[(PPU.CGDATA[i])       & 0x1f];
-		IPPU.Green[i] = IPPU.XB[(PPU.CGDATA[i] >>  5) & 0x1f];
-		IPPU.Blue[i]  = IPPU.XB[(PPU.CGDATA[i] >> 10) & 0x1f];
-		IPPU.ScreenColors[i] = BUILD_PIXEL(IPPU.Red[i], IPPU.Green[i], IPPU.Blue[i]);
-	}
-}*/
-
-void S9xSetPPU (uint8_t Byte, uint16_t Address)
+void S9xSetPPU(uint8_t Byte, uint16_t Address)
 {
 	// MAP_PPU: $2000-$3FFF
 
 	if (CPU.InDMAorHDMA)
 	{
 		if (CPU.CurrentDMAorHDMAChannel >= 0 && DMA[CPU.CurrentDMAorHDMAChannel].ReverseTransfer)
-		{
 			// S9xSetPPU() is called to write to DMA[].AAddress
-			if ((Address & 0xff00) == 0x2100)
-			{
-				// Cannot access to Address Bus B ($2100-$21ff) via (H)DMA
-				return;
-			}
-			else
-			{
-				// 0x2000-0x3FFF is connected to Address Bus A
-				// SA1, SuperFX and SRTC are mapped here
-				// I don't bother for now...
-				return;
-			}
-		}
+			return;
 		else
 		{
 			// S9xSetPPU() is called to read from $21xx
@@ -325,39 +225,18 @@
 		}
 	}
 
-#ifdef DEBUGGER
-	if (CPU.InHDMA)
-		S9xTraceFormattedMessage("--- HDMA PPU %04X -> %02X", Address, Byte);
-#endif
-
 	if ((Address & 0xffc0) == 0x2140) // APUIO0, APUIO1, APUIO2, APUIO3
 		// write_port will run the APU until given clock before writing value
 		S9xAPUWritePort(Address & 3, Byte);
-	else
-	if (Address <= 0x2183)
+	else if (Address <= 0x2183)
 	{
 		switch (Address)
 		{
 			case 0x2100: // INIDISP
 				if (Byte != Memory.FillRAM[0x2100])
 				{
-					//FLUSH_REDRAW();
-
-					if (PPU.Brightness != (Byte & 0xf))
-					{
-						IPPU.ColorsChanged = true;
-						IPPU.DirectColourMapsNeedRebuild = true;
-						PPU.Brightness = Byte & 0xf;
-						//S9xFixColourBrightness();
-						if (PPU.Brightness > IPPU.MaxBrightness)
-							IPPU.MaxBrightness = PPU.Brightness;
-					}
-
 					if ((Memory.FillRAM[0x2100] & 0x80) != (Byte & 0x80))
-					{
-						IPPU.ColorsChanged = true;
-						PPU.ForcedBlanking = (Byte >> 7) & 1;
-					}
+						PPU.ForcedBlanking = !!((Byte >> 7) & 1);
 				}
 
 				if ((Memory.FillRAM[0x2100] & 0x80) && CPU.V_Counter == PPU.ScreenHeight + FIRST_VISIBLE_LINE)
@@ -368,24 +247,9 @@
 					if (PPU.OAMPriorityRotation)
 						tmp = (PPU.OAMAddr & 0xfe) >> 1;
 					if ((PPU.OAMFlip & 1) || PPU.FirstSprite != tmp)
-					{
 						PPU.FirstSprite = tmp;
-						IPPU.OBJChanged = true;
-					}
 
 					PPU.OAMFlip = 0;
-				}
-
-				break;
-
-			case 0x2101: // OBSEL
-				if (Byte != Memory.FillRAM[0x2101])
-				{
-					//FLUSH_REDRAW();
-					PPU.OBJNameBase = (Byte & 3) << 14;
-					PPU.OBJNameSelect = ((Byte >> 3) & 3) << 13;
-					PPU.OBJSizeSelect = (Byte >> 5) & 7;
-					IPPU.OBJChanged = true;
 				}
 
 				break;
@@ -393,47 +257,24 @@
 			case 0x2102: // OAMADDL
 				PPU.OAMAddr = ((Memory.FillRAM[0x2103] & 1) << 8) | Byte;
 				PPU.OAMFlip = 2;
-				PPU.OAMReadFlip = 0;
 				PPU.SavedOAMAddr = PPU.OAMAddr;
 				if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1))
-				{
 					PPU.FirstSprite = (PPU.OAMAddr & 0xfe) >> 1;
-					IPPU.OBJChanged = true;
-				#ifdef DEBUGGER
-					missing.sprite_priority_rotation = 1;
-				#endif
-				}
 
 				break;
 
 			case 0x2103: // OAMADDH
 				PPU.OAMAddr = ((Byte & 1) << 8) | Memory.FillRAM[0x2102];
-				PPU.OAMPriorityRotation = (Byte & 0x80) ? 1 : 0;
+				PPU.OAMPriorityRotation = !!(Byte & 0x80);
 				if (PPU.OAMPriorityRotation)
 				{
 					if (PPU.FirstSprite != (PPU.OAMAddr >> 1))
-					{
 						PPU.FirstSprite = (PPU.OAMAddr & 0xfe) >> 1;
-						IPPU.OBJChanged = true;
-					#ifdef DEBUGGER
-						missing.sprite_priority_rotation = 1;
-					#endif
-					}
-				}
-				else
-				{
-					if (PPU.FirstSprite != 0)
-					{
-						PPU.FirstSprite = 0;
-						IPPU.OBJChanged = true;
-					#ifdef DEBUGGER
-						missing.sprite_priority_rotation = 1;
-					#endif
-					}
-				}
+				}
+				else if (PPU.FirstSprite)
+					PPU.FirstSprite = 0;
 
 				PPU.OAMFlip = 0;
-				PPU.OAMReadFlip = 0;
 				PPU.SavedOAMAddr = PPU.OAMAddr;
 
 				break;
@@ -444,176 +285,45 @@
 
 			case 0x2105: // BGMODE
 				if (Byte != Memory.FillRAM[0x2105])
-				{
-					//FLUSH_REDRAW();
-					PPU.BG[0].BGSize = (Byte >> 4) & 1;
-					PPU.BG[1].BGSize = (Byte >> 5) & 1;
-					PPU.BG[2].BGSize = (Byte >> 6) & 1;
-					PPU.BG[3].BGSize = (Byte >> 7) & 1;
-					PPU.BGMode = Byte & 7;
-					// BJ: BG3Priority only takes effect if BGMode == 1 and the bit is set
-					PPU.BG3Priority = ((Byte & 0x0f) == 0x09);
-					IPPU.Interlace = Memory.FillRAM[0x2133] & 1;
-				#ifdef DEBUGGER
-					missing.modes[PPU.BGMode] = 1;
-				#endif
-				}
-
-				break;
-
-			case 0x2106: // MOSAIC
-				if (Byte != Memory.FillRAM[0x2106])
-				{
-					//FLUSH_REDRAW();
-					PPU.MosaicStart = CPU.V_Counter;
-					if (PPU.MosaicStart > PPU.ScreenHeight)
-						PPU.MosaicStart = 0;
-					PPU.Mosaic = (Byte >> 4) + 1;
-					PPU.BGMosaic[0] = (Byte & 1);
-					PPU.BGMosaic[1] = !!(Byte & 2);
-					PPU.BGMosaic[2] = !!(Byte & 4);
-					PPU.BGMosaic[3] = !!(Byte & 8);
-				#ifdef DEBUGGER
-					if ((Byte & 0xf0) && (Byte & 0x0f))
-						missing.mosaic = 1;
-				#endif
-				}
-
-				break;
-
-			case 0x2107: // BG1SC
-				if (Byte != Memory.FillRAM[0x2107])
-				{
-					//FLUSH_REDRAW();
-					PPU.BG[0].SCSize = Byte & 3;
-					PPU.BG[0].SCBase = (Byte & 0x7c) << 8;
-				}
-
-				break;
-
-			case 0x2108: // BG2SC
-				if (Byte != Memory.FillRAM[0x2108])
-				{
-					//FLUSH_REDRAW();
-					PPU.BG[1].SCSize = Byte & 3;
-					PPU.BG[1].SCBase = (Byte & 0x7c) << 8;
-				}
-
-				break;
-
-			case 0x2109: // BG3SC
-				if (Byte != Memory.FillRAM[0x2109])
-				{
-					//FLUSH_REDRAW();
-					PPU.BG[2].SCSize = Byte & 3;
-					PPU.BG[2].SCBase = (Byte & 0x7c) << 8;
-				}
-
-				break;
-
-			case 0x210a: // BG4SC
-				if (Byte != Memory.FillRAM[0x210a])
-				{
-					//FLUSH_REDRAW();
-					PPU.BG[3].SCSize = Byte & 3;
-					PPU.BG[3].SCBase = (Byte & 0x7c) << 8;
-				}
-
-				break;
-
-			case 0x210b: // BG12NBA
-				if (Byte != Memory.FillRAM[0x210b])
-				{
-					//FLUSH_REDRAW();
-					PPU.BG[0].NameBase = (Byte & 7) << 12;
-					PPU.BG[1].NameBase = ((Byte >> 4) & 7) << 12;
-				}
-
-				break;
-
-			case 0x210c: // BG34NBA
-				if (Byte != Memory.FillRAM[0x210c])
-				{
-					//FLUSH_REDRAW();
-					PPU.BG[2].NameBase = (Byte & 7) << 12;
-					PPU.BG[3].NameBase = ((Byte >> 4) & 7) << 12;
-				}
+					IPPU.Interlace = !!(Memory.FillRAM[0x2133] & 1);
 
 				break;
 
 			case 0x210d: // BG1HOFS, M7HOFS
-				PPU.BG[0].HOffset = (Byte << 8) | (PPU.BGnxOFSbyte & ~7) | ((PPU.BG[0].HOffset >> 8) & 7);
-				PPU.M7HOFS = (Byte << 8) | PPU.M7byte;
-				PPU.BGnxOFSbyte = Byte;
 				PPU.M7byte = Byte;
 				break;
 
 			case 0x210e: // BG1VOFS, M7VOFS
-				PPU.BG[0].VOffset = (Byte << 8) | PPU.BGnxOFSbyte;
-				PPU.M7VOFS = (Byte << 8) | PPU.M7byte;
-				PPU.BGnxOFSbyte = Byte;
 				PPU.M7byte = Byte;
 				break;
 
-			case 0x210f: // BG2HOFS
-				PPU.BG[1].HOffset = (Byte << 8) | (PPU.BGnxOFSbyte & ~7) | ((PPU.BG[1].HOffset >> 8) & 7);
-				PPU.BGnxOFSbyte = Byte;
-				break;
-
-			case 0x2110: // BG2VOFS
-				PPU.BG[1].VOffset = (Byte << 8) | PPU.BGnxOFSbyte;
-				PPU.BGnxOFSbyte = Byte;
-				break;
-
-			case 0x2111: // BG3HOFS
-				PPU.BG[2].HOffset = (Byte << 8) | (PPU.BGnxOFSbyte & ~7) | ((PPU.BG[2].HOffset >> 8) & 7);
-				PPU.BGnxOFSbyte = Byte;
-				break;
-
-			case 0x2112: // BG3VOFS
-				PPU.BG[2].VOffset = (Byte << 8) | PPU.BGnxOFSbyte;
-				PPU.BGnxOFSbyte = Byte;
-				break;
-
-			case 0x2113: // BG4HOFS
-				PPU.BG[3].HOffset = (Byte << 8) | (PPU.BGnxOFSbyte & ~7) | ((PPU.BG[3].HOffset >> 8) & 7);
-				PPU.BGnxOFSbyte = Byte;
-				break;
-
-			case 0x2114: // BG4VOFS
-				PPU.BG[3].VOffset = (Byte << 8) | PPU.BGnxOFSbyte;
-				PPU.BGnxOFSbyte = Byte;
-				break;
-
 			case 0x2115: // VMAIN
-				PPU.VMA.High = (Byte & 0x80) == 0 ? false : true;
+				PPU.VMA.High = !!(Byte & 0x80);
 				switch (Byte & 3)
 				{
-					case 0: PPU.VMA.Increment = 1;   break;
-					case 1: PPU.VMA.Increment = 32;  break;
-					case 2: PPU.VMA.Increment = 128; break;
-					case 3: PPU.VMA.Increment = 128; break;
+					case 0:
+						PPU.VMA.Increment = 1;
+						break;
+					case 1:
+						PPU.VMA.Increment = 32;
+						break;
+					case 2:
+					case 3:
+						PPU.VMA.Increment = 128;
 				}
 
 				if (Byte & 0x0c)
 				{
-					static uint16_t Shift[4]    = { 0, 5, 6, 7 };
-					static uint16_t IncCount[4] = { 0, 32, 64, 128 };
+					static const uint16_t Shift[] = { 0, 5, 6, 7 };
+					static const uint16_t IncCount[] = { 0, 32, 64, 128 };
 
 					uint8_t i = (Byte & 0x0c) >> 2;
 					PPU.VMA.FullGraphicCount = IncCount[i];
 					PPU.VMA.Mask1 = IncCount[i] * 8 - 1;
 					PPU.VMA.Shift = Shift[i];
-				#ifdef DEBUGGER
-					missing.vram_full_graphic_inc = (Byte & 0x0c) >> 2;
-				#endif
 				}
 				else
 					PPU.VMA.FullGraphicCount = 0;
-			#ifdef DEBUGGER
-				if (Byte & 3)
-					missing.vram_inc = Byte & 3;
-			#endif
 				break;
 
 			case 0x2116: // VMADDL
@@ -625,10 +335,10 @@
 					uint32_t addr = PPU.VMA.Address;
 					uint32_t rem = addr & PPU.VMA.Mask1;
 					uint32_t address = (addr & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3);
-					IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((address << 1) & 0xffff));
+					IPPU.VRAMReadBuffer = READ_WORD(&Memory.VRAM[(address << 1) & 0xffff]);
 				}
 				else
-					IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((PPU.VMA.Address << 1) & 0xffff));
+					IPPU.VRAMReadBuffer = READ_WORD(&Memory.VRAM[(PPU.VMA.Address << 1) & 0xffff]);
 
 				break;
 
@@ -641,10 +351,10 @@
 					uint32_t addr = PPU.VMA.Address;
 					uint32_t rem = addr & PPU.VMA.Mask1;
 					uint32_t address = (addr & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3);
-					IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((address << 1) & 0xffff));
+					IPPU.VRAMReadBuffer = READ_WORD(&Memory.VRAM[(address << 1) & 0xffff]);
 				}
 				else
-					IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((PPU.VMA.Address << 1) & 0xffff));
+					IPPU.VRAMReadBuffer = READ_WORD(&Memory.VRAM[(PPU.VMA.Address << 1) & 0xffff]);
 
 				break;
 
@@ -654,19 +364,6 @@
 
 			case 0x2119: // VMDATAH
 				REGISTER_2119(Byte);
-				break;
-
-			case 0x211a: // M7SEL
-				if (Byte != Memory.FillRAM[0x211a])
-				{
-					//FLUSH_REDRAW();
-					PPU.Mode7Repeat = Byte >> 6;
-					if (PPU.Mode7Repeat == 1)
-						PPU.Mode7Repeat = 0;
-					PPU.Mode7VFlip = !!((Byte & 2) >> 1);
-					PPU.Mode7HFlip = Byte & 1;
-				}
-
 				break;
 
 			case 0x211b: // M7A
@@ -682,329 +379,30 @@
 				break;
 
 			case 0x211d: // M7C
-				PPU.MatrixC = PPU.M7byte | (Byte << 8);
+			case 0x211e: // M7D
+			case 0x211f: // M7X
+			case 0x2120: // M7Y
 				PPU.M7byte = Byte;
 				break;
 
-			case 0x211e: // M7D
-				PPU.MatrixD = PPU.M7byte | (Byte << 8);
-				PPU.M7byte = Byte;
-				break;
-
-			case 0x211f: // M7X
-				PPU.CentreX = PPU.M7byte | (Byte << 8);
-				PPU.M7byte = Byte;
-				break;
-
-			case 0x2120: // M7Y
-				PPU.CentreY = PPU.M7byte | (Byte << 8);
-				PPU.M7byte = Byte;
-				break;
-
 			case 0x2121: // CGADD
-				PPU.CGFLIP = 0;
-				PPU.CGFLIPRead = 0;
+				PPU.CGFLIPRead = false;
 				PPU.CGADD = Byte;
-				break;
-
-			/*case 0x2122: // CGDATA
-				REGISTER_2122(Byte);
-				break;*/
-
-			case 0x2123: // W12SEL
-				if (Byte != Memory.FillRAM[0x2123])
-				{
-					//FLUSH_REDRAW();
-					PPU.ClipWindow1Enable[0] = !!(Byte & 0x02);
-					PPU.ClipWindow1Enable[1] = !!(Byte & 0x20);
-					PPU.ClipWindow2Enable[0] = !!(Byte & 0x08);
-					PPU.ClipWindow2Enable[1] = !!(Byte & 0x80);
-					PPU.ClipWindow1Inside[0] = !(Byte & 0x01);
-					PPU.ClipWindow1Inside[1] = !(Byte & 0x10);
-					PPU.ClipWindow2Inside[0] = !(Byte & 0x04);
-					PPU.ClipWindow2Inside[1] = !(Byte & 0x40);
-					PPU.RecomputeClipWindows = true;
-				#ifdef DEBUGGER
-					if (Byte & 0x80)
-						missing.window2[1] = 1;
-					if (Byte & 0x20)
-						missing.window1[1] = 1;
-					if (Byte & 0x08)
-						missing.window2[0] = 1;
-					if (Byte & 0x02)
-						missing.window1[0] = 1;
-				#endif
-				}
-
-				break;
-
-			case 0x2124: // W34SEL
-				if (Byte != Memory.FillRAM[0x2124])
-				{
-					//FLUSH_REDRAW();
-					PPU.ClipWindow1Enable[2] = !!(Byte & 0x02);
-					PPU.ClipWindow1Enable[3] = !!(Byte & 0x20);
-					PPU.ClipWindow2Enable[2] = !!(Byte & 0x08);
-					PPU.ClipWindow2Enable[3] = !!(Byte & 0x80);
-					PPU.ClipWindow1Inside[2] = !(Byte & 0x01);
-					PPU.ClipWindow1Inside[3] = !(Byte & 0x10);
-					PPU.ClipWindow2Inside[2] = !(Byte & 0x04);
-					PPU.ClipWindow2Inside[3] = !(Byte & 0x40);
-					PPU.RecomputeClipWindows = true;
-				#ifdef DEBUGGER
-					if (Byte & 0x80)
-						missing.window2[3] = 1;
-					if (Byte & 0x20)
-						missing.window1[3] = 1;
-					if (Byte & 0x08)
-						missing.window2[2] = 1;
-					if (Byte & 0x02)
-						missing.window1[2] = 1;
-				#endif
-				}
-
-				break;
-
-			case 0x2125: // WOBJSEL
-				if (Byte != Memory.FillRAM[0x2125])
-				{
-					//FLUSH_REDRAW();
-					PPU.ClipWindow1Enable[4] = !!(Byte & 0x02);
-					PPU.ClipWindow1Enable[5] = !!(Byte & 0x20);
-					PPU.ClipWindow2Enable[4] = !!(Byte & 0x08);
-					PPU.ClipWindow2Enable[5] = !!(Byte & 0x80);
-					PPU.ClipWindow1Inside[4] = !(Byte & 0x01);
-					PPU.ClipWindow1Inside[5] = !(Byte & 0x10);
-					PPU.ClipWindow2Inside[4] = !(Byte & 0x04);
-					PPU.ClipWindow2Inside[5] = !(Byte & 0x40);
-					PPU.RecomputeClipWindows = true;
-				#ifdef DEBUGGER
-					if (Byte & 0x80)
-						missing.window2[5] = 1;
-					if (Byte & 0x20)
-						missing.window1[5] = 1;
-					if (Byte & 0x08)
-						missing.window2[4] = 1;
-					if (Byte & 0x02)
-						missing.window1[4] = 1;
-				#endif
-				}
-
-				break;
-
-			case 0x2126: // WH0
-				if (Byte != Memory.FillRAM[0x2126])
-				{
-					//FLUSH_REDRAW();
-					PPU.Window1Left = Byte;
-					PPU.RecomputeClipWindows = true;
-				}
-
-				break;
-
-			case 0x2127: // WH1
-				if (Byte != Memory.FillRAM[0x2127])
-				{
-					//FLUSH_REDRAW();
-					PPU.Window1Right = Byte;
-					PPU.RecomputeClipWindows = true;
-				}
-
-				break;
-
-			case 0x2128: // WH2
-				if (Byte != Memory.FillRAM[0x2128])
-				{
-					//FLUSH_REDRAW();
-					PPU.Window2Left = Byte;
-					PPU.RecomputeClipWindows = true;
-				}
-
-				break;
-
-			case 0x2129: // WH3
-				if (Byte != Memory.FillRAM[0x2129])
-				{
-					//FLUSH_REDRAW();
-					PPU.Window2Right = Byte;
-					PPU.RecomputeClipWindows = true;
-				}
-
-				break;
-
-			case 0x212a: // WBGLOG
-				if (Byte != Memory.FillRAM[0x212a])
-				{
-					//FLUSH_REDRAW();
-					PPU.ClipWindowOverlapLogic[0] = (Byte & 0x03);
-					PPU.ClipWindowOverlapLogic[1] = (Byte & 0x0c) >> 2;
-					PPU.ClipWindowOverlapLogic[2] = (Byte & 0x30) >> 4;
-					PPU.ClipWindowOverlapLogic[3] = (Byte & 0xc0) >> 6;
-					PPU.RecomputeClipWindows = true;
-				}
-
-				break;
-
-			case 0x212b: // WOBJLOG
-				if (Byte != Memory.FillRAM[0x212b])
-				{
-					//FLUSH_REDRAW();
-					PPU.ClipWindowOverlapLogic[4] = (Byte & 0x03);
-					PPU.ClipWindowOverlapLogic[5] = (Byte & 0x0c) >> 2;
-					PPU.RecomputeClipWindows = true;
-				}
-
-				break;
-
-			case 0x212c: // TM
-				if (Byte != Memory.FillRAM[0x212c])
-				{
-					//FLUSH_REDRAW();
-					PPU.RecomputeClipWindows = true;
-				}
-
-				break;
-
-			case 0x212d: // TS
-				if (Byte != Memory.FillRAM[0x212d])
-				{
-					//FLUSH_REDRAW();
-					PPU.RecomputeClipWindows = true;
-				#ifdef DEBUGGER
-					if (Byte & 0x1f)
-						missing.subscreen = 1;
-				#endif
-				}
-
-				break;
-
-			case 0x212e: // TMW
-				if (Byte != Memory.FillRAM[0x212e])
-				{
-					//FLUSH_REDRAW();
-					PPU.RecomputeClipWindows = true;
-				}
-
-				break;
-
-			case 0x212f: // TSW
-				if (Byte != Memory.FillRAM[0x212f])
-				{
-					//FLUSH_REDRAW();
-					PPU.RecomputeClipWindows = true;
-				}
-
-				break;
-
-			case 0x2130: // CGWSEL
-				if (Byte != Memory.FillRAM[0x2130])
-				{
-					//FLUSH_REDRAW();
-					PPU.RecomputeClipWindows = true;
-				#ifdef DEBUGGER
-					if ((Byte & 1) && (PPU.BGMode == 3 || PPU.BGMode == 4 || PPU.BGMode == 7))
-						missing.direct = 1;
-				#endif
-				}
-
-				break;
-
-			case 0x2131: // CGADSUB
-				if (Byte != Memory.FillRAM[0x2131])
-				{
-					//FLUSH_REDRAW();
-				#ifdef DEBUGGER
-					if (Byte & 0x80)
-					{
-						if (Memory.FillRAM[0x2130] & 0x02)
-							missing.subscreen_sub = 1;
-						else
-							missing.fixed_colour_sub = 1;
-					}
-					else
-					{
-						if (Memory.FillRAM[0x2130] & 0x02)
-							missing.subscreen_add = 1;
-						else
-							missing.fixed_colour_add = 1;
-					}
-				#endif
-				}
-
-				break;
-
-			case 0x2132: // COLDATA
-				if (Byte != Memory.FillRAM[0x2132])
-				{
-					//FLUSH_REDRAW();
-					if (Byte & 0x80)
-						PPU.FixedColourBlue  = Byte & 0x1f;
-					if (Byte & 0x40)
-						PPU.FixedColourGreen = Byte & 0x1f;
-					if (Byte & 0x20)
-						PPU.FixedColourRed   = Byte & 0x1f;
-				}
-
 				break;
 
 			case 0x2133: // SETINI
 				if (Byte != Memory.FillRAM[0x2133])
 				{
-					if ((Memory.FillRAM[0x2133] ^ Byte) & 8)
-					{
-						//FLUSH_REDRAW();
-						IPPU.PseudoHires = !!(Byte & 8);
-					}
-
 					if (Byte & 0x04)
-					{
 						PPU.ScreenHeight = SNES_HEIGHT_EXTENDED;
-						if (IPPU.DoubleHeightPixels)
-							IPPU.RenderedScreenHeight = PPU.ScreenHeight << 1;
-						else
-							IPPU.RenderedScreenHeight = PPU.ScreenHeight;
-					#ifdef DEBUGGER
-						missing.lines_239 = 1;
-					#endif
-					}
 					else
 						PPU.ScreenHeight = SNES_HEIGHT;
 
 					if ((Memory.FillRAM[0x2133] ^ Byte) & 3)
-					{
-						//FLUSH_REDRAW();
-						if ((Memory.FillRAM[0x2133] ^ Byte) & 2)
-							IPPU.OBJChanged = true;
-						IPPU.Interlace = Byte & 1;
-						IPPU.InterlaceOBJ = !!(Byte & 2);
-					}
-				#ifdef DEBUGGER
-					if (Byte & 0x40)
-						missing.mode7_bgmode = 1;
-					if (Byte & 0x08)
-						missing.pseudo_512 = 1;
-					if (Byte & 0x02)
-						missing.sprite_double_height = 1;
-					if (Byte & 0x01)
-						missing.interlace = 1;
-				#endif
-				}
-
-				break;
-
-			case 0x2134: // MPYL
-			case 0x2135: // MPYM
-			case 0x2136: // MPYH
-			case 0x2137: // SLHV
-			case 0x2138: // OAMDATAREAD
-			case 0x2139: // VMDATALREAD
-			case 0x213a: // VMDATAHREAD
-			case 0x213b: // CGDATAREAD
-			case 0x213c: // OPHCT
-			case 0x213d: // OPVCT
-			case 0x213e: // STAT77
-			case 0x213f: // STAT78
-				return;
+						IPPU.Interlace = !!(Byte & 1);
+				}
+
+				break;
 
 			case 0x2180: // WMDATA
 				if (!CPU.InWRAMDMAorHDMA)
@@ -1040,45 +438,11 @@
 				break;
 		}
 	}
-	/*else
-	{
-		if (Settings.SuperFX && Address >= 0x3000 && Address <= 0x32ff)
-		{
-			S9xSetSuperFX(Byte, Address);
-			return;
-		}
-		else
-		if (Settings.SA1     && Address >= 0x2200)
-		{
-			if (Address <= 0x23ff)
-				S9xSetSA1(Byte, Address);
-			else
-				Memory.FillRAM[Address] = Byte;
-			return;
-		}
-		else
-		if (Settings.BS      && Address >= 0x2188 && Address <= 0x219f)
-			S9xSetBSXPPU(Byte, Address);
-		else
-		if (Settings.SRTC    && Address == 0x2801)
-			S9xSetSRTC(Byte, Address);
-	#ifdef DEBUGGER
-		else
-		{
-			missing.unknownppu_write = Address;
-			if (Settings.TraceUnknownRegisters)
-			{
-				sprintf(String, "Unknown register write: $%02X->$%04X\n", Byte, Address);
-				S9xMessage(S9X_TRACE, S9X_PPU_TRACE, String);
-			}
-		}
-	#endif
-	}*/
 
 	Memory.FillRAM[Address] = Byte;
 }
 
-uint8_t S9xGetPPU (uint16_t Address)
+uint8_t S9xGetPPU(uint16_t Address)
 {
 	// MAP_PPU: $2000-$3FFF
 
@@ -1088,17 +452,8 @@
 	if (CPU.InDMAorHDMA)
 	{
 		if (CPU.CurrentDMAorHDMAChannel >= 0 && !DMA[CPU.CurrentDMAorHDMAChannel].ReverseTransfer)
-		{
 			// S9xGetPPU() is called to read from DMA[].AAddress
-			if ((Address & 0xff00) == 0x2100)
-				// Cannot access to Address Bus B ($2100-$21FF) via (H)DMA
-				return OpenBus;
-			else
-				// $2200-$3FFF are connected to Address Bus A
-				// SA1, SuperFX and SRTC are mapped here
-				// I don't bother for now...
-				return OpenBus;
-		}
+			return OpenBus;
 		else
 		{
 			// S9xGetPPU() is called to write to $21xx
@@ -1111,10 +466,9 @@
 	if ((Address & 0xffc0) == 0x2140) // APUIO0, APUIO1, APUIO2, APUIO3
 		// read_port will run the APU until given APU time before reading value
 		return S9xAPUReadPort(Address & 3);
-	else
-	if (Address <= 0x2183)
-    {
-		uint8_t	byte;
+	else if (Address <= 0x2183)
+	{
+		uint8_t byte;
 
 		switch (Address)
 		{
@@ -1143,19 +497,15 @@
 			case 0x2136: // MPYH
 				if (PPU.Need16x8Mulitply)
 				{
-					int32_t r = (int32_t) PPU.MatrixA * (int32_t) (PPU.MatrixB >> 8);
-					Memory.FillRAM[0x2134] = (uint8_t) r;
-					Memory.FillRAM[0x2135] = (uint8_t) (r >> 8);
-					Memory.FillRAM[0x2136] = (uint8_t) (r >> 16);
+					int32_t r = static_cast<int32_t>(PPU.MatrixA) * static_cast<int32_t>(PPU.MatrixB >> 8);
+					Memory.FillRAM[0x2134] = static_cast<uint8_t>(r);
+					Memory.FillRAM[0x2135] = static_cast<uint8_t>(r >> 8);
+					Memory.FillRAM[0x2136] = static_cast<uint8_t>(r >> 16);
 					PPU.Need16x8Mulitply = false;
 				}
-			#ifdef DEBUGGER
-				missing.matrix_multiply = 1;
-			#endif
 				return (PPU.OpenBus1 = Memory.FillRAM[Address]);
 
 			case 0x2137: // SLHV
-				S9xLatchCounters(0);
 				return OpenBus;
 
 			case 0x2138: // OAMDATAREAD
@@ -1168,13 +518,7 @@
 						byte = PPU.OAMData[((PPU.OAMAddr & 0x10f) << 1) + 1];
 						PPU.OAMAddr = (PPU.OAMAddr + 1) & 0x1ff;
 						if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1))
-						{
 							PPU.FirstSprite = (PPU.OAMAddr & 0xfe) >> 1;
-							IPPU.OBJChanged = true;
-						#ifdef DEBUGGER
-							missing.sprite_priority_rotation = 1;
-						#endif
-						}
 					}
 				}
 				else
@@ -1186,20 +530,11 @@
 						byte = PPU.OAMData[(PPU.OAMAddr << 1) + 1];
 						++PPU.OAMAddr;
 						if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1))
-						{
 							PPU.FirstSprite = (PPU.OAMAddr & 0xfe) >> 1;
-							IPPU.OBJChanged = true;
-						#ifdef DEBUGGER
-							missing.sprite_priority_rotation = 1;
-						#endif
-						}
 					}
 				}
 
 				PPU.OAMFlip ^= 1;
-			#ifdef DEBUGGER
-				missing.oam_read = 1;
-			#endif
 				return (PPU.OpenBus1 = byte);
 
 			case 0x2139: // VMDATALREAD
@@ -1211,17 +546,13 @@
 						uint32_t addr = PPU.VMA.Address;
 						uint32_t rem = addr & PPU.VMA.Mask1;
 						uint32_t address = (addr & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3);
-						IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((address << 1) & 0xffff));
+						IPPU.VRAMReadBuffer = READ_WORD(&Memory.VRAM[(address << 1) & 0xffff]);
 					}
 					else
-						IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((PPU.VMA.Address << 1) & 0xffff));
+						IPPU.VRAMReadBuffer = READ_WORD(&Memory.VRAM[(PPU.VMA.Address << 1) & 0xffff]);
 
 					PPU.VMA.Address += PPU.VMA.Increment;
 				}
-
-			#ifdef DEBUGGER
-				missing.vram_read = 1;
-			#endif
 				return (PPU.OpenBus1 = byte);
 
 			case 0x213a: // VMDATAHREAD
@@ -1233,16 +564,13 @@
 						uint32_t addr = PPU.VMA.Address;
 						uint32_t rem = addr & PPU.VMA.Mask1;
 						uint32_t address = (addr & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3);
-						IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((address << 1) & 0xffff));
+						IPPU.VRAMReadBuffer = READ_WORD(&Memory.VRAM[(address << 1) & 0xffff]);
 					}
 					else
-						IPPU.VRAMReadBuffer = READ_WORD(Memory.VRAM + ((PPU.VMA.Address << 1) & 0xffff));
+						IPPU.VRAMReadBuffer = READ_WORD(&Memory.VRAM[(PPU.VMA.Address << 1) & 0xffff]);
 
 					PPU.VMA.Address += PPU.VMA.Increment;
 				}
-			#ifdef DEBUGGER
-				missing.vram_read = 1;
-			#endif
 				return (PPU.OpenBus1 = byte);
 
 			case 0x213b: // CGDATAREAD
@@ -1250,44 +578,31 @@
 					byte = (PPU.OpenBus2 & 0x80) | ((PPU.CGDATA[PPU.CGADD++] >> 8) & 0x7f);
 				else
 					byte = PPU.CGDATA[PPU.CGADD] & 0xff;
-				PPU.CGFLIPRead ^= 1;
-			#ifdef DEBUGGER
-				missing.cgram_read = 1;
-			#endif
+				PPU.CGFLIPRead = !PPU.CGFLIPRead;
 				return (PPU.OpenBus2 = byte);
 
 			case 0x213c: // OPHCT
-				S9xTryGunLatch(false);
 				if (PPU.HBeamFlip)
-					byte = (PPU.OpenBus2 & 0xfe) | ((PPU.HBeamPosLatched >> 8) & 0x01);
+					byte = PPU.OpenBus2 & 0xfe;
 				else
-					byte = (uint8_t) PPU.HBeamPosLatched;
-				PPU.HBeamFlip ^= 1;
-			#ifdef DEBUGGER
-				missing.h_counter_read = 1;
-			#endif
+					byte = 0;
+				PPU.HBeamFlip = !PPU.HBeamFlip;
 				return (PPU.OpenBus2 = byte);
 
 			case 0x213d: // OPVCT
-				S9xTryGunLatch(false);
 				if (PPU.VBeamFlip)
-					byte = (PPU.OpenBus2 & 0xfe) | ((PPU.VBeamPosLatched >> 8) & 0x01);
+					byte = PPU.OpenBus2 & 0xfe;
 				else
-					byte = (uint8_t) PPU.VBeamPosLatched;
-				PPU.VBeamFlip ^= 1;
-			#ifdef DEBUGGER
-				missing.v_counter_read = 1;
-			#endif
+					byte = 0;
+				PPU.VBeamFlip = !PPU.VBeamFlip;
 				return (PPU.OpenBus2 = byte);
 
 			case 0x213e: // STAT77
-				//FLUSH_REDRAW();
-				byte = (PPU.OpenBus1 & 0x10) | PPU.RangeTimeOver | Model->_5C77;
+				byte = (PPU.OpenBus1 & 0x10) | Model->_5C77;
 				return (PPU.OpenBus1 = byte);
 
 			case 0x213f: // STAT78
-				S9xTryGunLatch(false);
-				PPU.VBeamFlip = PPU.HBeamFlip = 0;
+				PPU.VBeamFlip = PPU.HBeamFlip = false;
 				byte = (PPU.OpenBus2 & 0x20) | (Memory.FillRAM[0x213f] & 0xc0) | (Settings.PAL ? 0x10 : 0) | Model->_5C78;
 				Memory.FillRAM[0x213f] &= ~0x40;
 				return (PPU.OpenBus2 = byte);
@@ -1300,9 +615,6 @@
 				}
 				else
 					byte = OpenBus;
-			#ifdef DEBUGGER
-				missing.wram_read = 1;
-			#endif
 				return byte;
 
 			default:
@@ -1310,19 +622,7 @@
 		}
 	}
 	else
-    {
-		/*if (Settings.SuperFX && Address >= 0x3000 && Address <= 0x32ff)
-			return S9xGetSuperFX(Address);
-		else
-		if (Settings.SA1     && Address >= 0x2200)
-			return S9xGetSA1(Address);
-		else
-		if (Settings.BS      && Address >= 0x2188 && Address <= 0x219f)
-			return S9xGetBSXPPU(Address);
-		else	
-		if (Settings.SRTC    && Address == 0x2800)
-			return S9xGetSRTC(Address);
-		else*/
+	{
 		switch (Address)
 		{
 			case 0x21c2:
@@ -1341,40 +641,24 @@
 	}
 }
 
-void S9xSetCPU (uint8_t Byte, uint16_t Address)
+void S9xSetCPU(uint8_t Byte, uint16_t Address)
 {
-	if (Address < 0x4200)
-	{
-		/*switch (Address)
-		{
-			case 0x4016: // JOYSER0
-				S9xSetJoypadLatch(Byte & 1);
-				break;
-
-			case 0x4017: // JOYSER1
-				return;
-
-			default:
-				break;
-		}*/
-	}
-	else
 	if ((Address & 0xff80) == 0x4300)
 	{
 		if (CPU.InDMAorHDMA)
 			return;
 
-		int	d = (Address >> 4) & 0x7;
+		int d = (Address >> 4) & 0x7;
 
 		switch (Address & 0xf)
 		{
 			case 0x0: // 0x43x0: DMAPx
-				DMA[d].ReverseTransfer        = (Byte & 0x80) ? true : false;
-				DMA[d].HDMAIndirectAddressing = (Byte & 0x40) ? true : false;
-				DMA[d].UnusedBit43x0          = (Byte & 0x20) ? true : false;
-				DMA[d].AAddressDecrement      = (Byte & 0x10) ? true : false;
-				DMA[d].AAddressFixed          = (Byte & 0x08) ? true : false;
-				DMA[d].TransferMode           = (Byte & 7);
+				DMA[d].ReverseTransfer = !!(Byte & 0x80);
+				DMA[d].HDMAIndirectAddressing = !!(Byte & 0x40);
+				DMA[d].UnusedBit43x0 = !!(Byte & 0x20);
+				DMA[d].AAddressDecrement = !!(Byte & 0x10);
+				DMA[d].AAddressFixed = !!(Byte & 0x08);
+				DMA[d].TransferMode = (Byte & 7);
 				return;
 
 			case 0x1: // 0x43x1: BBADx
@@ -1393,36 +677,36 @@
 
 			case 0x4: // 0x43x4: A1Bx
 				DMA[d].ABank = Byte;
-				HDMAMemPointers[d] = NULL;
+				HDMAMemPointers[d] = nullptr;
 				return;
 
 			case 0x5: // 0x43x5: DASxL
 				DMA[d].DMACount_Or_HDMAIndirectAddress &= 0xff00;
 				DMA[d].DMACount_Or_HDMAIndirectAddress |= Byte;
-				HDMAMemPointers[d] = NULL;
+				HDMAMemPointers[d] = nullptr;
 				return;
 
 			case 0x6: // 0x43x6: DASxH
 				DMA[d].DMACount_Or_HDMAIndirectAddress &= 0xff;
 				DMA[d].DMACount_Or_HDMAIndirectAddress |= Byte << 8;
-				HDMAMemPointers[d] = NULL;
+				HDMAMemPointers[d] = nullptr;
 				return;
 
 			case 0x7: // 0x43x7: DASBx
 				DMA[d].IndirectBank = Byte;
-				HDMAMemPointers[d] = NULL;
+				HDMAMemPointers[d] = nullptr;
 				return;
 
 			case 0x8: // 0x43x8: A2AxL
 				DMA[d].Address &= 0xff00;
 				DMA[d].Address |= Byte;
-				HDMAMemPointers[d] = NULL;
+				HDMAMemPointers[d] = nullptr;
 				return;
 
 			case 0x9: // 0x43x9: A2AxH
 				DMA[d].Address &= 0xff;
 				DMA[d].Address |= Byte << 8;
-				HDMAMemPointers[d] = NULL;
+				HDMAMemPointers[d] = nullptr;
 				return;
 
 			case 0xa: // 0x43xa: NLTRx
@@ -1443,84 +727,47 @@
 			case 0xf: // 0x43xf: mirror of 0x43xb
 				DMA[d].UnknownByte = Byte;
 				return;
-
-			default:
-				break;
 		}
 	}
-	else
-	{
-		uint16_t	pos;
+	else if (Address >= 0x4200)
+	{
+		uint16_t pos;
 
 		switch (Address)
 		{
 			case 0x4200: // NMITIMEN
-				if (Byte & 0x20)
-				{
-					PPU.VTimerEnabled = true;
-				#ifdef DEBUGGER
-					missing.virq = 1;
-					missing.virq_pos = PPU.IRQVBeamPos;
-				#endif
-				}
-				else
-					PPU.VTimerEnabled = false;
-
-				if (Byte & 0x10)
-				{
-					PPU.HTimerEnabled = true;
-				#ifdef DEBUGGER
-					missing.hirq = 1;
-					missing.hirq_pos = PPU.IRQHBeamPos;
-				#endif
-				}
-				else
-					PPU.HTimerEnabled = false;
+				PPU.VTimerEnabled = !!(Byte & 0x20);
+				PPU.HTimerEnabled = !!(Byte & 0x10);
 
 				if (CPU.IRQLine && !PPU.HTimerEnabled && PPU.VTimerEnabled)
 					CPU.IRQTransition = true;
 
 				if (!PPU.HTimerEnabled && !PPU.VTimerEnabled)
-				{
-					CPU.IRQLine = false;
-					CPU.IRQTransition = false;
-				}
+					CPU.IRQLine = CPU.IRQTransition = false;
 
 				// NMI can trigger immediately during VBlank as long as NMI_read ($4210) wasn't cleard.
-				if ((Byte & 0x80) && !(Memory.FillRAM[0x4200] & 0x80) &&
-					(CPU.V_Counter >= PPU.ScreenHeight + FIRST_VISIBLE_LINE) && (Memory.FillRAM[0x4210] & 0x80))
+				if ((Byte & 0x80) && !(Memory.FillRAM[0x4200] & 0x80) && CPU.V_Counter >= PPU.ScreenHeight + FIRST_VISIBLE_LINE && (Memory.FillRAM[0x4210] & 0x80))
 				{
 					// FIXME: triggered at HC+=6, checked just before the final CPU cycle,
 					// then, when to call S9xOpcode_NMI()?
 					CPU.NMILine = true;
-					Timings.NMITriggerPos = CPU.Cycles + 6 + 6;
+					Timings.NMITriggerPos = CPU.Cycles + 12;
 				}
 
 				break;
 
 			case 0x4201: // WRIO
-				if ((Byte & 0x80) == 0 && (Memory.FillRAM[0x4213] & 0x80) == 0x80)
-					S9xLatchCounters(1);
-				else
-					S9xTryGunLatch((Byte & 0x80) ? true : false);
 				Memory.FillRAM[0x4201] = Memory.FillRAM[0x4213] = Byte;
-				break;
-
-			case 0x4202: // WRMPYA
 				break;
 
 			case 0x4203: // WRMPYB
 			{
 				uint32_t res = Memory.FillRAM[0x4202] * Byte;
 				// FIXME: The update occurs 8 machine cycles after $4203 is set.
-				Memory.FillRAM[0x4216] = (uint8_t) res;
-				Memory.FillRAM[0x4217] = (uint8_t) (res >> 8);
+				Memory.FillRAM[0x4216] = static_cast<uint8_t>(res);
+				Memory.FillRAM[0x4217] = static_cast<uint8_t>(res >> 8);
 				break;
 			}
-
-			case 0x4204: // WRDIVL
-			case 0x4205: // WRDIVH
-				break;
 
 			case 0x4206: // WRDIVB
 			{
@@ -1528,9 +775,9 @@
 				uint16_t div = Byte ? a / Byte : 0xffff;
 				uint16_t rem = Byte ? a % Byte : a;
 				// FIXME: The update occurs 16 machine cycles after $4206 is set.
-				Memory.FillRAM[0x4214] = (uint8_t) div;
+				Memory.FillRAM[0x4214] = static_cast<uint8_t>(div);
 				Memory.FillRAM[0x4215] = div >> 8;
-				Memory.FillRAM[0x4216] = (uint8_t) rem;
+				Memory.FillRAM[0x4216] = static_cast<uint8_t>(rem);
 				Memory.FillRAM[0x4217] = rem >> 8;
 				break;
 			}
@@ -1540,9 +787,6 @@
 				PPU.IRQHBeamPos = (PPU.IRQHBeamPos & 0xff00) | Byte;
 				if (PPU.IRQHBeamPos != pos)
 					S9xUpdateHVTimerPosition();
-			#ifdef DEBUGGER
-				missing.hirq_pos = PPU.IRQHBeamPos;
-			#endif
 				break;
 
 			case 0x4208: // HTIMEH
@@ -1550,9 +794,6 @@
 				PPU.IRQHBeamPos = (PPU.IRQHBeamPos & 0xff) | ((Byte & 1) << 8);
 				if (PPU.IRQHBeamPos != pos)
 					S9xUpdateHVTimerPosition();
-			#ifdef DEBUGGER
-				missing.hirq_pos = PPU.IRQHBeamPos;
-			#endif
 				break;
 
 			case 0x4209: // VTIMEL
@@ -1560,9 +801,6 @@
 				PPU.IRQVBeamPos = (PPU.IRQVBeamPos & 0xff00) | Byte;
 				if (PPU.IRQVBeamPos != pos)
 					S9xUpdateHVTimerPosition();
-			#ifdef DEBUGGER
-				missing.virq_pos = PPU.IRQVBeamPos;
-			#endif
 				break;
 
 			case 0x420a: // VTIMEH
@@ -1570,9 +808,6 @@
 				PPU.IRQVBeamPos = (PPU.IRQVBeamPos & 0xff) | ((Byte & 1) << 8);
 				if (PPU.IRQVBeamPos != pos)
 					S9xUpdateHVTimerPosition();
-			#ifdef DEBUGGER
-				missing.virq_pos = PPU.IRQVBeamPos;
-			#endif
 				break;
 
 			case 0x420b: // MDMAEN
@@ -1597,10 +832,6 @@
 					S9xDoDMA(6);
 				if (Byte & 0x80)
 					S9xDoDMA(7);
-			#ifdef DEBUGGER
-				missing.dma_this_frame = Byte;
-				missing.dma_channels = Byte;
-			#endif
 				break;
 
 			case 0x420c: // HDMAEN
@@ -1609,22 +840,13 @@
 				Memory.FillRAM[0x420c] = Byte;
 				// Yoshi's Island, Genjyu Ryodan, Mortal Kombat, Tales of Phantasia
 				PPU.HDMA = Byte & ~PPU.HDMAEnded;
-			#ifdef DEBUGGER
-				missing.hdma_this_frame |= Byte;
-				missing.hdma_channels |= Byte;
-			#endif
 				break;
 
 			case 0x420d: // MEMSEL
 				if ((Byte & 1) != (Memory.FillRAM[0x420d] & 1))
 				{
 					if (Byte & 1)
-					{
 						CPU.FastROMSpeed = ONE_CYCLE;
-					#ifdef DEBUGGER
-						missing.fast_rom = 1;
-					#endif
-					}
 					else
 						CPU.FastROMSpeed = SLOW_ONE_CYCLE;
 				}
@@ -1650,58 +872,30 @@
 				return;
 
 			default:
-				/*if (Settings.SPC7110 && Address >= 0x4800)
-					S9xSetSPC7110(Byte, Address);
-				else*/
 				if (Settings.SDD1 && Address >= 0x4804 && Address <= 0x4807)
 					S9xSetSDD1MemoryMap(Address - 0x4804, Byte & 7);
-				break;
 		}
 	}
 
 	Memory.FillRAM[Address] = Byte;
 }
 
-uint8_t S9xGetCPU (uint16_t Address)
+uint8_t S9xGetCPU(uint16_t Address)
 {
 	if (Address < 0x4200)
-	{
-	#ifdef SNES_JOY_READ_CALLBACKS
-		extern bool pad_read;
-		if (Address == 0x4016 || Address == 0x4017)
-		{
-			S9xOnSNESPadRead();
-			pad_read = true;
-		}
-	#endif
-
-		/*switch (Address)
-		{
-			case 0x4016: // JOYSER0
-			case 0x4017: // JOYSER1
-				return S9xReadJOYSERn(Address);
-
-			default:*/
-				return OpenBus;
-		//}
-	}
-	else
-	if ((Address & 0xff80) == 0x4300)
+		return OpenBus;
+	else if ((Address & 0xff80) == 0x4300)
 	{
 		if (CPU.InDMAorHDMA)
 			return OpenBus;
 
-		int	d = (Address >> 4) & 0x7;
+		int d = (Address >> 4) & 0x7;
 
 		switch (Address & 0xf)
 		{
 			case 0x0: // 0x43x0: DMAPx
-				return  (DMA[d].ReverseTransfer        ? 0x80 : 0) |
-						(DMA[d].HDMAIndirectAddressing ? 0x40 : 0) |
-						(DMA[d].UnusedBit43x0          ? 0x20 : 0) |
-						(DMA[d].AAddressDecrement      ? 0x10 : 0) |
-						(DMA[d].AAddressFixed          ? 0x08 : 0) |
-						(DMA[d].TransferMode & 7);
+				return (DMA[d].ReverseTransfer ? 0x80 : 0) | (DMA[d].HDMAIndirectAddressing ? 0x40 : 0) | (DMA[d].UnusedBit43x0 ? 0x20 : 0) | (DMA[d].AAddressDecrement ? 0x10 : 0) |
+					(DMA[d].AAddressFixed ? 0x08 : 0) | (DMA[d].TransferMode & 7);
 
 			case 0x1: // 0x43x1: BBADx
 				return DMA[d].BAddress;
@@ -1743,7 +937,7 @@
 	}
 	else
 	{
-		uint8_t	byte;
+		uint8_t byte;
 
 		switch (Address)
 		{
@@ -1778,19 +972,9 @@
 			case 0x421d: // JOY3H
 			case 0x421e: // JOY4L
 			case 0x421f: // JOY4H
-			#ifdef SNES_JOY_READ_CALLBACKS
-				extern bool pad_read;
-				if (Memory.FillRAM[0x4200] & 1)
-				{
-					S9xOnSNESPadRead();
-					pad_read = true;
-				}
-			#endif
 				return Memory.FillRAM[Address];
 
 			default:
-				/*if (Settings.SPC7110 && Address >= 0x4800)
-					return S9xGetSPC7110(Address);*/
 				if (Settings.SDD1 && Address >= 0x4800 && Address <= 0x4807)
 					return Memory.FillRAM[Address];
 				return OpenBus;
@@ -1801,186 +985,65 @@
 void S9xResetPPU()
 {
 	S9xSoftResetPPU();
-	//S9xControlsReset();
-	PPU.M7HOFS = 0;
-	PPU.M7VOFS = 0;
 	PPU.M7byte = 0;
 }
 
 void S9xSoftResetPPU()
 {
-	//S9xControlsSoftReset();
-
-	PPU.VMA.High = 0;
+	PPU.VMA.High = false;
 	PPU.VMA.Increment = 1;
-	PPU.VMA.Address = 0;
-	PPU.VMA.FullGraphicCount = 0;
-	PPU.VMA.Shift = 0;
+	PPU.VMA.Address = PPU.VMA.FullGraphicCount = PPU.VMA.Shift = 0;
 
 	PPU.WRAM = 0;
 
-	for (int c = 0; c < 4; c++)
-	{
-		PPU.BG[c].SCBase = 0;
-		PPU.BG[c].HOffset = 0;
-		PPU.BG[c].VOffset = 0;
-		PPU.BG[c].BGSize = 0;
-		PPU.BG[c].NameBase = 0;
-		PPU.BG[c].SCSize = 0;
-	}
-
-	PPU.BGMode = 0;
-	PPU.BG3Priority = 0;
-
-	PPU.CGFLIP = 0;
-	PPU.CGFLIPRead = 0;
+	PPU.CGFLIPRead = false;
 	PPU.CGADD = 0;
 
-	for (int c = 0; c < 256; c++)
-	{
-		IPPU.Red[c]   = (c & 7) << 2;
+	for (int c = 0; c < 256; ++c)
+	{
+		IPPU.Red[c] = (c & 7) << 2;
 		IPPU.Green[c] = ((c >> 3) & 7) << 2;
-		IPPU.Blue[c]  = ((c >> 6) & 2) << 3;
+		IPPU.Blue[c] = ((c >> 6) & 2) << 3;
 		PPU.CGDATA[c] = IPPU.Red[c] | (IPPU.Green[c] << 5) | (IPPU.Blue[c] << 10);
 	}
 
-	for (int c = 0; c < 128; c++)
-	{
-		PPU.OBJ[c].HPos = 0;
-		PPU.OBJ[c].VPos = 0;
-		PPU.OBJ[c].HFlip = 0;
-		PPU.OBJ[c].VFlip = 0;
-		PPU.OBJ[c].Name = 0;
-		PPU.OBJ[c].Priority = 0;
-		PPU.OBJ[c].Palette = 0;
-		PPU.OBJ[c].Size = 0;
-	}
-
-	PPU.OBJThroughMain = false;
-	PPU.OBJThroughSub = false;
-	PPU.OBJAddition = false;
-	PPU.OBJNameBase = 0;
-	PPU.OBJNameSelect = 0;
-	PPU.OBJSizeSelect = 0;
-
-	PPU.OAMAddr = 0;
-	PPU.SavedOAMAddr = 0;
-	PPU.OAMPriorityRotation = 0;
+	PPU.OAMAddr = PPU.SavedOAMAddr = 0;
+	PPU.OAMPriorityRotation = false;
 	PPU.OAMFlip = 0;
-	PPU.OAMReadFlip = 0;
-	PPU.OAMTileAddress = 0;
 	PPU.OAMWriteRegister = 0;
-	ZeroMemory(PPU.OAMData, 512 + 32);
+	std::fill(&PPU.OAMData[0], &PPU.OAMData[512 + 32], 0);
 
 	PPU.FirstSprite = 0;
-	PPU.LastSprite = 127;
-	PPU.RangeTimeOver = 0;
-
-	PPU.HTimerEnabled = false;
-	PPU.VTimerEnabled = false;
+
+	PPU.HTimerEnabled = PPU.VTimerEnabled = false;
 	PPU.HTimerPosition = Timings.H_Max + 1;
 	PPU.VTimerPosition = Timings.V_Max + 1;
-	PPU.IRQHBeamPos = 0x1ff;
-	PPU.IRQVBeamPos = 0x1ff;
-
-	PPU.HBeamFlip = 0;
-	PPU.VBeamFlip = 0;
-	PPU.HBeamPosLatched = 0;
-	PPU.VBeamPosLatched = 0;
-	PPU.GunHLatch = 0;
-	PPU.GunVLatch = 1000;
-	PPU.HVBeamCounterLatched = 0;
-
-	PPU.Mode7HFlip = false;
-	PPU.Mode7VFlip = false;
-	PPU.Mode7Repeat = 0;
-	PPU.MatrixA = 0;
-	PPU.MatrixB = 0;
-	PPU.MatrixC = 0;
-	PPU.MatrixD = 0;
-	PPU.CentreX = 0;
-	PPU.CentreY = 0;
-
-	PPU.Mosaic = 0;
-	PPU.BGMosaic[0] = false;
-	PPU.BGMosaic[1] = false;
-	PPU.BGMosaic[2] = false;
-	PPU.BGMosaic[3] = false;
-	
-	PPU.Window1Left = 1;
-	PPU.Window1Right = 0;
-	PPU.Window2Left = 1;
-	PPU.Window2Right = 0;
-	PPU.RecomputeClipWindows = true;
-
-	for (int c = 0; c < 6; c++)
-	{
-		PPU.ClipCounts[c] = 0;
-		PPU.ClipWindowOverlapLogic[c] = CLIP_OR;
-		PPU.ClipWindow1Enable[c] = false;
-		PPU.ClipWindow2Enable[c] = false;
-		PPU.ClipWindow1Inside[c] = true;
-		PPU.ClipWindow2Inside[c] = true;
-	}
+	PPU.IRQHBeamPos = PPU.IRQVBeamPos = 0x1ff;
+
+	PPU.HBeamFlip = PPU.VBeamFlip = false;
+
+	PPU.MatrixA = PPU.MatrixB = 0;
 
 	PPU.ForcedBlanking = true;
 
-	PPU.FixedColourRed = 0;
-	PPU.FixedColourGreen = 0;
-	PPU.FixedColourBlue = 0;
-	PPU.Brightness = 0;
 	PPU.ScreenHeight = SNES_HEIGHT;
 
 	PPU.Need16x8Mulitply = false;
-	PPU.BGnxOFSbyte = 0;
-
-	PPU.HDMA = 0;
-	PPU.HDMAEnded = 0;
-
-	PPU.OpenBus1 = 0;
-	PPU.OpenBus2 = 0;
-
-	for (int c = 0; c < 2; c++)
-		memset(&IPPU.Clip[c], 0, sizeof(struct ClipData));
-	IPPU.ColorsChanged = true;
-	IPPU.OBJChanged = true;
-	IPPU.DirectColourMapsNeedRebuild = true;
-	ZeroMemory(IPPU.TileCached[TILE_2BIT], MAX_2BIT_TILES);
-	ZeroMemory(IPPU.TileCached[TILE_4BIT], MAX_4BIT_TILES);
-	ZeroMemory(IPPU.TileCached[TILE_8BIT], MAX_8BIT_TILES);
-	ZeroMemory(IPPU.TileCached[TILE_2BIT_EVEN], MAX_2BIT_TILES);
-	ZeroMemory(IPPU.TileCached[TILE_2BIT_ODD],  MAX_2BIT_TILES);
-	ZeroMemory(IPPU.TileCached[TILE_4BIT_EVEN], MAX_4BIT_TILES);
-	ZeroMemory(IPPU.TileCached[TILE_4BIT_ODD],  MAX_4BIT_TILES);
+
+	PPU.HDMA = PPU.HDMAEnded = 0;
+
+	PPU.OpenBus1 = PPU.OpenBus2 = 0;
+
 	IPPU.VRAMReadBuffer = 0; // XXX: FIXME: anything better?
 	IPPU.Interlace = false;
-	IPPU.InterlaceOBJ = false;
-	IPPU.DoubleWidthPixels = false;
-	IPPU.DoubleHeightPixels = false;
-	IPPU.CurrentLine = 0;
-	IPPU.PreviousLine = 0;
-	IPPU.XB = NULL;
-	for (int c = 0; c < 256; c++)
-		IPPU.ScreenColors[c] = c;
-	IPPU.MaxBrightness = 0;
-	IPPU.RenderThisFrame = true;
-	IPPU.RenderedScreenWidth = SNES_WIDTH;
-	IPPU.RenderedScreenHeight = SNES_HEIGHT;
-	IPPU.FrameCount = 0;
-	IPPU.RenderedFramesCount = 0;
-	IPPU.DisplayedRenderedFrameCount = 0;
-	IPPU.SkippedFrames = 0;
-	IPPU.FrameSkip = 0;
-
-	//S9xFixColourBrightness();
 
 	for (int c = 0; c < 0x8000; c += 0x100)
-		memset(&Memory.FillRAM[c], c >> 8, 0x100);
-	ZeroMemory(&Memory.FillRAM[0x2100], 0x100);
-	ZeroMemory(&Memory.FillRAM[0x4200], 0x100);
-	ZeroMemory(&Memory.FillRAM[0x4000], 0x100);
+		std::fill(&Memory.FillRAM[c], &Memory.FillRAM[c + 0x100], c >> 8);
+	std::fill(&Memory.FillRAM[0x2100], &Memory.FillRAM[0x2200], 0);
+	std::fill(&Memory.FillRAM[0x4200], &Memory.FillRAM[0x4300], 0);
+	std::fill(&Memory.FillRAM[0x4000], &Memory.FillRAM[0x4100], 0);
 	// For BS Suttehakkun 2...
-	ZeroMemory(&Memory.FillRAM[0x1000], 0x1000);
+	std::fill(&Memory.FillRAM[0x1000], &Memory.FillRAM[0x2000], 0);
 
 	Memory.FillRAM[0x4201] = Memory.FillRAM[0x4213] = 0xff;
 }

--- a/src/in_snsf/snes9x/ppu.h
+++ b/src/in_snsf/snes9x/ppu.h
@@ -175,257 +175,120 @@
   Nintendo Co., Limited and its subsidiary companies.
  ***********************************************************************************/
 
-
 #ifndef _PPU_H_
 #define _PPU_H_
 
-#define FIRST_VISIBLE_LINE	1
-
-#define TILE_2BIT			0
-#define TILE_4BIT			1
-#define TILE_8BIT			2
-#define TILE_2BIT_EVEN		3
-#define TILE_2BIT_ODD		4
-#define TILE_4BIT_EVEN		5
-#define TILE_4BIT_ODD		6
-
-#define MAX_2BIT_TILES		4096
-#define MAX_4BIT_TILES		2048
-#define MAX_8BIT_TILES		1024
-
-#define CLIP_OR				0
-#define CLIP_AND			1
-#define CLIP_XOR			2
-#define CLIP_XNOR			3
-
-struct ClipData
-{
-	uint8_t	Count;
-	uint8_t	DrawMode[6];
-	uint16_t	Left[6];
-	uint16_t	Right[6];
+const int32_t FIRST_VISIBLE_LINE = 1;
+
+enum
+{
+	TILE_2BIT,
+	TILE_4BIT,
+	TILE_8BIT,
+	TILE_2BIT_EVEN,
+	TILE_2BIT_ODD,
+	TILE_4BIT_EVEN,
+	TILE_4BIT_ODD
 };
 
+const size_t MAX_2BIT_TILES = 4096;
+const size_t MAX_4BIT_TILES = 2048;
+const size_t MAX_8BIT_TILES = 1024;
+
 struct InternalPPU
 {
-	struct ClipData Clip[2][6];
-	bool	ColorsChanged;
-	bool	OBJChanged;
-	bool	DirectColourMapsNeedRebuild;
-	uint8_t	*TileCache[7];
-	uint8_t	*TileCached[7];
-	uint16_t	VRAMReadBuffer;
-	bool	Interlace;
-	bool	InterlaceOBJ;
-	bool	PseudoHires;
-	bool	DoubleWidthPixels;
-	bool	DoubleHeightPixels;
-	int		CurrentLine;
-	int		PreviousLine;
-	uint8_t	*XB;
-	uint32_t	Red[256];
-	uint32_t	Green[256];
-	uint32_t	Blue[256];
-	uint16_t	ScreenColors[256];
-	uint8_t	MaxBrightness;
-	bool	RenderThisFrame;
-	int		RenderedScreenWidth;
-	int		RenderedScreenHeight;
-	uint32_t	FrameCount;
-	uint32_t	RenderedFramesCount;
-	uint32_t	DisplayedRenderedFrameCount;
-	uint32_t	TotalEmulatedFrames;
-	uint32_t	SkippedFrames;
-	uint32_t	FrameSkip;
+	uint16_t VRAMReadBuffer;
+	bool Interlace;
+	uint32_t Red[256];
+	uint32_t Green[256];
+	uint32_t Blue[256];
 };
 
-struct SOBJ
-{
-	int16_t	HPos;
-	uint16_t	VPos;
-	uint8_t	HFlip;
-	uint8_t	VFlip;
-	uint16_t	Name;
-	uint8_t	Priority;
-	uint8_t	Palette;
-	uint8_t	Size;
+struct SPPU
+{
+	struct
+	{
+		bool High;
+		uint8_t Increment;
+		uint16_t Address;
+		uint16_t Mask1;
+		uint16_t FullGraphicCount;
+		uint16_t Shift;
+	} VMA;
+
+	uint32_t WRAM;
+
+	bool CGFLIPRead;
+	uint8_t CGADD;
+	uint16_t CGDATA[256];
+
+	uint16_t OAMAddr;
+	uint16_t SavedOAMAddr;
+	bool OAMPriorityRotation;
+	uint8_t OAMFlip;
+	uint16_t OAMWriteRegister;
+	uint8_t OAMData[512 + 32];
+
+	uint8_t FirstSprite;
+
+	bool HTimerEnabled;
+	bool VTimerEnabled;
+	short HTimerPosition;
+	short VTimerPosition;
+	uint16_t IRQHBeamPos;
+	uint16_t IRQVBeamPos;
+
+	bool HBeamFlip;
+	bool VBeamFlip;
+
+	short MatrixA;
+	short MatrixB;
+
+	bool ForcedBlanking;
+
+	uint16_t ScreenHeight;
+
+	bool Need16x8Mulitply;
+	uint8_t M7byte;
+
+	uint8_t HDMA;
+	uint8_t HDMAEnded;
+
+	uint8_t OpenBus1;
+	uint8_t OpenBus2;
 };
 
-struct SPPU
-{
-	struct
-	{
-		bool	High;
-		uint8_t	Increment;
-		uint16_t	Address;
-		uint16_t	Mask1;
-		uint16_t	FullGraphicCount;
-		uint16_t	Shift;
-	}	VMA;
-
-	uint32_t	WRAM;
-
-	struct
-	{
-		uint16_t	SCBase;
-		uint16_t	HOffset;
-		uint16_t	VOffset;
-		uint8_t	BGSize;
-		uint16_t	NameBase;
-		uint16_t	SCSize;
-	}	BG[4];
-
-	uint8_t	BGMode;
-	uint8_t	BG3Priority;
-
-	bool	CGFLIP;
-	uint8_t	CGFLIPRead;
-	uint8_t	CGADD;
-	uint16_t	CGDATA[256];
-
-	struct SOBJ OBJ[128];
-	bool	OBJThroughMain;
-	bool	OBJThroughSub;
-	bool	OBJAddition;
-	uint16_t	OBJNameBase;
-	uint16_t	OBJNameSelect;
-	uint8_t	OBJSizeSelect;
-
-	uint16_t	OAMAddr;
-	uint16_t	SavedOAMAddr;
-	uint8_t	OAMPriorityRotation;
-	uint8_t	OAMFlip;
-	uint8_t	OAMReadFlip;
-	uint16_t	OAMTileAddress;
-	uint16_t	OAMWriteRegister;
-	uint8_t	OAMData[512 + 32];
-
-	uint8_t	FirstSprite;
-	uint8_t	LastSprite;
-	uint8_t	RangeTimeOver;
-
-	bool	HTimerEnabled;
-	bool	VTimerEnabled;
-	short	HTimerPosition;
-	short	VTimerPosition;
-	uint16_t	IRQHBeamPos;
-	uint16_t	IRQVBeamPos;
-
-	uint8_t	HBeamFlip;
-	uint8_t	VBeamFlip;
-	uint16_t	HBeamPosLatched;
-	uint16_t	VBeamPosLatched;
-	uint16_t	GunHLatch;
-	uint16_t	GunVLatch;
-	uint8_t	HVBeamCounterLatched;
-
-	bool	Mode7HFlip;
-	bool	Mode7VFlip;
-	uint8_t	Mode7Repeat;
-	short	MatrixA;
-	short	MatrixB;
-	short	MatrixC;
-	short	MatrixD;
-	short	CentreX;
-	short	CentreY;
-	short	M7HOFS;
-	short	M7VOFS;
-
-	uint8_t	Mosaic;
-	uint8_t	MosaicStart;
-	bool	BGMosaic[4];
-
-	uint8_t	Window1Left;
-	uint8_t	Window1Right;
-	uint8_t	Window2Left;
-	uint8_t	Window2Right;
-	bool	RecomputeClipWindows;
-	uint8_t	ClipCounts[6];
-	uint8_t	ClipWindowOverlapLogic[6];
-	uint8_t	ClipWindow1Enable[6];
-	uint8_t	ClipWindow2Enable[6];
-	bool	ClipWindow1Inside[6];
-	bool	ClipWindow2Inside[6];
-
-	bool	ForcedBlanking;
-
-	uint8_t	FixedColourRed;
-	uint8_t	FixedColourGreen;
-	uint8_t	FixedColourBlue;
-	uint8_t	Brightness;
-	uint16_t	ScreenHeight;
-
-	bool	Need16x8Mulitply;
-	uint8_t	BGnxOFSbyte;
-	uint8_t	M7byte;
-
-	uint8_t	HDMA;
-	uint8_t	HDMAEnded;
-
-	uint8_t	OpenBus1;
-	uint8_t	OpenBus2;
-};
-
-extern uint16_t				SignExtend[2];
-extern struct SPPU			PPU;
-extern struct InternalPPU	IPPU;
+extern uint16_t SignExtend[2];
+extern SPPU PPU;
+extern InternalPPU IPPU;
 
 void S9xResetPPU();
 void S9xSoftResetPPU();
-void S9xSetPPU (uint8_t, uint16_t);
-uint8_t S9xGetPPU (uint16_t);
-void S9xSetCPU (uint8_t, uint16_t);
-uint8_t S9xGetCPU (uint16_t);
+void S9xSetPPU(uint8_t, uint16_t);
+uint8_t S9xGetPPU(uint16_t);
+void S9xSetCPU(uint8_t, uint16_t);
+uint8_t S9xGetCPU(uint16_t);
 void S9xUpdateHVTimerPosition();
-//void S9xFixColourBrightness();
-//void S9xDoAutoJoypad();
-
-//#include "gfx.h"
+
 #include "memmap.h"
 
-typedef struct
-{
-	uint8_t	_5C77;
-	uint8_t	_5C78;
-	uint8_t	_5A22;
-}	SnesModel;
-
-extern SnesModel	*Model;
-extern SnesModel	M1SNES;
-//extern SnesModel	M2SNES;
-
-#define MAX_5C77_VERSION	0x01
-#define MAX_5C78_VERSION	0x03
-#define MAX_5A22_VERSION	0x02
-
-/*static inline void FLUSH_REDRAW()
-{
-	if (IPPU.PreviousLine != IPPU.CurrentLine)
-		S9xUpdateScreen();
-}*/
-
-static inline void REGISTER_2104 (uint8_t Byte)
+struct SnesModel
+{
+	uint8_t _5C77;
+	uint8_t _5C78;
+	uint8_t _5A22;
+};
+
+extern SnesModel *Model;
+extern SnesModel M1SNES;
+
+inline void REGISTER_2104(uint8_t Byte)
 {
 	if (PPU.OAMAddr & 0x100)
 	{
 		int addr = ((PPU.OAMAddr & 0x10f) << 1) + (PPU.OAMFlip & 1);
 		if (Byte != PPU.OAMData[addr])
-		{
-			//FLUSH_REDRAW();
 			PPU.OAMData[addr] = Byte;
-			IPPU.OBJChanged = true;
-
-			// X position high bit, and sprite size (x4)
-			struct SOBJ *pObj = &PPU.OBJ[(addr & 0x1f) * 4];
-			pObj->HPos = (pObj->HPos & 0xFF) | SignExtend[(Byte >> 0) & 1];
-			pObj++->Size = Byte & 2;
-			pObj->HPos = (pObj->HPos & 0xFF) | SignExtend[(Byte >> 2) & 1];
-			pObj++->Size = Byte & 8;
-			pObj->HPos = (pObj->HPos & 0xFF) | SignExtend[(Byte >> 4) & 1];
-			pObj++->Size = Byte & 32;
-			pObj->HPos = (pObj->HPos & 0xFF) | SignExtend[(Byte >> 6) & 1];
-			pObj->Size = Byte & 128;
-		}
 
 		PPU.OAMFlip ^= 1;
 		if (!(PPU.OAMFlip & 1))
@@ -433,90 +296,45 @@
 			++PPU.OAMAddr;
 			PPU.OAMAddr &= 0x1ff;
 			if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1))
-			{
 				PPU.FirstSprite = (PPU.OAMAddr & 0xfe) >> 1;
-				IPPU.OBJChanged = true;
-			}
-		}
-		else
-		{
-			if (PPU.OAMPriorityRotation && (PPU.OAMAddr & 1))
-				IPPU.OBJChanged = true;
 		}
 	}
-	else
-	if (!(PPU.OAMFlip & 1))
+	else if (!(PPU.OAMFlip & 1))
 	{
 		PPU.OAMWriteRegister &= 0xff00;
 		PPU.OAMWriteRegister |= Byte;
 		PPU.OAMFlip |= 1;
-		if (PPU.OAMPriorityRotation && (PPU.OAMAddr & 1))
-			IPPU.OBJChanged = true;
 	}
 	else
 	{
 		PPU.OAMWriteRegister &= 0x00ff;
-		uint8_t lowbyte = (uint8_t) (PPU.OAMWriteRegister);
+		uint8_t lowbyte = static_cast<uint8_t>(PPU.OAMWriteRegister);
 		uint8_t highbyte = Byte;
 		PPU.OAMWriteRegister |= Byte << 8;
 
-		int addr = (PPU.OAMAddr << 1);
+		int addr = PPU.OAMAddr << 1;
 		if (lowbyte != PPU.OAMData[addr] || highbyte != PPU.OAMData[addr + 1])
 		{
-			//FLUSH_REDRAW();
 			PPU.OAMData[addr] = lowbyte;
 			PPU.OAMData[addr + 1] = highbyte;
-			IPPU.OBJChanged = true;
-			if (addr & 2)
-			{
-				// Tile
-				PPU.OBJ[addr = PPU.OAMAddr >> 1].Name = PPU.OAMWriteRegister & 0x1ff;
-				// priority, h and v flip.
-				PPU.OBJ[addr].Palette  = (highbyte >> 1) & 7;
-				PPU.OBJ[addr].Priority = (highbyte >> 4) & 3;
-				PPU.OBJ[addr].HFlip    = (highbyte >> 6) & 1;
-				PPU.OBJ[addr].VFlip    = (highbyte >> 7) & 1;
-			}
-			else
-			{
-				// X position (low)
-				PPU.OBJ[addr = PPU.OAMAddr >> 1].HPos &= 0xff00;
-				PPU.OBJ[addr].HPos |= lowbyte;
-				// Sprite Y position
-				PPU.OBJ[addr].VPos = highbyte;
-			}
 		}
 
 		PPU.OAMFlip &= ~1;
 		++PPU.OAMAddr;
 		if (PPU.OAMPriorityRotation && PPU.FirstSprite != (PPU.OAMAddr >> 1))
-		{
 			PPU.FirstSprite = (PPU.OAMAddr & 0xfe) >> 1;
-			IPPU.OBJChanged = true;
-		}
 	}
 }
 
 // This code is correct, however due to Snes9x's inaccurate timings, some games might be broken by this chage. :(
-#ifdef DEBUGGER
-#define CHECK_INBLANK() \
-	if (!PPU.ForcedBlanking && CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE) \
-	{ \
-		printf("Invalid VRAM acess at (%04d, %04d) blank:%d\n", CPU.Cycles, CPU.V_Counter, PPU.ForcedBlanking); \
-		if (Settings.BlockInvalidVRAMAccess) \
-			return; \
-	}
-#else
-#define CHECK_INBLANK() \
-	if (Settings.BlockInvalidVRAMAccess && !PPU.ForcedBlanking && CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE) \
-		return;
-#endif
-
-static inline void REGISTER_2118 (uint8_t Byte)
-{
-	CHECK_INBLANK();
-
-	uint32_t	address;
+inline bool CHECK_INBLANK() { return Settings.BlockInvalidVRAMAccess && !PPU.ForcedBlanking && CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE; }
+
+inline void REGISTER_2118(uint8_t Byte)
+{
+	if (CHECK_INBLANK())
+		return;
+
+	uint32_t address;
 
 	if (PPU.VMA.FullGraphicCount)
 	{
@@ -527,33 +345,16 @@
 	else
 		Memory.VRAM[address = (PPU.VMA.Address << 1) & 0xffff] = Byte;
 
-	IPPU.TileCached[TILE_2BIT][address >> 4] = false;
-	IPPU.TileCached[TILE_4BIT][address >> 5] = false;
-	IPPU.TileCached[TILE_8BIT][address >> 6] = false;
-	IPPU.TileCached[TILE_2BIT_EVEN][address >> 4] = false;
-	IPPU.TileCached[TILE_2BIT_EVEN][((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = false;
-	IPPU.TileCached[TILE_2BIT_ODD] [address >> 4] = false;
-	IPPU.TileCached[TILE_2BIT_ODD] [((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = false;
-	IPPU.TileCached[TILE_4BIT_EVEN][address >> 5] = false;
-	IPPU.TileCached[TILE_4BIT_EVEN][((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = false;
-	IPPU.TileCached[TILE_4BIT_ODD] [address >> 5] = false;
-	IPPU.TileCached[TILE_4BIT_ODD] [((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = false;
-
 	if (!PPU.VMA.High)
-	{
-	#ifdef DEBUGGER
-		if (Settings.TraceVRAM && !CPU.InDMAorHDMA)
-			printf("VRAM write byte: $%04X (%d, %d)\n", PPU.VMA.Address, Memory.FillRAM[0x2115] & 3, (Memory.FillRAM[0x2115] & 0x0c) >> 2);
-	#endif
-		PPU.VMA.Address += PPU.VMA.Increment;
-	}
-}
-
-static inline void REGISTER_2119 (uint8_t Byte)
-{
-	CHECK_INBLANK();
-
-	uint32_t	address;
+		PPU.VMA.Address += PPU.VMA.Increment;
+}
+
+inline void REGISTER_2119(uint8_t Byte)
+{
+	if (CHECK_INBLANK())
+		return;
+
+	uint32_t address;
 
 	if (PPU.VMA.FullGraphicCount)
 	{
@@ -564,178 +365,82 @@
 	else
 		Memory.VRAM[address = ((PPU.VMA.Address << 1) + 1) & 0xffff] = Byte;
 
-	IPPU.TileCached[TILE_2BIT][address >> 4] = false;
-	IPPU.TileCached[TILE_4BIT][address >> 5] = false;
-	IPPU.TileCached[TILE_8BIT][address >> 6] = false;
-	IPPU.TileCached[TILE_2BIT_EVEN][address >> 4] = false;
-	IPPU.TileCached[TILE_2BIT_EVEN][((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = false;
-	IPPU.TileCached[TILE_2BIT_ODD] [address >> 4] = false;
-	IPPU.TileCached[TILE_2BIT_ODD] [((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = false;
-	IPPU.TileCached[TILE_4BIT_EVEN][address >> 5] = false;
-	IPPU.TileCached[TILE_4BIT_EVEN][((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = false;
-	IPPU.TileCached[TILE_4BIT_ODD] [address >> 5] = false;
-	IPPU.TileCached[TILE_4BIT_ODD] [((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = false;
-
 	if (PPU.VMA.High)
-	{
-	#ifdef DEBUGGER
-		if (Settings.TraceVRAM && !CPU.InDMAorHDMA)
-			printf("VRAM write word: $%04X (%d, %d)\n", PPU.VMA.Address, Memory.FillRAM[0x2115] & 3, (Memory.FillRAM[0x2115] & 0x0c) >> 2);
-	#endif
-		PPU.VMA.Address += PPU.VMA.Increment;
-	}
-}
-
-static inline void REGISTER_2118_tile (uint8_t Byte)
-{
-	CHECK_INBLANK();
+		PPU.VMA.Address += PPU.VMA.Increment;
+}
+
+inline void REGISTER_2118_tile(uint8_t Byte)
+{
+	if (CHECK_INBLANK())
+		return;
 
 	uint32_t rem = PPU.VMA.Address & PPU.VMA.Mask1;
 	uint32_t address = (((PPU.VMA.Address & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3)) << 1) & 0xffff;
 
 	Memory.VRAM[address] = Byte;
 
-	IPPU.TileCached[TILE_2BIT][address >> 4] = false;
-	IPPU.TileCached[TILE_4BIT][address >> 5] = false;
-	IPPU.TileCached[TILE_8BIT][address >> 6] = false;
-	IPPU.TileCached[TILE_2BIT_EVEN][address >> 4] = false;
-	IPPU.TileCached[TILE_2BIT_EVEN][((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = false;
-	IPPU.TileCached[TILE_2BIT_ODD] [address >> 4] = false;
-	IPPU.TileCached[TILE_2BIT_ODD] [((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = false;
-	IPPU.TileCached[TILE_4BIT_EVEN][address >> 5] = false;
-	IPPU.TileCached[TILE_4BIT_EVEN][((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = false;
-	IPPU.TileCached[TILE_4BIT_ODD] [address >> 5] = false;
-	IPPU.TileCached[TILE_4BIT_ODD] [((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = false;
-
 	if (!PPU.VMA.High)
 		PPU.VMA.Address += PPU.VMA.Increment;
 }
 
-static inline void REGISTER_2119_tile (uint8_t Byte)
-{
-	CHECK_INBLANK();
+inline void REGISTER_2119_tile(uint8_t Byte)
+{
+	if (CHECK_INBLANK())
+		return;
 
 	uint32_t rem = PPU.VMA.Address & PPU.VMA.Mask1;
 	uint32_t address = ((((PPU.VMA.Address & ~PPU.VMA.Mask1) + (rem >> PPU.VMA.Shift) + ((rem & (PPU.VMA.FullGraphicCount - 1)) << 3)) << 1) + 1) & 0xffff;
 
 	Memory.VRAM[address] = Byte;
 
-	IPPU.TileCached[TILE_2BIT][address >> 4] = false;
-	IPPU.TileCached[TILE_4BIT][address >> 5] = false;
-	IPPU.TileCached[TILE_8BIT][address >> 6] = false;
-	IPPU.TileCached[TILE_2BIT_EVEN][address >> 4] = false;
-	IPPU.TileCached[TILE_2BIT_EVEN][((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = false;
-	IPPU.TileCached[TILE_2BIT_ODD] [address >> 4] = false;
-	IPPU.TileCached[TILE_2BIT_ODD] [((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = false;
-	IPPU.TileCached[TILE_4BIT_EVEN][address >> 5] = false;
-	IPPU.TileCached[TILE_4BIT_EVEN][((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = false;
-	IPPU.TileCached[TILE_4BIT_ODD] [address >> 5] = false;
-	IPPU.TileCached[TILE_4BIT_ODD] [((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = false;
-
 	if (PPU.VMA.High)
 		PPU.VMA.Address += PPU.VMA.Increment;
 }
 
-static inline void REGISTER_2118_linear (uint8_t Byte)
-{
-	CHECK_INBLANK();
-
-	uint32_t	address;
+inline void REGISTER_2118_linear(uint8_t Byte)
+{
+	if (CHECK_INBLANK())
+		return;
+
+	uint32_t address;
 
 	Memory.VRAM[address = (PPU.VMA.Address << 1) & 0xffff] = Byte;
 
-	IPPU.TileCached[TILE_2BIT][address >> 4] = false;
-	IPPU.TileCached[TILE_4BIT][address >> 5] = false;
-	IPPU.TileCached[TILE_8BIT][address >> 6] = false;
-	IPPU.TileCached[TILE_2BIT_EVEN][address >> 4] = false;
-	IPPU.TileCached[TILE_2BIT_EVEN][((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = false;
-	IPPU.TileCached[TILE_2BIT_ODD] [address >> 4] = false;
-	IPPU.TileCached[TILE_2BIT_ODD] [((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = false;
-	IPPU.TileCached[TILE_4BIT_EVEN][address >> 5] = false;
-	IPPU.TileCached[TILE_4BIT_EVEN][((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = false;
-	IPPU.TileCached[TILE_4BIT_ODD] [address >> 5] = false;
-	IPPU.TileCached[TILE_4BIT_ODD] [((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = false;
-
 	if (!PPU.VMA.High)
 		PPU.VMA.Address += PPU.VMA.Increment;
 }
 
-static inline void REGISTER_2119_linear (uint8_t Byte)
-{
-	CHECK_INBLANK();
-
-	uint32_t	address;
+inline void REGISTER_2119_linear(uint8_t Byte)
+{
+	if (CHECK_INBLANK())
+		return;
+
+	uint32_t address;
 
 	Memory.VRAM[address = ((PPU.VMA.Address << 1) + 1) & 0xffff] = Byte;
 
-	IPPU.TileCached[TILE_2BIT][address >> 4] = false;
-	IPPU.TileCached[TILE_4BIT][address >> 5] = false;
-	IPPU.TileCached[TILE_8BIT][address >> 6] = false;
-	IPPU.TileCached[TILE_2BIT_EVEN][address >> 4] = false;
-	IPPU.TileCached[TILE_2BIT_EVEN][((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = false;
-	IPPU.TileCached[TILE_2BIT_ODD] [address >> 4] = false;
-	IPPU.TileCached[TILE_2BIT_ODD] [((address >> 4) - 1) & (MAX_2BIT_TILES - 1)] = false;
-	IPPU.TileCached[TILE_4BIT_EVEN][address >> 5] = false;
-	IPPU.TileCached[TILE_4BIT_EVEN][((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = false;
-	IPPU.TileCached[TILE_4BIT_ODD] [address >> 5] = false;
-	IPPU.TileCached[TILE_4BIT_ODD] [((address >> 5) - 1) & (MAX_4BIT_TILES - 1)] = false;
-
 	if (PPU.VMA.High)
 		PPU.VMA.Address += PPU.VMA.Increment;
 }
 
-/*static inline void REGISTER_2122 (uint8_t Byte)
-{
-	if (PPU.CGFLIP)
-	{
-		if ((Byte & 0x7f) != (PPU.CGDATA[PPU.CGADD] >> 8))
-		{
-			FLUSH_REDRAW();
-			PPU.CGDATA[PPU.CGADD] &= 0x00ff;
-			PPU.CGDATA[PPU.CGADD] |= (Byte & 0x7f) << 8;
-			IPPU.ColorsChanged = true;
-			IPPU.Blue[PPU.CGADD] = IPPU.XB[(Byte >> 2) & 0x1f];
-			IPPU.Green[PPU.CGADD] = IPPU.XB[(PPU.CGDATA[PPU.CGADD] >> 5) & 0x1f];
-			IPPU.ScreenColors[PPU.CGADD] = (uint16_t) BUILD_PIXEL(IPPU.Red[PPU.CGADD], IPPU.Green[PPU.CGADD], IPPU.Blue[PPU.CGADD]);
-		}
-
-		PPU.CGADD++;
-	}
-	else
-	{
-		if (Byte != (uint8_t) (PPU.CGDATA[PPU.CGADD] & 0xff))
-		{
-			FLUSH_REDRAW();
-			PPU.CGDATA[PPU.CGADD] &= 0x7f00;
-			PPU.CGDATA[PPU.CGADD] |= Byte;
-			IPPU.ColorsChanged = true;
-			IPPU.Red[PPU.CGADD] = IPPU.XB[Byte & 0x1f];
-			IPPU.Green[PPU.CGADD] = IPPU.XB[(PPU.CGDATA[PPU.CGADD] >> 5) & 0x1f];
-			IPPU.ScreenColors[PPU.CGADD] = (uint16_t) BUILD_PIXEL(IPPU.Red[PPU.CGADD], IPPU.Green[PPU.CGADD], IPPU.Blue[PPU.CGADD]);
-		}
-	}
-
-	PPU.CGFLIP ^= 1;
-}*/
-
-static inline void REGISTER_2180 (uint8_t Byte)
+inline void REGISTER_2180(uint8_t Byte)
 {
 	Memory.RAM[PPU.WRAM++] = Byte;
 	PPU.WRAM &= 0x1ffff;
 }
 
-static inline uint8_t REGISTER_4212()
-{
-	uint8_t	byte = 0;
-
-    if ((CPU.V_Counter >= PPU.ScreenHeight + FIRST_VISIBLE_LINE) && (CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE + 3))
+inline uint8_t REGISTER_4212()
+{
+	uint8_t byte = 0;
+
+	if (CPU.V_Counter >= PPU.ScreenHeight + FIRST_VISIBLE_LINE && CPU.V_Counter < PPU.ScreenHeight + FIRST_VISIBLE_LINE + 3)
 		byte = 1;
-	if ((CPU.Cycles < Timings.HBlankEnd) || (CPU.Cycles >= Timings.HBlankStart))
+	if (CPU.Cycles < Timings.HBlankEnd || CPU.Cycles >= Timings.HBlankStart)
 		byte |= 0x40;
-    if (CPU.V_Counter >= PPU.ScreenHeight + FIRST_VISIBLE_LINE)
+	if (CPU.V_Counter >= PPU.ScreenHeight + FIRST_VISIBLE_LINE)
 		byte |= 0x80;
 
-    return byte;
+	return byte;
 }
 
 #endif

--- a/src/in_snsf/snes9x/sdd1.cpp
+++ b/src/in_snsf/snes9x/sdd1.cpp
@@ -175,15 +175,15 @@
   Nintendo Co., Limited and its subsidiary companies.
  ***********************************************************************************/
 
+#include <algorithm>
 #include "snes9x.h"
 #include "memmap.h"
 #include "sdd1.h"
-//#include "display.h"
 
 void S9xSetSDD1MemoryMap(uint32_t bank, uint32_t value)
 {
 	bank = 0xc00 + bank * 0x100;
-	value = value * 1024 * 1024;
+	value *= 1024 * 1024;
 
 	for (int c = 0; c < 0x100; c += 16)
 	{
@@ -195,7 +195,7 @@
 
 void S9xResetSDD1()
 {
-	memset(&Memory.FillRAM[0x4800], 0, 4);
+	std::fill(&Memory.FillRAM[0x4800], &Memory.FillRAM[0x4804], 0);
 	for (int i = 0; i < 4; ++i)
 	{
 		Memory.FillRAM[0x4804 + i] = i;
@@ -203,9 +203,3 @@
 	}
 }
 
-/*void S9xSDD1PostLoadState()
-{
-	for (int i = 0; i < 4; ++i)
-		S9xSetSDD1MemoryMap(i, Memory.FillRAM[0x4804 + i]);
-}*/
-

--- a/src/in_snsf/snes9x/sdd1.h
+++ b/src/in_snsf/snes9x/sdd1.h
@@ -175,13 +175,11 @@
   Nintendo Co., Limited and its subsidiary companies.
  ***********************************************************************************/
 
-
 #ifndef _SDD1_H_
 #define _SDD1_H_
 
-void S9xSetSDD1MemoryMap (uint32_t, uint32_t);
+void S9xSetSDD1MemoryMap(uint32_t, uint32_t);
 void S9xResetSDD1();
-//void S9xSDD1PostLoadState();
 
 #endif
 

--- a/src/in_snsf/snes9x/snes9x.h
+++ b/src/in_snsf/snes9x/snes9x.h
@@ -175,296 +175,138 @@
   Nintendo Co., Limited and its subsidiary companies.
  ***********************************************************************************/
 
-
 #ifndef _SNES9X_H_
 #define _SNES9X_H_
 
 #ifndef VERSION
-#define VERSION	"1.53"
+#define VERSION "1.53"
 #endif
 
 #include "port.h"
-#include "65c816.h"
-//#include "messages.h"
-
-#ifdef ZLIB
-#include <zlib.h>
-#define STREAM					gzFile
-#define READ_STREAM(p, l, s)	gzread(s, p, l)
-#define WRITE_STREAM(p, l, s)	gzwrite(s, p, l)
-#define GETS_STREAM(p, l, s)	gzgets(s, p, l)
-#define GETC_STREAM(s)			gzgetc(s)
-#define OPEN_STREAM(f, m)		gzopen(f, m)
-#define REOPEN_STREAM(f, m)		gzdopen(f, m)
-#define FIND_STREAM(f)			gztell(f)
-#define REVERT_STREAM(f, o, s)	gzseek(f, o, s)
-#define CLOSE_STREAM(s)			gzclose(s)
-#else
-#define STREAM					FILE *
-#define READ_STREAM(p, l, s)	fread(p, 1, l, s)
-#define WRITE_STREAM(p, l, s)	fwrite(p, 1, l, s)
-#define GETS_STREAM(p, l, s)	fgets(p, l, s)
-#define GETC_STREAM(s)			fgetc(s)
-#define OPEN_STREAM(f, m)		fopen(f, m)
-#define REOPEN_STREAM(f, m)		fdopen(f, m)
-#define FIND_STREAM(f)			ftell(f)
-#define REVERT_STREAM(f, o, s)	fseek(f, o, s)
-#define CLOSE_STREAM(s)			fclose(s)
+
+const int SNES_WIDTH = 256;
+const int SNES_HEIGHT = 224;
+const uint16_t SNES_HEIGHT_EXTENDED = 239;
+
+const int32_t SNES_MAX_NTSC_VCOUNTER = 262;
+const int32_t SNES_MAX_PAL_VCOUNTER = 312;
+const int32_t SNES_HCOUNTER_MAX = 341;
+
+const int32_t ONE_CYCLE = 6;
+const int32_t SLOW_ONE_CYCLE = 8;
+const int32_t TWO_CYCLES = 12;
+const int32_t ONE_DOT_CYCLE = 4;
+
+const int32_t SNES_CYCLES_PER_SCANLINE = SNES_HCOUNTER_MAX * ONE_DOT_CYCLE;
+
+const int32_t SNES_WRAM_REFRESH_HC_v1 = 530;
+const int32_t SNES_WRAM_REFRESH_HC_v2 = 538;
+const int32_t SNES_WRAM_REFRESH_CYCLES = 40;
+
+const int32_t SNES_HBLANK_START_HC = 1096; // H=274
+const int32_t SNES_HDMA_START_HC = 1106; // FIXME: not true
+const int32_t SNES_HBLANK_END_HC = 4; // H=1
+const int32_t SNES_HDMA_INIT_HC = 20; // FIXME: not true
+const int32_t SNES_RENDER_START_HC = 48 * ONE_DOT_CYCLE; // FIXME: Snes9x renders a line at a time.
+
+const uint32_t DEBUG_MODE_FLAG = 1; // debugger
+const uint32_t TRACE_FLAG = 1 << 1; // debugger
+const uint32_t SCAN_KEYS_FLAG = 1 << 4; // CPU
+const uint32_t HALTED_FLAG = 1 << 12; // APU
+
+const size_t ROM_NAME_LEN = 23;
+
+struct SCPUState
+{
+	uint32_t Flags;
+	int32_t Cycles;
+	int32_t PrevCycles;
+	int32_t V_Counter;
+	uint8_t *PCBase;
+	bool NMILine;
+	bool IRQLine;
+	bool IRQTransition;
+	bool IRQLastState;
+	int32_t IRQPending;
+	int32_t MemSpeed;
+	int32_t MemSpeedx2;
+	int32_t FastROMSpeed;
+	bool InDMA;
+	bool InHDMA;
+	bool InDMAorHDMA;
+	bool InWRAMDMAorHDMA;
+	uint8_t HDMARanInDMA;
+	int32_t CurrentDMAorHDMAChannel;
+	uint8_t WhichEvent;
+	int32_t NextEvent;
+	bool WaitingForInterrupt;
+};
+
+enum
+{
+	HC_HBLANK_START_EVENT = 1,
+	HC_HDMA_START_EVENT = 2,
+	HC_HCOUNTER_MAX_EVENT = 3,
+	HC_HDMA_INIT_EVENT = 4,
+	HC_RENDER_EVENT = 5,
+	HC_WRAM_REFRESH_EVENT = 6
+};
+
+struct STimings
+{
+	int32_t H_Max_Master;
+	int32_t H_Max;
+	int32_t V_Max_Master;
+	int32_t V_Max;
+	int32_t HBlankStart;
+	int32_t HBlankEnd;
+	int32_t HDMAInit;
+	int32_t HDMAStart;
+	int32_t NMITriggerPos;
+	int32_t IRQTriggerCycles;
+	int32_t WRAMRefreshPos;
+	int32_t RenderPos;
+	bool InterlaceField;
+	int32_t DMACPUSync; // The cycles to synchronize DMA and CPU. Snes9x cannot emulate correctly.
+	int32_t NMIDMADelay; // The delay of NMI trigger after DMA transfers. Snes9x cannot emulate correctly.
+	int32_t IRQPendCount; // This value is just a hack.
+	int32_t APUSpeedup;
+	bool APUAllowTimeOverflow;
+};
+
+struct SSettings
+{
+	bool SDD1;
+
+	bool ForceNotInterleaved;
+	bool PAL;
+
+	bool SoundSync;
+	bool SixteenBitSound;
+	uint32_t SoundPlaybackRate;
+	uint32_t SoundInputRate;
+	bool Stereo;
+	bool ReverseStereo;
+	bool Mute;
+
+	bool DisableGameSpecificHacks;
+	bool BlockInvalidVRAMAccessMaster;
+	bool BlockInvalidVRAMAccess;
+	int32_t HDMATimingHack;
+
+	bool TurboMode;
+};
+
+struct SSNESGameFixes
+{
+	uint8_t SRAMInitialValue;
+	bool Uniracers;
+};
+
+extern SSettings Settings;
+extern SCPUState CPU;
+extern STimings Timings;
+extern SSNESGameFixes SNESGameFixes;
+
 #endif
 
-#define SNES_WIDTH					256
-#define SNES_HEIGHT					224
-#define SNES_HEIGHT_EXTENDED		239
-#define MAX_SNES_WIDTH				(SNES_WIDTH * 2)
-#define MAX_SNES_HEIGHT				(SNES_HEIGHT_EXTENDED * 2)
-#define IMAGE_WIDTH					(Settings.SupportHiRes ? MAX_SNES_WIDTH : SNES_WIDTH)
-#define IMAGE_HEIGHT				(Settings.SupportHiRes ? MAX_SNES_HEIGHT : SNES_HEIGHT_EXTENDED)
-
-#define	NTSC_MASTER_CLOCK			21477272.0
-#define	PAL_MASTER_CLOCK			21281370.0
-
-#define SNES_MAX_NTSC_VCOUNTER		262
-#define SNES_MAX_PAL_VCOUNTER		312
-#define SNES_HCOUNTER_MAX			341
-
-#define ONE_CYCLE					6
-#define SLOW_ONE_CYCLE				8
-#define TWO_CYCLES					12
-#define	ONE_DOT_CYCLE				4
-
-#define SNES_CYCLES_PER_SCANLINE	(SNES_HCOUNTER_MAX * ONE_DOT_CYCLE)
-#define SNES_SCANLINE_TIME			(SNES_CYCLES_PER_SCANLINE / NTSC_MASTER_CLOCK)
-
-#define SNES_WRAM_REFRESH_HC_v1		530
-#define SNES_WRAM_REFRESH_HC_v2		538
-#define SNES_WRAM_REFRESH_CYCLES	40
-
-#define SNES_HBLANK_START_HC		1096					// H=274
-#define	SNES_HDMA_START_HC			1106					// FIXME: not true
-#define	SNES_HBLANK_END_HC			4						// H=1
-#define	SNES_HDMA_INIT_HC			20						// FIXME: not true
-#define	SNES_RENDER_START_HC		(48 * ONE_DOT_CYCLE)	// FIXME: Snes9x renders a line at a time.
-
-#define SNES_TR_MASK		(1 <<  4)
-#define SNES_TL_MASK		(1 <<  5)
-#define SNES_X_MASK			(1 <<  6)
-#define SNES_A_MASK			(1 <<  7)
-#define SNES_RIGHT_MASK		(1 <<  8)
-#define SNES_LEFT_MASK		(1 <<  9)
-#define SNES_DOWN_MASK		(1 << 10)
-#define SNES_UP_MASK		(1 << 11)
-#define SNES_START_MASK		(1 << 12)
-#define SNES_SELECT_MASK	(1 << 13)
-#define SNES_Y_MASK			(1 << 14)
-#define SNES_B_MASK			(1 << 15)
-
-#define DEBUG_MODE_FLAG		(1 <<  0)	// debugger
-#define TRACE_FLAG			(1 <<  1)	// debugger
-#define SINGLE_STEP_FLAG	(1 <<  2)	// debugger
-#define BREAK_FLAG			(1 <<  3)	// debugger
-#define SCAN_KEYS_FLAG		(1 <<  4)	// CPU
-#define HALTED_FLAG			(1 << 12)	// APU
-#define FRAME_ADVANCE_FLAG	(1 <<  9)
-
-#define ROM_NAME_LEN	23
-#define AUTO_FRAMERATE	200
-
-struct SCPUState
-{
-	uint32_t	Flags;
-	int32_t	Cycles;
-	int32_t	PrevCycles;
-	int32_t	V_Counter;
-	uint8_t	*PCBase;
-	bool	NMILine;
-	bool	IRQLine;
-	bool	IRQTransition;
-	bool	IRQLastState;
-	bool	IRQExternal;
-	int32_t	IRQPending;
-	int32_t	MemSpeed;
-	int32_t	MemSpeedx2;
-	int32_t	FastROMSpeed;
-	bool	InDMA;
-	bool	InHDMA;
-	bool	InDMAorHDMA;
-	bool	InWRAMDMAorHDMA;
-	uint8_t	HDMARanInDMA;
-	int32_t	CurrentDMAorHDMAChannel;
-	uint8_t	WhichEvent;
-	int32_t	NextEvent;
-	bool	WaitingForInterrupt;
-	uint32_t	AutoSaveTimer;
-	bool	SRAMModified;
-};
-
-enum
-{
-	HC_HBLANK_START_EVENT = 1,
-	HC_HDMA_START_EVENT   = 2,
-	HC_HCOUNTER_MAX_EVENT = 3,
-	HC_HDMA_INIT_EVENT    = 4,
-	HC_RENDER_EVENT       = 5,
-	HC_WRAM_REFRESH_EVENT = 6
-};
-
-struct STimings
-{
-	int32_t	H_Max_Master;
-	int32_t	H_Max;
-	int32_t	V_Max_Master;
-	int32_t	V_Max;
-	int32_t	HBlankStart;
-	int32_t	HBlankEnd;
-	int32_t	HDMAInit;
-	int32_t	HDMAStart;
-	int32_t	NMITriggerPos;
-	int32_t	IRQTriggerCycles;
-	int32_t	WRAMRefreshPos;
-	int32_t	RenderPos;
-	bool	InterlaceField;
-	int32_t	DMACPUSync;		// The cycles to synchronize DMA and CPU. Snes9x cannot emulate correctly.
-	int32_t	NMIDMADelay;	// The delay of NMI trigger after DMA transfers. Snes9x cannot emulate correctly.
-	int32_t	IRQPendCount;	// This value is just a hack.
-	int32_t	APUSpeedup;
-	bool	APUAllowTimeOverflow;
-};
-
-struct SSettings
-{
-	bool	TraceDMA;
-	bool	TraceHDMA;
-	bool	TraceVRAM;
-	bool	TraceUnknownRegisters;
-	bool	TraceDSP;
-	bool	TraceHCEvent;
-
-	bool	SuperFX;
-	uint8_t	DSP;
-	bool	SA1;
-	bool	C4;
-	bool	SDD1;
-	bool	SPC7110;
-	bool	SPC7110RTC;
-	bool	OBC1;
-	uint8_t	SETA;
-	bool	SRTC;
-	bool	BS;
-	bool	BSXItself;
-	bool	BSXBootup;
-	bool	MouseMaster;
-	bool	SuperScopeMaster;
-	bool	JustifierMaster;
-	bool	MultiPlayer5Master;
-
-	bool	ForceLoROM;
-	bool	ForceHiROM;
-	bool	ForceHeader;
-	bool	ForceNoHeader;
-	bool	ForceInterleaved;
-	bool	ForceInterleaved2;
-	bool	ForceInterleaveGD24;
-	bool	ForceNotInterleaved;
-	bool	ForcePAL;
-	bool	ForceNTSC;
-	bool	PAL;
-	uint32_t	FrameTimePAL;
-	uint32_t	FrameTimeNTSC;
-	uint32_t	FrameTime;
-
-	bool	SoundSync;
-	bool	SixteenBitSound;
-	uint32_t	SoundPlaybackRate;
-	uint32_t	SoundInputRate;
-	bool	Stereo;
-	bool	ReverseStereo;
-	bool	Mute;
-
-	bool	SupportHiRes;
-	bool	Transparency;
-	uint8_t	BG_Forced;
-	bool	DisableGraphicWindows;
-
-	bool	DisplayFrameRate;
-	bool	DisplayWatchedAddresses;
-	bool	DisplayPressedKeys;
-	bool	DisplayMovieFrame;
-	bool	AutoDisplayMessages;
-	uint32_t	InitialInfoStringTimeout;
-	uint16_t	DisplayColor;
-
-	bool	Multi;
-	char	CartAName[PATH_MAX + 1];
-	char	CartBName[PATH_MAX + 1];
-
-	bool	DisableGameSpecificHacks;
-	bool	BlockInvalidVRAMAccessMaster;
-	bool	BlockInvalidVRAMAccess;
-	int32_t	HDMATimingHack;
-
-	bool	ForcedPause;
-	bool	Paused;
-	bool	StopEmulation;
-
-	uint32_t	SkipFrames;
-	uint32_t	TurboSkipFrames;
-	uint32_t	AutoMaxSkipFrames;
-	bool	TurboMode;
-	uint32_t	HighSpeedSeek;
-	bool	FrameAdvance;
-
-	bool	NetPlay;
-	bool	NetPlayServer;
-	char	ServerName[128];
-	int		Port;
-
-	bool	MovieTruncate;
-	bool	MovieNotifyIgnored;
-	bool	WrongMovieStateProtection;
-	bool	DumpStreams;
-	int		DumpStreamsMaxFrames;
-
-	bool	TakeScreenshot;
-	int8_t	StretchScreenshots;
-	bool	SnapshotScreenshots;
-
-	bool	ApplyCheats;
-	bool	NoPatch;
-	int32_t	AutoSaveDelay;
-	bool	DontSaveOopsSnapshot;
-	bool	UpAndDown;
-
-	bool	OpenGLEnable;
-};
-
-struct SSNESGameFixes
-{
-	uint8_t	SRAMInitialValue;
-	uint8_t	Uniracers;
-};
-
-enum
-{
-	PAUSE_NETPLAY_CONNECT		= (1 << 0),
-	PAUSE_TOGGLE_FULL_SCREEN	= (1 << 1),
-	PAUSE_EXIT					= (1 << 2),
-	PAUSE_MENU					= (1 << 3),
-	PAUSE_INACTIVE_WINDOW		= (1 << 4),
-	PAUSE_WINDOW_ICONISED		= (1 << 5),
-	PAUSE_RESTORE_GUI			= (1 << 6),
-	PAUSE_FREEZE_FILE			= (1 << 7)
-};
-
-void S9xSetPause(uint32_t);
-void S9xClearPause(uint32_t);
-void S9xExi();
-void S9xMessage(int, int, const char *);
-
-extern struct SSettings			Settings;
-extern struct SCPUState			CPU;
-extern struct STimings			Timings;
-extern struct SSNESGameFixes	SNESGameFixes;
-//extern char						String[513];
-
-#endif
-