Skip to content

Commit 610abf9

Browse files
committed
CRITICAL: Work on MFM encoder
1 parent 36ff90c commit 610abf9

File tree

13 files changed

+270
-33
lines changed

13 files changed

+270
-33
lines changed

Core/Peripherals/Drive/DiskEncoder.cpp

Lines changed: 112 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,100 @@
1818

1919
namespace vamiga {
2020

21+
void
22+
DiskEncoder::encodeTrack(const MutableByteView &track, Track t, span<const u8> data)
23+
{
24+
const isize bsize = 512; // Block size in bytes
25+
const isize ssize = 1088; // Encoded sector size in bytes
26+
const isize sectors = data.size() / bsize; // Number of sectors to encode
27+
28+
assert(data.size() % bsize == 0);
29+
30+
if (ADF_DEBUG) fprintf(stderr, "Encoding Amiga track %ld with %ld sectors\n", t, sectors);
31+
32+
// Format track
33+
track.clear(0xAA);
34+
35+
// Encode all sectors
36+
for (Sector s = 0; s < sectors; s++) {
37+
encodeSector(track, s * ssize, t, s, data.subspan(s * bsize, 512));
38+
}
39+
40+
// Compute a debug checksum
41+
if (ADF_DEBUG) fprintf(stderr, "Track %ld checksum = %x\n", t, track.fnv32());
42+
}
43+
44+
void
45+
DiskEncoder::encodeSector(const MutableByteView &track, isize offset, Track t, Sector s, span<const u8> data)
46+
{
47+
assert(data.size() == 512);
48+
49+
if (ADF_DEBUG) fprintf(stderr, "Encoding sector %ld\n", s);
50+
51+
// Block header layout:
52+
//
53+
// Start Size Value
54+
// Bytes before SYNC 00 4 0xAA 0xAA 0xAA 0xAA
55+
// SYNC mark 04 4 0x44 0x89 0x44 0x89
56+
// Track & sector info 08 8 Odd/Even encoded
57+
// Unused area 16 32 0xAA
58+
// Block checksum 48 8 Odd/Even encoded
59+
// Data checksum 56 8 Odd/Even encoded
60+
61+
auto it = track.cyclic_begin(offset);
62+
63+
// Bytes before SYNC
64+
it[0] = (it[-1] & 1) ? 0x2A : 0xAA;
65+
it[1] = 0xAA;
66+
it[2] = 0xAA;
67+
it[3] = 0xAA;
68+
69+
// SYNC mark
70+
u16 sync = 0x4489;
71+
it[4] = HI_BYTE(sync);
72+
it[5] = LO_BYTE(sync);
73+
it[6] = HI_BYTE(sync);
74+
it[7] = LO_BYTE(sync);
75+
76+
// Track and sector information
77+
u8 info[4] = { 0xFF, (u8)t, (u8)s, (u8)(11 - s) };
78+
FloppyDisk::encodeOddEven(&it[8], info, sizeof(info));
79+
80+
// Unused area
81+
for (isize i = 16; i < 48; i++)
82+
it[i] = 0xAA;
83+
84+
// Data
85+
FloppyDisk::encodeOddEven(&it[64], data);
86+
87+
// Block checksum
88+
u8 bcheck[4] = { 0, 0, 0, 0 };
89+
for(isize i = 8; i < 48; i += 4) {
90+
bcheck[0] ^= it[i];
91+
bcheck[1] ^= it[i+1];
92+
bcheck[2] ^= it[i+2];
93+
bcheck[3] ^= it[i+3];
94+
}
95+
FloppyDisk::encodeOddEven(&it[48], bcheck, sizeof(bcheck));
96+
97+
// Data checksum
98+
u8 dcheck[4] = { 0, 0, 0, 0 };
99+
for(isize i = 64; i < 1088; i += 4) {
100+
dcheck[0] ^= it[i];
101+
dcheck[1] ^= it[i+1];
102+
dcheck[2] ^= it[i+2];
103+
dcheck[3] ^= it[i+3];
104+
}
105+
FloppyDisk::encodeOddEven(&it[56], dcheck, sizeof(bcheck));
106+
107+
// Add clock bits
108+
for(isize i = 8; i < 1088 + 1; i++) {
109+
it[i] = FloppyDisk::addClockBits(it[i], it[i-1]);
110+
}
111+
// (it[1087] & 1) ? it[1088] &= 0x7F : it[1088] |= 0x80;
112+
}
113+
114+
21115
//
22116
// ADF
23117
//
@@ -39,7 +133,9 @@ DiskEncoder::encode(const ADFFile &adf, FloppyDisk &disk)
39133
disk.clearDisk();
40134

41135
// Encode all tracks
42-
for (Track t = 0; t < tracks; t++) encodeTrack(adf, disk, t);
136+
for (Track t = 0; t < tracks; t++) {
137+
encodeTrack(disk.byteView(t), t, adf.byteView(t));
138+
}
43139

44140
// In debug mode, also run the decoder
45141
if (ADF_DEBUG) {
@@ -61,7 +157,20 @@ DiskEncoder::encodeTrack(const ADFFile &adf, FloppyDisk &disk, Track t)
61157
disk.clearTrack(t, 0xAA);
62158

63159
// Encode all sectors
64-
for (Sector s = 0; s < sectors; s++) encodeSector(adf, disk, t, s);
160+
for (Sector s = 0; s < sectors; s++) {
161+
162+
encodeSector(adf, disk, t, s);
163+
164+
// REMOVE ASAP
165+
u8 q[1088];
166+
u8 adfbytes[512];
167+
adf.readBlock(adfbytes, t, s);
168+
auto mbv = MutableByteView(q, 1088);
169+
encodeSector(mbv, 0, t, s, span<const u8>(adfbytes,512));
170+
for (isize j = 0; j < 1088; j++) {
171+
assert((disk.data.track[t] + (s * 1088))[j] == q[j]);
172+
}
173+
}
65174

66175
// Rectify the first clock bit (where the buffer wraps over)
67176
if (disk.readBit(t, disk.length.track[t] * 8 - 1)) {
@@ -665,3 +774,4 @@ DiskEncoder::decodeSector(STFile &img, u8 *dst, const u8 *src)
665774

666775

667776
}
777+

Core/Peripherals/Drive/DiskEncoder.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@ class DiskEncoder {
1919
// General MFM
2020
//
2121

22-
// static void encodeSector(ByteView &track, isize offset, Track t, Sector s, span<const u8> data);
22+
public:
23+
24+
static void encodeTrack(const MutableByteView &track, Track t, span<const u8> data);
25+
static void encodeSector(const MutableByteView &track, isize offset, Track t, Sector s, span<const u8> data);
2326

2427

2528
//

Core/Peripherals/Drive/FloppyDisk.cpp

Lines changed: 56 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "Media.h"
1313
#include "MediaFile.h"
1414
#include "DeviceError.h"
15+
#include "DiskEncoder.h"
1516
#include "utl/io.h"
1617

1718
namespace vamiga {
@@ -21,17 +22,17 @@ FloppyDisk::init(Diameter dia, Density den, bool wp)
2122
{
2223
diameter = dia;
2324
density = den;
24-
25+
2526
u32 trackLength = 0;
26-
27+
2728
if (dia == Diameter::INCH_35 && den == Density::DD) trackLength = 12668;
2829
if (dia == Diameter::INCH_35 && den == Density::HD) trackLength = 24636;
2930
if (dia == Diameter::INCH_525 && den == Density::DD) trackLength = 12668;
30-
31+
3132
if (trackLength == 0 || FORCE_DISK_INVALID_LAYOUT) {
3233
throw DeviceError(DeviceError::DSK_INVALID_LAYOUT);
3334
}
34-
35+
3536
for (isize i = 0; i < 168; i++) length.track[i] = trackLength;
3637
clearDisk();
3738
setWriteProtection(wp);
@@ -68,7 +69,7 @@ FloppyDisk::_dump(Category category, std::ostream &os) const
6869
using namespace utl;
6970

7071
if (category == Category::State) {
71-
72+
7273
os << tab("Type");
7374
os << DiameterEnum::key(diameter) << std::endl;
7475
os << tab("Density");
@@ -159,6 +160,31 @@ FloppyDisk::checksum(Cylinder c, Head h) const
159160
return checksum(c * numHeads() + h);
160161
}
161162

163+
164+
ByteView
165+
FloppyDisk::byteView(Track t) const
166+
{
167+
return ByteView(data.track[t], length.track[t]);
168+
}
169+
170+
ByteView
171+
FloppyDisk::byteView(Track t, Sector s) const
172+
{
173+
return ByteView(data.track[t] + s * 1088, 1088);
174+
}
175+
176+
MutableByteView
177+
FloppyDisk::byteView(Track t)
178+
{
179+
return MutableByteView(data.track[t], length.track[t]);
180+
}
181+
182+
MutableByteView
183+
FloppyDisk::byteView(Track t, Sector s)
184+
{
185+
return MutableByteView(data.track[t] + s * 1088, 1088);
186+
}
187+
162188
u8
163189
FloppyDisk::readBit(Track t, isize offset) const
164190
{
@@ -312,7 +338,7 @@ FloppyDisk::encodeDisk(const FloppyDiskImage &file)
312338
switch (MediaFile::type(file)) {
313339
// switch (file.type()) {
314340

315-
case FileType::ADF: ADFEncoder::encode(dynamic_cast<const ADFFile &>(file), *this); break;
341+
case FileType::ADF: DiskEncoder::encode(dynamic_cast<const ADFFile &>(file), *this); break;
316342
case FileType::ADZ: ADZEncoder::encode(dynamic_cast<const ADZFile &>(file), *this); break;
317343
case FileType::EADF: EADFEncoder::encode(dynamic_cast<const EADFFile &>(file), *this); break;
318344
case FileType::IMG: IMGEncoder::encode(dynamic_cast<const IMGFile &>(file), *this); break;
@@ -395,6 +421,18 @@ FloppyDisk::encodeOddEven(u8 *dst, const u8 *src, isize count)
395421
dst[i + count] = src[i] & 0x55;
396422
}
397423

424+
void
425+
FloppyDisk::encodeOddEven(u8 *dst, span<const u8>src)
426+
{
427+
// Encode odd bits
428+
for(usize i = 0; i < src.size(); ++i)
429+
dst[i] = (src[i] >> 1) & 0x55;
430+
431+
// Encode even bits
432+
for(usize i = 0; i < src.size(); ++i)
433+
dst[i + src.size()] = src[i] & 0x55;
434+
}
435+
398436
void
399437
FloppyDisk::decodeOddEven(u8 *dst, const u8 *src, isize count)
400438
{
@@ -407,6 +445,18 @@ FloppyDisk::decodeOddEven(u8 *dst, const u8 *src, isize count)
407445
dst[i] |= src[i + count] & 0x55;
408446
}
409447

448+
void
449+
FloppyDisk::decodeOddEven(u8 *dst, span<const u8>src)
450+
{
451+
// Decode odd bits
452+
for(usize i = 0; i < src.size(); ++i)
453+
dst[i] = (u8)((src[i] & 0x55) << 1);
454+
455+
// Decode even bits
456+
for(usize i = 0; i < src.size(); ++i)
457+
dst[i] |= src[i + src.size()] & 0x55;
458+
}
459+
410460
void
411461
FloppyDisk::addClockBits(u8 *dst, isize count)
412462
{

Core/Peripherals/Drive/FloppyDisk.h

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -169,10 +169,6 @@ class FloppyDisk : public CoreObject, public TrackDevice {
169169
void readTrack(u8 *dst, isize nr) const override;
170170
void writeTrack(const u8 *src, isize nr) override;
171171

172-
// isize numCyls() const { return diameter == Diameter::INCH_525 ? 42 : 84; }
173-
// isize numHeads() const { return 2; }
174-
// isize numTracks() const { return diameter == Diameter::INCH_525 ? 84 : 168; }
175-
176172

177173
//
178174
// Serializing
@@ -219,12 +215,6 @@ class FloppyDisk : public CoreObject, public TrackDevice {
219215
Diameter getDiameter() const { return diameter; }
220216
Density getDensity() const { return density; }
221217

222-
/*
223-
isize numCyls() const { return diameter == Diameter::INCH_525 ? 42 : 84; }
224-
isize numHeads() const { return 2; }
225-
isize numTracks() const { return diameter == Diameter::INCH_525 ? 84 : 168; }
226-
*/
227-
228218
bool isWriteProtected() const { return flags & long(DiskFlags::PROTECTED); }
229219
void setWriteProtection(bool value) { value ? flags |= long(DiskFlags::PROTECTED) : flags &= ~long(DiskFlags::PROTECTED); }
230220

@@ -236,7 +226,18 @@ class FloppyDisk : public CoreObject, public TrackDevice {
236226
void setFlag(DiskFlags flag) { setFlag(flag, true); }
237227
void clearFlag(DiskFlags flag) { setFlag(flag, false); }
238228

239-
229+
230+
//
231+
// Accessing tracks and sectors
232+
//
233+
234+
ByteView byteView(Track t) const;
235+
ByteView byteView(Track t, Sector s) const;
236+
MutableByteView byteView(Track t);
237+
MutableByteView byteView(Track t, Sector s);
238+
239+
240+
240241
//
241242
// Reading and writing
242243
//
@@ -299,7 +300,10 @@ class FloppyDisk : public CoreObject, public TrackDevice {
299300
static void decodeMFM(u8 *dst, const u8 *src, isize count);
300301

301302
static void encodeOddEven(u8 *dst, const u8 *src, isize count);
303+
static void encodeOddEven(u8 *dst, span<const u8> src);
304+
302305
static void decodeOddEven(u8 *dst, const u8 *src, isize count);
306+
static void decodeOddEven(u8 *dst, span<const u8> src);
303307

304308
static void addClockBits(u8 *dst, isize count);
305309
static u8 addClockBits(u8 value, u8 previous);

Core/Storage/Devices/LinearDevice.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#pragma once
1111

1212
#include "utl/common.h"
13+
#include "DeviceTypes.h"
1314

1415
namespace vamiga {
1516

Core/Storage/Media/ADF/ADFEncoder.cpp

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,14 @@
1111
#include "ADFEncoder.h"
1212
#include "ADFFactory.h"
1313
#include "DeviceError.h"
14+
#include "DiskEncoder.h"
1415

1516
namespace vamiga {
1617

1718
void
1819
ADFEncoder::encode(const ADFFile &adf, FloppyDisk &disk)
1920
{
21+
2022
if (disk.getDiameter() != adf.getDiameter()) {
2123
throw DeviceError(DeviceError::DSK_INVALID_DIAMETER);
2224
}
@@ -47,19 +49,43 @@ void
4749
ADFEncoder::encodeTrack(const ADFFile &adf, FloppyDisk &disk, Track t)
4850
{
4951
isize sectors = adf.numSectors(t);
50-
if (ADF_DEBUG) fprintf(stderr, "Encoding Amiga track %ld with %ld sectors\n", t, sectors);
52+
if (ADF_DEBUG) fprintf(stderr, "Encoding Amiga track %ld with %ld sectors (%d bytes)\n", t, sectors, disk.length.track[t]);
53+
54+
printf("Encoding Amiga track %ld with %ld sectors (%d bytes)\n", t, sectors, disk.length.track[t]);
5155

5256
// Format track
5357
disk.clearTrack(t, 0xAA);
5458

5559
// Encode all sectors
56-
for (Sector s = 0; s < sectors; s++) encodeSector(adf, disk, t, s);
60+
// for (Sector s = 0; s < sectors; s++) encodeSector(adf, disk, t, s);
61+
62+
// Encode all sectors
63+
for (Sector s = 0; s < sectors; s++) { encodeSector(adf, disk, t, s); }
5764

5865
// Rectify the first clock bit (where the buffer wraps over)
5966
if (disk.readBit(t, disk.length.track[t] * 8 - 1)) {
6067
disk.writeBit(t, 0, 0);
6168
}
6269

70+
// REMOVE ASAP
71+
{
72+
// Make a copy of the track
73+
u8 copy[30*1088];
74+
for (isize j = 0; j < disk.length.track[t]; ++j) { copy[j] = disk.data.track[t][j]; }
75+
76+
// printf("1:"); for (isize j = 0; j < 6540; ++j) { printf("%02X ", copy[j]); } printf("\n");
77+
auto bv = disk.byteView(t);
78+
DiskEncoder::encodeTrack(bv, t, adf.byteView(t));
79+
80+
// printf("2:"); for (isize j = 0; j < 6540; ++j) { printf("%02X ", disk.data.track[t][j]); } printf("\n");
81+
for (isize j = 0; j < disk.length.track[t]; j++) {
82+
if (copy[j] != disk.data.track[t][j]) {
83+
printf("MISMATCH %ld %x %x (%d)\n", j, copy[j], disk.data.track[t][j], disk.length.track[t]);
84+
// assert(copy[j] == disk.data.track[t][j]);
85+
}
86+
}
87+
}
88+
6389
// Compute a debug checksum
6490
if (ADF_DEBUG) fprintf(stderr, "Track %ld checksum = %x\n",
6591
t, Hashable::fnv32(disk.data.track[t], disk.length.track[t]));

0 commit comments

Comments
 (0)