mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-31 11:17:01 -07:00
First draft of the DiskCopy 4.2 image writer.
This commit is contained in:
13
lib/bytes.h
13
lib/bytes.h
@@ -1,6 +1,8 @@
|
||||
#ifndef BYTES_H
|
||||
#define BYTES_H
|
||||
|
||||
#include <string.h>
|
||||
|
||||
class ByteReader;
|
||||
class ByteWriter;
|
||||
|
||||
@@ -10,6 +12,7 @@ public:
|
||||
Bytes();
|
||||
Bytes(unsigned size);
|
||||
Bytes(const uint8_t* ptr, size_t len);
|
||||
Bytes(const std::string& 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, unsigned start, unsigned end);
|
||||
@@ -271,6 +274,16 @@ public:
|
||||
|
||||
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)
|
||||
{
|
||||
return *this += data;
|
||||
|
||||
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},
|
||||
{".d64", ImageWriter::createD64ImageWriter},
|
||||
{".d81", ImageWriter::createImgImageWriter},
|
||||
{".diskcopy", ImageWriter::createDiskCopyImageWriter},
|
||||
{".img", ImageWriter::createImgImageWriter},
|
||||
{".ldbs", ImageWriter::createLDBSImageWriter},
|
||||
};
|
||||
|
||||
@@ -29,6 +29,8 @@ private:
|
||||
const SectorSet& sectors, const ImageSpec& spec);
|
||||
static std::unique_ptr<ImageWriter> createD64ImageWriter(
|
||||
const SectorSet& sectors, const ImageSpec& spec);
|
||||
static std::unique_ptr<ImageWriter> createDiskCopyImageWriter(
|
||||
const SectorSet& sectors, const ImageSpec& spec);
|
||||
|
||||
static Constructor findConstructor(const ImageSpec& spec);
|
||||
|
||||
|
||||
@@ -154,6 +154,7 @@ buildlibrary libbackend.a \
|
||||
lib/imagereader/imagereader.cc \
|
||||
lib/imagereader/imgimagereader.cc \
|
||||
lib/imagewriter/d64imagewriter.cc \
|
||||
lib/imagewriter/diskcopyimagewriter.cc \
|
||||
lib/imagewriter/imagewriter.cc \
|
||||
lib/imagewriter/imgimagewriter.cc \
|
||||
lib/imagewriter/ldbsimagewriter.cc \
|
||||
|
||||
Reference in New Issue
Block a user