Simplify op table (#194)

This commit is contained in:
Will Scullin 2023-08-06 20:59:25 -07:00 committed by GitHub
parent 44fef94b4d
commit 9f7c9f25f9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 343 additions and 354 deletions

View File

@ -147,23 +147,13 @@ type WriteFn = (val: byte) => void;
type ReadAddrFn = (opts?: Opts) => word; type ReadAddrFn = (opts?: Opts) => word;
type ImpliedFn = () => void; type ImpliedFn = () => void;
interface Instruction<T = unknown> { interface Instruction {
name: string; name: string;
mode: Mode; mode: Mode;
op: (fn: T) => void; fn: () => void;
modeFn: T;
} }
type StrictInstruction = type Instructions = Record<byte, Instruction>;
Instruction<ReadFn> |
Instruction<WriteFn> |
Instruction<ReadAddrFn> |
Instruction<ImpliedFn> |
Instruction<flag> |
Instruction<flag|0> |
Instruction<byte>;
type Instructions = Record<byte, StrictInstruction>;
type callback = (cpu: CPU6502) => boolean | void; type callback = (cpu: CPU6502) => boolean | void;
@ -1345,13 +1335,12 @@ export default class CPU6502 {
}; };
private unknown(b: byte) { private unknown(b: byte) {
let unk: StrictInstruction; let unk: Instruction;
if (this.is65C02) { if (this.is65C02) {
// Default behavior is a 1 cycle NOP // Default behavior is a 1 cycle NOP
unk = { unk = {
name: 'NOP', name: 'NOP',
op: this.nop, fn: () => this.nop(this.readNopImplied),
modeFn: this.readNopImplied,
mode: 'implied', mode: 'implied',
}; };
} else { } else {
@ -1365,7 +1354,7 @@ export default class CPU6502 {
this.sync = true; this.sync = true;
this.op = this.opary[this.readBytePC()]; this.op = this.opary[this.readBytePC()];
this.sync = false; this.sync = false;
this.op.op(this.op.modeFn); this.op.fn();
cb?.(this); cb?.(this);
} }
@ -1375,7 +1364,7 @@ export default class CPU6502 {
this.sync = true; this.sync = true;
this.op = this.opary[this.readBytePC()]; this.op = this.opary[this.readBytePC()];
this.sync = false; this.sync = false;
this.op.op(this.op.modeFn); this.op.fn();
if (cb?.(this)) { if (cb?.(this)) {
return; return;
@ -1390,7 +1379,7 @@ export default class CPU6502 {
this.sync = true; this.sync = true;
this.op = this.opary[this.readBytePC()]; this.op = this.opary[this.readBytePC()];
this.sync = false; this.sync = false;
this.op.op(this.op.modeFn); this.op.fn();
} }
} }
@ -1401,7 +1390,7 @@ export default class CPU6502 {
this.sync = true; this.sync = true;
this.op = this.opary[this.readBytePC()]; this.op = this.opary[this.readBytePC()];
this.sync = false; this.sync = false;
this.op.op(this.op.modeFn); this.op.fn();
if (cb?.(this)) { if (cb?.(this)) {
return; return;
@ -1564,551 +1553,551 @@ export default class CPU6502 {
OPS_6502: Instructions = { OPS_6502: Instructions = {
// LDA // LDA
0xa9: { name: 'LDA', op: this.lda, modeFn: this.readImmediate, mode: 'immediate' }, 0xa9: { name: 'LDA', fn: () => this.lda(this.readImmediate), mode: 'immediate' },
0xa5: { name: 'LDA', op: this.lda, modeFn: this.readZeroPage, mode: 'zeroPage' }, 0xa5: { name: 'LDA', fn: () => this.lda(this.readZeroPage), mode: 'zeroPage' },
0xb5: { name: 'LDA', op: this.lda, modeFn: this.readZeroPageX, mode: 'zeroPageX' }, 0xb5: { name: 'LDA', fn: () => this.lda(this.readZeroPageX), mode: 'zeroPageX' },
0xad: { name: 'LDA', op: this.lda, modeFn: this.readAbsolute, mode: 'absolute' }, 0xad: { name: 'LDA', fn: () => this.lda(this.readAbsolute), mode: 'absolute' },
0xbd: { name: 'LDA', op: this.lda, modeFn: this.readAbsoluteX, mode: 'absoluteX' }, 0xbd: { name: 'LDA', fn: () => this.lda(this.readAbsoluteX), mode: 'absoluteX' },
0xb9: { name: 'LDA', op: this.lda, modeFn: this.readAbsoluteY, mode: 'absoluteY' }, 0xb9: { name: 'LDA', fn: () => this.lda(this.readAbsoluteY), mode: 'absoluteY' },
0xa1: { name: 'LDA', op: this.lda, modeFn: this.readZeroPageXIndirect, mode: 'zeroPageXIndirect' }, 0xa1: { name: 'LDA', fn: () => this.lda(this.readZeroPageXIndirect), mode: 'zeroPageXIndirect' },
0xb1: { name: 'LDA', op: this.lda, modeFn: this.readZeroPageIndirectY, mode: 'zeroPageIndirectY' }, 0xb1: { name: 'LDA', fn: () => this.lda(this.readZeroPageIndirectY), mode: 'zeroPageIndirectY' },
// LDX // LDX
0xa2: { name: 'LDX', op: this.ldx, modeFn: this.readImmediate, mode: 'immediate' }, 0xa2: { name: 'LDX', fn: () => this.ldx(this.readImmediate), mode: 'immediate' },
0xa6: { name: 'LDX', op: this.ldx, modeFn: this.readZeroPage, mode: 'zeroPage' }, 0xa6: { name: 'LDX', fn: () => this.ldx(this.readZeroPage), mode: 'zeroPage' },
0xb6: { name: 'LDX', op: this.ldx, modeFn: this.readZeroPageY, mode: 'zeroPageY' }, 0xb6: { name: 'LDX', fn: () => this.ldx(this.readZeroPageY), mode: 'zeroPageY' },
0xae: { name: 'LDX', op: this.ldx, modeFn: this.readAbsolute, mode: 'absolute' }, 0xae: { name: 'LDX', fn: () => this.ldx(this.readAbsolute), mode: 'absolute' },
0xbe: { name: 'LDX', op: this.ldx, modeFn: this.readAbsoluteY, mode: 'absoluteY' }, 0xbe: { name: 'LDX', fn: () => this.ldx(this.readAbsoluteY), mode: 'absoluteY' },
// LDY // LDY
0xa0: { name: 'LDY', op: this.ldy, modeFn: this.readImmediate, mode: 'immediate' }, 0xa0: { name: 'LDY', fn: () => this.ldy(this.readImmediate), mode: 'immediate' },
0xa4: { name: 'LDY', op: this.ldy, modeFn: this.readZeroPage, mode: 'zeroPage' }, 0xa4: { name: 'LDY', fn: () => this.ldy(this.readZeroPage), mode: 'zeroPage' },
0xb4: { name: 'LDY', op: this.ldy, modeFn: this.readZeroPageX, mode: 'zeroPageX' }, 0xb4: { name: 'LDY', fn: () => this.ldy(this.readZeroPageX), mode: 'zeroPageX' },
0xac: { name: 'LDY', op: this.ldy, modeFn: this.readAbsolute, mode: 'absolute' }, 0xac: { name: 'LDY', fn: () => this.ldy(this.readAbsolute), mode: 'absolute' },
0xbc: { name: 'LDY', op: this.ldy, modeFn: this.readAbsoluteX, mode: 'absoluteX' }, 0xbc: { name: 'LDY', fn: () => this.ldy(this.readAbsoluteX), mode: 'absoluteX' },
// STA // STA
0x85: { name: 'STA', op: this.sta, modeFn: this.writeZeroPage, mode: 'zeroPage' }, 0x85: { name: 'STA', fn: () => this.sta(this.writeZeroPage), mode: 'zeroPage' },
0x95: { name: 'STA', op: this.sta, modeFn: this.writeZeroPageX, mode: 'zeroPageX' }, 0x95: { name: 'STA', fn: () => this.sta(this.writeZeroPageX), mode: 'zeroPageX' },
0x8d: { name: 'STA', op: this.sta, modeFn: this.writeAbsolute, mode: 'absolute' }, 0x8d: { name: 'STA', fn: () => this.sta(this.writeAbsolute), mode: 'absolute' },
0x9d: { name: 'STA', op: this.sta, modeFn: this.writeAbsoluteX, mode: 'absoluteX' }, 0x9d: { name: 'STA', fn: () => this.sta(this.writeAbsoluteX), mode: 'absoluteX' },
0x99: { name: 'STA', op: this.sta, modeFn: this.writeAbsoluteY, mode: 'absoluteY' }, 0x99: { name: 'STA', fn: () => this.sta(this.writeAbsoluteY), mode: 'absoluteY' },
0x81: { name: 'STA', op: this.sta, modeFn: this.writeZeroPageXIndirect, mode: 'zeroPageXIndirect' }, 0x81: { name: 'STA', fn: () => this.sta(this.writeZeroPageXIndirect), mode: 'zeroPageXIndirect' },
0x91: { name: 'STA', op: this.sta, modeFn: this.writeZeroPageIndirectY, mode: 'zeroPageIndirectY' }, 0x91: { name: 'STA', fn: () => this.sta(this.writeZeroPageIndirectY), mode: 'zeroPageIndirectY' },
// STX // STX
0x86: { name: 'STX', op: this.stx, modeFn: this.writeZeroPage, mode: 'zeroPage' }, 0x86: { name: 'STX', fn: () => this.stx(this.writeZeroPage), mode: 'zeroPage' },
0x96: { name: 'STX', op: this.stx, modeFn: this.writeZeroPageY, mode: 'zeroPageY' }, 0x96: { name: 'STX', fn: () => this.stx(this.writeZeroPageY), mode: 'zeroPageY' },
0x8e: { name: 'STX', op: this.stx, modeFn: this.writeAbsolute, mode: 'absolute' }, 0x8e: { name: 'STX', fn: () => this.stx(this.writeAbsolute), mode: 'absolute' },
// STY // STY
0x84: { name: 'STY', op: this.sty, modeFn: this.writeZeroPage, mode: 'zeroPage' }, 0x84: { name: 'STY', fn: () => this.sty(this.writeZeroPage), mode: 'zeroPage' },
0x94: { name: 'STY', op: this.sty, modeFn: this.writeZeroPageX, mode: 'zeroPageX' }, 0x94: { name: 'STY', fn: () => this.sty(this.writeZeroPageX), mode: 'zeroPageX' },
0x8c: { name: 'STY', op: this.sty, modeFn: this.writeAbsolute, mode: 'absolute' }, 0x8c: { name: 'STY', fn: () => this.sty(this.writeAbsolute), mode: 'absolute' },
// ADC // ADC
0x69: { name: 'ADC', op: this.adc, modeFn: this.readImmediate, mode: 'immediate' }, 0x69: { name: 'ADC', fn: () => this.adc(this.readImmediate), mode: 'immediate' },
0x65: { name: 'ADC', op: this.adc, modeFn: this.readZeroPage, mode: 'zeroPage' }, 0x65: { name: 'ADC', fn: () => this.adc(this.readZeroPage), mode: 'zeroPage' },
0x75: { name: 'ADC', op: this.adc, modeFn: this.readZeroPageX, mode: 'zeroPageX' }, 0x75: { name: 'ADC', fn: () => this.adc(this.readZeroPageX), mode: 'zeroPageX' },
0x6D: { name: 'ADC', op: this.adc, modeFn: this.readAbsolute, mode: 'absolute' }, 0x6D: { name: 'ADC', fn: () => this.adc(this.readAbsolute), mode: 'absolute' },
0x7D: { name: 'ADC', op: this.adc, modeFn: this.readAbsoluteX, mode: 'absoluteX' }, 0x7D: { name: 'ADC', fn: () => this.adc(this.readAbsoluteX), mode: 'absoluteX' },
0x79: { name: 'ADC', op: this.adc, modeFn: this.readAbsoluteY, mode: 'absoluteY' }, 0x79: { name: 'ADC', fn: () => this.adc(this.readAbsoluteY), mode: 'absoluteY' },
0x61: { name: 'ADC', op: this.adc, modeFn: this.readZeroPageXIndirect, mode: 'zeroPageXIndirect' }, 0x61: { name: 'ADC', fn: () => this.adc(this.readZeroPageXIndirect), mode: 'zeroPageXIndirect' },
0x71: { name: 'ADC', op: this.adc, modeFn: this.readZeroPageIndirectY, mode: 'zeroPageIndirectY' }, 0x71: { name: 'ADC', fn: () => this.adc(this.readZeroPageIndirectY), mode: 'zeroPageIndirectY' },
// SBC // SBC
0xe9: { name: 'SBC', op: this.sbc, modeFn: this.readImmediate, mode: 'immediate' }, 0xe9: { name: 'SBC', fn: () => this.sbc(this.readImmediate), mode: 'immediate' },
0xe5: { name: 'SBC', op: this.sbc, modeFn: this.readZeroPage, mode: 'zeroPage' }, 0xe5: { name: 'SBC', fn: () => this.sbc(this.readZeroPage), mode: 'zeroPage' },
0xf5: { name: 'SBC', op: this.sbc, modeFn: this.readZeroPageX, mode: 'zeroPageX' }, 0xf5: { name: 'SBC', fn: () => this.sbc(this.readZeroPageX), mode: 'zeroPageX' },
0xeD: { name: 'SBC', op: this.sbc, modeFn: this.readAbsolute, mode: 'absolute' }, 0xeD: { name: 'SBC', fn: () => this.sbc(this.readAbsolute), mode: 'absolute' },
0xfD: { name: 'SBC', op: this.sbc, modeFn: this.readAbsoluteX, mode: 'absoluteX' }, 0xfD: { name: 'SBC', fn: () => this.sbc(this.readAbsoluteX), mode: 'absoluteX' },
0xf9: { name: 'SBC', op: this.sbc, modeFn: this.readAbsoluteY, mode: 'absoluteY' }, 0xf9: { name: 'SBC', fn: () => this.sbc(this.readAbsoluteY), mode: 'absoluteY' },
0xe1: { name: 'SBC', op: this.sbc, modeFn: this.readZeroPageXIndirect, mode: 'zeroPageXIndirect' }, 0xe1: { name: 'SBC', fn: () => this.sbc(this.readZeroPageXIndirect), mode: 'zeroPageXIndirect' },
0xf1: { name: 'SBC', op: this.sbc, modeFn: this.readZeroPageIndirectY, mode: 'zeroPageIndirectY' }, 0xf1: { name: 'SBC', fn: () => this.sbc(this.readZeroPageIndirectY), mode: 'zeroPageIndirectY' },
// INC // INC
0xe6: { name: 'INC', op: this.inc, modeFn: this.readAddrZeroPage, mode: 'zeroPage' }, 0xe6: { name: 'INC', fn: () => this.inc(this.readAddrZeroPage), mode: 'zeroPage' },
0xf6: { name: 'INC', op: this.inc, modeFn: this.readAddrZeroPageX, mode: 'zeroPageX' }, 0xf6: { name: 'INC', fn: () => this.inc(this.readAddrZeroPageX), mode: 'zeroPageX' },
0xee: { name: 'INC', op: this.inc, modeFn: this.readAddrAbsolute, mode: 'absolute' }, 0xee: { name: 'INC', fn: () => this.inc(this.readAddrAbsolute), mode: 'absolute' },
0xfe: { name: 'INC', op: this.inc, modeFn: this.readAddrAbsoluteX, mode: 'absoluteX' }, 0xfe: { name: 'INC', fn: () => this.inc(this.readAddrAbsoluteX), mode: 'absoluteX' },
// INX // INX
0xe8: { name: 'INX', op: this.inx, modeFn: this.implied, mode: 'implied' }, 0xe8: { name: 'INX', fn: () => this.inx(), mode: 'implied' },
// INY // INY
0xc8: { name: 'INY', op: this.iny, modeFn: this.implied, mode: 'implied' }, 0xc8: { name: 'INY', fn: () => this.iny(), mode: 'implied' },
// DEC // DEC
0xc6: { name: 'DEC', op: this.dec, modeFn: this.readAddrZeroPage, mode: 'zeroPage' }, 0xc6: { name: 'DEC', fn: () => this.dec(this.readAddrZeroPage), mode: 'zeroPage' },
0xd6: { name: 'DEC', op: this.dec, modeFn: this.readAddrZeroPageX, mode: 'zeroPageX' }, 0xd6: { name: 'DEC', fn: () => this.dec(this.readAddrZeroPageX), mode: 'zeroPageX' },
0xce: { name: 'DEC', op: this.dec, modeFn: this.readAddrAbsolute, mode: 'absolute' }, 0xce: { name: 'DEC', fn: () => this.dec(this.readAddrAbsolute), mode: 'absolute' },
0xde: { name: 'DEC', op: this.dec, modeFn: this.readAddrAbsoluteX, mode: 'absoluteX' }, 0xde: { name: 'DEC', fn: () => this.dec(this.readAddrAbsoluteX), mode: 'absoluteX' },
// DEX // DEX
0xca: { name: 'DEX', op: this.dex, modeFn: this.implied, mode: 'implied' }, 0xca: { name: 'DEX', fn: () => this.dex(), mode: 'implied' },
// DEY // DEY
0x88: { name: 'DEY', op: this.dey, modeFn: this.implied, mode: 'implied' }, 0x88: { name: 'DEY', fn: () => this.dey(), mode: 'implied' },
// ASL // ASL
0x0A: { name: 'ASL', op: this.aslA, modeFn: this.implied, mode: 'accumulator' }, 0x0A: { name: 'ASL', fn: () => this.aslA(), mode: 'accumulator' },
0x06: { name: 'ASL', op: this.asl, modeFn: this.readAddrZeroPage, mode: 'zeroPage' }, 0x06: { name: 'ASL', fn: () => this.asl(this.readAddrZeroPage), mode: 'zeroPage' },
0x16: { name: 'ASL', op: this.asl, modeFn: this.readAddrZeroPageX, mode: 'zeroPageX' }, 0x16: { name: 'ASL', fn: () => this.asl(this.readAddrZeroPageX), mode: 'zeroPageX' },
0x0E: { name: 'ASL', op: this.asl, modeFn: this.readAddrAbsolute, mode: 'absolute' }, 0x0E: { name: 'ASL', fn: () => this.asl(this.readAddrAbsolute), mode: 'absolute' },
0x1E: { name: 'ASL', op: this.asl, modeFn: this.readAddrAbsoluteX, mode: 'absoluteX' }, 0x1E: { name: 'ASL', fn: () => this.asl(this.readAddrAbsoluteX), mode: 'absoluteX' },
// LSR // LSR
0x4A: { name: 'LSR', op: this.lsrA, modeFn: this.implied, mode: 'accumulator' }, 0x4A: { name: 'LSR', fn: () => this.lsrA(), mode: 'accumulator' },
0x46: { name: 'LSR', op: this.lsr, modeFn: this.readAddrZeroPage, mode: 'zeroPage' }, 0x46: { name: 'LSR', fn: () => this.lsr(this.readAddrZeroPage), mode: 'zeroPage' },
0x56: { name: 'LSR', op: this.lsr, modeFn: this.readAddrZeroPageX, mode: 'zeroPageX' }, 0x56: { name: 'LSR', fn: () => this.lsr(this.readAddrZeroPageX), mode: 'zeroPageX' },
0x4E: { name: 'LSR', op: this.lsr, modeFn: this.readAddrAbsolute, mode: 'absolute' }, 0x4E: { name: 'LSR', fn: () => this.lsr(this.readAddrAbsolute), mode: 'absolute' },
0x5E: { name: 'LSR', op: this.lsr, modeFn: this.readAddrAbsoluteX, mode: 'absoluteX' }, 0x5E: { name: 'LSR', fn: () => this.lsr(this.readAddrAbsoluteX), mode: 'absoluteX' },
// ROL // ROL
0x2A: { name: 'ROL', op: this.rolA, modeFn: this.implied, mode: 'accumulator' }, 0x2A: { name: 'ROL', fn: () => this.rolA(), mode: 'accumulator' },
0x26: { name: 'ROL', op: this.rol, modeFn: this.readAddrZeroPage, mode: 'zeroPage' }, 0x26: { name: 'ROL', fn: () => this.rol(this.readAddrZeroPage), mode: 'zeroPage' },
0x36: { name: 'ROL', op: this.rol, modeFn: this.readAddrZeroPageX, mode: 'zeroPageX' }, 0x36: { name: 'ROL', fn: () => this.rol(this.readAddrZeroPageX), mode: 'zeroPageX' },
0x2E: { name: 'ROL', op: this.rol, modeFn: this.readAddrAbsolute, mode: 'absolute' }, 0x2E: { name: 'ROL', fn: () => this.rol(this.readAddrAbsolute), mode: 'absolute' },
0x3E: { name: 'ROL', op: this.rol, modeFn: this.readAddrAbsoluteX, mode: 'absoluteX' }, 0x3E: { name: 'ROL', fn: () => this.rol(this.readAddrAbsoluteX), mode: 'absoluteX' },
// ROR // ROR
0x6A: { name: 'ROR', op: this.rorA, modeFn: this.implied, mode: 'accumulator' }, 0x6A: { name: 'ROR', fn: () => this.rorA(), mode: 'accumulator' },
0x66: { name: 'ROR', op: this.ror, modeFn: this.readAddrZeroPage, mode: 'zeroPage' }, 0x66: { name: 'ROR', fn: () => this.ror(this.readAddrZeroPage), mode: 'zeroPage' },
0x76: { name: 'ROR', op: this.ror, modeFn: this.readAddrZeroPageX, mode: 'zeroPageX' }, 0x76: { name: 'ROR', fn: () => this.ror(this.readAddrZeroPageX), mode: 'zeroPageX' },
0x6E: { name: 'ROR', op: this.ror, modeFn: this.readAddrAbsolute, mode: 'absolute' }, 0x6E: { name: 'ROR', fn: () => this.ror(this.readAddrAbsolute), mode: 'absolute' },
0x7E: { name: 'ROR', op: this.ror, modeFn: this.readAddrAbsoluteX, mode: 'absoluteX' }, 0x7E: { name: 'ROR', fn: () => this.ror(this.readAddrAbsoluteX), mode: 'absoluteX' },
// AND // AND
0x29: { name: 'AND', op: this.and, modeFn: this.readImmediate, mode: 'immediate' }, 0x29: { name: 'AND', fn: () => this.and(this.readImmediate), mode: 'immediate' },
0x25: { name: 'AND', op: this.and, modeFn: this.readZeroPage, mode: 'zeroPage' }, 0x25: { name: 'AND', fn: () => this.and(this.readZeroPage), mode: 'zeroPage' },
0x35: { name: 'AND', op: this.and, modeFn: this.readZeroPageX, mode: 'zeroPageX' }, 0x35: { name: 'AND', fn: () => this.and(this.readZeroPageX), mode: 'zeroPageX' },
0x2D: { name: 'AND', op: this.and, modeFn: this.readAbsolute, mode: 'absolute' }, 0x2D: { name: 'AND', fn: () => this.and(this.readAbsolute), mode: 'absolute' },
0x3D: { name: 'AND', op: this.and, modeFn: this.readAbsoluteX, mode: 'absoluteX' }, 0x3D: { name: 'AND', fn: () => this.and(this.readAbsoluteX), mode: 'absoluteX' },
0x39: { name: 'AND', op: this.and, modeFn: this.readAbsoluteY, mode: 'absoluteY' }, 0x39: { name: 'AND', fn: () => this.and(this.readAbsoluteY), mode: 'absoluteY' },
0x21: { name: 'AND', op: this.and, modeFn: this.readZeroPageXIndirect, mode: 'zeroPageXIndirect' }, 0x21: { name: 'AND', fn: () => this.and(this.readZeroPageXIndirect), mode: 'zeroPageXIndirect' },
0x31: { name: 'AND', op: this.and, modeFn: this.readZeroPageIndirectY, mode: 'zeroPageIndirectY' }, 0x31: { name: 'AND', fn: () => this.and(this.readZeroPageIndirectY), mode: 'zeroPageIndirectY' },
// ORA // ORA
0x09: { name: 'ORA', op: this.ora, modeFn: this.readImmediate, mode: 'immediate' }, 0x09: { name: 'ORA', fn: () => this.ora(this.readImmediate), mode: 'immediate' },
0x05: { name: 'ORA', op: this.ora, modeFn: this.readZeroPage, mode: 'zeroPage' }, 0x05: { name: 'ORA', fn: () => this.ora(this.readZeroPage), mode: 'zeroPage' },
0x15: { name: 'ORA', op: this.ora, modeFn: this.readZeroPageX, mode: 'zeroPageX' }, 0x15: { name: 'ORA', fn: () => this.ora(this.readZeroPageX), mode: 'zeroPageX' },
0x0D: { name: 'ORA', op: this.ora, modeFn: this.readAbsolute, mode: 'absolute' }, 0x0D: { name: 'ORA', fn: () => this.ora(this.readAbsolute), mode: 'absolute' },
0x1D: { name: 'ORA', op: this.ora, modeFn: this.readAbsoluteX, mode: 'absoluteX' }, 0x1D: { name: 'ORA', fn: () => this.ora(this.readAbsoluteX), mode: 'absoluteX' },
0x19: { name: 'ORA', op: this.ora, modeFn: this.readAbsoluteY, mode: 'absoluteY' }, 0x19: { name: 'ORA', fn: () => this.ora(this.readAbsoluteY), mode: 'absoluteY' },
0x01: { name: 'ORA', op: this.ora, modeFn: this.readZeroPageXIndirect, mode: 'zeroPageXIndirect' }, 0x01: { name: 'ORA', fn: () => this.ora(this.readZeroPageXIndirect), mode: 'zeroPageXIndirect' },
0x11: { name: 'ORA', op: this.ora, modeFn: this.readZeroPageIndirectY, mode: 'zeroPageIndirectY' }, 0x11: { name: 'ORA', fn: () => this.ora(this.readZeroPageIndirectY), mode: 'zeroPageIndirectY' },
// EOR // EOR
0x49: { name: 'EOR', op: this.eor, modeFn: this.readImmediate, mode: 'immediate' }, 0x49: { name: 'EOR', fn: () => this.eor(this.readImmediate), mode: 'immediate' },
0x45: { name: 'EOR', op: this.eor, modeFn: this.readZeroPage, mode: 'zeroPage' }, 0x45: { name: 'EOR', fn: () => this.eor(this.readZeroPage), mode: 'zeroPage' },
0x55: { name: 'EOR', op: this.eor, modeFn: this.readZeroPageX, mode: 'zeroPageX' }, 0x55: { name: 'EOR', fn: () => this.eor(this.readZeroPageX), mode: 'zeroPageX' },
0x4D: { name: 'EOR', op: this.eor, modeFn: this.readAbsolute, mode: 'absolute' }, 0x4D: { name: 'EOR', fn: () => this.eor(this.readAbsolute), mode: 'absolute' },
0x5D: { name: 'EOR', op: this.eor, modeFn: this.readAbsoluteX, mode: 'absoluteX' }, 0x5D: { name: 'EOR', fn: () => this.eor(this.readAbsoluteX), mode: 'absoluteX' },
0x59: { name: 'EOR', op: this.eor, modeFn: this.readAbsoluteY, mode: 'absoluteY' }, 0x59: { name: 'EOR', fn: () => this.eor(this.readAbsoluteY), mode: 'absoluteY' },
0x41: { name: 'EOR', op: this.eor, modeFn: this.readZeroPageXIndirect, mode: 'zeroPageXIndirect' }, 0x41: { name: 'EOR', fn: () => this.eor(this.readZeroPageXIndirect), mode: 'zeroPageXIndirect' },
0x51: { name: 'EOR', op: this.eor, modeFn: this.readZeroPageIndirectY, mode: 'zeroPageIndirectY' }, 0x51: { name: 'EOR', fn: () => this.eor(this.readZeroPageIndirectY), mode: 'zeroPageIndirectY' },
// CMP // CMP
0xc9: { name: 'CMP', op: this.cmp, modeFn: this.readImmediate, mode: 'immediate' }, 0xc9: { name: 'CMP', fn: () => this.cmp(this.readImmediate), mode: 'immediate' },
0xc5: { name: 'CMP', op: this.cmp, modeFn: this.readZeroPage, mode: 'zeroPage' }, 0xc5: { name: 'CMP', fn: () => this.cmp(this.readZeroPage), mode: 'zeroPage' },
0xd5: { name: 'CMP', op: this.cmp, modeFn: this.readZeroPageX, mode: 'zeroPageX' }, 0xd5: { name: 'CMP', fn: () => this.cmp(this.readZeroPageX), mode: 'zeroPageX' },
0xcD: { name: 'CMP', op: this.cmp, modeFn: this.readAbsolute, mode: 'absolute' }, 0xcD: { name: 'CMP', fn: () => this.cmp(this.readAbsolute), mode: 'absolute' },
0xdD: { name: 'CMP', op: this.cmp, modeFn: this.readAbsoluteX, mode: 'absoluteX' }, 0xdD: { name: 'CMP', fn: () => this.cmp(this.readAbsoluteX), mode: 'absoluteX' },
0xd9: { name: 'CMP', op: this.cmp, modeFn: this.readAbsoluteY, mode: 'absoluteY' }, 0xd9: { name: 'CMP', fn: () => this.cmp(this.readAbsoluteY), mode: 'absoluteY' },
0xc1: { name: 'CMP', op: this.cmp, modeFn: this.readZeroPageXIndirect, mode: 'zeroPageXIndirect' }, 0xc1: { name: 'CMP', fn: () => this.cmp(this.readZeroPageXIndirect), mode: 'zeroPageXIndirect' },
0xd1: { name: 'CMP', op: this.cmp, modeFn: this.readZeroPageIndirectY, mode: 'zeroPageIndirectY' }, 0xd1: { name: 'CMP', fn: () => this.cmp(this.readZeroPageIndirectY), mode: 'zeroPageIndirectY' },
// CPX // CPX
0xE0: { name: 'CPX', op: this.cpx, modeFn: this.readImmediate, mode: 'immediate' }, 0xE0: { name: 'CPX', fn: () => this.cpx(this.readImmediate), mode: 'immediate' },
0xE4: { name: 'CPX', op: this.cpx, modeFn: this.readZeroPage, mode: 'zeroPage' }, 0xE4: { name: 'CPX', fn: () => this.cpx(this.readZeroPage), mode: 'zeroPage' },
0xEC: { name: 'CPX', op: this.cpx, modeFn: this.readAbsolute, mode: 'absolute' }, 0xEC: { name: 'CPX', fn: () => this.cpx(this.readAbsolute), mode: 'absolute' },
// CPY // CPY
0xC0: { name: 'CPY', op: this.cpy, modeFn: this.readImmediate, mode: 'immediate' }, 0xC0: { name: 'CPY', fn: () => this.cpy(this.readImmediate), mode: 'immediate' },
0xC4: { name: 'CPY', op: this.cpy, modeFn: this.readZeroPage, mode: 'zeroPage' }, 0xC4: { name: 'CPY', fn: () => this.cpy(this.readZeroPage), mode: 'zeroPage' },
0xCC: { name: 'CPY', op: this.cpy, modeFn: this.readAbsolute, mode: 'absolute' }, 0xCC: { name: 'CPY', fn: () => this.cpy(this.readAbsolute), mode: 'absolute' },
// BIT // BIT
0x24: { name: 'BIT', op: this.bit, modeFn: this.readZeroPage, mode: 'zeroPage' }, 0x24: { name: 'BIT', fn: () => this.bit(this.readZeroPage), mode: 'zeroPage' },
0x2C: { name: 'BIT', op: this.bit, modeFn: this.readAbsolute, mode: 'absolute' }, 0x2C: { name: 'BIT', fn: () => this.bit(this.readAbsolute), mode: 'absolute' },
// BCC // BCC
0x90: { name: 'BCC', op: this.brc, modeFn: flags.C, mode: 'relative' }, 0x90: { name: 'BCC', fn: () => this.brc(flags.C), mode: 'relative' },
// BCS // BCS
0xB0: { name: 'BCS', op: this.brs, modeFn: flags.C, mode: 'relative' }, 0xB0: { name: 'BCS', fn: () => this.brs(flags.C), mode: 'relative' },
// BEQ // BEQ
0xF0: { name: 'BEQ', op: this.brs, modeFn: flags.Z, mode: 'relative' }, 0xF0: { name: 'BEQ', fn: () => this.brs(flags.Z), mode: 'relative' },
// BMI // BMI
0x30: { name: 'BMI', op: this.brs, modeFn: flags.N, mode: 'relative' }, 0x30: { name: 'BMI', fn: () => this.brs(flags.N), mode: 'relative' },
// BNE // BNE
0xD0: { name: 'BNE', op: this.brc, modeFn: flags.Z, mode: 'relative' }, 0xD0: { name: 'BNE', fn: () => this.brc(flags.Z), mode: 'relative' },
// BPL // BPL
0x10: { name: 'BPL', op: this.brc, modeFn: flags.N, mode: 'relative' }, 0x10: { name: 'BPL', fn: () => this.brc(flags.N), mode: 'relative' },
// BVC // BVC
0x50: { name: 'BVC', op: this.brc, modeFn: flags.V, mode: 'relative' }, 0x50: { name: 'BVC', fn: () => this.brc(flags.V), mode: 'relative' },
// BVS // BVS
0x70: { name: 'BVS', op: this.brs, modeFn: flags.V, mode: 'relative' }, 0x70: { name: 'BVS', fn: () => this.brs(flags.V), mode: 'relative' },
// TAX // TAX
0xAA: { name: 'TAX', op: this.tax, modeFn: this.implied, mode: 'implied' }, 0xAA: { name: 'TAX', fn: () => this.tax(), mode: 'implied' },
// TXA // TXA
0x8A: { name: 'TXA', op: this.txa, modeFn: this.implied, mode: 'implied' }, 0x8A: { name: 'TXA', fn: () => this.txa(), mode: 'implied' },
// TAY // TAY
0xA8: { name: 'TAY', op: this.tay, modeFn: this.implied, mode: 'implied' }, 0xA8: { name: 'TAY', fn: () => this.tay(), mode: 'implied' },
// TYA // TYA
0x98: { name: 'TYA', op: this.tya, modeFn: this.implied, mode: 'implied' }, 0x98: { name: 'TYA', fn: () => this.tya(), mode: 'implied' },
// TSX // TSX
0xBA: { name: 'TSX', op: this.tsx, modeFn: this.implied, mode: 'implied' }, 0xBA: { name: 'TSX', fn: () => this.tsx(), mode: 'implied' },
// TXS // TXS
0x9A: { name: 'TXS', op: this.txs, modeFn: this.implied, mode: 'implied' }, 0x9A: { name: 'TXS', fn: () => this.txs(), mode: 'implied' },
// PHA // PHA
0x48: { name: 'PHA', op: this.pha, modeFn: this.implied, mode: 'implied' }, 0x48: { name: 'PHA', fn: () => this.pha(), mode: 'implied' },
// PLA // PLA
0x68: { name: 'PLA', op: this.pla, modeFn: this.implied, mode: 'implied' }, 0x68: { name: 'PLA', fn: () => this.pla(), mode: 'implied' },
// PHP // PHP
0x08: { name: 'PHP', op: this.php, modeFn: this.implied, mode: 'implied' }, 0x08: { name: 'PHP', fn: () => this.php(), mode: 'implied' },
// PLP // PLP
0x28: { name: 'PLP', op: this.plp, modeFn: this.implied, mode: 'implied' }, 0x28: { name: 'PLP', fn: () => this.plp(), mode: 'implied' },
// JMP // JMP
0x4C: { 0x4C: {
name: 'JMP', op: this.jmp, modeFn: this.readAddrAbsolute, mode: 'absolute' name: 'JMP', fn: () => this.jmp(this.readAddrAbsolute), mode: 'absolute'
}, },
0x6C: { 0x6C: {
name: 'JMP', op: this.jmp, modeFn: this.readAddrAbsoluteIndirectBug, mode: 'absoluteIndirect' name: 'JMP', fn: () => this.jmp(this.readAddrAbsoluteIndirectBug), mode: 'absoluteIndirect'
}, },
// JSR // JSR
0x20: { name: 'JSR', op: this.jsr, modeFn: this.readAddrAbsolute, mode: 'absolute' }, 0x20: { name: 'JSR', fn: () => this.jsr(), mode: 'absolute' },
// RTS // RTS
0x60: { name: 'RTS', op: this.rts, modeFn: this.implied, mode: 'implied' }, 0x60: { name: 'RTS', fn: () => this.rts(), mode: 'implied' },
// RTI // RTI
0x40: { name: 'RTI', op: this.rti, modeFn: this.implied, mode: 'implied' }, 0x40: { name: 'RTI', fn: () => this.rti(), mode: 'implied' },
// SEC // SEC
0x38: { name: 'SEC', op: this.set, modeFn: flags.C, mode: 'implied' }, 0x38: { name: 'SEC', fn: () => this.set(flags.C), mode: 'implied' },
// SED // SED
0xF8: { name: 'SED', op: this.set, modeFn: flags.D, mode: 'implied' }, 0xF8: { name: 'SED', fn: () => this.set(flags.D), mode: 'implied' },
// SEI // SEI
0x78: { name: 'SEI', op: this.set, modeFn: flags.I, mode: 'implied' }, 0x78: { name: 'SEI', fn: () => this.set(flags.I), mode: 'implied' },
// CLC // CLC
0x18: { name: 'CLC', op: this.clr, modeFn: flags.C, mode: 'implied' }, 0x18: { name: 'CLC', fn: () => this.clr(flags.C), mode: 'implied' },
// CLD // CLD
0xD8: { name: 'CLD', op: this.clr, modeFn: flags.D, mode: 'implied' }, 0xD8: { name: 'CLD', fn: () => this.clr(flags.D), mode: 'implied' },
// CLI // CLI
0x58: { name: 'CLI', op: this.clr, modeFn: flags.I, mode: 'implied' }, 0x58: { name: 'CLI', fn: () => this.clr(flags.I), mode: 'implied' },
// CLV // CLV
0xB8: { name: 'CLV', op: this.clr, modeFn: flags.V, mode: 'implied' }, 0xB8: { name: 'CLV', fn: () => this.clr(flags.V), mode: 'implied' },
// NOP // NOP
0xea: { name: 'NOP', op: this.nop, modeFn: this.implied, mode: 'implied' }, 0xea: { name: 'NOP', fn: () => this.nop(this.implied), mode: 'implied' },
// BRK // BRK
0x00: { name: 'BRK', op: this.brk, modeFn: this.readImmediate, mode: 'immediate' } 0x00: { name: 'BRK', fn: () => this.brk(this.readImmediate), mode: 'immediate' }
}; };
/* 65C02 Instructions */ /* 65C02 Instructions */
OPS_65C02: Instructions = { OPS_65C02: Instructions = {
// INC / DEC A // INC / DEC A
0x1A: { name: 'INC', op: this.incA, modeFn: this.implied, mode: 'accumulator' }, 0x1A: { name: 'INC', fn: () => this.incA(), mode: 'accumulator' },
0x3A: { name: 'DEC', op: this.decA, modeFn: this.implied, mode: 'accumulator' }, 0x3A: { name: 'DEC', fn: () => this.decA(), mode: 'accumulator' },
// Indirect Zero Page for the masses // Indirect Zero Page for the masses
0x12: { name: 'ORA', op: this.ora, modeFn: this.readZeroPageIndirect, mode: 'zeroPageIndirect' }, 0x12: { name: 'ORA', fn: () => this.ora(this.readZeroPageIndirect), mode: 'zeroPageIndirect' },
0x32: { name: 'AND', op: this.and, modeFn: this.readZeroPageIndirect, mode: 'zeroPageIndirect' }, 0x32: { name: 'AND', fn: () => this.and(this.readZeroPageIndirect), mode: 'zeroPageIndirect' },
0x52: { name: 'EOR', op: this.eor, modeFn: this.readZeroPageIndirect, mode: 'zeroPageIndirect' }, 0x52: { name: 'EOR', fn: () => this.eor(this.readZeroPageIndirect), mode: 'zeroPageIndirect' },
0x72: { name: 'ADC', op: this.adc, modeFn: this.readZeroPageIndirect, mode: 'zeroPageIndirect' }, 0x72: { name: 'ADC', fn: () => this.adc(this.readZeroPageIndirect), mode: 'zeroPageIndirect' },
0x92: { name: 'STA', op: this.sta, modeFn: this.writeZeroPageIndirect, mode: 'zeroPageIndirect' }, 0x92: { name: 'STA', fn: () => this.sta(this.writeZeroPageIndirect), mode: 'zeroPageIndirect' },
0xB2: { name: 'LDA', op: this.lda, modeFn: this.readZeroPageIndirect, mode: 'zeroPageIndirect' }, 0xB2: { name: 'LDA', fn: () => this.lda(this.readZeroPageIndirect), mode: 'zeroPageIndirect' },
0xD2: { name: 'CMP', op: this.cmp, modeFn: this.readZeroPageIndirect, mode: 'zeroPageIndirect' }, 0xD2: { name: 'CMP', fn: () => this.cmp(this.readZeroPageIndirect), mode: 'zeroPageIndirect' },
0xF2: { name: 'SBC', op: this.sbc, modeFn: this.readZeroPageIndirect, mode: 'zeroPageIndirect' }, 0xF2: { name: 'SBC', fn: () => this.sbc(this.readZeroPageIndirect), mode: 'zeroPageIndirect' },
// Better BIT // Better BIT
0x34: { name: 'BIT', op: this.bit, modeFn: this.readZeroPageX, mode: 'zeroPageX' }, 0x34: { name: 'BIT', fn: () => this.bit(this.readZeroPageX), mode: 'zeroPageX' },
0x3C: { name: 'BIT', op: this.bit, modeFn: this.readAbsoluteX, mode: 'absoluteX' }, 0x3C: { name: 'BIT', fn: () => this.bit(this.readAbsoluteX), mode: 'absoluteX' },
0x89: { name: 'BIT', op: this.bitI, modeFn: this.readImmediate, mode: 'immediate' }, 0x89: { name: 'BIT', fn: () => this.bitI(this.readImmediate), mode: 'immediate' },
// JMP absolute indirect indexed // JMP absolute indirect indexed
0x6C: { 0x6C: {
name: 'JMP', op: this.jmp, modeFn: this.readAddrAbsoluteIndirect, mode: 'absoluteIndirect' name: 'JMP', fn: () => this.jmp(this.readAddrAbsoluteIndirect), mode: 'absoluteIndirect'
}, },
0x7C: { 0x7C: {
name: 'JMP', op: this.jmp, modeFn: this.readAddrAbsoluteXIndirect, mode: 'absoluteXIndirect' name: 'JMP', fn: () => this.jmp(this.readAddrAbsoluteXIndirect), mode: 'absoluteXIndirect'
}, },
// BBR/BBS // BBR/BBS
0x0F: { name: 'BBR0', op: this.bbr, modeFn: 0, mode: 'zeroPage_relative' }, 0x0F: { name: 'BBR0', fn: () => this.bbr(0), mode: 'zeroPage_relative' },
0x1F: { name: 'BBR1', op: this.bbr, modeFn: 1, mode: 'zeroPage_relative' }, 0x1F: { name: 'BBR1', fn: () => this.bbr(1), mode: 'zeroPage_relative' },
0x2F: { name: 'BBR2', op: this.bbr, modeFn: 2, mode: 'zeroPage_relative' }, 0x2F: { name: 'BBR2', fn: () => this.bbr(2), mode: 'zeroPage_relative' },
0x3F: { name: 'BBR3', op: this.bbr, modeFn: 3, mode: 'zeroPage_relative' }, 0x3F: { name: 'BBR3', fn: () => this.bbr(3), mode: 'zeroPage_relative' },
0x4F: { name: 'BBR4', op: this.bbr, modeFn: 4, mode: 'zeroPage_relative' }, 0x4F: { name: 'BBR4', fn: () => this.bbr(4), mode: 'zeroPage_relative' },
0x5F: { name: 'BBR5', op: this.bbr, modeFn: 5, mode: 'zeroPage_relative' }, 0x5F: { name: 'BBR5', fn: () => this.bbr(5), mode: 'zeroPage_relative' },
0x6F: { name: 'BBR6', op: this.bbr, modeFn: 6, mode: 'zeroPage_relative' }, 0x6F: { name: 'BBR6', fn: () => this.bbr(6), mode: 'zeroPage_relative' },
0x7F: { name: 'BBR7', op: this.bbr, modeFn: 7, mode: 'zeroPage_relative' }, 0x7F: { name: 'BBR7', fn: () => this.bbr(7), mode: 'zeroPage_relative' },
0x8F: { name: 'BBS0', op: this.bbs, modeFn: 0, mode: 'zeroPage_relative' }, 0x8F: { name: 'BBS0', fn: () => this.bbs(0), mode: 'zeroPage_relative' },
0x9F: { name: 'BBS1', op: this.bbs, modeFn: 1, mode: 'zeroPage_relative' }, 0x9F: { name: 'BBS1', fn: () => this.bbs(1), mode: 'zeroPage_relative' },
0xAF: { name: 'BBS2', op: this.bbs, modeFn: 2, mode: 'zeroPage_relative' }, 0xAF: { name: 'BBS2', fn: () => this.bbs(2), mode: 'zeroPage_relative' },
0xBF: { name: 'BBS3', op: this.bbs, modeFn: 3, mode: 'zeroPage_relative' }, 0xBF: { name: 'BBS3', fn: () => this.bbs(3), mode: 'zeroPage_relative' },
0xCF: { name: 'BBS4', op: this.bbs, modeFn: 4, mode: 'zeroPage_relative' }, 0xCF: { name: 'BBS4', fn: () => this.bbs(4), mode: 'zeroPage_relative' },
0xDF: { name: 'BBS5', op: this.bbs, modeFn: 5, mode: 'zeroPage_relative' }, 0xDF: { name: 'BBS5', fn: () => this.bbs(5), mode: 'zeroPage_relative' },
0xEF: { name: 'BBS6', op: this.bbs, modeFn: 6, mode: 'zeroPage_relative' }, 0xEF: { name: 'BBS6', fn: () => this.bbs(6), mode: 'zeroPage_relative' },
0xFF: { name: 'BBS7', op: this.bbs, modeFn: 7, mode: 'zeroPage_relative' }, 0xFF: { name: 'BBS7', fn: () => this.bbs(7), mode: 'zeroPage_relative' },
// BRA // BRA
0x80: { name: 'BRA', op: this.brc, modeFn: 0, mode: 'relative' }, 0x80: { name: 'BRA', fn: () => this.brc(0), mode: 'relative' },
// NOP // NOP
0x02: { name: 'NOP', op: this.nop, modeFn: this.readImmediate, mode: 'immediate' }, 0x02: { name: 'NOP', fn: () => this.nop(this.readImmediate), mode: 'immediate' },
0x22: { name: 'NOP', op: this.nop, modeFn: this.readImmediate, mode: 'immediate' }, 0x22: { name: 'NOP', fn: () => this.nop(this.readImmediate), mode: 'immediate' },
0x42: { name: 'NOP', op: this.nop, modeFn: this.readImmediate, mode: 'immediate' }, 0x42: { name: 'NOP', fn: () => this.nop(this.readImmediate), mode: 'immediate' },
0x44: { name: 'NOP', op: this.nop, modeFn: this.readZeroPage, mode: 'immediate' }, 0x44: { name: 'NOP', fn: () => this.nop(this.readZeroPage), mode: 'immediate' },
0x54: { name: 'NOP', op: this.nop, modeFn: this.readZeroPageX, mode: 'immediate' }, 0x54: { name: 'NOP', fn: () => this.nop(this.readZeroPageX), mode: 'immediate' },
0x62: { name: 'NOP', op: this.nop, modeFn: this.readImmediate, mode: 'immediate' }, 0x62: { name: 'NOP', fn: () => this.nop(this.readImmediate), mode: 'immediate' },
0x82: { name: 'NOP', op: this.nop, modeFn: this.readImmediate, mode: 'immediate' }, 0x82: { name: 'NOP', fn: () => this.nop(this.readImmediate), mode: 'immediate' },
0xC2: { name: 'NOP', op: this.nop, modeFn: this.readImmediate, mode: 'immediate' }, 0xC2: { name: 'NOP', fn: () => this.nop(this.readImmediate), mode: 'immediate' },
0xD4: { name: 'NOP', op: this.nop, modeFn: this.readZeroPageX, mode: 'immediate' }, 0xD4: { name: 'NOP', fn: () => this.nop(this.readZeroPageX), mode: 'immediate' },
0xE2: { name: 'NOP', op: this.nop, modeFn: this.readImmediate, mode: 'immediate' }, 0xE2: { name: 'NOP', fn: () => this.nop(this.readImmediate), mode: 'immediate' },
0xF4: { name: 'NOP', op: this.nop, modeFn: this.readZeroPageX, mode: 'immediate' }, 0xF4: { name: 'NOP', fn: () => this.nop(this.readZeroPageX), mode: 'immediate' },
0x5C: { name: 'NOP', op: this.nop, modeFn: this.readNop, mode: 'absolute' }, 0x5C: { name: 'NOP', fn: () => this.nop(this.readNop), mode: 'absolute' },
0xDC: { name: 'NOP', op: this.nop, modeFn: this.readNop, mode: 'absolute' }, 0xDC: { name: 'NOP', fn: () => this.nop(this.readNop), mode: 'absolute' },
0xFC: { name: 'NOP', op: this.nop, modeFn: this.readNop, mode: 'absolute' }, 0xFC: { name: 'NOP', fn: () => this.nop(this.readNop), mode: 'absolute' },
// PHX // PHX
0xDA: { name: 'PHX', op: this.phx, modeFn: this.implied, mode: 'implied' }, 0xDA: { name: 'PHX', fn: () => this.phx(), mode: 'implied' },
// PHY // PHY
0x5A: { name: 'PHY', op: this.phy, modeFn: this.implied, mode: 'implied' }, 0x5A: { name: 'PHY', fn: () => this.phy(), mode: 'implied' },
// PLX // PLX
0xFA: { name: 'PLX', op: this.plx, modeFn: this.implied, mode: 'implied' }, 0xFA: { name: 'PLX', fn: () => this.plx(), mode: 'implied' },
// PLY // PLY
0x7A: { name: 'PLY', op: this.ply, modeFn: this.implied, mode: 'implied' }, 0x7A: { name: 'PLY', fn: () => this.ply(), mode: 'implied' },
// RMB/SMB // RMB/SMB
0x07: { name: 'RMB0', op: this.rmb, modeFn: 0, mode: 'zeroPage' }, 0x07: { name: 'RMB0', fn: () => this.rmb(0), mode: 'zeroPage' },
0x17: { name: 'RMB1', op: this.rmb, modeFn: 1, mode: 'zeroPage' }, 0x17: { name: 'RMB1', fn: () => this.rmb(1), mode: 'zeroPage' },
0x27: { name: 'RMB2', op: this.rmb, modeFn: 2, mode: 'zeroPage' }, 0x27: { name: 'RMB2', fn: () => this.rmb(2), mode: 'zeroPage' },
0x37: { name: 'RMB3', op: this.rmb, modeFn: 3, mode: 'zeroPage' }, 0x37: { name: 'RMB3', fn: () => this.rmb(3), mode: 'zeroPage' },
0x47: { name: 'RMB4', op: this.rmb, modeFn: 4, mode: 'zeroPage' }, 0x47: { name: 'RMB4', fn: () => this.rmb(4), mode: 'zeroPage' },
0x57: { name: 'RMB5', op: this.rmb, modeFn: 5, mode: 'zeroPage' }, 0x57: { name: 'RMB5', fn: () => this.rmb(5), mode: 'zeroPage' },
0x67: { name: 'RMB6', op: this.rmb, modeFn: 6, mode: 'zeroPage' }, 0x67: { name: 'RMB6', fn: () => this.rmb(6), mode: 'zeroPage' },
0x77: { name: 'RMB7', op: this.rmb, modeFn: 7, mode: 'zeroPage' }, 0x77: { name: 'RMB7', fn: () => this.rmb(7), mode: 'zeroPage' },
0x87: { name: 'SMB0', op: this.smb, modeFn: 0, mode: 'zeroPage' }, 0x87: { name: 'SMB0', fn: () => this.smb(0), mode: 'zeroPage' },
0x97: { name: 'SMB1', op: this.smb, modeFn: 1, mode: 'zeroPage' }, 0x97: { name: 'SMB1', fn: () => this.smb(1), mode: 'zeroPage' },
0xA7: { name: 'SMB2', op: this.smb, modeFn: 2, mode: 'zeroPage' }, 0xA7: { name: 'SMB2', fn: () => this.smb(2), mode: 'zeroPage' },
0xB7: { name: 'SMB3', op: this.smb, modeFn: 3, mode: 'zeroPage' }, 0xB7: { name: 'SMB3', fn: () => this.smb(3), mode: 'zeroPage' },
0xC7: { name: 'SMB4', op: this.smb, modeFn: 4, mode: 'zeroPage' }, 0xC7: { name: 'SMB4', fn: () => this.smb(4), mode: 'zeroPage' },
0xD7: { name: 'SMB5', op: this.smb, modeFn: 5, mode: 'zeroPage' }, 0xD7: { name: 'SMB5', fn: () => this.smb(5), mode: 'zeroPage' },
0xE7: { name: 'SMB6', op: this.smb, modeFn: 6, mode: 'zeroPage' }, 0xE7: { name: 'SMB6', fn: () => this.smb(6), mode: 'zeroPage' },
0xF7: { name: 'SMB7', op: this.smb, modeFn: 7, mode: 'zeroPage' }, 0xF7: { name: 'SMB7', fn: () => this.smb(7), mode: 'zeroPage' },
// STZ // STZ
0x64: { name: 'STZ', op: this.stz, modeFn: this.writeZeroPage, mode: 'zeroPage' }, 0x64: { name: 'STZ', fn: () => this.stz(this.writeZeroPage), mode: 'zeroPage' },
0x74: { name: 'STZ', op: this.stz, modeFn: this.writeZeroPageX, mode: 'zeroPageX' }, 0x74: { name: 'STZ', fn: () => this.stz(this.writeZeroPageX), mode: 'zeroPageX' },
0x9C: { name: 'STZ', op: this.stz, modeFn: this.writeAbsolute, mode: 'absolute' }, 0x9C: { name: 'STZ', fn: () => this.stz(this.writeAbsolute), mode: 'absolute' },
0x9E: { name: 'STZ', op: this.stz, modeFn: this.writeAbsoluteX, mode: 'absoluteX' }, 0x9E: { name: 'STZ', fn: () => this.stz(this.writeAbsoluteX), mode: 'absoluteX' },
// TRB // TRB
0x14: { name: 'TRB', op: this.trb, modeFn: this.readAddrZeroPage, mode: 'zeroPage' }, 0x14: { name: 'TRB', fn: () => this.trb(this.readAddrZeroPage), mode: 'zeroPage' },
0x1C: { name: 'TRB', op: this.trb, modeFn: this.readAddrAbsolute, mode: 'absolute' }, 0x1C: { name: 'TRB', fn: () => this.trb(this.readAddrAbsolute), mode: 'absolute' },
// TSB // TSB
0x04: { name: 'TSB', op: this.tsb, modeFn: this.readAddrZeroPage, mode: 'zeroPage' }, 0x04: { name: 'TSB', fn: () => this.tsb(this.readAddrZeroPage), mode: 'zeroPage' },
0x0C: { name: 'TSB', op: this.tsb, modeFn: this.readAddrAbsolute, mode: 'absolute' } 0x0C: { name: 'TSB', fn: () => this.tsb(this.readAddrAbsolute), mode: 'absolute' }
}; };
OPS_NMOS_6502: Instructions = { OPS_NMOS_6502: Instructions = {
// ASO // ASO
0x0F: { name: 'ASO', op: this.aso, modeFn: this.readAddrAbsolute, mode: 'absolute' }, 0x0F: { name: 'ASO', fn: () => this.aso(this.readAddrAbsolute), mode: 'absolute' },
0x1F: { name: 'ASO', op: this.aso, modeFn: this.readAddrAbsoluteX, mode: 'absoluteX' }, 0x1F: { name: 'ASO', fn: () => this.aso(this.readAddrAbsoluteX), mode: 'absoluteX' },
0x1B: { name: 'ASO', op: this.aso, modeFn: this.readAddrAbsoluteY, mode: 'absoluteY' }, 0x1B: { name: 'ASO', fn: () => this.aso(this.readAddrAbsoluteY), mode: 'absoluteY' },
0x07: { name: 'ASO', op: this.aso, modeFn: this.readAddrZeroPage, mode: 'zeroPage' }, 0x07: { name: 'ASO', fn: () => this.aso(this.readAddrZeroPage), mode: 'zeroPage' },
0x17: { name: 'ASO', op: this.aso, modeFn: this.readAddrZeroPageX, mode: 'zeroPageX' }, 0x17: { name: 'ASO', fn: () => this.aso(this.readAddrZeroPageX), mode: 'zeroPageX' },
0x03: { name: 'ASO', op: this.aso, modeFn: this.readAddrZeroPageXIndirect, mode: 'zeroPageXIndirect' }, 0x03: { name: 'ASO', fn: () => this.aso(this.readAddrZeroPageXIndirect), mode: 'zeroPageXIndirect' },
0x13: { name: 'ASO', op: this.aso, modeFn: this.readAddrZeroPageIndirectY, mode: 'zeroPageIndirectY' }, 0x13: { name: 'ASO', fn: () => this.aso(this.readAddrZeroPageIndirectY), mode: 'zeroPageIndirectY' },
// RLA // RLA
0x2F: { name: 'RLA', op: this.rla, modeFn: this.readAddrAbsolute, mode: 'absolute' }, 0x2F: { name: 'RLA', fn: () => this.rla(this.readAddrAbsolute), mode: 'absolute' },
0x3F: { name: 'RLA', op: this.rla, modeFn: this.readAddrAbsoluteX, mode: 'absoluteX' }, 0x3F: { name: 'RLA', fn: () => this.rla(this.readAddrAbsoluteX), mode: 'absoluteX' },
0x3B: { name: 'RLA', op: this.rla, modeFn: this.readAddrAbsoluteY, mode: 'absoluteY' }, 0x3B: { name: 'RLA', fn: () => this.rla(this.readAddrAbsoluteY), mode: 'absoluteY' },
0x27: { name: 'RLA', op: this.rla, modeFn: this.readAddrZeroPage, mode: 'zeroPage' }, 0x27: { name: 'RLA', fn: () => this.rla(this.readAddrZeroPage), mode: 'zeroPage' },
0x37: { name: 'RLA', op: this.rla, modeFn: this.readAddrZeroPageX, mode: 'zeroPageX' }, 0x37: { name: 'RLA', fn: () => this.rla(this.readAddrZeroPageX), mode: 'zeroPageX' },
0x23: { name: 'RLA', op: this.rla, modeFn: this.readAddrZeroPageXIndirect, mode: 'zeroPageXIndirect' }, 0x23: { name: 'RLA', fn: () => this.rla(this.readAddrZeroPageXIndirect), mode: 'zeroPageXIndirect' },
0x33: { name: 'RLA', op: this.rla, modeFn: this.readAddrZeroPageIndirectY, mode: 'zeroPageIndirectY' }, 0x33: { name: 'RLA', fn: () => this.rla(this.readAddrZeroPageIndirectY), mode: 'zeroPageIndirectY' },
// LSE // LSE
0x4F: { name: 'LSE', op: this.lse, modeFn: this.readAddrAbsolute, mode: 'absolute' }, 0x4F: { name: 'LSE', fn: () => this.lse(this.readAddrAbsolute), mode: 'absolute' },
0x5F: { name: 'LSE', op: this.lse, modeFn: this.readAddrAbsoluteX, mode: 'absoluteX' }, 0x5F: { name: 'LSE', fn: () => this.lse(this.readAddrAbsoluteX), mode: 'absoluteX' },
0x5B: { name: 'LSE', op: this.lse, modeFn: this.readAddrAbsoluteY, mode: 'absoluteY' }, 0x5B: { name: 'LSE', fn: () => this.lse(this.readAddrAbsoluteY), mode: 'absoluteY' },
0x47: { name: 'LSE', op: this.lse, modeFn: this.readAddrZeroPage, mode: 'zeroPage' }, 0x47: { name: 'LSE', fn: () => this.lse(this.readAddrZeroPage), mode: 'zeroPage' },
0x57: { name: 'LSE', op: this.lse, modeFn: this.readAddrZeroPageX, mode: 'zeroPageX' }, 0x57: { name: 'LSE', fn: () => this.lse(this.readAddrZeroPageX), mode: 'zeroPageX' },
0x43: { name: 'LSE', op: this.lse, modeFn: this.readAddrZeroPageXIndirect, mode: 'zeroPageXIndirect' }, 0x43: { name: 'LSE', fn: () => this.lse(this.readAddrZeroPageXIndirect), mode: 'zeroPageXIndirect' },
0x53: { name: 'LSE', op: this.lse, modeFn: this.readAddrZeroPageIndirectY, mode: 'zeroPageIndirectY' }, 0x53: { name: 'LSE', fn: () => this.lse(this.readAddrZeroPageIndirectY), mode: 'zeroPageIndirectY' },
// RRA // RRA
0x6F: { name: 'RRA', op: this.rra, modeFn: this.readAddrAbsolute, mode: 'absolute' }, 0x6F: { name: 'RRA', fn: () => this.rra(this.readAddrAbsolute), mode: 'absolute' },
0x7F: { name: 'RRA', op: this.rra, modeFn: this.readAddrAbsoluteX, mode: 'absoluteX' }, 0x7F: { name: 'RRA', fn: () => this.rra(this.readAddrAbsoluteX), mode: 'absoluteX' },
0x7B: { name: 'RRA', op: this.rra, modeFn: this.readAddrAbsoluteY, mode: 'absoluteY' }, 0x7B: { name: 'RRA', fn: () => this.rra(this.readAddrAbsoluteY), mode: 'absoluteY' },
0x67: { name: 'RRA', op: this.rra, modeFn: this.readAddrZeroPage, mode: 'zeroPage' }, 0x67: { name: 'RRA', fn: () => this.rra(this.readAddrZeroPage), mode: 'zeroPage' },
0x77: { name: 'RRA', op: this.rra, modeFn: this.readAddrZeroPageX, mode: 'zeroPageX' }, 0x77: { name: 'RRA', fn: () => this.rra(this.readAddrZeroPageX), mode: 'zeroPageX' },
0x63: { name: 'RRA', op: this.rra, modeFn: this.readAddrZeroPageXIndirect, mode: 'zeroPageXIndirect' }, 0x63: { name: 'RRA', fn: () => this.rra(this.readAddrZeroPageXIndirect), mode: 'zeroPageXIndirect' },
0x73: { name: 'RRA', op: this.rra, modeFn: this.readAddrZeroPageIndirectY, mode: 'zeroPageIndirectY' }, 0x73: { name: 'RRA', fn: () => this.rra(this.readAddrZeroPageIndirectY), mode: 'zeroPageIndirectY' },
// AXS // AXS
0x8F: { name: 'AXS', op: this.axs, modeFn: this.writeAbsolute, mode: 'absolute'}, 0x8F: { name: 'AXS', fn: () => this.axs(this.writeAbsolute), mode: 'absolute'},
0x87: { name: 'AXS', op: this.axs, modeFn: this.writeZeroPage, mode: 'zeroPage'}, 0x87: { name: 'AXS', fn: () => this.axs(this.writeZeroPage), mode: 'zeroPage'},
0x97: { name: 'AXS', op: this.axs, modeFn: this.writeZeroPageY, mode: 'zeroPageY'}, 0x97: { name: 'AXS', fn: () => this.axs(this.writeZeroPageY), mode: 'zeroPageY'},
0x83: { name: 'AXS', op: this.axs, modeFn: this.writeZeroPageXIndirect, mode: 'zeroPageXIndirect'}, 0x83: { name: 'AXS', fn: () => this.axs(this.writeZeroPageXIndirect), mode: 'zeroPageXIndirect'},
// LAX // LAX
0xAF: { name: 'LAX', op: this.lax, modeFn: this.readAbsolute, mode: 'absolute'}, 0xAF: { name: 'LAX', fn: () => this.lax(this.readAbsolute), mode: 'absolute'},
0xBF: { name: 'LAX', op: this.lax, modeFn: this.readAbsoluteY, mode: 'absoluteY'}, 0xBF: { name: 'LAX', fn: () => this.lax(this.readAbsoluteY), mode: 'absoluteY'},
0xA7: { name: 'LAX', op: this.lax, modeFn: this.readZeroPage, mode: 'zeroPage'}, 0xA7: { name: 'LAX', fn: () => this.lax(this.readZeroPage), mode: 'zeroPage'},
0xB7: { name: 'LAX', op: this.lax, modeFn: this.readZeroPageY, mode: 'zeroPageY'}, 0xB7: { name: 'LAX', fn: () => this.lax(this.readZeroPageY), mode: 'zeroPageY'},
0xA3: { name: 'LAX', op: this.lax, modeFn: this.readZeroPageXIndirect, mode: 'zeroPageXIndirect'}, 0xA3: { name: 'LAX', fn: () => this.lax(this.readZeroPageXIndirect), mode: 'zeroPageXIndirect'},
0xB3: { name: 'LAX', op: this.lax, modeFn: this.readZeroPageIndirectY, mode: 'zeroPageIndirectY'}, 0xB3: { name: 'LAX', fn: () => this.lax(this.readZeroPageIndirectY), mode: 'zeroPageIndirectY'},
// DCM // DCM
0xCF: { name: 'DCM', op: this.dcm, modeFn: this.readAddrAbsolute, mode: 'absolute' }, 0xCF: { name: 'DCM', fn: () => this.dcm(this.readAddrAbsolute), mode: 'absolute' },
0xDF: { name: 'DCM', op: this.dcm, modeFn: this.readAddrAbsoluteX, mode: 'absoluteX' }, 0xDF: { name: 'DCM', fn: () => this.dcm(this.readAddrAbsoluteX), mode: 'absoluteX' },
0xDB: { name: 'DCM', op: this.dcm, modeFn: this.readAddrAbsoluteY, mode: 'absoluteY' }, 0xDB: { name: 'DCM', fn: () => this.dcm(this.readAddrAbsoluteY), mode: 'absoluteY' },
0xC7: { name: 'DCM', op: this.dcm, modeFn: this.readAddrZeroPage, mode: 'zeroPage' }, 0xC7: { name: 'DCM', fn: () => this.dcm(this.readAddrZeroPage), mode: 'zeroPage' },
0xD7: { name: 'DCM', op: this.dcm, modeFn: this.readAddrZeroPageX, mode: 'zeroPageX' }, 0xD7: { name: 'DCM', fn: () => this.dcm(this.readAddrZeroPageX), mode: 'zeroPageX' },
0xC3: { name: 'DCM', op: this.dcm, modeFn: this.readAddrZeroPageXIndirect, mode: 'zeroPageXIndirect' }, 0xC3: { name: 'DCM', fn: () => this.dcm(this.readAddrZeroPageXIndirect), mode: 'zeroPageXIndirect' },
0xD3: { name: 'DCM', op: this.dcm, modeFn: this.readAddrZeroPageIndirectY, mode: 'zeroPageIndirectY' }, 0xD3: { name: 'DCM', fn: () => this.dcm(this.readAddrZeroPageIndirectY), mode: 'zeroPageIndirectY' },
// INS // INS
0xEF: { name: 'INS', op: this.ins, modeFn: this.readAddrAbsolute, mode: 'absolute' }, 0xEF: { name: 'INS', fn: () => this.ins(this.readAddrAbsolute), mode: 'absolute' },
0xFF: { name: 'INS', op: this.ins, modeFn: this.readAddrAbsoluteX, mode: 'absoluteX' }, 0xFF: { name: 'INS', fn: () => this.ins(this.readAddrAbsoluteX), mode: 'absoluteX' },
0xFB: { name: 'INS', op: this.ins, modeFn: this.readAddrAbsoluteY, mode: 'absoluteY' }, 0xFB: { name: 'INS', fn: () => this.ins(this.readAddrAbsoluteY), mode: 'absoluteY' },
0xE7: { name: 'INS', op: this.ins, modeFn: this.readAddrZeroPage, mode: 'zeroPage' }, 0xE7: { name: 'INS', fn: () => this.ins(this.readAddrZeroPage), mode: 'zeroPage' },
0xF7: { name: 'INS', op: this.ins, modeFn: this.readAddrZeroPageX, mode: 'zeroPageX' }, 0xF7: { name: 'INS', fn: () => this.ins(this.readAddrZeroPageX), mode: 'zeroPageX' },
0xE3: { name: 'INS', op: this.ins, modeFn: this.readAddrZeroPageXIndirect, mode: 'zeroPageXIndirect' }, 0xE3: { name: 'INS', fn: () => this.ins(this.readAddrZeroPageXIndirect), mode: 'zeroPageXIndirect' },
0xF3: { name: 'INS', op: this.ins, modeFn: this.readAddrZeroPageIndirectY, mode: 'zeroPageIndirectY' }, 0xF3: { name: 'INS', fn: () => this.ins(this.readAddrZeroPageIndirectY), mode: 'zeroPageIndirectY' },
// ALR // ALR
0x4B: { name: 'ALR', op: this.alr, modeFn: this.readImmediate, mode: 'immediate' }, 0x4B: { name: 'ALR', fn: () => this.alr(this.readImmediate), mode: 'immediate' },
// ARR // ARR
0x6B: { name: 'ARR', op: this.arr, modeFn: this.readImmediate, mode: 'immediate' }, 0x6B: { name: 'ARR', fn: () => this.arr(this.readImmediate), mode: 'immediate' },
// XAA // XAA
0x8B: { name: 'XAA', op: this.xaa, modeFn: this.readImmediate, mode: 'immediate' }, 0x8B: { name: 'XAA', fn: () => this.xaa(this.readImmediate), mode: 'immediate' },
// OAL // OAL
0xAB: { name: 'OAL', op: this.oal, modeFn: this.readImmediate, mode: 'immediate' }, 0xAB: { name: 'OAL', fn: () => this.oal(this.readImmediate), mode: 'immediate' },
// SAX // SAX
0xCB: { name: 'SAX', op: this.sax, modeFn: this.readImmediate, mode: 'immediate' }, 0xCB: { name: 'SAX', fn: () => this.sax(this.readImmediate), mode: 'immediate' },
// NOP // NOP
0x1a: { name: 'NOP', op: this.nop, modeFn: this.implied, mode: 'implied' }, 0x1a: { name: 'NOP', fn: () => this.nop(this.implied), mode: 'implied' },
0x3a: { name: 'NOP', op: this.nop, modeFn: this.implied, mode: 'implied' }, 0x3a: { name: 'NOP', fn: () => this.nop(this.implied), mode: 'implied' },
0x5a: { name: 'NOP', op: this.nop, modeFn: this.implied, mode: 'implied' }, 0x5a: { name: 'NOP', fn: () => this.nop(this.implied), mode: 'implied' },
0x7a: { name: 'NOP', op: this.nop, modeFn: this.implied, mode: 'implied' }, 0x7a: { name: 'NOP', fn: () => this.nop(this.implied), mode: 'implied' },
0xda: { name: 'NOP', op: this.nop, modeFn: this.implied, mode: 'implied' }, 0xda: { name: 'NOP', fn: () => this.nop(this.implied), mode: 'implied' },
0xfa: { name: 'NOP', op: this.nop, modeFn: this.implied, mode: 'implied' }, 0xfa: { name: 'NOP', fn: () => this.nop(this.implied), mode: 'implied' },
// SKB // SKB
0x80: { name: 'SKB', op: this.skp, modeFn: this.readImmediate, mode: 'immediate' }, 0x80: { name: 'SKB', fn: () => this.skp(this.readImmediate), mode: 'immediate' },
0x82: { name: 'SKB', op: this.skp, modeFn: this.readImmediate, mode: 'immediate' }, 0x82: { name: 'SKB', fn: () => this.skp(this.readImmediate), mode: 'immediate' },
0x89: { name: 'SKB', op: this.skp, modeFn: this.readImmediate, mode: 'immediate' }, 0x89: { name: 'SKB', fn: () => this.skp(this.readImmediate), mode: 'immediate' },
0xC2: { name: 'SKB', op: this.skp, modeFn: this.readImmediate, mode: 'immediate' }, 0xC2: { name: 'SKB', fn: () => this.skp(this.readImmediate), mode: 'immediate' },
0xE2: { name: 'SKB', op: this.skp, modeFn: this.readImmediate, mode: 'immediate' }, 0xE2: { name: 'SKB', fn: () => this.skp(this.readImmediate), mode: 'immediate' },
0x04: { name: 'SKB', op: this.skp, modeFn: this.readZeroPage, mode: 'zeroPage' }, 0x04: { name: 'SKB', fn: () => this.skp(this.readZeroPage), mode: 'zeroPage' },
0x14: { name: 'SKB', op: this.skp, modeFn: this.readZeroPageX, mode: 'zeroPageX' }, 0x14: { name: 'SKB', fn: () => this.skp(this.readZeroPageX), mode: 'zeroPageX' },
0x34: { name: 'SKB', op: this.skp, modeFn: this.readZeroPageX, mode: 'zeroPageX' }, 0x34: { name: 'SKB', fn: () => this.skp(this.readZeroPageX), mode: 'zeroPageX' },
0x44: { name: 'SKB', op: this.skp, modeFn: this.readZeroPage, mode: 'zeroPage' }, 0x44: { name: 'SKB', fn: () => this.skp(this.readZeroPage), mode: 'zeroPage' },
0x54: { name: 'SKB', op: this.skp, modeFn: this.readZeroPageX, mode: 'zeroPageX' }, 0x54: { name: 'SKB', fn: () => this.skp(this.readZeroPageX), mode: 'zeroPageX' },
0x64: { name: 'SKB', op: this.skp, modeFn: this.readZeroPage, mode: 'zeroPage' }, 0x64: { name: 'SKB', fn: () => this.skp(this.readZeroPage), mode: 'zeroPage' },
0x74: { name: 'SKB', op: this.skp, modeFn: this.readZeroPageX, mode: 'zeroPageX' }, 0x74: { name: 'SKB', fn: () => this.skp(this.readZeroPageX), mode: 'zeroPageX' },
0xD4: { name: 'SKB', op: this.skp, modeFn: this.readZeroPageX, mode: 'zeroPageX' }, 0xD4: { name: 'SKB', fn: () => this.skp(this.readZeroPageX), mode: 'zeroPageX' },
0xF4: { name: 'SKB', op: this.skp, modeFn: this.readZeroPageX, mode: 'zeroPageX' }, 0xF4: { name: 'SKB', fn: () => this.skp(this.readZeroPageX), mode: 'zeroPageX' },
// SKW // SKW
0x0C: { name: 'SKW', op: this.skp, modeFn: this.readAddrAbsolute, mode: 'absolute' }, 0x0C: { name: 'SKW', fn: () => this.skp(this.readAddrAbsolute), mode: 'absolute' },
0x1C: { name: 'SKW', op: this.skp, modeFn: this.readAddrAbsoluteX, mode: 'absoluteX' }, 0x1C: { name: 'SKW', fn: () => this.skp(this.readAddrAbsoluteX), mode: 'absoluteX' },
0x3C: { name: 'SKW', op: this.skp, modeFn: this.readAddrAbsoluteX, mode: 'absoluteX' }, 0x3C: { name: 'SKW', fn: () => this.skp(this.readAddrAbsoluteX), mode: 'absoluteX' },
0x5C: { name: 'SKW', op: this.skp, modeFn: this.readAddrAbsoluteX, mode: 'absoluteX' }, 0x5C: { name: 'SKW', fn: () => this.skp(this.readAddrAbsoluteX), mode: 'absoluteX' },
0x7C: { name: 'SKW', op: this.skp, modeFn: this.readAddrAbsoluteX, mode: 'absoluteX' }, 0x7C: { name: 'SKW', fn: () => this.skp(this.readAddrAbsoluteX), mode: 'absoluteX' },
0xDC: { name: 'SKW', op: this.skp, modeFn: this.readAddrAbsoluteX, mode: 'absoluteX' }, 0xDC: { name: 'SKW', fn: () => this.skp(this.readAddrAbsoluteX), mode: 'absoluteX' },
0xFC: { name: 'SKW', op: this.skp, modeFn: this.readAddrAbsoluteX, mode: 'absoluteX' }, 0xFC: { name: 'SKW', fn: () => this.skp(this.readAddrAbsoluteX), mode: 'absoluteX' },
// HLT // HLT
0x02: { name: 'HLT', op: this.hlt, modeFn: this.readNopImplied, mode: 'implied' }, 0x02: { name: 'HLT', fn: () => this.hlt(this.readNopImplied), mode: 'implied' },
0x12: { name: 'HLT', op: this.hlt, modeFn: this.readNopImplied, mode: 'implied' }, 0x12: { name: 'HLT', fn: () => this.hlt(this.readNopImplied), mode: 'implied' },
0x22: { name: 'HLT', op: this.hlt, modeFn: this.readNopImplied, mode: 'implied' }, 0x22: { name: 'HLT', fn: () => this.hlt(this.readNopImplied), mode: 'implied' },
0x32: { name: 'HLT', op: this.hlt, modeFn: this.readNopImplied, mode: 'implied' }, 0x32: { name: 'HLT', fn: () => this.hlt(this.readNopImplied), mode: 'implied' },
0x42: { name: 'HLT', op: this.hlt, modeFn: this.readNopImplied, mode: 'implied' }, 0x42: { name: 'HLT', fn: () => this.hlt(this.readNopImplied), mode: 'implied' },
0x52: { name: 'HLT', op: this.hlt, modeFn: this.readNopImplied, mode: 'implied' }, 0x52: { name: 'HLT', fn: () => this.hlt(this.readNopImplied), mode: 'implied' },
0x62: { name: 'HLT', op: this.hlt, modeFn: this.readNopImplied, mode: 'implied' }, 0x62: { name: 'HLT', fn: () => this.hlt(this.readNopImplied), mode: 'implied' },
0x72: { name: 'HLT', op: this.hlt, modeFn: this.readNopImplied, mode: 'implied' }, 0x72: { name: 'HLT', fn: () => this.hlt(this.readNopImplied), mode: 'implied' },
0x92: { name: 'HLT', op: this.hlt, modeFn: this.readNopImplied, mode: 'implied' }, 0x92: { name: 'HLT', fn: () => this.hlt(this.readNopImplied), mode: 'implied' },
0xB2: { name: 'HLT', op: this.hlt, modeFn: this.readNopImplied, mode: 'implied' }, 0xB2: { name: 'HLT', fn: () => this.hlt(this.readNopImplied), mode: 'implied' },
0xD2: { name: 'HLT', op: this.hlt, modeFn: this.readNopImplied, mode: 'implied' }, 0xD2: { name: 'HLT', fn: () => this.hlt(this.readNopImplied), mode: 'implied' },
0xF2: { name: 'HLT', op: this.hlt, modeFn: this.readNopImplied, mode: 'implied' }, 0xF2: { name: 'HLT', fn: () => this.hlt(this.readNopImplied), mode: 'implied' },
// TAS // TAS
0x9B: { name: 'TAS', op: this.tas, modeFn: this.readAddrAbsoluteY, mode: 'absoluteY'}, 0x9B: { name: 'TAS', fn: () => this.tas(this.readAddrAbsoluteY), mode: 'absoluteY'},
// SAY // SAY
0x9C: { name: 'SAY', op: this.say, modeFn: this.readAddrAbsoluteX, mode: 'absoluteX'}, 0x9C: { name: 'SAY', fn: () => this.say(this.readAddrAbsoluteX), mode: 'absoluteX'},
// XAS // XAS
0x9E: { name: 'XAS', op: this.xas, modeFn: this.readAddrAbsoluteY, mode: 'absoluteY'}, 0x9E: { name: 'XAS', fn: () => this.xas(this.readAddrAbsoluteY), mode: 'absoluteY'},
// AXA // AXA
0x9F: { name: 'AXA', op: this.axa, modeFn: this.readAddrAbsoluteY, mode: 'absoluteY'}, 0x9F: { name: 'AXA', fn: () => this.axa(this.readAddrAbsoluteY), mode: 'absoluteY'},
0x93: { name: 'AXA', op: this.axa, modeFn: this.readAddrZeroPageIndirectY, mode: 'zeroPageIndirectY'}, 0x93: { name: 'AXA', fn: () => this.axa(this.readAddrZeroPageIndirectY), mode: 'zeroPageIndirectY'},
// ANC // ANC
0x2b: { name: 'ANC', op: this.anc, modeFn: this.readImmediate, mode: 'immediate' }, 0x2b: { name: 'ANC', fn: () => this.anc(this.readImmediate), mode: 'immediate' },
0x0b: { name: 'ANC', op: this.anc, modeFn: this.readImmediate, mode: 'immediate' }, 0x0b: { name: 'ANC', fn: () => this.anc(this.readImmediate), mode: 'immediate' },
// LAS // LAS
0xBB: { name: 'LAS', op: this.las, modeFn: this.readAbsoluteY, mode: 'absoluteY'}, 0xBB: { name: 'LAS', fn: () => this.las(this.readAbsoluteY), mode: 'absoluteY'},
// SBC // SBC
0xEB: { name: 'SBC', op: this.sbc, modeFn: this.readImmediate, mode: 'immediate'} 0xEB: { name: 'SBC', fn: () => this.sbc(this.readImmediate), mode: 'immediate'}
}; };
OPS_ROCKWELL_65C02: Instructions = { OPS_ROCKWELL_65C02: Instructions = {
0xCB: { name: 'NOP', op: this.nop, modeFn: this.implied, mode: 'implied' }, 0xCB: { name: 'NOP', fn: () => this.nop(this.implied), mode: 'implied' },
0xDB: { name: 'NOP', op: this.nop, modeFn: this.readZeroPageX, mode: 'immediate' }, 0xDB: { name: 'NOP', fn: () => this.nop(this.readZeroPageX), mode: 'immediate' },
}; };
/* WDC 65C02 Instructions */ /* WDC 65C02 Instructions */
OPS_WDC_65C02: Instructions = { OPS_WDC_65C02: Instructions = {
0xCB: { name: 'WAI', op: this.wai, modeFn: this.implied, mode: 'implied' }, 0xCB: { name: 'WAI', fn: () => this.wai(), mode: 'implied' },
0xDB: { name: 'STP', op: this.stp, modeFn: this.implied, mode: 'implied' } 0xDB: { name: 'STP', fn: () => this.stp(), mode: 'implied' }
}; };
} }