]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
3200b7
authorToni Wilen <twilen@winuae.net>
Wed, 12 Aug 2015 17:21:24 +0000 (20:21 +0300)
committerToni Wilen <twilen@winuae.net>
Wed, 12 Aug 2015 17:21:24 +0000 (20:21 +0300)
17 files changed:
65c02core.cpp [new file with mode: 0644]
cdtvcr.cpp
cia.cpp
disk.cpp
gfxboard.cpp
include/gui.h
memory.cpp
od-win32/rp.cpp
od-win32/rp.h
od-win32/win32.cpp
od-win32/win32.h
od-win32/win32gfx.cpp
od-win32/win32gui.cpp
od-win32/winuaechangelog.txt
qemuvga/esp.cpp
specialmonitors.cpp
x86.cpp

diff --git a/65c02core.cpp b/65c02core.cpp
new file mode 100644 (file)
index 0000000..d162fdc
--- /dev/null
@@ -0,0 +1,2493 @@
+/*
+ * 65C02core.c - 65C02/65SC02 emulation core.
+ *
+ * Written by
+ *  Marco van den Heuvel <blackystardust68@yahoo.com>
+ *
+ * This file is part of VICE, the Versatile Commodore Emulator.
+ * See README for copyright notice.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA.
+ *
+ */
+
+/* This file is included by the following CPU definition files:
+   - drivecpu65c02.c
+ */
+
+/* any CPU definition file that includes this file needs to do the following:
+ *
+ * - define reg_a as 8bit.
+ * - define reg_x as 8bit.
+ * - define reg_y as 8bit.
+ * - define reg_pc as 16bit.
+ * - define reg_sp as 8bit.
+ * - define reg_p as 8bit
+ * - define the cpu being emulated in a var 'cpu_type' (CPU_WDC65C02, CPU_R65C02, CPU_65SC02).
+ * - define a function to handle the WDC65C02 STP opcode (WDC_STP(void)).
+ * - define a function to handle the WDC65C02 WAI opcode (WDC_WAI(void)).
+ *
+ */
+
+/* still to check and possibly fix:
+ *
+ * - BRK does get interrupted by an IRQ/NMI on the 65(S)C02?
+ */
+
+#ifndef CPU_STR
+#define CPU_STR "65(S)C02 CPU"
+#endif
+
+//#include "traps.h"
+
+/* To avoid 'magic' numbers, we will use the following defines. */
+#define CYCLES_0   0
+#define CYCLES_1   1
+#define CYCLES_2   2
+#define CYCLES_3   3
+#define CYCLES_4   4
+#define CYCLES_5   5
+
+#define SIZE_1   1
+#define SIZE_2   2
+#define SIZE_3   3
+
+#define BIT_0   0
+#define BIT_1   1
+#define BIT_2   2
+#define BIT_3   3
+#define BIT_4   4
+#define BIT_5   5
+#define BIT_6   6
+#define BIT_7   7
+
+#define IRQ_CYCLES      7
+#define NMI_CYCLES      7
+#define RESET_CYCLES    6
+
+/* ------------------------------------------------------------------------- */
+/* Backup for non-6509 CPUs.  */
+
+#ifndef LOAD_IND
+#define LOAD_IND(a)     LOAD(a)
+#endif
+#ifndef STORE_IND
+#define STORE_IND(a, b)  STORE(a, b)
+#endif
+
+/* ------------------------------------------------------------------------- */
+/* Backup for non-variable cycle CPUs.  */
+
+#ifndef CLK_ADD
+#define CLK_ADD(clock, amount) clock += amount
+#endif
+
+#ifndef REWIND_FETCH_OPCODE
+#define REWIND_FETCH_OPCODE(clock, amount) clock -= amount
+#endif
+
+/* ------------------------------------------------------------------------- */
+/* Hook for additional delay.  */
+
+#ifndef CPU_DELAY_CLK
+#define CPU_DELAY_CLK
+#endif
+
+#ifndef CPU_REFRESH_CLK
+#define CPU_REFRESH_CLK
+#endif
+
+/* ------------------------------------------------------------------------- */
+
+#ifndef CYCLE_EXACT_ALARM
+#define PROCESS_ALARMS                                             \
+    while (CLK >= alarm_context_next_pending_clk(ALARM_CONTEXT)) { \
+        alarm_context_dispatch(ALARM_CONTEXT, CLK);                \
+        CPU_DELAY_CLK                                              \
+    }
+#else
+#define PROCESS_ALARMS
+#endif
+
+/* ------------------------------------------------------------------------- */
+
+#define LOCAL_SET_NZ(val)        (flag_z = flag_n = (val))
+
+#define LOCAL_SET_OVERFLOW(val)   \
+    do {                          \
+        if (val) {                \
+            reg_p |= P_OVERFLOW;  \
+        } else {                  \
+            reg_p &= ~P_OVERFLOW; \
+        }                         \
+    } while (0)
+
+#define LOCAL_SET_BREAK(val)   \
+    do {                       \
+        if (val) {             \
+            reg_p |= P_BREAK;  \
+        } else {               \
+            reg_p &= ~P_BREAK; \
+        }                      \
+    } while (0)
+
+#define LOCAL_SET_DECIMAL(val)   \
+    do {                         \
+        if (val) {               \
+            reg_p |= P_DECIMAL;  \
+        } else {                 \
+            reg_p &= ~P_DECIMAL; \
+        }                        \
+    } while (0)
+
+#define LOCAL_SET_INTERRUPT(val)   \
+    do {                           \
+        if (val) {                 \
+            reg_p |= P_INTERRUPT;  \
+        } else {                   \
+            reg_p &= ~P_INTERRUPT; \
+        }                          \
+    } while (0)
+
+#define LOCAL_SET_CARRY(val)   \
+    do {                       \
+        if (val) {             \
+            reg_p |= P_CARRY;  \
+        } else {               \
+            reg_p &= ~P_CARRY; \
+        }                      \
+    } while (0)
+
+#define LOCAL_SET_SIGN(val)      (flag_n = (val) ? 0x80 : 0)
+#define LOCAL_SET_ZERO(val)      (flag_z = !(val))
+#define LOCAL_SET_STATUS(val)    (reg_p = ((val) & ~(P_ZERO | P_SIGN)), \
+                                  LOCAL_SET_ZERO((val) & P_ZERO),       \
+                                  flag_n = (val))
+
+#define LOCAL_OVERFLOW()         (reg_p & P_OVERFLOW)
+#define LOCAL_BREAK()            (reg_p & P_BREAK)
+#define LOCAL_DECIMAL()          (reg_p & P_DECIMAL)
+#define LOCAL_INTERRUPT()        (reg_p & P_INTERRUPT)
+#define LOCAL_CARRY()            (reg_p & P_CARRY)
+#define LOCAL_SIGN()             (flag_n & 0x80)
+#define LOCAL_ZERO()             (!flag_z)
+#define LOCAL_STATUS()           (reg_p | (flag_n & 0x80) | P_UNUSED    \
+                                  | (LOCAL_ZERO() ? P_ZERO : 0))
+
+#ifdef LAST_OPCODE_INFO
+
+/* If requested, gather some info about the last executed opcode for timing
+   purposes.  */
+
+/* Remember the number of the last opcode.  By default, the opcode does not
+   delay interrupt and does not change the I flag.  */
+#define SET_LAST_OPCODE(x) OPINFO_SET(LAST_OPCODE_INFO, (x), 0, 0, 0)
+
+/* Remember that the last opcode delayed a pending IRQ or NMI by one cycle.  */
+#define OPCODE_DELAYS_INTERRUPT() OPINFO_SET_DELAYS_INTERRUPT(LAST_OPCODE_INFO, 1)
+
+/* Remember that the last opcode changed the I flag from 0 to 1, so we have
+   to dispatch an IRQ even if the I flag is 0 when we check it.  */
+#define OPCODE_DISABLES_IRQ() OPINFO_SET_DISABLES_IRQ(LAST_OPCODE_INFO, 1)
+
+/* Remember that the last opcode changed the I flag from 1 to 0, so we must
+   not dispatch an IRQ even if the I flag is 1 when we check it.  */
+#define OPCODE_ENABLES_IRQ() OPINFO_SET_ENABLES_IRQ(LAST_OPCODE_INFO, 1)
+
+#else
+
+/* Info about the last opcode is not needed.  */
+#define SET_LAST_OPCODE(x)
+#define OPCODE_DELAYS_INTERRUPT()
+#define OPCODE_DISABLES_IRQ()
+#define OPCODE_ENABLES_IRQ()
+
+#endif
+
+#ifdef LAST_OPCODE_ADDR
+#define SET_LAST_ADDR(x) LAST_OPCODE_ADDR = (x)
+#else
+#error "please define LAST_OPCODE_ADDR"
+#endif
+
+#ifndef DRIVE_CPU
+/* Export the local version of the registers.  */
+#define EXPORT_REGISTERS()       \
+    do {                         \
+        GLOBAL_REGS.pc = reg_pc; \
+        GLOBAL_REGS.a = reg_a;   \
+        GLOBAL_REGS.x = reg_x;   \
+        GLOBAL_REGS.y = reg_y;   \
+        GLOBAL_REGS.sp = reg_sp; \
+        GLOBAL_REGS.p = reg_p;   \
+        GLOBAL_REGS.n = flag_n;  \
+        GLOBAL_REGS.z = flag_z;  \
+    } while (0)
+
+/* Import the public version of the registers.  */
+#define IMPORT_REGISTERS()                                 \
+    do {                                                   \
+        reg_a = GLOBAL_REGS.a;                             \
+        reg_x = GLOBAL_REGS.x;                             \
+        reg_y = GLOBAL_REGS.y;                             \
+        reg_sp = GLOBAL_REGS.sp;                           \
+        reg_p = GLOBAL_REGS.p;                             \
+        flag_n = GLOBAL_REGS.n;                            \
+        flag_z = GLOBAL_REGS.z;                            \
+        bank_start = bank_limit = 0; /* prevent caching */ \
+        JUMP(GLOBAL_REGS.pc);                              \
+    } while (0)
+#else  /* DRIVE_CPU */
+#define IMPORT_REGISTERS()
+#define EXPORT_REGISTERS()
+#endif /* !DRIVE_CPU */
+
+/* Stack operations. */
+
+#ifndef PUSH
+#define PUSH(val) ((PAGE_ONE)[(reg_sp--)] = ((BYTE)(val)))
+#endif
+#ifndef PULL
+#define PULL()    ((PAGE_ONE)[(++reg_sp)])
+#endif
+
+#ifdef DEBUG
+#define TRACE_NMI(clk)                        \
+    do {                                      \
+        if (TRACEFLG) {                       \
+            debug_nmi(CPU_INT_STATUS, (clk)); \
+        }                                     \
+    } while (0)
+#define TRACE_IRQ(clk)                        \
+    do {                                      \
+        if (TRACEFLG) {                       \
+            debug_irq(CPU_INT_STATUS, (clk)); \
+        }                                     \
+    } while (0)
+#define TRACE_BRK()                \
+    do {                           \
+        if (TRACEFLG) {            \
+            debug_text("*** BRK"); \
+        }                          \
+    } while (0)
+#else
+#define TRACE_NMI(clk)
+#define TRACE_IRQ(clk)
+#define TRACE_BRK()
+#endif
+
+/* Perform the interrupts in `int_kind'.  If we have both NMI and IRQ,
+   execute NMI. NMI can _not_ take over an in progress IRQ. */
+/* FIXME: LOCAL_STATUS() should check byte ready first.  */
+#define DO_INTERRUPT(int_kind)                                                                                \
+    do {                                                                                                      \
+        BYTE ik = (int_kind);                                                                                 \
+                                                                                                              \
+        if (ik & (IK_IRQ | IK_IRQPEND | IK_NMI)) {                                                            \
+            if ((ik & IK_NMI)                                                                                 \
+                 && interrupt_check_nmi_delay(CPU_INT_STATUS, CLK)) {                                         \
+                TRACE_NMI(CLK);                                                                               \
+                if (monitor_mask[CALLER] & (MI_STEP)) {                                                       \
+                    monitor_check_icount_interrupt();                                                         \
+                }                                                                                             \
+                interrupt_ack_nmi(CPU_INT_STATUS);                                                            \
+                if (NMI_CYCLES == 7) {                                                                        \
+                    LOAD(reg_pc);   /* dummy reads */                                                         \
+                    CLK_ADD(CLK, 1);                                                                          \
+                    LOAD(reg_pc);                                                                             \
+                    CLK_ADD(CLK, 1);                                                                          \
+                }                                                                                             \
+                LOCAL_SET_BREAK(0);                                                                           \
+                PUSH(reg_pc >> 8);                                                                            \
+                PUSH(reg_pc & 0xff);                                                                          \
+                CLK_ADD(CLK, 2);                                                                              \
+                PUSH(LOCAL_STATUS());                                                                         \
+                CLK_ADD(CLK, 1);                                                                              \
+                LOCAL_SET_DECIMAL(0);                                                                         \
+                LOCAL_SET_INTERRUPT(1);                                                                       \
+                JUMP(LOAD_ADDR(0xfffa));                                                                      \
+                SET_LAST_OPCODE(0);                                                                           \
+                CLK_ADD(CLK, 2);                                                                              \
+            }                                                                                                 \
+            if ((ik & (IK_IRQ | IK_IRQPEND)) && (!LOCAL_INTERRUPT() || OPINFO_DISABLES_IRQ(LAST_OPCODE_INFO)) \
+                    && interrupt_check_irq_delay(CPU_INT_STATUS, CLK)) {                                      \
+                TRACE_IRQ(CLK);                                                                               \
+                if (monitor_mask[CALLER] & (MI_STEP)) {                                                       \
+                    monitor_check_icount_interrupt();                                                         \
+                }                                                                                             \
+                interrupt_ack_irq(CPU_INT_STATUS);                                                            \
+                if (NMI_CYCLES == 7) {                                                                        \
+                    LOAD(reg_pc);   /* dummy reads */                                                         \
+                    CLK_ADD(CLK, 1);                                                                          \
+                    LOAD(reg_pc);                                                                             \
+                    CLK_ADD(CLK, 1);                                                                          \
+                }                                                                                             \
+                LOCAL_SET_BREAK(0);                                                                           \
+                PUSH(reg_pc >> 8);                                                                            \
+                PUSH(reg_pc & 0xff);                                                                          \
+                CLK_ADD(CLK, 2);                                                                              \
+                PUSH(LOCAL_STATUS());                                                                         \
+                CLK_ADD(CLK, 1);                                                                              \
+                LOCAL_SET_DECIMAL(0);                                                                         \
+                LOCAL_SET_INTERRUPT(1);                                                                       \
+                JUMP(LOAD_ADDR(0xfffe));                                                                      \
+                SET_LAST_OPCODE(0);                                                                           \
+                CLK_ADD(CLK, 2);                                                                              \
+            }                                                                                                 \
+        }                                                                                                     \
+        if (ik & (IK_TRAP | IK_RESET)) {                                                                      \
+            if (ik & IK_TRAP) {                                                                               \
+                EXPORT_REGISTERS();                                                                           \
+                interrupt_do_trap(CPU_INT_STATUS, (WORD)reg_pc);                                              \
+                IMPORT_REGISTERS();                                                                           \
+                if (CPU_INT_STATUS->global_pending_int & IK_RESET) {                                          \
+                    ik |= IK_RESET;                                                                           \
+                }                                                                                             \
+            }                                                                                                 \
+            if (ik & IK_RESET) {                                                                              \
+                interrupt_ack_reset(CPU_INT_STATUS);                                                          \
+                cpu65c02_reset();                                                                                  \
+                bank_start = bank_limit = 0; /* prevent caching */                                            \
+                JUMP(LOAD_ADDR(0xfffc));                                                                      \
+                DMA_ON_RESET;                                                                                 \
+            }                                                                                                 \
+        }                                                                                                     \
+        if (ik & (IK_MONITOR | IK_DMA)) {                                                                     \
+            if (ik & IK_MONITOR) {                                                                            \
+                if (monitor_force_import(CALLER)) {                                                           \
+                    IMPORT_REGISTERS();                                                                       \
+                }                                                                                             \
+                if (monitor_mask[CALLER]) {                                                                   \
+                    EXPORT_REGISTERS();                                                                       \
+                }                                                                                             \
+                if (monitor_mask[CALLER] & (MI_STEP)) {                                                       \
+                    monitor_check_icount((WORD)reg_pc);                                                       \
+                    IMPORT_REGISTERS();                                                                       \
+                }                                                                                             \
+                if (monitor_mask[CALLER] & (MI_BREAK)) {                                                      \
+                    if (monitor_check_breakpoints(CALLER, (WORD)reg_pc)) {                                    \
+                        monitor_startup(CALLER);                                                              \
+                        IMPORT_REGISTERS();                                                                   \
+                    }                                                                                         \
+                }                                                                                             \
+                if (monitor_mask[CALLER] & (MI_WATCH)) {                                                      \
+                    monitor_check_watchpoints(LAST_OPCODE_ADDR, (WORD)reg_pc);                                \
+                    IMPORT_REGISTERS();                                                                       \
+                }                                                                                             \
+            }                                                                                                 \
+            if (ik & IK_DMA) {                                                                                \
+                EXPORT_REGISTERS();                                                                           \
+                DMA_FUNC;                                                                                     \
+                interrupt_ack_dma(CPU_INT_STATUS);                                                            \
+                IMPORT_REGISTERS();                                                                           \
+            }                                                                                                 \
+        }                                                                                                     \
+    } while (0)
+
+/* ------------------------------------------------------------------------- */
+
+/* Addressing modes.  For convenience, page boundary crossing cycles and
+   ``idle'' memory reads are handled here as well. */
+
+#define LOAD_ABS(addr) LOAD(addr)
+
+#define LOAD_ABS_X(addr)              \
+    ((((addr) & 0xff) + reg_x) > 0xff \
+     ? (LOAD(reg_pc + 2),             \
+        CLK_ADD(CLK, CYCLES_1),       \
+        LOAD((addr) + reg_x))         \
+     : LOAD((addr) + reg_x))
+
+#define LOAD_ABS_X_RMW(addr) \
+    (LOAD(reg_pc + 2),       \
+     CLK_ADD(CLK, CYCLES_1), \
+     LOAD((addr) + reg_x))
+
+#define LOAD_ABS_Y(addr)              \
+    ((((addr) & 0xff) + reg_y) > 0xff \
+     ? (LOAD(reg_pc + 2),             \
+        CLK_ADD(CLK, CYCLES_1),       \
+        LOAD((addr) + reg_y))         \
+     : LOAD((addr) + reg_y))
+
+#define LOAD_INDIRECT(addr) (CLK_ADD(CLK, CYCLES_2), LOAD(LOAD_ZERO_ADDR((addr))))
+
+#define LOAD_IND_X(addr) (CLK_ADD(CLK, CYCLES_3), LOAD(LOAD_ZERO_ADDR((addr) + reg_x)))
+
+#define LOAD_IND_Y(addr)                                                      \
+    (CLK_ADD(CLK, CYCLES_2), ((LOAD_ZERO_ADDR((addr)) & 0xff) + reg_y) > 0xff \
+     ? (LOAD(reg_pc + 1),                                                     \
+        CLK_ADD(CLK, CYCLES_1),                                               \
+        LOAD(LOAD_ZERO_ADDR((addr)) + reg_y))                                 \
+     : LOAD(LOAD_ZERO_ADDR((addr)) + reg_y))
+
+#define LOAD_ZERO_X(addr) (LOAD_ZERO((addr) + reg_x))
+
+#define LOAD_ZERO_Y(addr) (LOAD_ZERO((addr) + reg_y))
+
+#define LOAD_IND_Y_BANK(addr)                                                 \
+    (CLK_ADD(CLK, CYCLES_2), ((LOAD_ZERO_ADDR((addr)) & 0xff) + reg_y) > 0xff \
+     ? (LOAD(reg_pc + 1),                                                     \
+        CLK_ADD(CLK, CYCLES_1),                                               \
+        LOAD_IND(LOAD_ZERO_ADDR((addr)) + reg_y))                             \
+     : LOAD_IND(LOAD_ZERO_ADDR((addr)) + reg_y))
+
+#define STORE_ABS(addr, value)  \
+    do {                        \
+        STORE((addr), (value)); \
+    } while (0)
+
+#define STORE_ABS_RRW(addr, value) \
+    do {                           \
+        LOAD(addr);                \
+        CLK_ADD(CLK, CYCLES_1);    \
+        STORE(addr, value);        \
+        CLK_ADD(CLK, CYCLES_1);    \
+    } while (0)
+
+#define STORE_ABS_X(addr, value)        \
+    do {                                \
+        LOAD(reg_pc - 1);               \
+        CLK_ADD(CLK, CYCLES_1);         \
+        STORE((addr) + reg_x, (value)); \
+        CLK_ADD(CLK, CYCLES_1);         \
+    } while (0)
+
+#define STORE_ABS_X_RRW(addr, value)    \
+    do {                                \
+        LOAD((addr) + reg_x);           \
+        CLK_ADD(CLK, CYCLES_1);         \
+        STORE((addr) + reg_x, (value)); \
+        CLK_ADD(CLK, CYCLES_1);         \
+    } while (0)
+
+#define STORE_ABS_Y(addr, value)        \
+    do {                                \
+        LOAD(reg_pc - 1);               \
+        CLK_ADD(CLK, CYCLES_1);         \
+        STORE((addr) + reg_y, (value)); \
+        CLK_ADD(CLK, CYCLES_1);         \
+    } while (0)
+
+#define INC_PC(value) (reg_pc += (value))
+
+/* ------------------------------------------------------------------------- */
+
+/* Opcodes.  */
+
+/*
+   A couple of caveats about PC:
+
+   - the VIC-II emulation requires PC to be incremented before the first
+     write access (this is not (very) important when writing to the zero
+     page);
+
+   - `p0', `p1' and `p2' can only be used *before* incrementing PC: some
+     machines (eg. the C128) might depend on this.
+*/
+
+#define ADC(value, clk_inc, pc_inc)                                                      \
+    do {                                                                                 \
+        unsigned int tmp_value;                                                          \
+        unsigned int tmp, tmp2;                                                          \
+                                                                                         \
+        tmp_value = (value);                                                             \
+        CLK_ADD(CLK, (clk_inc));                                                         \
+                                                                                         \
+        if (LOCAL_DECIMAL()) {                                                           \
+            tmp = (reg_a & 0xf) + (tmp_value & 0xf) + LOCAL_CARRY();                     \
+            tmp2 = (reg_a & 0xf0) + (tmp_value & 0xf0);                                  \
+            if (tmp > 9) {                                                               \
+                tmp2 += 0x10;                                                            \
+                tmp += 6;                                                                \
+            }                                                                            \
+            LOCAL_SET_OVERFLOW(~(reg_a ^ tmp_value) & (reg_a ^ tmp) & 0x80);             \
+            if (tmp2 > 0x90) {                                                           \
+                tmp2 += 0x60;                                                            \
+            }                                                                            \
+            LOCAL_SET_CARRY(tmp2 & 0xff00);                                              \
+            tmp = (tmp & 0xf) + (tmp2 & 0xf0);                                           \
+            LOCAL_SET_NZ(tmp);                                                           \
+            LOAD(reg_pc + pc_inc - 1);                                                   \
+            CLK_ADD(CLK, CYCLES_1);                                                      \
+        } else {                                                                         \
+            tmp = tmp_value + reg_a + LOCAL_CARRY();                                     \
+            LOCAL_SET_NZ(tmp & 0xff);                                                    \
+            LOCAL_SET_OVERFLOW(!((reg_a ^ tmp_value) & 0x80) && ((reg_a ^ tmp) & 0x80)); \
+            LOCAL_SET_CARRY(tmp > 0xff);                                                 \
+        }                                                                                \
+        reg_a = tmp;                                                                     \
+        INC_PC(pc_inc);                                                                  \
+    } while (0)
+
+#define AND(value, clk_inc, pc_inc)      \
+    do {                                 \
+        reg_a = (BYTE)(reg_a & (value)); \
+        LOCAL_SET_NZ(reg_a);             \
+        CLK_ADD(CLK, (clk_inc));         \
+        INC_PC(pc_inc);                  \
+    } while (0)
+
+#define ASL(addr, clk_inc, pc_inc, load_func, store_func) \
+    do {                                                  \
+        unsigned int tmp_value, tmp_addr;                 \
+                                                          \
+        tmp_addr = (addr);                                \
+        tmp_value = load_func(tmp_addr);                  \
+        LOCAL_SET_CARRY(tmp_value & 0x80);                \
+        tmp_value = (tmp_value << 1) & 0xff;              \
+        LOCAL_SET_NZ(tmp_value);                          \
+        INC_PC(pc_inc);                                   \
+        CLK_ADD(CLK, clk_inc);                            \
+        store_func(tmp_addr, tmp_value);                  \
+    } while (0)
+
+#define ASL_A()                        \
+    do {                               \
+        LOCAL_SET_CARRY(reg_a & 0x80); \
+        reg_a = reg_a << 1;            \
+        LOCAL_SET_NZ(reg_a);           \
+        INC_PC(SIZE_1);                \
+    } while (0)
+
+#define BBR(bit)                                           \
+    do {                                                   \
+        unsigned int tmp, tmp_addr;                        \
+        unsigned int dest_addr;                            \
+        BYTE value;                                        \
+                                                           \
+        if (cpu_type == CPU_65SC02) {                      \
+            NOOP_IMM(SIZE_1);                              \
+        } else {                                           \
+            tmp_addr = LOAD(reg_pc + 1);                   \
+            CLK_ADD(CLK, CYCLES_1);                        \
+            value = LOAD(reg_pc + 2);                      \
+            CLK_ADD(CLK, CYCLES_1);                        \
+            tmp = LOAD_ZERO(tmp_addr) & (1 << bit);        \
+            CLK_ADD(CLK, CYCLES_1);                        \
+            INC_PC(SIZE_3);                                \
+            LOAD(reg_pc);                                  \
+            CLK_ADD(CLK, CYCLES_1);                        \
+            if (!tmp) {                                    \
+                dest_addr = reg_pc + (signed char)(value); \
+                OPCODE_DELAYS_INTERRUPT();                 \
+                JUMP(dest_addr & 0xffff);                  \
+            }                                              \
+        }                                                  \
+    } while (0)
+
+#define BBS(bit)                                           \
+    do {                                                   \
+        unsigned int tmp, tmp_addr;                        \
+        unsigned int dest_addr;                            \
+        BYTE value;                                        \
+                                                           \
+        if (cpu_type == CPU_65SC02) {                      \
+            NOOP_IMM(SIZE_1);                              \
+        } else {                                           \
+            tmp_addr = LOAD(reg_pc + 1);                   \
+            CLK_ADD(CLK, CYCLES_1);                        \
+            value = LOAD(reg_pc + 2);                      \
+            CLK_ADD(CLK, CYCLES_1);                        \
+            tmp = LOAD_ZERO(tmp_addr) & (1 << bit);        \
+            CLK_ADD(CLK, CYCLES_1);                        \
+            INC_PC(SIZE_3);                                \
+            LOAD(reg_pc);                                  \
+            CLK_ADD(CLK, CYCLES_1);                        \
+                                                           \
+            if (tmp) {                                     \
+                dest_addr = reg_pc + (signed char)(value); \
+                OPCODE_DELAYS_INTERRUPT();                 \
+                JUMP(dest_addr & 0xffff);                  \
+            }                                              \
+        }                                                  \
+    } while (0)
+
+#define BIT(value, clk_inc, pc_inc)     \
+    do {                                \
+        unsigned int tmp;               \
+                                        \
+        tmp = (value);                  \
+        CLK_ADD(CLK, clk_inc);          \
+        LOCAL_SET_SIGN(tmp & 0x80);     \
+        LOCAL_SET_OVERFLOW(tmp & 0x40); \
+        LOCAL_SET_ZERO(!(tmp & reg_a)); \
+        INC_PC(pc_inc);                 \
+    } while (0)
+
+#define BIT_IMM(value)                  \
+    do {                                \
+        unsigned int tmp;               \
+                                        \
+        tmp = (value);                  \
+        LOCAL_SET_ZERO(!(tmp & reg_a)); \
+        INC_PC(SIZE_2);                 \
+    } while (0)
+
+#define BRANCH(cond, value)                            \
+    do {                                               \
+        unsigned int dest_addr = 0;                    \
+        INC_PC(SIZE_2);                                \
+                                                       \
+        if (cond) {                                    \
+            dest_addr = reg_pc + (signed char)(value); \
+                                                       \
+            LOAD(reg_pc);                              \
+            CLK_ADD(CLK, CYCLES_1);                    \
+            if ((reg_pc ^ dest_addr) & 0xff00) {       \
+                LOAD(reg_pc);                          \
+                CLK_ADD(CLK, CYCLES_1);                \
+            } else {                                   \
+                OPCODE_DELAYS_INTERRUPT();             \
+            }                                          \
+            JUMP(dest_addr & 0xffff);                  \
+        }                                              \
+    } while (0)
+
+#define BRK()                    \
+    do {                         \
+        EXPORT_REGISTERS();      \
+        TRACE_BRK();             \
+        INC_PC(SIZE_2);          \
+        LOCAL_SET_BREAK(1);      \
+        PUSH(reg_pc >> 8);       \
+        PUSH(reg_pc & 0xff);     \
+        CLK_ADD(CLK, CYCLES_2);  \
+        PUSH(LOCAL_STATUS());    \
+        CLK_ADD(CLK, CYCLES_1);  \
+        LOCAL_SET_DECIMAL(0);    \
+        LOCAL_SET_INTERRUPT(1);  \
+        JUMP(LOAD_ADDR(0xfffe)); \
+        CLK_ADD(CLK, CYCLES_2);  \
+    } while (0)
+
+#define CLC()               \
+    do {                    \
+        INC_PC(SIZE_1);     \
+        LOCAL_SET_CARRY(0); \
+    } while (0)
+
+#define CLD()                 \
+    do {                      \
+        INC_PC(SIZE_1);       \
+        LOCAL_SET_DECIMAL(0); \
+    } while (0)
+
+#define CLI()                     \
+    do {                          \
+        INC_PC(SIZE_1);           \
+        if (LOCAL_INTERRUPT()) {  \
+            OPCODE_ENABLES_IRQ(); \
+        }                         \
+        LOCAL_SET_INTERRUPT(0);   \
+    } while (0)
+
+#define CLV()                  \
+    do {                       \
+        INC_PC(SIZE_1);        \
+        LOCAL_SET_OVERFLOW(0); \
+    } while (0)
+
+#define CMP(value, clk_inc, pc_inc)   \
+    do {                              \
+        unsigned int tmp;             \
+                                      \
+        tmp = reg_a - (value);        \
+        LOCAL_SET_CARRY(tmp < 0x100); \
+        LOCAL_SET_NZ(tmp & 0xff);     \
+        CLK_ADD(CLK, (clk_inc));      \
+        INC_PC(pc_inc);               \
+    } while (0)
+
+#define CPX(value, clk_inc, pc_inc)   \
+    do {                              \
+        unsigned int tmp;             \
+                                      \
+        tmp = reg_x - (value);        \
+        LOCAL_SET_CARRY(tmp < 0x100); \
+        LOCAL_SET_NZ(tmp & 0xff);     \
+        CLK_ADD(CLK, (clk_inc));      \
+        INC_PC(pc_inc);               \
+    } while (0)
+
+#define CPY(value, clk_inc, pc_inc)   \
+    do {                              \
+        unsigned int tmp;             \
+                                      \
+        tmp = reg_y - (value);        \
+        LOCAL_SET_CARRY(tmp < 0x100); \
+        LOCAL_SET_NZ(tmp & 0xff);     \
+        CLK_ADD(CLK, (clk_inc));      \
+        INC_PC(pc_inc);               \
+    } while (0)
+
+#define DEA()                \
+    do {                     \
+        reg_a--;             \
+        LOCAL_SET_NZ(reg_a); \
+        INC_PC(SIZE_1);      \
+    } while (0)
+
+#define DEC(addr, clk_inc, pc_inc, load_func, store_func) \
+    do {                                                  \
+        unsigned int tmp, tmp_addr;                       \
+                                                          \
+        tmp_addr = (addr);                                \
+        tmp = load_func(tmp_addr);                        \
+        tmp = (tmp - 1) & 0xff;                           \
+        LOCAL_SET_NZ(tmp);                                \
+        INC_PC(pc_inc);                                   \
+        CLK_ADD(CLK, (clk_inc));                          \
+        store_func(tmp_addr, tmp);                        \
+    } while (0)
+
+#define DEX()                \
+    do {                     \
+        reg_x--;             \
+        LOCAL_SET_NZ(reg_x); \
+        INC_PC(SIZE_1);      \
+    } while (0)
+
+#define DEY()                \
+    do {                     \
+        reg_y--;             \
+        LOCAL_SET_NZ(reg_y); \
+        INC_PC(SIZE_1);      \
+    } while (0)
+
+#define EOR(value, clk_inc, pc_inc)      \
+    do {                                 \
+        reg_a = (BYTE)(reg_a ^ (value)); \
+        LOCAL_SET_NZ(reg_a);             \
+        CLK_ADD(CLK, (clk_inc));         \
+        INC_PC(pc_inc);                  \
+    } while (0)
+
+#define INA()                \
+    do {                     \
+        reg_a++;             \
+        LOCAL_SET_NZ(reg_a); \
+        INC_PC(SIZE_1);      \
+    } while (0)
+
+#define INC(addr, clk_inc, pc_inc, load_func, store_func) \
+    do {                                                  \
+        unsigned int tmp, tmp_addr;                       \
+                                                          \
+        tmp_addr = (addr);                                \
+        tmp = (load_func(tmp_addr) + 1) & 0xff;           \
+        LOCAL_SET_NZ(tmp);                                \
+        INC_PC(pc_inc);                                   \
+        CLK_ADD(CLK, (clk_inc));                          \
+        store_func(tmp_addr, tmp);                        \
+    } while (0)
+
+#define INX()                \
+    do {                     \
+        reg_x++;             \
+        LOCAL_SET_NZ(reg_x); \
+        INC_PC(SIZE_1);      \
+    } while (0)
+
+#define INY()                \
+    do {                     \
+        reg_y++;             \
+        LOCAL_SET_NZ(reg_y); \
+        INC_PC(SIZE_1);      \
+    } while (0)
+
+/* The 0x02 NOP opcode is also used to patch the ROM.  The function trap_handler()
+   returns nonzero if this is not a patch, but a `real' NOP instruction. */
+
+#define NOP_02()                                                  \
+    do {                                                          \
+        DWORD trap_result;                                        \
+        EXPORT_REGISTERS();                                       \
+        if (!ROM_TRAP_ALLOWED()                                   \
+            || (trap_result = ROM_TRAP_HANDLER()) == (DWORD)-1) { \
+            NOOP_IMM(SIZE_2);                                     \
+        } else {                                                  \
+            if (trap_result) {                                    \
+                REWIND_FETCH_OPCODE(CLK, CYCLES_2);               \
+                SET_OPCODE(trap_result);                          \
+                IMPORT_REGISTERS();                               \
+                goto trap_skipped;                                \
+            } else {                                              \
+                IMPORT_REGISTERS();                               \
+            }                                                     \
+        }                                                         \
+    } while (0)
+
+#define JMP(addr)   \
+    do {            \
+        JUMP(addr); \
+    } while (0)
+
+#define JMP_IND()                                    \
+    do {                                             \
+        WORD dest_addr;                              \
+        dest_addr = LOAD(p2);                        \
+        CLK_ADD(CLK, CYCLES_1);                      \
+        LOAD(reg_pc + 2);                            \
+        CLK_ADD(CLK, CYCLES_1);                      \
+        dest_addr |= (LOAD((p2 + 1) & 0xffff) << 8); \
+        CLK_ADD(CLK, CYCLES_1);                      \
+        JUMP(dest_addr);                             \
+    } while (0)
+
+#define JMP_IND_X()                                          \
+    do {                                                     \
+        WORD dest_addr;                                      \
+        dest_addr = LOAD((p2 + reg_x) & 0xffff);             \
+        CLK_ADD(CLK, CYCLES_1);                              \
+        LOAD(reg_pc + 2);                                    \
+        CLK_ADD(CLK, CYCLES_1);                              \
+        dest_addr |= (LOAD((p2 + reg_x + 1) & 0xffff) << 8); \
+        CLK_ADD(CLK, CYCLES_1);                              \
+        JUMP(dest_addr);                                     \
+    } while (0)
+
+#define JSR()                                  \
+    do {                                       \
+        unsigned int tmp_addr;                 \
+                                               \
+        CLK_ADD(CLK, CYCLES_1);                \
+        INC_PC(SIZE_2);                        \
+        CLK_ADD(CLK, CYCLES_2);                \
+        PUSH(((reg_pc) >> 8) & 0xff);          \
+        PUSH((reg_pc) & 0xff);                 \
+        tmp_addr = (p1 | (LOAD(reg_pc) << 8)); \
+        CLK_ADD(CLK, CYCLES_1);                \
+        JUMP(tmp_addr);                        \
+    } while (0)
+
+#define LDA(value, clk_inc, pc_inc) \
+    do {                            \
+        reg_a = (BYTE)(value);      \
+        CLK_ADD(CLK, (clk_inc));    \
+        LOCAL_SET_NZ(reg_a);        \
+        INC_PC(pc_inc);             \
+    } while (0)
+
+#define LDX(value, clk_inc, pc_inc) \
+    do {                            \
+        reg_x = (BYTE)(value);      \
+        LOCAL_SET_NZ(reg_x);        \
+        CLK_ADD(CLK, (clk_inc));    \
+        INC_PC(pc_inc);             \
+    } while (0)
+
+#define LDY(value, clk_inc, pc_inc) \
+    do {                            \
+        reg_y = (BYTE)(value);      \
+        LOCAL_SET_NZ(reg_y);        \
+        CLK_ADD(CLK, (clk_inc));    \
+        INC_PC(pc_inc);             \
+    } while (0)
+
+#define LSR(addr, clk_inc, pc_inc, load_func, store_func) \
+    do {                                                  \
+        unsigned int tmp, tmp_addr;                       \
+                                                          \
+        tmp_addr = (addr);                                \
+        tmp = load_func(tmp_addr);                        \
+        LOCAL_SET_CARRY(tmp & 0x01);                      \
+        tmp >>= 1;                                        \
+        LOCAL_SET_NZ(tmp);                                \
+        INC_PC(pc_inc);                                   \
+        CLK_ADD(CLK, clk_inc);                            \
+        store_func(tmp_addr, tmp);                        \
+    } while (0)
+
+#define LSR_A()                        \
+    do {                               \
+        LOCAL_SET_CARRY(reg_a & 0x01); \
+        reg_a = reg_a >> 1;            \
+        LOCAL_SET_NZ(reg_a);           \
+        INC_PC(SIZE_1);                \
+    } while (0)
+
+#define ORA(value, clk_inc, pc_inc)      \
+    do {                                 \
+        reg_a = (BYTE)(reg_a | (value)); \
+        LOCAL_SET_NZ(reg_a);             \
+        CLK_ADD(CLK, (clk_inc));         \
+        INC_PC(pc_inc);                  \
+    } while (0)
+
+#define NOOP(clk_inc, pc_inc) (CLK_ADD(CLK, (clk_inc)), INC_PC(pc_inc))
+
+#define NOOP_IMM(pc_inc) INC_PC(pc_inc)
+
+#define NOOP_ZP()               \
+    do {                        \
+        LOAD_ZERO(p1);          \
+        CLK_ADD(CLK, CYCLES_1); \
+        INC_PC(SIZE_2);         \
+    } while (0)
+
+#define NOOP_ZP_X()             \
+    do {                        \
+        LOAD_ZERO(p1);          \
+        CLK_ADD(CLK, CYCLES_1); \
+        LOAD_ZERO(p1 + reg_x);  \
+        CLK_ADD(CLK, CYCLES_1); \
+        INC_PC(SIZE_2);         \
+    } while (0)
+
+#define NOOP_ABS()              \
+    do {                        \
+        LOAD(p2);               \
+        CLK_ADD(CLK, CYCLES_1); \
+        INC_PC(SIZE_3);         \
+    } while (0)
+
+#define NOOP_5C()               \
+    do {                        \
+        LOAD(p2);               \
+        CLK_ADD(CLK, CYCLES_1); \
+        LOAD(reg_pc + 2);       \
+        CLK_ADD(CLK, CYCLES_1); \
+        LOAD(reg_pc + 2);       \
+        CLK_ADD(CLK, CYCLES_1); \
+        LOAD(reg_pc + 2);       \
+        CLK_ADD(CLK, CYCLES_1); \
+        LOAD(reg_pc + 2);       \
+        CLK_ADD(CLK, CYCLES_1); \
+        INC_PC(SIZE_3);         \
+    } while (0)
+
+#define NOP()  NOOP_IMM(SIZE_1)
+
+#define PHA()                   \
+    do {                        \
+        CLK_ADD(CLK, CYCLES_1); \
+        PUSH(reg_a);            \
+        INC_PC(SIZE_1);         \
+    } while (0)
+
+#define PHP()                           \
+    do {                                \
+        CLK_ADD(CLK, CYCLES_1);         \
+        PUSH(LOCAL_STATUS() | P_BREAK); \
+        INC_PC(SIZE_1);                 \
+    } while (0)
+
+#define PHX()                   \
+    do {                        \
+        CLK_ADD(CLK, CYCLES_1); \
+        PUSH(reg_x);            \
+        INC_PC(SIZE_1);         \
+    } while (0)
+
+#define PHY()                   \
+    do {                        \
+        CLK_ADD(CLK, CYCLES_1); \
+        PUSH(reg_y);            \
+        INC_PC(SIZE_1);         \
+    } while (0)
+
+#define PLA()                   \
+    do {                        \
+        CLK_ADD(CLK, CYCLES_2); \
+        reg_a = PULL();         \
+        LOCAL_SET_NZ(reg_a);    \
+        INC_PC(SIZE_1);         \
+    } while (0)
+
+#define PLP()                                                 \
+    do {                                                      \
+        BYTE s = PULL();                                      \
+                                                              \
+        if (!(s & P_INTERRUPT) && LOCAL_INTERRUPT()) {        \
+            OPCODE_ENABLES_IRQ();                             \
+        } else if ((s & P_INTERRUPT) && !LOCAL_INTERRUPT()) { \
+            OPCODE_DISABLES_IRQ();                            \
+        }                                                     \
+        CLK_ADD(CLK, CYCLES_2);                               \
+        LOCAL_SET_STATUS(s);                                  \
+        INC_PC(SIZE_1);                                       \
+    } while (0)
+
+#define PLX()                   \
+    do {                        \
+        CLK_ADD(CLK, CYCLES_2); \
+        reg_x = PULL();         \
+        LOCAL_SET_NZ(reg_x);    \
+        INC_PC(SIZE_1);         \
+    } while (0)
+
+#define PLY()                   \
+    do {                        \
+        CLK_ADD(CLK, CYCLES_2); \
+        reg_y = PULL();         \
+        LOCAL_SET_NZ(reg_y);    \
+        INC_PC(SIZE_1);         \
+    } while (0)
+
+#define RMB(bit)                                     \
+    do {                                             \
+        unsigned int tmp, tmp_addr;                  \
+                                                     \
+        if (cpu_type == CPU_65SC02) {                \
+            NOOP_IMM(SIZE_1);                        \
+        } else {                                     \
+            tmp_addr = LOAD(reg_pc + 1);             \
+            CLK_ADD(CLK, CYCLES_1);                  \
+            LOAD_ZERO(tmp_addr);                     \
+            CLK_ADD(CLK, CYCLES_1);                  \
+            tmp = LOAD_ZERO(tmp_addr) & ~(1 << bit); \
+            CLK_ADD(CLK, CYCLES_1);                  \
+            INC_PC(SIZE_2);                          \
+            STORE_ZERO(tmp_addr, tmp);               \
+            CLK_ADD(CLK, 1);                         \
+        }                                            \
+    } while (0)
+
+#define ROL(addr, clk_inc, pc_inc, load_func, store_func) \
+    do {                                                  \
+        unsigned int tmp, tmp_addr;                       \
+                                                          \
+        tmp_addr = (addr);                                \
+        tmp = load_func(tmp_addr);                        \
+        tmp = (tmp << 1) | LOCAL_CARRY();                 \
+        LOCAL_SET_CARRY(tmp & 0x100);                     \
+        LOCAL_SET_NZ(tmp & 0xff);                         \
+        INC_PC(pc_inc);                                   \
+        CLK_ADD(CLK, clk_inc);                            \
+        store_func(tmp_addr, tmp);                        \
+    } while (0)
+
+#define ROL_A()                        \
+    do {                               \
+        unsigned int tmp = reg_a << 1; \
+                                       \
+        reg_a = tmp | LOCAL_CARRY();   \
+        LOCAL_SET_CARRY(tmp & 0x100);  \
+        LOCAL_SET_NZ(reg_a);           \
+        INC_PC(SIZE_1);                \
+    } while (0)
+
+#define ROR(addr, clk_inc, pc_inc, load_func, store_func) \
+    do {                                                  \
+        unsigned int src, tmp_addr;                       \
+                                                          \
+        tmp_addr = (addr);                                \
+        src = load_func(tmp_addr);                        \
+        if (LOCAL_CARRY()) {                              \
+            src |= 0x100;                                 \
+        }                                                 \
+        LOCAL_SET_CARRY(src & 0x01);                      \
+        src >>= 1;                                        \
+        LOCAL_SET_NZ(src);                                \
+        INC_PC(pc_inc);                                   \
+        CLK_ADD(CLK, (clk_inc));                          \
+        store_func(tmp_addr, src);                        \
+    } while (0)
+
+#define ROR_A()                              \
+    do {                                     \
+        BYTE tmp = reg_a;                    \
+                                             \
+        reg_a = (reg_a >> 1) | (reg_p << 7); \
+        LOCAL_SET_CARRY(tmp & 0x01);         \
+        LOCAL_SET_NZ(reg_a);                 \
+        INC_PC(SIZE_1);                      \
+    } while (0)
+
+/* RTI does must not use `OPCODE_ENABLES_IRQ()' even if the I flag changes
+   from 1 to 0 because the value of I is set 3 cycles before the end of the
+   opcode, and thus the 6510 has enough time to call the interrupt routine as
+   soon as the opcode ends, if necessary.  */
+#define RTI()                        \
+    do {                             \
+        WORD tmp;                    \
+                                     \
+        CLK_ADD(CLK, CYCLES_4);      \
+        tmp = (WORD)PULL();          \
+        LOCAL_SET_STATUS((BYTE)tmp); \
+        tmp = (WORD)PULL();          \
+        tmp |= (WORD)PULL() << 8;    \
+        JUMP(tmp);                   \
+    } while (0)
+
+#define RTS()                      \
+    do {                           \
+        WORD tmp;                  \
+                                   \
+        CLK_ADD(CLK, CYCLES_3);    \
+        tmp = PULL();              \
+        tmp = tmp | (PULL() << 8); \
+        LOAD(tmp);                 \
+        CLK_ADD(CLK, CYCLES_1);    \
+        tmp++;                     \
+        JUMP(tmp);                 \
+    } while (0)
+
+#define SBC(value, clk_inc, pc_inc)                                               \
+    do {                                                                          \
+        WORD src, tmp;                                                            \
+                                                                                  \
+        src = (WORD)(value);                                                      \
+        CLK_ADD(CLK, (clk_inc));                                                  \
+        if (LOCAL_DECIMAL()) {                                                    \
+            tmp = reg_a - (src & 0xf) + LOCAL_CARRY() - 1;                        \
+            if ((tmp & 0xf) > (reg_a & 0xf)) {                                    \
+                tmp -= 6;                                                         \
+            }                                                                     \
+            tmp -= (src & 0xf0);                                                  \
+            if ((tmp & 0xf0) > (reg_a & 0xf0)) {                                  \
+                tmp -= 0x60;                                                      \
+            }                                                                     \
+            LOCAL_SET_OVERFLOW(!(tmp > reg_a));                                   \
+            LOCAL_SET_CARRY(!(tmp > reg_a));                                      \
+            LOCAL_SET_NZ(tmp & 0xff);                                             \
+            LOAD(reg_pc + pc_inc - 1);                                            \
+            CLK_ADD(CLK, CYCLES_1);                                               \
+        } else {                                                                  \
+            tmp = reg_a - src - ((LOCAL_CARRY()) ? 0 : 1);                        \
+            LOCAL_SET_NZ(tmp & 0xff);                                             \
+            LOCAL_SET_CARRY(tmp < 0x100);                                         \
+            LOCAL_SET_OVERFLOW(((reg_a ^ tmp) & 0x80) && ((reg_a ^ src) & 0x80)); \
+        }                                                                         \
+        reg_a = (BYTE)tmp;                                                        \
+        INC_PC(pc_inc);                                                           \
+    } while (0)
+
+#undef SEC    /* defined in time.h on SunOS. */
+#define SEC()               \
+    do {                    \
+        LOCAL_SET_CARRY(1); \
+        INC_PC(SIZE_1);     \
+    } while (0)
+
+#define SED()                 \
+    do {                      \
+        LOCAL_SET_DECIMAL(1); \
+        INC_PC(SIZE_1);       \
+    } while (0)
+
+#define SEI()                      \
+    do {                           \
+        if (!LOCAL_INTERRUPT()) {  \
+            OPCODE_DISABLES_IRQ(); \
+        }                          \
+        LOCAL_SET_INTERRUPT(1);    \
+        INC_PC(SIZE_1);            \
+    } while (0)
+
+#define SMB(bit)                                    \
+    do {                                            \
+        unsigned tmp, tmp_addr;                     \
+                                                    \
+        if (cpu_type == CPU_65SC02) {               \
+            NOOP_IMM(SIZE_1);                       \
+        } else {                                    \
+            tmp_addr = LOAD(reg_pc + 1);            \
+            CLK_ADD(CLK, CYCLES_1);                 \
+            LOAD(tmp_addr);                         \
+            CLK_ADD(CLK, CYCLES_1);                 \
+            tmp = LOAD_ZERO(tmp_addr) | (1 << bit); \
+            CLK_ADD(CLK, CYCLES_1);                 \
+            INC_PC(SIZE_2);                         \
+            STORE_ZERO(tmp_addr, tmp);              \
+            CLK_ADD(CLK, CYCLES_1);                 \
+        }                                           \
+    } while (0)
+
+#define STA(addr, clk_inc1, clk_inc2, pc_inc, store_func) \
+    do {                                                  \
+        unsigned int tmp;                                 \
+                                                          \
+        CLK_ADD(CLK, (clk_inc1));                         \
+        tmp = (addr);                                     \
+        INC_PC(pc_inc);                                   \
+        CLK_ADD(CLK, clk_inc2 - 1);                       \
+        store_func(tmp, reg_a);                           \
+        CLK_ADD(CLK, CYCLES_1);                           \
+    } while (0)
+
+#define STA_ZERO(addr, clk_inc, pc_inc) \
+    do {                                \
+        CLK_ADD(CLK, (clk_inc));        \
+        STORE_ZERO((addr), reg_a);      \
+        INC_PC(pc_inc);                 \
+    } while (0)
+
+#define STA_IND_Y(addr)                \
+    do {                               \
+        unsigned int tmp;              \
+                                       \
+        CLK_ADD(CLK, CYCLES_2);        \
+        tmp = LOAD_ZERO_ADDR(addr);    \
+        LOAD(reg_pc + 1);              \
+        CLK_ADD(CLK, CYCLES_1);        \
+        INC_PC(SIZE_2);                \
+        STORE_IND(tmp + reg_y, reg_a); \
+        CLK_ADD(CLK, CYCLES_1);        \
+    } while (0)
+
+#define STP()                            \
+    do {                                 \
+        if (cpu_type == CPU_WDC65C02) {  \
+            WDC_STP();                   \
+        } else {                         \
+            REWIND_FETCH_OPCODE(CLK, 2); \
+            NOOP_IMM(SIZE_1);            \
+        }                                \
+    } while (0)
+
+#define STX(addr)               \
+    do {                        \
+        unsigned int tmp;       \
+                                \
+        tmp = (addr);           \
+        INC_PC(SIZE_3);         \
+        STORE(tmp, reg_x);      \
+        CLK_ADD(CLK, CYCLES_1); \
+    } while (0)
+
+#define STX_ZERO(addr, clk_inc, pc_inc) \
+    do {                                \
+        CLK_ADD(CLK, (clk_inc));        \
+        STORE_ZERO((addr), reg_x);      \
+        INC_PC(pc_inc);                 \
+    } while (0)
+
+#define STY(addr)               \
+    do {                        \
+        unsigned int tmp;       \
+                                \
+        tmp = (addr);           \
+        INC_PC(SIZE_3);         \
+        STORE(tmp, reg_y);      \
+        CLK_ADD(CLK, CYCLES_1); \
+    } while (0)
+
+#define STY_ZERO(addr, clk_inc, pc_inc) \
+    do {                                \
+        CLK_ADD(CLK, (clk_inc));        \
+        STORE_ZERO((addr), reg_y);      \
+        INC_PC(pc_inc);                 \
+    } while (0)
+
+#define STZ(addr, clk_inc, pc_inc, store_func) \
+    do {                                       \
+        unsigned int tmp;                      \
+                                               \
+        tmp = (addr);                          \
+        INC_PC(pc_inc);                        \
+        CLK_ADD(CLK, clk_inc);                 \
+        store_func(tmp, 0);                    \
+    } while (0)
+
+#define STZ_ZERO(addr, clk_inc, pc_inc) \
+    do {                                \
+        CLK_ADD(CLK, (clk_inc));        \
+        STORE_ZERO((addr), 0);          \
+        INC_PC(pc_inc);                 \
+    } while (0)
+
+#define TAX()                \
+    do {                     \
+        reg_x = reg_a;       \
+        LOCAL_SET_NZ(reg_a); \
+        INC_PC(SIZE_1);      \
+    } while (0)
+
+#define TAY()                \
+    do {                     \
+        reg_y = reg_a;       \
+        LOCAL_SET_NZ(reg_a); \
+        INC_PC(SIZE_1);      \
+    } while (0)
+
+#define TRB(addr, clk_inc, pc_inc, load_func, store_func) \
+    do {                                                  \
+        unsigned int tmp_value, tmp_addr;                 \
+                                                          \
+        tmp_addr = (addr);                                \
+        tmp_value = load_func(tmp_addr);                  \
+        LOCAL_SET_ZERO(!(tmp_value & reg_a));             \
+        tmp_value &= (~reg_a);                            \
+        INC_PC(pc_inc);                                   \
+        CLK_ADD(CLK, clk_inc);                            \
+        store_func(tmp_addr, tmp_value);                  \
+    } while (0)
+
+#define TSB(addr, clk_inc, pc_inc, load_func, store_func) \
+    do {                                                  \
+        unsigned int tmp_value, tmp_addr;                 \
+                                                          \
+        tmp_addr = (addr);                                \
+        tmp_value = load_func(tmp_addr);                  \
+        LOCAL_SET_ZERO(!(tmp_value & reg_a));             \
+        tmp_value |= reg_a;                               \
+        INC_PC(pc_inc);                                   \
+        CLK_ADD(CLK, clk_inc);                            \
+        store_func(tmp_addr, tmp_value);                  \
+    } while (0)
+
+#define TSX()                 \
+    do {                      \
+        reg_x = reg_sp;       \
+        LOCAL_SET_NZ(reg_sp); \
+        INC_PC(SIZE_1);       \
+    } while (0)
+
+#define TXA()                \
+    do {                     \
+        reg_a = reg_x;       \
+        LOCAL_SET_NZ(reg_a); \
+        INC_PC(SIZE_1);      \
+    } while (0)
+
+#define TXS()           \
+    do {                \
+        reg_sp = reg_x; \
+        INC_PC(SIZE_1); \
+    } while (0)
+
+#define TYA()                \
+    do {                     \
+        reg_a = reg_y;       \
+        LOCAL_SET_NZ(reg_a); \
+        INC_PC(SIZE_1);      \
+    } while (0)
+
+#define WAI()                            \
+    do {                                 \
+        if (cpu_type == CPU_WDC65C02) {  \
+            WDC_WAI();                   \
+        } else {                         \
+            REWIND_FETCH_OPCODE(CLK, 2); \
+            NOOP_IMM(SIZE_1);            \
+        }                                \
+    } while (0)
+
+/* ------------------------------------------------------------------------- */
+
+/* These tables have a different meaning than for the 6502, it represents
+   the amount of extra fetches to the opcode fetch.
+ */
+ static const BYTE fetch_tab[] = {
+            /* 0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F */
+    /* $00 */  1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 2, 2, 2, 0, /* $00 */
+    /* $10 */  1, 1, 1, 0, 1, 1, 1, 0, 1, 2, 1, 0, 2, 2, 2, 0, /* $10 */
+    /* $20 */  1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 2, 2, 2, 0, /* $20 */
+    /* $30 */  1, 1, 1, 0, 1, 1, 1, 0, 1, 2, 1, 0, 2, 2, 2, 0, /* $30 */
+    /* $40 */  1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 2, 2, 2, 0, /* $40 */
+    /* $50 */  1, 1, 1, 0, 1, 1, 1, 0, 1, 2, 1, 0, 2, 2, 2, 0, /* $50 */
+    /* $60 */  1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 2, 2, 2, 0, /* $60 */
+    /* $70 */  1, 1, 1, 0, 1, 1, 1, 0, 1, 2, 1, 0, 2, 2, 2, 0, /* $70 */
+    /* $80 */  1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 2, 2, 2, 0, /* $80 */
+    /* $90 */  1, 1, 1, 0, 1, 1, 1, 0, 1, 2, 1, 0, 2, 2, 2, 0, /* $90 */ 
+    /* $A0 */  1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 2, 2, 2, 0, /* $A0 */
+    /* $B0 */  1, 1, 1, 0, 1, 1, 1, 0, 1, 2, 1, 0, 2, 2, 2, 0, /* $B0 */
+    /* $C0 */  1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 2, 2, 2, 2, 0, /* $C0 */
+    /* $D0 */  1, 1, 1, 0, 1, 1, 1, 0, 1, 2, 1, 2, 2, 2, 2, 0, /* $D0 */
+    /* $E0 */  1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 2, 2, 2, 0, /* $E0 */
+    /* $F0 */  1, 1, 1, 0, 1, 1, 1, 0, 1, 2, 1, 0, 2, 2, 2, 0  /* $F0 */
+};
+
+#if !defined WORDS_BIGENDIAN && defined ALLOW_UNALIGNED_ACCESS
+
+#define opcode_t DWORD
+
+#define FETCH_OPCODE(o)                                        \
+    do {                                                       \
+        if (((int)reg_pc) < bank_limit) {                      \
+            o = (*((DWORD *)(bank_base + reg_pc)) & 0xffffff); \
+            CLK_ADD(CLK, CYCLES_1);                            \
+            if (fetch_tab[o & 0xff]) {                         \
+                CLK_ADD(CLK, fetch_tab[o & 0xff]);             \
+            }                                                  \
+        } else {                                               \
+            o = LOAD(reg_pc);                                  \
+            CLK_ADD(CLK, CYCLES_1);                            \
+            if (fetch_tab[o & 0xff]) {                         \
+                o |= LOAD(reg_pc + 1) << 8;                    \
+                CLK_ADD(CLK, CYCLES_1);                        \
+                if (fetch_tab[o & 0xff] - 1) {                 \
+                    o |= (LOAD(reg_pc + 2) << 16);             \
+                    CLK_ADD(CLK, CYCLES_1);                    \
+                }                                              \
+            }                                                  \
+        }                                                      \
+    } while (0)
+
+#define p0 (opcode & 0xff)
+#define p1 ((opcode >> 8) & 0xff)
+#define p2 (opcode >> 8)
+
+#else /* WORDS_BIGENDIAN || !ALLOW_UNALIGNED_ACCESS */
+
+#define opcode_t         \
+    struct {             \
+        BYTE ins;        \
+        union {          \
+            BYTE op8[2]; \
+            WORD op16;   \
+        } op;            \
+    }
+
+#define FETCH_OPCODE(o)                                                                   \
+    do {                                                                                  \
+        if (((int)reg_pc) < bank_limit) {                                                 \
+            (o).ins = *(bank_base + reg_pc);                                              \
+            (o).op.op16 = (*(bank_base + reg_pc + 1) | (*(bank_base + reg_pc + 2) << 8)); \
+            CLK_ADD(CLK, CYCLES_1);                                                       \
+            if (fetch_tab[(o).ins]) {                                                     \
+                CLK_ADD(CLK, fetch_tab[(o).ins]);                                         \
+            }                                                                             \
+        } else {                                                                          \
+            (o).ins = LOAD(reg_pc);                                                       \
+            CLK_ADD(CLK, CYCLES_1);                                                       \
+            if (fetch_tab[(o).ins]) {                                                     \
+                (o).op.op16 = LOAD(reg_pc + 1);                                           \
+                CLK_ADD(CLK, CYCLES_1);                                                   \
+                if (fetch_tab[(o).ins - 1]) {                                             \
+                    (o).op.op16 |= (LOAD(reg_pc + 2) << 8);                               \
+                    CLK_ADD(CLK, CYCLES_1);                                               \
+                }                                                                         \
+            }                                                                             \
+        }                                                                                 \
+    } while (0)
+
+#define p0 (opcode.ins)
+#define p2 (opcode.op.op16)
+
+#ifdef WORDS_BIGENDIAN
+#  define p1 (opcode.op.op8[1])
+#else
+#  define p1 (opcode.op.op8[0])
+#endif
+
+#endif /* !WORDS_BIGENDIAN */
+
+/*  SET_OPCODE for traps */
+#if !defined WORDS_BIGENDIAN && defined ALLOW_UNALIGNED_ACCESS
+#define SET_OPCODE(o) (opcode) = o;
+#else
+#if !defined WORDS_BIGENDIAN
+#define SET_OPCODE(o)                          \
+    do {                                       \
+        opcode.ins = (o) & 0xff;               \
+        opcode.op.op8[0] = ((o) >> 8) & 0xff;  \
+        opcode.op.op8[1] = ((o) >> 16) & 0xff; \
+    } while (0)
+#else
+#define SET_OPCODE(o)                          \
+    do {                                       \
+        opcode.ins = (o) & 0xff;               \
+        opcode.op.op8[1] = ((o) >> 8) & 0xff;  \
+        opcode.op.op8[0] = ((o) >> 16) & 0xff; \
+    } while (0)
+#endif
+#endif
+
+/* ------------------------------------------------------------------------ */
+
+/* Here, the CPU is emulated. */
+
+{
+    CPU_DELAY_CLK;
+
+    PROCESS_ALARMS;
+
+    {
+        enum cpu_int pending_interrupt;
+
+        if (!(CPU_INT_STATUS->global_pending_int & IK_IRQ)
+            && (CPU_INT_STATUS->global_pending_int & IK_IRQPEND)
+            && CPU_INT_STATUS->irq_pending_clk <= CLK) {
+            interrupt_ack_irq(CPU_INT_STATUS);
+        }
+
+        pending_interrupt = (cpu_int)CPU_INT_STATUS->global_pending_int;
+        if (pending_interrupt != IK_NONE) {
+            DO_INTERRUPT(pending_interrupt);
+            if (!(CPU_INT_STATUS->global_pending_int & IK_IRQ)
+                && CPU_INT_STATUS->global_pending_int & IK_IRQPEND) {
+                CPU_INT_STATUS->global_pending_int &= ~IK_IRQPEND;
+            }
+            CPU_DELAY_CLK
+
+                PROCESS_ALARMS                                        \
+        }
+    }
+
+    {
+        opcode_t opcode;
+#ifdef DEBUG
+        CLOCK debug_clk;
+#ifdef DRIVE_CPU
+        debug_clk = CLK;
+#else
+        debug_clk = maincpu_clk;
+#endif
+#endif
+
+#ifdef FEATURE_CPUMEMHISTORY
+#ifndef DRIVE_CPU
+        memmap_state |= (MEMMAP_STATE_INSTR | MEMMAP_STATE_OPCODE);
+#endif
+#endif
+        SET_LAST_ADDR(reg_pc);
+        FETCH_OPCODE(opcode);
+
+#ifdef FEATURE_CPUMEMHISTORY
+#ifndef DRIVE_CPU
+        /* HACK to cope with FETCH_OPCODE optimization in x64 */
+        if (((int)reg_pc) < bank_limit) {
+            memmap_mem_read(reg_pc);
+        }
+#endif
+        if (p0 == 0x20) {
+            monitor_cpuhistory_store(reg_pc, p0, p1, LOAD(reg_pc + 2), reg_a, reg_x, reg_y, reg_sp, LOCAL_STATUS());
+        } else {
+            monitor_cpuhistory_store(reg_pc, p0, p1, p2 >> 8, reg_a, reg_x, reg_y, reg_sp, LOCAL_STATUS());
+        }
+        memmap_state &= ~(MEMMAP_STATE_INSTR | MEMMAP_STATE_OPCODE);
+#endif
+
+#ifdef DEBUG
+#ifdef DRIVE_CPU
+        if (TRACEFLG) {
+            BYTE op = (BYTE)(p0);
+            BYTE lo = (BYTE)(p1);
+            BYTE hi = (BYTE)(p2 >> 8);
+
+            debug_drive((DWORD)(reg_pc), debug_clk,
+                        mon_disassemble_to_string(e_disk8_space,
+                                                  reg_pc, op,
+                                                  lo, hi, 0, 1, "R65(SC)02"),
+                        reg_a, reg_x, reg_y, reg_sp, drv->mynumber + 8);
+        }
+#else
+        if (TRACEFLG) {
+            BYTE op = (BYTE)(p0);
+            BYTE lo = (BYTE)(p1);
+            BYTE hi = (BYTE)(p2 >> 8);
+
+            if (op == 0x20) {
+                hi = LOAD(reg_pc + 2);
+            }
+
+            debug_maincpu((DWORD)(reg_pc), debug_clk,
+                          mon_disassemble_to_string(e_comp_space,
+                                                    reg_pc, op,
+                                                    lo, hi, 0, 1, "65(SC)02"),
+                          reg_a, reg_x, reg_y, reg_sp);
+        }
+        if (debug.perform_break_into_monitor) {
+            monitor_startup_trap();
+            debug.perform_break_into_monitor = 0;
+        }
+#endif
+#endif
+
+trap_skipped:
+        SET_LAST_OPCODE(p0);
+
+        switch (p0) {
+            default:            /* 1 byte, 1 cycle NOP */
+                NOOP_IMM(SIZE_1);
+                break;
+
+            case 0x22:          /* NOP #$nn */
+            case 0x42:          /* NOP #$nn */
+            case 0x62:          /* NOP #$nn */
+            case 0x82:          /* NOP #$nn */
+            case 0xc2:          /* NOP #$nn */
+            case 0xe2:          /* NOP #$nn */
+                NOOP_IMM(SIZE_2);
+                break;
+
+            case 0x44:          /* NOP $nn */
+                NOOP_ZP();
+                break;
+
+            case 0x54:          /* NOP $nn,X */
+            case 0xd4:          /* NOP $nn,X */
+            case 0xf4:          /* NOP $nn,X */
+                NOOP_ZP_X();
+                break;
+
+            case 0xdc:          /* NOP $nnnn */
+            case 0xfc:          /* NOP $nnnn */
+                NOOP_ABS();
+                break;
+
+            case 0x5c:          /* NOP $nnnn + 4 (FIXME: correct ??) */
+                NOOP_5C();
+                break;
+
+            case 0x00:          /* BRK */
+                BRK();
+                break;
+
+            case 0x01:          /* ORA ($nn,X) */
+                ORA(LOAD_IND_X(p1), CYCLES_1, SIZE_2);
+                break;
+
+            case 0x02:          /* NOP #$nn - also used for traps */
+                STATIC_ASSERT(TRAP_OPCODE == 0x02);
+                NOP_02();
+                break;
+
+            case 0x04:          /* TSB $nn */
+                TSB(p1, CYCLES_3, SIZE_2, LOAD_ZERO, STORE_ZERO);
+                break;
+
+            case 0x05:          /* ORA $nn */
+                ORA(LOAD_ZERO(p1), CYCLES_1, SIZE_2);
+                break;
+
+            case 0x06:          /* ASL $nn */
+                ASL(p1, CYCLES_3, SIZE_2, LOAD_ZERO, STORE_ZERO);
+                break;
+
+            case 0x07:          /* RMB0 $nn (65C02) / single byte, single cycle NOP (65SC02) */
+                RMB(BIT_0);
+                break;
+
+            case 0x08:          /* PHP */
+                PHP();
+                break;
+
+            case 0x09:          /* ORA #$nn */
+                ORA(p1, CYCLES_0, SIZE_2);
+                break;
+
+            case 0x0a:          /* ASL A */
+                ASL_A();
+                break;
+
+            case 0x0c:          /* TSB $nnnn */
+                TSB(p2, CYCLES_1, SIZE_3, LOAD_ABS, STORE_ABS_RRW);
+                break;
+
+            case 0x0d:          /* ORA $nnnn */
+                ORA(LOAD(p2), CYCLES_1, SIZE_3);
+                break;
+
+            case 0x0e:          /* ASL $nnnn */
+                ASL(p2, CYCLES_1, SIZE_3, LOAD_ABS, STORE_ABS_RRW);
+                break;
+
+            case 0x0f:          /* BBR0 $nn,$nnnn (65C02) / single byte, single cycle NOP (65SC02) */
+                BBR(BIT_0);
+                break;
+
+            case 0x10:          /* BPL $nnnn */
+                BRANCH(!LOCAL_SIGN(), p1);
+                break;
+
+            case 0x11:          /* ORA ($nn),Y */
+                ORA(LOAD_IND_Y(p1), CYCLES_1, SIZE_2);
+                break;
+
+            case 0x12:          /* ORA ($nn) */
+                ORA(LOAD_INDIRECT(p1), CYCLES_1, SIZE_2);
+                break;
+
+            case 0x14:          /* TRB $nn */
+                TRB(p1, CYCLES_3, SIZE_2, LOAD_ZERO, STORE_ZERO);
+                break;
+
+            case 0x15:          /* ORA $nn,X */
+                ORA(LOAD_ZERO_X(p1), CYCLES_2, SIZE_2);
+                break;
+
+            case 0x16:          /* ASL $nn,X */
+                ASL((p1 + reg_x) & 0xff, CYCLES_4, SIZE_2, LOAD_ZERO, STORE_ZERO);
+                break;
+
+            case 0x17:          /* RMB1 $nn (65C02) / single byte, single cycle NOP (65SC02) */
+                RMB(BIT_1);
+                break;
+
+            case 0x18:          /* CLC */
+                CLC();
+                break;
+
+            case 0x19:          /* ORA $nnnn,Y */
+                ORA(LOAD_ABS_Y(p2), CYCLES_1, SIZE_3);
+                break;
+
+            case 0x1a:          /* INA */
+                INA();
+                break;
+
+            case 0x1c:          /* TRB $nnnn */
+                TRB(p2, CYCLES_1, SIZE_3, LOAD_ABS, STORE_ABS_RRW);
+                break;
+
+            case 0x1d:          /* ORA $nnnn,X */
+                ORA(LOAD_ABS_X(p2), CYCLES_1, SIZE_3);
+                break;
+
+            case 0x1e:          /* ASL $nnnn,X */
+                ASL(p2, CYCLES_1, SIZE_3, LOAD_ABS_X, STORE_ABS_X_RRW);
+                break;
+
+            case 0x1f:          /* BBR1 $nn,$nnnn (65C02) / single byte, single cycle NOP (65SC02) */
+                BBR(BIT_1);
+                break;
+
+            case 0x20:          /* JSR $nnnn */
+                JSR();
+                break;
+
+            case 0x21:          /* AND ($nn,X) */
+                AND(LOAD_IND_X(p1), CYCLES_1, SIZE_2);
+                break;
+
+            case 0x24:          /* BIT $nn */
+                BIT(LOAD_ZERO(p1), CYCLES_1, SIZE_2);
+                break;
+
+            case 0x25:          /* AND $nn */
+                AND(LOAD_ZERO(p1), CYCLES_1, SIZE_2);
+                break;
+
+            case 0x26:          /* ROL $nn */
+                ROL(p1, CYCLES_3, SIZE_2, LOAD_ZERO, STORE_ZERO);
+                break;
+
+            case 0x27:          /* RMB2 $nn (65C02) / single byte, single cycle NOP (65SC02) */
+                RMB(BIT_2);
+                break;
+
+            case 0x28:          /* PLP */
+                PLP();
+                break;
+
+            case 0x29:          /* AND #$nn */
+                AND(p1, CYCLES_0, SIZE_2);
+                break;
+
+            case 0x2a:          /* ROL A */
+                ROL_A();
+                break;
+
+            case 0x2c:          /* BIT $nnnn */
+                BIT(LOAD(p2), CYCLES_1, SIZE_3);
+                break;
+
+            case 0x2d:          /* AND $nnnn */
+                AND(LOAD(p2), CYCLES_1, SIZE_3);
+                break;
+
+            case 0x2e:          /* ROL $nnnn */
+                ROL(p2, CYCLES_1, SIZE_3, LOAD_ABS, STORE_ABS_RRW);
+                break;
+
+            case 0x2f:          /* BBR2 $nn,$nnnn (65C02) / single byte, single cycle NOP (65SC02) */
+                BBR(BIT_2);
+                break;
+
+            case 0x30:          /* BMI $nnnn */
+                BRANCH(LOCAL_SIGN(), p1);
+                break;
+
+            case 0x31:          /* AND ($nn),Y */
+                AND(LOAD_IND_Y(p1), CYCLES_1, SIZE_2);
+                break;
+
+            case 0x32:          /* AND ($nn) */
+                AND(LOAD_INDIRECT(p1), CYCLES_1, SIZE_2);
+                break;
+
+            case 0x34:          /* BIT $nn,X */
+                BIT(LOAD_ZERO_X(p1), CYCLES_2, SIZE_2);
+                break;
+
+            case 0x35:          /* AND $nn,X */
+                AND(LOAD_ZERO_X(p1), CYCLES_2, SIZE_2);
+                break;
+
+            case 0x36:          /* ROL $nn,X */
+                ROL((p1 + reg_x) & 0xff, CYCLES_4, SIZE_2, LOAD_ZERO, STORE_ZERO);
+                break;
+
+            case 0x37:          /* RMB3 $nn (65C02) / single byte, single cycle NOP (65SC02) */
+                RMB(BIT_3);
+                break;
+
+            case 0x38:          /* SEC */
+                SEC();
+                break;
+
+            case 0x39:          /* AND $nnnn,Y */
+                AND(LOAD_ABS_Y(p2), CYCLES_1, SIZE_3);
+                break;
+
+            case 0x3a:          /* DEA */
+                DEA();
+                break;
+
+            case 0x3c:          /* BIT $nnnn,X */
+                BIT(LOAD_ABS_X(p2), CYCLES_1, SIZE_3);
+                break;
+
+            case 0x3d:          /* AND $nnnn,X */
+                AND(LOAD_ABS_X(p2), CYCLES_1, SIZE_3);
+                break;
+
+            case 0x3e:          /* ROL $nnnn,X */
+                ROL(p2, CYCLES_1, SIZE_3, LOAD_ABS_X, STORE_ABS_X_RRW);
+                break;
+
+            case 0x3f:          /* BBR3 $nn,$nnnn (65C02) / single byte, single cycle NOP (65SC02) */
+                BBR(BIT_3);
+                break;
+
+            case 0x40:          /* RTI */
+                RTI();
+                break;
+
+            case 0x41:          /* EOR ($nn,X) */
+                EOR(LOAD_IND_X(p1), CYCLES_1, SIZE_2);
+                break;
+
+            case 0x45:          /* EOR $nn */
+                EOR(LOAD_ZERO(p1), CYCLES_1, SIZE_2);
+                break;
+
+            case 0x46:          /* LSR $nn */
+                LSR(p1, CYCLES_3, SIZE_2, LOAD_ZERO, STORE_ZERO);
+                break;
+
+            case 0x47:          /* RMB4 $nn (65C02) / single byte, single cycle NOP (65SC02) */
+                RMB(BIT_4);
+                break;
+
+            case 0x48:          /* PHA */
+                PHA();
+                break;
+
+            case 0x49:          /* EOR #$nn */
+                EOR(p1, CYCLES_0, SIZE_2);
+                break;
+
+            case 0x4a:          /* LSR A */
+                LSR_A();
+                break;
+
+            case 0x4c:          /* JMP $nnnn */
+                JMP(p2);
+                break;
+
+            case 0x4d:          /* EOR $nnnn */
+                EOR(LOAD(p2), CYCLES_1, SIZE_3);
+                break;
+
+            case 0x4e:          /* LSR $nnnn */
+                LSR(p2, CYCLES_1, SIZE_3, LOAD_ABS, STORE_ABS_RRW);
+                break;
+
+            case 0x4f:          /* BBR4 $nn,$nnnn (65C02) / single byte, single cycle NOP (65SC02) */
+                BBR(BIT_4);
+                break;
+
+            case 0x50:          /* BVC $nnnn */
+                BRANCH(!LOCAL_OVERFLOW(), p1);
+                break;
+
+            case 0x51:          /* EOR ($nn),Y */
+                EOR(LOAD_IND_Y(p1), CYCLES_1, SIZE_2);
+                break;
+
+            case 0x52:          /* EOR ($nn) */
+                EOR(LOAD_INDIRECT(p1), CYCLES_1, SIZE_2);
+                break;
+
+            case 0x55:          /* EOR $nn,X */
+                EOR(LOAD_ZERO_X(p1), CYCLES_2, SIZE_2);
+                break;
+
+            case 0x56:          /* LSR $nn,X */
+                LSR((p1 + reg_x) & 0xff, CYCLES_4, SIZE_2, LOAD_ZERO, STORE_ZERO);
+                break;
+
+            case 0x57:          /* RMB5 $nn (65C02) / single byte, single cycle NOP (65SC02) */
+                RMB(BIT_5);
+                break;
+
+            case 0x58:          /* CLI */
+                CLI();
+                break;
+
+            case 0x59:          /* EOR $nnnn,Y */
+                EOR(LOAD_ABS_Y(p2), CYCLES_1, SIZE_3);
+                break;
+
+            case 0x5a:          /* PHY */
+                PHY();
+                break;
+
+            case 0x5d:          /* EOR $nnnn,X */
+                EOR(LOAD_ABS_X(p2), CYCLES_1, SIZE_3);
+                break;
+
+            case 0x5e:          /* LSR $nnnn,X */
+                LSR(p2, CYCLES_1, SIZE_3, LOAD_ABS_X, STORE_ABS_X_RRW);
+                break;
+
+            case 0x5f:          /* BBR5 $nn,$nnnn (65C02) / single byte, single cycle NOP (65SC02) */
+                BBR(BIT_5);
+                break;
+
+            case 0x60:          /* RTS */
+                RTS();
+                break;
+
+            case 0x61:          /* ADC ($nn,X) */
+                ADC(LOAD_IND_X(p1), CYCLES_1, SIZE_2);
+                break;
+
+            case 0x64:          /* STZ $nn */
+                STZ_ZERO(p1, CYCLES_1, SIZE_2);
+                break;
+
+            case 0x65:          /* ADC $nn */
+                ADC(LOAD_ZERO(p1), CYCLES_1, SIZE_2);
+                break;
+
+            case 0x66:          /* ROR $nn */
+                ROR(p1, CYCLES_3, SIZE_2, LOAD_ZERO, STORE_ZERO);
+                break;
+
+            case 0x67:          /* RMB6 $nn (65C02) / single byte, single cycle NOP (65SC02) */
+                RMB(BIT_6);
+                break;
+
+            case 0x68:          /* PLA */
+                PLA();
+                break;
+
+            case 0x69:          /* ADC #$nn */
+                ADC(p1, CYCLES_0, SIZE_2);
+                break;
+
+            case 0x6a:          /* ROR A */
+                ROR_A();
+                break;
+
+            case 0x6c:          /* JMP ($nnnn) */
+                JMP_IND();
+                break;
+
+            case 0x6d:          /* ADC $nnnn */
+                ADC(LOAD(p2), CYCLES_1, SIZE_3);
+                break;
+
+            case 0x6e:          /* ROR $nnnn */
+                ROR(p2, CYCLES_1, SIZE_3, LOAD_ABS, STORE_ABS_RRW);
+                break;
+
+            case 0x6f:          /* BBR6 $nn,$nnnn (65C02) / single byte, single cycle NOP (65SC02) */
+                BBR(BIT_6);
+                break;
+
+            case 0x70:          /* BVS $nnnn */
+                BRANCH(LOCAL_OVERFLOW(), p1);
+                break;
+
+            case 0x71:          /* ADC ($nn),Y */
+                ADC(LOAD_IND_Y(p1), CYCLES_1, SIZE_2);
+                break;
+
+            case 0x72:          /* ADC ($nn) */
+                ADC(LOAD_INDIRECT(p1), CYCLES_1, SIZE_2);
+                break;
+
+            case 0x74:          /* STZ $nn,X */
+                STZ_ZERO(p1 + reg_x, CYCLES_2, SIZE_2);
+                break;
+
+            case 0x75:          /* ADC $nn,X */
+                ADC(LOAD_ZERO_X(p1), CYCLES_2, SIZE_2);
+                break;
+
+            case 0x76:          /* ROR $nn,X */
+                ROR((p1 + reg_x) & 0xff, CYCLES_4, SIZE_2, LOAD_ZERO, STORE_ZERO);
+                break;
+
+            case 0x77:          /* RMB7 $nn (65C02) / single byte, single cycle NOP (65SC02) */
+                RMB(BIT_7);
+                break;
+
+            case 0x78:          /* SEI */
+                SEI();
+                break;
+
+            case 0x79:          /* ADC $nnnn,Y */
+                ADC(LOAD_ABS_Y(p2), CYCLES_1, SIZE_3);
+                break;
+
+            case 0x7a:          /* PLY */
+                PLY();
+                break;
+
+            case 0x7c:          /* JMP ($nnnn,X) */
+                JMP_IND_X();
+                break;
+
+            case 0x7d:          /* ADC $nnnn,X */
+                ADC(LOAD_ABS_X(p2), CYCLES_1, SIZE_3);
+                break;
+
+            case 0x7e:          /* ROR $nnnn,X */
+                ROR(p2, CYCLES_1, SIZE_3, LOAD_ABS_X, STORE_ABS_X_RRW);
+                break;
+
+            case 0x7f:          /* BBR7 $nn,$nnnn (65C02) / single byte, single cycle NOP (65SC02) */
+                BBR(BIT_7);
+                break;
+
+            case 0x80:          /* BRA $nnnn */
+                BRANCH(1, p1);
+                break;
+
+            case 0x81:          /* STA ($nn,X) */
+                STA(LOAD_ZERO_ADDR(p1 + reg_x), CYCLES_3, CYCLES_1, SIZE_2, STORE_ABS);
+                break;
+
+            case 0x84:          /* STY $nn */
+                STY_ZERO(p1, CYCLES_1, SIZE_2);
+                break;
+
+            case 0x85:          /* STA $nn */
+                STA_ZERO(p1, CYCLES_1, SIZE_2);
+                break;
+
+            case 0x86:          /* STX $nn */
+                STX_ZERO(p1, CYCLES_1, SIZE_2);
+                break;
+
+            case 0x87:          /* SMB0 $nn (65C02) / single byte, single cycle NOP (65SC02) */
+                SMB(BIT_0);
+                break;
+
+            case 0x88:          /* DEY */
+                DEY();
+                break;
+
+            case 0x89:          /* BIT #$nn */
+                BIT_IMM(p1);
+                break;
+
+            case 0x8a:          /* TXA */
+                TXA();
+                break;
+
+            case 0x8c:          /* STY $nnnn */
+                STY(p2);
+                break;
+
+            case 0x8d:          /* STA $nnnn */
+                STA(p2, CYCLES_0, CYCLES_1, SIZE_3, STORE_ABS);
+                break;
+
+            case 0x8e:          /* STX $nnnn */
+                STX(p2);
+                break;
+
+            case 0x8f:          /* BBS0 $nn,$nnnn (65C02) / single byte, single cycle NOP (65SC02) */
+                BBS(BIT_0);
+                break;
+
+            case 0x90:          /* BCC $nnnn */
+                BRANCH(!LOCAL_CARRY(), p1);
+                break;
+
+            case 0x91:          /* STA ($nn),Y */
+                STA_IND_Y(p1);
+                break;
+
+            case 0x92:          /* STA ($nn) */
+                STA(LOAD_ZERO_ADDR(p1), CYCLES_2, CYCLES_1, SIZE_2, STORE_ABS);
+                break;
+
+            case 0x94:          /* STY $nn,X */
+                STY_ZERO(p1 + reg_x, CYCLES_2, SIZE_2);
+                break;
+
+            case 0x95:          /* STA $nn,X */
+                STA_ZERO(p1 + reg_x, CYCLES_2, SIZE_2);
+                break;
+
+            case 0x96:          /* STX $nn,Y */
+                STX_ZERO(p1 + reg_y, CYCLES_2, SIZE_2);
+                break;
+
+            case 0x97:          /* SMB1 $nn (65C02) / single byte, single cycle NOP (65SC02) */
+                SMB(BIT_1);
+                break;
+
+            case 0x98:          /* TYA */
+                TYA();
+                break;
+
+            case 0x99:          /* STA $nnnn,Y */
+                STA(p2, CYCLES_0, CYCLES_0, SIZE_3, STORE_ABS_Y);
+                break;
+
+            case 0x9a:          /* TXS */
+                TXS();
+                break;
+
+            case 0x9c:          /* STZ $nnnn */
+                STZ(p2, CYCLES_1, SIZE_3, STORE_ABS);
+                break;
+
+            case 0x9d:          /* STA $nnnn,X */
+                STA(p2, CYCLES_0, CYCLES_0, SIZE_3, STORE_ABS_X);
+                break;
+
+            case 0x9e:          /* STZ $nnnn,X */
+                STZ(p2, CYCLES_0, SIZE_3, STORE_ABS_X);
+                break;
+
+            case 0x9f:          /* BBS1 $nn,$nnnn (65C02) / single byte, single cycle NOP (65SC02) */
+                BBS(BIT_1);
+                break;
+
+            case 0xa0:          /* LDY #$nn */
+                LDY(p1, CYCLES_0, SIZE_2);
+                break;
+
+            case 0xa1:          /* LDA ($nn,X) */
+                LDA(LOAD_IND_X(p1), CYCLES_1, SIZE_2);
+                break;
+
+            case 0xa2:          /* LDX #$nn */
+                LDX(p1, CYCLES_0, SIZE_2);
+                break;
+
+            case 0xa4:          /* LDY $nn */
+                LDY(LOAD_ZERO(p1), CYCLES_1, SIZE_2);
+                break;
+
+            case 0xa5:          /* LDA $nn */
+                LDA(LOAD_ZERO(p1), CYCLES_1, SIZE_2);
+                break;
+
+            case 0xa6:          /* LDX $nn */
+                LDX(LOAD_ZERO(p1), CYCLES_1, SIZE_2);
+                break;
+
+            case 0xa7:          /* SMB2 $nn (65C02) / single byte, single cycle NOP (65SC02) */
+                SMB(BIT_2);
+                break;
+
+            case 0xa8:          /* TAY */
+                TAY();
+                break;
+
+            case 0xa9:          /* LDA #$nn */
+                LDA(p1, CYCLES_0, SIZE_2);
+                break;
+
+            case 0xaa:          /* TAX */
+                TAX();
+                break;
+
+            case 0xac:          /* LDY $nnnn */
+                LDY(LOAD(p2), CYCLES_1, SIZE_3);
+                break;
+
+            case 0xad:          /* LDA $nnnn */
+                LDA(LOAD(p2), CYCLES_1, SIZE_3);
+                break;
+
+            case 0xae:          /* LDX $nnnn */
+                LDX(LOAD(p2), CYCLES_1, SIZE_3);
+                break;
+
+            case 0xaf:          /* BBS2 $nn,$nnnn (65C02) / single byte, single cycle NOP (65SC02) */
+                BBS(BIT_2);
+                break;
+
+            case 0xb0:          /* BCS $nnnn */
+                BRANCH(LOCAL_CARRY(), p1);
+                break;
+
+            case 0xb1:          /* LDA ($nn),Y */
+                LDA(LOAD_IND_Y_BANK(p1), CYCLES_1, SIZE_2);
+                break;
+
+            case 0xb2:          /* LDA ($nn) */
+                LDA(LOAD_INDIRECT(p1), CYCLES_1, SIZE_2);
+                break;
+
+            case 0xb4:          /* LDY $nn,X */
+                LDY(LOAD_ZERO_X(p1), CYCLES_2, SIZE_2);
+                break;
+
+            case 0xb5:          /* LDA $nn,X */
+                LDA(LOAD_ZERO_X(p1), CYCLES_2, SIZE_2);
+                break;
+
+            case 0xb6:          /* LDX $nn,Y */
+                LDX(LOAD_ZERO_Y(p1), CYCLES_2, SIZE_2);
+                break;
+
+            case 0xb7:          /* SMB3 $nn (65C02) / single byte, single cycle NOP (65SC02) */
+                SMB(BIT_3);
+                break;
+
+            case 0xb8:          /* CLV */
+                CLV();
+                break;
+
+            case 0xb9:          /* LDA $nnnn,Y */
+                LDA(LOAD_ABS_Y(p2), CYCLES_1, SIZE_3);
+                break;
+
+            case 0xba:          /* TSX */
+                TSX();
+                break;
+
+            case 0xbc:          /* LDY $nnnn,X */
+                LDY(LOAD_ABS_X(p2), CYCLES_1, SIZE_3);
+                break;
+
+            case 0xbd:          /* LDA $nnnn,X */
+                LDA(LOAD_ABS_X(p2), CYCLES_1, SIZE_3);
+                break;
+
+            case 0xbe:          /* LDX $nnnn,Y */
+                LDX(LOAD_ABS_Y(p2), CYCLES_1, SIZE_3);
+                break;
+
+            case 0xbf:          /* BBS3 $nn,$nnnn (65C02) / single byte, single cycle NOP (65SC02) */
+                BBS(BIT_3);
+                break;
+
+            case 0xc0:          /* CPY #$nn */
+                CPY(p1, CYCLES_0, SIZE_2);
+                break;
+
+            case 0xc1:          /* CMP ($nn,X) */
+                CMP(LOAD_IND_X(p1), CYCLES_1, SIZE_2);
+                break;
+
+            case 0xc4:          /* CPY $nn */
+                CPY(LOAD_ZERO(p1), CYCLES_1, SIZE_2);
+                break;
+
+            case 0xc5:          /* CMP $nn */
+                CMP(LOAD_ZERO(p1), CYCLES_1, SIZE_2);
+                break;
+
+            case 0xc6:          /* DEC $nn */
+                DEC(p1, CYCLES_3, SIZE_2, LOAD_ZERO, STORE_ZERO);
+                break;
+
+            case 0xc7:          /* SMB4 $nn (65C02) / single byte, single cycle NOP (65SC02) */
+                SMB(BIT_4);
+                break;
+
+            case 0xc8:          /* INY */
+                INY();
+                break;
+
+            case 0xc9:          /* CMP #$nn */
+                CMP(p1, CYCLES_0, SIZE_2);
+                break;
+
+            case 0xca:          /* DEX */
+                DEX();
+                break;
+
+            case 0xcb:          /* WAI (WDC65C02) / single byte, single cycle NOP (R65C02/65SC02) */
+                WAI();
+                break;
+
+            case 0xcc:          /* CPY $nnnn */
+                CPY(LOAD(p2), CYCLES_1, SIZE_3);
+                break;
+
+            case 0xcd:          /* CMP $nnnn */
+                CMP(LOAD(p2), CYCLES_1, SIZE_3);
+                break;
+
+            case 0xce:          /* DEC $nnnn */
+                DEC(p2, CYCLES_1, SIZE_3, LOAD_ABS, STORE_ABS_RRW);
+                break;
+
+            case 0xcf:          /* BBS4 $nn,$nnnn (65C02) / single byte, single cycle NOP (65SC02) */
+                BBS(BIT_4);
+                break;
+
+            case 0xd0:          /* BNE $nnnn */
+                BRANCH(!LOCAL_ZERO(), p1);
+                break;
+
+            case 0xd1:          /* CMP ($nn),Y */
+                CMP(LOAD_IND_Y(p1), CYCLES_1, SIZE_2);
+                break;
+
+            case 0xd2:          /* CMP ($nn) */
+                CMP(LOAD_INDIRECT(p1), CYCLES_1, SIZE_2);
+                break;
+
+            case 0xd5:          /* CMP $nn,X */
+                CMP(LOAD_ZERO_X(p1), CYCLES_2, SIZE_2);
+                break;
+
+            case 0xd6:          /* DEC $nn,X */
+                DEC((p1 + reg_x) & 0xff, CYCLES_4, SIZE_2, LOAD_ZERO, STORE_ZERO);
+                break;
+
+            case 0xd7:          /* SMB5 $nn (65C02) / single byte, single cycle NOP (65SC02) */
+                SMB(BIT_5);
+                break;
+
+            case 0xd8:          /* CLD */
+                CLD();
+                break;
+
+            case 0xd9:          /* CMP $nnnn,Y */
+                CMP(LOAD_ABS_Y(p2), CYCLES_1, SIZE_3);
+                break;
+
+            case 0xda:          /* PHX */
+                PHX();
+                break;
+
+            case 0xdb:          /* STP (WDC65C02) / single byte, single cycle NOP (R65C02/65SC02) */
+                STP();
+                break;
+
+            case 0xdd:          /* CMP $nnnn,X */
+                CMP(LOAD_ABS_X(p2), CYCLES_1, SIZE_3);
+                break;
+
+            case 0xde:          /* DEC $nnnn,X */
+                DEC(p2, CYCLES_1, SIZE_3, LOAD_ABS_X_RMW, STORE_ABS_X_RRW);
+                break;
+
+            case 0xdf:          /* BBS5 $nn,$nnnn (65C02) / single byte, single cycle NOP (65SC02) */
+                BBS(BIT_5);
+                break;
+
+            case 0xe0:          /* CPX #$nn */
+                CPX(p1, CYCLES_0, SIZE_2);
+                break;
+
+            case 0xe1:          /* SBC ($nn,X) */
+                SBC(LOAD_IND_X(p1), CYCLES_1, SIZE_2);
+                break;
+
+            case 0xe4:          /* CPX $nn */
+                CPX(LOAD_ZERO(p1), CYCLES_1, SIZE_2);
+                break;
+
+            case 0xe5:          /* SBC $nn */
+                SBC(LOAD_ZERO(p1), CYCLES_1, SIZE_2);
+                break;
+
+            case 0xe6:          /* INC $nn */
+                INC(p1, CYCLES_3, SIZE_2, LOAD_ZERO, STORE_ZERO);
+                break;
+
+            case 0xe7:          /* SMB6 $nn (65C02) / single byte, single cycle NOP (65SC02) */
+                SMB(BIT_6);
+                break;
+
+            case 0xe8:          /* INX */
+                INX();
+                break;
+
+            case 0xe9:          /* SBC #$nn */
+                SBC(p1, CYCLES_0, SIZE_2);
+                break;
+
+            case 0xea:          /* NOP */
+                NOP();
+                break;
+
+            case 0xec:          /* CPX $nnnn */
+                CPX(LOAD(p2), CYCLES_1, SIZE_3);
+                break;
+
+            case 0xed:          /* SBC $nnnn */
+                SBC(LOAD(p2), CYCLES_1, SIZE_3);
+                break;
+
+            case 0xee:          /* INC $nnnn */
+                INC(p2, CYCLES_1, SIZE_3, LOAD_ABS, STORE_ABS_RRW);
+                break;
+
+            case 0xef:          /* BBS6 $nn,$nnnn (65C02) / single byte, single cycle NOP (65SC02) */
+                BBS(BIT_6);
+                break;
+
+            case 0xf0:          /* BEQ $nnnn */
+                BRANCH(LOCAL_ZERO(), p1);
+                break;
+
+            case 0xf1:          /* SBC ($nn),Y */
+                SBC(LOAD_IND_Y(p1), CYCLES_1, SIZE_2);
+                break;
+
+            case 0xf2:          /* SBC ($nn) */
+                SBC(LOAD_INDIRECT(p1), CYCLES_1, SIZE_2);
+                break;
+
+            case 0xf5:          /* SBC $nn,X */
+                SBC(LOAD_ZERO_X(p1), CYCLES_2, SIZE_2);
+                break;
+
+            case 0xf6:          /* INC $nn,X */
+                INC((p1 + reg_x) & 0xff, CYCLES_4, SIZE_2, LOAD_ZERO, STORE_ZERO);
+                break;
+
+            case 0xf7:          /* SMB7 $nn (65C02) / single byte, single cycle NOP (65SC02) */
+                SMB(BIT_7);
+                break;
+
+            case 0xf8:          /* SED */
+                SED();
+                break;
+
+            case 0xf9:          /* SBC $nnnn,Y */
+                SBC(LOAD_ABS_Y(p2), CYCLES_1, SIZE_3);
+                break;
+
+            case 0xfa:          /* PLX */
+                PLX();
+                break;
+
+            case 0xfd:          /* SBC $nnnn,X */
+                SBC(LOAD_ABS_X(p2), CYCLES_1, SIZE_3);
+                break;
+
+            case 0xfe:          /* INC $nnnn,X */
+                INC(p2, CYCLES_1, SIZE_3, LOAD_ABS_X_RMW, STORE_ABS_X_RRW);
+                break;
+
+            case 0xff:          /* BBS7 $nn,$nnnn (65C02) / single byte, single cycle NOP (65SC02) */
+                BBS(BIT_7);
+                break;
+        }
+    }
+}
index 693ffb6531d6efedc55dd5a4f31c37fb339abfa9..a9bb9bfb774b1334a4b9243d42810c3a52cb5a7e 100644 (file)
@@ -9,6 +9,8 @@
 *
 */
 
