Emulator: Add cartridge ROM bank loading
This commit is contained in:
+10
-1
@@ -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);
|
||||||
|
|||||||
@@ -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 };
|
||||||
|
|||||||
+39
-3
@@ -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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user