mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-31 11:17:01 -07:00
Make the DS990 decoder work.
This commit is contained in:
@@ -8,54 +8,79 @@
|
||||
#include "record.h"
|
||||
#include "track.h"
|
||||
#include <string.h>
|
||||
#include <fmt/format.h>
|
||||
|
||||
const int SECTOR_SIZE = 256;
|
||||
/* The Texas Instruments DS990 uses MFM with a scheme similar to a simplified
|
||||
* version of the IBM record scheme (it's actually easier to parse than IBM).
|
||||
* There are 26 sectors per track, each holding a rather weird 288 bytes.
|
||||
*/
|
||||
|
||||
const FluxPattern ID_PATTERN(32, 0xaaaaffaf);
|
||||
/*
|
||||
* Sector record:
|
||||
* data: 0 1 0 1 0 1 0 1 .0 0 0 0 1 0 1 0 = 0x550a
|
||||
* mfm: 00 01 00 01 00 01 00 01.00 10 10 10 01 00 01 00 = 0x11112a44
|
||||
* special: 00 01 00 01 00 01 00 01.00 10 00 10 01 00 01 00 = 0x11112244
|
||||
* ^^
|
||||
* When shifted out of phase, the special 0xa1 byte becomes an illegal
|
||||
* encoding (you can't do 10 00). So this can't be spoofed by user data.
|
||||
*/
|
||||
const FluxPattern SECTOR_RECORD_PATTERN(32, 0x11112244);
|
||||
|
||||
/*
|
||||
* Data record:
|
||||
* data: 0 1 0 1 0 1 0 1 .0 0 0 0 1 0 1 1 = 0x550c
|
||||
* mfm: 00 01 00 01 00 01 00 01.00 10 10 10 01 00 01 01 = 0x11112a45
|
||||
* special: 00 01 00 01 00 01 00 01.00 10 00 10 01 00 01 01 = 0x11112245
|
||||
* ^^
|
||||
* When shifted out of phase, the special 0xa1 byte becomes an illegal
|
||||
* encoding (you can't do 10 00). So this can't be spoofed by user data.
|
||||
*/
|
||||
const FluxPattern DATA_RECORD_PATTERN(32, 0x11112245);
|
||||
|
||||
const FluxMatchers ANY_RECORD_PATTERN({ &SECTOR_RECORD_PATTERN, &DATA_RECORD_PATTERN });
|
||||
|
||||
AbstractDecoder::RecordType TiDs990Decoder::advanceToNextRecord()
|
||||
{
|
||||
return UNKNOWN_RECORD;
|
||||
// if (_currentSector == -1)
|
||||
// {
|
||||
// /* First sector in the track: look for the sync marker. */
|
||||
// const FluxMatcher* matcher = nullptr;
|
||||
// _sector->clock = _clock = _fmr->seekToPattern(ID_PATTERN, matcher);
|
||||
// readRawBits(32); /* skip the ID mark */
|
||||
// _logicalTrack = decodeFmMfm(readRawBits(32)).slice(0, 32).reader().read_be16();
|
||||
// }
|
||||
// else if (_currentSector == 10)
|
||||
// {
|
||||
// /* That was the last sector on the disk. */
|
||||
// return UNKNOWN_RECORD;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// /* Otherwise we assume the clock from the first sector is still valid.
|
||||
// * The decoder framwork will automatically stop when we hit the end of
|
||||
// * the track. */
|
||||
// _sector->clock = _clock;
|
||||
// }
|
||||
//
|
||||
// _currentSector++;
|
||||
// return SECTOR_RECORD;
|
||||
const FluxMatcher* matcher = nullptr;
|
||||
_sector->clock = _fmr->seekToPattern(ANY_RECORD_PATTERN, matcher);
|
||||
if (matcher == &SECTOR_RECORD_PATTERN)
|
||||
return RecordType::SECTOR_RECORD;
|
||||
if (matcher == &DATA_RECORD_PATTERN)
|
||||
return RecordType::DATA_RECORD;
|
||||
return RecordType::UNKNOWN_RECORD;
|
||||
}
|
||||
|
||||
void TiDs990Decoder::decodeSectorRecord()
|
||||
{
|
||||
// auto bits = readRawBits((SECTOR_SIZE+2)*16);
|
||||
// auto bytes = decodeFmMfm(bits).slice(0, SECTOR_SIZE+2).swab();
|
||||
//
|
||||
// uint16_t gotChecksum = 0;
|
||||
// ByteReader br(bytes);
|
||||
// for (int i=0; i<(SECTOR_SIZE/2); i++)
|
||||
// gotChecksum += br.read_le16();
|
||||
// uint16_t wantChecksum = br.read_le16();
|
||||
//
|
||||
// _sector->logicalTrack = _logicalTrack;
|
||||
// _sector->logicalSide = _track->physicalSide;
|
||||
// _sector->logicalSector = _currentSector;
|
||||
// _sector->data = bytes.slice(0, SECTOR_SIZE);
|
||||
// _sector->status = (gotChecksum == wantChecksum) ? Sector::OK : Sector::BAD_CHECKSUM;
|
||||
auto bits = readRawBits(TIDS990_SECTOR_RECORD_SIZE*16);
|
||||
auto bytes = decodeFmMfm(bits).slice(0, TIDS990_SECTOR_RECORD_SIZE);
|
||||
|
||||
ByteReader br(bytes);
|
||||
uint16_t gotChecksum = crc16(CCITT_POLY, bytes.slice(1, TIDS990_SECTOR_RECORD_SIZE-3));
|
||||
|
||||
br.seek(2);
|
||||
_sector->logicalSide = br.read_8() >> 3;
|
||||
_sector->logicalTrack = br.read_8();
|
||||
br.read_8(); /* number of sectors per track */
|
||||
_sector->logicalSector = br.read_8();
|
||||
br.read_be16(); /* sector size */
|
||||
uint16_t wantChecksum = br.read_be16();
|
||||
|
||||
if (wantChecksum == gotChecksum)
|
||||
_sector->status = Sector::DATA_MISSING; /* correct but unintuitive */
|
||||
}
|
||||
|
||||
void TiDs990Decoder::decodeDataRecord()
|
||||
{
|
||||
auto bits = readRawBits(TIDS990_DATA_RECORD_SIZE*16);
|
||||
auto bytes = decodeFmMfm(bits).slice(0, TIDS990_DATA_RECORD_SIZE);
|
||||
|
||||
ByteReader br(bytes);
|
||||
uint16_t gotChecksum = crc16(CCITT_POLY, bytes.slice(1, TIDS990_DATA_RECORD_SIZE-3));
|
||||
|
||||
br.seek(2);
|
||||
_sector->data = br.read(TIDS990_PAYLOAD_SIZE);
|
||||
uint16_t wantChecksum = br.read_be16();
|
||||
_sector->status = (wantChecksum == gotChecksum) ? Sector::OK : Sector::BAD_CHECKSUM;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#ifndef TIDS990_H
|
||||
#define TIDS990_H
|
||||
|
||||
#define TIDS990_RECORD_SIZE 0x516 /* bytes */
|
||||
#define TIDS990_ID_SIZE 17
|
||||
#define TIDS990_PAYLOAD_SIZE 0x500
|
||||
#define TIDS990_PAYLOAD_SIZE 288 /* bytes */
|
||||
#define TIDS990_SECTOR_RECORD_SIZE 10 /* bytes */
|
||||
#define TIDS990_DATA_RECORD_SIZE (TIDS990_PAYLOAD_SIZE + 4) /* bytes */
|
||||
|
||||
class Sector;
|
||||
class Fluxmap;
|
||||
@@ -16,6 +16,7 @@ public:
|
||||
|
||||
RecordType advanceToNextRecord();
|
||||
void decodeSectorRecord();
|
||||
void decodeDataRecord();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -13,8 +13,8 @@ static FlagGroup flags { &readerFlags };
|
||||
|
||||
int mainReadTiDs990(int argc, const char* argv[])
|
||||
{
|
||||
setReaderDefaultSource(":t=0-79:s=0");
|
||||
setReaderDefaultOutput("dfs.img");
|
||||
setReaderDefaultSource(":t=0-76");
|
||||
setReaderDefaultOutput("tids990.img");
|
||||
setReaderRevolutions(2);
|
||||
flags.parseFlags(argc, argv);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user