diff --git a/.gitignore b/.gitignore index daad2ef..88fccab 100644 --- a/.gitignore +++ b/.gitignore @@ -154,3 +154,4 @@ environment_run.ps1.env environment_run.sh.env # End of https://www.toptal.com/developers/gitignore/api/cmake,clion,conan +/test_roms/ diff --git a/cpu/cpu.c b/cpu/cpu.c index d9afa4b..c5a9d8d 100644 --- a/cpu/cpu.c +++ b/cpu/cpu.c @@ -11,7 +11,7 @@ /* * ===================================================================================== * - * Filename: cpu.c + * Filename: cpu_state.c * * Description: 6502 CPU emulator * @@ -26,133 +26,147 @@ * ===================================================================================== */ -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; - cpu->nmi_requested = false; +CPU cpu_state; + +void cpu_init() { + cpu_state.program_counter = 0x8000; + cpu_state.stack_pointer = 0xfd; + cpu_state.accumulator = 0x00; + cpu_state.x = 0x00; + cpu_state.y = 0x00; + cpu_state.status = 0x04; + cpu_state.oam_dma_triggered = false; + cpu_state.nmi_requested = 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, +void print_registers(byte op, unsigned long cycle_count) { + log_info("%#02x %#02x %s \t A:%#02x X:%#02x Y:%#02x F:%#02x SP:%#02x \t [%d]", + cpu_state.program_counter, op, get_op_code_name(op), - cpu.accumulator, - cpu.x, - cpu.y, - cpu.status, - cpu.stack_pointer, + cpu_state.accumulator, + cpu_state.x, + cpu_state.y, + cpu_state.status, + cpu_state.stack_pointer, cycle_count); } -void cpu_process_nmi(System *system) { - cpu_stack_push_context(system); +void cpu_process_nmi() { + cpu_stack_push_context(); - address handler_addr = mem_get_word(system, 0xfffa); + address handler_addr = mem_get_word(0xfffa); log_debug("NMI %#04x", handler_addr); - system->cpu.nmi_requested = false; - system->cpu.program_counter = handler_addr; + cpu_state.nmi_requested = false; + cpu_state.program_counter = handler_addr; } -void oam_dma_upload(System *system) { - byte page_high_addr = *system->ppu.oam_dma_register; +void oam_dma_upload() { + byte page_high_addr = *ppu_get_state()->oam_dma_register; // TODO address page_addr = ((address) page_high_addr) << 8; byte n = 0xff; - byte *ram_source = &system->ram[page_addr]; - byte *oam_destination = system->ppu.oam; + byte *ram_source = mem_get_ptr(page_addr); + byte *oam_destination = ppu_get_state()->oam; memcpy(oam_destination, ram_source, n); log_debug("OAM DMA %#04x", page_addr); - cpu_add_cycles(system, 513); // TODO + cpu_add_cycles(513); // TODO } -void cpu_cycle(System *system) { - if (system->cpu.nmi_requested) { - cpu_process_nmi(system); +void cpu_cycle() { + if (cpu_state.nmi_requested) { + cpu_process_nmi(); } - if (system->cpu.oam_dma_triggered) { - oam_dma_upload(system); - system->cpu.oam_dma_triggered = false; + if (cpu_state.oam_dma_triggered) { + oam_dma_upload(); + cpu_state.oam_dma_triggered = false; return; } - CPU cpu = system->cpu; - byte op = cpu_get_next_byte(system); + CPU cpu = cpu_state; + byte op = cpu_get_next_byte(); - print_registers(cpu, op, system->cycle_count); + print_registers(op, system_get_cycles()); - process_op_code(system, op); + process_op_code(op); } -void cpu_add_cycles(System *system, unsigned int cycle_count) { - system->cycle_count += cycle_count; +void cpu_add_cycles(unsigned int cycle_count) { + system_add_cycles(cycle_count); } // === Registers === -bool system_get_flag(System *system, byte mask) { - return cpu_get_flag(&system->cpu, mask); +bool cpu_get_flag(byte mask) { + return cpu_state.status & mask; } -void system_set_flag(System *system, byte mask, bool set) { +void cpu_set_flag(byte mask, bool set) { if (set) { - system->cpu.status |= mask; + cpu_state.status |= mask; } else { - system->cpu.status &= ~mask; + cpu_state.status &= ~mask; } } -byte cpu_get_next_byte(System *system) { - byte next_byte = mem_get_byte(system, system->cpu.program_counter); - system->cpu.program_counter++; +byte cpu_get_next_byte() { + byte next_byte = mem_get_byte(cpu_state.program_counter); + cpu_state.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; +word cpu_get_next_word() { + word next_word = mem_get_word(cpu_state.program_counter); + cpu_state.program_counter += 2; return next_word; } -void cpu_stack_push(System *system, byte value) { - assert(system->cpu.stack_pointer > 0); +void cpu_stack_push(byte value) { + assert(cpu_state.stack_pointer > 0); - address mem_addr = CPU_STACK_ADDR | system->cpu.stack_pointer; - mem_set_byte(system, mem_addr, value); - system->cpu.stack_pointer--; + address mem_addr = CPU_STACK_ADDR | cpu_state.stack_pointer; + mem_set_byte(mem_addr, value); + cpu_state.stack_pointer--; } -byte cpu_stack_pop(System *system) { - assert(system->cpu.stack_pointer < 0xff); +byte cpu_stack_pop() { + assert(cpu_state.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); + cpu_state.stack_pointer++; + address mem_addr = CPU_STACK_ADDR | cpu_state.stack_pointer; + byte value = mem_get_byte(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_push_context() { + cpu_stack_push(cpu_state.program_counter >> 8); + cpu_stack_push(cpu_state.program_counter & 0xff); + cpu_stack_push(cpu_state.status); } -void cpu_stack_pop_context(System *system) { - byte value = cpu_stack_pop(system); +void cpu_stack_pop_context() { + byte value = cpu_stack_pop(); 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; + cpu_state.status = value; - byte lo = cpu_stack_pop(system); - address pc = cpu_stack_pop(system) << 8; + byte lo = cpu_stack_pop(); + address pc = cpu_stack_pop() << 8; pc += lo; - system->cpu.program_counter = pc; + cpu_state.program_counter = pc; +} + +void cpu_trigger_oam_dma() { + cpu_state.oam_dma_triggered = true; +} + +void cpu_trigger_nmi() { + cpu_state.nmi_requested = true; +} + +CPU *cpu_get_state() { + return &cpu_state; } \ No newline at end of file diff --git a/cpu/cpu.h b/cpu/cpu.h index 977f6ee..d24fb97 100644 --- a/cpu/cpu.h +++ b/cpu/cpu.h @@ -19,6 +19,20 @@ #define CPU_STACK_ADDR 0x0100 +// Reference: https://www.nesdev.org/obelisk-6502-guide/registers.html +typedef struct cpu { + address program_counter; + byte stack_pointer; + byte accumulator; + byte x; + byte y; + byte status; + bool oam_dma_triggered; + bool nmi_requested; +} CPU; + +CPU *cpu_get_state(); + /** * Gets a flag from the CPU registers. * @@ -26,11 +40,7 @@ * @param mask The flag mask * @return The value of the flag. */ -bool system_get_flag(System *system, byte mask); - -static inline bool cpu_get_flag(CPU *cpu, byte mask) { - return cpu->status & mask; -} +bool cpu_get_flag(byte mask); /** * Sets a flag in the CPU registers. @@ -39,7 +49,7 @@ static inline bool cpu_get_flag(CPU *cpu, byte mask) { * @param mask The flag mask * @param set If the flag is set or not */ -void system_set_flag(System *system, byte mask, bool set); +void cpu_set_flag(byte mask, bool set); /** * Gets the next byte in the program. @@ -48,7 +58,7 @@ void system_set_flag(System *system, byte mask, bool set); * @param system The system * @return The value of the next byte. */ -byte cpu_get_next_byte(System *system); +byte cpu_get_next_byte(); /** * Gets the next word in the program. @@ -57,7 +67,7 @@ byte cpu_get_next_byte(System *system); * @param system The system * @return The value of the next word. */ -word cpu_get_next_word(System *system); +word cpu_get_next_word(); /** * Pushes a byte in to the stack. @@ -65,7 +75,7 @@ word cpu_get_next_word(System *system); * @param system The system * @param value The value to push to the stack */ -void cpu_stack_push(System *system, byte value); +void cpu_stack_push(byte value); /** * Pushes the execution context to the stack. @@ -73,7 +83,7 @@ void cpu_stack_push(System *system, byte value); * * @param system The system */ -void cpu_stack_push_context(System *system); +void cpu_stack_push_context(); /** * Pops a byte from the stack. @@ -81,7 +91,7 @@ void cpu_stack_push_context(System *system); * @param system The system * @return The value of the byte */ -byte cpu_stack_pop(System *system); +byte cpu_stack_pop(); /** * Pops an execution context from the stack and overwrite the current context. @@ -89,13 +99,16 @@ byte cpu_stack_pop(System *system); * * @param system The system */ -void cpu_stack_pop_context(System *system); +void cpu_stack_pop_context(); /** * Adds wait cycles to the CPU. * * @param cycle_count The number of cycle to wait */ -void cpu_add_cycles(System *system, unsigned int cycle_count); +void cpu_add_cycles(unsigned int cycle_count); + +void cpu_trigger_oam_dma(); +void cpu_trigger_nmi(); #endif //CPU_CPU_H diff --git a/cpu/decoding.c b/cpu/decoding.c index c69979d..0a57224 100644 --- a/cpu/decoding.c +++ b/cpu/decoding.c @@ -7,52 +7,52 @@ #include #include "log.h" -address decode_operand_addr(System *system, AddressingMode addr_mode, bool *page_crossing) { - CPU registers = system->cpu; +address decode_operand_addr(AddressingMode addr_mode, bool *page_crossing) { + CPU *registers = cpu_get_state(); address operand_addr; if (addr_mode == ADDR_MODE_ZERO_PAGE) { - operand_addr = cpu_get_next_byte(system); + operand_addr = cpu_get_next_byte(); } else if (addr_mode == ADDR_MODE_ZERO_PAGE_INDEXED_X) { - operand_addr = (cpu_get_next_byte(system) + registers.x) & 0xff; + operand_addr = (cpu_get_next_byte() + registers->x) & 0xff; } else if (addr_mode == ADDR_MODE_ZERO_PAGE_INDEXED_Y) { - operand_addr = (cpu_get_next_byte(system) + registers.y) & 0xff; + operand_addr = (cpu_get_next_byte() + registers->y) & 0xff; } else if (addr_mode == ADDR_MODE_ABSOLUTE) { - operand_addr = cpu_get_next_word(system); + operand_addr = cpu_get_next_word(); } else if (addr_mode == ADDR_MODE_ABSOLUTE_INDEXED_X) { - word addr = cpu_get_next_word(system); - word new_addr = addr + registers.x; + word addr = cpu_get_next_word(); + word new_addr = addr + registers->x; *page_crossing = (addr & 0xff00) != (new_addr & 0xff00); operand_addr = new_addr; } else if (addr_mode == ADDR_MODE_ABSOLUTE_INDEXED_Y) { - word addr = cpu_get_next_word(system); - word new_addr = addr + registers.y; + word addr = cpu_get_next_word(); + word new_addr = addr + registers->y; *page_crossing = (addr & 0xff00) != (new_addr & 0xff00); operand_addr = new_addr; } else if (addr_mode == ADDR_MODE_INDIRECT_JUMP) { - word addr = cpu_get_next_word(system); + word addr = cpu_get_next_word(); if ((addr & 0xff) == 0xff) { // Error in NES CPU for JMP op - word result = mem_get_byte(system, addr); - result += mem_get_byte(system, addr & 0xff00) << 8; + word result = mem_get_byte(addr); + result += mem_get_byte(addr & 0xff00) << 8; operand_addr = result; } else { - operand_addr = mem_get_word(system, addr); + operand_addr = mem_get_word(addr); } } else if (addr_mode == ADDR_MODE_INDIRECT_X) { - byte arg_addr = cpu_get_next_byte(system); + byte arg_addr = cpu_get_next_byte(); - word addr = mem_get_byte(system, (arg_addr + system->cpu.x) & 0xff); - addr += mem_get_byte(system, (arg_addr + system->cpu.x + 1) & 0xff) << 8; + word addr = mem_get_byte((arg_addr + registers->x) & 0xff); + addr += mem_get_byte((arg_addr + registers->x + 1) & 0xff) << 8; operand_addr = addr; } else if (addr_mode == ADDR_MODE_INDIRECT_Y) { - byte arg_addr = cpu_get_next_byte(system); - word addr = mem_get_byte(system, arg_addr) + (mem_get_byte(system, (arg_addr + 1) & 0xff) << 8); - word new_addr = addr + registers.y; + byte arg_addr = cpu_get_next_byte(); + word addr = mem_get_byte(arg_addr) + (mem_get_byte((arg_addr + 1) & 0xff) << 8); + word new_addr = addr + registers->y; *page_crossing = (addr & 0xff00) != (new_addr & 0xff00); @@ -65,7 +65,7 @@ address decode_operand_addr(System *system, AddressingMode addr_mode, bool *page return operand_addr; } -Operand decode_operand(System *system, AddressingMode addr_mode) { +Operand decode_operand(AddressingMode addr_mode) { Operand operand; if (addr_mode == ADDR_MODE_ACCUMULATOR) { @@ -74,25 +74,25 @@ Operand decode_operand(System *system, AddressingMode addr_mode) { operand.is_page_crossing = false; } else if (addr_mode == ADDR_MODE_IMMEDIATE) { operand.type = OPERAND_TYPE_IMMEDIATE; - operand.value = cpu_get_next_byte(system); + operand.value = cpu_get_next_byte(); operand.is_page_crossing = false; } else { operand.type = OPERAND_TYPE_ADDRESS; - operand.value = decode_operand_addr(system, addr_mode, &operand.is_page_crossing); + operand.value = decode_operand_addr(addr_mode, &operand.is_page_crossing); } log_trace("Operand type: %s, value: %#02x", operand_name(&operand), operand.value); return operand; } -byte read_operand(System *system, Operand operand) { +byte read_operand(Operand operand) { switch (operand.type) { case OPERAND_TYPE_ACCUMULATOR: - return system->cpu.accumulator; + return cpu_get_state()->accumulator; case OPERAND_TYPE_IMMEDIATE: return (byte) operand.value; case OPERAND_TYPE_ADDRESS: - return mem_get_byte(system, operand.value); + return mem_get_byte(operand.value); default: assert(false); } diff --git a/cpu/decoding.h b/cpu/decoding.h index 4665746..e52e13c 100644 --- a/cpu/decoding.h +++ b/cpu/decoding.h @@ -37,11 +37,11 @@ typedef struct { bool is_page_crossing; } Operand; -address decode_operand_addr(System *system, AddressingMode addr_mode, bool *page_crossing); +address decode_operand_addr(AddressingMode addr_mode, bool *page_crossing); -Operand decode_operand(System *system, AddressingMode addr_mode); +Operand decode_operand(AddressingMode addr_mode); -byte read_operand(System *system, Operand operand); +byte read_operand(Operand operand); char *get_addr_mode_name(AddressingMode addr_mode); diff --git a/cpu/memory.c b/cpu/memory.c index a4bc7f3..334fbc5 100644 --- a/cpu/memory.c +++ b/cpu/memory.c @@ -6,6 +6,7 @@ #include "log.h" #include "memory.h" #include "../include/rom.h" +#include "cpu.h" #define RAM_MAX_ADDR 0x2000 #define RAM_BANK_SIZE 0x800 @@ -14,36 +15,34 @@ #define APU_MAX_ADDR 0x4020 #define MAX_ADDR 0xffff -byte mem_get_byte(System *system, address addr) { +byte ram[RAM_SIZE]; + +byte mem_get_byte(address addr) { assert(addr <= MAX_ADDR); if (addr >= RAM_MAX_ADDR && addr < PPU_MAX_ADDR) { byte reg = (addr - RAM_MAX_ADDR) % PPU_BANK_SIZE; - ppu_read_register(&system->ppu, reg); - return system->ppu.registers[reg]; + ppu_read_register(reg); } - if (addr >= PPU_MAX_ADDR && addr < APU_MAX_ADDR) { - byte apu_addr = addr - PPU_MAX_ADDR; - return system->apu_registers[apu_addr]; - } - - return system->ram[addr]; + return ram[addr]; } -word mem_get_word(System *system, address addr) { +byte *mem_get_ptr(address addr) { + assert(addr <= MAX_ADDR); + + return &ram[addr]; +} + +word mem_get_word(address addr) { assert(addr < MAX_ADDR); - if (addr >= RAM_MAX_ADDR && addr < APU_MAX_ADDR) { - assert(false); - } - - word word = system->ram[addr]; - word += system->ram[addr + 1] << 8; // Little endian + word word = ram[addr]; + word += ram[addr + 1] << 8; // Little endian return word; } -void mem_set_byte(System *system, address addr, byte byte) { +void mem_set_byte(address addr, byte byte) { assert(addr < MAX_ADDR); log_trace("Writing '%02x' to address 0x%04x", byte, addr); @@ -54,24 +53,24 @@ void mem_set_byte(System *system, address addr, byte byte) { // The value must also be cloned in the three mirrors for (int i = 0; i < 4; i++) { address ram_addr = init_ram_addr + RAM_BANK_SIZE * i; - system->ram[ram_addr] = byte; + ram[ram_addr] = byte; } } else if (addr < PPU_MAX_ADDR) { address reg_addr = (addr - RAM_MAX_ADDR) % PPU_BANK_SIZE; int bank_count = (PPU_MAX_ADDR - RAM_MAX_ADDR) / PPU_BANK_SIZE; for (int i = 0; i < bank_count; i++) { - address ram_addr = reg_addr + PPU_BANK_SIZE * i; - system->ppu.registers[ram_addr] = byte; + address ram_addr = reg_addr + PPU_BANK_SIZE * i + RAM_MAX_ADDR; + ram[ram_addr] = byte; } - ppu_write_register(&system->ppu, reg_addr); + ppu_write_register(reg_addr); } else { - system->ram[addr] = byte; + ram[addr] = byte; if (addr == PPU_REGISTER_OAM_DMA_ADDR) { // Writing to this address triggers an upload to the PPU memory - system->cpu.oam_dma_triggered = true; + cpu_trigger_oam_dma(); } } } \ No newline at end of file diff --git a/cpu/memory.h b/cpu/memory.h index 073e6a4..6de54cf 100644 --- a/cpu/memory.h +++ b/cpu/memory.h @@ -11,28 +11,34 @@ /** * Gets a byte from a system's memory. * - * @param system A reference to the system * @param addr The address to get * @return The value of the byte at the given address. */ -byte mem_get_byte(System *system, address addr); +byte mem_get_byte(address addr); + +/** + * Gets a pointer to a byte in the memory. + * Should not be used by the CPU, because the PPU will not be triggered if reading some addresses. + * + * @param addr The address to get a pointer to + * @return A pointer to the byte in memory + */ +byte* mem_get_ptr(address addr); /** * Gets a word from a system's memory. * - * @param system A reference to the system * @param addr The address to get * @return The value of the word at the given address. */ -word mem_get_word(System *system, address addr); +word mem_get_word(address addr); /** * Sets a byte in a system's memory. * - * @param system A reference to the system * @param addr The address to set * @param value The value to set */ -void mem_set_byte(System *system, address addr, byte value); +void mem_set_byte(address addr, byte value); #endif //NESEMULATOR_MEMORY_H diff --git a/cpu/op.c b/cpu/op.c index 6290673..b71f83d 100644 --- a/cpu/op.c +++ b/cpu/op.c @@ -10,7 +10,7 @@ #define IS_OP_CODE_MODE(op, op_code, addr_mode) \ case op_code: \ - op_ ## op(system, ADDR_MODE_ ## addr_mode); \ + op_ ## op(ADDR_MODE_ ## addr_mode); \ break; #define IS_OP_CODE(op, op_code) \ @@ -60,13 +60,13 @@ IS_UNOFFICIAL_OP_CODE_(op, line, 0x1b, ABSOLUTE_INDEXED_Y) \ IS_UNOFFICIAL_OP_CODE_(op, line, 0x1f, ABSOLUTE_INDEXED_X) -void write_operand(System *system, Operand operand, byte value) { +void write_operand(Operand operand, byte value) { switch (operand.type) { case OPERAND_TYPE_ACCUMULATOR: - system->cpu.accumulator = value; + cpu_get_state()->accumulator = value; break; case OPERAND_TYPE_ADDRESS: - mem_set_byte(system, operand.value, value); + mem_set_byte(operand.value, value); break; default: assert(false); @@ -121,13 +121,13 @@ byte get_shift_cycle_count(AddressingMode addr_mode) { } } -void set_acl_flags(System *system, byte result) { - system_set_flag(system, CPU_STATUS_ZERO_MASK, result == 0); - system_set_flag(system, CPU_STATUS_NEGATIVE_MASK, result & 0x80); +void set_acl_flags(byte result) { + cpu_set_flag(CPU_STATUS_ZERO_MASK, result == 0); + cpu_set_flag(CPU_STATUS_NEGATIVE_MASK, result & 0x80); } -byte get_branch_cycle_count(System *system, bool branching, char offset) { - address target = system->cpu.program_counter; +byte get_branch_cycle_count(bool branching, char offset) { + address target = cpu_get_state()->program_counter; byte cycle_count = 2; if (branching) { @@ -142,20 +142,20 @@ byte get_branch_cycle_count(System *system, bool branching, char offset) { } __attribute__((unused)) -void op_branch(System *system, bool branching) { - char offset = (char) cpu_get_next_byte(system); +void op_branch(bool branching) { + char offset = (char) cpu_get_next_byte(); if (branching) { - address counter = system->cpu.program_counter; + address counter = cpu_get_state()->program_counter; address target = counter + offset; - system->cpu.program_counter = target; + cpu_get_state()->program_counter = target; } - cpu_add_cycles(system, get_branch_cycle_count(system, branching, offset)); + cpu_add_cycles(get_branch_cycle_count(branching, offset)); } -void add_with_carry(System *system, byte value) { - byte acc = system->cpu.accumulator; +void add_with_carry(byte value) { + byte acc = cpu_get_state()->accumulator; byte addition = acc + value; bool overflow = false; @@ -166,229 +166,229 @@ void add_with_carry(System *system, byte value) { } // Add carry flag and check for overflow again - byte result = addition + system_get_flag(system, CPU_STATUS_CARRY_MASK); + byte result = addition + cpu_get_flag(CPU_STATUS_CARRY_MASK); if (result < addition) { overflow = true; } - system->cpu.accumulator = result; + cpu_get_state()->accumulator = result; - system_set_flag(system, CPU_STATUS_CARRY_MASK, overflow); - system_set_flag(system, CPU_STATUS_OVERFLOW_MASK, is_sign_overflow(acc, value, result)); + cpu_set_flag(CPU_STATUS_CARRY_MASK, overflow); + cpu_set_flag(CPU_STATUS_OVERFLOW_MASK, is_sign_overflow(acc, value, result)); - set_acl_flags(system, result); + set_acl_flags(result); } __attribute__((unused)) -void op_ADC(System *system, AddressingMode addr_mode) { - Operand operand = decode_operand(system, addr_mode); +void op_ADC(AddressingMode addr_mode) { + Operand operand = decode_operand(addr_mode); - byte value = read_operand(system, operand); - add_with_carry(system, value); + byte value = read_operand(operand); + add_with_carry(value); - cpu_add_cycles(system, get_cycle_count(operand, addr_mode)); + cpu_add_cycles(get_cycle_count(operand, addr_mode)); } __attribute__((unused)) -void op_AHX(System *system, AddressingMode addr_mode) { +void op_AHX(AddressingMode addr_mode) { assert(false); } __attribute__((unused)) -void op_ALR(System *system, AddressingMode addr_mode) { +void op_ALR(AddressingMode addr_mode) { assert(false); } __attribute__((unused)) -void op_ANC(System *system, AddressingMode addr_mode) { +void op_ANC(AddressingMode addr_mode) { assert(false); } __attribute__((unused)) -void op_AND(System *system, AddressingMode addr_mode) { - Operand operand = decode_operand(system, addr_mode); - byte value = read_operand(system, operand); - byte acc = system->cpu.accumulator; +void op_AND(AddressingMode addr_mode) { + Operand operand = decode_operand(addr_mode); + byte value = read_operand(operand); + byte acc = cpu_get_state()->accumulator; byte result = acc & value; - system->cpu.accumulator = result; + cpu_get_state()->accumulator = result; - set_acl_flags(system, result); - cpu_add_cycles(system, get_cycle_count(operand, addr_mode)); + set_acl_flags(result); + cpu_add_cycles(get_cycle_count(operand, addr_mode)); } __attribute__((unused)) -void op_ARR(System *system, AddressingMode addr_mode) { +void op_ARR(AddressingMode addr_mode) { assert(false); } __attribute__((unused)) -void op_ASL(System *system, AddressingMode addr_mode) { - Operand operand = decode_operand(system, addr_mode); - byte value = read_operand(system, operand); +void op_ASL(AddressingMode addr_mode) { + Operand operand = decode_operand(addr_mode); + byte value = read_operand(operand); byte result = value << 1; - write_operand(system, operand, result); + write_operand(operand, result); - system_set_flag(system, CPU_STATUS_CARRY_MASK, value & 0x80); - set_acl_flags(system, result); - cpu_add_cycles(system, get_shift_cycle_count(addr_mode)); + cpu_set_flag(CPU_STATUS_CARRY_MASK, value & 0x80); + set_acl_flags(result); + cpu_add_cycles(get_shift_cycle_count(addr_mode)); } __attribute__((unused)) -void op_AXS(System *system, AddressingMode addr_mode) { +void op_AXS(AddressingMode addr_mode) { assert(false); } __attribute__((unused)) -void op_BCC(System *system, AddressingMode addr_mode) { - op_branch(system, !system_get_flag(system, CPU_STATUS_CARRY_MASK)); +void op_BCC(AddressingMode addr_mode) { + op_branch(!cpu_get_flag(CPU_STATUS_CARRY_MASK)); } __attribute__((unused)) -void op_BCS(System *system, AddressingMode addr_mode) { - op_branch(system, system_get_flag(system, CPU_STATUS_CARRY_MASK)); +void op_BCS(AddressingMode addr_mode) { + op_branch(cpu_get_flag(CPU_STATUS_CARRY_MASK)); } __attribute__((unused)) -void op_BEQ(System *system, AddressingMode addr_mode) { - op_branch(system, system_get_flag(system, CPU_STATUS_ZERO_MASK)); +void op_BEQ(AddressingMode addr_mode) { + op_branch(cpu_get_flag(CPU_STATUS_ZERO_MASK)); } __attribute__((unused)) -void op_BIT(System *system, AddressingMode addr_mode) { - Operand operand = decode_operand(system, addr_mode); - byte value = read_operand(system, operand); - byte acc = system->cpu.accumulator; +void op_BIT(AddressingMode addr_mode) { + Operand operand = decode_operand(addr_mode); + byte value = read_operand(operand); + byte acc = cpu_get_state()->accumulator; byte result = value & acc; - system_set_flag(system, CPU_STATUS_ZERO_MASK, result == 0); - system_set_flag(system, CPU_STATUS_OVERFLOW_MASK, value & 0x40); - system_set_flag(system, CPU_STATUS_NEGATIVE_MASK, value & 0x80); + cpu_set_flag(CPU_STATUS_ZERO_MASK, result == 0); + cpu_set_flag(CPU_STATUS_OVERFLOW_MASK, value & 0x40); + cpu_set_flag(CPU_STATUS_NEGATIVE_MASK, value & 0x80); } __attribute__((unused)) -void op_BMI(System *system, AddressingMode addr_mode) { - op_branch(system, system_get_flag(system, CPU_STATUS_NEGATIVE_MASK)); +void op_BMI(AddressingMode addr_mode) { + op_branch(cpu_get_flag(CPU_STATUS_NEGATIVE_MASK)); } __attribute__((unused)) -void op_BNE(System *system, AddressingMode addr_mode) { - op_branch(system, !system_get_flag(system, CPU_STATUS_ZERO_MASK)); +void op_BNE(AddressingMode addr_mode) { + op_branch(!cpu_get_flag(CPU_STATUS_ZERO_MASK)); } __attribute__((unused)) -void op_BPL(System *system, AddressingMode addr_mode) { - op_branch(system, !system_get_flag(system, CPU_STATUS_NEGATIVE_MASK)); +void op_BPL(AddressingMode addr_mode) { + op_branch(!cpu_get_flag(CPU_STATUS_NEGATIVE_MASK)); } // Stops program execution, useful for debugging __attribute__((unused)) -void op_BRK(System *system, AddressingMode addr_mode) { - cpu_stack_push_context(system); +void op_BRK(AddressingMode addr_mode) { + cpu_stack_push_context(); // TODO Load IRQ interrupt vector in PC at $FFFE/F assert(false); - system_set_flag(system, CPU_STATUS_B_MASK, true); - cpu_add_cycles(system, 7); + cpu_set_flag(CPU_STATUS_B_MASK, true); + cpu_add_cycles(7); } __attribute__((unused)) -void op_BVC(System *system, AddressingMode addr_mode) { - op_branch(system, !system_get_flag(system, CPU_STATUS_OVERFLOW_MASK)); +void op_BVC(AddressingMode addr_mode) { + op_branch(!cpu_get_flag(CPU_STATUS_OVERFLOW_MASK)); } __attribute__((unused)) -void op_BVS(System *system, AddressingMode addr_mode) { - op_branch(system, system_get_flag(system, CPU_STATUS_OVERFLOW_MASK)); +void op_BVS(AddressingMode addr_mode) { + op_branch(cpu_get_flag(CPU_STATUS_OVERFLOW_MASK)); } __attribute__((unused)) -void op_CLC(System *system, AddressingMode addr_mode) { - system_set_flag(system, CPU_STATUS_CARRY_MASK, false); - cpu_add_cycles(system, 2); +void op_CLC(AddressingMode addr_mode) { + cpu_set_flag(CPU_STATUS_CARRY_MASK, false); + cpu_add_cycles(2); } __attribute__((unused)) -void op_CLD(System *system, AddressingMode addr_mode) { - system_set_flag(system, CPU_STATUS_DECIMAL_MASK, false); - cpu_add_cycles(system, 2); +void op_CLD(AddressingMode addr_mode) { + cpu_set_flag(CPU_STATUS_DECIMAL_MASK, false); + cpu_add_cycles(2); } __attribute__((unused)) -void op_CLI(System *system, AddressingMode addr_mode) { - system_set_flag(system, CPU_STATUS_INTERRUPT_DISABLE_MASK, false); - cpu_add_cycles(system, 2); +void op_CLI(AddressingMode addr_mode) { + cpu_set_flag(CPU_STATUS_INTERRUPT_DISABLE_MASK, false); + cpu_add_cycles(2); } __attribute__((unused)) -void op_CLV(System *system, AddressingMode addr_mode) { - system_set_flag(system, CPU_STATUS_OVERFLOW_MASK, false); - cpu_add_cycles(system, 2); +void op_CLV(AddressingMode addr_mode) { + cpu_set_flag(CPU_STATUS_OVERFLOW_MASK, false); + cpu_add_cycles(2); } __attribute__((unused)) -void op_CMP(System *system, AddressingMode addr_mode) { - Operand operand = decode_operand(system, addr_mode); - byte value = read_operand(system, operand); - byte acc = system->cpu.accumulator; +void op_CMP(AddressingMode addr_mode) { + Operand operand = decode_operand(addr_mode); + byte value = read_operand(operand); + byte acc = cpu_get_state()->accumulator; byte result = acc - value; - system_set_flag(system, CPU_STATUS_CARRY_MASK, acc >= value); - system_set_flag(system, CPU_STATUS_ZERO_MASK, result == 0); - system_set_flag(system, CPU_STATUS_NEGATIVE_MASK, result & 0x80); + cpu_set_flag(CPU_STATUS_CARRY_MASK, acc >= value); + cpu_set_flag(CPU_STATUS_ZERO_MASK, result == 0); + cpu_set_flag(CPU_STATUS_NEGATIVE_MASK, result & 0x80); - cpu_add_cycles(system, get_cycle_count(operand, addr_mode)); + cpu_add_cycles(get_cycle_count(operand, addr_mode)); } __attribute__((unused)) -void op_CPX(System *system, AddressingMode addr_mode) { - Operand operand = decode_operand(system, addr_mode); - byte value = read_operand(system, operand); - byte x = system->cpu.x; +void op_CPX(AddressingMode addr_mode) { + Operand operand = decode_operand(addr_mode); + byte value = read_operand(operand); + byte x = cpu_get_state()->x; byte result = x - value; - system_set_flag(system, CPU_STATUS_CARRY_MASK, x >= value); - system_set_flag(system, CPU_STATUS_ZERO_MASK, result == 0); - system_set_flag(system, CPU_STATUS_NEGATIVE_MASK, result & 0x80); + cpu_set_flag(CPU_STATUS_CARRY_MASK, x >= value); + cpu_set_flag(CPU_STATUS_ZERO_MASK, result == 0); + cpu_set_flag(CPU_STATUS_NEGATIVE_MASK, result & 0x80); - cpu_add_cycles(system, get_cycle_count(operand, addr_mode)); + cpu_add_cycles(get_cycle_count(operand, addr_mode)); } __attribute__((unused)) -void op_CPY(System *system, AddressingMode addr_mode) { - Operand operand = decode_operand(system, addr_mode); - byte value = read_operand(system, operand); - byte y = system->cpu.y; +void op_CPY(AddressingMode addr_mode) { + Operand operand = decode_operand(addr_mode); + byte value = read_operand(operand); + byte y = cpu_get_state()->y; byte result = y - value; - system_set_flag(system, CPU_STATUS_CARRY_MASK, y >= value); - system_set_flag(system, CPU_STATUS_ZERO_MASK, result == 0); - system_set_flag(system, CPU_STATUS_NEGATIVE_MASK, result & 0x80); + cpu_set_flag(CPU_STATUS_CARRY_MASK, y >= value); + cpu_set_flag(CPU_STATUS_ZERO_MASK, result == 0); + cpu_set_flag(CPU_STATUS_NEGATIVE_MASK, result & 0x80); - cpu_add_cycles(system, get_cycle_count(operand, addr_mode)); + cpu_add_cycles(get_cycle_count(operand, addr_mode)); } __attribute__((unused)) -void op_DCP(System *system, AddressingMode addr_mode) { - Operand operand = decode_operand(system, addr_mode); - byte value = read_operand(system, operand); - byte acc = system->cpu.accumulator; +void op_DCP(AddressingMode addr_mode) { + Operand operand = decode_operand(addr_mode); + byte value = read_operand(operand); + byte acc = cpu_get_state()->accumulator; byte result = value - 1; byte cmp_result = acc - result; - system_set_flag(system, CPU_STATUS_CARRY_MASK, acc >= value); - system_set_flag(system, CPU_STATUS_ZERO_MASK, cmp_result == 0); - system_set_flag(system, CPU_STATUS_NEGATIVE_MASK, cmp_result & 0x80); + cpu_set_flag(CPU_STATUS_CARRY_MASK, acc >= value); + cpu_set_flag(CPU_STATUS_ZERO_MASK, cmp_result == 0); + cpu_set_flag(CPU_STATUS_NEGATIVE_MASK, cmp_result & 0x80); - write_operand(system, operand, result); + write_operand(operand, result); byte cycle_count; switch (addr_mode) { @@ -410,107 +410,107 @@ void op_DCP(System *system, AddressingMode addr_mode) { default: assert(false); } - cpu_add_cycles(system, cycle_count); + cpu_add_cycles(cycle_count); } __attribute__((unused)) -void op_DEC(System *system, AddressingMode addr_mode) { - Operand operand = decode_operand(system, addr_mode); - byte value = read_operand(system, operand); +void op_DEC(AddressingMode addr_mode) { + Operand operand = decode_operand(addr_mode); + byte value = read_operand(operand); byte result = value - 1; - set_acl_flags(system, result); - write_operand(system, operand, result); - cpu_add_cycles(system, get_cycle_count(operand, addr_mode)); + set_acl_flags(result); + write_operand(operand, result); + cpu_add_cycles(get_cycle_count(operand, addr_mode)); } __attribute__((unused)) -void op_DEX(System *system, AddressingMode addr_mode) { - byte x = system->cpu.x; +void op_DEX(AddressingMode addr_mode) { + byte x = cpu_get_state()->x; byte result = x - 1; - system->cpu.x = result; + cpu_get_state()->x = result; - set_acl_flags(system, result); - cpu_add_cycles(system, 2); + set_acl_flags(result); + cpu_add_cycles(2); } __attribute__((unused)) -void op_DEY(System *system, AddressingMode addr_mode) { - byte y = system->cpu.y; +void op_DEY(AddressingMode addr_mode) { + byte y = cpu_get_state()->y; byte result = y - 1; - system->cpu.y = result; + cpu_get_state()->y = result; - set_acl_flags(system, result); - cpu_add_cycles(system, 2); + set_acl_flags(result); + cpu_add_cycles(2); } __attribute__((unused)) -void op_EOR(System *system, AddressingMode addr_mode) { - Operand operand = decode_operand(system, addr_mode); - byte value = read_operand(system, operand); - byte acc = system->cpu.accumulator; +void op_EOR(AddressingMode addr_mode) { + Operand operand = decode_operand(addr_mode); + byte value = read_operand(operand); + byte acc = cpu_get_state()->accumulator; acc ^= value; - system->cpu.accumulator = acc; + cpu_get_state()->accumulator = acc; - set_acl_flags(system, acc); - cpu_add_cycles(system, get_cycle_count(operand, addr_mode)); + set_acl_flags(acc); + cpu_add_cycles(get_cycle_count(operand, addr_mode)); } __attribute__((unused)) -void op_INC(System *system, AddressingMode addr_mode) { - Operand operand = decode_operand(system, addr_mode); - byte value = read_operand(system, operand); +void op_INC(AddressingMode addr_mode) { + Operand operand = decode_operand(addr_mode); + byte value = read_operand(operand); value += 1; - write_operand(system, operand, value); + write_operand(operand, value); - set_acl_flags(system, value); - cpu_add_cycles(system, get_shift_cycle_count(addr_mode)); + set_acl_flags(value); + cpu_add_cycles(get_shift_cycle_count(addr_mode)); } __attribute__((unused)) -void op_INX(System *system, AddressingMode addr_mode) { - byte x = system->cpu.x; +void op_INX(AddressingMode addr_mode) { + byte x = cpu_get_state()->x; x += 1; - system->cpu.x = x; + cpu_get_state()->x = x; - set_acl_flags(system, x); - cpu_add_cycles(system, 2); + set_acl_flags(x); + cpu_add_cycles(2); } __attribute__((unused)) -void op_INY(System *system, AddressingMode addr_mode) { - byte y = system->cpu.y; +void op_INY(AddressingMode addr_mode) { + byte y = cpu_get_state()->y; y += 1; - system->cpu.y = y; + cpu_get_state()->y = y; - set_acl_flags(system, y); - cpu_add_cycles(system, 2); + set_acl_flags(y); + cpu_add_cycles(2); } __attribute__((unused)) -void op_ISC(System *system, AddressingMode addr_mode) { - Operand operand = decode_operand(system, addr_mode); - byte value = read_operand(system, operand); +void op_ISC(AddressingMode addr_mode) { + Operand operand = decode_operand(addr_mode); + byte value = read_operand(operand); value += 1; - write_operand(system, operand, value); - add_with_carry(system, ~value); + write_operand(operand, value); + add_with_carry(~value); - cpu_add_cycles(system, get_shift_cycle_count(addr_mode)); + cpu_add_cycles(get_shift_cycle_count(addr_mode)); } __attribute__((unused)) -void op_JMP(System *system, AddressingMode addr_mode) { - word addr = decode_operand_addr(system, addr_mode, NULL); +void op_JMP(AddressingMode addr_mode) { + word addr = decode_operand_addr(addr_mode, NULL); - system->cpu.program_counter = addr; + cpu_get_state()->program_counter = addr; // TODO WN: Handle CPU bug? // > An original 6502 has does not correctly fetch the target address if the indirect vector falls on a page boundary (e.g. $xxFF where xx is any value from $00 to $FF). @@ -522,418 +522,418 @@ void op_JMP(System *system, AddressingMode addr_mode) { cycle_count = 5; } - cpu_add_cycles(system, cycle_count); + cpu_add_cycles(cycle_count); } __attribute__((unused)) -void op_JSR(System *system, AddressingMode addr_mode) { +void op_JSR(AddressingMode addr_mode) { // Push the program counter on the stack - address program_counter = system->cpu.program_counter + 1; - cpu_stack_push(system, program_counter >> 8); - cpu_stack_push(system, program_counter & 0xff); + address program_counter = cpu_get_state()->program_counter + 1; + cpu_stack_push(program_counter >> 8); + cpu_stack_push(program_counter & 0xff); // Updates the program counter to the address in the operand - address addr = decode_operand_addr(system, addr_mode, NULL); - system->cpu.program_counter = addr; + address addr = decode_operand_addr(addr_mode, NULL); + cpu_get_state()->program_counter = addr; - cpu_add_cycles(system, 6); + cpu_add_cycles(6); } __attribute__((unused)) -void op_LAS(System *system, AddressingMode addr_mode) { +void op_LAS(AddressingMode addr_mode) { assert(false); } __attribute__((unused)) -void op_LAX(System *system, AddressingMode addr_mode) { - Operand operand = decode_operand(system, addr_mode); - byte value = read_operand(system, operand); +void op_LAX(AddressingMode addr_mode) { + Operand operand = decode_operand(addr_mode); + byte value = read_operand(operand); - system->cpu.accumulator = value; - system->cpu.x = value; + cpu_get_state()->accumulator = value; + cpu_get_state()->x = value; - set_acl_flags(system, value); - cpu_add_cycles(system, get_cycle_count(operand, addr_mode)); + set_acl_flags(value); + cpu_add_cycles(get_cycle_count(operand, addr_mode)); } __attribute__((unused)) -void op_LDA(System *system, AddressingMode addr_mode) { - Operand operand = decode_operand(system, addr_mode); - byte value = read_operand(system, operand); +void op_LDA(AddressingMode addr_mode) { + Operand operand = decode_operand(addr_mode); + byte value = read_operand(operand); - system->cpu.accumulator = value; + cpu_get_state()->accumulator = value; - set_acl_flags(system, value); - cpu_add_cycles(system, get_cycle_count(operand, addr_mode)); + set_acl_flags(value); + cpu_add_cycles(get_cycle_count(operand, addr_mode)); } __attribute__((unused)) -void op_LDX(System *system, AddressingMode addr_mode) { - Operand operand = decode_operand(system, addr_mode); - byte value = read_operand(system, operand); +void op_LDX(AddressingMode addr_mode) { + Operand operand = decode_operand(addr_mode); + byte value = read_operand(operand); - system->cpu.x = value; + cpu_get_state()->x = value; - set_acl_flags(system, value); - cpu_add_cycles(system, get_cycle_count(operand, addr_mode)); + set_acl_flags(value); + cpu_add_cycles(get_cycle_count(operand, addr_mode)); } __attribute__((unused)) -void op_LDY(System *system, AddressingMode addr_mode) { - Operand operand = decode_operand(system, addr_mode); - byte value = read_operand(system, operand); +void op_LDY(AddressingMode addr_mode) { + Operand operand = decode_operand(addr_mode); + byte value = read_operand(operand); - system->cpu.y = value; + cpu_get_state()->y = value; - set_acl_flags(system, value); - cpu_add_cycles(system, get_cycle_count(operand, addr_mode)); + set_acl_flags(value); + cpu_add_cycles(get_cycle_count(operand, addr_mode)); } __attribute__((unused)) -void op_LSR(System *system, AddressingMode addr_mode) { - Operand operand = decode_operand(system, addr_mode); - byte value = read_operand(system, operand); +void op_LSR(AddressingMode addr_mode) { + Operand operand = decode_operand(addr_mode); + byte value = read_operand(operand); // Put bit 0 in the carry flag - system_set_flag(system, CPU_STATUS_CARRY_MASK, value & 0x01); + cpu_set_flag(CPU_STATUS_CARRY_MASK, value & 0x01); value >>= 1; - write_operand(system, operand, value); + write_operand(operand, value); - set_acl_flags(system, value); - cpu_add_cycles(system, get_shift_cycle_count(addr_mode)); + set_acl_flags(value); + cpu_add_cycles(get_shift_cycle_count(addr_mode)); } __attribute__((unused)) -void op_NOP(System *system, AddressingMode addr_mode) { +void op_NOP(AddressingMode addr_mode) { if (addr_mode != ADDR_MODE_IMPLICIT) { - Operand operand = decode_operand(system, addr_mode); - cpu_add_cycles(system, get_cycle_count(operand, addr_mode)); + Operand operand = decode_operand(addr_mode); + cpu_add_cycles(get_cycle_count(operand, addr_mode)); } else { - cpu_add_cycles(system, 2); + cpu_add_cycles(2); } } __attribute__((unused)) -void op_ORA(System *system, AddressingMode addr_mode) { - Operand operand = decode_operand(system, addr_mode); - byte value = read_operand(system, operand); - byte acc = system->cpu.accumulator; +void op_ORA(AddressingMode addr_mode) { + Operand operand = decode_operand(addr_mode); + byte value = read_operand(operand); + byte acc = cpu_get_state()->accumulator; acc |= value; - system->cpu.accumulator = acc; + cpu_get_state()->accumulator = acc; - set_acl_flags(system, acc); - cpu_add_cycles(system, get_cycle_count(operand, addr_mode)); + set_acl_flags(acc); + cpu_add_cycles(get_cycle_count(operand, addr_mode)); } __attribute__((unused)) -void op_PHA(System *system, AddressingMode addr_mode) { - byte acc = system->cpu.accumulator; - cpu_stack_push(system, acc); +void op_PHA(AddressingMode addr_mode) { + byte acc = cpu_get_state()->accumulator; + cpu_stack_push(acc); - cpu_add_cycles(system, 3); + cpu_add_cycles(3); } __attribute__((unused)) -void op_PHP(System *system, AddressingMode addr_mode) { - byte status = system->cpu.status; - cpu_stack_push(system, status); +void op_PHP(AddressingMode addr_mode) { + byte status = cpu_get_state()->status; + cpu_stack_push(status); -// system_set_flag(system, CPU_STATUS_B_MASK, true); +// cpu_set_flag(CPU_STATUS_B_MASK, true); - cpu_add_cycles(system, 3); + cpu_add_cycles(3); } __attribute__((unused)) -void op_PLA(System *system, AddressingMode addr_mode) { - byte value = cpu_stack_pop(system); - system->cpu.accumulator = value; +void op_PLA(AddressingMode addr_mode) { + byte value = cpu_stack_pop(); + cpu_get_state()->accumulator = value; - set_acl_flags(system, value); + set_acl_flags(value); - cpu_add_cycles(system, 4); + cpu_add_cycles(4); } __attribute__((unused)) -void op_PLP(System *system, AddressingMode addr_mode) { - byte value = cpu_stack_pop(system); +void op_PLP(AddressingMode addr_mode) { + byte value = cpu_stack_pop(); 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; + cpu_get_state()->status = value; - cpu_add_cycles(system, 4); + cpu_add_cycles(4); } __attribute__((unused)) -void op_RLA(System *system, AddressingMode addr_mode) { - Operand operand = decode_operand(system, addr_mode); - byte value = read_operand(system, operand); - byte carry = system_get_flag(system, CPU_STATUS_CARRY_MASK); - byte acc = system->cpu.accumulator; +void op_RLA(AddressingMode addr_mode) { + Operand operand = decode_operand(addr_mode); + byte value = read_operand(operand); + byte carry = cpu_get_flag(CPU_STATUS_CARRY_MASK); + byte acc = cpu_get_state()->accumulator; - system_set_flag(system, CPU_STATUS_CARRY_MASK, value & 0x80); + cpu_set_flag(CPU_STATUS_CARRY_MASK, value & 0x80); value = (value << 1) | carry; byte and_result = acc & value; - system->cpu.accumulator = and_result; + cpu_get_state()->accumulator = and_result; - write_operand(system, operand, value); + write_operand(operand, value); - set_acl_flags(system, value); - cpu_add_cycles(system, get_shift_cycle_count(addr_mode)); + set_acl_flags(value); + cpu_add_cycles(get_shift_cycle_count(addr_mode)); } __attribute__((unused)) -void op_ROL(System *system, AddressingMode addr_mode) { - Operand operand = decode_operand(system, addr_mode); - byte value = read_operand(system, operand); - byte carry = system_get_flag(system, CPU_STATUS_CARRY_MASK); +void op_ROL(AddressingMode addr_mode) { + Operand operand = decode_operand(addr_mode); + byte value = read_operand(operand); + byte carry = cpu_get_flag(CPU_STATUS_CARRY_MASK); - system_set_flag(system, CPU_STATUS_CARRY_MASK, value & 0x80); + cpu_set_flag(CPU_STATUS_CARRY_MASK, value & 0x80); value = (value << 1) | carry; - write_operand(system, operand, value); + write_operand(operand, value); - set_acl_flags(system, value); - cpu_add_cycles(system, get_shift_cycle_count(addr_mode)); + set_acl_flags(value); + cpu_add_cycles(get_shift_cycle_count(addr_mode)); } __attribute__((unused)) -void op_ROR(System *system, AddressingMode addr_mode) { - Operand operand = decode_operand(system, addr_mode); - byte value = read_operand(system, operand); - byte carry = system_get_flag(system, CPU_STATUS_CARRY_MASK); +void op_ROR(AddressingMode addr_mode) { + Operand operand = decode_operand(addr_mode); + byte value = read_operand(operand); + byte carry = cpu_get_flag(CPU_STATUS_CARRY_MASK); - system_set_flag(system, CPU_STATUS_CARRY_MASK, value & 0x01); + cpu_set_flag(CPU_STATUS_CARRY_MASK, value & 0x01); value = (value >> 1) | (carry << 7); - write_operand(system, operand, value); + write_operand(operand, value); - set_acl_flags(system, value); - cpu_add_cycles(system, get_shift_cycle_count(addr_mode)); + set_acl_flags(value); + cpu_add_cycles(get_shift_cycle_count(addr_mode)); } __attribute__((unused)) -void op_RRA(System *system, AddressingMode addr_mode) { - Operand operand = decode_operand(system, addr_mode); - byte value = read_operand(system, operand); - byte carry = system_get_flag(system, CPU_STATUS_CARRY_MASK); +void op_RRA(AddressingMode addr_mode) { + Operand operand = decode_operand(addr_mode); + byte value = read_operand(operand); + byte carry = cpu_get_flag(CPU_STATUS_CARRY_MASK); - system_set_flag(system, CPU_STATUS_CARRY_MASK, value & 0x01); + cpu_set_flag(CPU_STATUS_CARRY_MASK, value & 0x01); value = (value >> 1) | (carry << 7); - add_with_carry(system, value); - write_operand(system, operand, value); + add_with_carry(value); + write_operand(operand, value); -// set_acl_flags(system, value); - cpu_add_cycles(system, get_shift_cycle_count(addr_mode)); +// set_acl_flags(value); + cpu_add_cycles(get_shift_cycle_count(addr_mode)); } __attribute__((unused)) -void op_RTI(System *system, AddressingMode addr_mode) { - cpu_stack_pop_context(system); - cpu_add_cycles(system, 6); +void op_RTI(AddressingMode addr_mode) { + cpu_stack_pop_context(); + cpu_add_cycles(6); } __attribute__((unused)) -void op_RTS(System *system, AddressingMode addr_mode) { - byte lo = cpu_stack_pop(system); - address pc = cpu_stack_pop(system) << 8; +void op_RTS(AddressingMode addr_mode) { + byte lo = cpu_stack_pop(); + address pc = cpu_stack_pop() << 8; pc += lo; - system->cpu.program_counter = pc + 1; - cpu_add_cycles(system, 6); + cpu_get_state()->program_counter = pc + 1; + cpu_add_cycles(6); } __attribute__((unused)) -void op_SAX(System *system, AddressingMode addr_mode) { - Operand operand = decode_operand(system, addr_mode); +void op_SAX(AddressingMode addr_mode) { + Operand operand = decode_operand(addr_mode); - byte x = system->cpu.x; - byte acc = system->cpu.accumulator; + byte x = cpu_get_state()->x; + byte acc = cpu_get_state()->accumulator; byte result = acc & x; - write_operand(system, operand, result); + write_operand(operand, result); - cpu_add_cycles(system, get_cycle_count(operand, addr_mode)); + cpu_add_cycles(get_cycle_count(operand, addr_mode)); } __attribute__((unused)) -void op_SBC(System *system, AddressingMode addr_mode) { - Operand operand = decode_operand(system, addr_mode); - byte value = read_operand(system, operand); +void op_SBC(AddressingMode addr_mode) { + Operand operand = decode_operand(addr_mode); + byte value = read_operand(operand); - add_with_carry(system, ~value); + add_with_carry(~value); - cpu_add_cycles(system, get_cycle_count(operand, addr_mode)); + cpu_add_cycles(get_cycle_count(operand, addr_mode)); } __attribute__((unused)) -void op_SEC(System *system, AddressingMode addr_mode) { - system_set_flag(system, CPU_STATUS_CARRY_MASK, true); - cpu_add_cycles(system, 2); +void op_SEC(AddressingMode addr_mode) { + cpu_set_flag(CPU_STATUS_CARRY_MASK, true); + cpu_add_cycles(2); } __attribute__((unused)) -void op_SED(System *system, AddressingMode addr_mode) { - system_set_flag(system, CPU_STATUS_DECIMAL_MASK, true); - cpu_add_cycles(system, 2); +void op_SED(AddressingMode addr_mode) { + cpu_set_flag(CPU_STATUS_DECIMAL_MASK, true); + cpu_add_cycles(2); } __attribute__((unused)) -void op_SEI(System *system, AddressingMode addr_mode) { - system_set_flag(system, CPU_STATUS_INTERRUPT_DISABLE_MASK, true); - cpu_add_cycles(system, 2); +void op_SEI(AddressingMode addr_mode) { + cpu_set_flag(CPU_STATUS_INTERRUPT_DISABLE_MASK, true); + cpu_add_cycles(2); } __attribute__((unused)) -void op_SHX(System *system, AddressingMode addr_mode) { +void op_SHX(AddressingMode addr_mode) { assert(false); } __attribute__((unused)) -void op_SHY(System *system, AddressingMode addr_mode) { +void op_SHY(AddressingMode addr_mode) { assert(false); } __attribute__((unused)) -void op_SLO(System *system, AddressingMode addr_mode) { - Operand operand = decode_operand(system, addr_mode); - byte value = read_operand(system, operand); - byte acc = system->cpu.accumulator; +void op_SLO(AddressingMode addr_mode) { + Operand operand = decode_operand(addr_mode); + byte value = read_operand(operand); + byte acc = cpu_get_state()->accumulator; byte result = value << 1; acc |= result; - system->cpu.accumulator = acc; + cpu_get_state()->accumulator = acc; - write_operand(system, operand, result); + write_operand(operand, result); - system_set_flag(system, CPU_STATUS_CARRY_MASK, value & 0x80); - set_acl_flags(system, acc); - cpu_add_cycles(system, get_shift_cycle_count(addr_mode)); + cpu_set_flag(CPU_STATUS_CARRY_MASK, value & 0x80); + set_acl_flags(acc); + cpu_add_cycles(get_shift_cycle_count(addr_mode)); } __attribute__((unused)) -void op_SRE(System *system, AddressingMode addr_mode) { - Operand operand = decode_operand(system, addr_mode); - byte value = read_operand(system, operand); - byte acc = system->cpu.accumulator; +void op_SRE(AddressingMode addr_mode) { + Operand operand = decode_operand(addr_mode); + byte value = read_operand(operand); + byte acc = cpu_get_state()->accumulator; // Put bit 0 in the carry flag - system_set_flag(system, CPU_STATUS_CARRY_MASK, value & 0x01); + cpu_set_flag(CPU_STATUS_CARRY_MASK, value & 0x01); value >>= 1; acc ^= value; - system->cpu.accumulator = acc; - write_operand(system, operand, value); + cpu_get_state()->accumulator = acc; + write_operand(operand, value); - set_acl_flags(system, acc); - cpu_add_cycles(system, get_shift_cycle_count(addr_mode)); + set_acl_flags(acc); + cpu_add_cycles(get_shift_cycle_count(addr_mode)); } __attribute__((unused)) -void op_STA(System *system, AddressingMode addr_mode) { - Operand operand = decode_operand(system, addr_mode); - byte acc = system->cpu.accumulator; +void op_STA(AddressingMode addr_mode) { + Operand operand = decode_operand(addr_mode); + byte acc = cpu_get_state()->accumulator; assert(operand.type == OPERAND_TYPE_ADDRESS); - mem_set_byte(system, operand.value, acc); + mem_set_byte(operand.value, acc); operand.is_page_crossing = true; - cpu_add_cycles(system, get_cycle_count(operand, addr_mode)); + cpu_add_cycles(get_cycle_count(operand, addr_mode)); } __attribute__((unused)) -void op_STP(System *system, AddressingMode addr_mode) { +void op_STP(AddressingMode addr_mode) { assert(false); } __attribute__((unused)) -void op_STX(System *system, AddressingMode addr_mode) { - Operand operand = decode_operand(system, addr_mode); - byte x = system->cpu.x; +void op_STX(AddressingMode addr_mode) { + Operand operand = decode_operand(addr_mode); + byte x = cpu_get_state()->x; assert(operand.type == OPERAND_TYPE_ADDRESS); - mem_set_byte(system, operand.value, x); + mem_set_byte(operand.value, x); - cpu_add_cycles(system, get_cycle_count(operand, addr_mode)); + cpu_add_cycles(get_cycle_count(operand, addr_mode)); } __attribute__((unused)) -void op_STY(System *system, AddressingMode addr_mode) { - Operand operand = decode_operand(system, addr_mode); - byte y = system->cpu.y; +void op_STY(AddressingMode addr_mode) { + Operand operand = decode_operand(addr_mode); + byte y = cpu_get_state()->y; assert(operand.type == OPERAND_TYPE_ADDRESS); - mem_set_byte(system, operand.value, y); + mem_set_byte(operand.value, y); - cpu_add_cycles(system, get_cycle_count(operand, addr_mode)); + cpu_add_cycles(get_cycle_count(operand, addr_mode)); } __attribute__((unused)) -void op_TAS(System *system, AddressingMode addr_mode) { +void op_TAS(AddressingMode addr_mode) { assert(false); } __attribute__((unused)) -void op_TAX(System *system, AddressingMode addr_mode) { - byte acc = system->cpu.accumulator; - system->cpu.x = acc; +void op_TAX(AddressingMode addr_mode) { + byte acc = cpu_get_state()->accumulator; + cpu_get_state()->x = acc; - set_acl_flags(system, acc); - cpu_add_cycles(system, 2); + set_acl_flags(acc); + cpu_add_cycles(2); } __attribute__((unused)) -void op_TAY(System *system, AddressingMode addr_mode) { - byte acc = system->cpu.accumulator; - system->cpu.y = acc; +void op_TAY(AddressingMode addr_mode) { + byte acc = cpu_get_state()->accumulator; + cpu_get_state()->y = acc; - set_acl_flags(system, acc); - cpu_add_cycles(system, 2); + set_acl_flags(acc); + cpu_add_cycles(2); } __attribute__((unused)) -void op_TSX(System *system, AddressingMode addr_mode) { - byte value = system->cpu.stack_pointer; - system->cpu.x = value; +void op_TSX(AddressingMode addr_mode) { + byte value = cpu_get_state()->stack_pointer; + cpu_get_state()->x = value; - set_acl_flags(system, value); - cpu_add_cycles(system, 2); + set_acl_flags(value); + cpu_add_cycles(2); } __attribute__((unused)) -void op_TXA(System *system, AddressingMode addr_mode) { - byte x = system->cpu.x; - system->cpu.accumulator = x; +void op_TXA(AddressingMode addr_mode) { + byte x = cpu_get_state()->x; + cpu_get_state()->accumulator = x; - set_acl_flags(system, x); - cpu_add_cycles(system, 2); + set_acl_flags(x); + cpu_add_cycles(2); } __attribute__((unused)) -void op_TXS(System *system, AddressingMode addr_mode) { - byte x = system->cpu.x; - system->cpu.stack_pointer = x; +void op_TXS(AddressingMode addr_mode) { + byte x = cpu_get_state()->x; + cpu_get_state()->stack_pointer = x; - cpu_add_cycles(system, 2); + cpu_add_cycles(2); } __attribute__((unused)) -void op_TYA(System *system, AddressingMode addr_mode) { - byte y = system->cpu.y; - system->cpu.accumulator = y; +void op_TYA(AddressingMode addr_mode) { + byte y = cpu_get_state()->y; + cpu_get_state()->accumulator = y; - set_acl_flags(system, y); - cpu_add_cycles(system, 2); + set_acl_flags(y); + cpu_add_cycles(2); } __attribute__((unused)) -void op_XAA(System *system, AddressingMode addr_mode) { +void op_XAA(AddressingMode addr_mode) { assert(false); } -void process_op_code(System *system, byte op) { +void process_op_code(byte op) { switch (op) { // CTRL IS_OP_CODE(BRK, 0x00) diff --git a/cpu/op.h b/cpu/op.h index 97af987..9b8e36e 100644 --- a/cpu/op.h +++ b/cpu/op.h @@ -17,7 +17,7 @@ enum op_code_base { OP_CODE_BASE_SBC = 0xe0 }; -void process_op_code(System *system, byte op); +void process_op_code(byte op); AddressingMode get_op_addr_mode(byte op_code); diff --git a/debugger/cpu_view.c b/debugger/cpu_view.c index d5a14cc..ad8ac31 100644 --- a/debugger/cpu_view.c +++ b/debugger/cpu_view.c @@ -7,24 +7,24 @@ #include "../cpu/cpu.h" void cv_print(CpuView *view) { - window_print(view->window, 0, 0, "PC: $%04x", view->cpu->program_counter); - window_print(view->window, 0, 1, "SP: %02x", view->cpu->stack_pointer); - window_print(view->window, 0, 2, "A: %02x", view->cpu->accumulator); - window_print(view->window, 0, 3, "X: %02x", view->cpu->x); - window_print(view->window, 0, 4, "Y: %02x", view->cpu->y); - window_print(view->window, 0, 5, "C: %01x", cpu_get_flag(view->cpu, CPU_STATUS_CARRY_MASK)); - window_print(view->window, 0, 6, "Z: %01x", cpu_get_flag(view->cpu, CPU_STATUS_ZERO_MASK)); - window_print(view->window, 0, 7, "I: %01x", cpu_get_flag(view->cpu, CPU_STATUS_INTERRUPT_DISABLE_MASK)); - window_print(view->window, 0, 8, "D: %01x", cpu_get_flag(view->cpu, CPU_STATUS_DECIMAL_MASK)); - window_print(view->window, 0, 9, "B: %01x", cpu_get_flag(view->cpu, CPU_STATUS_B_MASK)); - window_print(view->window, 0, 10, "O: %01x", cpu_get_flag(view->cpu, CPU_STATUS_OVERFLOW_MASK)); - window_print(view->window, 0, 11, "N: %01x", cpu_get_flag(view->cpu, CPU_STATUS_NEGATIVE_MASK)); + CPU *cpu_state = cpu_get_state(); + window_print(view->window, 0, 0, "PC: $%04x", cpu_state->program_counter); + window_print(view->window, 0, 1, "SP: %02x", cpu_state->stack_pointer); + window_print(view->window, 0, 2, "A: %02x", cpu_state->accumulator); + window_print(view->window, 0, 3, "X: %02x", cpu_state->x); + window_print(view->window, 0, 4, "Y: %02x", cpu_state->y); + window_print(view->window, 0, 5, "C: %01x", cpu_get_flag(CPU_STATUS_CARRY_MASK)); + window_print(view->window, 0, 6, "Z: %01x", cpu_get_flag(CPU_STATUS_ZERO_MASK)); + window_print(view->window, 0, 7, "I: %01x", cpu_get_flag(CPU_STATUS_INTERRUPT_DISABLE_MASK)); + window_print(view->window, 0, 8, "D: %01x", cpu_get_flag(CPU_STATUS_DECIMAL_MASK)); + window_print(view->window, 0, 9, "B: %01x", cpu_get_flag(CPU_STATUS_B_MASK)); + window_print(view->window, 0, 10, "O: %01x", cpu_get_flag(CPU_STATUS_OVERFLOW_MASK)); + window_print(view->window, 0, 11, "N: %01x", cpu_get_flag(CPU_STATUS_NEGATIVE_MASK)); } -CpuView *cv_init(CPU *cpu, int x, int y) { +CpuView *cv_init(int x, int y) { CpuView *view = malloc(sizeof(CpuView)); view->window = malloc(sizeof(Window)); - view->cpu = cpu; window_init(view->window, x, y, CPU_VIEW_WIDTH, CPU_VIEW_HEIGHT, "CPU VIEW"); cv_print(view); diff --git a/debugger/cpu_view.h b/debugger/cpu_view.h index 581cd94..3d98299 100644 --- a/debugger/cpu_view.h +++ b/debugger/cpu_view.h @@ -14,13 +14,12 @@ typedef struct cpu_view { Window *window; - CPU *cpu; } CpuView; /** * Initializes a CPU view for a system RAM. */ -CpuView *cv_init(CPU *cpu, int x, int y); +CpuView *cv_init(int x, int y); void cv_uninit(CpuView *cpu_view); diff --git a/debugger/debugger.c b/debugger/debugger.c index 5475b18..c644951 100644 --- a/debugger/debugger.c +++ b/debugger/debugger.c @@ -23,18 +23,18 @@ void debugger_create_window() { keypad(stdscr, true); } -LinkedList debugger_create_interactive_windows(System *system) { +LinkedList debugger_create_interactive_windows() { LinkedList interactive_windows; InteractWindow *window; interactive_windows = linked_list_init(true); window = malloc(sizeof(InteractWindow)); - mv_init(window, system->ram, 0, 0); + mv_init(window, 0, 0); linked_list_add(&interactive_windows, window); window = malloc(sizeof(InteractWindow)); - pv_init(window, system, MEMORY_VIEW_WIDTH, 0); + pv_init(window, MEMORY_VIEW_WIDTH, 0); linked_list_add(&interactive_windows, window); return interactive_windows; @@ -62,8 +62,8 @@ void start_debugger(System *system) { interactive_windows = debugger_create_interactive_windows(system); current_window = interactive_windows.current->data; - cpu_view = cv_init(&system->cpu, 0, MEMORY_VIEW_HEIGHT); - ppu_view = ppv_init(&system->ppu, CPU_VIEW_WIDTH, MEMORY_VIEW_HEIGHT); + cpu_view = cv_init(0, MEMORY_VIEW_HEIGHT); + ppu_view = ppv_init(CPU_VIEW_WIDTH, MEMORY_VIEW_HEIGHT); cursor_enable(¤t_window->cursor); diff --git a/debugger/debugger.h b/debugger/debugger.h index 6de8a78..97b3493 100644 --- a/debugger/debugger.h +++ b/debugger/debugger.h @@ -7,6 +7,6 @@ #include "../include/system.h" -void start_debugger(System *system); +void start_debugger(); #endif //NESEMULATOR_DEBUGGER_H diff --git a/debugger/memory_view.c b/debugger/memory_view.c index 48b0cb9..b811323 100644 --- a/debugger/memory_view.c +++ b/debugger/memory_view.c @@ -3,6 +3,7 @@ #include "memory_view.h" #include "dialog.h" #include "keys.h" +#include "../cpu/memory.h" // // Created by william on 6/1/24. @@ -40,10 +41,9 @@ void mv_handle_key_down(InteractWindow *window, int keycode) { } } -void mv_init(InteractWindow *interact, ram ram, int x, int y) { +void mv_init(InteractWindow *interact, int x, int y) { MemoryView *view = malloc(sizeof(MemoryView)); view->window = interact; - view->ram = ram; view->base_address = 0x0000; interact->view = view; @@ -61,7 +61,7 @@ void mv_init(InteractWindow *interact, ram ram, int x, int y) { void mv_print(MemoryView *view) { for (int line = 0; line <= MEMORY_VIEW_LINE_COUNT; line++) { address line_address = view->base_address + line * (MEMORY_VIEW_LINE_BYTE_COUNT + 1); - byte *data = &view->ram[line_address]; + byte *data = mem_get_ptr(line_address); mv_write_line(view, line, line_address, data); } diff --git a/debugger/memory_view.h b/debugger/memory_view.h index 447f5bc..8dbd740 100644 --- a/debugger/memory_view.h +++ b/debugger/memory_view.h @@ -18,7 +18,6 @@ typedef struct memory_view { InteractWindow *window; - byte *ram; address base_address; } MemoryView; @@ -27,9 +26,8 @@ typedef struct memory_view { * The viewer base address will be set to 0x0000, and the cursor (0, 0). * The content of the memory will be printed on a new curses window. * @param view A pointer to the view to initialize - * @param ram A pointer to the RAM */ -void mv_init(InteractWindow *interact, ram ram, int x, int y); +void mv_init(InteractWindow *interact, int x, int y); /** * Prints the RAM content from the viewer base address. diff --git a/debugger/ppu_view.c b/debugger/ppu_view.c index 05bd57a..9f59861 100644 --- a/debugger/ppu_view.c +++ b/debugger/ppu_view.c @@ -6,7 +6,7 @@ #include "ppu_view.h" void ppv_print_line(PpuView *view, byte reg, int line, char *fmt) { - int reg_value = view->ppu->registers[reg]; + int reg_value = ppu_get_state()->registers[reg]; window_print(view->window, 0, line, fmt); for (int i = 0; i < 0x8; i++) { @@ -33,10 +33,9 @@ void ppv_print(PpuView *view) { ppv_print_line(view, PPU_REGISTER_DATA, 7, " DATA:"); } -PpuView *ppv_init(PPU *ppu, int x, int y) { +PpuView *ppv_init(int x, int y) { PpuView *view = malloc(sizeof(PpuView)); view->window = malloc(sizeof(Window)); - view->ppu = ppu; window_init(view->window, x, y, PPU_VIEW_WIDTH, PPU_VIEW_HEIGHT, "PPU VIEW"); ppv_print(view); diff --git a/debugger/ppu_view.h b/debugger/ppu_view.h index 1d94895..6fbba2e 100644 --- a/debugger/ppu_view.h +++ b/debugger/ppu_view.h @@ -13,10 +13,9 @@ typedef struct ppu_view { Window *window; - PPU *ppu; } PpuView; -PpuView *ppv_init(PPU *ppu, int x, int y); +PpuView *ppv_init(int x, int y); void ppv_uninit(PpuView *ppu_view); diff --git a/debugger/program_view.c b/debugger/program_view.c index 3b0fe76..cddc8f6 100644 --- a/debugger/program_view.c +++ b/debugger/program_view.c @@ -19,7 +19,7 @@ void decode_operands(ProgramView *view) { exit(EXIT_FAILURE); } - byte op_code = view->ram[pc]; + byte op_code = mem_get_byte(pc); operand->addr = pc; operand->op_code = op_code; operand->addr_mode = get_op_addr_mode(op_code); @@ -36,12 +36,12 @@ void decode_operands(ProgramView *view) { case ADDR_MODE_ZERO_PAGE: case ADDR_MODE_ZERO_PAGE_INDEXED_X: case ADDR_MODE_ZERO_PAGE_INDEXED_Y: - operand->value = view->ram[pc]; + operand->value = mem_get_byte(pc); pc += 1; break; default: - operand->value = view->ram[pc]; - operand->value += view->ram[pc + 1] << 8; + operand->value = mem_get_byte(pc); + operand->value += mem_get_byte(pc + 1) << 8; pc += 2; break; } @@ -183,11 +183,10 @@ void pv_deinit(InteractWindow *window) { linked_list_uninit(&view->operands); } -void pv_init(InteractWindow *interact, System *system, int x, int y) { +void pv_init(InteractWindow *interact, int x, int y) { ProgramView *view = malloc(sizeof(ProgramView)); view->window = interact; - view->ram = system->ram; - view->pc = &system->cpu.program_counter; + view->pc = &cpu_get_state()->program_counter; view->operands = linked_list_init(false); interact->view = view; diff --git a/debugger/program_view.h b/debugger/program_view.h index 45f71e5..4646556 100644 --- a/debugger/program_view.h +++ b/debugger/program_view.h @@ -25,13 +25,12 @@ typedef struct debug_operand { typedef struct program_view { InteractWindow *window; - byte *ram; address *pc; LinkedList operands; LinkedListNode *first_operand_node; LinkedListNode *last_operand_node; } ProgramView; -void pv_init(InteractWindow *interact, System *system, int x, int y); +void pv_init(InteractWindow *interact, int x, int y); #endif //NESEMULATOR_PROGRAM_VIEW_H \ No newline at end of file diff --git a/include/cpu.h b/include/cpu.h index 9b0464d..b854620 100644 --- a/include/cpu.h +++ b/include/cpu.h @@ -1,7 +1,7 @@ /* * ===================================================================================== * - * Filename: cpu.h + * Filename: cpu_state.h * * Description: 6502 CPU emulator headers * @@ -22,8 +22,8 @@ #ifndef NESEMULATOR_CPU_H #define NESEMULATOR_CPU_H -void cpu_init(CPU *cpu); +void cpu_init(); -void cpu_cycle(System *system); +void cpu_cycle(); #endif diff --git a/include/mapper.h b/include/mapper.h index b7c4293..9717cc5 100644 --- a/include/mapper.h +++ b/include/mapper.h @@ -10,7 +10,7 @@ typedef struct mapper { address prg_rom_start_addr; - void (*post_prg_load)(ram, unsigned int); + void (*post_prg_load)(unsigned int); } Mapper; enum MapperType { diff --git a/include/ppu.h b/include/ppu.h index 655b48f..b358018 100644 --- a/include/ppu.h +++ b/include/ppu.h @@ -47,8 +47,8 @@ #define PPU_MASK_NONE 0xff typedef struct ppu { - byte* registers; - byte* oam_dma_register; + byte *registers; + byte *oam_dma_register; byte vram[PPU_VRAM_SIZE]; byte oam[PPU_OAM_SIZE]; bool odd_frame; @@ -56,15 +56,19 @@ typedef struct ppu { address t; byte x; bool w; + + void (*trigger_nmi)(); } PPU; +PPU *ppu_get_state(); + /** * Initializes the PPU, according to the power up state. * https://www.nesdev.org/wiki/PPU_power_up_state * * @param ppu */ -void ppu_init(PPU *ppu, byte *registers_ram, byte *oam_dma_register); +void ppu_init(byte *registers_ram, byte *oam_dma_register); /** * Cycles the PPU. @@ -72,7 +76,7 @@ void ppu_init(PPU *ppu, byte *registers_ram, byte *oam_dma_register); * @param ppu * @param ram */ -void ppu_cycle(PPU *ppu); +void ppu_cycle(); /** * Read a flag from the PPU registers. @@ -80,7 +84,7 @@ void ppu_cycle(PPU *ppu); * @param reg The register index * @param mask The flag mask */ -bool ppu_read_flag(PPU *ppu, size_t reg, byte mask); +bool ppu_read_flag(size_t reg, byte mask); /** * Read a value from the PPU registers. Does not apply any offset to the value, a mask of 0x20 will either result in 0x20 (true) or 0x0 (false). @@ -89,8 +93,8 @@ bool ppu_read_flag(PPU *ppu, size_t reg, byte mask); * @param reg The register index * @param mask The value mask */ -void ppu_read_register(PPU *ppu, byte reg); +void ppu_read_register(byte reg); -void ppu_write_register(PPU *ppu, byte reg); +void ppu_write_register(byte reg); #endif //NESEMULATOR_PPU_H diff --git a/include/rom.h b/include/rom.h index fb85395..d2018b3 100644 --- a/include/rom.h +++ b/include/rom.h @@ -24,9 +24,8 @@ typedef struct { * Loads a ROM from a specified file path. * * @param path The file path - * @param rom ROM * @return A boolean indicating a success (true) or an error. */ -bool rom_load(char *path, System *system); +bool rom_load(char *path); #endif //NESEMULATOR_ROM_H \ No newline at end of file diff --git a/include/system.h b/include/system.h index 2a69e0c..65166e4 100644 --- a/include/system.h +++ b/include/system.h @@ -19,49 +19,33 @@ #define PPU_REGISTER_OAM_DMA_ADDR 0x4014 #define APU_REGISTERS_COUNT 24 -// Reference: https://www.nesdev.org/obelisk-6502-guide/registers.html -typedef struct cpu { - address program_counter; - byte stack_pointer; - byte accumulator; - byte x; - byte y; - byte status; - bool oam_dma_triggered; - bool nmi_requested; -} CPU; - typedef struct system { void *rom_header; - CPU cpu; - PPU ppu; Mapper mapper; - ram ram; byte apu_registers[APU_REGISTERS_COUNT]; unsigned long cycle_count; } System; /** * Initialize all components of a system. - * - * @param system The system to initialize */ -void system_init(System *system); +void system_init(); -void system_start(System *system); +void system_start(); /** * Starts the main loop of a system. - * - * @param system The system */ -void system_loop(System *system); +void system_loop(); /** * De-initialize the components of a system. - * - * @param system The system to de-initialize */ -void system_uninit(System *system); +void system_uninit(); + +unsigned int system_get_cycles(); +void system_add_cycles(unsigned int cycles); + +Mapper *system_get_mapper(); #endif //NESEMULATOR_SYSTEM_H diff --git a/include/types.h b/include/types.h index 0c31ed3..81cb718 100644 --- a/include/types.h +++ b/include/types.h @@ -12,7 +12,7 @@ typedef unsigned char byte; typedef unsigned short address; typedef unsigned short word; -typedef byte ram[RAM_SIZE]; +//typedef byte ram[RAM_SIZE]; typedef byte vram[VRAM_SIZE]; #endif //NESEMULATOR_TYPES_H diff --git a/main.c b/main.c index b7aa128..0ef58b7 100644 --- a/main.c +++ b/main.c @@ -23,22 +23,20 @@ #include "include/system.h" int main() { - System system; - log_set_level(LOG_INFO); - system_init(&system); + system_init(); char *rom_path = "../test_roms/smb.nes"; - if (!rom_load(rom_path, &system)) { - system_uninit(&system); + if (!rom_load(rom_path)) { + system_uninit(); return EXIT_FAILURE; } - system_start(&system); -// start_debugger(&system); - system_loop(&system); + system_start(); +// start_debugger(); + system_loop(); - system_uninit(&system); + system_uninit(); return EXIT_SUCCESS; } \ No newline at end of file diff --git a/mappers/simple_mapper.c b/mappers/simple_mapper.c index cee62e6..769061d 100644 --- a/mappers/simple_mapper.c +++ b/mappers/simple_mapper.c @@ -1,19 +1,20 @@ #include "../include/mapper.h" #include "../include/rom.h" +#include "../cpu/memory.h" #include #define SIMPLE_MAPPER_PRG_START_ADDR 0x8000 #define PRG_PART_SIZE 0x4000 // 16Kb -void post_prg_load(ram ram, unsigned int prg_size) { +void post_prg_load(unsigned int prg_size) { if (prg_size == 2) { // The whole space is occupied, nothing to do return; } // We need to mirror the data in the upper ram - byte *source = (byte *) &ram[SIMPLE_MAPPER_PRG_START_ADDR]; - byte *destination = (byte *) &ram[SIMPLE_MAPPER_PRG_START_ADDR + PRG_PART_SIZE]; + byte *source = mem_get_ptr(SIMPLE_MAPPER_PRG_START_ADDR); + byte *destination = mem_get_ptr(SIMPLE_MAPPER_PRG_START_ADDR + PRG_PART_SIZE); memcpy(destination, source, PRG_PART_SIZE); } diff --git a/ppu/ppu.c b/ppu/ppu.c index cda8b1e..3dbec42 100644 --- a/ppu/ppu.c +++ b/ppu/ppu.c @@ -14,31 +14,56 @@ // 10. This is where I'm stuck. I think I need to read the "sprites" section of https://wiki.nesdev.com/w/index.php/PPU_rendering very carefully. // -#include #include "../include/ppu.h" -void ppu_init(PPU *ppu, byte *registers_ram, byte *oam_dma_register) { - ppu->registers = registers_ram; - ppu->registers[PPU_REGISTER_CTRL] = 0x00; - ppu->registers[PPU_REGISTER_MASK] = 0x00; - ppu->registers[PPU_REGISTER_STATUS] = 0x00; - ppu->registers[PPU_REGISTER_OAM_ADDR] = 0x00; - ppu->registers[PPU_REGISTER_OAM_DATA] = 0x00; - ppu->registers[PPU_REGISTER_SCROLL] = 0x00; - ppu->registers[PPU_REGISTER_ADDR] = 0x00; - ppu->registers[PPU_REGISTER_DATA] = 0x00; - ppu->oam_dma_register = oam_dma_register; - ppu->odd_frame = false; +PPU ppu_state; + +void ppu_init(byte *registers_ram, byte *oam_dma_register) { + ppu_state.registers = registers_ram; + ppu_state.registers[PPU_REGISTER_CTRL] = 0x00; + ppu_state.registers[PPU_REGISTER_MASK] = 0x00; + ppu_state.registers[PPU_REGISTER_STATUS] = 0x00; + ppu_state.registers[PPU_REGISTER_OAM_ADDR] = 0x00; + ppu_state.registers[PPU_REGISTER_OAM_DATA] = 0x00; + ppu_state.registers[PPU_REGISTER_SCROLL] = 0x00; + ppu_state.registers[PPU_REGISTER_ADDR] = 0x00; + ppu_state.registers[PPU_REGISTER_DATA] = 0x00; + ppu_state.oam_dma_register = oam_dma_register; + ppu_state.odd_frame = false; +} + +PPU *ppu_get_state() { + return &ppu_state; +} + +void ppu_status_set(byte mask, bool enabled) { + if (enabled) { + ppu_state.registers[PPU_REGISTER_STATUS] |= mask; + } else { + ppu_state.registers[PPU_REGISTER_STATUS] &= ~mask; + } } long frame = 0; int x, y = 0; -void ppu_cycle(PPU *ppu) { +void ppu_cycle() { + if (x == 1) { + if (y == 241) { + // VBlank start + ppu_status_set(PPU_STATUS_VBLANK, true); + } + + if (y == 261) { + // VBlank clear + ppu_status_set(PPU_STATUS_VBLANK, false); + } + } + int frame_width = 341; int frame_height = 262; - bool rendering_enabled = ppu_read_flag(ppu, PPU_REGISTER_MASK, PPU_MASK_SHOW_BG | PPU_MASK_SHOW_SP); - if (rendering_enabled && ppu->odd_frame) { + bool rendering_enabled = ppu_read_flag(PPU_REGISTER_MASK, PPU_MASK_SHOW_BG | PPU_MASK_SHOW_SP); + if (rendering_enabled && ppu_state.odd_frame) { // With rendering enabled, the odd frames are shorter // TODO: and doing the last cycle of the last dummy nametable fetch there instead frame_width = 339; @@ -54,30 +79,30 @@ void ppu_cycle(PPU *ppu) { if (y >= frame_height) { y = 0; frame++; - ppu->odd_frame = !ppu->odd_frame; + ppu_state.odd_frame = !ppu_state.odd_frame; } } -bool ppu_read_flag(PPU *ppu, size_t reg, byte mask) { - return ppu->registers[reg] & mask; +bool ppu_read_flag(size_t reg, byte mask) { + return ppu_state.registers[reg] & mask; } -//byte ppu_read_register(PPU *ppu, size_t reg, byte mask) { -// return ppu->registers[reg] & mask; +//byte ppu_read_register(size_t reg, byte mask) { +// return ppu_state.registers[reg] & mask; //} -void ppu_read_register(PPU *ppu, byte reg) { +void ppu_read_register(byte reg) { if (reg == PPU_REGISTER_STATUS) { - ppu->w = false; + ppu_state.w = false; } } -void ppu_write_register(PPU *ppu, byte reg) { +void ppu_write_register(byte reg) { if (reg == PPU_REGISTER_SCROLL || reg == PPU_REGISTER_ADDR) { - ppu->w = !ppu->w; + ppu_state.w = !ppu_state.w; } if (reg == PPU_REGISTER_OAM_DATA) { - ppu->registers[PPU_REGISTER_OAM_ADDR]++; + ppu_state.registers[PPU_REGISTER_OAM_ADDR]++; } } \ No newline at end of file diff --git a/rom/ines.c b/rom/ines.c index 9651458..e3f8732 100644 --- a/rom/ines.c +++ b/rom/ines.c @@ -7,6 +7,7 @@ #include "log.h" #include "../include/rom.h" #include "../include/system.h" +#include "../cpu/memory.h" // Flag 6 #define NES_HEADER_FLAG_MIRRORING 0x01 @@ -126,21 +127,22 @@ bool rom_ines_read_trainer(FILE *file, INesHeader *header) { return false; } -bool rom_ines_read_prg_rom(FILE *file, INesHeader *header, System *system) { +bool rom_ines_read_prg_rom(FILE *file, INesHeader *header) { unsigned int prg_rom_size = header->prg_rom_size * 16384; log_debug("Reading %d bytes PRG ROM", prg_rom_size); - if (fread(&system->ram[system->mapper.prg_rom_start_addr], sizeof(byte), prg_rom_size, file) < prg_rom_size) { + byte *prg_rom_location = mem_get_ptr(system_get_mapper()->prg_rom_start_addr); + if (fread(prg_rom_location, sizeof(byte), prg_rom_size, file) < prg_rom_size) { log_error("Failed to read PRG ROM"); return false; } - system->mapper.post_prg_load(&system->ram[0], header->prg_rom_size); + system_get_mapper()->post_prg_load(header->prg_rom_size); return true; } -bool rom_ines_read_chr_rom(FILE *file, INesHeader *header, System *system) { +bool rom_ines_read_chr_rom(FILE *file, INesHeader *header) { if (header->chr_rom_size <= 0) { log_debug("No CHR ROM to read"); return true; @@ -149,7 +151,8 @@ bool rom_ines_read_chr_rom(FILE *file, INesHeader *header, System *system) { unsigned int chr_rom_size = header->chr_rom_size * 8192; log_debug("Reading %d bytes CHR ROM", chr_rom_size); - if (fread(system->ppu.vram, sizeof(byte), chr_rom_size, file) < chr_rom_size) { + byte *chr_rom_location = ppu_get_state()->vram; + if (fread(chr_rom_location, sizeof(byte), chr_rom_size, file) < chr_rom_size) { log_error("Failed to read CHR ROM"); return false; } @@ -157,11 +160,11 @@ bool rom_ines_read_chr_rom(FILE *file, INesHeader *header, System *system) { return true; } -bool rom_ines_read(const char header_buf[ROM_HEADER_SIZE], FILE *file, System *system) { +bool rom_ines_read(const char header_buf[ROM_HEADER_SIZE], FILE *file) { INesHeader header = read_header(header_buf); - system->rom_header = &header; +// system->rom_header = &header; return rom_ines_read_trainer(file, &header) && - rom_ines_read_prg_rom(file, &header, system) && - rom_ines_read_chr_rom(file, &header, system); + rom_ines_read_prg_rom(file, &header) && + rom_ines_read_chr_rom(file, &header); } \ No newline at end of file diff --git a/rom/rom.c b/rom/rom.c index 291f270..3d1b528 100644 --- a/rom/rom.c +++ b/rom/rom.c @@ -8,7 +8,7 @@ #include "ines.c" #include "../include/system.h" -bool rom_load(char *path, System *system) { +bool rom_load(char *path) { FILE *file = fopen(path, "r"); if (!file) { log_error("Failed to open ROM"); @@ -28,7 +28,7 @@ bool rom_load(char *path, System *system) { } log_info("Reading iNes 1.0 ROM at %s", path); - rom_ines_read(header_buffer, file, system); + rom_ines_read(header_buffer, file); if (fclose(file) != 0) { log_error("Failed to close ROM file"); diff --git a/system.c b/system.c index 7a493fe..08ba5e1 100644 --- a/system.c +++ b/system.c @@ -7,25 +7,27 @@ #include "memory.h" #include #include -#include "log.h" +#include "cpu.h" -void system_init(System *system) { - byte *registers_base_addr = &system->ram[PPU_REGISTERS_BASE_ADDR]; - byte *oam_dma_register = &system->ram[PPU_REGISTER_OAM_DMA_ADDR]; +System current_sys; - cpu_init(&system->cpu); - ppu_init(&system->ppu, registers_base_addr, oam_dma_register); +void system_init() { + byte *registers_base_addr = mem_get_ptr(PPU_REGISTERS_BASE_ADDR); + byte *oam_dma_register = mem_get_ptr(PPU_REGISTER_OAM_DMA_ADDR); - system->mapper = get_mapper(MAPPER_TYPE_SIMPLE); - system->cycle_count = 7; + cpu_init(); + ppu_init(registers_base_addr, oam_dma_register); + + current_sys.mapper = get_mapper(MAPPER_TYPE_SIMPLE); + current_sys.cycle_count = 7; } -void system_start(System *system) { - address pc = mem_get_word(system, 0xfffc); - system->cpu.program_counter = pc; +void system_start() { + address pc = mem_get_word(0xfffc); + cpu_get_state()->program_counter = pc; } -void system_loop(System *system) { +void system_loop() { assert(CPU_CLOCK_DIVISOR > PPU_CLOCK_DIVISOR); unsigned int master_cycle_per_frame = MASTER_CLOCK / FRAME_RATE; @@ -37,14 +39,14 @@ void system_loop(System *system) { while (true) { // log_info("Frame %d", frame); - while (system->cycle_count < cpu_cycle_per_frame * frame) { - if (cpu_cycle_count == system->cycle_count) { - cpu_cycle(system); + while (current_sys.cycle_count < cpu_cycle_per_frame * frame) { + if (cpu_cycle_count == current_sys.cycle_count) { + cpu_cycle(); } cpu_cycle_count++; for (int ppu_c = 0; ppu_c < ppu_cycle_per_cpu_cycle; ppu_c++) { - ppu_cycle(&system->ppu); + ppu_cycle(); } } @@ -53,5 +55,17 @@ void system_loop(System *system) { } } -void system_uninit(System *system) { +void system_uninit() { +} + +unsigned int system_get_cycles() { + return current_sys.cycle_count; +} + +void system_add_cycles(unsigned int cycles) { + current_sys.cycle_count += cycles; +} + +Mapper *system_get_mapper() { + return ¤t_sys.mapper; } \ No newline at end of file