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