197 unsigned char cycles = 0;
523 goto branch_page_test;
530 goto branch_page_test;
537 goto branch_page_test;
544 goto branch_page_test;
551 goto branch_page_test;
558 goto branch_page_test;
565 goto branch_page_test;
1212 printf(
"|======== Registers State ========|\n");
1213 printf(
"Accumulator: %i\n", processor->
accumulator);
1214 printf(
"X Register: %i\n", processor->
register_x);
1215 printf(
"Y Register: %i\n", processor->
register_y);
1218 printf(
"Flags: %#02x\n", processor->
flags);
1222 printf(
"|======== Flags State ========|\n");
1223 printf(
"Negative Flag (N): %i\n", (
GET_N_FLAG(processor) >> 7));
1224 printf(
"Overflow Flag (V): %i\n", (
GET_V_FLAG(processor) >> 6));
1225 printf(
"Pause Flag (P): %i\n", (
GET_P_FLAG(processor) >> 5));
1226 printf(
"Break Flag (B): %i\n", (
GET_B_FLAG(processor) >> 4));
1227 printf(
"Decimal Flag (D): %i\n", (
GET_D_FLAG(processor) >> 3));
1228 printf(
"Interrupt Flag (I): %i\n", (
GET_I_FLAG(processor) >> 2));
1229 printf(
"Zero Flag (Z): %i\n", (
GET_Z_FLAG(processor) >> 1));
1230 printf(
"Carry Flag (C): %i\n",
GET_C_FLAG(processor));
1236 printf(
"|======== EXPECTED: Registers State ========|\n");
1237 printf(
"Accumulator: %i\n", acc);
1238 printf(
"X Register: %i\n", x);
1239 printf(
"Y Register: %i\n", y);
1240 printf(
"Program Counter: %#04x\n", pc);
1241 printf(
"Stack Pointer: %#02x\n", sp);
1242 printf(
"Flags: %#02x\n", flags);
1246 printf(
"|======== EXPECTED: Flags State ========|\n");
1247 printf(
"Negative Flag (N): %i\n", ((flags &
BIT_7_MASK) >> 7));
1248 printf(
"Overflow Flag (V): %i\n", ((flags &
BIT_6_MASK) >> 6));
1249 printf(
"Pause Flag (P): %i\n", ((flags &
BIT_5_MASK) >> 5));
1250 printf(
"Break Flag (B): %i\n", ((flags &
BIT_4_MASK) >> 4));
1251 printf(
"Decimal Flag (D): %i\n", ((flags &
BIT_3_MASK) >> 3));
1252 printf(
"Interrupt Flag (I): %i\n", ((flags &
BIT_2_MASK) >> 2));
1253 printf(
"Zero Flag (Z): %i\n", ((flags &
BIT_1_MASK) >> 1));
1254 printf(
"Carry Flag (C): %i\n", (flags &
BIT_0_MASK));
1261 printf(
"<====== Stack State =====>\n");
1269 printf(
"sp: | int |\t | hex |\n\n");
1271 for (uint8_t sp = cpu->
stack_pointer + 1; sp < 0xFF; ++sp) {
1283 printf(
"<===== EXPECTED: Stack State =====>\n");
1284 printf(
"Stack pointer: %#02x\n", start);
1286 if (start == 0xFF) {
1291 printf(
"sp: | int |\t | hex |\n\n");
1293 for (
data sp = start + 1; sp < 0xFF; ++sp) {
1294 printf(
"%#02x: | %i |", sp, stack[sp]);
1295 printf(
"\t | %#02x |\n", stack[sp]);
1298 printf(
"%#02x: | %i |", 0xFF, stack[0xFF]);
1299 printf(
"\t | %#02x |\n", stack[0xFF]);
errcode_t step_cpu(CPU *cpu)
Function that step a clock cycle.
void print_stack_expected(memory stack, data start)
Procedure that display the expected state of the stack.
unsigned char get_next_instruction(CPU *cpu)
Function that get the next instruction written in the ROM.
void init_cpu(CPU *cpu, memory mem)
Procedure that initialize the CPU to its boot/reset state.
void print_cpu_state(CPU *processor)
Procedure that displays the current state of the CPU.
void print_cpu_expected(data acc, data x, data y, data flags, address pc, data sp)
Procedure that display the expected state of the CPU.
void print_stack_state(CPU *cpu)
Procedure that display the current state of the stack.
errcode_t execute_instruction(CPU *cpu)
Function that execute the current instruction in the ROM.
void start_cpu(CPU *cpu)
Procedure that acts like the reset button of the NES.
void free_cpu(CPU *cpu)
Procedure that free the memory used by the CPU and the memory array.
#define ADD_indexed_indirect(processor, addr, offset)
Procedure that perform a ADD with the carry flag (A,Z,C,N=A+M+C) with indexed indirect addressing mod...
#define STR_absolute_X(processor, addr)
Procedure that store the X register value to a memory address.
#define COMPARE_indexed_indirect_ACC(processor, addr, offset)
Procedure that performs a CMP operation (Z, C, N = A - M) with an indexed indirect addressing mode.
#define COMPARE_Immediate_ACC(processor, value)
Procedure that performs a CMP operation (Z,C,N = A - M) with an immediate value.
#define TR_ACC_X(processor)
Procedure that store the value in the accumulator in the X register.
#define OR_indexed_indirect(processor, addr, offset)
Procedure that perform a OR with the carry flag (A,Z,C,N=A+M+C) with indexed indirect addressing mode...
#define PULL_FLAGS(processor)
Procedure that pop the top value of the stack and return it to the flags register.
#define COMPARE_absolute_Y(processor, addr)
Procedure that performs a CMP operation (Z, C, N = Y - M) with an indirect indexed addressing mode.
#define OR_absolute(processor, addr)
Procedure that performs a bitwise logic OR (A,Z,N = A&M) using absolute addressing mode.
#define BRANCH_If_Minus(processor, offset)
Procedure that performs a BMI (branch if positive, if the N flag is clear)
#define AND_indirect_indexed(processor, addr, offset)
Procedure that perform a AND with the carry flag (A,Z,C,N=A+M+C) with indirect indexed.
#define TR_ACC_Y(processor)
Procedure that store the value in accumulator in the Y register.
#define ROTATION_RIGHT_absolute(processor, addr)
Procedure that performs a bit shift with rotation to the right (ROR operation) at the memory address ...
#define ROTATION_RIGHT_offset(processor, addr, offset)
Procedure that performs a bit shift with rotation to the right (ROR operation) at the memory address ...
#define ADD_immediate(processor, data)
Procedure that perform a ADD with the carry flag (A,Z,C,N=A+data+C) with an immediate.
#define SHIFT_RIGHT_absolute(processor, addr)
Procedure that performs a bitshift to the right (LSR operation) at the address addr and place the 0th...
#define ROTATION_RIGHT_ACC(processor)
Procedure that performs a bit shift with rotation to the right (ROR operation) on the accumulator....
#define TR_X_SP(processor)
Procedure that store the value in the X register in the stack pointer.
#define STR_offset_ACC(processor, addr, offset)
Procedure that store the accumulator value to a memory address + offset.
#define XOR_immediate(processor, data)
Procedure that performs a bitwise logic XOR (A,Z,N = A & data)
#define DEC_Y(processor)
Procedure that decrements the Y register.
#define XOR_indexed_indirect(processor, addr, offset)
Procedure that perform a XOR with the carry flag (A,Z,C,N=A+M+C) with indexed indirect addressing mod...
#define get_address(cpu)
Macro to recreate the current address pointed by pc + 1.
#define STR_offset_X(processor, addr, offset)
Procedure that store the X register value to a memory address + offset.
#define DEC_offset(processor, addr, offset)
Procedure that decrement a specific memory location.
#define STR_absolute_ACC(processor, addr)
Procedure that store the accumulator value to a memory address.
#define LD_indirect_indexed_ACC(processor, addr, offset)
Procedure that loads to the accmulator using Inderect Indexed.
#define COMPARE_indirect_indexed_ACC(processor, addr, offset)
Procedure that performs a CMP operation (Z, C, N = A - M) with an indirect indexed addressing mode.
#define OR_immediate(processor, data)
Procedure that performs a bitwise logic OR (A,Z,N = A & data)
#define ADD_indirect_indexed(processor, addr, offset)
Procedure that perform a ADD with the carry flag (A,Z,C,N=A+M+C) with indirect indexed.
#define is_page_crossed(addr, offset)
Macro to know if we cross a page when doing the instruction.
#define AND_absolute(processor, addr)
Procedure that performs a bitwise logic AND (A,Z,N = A&M) using absolute addressing mode.
#define BRANCH_Carry_S(processor, offset)
Procedure that performs a BCS (branch if positive, if the N flag is clear)
#define AND_indexed_indirect(processor, addr, offset)
Procedure that perform a AND with the carry flag (A,Z,C,N=A+M+C) with indexed indirect addressing mod...
#define COMPARE_Immediate_X(processor, value)
Procedure that performs a CMP operation (Z, C, N = X - M) with a value addressing mode.
#define BRANCH_Not_Equal(processor, offset)
Procedure that performs a BNE (if the Z flag is clear)
#define BRANCH_If_Positive(processor, offset)
Procedure that performs a BPL (branch if positive, if the N flag is clear)
#define STR_indirect_indexed_ACC(processor, addr, offset)
Procedure that store the accumulator value to a memory address using indirect indexed addressing mode...
#define INC_offset(processor, addr, offset)
Procedure that increment a specific memory location.
#define COMPARE_offset_ACC(processor, addr, offset)
Procedure that performs a CMP operation (Z, C, N = A - M) with an absolute + offset addressing mode.
#define STR_offset_Y(processor, addr, offset)
Procedure that store the Y register value to a memory address + offset.
#define DEC_X(processor)
Procedure that decrements the X register.
#define BREAK(processor)
Procedure that performs a break instruction (forces an interrupt).
#define RETURN_Subroutine(processor)
Procedure that performs a return from subroutine (RTS instruction) by pulling the top two elements of...
#define LD_absolute_X(processor, addr)
Procedure that loads a value from memory at the address addr to the X register.
#define LD_immediate_ACC(processor, d)
Procedure that loads an immediate (const value) in the accumulator.
#define LD_immediate_X(processor, d)
Procedure that loads an immediate (const value) in the X register.
#define SHIFT_LEFT_ACC(processor)
Procedure that performs a bitshift to the left (ASL operation) on the accumulator and place the 7th b...
#define BIT_TEST(processor, addr)
Procedure that performs a BIT test (A & M, N = M7, V = M6)
#define ADD_offset(processor, addr, offset)
Procedure that perform a ADD with the carry flag (A,Z,C,N=A+M+C) with absolute+offset addressing addr...
#define PUSH_ACC(processor)
Procedure that push the accumulator value to the top of the stack.
#define SHIFT_LEFT_absolute(processor, addr)
Procedure that performs a bitshift to the left (ASL operation) at the address addr and place the 7th ...
#define SBC_indexed_indirect(processor, addr, offset)
Procedure that perform a SBC with the carry flag (A,Z,C,N=A-M-C) with indexed indirect addressing mod...
#define INC_Y(processor)
Procedure that increments the Y register.
#define XOR_absolute(processor, addr)
Procedure that performs a bitwise logic XOR (A,Z,N = A&M) using absolute addressing mode.
#define LD_absolute_Y(processor, addr)
Procedure that loads a value from memory at the address addr to the Y register.
#define JUMP_absolute(processor, addr)
Procedure that sets the program counter to a certain address (JMP instruction)
#define PULL_ACC(processor)
Procedure that pop the top value of the stack and return it to the accumulator.
#define SBC_offset(processor, addr, offset)
Procedure that perform a SBC with the carry flag (A,Z,C,N=A-M-C) with offset addressing mode.
#define SBC_absolute(processor, addr)
Procedure that perform a SBC with the carry flag (A,Z,C,N=A-M-C) with absolute addressing mode.
#define OR_offset(processor, addr, offset)
Procedure that performs a bitwise logic OR (A,Z,N = A&M) using offset addressing mode.
#define SBC_immediate(processor, data)
Procedure that perform a substract with the carry flag (A,Z,C,N=A-data-C) with an immediate.
#define BRANCH_Equal(processor, offset)
Procedure that performs a BEQ (branch if positive, if the N flag is clear)
#define TR_SP_X(processor)
Procedure that store the stack pointer in the X register.
#define LD_indexed_indirect_ACC(processor, addr, offset)
Procedure that loads to the accumulator using Indexed Indirect.
#define LD_offset_ACC(processor, addr, offset)
Procedure that loads a value from memory at address addr+offset to the X register.
#define RETURN_Interrupt(processor)
Procedure that performs a return from interrupt (RTI instruction) by pulling the flags from the top o...
#define LD_absolute_ACC(processor, addr)
Procedure that loads a value from memory at the address addr to the accumulator.
#define COMPARE_Immediate_Y(processor, value)
Procedure that performs a CMP operation (Z, C, N = Y - M) with a value addressing mode.
#define indirect_indexed(cpu, addr, offset)
Macro to access memory by indirect indexed addressing mode.
#define DEC_absolute(processor, addr)
Procedure that decrement a specific memory location.
#define XOR_offset(processor, addr, offset)
Procedure that performs a bitwise logic XOR (A,Z,N = A&M) using offset addressing mode.
#define INC_absolute(processor, addr)
Procedure that increment a specific memory location.
#define AND_offset(processor, addr, offset)
Procedure that performs a bitwise logic AND (A,Z,N = A&M) using offset addressing mode.
#define TR_X_ACC(processor)
Procedure that store the value in the X register in the accumulator.
#define SHIFT_RIGHT_ACC(processor)
Procedure that performs a bitshift to the right (LSR operation) on the accumulator and place the 0th ...
#define OR_indirect_indexed(processor, addr, offset)
Procedure that perform a OR with the carry flag (A,Z,C,N=A+M+C) with indirect indexed.
#define XOR_indirect_indexed(processor, addr, offset)
Procedure that perform a XOR with the carry flag (A,Z,C,N=A+M+C) with indirect indexed.
#define ROTATION_LEFT_offset(processor, addr, offset)
Procedure that performs a bit shift with rotation to the left (ROL operation) at the memory address (...
#define TR_Y_ACC(processor)
Procedure that store the value in the Y register in the accumulator.
#define COMPARE_absolute_X(processor, addr)
Procedure that performs a CMP operation (Z, C, N = X - M) with an indirect indexed addressing mode.
#define SBC_indirect_indexed(processor, addr, offset)
Procedure that perform a SBC with the carry flag (A,Z,C,N=A-M-C) with indirect indexed addressing mod...
#define JUMP_Subroutine(processor, addr)
Procedure that performs a Jump to a subroutine (JSR instruction) located at the address addr.
#define SHIFT_RIGHT_offset(processor, addr, offset)
Procedure that performs a bitshift to the right (LSR operation) at the address (addr + offset) and pl...
#define LD_immediate_Y(processor, d)
Procedure that loads an immediate (const value) in the Y register.
#define JUMP_indirect(processor, addr)
Procedure that sets the program counter to a certain indirect address (JMP instruction)
#define COMPARE_absolute_ACC(processor, addr)
Procedure that performs a CMP operation (Z, C, N = A - M) with an absolute addressing mode.
#define INC_X(processor)
Procedure that increments the X register.
#define ADD_absolute(processor, addr)
Procedure that perform a ADD with the carry flag (A,Z,C,N=A+M+C) with absolute addressing mode.
#define BRANCH_Overflow_S(processor, offset)
Procedure that performs a BVS (branch if positive, if the N flag is clear)
#define BRANCH_Overflow_C(processor, offset)
Procedure that performs a BVC (branch if overflow clear, if the V flag is clear)
#define ROTATION_LEFT_absolute(processor, addr)
Procedure that performs a bit shift with rotation to the left (ROL operation) at the memory address a...
#define PUSH_FLAGS(processor)
Procedure that push the processor flags to the top of the stack.
#define LD_offset_X(processor, addr, offset)
Procedure that loads a value from memory at address addr+offset to the X register.
#define AND_immediate(processor, data)
Procedure that performs a bitwise logic AND (A,Z,N = A & data)
#define BRANCH_Carry_C(processor, offset)
Procedure that performs a BCC (if the C flag is clear)
#define STR_absolute_Y(processor, addr)
Procedure that store the Y register value to a memory address.
#define ROTATION_LEFT_ACC(processor)
Procedure that performs a bit shift with rotation to the left (ROL operation) on the accumulator....
#define SHIFT_LEFT_offset(processor, addr, offset)
Procedure that performs a bitshift to the left (ASL operation) at the address (addr + offset) and pla...
#define STR_indexed_indirect_ACC(processor, addr, offset)
Procedure that store the accumulator value to a memory address using indexes indirect addressing mode...
#define LD_offset_Y(processor, addr, offset)
Procedure that loads a value from memory at address addr+offset to the Y register.
void free_memory(memory mem)
This procedure free the memory pointer.
void memory_mirroring(memory mem)
This procedure make the memory mirroring.
@ LSR_ZX
LSR Zero Page, X.
@ RTI
Return from the current interrupt.
@ CMP_IdX
CMP (Indirect, X)
@ ROL_ZX
ROL Zero Page, X.
@ CMP_IdY
CMP (Indirect), Y.
@ ASL_ZX
ASL Zero Page, X.
@ ORA_ZX
ORA Zero Page, X.
@ SBC_ZX
SBC Zero Page, X.
@ LDX_ZY
LDX Zero Page, Y.
@ ADC_IdX
ADC (Indirect, X)
@ LDY_ZX
LDY Zero Page, X.
@ AND_ZX
AND Zero Page, X.
@ INC_ZX
INC Zero Page, X.
@ PLP
flags = pull(); sp = sp + 1;
@ ADC_ZX
ADC Zero Page, X.
@ AND_IdX
AND (Indirect, X)
@ CMP_ZX
CMP Zero Page, X.
@ PHP
push(flags); sp = sp - 1;
@ EOR_ZX
EOR Zero Page, X.
@ LDA_ZX
LDA Zero Page, X.
@ AND_IdY
AND (Indirect), Y.
@ SBC_IdY
SBC (Indirect), Y.
@ ADC_IdY
ADC (Indirect), Y.
@ ROR_ZX
ROR Zero Page, X.
@ STA_IdY
STA (Indirect), Y.
@ SBC_IdX
SBC (Indirect, X)
@ STY_ZX
STY Zero Page, X.
@ ORA_IdY
ORA (Indirect), Y.
@ STA_IdX
STA (Indirect, X)
@ STX_ZY
STX Zero Page, Y.
@ PLA
ACC = pull(); sp = sp + 1;.
@ STA_ZX
STA Zero Page, X.
@ EOR_IdX
EOR (Indirect, X)
@ DEC_ZX
DEC Zero Page, X.
@ EOR_IdY
EOR (Indirect), Y.
@ LDA_IdX
LDA (Indirect, X)
@ LDA_IdY
LDA (Indirect), Y.
@ PHA
push(ACC); sp = sp - 1;
@ ORA_IdX
ORA (Indirect, X)
@ RTS
Return from the current subroutine.
@ JSR
Jump to the subroutine.
This structure will be used to represent the state of the Central Processing Unit (CPU) of our emulat...
data cache
A 8 bit reserved space that I use for some operations.
data accumulator
A 8 bit register used to perform operations.
data register_y
A 8 bit register. Commonly used to hold offset and counters.
address program_counter
An address pointing to the next instruction to be executed.
unsigned char cycle_counter
The cycle counter. The counter is decremented every step.
data stack_pointer
A register that holds the 8 lower bytes of the address 0x11??.
memory mem
A direct access to the Emulator Memory.
data register_x
A 8 bit register. Commonly used to hold offset and counters.
two_bytes_word address
Definition of the address format used by the CPU.
byte errcode_t
Definition of the error code type used by some function.
byte data
Definition of the data format used by the CPU.