12 printf(
"|======== Registers State ========|\n");
13 printf(
"Accumulator: %i\n", processor->
accumulator);
14 printf(
"X Register: %i\n", processor->
register_x);
15 printf(
"Y Register: %i\n", processor->
register_y);
18 printf(
"Flags: %#02x\n", processor->
flags);
22 printf(
"|======== Flags State ========|\n");
23 printf(
"Negative Flag (N): %i\n", (
GET_N_FLAG(processor) >> 7));
24 printf(
"Overflow Flag (V): %i\n", (
GET_V_FLAG(processor) >> 6));
25 printf(
"Pause Flag (P): %i\n", (
GET_P_FLAG(processor) >> 5));
26 printf(
"Break Flag (B): %i\n", (
GET_B_FLAG(processor) >> 4));
27 printf(
"Decimal Flag (D): %i\n", (
GET_D_FLAG(processor) >> 3));
28 printf(
"Interrupt Flag (I): %i\n", (
GET_I_FLAG(processor) >> 2));
29 printf(
"Zero Flag (Z): %i\n", (
GET_Z_FLAG(processor) >> 1));
30 printf(
"Carry Flag (C): %i\n",
GET_C_FLAG(processor));
36 printf(
"|======== EXPECTED: Registers State ========|\n");
37 printf(
"Accumulator: %i\n", acc);
38 printf(
"X Register: %i\n", x);
39 printf(
"Y Register: %i\n", y);
40 printf(
"Program Counter: %#04x\n", pc);
41 printf(
"Stack Pointer: %#02x\n", sp);
42 printf(
"Flags: %#02x\n", flags);
46 printf(
"|======== EXPECTED: Flags State ========|\n");
47 printf(
"Negative Flag (N): %i\n", ((flags &
BIT_7_MASK) >> 7));
48 printf(
"Overflow Flag (V): %i\n", ((flags &
BIT_6_MASK) >> 6));
49 printf(
"Pause Flag (P): %i\n", ((flags &
BIT_5_MASK) >> 5));
50 printf(
"Break Flag (B): %i\n", ((flags &
BIT_4_MASK) >> 4));
51 printf(
"Decimal Flag (D): %i\n", ((flags &
BIT_3_MASK) >> 3));
52 printf(
"Interrupt Flag (I): %i\n", ((flags &
BIT_2_MASK) >> 2));
53 printf(
"Zero Flag (Z): %i\n", ((flags &
BIT_1_MASK) >> 1));
54 printf(
"Carry Flag (C): %i\n", (flags &
BIT_0_MASK));
61 printf(
"<====== Stack State =====>\n");
69 printf(
"sp: | int |\t | hex |\n\n");
83 printf(
"<===== EXPECTED: Stack State =====>\n");
84 printf(
"Stack pointer: %#02x\n", start);
91 printf(
"sp: | int |\t | hex |\n\n");
93 for (
data sp = start + 1; sp < 0xFF; ++sp) {
94 printf(
"%#02x: | %i |", sp, stack[sp]);
95 printf(
"\t | %#02x |\n", stack[sp]);
98 printf(
"%#02x: | %i |", 0xFF, stack[0xFF]);
99 printf(
"\t | %#02x |\n", stack[0xFF]);
104int main(
int argc,
char** argv) {
109 while ((opt = getopt(argc, argv,
":i:")) != -1) {
112 printf(
"Filepath: %s\n", optarg);
114 if (my_rom != NULL) {
126 data stack_test[256];
132 for (
unsigned int i = 0; i < 50; ++i) {
136 printf(
"##### Load Tests #####\n\n");
159 cpu->
mem[0 | 1 << 8] = 121;
160 cpu->
mem[1 | 2 << 8] = 122;
161 cpu->
mem[2 | 3 << 8] = 123;
173 printf(
"##### INC/DEC Tests #####\n\n");
187 printf(
"##### Indirections test #####\n\n");
189 cpu->
mem[(5) | (6) << 8] = 150;
200 cpu->
mem[((1) | (1) << 8) + 2] = 5;
209 stack_test[0xFF] = 5;
211 printf(
"##### PUSH/PULL tests #####\n\n");
233 stack_test[0xFF] = 0xFC;
234 stack_test[0xFE] = 0xFF;
239 stack_test[0xFF] = 0x0C;
240 stack_test[0xFE] = 0x81;
257 stack_test[0xFF] = 0x9c;
277 printf(
"##### ADD Tests #####\n\n");
311 cpu->
mem[0x1111] = 20;
337 printf(
"##### And Tests #####\n\n");
344 cpu->
mem[0x5040] = 0xf1;
361 cpu->
mem[0x1111] = 0x00;
375 printf(
"##### Or Tests #####\n\n");
382 cpu->
mem[0] = 0b00000010;
389 cpu->
mem[1] = 0b00000100;
398 cpu->
mem[0x1111] = 0b00001000;
405 cpu->
mem[0x1111] = 0b00010000;
412 printf(
"##### Xor Tests #####\n\n");
420 cpu->
mem[0] = 0b11000011;
427 cpu->
mem[1] = 0b10101010;
436 cpu->
mem[0x5555] = 0b01010101;
443 cpu->
mem[0x5555] = 0xff;
450 printf(
"##### Sbc Tests #####\n\n");
477 cpu->
mem[0x1111] = 10;
489 printf(
"##### TR Tests #####\n\n");
529 printf(
"##### STR Tests #####\n\n");
532 printf(
"\nExpected: 10 | %i\n", cpu->
mem[0x1100]);
535 printf(
"\nExpected: 10 | %i\n", cpu->
mem[0x1101]);
538 printf(
"\nExpected: 10 | %i\n", cpu->
mem[0x1102]);
545 printf(
"\nExpected: 15 | %i\n", cpu->
mem[0x05]);
548 printf(
"\nExpected: 16 | %i\n", cpu->
mem[0x06]);
551 printf(
"\nExpected: 17 | %i\n", cpu->
mem[0x07]);
559 printf(
"##### BIT Tests #####\n\n");
561 cpu->
mem[0x00] = 0xFF;
562 cpu->
mem[0x01] = 0b00110011;
563 cpu->
mem[0x02] = 0x00;
590 printf(
"##### Branch Tests #####\n\n");
640 printf(
"##### Shifts Tests #####\n\n");
655 for (
int i = 0; i < 3; ++i) {
663 cpu->
mem[10] = 0b10000001;
670 printf(
"\nExpected: 2 | %i\n\n", cpu->
mem[10]);
677 printf(
"\nExpected: 4 | %i\n\n", cpu->
mem[10]);
684 printf(
"\nExpected: 2 | %i\n\n", cpu->
mem[10]);
692 printf(
"\nExpected: 0 | %i\n\n", cpu->
mem[10]);
694 printf(
"##### Rotations Tests #####\n\n");
728 cpu->
mem[10] = 0b00000110;
735 printf(
"\nExpected: 1 | %i\n\n", cpu->
mem[10]);
743 printf(
"\nExpected: %i | %i\n\n", 0b11000000, cpu->
mem[10]);
753 printf(
"\nExpected: 1 | %i\n\n", cpu->
mem[10]);
761 printf(
"\nExpected: 6 | %i\n\n", cpu->
mem[10]);
763 printf(
"##### Jump Tests #####\n\n");
770 cpu->
mem[0x00ff] = 0x0c;
771 cpu->
mem[0x0100] = 0x81;
778 printf(
"##### Break Test #####\n\n");
780 cpu->
mem[0xfffe] = 0xaa;
781 cpu->
mem[0xffff] = 0xff;
783 stack_test[0xff] = 0x81;
784 stack_test[0xfe] = 0x0c;
785 stack_test[0xfd] = 0;
795 printf(
"##### RTI, RTS, JSR Test #####\n\n");
804 stack_test[0xff] = 0x81;
805 stack_test[0xfe] = 0x0e;
820 if (my_rom != NULL) {
#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 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 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 LD_indirect_ACC(processor, addr)
Procedure that lods a value from memory at the address contained in addr|addr+1. (indirection)
#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...
void init_cpu(CPU *cpu, memory mem)
Procedure that initialize the CPU to its boot/reset state.
#define STR_offset_X(processor, addr, offset)
Procedure that store the X register value to a memory address + offset.
#define PULL_PC(processor)
Procedure that pop the top value of the stack and return it to the program counter.
#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 OR_immediate(processor, data)
Procedure that performs a bitwise logic OR (A,Z,N = A & data)
#define LD_indirect_X(processor, addr)
Procedure that lods a value from memory at the address contained in addr|addr+1. (indirection)
#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 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 LD_indirect_Y(processor, addr)
Procedure that lods a value from memory at the address contained in addr|addr+1. (indirection)
#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 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 indirect_indexed(cpu, addr, offset)
Macro to access memory by indirect indexed addressing mode.
#define CLEAR_ALL_FLAGS(x)
#define XOR_offset(processor, addr, offset)
Procedure that performs a bitwise logic XOR (A,Z,N = A&M) using offset addressing mode.
#define PUSH_PC(processor)
Procedure that push the program_counter to the top of the stack.
#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 indexed_indirect(cpu, addr, offset)
Macro to access memory by indexed indirect addressing mode.
#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 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 INC_X(processor)
Procedure that increments the X register.
#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)
void free_cpu(CPU *cpu)
Procedure that free the memory used by the CPU and the memory array.
#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 reset_memory(memory mem)
This procedure set the entire memory to 0.
memory init_memory()
This function allocate on the heap a memory of exactly TOTAL_MEMORY_SIZE.
void free_rom(rom *r)
Frees the rom struct.
void display_rom(rom *r)
Procedure that displays the content of the rom in hexadecimal.
rom * open_rom(char *filepath)
A function that open the NES rom at a specified path.
This structure will be used to represent the state of the Central Processing Unit (CPU) of our emulat...
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.
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 data
Definition of the data format used by the CPU.
void print_stack_expected(memory stack, data start)
Procedure that display the expected state of the stack.
int main(int argc, char **argv)
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.