summaryrefslogtreecommitdiff
path: root/mknes_cpu_opcodes_ud.c
diff options
context:
space:
mode:
authorPeter Fors <peter.fors@mindkiller.com>2025-10-09 22:07:52 +0200
committerPeter Fors <peter.fors@mindkiller.com>2025-10-09 22:07:52 +0200
commit030724a9aea346e4a9843d5842fb28c6d6c4cf1a (patch)
treef06fb84aaef64b2f4e2d81b3d2d3eef71bad83ec /mknes_cpu_opcodes_ud.c
parent412b2ef851516c1de8ba5006ddd284192cbcaf9b (diff)
Rearrangement and refactoring and optimizations and more accuracy
Diffstat (limited to 'mknes_cpu_opcodes_ud.c')
-rw-r--r--mknes_cpu_opcodes_ud.c1398
1 files changed, 1398 insertions, 0 deletions
diff --git a/mknes_cpu_opcodes_ud.c b/mknes_cpu_opcodes_ud.c
new file mode 100644
index 0000000..9944f02
--- /dev/null
+++ b/mknes_cpu_opcodes_ud.c
@@ -0,0 +1,1398 @@
+
+
+
+// NOP
+
+static void opcode_nop_imm(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ memory_read(state, cpu->pc++); // T1: consume operand
+}
+
+static void opcode_nop_zp(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t addr = memory_read(state, cpu->pc++); // T1
+ memory_read_dummy(state, addr); // T2
+}
+
+static void opcode_nop_abs(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t lo = memory_read(state, cpu->pc++); // T1
+ uint8_t hi = memory_read(state, cpu->pc++); // T2
+ uint16_t addr = lo | (hi << 8);
+
+ memory_read_dummy(state, addr); // T3
+}
+
+static void opcode_nop_zpx(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t base = memory_read(state, cpu->pc++); // T1: fetch operand
+ memory_read_dummy(state, base); // T2: internal timing quirk (not used, but real)
+ uint8_t addr = (base + cpu->x) & 0xff;
+ memory_read_dummy(state, addr); // T3: final bus read to correct address
+}
+
+static void opcode_nop_absx(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t lo = memory_read(state, cpu->pc++); // T1
+ uint8_t hi = memory_read(state, cpu->pc++); // T2
+ uint16_t base = lo | (hi << 8);
+ uint16_t addr = base + cpu->x;
+
+ if(PAGE_CROSSED(base, addr)) {
+ memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff)); // T3 dummy read
+ }
+
+ memory_read_dummy(state, addr); // T4 — final bus cycle (even if not used)
+}
+
+
+static void opcode_nop_implied(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ memory_read_dummy(state, cpu->pc); // T1
+}
+
+
+// LAX
+
+static void opcode_lax_imm(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t value = memory_read(state, cpu->pc++);
+ cpu->a = value;
+ cpu->x = value;
+ update_zn(cpu, value);
+}
+
+static void opcode_lax_indx(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t zp = memory_read(state, cpu->pc++);
+ memory_read_dummy(state, zp);
+
+ uint8_t ptr = (zp + cpu->x) & 0xff;
+ uint8_t lo = memory_read(state, ptr);
+ uint8_t hi = memory_read(state, (ptr + 1) & 0xff);
+ uint16_t addr = lo | (hi << 8);
+
+ uint8_t value = memory_read(state, addr);
+ cpu->a = value;
+ cpu->x = value;
+ update_zn(cpu, value);
+}
+
+static void opcode_lax_zp(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t addr = memory_read(state, cpu->pc++);
+ uint8_t value = memory_read(state, addr);
+
+ cpu->a = value;
+ cpu->x = value;
+ update_zn(cpu, value);
+}
+
+static void opcode_lax_zpy(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t base = memory_read(state, cpu->pc++);
+ memory_read_dummy(state, base);
+ uint8_t addr = (base + cpu->y) & 0xff;
+
+ uint8_t value = memory_read(state, addr);
+ cpu->a = value;
+ cpu->x = value;
+ update_zn(cpu, value);
+}
+
+static void opcode_lax_abs(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t lo = memory_read(state, cpu->pc++);
+ uint8_t hi = memory_read(state, cpu->pc++);
+ uint16_t addr = lo | (hi << 8);
+
+ uint8_t value = memory_read(state, addr);
+ cpu->a = value;
+ cpu->x = value;
+ update_zn(cpu, value);
+}
+
+static void opcode_lax_absy(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t lo = memory_read(state, cpu->pc++);
+ uint8_t hi = memory_read(state, cpu->pc++);
+ uint16_t base = lo | (hi << 8);
+ uint16_t addr = base + cpu->y;
+
+ if(PAGE_CROSSED(base, addr)) {
+ memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff));
+ }
+
+ uint8_t value = memory_read(state, addr);
+ cpu->a = value;
+ cpu->x = value;
+ update_zn(cpu, value);
+}
+
+static void opcode_lax_indy(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t zp = memory_read(state, cpu->pc++);
+ uint8_t lo = memory_read(state, zp);
+ uint8_t hi = memory_read(state, (zp + 1) & 0xff);
+ uint16_t base = lo | (hi << 8);
+ uint16_t addr = base + cpu->y;
+
+ if(PAGE_CROSSED(base, addr)) {
+ memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff));
+ }
+
+ uint8_t value = memory_read(state, addr);
+ cpu->a = value;
+ cpu->x = value;
+ update_zn(cpu, value);
+}
+
+
+// SAX
+
+static void opcode_sax_indx(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t zp = memory_read(state, cpu->pc++); // T1
+ memory_read_dummy(state, zp); // T2
+ uint8_t ptr = zp + cpu->x;
+ uint8_t lo = memory_read(state, ptr & 0xff); // T3
+ uint8_t hi = memory_read(state, (ptr + 1) & 0xff); // T4
+ uint16_t addr = lo | (hi << 8);
+ memory_write(state, addr, cpu->a & cpu->x); // T5
+}
+
+
+static void opcode_sax_zp(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t addr = memory_read(state, cpu->pc++);
+ memory_write(state, addr, cpu->a & cpu->x);
+}
+
+static void opcode_sax_abs(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t lo = memory_read(state, cpu->pc++);
+ uint8_t hi = memory_read(state, cpu->pc++);
+ uint16_t addr = lo | (hi << 8);
+
+ memory_write(state, addr, cpu->a & cpu->x);
+}
+
+static void opcode_sax_zpy(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t base = memory_read(state, cpu->pc++);
+ memory_read_dummy(state, base);
+ uint8_t addr = (base + cpu->y) & 0xff;
+
+ memory_write(state, addr, cpu->a & cpu->x);
+}
+
+/* SHA (SHA Absolute,Y) - Opcode $9F - 5 cycles */
+static void opcode_sha_absy(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t lo = memory_read(state, cpu->pc++); // T1
+ uint8_t hi = memory_read(state, cpu->pc++); // T2
+
+ uint16_t base_addr = lo | (hi << 8);
+ uint16_t eff_addr = base_addr + cpu->y;
+
+ // T3: Dummy read from the base address. CAPTURE the high byte here.
+ memory_read(state, base_addr);
+ uint8_t H = (base_addr >> 8); // This is the 'H' from the author's code
+
+ // T4: The write cycle
+ if ((base_addr & 0xFF00) != (eff_addr & 0xFF00)) {
+ eff_addr = (eff_addr & 0x00FF) | (((eff_addr >> 8) & cpu->x) << 8);
+ }
+
+ uint8_t magic = 0xF5;
+ // USE H in the value calculation: A & (X | magic) & H
+ uint8_t value_to_store = cpu->a & (cpu->x | magic) & H;
+
+ memory_write(state, eff_addr, value_to_store); // T4, T5: Write
+}
+
+/* SHA (SHA Indirect,Y) - Opcode $93 - 6 cycles - REVISED THEORY */
+/*
+// Old implementation - commented out for reference
+static void opcode_sha_indy(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t zp = memory_read(state, cpu->pc++); // T1
+ uint8_t ptr_lo = memory_read(state, zp); // T2
+ uint8_t ptr_hi = memory_read(state, (zp + 1) & 0xFF); // T3
+
+ uint16_t base_addr = ptr_lo | (ptr_hi << 8);
+ uint16_t eff_addr = base_addr + cpu->y;
+
+ // REVISED FORMULA: AND the high byte of the effective address with (X + 1)
+ uint8_t hi_byte = (eff_addr >> 8);
+ uint8_t hi_byte_corrupted = hi_byte & (cpu->x + 1); // <-- KEY CHANGE: & (X + 1)
+ uint16_t final_addr = (eff_addr & 0x00FF) | (hi_byte_corrupted << 8);
+
+ memory_read(state, base_addr); // T4: Dummy read
+
+ uint8_t value = cpu->a & cpu->x;
+ memory_write(state, final_addr, value); // T5, T6: Write
+}
+*/
+
+static void opcode_sha_indy(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t zp = memory_read(state, cpu->pc++); // T1: fetch pointer address
+ uint8_t ptr_lo = memory_read(state, zp); // T2: fetch address low
+ uint8_t ptr_hi = memory_read(state, (zp + 1) & 0xFF); // T3: fetch address high
+
+ // T3: add Y to low byte only, save original as temporaryAddress
+ uint16_t temporary_address = ptr_lo | (ptr_hi << 8);
+ uint16_t address_bus = (temporary_address & 0xFF00) | ((temporary_address + cpu->y) & 0xFF);
+
+ // T4: dummy read from current address_bus
+ memory_read(state, address_bus);
+
+ // T4: Calculate H (high byte + 1) and check for page boundary crossing
+ uint8_t h = (address_bus >> 8) + 1;
+ uint16_t full_address = temporary_address + cpu->y;
+ uint8_t page_crossed = ((temporary_address & 0xFF00) != (full_address & 0xFF00));
+ if (page_crossed) {
+ address_bus += 0x100; // increment high byte if page boundary crossed
+ }
+
+ // T5: read from address (this is where the actual read happens in cycle 5)
+ memory_read(state, address_bus);
+
+ // T5: Apply corruption if page boundary was crossed
+ if (page_crossed) {
+ // Alternate SHA behavior when page boundary crossed
+ address_bus = (uint8_t)address_bus | (((address_bus >> 8) & cpu->x) << 8);
+ }
+
+ // T5: Store A & (X | 0xF5) & H - using 0xF5 as magic number
+ uint8_t value = cpu->a & (cpu->x | 0xF5) & h;
+ memory_write(state, address_bus, value); // T6: Write
+}
+
+// DCP
+
+static void opcode_dcp_indx(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t zp = memory_read(state, cpu->pc++);
+ memory_read_dummy(state, zp);
+
+ uint8_t ptr = (zp + cpu->x) & 0xff;
+ uint8_t lo = memory_read(state, ptr);
+ uint8_t hi = memory_read(state, (ptr + 1) & 0xff);
+ uint16_t addr = lo | (hi << 8);
+
+ uint8_t value = memory_read(state, addr);
+ memory_write(state, addr, value); // dummy write
+ value--;
+ memory_write(state, addr, value);
+
+ uint16_t tmp = cpu->a - value;
+ cpu->c = (cpu->a >= value);
+ update_zn(cpu, tmp & 0xff);
+}
+
+static void opcode_dcp_zp(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t addr = memory_read(state, cpu->pc++);
+ uint8_t value = memory_read(state, addr);
+ memory_write(state, addr, value); // dummy write
+ value--;
+ memory_write(state, addr, value);
+
+ uint16_t tmp = cpu->a - value;
+ cpu->c = (cpu->a >= value);
+ update_zn(cpu, tmp & 0xff);
+}
+
+static void opcode_dcp_abs(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t lo = memory_read(state, cpu->pc++);
+ uint8_t hi = memory_read(state, cpu->pc++);
+ uint16_t addr = lo | (hi << 8);
+
+ uint8_t value = memory_read(state, addr);
+ memory_write(state, addr, value); // dummy write
+ value--;
+ memory_write(state, addr, value);
+
+ uint16_t tmp = cpu->a - value;
+ cpu->c = (cpu->a >= value);
+ update_zn(cpu, tmp & 0xff);
+}
+
+static void opcode_dcp_indy(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t zp = memory_read(state, cpu->pc++);
+ uint8_t lo = memory_read(state, zp);
+ uint8_t hi = memory_read(state, (zp + 1) & 0xff);
+ uint16_t base = lo | (hi << 8);
+ uint16_t addr = base + cpu->y;
+
+ if(PAGE_CROSSED(base, addr)) {
+ memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff));
+ }
+
+ uint8_t value = memory_read(state, addr);
+ memory_write(state, addr, value); // dummy write
+ value--;
+ memory_write(state, addr, value);
+
+ uint16_t tmp = cpu->a - value;
+ cpu->c = (cpu->a >= value);
+ update_zn(cpu, tmp & 0xff);
+}
+
+static void opcode_dcp_zpx(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t base = memory_read(state, cpu->pc++);
+ memory_read_dummy(state, base);
+ uint8_t addr = (base + cpu->x) & 0xff;
+
+ uint8_t value = memory_read(state, addr);
+ memory_write(state, addr, value); // dummy write
+ value--;
+ memory_write(state, addr, value);
+
+ uint16_t tmp = cpu->a - value;
+ cpu->c = (cpu->a >= value);
+ update_zn(cpu, tmp & 0xff);
+}
+
+static void opcode_dcp_absy(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t lo = memory_read(state, cpu->pc++);
+ uint8_t hi = memory_read(state, cpu->pc++);
+ uint16_t base = lo | (hi << 8);
+ uint16_t addr = base + cpu->y;
+
+ memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff));
+
+ uint8_t value = memory_read(state, addr);
+ memory_write(state, addr, value); // dummy write
+ value--;
+ memory_write(state, addr, value);
+
+ uint16_t tmp = cpu->a - value;
+ cpu->c = (cpu->a >= value);
+ update_zn(cpu, tmp & 0xff);
+}
+
+static void opcode_dcp_absx(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t lo = memory_read(state, cpu->pc++);
+ uint8_t hi = memory_read(state, cpu->pc++);
+ uint16_t base = lo | (hi << 8);
+ uint16_t addr = base + cpu->x;
+
+ memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff));
+
+ uint8_t value = memory_read(state, addr);
+ memory_write(state, addr, value); // dummy write
+ value--;
+ memory_write(state, addr, value);
+
+ uint16_t tmp = cpu->a - value;
+ cpu->c = (cpu->a >= value);
+ update_zn(cpu, tmp & 0xff);
+}
+
+
+// ISC
+
+static void opcode_isc_indx(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t zp = memory_read(state, cpu->pc++);
+ memory_read_dummy(state, zp);
+
+ uint8_t ptr = (zp + cpu->x) & 0xff;
+ uint8_t lo = memory_read(state, ptr);
+ uint8_t hi = memory_read(state, (ptr + 1) & 0xff);
+ uint16_t addr = lo | (hi << 8);
+
+ uint8_t value = memory_read(state, addr);
+ memory_write(state, addr, value); // dummy write
+ value++;
+ memory_write(state, addr, value);
+
+ sbc(cpu, value);
+}
+
+static void opcode_isc_zp(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t addr = memory_read(state, cpu->pc++);
+ uint8_t value = memory_read(state, addr);
+ memory_write(state, addr, value); // dummy write
+ value++;
+ memory_write(state, addr, value);
+
+ sbc(cpu, value);
+}
+
+static void opcode_isc_abs(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t lo = memory_read(state, cpu->pc++);
+ uint8_t hi = memory_read(state, cpu->pc++);
+ uint16_t addr = lo | (hi << 8);
+
+ uint8_t value = memory_read(state, addr);
+ memory_write(state, addr, value); // dummy write
+ value++;
+ memory_write(state, addr, value);
+
+ sbc(cpu, value);
+}
+
+static void opcode_isc_indy(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t zp = memory_read(state, cpu->pc++);
+ uint8_t lo = memory_read(state, zp);
+ uint8_t hi = memory_read(state, (zp + 1) & 0xff);
+ uint16_t base = lo | (hi << 8);
+ uint16_t addr = base + cpu->y;
+
+ if(PAGE_CROSSED(base, addr)) {
+ memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff));
+ }
+
+ uint8_t value = memory_read(state, addr);
+ memory_write(state, addr, value); // dummy write
+ value++;
+ memory_write(state, addr, value);
+
+ sbc(cpu, value);
+}
+
+static void opcode_isc_zpx(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t base = memory_read(state, cpu->pc++);
+ memory_read_dummy(state, base);
+ uint8_t addr = (base + cpu->x) & 0xff;
+
+ uint8_t value = memory_read(state, addr);
+ memory_write(state, addr, value); // dummy write
+ value++;
+ memory_write(state, addr, value);
+
+ sbc(cpu, value);
+}
+
+static void opcode_isc_absy(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t lo = memory_read(state, cpu->pc++);
+ uint8_t hi = memory_read(state, cpu->pc++);
+ uint16_t base = lo | (hi << 8);
+ uint16_t addr = base + cpu->y;
+
+ memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff));
+
+ uint8_t value = memory_read(state, addr);
+ memory_write(state, addr, value); // dummy write
+ value++;
+ memory_write(state, addr, value);
+
+ sbc(cpu, value);
+}
+
+static void opcode_isc_absx(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t lo = memory_read(state, cpu->pc++);
+ uint8_t hi = memory_read(state, cpu->pc++);
+ uint16_t base = lo | (hi << 8);
+ uint16_t addr = base + cpu->x;
+
+ memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff));
+
+ uint8_t value = memory_read(state, addr);
+ memory_write(state, addr, value); // dummy write
+ value++;
+ memory_write(state, addr, value);
+
+ sbc(cpu, value);
+}
+
+
+// SLO
+
+static void opcode_slo_indx(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t zp = memory_read(state, cpu->pc++);
+ memory_read_dummy(state, zp);
+
+ uint8_t ptr = (zp + cpu->x) & 0xff;
+ uint8_t lo = memory_read(state, ptr);
+ uint8_t hi = memory_read(state, (ptr + 1) & 0xff);
+ uint16_t addr = lo | (hi << 8);
+
+ uint8_t value = memory_read(state, addr);
+ memory_write(state, addr, value); // dummy write
+
+ cpu->c = (value >> 7) & 1;
+ value <<= 1;
+
+ memory_write(state, addr, value);
+ cpu->a |= value;
+ update_zn(cpu, cpu->a);
+}
+
+static void opcode_slo_zp(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t addr = memory_read(state, cpu->pc++);
+ uint8_t value = memory_read(state, addr);
+ memory_write(state, addr, value); // dummy write
+
+ cpu->c = (value >> 7) & 1;
+ value <<= 1;
+
+ memory_write(state, addr, value);
+ cpu->a |= value;
+ update_zn(cpu, cpu->a);
+}
+
+static void opcode_slo_abs(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t lo = memory_read(state, cpu->pc++);
+ uint8_t hi = memory_read(state, cpu->pc++);
+ uint16_t addr = lo | (hi << 8);
+
+ uint8_t value = memory_read(state, addr);
+ memory_write(state, addr, value); // dummy write
+
+ cpu->c = (value >> 7) & 1;
+ value <<= 1;
+
+ memory_write(state, addr, value);
+ cpu->a |= value;
+ update_zn(cpu, cpu->a);
+}
+
+static void opcode_slo_indy(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t zp = memory_read(state, cpu->pc++);
+ uint8_t lo = memory_read(state, zp);
+ uint8_t hi = memory_read(state, (zp + 1) & 0xff);
+ uint16_t base = lo | (hi << 8);
+ uint16_t addr = base + cpu->y;
+
+ if(PAGE_CROSSED(base, addr)) {
+ memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff));
+ }
+
+ uint8_t value = memory_read(state, addr);
+ memory_write(state, addr, value); // dummy write
+
+ cpu->c = (value >> 7) & 1;
+ value <<= 1;
+
+ memory_write(state, addr, value);
+ cpu->a |= value;
+ update_zn(cpu, cpu->a);
+}
+
+static void opcode_slo_zpx(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t base = memory_read(state, cpu->pc++);
+ memory_read_dummy(state, base);
+ uint8_t addr = (base + cpu->x) & 0xff;
+
+ uint8_t value = memory_read(state, addr);
+ memory_write(state, addr, value); // dummy write
+
+ cpu->c = (value >> 7) & 1;
+ value <<= 1;
+
+ memory_write(state, addr, value);
+ cpu->a |= value;
+ update_zn(cpu, cpu->a);
+}
+
+static void opcode_slo_absy(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t lo = memory_read(state, cpu->pc++);
+ uint8_t hi = memory_read(state, cpu->pc++);
+ uint16_t base = lo | (hi << 8);
+ uint16_t addr = base + cpu->y;
+
+ memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff));
+
+ uint8_t value = memory_read(state, addr);
+ memory_write(state, addr, value); // dummy write
+
+ cpu->c = (value >> 7) & 1;
+ value <<= 1;
+
+ memory_write(state, addr, value);
+ cpu->a |= value;
+ update_zn(cpu, cpu->a);
+}
+
+static void opcode_slo_absx(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t lo = memory_read(state, cpu->pc++);
+ uint8_t hi = memory_read(state, cpu->pc++);
+ uint16_t base = lo | (hi << 8);
+ uint16_t addr = base + cpu->x;
+
+ memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff));
+
+ uint8_t value = memory_read(state, addr);
+ memory_write(state, addr, value); // dummy write
+
+ cpu->c = (value >> 7) & 1;
+ value <<= 1;
+
+ memory_write(state, addr, value);
+ cpu->a |= value;
+ update_zn(cpu, cpu->a);
+}
+
+
+// RLA
+
+static void opcode_rla_indx(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t zp = memory_read(state, cpu->pc++);
+ memory_read_dummy(state, zp);
+
+ uint8_t ptr = (zp + cpu->x) & 0xff;
+ uint8_t lo = memory_read(state, ptr);
+ uint8_t hi = memory_read(state, (ptr + 1) & 0xff);
+ uint16_t addr = lo | (hi << 8);
+
+ uint8_t value = memory_read(state, addr);
+ memory_write(state, addr, value); // dummy write
+
+ uint8_t in = cpu->c;
+ cpu->c = (value >> 7) & 1;
+ value = (value << 1) | in;
+
+ memory_write(state, addr, value);
+ cpu->a &= value;
+ update_zn(cpu, cpu->a);
+}
+
+static void opcode_rla_zp(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t addr = memory_read(state, cpu->pc++);
+ uint8_t value = memory_read(state, addr);
+ memory_write(state, addr, value); // dummy write
+
+ uint8_t in = cpu->c;
+ cpu->c = (value >> 7) & 1;
+ value = (value << 1) | in;
+
+ memory_write(state, addr, value);
+ cpu->a &= value;
+ update_zn(cpu, cpu->a);
+}
+
+static void opcode_rla_abs(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t lo = memory_read(state, cpu->pc++);
+ uint8_t hi = memory_read(state, cpu->pc++);
+ uint16_t addr = lo | (hi << 8);
+
+ uint8_t value = memory_read(state, addr);
+ memory_write(state, addr, value); // dummy write
+
+ uint8_t in = cpu->c;
+ cpu->c = (value >> 7) & 1;
+ value = (value << 1) | in;
+
+ memory_write(state, addr, value);
+ cpu->a &= value;
+ update_zn(cpu, cpu->a);
+}
+
+static void opcode_rla_indy(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t zp = memory_read(state, cpu->pc++);
+ uint8_t lo = memory_read(state, zp);
+ uint8_t hi = memory_read(state, (zp + 1) & 0xff);
+ uint16_t base = lo | (hi << 8);
+ uint16_t addr = base + cpu->y;
+
+ if(PAGE_CROSSED(base, addr)) {
+ memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff));
+ }
+
+ uint8_t value = memory_read(state, addr);
+ memory_write(state, addr, value); // dummy write
+
+ uint8_t in = cpu->c;
+ cpu->c = (value >> 7) & 1;
+ value = (value << 1) | in;
+
+ memory_write(state, addr, value);
+ cpu->a &= value;
+ update_zn(cpu, cpu->a);
+}
+
+static void opcode_rla_zpx(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t base = memory_read(state, cpu->pc++);
+ memory_read_dummy(state, base);
+ uint8_t addr = (base + cpu->x) & 0xff;
+
+ uint8_t value = memory_read(state, addr);
+ memory_write(state, addr, value); // dummy write
+
+ uint8_t in = cpu->c;
+ cpu->c = (value >> 7) & 1;
+ value = (value << 1) | in;
+
+ memory_write(state, addr, value);
+ cpu->a &= value;
+ update_zn(cpu, cpu->a);
+}
+
+static void opcode_rla_absy(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t lo = memory_read(state, cpu->pc++);
+ uint8_t hi = memory_read(state, cpu->pc++);
+ uint16_t base = lo | (hi << 8);
+ uint16_t addr = base + cpu->y;
+
+ memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff));
+
+ uint8_t value = memory_read(state, addr);
+ memory_write(state, addr, value); // dummy write
+
+ uint8_t in = cpu->c;
+ cpu->c = (value >> 7) & 1;
+ value = (value << 1) | in;
+
+ memory_write(state, addr, value);
+ cpu->a &= value;
+ update_zn(cpu, cpu->a);
+}
+
+static void opcode_rla_absx(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t lo = memory_read(state, cpu->pc++);
+ uint8_t hi = memory_read(state, cpu->pc++);
+ uint16_t base = lo | (hi << 8);
+ uint16_t addr = base + cpu->x;
+
+ memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff));
+
+ uint8_t value = memory_read(state, addr);
+ memory_write(state, addr, value); // dummy write
+
+ uint8_t in = cpu->c;
+ cpu->c = (value >> 7) & 1;
+ value = (value << 1) | in;
+
+ memory_write(state, addr, value);
+ cpu->a &= value;
+ update_zn(cpu, cpu->a);
+}
+
+
+// SRE
+
+static void opcode_sre_indx(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t zp = memory_read(state, cpu->pc++);
+ memory_read_dummy(state, zp);
+
+ uint8_t ptr = (zp + cpu->x) & 0xff;
+ uint8_t lo = memory_read(state, ptr);
+ uint8_t hi = memory_read(state, (ptr + 1) & 0xff);
+ uint16_t addr = lo | (hi << 8);
+
+ uint8_t value = memory_read(state, addr);
+ memory_write(state, addr, value); // dummy write
+
+ cpu->c = value & 1;
+ value >>= 1;
+
+ memory_write(state, addr, value);
+ cpu->a ^= value;
+ update_zn(cpu, cpu->a);
+}
+
+static void opcode_sre_zp(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t addr = memory_read(state, cpu->pc++);
+ uint8_t value = memory_read(state, addr);
+ memory_write(state, addr, value); // dummy write
+
+ cpu->c = value & 1;
+ value >>= 1;
+
+ memory_write(state, addr, value);
+ cpu->a ^= value;
+ update_zn(cpu, cpu->a);
+}
+
+static void opcode_sre_abs(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t lo = memory_read(state, cpu->pc++);
+ uint8_t hi = memory_read(state, cpu->pc++);
+ uint16_t addr = lo | (hi << 8);
+
+ uint8_t value = memory_read(state, addr);
+ memory_write(state, addr, value); // dummy write
+
+ cpu->c = value & 1;
+ value >>= 1;
+
+ memory_write(state, addr, value);
+ cpu->a ^= value;
+ update_zn(cpu, cpu->a);
+}
+
+static void opcode_sre_indy(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t zp = memory_read(state, cpu->pc++);
+ uint8_t lo = memory_read(state, zp);
+ uint8_t hi = memory_read(state, (zp + 1) & 0xff);
+ uint16_t base = lo | (hi << 8);
+ uint16_t addr = base + cpu->y;
+
+ if(PAGE_CROSSED(base, addr)) {
+ memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff));
+ }
+
+ uint8_t value = memory_read(state, addr);
+ memory_write(state, addr, value); // dummy write
+
+ cpu->c = value & 1;
+ value >>= 1;
+
+ memory_write(state, addr, value);
+ cpu->a ^= value;
+ update_zn(cpu, cpu->a);
+}
+
+static void opcode_sre_zpx(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t base = memory_read(state, cpu->pc++);
+ memory_read_dummy(state, base);
+ uint8_t addr = (base + cpu->x) & 0xff;
+
+ uint8_t value = memory_read(state, addr);
+ memory_write(state, addr, value); // dummy write
+
+ cpu->c = value & 1;
+ value >>= 1;
+
+ memory_write(state, addr, value);
+ cpu->a ^= value;
+ update_zn(cpu, cpu->a);
+}
+
+static void opcode_sre_absy(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t lo = memory_read(state, cpu->pc++);
+ uint8_t hi = memory_read(state, cpu->pc++);
+ uint16_t base = lo | (hi << 8);
+ uint16_t addr = base + cpu->y;
+
+ memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff));
+
+ uint8_t value = memory_read(state, addr);
+ memory_write(state, addr, value); // dummy write
+
+ cpu->c = value & 1;
+ value >>= 1;
+
+ memory_write(state, addr, value);
+ cpu->a ^= value;
+ update_zn(cpu, cpu->a);
+}
+
+static void opcode_sre_absx(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t lo = memory_read(state, cpu->pc++);
+ uint8_t hi = memory_read(state, cpu->pc++);
+ uint16_t base = lo | (hi << 8);
+ uint16_t addr = base + cpu->x;
+
+ memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff));
+
+ uint8_t value = memory_read(state, addr);
+ memory_write(state, addr, value); // dummy write
+
+ cpu->c = value & 1;
+ value >>= 1;
+
+ memory_write(state, addr, value);
+ cpu->a ^= value;
+ update_zn(cpu, cpu->a);
+}
+
+
+// opcode_rra
+
+static void opcode_rra_indx(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t zp = memory_read(state, cpu->pc++);
+ memory_read_dummy(state, zp);
+
+ uint8_t ptr = (zp + cpu->x) & 0xff;
+ uint8_t lo = memory_read(state, ptr);
+ uint8_t hi = memory_read(state, (ptr + 1) & 0xff);
+ uint16_t addr = lo | (hi << 8);
+
+ uint8_t value = memory_read(state, addr);
+ memory_write(state, addr, value); // dummy write
+
+ uint8_t new_c = value & 1;
+ value = (value >> 1) | (cpu->c << 7);
+ cpu->c = new_c;
+
+ memory_write(state, addr, value);
+ adc(cpu, value);
+}
+
+static void opcode_rra_zp(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t addr = memory_read(state, cpu->pc++);
+ uint8_t value = memory_read(state, addr);
+ memory_write(state, addr, value); // dummy write
+
+ uint8_t new_c = value & 1;
+ value = (value >> 1) | (cpu->c << 7);
+ cpu->c = new_c;
+
+ memory_write(state, addr, value);
+ adc(cpu, value);
+}
+
+static void opcode_rra_abs(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t lo = memory_read(state, cpu->pc++);
+ uint8_t hi = memory_read(state, cpu->pc++);
+ uint16_t addr = lo | (hi << 8);
+
+ uint8_t value = memory_read(state, addr);
+ memory_write(state, addr, value); // dummy write
+
+ uint8_t new_c = value & 1;
+ value = (value >> 1) | (cpu->c << 7);
+ cpu->c = new_c;
+
+ memory_write(state, addr, value);
+ adc(cpu, value);
+}
+
+static void opcode_rra_indy(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t zp = memory_read(state, cpu->pc++);
+ uint8_t lo = memory_read(state, zp);
+ uint8_t hi = memory_read(state, (zp + 1) & 0xff);
+ uint16_t base = lo | (hi << 8);
+ uint16_t addr = base + cpu->y;
+
+ if(PAGE_CROSSED(base, addr)) {
+ memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff));
+ }
+
+ uint8_t value = memory_read(state, addr);
+ memory_write(state, addr, value); // dummy write
+
+ uint8_t new_c = value & 1;
+ value = (value >> 1) | (cpu->c << 7);
+ cpu->c = new_c;
+
+ memory_write(state, addr, value);
+ adc(cpu, value);
+}
+
+static void opcode_rra_zpx(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t base = memory_read(state, cpu->pc++);
+ memory_read_dummy(state, base);
+ uint8_t addr = (base + cpu->x) & 0xff;
+
+ uint8_t value = memory_read(state, addr);
+ memory_write(state, addr, value); // dummy write
+
+ uint8_t new_c = value & 1;
+ value = (value >> 1) | (cpu->c << 7);
+ cpu->c = new_c;
+
+ memory_write(state, addr, value);
+ adc(cpu, value);
+}
+
+static void opcode_rra_absy(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t lo = memory_read(state, cpu->pc++);
+ uint8_t hi = memory_read(state, cpu->pc++);
+ uint16_t base = lo | (hi << 8);
+ uint16_t addr = base + cpu->y;
+
+ memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff));
+
+ uint8_t value = memory_read(state, addr);
+ memory_write(state, addr, value); // dummy write
+
+ uint8_t new_c = value & 1;
+ value = (value >> 1) | (cpu->c << 7);
+ cpu->c = new_c;
+
+ memory_write(state, addr, value);
+ adc(cpu, value);
+}
+
+static void opcode_rra_absx(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t lo = memory_read(state, cpu->pc++);
+ uint8_t hi = memory_read(state, cpu->pc++);
+ uint16_t base = lo | (hi << 8);
+ uint16_t addr = base + cpu->x;
+
+ memory_read_dummy(state, (base & 0xff00) | (addr & 0x00ff));
+
+ uint8_t value = memory_read(state, addr);
+ memory_write(state, addr, value); // dummy write
+
+ uint8_t new_c = value & 1;
+ value = (value >> 1) | (cpu->c << 7);
+ cpu->c = new_c;
+
+ memory_write(state, addr, value);
+ adc(cpu, value);
+}
+
+
+// ALR
+
+static void opcode_alr_imm(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+ uint8_t value = memory_read(state, cpu->pc++);
+ cpu->a &= value;
+ cpu->c = cpu->a & 1;
+ cpu->a >>= 1;
+ update_zn(cpu, cpu->a);
+}
+
+/* ANC (ANC Immediate) - Opcode $0B / $2B - 2 cycles? OR 1 byte? */
+static void opcode_anc_imm(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t value = memory_read(state, cpu->pc++);
+ cpu->a = cpu->a & value;
+ cpu->c = (cpu->a >= 0x80);
+ update_zn(cpu, cpu->a);
+
+}
+
+/* ARR (ARR Immediate) - Opcode $6B - 2 cycles - ALTERNATIVE PRECISE VERSION */
+static void opcode_arr_imm(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t value = memory_read(state, cpu->pc++); // GetImmediate()
+ cpu->a = cpu->a & value; // A = (byte)(A & dl);
+
+ // Op_ROR_A(); (Standard ROR on A)
+ uint8_t new_carry = cpu->a & 0x01;
+ cpu->a = (cpu->a >> 1) | (cpu->c << 7);
+
+ // Set flags exactly as the author does
+ cpu->z = (cpu->a == 0); // flag_Zero = A == 0;
+ cpu->n = (cpu->a & 0x80) ? 1 : 0; // flag_Negative = A >= 0x80;
+ cpu->c = (cpu->a & 0x40) ? 1 : 0; // flag_Carry = ((A & 0x40) >> 6) == 1;
+ cpu->v = (cpu->a & 0x20) ? 1 : 0; // flag_Overflow = ((A & 0x20) >> 5) == 1;
+ if (cpu->c) { // if (flag_Carry) {
+ cpu->v = cpu->v ^ 1; // flag_Overflow = !flag_Overflow;
+ }
+}
+
+// XAA
+
+static void opcode_xaa_imm(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t value = memory_read(state, cpu->pc++);
+ cpu->a = cpu->a & cpu->x & value;
+ update_zn(cpu, cpu->a);
+}
+
+
+/* AXS (AXS Immediate) - Opcode $CB - 2 cycles */
+static void opcode_axs_imm(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t value = memory_read(state, cpu->pc++); // T1
+ uint16_t temp = (cpu->a & cpu->x) - value; // T2: The core operation
+
+ cpu->c = (temp <= 0xFF) ? 1 : 0; // Carry is set if no borrow was needed (like CMP)
+ cpu->x = temp & 0xFF; // Result is stored in X
+
+ update_zn(cpu, cpu->x);
+}
+
+/* LAS (LAS Absolute,Y) - Opcode $BB - 4 cycles (+1 if page crossed) */
+static void opcode_las_absy(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t lo = memory_read(state, cpu->pc++); // T1
+ uint8_t hi = memory_read(state, cpu->pc++); // T2
+
+ uint16_t addr = lo | (hi << 8);
+ uint16_t addr_final = addr + cpu->y;
+
+ // Handle page crossing penalty
+ if ((addr & 0xFF00) != (addr_final & 0xFF00)) {
+ memory_read(state, (addr & 0xFF00) | (addr_final & 0x00FF)); // T3: Read from wrong page
+ }
+
+ uint8_t value = memory_read(state, addr_final); // T4: Read from correct address
+ value = value & cpu->sp; // The key operation: AND with Stack Pointer
+
+ cpu->a = value;
+ cpu->x = value;
+ cpu->sp = value;
+
+ update_zn(cpu, cpu->a);
+}
+
+/* SHX (SHX Absolute,Y) - Opcode $9E - 5 cycles */
+static void opcode_shx_absy(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t lo = memory_read(state, cpu->pc++); // T1
+ uint8_t hi = memory_read(state, cpu->pc++); // T2
+
+ uint16_t base_addr = lo | (hi << 8);
+ uint16_t eff_addr = base_addr + cpu->y;
+
+ uint8_t hi_byte_corrupted = (eff_addr >> 8) & cpu->x; // AND with X
+ uint16_t final_addr = (eff_addr & 0x00FF) | (hi_byte_corrupted << 8);
+
+ memory_read(state, base_addr); // T3: Dummy read
+
+ memory_write(state, final_addr, cpu->x); // T4, T5: Write X
+}
+
+/* SHY (SHY Absolute,X) - Opcode $9C - 5 cycles */
+static void opcode_shy_absx(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t lo = memory_read(state, cpu->pc++);
+ uint8_t hi = memory_read(state, cpu->pc++);
+ uint16_t base_addr = lo | (hi << 8);
+ uint16_t eff_addr = base_addr + cpu->x;
+
+ // CAPTURE H from the dummy read
+ memory_read(state, base_addr);
+ uint8_t H = (base_addr >> 8);
+
+ if ((base_addr & 0xFF00) != (eff_addr & 0xFF00)) {
+ eff_addr = (eff_addr & 0x00FF) | (((eff_addr >> 8) & cpu->y) << 8);
+ }
+
+ // USE H: Store Y & H
+ uint8_t value_to_store = cpu->y & H;
+ memory_write(state, eff_addr, value_to_store);
+}
+
+/* SHS (SHS Absolute,Y) - Opcode $9B - 5 cycles */
+static void opcode_shs_absy(struct nes_state *state) {
+ struct cpu_state * restrict cpu = &state->cpu;
+
+ uint8_t lo = memory_read(state, cpu->pc++); // T1
+ uint8_t hi = memory_read(state, cpu->pc++); // T2
+
+ uint16_t base_addr = lo | (hi << 8);
+
+ // Calculate the low byte of the effective address and the carry from this addition
+ uint16_t eff_low = (base_addr & 0xFF) + cpu->y;
+ uint8_t carry_from_y = (eff_low > 0xFF) ? 1 : 0; // Carry from low-byte addition
+ eff_low &= 0xFF;
+
+ // Calculate the high byte of the effective address BEFORE corruption
+ uint8_t eff_hi_uncorrupted = (base_addr >> 8) + carry_from_y;
+
+ // THE KEY STEP: Calculate the corrupted high byte
+ // 1. Do the magic AND operation on the intermediate high byte result
+ cpu->sp = cpu->a & cpu->x;
+ uint8_t eff_hi_corrupted = (eff_hi_uncorrupted + 1) & cpu->sp;
+
+ // Form the final address from the calculated low byte and corrupted high byte
+ uint16_t final_addr = eff_low | (eff_hi_corrupted << 8);
+
+ // The dummy read uses the original, un-indexed address
+ memory_read(state, base_addr); // T3: Dummy read
+
+ memory_write(state, final_addr, cpu->sp); // T4, T5: Write the value (A & X)
+}
+
+
+__attribute__((noinline))
+static void init_opcode_ud_lut(void) {
+ opcode_lut[0x80] = opcode_nop_imm;
+ opcode_lut[0x82] = opcode_nop_imm;
+ opcode_lut[0x89] = opcode_nop_imm;
+ opcode_lut[0xc2] = opcode_nop_imm;
+ opcode_lut[0xe2] = opcode_nop_imm;
+
+ opcode_lut[0x04] = opcode_nop_zp;
+ opcode_lut[0x44] = opcode_nop_zp;
+ opcode_lut[0x64] = opcode_nop_zp;
+
+ opcode_lut[0x0c] = opcode_nop_abs;
+
+ opcode_lut[0x14] = opcode_nop_zpx;
+ opcode_lut[0x34] = opcode_nop_zpx;
+ opcode_lut[0x54] = opcode_nop_zpx;
+ opcode_lut[0x74] = opcode_nop_zpx;
+ opcode_lut[0xd4] = opcode_nop_zpx;
+ opcode_lut[0xf4] = opcode_nop_zpx;
+
+ opcode_lut[0x1c] = opcode_nop_absx;
+ opcode_lut[0x3c] = opcode_nop_absx;
+ opcode_lut[0x5c] = opcode_nop_absx;
+ opcode_lut[0x7c] = opcode_nop_absx;
+ opcode_lut[0xdc] = opcode_nop_absx;
+ opcode_lut[0xfc] = opcode_nop_absx;
+
+ opcode_lut[0x1a] = opcode_nop_implied;
+ opcode_lut[0x3a] = opcode_nop_implied;
+ opcode_lut[0x5a] = opcode_nop_implied;
+ opcode_lut[0x7a] = opcode_nop_implied;
+ opcode_lut[0xda] = opcode_nop_implied;
+ opcode_lut[0xfa] = opcode_nop_implied;
+
+ opcode_lut[0xab] = opcode_lax_imm;
+ opcode_lut[0xa3] = opcode_lax_indx;
+ opcode_lut[0xaf] = opcode_lax_abs;
+ opcode_lut[0xbb] = opcode_las_absy;
+ opcode_lut[0xbf] = opcode_lax_absy;
+ opcode_lut[0xa7] = opcode_lax_zp;
+ opcode_lut[0xb7] = opcode_lax_zpy;
+ opcode_lut[0xb3] = opcode_lax_indy;
+
+ opcode_lut[0x83] = opcode_sax_indx;
+ opcode_lut[0x8f] = opcode_sax_abs;
+ opcode_lut[0x9f] = opcode_sha_absy;
+ opcode_lut[0x87] = opcode_sax_zp;
+ opcode_lut[0x97] = opcode_sax_zpy;
+ opcode_lut[0x93] = opcode_sha_indy;
+
+ opcode_lut[0xc3] = opcode_dcp_indx;
+ opcode_lut[0xc7] = opcode_dcp_zp;
+ opcode_lut[0xcf] = opcode_dcp_abs;
+ opcode_lut[0xd3] = opcode_dcp_indy;
+ opcode_lut[0xd7] = opcode_dcp_zpx;
+ opcode_lut[0xdb] = opcode_dcp_absy;
+ opcode_lut[0xdf] = opcode_dcp_absx;
+
+ opcode_lut[0xe3] = opcode_isc_indx;
+ opcode_lut[0xe7] = opcode_isc_zp;
+ opcode_lut[0xef] = opcode_isc_abs;
+ opcode_lut[0xf3] = opcode_isc_indy;
+ opcode_lut[0xf7] = opcode_isc_zpx;
+ opcode_lut[0xfb] = opcode_isc_absy;
+ opcode_lut[0xff] = opcode_isc_absx;
+
+ opcode_lut[0x03] = opcode_slo_indx;
+ opcode_lut[0x07] = opcode_slo_zp;
+ opcode_lut[0x0f] = opcode_slo_abs;
+ opcode_lut[0x13] = opcode_slo_indy;
+ opcode_lut[0x17] = opcode_slo_zpx;
+ opcode_lut[0x1b] = opcode_slo_absy;
+ opcode_lut[0x1f] = opcode_slo_absx;
+
+ opcode_lut[0x23] = opcode_rla_indx;
+ opcode_lut[0x27] = opcode_rla_zp;
+ opcode_lut[0x2f] = opcode_rla_abs;
+ opcode_lut[0x33] = opcode_rla_indy;
+ opcode_lut[0x37] = opcode_rla_zpx;
+ opcode_lut[0x3b] = opcode_rla_absy;
+ opcode_lut[0x3f] = opcode_rla_absx;
+
+ opcode_lut[0x43] = opcode_sre_indx;
+ opcode_lut[0x47] = opcode_sre_zp;
+ opcode_lut[0x4f] = opcode_sre_abs;
+ opcode_lut[0x53] = opcode_sre_indy;
+ opcode_lut[0x57] = opcode_sre_zpx;
+ opcode_lut[0x5b] = opcode_sre_absy;
+ opcode_lut[0x5f] = opcode_sre_absx;
+
+ opcode_lut[0x63] = opcode_rra_indx;
+ opcode_lut[0x67] = opcode_rra_zp;
+ opcode_lut[0x6f] = opcode_rra_abs;
+ opcode_lut[0x73] = opcode_rra_indy;
+ opcode_lut[0x77] = opcode_rra_zpx;
+ opcode_lut[0x7b] = opcode_rra_absy;
+ opcode_lut[0x7f] = opcode_rra_absx;
+
+ opcode_lut[0x4b] = opcode_alr_imm;
+ opcode_lut[0x8b] = opcode_xaa_imm;
+ opcode_lut[0xcb] = opcode_axs_imm;
+ opcode_lut[0x6b] = opcode_arr_imm;
+
+ opcode_lut[0x9b] = opcode_shs_absy;
+ opcode_lut[0x9c] = opcode_shy_absx;
+ opcode_lut[0x9e] = opcode_shx_absy;
+
+ opcode_lut[0x0b] = opcode_anc_imm;
+ opcode_lut[0x2b] = opcode_anc_imm;
+}