]> git.sur5r.net Git - cc65/commitdiff
Intermediate state - doesn't run as is.
authoruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Thu, 5 Apr 2012 13:30:21 +0000 (13:30 +0000)
committeruz <uz@b7a2c559-68d2-44c3-8de9-860c34a00d81>
Thu, 5 Apr 2012 13:30:21 +0000 (13:30 +0000)
git-svn-id: svn://svn.cc65.org/cc65/trunk@5643 b7a2c559-68d2-44c3-8de9-860c34a00d81

19 files changed:
src/sim65/addrspace.c
src/sim65/addrspace.h
src/sim65/cfgdata.c
src/sim65/cfgdata.h
src/sim65/chip.c
src/sim65/chips/console.c
src/sim65/chips/make/gcc.mak
src/sim65/chips/stdio.c
src/sim65/config.c
src/sim65/cpu-6502.c [new file with mode: 0644]
src/sim65/cpu-6502.h [new file with mode: 0644]
src/sim65/cpucore.c
src/sim65/cpucore.h
src/sim65/make/gcc.mak
src/sim65/memory.c
src/sim65/memory.h
src/sim65/scanner.c
src/sim65/scanner.h
src/sim65/simdata.h

index 1eda9f76a14df4dd5bd4338d1a3e5e0ce4eb5d22..78c069437d15948399d4aabb2802bd140be7e684 100644 (file)
@@ -6,10 +6,10 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2003      Ullrich von Bassewitz                                       */
-/*               Römerstrasse 52                                             */
-/*               D-70794 Filderstadt                                         */
-/* EMail:        uz@cc65.org                                                 */
+/* (C) 2002-2012, Ullrich von Bassewitz                                      */
+/*                Roemerstrasse 52                                           */
+/*                D-70794 Filderstadt                                        */
+/* EMail:         uz@cc65.org                                                */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
index b353068e4b37352a3c90c90844225f291bfdf192..8d50156b4d2ed2e44e1f0e02611a1880d5f02fbb 100644 (file)
@@ -6,10 +6,10 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2003      Ullrich von Bassewitz                                       */
-/*               Römerstrasse 52                                             */
-/*               D-70794 Filderstadt                                         */
-/* EMail:        uz@cc65.org                                                 */
+/* (C) 2003-2012, Ullrich von Bassewitz                                      */
+/*                Roemerstrasse 52                                           */
+/*                D-70794 Filderstadt                                        */
+/* EMail:         uz@cc65.org                                                */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
index 5c33ea2a710df842fb5bd4c991ac82b5df233bcb..e1cbf98e95bc882cfa6370bb942765af4d0ac41f 100644 (file)
@@ -6,10 +6,10 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2002-2003 Ullrich von Bassewitz                                       */
-/*               Römerstrasse 52                                             */
-/*               D-70794 Filderstadt                                         */
-/* EMail:        uz@cc65.org                                                 */
+/* (C) 2002-2012, Ullrich von Bassewitz                                      */
+/*                Roemerstrasse 52                                           */
+/*                D-70794 Filderstadt                                        */
+/* EMail:         uz@cc65.org                                                */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
@@ -57,17 +57,14 @@ CfgData* NewCfgData (void)
  * uses the current output of the config scanner.
  */
 {
-    /* Get the length of the identifier */
-    unsigned AttrLen = strlen (CfgSVal);
-
     /* Allocate memory */
-    CfgData* D = xmalloc (sizeof (CfgData) + AttrLen);
+    CfgData* D = xmalloc (sizeof (CfgData) + SB_GetLen (&CfgSVal));
 
     /* Initialize the fields */
     D->Type = CfgDataInvalid;
     D->Line = CfgErrorLine;
     D->Col  = CfgErrorCol;
-    memcpy (D->Attr, CfgSVal, AttrLen+1);
+    memcpy (D->Attr, SB_GetConstBuf (&CfgSVal), SB_GetLen (&CfgSVal) + 1);
 
     /* Return the new struct */
     return D;
@@ -78,7 +75,7 @@ CfgData* NewCfgData (void)
 void FreeCfgData (CfgData* D)
 /* Free a config data structure */
 {
-    if (D->Type == CfgDataString) {
+    if (D->Type == CfgDataId || D->Type == CfgDataString) {
         /* Free the string value */
         xfree (D->V.SVal);
     }
index c86522f724fcdd82a3f382c2700c5ac843a1e3e1..f1a278f92cc30ff47d44341be024c6805cf96e9e 100644 (file)
@@ -6,10 +6,10 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2002-2003 Ullrich von Bassewitz                                       */
-/*               Römerstrasse 52                                             */
-/*               D-70794 Filderstadt                                         */
-/* EMail:        uz@cc65.org                                                 */
+/* (C) 2002-2012, Ullrich von Bassewitz                                      */
+/*                Roemerstrasse 52                                           */
+/*                D-70794 Filderstadt                                        */
+/* EMail:         uz@cc65.org                                                */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
@@ -58,7 +58,7 @@ struct CfgData {
        CfgDataString
     }          Type;           /* Type of the value */
     union {
-       char*   SVal;           /* String or id value */
+        char*   SVal;           /* String or id value */
        long    IVal;           /* Integer value */
     } V;
     unsigned    Line;           /* Line where the attribute was defined */
index 50d248c4e906f53987ea57c0aacf261a24d69ba1..7d1504bf9d3691c4c6abd1511bde5b5ee36c9187 100644 (file)
@@ -105,6 +105,8 @@ static const SimData Sim65Data = {
     GetCfgId,
     GetCfgStr,
     GetCfgNum,
+    0,
+    0,
     Break,
     IRQRequest,
     NMIRequest,
@@ -156,7 +158,7 @@ static int GetCfgNum (void* CfgInfo, const char* Name, long* Val)
 
 
 static int CmpChips (void* Data attribute ((unused)),
-                    const void* lhs, const void* rhs)
+                    const void* lhs, const void* rhs)
 /* Compare function for CollSort */
 {
     /* Cast the object pointers */
@@ -404,7 +406,7 @@ void LoadChipLibrary (const char* LibName)
         /* Output chip name and version to keep the user happy */
         Print (stdout, 1,
                "  Found %s `%s', version %u.%u in library `%s'\n",
-              (D->Type == CHIPDATA_TYPE_CHIP)? "chip" : "cpu",
+              (D->Type == CHIPDATA_TYPE_CHIP)? "chip" : "cpu",
                D->ChipName,
                D->MajorVersion,
                D->MinorVersion,
index c257fa787e95c0407842185631cc936dc694d712..528925b1466e2d2feacfb651f313f62db5e4f354 100644 (file)
@@ -6,7 +6,7 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2003-2009, Ullrich von Bassewitz                                      */
+/* (C) 2003-2012, Ullrich von Bassewitz                                      */
 /*                Roemerstrasse 52                                           */
 /*                D-70794 Filderstadt                                        */
 /* EMail:         uz@cc65.org                                                */
index 82a5e152ed876563523a0c0a3668199a52334032..506b1670a49ab10317b9be1b8d41c08b04611de3 100644 (file)
@@ -6,7 +6,7 @@
 COMMON  = ../../common
 SIM65  = ..
 
-CFLAGS         = -g -O2 -Wall -W -std=c89
+CFLAGS         = -g -Wall -W -std=c89
 override CFLAGS += -I$(COMMON) -I$(SIM65) -fpic
 CC     = gcc
 EBIND  = emxbind
index bce203f84f05f715153c452b63ce061b3f469d7f..1e66feb97aa7e51563338b239e69e973c9a3558d 100644 (file)
@@ -6,10 +6,10 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2002-2003 Ullrich von Bassewitz                                       */
-/*               Römerstrasse 52                                             */
-/*               D-70794 Filderstadt                                         */
-/* EMail:        uz@cc65.org                                                 */
+/* (C) 2002-2012, Ullrich von Bassewitz                                      */
+/*                Roemerstrasse 52                                           */
+/*                D-70794 Filderstadt                                        */
+/* EMail:         uz@cc65.org                                                */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
@@ -60,9 +60,15 @@ static void* CreateInstance (unsigned Addr, unsigned Range, void* CfgInfo);
 static void DestroyInstance (void* Data);
 /* Destroy a chip instance */
 
+static void WriteCtrl (void* Data, unsigned Offs, unsigned char Val);
+/* Write control data */
+
 static void Write (void* Data, unsigned Offs, unsigned char Val);
 /* Write user data */
 
+static unsigned char ReadCtrl (void* Data, unsigned Offs);
+/* Read control data */
+
 static unsigned char Read (void* Data, unsigned Offs);
 /* Read user data */
 
@@ -74,6 +80,9 @@ static unsigned char Read (void* Data, unsigned Offs);
 
 
 
+/* The SimData pointer we get when InitChip is called */
+static const SimData* Sim;
+
 /* Control data passed to the main program */
 static const struct ChipData CData[1] = {
     {
@@ -86,15 +95,33 @@ static const struct ChipData CData[1] = {
         InitChip,
         CreateInstance,
        DestroyInstance,
+        WriteCtrl,
         Write,
-        Write,
-        Read,
+        ReadCtrl,
         Read
     }
 };
 
-/* The SimData pointer we get when InitChip is called */
-static const SimData* Sim;
+/* Screen instance data */
+typedef struct InstanceData InstanceData;
+struct InstanceData {
+    /* The memory area used for data */
+    unsigned char*      Mem[32];
+};
+
+/* Function opcodes */
+enum {
+    F_open,
+    F_close,
+    F_write,
+    F_read,
+    F_lseek,
+    F_unlink,
+    F_chdir,
+    F_getcwd,
+    F_mkdir,
+    F_rmdir,
+};
 
 
 
@@ -137,8 +164,14 @@ static int InitChip (const struct SimData* Data)
 static void* CreateInstance (unsigned Addr, unsigned Range, void* CfgInfo)
 /* Initialize a new chip instance */
 {
-    /* We don't need any instance data */
-    return 0;
+    /* Allocate the instance data */
+    InstanceData* D = Sim->Malloc (sizeof (InstanceData));
+
+    /* Initialize the instance data */
+    memset (D->Mem, 0x00, sizeof (D->Mem));
+
+    /* Return the instance data */
+    return D;
 }
 
 
@@ -146,28 +179,111 @@ static void* CreateInstance (unsigned Addr, unsigned Range, void* CfgInfo)
 static void DestroyInstance (void* Data)
 /* Destroy a chip instance */
 {
+    /* Cast the instance data pointer */
+    InstanceData* D = Data;
+
+    /* Free the instance data */
+    Sim->Free (D);
+}
+
+
+
+static void WriteCtrl (void* Data attribute, unsigned Offs, unsigned char Val)
+/* Write user data */
+{
+    /* Cast the instance data pointer */
+    InstanceData* D = Data;
+
+    /* Write to the memory */
+    D->Mem[Offs] = Val;
 }
 
 
 
-static void Write (void* Data attribute ((unused)),
-                  unsigned Offs attribute ((unused)),
-                  unsigned char Val)
+static void Write (void* Data, unsigned Offs, unsigned char Val)
 /* Write user data */
 {
-    putchar (Val);
+    /* Cast the instance data pointer */
+    InstanceData* D = Data;
+
+    /* Write to the memory */
+    D->Mem[Offs] = Val;
+
+    /* Now check the offset. Zero is special because it will trigger the
+     * action
+     */
+    if (Offs == 0) {
+
+        /* The action is determined by the value that is written */
+        switch (Val) {
+
+            case F_open:
+                Sim->Break ("Unsupported function $%02X", Val);
+                break;
+
+            case F_close:
+                Sim->Break ("Unsupported function $%02X", Val);
+                break;
+
+            case F_write:
+                Sim->Break ("Unsupported function $%02X", Val);
+                break;
+
+            case F_read:
+                Sim->Break ("Unsupported function $%02X", Val);
+                break;
+
+            case F_lseek:
+                Sim->Break ("Unsupported function $%02X", Val);
+                break;
+
+            case F_unlink:
+                Sim->Break ("Unsupported function $%02X", Val);
+                break;
+
+            case F_chdir:
+                Sim->Break ("Unsupported function $%02X", Val);
+                break;
+
+            case F_getcwd:
+                Sim->Break ("Unsupported function $%02X", Val);
+                break;
+
+            case F_mkdir:
+                Sim->Break ("Unsupported function $%02X", Val);
+                break;
+
+            case F_rmdir:
+                Sim->Break ("Unsupported function $%02X", Val);
+                break;
+
+        }
+    }
 }
 
 
 
-static unsigned char Read (void* Data attribute ((unused)),
-                          unsigned Offs attribute ((unused)))
+static unsigned char ReadCtrl (void* Data, unsigned Offs)
 /* Read user data */
 {
-    /* Read a character and return the value */
-    return getchar ();
+    /* Cast the instance data pointer */
+    InstanceData* D = Data;
+
+    /* Read the cell and return the value */
+    return D->Mem[Offs];
 }
 
 
 
+static unsigned char Read (void* Data, unsigned Offs)
+/* Read user data */
+{
+    /* Cast the instance data pointer */
+    InstanceData* D = Data;
+
+    /* Read the cell and return the value */
+    return D->Mem[Offs];
+}
+
+
 
index 3a2a14cdcc4010ed139552fb0e1a27b76c435540..7c828026cdee6a028e1f876c520700d1607364c5 100644 (file)
@@ -6,10 +6,10 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998-2003 Ullrich von Bassewitz                                       */
-/*               Römerstrasse 52                                             */
-/*               D-70794 Filderstadt                                         */
-/* EMail:        uz@cc65.org                                                 */
+/* (C) 1998-2012, Ullrich von Bassewitz                                      */
+/*                Roemerstrasse 52                                           */
+/*                D-70794 Filderstadt                                        */
+/* EMail:         uz@cc65.org                                                */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
 #include "xmalloc.h"
 
 /* sim65 */
+#include "addrspace.h"
 #include "cfgdata.h"
 #include "chip.h"
 #include "error.h"
 #include "global.h"
-#include "memory.h"
 #include "location.h"
 #include "scanner.h"
 #include "config.h"
@@ -143,18 +143,26 @@ static void ParseCPU (void)
     AttrCheck (Attr, atType, "TYPE");
     AttrCheck (Attr, atAddrSpace, "ADDRSPACE");
 
+    /* Create the CPU */
+    CPUInstance = NewCPU ("6502", Size);
+
     /* Skip the semicolon */
     CfgConsumeSemi ();
 }
 
 
 
-static void ParseMemory (void)
-/* Parse a MEMORY section */
+static void ParseAddrSpace (void)
+/* Parse a ADDRSPACE section */
 {
     unsigned I;
 
+    /* CPU must be defined before the address space */
+    if (CPUInstance == 0) {
+        CfgError ("CPU must be defined before address space definitions");
+    }
 
+    /* Parse addresses */
     while (CfgTok == CFGTOK_INTCON) {
 
         Location* L;
@@ -263,8 +271,8 @@ static void ParseMemory (void)
         /* Delete the "name" attribute */
         FreeCfgData (D);
 
-        /* Assign the chip instance to memory */
-        MemAssignChip (CI, L->Start, Range);
+        /* Assign the chip instance to address space */
+        ASAssignChip (CPUInstance->AS, CI, L->Start, Range);
     }
 
     /* Create the mirrors */
@@ -295,7 +303,7 @@ static void ParseMemory (void)
         /* For simplicity, get the chip instance we're mirroring from the
          * memory, instead of searching for the range in the list.
          */
-        CI = MemGetChip (MirrorAddr);
+        CI = ASGetChip (MirrorAddr);
         if (CI == 0) {
             /* We are mirroring an unassigned address */
             Error ("%s(%u): Mirroring an unassigned address",
@@ -316,8 +324,8 @@ static void ParseMemory (void)
         /* Clone the chip instance for the new location */
         MCI = MirrorChipInstance (CI, L->Start - Offs);
 
-        /* Assign the chip instance to memory */
-        MemAssignChip (MCI, L->Start, Range);
+        /* Assign the chip instance to address space */
+        ASAssignChip (CPUInstance->AS, MCI, L->Start, Range);
     }
 }
 
@@ -327,8 +335,8 @@ static void ParseConfig (void)
 /* Parse the config file */
 {
     static const IdentTok BlockNames [] = {
-               {   "CPU",      CFGTOK_CPU      },
-               {   "MEMORY",   CFGTOK_MEMORY   },
+               {   "ADDRSPACE",        CFGTOK_ADDRSPACE        },
+               {   "CPU",              CFGTOK_CPU              },
     };
     cfgtok_t BlockTok;
 
@@ -345,12 +353,12 @@ static void ParseConfig (void)
        /* Read the block */
        switch (BlockTok) {
 
-            case CFGTOK_CPU:
-                ParseCPU ();
+            case CFGTOK_ADDRSPACE:
+                ParseAddrSpace ();
                 break;
 
-            case CFGTOK_MEMORY:
-                ParseMemory ();
+            case CFGTOK_CPU:
+                ParseCPU ();
                 break;
 
            default:
diff --git a/src/sim65/cpu-6502.c b/src/sim65/cpu-6502.c
new file mode 100644 (file)
index 0000000..3992963
--- /dev/null
@@ -0,0 +1,2592 @@
+/*****************************************************************************/
+/*                                                                           */
+/*                                   cpucore.c                               */
+/*                                                                           */
+/*                        CPU core for the 6502 simulator                    */
+/*                                                                           */
+/*                                                                           */
+/*                                                                           */
+/* (C) 2003-2012, Ullrich von Bassewitz                                      */
+/*                Roemerstrasse 52                                           */
+/*                D-70794 Filderstadt                                        */
+/* EMail:         uz@cc65.org                                                */
+/*                                                                           */
+/*                                                                           */
+/* This software is provided 'as-is', without any expressed or implied       */
+/* warranty.  In no event will the authors be held liable for any damages    */
+/* arising from the use of this software.                                    */
+/*                                                                           */
+/* Permission is granted to anyone to use this software for any purpose,     */
+/* including commercial applications, and to alter it and redistribute it    */
+/* freely, subject to the following restrictions:                            */
+/*                                                                           */
+/* 1. The origin of this software must not be misrepresented; you must not   */
+/*    claim that you wrote the original software. If you use this software   */
+/*    in a product, an acknowledgment in the product documentation would be  */
+/*    appreciated but is not required.                                       */
+/* 2. Altered source versions must be plainly marked as such, and must not   */
+/*    be misrepresented as being the original software.                      */
+/* 3. This notice may not be removed or altered from any source              */
+/*    distribution.                                                          */
+/*                                                                           */
+/*****************************************************************************/
+
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+/* common */
+#include "abend.h"
+#include "attrib.h"
+#include "print.h"
+#include "strbuf.h"
+
+/* sim65 */
+#include "cpuregs.h"
+#include "cputype.h"
+#include "error.h"
+#include "global.h"
+#include "memory.h"
+#include "cpucore.h"
+
+
+
+/*****************************************************************************/
+/*                                  Data                                    */
+/*****************************************************************************/
+
+
+
+/* Registers */
+CPURegs Regs;
+
+/* Count the total number of cylcles */
+unsigned       Cycles;         /* Cycles per insn */
+unsigned long  TotalCycles;    /* Total cycles */
+
+/* Allow the stack page to be changed */
+static unsigned StackPage = 0x100;
+
+/* CPU flags */
+int HaveNMIRequest = 0;
+int HaveIRQRequest = 0;
+int CPUHalted      = 0;
+
+/* Break message */
+static StrBuf BreakMsg = STATIC_STRBUF_INITIALIZER;
+
+
+
+/*****************************************************************************/
+/*                       Helper functions and macros                        */
+/*****************************************************************************/
+
+
+
+/* Return the flags as a boolean value (0/1) */
+#define GET_CF()        ((Regs.SR & CF) != 0)
+#define GET_ZF()        ((Regs.SR & ZF) != 0)
+#define GET_IF()        ((Regs.SR & IF) != 0)
+#define GET_DF()        ((Regs.SR & DF) != 0)
+#define GET_BF()        ((Regs.SR & BF) != 0)
+#define GET_OF()        ((Regs.SR & OF) != 0)
+#define GET_SF()        ((Regs.SR & SF) != 0)
+
+/* Set the flags. The parameter is a boolean flag that says if the flag should be
+ * set or reset.
+ */
+#define SET_CF(f)       do { if (f) { Regs.SR |= CF; } else { Regs.SR &= ~CF; } } while (0)
+#define SET_ZF(f)       do { if (f) { Regs.SR |= ZF; } else { Regs.SR &= ~ZF; } } while (0)
+#define SET_IF(f)       do { if (f) { Regs.SR |= IF; } else { Regs.SR &= ~IF; } } while (0)
+#define SET_DF(f)       do { if (f) { Regs.SR |= DF; } else { Regs.SR &= ~DF; } } while (0)
+#define SET_BF(f)       do { if (f) { Regs.SR |= BF; } else { Regs.SR &= ~BF; } } while (0)
+#define SET_OF(f)       do { if (f) { Regs.SR |= OF; } else { Regs.SR &= ~OF; } } while (0)
+#define SET_SF(f)       do { if (f) { Regs.SR |= SF; } else { Regs.SR &= ~SF; } } while (0)
+
+/* Special test and set macros. The meaning of the parameter depends on the
+ * actual flag that should be set or reset.
+ */
+#define TEST_ZF(v)      SET_ZF (((v) & 0xFF) == 0)
+#define TEST_SF(v)      SET_SF (((v) & 0x80) != 0)
+#define TEST_CF(v)      SET_CF (((v) & 0xFF00) != 0)
+
+/* Program counter halves */
+#define PCL            (Regs.PC & 0xFF)
+#define PCH            ((Regs.PC >> 8) & 0xFF)
+
+/* Stack operations */
+#define PUSH(Val)       MemWriteByte (StackPage + Regs.SP--, Val)
+#define POP()           MemReadByte (StackPage + ++Regs.SP)
+
+/* Test for page cross */
+#define PAGE_CROSS(addr,offs)   ((((addr) & 0xFF) + offs) >= 0x100)
+
+/* #imm */
+#define AC_OP_IMM(op)                                           \
+    Cycles = 2;                                                 \
+    Regs.AC = Regs.AC op MemReadByte (Regs.PC+1);               \
+    TEST_ZF (Regs.AC);                                          \
+    TEST_SF (Regs.AC);                                          \
+    Regs.PC += 2
+
+/* zp */
+#define AC_OP_ZP(op)                                            \
+    Cycles = 3;                                                 \
+    Regs.AC = Regs.AC op MemReadByte (MemReadByte (Regs.PC+1)); \
+    TEST_ZF (Regs.AC);                                          \
+    TEST_SF (Regs.AC);                                          \
+    Regs.PC += 2
+
+/* zp,x */
+#define AC_OP_ZPX(op)                                           \
+    unsigned char ZPAddr;                                       \
+    Cycles = 4;                                                 \
+    ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;                 \
+    Regs.AC = Regs.AC op MemReadByte (ZPAddr);                  \
+    TEST_ZF (Regs.AC);                                          \
+    TEST_SF (Regs.AC);                                          \
+    Regs.PC += 2
+
+/* zp,y */
+#define AC_OP_ZPY(op)                                           \
+    unsigned char ZPAddr;                                       \
+    Cycles = 4;                                                 \
+    ZPAddr = MemReadByte (Regs.PC+1) + Regs.YR;                 \
+    Regs.AC = Regs.AC op MemReadByte (ZPAddr);                  \
+    TEST_ZF (Regs.AC);                                          \
+    TEST_SF (Regs.AC);                                          \
+    Regs.PC += 2
+
+/* abs */
+#define AC_OP_ABS(op)                                           \
+    unsigned Addr;                                              \
+    Cycles = 4;                                                 \
+    Addr = MemReadWord (Regs.PC+1);                             \
+    Regs.AC = Regs.AC op MemReadByte (Addr);                    \
+    TEST_ZF (Regs.AC);                                          \
+    TEST_SF (Regs.AC);                                          \
+    Regs.PC += 3
+
+/* abs,x */
+#define AC_OP_ABSX(op)                                          \
+    unsigned Addr;                                              \
+    Cycles = 4;                                                 \
+    Addr = MemReadWord (Regs.PC+1);                             \
+    if (PAGE_CROSS (Addr, Regs.XR)) {                           \
+        ++Cycles;                                               \
+    }                                                           \
+    Regs.AC = Regs.AC op MemReadByte (Addr + Regs.XR);          \
+    TEST_ZF (Regs.AC);                                          \
+    TEST_SF (Regs.AC);                                          \
+    Regs.PC += 3
+
+/* abs,y */
+#define AC_OP_ABSY(op)                                          \
+    unsigned Addr;                                              \
+    Cycles = 4;                                                 \
+    Addr = MemReadWord (Regs.PC+1);                             \
+    if (PAGE_CROSS (Addr, Regs.YR)) {                           \
+        ++Cycles;                                               \
+    }                                                           \
+    Regs.AC = Regs.AC op MemReadByte (Addr + Regs.YR);          \
+    TEST_ZF (Regs.AC);                                          \
+    TEST_SF (Regs.AC);                                          \
+    Regs.PC += 3
+
+/* (zp,x) */
+#define AC_OP_ZPXIND(op)                                        \
+    unsigned char ZPAddr;                                       \
+    unsigned Addr;                                              \
+    Cycles = 6;                                                 \
+    ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;                 \
+    Addr = MemReadZPWord (ZPAddr);                              \
+    Regs.AC = Regs.AC op MemReadByte (Addr);                    \
+    TEST_ZF (Regs.AC);                                          \
+    TEST_SF (Regs.AC);                                          \
+    Regs.PC += 2
+
+/* (zp),y */
+#define AC_OP_ZPINDY(op)                                        \
+    unsigned char ZPAddr;                                       \
+    unsigned Addr;                                              \
+    Cycles = 5;                                                 \
+    ZPAddr = MemReadByte (Regs.PC+1);                           \
+    Addr = MemReadZPWord (ZPAddr) + Regs.YR;                    \
+    Regs.AC = Regs.AC op MemReadByte (Addr);                    \
+    TEST_ZF (Regs.AC);                                          \
+    TEST_SF (Regs.AC);                                          \
+    Regs.PC += 2
+
+/* ADC */
+#define ADC(v)                                                  \
+    do {                                                        \
+        unsigned old = Regs.AC;                                 \
+        unsigned rhs = (v & 0xFF);                              \
+        if (GET_DF ()) {                                        \
+            unsigned lo;                                        \
+            int res;                                            \
+            lo = (old & 0x0F) + (rhs & 0x0F) + GET_CF ();       \
+            if (lo >= 0x0A) {                                   \
+                lo = ((lo + 0x06) & 0x0F) + 0x10;               \
+            }                                                   \
+            Regs.AC = (old & 0xF0) + (rhs & 0xF0) + lo;         \
+            res = (signed char)(old & 0xF0) +                   \
+                  (signed char)(rhs & 0xF0) +                   \
+                  (signed char)lo;                              \
+            TEST_ZF (old + rhs + GET_CF ());                    \
+            TEST_SF (Regs.AC);                                  \
+            if (Regs.AC >= 0xA0) {                              \
+                Regs.AC += 0x60;                                \
+            }                                                   \
+            TEST_CF (Regs.AC);                                  \
+            SET_OF ((res < -128) || (res > 127));               \
+        } else {                                                \
+            Regs.AC += rhs + GET_CF ();                         \
+            TEST_ZF (Regs.AC);                                  \
+            TEST_SF (Regs.AC);                                  \
+            TEST_CF (Regs.AC);                                  \
+            SET_OF (!((old ^ rhs) & 0x80) &&                    \
+                    ((old ^ Regs.AC) & 0x80));                  \
+            Regs.AC &= 0xFF;                                    \
+        }                                                       \
+    } while (0)
+
+/* branches */
+#define BRANCH(cond)                                            \
+    Cycles = 2;                                                 \
+    if (cond) {                                                 \
+        signed char Offs;                                       \
+        unsigned char OldPCH;                                   \
+        ++Cycles;                                               \
+        Offs = (signed char) MemReadByte (Regs.PC+1);           \
+        OldPCH = PCH;                                           \
+        Regs.PC += 2 + (int) Offs;                              \
+        if (PCH != OldPCH) {                                    \
+            ++Cycles;                                           \
+        }                                                       \
+    } else {                                                    \
+        Regs.PC += 2;                                           \
+    }
+
+/* compares */
+#define CMP(v1,v2)                                              \
+    do {                                                        \
+        unsigned Result = v1 - v2;                              \
+        TEST_ZF (Result & 0xFF);                                \
+        TEST_SF (Result);                                       \
+        SET_CF (Result <= 0xFF);                                \
+    } while (0)
+
+
+/* ROL */
+#define ROL(Val)                                                \
+    Val <<= 1;                                                  \
+    if (GET_CF ()) {                                            \
+        Val |= 0x01;                                            \
+    }                                                           \
+    TEST_ZF (Val);                                              \
+    TEST_SF (Val);                                              \
+    TEST_CF (Val)
+
+/* ROR */
+#define ROR(Val)                                                \
+    if (GET_CF ()) {                                            \
+        Val |= 0x100;                                           \
+    }                                                           \
+    SET_CF (Val & 0x01);                                        \
+    Val >>= 1;                                                  \
+    TEST_ZF (Val);                                              \
+    TEST_SF (Val)
+
+/* SBC */
+#define SBC(v)                                                  \
+    do {                                                        \
+        unsigned old = Regs.AC;                                 \
+        unsigned rhs = (v & 0xFF);                              \
+        if (GET_DF ()) {                                        \
+            unsigned lo;                                        \
+            int res;                                            \
+            lo = (old & 0x0F) - (rhs & 0x0F) + GET_CF () - 1;   \
+            if (lo & 0x80) {                                    \
+                lo = ((lo - 0x06) & 0x0F) - 0x10;               \
+            }                                                   \
+            Regs.AC = (old & 0xF0) - (rhs & 0xF0) + lo;         \
+            if (Regs.AC & 0x80) {                               \
+                Regs.AC -= 0x60;                                \
+            }                                                   \
+            res = Regs.AC - rhs + (!GET_CF ());                 \
+            TEST_ZF (res);                                      \
+            TEST_SF (res);                                      \
+            SET_CF (res <= 0xFF);                               \
+            SET_OF (((old^rhs) & (old^res) & 0x80));            \
+        } else {                                                \
+            Regs.AC -= rhs - (!GET_CF ());                      \
+            TEST_ZF (Regs.AC);                                  \
+            TEST_SF (Regs.AC);                                  \
+            SET_CF (Regs.AC <= 0xFF);                           \
+            SET_OF (((old^rhs) & (old^Regs.AC) & 0x80));        \
+            Regs.AC &= 0xFF;                                    \
+        }                                                       \
+    } while (0)
+
+
+/*****************************************************************************/
+/*                               Helper functions                            */
+/*****************************************************************************/
+
+
+
+static void OPC_Illegal (void)
+{
+    Warning ("Illegal opcode $%02X at address $%04X\n", MemReadByte (Regs.PC), Regs.PC);
+}
+
+
+
+/*****************************************************************************/
+/*                                  Code                                    */
+/*****************************************************************************/
+
+
+
+static void OPC_6502_00 (void)
+/* Opcode $00: BRK */
+{
+    Cycles = 7;
+    Regs.PC += 2;
+    SET_BF (1);
+    PUSH (PCH);
+    PUSH (PCL);
+    PUSH (Regs.SR);
+    SET_IF (1);
+    Regs.PC = MemReadWord (0xFFFE);
+    CPUHalted = 1;
+}
+
+
+
+static void OPC_6502_01 (void)
+/* Opcode $01: ORA (ind,x) */
+{
+    AC_OP_ZPXIND (|);
+}
+
+
+
+static void OPC_6502_05 (void)
+/* Opcode $05: ORA zp */
+{
+    AC_OP_ZP (|);
+}
+
+
+
+static void OPC_6502_06 (void)
+/* Opcode $06: ASL zp */
+{
+    unsigned char ZPAddr;
+    unsigned Val;
+    Cycles = 5;
+    ZPAddr = MemReadByte (Regs.PC+1);
+    Val    = MemReadByte (ZPAddr) << 1;
+    MemWriteByte (ZPAddr, (unsigned char) Val);
+    TEST_ZF (Val & 0xFF);
+    TEST_SF (Val);
+    SET_CF (Val & 0x100);
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_08 (void)
+/* Opcode $08: PHP */
+{
+    Cycles = 3;
+    PUSH (Regs.SR & ~BF);
+    Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_09 (void)
+/* Opcode $09: ORA #imm */
+{
+    AC_OP_IMM (|);
+}
+
+
+
+static void OPC_6502_0A (void)
+/* Opcode $0A: ASL a */
+{
+    Cycles = 2;
+    Regs.AC <<= 1;
+    TEST_ZF (Regs.AC & 0xFF);
+    TEST_SF (Regs.AC);
+    SET_CF (Regs.AC & 0x100);
+    Regs.AC &= 0xFF;
+    Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_0D (void)
+/* Opcode $0D: ORA abs */
+{
+    AC_OP_ABS (|);
+}
+
+
+
+static void OPC_6502_0E (void)
+/* Opcode $0E: ALS abs */
+{
+    unsigned Addr;
+    unsigned Val;
+    Cycles = 6;
+    Addr = MemReadWord (Regs.PC+1);
+    Val  = MemReadByte (Addr) << 1;
+    MemWriteByte (Addr, (unsigned char) Val);
+    TEST_ZF (Val & 0xFF);
+    TEST_SF (Val);
+    SET_CF (Val & 0x100);
+    Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_10 (void)
+/* Opcode $10: BPL */
+{
+    BRANCH (!GET_SF ());
+}
+
+
+
+static void OPC_6502_11 (void)
+/* Opcode $11: ORA (zp),y */
+{
+    AC_OP_ZPINDY (|);
+}
+
+
+
+static void OPC_6502_15 (void)
+/* Opcode $15: ORA zp,x */
+{
+   AC_OP_ZPX (|);
+}
+
+
+
+static void OPC_6502_16 (void)
+/* Opcode $16: ASL zp,x */
+{
+    unsigned char ZPAddr;
+    unsigned Val;
+    Cycles = 6;
+    ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
+    Val    = MemReadByte (ZPAddr) << 1;
+    MemWriteByte (ZPAddr, (unsigned char) Val);
+    TEST_ZF (Val & 0xFF);
+    TEST_SF (Val);
+    SET_CF (Val & 0x100);
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_18 (void)
+/* Opcode $18: CLC */
+{
+    Cycles = 2;
+    SET_CF (0);
+    Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_19 (void)
+/* Opcode $19: ORA abs,y */
+{
+    AC_OP_ABSY (|);
+}
+
+
+
+static void OPC_6502_1D (void)
+/* Opcode $1D: ORA abs,x */
+{
+    AC_OP_ABSX (|);
+}
+
+
+
+static void OPC_6502_1E (void)
+/* Opcode $1E: ASL abs,x */
+{
+    unsigned Addr;
+    unsigned Val;
+    Cycles = 7;
+    Addr = MemReadWord (Regs.PC+1) + Regs.XR;
+    Val  = MemReadByte (Addr) << 1;
+    MemWriteByte (Addr, (unsigned char) Val);
+    TEST_ZF (Val & 0xFF);
+    TEST_SF (Val);
+    SET_CF (Val & 0x100);
+    Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_20 (void)
+/* Opcode $20: JSR */
+{
+    unsigned Addr;
+    Cycles = 6;
+    Addr   = MemReadWord (Regs.PC+1);
+    Regs.PC += 2;
+    PUSH (PCH);
+    PUSH (PCL);
+    Regs.PC = Addr;
+}
+
+
+
+static void OPC_6502_21 (void)
+/* Opcode $21: AND (zp,x) */
+{
+    AC_OP_ZPXIND (&);
+}
+
+
+
+static void OPC_6502_24 (void)
+/* Opcode $24: BIT zp */
+{
+    unsigned char ZPAddr;
+    unsigned char Val;
+    Cycles = 3;
+    ZPAddr = MemReadByte (Regs.PC+1);
+    Val    = MemReadByte (ZPAddr);
+    SET_SF (Val & 0x80);
+    SET_OF (Val & 0x40);
+    SET_ZF ((Val & Regs.AC) == 0);
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_25 (void)
+/* Opcode $25: AND zp */
+{
+    AC_OP_ZP (&);
+}
+
+
+
+static void OPC_6502_26 (void)
+/* Opcode $26: ROL zp */
+{
+    unsigned char ZPAddr;
+    unsigned Val;
+    Cycles = 5;
+    ZPAddr = MemReadByte (Regs.PC+1);
+    Val    = MemReadByte (ZPAddr);
+    ROL (Val);
+    MemWriteByte (ZPAddr, Val);
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_28 (void)
+/* Opcode $28: PLP */
+{
+    Cycles = 4;
+    Regs.SR = (POP () & ~BF);
+    Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_29 (void)
+/* Opcode $29: AND #imm */
+{
+    AC_OP_IMM (&);
+}
+
+
+
+static void OPC_6502_2A (void)
+/* Opcode $2A: ROL a */
+{
+    Cycles = 2;
+    ROL (Regs.AC);
+    Regs.AC &= 0xFF;
+    Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_2C (void)
+/* Opcode $2C: BIT abs */
+{
+    unsigned Addr;
+    unsigned char Val;
+    Cycles = 4;
+    Addr = MemReadByte (Regs.PC+1);
+    Val  = MemReadByte (Addr);
+    SET_SF (Val & 0x80);
+    SET_OF (Val & 0x40);
+    SET_ZF ((Val & Regs.AC) == 0);
+    Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_2D (void)
+/* Opcode $2D: AND abs */
+{
+    AC_OP_ABS (&);
+}
+
+
+
+static void OPC_6502_2E (void)
+/* Opcode $2E: ROL abs */
+{
+    unsigned Addr;
+    unsigned Val;
+    Cycles = 6;
+    Addr = MemReadWord (Regs.PC+1);
+    Val  = MemReadByte (Addr);
+    ROL (Val);
+    MemWriteByte (Addr, Val);
+    Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_30 (void)
+/* Opcode $30: BMI */
+{
+    BRANCH (GET_SF ());
+}
+
+
+
+static void OPC_6502_31 (void)
+/* Opcode $31: AND (zp),y */
+{
+    AC_OP_ZPINDY (&);
+}
+
+
+
+static void OPC_6502_35 (void)
+/* Opcode $35: AND zp,x */
+{
+    AC_OP_ZPX (&);
+}
+
+
+
+static void OPC_6502_36 (void)
+/* Opcode $36: ROL zp,x */
+{
+    unsigned char ZPAddr;
+    unsigned Val;
+    Cycles = 6;
+    ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
+    Val    = MemReadByte (ZPAddr);
+    ROL (Val);
+    MemWriteByte (ZPAddr, Val);
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_38 (void)
+/* Opcode $38: SEC */
+{
+    Cycles = 2;
+    SET_CF (1);
+    Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_39 (void)
+/* Opcode $39: AND abs,y */
+{
+    AC_OP_ABSY (&);
+}
+
+
+
+static void OPC_6502_3D (void)
+/* Opcode $3D: AND abs,x */
+{
+    AC_OP_ABSX (&);
+}
+
+
+
+static void OPC_6502_3E (void)
+/* Opcode $3E: ROL abs,x */
+{
+    unsigned Addr;
+    unsigned Val;
+    Cycles = 7;
+    Addr = MemReadWord (Regs.PC+1) + Regs.XR;
+    Val  = MemReadByte (Addr);
+    ROL (Val);
+    MemWriteByte (Addr, Val);
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_40 (void)
+/* Opcode $40: RTI */
+{
+    Cycles = 6;
+    Regs.SR = POP ();
+    Regs.PC = POP ();                /* PCL */
+    Regs.PC |= (POP () << 8);        /* PCH */
+}
+
+
+
+static void OPC_6502_41 (void)
+/* Opcode $41: EOR (zp,x) */
+{
+    AC_OP_ZPXIND (^);
+}
+
+
+
+static void OPC_6502_45 (void)
+/* Opcode $45: EOR zp */
+{
+    AC_OP_ZP (^);
+}
+
+
+
+static void OPC_6502_46 (void)
+/* Opcode $46: LSR zp */
+{
+    unsigned char ZPAddr;
+    unsigned char Val;
+    Cycles = 5;
+    ZPAddr = MemReadByte (Regs.PC+1);
+    Val    = MemReadByte (ZPAddr);
+    SET_CF (Val & 0x01);
+    Val >>= 1;
+    MemWriteByte (ZPAddr, Val);
+    TEST_ZF (Val);
+    TEST_SF (Val);
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_48 (void)
+/* Opcode $48: PHA */
+{
+    Cycles = 3;
+    PUSH (Regs.AC);
+    Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_49 (void)
+/* Opcode $49: EOR #imm */
+{
+    AC_OP_IMM (^);
+}
+
+
+
+static void OPC_6502_4A (void)
+/* Opcode $4A: LSR a */
+{
+    Cycles = 2;
+    SET_CF (Regs.AC & 0x01);
+    Regs.AC >>= 1;
+    TEST_ZF (Regs.AC);
+    TEST_SF (Regs.AC);
+    Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_4C (void)
+/* Opcode $4C: JMP abs */
+{
+    Cycles = 3;
+    Regs.PC = MemReadWord (Regs.PC+1);
+}
+
+
+
+static void OPC_6502_4D (void)
+/* Opcode $4D: EOR abs */
+{
+    AC_OP_ABS (^);
+}
+
+
+
+static void OPC_6502_4E (void)
+/* Opcode $4E: LSR abs */
+{
+    unsigned Addr;
+    unsigned char Val;
+    Cycles = 6;
+    Addr = MemReadWord (Regs.PC+1);
+    Val  = MemReadByte (Addr);
+    SET_CF (Val & 0x01);
+    Val >>= 1;
+    MemWriteByte (Addr, Val);
+    TEST_ZF (Val);
+    TEST_SF (Val);
+    Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_50 (void)
+/* Opcode $50: BVC */
+{
+    BRANCH (!GET_OF ());
+}
+
+
+
+static void OPC_6502_51 (void)
+/* Opcode $51: EOR (zp),y */
+{
+    AC_OP_ZPINDY (^);
+}
+
+
+
+static void OPC_6502_55 (void)
+/* Opcode $55: EOR zp,x */
+{
+    AC_OP_ZPX (^);
+}
+
+
+
+static void OPC_6502_56 (void)
+/* Opcode $56: LSR zp,x */
+{
+    unsigned char ZPAddr;
+    unsigned char Val;
+    Cycles = 6;
+    ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
+    Val    = MemReadByte (ZPAddr);
+    SET_CF (Val & 0x01);
+    Val >>= 1;
+    MemWriteByte (ZPAddr, Val);
+    TEST_ZF (Val);
+    TEST_SF (Val);
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_58 (void)
+/* Opcode $58: CLI */
+{
+    Cycles = 2;
+    SET_IF (0);
+    Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_59 (void)
+/* Opcode $59: EOR abs,y */
+{
+    AC_OP_ABSY (^);
+}
+
+
+
+static void OPC_6502_5D (void)
+/* Opcode $5D: EOR abs,x */
+{
+    AC_OP_ABSX (^);
+}
+
+
+
+static void OPC_6502_5E (void)
+/* Opcode $5E: LSR abs,x */
+{
+    unsigned Addr;
+    unsigned char Val;
+    Cycles = 7;
+    Addr = MemReadWord (Regs.PC+1) + Regs.XR;
+    Val  = MemReadByte (Addr);
+    SET_CF (Val & 0x01);
+    Val >>= 1;
+    MemWriteByte (Addr, Val);
+    TEST_ZF (Val);
+    TEST_SF (Val);
+    Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_60 (void)
+/* Opcode $60: RTS */
+{
+    Cycles = 6;
+    Regs.PC = POP ();                /* PCL */
+    Regs.PC |= (POP () << 8);        /* PCH */
+    Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_61 (void)
+/* Opcode $61: ADC (zp,x) */
+{
+    unsigned char ZPAddr;
+    unsigned Addr;
+    Cycles = 6;
+    ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
+    Addr   = MemReadZPWord (ZPAddr);
+    ADC (MemReadByte (Addr));
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_65 (void)
+/* Opcode $65: ADC zp */
+{
+    unsigned char ZPAddr;
+    Cycles = 3;
+    ZPAddr = MemReadByte (Regs.PC+1);
+    ADC (MemReadByte (ZPAddr));
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_66 (void)
+/* Opcode $66: ROR zp */
+{
+    unsigned char ZPAddr;
+    unsigned Val;
+    Cycles = 5;
+    ZPAddr = MemReadByte (Regs.PC+1);
+    Val    = MemReadByte (ZPAddr);
+    ROR (Val);
+    MemWriteByte (ZPAddr, Val);
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_68 (void)
+/* Opcode $68: PLA */
+{
+    Cycles = 4;
+    Regs.AC = POP ();
+    TEST_ZF (Regs.AC);
+    TEST_SF (Regs.AC);
+    Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_69 (void)
+/* Opcode $69: ADC #imm */
+{
+    Cycles = 2;
+    ADC (MemReadByte (Regs.PC+1));
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_6A (void)
+/* Opcode $6A: ROR a */
+{
+    Cycles = 2;
+    ROR (Regs.AC);
+    Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_6C (void)
+/* Opcode $6C: JMP (ind) */
+{
+    unsigned Addr;
+    Cycles = 5;
+    Addr = MemReadWord (Regs.PC+1);
+    if (CPU == CPU_6502) {
+        /* Emulate the 6502 bug */
+        Regs.PC = MemReadByte (Addr);
+        Addr = (Addr & 0xFF00) | ((Addr + 1) & 0xFF);
+        Regs.PC |= (MemReadByte (Addr) << 8);
+    } else {
+        /* 65C02 and above have this bug fixed */
+        Regs.PC = MemReadWord (Addr);
+    }
+}
+
+
+
+static void OPC_6502_6D (void)
+/* Opcode $6D: ADC abs */
+{
+    unsigned Addr;
+    Cycles = 4;
+    Addr   = MemReadWord (Regs.PC+1);
+    ADC (MemReadByte (Addr));
+    Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_6E (void)
+/* Opcode $6E: ROR abs */
+{
+    unsigned Addr;
+    unsigned Val;
+    Cycles = 6;
+    Addr = MemReadWord (Regs.PC+1);
+    Val  = MemReadByte (Addr);
+    ROR (Val);
+    MemWriteByte (Addr, Val);
+    Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_70 (void)
+/* Opcode $70: BVS */
+{
+    BRANCH (GET_OF ());
+}
+
+
+
+static void OPC_6502_71 (void)
+/* Opcode $71: ADC (zp),y */
+{
+    unsigned char ZPAddr;
+    unsigned Addr;
+    Cycles = 5;
+    ZPAddr = MemReadByte (Regs.PC+1);
+    Addr   = MemReadZPWord (ZPAddr);
+    if (PAGE_CROSS (Addr, Regs.YR)) {
+        ++Cycles;
+    }
+    ADC (MemReadByte (Addr + Regs.YR));
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_75 (void)
+/* Opcode $75: ADC zp,x */
+{
+    unsigned char ZPAddr;
+    Cycles = 4;
+    ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
+    ADC (MemReadByte (ZPAddr));
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_76 (void)
+/* Opcode $76: ROR zp,x */
+{
+    unsigned char ZPAddr;
+    unsigned Val;
+    Cycles = 6;
+    ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
+    Val    = MemReadByte (ZPAddr);
+    ROR (Val);
+    MemWriteByte (ZPAddr, Val);
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_78 (void)
+/* Opcode $78: SEI */
+{
+    Cycles = 2;
+    SET_IF (1);
+    Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_79 (void)
+/* Opcode $79: ADC abs,y */
+{
+    unsigned Addr;
+    Cycles = 4;
+    Addr   = MemReadWord (Regs.PC+1);
+    if (PAGE_CROSS (Addr, Regs.YR)) {
+        ++Cycles;
+    }
+    ADC (MemReadByte (Addr + Regs.YR));
+    Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_7D (void)
+/* Opcode $7D: ADC abs,x */
+{
+    unsigned Addr;
+    Cycles = 4;
+    Addr   = MemReadWord (Regs.PC+1);
+    if (PAGE_CROSS (Addr, Regs.XR)) {
+        ++Cycles;
+    }
+    ADC (MemReadByte (Addr + Regs.XR));
+    Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_7E (void)
+/* Opcode $7E: ROR abs,x */
+{
+    unsigned Addr;
+    unsigned Val;
+    Cycles = 7;
+    Addr = MemReadByte (Regs.PC+1) + Regs.XR;
+    Val  = MemReadByte (Addr);
+    ROR (Val);
+    MemWriteByte (Addr, Val);
+    Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_81 (void)
+/* Opcode $81: STA (zp,x) */
+{
+    unsigned char ZPAddr;
+    unsigned Addr;
+    Cycles = 6;
+    ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
+    Addr   = MemReadZPWord (ZPAddr);
+    MemWriteByte (Addr, Regs.AC);
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_84 (void)
+/* Opcode $84: STY zp */
+{
+    unsigned char ZPAddr;
+    Cycles = 3;
+    ZPAddr = MemReadByte (Regs.PC+1);
+    MemWriteByte (ZPAddr, Regs.YR);
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_85 (void)
+/* Opcode $85: STA zp */
+{
+    unsigned char ZPAddr;
+    Cycles = 3;
+    ZPAddr = MemReadByte (Regs.PC+1);
+    MemWriteByte (ZPAddr, Regs.AC);
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_86 (void)
+/* Opcode $86: STX zp */
+{
+    unsigned char ZPAddr;
+    Cycles = 3;
+    ZPAddr = MemReadByte (Regs.PC+1);
+    MemWriteByte (ZPAddr, Regs.XR);
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_88 (void)
+/* Opcode $88: DEY */
+{
+    Cycles = 2;
+    Regs.YR = (Regs.YR - 1) & 0xFF;
+    TEST_ZF (Regs.YR);
+    TEST_SF (Regs.YR);
+    Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_8A (void)
+/* Opcode $8A: TXA */
+{
+    Cycles = 2;
+    Regs.AC = Regs.XR;
+    TEST_ZF (Regs.AC);
+    TEST_SF (Regs.AC);
+    Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_8C (void)
+/* Opcode $8C: STY abs */
+{
+    unsigned Addr;
+    Cycles = 4;
+    Addr = MemReadWord (Regs.PC+1);
+    MemWriteByte (Addr, Regs.YR);
+    Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_8D (void)
+/* Opcode $8D: STA abs */
+{
+    unsigned Addr;
+    Cycles = 4;
+    Addr = MemReadWord (Regs.PC+1);
+    MemWriteByte (Addr, Regs.AC);
+    Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_8E (void)
+/* Opcode $8E: STX abs */
+{
+    unsigned Addr;
+    Cycles = 4;
+    Addr = MemReadWord (Regs.PC+1);
+    MemWriteByte (Addr, Regs.XR);
+    Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_90 (void)
+/* Opcode $90: BCC */
+{
+    BRANCH (!GET_CF ());
+}
+
+
+
+static void OPC_6502_91 (void)
+/* Opcode $91: sta (zp),y */
+{
+    unsigned char ZPAddr;
+    unsigned Addr;
+    Cycles = 6;
+    ZPAddr = MemReadByte (Regs.PC+1);
+    Addr   = MemReadZPWord (ZPAddr) + Regs.YR;
+    MemWriteByte (Addr, Regs.AC);
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_94 (void)
+/* Opcode $94: STY zp,x */
+{
+    unsigned char ZPAddr;
+    Cycles = 4;
+    ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
+    MemWriteByte (ZPAddr, Regs.YR);
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_95 (void)
+/* Opcode $95: STA zp,x */
+{
+    unsigned char ZPAddr;
+    Cycles = 4;
+    ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
+    MemWriteByte (ZPAddr, Regs.AC);
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_96 (void)
+/* Opcode $96: stx zp,y */
+{
+    unsigned char ZPAddr;
+    Cycles = 4;
+    ZPAddr = MemReadByte (Regs.PC+1) + Regs.YR;
+    MemWriteByte (ZPAddr, Regs.XR);
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_98 (void)
+/* Opcode $98: TYA */
+{
+    Cycles = 2;
+    Regs.AC = Regs.YR;
+    TEST_ZF (Regs.AC);
+    TEST_SF (Regs.AC);
+    Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_99 (void)
+/* Opcode $99: STA abs,y */
+{
+    unsigned Addr;
+    Cycles = 5;
+    Addr   = MemReadWord (Regs.PC+1) + Regs.YR;
+    MemWriteByte (Addr, Regs.AC);
+    Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_9A (void)
+/* Opcode $9A: TXS */
+{
+    Cycles = 2;
+    Regs.SP = Regs.XR;
+    Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_9D (void)
+/* Opcode $9D: STA abs,x */
+{
+    unsigned Addr;
+    Cycles = 5;
+    Addr   = MemReadWord (Regs.PC+1) + Regs.XR;
+    MemWriteByte (Addr, Regs.AC);
+    Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_A0 (void)
+/* Opcode $A0: LDY #imm */
+{
+    Cycles = 2;
+    Regs.YR = MemReadByte (Regs.PC+1);
+    TEST_ZF (Regs.YR);
+    TEST_SF (Regs.YR);
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_A1 (void)
+/* Opcode $A1: LDA (zp,x) */
+{
+    unsigned char ZPAddr;
+    unsigned Addr;
+    Cycles = 6;
+    ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
+    Addr = MemReadZPWord (ZPAddr);
+    Regs.AC = MemReadByte (Addr);
+    TEST_ZF (Regs.AC);
+    TEST_SF (Regs.AC);
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_A2 (void)
+/* Opcode $A2: LDX #imm */
+{
+    Cycles = 2;
+    Regs.XR = MemReadByte (Regs.PC+1);
+    TEST_ZF (Regs.XR);
+    TEST_SF (Regs.XR);
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_A4 (void)
+/* Opcode $A4: LDY zp */
+{
+    unsigned char ZPAddr;
+    Cycles = 3;
+    ZPAddr = MemReadByte (Regs.PC+1);
+    Regs.YR = MemReadByte (ZPAddr);
+    TEST_ZF (Regs.YR);
+    TEST_SF (Regs.YR);
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_A5 (void)
+/* Opcode $A5: LDA zp */
+{
+    unsigned char ZPAddr;
+    Cycles = 3;
+    ZPAddr = MemReadByte (Regs.PC+1);
+    Regs.AC = MemReadByte (ZPAddr);
+    TEST_ZF (Regs.AC);
+    TEST_SF (Regs.AC);
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_A6 (void)
+/* Opcode $A6: LDX zp */
+{
+    unsigned char ZPAddr;
+    Cycles = 3;
+    ZPAddr = MemReadByte (Regs.PC+1);
+    Regs.XR = MemReadByte (ZPAddr);
+    TEST_ZF (Regs.XR);
+    TEST_SF (Regs.XR);
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_A8 (void)
+/* Opcode $A8: TAY */
+{
+    Cycles = 2;
+    Regs.YR = Regs.AC;
+    TEST_ZF (Regs.YR);
+    TEST_SF (Regs.YR);
+    Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_A9 (void)
+/* Opcode $A9: LDA #imm */
+{
+    Cycles = 2;
+    Regs.AC = MemReadByte (Regs.PC+1);
+    TEST_ZF (Regs.AC);
+    TEST_SF (Regs.AC);
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_AA (void)
+/* Opcode $AA: TAX */
+{
+    Cycles = 2;
+    Regs.XR = Regs.AC;
+    TEST_ZF (Regs.XR);
+    TEST_SF (Regs.XR);
+    Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_AC (void)
+/* Opcode $Regs.AC: LDY abs */
+{
+    unsigned Addr;
+    Cycles = 4;
+    Addr   = MemReadWord (Regs.PC+1);
+    Regs.YR     = MemReadByte (Addr);
+    TEST_ZF (Regs.YR);
+    TEST_SF (Regs.YR);
+    Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_AD (void)
+/* Opcode $AD: LDA abs */
+{
+    unsigned Addr;
+    Cycles = 4;
+    Addr   = MemReadWord (Regs.PC+1);
+    Regs.AC     = MemReadByte (Addr);
+    TEST_ZF (Regs.AC);
+    TEST_SF (Regs.AC);
+    Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_AE (void)
+/* Opcode $AE: LDX abs */
+{
+    unsigned Addr;
+    Cycles = 4;
+    Addr   = MemReadWord (Regs.PC+1);
+    Regs.XR     = MemReadByte (Addr);
+    TEST_ZF (Regs.XR);
+    TEST_SF (Regs.XR);
+    Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_B0 (void)
+/* Opcode $B0: BCS */
+{
+    BRANCH (GET_CF ());
+}
+
+
+
+static void OPC_6502_B1 (void)
+/* Opcode $B1: LDA (zp),y */
+{
+    unsigned char ZPAddr;
+    unsigned Addr;
+    Cycles = 5;
+    ZPAddr = MemReadByte (Regs.PC+1);
+    Addr   = MemReadZPWord (ZPAddr);
+    if (PAGE_CROSS (Addr, Regs.YR)) {
+        ++Cycles;
+    }
+    Regs.AC = MemReadByte (Addr + Regs.YR);
+    TEST_ZF (Regs.AC);
+    TEST_SF (Regs.AC);
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_B4 (void)
+/* Opcode $B4: LDY zp,x */
+{
+    unsigned char ZPAddr;
+    Cycles = 4;
+    ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
+    Regs.YR     = MemReadByte (ZPAddr);
+    TEST_ZF (Regs.YR);
+    TEST_SF (Regs.YR);
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_B5 (void)
+/* Opcode $B5: LDA zp,x */
+{
+    unsigned char ZPAddr;
+    Cycles = 4;
+    ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
+    Regs.AC     = MemReadByte (ZPAddr);
+    TEST_ZF (Regs.AC);
+    TEST_SF (Regs.AC);
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_B6 (void)
+/* Opcode $B6: LDX zp,y */
+{
+    unsigned char ZPAddr;
+    Cycles = 4;
+    ZPAddr = MemReadByte (Regs.PC+1) + Regs.YR;
+    Regs.XR     = MemReadByte (ZPAddr);
+    TEST_ZF (Regs.XR);
+    TEST_SF (Regs.XR);
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_B8 (void)
+/* Opcode $B8: CLV */
+{
+    Cycles = 2;
+    SET_OF (0);
+    Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_B9 (void)
+/* Opcode $B9: LDA abs,y */
+{
+    unsigned Addr;
+    Cycles = 4;
+    Addr = MemReadWord (Regs.PC+1);
+    if (PAGE_CROSS (Addr, Regs.YR)) {
+        ++Cycles;
+    }
+    Regs.AC = MemReadByte (Addr + Regs.YR);
+    TEST_ZF (Regs.AC);
+    TEST_SF (Regs.AC);
+    Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_BA (void)
+/* Opcode $BA: TSX */
+{
+    Cycles = 2;
+    Regs.XR = Regs.SP;
+    TEST_ZF (Regs.XR);
+    TEST_SF (Regs.XR);
+    Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_BC (void)
+/* Opcode $BC: LDY abs,x */
+{
+    unsigned Addr;
+    Cycles = 4;
+    Addr = MemReadWord (Regs.PC+1);
+    if (PAGE_CROSS (Addr, Regs.XR)) {
+        ++Cycles;
+    }
+    Regs.YR = MemReadByte (Addr + Regs.XR);
+    TEST_ZF (Regs.YR);
+    TEST_SF (Regs.YR);
+    Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_BD (void)
+/* Opcode $BD: LDA abs,x */
+{
+    unsigned Addr;
+    Cycles = 4;
+    Addr = MemReadWord (Regs.PC+1);
+    if (PAGE_CROSS (Addr, Regs.XR)) {
+        ++Cycles;
+    }
+    Regs.AC = MemReadByte (Addr + Regs.XR);
+    TEST_ZF (Regs.AC);
+    TEST_SF (Regs.AC);
+    Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_BE (void)
+/* Opcode $BE: LDX abs,y */
+{
+    unsigned Addr;
+    Cycles = 4;
+    Addr = MemReadWord (Regs.PC+1);
+    if (PAGE_CROSS (Addr, Regs.YR)) {
+        ++Cycles;
+    }
+    Regs.XR = MemReadByte (Addr + Regs.YR);
+    TEST_ZF (Regs.XR);
+    TEST_SF (Regs.XR);
+    Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_C0 (void)
+/* Opcode $C0: CPY #imm */
+{
+    Cycles = 2;
+    CMP (Regs.YR, MemReadByte (Regs.PC+1));
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_C1 (void)
+/* Opcode $C1: CMP (zp,x) */
+{
+    unsigned char ZPAddr;
+    unsigned Addr;
+    Cycles = 6;
+    ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
+    Addr   = MemReadZPWord (ZPAddr);
+    CMP (Regs.AC, MemReadByte (Addr));
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_C4 (void)
+/* Opcode $C4: CPY zp */
+{
+    unsigned char ZPAddr;
+    Cycles = 3;
+    ZPAddr = MemReadByte (Regs.PC+1);
+    CMP (Regs.YR, MemReadByte (ZPAddr));
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_C5 (void)
+/* Opcode $C5: CMP zp */
+{
+    unsigned char ZPAddr;
+    Cycles = 3;
+    ZPAddr = MemReadByte (Regs.PC+1);
+    CMP (Regs.AC, MemReadByte (ZPAddr));
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_C6 (void)
+/* Opcode $C6: DEC zp */
+{
+    unsigned char ZPAddr;
+    unsigned char Val;
+    Cycles = 5;
+    ZPAddr = MemReadByte (Regs.PC+1);
+    Val    = MemReadByte (ZPAddr) - 1;
+    MemWriteByte (ZPAddr, Val);
+    TEST_ZF (Val);
+    TEST_SF (Val);
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_C8 (void)
+/* Opcode $C8: INY */
+{
+    Cycles = 2;
+    Regs.YR = (Regs.YR + 1) & 0xFF;
+    TEST_ZF (Regs.YR);
+    TEST_SF (Regs.YR);
+    Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_C9 (void)
+/* Opcode $C9: CMP #imm */
+{
+    Cycles = 2;
+    CMP (Regs.AC, MemReadByte (Regs.PC+1));
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_CA (void)
+/* Opcode $CA: DEX */
+{
+    Cycles = 2;
+    Regs.XR = (Regs.XR - 1) & 0xFF;
+    TEST_ZF (Regs.XR);
+    TEST_SF (Regs.XR);
+    Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_CC (void)
+/* Opcode $CC: CPY abs */
+{
+    unsigned Addr;
+    Cycles = 4;
+    Addr   = MemReadWord (Regs.PC+1);
+    CMP (Regs.YR, MemReadByte (Addr));
+    Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_CD (void)
+/* Opcode $CD: CMP abs */
+{
+    unsigned Addr;
+    Cycles = 4;
+    Addr   = MemReadWord (Regs.PC+1);
+    CMP (Regs.AC, MemReadByte (Addr));
+    Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_CE (void)
+/* Opcode $CE: DEC abs */
+{
+    unsigned Addr;
+    unsigned char Val;
+    Cycles = 6;
+    Addr = MemReadWord (Regs.PC+1);
+    Val  = MemReadByte (Addr) - 1;
+    MemWriteByte (Addr, Val);
+    TEST_ZF (Val);
+    TEST_SF (Val);
+    Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_D0 (void)
+/* Opcode $D0: BNE */
+{
+    BRANCH (!GET_ZF ());
+}
+
+
+
+static void OPC_6502_D1 (void)
+/* Opcode $D1: CMP (zp),y */
+{
+    unsigned ZPAddr;
+    unsigned Addr;
+    Cycles = 5;
+    ZPAddr = MemReadByte (Regs.PC+1);
+    Addr   = MemReadWord (ZPAddr);
+    if (PAGE_CROSS (Addr, Regs.YR)) {
+        ++Cycles;
+    }
+    CMP (Regs.AC, MemReadByte (Addr + Regs.YR));
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_D5 (void)
+/* Opcode $D5: CMP zp,x */
+{
+    unsigned char ZPAddr;
+    Cycles = 4;
+    ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
+    CMP (Regs.AC, MemReadByte (ZPAddr));
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_D6 (void)
+/* Opcode $D6: DEC zp,x */
+{
+    unsigned char ZPAddr;
+    unsigned char Val;
+    Cycles = 6;
+    ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
+    Val  = MemReadByte (ZPAddr) - 1;
+    MemWriteByte (ZPAddr, Val);
+    TEST_ZF (Val);
+    TEST_SF (Val);
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_D8 (void)
+/* Opcode $D8: CLD */
+{
+    Cycles = 2;
+    SET_DF (0);
+    Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_D9 (void)
+/* Opcode $D9: CMP abs,y */
+{
+    unsigned Addr;
+    Cycles = 4;
+    Addr = MemReadWord (Regs.PC+1);
+    if (PAGE_CROSS (Addr, Regs.YR)) {
+        ++Cycles;
+    }
+    CMP (Regs.AC, MemReadByte (Addr + Regs.YR));
+    Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_DD (void)
+/* Opcode $DD: CMP abs,x */
+{
+    unsigned Addr;
+    Cycles = 4;
+    Addr = MemReadWord (Regs.PC+1);
+    if (PAGE_CROSS (Addr, Regs.XR)) {
+        ++Cycles;
+    }
+    CMP (Regs.AC, MemReadByte (Addr + Regs.XR));
+    Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_DE (void)
+/* Opcode $DE: DEC abs,x */
+{
+    unsigned Addr;
+    unsigned char Val;
+    Cycles = 7;
+    Addr = MemReadWord (Regs.PC+1) + Regs.XR;
+    Val  = MemReadByte (Addr) - 1;
+    MemWriteByte (Addr, Val);
+    TEST_ZF (Val);
+    TEST_SF (Val);
+    Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_E0 (void)
+/* Opcode $E0: CPX #imm */
+{
+    Cycles = 2;
+    CMP (Regs.XR, MemReadByte (Regs.PC+1));
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_E1 (void)
+/* Opcode $E1: SBC (zp,x) */
+{
+    unsigned char ZPAddr;
+    unsigned Addr;
+    Cycles = 6;
+    ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
+    Addr   = MemReadZPWord (ZPAddr);
+    SBC (MemReadByte (Addr));
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_E4 (void)
+/* Opcode $E4: CPX zp */
+{
+    unsigned char ZPAddr;
+    Cycles = 3;
+    ZPAddr = MemReadByte (Regs.PC+1);
+    CMP (Regs.XR, MemReadByte (ZPAddr));
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_E5 (void)
+/* Opcode $E5: SBC zp */
+{
+    unsigned char ZPAddr;
+    Cycles = 3;
+    ZPAddr = MemReadByte (Regs.PC+1);
+    SBC (MemReadByte (ZPAddr));
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_E6 (void)
+/* Opcode $E6: INC zp */
+{
+    unsigned char ZPAddr;
+    unsigned char Val;
+    Cycles = 5;
+    ZPAddr = MemReadByte (Regs.PC+1);
+    Val    = MemReadByte (ZPAddr) + 1;
+    MemWriteByte (ZPAddr, Val);
+    TEST_ZF (Val);
+    TEST_SF (Val);
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_E8 (void)
+/* Opcode $E8: INX */
+{
+    Cycles = 2;
+    Regs.XR = (Regs.XR + 1) & 0xFF;
+    TEST_ZF (Regs.XR);
+    TEST_SF (Regs.XR);
+    Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_E9 (void)
+/* Opcode $E9: SBC #imm */
+{
+    Cycles = 2;
+    SBC (MemReadByte (Regs.PC+1));
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_EA (void)
+/* Opcode $EA: NOP */
+{
+    /* This one is easy... */
+    Cycles = 2;
+    Regs.PC += 1;
+}
+
+
+
+static void OPC_6502_EC (void)
+/* Opcode $EC: CPX abs */
+{
+    unsigned Addr;
+    Cycles = 4;
+    Addr   = MemReadWord (Regs.PC+1);
+    CMP (Regs.XR, MemReadByte (Addr));
+    Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_ED (void)
+/* Opcode $ED: SBC abs */
+{
+    unsigned Addr;
+    Cycles = 4;
+    Addr   = MemReadWord (Regs.PC+1);
+    SBC (MemReadByte (Addr));
+    Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_EE (void)
+/* Opcode $EE: INC abs */
+{
+    unsigned Addr;
+    unsigned char Val;
+    Cycles = 6;
+    Addr = MemReadWord (Regs.PC+1);
+    Val  = MemReadByte (Addr) + 1;
+    MemWriteByte (Addr, Val);
+    TEST_ZF (Val);
+    TEST_SF (Val);
+    Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_F0 (void)
+/* Opcode $F0: BEQ */
+{
+    BRANCH (GET_ZF ());
+}
+
+
+
+static void OPC_6502_F1 (void)
+/* Opcode $F1: SBC (zp),y */
+{
+    unsigned char ZPAddr;
+    unsigned Addr;
+    Cycles = 5;
+    ZPAddr = MemReadByte (Regs.PC+1);
+    Addr   = MemReadZPWord (ZPAddr);
+    if (PAGE_CROSS (Addr, Regs.YR)) {
+        ++Cycles;
+    }
+    SBC (MemReadByte (Addr + Regs.YR));
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_F5 (void)
+/* Opcode $F5: SBC zp,x */
+{
+    unsigned char ZPAddr;
+    Cycles = 4;
+    ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
+    SBC (MemReadByte (ZPAddr));
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_F6 (void)
+/* Opcode $F6: INC zp,x */
+{
+    unsigned char ZPAddr;
+    unsigned char Val;
+    Cycles = 6;
+    ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
+    Val  = MemReadByte (ZPAddr) + 1;
+    MemWriteByte (ZPAddr, Val);
+    TEST_ZF (Val);
+    TEST_SF (Val);
+    Regs.PC += 2;
+}
+
+
+
+static void OPC_6502_F8 (void)
+/* Opcode $F8: SED */
+{
+    SET_DF (1);
+}
+
+
+
+static void OPC_6502_F9 (void)
+/* Opcode $F9: SBC abs,y */
+{
+    unsigned Addr;
+    Cycles = 4;
+    Addr   = MemReadWord (Regs.PC+1);
+    if (PAGE_CROSS (Addr, Regs.YR)) {
+        ++Cycles;
+    }
+    SBC (MemReadByte (Addr + Regs.YR));
+    Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_FD (void)
+/* Opcode $FD: SBC abs,x */
+{
+    unsigned Addr;
+    Cycles = 4;
+    Addr   = MemReadWord (Regs.PC+1);
+    if (PAGE_CROSS (Addr, Regs.XR)) {
+        ++Cycles;
+    }
+    SBC (MemReadByte (Addr + Regs.XR));
+    Regs.PC += 3;
+}
+
+
+
+static void OPC_6502_FE (void)
+/* Opcode $FE: INC abs,x */
+{
+    unsigned Addr;
+    unsigned char Val;
+    Cycles = 7;
+    Addr = MemReadWord (Regs.PC+1) + Regs.XR;
+    Val  = MemReadByte (Addr) + 1;
+    MemWriteByte (Addr, Val);
+    TEST_ZF (Val);
+    TEST_SF (Val);
+    Regs.PC += 3;
+}
+
+
+
+/*****************************************************************************/
+/*                                  Data                                    */
+/*****************************************************************************/
+
+
+
+/* Opcode handler table */
+typedef void (*OPCFunc) (void);
+static OPCFunc OPCTable[256] = {
+    OPC_6502_00,
+    OPC_6502_01,
+    OPC_Illegal,
+    OPC_Illegal,
+    OPC_Illegal,
+    OPC_6502_05,
+    OPC_6502_06,
+    OPC_Illegal,
+    OPC_6502_08,
+    OPC_6502_09,
+    OPC_6502_0A,
+    OPC_Illegal,
+    OPC_Illegal,
+    OPC_6502_0D,
+    OPC_6502_0E,
+    OPC_Illegal,
+    OPC_6502_10,
+    OPC_6502_11,
+    OPC_Illegal,
+    OPC_Illegal,
+    OPC_Illegal,
+    OPC_6502_15,
+    OPC_6502_16,
+    OPC_Illegal,
+    OPC_6502_18,
+    OPC_6502_19,
+    OPC_Illegal,
+    OPC_Illegal,
+    OPC_Illegal,
+    OPC_6502_1D,
+    OPC_6502_1E,
+    OPC_Illegal,
+    OPC_6502_20,
+    OPC_6502_21,
+    OPC_Illegal,
+    OPC_Illegal,
+    OPC_6502_24,
+    OPC_6502_25,
+    OPC_6502_26,
+    OPC_Illegal,
+    OPC_6502_28,
+    OPC_6502_29,
+    OPC_6502_2A,
+    OPC_Illegal,
+    OPC_6502_2C,
+    OPC_6502_2D,
+    OPC_6502_2E,
+    OPC_Illegal,
+    OPC_6502_30,
+    OPC_6502_31,
+    OPC_Illegal,
+    OPC_Illegal,
+    OPC_Illegal,
+    OPC_6502_35,
+    OPC_6502_36,
+    OPC_Illegal,
+    OPC_6502_38,
+    OPC_6502_39,
+    OPC_Illegal,
+    OPC_Illegal,
+    OPC_Illegal,
+    OPC_6502_3D,
+    OPC_6502_3E,
+    OPC_Illegal,
+    OPC_6502_40,
+    OPC_6502_41,
+    OPC_Illegal,
+    OPC_Illegal,
+    OPC_Illegal,
+    OPC_6502_45,
+    OPC_6502_46,
+    OPC_Illegal,
+    OPC_6502_48,
+    OPC_6502_49,
+    OPC_6502_4A,
+    OPC_Illegal,
+    OPC_6502_4C,
+    OPC_6502_4D,
+    OPC_6502_4E,
+    OPC_Illegal,
+    OPC_6502_50,
+    OPC_6502_51,
+    OPC_Illegal,
+    OPC_Illegal,
+    OPC_Illegal,
+    OPC_6502_55,
+    OPC_6502_56,
+    OPC_Illegal,
+    OPC_6502_58,
+    OPC_6502_59,
+    OPC_Illegal,
+    OPC_Illegal,
+    OPC_Illegal,
+    OPC_6502_5D,
+    OPC_6502_5E,
+    OPC_Illegal,
+    OPC_6502_60,
+    OPC_6502_61,
+    OPC_Illegal,
+    OPC_Illegal,
+    OPC_Illegal,
+    OPC_6502_65,
+    OPC_6502_66,
+    OPC_Illegal,
+    OPC_6502_68,
+    OPC_6502_69,
+    OPC_6502_6A,
+    OPC_Illegal,
+    OPC_6502_6C,
+    OPC_6502_6D,
+    OPC_6502_6E,
+    OPC_Illegal,
+    OPC_6502_70,
+    OPC_6502_71,
+    OPC_Illegal,
+    OPC_Illegal,
+    OPC_Illegal,
+    OPC_6502_75,
+    OPC_6502_76,
+    OPC_Illegal,
+    OPC_6502_78,
+    OPC_6502_79,
+    OPC_Illegal,
+    OPC_Illegal,
+    OPC_Illegal,
+    OPC_6502_7D,
+    OPC_6502_7E,
+    OPC_Illegal,
+    OPC_Illegal,
+    OPC_6502_81,
+    OPC_Illegal,
+    OPC_Illegal,
+    OPC_6502_84,
+    OPC_6502_85,
+    OPC_6502_86,
+    OPC_Illegal,
+    OPC_6502_88,
+    OPC_Illegal,
+    OPC_6502_8A,
+    OPC_Illegal,
+    OPC_6502_8C,
+    OPC_6502_8D,
+    OPC_6502_8E,
+    OPC_Illegal,
+    OPC_6502_90,
+    OPC_6502_91,
+    OPC_Illegal,
+    OPC_Illegal,
+    OPC_6502_94,
+    OPC_6502_95,
+    OPC_6502_96,
+    OPC_Illegal,
+    OPC_6502_98,
+    OPC_6502_99,
+    OPC_6502_9A,
+    OPC_Illegal,
+    OPC_Illegal,
+    OPC_6502_9D,
+    OPC_Illegal,
+    OPC_Illegal,
+    OPC_6502_A0,
+    OPC_6502_A1,
+    OPC_6502_A2,
+    OPC_Illegal,
+    OPC_6502_A4,
+    OPC_6502_A5,
+    OPC_6502_A6,
+    OPC_Illegal,
+    OPC_6502_A8,
+    OPC_6502_A9,
+    OPC_6502_AA,
+    OPC_Illegal,
+    OPC_6502_AC,
+    OPC_6502_AD,
+    OPC_6502_AE,
+    OPC_Illegal,
+    OPC_6502_B0,
+    OPC_6502_B1,
+    OPC_Illegal,
+    OPC_Illegal,
+    OPC_6502_B4,
+    OPC_6502_B5,
+    OPC_6502_B6,
+    OPC_Illegal,
+    OPC_6502_B8,
+    OPC_6502_B9,
+    OPC_6502_BA,
+    OPC_Illegal,
+    OPC_6502_BC,
+    OPC_6502_BD,
+    OPC_6502_BE,
+    OPC_Illegal,
+    OPC_6502_C0,
+    OPC_6502_C1,
+    OPC_Illegal,
+    OPC_Illegal,
+    OPC_6502_C4,
+    OPC_6502_C5,
+    OPC_6502_C6,
+    OPC_Illegal,
+    OPC_6502_C8,
+    OPC_6502_C9,
+    OPC_6502_CA,
+    OPC_Illegal,
+    OPC_6502_CC,
+    OPC_6502_CD,
+    OPC_6502_CE,
+    OPC_Illegal,
+    OPC_6502_D0,
+    OPC_6502_D1,
+    OPC_Illegal,
+    OPC_Illegal,
+    OPC_Illegal,
+    OPC_6502_D5,
+    OPC_6502_D6,
+    OPC_Illegal,
+    OPC_6502_D8,
+    OPC_6502_D9,
+    OPC_Illegal,
+    OPC_Illegal,
+    OPC_Illegal,
+    OPC_6502_DD,
+    OPC_6502_DE,
+    OPC_Illegal,
+    OPC_6502_E0,
+    OPC_6502_E1,
+    OPC_Illegal,
+    OPC_Illegal,
+    OPC_6502_E4,
+    OPC_6502_E5,
+    OPC_6502_E6,
+    OPC_Illegal,
+    OPC_6502_E8,
+    OPC_6502_E9,
+    OPC_6502_EA,
+    OPC_Illegal,
+    OPC_6502_EC,
+    OPC_6502_ED,
+    OPC_6502_EE,
+    OPC_Illegal,
+    OPC_6502_F0,
+    OPC_6502_F1,
+    OPC_Illegal,
+    OPC_Illegal,
+    OPC_Illegal,
+    OPC_6502_F5,
+    OPC_6502_F6,
+    OPC_Illegal,
+    OPC_6502_F8,
+    OPC_6502_F9,
+    OPC_Illegal,
+    OPC_Illegal,
+    OPC_Illegal,
+    OPC_6502_FD,
+    OPC_6502_FE,
+    OPC_Illegal,
+};
+
+
+
+/*****************************************************************************/
+/*                                  Code                                    */
+/*****************************************************************************/
+
+
+
+void CPUInit (void)
+/* Initialize the CPU */
+{
+    RESET ();
+}
+
+
+
+void IRQRequest (void)
+/* Generate an IRQ */
+{
+    HaveIRQRequest = 1;
+}
+
+
+
+void NMIRequest (void)
+/* Generate an NMI */
+{
+    HaveNMIRequest = 1;
+}
+
+
+
+void RESET (void)
+/* Generate a CPU RESET */
+{
+    CPUHalted = HaveIRQRequest = HaveNMIRequest = 0;
+    Regs.PC = MemReadWord (0xFFFC);
+}
+
+
+
+void Break (const char* Format, ...)
+/* Stop running and display the given message */
+{
+    va_list ap;
+    va_start (ap, Format);
+    SB_VPrintf (&BreakMsg, Format, ap);
+    va_end (ap);
+}
+
+
+
+void CPURun (void)
+/* Run one CPU instruction */
+{
+    /* If the CPU is halted, do nothing */
+    if (CPUHalted) {
+        return;
+    }
+
+    /* If we have an NMI request, handle it */
+    if (HaveNMIRequest) {
+
+        HaveNMIRequest = 0;
+        PUSH (PCH);
+        PUSH (PCL);
+        PUSH (Regs.SR);
+        SET_IF (1);
+        Regs.PC = MemReadWord (0xFFFA);
+        Cycles = 7;
+
+    } else if (HaveIRQRequest && GET_IF () == 0) {
+
+        HaveIRQRequest = 0;
+        PUSH (PCH);
+        PUSH (PCL);
+        PUSH (Regs.SR);
+        SET_IF (1);
+        Regs.PC = MemReadWord (0xFFFE);
+        Cycles = 7;
+
+    } else {
+
+        /* Normal instruction - read the next opcode */
+        unsigned char OPC = MemReadByte (Regs.PC);
+
+        /* Execute it */
+        OPCTable[OPC] ();
+
+    }
+
+    /* Count cycles */
+    TotalCycles += Cycles;
+
+    if (SB_GetLen (&BreakMsg) > 0) {
+        printf ("%.*s\n", SB_GetLen (&BreakMsg), SB_GetConstBuf (&BreakMsg));
+        SB_Clear (&BreakMsg);
+    }
+}
+
+
+
+#if 0
+    if ((++I & 0xFF) == 0)
+    printf ("%9lu %06X %02X A=%02X X=%02X Y=%02X %c%c%c%c%c%c%c\n",
+            TotalCycles, Regs.PC, OPC, Regs.AC, Regs.XR, Regs.YR,
+            GET_SF()? 'S' : '-',
+            GET_ZF()? 'Z' : '-',
+            GET_CF()? 'C' : '-',
+            GET_IF()? 'I' : '-',
+            GET_BF()? 'B' : '-',
+            GET_DF()? 'D' : '-',
+            GET_OF()? 'V' : '-');
+#endif
+
+
diff --git a/src/sim65/cpu-6502.h b/src/sim65/cpu-6502.h
new file mode 100644 (file)
index 0000000..b886171
--- /dev/null
@@ -0,0 +1,88 @@
+/*****************************************************************************/
+/*                                                                           */
+/*                                   cpucore.h                               */
+/*                                                                           */
+/*                        CPU core for the 6502 simulator                    */
+/*                                                                           */
+/*                                                                           */
+/*                                                                           */
+/* (C) 2002-2003 Ullrich von Bassewitz                                       */
+/*               Römerstrasse 52                                             */
+/*               D-70794 Filderstadt                                         */
+/* EMail:        uz@cc65.org                                                 */
+/*                                                                           */
+/*                                                                           */
+/* This software is provided 'as-is', without any expressed or implied       */
+/* warranty.  In no event will the authors be held liable for any damages    */
+/* arising from the use of this software.                                    */
+/*                                                                           */
+/* Permission is granted to anyone to use this software for any purpose,     */
+/* including commercial applications, and to alter it and redistribute it    */
+/* freely, subject to the following restrictions:                            */
+/*                                                                           */
+/* 1. The origin of this software must not be misrepresented; you must not   */
+/*    claim that you wrote the original software. If you use this software   */
+/*    in a product, an acknowledgment in the product documentation would be  */
+/*    appreciated but is not required.                                       */
+/* 2. Altered source versions must be plainly marked as such, and must not   */
+/*    be misrepresented as being the original software.                      */
+/* 3. This notice may not be removed or altered from any source              */
+/*    distribution.                                                          */
+/*                                                                           */
+/*****************************************************************************/
+
+
+
+#ifndef CPUCORE_H
+#define CPUCORE_H
+
+
+
+/* sim65 */
+#include "cpuregs.h"
+
+
+
+/*****************************************************************************/
+/*                                  Data                                    */
+/*****************************************************************************/
+
+
+
+/* Registers */
+extern CPURegs Regs;
+
+
+
+/*****************************************************************************/
+/*                                  Code                                    */
+/*****************************************************************************/
+
+
+
+void CPUInit (void);
+/* Initialize the CPU */
+
+void RESET (void);
+/* Generate a CPU RESET */
+
+void IRQRequest (void);
+/* Generate an IRQ */
+
+void NMIRequest (void);
+/* Generate an NMI */
+
+void Break (const char* Format, ...);
+/* Stop running and display the given message */
+
+void CPURun (void);
+/* Run one CPU instruction */
+
+
+
+/* End of cpucore.h */
+
+#endif
+
+
+
index 39929634dac2664b6948473246e1eaf9d6e86221..e4e189f6d1c91c19d53bbeab020a5d6ce91816ee 100644 (file)
@@ -1,8 +1,8 @@
 /*****************************************************************************/
 /*                                                                           */
-/*                                   cpucore.c                               */
+/*                                 cpucore.c                                 */
 /*                                                                           */
-/*                        CPU core for the 6502 simulator                    */
+/*                     CPU definition for the simulator                      */
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
 
 
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
+#include <string.h>
 
 /* common */
-#include "abend.h"
-#include "attrib.h"
-#include "print.h"
-#include "strbuf.h"
+#include "xmalloc.h"
 
 /* sim65 */
-#include "cpuregs.h"
-#include "cputype.h"
-#include "error.h"
-#include "global.h"
-#include "memory.h"
-#include "cpucore.h"
-
-
-
-/*****************************************************************************/
-/*                                  Data                                    */
-/*****************************************************************************/
-
-
-
-/* Registers */
-CPURegs Regs;
-
-/* Count the total number of cylcles */
-unsigned       Cycles;         /* Cycles per insn */
-unsigned long  TotalCycles;    /* Total cycles */
-
-/* Allow the stack page to be changed */
-static unsigned StackPage = 0x100;
-
-/* CPU flags */
-int HaveNMIRequest = 0;
-int HaveIRQRequest = 0;
-int CPUHalted      = 0;
-
-/* Break message */
-static StrBuf BreakMsg = STATIC_STRBUF_INITIALIZER;
-
-
-
-/*****************************************************************************/
-/*                       Helper functions and macros                        */
-/*****************************************************************************/
-
-
-
-/* Return the flags as a boolean value (0/1) */
-#define GET_CF()        ((Regs.SR & CF) != 0)
-#define GET_ZF()        ((Regs.SR & ZF) != 0)
-#define GET_IF()        ((Regs.SR & IF) != 0)
-#define GET_DF()        ((Regs.SR & DF) != 0)
-#define GET_BF()        ((Regs.SR & BF) != 0)
-#define GET_OF()        ((Regs.SR & OF) != 0)
-#define GET_SF()        ((Regs.SR & SF) != 0)
-
-/* Set the flags. The parameter is a boolean flag that says if the flag should be
- * set or reset.
- */
-#define SET_CF(f)       do { if (f) { Regs.SR |= CF; } else { Regs.SR &= ~CF; } } while (0)
-#define SET_ZF(f)       do { if (f) { Regs.SR |= ZF; } else { Regs.SR &= ~ZF; } } while (0)
-#define SET_IF(f)       do { if (f) { Regs.SR |= IF; } else { Regs.SR &= ~IF; } } while (0)
-#define SET_DF(f)       do { if (f) { Regs.SR |= DF; } else { Regs.SR &= ~DF; } } while (0)
-#define SET_BF(f)       do { if (f) { Regs.SR |= BF; } else { Regs.SR &= ~BF; } } while (0)
-#define SET_OF(f)       do { if (f) { Regs.SR |= OF; } else { Regs.SR &= ~OF; } } while (0)
-#define SET_SF(f)       do { if (f) { Regs.SR |= SF; } else { Regs.SR &= ~SF; } } while (0)
-
-/* Special test and set macros. The meaning of the parameter depends on the
- * actual flag that should be set or reset.
- */
-#define TEST_ZF(v)      SET_ZF (((v) & 0xFF) == 0)
-#define TEST_SF(v)      SET_SF (((v) & 0x80) != 0)
-#define TEST_CF(v)      SET_CF (((v) & 0xFF00) != 0)
-
-/* Program counter halves */
-#define PCL            (Regs.PC & 0xFF)
-#define PCH            ((Regs.PC >> 8) & 0xFF)
-
-/* Stack operations */
-#define PUSH(Val)       MemWriteByte (StackPage + Regs.SP--, Val)
-#define POP()           MemReadByte (StackPage + ++Regs.SP)
-
-/* Test for page cross */
-#define PAGE_CROSS(addr,offs)   ((((addr) & 0xFF) + offs) >= 0x100)
-
-/* #imm */
-#define AC_OP_IMM(op)                                           \
-    Cycles = 2;                                                 \
-    Regs.AC = Regs.AC op MemReadByte (Regs.PC+1);               \
-    TEST_ZF (Regs.AC);                                          \
-    TEST_SF (Regs.AC);                                          \
-    Regs.PC += 2
-
-/* zp */
-#define AC_OP_ZP(op)                                            \
-    Cycles = 3;                                                 \
-    Regs.AC = Regs.AC op MemReadByte (MemReadByte (Regs.PC+1)); \
-    TEST_ZF (Regs.AC);                                          \
-    TEST_SF (Regs.AC);                                          \
-    Regs.PC += 2
-
-/* zp,x */
-#define AC_OP_ZPX(op)                                           \
-    unsigned char ZPAddr;                                       \
-    Cycles = 4;                                                 \
-    ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;                 \
-    Regs.AC = Regs.AC op MemReadByte (ZPAddr);                  \
-    TEST_ZF (Regs.AC);                                          \
-    TEST_SF (Regs.AC);                                          \
-    Regs.PC += 2
-
-/* zp,y */
-#define AC_OP_ZPY(op)                                           \
-    unsigned char ZPAddr;                                       \
-    Cycles = 4;                                                 \
-    ZPAddr = MemReadByte (Regs.PC+1) + Regs.YR;                 \
-    Regs.AC = Regs.AC op MemReadByte (ZPAddr);                  \
-    TEST_ZF (Regs.AC);                                          \
-    TEST_SF (Regs.AC);                                          \
-    Regs.PC += 2
-
-/* abs */
-#define AC_OP_ABS(op)                                           \
-    unsigned Addr;                                              \
-    Cycles = 4;                                                 \
-    Addr = MemReadWord (Regs.PC+1);                             \
-    Regs.AC = Regs.AC op MemReadByte (Addr);                    \
-    TEST_ZF (Regs.AC);                                          \
-    TEST_SF (Regs.AC);                                          \
-    Regs.PC += 3
-
-/* abs,x */
-#define AC_OP_ABSX(op)                                          \
-    unsigned Addr;                                              \
-    Cycles = 4;                                                 \
-    Addr = MemReadWord (Regs.PC+1);                             \
-    if (PAGE_CROSS (Addr, Regs.XR)) {                           \
-        ++Cycles;                                               \
-    }                                                           \
-    Regs.AC = Regs.AC op MemReadByte (Addr + Regs.XR);          \
-    TEST_ZF (Regs.AC);                                          \
-    TEST_SF (Regs.AC);                                          \
-    Regs.PC += 3
-
-/* abs,y */
-#define AC_OP_ABSY(op)                                          \
-    unsigned Addr;                                              \
-    Cycles = 4;                                                 \
-    Addr = MemReadWord (Regs.PC+1);                             \
-    if (PAGE_CROSS (Addr, Regs.YR)) {                           \
-        ++Cycles;                                               \
-    }                                                           \
-    Regs.AC = Regs.AC op MemReadByte (Addr + Regs.YR);          \
-    TEST_ZF (Regs.AC);                                          \
-    TEST_SF (Regs.AC);                                          \
-    Regs.PC += 3
-
-/* (zp,x) */
-#define AC_OP_ZPXIND(op)                                        \
-    unsigned char ZPAddr;                                       \
-    unsigned Addr;                                              \
-    Cycles = 6;                                                 \
-    ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;                 \
-    Addr = MemReadZPWord (ZPAddr);                              \
-    Regs.AC = Regs.AC op MemReadByte (Addr);                    \
-    TEST_ZF (Regs.AC);                                          \
-    TEST_SF (Regs.AC);                                          \
-    Regs.PC += 2
-
-/* (zp),y */
-#define AC_OP_ZPINDY(op)                                        \
-    unsigned char ZPAddr;                                       \
-    unsigned Addr;                                              \
-    Cycles = 5;                                                 \
-    ZPAddr = MemReadByte (Regs.PC+1);                           \
-    Addr = MemReadZPWord (ZPAddr) + Regs.YR;                    \
-    Regs.AC = Regs.AC op MemReadByte (Addr);                    \
-    TEST_ZF (Regs.AC);                                          \
-    TEST_SF (Regs.AC);                                          \
-    Regs.PC += 2
-
-/* ADC */
-#define ADC(v)                                                  \
-    do {                                                        \
-        unsigned old = Regs.AC;                                 \
-        unsigned rhs = (v & 0xFF);                              \
-        if (GET_DF ()) {                                        \
-            unsigned lo;                                        \
-            int res;                                            \
-            lo = (old & 0x0F) + (rhs & 0x0F) + GET_CF ();       \
-            if (lo >= 0x0A) {                                   \
-                lo = ((lo + 0x06) & 0x0F) + 0x10;               \
-            }                                                   \
-            Regs.AC = (old & 0xF0) + (rhs & 0xF0) + lo;         \
-            res = (signed char)(old & 0xF0) +                   \
-                  (signed char)(rhs & 0xF0) +                   \
-                  (signed char)lo;                              \
-            TEST_ZF (old + rhs + GET_CF ());                    \
-            TEST_SF (Regs.AC);                                  \
-            if (Regs.AC >= 0xA0) {                              \
-                Regs.AC += 0x60;                                \
-            }                                                   \
-            TEST_CF (Regs.AC);                                  \
-            SET_OF ((res < -128) || (res > 127));               \
-        } else {                                                \
-            Regs.AC += rhs + GET_CF ();                         \
-            TEST_ZF (Regs.AC);                                  \
-            TEST_SF (Regs.AC);                                  \
-            TEST_CF (Regs.AC);                                  \
-            SET_OF (!((old ^ rhs) & 0x80) &&                    \
-                    ((old ^ Regs.AC) & 0x80));                  \
-            Regs.AC &= 0xFF;                                    \
-        }                                                       \
-    } while (0)
-
-/* branches */
-#define BRANCH(cond)                                            \
-    Cycles = 2;                                                 \
-    if (cond) {                                                 \
-        signed char Offs;                                       \
-        unsigned char OldPCH;                                   \
-        ++Cycles;                                               \
-        Offs = (signed char) MemReadByte (Regs.PC+1);           \
-        OldPCH = PCH;                                           \
-        Regs.PC += 2 + (int) Offs;                              \
-        if (PCH != OldPCH) {                                    \
-            ++Cycles;                                           \
-        }                                                       \
-    } else {                                                    \
-        Regs.PC += 2;                                           \
-    }
-
-/* compares */
-#define CMP(v1,v2)                                              \
-    do {                                                        \
-        unsigned Result = v1 - v2;                              \
-        TEST_ZF (Result & 0xFF);                                \
-        TEST_SF (Result);                                       \
-        SET_CF (Result <= 0xFF);                                \
-    } while (0)
-
-
-/* ROL */
-#define ROL(Val)                                                \
-    Val <<= 1;                                                  \
-    if (GET_CF ()) {                                            \
-        Val |= 0x01;                                            \
-    }                                                           \
-    TEST_ZF (Val);                                              \
-    TEST_SF (Val);                                              \
-    TEST_CF (Val)
-
-/* ROR */
-#define ROR(Val)                                                \
-    if (GET_CF ()) {                                            \
-        Val |= 0x100;                                           \
-    }                                                           \
-    SET_CF (Val & 0x01);                                        \
-    Val >>= 1;                                                  \
-    TEST_ZF (Val);                                              \
-    TEST_SF (Val)
-
-/* SBC */
-#define SBC(v)                                                  \
-    do {                                                        \
-        unsigned old = Regs.AC;                                 \
-        unsigned rhs = (v & 0xFF);                              \
-        if (GET_DF ()) {                                        \
-            unsigned lo;                                        \
-            int res;                                            \
-            lo = (old & 0x0F) - (rhs & 0x0F) + GET_CF () - 1;   \
-            if (lo & 0x80) {                                    \
-                lo = ((lo - 0x06) & 0x0F) - 0x10;               \
-            }                                                   \
-            Regs.AC = (old & 0xF0) - (rhs & 0xF0) + lo;         \
-            if (Regs.AC & 0x80) {                               \
-                Regs.AC -= 0x60;                                \
-            }                                                   \
-            res = Regs.AC - rhs + (!GET_CF ());                 \
-            TEST_ZF (res);                                      \
-            TEST_SF (res);                                      \
-            SET_CF (res <= 0xFF);                               \
-            SET_OF (((old^rhs) & (old^res) & 0x80));            \
-        } else {                                                \
-            Regs.AC -= rhs - (!GET_CF ());                      \
-            TEST_ZF (Regs.AC);                                  \
-            TEST_SF (Regs.AC);                                  \
-            SET_CF (Regs.AC <= 0xFF);                           \
-            SET_OF (((old^rhs) & (old^Regs.AC) & 0x80));        \
-            Regs.AC &= 0xFF;                                    \
-        }                                                       \
-    } while (0)
-
-
-/*****************************************************************************/
-/*                               Helper functions                            */
-/*****************************************************************************/
-
-
-
-static void OPC_Illegal (void)
-{
-    Warning ("Illegal opcode $%02X at address $%04X\n", MemReadByte (Regs.PC), Regs.PC);
-}
-
-
-
-/*****************************************************************************/
-/*                                  Code                                    */
-/*****************************************************************************/
-
-
-
-static void OPC_6502_00 (void)
-/* Opcode $00: BRK */
-{
-    Cycles = 7;
-    Regs.PC += 2;
-    SET_BF (1);
-    PUSH (PCH);
-    PUSH (PCL);
-    PUSH (Regs.SR);
-    SET_IF (1);
-    Regs.PC = MemReadWord (0xFFFE);
-    CPUHalted = 1;
-}
-
-
-
-static void OPC_6502_01 (void)
-/* Opcode $01: ORA (ind,x) */
-{
-    AC_OP_ZPXIND (|);
-}
-
-
-
-static void OPC_6502_05 (void)
-/* Opcode $05: ORA zp */
-{
-    AC_OP_ZP (|);
-}
-
-
-
-static void OPC_6502_06 (void)
-/* Opcode $06: ASL zp */
-{
-    unsigned char ZPAddr;
-    unsigned Val;
-    Cycles = 5;
-    ZPAddr = MemReadByte (Regs.PC+1);
-    Val    = MemReadByte (ZPAddr) << 1;
-    MemWriteByte (ZPAddr, (unsigned char) Val);
-    TEST_ZF (Val & 0xFF);
-    TEST_SF (Val);
-    SET_CF (Val & 0x100);
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_08 (void)
-/* Opcode $08: PHP */
-{
-    Cycles = 3;
-    PUSH (Regs.SR & ~BF);
-    Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_09 (void)
-/* Opcode $09: ORA #imm */
-{
-    AC_OP_IMM (|);
-}
-
-
-
-static void OPC_6502_0A (void)
-/* Opcode $0A: ASL a */
-{
-    Cycles = 2;
-    Regs.AC <<= 1;
-    TEST_ZF (Regs.AC & 0xFF);
-    TEST_SF (Regs.AC);
-    SET_CF (Regs.AC & 0x100);
-    Regs.AC &= 0xFF;
-    Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_0D (void)
-/* Opcode $0D: ORA abs */
-{
-    AC_OP_ABS (|);
-}
-
-
-
-static void OPC_6502_0E (void)
-/* Opcode $0E: ALS abs */
-{
-    unsigned Addr;
-    unsigned Val;
-    Cycles = 6;
-    Addr = MemReadWord (Regs.PC+1);
-    Val  = MemReadByte (Addr) << 1;
-    MemWriteByte (Addr, (unsigned char) Val);
-    TEST_ZF (Val & 0xFF);
-    TEST_SF (Val);
-    SET_CF (Val & 0x100);
-    Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_10 (void)
-/* Opcode $10: BPL */
-{
-    BRANCH (!GET_SF ());
-}
-
-
-
-static void OPC_6502_11 (void)
-/* Opcode $11: ORA (zp),y */
-{
-    AC_OP_ZPINDY (|);
-}
-
-
-
-static void OPC_6502_15 (void)
-/* Opcode $15: ORA zp,x */
-{
-   AC_OP_ZPX (|);
-}
-
-
-
-static void OPC_6502_16 (void)
-/* Opcode $16: ASL zp,x */
-{
-    unsigned char ZPAddr;
-    unsigned Val;
-    Cycles = 6;
-    ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
-    Val    = MemReadByte (ZPAddr) << 1;
-    MemWriteByte (ZPAddr, (unsigned char) Val);
-    TEST_ZF (Val & 0xFF);
-    TEST_SF (Val);
-    SET_CF (Val & 0x100);
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_18 (void)
-/* Opcode $18: CLC */
-{
-    Cycles = 2;
-    SET_CF (0);
-    Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_19 (void)
-/* Opcode $19: ORA abs,y */
-{
-    AC_OP_ABSY (|);
-}
-
-
-
-static void OPC_6502_1D (void)
-/* Opcode $1D: ORA abs,x */
-{
-    AC_OP_ABSX (|);
-}
-
-
-
-static void OPC_6502_1E (void)
-/* Opcode $1E: ASL abs,x */
-{
-    unsigned Addr;
-    unsigned Val;
-    Cycles = 7;
-    Addr = MemReadWord (Regs.PC+1) + Regs.XR;
-    Val  = MemReadByte (Addr) << 1;
-    MemWriteByte (Addr, (unsigned char) Val);
-    TEST_ZF (Val & 0xFF);
-    TEST_SF (Val);
-    SET_CF (Val & 0x100);
-    Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_20 (void)
-/* Opcode $20: JSR */
-{
-    unsigned Addr;
-    Cycles = 6;
-    Addr   = MemReadWord (Regs.PC+1);
-    Regs.PC += 2;
-    PUSH (PCH);
-    PUSH (PCL);
-    Regs.PC = Addr;
-}
-
-
-
-static void OPC_6502_21 (void)
-/* Opcode $21: AND (zp,x) */
-{
-    AC_OP_ZPXIND (&);
-}
-
-
-
-static void OPC_6502_24 (void)
-/* Opcode $24: BIT zp */
-{
-    unsigned char ZPAddr;
-    unsigned char Val;
-    Cycles = 3;
-    ZPAddr = MemReadByte (Regs.PC+1);
-    Val    = MemReadByte (ZPAddr);
-    SET_SF (Val & 0x80);
-    SET_OF (Val & 0x40);
-    SET_ZF ((Val & Regs.AC) == 0);
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_25 (void)
-/* Opcode $25: AND zp */
-{
-    AC_OP_ZP (&);
-}
-
-
-
-static void OPC_6502_26 (void)
-/* Opcode $26: ROL zp */
-{
-    unsigned char ZPAddr;
-    unsigned Val;
-    Cycles = 5;
-    ZPAddr = MemReadByte (Regs.PC+1);
-    Val    = MemReadByte (ZPAddr);
-    ROL (Val);
-    MemWriteByte (ZPAddr, Val);
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_28 (void)
-/* Opcode $28: PLP */
-{
-    Cycles = 4;
-    Regs.SR = (POP () & ~BF);
-    Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_29 (void)
-/* Opcode $29: AND #imm */
-{
-    AC_OP_IMM (&);
-}
-
-
-
-static void OPC_6502_2A (void)
-/* Opcode $2A: ROL a */
-{
-    Cycles = 2;
-    ROL (Regs.AC);
-    Regs.AC &= 0xFF;
-    Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_2C (void)
-/* Opcode $2C: BIT abs */
-{
-    unsigned Addr;
-    unsigned char Val;
-    Cycles = 4;
-    Addr = MemReadByte (Regs.PC+1);
-    Val  = MemReadByte (Addr);
-    SET_SF (Val & 0x80);
-    SET_OF (Val & 0x40);
-    SET_ZF ((Val & Regs.AC) == 0);
-    Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_2D (void)
-/* Opcode $2D: AND abs */
-{
-    AC_OP_ABS (&);
-}
-
-
-
-static void OPC_6502_2E (void)
-/* Opcode $2E: ROL abs */
-{
-    unsigned Addr;
-    unsigned Val;
-    Cycles = 6;
-    Addr = MemReadWord (Regs.PC+1);
-    Val  = MemReadByte (Addr);
-    ROL (Val);
-    MemWriteByte (Addr, Val);
-    Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_30 (void)
-/* Opcode $30: BMI */
-{
-    BRANCH (GET_SF ());
-}
-
-
-
-static void OPC_6502_31 (void)
-/* Opcode $31: AND (zp),y */
-{
-    AC_OP_ZPINDY (&);
-}
-
-
-
-static void OPC_6502_35 (void)
-/* Opcode $35: AND zp,x */
-{
-    AC_OP_ZPX (&);
-}
-
-
-
-static void OPC_6502_36 (void)
-/* Opcode $36: ROL zp,x */
-{
-    unsigned char ZPAddr;
-    unsigned Val;
-    Cycles = 6;
-    ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
-    Val    = MemReadByte (ZPAddr);
-    ROL (Val);
-    MemWriteByte (ZPAddr, Val);
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_38 (void)
-/* Opcode $38: SEC */
-{
-    Cycles = 2;
-    SET_CF (1);
-    Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_39 (void)
-/* Opcode $39: AND abs,y */
-{
-    AC_OP_ABSY (&);
-}
-
-
-
-static void OPC_6502_3D (void)
-/* Opcode $3D: AND abs,x */
-{
-    AC_OP_ABSX (&);
-}
-
-
-
-static void OPC_6502_3E (void)
-/* Opcode $3E: ROL abs,x */
-{
-    unsigned Addr;
-    unsigned Val;
-    Cycles = 7;
-    Addr = MemReadWord (Regs.PC+1) + Regs.XR;
-    Val  = MemReadByte (Addr);
-    ROL (Val);
-    MemWriteByte (Addr, Val);
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_40 (void)
-/* Opcode $40: RTI */
-{
-    Cycles = 6;
-    Regs.SR = POP ();
-    Regs.PC = POP ();                /* PCL */
-    Regs.PC |= (POP () << 8);        /* PCH */
-}
-
-
-
-static void OPC_6502_41 (void)
-/* Opcode $41: EOR (zp,x) */
-{
-    AC_OP_ZPXIND (^);
-}
-
-
-
-static void OPC_6502_45 (void)
-/* Opcode $45: EOR zp */
-{
-    AC_OP_ZP (^);
-}
-
-
-
-static void OPC_6502_46 (void)
-/* Opcode $46: LSR zp */
-{
-    unsigned char ZPAddr;
-    unsigned char Val;
-    Cycles = 5;
-    ZPAddr = MemReadByte (Regs.PC+1);
-    Val    = MemReadByte (ZPAddr);
-    SET_CF (Val & 0x01);
-    Val >>= 1;
-    MemWriteByte (ZPAddr, Val);
-    TEST_ZF (Val);
-    TEST_SF (Val);
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_48 (void)
-/* Opcode $48: PHA */
-{
-    Cycles = 3;
-    PUSH (Regs.AC);
-    Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_49 (void)
-/* Opcode $49: EOR #imm */
-{
-    AC_OP_IMM (^);
-}
-
-
-
-static void OPC_6502_4A (void)
-/* Opcode $4A: LSR a */
-{
-    Cycles = 2;
-    SET_CF (Regs.AC & 0x01);
-    Regs.AC >>= 1;
-    TEST_ZF (Regs.AC);
-    TEST_SF (Regs.AC);
-    Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_4C (void)
-/* Opcode $4C: JMP abs */
-{
-    Cycles = 3;
-    Regs.PC = MemReadWord (Regs.PC+1);
-}
-
-
-
-static void OPC_6502_4D (void)
-/* Opcode $4D: EOR abs */
-{
-    AC_OP_ABS (^);
-}
-
-
-
-static void OPC_6502_4E (void)
-/* Opcode $4E: LSR abs */
-{
-    unsigned Addr;
-    unsigned char Val;
-    Cycles = 6;
-    Addr = MemReadWord (Regs.PC+1);
-    Val  = MemReadByte (Addr);
-    SET_CF (Val & 0x01);
-    Val >>= 1;
-    MemWriteByte (Addr, Val);
-    TEST_ZF (Val);
-    TEST_SF (Val);
-    Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_50 (void)
-/* Opcode $50: BVC */
-{
-    BRANCH (!GET_OF ());
-}
-
-
-
-static void OPC_6502_51 (void)
-/* Opcode $51: EOR (zp),y */
-{
-    AC_OP_ZPINDY (^);
-}
-
-
-
-static void OPC_6502_55 (void)
-/* Opcode $55: EOR zp,x */
-{
-    AC_OP_ZPX (^);
-}
-
-
-
-static void OPC_6502_56 (void)
-/* Opcode $56: LSR zp,x */
-{
-    unsigned char ZPAddr;
-    unsigned char Val;
-    Cycles = 6;
-    ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
-    Val    = MemReadByte (ZPAddr);
-    SET_CF (Val & 0x01);
-    Val >>= 1;
-    MemWriteByte (ZPAddr, Val);
-    TEST_ZF (Val);
-    TEST_SF (Val);
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_58 (void)
-/* Opcode $58: CLI */
-{
-    Cycles = 2;
-    SET_IF (0);
-    Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_59 (void)
-/* Opcode $59: EOR abs,y */
-{
-    AC_OP_ABSY (^);
-}
-
-
-
-static void OPC_6502_5D (void)
-/* Opcode $5D: EOR abs,x */
-{
-    AC_OP_ABSX (^);
-}
-
-
-
-static void OPC_6502_5E (void)
-/* Opcode $5E: LSR abs,x */
-{
-    unsigned Addr;
-    unsigned char Val;
-    Cycles = 7;
-    Addr = MemReadWord (Regs.PC+1) + Regs.XR;
-    Val  = MemReadByte (Addr);
-    SET_CF (Val & 0x01);
-    Val >>= 1;
-    MemWriteByte (Addr, Val);
-    TEST_ZF (Val);
-    TEST_SF (Val);
-    Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_60 (void)
-/* Opcode $60: RTS */
-{
-    Cycles = 6;
-    Regs.PC = POP ();                /* PCL */
-    Regs.PC |= (POP () << 8);        /* PCH */
-    Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_61 (void)
-/* Opcode $61: ADC (zp,x) */
-{
-    unsigned char ZPAddr;
-    unsigned Addr;
-    Cycles = 6;
-    ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
-    Addr   = MemReadZPWord (ZPAddr);
-    ADC (MemReadByte (Addr));
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_65 (void)
-/* Opcode $65: ADC zp */
-{
-    unsigned char ZPAddr;
-    Cycles = 3;
-    ZPAddr = MemReadByte (Regs.PC+1);
-    ADC (MemReadByte (ZPAddr));
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_66 (void)
-/* Opcode $66: ROR zp */
-{
-    unsigned char ZPAddr;
-    unsigned Val;
-    Cycles = 5;
-    ZPAddr = MemReadByte (Regs.PC+1);
-    Val    = MemReadByte (ZPAddr);
-    ROR (Val);
-    MemWriteByte (ZPAddr, Val);
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_68 (void)
-/* Opcode $68: PLA */
-{
-    Cycles = 4;
-    Regs.AC = POP ();
-    TEST_ZF (Regs.AC);
-    TEST_SF (Regs.AC);
-    Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_69 (void)
-/* Opcode $69: ADC #imm */
-{
-    Cycles = 2;
-    ADC (MemReadByte (Regs.PC+1));
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_6A (void)
-/* Opcode $6A: ROR a */
-{
-    Cycles = 2;
-    ROR (Regs.AC);
-    Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_6C (void)
-/* Opcode $6C: JMP (ind) */
-{
-    unsigned Addr;
-    Cycles = 5;
-    Addr = MemReadWord (Regs.PC+1);
-    if (CPU == CPU_6502) {
-        /* Emulate the 6502 bug */
-        Regs.PC = MemReadByte (Addr);
-        Addr = (Addr & 0xFF00) | ((Addr + 1) & 0xFF);
-        Regs.PC |= (MemReadByte (Addr) << 8);
-    } else {
-        /* 65C02 and above have this bug fixed */
-        Regs.PC = MemReadWord (Addr);
-    }
-}
-
-
-
-static void OPC_6502_6D (void)
-/* Opcode $6D: ADC abs */
-{
-    unsigned Addr;
-    Cycles = 4;
-    Addr   = MemReadWord (Regs.PC+1);
-    ADC (MemReadByte (Addr));
-    Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_6E (void)
-/* Opcode $6E: ROR abs */
-{
-    unsigned Addr;
-    unsigned Val;
-    Cycles = 6;
-    Addr = MemReadWord (Regs.PC+1);
-    Val  = MemReadByte (Addr);
-    ROR (Val);
-    MemWriteByte (Addr, Val);
-    Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_70 (void)
-/* Opcode $70: BVS */
-{
-    BRANCH (GET_OF ());
-}
-
-
-
-static void OPC_6502_71 (void)
-/* Opcode $71: ADC (zp),y */
-{
-    unsigned char ZPAddr;
-    unsigned Addr;
-    Cycles = 5;
-    ZPAddr = MemReadByte (Regs.PC+1);
-    Addr   = MemReadZPWord (ZPAddr);
-    if (PAGE_CROSS (Addr, Regs.YR)) {
-        ++Cycles;
-    }
-    ADC (MemReadByte (Addr + Regs.YR));
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_75 (void)
-/* Opcode $75: ADC zp,x */
-{
-    unsigned char ZPAddr;
-    Cycles = 4;
-    ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
-    ADC (MemReadByte (ZPAddr));
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_76 (void)
-/* Opcode $76: ROR zp,x */
-{
-    unsigned char ZPAddr;
-    unsigned Val;
-    Cycles = 6;
-    ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
-    Val    = MemReadByte (ZPAddr);
-    ROR (Val);
-    MemWriteByte (ZPAddr, Val);
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_78 (void)
-/* Opcode $78: SEI */
-{
-    Cycles = 2;
-    SET_IF (1);
-    Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_79 (void)
-/* Opcode $79: ADC abs,y */
-{
-    unsigned Addr;
-    Cycles = 4;
-    Addr   = MemReadWord (Regs.PC+1);
-    if (PAGE_CROSS (Addr, Regs.YR)) {
-        ++Cycles;
-    }
-    ADC (MemReadByte (Addr + Regs.YR));
-    Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_7D (void)
-/* Opcode $7D: ADC abs,x */
-{
-    unsigned Addr;
-    Cycles = 4;
-    Addr   = MemReadWord (Regs.PC+1);
-    if (PAGE_CROSS (Addr, Regs.XR)) {
-        ++Cycles;
-    }
-    ADC (MemReadByte (Addr + Regs.XR));
-    Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_7E (void)
-/* Opcode $7E: ROR abs,x */
-{
-    unsigned Addr;
-    unsigned Val;
-    Cycles = 7;
-    Addr = MemReadByte (Regs.PC+1) + Regs.XR;
-    Val  = MemReadByte (Addr);
-    ROR (Val);
-    MemWriteByte (Addr, Val);
-    Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_81 (void)
-/* Opcode $81: STA (zp,x) */
-{
-    unsigned char ZPAddr;
-    unsigned Addr;
-    Cycles = 6;
-    ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
-    Addr   = MemReadZPWord (ZPAddr);
-    MemWriteByte (Addr, Regs.AC);
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_84 (void)
-/* Opcode $84: STY zp */
-{
-    unsigned char ZPAddr;
-    Cycles = 3;
-    ZPAddr = MemReadByte (Regs.PC+1);
-    MemWriteByte (ZPAddr, Regs.YR);
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_85 (void)
-/* Opcode $85: STA zp */
-{
-    unsigned char ZPAddr;
-    Cycles = 3;
-    ZPAddr = MemReadByte (Regs.PC+1);
-    MemWriteByte (ZPAddr, Regs.AC);
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_86 (void)
-/* Opcode $86: STX zp */
-{
-    unsigned char ZPAddr;
-    Cycles = 3;
-    ZPAddr = MemReadByte (Regs.PC+1);
-    MemWriteByte (ZPAddr, Regs.XR);
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_88 (void)
-/* Opcode $88: DEY */
-{
-    Cycles = 2;
-    Regs.YR = (Regs.YR - 1) & 0xFF;
-    TEST_ZF (Regs.YR);
-    TEST_SF (Regs.YR);
-    Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_8A (void)
-/* Opcode $8A: TXA */
-{
-    Cycles = 2;
-    Regs.AC = Regs.XR;
-    TEST_ZF (Regs.AC);
-    TEST_SF (Regs.AC);
-    Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_8C (void)
-/* Opcode $8C: STY abs */
-{
-    unsigned Addr;
-    Cycles = 4;
-    Addr = MemReadWord (Regs.PC+1);
-    MemWriteByte (Addr, Regs.YR);
-    Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_8D (void)
-/* Opcode $8D: STA abs */
-{
-    unsigned Addr;
-    Cycles = 4;
-    Addr = MemReadWord (Regs.PC+1);
-    MemWriteByte (Addr, Regs.AC);
-    Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_8E (void)
-/* Opcode $8E: STX abs */
-{
-    unsigned Addr;
-    Cycles = 4;
-    Addr = MemReadWord (Regs.PC+1);
-    MemWriteByte (Addr, Regs.XR);
-    Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_90 (void)
-/* Opcode $90: BCC */
-{
-    BRANCH (!GET_CF ());
-}
-
-
-
-static void OPC_6502_91 (void)
-/* Opcode $91: sta (zp),y */
-{
-    unsigned char ZPAddr;
-    unsigned Addr;
-    Cycles = 6;
-    ZPAddr = MemReadByte (Regs.PC+1);
-    Addr   = MemReadZPWord (ZPAddr) + Regs.YR;
-    MemWriteByte (Addr, Regs.AC);
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_94 (void)
-/* Opcode $94: STY zp,x */
-{
-    unsigned char ZPAddr;
-    Cycles = 4;
-    ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
-    MemWriteByte (ZPAddr, Regs.YR);
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_95 (void)
-/* Opcode $95: STA zp,x */
-{
-    unsigned char ZPAddr;
-    Cycles = 4;
-    ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
-    MemWriteByte (ZPAddr, Regs.AC);
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_96 (void)
-/* Opcode $96: stx zp,y */
-{
-    unsigned char ZPAddr;
-    Cycles = 4;
-    ZPAddr = MemReadByte (Regs.PC+1) + Regs.YR;
-    MemWriteByte (ZPAddr, Regs.XR);
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_98 (void)
-/* Opcode $98: TYA */
-{
-    Cycles = 2;
-    Regs.AC = Regs.YR;
-    TEST_ZF (Regs.AC);
-    TEST_SF (Regs.AC);
-    Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_99 (void)
-/* Opcode $99: STA abs,y */
-{
-    unsigned Addr;
-    Cycles = 5;
-    Addr   = MemReadWord (Regs.PC+1) + Regs.YR;
-    MemWriteByte (Addr, Regs.AC);
-    Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_9A (void)
-/* Opcode $9A: TXS */
-{
-    Cycles = 2;
-    Regs.SP = Regs.XR;
-    Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_9D (void)
-/* Opcode $9D: STA abs,x */
-{
-    unsigned Addr;
-    Cycles = 5;
-    Addr   = MemReadWord (Regs.PC+1) + Regs.XR;
-    MemWriteByte (Addr, Regs.AC);
-    Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_A0 (void)
-/* Opcode $A0: LDY #imm */
-{
-    Cycles = 2;
-    Regs.YR = MemReadByte (Regs.PC+1);
-    TEST_ZF (Regs.YR);
-    TEST_SF (Regs.YR);
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_A1 (void)
-/* Opcode $A1: LDA (zp,x) */
-{
-    unsigned char ZPAddr;
-    unsigned Addr;
-    Cycles = 6;
-    ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
-    Addr = MemReadZPWord (ZPAddr);
-    Regs.AC = MemReadByte (Addr);
-    TEST_ZF (Regs.AC);
-    TEST_SF (Regs.AC);
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_A2 (void)
-/* Opcode $A2: LDX #imm */
-{
-    Cycles = 2;
-    Regs.XR = MemReadByte (Regs.PC+1);
-    TEST_ZF (Regs.XR);
-    TEST_SF (Regs.XR);
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_A4 (void)
-/* Opcode $A4: LDY zp */
-{
-    unsigned char ZPAddr;
-    Cycles = 3;
-    ZPAddr = MemReadByte (Regs.PC+1);
-    Regs.YR = MemReadByte (ZPAddr);
-    TEST_ZF (Regs.YR);
-    TEST_SF (Regs.YR);
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_A5 (void)
-/* Opcode $A5: LDA zp */
-{
-    unsigned char ZPAddr;
-    Cycles = 3;
-    ZPAddr = MemReadByte (Regs.PC+1);
-    Regs.AC = MemReadByte (ZPAddr);
-    TEST_ZF (Regs.AC);
-    TEST_SF (Regs.AC);
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_A6 (void)
-/* Opcode $A6: LDX zp */
-{
-    unsigned char ZPAddr;
-    Cycles = 3;
-    ZPAddr = MemReadByte (Regs.PC+1);
-    Regs.XR = MemReadByte (ZPAddr);
-    TEST_ZF (Regs.XR);
-    TEST_SF (Regs.XR);
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_A8 (void)
-/* Opcode $A8: TAY */
-{
-    Cycles = 2;
-    Regs.YR = Regs.AC;
-    TEST_ZF (Regs.YR);
-    TEST_SF (Regs.YR);
-    Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_A9 (void)
-/* Opcode $A9: LDA #imm */
-{
-    Cycles = 2;
-    Regs.AC = MemReadByte (Regs.PC+1);
-    TEST_ZF (Regs.AC);
-    TEST_SF (Regs.AC);
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_AA (void)
-/* Opcode $AA: TAX */
-{
-    Cycles = 2;
-    Regs.XR = Regs.AC;
-    TEST_ZF (Regs.XR);
-    TEST_SF (Regs.XR);
-    Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_AC (void)
-/* Opcode $Regs.AC: LDY abs */
-{
-    unsigned Addr;
-    Cycles = 4;
-    Addr   = MemReadWord (Regs.PC+1);
-    Regs.YR     = MemReadByte (Addr);
-    TEST_ZF (Regs.YR);
-    TEST_SF (Regs.YR);
-    Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_AD (void)
-/* Opcode $AD: LDA abs */
-{
-    unsigned Addr;
-    Cycles = 4;
-    Addr   = MemReadWord (Regs.PC+1);
-    Regs.AC     = MemReadByte (Addr);
-    TEST_ZF (Regs.AC);
-    TEST_SF (Regs.AC);
-    Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_AE (void)
-/* Opcode $AE: LDX abs */
-{
-    unsigned Addr;
-    Cycles = 4;
-    Addr   = MemReadWord (Regs.PC+1);
-    Regs.XR     = MemReadByte (Addr);
-    TEST_ZF (Regs.XR);
-    TEST_SF (Regs.XR);
-    Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_B0 (void)
-/* Opcode $B0: BCS */
-{
-    BRANCH (GET_CF ());
-}
-
-
-
-static void OPC_6502_B1 (void)
-/* Opcode $B1: LDA (zp),y */
-{
-    unsigned char ZPAddr;
-    unsigned Addr;
-    Cycles = 5;
-    ZPAddr = MemReadByte (Regs.PC+1);
-    Addr   = MemReadZPWord (ZPAddr);
-    if (PAGE_CROSS (Addr, Regs.YR)) {
-        ++Cycles;
-    }
-    Regs.AC = MemReadByte (Addr + Regs.YR);
-    TEST_ZF (Regs.AC);
-    TEST_SF (Regs.AC);
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_B4 (void)
-/* Opcode $B4: LDY zp,x */
-{
-    unsigned char ZPAddr;
-    Cycles = 4;
-    ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
-    Regs.YR     = MemReadByte (ZPAddr);
-    TEST_ZF (Regs.YR);
-    TEST_SF (Regs.YR);
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_B5 (void)
-/* Opcode $B5: LDA zp,x */
-{
-    unsigned char ZPAddr;
-    Cycles = 4;
-    ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
-    Regs.AC     = MemReadByte (ZPAddr);
-    TEST_ZF (Regs.AC);
-    TEST_SF (Regs.AC);
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_B6 (void)
-/* Opcode $B6: LDX zp,y */
-{
-    unsigned char ZPAddr;
-    Cycles = 4;
-    ZPAddr = MemReadByte (Regs.PC+1) + Regs.YR;
-    Regs.XR     = MemReadByte (ZPAddr);
-    TEST_ZF (Regs.XR);
-    TEST_SF (Regs.XR);
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_B8 (void)
-/* Opcode $B8: CLV */
-{
-    Cycles = 2;
-    SET_OF (0);
-    Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_B9 (void)
-/* Opcode $B9: LDA abs,y */
-{
-    unsigned Addr;
-    Cycles = 4;
-    Addr = MemReadWord (Regs.PC+1);
-    if (PAGE_CROSS (Addr, Regs.YR)) {
-        ++Cycles;
-    }
-    Regs.AC = MemReadByte (Addr + Regs.YR);
-    TEST_ZF (Regs.AC);
-    TEST_SF (Regs.AC);
-    Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_BA (void)
-/* Opcode $BA: TSX */
-{
-    Cycles = 2;
-    Regs.XR = Regs.SP;
-    TEST_ZF (Regs.XR);
-    TEST_SF (Regs.XR);
-    Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_BC (void)
-/* Opcode $BC: LDY abs,x */
-{
-    unsigned Addr;
-    Cycles = 4;
-    Addr = MemReadWord (Regs.PC+1);
-    if (PAGE_CROSS (Addr, Regs.XR)) {
-        ++Cycles;
-    }
-    Regs.YR = MemReadByte (Addr + Regs.XR);
-    TEST_ZF (Regs.YR);
-    TEST_SF (Regs.YR);
-    Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_BD (void)
-/* Opcode $BD: LDA abs,x */
-{
-    unsigned Addr;
-    Cycles = 4;
-    Addr = MemReadWord (Regs.PC+1);
-    if (PAGE_CROSS (Addr, Regs.XR)) {
-        ++Cycles;
-    }
-    Regs.AC = MemReadByte (Addr + Regs.XR);
-    TEST_ZF (Regs.AC);
-    TEST_SF (Regs.AC);
-    Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_BE (void)
-/* Opcode $BE: LDX abs,y */
-{
-    unsigned Addr;
-    Cycles = 4;
-    Addr = MemReadWord (Regs.PC+1);
-    if (PAGE_CROSS (Addr, Regs.YR)) {
-        ++Cycles;
-    }
-    Regs.XR = MemReadByte (Addr + Regs.YR);
-    TEST_ZF (Regs.XR);
-    TEST_SF (Regs.XR);
-    Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_C0 (void)
-/* Opcode $C0: CPY #imm */
-{
-    Cycles = 2;
-    CMP (Regs.YR, MemReadByte (Regs.PC+1));
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_C1 (void)
-/* Opcode $C1: CMP (zp,x) */
-{
-    unsigned char ZPAddr;
-    unsigned Addr;
-    Cycles = 6;
-    ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
-    Addr   = MemReadZPWord (ZPAddr);
-    CMP (Regs.AC, MemReadByte (Addr));
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_C4 (void)
-/* Opcode $C4: CPY zp */
-{
-    unsigned char ZPAddr;
-    Cycles = 3;
-    ZPAddr = MemReadByte (Regs.PC+1);
-    CMP (Regs.YR, MemReadByte (ZPAddr));
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_C5 (void)
-/* Opcode $C5: CMP zp */
-{
-    unsigned char ZPAddr;
-    Cycles = 3;
-    ZPAddr = MemReadByte (Regs.PC+1);
-    CMP (Regs.AC, MemReadByte (ZPAddr));
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_C6 (void)
-/* Opcode $C6: DEC zp */
-{
-    unsigned char ZPAddr;
-    unsigned char Val;
-    Cycles = 5;
-    ZPAddr = MemReadByte (Regs.PC+1);
-    Val    = MemReadByte (ZPAddr) - 1;
-    MemWriteByte (ZPAddr, Val);
-    TEST_ZF (Val);
-    TEST_SF (Val);
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_C8 (void)
-/* Opcode $C8: INY */
-{
-    Cycles = 2;
-    Regs.YR = (Regs.YR + 1) & 0xFF;
-    TEST_ZF (Regs.YR);
-    TEST_SF (Regs.YR);
-    Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_C9 (void)
-/* Opcode $C9: CMP #imm */
-{
-    Cycles = 2;
-    CMP (Regs.AC, MemReadByte (Regs.PC+1));
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_CA (void)
-/* Opcode $CA: DEX */
-{
-    Cycles = 2;
-    Regs.XR = (Regs.XR - 1) & 0xFF;
-    TEST_ZF (Regs.XR);
-    TEST_SF (Regs.XR);
-    Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_CC (void)
-/* Opcode $CC: CPY abs */
-{
-    unsigned Addr;
-    Cycles = 4;
-    Addr   = MemReadWord (Regs.PC+1);
-    CMP (Regs.YR, MemReadByte (Addr));
-    Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_CD (void)
-/* Opcode $CD: CMP abs */
-{
-    unsigned Addr;
-    Cycles = 4;
-    Addr   = MemReadWord (Regs.PC+1);
-    CMP (Regs.AC, MemReadByte (Addr));
-    Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_CE (void)
-/* Opcode $CE: DEC abs */
-{
-    unsigned Addr;
-    unsigned char Val;
-    Cycles = 6;
-    Addr = MemReadWord (Regs.PC+1);
-    Val  = MemReadByte (Addr) - 1;
-    MemWriteByte (Addr, Val);
-    TEST_ZF (Val);
-    TEST_SF (Val);
-    Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_D0 (void)
-/* Opcode $D0: BNE */
-{
-    BRANCH (!GET_ZF ());
-}
-
-
-
-static void OPC_6502_D1 (void)
-/* Opcode $D1: CMP (zp),y */
-{
-    unsigned ZPAddr;
-    unsigned Addr;
-    Cycles = 5;
-    ZPAddr = MemReadByte (Regs.PC+1);
-    Addr   = MemReadWord (ZPAddr);
-    if (PAGE_CROSS (Addr, Regs.YR)) {
-        ++Cycles;
-    }
-    CMP (Regs.AC, MemReadByte (Addr + Regs.YR));
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_D5 (void)
-/* Opcode $D5: CMP zp,x */
-{
-    unsigned char ZPAddr;
-    Cycles = 4;
-    ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
-    CMP (Regs.AC, MemReadByte (ZPAddr));
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_D6 (void)
-/* Opcode $D6: DEC zp,x */
-{
-    unsigned char ZPAddr;
-    unsigned char Val;
-    Cycles = 6;
-    ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
-    Val  = MemReadByte (ZPAddr) - 1;
-    MemWriteByte (ZPAddr, Val);
-    TEST_ZF (Val);
-    TEST_SF (Val);
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_D8 (void)
-/* Opcode $D8: CLD */
-{
-    Cycles = 2;
-    SET_DF (0);
-    Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_D9 (void)
-/* Opcode $D9: CMP abs,y */
-{
-    unsigned Addr;
-    Cycles = 4;
-    Addr = MemReadWord (Regs.PC+1);
-    if (PAGE_CROSS (Addr, Regs.YR)) {
-        ++Cycles;
-    }
-    CMP (Regs.AC, MemReadByte (Addr + Regs.YR));
-    Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_DD (void)
-/* Opcode $DD: CMP abs,x */
-{
-    unsigned Addr;
-    Cycles = 4;
-    Addr = MemReadWord (Regs.PC+1);
-    if (PAGE_CROSS (Addr, Regs.XR)) {
-        ++Cycles;
-    }
-    CMP (Regs.AC, MemReadByte (Addr + Regs.XR));
-    Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_DE (void)
-/* Opcode $DE: DEC abs,x */
-{
-    unsigned Addr;
-    unsigned char Val;
-    Cycles = 7;
-    Addr = MemReadWord (Regs.PC+1) + Regs.XR;
-    Val  = MemReadByte (Addr) - 1;
-    MemWriteByte (Addr, Val);
-    TEST_ZF (Val);
-    TEST_SF (Val);
-    Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_E0 (void)
-/* Opcode $E0: CPX #imm */
-{
-    Cycles = 2;
-    CMP (Regs.XR, MemReadByte (Regs.PC+1));
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_E1 (void)
-/* Opcode $E1: SBC (zp,x) */
-{
-    unsigned char ZPAddr;
-    unsigned Addr;
-    Cycles = 6;
-    ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
-    Addr   = MemReadZPWord (ZPAddr);
-    SBC (MemReadByte (Addr));
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_E4 (void)
-/* Opcode $E4: CPX zp */
-{
-    unsigned char ZPAddr;
-    Cycles = 3;
-    ZPAddr = MemReadByte (Regs.PC+1);
-    CMP (Regs.XR, MemReadByte (ZPAddr));
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_E5 (void)
-/* Opcode $E5: SBC zp */
-{
-    unsigned char ZPAddr;
-    Cycles = 3;
-    ZPAddr = MemReadByte (Regs.PC+1);
-    SBC (MemReadByte (ZPAddr));
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_E6 (void)
-/* Opcode $E6: INC zp */
-{
-    unsigned char ZPAddr;
-    unsigned char Val;
-    Cycles = 5;
-    ZPAddr = MemReadByte (Regs.PC+1);
-    Val    = MemReadByte (ZPAddr) + 1;
-    MemWriteByte (ZPAddr, Val);
-    TEST_ZF (Val);
-    TEST_SF (Val);
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_E8 (void)
-/* Opcode $E8: INX */
-{
-    Cycles = 2;
-    Regs.XR = (Regs.XR + 1) & 0xFF;
-    TEST_ZF (Regs.XR);
-    TEST_SF (Regs.XR);
-    Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_E9 (void)
-/* Opcode $E9: SBC #imm */
-{
-    Cycles = 2;
-    SBC (MemReadByte (Regs.PC+1));
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_EA (void)
-/* Opcode $EA: NOP */
-{
-    /* This one is easy... */
-    Cycles = 2;
-    Regs.PC += 1;
-}
-
-
-
-static void OPC_6502_EC (void)
-/* Opcode $EC: CPX abs */
-{
-    unsigned Addr;
-    Cycles = 4;
-    Addr   = MemReadWord (Regs.PC+1);
-    CMP (Regs.XR, MemReadByte (Addr));
-    Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_ED (void)
-/* Opcode $ED: SBC abs */
-{
-    unsigned Addr;
-    Cycles = 4;
-    Addr   = MemReadWord (Regs.PC+1);
-    SBC (MemReadByte (Addr));
-    Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_EE (void)
-/* Opcode $EE: INC abs */
-{
-    unsigned Addr;
-    unsigned char Val;
-    Cycles = 6;
-    Addr = MemReadWord (Regs.PC+1);
-    Val  = MemReadByte (Addr) + 1;
-    MemWriteByte (Addr, Val);
-    TEST_ZF (Val);
-    TEST_SF (Val);
-    Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_F0 (void)
-/* Opcode $F0: BEQ */
-{
-    BRANCH (GET_ZF ());
-}
-
-
-
-static void OPC_6502_F1 (void)
-/* Opcode $F1: SBC (zp),y */
-{
-    unsigned char ZPAddr;
-    unsigned Addr;
-    Cycles = 5;
-    ZPAddr = MemReadByte (Regs.PC+1);
-    Addr   = MemReadZPWord (ZPAddr);
-    if (PAGE_CROSS (Addr, Regs.YR)) {
-        ++Cycles;
-    }
-    SBC (MemReadByte (Addr + Regs.YR));
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_F5 (void)
-/* Opcode $F5: SBC zp,x */
-{
-    unsigned char ZPAddr;
-    Cycles = 4;
-    ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
-    SBC (MemReadByte (ZPAddr));
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_F6 (void)
-/* Opcode $F6: INC zp,x */
-{
-    unsigned char ZPAddr;
-    unsigned char Val;
-    Cycles = 6;
-    ZPAddr = MemReadByte (Regs.PC+1) + Regs.XR;
-    Val  = MemReadByte (ZPAddr) + 1;
-    MemWriteByte (ZPAddr, Val);
-    TEST_ZF (Val);
-    TEST_SF (Val);
-    Regs.PC += 2;
-}
-
-
-
-static void OPC_6502_F8 (void)
-/* Opcode $F8: SED */
-{
-    SET_DF (1);
-}
-
-
-
-static void OPC_6502_F9 (void)
-/* Opcode $F9: SBC abs,y */
-{
-    unsigned Addr;
-    Cycles = 4;
-    Addr   = MemReadWord (Regs.PC+1);
-    if (PAGE_CROSS (Addr, Regs.YR)) {
-        ++Cycles;
-    }
-    SBC (MemReadByte (Addr + Regs.YR));
-    Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_FD (void)
-/* Opcode $FD: SBC abs,x */
-{
-    unsigned Addr;
-    Cycles = 4;
-    Addr   = MemReadWord (Regs.PC+1);
-    if (PAGE_CROSS (Addr, Regs.XR)) {
-        ++Cycles;
-    }
-    SBC (MemReadByte (Addr + Regs.XR));
-    Regs.PC += 3;
-}
-
-
-
-static void OPC_6502_FE (void)
-/* Opcode $FE: INC abs,x */
-{
-    unsigned Addr;
-    unsigned char Val;
-    Cycles = 7;
-    Addr = MemReadWord (Regs.PC+1) + Regs.XR;
-    Val  = MemReadByte (Addr) + 1;
-    MemWriteByte (Addr, Val);
-    TEST_ZF (Val);
-    TEST_SF (Val);
-    Regs.PC += 3;
-}
+#include "cpucore.h"
+#include "error.h"
 
 
 
 /*****************************************************************************/
-/*                                  Data                                    */
+/*                                          Data                                    */
 /*****************************************************************************/
 
 
 
-/* Opcode handler table */
-typedef void (*OPCFunc) (void);
-static OPCFunc OPCTable[256] = {
-    OPC_6502_00,
-    OPC_6502_01,
-    OPC_Illegal,
-    OPC_Illegal,
-    OPC_Illegal,
-    OPC_6502_05,
-    OPC_6502_06,
-    OPC_Illegal,
-    OPC_6502_08,
-    OPC_6502_09,
-    OPC_6502_0A,
-    OPC_Illegal,
-    OPC_Illegal,
-    OPC_6502_0D,
-    OPC_6502_0E,
-    OPC_Illegal,
-    OPC_6502_10,
-    OPC_6502_11,
-    OPC_Illegal,
-    OPC_Illegal,
-    OPC_Illegal,
-    OPC_6502_15,
-    OPC_6502_16,
-    OPC_Illegal,
-    OPC_6502_18,
-    OPC_6502_19,
-    OPC_Illegal,
-    OPC_Illegal,
-    OPC_Illegal,
-    OPC_6502_1D,
-    OPC_6502_1E,
-    OPC_Illegal,
-    OPC_6502_20,
-    OPC_6502_21,
-    OPC_Illegal,
-    OPC_Illegal,
-    OPC_6502_24,
-    OPC_6502_25,
-    OPC_6502_26,
-    OPC_Illegal,
-    OPC_6502_28,
-    OPC_6502_29,
-    OPC_6502_2A,
-    OPC_Illegal,
-    OPC_6502_2C,
-    OPC_6502_2D,
-    OPC_6502_2E,
-    OPC_Illegal,
-    OPC_6502_30,
-    OPC_6502_31,
-    OPC_Illegal,
-    OPC_Illegal,
-    OPC_Illegal,
-    OPC_6502_35,
-    OPC_6502_36,
-    OPC_Illegal,
-    OPC_6502_38,
-    OPC_6502_39,
-    OPC_Illegal,
-    OPC_Illegal,
-    OPC_Illegal,
-    OPC_6502_3D,
-    OPC_6502_3E,
-    OPC_Illegal,
-    OPC_6502_40,
-    OPC_6502_41,
-    OPC_Illegal,
-    OPC_Illegal,
-    OPC_Illegal,
-    OPC_6502_45,
-    OPC_6502_46,
-    OPC_Illegal,
-    OPC_6502_48,
-    OPC_6502_49,
-    OPC_6502_4A,
-    OPC_Illegal,
-    OPC_6502_4C,
-    OPC_6502_4D,
-    OPC_6502_4E,
-    OPC_Illegal,
-    OPC_6502_50,
-    OPC_6502_51,
-    OPC_Illegal,
-    OPC_Illegal,
-    OPC_Illegal,
-    OPC_6502_55,
-    OPC_6502_56,
-    OPC_Illegal,
-    OPC_6502_58,
-    OPC_6502_59,
-    OPC_Illegal,
-    OPC_Illegal,
-    OPC_Illegal,
-    OPC_6502_5D,
-    OPC_6502_5E,
-    OPC_Illegal,
-    OPC_6502_60,
-    OPC_6502_61,
-    OPC_Illegal,
-    OPC_Illegal,
-    OPC_Illegal,
-    OPC_6502_65,
-    OPC_6502_66,
-    OPC_Illegal,
-    OPC_6502_68,
-    OPC_6502_69,
-    OPC_6502_6A,
-    OPC_Illegal,
-    OPC_6502_6C,
-    OPC_6502_6D,
-    OPC_6502_6E,
-    OPC_Illegal,
-    OPC_6502_70,
-    OPC_6502_71,
-    OPC_Illegal,
-    OPC_Illegal,
-    OPC_Illegal,
-    OPC_6502_75,
-    OPC_6502_76,
-    OPC_Illegal,
-    OPC_6502_78,
-    OPC_6502_79,
-    OPC_Illegal,
-    OPC_Illegal,
-    OPC_Illegal,
-    OPC_6502_7D,
-    OPC_6502_7E,
-    OPC_Illegal,
-    OPC_Illegal,
-    OPC_6502_81,
-    OPC_Illegal,
-    OPC_Illegal,
-    OPC_6502_84,
-    OPC_6502_85,
-    OPC_6502_86,
-    OPC_Illegal,
-    OPC_6502_88,
-    OPC_Illegal,
-    OPC_6502_8A,
-    OPC_Illegal,
-    OPC_6502_8C,
-    OPC_6502_8D,
-    OPC_6502_8E,
-    OPC_Illegal,
-    OPC_6502_90,
-    OPC_6502_91,
-    OPC_Illegal,
-    OPC_Illegal,
-    OPC_6502_94,
-    OPC_6502_95,
-    OPC_6502_96,
-    OPC_Illegal,
-    OPC_6502_98,
-    OPC_6502_99,
-    OPC_6502_9A,
-    OPC_Illegal,
-    OPC_Illegal,
-    OPC_6502_9D,
-    OPC_Illegal,
-    OPC_Illegal,
-    OPC_6502_A0,
-    OPC_6502_A1,
-    OPC_6502_A2,
-    OPC_Illegal,
-    OPC_6502_A4,
-    OPC_6502_A5,
-    OPC_6502_A6,
-    OPC_Illegal,
-    OPC_6502_A8,
-    OPC_6502_A9,
-    OPC_6502_AA,
-    OPC_Illegal,
-    OPC_6502_AC,
-    OPC_6502_AD,
-    OPC_6502_AE,
-    OPC_Illegal,
-    OPC_6502_B0,
-    OPC_6502_B1,
-    OPC_Illegal,
-    OPC_Illegal,
-    OPC_6502_B4,
-    OPC_6502_B5,
-    OPC_6502_B6,
-    OPC_Illegal,
-    OPC_6502_B8,
-    OPC_6502_B9,
-    OPC_6502_BA,
-    OPC_Illegal,
-    OPC_6502_BC,
-    OPC_6502_BD,
-    OPC_6502_BE,
-    OPC_Illegal,
-    OPC_6502_C0,
-    OPC_6502_C1,
-    OPC_Illegal,
-    OPC_Illegal,
-    OPC_6502_C4,
-    OPC_6502_C5,
-    OPC_6502_C6,
-    OPC_Illegal,
-    OPC_6502_C8,
-    OPC_6502_C9,
-    OPC_6502_CA,
-    OPC_Illegal,
-    OPC_6502_CC,
-    OPC_6502_CD,
-    OPC_6502_CE,
-    OPC_Illegal,
-    OPC_6502_D0,
-    OPC_6502_D1,
-    OPC_Illegal,
-    OPC_Illegal,
-    OPC_Illegal,
-    OPC_6502_D5,
-    OPC_6502_D6,
-    OPC_Illegal,
-    OPC_6502_D8,
-    OPC_6502_D9,
-    OPC_Illegal,
-    OPC_Illegal,
-    OPC_Illegal,
-    OPC_6502_DD,
-    OPC_6502_DE,
-    OPC_Illegal,
-    OPC_6502_E0,
-    OPC_6502_E1,
-    OPC_Illegal,
-    OPC_Illegal,
-    OPC_6502_E4,
-    OPC_6502_E5,
-    OPC_6502_E6,
-    OPC_Illegal,
-    OPC_6502_E8,
-    OPC_6502_E9,
-    OPC_6502_EA,
-    OPC_Illegal,
-    OPC_6502_EC,
-    OPC_6502_ED,
-    OPC_6502_EE,
-    OPC_Illegal,
-    OPC_6502_F0,
-    OPC_6502_F1,
-    OPC_Illegal,
-    OPC_Illegal,
-    OPC_Illegal,
-    OPC_6502_F5,
-    OPC_6502_F6,
-    OPC_Illegal,
-    OPC_6502_F8,
-    OPC_6502_F9,
-    OPC_Illegal,
-    OPC_Illegal,
-    OPC_Illegal,
-    OPC_6502_FD,
-    OPC_6502_FE,
-    OPC_Illegal,
-};
+/* The actual CPU instance */
+CPUCore*        CPU = 0;
 
 
 
 /*****************************************************************************/
-/*                                  Code                                    */
+/*                                          Code                                    */
 /*****************************************************************************/
 
 
 
-void CPUInit (void)
-/* Initialize the CPU */
-{
-    RESET ();
-}
-
-
-
-void IRQRequest (void)
-/* Generate an IRQ */
-{
-    HaveIRQRequest = 1;
-}
-
-
-
-void NMIRequest (void)
-/* Generate an NMI */
-{
-    HaveNMIRequest = 1;
-}
-
-
-
-void RESET (void)
-/* Generate a CPU RESET */
-{
-    CPUHalted = HaveIRQRequest = HaveNMIRequest = 0;
-    Regs.PC = MemReadWord (0xFFFC);
-}
-
-
-
-void Break (const char* Format, ...)
-/* Stop running and display the given message */
+CPUCore* NewCPUCore (const char* Name, unsigned AddrSpaceSize)
+/* Create and return a new CPU including it's address space */
 {
-    va_list ap;
-    va_start (ap, Format);
-    SB_VPrintf (&BreakMsg, Format, ap);
-    va_end (ap);
-}
-
-
+    CPUCore* C;
 
-void CPURun (void)
-/* Run one CPU instruction */
-{
-    /* If the CPU is halted, do nothing */
-    if (CPUHalted) {
-        return;
+    /* Make sure this is a 6502 CPU for now */
+    if (strcmp (Name, "6502") != 0) {
+        Error ("Unknown CPU type `%s'", Name);
     }
 
-    /* If we have an NMI request, handle it */
-    if (HaveNMIRequest) {
-
-        HaveNMIRequest = 0;
-        PUSH (PCH);
-        PUSH (PCL);
-        PUSH (Regs.SR);
-        SET_IF (1);
-        Regs.PC = MemReadWord (0xFFFA);
-        Cycles = 7;
-
-    } else if (HaveIRQRequest && GET_IF () == 0) {
-
-        HaveIRQRequest = 0;
-        PUSH (PCH);
-        PUSH (PCL);
-        PUSH (Regs.SR);
-        SET_IF (1);
-        Regs.PC = MemReadWord (0xFFFE);
-        Cycles = 7;
+    /* Allocate memory */
+    C = xmalloc (sizeof (*C));
 
-    } else {
+    /* Initialize the data */
+    C->Handle = 0;              /* ### */
+    C->AS     = NewAddressSpace (AddrSpaceSize);
 
-        /* Normal instruction - read the next opcode */
-        unsigned char OPC = MemReadByte (Regs.PC);
-
-        /* Execute it */
-        OPCTable[OPC] ();
-
-    }
-
-    /* Count cycles */
-    TotalCycles += Cycles;
-
-    if (SB_GetLen (&BreakMsg) > 0) {
-        printf ("%.*s\n", SB_GetLen (&BreakMsg), SB_GetConstBuf (&BreakMsg));
-        SB_Clear (&BreakMsg);
-    }
+    /* Return the new CPU core */
+    return C;
 }
 
 
 
-#if 0
-    if ((++I & 0xFF) == 0)
-    printf ("%9lu %06X %02X A=%02X X=%02X Y=%02X %c%c%c%c%c%c%c\n",
-            TotalCycles, Regs.PC, OPC, Regs.AC, Regs.XR, Regs.YR,
-            GET_SF()? 'S' : '-',
-            GET_ZF()? 'Z' : '-',
-            GET_CF()? 'C' : '-',
-            GET_IF()? 'I' : '-',
-            GET_BF()? 'B' : '-',
-            GET_DF()? 'D' : '-',
-            GET_OF()? 'V' : '-');
-#endif
-
-
index b88617143e9cdd95423baacf097d5bb3d570822d..28b9351ff4fbe21618353c07ef8a8e1c9a2cc1e2 100644 (file)
@@ -1,15 +1,15 @@
 /*****************************************************************************/
 /*                                                                           */
-/*                                   cpucore.h                               */
+/*                                 cpucore.h                                 */
 /*                                                                           */
-/*                        CPU core for the 6502 simulator                    */
+/*                     CPU definition for the simulator                      */
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2002-2003 Ullrich von Bassewitz                                       */
-/*               Römerstrasse 52                                             */
-/*               D-70794 Filderstadt                                         */
-/* EMail:        uz@cc65.org                                                 */
+/* (C) 2003-2012, Ullrich von Bassewitz                                      */
+/*                Roemerstrasse 52                                           */
+/*                D-70794 Filderstadt                                        */
+/* EMail:         uz@cc65.org                                                */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
 
 
 /* sim65 */
-#include "cpuregs.h"
+#include "addrspace.h"
 
 
 
 /*****************************************************************************/
-/*                                  Data                                    */
+/*                                          Data                                    */
 /*****************************************************************************/
 
 
 
-/* Registers */
-extern CPURegs Regs;
+/* CPU core structure */
+typedef struct CPUCore CPUCore;
+struct CPUCore {
+    void*           Handle;             /* Pointer to shared lib handle */
+    AddressSpace*   AS;                 /* Address space */
+};
+
+/* The actual CPU instance */
+extern CPUCore*         CPU;
 
 
 
 /*****************************************************************************/
-/*                                  Code                                    */
+/*                                          Code                                    */
 /*****************************************************************************/
 
 
 
-void CPUInit (void);
-/* Initialize the CPU */
-
-void RESET (void);
-/* Generate a CPU RESET */
-
-void IRQRequest (void);
-/* Generate an IRQ */
-
-void NMIRequest (void);
-/* Generate an NMI */
-
-void Break (const char* Format, ...);
-/* Stop running and display the given message */
-
-void CPURun (void);
-/* Run one CPU instruction */
+CPUCore* NewCPUCore (const char* Name, unsigned AddrSpaceSize);
+/* Create and return a new CPU including it's address space */
 
 
 
@@ -86,3 +78,4 @@ void CPURun (void);
 
 
 
+
index bbde6f84d5c8529ac56fa1ace03ede2365a0a268..fe70538bed333b2fe2b67da6e0a019d7b7b35a38 100644 (file)
@@ -12,7 +12,7 @@ COMMON        = ../common
 
 #
 CC     = gcc
-CFLAGS         = -g -O2 -Wall -W -std=c89
+CFLAGS         = -g -Wall -W -std=c89
 override CFLAGS += -I$(COMMON)
 EBIND  = emxbind
 LDFLAGS        = -ldl
@@ -27,13 +27,13 @@ OBJS =      addrspace.o     \
        chip.o          \
        chippath.o      \
        config.o        \
+        cpu-6502.o      \
        cpucore.o       \
        cputype.o       \
        error.o         \
        global.o        \
        location.o      \
        main.o          \
-       memory.o        \
        scanner.o       \
        system.o
 
index dac80a450f592500d4f2a9d9239473f46960bc2e..90edf46e610ec57f8d6afff9d76ee44275417937 100644 (file)
@@ -6,10 +6,10 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2002-2003 Ullrich von Bassewitz                                       */
-/*               Römerstrasse 52                                             */
-/*               D-70794 Filderstadt                                         */
-/* EMail:        uz@cc65.org                                                 */
+/* (C) 2002-2012, Ullrich von Bassewitz                                      */
+/*                Roemerstrasse 52                                           */
+/*                D-70794 Filderstadt                                        */
+/* EMail:         uz@cc65.org                                                */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
index 6874e641123b4e13f4a562ae004be528bf31d64f..cafca005279215847defdf737a2877cb8a6a2ea5 100644 (file)
@@ -6,10 +6,10 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 2002-2003 Ullrich von Bassewitz                                       */
-/*               Römerstrasse 52                                             */
-/*               D-70794 Filderstadt                                         */
-/* EMail:        uz@cc65.org                                                 */
+/* (C) 2002-2012, Ullrich von Bassewitz                                      */
+/*                Roemerstrasse 52                                           */
+/*                D-70794 Filderstadt                                        */
+/* EMail:         uz@cc65.org                                                */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
index 3e6ab739f6e4dcc5524050fbda22b769da2a2a7c..86c88fb6f3a312dc3d3594375a3ff6c085312712 100644 (file)
@@ -6,10 +6,10 @@
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998-2003 Ullrich von Bassewitz                                       */
-/*               Römerstrasse 52                                             */
-/*               D-70794 Filderstadt                                         */
-/* EMail:        uz@cc65.org                                                 */
+/* (C) 1998-2012, Ullrich von Bassewitz                                      */
+/*                Roemerstrasse 52                                           */
+/*                D-70794 Filderstadt                                        */
+/* EMail:         uz@cc65.org                                                */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
@@ -57,7 +57,7 @@
 
 /* Current token and attributes */
 cfgtok_t               CfgTok;
-char                           CfgSVal [CFG_MAX_IDENT_LEN+1];
+StrBuf                 CfgSVal = STATIC_STRBUF_INITIALIZER;
 unsigned long           CfgIVal;
 
 /* Error location */
@@ -266,7 +266,7 @@ Again:
            I = 0;
            while (C != '\"') {
                if (C == EOF || C == '\n') {
-                   Error ("%s(%u): Unterminated string", CfgName, InputLine);
+                   Error ("%s(%u): Unterminated string", CfgName, InputLine);
                }
                if (I < CFG_MAX_IDENT_LEN) {
                    CfgSVal [I++] = C;
index 3066e15dfd6d06548ed519f943367e9f24731622..5cb2342b202d8d5154b47430268cb73455954db8 100644 (file)
@@ -1,15 +1,15 @@
 /*****************************************************************************/
 /*                                                                           */
-/*                                scanner.h                                 */
+/*                                scanner.h                                 */
 /*                                                                           */
 /*            Configuration file scanner for the sim65 6502 simulator        */
 /*                                                                           */
 /*                                                                           */
 /*                                                                           */
-/* (C) 1998-2003 Ullrich von Bassewitz                                       */
-/*               Römerstrasse 52                                             */
-/*               D-70794 Filderstadt                                         */
-/* EMail:        uz@cc65.org                                                 */
+/* (C) 1998-2012, Ullrich von Bassewitz                                      */
+/*                Roemerstrasse 52                                           */
+/*                D-70794 Filderstadt                                        */
+/* EMail:         uz@cc65.org                                                */
 /*                                                                           */
 /*                                                                           */
 /* This software is provided 'as-is', without any expressed or implied       */
@@ -40,6 +40,7 @@
 
 /* common */
 #include "attrib.h"
+#include "strbuf.h"
 
 
 
@@ -67,11 +68,10 @@ typedef enum {
 
     /* Primary blocks */
     CFGTOK_CPU,
-    CFGTOK_MEMORY,
+    CFGTOK_ADDRSPACE,
 
-    /* CPU block */
+    /* Secondary stuff */
     CFGTOK_TYPE,
-    CFGTOK_ADDRSPACE,
 
     /* Special identifiers */
     CFGTOK_TRUE,
@@ -92,9 +92,8 @@ struct IdentTok {
 
 
 /* Current token and attributes */
-#define CFG_MAX_IDENT_LEN  255
 extern cfgtok_t                CfgTok;
-extern char                    CfgSVal [CFG_MAX_IDENT_LEN+1];
+extern StrBuf          CfgSVal;
 extern unsigned long   CfgIVal;
 
 /* Error location */
index fd97c122320bf489fbaeb89bf4fcb40da3acabe7..7eadc6e63a98b98438c180cb0a3b5087cea52b38 100644 (file)
@@ -89,6 +89,12 @@ struct SimData {
      * true. If not found, return false.
      */
 
+    unsigned char (*ReadCtrl) (unsigned Addr);
+    /* Read from the given address without triggering any additional action */
+
+    void (*WriteCtrl) (unsigned Addr, unsigned char Val);
+    /* Write to the given address without triggering additional action */
+
     void (*Break) (const char* Format, ...);
     /* Stop the CPU and display the given message */
 
@@ -98,7 +104,7 @@ struct SimData {
     void (*NMI) (void);
     /* Issue an nmi request */
 
-    
+
 
 };