-
Notifications
You must be signed in to change notification settings - Fork 77
Expand file tree
/
Copy pathdiskcopyimagereader.cc
More file actions
135 lines (112 loc) · 3 KB
/
diskcopyimagereader.cc
File metadata and controls
135 lines (112 loc) · 3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#include "globals.h"
#include "flags.h"
#include "sector.h"
#include "imagereader/imagereader.h"
#include "image.h"
#include "lib/config.pb.h"
#include "fmt/format.h"
#include <algorithm>
#include <iostream>
#include <fstream>
class DiskCopyImageReader : public ImageReader
{
public:
DiskCopyImageReader(const ImageReaderProto& config):
ImageReader(config)
{}
Image readImage()
{
std::ifstream inputFile(_config.filename(), std::ios::in | std::ios::binary);
if (!inputFile.is_open())
Error() << "cannot open input file";
Bytes data;
data.writer() += inputFile;
ByteReader br(data);
br.seek(1);
std::string label = br.read(data[0]);
br.seek(0x40);
uint32_t dataSize = br.read_be32();
br.seek(0x50);
uint8_t encoding = br.read_8();
uint8_t formatByte = br.read_8();
unsigned numCylinders = 80;
unsigned numHeads = 2;
unsigned numSectors = 0;
bool mfm = false;
switch (encoding)
{
case 0: /* GCR CLV 400kB */
numHeads = 1;
break;
case 1: /* GCR CLV 800kB */
break;
case 2: /* MFM CAV 720kB */
numSectors = 9;
mfm = true;
break;
case 3: /* MFM CAV 1440kB */
numSectors = 18;
mfm = true;
break;
default:
Error() << fmt::format("don't understand DiskCopy disks of type {}", encoding);
}
std::cout << "reading DiskCopy 4.2 image\n"
<< fmt::format("{} cylinders, {} heads; {}; {}\n",
numCylinders, numHeads,
mfm ? "MFM" : "GCR",
label);
auto sectorsPerTrack = [&](int track) -> int
{
if (mfm)
return numSectors;
if (track < 16)
return 12;
if (track < 32)
return 11;
if (track < 48)
return 10;
if (track < 64)
return 9;
return 8;
};
uint32_t dataPtr = 0x54;
uint32_t tagPtr = dataPtr + dataSize;
Image image;
for (int track = 0; track < numCylinders; track++)
{
int numSectors = sectorsPerTrack(track);
for (int head = 0; head < numHeads; head++)
{
for (int sectorId = 0; sectorId < numSectors; sectorId++)
{
br.seek(dataPtr);
Bytes payload = br.read(512);
dataPtr += 512;
br.seek(tagPtr);
Bytes tag = br.read(12);
tagPtr += 12;
const auto& sector = image.put(track, head, sectorId);
sector->status = Sector::OK;
sector->logicalTrack = sector->physicalCylinder = track;
sector->logicalSide = sector->physicalHead = head;
sector->logicalSector = sectorId;
sector->data.writer().append(payload).append(tag);
}
}
}
Geometry g;
g.numTracks = numCylinders;
g.numSides = numHeads;
g.numSectors = 12;
g.sectorSize = 512 + 12;
g.irregular = true;
image.setGeometry(g);
return image;
}
};
std::unique_ptr<ImageReader> ImageReader::createDiskCopyImageReader(
const ImageReaderProto& config)
{
return std::unique_ptr<ImageReader>(new DiskCopyImageReader(config));
}