#include #include #include "dat.h" #include "fns.h" u8int rA, rS, rX, rY, rP; u16int pc; int irq, nmi; void nz(u8int v) { rP &= ~(Negative | Zero); if(v & 0x80) rP |= Negative; if(v == 0) rP |= Zero; } void adc(u8int d) { int r; r = rA + d + (rP & Carry); rP &= ~(Negative | Zero | Overflow | Carry); if(r > 0xFF) rP |= Carry; if(r & 0x80) rP |= Negative; if((~(rA ^ d) & (rA ^ r)) & 0x80) rP |= Overflow; rA = r; if(rA == 0) rP |= Zero; } void sbc(u8int d) { int r; r = rA + (u8int)~d + (rP & Carry); rP &= ~(Negative | Zero | Overflow | Carry); if(r > 0xFF) rP |= Carry; if((~(rA ^ d) & (rA ^ r)) & 0x80) rP |= Overflow; rA = r; if(rA == 0) rP |= Zero; if(rA & 0x80) rP |= Negative; } void asl(u16int a) { u8int v; v = memread(a); rP &= ~(Negative | Zero | Carry); if(v & 0x80) rP |= Carry; v <<= 1; if(v == 0) rP |= Zero; if(v & 0x80) rP |= Negative; memwrite(a, v); } void lsr(u16int a) { u8int v; v = memread(a); rP &= ~(Negative | Zero | Carry); rP |= v & 1; v >>= 1; if(v == 0) rP |= Zero; if(v & 0x80) rP |= Negative; memwrite(a, v); } void rol(u16int a) { u8int v, b; v = memread(a); b = rP & Carry; rP &= ~(Carry | Negative | Zero); if(v & 0x80) rP |= Carry; v = (v << 1) | b; if(v & 0x80) rP |= Negative; if(v == 0) rP |= Zero; memwrite(a, v); } void ror(u16int a) { u8int v, b; v = memread(a); b = rP & Carry; rP &= ~(Carry | Negative | Zero); rP |= v & 1; v = (v >> 1) | (b << 7); if(v & 0x80) rP |= Negative; if(v == 0) rP |= Zero; memwrite(a, v); } void cmp(u8int A, u8int B) { rP &= ~(Negative | Zero | Carry); if(A == B) rP |= Zero; if(A >= B) rP |= Carry; if((A - B) & 0x80) rP |= Negative; } void inc(u16int a) { u8int v; v = memread(a); v++; nz(v); memwrite(a, v); } void dec(u16int a) { u8int v; v = memread(a); v--; nz(v); memwrite(a, v); } int branch(void) { s8int t; u16int npc; t = fetch8(); npc = pc+t; if((npc ^ pc) >> 8){ pc = npc; return 4; } pc = npc; return 3; } u16int aindX(void) { u8int r; u16int b; r = fetch8() + rX; b = memread(r++); b |= memread(r) << 8; return b; } u16int aindY(int *p) { u8int r; u16int b; r = fetch8(); b = memread(r++) + rY; *p = b > 0xFF; b += memread(r) << 8; return b; } void interrupt(int nmi, int brk) { push16(pc); push8(rP | 0x20 | (brk << 4)); pc = memread(0xFFFA | (!nmi << 2)); pc |= memread(0xFFFB | (!nmi << 2)) << 8; rP |= Interrupt; } #define zp() mem[fetch8()] #define zpX() mem[(u8int)(fetch8()+rX)] #define zpY() mem[(u8int)(fetch8()+rY)] #define abso() mem[fetch16()] #define absX() mem[a = fetch16()+rX] #define absY() mem[a = fetch16()+rY] #define indX() mem[aindX()] #define indY(c) mem[aindY(c)] int step(void) { u8int op; u16int a, v, cpc; int c; if(nmi) if(--nmi == 0){ interrupt(1, 0); nmi = 0; return 7; } if(irq && (rP & Interrupt) == 0){ interrupt(0, 0); return 7; } cpc = pc; op = fetch8(); print("%02x %08b %08b %08b %08b %04x %02x\n", op, rA, rX, rY, rP, cpc, rS); switch(op){ case 0x00: pc++; interrupt(0, 1); return 7; case 0x01: nz(rA |= indX()); return 6; case 0x05: nz(rA |= zp()); return 3; case 0x06: asl(fetch8()); return 5; case 0x08: push8(rP | 0x30); return 3; case 0x09: nz(rA |= fetch8()); return 2; case 0x0A: rP &= ~(Negative | Zero | Carry); if(rA & 0x80) rP |= Carry; rA <<= 1; if(rA == 0) rP |= Zero; if(rA & 0x80) rP |= Negative; return 2; case 0x0D: nz(rA |= abso()); return 4; case 0x0E: asl(fetch16()); return 6; case 0x10: if((rP & Negative) == 0) return branch(); pc++; return 2; case 0x11: nz(rA |= indY(&c)); return 5+c; case 0x15: nz(rA |= zpX()); return 4; case 0x16: asl((u8int)(fetch8() + rX)); return 6; case 0x18: rP &= ~Carry; return 2; case 0x19: nz(rA |= absY()); return 4 + ((u8int)a < rY); case 0x1D: nz(rA |= absX()); return 4 + ((u8int)a < rX); case 0x1E: asl(fetch16() + rX); return 7; case 0x20: push16(pc+1); pc = fetch16(); return 6; case 0x21: nz(rA &= indX()); return 6; case 0x24: a = mem[fetch8()]; rP &= ~(Negative | Zero | Overflow); rP |= a & 0xC0; if((a & rA) == 0) rP |= Zero; return 3; case 0x25: nz(rA &= zp()); return 3; case 0x26: rol(fetch8()); return 5; case 0x28: rP = pop8() & 0xcf; return 4; case 0x29: nz(rA &= fetch8()); return 2; case 0x2A: a = rP & Carry; rP &= ~(Carry | Zero | Negative); if(rA & 0x80) rP |= Carry; rA = (rA << 1) | a; if(rA & 0x80) rP |= Negative; if(rA == 0) rP |= Zero; return 2; case 0x2C: a = mem[fetch16()]; rP &= ~(Negative | Zero | Overflow); rP |= a & 0xC0; if((a & rA) == 0) rP |= Zero; return 4; case 0x2D: nz(rA &= abso()); return 4; case 0x2E: rol(fetch16()); return 6; case 0x30: if((rP & Negative) != 0) return branch(); pc++; return 3; case 0x31: nz(rA &= indY(&c)); return 5+c; case 0x35: nz(rA &= zpX()); return 4; case 0x36: rol((u8int)(fetch8() + rX)); return 6; case 0x38: rP |= Carry; return 2; case 0x39: nz(rA &= absY()); return 4 + ((u8int)a < rY); case 0x3E: rol(fetch16() + rX); return 7; case 0x3D: nz(rA &= absX()); return 4 + ((u8int)a < rX); case 0x40: rP = pop8() & 0xcf; pc = pop16(); return 6; case 0x41: nz(rA ^= indX()); return 6; case 0x45: nz(rA ^= zp()); return 3; case 0x46: lsr(fetch8()); return 5; case 0x48: push8(rA); return 3; case 0x49: nz(rA ^= fetch8()); return 2; case 0x4A: rP &= ~(Negative | Zero | Carry); rP |= rA & 1; rA >>= 1; if(rA == 0) rP |= Zero; if(rA & 0x80) rP |= Negative; return 2; case 0x4C: pc = fetch16(); return 3; case 0x4D: nz(rA ^= abso()); return 4; case 0x4E: lsr(fetch16()); return 6; case 0x51: nz(rA ^= indY(&c)); return 5+c; case 0x56: lsr((u8int)(fetch8() + rX)); return 6; case 0x58: rP &= ~Interrupt; return 2; case 0x50: if((rP & Overflow) == 0) return branch(); pc++; return 3; case 0x55: nz(rA ^= zpX()); return 4; case 0x59: nz(rA ^= absY()); return 4 + ((u8int)a < rX); case 0x5D: nz(rA ^= absX()); return 4 + ((u8int)a < rX); case 0x5E: lsr(fetch16() + rX); return 7; case 0x60: pc = pop16() + 1; return 6; case 0x61: adc(indX()); return 6; case 0x65: adc(zp()); return 3; case 0x66: ror(fetch8()); return 5; case 0x68: nz(rA = pop8()); return 4; case 0x69: adc(fetch8()); return 2; case 0x6A: a = rP & Carry; rP &= ~(Carry | Negative | Zero); rP |= rA & 1; rA = (rA >> 1) | (a << 7); if(rA & 0x80) rP |= Negative; if(rA == 0) rP |= Zero; return 2; case 0x6C: v = fetch16(); pc = mem[v] | (mem[(v & 0xFF00) | (u8int)(v+1)] << 8); return 5; case 0x6D: adc(abso()); return 4; case 0x6E: ror(fetch16()); return 6; case 0x70: if((rP & Overflow) != 0) return branch(); pc++; return 3; case 0x71: adc(indY(&c)); return 5+c; case 0x75: adc(zpX()); return 4; case 0x76: ror((u8int)(fetch8() + rX)); return 6; case 0x78: rP |= Interrupt; return 2; case 0x79: adc(absY()); return 4 + ((u8int)a < rY); case 0x7D: adc(absX()); return 4 + ((u8int)a < rX); case 0x7E: ror(fetch16() + rX); return 7; case 0x81: mem[aindX()] = rA; return 6; case 0x84: mem[fetch8()] = rY; return 3; case 0x85: mem[fetch8()] = rA; return 3; case 0x86: mem[fetch8()] = rX; return 3; case 0x88: nz(--rY); return 2; case 0x8A: nz(rA = rX); return 2; case 0x8C: mem[fetch16()] = rY; return 4; case 0x8D: mem[fetch16()] = rA; return 4; case 0x8E: mem[fetch16()] = rX; return 4; case 0x90: if((rP & Carry) == 0) return branch(); pc++; return 3; case 0x91: mem[aindY(&c)] = rA; return 6; case 0x94: mem[(u8int)(fetch8() + rX)] = rY; return 4; case 0x95: mem[(u8int)(fetch8() + rX)] = rA; return 4; case 0x96: mem[(u8int)(fetch8() + rY)] = rX; return 4; case 0x98: nz(rA = rY); return 2; case 0x99: mem[fetch16() + rY] = rA; return 5; case 0x9A: rS = rX; return 2; case 0x9D: mem[fetch16() + rX] = rA; return 5; case 0xA0: nz(rY = fetch8()); return 2; case 0xA1: nz(rA = indX()); return 6; case 0xA2: nz(rX = fetch8()); return 2; case 0xA4: nz(rY = zp()); return 3; case 0xA5: nz(rA = zp()); return 3; case 0xA6: nz(rX = zp()); return 3; case 0xA8: nz(rY = rA); return 2; case 0xA9: nz(rA = fetch8()); return 2; case 0xAA: nz(rX = rA); return 2; case 0xAC: nz(rY = abso()); return 4; case 0xAE: nz(rX = abso()); return 4; case 0xAD: nz(rA = abso()); return 4; case 0xB0: if((rP & Carry) != 0) return branch(); pc++; return 3; case 0xB1: nz(rA = indY(&c)); return 5+c; case 0xB4: nz(rY = zpX()); return 4; case 0xB5: nz(rA = zpX()); return 4; case 0xB6: nz(rX = zpY()); return 4; case 0xB8: rP &= ~Overflow; return 2; case 0xB9: nz(rA = absY()); return 4 + ((u8int)a < rY); case 0xBA: nz(rX = rS); return 2; case 0xBC: nz(rY = absX()); return 4 + ((u8int)a < rX); case 0xBD: nz(rA = absX()); return 4 + ((u8int)a < rX); case 0xBE: nz(rX = absY()); return 4 + ((u8int)a < rY); case 0xC1: cmp(rA, indX()); return 6; case 0xC5: cmp(rA, zp()); return 3; case 0xC9: cmp(rA, fetch8()); return 2; case 0xCD: cmp(rA, abso()); return 4; case 0xD0: if((rP & Zero) == 0) return branch(); pc++; return 3; case 0xD1: cmp(rA, indY(&c)); return 5 + c; case 0xD5: cmp(rA, zpX()); return 4; case 0xD8: rP &= ~Decimal; return 2; case 0xD9: cmp(rA, absY()); return 4 + ((u8int)a < rY); case 0xDD: cmp(rA, absX()); return 4 + ((u8int)a < rX); case 0xC0: cmp(rY, fetch8()); return 2; case 0xC4: cmp(rY, zp()); return 3; case 0xC6: dec(fetch8()); return 5; case 0xC8: nz(++rY); return 2; case 0xCA: nz(--rX); return 2; case 0xCC: cmp(rY, abso()); return 4; case 0xCE: dec(fetch16()); return 6; case 0xD6: dec((u8int)(fetch8() + rX)); return 6; case 0xDE: dec(fetch16() + rX); return 7; case 0xE0: cmp(rX, fetch8()); return 2; case 0xE1: sbc(indX()); return 6; case 0xE4: cmp(rX, zp()); return 3; case 0xE5: sbc(zp()); return 3; case 0xE6: inc(fetch8()); return 5; case 0xE8: nz(++rX); return 2; case 0xE9: sbc(fetch8()); return 2; case 0xEA: return 2; case 0xEC: cmp(rX, abso()); return 4; case 0xED: sbc(abso()); return 4; case 0xEE: inc(fetch16()); return 6; case 0xF0: if((rP & Zero) != 0) return branch(); pc++; return 3; case 0xF1: sbc(indY(&c)); return 5+c; case 0xF5: sbc(zpX()); return 4; case 0xF6: inc((u8int)(fetch8() + rX)); return 6; case 0xF8: rP |= Decimal; return 2; case 0xF9: sbc(absY()); return 4 + ((u8int)a < rY); case 0xFD: sbc(absX()); return 4 + ((u8int)a < rX); case 0xFE: inc(fetch16() + rX); return 7; default: print("unimplemented %#02x\n", op); exits(nil); case 0xFF: print("%s\n", (s8int*)mem+0x500); exits(nil); } }