Compare commits

...

21 Commits

Author SHA1 Message Date
David Given
bb82dc864a Make cross-track sector collation optional (as it usually just makes things
confusing).
2024-02-03 01:08:23 +01:00
David Given
df83b558bf Merge pull request #742 from davidgiven/devices
Don't print the detection banner if no devices were detected.
2024-01-30 22:59:18 +01:00
David Given
7c2b5f116d Don't print the detection banner if no devices were detected. 2024-01-30 22:58:40 +01:00
David Given
30fe75f9bf Merge pull request #741 from davidgiven/devices
Add a command to list detectable devices on the command line.
2024-01-30 22:57:01 +01:00
David Given
401e7a9edb The rpm command now defaults to use real hardware, like it should. 2024-01-30 22:36:16 +01:00
David Given
fd4ddc56f2 Add a command to list detectable devices on the command line. 2024-01-30 21:44:11 +01:00
David Given
83d907bf71 Do parallel builds on OSX. 2024-01-30 21:28:03 +01:00
David Given
327bc76c6e Another try at making OSX builds work. 2024-01-22 22:31:51 +01:00
David Given
fdd39fb2d8 Try to fix OSX builds. 2024-01-22 22:16:49 +01:00
David Given
bfcfa8eb19 Merge pull request #738 from davidgiven/overrides
Fix a whole pile of missing 'override' keywords.
2024-01-22 21:08:27 +01:00
David Given
7095c03e28 Fix a whole pile of missing 'override' keywords. 2024-01-22 20:55:38 +01:00
David Given
45e796f15f Merge pull request #736 from davidgiven/ab
Remove stray files.
2024-01-07 23:20:02 +01:00
David Given
3d1dcd6874 imagemagick is just too much trouble for creating icons, so use png2ico instead. 2024-01-08 00:05:18 +01:00
David Given
0033d0759f 32-bit imagemagick has gone. 2024-01-07 21:29:06 +01:00
David Given
53f7dfe6c9 Remove stray files. 2024-01-07 21:24:53 +01:00
David Given
75446de29b Merge pull request #732 from davidgiven/acorn
Update the acorndfs format so that writes actually work.
2023-12-12 23:45:47 +00:00
David Given
1d119d6921 Update the acorndfs format so that writes actually work. 2023-12-13 00:31:12 +01:00
David Given
7462bd995f Merge pull request #731 from davidgiven/ab
Update ab. You can now build individual tools individually.
2023-12-12 22:31:48 +00:00
David Given
0dd99efad3 Update ab. 2023-12-12 23:17:06 +01:00
David Given
1234e81463 Update ab. You can now build individual tools individually. 2023-12-12 23:11:09 +01:00
David Given
ea13d66e6b Merge pull request #725 from davidgiven/dmk
Add support for DMK directory streams.
2023-11-02 01:35:24 +01:00
60 changed files with 208 additions and 578 deletions

View File

@@ -70,7 +70,7 @@ jobs:
mingw-w64-i686-sqlite3
mingw-w64-i686-wxWidgets
mingw-w64-i686-zlib
mingw-w64-i686-imagemagick
mingw-w64-i686-png2ico
vim
zip
- name: update-protobuf

View File

@@ -34,7 +34,7 @@ jobs:
mingw-w64-i686-sqlite3
mingw-w64-i686-wxWidgets
mingw-w64-i686-zlib
mingw-w64-i686-imagemagick
mingw-w64-i686-png2ico
vim
zip
- uses: actions/checkout@v3
@@ -94,10 +94,12 @@ jobs:
runs-on: macos-latest
steps:
- uses: actions/checkout@v2
- name: brew
run: brew install sqlite pkg-config libusb protobuf wxwidgets fmt make coreutils dylibbundler libjpeg
- name: make
run: gmake
run: gmake -j`nproc`
- name: tag
uses: EndBug/latest-tag@latest

194
build.lua
View File

