summaryrefslogtreecommitdiff
path: root/cpu.c
diff options
context:
space:
mode:
Diffstat (limited to 'cpu.c')
-rw-r--r--cpu.c62
1 files changed, 49 insertions, 13 deletions
diff --git a/cpu.c b/cpu.c
index 61b835c..968fcd8 100644
--- a/cpu.c
+++ b/cpu.c
@@ -1,8 +1,11 @@
+#include <libgen.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include "rom.h"
+
#define MAX(a, b) ((a > b) ? a : b)
#define STATUS_UPDATE_ZERO(r) \
@@ -37,7 +40,9 @@ struct registers {
struct cpu_flags status;
uint16_t pc;
};
-struct registers regs;
+struct registers regs = {0};
+
+struct Rom rom = {0};
enum addressing_mode {
AM_IMM,
@@ -56,9 +61,6 @@ enum addressing_mode {
/* 64K address space, 16bit words */
uint8_t memory[0x16000];
-/* example program taken from https://bugzmanov.github.io/nes_ebook/chapter_3_1.html */
-uint8_t program[] = { 0xa9, 0xc0, 0xaa, 0xe8, 0x00 };
-
uint32_t cycles = 0;
static uint8_t
@@ -66,7 +68,14 @@ peek(uint16_t addr)
{
MEMORY_MIRROR(addr);
- return memory[addr];
+ if (addr > 0x7FFF) {
+ if (rom.prg_rom_size == 0x4000)
+ return rom.prg_rom[(addr - 0x8000) % 0x4000];
+ else if (rom.prg_rom_size == 0x8000)
+ return rom.prg_rom[addr - 0x8000];
+ } else {
+ return memory[addr];
+ }
}
static uint16_t
@@ -738,7 +747,7 @@ interpret(void)
for (;;) {
opcode = peek(regs.pc++);
- printf("opcode: $%02X\n", opcode);
+ printf("opcode: $%02X @ $%04X\n", opcode, regs.pc - 1);
switch (opcode) {
case 0x69:
@@ -1403,7 +1412,7 @@ interpret(void)
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",
+ printf("A: $%02X, X: $%02X, Y: $%02X, SP: $%02X, PC: $%04X\n",
regs.a, regs.x, regs.y, regs.sp, regs.pc);
}
}
@@ -1416,26 +1425,51 @@ cpu_init(void)
regs.pc = 0xFFFC;
regs.sp = 0xFD;
- memset(&regs.status, 0, sizeof(regs.status));
+ //memset(&regs.status, 0, sizeof(regs.status));
regs.status.unused = 1;
cycles += 7;
}
int
-main(void)
+main(int argc, char *argv[])
{
+ FILE *fp;
+ uint8_t *buf;
+ size_t buflen;
+
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s rom.nes\n", basename(argv[0]));
+ return 1;
+ }
+
+ fp = fopen(argv[1], "r");
+ fseek(fp, 0, SEEK_END);
+ buflen = ftell(fp);
+ buf = calloc(1, buflen);
+ fseek(fp, 0, SEEK_SET);
+ if (fread(buf, 1, buflen, fp) != buflen && ferror(fp)) {
+ fprintf(stderr, "file %s was not read properly\n", argv[1]);
+ clearerr(fp);
+ fclose(fp);
+ return 1;
+ }
+ fclose(fp);
+
+ parse_rom(buf, buflen, &rom);
+ free(buf);
+
cpu_init();
- if (sizeof(program) > (0x10000 - 0x8000)) {
- fprintf(stderr, "program is too big for memory\n");
+ /* TODO: move to separate file? */
+ if (rom.mapper != 0) {
+ fprintf(stderr, "Only iNES ROMs using Mapper 0 are supported for now.\n");
return 1;
}
- memcpy(memory + 0x8000, program, sizeof(program));
+ memwrite16(0xFFFC, 0x8000);
regs.pc = 0x8000;
- 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,
@@ -1448,5 +1482,7 @@ main(void)
interpret();
+ free_rom(&rom);
+
return 0;
}