]> Shamusworld >> Repos - stargem2/commitdiff
Finalizing move to trunk...
authorShamus Hammons <jlhamm@acm.org>
Tue, 29 May 2007 03:43:29 +0000 (03:43 +0000)
committerShamus Hammons <jlhamm@acm.org>
Tue, 29 May 2007 03:43:29 +0000 (03:43 +0000)
Makefile
src/dis6808.cpp
src/dis6809.cpp
src/sound.cpp
src/stargem2.cpp
src/v6808.cpp
src/v6808.h
src/v6809.cpp
src/v6809.h
src/video.cpp
stargem2.cfg

index 40b8c565fc5666e20a01b3b12b9138b98e5471a7..c8e488649902f37c4784557988ce74bdc4ecc68c 100755 (executable)
--- a/Makefile
+++ b/Makefile
@@ -44,9 +44,9 @@ TARGET     = stargem2
 
 CFLAGS   = -MMD -Wall -Wno-switch -Wno-uninitialized -O2 -D$(SYSTYPE) -fomit-frame-pointer `sdl-config --cflags`
 CPPFLAGS = -MMD -Wall -Wno-switch -Wno-non-virtual-dtor -Wno-uninitialized -O2 -D$(SYSTYPE) \
-               -fomit-frame-pointer `sdl-config --cflags`
-#              -fomit-frame-pointer `sdl-config --cflags` -g
-#              -fomit-frame-pointer `sdl-config --cflags` -DLOG_UNMAPPED_MEMORY_ACCESSES
+               -fomit-frame-pointer `sdl-config --cflags` \
+               -g
+#              -DLOG_UNMAPPED_MEMORY_ACCESSES
 
 LDFLAGS =
 
@@ -54,8 +54,6 @@ LIBS = -L/usr/local/lib `sdl-config $(SDLLIBTYPE)` -lstdc++ -lz $(GLLIB)
 
 INCS = -I. -Isrc -I/usr/local/include
 
-#THECC = $(CC) $(CFLAGS) $(INCS)
-
 OBJS = \
        obj/dis6808.o       \
        obj/dis6809.o       \
index 98b1bf4bfc9199353007a277f6d3f289559faa2b..17cd301fd51f4c45b5e0a70c069466a63a799060 100755 (executable)
@@ -103,34 +103,43 @@ int Decode6808(uint16 pc)
 {
        char outbuf[80];
 
-       uint16 addr = pc;
+       uint16 addr = pc, offset;
        uint8 opcode = soundCPU.RdMem(addr++);                          // Get the opcode
 
        switch (op_mat[opcode])                                                         // Decode the addressing mode...
        {
        case 0:                                                                                         // Illegal
-               sprintf(outbuf, "???");
+               sprintf(outbuf, "???          ");
                break;
        case 1:                                                                                         // Zero page
-               sprintf(outbuf, "%s $%02X", mnemonics[opcode], soundCPU.RdMem(addr++));
+               sprintf(outbuf, "%s $%02X    ", mnemonics[opcode], soundCPU.RdMem(addr++));
                break;
        case 2:                                                                                         // Absolute
-               sprintf(outbuf, "%s $%04X", mnemonics[opcode], (soundCPU.RdMem(addr++) << 8) | soundCPU.RdMem(addr++));
+//             sprintf(outbuf, "%s $%04X", mnemonics[opcode], (soundCPU.RdMem(addr++) << 8) | soundCPU.RdMem(addr++));
+               offset = (soundCPU.RdMem(addr + 0) << 8) | soundCPU.RdMem(addr + 1);
+               addr += 2;
+               sprintf(outbuf, "%s $%04X  ", mnemonics[opcode], offset);
                break;
        case 3:                                                                                         // Relative
-               sprintf(outbuf, "%s $%04X", mnemonics[opcode], ++addr + (int16)(int8)soundCPU.RdMem(addr));
+//             sprintf(outbuf, "%s $%04X", mnemonics[opcode], ++addr + (int16)(int8)soundCPU.RdMem(addr));
+               offset = addr + 1 + (int16)(int8)soundCPU.RdMem(addr);
+               addr++;
+               sprintf(outbuf, "%s $%04X  ", mnemonics[opcode], offset);
                break;
        case 5:                                                                                         // Inherent
-               sprintf(outbuf, "%s ", mnemonics[opcode]);
+               sprintf(outbuf, "%s        ", mnemonics[opcode]);
                break;
        case 7:                                                                                         // Indexed
-               sprintf(outbuf, "%s $%02X,X", mnemonics[opcode], soundCPU.RdMem(addr++));
+               sprintf(outbuf, "%s $%02X,X  ", mnemonics[opcode], soundCPU.RdMem(addr++));
                break;
        case 8:                                                                                         // Immediate
-               sprintf(outbuf, "%s #$%02X", mnemonics[opcode], soundCPU.RdMem(addr++));
+               sprintf(outbuf, "%s #$%02X   ", mnemonics[opcode], soundCPU.RdMem(addr++));
                break;
        case 9:                                                                                         // Long Immediate
-               sprintf(outbuf, "%s #$%04X", mnemonics[opcode], (soundCPU.RdMem(addr++) << 8) | soundCPU.RdMem(addr++));
+//             sprintf(outbuf, "%s #$%04X", mnemonics[opcode], (soundCPU.RdMem(addr++) << 8) | soundCPU.RdMem(addr++));
+               offset = (soundCPU.RdMem(addr + 0) << 8) | soundCPU.RdMem(addr + 1);
+               addr += 2;
+               sprintf(outbuf, "%s #$%04X ", mnemonics[opcode], offset);
                break;
        }
 
index 320f9f240b28993bd1d86c0b82c5fbaeb2d5e5ba..fdb45d451bf82cdc6dc0f7106676ebeea4761374 100755 (executable)
@@ -217,7 +217,7 @@ int Decode6809(uint16 pc)
        char outbuf[80], mnem[6], tmp[30];
        uint8 opcode2, operand;
 
-       uint16 addr = pc;
+       uint16 addr = pc, offset;
 
        uint8 opcode = mainCPU.RdMem(addr++);                           // Get the opcode
        uint8 admode = op_mat1[opcode];                                         // addressing mode
@@ -245,13 +245,23 @@ int Decode6809(uint16 pc)
                sprintf(outbuf, "%s $%02X", mnem, mainCPU.RdMem(addr++));
                break;
        case 2:                                                                                         // Absolute
-               sprintf(outbuf, "%s $%04X", mnem, (mainCPU.RdMem(addr++) << 8) | mainCPU.RdMem(addr++));
+//             sprintf(outbuf, "%s $%04X", mnem, (mainCPU.RdMem(addr++) << 8) | mainCPU.RdMem(addr++));
+               offset = (mainCPU.RdMem(addr) << 8) | mainCPU.RdMem(addr + 1);
+               addr += 2;
+               sprintf(outbuf, "%s $%04X", mnem, offset);
                break;
        case 3:                                                                                         // Relative
-               sprintf(outbuf, "%s $%04X", mnem, ++addr + (int16)(int8)mainCPU.RdMem(addr));
+//DISNOWOK--FIX
+//             sprintf(outbuf, "%s $%04X", mnem, ++addr + (int16)((int8)mainCPU.RdMem(addr)));
+               offset = addr + 1 + (int16)(int8)mainCPU.RdMem(addr);
+               addr++;
+               sprintf(outbuf, "%s $%04X", mnem, offset);
                break;
        case 4:                                                                                         // Long Relative
-               sprintf(outbuf, "%s $%04X", mnem, addr + (int16)((mainCPU.RdMem(addr++) << 8) | mainCPU.RdMem(addr++)) + 2);
+//             sprintf(outbuf, "%s $%04X", mnem, addr + (int16)((mainCPU.RdMem(addr++) << 8) | mainCPU.RdMem(addr++)) + 2);
+               offset = addr + (int16)((mainCPU.RdMem(addr) << 8) | mainCPU.RdMem(addr + 1)) + 2;
+               addr += 2;
+               sprintf(outbuf, "%s $%04X", mnem, offset);
                break;
        case 5:                                                                                         // Inherent
                sprintf(outbuf, "%s ", mnem);
@@ -301,7 +311,8 @@ int Decode6809(uint16 pc)
                                        sprintf(tmp, "($%02X,%s)", boff, iregs[reg]);
                                        break;
                                case 9:
-                                       woff = (mainCPU.RdMem(addr++) << 8) | mainCPU.RdMem(addr++);
+                                       woff = (mainCPU.RdMem(addr) << 8) | mainCPU.RdMem(addr + 1);
+                                       addr += 2;
                                        sprintf(tmp, "($%04X,%s)", woff, iregs[reg]);
                                        break;
                                case 11:  sprintf(tmp, "(D,%s)", iregs[reg]);  break;
@@ -310,11 +321,13 @@ int Decode6809(uint16 pc)
                                        sprintf(tmp, "($%02X,PC)", boff);
                                        break;
                                case 13:  
-                                       woff = (mainCPU.RdMem(addr++) << 8) | mainCPU.RdMem(addr++);
+                                       woff = (mainCPU.RdMem(addr) << 8) | mainCPU.RdMem(addr + 1);
+                                       addr += 2;
                                        sprintf(tmp, "($%04X,PC)", woff);
                                        break;
                                case 15:
-                                       woff = (mainCPU.RdMem(addr++) << 8) | mainCPU.RdMem(addr++);
+                                       woff = (mainCPU.RdMem(addr) << 8) | mainCPU.RdMem(addr + 1);
+                                       addr += 2;
                                        sprintf(tmp, "[$%04X]", woff);
                                        break;
                                default:
@@ -337,7 +350,8 @@ int Decode6809(uint16 pc)
                                        sprintf(tmp, "($%02X),%s", boff, iregs[reg]);
                                        break;
                                case 9:
-                                       woff = (mainCPU.RdMem(addr++) << 8) | mainCPU.RdMem(addr++);
+                                       woff = (mainCPU.RdMem(addr) << 8) | mainCPU.RdMem(addr + 1);
+                                       addr += 2;
                                        sprintf(tmp, "($%04X),%s", woff, iregs[reg]);
                                        break;
                                case 11:
@@ -347,8 +361,9 @@ int Decode6809(uint16 pc)
                                        boff = mainCPU.RdMem(addr++);
                                        sprintf(tmp, "($%02X),PC", boff);
                                        break;
-                               case 13:  
-                                       woff = (mainCPU.RdMem(addr++) << 8) | mainCPU.RdMem(addr++);
+                               case 13:
+                                       woff = (mainCPU.RdMem(addr) << 8) | mainCPU.RdMem(addr + 1);
+                                       addr += 2;
                                        sprintf(tmp, "($%04X),PC", woff);
                                        break;
                                default:
@@ -363,7 +378,10 @@ int Decode6809(uint16 pc)
                sprintf(outbuf, "%s #$%02X", mnem, mainCPU.RdMem(addr++));
                break;
        case 9:                                                                                         // Long Immediate
-               sprintf(outbuf, "%s #$%04X", mnem, (mainCPU.RdMem(addr++) << 8) | mainCPU.RdMem(addr++));
+//             sprintf(outbuf, "%s #$%04X", mnem, (mainCPU.RdMem(addr++) << 8) | mainCPU.RdMem(addr++));
+               offset = (mainCPU.RdMem(addr) << 8) | mainCPU.RdMem(addr + 1);
+               addr += 2;
+               sprintf(outbuf, "%s #$%04X", mnem, offset);
                break;
        }
 
index 6cc1860d29ccea31ef5eb6c0c9842be42bb4fdac..b67659b0a4f7daeb9cda3e859820b134d8785638 100755 (executable)
@@ -81,7 +81,8 @@ void SoundDone(void)
 void SDLSoundCallback(void * userdata, Uint8 * buffer, int length)
 {
        extern V6808REGS soundCPU;
-       extern uint8 * sram;
+//     extern uint8 * sram;
+       extern uint8 sram[];
        int cnt = 0;
 
        while (cnt != length)
index ee1b814df06f51fcf20a007d67fb3845c7832ab3..edad8fdf8c2697a5b55e5d79ed8a0c3404bfbcf7 100755 (executable)
 #include "dis6809.h"
 #include "dis6808.h"
 
+#define __DEBUG__
+
 using namespace std;
 
-#define ROM1           "01"
-#define ROM2           "02"
-#define ROM3           "03"
-#define ROM4           "04"
-#define ROM5           "05"
-#define ROM6           "06"
-#define ROM7           "07"
-#define ROM8           "08"
-#define ROM9           "09"
-#define ROM10          "10"
-#define ROM11          "11"
-#define ROM12          "12"
-#define SOUNDROM       "sg.snd"
+#define SOUNDROM       "ROMs/sg.snd"
 #define CMOS           "cmos.ram"
 #define SAVESTATE      "sg2.state"
 
 // Global variables
 
-uint8 * gram, * grom, * sram, * srom;                  // RAM & ROM pointers
+uint8 gram[0x10000], grom[0x10000], sram[0x10000], srom[0x10000]; // RAM & ROM spaces
 V6809REGS mainCPU;
 V6808REGS soundCPU;
 uint8 color[16];
@@ -59,17 +49,6 @@ uint32 palette[256];
 
 // Local variables
 
-//static uint8 lastKeyPressed = 0;
-//static bool keyDown = false;
-
-//static FloppyDrive floppyDrive;
-
-//enum { LC_BANK_1, LC_BANK_2 };
-
-//static uint8 visibleBank = LC_BANK_1;
-//static bool readRAM = false;
-//static bool writeRAM = false;
-
 static bool running = true;                                            // Machine running state flag...
 static uint32 startTicks;
 static uint8 * keys;                                                   // SDL raw keyboard matrix
@@ -187,6 +166,11 @@ uint8 RdMem6808(uint16 addr)
 void WrMem6808(uint16 addr, uint8 b)
 {
        sram[addr] = b;
+
+       // A total guess, but let's try it...
+//It probably depends on how the PIA is configured, so this is most likely wrong.
+//     if (addr == 0x0401)
+//             soundCPU.cpuFlags &= ~V6808_ASSERT_LINE_IRQ;
 }
 
 //
@@ -194,18 +178,10 @@ void WrMem6808(uint16 addr, uint8 b)
 //
 bool LoadImg(char * filename, uint8 * ram, int size)
 {
-       char pathname[4096];
-
-       strcpy(pathname, settings.BIOSPath);
-       strcat(pathname, filename);
-
-       FILE * fp = fopen(pathname, "rb");
+       FILE * fp = fopen(filename, "rb");
 
        if (fp == NULL)
-       {
-               WriteLog("Could not open file '%s'!\n", pathname);
                return false;
-       }
 
        fread(ram, 1, size, fp);
        fclose(fp);
@@ -281,12 +257,11 @@ void SaveMachineState(void)
 //
 int main(int /*argc*/, char * /*argv*/[])
 {
-//     bool running;                                                                           // Machine running state flag...
-
-       LoadSettings();
        InitLog("stargem2.log");
        WriteLog("StarGem2 - A portable Stargate emulator by James L. Hammons\n");
 
+       LoadSettings();
+
        // Initialize Williams' palette (RGB coded as: 3 bits red, 3 bits green, 2 bits blue)
        for(uint32 i=0; i<256; i++)
                palette[i] =
@@ -300,32 +275,6 @@ int main(int /*argc*/, char * /*argv*/[])
                        | ((((i & 0x40) >> 6) * 71 + ((i & 0x80) >> 7) * 151) << 16) | 0xFF000000;
 #endif
 
-       gram = new uint8[0x10000];
-       grom = new uint8[0x10000];
-       sram = new uint8[0x10000];
-       srom = new uint8[0x10000];
-
-       if (gram == NULL)
-       {
-               WriteLog("Could not allocate RAM space!\nAborting!\n");
-               return -1;
-       }
-       else if (grom == NULL)
-       {
-               WriteLog("Could not allocate ROM space!\nAborting!\n");
-               return -1;
-       }
-       else if (sram == NULL)
-       {
-               WriteLog("Could not allocate sRAM space!\nAborting!\n");
-               return -1;
-       }
-       else if (srom == NULL)
-       {
-               WriteLog("Could not allocate sROM space!\nAborting!\n");
-               return -1;
-       }
-
        // Zero out memory
        for(long i=0; i<0x10000; i++)
                gram[i] = grom[i] = sram[i] = srom[i] = 0;
@@ -342,47 +291,34 @@ int main(int /*argc*/, char * /*argv*/[])
        soundCPU.WrMem = WrMem6808;
        soundCPU.cpuFlags |= V6808_ASSERT_LINE_RESET;
 
-       if (!LoadImg(CMOS, gram + 0xCC00, 0x400))
-               WriteLog("CMOS RAM not found!\n");
+       char ROMs[12][8] = {
+               "ROMs/01", "ROMs/02", "ROMs/03", "ROMs/04", "ROMs/05", "ROMs/06",
+               "ROMs/07", "ROMs/08", "ROMs/09", "ROMs/10", "ROMs/11", "ROMs/12"
+               };
 
-       if (!LoadImg(ROM1, grom + 0x0000, 0x1000))
-               return -1;
-
-       if (!LoadImg(ROM2, grom + 0x1000, 0x1000))
-               return -1;
-
-       if (!LoadImg(ROM3, grom + 0x2000, 0x1000))
-               return -1;
-
-       if (!LoadImg(ROM4, grom + 0x3000, 0x1000))
-               return -1;
-
-       if (!LoadImg(ROM5, grom + 0x4000, 0x1000))
-               return -1;
-
-       if (!LoadImg(ROM6, grom + 0x5000, 0x1000))
-               return -1;
-
-       if (!LoadImg(ROM7, grom + 0x6000, 0x1000))
-               return -1;
-
-       if (!LoadImg(ROM8, grom + 0x7000, 0x1000))
-               return -1;
-
-       if (!LoadImg(ROM9, grom + 0x8000, 0x1000))
-               return -1;
-
-       if (!LoadImg(ROM10, grom + 0xD000, 0x1000))
-               return -1;
+       for(int i=0; i<12; i++)
+       {
+               uint32 baseAddress = i * 0x1000;
 
-       if (!LoadImg(ROM11, grom + 0xE000, 0x1000))
-               return -1;
+               if (i > 8)
+                       baseAddress += 0x4000;
 
-       if (!LoadImg(ROM12, grom + 0xF000, 0x1000))
-               return -1;
+#if 0
+WriteLog("Loading ROM image '%s' at $%04X...\n", ROMs[i], baseAddress);
+#endif
+//             if (!LoadImg(ROMs[i], grom + (i * 0x1000), 0x1000))
+               if (!LoadImg(ROMs[i], grom + baseAddress, 0x1000))
+               {
+                       WriteLog("Could not open file '%s'!\n", ROMs[i]);
+                       return -1;
+               }
+       }
 
        if (!LoadImg(SOUNDROM, srom + 0xF800, 0x800))
+       {
+               WriteLog("Could not open file '%s'!\n", SOUNDROM);
                return -1;
+       }
 
        WriteLog("Stargate ROM images loaded...\n");
        WriteLog("About to initialize video...\n");
@@ -394,8 +330,15 @@ int main(int /*argc*/, char * /*argv*/[])
        }
 
        // Have to do this *after* video init but *before* sound init...!
+       WriteLog("About to load machine state...");
+
        if (!LoadMachineState())
                WriteLog("Machine state file not found!\n");
+       else
+               WriteLog("done!\n");
+
+       if (!LoadImg(CMOS, gram + 0xCC00, 0x400))
+               WriteLog("CMOS RAM not found!\n");
 
        WriteLog("About to intialize audio...\n");
        SoundInit();
@@ -584,6 +527,28 @@ for(int i=0; i<200; i++)
                HandleNextEvent();
        }
 
+#ifdef __DEBUG__
+WriteLog("\n");
+WriteLog("$C900 = $%02X (0=RAM)\n", gram[0xC900]);
+WriteLog("PC: %04X, X: %04X, Y: %04X, S: %04X, U: %04X, A: %02X, B: %02X, DP: %02X, CC: %02X\n", mainCPU.pc, mainCPU.x, mainCPU.y, mainCPU.s, mainCPU.u, mainCPU.a, mainCPU.b, mainCPU.dp, mainCPU.cc);
+WriteLog("\n");
+
+/*uint16 pc = mainCPU.pc;//0x15BA;
+for(int i=0; i<200; i++)
+//while (pc < 0x9000)
+{
+       pc += Decode6809(pc);
+       WriteLog("\n");
+}//*/
+
+/*uint32 pc = 0;
+while (pc < 0xFFFF)
+{
+       pc += Decode6809(pc);
+       WriteLog("\n");
+}//*/
+#endif
+
 #endif
 
        SoundDone();
@@ -592,11 +557,6 @@ for(int i=0; i<200; i++)
        SaveMachineState();
        LogDone();
 
-       delete[] gram;                                                          // Deallocate RAM & ROM spaces
-       delete[] grom;
-       delete[] sram;
-       delete[] srom;
-
        return 0;
 }
 
index e9c4253dce603a899047ad7a3d98b1729073590c..b26cb4af4e0a2551d2f1e86599a7d06101fdf8f2 100755 (executable)
@@ -1,8 +1,8 @@
 //
-// Virtual 6808 Emulator v1.2
+// Virtual 6808 Emulator v2.0
 //
 // by James L. Hammons
-// (c) 2006 Underground Software
+// (C) 2006 Underground Software
 //
 // JLH = James L. Hammons <jlhamm@acm.org>
 //
 // ---  ----------  ------------------------------------------------------------
 // JLH  06/15/2006  Added changelog ;-)
 // JLH  06/15/2006  Scrubbed all BYTE, WORD & DWORD references from the code
+// JLH  11/13/2006  Converted core to V65C02 macro style :-)
+// JLH  11/13/2006  Converted flags to unpacked and separate flags
 //
 
-// Mebbe someday I'll get around to fixing the core to be more like V65C02...
+// NOTE: V6808_STATE_WAI is not handled in the main loop correctly. !!! FIX !!!
+
+// Some random thoughts: Could there be a performance gain by breaking
+// out the flags in regs.cc into separate uint8 variables (or bools)?
+// You'd have to convert on entering and exiting the emulation loop, but I
+// think the perfomance hit would be negligible compared to the gain in not
+// having to mask and shift flags all the time. Investigate after the
+// conversion to macro style opcodes is completed. :-)
+// [DONE--remain to be seen if there is any performance increase]
 
 //#define __DEBUG__
 
 #include "log.h"
 #endif
 
