27 using std::unique_ptr;
39 [[nodiscard]]
unsigned getSize()
const override;
41 [[nodiscard]]
byte read(
unsigned address)
override;
42 void write(
unsigned address,
byte value)
override;
52 : name(std::move(name_)), description(description_)
57 if (c->getAttribute(
"id", {}) ==
id) {
63 if (!errors.empty() && (errors.back() !=
'\n')) {
72 string err =
"Missing <rom> tag";
91 bool checkResolvedSha1 =
false;
95 const auto* resolvedFilenameElem = config.
findChild(
"resolvedFilename");
96 const auto* resolvedSha1Elem = config.
findChild(
"resolvedSha1");
109 size = (last - first + 1) * 0x2000;
114 checkResolvedSha1 =
false;
116 }
else if (resolvedFilenameElem || resolvedSha1Elem ||
117 !sums.empty() || !filenames.empty()) {
120 if (resolvedFilenameElem) {
122 file = File(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();
187 if (mmap.size() > std::numeric_limits<decltype(size)>::
max()) {
188 throw MSXException(
"Rom file too big: ", file.
getURL());
191 size = unsigned(mmap.size());
192 }
catch (FileException&) {
193 throw MSXException(
"Error reading ROM image: ", file.
getURL());
198 if (originalSha1.
empty()) {
199 originalSha1 = filepool.getSha1Sum(file);
203 if (!checkSHA1(config)) {
205 "SHA1 sum for '", name,
206 "' does not match with sum of '",
211 checkResolvedSha1 =
true;
220 memset(extendedRom.
data(), 0xff, size);
221 rom = extendedRom.
data();
224 checkResolvedSha1 =
false;
228 if (
const auto* patchesElem = config.
findChild(
"patches")) {
232 unique_ptr<PatchInterface> patch =
233 std::make_unique<EmptyPatch>(rom, size);
235 for (
auto& p : patchesElem->getChildren(
"ips")) {
236 patch = std::make_unique<IPSPatch>(
240 auto patchSize = unsigned(patch->getSize());
241 if (patchSize <= size) {
242 patch->copyBlock(0,
const_cast<byte*
>(rom), size);
246 patch->copyBlock(0, extendedRom.
data(), size);
247 rom = extendedRom.
data();
254 checkResolvedSha1 =
true;
262 std::string_view title;
264 title = romInfo->getTitle(db.getBufferStart());
266 if (!title.empty()) {
277 if (debugger.findDebuggable(name)) {
281 tmp =
strCat(name,
" (", ++n,
')');
282 }
while (debugger.findDebuggable(tmp));
283 name = std::move(tmp);
287 if (checkResolvedSha1) {
288 auto& mutableConfig =
const_cast<XMLElement&
>(config);
290 const auto& actualSha1Elem = mutableConfig.getCreateChild(
291 "resolvedSha1", patchedSha1Str);
292 if (actualSha1Elem.getData() != patchedSha1Str) {
293 std::string_view tmp = file.
is_open() ? file.
getURL() : name;
296 "The content of the rom ", tmp,
" has "
297 "changed since the time this savestate was "
298 "created. This might result in emulation "
305 if (
const auto* windowElem = config.
findChild(
"window")) {
306 unsigned windowBase = windowElem->getAttributeAsInt(
"base", 0);
307 unsigned windowSize = windowElem->getAttributeAsInt(
"size", size);
308 if ((windowBase + windowSize) > size) {
310 "The specified window [", windowBase,
',',
311 windowBase + windowSize,
") falls outside "
312 "the rom (with size ", size,
").");
314 rom = &rom[windowBase];
320 romDebuggable = std::make_unique<RomDebuggable>(debugger, *
this);
324 bool Rom::checkSHA1(
const XMLElement& config)
const
326 auto sums = config.getChildren(
"sha1");
332 return Sha1Sum(s->getData()) == sha1sum;
337 : rom (std::move(r.rom))
338 , extendedRom (std::move(r.extendedRom))
339 , file (std::move(r.file))
340 , originalSha1 (std::move(r.originalSha1))
341 , actualSha1 (std::move(r.actualSha1))
342 , name (std::move(r.name))
343 , description (std::move(r.description))
344 ,
size (std::move(r.size))
345 , romDebuggable(std::move(r.romDebuggable))
347 if (romDebuggable) romDebuggable->moved(*
this);
359 if (originalSha1.
empty()) {
367 if (actualSha1.
empty())
376 assert(newSize >= size);
377 if (newSize == size)
return;
380 auto* newData = tmp.
data();
381 memcpy(newData, rom, size);
382 memset(newData + size, filler, newSize - size);
384 extendedRom = std::move(tmp);
390 : debugger(debugger_), rom(&rom_)
413 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
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.
const std::string & getMessage() const &
CliComm & getMSXCliComm()
PanasonicMemory & getPanasonicMemory()
const T * data() const
Returns pointer to the start of the memory buffer.
void resize(size_t size)
Grow or shrink the memory block.
const byte * getRomRange(unsigned first, unsigned last)
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={})
const std::string & getName() const
void addPadding(unsigned newSize, byte filler=0xff)
static Sha1Sum calc(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
const XMLElement * findChild(std::string_view childName) const
const Children & getChildren() const
int getChildDataAsInt(std::string_view childName, int defaultValue=0) const
bool startsWith(string_view total, string_view part)
constexpr vecN< N, T > max(const vecN< N, T > &x, const vecN< N, T > &y)
std::unique_ptr< Context > context
This file implemented 3 utility functions:
bool any_of(InputRange &&range, UnaryPredicate pred)
size_t size(std::string_view utf8)
std::string strCat(Ts &&...ts)
void strAppend(std::string &result, Ts &&...ts)