diff options
Diffstat (limited to 'cpu.c')
-rw-r--r-- | cpu.c | 62 |
1 files changed, 49 insertions, 13 deletions
@@ -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(®s.status, 0, sizeof(regs.status)); + //memset(®s.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; } |