Reformat.

This commit is contained in:
David Given
2022-06-15 23:37:50 +02:00
parent cb5c0d5ebe
commit b55ebe95d9

View File

@@ -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 };