diff --git a/AppleWinExpress2013.sln b/AppleWinExpress2013.sln
index e4ea32bb..10dc5eb9 100644
--- a/AppleWinExpress2013.sln
+++ b/AppleWinExpress2013.sln
@@ -1,8 +1,12 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Express 2012 for Windows Desktop
+# Visual Studio 2013
+VisualStudioVersion = 12.0.31101.0
+MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AppleWin", "AppleWinExpress2013.vcxproj", "{0A960136-A00A-4D4B-805F-664D9950D2CA}"
ProjectSection(ProjectDependencies) = postProject
+ {CF5A49BF-62A5-41BB-B10C-F34D556A7A45} = {CF5A49BF-62A5-41BB-B10C-F34D556A7A45}
+ {0212E0DF-06DA-4080-BD1D-F3B01599F70F} = {0212E0DF-06DA-4080-BD1D-F3B01599F70F}
{509739E7-0AF3-4C09-A1A9-F0B1BC31B39D} = {509739E7-0AF3-4C09-A1A9-F0B1BC31B39D}
{9B32A6E7-1237-4F36-8903-A3FD51DF9C4E} = {9B32A6E7-1237-4F36-8903-A3FD51DF9C4E}
EndProjectSection
@@ -11,6 +15,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zip_lib", "zip_lib\zip_lib2
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "zlib\zlib-Express2013.vcxproj", "{9B32A6E7-1237-4F36-8903-A3FD51DF9C4E}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "yaml", "libyaml\win32\yaml2013.vcxproj", "{0212E0DF-06DA-4080-BD1D-F3B01599F70F}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestCPU6502", "test\TestCPU6502\TestCPU6502-vs2013.vcxproj", "{CF5A49BF-62A5-41BB-B10C-F34D556A7A45}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug NoDX|Win32 = Debug NoDX|Win32
@@ -43,6 +51,22 @@ Global
{9B32A6E7-1237-4F36-8903-A3FD51DF9C4E}.Release NoDX|Win32.Build.0 = Release|Win32
{9B32A6E7-1237-4F36-8903-A3FD51DF9C4E}.Release|Win32.ActiveCfg = Release|Win32
{9B32A6E7-1237-4F36-8903-A3FD51DF9C4E}.Release|Win32.Build.0 = Release|Win32
+ {0212E0DF-06DA-4080-BD1D-F3B01599F70F}.Debug NoDX|Win32.ActiveCfg = Debug|Win32
+ {0212E0DF-06DA-4080-BD1D-F3B01599F70F}.Debug NoDX|Win32.Build.0 = Debug|Win32
+ {0212E0DF-06DA-4080-BD1D-F3B01599F70F}.Debug|Win32.ActiveCfg = Debug|Win32
+ {0212E0DF-06DA-4080-BD1D-F3B01599F70F}.Debug|Win32.Build.0 = Debug|Win32
+ {0212E0DF-06DA-4080-BD1D-F3B01599F70F}.Release NoDX|Win32.ActiveCfg = Release|Win32
+ {0212E0DF-06DA-4080-BD1D-F3B01599F70F}.Release NoDX|Win32.Build.0 = Release|Win32
+ {0212E0DF-06DA-4080-BD1D-F3B01599F70F}.Release|Win32.ActiveCfg = Release|Win32
+ {0212E0DF-06DA-4080-BD1D-F3B01599F70F}.Release|Win32.Build.0 = Release|Win32
+ {CF5A49BF-62A5-41BB-B10C-F34D556A7A45}.Debug NoDX|Win32.ActiveCfg = Debug|Win32
+ {CF5A49BF-62A5-41BB-B10C-F34D556A7A45}.Debug NoDX|Win32.Build.0 = Debug|Win32
+ {CF5A49BF-62A5-41BB-B10C-F34D556A7A45}.Debug|Win32.ActiveCfg = Debug|Win32
+ {CF5A49BF-62A5-41BB-B10C-F34D556A7A45}.Debug|Win32.Build.0 = Debug|Win32
+ {CF5A49BF-62A5-41BB-B10C-F34D556A7A45}.Release NoDX|Win32.ActiveCfg = Release|Win32
+ {CF5A49BF-62A5-41BB-B10C-F34D556A7A45}.Release NoDX|Win32.Build.0 = Release|Win32
+ {CF5A49BF-62A5-41BB-B10C-F34D556A7A45}.Release|Win32.ActiveCfg = Release|Win32
+ {CF5A49BF-62A5-41BB-B10C-F34D556A7A45}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/ApplewinExpress9.00.sln b/ApplewinExpress9.00.sln
index 6fbec8fe..475784bc 100644
--- a/ApplewinExpress9.00.sln
+++ b/ApplewinExpress9.00.sln
@@ -1,9 +1,11 @@
Microsoft Visual Studio Solution File, Format Version 10.00
-# Visual C++ Express 2008
+# Visual Studio 2008
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Applewin", "ApplewinExpress9.00.vcproj", "{1DA0C491-B5F4-4EC8-B1D2-CF6BE635DADC}"
ProjectSection(ProjectDependencies) = postProject
+ {5CE8051A-3F0C-4C39-B1C0-3338E48BA60F} = {5CE8051A-3F0C-4C39-B1C0-3338E48BA60F}
{7935B998-C713-42AE-8F6D-9FF9080A1B1B} = {7935B998-C713-42AE-8F6D-9FF9080A1B1B}
+ {2CC8CA9F-E37E-41A4-BFAD-77E54EB783A2} = {2CC8CA9F-E37E-41A4-BFAD-77E54EB783A2}
{709278B8-C583-4BD8-90DE-4E4F35A3BD8B} = {709278B8-C583-4BD8-90DE-4E4F35A3BD8B}
EndProjectSection
EndProject
@@ -11,6 +13,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "zlib\zlib-Express9.
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zip_lib", "zip_lib\zip_lib.vcproj", "{709278B8-C583-4BD8-90DE-4E4F35A3BD8B}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestCPU6502", "test\TestCPU6502\TestCPU6502.vcproj", "{2CC8CA9F-E37E-41A4-BFAD-77E54EB783A2}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "yaml", "libyaml\win32\yaml2008.vcproj", "{5CE8051A-3F0C-4C39-B1C0-3338E48BA60F}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
@@ -29,6 +35,14 @@ Global
{709278B8-C583-4BD8-90DE-4E4F35A3BD8B}.Debug|Win32.Build.0 = Debug|Win32
{709278B8-C583-4BD8-90DE-4E4F35A3BD8B}.Release|Win32.ActiveCfg = Release|Win32
{709278B8-C583-4BD8-90DE-4E4F35A3BD8B}.Release|Win32.Build.0 = Release|Win32
+ {2CC8CA9F-E37E-41A4-BFAD-77E54EB783A2}.Debug|Win32.ActiveCfg = Debug|Win32
+ {2CC8CA9F-E37E-41A4-BFAD-77E54EB783A2}.Debug|Win32.Build.0 = Debug|Win32
+ {2CC8CA9F-E37E-41A4-BFAD-77E54EB783A2}.Release|Win32.ActiveCfg = Release|Win32
+ {2CC8CA9F-E37E-41A4-BFAD-77E54EB783A2}.Release|Win32.Build.0 = Release|Win32
+ {5CE8051A-3F0C-4C39-B1C0-3338E48BA60F}.Debug|Win32.ActiveCfg = Debug|Win32
+ {5CE8051A-3F0C-4C39-B1C0-3338E48BA60F}.Debug|Win32.Build.0 = Debug|Win32
+ {5CE8051A-3F0C-4C39-B1C0-3338E48BA60F}.Release|Win32.ActiveCfg = Release|Win32
+ {5CE8051A-3F0C-4C39-B1C0-3338E48BA60F}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/test/TestCPU6502/TestCPU6502-vs2013.vcxproj b/test/TestCPU6502/TestCPU6502-vs2013.vcxproj
new file mode 100644
index 00000000..3e2fbeb3
--- /dev/null
+++ b/test/TestCPU6502/TestCPU6502-vs2013.vcxproj
@@ -0,0 +1,89 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+
+
+
+
+
+
+
+
+ {CF5A49BF-62A5-41BB-B10C-F34D556A7A45}
+ Win32Proj
+ TestCPU6502vs2013
+ TestCPU6502
+
+
+
+ Application
+ true
+ v120
+ Unicode
+
+
+ Application
+ false
+ v120
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+ false
+
+
+
+
+
+ Level3
+ Disabled
+ WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
+
+
+ Console
+ true
+
+
+
+
+ Level3
+
+
+ MaxSpeed
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)
+
+
+ Console
+ true
+ true
+ true
+
+
+
+
+
+
\ No newline at end of file
diff --git a/test/TestCPU6502/TestCPU6502-vs2013.vcxproj.filters b/test/TestCPU6502/TestCPU6502-vs2013.vcxproj.filters
new file mode 100644
index 00000000..71e4100b
--- /dev/null
+++ b/test/TestCPU6502/TestCPU6502-vs2013.vcxproj.filters
@@ -0,0 +1,22 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
+ Source Files
+
+
+
\ No newline at end of file
diff --git a/test/TestCPU6502/TestCPU6502.cpp b/test/TestCPU6502/TestCPU6502.cpp
new file mode 100644
index 00000000..df50fe55
--- /dev/null
+++ b/test/TestCPU6502/TestCPU6502.cpp
@@ -0,0 +1,1127 @@
+#include "stdafx.h"
+
+#include "../../source/Applewin.h"
+#include "../../source/CPU.h"
+
+// From Applewin.cpp
+enum AppMode_e g_nAppMode = MODE_RUNNING;
+
+// From Memory.cpp
+LPBYTE memwrite[0x100]; // TODO: Init
+LPBYTE mem = NULL; // TODO: Init
+LPBYTE memdirty = NULL; // TODO: Init
+iofunction IORead[256] = {0}; // TODO: Init
+iofunction IOWrite[256] = {0}; // TODO: Init
+
+// From Debugger_Types.h
+ enum AddressingMode_e // ADDRESSING_MODES_e
+ {
+ AM_IMPLIED // Note: SetDebugBreakOnInvalid() assumes this order of first 4 entries
+ , AM_1 // Invalid 1 Byte
+ , AM_2 // Invalid 2 Bytes
+ , AM_3 // Invalid 3 Bytes
+ };
+
+// From CPU.cpp
+#define AF_SIGN 0x80
+#define AF_OVERFLOW 0x40
+#define AF_RESERVED 0x20
+#define AF_BREAK 0x10
+#define AF_DECIMAL 0x08
+#define AF_INTERRUPT 0x04
+#define AF_ZERO 0x02
+#define AF_CARRY 0x01
+
+regsrec regs;
+
+static const int IRQ_CHECK_TIMEOUT = 128;
+static signed int g_nIrqCheckTimeout = IRQ_CHECK_TIMEOUT;
+
+static eCpuType g_ActiveCPU = CPU_65C02;
+
+eCpuType GetActiveCpu(void)
+{
+ return g_ActiveCPU;
+}
+
+static __forceinline int Fetch(BYTE& iOpcode, ULONG uExecutedCycles)
+{
+ iOpcode = *(mem+regs.pc);
+ regs.pc++;
+ return 1;
+}
+
+#define INV IsDebugBreakOnInvalid(AM_1);
+inline int IsDebugBreakOnInvalid( int iOpcodeType )
+{
+ return 0;
+}
+
+static __forceinline void DoIrqProfiling(DWORD uCycles)
+{
+}
+
+static __forceinline void CheckInterruptSources(ULONG uExecutedCycles)
+{
+}
+
+static __forceinline void NMI(ULONG& uExecutedCycles, UINT& uExtraCycles, BOOL& flagc, BOOL& flagn, BOOL& flagv, BOOL& flagz)
+{
+}
+
+static __forceinline void IRQ(ULONG& uExecutedCycles, UINT& uExtraCycles, BOOL& flagc, BOOL& flagn, BOOL& flagv, BOOL& flagz)
+{
+}
+
+void RequestDebugger()
+{
+}
+
+// From Debug.h
+inline int IsDebugBreakpointHit()
+{
+ return 0;
+}
+
+// From Debug.cpp
+int g_bDebugBreakpointHit = 0;
+
+// From z80.cpp
+DWORD z80_mainloop(ULONG uTotalCycles, ULONG uExecutedCycles)
+{
+ return 0;
+}
+
+// From NTSC.cpp
+void NTSC_VideoUpdateCycles( long cycles6502 )
+{
+}
+
+//-------------------------------------
+
+#include "../../source/cpu/cpu_general.inl"
+#include "../../source/cpu/cpu_instructions.inl"
+#include "../../source/cpu/cpu6502.h" // MOS 6502
+#include "../../source/cpu/cpu65C02.h" // WDC 65C02
+
+void init(void)
+{
+ mem = (LPBYTE)VirtualAlloc(NULL,64*1024,MEM_COMMIT,PAGE_READWRITE);
+
+ for (UINT i=0; i<256; i++)
+ memwrite[i] = mem+i*256;
+
+ memdirty = new BYTE[256];
+}
+
+void reset(void)
+{
+ regs.a = 0;
+ regs.x = 0;
+ regs.y = 0;
+ regs.pc = 0x300;
+ regs.sp = 0x1FF;
+ regs.ps = 0;
+ regs.bJammed = 0;
+}
+
+//-------------------------------------
+
+int GH264_test(void)
+{
+ // No page-cross
+ reset();
+ regs.pc = 0x300;
+ WORD abs = regs.pc+3;
+ WORD dst = abs+2;
+ mem[regs.pc+0] = 0x6c; // JMP (IND)
+ mem[regs.pc+1] = abs&0xff;
+ mem[regs.pc+2] = abs>>8;
+ mem[regs.pc+3] = dst&0xff;
+ mem[regs.pc+4] = dst>>8;
+
+ DWORD cycles = Cpu6502(0);
+ if (cycles != 5) return 1;
+ if (regs.pc != dst) return 1;
+
+ reset();
+ cycles = Cpu65C02(0);
+ if (cycles != 6) return 1;
+ if (regs.pc != dst) return 1;
+
+ // Page-cross
+ reset();
+ regs.pc = 0x3fc; // 3FC: JMP (abs)
+ abs = regs.pc+3; // 3FF: lo(dst), hi(dst)
+ dst = abs+2;
+ mem[regs.pc+0] = 0x6c; // JMP (IND)
+ mem[regs.pc+1] = abs&0xff;
+ mem[regs.pc+2] = abs>>8;
+ mem[regs.pc+3] = dst&0xff;
+ mem[regs.pc+4] = mem[regs.pc & ~0xff] = dst>>8; // Allow for bug in 6502
+
+ cycles = Cpu6502(0);
+ if (cycles != 5) return 1;
+ if (regs.pc != dst) return 1;
+
+ reset();
+ regs.pc = 0x3fc;
+ mem[regs.pc & ~0xff] = 0; // Test that 65C02 fixes the bug in the 6502
+ cycles = Cpu65C02(0);
+ if (cycles != 7) return 1; // todo: is this 6 or 7?
+ if (regs.pc != dst) return 1;
+
+ return 0;
+}
+
+//-------------------------------------
+
+void ASL_ABSX(BYTE x, WORD base, BYTE d)
+{
+ WORD addr = base+x;
+ mem[addr] = d;
+
+ reset();
+ regs.x = x;
+ mem[regs.pc+0] = 0x1e;
+ mem[regs.pc+1] = base&0xff;
+ mem[regs.pc+2] = base>>8;
+}
+
+void DEC_ABSX(BYTE x, WORD base, BYTE d)
+{
+ WORD addr = base+x;
+ mem[addr] = d;
+
+ reset();
+ regs.x = x;
+ mem[regs.pc+0] = 0xde;
+ mem[regs.pc+1] = base&0xff;
+ mem[regs.pc+2] = base>>8;
+}
+
+void INC_ABSX(BYTE x, WORD base, BYTE d)
+{
+ WORD addr = base+x;
+ mem[addr] = d;
+
+ reset();
+ regs.x = x;
+ mem[regs.pc+0] = 0xfe;
+ mem[regs.pc+1] = base&0xff;
+ mem[regs.pc+2] = base>>8;
+}
+
+int GH271_test(void)
+{
+ // asl abs,x
+ {
+ const WORD base = 0x20ff;
+ const BYTE d = 0x40;
+
+ // no page-cross
+ {
+ const BYTE x = 0;
+
+ ASL_ABSX(x, base, d);
+ if (Cpu6502(0) != 7) return 1;
+ if (mem[base+x] != ((d<<1)&0xff)) return 1;
+
+ ASL_ABSX(x, base, d);
+ if (Cpu65C02(0) != 6) return 1; // Non-PX case is optimised on 65C02
+ if (mem[base+x] != ((d<<1)&0xff)) return 1;
+ }
+
+ // page-cross
+ {
+ const BYTE x = 1;
+
+ ASL_ABSX(x, base, d);
+ if (Cpu6502(0) != 7) return 1;
+ if (mem[base+x] != ((d<<1)&0xff)) return 1;
+
+ ASL_ABSX(x, base, d);
+ if (Cpu65C02(0) != 7) return 1;
+ if (mem[base+x] != ((d<<1)&0xff)) return 1;
+ }
+ }
+
+ // dec abs,x
+ {
+ const WORD base = 0x20ff;
+ const BYTE d = 0x40;
+
+ // no page-cross
+ {
+ const BYTE x = 0;
+
+ DEC_ABSX(x, base, d);
+ if (Cpu6502(0) != 7) return 1;
+ if (mem[base+x] != ((d-1)&0xff)) return 1;
+
+ DEC_ABSX(x, base, d);
+ if (Cpu65C02(0) != 7) return 1; // NB. Not optimised for 65C02
+ if (mem[base+x] != ((d-1)&0xff)) return 1;
+ }
+
+ // page-cross
+ {
+ const BYTE x = 1;
+
+ DEC_ABSX(x, base, d);
+ if (Cpu6502(0) != 7) return 1;
+ if (mem[base+x] != ((d-1)&0xff)) return 1;
+
+ DEC_ABSX(x, base, d);
+ if (Cpu65C02(0) != 7) return 1;
+ if (mem[base+x] != ((d-1)&0xff)) return 1;
+ }
+ }
+
+ // inc abs,x
+ {
+ const WORD base = 0x20ff;
+ const BYTE d = 0x40;
+
+ // no page-cross
+ {
+ const BYTE x = 0;
+
+ INC_ABSX(x, base, d);
+ if (Cpu6502(0) != 7) return 1;
+ if (mem[base+x] != ((d+1)&0xff)) return 1;
+
+ INC_ABSX(x, base, d);
+ if (Cpu65C02(0) != 7) return 1; // NB. Not optimised for 65C02
+ if (mem[base+x] != ((d+1)&0xff)) return 1;
+ }
+
+ // page-cross
+ {
+ const BYTE x = 1;
+
+ INC_ABSX(x, base, d);
+ if (Cpu6502(0) != 7) return 1;
+ if (mem[base+x] != ((d+1)&0xff)) return 1;
+
+ INC_ABSX(x, base, d);
+ if (Cpu65C02(0) != 7) return 1;
+ if (mem[base+x] != ((d+1)&0xff)) return 1;
+ }
+ }
+
+ return 0;
+}
+
+//-------------------------------------
+
+enum {CYC_6502=0, CYC_6502_PX, CYC_65C02, CYC_65C02_PX};
+
+const BYTE g_OpcodeTimings[256][4] =
+{
+// 6502 (no page-cross), 6502 (page-cross), 65C02 (no page-cross), 65C02 (page-cross)
+ {7,7,7,7}, // 00
+ {6,6,6,6}, // 01
+ {2,2,2,2}, // 02
+ {8,8,1,1}, // 03
+ {3,3,5,5}, // 04
+ {3,3,3,3}, // 05
+ {5,5,5,5}, // 06
+ {5,5,1,1}, // 07
+ {3,3,3,3}, // 08
+ {2,2,2,2}, // 09
+ {2,2,2,2}, // 0A
+ {2,2,1,1}, // 0B
+ {4,5,6,6}, // 0C
+ {4,4,4,4}, // 0D
+ {6,6,6,6}, // 0E
+ {6,6,1,1}, // 0F
+ {3,3,3,3}, // 10
+ {5,6,5,6}, // 11
+ {2,2,5,5}, // 12
+ {8,8,1,1}, // 13
+ {4,4,5,5}, // 14
+ {4,4,4,4}, // 15
+ {6,6,6,6}, // 16
+ {6,6,1,1}, // 17
+ {2,2,2,2}, // 18
+ {4,5,4,5}, // 19
+ {2,2,2,2}, // 1A
+ {7,7,1,1}, // 1B
+ {4,5,6,6}, // 1C
+ {4,5,4,5}, // 1D
+ {7,7,6,7}, // 1E
+ {7,7,1,1}, // 1F
+ {6,6,6,6}, // 20
+ {6,6,6,6}, // 21
+ {2,2,2,2}, // 22
+ {8,8,1,1}, // 23
+ {3,3,3,3}, // 24
+ {3,3,3,3}, // 25
+ {5,5,5,5}, // 26
+ {5,5,1,1}, // 27
+ {4,4,4,4}, // 28
+ {2,2,2,2}, // 29
+ {2,2,2,2}, // 2A
+ {2,2,1,1}, // 2B
+ {4,4,4,4}, // 2C
+ {4,4,4,4}, // 2D
+ {6,6,6,6}, // 2E
+ {6,6,1,1}, // 2F
+ {2,2,2,2}, // 30
+ {5,6,5,6}, // 31
+ {2,2,5,5}, // 32
+ {8,8,1,1}, // 33
+ {4,4,4,4}, // 34
+ {4,4,4,4}, // 35
+ {6,6,6,6}, // 36
+ {6,6,1,1}, // 37
+ {2,2,2,2}, // 38
+ {4,5,4,5}, // 39
+ {2,2,2,2}, // 3A
+ {7,7,1,1}, // 3B
+ {4,5,4,5}, // 3C
+ {4,5,4,5}, // 3D
+ {6,6,6,7}, // 3E
+ {7,7,1,1}, // 3F
+ {6,6,6,6}, // 40
+ {6,6,6,6}, // 41
+ {2,2,2,2}, // 42
+ {8,8,1,1}, // 43
+ {3,3,3,3}, // 44
+ {3,3,3,3}, // 45
+ {5,5,5,5}, // 46
+ {5,5,1,1}, // 47
+ {3,3,3,3}, // 48
+ {2,2,2,2}, // 49
+ {2,2,2,2}, // 4A
+ {2,2,1,1}, // 4B
+ {3,3,3,3}, // 4C
+ {4,4,4,4}, // 4D
+ {6,6,6,6}, // 4E
+ {6,6,1,1}, // 4F
+ {3,3,3,3}, // 50
+ {5,6,5,6}, // 51
+ {2,2,5,5}, // 52
+ {8,8,1,1}, // 53
+ {4,4,4,4}, // 54
+ {4,4,4,4}, // 55
+ {6,6,6,6}, // 56
+ {6,6,1,1}, // 57
+ {2,2,2,2}, // 58
+ {4,5,4,5}, // 59
+ {2,2,3,3}, // 5A
+ {7,7,1,1}, // 5B
+ {4,5,8,8}, // 5C
+ {4,5,4,5}, // 5D
+ {6,6,6,7}, // 5E
+ {7,7,1,1}, // 5F
+ {6,6,6,6}, // 60
+ {6,6,6,6}, // 61
+ {2,2,2,2}, // 62
+ {8,8,1,1}, // 63
+ {3,3,3,3}, // 64
+ {3,3,3,3}, // 65
+ {5,5,5,5}, // 66
+ {5,5,1,1}, // 67
+ {4,4,4,4}, // 68
+ {2,2,2,2}, // 69
+ {2,2,2,2}, // 6A
+ {2,2,1,1}, // 6B
+ {5,5,7,7}, // 6C
+ {4,4,4,4}, // 6D
+ {6,6,6,6}, // 6E
+ {6,6,1,1}, // 6F
+ {2,2,2,2}, // 70
+ {5,6,5,6}, // 71
+ {2,2,5,5}, // 72
+ {8,8,1,1}, // 73
+ {4,4,4,4}, // 74
+ {4,4,4,4}, // 75
+ {6,6,6,6}, // 76
+ {6,6,1,1}, // 77
+ {2,2,2,2}, // 78
+ {4,5,4,5}, // 79
+ {2,2,4,4}, // 7A
+ {7,7,1,1}, // 7B
+ {4,5,6,6}, // 7C
+ {4,5,4,5}, // 7D
+ {6,6,6,7}, // 7E
+ {7,7,1,1}, // 7F
+ {2,2,3,3}, // 80
+ {6,6,6,6}, // 81
+ {2,2,2,2}, // 82
+ {6,6,1,1}, // 83
+ {3,3,3,3}, // 84
+ {3,3,3,3}, // 85
+ {3,3,3,3}, // 86
+ {3,3,1,1}, // 87
+ {2,2,2,2}, // 88
+ {2,2,2,2}, // 89
+ {2,2,2,2}, // 8A
+ {2,2,1,1}, // 8B
+ {4,4,4,4}, // 8C
+ {4,4,4,4}, // 8D
+ {4,4,4,4}, // 8E
+ {4,4,1,1}, // 8F
+ {3,3,3,3}, // 90
+ {6,6,6,6}, // 91
+ {2,2,5,5}, // 92
+ {6,6,1,1}, // 93
+ {4,4,4,4}, // 94
+ {4,4,4,4}, // 95
+ {4,4,4,4}, // 96
+ {4,4,1,1}, // 97
+ {2,2,2,2}, // 98
+ {5,5,5,5}, // 99
+ {2,2,2,2}, // 9A
+ {5,5,1,1}, // 9B
+ {5,5,4,4}, // 9C
+ {5,5,5,5}, // 9D
+ {5,5,5,5}, // 9E
+ {5,5,1,1}, // 9F
+ {2,2,2,2}, // A0
+ {6,6,6,6}, // A1
+ {2,2,2,2}, // A2
+ {6,6,1,1}, // A3
+ {3,3,3,3}, // A4
+ {3,3,3,3}, // A5
+ {3,3,3,3}, // A6
+ {3,3,1,1}, // A7
+ {2,2,2,2}, // A8
+ {2,2,2,2}, // A9
+ {2,2,2,2}, // AA
+ {2,2,1,1}, // AB
+ {4,4,4,4}, // AC
+ {4,4,4,4}, // AD
+ {4,4,4,4}, // AE
+ {4,4,1,1}, // AF
+ {2,2,2,2}, // B0
+ {5,6,5,6}, // B1
+ {2,2,5,5}, // B2
+ {5,6,1,1}, // B3
+ {4,4,4,4}, // B4
+ {4,4,4,4}, // B5
+ {4,4,4,4}, // B6
+ {4,4,1,1}, // B7
+ {2,2,2,2}, // B8
+ {4,5,4,5}, // B9
+ {2,2,2,2}, // BA
+ {4,5,1,1}, // BB
+ {4,5,4,5}, // BC
+ {4,5,4,5}, // BD
+ {4,5,4,5}, // BE
+ {4,5,1,1}, // BF
+ {2,2,2,2}, // C0
+ {6,6,6,6}, // C1
+ {2,2,2,2}, // C2
+ {8,8,1,1}, // C3
+ {3,3,3,3}, // C4
+ {3,3,3,3}, // C5
+ {5,5,5,5}, // C6
+ {5,5,1,1}, // C7
+ {2,2,2,2}, // C8
+ {2,2,2,2}, // C9
+ {2,2,2,2}, // CA
+ {2,2,1,1}, // CB
+ {4,4,4,4}, // CC
+ {4,4,4,4}, // CD
+ {6,6,6,6}, // CE
+ {6,6,1,1}, // CF
+ {3,3,3,3}, // D0
+ {5,6,5,6}, // D1
+ {2,2,5,5}, // D2
+ {8,8,1,1}, // D3
+ {4,4,4,4}, // D4
+ {4,4,4,4}, // D5
+ {6,6,6,6}, // D6
+ {6,6,1,1}, // D7
+ {2,2,2,2}, // D8
+ {4,5,4,5}, // D9
+ {2,2,3,3}, // DA
+ {7,7,1,1}, // DB
+ {4,5,4,4}, // DC
+ {4,5,4,5}, // DD
+ {7,7,7,7}, // DE
+ {7,7,1,1}, // DF
+ {2,2,2,2}, // E0
+ {6,6,6,6}, // E1
+ {2,2,2,2}, // E2
+ {8,8,1,1}, // E3
+ {3,3,3,3}, // E4
+ {3,3,3,3}, // E5
+ {5,5,5,5}, // E6
+ {5,5,1,1}, // E7
+ {2,2,2,2}, // E8
+ {2,2,2,2}, // E9
+ {2,2,2,2}, // EA
+ {2,2,1,1}, // EB
+ {4,4,4,4}, // EC
+ {4,4,4,4}, // ED
+ {6,6,6,6}, // EE
+ {6,6,1,1}, // EF
+ {2,2,2,2}, // F0
+ {5,6,5,6}, // F1
+ {2,2,5,5}, // F2
+ {8,8,1,1}, // F3
+ {4,4,4,4}, // F4
+ {4,4,4,4}, // F5
+ {6,6,6,6}, // F6
+ {6,6,1,1}, // F7
+ {2,2,2,2}, // F8
+ {4,5,4,5}, // F9
+ {2,2,4,4}, // FA
+ {7,7,1,1}, // FB
+ {4,5,4,4}, // FC
+ {4,5,4,5}, // FD
+ {7,7,7,7}, // FE
+ {7,7,1,1}, // FF
+};
+
+int GH278_Bcc_Sub(BYTE op, BYTE ps_not_taken, BYTE ps_taken, WORD pc)
+{
+ mem[pc+0] = op;
+ mem[pc+1] = 0x01;
+ const WORD dst_not_taken = pc+2;
+ const WORD dst_taken = pc+2 + mem[pc+1];
+
+ const int pagecross = (((pc+2) ^ dst_taken) >> 8) & 1;
+
+ // 6502
+
+ reset();
+ regs.pc = pc;
+ regs.ps = ps_not_taken;
+ if (Cpu6502(0) != 2) return 1;
+ if (regs.pc != dst_not_taken) return 1;
+
+ reset();
+ regs.pc = pc;
+ regs.ps = ps_taken;
+ if (Cpu6502(0) != 3+pagecross) return 1;
+ if (regs.pc != dst_taken) return 1;
+
+ // 65C02
+
+ reset();
+ regs.pc = pc;
+ regs.ps = ps_not_taken;
+ if (Cpu65C02(0) != 2) return 1;
+ if (regs.pc != dst_not_taken) return 1;
+
+ reset();
+ regs.pc = pc;
+ regs.ps = ps_taken;
+ if (Cpu65C02(0) != 3+pagecross) return 1;
+ if (regs.pc != dst_taken) return 1;
+
+ return 0;
+}
+
+int GH278_Bcc(BYTE op, BYTE ps_not_taken, BYTE ps_taken)
+{
+ if (GH278_Bcc_Sub(op, ps_not_taken, ps_taken, 0x300)) return 1; // no page cross
+ if (GH278_Bcc_Sub(op, ps_not_taken, ps_taken, 0x3FD)) return 1; // page cross
+
+ return 0;
+}
+
+int GH278_BRA(void)
+{
+ // No page-cross
+ {
+ WORD pc = 0x300;
+ mem[pc+0] = 0x80; // BRA
+ mem[pc+1] = 0x01;
+ const WORD dst_taken = pc+2 + mem[pc+1];
+
+ reset();
+ regs.pc = pc;
+ if (Cpu65C02(0) != 3) return 1;
+ if (regs.pc != dst_taken) return 1;
+ }
+
+ // Page-cross
+ {
+ WORD pc = 0x3FD;
+ mem[pc+0] = 0x80; // BRA
+ mem[pc+1] = 0x01;
+ const WORD dst_taken = pc+2 + mem[pc+1];
+
+ reset();
+ regs.pc = pc;
+ if (Cpu65C02(0) != 4) return 1;
+ if (regs.pc != dst_taken) return 1;
+ }
+
+ return 0;
+}
+
+int GH278_JMP_INDX(void)
+{
+ // No page-cross
+ reset();
+ regs.pc = 0x300;
+ WORD abs = regs.pc+3;
+ WORD dst = abs+2;
+ mem[regs.pc+0] = 0x7c; // JMP (IND,X)
+ mem[regs.pc+1] = abs&0xff;
+ mem[regs.pc+2] = abs>>8;
+ mem[regs.pc+3] = dst&0xff;
+ mem[regs.pc+4] = dst>>8;
+
+ DWORD cycles = Cpu65C02(0);
+ if (cycles != 6) return 1;
+ if (regs.pc != dst) return 1;
+
+ // Page-cross (case 1)
+ reset();
+ regs.pc = 0x3fc;
+ abs = regs.pc+3;
+ dst = abs+2;
+ mem[regs.pc+0] = 0x7c; // JMP (IND,X)
+ mem[regs.pc+1] = abs&0xff;
+ mem[regs.pc+2] = abs>>8;
+ mem[regs.pc+3] = dst&0xff;
+ mem[regs.pc+4] = dst>>8;
+
+ cycles = Cpu65C02(0);
+ if (cycles != 6) return 1; // todo: is this 6 or 7?
+ if (regs.pc != dst) return 1;
+
+ // Page-cross (case 2)
+ reset();
+ regs.x = 1;
+ regs.pc = 0x3fa;
+ abs = regs.pc+3;
+ dst = abs+2 + regs.x;
+ mem[regs.pc+0] = 0x7c; // JMP (IND,X)
+ mem[regs.pc+1] = abs&0xff;
+ mem[regs.pc+2] = abs>>8;
+ mem[regs.pc+3] = 0xcc; // unused
+ mem[regs.pc+4] = dst&0xff;
+ mem[regs.pc+5] = dst>>8;
+
+ cycles = Cpu65C02(0);
+ if (cycles != 6) return 1; // todo: is this 6 or 7?
+ if (regs.pc != dst) return 1;
+
+ return 0;
+}
+
+int GH278_ADC_SBC(UINT op)
+{
+ const WORD base = 0x20ff;
+ reset();
+ mem[regs.pc+0] = op;
+ mem[regs.pc+1] = base&0xff;
+ mem[regs.pc+2] = base>>8;
+ mem[0xff] = 0xff; mem[0x00] = 0x00; // For: OPCODE (zp),Y
+
+ // No page-cross
+ reset();
+ regs.ps = AF_DECIMAL;
+ DWORD cycles = Cpu6502(0);
+ if (g_OpcodeTimings[op][CYC_6502] != cycles) return 1;
+
+ reset();
+ regs.ps = AF_DECIMAL;
+ cycles = Cpu65C02(0);
+ if (g_OpcodeTimings[op][CYC_65C02]+1 != cycles) return 1; // CMOS is +1 cycles in decimal mode
+
+ // Page-cross
+ reset();
+ regs.ps = AF_DECIMAL;
+ regs.x = 1;
+ regs.y = 1;
+ cycles = Cpu6502(0);
+ if (g_OpcodeTimings[op][CYC_6502_PX] != cycles) return 1;
+
+ reset();
+ regs.ps = AF_DECIMAL;
+ regs.x = 1;
+ regs.y = 1;
+ cycles = Cpu65C02(0);
+ if (g_OpcodeTimings[op][CYC_65C02_PX]+1 != cycles) return 1; // CMOS is +1 cycles in decimal mode
+
+ return 0;
+}
+
+int GH278_ADC(void)
+{
+ const BYTE adc[] = {0x61,0x65,0x69,0x6D,0x71,0x72,0x75,0x79,0x7D};
+
+ for (UINT i = 0; i>8;
+ DWORD cycles = Cpu6502(0);
+ if (g_OpcodeTimings[op][variant] != cycles) return 1;
+ }
+
+ variant++;
+
+ // Page-cross
+ for (UINT op=0; op<256; op++)
+ {
+ reset();
+ regs.x = 1;
+ regs.y = 1;
+ WORD base = 0x20ff;
+ mem[regs.pc+0] = op;
+ mem[regs.pc+1] = base&0xff;
+ mem[regs.pc+2] = base>>8;
+ mem[0xff] = 0xff; mem[0x00] = 0x00; // For: OPCODE (zp),Y
+ DWORD cycles = Cpu6502(0);
+ if (g_OpcodeTimings[op][variant] != cycles) return 1;
+ }
+
+ variant++;
+
+ //
+ // 65C02
+ //
+
+ // No page-cross
+ for (UINT op=0; op<256; op++)
+ {
+ reset();
+ WORD base = 0x20ff;
+ mem[regs.pc+0] = op;
+ mem[regs.pc+1] = base&0xff;
+ mem[regs.pc+2] = base>>8;
+ DWORD cycles = Cpu65C02(0);
+ if (g_OpcodeTimings[op][variant] != cycles) return 1;
+ }
+
+ variant++;
+
+ // Page-cross
+ for (UINT op=0; op<256; op++)
+ {
+ reset();
+ regs.x = 1;
+ regs.y = 1;
+ WORD base = 0x20ff;
+ mem[regs.pc+0] = op;
+ mem[regs.pc+1] = base&0xff;
+ mem[regs.pc+2] = base>>8;
+ mem[0xff] = 0xff; mem[0x00] = 0x00; // For: OPCODE (zp),Y
+ DWORD cycles = Cpu65C02(0);
+ if (g_OpcodeTimings[op][variant] != cycles) return 1;
+ }
+
+ //
+ // Bcc
+ //
+
+ if (GH278_Bcc(0x10, AF_SIGN, 0)) return 1; // BPL
+ if (GH278_Bcc(0x30, 0, AF_SIGN)) return 1; // BMI
+ if (GH278_Bcc(0x50, AF_OVERFLOW, 0)) return 1; // BVC
+ if (GH278_Bcc(0x70, 0, AF_OVERFLOW)) return 1; // BVS
+ if (GH278_Bcc(0x90, AF_CARRY, 0)) return 1; // BCC
+ if (GH278_Bcc(0xB0, 0, AF_CARRY)) return 1; // BCS
+ if (GH278_Bcc(0xD0, AF_ZERO, 0)) return 1; // BNE
+ if (GH278_Bcc(0xF0, 0, AF_ZERO)) return 1; // BEQ
+ if (GH278_BRA()) return 1; // BRA
+
+ //
+ // JMP (IND) and JMP (IND,X)
+ // . NB. GH264_test() tests JMP (IND)
+ //
+
+ if (GH278_JMP_INDX()) return 1;
+
+ //
+ // ADC/SBC CMOS decimal mode is +1 cycles
+ //
+
+ if (GH278_ADC()) return 1;
+ if (GH278_SBC()) return 1;
+
+ return 0;
+}
+
+//-------------------------------------
+
+DWORD AXA_ZPY(BYTE a, BYTE x, BYTE y, WORD base)
+{
+ reset();
+ mem[0xfe] = base&0xff;
+ mem[0xff] = base>>8;
+ regs.a = a;
+ regs.x = x;
+ regs.y = y;
+ mem[regs.pc+0] = 0x93;
+ mem[regs.pc+1] = 0xfe;
+ return Cpu6502(0);
+}
+
+DWORD AXA_ABSY(BYTE a, BYTE x, BYTE y, WORD base)
+{
+ reset();
+ regs.a = a;
+ regs.x = x;
+ regs.y = y;
+ mem[regs.pc+0] = 0x9f;
+ mem[regs.pc+1] = base&0xff;
+ mem[regs.pc+2] = base>>8;
+ return Cpu6502(0);
+}
+
+DWORD SAY_ABSX(BYTE a, BYTE x, BYTE y, WORD base)
+{
+ reset();
+ regs.a = a;
+ regs.x = x;
+ regs.y = y;
+ mem[regs.pc+0] = 0x9c;
+ mem[regs.pc+1] = base&0xff;
+ mem[regs.pc+2] = base>>8;
+ return Cpu6502(0);
+}
+
+DWORD TAS_ABSY(BYTE a, BYTE x, BYTE y, WORD base)
+{
+ reset();
+ regs.a = a;
+ regs.x = x;
+ regs.y = y;
+ mem[regs.pc+0] = 0x9b;
+ mem[regs.pc+1] = base&0xff;
+ mem[regs.pc+2] = base>>8;
+ return Cpu6502(0);
+}
+
+DWORD XAS_ABSY(BYTE a, BYTE x, BYTE y, WORD base)
+{
+ reset();
+ regs.a = a;
+ regs.x = x;
+ regs.y = y;
+ mem[regs.pc+0] = 0x9e;
+ mem[regs.pc+1] = base&0xff;
+ mem[regs.pc+2] = base>>8;
+ return Cpu6502(0);
+}
+
+int GH282_test(void)
+{
+ // axa (zp),y
+ {
+ WORD base = 0x20ff, addr = 0x20ff;
+ mem[addr] = 0xcc;
+ BYTE a = 0xea, x = 0xff, y = 0;
+ DWORD cycles = AXA_ZPY(a, x, y, base);
+ if (cycles != 6) return 1;
+ if (mem[addr] != (a & x & ((base>>8)+1))) return 1;
+ }
+
+ // axa (zp),y (page-cross)
+ {
+ WORD base = 0x20ff, addr = 0x2000;
+ mem[addr] = 0xcc;
+ BYTE a = 0xea, x = 0xff, y = 1;
+ DWORD cycles = AXA_ZPY(a, x, y, base);
+ if (cycles != 6) return 1;
+ if (mem[addr] != (a & x & ((base>>8)+1))) return 1;
+ }
+
+ //
+
+ // axa abs,y
+ {
+ WORD base = 0x20ff, addr = 0x20ff;
+ mem[addr] = 0xcc;
+ BYTE a = 0xea, x = 0xff, y = 0;
+ DWORD cycles = AXA_ABSY(a, x, y, base);
+ if (cycles != 5) return 1;
+ if (mem[addr] != (a & x & ((base>>8)+1))) return 1;
+ }
+
+ // axa abs,y (page-cross)
+ {
+ WORD base = 0x20ff, addr = 0x2000;
+ mem[addr] = 0xcc;
+ BYTE a = 0xea, x = 0xff, y = 1;
+ DWORD cycles = AXA_ABSY(a, x, y, base);
+ if (cycles != 5) return 1;
+ if (mem[addr] != (a & x & ((base>>8)+1))) return 1;
+ }
+
+ //
+
+ // say abs,x
+ {
+ WORD base = 0x20ff, addr = 0x20ff;
+ mem[addr] = 0xcc;
+ BYTE a = 0xea, x = 0, y=0x20;
+ DWORD cycles = SAY_ABSX(a, x, y, base);
+ if (cycles != 5) return 1;
+ if (mem[addr] != (y & ((base>>8)+1))) return 1;
+ }
+
+ // say abs,x (page-cross)
+ {
+ WORD base = 0x20ff, addr = 0x2000;
+ mem[addr] = 0xcc;
+ BYTE a = 0xea, x = 1, y=0x20;
+ DWORD cycles = SAY_ABSX(a, x, y, base);
+ if (cycles != 5) return 1;
+ if (mem[addr] != (y & ((base>>8)+1))) return 1;
+ }
+
+ //
+
+ // tas abs,y
+ {
+ WORD base = 0x20ff, addr = 0x20ff;
+ mem[addr] = 0xcc;
+ BYTE a = 0xea, x = 0xff, y = 0;
+ DWORD cycles = TAS_ABSY(a, x, y, base);
+ if (cycles != 5) return 1;
+ if (mem[addr] != (a & x & ((base>>8)+1))) return 1;
+ if (regs.sp != (0x100 | (a & x))) return 1;
+ }
+
+ // tas abs,y (page-cross)
+ {
+ WORD base = 0x20ff, addr = 0x2000;
+ mem[addr] = 0xcc;
+ BYTE a = 0xea, x = 0xff, y = 1;
+ DWORD cycles = TAS_ABSY(a, x, y, base);
+ if (cycles != 5) return 1;
+ if (mem[addr] != (a & x & ((base>>8)+1))) return 1;
+ if (regs.sp != (0x100 | (a & x))) return 1;
+ }
+
+ //
+
+ // xas abs,y
+ {
+ WORD base = 0x20ff, addr = 0x20ff;
+ mem[addr] = 0xcc;
+ BYTE a = 0xea, x = 0x20, y = 0;
+ DWORD cycles = XAS_ABSY(a, x, y, base);
+ if (cycles != 5) return 1;
+ if (mem[addr] != (x & ((base>>8)+1))) return 1;
+ }
+
+ // xas abs,y (page-cross)
+ {
+ WORD base = 0x20ff, addr = 0x2000;
+ mem[addr] = 0xcc;
+ BYTE a = 0xea, x = 0x20, y = 1;
+ DWORD cycles = XAS_ABSY(a, x, y, base);
+ if (cycles != 5) return 1;
+ if (mem[addr] != (x & ((base>>8)+1))) return 1;
+ }
+
+ return 0;
+}
+
+//-------------------------------------
+
+int g_fn_C000_count = 0;
+
+BYTE __stdcall fn_C000(WORD, WORD, BYTE, BYTE, ULONG)
+{
+ g_fn_C000_count++;
+ return 42;
+}
+
+int GH292_test(void)
+{
+ // Undocumented 65C02 NOPs: 1 cycle & 1 byte
+ for (UINT op=0; op<256; op+=0x10)
+ {
+ reset();
+ WORD base=regs.pc;
+
+ mem[regs.pc] = op+0x03; if (Cpu65C02(0) != 1 || regs.pc != base+1) return 1;
+ mem[regs.pc] = op+0x07; if (Cpu65C02(0) != 1 || regs.pc != base+2) return 1;
+ mem[regs.pc] = op+0x0B; if (Cpu65C02(0) != 1 || regs.pc != base+3) return 1;
+ mem[regs.pc] = op+0x0F; if (Cpu65C02(0) != 1 || regs.pc != base+4) return 1;
+ }
+
+ //
+
+ // Undocumented 65C02 NOP: LDD - LoaD and Discard
+ IORead[0] = fn_C000;
+
+ reset();
+ WORD base = regs.pc;
+ mem[regs.pc+0] = 0xDC;
+ mem[regs.pc+1] = 0x00;
+ mem[regs.pc+2] = 0xC0;
+ if (Cpu65C02(0) != 4 || regs.pc != base+3 || g_fn_C000_count != 1 || regs.a != 0) return 1;
+
+ reset();
+ base = regs.pc;
+ mem[regs.pc+0] = 0xFC;
+ mem[regs.pc+1] = 0x00;
+ mem[regs.pc+2] = 0xC0;
+ if (Cpu65C02(0) != 4 || regs.pc != base+3 || g_fn_C000_count != 2 || regs.a != 0) return 1;
+
+ IORead[0] = NULL;
+
+ return 0;
+}
+
+//-------------------------------------
+
+int _tmain(int argc, _TCHAR* argv[])
+{
+ int res = 1;
+ init();
+ reset();
+
+ res = GH264_test();
+ if (res) return res;
+
+ res = GH271_test();
+ if (res) return res;
+
+ res = GH278_test();
+ if (res) return res;
+
+ res = GH282_test();
+ if (res) return res;
+
+ res = GH292_test();
+ if (res) return res;
+
+ return 0;
+}
diff --git a/test/TestCPU6502/TestCPU6502.vcproj b/test/TestCPU6502/TestCPU6502.vcproj
new file mode 100644
index 00000000..f5582875
--- /dev/null
+++ b/test/TestCPU6502/TestCPU6502.vcproj
@@ -0,0 +1,205 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/TestCPU6502/stdafx.cpp b/test/TestCPU6502/stdafx.cpp
new file mode 100644
index 00000000..eb380001
--- /dev/null
+++ b/test/TestCPU6502/stdafx.cpp
@@ -0,0 +1,8 @@
+// stdafx.cpp : source file that includes just the standard includes
+// TestCPU6502.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+// TODO: reference any additional headers you need in STDAFX.H
+// and not in this file
diff --git a/test/TestCPU6502/stdafx.h b/test/TestCPU6502/stdafx.h
new file mode 100644
index 00000000..47956f7e
--- /dev/null
+++ b/test/TestCPU6502/stdafx.h
@@ -0,0 +1,13 @@
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#pragma once
+
+#include
+#include
+
+#include
+
+#include