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 ===
|
// === 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 {
|
||||||
|
|
|
@ -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.
|
||||||
|
|
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) {
|
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;
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
|
@ -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(¤t_window->cursor);
|
cursor_enable(¤t_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(¤t_window->cursor);
|
cursor_disable(¤t_window->cursor);
|
||||||
current_window = &windows[window_index];
|
current_window = linked_list_next(&interactive_windows)->data;
|
||||||
cursor_enable(¤t_window->cursor);
|
cursor_enable(¤t_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();
|
||||||
}
|
}
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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.
|
||||||
|
|
Loading…
Reference in New Issue