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