This commit is contained in:
william 2024-01-16 15:46:22 -05:00
parent 091a5e3bf5
commit e3839dc9d6
15 changed files with 235 additions and 108 deletions

View File

@ -6,13 +6,15 @@ add_subdirectory(ppu)
add_subdirectory(mappers) add_subdirectory(mappers)
add_subdirectory(rom) add_subdirectory(rom)
add_subdirectory(debugger) add_subdirectory(debugger)
add_subdirectory(utils)
list(APPEND EXTRA_INCLUDES list(APPEND EXTRA_INCLUDES
"${PROJECT_SOURCE_DIR}/cpu" "${PROJECT_SOURCE_DIR}/cpu"
"${PROJECT_SOURCE_DIR}/ppu" "${PROJECT_SOURCE_DIR}/ppu"
"${PROJECT_SOURCE_DIR}/mappers" "${PROJECT_SOURCE_DIR}/mappers"
"${PROJECT_SOURCE_DIR}/rom" "${PROJECT_SOURCE_DIR}/rom"
"${PROJECT_SOURCE_DIR}/debugger") "${PROJECT_SOURCE_DIR}/debugger"
"${PROJECT_SOURCE_DIR}/utils")
add_executable(NESEmulator main.c add_executable(NESEmulator main.c
system.c system.c
@ -21,7 +23,7 @@ add_executable(NESEmulator main.c
find_package(log.c) find_package(log.c)
target_link_libraries(NESEmulator CPU PPU Mappers ROM DEBUG log.c::log.c) target_link_libraries(NESEmulator CPU PPU Mappers ROM DEBUG UTILS log.c::log.c)
target_include_directories(NESEmulator PUBLIC target_include_directories(NESEmulator PUBLIC
"${PROJECT_BINARY_DIR}" "${PROJECT_BINARY_DIR}"
${EXTRA_INCLUDES}) ${EXTRA_INCLUDES})

View File

@ -19,14 +19,6 @@
#define CPU_STACK_ADDR 0x0100 #define CPU_STACK_ADDR 0x0100
/**
* Gets the name of the type of an operand, for logging.
*
* @param operand The operand
* @return The name of the operand's type.
*/
//char *operand_name(Operand *operand);
/** /**
* Gets a flag from the CPU registers. * Gets a flag from the CPU registers.
* *

View File

@ -1231,6 +1231,7 @@ AddressingMode get_op_addr_mode(byte op_code) {
case 0x22: case 0x22:
case 0x28: case 0x28:
case 0x32: case 0x32:
case 0x38:
case 0x3a: case 0x3a:
case 0x40: case 0x40:
case 0x42: case 0x42:

View File

@ -7,12 +7,8 @@
#include <stdlib.h> #include <stdlib.h>
#include "debugger.h" #include "debugger.h"
#include "memory_view.h" #include "memory_view.h"
#include "dialog.h"
#include "program_view.h" #include "program_view.h"
#define CTRL_KEY_EXIT 3
#define CTRL_KEY_G 103
void create_window() { void create_window() {
setenv("TERMINFO", "/usr/share/terminfo", 1); setenv("TERMINFO", "/usr/share/terminfo", 1);
setenv("TERM", "xterm", 1); setenv("TERM", "xterm", 1);
@ -26,45 +22,40 @@ void create_window() {
void start_debugger(System *system) { void start_debugger(System *system) {
InteractWindow windows[2]; InteractWindow windows[2];
InteractWindow *current_window; size_t window_index = 0;
InteractWindow *current_window = &windows[window_index];
create_window(); create_window();
memory_view_init(&windows[0], system->ram, 0, 0); memory_view_init(&windows[0], system->ram, 0, 0);
program_view_init(&windows[1], system->ram, MEMORY_VIEW_WIDTH, 0); program_view_init(&windows[1], system, MEMORY_VIEW_WIDTH, 0);
cursor_enable(&current_window->cursor);
update_panels(); update_panels();
doupdate(); doupdate();
int keycode; int keycode;
while ((keycode = getch()) != CTRL_KEY_EXIT) { while ((keycode = getch()) != CTRL_KEY_EXIT) {
if (keycode == KEY_UP) { if (keycode == CTRL_KEY_TOGGLE) {
window_index++;
if (window_index > 1) {
window_index = 0;
}
cursor_disable(&current_window->cursor);
current_window = &windows[window_index];
cursor_enable(&current_window->cursor);
} else if (keycode == KEY_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) {
if (keycode == KEY_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) {
if (keycode == KEY_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) {
if (keycode == KEY_RIGHT) {
current_window->handle_cursor_move(current_window, CURSOR_OFFSET_RIGHT, 0); current_window->handle_cursor_move(current_window, CURSOR_OFFSET_RIGHT, 0);
} } else {
current_window->handle_key_down(current_window, keycode);
if (keycode == CTRL_KEY_G) {
Dialog dialog = dialog_create("Goto Address");
bool cancelled = false;
address input = dialog_get_address(&dialog, &cancelled);
dialog_remove(&dialog);
if (!cancelled) {
memory_view_goto(&m_view, input);
memory_view_cursor_set_addr(&m_view, input);
}
} }
update_panels(); update_panels();

View File

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

View File

@ -1,6 +1,7 @@
#include <assert.h> #include <assert.h>
#include <stdlib.h> #include <stdlib.h>
#include "memory_view.h" #include "memory_view.h"
#include "dialog.h"
// //
// Created by william on 6/1/24. // Created by william on 6/1/24.
@ -20,12 +21,22 @@ void memory_view_cursor_init(MemoryView *view) {
cursor->min_y = 2; cursor->min_y = 2;
cursor->multiplier_x = 3; cursor->multiplier_x = 3;
cursor->width = 2; cursor->width = 2;
cursor_enable(cursor);
} }
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) {
Dialog dialog = dialog_create("Goto Address");
bool cancelled = false;
address input = dialog_get_address(&dialog, &cancelled);
dialog_remove(&dialog);
if (!cancelled) {
MemoryView *view = window->view;
memory_view_goto(view, input);
memory_view_cursor_set_addr(view, input);
}
}
} }
void memory_view_init(InteractWindow *interact, ram ram, int x, int y) { void memory_view_init(InteractWindow *interact, ram ram, int x, int y) {

View File

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

View File

@ -3,40 +3,41 @@
// //
#include <stdlib.h> #include <stdlib.h>
#include <assert.h>
#include "program_view.h" #include "program_view.h"
#include "../cpu/op.h" #include "../cpu/op.h"
#include "memory_view.h"
void decode_operands(DebugOperand *operands, const byte *ram, address start_addr) { void decode_operands(ProgramView *view) {
int pc = start_addr; int pc = PROGRAM_VIEW_BASE_ADDR;
for (int i = 0; i < 10; i++) { while (pc < 0xfffa) {
DebugOperand operand; DebugOperand *operand = malloc(sizeof(DebugOperand));
byte op_code = ram[pc]; if (operand == NULL) {
perror("Failed to allocate memory for debug operand");
exit(EXIT_FAILURE);
}
operand.addr = pc; byte op_code = view->ram[pc];
operand.op_code = op_code; operand->addr = pc;
operand.addr_mode = get_op_addr_mode(op_code); operand->op_code = op_code;
operand->addr_mode = get_op_addr_mode(op_code);
pc += 1; pc += 1;
if (operand.addr_mode == ADDR_MODE_ACCUMULATOR || operand.addr_mode == ADDR_MODE_IMPLICIT) { if (operand->addr_mode == ADDR_MODE_ACCUMULATOR || operand->addr_mode == ADDR_MODE_IMPLICIT) {
operand.type = OPERAND_TYPE_ACCUMULATOR; operand->value = 0;
operand.value = 0; } else if (operand->addr_mode == ADDR_MODE_RELATIVE || operand->addr_mode == ADDR_MODE_IMMEDIATE ||
} else if (operand.addr_mode == ADDR_MODE_IMMEDIATE) { operand->addr_mode == ADDR_MODE_ZERO_PAGE || operand->addr_mode == ADDR_MODE_ZERO_PAGE_INDEXED_X ||
operand.type = OPERAND_TYPE_IMMEDIATE; operand->addr_mode == ADDR_MODE_ZERO_PAGE_INDEXED_Y) {
operand.value = ram[pc]; operand->value = view->ram[pc];
pc += 1;
} else if (operand.addr_mode == ADDR_MODE_RELATIVE) {
operand.type = OPERAND_TYPE_ADDRESS;
operand.value = ram[pc];
pc += 1; pc += 1;
} else { } else {
operand.type = OPERAND_TYPE_ADDRESS; operand->value = view->ram[pc];
operand.value = ram[pc]; operand->value += view->ram[pc + 1] << 8;
operand.value += ram[pc + 1] << 8;
pc += 2; pc += 2;
} }
operands[i] = operand; linked_list_add(&view->operands, operand);
} }
} }
@ -75,25 +76,48 @@ 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);
window_inter_print(view->window, 0, line, "%04x:", operand->addr); window_inter_print(view->window, 0, line, "%04x:", operand->addr);
window_inter_print(view->window, 6, line, "%s", op_name); window_inter_print(view->window, 6, line, "(%02x) %s", operand->op_code, op_name);
char *format = get_addr_mode_format_str(operand->addr_mode); char *format = get_addr_mode_format_str(operand->addr_mode);
window_inter_print(view->window, 10, line, format, operand->value); window_inter_print(view->window, 16, line, format, operand->value);
} }
void program_view_print(ProgramView *view, DebugOperand *operands) { void program_view_print(ProgramView *view) {
for (int line = 0; line < 10; line++) { LinkedListNode *current_node = view->current_operand_node;
program_view_write_line(view, line, &operands[line]); int line = 0;
while (line <= 0xf && current_node != NULL) {
program_view_write_line(view, line, (DebugOperand *) current_node->data);
current_node = current_node->next;
line++;
} }
} }
void program_view_cursor_init(ProgramView *view) { void program_view_cursor_init(ProgramView *view) {
window_inter_cursor_init(view->window, 0, 10); window_inter_cursor_init(view->window, 0, 0xf);
view->window->cursor.width = PROGRAM_VIEW_WIDTH - 2; view->window->cursor.width = PROGRAM_VIEW_WIDTH - 2;
cursor_enable(&view->window->cursor);
} }
void program_view_handle_cursor_move(InteractWindow *window, int horizontal, int vertical) { 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;
}
program_view_print(view);
}
void pv_handle_cursor_move(InteractWindow *window, int horizontal, int vertical) {
ProgramView *view = (ProgramView *) window->view;
if (vertical == CURSOR_OFFSET_DOWN && view->window->cursor.pos_y == 0xf ||
vertical == CURSOR_OFFSET_UP && view->window->cursor.pos_y == 0) {
// Scroll the view
pv_scroll(view, vertical);
}
cursor_move(&window->cursor, horizontal, vertical); cursor_move(&window->cursor, horizontal, vertical);
} }
@ -101,19 +125,33 @@ void program_view_handle_key_down(InteractWindow *window, int keycode) {
} }
void program_view_init(InteractWindow *interact, ram ram, int x, int y) { void pv_deinit(InteractWindow *window) {
ProgramView *view = (ProgramView *) window->view;
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)); ProgramView *view = malloc(sizeof(ProgramView));
view->window = interact; view->window = interact;
view->ram = ram; view->ram = system->ram;
view->pc = &system->cpu.program_counter;
view->operands = linked_list_init();
interact->view = view; interact->view = view;
interact->handle_cursor_move = &program_view_handle_cursor_move; interact->handle_cursor_move = &pv_handle_cursor_move;
interact->handle_key_down = &program_view_handle_key_down; interact->handle_key_down = &program_view_handle_key_down;
interact->deinit = &pv_deinit;
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");
DebugOperand operands[10]; decode_operands(view);
decode_operands(&operands[0], ram, 0xc004); view->current_operand_node = linked_list_get_if(&view->operands, &pv_predicate_operand_by_addr, view->pc);
program_view_print(view, &operands[0]); program_view_print(view);
program_view_cursor_init(view); program_view_cursor_init(view);
} }

View File

@ -10,24 +10,27 @@
#include "../cpu/decoding.h" #include "../cpu/decoding.h"
#include "cursor.h" #include "cursor.h"
#include "window.h" #include "window.h"
#include "../utils/linked_list.h"
#define PROGRAM_VIEW_HEIGHT 19 #define PROGRAM_VIEW_HEIGHT 19
#define PROGRAM_VIEW_WIDTH 42 #define PROGRAM_VIEW_WIDTH 42
#define PROGRAM_VIEW_BASE_ADDR 0x0000
typedef struct program_view {
InteractWindow *window;
byte *ram;
address base_address;
} ProgramView;
typedef struct debug_operand { typedef struct debug_operand {
address addr; address addr;
byte op_code; byte op_code;
AddressingMode addr_mode; AddressingMode addr_mode;
enum OperandType type;
word value; word value;
} DebugOperand; } DebugOperand;
void program_view_init(InteractWindow *interact, ram ram, int x, int y); typedef struct program_view {
InteractWindow *window;
byte *ram;
address *pc;
LinkedList operands;
LinkedListNode *current_operand_node;
} ProgramView;
void program_view_init(InteractWindow *interact, System *system, int x, int y);
#endif //NESEMULATOR_PROGRAM_VIEW_H #endif //NESEMULATOR_PROGRAM_VIEW_H

View File

@ -57,5 +57,9 @@ void window_inter_print(InteractWindow *window, int x, int y, const char *fmt, .
void window_inter_deinit(InteractWindow *window) { void window_inter_deinit(InteractWindow *window) {
assert(window->view != NULL); assert(window->view != NULL);
if (window->deinit != NULL) {
window->deinit(window);
}
free(window->view); free(window->view);
} }

View File

@ -22,6 +22,8 @@ typedef struct interact_window {
void (*handle_cursor_move)(struct interact_window *window, int horizontal, int vertical); void (*handle_cursor_move)(struct interact_window *window, int horizontal, int vertical);
void (*handle_key_down)(struct interact_window *window, int keycode); void (*handle_key_down)(struct interact_window *window, int keycode);
void (*deinit)(struct interact_window *window);
} InteractWindow; } InteractWindow;
/** /**

23
main.c
View File

@ -22,22 +22,6 @@
#include "include/rom.h" #include "include/rom.h"
#include "include/system.h" #include "include/system.h"
//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;
//}
int main() { int main() {
System system; System system;
@ -51,16 +35,15 @@ int main() {
return EXIT_FAILURE; return EXIT_FAILURE;
} }
system_start(&system);
start_debugger(&system); start_debugger(&system);
system_uninit(&system); system_uninit(&system);
return 0; return EXIT_SUCCESS;
//
// system_start(&system);
// system_loop(&system); // system_loop(&system);
// system_uninit(&system); // system_uninit(&system);
// return EXIT_SUCCESS;
// return win(); // return win();
} }

2
utils/CMakeLists.txt Normal file
View File

@ -0,0 +1,2 @@
add_library(UTILS
linked_list.c)

65
utils/linked_list.c Normal file
View File

@ -0,0 +1,65 @@
//
// Created by william on 1/16/24.
//
#include <stddef.h>
#include <malloc.h>
#include <stdlib.h>
#include <assert.h>
#include "linked_list.h"
LinkedList linked_list_init() {
LinkedList list;
list.head = NULL;
list.end = NULL;
return list;
}
void linked_list_add(LinkedList *list, void *data) {
LinkedListNode *node = malloc(sizeof(LinkedListNode));
if (node == NULL) {
perror("Failed to allocate memory for linked list node");
exit(EXIT_FAILURE);
}
node->data = data;
node->previous = list->end;
node->next = NULL;
if (list->head == NULL) {
list->head = node;
}
if (list->end != NULL) {
list->end->next = node;
}
list->end = node;
}
LinkedListNode *linked_list_get_if(LinkedList *list, bool(*predicate)(void *, void *), void *userdata) {
LinkedListNode *node = list->head;
while (node != NULL) {
if (predicate(node->data, userdata)) {
return node;
}
node = node->next;
}
return NULL;
}
void linked_list_uninit(LinkedList *list) {
assert(list != NULL);
LinkedListNode *node = list->head;
while (node != NULL) {
LinkedListNode *current_node = node;
node = node->next;
free(current_node->data);
free(current_node);
}
}

29
utils/linked_list.h Normal file
View File

@ -0,0 +1,29 @@
//
// Created by william on 1/16/24.
//
#include <stdbool.h>
#ifndef NESEMULATOR_LINKED_LIST_H
#define NESEMULATOR_LINKED_LIST_H
typedef struct linked_list_node {
struct linked_list_node *previous;
struct linked_list_node *next;
void *data;
} LinkedListNode;
typedef struct linked_list {
LinkedListNode *head;
LinkedListNode *end;
} LinkedList;
LinkedList linked_list_init();
void linked_list_add(LinkedList *list, void *data);
LinkedListNode *linked_list_get_if(LinkedList *list, bool(*predicate)(void *, void *), void* userdata);
void linked_list_uninit(LinkedList *list);
#endif //NESEMULATOR_LINKED_LIST_H