Skip to content

Commit

Permalink
Merge pull request #1 from shattered/_3cdd30f
Browse files Browse the repository at this point in the history
Add support for DVK MX format and --scale option
  • Loading branch information
simonowen committed Feb 4, 2017
2 parents 7bd82fa + 16f031f commit 429fd70
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 4 deletions.
2 changes: 2 additions & 0 deletions include/BitstreamDecoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ void scan_flux_mfm_fm (TrackData &trackdata, DataRate last_datarate);
void scan_flux_amiga (TrackData &trackdata);
void scan_flux_gcr (TrackData &trackdata);
void scan_flux_ace (TrackData &trackdata);
void scan_flux_mx (TrackData &trackdata);

void scan_bitstream (TrackData &trackdata);
void scan_bitstream_mfm_fm (TrackData &trackdata);
void scan_bitstream_amiga (TrackData &trackdata);
void scan_bitstream_ace (TrackData &trackdata);
void scan_bitstream_gcr (TrackData &trackdata);
void scan_bitstream_mx (TrackData &trackdata);

#endif // BITSTREAM_DECODER_H
2 changes: 1 addition & 1 deletion include/Header.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#define HEADER_H

enum class DataRate : int { Unknown = 0, _250K = 250'000, _300K = 300'000, _500K = 500'000, _1M = 1'000'000 };
enum class Encoding { Unknown, MFM, FM, Amiga, GCR, Ace };
enum class Encoding { Unknown, MFM, FM, Amiga, GCR, Ace, MX };

std::string to_string (const DataRate &datarate);
std::string to_string (const Encoding &encoding);
Expand Down
4 changes: 2 additions & 2 deletions include/SAMdisk.h
Original file line number Diff line number Diff line change
Expand Up @@ -267,8 +267,8 @@ typedef struct
int offsets = -1, absoffsets = 0, nowrite = 0, nodiff = 0, noformat = 0, nodups = 0, rpm = 0, flip = 0;
int base = -1, size = -1, gap3 = -1, interleave = -1, skew = -1, fill = -1, fm = -1, head0 = -1, head1 = -1;
int maxcopies = 3, fmoverlap = 0, multiformat = 0, cylsfirst = -1;
int bdos = 0, atom = 0, hdf = 0, cpm = 0, resize = 0, nocfa = 0, noidentify = 0, ace = 0;
int force = 0, nosig = 0, check8k = -1, tty = 0, nodata = 0, noflux = 0, nowobble = 0;
int bdos = 0, atom = 0, hdf = 0, cpm = 0, resize = 0, nocfa = 0, noidentify = 0, ace = 0, mx = 0;
int force = 0, nosig = 0, check8k = -1, tty = 0, nodata = 0, noflux = 0, nowobble = 0, scale = 100;
int time = 0, rate = -1, mt = -1;
long sectors = -1;
std::string label {}, boot {};
Expand Down
112 changes: 112 additions & 0 deletions src/BitstreamDecoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ void scan_flux (TrackData &trackdata)
return;
}

if (opt.mx)
{
scan_flux_mx(trackdata);
return;
}

// Set the encoding scanning order, with the last successful encoding first (and its duplicate removed)
std::vector<Encoding> encodings = { last_encoding, Encoding::MFM, Encoding::Amiga/*, Encoding::GCR*/ };
encodings.erase(std::next(std::find(encodings.rbegin(), encodings.rend(), last_encoding)).base());
Expand Down Expand Up @@ -107,6 +113,12 @@ void scan_bitstream (TrackData &trackdata)
return;
}

if (opt.mx)
{
scan_bitstream_mx(trackdata);
return;
}

// Set the encoding scanning order, with the last successful encoding first (and its duplicate removed)
std::vector<Encoding> encodings = { last_encoding, Encoding::MFM, Encoding::Amiga/*, Encoding::GCR*/ };
encodings.erase(std::next(std::find(encodings.rbegin(), encodings.rend(), last_encoding)).base());
Expand Down Expand Up @@ -374,6 +386,106 @@ void scan_flux_ace (TrackData &trackdata)
}


/*
* DVK MX format. DVK was a family of DEC LSI-11 compatible computers
* produced by Soviet Union in 1980's, MX.SYS is the RT-11 driver name
* for the controller.
*
* FM encoding. Track format is driver-dependent (except the sync word).
* Hardware always reads or writes entire track, hence no sector headers.
*
* 1. gap1 (8 words)
* 2. sync (1 word, 000363 octal, regular FM encoding)
* 3. zero-based track number (1 word)
* 4. 11 sectors:
* data (128 words)
* checksum (1 word)
* 5. extra (1..4 words)
* 6. gap4 (or unformatted)
*
* See also http://torlus.com/floppy/forum/viewtopic.php?f=19&t=1384
*/