+#define CDTVCR_4510_EMULATION 0
+
 #define CDTVCR_DEBUG 0
 
 #include "sysconfig.h"
@@ -1018,3 +1020,485 @@ void cdtvcr_free(void)
        thread_alive = 0;
        close_unit ();
 }
+
+#if CDTVCR_4510_EMULATION
+
+// VICE 65C02 emulator, waiting for future full CDTV-CR 4510 emulation.
+
+typedef unsigned char BYTE;
+typedef unsigned short WORD;
+typedef unsigned int CLOCK;
+
+static void cpu65c02_reset(void)
+{
+}
+
+#define CLOCK_MAX (~((CLOCK)0))
+#define TRAP_OPCODE 0x02
+#define STATIC_ASSERT(_x)
+
+#define NUM_MEMSPACES e_invalid_space
+
+enum mon_int {
+       MI_NONE = 0,
+       MI_BREAK = 1 << 0,
+       MI_WATCH = 1 << 1,
+       MI_STEP = 1 << 2
+};
+
+enum t_memspace {
+       e_default_space = 0,
+       e_comp_space,
+       e_disk8_space,
+       e_disk9_space,
+       e_disk10_space,
+       e_disk11_space,
+       e_invalid_space
+};
+typedef enum t_memspace MEMSPACE;
+static unsigned monitor_mask[NUM_MEMSPACES];
+static void monitor_check_icount_interrupt(void)
+{
+}
+static void monitor_check_icount(WORD a)
+{
+}
+static int monitor_force_import(int mem)
+{
+       return 0;
+}
+static int monitor_check_breakpoints(int mem, WORD addr)
+{
+       return 0;
+}
+static void monitor_check_watchpoints(unsigned int lastpc, unsigned int pc)
+{
+}
+static void monitor_startup(int mem)
+{
+}
+
+#define INTERRUPT_DELAY 2
+
+#define INTRRUPT_MAX_DMA_PER_OPCODE (7+10000)
+
+enum cpu_int {
+       IK_NONE = 0,
+       IK_NMI = 1 << 0,
+       IK_IRQ = 1 << 1,
+       IK_RESET = 1 << 2,
+       IK_TRAP = 1 << 3,
+       IK_MONITOR = 1 << 4,
+       IK_DMA = 1 << 5,
+       IK_IRQPEND = 1 << 6
+};
+
+struct interrupt_cpu_status_s {
+       /* Number of interrupt lines.  */
+       unsigned int num_ints;
+
+       /* Define, for each interrupt source, whether it has a pending interrupt
+       (IK_IRQ, IK_NMI, IK_RESET and IK_TRAP) or not (IK_NONE).  */
+       unsigned int *pending_int;
+
+       /* Name for each interrupt source */
+       char **int_name;
+
+       /* Number of active IRQ lines.  */
+       int nirq;
+
+       /* Tick when the IRQ was triggered.  */
+       CLOCK irq_clk;
+
+       /* Number of active NMI lines.  */
+       int nnmi;
+
+       /* Tick when the NMI was triggered.  */
+       CLOCK nmi_clk;
+
+       /* If an opcode is intercepted by a DMA, save the number of cycles
+       left at the start of this particular DMA (needed by *_set_irq() to
+       calculate irq_clk).  */
+       unsigned int num_dma_per_opcode;
+       unsigned int num_cycles_left[INTRRUPT_MAX_DMA_PER_OPCODE];
+       CLOCK dma_start_clk[INTRRUPT_MAX_DMA_PER_OPCODE];
+
+       /* counters for delay between interrupt request and handler */
+       unsigned int irq_delay_cycles;
+       unsigned int nmi_delay_cycles;
+
+       /* If 1, do a RESET.  */
+       int reset;
+
+       /* If 1, call the trapping function.  */
+       int trap;
+
+       /* Debugging function.  */
+       void(*trap_func)(WORD, void *data);
+
+       /* Data to pass to the debugging function when called.  */
+       void *trap_data;
+
+       /* Pointer to the last executed opcode information.  */
+       unsigned int *last_opcode_info_ptr;
+
+       /* Number of cycles we have stolen to the processor last time.  */
+       int num_last_stolen_cycles;
+
+       /* Clock tick at which these cycles have been stolen.  */
+       CLOCK last_stolen_cycles_clk;
+
+       /* Clock tick where just ACK'd IRQs may still trigger an interrupt.
+       Set to CLOCK_MAX when irrelevant.  */
+       CLOCK irq_pending_clk;
+
+       unsigned int global_pending_int;
+
+       void(*nmi_trap_func)(void);
+
+       void(*reset_trap_func)(void);
+};
+typedef struct interrupt_cpu_status_s interrupt_cpu_status_t;
+
+/* Masks to extract information. */
+#define OPINFO_DELAYS_INTERRUPT_MSK     (1 << 8)
+#define OPINFO_DISABLES_IRQ_MSK         (1 << 9)
+#define OPINFO_ENABLES_IRQ_MSK          (1 << 10)
+
+/* Return nonzero if `opinfo' causes a 1-cycle interrupt delay.  */
+#define OPINFO_DELAYS_INTERRUPT(opinfo)         \
+    ((opinfo) & OPINFO_DELAYS_INTERRUPT_MSK)
+
+/* Return nonzero if `opinfo' has changed the I flag from 0 to 1, so that an
+IRQ that happened 2 or more cycles before the end of the opcode should be
+allowed.  */
+#define OPINFO_DISABLES_IRQ(opinfo)             \
+    ((opinfo) & OPINFO_DISABLES_IRQ_MSK)
+
+/* Return nonzero if `opinfo' has changed the I flag from 1 to 0, so that an
+IRQ that happened 2 or more cycles before the end of the opcode should not
+be allowed.  */
+#define OPINFO_ENABLES_IRQ(opinfo)              \
+    ((opinfo) & OPINFO_ENABLES_IRQ_MSK)
+
+/* Set the information for `opinfo'.  `number' is the opcode number,
+`delays_interrupt' must be non-zero if it causes a 1-cycle interrupt
+delay, `disables_interrupts' must be non-zero if it disabled IRQs.  */
+#define OPINFO_SET(opinfo,                                                \
+                   number, delays_interrupt, disables_irq, enables_irq)   \
+    ((opinfo) = ((number)                                                 \
+                 | ((delays_interrupt) ? OPINFO_DELAYS_INTERRUPT_MSK : 0) \
+                 | ((disables_irq) ? OPINFO_DISABLES_IRQ_MSK : 0)         \
+                 | ((enables_irq) ? OPINFO_ENABLES_IRQ_MSK : 0)))
+
+/* Set whether the opcode causes the 1-cycle interrupt delay according to
+`delay'.  */
+#define OPINFO_SET_DELAYS_INTERRUPT(opinfo, delay)   \
+    do {                                             \
+        if ((delay))                                 \
+            (opinfo) |= OPINFO_DELAYS_INTERRUPT_MSK; \
+    } while (0)
+
+/* Set whether the opcode disables previously enabled IRQs according to
+`disable'.  */
+#define OPINFO_SET_DISABLES_IRQ(opinfo, disable) \
+    do {                                         \
+        if ((disable))                           \
+            (opinfo) |= OPINFO_DISABLES_IRQ_MSK; \
+    } while (0)
+
+/* Set whether the opcode enables previously disabled IRQs according to
+`enable'.  */
+#define OPINFO_SET_ENABLES_IRQ(opinfo, enable)  \
+    do {                                        \
+        if ((enable))                           \
+            (opinfo) |= OPINFO_ENABLES_IRQ_MSK; \
+    } while (0)
+
+
+
+typedef struct mos6510_regs_s {
+       unsigned int pc;        /* `unsigned int' required by the drive code. */
+       BYTE a;
+       BYTE x;
+       BYTE y;
+       BYTE sp;
+       BYTE p;
+       BYTE n;
+       BYTE z;
+} mos6510_regs_t;
+
+typedef struct R65C02_regs_s
+{
+       unsigned int pc;
+       BYTE a;
+       BYTE x;
+       BYTE y;
+       BYTE sp;
+       BYTE p;
+       BYTE n;
+       BYTE z;
+} R65C02_regs_t;
+
+#define DRIVE_RAM_SIZE 32768
+
+typedef BYTE drive_read_func_t(struct drive_context_s *, WORD);
+typedef void drive_store_func_t(struct drive_context_s *, WORD,
+       BYTE);
+
+typedef struct drivecpud_context_s {
+       /* Drive RAM */
+       BYTE drive_ram[DRIVE_RAM_SIZE];
+
+       /* functions */
+       drive_read_func_t  *read_func[0x101];
+       drive_store_func_t *store_func[0x101];
+//     drive_read_func_t  *read_func_watch[0x101];
+//     drive_store_func_t *store_func_watch[0x101];
+//     drive_read_func_t  *read_func_nowatch[0x101];
+//     drive_store_func_t *store_func_nowatch[0x101];
+
+       int sync_factor;
+} drivecpud_context_t;
+
+typedef struct drive_context_s {
+       int mynumber;         /* init to [0123] */
+       CLOCK *clk_ptr;       /* shortcut to drive_clk[mynumber] */
+
+       struct drivecpu_context_s *cpu;
+       struct drivecpud_context_s *cpud;
+       struct drivefunc_context_s *func;
+} drive_context_t;
+
+static int drive_trap_handler(drive_context_t *d)
+{
+       return -1;
+}
+
+typedef struct drivecpu_context_s
+{
+       int traceflg;
+       /* This is non-zero each time a Read-Modify-Write instructions that accesses
+       memory is executed.  We can emulate the RMW bug of the 6502 this way.  */
+       int rmw_flag; /* init to 0 */
+
+                                 /* Interrupt/alarm status.  */
+       struct interrupt_cpu_status_s *int_status;
+
+       struct alarm_context_s *alarm_context;
+
+       /* Clk guard.  */
+       struct clk_guard_s *clk_guard;
+
+       struct monitor_interface_s *monitor_interface;
+
+       /* Value of clk for the last time mydrive_cpu_execute() was called.  */
+       CLOCK last_clk;
+
+       /* Number of cycles in excess we executed last time mydrive_cpu_execute()
+       was called.  */
+       CLOCK last_exc_cycles;
+
+       CLOCK stop_clk;
+
+       CLOCK cycle_accum;
+       BYTE *d_bank_base;
+       unsigned int d_bank_start;
+       unsigned int d_bank_limit;
+
+       /* Information about the last executed opcode.  */
+       unsigned int last_opcode_info;
+
+       /* Address of the last executed opcode. This is used by watchpoints. */
+       unsigned int last_opcode_addr;
+
+       /* Public copy of the registers.  */
+       mos6510_regs_t cpu_regs;
+//     R65C02_regs_t cpu_R65C02_regs;
+
+       BYTE *pageone;        /* init to NULL */
+
+       int monspace;         /* init to e_disk[89]_space */
+
+       char *snap_module_name;
+
+       char *identification_string;
+} drivecpu_context_t;
+
+#define LOAD(a)           (drv->cpud->read_func[(a) >> 8](drv, (WORD)(a)))
+#define LOAD_ZERO(a)      (drv->cpud->read_func[0](drv, (WORD)(a)))
+#define LOAD_ADDR(a)      (LOAD(a) | (LOAD((a) + 1) << 8))
+#define LOAD_ZERO_ADDR(a) (LOAD_ZERO(a) | (LOAD_ZERO((a) + 1) << 8))
+#define STORE(a, b)       (drv->cpud->store_func[(a) >> 8](drv, (WORD)(a), \
+                          (BYTE)(b)))
+#define STORE_ZERO(a, b)  (drv->cpud->store_func[0](drv, (WORD)(a), \
+                          (BYTE)(b)))
+
+#define JUMP(addr)                                       \
+
+#define P_SIGN          0x80
+#define P_OVERFLOW      0x40
+#define P_UNUSED        0x20
+#define P_BREAK         0x10
+#define P_DECIMAL       0x08
+#define P_INTERRUPT     0x04
+#define P_ZERO          0x02
+#define P_CARRY         0x01
+
+#define CPU_WDC65C02   0
+#define CPU_R65C02     1
+#define CPU_65SC02     2
+
+#define CLK (*(drv->clk_ptr))
+#define RMW_FLAG (cpu->rmw_flag)
+#define PAGE_ONE (cpu->pageone)
+#define LAST_OPCODE_INFO (cpu->last_opcode_info)
+#define LAST_OPCODE_ADDR (cpu->last_opcode_addr)
+#define TRACEFLG (debug.drivecpu_traceflg[drv->mynumber])
+
+#define CPU_INT_STATUS (cpu->int_status)
+
+#define ALARM_CONTEXT (cpu->alarm_context)
+
+#define ROM_TRAP_ALLOWED() 1
+
+#define ROM_TRAP_HANDLER() drive_trap_handler(drv)
+
+#define CALLER (cpu->monspace)
+
+#define DMA_FUNC drive_generic_dma()
+
+#define DMA_ON_RESET
+
+#define cpu_reset() (cpu_reset)(drv)
+#define bank_limit (cpu->d_bank_limit)
+#define bank_start (cpu->d_bank_start)
+#define bank_base (cpu->d_bank_base)
+
+/* WDC_STP() and WDC_WAI() are not used on the R65C02. */
+#define WDC_STP()
+#define WDC_WAI()
+
+#define GLOBAL_REGS cpu->cpu_R65C02_regs
+
+#define DRIVE_CPU
+
+static void drive_generic_dma(void)
+{
+}
+static void interrupt_trigger_dma(interrupt_cpu_status_t *cs, CLOCK cpu_clk)
+{
+       cs->global_pending_int = (enum cpu_int)
+               (cs->global_pending_int | IK_DMA);
+}
+static void interrupt_ack_dma(interrupt_cpu_status_t *cs)
+{
+       cs->global_pending_int = (enum cpu_int)
+               (cs->global_pending_int & ~IK_DMA);
+}
+static void interrupt_do_trap(interrupt_cpu_status_t *cs, WORD address)
+{
+       cs->global_pending_int &= ~IK_TRAP;
+       cs->trap_func(address, cs->trap_data);
+}
+static void interrupt_ack_reset(interrupt_cpu_status_t *cs)
+{
+       cs->global_pending_int &= ~IK_RESET;
+
+       if (cs->reset_trap_func)
+               cs->reset_trap_func();
+}
+static void interrupt_ack_nmi(interrupt_cpu_status_t *cs)
+{
+       cs->global_pending_int =
+               (cs->global_pending_int & ~IK_NMI);
+
+       if (cs->nmi_trap_func) {
+               cs->nmi_trap_func();
+       }
+}
+static void interrupt_ack_irq(interrupt_cpu_status_t *cs)
+{
+       cs->global_pending_int =
+               (cs->global_pending_int & ~IK_IRQPEND);
+       cs->irq_pending_clk = CLOCK_MAX;
+}
+static int interrupt_check_nmi_delay(interrupt_cpu_status_t *cs,
+       CLOCK cpu_clk)
+{
+       CLOCK nmi_clk = cs->nmi_clk + INTERRUPT_DELAY;
+
+       /* Branch instructions delay IRQs and NMI by one cycle if branch
+       is taken with no page boundary crossing.  */
+       if (OPINFO_DELAYS_INTERRUPT(*cs->last_opcode_info_ptr))
+               nmi_clk++;
+
+       if (cpu_clk >= nmi_clk)
+               return 1;
+
+       return 0;
+}
+static int interrupt_check_irq_delay(interrupt_cpu_status_t *cs,
+       CLOCK cpu_clk)
+{
+       CLOCK irq_clk = cs->irq_clk + INTERRUPT_DELAY;
+
+       /* Branch instructions delay IRQs and NMI by one cycle if branch
+       is taken with no page boundary crossing.  */
+       if (OPINFO_DELAYS_INTERRUPT(*cs->last_opcode_info_ptr))
+               irq_clk++;
+
+       /* If an opcode changes the I flag from 1 to 0, the 6510 needs
+       one more opcode before it triggers the IRQ routine.  */
+       if (cpu_clk >= irq_clk) {
+               if (!OPINFO_ENABLES_IRQ(*cs->last_opcode_info_ptr)) {
+                       return 1;
+               } else {
+                       cs->global_pending_int |= IK_IRQPEND;
+               }
+       }
+       return 0;
+}
+
+struct alarm_context_s {
+       CLOCK next_pending_alarm_clk;
+};
+typedef struct alarm_context_s alarm_context_t;
+
+static void alarm_context_dispatch(alarm_context_t *context, CLOCK cpu_clk)
+{
+}
+static CLOCK alarm_context_next_pending_clk(alarm_context_t *context)
+{
+       return context->next_pending_alarm_clk;
+}
+
+static void cpu_4510(void)
+{
+       int cpu_type = CPU_R65C02;
+       drivecpu_context_t *cpu = NULL;
+       drive_context_t *drv = NULL;
+
+#define reg_a   (cpu->cpu_regs.a)
+#define reg_x   (cpu->cpu_regs.x)
+#define reg_y   (cpu->cpu_regs.y)
+#define reg_pc  (cpu->cpu_regs.pc)
+#define reg_sp  (cpu->cpu_regs.sp)
+#define reg_p   (cpu->cpu_regs.p)
+#define flag_z  (cpu->cpu_regs.z)
+#define flag_n  (cpu->cpu_regs.n)
+
+#include "65c02core.cpp"
+}
+
+static void init_65c02(struct drive_context_s *drv)
+{
+       drivecpu_context_t *cpu = drv->cpu;
+
+       cpu->rmw_flag = 0;
+       cpu->d_bank_limit = 0;
+       cpu->d_bank_start = 0;
+       cpu->pageone = NULL;
+}
+
+#endif
diff --git a/cia.cpp b/cia.cpp
index 91eeb3f27cd195483f47d667e45c1560f25bbf3f..ef15c962af4f89f9fdfc5adef271451daa36f1ee 100644 (file)
--- a/cia.cpp
+++ b/cia.cpp
@@ -868,7 +868,7 @@ static void led_vsync (void)
        led_cycles_off = 0;
        if (led_old_brightness != gui_data.powerled_brightness) {
                gui_data.powerled = gui_data.powerled_brightness > 127;
-               gui_led (LED_POWER, gui_data.powerled);
+               gui_led (LED_POWER, gui_data.powerled, gui_data.powerled_brightness);
                led_filter_audio ();
        }
        led_old_brightness = gui_data.powerled_brightness;
