Add an "UnusedMemory" class to better allow "gaps" in the memory map.

Signed-off-by: Adrian Conlon <Adrian.conlon@gmail.com>
This commit is contained in:
Adrian Conlon 2018-11-03 23:11:48 +00:00
parent 984626a331
commit 9132f2028f
9 changed files with 87 additions and 31 deletions

View File

@ -7,6 +7,7 @@
#include <Ram.h>
#include <Bus.h>
#include <Register.h>
#include <UnusedMemory.h>
#include "LR35902.h"
#include "IoRegisters.h"
@ -59,16 +60,16 @@ namespace EightBit {
private:
LR35902 m_cpu;
Rom m_bootRom = 0x100; // 0x0000 - 0x00ff
std::vector<Rom> m_gameRomBanks; // 0x0000 - 0x3fff, 0x4000 - 0x7fff (switchable)
Ram m_videoRam = 0x2000; // 0x8000 - 0x9fff
std::vector<Ram> m_ramBanks; // 0xa000 - 0xbfff (switchable)
Rom m_unmapped2000 = 0x2000; // 0xa000 - 0xbfff
Ram m_lowInternalRam = 0x2000; // 0xc000 - 0xdfff (mirrored at 0xe000)
Ram m_oamRam = 0xa0; // 0xfe00 - 0xfe9f
Rom m_unmapped60 = 0x60; // 0xfea0 - 0xfeff
IoRegisters m_ioPorts; // 0xff00 - 0xff7f
Ram m_highInternalRam = 0x80; // 0xff80 - 0xffff
Rom m_bootRom = 0x100; // 0x0000 - 0x00ff
std::vector<Rom> m_gameRomBanks; // 0x0000 - 0x3fff, 0x4000 - 0x7fff (switchable)
Ram m_videoRam = 0x2000; // 0x8000 - 0x9fff
std::vector<Ram> m_ramBanks; // 0xa000 - 0xbfff (switchable)
UnusedMemory m_unmapped2000 = { 0x2000, 0xff }; // 0xa000 - 0xbfff
Ram m_lowInternalRam = 0x2000; // 0xc000 - 0xdfff (mirrored at 0xe000)
Ram m_oamRam = 0xa0; // 0xfe00 - 0xfe9f
UnusedMemory m_unmapped60 = { 0x60, 0xff }; // 0xfea0 - 0xfeff
IoRegisters m_ioPorts; // 0xff00 - 0xff7f
Ram m_highInternalRam = 0x80; // 0xff80 - 0xffff
bool m_enabledLCD = false;

View File

@ -6,18 +6,6 @@ EightBit::GameBoy::Bus::Bus() noexcept
: m_cpu(*this),
m_ioPorts(*this) {
WrittenByte.connect(std::bind(&GameBoy::Bus::Bus_WrittenByte, this, std::placeholders::_1));
{
std::vector<uint8_t> content(m_unmapped2000.size());
std::fill(content.begin(), content.end(), 0xff);
m_unmapped2000.load(content);
}
{
std::vector<uint8_t> content(m_unmapped60.size());
std::fill(content.begin(), content.end(), 0xff);
m_unmapped60.load(content);
}
}
void EightBit::GameBoy::Bus::reset() {

View File

@ -5,9 +5,6 @@ Board::Board(const Configuration& configuration)
: m_configuration(configuration),
m_cpu(EightBit::mc6809(*this)),
m_disassembler(*this, m_cpu) {
std::vector<uint8_t> content(m_unused2000.size());
std::fill(content.begin(), content.end(), 0xff);
m_unused2000.load(content);
}
void Board::initialise() {

View File

@ -9,6 +9,7 @@
#include <mc6809.h>
#include <Disassembly.h>
#include <MC6850.h>
#include <UnusedMemory.h>
class Board : public EightBit::Bus {
public:
@ -24,10 +25,10 @@ protected:
private:
const Configuration& m_configuration;
EightBit::Ram m_ram = 0x8000; // 0000 - 7FFF, 32K RAM
EightBit::Rom m_unused2000 = 0x2000; // 8000 - 9FFF, 8K unused
EightBit::Ram m_io = 0x2000; // A000 - BFFF, 8K serial interface, minimally decoded
EightBit::Rom m_rom = 0x4000; // C000 - FFFF, 16K ROM
EightBit::Ram m_ram = 0x8000; // 0000 - 7FFF, 32K RAM
EightBit::UnusedMemory m_unused2000 = { 0x2000, 0xff }; // 8000 - 9FFF, 8K unused
EightBit::Ram m_io = 0x2000; // A000 - BFFF, 8K serial interface, minimally decoded
EightBit::Rom m_rom = 0x4000; // C000 - FFFF, 16K ROM
EightBit::mc6850 m_acia;

26
inc/MemoryInterface.h Normal file
View File

@ -0,0 +1,26 @@
#pragma once
#include <cstdint>
#include <fstream>
#include <stdexcept>
#include <string>
#include <vector>
namespace EightBit {
class MemoryInterface {
public:
virtual size_t size() const = 0;
virtual uint8_t peek(uint16_t address) const = 0;
virtual uint8_t& reference(uint16_t) {
throw new std::logic_error("Reference operation not allowed.");
}
virtual int load(std::ifstream& file, int writeOffset = 0, int readOffset = 0, int limit = -1) = 0;
virtual int load(const std::string& path, int writeOffset = 0, int readOffset = 0, int limit = -1) = 0;
virtual int load(const std::vector<uint8_t>& bytes, int writeOffset = 0, int readOffset = 0, int limit = -1) = 0;
protected:
virtual void poke(uint16_t address, uint8_t value) = 0;
};
}

40
inc/UnusedMemory.h Normal file
View File

@ -0,0 +1,40 @@
#pragma once
#include "MemoryInterface.h"
namespace EightBit {
class UnusedMemory final : public MemoryInterface {
public:
UnusedMemory(const size_t size, const uint8_t value)
: m_size(size), m_value(value) {}
virtual ~UnusedMemory() = default;
virtual size_t size() const final { return m_size; }
virtual uint8_t peek(uint16_t address) const final { return m_value; }
virtual uint8_t& reference(uint16_t) {
throw new std::logic_error("Reference operation not allowed.");
}
virtual int load(std::ifstream& file, int writeOffset = 0, int readOffset = 0, int limit = -1) final {
throw new std::logic_error("load operation not allowed.");
}
virtual int load(const std::string& path, int writeOffset = 0, int readOffset = 0, int limit = -1) final {
throw new std::logic_error("load operation not allowed.");
}
virtual int load(const std::vector<uint8_t>& bytes, int writeOffset = 0, int readOffset = 0, int limit = -1) final {
throw new std::logic_error("load operation not allowed.");
}
protected:
virtual void poke(uint16_t address, uint8_t value) {
throw new std::logic_error("Poke operation not allowed.");
}
private:
size_t m_size;
uint8_t m_value;
};
}

View File

@ -93,6 +93,5 @@ uint8_t& EightBit::Bus::reference(const uint16_t address) {
const uint16_t offset = (address - mapped.begin) & mapped.mask;
if (mapped.access == MemoryMapping::ReadOnly)
return DATA() = mapped.memory.peek(offset);
Ram& ram = (Ram&)(mapped.memory);
return ram.reference(offset);
return mapped.memory.reference(offset);
}

View File

@ -156,6 +156,7 @@
<ClInclude Include="..\inc\Register.h" />
<ClInclude Include="..\inc\Signal.h" />
<ClInclude Include="..\inc\TestHarness.h" />
<ClInclude Include="..\inc\UnusedMemory.h" />
<ClInclude Include="stdafx.h" />
</ItemGroup>
<ItemGroup>

View File

@ -62,6 +62,9 @@
<ClInclude Include="..\inc\MemoryInterface.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\inc\UnusedMemory.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp">