mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-31 11:17:01 -07:00
Compare commits
11 Commits
FluxEngine
...
FluxEngine
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
35f8249c67 | ||
|
|
d1467a14b8 | ||
|
|
3e6b9eb74d | ||
|
|
ce2e8fb4b5 | ||
|
|
7eaa75c05d | ||
|
|
e86de4483a | ||
|
|
203a74713f | ||
|
|
59ed2a6793 | ||
|
|
a03283ce64 | ||
|
|
984cdaeb03 | ||
|
|
a1ed4a9171 |
@@ -121,7 +121,7 @@ uint8_t decode_side(uint8_t side)
|
|||||||
* bit 5) and also whether we're above track 0x3f (in bit 6).
|
* bit 5) and also whether we're above track 0x3f (in bit 6).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
return !!(side & 0x40);
|
return !!(side & 0x20);
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractDecoder::RecordType MacintoshDecoder::advanceToNextRecord()
|
AbstractDecoder::RecordType MacintoshDecoder::advanceToNextRecord()
|
||||||
|
|||||||
@@ -45,22 +45,20 @@ Reading discs
|
|||||||
Just do:
|
Just do:
|
||||||
|
|
||||||
```
|
```
|
||||||
fluxengine read mac
|
fluxengine read mac -o mac.diskcopy
|
||||||
```
|
```
|
||||||
|
|
||||||
You should end up with an `mac.img` which is 1001888 bytes long (for a normal
|
You should end up with a `mac.diskcopy` file which is compatible with DiskCopy
|
||||||
DD disk). If you want the single-sided variety, use `-s :s=0`.
|
4.2, which most Mac emulators support.
|
||||||
|
|
||||||
**Big warning!** The image may not work in an emulator. Mac disk images are
|
**Big warning!** Mac disk images are complicated due to the way the tracks are
|
||||||
complicated due to the way the tracks are different sizes and the odd sector
|
different sizes and the odd sector size. If you use a normal `.img` file, then
|
||||||
size. FluxEngine chooses to store them in a simple 524 x 12 x 2 x 80 layout,
|
FluxEngine will store them in a simple 524 x 12 x 2 x 80 layout, with holes
|
||||||
with holes where missing sectors should be. This was easiest. If anyone can
|
where missing sectors should be; this was easiest, but is unlikely to work with
|
||||||
suggest a better way, please [get in
|
most Mac emulators and other software. In these files, the The 12 bytes of
|
||||||
touch](https://github.com/davidgiven/fluxengine/issues/new).
|
metadata _follow_ the 512 bytes of user payload in the sector image. If you
|
||||||
|
don't want it, specify a geometry in the output file with a 512-byte sectore
|
||||||
The 12 bytes of metadata _follow_ the 512 bytes of user payload in the sector
|
size like `-o mac.img:c=80:h=1:s=12:b=512`.
|
||||||
image. If you don't want it, specify a geometry in the output file with a
|
|
||||||
512-byte sectore size like `-o mac.img:c=80:h=1:s=12:b=512`.
|
|
||||||
|
|
||||||
Useful references
|
Useful references
|
||||||
-----------------
|
-----------------
|
||||||
@@ -74,3 +72,7 @@ Useful references
|
|||||||
|
|
||||||
- [Les Disquettes et le drive Disk II](http://www.hackzapple.com/DISKII/DISKIITECH.HTM), an
|
- [Les Disquettes et le drive Disk II](http://www.hackzapple.com/DISKII/DISKIITECH.HTM), an
|
||||||
epicly detailed writeup of the Apple II disk format (which is closely related)
|
epicly detailed writeup of the Apple II disk format (which is closely related)
|
||||||
|
|
||||||
|
- [The DiskCopy 4.2
|
||||||
|
format](https://www.discferret.com/wiki/Apple_DiskCopy_4.2), described on
|
||||||
|
the DiskFerret website.
|
||||||
|
|||||||
@@ -117,6 +117,10 @@ exact format varies according to the extension:
|
|||||||
FluxEngine's D64 support is currently limited to write only. It will work
|
FluxEngine's D64 support is currently limited to write only. It will work
|
||||||
with up to 40 logical tracks.
|
with up to 40 logical tracks.
|
||||||
|
|
||||||
|
- `.diskcopy`: a Macintosh DiskCopy 4.2 file. This is a special-purpose
|
||||||
|
format due to the weird layout of Mac GCR disks, but it can also support
|
||||||
|
720kB and 1440kB IBM disks (although there's no real benefit).
|
||||||
|
|
||||||
### High density disks
|
### High density disks
|
||||||
|
|
||||||
High density disks use a different magnetic medium to low and double density
|
High density disks use a different magnetic medium to low and double density
|
||||||
|
|||||||
13
lib/bytes.h
13
lib/bytes.h
@@ -1,6 +1,8 @@
|
|||||||
#ifndef BYTES_H
|
#ifndef BYTES_H
|
||||||
#define BYTES_H
|
#define BYTES_H
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
class ByteReader;
|
class ByteReader;
|
||||||
class ByteWriter;
|
class ByteWriter;
|
||||||
|
|
||||||
@@ -10,6 +12,7 @@ public:
|
|||||||
Bytes();
|
Bytes();
|
||||||
Bytes(unsigned size);
|
Bytes(unsigned size);
|
||||||
Bytes(const uint8_t* ptr, size_t len);
|
Bytes(const uint8_t* ptr, size_t len);
|
||||||
|
Bytes(const std::string& data);
|
||||||
Bytes(std::initializer_list<uint8_t> data);
|
Bytes(std::initializer_list<uint8_t> data);
|
||||||
Bytes(std::shared_ptr<std::vector<uint8_t>> data);
|
Bytes(std::shared_ptr<std::vector<uint8_t>> data);
|
||||||
Bytes(std::shared_ptr<std::vector<uint8_t>> data, unsigned start, unsigned end);
|
Bytes(std::shared_ptr<std::vector<uint8_t>> data, unsigned start, unsigned end);
|
||||||
@@ -271,6 +274,16 @@ public:
|
|||||||
|
|
||||||
ByteWriter& operator += (std::istream& stream);
|
ByteWriter& operator += (std::istream& stream);
|
||||||
|
|
||||||
|
ByteWriter& append(const char* data)
|
||||||
|
{
|
||||||
|
return *this += Bytes((const uint8_t*)data, strlen(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteWriter& append(const std::string& data)
|
||||||
|
{
|
||||||
|
return *this += Bytes(data);
|
||||||
|
}
|
||||||
|
|
||||||
ByteWriter& append(const Bytes data)
|
ByteWriter& append(const Bytes data)
|
||||||
{
|
{
|
||||||
return *this += data;
|
return *this += data;
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
#include <set>
|
#include <set>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
typedef int nanoseconds_t;
|
typedef double nanoseconds_t;
|
||||||
class Bytes;
|
class Bytes;
|
||||||
|
|
||||||
extern double getCurrentTime();
|
extern double getCurrentTime();
|
||||||
|
|||||||
169
lib/imagewriter/diskcopyimagewriter.cc
Normal file
169
lib/imagewriter/diskcopyimagewriter.cc
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
#include "globals.h"
|
||||||
|
#include "flags.h"
|
||||||
|
#include "dataspec.h"
|
||||||
|
#include "sector.h"
|
||||||
|
#include "sectorset.h"
|
||||||
|
#include "imagewriter/imagewriter.h"
|
||||||
|
#include "fmt/format.h"
|
||||||
|
#include "ldbs.h"
|
||||||
|
#include <algorithm>
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
static const char LABEL[] = "FluxEngine image";
|
||||||
|
|
||||||
|
static void write_and_update_checksum(ByteWriter& bw, uint32_t& checksum, const Bytes& data)
|
||||||
|
{
|
||||||
|
ByteReader br(data);
|
||||||
|
while (!br.eof())
|
||||||
|
{
|
||||||
|
uint32_t i = br.read_be16();
|
||||||
|
checksum += i;
|
||||||
|
checksum = (checksum >> 1) | (checksum << 31);
|
||||||
|
bw.write_be16(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class DiskCopyImageWriter : public ImageWriter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DiskCopyImageWriter(const SectorSet& sectors, const ImageSpec& spec):
|
||||||
|
ImageWriter(sectors, spec)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void writeImage()
|
||||||
|
{
|
||||||
|
bool mfm = false;
|
||||||
|
|
||||||
|
if (spec.bytes == 524)
|
||||||
|
{
|
||||||
|
/* GCR disk */
|
||||||
|
}
|
||||||
|
else if (spec.bytes == 512)
|
||||||
|
{
|
||||||
|
/* MFM disk */
|
||||||
|
mfm = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Error() << "this image is not compatible with the DiskCopy 4.2 format";
|
||||||
|
|
||||||
|
|
||||||
|
std::cout << "writing DiskCopy 4.2 image\n"
|
||||||
|
<< fmt::format("{} tracks, {} heads, {} sectors, {} bytes per sector; {}\n",
|
||||||
|
spec.cylinders, spec.heads, spec.sectors, spec.bytes,
|
||||||
|
mfm ? "MFM" : "GCR");
|
||||||
|
|
||||||
|
auto sectors_per_track = [&](int track) -> int
|
||||||
|
{
|
||||||
|
if (mfm)
|
||||||
|
return spec.sectors;
|
||||||
|
|
||||||
|
if (track < 16)
|
||||||
|
return 12;
|
||||||
|
if (track < 32)
|
||||||
|
return 11;
|
||||||
|
if (track < 48)
|
||||||
|
return 10;
|
||||||
|
if (track < 64)
|
||||||
|
return 9;
|
||||||
|
return 8;
|
||||||
|
};
|
||||||
|
|
||||||
|
Bytes image;
|
||||||
|
ByteWriter bw(image);
|
||||||
|
|
||||||
|
/* Write the actual sectr data. */
|
||||||
|
|
||||||
|
uint32_t dataChecksum = 0;
|
||||||
|
uint32_t tagChecksum = 0;
|
||||||
|
uint32_t offset = 0x54;
|
||||||
|
uint32_t sectorDataStart = offset;
|
||||||
|
for (int track = 0; track < spec.cylinders; track++)
|
||||||
|
{
|
||||||
|
for (int head = 0; head < spec.heads; head++)
|
||||||
|
{
|
||||||
|
int sectorCount = sectors_per_track(track);
|
||||||
|
for (int sectorId = 0; sectorId < sectorCount; sectorId++)
|
||||||
|
{
|
||||||
|
const auto& sector = sectors.get(track, head, sectorId);
|
||||||
|
if (sector)
|
||||||
|
{
|
||||||
|
bw.seek(offset);
|
||||||
|
write_and_update_checksum(bw, dataChecksum, sector->data.slice(0, 512));
|
||||||
|
}
|
||||||
|
offset += 512;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uint32_t sectorDataEnd = offset;
|
||||||
|
if (!mfm)
|
||||||
|
{
|
||||||
|
for (int track = 0; track < spec.cylinders; track++)
|
||||||
|
{
|
||||||
|
for (int head = 0; head < spec.heads; head++)
|
||||||
|
{
|
||||||
|
int sectorCount = sectors_per_track(track);
|
||||||
|
for (int sectorId = 0; sectorId < sectorCount; sectorId++)
|
||||||
|
{
|
||||||
|
const auto& sector = sectors.get(track, head, sectorId);
|
||||||
|
if (sector)
|
||||||
|
{
|
||||||
|
bw.seek(offset);
|
||||||
|
write_and_update_checksum(bw, tagChecksum, sector->data.slice(512, 12));
|
||||||
|
}
|
||||||
|
offset += 12;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uint32_t tagDataEnd = offset;
|
||||||
|
|
||||||
|
/* Write the header. */
|
||||||
|
|
||||||
|
uint8_t encoding;
|
||||||
|
uint8_t format;
|
||||||
|
if (mfm)
|
||||||
|
{
|
||||||
|
format = 0x22;
|
||||||
|
if (spec.sectors == 18)
|
||||||
|
encoding = 3;
|
||||||
|
else
|
||||||
|
encoding = 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (spec.heads == 2)
|
||||||
|
{
|
||||||
|
encoding = 1;
|
||||||
|
format = 0x22;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
encoding = 0;
|
||||||
|
format = 0x02;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bw.seek(0);
|
||||||
|
bw.write_8(sizeof(LABEL));
|
||||||
|
bw.append(LABEL);
|
||||||
|
bw.seek(0x40);
|
||||||
|
bw.write_be32(sectorDataEnd - sectorDataStart); /* data size */
|
||||||
|
bw.write_be32(tagDataEnd - sectorDataEnd); /* tag size */
|
||||||
|
bw.write_be32(dataChecksum); /* data checksum */
|
||||||
|
bw.write_be32(tagChecksum); /* tag checksum */
|
||||||
|
bw.write_8(encoding); /* encoding */
|
||||||
|
bw.write_8(format); /* format byte */
|
||||||
|
bw.write_be16(0x0100); /* magic number */
|
||||||
|
|
||||||
|
image.writeToFile(spec.filename);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::unique_ptr<ImageWriter> ImageWriter::createDiskCopyImageWriter(
|
||||||
|
const SectorSet& sectors, const ImageSpec& spec)
|
||||||
|
{
|
||||||
|
return std::unique_ptr<ImageWriter>(new DiskCopyImageWriter(sectors, spec));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -13,6 +13,7 @@ std::map<std::string, ImageWriter::Constructor> ImageWriter::formats =
|
|||||||
{".adf", ImageWriter::createImgImageWriter},
|
{".adf", ImageWriter::createImgImageWriter},
|
||||||
{".d64", ImageWriter::createD64ImageWriter},
|
{".d64", ImageWriter::createD64ImageWriter},
|
||||||
{".d81", ImageWriter::createImgImageWriter},
|
{".d81", ImageWriter::createImgImageWriter},
|
||||||
|
{".diskcopy", ImageWriter::createDiskCopyImageWriter},
|
||||||
{".img", ImageWriter::createImgImageWriter},
|
{".img", ImageWriter::createImgImageWriter},
|
||||||
{".ldbs", ImageWriter::createLDBSImageWriter},
|
{".ldbs", ImageWriter::createLDBSImageWriter},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ private:
|
|||||||
const SectorSet& sectors, const ImageSpec& spec);
|
const SectorSet& sectors, const ImageSpec& spec);
|
||||||
static std::unique_ptr<ImageWriter> createD64ImageWriter(
|
static std::unique_ptr<ImageWriter> createD64ImageWriter(
|
||||||
const SectorSet& sectors, const ImageSpec& spec);
|
const SectorSet& sectors, const ImageSpec& spec);
|
||||||
|
static std::unique_ptr<ImageWriter> createDiskCopyImageWriter(
|
||||||
|
const SectorSet& sectors, const ImageSpec& spec);
|
||||||
|
|
||||||
static Constructor findConstructor(const ImageSpec& spec);
|
static Constructor findConstructor(const ImageSpec& spec);
|
||||||
|
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ void Track::readFluxmap()
|
|||||||
fluxmap = fluxsource->readFlux(physicalTrack, physicalSide);
|
fluxmap = fluxsource->readFlux(physicalTrack, physicalSide);
|
||||||
std::cout << fmt::format(
|
std::cout << fmt::format(
|
||||||
"{0} ms in {1} bytes\n",
|
"{0} ms in {1} bytes\n",
|
||||||
int(fluxmap->duration()/1e6),
|
fluxmap->duration()/1e6,
|
||||||
fluxmap->bytes());
|
fluxmap->bytes());
|
||||||
if (outputFluxSink)
|
if (outputFluxSink)
|
||||||
outputFluxSink->writeFlux(physicalTrack, physicalSide, *fluxmap);
|
outputFluxSink->writeFlux(physicalTrack, physicalSide, *fluxmap);
|
||||||
|
|||||||
@@ -47,8 +47,8 @@ void visualiseSectorsToFile(const SectorSet& sectors, const std::string& filenam
|
|||||||
|
|
||||||
auto drawArc = [&](const std::unique_ptr<Sector>& sector, nanoseconds_t start, nanoseconds_t end, const std::string& colour)
|
auto drawArc = [&](const std::unique_ptr<Sector>& sector, nanoseconds_t start, nanoseconds_t end, const std::string& colour)
|
||||||
{
|
{
|
||||||
start %= period*1000000;
|
start = fmod(start, period*1000000.0);
|
||||||
end %= period*1000000;
|
end = fmod(end, period*1000000.0);
|
||||||
if (end < start)
|
if (end < start)
|
||||||
end += period*1000000;
|
end += period*1000000;
|
||||||
|
|
||||||
|
|||||||
@@ -154,6 +154,7 @@ buildlibrary libbackend.a \
|
|||||||
lib/imagereader/imagereader.cc \
|
lib/imagereader/imagereader.cc \
|
||||||
lib/imagereader/imgimagereader.cc \
|
lib/imagereader/imgimagereader.cc \
|
||||||
lib/imagewriter/d64imagewriter.cc \
|
lib/imagewriter/d64imagewriter.cc \
|
||||||
|
lib/imagewriter/diskcopyimagewriter.cc \
|
||||||
lib/imagewriter/imagewriter.cc \
|
lib/imagewriter/imagewriter.cc \
|
||||||
lib/imagewriter/imgimagewriter.cc \
|
lib/imagewriter/imgimagewriter.cc \
|
||||||
lib/imagewriter/ldbsimagewriter.cc \
|
lib/imagewriter/ldbsimagewriter.cc \
|
||||||
|
|||||||
@@ -18,6 +18,11 @@ static SettableFlag fortyTrackMode(
|
|||||||
"set 48 tpi mode; only every other physical track is emitted"
|
"set 48 tpi mode; only every other physical track is emitted"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
static SettableFlag indexedMode(
|
||||||
|
{ "--indexed", "-i" },
|
||||||
|
"align data to track boundaries"
|
||||||
|
);
|
||||||
|
|
||||||
static SettableFlag singleSided(
|
static SettableFlag singleSided(
|
||||||
{ "--single-sided", "-s" },
|
{ "--single-sided", "-s" },
|
||||||
"only emit side 0"
|
"only emit side 0"
|
||||||
@@ -45,14 +50,18 @@ static void write_le32(uint8_t dest[4], uint32_t v)
|
|||||||
dest[3] = v >> 24;
|
dest[3] = v >> 24;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void appendChecksum(uint32_t& checksum, const Bytes& bytes)
|
||||||
|
{
|
||||||
|
ByteReader br(bytes);
|
||||||
|
while (!br.eof())
|
||||||
|
checksum += br.read_8();
|
||||||
|
}
|
||||||
|
|
||||||
static int strackno(int track, int side)
|
static int strackno(int track, int side)
|
||||||
{
|
{
|
||||||
if (fortyTrackMode)
|
if (fortyTrackMode)
|
||||||
track /= 2;
|
track /= 2;
|
||||||
if (singleSided)
|
return (track << 1) | side;
|
||||||
return track;
|
|
||||||
else
|
|
||||||
return (track << 1) | side;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int mainConvertFluxToScp(int argc, const char* argv[])
|
int mainConvertFluxToScp(int argc, const char* argv[])
|
||||||
@@ -90,7 +99,8 @@ int mainConvertFluxToScp(int argc, const char* argv[])
|
|||||||
fileheader.revolutions = 5;
|
fileheader.revolutions = 5;
|
||||||
fileheader.start_track = 0;
|
fileheader.start_track = 0;
|
||||||
fileheader.end_track = maxStrack;
|
fileheader.end_track = maxStrack;
|
||||||
fileheader.flags = SCP_FLAG_INDEXED | (fortyTrackMode ? 0 : SCP_FLAG_96TPI);
|
fileheader.flags = (indexedMode ? SCP_FLAG_INDEXED : 0)
|
||||||
|
| (fortyTrackMode ? 0 : SCP_FLAG_96TPI);
|
||||||
fileheader.cell_width = 0;
|
fileheader.cell_width = 0;
|
||||||
fileheader.heads = singleSided ? 1 : 0;
|
fileheader.heads = singleSided ? 1 : 0;
|
||||||
|
|
||||||
@@ -104,9 +114,15 @@ int mainConvertFluxToScp(int argc, const char* argv[])
|
|||||||
for (int side = 0; side <= maxside; side++)
|
for (int side = 0; side <= maxside; side++)
|
||||||
{
|
{
|
||||||
int strack = strackno(track, side);
|
int strack = strackno(track, side);
|
||||||
std::cout << fmt::format("FE track {}.{}, SCP track {}: ", track, side, strack) << std::flush;
|
std::cout << fmt::format("{}.{}: ", track, side) << std::flush;
|
||||||
|
|
||||||
auto fluxmap = sqlReadFlux(inputDb, track, side);
|
auto fluxmap = sqlReadFlux(inputDb, track, side);
|
||||||
|
if (fluxmap->bytes() == 0)
|
||||||
|
{
|
||||||
|
std::cout << "missing\n";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
ScpTrack trackheader = {0};
|
ScpTrack trackheader = {0};
|
||||||
trackheader.track_id[0] = 'T';
|
trackheader.track_id[0] = 'T';
|
||||||
trackheader.track_id[1] = 'R';
|
trackheader.track_id[1] = 'R';
|
||||||
@@ -117,6 +133,9 @@ int mainConvertFluxToScp(int argc, const char* argv[])
|
|||||||
Bytes fluxdata;
|
Bytes fluxdata;
|
||||||
ByteWriter fluxdataWriter(fluxdata);
|
ByteWriter fluxdataWriter(fluxdata);
|
||||||
|
|
||||||
|
if (indexedMode)
|
||||||
|
fmr.findEvent(F_BIT_INDEX);
|
||||||
|
|
||||||
int revolution = 0;
|
int revolution = 0;
|
||||||
unsigned revTicks = 0;
|
unsigned revTicks = 0;
|
||||||
unsigned totalTicks = 0;
|
unsigned totalTicks = 0;
|
||||||
@@ -159,7 +178,7 @@ int mainConvertFluxToScp(int argc, const char* argv[])
|
|||||||
trackdataWriter += Bytes((uint8_t*)&trackheader, sizeof(trackheader));
|
trackdataWriter += Bytes((uint8_t*)&trackheader, sizeof(trackheader));
|
||||||
trackdataWriter += fluxdata;
|
trackdataWriter += fluxdata;
|
||||||
|
|
||||||
std::cout << fmt::format("{} ms in {} bytes\n",
|
std::cout << fmt::format("{:.3f} ms in {} bytes\n",
|
||||||
totalTicks * MS_PER_TICK,
|
totalTicks * MS_PER_TICK,
|
||||||
fluxdata.size());
|
fluxdata.size());
|
||||||
}
|
}
|
||||||
@@ -167,6 +186,13 @@ int mainConvertFluxToScp(int argc, const char* argv[])
|
|||||||
|
|
||||||
sqlClose(inputDb);
|
sqlClose(inputDb);
|
||||||
|
|
||||||
|
uint32_t checksum = 0;
|
||||||
|
appendChecksum(checksum,
|
||||||
|
Bytes((const uint8_t*) &fileheader, sizeof(fileheader))
|
||||||
|
.slice(0x10));
|
||||||
|
appendChecksum(checksum, trackdata);
|
||||||
|
write_le32(fileheader.checksum, checksum);
|
||||||
|
|
||||||
std::cout << "Writing output file...\n";
|
std::cout << "Writing output file...\n";
|
||||||
std::ofstream of(filenames[1], std::ios::out | std::ios::binary);
|
std::ofstream of(filenames[1], std::ios::out | std::ios::binary);
|
||||||
if (!of.is_open())
|
if (!of.is_open())
|
||||||
|
|||||||
@@ -28,15 +28,11 @@ static void check_for_error()
|
|||||||
|
|
||||||
static int trackno(int strack)
|
static int trackno(int strack)
|
||||||
{
|
{
|
||||||
if (startSide == endSide)
|
|
||||||
return strack;
|
|
||||||
return strack >> 1;
|
return strack >> 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int headno(int strack)
|
static int headno(int strack)
|
||||||
{
|
{
|
||||||
if (startSide == endSide)
|
|
||||||
return startSide;
|
|
||||||
return strack & 1;
|
return strack & 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,6 +61,8 @@ static void read_header()
|
|||||||
static void read_track(int strack)
|
static void read_track(int strack)
|
||||||
{
|
{
|
||||||
uint32_t offset = Bytes(header.track[strack], 4).reader().read_le32();
|
uint32_t offset = Bytes(header.track[strack], 4).reader().read_le32();
|
||||||
|
if (offset == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
ScpTrack trackheader;
|
ScpTrack trackheader;
|
||||||
inputFile.seekg(offset, std::ios::beg);
|
inputFile.seekg(offset, std::ios::beg);
|
||||||
@@ -112,7 +110,7 @@ static void read_track(int strack)
|
|||||||
inputBytes += datalength*2;
|
inputBytes += datalength*2;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << fmt::format(" {} ms in {} input bytes and {} output bytes\n",
|
std::cout << fmt::format(" {:.3f} ms in {} input bytes and {} output bytes\n",
|
||||||
fluxmap.duration() / 1e6, inputBytes, fluxmap.bytes());
|
fluxmap.duration() / 1e6, inputBytes, fluxmap.bytes());
|
||||||
sqlWriteFlux(outputDb, trackno(strack), headno(strack), fluxmap);
|
sqlWriteFlux(outputDb, trackno(strack), headno(strack), fluxmap);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user