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{
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 */
30SRAM::SRAM(const std::string& name, static_string_view description,
31 size_t size, const DeviceConfig& config_, DontLoadTag)
32 : ram(config_, name, description, size)
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 && schedulable->isPendingRT()) {
59 schedulable->cancelRT();
60 save();
61 }
62}
63
64void SRAM::write(size_t addr, byte value)
65{
66 if (schedulable && !schedulable->isPendingRT()) {
67 schedulable->scheduleRT(5000000); // sync to disk after 5s
68 }
69 assert(addr < size());
70 ram.write(addr, value);
71}
72
73void SRAM::memset(size_t addr, byte c, size_t aSize)
74{
75 if (schedulable && !schedulable->isPendingRT()) {
76 schedulable->scheduleRT(5000000); // sync to disk after 5s
77 }
78 assert((addr + aSize) <= size());
79 ranges::fill(ram.getWriteBackdoor().subspan(addr, aSize), c);
80}
81
82void 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;
89 File file(config.getFileContext().resolveCreate(filename),
91 if (header) {
92 size_t length = strlen(header);
93 VLA(char, buf, length);
94 file.read(buf);
95 headerOk = ranges::equal(buf, std::span{header, length});
96 }
97 if (headerOk) {
98 file.read(ram.getWriteBackdoor());
99 if (loaded) *loaded = true;
100 } else {
101 config.getCliComm().printWarning(
102 "Warning no correct SRAM file: ", filename);
103 }
104 } catch (FileNotFoundException& /*e*/) {
105 // SRAM file not found, assuming blank SRAM content.
106 } catch (FileException& e) {
107 config.getCliComm().printWarning(
108 "Couldn't load SRAM ", filename,
109 " (", e.getMessage(), ").");
110 }
111}
112
113void SRAM::save() const
114{
115 assert(config.getXML());
116 const auto& filename = config.getChildData("sramname");
117 try {
118 File file(config.getFileContext().resolveCreate(filename),
120 if (header) {
121 auto length = strlen(header);
122 file.write(std::span{header, length});
123 }
124 //file.write(std::span{ram}); // TODO error with clang-15/libc++
125 file.write(std::span{ram.begin(), ram.end()});
126 } catch (FileException& e) {
127 config.getCliComm().printWarning(
128 "Couldn't save SRAM ", filename,
129 " (", e.getMessage(), ").");
130 }
131}
132
133void SRAM::SRAMSchedulable::executeRT()
134{
135 sram.save();
136}
137
138template<typename Archive>
139void SRAM::serialize(Archive& ar, unsigned /*version*/)
140{
141 ar.serialize("ram", ram);
142}
144
145} // namespace openmsx
void printWarning(std::string_view message)
Definition CliComm.cc:12
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
SRAM(size_t size, const XMLElement &xml, DontLoadTag)
Definition SRAM.cc:21
void write(size_t addr, byte value)
Definition SRAM.cc:64
void serialize(Archive &ar, unsigned version)
Definition SRAM.cc:139
size_t size() const
Definition SRAM.hh:35
void memset(size_t addr, byte c, size_t size)
Definition SRAM.cc:73
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:315
constexpr bool equal(InputRange1 &&range1, InputRange2 &&range2, Pred pred={}, Proj1 proj1={}, Proj2 proj2={})
Definition ranges.hh:378
STL namespace.
#define INSTANTIATE_SERIALIZE_METHODS(CLASS)
#define VLA(TYPE, NAME, LENGTH)
Definition vla.hh:12