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 @@
1#include <libgen.h>
1#include <stdint.h> 2#include <stdint.h>
2#include <stdio.h> 3#include <stdio.h>
3#include <stdlib.h> 4#include <stdlib.h>
4#include <string.h> 5#include <string.h>
5 6
7#include "rom.h"
8
6#define MAX(a, b) ((a > b) ? a : b) 9#define MAX(a, b) ((a > b) ? a : b)
7 10
8#define STATUS_UPDATE_ZERO(r) \ 11#define STATUS_UPDATE_ZERO(r) \
@@ -37,7 +40,9 @@ struct registers {
37 struct cpu_flags status; 40 struct cpu_flags status;
38 uint16_t pc; 41 uint16_t pc;
39}; 42};
40struct registers regs; 43struct registers regs = {0};
44
45struct Rom rom = {0};
41 46
42enum addressing_mode { 47enum addressing_mode {
43 AM_IMM, 48 AM_IMM,
@@ -56,9 +61,6 @@ enum addressing_mode {
56/* 64K address space, 16bit words */ 61/* 64K address space, 16bit words */
57uint8_t memory[0x16000]; 62uint8_t memory[0x16000];
58 63
59/* example program taken from https://bugzmanov.github.io/nes_ebook/chapter_3_1.html */
60uint8_t program[] = { 0xa9, 0xc0, 0xaa, 0xe8, 0x00 };
61
62uint32_t cycles = 0; 64uint32_t cycles = 0;
63 65
64static uint8_t 66static uint8_t
@@ -66,7 +68,14 @@ peek(uint16_t addr)
66{ 68{
67 MEMORY_MIRROR(addr); 69 MEMORY_MIRROR(addr);
68 70
69 return memory[addr]; 71 if (addr > 0x7FFF) {
72 if (rom.prg_rom_size == 0x4000)
73 return rom.prg_rom[(addr - 0x8000) % 0x4000];
74 else if (rom.prg_rom_size == 0x8000)
75 return rom.prg_rom[addr - 0x8000];
76 } else {
77 return memory[addr];
78 }
70} 79}
71 80
72static uint16_t 81static uint16_t
@@ -738,7 +747,7 @@ interpret(void)
738 for (;;) { 747 for (;;) {
739 opcode = peek(regs.pc++); 748 opcode = peek(regs.pc++);
740 749
741 printf("opcode: $%02X\n", opcode); 750 printf("opcode: $%02X @ $%04X\n", opcode, regs.pc - 1);
742 751
743 switch (opcode) { 752 switch (opcode) {
744 case 0x69: 753 case 0x69:
@@ -1403,7 +1412,7 @@ interpret(void)
1403 regs.status.decimal_mode, regs.status.brk, 1412 regs.status.decimal_mode, regs.status.brk,
1404 regs.status.unused, regs.status.overflow, 1413 regs.status.unused, regs.status.overflow,
1405 regs.status.negative); 1414 regs.status.negative);
1406 printf("A: $%02X, X: $%02X, Y: $%02X, SP: $%02X, PC: $%02X\n", 1415 printf("A: $%02X, X: $%02X, Y: $%02X, SP: $%02X, PC: $%04X\n",
1407 regs.a, regs.x, regs.y, regs.sp, regs.pc); 1416 regs.a, regs.x, regs.y, regs.sp, regs.pc);
1408 } 1417 }
1409} 1418}
@@ -1416,26 +1425,51 @@ cpu_init(void)
1416 regs.pc = 0xFFFC; 1425 regs.pc = 0xFFFC;
1417 regs.sp = 0xFD; 1426 regs.sp = 0xFD;
1418 1427
1419 memset(&regs.status, 0, sizeof(regs.status)); 1428 //memset(&regs.status, 0, sizeof(regs.status));
1420 regs.status.unused = 1; 1429 regs.status.unused = 1;
1421 1430
1422 cycles += 7; 1431 cycles += 7;
1423} 1432}
1424 1433
1425int 1434int
1426main(void) 1435main(int argc, char *argv[])
1427{ 1436{
1437 FILE *fp;
1438 uint8_t *buf;
1439 size_t buflen;
1440
1441 if (argc != 2) {
1442 fprintf(stderr, "Usage: %s rom.nes\n", basename(argv[0]));
1443 return 1;
1444 }
1445
1446 fp = fopen(argv[1], "r");
1447 fseek(fp, 0, SEEK_END);
1448 buflen = ftell(fp);
1449 buf = calloc(1, buflen);
1450 fseek(fp, 0, SEEK_SET);
1451 if (fread(buf, 1, buflen, fp) != buflen && ferror(fp)) {
1452 fprintf(stderr, "file %s was not read properly\n", argv[1]);
1453 clearerr(fp);
1454 fclose(fp);
1455 return 1;
1456 }
1457 fclose(fp);
1458
1459 parse_rom(buf, buflen, &rom);
1460 free(buf);
1461
1428 cpu_init(); 1462 cpu_init();
1429 1463
1430 if (sizeof(program) > (0x10000 - 0x8000)) { 1464 /* TODO: move to separate file? */
1431 fprintf(stderr, "program is too big for memory\n"); 1465 if (rom.mapper != 0) {
1466 fprintf(stderr, "Only iNES ROMs using Mapper 0 are supported for now.\n");
1432 return 1; 1467 return 1;
1433 } 1468 }
1434 1469
1435 memcpy(memory + 0x8000, program, sizeof(program)); 1470 memwrite16(0xFFFC, 0x8000);
1436 regs.pc = 0x8000; 1471 regs.pc = 0x8000;
1437 1472
1438 printf("Initial State:\n");
1439 printf("status: %i%i%i%i%i%i%i%i\n", regs.status.carry, 1473 printf("status: %i%i%i%i%i%i%i%i\n", regs.status.carry,
1440 regs.status.zero, regs.status.interrupt_disable, 1474 regs.status.zero, regs.status.interrupt_disable,
1441 regs.status.decimal_mode, regs.status.brk, 1475 regs.status.decimal_mode, regs.status.brk,
@@ -1448,5 +1482,7 @@ main(void)
1448 1482
1449 interpret(); 1483 interpret();
1450 1484
1485 free_rom(&rom);
1486
1451 return 0; 1487 return 0;
1452} 1488}