openMSX
Disk.cc
Go to the documentation of this file.
1 #include "Disk.hh"
2 #include "DiskExceptions.hh"
3 #include "one_of.hh"
4 
5 namespace openmsx {
6 
8  : name(std::move(name_)), nbSides(0)
9 {
10 }
11 
12 void Disk::writeTrack(byte track, byte side, const RawTrack& input)
13 {
14  if (isWriteProtected()) {
16  }
17  writeTrackImpl(track, side, input);
18  flushCaches();
19 }
20 
22 {
23  if (!nbSides) {
25  }
26  return nbSides == 2;
27 }
28 
29 // Note: Special case to convert between logical/physical sector numbers
30 // for the boot sector and the 1st FAT sector (logical sector: 0/1,
31 // physical location: track 0, side 0, sector 1/2): perform this
32 // conversion without relying on the detected geometry parameters.
33 // Otherwise the detectGeometry() method (which itself reads these
34 // two sectors) would get in an infinite loop.
35 size_t Disk::physToLog(byte track, byte side, byte sector)
36 {
37  if ((track == 0) && (side == 0)) {
38  return sector - 1;
39  }
40  if (!nbSides) {
42  }
43  return sectorsPerTrack * (side + nbSides * track) + (sector - 1);
44 }
46 {
47  if (log <= 1) {
48  byte track = 0;
49  byte side = 0;
50  byte sector = byte(log + 1);
51  return {track, side, sector};
52  }
53  if (!nbSides) {
55  }
56  byte track = byte(log / (nbSides * sectorsPerTrack)); // TODO check for overflow
57  byte side = byte((log / sectorsPerTrack) % nbSides);
58  byte sector = byte((log % sectorsPerTrack) + 1);
59  return {track, side, sector};
60 }
61 
63 {
64  if (!nbSides) {
66  }
67  return sectorsPerTrack;
68 }
69 
70 void Disk::detectGeometryFallback() // if all else fails, use statistics
71 {
72  // TODO maybe also check for 8*80 for 8 sectors per track
73  sectorsPerTrack = 9; // most of the time (sorry 5.25" disk users...)
74  // 360k disks are likely to be single sided:
75  nbSides = (getNbSectors() == 720) ? 1 : 2;
76 }
77 
79 {
80  // From the MSX Red Book (p265):
81  //
82  // How to determine media types
83  //
84  // a) Read the boot sector (track 0, sector 1) of the target drive
85  //
86  // b) Check if the first byte is either 0E9H or 0EBH (the JMP
87  // instruction on 8086)
88  //
89  // c) If step b) fails, the disk is a version prior to MS-DOS 2.0;
90  // therefore, use the first byte of the FAT passed from the caller
91  // and make sure it is between 0F8h and 0FFh.
92  //
93  // If step c) is successful, use this as a media descriptor.
94  // If step c) fails, then this disk cannot be read.
95  //
96  // d) If step b) succeeds, read bytes # 0B to # 1D. This is the
97  // DPB for MS-DOS, Version 2.0 and above. The DPB for MSX-DOS can
98  // be obtained as follows.
99  //
100  // ....
101  // +18 +19 Sectors per track
102  // +1A +1B Number of heads
103  // ...
104 
105  //
106  // Media Descriptor 0F8H 0F9H 0FAh 0FBH 0FCH 0FDH 0FEH 0FFH
107  // byte (FAT-ID)
108  // Sectors/track 9 9 8 8 9 9 8 8
109  // No. of sides 1 2 1 2 1 2 1 2
110  // Tracks/side 80 80 80 80 40 40 40 40
111  // ...
112 
113  try {
114  SectorBuffer buf;
115  readSector(0, buf); // bootsector
116  if (buf.raw[0] == one_of(0xE9, 0xEB)) {
117  // use values from bootsector
118  sectorsPerTrack = buf.bootSector.sectorsTrack;
119  nbSides = buf.bootSector.nrSides;
120  if ((sectorsPerTrack == 0) || (sectorsPerTrack > 255) ||
121  (nbSides == 0) || (nbSides > 255)) {
122  // seems like bogus values, use defaults
124  }
125  } else {
126  readSector(1, buf); // 1st fat sector
127  byte mediaDescriptor = buf.raw[0];
128  if (mediaDescriptor >= 0xF8) {
129  sectorsPerTrack = (mediaDescriptor & 2) ? 8 : 9;
130  nbSides = (mediaDescriptor & 1) ? 2 : 1;
131  } else {
132  // invalid media descriptor, just assume it's a
133  // normal DS or SS DD disk
135  }
136  }
137  } catch (MSXException&) {
138  // read error, assume it's a 3.5" DS or SS DD disk
140  }
141 }
142 
143 } // namespace openmsx
Definition: one_of.hh:7
virtual void detectGeometryFallback()
Definition: Disk.cc:70
void writeTrack(byte track, byte side, const RawTrack &input)
Replace a full track in this image with the given track.
Definition: Disk.cc:12
unsigned getSectorsPerTrack()
Definition: Disk.cc:62
Disk(DiskName name)
Definition: Disk.cc:7
bool isDoubleSided()
Definition: Disk.cc:21
virtual void detectGeometry()
Definition: Disk.cc:78
TSS logToPhys(size_t log)
Definition: Disk.cc:45
size_t physToLog(byte track, byte side, byte sector)
Definition: Disk.cc:35
virtual void writeTrackImpl(byte track, byte side, const RawTrack &input)=0
void readSector(size_t sector, SectorBuffer &buf)
constexpr double log(double x)
Definition: cstd.hh:316
This file implemented 3 utility functions:
Definition: Autofire.cc:9
uint8_t byte
8 bit unsigned integer
Definition: openmsx.hh:26
MSXBootSector bootSector