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