@@ -1,194 +0,0 @@
vars.cflags = { "$(CFLAGS)" }
vars.cxxflags = { "$(CXXFLAGS)" }
vars.ldflags = { "-pthread" }
include "build/protobuf.lua"
include "build/dependency.lua"
include "build/tests.lua"
dependency {
name = "fmt_dep",
pkg_config = "fmt",
}
dependency {
name = "stb_dep",
pkg_config = "stb",
fallback = "dep/stb+stb"
}
dependency {
name = "protobuf_dep",
pkg_config = "protobuf"
}
dependency {
name = "zlib_dep",
pkg_config = "zlib"
}
proto_cc_library {
name = "config_lib",
srcs = {
"./lib/common.proto",
"./lib/config.proto",
"./lib/decoders/decoders.proto",
"./lib/drive.proto",
"./lib/encoders/encoders.proto",
"./lib/fl2.proto",
"./lib/fluxsink/fluxsink.proto",
"./lib/fluxsource/fluxsource.proto",
"./lib/imagereader/imagereader.proto",
"./lib/imagewriter/imagewriter.proto",
"./lib/mapper.proto",
"./lib/usb/usb.proto",
"./arch/aeslanier/aeslanier.proto",
"./arch/agat/agat.proto",
"./arch/amiga/amiga.proto",
"./arch/apple2/apple2.proto",
"./arch/brother/brother.proto",
"./arch/c64/c64.proto",
"./arch/f85/f85.proto",
"./arch/fb100/fb100.proto",
"./arch/ibm/ibm.proto",
"./arch/macintosh/macintosh.proto",
"./arch/micropolis/micropolis.proto",
"./arch/mx/mx.proto",
"./arch/northstar/northstar.proto",
"./arch/rolandd20/rolandd20.proto",
"./arch/tids990/tids990.proto",
"./arch/victor9k/victor9k.proto",
"./arch/zilogmcz/zilogmcz.proto",
}
}
clibrary {
name = "protocol_lib",
hdrs = { "./protocol.h" }
}
clibrary {
name = "libfluxengine",
srcs = {
"./arch/aeslanier/decoder.cc",
"./arch/agat/agat.cc",
"./arch/agat/decoder.cc",
"./arch/amiga/amiga.cc",
"./arch/amiga/decoder.cc",
"./arch/amiga/encoder.cc",
"./arch/apple2/decoder.cc",
"./arch/apple2/encoder.cc",
"./arch/brother/decoder.cc",
"./arch/brother/encoder.cc",
"./arch/c64/c64.cc",
"./arch/c64/decoder.cc",
"./arch/c64/encoder.cc",
"./arch/f85/decoder.cc",
"./arch/fb100/decoder.cc",
"./arch/ibm/decoder.cc",
"./arch/ibm/encoder.cc",
"./arch/macintosh/decoder.cc",
"./arch/macintosh/encoder.cc",
"./arch/micropolis/decoder.cc",
"./arch/micropolis/encoder.cc",
"./arch/mx/decoder.cc",
"./arch/northstar/decoder.cc",
"./arch/northstar/encoder.cc",
"./arch/rolandd20/rolandd20.cc",
"./arch/tids990/decoder.cc",
"./arch/tids990/encoder.cc",
"./arch/victor9k/decoder.cc",
"./arch/victor9k/encoder.cc",
"./arch/zilogmcz/decoder.cc",
"./lib/bitmap.cc",
"./lib/bytes.cc",
"./lib/crc.cc",
"./lib/csvreader.cc",
"./lib/decoders/decoders.cc",
"./lib/decoders/fluxdecoder.cc",
"./lib/decoders/fluxmapreader.cc",
"./lib/decoders/fmmfm.cc",
"./lib/encoders/encoders.cc",
"./lib/flags.cc",
"./lib/fluxmap.cc",
"./lib/fluxsink/aufluxsink.cc",
"./lib/fluxsink/fl2fluxsink.cc",
"./lib/fluxsink/fluxsink.cc",
"./lib/fluxsink/hardwarefluxsink.cc",
"./lib/fluxsink/scpfluxsink.cc",
"./lib/fluxsink/vcdfluxsink.cc",
"./lib/fluxsource/cwffluxsource.cc",
"./lib/fluxsource/erasefluxsource.cc",
"./lib/fluxsource/fl2fluxsource.cc",
"./lib/fluxsource/fluxsource.cc",
"./lib/fluxsource/hardwarefluxsource.cc",
"./lib/fluxsource/kryoflux.cc",
"./lib/fluxsource/kryofluxfluxsource.cc",
"./lib/fluxsource/scpfluxsource.cc",
"./lib/fluxsource/testpatternfluxsource.cc",
"./lib/globals.cc",
"./lib/hexdump.cc",
"./lib/image.cc",
"./lib/imagereader/d64imagereader.cc",
"./lib/imagereader/d88imagereader.cc",
"./lib/imagereader/dimimagereader.cc",
"./lib/imagereader/diskcopyimagereader.cc",
"./lib/imagereader/fdiimagereader.cc",
"./lib/imagereader/imagereader.cc",
"./lib/imagereader/imdimagereader.cc",
"./lib/imagereader/imgimagereader.cc",
"./lib/imagereader/jv3imagereader.cc",
"./lib/imagereader/nfdimagereader.cc",
"./lib/imagereader/nsiimagereader.cc",
"./lib/imagereader/td0imagereader.cc",
"./lib/imagewriter/d64imagewriter.cc",
"./lib/imagewriter/d88imagewriter.cc",
"./lib/imagewriter/diskcopyimagewriter.cc",
"./lib/imagewriter/imagewriter.cc",
"./lib/imagewriter/imgimagewriter.cc",
"./lib/imagewriter/ldbsimagewriter.cc",
"./lib/imagewriter/nsiimagewriter.cc",
"./lib/imagewriter/rawimagewriter.cc",
"./lib/imginputoutpututils.cc",
"./lib/ldbs.cc",
"./lib/logger.cc",
"./lib/mapper.cc",
"./lib/proto.cc",
"./lib/readerwriter.cc",
"./lib/sector.cc",
"./lib/usb/fluxengineusb.cc",
"./lib/usb/greaseweazle.cc",
"./lib/usb/greaseweazleusb.cc",
"./lib/usb/serial.cc",
"./lib/usb/usb.cc",
"./lib/usb/usbfinder.cc",
"./lib/utils.cc",
"protocol.h",
},
deps = {
"+config_lib",
"+protocol_lib",
"+fmt_dep",
"+protobuf_dep",
"+zlib_dep",
"dep/libusbp+libusbp",
},
dep_cflags = { "-Ilib", "-Iarch", "-I." },
vars = {
["+cflags"] = { "-Ilib", "-Iarch", "-I." }
}
}
installable {
name = "all",
map = {
["fluxengine"] = "src+fluxengine",
["fluxengine-gui"] = "src/gui+fluxengine",
["brother120tool"] = "tools+brother120tool",
["brother240tool"] = "tools+brother240tool",
["upgrade-flux-file"] = "tools+upgrade-flux-file",
}
}
include "tests/build.lua"

View File

@@ -227,6 +227,7 @@ if not glob("../fluxengine-testdata/data"):
print("fluxengine-testdata not found; skipping corpus tests")
else:
corpus = [
("acorndfs", "", "--200"),
("agat", "", ""),
("amiga", "", ""),
("apple2", "", "--140 40track_drive"),

View File

@@ -417,8 +417,6 @@ def export(self, name=None, items: TargetsMap = {}, deps: Targets = []):
for dest, src in items.items():
destf = filenameof(dest)
dir = dirname(destf)
if dir:
cs += ["mkdir -p " + dir]
srcs = filenamesof(src)
if len(srcs) != 1:
@@ -426,13 +424,16 @@ def export(self, name=None, items: TargetsMap = {}, deps: Targets = []):
"a dependency of an export must have exactly one output file"
)
cs += ["cp %s %s" % (srcs[0], destf)]
emitter_rule(self.name + "+" + destf, srcs, [destf])
emitter_label(f"CP {destf}")
if dir:
emitter_exec(["mkdir -p " + dir])
emitter_exec(["cp %s %s" % (srcs[0], destf)])
self.outs += [destf]
emitter_rule(self.name, items.values(), self.outs, deps)
emitter_label(f"EXPORT {self.name}")
emitter_exec(cs)
emitter_rule(self.name, self.outs, [], deps)
emit("\t@")
if self.outs:
emit("clean::")

View File

