This commit is contained in:
parent
e3839dc9d6
commit
4148f80360
|
@ -7,7 +7,8 @@ add_library(DEBUG
|
|||
cursor.c
|
||||
cursor.h
|
||||
window.c
|
||||
window.h)
|
||||
window.h
|
||||
keys.h)
|
||||
|
||||
find_package(Curses)
|
||||
|
||||
|
|
|
@ -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(¤t_window->cursor);
|
||||
current_window = &windows[window_index];
|
||||
cursor_enable(¤t_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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
4
main.c
|
@ -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);
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
|
Loading…
Reference in New Issue