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 "enumerate.hh"
7#include "sha1.hh"
8#include "xrange.hh"
9#include <array>
10#include <memory>
11
12namespace openmsx {
13
15 : patch(std::make_unique<EmptyDiskPatch>(*this))
16{
17}
18
20
22{
23 readSectors(std::span{&buf, 1}, sector);
24}
25
27 std::span<SectorBuffer> buffers, size_t startSector)
28{
29 auto last = startSector + buffers.size() - 1;
30 if (!isDummyDisk() && // in that case we want DriveEmptyException
31 (last > 1) && // allow reading sector 0 and 1 without calling
32 // getNbSectors() because this potentially calls
33 // detectGeometry() and that would cause an
34 // infinite loop
35 (getNbSectors() <= last)) {
36 throw NoSuchSectorException("No such sector");
37 }
38 try {
39 // in the end this calls readSectorsImpl()
40 patch->copyBlock(startSector * sizeof(SectorBuffer),
41 std::span{buffers[0].raw.data(),
42 buffers.size_bytes()});
43 } catch (MSXException& e) {
44 throw DiskIOErrorException("Disk I/O error: ", e.getMessage());
45 }
46}
47
49 std::span<SectorBuffer> buffers, size_t startSector)
50{
51 // Default implementation reads one sector at a time. But subclasses can
52 // override this method if they can do it more efficiently.
53 for (auto [i, buf] : enumerate(buffers)) {
54 readSectorImpl(startSector + i, buf);
55 }
56}
57
58void SectorAccessibleDisk::readSectorImpl(size_t /*sector*/, SectorBuffer& /*buf*/)
59{
60 // subclass should override exactly one of
61 // readSectorImpl() or readSectorsImpl()
62 assert(false);
63}
64
65void SectorAccessibleDisk::writeSector(size_t sector, const SectorBuffer& buf)
66{
67 if (isWriteProtected()) {
69 }
70 if (!isDummyDisk() && (getNbSectors() <= sector)) {
71 throw NoSuchSectorException("No such sector");
72 }
73 try {
74 writeSectorImpl(sector, buf);
75 } catch (MSXException& e) {
76 throw DiskIOErrorException("Disk I/O error: ", e.getMessage());
77 }
79}
80
82 std::span<const SectorBuffer> buffers, size_t startSector)
83{
84 // Simply write one-at-a-time. There's no possibility (nor any need) yet
85 // to allow to optimize this
86 for (auto [i, buf] : enumerate(buffers)) {
87 writeSector(startSector + i, buf);
88 }
89}
90
91
93{
94 return getNbSectorsImpl();
95}
96
98{
99 patch = std::make_unique<IPSPatch>(std::move(patchFile), std::move(patch));
100}
101
102std::vector<Filename> SectorAccessibleDisk::getPatches() const
103{
104 return patch->getFilenames();
105}
106
108{
109 return !patch->isEmptyPatch();
110}
111
113{
114 checkCaches();
115 if (sha1cache.empty()) {
116 sha1cache = getSha1SumImpl(filePool);
117 }
118 return sha1cache;
119}
120
122{
123 try {
124 setPeekMode(true);
125 SHA1 sha1;
126
127 std::array<SectorBuffer, 32> buf;
128 size_t total = getNbSectors();
129 size_t sector = 0;
130 while (sector < total) {
131 auto chunk = std::min(buf.size(), total - sector);
132 auto sub = subspan(buf, 0, chunk);
133 readSectors(sub, sector);
134 sha1.update({sub[0].raw.data(), sub.size_bytes()});
135 sector += chunk;
136 }
137
138 setPeekMode(false);
139 return sha1.digest();
140 } catch (MSXException&) {
141 setPeekMode(false);
142 throw;
143 }
144}
145
147{
148 return forcedWriteProtect || isWriteProtectedImpl();
149}
150
152{
153 // can't be undone
154 forcedWriteProtect = true;
155}
156
158{
159 return false;
160}
161
163{
164 // nothing
165}
166
168{
169 sha1cache.clear();
170}
171
172} // namespace openmsx
This class represents a filename.
Definition Filename.hh:18
Helper class to perform a sha1 calculation.
Definition sha1.hh:80
Sha1Sum digest()
Get the final hash.
void update(std::span< const uint8_t > data)
Incrementally calculate the hash value.
void writeSectors(std::span< const SectorBuffer > buffers, size_t startSector)
virtual Sha1Sum getSha1SumImpl(FilePool &filePool)
Sha1Sum getSha1Sum(FilePool &filePool)
Calculate SHA1 of the content of this disk.
void readSector(size_t sector, SectorBuffer &buf)
void readSectors(std::span< SectorBuffer > buffers, size_t startSector)
virtual void readSectorsImpl(std::span< SectorBuffer > buffers, size_t startSector)
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:23
bool empty() const
constexpr auto enumerate(Iterable &&iterable)
Heavily inspired by Nathan Reed's blog post: Python-Like enumerate() In C++17 http://reedbeta....
Definition enumerate.hh:28
This file implemented 3 utility functions:
Definition Autofire.cc:9
STL namespace.
constexpr auto subspan(Range &&range, size_t offset, size_t count=std::dynamic_extent)
Definition ranges.hh:471