+// Various macros
+
+#if 0
+#define CLR_Z                          (regs.cc &= ~FLAG_Z)
+#define CLR_ZN                         (regs.cc &= ~(FLAG_Z | FLAG_N))
+#define CLR_ZNC                                (regs.cc &= ~(FLAG_Z | FLAG_N | FLAG_C))
+#define CLR_NVC                                (regs.cc &= ~(FLAG_N | FLAG_V | FLAG_C))
+#define CLR_VC                         (regs.cc &= ~(FLAG_V | FLAG_C))
+#define CLR_V                          (regs.cc &= ~FLAG_V)
+#define CLR_N                          (regs.cc &= ~FLAG_N)
+#define SET_Z(r)                       (regs.cc = ((r) == 0 ? regs.cc | FLAG_Z : regs.cc & ~FLAG_Z))
+#define SET_N(r)                       (regs.cc = ((r) & 0x80 ? regs.cc | FLAG_N : regs.cc & ~FLAG_N))
+#define SET_V(a,b,r)           (regs.cc = ((b) ^ (a) ^ (r) ^ ((r) >> 1)) & 0x80 ? regs.cc | FLAG_V : regs.cc & ~FLAG_V)
+
+//Not sure that this code is computing the carry correctly... Investigate! [Seems to be]
+#define SET_C_ADD(a,b)         (regs.cc = ((uint8)(b) > (uint8)(~(a)) ? regs.cc | FLAG_C : regs.cc & ~FLAG_C))
+#define SET_C_CMP(a,b)         (regs.cc = ((uint8)(b) < (uint8)(a) ? regs.cc | FLAG_C : regs.cc & ~FLAG_C))
+#define SET_ZN(r)                      SET_N(r); SET_Z(r)
+#define SET_ZNC_ADD(a,b,r)     SET_N(r); SET_Z(r); SET_C_ADD(a,b)
+#define SET_ZNVC_CMP(a,b,r)    SET_N(r); SET_Z(r); SET_C_CMP(a,b); SET_V(a,b,r)
+
+#define SET_N16(r)                             (regs.cc = ((r) & 0x8000 ? regs.cc | FLAG_N : regs.cc & ~FLAG_N))
+#define SET_V16(a,b,r)         (regs.cc = ((b) ^ (a) ^ (r) ^ ((r) >> 1)) & 0x8000 ? regs.cc | FLAG_V : regs.cc & ~FLAG_V)
+#define SET_C_CMP16(a,b)               (regs.cc = ((uint16)(b) < (uint16)(a) ? regs.cc | FLAG_C : regs.cc & ~FLAG_C))
+#define SET_ZNVC_CMP16(a,b,r)  SET_N16(r); SET_Z(r); SET_C_CMP16(a,b); SET_V16(a,b,r)
+#else
+#define CLR_Z                                  (flagZ = 0)
+#define CLR_ZN                                 (flagZ = flagN = 0)
+#define CLR_ZNC                                        (flagZ = flagN = flagC = 0)
+#define CLR_NVC                                        (flagN = flagV = flagC = 0)
+#define CLR_VC                                 (flagV = flagC = 0)
+#define CLR_V                                  (flagV = 0)
+#define CLR_N                                  (flagN = 0)
+#define SET_Z(r)                               (flagZ = ((r) == 0 ? 1 : 0))
+#define SET_N(r)                               (flagN = ((r) & 0x80) >> 7)
+#define SET_V(a,b,r)                   (flagV = (((b) ^ (a) ^ (r) ^ ((r) >> 1)) & 0x80) >> 7)
+
+#define SET_C_CMP(a,b)                 (flagC = ((uint8)(b) < (uint8)(a) ? 1 : 0))
+#define SET_ZN(r)                              SET_N(r); SET_Z(r)
+#define SET_ZNC_ADD(a,b,r)             SET_N(r); SET_Z(r); SET_C_ADD(a,b)
+#define SET_ZNVC_CMP(a,b,r)            SET_N(r); SET_Z(r); SET_C_CMP(a,b); SET_V(a,b,r)
+
+#define SET_N16(r)                             (flagN = ((r) & 0x8000) >> 15)
+#define SET_V16(a,b,r)                 (flagV = (((b) ^ (a) ^ (r) ^ ((r) >> 1)) & 0x8000) >> 15)
+#define SET_C_CMP16(a,b)               (flagC = ((uint16)(b) < (uint16)(a) ? 1 : 0))
+#define SET_ZNVC_CMP16(a,b,r)  SET_N16(r); SET_Z(r); SET_C_CMP16(a,b); SET_V16(a,b,r)
+#endif
+
+//Small problem with the EA_ macros: ABS macros don't increment the PC!!! !!! FIX !!! [DONE, kinda]
+#define EA_IMM                         regs.pc++
+#define EA_ZP                          regs.RdMem(regs.pc++)
+#define EA_ZP_X                                (regs.RdMem(regs.pc++) + regs.x)
+#define EA_ABS                         RdMemW(regs.pc)
+
+#define READ_IMM                       regs.RdMem(EA_IMM)
+#define READ_ZP                                regs.RdMem(EA_ZP)
+#define READ_ZP_X                      regs.RdMem(EA_ZP_X)
+#define READ_ABS                       regs.RdMem(EA_ABS);                     regs.pc += 2
+
+#define READ_IMM16                     RdMemW(regs.pc);                        regs.pc += 2
+#define READ_ZP16                      RdMemW(EA_ZP)
+#define READ_ZP_X16                    RdMemW(EA_ZP_X)
+#define READ_ABS16                     RdMemW(EA_ABS);                         regs.pc += 2
+
+#define READ_IMM_WB(v)         uint16 addr = EA_IMM;           v = regs.RdMem(addr)
+#define READ_ZP_WB(v)          uint16 addr = EA_ZP;            v = regs.RdMem(addr)
+#define READ_ZP_X_WB(v)                uint16 addr = EA_ZP_X;          v = regs.RdMem(addr)
+#define READ_ABS_WB(v)         uint16 addr = EA_ABS;           v = regs.RdMem(addr); regs.pc += 2
+
+#define WRITE_BACK(d)          regs.WrMem(addr, (d))
+
+#define PULL                           regs.RdMem(regs.s++)
+#define PUSH(r)                                regs.WrMem(--regs.s, (r))
+#define PULL16                         RdMemW(regs.s);                         regs.s += 2
+#define PUSH16(r)                      regs.WrMem(--regs.s, (r) & 0xFF); regs.WrMem(--regs.s, (r) >> 8)
+
+#define PACK_FLAGS                     ((regs.cc & 0xC0) | (flagH << 5) | (flagI << 4) | (flagN << 3) | (flagZ << 2) | (flagV << 1) | flagC)
+#define UNPACK_FLAGS           flagH = (regs.cc & FLAG_H) >> 5; \
+       flagI = (regs.cc & FLAG_I) >> 4; \
+       flagN = (regs.cc & FLAG_N) >> 3; \
+       flagZ = (regs.cc & FLAG_Z) >> 2; \
+       flagV = (regs.cc & FLAG_V) >> 1; \
+       flagC = (regs.cc & FLAG_C)
+
 // Private global variables
 
 static V6808REGS regs;
