openMSX
Ram.cc
Go to the documentation of this file.
1 #include "Ram.hh"
2 #include "DeviceConfig.hh"
3 #include "SimpleDebuggable.hh"
4 #include "XMLElement.hh"
5 #include "Base64.hh"
6 #include "HexDump.hh"
7 #include "MSXException.hh"
8 #include "serialize.hh"
9 #include <zlib.h>
10 #include <algorithm>
11 #include <cstring>
12 #include <memory>
13 
14 using std::string;
15 
16 namespace openmsx {
17 
18 class RamDebuggable final : public SimpleDebuggable
19 {
20 public:
21  RamDebuggable(MSXMotherBoard& motherBoard, const string& name,
22  const string& description, Ram& ram);
23  byte read(unsigned address) override;
24  void write(unsigned address, byte value) override;
25 private:
26  Ram& ram;
27 };
28 
29 
30 Ram::Ram(const DeviceConfig& config, const string& name,
31  const string& description, unsigned size_)
32  : xml(*config.getXML())
33  , ram(size_)
34  , size(size_)
35  , debuggable(std::make_unique<RamDebuggable>(
36  config.getMotherBoard(), name, description, *this))
37 {
38  clear();
39 }
40 
41 Ram::Ram(const XMLElement& xml_, unsigned size_)
42  : xml(xml_)
43  , ram(size_)
44  , size(size_)
45 {
46  clear();
47 }
48 
49 Ram::~Ram() = default;
50 
52 {
53  if (const XMLElement* init = xml.findChild("initialContent")) {
54  // get pattern (and decode)
55  const string& encoding = init->getAttribute("encoding");
56  size_t done = 0;
57  if (encoding == "gz-base64") {
58  auto [buf, bufSize] = Base64::decode(init->getData());
59  uLongf dstLen = getSize();
60  if (uncompress(reinterpret_cast<Bytef*>(ram.data()), &dstLen,
61  reinterpret_cast<const Bytef*>(buf.data()), uLong(bufSize))
62  != Z_OK) {
63  throw MSXException("Error while decompressing initialContent.");
64  }
65  done = dstLen;
66  } else if ((encoding == "hex") || (encoding == "base64")) {
67  auto [buf, bufSize] = (encoding == "hex")
68  ? HexDump::decode(init->getData())
69  : Base64 ::decode(init->getData());
70  if (bufSize == 0) {
71  throw MSXException("Zero-length initial pattern");
72  }
73  done = std::min(size_t(size), bufSize);
74  memcpy(ram.data(), buf.data(), done);
75  } else {
76  throw MSXException("Unsupported encoding \"", encoding,
77  "\" for initialContent");
78  }
79 
80  // repeat pattern over whole ram
81  auto left = size - done;
82  while (left) {
83  auto tmp = std::min(done, left);
84  memcpy(&ram[done], &ram[0], tmp);
85  done += tmp;
86  left -= tmp;
87  }
88  } else {
89  // no init pattern specified
90  memset(ram.data(), c, size);
91  }
92 
93 }
94 
95 const string& Ram::getName() const
96 {
97  return debuggable->getName();
98 }
99 
101  const string& name_,
102  const string& description_, Ram& ram_)
103  : SimpleDebuggable(motherBoard_, name_, description_, ram_.getSize())
104  , ram(ram_)
105 {
106 }
107 
108 byte RamDebuggable::read(unsigned address)
109 {
110  return ram[address];
111 }
112 
113 void RamDebuggable::write(unsigned address, byte value)
114 {
115  ram[address] = value;
116 }
117 
118 
119 template<typename Archive>
120 void Ram::serialize(Archive& ar, unsigned /*version*/)
121 {
122  ar.serialize_blob("ram", ram.data(), size);
123 }
125 
126 } // namespace openmsx
const std::string & getName() const
Definition: Ram.cc:95
byte read(unsigned address) override
Definition: Ram.cc:108
RamDebuggable(MSXMotherBoard &motherBoard, const string &name, const string &description, Ram &ram)
Definition: Ram.cc:100
vecN< N, T > min(const vecN< N, T > &x, const vecN< N, T > &y)
Definition: gl_vec.hh:269
uint8_t byte
8 bit unsigned integer
Definition: openmsx.hh:26
STL namespace.
void clear(byte c=0xff)
Definition: Ram.cc:51
const T * data() const
Returns pointer to the start of the memory buffer.
Definition: MemBuffer.hh:90
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
const XMLElement * findChild(std::string_view name) const
MSXMotherBoard & getMotherBoard() const
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
Definition: serialize.hh:981
Ram(const DeviceConfig &config, const std::string &name, const std::string &description, unsigned size)
Create Ram object with an associated debuggable.
Definition: Ram.cc:30
void write(unsigned address, byte value) override
Definition: Ram.cc:113
void serialize(Archive &ar, unsigned version)
Definition: Ram.cc:120
unsigned getSize() const
Definition: Ram.hh:33