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 "memory.hh"
13 #include <cstring>
14 
15 using std::string;
16 
17 namespace openmsx {
18 
19 // class SRAM
20 
21 /* Creates a SRAM that is not loaded from or saved to a file.
22  * The only reason to use this (instead of a plain Ram object) is when you
23  * dynamically need to decide whether load/save is needed.
24  */
25 SRAM::SRAM(const std::string& name, const std::string& description,
26  int size, const DeviceConfig& config_, DontLoad)
27  : RTSchedulable(config_.getReactor().getRTScheduler())
28  , ram(config_, name, description, size)
29  , header(nullptr) // not used
30 {
31 }
32 
33 SRAM::SRAM(const string& name, int size,
34  const DeviceConfig& config_, const char* header_, bool* loaded)
35  : RTSchedulable(config_.getReactor().getRTScheduler())
36  , config(config_)
37  , ram(config, name, "sram", size)
38  , header(header_)
39 {
40  load(loaded);
41 }
42 
43 SRAM::SRAM(const string& name, const string& description, int size,
44  const DeviceConfig& config_, const char* header_, bool* loaded)
45  : RTSchedulable(config_.getReactor().getRTScheduler())
46  , config(config_)
47  , ram(config, name, description, size)
48  , header(header_)
49 {
50  load(loaded);
51 }
52 
54 {
55  save();
56 }
57 
58 void SRAM::write(unsigned addr, byte value)
59 {
60  if (!isPendingRT()) {
61  scheduleRT(5000000); // sync to disk after 5s
62  }
63  assert(addr < getSize());
64  ram.write(addr, value);
65 }
66 
67 void SRAM::memset(unsigned addr, byte c, unsigned size)
68 {
69  if (!isPendingRT()) {
70  scheduleRT(5000000); // sync to disk after 5s
71  }
72  assert((addr + size) <= getSize());
73  ::memset(ram.getWriteBackdoor() + addr, c, size);
74 }
75 
76 void SRAM::load(bool* loaded)
77 {
78  assert(config.getXML());
79  if (loaded) *loaded = false;
80  const string& filename = config.getChildData("sramname");
81  try {
82  bool headerOk = true;
83  File file(config.getFileContext().resolveCreate(filename),
85  if (header) {
86  size_t length = strlen(header);
87  VLA(char, temp, length);
88  file.read(temp, length);
89  if (memcmp(temp, header, length) != 0) {
90  headerOk = false;
91  }
92  }
93  if (headerOk) {
94  file.read(ram.getWriteBackdoor(), getSize());
95  loadedFilename = file.getURL();
96  if (loaded) *loaded = true;
97  } else {
98  config.getCliComm().printWarning(
99  "Warning no correct SRAM file: " + filename);
100  }
101  } catch (FileNotFoundException& /*e*/) {
102  config.getCliComm().printInfo(
103  "SRAM file " + filename + " not found" +
104  ", assuming blank SRAM content.");
105  } catch (FileException& e) {
106  config.getCliComm().printWarning(
107  "Couldn't load SRAM " + filename +
108  " (" + e.getMessage() + ").");
109  }
110 }
111 
112 void SRAM::save()
113 {
114  if (!config.getXML()) return;
115  const string& filename = config.getChildData("sramname");
116  try {
117  File file(config.getFileContext().resolveCreate(filename),
119  if (header) {
120  int length = int(strlen(header));
121  file.write(header, length);
122  }
123  file.write(&ram[0], getSize());
124  } catch (FileException& e) {
125  config.getCliComm().printWarning(
126  "Couldn't save SRAM " + filename +
127  " (" + e.getMessage() + ").");
128  }
129 }
130 
131 void SRAM::executeRT()
132 {
133  save();
134 }
135 
136 template<typename Archive>
137 void SRAM::serialize(Archive& ar, unsigned /*version*/)
138 {
139  ar.serialize("ram", ram);
140 }
142 
143 } // namespace openmsx
T length(const vecN< N, T > &x)
Definition: gl_vec.hh:333
byte * getWriteBackdoor()
Definition: TrackedRam.hh:52
void printWarning(string_ref message)
Definition: CliComm.cc:20
uint8_t byte
8 bit unsigned integer
Definition: openmsx.hh:26
void write(unsigned addr, byte value)
Definition: SRAM.cc:58
const FileContext & getFileContext() const
Definition: DeviceConfig.cc:9
void memset(unsigned addr, byte c, unsigned size)
Definition: SRAM.cc:67
CliComm & getCliComm() const
Definition: DeviceConfig.cc:18
const std::string & getMessage() const
Definition: MSXException.hh:13
bool isPendingRT() const
SRAM(const std::string &name, const std::string &description, int size, const DeviceConfig &config, DontLoad)
Definition: SRAM.cc:25
void serialize(Archive &ar, unsigned version)
Definition: SRAM.cc:137
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
unsigned getSize() const
Definition: SRAM.hh:31
size_t size() const
const std::string & getChildData(string_ref name) const
Definition: DeviceConfig.cc:43
void scheduleRT(uint64_t delta)
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
Definition: serialize.hh:840
const std::string resolveCreate(string_ref filename) const
Definition: FileContext.cc:85
void printInfo(string_ref message)
Definition: CliComm.cc:15
const XMLElement * getXML() const
Definition: DeviceConfig.hh:54
#define VLA(TYPE, NAME, LENGTH)
Definition: vla.hh:10
void write(unsigned addr, byte value)
Definition: TrackedRam.hh:38