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