This commit is contained in:
parent
e3839dc9d6
commit
4148f80360
|
@ -7,7 +7,8 @@ add_library(DEBUG
|
||||||
cursor.c
|
cursor.c
|
||||||
cursor.h
|
cursor.h
|
||||||
window.c
|
window.c
|
||||||
window.h)
|
window.h
|
||||||
|
keys.h)
|
||||||
|
|
||||||
find_package(Curses)
|
find_package(Curses)
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "debugger.h"
|
#include "debugger.h"
|
||||||
#include "memory_view.h"
|
#include "memory_view.h"
|
||||||
#include "program_view.h"
|
#include "program_view.h"
|
||||||
|
#include "keys.h"
|
||||||
|
|
||||||
void create_window() {
|
void create_window() {
|
||||||
setenv("TERMINFO", "/usr/share/terminfo", 1);
|
setenv("TERMINFO", "/usr/share/terminfo", 1);
|
||||||
|
@ -36,8 +37,8 @@ void start_debugger(System *system) {
|
||||||
doupdate();
|
doupdate();
|
||||||
|
|
||||||
int keycode;
|
int keycode;
|
||||||
while ((keycode = getch()) != CTRL_KEY_EXIT) {
|
while ((keycode = getch()) != KEY_EXIT_DEBUGGER) {
|
||||||
if (keycode == CTRL_KEY_TOGGLE) {
|
if (keycode == KEY_NEXT_VIEW) {
|
||||||
window_index++;
|
window_index++;
|
||||||
if (window_index > 1) {
|
if (window_index > 1) {
|
||||||
window_index = 0;
|
window_index = 0;
|
||||||
|
@ -46,13 +47,13 @@ void start_debugger(System *system) {
|
||||||
cursor_disable(¤t_window->cursor);
|
cursor_disable(¤t_window->cursor);
|
||||||
current_window = &windows[window_index];
|
current_window = &windows[window_index];
|
||||||
cursor_enable(¤t_window->cursor);
|
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);
|
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);
|
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);
|
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);
|
current_window->handle_cursor_move(current_window, CURSOR_OFFSET_RIGHT, 0);
|
||||||
} else {
|
} else {
|
||||||
current_window->handle_key_down(current_window, keycode);
|
current_window->handle_key_down(current_window, keycode);
|
||||||
|
|
|
@ -7,9 +7,6 @@
|
||||||
|
|
||||||
#include "../include/system.h"
|
#include "../include/system.h"
|
||||||
|
|
||||||
#define CTRL_KEY_EXIT 3
|
|
||||||
#define CTRL_KEY_TOGGLE 116
|
|
||||||
|
|
||||||
void start_debugger(System *system);
|
void start_debugger(System *system);
|
||||||
|
|
||||||
#endif //NESEMULATOR_DEBUGGER_H
|
#endif //NESEMULATOR_DEBUGGER_H
|
||||||
|
|
|
@ -12,8 +12,21 @@ typedef struct dialog {
|
||||||
PANEL *panel;
|
PANEL *panel;
|
||||||
} Dialog;
|
} 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);
|
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);
|
address dialog_get_address(Dialog *dialog, bool *cancelled);
|
||||||
|
|
||||||
void dialog_remove(Dialog *dialog);
|
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 <stdlib.h>
|
||||||
#include "memory_view.h"
|
#include "memory_view.h"
|
||||||
#include "dialog.h"
|
#include "dialog.h"
|
||||||
|
#include "keys.h"
|
||||||
|
|
||||||
//
|
//
|
||||||
// Created by william on 6/1/24.
|
// 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) {
|
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");
|
Dialog dialog = dialog_create("Goto Address");
|
||||||
|
|
||||||
bool cancelled = false;
|
bool cancelled = false;
|
||||||
|
@ -65,7 +66,7 @@ void memory_view_print(MemoryView *view) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void memory_view_goto(MemoryView *view, address target) {
|
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;
|
||||||
if (target > max_base_address) {
|
if (target > max_base_address) {
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
#define MEMORY_VIEW_LINE_COUNT 0xf
|
#define MEMORY_VIEW_LINE_COUNT 0xf
|
||||||
#define MEMORY_VIEW_LINE_BYTE_COUNT 0xf
|
#define MEMORY_VIEW_LINE_BYTE_COUNT 0xf
|
||||||
#define MEMORY_VIEW_BYTE_COUNT 0xff
|
#define MEMORY_VIEW_BYTE_COUNT 0xff
|
||||||
#define MEMORY_VIEW_KEY_GOTO 103
|
|
||||||
|
|
||||||
typedef struct memory_view {
|
typedef struct memory_view {
|
||||||
InteractWindow *window;
|
InteractWindow *window;
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
#include "program_view.h"
|
#include "program_view.h"
|
||||||
#include "../cpu/op.h"
|
#include "../cpu/op.h"
|
||||||
#include "memory_view.h"
|
#include "memory_view.h"
|
||||||
|
#include "keys.h"
|
||||||
|
#include "dialog.h"
|
||||||
|
|
||||||
void decode_operands(ProgramView *view) {
|
void decode_operands(ProgramView *view) {
|
||||||
int pc = PROGRAM_VIEW_BASE_ADDR;
|
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) {
|
void program_view_write_line(ProgramView *view, int line, DebugOperand *operand) {
|
||||||
char *op_name = get_op_code_name(operand->op_code);
|
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) {
|
void program_view_print(ProgramView *view) {
|
||||||
LinkedListNode *current_node = view->current_operand_node;
|
LinkedListNode *current_node = view->first_operand_node;
|
||||||
int line = 0;
|
int line = 0;
|
||||||
while (line <= 0xf && current_node != NULL) {
|
while (line <= 0xf && current_node != NULL) {
|
||||||
program_view_write_line(view, line, (DebugOperand *) current_node->data);
|
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;
|
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) {
|
void pv_scroll(ProgramView *view, int direction) {
|
||||||
assert(direction == CURSOR_OFFSET_DOWN || direction == CURSOR_OFFSET_UP);
|
assert(direction == CURSOR_OFFSET_DOWN || direction == CURSOR_OFFSET_UP);
|
||||||
|
|
||||||
if (direction == CURSOR_OFFSET_UP) {
|
if (direction == CURSOR_OFFSET_UP && view->first_operand_node->previous != NULL) {
|
||||||
view->current_operand_node = view->current_operand_node->previous;
|
view->first_operand_node = view->first_operand_node->previous;
|
||||||
} else {
|
view->last_operand_node = view->last_operand_node->previous;
|
||||||
view->current_operand_node = view->current_operand_node->next;
|
} 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);
|
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) {
|
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) {
|
void pv_deinit(InteractWindow *window) {
|
||||||
|
@ -130,12 +173,6 @@ void pv_deinit(InteractWindow *window) {
|
||||||
linked_list_uninit(&view->operands);
|
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) {
|
void program_view_init(InteractWindow *interact, System *system, int x, int y) {
|
||||||
ProgramView *view = malloc(sizeof(ProgramView));
|
ProgramView *view = malloc(sizeof(ProgramView));
|
||||||
view->window = interact;
|
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");
|
window_inter_init(interact, x, y, PROGRAM_VIEW_WIDTH, PROGRAM_VIEW_HEIGHT, "PROGRAM VIEW");
|
||||||
|
|
||||||
decode_operands(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_print(view);
|
||||||
program_view_cursor_init(view);
|
program_view_cursor_init(view);
|
||||||
|
|
|
@ -28,7 +28,8 @@ typedef struct program_view {
|
||||||
byte *ram;
|
byte *ram;
|
||||||
address *pc;
|
address *pc;
|
||||||
LinkedList operands;
|
LinkedList operands;
|
||||||
LinkedListNode *current_operand_node;
|
LinkedListNode *first_operand_node;
|
||||||
|
LinkedListNode *last_operand_node;
|
||||||
} ProgramView;
|
} ProgramView;
|
||||||
|
|
||||||
void program_view_init(InteractWindow *interact, System *system, int x, int y);
|
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);
|
log_set_level(LOG_INFO);
|
||||||
system_init(&system);
|
system_init(&system);
|
||||||
|
|
||||||
char *rom_path = "../test_roms/nestest.nes";
|
char *rom_path = "../test_roms/smb.nes";
|
||||||
|
|
||||||
if (!rom_load(rom_path, &system)) {
|
if (!rom_load(rom_path, &system)) {
|
||||||
system_uninit(&system);
|
system_uninit(&system);
|
||||||
|
@ -37,11 +37,11 @@ int main() {
|
||||||
|
|
||||||
system_start(&system);
|
system_start(&system);
|
||||||
start_debugger(&system);
|
start_debugger(&system);
|
||||||
|
// system_loop(&system);
|
||||||
|
|
||||||
system_uninit(&system);
|
system_uninit(&system);
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
|
|
||||||
// system_loop(&system);
|
|
||||||
// system_uninit(&system);
|
// system_uninit(&system);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,21 @@ LinkedListNode *linked_list_get_if(LinkedList *list, bool(*predicate)(void *, vo
|
||||||
return NULL;
|
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) {
|
void linked_list_uninit(LinkedList *list) {
|
||||||
assert(list != NULL);
|
assert(list != NULL);
|
||||||
|
|
||||||
|
|
|
@ -18,12 +18,39 @@ typedef struct linked_list {
|
||||||
LinkedListNode *end;
|
LinkedListNode *end;
|
||||||
} LinkedList;
|
} LinkedList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a new linked list.
|
||||||
|
*
|
||||||
|
* @return The linked list instance
|
||||||
|
*/
|
||||||
LinkedList linked_list_init();
|
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);
|
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);
|
void linked_list_uninit(LinkedList *list);
|
||||||
|
|
||||||
#endif //NESEMULATOR_LINKED_LIST_H
|
#endif //NESEMULATOR_LINKED_LIST_H
|
||||||
|
|
Loading…
Reference in New Issue