From abb9b2e54a34e1c94bc75a3f074122eb3f4380c5 Mon Sep 17 00:00:00 2001 From: Lauchmelder Date: Wed, 20 Oct 2021 23:11:08 +0200 Subject: [PATCH] added cartridge loading --- NES Emulator/CMakeLists.txt | 10 ++++++- NES Emulator/bus.c | 8 ++++-- NES Emulator/cartridge.c | 53 ++++++++++++++++++++++++++++++++++-- NES Emulator/cartridge.h | 3 +- roms/nestest.nes | Bin 0 -> 24592 bytes 5 files changed, 68 insertions(+), 6 deletions(-) create mode 100644 roms/nestest.nes diff --git a/NES Emulator/CMakeLists.txt b/NES Emulator/CMakeLists.txt index 257ec8b..3caca6e 100644 --- a/NES Emulator/CMakeLists.txt +++ b/NES Emulator/CMakeLists.txt @@ -1,3 +1,11 @@ cmake_minimum_required (VERSION 3.8) -add_executable (CMakeTarget "main.c" "cpu.h" "types.h" "bus.h" "bus.c" "cartridge.h" "cpu.c" "cartridge.c") +add_executable (nesemu "main.c" "cpu.h" "types.h" "bus.h" "bus.c" "cartridge.h" "cpu.c" "cartridge.c") + +if(MSVC) +target_compile_definitions(nesemu PUBLIC _CRT_SECURE_NO_WARNINGS) +endif() + +add_custom_command(TARGET nesemu POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/roms $/roms +) \ No newline at end of file diff --git a/NES Emulator/bus.c b/NES Emulator/bus.c index 9410ed8..9530767 100644 --- a/NES Emulator/bus.c +++ b/NES Emulator/bus.c @@ -26,7 +26,7 @@ struct Bus* createBus() bus->cpu = createCPU(bus); // Create and insert cartridge - bus->cartridge = createCartridge(bus, "nestest.nes"); + bus->cartridge = createCartridge(bus, "roms/nestest.nes"); return bus; } @@ -42,10 +42,12 @@ void destroyBus(struct Bus* bus) Byte Read(struct Bus* bus, Word addr) { + Byte val = 0; + // Return from the appropriate device depending on the address if (addr <= 0x1FFF) // RAM (or one of the mirrored addresses) { - return bus->ram[addr & 0x7FF]; + val = bus->ram[addr & 0x7FF]; } else if (0x4020 <= addr && addr <= 0xFFFF) // Cartridge space { @@ -56,6 +58,8 @@ Byte Read(struct Bus* bus, Word addr) fprintf(stderr, "Access violation at $%x", addr); exit(1); } + + return val; } void Write(struct Bus* bus, Word addr, Byte val) diff --git a/NES Emulator/cartridge.c b/NES Emulator/cartridge.c index df37464..3b8b105 100644 --- a/NES Emulator/cartridge.c +++ b/NES Emulator/cartridge.c @@ -4,6 +4,33 @@ #include "bus.h" +struct INES_Header +{ + Byte nestext[4]; + Byte prg_rom_size; + Byte chr_rom_size; + + struct + { + Byte mirror : 1; + Byte battery : 1; + Byte trainer : 1; + Byte ignore_mirror : 1; + Byte mapper_lower_nibble : 4; + } Flags6; + + struct + { + Byte vs : 1; + Byte playchoice : 1; + Byte nes20 : 2; + Byte mapper_upper_nibble : 4; + } Flags7; + + Byte prg_ram_size; + Byte unused[7]; +}; + struct Cartridge* createCartridge(struct Bus* parent, const char* filepath) { struct Cartridge* cartridge = (struct Cartridge*)malloc(sizeof(struct Cartridge)); @@ -13,13 +40,35 @@ struct Cartridge* createCartridge(struct Bus* parent, const char* filepath) exit(1); } - cartridge->memory = NULL; + // Open ROM + FILE* fp = fopen(filepath, "rb"); + + // Read header + struct INES_Header header; + fread(&header, sizeof(header), 1, fp); + + cartridge->prg_rom = (Byte*)malloc(0x4000 * (size_t)header.prg_rom_size); + if (cartridge->prg_rom == NULL) + { + fprintf(stderr, "Failed to allocate PRG memory for cartridge, aborting.\n"); + exit(1); + } + + cartridge->chr_rom = (Byte*)malloc(0x2000 * (size_t)header.chr_rom_size); + if (cartridge->prg_rom == NULL) + { + fprintf(stderr, "Failed to allocate CHR memory for cartridge, aborting.\n"); + exit(1); + } + cartridge->bus = parent; return cartridge; } void destroyCartridge(struct Cartridge* cartridge) { - // free(cartridge->memory); + free(cartridge->chr_rom); + free(cartridge->prg_rom); + free(cartridge); } diff --git a/NES Emulator/cartridge.h b/NES Emulator/cartridge.h index fb9dc64..6bdcf37 100644 --- a/NES Emulator/cartridge.h +++ b/NES Emulator/cartridge.h @@ -7,7 +7,8 @@ struct Bus; struct Cartridge { - Byte* memory; + Byte* prg_rom; + Byte* chr_rom; struct Bus* bus; }; diff --git a/roms/nestest.nes b/roms/nestest.nes new file mode 100644 index 0000000000000000000000000000000000000000..fc2a88c36db9c5c2de9cca33be0e446e12007f17 GIT binary patch literal 24592 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 O2L?Sb=z;&AJn-*m;2p96 literal 0 HcmV?d00001