Archival, non-working checkin of the flux to scp converter (it appears to

produce garbage).
This commit is contained in:
David Given
2019-08-31 01:41:11 +02:00
parent 5a2b2bc07a
commit 116529f85a
4 changed files with 223 additions and 30 deletions

176
src/fe-fluxtoscp.cc Normal file
View File

@@ -0,0 +1,176 @@
#include "globals.h"
#include "flags.h"
#include "fluxmap.h"
#include "sql.h"
#include "bytes.h"
#include "protocol.h"
#include "dataspec.h"
#include "fmt/format.h"
#include "decoders/fluxmapreader.h"
#include "scp.h"
#include <fstream>
static FlagGroup flags { };
static SettableFlag fortyTrackMode(
{ "--48", "-4" },
"set 48 tpi mode; only every other physical track is emitted"
);
static SettableFlag singleSided(
{ "--single-sided", "-s" },
"only emit side 0"
);
static IntFlag diskType(
{ "--disk-type" },
"sets the SCP disk type byte",
0xff
);
static sqlite3* inputDb;
static void syntax()
{
std::cout << "Syntax: fluxengine convert fluxtoscp <fluxfile> <scpfile>\n";
exit(0);
}
static void write_le32(uint8_t dest[4], uint32_t v)
{
dest[0] = v;
dest[1] = v >> 8;
dest[2] = v >> 16;
dest[3] = v >> 24;
}
int mainConvertFluxToScp(int argc, const char* argv[])
{
auto filenames = flags.parseFlagsWithFilenames(argc, argv);
if (filenames.size() != 2)
syntax();
inputDb = sqlOpen(filenames[0], SQLITE_OPEN_READONLY);
auto tracks = sqlFindFlux(inputDb);
int maxTrack = 0;
for (auto p : tracks)
{
if (singleSided && (p.second == 1))
continue;
if (p.first > maxTrack)
maxTrack = p.first;
}
std::cout << fmt::format("Writing {} {} SCP file containing {} tracks\n",
fortyTrackMode ? "48 tpi" : "96 tpi",
singleSided ? "single sided" : "double sided",
(fortyTrackMode ? (maxTrack / 2) : maxTrack) + 1
);
ScpHeader fileheader = {0};
fileheader.file_id[0] = 'S';
fileheader.file_id[1] = 'C';
fileheader.file_id[2] = 'P';
fileheader.file_id[3] = 0x18; /* Version 1.8 of the spec */
fileheader.type = diskType;
fileheader.revolutions = 5;
fileheader.start_track = 0;
fileheader.end_track = maxTrack;
fileheader.flags = SCP_FLAG_INDEXED | (fortyTrackMode ? 0 : SCP_FLAG_96TPI);
fileheader.cell_width = 0;
fileheader.heads = singleSided ? 1 : 0;
Bytes trackdata;
ByteWriter trackdataWriter(trackdata);
int trackstep = 1 + fortyTrackMode;
int maxside = singleSided ? 0 : 1;
int strack = 0;
for (int track = 0; track <= maxTrack; track += trackstep)
{
for (int side = 0; side <= maxside; side++)
{
std::cout << fmt::format("FE track {}.{}, SCP track {}: ", track, side, strack) << std::flush;
auto fluxmap = sqlReadFlux(inputDb, track, side);
ScpTrack trackheader = {0};
trackheader.track_id[0] = 'T';
trackheader.track_id[1] = 'R';
trackheader.track_id[2] = 'K';
trackheader.strack = strack;
FluxmapReader fmr(*fluxmap);
Bytes fluxdata;
ByteWriter fluxdataWriter(fluxdata);
int revolution = 0;
unsigned revTicks = 0;
unsigned totalTicks = 0;
unsigned ticksSinceLastPulse = 0;
uint32_t startOffset = 0;
while (revolution < 5)
{
unsigned ticks;
int opcode = fmr.readOpcode(ticks);
if (ticks)
{
ticksSinceLastPulse += ticks;
totalTicks += ticks;
revTicks += ticks;
}
switch (opcode)
{
case -1: /* end of flux, treat like an index marker */
case F_OP_INDEX:
{
auto* revheader = &trackheader.revolution[revolution];
write_le32(revheader->offset, startOffset + sizeof(ScpTrack));
write_le32(revheader->length, fluxdataWriter.pos - startOffset);
write_le32(revheader->index, revTicks * NS_PER_TICK / 25);
revolution++;
revheader++;
revTicks = 0;
startOffset = fluxdataWriter.pos;
break;
}
case F_OP_PULSE:
{
unsigned t = ticksSinceLastPulse * NS_PER_TICK / 25;
while (t >= 0x10000)
{
fluxdataWriter.write_be16(0);
t -= 0x10000;
}
fluxdataWriter.write_be16(t);
ticksSinceLastPulse = 0;
break;
}
}
}
write_le32(fileheader.track[strack], trackdataWriter.pos + sizeof(ScpHeader));
trackdataWriter += Bytes((uint8_t*)&trackheader, sizeof(trackheader));
trackdataWriter += fluxdata;
std::cout << fmt::format("{} ms in {} bytes\n",
totalTicks * MS_PER_TICK,
fluxdata.size());
strack++;
}
}
sqlClose(inputDb);
std::cout << "Writing output file...\n";
std::ofstream of(filenames[1], std::ios::out | std::ios::binary);
if (!of.is_open())
Error() << "cannot open output file";
of.write((const char*) &fileheader, sizeof(fileheader));
of.write((const char*) trackdata.begin(), trackdata.size());
of.close();
return 0;
}

