openMSX
MSXMemoryMapperBase.cc
Go to the documentation of this file.
2#include "MSXException.hh"
3#include "outer.hh"
4#include "ranges.hh"
5#include "serialize.hh"
6#include <bit>
7
8namespace openmsx {
9
10[[nodiscard]] static unsigned getRamSize(const DeviceConfig& config)
11{
12 int kSize = config.getChildDataAsInt("size", 0);
13 if ((kSize % 16) != 0) {
14 throw MSXException("Mapper size is not a multiple of 16K: ", kSize);
15 }
16 if (kSize <= 0) {
17 throw MSXException("Mapper size must be at least 16kB: ", kSize);
18 }
19 if (kSize > 4096) {
20 throw MSXException("Mapper size must not be larger than 4096kB: ", kSize);
21 }
22 return kSize * 1024; // in bytes
23}
24
26 : MSXDevice(config)
27 , MSXMapperIOClient(getMotherBoard())
28 , checkedRam(config, getName(), "memory mapper", getRamSize(config))
29 , debuggable(getMotherBoard(), getName())
30{
31}
32
34{
35 return 0x4000;
36}
37
38void MSXMemoryMapperBase::powerUp(EmuTime::param time)
39{
41 reset(time);
42}
43
44void MSXMemoryMapperBase::reset(EmuTime::param /*time*/)
45{
46 // Most mappers initialize to segment 0 for all pages.
47 // On MSX2 and higher, the BIOS will select segments 3..0 for pages 0..3.
49}
50
51byte MSXMemoryMapperBase::readIO(word port, EmuTime::param time)
52{
53 return peekIO(port, time);
54}
55
56byte MSXMemoryMapperBase::peekIO(word port, EmuTime::param /*time*/) const
57{
58 auto numSegments = narrow<unsigned>(checkedRam.size() / 0x4000);
59 return registers[port & 0x03] | byte(~(std::bit_ceil(numSegments) - 1));
60}
61
62void MSXMemoryMapperBase::writeIOImpl(word port, byte value, EmuTime::param /*time*/)
63{
64 auto numSegments = narrow<unsigned>(checkedRam.size() / 0x4000);
65 registers[port & 3] = value & byte(std::bit_ceil(numSegments) - 1);
66 // Note: subclasses are responsible for handling CPU cacheline stuff
67}
68
69unsigned MSXMemoryMapperBase::segmentOffset(byte page) const
70{
71 unsigned segment = registers[page];
72 auto numSegments = narrow<unsigned>(checkedRam.size() / 0x4000);
73 segment = (segment < numSegments) ? segment : segment & (numSegments - 1);
74 return segment * 0x4000;
75}
76
78{
79 return segmentOffset(narrow<byte>(address / 0x4000)) | (address & 0x3fff);
80}
81
82byte MSXMemoryMapperBase::peekMem(word address, EmuTime::param /*time*/) const
83{
84 return checkedRam.peek(calcAddress(address));
85}
86
87byte MSXMemoryMapperBase::readMem(word address, EmuTime::param /*time*/)
88{
89 return checkedRam.read(calcAddress(address));
90}
91
92void MSXMemoryMapperBase::writeMem(word address, byte value, EmuTime::param /*time*/)
93{
94 checkedRam.write(calcAddress(address), value);
95}
96
98{
100}
101
106
107
108// SimpleDebuggable
109
111 const std::string& name_)
112 : SimpleDebuggable(motherBoard_, name_ + " regs",
113 "Memory mapper registers", 4)
114{
115}
116
117byte MSXMemoryMapperBase::Debuggable::read(unsigned address)
118{
119 auto& mapper = OUTER(MSXMemoryMapperBase, debuggable);
120 return mapper.registers[address];
121}
122
123void MSXMemoryMapperBase::Debuggable::write(unsigned address, byte value)
124{
125 auto& mapper = OUTER(MSXMemoryMapperBase, debuggable);
126 mapper.writeIO(narrow<word>(address), value, EmuTime::dummy());
127}
128
129
130template<typename Archive>
131void MSXMemoryMapperBase::serialize(Archive& ar, unsigned version)
132{
133 ar.template serializeBase<MSXDevice>(*this);
134 if (ar.versionAtLeast(version, 2)) {
135 ar.serialize("registers", registers);
136 }
137 // TODO ar.serialize("checkedRam", checkedRam);
138 ar.serialize("ram", checkedRam.getUncheckedRam());
139}
141//REGISTER_MSXDEVICE(MSXMemoryMapperBase, "MemoryMapper");
142
143} // namespace openmsx
Ram & getUncheckedRam()
Give access to the unchecked Ram.
Definition CheckedRam.hh:51
size_t size() const
Definition CheckedRam.hh:42
byte * getWriteCacheLine(size_t addr) const
Definition CheckedRam.cc:45
void write(size_t addr, byte value)
Definition CheckedRam.cc:64
byte peek(size_t addr) const
Definition CheckedRam.hh:35
const byte * getReadCacheLine(size_t addr) const
Definition CheckedRam.cc:39
byte read(size_t addr)
Definition CheckedRam.cc:28
An MSXDevice is an emulated hardware component connected to the bus of the emulated MSX.
Definition MSXDevice.hh:36
byte readMem(word address, EmuTime::param time) override
Read a byte from a location at a certain time from this device.
unsigned calcAddress(word address) const
Converts a Z80 address to a RAM address.
void writeIOImpl(word port, byte value, EmuTime::param time)
byte peekMem(word address, EmuTime::param time) const override
Read a byte from a given memory location.
MSXMemoryMapperBase(const DeviceConfig &config)
void powerUp(EmuTime::param time) override
This method is called when MSX is powered up.
unsigned getBaseSizeAlignment() const override
The 'base' and 'size' attribute values need to be at least aligned to CacheLine::SIZE.
void serialize(Archive &ar, unsigned version)
void writeMem(word address, byte value, EmuTime::param time) override
Write a given byte to a given location at a certain time to this device.
const byte * getReadCacheLine(word start) const override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for reading.
byte * getWriteCacheLine(word start) const override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for writing.
byte readIO(word port, EmuTime::param time) override
Read a byte from an IO port at a certain time from this device.
byte peekIO(word port, EmuTime::param time) const override
Read a byte from a given IO port.
unsigned segmentOffset(byte page) const
void reset(EmuTime::param time) override
This method is called on reset.
This file implemented 3 utility functions:
Definition Autofire.cc:9
uint8_t byte
8 bit unsigned integer
Definition openmsx.hh:26
uint16_t word
16 bit unsigned integer
Definition openmsx.hh:29
constexpr void fill(ForwardRange &&range, const T &value)
Definition ranges.hh:305
#define OUTER(type, member)
Definition outer.hh:41
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)