diff --git a/ApplewinExpress9.00.sln b/ApplewinExpress9.00.sln
index 6fbec8fe..0b5bd62c 100644
--- a/ApplewinExpress9.00.sln
+++ b/ApplewinExpress9.00.sln
@@ -11,6 +11,8 @@ 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
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
@@ -29,6 +31,10 @@ 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
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/test/TestCPU6502/TestCPU6502.cpp b/test/TestCPU6502/TestCPU6502.cpp
new file mode 100644
index 00000000..7ca2d2d9
--- /dev/null
+++ b/test/TestCPU6502/TestCPU6502.cpp
@@ -0,0 +1,299 @@
+#include "stdafx.h"
+
+#include "../../source/Applewin.h"
+#include "../../source/CPU.h"
+
+// From Applewin.cpp
+eCPU g_ActiveCPU = CPU_6502;
+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 __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;
+}
+
+#include "../../source/cpu/cpu_general.inl"
+#include "../../source/cpu/cpu_instructions.inl"
+#include "../../source/cpu/cpu6502.h" // MOS 6502
+
+void init(void)
+{
+ //mem = new BYTE[64*1024];
+ 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;
+}
+
+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 test6502_GH282(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 _tmain(int argc, _TCHAR* argv[])
+{
+ init();
+ reset();
+
+ int res = test6502_GH282();
+
+ return res;
+}
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..ca800fd6
--- /dev/null
+++ b/test/TestCPU6502/stdafx.h
@@ -0,0 +1,11 @@
+// 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