This commit is contained in:
parent
091a5e3bf5
commit
e3839dc9d6
|
@ -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})
|
||||||
|
|
|
@ -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.
|
||||||
*
|
*
|
||||||
|
|
1
cpu/op.c
1
cpu/op.c
|
@ -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:
|
||||||
|
|
|
@ -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(¤t_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) {
|
||||||
current_window->handle_cursor_move(current_window, 0, CURSOR_OFFSET_UP);
|
window_index++;
|
||||||
}
|
if (window_index > 1) {
|
||||||
|
window_index = 0;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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();
|
update_panels();
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
|
@ -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
|
|
@ -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);
|
||||||
}
|
}
|
|
@ -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
23
main.c
|
@ -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();
|
||||||
}
|
}
|
|
@ -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