From 81fe126068202d9438b79730d3d42a0a62ac6b59 Mon Sep 17 00:00:00 2001 From: Riyyi Date: Fri, 26 Aug 2022 07:22:44 +0200 Subject: [PATCH] Emulator: Add cartridge ROM bank loading --- src/emu.cpp | 11 ++++++++++- src/emu.h | 2 ++ src/loader.cpp | 44 ++++++++++++++++++++++++++++++++++++++++---- src/loader.h | 2 ++ 4 files changed, 54 insertions(+), 5 deletions(-) diff --git a/src/emu.cpp b/src/emu.cpp index d646bac..db40a8e 100644 --- a/src/emu.cpp +++ b/src/emu.cpp @@ -12,6 +12,7 @@ #include "cpu.h" #include "emu.h" +#include "loader.h" #include "ruc/format/log.h" #include "ruc/format/print.h" #include "ruc/meta/assert.h" @@ -56,11 +57,19 @@ void Emu::addMemorySpace(std::string_view name, uint32_t start_address, uint32_t m_memory_spaces.emplace(name, std::move(memory_space)); } +void Emu::removeMemorySpace(std::string_view name) +{ + m_memory_spaces.erase(name); +} + void Emu::writeMemory(uint32_t address, uint32_t value) { for (auto& memory_space : m_memory_spaces) { auto& memory = memory_space.second; - if (address >= memory.start_address && address <= memory.end_address) { + if (address == 0xff50) { + Loader::the().disableBootrom(); + } + else if (address >= memory.start_address && address <= memory.end_address) { // Note: ECHO RAM hack if (address >= 0xc000 && address <= 0xddff) { writeMemory(address + (0xe000 - 0xc000), value); diff --git a/src/emu.h b/src/emu.h index 5a5f5d4..e78530e 100644 --- a/src/emu.h +++ b/src/emu.h @@ -36,6 +36,7 @@ public: void addProcessingUnit(std::string_view name, ProcessingUnit* processing_unit); void addMemorySpace(std::string_view name, uint32_t start_address, uint32_t end_address, uint32_t amount_of_banks = 1); + void removeMemorySpace(std::string_view name); void writeMemory(uint32_t address, uint32_t value); uint32_t readMemory(uint32_t address) const; @@ -43,6 +44,7 @@ public: // ------------------------------------- ProcessingUnit* processingUnit(std::string_view name) const { return m_processing_units.at(name); } + MemorySpace memorySpace(std::string_view name) { return m_memory_spaces[name]; } private: uint32_t m_frequency { 0 }; diff --git a/src/loader.cpp b/src/loader.cpp index 6dfd322..5790362 100644 --- a/src/loader.cpp +++ b/src/loader.cpp @@ -5,6 +5,7 @@ */ #include // size_t +#include // uint32_t #include "cpu.h" #include "emu.h" @@ -22,6 +23,19 @@ void Loader::loadRom(std::string_view rom_path) init(); } +void Loader::disableBootrom() +{ + Emu::the().removeMemorySpace("BOOTROM1"); + Emu::the().removeMemorySpace("CARTHEADER"); + Emu::the().removeMemorySpace("BOOTROM2"); + + // Load cartridge bank 0 + Emu::the().addMemorySpace("CARTROM1", 0x0000, 0x3fff); // 16KiB + for (size_t i = 0x0000; i <= 0x3fff; ++i) { + Emu::the().writeMemory(i, m_rom_data[i]); + } +} + // ----------------------------------------- void Loader::init() @@ -40,9 +54,10 @@ void Loader::init() // https://gbdev.io/pandocs/Power_Up_Sequence.html Emu::the().addMemorySpace("BOOTROM1", 0x0000, 0x00ff); // 256B loadCartridgeHeader(); - Emu::the().addMemorySpace("BOOTROM2", 0x0200, 0x08ff); // 1792B + Emu::the().addMemorySpace("BOOTROM2", 0x0200, 0x08ff); // 1792B + loadCartridgeBanks(); Emu::the().addMemorySpace("VRAM", 0x8000, 0x9fff, 2); // 8KiB * 2 banks - Emu::the().addMemorySpace("CARDRAM", 0xa000, 0xbfff, 1); // 8KiB * ? banks, if any + Emu::the().addMemorySpace("CARTRAM", 0xa000, 0xbfff, 1); // 8KiB * ? banks, if any Emu::the().addMemorySpace("WRAM1", 0xc000, 0xcfff); // 4 KiB, Work RAM Emu::the().addMemorySpace("WRAM2", 0xd000, 0xdfff, 7); // 4 KiB * 7 banks, Work RAM Emu::the().addMemorySpace("ECHORAM", 0xe000, 0xfdff); // 7680B, Mirror of 0xc000~0xddff @@ -84,9 +99,30 @@ void Loader::loadCartridgeHeader() return; } - Emu::the().addMemorySpace("CARTHEADER", 0x100, 0x14f); + Emu::the().addMemorySpace("CARTHEADER", 0x100, 0x14f); // 80B - for (size_t i = 0x100; i <= 0x14f; ++i) { + for (size_t i = 0x0100; i <= 0x014f; ++i) { Emu::the().writeMemory(i, m_rom_data[i]); } } + +void Loader::loadCartridgeBanks() +{ + if (m_rom_data.empty()) { + return; + } + + uint32_t rom_size = 32 * 1024 * (1 << m_rom_data[0x0148]); + uint32_t rom_banks = rom_size / (16 * 1024) - 1; + Emu::the().addMemorySpace("CARTROM2", 0x4000, 0x7fff, rom_banks); // 16KiB * banks + + // Load cartridge bank 1~NN + auto rom_memory_spaces = Emu::the().memorySpace("CARTROM2"); + for (size_t i = 0; i < rom_banks; ++i) { + for (size_t i = 0x4000; i <= 0x7fff; ++i) { + Emu::the().writeMemory(i, m_rom_data[i]); + } + rom_memory_spaces.active_bank += 1; + } + rom_memory_spaces.active_bank = 0; +} diff --git a/src/loader.h b/src/loader.h index 842337b..5200a7d 100644 --- a/src/loader.h +++ b/src/loader.h @@ -16,6 +16,7 @@ public: Loader(s) {} void loadRom(std::string_view rom_path); + void disableBootrom(); void setBootromPath(std::string_view bootrom_path) { m_bootrom_path = bootrom_path; } @@ -25,6 +26,7 @@ private: void destroy(); void loadCartridgeHeader(); + void loadCartridgeBanks(); std::string_view m_bootrom_path; std::string m_rom_data;