Use linked list to navigate through interactive debugger windows

This commit is contained in:
william 2024-05-01 11:45:39 -04:00
parent e5e972fc4a
commit 6565364bc9
9 changed files with 233 additions and 76 deletions

View File

@ -83,11 +83,11 @@ void cpu_add_cycles(System *system, unsigned int cycle_count) {
} }
// === Registers === // === Registers ===
bool cpu_get_flag(System *system, byte mask) { bool system_get_flag(System *system, byte mask) {
return system->cpu.status & mask; return cpu_get_flag(&system->cpu, mask);
} }
void cpu_set_flag(System *system, byte mask, bool set) { void system_set_flag(System *system, byte mask, bool set) {
if (set) { if (set) {
system->cpu.status |= mask; system->cpu.status |= mask;
} else { } else {

View File

@ -26,7 +26,11 @@
* @param mask The flag mask * @param mask The flag mask
* @return The value of the flag. * @return The value of the flag.
*/ */
bool cpu_get_flag(System *system, byte mask); bool system_get_flag(System *system, byte mask);
static inline bool cpu_get_flag(CPU *cpu, byte mask) {
return cpu->status & mask;
}
/** /**
* Sets a flag in the CPU registers. * Sets a flag in the CPU registers.
@ -35,7 +39,7 @@ bool cpu_get_flag(System *system, byte mask);
* @param mask The flag mask * @param mask The flag mask
* @param set If the flag is set or not * @param set If the flag is set or not
*/ */
void cpu_set_flag(System *system, byte mask, bool set); void system_set_flag(System *system, byte mask, bool set);
/** /**
* Gets the next byte in the program. * Gets the next byte in the program.

View File

@ -122,8 +122,8 @@ byte get_shift_cycle_count(AddressingMode addr_mode) {
} }
void set_acl_flags(System *system, byte result) { void set_acl_flags(System *system, byte result) {
cpu_set_flag(system, CPU_STATUS_ZERO_MASK, result == 0); system_set_flag(system, CPU_STATUS_ZERO_MASK, result == 0);
cpu_set_flag(system, CPU_STATUS_NEGATIVE_MASK, result & 0x80); system_set_flag(system, CPU_STATUS_NEGATIVE_MASK, result & 0x80);
} }
byte get_branch_cycle_count(System *system, bool branching, char offset) { byte get_branch_cycle_count(System *system, bool branching, char offset) {
@ -166,15 +166,15 @@ void add_with_carry(System *system, byte value) {
} }
// Add carry flag and check for overflow again // Add carry flag and check for overflow again
byte result = addition + cpu_get_flag(system, CPU_STATUS_CARRY_MASK); byte result = addition + system_get_flag(system, CPU_STATUS_CARRY_MASK);
if (result < addition) { if (result < addition) {
overflow = true; overflow = true;
} }
system->cpu.accumulator = result; system->cpu.accumulator = result;
cpu_set_flag(system, CPU_STATUS_CARRY_MASK, overflow); system_set_flag(system, CPU_STATUS_CARRY_MASK, overflow);
cpu_set_flag(system, CPU_STATUS_OVERFLOW_MASK, is_sign_overflow(acc, value, result)); system_set_flag(system, CPU_STATUS_OVERFLOW_MASK, is_sign_overflow(acc, value, result));
set_acl_flags(system, result); set_acl_flags(system, result);
} }
@ -230,7 +230,7 @@ void op_ASL(System *system, AddressingMode addr_mode) {
byte result = value << 1; byte result = value << 1;
write_operand(system, operand, result); write_operand(system, operand, result);
cpu_set_flag(system, CPU_STATUS_CARRY_MASK, value & 0x80); system_set_flag(system, CPU_STATUS_CARRY_MASK, value & 0x80);
set_acl_flags(system, result); set_acl_flags(system, result);
cpu_add_cycles(system, get_shift_cycle_count(addr_mode)); cpu_add_cycles(system, get_shift_cycle_count(addr_mode));
} }
@ -242,17 +242,17 @@ void op_AXS(System *system, AddressingMode addr_mode) {
__attribute__((unused)) __attribute__((unused))
void op_BCC(System *system, AddressingMode addr_mode) { void op_BCC(System *system, AddressingMode addr_mode) {
op_branch(system, !cpu_get_flag(system, CPU_STATUS_CARRY_MASK)); op_branch(system, !system_get_flag(system, CPU_STATUS_CARRY_MASK));
} }
__attribute__((unused)) __attribute__((unused))
void op_BCS(System *system, AddressingMode addr_mode) { void op_BCS(System *system, AddressingMode addr_mode) {
op_branch(system, cpu_get_flag(system, CPU_STATUS_CARRY_MASK)); op_branch(system, system_get_flag(system, CPU_STATUS_CARRY_MASK));
} }
__attribute__((unused)) __attribute__((unused))
void op_BEQ(System *system, AddressingMode addr_mode) { void op_BEQ(System *system, AddressingMode addr_mode) {
op_branch(system, cpu_get_flag(system, CPU_STATUS_ZERO_MASK)); op_branch(system, system_get_flag(system, CPU_STATUS_ZERO_MASK));
} }
__attribute__((unused)) __attribute__((unused))
@ -263,24 +263,24 @@ void op_BIT(System *system, AddressingMode addr_mode) {
byte result = value & acc; byte result = value & acc;
cpu_set_flag(system, CPU_STATUS_ZERO_MASK, result == 0); system_set_flag(system, CPU_STATUS_ZERO_MASK, result == 0);
cpu_set_flag(system, CPU_STATUS_OVERFLOW_MASK, value & 0x40); system_set_flag(system, CPU_STATUS_OVERFLOW_MASK, value & 0x40);
cpu_set_flag(system, CPU_STATUS_NEGATIVE_MASK, value & 0x80); system_set_flag(system, CPU_STATUS_NEGATIVE_MASK, value & 0x80);
} }
__attribute__((unused)) __attribute__((unused))
void op_BMI(System *system, AddressingMode addr_mode) { void op_BMI(System *system, AddressingMode addr_mode) {
op_branch(system, cpu_get_flag(system, CPU_STATUS_NEGATIVE_MASK)); op_branch(system, system_get_flag(system, CPU_STATUS_NEGATIVE_MASK));
} }
__attribute__((unused)) __attribute__((unused))
void op_BNE(System *system, AddressingMode addr_mode) { void op_BNE(System *system, AddressingMode addr_mode) {
op_branch(system, !cpu_get_flag(system, CPU_STATUS_ZERO_MASK)); op_branch(system, !system_get_flag(system, CPU_STATUS_ZERO_MASK));
} }
__attribute__((unused)) __attribute__((unused))
void op_BPL(System *system, AddressingMode addr_mode) { void op_BPL(System *system, AddressingMode addr_mode) {
op_branch(system, !cpu_get_flag(system, CPU_STATUS_NEGATIVE_MASK)); op_branch(system, !system_get_flag(system, CPU_STATUS_NEGATIVE_MASK));
} }
// Stops program execution, useful for debugging // Stops program execution, useful for debugging
@ -292,41 +292,41 @@ void op_BRK(System *system, AddressingMode addr_mode) {
assert(false); assert(false);
cpu_set_flag(system, CPU_STATUS_B_MASK, true); system_set_flag(system, CPU_STATUS_B_MASK, true);
cpu_add_cycles(system, 7); cpu_add_cycles(system, 7);
} }
__attribute__((unused)) __attribute__((unused))
void op_BVC(System *system, AddressingMode addr_mode) { void op_BVC(System *system, AddressingMode addr_mode) {
op_branch(system, !cpu_get_flag(system, CPU_STATUS_OVERFLOW_MASK)); op_branch(system, !system_get_flag(system, CPU_STATUS_OVERFLOW_MASK));
} }
__attribute__((unused)) __attribute__((unused))
void op_BVS(System *system, AddressingMode addr_mode) { void op_BVS(System *system, AddressingMode addr_mode) {
op_branch(system, cpu_get_flag(system, CPU_STATUS_OVERFLOW_MASK)); op_branch(system, system_get_flag(system, CPU_STATUS_OVERFLOW_MASK));
} }
__attribute__((unused)) __attribute__((unused))
void op_CLC(System *system, AddressingMode addr_mode) { void op_CLC(System *system, AddressingMode addr_mode) {
cpu_set_flag(system, CPU_STATUS_CARRY_MASK, false); system_set_flag(system, CPU_STATUS_CARRY_MASK, false);
cpu_add_cycles(system, 2); cpu_add_cycles(system, 2);
} }
__attribute__((unused)) __attribute__((unused))
void op_CLD(System *system, AddressingMode addr_mode) { void op_CLD(System *system, AddressingMode addr_mode) {
cpu_set_flag(system, CPU_STATUS_DECIMAL_MASK, false); system_set_flag(system, CPU_STATUS_DECIMAL_MASK, false);
cpu_add_cycles(system, 2); cpu_add_cycles(system, 2);
} }
__attribute__((unused)) __attribute__((unused))
void op_CLI(System *system, AddressingMode addr_mode) { void op_CLI(System *system, AddressingMode addr_mode) {
cpu_set_flag(system, CPU_STATUS_INTERRUPT_DISABLE_MASK, false); system_set_flag(system, CPU_STATUS_INTERRUPT_DISABLE_MASK, false);
cpu_add_cycles(system, 2); cpu_add_cycles(system, 2);
} }
__attribute__((unused)) __attribute__((unused))
void op_CLV(System *system, AddressingMode addr_mode) { void op_CLV(System *system, AddressingMode addr_mode) {
cpu_set_flag(system, CPU_STATUS_OVERFLOW_MASK, false); system_set_flag(system, CPU_STATUS_OVERFLOW_MASK, false);
cpu_add_cycles(system, 2); cpu_add_cycles(system, 2);
} }
@ -338,9 +338,9 @@ void op_CMP(System *system, AddressingMode addr_mode) {
byte result = acc - value; byte result = acc - value;
cpu_set_flag(system, CPU_STATUS_CARRY_MASK, acc >= value); system_set_flag(system, CPU_STATUS_CARRY_MASK, acc >= value);
cpu_set_flag(system, CPU_STATUS_ZERO_MASK, result == 0); system_set_flag(system, CPU_STATUS_ZERO_MASK, result == 0);
cpu_set_flag(system, CPU_STATUS_NEGATIVE_MASK, result & 0x80); system_set_flag(system, CPU_STATUS_NEGATIVE_MASK, result & 0x80);
cpu_add_cycles(system, get_cycle_count(operand, addr_mode)); cpu_add_cycles(system, get_cycle_count(operand, addr_mode));
} }
@ -353,9 +353,9 @@ void op_CPX(System *system, AddressingMode addr_mode) {
byte result = x - value; byte result = x - value;
cpu_set_flag(system, CPU_STATUS_CARRY_MASK, x >= value); system_set_flag(system, CPU_STATUS_CARRY_MASK, x >= value);
cpu_set_flag(system, CPU_STATUS_ZERO_MASK, result == 0); system_set_flag(system, CPU_STATUS_ZERO_MASK, result == 0);
cpu_set_flag(system, CPU_STATUS_NEGATIVE_MASK, result & 0x80); system_set_flag(system, CPU_STATUS_NEGATIVE_MASK, result & 0x80);
cpu_add_cycles(system, get_cycle_count(operand, addr_mode)); cpu_add_cycles(system, get_cycle_count(operand, addr_mode));
} }
@ -368,9 +368,9 @@ void op_CPY(System *system, AddressingMode addr_mode) {
byte result = y - value; byte result = y - value;
cpu_set_flag(system, CPU_STATUS_CARRY_MASK, y >= value); system_set_flag(system, CPU_STATUS_CARRY_MASK, y >= value);
cpu_set_flag(system, CPU_STATUS_ZERO_MASK, result == 0); system_set_flag(system, CPU_STATUS_ZERO_MASK, result == 0);
cpu_set_flag(system, CPU_STATUS_NEGATIVE_MASK, result & 0x80); system_set_flag(system, CPU_STATUS_NEGATIVE_MASK, result & 0x80);
cpu_add_cycles(system, get_cycle_count(operand, addr_mode)); cpu_add_cycles(system, get_cycle_count(operand, addr_mode));
} }
@ -384,9 +384,9 @@ void op_DCP(System *system, AddressingMode addr_mode) {
byte result = value - 1; byte result = value - 1;
byte cmp_result = acc - result; byte cmp_result = acc - result;
cpu_set_flag(system, CPU_STATUS_CARRY_MASK, acc >= value); system_set_flag(system, CPU_STATUS_CARRY_MASK, acc >= value);
cpu_set_flag(system, CPU_STATUS_ZERO_MASK, cmp_result == 0); system_set_flag(system, CPU_STATUS_ZERO_MASK, cmp_result == 0);
cpu_set_flag(system, CPU_STATUS_NEGATIVE_MASK, cmp_result & 0x80); system_set_flag(system, CPU_STATUS_NEGATIVE_MASK, cmp_result & 0x80);
write_operand(system, operand, result); write_operand(system, operand, result);
@ -595,7 +595,7 @@ void op_LSR(System *system, AddressingMode addr_mode) {
byte value = read_operand(system, operand); byte value = read_operand(system, operand);
// Put bit 0 in the carry flag // Put bit 0 in the carry flag
cpu_set_flag(system, CPU_STATUS_CARRY_MASK, value & 0x01); system_set_flag(system, CPU_STATUS_CARRY_MASK, value & 0x01);
value >>= 1; value >>= 1;
write_operand(system, operand, value); write_operand(system, operand, value);
@ -640,7 +640,7 @@ void op_PHP(System *system, AddressingMode addr_mode) {
byte status = system->cpu.status; byte status = system->cpu.status;
cpu_stack_push(system, status); cpu_stack_push(system, status);
// cpu_set_flag(system, CPU_STATUS_B_MASK, true); // system_set_flag(system, CPU_STATUS_B_MASK, true);
cpu_add_cycles(system, 3); cpu_add_cycles(system, 3);
} }
@ -671,10 +671,10 @@ __attribute__((unused))
void op_RLA(System *system, AddressingMode addr_mode) { void op_RLA(System *system, AddressingMode addr_mode) {
Operand operand = decode_operand(system, addr_mode); Operand operand = decode_operand(system, addr_mode);
byte value = read_operand(system, operand); byte value = read_operand(system, operand);
byte carry = cpu_get_flag(system, CPU_STATUS_CARRY_MASK); byte carry = system_get_flag(system, CPU_STATUS_CARRY_MASK);
byte acc = system->cpu.accumulator; byte acc = system->cpu.accumulator;
cpu_set_flag(system, CPU_STATUS_CARRY_MASK, value & 0x80); system_set_flag(system, CPU_STATUS_CARRY_MASK, value & 0x80);
value = (value << 1) | carry; value = (value << 1) | carry;
byte and_result = acc & value; byte and_result = acc & value;
@ -690,9 +690,9 @@ __attribute__((unused))
void op_ROL(System *system, AddressingMode addr_mode) { void op_ROL(System *system, AddressingMode addr_mode) {
Operand operand = decode_operand(system, addr_mode); Operand operand = decode_operand(system, addr_mode);
byte value = read_operand(system, operand); byte value = read_operand(system, operand);
byte carry = cpu_get_flag(system, CPU_STATUS_CARRY_MASK); byte carry = system_get_flag(system, CPU_STATUS_CARRY_MASK);
cpu_set_flag(system, CPU_STATUS_CARRY_MASK, value & 0x80); system_set_flag(system, CPU_STATUS_CARRY_MASK, value & 0x80);
value = (value << 1) | carry; value = (value << 1) | carry;
write_operand(system, operand, value); write_operand(system, operand, value);
@ -704,9 +704,9 @@ __attribute__((unused))
void op_ROR(System *system, AddressingMode addr_mode) { void op_ROR(System *system, AddressingMode addr_mode) {
Operand operand = decode_operand(system, addr_mode); Operand operand = decode_operand(system, addr_mode);
byte value = read_operand(system, operand); byte value = read_operand(system, operand);
byte carry = cpu_get_flag(system, CPU_STATUS_CARRY_MASK); byte carry = system_get_flag(system, CPU_STATUS_CARRY_MASK);
cpu_set_flag(system, CPU_STATUS_CARRY_MASK, value & 0x01); system_set_flag(system, CPU_STATUS_CARRY_MASK, value & 0x01);
value = (value >> 1) | (carry << 7); value = (value >> 1) | (carry << 7);
write_operand(system, operand, value); write_operand(system, operand, value);
@ -718,9 +718,9 @@ __attribute__((unused))
void op_RRA(System *system, AddressingMode addr_mode) { void op_RRA(System *system, AddressingMode addr_mode) {
Operand operand = decode_operand(system, addr_mode); Operand operand = decode_operand(system, addr_mode);
byte value = read_operand(system, operand); byte value = read_operand(system, operand);
byte carry = cpu_get_flag(system, CPU_STATUS_CARRY_MASK); byte carry = system_get_flag(system, CPU_STATUS_CARRY_MASK);
cpu_set_flag(system, CPU_STATUS_CARRY_MASK, value & 0x01); system_set_flag(system, CPU_STATUS_CARRY_MASK, value & 0x01);
value = (value >> 1) | (carry << 7); value = (value >> 1) | (carry << 7);
add_with_carry(system, value); add_with_carry(system, value);
write_operand(system, operand, value); write_operand(system, operand, value);
@ -770,19 +770,19 @@ void op_SBC(System *system, AddressingMode addr_mode) {
__attribute__((unused)) __attribute__((unused))
void op_SEC(System *system, AddressingMode addr_mode) { void op_SEC(System *system, AddressingMode addr_mode) {
cpu_set_flag(system, CPU_STATUS_CARRY_MASK, true); system_set_flag(system, CPU_STATUS_CARRY_MASK, true);
cpu_add_cycles(system, 2); cpu_add_cycles(system, 2);
} }
__attribute__((unused)) __attribute__((unused))
void op_SED(System *system, AddressingMode addr_mode) { void op_SED(System *system, AddressingMode addr_mode) {
cpu_set_flag(system, CPU_STATUS_DECIMAL_MASK, true); system_set_flag(system, CPU_STATUS_DECIMAL_MASK, true);
cpu_add_cycles(system, 2); cpu_add_cycles(system, 2);
} }
__attribute__((unused)) __attribute__((unused))
void op_SEI(System *system, AddressingMode addr_mode) { void op_SEI(System *system, AddressingMode addr_mode) {
cpu_set_flag(system, CPU_STATUS_INTERRUPT_DISABLE_MASK, true); system_set_flag(system, CPU_STATUS_INTERRUPT_DISABLE_MASK, true);
cpu_add_cycles(system, 2); cpu_add_cycles(system, 2);
} }
@ -808,7 +808,7 @@ void op_SLO(System *system, AddressingMode addr_mode) {
write_operand(system, operand, result); write_operand(system, operand, result);
cpu_set_flag(system, CPU_STATUS_CARRY_MASK, value & 0x80); system_set_flag(system, CPU_STATUS_CARRY_MASK, value & 0x80);
set_acl_flags(system, acc); set_acl_flags(system, acc);
cpu_add_cycles(system, get_shift_cycle_count(addr_mode)); cpu_add_cycles(system, get_shift_cycle_count(addr_mode));
} }
@ -820,7 +820,7 @@ void op_SRE(System *system, AddressingMode addr_mode) {
byte acc = system->cpu.accumulator; byte acc = system->cpu.accumulator;
// Put bit 0 in the carry flag // Put bit 0 in the carry flag
cpu_set_flag(system, CPU_STATUS_CARRY_MASK, value & 0x01); system_set_flag(system, CPU_STATUS_CARRY_MASK, value & 0x01);
value >>= 1; value >>= 1;
acc ^= value; acc ^= value;

View File

@ -2,4 +2,37 @@
// Created by william on 4/30/24. // Created by william on 4/30/24.
// //
#include <stdlib.h>
#include "cpu_view.h" #include "cpu_view.h"
#include "../cpu/cpu.h"
void cv_print(CpuView *view) {
window_print(view->window, 0, 0, "PC: $%04x", view->cpu->program_counter);
window_print(view->window, 0, 1, "SP: %02x", view->cpu->stack_pointer);
window_print(view->window, 0, 2, "A: %02x", view->cpu->accumulator);
window_print(view->window, 0, 3, "X: %02x", view->cpu->x);
window_print(view->window, 0, 4, "Y: %02x", view->cpu->y);
window_print(view->window, 0, 5, "C: %01x", cpu_get_flag(view->cpu, CPU_STATUS_CARRY_MASK));
window_print(view->window, 0, 6, "Z: %01x", cpu_get_flag(view->cpu, CPU_STATUS_ZERO_MASK));
window_print(view->window, 0, 7, "I: %01x", cpu_get_flag(view->cpu, CPU_STATUS_INTERRUPT_DISABLE_MASK));
window_print(view->window, 0, 8, "D: %01x", cpu_get_flag(view->cpu, CPU_STATUS_DECIMAL_MASK));
window_print(view->window, 0, 9, "B: %01x", cpu_get_flag(view->cpu, CPU_STATUS_B_MASK));
window_print(view->window, 0, 10, "O: %01x", cpu_get_flag(view->cpu, CPU_STATUS_OVERFLOW_MASK));
window_print(view->window, 0, 11, "N: %01x", cpu_get_flag(view->cpu, CPU_STATUS_NEGATIVE_MASK));
}
CpuView *cv_init(CPU *cpu, int x, int y) {
CpuView *view = malloc(sizeof(CpuView));
view->window = malloc(sizeof(Window));
view->cpu = cpu;
window_init(view->window, x, y, CPU_VIEW_WIDTH, CPU_VIEW_HEIGHT, "CPU VIEW");
cv_print(view);
return view;
}
void cv_uninit(CpuView *view) {
free(view->window);
free(view);
}

View File

@ -5,4 +5,28 @@
#ifndef NESEMULATOR_CPU_VIEW_H #ifndef NESEMULATOR_CPU_VIEW_H
#define NESEMULATOR_CPU_VIEW_H #define NESEMULATOR_CPU_VIEW_H
#include "window.h"
#include "../include/types.h"
#include "../include/cpu.h"
#define CPU_VIEW_HEIGHT 14
#define CPU_VIEW_WIDTH 12
typedef struct cpu_view {
Window *window;
CPU *cpu;
} CpuView;
/**
* Initializes a CPU view for a system RAM.
*
* @param interact
* @param ram
* @param x
* @param y
*/
CpuView *cv_init(CPU *cpu, int x, int y);
void cv_uninit(CpuView *cpu_view);
#endif //NESEMULATOR_CPU_VIEW_H #endif //NESEMULATOR_CPU_VIEW_H

View File

@ -9,8 +9,9 @@
#include "memory_view.h" #include "memory_view.h"
#include "program_view.h" #include "program_view.h"
#include "keys.h" #include "keys.h"
#include "cpu_view.h"
void create_window() { void debugger_create_window() {
setenv("TERMINFO", "/usr/share/terminfo", 1); setenv("TERMINFO", "/usr/share/terminfo", 1);
setenv("TERM", "xterm", 1); setenv("TERM", "xterm", 1);
@ -21,15 +22,45 @@ void create_window() {
keypad(stdscr, true); keypad(stdscr, true);
} }
LinkedList debugger_create_interactive_windows(System *system) {
LinkedList interactive_windows;
InteractWindow *window;
interactive_windows = linked_list_init(true);
window = malloc(sizeof(InteractWindow));
mv_init(window, system->ram, 0, 0);
linked_list_add(&interactive_windows, window);
window = malloc(sizeof(InteractWindow));
pv_init(window, system, MEMORY_VIEW_WIDTH, 0);
linked_list_add(&interactive_windows, window);
return interactive_windows;
}
void debugger_uninit_interactive_windows(LinkedList *windows) {
linked_list_cursor_reset(windows);
InteractWindow *window = windows->current->data;
for (int i = 0; i < windows->size; i++) {
window_inter_deinit(window);
window = linked_list_next(windows)->data;
}
linked_list_uninit(windows);
}
void start_debugger(System *system) { void start_debugger(System *system) {
InteractWindow windows[2]; CpuView *cpu_view;
size_t window_index = 0; LinkedList interactive_windows;
InteractWindow *current_window = &windows[window_index]; InteractWindow *current_window;
create_window(); debugger_create_window();
mv_init(&windows[0], system->ram, 0, 0); interactive_windows = debugger_create_interactive_windows(system);
pv_init(&windows[1], system, MEMORY_VIEW_WIDTH, 0); current_window = interactive_windows.current->data;
cpu_view = cv_init(&system->cpu, MEMORY_VIEW_WIDTH + PROGRAM_VIEW_WIDTH, 0);
cursor_enable(&current_window->cursor); cursor_enable(&current_window->cursor);
@ -39,13 +70,9 @@ void start_debugger(System *system) {
int keycode; int keycode;
while ((keycode = getch()) != KEY_EXIT_DEBUGGER) { while ((keycode = getch()) != KEY_EXIT_DEBUGGER) {
if (keycode == KEY_NEXT_VIEW) { if (keycode == KEY_NEXT_VIEW) {
window_index++;
if (window_index > 1) {
window_index = 0;
}
cursor_disable(&current_window->cursor); cursor_disable(&current_window->cursor);
current_window = &windows[window_index]; current_window = linked_list_next(&interactive_windows)->data;
cursor_enable(&current_window->cursor); cursor_enable(&current_window->cursor);
} else if (keycode == KEY_VIEW_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);
@ -63,8 +90,8 @@ void start_debugger(System *system) {
doupdate(); doupdate();
} }
window_inter_deinit(&windows[0]); debugger_uninit_interactive_windows(&interactive_windows);
window_inter_deinit(&windows[1]); cv_uninit(cpu_view);
endwin(); endwin();
} }

View File

@ -188,7 +188,7 @@ void pv_init(InteractWindow *interact, System *system, int x, int y) {
view->window = interact; view->window = interact;
view->ram = system->ram; view->ram = system->ram;
view->pc = &system->cpu.program_counter; view->pc = &system->cpu.program_counter;
view->operands = linked_list_init(); view->operands = linked_list_init(false);
interact->view = view; interact->view = view;
interact->handle_cursor_move = &pv_handle_cursor_move; interact->handle_cursor_move = &pv_handle_cursor_move;

View File

@ -8,14 +8,21 @@
#include <assert.h> #include <assert.h>
#include "linked_list.h" #include "linked_list.h"
LinkedList linked_list_init() { LinkedList linked_list_init(bool circular) {
LinkedList list; LinkedList list;
list.circular = circular;
list.size = 0;
list.head = NULL; list.head = NULL;
list.end = NULL; list.end = NULL;
list.current = NULL;
return list; return list;
} }
void linked_list_add(LinkedList *list, void *data) { void linked_list_add(LinkedList *list, void *data) {
assert(list != NULL);
LinkedListNode *node = malloc(sizeof(LinkedListNode)); LinkedListNode *node = malloc(sizeof(LinkedListNode));
if (node == NULL) { if (node == NULL) {
perror("Failed to allocate memory for linked list node"); perror("Failed to allocate memory for linked list node");
@ -24,20 +31,48 @@ void linked_list_add(LinkedList *list, void *data) {
node->data = data; node->data = data;
node->previous = list->end; node->previous = list->end;
node->next = NULL;
if (list->head == NULL) { if (list->head == NULL) {
list->head = node; list->head = node;
list->current = node;
} }
if (list->end != NULL) { if (list->end != NULL) {
list->end->next = node; list->end->next = node;
} }
if (list->circular) {
node->next = list->head;
} else {
node->next = NULL;
}
list->end = node; list->end = node;
list->size++;
}
LinkedListNode *linked_list_next(LinkedList* list) {
assert(list != NULL);
if (list->head == NULL) {
return NULL;
}
LinkedListNode *next = list->current->next;
list->current = next;
return next;
}
void linked_list_cursor_reset(LinkedList *list) {
assert(list != NULL);
list->current = list->head;
} }
LinkedListNode *linked_list_get_if(LinkedList *list, bool(*predicate)(void *, void *), void *userdata) { LinkedListNode *linked_list_get_if(LinkedList *list, bool(*predicate)(void *, void *), void *userdata) {
assert(list != NULL);
assert(predicate != NULL);
LinkedListNode *node = list->head; LinkedListNode *node = list->head;
while (node != NULL) { while (node != NULL) {
@ -51,10 +86,13 @@ 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 *linked_list_get_near(LinkedList *list, int(*compute_distance)(void *, void *), void *userdata) {
assert(list != NULL);
assert(compute_distance != NULL);
LinkedListNode *near_node = list->head; LinkedListNode *near_node = list->head;
int current_distance = predicate(near_node->data, userdata); int current_distance = compute_distance(near_node->data, userdata);
if (current_distance == 0) { if (current_distance == 0) {
return near_node; return near_node;
} }
@ -65,7 +103,7 @@ LinkedListNode *linked_list_get_near(LinkedList *list, int(*predicate)(void *, v
while (current_distance < last_distance && near_node->next != NULL) { while (current_distance < last_distance && near_node->next != NULL) {
node = near_node->next; node = near_node->next;
last_distance = current_distance; last_distance = current_distance;
current_distance = predicate(node->data, userdata); current_distance = compute_distance(node->data, userdata);
} }
// After the loop, we have found the nearest node in the list, assuming there is only one point of convergence // After the loop, we have found the nearest node in the list, assuming there is only one point of convergence
@ -82,5 +120,10 @@ void linked_list_uninit(LinkedList *list) {
free(current_node->data); free(current_node->data);
free(current_node); free(current_node);
if (node == list->head) {
// The list may be circular, we don't want an infinite free loop
break;
}
} }
} }

View File

@ -14,16 +14,20 @@ typedef struct linked_list_node {
} LinkedListNode; } LinkedListNode;
typedef struct linked_list { typedef struct linked_list {
bool circular;
unsigned int size;
LinkedListNode *head; LinkedListNode *head;
LinkedListNode *end; LinkedListNode *end;
LinkedListNode *current;
} LinkedList; } LinkedList;
/** /**
* Initializes a new linked list. * Initializes a new linked list.
* *
* @param circular If the list is circular, meaning that the last node is linked to the first node.
* @return The linked list instance * @return The linked list instance
*/ */
LinkedList linked_list_init(); LinkedList linked_list_init(bool circular);
/** /**
* Adds data to a linked list. * Adds data to a linked list.
@ -33,6 +37,19 @@ LinkedList linked_list_init();
*/ */
void linked_list_add(LinkedList *list, void *data); void linked_list_add(LinkedList *list, void *data);
/**
* Gets the next node in the list.
*
* @param list The linked list
* @return The next node in the list. Can be NULL if the list is empty or depleted.
*/
LinkedListNode *linked_list_next(LinkedList *list);
/**
* Resets the position of the cursor to the head of the list.
*/
void linked_list_cursor_reset(LinkedList *list);
/** /**
* Searches for data corresponding to a predicate. * Searches for data corresponding to a predicate.
* The search will stop after reaching the first node matching the given predicate. * The search will stop after reaching the first node matching the given predicate.
@ -44,7 +61,16 @@ void linked_list_add(LinkedList *list, void *data);
*/ */
LinkedListNode *linked_list_get_if(LinkedList *list, bool(*predicate)(void *, void *), void *userdata); 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); /**
* Searches for data with the smallest distance computed from a function.
* The search will stop when a node increasing the distance is found. For this reason, the distance computing function should have a single minimum.
*
* @param list The list to search in
* @param compute_distance The function to compute the distance of a node's data
* @param userdata Parameter to pass to the function
* @return The node with the smallest distance
*/
LinkedListNode *linked_list_get_near(LinkedList *list, int(*compute_distance)(void *, void *), void *userdata);
/** /**
* Deinitializes a linked list. * Deinitializes a linked list.