diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 70af33d..a8ca30f 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -25,11 +25,16 @@ - + + + + + + + + - - @@ -456,7 +461,7 @@ - + - @@ -517,7 +530,8 @@ - diff --git a/cpu/CMakeLists.txt b/cpu/CMakeLists.txt index 80e79ab..8ecf7e6 100644 --- a/cpu/CMakeLists.txt +++ b/cpu/CMakeLists.txt @@ -2,7 +2,9 @@ add_library(CPU cpu.c op.c memory.c - cpu.h) + cpu.h + decoding.c + decoding.h) find_package(log.c) target_link_libraries(CPU log.c::log.c) \ No newline at end of file diff --git a/cpu/cpu.c b/cpu/cpu.c index 62c0997..c8ee001 100644 --- a/cpu/cpu.c +++ b/cpu/cpu.c @@ -5,6 +5,7 @@ #include "cpu.h" #include "memory.h" #include "op.h" +#include "decoding.h" /* * ===================================================================================== @@ -138,15 +139,4 @@ void cpu_stack_pop_context(System *system) { address pc = cpu_stack_pop(system) << 8; pc += lo; system->cpu.program_counter = pc; -} - -char *operand_name(Operand *operand) { - switch (operand->type) { - case OPERAND_TYPE_ACCUMULATOR: - return "Accumulator"; - case OPERAND_TYPE_IMMEDIATE: - return "Immediate"; - case OPERAND_TYPE_ADDRESS: - return "Address"; - } } \ No newline at end of file diff --git a/cpu/cpu.h b/cpu/cpu.h index 8301bae..c68ddf9 100644 --- a/cpu/cpu.h +++ b/cpu/cpu.h @@ -19,25 +19,13 @@ #define CPU_STACK_ADDR 0x0100 -enum OperandType { - OPERAND_TYPE_ACCUMULATOR, - OPERAND_TYPE_IMMEDIATE, - OPERAND_TYPE_ADDRESS -}; - -typedef struct { - word value; - enum OperandType type; - bool is_page_crossing; -} Operand; - /** * Gets the name of the type of an operand, for logging. * * @param operand The operand * @return The name of the operand's type. */ -char *operand_name(Operand *operand); +//char *operand_name(Operand *operand); /** * Gets a flag from the CPU registers. diff --git a/cpu/decoding.c b/cpu/decoding.c new file mode 100644 index 0000000..1449265 --- /dev/null +++ b/cpu/decoding.c @@ -0,0 +1,482 @@ +// +// Created by william on 1/9/24. +// + +#include "decoding.h" + +#include +#include + +address decode_operand_addr(System *system, AddressingMode addr_mode, bool *page_crossing) { + CPU registers = system->cpu; + address operand_addr; + + if (addr_mode == ADDR_MODE_ZERO_PAGE) { + operand_addr = cpu_get_next_byte(system); + } else if (addr_mode == ADDR_MODE_ZERO_PAGE_INDEXED_X) { + operand_addr = (cpu_get_next_byte(system) + registers.x) & 0xff; + } else if (addr_mode == ADDR_MODE_ZERO_PAGE_INDEXED_Y) { + operand_addr = (cpu_get_next_byte(system) + registers.y) & 0xff; + } else if (addr_mode == ADDR_MODE_ABSOLUTE) { + operand_addr = cpu_get_next_word(system); + } else if (addr_mode == ADDR_MODE_ABSOLUTE_INDEXED_X) { + word addr = cpu_get_next_word(system); + 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; + + *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); + 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; + operand_addr = result; + } else { + operand_addr = mem_get_word(system, addr); + } + } else if (addr_mode == ADDR_MODE_INDIRECT_X) { + byte arg_addr = cpu_get_next_byte(system); + + 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; + 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; + + *page_crossing = (addr & 0xff00) != (new_addr & 0xff00); + + operand_addr = new_addr; + } else { + assert(false); + } + + log_trace("Operand address: %#02x, Addressing mode: %s", operand_addr, get_addr_mode_name(addr_mode)); + return operand_addr; +} + +Operand decode_operand(System *system, AddressingMode addr_mode) { + Operand operand; + + if (addr_mode == ADDR_MODE_ACCUMULATOR) { + operand.type = OPERAND_TYPE_ACCUMULATOR; + operand.value = 0; + 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.is_page_crossing = false; + } else { + operand.type = OPERAND_TYPE_ADDRESS; + operand.value = decode_operand_addr(system, 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) { + switch (operand.type) { + case OPERAND_TYPE_ACCUMULATOR: + return system->cpu.accumulator; + case OPERAND_TYPE_IMMEDIATE: + return (byte) operand.value; + case OPERAND_TYPE_ADDRESS: + return mem_get_byte(system, operand.value); + default: + assert(false); + } +} + +char *get_addr_mode_name(AddressingMode addr_mode) { + switch (addr_mode) { + case ADDR_MODE_ABSOLUTE: + return "a"; + case ADDR_MODE_ABSOLUTE_INDEXED_X: + return "a,x"; + case ADDR_MODE_ABSOLUTE_INDEXED_Y: + return "a,y"; + case ADDR_MODE_ACCUMULATOR: + return "A"; + case ADDR_MODE_IMMEDIATE: + return "#"; + case ADDR_MODE_IMPLICIT: + return " "; + case ADDR_MODE_INDIRECT_X: + return "(d,x)"; + case ADDR_MODE_INDIRECT_Y: + return "(d,y)"; + case ADDR_MODE_INDIRECT_JUMP: + return "(a)"; + case ADDR_MODE_RELATIVE: + return "label"; + case ADDR_MODE_ZERO_PAGE: + return "d"; + case ADDR_MODE_ZERO_PAGE_INDEXED_X: + return "d,x"; + case ADDR_MODE_ZERO_PAGE_INDEXED_Y: + return "d,y"; + } +} + +char *operand_name(Operand *operand) { + switch (operand->type) { + case OPERAND_TYPE_ACCUMULATOR: + return "Accumulator"; + case OPERAND_TYPE_IMMEDIATE: + return "Immediate"; + case OPERAND_TYPE_ADDRESS: + return "Address"; + } +} + +char *get_op_code_name(byte op) { + switch (op) { + case 0x00: + return "BRK"; + case 0x08: + return "PHP"; + case 0x0b: + case 0x2b: + return "ANC"; + case 0x10: + return "BPL"; + case 0x18: + return "CLC"; + case 0x20: + return "JSR"; + case 0x24: + case 0x2c: + return "BIT"; + case 0x28: + return "PLP"; + case 0x30: + return "BMI"; + case 0x38: + return "SEC"; + case 0x40: + return "RTI"; + case 0x48: + return "PHA"; + case 0x4c: + case 0x6c: + return "JMP"; + case 0x50: + return "BVC"; + case 0x58: + return "CLI"; + case 0x60: + return "RTS"; + case 0x68: + return "PLA"; + case 0x70: + return "BVS"; + case 0x78: + return "SEI"; + case 0x84: + case 0x8c: + case 0x94: + return "STY"; + case 0x88: + return "DEY"; + case 0x90: + return "BCC"; + case 0x98: + return "TYA"; + case 0x9c: + return "SHY"; + case 0xa0: + case 0xa4: + case 0xac: + case 0xb4: + case 0xbc: + return "LDY"; + case 0xa8: + return "TAY"; + case 0xb0: + return "BCS"; + case 0xb8: + return "CLV"; + case 0xc0: + case 0xc4: + case 0xcc: + return "CPY"; + case 0xc8: + return "INY"; + case 0xd0: + return "BNE"; + case 0xd8: + return "CLD"; + case 0xe0: + case 0xe4: + case 0xec: + return "CPX"; + case 0xe8: + return "INX"; + case 0xf0: + return "BEQ"; + case 0xf8: + return "SED"; + + case 0x01: + case 0x05: + case 0x09: + case 0x0d: + case 0x11: + case 0x15: + case 0x19: + case 0x1d: + return "ORA"; + case 0x21: + case 0x25: + case 0x29: + case 0x2d: + case 0x31: + case 0x35: + case 0x39: + case 0x3d: + return "AND"; + case 0x41: + case 0x45: + case 0x49: + case 0x4d: + case 0x51: + case 0x55: + case 0x59: + case 0x5d: + return "EOR"; + case 0x61: + case 0x65: + case 0x69: + case 0x6d: + case 0x71: + case 0x75: + case 0x79: + case 0x7d: + return "ADC"; + case 0x81: + case 0x85: + case 0x8d: + case 0x91: + case 0x95: + case 0x99: + case 0x9d: + return "STA"; + case 0xa1: + case 0xa5: + case 0xa9: + case 0xad: + case 0xb1: + case 0xb5: + case 0xb9: + case 0xbd: + return "LDA"; + case 0xc1: + case 0xc5: + case 0xc9: + case 0xcd: + case 0xd1: + case 0xd5: + case 0xd9: + case 0xdd: + return "CMP"; + case 0xe1: + case 0xe5: + case 0xe9: + case 0xed: + case 0xf1: + case 0xf5: + case 0xf9: + case 0xfd: + return "SBC"; + + case 0x03: + case 0x07: + case 0x0f: + case 0x13: + case 0x17: + case 0x1b: + case 0x1f: + return "SLO"; + case 0x23: + case 0x27: + case 0x2f: + case 0x33: + case 0x37: + case 0x3b: + case 0x3f: + return "RLA"; + case 0x43: + case 0x47: + case 0x4f: + case 0x53: + case 0x57: + case 0x5b: + case 0x5f: + return "SRE"; + case 0x4b: + return "ALR"; + case 0x63: + case 0x67: + case 0x6f: + case 0x73: + case 0x77: + case 0x7b: + case 0x7f: + return "RRA"; + case 0x6b: + return "ARR"; + case 0x83: + case 0x87: + case 0x8f: + case 0x97: + return "SAX"; + case 0x8b: + return "XAA"; + case 0x93: + case 0x9f: + return "AHX"; + case 0x9b: + return "TAS"; + case 0xa3: + case 0xa7: + case 0xab: + case 0xaf: + case 0xb3: + case 0xb7: + case 0xbb: + case 0xbf: + return "LAX"; + case 0xc3: + case 0xc7: + case 0xcf: + case 0xd3: + case 0xd7: + case 0xdb: + case 0xdf: + return "DCP"; + case 0xcb: + return "AXS"; + case 0xe3: + case 0xe7: + case 0xef: + case 0xf3: + case 0xf7: + case 0xfb: + case 0xff: + return "ISC"; + case 0xeb: + return "SBC"; + + case 0x06: + case 0x0a: + case 0x0e: + case 0x16: + case 0x1e: + return "ASL"; + case 0x26: + case 0x2a: + case 0x2e: + case 0x36: + case 0x3e: + return "ROL"; + case 0x46: + case 0x4a: + case 0x4e: + case 0x56: + case 0x5e: + return "LSR"; + case 0x66: + case 0x6a: + case 0x6e: + case 0x76: + case 0x7e: + return "ROR"; + case 0x86: + case 0x8e: + case 0x96: + return "STX"; + case 0x8a: + return "TXA"; + case 0x9a: + case 0xba: + return "TSX"; + case 0x9e: + return "SHX"; + case 0xa2: + case 0xa6: + case 0xae: + case 0xb6: + case 0xbe: + return "LDX"; + case 0xaa: + return "TAX"; + case 0xc6: + case 0xca: + case 0xce: + case 0xd6: + case 0xde: + return "DEC"; + case 0xe6: + case 0xee: + case 0xf6: + case 0xfe: + return "INC"; + + case 0x02: + case 0x12: + case 0x22: + case 0x32: + case 0x42: + case 0x52: + case 0x62: + case 0x72: + case 0x92: + case 0xb2: + case 0xd2: + case 0xf2: + return "STP"; + case 0x04: + case 0x0c: + case 0x14: + case 0x1c: + case 0x1a: + case 0x34: + case 0x3a: + case 0x3c: + case 0x44: + case 0x54: + case 0x5a: + case 0x5c: + case 0x64: + case 0x74: + case 0x7a: + case 0x7c: + case 0x80: + case 0x82: + case 0x89: + case 0xc2: + case 0xd4: + case 0xda: + case 0xdc: + case 0xe2: + case 0xea: + case 0xf4: + case 0xfa: + case 0xfc: + return "NOP"; + + default: + assert(false); + } +} \ No newline at end of file diff --git a/cpu/decoding.h b/cpu/decoding.h new file mode 100644 index 0000000..4665746 --- /dev/null +++ b/cpu/decoding.h @@ -0,0 +1,52 @@ +// +// Created by william on 1/9/24. +// + +#ifndef NESEMULATOR_DECODING_H +#define NESEMULATOR_DECODING_H + +#include "../include/types.h" +#include "../include/system.h" +#include "cpu.h" + +typedef enum { + ADDR_MODE_ABSOLUTE, // a + ADDR_MODE_ABSOLUTE_INDEXED_X, // a,x + ADDR_MODE_ABSOLUTE_INDEXED_Y, // a,y + ADDR_MODE_ACCUMULATOR, // A + ADDR_MODE_IMMEDIATE, // #i + ADDR_MODE_IMPLICIT, // Imp + ADDR_MODE_INDIRECT_X, // (d,x) + ADDR_MODE_INDIRECT_JUMP, // + ADDR_MODE_INDIRECT_Y, // (d),y + ADDR_MODE_RELATIVE, // label + ADDR_MODE_ZERO_PAGE, // d + ADDR_MODE_ZERO_PAGE_INDEXED_X, // d,x + ADDR_MODE_ZERO_PAGE_INDEXED_Y, // d,y +} AddressingMode; + +enum OperandType { + OPERAND_TYPE_ACCUMULATOR, + OPERAND_TYPE_IMMEDIATE, + OPERAND_TYPE_ADDRESS +}; + +typedef struct { + word value; + enum OperandType type; + bool is_page_crossing; +} Operand; + +address decode_operand_addr(System *system, AddressingMode addr_mode, bool *page_crossing); + +Operand decode_operand(System *system, AddressingMode addr_mode); + +byte read_operand(System *system, Operand operand); + +char *get_addr_mode_name(AddressingMode addr_mode); + +char *operand_name(Operand *operand); + +char *get_op_code_name(byte op); + +#endif //NESEMULATOR_DECODING_H diff --git a/cpu/op.c b/cpu/op.c index b56b359..38c321f 100644 --- a/cpu/op.c +++ b/cpu/op.c @@ -4,6 +4,7 @@ #include "op.h" #include "cpu.h" +#include "decoding.h" // Reference: https://www.nesdev.org/wiki/CPU_unofficial_opcodes // https://www.middle-engine.com/blog/posts/2020/06/23/programming-the-nes-the-6502-in-detail @@ -60,130 +61,6 @@ IS_UNOFFICIAL_OP_CODE_(op, line, 0x1b, ABSOLUTE_INDEXED_Y) \ IS_UNOFFICIAL_OP_CODE_(op, line, 0x1f, ABSOLUTE_INDEXED_X) -char *addr_mode_name(AddressingMode addr_mode) { - switch (addr_mode) { - case ADDR_MODE_ABSOLUTE: - return "Absolute"; - case ADDR_MODE_ABSOLUTE_JUMP: - return "Absolute Jump"; - case ADDR_MODE_ABSOLUTE_INDEXED_X: - return "Absolute Indexed X"; - case ADDR_MODE_ABSOLUTE_INDEXED_Y: - return "Absolute Indexed Y"; - case ADDR_MODE_ACCUMULATOR: - return "Accumulator"; - case ADDR_MODE_IMMEDIATE: - return "Immediate"; - case ADDR_MODE_IMPLICIT: - return "Implicit"; - case ADDR_MODE_INDIRECT_X: - return "Indirect X"; - case ADDR_MODE_INDIRECT_JUMP: - return "Indirect Jump"; - case ADDR_MODE_INDIRECT_Y: - return "Indirect Y"; - case ADDR_MODE_RELATIVE: - return "Relative"; - case ADDR_MODE_ZERO_PAGE: - return "Zero Page"; - case ADDR_MODE_ZERO_PAGE_INDEXED_X: - return "Zero Page X"; - case ADDR_MODE_ZERO_PAGE_INDEXED_Y: - return "Zero Page Y"; - } -} - -address decode_operand_addr(System *system, AddressingMode addr_mode, bool *page_crossing) { - CPU registers = system->cpu; - address operand_addr; - - if (addr_mode == ADDR_MODE_ZERO_PAGE) { - operand_addr = cpu_get_next_byte(system); - } else if (addr_mode == ADDR_MODE_ZERO_PAGE_INDEXED_X) { - operand_addr = (cpu_get_next_byte(system) + registers.x) & 0xff; - } else if (addr_mode == ADDR_MODE_ZERO_PAGE_INDEXED_Y) { - operand_addr = (cpu_get_next_byte(system) + registers.y) & 0xff; - } else if (addr_mode == ADDR_MODE_ABSOLUTE || addr_mode == ADDR_MODE_ABSOLUTE_JUMP) { - operand_addr = cpu_get_next_word(system); - } else if (addr_mode == ADDR_MODE_ABSOLUTE_INDEXED_X) { - word addr = cpu_get_next_word(system); - 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; - - *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); - 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; - operand_addr = result; - } else { - operand_addr = mem_get_word(system, addr); - } - } else if (addr_mode == ADDR_MODE_INDIRECT_X) { - byte arg_addr = cpu_get_next_byte(system); - - 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; - 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; - - *page_crossing = (addr & 0xff00) != (new_addr & 0xff00); - - operand_addr = new_addr; - } else { - assert(false); - } - - log_trace("Operand address: %#02x, Addressing mode: %s", operand_addr, addr_mode_name(addr_mode)); - return operand_addr; -} - -Operand decode_operand(System *system, AddressingMode addr_mode) { - Operand operand; - - if (addr_mode == ADDR_MODE_ACCUMULATOR) { - operand.type = OPERAND_TYPE_ACCUMULATOR; - operand.value = 0; - 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.is_page_crossing = false; - } else { - operand.type = OPERAND_TYPE_ADDRESS; - operand.value = decode_operand_addr(system, 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) { - switch (operand.type) { - case OPERAND_TYPE_ACCUMULATOR: - return system->cpu.accumulator; - case OPERAND_TYPE_IMMEDIATE: - return (byte) operand.value; - case OPERAND_TYPE_ADDRESS: - return mem_get_byte(system, operand.value); - default: - assert(false); - } -} - void write_operand(System *system, Operand operand, byte value) { switch (operand.type) { case OPERAND_TYPE_ACCUMULATOR: @@ -1226,347 +1103,6 @@ void process_op_code(System *system, byte op) { IS_OP_CODE_MODE(LAS, 0xbb, ABSOLUTE_INDEXED_Y) IS_OP_CODE_MODE(LAX, 0xbf, ABSOLUTE_INDEXED_Y) - default: - assert(false); - } -} - -char *get_op_code_name(byte op) { - switch (op) { - case 0x00: - return "BRK"; - case 0x08: - return "PHP"; - case 0x0b: - case 0x2b: - return "ANC"; - case 0x10: - return "BPL"; - case 0x18: - return "CLC"; - case 0x20: - return "JSR"; - case 0x24: - case 0x2c: - return "BIT"; - case 0x28: - return "PLP"; - case 0x30: - return "BMI"; - case 0x38: - return "SEC"; - case 0x40: - return "RTI"; - case 0x48: - return "PHA"; - case 0x4c: - case 0x6c: - return "JMP"; - case 0x50: - return "BVC"; - case 0x58: - return "CLI"; - case 0x60: - return "RTS"; - case 0x68: - return "PLA"; - case 0x70: - return "BVS"; - case 0x78: - return "SEI"; - case 0x84: - case 0x8c: - case 0x94: - return "STY"; - case 0x88: - return "DEY"; - case 0x90: - return "BCC"; - case 0x98: - return "TYA"; - case 0x9c: - return "SHY"; - case 0xa0: - case 0xa4: - case 0xac: - case 0xb4: - case 0xbc: - return "LDY"; - case 0xa8: - return "TAY"; - case 0xb0: - return "BCS"; - case 0xb8: - return "CLV"; - case 0xc0: - case 0xc4: - case 0xcc: - return "CPY"; - case 0xc8: - return "INY"; - case 0xd0: - return "BNE"; - case 0xd8: - return "CLD"; - case 0xe0: - case 0xe4: - case 0xec: - return "CPX"; - case 0xe8: - return "INX"; - case 0xf0: - return "BEQ"; - case 0xf8: - return "SED"; - - case 0x01: - case 0x05: - case 0x09: - case 0x0d: - case 0x11: - case 0x15: - case 0x19: - case 0x1d: - return "ORA"; - case 0x21: - case 0x25: - case 0x29: - case 0x2d: - case 0x31: - case 0x35: - case 0x39: - case 0x3d: - return "AND"; - case 0x41: - case 0x45: - case 0x49: - case 0x4d: - case 0x51: - case 0x55: - case 0x59: - case 0x5d: - return "EOR"; - case 0x61: - case 0x65: - case 0x69: - case 0x6d: - case 0x71: - case 0x75: - case 0x79: - case 0x7d: - return "ADC"; - case 0x81: - case 0x85: - case 0x8d: - case 0x91: - case 0x95: - case 0x99: - case 0x9d: - return "STA"; - case 0xa1: - case 0xa5: - case 0xa9: - case 0xad: - case 0xb1: - case 0xb5: - case 0xb9: - case 0xbd: - return "LDA"; - case 0xc1: - case 0xc5: - case 0xc9: - case 0xcd: - case 0xd1: - case 0xd5: - case 0xd9: - case 0xdd: - return "CMP"; - case 0xe1: - case 0xe5: - case 0xe9: - case 0xed: - case 0xf1: - case 0xf5: - case 0xf9: - case 0xfd: - return "SBC"; - - case 0x03: - case 0x07: - case 0x0f: - case 0x13: - case 0x17: - case 0x1b: - case 0x1f: - return "SLO"; - case 0x23: - case 0x27: - case 0x2f: - case 0x33: - case 0x37: - case 0x3b: - case 0x3f: - return "RLA"; - case 0x43: - case 0x47: - case 0x4f: - case 0x53: - case 0x57: - case 0x5b: - case 0x5f: - return "SRE"; - case 0x4b: - return "ALR"; - case 0x63: - case 0x67: - case 0x6f: - case 0x73: - case 0x77: - case 0x7b: - case 0x7f: - return "RRA"; - case 0x6b: - return "ARR"; - case 0x83: - case 0x87: - case 0x8f: - case 0x97: - return "SAX"; - case 0x8b: - return "XAA"; - case 0x93: - case 0x9f: - return "AHX"; - case 0x9b: - return "TAS"; - case 0xa3: - case 0xa7: - case 0xab: - case 0xaf: - case 0xb3: - case 0xb7: - case 0xbb: - case 0xbf: - return "LAX"; - case 0xc3: - case 0xc7: - case 0xcf: - case 0xd3: - case 0xd7: - case 0xdb: - case 0xdf: - return "DCP"; - case 0xcb: - return "AXS"; - case 0xe3: - case 0xe7: - case 0xef: - case 0xf3: - case 0xf7: - case 0xfb: - case 0xff: - return "ISC"; - case 0xeb: - return "SBC"; - - case 0x06: - case 0x0a: - case 0x0e: - case 0x16: - case 0x1e: - return "ASL"; - case 0x26: - case 0x2a: - case 0x2e: - case 0x36: - case 0x3e: - return "ROL"; - case 0x46: - case 0x4a: - case 0x4e: - case 0x56: - case 0x5e: - return "LSR"; - case 0x66: - case 0x6a: - case 0x6e: - case 0x76: - case 0x7e: - return "ROR"; - case 0x86: - case 0x8e: - case 0x96: - return "STX"; - case 0x8a: - return "TXA"; - case 0x9a: - case 0xba: - return "TSX"; - case 0x9e: - return "SHX"; - case 0xa2: - case 0xa6: - case 0xae: - case 0xb6: - case 0xbe: - return "LDX"; - case 0xaa: - return "TAX"; - case 0xc6: - case 0xca: - case 0xce: - case 0xd6: - case 0xde: - return "DEC"; - case 0xe6: - case 0xee: - case 0xf6: - case 0xfe: - return "INC"; - - case 0x02: - case 0x12: - case 0x22: - case 0x32: - case 0x42: - case 0x52: - case 0x62: - case 0x72: - case 0x92: - case 0xb2: - case 0xd2: - case 0xf2: - return "STP"; - case 0x04: - case 0x0c: - case 0x14: - case 0x1c: - case 0x1a: - case 0x34: - case 0x3a: - case 0x3c: - case 0x44: - case 0x54: - case 0x5a: - case 0x5c: - case 0x64: - case 0x74: - case 0x7a: - case 0x7c: - case 0x80: - case 0x82: - case 0x89: - case 0xc2: - case 0xd4: - case 0xda: - case 0xdc: - case 0xe2: - case 0xea: - case 0xf4: - case 0xfa: - case 0xfc: - return "NOP"; - default: assert(false); } diff --git a/cpu/op.h b/cpu/op.h index 6d4412f..f2fcd12 100644 --- a/cpu/op.h +++ b/cpu/op.h @@ -16,24 +16,6 @@ enum op_code_base { OP_CODE_BASE_SBC = 0xe0 }; -typedef enum { - ADDR_MODE_ABSOLUTE, // a - ADDR_MODE_ABSOLUTE_JUMP, // (a) - ADDR_MODE_ABSOLUTE_INDEXED_X, // a,x - ADDR_MODE_ABSOLUTE_INDEXED_Y, // a,y - ADDR_MODE_ACCUMULATOR, // A - ADDR_MODE_IMMEDIATE, // #i - ADDR_MODE_IMPLICIT, // Imp - ADDR_MODE_INDIRECT_X, // (d,x) - ADDR_MODE_INDIRECT_JUMP, // - ADDR_MODE_INDIRECT_Y, // (d),y - ADDR_MODE_RELATIVE, // label - ADDR_MODE_ZERO_PAGE, // d - ADDR_MODE_ZERO_PAGE_INDEXED_X, // d,x - ADDR_MODE_ZERO_PAGE_INDEXED_Y, // d,y -} AddressingMode; - void process_op_code(System *system, byte op); -char* get_op_code_name(byte op); #endif \ No newline at end of file diff --git a/debugger/debugger.c b/debugger/debugger.c index 54257d8..cf738cc 100644 --- a/debugger/debugger.c +++ b/debugger/debugger.c @@ -36,19 +36,19 @@ void start_debugger(System *system) { int keycode; while ((keycode = getch()) != CTRL_KEY_EXIT) { if (keycode == KEY_UP) { - memory_view_move_cursor(&view, 0, -1); + memory_view_move_cursor(&view, 0, MEMORY_VIEW_DIRECTION_DOWN); } if (keycode == KEY_DOWN) { - memory_view_move_cursor(&view, 0, 1); + memory_view_move_cursor(&view, 0, MEMORY_VIEW_DIRECTION_UP); } if (keycode == KEY_LEFT) { - memory_view_move_cursor(&view, -1, 0); + memory_view_move_cursor(&view, MEMORY_VIEW_DIRECTION_LEFT, 0); } if (keycode == KEY_RIGHT) { - memory_view_move_cursor(&view, 1, 0); + memory_view_move_cursor(&view, MEMORY_VIEW_DIRECTION_RIGHT, 0); } if (keycode == CTRL_KEY_G) { diff --git a/debugger/memory_view.c b/debugger/memory_view.c index 6281792..0262774 100644 --- a/debugger/memory_view.c +++ b/debugger/memory_view.c @@ -93,13 +93,13 @@ void memory_view_scroll(MemoryView *view, char direction) { } void memory_view_move_cursor(MemoryView *view, char horizontal, char vertical) { - if (horizontal == 1 && view->cursor_x == 0xf || - horizontal == -1 && view->cursor_x == 0) { + if (horizontal == MEMORY_VIEW_DIRECTION_UP && view->cursor_x == 0xf || + horizontal == MEMORY_VIEW_DIRECTION_DOWN && view->cursor_x == 0) { return; } - if (vertical == 1 && view->cursor_y == 0xf || - vertical == -1 && view->cursor_y == 0) { + if (vertical == MEMORY_VIEW_DIRECTION_RIGHT && view->cursor_y == 0xf || + vertical == MEMORY_VIEW_DIRECTION_LEFT && view->cursor_y == 0) { memory_view_scroll(view, vertical); return; } diff --git a/debugger/memory_view.h b/debugger/memory_view.h index e2e2882..0842e83 100644 --- a/debugger/memory_view.h +++ b/debugger/memory_view.h @@ -16,6 +16,8 @@ #define MEMORY_VIEW_DIRECTION_UP 1 #define MEMORY_VIEW_DIRECTION_DOWN (-1) +#define MEMORY_VIEW_DIRECTION_RIGHT 1 +#define MEMORY_VIEW_DIRECTION_LEFT (-1) typedef struct memory_view { PANEL *panel; @@ -25,16 +27,54 @@ typedef struct memory_view { char cursor_y; } MemoryView; +/** + * Initializes a memory view for a system RAM. + * 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 memory_view_init(MemoryView *view, ram ram); +/** + * Prints the RAM content from the viewer base address. + * + * @param view + */ void memory_view_print(MemoryView *view); +/** + * Sets the viewer base address to the target address page (the first byte) and prints the RAM. + * + * @param view + * @param target The target address to print + */ void memory_view_goto(MemoryView *view, address target); +/** + * Scrolls the base address up or down by steps of 0x10. + * + * @param view + * @param direction The scroll direction + */ void memory_view_scroll(MemoryView *view, char direction); +/** + * Moves the cursor up, down, right or left. + * + * @param view + * @param horizontal + * @param vertical + */ void memory_view_move_cursor(MemoryView *view, char horizontal, char vertical); +/** + * Moves the cursor to a specific memory address. + * The view will not be scrolled if the target address is not displayed. + * + * @param view + * @param target + */ void memory_view_set_cursor_addr(MemoryView *view, address target); #endif //NESEMULATOR_MEMORY_VIEW_H