openMSX
MSXMapperIO.cc
Go to the documentation of this file.
1 #include "MSXMapperIO.hh"
2 #include "MSXMotherBoard.hh"
3 #include "SimpleDebuggable.hh"
4 #include "HardwareConfig.hh"
5 #include "XMLElement.hh"
6 #include "MSXException.hh"
7 #include "Math.hh"
8 #include "serialize.hh"
9 #include "memory.hh"
10 
11 using std::string;
12 
13 namespace openmsx {
14 
16 {
17 public:
18  MapperIODebuggable(MSXMotherBoard& motherBoard, MSXMapperIO& mapperIO);
19  virtual byte read(unsigned address);
20  virtual void write(unsigned address, byte value);
21 private:
22  MSXMapperIO& mapperIO;
23 };
24 
25 
26 static byte calcEngineMask(MSXMotherBoard& motherBoard)
27 {
28  string_ref type = motherBoard.getMachineConfig()->getConfig().getChildData(
29  "MapperReadBackBits", "largest");
30  if (type == "5") {
31  return 0xE0; // upper 3 bits always read "1"
32  } else if (type == "largest") {
33  return 0x00; // all bits can be read
34  } else {
35  throw FatalError("Unknown mapper type: \"" + type + "\".");
36  }
37 }
38 
40  : MSXDevice(config)
41  , debuggable(make_unique<MapperIODebuggable>(getMotherBoard(), *this))
42  , engineMask(calcEngineMask(getMotherBoard()))
43 {
44  updateMask();
46 }
47 
49 {
50 }
51 
52 void MSXMapperIO::updateMask()
53 {
54  // unused bits always read "1"
55  unsigned largest = (mapperSizes.empty()) ? 1 : mapperSizes.back();
56  mask = ((256 - Math::powerOfTwo(largest)) & 255) | engineMask;
57 }
58 
59 void MSXMapperIO::registerMapper(unsigned blocks)
60 {
61  auto it = upper_bound(mapperSizes.begin(), mapperSizes.end(), blocks);
62  mapperSizes.insert(it, blocks);
63  updateMask();
64 }
65 
66 void MSXMapperIO::unregisterMapper(unsigned blocks)
67 {
68  auto it = find(mapperSizes.begin(), mapperSizes.end(), blocks);
69  assert(it != mapperSizes.end());
70  mapperSizes.erase(it);
71  updateMask();
72 }
73 
75 {
76  // TODO in what state is mapper after reset?
77  // Zeroed is most likely.
78  // To find out for real, insert an external memory mapper on an MSX1.
79  for (unsigned i = 0; i < 4; ++i) {
80  registers[i] = 0;
81  }
82 }
83 
85 {
86  return peekIO(port, time);
87 }
88 
90 {
91  return getSelectedPage(port & 0x03) | mask;
92 }
93 
94 void MSXMapperIO::writeIO(word port, byte value, EmuTime::param /*time*/)
95 {
96  write(port & 0x03, value);
97 }
98 
100 {
101  return registers[bank];
102 }
103 
104 void MSXMapperIO::write(unsigned address, byte value)
105 {
106  registers[address] = value;
107  invalidateMemCache(0x4000 * address, 0x4000);
108 }
109 
110 
111 // SimpleDebuggable
112 
114  MSXMapperIO& mapperIO_)
115  : SimpleDebuggable(motherBoard, mapperIO_.getName(),
116  "Memory mapper registers", 4)
117  , mapperIO(mapperIO_)
118 {
119 }
120 
122 {
123  return mapperIO.getSelectedPage(address);
124 }
125 
126 void MapperIODebuggable::write(unsigned address, byte value)
127 {
128  mapperIO.write(address, value);
129 }
130 
131 
132 template<typename Archive>
133 void MSXMapperIO::serialize(Archive& ar, unsigned /*version*/)
134 {
135  ar.serialize("registers", registers);
136  // all other state is reconstructed in another way
137 }
139 
140 } // namespace openmsx