Use linked list to navigate through interactive debugger windows
This commit is contained in:
parent
e5e972fc4a
commit
6565364bc9
|
@ -83,11 +83,11 @@ void cpu_add_cycles(System *system, unsigned int cycle_count) {
|
|||
}
|
||||
|
||||
// === Registers ===
|
||||
bool cpu_get_flag(System *system, byte mask) {
|
||||
return system->cpu.status & mask;
|
||||
bool system_get_flag(System *system, byte 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) {
|
||||
system->cpu.status |= mask;
|
||||
} else {
|
||||
|
|
|
@ -26,7 +26,11 @@
|
|||
* @param mask The flag mask
|
||||
* @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.
|
||||
|
@ -35,7 +39,7 @@ bool cpu_get_flag(System *system, byte mask);
|
|||
* @param mask The flag mask
|
||||
* @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.
|
||||
|
|
98
cpu/op.c
98
cpu/op.c
|
@ -122,8 +122,8 @@ byte get_shift_cycle_count(AddressingMode addr_mode) {
|
|||
}
|
||||
|
||||
void set_acl_flags(System *system, byte result) {
|
||||
cpu_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_ZERO_MASK, result == 0);
|
||||
system_set_flag(system, CPU_STATUS_NEGATIVE_MASK, result & 0x80);
|
||||
}
|
||||
|
||||
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
|
||||
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) {
|
||||
overflow = true;
|
||||
}
|
||||
|
||||
system->cpu.accumulator = result;
|
||||
|
||||
cpu_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_CARRY_MASK, overflow);
|
||||
system_set_flag(system, CPU_STATUS_OVERFLOW_MASK, is_sign_overflow(acc, value, result));
|
||||
|
||||
set_acl_flags(system, result);
|
||||
}
|
||||
|
@ -230,7 +230,7 @@ void op_ASL(System *system, AddressingMode addr_mode) {
|
|||
byte result = value << 1;
|
||||
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);
|
||||
cpu_add_cycles(system, get_shift_cycle_count(addr_mode));
|
||||
}
|
||||
|
@ -242,17 +242,17 @@ void op_AXS(System *system, AddressingMode addr_mode) {
|
|||
|
||||
__attribute__((unused))
|
||||
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))
|
||||
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))
|
||||
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))
|
||||
|
@ -263,24 +263,24 @@ void op_BIT(System *system, AddressingMode addr_mode) {
|
|||
|
||||
byte result = value & acc;
|
||||
|
||||
cpu_set_flag(system, CPU_STATUS_ZERO_MASK, result == 0);
|
||||
cpu_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_ZERO_MASK, result == 0);
|
||||
system_set_flag(system, CPU_STATUS_OVERFLOW_MASK, value & 0x40);
|
||||
system_set_flag(system, CPU_STATUS_NEGATIVE_MASK, value & 0x80);
|
||||
}
|
||||
|
||||
__attribute__((unused))
|
||||
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))
|
||||
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))
|
||||
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
|
||||
|
@ -292,41 +292,41 @@ void op_BRK(System *system, AddressingMode addr_mode) {
|
|||
|
||||
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);
|
||||
}
|
||||
|
||||
__attribute__((unused))
|
||||
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))
|
||||
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))
|
||||
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);
|
||||
}
|
||||
|
||||
__attribute__((unused))
|
||||
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);
|
||||
}
|
||||
|
||||
__attribute__((unused))
|
||||
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);
|
||||
}
|
||||
|
||||
__attribute__((unused))
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -338,9 +338,9 @@ void op_CMP(System *system, AddressingMode addr_mode) {
|
|||
|
||||
byte result = acc - value;
|
||||
|
||||
cpu_set_flag(system, CPU_STATUS_CARRY_MASK, acc >= value);
|
||||
cpu_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_CARRY_MASK, acc >= value);
|
||||
system_set_flag(system, CPU_STATUS_ZERO_MASK, result == 0);
|
||||
system_set_flag(system, CPU_STATUS_NEGATIVE_MASK, result & 0x80);
|
||||
|
||||
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;
|
||||
|
||||
cpu_set_flag(system, CPU_STATUS_CARRY_MASK, x >= value);
|
||||
cpu_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_CARRY_MASK, x >= value);
|
||||
system_set_flag(system, CPU_STATUS_ZERO_MASK, result == 0);
|
||||
system_set_flag(system, CPU_STATUS_NEGATIVE_MASK, result & 0x80);
|
||||
|
||||
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;
|
||||
|
||||
cpu_set_flag(system, CPU_STATUS_CARRY_MASK, y >= value);
|
||||
cpu_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_CARRY_MASK, y >= value);
|
||||
system_set_flag(system, CPU_STATUS_ZERO_MASK, result == 0);
|
||||
system_set_flag(system, CPU_STATUS_NEGATIVE_MASK, result & 0x80);
|
||||
|
||||
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 cmp_result = acc - result;
|
||||
|
||||
cpu_set_flag(system, CPU_STATUS_CARRY_MASK, acc >= value);
|
||||
cpu_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_CARRY_MASK, acc >= value);
|
||||
system_set_flag(system, CPU_STATUS_ZERO_MASK, cmp_result == 0);
|
||||
system_set_flag(system, CPU_STATUS_NEGATIVE_MASK, cmp_result & 0x80);
|
||||
|
||||
write_operand(system, operand, result);
|
||||
|
||||
|
@ -595,7 +595,7 @@ void op_LSR(System *system, AddressingMode addr_mode) {
|
|||
byte value = read_operand(system, operand);
|
||||
|
||||
// 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;
|
||||
write_operand(system, operand, value);
|
||||
|
@ -640,7 +640,7 @@ void op_PHP(System *system, AddressingMode addr_mode) {
|
|||
byte status = system->cpu.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);
|
||||
}
|
||||
|
@ -671,10 +671,10 @@ __attribute__((unused))
|
|||
void op_RLA(System *system, AddressingMode addr_mode) {
|
||||
Operand operand = decode_operand(system, addr_mode);
|
||||
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;
|
||||
|
||||
cpu_set_flag(system, CPU_STATUS_CARRY_MASK, value & 0x80);
|
||||
system_set_flag(system, CPU_STATUS_CARRY_MASK, value & 0x80);
|
||||
|
||||
value = (value << 1) | carry;
|
||||
byte and_result = acc & value;
|
||||
|
@ -690,9 +690,9 @@ __attribute__((unused))
|
|||
void op_ROL(System *system, AddressingMode addr_mode) {
|
||||
Operand operand = decode_operand(system, addr_mode);
|
||||
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;
|
||||
write_operand(system, operand, value);
|
||||
|
||||
|
@ -704,9 +704,9 @@ __attribute__((unused))
|
|||
void op_ROR(System *system, AddressingMode addr_mode) {
|
||||
Operand operand = decode_operand(system, addr_mode);
|
||||
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);
|
||||
write_operand(system, operand, value);
|
||||
|
||||
|
@ -718,9 +718,9 @@ __attribute__((unused))
|
|||
void op_RRA(System *system, AddressingMode addr_mode) {
|
||||
Operand operand = decode_operand(system, addr_mode);
|
||||
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);
|
||||
add_with_carry(system, value);
|
||||
write_operand(system, operand, value);
|
||||
|
@ -770,19 +770,19 @@ void op_SBC(System *system, AddressingMode addr_mode) {
|
|||
|
||||
__attribute__((unused))
|
||||
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);
|
||||
}
|
||||
|
||||
__attribute__((unused))
|
||||
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);
|
||||
}
|
||||
|
||||
__attribute__((unused))
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -808,7 +808,7 @@ void op_SLO(System *system, AddressingMode addr_mode) {
|
|||
|
||||
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);
|
||||
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;
|
||||
|
||||
// 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;
|
||||
acc ^= value;
|
||||
|
|
|
@ -2,4 +2,37 @@
|
|||
// Created by william on 4/30/24.
|
||||
//
|
||||
|
||||
#include <stdlib.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);
|
||||
}
|
|
@ -5,4 +5,28 @@
|
|||
#ifndef 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
|
||||
|
|
|
@ -9,8 +9,9 @@
|
|||
#include "memory_view.h"
|
||||
#include "program_view.h"
|
||||
#include "keys.h"
|
||||
#include "cpu_view.h"
|
||||
|
||||
void create_window() {
|
||||
void debugger_create_window() {
|
||||
setenv("TERMINFO", "/usr/share/terminfo", 1);
|
||||
setenv("TERM", "xterm", 1);
|
||||
|
||||
|
@ -21,15 +22,45 @@ void create_window() {
|
|||
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) {
|
||||
InteractWindow windows[2];
|
||||
size_t window_index = 0;
|
||||
InteractWindow *current_window = &windows[window_index];
|
||||
CpuView *cpu_view;
|
||||
LinkedList interactive_windows;
|
||||
InteractWindow *current_window;
|
||||
|
||||
create_window();
|
||||
debugger_create_window();
|
||||
|
||||
mv_init(&windows[0], system->ram, 0, 0);
|
||||
pv_init(&windows[1], system, MEMORY_VIEW_WIDTH, 0);
|
||||
interactive_windows = debugger_create_interactive_windows(system);
|
||||
current_window = interactive_windows.current->data;
|
||||
cpu_view = cv_init(&system->cpu, MEMORY_VIEW_WIDTH + PROGRAM_VIEW_WIDTH, 0);
|
||||
|
||||
cursor_enable(¤t_window->cursor);
|
||||
|
||||
|
@ -39,13 +70,9 @@ void start_debugger(System *system) {
|
|||
int keycode;
|
||||
while ((keycode = getch()) != KEY_EXIT_DEBUGGER) {
|
||||
if (keycode == KEY_NEXT_VIEW) {
|
||||
window_index++;
|
||||
if (window_index > 1) {
|
||||
window_index = 0;
|
||||
}
|
||||
|
||||
cursor_disable(¤t_window->cursor);
|
||||
current_window = &windows[window_index];
|
||||
current_window = linked_list_next(&interactive_windows)->data;
|
||||
cursor_enable(¤t_window->cursor);
|
||||
} else if (keycode == KEY_VIEW_UP) {
|
||||
current_window->handle_cursor_move(current_window, 0, CURSOR_OFFSET_UP);
|
||||
|
@ -63,8 +90,8 @@ void start_debugger(System *system) {
|
|||
doupdate();
|
||||
}
|
||||
|
||||
window_inter_deinit(&windows[0]);
|
||||
window_inter_deinit(&windows[1]);
|
||||
debugger_uninit_interactive_windows(&interactive_windows);
|
||||
cv_uninit(cpu_view);
|
||||
|
||||
endwin();
|
||||
}
|
|
@ -188,7 +188,7 @@ void pv_init(InteractWindow *interact, System *system, int x, int y) {
|
|||
view->window = interact;
|
||||
view->ram = system->ram;
|
||||
view->pc = &system->cpu.program_counter;
|
||||
view->operands = linked_list_init();
|
||||
view->operands = linked_list_init(false);
|
||||
|
||||
interact->view = view;
|
||||
interact->handle_cursor_move = &pv_handle_cursor_move;
|
||||
|
|
|
@ -8,14 +8,21 @@
|
|||
#include <assert.h>
|
||||
#include "linked_list.h"
|
||||
|
||||
LinkedList linked_list_init() {
|
||||
LinkedList linked_list_init(bool circular) {
|
||||
LinkedList list;
|
||||
|
||||
list.circular = circular;
|
||||
list.size = 0;
|
||||
list.head = NULL;
|
||||
list.end = NULL;
|
||||
list.current = NULL;
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
void linked_list_add(LinkedList *list, void *data) {
|
||||
assert(list != NULL);
|
||||
|
||||
LinkedListNode *node = malloc(sizeof(LinkedListNode));
|
||||
if (node == NULL) {
|
||||
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->previous = list->end;
|
||||
node->next = NULL;
|
||||
|
||||
if (list->head == NULL) {
|
||||
list->head = node;
|
||||
list->current = node;
|
||||
}
|
||||
|
||||
if (list->end != NULL) {
|
||||
list->end->next = node;
|
||||
}
|
||||
|
||||
if (list->circular) {
|
||||
node->next = list->head;
|
||||
} else {
|
||||
node->next = NULL;
|
||||
}
|
||||
|
||||
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) {
|
||||
assert(list != NULL);
|
||||
assert(predicate != NULL);
|
||||
|
||||
LinkedListNode *node = list->head;
|
||||
|
||||
while (node != NULL) {
|
||||
|
@ -51,10 +86,13 @@ LinkedListNode *linked_list_get_if(LinkedList *list, bool(*predicate)(void *, vo
|
|||
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;
|
||||
|
||||
int current_distance = predicate(near_node->data, userdata);
|
||||
int current_distance = compute_distance(near_node->data, userdata);
|
||||
if (current_distance == 0) {
|
||||
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) {
|
||||
node = near_node->next;
|
||||
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
|
||||
|
@ -82,5 +120,10 @@ void linked_list_uninit(LinkedList *list) {
|
|||
|
||||
free(current_node->data);
|
||||
free(current_node);
|
||||
|
||||
if (node == list->head) {
|
||||
// The list may be circular, we don't want an infinite free loop
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -14,16 +14,20 @@ typedef struct linked_list_node {
|
|||
} LinkedListNode;
|
||||
|
||||
typedef struct linked_list {
|
||||
bool circular;
|
||||
unsigned int size;
|
||||
LinkedListNode *head;
|
||||
LinkedListNode *end;
|
||||
LinkedListNode *current;
|
||||
} LinkedList;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
LinkedList linked_list_init();
|
||||
LinkedList linked_list_init(bool circular);
|
||||
|
||||
/**
|
||||
* Adds data to a linked list.
|
||||
|
@ -33,6 +37,19 @@ LinkedList linked_list_init();
|
|||
*/
|
||||
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.
|
||||
* 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_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.
|
||||
|
|
Loading…
Reference in New Issue