Skip to content

Commit 98a2822

Browse files
committed
Add support for the 83kB 5.25" Lanier format.
1 parent d041b53 commit 98a2822

File tree

7 files changed

+66
-25
lines changed

7 files changed

+66
-25
lines changed

arch/aeslanier/aeslanier.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,19 @@
11
#ifndef AESLANIER_H
22
#define AESLANIER_H
33

4+
/* MFM:
5+
*
6+
* Raw bits:
7+
* 5 5 5 5 5 1 2 2
8+
* 0101 0101 0101 0101 0101 0001 0010 0010
9+
* 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1
10+
* 0 0 0 5
11+
* Decoded bits.
12+
*/
13+
414
#define AESLANIER_RECORD_SEPARATOR 0x55555122
515
#define AESLANIER_SECTOR_LENGTH 256
6-
#define AESLANIER_RECORD_SIZE (AESLANIER_SECTOR_LENGTH + 5)
16+
#define AESLANIER_RECORD_SIZE (AESLANIER_SECTOR_LENGTH + 4)
717

818
extern std::unique_ptr<Decoder> createAesLanierDecoder(
919
const DecoderProto& config);

arch/aeslanier5/aeslanier5.h

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,19 @@
11
#ifndef AESLANIER5_H
22
#define AESLANIER5_H
33

4-
#define AESLANIER5_RECORD_SEPARATOR 0x55555122
5-
#define AESLANIER5_SECTOR_LENGTH 256
6-
#define AESLANIER5_RECORD_SIZE (AESLANIER5_SECTOR_LENGTH + 5)
4+
/* Format is FM:
5+
*
6+
* a a a a f b e f
7+
* 1010 1010 1010 1010 1111 1011 1110 1111
8+
* 0 0 0 0 0 0 0 0 1 1 0 1 1 0 1 1
9+
* 0 0 d b
10+
*
11+
* However, note that this pattern is _not_ reversed...
12+
*/
13+
14+
#define AESLANIER5_RECORD_SEPARATOR 0xaaaaaaaaaaaafbefLL
15+
#define AESLANIER5_SECTOR_LENGTH 151
16+
#define AESLANIER5_RECORD_SIZE (AESLANIER5_SECTOR_LENGTH + 3)
717

818
extern std::unique_ptr<Decoder> createAesLanier5Decoder(
919
const DecoderProto& config);

arch/aeslanier5/decoder.cc

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
static const FluxPattern SECTOR_PATTERN(32, AESLANIER5_RECORD_SEPARATOR);
1414

15-
/* This is actually M2FM, rather than MFM, but it our MFM/FM decoder copes fine
15+
/* This is actually FM, rather than MFM, but it our MFM/FM decoder copes fine
1616
* with it. */
1717

1818
class AesLanier5Decoder : public Decoder
@@ -29,32 +29,45 @@ class AesLanier5Decoder : public Decoder
2929
{
3030
/* Skip ID mark (we know it's a AESLANIER5_RECORD_SEPARATOR). */
3131

32-
readRawBits(16);
32+
readRawBits(SECTOR_PATTERN.length());
3333

3434
const auto& rawbits = readRawBits(AESLANIER5_RECORD_SIZE * 16);
3535
const auto& bytes =
3636
decodeFmMfm(rawbits).slice(0, AESLANIER5_RECORD_SIZE);
3737
const auto& reversed = bytes.reverseBits();
3838

39-
_sector->logicalTrack = reversed[1];
39+
uint8_t encodedTrack = reversed[0];
40+
uint8_t encodedSector = reversed[1];
41+
42+
_sector->logicalTrack = encodedTrack >> 1;
4043
_sector->logicalSide = 0;
41-
_sector->logicalSector = reversed[2];
44+
_sector->logicalSector = encodedSector;
4245

4346
/* Check header 'checksum' (which seems far too simple to mean much). */
4447

4548
{
46-
uint8_t wanted = reversed[3];
47-
uint8_t got = reversed[1] + reversed[2];
49+
uint8_t wanted = reversed[2];
50+
uint8_t got = reversed[0] + reversed[1];
4851
if (wanted != got)
4952
return;
5053
}
5154

5255
/* Check data checksum, which also includes the header and is
5356
* significantly better. */
5457

55-
_sector->data = reversed.slice(1, AESLANIER5_SECTOR_LENGTH);
56-
uint16_t wanted = reversed.reader().seek(0x101).read_le16();
57-
uint16_t got = crc16ref(MODBUS_POLY_REF, _sector->data);
58+
_sector->data = reversed.slice(3, AESLANIER5_SECTOR_LENGTH);
59+
uint8_t wanted, got;
60+
ByteReader br(_sector->data);
61+
if ((encodedSector == 0) || (encodedSector == 8))
62+
{
63+
wanted = br.seek(17).read_8() + br.seek(150).read_8();
64+
got = sumBytes(_sector->data.slice(0, 17)) + sumBytes(_sector->data.slice(18, 132));
65+
}
66+
else
67+
{
68+
wanted = br.seek(150).read_8();
69+
got = sumBytes(_sector->data.slice(0, AESLANIER5_SECTOR_LENGTH-1));
70+
}
5871
_sector->status = (wanted == got) ? Sector::OK : Sector::BAD_CHECKSUM;
5972
}
6073
};

