#include #include "cpu.h" #include "opcodes.h" extern void reset6502(void); extern void step6502(void); uint8_t cpu_memory[65536] = { [0xfffc] = 0x0, [0xfffd] = 0x0, }; uint8_t read6502(uint16_t address) { return cpu_memory[address]; } void write6502(uint16_t address, uint8_t value) { cpu_memory[address] = value; } extern uint16_t pc; extern uint8_t sp, a, x, y, status; cpu_history_t cpu_history[65536] = { 0 }; int cpu_history_len; int cpu_history_ix; void cpu_get_state(cpu_state_t * state) { *state = (cpu_state_t){ .a = a, .y = y, .x = x, .pc = pc, .sp = sp, .status = status, }; } static inline void update_history(void) { instruction_t instruction = decode_ins[cpu_memory[pc]]; addressing_mode_t addressing_mode = addressing_modes[instruction.mode]; if (cpu_history_len < 65536) cpu_history_len++; cpu_history[cpu_history_ix] = (cpu_history_t){ .state = (cpu_state_t){ .a = a, .y = y, .x = x, .pc = pc, .sp = sp, .status = status, }, .pc_mem = { cpu_memory[pc], cpu_memory[pc+1], cpu_memory[pc+2] }, .value = (addressing_mode.func)(pc), }; cpu_history_ix = (cpu_history_ix + 1) & 0xffff; } void cpu_reset(void) { reset6502(); cpu_history_len = 0; cpu_history_ix = 0; } void cpu_step(void) { update_history(); step6502(); } static uint8_t * mem = cpu_memory; uint16_t absolute(uint16_t _pc) { uint16_t effective = ((uint16_t)mem[_pc + 2] << 8) | ((uint16_t)mem[_pc + 1] << 0); return effective; } uint16_t absolute_indexed_indirect(uint16_t _pc) { uint16_t effective = (((uint16_t)mem[_pc + 2] << 8) | ((uint16_t)mem[_pc + 1] << 0)) + x; uint16_t indirect = ((uint16_t)mem[effective + 1] << 8) | ((uint16_t)mem[effective + 0] << 0); return indirect; } uint16_t absolute_indexed_with_x(uint16_t _pc) { uint16_t effective = (((uint16_t)mem[_pc + 2] << 8) | ((uint16_t)mem[_pc + 1] << 0)) + x; return effective; } uint16_t absolute_indexed_with_y(uint16_t _pc) { uint16_t effective = (((uint16_t)mem[_pc + 2] << 8) | ((uint16_t)mem[_pc + 1] << 0)) + y; return effective; } uint16_t absolute_indirect(uint16_t _pc) { uint16_t effective = (((uint16_t)mem[_pc + 2] << 8) | ((uint16_t)mem[_pc + 1] << 0)) + y; uint16_t indirect = ((uint16_t)mem[effective + 1] << 8) | ((uint16_t)mem[effective + 0] << 0); return indirect; } uint16_t accumulator(uint16_t _pc) { return a; } uint16_t immediate(uint16_t _pc) { return (uint8_t)mem[_pc + 1]; } uint16_t implied(uint16_t _pc) { return 0; // ??? } uint16_t program_counter_relative(uint16_t _pc) { uint16_t effective = _pc + 2 + ((int8_t)mem[_pc + 1]); return effective; } uint16_t stack(uint16_t _pc) { uint16_t effective = (0x01 << 8) | (sp << 0); return effective; } uint16_t zero_page(uint16_t _pc) { uint16_t effective = (0x00 << 8) | ((uint16_t)mem[_pc + 1] << 0); return effective; } uint16_t zero_page_indexed_indirect(uint16_t _pc) { uint8_t base = x + ((uint8_t)mem[_pc + 1] << 0); uint16_t effective = (0x00 << 8) | base; uint16_t indirect = ((uint16_t)mem[effective + 1] << 8) | ((uint16_t)mem[effective + 0] << 0); return indirect; } uint16_t zero_page_indexed_with_x(uint16_t _pc) { uint8_t base = x + ((uint8_t)mem[_pc + 1] << 0); uint16_t effective = (0x00 << 8) | base; return effective; } uint16_t zero_page_indexed_with_y(uint16_t _pc) { uint8_t base = y + ((uint8_t)mem[_pc + 1] << 0); uint16_t effective = (0x00 << 8) | base; return effective; } uint16_t zero_page_indirect(uint16_t _pc) { uint8_t base = ((uint8_t)mem[_pc + 1] << 0); uint16_t effective = (0x00 << 8) | base; uint16_t indirect = ((uint16_t)mem[effective + 1] << 8) | ((uint16_t)mem[effective + 0] << 0); return indirect; } uint16_t zero_page_indirect_indexed_with_y(uint16_t _pc) { uint8_t base = ((uint8_t)mem[_pc + 1] << 0); uint16_t indirect = ((uint16_t)mem[base + 1] << 8) | ((uint16_t)mem[base + 0] << 0); uint16_t effective = indirect + y; return effective; } addressing_mode_t addressing_modes[16] = { [A] = { .alen = 2, .olen = 2, .func = absolute }, [AII] = { .alen = 2, .olen = 2, .func = absolute_indexed_indirect }, [AIX] = { .alen = 2, .olen = 2, .func = absolute_indexed_with_x }, [AIY] = { .alen = 2, .olen = 2, .func = absolute_indexed_with_y }, [AI] = { .alen = 2, .olen = 2, .func = absolute_indirect }, [ACC] = { .alen = 0, .olen = 1, .func = accumulator }, [IMM] = { .alen = 1, .olen = 1, .func = immediate }, [I] = { .alen = 0, .olen = 0, .func = implied }, [R] = { .alen = 1, .olen = 2, .func = program_counter_relative }, [S] = { .alen = 0, .olen = 2, .func = stack }, [ZP] = { .alen = 1, .olen = 2, .func = zero_page }, [ZPII] = { .alen = 1, .olen = 2, .func = zero_page_indexed_indirect }, [ZPX] = { .alen = 1, .olen = 2, .func = zero_page_indexed_with_x }, [ZPY] = { .alen = 1, .olen = 2, .func = zero_page_indexed_with_y }, [ZPI] = { .alen = 1, .olen = 2, .func = zero_page_indirect }, [ZPIY] = { .alen = 1, .olen = 2, .func = zero_page_indirect_indexed_with_y }, };