index 360f8111484023f277f0b002f4f0cabe8f0040a4..e22d74e34a7ce1fa94cda46717fd68607bc5d2f7 100644 (file)
--- a/disk.cpp
+++ b/disk.cpp
@@ -711,7 +711,7 @@ static void reset_drive (int num)
        drv->dskready_up_time = 0;
        drv->buffered_cyl = -1;
        drv->buffered_side = -1;
-       gui_led (num + LED_DF0, 0);
+       gui_led (num + LED_DF0, 0, -1);
        drive_settype_id (drv);
        _tcscpy (currprefs.floppyslots[num].df, changed_prefs.floppyslots[num].df);
        drv->newname[0] = 0;
@@ -742,7 +742,7 @@ static void update_drive_gui (int num, bool force)
        else
                gui_data.drive_side = side;
        gui_data.drive_writing[num] = writ;
-       gui_led (num + LED_DF0, (gui_data.drive_motor[num] ? 1 : 0) | (gui_data.drive_writing[num] ? 2 : 0));
+       gui_led (num + LED_DF0, (gui_data.drive_motor[num] ? 1 : 0) | (gui_data.drive_writing[num] ? 2 : 0), -1);
 }
 
 static void drive_fill_bigbuf (drive * drv,int);
index a411d733405adde38b8105a5305efb5b1e033617..95a3133ef69e9a7a39f6de4d1599ea1f9f37a6bb 100644 (file)
@@ -431,7 +431,7 @@ void gfxboard_vsync_handler (void)
                monswitch_delay = 0;
        }
 
