From acce479cfa346b42f0cb4185573e089d17508d6e Mon Sep 17 00:00:00 2001 From: FyloZ Date: Sat, 23 Dec 2023 16:35:23 -0500 Subject: [PATCH] Load and execute first instruction --- .idea/workspace.xml | 56 +++++++---------------------------- cpu/cpu.c | 18 +++++++++++- cpu/cpu.h | 2 ++ cpu/memory.c | 19 ++++++++++-- cpu/op.c | 4 +-- cpu/op.h | 6 +++- include/cpu.h | 8 ++--- include/rom.h | 21 +++++++++++--- main.c | 10 +++++-- rom/ines.c | 69 +++++++++++++++++++++++++++++++------------- rom/rom.c | 58 +++++++++++++++++++++++++------------ tests/smb.nes | Bin 0 -> 40976 bytes 12 files changed, 169 insertions(+), 102 deletions(-) create mode 100644 tests/smb.nes diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 4af0041..f9bd56e 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -23,40 +23,19 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + + - + + + + + - - - - @@ -315,6 +289,7 @@ + - - - - - file://$PROJECT_DIR$/rom/rom.c - 32 - - - - \ No newline at end of file diff --git a/cpu/cpu.c b/cpu/cpu.c index 9a582e6..5e7654e 100644 --- a/cpu/cpu.c +++ b/cpu/cpu.c @@ -1,6 +1,7 @@ #include "../include/cpu.h" #include "cpu.h" #include "memory.h" +#include "op.h" /* * ===================================================================================== @@ -24,12 +25,27 @@ CpuRegisters registers; Mapper mapper; void cpu_init() { - registers.program_counter = 0x0000; + registers.program_counter = 0xc000; registers.stack_pointer = 0xff; registers.accumulator = 0x00; registers.x = 0x00; registers.y = 0x00; registers.status = 0x00; + + mapper = get_mapper(MAPPER_TYPE_SIMPLE); +} + +void cpu_step() { + int i = 0; + while (i < 10) { + byte op = cpu_get_next_byte(); + process_op_code(op); + i += 1; + } +} + +void cpu_add_cycles(unsigned int cycle_count) { + } // === Registers === diff --git a/cpu/cpu.h b/cpu/cpu.h index faaea60..5653508 100644 --- a/cpu/cpu.h +++ b/cpu/cpu.h @@ -58,4 +58,6 @@ void cpu_stack_push_context(); byte cpu_stack_pop(); void cpu_stack_pop_context(); +void cpu_add_cycles(unsigned int cycle_count); + #endif //CPU_CPU_H diff --git a/cpu/memory.c b/cpu/memory.c index 00df8c7..57d4337 100644 --- a/cpu/memory.c +++ b/cpu/memory.c @@ -4,15 +4,30 @@ #include "memory.h" #include "ram.h" +#include "../include/rom.h" byte mem_get_byte(Mapper *mapper, address addr) { address redirected_addr = mapper->redirect_addr(addr); - return ram_get_byte(redirected_addr); + + if (redirected_addr < 0x0800) { + return ram_get_byte(redirected_addr); + } else if (redirected_addr >= 0x4020) { + return rom_prg_get_byte(redirected_addr - 0x4020); + } + + return 0; } word mem_get_word(Mapper *mapper, address addr) { address redirected_addr = mapper->redirect_addr(addr); - return ram_get_word(redirected_addr); + + if (redirected_addr < 0x0800) { + return ram_get_word(redirected_addr); + } else if (redirected_addr >= 0x4020) { + return rom_prg_get_word(redirected_addr - 0x4020); + } + + return 0; } void mem_set_byte(Mapper *mapper, address addr, byte byte) { diff --git a/cpu/op.c b/cpu/op.c index a548ecf..196f437 100644 --- a/cpu/op.c +++ b/cpu/op.c @@ -10,7 +10,7 @@ #define IS_OP_CODE_MODE(op, op_code, addr_mode) \ case op_code: \ - log_debug("OP: %s", "op"); \ + log_debug("OP: %s", #op); \ op_ ## op(ADDR_MODE_ ## addr_mode); \ break; @@ -809,7 +809,7 @@ void op_XAA(AddressingMode addr_mode) { assert(false); } -void process_op_code(int op) { +void process_op_code(byte op) { switch (op) { // CTRL IS_OP_CODE(BRK, 0x00) diff --git a/cpu/op.h b/cpu/op.h index 9a8a8bc..9ffe03c 100644 --- a/cpu/op.h +++ b/cpu/op.h @@ -1,3 +1,5 @@ +#include "../include/cpu.h" + #ifndef CPU_OP_H #define CPU_OP_H @@ -31,4 +33,6 @@ typedef enum { ADDR_MODE_ZERO_PAGE_INDEXED_Y, // d,y } AddressingMode; -#endif +void process_op_code(byte op); + +#endif \ No newline at end of file diff --git a/include/cpu.h b/include/cpu.h index 92468cb..7236bae 100644 --- a/include/cpu.h +++ b/include/cpu.h @@ -23,11 +23,7 @@ typedef unsigned char byte; typedef unsigned short address; typedef unsigned short word; -/** - * @brief Set clock - */ -void cpu_step_to(int cycle); - -void cpu_add_cycles(int count); +void cpu_init(); +void cpu_step(); #endif diff --git a/include/rom.h b/include/rom.h index 62f67d3..af5afca 100644 --- a/include/rom.h +++ b/include/rom.h @@ -5,12 +5,25 @@ #ifndef NESEMULATOR_ROM_H #define NESEMULATOR_ROM_H +// The size of the header in a ROM file, in bytes +#include "cpu.h" + +#define ROM_HEADER_SIZE 16 +// The size of the trainer in a ROM file, in bytes +#define ROM_TRAINER_SIZE 512 + typedef struct { - char* prg_rom; - char* chr_rom; - void* header; + byte *prg_rom; + byte *chr_rom; + void *header; } Rom; -int read_rom(char* path); +int rom_load(char *path); + +void rom_uninit(); + +byte rom_prg_get_byte(address addr); + +word rom_prg_get_word(address addr); #endif //NESEMULATOR_ROM_H \ No newline at end of file diff --git a/main.c b/main.c index b1059a9..00a111c 100644 --- a/main.c +++ b/main.c @@ -20,8 +20,14 @@ #include "include/rom.h" int main() { - char *rom_path = "../tests/cpu_exec_space/test_cpu_exec_space_ppuio.nes"; - read_rom(rom_path); + char *rom_path = "../tests/smb.nes"; + + cpu_init(); + rom_load(rom_path); + + cpu_step(); + + rom_uninit(); return EXIT_SUCCESS; } diff --git a/rom/ines.c b/rom/ines.c index 63eaf71..5828424 100644 --- a/rom/ines.c +++ b/rom/ines.c @@ -110,31 +110,60 @@ INesHeader read_header(const char header_buf[16]) { return header; } -bool rom_nes_read(const char header_buf[16], FILE *file, Rom *rom) { - INesHeader header = read_header(header_buf); - rom->header = &header; - - // We don't support the trainer, so we skip ahead by 512 bytes if needed. - if (header.flags.has_trainer && !fseek(file, 512, SEEK_CUR)) { - perror("Failed to seek ahead of trainer ROM section"); - return false; +bool rom_ines_read_trainer(FILE *file, INesHeader *header) { + if (!header->flags.has_trainer) { + log_debug("ROM does not contains trainer"); + return true; } - unsigned int prg_rom_size = header.prg_rom_size * 16384; + // We don't support the trainer, so we skip ahead instead. + if (fseek(file, ROM_TRAINER_SIZE, SEEK_CUR)) { + log_debug("ROM has trainer, skipping %d bytes", ROM_TRAINER_SIZE); + return true; + } + + log_error("Failed to skip trainer"); + return false; +} + +bool rom_ines_read_prg_rom(FILE *file, INesHeader *header, Rom *rom) { + unsigned int prg_rom_size = header->prg_rom_size * 16384; rom->prg_rom = (char *) malloc(prg_rom_size * sizeof(char)); - if (fread(rom->prg_rom, sizeof(char), prg_rom_size, file) < prg_rom_size) { - perror("Failed to read PRG ROM"); - return false; - } - if (header.chr_rom_size > 0) { - unsigned int chr_rom_size = header.chr_rom_size * 8192; - rom->chr_rom = (char *) malloc(chr_rom_size * sizeof(char)); - if (fread(rom->chr_rom, sizeof(char), chr_rom_size, file) < chr_rom_size) { - perror("Failed to read CHR ROM"); - return false; - } + log_debug("Reading %d bytes PRG ROM", prg_rom_size); + + if (fread(rom->prg_rom, sizeof(char), prg_rom_size, file) < prg_rom_size) { + log_error("Failed to read PRG ROM"); + return false; } return true; +} + +bool rom_ines_read_chr_rom(FILE *file, INesHeader *header, Rom *rom) { + if (header->chr_rom_size <= 0) { + log_debug("No CHR ROM to read"); + return true; + } + + unsigned int chr_rom_size = header->chr_rom_size * 8192; + rom->chr_rom = (char *) malloc(chr_rom_size * sizeof(char)); + + log_debug("Reading %d bytes CHR ROM", chr_rom_size); + + if (fread(rom->chr_rom, sizeof(char), chr_rom_size, file) < chr_rom_size) { + log_error("Failed to read CHR ROM"); + return false; + } + + return true; +} + +bool rom_ines_read(const char header_buf[ROM_HEADER_SIZE], FILE *file, Rom *rom) { + INesHeader header = read_header(header_buf); + rom->header = &header; + + return rom_ines_read_trainer(file, &header) && + rom_ines_read_prg_rom(file, &header, rom) && + rom_ines_read_chr_rom(file, &header, rom); } \ No newline at end of file diff --git a/rom/rom.c b/rom/rom.c index 82a29a2..50eab4f 100644 --- a/rom/rom.c +++ b/rom/rom.c @@ -4,51 +4,73 @@ #include #include +#include #include "../include/rom.h" #include "ines.c" #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) -void rom_init(Rom *rom) { - rom->header = NULL; - rom->prg_rom = NULL; - rom->chr_rom = NULL; +Rom rom; + +void rom_init() { + rom.header = NULL; + rom.prg_rom = NULL; + rom.chr_rom = NULL; } -void rom_uninit(Rom *rom) { - free(rom->prg_rom); - free(rom->chr_rom); -} +int rom_load(char *path) { + rom_init(); -int read_rom(char *path) { FILE *file = fopen(path, "r"); if (!file) { - perror("Failed to open ROM"); + log_error("Failed to open ROM"); return EXIT_FAILURE; } - char header_buffer[16] = {0}; + char header_buffer[ROM_HEADER_SIZE] = {0}; size_t read_size = fread(header_buffer, sizeof(char), ARRAY_SIZE(header_buffer), file); if (read_size < ARRAY_SIZE(header_buffer)) { - perror("Failed to read ROM"); + log_error("Failed to read ROM"); return EXIT_FAILURE; } if (!rom_is_ines(header_buffer)) { - perror("Only iNes ROMs are supported"); + log_error("Only iNes ROMs are supported"); return EXIT_FAILURE; } - Rom rom; - rom_init(&rom); - rom_nes_read(header_buffer, file, &rom); - rom_uninit(&rom); + log_info("Reading iNes 1.0 ROM at %s", path); + rom_ines_read(header_buffer, file, &rom); if (fclose(file) != 0) { - perror("Failed to close ROM file"); + log_error("Failed to close ROM file"); return EXIT_FAILURE; } return 0; +} + +void rom_uninit() { + assert(rom.prg_rom != NULL); + assert(rom.chr_rom != NULL); + + free(rom.prg_rom); + free(rom.chr_rom); + + log_info("Cleared ROM data"); +} + +byte rom_prg_get_byte(address addr) { + assert(rom.prg_rom != NULL); + + return rom.prg_rom[addr]; +} + +word rom_prg_get_word(address addr) { + assert(rom.prg_rom != NULL); + + word word = rom.prg_rom[addr]; + word += rom.prg_rom[addr + 1] << 8; // Little endian + return word; } \ No newline at end of file diff --git a/tests/smb.nes b/tests/smb.nes new file mode 100644 index 0000000000000000000000000000000000000000..4342b2eec67ed2497bd5b4392d4c40279921a48b GIT binary patch literal 40976 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≷Woja?()9P3JgKzg5j00M?0 z!Md=7Ed68_euMk-jaFu$l^ci! zF-@DjzeZZ$!6R%~cc|$F-BVA~!#Xpbdw!-l@IqUo7i+<796LofZ1pd^{(+c&z}ks^ zq;wUE-w)jA@L$V$dsQN;MbFi37u<(&unEzV;^P!`;*@n(D0g zP1_K|HA+%FTH<)a^rmCAX^rC?T|_U?Y@H*{`+TA@s}AJqx2?>ZBG%F+8&BM}?pv(h z&)gJu-xR0)Qn2fQHz~{N{pNz5GhJ|;b9)PnqP;iD{Zr`6pB?8Am?$lzGc%W+1OQKQFb8p$|cq<{B9+nQS$Kkjeg8FF8u`8B>X4em-ZKUx1|)!B>=grBt>3 z-R4KYixREvp!qSJBLx$hMeX{7h^Ja|(9E`BekiB1m|?C``{hCNdnll^avq7fw-u+` z+C&>hsS{-M05(fi9OvePRFGkzr8CTC?FwtNN}Ccv%6@1HFjF05HP& z@jRqEK7;=l2|#L5hyc~b9j;F!+uPk;Fp0ws(by03V(v^9-aYC9!(=i_#adju?n zF~($IfYiT4tsSm=Ok&(&th3oV+eyLWXRGAhEP{rq4ur9aFCW%vBage#80C$e(=Wit z2h@liqwV)KOd;AC-MFAgfU(^Tds_EoftaCD^sookLFe=79M$LfN=Pt8GyO(2dk-fx z-#nbrJP&uTH^1Ke*WuFRUmnkCeymyFY(DNiY(C!o-HUtg;pdKYf1f!*pXm3y

m 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%0DEkguRi*P9DR( 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