diff --git a/.idea/workspace.xml b/.idea/workspace.xml index eeaa3f2..abbf0b3 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -12,6 +12,7 @@ + @@ -24,59 +25,18 @@ - - - - - - - - - - + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -534,7 +512,8 @@ - diff --git a/CMakeLists.txt b/CMakeLists.txt index 0a746a7..cec06e3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,12 +5,14 @@ add_subdirectory(cpu) add_subdirectory(ppu) add_subdirectory(mappers) add_subdirectory(rom) +add_subdirectory(debugger) list(APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/cpu" "${PROJECT_SOURCE_DIR}/ppu" "${PROJECT_SOURCE_DIR}/mappers" - "${PROJECT_SOURCE_DIR}/rom") + "${PROJECT_SOURCE_DIR}/rom" + "${PROJECT_SOURCE_DIR}/debugger") add_executable(NESEmulator main.c system.c @@ -19,7 +21,7 @@ add_executable(NESEmulator main.c find_package(log.c) -target_link_libraries(NESEmulator CPU PPU Mappers ROM log.c::log.c) +target_link_libraries(NESEmulator CPU PPU Mappers ROM DEBUG log.c::log.c) target_include_directories(NESEmulator PUBLIC "${PROJECT_BINARY_DIR}" ${EXTRA_INCLUDES}) diff --git a/conandata.yml b/conandata.yml index 72d8f52..69e9b4f 100644 --- a/conandata.yml +++ b/conandata.yml @@ -2,5 +2,6 @@ # To keep your changes, remove these comment lines, but the plugin won't be able to modify your requirements requirements: + - "ncurses/6.4" - "libcheck/0.15.2" - "log.c/cci.20200620" \ No newline at end of file diff --git a/debugger/CMakeLists.txt b/debugger/CMakeLists.txt new file mode 100644 index 0000000..896d677 --- /dev/null +++ b/debugger/CMakeLists.txt @@ -0,0 +1,8 @@ +add_library(DEBUG + debugger.c + memory_view.c + dialog.c) + +find_package(Curses) + +target_link_libraries(DEBUG Curses::Curses) \ No newline at end of file diff --git a/debugger/debugger.c b/debugger/debugger.c new file mode 100644 index 0000000..48c0384 --- /dev/null +++ b/debugger/debugger.c @@ -0,0 +1,63 @@ +// +// Created by william on 1/6/24. +// + +#include +#include +#include +#include "debugger.h" +#include "memory_view.h" +#include "dialog.h" + +#define CTRL_KEY_EXIT 3 +#define CTRL_KEY_UP 65 +#define CTRL_KEY_DOWN 66 +#define CTRL_KEY_G 103 + +MemoryView view; + +void create_window() { + setenv("TERMINFO", "/usr/share/terminfo", 1); + setenv("TERM", "xterm", 1); + + initscr(); + raw(); + noecho(); +// wborder(window, '|', '|', '-', '-', '+', '+', '+', '+'); +} + +void destroy_window() { + endwin(); +} + +void some_func(char* user_input) { +} + +void start_debugger(System *system) { + create_window(); + + memory_view_init(&view, system->ram); + + update_panels(); + doupdate(); + + int keycode; + while ((keycode = getch()) != CTRL_KEY_EXIT) { + if (keycode == CTRL_KEY_UP) { + memory_view_scroll(&view, -1, system->ram); + } + + if (keycode == CTRL_KEY_DOWN) { + memory_view_scroll(&view, 1, system->ram); + } + + if (keycode == CTRL_KEY_G) { + Dialog dialog = dialog_create("Goto Address", &some_func); + } + + update_panels(); + doupdate(); + } + + endwin(); +} \ No newline at end of file diff --git a/debugger/debugger.h b/debugger/debugger.h new file mode 100644 index 0000000..e27eb35 --- /dev/null +++ b/debugger/debugger.h @@ -0,0 +1,12 @@ +// +// Created by william on 1/6/24. +// + +#include "../include/system.h" + +#ifndef NESEMULATOR_DEBUGGER_H +#define NESEMULATOR_DEBUGGER_H + +void start_debugger(System *system); + +#endif //NESEMULATOR_DEBUGGER_H diff --git a/debugger/dialog.c b/debugger/dialog.c new file mode 100644 index 0000000..b7b56f2 --- /dev/null +++ b/debugger/dialog.c @@ -0,0 +1,21 @@ +// +// Created by william on 1/7/24. +// + +#include +#include "dialog.h" + +Dialog dialog_create(char *message, void (*callback)(char *user_input)) { + Dialog dialog; + int width = (int) strlen(message) + 2; + + WINDOW *window = newwin(3, width, 2, 2); + box(window, 0, 0); + + mvwprintw(window, 0, 1, "%s", message); + + dialog.panel = new_panel(window); + dialog.callback = callback; + + return dialog; +} diff --git a/debugger/dialog.h b/debugger/dialog.h new file mode 100644 index 0000000..7febd66 --- /dev/null +++ b/debugger/dialog.h @@ -0,0 +1,18 @@ +// +// Created by william on 1/7/24. +// + +#ifndef NESEMULATOR_DIALOG_H +#define NESEMULATOR_DIALOG_H + +#include + +typedef struct dialog { + PANEL *panel; + + void (*callback)(char *user_input); +} Dialog; + +Dialog dialog_create(char *message, void (*callback)(char *user_input)); + +#endif //NESEMULATOR_DIALOG_H diff --git a/debugger/memory_view.c b/debugger/memory_view.c new file mode 100644 index 0000000..8062892 --- /dev/null +++ b/debugger/memory_view.c @@ -0,0 +1,65 @@ +#include +#include +#include +#include "memory_view.h" + +// +// Created by william on 1/6/24. +// + +void write_line(WINDOW *window, int line, address base_address, byte *data) { + mvwprintw(window, line + 2, 1, "[%04x]", base_address); + + for (int i = 0; i <= MEMORY_VIEW_LINE_BYTE_COUNT; i++) { + mvwprintw(window, line + 2, 8 + i * 3, "%02x", data[i]); + } +} + +void memory_view_init(MemoryView *view, ram ram) { + WINDOW *window = newwin(MEMORY_VIEW_HEIGHT, MEMORY_VIEW_WIDTH, 0, 0); + box(window, 0, 0); + + mvwprintw(window, 0, 1, " MEMORY VIEW "); + mvwprintw(window, 1, 1, " +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +a +b +c +d +e +f"); + + view->panel = new_panel(window); + view->base_address = 0xfc00; + + memory_view_print(view, ram); +} + +void memory_view_print(MemoryView *view, ram ram) { + 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 = &ram[line_address]; + + write_line(view->panel->win, line, line_address, data); + } +} + +void memory_view_goto(MemoryView *view, address target, ram ram) { + assert(target < RAM_SIZE); + + address max_base_address = RAM_SIZE - MEMORY_VIEW_BYTE_COUNT; + if (target > max_base_address) { + target = max_base_address; + } + + view->base_address = target; + memory_view_print(view, ram); +} + +void memory_view_scroll(MemoryView *view, char direction, ram ram) { + assert(direction == MEMORY_VIEW_DIRECTION_DOWN || direction == MEMORY_VIEW_DIRECTION_UP); + + int offset = 0; + if (direction == MEMORY_VIEW_DIRECTION_DOWN && view->base_address > MEMORY_VIEW_LINE_BYTE_COUNT) { + offset -= MEMORY_VIEW_LINE_BYTE_COUNT + 1; + } + if (direction == MEMORY_VIEW_DIRECTION_UP && view->base_address < RAM_SIZE - MEMORY_VIEW_BYTE_COUNT) { + offset += MEMORY_VIEW_LINE_BYTE_COUNT + 1; + } + + address target = view->base_address + offset; + memory_view_goto(view, target, ram); +} \ No newline at end of file diff --git a/debugger/memory_view.h b/debugger/memory_view.h new file mode 100644 index 0000000..42bb8d8 --- /dev/null +++ b/debugger/memory_view.h @@ -0,0 +1,33 @@ +// +// Created by william on 1/6/24. +// + +#ifndef NESEMULATOR_MEMORY_VIEW_H +#define NESEMULATOR_MEMORY_VIEW_H + +#include +#include "../include/types.h" + +#define MEMORY_VIEW_HEIGHT 19 +#define MEMORY_VIEW_WIDTH 56 +#define MEMORY_VIEW_LINE_COUNT 0xf +#define MEMORY_VIEW_LINE_BYTE_COUNT 0xf +#define MEMORY_VIEW_BYTE_COUNT 0xff + +#define MEMORY_VIEW_DIRECTION_UP 1 +#define MEMORY_VIEW_DIRECTION_DOWN -1 + +typedef struct memory_view { + PANEL *panel; + address base_address; +} MemoryView; + +void memory_view_init(MemoryView *view, ram ram); + +void memory_view_print(MemoryView *view, ram ram); + +void memory_view_goto(MemoryView *view, address target, ram ram); + +void memory_view_scroll(MemoryView *view, char direction, ram ram); + +#endif //NESEMULATOR_MEMORY_VIEW_H diff --git a/main.c b/main.c index 6a795f9..68d73d4 100644 --- a/main.c +++ b/main.c @@ -17,26 +17,50 @@ */ #include #include +#include "debugger/debugger.h" #include "include/rom.h" #include "include/system.h" -int main() { - log_set_level(LOG_INFO); +//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; +//} - char *rom_path = "../test_roms/nestest.nes"; +int main() { System system; + log_set_level(LOG_INFO); system_init(&system); + char *rom_path = "../test_roms/nestest.nes"; + if (!rom_load(rom_path, &system)) { system_uninit(&system); return EXIT_FAILURE; } - system_start(&system); - system_loop(&system); - system_uninit(&system); + start_debugger(&system); - return EXIT_SUCCESS; + system_uninit(&system); + return 0; +// +// system_start(&system); +// system_loop(&system); +// system_uninit(&system); + +// return EXIT_SUCCESS; + +// return win(); } \ No newline at end of file