Skip to content

Commit

Permalink
Merge pull request #92 from davidgiven/d64
Browse files Browse the repository at this point in the history
Add write-only support for D64 disk images.
  • Loading branch information
davidgiven authored Aug 15, 2019
2 parents 29db675 + a626d5f commit d6ae373
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 9 deletions.
15 changes: 7 additions & 8 deletions doc/disk-c64.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ computer](https://ilesj.wordpress.com/2014/05/14/1541-why-so-complicated/) of
300 bytes per second (!). (The drive itself could transfer data reasonably
quickly.)

A standard 1541 disk has 35 tracks of 17 to 20 sectors, each 256 bytes long.
A standard 1541 disk has 35 tracks of 17 to 21 sectors, each 256 bytes long.

Reading discs
-------------
Expand All @@ -34,15 +34,14 @@ Just do:
fluxengine read c64
```

You should end up with an `c64.img` which is 187136 bytes long (for a normal
1541 disk).
You should end up with an `c64.d64` file which is 174848 bytes long. You can
load this straight into a Commodore 64 emulator such as
[VICE](http://vice-emu.sourceforge.net/).

**Big warning!** The image may not work in an emulator. Commodore 64 disk images are
**Big warning!** Commodore 64 disk images are
complicated due to the way the tracks are different sizes and the odd sector
size. FluxEngine chooses to store them in a simple 256 x 20 x 35 layout,
with holes where missing sectors should be. This was easiest. If anyone can
suggest a better way, please [get in
touch](https://github.com/davidgiven/fluxengine/issues/new).
size, so you need the special D64 or LDBS output formats to represent them
sensibly. Don't use IMG unless you know what you're doing.

Useful references
-----------------
Expand Down
9 changes: 9 additions & 0 deletions doc/using.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,15 @@ based on the extension:
it doesn't store a lot of the more esoteric LDBS features like format
types, timings, and data rates.
- `.d64`: the venerable Commodore 64 disk image format as used by the 1540,
1541, etc. This is a special-purpose format due to the weird layout of
1540 disks and while you can use this for non-Commodore disks the result
will be gibberish. Use this to image Commodore 64 disks and load the
result into an emulator.
FluxEngine's D64 support is currently limited to write only. It will work
with up to 40 logical tracks.
### High density disks
High density disks use a different magnetic medium to low and double density
Expand Down
64 changes: 64 additions & 0 deletions lib/imagewriter/d64imagewriter.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#include "globals.h"
#include "image.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 int sectors_per_track(int track)
{
if (track < 17)
return 21;
if (track < 24)
return 19;
if (track < 30)
return 18;
return 17;
}

class D64ImageWriter : public ImageWriter
{
public:
D64ImageWriter(const SectorSet& sectors, const ImageSpec& spec):
ImageWriter(sectors, spec)
{}

void writeImage()
{
std::cout << "writing D64 triangular image\n";

std::ofstream outputFile(spec.filename, std::ios::out | std::ios::binary);
if (!outputFile.is_open())
Error() << "cannot open output file";

uint32_t offset = 0;
for (int track = 0; track < 40; track++)
{
int sectorCount = sectors_per_track(track);
for (int sectorId = 0; sectorId < sectorCount; sectorId++)
{
const auto& sector = sectors.get(track, 0, sectorId);
if (sector)
{
outputFile.seekp(offset);
outputFile.write((const char*) sector->data.cbegin(), 256);
}

offset += 256;
}
}
}
};

std::unique_ptr<ImageWriter> ImageWriter::createD64ImageWriter(
const SectorSet& sectors, const ImageSpec& spec)
{
return std::unique_ptr<ImageWriter>(new D64ImageWriter(sectors, spec));
}

2 changes: 2 additions & 0 deletions lib/imagewriter/imagewriter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ std::unique_ptr<ImageWriter> ImageWriter::create(const SectorSet& sectors, const
return createImgImageWriter(sectors, spec);
else if (ends_with(filename, ".ldbs"))
return createLDBSImageWriter(sectors, spec);
else if (ends_with(filename, ".d64"))
return createD64ImageWriter(sectors, spec);

Error() << "unrecognised image filename extension";
return std::unique_ptr<ImageWriter>();
Expand Down
2 changes: 2 additions & 0 deletions lib/imagewriter/imagewriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ class ImageWriter
const SectorSet& sectors, const ImageSpec& spec);
static std::unique_ptr<ImageWriter> createLDBSImageWriter(
const SectorSet& sectors, const ImageSpec& spec);
static std::unique_ptr<ImageWriter> createD64ImageWriter(
const SectorSet& sectors, const ImageSpec& spec);

public:
virtual void adjustGeometry();
Expand Down
1 change: 1 addition & 0 deletions mkninja.sh
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ buildlibrary libfmt.a \
buildlibrary libbackend.a \
lib/imagereader/imagereader.cc \
lib/imagereader/imgimagereader.cc \
lib/imagewriter/d64imagewriter.cc \
lib/imagewriter/imagewriter.cc \
lib/imagewriter/imgimagewriter.cc \
lib/imagewriter/ldbsimagewriter.cc \
Expand Down
2 changes: 1 addition & 1 deletion src/fe-readc64.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ static FlagGroup flags { &readerFlags };
int mainReadC64(int argc, const char* argv[])
{
setReaderDefaultSource(":t=0-79x2:s=0");
setReaderDefaultOutput("c64.img");
setReaderDefaultOutput("c64.d64");
setReaderRevolutions(2);
flags.parseFlags(argc, argv);

Expand Down

0 comments on commit d6ae373

Please sign in to comment.