openMSX
SRAM.cc
Go to the documentation of this file.
1 #include "SRAM.hh"
2 #include "DeviceConfig.hh"
3 #include "File.hh"
4 #include "FileContext.hh"
5 #include "FileException.hh"
7 #include "Reactor.hh"
8 #include "CliComm.hh"
9 #include "serialize.hh"
10 #include "openmsx.hh"
11 #include "vla.hh"
12 #include <cstring>
13 
14 namespace openmsx {
15 
16 // class SRAM
17 
18 // Like the constructor below, but doesn't create a debuggable.
19 // For use in unittests.
21  : ram(xml, size)
22  , header(nullptr) // not used
23 {
24 }
25 
26 /* Creates a SRAM that is not loaded from or saved to a file.
27  * The only reason to use this (instead of a plain Ram object) is when you
28  * dynamically need to decide whether load/save is needed.
29  */
30 SRAM::SRAM(const std::string& name, static_string_view description,
31  int size, const DeviceConfig& config_, DontLoadTag)
32  : ram(config_, name, description, size)
33  , header(nullptr) // not used
34 {
35 }
36 
37 SRAM::SRAM(const std::string& name, int size,
38  const DeviceConfig& config_, const char* header_, bool* loaded)
39  : schedulable(std::in_place, config_.getReactor().getRTScheduler(), *this)
40  , config(config_)
41  , ram(config, name, "sram", size)
42  , header(header_)
43 {
44  load(loaded);
45 }
46 
47 SRAM::SRAM(const std::string& name, static_string_view description, int size,
48  const DeviceConfig& config_, const char* header_, bool* loaded)
49  : schedulable(std::in_place, config_.getReactor().getRTScheduler(), *this)
50  , config(config_)
51  , ram(config, name, description, size)
52  , header(header_)
53 {
54  load(loaded);
55 }
56 
58 {
59  if (schedulable) {
60  save();
61  }
62 }
63 
64 void SRAM::write(unsigned addr, byte value)
65 {
66  if (schedulable && !schedulable->isPendingRT()) {
67  schedulable->scheduleRT(5000000); // sync to disk after 5s
68  }
69  assert(addr < getSize());
70  ram.write(addr, value);
71 }
72 
73 void SRAM::memset(unsigned addr, byte c, unsigned size)
74 {
75  if (schedulable && !schedulable->isPendingRT()) {
76  schedulable->scheduleRT(5000000); // sync to disk after 5s
77  }
78  assert((addr + size) <= getSize());
79  ::memset(ram.getWriteBackdoor() + addr, c, size);
80 }
81 
82 void SRAM::load(bool* loaded)
83 {
84  assert(config.getXML());
85  if (loaded) *loaded = false;
86  const auto& filename = config.getChildData("sramname");
87  try {
88  bool headerOk = true;
91  if (header) {
92  size_t length = strlen(header);
93  VLA(char, temp, length);
94  file.read(temp, length);
95  if (memcmp(temp, header, length) != 0) {
96  headerOk = false;
97  }
98  }
99  if (headerOk) {
100  file.read(ram.getWriteBackdoor(), getSize());
101  loadedFilename = file.getURL();
102  if (loaded) *loaded = true;
103  } else {
104  config.getCliComm().printWarning(
105  "Warning no correct SRAM file: ", filename);
106  }
107  } catch (FileNotFoundException& /*e*/) {
108  config.getCliComm().printInfo(
109  "SRAM file ", filename, " not found, "
110  "assuming blank SRAM content.");
111  } catch (FileException& e) {
112  config.getCliComm().printWarning(
113  "Couldn't load SRAM ", filename,
114  " (", e.getMessage(), ").");
115  }
116 }
117 
118 void SRAM::save()
119 {
120  assert(config.getXML());
121  const auto& filename = config.getChildData("sramname");
122  try {
123  File file(config.getFileContext().resolveCreate(filename),
125  if (header) {
126  int length = int(strlen(header));
127  file.write(header, length);
128  }
129  file.write(&ram[0], getSize());
130  } catch (FileException& e) {
131  config.getCliComm().printWarning(
132  "Couldn't save SRAM ", filename,
133  " (", e.getMessage(), ").");
134  }
135 }
136 
137 void SRAM::SRAMSchedulable::executeRT()
138 {
139  sram.save();
140 }
141 
142 template<typename Archive>
143 void SRAM::serialize(Archive& ar, unsigned /*version*/)
144 {
145  ar.serialize("ram", ram);
146 }
148 
149 } // namespace openmsx
void printInfo(std::string_view message)
Definition: CliComm.cc:5
void printWarning(std::string_view message)
Definition: CliComm.cc:10
CliComm & getCliComm() const
Definition: DeviceConfig.cc:18
const FileContext & getFileContext() const
Definition: DeviceConfig.cc:9
std::string_view getChildData(std::string_view name) const
Definition: DeviceConfig.cc:48
const XMLElement * getXML() const
Definition: DeviceConfig.hh:48
std::string resolveCreate(std::string_view filename) const
Definition: FileContext.cc:88
@ SAVE_PERSISTENT
Definition: File.hh:23
@ LOAD_PERSISTENT
Definition: File.hh:22
void write(unsigned addr, byte value)
Definition: SRAM.cc:64
unsigned getSize() const
Definition: SRAM.hh:33
SRAM(int size, const XMLElement &xml, DontLoadTag)
Definition: SRAM.cc:20
void memset(unsigned addr, byte c, unsigned size)
Definition: SRAM.cc:73
void serialize(Archive &ar, unsigned version)
Definition: SRAM.cc:143
void write(unsigned addr, byte value)
Definition: TrackedRam.hh:38
byte * getWriteBackdoor()
Definition: TrackedRam.hh:52
static_string_view
T length(const vecN< N, T > &x)
Definition: gl_vec.hh:343
This file implemented 3 utility functions:
Definition: Autofire.cc:9
constexpr const char *const filename
size_t size(std::string_view utf8)
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
Definition: serialize.hh:998
#define VLA(TYPE, NAME, LENGTH)
Definition: vla.hh:10