doc/disk-aeslanier.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,15 @@ based on what looks right. If anyone knows _anything_ about these disks,
3232
## Options
3333

3434
- Format variants:
35-
- `8" format`: use the format found on 8" disks
36-
- `5.25" format`: use the format found on 5.25" disks
35+
- `8`: use the format found on 8" disks
36+
- `5`: use the format found on 5.25" disks
3737

3838
## Examples
3939

4040
To read:
4141

42-
- `fluxengine read aeslanier --8" format -s drive:0 -o aeslanier.img`
43-
- `fluxengine read aeslanier --5.25" format -s drive:0 -o aeslanier.img`
42+
- `fluxengine read aeslanier --8 -s drive:0 -o aeslanier.img`
43+
- `fluxengine read aeslanier --5 -s drive:0 -o aeslanier.img`
4444

4545
## References
4646

lib/data/fluxpattern.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ class FluxPattern : public FluxMatcher
3333

3434
bool matches(const unsigned* intervals, FluxMatch& match) const override;
3535

36+
unsigned length() const
37+
{
38+
return _bits;
39+
}
40+
3641
unsigned intervals() const override
3742
{
3843
return _intervals.size();

src/formats/aeslanier.textpb

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ of nearly £50,000 in 2018!).
1414
processing software off twin 5.25" drive units, but apparently other software
1515
was available.
1616

17+
**Note:** the following is wrong and needs to be updated.
18+
1719
The disk format is exceptionally weird. They used 77 track, 32 sector, single-sided
1820
_hard_ sectored disks, where there were multiple index holes,
1921
indicating to the hardware where the sectors start. The encoding scheme
@@ -50,7 +52,7 @@ option_group {
5052
comment: "$formats"
5153

5254
option {
53-
name: '8" format'
55+
name: '8'
5456
comment: 'use the format found on 8" disks'
5557
set_by_default: true
5658

@@ -75,8 +77,8 @@ option_group {
7577
}
7678

7779
option {
78-
name: '5.25" format'
79-
comment: 'use the format found on 5.25" disks'
80+
name: '83'
81+
comment: '83kB 5.25" 35-track 16-sector SSSD'
8082

8183
config {
8284
decoder {

src/gui/fluxviewercontrol.cc

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -246,12 +246,13 @@ void FluxViewerControl::OnPaint(wxPaintEvent&)
246246
dc.SetTextForeground(*wxBLACK);
247247
for (auto& sector : trackdata->sectors)
248248
{
249-
nanoseconds_t sr = sector->dataEndTime;
250-
if (!sr)
251-
sr = sector->headerEndTime;
249+
nanoseconds_t tl = sector->headerStartTime;
250+
nanoseconds_t tr = sector->dataEndTime;
251+
if (!tl && !sector->headerEndTime)
252+
tl = sector->dataStartTime;
252253

253-
int sp = sector->headerStartTime / _nanosecondsPerPixel;
254-
int sw = (sr - sector->headerStartTime) / _nanosecondsPerPixel;
254+
int sp = tl / _nanosecondsPerPixel;
255+
int sw = (tr - tl) / _nanosecondsPerPixel;
255256

256257
wxRect rect = {x + sp, t1y - ch2, sw, ch};
257258
bool hovered = rect.Contains(_mouseX, _mouseY);

0 commit comments

Comments
 (0)