This commit is contained in:
william 2024-04-03 23:03:35 -04:00
parent e3839dc9d6
commit 4148f80360
12 changed files with 144 additions and 29 deletions

View File

@ -7,7 +7,8 @@ add_library(DEBUG
cursor.c
cursor.h
window.c
window.h)
window.h
keys.h)
find_package(Curses)

View File

@ -8,6 +8,7 @@
#include "debugger.h"
#include "memory_view.h"
#include "program_view.h"
#include "keys.h"
void create_window() {
setenv("TERMINFO", "/usr/share/terminfo", 1);
@ -36,8 +37,8 @@ void start_debugger(System *system) {
doupdate();
int keycode;
while ((keycode = getch()) != CTRL_KEY_EXIT) {
if (keycode == CTRL_KEY_TOGGLE) {
while ((keycode = getch()) != KEY_EXIT_DEBUGGER) {
if (keycode == KEY_NEXT_VIEW) {
window_index++;
if (window_index > 1) {
window_index = 0;
@ -46,13 +47,13 @@ void start_debugger(System *system) {
cursor_disable(&current_window->cursor);
current_window = &windows[window_index];
cursor_enable(&current_window->cursor);
} else if (keycode == KEY_UP) {
} else if (keycode == KEY_VIEW_UP) {
current_window->handle_cursor_move(current_window, 0, CURSOR_OFFSET_UP);
} else if (keycode == KEY_DOWN) {
} else if (keycode == KEY_VIEW_DOWN) {
current_window->handle_cursor_move(current_window, 0, CURSOR_OFFSET_DOWN);
} else if (keycode == KEY_LEFT) {
} else if (keycode == KEY_VIEW_LEFT) {
current_window->handle_cursor_move(current_window, CURSOR_OFFSET_LEFT, 0);
} else if (keycode == KEY_RIGHT) {
} else if (keycode == KEY_VIEW_RIGHT) {
current_window->handle_cursor_move(current_window, CURSOR_OFFSET_RIGHT, 0);
} else {
current_window->handle_key_down(current_window, keycode);

View File

@ -7,9 +7,6 @@
#include "../include/system.h"
#define CTRL_KEY_EXIT 3
#define CTRL_KEY_TOGGLE 116
void start_debugger(System *system);
#endif //NESEMULATOR_DEBUGGER_H

View File

@ -12,8 +12,21 @@ typedef struct dialog {
PANEL *panel;
} Dialog;
/**
* Creates a dialog box and present it to the user.
*
* @param message The message to show in the dialog
* @return The dialog instance
*/
Dialog dialog_create(char *message);
/**
* Gets the address typed by the user. Will block until the input has been confirmed by them.
*
* @param dialog A pointer to the dialog
* @param cancelled A boolean indicating if the user has cancelled its input
* @return The address typed by the user
*/
address dialog_get_address(Dialog *dialog, bool *cancelled);
void dialog_remove(Dialog *dialog);

18
debugger/keys.h Normal file
View File

@ -0,0 +1,18 @@
//
// Created by william on 2/22/24.
//
#include <curses.h>
#ifndef NESEMULATOR_KEYS_H
#define NESEMULATOR_KEYS_H
#define KEY_EXIT_DEBUGGER 3
#define KEY_GOTO 103
#define KEY_NEXT_VIEW 116
#define KEY_VIEW_DOWN KEY_DOWN
#define KEY_VIEW_LEFT KEY_LEFT
#define KEY_VIEW_RIGHT KEY_RIGHT
#define KEY_VIEW_UP KEY_UP
#endif //NESEMULATOR_KEYS_H

View File

@ -2,6 +2,7 @@
#include <stdlib.h>
#include "memory_view.h"
#include "dialog.h"
#include "keys.h"
//
// Created by william on 6/1/24.
@ -24,7 +25,7 @@ void memory_view_cursor_init(MemoryView *view) {
}
void memory_view_handle_key_down(InteractWindow *window, int keycode) {
if (keycode == MEMORY_VIEW_KEY_GOTO) {
if (keycode == KEY_GOTO) {
Dialog dialog = dialog_create("Goto Address");
bool cancelled = false;
@ -65,7 +66,7 @@ void memory_view_print(MemoryView *view) {
}
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;
if (target > max_base_address) {

View File

@ -15,7 +15,6 @@
#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;

View File

@ -7,6 +7,8 @@
#include "program_view.h"
#include "../cpu/op.h"
#include "memory_view.h"
#include "keys.h"
#include "dialog.h"
void decode_operands(ProgramView *view) {
int pc = PROGRAM_VIEW_BASE_ADDR;
@ -72,6 +74,18 @@ char *get_addr_mode_format_str(AddressingMode addr_mode) {
}
}
bool pv_predicate_operand_by_addr(void *data, void *userdata) {
DebugOperand *operand = (DebugOperand *) data;
address *addr = (address *) userdata;
return operand->addr == *addr;
}
int pv_predicate_operand_distance(void *data, void *userdata) {
DebugOperand *operand = (DebugOperand *) data;
address *addr = (address *) userdata;
return operand->addr - *addr;
}
void program_view_write_line(ProgramView *view, int line, DebugOperand *operand) {
char *op_name = get_op_code_name(operand->op_code);
@ -83,7 +97,7 @@ void program_view_write_line(ProgramView *view, int line, DebugOperand *operand)
}
void program_view_print(ProgramView *view) {
LinkedListNode *current_node = view->current_operand_node;
LinkedListNode *current_node = view->first_operand_node;
int line = 0;
while (line <= 0xf && current_node != NULL) {
program_view_write_line(view, line, (DebugOperand *) current_node->data);
@ -97,13 +111,30 @@ void program_view_cursor_init(ProgramView *view) {
view->window->cursor.width = PROGRAM_VIEW_WIDTH - 2;
}
void pv_goto(ProgramView *view, address target) {
assert(target <= RAM_SIZE);
LinkedListNode *match = linked_list_get_near(&view->operands, &pv_predicate_operand_distance, &target);
view->first_operand_node = match;
// Move the first node back until we do not overflow the NES memory
while (RAM_SIZE - target < 0xf) {
view->first_operand_node = view->first_operand_node->previous;
target--;
}
program_view_print(view);
}
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;
if (direction == CURSOR_OFFSET_UP && view->first_operand_node->previous != NULL) {
view->first_operand_node = view->first_operand_node->previous;
view->last_operand_node = view->last_operand_node->previous;
} else if (view->last_operand_node->next != NULL) {
view->first_operand_node = view->first_operand_node->next;
view->last_operand_node = view->last_operand_node->next;
}
program_view_print(view);
@ -122,7 +153,19 @@ void pv_handle_cursor_move(InteractWindow *window, int horizontal, int vertical)
}
void program_view_handle_key_down(InteractWindow *window, int keycode) {
if (keycode == KEY_GOTO) {
Dialog dialog = dialog_create("Goto Address");
bool cancelled = false;
address input = dialog_get_address(&dialog, &cancelled);
dialog_remove(&dialog);
if (!cancelled) {
ProgramView *view = window->view;
pv_goto(view, input);
cursor_set_pos(&view->window->cursor, 0, 0);
}
}
}
void pv_deinit(InteractWindow *window) {
@ -130,12 +173,6 @@ void pv_deinit(InteractWindow *window) {
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;
@ -150,7 +187,12 @@ void program_view_init(InteractWindow *interact, System *system, int x, int y) {
window_inter_init(interact, x, y, PROGRAM_VIEW_WIDTH, PROGRAM_VIEW_HEIGHT, "PROGRAM VIEW");
decode_operands(view);
view->current_operand_node = linked_list_get_if(&view->operands, &pv_predicate_operand_by_addr, view->pc);
view->first_operand_node = linked_list_get_if(&view->operands, &pv_predicate_operand_by_addr, view->pc);
LinkedListNode *last_node = view->first_operand_node;
for (int i = 0; i < 0xf; i++) {
last_node = last_node->next;
}
view->last_operand_node = last_node;
program_view_print(view);
program_view_cursor_init(view);

View File

@ -28,7 +28,8 @@ typedef struct program_view {
byte *ram;
address *pc;
LinkedList operands;
LinkedListNode *current_operand_node;
LinkedListNode *first_operand_node;
LinkedListNode *last_operand_node;
} ProgramView;
void program_view_init(InteractWindow *interact, System *system, int x, int y);

4
main.c
View File

@ -28,7 +28,7 @@ int main() {
log_set_level(LOG_INFO);
system_init(&system);
char *rom_path = "../test_roms/nestest.nes";
char *rom_path = "../test_roms/smb.nes";
if (!rom_load(rom_path, &system)) {
system_uninit(&system);
@ -37,11 +37,11 @@ int main() {
system_start(&system);
start_debugger(&system);
// system_loop(&system);
system_uninit(&system);
return EXIT_SUCCESS;
// system_loop(&system);
// system_uninit(&system);

View File

@ -51,6 +51,21 @@ LinkedListNode *linked_list_get_if(LinkedList *list, bool(*predicate)(void *, vo
return NULL;
}
LinkedListNode *linked_list_get_near(LinkedList *list, int(*predicate)(void *, void *), void *userdata) {
LinkedListNode *near_node = list->head;
int last_distance;
int current_distance = 0xffffffff >> 1;
do {
last_distance = current_distance;
near_node = near_node->next;
current_distance = predicate(near_node->data, userdata);
} while (current_distance < last_distance && near_node->next != NULL);
// After the loop, we have found the nearest node in the list, assuming there is only one point of convergence
return near_node;
}
void linked_list_uninit(LinkedList *list) {
assert(list != NULL);

View File

@ -18,12 +18,39 @@ typedef struct linked_list {
LinkedListNode *end;
} LinkedList;
/**
* Initializes a new linked list.
*
* @return The linked list instance
*/
LinkedList linked_list_init();
/**
* Adds data to a linked list.
*
* @param list The linked list
* @param data The data to add
*/
void linked_list_add(LinkedList *list, void *data);
LinkedListNode *linked_list_get_if(LinkedList *list, bool(*predicate)(void *, void *), void* userdata);
/**
* Searches for data corresponding to a predicate.
* The search will stop after reaching the first node matching the given predicate.
*
* @param list The list to search in
* @param predicate The predicate to match the data
* @param userdata Parameter to pass to the predicate
* @return The first node in the list matching the predicate
*/
LinkedListNode *linked_list_get_if(LinkedList *list, bool(*predicate)(void *, void *), void *userdata);
LinkedListNode *linked_list_get_near(LinkedList *list, int(*predicate)(void *, void *), void *userdata);
/**
* Deinitializes a linked list.
*
* @param list The list to deinitialize
*/
void linked_list_uninit(LinkedList *list);
#endif //NESEMULATOR_LINKED_LIST_H