commit 7d77f4257759213bca1e96419be11ac7e84d687f
Author: klewer-martin <martin.cachari@gmail.com>
Date: Tue, 12 Jul 2022 01:40:58 -0300
First commit
A lot of functions still not implemented.
Diffstat:
A | 6502.c | | | 573 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | 6502.h | | | 135 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | Makefile | | | 21 | +++++++++++++++++++++ |
A | README.md | | | 26 | ++++++++++++++++++++++++++ |
A | main.c | | | 30 | ++++++++++++++++++++++++++++++ |
5 files changed, 785 insertions(+), 0 deletions(-)
diff --git a/6502.c b/6502.c
@@ -0,0 +1,573 @@
+#include "6502.h"
+
+#include <stdio.h>
+#include <string.h>
+
+static CPU cpu;
+static MEM mem; /* 8 bit word */
+
+static uint8_t cyc;
+static uint8_t opc;
+static uint8_t fch;
+
+static uint16_t addr_abs;
+static uint16_t addr_rel;
+
+INS lookup[0x100];
+
+static uint8_t ST_FLAG_MASK[] = {
+ (1 << 0), /* Carry */
+ (1 << 1), /* Zero */
+ (1 << 2), /* Disable interrupts */
+ (1 << 3), /* Decimal mode */
+ (1 << 4), /* Break */
+ (1 << 5), /* Unused */
+ (1 << 6), /* Overflow */
+ (1 << 7) /* Negative */
+};
+
+
+/* Cpu methods */
+void CPU_init(void) {
+ cpu.ac = cpu.x = cpu.y = cpu.sp = cpu.st = 0;
+}
+
+void CPU_reset(void) {
+ cpu.sp = 0xFF; /* first page */
+ cpu.st = 0x00 | ST_FLAG_MASK[U];
+
+ /* little endian */
+ uint16_t lo = MEM_fetch(0xFFFC);
+ uint16_t hi = MEM_fetch(0xFFFD);
+
+ cpu.pc = (hi << 8) | lo;
+
+ addr_abs = addr_rel = opc = 0x0000;
+
+ cyc = 8;
+}
+
+void CPU_clock(void) {
+}
+
+void CPU_fetch(INS *ins) {
+ *ins = lookup[MEM_fetch(cpu.pc++)];
+}
+
+void CPU_exec(const INS ins) {
+ addr_abs = 0x0000;
+ ins.mode();
+ ins.op();
+}
+
+void CPU_irq(void) {
+}
+
+void CPU_nm_irq(void) {
+}
+
+void CPU_set_flag(ST_FLAG flag, uint8_t val) {
+ cpu.st = val ? cpu.st | ST_FLAG_MASK[flag] : cpu.st & ~(ST_FLAG_MASK[flag]);
+}
+
+uint8_t CPU_get_flag(ST_FLAG flag) {
+ return ((cpu.st & ST_FLAG_MASK[flag]) >> flag);
+}
+
+void print_reg(uint8_t reg) {
+ for(unsigned long i = ((sizeof(reg) * 8)); i > 0; i--) {
+ putchar((reg & (0x01 << (i - 1))) ? '1' : '0');
+ putchar(' ');
+ }
+
+ putchar('\n');
+}
+
+void CPU_dump(void) {
+ printf("N O - B D I Z C\n");
+ print_reg(cpu.st);
+ printf(" a: %02X\n", cpu.ac);
+ printf(" x: %02X\n", cpu.x);
+ printf(" y: %02X\n", cpu.y);
+ printf(" sp: %02X\n", cpu.sp);
+ printf(" pc: %04X\n", cpu.pc);
+ printf("ram[%04X]: %02X\n", cpu.pc, mem.ram[cpu.pc]);
+}
+
+/* Memory methods */
+void MEM_init(void) {
+ for(uint16_t i = 0; i < 0xFFFF; i++)
+ mem.ram[i] = 0;
+
+ mem.ram[0xFFFC] = 0x00;
+ mem.ram[0xFFFD] = 0x80;
+}
+
+void MEM_load_from_file(char *path) {
+ FILE *fp;
+
+ if(path == NULL) return;
+
+ fp = fopen(path, "rb");
+ if(fp == NULL) return;
+
+ fread(mem.ram + 0x8000, 1, 0x7FFF - 0x6, fp);
+
+ fclose(fp);
+}
+
+uint8_t MEM_fetch(uint16_t addr) {
+ return mem.ram[addr];
+}
+
+uint8_t MEM_write(uint16_t addr, uint8_t val) {
+ mem.ram[addr] = val;
+ return 0;
+}
+
+void MEM_dump(void) {
+ for(uint16_t i = 0; i < 0xF; i++)
+ printf("%02X ", mem.ram[i]);
+
+ putchar('\n');
+}
+
+char *mode_to_str(uint8_t (*mode)(void)) {
+ if(mode == &IMM) return "IMM";
+ else if(mode == &ABS) return "ABS";
+ else if(mode == &ABX) return "ABX";
+ else if(mode == &ABY) return "ABY";
+ else if(mode == &IMP) return "IMP";
+ else if(mode == &IND) return "IND";
+ else if(mode == &IZX) return "IZX";
+ else if(mode == &IZY) return "IZY";
+ else if(mode == &REL) return "REL";
+ else if(mode == &ZP0) return "ZP0";
+ else if(mode == &ZPX) return "ZPX";
+ else if(mode == &ZPY) return "ZPY";
+
+ return "NUL";
+}
+
+/* Lookup table */
+INS lookup[0x100] = {
+ {"BRK", &BRK, &IMM, 7}, {"ORA", &ORA, &IZX, 6}, {"???", &NUL, &IMP, 2},
+ {"???", &NUL, &IMP, 8}, {"???", &NOP, &IMP, 3}, {"ORA", &ORA, &ZP0, 3},
+ {"ASL", &ASL, &ZP0, 5}, {"???", &NUL, &IMP, 5}, {"PHP", &PHP, &IMP, 3},
+ {"ORA", &ORA, &IMM, 2}, {"ASL", &ASL, &IMP, 2}, {"???", &NUL, &IMP, 2},
+ {"???", &NOP, &IMP, 4}, {"ORA", &ORA, &ABS, 4}, {"ASL", &ASL, &ABS, 6},
+ {"???", &NUL, &IMP, 6}, {"BPL", &BPL, &REL, 2}, {"ORA", &ORA, &IZY, 5},
+ {"???", &NUL, &IMP, 2}, {"???", &NUL, &IMP, 8}, {"???", &NOP, &IMP, 4},
+ {"ORA", &ORA, &ZPX, 4}, {"ASL", &ASL, &ZPX, 6}, {"???", &NUL, &IMP, 6},
+ {"CLC", &CLC, &IMP, 2}, {"ORA", &ORA, &ABY, 4}, {"???", &NOP, &IMP, 2},
+ {"???", &NUL, &IMP, 7}, {"???", &NOP, &IMP, 4}, {"ORA", &ORA, &ABX, 4},
+ {"ASL", &ASL, &ABX, 7}, {"???", &NUL, &IMP, 7}, {"JSR", &JSR, &ABS, 6},
+ {"AND", &AND, &IZX, 6}, {"???", &NUL, &IMP, 2}, {"???", &NUL, &IMP, 8},
+ {"BIT", &BIT, &ZP0, 3}, {"AND", &AND, &ZP0, 3}, {"ROL", &ROL, &ZP0, 5},
+ {"???", &NUL, &IMP, 5}, {"PLP", &PLP, &IMP, 4}, {"AND", &AND, &IMM, 2},
+ {"ROL", &ROL, &IMP, 2}, {"???", &NUL, &IMP, 2}, {"BIT", &BIT, &ABS, 4},
+ {"AND", &AND, &ABS, 4}, {"ROL", &ROL, &ABS, 6}, {"???", &NUL, &IMP, 6},
+ {"BMI", &BMI, &REL, 2}, {"AND", &AND, &IZY, 5}, {"???", &NUL, &IMP, 2},
+ {"???", &NUL, &IMP, 8}, {"???", &NOP, &IMP, 4}, {"AND", &AND, &ZPX, 4},
+ {"ROL", &ROL, &ZPX, 6}, {"???", &NUL, &IMP, 6}, {"SEC", &SEC, &IMP, 2},
+ {"AND", &AND, &ABY, 4}, {"???", &NOP, &IMP, 2}, {"???", &NUL, &IMP, 7},
+ {"???", &NOP, &IMP, 4}, {"AND", &AND, &ABX, 4}, {"ROL", &ROL, &ABX, 7},
+ {"???", &NUL, &IMP, 7}, {"RTI", &RTI, &IMP, 6}, {"EOR", &EOR, &IZX, 6},
+ {"???", &NUL, &IMP, 2}, {"???", &NUL, &IMP, 8}, {"???", &NOP, &IMP, 3},
+ {"EOR", &EOR, &ZP0, 3}, {"LSR", &LSR, &ZP0, 5}, {"???", &NUL, &IMP, 5},
+ {"PHA", &PHA, &IMP, 3}, {"EOR", &EOR, &IMM, 2}, {"LSR", &LSR, &IMP, 2},
+ {"???", &NUL, &IMP, 2}, {"JMP", &JMP, &ABS, 3}, {"EOR", &EOR, &ABS, 4},
+ {"LSR", &LSR, &ABS, 6}, {"???", &NUL, &IMP, 6}, {"BVC", &BVC, &REL, 2},
+ {"EOR", &EOR, &IZY, 5}, {"???", &NUL, &IMP, 2}, {"???", &NUL, &IMP, 8},
+ {"???", &NOP, &IMP, 4}, {"EOR", &EOR, &ZPX, 4}, {"LSR", &LSR, &ZPX, 6},
+ {"???", &NUL, &IMP, 6}, {"CLI", &CLI, &IMP, 2}, {"EOR", &EOR, &ABY, 4},
+ {"???", &NOP, &IMP, 2}, {"???", &NUL, &IMP, 7}, {"???", &NOP, &IMP, 4},
+ {"EOR", &EOR, &ABX, 4}, {"LSR", &LSR, &ABX, 7}, {"???", &NUL, &IMP, 7},
+ {"RTS", &RTS, &IMP, 6}, {"ADC", &ADC, &IZX, 6}, {"???", &NUL, &IMP, 2},
+ {"???", &NUL, &IMP, 8}, {"???", &NOP, &IMP, 3}, {"ADC", &ADC, &ZP0, 3},
+ {"ROR", &ROR, &ZP0, 5}, {"???", &NUL, &IMP, 5}, {"PLA", &PLA, &IMP, 4},
+ {"ADC", &ADC, &IMM, 2}, {"ROR", &ROR, &IMP, 2}, {"???", &NUL, &IMP, 2},
+ {"JMP", &JMP, &IND, 5}, {"ADC", &ADC, &ABS, 4}, {"ROR", &ROR, &ABS, 6},
+ {"???", &NUL, &IMP, 6}, {"BVS", &BVS, &REL, 2}, {"ADC", &ADC, &IZY, 5},
+ {"???", &NUL, &IMP, 2}, {"???", &NUL, &IMP, 8}, {"???", &NOP, &IMP, 4},
+ {"ADC", &ADC, &ZPX, 4}, {"ROR", &ROR, &ZPX, 6}, {"???", &NUL, &IMP, 6},
+ {"SEI", &SEI, &IMP, 2}, {"ADC", &ADC, &ABY, 4}, {"???", &NOP, &IMP, 2},
+ {"???", &NUL, &IMP, 7}, {"???", &NOP, &IMP, 4}, {"ADC", &ADC, &ABX, 4},
+ {"ROR", &ROR, &ABX, 7}, {"???", &NUL, &IMP, 7}, {"???", &NOP, &IMP, 2},
+ {"STA", &STA, &IZX, 6}, {"???", &NOP, &IMP, 2}, {"???", &NUL, &IMP, 6},
+ {"STY", &STY, &ZP0, 3}, {"STA", &STA, &ZP0, 3}, {"STX", &STX, &ZP0, 3},
+ {"???", &NUL, &IMP, 3}, {"DEY", &DEY, &IMP, 2}, {"???", &NOP, &IMP, 2},
+ {"TXA", &TXA, &IMP, 2}, {"???", &NUL, &IMP, 2}, {"STY", &STY, &ABS, 4},
+ {"STA", &STA, &ABS, 4}, {"STX", &STX, &ABS, 4}, {"???", &NUL, &IMP, 4},
+ {"BCC", &BCC, &REL, 2}, {"STA", &STA, &IZY, 6}, {"???", &NUL, &IMP, 2},
+ {"???", &NUL, &IMP, 6}, {"STY", &STY, &ZPX, 4}, {"STA", &STA, &ZPX, 4},
+ {"STX", &STX, &ZPY, 4}, {"???", &NUL, &IMP, 4}, {"TYA", &TYA, &IMP, 2},
+ {"STA", &STA, &ABY, 5}, {"TXS", &TXS, &IMP, 2}, {"???", &NUL, &IMP, 5},
+ {"???", &NOP, &IMP, 5}, {"STA", &STA, &ABX, 5}, {"???", &NUL, &IMP, 5},
+ {"???", &NUL, &IMP, 5}, {"LDY", &LDY, &IMM, 2}, {"LDA", &LDA, &IZX, 6},
+ {"LDX", &LDX, &IMM, 2}, {"???", &NUL, &IMP, 6}, {"LDY", &LDY, &ZP0, 3},
+ {"LDA", &LDA, &ZP0, 3}, {"LDX", &LDX, &ZP0, 3}, {"???", &NUL, &IMP, 3},
+ {"TAY", &TAY, &IMP, 2}, {"LDA", &LDA, &IMM, 2}, {"TAX", &TAX, &IMP, 2},
+ {"???", &NUL, &IMP, 2}, {"LDY", &LDY, &ABS, 4}, {"LDA", &LDA, &ABS, 4},
+ {"LDX", &LDX, &ABS, 4}, {"???", &NUL, &IMP, 4}, {"BCS", &BCS, &REL, 2},
+ {"LDA", &LDA, &IZY, 5}, {"???", &NUL, &IMP, 2}, {"???", &NUL, &IMP, 5},
+ {"LDY", &LDY, &ZPX, 4}, {"LDA", &LDA, &ZPX, 4}, {"LDX", &LDX, &ZPY, 4},
+ {"???", &NUL, &IMP, 4}, {"CLV", &CLV, &IMP, 2}, {"LDA", &LDA, &ABY, 4},
+ {"TSX", &TSX, &IMP, 2}, {"???", &NUL, &IMP, 4}, {"LDY", &LDY, &ABX, 4},
+ {"LDA", &LDA, &ABX, 4}, {"LDX", &LDX, &ABY, 4}, {"???", &NUL, &IMP, 4},
+ {"CPY", &CPY, &IMM, 2}, {"CMP", &CMP, &IZX, 6}, {"???", &NOP, &IMP, 2},
+ {"???", &NUL, &IMP, 8}, {"CPY", &CPY, &ZP0, 3}, {"CMP", &CMP, &ZP0, 3},
+ {"DEC", &DEC, &ZP0, 5}, {"???", &NUL, &IMP, 5}, {"INY", &INY, &IMP, 2},
+ {"CMP", &CMP, &IMM, 2}, {"DEX", &DEX, &IMP, 2}, {"???", &NUL, &IMP, 2},
+ {"CPY", &CPY, &ABS, 4}, {"CMP", &CMP, &ABS, 4}, {"DEC", &DEC, &ABS, 6},
+ {"???", &NUL, &IMP, 6}, {"BNE", &BNE, &REL, 2}, {"CMP", &CMP, &IZY, 5},
+ {"???", &NUL, &IMP, 2}, {"???", &NUL, &IMP, 8}, {"???", &NOP, &IMP, 4},
+ {"CMP", &CMP, &ZPX, 4}, {"DEC", &DEC, &ZPX, 6}, {"???", &NUL, &IMP, 6},
+ {"CLD", &CLD, &IMP, 2}, {"CMP", &CMP, &ABY, 4}, {"NOP", &NOP, &IMP, 2},
+ {"???", &NUL, &IMP, 7}, {"???", &NOP, &IMP, 4}, {"CMP", &CMP, &ABX, 4},
+ {"DEC", &DEC, &ABX, 7}, {"???", &NUL, &IMP, 7}, {"CPX", &CPX, &IMM, 2},
+ {"SBC", &SBC, &IZX, 6}, {"???", &NOP, &IMP, 2}, {"???", &NUL, &IMP, 8},
+ {"CPX", &CPX, &ZP0, 3}, {"SBC", &SBC, &ZP0, 3}, {"INC", &INC, &ZP0, 5},
+ {"???", &NUL, &IMP, 5}, {"INX", &INX, &IMP, 2}, {"SBC", &SBC, &IMM, 2},
+ {"NOP", &NOP, &IMP, 2}, {"???", &SBC, &IMP, 2}, {"CPX", &CPX, &ABS, 4},
+ {"SBC", &SBC, &ABS, 4}, {"INC", &INC, &ABS, 6}, {"???", &NUL, &IMP, 6},
+ {"BEQ", &BEQ, &REL, 2}, {"SBC", &SBC, &IZY, 5}, {"???", &NUL, &IMP, 2},
+ {"???", &NUL, &IMP, 8}, {"???", &NOP, &IMP, 4}, {"SBC", &SBC, &ZPX, 4},
+ {"INC", &INC, &ZPX, 6}, {"???", &NUL, &IMP, 6}, {"SED", &SED, &IMP, 2},
+ {"SBC", &SBC, &ABY, 4}, {"NOP", &NOP, &IMP, 2}, {"???", &NUL, &IMP, 7},
+ {"???", &NOP, &IMP, 4}, {"SBC", &SBC, &ABX, 4}, {"INC", &INC, &ABX, 7},
+ {"???", &NUL, &IMP, 7}
+};
+
+
+/* Addressing modes */
+uint8_t ABS(void) {
+ uint8_t lo = MEM_fetch(cpu.pc++);
+ uint8_t hi = MEM_fetch(cpu.pc++);
+
+ addr_abs = (hi << 8) | lo;
+ return 0;
+}
+
+uint8_t ABX(void) {
+ return 0;
+}
+
+uint8_t ABY(void) {
+ return 0;
+}
+
+uint8_t IMM(void) {
+ addr_abs = cpu.pc++;
+ return 0;
+}
+
+uint8_t IMP(void) {
+ fch = cpu.ac;
+ return 0;
+}
+
+uint8_t IND(void) {
+ return 0;
+}
+
+uint8_t IZX(void) {
+ return 0;
+}
+
+uint8_t IZY(void) {
+ return 0;
+}
+
+uint8_t REL(void) {
+ addr_rel = MEM_fetch(cpu.pc++);
+
+ if(addr_rel & (1 << 7))
+ addr_rel |= 0xFF00;
+
+ return 0;
+}
+
+uint8_t ZP0(void) {
+ return 0;
+}
+
+uint8_t ZPX(void) {
+ return 0;
+}
+
+uint8_t ZPY(void) {
+ return 0;
+}
+
+
+/* Instructions */
+uint8_t ADC(void) {
+ uint8_t data = MEM_fetch(addr_abs);
+
+ cpu.ac += (data + CPU_get_flag(C));
+
+ CPU_set_flag(Z, cpu.ac == 0);
+ CPU_set_flag(N, cpu.ac & (1 << 7));
+ CPU_set_flag(O, ((cpu.ac^data) & ~(cpu.ac^data)) & (1 << 7));
+
+ return 1;
+}
+
+uint8_t AND(void) {
+ return 0;
+}
+
+uint8_t ASL(void) {
+
+ return 0;
+}
+
+uint8_t BCC(void) {
+ return 0;
+}
+
+uint8_t BCS(void) {
+ return 0;
+}
+
+uint8_t BEQ(void) {
+ return 0;
+}
+
+uint8_t BIT(void) {
+ return 0;
+}
+
+uint8_t BMI(void) {
+ return 0;
+}
+
+uint8_t BNE(void) {
+ if(!CPU_get_flag(Z))
+ cpu.pc += addr_rel;
+
+ return 0;
+}
+
+uint8_t BPL(void) {
+ return 0;
+}
+
+uint8_t BRK(void) {
+ return 0;
+}
+
+uint8_t BVC(void) {
+ return 0;
+}
+
+uint8_t BVS(void) {
+ return 0;
+}
+
+uint8_t CLC(void) {
+ CPU_set_flag(C, 0);
+ return 0;
+}
+
+uint8_t CLD(void) {
+ return 0;
+}
+
+uint8_t CLI(void) {
+ return 0;
+}
+
+uint8_t CLV(void) {
+ return 0;
+}
+
+uint8_t CMP(void) {
+ return 0;
+}
+
+uint8_t CPX(void) {
+ return 0;
+}
+
+uint8_t CPY(void) {
+ return 0;
+}
+
+uint8_t DEC(void) {
+ return 0;
+}
+
+uint8_t DEX(void) {
+ cpu.x -= 1;
+
+ CPU_set_flag(Z, cpu.x == 0);
+ CPU_set_flag(N, cpu.x & (1 << 7));
+
+ return 0;
+}
+
+/* Subtracts one from the Y register */
+uint8_t DEY(void) {
+ cpu.y -= 1;
+
+ CPU_set_flag(Z, cpu.y == 0);
+ CPU_set_flag(N, cpu.y & (1 << 7));
+
+ return 0;
+}
+
+uint8_t EOR(void) {
+ return 0;
+}
+
+uint8_t INC(void) {
+ return 0;
+}
+
+uint8_t INX(void) {
+ return 0;
+}
+
+uint8_t INY(void) {
+ return 0;
+}
+
+uint8_t JMP(void) {
+ return 0;
+}
+
+uint8_t JSR(void) {
+ return 0;
+}
+
+uint8_t LDA(void) {
+ cpu.ac = MEM_fetch(addr_abs);
+
+ CPU_set_flag(Z, cpu.ac == 0);
+ CPU_set_flag(N, cpu.ac & (1 << 7));
+
+ return 0;
+}
+
+uint8_t LDX(void) {
+ cpu.x = MEM_fetch(addr_abs);
+
+ CPU_set_flag(Z, cpu.x == 0);
+ CPU_set_flag(N, cpu.x & (1 << 7));
+
+ return 0;
+}
+
+uint8_t LDY(void) {
+ cpu.y = MEM_fetch(addr_abs);
+
+ CPU_set_flag(Z, cpu.y == 0);
+ CPU_set_flag(N, cpu.y & (1 << 7));
+
+ return 0;
+}
+
+uint8_t LSR(void) {
+ return 0;
+}
+
+uint8_t NOP(void) {
+ return 0;
+}
+
+uint8_t ORA(void) {
+ return 0;
+}
+
+uint8_t PHA(void) {
+ return 0;
+}
+
+uint8_t PHP(void) {
+ return 0;
+}
+
+uint8_t PLA(void) {
+ return 0;
+}
+
+uint8_t PLP(void) {
+ return 0;
+}
+
+uint8_t ROL(void) {
+ return 0;
+}
+
+uint8_t ROR(void) {
+ return 0;
+}
+
+uint8_t RTI(void) {
+ return 0;
+}
+
+uint8_t RTS(void) {
+ return 0;
+}
+
+uint8_t SBC(void) {
+ return 0;
+}
+
+uint8_t SEC(void) {
+ return 0;
+}
+
+uint8_t SED(void) {
+ return 0;
+}
+
+uint8_t SEI(void) {
+ return 0;
+}
+
+uint8_t STA(void) {
+ MEM_write(addr_abs, cpu.ac);
+ return 0;
+}
+
+uint8_t STX(void) {
+ MEM_write(addr_abs, cpu.x);
+ return 0;
+}
+
+uint8_t STY(void) {
+ return 0;
+}
+
+uint8_t TAX(void) {
+ return 0;
+}
+
+uint8_t TAY(void) {
+ return 0;
+}
+
+uint8_t TSX(void) {
+ return 0;
+}
+
+uint8_t TXA(void) {
+ return 0;
+}
+
+uint8_t TXS(void) {
+ return 0;
+}
+
+uint8_t TYA(void) {
+ return 0;
+}
+
+
+uint8_t NUL(void) {
+ return 0;
+}
diff --git a/6502.h b/6502.h
@@ -0,0 +1,135 @@
+#ifndef __6502_H__
+#define __6502_H__
+
+#include <stdio.h>
+#include <stdint.h>
+
+/* Instruction */
+typedef struct {
+ char *name;
+ uint8_t (*op)(void);
+ uint8_t (*mode)(void);
+ uint8_t cycles;
+} INS;
+
+typedef struct {
+ uint8_t ac, x, y, sp, st;
+ uint16_t pc;
+} CPU;
+
+typedef struct {
+ uint8_t ram[0xFFFF]; /* 8 bit word */
+} MEM;
+
+/* 6502 status register */
+typedef enum {
+ C, /* Carry */
+ Z, /* Zero */
+ I, /* Disable interrupts */
+ D, /* Decimal mode */
+ B, /* Break */
+ U, /* Unused */
+ O, /* Overflow */
+ N /* Negative */
+} ST_FLAG;
+
+void CPU_init(void);
+void CPU_reset(void);
+void CPU_clock(void);
+void CPU_fetch(INS *ins);
+void CPU_exec(INS ins);
+
+void CPU_irq(void);
+void CPU_nm_irq(void);
+
+void CPU_set_flag(ST_FLAG flag, uint8_t val);
+uint8_t CPU_get_flag(ST_FLAG flag);
+
+void CPU_dump(void);
+
+void MEM_init(void);
+void MEM_dump(void);
+void MEM_load_from_file(char *fp);
+
+uint8_t MEM_fetch(uint16_t addr);
+uint8_t MEM_write(uint16_t addr, uint8_t val);
+
+char *mode_to_str(uint8_t (*mode)(void));
+
+/* Addresing modes */
+uint8_t ABS(void);
+uint8_t ABX(void);
+uint8_t ABY(void);
+uint8_t IMM(void);
+uint8_t IMP(void);
+uint8_t IND(void);
+uint8_t IZX(void);
+uint8_t IZY(void);
+uint8_t REL(void);
+uint8_t ZP0(void);
+uint8_t ZPX(void);
+uint8_t ZPY(void);
+
+
+/* Opcodes */
+uint8_t ADC(void);
+uint8_t AND(void);
+uint8_t ASL(void);
+uint8_t BCC(void);
+uint8_t BCS(void);
+uint8_t BEQ(void);
+uint8_t BIT(void);
+uint8_t BMI(void);
+uint8_t BNE(void);
+uint8_t BPL(void);
+uint8_t BRK(void);
+uint8_t BVC(void);
+uint8_t BVS(void);
+uint8_t CLC(void);
+uint8_t CLD(void);
+uint8_t CLI(void);
+uint8_t CLV(void);
+uint8_t CMP(void);
+uint8_t CPX(void);
+uint8_t CPY(void);
+uint8_t DEC(void);
+uint8_t DEX(void);
+uint8_t DEY(void);
+uint8_t EOR(void);
+uint8_t INC(void);
+uint8_t INX(void);
+uint8_t INY(void);
+uint8_t JMP(void);
+uint8_t JSR(void);
+uint8_t LDA(void);
+uint8_t LDX(void);
+uint8_t LDY(void);
+uint8_t LSR(void);
+uint8_t NOP(void);
+uint8_t ORA(void);
+uint8_t PHA(void);
+uint8_t PHP(void);
+uint8_t PLA(void);
+uint8_t PLP(void);
+uint8_t ROL(void);
+uint8_t ROR(void);
+uint8_t RTI(void);
+uint8_t RTS(void);
+uint8_t SBC(void);
+uint8_t SEC(void);
+uint8_t SED(void);
+uint8_t SEI(void);
+uint8_t STA(void);
+uint8_t STX(void);
+uint8_t STY(void);
+uint8_t TAX(void);
+uint8_t TAY(void);
+uint8_t TSX(void);
+uint8_t TXA(void);
+uint8_t TXS(void);
+uint8_t TYA(void);
+
+uint8_t NUL(void);
+
+
+#endif
diff --git a/Makefile b/Makefile
@@ -0,0 +1,21 @@
+CC := gcc
+CLIBS :=
+CFLAGS := -Wall -Wshadow -pedantic -ansi -std=c99 -O3
+SRCS := $(wildcard *.c)
+OBJS := $(SRCS:.c=.o)
+
+TARGET := 6502
+
+.PHONY: all clean
+
+all: $(TARGET)
+
+$(TARGET): $(OBJS)
+ $(CC) $(CLIBS) $(CFLAGS) -o $@ $^
+ rm -f $(OBJS)
+
+%.o: %.c
+ $(CC) $(CLIBS) $(CFLAGS) -c $< -o $@
+
+clean:
+ rm -f $(OBJS)
diff --git a/README.md b/README.md
@@ -0,0 +1,26 @@
+# 6502 Emulator
+
+## Resources used
+- 27c3: Reverse Engineering the MOS 6502 CPU (en): <br>
+ https://www.youtube.com/watch?v=fWqBmmPQP40&t=34s
+
+- NES Emulator Part #2: The CPU (6502 Implementation): <br>
+ https://www.youtube.com/watch?v=8XmxKPJDGU0&t=625s
+
+- Interpreting Instructions in C: <br>
+ https://www.youtube.com/watch?v=ZJy2evCLAsM
+
+- Emulator 101 - 6502 Addressing Modes: <br>
+ http://www.emulator101.com/6502-addressing-modes.html
+
+- “Hello, world” from scratch on a 6502 — Part 1: <br>
+ https://www.youtube.com/watch?v=LnzuMJLZRdU
+
+
+### Clock algorithm
+
+1. Read byte @ pc
+2. Decode the byte in order to get info about the instruction
+3. Read 0,1 or 2 more bytes, depending on the decoded byte
+4. Execute the instruction
+5. Wait, cycling until the instruction is complete
diff --git a/main.c b/main.c
@@ -0,0 +1,30 @@
+#include "6502.h"
+
+#include <stdio.h>
+#include <stdbool.h>
+
+#define INPUT_FILE_PATH "example.bin"
+
+int main (void) {
+ INS ins;
+
+ MEM_init();
+ MEM_load_from_file(INPUT_FILE_PATH);
+
+ CPU_init();
+ CPU_reset();
+
+ do {
+ CPU_dump();
+ CPU_fetch(&ins);
+ CPU_exec(ins);
+
+ printf("ins: %s (%s)(%d)\n", ins.name, mode_to_str(ins.mode), ins.cycles);
+
+ CPU_clock();
+
+ MEM_dump();
+ } while(getchar() != 'q');
+
+ return 0;
+}