40 [[nodiscard]]
unsigned getSize()
const override;
42 [[nodiscard]]
byte read(
unsigned address)
override;
43 void write(
unsigned address,
byte value)
override;
53 : name(
std::move(name_)), description(description_)
58 if (c->getAttributeValue(
"id", {}) ==
id) {
64 if (!errors.empty() && (errors.back() !=
'\n')) {
67 errors +=
e.getMessage();
73 string err =
"Missing <rom> tag";
92 bool checkResolvedSha1 =
false;
96 const auto* resolvedFilenameElem = config.
findChild(
"resolvedFilename");
97 const auto* resolvedSha1Elem = config.
findChild(
"resolvedSha1");
114 checkResolvedSha1 =
false;
116 }
else if (resolvedFilenameElem || resolvedSha1Elem ||
117 !sums.empty() || !filenames.empty()) {
120 if (resolvedFilenameElem) {
122 file = File(std::string(resolvedFilenameElem->getData()));
123 }
catch (FileException&) {
128 auto fileType =
context.isUserContext()
130 if (!file.
is_open() && resolvedSha1Elem) {
131 Sha1Sum sha1(resolvedSha1Elem->getData());
132 file = filePool.getFile(fileType, sha1);
140 for (
auto& f : filenames) {
144 }
catch (FileException&) {
152 for (
auto& s : sums) {
153 Sha1Sum sha1(s->getData());
154 file = filePool.getFile(fileType, sha1);
164 string error =
strCat(
"Couldn't find ROM file for \"", name,
'"');
165 if (!filenames.empty()) {
166 strAppend(error,
' ', filenames.front()->getData());
168 if (resolvedSha1Elem) {
169 strAppend(error,
" (sha1: ", resolvedSha1Elem->getData(),
')');
170 }
else if (!sums.empty()) {
171 strAppend(error,
" (sha1: ", sums.front()->getData(),
')');
174 throw MSXException(std::move(error));
181 "The <filesize> and <skip_headerbytes> tags "
182 "inside a <rom> section are no longer "
186 auto mmap = file.
mmap();
188 }
catch (FileException&) {
189 throw MSXException(
"Error reading ROM image: ", file.
getURL());
194 if (originalSha1.
empty()) {
195 originalSha1 = filePool.getSha1Sum(file);
199 if (!checkSHA1(config)) {
201 "SHA1 sum for '", name,
202 "' does not match with sum of '",
207 checkResolvedSha1 =
true;
216 std::span newRom{extendedRom.
data(),
size};
221 checkResolvedSha1 =
false;
225 if (
const auto* patchesElem = config.
findChild(
"patches")) {
229 std::unique_ptr<PatchInterface> patch =
230 std::make_unique<EmptyPatch>(rom);
232 for (
const auto* p : patchesElem->getChildren(
"ips")) {
233 patch = std::make_unique<IPSPatch>(
237 auto patchSize = patch->getSize();
238 if (patchSize <= rom.size()) {
239 patch->copyBlock(0, std::span{
const_cast<uint8_t*
>(rom.data()), rom.size()});
241 MemBuffer<byte> extendedRom2(patchSize);
242 patch->copyBlock(0, std::span{extendedRom2.data(), patchSize});
243 extendedRom = std::move(extendedRom2);
244 rom = std::span{extendedRom.
data(), patchSize};
251 checkResolvedSha1 =
true;
257 if (name.starts_with(
"MSXRom")) {
259 std::string_view title;
261 title = romInfo->getTitle(db.getBufferStart());
263 if (!title.empty()) {
274 if (debugger.findDebuggable(name)) {
278 tmp =
strCat(name,
" (", ++n,
')');
279 }
while (debugger.findDebuggable(tmp));
280 name = std::move(tmp);
284 if (checkResolvedSha1) {
287 const auto* actualSha1Elem = doc.getOrCreateChild(
288 const_cast<XMLElement&
>(config),
289 "resolvedSha1", doc.allocateString(patchedSha1Str));
290 if (actualSha1Elem->getData() != patchedSha1Str) {
291 std::string_view tmp = file.
is_open() ? file.
getURL() : name;
294 "The content of the rom ", tmp,
" has "
295 "changed since the time this savestate was "
296 "created. This might result in emulation "
303 if (
const auto* windowElem = config.
findChild(
"window")) {
304 unsigned windowBase = windowElem->getAttributeValueAsInt(
"base", 0);
305 unsigned windowSize = windowElem->getAttributeValueAsInt(
"size", narrow_cast<int>(rom.size()));
306 if ((windowBase + windowSize) > rom.size()) {
308 "The specified window [", windowBase,
',',
309 windowBase + windowSize,
") falls outside "
310 "the rom (with size ", rom.size(),
").");
312 rom = rom.subspan(windowBase, windowSize);
317 romDebuggable = std::make_unique<RomDebuggable>(debugger, *
this);
321bool Rom::checkSHA1(
const XMLElement& config)
const
323 auto sums =
to_vector(config.getChildren(
"sha1"));
324 return sums.empty() ||
326 [](
const auto* s) {
return Sha1Sum(s->getData()); });
330 : rom (std::move(r.rom))
331 , extendedRom (std::move(r.extendedRom))
332 , file (std::move(r.file))
333 , originalSha1 (std::move(r.originalSha1))
334 , actualSha1 (std::move(r.actualSha1))
335 , name (std::move(r.name))
336 , description (std::move(r.description))
337 , romDebuggable(std::move(r.romDebuggable))
339 if (romDebuggable) romDebuggable->moved(*
this);
351 if (originalSha1.
empty()) {
359 if (actualSha1.
empty())
368 assert(newSize >= rom.size());
369 if (newSize == rom.size())
return;
372 std::span newRom{tmp.
data(), newSize};
376 extendedRom = std::move(tmp);
389 : debugger(debugger_), rom(&rom_)
401 return narrow<unsigned>(rom->
size());
412 return (*rom)[address];
void printWarning(std::string_view message)
void unregisterDebuggable(std::string_view name, Debuggable &debuggable)
void registerDebuggable(std::string name, Debuggable &debuggable)
const FileContext & getFileContext() const
MSXMotherBoard & getMotherBoard() const
const XMLElement * getXML() const
std::span< const uint8_t > mmap()
Map file in memory.
std::string_view getOriginalName()
Get Original filename for this object.
bool is_open() const
Return true iff this file handle refers to an open file.
const std::string & getURL() const
Returns the URL of this file object.
XMLDocument & getXMLDocument()
const HardwareConfig * getMachineConfig() const
CliComm & getMSXCliComm()
PanasonicMemory & getPanasonicMemory()
void resize(size_t size)
Grow or shrink the memory block.
const T * data() const
Returns pointer to the start of the memory buffer.
std::span< const byte > getRomRange(unsigned first, unsigned last) const
RomDatabase & getSoftwareDatabase()
RomDebuggable & operator=(const RomDebuggable &)=delete
unsigned getSize() const override
byte read(unsigned address) override
void write(unsigned address, byte value) override
RomDebuggable(const RomDebuggable &)=delete
RomDebuggable(Debugger &debugger, Rom &rom)
std::string_view getDescription() const override
std::string_view getDescription() const
const Sha1Sum & getSHA1() const
const Sha1Sum & getOriginalSHA1() const
std::string_view getFilename() const
Rom(std::string name, static_string_view description, const DeviceConfig &config, const std::string &id={})
void getInfo(TclObject &result) const
Add dict values with info to result.
const std::string & getName() const
void addPadding(size_t newSize, byte filler=0xff)
static Sha1Sum calc(std::span< const uint8_t > data)
Easier to use interface, if you can pass all data in one go.
This class represents the result of a sha1 calculation (a 160-bit value).
std::string toString() const
void addDictKeyValues(Args &&... args)
int getChildDataAsInt(std::string_view childName, int defaultValue) const
const XMLElement * findChild(std::string_view childName) const
ChildRange getChildren() const
std::optional< Context > context
This file implemented 3 utility functions:
std::string toString(const Event &event)
Get a string representation of this event.
constexpr void fill(ForwardRange &&range, const T &value)
auto copy(InputRange &&range, OutputIter out)
auto to_vector(Range &&range) -> std::vector< detail::ToVectorType< T, decltype(std::begin(range))> >
constexpr bool contains(ITER first, ITER last, const VAL &val)
Check if a range contains a given value, using linear search.
std::string strCat(Ts &&...ts)
void strAppend(std::string &result, Ts &&...ts)