-       if (monswitch_current && picasso_on) {
+       if (!monswitch_delay && monswitch_current && picasso_on && picasso_requested_on) {
                picasso_getwritewatch (vram_start_offset);
                if (fullrefresh)
                        vga.vga.graphic_mode = -1;
@@ -2308,6 +2308,7 @@ addrbank *gfxboard_init_memory (int devnum)
 
        if (ISP4()) {
                int roms[] = { 91, -1 };
+               struct romlist *rl = getromlistbyids(roms, NULL);
                TCHAR path[MAX_DPATH];
                fetch_rompath (path, sizeof path / sizeof (TCHAR));
 
@@ -2316,6 +2317,9 @@ addrbank *gfxboard_init_memory (int devnum)
                if (!p4rom && currprefs.picassoivromfile[0])
                        p4rom = read_rom_name(currprefs.picassoivromfile);
 
+               if (!p4rom && rl)
+                       p4rom = read_rom(rl->rd);
+
                if (!p4rom) {
                        _tcscat (path, _T("picasso_iv_flash.rom"));
                        p4rom = read_rom_name (path);
index b509e80f15b5f893337c0290353086272ca7fb62..890e1584c712c5baa1471a2acb38ed235a3918ae 100644 (file)
@@ -9,7 +9,7 @@
 extern int gui_init (void);
 extern int gui_update (void);
 extern void gui_exit (void);
-extern void gui_led (int, int);
+extern void gui_led (int, int, int);
 extern void gui_handle_events (void);
 extern void gui_filename (int, const TCHAR *);
 extern void gui_fps (int fps, int idle, int color);
index 56c22a4c714be7fd84c39015a000d09db4542ea7..7084ad9e1a7c7731513b586f4e16728f44c041af 100644 (file)
@@ -1979,14 +1979,14 @@ static void allocate_memory (void)
                }
        }
        if (mem25bit_bank.allocated != currprefs.mem25bit_size) {
-               mapped_free (&mem25bit_bank);
+               mapped_free(&mem25bit_bank);
 
                mem25bit_bank.allocated = currprefs.mem25bit_size;
                mem25bit_bank.mask = mem25bit_bank.allocated - 1;
                mem25bit_bank.start = 0x01000000;
                if (mem25bit_bank.allocated) {
-                       if (!mapped_malloc (&mem25bit_bank)) {
-                               write_log (_T("Out of memory for 25 bit memory.\n"));
+                       if (!mapped_malloc(&mem25bit_bank)) {
+                               write_log(_T("Out of memory for 25 bit memory.\n"));
                                mem25bit_bank.allocated = 0;
                        }
                }
@@ -2069,7 +2069,7 @@ static void allocate_memory (void)
                if (bogomem_bank.allocated > 0)
                        restore_ram (bogo_filepos, bogomem_bank.baseaddr);
                if (mem25bit_bank.allocated > 0)
-                       restore_ram (mem25bit_filepos, mem25bit_bank.baseaddr);
+                       restore_ram(mem25bit_filepos, mem25bit_bank.baseaddr);
                if (a3000lmem_bank.allocated > 0)
                        restore_ram (a3000lmem_filepos, a3000lmem_bank.baseaddr);
                if (a3000hmem_bank.allocated > 0)
@@ -2096,14 +2096,14 @@ static void fill_ce_banks (void)
                memset (ce_banktype, CE_MEMBANK_FAST32, sizeof ce_banktype);
        }
        // data cachable regions (2 = burst supported)
-       memset (ce_cachable, 0, sizeof ce_cachable);
-       memset (ce_cachable + (0x00200000 >> 16), 1 | 2, currprefs.fastmem_size >> 16);
-       memset (ce_cachable + (0x00c00000 >> 16), 1, currprefs.bogomem_size >> 16);
-       memset (ce_cachable + (z3fastmem_bank.start >> 16), 1 | 2, currprefs.z3fastmem_size >> 16);
-       memset (ce_cachable + (z3fastmem2_bank.start >> 16), 1 | 2, currprefs.z3fastmem2_size >> 16);
-       memset (ce_cachable + (a3000hmem_bank.start >> 16), 1 | 2, currprefs.mbresmem_high_size >> 16);
-       memset (ce_cachable + (a3000lmem_bank.start >> 16), 1 | 2, currprefs.mbresmem_low_size >> 16);
-       memset (ce_cachable + (mem25bit_bank.start >> 16), 1 | 2, currprefs.mem25bit_size >> 16);
+       memset(ce_cachable, 0, sizeof ce_cachable);
+       memset(ce_cachable + (0x00200000 >> 16), 1 | 2, currprefs.fastmem_size >> 16);
+       memset(ce_cachable + (0x00c00000 >> 16), 1, currprefs.bogomem_size >> 16);
+       memset(ce_cachable + (z3fastmem_bank.start >> 16), 1 | 2, currprefs.z3fastmem_size >> 16);
+       memset(ce_cachable + (z3fastmem2_bank.start >> 16), 1 | 2, currprefs.z3fastmem2_size >> 16);
+       memset(ce_cachable + (a3000hmem_bank.start >> 16), 1 | 2, currprefs.mbresmem_high_size >> 16);
+       memset(ce_cachable + (a3000lmem_bank.start >> 16), 1 | 2, currprefs.mbresmem_low_size >> 16);
+       memset(ce_cachable + (mem25bit_bank.start >> 16), 1 | 2, currprefs.mem25bit_size >> 16);
 
        if (&get_mem_bank (0) == &chipmem_bank) {
                for (i = 0; i < (0x200000 >> 16); i++) {
@@ -2242,15 +2242,15 @@ void memory_clear (void)
        if (savestate_state == STATE_RESTORE)
                return;
        if (chipmem_bank.baseaddr)
-               memset (chipmem_bank.baseaddr, 0, chipmem_bank.allocated);
+               memset(chipmem_bank.baseaddr, 0, chipmem_bank.allocated);
        if (bogomem_bank.baseaddr)
-               memset (bogomem_bank.baseaddr, 0, bogomem_bank.allocated);
+               memset(bogomem_bank.baseaddr, 0, bogomem_bank.allocated);
        if (mem25bit_bank.baseaddr)
-               memset (mem25bit_bank.baseaddr, 0, mem25bit_bank.allocated);
+               memset(mem25bit_bank.baseaddr, 0, mem25bit_bank.allocated);
        if (a3000lmem_bank.baseaddr)
-               memset (a3000lmem_bank.baseaddr, 0, a3000lmem_bank.allocated);
+               memset(a3000lmem_bank.baseaddr, 0, a3000lmem_bank.allocated);
        if (a3000hmem_bank.baseaddr)
-               memset (a3000hmem_bank.baseaddr, 0, a3000hmem_bank.allocated);
+               memset(a3000hmem_bank.baseaddr, 0, a3000hmem_bank.allocated);
        expansion_clear ();
        cpuboard_clear();
 }
@@ -2449,11 +2449,11 @@ void memory_reset (void)
 #endif
 
        if (mem25bit_bank.baseaddr)
-               map_banks (&mem25bit_bank, mem25bit_bank.start >> 16, mem25bit_bank.allocated >> 16, 0);
+               map_banks(&mem25bit_bank, mem25bit_bank.start >> 16, mem25bit_bank.allocated >> 16, 0);
        if (a3000lmem_bank.baseaddr)
-               map_banks (&a3000lmem_bank, a3000lmem_bank.start >> 16, a3000lmem_bank.allocated >> 16, 0);
+               map_banks(&a3000lmem_bank, a3000lmem_bank.start >> 16, a3000lmem_bank.allocated >> 16, 0);
        if (a3000hmem_bank.baseaddr)
-               map_banks (&a3000hmem_bank, a3000hmem_bank.start >> 16, a3000hmem_bank.allocated >> 16, 0);
+               map_banks(&a3000hmem_bank, a3000hmem_bank.start >> 16, a3000hmem_bank.allocated >> 16, 0);
 #ifdef CDTV
        if (cardmem_bank.baseaddr)
                map_banks (&cardmem_bank, cardmem_bank.start >> 16, cardmem_bank.allocated >> 16, 0);
@@ -2610,13 +2610,13 @@ void memory_init (void)
 
 void memory_cleanup (void)
 {
-       mapped_free (&mem25bit_bank);
-       mapped_free (&a3000lmem_bank);
-       mapped_free (&a3000hmem_bank);
-       mapped_free (&bogomem_bank);
-       mapped_free (&kickmem_bank);
-       xfree (a1000_bootrom);
-       mapped_free (&chipmem_bank);
+       mapped_free(&mem25bit_bank);
+       mapped_free(&a3000lmem_bank);
+       mapped_free(&a3000hmem_bank);
+       mapped_free(&bogomem_bank);
+       mapped_free(&kickmem_bank);
+       xfree(a1000_bootrom);
+       mapped_free(&chipmem_bank);
 #ifdef CDTV
        if (cardmem_bank.baseaddr) {
                cdtv_savecardmem (cardmem_bank.baseaddr, cardmem_bank.allocated);
index 9fb16704a6b4f72fadc63d8ed85bee449c2d38d4..00e0ff34c6e790ea3f62e57555011c4371df772d 100644 (file)
@@ -1420,7 +1420,7 @@ void rp_fixup_options (struct uae_prefs *p)
        rp_turbo_cpu (currprefs.turbo_emulation);
        rp_turbo_floppy (currprefs.floppy_speed == 0);
        for (i = 0; i <= 4; i++)
-               rp_update_leds (i, 0, 0);
+               rp_update_leds (i, 0, -1, 0);
        set_config_changed ();
 }
 
@@ -1543,7 +1543,7 @@ void rp_floppy_track (int floppy, int track)
        RPPostMessagex (RP_IPC_TO_HOST_DEVICESEEK, MAKEWORD (RP_DEVICECATEGORY_FLOPPY, floppy), track, &guestinfo);
 }
 
-void rp_update_leds (int led, int onoff, int write)
+void rp_update_leds (int led, int onoff, int brightness, int write)
 {
        static int oldled[5];
        int ledstate;
@@ -1554,10 +1554,12 @@ void rp_update_leds (int led, int onoff, int write)
                return;
        if (onoff < 0)
                return;
+       if (brightness < 0)
+               brightness = onoff ? 250 : 0;
        switch (led)
        {
        case LED_POWER:
-               ledstate = onoff >= 250 ? 100 : onoff * 5 / 26 + 49;
+               ledstate = brightness >= 250 ? 100 : brightness * 5 / 26 + 49;
                if (ledstate == oldled[led])
                        return;
                oldled[led] = ledstate;
index 2a3c495a2ba1190d3c3cd094d24ee638848c660f..385a3d43b51704d11ede51f0226071cb6ebf5a1d 100644 (file)
@@ -33,7 +33,7 @@ extern void rp_cd_image_change (int num, const TCHAR *name);
 
 extern void rp_update_gameport (int port, int mask, int onoff);
 extern void rp_update_volume (struct uae_prefs*);
-extern void rp_update_leds (int, int, int);
+extern void rp_update_leds (int, int, int, int);
 extern void rp_floppy_track (int floppy, int track);
 extern void rp_hd_activity (int, int, int);
 extern void rp_cd_activity (int, int);
index 7860fd4e74967a30200137c14e07199de0862e31..091410556f4e8315dc4c701255976e11842fb85b 100644 (file)
@@ -2305,7 +2305,7 @@ bool handle_events (void)
                        was_paused = pause_emulation;
                        manual_painting_needed++;
                        gui_fps (0, 0, 0);
-                       gui_led (LED_SND, 0);
+                       gui_led (LED_SND, 0, -1);
                }
                MsgWaitForMultipleObjects (0, NULL, FALSE, 100, QS_ALLINPUT);
                while (PeekMessage (&msg, 0, 0, 0, PM_REMOVE)) {
index bb9a00dab45674c9b17246089d384121da32c175..bffb2ccbc754b7f8baf92b13dbcbe06ac429713c 100644 (file)
 #define LANG_DLL_FULL_VERSION_MATCH 1
 
 #if WINUAEPUBLICBETA
-#define WINUAEBETA _T("6")
+#define WINUAEBETA _T("7")
 #else
 #define WINUAEBETA _T("")
 #endif
 
-#define WINUAEDATE MAKEBD(2015, 8, 1)
+#define WINUAEDATE MAKEBD(2015, 8, 12)
 
 //#define WINUAEEXTRA _T("AmiKit Preview")
 //#define WINUAEEXTRA _T("Amiga Forever Edition")
index d25788463cffb7ae0570189ba475ee31be69f8d6..d888ec8e4aabbd6e6e2c8b8e20cf5774bcd9c67a 100644 (file)
@@ -1744,13 +1744,13 @@ static int open_windows (bool mousecapture)
        if (upd > 1) {
                for (i = 0; i < NUM_LEDS; i++)
                        gui_flicker_led (i, -1, -1);
-               gui_led (LED_POWER, gui_data.powerled);
+               gui_led (LED_POWER, gui_data.powerled, gui_data.powerled_brightness);
                gui_fps (0, 0, 0);
                if (gui_data.md >= 0)
-                       gui_led (LED_MD, 0);
+                       gui_led (LED_MD, 0, -1);
                for (i = 0; i < 4; i++) {
                        if (currprefs.floppyslots[i].dfxtype >= 0)
-                               gui_led (LED_DF0 + i, 0);
+                               gui_led (LED_DF0 + i, 0, -1);
                }
        }
        if (upd > 0) {
index 59207ab908e2667454c40cefbf766d43b03aa71b..10c4ded177bad9181e757ac57ce55402623a55ce 100644 (file)
@@ -1707,6 +1707,7 @@ static void show_rom_list (void)
                110, -1, -1, // GVP G-Force 030
                114, -1, -1, // A3001
                126, -1, -1, // Golem 030
+               144, -1, -1, // E-Matrix 530
                89, -1, -1, // 1230-IV
                89, -1, 94, -1, -1, // 1230-IV SCSI
                90, -1, -1, // 1260
@@ -1759,6 +1760,7 @@ static void show_rom_list (void)
                _T("GVP G-FORCE 030\0")
                _T("GVP A3001 Series I\0")
                _T("Kupke Golem 030\0")
+               _T("M-Tec E-Matrix 530\0")
                _T("Blizzard 1230-IV\0Blizzard 1260\0")
                _T("Blizzard 1230-IV/SCSI\0Blizzard 1260/SCSI\0")
                _T("Blizzard 2060\0Warp Engine\0TekMagic 2040/2060\0")
@@ -7738,8 +7740,9 @@ static void setcpuboardmemsize(HWND hDlg)
        if (cpuboard_memorytype(&workprefs) == BOARD_MEMORY_25BITMEM) {
                workprefs.mem25bit_size = workprefs.cpuboardmem1_size;
        }
-       if (workprefs.cpuboard_type == 0)
+       if (workprefs.cpuboard_type == 0) {
                workprefs.mem25bit_size = 0;
+       }
 
        if (cpuboard_memorytype(&workprefs) == BOARD_MEMORY_HIGHMEM)
                workprefs.mbresmem_high_size = workprefs.cpuboardmem1_size;
@@ -8827,6 +8830,8 @@ static INT_PTR CALLBACK Expansion2DlgProc(HWND hDlg, UINT msg, WPARAM wParam, LP
                                case IDC_A2065:
                                if (ischecked(hDlg, IDC_A2065)) {
                                        _tcscpy(workprefs.a2065name, _T("none"));
+                                       workprefs.ne2000pciname[0] = 0;
+                                       setchecked(hDlg, IDC_NE2000, false);
                                        expansion_net(hDlg);
                                        enable_for_expansion2dlg(hDlg);
                                } else {
@@ -8839,6 +8844,8 @@ static INT_PTR CALLBACK Expansion2DlgProc(HWND hDlg, UINT msg, WPARAM wParam, LP
                                case IDC_NE2000:
                                if (ischecked(hDlg, IDC_NE2000)) {
                                        _tcscpy(workprefs.ne2000pciname, _T("none"));
+                                       workprefs.a2065name[0] = 0;
+                                       setchecked(hDlg, IDC_A2065, false);
                                        expansion_net(hDlg);
                                        enable_for_expansion2dlg(hDlg);
                                } else {
@@ -8859,15 +8866,33 @@ static INT_PTR CALLBACK Expansion2DlgProc(HWND hDlg, UINT msg, WPARAM wParam, LP
                                if (!workprefs.sound_toccata)
                                        workprefs.sound_toccata_mixer = false;
                                enable_for_expansion2dlg(hDlg);
+                               if (workprefs.sound_toccata && (workprefs.sound_fm801 || workprefs.sound_es1370)) {
+                                       workprefs.sound_fm801 = 0;
+                                       workprefs.sound_es1370 = 0;
+                               }
                                break;
                                case IDC_CS_TOCCATAMIXER:
                                workprefs.sound_toccata_mixer = ischecked(hDlg, IDC_CS_TOCCATAMIXER) ? 1 : 0;
                                break;
                                case IDC_CS_ES1370:
                                workprefs.sound_es1370 = ischecked(hDlg, IDC_CS_ES1370) ? 1 : 0;
+                               if (workprefs.sound_es1370 && (workprefs.sound_fm801 || workprefs.sound_toccata)) {
+                                       workprefs.sound_fm801 = 0;
+                                       workprefs.sound_toccata = 0;
+                                       workprefs.sound_toccata_mixer = false;
+                                       values_to_expansion2dlg(hDlg);
+                                       enable_for_expansion2dlg(hDlg);
+                               }
                                break;
                                case IDC_CS_FM801:
                                workprefs.sound_fm801 = ischecked(hDlg, IDC_CS_FM801) ? 1 : 0;
+                               if (workprefs.sound_fm801 && (workprefs.sound_es1370 || workprefs.sound_toccata)) {
+                                       workprefs.sound_es1370 = 0;
+                                       workprefs.sound_toccata = 0;
+                                       workprefs.sound_toccata_mixer = false;
+                                       values_to_expansion2dlg(hDlg);
+                                       enable_for_expansion2dlg(hDlg);
+                               }
                                break;
                                case IDC_SCSIROMSELECTED:
                                values_from_expansion2dlg(hDlg);
@@ -8968,10 +8993,16 @@ static INT_PTR CALLBACK Expansion2DlgProc(HWND hDlg, UINT msg, WPARAM wParam, LP
                                                        v--;
                                                        s = ndd[v]->name;
                                                }
-                                               if (ischecked(hDlg, IDC_A2065))
+                                               if (ischecked(hDlg, IDC_A2065)) {
                                                        _tcscpy(workprefs.a2065name, s);
-                                               if (ischecked(hDlg, IDC_NE2000))
+                                                       workprefs.ne2000pciname[0] = 0;
+                                                       setchecked(hDlg, IDC_NE2000, false);
+                                               }
+                                               if (ischecked(hDlg, IDC_NE2000)) {
                                                        _tcscpy(workprefs.ne2000pciname, s);
+                                                       workprefs.a2065name[0] = 0;
+                                                       setchecked(hDlg, IDC_A2065, false);
+                                               }
                                        }
                                        break;
                                }
@@ -18903,16 +18934,16 @@ static void gui_flicker_led2 (int led, int unitnum, int status)
        old = *p;
        if (status < 0) {
                if (old < 0) {
-                       gui_led (led, -1);
+                       gui_led (led, -1, -1);
                } else {
-                       gui_led (led, 0);
+                       gui_led (led, 0, -1);
                }
                return;
        }
        if (status == 0 && old < 0) {
                *p = 0;
                resetcounter[led] = 0;
-               gui_led (led, 0);
+               gui_led (led, 0, -1);
                return;
        }
        if (status == 0) {
@@ -18931,7 +18962,7 @@ static void gui_flicker_led2 (int led, int unitnum, int status)
        *p = status;
        resetcounter[led] = 6;
        if (old != *p)
-               gui_led (led, *p);
+               gui_led (led, *p, -1);
 }
 
 void gui_flicker_led (int led, int unitnum, int status)
@@ -18951,13 +18982,13 @@ void gui_fps (int fps, int idle, int color)
        gui_data.fps = fps;
        gui_data.idle = idle;
        gui_data.fps_color = color;
-       gui_led (LED_FPS, 0);
-       gui_led (LED_CPU, 0);
-       gui_led (LED_SND, (gui_data.sndbuf_status > 1 || gui_data.sndbuf_status < 0) ? 0 : 1);
+       gui_led (LED_FPS, 0, -1);
+       gui_led (LED_CPU, 0, -1);
+       gui_led (LED_SND, (gui_data.sndbuf_status > 1 || gui_data.sndbuf_status < 0) ? 0 : 1, -1);
 }
 
 #define LED_STRING_WIDTH 40
-void gui_led (int led, int on)
+void gui_led (int led, int on, int brightness)
 {
        WORD type;
        static TCHAR drive_text[NUM_LEDS * LED_STRING_WIDTH];
@@ -18976,7 +19007,7 @@ void gui_led (int led, int on)
                rp_floppy_track (led - LED_DF0, gui_data.drive_track[led - LED_DF0]);
                writing = gui_data.drive_writing[led - LED_DF0];
        }
-       rp_update_leds (led, on, writing);
+       rp_update_leds (led, on, brightness, writing);
 #endif
        if (!hStatusWnd)
                return;
index 9be49bd6625f9b047b67c7dc8d98d78bbf16830e..35b1e6f05bc6e6e82da160060dbf2fe8a1cb9c88 100644 (file)
@@ -1,4 +1,36 @@
 
+Beta 7:
+
+- 68030 prefetch/ce mode now also uses improved prefetch pipeline emulation.
+- b4 prefetch RTS (and others) special case does not exist, my original test must have been broken.
+- GUI won't anymore allow multiple sound or network cards enabled at the same. (It has never been
+  supported configuration)
+- Cirrus Logic out of bounds VRAM access check improved.
+- Picasso IV ROM loader update didn't support all old ROM paths (b6)
+- SCSI Unit Attention (bus reset/media change) status handling should be now exactly as described in
+  SCSI spec. (Roctec Rochard v2 boot ROM*)
+- A1060 Diagnostics and 8087 jumper was inverted.
+- Continuing WD SCSI transfer with another Select and Transfer when previous SaT had already transferred
+  all buffered data: new SaT restarted from beginning. (A590/A2091 omniscsi.device + cdfs)
+- Config file loaded with non-existing *_rom_file_id: rom key file ("rom" with ID=0) was selected.
+- M-Tec E-Matrix 530 accelerator board added (Thanks to Jozsef Vamosi)
+
+Rochard RH800C with v2 boot ROM:
+- Supports both SCSI and IDE. v1 is IDE only.
+- Has crazy "Is drive ready?" polling routine, driver executes 300 (!) TEST UNIT READY commands in
+  CPU loop per LUN (timer.device exists for a reason..), with single SCSI drive, driver executes total
+  6*300=1800 TUR commands during drive detection! (I recommend not to enable scsi logging..)
+- ROM not yet added.
+
+M-Tec E-Matrix 530:
+- ROM image is software dumped (chip is not socketed), ROM layout (single chip contains two logical
+  autoconfig boot ROMs) may not match real ROM dump.
+- 53C94 based SCSI. Fake DMA, 2*long word wide data port. Whole transfer loop runs in level 2
+  interrupt routine..
+- Boot ROM requires KS2.0+ only because it calls CacheControl() without checking ROM version.
+
+Beta 6:
+
 - Bridgeboard floppy drive motor and click sound supported.
 - x86 CPU status string was visible even when bridgeboard was not active.
 - Added software readable A4091 DIP switches and Warp Engine SCSI jumpers to GUI. Note that default
index ce65243f154dc405208fc8eeed53849ed83ed981..8f32ffb219484a4a0391e036c63a6673888753e9 100644 (file)
@@ -513,6 +513,10 @@ void esp_reg_write(void *opaque, uint32_t saddr, uint64_t val)
             break;
         case CMD_RESET:
             esp_soft_reset(s);
+                       // E-Matrix 530 detects existence of SCSI chip by
+                       // writing CMD_RESET and then immediately checking
+                       // if it reads back.
+                       s->rregs[saddr] = CMD_RESET;
             break;
         case CMD_BUSRESET:
             s->rregs[ESP_RINTR] = INTR_RST;
index ae460b0d01e1c77ea1ed69b9118c0c0a8abc8899..9abc785a9dc410e2e321e3a47f4bb2dac6edea62 100755 (executable)
@@ -102,6 +102,20 @@ STATIC_INLINE uae_u8 FIRGB(struct vidbuffer *src, uae_u8 *dataline)
        return v;
 }
 
+STATIC_INLINE uae_u8 DCTV_FIRBG(struct vidbuffer *src, uae_u8 *dataline)
+{
+       uae_u8 v = 0;
+       if (FI(src, dataline))
+               v |= 0x40;
+       if (FR(src, dataline))
+               v |= 0x10;
+       if (FB(src, dataline))
+               v |= 0x04;
+       if (FG(src, dataline))
+               v |= 0x01;
+       return v;
+}
+
 STATIC_INLINE void PRGB(struct vidbuffer *dst, uae_u8 *dataline, uae_u8 r, uae_u8 g, uae_u8 b)
 {
        if (dst->pixbytes == 4) {
@@ -171,6 +185,78 @@ static void clearmonitor(struct vidbuffer *dst)
        }
 }
 
+static void blank_generic(struct vidbuffer *src, struct vidbuffer *dst, int oddlines)
+{
+       int y, vdbl;
+       int ystart, yend, isntsc;
+
+       isntsc = (beamcon0 & 0x20) ? 0 : 1;
+       if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS))
+               isntsc = currprefs.ntscmode ? 1 : 0;
+
+       vdbl = gfxvidinfo.ychange;
+
+       ystart = isntsc ? VBLANK_ENDLINE_NTSC : VBLANK_ENDLINE_PAL;
+       yend = isntsc ? MAXVPOS_NTSC : MAXVPOS_PAL;
+
+       for (y = ystart; y < yend; y++) {
+               int yoff = (((y * 2 + oddlines) - src->yoffset) / vdbl);
+               if (yoff < 0)
+                       continue;
+               if (yoff >= src->inheight)
+                       continue;
+               uae_u8 *dstline = dst->bufmem + (((y * 2 + oddlines) - dst->yoffset) / vdbl) * dst->rowbytes;
+               memset(dstline, 0, dst->inwidth * dst->pixbytes);
+       }
+}
+
+static uae_s8 dctv_chroma[1600];
+static uae_u8 dctv_luma[1600];
+
+static const uae_u16 dctv_tables[] = {
+       0xF9AF, 0xF9C9, 0xF9E2, 0xF9FC, 0xFA15, 0xFA2F, 0xFA48, 0xFA62,
+       0xFA7B, 0xFA95, 0xFAAE, 0xFAC8, 0xFAE1, 0xFAFB, 0xFB14, 0xFB2E,
+       0xFB47, 0xFB61, 0xFB7A, 0xFB94, 0xFBAD, 0xFBC7, 0xFBE0, 0xFBFA,
+       0xFC13, 0xFC2D, 0xFC46, 0xFC60, 0xFC79, 0xFC93, 0xFCAC, 0xFCC6,
+       0xFCDF, 0xFCF9, 0xFD12, 0xFD2C, 0xFD45, 0xFD5F, 0xFD78, 0xFD92,
+       0xFDAB, 0xFDC5, 0xFDDE, 0xFDF8, 0xFE11, 0xFE2B, 0xFE44, 0xFE5E,
+       0xFE77, 0xFE91, 0xFEAA, 0xFEC4, 0xFEDD, 0xFEF7, 0xFF10, 0xFF2A,
+       0xFF43, 0xFF5D, 0xFF76, 0xFF90, 0xFFA9, 0xFFC3, 0xFFDC, 0xFFF6,
+       0x000F, 0x0029, 0x0042, 0x005C, 0x0075, 0x008F, 0x00A8, 0x00C2,
+       0x00DB, 0x00F5, 0x010E, 0x0128, 0x0141, 0x015B, 0x0174, 0x018E,
+       0x01A7, 0x01C1, 0x01DA, 0x01F4, 0x020D, 0x0227, 0x0240, 0x025A,
+       0x0273, 0x028D, 0x02A6, 0x02C0, 0x02D9, 0x02F3, 0x030C, 0x0326,
+       0x033F, 0x0359, 0x0372, 0x038C, 0x03A5, 0x03BF, 0x03D8, 0x03F2,
+       0x040B, 0x0425, 0x043E, 0x0458, 0x0471, 0x048B, 0x04A4, 0x04BE,
+       0x04D7, 0x04F1, 0x050A, 0x0524, 0x053D, 0x0557, 0x0570, 0x058A,
+       0x05A3, 0x05BD, 0x05D6, 0x05F0, 0x0609, 0x0623, 0x063C, 0x0656,
+       0x066F, 0x0689, 0x06A2, 0x06BC, 0x06D5, 0x06EF, 0x0708, 0x0722,
+       0x073B, 0x0755, 0x076E, 0x0788, 0x07A1, 0x07BB, 0x07D4, 0x07EE,
+       0x0807, 0x0821, 0x083A, 0x0854, 0x086D, 0x0887, 0x08A0, 0x08BA,
+       0x08D3, 0x08ED, 0x0906, 0x0920, 0x0939, 0x0953, 0x096C, 0x0986,
+       0x099F, 0x09B9, 0x09D2, 0x09EC, 0x0A05, 0x0A1F, 0x0A38, 0x0A52,
+       0x0A6B, 0x0A85, 0x0A9E, 0x0AB8, 0x0AD1, 0x0AEB, 0x0B04, 0x0B1E,
+       0x0B37, 0x0B51, 0x0B6A, 0x0B84, 0x0B9D, 0x0BB7, 0x0BD0, 0x0BEA,
+       0x0C03, 0x0C1D, 0x0C36, 0x0C50, 0x0C69, 0x0C83, 0x0C9C, 0x0CB6,
+       0x0CCF, 0x0CE9, 0x0D02, 0x0D1C, 0x0D35, 0x0D4F, 0x0D68, 0x0D82,
+       0x0D9B, 0x0DB5, 0x0DCE, 0x0DE8, 0x0E01, 0x0E1B, 0x0E34, 0x0E4E,
+       0x0E67, 0x0E81, 0x0E9A, 0x0EB4, 0x0ECD, 0x0EE7, 0x0F00, 0x0F1A,
+       0x0F33, 0x0F4D, 0x0F66, 0x0F80, 0x0F99, 0x0FB3, 0x0FCC, 0x0FE6,
+       0x0FFF, 0x1019, 0x1032, 0x104C, 0x1065, 0x107F, 0x1098, 0x10B2,
+       0x10CB, 0x10E5, 0x10FE, 0x1118, 0x1131, 0x114B, 0x1164, 0x117E,
+       0x1197, 0x11B1, 0x11CA, 0x11E4, 0x11FD, 0x1217, 0x1230, 0x124A,
+       0x1263, 0x127D, 0x1296, 0x12B0, 0x12C9, 0x12E3, 0x12FC, 0x1316
+};
+
+STATIC_INLINE int minmax(int v, int min, int max)
+{
+       if (v < min)
+               v = min;
+       if (v > max)
+               v = max;
+       return v;
+}
+
 static bool dctv(struct vidbuffer *src, struct vidbuffer *dst, bool doublelines, int oddlines)
 {
        int y, x, vdbl, hdbl;
@@ -191,8 +277,13 @@ static bool dctv(struct vidbuffer *src, struct vidbuffer *dst, bool doublelines,
 
        oddlines = 1;
 
+       memset(dctv_luma, 0x40, sizeof dctv_luma);
+
+       int signature_detected = -1;
+       int signature_x = -1;
+       int linenr = 0;
        uae_u8 r, g, b;
-       for (y = ystart; y < yend; y += 2) {
+       for (y = ystart; y < yend; y++) {
                int yoff = (((y * 2 + oddlines) - src->yoffset) / vdbl);
                if (yoff < 0)
                        continue;
@@ -201,6 +292,7 @@ static bool dctv(struct vidbuffer *src, struct vidbuffer *dst, bool doublelines,
                uae_u8 *line = src->bufmem + yoff * src->rowbytes;
                uae_u8 *dstline = dst->bufmem + (((y * 2 + oddlines) - dst->yoffset) / vdbl) * dst->rowbytes;
 
+#if 0
                if (y < 60) {
                        write_log(_T("%d:\n"), y);
                        for (x = 22; x < 300; x += 1) {
@@ -214,53 +306,99 @@ static bool dctv(struct vidbuffer *src, struct vidbuffer *dst, bool doublelines,
                        }
                        write_log(_T("\n"));
                }
+#endif
 
-               for (x = 1; x < src->inwidth; x += 4) {
+               int signature_cnt = -1;
+               bool signature_line = false;
+               int firstnz = -1;
+               bool sign = false;
+               int oddeven = 0;
+               uae_u8 prev = 0;
+               uae_u8 vals[3] = { 0x40, 0x40, 0x40 };
+               int chrsum = 0;
+               uae_s8 *chrbuf = dctv_chroma + 10;
+               uae_u8 *lumabuf = dctv_luma + 10;
+               int zigzagoffset = 0;
+               int prevtval = 0;
+               for (x = 0; x < src->inwidth; x++) {
                        uae_u8 *s = line + ((x << 1) / hdbl) * src->pixbytes;
-                       uae_u8 *d = dstline + ((x << 1) / hdbl) * dst->pixbytes;
+                       uae_u8 *d = dstline + ((x << 1) / hdbl) * dst->pixbytes + zigzagoffset;
                        uae_u8 *s2 = s + src->rowbytes;
                        uae_u8 *d2 = d + dst->rowbytes;
-                       uae_u8 newval = FIRGB(src, s);
-
-                       r = newval << 4;
-                       g = newval << 4;
-                       b = newval << 4;
+                       uae_u8 newval = DCTV_FIRBG(src, s);
+                       uae_u8 val = prev | newval;
 
-                       for (int xx = 0; xx < 4; xx++) {
-                               PRGB(dst, d + dst->pixbytes * xx, r, g, b);
-                               PRGB(dst, d + dst->rowbytes + dst->pixbytes * xx, r, g, b);
+                       if (firstnz < 0 && newval) {
+                               firstnz = 0;
+                               if (newval == 0x14) {
+                                       zigzagoffset = -1 * dst->pixbytes;
+                                       oddeven = -2;
+                               } else {
+                                       zigzagoffset = 0;
+                                       oddeven = -2;
+                               }
                        }
 
+                       if (oddeven > 0) {
+                               if (!val)
+                                       val = 64;
+                               int tval = minmax(val, 64, 224);
+                               if (tval != val)
+                                       tval = prevtval;
+                               prevtval = tval;
+
+                               uae_s16 luma = (uae_s16)dctv_tables[tval];
+                               tval = minmax(luma / 16, 0, 255);
+                               uae_u8 v1 = (uae_u8)tval;
+
+                               r = b = g = v1;
+
+                               if (val < 64) {
+                                       r = 0x80 + val * 2;
+                                       b = g = 0;
+                               } else if (val > 224) {
+                                       r = b = 0;
+                                       g = 0x80 + (val - 224) * 2;
+                               }
+                               
+
+                               sign = !sign;
+
+                               PRGB(dst, d - dst->pixbytes, r, g, b);
+                               PRGB(dst, d, r, g, b);
+                               if (doublelines) {
+                                       PRGB(dst, d2 - dst->pixbytes, r, g, b);
+                                       PRGB(dst, d2, r, g, b);
+                               }
+                       }
 
+                       if (oddeven >= 0)
+                               oddeven = oddeven ? 0 : 1;
+                       else
+                               oddeven++;
+                       prev = newval << 1;
                }
        }
        dst->nativepositioning = true;
        return true;
 }
 
-static void blank_generic(struct vidbuffer *src, struct vidbuffer *dst, int oddlines)
+static bool do_dctv(struct vidbuffer *src, struct vidbuffer *dst)
 {
-       int y, vdbl;
-       int ystart, yend, isntsc;
-
-       isntsc = (beamcon0 & 0x20) ? 0 : 1;
-       if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS))
-               isntsc = currprefs.ntscmode ? 1 : 0;
-
-       vdbl = gfxvidinfo.ychange;
-
-       ystart = isntsc ? VBLANK_ENDLINE_NTSC : VBLANK_ENDLINE_PAL;
-       yend = isntsc ? MAXVPOS_NTSC : MAXVPOS_PAL;
-
-       for (y = ystart; y < yend; y++) {
-               int yoff = (((y * 2 + oddlines) - src->yoffset) / vdbl);
-               if (yoff < 0)
-                       continue;
-               if (yoff >= src->inheight)
-                       continue;
-               uae_u8 *dstline = dst->bufmem + (((y * 2 + oddlines) - dst->yoffset) / vdbl) * dst->rowbytes;
-               memset(dstline, 0, dst->inwidth * dst->pixbytes);
+       bool v;
+       if (interlace_seen) {
+               if (currprefs.gfx_iscanlines) {
+                       v = dctv(src, dst, false, lof_store ? 0 : 1);
+                       if (v && currprefs.gfx_iscanlines > 1)
+                               blank_generic(src, dst, lof_store ? 1 : 0);
+               } else {
+                       v = dctv(src, dst, false, 0);
+                       v |= dctv(src, dst, false, 1);
+               }
+       } else {
+               v = dctv(src, dst, true, 0);
        }
+       return v;
 }
 
 static uae_u8 *sm_frame_buffer;
@@ -1782,7 +1920,7 @@ static bool emulate_specialmonitors2(struct vidbuffer *src, struct vidbuffer *ds
        } else if (currprefs.monitoremu == MONITOREMU_GRAFFITI) {
                return graffiti(src, dst);
        } else if (currprefs.monitoremu == MONITOREMU_DCTV) {
-               return dctv(src, dst, false, 0);
+               return do_dctv(src, dst);
        } else if (currprefs.monitoremu == MONITOREMU_HAM_E || currprefs.monitoremu == MONITOREMU_HAM_E_PLUS) {
                return do_hame(src, dst);
        } else if (currprefs.monitoremu == MONITOREMU_VIDEODAC18) {
diff --git a/x86.cpp b/x86.cpp
index 01fa503b02315418d8a06cafa1dab3f16fb75ad6..27734839c07159d8f5ea03883b950749e0969f87 100644 (file)
--- a/x86.cpp
+++ b/x86.cpp
@@ -2970,7 +2970,7 @@ addrbank *x86_bridge_init(struct romconfig *rc, int type)
                load_vga_bios();
        }
 
-       xb->pc_jumpers = (xb->settings & 0xff) ^ ((0x80 | 0x40) | (0x20 | 0x10));
+       xb->pc_jumpers = (xb->settings & 0xff) ^ ((0x80 | 0x40) | (0x20 | 0x10 | 0x01 | 0x02));
 
        int ramsize = (xb->settings >> 2) & 3;
        switch(ramsize) {