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