Finished read-only memory debugger

This commit is contained in:
william 2024-01-09 14:46:20 -05:00
parent 084cbed0f4
commit 4a44443dc7
6 changed files with 194 additions and 51 deletions

View File

@ -25,18 +25,13 @@
</configurations> </configurations>
</component> </component>
<component name="ChangeListManager"> <component name="ChangeListManager">
<list default="true" id="0c3b231e-0637-4ac1-8964-c60fc9e9e691" name="Changes" comment="Things"> <list default="true" id="0c3b231e-0637-4ac1-8964-c60fc9e9e691" name="Changes" comment="Memory debugger">
<change afterPath="$PROJECT_DIR$/debugger/CMakeLists.txt" afterDir="false" />
<change afterPath="$PROJECT_DIR$/debugger/debugger.c" afterDir="false" />
<change afterPath="$PROJECT_DIR$/debugger/debugger.h" afterDir="false" />
<change afterPath="$PROJECT_DIR$/debugger/dialog.c" afterDir="false" />
<change afterPath="$PROJECT_DIR$/debugger/dialog.h" afterDir="false" />
<change afterPath="$PROJECT_DIR$/debugger/memory_view.c" afterDir="false" />
<change afterPath="$PROJECT_DIR$/debugger/memory_view.h" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" /> <change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/CMakeLists.txt" beforeDir="false" afterPath="$PROJECT_DIR$/CMakeLists.txt" afterDir="false" /> <change beforePath="$PROJECT_DIR$/debugger/debugger.c" beforeDir="false" afterPath="$PROJECT_DIR$/debugger/debugger.c" afterDir="false" />
<change beforePath="$PROJECT_DIR$/conandata.yml" beforeDir="false" afterPath="$PROJECT_DIR$/conandata.yml" afterDir="false" /> <change beforePath="$PROJECT_DIR$/debugger/dialog.c" beforeDir="false" afterPath="$PROJECT_DIR$/debugger/dialog.c" afterDir="false" />
<change beforePath="$PROJECT_DIR$/main.c" beforeDir="false" afterPath="$PROJECT_DIR$/main.c" afterDir="false" /> <change beforePath="$PROJECT_DIR$/debugger/dialog.h" beforeDir="false" afterPath="$PROJECT_DIR$/debugger/dialog.h" afterDir="false" />
<change beforePath="$PROJECT_DIR$/debugger/memory_view.c" beforeDir="false" afterPath="$PROJECT_DIR$/debugger/memory_view.c" afterDir="false" />
<change beforePath="$PROJECT_DIR$/debugger/memory_view.h" beforeDir="false" afterPath="$PROJECT_DIR$/debugger/memory_view.h" afterDir="false" />
</list> </list>
<option name="SHOW_DIALOG" value="false" /> <option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" /> <option name="HIGHLIGHT_CONFLICTS" value="true" />
@ -265,7 +260,7 @@
<option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" /> <option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
</method> </method>
</configuration> </configuration>
<configuration name="NESEmulator (Term)" type="CMakeRunConfiguration" factoryName="Application" PROGRAM_PARAMS="-- $CMakeCurrentBuildDir$/NESEmulator" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="true" PASS_PARENT_ENVS_2="true" PROJECT_NAME="NESEmulator" TARGET_NAME="NESEmulator" CONFIG_NAME="Debug" RUN_PATH="/usr/bin/gnome-terminal"> <configuration name="NESEmulator (Term)" type="CMakeRunConfiguration" factoryName="Application" PROGRAM_PARAMS="-- $CMakeCurrentBuildDir$/NESEmulator" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="NESEmulator" TARGET_NAME="NESEmulator" CONFIG_NAME="Debug" RUN_PATH="/usr/bin/gnome-terminal">
<method v="2"> <method v="2">
<option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" /> <option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
</method> </method>
@ -461,7 +456,7 @@
<workItem from="1704501418104" duration="8204000" /> <workItem from="1704501418104" duration="8204000" />
<workItem from="1704569084127" duration="8903000" /> <workItem from="1704569084127" duration="8903000" />
<workItem from="1704582152049" duration="7863000" /> <workItem from="1704582152049" duration="7863000" />
<workItem from="1704660072645" duration="2354000" /> <workItem from="1704660072645" duration="15399000" />
</task> </task>
<task id="LOCAL-00001" summary="Cpu opcodes implementation"> <task id="LOCAL-00001" summary="Cpu opcodes implementation">
<option name="closed" value="true" /> <option name="closed" value="true" />
@ -495,7 +490,15 @@
<option name="project" value="LOCAL" /> <option name="project" value="LOCAL" />
<updated>1704569231622</updated> <updated>1704569231622</updated>
</task> </task>
<option name="localTasksCounter" value="5" /> <task id="LOCAL-00005" summary="Memory debugger">
<option name="closed" value="true" />
<created>1704662439962</created>
<option name="number" value="00005" />
<option name="presentableId" value="LOCAL-00005" />
<option name="project" value="LOCAL" />
<updated>1704662439962</updated>
</task>
<option name="localTasksCounter" value="6" />
<servers /> <servers />
</component> </component>
<component name="TypeScriptGeneratedFilesManager"> <component name="TypeScriptGeneratedFilesManager">
@ -513,7 +516,8 @@
<MESSAGE value="Gitignore" /> <MESSAGE value="Gitignore" />
<MESSAGE value="Added logging for operand decoding" /> <MESSAGE value="Added logging for operand decoding" />
<MESSAGE value="Things" /> <MESSAGE value="Things" />
<option name="LAST_COMMIT_MESSAGE" value="Things" /> <MESSAGE value="Memory debugger" />
<option name="LAST_COMMIT_MESSAGE" value="Memory debugger" />
</component> </component>
<component name="XDebuggerManager"> <component name="XDebuggerManager">
<breakpoint-manager> <breakpoint-manager>

