#include #include #include #include "../include/cpu.h" #include "cpu.h" #include "memory.h" #include "op.h" #include "decoding.h" /* * ===================================================================================== * * Filename: cpu.c * * Description: 6502 CPU emulator * * Version: 1.0 * Created: 2023-09-21 10:10:26 PM * Revision: none * Compiler: gcc * * Author: William Nolin, * Organization: * * ===================================================================================== */ void cpu_init(CPU *cpu) { cpu->program_counter = 0x8000; cpu->stack_pointer = 0xfd; cpu->accumulator = 0x00; cpu->x = 0x00; cpu->y = 0x00; cpu->status = 0x04; cpu->oam_dma_triggered = false; } void print_registers(CPU cpu, byte op, unsigned long cycle_count) { log_debug("%#02x %#02x %s \t A:%#02x X:%#02x Y:%#02x F:%#02x SP:%#02x \t [%d]", cpu.program_counter, op, get_op_code_name(op), cpu.accumulator, cpu.x, cpu.y, cpu.status, cpu.stack_pointer, cycle_count); } void oam_dma_upload(System *system) { byte page_high_addr = *system->ppu.oam_dma_register; address page_addr = ((address) page_high_addr) << 8; byte n = 0xff; byte *ram_source = &system->ram[page_addr]; byte *oam_destination = system->ppu.oam; memcpy(oam_destination, ram_source, n); log_debug("OAM DMA %#04x", page_addr); cpu_add_cycles(system, 513); // TODO } void cpu_cycle(System *system) { if (system->cpu.oam_dma_triggered) { oam_dma_upload(system); system->cpu.oam_dma_triggered = false; return; } CPU registers = system->cpu; byte op = cpu_get_next_byte(system); print_registers(registers, op, system->cycle_count); process_op_code(system, op); } void cpu_add_cycles(System *system, unsigned int cycle_count) { system->cycle_count += cycle_count; } // === Registers === bool cpu_get_flag(System *system, byte mask) { return system->cpu.status & mask; } void cpu_set_flag(System *system, byte mask, bool set) { if (set) { system->cpu.status |= mask; } else { system->cpu.status &= ~mask; } } byte cpu_get_next_byte(System *system) { byte next_byte = mem_get_byte(system, system->cpu.program_counter); system->cpu.program_counter++; return next_byte; } word cpu_get_next_word(System *system) { word next_word = mem_get_word(system, system->cpu.program_counter); system->cpu.program_counter += 2; return next_word; } void cpu_stack_push(System *system, byte value) { assert(system->cpu.stack_pointer > 0); address mem_addr = CPU_STACK_ADDR | system->cpu.stack_pointer; mem_set_byte(system, mem_addr, value); system->cpu.stack_pointer--; } byte cpu_stack_pop(System *system) { assert(system->cpu.stack_pointer < 0xff); system->cpu.stack_pointer++; address mem_addr = CPU_STACK_ADDR | system->cpu.stack_pointer; byte value = mem_get_byte(system, mem_addr); return value; } void cpu_stack_push_context(System *system) { cpu_stack_push(system, system->cpu.program_counter >> 8); cpu_stack_push(system, system->cpu.program_counter & 0xff); cpu_stack_push(system, system->cpu.status); } void cpu_stack_pop_context(System *system) { byte value = cpu_stack_pop(system); value &= 0xef; // The B mask cannot be set as it is a CPU signal value |= 0x20; // This value is always set system->cpu.status = value; byte lo = cpu_stack_pop(system); address pc = cpu_stack_pop(system) << 8; pc += lo; system->cpu.program_counter = pc; }