diff options
author | leo <leo@azuminha.com> | 2024-07-07 03:31:34 -0300 |
---|---|---|
committer | leo <leo@azuminha.com> | 2024-07-07 03:31:34 -0300 |
commit | 93c7430dbe4dceb8f8e90cede2d5a65d1fdba2a9 (patch) | |
tree | 2e8a53163860ed94edf5ce462b08ea8a12928b86 | |
parent | 1cffb789b5d258c3d6fced0fb949f068b1b23bae (diff) |
-rw-r--r-- | CPU.c | 1097 | ||||
-rw-r--r-- | CPU.h | 59 | ||||
-rw-r--r-- | opcode_pc.h | 369 |
3 files changed, 1127 insertions, 398 deletions
@@ -6,347 +6,898 @@ #include "CPU.h" #include "opcode_pc.h" +#include <raylib.h> + +#define STACK 0x0100 +#define STACK_RESET 0xfd + struct CPU create_cpu(){ - struct CPU cpu = { - .register_a = 0, - .register_x = 0, - .register_y = 0, - .status = 0, - .pc = 0 - }; - return cpu; + struct CPU cpu = { + .register_a = 0, + .register_x = 0, + .register_y = 0, + .status = 0, + .pc = 0, + .sp = STACK_RESET + }; + return cpu; +} + +uint8_t stack_pop(struct CPU *cpu){ + cpu->sp += 1; + uint8_t data = mem_read(cpu, (uint16_t)STACK | (uint16_t)cpu->sp); + return data; +} + +void stack_push(struct CPU *cpu, uint8_t data){ + uint16_t addr = (uint16_t)STACK | (uint16_t)cpu->sp; + mem_write(cpu, addr, data); + cpu->sp -= 1; } -int array_size(uint8_t *program){ - return sizeof(program) / sizeof(program[0]); +void stack_push_u16(struct CPU *cpu, uint16_t data){ + uint8_t hi = data >> 8; + uint8_t lo = data & 0xFF; + stack_push(cpu, hi); + stack_push(cpu, lo); +} + +uint16_t stack_pop_u16(struct CPU *cpu){ + uint16_t lo = (uint16_t)stack_pop(cpu); + uint16_t hi = (uint16_t)stack_pop(cpu); + uint16_t data = (hi << 8) | lo; + return data; } uint8_t mem_read(struct CPU *cpu, uint16_t addr){ - return cpu->memory[addr]; + return cpu->memory[addr]; } void mem_write(struct CPU *cpu, uint16_t addr, uint8_t data){ - cpu->memory[addr] = 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); + //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); + 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); + for(int i=0; i < array_size(program); ++i){ + cpu->memory[0x8000+i] = program[i]; + } + mem_write_u16(cpu, 0xfffc, 0x8000); +} +*/ +void load(struct CPU *cpu, uint8_t *program, int size_of_program){ + for(int i=0; i < size_of_program; ++i){ + cpu->memory[0x0600+i] = program[i]; + } + mem_write_u16(cpu, 0xfffc, 0x0600); } -void load_and_run(struct CPU *cpu, uint8_t *program){ - load(cpu, program); - reset_cpu(cpu); - interpret(cpu); +void load_and_run(struct CPU *cpu, uint8_t *program, int size_of_program){ + load(cpu, program, size_of_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); + (*cpu).register_a = 0; + (*cpu).register_x = 0; + (*cpu).status = 0; + (*cpu).pc = mem_read_u16(cpu, 0xfffc); } uint16_t get_operand_address(struct CPU *cpu, enum adressing_mode mode){ - switch(mode){ - case Immediate: - return cpu->pc; - case ZeroPage: - return (uint16_t)mem_read(cpu, cpu->pc); - - case Absolute: - return mem_read_u16(cpu, cpu->pc); - - case ZeroPage_X: - { - uint8_t pos = mem_read(cpu, cpu->pc); - uint16_t addr = (pos + cpu->register_x) % 0x100; - return addr; - } - - case ZeroPage_Y: - { - uint8_t pos = mem_read(cpu, cpu->pc); - uint16_t addr = (pos + cpu->register_y) % 0x100; - return addr; - } - - case Absolute_X: - { - uint16_t pos = mem_read_u16(cpu, cpu->pc); - uint16_t addr = (pos + (uint16_t)cpu->register_x) % 0x10000; - return addr; - } - - case Absolute_Y: - { - uint16_t pos = mem_read_u16(cpu, cpu->pc); - uint16_t addr = (pos + (uint16_t)cpu->register_y) % 0x10000; - return addr; - } - - case Indirect_X: - { - uint8_t pos = mem_read(cpu, cpu->pc); - - uint8_t ptr = (pos + cpu->register_x) % 0x100; - uint8_t lo = mem_read(cpu, (uint16_t)ptr); - uint8_t hi = mem_read(cpu, (uint16_t)((ptr+1) % 0x100)); - return ((uint16_t)hi << 8) | ((uint16_t)lo); - } - - case Indirect_Y: - { - uint8_t pos = mem_read(cpu, cpu->pc); - - uint8_t lo = mem_read(cpu, (uint16_t)pos); - uint8_t hi = mem_read(cpu, (uint16_t)((pos+1) % 0x100)); - uint16_t deref_pos = ((uint16_t)hi << 8) | (uint16_t)lo; - uint16_t deref = (deref_pos + (uint16_t)cpu->register_y) % 0x10000; - return deref; - } - - case NoneAddressing: - exit(1); - break; - } + switch(mode){ + case Immediate: + return cpu->pc; + case ZeroPage: + return (uint16_t)mem_read(cpu, cpu->pc); + + case Absolute: + return mem_read_u16(cpu, cpu->pc); + + case ZeroPage_X: + { + uint8_t pos = mem_read(cpu, cpu->pc); + uint16_t addr = (pos + cpu->register_x) % 0x100; + return addr; + } + + case ZeroPage_Y: + { + uint8_t pos = mem_read(cpu, cpu->pc); + uint16_t addr = (pos + cpu->register_y) % 0x100; + return addr; + } + + case Absolute_X: + { + uint16_t pos = mem_read_u16(cpu, cpu->pc); + uint16_t addr = (pos + (uint16_t)cpu->register_x) % 0x10000; + return addr; + } + + case Absolute_Y: + { + uint16_t pos = mem_read_u16(cpu, cpu->pc); + uint16_t addr = (pos + (uint16_t)cpu->register_y) % 0x10000; + return addr; + } + + case Indirect_X: + { + uint8_t pos = mem_read(cpu, cpu->pc); + + uint8_t ptr = (pos + cpu->register_x) % 0x100; + uint8_t lo = mem_read(cpu, (uint16_t)ptr); + uint8_t hi = mem_read(cpu, (uint16_t)((ptr+1) % 0x100)); + return ((uint16_t)hi << 8) | ((uint16_t)lo); + } + + case Indirect_Y: + { + uint8_t pos = mem_read(cpu, cpu->pc); + + uint8_t lo = mem_read(cpu, (uint16_t)pos); + uint8_t hi = mem_read(cpu, (uint16_t)((pos+1) % 0x100)); + uint16_t deref_pos = ((uint16_t)hi << 8) | (uint16_t)lo; + uint16_t deref = (deref_pos + (uint16_t)cpu->register_y) % 0x10000; + return deref; + } + + case NoneAddressing: + exit(1); + break; + } } void update_zero_and_negative_flags(struct CPU *cpu, uint8_t result){ - if(result == 0) - enable_flag(cpu, ZERO);//cpu->status |= 0b00000010; - else - disable_flag(cpu, ZERO);//cpu->status &= 0b11111101; - - if((result & 0b10000000) != 0) - cpu->status |= 0b10000000; - else - cpu->status &= 0b01111111; + if(result == 0) + enable_flag(cpu, ZERO);//cpu->status |= 0b00000010; + else + disable_flag(cpu, ZERO);//cpu->status &= 0b11111101; + + if((result & 0b10000000) != 0) + cpu->status |= 0b10000000; + else + cpu->status &= 0b01111111; } void lda(struct CPU *cpu, enum adressing_mode mode/*uint8_t value*/){ - uint16_t addr = get_operand_address(cpu, mode); - uint8_t value = mem_read(cpu, addr); + uint16_t addr = get_operand_address(cpu, mode); + uint8_t value = mem_read(cpu, addr); + + cpu->register_a = value; + update_zero_and_negative_flags(cpu, cpu->register_a); + // cpu->register_a = value; + // update_zero_and_negative_flags(cpu, cpu->register_a); +} + +void ldx(struct CPU *cpu, enum adressing_mode mode){ + uint16_t addr = get_operand_address(cpu, mode); + uint8_t value = mem_read(cpu, addr); + + cpu->register_x = value; + update_zero_and_negative_flags(cpu, cpu->register_x); +} + +void ldy(struct CPU *cpu, enum adressing_mode mode){ + uint16_t addr = get_operand_address(cpu, mode); + uint8_t value = mem_read(cpu, addr); + + cpu->register_y = value; + update_zero_and_negative_flags(cpu, cpu->register_y); +} + +void dec(struct CPU *cpu, enum adressing_mode mode){ + uint16_t addr = get_operand_address(cpu, mode); + uint8_t value = mem_read(cpu, addr); + + uint8_t data = value - 1; + mem_write(cpu, addr, data); + update_zero_and_negative_flags(cpu, data); +} + +void eor(struct CPU *cpu, enum adressing_mode mode){ + uint16_t addr = get_operand_address(cpu, mode); + uint8_t value = mem_read(cpu, addr); - cpu->register_a = value; - update_zero_and_negative_flags(cpu, cpu->register_a); - // cpu->register_a = value; - // update_zero_and_negative_flags(cpu, cpu->register_a); + cpu->register_a ^= value; + update_zero_and_negative_flags(cpu, cpu->register_a); +} + +void inc(struct CPU *cpu, enum adressing_mode mode){ + uint16_t addr = get_operand_address(cpu, mode); + uint8_t value = mem_read(cpu, addr); + + uint8_t data = value + 1; + mem_write(cpu, addr, data); + update_zero_and_negative_flags(cpu, data); } void sta(struct CPU *cpu, enum adressing_mode mode){ - uint16_t addr = get_operand_address(cpu, mode); - mem_write(cpu, addr, cpu->register_a); + uint16_t addr = get_operand_address(cpu, mode); + mem_write(cpu, addr, cpu->register_a); +} + +void stx(struct CPU *cpu, enum adressing_mode mode){ + uint16_t addr = get_operand_address(cpu, mode); + mem_write(cpu, addr, cpu->register_x); +} + +void sty(struct CPU *cpu, enum adressing_mode mode){ + uint16_t addr = get_operand_address(cpu, mode); + mem_write(cpu, addr, cpu->register_y); } void and(struct CPU *cpu, enum adressing_mode mode){ - uint16_t addr = get_operand_address(cpu, mode); - uint8_t value = mem_read(cpu, addr); + uint16_t addr = get_operand_address(cpu, mode); + uint8_t value = mem_read(cpu, addr); - cpu->register_a &= value; - update_zero_and_negative_flags(cpu, cpu->register_a); + cpu->register_a &= value; + update_zero_and_negative_flags(cpu, cpu->register_a); } void enable_flag(struct CPU *cpu, uint8_t flag){ - cpu->status |= flag; + cpu->status |= flag; } void disable_flag(struct CPU *cpu, uint8_t flag){ - cpu->status &= ~flag; + cpu->status &= ~flag; } int test_flag(struct CPU *cpu, uint8_t flag){ - return (flag & cpu->status) > 0; + return (flag & cpu->status) > 0; } void branch(struct CPU *cpu, bool cond){ - if(cond){ - int8_t jump = mem_read(cpu, cpu->pc); - cpu->pc = (cpu->pc + jump + 1) % 0x10000; - } + if(cond){ + int8_t jump = mem_read(cpu, cpu->pc); + cpu->pc = (cpu->pc + jump + 1) % 0x10000; + } } void asl(struct CPU *cpu, enum adressing_mode mode){ - uint16_t addr = get_operand_address(cpu, mode); - uint8_t value = mem_read(cpu, addr); + uint16_t addr = get_operand_address(cpu, mode); + uint8_t value = mem_read(cpu, addr); - if(value >> 7 == 1) enable_flag(cpu, CARRY); - else disable_flag(cpu, CARRY); + if(value >> 7 == 1) enable_flag(cpu, CARRY); + else disable_flag(cpu, CARRY); - value = value << 1; - mem_write(cpu, addr, value); - update_zero_and_negative_flags(cpu, value); + value = value << 1; + mem_write(cpu, addr, value); + update_zero_and_negative_flags(cpu, value); } void compare(struct CPU *cpu, enum adressing_mode mode, uint8_t comp_val){ - uint16_t addr = get_operand_address(cpu, mode); - uint8_t value = mem_read(cpu, addr); + uint16_t addr = get_operand_address(cpu, mode); + uint8_t value = mem_read(cpu, addr); - if(comp_val >= value){ - enable_flag(cpu, CARRY); - }else{ - disable_flag(cpu, CARRY); - } + if(comp_val >= value){ + enable_flag(cpu, CARRY); + }else{ + disable_flag(cpu, CARRY); + } - update_zero_and_negative_flags(cpu, (comp_val - value)); + update_zero_and_negative_flags(cpu, (comp_val - value)); +} + +void lsr(struct CPU *cpu, enum adressing_mode mode){ + uint16_t addr = get_operand_address(cpu, mode); + uint8_t data = mem_read(cpu, addr); + if(data & 1){ + enable_flag(cpu, CARRY); + }else{ + disable_flag(cpu, CARRY); + } + data = data >> 1; + mem_write(cpu, addr, data); + update_zero_and_negative_flags(cpu, data); +} + +void ora(struct CPU *cpu, enum adressing_mode mode){ + uint16_t addr = get_operand_address(cpu, mode); + uint8_t value = mem_read(cpu, addr); + + cpu->register_a |= value; + update_zero_and_negative_flags(cpu, cpu->register_a); +} + +void rol(struct CPU *cpu, enum adressing_mode mode){ + if(mode == NoneAddressing){ + int c = test_flag(cpu, CARRY); + uint8_t value = cpu->register_a; + if((value >> 7) == 1){ + enable_flag(cpu, CARRY); + }else{ + disable_flag(cpu, CARRY); + } + + value = value << 1; + if(c == 1){ + value |= 1; + }else{ + } + cpu->register_a = value; + update_zero_and_negative_flags(cpu, cpu->register_a); + }else{ + int c = test_flag(cpu, CARRY); + uint16_t addr = get_operand_address(cpu, mode); + uint8_t value = mem_read(cpu, addr); + if((value >> 7) == 1){ + enable_flag(cpu, CARRY); + }else{ + disable_flag(cpu, CARRY); + } + + value = value << 1; + if(c == 1){ + value |= 1; + }else{ + } + mem_write(cpu, addr, value); + update_zero_and_negative_flags(cpu, value); + } +} + +void ror(struct CPU *cpu, enum adressing_mode mode){ + if(mode == NoneAddressing){ + int c = test_flag(cpu, CARRY); + uint8_t data = cpu->register_a; + if((data & 1) == 1){ + enable_flag(cpu, CARRY); + }else{ + disable_flag(cpu, CARRY); + } + + data = data >> 1; + if(c == 1){ + data |= 0b10000000; + }else{ + } + + cpu->register_a = data; + update_zero_and_negative_flags(cpu, cpu->register_a); + }else{ + int c = test_flag(cpu, CARRY); + uint16_t addr = get_operand_address(cpu, mode); + uint8_t data = mem_read(cpu, addr); + if((data & 1) == 1){ + enable_flag(cpu, CARRY); + }else{ + disable_flag(cpu, CARRY); + } + + data = data >> 1; + if(c == 1){ + data |= 0b10000000; + }else{ + } + + mem_write(cpu, addr, data); + update_zero_and_negative_flags(cpu, data); + } +} + +void adc(struct CPU *cpu, enum adressing_mode mode){ + uint16_t addr = get_operand_address(cpu, mode); + uint8_t value = mem_read(cpu, addr); + uint8_t ra = cpu->register_a; + //sum = value + ra + CARRY; + uint16_t sum; + sum = (uint16_t)value + (uint16_t)ra; + if(test_flag(cpu, CARRY) == 1){ + sum += 1; + }else{ + } + + bool new_carry = (sum > 0xFF); // will set carry flag in overflow too + if(new_carry == 1) enable_flag(cpu, CARRY); + else disable_flag(cpu, CARRY); + + sum &= 0xFF; // sum & 0b11111111 + uint8_t res = (uint8_t)sum; + // ver se os sinais mudaram + // ra, value, res + // ra ^ res -> bit 7 flipou? + // value ^ res -> bit 7 fliplou? + // 1 1 0 - 1 + // 0 0 1 - 1 + // 0 0 0 - 0 + // 1 1 1 - 0 + if( (value ^ res) & (ra ^ res) & 0x80 ){ + enable_flag(cpu, OVERFLOW); + }else{ + disable_flag(cpu, OVERFLOW); + } + + cpu->register_a = res; + update_zero_and_negative_flags(cpu, cpu->register_a); +} + +void sbc(struct CPU *cpu, enum adressing_mode mode){ + uint16_t addr = get_operand_address(cpu, mode); + uint8_t value = mem_read(cpu, addr); + value = ~value + 1; + uint8_t ra = cpu->register_a; + //sum = value + ra + CARRY; + uint16_t sum; + sum = (uint16_t)value + (uint16_t)ra; + if(test_flag(cpu, CARRY) == 1){ + sum += 1; + }else{ + } + + bool new_carry = (sum > 0xFF); // will set carry flag in overflow too + if(new_carry == 1) enable_flag(cpu, CARRY); + else disable_flag(cpu, CARRY); + + sum &= 0xFF; // sum & 0b11111111 + uint8_t res = (uint8_t)sum; + // ver se os sinais mudaram + // ra, value, res + // ra ^ res -> bit 7 flipou? + // value ^ res -> bit 7 fliplou? + // 1 1 0 - 1 + // 0 0 1 - 1 + // 0 0 0 - 0 + // 1 1 1 - 0 + if( (value ^ res) & (ra ^ res) & 0x80 ){ + enable_flag(cpu, OVERFLOW); + }else{ + disable_flag(cpu, OVERFLOW); + } + + cpu->register_a = res; + update_zero_and_negative_flags(cpu, cpu->register_a); + +} +void bit(struct CPU *cpu, enum adressing_mode mode){ + uint16_t addr = get_operand_address(cpu, mode); + uint8_t value = mem_read(cpu, addr); + + value &= cpu->register_a; + if(value == 0){ + enable_flag(cpu, ZERO); + }else{ + disable_flag(cpu, ZERO); + } + + if((value & 0b01000000) > 0){ + enable_flag(cpu, OVERFLOW); + }else{ + disable_flag(cpu, OVERFLOW); + } + + if((value & 0b10000000) > 0){ + enable_flag(cpu, NEGATIV); + }else{ + disable_flag(cpu, NEGATIV); + } } void interpret(struct CPU *cpu){ - while(1){ - uint8_t opcode = mem_read(cpu, cpu->pc); - cpu->pc += 1; - - switch(OPCODE[opcode].instruction){ - case BRK: - return; - case TAX: - cpu->register_x = cpu->register_a; - update_zero_and_negative_flags(cpu, cpu->register_x); - break; - case LDA: - lda(cpu, OPCODE[opcode].mode); - cpu->pc += OPCODE[opcode].bytes - 1; - break; - case STA: - sta(cpu, OPCODE[opcode].mode); - cpu->pc += OPCODE[opcode].bytes - 1; - break; - case INX: - cpu->register_x++; - update_zero_and_negative_flags(cpu, cpu->register_x); - break; - case AND: - and(cpu, OPCODE[opcode].mode); - cpu->pc += OPCODE[opcode].bytes - 1; - break; - case ASL: - if(OPCODE[opcode].mode == NoneAddressing){ - uint8_t value = cpu->register_a; - if(value >> 7 == 1) enable_flag(cpu, CARRY); - else disable_flag(cpu, CARRY); - cpu->register_a = value << 1; - update_zero_and_negative_flags(cpu, cpu->register_a); - }else{ - asl(cpu, OPCODE[opcode].mode); - } - cpu->pc += OPCODE[opcode].bytes - 1; - break; - case BCC: - branch(cpu, !test_flag(cpu, CARRY)); - break; - case BCS: - branch(cpu, test_flag(cpu, CARRY)); - break; - case BEQ: - branch(cpu, test_flag(cpu, ZERO)); - break; - case BMI: - branch(cpu, test_flag(cpu, NEGATIV)); - break; - case BNE: - branch(cpu, !test_flag(cpu, ZERO)); - break; - case BPL: - branch(cpu, !test_flag(cpu, NEGATIV)); - break; - case BVC: - branch(cpu, !test_flag(cpu, OVERFLOW)); - break; - case BVS: - branch(cpu, test_flag(cpu, OVERFLOW)); - break; + //while(1){ + { + uint8_t opcode = mem_read(cpu, cpu->pc); + // printf("opcode %x\n", opcode); + // printf("pc %x\n", cpu->pc); + cpu->pc += 1; + uint16_t save_pc = cpu->pc; + + switch(OPCODE[opcode].instruction){ + case BRK: + return; + case TAX: + cpu->register_x = cpu->register_a; + update_zero_and_negative_flags(cpu, cpu->register_x); + break; + case LDA: + lda(cpu, OPCODE[opcode].mode); + cpu->pc += OPCODE[opcode].bytes - 1; + break; + case STA: + sta(cpu, OPCODE[opcode].mode); + cpu->pc += OPCODE[opcode].bytes - 1; + break; + case INX: + cpu->register_x++; + update_zero_and_negative_flags(cpu, cpu->register_x); + break; + case AND: + and(cpu, OPCODE[opcode].mode); + cpu->pc += OPCODE[opcode].bytes - 1; + break; + case ASL: + if(OPCODE[opcode].mode == NoneAddressing){ + uint8_t value = cpu->register_a; + if(value >> 7 == 1) enable_flag(cpu, CARRY); + else disable_flag(cpu, CARRY); + cpu->register_a = value << 1; + update_zero_and_negative_flags(cpu, cpu->register_a); + }else{ + asl(cpu, OPCODE[opcode].mode); + } + cpu->pc += OPCODE[opcode].bytes - 1; + break; + case BCC: + branch(cpu, !test_flag(cpu, CARRY)); + break; + case BCS: + branch(cpu, test_flag(cpu, CARRY)); + break; + case BEQ: + branch(cpu, test_flag(cpu, ZERO)); + break; + case BMI: + branch(cpu, test_flag(cpu, NEGATIV)); + break; + case BNE: + branch(cpu, !test_flag(cpu, ZERO)); + break; + case BPL: + branch(cpu, !test_flag(cpu, NEGATIV)); + break; + case BVC: + branch(cpu, !test_flag(cpu, OVERFLOW)); + break; + case BVS: + branch(cpu, test_flag(cpu, OVERFLOW)); + break; case CLC: - disable_flag(cpu, CARRY); - break; - case CLD: - disable_flag(cpu, DECIMAL_MODE); - break; - case CLI: - disable_flag(cpu, INTERRUPT_DISABLE); - break; - case CLV: - disable_flag(cpu, OVERFLOW); - break; - case CMP: - compare(cpu, OPCODE[opcode].mode, cpu->register_a); - break; - case CPX: - compare(cpu, OPCODE[opcode].mode, cpu->register_x); - break; - case CPY: - compare(cpu, OPCODE[opcode].mode, cpu->register_y); - break; - default: - break; - } - } - - return; + disable_flag(cpu, CARRY); + break; + case CLD: + disable_flag(cpu, DECIMAL_MODE); + break; + case CLI: + disable_flag(cpu, INTERRUPT_DISABLE); + break; + case CLV: + disable_flag(cpu, OVERFLOW); + break; + case CMP: + compare(cpu, OPCODE[opcode].mode, cpu->register_a); + break; + case CPX: + compare(cpu, OPCODE[opcode].mode, cpu->register_x); + break; + case CPY: + compare(cpu, OPCODE[opcode].mode, cpu->register_y); + break; + case DEC: + dec(cpu, OPCODE[opcode].mode); + break; + case DEX: + cpu->register_x -= 1; + update_zero_and_negative_flags(cpu, cpu->register_x); + break; + case DEY: + cpu->register_y -= 1; + update_zero_and_negative_flags(cpu, cpu->register_y); + case EOR: + eor(cpu, OPCODE[opcode].mode); + break; + case INC: + inc(cpu, OPCODE[opcode].mode); + break; + case INY: + cpu->register_y++; + update_zero_and_negative_flags(cpu, cpu->register_y); + break; + case JMP: + if(OPCODE[opcode].mode == Absolute){ + uint16_t addr = get_operand_address(cpu, Absolute); + cpu->pc = addr; + }else{ + /*Indirect -> JMP is the only 6502 instruction to support indirection.*/ + uint16_t addr = mem_read_u16(cpu, cpu->pc); + + uint16_t indirect_ref; + if((addr & 0x00FF) == 0x00FF){ + uint8_t lo = mem_read(cpu, addr); + uint8_t hi = mem_read(cpu, addr & 0x00FF); + indirect_ref = ((uint16_t)hi << 8) | ((uint16_t)lo); + }else{ + indirect_ref = mem_read_u16(cpu, addr); + } + + cpu->pc = indirect_ref; + } + break; + case JSR: // + 2 -> JSR uses 3 bytes, but 1 is already added + stack_push_u16(cpu, cpu->pc + 2 - 1); + uint16_t new_addr = mem_read_u16(cpu, cpu->pc); + cpu->pc = new_addr; + + break; + case LDX: + ldx(cpu, OPCODE[opcode].mode); + break; + case LDY: + ldy(cpu, OPCODE[opcode].mode); + break; + case LSR: + if(OPCODE[opcode].mode == NoneAddressing){ + uint8_t data = cpu->register_a; + if(data & 1){ + enable_flag(cpu, CARRY); + }else{ + disable_flag(cpu, CARRY); + } + data = data >> 1; + cpu->register_a = data; + update_zero_and_negative_flags(cpu, cpu->register_a); + }else{ + lsr(cpu, OPCODE[opcode].mode); + } + break; + case NOP: + break; + case ORA: + ora(cpu, OPCODE[opcode].mode); + break; + case PHA: + stack_push(cpu, cpu->register_a); + break; + case PHP: + stack_push(cpu, cpu->status | BREAK | BREAK2); + break; + case PLA: + cpu->register_a = stack_pop(cpu); + update_zero_and_negative_flags(cpu, cpu->register_a); + break; + case PLP: + { + uint8_t flags_data = stack_pop(cpu); + printf("flags pulled: %x\n", flags_data); + flags_data &= (~BREAK); + flags_data |= BREAK2; + printf("flags saved in status: %x\n", flags_data); + cpu->status = flags_data; + } + break; + case ROL: + rol(cpu, OPCODE[opcode].mode); + break; + case ROR: + ror(cpu, OPCODE[opcode].mode); + break; + case ADC: + adc(cpu, OPCODE[opcode].mode); + break; + case RTI: + cpu->status = stack_pop(cpu); + cpu->status &= ~BREAK; + cpu->status |= BREAK2; + cpu->pc = stack_pop_u16(cpu); + break; + case RTS: + cpu->pc = stack_pop_u16(cpu) + 1; + break; + case SBC: + sbc(cpu, OPCODE[opcode].mode); + break; + case SEC: + enable_flag(cpu, CARRY); + break; + case SED: + enable_flag(cpu, DECIMAL_MODE); + break; + case SEI: + enable_flag(cpu, INTERRUPT_DISABLE); + break; + case TAY: + cpu->register_y = cpu->register_a; + update_zero_and_negative_flags(cpu, cpu->register_y); + break; + case TSX: + cpu->register_x = cpu->sp; + update_zero_and_negative_flags(cpu, cpu->register_x); + break; + case TXA: + cpu->register_a = cpu->register_x; + update_zero_and_negative_flags(cpu, cpu->register_a); + break; + case TXS: + cpu->sp = cpu->register_x; + break; + case TYA: + cpu->register_a = cpu->register_y; + update_zero_and_negative_flags(cpu, cpu->register_a); + break; + case BIT: + bit(cpu, OPCODE[opcode].mode); + break; + default: + break; + } + + if(save_pc == cpu->pc){ + cpu->pc += OPCODE[opcode].bytes - 1; + } + } + + return; +} + +int test_operands(){ + init_opcode_pc(); + + printf("test_0xa9_lda_immediate_load_data: "); + struct CPU cpu_1 = create_cpu(); + uint8_t program_1[] = {0xa9, 0x05, 0x00}; + load_and_run(&cpu_1, program_1, sizeof(program_1)/sizeof(program_1[0])); + assert(cpu_1.register_a == 0x05); + assert((cpu_1.status & 0b00000010) == 0b00); + assert((cpu_1.status & 0b10000000) == 0); + printf("PASSED\n"); + + printf("test_0xa9_lda_zero_flag: "); + struct CPU cpu_2 = create_cpu(); + uint8_t program_2[] = {0xa9, 0x00, 0x00}; + load_and_run(&cpu_2, program_2, sizeof(program_2)/sizeof(program_2[0])); + 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, sizeof(program_3)/sizeof(program_3[0])); + 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, sizeof(program_4)/sizeof(program_4[0])); + 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, sizeof(program_5)/sizeof(program_5[0])); + assert(cpu_5.register_x == 1); + printf("PASSED\n"); + + printf("test_lda_from_memory: "); + struct CPU cpu_6 = create_cpu(); + mem_write(&cpu_6, 0x10, 0x55); + uint8_t program_6[] = {0xa5, 0x10, 0x00}; + load_and_run(&cpu_6, program_6, sizeof(program_6)/sizeof(program_6[0])); + assert(cpu_6.register_a == 0x55); + printf("PASSED\n"); + + printf("test_adc: "); + struct CPU cpu_7 = create_cpu(); + uint8_t program_7[] = {0xa9, 64, 0x69, 64, 0x00}; + load_and_run(&cpu_7, program_7, sizeof(program_7)/sizeof(program_7[0])); + assert(cpu_7.register_a == 128); + assert(test_flag(&cpu_7, OVERFLOW) == 1); + printf("PASSED\n"); + + printf("test_sbc: "); + struct CPU cpu_8 = create_cpu(); + uint8_t program_8[] = {0xa9, 0b10000000, 0xe9, 31, 0x00}; + load_and_run(&cpu_8, program_8, sizeof(program_8)/sizeof(program_8[0])); + assert(cpu_8.register_a == 128-31); + assert(test_flag(&cpu_8, OVERFLOW) == 1); + printf("PASSED\n"); + + printf("test_sec: "); + struct CPU cpu_9 = create_cpu(); + uint8_t program_9[] = {0xa9, 10, 0x38, 0xa9, 11, 0xa9, 12, 0x00}; + load_and_run(&cpu_9, program_9, sizeof(program_9)/sizeof(program_9[0])); + assert(test_flag(&cpu_9, CARRY) == 1); + assert(cpu_9.register_a == 12); + printf("PASSED\n"); + + return 0; } int main(){ - init_opcode_pc(); - - printf("test_0xa9_lda_immediate_load_data: "); - struct CPU cpu_1 = create_cpu(); - uint8_t program_1[] = {0xa9, 0x05, 0x00}; - 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); - printf("PASSED\n"); - - printf("test_0xa9_lda_zero_flag: "); - struct CPU cpu_2 = create_cpu(); - uint8_t program_2[] = {0xa9, 0x00, 0x00}; - 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"); - - printf("test_lda_from_memory: "); - struct CPU cpu_6 = create_cpu(); - mem_write(&cpu_6, 0x10, 0x55); - uint8_t program_6[] = {0xa5, 0x10, 0x00}; - load_and_run(&cpu_6, program_6); - assert(cpu_6.register_a == 0x55); - printf("PASSED\n"); + //test_operands(); + init_opcode_pc(); + + struct CPU cpu = create_cpu(); + uint8_t program[] = { + 0x20, 0x06, 0x06, 0x20, 0x38, 0x06, 0x20, 0x0d, 0x06, 0x20, 0x2a, 0x06, 0x60, 0xa9, 0x02, 0x85, + 0x02, 0xa9, 0x04, 0x85, 0x03, 0xa9, 0x11, 0x85, 0x10, 0xa9, 0x10, 0x85, 0x12, 0xa9, 0x0f, 0x85, + 0x14, 0xa9, 0x04, 0x85, 0x11, 0x85, 0x13, 0x85, 0x15, 0x60, 0xa5, 0xfe, 0x85, 0x00, 0xa5, 0xfe, + 0x29, 0x03, 0x18, 0x69, 0x02, 0x85, 0x01, 0x60, 0x20, 0x4d, 0x06, 0x20, 0x8d, 0x06, 0x20, 0xc3, + 0x06, 0x20, 0x19, 0x07, 0x20, 0x20, 0x07, 0x20, 0x2d, 0x07, 0x4c, 0x38, 0x06, 0xa5, 0xff, 0xc9, + 0x77, 0xf0, 0x0d, 0xc9, 0x64, 0xf0, 0x14, 0xc9, 0x73, 0xf0, 0x1b, 0xc9, 0x61, 0xf0, 0x22, 0x60, + 0xa9, 0x04, 0x24, 0x02, 0xd0, 0x26, 0xa9, 0x01, 0x85, 0x02, 0x60, 0xa9, 0x08, 0x24, 0x02, 0xd0, + 0x1b, 0xa9, 0x02, 0x85, 0x02, 0x60, 0xa9, 0x01, 0x24, 0x02, 0xd0, 0x10, 0xa9, 0x04, 0x85, 0x02, + 0x60, 0xa9, 0x02, 0x24, 0x02, 0xd0, 0x05, 0xa9, 0x08, 0x85, 0x02, 0x60, 0x60, 0x20, 0x94, 0x06, + 0x20, 0xa8, 0x06, 0x60, 0xa5, 0x00, 0xc5, 0x10, 0xd0, 0x0d, 0xa5, 0x01, 0xc5, 0x11, 0xd0, 0x07, + 0xe6, 0x03, 0xe6, 0x03, 0x20, 0x2a, 0x06, 0x60, 0xa2, 0x02, 0xb5, 0x10, 0xc5, 0x10, 0xd0, 0x06, + 0xb5, 0x11, 0xc5, 0x11, 0xf0, 0x09, 0xe8, 0xe8, 0xe4, 0x03, 0xf0, 0x06, 0x4c, 0xaa, 0x06, 0x4c, + 0x35, 0x07, 0x60, 0xa6, 0x03, 0xca, 0x8a, 0xb5, 0x10, 0x95, 0x12, 0xca, 0x10, 0xf9, 0xa5, 0x02, + 0x4a, 0xb0, 0x09, 0x4a, 0xb0, 0x19, 0x4a, 0xb0, 0x1f, 0x4a, 0xb0, 0x2f, 0xa5, 0x10, 0x38, 0xe9, + 0x20, 0x85, 0x10, 0x90, 0x01, 0x60, 0xc6, 0x11, 0xa9, 0x01, 0xc5, 0x11, 0xf0, 0x28, 0x60, 0xe6, + 0x10, 0xa9, 0x1f, 0x24, 0x10, 0xf0, 0x1f, 0x60, 0xa5, 0x10, 0x18, 0x69, 0x20, 0x85, 0x10, 0xb0, + 0x01, 0x60, 0xe6, 0x11, 0xa9, 0x06, 0xc5, 0x11, 0xf0, 0x0c, 0x60, 0xc6, 0x10, 0xa5, 0x10, 0x29, + 0x1f, 0xc9, 0x1f, 0xf0, 0x01, 0x60, 0x4c, 0x35, 0x07, 0xa0, 0x00, 0xa5, 0xfe, 0x91, 0x00, 0x60, + 0xa6, 0x03, 0xa9, 0x00, 0x81, 0x10, 0xa2, 0x00, 0xa9, 0x01, 0x81, 0x10, 0x60, 0xa2, 0x00, 0xea, + 0xea, 0xca, 0xd0, 0xfb, 0x60 + }; + + int sW, sH; + sW = sH = 320; + InitWindow(sW, sH, "snake"); + load(&cpu, program, sizeof(program)/sizeof(program[0])); + reset_cpu(&cpu); + + mem_write(&cpu, 0xff, 0x77); + //while(1){ + // mem_write(&cpu, 0xfe, rand()%15 + 1); + // interpret(&cpu); + // printf("%d", OPCODE[cpu.memory[cpu.pc]].instruction); + // printf("%x\n", cpu.pc); + // for(int i=0x0200; i < 0x0600; ++i){ + // printf("%d ", cpu.memory[i]); + // if(i%32 == 0) printf("\n"); + // } + // printf("\n"); + //} + + SetTargetFPS(5000); + while(!WindowShouldClose()){ + if(IsKeyDown(KEY_W)){ + mem_write(&cpu, 0xff, 0x77); + } + if(IsKeyDown(KEY_S)){ + mem_write(&cpu, 0xff, 0x73); + } + if(IsKeyDown(KEY_A)){ + mem_write(&cpu, 0xff, 0x61); + } + if(IsKeyDown(KEY_D)){ + mem_write(&cpu, 0xff, 0x64); + } + mem_write(&cpu, 0xfe, rand()%15 + 1); + + interpret(&cpu); + + BeginDrawing(); + { + int block = 0; + for(int i=0x0200; i < 0x0600; ++i){ + uint8_t x = cpu.memory[i]; + Color c; + if(x == 0) c = BLACK; + if(x == 1) c = WHITE; + if(x == 2 || x == 9) c = GRAY; + if(x == 3 || x == 10) c = RED; + if(x == 4 || x == 11) c = GREEN; + if(x == 5 || x == 12) c = BLUE; + if(x == 6 || x == 13) c = MAGENTA; + if(x == 7 || x == 14) c = YELLOW; + + int px, py; + py = block/32; + px = block%32; + DrawRectangle(px * 10, py * 10, 10, 10, c); + block++; + } + } + EndDrawing(); + } + return 0; } @@ -12,35 +12,39 @@ #define NEGATIV 0b10000000 struct CPU{ - uint8_t register_a; - uint8_t register_x; - uint8_t register_y; - uint8_t status; - uint16_t pc; - uint8_t memory[0xFFFF]; + uint8_t register_a; + uint8_t register_x; + uint8_t register_y; + uint8_t status; + uint16_t pc; + uint8_t sp; // stack pointer + uint8_t memory[0xFFFF]; }; enum adressing_mode{ - Immediate = 1, - ZeroPage, - ZeroPage_X, - ZeroPage_Y, - Absolute, - Absolute_X, - Absolute_Y, - Indirect_X, - Indirect_Y, - NoneAddressing, + Immediate = 1, + ZeroPage, + ZeroPage_X, + ZeroPage_Y, + Absolute, + Absolute_X, + Absolute_Y, + Indirect_X, + Indirect_Y, + NoneAddressing, }; +uint8_t stack_pop(struct CPU *cpu); +void stack_push(struct CPU *cpu, uint8_t data); +void stack_push_u16(struct CPU *cpu, uint16_t data); +uint16_t stack_pop_u16(struct CPU *cpu); 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 load(struct CPU *cpu, uint8_t *program, int size_of_program); +void load_and_run(struct CPU *cpu, uint8_t *program, int size_of_program); void reset_cpu(struct CPU *cpu); void update_zero_and_negative_flags(struct CPU *cpu, uint8_t result); void lda(struct CPU *cpu, enum adressing_mode mode); @@ -54,7 +58,20 @@ int test_flag(struct CPU *cpu, uint8_t flag); void asl(struct CPU *cpu, enum adressing_mode mode); void branch(struct CPU *cpu, bool cond); -void compare(struct CPU *cpu, enum adressing_mode mode, uint8_t comp_val)); +void dec(struct CPU *cpu, enum adressing_mode mode); +void eor(struct CPU *cpu, enum adressing_mode mode); +void inc(struct CPU *cpu, enum adressing_mode mode); +void compare(struct CPU *cpu, enum adressing_mode mode, uint8_t comp_val); +void ldx(struct CPU *cpu, enum adressing_mode mode); +void ldy(struct CPU *cpu, enum adressing_mode mode); +void lsr(struct CPU *cpu, enum adressing_mode mode); +void ora(struct CPU *cpu, enum adressing_mode mode); +void rol(struct CPU *cpu, enum adressing_mode mode); +void ror(struct CPU *cpu, enum adressing_mode mode); +void adc(struct CPU *cpu, enum adressing_mode mode); +void stx(struct CPU *cpu, enum adressing_mode mode); +void sty(struct CPU *cpu, enum adressing_mode mode); +void bit(struct CPU *cpu, enum adressing_mode mode); -#endif
\ No newline at end of file +#endif diff --git a/opcode_pc.h b/opcode_pc.h index 30a0d7b..384f0b0 100644 --- a/opcode_pc.h +++ b/opcode_pc.h @@ -4,117 +4,278 @@ #include <stdint.h> enum _INSTRUCTION{ - ADC = 1, - LDA, - TAX, - BRK, - STA, - INX, - AND, - ASL, - BCC, - BCS, - BEQ, - BMI, - BNE, - BPL, - BVC, - BVS, + ADC = 1, + LDA, + TAX, + BRK, + STA, + INX, + AND, + ASL, + BCC, + BCS, + BEQ, + BMI, + BNE, + BPL, + BVC, + BVS, CLC, - CLD, - CLI, - CLV, - CMP, - CPX, - CPY, + CLD, + CLI, + CLV, + CMP, + CPX, + CPY, + DEC, + DEX, + DEY, + EOR, + INC, + INY, + JMP, + JSR, + LDX, + LDY, + LSR, + NOP, + ORA, + PHA, + PHP, + PLA, + PLP, + ROL, + ROR, + RTI, + RTS, + SBC, + SEC, + SED, + SEI, + STX, + STY, + TAY, + TSX, + TXA, + TXS, + TYA, + BIT, }; struct _OPCODE{ - enum _INSTRUCTION instruction; - enum adressing_mode mode; - uint8_t bytes; + enum _INSTRUCTION instruction; + enum adressing_mode mode; + uint8_t bytes; }OPCODE[0xFF]; void init_opcode_pc(){ - /*LDA*/ - OPCODE[0xA9] = (struct _OPCODE){LDA, Immediate, 2}; - OPCODE[0xA5] = (struct _OPCODE){LDA, ZeroPage, 2}; - OPCODE[0xB5] = (struct _OPCODE){LDA, ZeroPage_X, 2}; - OPCODE[0XAD] = (struct _OPCODE){LDA, Absolute, 3}; - OPCODE[0xBD] = (struct _OPCODE){LDA, Absolute_X, 3}; - OPCODE[0xB9] = (struct _OPCODE){LDA, Absolute_Y, 3}; - OPCODE[0xA1] = (struct _OPCODE){LDA, Indirect_X, 2}; - OPCODE[0xB1] = (struct _OPCODE){LDA, Indirect_Y, 2}; - /*BRK*/ - OPCODE[0x00] = (struct _OPCODE){BRK, NoneAddressing, 1}; - /*TAX*/ - OPCODE[0xAA] = (struct _OPCODE){TAX, NoneAddressing, 1}; - /*STA*/ - OPCODE[0x85] = (struct _OPCODE){STA, ZeroPage, 2}; - OPCODE[0x95] = (struct _OPCODE){STA, ZeroPage_X, 2}; - OPCODE[0x8D] = (struct _OPCODE){STA, Absolute, 3}; - OPCODE[0x9D] = (struct _OPCODE){STA, Absolute_X, 3}; - OPCODE[0x99] = (struct _OPCODE){STA, Absolute_Y, 3}; - OPCODE[0x81] = (struct _OPCODE){STA, Indirect_X, 2}; - OPCODE[0x91] = (struct _OPCODE){STA, Indirect_Y, 2}; - /*INX*/ - OPCODE[0xE8] = (struct _OPCODE){INX, NoneAddressing, 1}; - /*AND*/ - OPCODE[0x29] = (struct _OPCODE){AND, Immediate, 2}; - OPCODE[0x25] = (struct _OPCODE){AND, ZeroPage, 2}; - OPCODE[0x35] = (struct _OPCODE){AND, ZeroPage_X, 2}; - OPCODE[0x2D] = (struct _OPCODE){AND, Absolute, 3}; - OPCODE[0x3D] = (struct _OPCODE){AND, Absolute_X, 3}; - OPCODE[0x39] = (struct _OPCODE){AND, Absolute_Y, 3}; - OPCODE[0x21] = (struct _OPCODE){AND, Indirect_X, 2}; - OPCODE[0x31] = (struct _OPCODE){AND, Indirect_Y, 2}; - /*ASL*/ - OPCODE[0x0A] = (struct _OPCODE){ASL, NoneAddressing, 1}; - OPCODE[0x06] = (struct _OPCODE){ASL, ZeroPage, 2}; - OPCODE[0x16] = (struct _OPCODE){ASL, ZeroPage_X, 2}; - OPCODE[0x0E] = (struct _OPCODE){ASL, Absolute, 3}; - OPCODE[0x1E] = (struct _OPCODE){ASL, Absolute_X, 3}; - /*BCC*/ - OPCODE[0x90] = (struct _OPCODE){BCC, NoneAddressing, 2}; - /*BCS*/ - OPCODE[0xB0] = (struct _OPCODE){BCS, NoneAddressing, 2}; - /*BEQ*/ - OPCODE[0xF0] = (struct _OPCODE){BEQ, NoneAddressing, 2}; - /*BMI*/ - OPCODE[0x30] = (struct _OPCODE){BMI, NoneAddressing, 2}; - /*BNE*/ - OPCODE[0xD0] = (struct _OPCODE){BNE, NoneAddressing, 2}; - /*BPL*/ - OPCODE[0x10] = (struct _OPCODE){BPL, NoneAddressing, 2}; - /*BVC*/ - OPCODE[0x50] = (struct _OPCODE){BVC, NoneAddressing, 2}; - /*BVS*/ - OPCODE[0x70] = (struct _OPCODE){BVS, NoneAddressing, 2}; - /*CLC*/ - OPCODE[0x18] = (struct _OPCODE){CLC, NoneAddressing, 2}; - /*CLD*/ - OPCODE[0xD8] = (struct _OPCODE){CLD, NoneAddressing, 2}; - /*CLI*/ - OPCODE[0x58] = (struct _OPCODE){CLI, NoneAddressing, 2}; - /*CLV*/ - OPCODE[0xB8] = (struct _OPCODE){CLV, NoneAddressing, 2}; - /*CMP*/ - OPCODE[0xC9] = (struct _OPCODE){CMP, Immediate, 2}; - OPCODE[0xC5] = (struct _OPCODE){CMP, ZeroPage, 2}; - OPCODE[0xD5] = (struct _OPCODE){CMP, ZeroPage_X, 2}; - OPCODE[0xCD] = (struct _OPCODE){CMP, Absolute, 3}; - OPCODE[0xDD] = (struct _OPCODE){CMP, Absolute_X, 3}; - OPCODE[0xD9] = (struct _OPCODE){CMP, Absolute_Y, 3}; - OPCODE[0xC1] = (struct _OPCODE){CMP, Indirect_X, 2}; - OPCODE[0xD1] = (struct _OPCODE){CMP, Indirect_Y, 2}; - /*CPX*/ - OPCODE[0xE0] = (struct _OPCODE){CPX, Immediate, 2}; - OPCODE[0xE4] = (struct _OPCODE){CPX, ZeroPage, 2}; - OPCODE[0xEC] = (struct _OPCODE){CPX, Absolute, 3}; - /*CPY*/ - OPCODE[0xC0] = (struct _OPCODE){CPY, Immediate, 2}; - OPCODE[0xC4] = (struct _OPCODE){CPY, ZeroPage, 2}; - OPCODE[0xCC] = (struct _OPCODE){CPY, Absolute, 3}; + /*LDA*/ + OPCODE[0xA9] = (struct _OPCODE){LDA, Immediate, 2}; + OPCODE[0xA5] = (struct _OPCODE){LDA, ZeroPage, 2}; + OPCODE[0xB5] = (struct _OPCODE){LDA, ZeroPage_X, 2}; + OPCODE[0XAD] = (struct _OPCODE){LDA, Absolute, 3}; + OPCODE[0xBD] = (struct _OPCODE){LDA, Absolute_X, 3}; + OPCODE[0xB9] = (struct _OPCODE){LDA, Absolute_Y, 3}; + OPCODE[0xA1] = (struct _OPCODE){LDA, Indirect_X, 2}; + OPCODE[0xB1] = (struct _OPCODE){LDA, Indirect_Y, 2}; + /*BRK*/ + OPCODE[0x00] = (struct _OPCODE){BRK, NoneAddressing, 1}; + /*TAX*/ + OPCODE[0xAA] = (struct _OPCODE){TAX, NoneAddressing, 1}; + /*STA*/ + OPCODE[0x85] = (struct _OPCODE){STA, ZeroPage, 2}; + OPCODE[0x95] = (struct _OPCODE){STA, ZeroPage_X, 2}; + OPCODE[0x8D] = (struct _OPCODE){STA, Absolute, 3}; + OPCODE[0x9D] = (struct _OPCODE){STA, Absolute_X, 3}; + OPCODE[0x99] = (struct _OPCODE){STA, Absolute_Y, 3}; + OPCODE[0x81] = (struct _OPCODE){STA, Indirect_X, 2}; + OPCODE[0x91] = (struct _OPCODE){STA, Indirect_Y, 2}; + /*INX*/ + OPCODE[0xE8] = (struct _OPCODE){INX, NoneAddressing, 1}; + /*AND*/ + OPCODE[0x29] = (struct _OPCODE){AND, Immediate, 2}; + OPCODE[0x25] = (struct _OPCODE){AND, ZeroPage, 2}; + OPCODE[0x35] = (struct _OPCODE){AND, ZeroPage_X, 2}; + OPCODE[0x2D] = (struct _OPCODE){AND, Absolute, 3}; + OPCODE[0x3D] = (struct _OPCODE){AND, Absolute_X, 3}; + OPCODE[0x39] = (struct _OPCODE){AND, Absolute_Y, 3}; + OPCODE[0x21] = (struct _OPCODE){AND, Indirect_X, 2}; + OPCODE[0x31] = (struct _OPCODE){AND, Indirect_Y, 2}; + /*ASL*/ + OPCODE[0x0A] = (struct _OPCODE){ASL, NoneAddressing, 1}; + OPCODE[0x06] = (struct _OPCODE){ASL, ZeroPage, 2}; + OPCODE[0x16] = (struct _OPCODE){ASL, ZeroPage_X, 2}; + OPCODE[0x0E] = (struct _OPCODE){ASL, Absolute, 3}; + OPCODE[0x1E] = (struct _OPCODE){ASL, Absolute_X, 3}; + /*BCC*/ + OPCODE[0x90] = (struct _OPCODE){BCC, NoneAddressing, 2}; + /*BCS*/ + OPCODE[0xB0] = (struct _OPCODE){BCS, NoneAddressing, 2}; + /*BEQ*/ + OPCODE[0xF0] = (struct _OPCODE){BEQ, NoneAddressing, 2}; + /*BMI*/ + OPCODE[0x30] = (struct _OPCODE){BMI, NoneAddressing, 2}; + /*BNE*/ + OPCODE[0xD0] = (struct _OPCODE){BNE, NoneAddressing, 2}; + /*BPL*/ + OPCODE[0x10] = (struct _OPCODE){BPL, NoneAddressing, 2}; + /*BVC*/ + OPCODE[0x50] = (struct _OPCODE){BVC, NoneAddressing, 2}; + /*BVS*/ + OPCODE[0x70] = (struct _OPCODE){BVS, NoneAddressing, 2}; + /*CLC*/ + OPCODE[0x18] = (struct _OPCODE){CLC, NoneAddressing, 1}; + /*CLD*/ + OPCODE[0xD8] = (struct _OPCODE){CLD, NoneAddressing, 1}; + /*CLI*/ + OPCODE[0x58] = (struct _OPCODE){CLI, NoneAddressing, 1}; + /*CLV*/ + OPCODE[0xB8] = (struct _OPCODE){CLV, NoneAddressing, 1}; + /*CMP*/ + OPCODE[0xC9] = (struct _OPCODE){CMP, Immediate, 2}; + OPCODE[0xC5] = (struct _OPCODE){CMP, ZeroPage, 2}; + OPCODE[0xD5] = (struct _OPCODE){CMP, ZeroPage_X, 2}; + OPCODE[0xCD] = (struct _OPCODE){CMP, Absolute, 3}; + OPCODE[0xDD] = (struct _OPCODE){CMP, Absolute_X, 3}; + OPCODE[0xD9] = (struct _OPCODE){CMP, Absolute_Y, 3}; + OPCODE[0xC1] = (struct _OPCODE){CMP, Indirect_X, 2}; + OPCODE[0xD1] = (struct _OPCODE){CMP, Indirect_Y, 2}; + /*CPX*/ + OPCODE[0xE0] = (struct _OPCODE){CPX, Immediate, 2}; + OPCODE[0xE4] = (struct _OPCODE){CPX, ZeroPage, 2}; + OPCODE[0xEC] = (struct _OPCODE){CPX, Absolute, 3}; + /*CPY*/ + OPCODE[0xC0] = (struct _OPCODE){CPY, Immediate, 2}; + OPCODE[0xC4] = (struct _OPCODE){CPY, ZeroPage, 2}; + OPCODE[0xCC] = (struct _OPCODE){CPY, Absolute, 3}; + /*DEC*/ + OPCODE[0xC6] = (struct _OPCODE){DEC, ZeroPage, 2}; + OPCODE[0xD6] = (struct _OPCODE){DEC, ZeroPage_X, 2}; + OPCODE[0xCE] = (struct _OPCODE){DEC, Absolute, 3}; + OPCODE[0xDE] = (struct _OPCODE){DEC, Absolute_X, 3}; + /*DEX*/ + OPCODE[0xCA] = (struct _OPCODE){DEX, NoneAddressing, 1}; + /*DEY*/ + OPCODE[0x88] = (struct _OPCODE){DEY, NoneAddressing, 1}; + /*EOR*/ + OPCODE[0x49] = (struct _OPCODE){EOR, Immediate, 2}; + OPCODE[0x45] = (struct _OPCODE){EOR, ZeroPage, 2}; + OPCODE[0x55] = (struct _OPCODE){EOR, ZeroPage_X, 2}; + OPCODE[0x4D] = (struct _OPCODE){EOR, Absolute, 3}; + OPCODE[0x5D] = (struct _OPCODE){EOR, Absolute_X, 3}; + OPCODE[0x59] = (struct _OPCODE){EOR, Absolute_Y, 3}; + OPCODE[0x41] = (struct _OPCODE){EOR, Indirect_X, 2}; + OPCODE[0x51] = (struct _OPCODE){EOR, Indirect_Y, 2}; + /*INC*/ + OPCODE[0xE6] = (struct _OPCODE){INC, ZeroPage, 2}; + OPCODE[0xF6] = (struct _OPCODE){INC, ZeroPage_X, 2}; + OPCODE[0xEE] = (struct _OPCODE){INC, Absolute, 3}; + OPCODE[0xFE] = (struct _OPCODE){INC, Absolute_X, 3}; + /*INY*/ + OPCODE[0xC8] = (struct _OPCODE){INY, NoneAddressing, 1}; + /*JMP*/ + OPCODE[0x4C] = (struct _OPCODE){JMP, Absolute, 3}; + OPCODE[0x6C] = (struct _OPCODE){JMP, NoneAddressing, 3}; + /*JSR*/ + OPCODE[0x20] = (struct _OPCODE){JSR, Absolute, 3}; + /*LDX*/ + OPCODE[0xA2] = (struct _OPCODE){LDX, Immediate, 2}; + OPCODE[0xA6] = (struct _OPCODE){LDX, ZeroPage, 2}; + OPCODE[0xB6] = (struct _OPCODE){LDX, ZeroPage_Y, 2}; + OPCODE[0xAE] = (struct _OPCODE){LDX, Absolute, 3}; + OPCODE[0xBE] = (struct _OPCODE){LDX, Absolute_Y, 3}; + /*LDY*/ + OPCODE[0xA0] = (struct _OPCODE){LDY, Immediate, 2}; + OPCODE[0xA4] = (struct _OPCODE){LDY, ZeroPage, 2}; + OPCODE[0xB4] = (struct _OPCODE){LDY, ZeroPage_X, 2}; + OPCODE[0xAC] = (struct _OPCODE){LDY, Absolute, 3}; + OPCODE[0xBC] = (struct _OPCODE){LDY, Absolute_X, 3}; + /*LSR*/ + OPCODE[0x4A] = (struct _OPCODE){LSR, NoneAddressing, 1}; + OPCODE[0x46] = (struct _OPCODE){LSR, ZeroPage, 2}; + OPCODE[0x56] = (struct _OPCODE){LSR, ZeroPage_X, 2}; + OPCODE[0x4E] = (struct _OPCODE){LSR, Absolute, 3}; + OPCODE[0x5E] = (struct _OPCODE){LSR, Absolute_X, 3}; + /*NOP*/ + OPCODE[0xEA] = (struct _OPCODE){NOP, NoneAddressing, 1}; + /*ORA*/ + OPCODE[0x09] = (struct _OPCODE){ORA, Immediate, 2}; + OPCODE[0x05] = (struct _OPCODE){ORA, ZeroPage, 2}; + OPCODE[0x15] = (struct _OPCODE){ORA, ZeroPage_X, 2}; + OPCODE[0x0D] = (struct _OPCODE){ORA, Absolute, 3}; + OPCODE[0x1D] = (struct _OPCODE){ORA, Absolute_X, 3}; + OPCODE[0x19] = (struct _OPCODE){ORA, Absolute_Y, 3}; + OPCODE[0x01] = (struct _OPCODE){ORA, Indirect_X, 2}; + OPCODE[0x11] = (struct _OPCODE){ORA, Indirect_Y, 2}; + /*PHA*/ + OPCODE[0x48] = (struct _OPCODE){PHA, NoneAddressing, 1}; + /*PHP*/ + OPCODE[0x08] = (struct _OPCODE){PHP, NoneAddressing, 1}; + /*PLA*/ + OPCODE[0x68] = (struct _OPCODE){PLA, NoneAddressing, 1}; + /*PLP*/ + OPCODE[0x28] = (struct _OPCODE){PLP, NoneAddressing, 1}; + /*ROL*/ + OPCODE[0x2A] = (struct _OPCODE){ROL, NoneAddressing, 1}; + OPCODE[0x26] = (struct _OPCODE){ROL, ZeroPage, 2}; + OPCODE[0x36] = (struct _OPCODE){ROL, ZeroPage_X, 2}; + OPCODE[0x2E] = (struct _OPCODE){ROL, Absolute, 3}; + OPCODE[0x3E] = (struct _OPCODE){ROL, Absolute_X, 3}; + /*ROR*/ + OPCODE[0x6A] = (struct _OPCODE){ROR, NoneAddressing, 1 }; + OPCODE[0x66] = (struct _OPCODE){ROR, ZeroPage, 2 }; + OPCODE[0x76] = (struct _OPCODE){ROR, ZeroPage_X, 2 }; + OPCODE[0x6E] = (struct _OPCODE){ROR, Absolute, 3 }; + OPCODE[0x7E] = (struct _OPCODE){ROR, Absolute_X, 3 }; + /* ADC */ + OPCODE[0x69] = (struct _OPCODE){ADC, Immediate, 2}; + OPCODE[0x65] = (struct _OPCODE){ADC, ZeroPage, 2}; + OPCODE[0x75] = (struct _OPCODE){ADC, ZeroPage_X, 2}; + OPCODE[0x6D] = (struct _OPCODE){ADC, Absolute, 3}; + OPCODE[0x7D] = (struct _OPCODE){ADC, Absolute_X, 3}; + OPCODE[0x79] = (struct _OPCODE){ADC, Absolute_Y, 3}; + OPCODE[0x61] = (struct _OPCODE){ADC, Indirect_X, 2}; + OPCODE[0x71] = (struct _OPCODE){ADC, Indirect_Y, 2}; + /* RTI */ + OPCODE[0x40] = (struct _OPCODE){RTI, NoneAddressing, 1}; + /* RTS */ + OPCODE[0x60] = (struct _OPCODE){RTS, NoneAddressing, 1}; + /* SBC */ + OPCODE[0xE9] = (struct _OPCODE){SBC, Immediate, 2}; + OPCODE[0xE5] = (struct _OPCODE){SBC, ZeroPage, 2}; + OPCODE[0xF5] = (struct _OPCODE){SBC, ZeroPage_X, 2}; + OPCODE[0xED] = (struct _OPCODE){SBC, Absolute, 3}; + OPCODE[0xFD] = (struct _OPCODE){SBC, Absolute_X, 3}; + OPCODE[0xF9] = (struct _OPCODE){SBC, Absolute_Y, 3}; + OPCODE[0xE1] = (struct _OPCODE){SBC, Indirect_X, 2}; + OPCODE[0xF1] = (struct _OPCODE){SBC, Indirect_Y, 2}; + /* SEC */ + OPCODE[0x38] = (struct _OPCODE){SEC, NoneAddressing, 1}; + /* SED */ + OPCODE[0xF8] = (struct _OPCODE){SED, NoneAddressing, 1}; + /* SEI */ + OPCODE[0x78] = (struct _OPCODE){SEI, NoneAddressing, 1}; + /* STX */ + OPCODE[0x86] = (struct _OPCODE){STX, ZeroPage, 2}; + OPCODE[0x96] = (struct _OPCODE){STX, ZeroPage_Y, 2}; + OPCODE[0x8E] = (struct _OPCODE){STX, Absolute, 3}; + /* STY */ + OPCODE[0x84] = (struct _OPCODE){STY, ZeroPage, 2}; + OPCODE[0x94] = (struct _OPCODE){STY, ZeroPage_X, 2}; + OPCODE[0x8C] = (struct _OPCODE){STY, Absolute, 3}; + /* TAY */ + OPCODE[0xA8] = (struct _OPCODE){TAY, NoneAddressing, 1}; + /* TSX */ + OPCODE[0xBA] = (struct _OPCODE){TSX, NoneAddressing, 1}; + /* TXA */ + OPCODE[0x8A] = (struct _OPCODE){TXA, NoneAddressing, 1}; + /* TXS */ + OPCODE[0x9A] = (struct _OPCODE){TXS, NoneAddressing, 1}; + /* TYA */ + OPCODE[0x98] = (struct _OPCODE){TYA, NoneAddressing, 1}; + /* BIT */ + OPCODE[0x24] = (struct _OPCODE){BIT, ZeroPage, 2}; + OPCODE[0x2C] = (struct _OPCODE){BIT, Absolute, 3}; } #endif |