diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4d0dfab --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +a.out +*.core +*~ diff --git a/cpu.c b/cpu.c index 0843189..14c2ce3 100644 --- a/cpu.c +++ b/cpu.c @@ -1,4 +1,10 @@ #include +#include + +#define STATUS_UPDATE_ZERO(r) \ + (regs.status.zero = r == 0) +#define STATUS_UPDATE_NEGATIVE(r) \ + (regs.status.negative = ((r & (1 << 7)) > 0)) struct cpu_flags { uint8_t carry : 1; @@ -12,7 +18,7 @@ struct cpu_flags { }; struct registers { - uint8_t acc, x, y, sp; + uint8_t a, x, y, sp; struct cpu_flags status; uint16_t pc; }; @@ -40,28 +46,64 @@ uint8_t addrbus[0x10000]; /* example program taken from https://bugzmanov.github.io/nes_ebook/chapter_3_1.html */ uint8_t program[] = { 0xa9, 0xc0, 0xaa, 0xe8, 0x00 }; -void brk(void) +void +brk(void) { + /* $00 */ /* TODO: push regs.pc and regs.status to stack and load IRQ vector */ regs.status.brk = 1; return; } -void lda(enum addressing_mode mode) +void +tax(void) +{ + /* $AA */ + regs.x = regs.a; + + STATUS_UPDATE_ZERO(regs.x); + STATUS_UPDATE_NEGATIVE(regs.x); +} + +void +inx(void) +{ + /* $E8 */ + regs.x++; + + STATUS_UPDATE_ZERO(regs.x); + STATUS_UPDATE_NEGATIVE(regs.x); +} + +void +lda(enum addressing_mode mode) { uint8_t val; switch (mode) { case AM_IMMEDIATE: /* $A9 */ val = program[regs.pc++]; - regs.acc = val; + printf("arg1 $%02X\n", val); + regs.a = val; break; case AM_ZERO_PAGE: /* $A5 */ + /* TODO */ + break; case AM_ZERO_PAGE_X: /* $B5 */ + /* TODO */ + break; case AM_ABSOLUTE: /* $AD */ + /* TODO */ + break; case AM_ABSOLUTE_X: /* $BD */ + /* TODO */ + break; case AM_ABSOLUTE_Y: /* $B9 */ + /* TODO */ + break; case AM_INDIRECT_X: /* $A1 */ + /* TODO */ + break; case AM_INDIRECT_Y: /* $B1 */ /* TODO */ break; @@ -69,48 +111,86 @@ void lda(enum addressing_mode mode) return; } - regs.status.zero = regs.acc == 0; - regs.status.negative = (regs.acc & (1 << 7)) != 0; + STATUS_UPDATE_ZERO(regs.a); + STATUS_UPDATE_NEGATIVE(regs.a); } -void interpret(void) +void +interpret(void) { uint8_t opcode; regs.pc = 0; + regs.status.unused = 1; + + printf("Initial State:\n"); + printf("status: %i%i%i%i%i%i%i%i\n", regs.status.carry, + regs.status.zero, regs.status.interrupt_disable, + regs.status.decimal_mode, regs.status.brk, + regs.status.unused, regs.status.overflow, + regs.status.negative); + printf("A: $%02X, X: $%02X, Y: $%02X, SP: $%02X, PC: $%02X\n", + regs.a, regs.x, regs.y, regs.sp, regs.pc); + + putchar('\n'); for (;;) { opcode = program[regs.pc++]; + printf("opcode: $%02X\n", opcode); + switch (opcode) { case 0x00: brk(); return; - case 0xa9: - lda(AM_IMMEDIATE); + case 0xa1: + lda(AM_INDIRECT_X); break; case 0xa5: lda(AM_ZERO_PAGE); break; - case 0xb5: - lda(AM_ZERO_PAGE_X); + case 0xa9: + lda(AM_IMMEDIATE); + break; + case 0xaa: + tax(); break; case 0xad: lda(AM_ABSOLUTE); break; - case 0xbd: - lda(AM_ABSOLUTE_X); + case 0xb1: + lda(AM_INDIRECT_Y); + break; + case 0xb5: + lda(AM_ZERO_PAGE_X); break; case 0xb9: lda(AM_ABSOLUTE_Y); break; - case 0xa1: - lda(AM_INDIRECT_X); + case 0xbd: + lda(AM_ABSOLUTE_X); break; - case 0xb1: - lda(AM_INDIRECT_Y); + case 0xe8: + inx(); break; default: + printf("opcode $%02X not implemented\n", opcode); break; } + + printf("status: %i%i%i%i%i%i%i%i\n", regs.status.carry, + regs.status.zero, regs.status.interrupt_disable, + regs.status.decimal_mode, regs.status.brk, + regs.status.unused, regs.status.overflow, + regs.status.negative); + printf("A: $%02X, X: $%02X, Y: $%02X, SP: $%02X, PC: $%02X\n", + regs.a, regs.x, regs.y, regs.sp, regs.pc); } } + +int +main(void) +{ + interpret(); + + return 0; +}