openMSX
SectorAccessibleDisk.cc
Go to the documentation of this file.
2 #include "EmptyDiskPatch.hh"
3 #include "IPSPatch.hh"
4 #include "DiskExceptions.hh"
5 #include "sha1.hh"
6 #include "xrange.hh"
7 #include "memory.hh"
8 
9 namespace openmsx {
10 
11 #ifndef _MSC_VER
12 // This line is required according to the c++ standard, but because of a vc++
13 // extension, we get a link error in vc++ when we add this line. See also:
14 // http://blogs.msdn.com/b/xiangfan/archive/2010/03/03/vc-s-evil-extension-implicit-definition-of-static-constant-member.aspx
16 #endif
17 
19  : patch(make_unique<EmptyDiskPatch>(*this))
20  , forcedWriteProtect(false)
21  , peekMode(false)
22 {
23 }
24 
26 {
27 }
28 
29 void SectorAccessibleDisk::readSector(size_t sector, byte* buf)
30 {
31  if (!isDummyDisk() && // in that case we want DriveEmptyException
32  (sector > 1) && // allow reading sector 0 and 1 without calling
33  // getNbSectors() because this potentially calls
34  // detectGeometry() and that would cause an
35  // infinite loop
36  (getNbSectors() <= sector)) {
37  throw NoSuchSectorException("No such sector");
38  }
39  try {
40  // in the end this calls readSectorImpl()
41  patch->copyBlock(sector * SECTOR_SIZE, buf, SECTOR_SIZE);
42  } catch (MSXException& e) {
43  throw DiskIOErrorException("Disk I/O error: " + e.getMessage());
44  }
45 }
46 
47 void SectorAccessibleDisk::writeSector(size_t sector, const byte* buf)
48 {
49  if (isWriteProtected()) {
50  throw WriteProtectedException("");
51  }
52  if (!isDummyDisk() && (getNbSectors() <= sector)) {
53  throw NoSuchSectorException("No such sector");
54  }
55  try {
56  writeSectorImpl(sector, buf);
57  } catch (MSXException& e) {
58  throw DiskIOErrorException("Disk I/O error: " + e.getMessage());
59  }
60  flushCaches();
61 }
62 
64 {
65  return getNbSectorsImpl();
66 }
67 
69 {
70  patch = make_unique<IPSPatch>(patchFile, std::move(patch));
71 }
72 
73 std::vector<Filename> SectorAccessibleDisk::getPatches() const
74 {
75  return patch->getFilenames();
76 }
77 
79 {
80  return !patch->isEmptyPatch();
81 }
82 
84 {
85  checkCaches();
86  if (sha1cache.empty()) {
87  try {
88  setPeekMode(true);
89  SHA1 sha1;
90  for (auto i : xrange(getNbSectors())) {
91  byte buf[SECTOR_SIZE];
92  readSector(i, buf);
93  sha1.update(buf, SECTOR_SIZE);
94  }
95  sha1cache = sha1.digest();
96  setPeekMode(false);
97  } catch (MSXException&) {
98  setPeekMode(false);
99  throw;
100  }
101  }
102  return sha1cache;
103 }
104 
106  byte* buffer, size_t startSector, size_t nbSectors)
107 {
108  try {
109  for (auto i : xrange(nbSectors)) {
110  readSector(startSector + i, &buffer[i * SECTOR_SIZE]);
111  }
112  return 0;
113  } catch (MSXException&) {
114  return -1;
115  }
116 }
117 
119  const byte* buffer, size_t startSector, size_t nbSectors)
120 {
121  try {
122  for (auto i : xrange(nbSectors)) {
123  writeSector(startSector + i, &buffer[i * SECTOR_SIZE]);
124  }
125  return 0;
126  } catch (MSXException&) {
127  return -1;
128  }
129 }
130 
132 {
133  return forcedWriteProtect || isWriteProtectedImpl();
134 }
135 
137 {
138  // can't be undone
139  forcedWriteProtect = true;
140 }
141 
143 {
144  return false;
145 }
146 
148 {
149  // nothing
150 }
151 
153 {
154  sha1cache.clear();
155 }
156 
157 } // namespace openmsx