This commit is contained in:
parent
091a5e3bf5
commit
e3839dc9d6
|
@ -6,13 +6,15 @@ add_subdirectory(ppu)
|
|||
add_subdirectory(mappers)
|
||||
add_subdirectory(rom)
|
||||
add_subdirectory(debugger)
|
||||
add_subdirectory(utils)
|
||||
|
||||
list(APPEND EXTRA_INCLUDES
|
||||
"${PROJECT_SOURCE_DIR}/cpu"
|
||||
"${PROJECT_SOURCE_DIR}/ppu"
|
||||
"${PROJECT_SOURCE_DIR}/mappers"
|
||||
"${PROJECT_SOURCE_DIR}/rom"
|
||||
"${PROJECT_SOURCE_DIR}/debugger")
|
||||
"${PROJECT_SOURCE_DIR}/debugger"
|
||||
"${PROJECT_SOURCE_DIR}/utils")
|
||||
|
||||
add_executable(NESEmulator main.c
|
||||
system.c
|
||||
|
@ -21,7 +23,7 @@ add_executable(NESEmulator main.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
|
||||
"${PROJECT_BINARY_DIR}"
|
||||
${EXTRA_INCLUDES})
|
||||
|
|
|
@ -19,14 +19,6 @@
|
|||
|
||||
#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.
|
||||
*
|
||||
|
|
1
cpu/op.c
1
cpu/op.c
|
@ -1231,6 +1231,7 @@ AddressingMode get_op_addr_mode(byte op_code) {
|
|||
case 0x22:
|
||||
case 0x28:
|
||||
case 0x32:
|
||||
case 0x38:
|
||||
case 0x3a:
|
||||
case 0x40:
|
||||
case 0x42:
|
||||
|
|
|
@ -7,12 +7,8 @@
|
|||
#include <stdlib.h>
|
||||
#include "debugger.h"
|
||||
#include "memory_view.h"
|
||||
#include "dialog.h"
|
||||
#include "program_view.h"
|
||||
|
||||
#define CTRL_KEY_EXIT 3
|
||||
#define CTRL_KEY_G 103
|
||||
|
||||
void create_window() {
|
||||
setenv("TERMINFO", "/usr/share/terminfo", 1);
|
||||
setenv("TERM", "xterm", 1);
|
||||
|
@ -26,45 +22,40 @@ void create_window() {
|
|||
|
||||
void start_debugger(System *system) {
|
||||
InteractWindow windows[2];
|
||||
InteractWindow *current_window;
|
||||
size_t window_index = 0;
|
||||
InteractWindow *current_window = &windows[window_index];
|
||||
|
||||
create_window();
|
||||
|
||||
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(¤t_window->cursor);
|
||||
|
||||
update_panels();
|
||||
doupdate();
|
||||
|
||||
int keycode;
|
||||
while ((keycode = getch()) != CTRL_KEY_EXIT) {
|
||||
if (keycode == KEY_UP) {
|
||||
current_window->handle_cursor_move(current_window, 0, CURSOR_OFFSET_UP);
|
||||
}
|
||||
|
||||
if (keycode == KEY_DOWN) {
|
||||
current_window->handle_cursor_move(current_window, 0, CURSOR_OFFSET_DOWN);
|
||||
}
|
||||
|
||||
if (keycode == KEY_LEFT) {
|
||||
current_window->handle_cursor_move(current_window, CURSOR_OFFSET_LEFT, 0);
|
||||
}
|
||||
|
||||
if (keycode == KEY_RIGHT) {
|
||||
current_window->handle_cursor_move(current_window, CURSOR_OFFSET_RIGHT, 0);
|
||||
}
|
||||
|
||||
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);
|
||||
if (keycode == CTRL_KEY_TOGGLE) {
|
||||
window_index++;
|
||||
if (window_index > 1) {
|
||||
window_index = 0;
|
||||
}
|
||||
|
||||
cursor_disable(¤t_window->cursor);
|
||||
current_window = &windows[window_index];
|
||||
cursor_enable(¤t_window->cursor);
|
||||
} else if (keycode == KEY_UP) {
|
||||
current_window->handle_cursor_move(current_window, 0, CURSOR_OFFSET_UP);
|
||||
} else if (keycode == KEY_DOWN) {
|
||||
current_window->handle_cursor_move(current_window, 0, CURSOR_OFFSET_DOWN);
|
||||
} else if (keycode == KEY_LEFT) {
|
||||
current_window->handle_cursor_move(current_window, CURSOR_OFFSET_LEFT, 0);
|
||||
} else if (keycode == KEY_RIGHT) {
|
||||
current_window->handle_cursor_move(current_window, CURSOR_OFFSET_RIGHT, 0);
|
||||
} else {
|
||||
current_window->handle_key_down(current_window, keycode);
|
||||
}
|
||||
|
||||
update_panels();
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
|
||||
#include "../include/system.h"
|
||||
|
||||
#define CTRL_KEY_EXIT 3
|
||||
#define CTRL_KEY_TOGGLE 116
|
||||
|
||||
void start_debugger(System *system);
|
||||
|
||||
#endif //NESEMULATOR_DEBUGGER_H
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include "memory_view.h"
|
||||
#include "dialog.h"
|
||||
|
||||
//
|
||||
// Created by william on 6/1/24.
|
||||
|
@ -20,12 +21,22 @@ void memory_view_cursor_init(MemoryView *view) {
|
|||
cursor->min_y = 2;
|
||||
cursor->multiplier_x = 3;
|
||||
cursor->width = 2;
|
||||
|
||||
cursor_enable(cursor);
|
||||
}
|
||||
|
||||
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) {
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#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;
|
||||
|
|
|
@ -3,40 +3,41 @@
|
|||
//
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include "program_view.h"
|
||||
#include "../cpu/op.h"
|
||||
#include "memory_view.h"
|
||||
|
||||
void decode_operands(DebugOperand *operands, const byte *ram, address start_addr) {
|
||||
int pc = start_addr;
|
||||
for (int i = 0; i < 10; i++) {
|
||||
DebugOperand operand;
|
||||
byte op_code = ram[pc];
|
||||
void decode_operands(ProgramView *view) {
|
||||
int pc = PROGRAM_VIEW_BASE_ADDR;
|
||||
while (pc < 0xfffa) {
|
||||
DebugOperand *operand = malloc(sizeof(DebugOperand));
|
||||
if (operand == NULL) {
|
||||
perror("Failed to allocate memory for debug operand");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
operand.addr = pc;
|
||||
operand.op_code = op_code;
|
||||
operand.addr_mode = get_op_addr_mode(op_code);
|
||||
byte op_code = view->ram[pc];
|
||||
operand->addr = pc;
|
||||
operand->op_code = op_code;
|
||||
operand->addr_mode = get_op_addr_mode(op_code);
|
||||
|
||||
pc += 1;
|
||||
|
||||
if (operand.addr_mode == ADDR_MODE_ACCUMULATOR || operand.addr_mode == ADDR_MODE_IMPLICIT) {
|
||||
operand.type = OPERAND_TYPE_ACCUMULATOR;
|
||||
operand.value = 0;
|
||||
} else if (operand.addr_mode == ADDR_MODE_IMMEDIATE) {
|
||||
operand.type = OPERAND_TYPE_IMMEDIATE;
|
||||
operand.value = ram[pc];
|
||||
pc += 1;
|
||||
} else if (operand.addr_mode == ADDR_MODE_RELATIVE) {
|
||||
operand.type = OPERAND_TYPE_ADDRESS;
|
||||
operand.value = ram[pc];
|
||||
if (operand->addr_mode == ADDR_MODE_ACCUMULATOR || operand->addr_mode == ADDR_MODE_IMPLICIT) {
|
||||
operand->value = 0;
|
||||
} else if (operand->addr_mode == ADDR_MODE_RELATIVE || operand->addr_mode == ADDR_MODE_IMMEDIATE ||
|
||||
operand->addr_mode == ADDR_MODE_ZERO_PAGE || operand->addr_mode == ADDR_MODE_ZERO_PAGE_INDEXED_X ||
|
||||
operand->addr_mode == ADDR_MODE_ZERO_PAGE_INDEXED_Y) {
|
||||
operand->value = view->ram[pc];
|
||||
pc += 1;
|
||||
} else {
|
||||
operand.type = OPERAND_TYPE_ADDRESS;
|
||||
operand.value = ram[pc];
|
||||
operand.value += ram[pc + 1] << 8;
|
||||
operand->value = view->ram[pc];
|
||||
operand->value += view->ram[pc + 1] << 8;
|
||||
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);
|
||||
|
||||
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);
|
||||
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) {
|
||||
for (int line = 0; line < 10; line++) {
|
||||
program_view_write_line(view, line, &operands[line]);
|
||||
void program_view_print(ProgramView *view) {
|
||||
LinkedListNode *current_node = view->current_operand_node;
|
||||
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) {
|
||||
window_inter_cursor_init(view->window, 0, 10);
|
||||
window_inter_cursor_init(view->window, 0, 0xf);
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -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));
|
||||
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->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->deinit = &pv_deinit;
|
||||
window_inter_init(interact, x, y, PROGRAM_VIEW_WIDTH, PROGRAM_VIEW_HEIGHT, "PROGRAM VIEW");
|
||||
|
||||
DebugOperand operands[10];
|
||||
decode_operands(&operands[0], ram, 0xc004);
|
||||
decode_operands(view);
|
||||
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);
|
||||
}
|
|
@ -10,24 +10,27 @@
|
|||
#include "../cpu/decoding.h"
|
||||
#include "cursor.h"
|
||||
#include "window.h"
|
||||
#include "../utils/linked_list.h"
|
||||
|
||||
#define PROGRAM_VIEW_HEIGHT 19
|
||||
#define PROGRAM_VIEW_WIDTH 42
|
||||
|
||||
typedef struct program_view {
|
||||
InteractWindow *window;
|
||||
byte *ram;
|
||||
address base_address;
|
||||
} ProgramView;
|
||||
#define PROGRAM_VIEW_BASE_ADDR 0x0000
|
||||
|
||||
typedef struct debug_operand {
|
||||
address addr;
|
||||
byte op_code;
|
||||
AddressingMode addr_mode;
|
||||
enum OperandType type;
|
||||
word value;
|
||||
} 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
|
|
@ -57,5 +57,9 @@ void window_inter_print(InteractWindow *window, int x, int y, const char *fmt, .
|
|||
void window_inter_deinit(InteractWindow *window) {
|
||||
assert(window->view != NULL);
|
||||
|
||||
if (window->deinit != NULL) {
|
||||
window->deinit(window);
|
||||
}
|
||||
|
||||
free(window->view);
|
||||
}
|
|
@ -22,6 +22,8 @@ typedef struct interact_window {
|
|||
void (*handle_cursor_move)(struct interact_window *window, int horizontal, int vertical);
|
||||
|
||||
void (*handle_key_down)(struct interact_window *window, int keycode);
|
||||
|
||||
void (*deinit)(struct interact_window *window);
|
||||
} InteractWindow;
|
||||
|
||||
/**
|
||||
|
|
23
main.c
23
main.c
|
@ -22,22 +22,6 @@
|
|||
#include "include/rom.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() {
|
||||
System system;
|
||||
|
||||
|
@ -51,16 +35,15 @@ int main() {
|
|||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
system_start(&system);
|
||||
start_debugger(&system);
|
||||
|
||||
system_uninit(&system);
|
||||
return 0;
|
||||
//
|
||||
// system_start(&system);
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
// system_loop(&system);
|
||||
// system_uninit(&system);
|
||||
|
||||
// return EXIT_SUCCESS;
|
||||
|
||||
// return win();
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
add_library(UTILS
|
||||
linked_list.c)
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
|
Loading…
Reference in New Issue