View File

@ -10,8 +10,6 @@
#include "dialog.h" #include "dialog.h"
#define CTRL_KEY_EXIT 3 #define CTRL_KEY_EXIT 3
#define CTRL_KEY_UP 65
#define CTRL_KEY_DOWN 66
#define CTRL_KEY_G 103 #define CTRL_KEY_G 103
MemoryView view; MemoryView view;
@ -23,14 +21,8 @@ void create_window() {
initscr(); initscr();
raw(); raw();
noecho(); noecho();
// wborder(window, '|', '|', '-', '-', '+', '+', '+', '+'); curs_set(0);
} keypad(stdscr, true);
void destroy_window() {
endwin();
}
void some_func(char* user_input) {
} }
void start_debugger(System *system) { void start_debugger(System *system) {
@ -43,16 +35,33 @@ void start_debugger(System *system) {
int keycode; int keycode;
while ((keycode = getch()) != CTRL_KEY_EXIT) { while ((keycode = getch()) != CTRL_KEY_EXIT) {
if (keycode == CTRL_KEY_UP) { if (keycode == KEY_UP) {
memory_view_scroll(&view, -1, system->ram); memory_view_move_cursor(&view, 0, -1);
} }
if (keycode == CTRL_KEY_DOWN) { if (keycode == KEY_DOWN) {
memory_view_scroll(&view, 1, system->ram); memory_view_move_cursor(&view, 0, 1);
}
if (keycode == KEY_LEFT) {
memory_view_move_cursor(&view, -1, 0);
}
if (keycode == KEY_RIGHT) {
memory_view_move_cursor(&view, 1, 0);
} }
if (keycode == CTRL_KEY_G) { if (keycode == CTRL_KEY_G) {
Dialog dialog = dialog_create("Goto Address", &some_func); Dialog dialog = dialog_create("Goto Address");
bool cancelled = false;
address input = dialog_get_address(&dialog, &cancelled);
dialog_remove(&dialog);
if (!cancelled) {
memory_view_goto(&view, input);
memory_view_set_cursor_addr(&view, input);
}
} }
update_panels(); update_panels();

View File

@ -5,17 +5,84 @@
#include <string.h> #include <string.h>
#include "dialog.h" #include "dialog.h"
Dialog dialog_create(char *message, void (*callback)(char *user_input)) { #define DIALOG_KEY_CONFIRM 10
Dialog dialog; #define DIALOG_KEY_EXIT 27
int width = (int) strlen(message) + 2; #define DIALOG_KEY_DELETE 127
#define DIALOG_KEY_DIGIT_MIN 48
#define DIALOG_KEY_DIGIT_MAX 57
#define DIALOG_KEY_ALPHA_MIN 97
#define DIALOG_KEY_ALPHA_MAX 102
WINDOW *window = newwin(3, width, 2, 2); Dialog dialog_create(char *message) {
Dialog dialog;
int termHeight = getmaxy(stdscr);
int termWidth = getmaxx(stdscr);
int height = 3;
int width = (int) strlen(message) + 2;
if (width % 2 == 1) {
width += 1;
}
int y = termHeight / 2 - (height / 2);
int x = termWidth / 2 - (width / 2);
WINDOW *window = newwin(height, width, y, x);
box(window, 0, 0); box(window, 0, 0);
mvwprintw(window, 0, 1, "%s", message); mvwprintw(window, 0, 1, "%s", message);
wmove(window, 1, 1);
dialog.panel = new_panel(window); dialog.panel = new_panel(window);
dialog.callback = callback;
return dialog; return dialog;
} }
address dialog_get_address(Dialog *dialog, bool *cancelled) {
int input_length = 0;
address out = 0;
int keycode;
while ((keycode = wgetch(dialog->panel->win)) != DIALOG_KEY_CONFIRM) {
if (keycode == DIALOG_KEY_EXIT) {
*cancelled = true;
return 0;
}
if (input_length > 0 && keycode == DIALOG_KEY_DELETE) {
int offset = 16 - (4 * input_length);
address mask = 0xf << offset;
out &= ~mask;
input_length--;
mvwprintw(dialog->panel->win, 1, 1 + input_length, " ");
wmove(dialog->panel->win, 1, 1 + input_length);
}
if (input_length < 4 && keycode >= DIALOG_KEY_DIGIT_MIN && keycode <= DIALOG_KEY_ALPHA_MAX) {
int digit = keycode - DIALOG_KEY_DIGIT_MIN; // 0-9
if (digit > 9) {
if (keycode >= DIALOG_KEY_ALPHA_MIN) { // A-F
digit -= DIALOG_KEY_ALPHA_MIN - DIALOG_KEY_DIGIT_MAX - 1;
} else {
// Anything else
continue;
}
}
int offset = 12 - (4 * input_length);
out += digit << offset;
mvwprintw(dialog->panel->win, 1, 1 + input_length, "%c", keycode);
input_length++;
}
}
return out;
}
void dialog_remove(Dialog *dialog) {
del_panel(dialog->panel);
}

View File

@ -6,13 +6,16 @@
#define NESEMULATOR_DIALOG_H #define NESEMULATOR_DIALOG_H
#include <panel.h> #include <panel.h>
#include "../include/types.h"
typedef struct dialog { typedef struct dialog {
PANEL *panel; PANEL *panel;
void (*callback)(char *user_input);
} Dialog; } Dialog;
Dialog dialog_create(char *message, void (*callback)(char *user_input)); Dialog dialog_create(char *message);
address dialog_get_address(Dialog *dialog, bool *cancelled);
void dialog_remove(Dialog *dialog);
#endif //NESEMULATOR_DIALOG_H #endif //NESEMULATOR_DIALOG_H

View File

@ -7,6 +7,29 @@
// Created by william on 1/6/24. // Created by william on 1/6/24.
// //
void memory_view_highlight_cursor(MemoryView *view) {
int win_x = 8 + view->cursor_x * 3;
int win_y = 2 + view->cursor_y;
mvwchgat(view->panel->win, win_y, win_x, 2, A_REVERSE, 0, NULL);
}
void memory_view_set_cursor_pos(MemoryView *view, int x, int y) {
assert(x >= 0);
assert(x <= 0xf);
assert(y >= 0);
assert(y <= 0xf);
int old_win_x = 8 + view->cursor_x * 3;
int old_win_y = 2 + view->cursor_y;
mvwchgat(view->panel->win, old_win_y, old_win_x, 2, A_NORMAL, 0, NULL);
view->cursor_x = (char) x;
view->cursor_y = (char) y;
memory_view_highlight_cursor(view);
}
void write_line(WINDOW *window, int line, address base_address, byte *data) { void write_line(WINDOW *window, int line, address base_address, byte *data) {
mvwprintw(window, line + 2, 1, "[%04x]", base_address); mvwprintw(window, line + 2, 1, "[%04x]", base_address);
@ -23,21 +46,25 @@ void memory_view_init(MemoryView *view, ram ram) {
mvwprintw(window, 1, 1, " +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +a +b +c +d +e +f"); 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->panel = new_panel(window);
view->base_address = 0xfc00; view->ram = ram;
view->base_address = 0x0000;
view->cursor_x = 0;
view->cursor_y = 0;
memory_view_print(view, ram); memory_view_print(view);
memory_view_set_cursor_pos(view, 0, 0);
} }
void memory_view_print(MemoryView *view, ram ram) { void memory_view_print(MemoryView *view) {
for (int line = 0; line <= MEMORY_VIEW_LINE_COUNT; line++) { for (int line = 0; line <= MEMORY_VIEW_LINE_COUNT; line++) {
address line_address = view->base_address + line * (MEMORY_VIEW_LINE_BYTE_COUNT + 1); address line_address = view->base_address + line * (MEMORY_VIEW_LINE_BYTE_COUNT + 1);
byte *data = &ram[line_address]; byte *data = &view->ram[line_address];
write_line(view->panel->win, line, line_address, data); write_line(view->panel->win, line, line_address, data);
} }
} }
void memory_view_goto(MemoryView *view, address target, ram ram) { void memory_view_goto(MemoryView *view, address target) {
assert(target < RAM_SIZE); assert(target < RAM_SIZE);
address max_base_address = RAM_SIZE - MEMORY_VIEW_BYTE_COUNT; address max_base_address = RAM_SIZE - MEMORY_VIEW_BYTE_COUNT;
@ -45,11 +72,12 @@ void memory_view_goto(MemoryView *view, address target, ram ram) {
target = max_base_address; target = max_base_address;
} }
view->base_address = target; address line_addr = target & 0xfff0;
memory_view_print(view, ram); view->base_address = line_addr;
memory_view_print(view);
} }
void memory_view_scroll(MemoryView *view, char direction, ram ram) { void memory_view_scroll(MemoryView *view, char direction) {
assert(direction == MEMORY_VIEW_DIRECTION_DOWN || direction == MEMORY_VIEW_DIRECTION_UP); assert(direction == MEMORY_VIEW_DIRECTION_DOWN || direction == MEMORY_VIEW_DIRECTION_UP);
int offset = 0; int offset = 0;
@ -61,5 +89,30 @@ void memory_view_scroll(MemoryView *view, char direction, ram ram) {
} }
address target = view->base_address + offset; address target = view->base_address + offset;
memory_view_goto(view, target, ram); memory_view_goto(view, target);
}
void memory_view_move_cursor(MemoryView *view, char horizontal, char vertical) {
if (horizontal == 1 && view->cursor_x == 0xf ||
horizontal == -1 && view->cursor_x == 0) {
return;
}
if (vertical == 1 && view->cursor_y == 0xf ||
vertical == -1 && view->cursor_y == 0) {
memory_view_scroll(view, vertical);
return;
}
int target_x = view->cursor_x + horizontal;
int target_y = view->cursor_y + vertical;
memory_view_set_cursor_pos(view, target_x, target_y);
}
void memory_view_set_cursor_addr(MemoryView *view, address target) {
int view_byte = target - view->base_address;
int x = view_byte & 0x0f;
int y = (view_byte & 0xf0) >> 4;
memory_view_set_cursor_pos(view, x, y);
} }

View File

@ -15,19 +15,26 @@
#define MEMORY_VIEW_BYTE_COUNT 0xff #define MEMORY_VIEW_BYTE_COUNT 0xff
#define MEMORY_VIEW_DIRECTION_UP 1 #define MEMORY_VIEW_DIRECTION_UP 1
#define MEMORY_VIEW_DIRECTION_DOWN -1 #define MEMORY_VIEW_DIRECTION_DOWN (-1)
typedef struct memory_view { typedef struct memory_view {
PANEL *panel; PANEL *panel;
byte *ram;
address base_address; address base_address;
char cursor_x;
char cursor_y;
} MemoryView; } MemoryView;
void memory_view_init(MemoryView *view, ram ram); void memory_view_init(MemoryView *view, ram ram);
void memory_view_print(MemoryView *view, ram ram); void memory_view_print(MemoryView *view);
void memory_view_goto(MemoryView *view, address target, ram ram); void memory_view_goto(MemoryView *view, address target);
void memory_view_scroll(MemoryView *view, char direction, ram ram); void memory_view_scroll(MemoryView *view, char direction);
void memory_view_move_cursor(MemoryView *view, char horizontal, char vertical);
void memory_view_set_cursor_addr(MemoryView *view, address target);
#endif //NESEMULATOR_MEMORY_VIEW_H #endif //NESEMULATOR_MEMORY_VIEW_H