mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-31 11:17:01 -07:00
Partially decode the Kryoflux Mac image I have (complete with checksum
checking). The read is very bad, but I don't know whether that's because there's something wrong I'm doing, or if the Kryoflux image is bad.
This commit is contained in:
@@ -11,7 +11,8 @@ class AmigaDecoder : public AbstractDecoder
|
||||
public:
|
||||
virtual ~AmigaDecoder() {}
|
||||
|
||||
SectorVector decodeToSectors(const RawRecordVector& rawRecords);
|
||||
SectorVector decodeToSectors(
|
||||
const RawRecordVector& rawRecords, unsigned physicalTrack);
|
||||
nanoseconds_t guessClock(Fluxmap& fluxmap) const;
|
||||
int recordMatcher(uint64_t fifo) const;
|
||||
};
|
||||
|
||||
@@ -63,7 +63,7 @@ static uint32_t checksum(std::vector<uint8_t>::const_iterator input, size_t len)
|
||||
return checksum & 0x55555555;
|
||||
}
|
||||
|
||||
SectorVector AmigaDecoder::decodeToSectors(const RawRecordVector& rawRecords)
|
||||
SectorVector AmigaDecoder::decodeToSectors(const RawRecordVector& rawRecords, unsigned)
|
||||
{
|
||||
std::vector<std::unique_ptr<Sector>> sectors;
|
||||
|
||||
|
||||
@@ -16,7 +16,8 @@ class BrotherDecoder : public AbstractDecoder
|
||||
public:
|
||||
virtual ~BrotherDecoder() {}
|
||||
|
||||
SectorVector decodeToSectors(const RawRecordVector& rawRecords);
|
||||
SectorVector decodeToSectors(
|
||||
const RawRecordVector& rawRecords, unsigned physicalTrack);
|
||||
int recordMatcher(uint64_t fifo) const;
|
||||
};
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ static int decode_header_gcr(uint16_t word)
|
||||
return -1;
|
||||
};
|
||||
|
||||
SectorVector BrotherDecoder::decodeToSectors(const RawRecordVector& rawRecords)
|
||||
SectorVector BrotherDecoder::decodeToSectors(const RawRecordVector& rawRecords, unsigned)
|
||||
{
|
||||
std::vector<std::unique_ptr<Sector>> sectors;
|
||||
bool headerIsValid = false;
|
||||
|
||||
@@ -18,7 +18,8 @@ public:
|
||||
virtual ~AbstractDecoder() {}
|
||||
|
||||
virtual nanoseconds_t guessClock(Fluxmap& fluxmap) const;
|
||||
virtual SectorVector decodeToSectors(const RawRecordVector& rawrecords) = 0;
|
||||
virtual SectorVector decodeToSectors(const RawRecordVector& rawrecords,
|
||||
unsigned physicalTrack) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
static_assert(std::is_trivially_copyable<IbmIdam>::value);
|
||||
|
||||
SectorVector AbstractIbmDecoder::decodeToSectors(const RawRecordVector& rawRecords)
|
||||
SectorVector AbstractIbmDecoder::decodeToSectors(const RawRecordVector& rawRecords, unsigned)
|
||||
{
|
||||
bool idamValid = false;
|
||||
IbmIdam idam;
|
||||
|
||||
@@ -34,7 +34,7 @@ public:
|
||||
{}
|
||||
virtual ~AbstractIbmDecoder() {}
|
||||
|
||||
SectorVector decodeToSectors(const RawRecordVector& rawRecords);
|
||||
SectorVector decodeToSectors(const RawRecordVector& rawRecords, unsigned physicalTrack);
|
||||
|
||||
protected:
|
||||
virtual int skipHeaderBytes() const = 0;
|
||||
|
||||
@@ -10,12 +10,151 @@
|
||||
#include <string.h>
|
||||
#include <algorithm>
|
||||
|
||||
SectorVector MacintoshDecoder::decodeToSectors(const RawRecordVector& rawRecords)
|
||||
static int decode_data_gcr(uint8_t gcr)
|
||||
{
|
||||
switch (gcr)
|
||||
{
|
||||
#define GCR_ENTRY(gcr, data) \
|
||||
case gcr: return data;
|
||||
#include "data_gcr.h"
|
||||
#undef GCR_ENTRY
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
|
||||
static std::vector<uint8_t> decode_crazy_data(const uint8_t* inp, int& status)
|
||||
{
|
||||
std::vector<uint8_t> output;
|
||||
|
||||
static const int LOOKUP_LEN = MAC_SECTOR_LENGTH / 3;
|
||||
|
||||
uint8_t b1[LOOKUP_LEN + 1];
|
||||
uint8_t b2[LOOKUP_LEN + 1];
|
||||
uint8_t b3[LOOKUP_LEN + 1];
|
||||
|
||||
for (int i=0; i<=LOOKUP_LEN; i++)
|
||||
{
|
||||
uint8_t w4 = *inp++;
|
||||
uint8_t w1 = *inp++;
|
||||
uint8_t w2 = *inp++;
|
||||
uint8_t w3 = (i != 174) ? *inp++ : 0;
|
||||
|
||||
b1[i] = (w1 & 0x3F) | ((w4 << 2) & 0xC0);
|
||||
b2[i] = (w2 & 0x3F) | ((w4 << 4) & 0xC0);
|
||||
b3[i] = (w3 & 0x3F) | ((w4 << 6) & 0xC0);
|
||||
}
|
||||
|
||||
/* Copy from the user's buffer to our buffer, while computing
|
||||
* the three-byte data checksum. */
|
||||
|
||||
uint32_t c1 = 0;
|
||||
uint32_t c2 = 0;
|
||||
uint32_t c3 = 0;
|
||||
unsigned count = 0;
|
||||
for (;;)
|
||||
{
|
||||
c1 = (c1 & 0xFF) << 1;
|
||||
if (c1 & 0x0100)
|
||||
c1++;
|
||||
|
||||
uint8_t val = b1[count] ^ c1;
|
||||
c3 += val;
|
||||
if (c1 & 0x0100)
|
||||
{
|
||||
c3++;
|
||||
c1 &= 0xFF;
|
||||
}
|
||||
output.push_back(val);
|
||||
|
||||
val = b2[count] ^ c3;
|
||||
c2 += val;
|
||||
if (c3 > 0xFF)
|
||||
{
|
||||
c2++;
|
||||
c3 &= 0xFF;
|
||||
}
|
||||
output.push_back(val);
|
||||
|
||||
if (output.size() == 524)
|
||||
break;
|
||||
|
||||
val = b3[count] ^ c2;
|
||||
c1 += val;
|
||||
if (c2 > 0xFF)
|
||||
{
|
||||
c1++;
|
||||
c2 &= 0xFF;
|
||||
}
|
||||
output.push_back(val);
|
||||
count++;
|
||||
}
|
||||
|
||||
uint8_t c4 = ((c1 & 0xC0) >> 6) | ((c2 & 0xC0) >> 4) | ((c3 & 0xC0) >> 2);
|
||||
if ((*inp++ == c1) && (*inp++ == c2) && (*inp++ == c3) && (*inp++ == c4))
|
||||
status = Sector::OK;
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
SectorVector MacintoshDecoder::decodeToSectors(
|
||||
const RawRecordVector& rawRecords, unsigned physicalTrack)
|
||||
{
|
||||
std::vector<std::unique_ptr<Sector>> sectors;
|
||||
int nextSector;
|
||||
int nextSide;
|
||||
bool headerIsValid = false;
|
||||
|
||||
for (auto& rawrecord : rawRecords)
|
||||
{
|
||||
const std::vector<bool>& rawdata = rawrecord->data;
|
||||
const std::vector<uint8_t>& rawbytes = toBytes(rawdata);
|
||||
|
||||
if (rawbytes.size() < 8)
|
||||
continue;
|
||||
|
||||
uint32_t signature = read_be24(&rawbytes[0]);
|
||||
switch (signature)
|
||||
{
|
||||
case MAC_SECTOR_RECORD:
|
||||
{
|
||||
unsigned track = decode_data_gcr(rawbytes[3]);
|
||||
if (track != (physicalTrack & 0x3f))
|
||||
break;
|
||||
nextSector = decode_data_gcr(rawbytes[4]);
|
||||
nextSide = decode_data_gcr(rawbytes[5]);
|
||||
uint8_t formatByte = decode_data_gcr(rawbytes[6]);
|
||||
uint8_t wantedsum = decode_data_gcr(rawbytes[7]);
|
||||
|
||||
uint8_t gotsum = track ^ nextSector ^ nextSide ^ formatByte;
|
||||
headerIsValid = (wantedsum == gotsum);
|
||||
break;
|
||||
}
|
||||
|
||||
case MAC_DATA_RECORD:
|
||||
{
|
||||
if (!headerIsValid)
|
||||
break;
|
||||
headerIsValid = false;
|
||||
|
||||
uint8_t inputbuffer[MAC_SECTOR_LENGTH * 8/6 + 4] = {};
|
||||
for (unsigned i=0; i<sizeof(inputbuffer); i++)
|
||||
{
|
||||
auto p = rawbytes.begin() + 4 + i;
|
||||
if (p > rawbytes.end())
|
||||
break;
|
||||
|
||||
inputbuffer[i] = decode_data_gcr(*p);
|
||||
}
|
||||
|
||||
int status = Sector::BAD_CHECKSUM;
|
||||
auto data = decode_crazy_data(inputbuffer, status);
|
||||
|
||||
auto sector = std::unique_ptr<Sector>(
|
||||
new Sector(status, physicalTrack, nextSide, nextSector, data));
|
||||
sectors.push_back(std::move(sector));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sectors;
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
#define MAC_SECTOR_RECORD 0xd5aa96
|
||||
#define MAC_DATA_RECORD 0xd5aaad
|
||||
|
||||
#define MAC_SECTOR_LENGTH 524 /* yes, really */
|
||||
|
||||
class Sector;
|
||||
class Fluxmap;
|
||||
|
||||
@@ -12,7 +14,7 @@ class MacintoshDecoder : public AbstractDecoder
|
||||
public:
|
||||
virtual ~MacintoshDecoder() {}
|
||||
|
||||
SectorVector decodeToSectors(const RawRecordVector& rawRecords);
|
||||
SectorVector decodeToSectors(const RawRecordVector& rawRecords, unsigned physicalTrack);
|
||||
int recordMatcher(uint64_t fifo) const;
|
||||
};
|
||||
|
||||
|
||||
@@ -124,7 +124,7 @@ void readDiskCommand(AbstractDecoder& decoder, const std::string& outputFilename
|
||||
auto rawrecords = decoder.extractRecords(bitmap);
|
||||
std::cout << fmt::format("{} records", rawrecords.size()) << std::endl;
|
||||
|
||||
auto sectors = decoder.decodeToSectors(rawrecords);
|
||||
auto sectors = decoder.decodeToSectors(rawrecords, track->track);
|
||||
std::cout << " " << sectors.size() << " sectors; ";
|
||||
|
||||
for (auto& sector : sectors)
|
||||
|
||||
@@ -18,7 +18,7 @@ static StringFlag outputFilename(
|
||||
|
||||
int main(int argc, const char* argv[])
|
||||
{
|
||||
setReaderDefaultSource(":t=0-79:s=0");
|
||||
setReaderDefaultSource(":t=0-79:s=0-1");
|
||||
setReaderRevolutions(2);
|
||||
Flag::parseFlags(argc, argv);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user