diff --git a/CMakeLists.txt b/CMakeLists.txt index cec06e3..13b591f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,13 +6,15 @@ add_subdirectory(ppu) add_subdirectory(mappers) add_subdirectory(rom) add_subdirectory(debugger) +add_subdirectory(utils) list(APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/cpu" "${PROJECT_SOURCE_DIR}/ppu" "${PROJECT_SOURCE_DIR}/mappers" "${PROJECT_SOURCE_DIR}/rom" - "${PROJECT_SOURCE_DIR}/debugger") + "${PROJECT_SOURCE_DIR}/debugger" + "${PROJECT_SOURCE_DIR}/utils") add_executable(NESEmulator main.c system.c @@ -21,7 +23,7 @@ add_executable(NESEmulator main.c find_package(log.c) -target_link_libraries(NESEmulator CPU PPU Mappers ROM DEBUG log.c::log.c) +target_link_libraries(NESEmulator CPU PPU Mappers ROM DEBUG UTILS log.c::log.c) target_include_directories(NESEmulator PUBLIC "${PROJECT_BINARY_DIR}" ${EXTRA_INCLUDES}) diff --git a/cpu/cpu.h b/cpu/cpu.h index c68ddf9..a7a14cb 100644 --- a/cpu/cpu.h +++ b/cpu/cpu.h @@ -19,14 +19,6 @@ #define CPU_STACK_ADDR 0x0100 -/** - * 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); - /** * Gets a flag from the CPU registers. * diff --git a/cpu/op.c b/cpu/op.c index 76b502a..312db48 100644 --- a/cpu/op.c +++ b/cpu/op.c @@ -1231,6 +1231,7 @@ AddressingMode get_op_addr_mode(byte op_code) { case 0x22: case 0x28: case 0x32: + case 0x38: case 0x3a: case 0x40: case 0x42: diff --git a/debugger/debugger.c b/debugger/debugger.c index 1086404..eea7c99 100644 --- a/debugger/debugger.c +++ b/debugger/debugger.c @@ -7,12 +7,8 @@ #include #include "debugger.h" #include "memory_view.h" -#include "dialog.h" #include "program_view.h" -#define CTRL_KEY_EXIT 3 -#define CTRL_KEY_G 103 - void create_window() { setenv("TERMINFO", "/usr/share/terminfo", 1); setenv("TERM", "xterm", 1); @@ -26,45 +22,40 @@ void create_window() { void start_debugger(System *system) { InteractWindow windows[2]; - InteractWindow *current_window; + size_t window_index = 0; + InteractWindow *current_window = &windows[window_index]; create_window(); memory_view_init(&windows[0], system->ram, 0, 0); - program_view_init(&windows[1], system->ram, MEMORY_VIEW_WIDTH, 0); + program_view_init(&windows[1], system, MEMORY_VIEW_WIDTH, 0); + + cursor_enable(¤t_window->cursor); update_panels(); doupdate(); int keycode; while ((keycode = getch()) != CTRL_KEY_EXIT) { - if (keycode == KEY_UP) { - current_window->handle_cursor_move(current_window, 0, CURSOR_OFFSET_UP); - } - - if (keycode == KEY_DOWN) { - current_window->handle_cursor_move(current_window, 0, CURSOR_OFFSET_DOWN); - } - - if (keycode == KEY_LEFT) { - current_window->handle_cursor_move(current_window, CURSOR_OFFSET_LEFT, 0); - } - - if (keycode == KEY_RIGHT) { - current_window->handle_cursor_move(current_window, CURSOR_OFFSET_RIGHT, 0); - } - - if (keycode == CTRL_KEY_G) { - Dialog dialog = dialog_create("Goto Address"); - - bool cancelled = false; - address input = dialog_get_address(&dialog, &cancelled); - dialog_remove(&dialog); - - if (!cancelled) { - memory_view_goto(&m_view, input); - memory_view_cursor_set_addr(&m_view, input); + if (keycode == CTRL_KEY_TOGGLE) { + window_index++; + if (window_index > 1) { + window_index = 0; } + + cursor_disable(¤t_window->cursor); + current_window = &windows[window_index]; + cursor_enable(¤t_window->cursor); + } else if (keycode == KEY_UP) { + current_window->handle_cursor_move(current_window, 0, CURSOR_OFFSET_UP); + } else if (keycode == KEY_DOWN) { + current_window->handle_cursor_move(current_window, 0, CURSOR_OFFSET_DOWN); + } else if (keycode == KEY_LEFT) { + current_window->handle_cursor_move(current_window, CURSOR_OFFSET_LEFT, 0); + } else if (keycode == KEY_RIGHT) { + current_window->handle_cursor_move(current_window, CURSOR_OFFSET_RIGHT, 0); + } else { + current_window->handle_key_down(current_window, keycode); } update_panels(); diff --git a/debugger/debugger.h b/debugger/debugger.h index 6de8a78..e847ce9 100644 --- a/debugger/debugger.h +++ b/debugger/debugger.h @@ -7,6 +7,9 @@ #include "../include/system.h" +#define CTRL_KEY_EXIT 3 +#define CTRL_KEY_TOGGLE 116 + void start_debugger(System *system); #endif //NESEMULATOR_DEBUGGER_H diff --git a/debugger/memory_view.c b/debugger/memory_view.c index eac4244..245fa22 100644 --- a/debugger/memory_view.c +++ b/debugger/memory_view.c @@ -1,6 +1,7 @@ #include #include #include "memory_view.h" +#include "dialog.h" // // Created by william on 6/1/24. @@ -20,12 +21,22 @@ void memory_view_cursor_init(MemoryView *view) { cursor->min_y = 2; cursor->multiplier_x = 3; cursor->width = 2; - - cursor_enable(cursor); } void memory_view_handle_key_down(InteractWindow *window, int keycode) { + if (keycode == MEMORY_VIEW_KEY_GOTO) { + Dialog dialog = dialog_create("Goto Address"); + bool cancelled = false; + address input = dialog_get_address(&dialog, &cancelled); + dialog_remove(&dialog); + + if (!cancelled) { + MemoryView *view = window->view; + memory_view_goto(view, input); + memory_view_cursor_set_addr(view, input); + } + } } void memory_view_init(InteractWindow *interact, ram ram, int x, int y) { diff --git a/debugger/memory_view.h b/debugger/memory_view.h index db15633..e40000d 100644 --- a/debugger/memory_view.h +++ b/debugger/memory_view.h @@ -15,6 +15,7 @@ #define MEMORY_VIEW_LINE_COUNT 0xf #define MEMORY_VIEW_LINE_BYTE_COUNT 0xf #define MEMORY_VIEW_BYTE_COUNT 0xff +#define MEMORY_VIEW_KEY_GOTO 103 typedef struct memory_view { InteractWindow *window; diff --git a/debugger/program_view.c b/debugger/program_view.c index 5027514..7badefa 100644 --- a/debugger/program_view.c +++ b/debugger/program_view.c @@ -3,40 +3,41 @@ // #include +#include #include "program_view.h" #include "../cpu/op.h" +#include "memory_view.h" -void decode_operands(DebugOperand *operands, const byte *ram, address start_addr) { - int pc = start_addr; - for (int i = 0; i < 10; i++) { - DebugOperand operand; - byte op_code = ram[pc]; +void decode_operands(ProgramView *view) { + int pc = PROGRAM_VIEW_BASE_ADDR; + while (pc < 0xfffa) { + DebugOperand *operand = malloc(sizeof(DebugOperand)); + if (operand == NULL) { + perror("Failed to allocate memory for debug operand"); + exit(EXIT_FAILURE); + } - operand.addr = pc; - operand.op_code = op_code; - operand.addr_mode = get_op_addr_mode(op_code); + byte op_code = view->ram[pc]; + operand->addr = pc; + operand->op_code = op_code; + operand->addr_mode = get_op_addr_mode(op_code); pc += 1; - if (operand.addr_mode == ADDR_MODE_ACCUMULATOR || operand.addr_mode == ADDR_MODE_IMPLICIT) { - operand.type = OPERAND_TYPE_ACCUMULATOR; - operand.value = 0; - } else if (operand.addr_mode == ADDR_MODE_IMMEDIATE) { - operand.type = OPERAND_TYPE_IMMEDIATE; - operand.value = ram[pc]; - pc += 1; - } else if (operand.addr_mode == ADDR_MODE_RELATIVE) { - operand.type = OPERAND_TYPE_ADDRESS; - operand.value = ram[pc]; + if (operand->addr_mode == ADDR_MODE_ACCUMULATOR || operand->addr_mode == ADDR_MODE_IMPLICIT) { + operand->value = 0; + } else if (operand->addr_mode == ADDR_MODE_RELATIVE || operand->addr_mode == ADDR_MODE_IMMEDIATE || + operand->addr_mode == ADDR_MODE_ZERO_PAGE || operand->addr_mode == ADDR_MODE_ZERO_PAGE_INDEXED_X || + operand->addr_mode == ADDR_MODE_ZERO_PAGE_INDEXED_Y) { + operand->value = view->ram[pc]; pc += 1; } else { - operand.type = OPERAND_TYPE_ADDRESS; - operand.value = ram[pc]; - operand.value += ram[pc + 1] << 8; + operand->value = view->ram[pc]; + operand->value += view->ram[pc + 1] << 8; pc += 2; } - operands[i] = operand; + linked_list_add(&view->operands, operand); } } @@ -75,25 +76,48 @@ void program_view_write_line(ProgramView *view, int line, DebugOperand *operand) char *op_name = get_op_code_name(operand->op_code); window_inter_print(view->window, 0, line, "%04x:", operand->addr); - window_inter_print(view->window, 6, line, "%s", op_name); + window_inter_print(view->window, 6, line, "(%02x) %s", operand->op_code, op_name); char *format = get_addr_mode_format_str(operand->addr_mode); - window_inter_print(view->window, 10, line, format, operand->value); + window_inter_print(view->window, 16, line, format, operand->value); } -void program_view_print(ProgramView *view, DebugOperand *operands) { - for (int line = 0; line < 10; line++) { - program_view_write_line(view, line, &operands[line]); +void program_view_print(ProgramView *view) { + LinkedListNode *current_node = view->current_operand_node; + int line = 0; + while (line <= 0xf && current_node != NULL) { + program_view_write_line(view, line, (DebugOperand *) current_node->data); + current_node = current_node->next; + line++; } } void program_view_cursor_init(ProgramView *view) { - window_inter_cursor_init(view->window, 0, 10); + window_inter_cursor_init(view->window, 0, 0xf); view->window->cursor.width = PROGRAM_VIEW_WIDTH - 2; - cursor_enable(&view->window->cursor); } -void program_view_handle_cursor_move(InteractWindow *window, int horizontal, int vertical) { +void pv_scroll(ProgramView *view, int direction) { + assert(direction == CURSOR_OFFSET_DOWN || direction == CURSOR_OFFSET_UP); + + if (direction == CURSOR_OFFSET_UP) { + view->current_operand_node = view->current_operand_node->previous; + } else { + view->current_operand_node = view->current_operand_node->next; + } + + program_view_print(view); +} + +void pv_handle_cursor_move(InteractWindow *window, int horizontal, int vertical) { + ProgramView *view = (ProgramView *) window->view; + + if (vertical == CURSOR_OFFSET_DOWN && view->window->cursor.pos_y == 0xf || + vertical == CURSOR_OFFSET_UP && view->window->cursor.pos_y == 0) { + // Scroll the view + pv_scroll(view, vertical); + } + cursor_move(&window->cursor, horizontal, vertical); } @@ -101,19 +125,33 @@ void program_view_handle_key_down(InteractWindow *window, int keycode) { } -void program_view_init(InteractWindow *interact, ram ram, int x, int y) { +void pv_deinit(InteractWindow *window) { + ProgramView *view = (ProgramView *) window->view; + linked_list_uninit(&view->operands); +} + +bool pv_predicate_operand_by_addr(void *data, void *userdata) { + DebugOperand *operand = (DebugOperand *) data; + address *addr = (address *) userdata; + return operand->addr == *addr; +} + +void program_view_init(InteractWindow *interact, System *system, int x, int y) { ProgramView *view = malloc(sizeof(ProgramView)); view->window = interact; - view->ram = ram; + view->ram = system->ram; + view->pc = &system->cpu.program_counter; + view->operands = linked_list_init(); interact->view = view; - interact->handle_cursor_move = &program_view_handle_cursor_move; + interact->handle_cursor_move = &pv_handle_cursor_move; interact->handle_key_down = &program_view_handle_key_down; + interact->deinit = &pv_deinit; window_inter_init(interact, x, y, PROGRAM_VIEW_WIDTH, PROGRAM_VIEW_HEIGHT, "PROGRAM VIEW"); - DebugOperand operands[10]; - decode_operands(&operands[0], ram, 0xc004); + decode_operands(view); + view->current_operand_node = linked_list_get_if(&view->operands, &pv_predicate_operand_by_addr, view->pc); - program_view_print(view, &operands[0]); + program_view_print(view); program_view_cursor_init(view); } \ No newline at end of file diff --git a/debugger/program_view.h b/debugger/program_view.h index 3f22ab9..743c548 100644 --- a/debugger/program_view.h +++ b/debugger/program_view.h @@ -10,24 +10,27 @@ #include "../cpu/decoding.h" #include "cursor.h" #include "window.h" +#include "../utils/linked_list.h" #define PROGRAM_VIEW_HEIGHT 19 #define PROGRAM_VIEW_WIDTH 42 - -typedef struct program_view { - InteractWindow *window; - byte *ram; - address base_address; -} ProgramView; +#define PROGRAM_VIEW_BASE_ADDR 0x0000 typedef struct debug_operand { address addr; byte op_code; AddressingMode addr_mode; - enum OperandType type; word value; } DebugOperand; -void program_view_init(InteractWindow *interact, ram ram, int x, int y); +typedef struct program_view { + InteractWindow *window; + byte *ram; + address *pc; + LinkedList operands; + LinkedListNode *current_operand_node; +} ProgramView; + +void program_view_init(InteractWindow *interact, System *system, int x, int y); #endif //NESEMULATOR_PROGRAM_VIEW_H \ No newline at end of file diff --git a/debugger/window.c b/debugger/window.c index 488fab8..a0d8b6e 100644 --- a/debugger/window.c +++ b/debugger/window.c @@ -57,5 +57,9 @@ void window_inter_print(InteractWindow *window, int x, int y, const char *fmt, . void window_inter_deinit(InteractWindow *window) { assert(window->view != NULL); + if (window->deinit != NULL) { + window->deinit(window); + } + free(window->view); } \ No newline at end of file diff --git a/debugger/window.h b/debugger/window.h index 1e59011..c65362d 100644 --- a/debugger/window.h +++ b/debugger/window.h @@ -22,6 +22,8 @@ typedef struct interact_window { void (*handle_cursor_move)(struct interact_window *window, int horizontal, int vertical); void (*handle_key_down)(struct interact_window *window, int keycode); + + void (*deinit)(struct interact_window *window); } InteractWindow; /** diff --git a/main.c b/main.c index 68d73d4..0107e82 100644 --- a/main.c +++ b/main.c @@ -22,22 +22,6 @@ #include "include/rom.h" #include "include/system.h" -//int win() { -// printf("NCURSES\n"); -// -// setlocale(LC_ALL, ""); -// setenv("TERM", "xterm-256color", 1); -// setenv("TERMINFO", "/usr/share/terminfo", 1); -// -// initscr(); -// printw("Hello World !!!"); -// refresh(); -// getch(); -// endwin(); -// -// return EXIT_SUCCESS; -//} - int main() { System system; @@ -51,16 +35,15 @@ int main() { return EXIT_FAILURE; } + system_start(&system); start_debugger(&system); system_uninit(&system); - return 0; -// -// system_start(&system); + return EXIT_SUCCESS; + // system_loop(&system); // system_uninit(&system); -// return EXIT_SUCCESS; // return win(); } \ No newline at end of file diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt new file mode 100644 index 0000000..6455fb5 --- /dev/null +++ b/utils/CMakeLists.txt @@ -0,0 +1,2 @@ +add_library(UTILS + linked_list.c) \ No newline at end of file diff --git a/utils/linked_list.c b/utils/linked_list.c new file mode 100644 index 0000000..a2ee4da --- /dev/null +++ b/utils/linked_list.c @@ -0,0 +1,65 @@ +// +// Created by william on 1/16/24. +// + +#include +#include +#include +#include +#include "linked_list.h" + +LinkedList linked_list_init() { + LinkedList list; + list.head = NULL; + list.end = NULL; + return list; +} + +void linked_list_add(LinkedList *list, void *data) { + LinkedListNode *node = malloc(sizeof(LinkedListNode)); + if (node == NULL) { + perror("Failed to allocate memory for linked list node"); + exit(EXIT_FAILURE); + } + + node->data = data; + node->previous = list->end; + node->next = NULL; + + if (list->head == NULL) { + list->head = node; + } + + if (list->end != NULL) { + list->end->next = node; + } + + list->end = node; +} + +LinkedListNode *linked_list_get_if(LinkedList *list, bool(*predicate)(void *, void *), void *userdata) { + LinkedListNode *node = list->head; + + while (node != NULL) { + if (predicate(node->data, userdata)) { + return node; + } + + node = node->next; + } + + return NULL; +} + +void linked_list_uninit(LinkedList *list) { + assert(list != NULL); + + LinkedListNode *node = list->head; + while (node != NULL) { + LinkedListNode *current_node = node; + node = node->next; + + free(current_node->data); + free(current_node); + } +} \ No newline at end of file diff --git a/utils/linked_list.h b/utils/linked_list.h new file mode 100644 index 0000000..d3e21ff --- /dev/null +++ b/utils/linked_list.h @@ -0,0 +1,29 @@ +// +// Created by william on 1/16/24. +// + +#include + +#ifndef NESEMULATOR_LINKED_LIST_H +#define NESEMULATOR_LINKED_LIST_H + +typedef struct linked_list_node { + struct linked_list_node *previous; + struct linked_list_node *next; + void *data; +} LinkedListNode; + +typedef struct linked_list { + LinkedListNode *head; + LinkedListNode *end; +} LinkedList; + +LinkedList linked_list_init(); + +void linked_list_add(LinkedList *list, void *data); + +LinkedListNode *linked_list_get_if(LinkedList *list, bool(*predicate)(void *, void *), void* userdata); + +void linked_list_uninit(LinkedList *list); + +#endif //NESEMULATOR_LINKED_LIST_H