openMSX
SectorAccessibleDisk.cc
Go to the documentation of this file.
2 #include "DiskImageUtils.hh"
3 #include "EmptyDiskPatch.hh"
4 #include "IPSPatch.hh"
5 #include "DiskExceptions.hh"
6 #include "sha1.hh"
7 #include "xrange.hh"
8 #include <memory>
9 
10 namespace openmsx {
11 
13  : patch(std::make_unique<EmptyDiskPatch>(*this))
14 {
15 }
16 
18 
20 {
21  readSectors(&buf, sector, 1);
22 }
23 
25  SectorBuffer* buffers, size_t startSector, size_t nbSectors)
26 {
27  auto last = startSector + nbSectors - 1;
28  if (!isDummyDisk() && // in that case we want DriveEmptyException
29  (last > 1) && // allow reading sector 0 and 1 without calling
30  // getNbSectors() because this potentially calls
31  // detectGeometry() and that would cause an
32  // infinite loop
33  (getNbSectors() <= last)) {
34  throw NoSuchSectorException("No such sector");
35  }
36  try {
37  // in the end this calls readSectorsImpl()
38  patch->copyBlock(startSector * sizeof(SectorBuffer),
39  buffers[0].raw,
40  nbSectors * sizeof(SectorBuffer));
41  } catch (MSXException& e) {
42  throw DiskIOErrorException("Disk I/O error: ", e.getMessage());
43  }
44 }
45 
47  SectorBuffer* buffers, size_t startSector, size_t nbSectors)
48 {
49  // Default implementation reads one sector at a time. But subclasses can
50  // override this method if they can do it more efficiently.
51  for (auto i : xrange(nbSectors)) {
52  readSectorImpl(startSector + i, buffers[i]);
53  }
54 }
55 
56 void SectorAccessibleDisk::readSectorImpl(size_t /*sector*/, SectorBuffer& /*buf*/)
57 {
58  // subclass should override exactly one of
59  // readSectorImpl() or readSectorsImpl()
60  assert(false);
61 }
62 
63 void SectorAccessibleDisk::writeSector(size_t sector, const SectorBuffer& buf)
64 {
65  if (isWriteProtected()) {
67  }
68  if (!isDummyDisk() && (getNbSectors() <= sector)) {
69  throw NoSuchSectorException("No such sector");
70  }
71  try {
72  writeSectorImpl(sector, buf);
73  } catch (MSXException& e) {
74  throw DiskIOErrorException("Disk I/O error: ", e.getMessage());
75  }
76  flushCaches();
77 }
78 
80  const SectorBuffer* buffers, size_t startSector, size_t nbSectors)
81 {
82  // Simply write one-at-a-time. There's no possibility (nor any need) yet
83  // to allow to optimize this
84  for (auto i : xrange(nbSectors)) {
85  writeSector(startSector + i, buffers[i]);
86  }
87 }
88 
89 
91 {
92  return getNbSectorsImpl();
93 }
94 
96 {
97  patch = std::make_unique<IPSPatch>(std::move(patchFile), std::move(patch));
98 }
99 
100 std::vector<Filename> SectorAccessibleDisk::getPatches() const
101 {
102  return patch->getFilenames();
103 }
104 
106 {
107  return !patch->isEmptyPatch();
108 }
109 
111 {
112  checkCaches();
113  if (sha1cache.empty()) {
114  sha1cache = getSha1SumImpl(filePool);
115  }
116  return sha1cache;
117 }
118 
120 {
121  try {
122  setPeekMode(true);
123  SHA1 sha1;
124 
125  constexpr size_t MAX_CHUNK = 32;
126  SectorBuffer buf[MAX_CHUNK];
127  size_t total = getNbSectors();
128  size_t sector = 0;
129  while (sector < total) {
130  auto chunk = std::min(MAX_CHUNK, total - sector);
131  readSectors(buf, sector, chunk);
132  sha1.update({buf[0].raw, chunk * sizeof(SectorBuffer)});
133  sector += chunk;
134  }
135 
136  setPeekMode(false);
137  return sha1.digest();
138  } catch (MSXException&) {
139  setPeekMode(false);
140  throw;
141  }
142 }
143 
145 {
146  return forcedWriteProtect || isWriteProtectedImpl();
147 }
148 
150 {
151  // can't be undone
152  forcedWriteProtect = true;
153 }
154 
156 {
157  return false;
158 }
159 
161 {
162  // nothing
163 }
164 
166 {
167  sha1cache.clear();
168 }
169 
170 } // namespace openmsx
This class represents a filename.
Definition: Filename.hh:18
const std::string & getMessage() const &
Definition: MSXException.hh:23
Helper class to perform a sha1 calculation.
Definition: sha1.hh:81
Sha1Sum digest()
Get the final hash.
Definition: utils/sha1.cc:363
void update(span< const uint8_t > data)
Incrementally calculate the hash value.
Definition: utils/sha1.cc:320
void readSector(size_t sector, SectorBuffer &buf)
void readSectors(SectorBuffer *buffers, size_t startSector, size_t nbSectors)
Sha1Sum getSha1Sum(FilePool &filepool)
Calculate SHA1 of the content of this disk.
virtual void readSectorsImpl(SectorBuffer *buffers, size_t startSector, size_t nbSectors)
virtual Sha1Sum getSha1SumImpl(FilePool &filepool)
void writeSectors(const SectorBuffer *buffers, size_t startSector, size_t nbSectors)
std::vector< Filename > getPatches() const
void applyPatch(Filename patchFile)
void writeSector(size_t sector, const SectorBuffer &buf)
virtual void readSectorImpl(size_t sector, SectorBuffer &buf)
This class represents the result of a sha1 calculation (a 160-bit value).
Definition: sha1.hh:22
bool empty() const
Definition: utils/sha1.cc:246
constexpr vecN< N, T > min(const vecN< N, T > &x, const vecN< N, T > &y)
Definition: gl_vec.hh:269
This file implemented 3 utility functions:
Definition: Autofire.cc:5
constexpr auto xrange(T e)
Definition: xrange.hh:155