@@ -1,251 +0,0 @@
local OBJDIR = "$(OBJDIR)"
local function objdir(e)
return concatpath(OBJDIR, e.cwd, e.name)
end
definerule("normalrule",
{
ins = { type="targets" },
deps = { type="targets", default={} },
outs = { type="targets", default={} },
outleaves = { type="strings" },
label = { type="string", optional=true },
objdir = { type="string", optional=true },
commands = { type="strings" },
},
function (e)
local dir = e.objdir or objdir(e)
local realouts = {}
for _, v in pairs(e.outleaves) do
realouts[#realouts+1] = concatpath(dir, v)
end
local vars = inherit(e.vars, {
dir = dir
})
local result = simplerule {
name = e.name,
ins = e.ins,
deps = e.deps,
outs = concat(realouts, filenamesof(e.outs)),
label = e.label,
commands = e.commands,
vars = vars,
}
result.dir = dir
return result
end
)
local function is_clike(f)
return f:find("%.c$") or f:find("%.cc$") or f:find("%.cpp$")
end
definerule("cfile",
{
srcs = { type="targets" },
deps = { type="targets", default={} }
},
function (e)
local cflags = e.vars.cflags
local cxxflags = e.vars.cxxflags
for _, target in ipairs(targetsof(e.deps)) do
if target.is.clibrary then
cflags = concat(cflags, target.dep_cflags)
cxxflags = concat(cxxflags, target.dep_cxxflags)
end
end
local src = filter(filenamesof(e.srcs), is_clike)
local cmd
local cxx = false
if src[1]:find("%.c$") then
cmd = "$(CC) -c -o %{outs[1]} %{ins[1]} %{hdrpaths} %{cflags}"
else
cmd = "$(CXX) -c -o %{outs[1]} %{ins[1]} %{hdrpaths} %{cflags} %{cxxflags}"
cxx = true
end
local outleaf = basename(e.name)..".o"
local rule = normalrule {
name = e.name,
cwd = e.cwd,
ins = e.srcs,
deps = e.deps,
outleaves = {outleaf},
label = e.label,
commands = cmd,
vars = {
hdrpaths = {},
cflags = cflags,
cxxflags = cxxflags,
}
}
rule.is.cxxfile = cxx
return rule
end
)
local function do_cfiles(e)
local outs = {}
local srcs = filenamesof(e.srcs)
for _, f in ipairs(sorted(filter(srcs, is_clike))) do
local ofile
if f:find(OBJDIR, 1, true) == 1 then
ofile = e.name.."/"..f:sub(#OBJDIR+1)..".o"
else
ofile = e.name.."/"..f..".o"
end
outs[#outs+1] = cfile {
name = ofile,
srcs = { f },
deps = e.deps
}
end
return outs
end
definerule("clibrary",
{
srcs = { type="targets", default={} },
deps = { type="targets", default={} },
hdrs = { type="targets", default={} },
dep_cflags = { type="strings", default={} },
dep_cxxflags = { type="strings", default={} },
dep_ldflags = { type="strings", default={} },
dep_libs = { type="strings", default={} },
},
function (e)
local ins = do_cfiles(e)
local cxx = false
for _, f in ipairs(ins) do
if f.is.cxxfile then
cxx = true
break
end
end
local mkdirs = {}
local copies = {}
local outs = {}
local function copy_file(src, dest)
mkdirs[#mkdirs+1] = "mkdir -p %{dir}/"..dirname(dest)
copies[#copies+1] = "cp "..src.." %{dir}/"..dest
outs[#outs+1] = objdir(e).."/"..dest
end
local deps = {}
for k, v in pairs(e.hdrs) do
deps[#deps+1] = v
if type(k) == "number" then
v = filenamesof(v)
for _, v in ipairs(v) do
if not startswith(e.cwd, v) then
error(string.format("filename '%s' is not local to '%s' --- "..
"you'll have to specify the output filename manually", v, e.cwd))
end
copy_file(v, v:gsub("^"..e.cwd, ""))
end
else
v = filenamesof(v)
if #v ~= 1 then
error("each mapped hdrs item can only cope with a single file")
end
copy_file(v[1], k)
end
end
ins = sorted(filenamesof(ins))
local has_ar = (#ins ~= 0)
local lib = normalrule {
name = e.name,
cwd = e.cwd,
ins = sorted(filenamesof(ins)),
deps = deps,
outs = outs,
outleaves = { e.name..".a" },
label = e.label,
commands = {
sorted(mkdirs),
sorted(copies),
has_ar and "rm -f %{outs[1]} && $(AR) cqs %{outs[1]} %{ins}" or {},
}
}
lib.dep_cflags = concat(e.dep_cflags, "-I"..lib.dir)
lib.dep_cxxflags = e.dep_cxxflags
lib.dep_ldflags = e.dep_ldflags
lib.dep_libs = concat(e.dep_libs, has_ar and matching(filenamesof(lib), "%.a$") or {})
lib.dep_cxx = cxx
for _, d in pairs(targetsof(e.deps)) do
lib.dep_cflags = concat(lib.dep_cflags, d.dep_cflags)
lib.dep_cxxflags = concat(lib.dep_cxxflags, d.dep_cxxflags)
lib.dep_ldflags = concat(lib.dep_ldflags, d.dep_ldflags)
lib.dep_libs = concat(lib.dep_libs, d.dep_libs)
lib.dep_cxx = lib.dep_cxx or d.dep_cxx
end
return lib
end
)
definerule("cprogram",
{
srcs = { type="targets", default={} },
deps = { type="targets", default={} },
},
function (e)
local deps = e.deps
local ins = {}
local cxx = false
if (#e.srcs > 0) then
local objs = do_cfiles(e)
for _, obj in pairs(objs) do
if obj.is.cxxfile then
cxx = true
end
ins[#ins+1] = obj
end
end
local libs = {}
local cflags = {}
local cxxflags = {}
local ldflags = {}
for _, lib in pairs(e.deps) do
cflags = concat(cflags, lib.dep_cflags)
cxxflags = concat(cxxflags, lib.dep_cxxflags)
ldflags = concat(ldflags, lib.dep_ldflags)
libs = concat(libs, lib.dep_libs)
cxx = cxx or lib.dep_cxx
end
local command
if cxx then
command = "$(CXX) $(LDFLAGS) %{ldflags} -o %{outs[1]} %{ins} %{libs} %{libs}"
else
command = "$(CC) $(LDFLAGS) %{ldflags} -o %{outs[1]} %{ins} %{libs} %{libs}"
end
return normalrule {
name = e.name,
cwd = e.cwd,
deps = deps,
ins = ins,
outleaves = { e.name },
commands = { command },
vars = {
cflags = cflags,
cxxflags = cxxflags,
ldflags = ldflags,
libs = libs,
}
}
end
)

View File

@@ -6,7 +6,7 @@ import subprocess
emit(
"""
PKG_CONFIG ?= pkg-config
PACKAGES := $(shell $(PKG_CONFIG) --list-all | cut -d' ' -f1)
PACKAGES := $(shell $(PKG_CONFIG) --list-all | cut -d' ' -f1 | sort)
"""
)

View File

@@ -1,18 +0,0 @@
definerule("test",
{
srcs = { type="targets", default={} },
},
function (e)
if vars.TESTS == "yes" then
normalrule {
name = e.name,
ins = e.srcs,
outleaves = { "log.txt" },
commands = {
"%{ins} > %{outs}",
}
}
end
end
)

View File

@@ -234,7 +234,7 @@ namespace libusbp
}
/*! Wrapper for libusbp_error_get_message(). */
virtual const char * what() const noexcept
virtual const char * what() const noexcept override
{
return libusbp_error_get_message(pointer);
}

View File

@@ -58,7 +58,14 @@ If _more_ than one device is plugged in, you need to specify which one to use
with the `--usb.serial` parameter, which takes the device serial number as a
parameter. You can find out the serial numbers by running the command without
the `--usb.serial` parameter, and if more than one device is attached they will
be listed. The serial number is also shown whenever a connection is made.
be listed. The serial number is also shown whenever a connection is made. You
can list all the detectable devices with:
```
$ fluxengine test devices
```
This will show you their serial numbers.
You _can_ work with more than one FluxEngine at the same time, using different
invocations of the client; but be careful of USB bandwidth. If the devices are

View File

@@ -38,7 +38,7 @@ normalrule(
ins=["./icon.png"],
outs=["fluxengine.ico"],
commands=[
"convert {ins[0]} -resize 64x46 -define icon:auto-resize=64,48,32,16 {outs[0]}"
"png2ico {outs[0]} {ins[0]}"
],
label="MAKEICON",
)

View File

@@ -137,8 +137,10 @@ std::shared_ptr<TrackDataFlux> Decoder::decodeToSectors(
if (_sector->status != Sector::MISSING)
{
auto trackLayout = Layout::getLayoutOfTrack(
_sector->logicalTrack, _sector->logicalSide);
if ((_sector->status == Sector::OK) &&
((_sector->logicalTrack != trackInfo->logicalTrack) ||
(_sector->logicalSide != trackInfo->logicalSide)))
_sector->status == Sector::WRONG_PLACE;
_trackdata->sectors.push_back(_sector);
}
}

View File

@@ -21,7 +21,7 @@ import "arch/zilogmcz/zilogmcz.proto";
import "lib/fluxsink/fluxsink.proto";
import "lib/common.proto";
//NEXT: 32
//NEXT: 33
message DecoderProto {
optional double pulse_debounce_threshold = 1 [default = 0.30,
(help) = "ignore pulses with intervals shorter than this, in fractions of a clock"];
@@ -66,6 +66,7 @@ message DecoderProto {
optional string write_csv_to = 23
[(help) = "if set, write a CSV report of the disk state"];
optional bool skip_unnecessary_tracks = 29 [default = true,
(help) = "don't read tracks if we already have all necessary sectors"];
(help) = "don't read physical tracks if we already have all necessary sectors"];
optional bool collate_sectors_from_all_tracks = 32 [default = false,
(help) = "when creating the image, consider all valid sectors even if they're on the wrong track"];
}

View File

@@ -87,15 +87,17 @@ public:
{
}
bool hasArgument() const
bool hasArgument() const override
{
return false;
}
const std::string defaultValueAsString() const
const std::string defaultValueAsString() const override
{
return "";
}
void set(const std::string& value)
void set(const std::string& value) override
{
_callback();
}
@@ -119,15 +121,17 @@ public:
return _value;
}
bool hasArgument() const
bool hasArgument() const override
{
return false;
}
const std::string defaultValueAsString() const
const std::string defaultValueAsString() const override
{
return "false";
}
void set(const std::string& value)
void set(const std::string& value) override
{
_value = true;
}
@@ -176,7 +180,7 @@ public:
_value = _defaultValue = value;
}
bool hasArgument() const
bool hasArgument() const override
{
return true;
}
@@ -203,11 +207,12 @@ public:
{
}
const std::string defaultValueAsString() const
const std::string defaultValueAsString() const override
{
return _defaultValue;
}
void set(const std::string& value)
void set(const std::string& value) override
{
_value = value;
_callback(_value);
@@ -230,11 +235,12 @@ public:
{
}
const std::string defaultValueAsString() const
const std::string defaultValueAsString() const override
{
return std::to_string(_defaultValue);
}
void set(const std::string& value)
void set(const std::string& value) override
{
_value = std::stoi(value);
_callback(_value);
@@ -257,7 +263,7 @@ public:
{
}
const std::string defaultValueAsString() const;
const std::string defaultValueAsString() const override;
};
class DoubleFlag : public ValueFlag<double>
@@ -275,11 +281,12 @@ public:
{
}
const std::string defaultValueAsString() const
const std::string defaultValueAsString() const override
{
return std::to_string(_defaultValue);
}
void set(const std::string& value)
void set(const std::string& value) override
{
_value = std::stod(value);
_callback(_value);
@@ -302,11 +309,11 @@ public:
{
}
const std::string defaultValueAsString() const
const std::string defaultValueAsString() const override
{
return _defaultValue ? "true" : "false";
}
void set(const std::string& value);
void set(const std::string& value) override;
};
#endif

View File

@@ -88,7 +88,7 @@ public:
}
public:
std::unique_ptr<const Fluxmap> readSingleFlux(int track, int side)
std::unique_ptr<const Fluxmap> readSingleFlux(int track, int side) override
{
const auto& p = _trackOffsets.find(std::make_pair(track, side));
if (p == _trackOffsets.end())
@@ -103,7 +103,7 @@ public:
return decodeCatweaselData(fluxdata, _clockPeriod);
}
void recalibrate() {}
void recalibrate() override {}
private:
void check_for_error()

View File

@@ -111,7 +111,7 @@ class EmptyFluxSourceIterator : public FluxSourceIterator
class TrivialFluxSource : public FluxSource
{
public:
std::unique_ptr<FluxSourceIterator> readFlux(int track, int side);
std::unique_ptr<FluxSourceIterator> readFlux(int track, int side) override;
virtual std::unique_ptr<const Fluxmap> readSingleFlux(
int track, int side) = 0;
};

View File

@@ -18,7 +18,7 @@ public:
return readStream(_path, track, side);
}
void recalibrate() {}
void recalibrate() override {}
private:
const std::string _path;

View File

@@ -47,7 +47,7 @@ public:
return std::make_unique<EmptyFluxSourceIterator>();
}
void recalibrate() {}
void recalibrate() override {}
private:
const DiskFlux& _flux;

View File

@@ -27,7 +27,7 @@ public:
return fluxmap;
}
void recalibrate() {}
void recalibrate() override {}
private:
const TestPatternFluxSourceProto& _config;

View File

@@ -14,7 +14,7 @@ class D64ImageReader : public ImageReader
public:
D64ImageReader(const ImageReaderProto& config): ImageReader(config) {}
std::unique_ptr<Image> readImage()
std::unique_ptr<Image> readImage() override
{
std::ifstream inputFile(
_config.filename(), std::ios::in | std::ios::binary);

View File

@@ -18,7 +18,7 @@ class D88ImageReader : public ImageReader
public:
D88ImageReader(const ImageReaderProto& config): ImageReader(config) {}
std::unique_ptr<Image> readImage()
std::unique_ptr<Image> readImage() override
{
std::ifstream inputFile(
_config.filename(), std::ios::in | std::ios::binary);

View File

@@ -18,7 +18,7 @@ class DimImageReader : public ImageReader
public:
DimImageReader(const ImageReaderProto& config): ImageReader(config) {}
std::unique_ptr<Image> readImage()
std::unique_ptr<Image> readImage() override
{
std::ifstream inputFile(
_config.filename(), std::ios::in | std::ios::binary);

View File

@@ -14,7 +14,7 @@ class DiskCopyImageReader : public ImageReader
public:
DiskCopyImageReader(const ImageReaderProto& config): ImageReader(config) {}
std::unique_ptr<Image> readImage()
std::unique_ptr<Image> readImage() override
{
std::ifstream inputFile(
_config.filename(), std::ios::in | std::ios::binary);

View File

@@ -18,7 +18,7 @@ class FdiImageReader : public ImageReader
public:
FdiImageReader(const ImageReaderProto& config): ImageReader(config) {}
std::unique_ptr<Image> readImage()
std::unique_ptr<Image> readImage() override
{
std::ifstream inputFile(
_config.filename(), std::ios::in | std::ios::binary);

View File

@@ -137,7 +137,7 @@ public:
* <End of file>
*/
// clang-format on
std::unique_ptr<Image> readImage()
std::unique_ptr<Image> readImage() override
{
// Read File
std::ifstream inputFile(

View File

@@ -17,7 +17,7 @@ class ImgImageReader : public ImageReader
public:
ImgImageReader(const ImageReaderProto& config): ImageReader(config) {}
std::unique_ptr<Image> readImage()
std::unique_ptr<Image> readImage() override
{
std::ifstream inputFile(
_config.filename(), std::ios::in | std::ios::binary);

View File

@@ -89,7 +89,7 @@ class Jv3ImageReader : public ImageReader
public:
Jv3ImageReader(const ImageReaderProto& config): ImageReader(config) {}
std::unique_ptr<Image> readImage()
std::unique_ptr<Image> readImage() override
{
std::ifstream inputFile(
_config.filename(), std::ios::in | std::ios::binary);

View File

@@ -18,7 +18,7 @@ class NFDImageReader : public ImageReader
public:
NFDImageReader(const ImageReaderProto& config): ImageReader(config) {}
std::unique_ptr<Image> readImage()
std::unique_ptr<Image> readImage() override
{
std::ifstream inputFile(
_config.filename(), std::ios::in | std::ios::binary);

View File

@@ -16,7 +16,7 @@ class NsiImageReader : public ImageReader
public:
NsiImageReader(const ImageReaderProto& config): ImageReader(config) {}
std::unique_ptr<Image> readImage()
std::unique_ptr<Image> readImage() override
{
std::ifstream inputFile(
_config.filename(), std::ios::in | std::ios::binary);

View File

@@ -47,7 +47,7 @@ class Td0ImageReader : public ImageReader
public:
Td0ImageReader(const ImageReaderProto& config): ImageReader(config) {}
std::unique_ptr<Image> readImage()
std::unique_ptr<Image> readImage() override
{
std::ifstream inputFile(
_config.filename(), std::ios::in | std::ios::binary);

View File

@@ -26,7 +26,7 @@ class D64ImageWriter : public ImageWriter
public:
D64ImageWriter(const ImageWriterProto& config): ImageWriter(config) {}
void writeImage(const Image& image)
void writeImage(const Image& image) override
{
log("D64: writing triangular image");

View File

@@ -26,7 +26,7 @@ class D88ImageWriter : public ImageWriter
public:
D88ImageWriter(const ImageWriterProto& config): ImageWriter(config) {}
void writeImage(const Image& image)
void writeImage(const Image& image) override
{
const Geometry geometry = image.getGeometry();

View File

@@ -30,7 +30,7 @@ class DiskCopyImageWriter : public ImageWriter
public:
DiskCopyImageWriter(const ImageWriterProto& config): ImageWriter(config) {}
void writeImage(const Image& image)
void writeImage(const Image& image) override
{
const Geometry& geometry = image.getGeometry();

View File

@@ -155,7 +155,7 @@ class ImdImageWriter : public ImageWriter
public:
ImdImageWriter(const ImageWriterProto& config): ImageWriter(config) {}
void writeImage(const Image& image)
void writeImage(const Image& image) override
{
const Geometry& geometry = image.getGeometry();
unsigned numHeads;

View File

@@ -17,7 +17,7 @@ class ImgImageWriter : public ImageWriter
public:
ImgImageWriter(const ImageWriterProto& config): ImageWriter(config) {}
void writeImage(const Image& image)
void writeImage(const Image& image) override
{
const Geometry geometry = image.getGeometry();

View File

@@ -15,7 +15,7 @@ class LDBSImageWriter : public ImageWriter
public:
LDBSImageWriter(const ImageWriterProto& config): ImageWriter(config) {}
void writeImage(const Image& image)
void writeImage(const Image& image) override
{
LDBS ldbs;

View File

@@ -16,7 +16,7 @@ class NsiImageWriter : public ImageWriter
public:
NsiImageWriter(const ImageWriterProto& config): ImageWriter(config) {}
void writeImage(const Image& image)
void writeImage(const Image& image) override
{
const Geometry& geometry = image.getGeometry();
bool mixedDensity = false;

View File

@@ -16,7 +16,7 @@ class RawImageWriter : public ImageWriter
public:
RawImageWriter(const ImageWriterProto& config): ImageWriter(config) {}
void writeImage(const Image& image)
void writeImage(const Image& image) override
{
const Geometry& geometry = image.getGeometry();

View File

@@ -97,9 +97,16 @@ void measureDiskRotation()
log(EndSpeedOperationLogMessage{oneRevolution});
}
static int getEffectiveStatus(int status)
{
if ((status == Sector::WRONG_PLACE) &&
globalConfig()->decoder().collate_sectors_from_all_tracks())
return Sector::OK;
return status;
}
/* Given a set of sectors, deduplicates them sensibly (e.g. if there is a good
* and bad version of the same sector, the bad version is dropped). */
static std::set<std::shared_ptr<const Sector>> collectSectors(
std::set<std::shared_ptr<const Sector>>& track_sectors,
bool collapse_conflicts = true)
@@ -124,9 +131,11 @@ static std::set<std::shared_ptr<const Sector>> collectSectors(
it->second,
[&](auto left, auto& rightit) -> std::shared_ptr<const Sector>
{
int leftStatus = left->status;
auto& right = rightit.second;
if ((left->status == Sector::OK) &&
(right->status == Sector::OK) &&
int rightStatus = right->status;
if ((leftStatus == Sector::OK) &&
(rightStatus == Sector::OK) &&
(left->data != right->data))
{
if (!collapse_conflicts)
@@ -139,13 +148,13 @@ static std::set<std::shared_ptr<const Sector>> collectSectors(
s->status = Sector::CONFLICT;
return s;
}
if (left->status == Sector::CONFLICT)
if (leftStatus == Sector::CONFLICT)
return left;
if (right->status == Sector::CONFLICT)
if (rightStatus == Sector::CONFLICT)
return right;
if (left->status == Sector::OK)
if (leftStatus == Sector::OK)
return left;
if (right->status == Sector::OK)
if (rightStatus == Sector::OK)
return right;
return left;
});

View File

@@ -31,6 +31,8 @@ std::string Sector::statusToString(Status status)
return "present but no data found";
case Status::CONFLICT:
return "conflicting data";
case Status::WRONG_PLACE:
return "incorrectly placed";
default:
return fmt::format("unknown error {}", status);
}
@@ -50,6 +52,8 @@ std::string Sector::statusToChar(Status status)
return "!";
case Status::CONFLICT:
return "*";
case Status::WRONG_PLACE:
return "/";
default:
return "?";
}

View File

@@ -44,6 +44,7 @@ struct Sector : public LogicalLocation
DATA_MISSING,
CONFLICT,
INTERNAL_ERROR,
WRONG_PLACE,
};
static std::string statusToString(Status status);

View File

@@ -123,7 +123,7 @@ private:
}
public:
int getVersion()
int getVersion() override
{
struct any_frame f = {
.f = {.type = F_FRAME_GET_VERSION_CMD, .size = sizeof(f)}
@@ -133,7 +133,7 @@ public:
return r->version;
}
void seek(int track)
void seek(int track) override
{
struct seek_frame f = {
.f = {.type = F_FRAME_SEEK_CMD, .size = sizeof(f)},
@@ -143,7 +143,7 @@ public:
await_reply<struct any_frame>(F_FRAME_SEEK_REPLY);
}
void recalibrate()
void recalibrate() override
{
struct any_frame f = {
.f = {.type = F_FRAME_RECALIBRATE_CMD, .size = sizeof(f)},
@@ -152,7 +152,7 @@ public:
await_reply<struct any_frame>(F_FRAME_RECALIBRATE_REPLY);
}
nanoseconds_t getRotationalPeriod(int hardSectorCount)
nanoseconds_t getRotationalPeriod(int hardSectorCount) override
{
struct measurespeed_frame f = {
.f = {.type = F_FRAME_MEASURE_SPEED_CMD, .size = sizeof(f)},
@@ -164,7 +164,7 @@ public:
return r->period_ms * 1000000;
}
void testBulkWrite()
void testBulkWrite() override
{
struct any_frame f = {
.f = {.type = F_FRAME_BULK_WRITE_TEST_CMD, .size = sizeof(f)}
@@ -204,7 +204,7 @@ public:
await_reply<struct any_frame>(F_FRAME_BULK_WRITE_TEST_REPLY);
}
void testBulkRead()
void testBulkRead() override
{
struct any_frame f = {
.f = {.type = F_FRAME_BULK_READ_TEST_CMD, .size = sizeof(f)}
@@ -242,7 +242,7 @@ public:
Bytes read(int side,
bool synced,
nanoseconds_t readTime,
nanoseconds_t hardSectorThreshold)
nanoseconds_t hardSectorThreshold) override
{
struct read_frame f = {
.f = {.type = F_FRAME_READ_CMD, .size = sizeof(f)},
@@ -265,7 +265,9 @@ public:
return buffer;
}
void write(int side, const Bytes& bytes, nanoseconds_t hardSectorThreshold)
void write(int side,
const Bytes& bytes,
nanoseconds_t hardSectorThreshold) override
{
unsigned safelen = bytes.size() & ~(FRAME_SIZE - 1);
Bytes safeBytes = bytes.slice(0, safelen);
@@ -287,7 +289,7 @@ public:
await_reply<struct any_frame>(F_FRAME_WRITE_REPLY);
}
void erase(int side, nanoseconds_t hardSectorThreshold)
void erase(int side, nanoseconds_t hardSectorThreshold) override
{
struct erase_frame f = {
.f = {.type = F_FRAME_ERASE_CMD, .size = sizeof(f)},
@@ -300,7 +302,7 @@ public:
await_reply<struct any_frame>(F_FRAME_ERASE_REPLY);
}
void setDrive(int drive, bool high_density, int index_mode)
void setDrive(int drive, bool high_density, int index_mode) override
{
struct set_drive_frame f = {
.f = {.type = F_FRAME_SET_DRIVE_CMD, .size = sizeof(f)},
@@ -312,7 +314,7 @@ public:
await_reply<struct any_frame>(F_FRAME_SET_DRIVE_REPLY);
}
void measureVoltages(struct voltages_frame* voltages)
void measureVoltages(struct voltages_frame* voltages) override
{
struct any_frame f = {
{.type = F_FRAME_MEASURE_VOLTAGES_CMD, .size = sizeof(f)},

View File

@@ -109,7 +109,7 @@ public:
do_command({CMD_SET_BUS_TYPE, 3, (uint8_t)config.bus_type()});
}
int getVersion()
int getVersion() override
{
do_command({CMD_GET_INFO, 3, GETINFO_FIRMWARE});
@@ -124,17 +124,17 @@ public:
return br.read_be16();
}
void recalibrate()
void recalibrate() override
{
seek(0);
}
void seek(int track)
void seek(int track) override
{
do_command({CMD_SEEK, 3, (uint8_t)track});
}
nanoseconds_t getRotationalPeriod(int hardSectorCount)
nanoseconds_t getRotationalPeriod(int hardSectorCount) override
{
if (hardSectorCount != 0)
error("hard sectors are currently unsupported on the Greaseweazle");
@@ -214,7 +214,7 @@ public:
return _revolutions;
}
void testBulkWrite()
void testBulkWrite() override
{
std::cout << "Writing data: " << std::flush;
const int LEN = 10 * 1024 * 1024;
@@ -264,7 +264,7 @@ public:
int((LEN / 1024.0) / elapsed_time));
}
void testBulkRead()
void testBulkRead() override
{
std::cout << "Reading data: " << std::flush;
const int LEN = 10 * 1024 * 1024;
@@ -309,7 +309,7 @@ public:
Bytes read(int side,
bool synced,
nanoseconds_t readTime,
nanoseconds_t hardSectorThreshold)
nanoseconds_t hardSectorThreshold) override
{
if (hardSectorThreshold != 0)
error("hard sectors are currently unsupported on the Greaseweazle");
@@ -362,7 +362,9 @@ public:
return fldata;
}
void write(int side, const Bytes& fldata, nanoseconds_t hardSectorThreshold)
void write(int side,
const Bytes& fldata,
nanoseconds_t hardSectorThreshold) override
{
if (hardSectorThreshold != 0)
error("hard sectors are currently unsupported on the Greaseweazle");
@@ -385,7 +387,7 @@ public:
do_command({CMD_GET_FLUX_STATUS, 2});
}
void erase(int side, nanoseconds_t hardSectorThreshold)
void erase(int side, nanoseconds_t hardSectorThreshold) override
{
if (hardSectorThreshold != 0)
error("hard sectors are currently unsupported on the Greaseweazle");
@@ -403,14 +405,14 @@ public:
do_command({CMD_GET_FLUX_STATUS, 2});
}
void setDrive(int drive, bool high_density, int index_mode)
void setDrive(int drive, bool high_density, int index_mode) override
{
do_command({CMD_SELECT, 3, (uint8_t)drive});
do_command({CMD_MOTOR, 4, (uint8_t)drive, 1});
do_command({CMD_SET_PIN, 4, 2, (uint8_t)(high_density ? 1 : 0)});
}
void measureVoltages(struct voltages_frame* voltages)
void measureVoltages(struct voltages_frame* voltages) override
{
error("unsupported operation on the Greaseweazle");
}

View File

@@ -113,12 +113,12 @@ public:
{
}
uint32_t capabilities() const
uint32_t capabilities() const override
{
return OP_GETFSDATA | OP_LIST | OP_GETFILE | OP_GETDIRENT;
}
std::map<std::string, std::string> getMetadata()
std::map<std::string, std::string> getMetadata() override
{
AcornDfsDirectory dir(this);
@@ -130,12 +130,12 @@ public:
return attributes;
}
FilesystemStatus check()
FilesystemStatus check() override
{
return FS_OK;
}
std::vector<std::shared_ptr<Dirent>> list(const Path& path)
std::vector<std::shared_ptr<Dirent>> list(const Path& path) override
{
if (!path.empty())
throw FileNotFoundException();
@@ -148,7 +148,7 @@ public:
return result;
}
Bytes getFile(const Path& path)
Bytes getFile(const Path& path) override
{
AcornDfsDirectory dir(this);
auto dirent = dir.findFile(path);
@@ -166,7 +166,7 @@ public:
return data;
}
std::shared_ptr<Dirent> getDirent(const Path& path)
std::shared_ptr<Dirent> getDirent(const Path& path) override
{
AcornDfsDirectory dir(this);
return dir.findFile(path);

View File

@@ -141,7 +141,7 @@ public:
{
}
uint32_t capabilities() const
uint32_t capabilities() const override
{
return OP_GETFSDATA | OP_LIST | OP_GETFILE | OP_GETDIRENT;
}

View File

@@ -101,7 +101,7 @@ public:
{
}
uint32_t capabilities() const
uint32_t capabilities() const override
{
return OP_GETFSDATA | OP_LIST | OP_GETFILE | OP_GETDIRENT;
}

View File

@@ -189,7 +189,7 @@ public:
{
}
uint32_t capabilities() const
uint32_t capabilities() const override
{
return OP_GETFSDATA | OP_LIST | OP_GETFILE | OP_GETDIRENT;
}

View File

@@ -23,6 +23,7 @@ cxxprogram(
"./fe-rpm.cc",
"./fe-seek.cc",
"./fe-testbandwidth.cc",
"./fe-testdevices.cc",
"./fe-testvoltages.cc",
"./fe-write.cc",
"./fileutils.cc",

View File

@@ -17,6 +17,7 @@ static StringFlag sourceFlux({"-s", "--source"},
int mainRpm(int argc, const char* argv[])
{
globalConfig().set("flux_source.type", "FLUXTYPE_DRIVE");
flags.parseFlagsWithConfigFiles(argc, argv, {});
if (globalConfig()->flux_source().type() != FLUXTYPE_DRIVE)

41
src/fe-testdevices.cc Normal file
View File

@@ -0,0 +1,41 @@
#include "lib/globals.h"
#include "lib/flags.h"
#include "lib/usb/usbfinder.h"
#include <fmt/format.h>
static FlagGroup flags;
int mainTestDevices(int argc, const char* argv[])
{
flags.parseFlagsWithConfigFiles(argc, argv, {});
auto candidates = findUsbDevices();
switch (candidates.size())
{
case 0:
fmt::print("Detected no devices.\n");
break;
case 1:
fmt::print("Detected one device:\n");
break;
default:
fmt::print("Detected {} devices:\n", candidates.size());
}
if (!candidates.empty())
{
fmt::print(
"{:15} {:30} {}\n", "Type", "Serial number", "Port (if any)");
for (auto& candidate : candidates)
{
fmt::print("{:15} {:30} {}\n",
getDeviceName(candidate->type),
candidate->serial,
candidate->serialPort);
}
}
return 0;
}

View File

@@ -23,6 +23,7 @@ extern command_cb mainRm;
extern command_cb mainRpm;
extern command_cb mainSeek;
extern command_cb mainTestBandwidth;
extern command_cb mainTestDevices;
extern command_cb mainTestVoltages;
extern command_cb mainWrite;
@@ -69,6 +70,7 @@ static std::vector<Command> analysables =
static std::vector<Command> testables =
{
{ "bandwidth", mainTestBandwidth, "Measures your USB bandwidth.", },
{ "devices", mainTestDevices, "Displays all detected devices.", },
{ "voltages", mainTestVoltages, "Measures the FDD bus voltages.", },
};
// clang-format on

View File

@@ -47,12 +47,16 @@ layout {
encoder {
ibm {
trackdata {
target_rotational_period_ms: 167
target_clock_period_us: 3.333
target_rotational_period_ms: 166
target_clock_period_us: 3.33
emit_iam: false
gap0: 80
gap2: 22
gap3: 34
use_fm: true
gap0: 0x10
gap2: 0x09
gap3: 0x10
idam_byte: 0xf57e
dam_byte: 0xf56f
gap_fill_byte: 0xffff
}
}
}

View File

@@ -109,6 +109,10 @@ option_group {
set_by_default: true
config {
decoder {
collate_sectors_from_all_tracks: true
}
layout {
format_type: FORMATTYPE_80TRACK
}

View File

@@ -6,11 +6,12 @@ emit(
"""
WX_CONFIG ?= wx-config
ifneq ($(strip $(shell command -v $(WX_CONFIG) >/dev/null 2>&1; echo $$?)),0)
$(error Required binary 'wx-config' not found.)
endif
WX_CFLAGS = $(error Required binary 'wx-config' not found.)
WX_LDFLAGS = $(error Required binary 'wx-config' not found.)
else
WX_CFLAGS := $(shell $(WX_CONFIG) --cxxflags core base adv aui richtext)
WX_LDFLAGS := $(shell $(WX_CONFIG) --libs core base adv aui richtext)
endif
"""
)
@@ -99,7 +100,7 @@ if config.osx:
"dylibbundler -of -x {outs[0]}/Contents/MacOS/fluxengine-gui -b -d {outs[0]}/Contents/libs -cd > /dev/null",
"cp $$(brew --prefix wxwidgets)/README.md $@/Contents/libs/wxWidgets.md",
"cp $$(brew --prefix protobuf)/LICENSE $@/Contents/libs/protobuf.txt",
"cp $$(brew --prefix fmt)/LICENSE.rst $@/Contents/libs/fmt.rst",
"cp $$(brew --prefix fmt)/LICENSE* $@/Contents/libs/fmt.rst",
"cp $$(brew --prefix libpng)/LICENSE $@/Contents/libs/libpng.txt",
"cp $$(brew --prefix libjpeg)/README $@/Contents/libs/libjpeg.txt",
"cp $$(brew --prefix abseil)/LICENSE $@/Contents/libs/abseil.txt",

View File

@@ -33,7 +33,7 @@ static inline R runOnUiThread(std::function<R()> callback)
class FluxEngineApp : public wxApp, public wxThreadHelper
{
public:
virtual bool OnInit();
virtual bool OnInit() override;
void RunOnWorkerThread(std::function<void()> callback);
private:
@@ -44,7 +44,7 @@ public:
bool IsWorkerThreadRunning();
protected:
virtual wxThread::ExitCode Entry();
virtual wxThread::ExitCode Entry() override;
private:
static wxWindow* CreateMainWindow();

View File

@@ -26,7 +26,7 @@ public:
{
}
wxEvent* Clone() const
wxEvent* Clone() const override
{
return new ExecEvent(*this);
}

View File

@@ -10,7 +10,7 @@ public:
{
}
wxEvent* Clone() const
wxEvent* Clone() const override
{
return new EditorSaveEvent(*this);
}

View File

@@ -20,7 +20,7 @@ public:
wxTextCtrl* GetTextControl() const;
private:
void OnClose(wxCloseEvent& event);
void OnClose(wxCloseEvent& event) override;
private:
bool _autodestroy;

View File

@@ -24,7 +24,7 @@ public:
{
}
wxEvent* Clone() const
wxEvent* Clone() const override
{
return new TrackSelectionEvent(*this);
}

View File

@@ -18,7 +18,7 @@ namespace
{
public:
std::shared_ptr<const Sector> get(
unsigned track, unsigned side, unsigned sectorId)
unsigned track, unsigned side, unsigned sectorId) override
{
auto s = _image.get(track, side, sectorId);
if (!s)
@@ -27,7 +27,7 @@ namespace
}
std::shared_ptr<Sector> put(
unsigned track, unsigned side, unsigned sectorId)
unsigned track, unsigned side, unsigned sectorId) override
{
return _image.put(track, side, sectorId);
}