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 @@
-
+
@@ -498,7 +503,15 @@
1704662439962
-
+
+
+ 1704829582042
+
+
+
+ 1704829582042
+
+
@@ -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