From 3bf4e77bafdce43e0781f6ed1981a8c506d8b772 Mon Sep 17 00:00:00 2001 From: leo Date: Sun, 15 Oct 2023 15:53:39 -0300 Subject: aaaaaaaaaaaaa --- CPU.c | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 115 insertions(+), 15 deletions(-) diff --git a/CPU.c b/CPU.c index cf95cbd..de8a0a7 100644 --- a/CPU.c +++ b/CPU.c @@ -5,43 +5,122 @@ struct CPU{ uint8_t register_a; + uint8_t register_x; uint8_t status; uint16_t pc; + uint8_t memory[0xFFFF]; }; +struct CPU create_cpu(); +int array_size(uint8_t *program); +uint8_t mem_read(struct CPU *cpu, uint16_t addr); +void mem_write(struct CPU *cpu, uint16_t addr, uint8_t data); +void load(struct CPU *cpu, uint8_t *program); +void load_and_run(struct CPU *cpu, uint8_t *program); +void reset_cpu(struct CPU *cpu); +void update_zero_and_negative_flags(struct CPU *cpu, uint8_t result); +void lda(struct CPU *cpu, uint8_t value); +void interpret(struct CPU *cpu); +uint16_t mem_read_u16(struct CPU *cpu, uint16_t pos); + struct CPU create_cpu(){ struct CPU cpu = { .register_a = 0, + .register_x = 0, .status = 0, .pc = 0 }; return cpu; } -void interpret(struct CPU *cpu, uint8_t *program){ - cpu->pc = 0; +int array_size(uint8_t *program){ + return sizeof(program) / sizeof(program[0]); +} + +uint8_t mem_read(struct CPU *cpu, uint16_t addr){ + return cpu->memory[addr]; +} + +void mem_write(struct CPU *cpu, uint16_t addr, uint8_t data){ + cpu->memory[addr] = data; +} + +uint16_t mem_read_u16(struct CPU *cpu, uint16_t pos){ + //little-endian + uint16_t lo = (uint16_t)mem_read(cpu, pos); + uint16_t hi = (uint16_t)mem_read(cpu, pos+1); + return (hi<<8) | (lo); +} + +void mem_write_u16(struct CPU *cpu, uint16_t pos, uint16_t data){ + uint8_t hi = (uint8_t)(data>>8); + uint8_t lo = (uint8_t)(data & 0x00ff); + mem_write(cpu, pos, lo); + mem_write(cpu, pos+1, hi); +} + +void load(struct CPU *cpu, uint8_t *program){ + for(int i=0; i < array_size(program); ++i){ + cpu->memory[0x8000+i] = program[i]; + } + mem_write_u16(cpu, 0xfffc, 0x8000); +} + +void load_and_run(struct CPU *cpu, uint8_t *program){ + load(cpu, program); + reset_cpu(cpu); + interpret(cpu); +} + +void reset_cpu(struct CPU *cpu){ + (*cpu).register_a = 0; + (*cpu).register_x = 0; + (*cpu).status = 0; + (*cpu).pc = mem_read_u16(cpu, 0xfffc); +} + +void update_zero_and_negative_flags(struct CPU *cpu, uint8_t result){ + if(result == 0) + cpu->status |= 0b00000010; + else + cpu->status &= 0b11111101; + + if((result & 0b10000000) != 0) + cpu->status |= 0b10000000; + else + cpu->status &= 0b01111111; +} + +void lda(struct CPU *cpu, uint8_t value){ + cpu->register_a = value; + update_zero_and_negative_flags(cpu, cpu->register_a); +} + +void interpret(struct CPU *cpu){ while(1){ - uint8_t opcode = program[cpu->pc]; + uint8_t opcode = mem_read(cpu, cpu->pc); cpu->pc += 1; switch(opcode){ case 0x00: return; + case 0xAA: + cpu->register_x = cpu->register_a; + update_zero_and_negative_flags(cpu, cpu->register_x); + + break; case 0xA9: - uint8_t param = program[cpu->pc]; + uint8_t param = mem_read(cpu, cpu->pc); cpu->pc += 1; - cpu->register_a = param; + lda(cpu, param); - if(cpu->register_a == 0) - cpu->status |= 0b00000010; - else - cpu->status &= 0b11111101; + break; + case 0xE8: + cpu->register_x++; + update_zero_and_negative_flags(cpu, cpu->register_x); - if((cpu->register_a & 0b10000000) != 0) - cpu->status |= 0b10000000; - else - cpu->status &= 0b01111111; + break; default: break; } @@ -54,7 +133,7 @@ int main(){ printf("test_0xa9_lda_immediate_load_data: "); struct CPU cpu_1 = create_cpu(); uint8_t program_1[] = {0xa9, 0x05, 0x00}; - interpret(&cpu_1, program_1); + load_and_run(&cpu_1, program_1); assert(cpu_1.register_a == 0x05); assert((cpu_1.status & 0b00000010) == 0b00); assert((cpu_1.status & 0b10000000) == 0); @@ -63,7 +142,28 @@ int main(){ printf("test_0xa9_lda_zero_flag: "); struct CPU cpu_2 = create_cpu(); uint8_t program_2[] = {0xa9, 0x00, 0x00}; - interpret(&cpu_2, program_2); + load_and_run(&cpu_2, program_2); assert((cpu_2.status & 0b00000010) == 0b00000010); printf("PASSED\n"); + + printf("text_0xaa_tax_move_a_to_x: "); + struct CPU cpu_3 = create_cpu(); + uint8_t program_3[] = {0xa9, 10, 0xaa, 0x00}; + load_and_run(&cpu_3, program_3); + assert(cpu_3.register_x == 10); + printf("PASSED\n"); + + printf("test_5_ops_working_together: "); + struct CPU cpu_4 = create_cpu(); + uint8_t program_4[] = {0xa9, 0xc0, 0xaa, 0xe8, 0x00}; + load_and_run(&cpu_4, program_4); + assert(cpu_4.register_x == 0xC1); + printf("PASSED\n"); + + printf("test_inx_overflow: "); + struct CPU cpu_5 = create_cpu(); + uint8_t program_5[] = {0xa9, 0xff, 0xaa, 0xe8, 0xe8, 0x00}; + load_and_run(&cpu_5, program_5); + assert(cpu_5.register_x == 1); + printf("PASSED\n"); } \ No newline at end of file -- cgit v1.2.3