mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-31 11:17:01 -07:00
Reformat.
This commit is contained in:
@@ -18,189 +18,212 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
uint32_t ticks_to_a2r(uint32_t ticks) {
|
||||
return ticks * NS_PER_TICK / A2R_NS_PER_TICK;
|
||||
uint32_t ticks_to_a2r(uint32_t ticks)
|
||||
{
|
||||
return ticks * NS_PER_TICK / A2R_NS_PER_TICK;
|
||||
}
|
||||
|
||||
bool singlesided(void) {
|
||||
return config.heads().start() == config.heads().end();
|
||||
bool singlesided(void)
|
||||
{
|
||||
return config.heads().start() == config.heads().end();
|
||||
}
|
||||
|
||||
class A2RFluxSink : public FluxSink
|
||||
{
|
||||
public:
|
||||
A2RFluxSink(const A2RFluxSinkProto& lconfig):
|
||||
_config(lconfig),
|
||||
_bytes{},
|
||||
_writer{_bytes.writer()}
|
||||
{
|
||||
A2RFluxSink(const A2RFluxSinkProto& lconfig):
|
||||
_config(lconfig),
|
||||
_bytes{},
|
||||
_writer{_bytes.writer()}
|
||||
{
|
||||
|
||||
Logger() << fmt::format("A2R: writing A2R {} file containing {} tracks\n",
|
||||
singlesided() ? "single sided" : "double sided",
|
||||
config.tracks().end() - config.tracks().start() + 1
|
||||
);
|
||||
Logger() << fmt::format(
|
||||
"A2R: writing A2R {} file containing {} tracks\n",
|
||||
singlesided() ? "single sided" : "double sided",
|
||||
config.tracks().end() - config.tracks().start() + 1);
|
||||
|
||||
time_t now{std::time(nullptr)};
|
||||
auto t = gmtime(&now);
|
||||
_metadata["image_date"] = fmt::format("{:%FT%TZ}", *t);
|
||||
}
|
||||
time_t now{std::time(nullptr)};
|
||||
auto t = gmtime(&now);
|
||||
_metadata["image_date"] = fmt::format("{:%FT%TZ}", *t);
|
||||
}
|
||||
|
||||
~A2RFluxSink()
|
||||
{
|
||||
writeHeader();
|
||||
writeInfo();
|
||||
writeStream();
|
||||
writeMeta();
|
||||
~A2RFluxSink()
|
||||
{
|
||||
writeHeader();
|
||||
writeInfo();
|
||||
writeStream();
|
||||
writeMeta();
|
||||
|
||||
Logger() << "A2R: writing output file...\n";
|
||||
std::ofstream of(_config.filename(), std::ios::out | std::ios::binary);
|
||||
if (!of.is_open())
|
||||
Error() << "cannot open output file";
|
||||
_bytes.writeTo(of);
|
||||
of.close();
|
||||
}
|
||||
Logger() << "A2R: writing output file...\n";
|
||||
std::ofstream of(_config.filename(), std::ios::out | std::ios::binary);
|
||||
if (!of.is_open())
|
||||
Error() << "cannot open output file";
|
||||
_bytes.writeTo(of);
|
||||
of.close();
|
||||
}
|
||||
|
||||
private:
|
||||
void writeChunkAndData(uint32_t chunk_id, const Bytes &data) {
|
||||
_writer.write_le32(chunk_id);
|
||||
_writer.write_le32(data.size());
|
||||
_writer += data;
|
||||
}
|
||||
void writeChunkAndData(uint32_t chunk_id, const Bytes& data)
|
||||
{
|
||||
_writer.write_le32(chunk_id);
|
||||
_writer.write_le32(data.size());
|
||||
_writer += data;
|
||||
}
|
||||
|
||||
void writeHeader() {
|
||||
_writer += Bytes(a2r2_fileheader, sizeof(a2r2_fileheader));
|
||||
}
|
||||
void writeHeader()
|
||||
{
|
||||
static const uint8_t a2r2_fileheader[] = {'A', '2', 'R', '2', 0xff, 0x0a, 0x0d, 0x0a};
|
||||
_writer += Bytes(a2r2_fileheader, sizeof(a2r2_fileheader));
|
||||
}
|
||||
|
||||
void writeInfo() {
|
||||
Bytes info;
|
||||
auto writer = info.writer();
|
||||
writer.write_8(A2R_INFO_CHUNK_VERSION);
|
||||
auto version_str_padded = fmt::format("{: <32}", "Fluxengine");
|
||||
assert(version_str_padded.size() == 32);
|
||||
writer.append(version_str_padded);
|
||||
writer.write_8(singlesided() ? A2R_DISK_525 : A2R_DISK_35);
|
||||
writer.write_8(1); // write protected
|
||||
writer.write_8(1); // synchronized
|
||||
writeChunkAndData(A2R_CHUNK_INFO, info);
|
||||
}
|
||||
void writeInfo()
|
||||
{
|
||||
Bytes info;
|
||||
auto writer = info.writer();
|
||||
writer.write_8(A2R_INFO_CHUNK_VERSION);
|
||||
auto version_str_padded = fmt::format("{: <32}", "Fluxengine");
|
||||
assert(version_str_padded.size() == 32);
|
||||
writer.append(version_str_padded);
|
||||
writer.write_8(singlesided() ? A2R_DISK_525 : A2R_DISK_35);
|
||||
writer.write_8(1); // write protected
|
||||
writer.write_8(1); // synchronized
|
||||
writeChunkAndData(A2R_CHUNK_INFO, info);
|
||||
}
|
||||
|
||||
void writeMeta() {
|
||||
Bytes meta;
|
||||
auto writer = meta.writer();
|
||||
for(auto &i : _metadata) {
|
||||
writer.append(i.first);
|
||||
writer.write_8('\t');
|
||||
writer.append(i.second);
|
||||
writer.write_8('\n');
|
||||
}
|
||||
writeChunkAndData(A2R_CHUNK_META, meta);
|
||||
}
|
||||
void writeMeta()
|
||||
{
|
||||
Bytes meta;
|
||||
auto writer = meta.writer();
|
||||
for (auto& i : _metadata)
|
||||
{
|
||||
writer.append(i.first);
|
||||
writer.write_8('\t');
|
||||
writer.append(i.second);
|
||||
writer.write_8('\n');
|
||||
}
|
||||
writeChunkAndData(A2R_CHUNK_META, meta);
|
||||
}
|
||||
|
||||
void writeStream() {
|
||||
// A STRM always ends with a 255, even though this could ALSO indicate the first byte of a multi-byte sequence
|
||||
_strmWriter.write_8(255);
|
||||
void writeStream()
|
||||
{
|
||||
// A STRM always ends with a 255, even though this could ALSO indicate
|
||||
// the first byte of a multi-byte sequence
|
||||
_strmWriter.write_8(255);
|
||||
|
||||
writeChunkAndData(A2R_CHUNK_STRM, _strmBytes);
|
||||
}
|
||||
writeChunkAndData(A2R_CHUNK_STRM, _strmBytes);
|
||||
}
|
||||
|
||||
void writeFlux(int cylinder, int head, const Fluxmap& fluxmap) override
|
||||
{
|
||||
if(!fluxmap.bytes()) {
|
||||
return;
|
||||
}
|
||||
void writeFlux(int cylinder, int head, const Fluxmap& fluxmap) override
|
||||
{
|
||||
if (!fluxmap.bytes())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Writing from an image (as opposed to from a floppy) will contain exactly one revolution and no index events.
|
||||
auto is_image = [](auto &fluxmap) {
|
||||
FluxmapReader fmr(fluxmap);
|
||||
fmr.skipToEvent(F_BIT_INDEX);
|
||||
// but maybe there is no index, if we're writing from an image to an a2r
|
||||
return fmr.eof();
|
||||
};
|
||||
// Writing from an image (as opposed to from a floppy) will contain
|
||||
// exactly one revolution and no index events.
|
||||
auto is_image = [](auto& fluxmap)
|
||||
{
|
||||
FluxmapReader fmr(fluxmap);
|
||||
fmr.skipToEvent(F_BIT_INDEX);
|
||||
// but maybe there is no index, if we're writing from an image to an
|
||||
// a2r
|
||||
return fmr.eof();
|
||||
};
|
||||
|
||||
// Write the flux data into its own Bytes
|
||||
Bytes trackBytes;
|
||||
auto trackWriter = trackBytes.writer();
|
||||
// Write the flux data into its own Bytes
|
||||
Bytes trackBytes;
|
||||
auto trackWriter = trackBytes.writer();
|
||||
|
||||
auto write_one_flux = [&](unsigned ticks) {
|
||||
auto value = ticks_to_a2r(ticks);
|
||||
while(value > 254) {
|
||||
trackWriter.write_8(255);
|
||||
value -= 255;
|
||||
}
|
||||
trackWriter.write_8(value);
|
||||
};
|
||||
auto write_one_flux = [&](unsigned ticks)
|
||||
{
|
||||
auto value = ticks_to_a2r(ticks);
|
||||
while (value > 254)
|
||||
{
|
||||
trackWriter.write_8(255);
|
||||
value -= 255;
|
||||
}
|
||||
trackWriter.write_8(value);
|
||||
};
|
||||
|
||||
int revolution = 0;
|
||||
uint32_t loopPoint = 0;
|
||||
uint32_t totalTicks = 0;
|
||||
FluxmapReader fmr(fluxmap);
|
||||
int revolution = 0;
|
||||
uint32_t loopPoint = 0;
|
||||
uint32_t totalTicks = 0;
|
||||
FluxmapReader fmr(fluxmap);
|
||||
|
||||
auto write_flux = [&](unsigned maxTicks = ~0u) {
|
||||
unsigned ticksSinceLastPulse = 0;
|
||||
auto write_flux = [&](unsigned maxTicks = ~0u)
|
||||
{
|
||||
unsigned ticksSinceLastPulse = 0;
|
||||
|
||||
while(!fmr.eof() && totalTicks < maxTicks) {
|
||||
unsigned ticks;
|
||||
int event;
|
||||
fmr.getNextEvent(event, ticks);
|
||||
while (!fmr.eof() && totalTicks < maxTicks)
|
||||
{
|
||||
unsigned ticks;
|
||||
int event;
|
||||
fmr.getNextEvent(event, ticks);
|
||||
|
||||
ticksSinceLastPulse += ticks;
|
||||
totalTicks += ticks;
|
||||
ticksSinceLastPulse += ticks;
|
||||
totalTicks += ticks;
|
||||
|
||||
if(event & F_BIT_PULSE) {
|
||||
write_one_flux(ticksSinceLastPulse);
|
||||
ticksSinceLastPulse = 0;
|
||||
}
|
||||
if (event & F_BIT_PULSE)
|
||||
{
|
||||
write_one_flux(ticksSinceLastPulse);
|
||||
ticksSinceLastPulse = 0;
|
||||
}
|
||||
|
||||
if(event & F_BIT_INDEX && revolution == 0) {
|
||||
loopPoint = totalTicks;
|
||||
revolution += 1;
|
||||
}
|
||||
}
|
||||
if (event & F_BIT_INDEX && revolution == 0)
|
||||
{
|
||||
loopPoint = totalTicks;
|
||||
revolution += 1;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
if (is_image(fluxmap))
|
||||
{
|
||||
// A timing stream with no index represents exactly one
|
||||
// revolution with no index. However, a2r nominally contains 450
|
||||
// degress of rotation, 250ms at 300rpm.
|
||||
write_flux();
|
||||
loopPoint = totalTicks;
|
||||
fmr.rewind();
|
||||
revolution += 1;
|
||||
write_flux(totalTicks * 5 / 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We have an index, so this is real from a floppy and should be
|
||||
// "one revolution plus a bit"
|
||||
fmr.skipToEvent(F_BIT_INDEX);
|
||||
write_flux();
|
||||
}
|
||||
|
||||
if(is_image(fluxmap)) {
|
||||
// A timing stream with no index represents exactly one
|
||||
// revolution with no index. However, a2r nominally contains 450
|
||||
// degress of rotation, 250ms at 300rpm.
|
||||
write_flux();
|
||||
loopPoint = totalTicks;
|
||||
fmr.rewind();
|
||||
revolution += 1;
|
||||
write_flux(totalTicks*5/4);
|
||||
} else {
|
||||
// We have an index, so this is real from a floppy and should be "one revolution plus a bit"
|
||||
fmr.skipToEvent(F_BIT_INDEX);
|
||||
write_flux();
|
||||
}
|
||||
uint32_t chunk_size = 10 + trackBytes.size();
|
||||
|
||||
uint32_t chunk_size = 10 + trackBytes.size();
|
||||
_strmWriter.write_8(cylinder);
|
||||
_strmWriter.write_8(A2R_TIMING);
|
||||
_strmWriter.write_le32(trackBytes.size());
|
||||
_strmWriter.write_le32(ticks_to_a2r(loopPoint));
|
||||
_strmWriter += trackBytes;
|
||||
}
|
||||
|
||||
_strmWriter.write_8(cylinder);
|
||||
_strmWriter.write_8(A2R_TIMING);
|
||||
_strmWriter.write_le32(trackBytes.size());
|
||||
_strmWriter.write_le32(ticks_to_a2r(loopPoint));
|
||||
_strmWriter += trackBytes;
|
||||
}
|
||||
|
||||
operator std::string () const override
|
||||
{
|
||||
return fmt::format("a2r({})", _config.filename());
|
||||
}
|
||||
operator std::string() const override
|
||||
{
|
||||
return fmt::format("a2r({})", _config.filename());
|
||||
}
|
||||
|
||||
private:
|
||||
const A2RFluxSinkProto& _config;
|
||||
Bytes _bytes;
|
||||
ByteWriter _writer;
|
||||
Bytes _strmBytes;
|
||||
ByteWriter _strmWriter{_strmBytes.writer()};
|
||||
std::map<std::string, std::string> _metadata;
|
||||
const A2RFluxSinkProto& _config;
|
||||
Bytes _bytes;
|
||||
ByteWriter _writer;
|
||||
Bytes _strmBytes;
|
||||
ByteWriter _strmWriter{_strmBytes.writer()};
|
||||
std::map<std::string, std::string> _metadata;
|
||||
};
|
||||
}
|
||||
} // namespace
|
||||
|
||||
std::unique_ptr<FluxSink> FluxSink::createA2RFluxSink(const A2RFluxSinkProto& config)
|
||||
std::unique_ptr<FluxSink> FluxSink::createA2RFluxSink(
|
||||
const A2RFluxSinkProto& config)
|
||||
{
|
||||
return std::unique_ptr<FluxSink>(new A2RFluxSink(config));
|
||||
return std::unique_ptr<FluxSink>(new A2RFluxSink(config));
|
||||
}
|
||||
|
||||
const uint8_t a2r2_fileheader[] = {'A', '2', 'R', '2', 0xff, 0x0a, 0x0d, 0x0a };
|
||||
|
||||
Reference in New Issue
Block a user