openMSX
MSXMemoryMapper.cc
Go to the documentation of this file.
1 #include "MSXMemoryMapper.hh"
2 #include "MSXException.hh"
3 #include "Math.hh"
4 #include "outer.hh"
5 #include "ranges.hh"
6 #include "serialize.hh"
7 
8 namespace openmsx {
9 
10 unsigned MSXMemoryMapper::getRamSize() const
11 {
12  int kSize = getDeviceConfig().getChildDataAsInt("size");
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.");
18  }
19  return kSize * 1024; // in bytes
20 }
21 
23  : MSXDevice(config)
25  , checkedRam(config, getName(), "memory mapper", getRamSize())
26  , debuggable(getMotherBoard(), getName())
27 {
28 }
29 
31 
32 void MSXMemoryMapper::powerUp(EmuTime::param time)
33 {
34  checkedRam.clear();
35  reset(time);
36 }
37 
38 void MSXMemoryMapper::reset(EmuTime::param /*time*/)
39 {
40  // Most mappers initialize to segment 0 for all pages.
41  // On MSX2 and higher, the BIOS will select segments 3..0 for pages 0..3.
43 }
44 
45 byte MSXMemoryMapper::readIO(word port, EmuTime::param time)
46 {
47  return peekIO(port, time);
48 }
49 
50 byte MSXMemoryMapper::peekIO(word port, EmuTime::param /*time*/) const
51 {
52  unsigned numSegments = checkedRam.getSize() / 0x4000;
53  return registers[port & 0x03] | ~(Math::ceil2(numSegments) - 1);
54 }
55 
56 void MSXMemoryMapper::writeIO(word port, byte value, EmuTime::param /*time*/)
57 {
58  unsigned numSegments = checkedRam.getSize() / 0x4000;
59  registers[port & 0x03] = value & (Math::ceil2(numSegments) - 1);
60 }
61 
62 unsigned MSXMemoryMapper::calcAddress(word address) const
63 {
64  unsigned segment = registers[address >> 14];
65  unsigned numSegments = checkedRam.getSize() / 0x4000;
66  segment = (segment < numSegments) ? segment : segment & (numSegments - 1);
67  return (segment << 14) | (address & 0x3FFF);
68 }
69 
70 byte MSXMemoryMapper::peekMem(word address, EmuTime::param /*time*/) const
71 {
72  return checkedRam.peek(calcAddress(address));
73 }
74 
75 byte MSXMemoryMapper::readMem(word address, EmuTime::param /*time*/)
76 {
77  return checkedRam.read(calcAddress(address));
78 }
79 
80 void MSXMemoryMapper::writeMem(word address, byte value, EmuTime::param /*time*/)
81 {
82  checkedRam.write(calcAddress(address), value);
83 }
84 
86 {
88 }
89 
91 {
93 }
94 
95 
96 // SimpleDebuggable
97 
98 MSXMemoryMapper::Debuggable::Debuggable(MSXMotherBoard& motherBoard_,
99  const std::string& name_)
100  : SimpleDebuggable(motherBoard_, name_ + " regs",
101  "Memory mapper registers", 4)
102 {
103 }
104 
105 byte MSXMemoryMapper::Debuggable::read(unsigned address)
106 {
107  auto& mapper = OUTER(MSXMemoryMapper, debuggable);
108  return mapper.registers[address];
109 }
110 
111 void MSXMemoryMapper::Debuggable::write(unsigned address, byte value)
112 {
113  auto& mapper = OUTER(MSXMemoryMapper, debuggable);
114  mapper.writeIO(address, value, EmuTime::dummy());
115 }
116 
117 
118 template<typename Archive>
119 void MSXMemoryMapper::serialize(Archive& ar, unsigned version)
120 {
121  ar.template serializeBase<MSXDevice>(*this);
122  if (ar.versionAtLeast(version, 2)) {
123  ar.serialize("registers", registers);
124  }
125  // TODO ar.serialize("checkedRam", checkedRam);
126  ar.serialize("ram", checkedRam.getUncheckedRam());
127 }
129 REGISTER_MSXDEVICE(MSXMemoryMapper, "MemoryMapper");
130 
131 } // namespace openmsx
void powerUp(EmuTime::param time) override
This method is called when MSX is powered up.
MSXMemoryMapper(const DeviceConfig &config)
const byte * getReadCacheLine(unsigned addr) const
Definition: CheckedRam.cc:47
uint8_t byte
8 bit unsigned integer
Definition: openmsx.hh:26
unsigned getSize() const
Definition: CheckedRam.hh:41
virtual std::string getName() const
Returns a human-readable name for this device.
Definition: MSXDevice.cc:374
byte readMem(word address, EmuTime::param time) override
Read a byte from a location at a certain time from this device.
void writeIO(word port, byte value, EmuTime::param time) override
Write a byte to a given IO port at a certain time to this device.
REGISTER_MSXDEVICE(ChakkariCopy, "ChakkariCopy")
void fill(ForwardRange &&range, const T &value)
Definition: ranges.hh:191
void reset(EmuTime::param time) override
This method is called on reset.
const byte * getReadCacheLine(word start) const override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for reading...
Ram & getUncheckedRam()
Give access to the unchecked Ram.
Definition: CheckedRam.hh:50
void write(unsigned addr, byte value)
Definition: CheckedRam.cc:59
virtual ~MSXMemoryMapper() override
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
An MSXDevice is an emulated hardware component connected to the bus of the emulated MSX...
Definition: MSXDevice.hh:31
MSXMotherBoard & getMotherBoard() const
Get the mother board this device belongs to.
Definition: MSXDevice.cc:77
byte peek(unsigned addr) const
Definition: CheckedRam.hh:35
uint16_t word
16 bit unsigned integer
Definition: openmsx.hh:29
byte read(unsigned addr)
Definition: CheckedRam.cc:36
int getChildDataAsInt(string_view name, int defaultValue=0) const
Definition: XMLElement.cc:187
byte * getWriteCacheLine(word start) const override
Test that the memory in the interval [start, start + CacheLine::SIZE) is cacheable for writing...
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
Definition: serialize.hh:1006
void serialize(Archive &ar, unsigned version)
byte peekIO(word port, EmuTime::param time) const override
Read a byte from a given IO port.
byte readIO(word port, EmuTime::param time) override
Read a byte from an IO port at a certain time from this device.
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.
byte peekMem(word address, EmuTime::param time) const override
Read a byte from a given memory location.
constexpr T ceil2(T x) noexcept
Returns the smallest number that is both >=a and a power of two.
Definition: Math.hh:84
const XMLElement & getDeviceConfig() const
Get the configuration section for this device.
Definition: MSXDevice.hh:218
#define OUTER(type, member)
Definition: outer.hh:38
unsigned calcAddress(word address) const
Converts a Z80 address to a RAM address.
byte * getWriteCacheLine(unsigned addr) const
Definition: CheckedRam.cc:53