Emulator: Add cartridge ROM bank loading
This commit is contained in:
+10
-1
@@ -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);
|
||||
|
||||
@@ -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 };
|
||||
|
||||
+39
-3
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
#include <cstddef> // size_t
|
||||
#include <cstdint> // 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()
|
||||
@@ -41,8 +55,9 @@ void Loader::init()
|
||||
Emu::the().addMemorySpace("BOOTROM1", 0x0000, 0x00ff); // 256B
|
||||
loadCartridgeHeader();
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user