44 [[nodiscard]]
unsigned getSize()
const override;
46 [[nodiscard]]
byte read(
unsigned address)
override;
47 void write(
unsigned address,
byte value)
override;
57 : name(
std::move(name_)), description(description_)
62 if (c->getAttributeValue(
"id", {}) ==
id) {
68 if (!errors.empty() && (errors.back() !=
'\n')) {
71 errors += e.getMessage();
77 string err =
"Missing <rom> tag";
96 bool checkResolvedSha1 =
false;
100 const auto* resolvedFilenameElem = config.
findChild(
"resolvedFilename");
101 const auto* resolvedSha1Elem = config.
findChild(
"resolvedSha1");
118 checkResolvedSha1 =
false;
120 }
else if (resolvedFilenameElem || resolvedSha1Elem ||
121 !sums.empty() || !filenames.empty()) {
124 if (resolvedFilenameElem) {
126 file = File(std::string(resolvedFilenameElem->getData()));
127 }
catch (FileException&) {
132 auto fileType =
context.isUserContext()
134 if (!file.
is_open() && resolvedSha1Elem) {
135 Sha1Sum sha1(resolvedSha1Elem->getData());
136 file = filePool.getFile(fileType, sha1);
144 for (
auto& f : filenames) {
146 file = File(
Filename(f->getData(), context));
148 }
catch (FileException&) {
156 for (
auto& s : sums) {
157 Sha1Sum sha1(s->getData());
158 file = filePool.getFile(fileType, sha1);
168 string error =
strCat(
"Couldn't find ROM file for \"", name,
'"');
169 if (!filenames.empty()) {
170 strAppend(error,
' ', filenames.front()->getData());
172 if (resolvedSha1Elem) {
173 strAppend(error,
" (sha1: ", resolvedSha1Elem->getData(),
')');
174 }
else if (!sums.empty()) {
175 strAppend(error,
" (sha1: ", sums.front()->getData(),
')');
178 throw MSXException(std::move(error));
185 "The <filesize> and <skip_headerbytes> tags "
186 "inside a <rom> section are no longer "
190 auto mmap = file.
mmap();
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 std::span newRom{extendedRom.
data(),
size};
225 checkResolvedSha1 =
false;
229 if (
const auto* patchesElem = config.
findChild(
"patches")) {
233 std::unique_ptr<PatchInterface> patch =
234 std::make_unique<EmptyPatch>(rom);
236 for (
const auto* p : patchesElem->getChildren(
"ips")) {
237 patch = std::make_unique<IPSPatch>(
241 auto patchSize = patch->getSize();
242 if (patchSize <= rom.size()) {
243 patch->copyBlock(0, std::span{
const_cast<uint8_t*
>(rom.data()), rom.size()});
245 MemBuffer<byte> extendedRom2(patchSize);
246 patch->copyBlock(0, std::span{extendedRom2.data(), patchSize});
247 extendedRom = std::move(extendedRom2);
248 rom = std::span{extendedRom.
data(), patchSize};
255 checkResolvedSha1 =
true;
261 if (name.starts_with(
"MSXRom")) {
263 std::string_view title;
265 title = romInfo->getTitle(db.getBufferStart());
267 if (!title.empty()) {
277 if (!rom.empty() && debugger.findDebuggable(name)) {
281 tmp =
strCat(name,
" (", ++n,
')');
282 }
while (debugger.findDebuggable(tmp));
283 name = std::move(tmp);
286 if (checkResolvedSha1) {
289 const auto* actualSha1Elem = doc.getOrCreateChild(
290 const_cast<XMLElement&
>(config),
291 "resolvedSha1", doc.allocateString(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->getAttributeValueAsInt(
"base", 0);
307 unsigned windowSize = windowElem->getAttributeValueAsInt(
"size", narrow_cast<int>(rom.size()));
308 if ((windowBase + windowSize) > rom.size()) {
310 "The specified window [", windowBase,
',',
311 windowBase + windowSize,
") falls outside "
312 "the rom (with size ", rom.size(),
").");
314 rom = rom.subspan(windowBase, windowSize);
319 romDebuggable = std::make_unique<RomDebuggable>(debugger, *
this);
323bool Rom::checkSHA1(
const XMLElement& config)
const
325 auto sums =
to_vector(config.getChildren(
"sha1"));
326 return sums.empty() ||
328 [](
const auto* s) {
return Sha1Sum(s->getData()); });
333 , extendedRom (std::move(r.extendedRom))
334 , file (std::move(r.file))
335 , originalSha1 (r.originalSha1)
336 , actualSha1 (r.actualSha1)
337 , name (std::move(r.name))
338 , description (r.description)
339 , romDebuggable(std::move(r.romDebuggable))
341 if (romDebuggable) romDebuggable->moved(*
this);
353 if (originalSha1.
empty()) {
361 if (actualSha1.
empty())
370 assert(newSize >= rom.size());
371 if (newSize == rom.size())
return;
374 std::span newRom{tmp.
data(), newSize};
378 extendedRom = std::move(tmp);
391 : debugger(debugger_), rom(&rom_)
403 return narrow<unsigned>(rom->
size());
414 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
MSXCliComm & getMSXCliComm()
PanasonicMemory & getPanasonicMemory()
This class manages the lifetime of a block of memory.
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(RomDebuggable &&)=delete
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)
RomDebuggable & operator=(RomDebuggable &&)=delete
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 BooleanInput &input)
constexpr void fill(ForwardRange &&range, const T &value)
constexpr 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.
void strAppend(std::string &result, Ts &&...ts)