#include #include "cpu/65el02.h" #include "memory/memory.h" int nospbug = 0; int readMem(int addr) { int i = 0; while ( (i <= cpu.breakpoint_count) && ((cpu.breakpoints[i] & 0x2ffff) != (cpu.regPC | 0x20000)) ) i++; if (i <= cpu.breakpoint_count) // breakpoint hit { cpu.cycles = 0; cpu.brk = 1; } return (mem_load(addr) & 0xff); } void writeMem(int addr, int val) { int i = 0; while ( (i <= cpu.breakpoint_count) && ((cpu.breakpoints[i] & 0x4ffff) != (cpu.regPC | 0x40000)) ) i++; if (i <= cpu.breakpoint_count) // breakpoint hit { cpu.cycles = 0; cpu.brk = 1; } mem_store(addr, val); } void coldBootCPU() { cpu.addrPOR = 0x2000; cpu.addrBRK = 0x2000; if (nospbug) cpu.regSP = 0x1ff; else cpu.regSP = 0x200; cpu.regPC = 0x400; cpu.regR = 0x300; cpu.regA = 0; cpu.regX = 0; cpu.regY = 0; cpu.regD = 0; cpu.flagC = 0; cpu.flagZ = 0; cpu.flagID = 0; cpu.flagD = 0; cpu.flagBRK = 0; cpu.flagO = 0; cpu.flagN = 0; cpu.flagE = 1; cpu.flagM = 1; cpu.flagX = 1; if (!cpu.byte0) cpu.byte0 = 2; if (!cpu.byte1) cpu.byte1 = 1; cpu.cycles = 0; cpu.ticks = 0; cpu.brk = 0; if (!cpu.cycles_per_tick) cpu.cycles_per_tick = 1000; } void incPC() { cpu.regPC = (cpu.regPC + 1) & 0xffff; } int maskM() { return cpu.flagM ? 0xff : 0xffff; } int maskX() { return cpu.flagX ? 0xff : 0xffff; } int negM() { return cpu.flagM ? 0x80 : 0x8000; } int negX() { return cpu.flagX ? 0x80 : 0x8000; } int readB() { int i = readMem(cpu.regPC); incPC(); return i; } int readM_PC() { int i = readMem(cpu.regPC); incPC(); if (!cpu.flagM) { i |= readMem(cpu.regPC) << 8; incPC(); } return i; } int readX_PC() { int i = readMem(cpu.regPC); incPC(); if (!cpu.flagX) { i |= readMem(cpu.regPC) << 8; incPC(); } return i; } int readM(int addr) { int i = readMem(addr); if (!cpu.flagM) i |= readMem(addr + 1) << 8; return i; } int readX(int addr) { int i = readMem(addr); if (!cpu.flagX) i |= readMem(addr + 1) << 8; return i; } void writeM(int addr, int reg) { writeMem(addr, reg); if (!cpu.flagM) writeMem(addr + 1, reg >> 8); } void writeX(int addr, int reg) { writeMem(addr, reg); if (!cpu.flagX) writeMem(addr + 1, reg >> 8); } int readBX() { int i = readMem(cpu.regPC) + cpu.regX; if (cpu.flagX) i &= 0xff; incPC(); return i; } int readBY() { int i = readMem(cpu.regPC) + cpu.regY; if (cpu.flagX) i &= 0xff; incPC(); return i; } int readBS() { int i = readMem(cpu.regPC) + cpu.regSP & 0xffff; incPC(); return i; } int readBR() { int i = readMem(cpu.regPC) + cpu.regR & 0xffff; incPC(); return i; } int readBSWY() { int i = readMem(cpu.regPC) + cpu.regSP & 0xffff; incPC(); return readW(i) + cpu.regY & 0xffff; } int readBRWY() { int i = readMem(cpu.regPC) + cpu.regR & 0xffff; incPC(); return readW(i) + cpu.regY & 0xffff; } int readW_PC() { int i = readMem(cpu.regPC); incPC(); i |= readMem(cpu.regPC) << 8; incPC(); return i; } int readW(int addr) { int i = readMem(addr); i |= readMem(addr + 1) << 8; return i; } int readWX() { int i = readMem(cpu.regPC); incPC(); i |= readMem(cpu.regPC) << 8; incPC(); return i + cpu.regX & 0xffff; } int readWY() { int i = readMem(cpu.regPC); incPC(); i |= readMem(cpu.regPC) << 8; incPC(); return i + cpu.regY & 0xffff; } int readWXW() { int i = readMem(cpu.regPC); incPC(); i |= readMem(cpu.regPC) << 8; incPC(); i = i + cpu.regX & 0xffff; int j = readMem(i); j |= readMem(i + 1) << 8; return j; } int readBW() { int i = readMem(cpu.regPC); incPC(); int j = readMem(i); j |= readMem(i + 1) << 8; return j; } int readWW() { int i = readMem(cpu.regPC); incPC(); i |= readMem(cpu.regPC) << 8; incPC(); int j = readMem(i); j |= readMem(i + 1) << 8; return j; } int readBXW() { int i = readMem(cpu.regPC) + cpu.regX & 0xff; incPC(); int j = readMem(i); j |= readMem(i + 1) << 8; return j; } int readBWY() { int i = readMem(cpu.regPC); incPC(); int j = readMem(i); j |= readMem(i + 1) << 8; return j + cpu.regY & 0xffff; } void upNZ_A() { cpu.flagN = ((cpu.regA & negM()) > 0); cpu.flagZ = (cpu.regA == 0); } void upNZ(int i) { cpu.flagN = ((i & negM()) > 0); cpu.flagZ = (i == 0); } void upNZX(int i) { cpu.flagN = ((i & negX()) > 0); cpu.flagZ = (i == 0); } void push1(int b) { if (nospbug) writeMem(cpu.regSP, b); if (!cpu.flagE) cpu.regSP = (cpu.regSP - 1) & 0xffff; else cpu.regSP = ((cpu.regSP - 1) & 0xff) | (cpu.regSP & 0xff00); if (!nospbug) writeMem(cpu.regSP, b); } void push1r(int b) { cpu.regR = (cpu.regR - 1) & 0xffff; writeMem(cpu.regR, b); } void push2(int w) { push1(w >> 8); push1(w & 0xff); } void push2r(int w) { push1r(w >> 8); push1r(w & 0xff); } void pushM(int b) { if (cpu.flagM) push1(b); else push2(b); } void pushX(int b) { if (cpu.flagX) push1(b); else push2(b); } void pushMr(int b) { if (cpu.flagM) push1r(b); else push2r(b); } void pushXr(int b) { if (cpu.flagX) push1r(b); else push2r(b); } int pop1() { int tr; if (!nospbug) tr = readMem(cpu.regSP); if (!cpu.flagE) cpu.regSP = (cpu.regSP + 1) & 0xffff; else cpu.regSP = ((cpu.regSP + 1) & 0xff) | (cpu.regSP & 0xff00); if (nospbug) tr = readMem(cpu.regSP); return tr; } int pop1r() { int tr = readMem(cpu.regR); cpu.regR = (cpu.regR + 1) & 0xffff; return tr; } int pop2() { int tr = pop1(); tr |= pop1() << 8; return tr; } int pop2r() { int tr = pop1r(); tr |= pop1r() << 8; return tr; } int popM() { if (cpu.flagM) return pop1(); return pop2(); } int popMr() { if (cpu.flagM) return pop1r(); return pop2r(); } int popX() { if (cpu.flagX) return pop1(); return pop2(); } int popXr() { if (cpu.flagX) return pop1r(); return pop2r(); } int getFlags() { return (cpu.flagC ? 1 : 0) | (cpu.flagZ ? 2 : 0) | (cpu.flagID ? 4 : 0) | (cpu.flagD ? 8 : 0) | (cpu.flagX ? 16 : 0) | (cpu.flagM ? 32 : 0) | (cpu.flagO ? 64 : 0) | (cpu.flagN ? 128 : 0); } void setFlags(int flags) { int m2 = (flags & 0x20) > 0; cpu.flagC = ((flags & 0x1) > 0); cpu.flagZ = ((flags & 0x2) > 0); cpu.flagID = ((flags & 0x4) > 0); cpu.flagD = ((flags & 0x8) > 0); cpu.flagX = ((flags & 0x10) > 0); cpu.flagO = ((flags & 0x40) > 0); cpu.flagN = ((flags & 0x80) > 0); if (cpu.flagE) { cpu.flagX = 0; cpu.flagM = 0; } else { cpu.flagX = ((flags & 0x10) > 0); if (cpu.flagX) { cpu.regX &= 0xff; cpu.regY &= 0xff; } if (m2 != cpu.flagM) { if (m2) { cpu.regB = (cpu.regA >> 8); cpu.regA &= 0xff; } else { cpu.regA |= cpu.regB << 8; } cpu.flagM = m2; } } } void i_adc(int val) { if (cpu.flagM) { if (cpu.flagD) { int v1 = (cpu.regA & 0x0f) + (val & 0x0f) + (cpu.flagC ? 1 : 0); if (v1 > 9) v1 = (v1 + 6 & 0x0f) + 16; int v2 = (cpu.regA & 0xf0) + (val & 0xf0) + v1; if (v2 > 160) v2 += 96; cpu.flagC = (v2 > 100); cpu.regA = (v2 & 0xff); cpu.flagO = 0; } else { int v = cpu.regA + val + (cpu.flagC ? 1 : 0); cpu.flagC = (v > 0xff); cpu.flagO = (((v ^ cpu.regA) & (v ^ val) & 0x80) > 0); cpu.regA = (v & 0xff); } } else { int v = cpu.regA + val + (cpu.flagC ? 1 : 0); cpu.flagC = (v > 0xffff); cpu.flagO = (((v ^ cpu.regA) & (v ^ val) & 0x8000) > 0); cpu.regA = (v & 0xffff); } upNZ_A(); } void i_sbc(int val) { if (cpu.flagM) { if (cpu.flagD) { int v1 = (cpu.regA & 0x0f) - (val & 0x0f) + (cpu.flagC ? 1 : 0) - 1; if (v1 < 0) v1 = (v1 - 6 & 0x0f) - 16; int v2 = (cpu.regA & 0xf0) - (val & 0xf0) + v1; if (v2 < 0) v2 -= 96; cpu.flagC = (v2 < 100); cpu.regA = (v2 & 0xff); cpu.flagO = 0; } else { int v = cpu.regA - val + (cpu.flagC ? 1 : 0) - 1; cpu.flagC = ((v & 0x100) == 0); cpu.flagO = (((v ^ cpu.regA) & (v ^ -val) & 0x80) > 0); cpu.regA = (v & 0xff); } } else { int v = cpu.regA - val + (cpu.flagC ? 1 : 0) - 1; cpu.flagC = ((v & 0x10000) == 0); cpu.flagO = (((v ^ cpu.regA) & (v ^ -val) & 0x8000) > 0); cpu.regA = (v & 0xffff); } upNZ_A(); } void i_mul(int val) { int v; if (cpu.flagM) { if (cpu.flagC) v = (signed char) val * (signed char) cpu.regA; else v = (unsigned char) val * (unsigned char) cpu.regA; cpu.regA = (v & 0xff); cpu.regD = (v >> 8 & 0xff); cpu.flagN = (v < 0); cpu.flagZ = (v == 0); cpu.flagO = ((cpu.regD != 0) && (cpu.regD != 0xff)); } else { if (cpu.flagC) v = (short) val * (short) cpu.regA; else v = (unsigned short) val * (unsigned short) cpu.regA; cpu.regA = (v & 0xffff); cpu.regD = ((v >> 16) & 0xffff); cpu.flagN = (v < 0); cpu.flagZ = (v == 0); cpu.flagO = ((cpu.regD != 0) && (cpu.regD != 0xffff)); } } void i_div(int val) { int q; if (val == 0) { cpu.regA = 0; cpu.regD = 0; cpu.flagO = 1; cpu.flagZ = 0; cpu.flagN = 0; return; } if (cpu.flagM) { if (cpu.flagC) { q = (signed char) cpu.regD << 8 | cpu.regA; val = (signed char) val; } else q = (unsigned char) cpu.regD << 8 | cpu.regA; cpu.regD = (q % val & 0xff); q /= val; cpu.regA = (q & 0xff); if (cpu.flagC) cpu.flagO = ((q > 127) || (q < -128)); else cpu.flagO = (q > 255); cpu.flagZ = (cpu.regA == 0); cpu.flagN = (q < 0); } else { if (cpu.flagC) { q = (short) cpu.regD << 16 | cpu.regA; val = (short) val; } else q = (unsigned short) cpu.regD << 16 | cpu.regA; cpu.regD = (q % val & 0xffff); q /= val; cpu.regA = (q & 0xffff); if (cpu.flagC) cpu.flagO = ((q > 32767) || (q < -32768)); else cpu.flagO = (q > 65535); cpu.flagZ = (cpu.regA == 0); cpu.flagN = (q < 0); } } void i_and(int val) { cpu.regA &= val; upNZ_A(); } void i_asl(int addr) { int i = readM(addr); cpu.flagC = ((i & negM()) > 0); i = i << 1 & maskM(); upNZ(i); writeM(addr, i); } void i_lsr(int addr) { int i = readM(addr); cpu.flagC = ((i & 0x1) > 0); i = i >> 1; upNZ(i); writeM(addr, i); } void i_rol(int addr) { int i = readM(addr); int n = (i << 1 | (cpu.flagC ? 1 : 0)) & maskM(); cpu.flagC = ((i & negM()) > 0); upNZ(n); writeM(addr, n); } void i_ror(int addr) { int i = readM(addr); int n = i >> 1 | (cpu.flagC ? negM() : 0); cpu.flagC = ((i & 0x1) > 0); upNZ(n); writeM(addr, n); } void i_brc(int cond) { int n = readB(); if (cond) cpu.regPC = (cpu.regPC + (signed char) n & 0xffff); } void i_bit(int val) { if (cpu.flagM) { cpu.flagO = ((val & 0x40) > 0); cpu.flagN = ((val & 0x80) > 0); } else { cpu.flagO = ((val & 0x4000) > 0); cpu.flagN = ((val & 0x8000) > 0); } cpu.flagZ = ((val & cpu.regA) > 0); } void i_trb(int val) { cpu.flagZ = ((val & cpu.regA) > 0); cpu.regA &= (val ^ 0xffffffff); } void i_tsb(int val) { cpu.flagZ = ((val & cpu.regA) > 0); cpu.regA |= val; } void i_cmp(int reg, int val) { reg -= val; cpu.flagC = (reg >= 0); cpu.flagZ = (reg == 0); cpu.flagN = ((reg & negM()) > 0); } void i_cmpx(int reg, int val) { reg -= val; cpu.flagC = (reg >= 0); cpu.flagZ = (reg == 0); cpu.flagN = ((reg & negX()) > 0); } void i_dec(int addr) { int i = readM(addr); i = i - 1 & maskM(); writeM(addr, i); upNZ(i); } void i_inc(int addr) { int i = readM(addr); i = i + 1 & maskM(); writeM(addr, i); upNZ(i); } void i_eor(int val) { cpu.regA ^= val; upNZ_A(); } void i_or(int val) { cpu.regA |= val; upNZ_A(); } void i_mmu(int mmu) { int t; switch (mmu) { case 0x00: t = cpu.regA & 0xff; if ((t != cpu.mmuRBA) && (!cpu.no_io_penality)) cpu.rbTimeout = 1; cpu.mmuRBA = t; break; case 0x80: cpu.regA = cpu.mmuRBA; break; case 0x01: cpu.mmuRBB = cpu.regA; break; case 0x81: cpu.regA = cpu.mmuRBB; if (!cpu.flagM) break; cpu.regB = (cpu.regA >> 8); cpu.regA &= 0xff; break; case 0x02: cpu.mmuEnRB = 1; break; case 0x82: cpu.mmuEnRB = 0; break; case 0x03: cpu.mmuRBW = cpu.regA; break; case 0x83: cpu.regA = cpu.mmuRBW; if (!cpu.flagM) break; cpu.regB = (cpu.regA >> 8); cpu.regA &= 0xff; break; case 0x04: cpu.mmuEnRBW = 1; break; case 0x84: cpu.mmuEnRBW = 0; break; case 0x05: cpu.addrBRK = cpu.regA; break; case 0x85: cpu.regA = cpu.addrBRK; if (!cpu.flagM) break; cpu.regB = (cpu.regA >> 8); cpu.regA &= 0xff; break; case 0x06: cpu.addrPOR = cpu.regA; break; case 0x86: cpu.regA = cpu.addrPOR; if (!cpu.flagM) break; cpu.regB = (cpu.regA >> 8); cpu.regA &= 0xff; break; default: printf("invalid MMU parameter %02x\n",mmu); } } void executeInsn() { int insn = readMem(cpu.regPC); incPC(); int n; switch (insn) { case 0x69: i_adc(readM_PC()); break; case 0x65: i_adc(readM(readB())); break; case 0x75: i_adc(readM(readBX())); break; case 0x6d: i_adc(readM(readW_PC())); break; case 0x7d: i_adc(readM(readWX())); break; case 0x79: i_adc(readM(readWY())); break; case 0x61: i_adc(readM(readBXW())); break; case 0x71: i_adc(readM(readBWY())); break; case 0x72: i_adc(readM(readBW())); break; case 0x63: i_adc(readM(readBS())); break; case 0x73: i_adc(readM(readBSWY())); break; case 0x67: i_adc(readM(readBR())); break; case 0x77: i_adc(readM(readBRWY())); break; case 0x29: i_and(readM_PC()); break; case 0x25: i_and(readM(readB())); break; case 0x35: i_and(readM(readBX())); break; case 0x2d: i_and(readM(readW_PC())); break; case 0x3d: i_and(readM(readWX())); break; case 0x39: i_and(readM(readWY())); break; case 0x21: i_and(readM(readBXW())); break; case 0x31: i_and(readM(readBWY())); break; case 0x32: i_and(readM(readBW())); break; case 0x23: i_and(readM(readBS())); break; case 0x33: i_and(readM(readBSWY())); break; case 0x27: i_and(readM(readBR())); break; case 0x37: i_and(readM(readBRWY())); break; case 0x0a: cpu.flagC = ((cpu.regA & negM()) > 0); cpu.regA = (cpu.regA << 1 & maskM()); upNZ_A(); break; case 0x06: i_asl(readB()); break; case 0x16: i_asl(readBX()); break; case 0x0e: i_asl(readW_PC()); break; case 0x1e: i_asl(readWX()); break; case 0x90: i_brc(!cpu.flagC); break; case 0xb0: i_brc(cpu.flagC); break; case 0xf0: i_brc(cpu.flagZ); break; case 0x30: i_brc(cpu.flagN); break; case 0xd0: i_brc(!cpu.flagZ); break; case 0x10: i_brc(!cpu.flagN); break; case 0x50: i_brc(!cpu.flagO); break; case 0x70: i_brc(cpu.flagO); break; case 0x80: i_brc(1); break; case 0x89: cpu.flagZ = ((readM_PC() & cpu.regA) == 0); break; case 0x24: i_bit(readM(readB())); break; case 0x34: i_bit(readM(readBX())); break; case 0x2c: i_bit(readM(readW_PC())); break; case 0x3c: i_bit(readM(readWX())); break; case 0x00: push2(cpu.regPC); push1(getFlags()); cpu.flagBRK = 1; cpu.regPC = cpu.addrBRK; break; case 0x18: cpu.flagC = 0; break; case 0xd8: cpu.flagD = 0; break; case 0x58: cpu.flagID = 0; break; case 0xb8: cpu.flagO = 0; break; case 0xc9: i_cmp(cpu.regA, readM_PC()); break; case 0xc5: i_cmp(cpu.regA, readM(readB())); break; case 0xd5: i_cmp(cpu.regA, readM(readBX())); break; case 0xcd: i_cmp(cpu.regA, readM(readW_PC())); break; case 0xdd: i_cmp(cpu.regA, readM(readWX())); break; case 0xd9: i_cmp(cpu.regA, readM(readWY())); break; case 0xc1: i_cmp(cpu.regA, readM(readBXW())); break; case 0xd1: i_cmp(cpu.regA, readM(readBWY())); break; case 0xd2: i_cmp(cpu.regA, readM(readBW())); break; case 0xc3: i_cmp(cpu.regA, readM(readBS())); break; case 0xd3: i_cmp(cpu.regA, readM(readBSWY())); break; case 0xc7: i_cmp(cpu.regA, readM(readBR())); break; case 0xd7: i_cmp(cpu.regA, readM(readBRWY())); break; case 0xe0: i_cmpx(cpu.regX, readX_PC()); break; case 0xe4: i_cmpx(cpu.regX, readX(readB())); break; case 0xec: i_cmpx(cpu.regX, readX(readW_PC())); break; case 0xc0: i_cmpx(cpu.regY, readX_PC()); break; case 0xc4: i_cmpx(cpu.regY, readX(readB())); break; case 0xcc: i_cmpx(cpu.regY, readX(readW_PC())); break; case 0x3a: cpu.regA = (cpu.regA - 1 & maskM()); upNZ(cpu.regA); break; case 0xc6: i_dec(readB()); break; case 0xd6: i_dec(readBX()); break; case 0xce: i_dec(readW_PC()); break; case 0xde: i_dec(readWX()); break; case 0xca: cpu.regX = (cpu.regX - 1 & maskX()); upNZ(cpu.regX); break; case 0x88: cpu.regY = (cpu.regY - 1 & maskX()); upNZ(cpu.regY); break; case 0x49: i_eor(readM_PC()); break; case 0x45: i_eor(readM(readB())); break; case 0x55: i_eor(readM(readBX())); break; case 0x4d: i_eor(readM(readW_PC())); break; case 0x5d: i_eor(readM(readWX())); break; case 0x59: i_eor(readM(readWY())); break; case 0x41: i_eor(readM(readBXW())); break; case 0x51: i_eor(readM(readBWY())); break; case 0x52: i_eor(readM(readBW())); break; case 0x43: i_eor(readM(readBS())); break; case 0x53: i_eor(readM(readBSWY())); break; case 0x47: i_eor(readM(readBR())); break; case 0x57: i_eor(readM(readBRWY())); break; case 0x1a: cpu.regA = (cpu.regA + 1 & maskM()); upNZ(cpu.regA); break; case 0xe6: i_inc(readB()); break; case 0xf6: i_inc(readBX()); break; case 0xee: i_inc(readW_PC()); break; case 0xfe: i_inc(readWX()); break; case 0xe8: cpu.regX = (cpu.regX + 1 & maskX()); upNZ(cpu.regX); break; case 0xc8: cpu.regY = (cpu.regY + 1 & maskX()); upNZ(cpu.regY); break; case 0x4c: cpu.regPC = readW_PC(); break; case 0x6c: cpu.regPC = readWW(); break; case 0x7c: cpu.regPC = readWXW(); break; case 0x20: push2(cpu.regPC + 1); cpu.regPC = readW_PC(); break; case 0xfc: push2(cpu.regPC + 1); cpu.regPC = readWXW(); break; case 0xa9: cpu.regA = readM_PC(); upNZ_A(); break; case 0xa5: cpu.regA = readM(readB()); upNZ_A(); break; case 0xb5: cpu.regA = readM(readBX()); upNZ_A(); break; case 0xad: cpu.regA = readM(readW_PC()); upNZ_A(); break; case 0xbd: cpu.regA = readM(readWX()); upNZ_A(); break; case 0xb9: cpu.regA = readM(readWY()); upNZ_A(); break; case 0xa1: cpu.regA = readM(readBXW()); upNZ_A(); break; case 0xb1: cpu.regA = readM(readBWY()); upNZ_A(); break; case 0xb2: cpu.regA = readM(readBW()); upNZ_A(); break; case 0xa3: cpu.regA = readM(readBS()); upNZ_A(); break; case 0xb3: cpu.regA = readM(readBSWY()); upNZ_A(); break; case 0xa7: cpu.regA = readM(readBR()); upNZ_A(); break; case 0xb7: cpu.regA = readM(readBRWY()); upNZ_A(); break; case 0xa2: cpu.regX = readX_PC(); upNZ(cpu.regX); break; case 0xa6: cpu.regX = readX(readB()); upNZ(cpu.regX); break; case 0xb6: cpu.regX = readX(readBY()); upNZ(cpu.regX); break; case 0xae: cpu.regX = readX(readW_PC()); upNZ(cpu.regX); break; case 0xbe: cpu.regX = readX(readWY()); upNZ(cpu.regX); break; case 0xa0: cpu.regY = readX_PC(); upNZ(cpu.regY); break; case 0xa4: cpu.regY = readX(readB()); upNZ(cpu.regY); break; case 0xb4: cpu.regY = readX(readBX()); upNZ(cpu.regY); break; case 0xac: cpu.regY = readX(readW_PC()); upNZ(cpu.regY); break; case 0xbc: cpu.regY = readX(readWX()); upNZ(cpu.regY); break; case 0x4a: cpu.flagC = ((cpu.regA & 0x1) > 0); cpu.regA = cpu.regA >> 1; upNZ_A(); break; case 0x46: i_lsr(readB()); break; case 0x56: i_lsr(readBX()); break; case 0x4e: i_lsr(readW_PC()); break; case 0x5e: i_lsr(readWX()); break; case 0xea: break; case 0x09: i_or(readM_PC()); break; case 0x05: i_or(readM(readB())); break; case 0x15: i_or(readM(readBX())); break; case 0x0d: i_or(readM(readW_PC())); break; case 0x1d: i_or(readM(readWX())); break; case 0x19: i_or(readM(readWY())); break; case 0x01: i_or(readM(readBXW())); break; case 0x11: i_or(readM(readBWY())); break; case 0x12: i_or(readM(readBW())); break; case 0x03: i_or(readM(readBS())); break; case 0x13: i_or(readM(readBSWY())); break; case 0x07: i_or(readM(readBR())); break; case 0x17: i_or(readM(readBRWY())); break; case 0x48: pushM(cpu.regA); break; case 0x08: push1(getFlags()); break; case 0xda: pushX(cpu.regX); break; case 0x5a: pushX(cpu.regY); break; case 0x68: cpu.regA = popM(); upNZ_A(); break; case 0x28: setFlags(pop1()); break; case 0xfa: cpu.regX = popX(); upNZX(cpu.regX); break; case 0x7a: cpu.regY = popX(); upNZX(cpu.regY); break; case 0x2a: n = (cpu.regA << 1 | (cpu.flagC ? 1 : 0)) & maskM(); cpu.flagC = ((cpu.regA & negM()) > 0); cpu.regA = n; upNZ_A(); break; case 0x26: i_rol(readB()); break; case 0x36: i_rol(readBX()); break; case 0x2e: i_rol(readW_PC()); break; case 0x3e: i_rol(readWX()); break; case 0x6a: n = cpu.regA >> 1 | (cpu.flagC ? negM() : 0); cpu.flagC = ((cpu.regA & 0x1) > 0); cpu.regA = n; upNZ_A(); break; case 0x66: i_ror(readB()); break; case 0x76: i_ror(readBX()); break; case 0x6e: i_ror(readW_PC()); break; case 0x7e: i_ror(readWX()); break; case 0x40: setFlags(pop1()); cpu.regPC = pop2(); break; case 0x60: cpu.regPC = (pop2() + 1); break; case 0xe9: i_sbc(readM_PC()); break; case 0xe5: i_sbc(readM(readB())); break; case 0xf5: i_sbc(readM(readBX())); break; case 0xed: i_sbc(readM(readW_PC())); break; case 0xfd: i_sbc(readM(readWX())); break; case 0xf9: i_sbc(readM(readWY())); break; case 0xe1: i_sbc(readM(readBXW())); break; case 0xf1: i_sbc(readM(readBWY())); break; case 0xf2: i_sbc(readM(readBW())); break; case 0xe3: i_sbc(readM(readBS())); break; case 0xf3: i_sbc(readM(readBSWY())); break; case 0xe7: i_sbc(readM(readBR())); break; case 0xf7: i_sbc(readM(readBRWY())); break; case 0x38: cpu.flagC = 1; break; case 0xf8: cpu.flagD = 1; break; case 0x78: cpu.flagID = 1; break; case 0x85: writeM(readB(), cpu.regA); break; case 0x95: writeM(readBX(), cpu.regA); break; case 0x8d: writeM(readW_PC(), cpu.regA); break; case 0x9d: writeM(readWX(), cpu.regA); break; case 0x99: writeM(readWY(), cpu.regA); break; case 0x81: writeM(readBXW(), cpu.regA); break; case 0x91: writeM(readBWY(), cpu.regA); break; case 0x92: writeM(readBW(), cpu.regA); break; case 0x83: writeM(readBS(), cpu.regA); break; case 0x93: writeM(readBSWY(), cpu.regA); break; case 0x87: writeM(readBR(), cpu.regA); break; case 0x97: writeM(readBRWY(), cpu.regA); break; case 0x86: writeX(readB(), cpu.regX); break; case 0x96: writeX(readBY(), cpu.regX); break; case 0x8e: writeX(readW_PC(), cpu.regX); break; case 0x84: writeX(readB(), cpu.regY); break; case 0x94: writeX(readBX(), cpu.regY); break; case 0x8c: writeX(readW_PC(), cpu.regY); break; case 0xaa: cpu.regX = cpu.regA; if (cpu.flagX) cpu.regX &= 0xff; upNZX(cpu.regX); break; case 0xa8: cpu.regY = cpu.regA; if (cpu.flagX) cpu.regY &= 0xff; upNZX(cpu.regY); break; case 0xba: cpu.regX = cpu.regSP; if (cpu.flagX) cpu.regX &= 0xff; upNZX(cpu.regX); break; case 0x8a: cpu.regA = cpu.regX; if (cpu.flagM) cpu.regA &= 0xff; upNZ_A(); break; case 0x9a: if (cpu.flagX) cpu.regSP = (cpu.regSP & 0xff00 | cpu.regX & 0xff); else cpu.regSP = cpu.regX; upNZX(cpu.regX); break; case 0x98: cpu.regA = cpu.regY; if (cpu.flagM) cpu.regA &= 0xff; upNZX(cpu.regY); break; case 0x64: writeM(readB(), 0); break; case 0x74: writeM(readBX(), 0); break; case 0x9c: writeM(readW_PC(), 0); break; case 0x9e: writeM(readWX(), 0); break; case 0x14: i_trb(readM(readB())); break; case 0x1c: i_trb(readM(readW_PC())); break; case 0x04: i_tsb(readM(readB())); break; case 0x0c: i_tsb(readM(readW_PC())); break; case 0xdb: cpu.regPC--; break; case 0xcb: cpu.waiTimeout = 1; break; case 0x9b: cpu.regY = cpu.regX; upNZX(cpu.regY); break; case 0xbb: cpu.regX = cpu.regY; upNZX(cpu.regX); break; case 0xf4: push2(readW_PC()); break; case 0xd4: push2(readBW()); break; case 0x62: n = readB(); push2(cpu.regPC + n); break; case 0xeb: if (cpu.flagM) { n = cpu.regA; cpu.regA = cpu.regB; cpu.regB = n; } else { cpu.regA = (cpu.regA >> 8 & 0xff | cpu.regA << 8 & 0xff00); } break; case 0xfb: if (cpu.flagE == cpu.flagC) break; if (cpu.flagE) { cpu.flagE = 0; cpu.flagC = 1; } else { cpu.flagE = 1; cpu.flagC = 0; if (!cpu.flagM) cpu.regB = (cpu.regA >> 8); cpu.flagM = 1; cpu.flagX = 1; cpu.regA &= 0xff; cpu.regX &= 0xff; cpu.regY &= 0xff; } break; case 0xc2: setFlags(getFlags() & (readB() ^ 0xffffffff)); break; case 0xe2: setFlags(getFlags() | readB()); break; case 0x8b: if (cpu.flagX) cpu.regSP = (cpu.regR & 0xff00 | cpu.regX & 0xff); else cpu.regR = cpu.regX; upNZX(cpu.regR); break; case 0xab: cpu.regX = cpu.regR; if (cpu.flagX) cpu.regX &= 0xff; upNZX(cpu.regX); break; case 0x44: push2r(readW_PC()); break; case 0x54: push2r(readBW()); break; case 0x82: n = readB(); push2r(cpu.regPC + n); break; case 0x3b: cpu.regX = popXr(); upNZX(cpu.regX); break; case 0x6b: cpu.regA = popMr(); upNZ(cpu.regA); break; case 0x7b: cpu.regY = popXr(); upNZX(cpu.regY); break; case 0x1b: pushXr(cpu.regX); break; case 0x4b: pushMr(cpu.regA); break; case 0x5b: pushXr(cpu.regY); break; case 0x0b: push2r(cpu.regI); break; case 0x2b: cpu.regI = pop2r(); upNZX(cpu.regI); break; case 0x5c: cpu.regI = cpu.regX; upNZX(cpu.regX); break; case 0xdc: cpu.regX = cpu.regI; if (cpu.flagX) cpu.regX &= 0xff; upNZX(cpu.regX); break; case 0x02: cpu.regPC = readW(cpu.regI); cpu.regI += 2; break; case 0x42: if (cpu.flagM) { cpu.regA = readMem(cpu.regI); cpu.regI += 1; } else { cpu.regA = readW(cpu.regI); cpu.regI += 2; } break; case 0x22: push2r(cpu.regI); cpu.regI = (cpu.regPC + 2); cpu.regPC = readW(cpu.regPC); break; case 0x0f: i_mul(readM(readB())); break; case 0x1f: i_mul(readM(readBX())); break; case 0x2f: i_mul(readM(readW_PC())); break; case 0x3f: i_mul(readM(readWX())); break; case 0x4f: i_div(readM(readB())); break; case 0x5f: i_div(readM(readBX())); break; case 0x6f: i_div(readM(readW_PC())); break; case 0x7f: i_div(readM(readWX())); break; case 0x8f: cpu.regD = 0; cpu.regB = 0; break; case 0x9f: cpu.regD = ((cpu.regA & negM()) > 0 ? 0xffff : 0); cpu.regB = (cpu.regD & 0xff); break; case 0xaf: cpu.regA = cpu.regD; if (cpu.flagM) cpu.regA &= 0xff; upNZ(cpu.regA); break; case 0xbf: if (cpu.flagM) cpu.regD = (cpu.regA | cpu.regB << 8); else { cpu.regD = cpu.regA; } upNZ(cpu.regA); break; case 0xcf: cpu.regD = popM(); break; case 0xdf: pushM(cpu.regD); break; case 0xef: i_mmu(readB()); break; } } void emulateframe() { int i = 0; cpu.rbTimeout = 0; cpu.waiTimeout = 0; cpu.brk = 0; cpu.cycles += cpu.cycles_per_tick; cpu.ticks ++; if (cpu.cycles > 100000) cpu.cycles = 100000; while ((cpu.cycles > 0) && (!cpu.waiTimeout) && (!cpu.rbTimeout) && (!cpu.brk)) { cpu.cycles --; executeInsn(); i = 0; while ( (i <= cpu.breakpoint_count) && ((cpu.breakpoints[i] & 0x1ffff) != (cpu.regPC | 0x10000)) ) i++; if (i <= cpu.breakpoint_count) // breakpoint hit { cpu.cycles = 0; cpu.brk = 1; } } }