View File

@@ -4,37 +4,9 @@
#include "bytes.h"
#include "protocol.h"
#include "fmt/format.h"
#include "scp.h"
#include <fstream>
struct ScpHeader
{
char file_id[3]; // file ID - 'SCP'
uint8_t version; // major/minor in nibbles
uint8_t type; // disk type - subclass/class in nibbles
uint8_t revolutions; // up to 5
uint8_t start_track; // 0..165
uint8_t end_track; // 0..165
uint8_t flags; // see below
uint8_t cell_width; // in bits, 0 meaning 16
uint8_t heads; // 0 = both, 1 = side 0 only, 2 = side 1 only
uint8_t resolution; // 25ns * (resolution+1)
uint8_t checksum[4]; // of data after this point
uint8_t track[165][4]; // track offsets, not necessarily 165
};
struct ScpTrack
{
char track_id[3]; // 'TRK'
uint8_t strack; // SCP track number
struct
{
uint8_t index[4]; // time for one revolution
uint8_t length[4]; // number of bitcells
uint8_t offset[4]; // offset to bitcell data, relative to track header
}
revolution[5];
};
static std::ifstream inputFile;
static sqlite3* outputDb;
static ScpHeader header;
@@ -133,7 +105,7 @@ static void read_track(int strack)
pending = 0;
}
else
pending += interval;
pending += 0x10000;
}
}

View File

@@ -5,6 +5,7 @@ typedef int command_cb(int agrc, const char* argv[]);
extern command_cb mainErase;
extern command_cb mainConvertCwfToFlux;
extern command_cb mainConvertFluxToAu;
extern command_cb mainConvertFluxToScp;
extern command_cb mainConvertFluxToVcd;
extern command_cb mainConvertScpToFlux;
extern command_cb mainInspect;
@@ -86,6 +87,7 @@ static std::vector<Command> convertables =
{ "cwftoflux", mainConvertCwfToFlux, "Converts CatWeasel stream files to flux.", },
{ "scptoflux", mainConvertScpToFlux, "Converts Supercard Pro stream files to flux.", },
{ "fluxtoau", mainConvertFluxToAu, "Converts (one track of a) flux file to an .au audio file.", },
{ "fluxtoscp", mainConvertFluxToScp, "Converrt a flux file to a Supercard Pro file.", },
{ "fluxtovcd", mainConvertFluxToVcd, "Converts (one track of a) flux file to a VCD file.", },
};

43
src/scp.h Normal file
View File

@@ -0,0 +1,43 @@
#ifndef SCP_H
#define SCP_H
struct ScpHeader
{
char file_id[3]; // file ID - 'SCP'
uint8_t version; // major/minor in nibbles
uint8_t type; // disk type - subclass/class in nibbles
uint8_t revolutions; // up to 5
uint8_t start_track; // 0..165
uint8_t end_track; // 0..165
uint8_t flags; // see below
uint8_t cell_width; // in bits, 0 meaning 16
uint8_t heads; // 0 = both, 1 = side 0 only, 2 = side 1 only
uint8_t resolution; // 25ns * (resolution+1)
uint8_t checksum[4]; // of data after this point
uint8_t track[165][4]; // track offsets, not necessarily 165
};
enum
{
SCP_FLAG_INDEXED = (1<<0),
SCP_FLAG_96TPI = (1<<1),
SCP_FLAG_360RPM = (1<<2),
SCP_FLAG_NORMALIZED = (1<<3),
SCP_FLAG_READWRITE = (1<<4),
SCP_FLAG_FOOTER = (1<<5)
};
struct ScpTrack
{
char track_id[3]; // 'TRK'
uint8_t strack; // SCP track number
struct
{
uint8_t index[4]; // time for one revolution
uint8_t length[4]; // number of bitcells
uint8_t offset[4]; // offset to bitcell data, relative to track header
}
revolution[5];
};
#endif