Browse Source

Emulator: Add cartridge ROM bank loading

master
Riyyi 2 years ago
parent
commit
81fe126068
  1. 11
      src/emu.cpp
  2. 2
      src/emu.h
  3. 42
      src/loader.cpp
  4. 2
      src/loader.h

11
src/emu.cpp

@ -12,6 +12,7 @@
#include "cpu.h" #include "cpu.h"
#include "emu.h" #include "emu.h"
#include "loader.h"
#include "ruc/format/log.h" #include "ruc/format/log.h"
#include "ruc/format/print.h" #include "ruc/format/print.h"
#include "ruc/meta/assert.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)); 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) void Emu::writeMemory(uint32_t address, uint32_t value)
{ {
for (auto& memory_space : m_memory_spaces) { for (auto& memory_space : m_memory_spaces) {
auto& memory = memory_space.second; 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 // Note: ECHO RAM hack
if (address >= 0xc000 && address <= 0xddff) { if (address >= 0xc000 && address <= 0xddff) {
writeMemory(address + (0xe000 - 0xc000), value); writeMemory(address + (0xe000 - 0xc000), value);

2
src/emu.h

@ -36,6 +36,7 @@ public:
void addProcessingUnit(std::string_view name, ProcessingUnit* processing_unit); 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 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); void writeMemory(uint32_t address, uint32_t value);
uint32_t readMemory(uint32_t address) const; 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); } 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: private:
uint32_t m_frequency { 0 }; uint32_t m_frequency { 0 };

42
src/loader.cpp

@ -5,6 +5,7 @@
*/ */
#include <cstddef> // size_t #include <cstddef> // size_t
#include <cstdint> // uint32_t
#include "cpu.h" #include "cpu.h"
#include "emu.h" #include "emu.h"
@ -22,6 +23,19 @@ void Loader::loadRom(std::string_view rom_path)
init(); 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() void Loader::init()
@ -41,8 +55,9 @@ void Loader::init()
Emu::the().addMemorySpace("BOOTROM1", 0x0000, 0x00ff); // 256B Emu::the().addMemorySpace("BOOTROM1", 0x0000, 0x00ff); // 256B
loadCartridgeHeader(); 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("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("WRAM1", 0xc000, 0xcfff); // 4 KiB, Work RAM
Emu::the().addMemorySpace("WRAM2", 0xd000, 0xdfff, 7); // 4 KiB * 7 banks, 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 Emu::the().addMemorySpace("ECHORAM", 0xe000, 0xfdff); // 7680B, Mirror of 0xc000~0xddff
@ -84,9 +99,30 @@ void Loader::loadCartridgeHeader()
return; 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]); 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;
}

2
src/loader.h

@ -16,6 +16,7 @@ public:
Loader(s) {} Loader(s) {}
void loadRom(std::string_view rom_path); void loadRom(std::string_view rom_path);
void disableBootrom();
void setBootromPath(std::string_view bootrom_path) { m_bootrom_path = bootrom_path; } void setBootromPath(std::string_view bootrom_path) { m_bootrom_path = bootrom_path; }
@ -25,6 +26,7 @@ private:
void destroy(); void destroy();
void loadCartridgeHeader(); void loadCartridgeHeader();
void loadCartridgeBanks();
std::string_view m_bootrom_path; std::string_view m_bootrom_path;
std::string m_rom_data; std::string m_rom_data;

Loading…
Cancel
Save