mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-31 11:17:01 -07:00
Compare commits
10 Commits
FluxEngine
...
FluxEngine
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
28d0ce765e | ||
|
|
4954d33307 | ||
|
|
55f3354287 | ||
|
|
d6ae373fa8 | ||
|
|
a626d5f9a0 | ||
|
|
29db67528d | ||
|
|
31d7477c6a | ||
|
|
56af9eaf18 | ||
|
|
5de0636fe7 | ||
|
|
f9117b8d11 |
@@ -15,7 +15,7 @@ install:
|
||||
|
||||
build_script:
|
||||
- make
|
||||
- zip -9 fluxengine.zip fluxengine.exe brother120tool.exe
|
||||
- zip -9 fluxengine.zip fluxengine.exe brother120tool.exe FluxEngine.cydsn/CortexM3/ARM_GCC_541/Release/FluxEngine.hex
|
||||
|
||||
artifacts:
|
||||
- path: fluxengine.zip
|
||||
|
||||
4626
FluxEngine.cydsn/CortexM3/ARM_GCC_541/Release/FluxEngine.hex
Normal file
4626
FluxEngine.cydsn/CortexM3/ARM_GCC_541/Release/FluxEngine.hex
Normal file
File diff suppressed because it is too large
Load Diff
@@ -3700,6 +3700,6 @@
|
||||
</ignored_deps>
|
||||
</CyGuid_495451fe-d201-4d01-b22d-5d3f5609ac37>
|
||||
<boot_component v="" />
|
||||
<current_generation v="60" />
|
||||
<current_generation v="68" />
|
||||
</CyGuid_fec8f9e8-2365-4bdb-96d3-a4380222e01b>
|
||||
</CyXmlSerializer>
|
||||
@@ -103,7 +103,43 @@ the unconnected pins and solder a short piece of wire to a GND pin on the
|
||||
board. Alternatively you'll need to splice it into your drive's power supply
|
||||
cable somehow. (The black one.)
|
||||
|
||||
## Building the firmware
|
||||
## Programming the board
|
||||
|
||||
You've got two options here. You can either use the precompiled firmware
|
||||
supplied with the source, or else install the Cypress SDK and build it
|
||||
yourself. If you want to hack the firmware source you need the latter, but
|
||||
if you trust me to do it for you use the precompiled firmware. In either
|
||||
case you'll need Windows and have to install some Cypress stuff.
|
||||
|
||||
**Before you read this:** If you're on Windows, good news! You can download a
|
||||
precompiled version of the FluxEngine client and precompiled firmware [from
|
||||
the GitHub releases
|
||||
page](https://github.com/davidgiven/fluxengine/releases/latest). Simply unzip
|
||||
it somewhere and run the `.exe` files from a `cmd` window (or other shell).
|
||||
Follow the instructions below to program the board with the firmware.
|
||||
|
||||
### Using the precompiled firmware
|
||||
|
||||
On your Windows machine, [install the PSoC
|
||||
Programmer](https://www.cypress.com/products/psoc-programming-solutions).
|
||||
**Note:** _not_ the Cypress Programmer, which is for a different board!
|
||||
Cypress will make you register.
|
||||
|
||||
Once done, run it. Plug the blunt end of the FluxEngine board into a USB
|
||||
port (the end which is a USB connector). The programmer should detect it
|
||||
and report it as a KitProg. You may be prompted to upgrade the programmer
|
||||
hardware; if so, follow the instructions and do it.
|
||||
|
||||
Now go to File -> File Load and open
|
||||
`FluxEngine.cydsn/CortexM3/ARM_GCC_541/Release/FluxEngine.hex` in the
|
||||
project. If you're on Windows, the precompiled zipfile also contains a copy
|
||||
of this file. Press the Program button (the one in the toolbar marked with a
|
||||
down arrow). Stuff will happen and you should be left with three green boxes
|
||||
in the status bar and 'Programming Succeeded' at the top of the log window.
|
||||
|
||||
You're done. You can unplug the board and close the programmer.
|
||||
|
||||
### Building the firmware yourself
|
||||
|
||||
On your Windows machine, [install the Cypress SDK and CY8CKIT-059
|
||||
BSP](http://www.cypress.com/documentation/development-kitsboards/cy8ckit-059-psoc-5lp-prototyping-kit-onboard-programmer-and).
|
||||
@@ -118,7 +154,7 @@ tutorial and making the LED on your board flash. It'll tell you where all the
|
||||
controls are and how to program the board. Remember that the big end of the
|
||||
board plugs into your computer for programming.
|
||||
|
||||
When you're ready, open the `FluxEngine.cydsn/FluxEngine.cywrk` workspace,
|
||||
When you're ready, open the `FluxEngine.cydsn/FluxEngine.cyprj` project,
|
||||
pick 'Program' from the menu, and the firmware should compile and be
|
||||
programmed onto your board.
|
||||
|
||||
@@ -139,11 +175,6 @@ the port and proceed normally.
|
||||
|
||||
## Building the client
|
||||
|
||||
**Before you read this:** If you're on Windows, good news! You can download a
|
||||
*precompiled version of the FluxEngine client [from the GitHub releases
|
||||
*page](https://github.com/davidgiven/fluxengine/releases/latest). Simply unzip
|
||||
*it somewhere and run it from a `cmd` window (or other shell).
|
||||
|
||||
The client software is where the intelligence, such as it is, is. It's pretty
|
||||
generic libusb stuff and should build and run on Windows, Linux and OSX as
|
||||
well, although on Windows it'll need MSYS2 and mingw32. You'll need to
|
||||
|
||||
@@ -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
|
||||
-------------
|
||||
@@ -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
|
||||
-----------------
|
||||
|
||||
28
doc/using.md
28
doc/using.md
@@ -129,6 +129,34 @@ based on the extension:
|
||||
geometry will be autodetected if left unspecified. For input files you
|
||||
normally have to specify it.
|
||||
|
||||
- `.ldbs`: John Elliott's [LDBS disk image
|
||||
format](http://www.seasip.info/Unix/LibDsk/ldbs.html), which is
|
||||
consumable by the [libdsk](http://www.seasip.info/Unix/LibDsk/) suite of
|
||||
tools. This allows things like variable numbers of sectors per track
|
||||
(e.g. Macintosh or Commodore 64) and also provides information about
|
||||
whether sectors were read correctly. You can use libdsk to convert this
|
||||
to other formats, using a command like this:
|
||||
|
||||
```
|
||||
$ dsktrans out.ldbs -otype tele out.td0
|
||||
```
|
||||
|
||||
...to convert to TeleDisk format. (Note you have to use dsktrans rather
|
||||
than dskconv due to a minor bug in the geometry hadnling.)
|
||||
|
||||
FluxEngine's LDBS support is currently limited to write only, and
|
||||
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
|
||||
|
||||
11
lib/bytes.cc
11
lib/bytes.cc
@@ -2,6 +2,7 @@
|
||||
#include "bytes.h"
|
||||
#include "fmt/format.h"
|
||||
#include "common/crunch.h"
|
||||
#include <fstream>
|
||||
#include <zlib.h>
|
||||
|
||||
static std::shared_ptr<std::vector<uint8_t>> createVector(unsigned size)
|
||||
@@ -280,6 +281,16 @@ Bytes Bytes::uncrunch() const
|
||||
return output;
|
||||
}
|
||||
|
||||
void Bytes::writeToFile(const std::string& filename) const
|
||||
{
|
||||
std::ofstream f(filename, std::ios::out | std::ios::binary);
|
||||
if (!f.is_open())
|
||||
Error() << fmt::format("cannot open output file '{}'", filename);
|
||||
|
||||
f.write((const char*) cbegin(), size());
|
||||
f.close();
|
||||
}
|
||||
|
||||
ByteReader Bytes::reader() const
|
||||
{
|
||||
return ByteReader(*this);
|
||||
|
||||
@@ -56,6 +56,8 @@ public:
|
||||
ByteReader reader() const;
|
||||
ByteWriter writer();
|
||||
|
||||
void writeToFile(const std::string& filename) const;
|
||||
|
||||
private:
|
||||
std::shared_ptr<std::vector<uint8_t>> _data;
|
||||
unsigned _low;
|
||||
|
||||
64
lib/imagewriter/d64imagewriter.cc
Normal file
64
lib/imagewriter/d64imagewriter.cc
Normal file
@@ -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));
|
||||
}
|
||||
|
||||
@@ -20,6 +20,10 @@ std::unique_ptr<ImageWriter> ImageWriter::create(const SectorSet& sectors, const
|
||||
|
||||
if (ends_with(filename, ".img") || ends_with(filename, ".adf"))
|
||||
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>();
|
||||
|
||||
@@ -16,6 +16,10 @@ public:
|
||||
private:
|
||||
static std::unique_ptr<ImageWriter> createImgImageWriter(
|
||||
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();
|
||||
|
||||
107
lib/imagewriter/ldbsimagewriter.cc
Normal file
107
lib/imagewriter/ldbsimagewriter.cc
Normal file
@@ -0,0 +1,107 @@
|
||||
#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>
|
||||
|
||||
class LDBSImageWriter : public ImageWriter
|
||||
{
|
||||
public:
|
||||
LDBSImageWriter(const SectorSet& sectors, const ImageSpec& spec):
|
||||
ImageWriter(sectors, spec)
|
||||
{}
|
||||
|
||||
void writeImage()
|
||||
{
|
||||
LDBS ldbs;
|
||||
|
||||
unsigned numCylinders = spec.cylinders;
|
||||
unsigned numHeads = spec.heads;
|
||||
unsigned numSectors = spec.sectors;
|
||||
unsigned numBytes = spec.bytes;
|
||||
std::cout << fmt::format("writing {} tracks, {} heads, {} sectors, {} bytes per sector",
|
||||
numCylinders, numHeads,
|
||||
numSectors, numBytes)
|
||||
<< std::endl;
|
||||
|
||||
Bytes trackDirectory;
|
||||
ByteWriter trackDirectoryWriter(trackDirectory);
|
||||
int trackDirectorySize = 0;
|
||||
trackDirectoryWriter.write_le16(0);
|
||||
|
||||
for (int track = 0; track < numCylinders; track++)
|
||||
{
|
||||
for (int head = 0; head < numHeads; head++)
|
||||
{
|
||||
Bytes trackHeader;
|
||||
ByteWriter trackHeaderWriter(trackHeader);
|
||||
|
||||
int actualSectors = 0;
|
||||
for (int sectorId = 0; sectorId < numSectors; sectorId++)
|
||||
{
|
||||
const auto& sector = sectors.get(track, head, sectorId);
|
||||
if (sector)
|
||||
actualSectors++;
|
||||
}
|
||||
|
||||
trackHeaderWriter.write_le16(0x000C); /* offset of sector headers */
|
||||
trackHeaderWriter.write_le16(0x0012); /* length of each sector descriptor */
|
||||
trackHeaderWriter.write_le16(actualSectors);
|
||||
trackHeaderWriter.write_8(0); /* data rate unknown */
|
||||
trackHeaderWriter.write_8(0); /* recording mode unknown */
|
||||
trackHeaderWriter.write_8(0); /* format gap length */
|
||||
trackHeaderWriter.write_8(0); /* filler byte */
|
||||
trackHeaderWriter.write_le16(0); /* approximate track length */
|
||||
|
||||
for (int sectorId = 0; sectorId < numSectors; sectorId++)
|
||||
{
|
||||
const auto& sector = sectors.get(track, head, sectorId);
|
||||
if (sector)
|
||||
{
|
||||
uint32_t sectorLabel = (('S') << 24) | ((track & 0xff) << 16) | (head << 8) | sectorId;
|
||||
uint32_t sectorAddress = ldbs.put(sector->data, sectorLabel);
|
||||
|
||||
trackHeaderWriter.write_8(track);
|
||||
trackHeaderWriter.write_8(head);
|
||||
trackHeaderWriter.write_8(sectorId);
|
||||
trackHeaderWriter.write_8(0); /* power-of-two size */
|
||||
trackHeaderWriter.write_8((sector->status == Sector::OK) ? 0x00 : 0x20); /* 8272 status 1 */
|
||||
trackHeaderWriter.write_8(0); /* 8272 status 2 */
|
||||
trackHeaderWriter.write_8(1); /* number of copies */
|
||||
trackHeaderWriter.write_8(0); /* filler byte */
|
||||
trackHeaderWriter.write_le32(sectorAddress);
|
||||
trackHeaderWriter.write_le16(0); /* trailing bytes */
|
||||
trackHeaderWriter.write_le16(0); /* approximate offset */
|
||||
trackHeaderWriter.write_le16(sector->data.size());
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t trackLabel = (('T') << 24) | ((track & 0xff) << 16) | ((track >> 8) << 8) | head;
|
||||
uint32_t trackHeaderAddress = ldbs.put(trackHeader, trackLabel);
|
||||
trackDirectoryWriter.write_be32(trackLabel);
|
||||
trackDirectoryWriter.write_le32(trackHeaderAddress);
|
||||
trackDirectorySize++;
|
||||
}
|
||||
}
|
||||
|
||||
trackDirectoryWriter.seek(0);
|
||||
trackDirectoryWriter.write_le16(trackDirectorySize);
|
||||
|
||||
uint32_t trackDirectoryAddress = ldbs.put(trackDirectory, LDBS_TRACK_BLOCK);
|
||||
Bytes data = ldbs.write(trackDirectoryAddress);
|
||||
data.writeToFile(spec.filename);
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<ImageWriter> ImageWriter::createLDBSImageWriter(
|
||||
const SectorSet& sectors, const ImageSpec& spec)
|
||||
{
|
||||
return std::unique_ptr<ImageWriter>(new LDBSImageWriter(sectors, spec));
|
||||
}
|
||||
81
lib/ldbs.cc
Normal file
81
lib/ldbs.cc
Normal file
@@ -0,0 +1,81 @@
|
||||
#include "globals.h"
|
||||
#include <string.h>
|
||||
#include "bytes.h"
|
||||
#include "ldbs.h"
|
||||
#include "fmt/format.h"
|
||||
|
||||
LDBS::LDBS()
|
||||
{}
|
||||
|
||||
uint32_t LDBS::put(const Bytes& data, uint32_t type)
|
||||
{
|
||||
uint32_t address = top;
|
||||
Block& block = blocks[address];
|
||||
block.type = type;
|
||||
block.data = data;
|
||||
|
||||
top += data.size() + 20;
|
||||
return address;
|
||||
}
|
||||
|
||||
uint32_t LDBS::read(const Bytes& data)
|
||||
{
|
||||
ByteReader br(data);
|
||||
|
||||
br.seek(0);
|
||||
if ((br.read_be32() != LDBS_FILE_MAGIC)
|
||||
|| (br.read_be32() != LDBS_FILE_TYPE))
|
||||
Error() << "not a valid LDBS file";
|
||||
|
||||
uint32_t address = br.read_le32();
|
||||
br.skip(4);
|
||||
uint32_t trackDirectory = br.read_le32();
|
||||
|
||||
while (address)
|
||||
{
|
||||
br.seek(address);
|
||||
if (br.read_be32() != LDBS_BLOCK_MAGIC)
|
||||
Error() << fmt::format("invalid block at address 0x{:x}", address);
|
||||
|
||||
Block& block = blocks[address];
|
||||
block.type = br.read_be32();
|
||||
|
||||
uint32_t size = br.read_le32();
|
||||
br.skip(4);
|
||||
address = br.read_le32();
|
||||
|
||||
block.data.writer().append(br.read(size));
|
||||
}
|
||||
|
||||
top = data.size();
|
||||
return trackDirectory;
|
||||
}
|
||||
|
||||
const Bytes LDBS::write(uint32_t trackDirectory)
|
||||
{
|
||||
Bytes data(top);
|
||||
ByteWriter bw(data);
|
||||
|
||||
uint32_t previous = 0;
|
||||
for (const auto& e : blocks)
|
||||
{
|
||||
bw.seek(e.first);
|
||||
bw.write_be32(LDBS_BLOCK_MAGIC);
|
||||
bw.write_be32(e.second.type);
|
||||
bw.write_le32(e.second.data.size());
|
||||
bw.write_le32(e.second.data.size());
|
||||
bw.write_le32(previous);
|
||||
bw.append(e.second.data);
|
||||
|
||||
previous = e.first;
|
||||
}
|
||||
|
||||
bw.seek(0);
|
||||
bw.write_be32(LDBS_FILE_MAGIC);
|
||||
bw.write_be32(LDBS_FILE_TYPE);
|
||||
bw.write_le32(previous);
|
||||
bw.write_le32(0);
|
||||
bw.write_le32(trackDirectory);
|
||||
|
||||
return data;
|
||||
}
|
||||
41
lib/ldbs.h
Normal file
41
lib/ldbs.h
Normal file
@@ -0,0 +1,41 @@
|
||||
#ifndef LDBS_H
|
||||
#define LDBS_H
|
||||
|
||||
class Bytes;
|
||||
|
||||
/* A very simple interface to John Elliott's LDBS image format:
|
||||
* http://www.seasip.info/Unix/LibDsk/ldbs.html
|
||||
*/
|
||||
|
||||
#define LDBS_FILE_MAGIC 0x4C425301 /* "LBS\01" */
|
||||
#define LDBS_FILE_TYPE 0x44534B02 /* "DSK\02" */
|
||||
#define LDBS_BLOCK_MAGIC 0x4C444201 /* "LDB\01" */
|
||||
#define LDBS_TRACK_BLOCK 0x44495201 /* "DIR\01" */
|
||||
|
||||
class LDBS
|
||||
{
|
||||
public:
|
||||
LDBS();
|
||||
|
||||
public:
|
||||
const Bytes& get(uint32_t address) const
|
||||
{ return blocks.at(address).data; }
|
||||
|
||||
uint32_t put(const Bytes& data, uint32_t type);
|
||||
|
||||
public:
|
||||
const Bytes write(uint32_t trackDirectory);
|
||||
uint32_t read(const Bytes& bytes);
|
||||
|
||||
private:
|
||||
struct Block
|
||||
{
|
||||
uint32_t type;
|
||||
Bytes data;
|
||||
};
|
||||
|
||||
std::map<uint32_t, Block> blocks;
|
||||
unsigned top = 20;
|
||||
};
|
||||
|
||||
#endif
|
||||
24
mkninja.sh
24
mkninja.sh
@@ -137,6 +137,12 @@ buildlibrary libfmt.a \
|
||||
dep/fmt/posix.cc \
|
||||
|
||||
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 \
|
||||
arch/aeslanier/decoder.cc \
|
||||
arch/amiga/decoder.cc \
|
||||
arch/apple2/decoder.cc \
|
||||
@@ -168,13 +174,10 @@ buildlibrary libbackend.a \
|
||||
lib/fluxsource/kryoflux.cc \
|
||||
lib/fluxsource/sqlitefluxsource.cc \
|
||||
lib/fluxsource/streamfluxsource.cc \
|
||||
lib/imagereader/imagereader.cc \
|
||||
lib/imagereader/imgimagereader.cc \
|
||||
lib/imagewriter/imagewriter.cc \
|
||||
lib/imagewriter/imgimagewriter.cc \
|
||||
lib/globals.cc \
|
||||
lib/hexdump.cc \
|
||||
lib/image.cc \
|
||||
lib/ldbs.cc \
|
||||
lib/reader.cc \
|
||||
lib/sector.cc \
|
||||
lib/sectorset.cc \
|
||||
@@ -227,12 +230,13 @@ buildsimpleprogram brother120tool \
|
||||
libemu.a \
|
||||
libfmt.a \
|
||||
|
||||
runtest bitaccumulator-test tests/bitaccumulator.cc
|
||||
runtest bytes-test tests/bytes.cc
|
||||
runtest compression-test tests/compression.cc
|
||||
runtest crunch-test tests/crunch.cc
|
||||
runtest dataspec-test tests/dataspec.cc
|
||||
runtest flags-test tests/flags.cc
|
||||
runtest fmmfm-test tests/fmmfm.cc
|
||||
runtest bitaccumulator-test tests/bitaccumulator.cc
|
||||
runtest kryoflux-test tests/kryoflux.cc
|
||||
runtest compression-test tests/compression.cc
|
||||
runtest bytes-test tests/bytes.cc
|
||||
runtest crunch-test tests/crunch.cc
|
||||
runtest fluxpattern-test tests/fluxpattern.cc
|
||||
runtest fmmfm-test tests/fmmfm.cc
|
||||
runtest kryoflux-test tests/kryoflux.cc
|
||||
runtest ldbs-test tests/ldbs.cc
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
70
tests/ldbs.cc
Normal file
70
tests/ldbs.cc
Normal file
@@ -0,0 +1,70 @@
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include "globals.h"
|
||||
#include "bytes.h"
|
||||
#include "ldbs.h"
|
||||
|
||||
static Bytes testdata
|
||||
{
|
||||
'L', 'B', 'S', 0x01, 'D', 'S', 'K', 0x02,
|
||||
0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x34, 0x12, 0x00, 0x00, 'L', 'D', 'B', 0x01,
|
||||
0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x01, 'L', 'D', 'B', 0x01, 0x00, 0x00, 0x00,
|
||||
0x02, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
|
||||
0x00, 0x14, 0x00, 0x00, 0x00, 0x02
|
||||
};
|
||||
|
||||
static void assertBytes(const Bytes& want, const Bytes& got)
|
||||
{
|
||||
if (want != got)
|
||||
{
|
||||
std::cout << "Wanted bytes:" << std::endl;
|
||||
hexdump(std::cout, want);
|
||||
std::cout << std::endl << "Produced bytes:" << std::endl;
|
||||
hexdump(std::cout, got);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
static void test_getset()
|
||||
{
|
||||
LDBS ldbs;
|
||||
|
||||
uint32_t block1 = ldbs.put(Bytes { 1 }, 1);
|
||||
uint32_t block2 = ldbs.put(Bytes { 2 }, 2);
|
||||
assert(block1 != block2);
|
||||
|
||||
assert(ldbs.get(block1) == Bytes { 1 });
|
||||
assert(ldbs.get(block2) == Bytes { 2 });
|
||||
}
|
||||
|
||||
static void test_write()
|
||||
{
|
||||
LDBS ldbs;
|
||||
|
||||
uint32_t block1 = ldbs.put(Bytes { 1 }, 1);
|
||||
uint32_t block2 = ldbs.put(Bytes { 2 }, 2);
|
||||
Bytes data = ldbs.write(0x1234);
|
||||
|
||||
assertBytes(testdata, data);
|
||||
}
|
||||
|
||||
static void test_read()
|
||||
{
|
||||
LDBS ldbs;
|
||||
uint32_t trackDirectory = ldbs.read(testdata);
|
||||
|
||||
assert(trackDirectory == 0x1234);
|
||||
assert(ldbs.get(0x14) == Bytes { 1 });
|
||||
assert(ldbs.get(0x29) == Bytes { 2 });
|
||||
}
|
||||
|
||||
int main(int argc, const char* argv[])
|
||||
{
|
||||
test_getset();
|
||||
test_write();
|
||||
test_read();
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user