void scan_bitstream_mx (TrackData &trackdata)
{
Track track;
Data block;
uint64_t dword = 0;
uint16_t stored_cksum = 0, cksum = 0;

auto &bitbuf = trackdata.bitstream();
bitbuf.seek(0);
bitbuf.encoding = Encoding::FM;
track.tracklen = bitbuf.track_bitsize();
bool sync = false;

while (!bitbuf.wrapped())
{
// Give up if no headers were found in the first revolution
if (!track.size() && bitbuf.tell() > track.tracklen)
break;

// ignore sync sequences after first one
if (sync)
break;

dword = (dword << 1) | bitbuf.read1();
if (opt.debug)
util::cout << util::fmt (" s_b_mx %016lx c:h %d:%d\n", dword, trackdata.cylhead.cyl, trackdata.cylhead.head);

switch (dword)
{
case 0x88888888aaaa88aa: // FM-encoded 0x00f3 (000363 octal)
sync = true;
if (opt.debug) util::cout << " s_b_mx found sync at " << bitbuf.tell() << "\n";
break;

default:
continue;
}

// skip track number
bitbuf.read_byte();
bitbuf.read_byte();

// read sectors
for (auto s = 0; s < 11; s++) {
Sector sector(DataRate::_250K, Encoding::MX, Header(trackdata.cylhead, s, SizeToCode(256)));

block.clear();
cksum = 0;

for (auto i = 0; i < 128; i++) {
auto msb = bitbuf.read_byte();
auto lsb = bitbuf.read_byte();
cksum += (lsb | (msb << 8));
block.push_back(lsb);
block.push_back(msb);
}

stored_cksum = bitbuf.read_byte() << 8;
stored_cksum |= bitbuf.read_byte();

if (opt.debug) util::cout << util::fmt ("cksum s %d disk:calc %06o:%06o (%04x:%04x)\n",
s, stored_cksum, cksum, stored_cksum, cksum);

sector.add(std::move(block), cksum != stored_cksum, 0);
track.add(std::move(sector));
}
}

trackdata.add(std::move(track));
}

void scan_flux_mx (TrackData &trackdata)
{
FluxDecoder decoder(trackdata.flux(), ::bitcell_ns(DataRate::_250K), opt.scale);
BitBuffer bitbuf(DataRate::_250K, decoder);

trackdata.add(std::move(bitbuf));
}


#define MFM_MASK 0x55555555UL

static bool amiga_read_dwords (BitBuffer &bitbuf, uint32_t *pdw, size_t dwords, uint32_t &checksum)
Expand Down
2 changes: 2 additions & 0 deletions src/Header.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ std::string to_string (const Encoding &encoding)
case Encoding::GCR: return "GCR"; break;
case Encoding::Amiga: return "Amiga"; break;
case Encoding::Ace: return "Ace"; break;
case Encoding::MX: return "MX"; break;
case Encoding::Unknown: break;
}
return "Unknown";
Expand All @@ -37,6 +38,7 @@ std::string short_name (const Encoding &encoding)
case Encoding::GCR: return "gcr"; break;
case Encoding::Amiga: return "ami"; break;
case Encoding::Ace: return "ace"; break;
case Encoding::MX: return "mx"; break;
case Encoding::Unknown: break;
}
return "unk";
Expand Down
5 changes: 4 additions & 1 deletion src/SAMdisk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ extern "C" {
#include "getopt_long.h"
}

enum { OPT_RPM = 256, OPT_RATE, OPT_LOG, OPT_VERSION, OPT_HEAD0, OPT_HEAD1, OPT_GAPMASK, OPT_MAXCOPIES, OPT_MAXSPLICE, OPT_CHECK8K, OPT_BYTES, OPT_HDF, OPT_ORDER };
enum { OPT_RPM = 256, OPT_RATE, OPT_LOG, OPT_VERSION, OPT_HEAD0, OPT_HEAD1, OPT_GAPMASK, OPT_MAXCOPIES, OPT_MAXSPLICE, OPT_CHECK8K, OPT_BYTES, OPT_HDF, OPT_ORDER, OPT_SCALE };

struct option long_options[] =
{
Expand Down Expand Up @@ -151,6 +151,7 @@ struct option long_options[] =
{ "byte-swap", no_argument, &opt.byteswap, 1 },
{ "atom", no_argument, &opt.byteswap, 1 },
{ "ace", no_argument, &opt.ace, 1 },
{ "mx", no_argument, &opt.mx, 1 },
{ "quick", no_argument, &opt.quick, 1 },
{ "repair", no_argument, &opt.repair, 1},
{ "fix", no_argument, &opt.fix, 1 },
Expand Down Expand Up @@ -181,6 +182,7 @@ struct option long_options[] =
{ "hdf", required_argument, nullptr, OPT_HDF },
{ "order", required_argument, nullptr, OPT_ORDER },
{ "version", no_argument, nullptr, OPT_VERSION },
{ "scale", required_argument, nullptr, OPT_SCALE },

{ 0, 0, 0, 0 }
};
Expand Down Expand Up @@ -303,6 +305,7 @@ bool ParseCommandLine (int argc_, char *argv_[])
case OPT_RPM: if (!GetInt(optarg, opt.rpm) || (opt.rpm != 300 && opt.rpm != 360)) return BadValue("rpm"); break;
case OPT_BYTES: if (!GetInt(optarg, opt.bytes) || !opt.bytes) return BadValue("bytes"); break;
case OPT_HDF: if (!GetInt(optarg, opt.hdf) || (opt.hdf != 10 && opt.hdf != 11)) return BadValue("hdf"); break;
case OPT_SCALE: if (!GetInt(optarg, opt.scale)) return BadValue("scale"); break;

case OPT_VERSION:
Version();
Expand Down

0 comments on commit 429fd70

Please sign in to comment.