summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorleo <leo@azuminha.com>2024-07-07 03:31:34 -0300
committerleo <leo@azuminha.com>2024-07-07 03:31:34 -0300
commit93c7430dbe4dceb8f8e90cede2d5a65d1fdba2a9 (patch)
tree2e8a53163860ed94edf5ce462b08ea8a12928b86
parent1cffb789b5d258c3d6fced0fb949f068b1b23bae (diff)
terminei a cpu, mas ta errado em alguma parte e eu nao seiHEADmaster
-rw-r--r--CPU.c1097
-rw-r--r--CPU.h59
-rw-r--r--opcode_pc.h369
3 files changed, 1127 insertions, 398 deletions
diff --git a/CPU.c b/CPU.c
index a0fe581..5e82aab 100644
--- a/CPU.c
+++ b/CPU.c
@@ -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;
}
diff --git a/CPU.h b/CPU.h
index 8918c47..dbfd9ed 100644
--- a/CPU.h
+++ b/CPU.h
@@ -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