-static uint16 addr;
-static uint8 tmp;
+static uint8 flagH, flagI, flagN, flagZ, flagV, flagC;
 
 static uint8 CPUCycles[256] = {
        1,  2,  1,  1,  1,  1,  2,  2,  4,  4,  2,  2,  2,  2,  2,  2,
@@ -50,1756 +143,1912 @@ static uint8 CPUCycles[256] = {
 
 // Private function prototypes
 
-static uint16 FetchW(void);
 static uint16 RdMemW(uint16);
-static void WrMemW(uint16, uint16);
-
-//
-// Fetch a word out of 6808 memory (little endian format)
-// This is a leftover from when fetches were separated from garden variety reads...
-//
-static uint16 FetchW()
-{
-       uint16 w = RdMemW(regs.pc);
-       regs.pc += 2;
-       return w;
-}
 
 //
 // Read a word out of 6808 memory (little endian format)
 //
-static uint16 RdMemW(uint16 address)
+static inline uint16 RdMemW(uint16 address)
 {
        return (uint16)(regs.RdMem(address) << 8) | regs.RdMem(address + 1);
 }
 
 //
-// Write a word into 6808 memory (little endian format)
-//
-static void WrMemW(uint16 address, uint16 w)
-{
-       regs.WrMem(address + 0, w >> 8);
-       regs.WrMem(address + 1, w & 0xFF);
-}
-
+// 6808 OPCODE IMPLEMENTATION
 //
-// Function to decode IDX data
+// NOTE: Lots of macros are used here to save a LOT of typing. Also
+//       helps speed the debugging process. :-) Because of this, combining
+//       certain lines may look like a good idea but would end in disaster.
+//       You have been warned! ;-)
 //
-inline uint16 DecodeIDX(uint8 code)
-{
-       return regs.x + code;
-}
 
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Add                     |ADDA |8B 2 2|9B 3 2|AB 5 2|BB 4 3|      |A=A+M     |T TTTT|
+                        |ADDB |CB 2 2|DB 3 2|EB 5 2|FB 4 3|      |B=B+M     |T TTTT|
+Add Accumulators        |ABA  |      |      |      |      |1B 2 1|A=A+B     |T TTTT|
+*/
 
-//
-// Opcode Functions (Mostly correct... Yikes!)
-//
+// ADD opcodes
 
-static void Op01(void)                                                 // NOP
+//#define OP_ADD_HANDLER(m, acc) \
+       uint16 sum = (uint16)(acc) + (m); \
+       regs.cc = (regs.cc & ~FLAG_C) | (sum >> 8); \
+       regs.cc = (regs.cc & ~FLAG_H) | ((sum << 1) & FLAG_H); \
+       SET_V(m, acc, sum); \
+       (acc) = sum & 0xFF; \
+       SET_ZN(acc)
+#define OP_ADD_HANDLER(m, acc) \
+       uint16 sum = (uint16)(acc) + (m); \
+       flagC = sum >> 8; \
+       flagH = (sum >> 4) & 0x01; \
+       SET_V(m, acc, sum); \
+       (acc) = sum & 0xFF; \
+       SET_ZN(acc)
+
+static void Op8B(void)                                                 // ADDA #
 {
+       uint16 m = READ_IMM;
+       OP_ADD_HANDLER(m, regs.a);
 }
 
-static void Op06(void)                                                 // TAP
+static void Op9B(void)                                                 // ADDA ZP
 {
-       regs.cc = regs.a;
+       uint16 m = READ_ZP;
+       OP_ADD_HANDLER(m, regs.a);
 }
 
-static void Op07(void)                                                 // TPA
+static void OpAB(void)                                                 // ADDA ZP, X
 {
-       regs.a = regs.cc;
+       uint16 m = READ_ZP_X;
+       OP_ADD_HANDLER(m, regs.a);
 }
 
-static void Op08(void)                                                 // INX
+static void OpBB(void)                                                 // ADDA ABS
 {
-       regs.x++;
-
-       (regs.x == 0 ? regs.cc |= FLAG_Z : regs.cc &= ~FLAG_Z);
+       uint16 m = READ_ABS;
+       OP_ADD_HANDLER(m, regs.a);
 }
 
-static void Op09(void)                                                 // DEX
+static void OpCB(void)                                                 // ADDB #
 {
-       regs.x--;
-
-       (regs.x == 0 ? regs.cc |= FLAG_Z : regs.cc &= ~FLAG_Z);
+       uint16 m = READ_IMM;
+       OP_ADD_HANDLER(m, regs.b);
 }
 
-static void Op0A(void)                                                 // CLV
+static void OpDB(void)                                                 // ADDB ZP
 {
-       regs.cc &= ~FLAG_V;
+       uint16 m = READ_ZP;
+       OP_ADD_HANDLER(m, regs.b);
 }
 
-static void Op0B(void)                                                 // SEV
+static void OpEB(void)                                                 // ADDB ZP, X
 {
-       regs.cc |= FLAG_V;
+       uint16 m = READ_ZP_X;
+       OP_ADD_HANDLER(m, regs.b);
 }
 
-static void Op0C(void)                                                 // CLC
+static void OpFB(void)                                                 // ADDB ABS
 {
-       regs.cc &= ~FLAG_C;
+       uint16 m = READ_ABS;
+       OP_ADD_HANDLER(m, regs.b);
 }
 
-static void Op0D(void)                                                 // SEC
+static void Op1B(void)                                                 // ABA
 {
-       regs.cc |= FLAG_C;
+       OP_ADD_HANDLER(regs.b, regs.a);
 }
 
-static void Op0E(void)                                                 // CLI
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Add with Carry          |ADCA |89 2 2|99 3 2|A9 5 2|B9 4 3|      |A=A+M+C   |T TTTT|
+                        |ADCB |C9 2 2|D9 3 2|E9 5 2|F9 4 3|      |B=B+M+C   |T TTTT|
+*/
+
+// ADC opcodes
+
+//#define OP_ADC_HANDLER(m, acc) \
+       uint16 sum = (uint16)acc + (m) + (uint16)(regs.cc & FLAG_C); \
+       regs.cc = (regs.cc & ~FLAG_C) | (sum >> 8); \
+       regs.cc = (regs.cc & ~FLAG_H) | ((sum << 1) & FLAG_H); \
+       SET_V(m, acc, sum); \
+       acc = sum & 0xFF; \
+       SET_ZN(acc)
+#define OP_ADC_HANDLER(m, acc) \
+       uint16 sum = (uint16)acc + (m) + (uint16)flagC; \
+       flagC = sum >> 8; \
+       flagH = (sum >> 4) & 0x01; \
+       SET_V(m, acc, sum); \
+       acc = sum & 0xFF; \
+       SET_ZN(acc)
+
+static void Op89(void)                                                 // ADCA #
 {
-       regs.cc &= ~FLAG_I;
+       uint16 m = READ_IMM;
+       OP_ADC_HANDLER(m, regs.a);
 }
 
-static void Op0F(void)                                                 // SEI
+static void Op99(void)                                                 // ADCA ZP
 {
-       regs.cc |= FLAG_I;
+       uint16 m = READ_ZP;
+       OP_ADC_HANDLER(m, regs.a);
 }
 
-static void Op10(void)                                                 // SBA
+static void OpA9(void)                                                 // ADCA ZP, X
 {
-       uint8 as = regs.a; 
-       regs.a -= regs.b;
-
-       regs.cc &= ~(FLAG_N | FLAG_Z | FLAG_V | FLAG_C);        // Clear NZVC
-
-       if (as < regs.b)
-               regs.cc |= FLAG_C;
-
-       if ((as ^ regs.b ^ regs.a ^ (regs.cc << 7)) & 0x80)
-               regs.cc |= FLAG_V;
-
-       if (regs.a == 0)
-               regs.cc |= FLAG_Z;
-
-       if (regs.a & 0x80)
-               regs.cc |= FLAG_N;
+       uint16 m = READ_ZP_X;
+       OP_ADC_HANDLER(m, regs.a);
 }
 
-static void Op11(void)                                                 // CBA (Compare B to A)
+static void OpB9(void)                                                 // ADCA ABS
 {
-       tmp = regs.a - regs.b;
-
-       regs.cc &= ~(FLAG_N | FLAG_Z | FLAG_V | FLAG_C);        // Clear NZVC
-
-       if (regs.a < regs.b)
-               regs.cc |= FLAG_C;
-
-       if ((tmp ^ regs.b ^ regs.a ^ (regs.cc << 7)) & 0x80)
-               regs.cc |= FLAG_V;
-
-       if (regs.a == 0)
-               regs.cc |= FLAG_Z;
-
-       if (regs.a & 0x80)
-               regs.cc |= FLAG_N;
+       uint16 m = READ_ABS;
+       OP_ADC_HANDLER(m, regs.a);
 }
 
-static void Op16(void)                                                 // TAB
+static void OpC9(void)                                                 // ADCB #
 {
-       regs.b = regs.a;
-
-       regs.cc &= ~(FLAG_N | FLAG_Z | FLAG_V);         // Clear NZV
+       uint16 m = READ_IMM;
+       OP_ADC_HANDLER(m, regs.b);
+}
 
-       if (regs.b == 0)
-               regs.cc |= FLAG_Z;
+static void OpD9(void)                                                 // ADCB ZP
+{
+       uint16 m = READ_ZP;
+       OP_ADC_HANDLER(m, regs.b);
+}
 
-       if (regs.b & 0x80)
-               regs.cc |= FLAG_N;
+static void OpE9(void)                                                 // ADCB ZP, X
+{
+       uint16 m = READ_ZP_X;
+       OP_ADC_HANDLER(m, regs.b);
 }
 
-static void Op17(void)                                                 // TBA
+static void OpF9(void)                                                 // ADCB ABS
 {
-       regs.a = regs.b;
+       uint16 m = READ_ABS;
+       OP_ADC_HANDLER(m, regs.b);
+}
 
-       regs.cc &= ~(FLAG_N | FLAG_Z | FLAG_V);         // Clear NZV
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+And                     |ANDA |84 2 2|94 3 2|A4 5 2|B4 4 3|      |A=A+M     |  TTR |
+                        |ANDB |C4 2 2|D4 3 2|E4 5 2|F4 4 3|      |B=B+M     |  TTR |
+*/
 
-       if (regs.a == 0)
-               regs.cc |= FLAG_Z;
+// AND opcodes
 
-       if (regs.a & 0x80)
-               regs.cc |= FLAG_N;
-}
+#define OP_AND_HANDLER(m, acc) \
+       acc &= m; \
+       SET_ZN(acc); \
+       CLR_V
 
-static void Op19(void)                                                 // DAA
+static void Op84(void)                                                 // ANDA #
 {
-  addr = regs.a;
-//  if (regs.cc&0x20)              addr += 6;    // H set? adjust
-  if ((addr&0x000F) > 9)     addr += 6;
-  if (regs.cc&0x01)              addr += 0x60; // C set? adjust
-  if ((addr&0x00F0) > 0x90)  addr += 0x60;
-  regs.cc &= 0xFD;                             // CLV
-  (addr > 0xFF ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-  regs.a = addr;
-  (regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);   // Adjust Zero flag 
-  (regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);   // Adjust Negative flag 
+       uint8 m = READ_IMM;
+       OP_AND_HANDLER(m, regs.a);
 }
 
-static void Op1B(void)                                                 // ABA
+static void Op94(void)                                                 // ANDA ZP
 {
-  addr = regs.a + regs.b;
-  regs.cc &= 0xF0;
-  if (addr > 0xFF)  regs.cc |= 0x01;    // Set Carry flag
-  if ((regs.a^regs.b^addr^(regs.cc<<7))&0x80)  regs.cc |= 0x02; // Set oVerflow 
-  regs.a = addr;                        // Set accumulator
-  if (regs.a == 0)      regs.cc |= 0x04;    // Set Zero flag
-  if (regs.a&0x80)      regs.cc |= 0x08;    // Set Negative flag
+       uint8 m = READ_ZP;
+       OP_AND_HANDLER(m, regs.a);
 }
 
-static void Op20(void)                                                 // BRA (BRanch Always)
+static void OpA4(void)                                                 // ANDA ZP, X
 {
-       regs.pc += (int16)(int8)regs.RdMem(regs.pc++);
+       uint16 m = READ_ZP_X;
+       OP_AND_HANDLER(m, regs.a);
 }
 
-static void Op22(void)                                                 // BHI
+static void OpB4(void)                                                 // ANDA ABS
 {
-       tmp = regs.RdMem(regs.pc++);
-
-       if (!(regs.cc & (FLAG_C | FLAG_Z)))
-               regs.pc += (signed short int)(signed char)tmp;
+       uint16 m = READ_ABS;
+       OP_AND_HANDLER(m, regs.a);
 }
 
-static void Op23(void)                                                 // BLS
+static void OpC4(void)                                                 // ANDB #
 {
-       tmp = regs.RdMem(regs.pc++);
-
-       if (regs.cc & (FLAG_C | FLAG_Z))
-               regs.pc += (signed short int)(signed char)tmp;
+       uint8 m = READ_IMM;
+       OP_AND_HANDLER(m, regs.b);
 }
 
-static void Op24(void)                                                 // BCC (BHS)
+static void OpD4(void)                                                 // ANDB ZP
 {
-  tmp = regs.RdMem(regs.pc++);
-  if (!(regs.cc&0x01))  regs.pc += (signed short int)(signed char)tmp;
+       uint8 m = READ_ZP;
+       OP_AND_HANDLER(m, regs.b);
 }
 
-static void Op25(void)                                                 // BCS (BLO)
+static void OpE4(void)                                                 // ANDB ZP, X
 {
-  tmp = regs.RdMem(regs.pc++);
-  if (regs.cc&0x01)  regs.pc += (signed short int)(signed char)tmp;
+       uint16 m = READ_ZP_X;
+       OP_AND_HANDLER(m, regs.b);
 }
 
-static void Op26(void)                                                 // BNE
+static void OpF4(void)                                                 // ANDB ABS
 {
-  tmp = regs.RdMem(regs.pc++);
-  if (!(regs.cc&0x04))  regs.pc += (signed short int)(signed char)tmp;
+       uint16 m = READ_ABS;
+       OP_AND_HANDLER(m, regs.b);
 }
 
-static void Op27(void)                                                 // BEQ
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Bit Test                |BITA |85 2 2|95 3 2|A5 5 2|B5 4 3|      |A+M       |  TTR |
+                        |BITB |C5 2 2|D5 3 2|E5 5 2|F5 4 3|      |B+M       |  TTR |
+*/
+
+// BIT opcodes
+
+#define OP_BIT_HANDLER(m, acc) \
+       int8 result = acc & (m); \
+       SET_ZN(result)
+
+static void Op85(void)                                                 // BITA #
 {
-  tmp = regs.RdMem(regs.pc++);
-  if (regs.cc&0x04)  regs.pc += (signed short int)(signed char)tmp;
+       uint8 m = READ_IMM;
+       OP_BIT_HANDLER(m, regs.a);
 }
 
-static void Op28(void)                                                 // BVC
+static void Op95(void)                                                 // BITA ZP
 {
-  tmp = regs.RdMem(regs.pc++);
-  if (!(regs.cc&0x02))  regs.pc += (signed short int)(signed char)tmp;
+       uint8 m = READ_ZP;
+       OP_BIT_HANDLER(m, regs.a);
 }
 
-static void Op29(void)                                                 // BVS
+static void OpA5(void)                                                 // BITA ZP, X
 {
-  tmp = regs.RdMem(regs.pc++);
-  if (regs.cc&0x02)  regs.pc += (signed short int)(signed char)tmp;
+       uint8 m = READ_ZP_X;
+       OP_BIT_HANDLER(m, regs.a);
 }
 
-static void Op2A(void)                                                 // BPL
+static void OpB5(void)                                                 // BITA ABS
 {
-  tmp = regs.RdMem(regs.pc++);
-  if (!(regs.cc&0x08))  regs.pc += (signed short int)(signed char)tmp;
+       uint8 m = READ_ABS;
+       OP_BIT_HANDLER(m, regs.a);
 }
 
-static void Op2B(void)                                                 // BMI
+static void OpC5(void)                                                 // BITB #
 {
-  tmp = regs.RdMem(regs.pc++);
-  if (regs.cc&0x08)  regs.pc += (signed short int)(signed char)tmp;
+       uint8 m = READ_IMM;
+       OP_BIT_HANDLER(m, regs.b);
 }
 
-static void Op2C(void)                                                 // BGE
+static void OpD5(void)                                                 // BITB ZP
 {
-  tmp = regs.RdMem(regs.pc++);
-  if (!(((regs.cc&0x08) >> 2) ^ (regs.cc&0x02)))  regs.pc += (signed short int)(signed char)tmp;
+       uint8 m = READ_ZP;
+       OP_BIT_HANDLER(m, regs.b);
 }
 
-static void Op2D(void)                                                 // BLT
+static void OpE5(void)                                                 // BITB ZP, X
 {
-  tmp = regs.RdMem(regs.pc++);
-  if (((regs.cc&0x08) >> 2) ^ (regs.cc&0x02))  regs.pc += (signed short int)(signed char)tmp;
+       uint8 m = READ_ZP_X;
+       OP_BIT_HANDLER(m, regs.b);
 }
 
-static void Op2E(void)                                                 // BGT
+static void OpF5(void)                                                 // BITB ABS
 {
-  tmp = regs.RdMem(regs.pc++);
-  if (!((regs.cc&0x04) | (((regs.cc&0x08) >> 2) ^ (regs.cc&0x02))))  regs.pc += (signed short int)(signed char)tmp;
+       uint8 m = READ_ABS;
+       OP_BIT_HANDLER(m, regs.b);
 }
 
-static void Op2F(void)                                                 // BLE
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Clear                   |CLR  |      |      |6F 7 2|7F 6 3|      |M=00      |  RSRR|
+                        |CLRA |      |      |      |      |4F 2 1|A=00      |  RSRR|
+                        |CLRB |      |      |      |      |5F 2 1|B=00      |  RSRR|
+*/
+
+// CLR opcodes
+
+static void Op6F(void)                                                 // CLR ZP, X
 {
-  tmp = regs.RdMem(regs.pc++);
-  if ((regs.cc&0x04) | (((regs.cc&0x08) >> 2) ^ (regs.cc&0x02)))  regs.pc += (signed short int)(signed char)tmp;
+       regs.WrMem(EA_ZP_X, 0);
+       CLR_NVC;
+       SET_Z(0);
 }
 
-static void Op30(void)                                                 // TSX
+static void Op7F(void)                                                 // CLR ABS
 {
-  regs.x = regs.s;
+       regs.WrMem(EA_ABS, 0);
+       regs.pc += 2;
+       CLR_NVC;
+       SET_Z(0);
 }
 
-static void Op31(void)                                                 // INS
+static void Op4F(void)                                                 // CLRA
 {
-  regs.s++;
+       regs.a = 0;
+       CLR_NVC;
+       SET_Z(0);
 }
 
-static void Op32(void)                                                 // PULA
+static void Op5F(void)                                                 // CLRB
 {
-  regs.a  = regs.RdMem(regs.s++);
+       regs.b = 0;
+       CLR_NVC;
+       SET_Z(0);
 }
 
-static void Op33(void)                                                 // PULB
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Compare                 |CMPA |81 2 2|91 3 2|A1 5 2|B1 4 3|      |A-M       |  TTTT|
+                        |CMPB |C1 2 2|D1 3 2|E1 5 2|F1 4 3|      |B-M       |  TTTT|
+Compare Accumulators    |CBA  |      |      |      |      |11 2 1|A-B       |  TTTT|
+*/
+
+// CMP opcodes
+
+/*
+Compare sets flags as if a subtraction had been carried out. If the value in the accumulator is equal or greater than the compared value, the Carry will be set. The equal (Z) and sign (S) flags will be set based on equality or lack thereof and the sign (i.e. A>=$80) of the accumulator.
+*/
+
+#define OP_CMP_HANDLER(m, acc) \
+       uint16 result = acc - (m); \
+       SET_ZNVC_CMP(m, acc, result)
+
+static void Op81(void)                                                 // CMPA #
 {
-  regs.b  = regs.RdMem(regs.s++);
+       uint8 m = READ_IMM;
+       OP_CMP_HANDLER(m, regs.a);
 }
 
-static void Op34(void)                                                 // DES
+static void Op91(void)                                                 // CMPA ZP
 {
-  regs.s--;
+       uint8 m = READ_ZP;
+       OP_CMP_HANDLER(m, regs.a);
 }
 
-static void Op35(void)                                                 // TXS
+static void OpA1(void)                                                 // CMPA ZP, X
 {
-  regs.s = regs.x;
+       uint8 m = READ_ZP_X;
+       OP_CMP_HANDLER(m, regs.a);
 }
 
-static void Op36(void)                                                 // PSHA
+static void OpB1(void)                                                 // CMPA ABS
 {
-       regs.WrMem(--regs.s, regs.a);
+       uint8 m = READ_ABS;
+       OP_CMP_HANDLER(m, regs.a);
 }
 
-static void Op37(void)                                                 // PSHB
+static void OpC1(void)                                                 // CMPB #
 {
-       regs.WrMem(--regs.s, regs.b);
+       uint8 m = READ_IMM;
+       OP_CMP_HANDLER(m, regs.b);
 }
 
-static void Op39(void)                                                 // RTS
+static void OpD1(void)                                                 // CMPB ZP
 {
-       regs.pc = (regs.RdMem(regs.s++) << 8) | regs.RdMem(regs.s++);
+       uint8 m = READ_ZP;
+       OP_CMP_HANDLER(m, regs.b);
 }
 
-static void Op3B(void)                                                 // RTI
+static void OpE1(void)                                                 // CMPB ZP, X
 {
-       regs.cc = regs.RdMem(regs.s++);
-       regs.a  = regs.RdMem(regs.s++);
-       regs.b  = regs.RdMem(regs.s++);
-       regs.x  = (regs.RdMem(regs.s++) << 8) | regs.RdMem(regs.s++);
-       regs.pc = (regs.RdMem(regs.s++) << 8) | regs.RdMem(regs.s++);
+       uint8 m = READ_ZP_X;
+       OP_CMP_HANDLER(m, regs.b);
 }
 
-static void Op3E(void)                                                 // WAI (wait for interrupt)
+static void OpF1(void)                                                 // CMPB ABS
 {
-       regs.cc &= regs.RdMem(regs.pc++);
-       regs.cc |= 0x80;//???Is this right???
+       uint8 m = READ_ABS;
+       OP_CMP_HANDLER(m, regs.b);
 }
 
-static void Op3F(void)                                                 // SWI (software interrupt)
+static void Op11(void)                                                 // CBA
 {
-//Does this respect the I flag???
-       regs.WrMem(--regs.s, regs.pc & 0xFF);           // Save all regs...
-       regs.WrMem(--regs.s, regs.pc >> 8);
-       regs.WrMem(--regs.s, regs.x & 0xFF);
-       regs.WrMem(--regs.s, regs.x >> 8);
-       regs.WrMem(--regs.s, regs.b);
-       regs.WrMem(--regs.s, regs.a);
-       regs.WrMem(--regs.s, regs.cc);
-       regs.pc = RdMemW(0xFFFA);                                       // And do it!
-
-       regs.cc |= FLAG_I;                                                      // Also, set IRQ inhibit
+       OP_CMP_HANDLER(regs.b, regs.a);
 }
 
-static void Op40(void)                                                 // NEGA
-{ 
-  regs.a = 256 - regs.a;  regs.cc &= 0xF0;
-  if (regs.a > 0x7F)   regs.cc |= 0x01;   // Set Carry
-  if (regs.a == 0x80)  regs.cc |= 0x02;   // Set oVerflow
-  if (regs.a == 0)     regs.cc |= 0x04;   // Set Zero flag
-  if (regs.a&0x80)     regs.cc |= 0x08;   // Set Negative flag
-}
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Complement 1's          |COM  |      |      |63 7 2|73 6 3|      |M=-M      |  TTRS|
+                        |COMA |      |      |      |      |43 2 1|A=-A      |  TTRS|
+                        |COMB |      |      |      |      |53 2 1|B=-B      |  TTRS|
+*/
 
-static void Op43(void)                                                 // COMA
+// COM opcodes
+
+//#define OP_COM_HANDLER(m) \
+       m = m ^ 0xFF; \
+       SET_ZN(m); \
+       CLR_V; \
+       regs.cc |= FLAG_C
+#define OP_COM_HANDLER(m) \
+       m = m ^ 0xFF; \
+       SET_ZN(m); \
+       CLR_V; \
+       flagC = 1
+
+static void Op63(void)                                                 // COM ZP, X
 {
-  regs.a ^= 0xFF;
-  regs.cc &= 0xF0;  regs.cc |= 0x01;                   // CLV, SEC
-  if (regs.a == 0)  regs.cc |= 0x04;                   // Set Zero flag
-  if (regs.a&0x80)  regs.cc |= 0x08;                   // Set Negative flag
+       uint8 m;
+       READ_ZP_X_WB(m);
+       OP_COM_HANDLER(m);
+       WRITE_BACK(m);
 }
 
-static void Op44(void)                                                 // LSRA
+static void Op73(void)                                                 // COM ABS
 {
-  (regs.a&0x01 ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Shift low bit into Carry
-  regs.a >>= 1;
-  (regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint8 m;
+       READ_ABS_WB(m);
+       OP_COM_HANDLER(m);
+       WRITE_BACK(m);
 }
 
-static void Op46(void)  // RORA
+static void Op43(void)                                                 // COMA
 {
-  tmp = regs.a;  regs.a = (tmp>>1) + (regs.cc&0x01)*128;
-  (tmp&0x01 ? regs.cc |= 0x01 : regs.cc &= 0xFE); // Shift bit into Carry
-  (regs.a == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB); // Adjust Zero flag
-  (regs.a&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7); // Adjust Negative flag
+       OP_COM_HANDLER(regs.a);
 }
 
-static void Op47(void)  // ASRA
+static void Op53(void)                                                 // COMB
 {
-  (regs.a&0x01 ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Shift bit into Carry
-  regs.a >>= 1;                               // Do the shift
-  if (regs.a&0x40)  regs.a |= 0x80;               // Set neg if it was set
-  (regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       OP_COM_HANDLER(regs.b);
 }
 
-static void Op48(void)  // LSLA (ASLA) [Keep checking from here...]
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Complement 2's          |NEG  |      |      |60 7 2|70 6 3|      |M=00-M    |  TT12|
+                        |NEGA |      |      |      |      |40 2 1|A=00-A    |  TT12|
+                        |NEGB |      |      |      |      |50 2 1|B=00-B    |  TT12|
+*/
+
+// NEG opcodes
+
+//#define OP_NEG_HANDLER(m) \
+       m = -m; \
+       SET_ZN(m); \
+       regs.cc = (m == 0x80 ? regs.cc | FLAG_V : regs.cc & ~FLAG_V); \
+       regs.cc = (m == 0x00 ? regs.cc | FLAG_C : regs.cc & ~FLAG_C)
+#define OP_NEG_HANDLER(m) \
+       m = -m; \
+       SET_ZN(m); \
+       flagV = (m == 0x80 ? 1 : 0); \
+       flagC = (m == 0x00 ? 1 : 0)
+
+static void Op60(void)                                                 // NEG ZP, X
 {
-  (regs.a&0x80 ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Shift hi bit into Carry
-  regs.a <<= 1;
-  (regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint8 m;
+       READ_ZP_X_WB(m);
+       OP_NEG_HANDLER(m);
+       WRITE_BACK(m);
 }
 
-static void Op49(void)  // ROLA  
+static void Op70(void)                                                 // NEG ABS
 {
-  tmp = regs.a;  regs.a = (tmp<<1) + (regs.cc&0x01);
-  (tmp&0x80 ? regs.cc |= 0x01 : regs.cc &= 0xFE); // Shift hi bit into Carry
-  (regs.a == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB); // Adjust Zero flag
-  (regs.a&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7); // Adjust Negative flag
+       uint8 m;
+       READ_ABS_WB(m);
+       OP_NEG_HANDLER(m);
+       WRITE_BACK(m);
 }
 
-static void Op4A(void)  // DECA
+static void Op40(void)                                                 // NEGA
 {
-  regs.a--;
-  (regs.a == 0x7F ? regs.cc |= 0x02 : regs.cc &= 0xFD); // Adjust oVerflow flag
-  (regs.a == 0    ? regs.cc |= 0x04 : regs.cc &= 0xFB); // Adjust Zero flag
-  (regs.a&0x80    ? regs.cc |= 0x08 : regs.cc &= 0xF7); // Adjust Negative flag
+       OP_NEG_HANDLER(regs.a);
 }
 
-static void Op4C(void)  // INCA
+static void Op50(void)                                                 // NEGB
 {
-regs.a++;
-(regs.a == 0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // Adjust oVerflow flag
-(regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);    // Adjust Zero flag
-(regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);    // Adjust Negative flag
+       OP_NEG_HANDLER(regs.b);
 }
 
-static void Op4D(void)  // TSTA
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Decimal Adjust          |DAA  |      |      |      |      |19 2 1|*         |  TTT3|
+*/
+
+static void Op19(void)                                                 // DAA
 {
-regs.cc &= 0xFD;                            // Clear oVerflow flag
-(regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+#if 0 // Just because we can optimize a little here, we will... ;-)
+       uint16 adjust = 0;
+
+       if ((regs.a & 0x0F) > 0x09 || (regs.cc & FLAG_H))
+               adjust |= 0x06;
+
+       if ((regs.a & 0xF0) > 0x90 || (regs.cc & FLAG_C) || ((regs.a & 0xF0) > 0x80 && (regs.a & 0x0F) > 0x09))
+               adjust |= 0x60;
+
+       uint16 result = regs.a + adjust;
+       regs.a = (uint8)result;
+       SET_ZN(result);
+       CLR_V;                                                                          // Not sure this is correct...
+       regs.cc |= (result & 0x100) >> 8;                       // Overwrite carry if it was 0, otherwise, ignore
+#else
+       uint16 result = (uint16)regs.a;
+
+//     if ((regs.a & 0x0F) > 0x09 || (regs.cc & FLAG_H))
+       if ((regs.a & 0x0F) > 0x09 || flagH)
+               result += 0x06;
+
+//     if ((regs.a & 0xF0) > 0x90 || (regs.cc & FLAG_C) || ((regs.a & 0xF0) > 0x80 && (regs.a & 0x0F) > 0x09))
+       if ((regs.a & 0xF0) > 0x90 || flagC || ((regs.a & 0xF0) > 0x80 && (regs.a & 0x0F) > 0x09))
+               result += 0x60;
+
+       regs.a = (uint8)result;
+       SET_ZN(result);
+       CLR_V;                                                                          // Not sure this is correct...
+//     regs.cc |= (result & 0x100) >> 8;                       // Overwrite carry if it was 0, otherwise, ignore
+       flagC |= (result & 0x100) >> 8;                         // Overwrite carry if it was 0, otherwise, ignore
+#endif
 }
 
-static void Op4F(void)  // CLRA
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Decrement               |DEC  |      |      |6A 7 2|7A 6 3|      |M=M-1     |  TT4 |
+                        |DECA |      |      |      |      |4A 2 1|A=A-1     |  TT4 |
+                        |DECB |      |      |      |      |5A 2 1|B=B-1     |  TT4 |
+*/
+
+// DEC opcodes
+
+//#define OP_DEC_HANDLER(m) \
+       m--; \
+       SET_ZN(m); \
+       regs.cc = (m == 0x7F ? regs.cc | FLAG_V : regs.cc & ~FLAG_V)
+#define OP_DEC_HANDLER(m) \
+       m--; \
+       SET_ZN(m); \
+       flagV = (m == 0x7F ? 1 : 0)
+
+static void Op6A(void)                                                 // DEC ZP, X
 {
-  regs.a = 0;
-  regs.cc &= 0xF0;  regs.cc |= 0x04;                // Set NZVC
+       uint8 m;
+       READ_ZP_X_WB(m);
+       OP_DEC_HANDLER(m);
+       WRITE_BACK(m);
 }
 
-static void Op50(void)  // NEGB
-{ 
-regs.b = 256 - regs.b;
-//        ((regs.b^tmp)&0x10 ? regs.cc |= 0x20 : regs.cc &= 0xDF); // Adjust H Carry
-(regs.b == 0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);   // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);   // Adjust Negative flag
-(regs.b > 0x7F ? regs.cc |= 0x01 : regs.cc &= 0xFE); // Adjust Carry
+static void Op7A(void)                                                 // DEC ABS
+{
+       uint8 m;
+       READ_ABS_WB(m);
+       OP_DEC_HANDLER(m);
+       WRITE_BACK(m);
 }
 
-static void Op53(void)  // COMB
+static void Op4A(void)                                                 // DECA
 {
-regs.b ^= 0xFF;
-regs.cc &= 0xFD;  regs.cc |= 0x01;              // CLV, SEC
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       OP_DEC_HANDLER(regs.a);
 }
 
-static void Op54(void)  // LSRB
+static void Op5A(void)                                                 // DECB
 {
-(regs.b&0x01 ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Shift low bit into Carry
-regs.b >>= 1;
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       OP_DEC_HANDLER(regs.b);
 }
 
-static void Op56(void)  // RORB
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Exclusive OR            |EORA |88 2 2|98 3 2|A8 5 2|B8 4 3|      |A=A(+)M   |  TTR |
+                        |EORB |C8 2 2|D8 3 2|E8 5 2|F8 4 3|      |B=B(+)M   |  TTR |
+*/
+
+// EOR opcodes
+
+#define OP_EOR_HANDLER(m, acc) \
+       acc ^= m; \
+       SET_ZN(acc); \
+       CLR_V
+
+static void Op88(void)                                                 // EORA #
 {
-tmp = regs.b;  regs.b = (regs.b >> 1) + (regs.cc&0x01)*128;
-(tmp&0x01 ? regs.cc |=0x01 : regs.cc &= 0xFE);  // Shift bit into Carry
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint8 m = READ_IMM;
+       OP_EOR_HANDLER(m, regs.a);
 }
 
-static void Op57(void)  // ASRB
+static void Op98(void)                                                 // EORA ZP
 {
-(regs.b&0x01 ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Shift bit into Carry
-regs.b >>= 1;                               // Do the shift
-if (regs.b&0x40)  regs.b |= 0x80;               // Set neg if it was set
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint8 m = READ_ZP;
+       OP_EOR_HANDLER(m, regs.a);
 }
 
-static void Op58(void)  // LSLB
+static void OpA8(void)                                                 // EORA ZP, X
 {
-(regs.b&0x80 ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Shift hi bit into Carry
-regs.b <<= 1;
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint8 m = READ_ZP_X;
+       OP_EOR_HANDLER(m, regs.a);
 }
 
-static void Op59(void)  // ROLB
+static void OpB8(void)                                                 // EORA ABS
 {
-  tmp = regs.b;
-  regs.b = (tmp<<1) + (regs.cc&0x01);
-  (tmp&0x80 ? regs.cc |= 0x01 : regs.cc &= 0xFE); // Shift hi bit into Carry
-  (regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint8 m = READ_ABS;
+       OP_EOR_HANDLER(m, regs.a);
 }
 
-static void Op5A(void)  // DECB
+static void OpC8(void)                                                 // EORB #
 {
-regs.b--;
-(regs.b == 0x7F ? regs.cc |= 0x02 : regs.cc &= 0xFD); // Adjust oVerflow flag
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);    // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);    // Adjust Negative flag
+       uint8 m = READ_IMM;
+       OP_EOR_HANDLER(m, regs.b);
 }
 
-static void Op5C(void)  // INCB
+static void OpD8(void)                                                 // EORB ZP
 {
-regs.b++;
-(regs.b == 0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // Adjust oVerflow flag 
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);    // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);    // Adjust Negative flag
+       uint8 m = READ_ZP;
+       OP_EOR_HANDLER(m, regs.b);
 }
 
-static void Op5D(void)  // TSTB
+static void OpE8(void)                                                 // EORB ZP, X
 {
-regs.cc &= 0xFD;                            // Cleregs.a oVerflow flag
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint8 m = READ_ZP_X;
+       OP_EOR_HANDLER(m, regs.b);
 }
 
-static void Op5F(void)  // CLRB
+static void OpF8(void)                                                 // EORB ABS
 {
-regs.b = 0;
-regs.cc &= 0xF0;  regs.cc |= 0x04;                // Set NZVC
+       uint8 m = READ_ABS;
+       OP_EOR_HANDLER(m, regs.b);
 }
 
-static void Op60(void)  // NEG IDX
-{ 
-addr = DecodeIDX(regs.RdMem(regs.pc++));
-tmp = regs.RdMem(addr);  uint8 res = 256 - tmp;
-regs.WrMem(addr, res);
-//        ((res^tmp)&0x10 ? regs.cc |= 0x20 : regs.cc &= 0xDF); // Adjust H Carry
-(res == 0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
-(res == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);   // Adjust Zero flag
-(res&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);   // Adjust Negative flag
-(res > 0x7F ? regs.cc |= 0x01 : regs.cc &= 0xFE); // Adjust Carry
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Increment               |INC  |      |      |6C 7 2|7C 6 3|      |M=M+1     |  TT5 |
+                        |INCA |      |      |      |      |4C 2 1|A=A+1     |  TT5 |
+                        |INCB |      |      |      |      |5C 2 1|B=B+1     |  TT5 |
+*/
+
+// INC opcodes
+
+//#define OP_INC_HANDLER(m) \
+       m++; \
+       SET_ZN(m); \
+       regs.cc = (m == 0x80 ? regs.cc | FLAG_V : regs.cc & ~FLAG_V)
+#define OP_INC_HANDLER(m) \
+       m++; \
+       SET_ZN(m); \
+       flagV = (m == 0x80 ? 1 : 0)
+
+static void Op6C(void)                                                 // INC ZP, X
+{
+       uint8 m;
+       READ_ZP_X_WB(m);
+       OP_INC_HANDLER(m);
+       WRITE_BACK(m);
 }
 
-static void Op63(void)  // COM IDX
+static void Op7C(void)                                                 // INC ABS
 {
-addr = DecodeIDX(regs.RdMem(regs.pc++));
-tmp = regs.RdMem(addr) ^ 0xFF;
-regs.WrMem(addr, tmp);
-regs.cc &= 0xFD;  regs.cc |= 0x01;               // CLV, SEC
-(tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(tmp&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint8 m;
+       READ_ABS_WB(m);
+       OP_INC_HANDLER(m);
+       WRITE_BACK(m);
 }
 
-static void Op64(void)  // LSR IDX
+static void Op4C(void)                                                 // INCA
 {
-addr = DecodeIDX(regs.RdMem(regs.pc++));
-tmp = regs.RdMem(addr);
-(tmp&0x01 ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Shift low bit into Carry
-tmp >>= 1;  regs.WrMem(addr, tmp);
-regs.cc &= 0xF7;                             // CLN
-(tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
+       OP_INC_HANDLER(regs.a);
 }
 
-static void Op66(void)  // ROR IDX
+static void Op5C(void)                                                 // INCB
 {
-addr = DecodeIDX(regs.RdMem(regs.pc++));
-tmp = regs.RdMem(addr);  uint8 tmp2 = tmp;
-tmp = (tmp >> 1) + (regs.cc&0x01)*128;
-regs.WrMem(addr, tmp);
-(tmp2&0x01 ? regs.cc |= 0x01 : regs.cc &= 0xFE); // Shift bit into Carry
-(tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(tmp&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       OP_INC_HANDLER(regs.b);
 }
 
-static void Op67(void)  // ASR IDX
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Load Accumulator        |LDAA |86 2 2|96 3 2|A6 5 2|B6 4 3|      |A=M       |  TTR |
+                        |LDAB |C6 2 2|D6 3 2|E6 5 2|F6 4 3|      |B=M       |  TTR |
+*/
+
+// LDA opcodes
+
+#define OP_LDA_HANDLER(m, acc) \
+       acc = m; \
+       SET_ZN(acc); \
+       CLR_V
+
+static void Op86(void)                                                 // LDAA #
 {
-addr = DecodeIDX(regs.RdMem(regs.pc++));
-tmp = regs.RdMem(addr);
-(tmp&0x01 ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Shift bit into Carry
-tmp >>= 1;
-if (tmp&0x40)  tmp |= 0x80;              // Set Neg if it was set
-regs.WrMem(addr, tmp);
-(tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(tmp&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint8 m = READ_IMM;
+       OP_LDA_HANDLER(m, regs.a);
 }
 
-static void Op68(void)  // LSL IDX
+static void Op96(void)                                                 // LDAA ZP
 {
-addr = DecodeIDX(regs.RdMem(regs.pc++));
-tmp = regs.RdMem(addr);
-(tmp&0x80 ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Shift hi bit into Carry
-tmp <<= 1;
-regs.WrMem(addr, tmp);
-(tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(tmp&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint8 m = READ_ZP;
+       OP_LDA_HANDLER(m, regs.a);
 }
 
-static void Op69(void)  // ROL IDX
+static void OpA6(void)                                                 // LDAA ZP, X
 {
-  uint8 tmp2 = regs.RdMem(DecodeIDX(regs.RdMem(regs.pc++)));
-  tmp = (tmp2<<1) + (regs.cc&0x01);
-  regs.WrMem(addr, tmp);
-  (tmp2&0x80 ? regs.cc |= 0x01 : regs.cc &= 0xFE); // Shift hi bit into Carry
-  (tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (tmp&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint8 m = READ_ZP_X;
+       OP_LDA_HANDLER(m, regs.a);
 }
 
-static void Op6A(void)  // DEC IDX
+static void OpB6(void)                                                 // LDAA ABS
 {
-uint8 tmp;  uint16 addr;
-addr = DecodeIDX(regs.RdMem(regs.pc++));
-tmp = regs.RdMem(addr) - 1;
-regs.WrMem(addr, tmp);
-(tmp == 0x7F ? regs.cc |= 0x02 : regs.cc &= 0xFD); // Adjust oVerflow flag
-(tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);    // Adjust Zero flag
-(tmp&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);    // Adjust Negative flag
+       uint8 m = READ_ABS;
+       OP_LDA_HANDLER(m, regs.a);
 }
 
-static void Op6C(void)  // INC IDX
-{       
-addr = DecodeIDX(regs.RdMem(regs.pc++));
-tmp = regs.RdMem(addr) + 1;
-regs.WrMem(addr, tmp);
-(tmp == 0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // Adjust oVerflow flag
-(tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);    // Adjust Zero flag
-(tmp&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);    // Adjust Negative flag
+static void OpC6(void)                                                 // LDAB #
+{
+       uint8 m = READ_IMM;
+       OP_LDA_HANDLER(m, regs.b);
 }
 
-static void Op6D(void)  // TST IDX
+static void OpD6(void)                                                 // LDAB ZP
 {
-tmp = regs.RdMem(DecodeIDX(regs.RdMem(regs.pc++)));
-(tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);   // Adjust Zero flag 
-(tmp&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);   // Adjust Negative flag 
+       uint8 m = READ_ZP;
+       OP_LDA_HANDLER(m, regs.b);
 }
 
-static void Op6E(void)  // JMP IDX
+static void OpE6(void)                                                 // LDAB ZP, X
 {
-  regs.pc = DecodeIDX(regs.RdMem(regs.pc++));
+       uint8 m = READ_ZP_X;
+       OP_LDA_HANDLER(m, regs.b);
 }
 
-static void Op6F(void)  // CLR IDX
+static void OpF6(void)                                                 // LDAB ABS
 {
-  addr = DecodeIDX(regs.RdMem(regs.pc++));
-  regs.WrMem(addr, 0);
-  regs.cc &= 0xF0;  regs.cc |= 0x04;                // Set NZVC
+       uint8 m = READ_ABS;
+       OP_LDA_HANDLER(m, regs.b);
 }
 
-static void Op70(void)  // NEG ABS
-{ 
-addr = FetchW();
-tmp = regs.RdMem(addr);  uint8 res = 256 - tmp;
-regs.WrMem(addr, res);
-(res == 0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
-(res == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);   // Adjust Zero flag
-(res&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);   // Adjust Negative flag
-(res > 0x7F ? regs.cc |= 0x01 : regs.cc &= 0xFE); // Adjust Carry
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+OR, Inclusive           |ORAA |8A 2 2|9A 3 2|AA 5 2|BA 4 3|      |A=A+M     |  TTR |
+                        |ORAB |CA 2 2|DA 3 2|EA 5 2|FA 4 3|      |B=B+M     |  TTR |
+*/
+
+// ORA opcodes
+
+#define OP_ORA_HANDLER(m, acc) \
+       acc |= m; \
+       SET_ZN(acc); \
+       CLR_V
+
+static void Op8A(void)                                                 // ORAA #
+{
+       uint8 m = READ_IMM;
+       OP_ORA_HANDLER(m, regs.a);
 }
 
-static void Op73(void)  // COM ABS
+static void Op9A(void)                                                 // ORAA ZP
 {
-addr = FetchW();
-tmp = regs.RdMem(addr) ^ 0xFF;
-regs.WrMem(addr, tmp);
-regs.cc &= 0xFD;  regs.cc |= 0x01;               // CLV, SEC
-(tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(tmp&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint8 m = READ_ZP;
+       OP_ORA_HANDLER(m, regs.a);
 }
 
-static void Op74(void)  // LSR ABS
+static void OpAA(void)                                                 // ORAA ZP, X
 {
-addr = FetchW();
-tmp = regs.RdMem(addr);
-(tmp&0x01 ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Shift low bit into Carry
-tmp >>= 1;  regs.WrMem(addr, tmp);
-regs.cc &= 0xF7;                             // CLN
-(tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
+       uint8 m = READ_ZP_X;
+       OP_ORA_HANDLER(m, regs.a);
 }
 
-static void Op76(void)  // ROR ABS
+static void OpBA(void)                                                 // ORAA ABS
 {
-uint8 tmp;  uint16 addr;
-addr = FetchW();
-tmp = regs.RdMem(addr);  uint8 tmp2 = tmp;
-tmp = (tmp >> 1) + (regs.cc&0x01)*128;
-regs.WrMem(addr, tmp);
-(tmp2&0x01 ? regs.cc |= 0x01 : regs.cc &= 0xFE); // Shift bit into Carry
-(tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(tmp&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint8 m = READ_ABS;
+       OP_ORA_HANDLER(m, regs.a);
 }
 
-static void Op77(void)  // ASR ABS
+static void OpCA(void)                                                 // ORAB #
 {
-uint8 tmp;  uint16 addr;
-addr = FetchW();
-tmp = regs.RdMem(addr);
-(tmp&0x01 ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Shift bit into Carry
-tmp >>= 1;
-if (tmp&0x40)  tmp |= 0x80;              // Set Neg if it was set
-regs.WrMem(addr, tmp);
-(tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(tmp&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint8 m = READ_IMM;
+       OP_ORA_HANDLER(m, regs.b);
 }
 
-static void Op78(void)  // LSL ABS
+static void OpDA(void)                                                 // ORAB ZP
 {
-uint8 tmp;  uint16 addr;
-addr = FetchW();
-tmp = regs.RdMem(addr);
-(tmp&0x80 ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Shift hi bit into Carry
-tmp <<= 1;
-regs.WrMem(addr, tmp);
-(tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(tmp&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint8 m = READ_ZP;
+       OP_ORA_HANDLER(m, regs.b);
 }
 
-static void Op79(void)  // ROL ABS
+static void OpEA(void)                                                 // ORAB ZP, X
 {
-  uint8 tmp2 = regs.RdMem(FetchW());
-  tmp = (tmp2<<1) + (regs.cc&0x01);
-  regs.WrMem(addr, tmp);
-  (tmp2&0x80 ? regs.cc |= 0x01 : regs.cc &= 0xFE); // Shift hi bit into Carry
-  (tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (tmp&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint8 m = READ_ZP_X;
+       OP_ORA_HANDLER(m, regs.b);
 }
 
-static void Op7A(void)  // DEC ABS
+static void OpFA(void)                                                 // ORAB ABS
 {
-uint8 tmp;  uint16 addr;
-addr = FetchW();
-tmp = regs.RdMem(addr) - 1;
-regs.WrMem(addr, tmp);
-(tmp == 0x7F ? regs.cc |= 0x02 : regs.cc &= 0xFD); // Adjust oVerflow flag
-(tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);    // Adjust Zero flag
-(tmp&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);    // Adjust Negative flag
+       uint8 m = READ_ABS;
+       OP_ORA_HANDLER(m, regs.b);
 }
 
-static void Op7C(void)                                                                 // INC ABS
-{       
-       addr = FetchW();
-       tmp = regs.RdMem(addr) + 1;
-       regs.WrMem(addr, tmp);
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Push Data               |PSHA |      |      |      |      |36 4 1|Msp=A, *- |      |
+                        |PSHB |      |      |      |      |37 4 1|Msp=B, *- |      |
+Pull Data               |PULA |      |      |      |      |32 4 1|A=Msp, *+ |      |
+                        |PULB |      |      |      |      |33 4 1|B=Msp, *+ |      |
+*/
 
-       (tmp == 0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // Adjust oVerflow flag
-       (tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);    // Adjust Zero flag
-       (tmp&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);    // Adjust Negative flag
+static void Op36(void)                                                 // PSHA
+{
+//     regs.WrMem(--regs.s, regs.a);
+       PUSH(regs.a);
 }
 
-static void Op7D(void)                                                                 // TST ABS
+static void Op37(void)                                                 // PSHB
 {
-       uint8 tmp = regs.RdMem(FetchW());
-
-       (tmp == 0   ? regs.cc |= 0x04 : regs.cc &= 0xFB);               // Adjust Zero flag 
-       (tmp & 0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);               // Adjust Negative flag 
+//     regs.WrMem(--regs.s, regs.b);
+       PUSH(regs.b);
 }
 
-static void Op7E(void)                                                                 // JMP ABS
+static void Op32(void)                                                 // PULA
 {
-       regs.pc = FetchW();
+//     regs.a = regs.RdMem(regs.s++);
+       regs.a = PULL;
 }
 
-static void Op7F(void)  // CLR ABS
+static void Op33(void)                                                 // PULB
 {
-regs.WrMem(FetchW(), 0);
-regs.cc &= 0xF0;  regs.cc |= 0x04;                // Set NZVC
+//     regs.b = regs.RdMem(regs.s++);
+       regs.b = PULL;
 }
 
-static void Op80(void)  // SUBA #
-{ 
-  uint8 tmp = regs.RdMem(regs.pc++);  uint8 as = regs.a; 
-  regs.a -= tmp;
-  (as < tmp ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-  ((as^tmp^regs.a^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
-  (regs.a == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.a&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Rotate Left             |ROL  |      |      |69 7 2|79 6 3|      |Memory  *1|  TT6T|
+                        |ROLA |      |      |      |      |49 2 1|Accum A *1|  TT6T|
+                        |ROLB |      |      |      |      |59 2 1|Accum B *1|  TT6T|
+*/
+
+// ROL opcodes
+
+//#define OP_ROL_HANDLER(m) \
+       uint8 newCarry = (m & 0x80) >> 7; \
+       m = (m << 1) | (regs.cc & FLAG_C); \
+       SET_ZN(m); \
+       regs.cc = (regs.cc & ~FLAG_C) | newCarry; \
+       regs.cc = (regs.cc & ~FLAG_V) | ((regs.cc & FLAG_N) >> 2) ^ ((regs.cc & FLAG_C) << 1)
+#define OP_ROL_HANDLER(m) \
+       uint8 newCarry = (m & 0x80) >> 7; \
+       m = (m << 1) | flagC; \
+       SET_ZN(m); \
+       flagC = newCarry; \
+       flagV = flagN ^ flagC
+
+static void Op69(void)                                                 // ROL ZP, X
+{
+       uint8 m;
+       READ_ZP_X_WB(m);
+       OP_ROL_HANDLER(m);
+       WRITE_BACK(m);
 }
 
-static void Op81(void)  // CMPA #
+static void Op79(void)                                                 // ROL ABS
 {
-  tmp = regs.RdMem(regs.pc++);
-  uint8 db = regs.a - tmp;
-  (regs.a < tmp ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-  ((regs.a^tmp^db^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
-  (db == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (db&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint8 m;
+       READ_ABS_WB(m);
+       OP_ROL_HANDLER(m);
+       WRITE_BACK(m);
 }
 
-static void Op82(void)  // SBCA #
+static void Op49(void)                                                 // ROLA
 {
-  tmp = regs.RdMem(regs.pc++);  uint8 as = regs.a; 
-  regs.a = regs.a - tmp - (regs.cc&0x01);
-  (as < (tmp+(regs.cc&0x01)) ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-  ((as^tmp^regs.a^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
-  (regs.a == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.a&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       OP_ROL_HANDLER(regs.a);
 }
 
-static void Op84(void)  // ANDA #
+static void Op59(void)                                                 // ROLB
 {
-regs.a &= regs.RdMem(regs.pc++);
-regs.cc &= 0xFD;                            // Cleregs.a oVerflow flag
-(regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       OP_ROL_HANDLER(regs.b);
 }
 
-static void Op85(void)  // BITA #
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Rotate Right            |ROR  |      |      |66 7 2|76 6 3|      |Memory  *2|  TT6T|
+                        |RORA |      |      |      |      |46 2 1|Accum A *2|  TT6T|
+                        |RORB |      |      |      |      |56 2 1|Accum B *2|  TT6T|
+*/
+
+// ROR opcodes
+
+//#define OP_ROR_HANDLER(m) \
+       uint8 newCarry = m & 0x01; \
+       m = (m >> 1) | ((regs.cc & FLAG_C) << 7); \
+       SET_ZN(m); \
+       regs.cc = (regs.cc & ~FLAG_C) | newCarry; \
+       regs.cc = (regs.cc & ~FLAG_V) | ((regs.cc & FLAG_N) >> 2) ^ ((regs.cc & FLAG_C) << 1)
+#define OP_ROR_HANDLER(m) \
+       uint8 newCarry = m & 0x01; \
+       m = (m >> 1) | (flagC << 7); \
+       SET_ZN(m); \
+       flagC = newCarry; \
+       flagV = flagN ^ flagC
+
+static void Op66(void)                                                 // ROR ZP, X
 {
-tmp = regs.a & regs.RdMem(regs.pc++);
-regs.cc &= 0xFD;                             // Cleregs.a oVerflow flag
-(tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(tmp&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint8 m;
+       READ_ZP_X_WB(m);
+       OP_ROR_HANDLER(m);
+       WRITE_BACK(m);
 }
 
-static void Op86(void)  // LDAA #
+static void Op76(void)                                                 // ROR ABS
 {
-regs.a = regs.RdMem(regs.pc++);
-regs.cc &= 0xFD;                            // CLV
-(regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint8 m;
+       READ_ABS_WB(m);
+       OP_ROR_HANDLER(m);
+       WRITE_BACK(m);
 }
 
-static void Op88(void)  // EORA #
+static void Op46(void)                                                 // RORA
 {
-regs.a ^= regs.RdMem(regs.pc++);
-regs.cc &= 0xFD;                            // CLV
-(regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       OP_ROR_HANDLER(regs.a);
 }
 
-static void Op89(void)  // ADCA #
+static void Op56(void)                                                 // RORB
 {
-  tmp = regs.RdMem(regs.pc++);
-  addr = (uint16)regs.a + (uint16)tmp + (uint16)(regs.cc&0x01);
-  (addr > 0x00FF ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry
-//    ((regs.a^tmp^addr)&0x10 ? regs.cc |= 0x20 : regs.cc &= 0xDF);  // Set Half Carry
-  ((regs.a^tmp^addr^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow 
-  regs.a = addr & 0xFF;                       // Set accumulator
-  (regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero
-  (regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative
+       OP_ROR_HANDLER(regs.b);
 }
 
-static void Op8A(void)  // ORAA #
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Arithmetic Shift Left   |ASL  |      |      |68 7 2|78 6 3|      |Memory  *3|  TT6T|
+                        |ASLA |      |      |      |      |48 2 1|Accum A *3|  TT6T|
+                        |ASLB |      |      |      |      |58 2 1|Accum B *3|  TT6T|
+*/
+
+// ASL opcodes
+
+//#define OP_ASL_HANDLER(m) \
+       uint8 newCarry = (m & 0x80) >> 7; \
+       m <<= 1; \
+       SET_ZN(m); \
+       regs.cc = (regs.cc & ~FLAG_C) | newCarry; \
+       regs.cc = (regs.cc & ~FLAG_V) | ((regs.cc & FLAG_N) >> 2) ^ ((regs.cc & FLAG_C) << 1)
+#define OP_ASL_HANDLER(m) \
+       uint8 newCarry = (m & 0x80) >> 7; \
+       m <<= 1; \
+       SET_ZN(m); \
+       flagC = newCarry; \
+       flagV = flagN ^ flagC
+
+static void Op68(void)                                                 // ASL ZP, X
 {
-regs.a |= regs.RdMem(regs.pc++);
-regs.cc &= 0xFD;                            // CLV
-(regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint8 m;
+       READ_ZP_X_WB(m);
+       OP_ASL_HANDLER(m);
+       WRITE_BACK(m);
 }
 
-static void Op8B(void)  // ADDA #
-{       
-  tmp = regs.RdMem(regs.pc++);  addr = regs.a + tmp;
-  (addr > 0xFF ? regs.cc |= 0x01 : regs.cc &= 0xFE); // Set Carry flag
-  ((regs.a^tmp^addr^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow 
-  regs.a = addr & 0xFF;                       // Set accumulator
-  (regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Set Zero flag
-  (regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Set Negative flag
+static void Op78(void)                                                 // ASL ABS
+{
+       uint8 m;
+       READ_ABS_WB(m);
+       OP_ASL_HANDLER(m);
+       WRITE_BACK(m);
 }
 
-static void Op8C(void)  // CPX #
+static void Op48(void)                                                 // ASLA
 {
-       addr = FetchW();
-       uint16 dw = regs.x - addr;
-       (regs.x < addr ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-       ((regs.x^addr^dw^(regs.cc<<15))&0x8000 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerfl
-       (dw == 0   ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-       (dw&0x8000 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       OP_ASL_HANDLER(regs.a);
 }
 
-static void Op8D(void)                                                                 // BSR
+static void Op58(void)                                                 // ASLB
 {
-       tmp = regs.RdMem(regs.pc++);
+       OP_ASL_HANDLER(regs.b);
+}
+
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Arithmetic Shift Right  |ASR  |      |      |67 7 2|77 6 3|      |Memory  *4|  TT6T|
+                        |ASRA |      |      |      |      |47 2 1|Accum A *4|  TT6T|
+                        |ASRB |      |      |      |      |57 2 1|Accum B *4|  TT6T|
+*/
+
+// ASR opcodes
 
-       regs.s -= 2;
-       WrMemW(regs.s, regs.pc);
+//#define OP_ASR_HANDLER(m) \
+       uint8 newCarry = m & 0x01; \
+       m = (m >> 1) | (m & 0x80); \
+       SET_ZN(m); \
+       regs.cc = (regs.cc & ~FLAG_C) | newCarry; \
+       regs.cc = (regs.cc & ~FLAG_V) | ((regs.cc & FLAG_N) >> 2) ^ ((regs.cc & FLAG_C) << 1)
+#define OP_ASR_HANDLER(m) \
+       uint8 newCarry = m & 0x01; \
+       m = (m >> 1) | (m & 0x80); \
+       SET_ZN(m); \
+       flagC = newCarry; \
+       flagV = flagN ^ flagC
 
-       regs.pc += (signed short int)(signed char)tmp;
+static void Op67(void)                                                 // ASR ZP, X
+{
+       uint8 m;
+       READ_ZP_X_WB(m);
+       OP_ASR_HANDLER(m);
+       WRITE_BACK(m);
 }
 
-static void Op8E(void)  // LDS #
+static void Op77(void)                                                 // ASR ABS
 {
-regs.s = FetchW();
-regs.cc &= 0xFD;                              // CLV
-(regs.s == 0   ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.s&0x8000 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint8 m;
+       READ_ABS_WB(m);
+       OP_ASR_HANDLER(m);
+       WRITE_BACK(m);
 }
 
-static void Op90(void)  // SUBA ZP
-{ 
-  tmp = regs.RdMem(regs.RdMem(regs.pc++));  uint8 as = regs.a; 
-  regs.a -= tmp;
-  (regs.a == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.a&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
-  (as < tmp ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-  ((as^tmp^regs.a^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
+static void Op47(void)                                                 // ASRA
+{
+       OP_ASR_HANDLER(regs.a);
 }
 
-static void Op91(void)  // CMPA ZP
+static void Op57(void)                                                 // ASRB
 {
-tmp = regs.RdMem(regs.RdMem(regs.pc++));
-uint8 db = regs.a - tmp;
-(db == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(db&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
-(regs.a < tmp ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-((regs.a^tmp^db^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
+       OP_ASR_HANDLER(regs.b);
 }
 
-static void Op92(void)  // SBCA ZP
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Logic Shift Right       |LSR  |      |      |64 7 2|74 6 3|      |Memory  *5|  TT6T|
+                        |LSRA |      |      |      |      |44 2 1|Accum A *5|  TT6T|
+                        |LSRB |      |      |      |      |54 2 1|Accum B *5|  TT6T|
+*/
+
+// LSR opcodes
+
+//#define OP_LSR_HANDLER(m) \
+       uint8 newCarry = m & 0x01; \
+       m >>= 1; \
+       SET_ZN(m); \
+       regs.cc = (regs.cc & ~FLAG_C) | newCarry; \
+       regs.cc = (regs.cc & ~FLAG_V) | ((regs.cc & FLAG_N) >> 2) ^ ((regs.cc & FLAG_C) << 1)
+#define OP_LSR_HANDLER(m) \
+       uint8 newCarry = m & 0x01; \
+       m >>= 1; \
+       SET_ZN(m); \
+       flagC = newCarry; \
+       flagV = flagN ^ flagC
+
+static void Op64(void)                                                 // LSR ZP, X
 {
-  tmp = regs.RdMem(regs.RdMem(regs.pc++));  uint8 as = regs.a; 
-  regs.a = regs.a - tmp - (regs.cc&0x01);
-  (as < (tmp+(regs.cc&0x01)) ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-  ((as^tmp^regs.a^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
-  (regs.a == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.a&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint8 m;
+       READ_ZP_X_WB(m);
+       OP_LSR_HANDLER(m);
+       WRITE_BACK(m);
 }
 
-static void Op94(void)  // ANDA ZP
+static void Op74(void)                                                 // LSR ABS
 {
-  regs.a &= regs.RdMem(regs.RdMem(regs.pc++));
-  regs.cc &= 0xF1;                   // CLV CLZ CLN
-  if (regs.a == 0)  regs.cc |= 0x04;     // Adjust Zero flag
-  if (regs.a&0x80)  regs.cc |= 0x08;     // Adjust Negative flag
+       uint8 m;
+       READ_ABS_WB(m);
+       OP_LSR_HANDLER(m);
+       WRITE_BACK(m);
 }
 
-static void Op95(void)  // BITA ZP
+static void Op44(void)                                                 // LSRA
 {
-tmp = regs.a & regs.RdMem(regs.RdMem(regs.pc++));
-regs.cc &= 0xFD;                             // Cleregs.a oVerflow flag
-(tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(tmp&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       OP_LSR_HANDLER(regs.a);
 }
 
-static void Op96(void)  // LDAA ZP
+static void Op54(void)                                                 // LSRB
 {
-  regs.a = regs.RdMem(regs.RdMem(regs.pc++));
-  regs.cc &= 0xF1;                            // CLN CLZ CLV
-  if (regs.a == 0)  regs.cc |= 0x04;              // Set Zero flag
-  if (regs.a&0x80)  regs.cc |= 0x08;              // Set Negative flag
+       OP_LSR_HANDLER(regs.b);
 }
 
-static void Op97(void)  // STAA ZP
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Store Accumulator       |STAA |      |97 4 2|A7 6 2|B7 5 3|      |M=A       |  TTR |
+                        |STAB |      |D7 4 2|E7 6 2|F7 5 3|      |M=B       |  TTR |
+*/
+
+static void Op97(void)                                                 // STAA ZP
 {
-regs.WrMem(regs.RdMem(regs.pc++), regs.a);
-regs.cc &= 0xFD;                            // CLV
-(regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       regs.WrMem(EA_ZP, regs.a);
 }
 
-static void Op98(void)  // EORA ZP
+static void OpA7(void)                                                 // STAA ZP, X
 {
-regs.a ^= regs.RdMem(regs.RdMem(regs.pc++));
-regs.cc &= 0xFD;                            // CLV
-(regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       regs.WrMem(EA_ZP_X, regs.a);
 }
 
-static void Op99(void)  // ADCA ZP
+static void OpB7(void)                                                 // STAA ABS
 {
-  tmp = regs.RdMem(regs.RdMem(regs.pc++));
-  addr = (uint16)regs.a + (uint16)tmp + (uint16)(regs.cc&0x01);
-  (addr > 0x00FF ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry
-  ((regs.a^tmp^addr^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow 
-  regs.a = addr & 0xFF;                       // Set accumulator
-  (regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero
-  (regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative
+       regs.WrMem(EA_ABS, regs.a);
+       regs.pc += 2;
 }
 
-static void Op9A(void)  // ORAA ZP
+static void OpD7(void)                                                 // STAB ZP
 {
-regs.a |= regs.RdMem(regs.RdMem(regs.pc++));
-regs.cc &= 0xFD;                            // CLV
-(regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       regs.WrMem(EA_ZP, regs.b);
 }
 
-static void Op9B(void)  // ADDA ZP
-{       
-  tmp = regs.RdMem(regs.RdMem(regs.pc++));
-  addr = (uint16)regs.a + (uint16)tmp;
-  (addr > 0x00FF ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Set Carry flag
-  ((regs.a^tmp^addr^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflo 
-  regs.a = addr & 0xFF;                       // Set accumulator
-  (regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Set Zero flag
-  (regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Set Negative flag
+static void OpE7(void)                                                 // STAB ZP, X
+{
+       regs.WrMem(EA_ZP_X, regs.b);
 }
 
-static void Op9C(void)  // CPX ZP
+static void OpF7(void)                                                 // STAB ABS
 {
-addr = regs.RdMem(regs.pc++);
-uint16 adr2 = (regs.RdMem(addr)<<8) | regs.RdMem(addr+1);
-uint16 dw = regs.x - adr2;
-(dw == 0   ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(dw&0x8000 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
-(regs.x < adr2 ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-((regs.x^adr2^dw^(regs.cc<<15))&0x8000 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerfl
+       regs.WrMem(EA_ABS, regs.b);
+       regs.pc += 2;
 }
 
-static void Op9E(void)                                                                 // LDS ZP
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Subtract                |SUBA |80 2 2|90 3 2|A0 5 2|B0 4 3|      |A=A-M     |  TTTT|
+                        |SUBB |C0 2 2|D0 3 2|E0 5 2|F0 4 3|      |B=B-M     |  TTTT|
+Subtract Accumulators   |SBA  |      |      |      |      |10 2 1|A=A-B     |  TTTT|
+*/
+
+// SUB opcodes
+
+//#define OP_SUB_HANDLER(m, acc) \
+       uint16 sum = (uint16)acc - (m); \
+       regs.cc = (regs.cc & ~FLAG_C) | (sum >> 15); \
+       SET_V(m, acc, sum); \
+       acc = (uint8)sum; \
+       SET_ZN(acc)
+#define OP_SUB_HANDLER(m, acc) \
+       uint16 sum = (uint16)acc - (m); \
+       flagC = sum >> 15; \
+       SET_V(m, acc, sum); \
+       acc = (uint8)sum; \
+       SET_ZN(acc)
+
+static void Op80(void)                                                 // SUBA #
 {
-       regs.s = RdMemW(regs.RdMem(regs.pc++));
+       uint16 m = READ_IMM;
+       OP_SUB_HANDLER(m, regs.a);
+}
 
-       regs.cc &= 0xFD;                              // CLV
-       (regs.s == 0   ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-       (regs.s&0x8000 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+static void Op90(void)                                                 // SUBA ZP
+{
+       uint16 m = READ_ZP;
+       OP_SUB_HANDLER(m, regs.a);
 }
 
-static void Op9F(void)                                                                 // STS ZP
+static void OpA0(void)                                                 // SUBA ZP, X
 {
-       WrMemW(regs.RdMem(regs.pc++), regs.s);
+       uint16 m = READ_ZP_X;
+       OP_SUB_HANDLER(m, regs.a);
+}
 
-       regs.cc &= 0xFD;                              // CLV
-       (regs.s == 0   ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-       (regs.s&0x8000 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+static void OpB0(void)                                                 // SUBA ABS
+{
+       uint16 m = READ_ABS;
+       OP_SUB_HANDLER(m, regs.a);
 }
 
-static void OpA0(void)  // SUBA IDX
-{ 
-tmp = regs.RdMem(DecodeIDX(regs.RdMem(regs.pc++)));  uint8 as = regs.a; 
-regs.a -= tmp;
-(regs.a == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.a&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
-(as < tmp ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-((as^tmp^regs.a^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
+static void OpC0(void)                                                 // SUBB #
+{
+       uint16 m = READ_IMM;
+       OP_SUB_HANDLER(m, regs.b);
 }
 
-static void OpA1(void)  // CMPA IDX
+static void OpD0(void)                                                 // SUBB ZP
 {
-tmp = regs.RdMem(DecodeIDX(regs.RdMem(regs.pc++)));
-uint8 db = regs.a - tmp;
-(db == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(db&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
-(regs.a < tmp ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-((regs.a^tmp^db^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
+       uint16 m = READ_ZP;
+       OP_SUB_HANDLER(m, regs.b);
 }
 
-static void OpA2(void)  // SBCA IDX
+static void OpE0(void)                                                 // SUBB ZP, X
 {
-  tmp = regs.RdMem(DecodeIDX(regs.RdMem(regs.pc++)));  uint8 as = regs.a; 
-  regs.a = regs.a - tmp - (regs.cc&0x01);
-  (as < (tmp+(regs.cc&0x01)) ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-  ((as^tmp^regs.a^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
-  (regs.a == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.a&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint16 m = READ_ZP_X;
+       OP_SUB_HANDLER(m, regs.b);
 }
 
-static void OpA4(void)  // ANDA IDX
+static void OpF0(void)                                                 // SUBB ABS
 {
-regs.a &= regs.RdMem(DecodeIDX(regs.RdMem(regs.pc++)));
-regs.cc &= 0xFD;                            // Cleregs.a oVerflow flag
-(regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint16 m = READ_ABS;
+       OP_SUB_HANDLER(m, regs.b);
 }
 
-static void OpA5(void)  // BITA IDX
+static void Op10(void)                                                 // SBA
 {
-tmp = regs.a & regs.RdMem(DecodeIDX(regs.RdMem(regs.pc++)));
-regs.cc &= 0xFD;                             // Cleregs.a oVerflow flag
-(tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(tmp&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       OP_SUB_HANDLER(regs.b, regs.a);
 }
 
-static void OpA6(void)  // LDAA IDX
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Subtract with Carry     |SBCA |82 2 2|92 3 2|A2 5 2|B2 4 3|      |A=A-M-C   |  TTTT|
+                        |SBCB |C2 2 2|D2 3 2|E2 5 2|F2 4 3|      |B=B-M-C   |  TTTT|
+*/
+
+// SBC opcodes
+
+//#define OP_SBC_HANDLER(m, acc) \
+       uint16 sum = (uint16)acc - (m) - (uint16)(regs.cc & FLAG_C); \
+       regs.cc = (regs.cc & ~FLAG_C) | (sum >> 15); \
+       SET_V(m, acc, sum); \
+       acc = (uint8)sum; \
+       SET_ZN(acc)
+#define OP_SBC_HANDLER(m, acc) \
+       uint16 sum = (uint16)acc - (m) - (uint16)flagC; \
+       flagC = sum >> 15; \
+       SET_V(m, acc, sum); \
+       acc = (uint8)sum; \
+       SET_ZN(acc)
+
+static void Op82(void)                                                 // SBCA #
 {
-  regs.a = regs.RdMem(DecodeIDX(regs.RdMem(regs.pc++)));
-  regs.cc &= 0xF1;                        // CLV CLZ CLN
-  if (regs.a == 0)  regs.cc |= 0x04;          // Set Zero flag
-  if (regs.a&0x80)  regs.cc |= 0x08;          // Set Negative flag
+       uint16 m = READ_IMM;
+       OP_SBC_HANDLER(m, regs.a);
 }
 
-static void OpA7(void)  // STAA IDX
+static void Op92(void)                                                 // SBCA ZP
 {
-  regs.WrMem(DecodeIDX(regs.RdMem(regs.pc++)), regs.a);
-  regs.cc &= 0xF1;                        // CLV CLZ CLN
-  if (regs.a == 0)  regs.cc |= 0x04;          // Set Zero flag
-  if (regs.a&0x80)  regs.cc |= 0x08;          // Set Negative flag
+       uint16 m = READ_ZP;
+       OP_SBC_HANDLER(m, regs.a);
 }
 
-static void OpA8(void)  // EORA IDX
+static void OpA2(void)                                                 // SBCA ZP, X
 {
-regs.a ^= regs.RdMem(DecodeIDX(regs.RdMem(regs.pc++)));
-regs.cc &= 0xFD;                            // CLV
-(regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint16 m = READ_ZP_X;
+       OP_SBC_HANDLER(m, regs.a);
 }
 
-static void OpA9(void)  // ADCA IDX
+static void OpB2(void)                                                 // SBCA ABS
 {
-  tmp = regs.RdMem(DecodeIDX(regs.RdMem(regs.pc++)));
-  addr = (uint16)regs.a + (uint16)tmp + (uint16)(regs.cc&0x01);
-  (addr > 0x00FF ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Set Carry flag
-  ((regs.a^tmp^addr^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflo 
-  regs.a = addr & 0xFF;                       // Set accumulator
-  (regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Set Zero flag
-  (regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Set Negative flag
+       uint16 m = READ_ABS;
+       OP_SBC_HANDLER(m, regs.a);
 }
 
-static void OpAA(void)  // ORAA IDX
+static void OpC2(void)                                                 // SBCB #
 {
-  regs.a |= regs.RdMem(DecodeIDX(regs.RdMem(regs.pc++)));
-  regs.cc &= 0xFD;                            // CLV
-  (regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint16 m = READ_IMM;
+       OP_SBC_HANDLER(m, regs.b);
 }
 
-static void OpAB(void)  // ADDA IDX
-{       
-  tmp = regs.RdMem(DecodeIDX(regs.RdMem(regs.pc++)));
-  addr = (uint16)regs.a + (uint16)tmp;
-  (addr > 0x00FF ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Set Carry flag
-  ((regs.a^tmp^addr^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflo 
-  regs.a = addr & 0xFF;                       // Set accumulator
-  (regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Set Zero flag
-  (regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Set Negative flag
+static void OpD2(void)                                                 // SBCB ZP
+{
+       uint16 m = READ_ZP;
+       OP_SBC_HANDLER(m, regs.b);
 }
 
-static void OpAC(void)  // CPX IDX
+static void OpE2(void)                                                 // SBCB ZP, X
 {
-  addr = DecodeIDX(regs.RdMem(regs.pc++));
-  uint16 addr2 = (regs.RdMem(addr)<<8) | regs.RdMem(addr+1);
-  uint16 dw = regs.x - addr2;
-  (dw == 0    ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (dw&0x8000  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
-  (regs.x < addr2 ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-  ((regs.x^addr2^dw^(regs.cc<<15))&0x8000 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
+       uint16 m = READ_ZP_X;
+       OP_SBC_HANDLER(m, regs.b);
 }
 
-static void OpAD(void)                                                                 // JSR IDX
+static void OpF2(void)                                                 // SBCB ABS
 {
-       addr = DecodeIDX(regs.RdMem(regs.pc++));
+       uint16 m = READ_ABS;
+       OP_SBC_HANDLER(m, regs.b);
+}
 
-       regs.s -= 2;
-       WrMemW(regs.s, regs.pc);
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Transfer Accumulators   |TAB  |      |      |      |      |16 2 1|B=A       |  TTR |
+                        |TBA  |      |      |      |      |17 2 1|A=B       |  TTR |
+*/
 
-       regs.pc = addr;                                                                         // JSR directly to IDX ptr
+static void Op16(void)                                                 // TAB
+{
+       regs.b = regs.a;
+       SET_ZN(regs.b);
+       CLR_V;
 }
 
-static void OpAE(void)                                                                 // LDS IDX
+static void Op17(void)                                                 // TBA
 {
-       regs.s = RdMemW(DecodeIDX(regs.RdMem(regs.pc++)));
-
-       regs.cc &= ~FLAG_V;
-       (regs.s == 0   ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-       (regs.s&0x8000 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       regs.a = regs.b;
+       SET_ZN(regs.a);
+       CLR_V;
 }
 
-static void OpAF(void)                                                                 // STS IDX
-{
-       WrMemW(DecodeIDX(regs.RdMem(regs.pc++)), regs.s);
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Test, Zero/Minus        |TST  |      |      |6D 7 2|7D 6 3|      |M-00      |  TTRR|
+                        |TSTA |      |      |      |      |4D 2 1|A-00      |  TTRR|
+                        |TSTB |      |      |      |      |5D 2 1|B-00      |  TTRR|
+*/
 
-       regs.cc &= ~(FLAG_N | FLAG_Z | FLAG_V);                         // Clear NZV
-       if (regs.s & 0x8000)  regs.cc |= FLAG_N;                        // Set Negative flag
-       if (regs.s == 0)      regs.cc |= FLAG_Z;                        // Set Zero flag
-}
+// TST opcodes
 
-static void OpB0(void)  // SUBA ABS
-{ 
-tmp = regs.RdMem(FetchW());  uint8 as = regs.a; 
-regs.a -= tmp;
-(regs.a == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.a&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
-(as < tmp ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-((as^tmp^regs.a^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
-}
+#define OP_TST_HANDLER(m) \
+       SET_ZN(m); \
+       CLR_VC
 
-static void OpB1(void)  // CMPA ABS
+static void Op6D(void)                                                 // TST ZP, X
 {
-tmp = regs.RdMem(FetchW());
-uint8 db = regs.a - tmp;
-(db == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(db&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
-(regs.a < tmp ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-((regs.a^tmp^db^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
+       uint8 m;
+       READ_ZP_X_WB(m);
+       OP_TST_HANDLER(m);
+       WRITE_BACK(m);
 }
 
-static void OpB2(void)  // SBCA ABS
+static void Op7D(void)                                                 // TST ABS
 {
-  tmp = regs.RdMem(FetchW());  uint8 as = regs.a; 
-  regs.a = regs.a - tmp - (regs.cc&0x01);
-  (as < (tmp+(regs.cc&0x01)) ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-  ((as^tmp^regs.a^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
-  (regs.a == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.a&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint8 m;
+       READ_ABS_WB(m);
+       OP_TST_HANDLER(m);
+       WRITE_BACK(m);
 }
 
-static void OpB4(void)  // ANDA ABS
+static void Op4D(void)                                                 // TSTA
 {
-  regs.a &= regs.RdMem(FetchW());
-  regs.cc &= 0xFD;                            // Cleregs.a oVerflow flag
-  (regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       OP_TST_HANDLER(regs.a);
 }
 
-static void OpB5(void)  // BITA ABS
+static void Op5D(void)                                                 // TSTB
 {
-  tmp = regs.a & regs.RdMem(FetchW());
-  regs.cc &= 0xFD;                             // Cleregs.a oVerflow flag
-  (tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (tmp&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       OP_TST_HANDLER(regs.b);
 }
 
-static void OpB6(void)  // LDAA ABS
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Compare Index Register  |CPX  |8C 3 3|9C 4 2|AC 6 2|BC 5 3|      |Formula 1 |  7T8 |
+*/
+
+// CPX opcodes
+
+/*
+Compare sets flags as if a subtraction had been carried out. If the value in the X register is equal or greater than the compared value, the Carry will be set. The equal (Z) and sign (S) flags will be set based on equality or lack thereof and the sign (i.e. X>=$8000) of the X register.
+*/
+
+#define OP_CPX_HANDLER(m) \
+       uint32 result = regs.x - (m); \
+       SET_ZNVC_CMP16(m, regs.x, result)
+
+static void Op8C(void)                                                 // CPX #
 {
-  regs.a = regs.RdMem(FetchW());
-  regs.cc &= 0xFD;                            // CLV
-  (regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint16 m = READ_IMM16;
+       OP_CPX_HANDLER(m);
 }
 
-static void OpB7(void)  // STAA ABS
+static void Op9C(void)                                                 // CPX ZP
 {
-  regs.WrMem(FetchW(), regs.a);
-  regs.cc &= 0xFD;                            // CLV
-  (regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint16 m = READ_ZP16;
+       OP_CPX_HANDLER(m);
 }
 
-static void OpB8(void)  // EORA ABS
+static void OpAC(void)                                                 // CPX ZP, X
 {
-  regs.a ^= regs.RdMem(FetchW());
-  regs.cc &= 0xFD;                            // CLV
-  (regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint16 m = READ_ZP_X16;
+       OP_CPX_HANDLER(m);
 }
 
-static void OpB9(void)  // ADCA ABS
+static void OpBC(void)                                                 // CPX ABS
 {
-  tmp = regs.RdMem(FetchW());
-  addr = (uint16)regs.a + (uint16)tmp + (uint16)(regs.cc&0x01);
-  (addr > 0x00FF ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Set Carry flag
-  ((regs.a^tmp^addr^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow 
-  regs.a = addr;                              // Set accumulator
-  (regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Set Zero flag
-  (regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Set Negative flag
+       uint16 m = READ_ABS16;
+       OP_CPX_HANDLER(m);
 }
 
-static void OpBA(void)  // ORAA ABS
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Decrement Index Register|DEX  |      |      |      |      |09 4 1|X=X-1     |   T  |
+Dec Stack Pointer       |DES  |      |      |      |      |34 4 1|SP=SP-1   |      |
+Inc Index Regster       |INX  |      |      |      |      |08 4 1|X=X+1     |   T  |
+Inc Stack Pointer       |INS  |      |      |      |      |31 4 1|SP=SP+1   |      |
+*/
+
+static void Op09(void)                                                 // DEX
 {
-  regs.a |= regs.RdMem(FetchW());
-  regs.cc &= 0xFD;                            // CLV
-  (regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       regs.x--;
+       SET_Z(regs.x);
 }
 
-static void OpBB(void)  // ADDA ABS
-{       
-  tmp = regs.RdMem(FetchW());
-  addr = (uint16)regs.a + (uint16)tmp;
-  (addr > 0x00FF ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Set Carry flag
-  ((regs.a^tmp^addr^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflo
-  regs.a = addr & 0xFF;                       // Set accumulator
-  (regs.a == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Set Zero flag
-  (regs.a&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Set Negative flag
+static void Op34(void)                                                 // DES
+{
+       regs.s--;
 }
 
-static void OpBC(void)  // CPX ABS
+static void Op08(void)                                                 // INX
 {
-  addr = FetchW();  uint16 addr2 = (regs.RdMem(addr)<<8) | regs.RdMem(addr+1);
-  uint16 dw = regs.x - addr2;
-  (dw == 0   ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (dw&0x8000 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
-  (regs.x < addr2 ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-  ((regs.x^addr2^dw^(regs.cc<<15))&0x8000 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
+       regs.x++;
+       SET_Z(regs.x);
 }
 
-static void OpBD(void)                                                                 // JSR ABS
+static void Op31(void)                                                 // INS
 {
-       addr = FetchW();
+       regs.s++;
+}
 
-       regs.s -= 2;
-       WrMemW(regs.s, regs.pc);
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Load Index Register     |LDX  |CE 3 3|DE 4 2|EE 6 2|FE 5 3|      |Formula 2 |  9TR |
+Load Stack Pointer      |LDS  |8E 3 3|9E 4 2|AE 6 2|BE 5 3|      |Formula 3 |  9TR |
+*/
 
-       regs.pc = addr;                                                                         // Go to absolute address (Not indir)
-}
+// LD* opcode handler
+
+#define OP_LD_HANDLER(acc) \
+       SET_N16(acc); \
+       SET_Z(acc); \
+       CLR_V
 
-static void OpBE(void)  // LDS ABS
+static void OpCE(void)                                                 // LDX #
 {
-  addr = FetchW();
-  regs.s = (regs.RdMem(addr) << 8) | regs.RdMem(addr+1);
-  regs.cc &= 0xFD;                              // CLV
-  (regs.s == 0   ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.s&0x8000 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       regs.x = READ_IMM16;
+       OP_LD_HANDLER(regs.x);
 }
 
-static void OpBF(void)  // STS ABS
+static void OpDE(void)                                                 // LDX ZP
 {
-addr = FetchW();
-regs.WrMem(addr, regs.s>>8);  regs.WrMem(addr+1, regs.s&0xFF);
-regs.cc &= 0xFD;                              // CLV
-(regs.s == 0   ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.s&0x8000 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       regs.x = READ_ZP16;
+       OP_LD_HANDLER(regs.x);
 }
 
-static void OpC0(void)  // SUBB #
-{ 
-tmp = regs.RdMem(regs.pc++);  uint8 bs = regs.b; 
-regs.b -= tmp;
-(regs.b == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.b&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
-(bs < tmp ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-((bs^tmp^regs.b^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
+static void OpEE(void)                                                 // LDX ZP, X
+{
+       regs.x = READ_ZP_X16;
+       OP_LD_HANDLER(regs.x);
 }
 
-static void OpC1(void)  // CMPB #
+static void OpFE(void)                                                 // LDX ABS
 {
-tmp = regs.RdMem(regs.pc++);
-uint8 db = regs.b - tmp;
-(regs.b < tmp ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-((regs.b^tmp^db^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
-(db == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(db&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       regs.x = READ_ABS16;
+       OP_LD_HANDLER(regs.x);
 }
 
-static void OpC2(void)  // SBCB #
+static void Op8E(void)                                                 // LDS #
 {
-  tmp = regs.RdMem(regs.pc++);  uint8 bs = regs.b; 
-  regs.b = regs.b - tmp - (regs.cc&0x01);
-  (bs < (tmp+(regs.cc&0x01)) ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-  ((bs^tmp^regs.b^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
-  (regs.b == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.b&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       regs.s = READ_IMM16;
+       OP_LD_HANDLER(regs.s);
 }
 
-static void OpC4(void)  // ANDB #
+static void Op9E(void)                                                 // LDS ZP
 {
-regs.b &= regs.RdMem(regs.pc++);
-regs.cc &= 0xFD;                            // Cleregs.a oVerflow flag
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       regs.s = READ_ZP16;
+       OP_LD_HANDLER(regs.s);
 }
 
-static void OpC5(void)  // BITB #
+static void OpAE(void)                                                 // LDS ZP, X
 {
-  tmp = regs.b & regs.RdMem(regs.pc++);
-  regs.cc &= 0xF1;                             // CLV CLZ CLN
-  if (tmp == 0)  regs.cc |= 0x04;              // Set Zero flag
-  if (tmp&0x80)  regs.cc |= 0x08;              // Set Negative flag
+       regs.s = READ_ZP_X16;
+       OP_LD_HANDLER(regs.s);
 }
 
-static void OpC6(void)  // LDAB #
+static void OpBE(void)                                                 // LDS ABS
 {
-  regs.b = regs.RdMem(regs.pc++);
-  regs.cc &= 0xF1;                             // CLV CLZ CLN
-  if (regs.b == 0)  regs.cc |= 0x04;               // Set Zero flag
-  if (regs.b&0x80)  regs.cc |= 0x08;               // Set Negative flag
+       regs.s = READ_ABS16;
+       OP_LD_HANDLER(regs.s);
 }
 
-static void OpC8(void)  // EORB #
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Store Index Register    |STX  |      |DF 5 2|EF 7 2|FF 6 3|      |Formula 4 |  9TR |
+Store Stack Pointer     |STS  |      |9F 5 2|AF 7 2|BF 6 3|      |Formula 5 |  9TR |
+*/
+
+// ST* opcode handler
+
+#define OP_ST_HANDLER(m, acc) \
+       regs.WrMem(m + 0, acc >> 8); \
+       regs.WrMem(m + 1, acc & 0xFF); \
+       SET_N16(acc); \
+       SET_Z(acc); \
+       CLR_V
+
+static void OpDF(void)                                                 // STX ZP
 {
-regs.b ^= regs.RdMem(regs.pc++);
-regs.cc &= 0xFD;                            // CLV
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint16 m = EA_ZP;
+       OP_ST_HANDLER(m, regs.x);
 }
 
-static void OpC9(void)  // ADCB #
+static void OpEF(void)                                                 // STX ZP, X
 {
-  tmp = regs.RdMem(regs.pc++);
-  addr = (uint16)regs.b + (uint16)tmp + (uint16)(regs.cc&0x01);
-  (addr > 0x00FF ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Set Carry flag
-  ((regs.b^tmp^addr^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflo 
-  regs.b = addr & 0xFF;                       // Set accumulator
-  (regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Set Zero flag
-  (regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Set Negative flag
+       uint16 m = EA_ZP_X;
+       OP_ST_HANDLER(m, regs.x);
 }
 
-static void OpCA(void)  // ORAB #
+static void OpFF(void)                                                 // STX ABS
 {
-regs.b |= regs.RdMem(regs.pc++);
-regs.cc &= 0xFD;                            // CLV
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint16 m = EA_ABS;
+       regs.pc += 2;
+       OP_ST_HANDLER(m, regs.x);
 }
 
-static void OpCB(void)  // ADDB #
-{       
-  tmp = regs.RdMem(regs.pc++);  addr = regs.b + tmp;
-  (addr > 0xFF ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Set Carry flag
-  ((regs.b^tmp^addr^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflo 
-  regs.b = addr & 0xFF;                       // Set accumulator
-  (regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Set Zero flag
-  (regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Set Negative flag
+static void Op9F(void)                                                 // STS ZP
+{
+       uint16 m = EA_ZP;
+       OP_ST_HANDLER(m, regs.s);
 }
 
-static void OpCE(void)  // LDX #
+static void OpAF(void)                                                 // STS ZP, X
 {
-  regs.x = FetchW();
-  regs.cc &= 0xFD;                              // CLV
-  (regs.x == 0   ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.x&0x8000 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       uint16 m = EA_ZP_X;
+       OP_ST_HANDLER(m, regs.s);
 }
 
-static void OpD0(void)  // SUBB ZP
-{ 
-  tmp = regs.RdMem(regs.RdMem(regs.pc++));  uint8 bs = regs.b; 
-  regs.b -= tmp;
-  (regs.b == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.b&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
-  (bs < tmp ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-  ((bs^tmp^regs.b^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
+static void OpBF(void)                                                 // STS ABS
+{
+       uint16 m = EA_ABS;
+       regs.pc += 2;
+       OP_ST_HANDLER(m, regs.s);
 }
 
-static void OpD1(void)  // CMPB ZP
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Index Reg > Stack Pnter |TXS  |      |      |      |      |35 4 1|SP=X-1    |      |
+Stack Ptr > Index Regtr |TSX  |      |      |      |      |30 4 1|X=SP+1    |      |
+*/
+
+static void Op35(void)                                                 // TXS
 {
-  tmp = regs.RdMem(regs.RdMem(regs.pc++));
-  uint8 db = regs.b - tmp;
-  (db == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (db&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
-  (regs.b < tmp ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-  ((regs.b^tmp^db^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
+       regs.s = regs.x - 1;
 }
 
-static void OpD2(void)  // SBCB ZP
+static void Op30(void)                                                 // TSX
 {
-  tmp = regs.RdMem(regs.RdMem(regs.pc++));  uint8 bs = regs.b; 
-  regs.b = regs.b - tmp - (regs.cc&0x01);
-  (bs < (tmp+(regs.cc&0x01)) ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-  ((bs^tmp^regs.b^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
-  (regs.b == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.b&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       regs.x = regs.s + 1;
 }
 
-static void OpD4(void)  // ANDB ZP
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Always                  |BRA  |      |20 4 2|      |      |      |none      |      |
+Carry is Clear          |BCC  |      |24 4 2|      |      |      |C=0       |      |
+Carry is Set            |BCS  |      |25 4 2|      |      |      |C=1       |      |
+Equals Zero             |BEQ  |      |27 4 2|      |      |      |Z=1       |      |
+Greater or Equal to Zero|BGE  |      |2C 4 2|      |      |      |N(+)V=0   |      |
+Greater than Zero       |BGT  |      |2E 4 2|      |      |      |Z+N(+)V=0 |      |
+Higher                  |BHI  |      |22 4 2|      |      |      |C+Z=0     |      |
+Less or Equal than Zero |BLE  |      |2F 4 2|      |      |      |Z+N(+)V=1 |      |
+Lower or Same           |BLS  |      |23 4 2|      |      |      |C+Z=1     |      |
+Less Than Zero          |BLT  |      |2D 4 2|      |      |      |N(+)V=1   |      |
+Minus                   |BMI  |      |2B 4 2|      |      |      |N=1       |      |
+Not Zero                |BNE  |      |26 4 2|      |      |      |Z=0       |      |
+Overflow Clear          |BVC  |      |28 4 2|      |      |      |V=0       |      |
+Overflow Set            |BVS  |      |29 4 2|      |      |      |V=1       |      |
+Plus                    |BPL  |      |2A 4 2|      |      |      |N=0       |      |
+*/
+
+static void Op20(void)                                                 // BRA
 {
-regs.b &= regs.RdMem(regs.RdMem(regs.pc++));
-regs.cc &= 0xFD;                            // Clear oVerflow flag
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       int16 m = (int16)(int8)READ_IMM;
+       regs.pc += m;
 }
 
-static void OpD5(void)  // BITB ZP
+static void Op24(void)                                                 // BCC
 {
-tmp = regs.b & regs.RdMem(regs.RdMem(regs.pc++));
-regs.cc &= 0xFD;                             // Clear oVerflow flag
-(tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(tmp&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       int16 m = (int16)(int8)READ_IMM;
+
+//     if (!(regs.cc & FLAG_C))
+       if (!flagC)
+               regs.pc += m;
 }
 
-static void OpD6(void)  // LDAB ZP
+static void Op25(void)                                                 // BCS
 {
-  regs.b = regs.RdMem(regs.RdMem(regs.pc++));
-  regs.cc &= 0xFD;                            // CLV
-  (regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       int16 m = (int16)(int8)READ_IMM;
+
+//     if (regs.cc & FLAG_C)
+       if (flagC)
+               regs.pc += m;
 }
 
-static void OpD7(void)  // STAB ZP
+static void Op27(void)                                                 // BEQ
 {
-regs.WrMem(regs.RdMem(regs.pc++), regs.b);
-regs.cc &= 0xFD;                            // CLV
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       int16 m = (int16)(int8)READ_IMM;
+
+//     if (regs.cc & FLAG_Z)
+       if (flagZ)
+               regs.pc += m;
 }
 
-static void OpD8(void)  // EORB ZP
+static void Op2C(void)                                                 // BGE
 {
-regs.b ^= regs.RdMem(regs.RdMem(regs.pc++));
-regs.cc &= 0xFD;                            // CLV
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       int16 m = (int16)(int8)READ_IMM;
+
+//     if (!(((regs.cc & FLAG_N) >> 2) ^ (regs.cc & FLAG_V)))
+       if (!(flagN ^ flagV))
+               regs.pc += m;
 }
 
-static void OpD9(void)  // ADCB ZP
+static void Op2E(void)                                                 // BGT
 {
-  tmp = regs.RdMem(regs.RdMem(regs.pc++));
-  addr = (uint16)regs.b + (uint16)tmp + (uint16)(regs.cc&0x01);
-  (addr > 0x00FF ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Set Carry flag
-  ((regs.b^tmp^addr^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow 
-  regs.b = addr;                              // Set accumulator
-  (regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Set Zero flag
-  (regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Set Negative flag
+       int16 m = (int16)(int8)READ_IMM;
+
+//     if (!(((regs.cc & FLAG_Z) >> 1) | (((regs.cc & FLAG_N) >> 2) ^ (regs.cc & FLAG_V))))
+       if (!(flagZ | (flagN ^ flagV)))
+               regs.pc += m;
 }
 
-static void OpDA(void)  // ORAB ZP
+static void Op22(void)                                                 // BHI
 {
-regs.b |= regs.RdMem(regs.RdMem(regs.pc++));
-regs.cc &= 0xFD;                            // CLV
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
-}
+       int16 m = (int16)(int8)READ_IMM;
 
-static void OpDB(void)  // ADDB ZP
-{       
-  tmp = regs.RdMem(regs.RdMem(regs.pc++));
-  addr = (uint16)regs.b + (uint16)tmp;
-  (addr > 0x00FF ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Set Carry flag
-  ((regs.b^tmp^addr^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow 
-  regs.b = addr & 0xFF;                       // Set accumulator
-  (regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Set Zero flag
-  (regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Set Negative flag
+//     if (!(((regs.cc & FLAG_Z) >> 2) | (regs.cc & FLAG_C)))
+       if (!(flagZ | flagC))
+               regs.pc += m;
 }
 
-static void OpDE(void)  // LDX ZP
+static void Op2F(void)                                                 // BLE
 {
-  addr = regs.RdMem(regs.pc++);
-  regs.x = (regs.RdMem(addr) << 8) | regs.RdMem(addr+1);
-  regs.cc &= 0xFD;                              // CLV
-  (regs.x == 0   ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.x&0x8000 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       int16 m = (int16)(int8)READ_IMM;
+
+//     if (((regs.cc & FLAG_Z) >> 1) | (((regs.cc & FLAG_N) >> 2) ^ (regs.cc & FLAG_V)))
+       if (flagZ | (flagN ^ flagV))
+               regs.pc += m;
 }
 
-static void OpDF(void)  // STX ZP
+static void Op23(void)                                                 // BLS
 {
-  addr = regs.RdMem(regs.pc++);
-  regs.WrMem(addr, regs.x>>8);  regs.WrMem(addr+1, regs.x&0xFF);
-  regs.cc &= 0xFD;                              // CLV
-  (regs.x == 0   ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.x&0x8000 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
-}
+       int16 m = (int16)(int8)READ_IMM;
 
-static void OpE0(void)  // SUBB IDX
-{ 
-  tmp = regs.RdMem(DecodeIDX(regs.RdMem(regs.pc++)));  uint8 bs = regs.b; 
-  regs.b -= tmp;
-  (regs.b == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.b&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
-  (bs < tmp ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-  ((bs^tmp^regs.b^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
+//     if (((regs.cc & FLAG_Z) >> 2) | (regs.cc & FLAG_C))
+       if (flagZ | flagC)
+               regs.pc += m;
 }
 
-static void OpE1(void)  // CMPB IDX
+static void Op2D(void)                                                 // BLT
 {
-  tmp = regs.RdMem(DecodeIDX(regs.RdMem(regs.pc++)));
-  uint8 db = regs.b - tmp;
-  (db == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (db&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
-  (regs.b < tmp ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-  ((regs.b^tmp^db^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
+       int16 m = (int16)(int8)READ_IMM;
+
+//     if (((regs.cc & FLAG_N) >> 2) ^ (regs.cc & FLAG_V))
+       if (flagN ^ flagV)
+               regs.pc += m;
 }
 
-static void OpE2(void)  // SBCB IDX
+static void Op2B(void)                                                 // BMI
 {
-  tmp = regs.RdMem(DecodeIDX(regs.RdMem(regs.pc++)));  uint8 bs = regs.b; 
-  regs.b = regs.b - tmp - (regs.cc&0x01);
-  (bs < (tmp+(regs.cc&0x01)) ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-  ((bs^tmp^regs.b^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
-  (regs.b == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.b&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       int16 m = (int16)(int8)READ_IMM;
+
+//     if (regs.cc & FLAG_N)
+       if (flagN)
+               regs.pc += m;
 }
 
-static void OpE4(void)  // ANDB IDX
+static void Op26(void)                                                 // BNE
 {
-regs.b &= regs.RdMem(DecodeIDX(regs.RdMem(regs.pc++)));
-regs.cc &= 0xFD;                            // Clear oVerflow flag
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       int16 m = (int16)(int8)READ_IMM;
+
+//     if (!(regs.cc & FLAG_Z))
+       if (!flagZ)
+               regs.pc += m;
 }
 
-static void OpE5(void)  // BITB IDX
+static void Op28(void)                                                 // BVC
 {
-tmp = regs.b & regs.RdMem(DecodeIDX(regs.RdMem(regs.pc++)));
-regs.cc &= 0xFD;                             // Clear oVerflow flag
-(tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(tmp&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       int16 m = (int16)(int8)READ_IMM;
+
+//     if (!(regs.cc & FLAG_V))
+       if (!flagV)
+               regs.pc += m;
 }
 
-static void OpE6(void)  // LDB IDX
+static void Op29(void)                                                 // BVS
 {
-regs.b = regs.RdMem(DecodeIDX(regs.RdMem(regs.pc++)));
-regs.cc &= 0xFD;                            // CLV
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       int16 m = (int16)(int8)READ_IMM;
+
+//     if (regs.cc & FLAG_V)
+       if (flagV)
+               regs.pc += m;
 }
 
-static void OpE7(void)  // STB IDX
+static void Op2A(void)                                                 // BPL
 {
-  regs.WrMem(DecodeIDX(regs.RdMem(regs.pc++)), regs.b);
-  regs.cc &= 0xF1;                            // CLV CLZ CLN
-  if (regs.b == 0)  regs.cc |= 0x04;              // Adjust Zero flag
-  if (regs.b&0x80)  regs.cc |= 0x08;              // Adjust Negative flag
+       int16 m = (int16)(int8)READ_IMM;
+
+//     if (!(regs.cc & FLAG_N))
+       if (!flagN)
+               regs.pc += m;
 }
 
-static void OpE8(void)  // EORB IDX
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Branch to Subroutine    |BSR  |      |8D 8 2|      |      |      |          |      |
+Jump                    |JMP  |      |      |6E 4 2|7E 3 3|      |          |      |
+Jump to Subroutine      |JSR  |      |      |AD 8 2|BD 9 3|      |          |      |
+*/
+
+static void Op8D(void)                                                 // BSR
 {
-regs.b ^= regs.RdMem(DecodeIDX(regs.RdMem(regs.pc++)));
-regs.cc &= 0xFD;                            // CLV
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       int16 m = (int16)(int8)READ_IMM;
+       PUSH16(regs.pc);
+       regs.pc += m;
 }
 
-static void OpE9(void)  // ADCB IDX
+static void Op6E(void)                                                 // JMP ZP, X
 {
-  tmp = regs.RdMem(DecodeIDX(regs.RdMem(regs.pc++)));
-  addr = (uint16)regs.b + (uint16)tmp + (uint16)(regs.cc&0x01);
-  (addr > 0x00FF ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Set Carry flag
-  ((regs.b^tmp^addr^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow 
-  regs.b = addr;                                  // Set accumulator
-  (regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Set Zero flag
-  (regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Set Negative flag
+       regs.pc = EA_ZP_X;
 }
 
-static void OpEA(void)  // ORB IDX
+static void Op7E(void)                                                 // JMP ABS
 {
-regs.b |= regs.RdMem(DecodeIDX(regs.RdMem(regs.pc++)));
-regs.cc &= 0xFD;                            // CLV
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       regs.pc = EA_ABS;
 }
 
-static void OpEB(void)  // ADDB IDX
-{       
-  tmp = regs.RdMem(DecodeIDX(regs.RdMem(regs.pc++)));
-  addr = (uint16)regs.b + (uint16)tmp;
-  (addr > 0x00FF ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Set Carry flag
-  ((regs.b^tmp^addr^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow 
-  regs.b = addr;                              // Set accumulator
-  (regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Set Zero flag
-  (regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Set Negative flag
+static void OpAD(void)                                                 // JSR ZP, X
+{
+       uint16 m = EA_ZP_X;
+       PUSH16(regs.pc);
+       regs.pc = m;
 }
 
-static void OpEE(void)  // LDX IDX
+static void OpBD(void)                                                 // JSR ABS
 {
-  addr = DecodeIDX(regs.RdMem(regs.pc++));
-  regs.x = (regs.RdMem(addr) << 8) | regs.RdMem(addr+1);
-  regs.cc &= 0xF1;                              // CLV CLZ CLN
-  if (regs.x == 0)    regs.cc |= 0x04;              // Set Zero flag
-  if (regs.x&0x8000)  regs.cc |= 0x08;              // Set Negative flag
+       uint16 m = EA_ABS;
+       regs.pc += 2;
+       PUSH16(regs.pc);
+       regs.pc = m;
 }
 
-static void OpEF(void)  // STX IDX
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+No Operation            |NOP  |      |      |      |      |01 2 1|          |      |
+Return from Interrupt   |RTI  |      |      |      |      |3B A 1|          |AAAAAA|
+Return from Subroutine  |RTS  |      |      |      |      |39 5 1|          |      |
+Software Interrupt      |SWI  |      |      |      |      |3F C 1|          | S    |
+Wait For Interrupt      |WAI  |      |      |      |      |3E 9 1|          | B    |
+*/
+
+static void Op01(void)                                                 // NOP
 {
-  addr = DecodeIDX(regs.RdMem(regs.pc++));
-  regs.WrMem(addr, regs.x>>8);  regs.WrMem(addr+1, regs.x&0xFF);
-  regs.cc &= 0xF1;                              // CLV CLZ CLN
-  if (regs.x == 0)    regs.cc |= 0x04;              // Set Zero flag
-  if (regs.x&0x8000)  regs.cc |= 0x08;              // Set Negative flag
 }
 
-static void OpF0(void)  // SUBB ABS
-{ 
-tmp = regs.RdMem(FetchW());  uint8 bs = regs.b; 
-regs.b -= tmp;
-(regs.b == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.b&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
-(bs < tmp ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-((bs^tmp^regs.b^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
+static void Op3B(void)                                                 // RTI
+{
+       regs.cc = PULL;
+       regs.a  = PULL;
+       regs.b  = PULL;
+       regs.x  = PULL16;
+       regs.pc = PULL16;
+       UNPACK_FLAGS;
 }
 
-static void OpF1(void)  // CMPB ABS
+static void Op39(void)                                                 // RTS
 {
-tmp = regs.RdMem(FetchW());
-uint8 db = regs.b - tmp;
-(db == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(db&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
-(regs.b < tmp ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-((regs.b^tmp^db^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
+       regs.pc = PULL16;
 }
 
-static void OpF2(void)  // SBCB ABS
+static void Op3F(void)                                                 // SWI
 {
-  tmp = regs.RdMem(FetchW());  uint8 bs = regs.b; 
-  regs.b = regs.b - tmp - (regs.cc&0x01);
-  (regs.b == 0  ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-  (regs.b&0x80  ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
-  (bs < tmp ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Adjust Carry flag
-  ((bs^tmp^regs.b^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflow
+       // It seems that the SWI is non-maskable, unlike the IRQ...
+       regs.cc = PACK_FLAGS;                                           // Mash flags back into the CC register
+       PUSH16(regs.pc);                                                        // Save all regs...
+       PUSH16(regs.x);
+       PUSH(regs.b);
+       PUSH(regs.a);
+       PUSH(regs.cc);
+       regs.pc = RdMemW(0xFFFA);                                       // And do it!
+//     regs.cc |= FLAG_I;                                                      // Also, set IRQ inhibit
+       flagI = 1;                                                                      // Also, set IRQ inhibit
 }
 
-static void OpF4(void)  // ANDB ABS
+static void Op3E(void)                                                 // WAI
 {
-regs.b &= regs.RdMem(FetchW());
-regs.cc &= 0xFD;                            // Clear oVerflow flag
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
-}
+#ifdef __DEBUG__
+WriteLog("*** WAI STATE ASSERTED ***\n");
+#endif
+       regs.cc = PACK_FLAGS;                                           // Mash flags back into the CC register
+       PUSH16(regs.pc);                                                        // Save all regs...
+       PUSH16(regs.x);
+       PUSH(regs.b);
+       PUSH(regs.a);
+       PUSH(regs.cc);
+       regs.cpuFlags |= V6808_STATE_WAI;                       // And signal that we're in WAI mode
+}
+
+/*
+Operation               |Mnem.|Immed.|Direct|Index |Extend|Inher.|Operation |CC Reg|
+                        |     |OP ~ #|OP ~ #|OP ~ #|OP ~ #|OP ~ #|          |HINZVC|
+Clear Carry             |CLC  |      |      |      |      |0C 2 1|C=0       |     R|
+Clear Interrupt         |CLI  |      |      |      |      |0E 2 1|I=0       | R    |
+Clear Overflow          |CLV  |      |      |      |      |0A 2 1|V=0       |    R |
+Set Carry               |SEC  |      |      |      |      |0D 2 1|C=1       |     S|
+Set Interrupt           |SEI  |      |      |      |      |0F 2 1|I=1       | S    |
+Set Overflow            |SEV  |      |      |      |      |0B 2 1|V=1       |    S |
+CCR=Accumulator A       |TAP  |      |      |      |      |06 2 1|CCR=A     |CCCCCC|
+Accumlator A=CCR        |TPA  |      |      |      |      |07 2 1|A=CCR     |      |
+*/
 
-static void OpF5(void)  // BITB ABS
+static void Op0C(void)                                                 // CLC
 {
-tmp = regs.b & regs.RdMem(FetchW());
-regs.cc &= 0xFD;                             // Clear oVerflow flag
-(tmp == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(tmp&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+//     regs.cc &= ~FLAG_C;
+       flagC = 0;
 }
 
-static void OpF6(void)  // LDB ABS
+static void Op0E(void)                                                 // CLI
 {
-regs.b = regs.RdMem(FetchW());
-regs.cc &= 0xFD;                            // CLV
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+//     regs.cc &= ~FLAG_I;
+       flagI = 0;
 }
 
-static void OpF7(void)  // STB ABS
+static void Op0A(void)                                                 // CLV
 {
-regs.WrMem(FetchW(), regs.b);
-regs.cc &= 0xFD;                            // CLV
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+//     regs.cc &= ~FLAG_V;
+       flagV = 0;
 }
 
-static void OpF8(void)  // EORB ABS
+static void Op0D(void)                                                 // SEC
 {
-regs.b ^= regs.RdMem(FetchW());
-regs.cc &= 0xFD;                            // CLV
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+//     regs.cc |= FLAG_C;
+       flagC = 1;
 }
 
-static void OpF9(void)  // ADCB ABS
+static void Op0F(void)                                                 // SEI
 {
-  tmp = regs.RdMem(FetchW());
-  addr = (uint16)regs.b + (uint16)tmp + (uint16)(regs.cc&0x01);
-  (addr > 0x00FF ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Set Carry flag
-  ((regs.b^tmp^addr^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflo 
-  regs.b = addr & 0xFF;                       // Set accumulator
-  (regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Set Zero flag
-  (regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Set Negative flag
+//     regs.cc |= FLAG_I;
+       flagI = 1;
 }
 
-static void OpFA(void)  // ORB ABS
+static void Op0B(void)                                                 // SEV
 {
-regs.b |= regs.RdMem(FetchW());
-regs.cc &= 0xFD;                            // CLV
-(regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
-}       
-
-static void OpFB(void)  // ADDB ABS
-{       
-  tmp = regs.RdMem(FetchW());
-  addr = (uint16)regs.b + (uint16)tmp;
-  (addr > 0x00FF ? regs.cc |= 0x01 : regs.cc &= 0xFE);  // Set Carry flag
-  ((regs.b^tmp^addr^(regs.cc<<7))&0x80 ? regs.cc |= 0x02 : regs.cc &= 0xFD); // oVerflo 
-  regs.b = addr & 0xFF;                       // Set accumulator
-  (regs.b == 0 ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Set Zero flag
-  (regs.b&0x80 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Set Negative flag
+//     regs.cc |= FLAG_V;
+       flagV = 1;
 }
 
-static void OpFE(void)  // LDX ABS
+static void Op06(void)                                                 // TAP
 {
-addr = FetchW();
-regs.x = (regs.RdMem(addr) << 8) | regs.RdMem(addr+1);
-regs.cc &= 0xFD;                              // CLV
-(regs.x == 0   ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.x&0x8000 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
+       regs.cc = regs.a;
+       UNPACK_FLAGS;
 }
 
-static void OpFF(void)  // STX ABS
+static void Op07(void)                                                 // TPA
 {
-addr = FetchW();
-regs.WrMem(addr, regs.x>>8);  regs.WrMem(addr+1, regs.x&0xFF);
-regs.cc &= 0xFD;                              // CLV
-(regs.x == 0   ? regs.cc |= 0x04 : regs.cc &= 0xFB);  // Adjust Zero flag
-(regs.x&0x8000 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
-}
+//     regs.a = regs.cc;
+       regs.a = PACK_FLAGS;
+}
+
+/*
+  OP  Operation Code, in Hexadecimal
+  ~   Number of MPU cycles required
+  #   Number of program bytes required
+  +   Arithmetic Plus
+  -   Arithmetic Minus
+  +   Boolean AND
+  Msp Contents of Memory pointed to be Stack Pointer
+  +   Boolean Inclusive OR
+  (+) Boolean Exclusive OR (XOR)
+  *   Converts Binary Addition of BCD Characters into BCD Format
+  *-  SP=SP-1
+  *+  SP=SP+1
+
+  Condition Code Register Legend
+     Not Affected
+   R Reset (0, Low)
+   S Set   (1, High)
+   T Tests and sets if True, cleared otherise
+   1 Test: Result=10000000?
+   2 Test: Result=00000000?
+   3 Test: Decimal value of most significant BCD character greater than nine?
+           (Not cleared if previously set)
+   4 Test: Operand=10000000 prior to execution?
+   5 Test: Operand=01111111 prior to execution?
+   6 Test: Set equal to result or N(+)C after shift has occurred.
+   7 Test: Sign bit of most significant byte or result=1?
+   8 Test: 2's compliment overflow from subtraction of least 
+           significant bytes?
+   9 Test: Result less than zero? (Bit 15=1)
+   A Load Condition Code Register from Stack.
+   B Set when interrupt occurs.  If previously set, a NMI is 
+        required to exit the wait state.
+   C Set according to the contents of Accumulator A.
+
+  *x SHIFT AND ROTATION DIAGRAMS
+   *1     +-----------------+       C to LSB
+          - C <- 76543210 <-+
+
+   *2    +-----------------+
+         +> C -> 76543210 -+
+
+   *3       C <- 76543210 <- 0(Data) 
+               +-+
+
+   *4          Ã€>76543210 -> C
+
+   *5 (Data)0 -> 76543210 -> C
+
+  FORMULAS
+   1: (Xh/Xl)-(M/M+1)
+   2: Xh=M, Xl=M+1
+   3: SPh=M, SPl=M+1
+   4: M=Xh, M+1=Xl
+*/
 
 static void Op__(void)
 {
@@ -1842,49 +2091,66 @@ static void myMemcpy(void * dst, void * src, uint32 size)
                d[i] = s[i];
 }
 
+#ifdef __DEBUG__
 //int instCount[256];
+static bool logGo = false;
+#endif
 //
 // Function to execute 6808 for "cycles" cycles
 //
 void Execute6808(V6808REGS * context, uint32 cycles)
 {
+#warning V6808_STATE_WAI is not properly handled yet!
+
        myMemcpy(&regs, context, sizeof(V6808REGS));
+       UNPACK_FLAGS;                                                           // Explode flags register into individual uint8s
 
        // Execute here...
        while (regs.clock < cycles)
        {
 #ifdef __DEBUG__
-Decode6808(regs.pc);
+if (logGo)
+       Decode6808(regs.pc);
 #endif
                uint8 opcode = regs.RdMem(regs.pc++);
 
+#ifdef __DEBUG__
 //if (!(regs.cpuFlags & V6808_STATE_ILLEGAL_INST))
 //instCount[opcode]++;
+#endif
 
-               exec_op[opcode]();                                                              // Execute that opcode...
+               exec_op[opcode]();                                              // Execute that opcode...
                regs.clock += CPUCycles[opcode];
 #ifdef __DEBUG__
-WriteLog(" [PC=%04X, S=%04X, X=%04X, A=%02X, B=%02X, CC=%02X]\n", regs.pc, regs.s, regs.x, regs.a, regs.b, regs.cc);
+if (logGo)
+//     WriteLog(" [PC=%04X, S=%04X, X=%04X, A=%02X, B=%02X, CC=%s%s%s%s%s%s%s%s]\n", regs.pc, regs.s, regs.x, regs.a, regs.b, (regs.cc & FLAG_E ? "E" : " "), (regs.cc & FLAG_F ? "F" : " "), (regs.cc & FLAG_H ? "H" : " "), (regs.cc & FLAG_I ? "I" : " "), (regs.cc & FLAG_N ? "N" : " "), (regs.cc & FLAG_Z ? "Z" : " "), (regs.cc & FLAG_V ? "V" : " "), (regs.cc & FLAG_C ? "C" : " "));
+       WriteLog(" [PC=%04X, S=%04X, X=%04X, A=%02X, B=%02X, CC=%s%s%s%s%s%s%s%s]\n", regs.pc, regs.s, regs.x, regs.a, regs.b, (regs.cc & FLAG_E ? "E" : " "), (regs.cc & FLAG_F ? "F" : " "), (flagH ? "H" : " "), (flagI ? "I" : " "), (flagN ? "N" : " "), (flagZ ? "Z" : " "), (flagV ? "V" : " "), (flagC ? "C" : " "));
 #endif
 
                if (regs.cpuFlags & V6808_ASSERT_LINE_RESET)
                {
-                       regs.cc |= FLAG_I;                                                      // Set I
-                       regs.pc = RdMemW(0xFFFE);                                       // And load PC with the RESET vector
+#ifdef __DEBUG__
+WriteLog("*** RESET LINE ASSERTED ***\n");
+#endif
+//                     regs.cc |= FLAG_I;                                      // Set I
+                       flagI = 1;                                                      // Set I
+                       regs.pc = RdMemW(0xFFFE);                       // And load PC with the RESET vector
 
                        context->cpuFlags &= ~V6808_ASSERT_LINE_RESET;
                        regs.cpuFlags &= ~V6808_ASSERT_LINE_RESET;
                }
                else if (regs.cpuFlags & V6808_ASSERT_LINE_NMI)
                {
-                       regs.WrMem(--regs.s, regs.pc & 0xFF);           // Save all regs...
-                       regs.WrMem(--regs.s, regs.pc >> 8);
-                       regs.WrMem(--regs.s, regs.x & 0xFF);
-                       regs.WrMem(--regs.s, regs.x >> 8);
-                       regs.WrMem(--regs.s, regs.b);
-                       regs.WrMem(--regs.s, regs.a);
-                       regs.WrMem(--regs.s, regs.cc);
-                       regs.pc = RdMemW(0xFFFC);                                       // And do it!
+#ifdef __DEBUG__
+WriteLog("*** NMI LINE ASSERTED ***\n");
+#endif
+                       regs.cc = PACK_FLAGS;                           // Mash flags back into the CC register
+                       PUSH16(regs.pc);                                        // Save all regs...
+                       PUSH16(regs.x);
+                       PUSH(regs.b);
+                       PUSH(regs.a);
+                       PUSH(regs.cc);
+                       regs.pc = RdMemW(0xFFFC);                       // And do it!
 
                        regs.clock += 0;                                                        // How many???
                        context->cpuFlags &= ~V6808_ASSERT_LINE_NMI;// Reset the asserted line (NMI)...
@@ -1892,24 +2158,32 @@ WriteLog(" [PC=%04X, S=%04X, X=%04X, A=%02X, B=%02X, CC=%02X]\n", regs.pc, regs.
                }
                else if (regs.cpuFlags & V6808_ASSERT_LINE_IRQ)
                {
-                       if (!(regs.cc & FLAG_I))                                        // Process an interrupt (I=0)?
+#ifdef __DEBUG__
+WriteLog("*** IRQ LINE ASSERTED ***\n");
+#endif
+//                     if (!(regs.cc & FLAG_I))                        // Process an interrupt (I=0)?
+                       if (!flagI)                                                     // Process an interrupt (I=0)?
                        {
-                               regs.WrMem(--regs.s, regs.pc & 0xFF);   // Save all regs...
-                               regs.WrMem(--regs.s, regs.pc >> 8);
-                               regs.WrMem(--regs.s, regs.x & 0xFF);
-                               regs.WrMem(--regs.s, regs.x >> 8);
-                               regs.WrMem(--regs.s, regs.b);
-                               regs.WrMem(--regs.s, regs.a);
-                               regs.WrMem(--regs.s, regs.cc);
-                               regs.pc = RdMemW(0xFFF8);                       // And do it!
-
-                               regs.clock += 0;                                                // How many???
+#ifdef __DEBUG__
+WriteLog("    IRQ TAKEN!\n");
+logGo = true;
+#endif
+                               regs.cc = PACK_FLAGS;                   // Mash flags back into the CC register
+                               PUSH16(regs.pc);                                // Save all regs...
+                               PUSH16(regs.x);
+                               PUSH(regs.b);
+                               PUSH(regs.a);
+                               PUSH(regs.cc);
+                               regs.pc = RdMemW(0xFFF8);               // And do it!
+
+                               regs.clock += 0;                                // How many???
                                context->cpuFlags &= ~V6808_ASSERT_LINE_IRQ;    // Reset the asserted line (IRQ)...
                                regs.cpuFlags &= ~V6808_ASSERT_LINE_IRQ;        // Reset the asserted line (IRQ)...
                        }
                }
        }
 
+       regs.cc = PACK_FLAGS;                                           // Mash flags back into the CC register
        myMemcpy(context, &regs, sizeof(V6808REGS));
 }
 
index a3d6d9041efa80fb99a94c82703756195df8684f..ec19a63f9ef36ce93144a852fc85a37cac610609 100755 (executable)
@@ -3,7 +3,7 @@
 //
 // by James L. Hammons
 //
-// (c) 2004 Underground Software
+// (C) 2006 Underground Software
 //
 
 #ifndef __V6808_H__
@@ -13,9 +13,8 @@
 
 // Useful defines
 
-#define FLAG_E         0x80            // ??? Entire ???
-#define FLAG_F         0x40            // ??? Fast IRQ ???
-
+#define FLAG_E         0x80            // ??? Entire ??? [No.]
+#define FLAG_F         0x40            // ??? Fast IRQ ??? [No.]
 #define FLAG_H         0x20            // Half carry
 #define FLAG_I         0x10            // IRQ
 #define FLAG_N         0x08            // Negative
@@ -26,7 +25,7 @@
 #define V6808_ASSERT_LINE_RESET                0x0001          // v6808 RESET line
 #define V6808_ASSERT_LINE_IRQ          0x0002          // v6808 IRQ line
 #define V6808_ASSERT_LINE_NMI          0x0004          // v6808 NMI line
-#define V6808_STATE_SYNC                       0x0008          // ??? v6808 SYNC line ???
+#define V6808_STATE_WAI                                0x0008          // v6808 wait for IRQ line
 #define V6808_STATE_ILLEGAL_INST       0x0010          // Illegal instruction executed flag
 //#define V6809_START_DEBUG_LOG                0x0020          // Debug log go (temporary!)
 
@@ -41,7 +40,6 @@ struct V6808REGS
        uint8 a;                                                // 6808 A register
        uint8 b;                                                // 6808 B register
        uint32 clock;                                   // 6808 clock
-//uint32 _reserved;//  uint8 (* Fetch)(uint16&);               // Address of uint8 fetch routine
        uint8 (* RdMem)(uint16);                // Address of uint8 read routine
        void (* WrMem)(uint16, uint8);  // Address of uint8 write routine
        uint32 cpuFlags;                                // v6808 IRQ/RESET flags
@@ -49,7 +47,8 @@ struct V6808REGS
 
 // Function prototypes
 
-void Execute6808(V6808REGS *, uint32);    // Function to execute 6808 instructions
+void Execute6808(V6808REGS *, uint32); // Function to execute 6808 instructions
 uint32 GetCurrentV6808Clock(void);             // Get the clock of the currently executing CPU
+//uint8 GetCCRegister(void);                           // Hmm.
 
 #endif // __V6808_H__
index 494b9f11abf117e749b37ab0c8204882fa5918f8..648d02b8d2f15ee5632cb545edc1c0e762add828 100755 (executable)
 // ---  ----------  ------------------------------------------------------------
 // JLH  06/15/2006  Added changelog ;-)
 // JLH  06/15/2006  Scrubbed all BYTE, WORD & DWORD references from the code
+// JLH  11/11/2006  Removed all SignedX() references
 //
 
 // Mebbe someday I'll get around to fixing the core to be more like V65C02...
+// We have a start... ;-)
 //
 
+#define __DEBUG__
+
 #include "v6809.h"
 
 #ifdef __DEBUG__
 #include "log.h"               // Temporary...
 #endif
 
+// Various macros
+
+#define CLR_Z                          (regs.cc &= ~FLAG_Z)
+#define CLR_ZN                         (regs.cc &= ~(FLAG_Z | FLAG_N))
+#define CLR_ZNC                                (regs.cc &= ~(FLAG_Z | FLAG_N | FLAG_C))
+#define CLR_V                          (regs.cc &= ~FLAG_V)
+#define CLR_N                          (regs.cc &= ~FLAG_N)
+#define SET_Z(r)                       (regs.cc = ((r) == 0 ? regs.cc | FLAG_Z : regs.cc & ~FLAG_Z))
+#define SET_N(r)                       (regs.cc = ((r) & 0x80 ? regs.cc | FLAG_N : regs.cc & ~FLAG_N))
+
+//Not sure that this code is computing the carry correctly... Investigate! [Seems to be]
+#define SET_C_ADD(a,b)         (regs.cc = ((uint8)(b) > (uint8)(~(a)) ? regs.cc | FLAG_C : regs.cc & ~FLAG_C))
+//#define SET_C_SUB(a,b)               (regs.cc = ((uint8)(b) >= (uint8)(a) ? regs.cc | FLAG_C : regs.cc & ~FLAG_C))
+#define SET_C_CMP(a,b)         (regs.cc = ((uint8)(b) >= (uint8)(a) ? regs.cc | FLAG_C : regs.cc & ~FLAG_C))
+#define SET_ZN(r)                      SET_N(r); SET_Z(r)
+#define SET_ZNC_ADD(a,b,r)     SET_N(r); SET_Z(r); SET_C_ADD(a,b)
+//#define SET_ZNC_SUB(a,b,r)   SET_N(r); SET_Z(r); SET_C_SUB(a,b)
+#define SET_ZNC_CMP(a,b,r)     SET_N(r); SET_Z(r); SET_C_CMP(a,b)
+
+//Small problem with the EA_ macros: ABS macros don't increment the PC!!! !!! FIX !!!
+#define EA_IMM                         regs.pc++
+#define EA_ZP                          regs.RdMem(regs.pc++)
+#define EA_ZP_X                                (regs.RdMem(regs.pc++) + regs.x) & 0xFF
+#define EA_ZP_Y                                (regs.RdMem(regs.pc++) + regs.y) & 0xFF
+#define EA_ABS                         RdMemW(regs.pc)
+#define EA_ABS_X                       RdMemW(regs.pc) + regs.x
+#define EA_ABS_Y                       RdMemW(regs.pc) + regs.y
+#define EA_IND_ZP_X                    RdMemW((regs.RdMem(regs.pc++) + regs.x) & 0xFF)
+#define EA_IND_ZP_Y                    RdMemW(regs.RdMem(regs.pc++)) + regs.y
+#define EA_IND_ZP                      RdMemW(regs.RdMem(regs.pc++))
+
+#define READ_IMM                       regs.RdMem(EA_IMM)
+#define READ_ZP                                regs.RdMem(EA_ZP)
+#define READ_ZP_X                      regs.RdMem(EA_ZP_X)
+#define READ_ZP_Y                      regs.RdMem(EA_ZP_Y)
+#define READ_ABS                       regs.RdMem(EA_ABS);     regs.pc += 2
+#define READ_ABS_X                     regs.RdMem(EA_ABS_X);   regs.pc += 2
+#define READ_ABS_Y                     regs.RdMem(EA_ABS_Y);   regs.pc += 2
+#define READ_IND_ZP_X          regs.RdMem(EA_IND_ZP_X)
+#define READ_IND_ZP_Y          regs.RdMem(EA_IND_ZP_Y)
+#define READ_IND_ZP                    regs.RdMem(EA_IND_ZP)
+
+#define READ_IMM_WB(v)         uint16 addr = EA_IMM;      v = regs.RdMem(addr)
+#define READ_ZP_WB(v)          uint16 addr = EA_ZP;       v = regs.RdMem(addr)
+#define READ_ZP_X_WB(v)                uint16 addr = EA_ZP_X;     v = regs.RdMem(addr)
+#define READ_ABS_WB(v)         uint16 addr = EA_ABS;      v = regs.RdMem(addr); regs.pc += 2
+#define READ_ABS_X_WB(v)       uint16 addr = EA_ABS_X;    v = regs.RdMem(addr); regs.pc += 2
+#define READ_ABS_Y_WB(v)       uint16 addr = EA_ABS_Y;    v = regs.RdMem(addr); regs.pc += 2
+#define READ_IND_ZP_X_WB(v)    uint16 addr = EA_IND_ZP_X; v = regs.RdMem(addr)
+#define READ_IND_ZP_Y_WB(v)    uint16 addr = EA_IND_ZP_Y; v = regs.RdMem(addr)
+#define READ_IND_ZP_WB(v)      uint16 addr = EA_IND_ZP;   v = regs.RdMem(addr)
+
+#define WRITE_BACK(d)          regs.WrMem(addr, (d))
+
 // Private global variables
 
 static V6809REGS regs;
+//Let's see if we can nuke this shit.
 static uint16 addr;                                                            // Temporary variables common to all funcs...
 static uint8 tmp;
 
 // Private function prototypes
 
-static int SignedB(uint8);                                             // Return signed byte from unsigned
-static int SignedW(uint16);                                            // Return signed word from unsigned
 static uint16 FetchW(void);
 static uint16 RdMemW(uint16 addr);
 static void WrMemW(uint16 addr, uint16 w);
@@ -186,22 +243,6 @@ void WrMemW(uint16 addr, uint16 w)
        regs.WrMem(addr + 1, w & 0xFF);
 }
 
-//
-// return signed byte from unsigned
-//
-int SignedB(uint8 b)
-{
-       return (b & 0x80 ? b - 256 : b);
-}
-
-//
-// return signed word from unsigned
-//
-int SignedW(uint16 w)
-{
-       return (w & 0x8000 ? w - 65536 : w);
-}
-
 //
 // Function to read TFR/EXG post byte
 //
@@ -343,31 +384,38 @@ uint16 DecodeIDX(uint8 code)
                                addr = RdMemW(woff);
                                break;
                        case 5:
-                               woff = DecodeReg(reg) + SignedB(regs.b);
+//                             woff = DecodeReg(reg) + SignedB(regs.b);
+                               woff = DecodeReg(reg) + (int16)(int8)regs.b;
                                addr = RdMemW(woff);
                                break;
                        case 6:
-                               woff = DecodeReg(reg) + SignedB(regs.a);
+//                             woff = DecodeReg(reg) + SignedB(regs.a);
+                               woff = DecodeReg(reg) + (int16)(int8)regs.a;
                                addr = RdMemW(woff);
                                break;
                        case 8:
-                               woff = DecodeReg(reg) + SignedB(regs.RdMem(regs.pc++));
+//                             woff = DecodeReg(reg) + SignedB(regs.RdMem(regs.pc++));
+                               woff = DecodeReg(reg) + (int16)(int8)regs.RdMem(regs.pc++);
                                addr = RdMemW(woff);
                                break;
                        case 9:
-                               woff = DecodeReg(reg) + SignedW(FetchW());
+//                             woff = DecodeReg(reg) + SignedW(FetchW());
+                               woff = DecodeReg(reg) + FetchW();
                                addr = RdMemW(woff);
                                break;
                        case 11:
-                               woff = DecodeReg(reg) + SignedW((regs.a << 8) | regs.b);
+//                             woff = DecodeReg(reg) + SignedW((regs.a << 8) | regs.b);
+                               woff = DecodeReg(reg) + ((regs.a << 8) | regs.b);
                                addr = RdMemW(woff);
                                break;
                        case 12:
-                               woff = regs.pc + SignedB(regs.RdMem(regs.pc++));
+//                             woff = regs.pc + SignedB(regs.RdMem(regs.pc++));
+                               woff = regs.pc + (int16)(int8)regs.RdMem(regs.pc++);
                                addr = RdMemW(woff);
                                break;
                        case 13:
-                               woff = regs.pc + SignedW(FetchW());
+//                             woff = regs.pc + SignedW(FetchW());
+                               woff = regs.pc + FetchW();
                                addr = RdMemW(woff);
                                break;
                        case 15:
@@ -417,13 +465,20 @@ uint16 DecodeIDX(uint8 code)
                    }
                    addr = DecodeReg(reg);  break; }
         case 4:  { addr = DecodeReg(reg);  break; }
-        case 5:  { addr = DecodeReg(reg) + SignedB(regs.b);  break; }
-        case 6:  { addr = DecodeReg(reg) + SignedB(regs.a);  break; }
-        case 8:  { addr = DecodeReg(reg) + SignedB(regs.RdMem(regs.pc++));  break; }
-        case 9:  { addr = DecodeReg(reg) + SignedW(FetchW());  break; }
-        case 11: { addr = DecodeReg(reg) + SignedW((regs.a << 8) | regs.b);  break; }
-        case 12: { addr = regs.pc + SignedB(regs.RdMem(regs.pc++));  break; }
-        case 13: { addr = regs.pc + SignedW(FetchW());  break; }
+//        case 5:  { addr = DecodeReg(reg) + SignedB(regs.b);  break; }
+        case 5:  { addr = DecodeReg(reg) + (int16)(int8)regs.b;  break; }
+//        case 6:  { addr = DecodeReg(reg) + SignedB(regs.a);  break; }
+        case 6:  { addr = DecodeReg(reg) + (int16)(int8)regs.a;  break; }
+//        case 8:  { addr = DecodeReg(reg) + SignedB(regs.RdMem(regs.pc++));  break; }
+        case 8:  { addr = DecodeReg(reg) + (int16)(int8)regs.RdMem(regs.pc++);  break; }
+//        case 9:  { addr = DecodeReg(reg) + SignedW(FetchW());  break; }
+        case 9:  { addr = DecodeReg(reg) + FetchW();  break; }
+//        case 11: { addr = DecodeReg(reg) + SignedW((regs.a << 8) | regs.b);  break; }
+        case 11: { addr = DecodeReg(reg) + ((regs.a << 8) | regs.b);  break; }
+//        case 12: { addr = regs.pc + SignedB(regs.RdMem(regs.pc++));  break; }
+        case 12: { addr = regs.pc + (int16)(int8)regs.RdMem(regs.pc++);  break; }
+//        case 13: { addr = regs.pc + SignedW(FetchW());  break; }
+        case 13: { addr = regs.pc + FetchW();  break; }
                        }
                }
        }
@@ -565,32 +620,41 @@ static void Op10(void)                                                                                    // Page 1 opcode
        exec_op1[regs.RdMem(regs.pc++)]();
 }
 
-static void Op11(void)                                                                                 // Page 2 opcode
+static void Op11(void)                                                 // Page 2 opcode
 {
        exec_op2[regs.RdMem(regs.pc++)]();
 }
 
-static void Op12(void)                                                                                 // NOP
+static void Op12(void)                                                 // NOP
 {
        regs.clock += 2;
 }
 
-static void Op13(void)  // SYNC
-{ 
-  regs.clock += 2;
+static void Op13(void)                                                 // SYNC
+{
+       // Fix this so it does the right thing (software interrupt!)
+       regs.clock += 2;
 }
-static void Op16(void)  // LBRA
+
+static void Op16(void)                                                 // LBRA
 {
-  regs.pc += SignedW(FetchW());
-  regs.clock += 5;
+//     regs.pc += SignedW(FetchW());
+       regs.pc += FetchW();                                            // No need to make signed, both are 16 bit quantities
+
+       regs.clock += 5;
 }
-static void Op17(void)  // LBSR
+
+static void Op17(void)                                                 // LBSR
 {
-  addr = FetchW();
-  regs.WrMem(--regs.s, regs.pc&0xFF);  regs.WrMem(--regs.s, regs.pc>>8);
-  regs.pc += SignedW(addr);
-  regs.clock += 9;
+       uint16 word = FetchW();
+       regs.WrMem(--regs.s, regs.pc & 0xFF);
+       regs.WrMem(--regs.s, regs.pc >> 8);
+//     regs.pc += SignedW(addr);
+       regs.pc += word;                                                        // No need to make signed, both are 16 bit
+
+       regs.clock += 9;
 }
+
 static void Op19(void)  // DAA
 {
   if ((regs.cc&0x20) || ((regs.a&0x0F) > 0x09))    // H set or lo nyb too big?
@@ -621,7 +685,7 @@ static void Op1C(void)                                                                      // ANDCC #
        regs.clock += 3;
 }
 
-static void Op1D(void)                                                                 // SEX
+static void Op1D(void)                                                 // SEX
 {
        (regs.b & 0x80 ? regs.a = 0xFF : regs.a = 0x00);
 
@@ -631,7 +695,7 @@ static void Op1D(void)                                                                      // SEX
        regs.clock += 2;
 }
 
-static void Op1E(void)                                                                 // EXG
+static void Op1E(void)                                                 // EXG
 {
        tmp = regs.RdMem(regs.pc++);
        addr = ReadEXG(tmp >> 4);
@@ -647,100 +711,162 @@ static void Op1F(void)  // TFR
   WriteEXG(tmp&0xF, ReadEXG(tmp>>4));
   regs.clock += 7;
 }
-static void Op20(void)  // BRA
+
+static void Op20(void)                                                 // BRA
 {
-  regs.pc += SignedB(regs.RdMem(regs.pc++));  // Branch always
-  regs.clock += 3;
+//     regs.pc += SignedB(regs.RdMem(regs.pc++));  // Branch always
+       regs.pc += (int16)(int8)regs.RdMem(regs.pc) + 1;        // Branch always
+
+       regs.clock += 3;
 }
-static void Op21(void)  // BRN
+
+static void Op21(void)                                                 // BRN
 {
-  regs.RdMem(regs.pc++);
-  regs.clock += 3;
+       regs.RdMem(regs.pc++);
+
+       regs.clock += 3;
 }
-static void Op22(void)  // BHI
+
+static void Op22(void)                                                 // BHI
 {
-  tmp = regs.RdMem(regs.pc++);
-  if (!(regs.cc&0x05))  regs.pc += SignedB(tmp);
-  regs.clock += 3;
+       uint16 word = (int16)(int8)regs.RdMem(regs.pc++);
+
+       if (!(regs.cc & 0x05))
+               regs.pc += word;
+
+       regs.clock += 3;
 }
-static void Op23(void)  // BLS
+
+static void Op23(void)                                                 // BLS
 {
-  tmp = regs.RdMem(regs.pc++);
-  if (regs.cc&0x05)  regs.pc += SignedB(tmp);
-  regs.clock += 3;
+       uint16 word = (int16)(int8)regs.RdMem(regs.pc++);
+
+       if (regs.cc & 0x05)
+               regs.pc += word;
+
+       regs.clock += 3;
 }
-static void Op24(void)  // BCC (BHS)
+
+static void Op24(void)                                                 // BCC (BHS)
 {
-  tmp = regs.RdMem(regs.pc++);
-  if (!(regs.cc&0x01))  regs.pc += SignedB(tmp);
-  regs.clock += 3;
+       uint16 word = (int16)(int8)regs.RdMem(regs.pc++);
+
+       if (!(regs.cc & 0x01))
+               regs.pc += word;
+
+       regs.clock += 3;
 }
-static void Op25(void)  // BCS (BLO)
+
+static void Op25(void)                                                 // BCS (BLO)
 {
-  tmp = regs.RdMem(regs.pc++);
-  if (regs.cc&0x01)  regs.pc += SignedB(tmp);
-  regs.clock += 3;
+       uint16 word = (int16)(int8)regs.RdMem(regs.pc++);
+
+       if (regs.cc & 0x01)
+               regs.pc += word;
+
+       regs.clock += 3;
 }
-static void Op26(void)  // BNE
+
+static void Op26(void)                                                 // BNE
 {
-  tmp = regs.RdMem(regs.pc++);
-  if (!(regs.cc&0x04))  regs.pc += SignedB(tmp);
-  regs.clock += 3;
+       uint16 word = (int16)(int8)regs.RdMem(regs.pc++);
+
+       if (!(regs.cc & 0x04))
+               regs.pc += word;
+
+       regs.clock += 3;
 }
-static void Op27(void)  // BEQ
+
+static void Op27(void)                                                 // BEQ
 {
-  tmp = regs.RdMem(regs.pc++);
-  if (regs.cc&0x04)  regs.pc += SignedB(tmp);
-  regs.clock += 3;
+       uint16 word = (int16)(int8)regs.RdMem(regs.pc++);
+
+       if (regs.cc & 0x04)
+               regs.pc += word;
+
+       regs.clock += 3;
 }
-static void Op28(void)  // BVC
+
+static void Op28(void)                                                 // BVC
 {
-  tmp = regs.RdMem(regs.pc++);
-  if (!(regs.cc&0x02))  regs.pc += SignedB(tmp);
-  regs.clock += 3;
+       uint16 word = (int16)(int8)regs.RdMem(regs.pc++);
+
+       if (!(regs.cc & 0x02))
+               regs.pc += word;
+
+       regs.clock += 3;
 }
-static void Op29(void)  // BVS
+
+static void Op29(void)                                                 // BVS
 {
-  tmp = regs.RdMem(regs.pc++);
-  if (regs.cc&0x02)  regs.pc += SignedB(tmp);
-  regs.clock += 3;
+       uint16 word = (int16)(int8)regs.RdMem(regs.pc++);
+
+       if (regs.cc & 0x02)
+               regs.pc += word;
+
+       regs.clock += 3;
 }
-static void Op2A(void)  // BPL
+
+static void Op2A(void)                                                 // BPL
 {
-  tmp = regs.RdMem(regs.pc++);
-  if (!(regs.cc&0x08))  regs.pc += SignedB(tmp);
-  regs.clock += 3;
+       uint16 word = (int16)(int8)regs.RdMem(regs.pc++);
+
+       if (!(regs.cc & 0x08))
+               regs.pc += word;
+
+       regs.clock += 3;
 }
-static void Op2B(void)  // BMI
+
+static void Op2B(void)                                                 // BMI
 {
-  tmp = regs.RdMem(regs.pc++);
-  if (regs.cc&0x08)  regs.pc += SignedB(tmp);
-  regs.clock += 3;
+       uint16 word = (int16)(int8)regs.RdMem(regs.pc++);
+
+       if (regs.cc & 0x08)
+               regs.pc += word;
+
+       regs.clock += 3;
 }
-static void Op2C(void)  // BGE
+
+static void Op2C(void)                                                 // BGE
 {
-  tmp = regs.RdMem(regs.pc++);
-  if (!(((regs.cc&0x08) >> 2) ^ (regs.cc&0x02)))  regs.pc += SignedB(tmp);
-  regs.clock += 3;
+       uint16 word = (int16)(int8)regs.RdMem(regs.pc++);
+
+       if (!(((regs.cc & 0x08) >> 2) ^ (regs.cc & 0x02)))
+               regs.pc += word;
+
+       regs.clock += 3;
 }
-static void Op2D(void)  // BLT
+
+static void Op2D(void)                                                 // BLT
 {
-  tmp = regs.RdMem(regs.pc++);
-  if (((regs.cc&0x08) >> 2) ^ (regs.cc&0x02))  regs.pc += SignedB(tmp);
-  regs.clock += 3;
+       uint16 word = (int16)(int8)regs.RdMem(regs.pc++);
+
+       if (((regs.cc & 0x08) >> 2) ^ (regs.cc & 0x02))
+               regs.pc += word;
+
+       regs.clock += 3;
 }
-static void Op2E(void)  // BGT
+
+static void Op2E(void)                                                 // BGT
 {
-  tmp = regs.RdMem(regs.pc++);
-  if (!((regs.cc&0x04) | (((regs.cc&0x08) >> 2) ^ (regs.cc&0x02))))  regs.pc += SignedB(tmp);
-  regs.clock += 3;
+       uint16 word = (int16)(int8)regs.RdMem(regs.pc++);
+
+       if (!((regs.cc & 0x04) | (((regs.cc & 0x08) >> 2) ^ (regs.cc & 0x02))))
+               regs.pc += word;
+
+       regs.clock += 3;
 }
-static void Op2F(void)  // BLE
+
+static void Op2F(void)                                                 // BLE
 {
-  tmp = regs.RdMem(regs.pc++);
-  if ((regs.cc&0x04) | (((regs.cc&0x08) >> 2) ^ (regs.cc&0x02)))  regs.pc += SignedB(tmp);
-  regs.clock += 3;
+       uint16 word = (int16)(int8)regs.RdMem(regs.pc++);
+
+       if ((regs.cc & 0x04) | (((regs.cc & 0x08) >> 2) ^ (regs.cc & 0x02)))
+               regs.pc += word;
+
+       regs.clock += 3;
 }
+
 static void Op30(void)  // LEAX
 {
   regs.x = DecodeIDX(regs.RdMem(regs.pc++));
@@ -1394,13 +1520,17 @@ static void Op8C(void)  // CMPX #
         (dw&0x8000 ? regs.cc |= 0x08 : regs.cc &= 0xF7);  // Adjust Negative flag
         regs.clock += 4;
 }
-static void Op8D(void)  // Bregs.s
-      {
-        tmp = regs.RdMem(regs.pc++);
-        regs.WrMem(--regs.s, regs.pc&0xFF);  regs.WrMem(--regs.s, regs.pc>>8);
-        regs.pc += SignedB(tmp);
-        regs.clock += 7;
-      }
+
+static void Op8D(void)                                                 // Bregs.s
+{
+       uint16 word = (int16)(int8)regs.RdMem(regs.pc++);
+       regs.WrMem(--regs.s, regs.pc & 0xFF);
+       regs.WrMem(--regs.s, regs.pc >> 8);
+       regs.pc += word;
+
+       regs.clock += 7;
+}
+
 static void Op8E(void)  // LDX #
       {
         regs.x = FetchW();
@@ -2445,95 +2575,153 @@ static void OpFF(void)  // STU ABS
 // Page one opcodes' execute code
 //
 
-static void Op1021(void)  // LBRN
+static void Op1021(void)                                               // LBRN
 {
-  addr = FetchW();
-  regs.clock += 5;
+       addr = FetchW();
+
+       regs.clock += 5;
 }
-static void Op1022(void)  // LBHI
+
+static void Op1022(void)                                               // LBHI
 {
-  addr = FetchW();
-  if (!((regs.cc&0x01)|(regs.cc&0x04)))  regs.pc += SignedW(addr);
-  regs.clock += 5;
+       uint16 word = FetchW();
+
+       if (!((regs.cc & 0x01) | (regs.cc & 0x04)))
+               regs.pc += word;
+
+       regs.clock += 5;
 }
-static void Op1023(void)  // LBLS
+
+static void Op1023(void)                                               // LBLS
 {
-  addr = FetchW();
-  if ((regs.cc&0x01)|(regs.cc&0x04))  regs.pc += SignedW(addr);
-  regs.clock += 5;
+       uint16 word = FetchW();
+
+       if ((regs.cc & 0x01) | (regs.cc & 0x04))
+               regs.pc += word;
+
+       regs.clock += 5;
 }
-static void Op1024(void)  // LBCC (LBHS)
+
+static void Op1024(void)                                               // LBCC (LBHS)
 {
-  addr = FetchW();
-  if (!(regs.cc&0x01))  regs.pc += SignedW(addr);
-  regs.clock += 5;
+       uint16 word = FetchW();
+
+       if (!(regs.cc & 0x01))
+               regs.pc += word;
+
+       regs.clock += 5;
 }
-static void Op1025(void)  // LBCS (LBLO)
+
+static void Op1025(void)                                               // LBCS (LBLO)
 {
-  addr = FetchW();
-  if (regs.cc&0x01)  regs.pc += SignedW(addr);
-  regs.clock += 5;
+       uint16 word = FetchW();
+
+       if (regs.cc & 0x01)
+               regs.pc += word;
+
+       regs.clock += 5;
 }
-static void Op1026(void)  // LBNE
+
+static void Op1026(void)                                               // LBNE
 {
-  addr = FetchW();
-  if (!(regs.cc&0x04))  regs.pc += SignedW(addr);
-  regs.clock += 5;
+       uint16 word = FetchW();
+
+       if (!(regs.cc & 0x04))
+               regs.pc += word;
+
+       regs.clock += 5;
 }
-static void Op1027(void)  // LBEQ
+
+static void Op1027(void)                                               // LBEQ
 {
-  addr = FetchW();
-  if (regs.cc&0x04)  regs.pc += SignedW(addr);
-  regs.clock += 5;
+       uint16 word = FetchW();
+
+       if (regs.cc & 0x04)
+               regs.pc += word;
+
+       regs.clock += 5;
 }
-static void Op1028(void)  // LBVC
+
+static void Op1028(void)                                               // LBVC
 {
-  addr = FetchW();
-  if (!(regs.cc&0x02))  regs.pc += SignedW(addr);
-  regs.clock += 5;
+       uint16 word = FetchW();
+
+       if (!(regs.cc & 0x02))
+               regs.pc += word;
+
+       regs.clock += 5;
 }
-static void Op1029(void)  // LBVS
+
+static void Op1029(void)                                               // LBVS
 {
-  addr = FetchW();
-  if (regs.cc&0x02)  regs.pc += SignedW(addr);
-  regs.clock += 5;
+       uint16 word = FetchW();
+
+       if (regs.cc & 0x02)
+               regs.pc += word;
+
+       regs.clock += 5;
 }
-static void Op102A(void)  // LBPL
+
+static void Op102A(void)                                               // LBPL
 {
-  addr = FetchW();
-  if (!(regs.cc&0x08))  regs.pc += SignedW(addr);
-  regs.clock += 5;
+       uint16 word = FetchW();
+
+       if (!(regs.cc & 0x08))
+               regs.pc += word;
+
+       regs.clock += 5;
 }
-static void Op102B(void)  // LBMI
+
+static void Op102B(void)                                               // LBMI
 {
-  addr = FetchW();
-  if (regs.cc&0x08)  regs.pc += SignedW(addr);
-  regs.clock += 5;
+       uint16 word = FetchW();
+
+       if (regs.cc & 0x08)
+               regs.pc += word;
+
+       regs.clock += 5;
 }
-static void Op102C(void)  // LBGE
+
+static void Op102C(void)                                               // LBGE
 {
-  addr = FetchW();
-  if (!(((regs.cc&0x08) >> 2) ^ (regs.cc&0x02)))  regs.pc += SignedW(addr);
-  regs.clock += 5;
+       uint16 word = FetchW();
+
+       if (!(((regs.cc & 0x08) >> 2) ^ (regs.cc & 0x02)))
+               regs.pc += word;
+
+       regs.clock += 5;
 }
-static void Op102D(void)  // LBLT
+
+static void Op102D(void)                                               // LBLT
 {
-  addr = FetchW();
-  if (((regs.cc&0x08) >> 2) ^ (regs.cc&0x02))  regs.pc += SignedW(addr);
-  regs.clock += 5;
+       uint16 word = FetchW();
+
+       if (((regs.cc & 0x08) >> 2) ^ (regs.cc & 0x02))
+               regs.pc += word;
+
+       regs.clock += 5;
 }
-static void Op102E(void)  // LBGT
+
+static void Op102E(void)                                               // LBGT
 {
-  addr = FetchW();
-  if (!((regs.cc&0x04) | (((regs.cc&0x08) >> 2) ^ (regs.cc&0x02))))  regs.pc += SignedW(addr);
-  regs.clock += 5;
+       uint16 word = FetchW();
+
+       if (!((regs.cc & 0x04) | (((regs.cc & 0x08) >> 2) ^ (regs.cc & 0x02))))
+               regs.pc += word;
+
+       regs.clock += 5;
 }
-static void Op102F(void)  // LBLE
+
+static void Op102F(void)                                               // LBLE
 {
-  addr = FetchW();
-  if ((regs.cc&0x04) | (((regs.cc&0x08) >> 2) ^ (regs.cc&0x02))) regs.pc += SignedW(addr);
-  regs.clock += 5;
+       uint16 word = FetchW();
+
+       if ((regs.cc & 0x04) | (((regs.cc & 0x08) >> 2) ^ (regs.cc & 0x02)))
+               regs.pc += word;
+
+       regs.clock += 5;
 }
+
 static void Op103F(void)  // SWI2 (Not yet implemented)
 {
   regs.clock += 20;
@@ -2846,20 +3034,24 @@ static void Op11BC(void)  // CMPS ABS
 }
 
 //temp, for testing...
-/*static uint8 backTrace[256];
+#ifdef __DEBUG__
+static uint8 backTrace[256];
 static uint16 btPC[256];
 static int btPtr = 0;//*/
+#endif
 static void Op__(void)                                                                 // Illegal opcode
 {
        regs.clock++;
 //     illegal = true;
        regs.cpuFlags |= V6809_STATE_ILLEGAL_INST;
+#ifdef __DEBUG__
 /*WriteLog("V6809: Executed illegal opcode %02X at PC=%04X...\n\nBacktrace:\n\n", regs.RdMem(regs.pc - 1), regs.pc - 1);
 for(int i=0; i<256; i++)
 {
-       dpc = btPC[(btPtr+i)&0xFF];
-       Decode_6809();
+       Decode6809(btPC[(btPtr + i) & 0xFF]);
+       WriteLog("\n");
 }//*/
+#endif
 }
 
 
@@ -2884,15 +3076,20 @@ void Execute6809(V6809REGS * context, uint32 cycles)
        // Execute here...
        while (regs.clock < cycles)
        {
-/*static bool disasm = false;
-if (regs.pc == 0x15BA) disasm = true;
-if (disasm) { dpc = regs.pc; Decode_6809(); }
-if (regs.pc == 0x164A) disasm = false;//*/
+#ifdef __DEBUG__
+//Decode6809(regs.pc);
+static bool disasm = false;
+/*//if (regs.pc == 0x15BA)     disasm = true;
+//if (regs.pc == 0xFE76)       disasm = true;
+if (regs.x == 0xFED4)  disasm = true;
+if (disasm) Decode6809(regs.pc);
+//if (regs.pc == 0x164A)       disasm = false;//*/
 
 //temp, for testing...
 /*backTrace[btPtr] = regs.RdMem(regs.pc);
 btPC[btPtr] = regs.pc;
-btPtr = (btPtr++) & 0xFF;//*/
+btPtr = (btPtr + 1) & 0xFF;//*/
+#endif
                exec_op0[regs.RdMem(regs.pc++)]();
 
                // Handle any pending interrupts
@@ -2901,6 +3098,9 @@ btPtr = (btPtr++) & 0xFF;//*/
 
                if (flags & V6809_ASSERT_LINE_RESET)                    // *** RESET handler ***
                {
+#ifdef __DEBUG__
+if (disasm) WriteLog("\nV6809: RESET line asserted!\n");
+#endif
                        regs.cc |= (FLAG_F | FLAG_I);                           // Set F, I
                        regs.dp = 0;                                                            // Reset direct page register
                        regs.pc = RdMemW(0xFFFE);                                       // And load PC with the RESET vector
@@ -2909,6 +3109,9 @@ btPtr = (btPtr++) & 0xFF;//*/
                }
                else if (flags & V6809_ASSERT_LINE_NMI)                 // *** NMI handler ***
                {
+#ifdef __DEBUG__
+if (disasm) WriteLog("\nV6809: NMI line asserted!\n");
+#endif
                        regs.cc |= FLAG_E;                                                      // Set the Entire flag
 
                        regs.WrMem(--regs.s, regs.pc & 0xFF);           // Save all regs...
@@ -2932,8 +3135,14 @@ btPtr = (btPtr++) & 0xFF;//*/
                }
                else if (flags & V6809_ASSERT_LINE_FIRQ)                // *** FIRQ handler ***
                {
+#ifdef __DEBUG__
+if (disasm) WriteLog("\nV6809: FIRQ line asserted!\n");
+#endif
                        if (!(regs.cc & FLAG_F))                                        // Is the FIRQ masked (F == 1)?
                        {
+#ifdef __DEBUG__
+if (disasm) WriteLog("       FIRQ taken...\n");
+#endif
                                regs.cc &= ~FLAG_E;                                             // Clear the Entire flag
 
                                regs.WrMem(--regs.s, regs.pc & 0xFF);   // Save PC, CC regs...
@@ -2949,8 +3158,14 @@ btPtr = (btPtr++) & 0xFF;//*/
                }
                else if (flags & V6809_ASSERT_LINE_IRQ)                 // *** IRQ handler ***
                {
+#ifdef __DEBUG__
+if (disasm) WriteLog("\nV6809: IRQ line asserted!\n");
+#endif
                        if (!(regs.cc & FLAG_I))                                        // Is the IRQ masked (I == 1)?
                        {
+#ifdef __DEBUG__
+if (disasm) WriteLog("       IRQ taken...\n");
+#endif
                                regs.cc |= FLAG_E;                                              // Set the Entire flag
 
                                regs.WrMem(--regs.s, regs.pc & 0xFF);   // Save all regs...
@@ -2973,8 +3188,12 @@ btPtr = (btPtr++) & 0xFF;//*/
                                regs.cpuFlags &= ~V6809_ASSERT_LINE_IRQ;        // Reset the asserted line (IRQ)...
                        }
                }
-/*if (disasm) WriteLog("\tA=%02X B=%02X CC=%02X DP=%02X X=%04X Y=%04X S=%04X U=%04X PC=%04X\n",
+#ifdef __DEBUG__
+if (disasm) WriteLog("\tA=%02X B=%02X CC=%02X DP=%02X X=%04X Y=%04X S=%04X U=%04X PC=%04X\n",
+       regs.a, regs.b, regs.cc, regs.dp, regs.x, regs.y, regs.s, regs.u, regs.pc);//*/
+/*WriteLog("\tA=%02X B=%02X CC=%02X DP=%02X X=%04X Y=%04X S=%04X U=%04X PC=%04X\n",
        regs.a, regs.b, regs.cc, regs.dp, regs.x, regs.y, regs.s, regs.u, regs.pc);//*/
+#endif
        }
 
        myMemcpy(context, &regs, sizeof(V6809REGS));
index 5a54fe68f4d415f744dcaecfcaef9f5e0308f0cf..a34c1d1f1d974db8675b6a88e2a8b37766a0dd79 100755 (executable)
 
 struct V6809REGS
 {
-       uint16 pc;                                      // 6809 PC register
+       uint16 pc;                                              // 6809 PC register
        uint16 x;                                               // 6809 X index register
        uint16 y;                                               // 6809 Y index register
        uint16 s;                                               // 6809 System stack pointer
        uint16 u;                                               // 6809 User stack pointer
-       uint8 cc;                                       // 6809 Condition Code register
+       uint8 cc;                                               // 6809 Condition Code register
        uint8 a;                                                // 6809 A register
        uint8 b;                                                // 6809 B register
-       uint8 dp;                                       // 6809 Direct Page register
-       uint32 clock;                           // 6809 clock
+       uint8 dp;                                               // 6809 Direct Page register
+       uint32 clock;                                   // 6809 clock
 //uint32 _reserved;//  uint8 (* Fetch)(uint16&);               // Address of uint8 fetch routine
        uint8 (* RdMem)(uint16);                // Address of uint8 read routine
        void (* WrMem)(uint16, uint8);  // Address of uint8 write routine
index fe552b9fc7692801276ae78c7591140165c60718..e3ad1b7abeab38f16632511d209560eb864c7406 100755 (executable)
@@ -61,7 +61,7 @@ bool InitVideo(void)
 
        if (settings.useOpenGL)
        {
-               mainSurfaceFlags = SDL_HWSURFACE | SDL_HWPALETTE | SDL_OPENGL;
+               mainSurfaceFlags = SDL_HWSURFACE | SDL_HWPALETTE | SDL_DOUBLEBUF | SDL_OPENGL;
                SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
 //We want 32BPP, so force the issue...
                SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
@@ -103,8 +103,7 @@ bool InitVideo(void)
        SDL_WM_SetCaption("StarGem2", "StarGem2");
 
        // Create the secondary SDL display (32 BPP) that we use directly
-       surface = SDL_CreateRGBSurface(SDL_SWSURFACE, VIRTUAL_SCREEN_WIDTH, VIRTUAL_SCREEN_HEIGHT, 32,
-               MASK_R, MASK_G, MASK_B, MASK_A);
+       surface = SDL_CreateRGBSurface(SDL_SWSURFACE, VIRTUAL_SCREEN_WIDTH, VIRTUAL_SCREEN_HEIGHT, 32, MASK_R, MASK_G, MASK_B, MASK_A);
 /*WriteLog("Video: Created secondary surface with attributes:\n\n");
 WriteLog("\tWidth, height: %u x %u\n", surface->w, surface->h);
 WriteLog("\t        Pitch: %u\n", surface->pitch);
index 76daeb416b530abe3774fe9d32f8d9aaf9ef04f5..2362adc6a59f41d7829910d0ab7552df3a9ba6b3 100755 (executable)
@@ -18,7 +18,7 @@ autoSaveState = 1
 
 # OpenGL options: 1 - use OpenGL rendering, 0 - use old style rendering
 
-useOpenGL = 0
+useOpenGL = 1
 
 # OpenGL filtering type: 1 - blurry, 0 - sharp