mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-31 11:17:01 -07:00
Compare commits
59 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1b859015ae | ||
|
|
294ac87503 | ||
|
|
c297adb0c7 | ||
|
|
446b965794 | ||
|
|
1927cc7fe1 | ||
|
|
4eca254daf | ||
|
|
c7d4fee3f6 | ||
|
|
a6f798ae5b | ||
|
|
c9ae836e52 | ||
|
|
e3ffa63f7f | ||
|
|
4ffc2cc1dc | ||
|
|
7f9ba14687 | ||
|
|
a24933e272 | ||
|
|
20bdacbecf | ||
|
|
1f5903a9a0 | ||
|
|
bb073b6bb3 | ||
|
|
516241f8f5 | ||
|
|
977b6831a0 | ||
|
|
c61effb54f | ||
|
|
346d989944 | ||
|
|
60a73c8d1e | ||
|
|
e52db4a837 | ||
|
|
4e317643bc | ||
|
|
5f520bf375 | ||
|
|
2efe521b3a | ||
|
|
5c21103646 | ||
|
|
9444696f37 | ||
|
|
082fe4e787 | ||
|
|
5e13cf23f9 | ||
|
|
8f98a1f557 | ||
|
|
5b21e8798b | ||
|
|
b9ef5b7db8 | ||
|
|
9867f8c302 | ||
|
|
315889faf6 | ||
|
|
798e8fee89 | ||
|
|
e1c49db329 | ||
|
|
dae9537472 | ||
|
|
1330d56cdd | ||
|
|
6ce3ce20d0 | ||
|
|
362c5ee9b0 | ||
|
|
0f34ce0278 | ||
|
|
0c27c7c4c8 | ||
|
|
9db6efe7a2 | ||
|
|
8b8a22d7fb | ||
|
|
0a70344bc1 | ||
|
|
e77d01911c | ||
|
|
d4c0853e1f | ||
|
|
363a4e959c | ||
|
|
9336a04681 | ||
|
|
214ff38749 | ||
|
|
a8f3c01d8b | ||
|
|
4da6585ef9 | ||
|
|
df40100feb | ||
|
|
f2d92e93fb | ||
|
|
854b3e9c59 | ||
|
|
28ca2b72f1 | ||
|
|
7781c8179f | ||
|
|
69ece3ffa0 | ||
|
|
53adcd92ed |
5
.github/workflows/ccpp.yml
vendored
5
.github/workflows/ccpp.yml
vendored
@@ -43,7 +43,7 @@ jobs:
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: ${{ github.event.repository.name }}.${{ github.sha }}
|
||||
path: fluxengine.FluxEngine.pkg
|
||||
path: fluxengine/FluxEngine.pkg
|
||||
|
||||
build-windows:
|
||||
runs-on: windows-latest
|
||||
@@ -69,6 +69,9 @@ jobs:
|
||||
mingw-w64-i686-nsis
|
||||
zip
|
||||
vim
|
||||
- name: update-protobuf
|
||||
run: |
|
||||
pacman -U --noconfirm https://repo.msys2.org/mingw/mingw32/mingw-w64-i686-protobuf-21.9-1-any.pkg.tar.zst
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
repository: 'davidgiven/fluxengine'
|
||||
|
||||
4
.github/workflows/release.yml
vendored
4
.github/workflows/release.yml
vendored
@@ -36,6 +36,10 @@ jobs:
|
||||
vim
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: update-protobuf
|
||||
run: |
|
||||
pacman -U --noconfirm https://repo.msys2.org/mingw/mingw32/mingw-w64-i686-protobuf-21.9-1-any.pkg.tar.zst
|
||||
|
||||
- name: build
|
||||
run: |
|
||||
make -j2
|
||||
|
||||
12
README.md
12
README.md
@@ -35,11 +35,11 @@ Don't believe me? Watch the demo reel!
|
||||
</div>
|
||||
|
||||
**New!** The FluxEngine client software now works with
|
||||
[GreaseWeazle](https://github.com/keirf/Greaseweazle/wiki) hardware. So, if you
|
||||
[Greaseweazle](https://github.com/keirf/Greaseweazle/wiki) hardware. So, if you
|
||||
can't find a PSoC5 development kit, or don't want to use the Cypress Windows
|
||||
tools for programming it, you can use one of these instead. Very nearly all
|
||||
FluxEngine features are available with the GreaseWeazle and it works out-of-the
|
||||
box. See the [dedicated GreaseWeazle documentation page](doc/greaseweazle.md)
|
||||
FluxEngine features are available with the Greaseweazle and it works out-of-the
|
||||
box. See the [dedicated Greaseweazle documentation page](doc/greaseweazle.md)
|
||||
for more information.
|
||||
|
||||
Where?
|
||||
@@ -65,7 +65,7 @@ following friendly articles:
|
||||
- [Using a FluxEngine](doc/using.md) ∾ what to do with your new hardware ∾
|
||||
flux files and image files ∾ knowing what you're doing
|
||||
|
||||
- [Using GreaseWeazle hardware with the FluxEngine client
|
||||
- [Using Greaseweazle hardware with the FluxEngine client
|
||||
software](doc/greaseweazle.md) ∾ what works ∾ what doesn't work ∾ where to
|
||||
go for help
|
||||
|
||||
@@ -132,13 +132,13 @@ choices because they can store multiple types of file system.
|
||||
| [`n88basic`](doc/disk-n88basic.md) | N88-BASIC: PC8800/PC98 5.25" 77-track 26-sector DSHD | 🦄 | 🦄 | |
|
||||
| [`northstar`](doc/disk-northstar.md) | Northstar: 5.25" hard sectored | 🦄 | 🦄 | |
|
||||
| [`psos`](doc/disk-psos.md) | pSOS: 800kB DSDD with PHILE | 🦄 | 🦄 | PHILE |
|
||||
| [`rolandd20`](doc/disk-rolandd20.md) | Roland D20: 3.5" electronic synthesiser disks | 🦖 | | |
|
||||
| [`rolandd20`](doc/disk-rolandd20.md) | Roland D20: 3.5" electronic synthesiser disks | 🦄 | 🦖 | ROLAND |
|
||||
| [`rx50`](doc/disk-rx50.md) | Digital RX50: 400kB 5.25" 80-track 10-sector SSDD | 🦖 | 🦖 | |
|
||||
| [`smaky6`](doc/disk-smaky6.md) | Smaky 6: 308kB 5.25" 77-track 16-sector SSDD, hard sectored | 🦖 | | SMAKY6 |
|
||||
| [`tids990`](doc/disk-tids990.md) | Texas Instruments DS990: 1126kB 8" DSSD | 🦖 | 🦖 | |
|
||||
| [`tiki`](doc/disk-tiki.md) | Tiki 100: CP/M | | | CPMFS |
|
||||
| [`victor9k`](doc/disk-victor9k.md) | Victor 9000 / Sirius One: 1224kB 5.25" DSDD GCR | 🦖 | 🦖 | |
|
||||
| [`zilogmcz`](doc/disk-zilogmcz.md) | Zilog MCZ: 320kB 8" 77-track SSSD hard-sectored | 🦖 | | |
|
||||
| [`zilogmcz`](doc/disk-zilogmcz.md) | Zilog MCZ: 320kB 8" 77-track SSSD hard-sectored | 🦖 | | ZDOS |
|
||||
{: .datatable }
|
||||
|
||||
<!-- FORMATSEND -->
|
||||
|
||||
@@ -51,26 +51,6 @@ static void write_bits(
|
||||
}
|
||||
}
|
||||
|
||||
void bindump(std::ostream& stream, std::vector<bool>& buffer)
|
||||
{
|
||||
size_t pos = 0;
|
||||
|
||||
while ((pos < buffer.size()) and (pos < 520))
|
||||
{
|
||||
stream << fmt::format("{:5d} : ", pos);
|
||||
for (int i = 0; i < 40; i++)
|
||||
{
|
||||
if ((pos + i) < buffer.size())
|
||||
stream << fmt::format("{:01b}", (buffer[pos + i]));
|
||||
else
|
||||
stream << "-- ";
|
||||
if ((((pos + i + 1) % 8) == 0) and i != 0)
|
||||
stream << " ";
|
||||
}
|
||||
stream << std::endl;
|
||||
pos += 40;
|
||||
}
|
||||
}
|
||||
static std::vector<bool> encode_data(uint8_t input)
|
||||
{
|
||||
/*
|
||||
|
||||
BIN
doc/FluxEngine_eagle_pcb.zip
Normal file
BIN
doc/FluxEngine_eagle_pcb.zip
Normal file
Binary file not shown.
@@ -93,6 +93,22 @@ You're now looking at the _top_ of the board.
|
||||
row of header sockets allowing you to plug the board directly onto the floppy
|
||||
disk drive; for simplicity I'm leaving that as an exercise for the reader.)
|
||||
|
||||
### If you want to use a PCB
|
||||
|
||||
Alternatively, you can make an actual PCB!
|
||||
|
||||
<div style="text-align: center">
|
||||
<a href="pcb.png"><img src="pcb.png" style="width:80%" alt="the PCB schematic"></a>
|
||||
</div>
|
||||
|
||||
This is a passive breakout board designed to take a PSoC5 development board, a
|
||||
standard 34-way PC connector, and a 50-way 8" drive connector. It was
|
||||
contributed by a user --- thanks!
|
||||
|
||||
<a href="FluxEngine_eagle_pcb.zip">Download this to get it</a>. This package
|
||||
contains the layout in Eagle format, a printable PDF of the PCB layout, and
|
||||
gerbers suitable for sending off for manufacture.
|
||||
|
||||
### Grounding
|
||||
|
||||
You _also_ need to solder a wire between a handy GND pin on the board and
|
||||
@@ -185,10 +201,14 @@ 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
|
||||
install some support packages.
|
||||
|
||||
- For Linux (this is Ubuntu, but this should apply to Debian too):
|
||||
- For Linux with Ubuntu/Debian:
|
||||
`libusb-1.0-0-dev`, `libsqlite3-dev`, `zlib1g-dev`,
|
||||
`libudev-dev`, `protobuf-compiler`, `libwxgtk3.0-gtk3-dev`,
|
||||
`libfmt-dev`.
|
||||
- For Linux with Fedora/Red Hat:
|
||||
`git`, `make`, `gcc`, `gcc-c++`, `xxd`, `protobuf-compiler`,
|
||||
`protobuf-devel`, `fmt-devel`, `systemd-devel`, `wxGTK3-devel`,
|
||||
`libsqlite3x-devel`
|
||||
- For OSX with Homebrew: `libusb`, `pkg-config`, `sqlite`,
|
||||
`protobuf`, `truncate`, `wxwidgets`, `fmt`.
|
||||
- For Windows with MSYS2: `make`, `mingw-w64-i686-libusb`,
|
||||
|
||||
@@ -1,4 +1,15 @@
|
||||
40track_drive
|
||||
====
|
||||
## Adjust configuration for a 40-track drive
|
||||
<!-- This file is automatically generated. Do not edit. -->
|
||||
# Adjust configuration for a 40-track drive
|
||||
|
||||
(This format has no documentation. Please file a bug.)
|
||||
This is an extension profile; adding this to the command line will configure
|
||||
FluxEngine to read from 40-track, 48tpi 5.25" drives. You have to tell it because there is
|
||||
no way to detect this automatically.
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
fluxengine read ibm --180 40track_drive
|
||||
```
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
acornadfs
|
||||
====
|
||||
## BBC Micro, Archimedes
|
||||
<!-- This file is automatically generated. Do not edit. -->
|
||||
# BBC Micro, Archimedes
|
||||
|
||||
Acorn ADFS disks are used by the 6502-based BBC Micro and ARM-based Archimedes
|
||||
series of computers. They are yet another variation on MFM encoded IBM scheme
|
||||
@@ -18,5 +20,20 @@ they might require nudging as the side order can't be reliably autodetected.
|
||||
|
||||
## Options
|
||||
|
||||
(no options)
|
||||
- Format variants:
|
||||
- `160`: 160kB 3.5" or 5.25" 40-track SSDD; S format
|
||||
- `320`: 320kB 3.5" or 5.25" 80-track SSDD; M format
|
||||
- `640`: 640kB 3.5" or 5.25" 80-track DSDD; L format
|
||||
- `800`: 800kB 3.5" 80-track DSDD; D and E formats
|
||||
- `1600`: 1600kB 3.5" 80-track DSHD; F formats
|
||||
|
||||
## Examples
|
||||
|
||||
To read:
|
||||
|
||||
- `fluxengine read acornadfs --160 -s drive:0 -o acornadfs.img`
|
||||
- `fluxengine read acornadfs --320 -s drive:0 -o acornadfs.img`
|
||||
- `fluxengine read acornadfs --640 -s drive:0 -o acornadfs.img`
|
||||
- `fluxengine read acornadfs --800 -s drive:0 -o acornadfs.img`
|
||||
- `fluxengine read acornadfs --1600 -s drive:0 -o acornadfs.img`
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
acorndfs
|
||||
====
|
||||
## Acorn Atom, BBC Micro series
|
||||
<!-- This file is automatically generated. Do not edit. -->
|
||||
# Acorn Atom, BBC Micro series
|
||||
|
||||
Acorn DFS disks are used by the Acorn Atom and BBC Micro series of computers.
|
||||
They are pretty standard FM encoded IBM scheme disks, with 256-sectors and
|
||||
@@ -14,7 +16,21 @@ requires a bit of fiddling as they have the same tracks on twice.
|
||||
|
||||
## Options
|
||||
|
||||
(no options)
|
||||
- Format variants:
|
||||
- `100`: 100kB 40-track SSSD
|
||||
- `200`: 200kB 80-track SSSD
|
||||
|
||||
## Examples
|
||||
|
||||
To read:
|
||||
|
||||
- `fluxengine read acorndfs --100 -s drive:0 -o acorndfs.img`
|
||||
- `fluxengine read acorndfs --200 -s drive:0 -o acorndfs.img`
|
||||
|
||||
To write:
|
||||
|
||||
- `fluxengine write acorndfs --100 -d drive:0 -i acorndfs.img`
|
||||
- `fluxengine write acorndfs --200 -d drive:0 -i acorndfs.img`
|
||||
|
||||
## References
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
aeslanier
|
||||
====
|
||||
## 616kB 5.25" 77-track SSDD hard sectored
|
||||
<!-- This file is automatically generated. Do not edit. -->
|
||||
# 616kB 5.25" 77-track SSDD hard sectored
|
||||
|
||||
Back in 1980 Lanier released a series of very early integrated word processor
|
||||
appliances, the No Problem. These were actually [rebranded AES Data Superplus
|
||||
@@ -31,6 +33,12 @@ based on what looks right. If anyone knows _anything_ about these disks,
|
||||
|
||||
(no options)
|
||||
|
||||
## Examples
|
||||
|
||||
To read:
|
||||
|
||||
- `fluxengine read aeslanier -s drive:0 -o aeslanier.img`
|
||||
|
||||
## References
|
||||
|
||||
* [SA800 Diskette Storage Drive - Theory Of
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
agat
|
||||
====
|
||||
## 840kB 5.25" 80-track DS
|
||||
<!-- This file is automatically generated. Do not edit. -->
|
||||
# 840kB 5.25" 80-track DS
|
||||
|
||||
The Agat (Russian: ↊fd74
|
||||
1983. These were based around a 6502 and were nominally Apple II-compatible
|
||||
@@ -14,6 +16,16 @@ profile.
|
||||
|
||||
(no options)
|
||||
|
||||
## Examples
|
||||
|
||||
To read:
|
||||
|
||||
- `fluxengine read agat -s drive:0 -o agat.img`
|
||||
|
||||
To write:
|
||||
|
||||
- `fluxengine write agat -d drive:0 -i agat.img`
|
||||
|
||||
## References
|
||||
|
||||
- [Magazine article on the
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
amiga
|
||||
====
|
||||
## 880kB 3.5" DSDD
|
||||
<!-- This file is automatically generated. Do not edit. -->
|
||||
# 880kB 3.5" DSDD
|
||||
|
||||
Amiga disks use MFM, but don't use IBM scheme. Instead, the entire track is
|
||||
read and written as a unit, with each sector butting up against the previous
|
||||
@@ -16,7 +18,19 @@ distinctly subpar and not particularly good at detecting errors.
|
||||
|
||||
## Options
|
||||
|
||||
(no options)
|
||||
- Sector size:
|
||||
- `without_metadata`: 512-byte sectors
|
||||
- `with_metadata`: 528-byte sectors
|
||||
|
||||
## Examples
|
||||
|
||||
To read:
|
||||
|
||||
- `fluxengine read amiga -s drive:0 -o amiga.adf`
|
||||
|
||||
To write:
|
||||
|
||||
- `fluxengine write amiga -d drive:0 -i amiga.adf`
|
||||
|
||||
## References
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
ampro
|
||||
====
|
||||
## CP/M
|
||||
<!-- This file is automatically generated. Do not edit. -->
|
||||
# CP/M
|
||||
|
||||
The Ampro Little Board was a very simple and cheap Z80-based computer from
|
||||
1984, which ran CP/M. It was, in fact, a single PCB which you could mount
|
||||
@@ -33,7 +35,16 @@ kayinfo.lbr
|
||||
|
||||
## Options
|
||||
|
||||
(no options)
|
||||
- Format variants:
|
||||
- `400`: 400kB 40-track DSDD
|
||||
- `800`: 800kB 80-track DSDD
|
||||
|
||||
## Examples
|
||||
|
||||
To read:
|
||||
|
||||
- `fluxengine read ampro --400 -s drive:0 -o ampro.img`
|
||||
- `fluxengine read ampro --800 -s drive:0 -o ampro.img`
|
||||
|
||||
## References
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
apple2
|
||||
====
|
||||
## Prodos, Appledos, and CP/M
|
||||
<!-- This file is automatically generated. Do not edit. -->
|
||||
# Prodos, Appledos, and CP/M
|
||||
|
||||
Apple II disks are nominally fairly sensible 40-track, single-sided, 256
|
||||
bytes-per-sector jobs. However, they come in two varieties: DOS 3.3/ProDOS and
|
||||
@@ -42,7 +44,7 @@ volume.
|
||||
|
||||
## Options
|
||||
|
||||
- Format variant:
|
||||
- Format variants:
|
||||
- `140`: 140kB 5.25" 35-track SS
|
||||
- `640`: 640kB 5.25" 80-track DS
|
||||
- Filesystem and sector skew:
|
||||
@@ -52,6 +54,18 @@ volume.
|
||||
- `cpm`: use CP/M soft sector skew and filesystem
|
||||
- `side1`: for AppleDOS file system access, read the volume on side 1 of a disk
|
||||
|
||||
## Examples
|
||||
|
||||
To read:
|
||||
|
||||
- `fluxengine read apple2 --140 -s drive:0 -o apple2.img`
|
||||
- `fluxengine read apple2 --640 -s drive:0 -o apple2.img`
|
||||
|
||||
To write:
|
||||
|
||||
- `fluxengine write apple2 --140 -d drive:0 -i apple2.img`
|
||||
- `fluxengine write apple2 --640 -d drive:0 -i apple2.img`
|
||||
|
||||
## References
|
||||
|
||||
- [Beneath Apple DOS](https://fabiensanglard.net/fd_proxy/prince_of_persia/Beneath%20Apple%20DOS.pdf)
|
||||
|
||||
@@ -1,4 +1,16 @@
|
||||
apple2_drive
|
||||
====
|
||||
## Adjust configuration for a 40-track Apple II drive
|
||||
<!-- This file is automatically generated. Do not edit. -->
|
||||
# Adjust configuration for a 40-track Apple II drive
|
||||
|
||||
(This format has no documentation. Please file a bug.)
|
||||
This is an extension profile; adding this to the command line will configure
|
||||
FluxEngine to adjust the pinout and track spacing to work with an Apple II
|
||||
drive. This only works on Greaseweazle hardware and requires a custom
|
||||
connector.
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
fluxengine read apple2 --160 apple2_drive
|
||||
```
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
atarist
|
||||
====
|
||||
## Almost PC compatible
|
||||
<!-- This file is automatically generated. Do not edit. -->
|
||||
# Almost PC compatible
|
||||
|
||||
Atari ST disks are standard MFM encoded IBM scheme disks without an IAM header.
|
||||
Disks are typically formatted 512 bytes per sector with between 9-10 (sometimes
|
||||
@@ -13,7 +15,39 @@ Be aware that many PC drives (including mine) won't do the 82 track formats.
|
||||
|
||||
## Options
|
||||
|
||||
(no options)
|
||||
- Format variants:
|
||||
- `360`: 360kB 3.5" 80-track 9-sector SSDD
|
||||
- `370`: 370kB 3.5" 82-track 9-sector SSDD
|
||||
- `400`: 400kB 3.5" 80-track 10-sector SSDD
|
||||
- `410`: 410kB 3.5" 82-track 10-sector SSDD
|
||||
- `720`: 720kB 3.5" 80-track 9-sector DSDD
|
||||
- `740`: 740kB 3.5" 82-track 9-sector DSDD
|
||||
- `800`: 800kB 3.5" 80-track 10-sector DSDD
|
||||
- `820`: 820kB 3.5" 82-track 10-sector DSDD
|
||||
|
||||
## Examples
|
||||
|
||||
To read:
|
||||
|
||||
- `fluxengine read atarist --360 -s drive:0 -o atarist.img`
|
||||
- `fluxengine read atarist --370 -s drive:0 -o atarist.img`
|
||||
- `fluxengine read atarist --400 -s drive:0 -o atarist.img`
|
||||
- `fluxengine read atarist --410 -s drive:0 -o atarist.img`
|
||||
- `fluxengine read atarist --720 -s drive:0 -o atarist.img`
|
||||
- `fluxengine read atarist --740 -s drive:0 -o atarist.img`
|
||||
- `fluxengine read atarist --800 -s drive:0 -o atarist.img`
|
||||
- `fluxengine read atarist --820 -s drive:0 -o atarist.img`
|
||||
|
||||
To write:
|
||||
|
||||
- `fluxengine write atarist --360 -d drive:0 -i atarist.img`
|
||||
- `fluxengine write atarist --370 -d drive:0 -i atarist.img`
|
||||
- `fluxengine write atarist --400 -d drive:0 -i atarist.img`
|
||||
- `fluxengine write atarist --410 -d drive:0 -i atarist.img`
|
||||
- `fluxengine write atarist --720 -d drive:0 -i atarist.img`
|
||||
- `fluxengine write atarist --740 -d drive:0 -i atarist.img`
|
||||
- `fluxengine write atarist --800 -d drive:0 -i atarist.img`
|
||||
- `fluxengine write atarist --820 -d drive:0 -i atarist.img`
|
||||
|
||||
## References
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
bk
|
||||
====
|
||||
## 800kB 5.25"/3.5" 80-track 10-sector DSDD
|
||||
<!-- This file is automatically generated. Do not edit. -->
|
||||
# 800kB 5.25"/3.5" 80-track 10-sector DSDD
|
||||
|
||||
The BK (an abbreviation for 1ba9
|
||||
is a Soviet era personal computer from Elektronika based on a PDP-11
|
||||
@@ -16,3 +18,13 @@ on what was available at the time, with the same format on both.
|
||||
|
||||
(no options)
|
||||
|
||||
## Examples
|
||||
|
||||
To read:
|
||||
|
||||
- `fluxengine read bk -s drive:0 -o bk800.img`
|
||||
|
||||
To write:
|
||||
|
||||
- `fluxengine write bk -d drive:0 -i bk800.img`
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
brother
|
||||
====
|
||||
## GCR family
|
||||
<!-- This file is automatically generated. Do not edit. -->
|
||||
# GCR family
|
||||
|
||||
Brother word processor disks are weird, using custom tooling and chipsets.
|
||||
They are completely not PC compatible in every possible way other than the
|
||||
@@ -34,7 +36,21 @@ investigate.
|
||||
|
||||
## Options
|
||||
|
||||
(no options)
|
||||
- Format variants:
|
||||
- `120`: 120kB 3.5" 39-track SS GCR
|
||||
- `240`: 240kB 3.5" 78-track SS GCR
|
||||
|
||||
## Examples
|
||||
|
||||
To read:
|
||||
|
||||
- `fluxengine read brother --120 -s drive:0 -o brother.img`
|
||||
- `fluxengine read brother --240 -s drive:0 -o brother.img`
|
||||
|
||||
To write:
|
||||
|
||||
- `fluxengine write brother --120 -d drive:0 -i brother.img`
|
||||
- `fluxengine write brother --240 -d drive:0 -i brother.img`
|
||||
|
||||
Dealing with misaligned disks
|
||||
-----------------------------
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
commodore
|
||||
====
|
||||
## 1541, 1581, 8050 and variations
|
||||
<!-- This file is automatically generated. Do not edit. -->
|
||||
# 1541, 1581, 8050 and variations
|
||||
|
||||
Commodore 8-bit computer disks come in two varieties: GCR, which are the
|
||||
overwhelming majority; and MFM, only used on the 1571 and 1581. The latter were
|
||||
@@ -41,7 +43,29 @@ A CMD FD2000 disk (a popular third-party Commodore disk drive)
|
||||
|
||||
## Options
|
||||
|
||||
(no options)
|
||||
- Format variants:
|
||||
- `171`: 171kB 1541, 35-track variant
|
||||
- `192`: 192kB 1541, 40-track variant
|
||||
- `800`: 800kB 3.5" 1581
|
||||
- `1042`: 1042kB 5.25" 8051
|
||||
- `1620`: 1620kB, CMD FD2000
|
||||
|
||||
## Examples
|
||||
|
||||
To read:
|
||||
|
||||
- `fluxengine read commodore --171 -s drive:0 -o commodore.d64`
|
||||
- `fluxengine read commodore --192 -s drive:0 -o commodore.d64`
|
||||
- `fluxengine read commodore --800 -s drive:0 -o commodore.d64`
|
||||
- `fluxengine read commodore --1042 -s drive:0 -o commodore.d64`
|
||||
- `fluxengine read commodore --1620 -s drive:0 -o commodore.d64`
|
||||
|
||||
To write:
|
||||
|
||||
- `fluxengine write commodore --171 -d drive:0 -i commodore.d64`
|
||||
- `fluxengine write commodore --192 -d drive:0 -i commodore.d64`
|
||||
- `fluxengine write commodore --800 -d drive:0 -i commodore.d64`
|
||||
- `fluxengine write commodore --1620 -d drive:0 -i commodore.d64`
|
||||
|
||||
## References
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
eco1
|
||||
====
|
||||
## CP/M; 1210kB 77-track mixed format DSHD
|
||||
<!-- This file is automatically generated. Do not edit. -->
|
||||
# CP/M; 1210kB 77-track mixed format DSHD
|
||||
|
||||
The Eco1 is a Italian CP/M machine produced in 1982. It had 64kB of RAM, in
|
||||
later models expandable up to 384kB, and _two_ Z80 processors. One of these was
|
||||
@@ -27,6 +29,12 @@ images.
|
||||
|
||||
(no options)
|
||||
|
||||
## Examples
|
||||
|
||||
To read:
|
||||
|
||||
- `fluxengine read eco1 -s drive:0 -o eco1.img`
|
||||
|
||||
## References
|
||||
|
||||
- [Apulio Retrocomputing's page on the
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
epsonpf10
|
||||
====
|
||||
## CP/M; 3.5" 40-track DSDD
|
||||
<!-- This file is automatically generated. Do not edit. -->
|
||||
# CP/M; 3.5" 40-track DSDD
|
||||
|
||||
The Epson PF10 is the disk unit for the Epson Z80 series of 'laptops', running
|
||||
CP/M. It uses a single-sided 40-track 3.5" format, which is unusual, but the
|
||||
@@ -9,3 +11,9 @@ format itself is yet another IBM scheme variant.
|
||||
|
||||
(no options)
|
||||
|
||||
## Examples
|
||||
|
||||
To read:
|
||||
|
||||
- `fluxengine read epsonpf10 -s drive:0 -o epsonpf10.img`
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
f85
|
||||
====
|
||||
## 461kB 5.25" 77-track SS
|
||||
<!-- This file is automatically generated. Do not edit. -->
|
||||
# 461kB 5.25" 77-track SS
|
||||
|
||||
The Durango F85 was an early office computer based around a 5MHz 8085 processor,
|
||||
sold in 1977. It had an impressive 64kB of RAM, upgradable to 128kB, and ran
|
||||
@@ -30,6 +32,12 @@ touch](https://github.com/davidgiven/fluxengine/issues/new).
|
||||
|
||||
(no options)
|
||||
|
||||
## Examples
|
||||
|
||||
To read:
|
||||
|
||||
- `fluxengine read f85 -s drive:0 -o f85.img`
|
||||
|
||||
## References
|
||||
|
||||
There's amazingly little information about these things.
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
fb100
|
||||
====
|
||||
## 100kB 3.5" 40-track SSSD
|
||||
<!-- This file is automatically generated. Do not edit. -->
|
||||
# 100kB 3.5" 40-track SSSD
|
||||
|
||||
The Brother FB-100 is a serial-attached smart floppy drive used by a several
|
||||
different machines for mass storage, including the Tandy Model 100 and
|
||||
@@ -24,6 +26,12 @@ I don't have access to one of those disks.
|
||||
|
||||
(no options)
|
||||
|
||||
## Examples
|
||||
|
||||
To read:
|
||||
|
||||
- `fluxengine read fb100 -s drive:0 -o fb100.img`
|
||||
|
||||
## References
|
||||
|
||||
- [Tandy Portable Disk Drive operations
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
hplif
|
||||
====
|
||||
## a variety of disk formats used by HP
|
||||
<!-- This file is automatically generated. Do not edit. -->
|
||||
# a variety of disk formats used by HP
|
||||
|
||||
LIF, a.k.a. Logical Interchange Format, is a series of formats used by
|
||||
Hewlett-Packard across their entire range of computers, from calculators to
|
||||
@@ -11,5 +13,22 @@ encoding scheme.
|
||||
|
||||
## Options
|
||||
|
||||
(no options)
|
||||
- Format variants:
|
||||
- `264`: 264kB 3.5" 66-track SSDD; HP9121 format
|
||||
- `616`: 616kB 3.5" 77-track DSDD
|
||||
- `770`: 770kB 3.5" 77-track DSDD
|
||||
|
||||
## Examples
|
||||
|
||||
To read:
|
||||
|
||||
- `fluxengine read hplif --264 -s drive:0 -o hplif.img`
|
||||
- `fluxengine read hplif --616 -s drive:0 -o hplif.img`
|
||||
- `fluxengine read hplif --770 -s drive:0 -o hplif.img`
|
||||
|
||||
To write:
|
||||
|
||||
- `fluxengine write hplif --264 -d drive:0 -i hplif.img`
|
||||
- `fluxengine write hplif --616 -d drive:0 -i hplif.img`
|
||||
- `fluxengine write hplif --770 -d drive:0 -i hplif.img`
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
ibm
|
||||
====
|
||||
## Generic PC 3.5"/5.25" disks
|
||||
<!-- This file is automatically generated. Do not edit. -->
|
||||
# Generic PC 3.5"/5.25" disks
|
||||
|
||||
IBM scheme disks are _the_ most common disk format, ever. They're used by a
|
||||
huge variety of different systems, and they come in a huge variety of different
|
||||
@@ -36,7 +38,47 @@ image format. FluxEngine will use these parameters.
|
||||
|
||||
## Options
|
||||
|
||||
(no options)
|
||||
- Format variants:
|
||||
- `auto`: try to autodetect the format (unreliable)
|
||||
- `160`: 160kB 5.25" 40-track 8-sector SSDD
|
||||
- `180`: 180kB 5.25" 40-track 9-sector SSDD
|
||||
- `320`: 320kB 5.25" 40-track 8-sector DSDD
|
||||
- `360`: 360kB 5.25" 40-track 9-sector DSDD
|
||||
- `720_96`: 720kB 5.25" 80-track 9-sector DSDD
|
||||
- `720_135`: 720kB 3.5" 80-track 9-sector DSDD
|
||||
- `1200`: 1200kB 5.25" 80-track 15-sector DSHD
|
||||
- `1232`: 1232kB 5.25" 77-track 8-sector DSHD
|
||||
- `1440`: 1440kB 3.5" 80-track 18-sector DSHD
|
||||
- `1680`: 1680kB 3.5" 80-track 21-sector DSHD; DMF
|
||||
|
||||
## Examples
|
||||
|
||||
To read:
|
||||
|
||||
- `fluxengine read ibm --auto -s drive:0 -o ibm.img`
|
||||
- `fluxengine read ibm --160 -s drive:0 -o ibm.img`
|
||||
- `fluxengine read ibm --180 -s drive:0 -o ibm.img`
|
||||
- `fluxengine read ibm --320 -s drive:0 -o ibm.img`
|
||||
- `fluxengine read ibm --360 -s drive:0 -o ibm.img`
|
||||
- `fluxengine read ibm --720_96 -s drive:0 -o ibm.img`
|
||||
- `fluxengine read ibm --720_135 -s drive:0 -o ibm.img`
|
||||
- `fluxengine read ibm --1200 -s drive:0 -o ibm.img`
|
||||
- `fluxengine read ibm --1232 -s drive:0 -o ibm.img`
|
||||
- `fluxengine read ibm --1440 -s drive:0 -o ibm.img`
|
||||
- `fluxengine read ibm --1680 -s drive:0 -o ibm.img`
|
||||
|
||||
To write:
|
||||
|
||||
- `fluxengine write ibm --160 -d drive:0 -i ibm.img`
|
||||
- `fluxengine write ibm --180 -d drive:0 -i ibm.img`
|
||||
- `fluxengine write ibm --320 -d drive:0 -i ibm.img`
|
||||
- `fluxengine write ibm --360 -d drive:0 -i ibm.img`
|
||||
- `fluxengine write ibm --720_96 -d drive:0 -i ibm.img`
|
||||
- `fluxengine write ibm --720_135 -d drive:0 -i ibm.img`
|
||||
- `fluxengine write ibm --1200 -d drive:0 -i ibm.img`
|
||||
- `fluxengine write ibm --1232 -d drive:0 -i ibm.img`
|
||||
- `fluxengine write ibm --1440 -d drive:0 -i ibm.img`
|
||||
- `fluxengine write ibm --1680 -d drive:0 -i ibm.img`
|
||||
|
||||
Mixed-format disks
|
||||
------------------
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
icl30
|
||||
====
|
||||
## CP/M; 263kB 35-track DSSD
|
||||
<!-- This file is automatically generated. Do not edit. -->
|
||||
# CP/M; 263kB 35-track DSSD
|
||||
|
||||
The ICL Model 30 is a reasonably standard CP/M machine using 35-track single
|
||||
density disks and the traditional CP/M 128-byte secotrs --- 30 of them per
|
||||
@@ -9,3 +11,9 @@ track! Other than that it's another IBM scheme variation.
|
||||
|
||||
(no options)
|
||||
|
||||
## Examples
|
||||
|
||||
To read:
|
||||
|
||||
- `fluxengine read icl30 -s drive:0 -o icl30.img`
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
mac
|
||||
====
|
||||
## 400kB/800kB 3.5" GCR
|
||||
<!-- This file is automatically generated. Do not edit. -->
|
||||
# 400kB/800kB 3.5" GCR
|
||||
|
||||
Macintosh disks come in two varieties: the newer 1440kB ones, which are
|
||||
perfectly ordinary PC disks you should use the `ibm` profile to read them, and
|
||||
@@ -36,11 +38,23 @@ standard for disk images is to omit it. If you want them, specify that you want
|
||||
|
||||
## Options
|
||||
|
||||
- Format variant:
|
||||
- Format variants:
|
||||
- `400`: 400kB 80-track SSDD
|
||||
- `800`: 800kB 80-track DSDD
|
||||
- `metadata`: read/write 524 byte sectors
|
||||
|
||||
## Examples
|
||||
|
||||
To read:
|
||||
|
||||
- `fluxengine read mac --400 -s drive:0 -o mac.dsk`
|
||||
- `fluxengine read mac --800 -s drive:0 -o mac.dsk`
|
||||
|
||||
To write:
|
||||
|
||||
- `fluxengine write mac --400 -d drive:0 -i mac.dsk`
|
||||
- `fluxengine write mac --800 -d drive:0 -i mac.dsk`
|
||||
|
||||
## References
|
||||
|
||||
- [MAME's ap_dsk35.cpp file](https://github.com/mamedev/mame/blob/4263a71e64377db11392c458b580c5ae83556bc7/src/lib/formats/ap_dsk35.cpp),
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
micropolis
|
||||
====
|
||||
## 100tpi MetaFloppy disks
|
||||
<!-- This file is automatically generated. Do not edit. -->
|
||||
# 100tpi MetaFloppy disks
|
||||
|
||||
Micropolis MetaFloppy disks use MFM and hard sectors. Mod I was 48 TPI and
|
||||
stored 143k per side. Mod II was 100 TPI and stored 315k per side. Each of the
|
||||
@@ -45,6 +47,16 @@ need to apply extra options to change the format if desired.
|
||||
- `630`: 630kB 5.25" DSDD hard-sectored; Micropolis MetaFloppy Mod II
|
||||
- `vgi`: Read/write VGI format images with 275 bytes per sector
|
||||
|
||||
## Examples
|
||||
|
||||
To read:
|
||||
|
||||
- `fluxengine read micropolis -s drive:0 -o micropolis.img`
|
||||
|
||||
To write:
|
||||
|
||||
- `fluxengine write micropolis -d drive:0 -i micropolis.img`
|
||||
|
||||
## References
|
||||
|
||||
- [Micropolis 1040/1050 S-100 Floppy Disk Subsystems User's Manual][micropolis1040/1050].
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
mx
|
||||
====
|
||||
## Soviet-era PDP-11 clone
|
||||
<!-- This file is automatically generated. Do not edit. -->
|
||||
# Soviet-era PDP-11 clone
|
||||
|
||||
The DVK (in Russian, 沾7d65
|
||||
Computing Complex) was a late 1970s Soviet personal computer, a cut-down
|
||||
@@ -40,7 +42,20 @@ Words are all stored little-endian.
|
||||
|
||||
## Options
|
||||
|
||||
(no options)
|
||||
- Format variants:
|
||||
- `110`: 110kB 5.25" 40-track SSSD
|
||||
- `220ds`: 220kB 5.25" 40-track DSSD
|
||||
- `220ss`: 220kB 5.25" 80-track SSSD
|
||||
- `440`: 440kB 5.25" 80-track DSSD
|
||||
|
||||
## Examples
|
||||
|
||||
To read:
|
||||
|
||||
- `fluxengine read mx --110 -s drive:0 -o mx.img`
|
||||
- `fluxengine read mx --220ds -s drive:0 -o mx.img`
|
||||
- `fluxengine read mx --220ss -s drive:0 -o mx.img`
|
||||
- `fluxengine read mx --440 -s drive:0 -o mx.img`
|
||||
|
||||
## References
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
n88basic
|
||||
====
|
||||
## PC8800/PC98 5.25" 77-track 26-sector DSHD
|
||||
<!-- This file is automatically generated. Do not edit. -->
|
||||
# PC8800/PC98 5.25" 77-track 26-sector DSHD
|
||||
|
||||
The N88-BASIC disk format is the one used by the operating system of the same
|
||||
name for the Japanese PC8800 and PC98 computers. It is another IBM scheme
|
||||
@@ -12,3 +14,13 @@ boot ROM could only read single density data.)
|
||||
|
||||
(no options)
|
||||
|
||||
## Examples
|
||||
|
||||
To read:
|
||||
|
||||
- `fluxengine read n88basic -s drive:0 -o n88basic.img`
|
||||
|
||||
To write:
|
||||
|
||||
- `fluxengine write n88basic -d drive:0 -i n88basic.img`
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
northstar
|
||||
====
|
||||
## 5.25" hard sectored
|
||||
<!-- This file is automatically generated. Do not edit. -->
|
||||
# 5.25" hard sectored
|
||||
|
||||
Northstar Floppy disks use 10-sector hard sectored disks with either FM or MFM
|
||||
encoding. They may be single- or double-sided. Each of the 10 sectors contains
|
||||
@@ -20,7 +22,24 @@ equivalent to .img images.
|
||||
|
||||
## Options
|
||||
|
||||
(no options)
|
||||
- Format variants:
|
||||
- `87`: 87.5kB 5.25" 35-track SSSD hard-sectored
|
||||
- `175`: 175kB 5.25" 40-track SSDD hard-sectored
|
||||
- `350`: 350kB 5.25" 40-track DSDD hard-sectored
|
||||
|
||||
## Examples
|
||||
|
||||
To read:
|
||||
|
||||
- `fluxengine read northstar --87 -s drive:0 -o northstar.nsi`
|
||||
- `fluxengine read northstar --175 -s drive:0 -o northstar.nsi`
|
||||
- `fluxengine read northstar --350 -s drive:0 -o northstar.nsi`
|
||||
|
||||
To write:
|
||||
|
||||
- `fluxengine write northstar --87 -d drive:0 -i northstar.nsi`
|
||||
- `fluxengine write northstar --175 -d drive:0 -i northstar.nsi`
|
||||
- `fluxengine write northstar --350 -d drive:0 -i northstar.nsi`
|
||||
|
||||
## References
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
psos
|
||||
====
|
||||
## 800kB DSDD with PHILE
|
||||
<!-- This file is automatically generated. Do not edit. -->
|
||||
# 800kB DSDD with PHILE
|
||||
|
||||
pSOS was an influential real-time operating system from the 1980s, used mainly
|
||||
on 68000-based machines, lasting up until about 2000 when it was bought (and
|
||||
@@ -18,3 +20,13 @@ and, oddly, swapped sides.
|
||||
|
||||
(no options)
|
||||
|
||||
## Examples
|
||||
|
||||
To read:
|
||||
|
||||
- `fluxengine read psos -s drive:0 -o pme.img`
|
||||
|
||||
To write:
|
||||
|
||||
- `fluxengine write psos -d drive:0 -i pme.img`
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
rolandd20
|
||||
====
|
||||
## 3.5" electronic synthesiser disks
|
||||
<!-- This file is automatically generated. Do not edit. -->
|
||||
# 3.5" electronic synthesiser disks
|
||||
|
||||
The Roland D20 is a classic electronic synthesiser with a built-in floppy
|
||||
drive, used for saving MIDI sequences and samples.
|
||||
@@ -7,9 +9,13 @@ drive, used for saving MIDI sequences and samples.
|
||||
Weirdly, it seems to use precisely the same format as the Brother word
|
||||
processors: a thoroughly non-IBM-compatible custom GCR system.
|
||||
|
||||
FluxEngine pretends to support this, but it has had almost no testing, the only
|
||||
disk image I have seen for it was mostly corrupt, and very little is known
|
||||
about the format, so I have no idea whether it's correct or not.
|
||||
FluxEngine supports both reading and writing D20 disks, as well as basic support
|
||||
for the filesystem, allowing files to be read from and written to D20 disks.
|
||||
Note that the D20 was never intended to support arbitrary files on its disks and
|
||||
is very likely to crash if you put unexpected files on a disk. In addition,
|
||||
while the file format itself is currently unknown, there is a header at the top
|
||||
of the file containing what appears to be the name shown in the D20 file
|
||||
browser, so the name by which you see it is not necessarily the filename.
|
||||
|
||||
Please [get in touch](https://github.com/davidgiven/fluxengine/issues/new) if
|
||||
you know anything about it.
|
||||
@@ -18,3 +24,13 @@ you know anything about it.
|
||||
|
||||
(no options)
|
||||
|
||||
## Examples
|
||||
|
||||
To read:
|
||||
|
||||
- `fluxengine read rolandd20 -s drive:0 -o rolandd20.img`
|
||||
|
||||
To write:
|
||||
|
||||
- `fluxengine write rolandd20 -d drive:0 -i rolandd20.img`
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
rx50
|
||||
====
|
||||
## 400kB 5.25" 80-track 10-sector SSDD
|
||||
<!-- This file is automatically generated. Do not edit. -->
|
||||
# 400kB 5.25" 80-track 10-sector SSDD
|
||||
|
||||
The Digital RX50 is one of the external floppy drive units used by Digital's
|
||||
range of computers, especially the DEC Rainbow microcomputer. It is a fairly
|
||||
@@ -9,3 +11,13 @@ vanilla single-sided IBM scheme variation.
|
||||
|
||||
(no options)
|
||||
|
||||
## Examples
|
||||
|
||||
To read:
|
||||
|
||||
- `fluxengine read rx50 -s drive:0 -o rx50.img`
|
||||
|
||||
To write:
|
||||
|
||||
- `fluxengine write rx50 -d drive:0 -i rx50.img`
|
||||
|
||||
|
||||
@@ -1,4 +1,15 @@
|
||||
shugart_drive
|
||||
====
|
||||
## Adjust configuration for a Shugart drive
|
||||
<!-- This file is automatically generated. Do not edit. -->
|
||||
# Adjust configuration for a Shugart drive
|
||||
|
||||
(This format has no documentation. Please file a bug.)
|
||||
This is an extension profile; adding this to the command line will configure
|
||||
FluxEngine to adjust the pinout to work with a Shugart drive. This only works
|
||||
on Greaseweazle hardware.
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
fluxengine read ibm --720 shugart_drive
|
||||
```
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
smaky6
|
||||
====
|
||||
## 308kB 5.25" 77-track 16-sector SSDD, hard sectored
|
||||
<!-- This file is automatically generated. Do not edit. -->
|
||||
# 308kB 5.25" 77-track 16-sector SSDD, hard sectored
|
||||
|
||||
The Smaky 6 is a Swiss computer from 1978 produced by Epsitec. It's based
|
||||
around a Z80 processor and has one or two Micropolis 5.25" drives which use
|
||||
@@ -20,6 +22,12 @@ this is completely correct, so don't trust it!
|
||||
|
||||
(no options)
|
||||
|
||||
## Examples
|
||||
|
||||
To read:
|
||||
|
||||
- `fluxengine read smaky6 -s drive:0 -o smaky6.img`
|
||||
|
||||
## References
|
||||
|
||||
- [Smaky Info, 1978-2002 (in French)](https://www.smaky.ch/theme.php?id=sminfo)
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
tids990
|
||||
====
|
||||
## 1126kB 8" DSSD
|
||||
<!-- This file is automatically generated. Do not edit. -->
|
||||
# 1126kB 8" DSSD
|
||||
|
||||
The Texas Instruments DS990 was a multiuser modular computing system from 1998,
|
||||
based around the TMS-9900 processor (as used by the TI-99). It had an 8" floppy
|
||||
@@ -20,6 +22,16 @@ FluxEngine will read and write these (but only the DSDD MFM variant).
|
||||
|
||||
(no options)
|
||||
|
||||
## Examples
|
||||
|
||||
To read:
|
||||
|
||||
- `fluxengine read tids990 -s drive:0 -o tids990.img`
|
||||
|
||||
To write:
|
||||
|
||||
- `fluxengine write tids990 -d drive:0 -i tids990.img`
|
||||
|
||||
## References
|
||||
|
||||
- [The FD1000 Depot Maintenance
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
tiki
|
||||
====
|
||||
## CP/M
|
||||
<!-- This file is automatically generated. Do not edit. -->
|
||||
# CP/M
|
||||
|
||||
The Tiki 100 is a Z80-based Norwegian microcomputer from the mid 1980s intended
|
||||
for eductional use. It mostly ran an unbranded CP/M clone, and uses fairly
|
||||
@@ -8,5 +10,18 @@ on the precise format.
|
||||
|
||||
## Options
|
||||
|
||||
(no options)
|
||||
- Format variants:
|
||||
- `90`: 90kB 40-track 18-sector SSSD
|
||||
- `200`: 200kB 40-track 10-sector SSDD
|
||||
- `400`: 400kB 40-track 10-sector DSDD
|
||||
- `800`: 800kB 80-track 10-sector DSDD
|
||||
|
||||
## Examples
|
||||
|
||||
To read:
|
||||
|
||||
- `fluxengine read tiki --90 -s drive:0 -o tiki.img`
|
||||
- `fluxengine read tiki --200 -s drive:0 -o tiki.img`
|
||||
- `fluxengine read tiki --400 -s drive:0 -o tiki.img`
|
||||
- `fluxengine read tiki --800 -s drive:0 -o tiki.img`
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
victor9k
|
||||
====
|
||||
## 1224kB 5.25" DSDD GCR
|
||||
<!-- This file is automatically generated. Do not edit. -->
|
||||
# 1224kB 5.25" DSDD GCR
|
||||
|
||||
The Victor 9000 / Sirius One was a rather strange old 8086-based machine
|
||||
which used a disk format very reminiscent of the Commodore format; not a
|
||||
@@ -36,7 +38,21 @@ FluxEngine can read and write both the single-sided and double-sided variants.
|
||||
|
||||
## Options
|
||||
|
||||
(no options)
|
||||
- Format variants:
|
||||
- `612`: 612kB 80-track DSHD GCR
|
||||
- `1224`: 1224kB 80-track DSHD GCR
|
||||
|
||||
## Examples
|
||||
|
||||
To read:
|
||||
|
||||
- `fluxengine read victor9k --612 -s drive:0 -o victor9k.img`
|
||||
- `fluxengine read victor9k --1224 -s drive:0 -o victor9k.img`
|
||||
|
||||
To write:
|
||||
|
||||
- `fluxengine write victor9k --612 -d drive:0 -i victor9k.img`
|
||||
- `fluxengine write victor9k --1224 -d drive:0 -i victor9k.img`
|
||||
|
||||
## References
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
zilogmcz
|
||||
====
|
||||
## 320kB 8" 77-track SSSD hard-sectored
|
||||
<!-- This file is automatically generated. Do not edit. -->
|
||||
# 320kB 8" 77-track SSSD hard-sectored
|
||||
|
||||
The Zilog MCZ is an extremely early Z80 development system, produced by
|
||||
Zilog, which came out in 1976. It used twin 8-inch hard sectored floppy
|
||||
@@ -18,16 +20,19 @@ bytes per sector --- 128 bytes of user payload plus two two-byte metadata
|
||||
words used to construct linked lists of sectors for storing files. These
|
||||
stored 320kB each.
|
||||
|
||||
FluxEngine has experimental read support for these disks, based on a single
|
||||
Catweasel flux file I've been able to obtain, which only contained 70 tracks.
|
||||
I haven't been able to try this for real. If anyone has any of these disks,
|
||||
an 8-inch drive, a FluxEngine and the appropriate adapter, please [get in
|
||||
touch](https://github.com/davidgiven/fluxengine/issues/new)...
|
||||
FluxEngine has read support for these, including support for RIO's ZDOS file
|
||||
system.
|
||||
|
||||
## Options
|
||||
|
||||
(no options)
|
||||
|
||||
## Examples
|
||||
|
||||
To read:
|
||||
|
||||
- `fluxengine read zilogmcz -s drive:0 -o zilogmcz.img`
|
||||
|
||||
## References
|
||||
|
||||
* [About the Zilog MCZ](http://www.retrotechnology.com/restore/zilog.html),
|
||||
|
||||
@@ -39,10 +39,10 @@ If you actually have a forty track drive, you need to tell FluxEngine. This is
|
||||
done by adding the special profile `40track_drive`:
|
||||
|
||||
```
|
||||
fluxengine write ibm360 40track_drive -i image.img -d drive:0
|
||||
fluxengine write ibm --360 40track_drive -i image.img -d drive:0
|
||||
```
|
||||
|
||||
It should then Just Work. This is supported by both FluxEngine and GreaseWeazle
|
||||
It should then Just Work. This is supported by both FluxEngine and Greaseweazle
|
||||
hardware.
|
||||
|
||||
Obviously you can't write an eighty-track format using a forty-track drive!
|
||||
@@ -63,7 +63,7 @@ The FluxEngine client supports these with the `apple2_drive` profile:
|
||||
fluxengine write apple2 apple2_drive -i image.img -d drive:0
|
||||
```
|
||||
|
||||
This is supported only by GreaseWeazle hardware.
|
||||
This is supported only by Greaseweazle hardware.
|
||||
|
||||
Shugart drives
|
||||
--------------
|
||||
@@ -86,5 +86,5 @@ fluxengine write atarist720 shugart_drive -i image.img -d drive:0
|
||||
(If you have a 40-track Shugart drive, use _both_ `shugart_drive` and
|
||||
`40track_drive`.)
|
||||
|
||||
This is supported only by GreaseWeazle hardware.
|
||||
This is supported only by Greaseweazle hardware.
|
||||
|
||||
|
||||
@@ -17,13 +17,16 @@ The following file systems are supported so far.
|
||||
|:-----------------------------------------|:-----:|:------:|-------|
|
||||
| Acorn DFS | Y | | |
|
||||
| Amiga FFS | Y | Y | Both OFS and FFS |
|
||||
| AppleDOS / ProDOS | Y | Y | With a choice of sector remapping |
|
||||
| Brother 120kB | Y | Y | |
|
||||
| Commodore CbmFS | Y | | Only 1541 disks so far |
|
||||
| CP/M | Y | | Requires configuration for each machine |
|
||||
| FatFS (a.k.a. MS-DOS) | Y | Y | FAT12, FAT16, FAT32; not Atari (AFAIK!) |
|
||||
| Hewlett-Packard LIF | Y | | |
|
||||
| Macintosh HFS | Y | Y | Only AppleDouble files may be written |
|
||||
| Apple ProDOS | Y | | |
|
||||
| pSOS' PHILE | Y | | Probably unreliable due to lack of documentation |
|
||||
| Smaky 6 | Y | | |
|
||||
| Zilog MCZ RIO's ZDOS | Y | | |
|
||||
{: .datatable }
|
||||
|
||||
Please not that Atari disks do _not_ use standard FatFS, and the library I'm
|
||||
@@ -38,19 +41,19 @@ Using it
|
||||
To use, try syntax like this:
|
||||
|
||||
```
|
||||
fluxengine ls ibm180 -f drive:0
|
||||
fluxengine ls ibm --180 -f drive:0
|
||||
```
|
||||
|
||||
`ibm180` is the format, which selects the most common filesystem automatically.
|
||||
`-f drive:0` specifies a flux source/sink, in this case a real disk. You may
|
||||
also specify a flux file (read only). Disk images may be specified with `-i
|
||||
disk.img` (read/write).
|
||||
`ibm --180` is the format, which selects the most common filesystem
|
||||
automatically. `-f drive:0` specifies a flux source/sink, in this case a real
|
||||
disk. You may also specify a flux file (read only). Disk images may be
|
||||
specified with `-i disk.img` (read/write).
|
||||
|
||||
Commands which take filename paramaters typically use `-p` to indicate the path
|
||||
on the disk, and `-l` for the local filename. For example:
|
||||
|
||||
```
|
||||
fluxengine putfile ibm180 -f drive:0 -p ondisk.pcx -l z.pcx
|
||||
fluxengine putfile ibm --180 -f drive:0 -p ondisk.pcx -l z.pcx
|
||||
```
|
||||
|
||||
This will copy the file `z.pcx` onto the disk and call it `ONDISK.PCX`.
|
||||
@@ -83,7 +86,7 @@ default; for example, Macintosh HFS filesystems are common on 3.5" floppies. You
|
||||
can do this as follows:
|
||||
|
||||
```
|
||||
fluxengine format ibm1440 -f drive:1 --filesystem.type=MACHFS
|
||||
fluxengine format ibm --1440 -f drive:1 --filesystem.type=MACHFS
|
||||
```
|
||||
|
||||
Some filesystems won't work on some disks --- don't try this with Amiga FFS, for
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
Using the FluxEngine client software with GreaseWeazle hardware
|
||||
Using the FluxEngine client software with Greaseweazle hardware
|
||||
===============================================================
|
||||
|
||||
The FluxEngine isn't the only project which does this; another one is the
|
||||
[GreaseWeazle](https://github.com/keirf/Greaseweazle/wiki), a Blue Pill based
|
||||
[Greaseweazle](https://github.com/keirf/Greaseweazle/wiki), a Blue Pill based
|
||||
completely open source solution. This requires more work to set up (or you can
|
||||
buy a prebuilt GreaseWeazle board), but provides completely open source
|
||||
buy a prebuilt Greaseweazle board), but provides completely open source
|
||||
hardware which doesn't require the use of the Cypress Windows-based tools that
|
||||
the FluxEngine does. Luckily, the FluxEngine software supports it almost
|
||||
out-of-the-box --- just plug it in and nearly everything should work. The
|
||||
@@ -16,10 +16,10 @@ FluxEngine makes things complicated when you're not using the FluxEngine client
|
||||
software with a FluxEngine board, but I'm afraid it's too late to change that
|
||||
now. Sorry.
|
||||
|
||||
**If you are using GreaseWeazle-compatible hardware** such as the
|
||||
**If you are using Greaseweazle-compatible hardware** such as the
|
||||
[adafruit-floppy](https://github.com/adafruit/Adafruit_Floppy) project, then
|
||||
FluxEngine will still work; however, as the USB VID/PID won't be that of a real
|
||||
GreaseWeazle, the the FluxEngine client can't autodetect it. Instead, you'll
|
||||
Greaseweazle, the the FluxEngine client can't autodetect it. Instead, you'll
|
||||
need to specify the serial port manually with something like
|
||||
`--usb.greaseweazle.port=/dev/ttyACM0` or `--usb.greaseweazle.port=COM5`.
|
||||
|
||||
@@ -32,7 +32,7 @@ Driver box says `WinUSB` and the right one says `USB Serial (CDC)`. Then press
|
||||
What works
|
||||
----------
|
||||
|
||||
Supported features with the GreaseWeazle include:
|
||||
Supported features with the Greaseweazle include:
|
||||
|
||||
- simple reading and writing of disks, seeking etc
|
||||
- erasing disks
|
||||
@@ -41,8 +41,9 @@ Supported features with the GreaseWeazle include:
|
||||
`--usb.greaseweazle.bus_type=SHUGART` or `IBMPC`; the default is `IBMPC`)
|
||||
- Apple 5.25 floppy interfaces (via `--usb.greaseweazle.bus_type=APPLE2`)
|
||||
|
||||
Which device types are supported depend on the hardware. Genuine Greaseweazle hardware supports SHUGART and IBMPC.
|
||||
APPLE2 is only supported with hand wiring and the Adafruit\_Floppy greaseweazle-compatible firmware.
|
||||
Which device types are supported depend on the hardware. Genuine Greaseweazle
|
||||
hardware supports SHUGART and IBMPC. APPLE2 is only supported with hand wiring
|
||||
and the Adafruit\_Floppy greaseweazle-compatible firmware.
|
||||
|
||||
What doesn't work
|
||||
-----------------
|
||||
@@ -59,12 +60,12 @@ Who to contact
|
||||
--------------
|
||||
|
||||
I want to make it clear that the FluxEngine code is _not_ supported by the
|
||||
GreaseWeazle team. If you have any problems, please [contact
|
||||
Greaseweazle team. If you have any problems, please [contact
|
||||
me](https://github.com/davidgiven/fluxengine/issues/new) and not them.
|
||||
|
||||
In addition, the GreaseWeazle release cycle is not synchronised to the
|
||||
In addition, the Greaseweazle release cycle is not synchronised to the
|
||||
FluxEngine release cycle, so it's possible you'll have a version of the
|
||||
GreaseWeazle firmware which is not supported by FluxEngine. Hopefully, it'll
|
||||
Greaseweazle firmware which is not supported by FluxEngine. Hopefully, it'll
|
||||
detect this and complain. Again, [file an
|
||||
issue](https://github.com/davidgiven/fluxengine/issues/new) and I'll look into
|
||||
it.
|
||||
|
||||
BIN
doc/pcb.png
Normal file
BIN
doc/pcb.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
BIN
doc/screenshot-details.png
Normal file
BIN
doc/screenshot-details.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
@@ -80,11 +80,11 @@ as you need an adapter cable or board, but this will allow you to replicate the
|
||||
FluxEngine hardware on a $2 Blue Pill.
|
||||
|
||||
I am _not_ planning on replacing the PSoC5 with a Blue Pill, because someone
|
||||
already has: [the GreaseWeazle](https://github.com/keirf/Greaseweazle/wiki) is
|
||||
already has: [the Greaseweazle](https://github.com/keirf/Greaseweazle/wiki) is
|
||||
a completely open source firmware package which will read and write Supercard
|
||||
Pro files via a standard Blue Pill or via a prebuilt board. It's supported by
|
||||
the FluxEngine client software, and you should, mostly, be able to use
|
||||
GreaseWeazle hardware interchangeably with FluxEngine hardware. See the
|
||||
Greaseweazle hardware interchangeably with FluxEngine hardware. See the
|
||||
[dedicated page](greaseweazle.md) for more information.
|
||||
|
||||
|
||||
@@ -95,41 +95,43 @@ For reference, here are the FDC pinouts:
|
||||
```ditaa
|
||||
:-E -s 0.75
|
||||
|
||||
+--+--+ +--+--+
|
||||
DISKCHG ---+34+33+ DISKCHG ---+34+33+
|
||||
+--+--+ +--+--+
|
||||
SIDE1 ---+32+31+ SIDE1 ---+32+31+
|
||||
+--+--+ +--+--+
|
||||
RDATA ---+30+29+ RDATA ---+30+29+
|
||||
+--+--+ +--+--+
|
||||
WPT ---+28+27+ WPT ---+28+27+
|
||||
+--+--+ +--+--+
|
||||
TRK00 ---+26+25+ TRK00 ---+26+25+
|
||||
+--+--+ +--+--+
|
||||
WGATE ---+24+23+ WGATE ---+24+23+
|
||||
+--+--+ +--+--+
|
||||
WDATA ---+22+21+ WDATA ---+22+21+
|
||||
+--+--+ +--+--+
|
||||
STEP ---+20+19+ STEP ---+20+19+
|
||||
+--+--+ +--+--+
|
||||
DIR/SIDE1 ---+18+17+ DIR/SIDE1 ---+18+17+
|
||||
+--+--+ +--+--+
|
||||
MOTEB ---+16+15+ MOTEB ---+16+15+
|
||||
+--+--+ +--+--+
|
||||
DRVSA ---+14+13+ DS3 ---+14+13+
|
||||
+--+--+ +--+--+
|
||||
DRVSB ---+12+11+ DS2 ---+12+11+
|
||||
+--+--+ +--+--+
|
||||
MOTEA ---+10+9 + DS1 ---+10+9 +
|
||||
+--+--+ +--+--+
|
||||
INDEX ---+8 +7 + INDEX ---+8 +7 +
|
||||
+--+--+ +--+--+
|
||||
n/c ---+6 +5 + DS4 ---+6 +5 +
|
||||
+--+--+ +--+--+
|
||||
n/c ---+4 +3 + INU ---+4 +3 +
|
||||
+--+--+ +--+--+
|
||||
REDWC ---+2 +1 + REDWC ---+2 +1 +
|
||||
+--+--+ +--+--+
|
||||
+-- GND +-- GND
|
||||
| (entire column) | (entire column)
|
||||
+----+-+--+ +----+-+--+
|
||||
DISKCHG ---+ 34 + 33 + DISKCHG ---+ 34 + 33 +
|
||||
+----+----+ +----+----+
|
||||
SIDE1 ---+ 32 + 31 + SIDE1 ---+ 32 + 31 +
|
||||
+----+----+ +----+----+
|
||||
RDATA ---+ 30 + 29 + RDATA ---+ 30 + 29 +
|
||||
+----+----+ +----+----+
|
||||
WPT ---+ 28 + 27 + WPT ---+ 28 + 27 +
|
||||
+----+----+ +----+----+
|
||||
TRK00 ---+ 26 + 25 + TRK00 ---+ 26 + 25 +
|
||||
+----+----+ +----+----+
|
||||
WGATE ---+ 24 + 23 + WGATE ---+ 24 + 23 +
|
||||
+----+----+ +----+----+
|
||||
WDATA ---+ 22 + 21 + WDATA ---+ 22 + 21 +
|
||||
+----+----+ +----+----+
|
||||
STEP ---+ 20 + 19 + STEP ---+ 20 + 19 +
|
||||
+----+----+ +----+----+
|
||||
DIR/SIDE1 ---+ 18 + 17 + DIR/SIDE1 ---+ 18 + 17 +
|
||||
+----+----+ +----+----+
|
||||
MOTEB ---+ 16 + 15 + MOTEB ---+ 16 + 15 +
|
||||
+----+----+ +----+----+
|
||||
DRVSA ---+ 14 + 13 + DS3 ---+ 14 + 13 +
|
||||
+----+----+ +----+----+
|
||||
DRVSB ---+ 12 + 11 + DS2 ---+ 12 + 11 +
|
||||
+----+----+ +----+----+
|
||||
MOTEA ---+ 10 + 9 + DS1 ---+ 10 + 9 +
|
||||
+----+----+ +----+----+
|
||||
INDEX ---+ 8 + 7 + INDEX ---+ 8 + 7 +
|
||||
+----+----+ +----+----+
|
||||
n/c ---+ 6 + 5 + DS4 ---+ 6 + 5 +
|
||||
+----+----+ +----+----+
|
||||
n/c ---+ 4 + 3 + INU ---+ 4 + 3 +
|
||||
+----+----+ +----+----+
|
||||
REDWC ---+ 2 + 1 + REDWC ---+ 2 + 1 +
|
||||
+----+----+ +----+----+
|
||||
|
||||
PC interface Shugart interface
|
||||
|
||||
|
||||
191
doc/using.md
191
doc/using.md
@@ -11,6 +11,13 @@ moving too quickly for the documentation to keep up. It does respond to
|
||||
`--help` or `help` depending on context. There are some common properties,
|
||||
described below.
|
||||
|
||||
If possible, try using the GUI, which should provide simplified access for most
|
||||
common operations.
|
||||
|
||||
<div style="text-align: center">
|
||||
<a href="doc/screenshot-details.png"><img src="doc/screenshot-details.png" style="width:60%" alt="screenshot of the GUI in action"></a>
|
||||
</div>
|
||||
|
||||
### Core concepts
|
||||
|
||||
FluxEngine's job is to read magnetic data (called _flux_) off a disk, decode
|
||||
@@ -43,7 +50,7 @@ file while changing the decoder options, to save disk wear. It's also much faste
|
||||
|
||||
### Connecting it up
|
||||
|
||||
To use, simply plug your FluxEngine (or [GreaseWeazle](greaseweazle.md)) into
|
||||
To use, simply plug your FluxEngine (or [Greaseweazle](greaseweazle.md)) into
|
||||
your computer and run the client. If a single device is plugged in, it will be
|
||||
automatically detected and used.
|
||||
|
||||
@@ -68,10 +75,10 @@ Here are some sample invocations:
|
||||
```
|
||||
# Read an PC 1440kB disk, producing a disk image with the default name
|
||||
# (ibm.img)
|
||||
$ fluxengine read ibm1440
|
||||
$ fluxengine read ibm --1440
|
||||
|
||||
# Write a PC 1440kB disk to drive 1
|
||||
$ fluxengine write ibm1440 -i image.img -d drive:1
|
||||
$ fluxengine write ibm --1440 -i image.img -d drive:1
|
||||
|
||||
# Read a Eco1 CP/M disk, making a copy of the flux into a file
|
||||
$ fluxengine read eco1 --copy-flux-to copy.flux -o eco1.ldbs
|
||||
@@ -90,30 +97,31 @@ $ cat config.textpb
|
||||
encoder {
|
||||
ibm {
|
||||
trackdata {
|
||||
emit_iam: false
|
||||
}
|
||||
emit_iam: false
|
||||
}
|
||||
}
|
||||
}
|
||||
$ fluxengine write ibm1440 config.textpb -i image.img
|
||||
$ fluxengine write ibm --1440 config.textpb -i image.img
|
||||
```
|
||||
|
||||
...or you can specify them on the command line:
|
||||
|
||||
```
|
||||
$ fluxengine write ibm1440 -i image.img --encoder.ibm.trackdata.emit_iam=false
|
||||
$ fluxengine write ibm --1440 -i image.img --encoder.ibm.trackdata.emit_iam=false
|
||||
```
|
||||
|
||||
Both the above invocations are equivalent. The text files use [Google's
|
||||
protobuf syntax](https://developers.google.com/protocol-buffers), which is
|
||||
hierarchical, type-safe, and easy to read.
|
||||
|
||||
The `ibm1440` string above is actually a reference to an internal configuration
|
||||
file containing all the settings for writing PC 1440kB disks. You may specify
|
||||
as many profile names or textpb files as you wish; they are all merged left to
|
||||
right. You can see all these settings by doing:
|
||||
The `ibm` string above is actually a reference to an internal configuration file
|
||||
containing all the settings for writing PC disks, and the `--1140` refers to a
|
||||
specific definition inside it. You may specify as many profile names or textpb
|
||||
files as you wish; they are all merged left to right. You can see all these
|
||||
settings by doing:
|
||||
|
||||
```
|
||||
$ fluxengine write ibm1440 --config
|
||||
$ fluxengine write ibm --1440 --config
|
||||
```
|
||||
|
||||
The `--config` option will cause the current configuration to be dumped to the
|
||||
@@ -131,29 +139,30 @@ different task. Run each one with `--help` to get a full list of
|
||||
(non-configuration-setting) options; this describes only basic usage of the
|
||||
more common tools.
|
||||
|
||||
- `fluxengine read <profile> -s <flux source> -o <image output>`
|
||||
- `fluxengine read <profile> <options> -s <flux source> -o <image output>`
|
||||
|
||||
Reads flux (possibly from a disk) and decodes it into a file system image.
|
||||
`<profile>` is a reference to an internal input configuration file
|
||||
describing the format.
|
||||
Reads flux (possibly from a disk) and decodes it into a file system image.
|
||||
`<profile>` is a reference to an internal input configuration file
|
||||
describing the format. `<options>` may be any combination of options
|
||||
defined by the profile.
|
||||
|
||||
- `fluxengine write <profile> -i <image input> -d <flux destination>`
|
||||
|
||||
Reads a filesystem image and encodes it into flux (possibly writing to a
|
||||
disk). `<profile>` is a reference to an internal output configuration file
|
||||
describing the format.
|
||||
Reads a filesystem image and encodes it into flux (possibly writing to a
|
||||
disk). `<profile>` is a reference to an internal output configuration file
|
||||
describing the format.
|
||||
|
||||
- `fluxengine rawread -s <flux source> -d <flux destination>`
|
||||
|
||||
Reads flux (possibly from a disk) and writes it to a flux file without
|
||||
doing any decoding. You can specify a profile if you want to read a subset
|
||||
of the disk.
|
||||
Reads flux (possibly from a disk) and writes it to a flux file without doing
|
||||
any decoding. You can specify a profile if you want to read a subset of the
|
||||
disk.
|
||||
|
||||
- `fluxengine rawwrite -s <flux source> -d <flux destination>`
|
||||
|
||||
Reads flux from a file and writes it (possibly to a disk) without doing any
|
||||
encoding. You can specify a profile if you want to write a subset of the
|
||||
disk.
|
||||
Reads flux from a file and writes it (possibly to a disk) without doing any
|
||||
encoding. You can specify a profile if you want to write a subset of the
|
||||
disk.
|
||||
|
||||
- `fluxengine merge -s <fluxfile> -s <fluxfile...> -d <fluxfile`
|
||||
|
||||
@@ -165,20 +174,20 @@ more common tools.
|
||||
|
||||
- `fluxengine inspect -s <flux source> -c <cylinder> -h <head> -B`
|
||||
|
||||
Reads flux (possibly from a disk) and does various analyses of it to try
|
||||
and detect the clock rate, display raw flux information, examine the
|
||||
underlying data from the FluxEngine board, etc. There are lots of options
|
||||
but the command above is the most useful.
|
||||
Reads flux (possibly from a disk) and does various analyses of it to try and
|
||||
detect the clock rate, display raw flux information, examine the underlying
|
||||
data from the FluxEngine board, etc. There are lots of options but the
|
||||
command above is the most useful.
|
||||
|
||||
- `fluxengine rpm`
|
||||
|
||||
Measures the rotation speed of a drive. For hard-sectored disks, you
|
||||
probably want to add the name of a read profile to configure the number of
|
||||
sectors.
|
||||
Measures the rotation speed of a drive. For hard-sectored disks, you
|
||||
probably want to add the name of a read profile to configure the number of
|
||||
sectors.
|
||||
|
||||
- `fluxengine seek -c <cylinder>`
|
||||
|
||||
Seeks a drive to a particular cylinder.
|
||||
Seeks a drive to a particular cylinder.
|
||||
|
||||
There are other tools; try `fluxengine --help`.
|
||||
|
||||
@@ -198,19 +207,19 @@ FluxEngine supports a number of ways to get or put flux. When using the `-s` or
|
||||
|
||||
- `drive:<n>`
|
||||
|
||||
Read from or write to a specific drive.
|
||||
Read from or write to a specific drive.
|
||||
|
||||
- `<filename.flux>`
|
||||
|
||||
Read from or write to a native FluxEngine flux file.
|
||||
Read from or write to a native FluxEngine flux file.
|
||||
|
||||
- `<filename.scp>`
|
||||
|
||||
Read from or write to a Supercard Pro `.scp` flux file.
|
||||
Read from or write to a Supercard Pro `.scp` flux file.
|
||||
|
||||
- `<filename.cwf>`
|
||||
|
||||
Read from a Catweasel flux file. **Read only.**
|
||||
Read from a Catweasel flux file. **Read only.**
|
||||
|
||||
- `<filename.a2r>`
|
||||
|
||||
@@ -218,8 +227,8 @@ FluxEngine supports a number of ways to get or put flux. When using the `-s` or
|
||||
|
||||
- `kryoflux:<directory>`
|
||||
|
||||
Read from a Kryoflux stream, where `<path>` is the directory containing the
|
||||
stream files. **Read only.**
|
||||
Read from a Kryoflux stream, where `<path>` is the directory containing
|
||||
the stream files. **Read only.**
|
||||
|
||||
- `flx:<directory>`
|
||||
|
||||
@@ -228,53 +237,54 @@ FluxEngine supports a number of ways to get or put flux. When using the `-s` or
|
||||
|
||||
- `erase:`
|
||||
|
||||
Read nothing --- writing this to a disk will magnetically erase a track.
|
||||
**Read only.**
|
||||
Read nothing --- writing this to a disk will magnetically erase a track.
|
||||
**Read only.**
|
||||
|
||||
- `testpattern:`
|
||||
|
||||
Read a test pattern, which can be written to a disk to help diagnosis.
|
||||
**Read only.**
|
||||
Read a test pattern, which can be written to a disk to help diagnosis.
|
||||
**Read only.**
|
||||
|
||||
- `au:<directory>`
|
||||
|
||||
Write to a series of `.au` files, one file per track, which can be loaded
|
||||
into an audio editor (such as Audacity) as a simple logic analyser. **Write
|
||||
only.**
|
||||
Write to a series of `.au` files, one file per track, which can be loaded
|
||||
into an audio editor (such as Audacity) as a simple logic analyser.
|
||||
**Write only.**
|
||||
|
||||
- `vcd:<directory>`
|
||||
|
||||
Write to a series of `.vcd` files, one file per track, which can be loaded
|
||||
into a logic analyser (such as Pulseview) for analysis. **Write only.**
|
||||
Write to a series of `.vcd` files, one file per track, which can be loaded
|
||||
into a logic analyser (such as Pulseview) for analysis. **Write only.**
|
||||
|
||||
### Image sources and destinations
|
||||
|
||||
FluxEngine also supports a number of file system image formats. When using the
|
||||
`-i` or `-o` options (for input and output), you can use any of these strings:
|
||||
|
||||
- `<filename.adf>`, `<filename.d81>`, `<filename.img>`, `<filename.st>`, `<filename.xdf>`
|
||||
- `<filename.adf>`, `<filename.d81>`, `<filename.img>`, `<filename.st>`,
|
||||
`<filename.xdf>`
|
||||
|
||||
Read from or write to a simple headerless image file (all these formats are
|
||||
the same). This will probably want configuration via the
|
||||
`input/output.image.img.*` configuration settings to specify all the
|
||||
parameters.
|
||||
Read from or write to a simple headerless image file (all these formats are
|
||||
the same). This will probably want configuration via the
|
||||
`input/output.image.img.*` configuration settings to specify all the
|
||||
parameters.
|
||||
|
||||
- `<filename.diskcopy>`
|
||||
|
||||
Read from or write to a [DiskCopy
|
||||
4.2](https://en.wikipedia.org/wiki/Disk_Copy) image file, commonly used by
|
||||
Apple Macintosh emulators.
|
||||
Read from or write to a [DiskCopy
|
||||
4.2](https://en.wikipedia.org/wiki/Disk_Copy) image file, commonly used by
|
||||
Apple Macintosh emulators.
|
||||
|
||||
- `<filename.td0>`
|
||||
|
||||
Read a [Sydex Teledisk TD0
|
||||
file](https://web.archive.org/web/20210420224336/http://dunfield.classiccmp.org/img47321/teledisk.htm)
|
||||
image file. Note that only uncompressed images are supported (so far).
|
||||
Read a [Sydex Teledisk TD0
|
||||
file](https://web.archive.org/web/20210420224336/http://dunfield.classiccmp.org/img47321/teledisk.htm)
|
||||
image file. Note that only uncompressed images are supported (so far).
|
||||
|
||||
- `<filename.jv3>`
|
||||
|
||||
Read from a JV3 image file, commonly used by TRS-80 emulators. **Read
|
||||
only.**
|
||||
Read from a JV3 image file, commonly used by TRS-80 emulators. **Read
|
||||
only.**
|
||||
|
||||
- `<filename.dim>`
|
||||
|
||||
@@ -382,38 +392,27 @@ behaviour.
|
||||
|
||||
- `--drive.revolutions=X`
|
||||
|
||||
When reading, spin the disk X times. X
|
||||
can be a floating point number. The default is usually 1.2. Some formats
|
||||
default to 1. Increasing the number will sample more data, and can be
|
||||
useful on dubious disks to try and get a better read.
|
||||
When reading, spin the disk X times. X can be a floating point number. The
|
||||
default is usually 1.2. Some formats default to 1. Increasing the number
|
||||
will sample more data, and can be useful on dubious disks to try and get a
|
||||
better read.
|
||||
|
||||
- `--drive.sync_with_index=true|false`
|
||||
|
||||
Wait for an index pulse
|
||||
before starting to read the disk. (Ignored for write operations.) By
|
||||
default FluxEngine doesn't, as it makes reads faster, but when diagnosing
|
||||
disk problems it's helpful to have all your data start at the same place
|
||||
each time.
|
||||
Wait for an index pulse before starting to read the disk. (Ignored for write
|
||||
operations.) By default FluxEngine doesn't, as it makes reads faster, but
|
||||
when diagnosing disk problems it's helpful to have all your data start at
|
||||
the same place each time.
|
||||
|
||||
- `--drive.index_source=X`
|
||||
- `--drive.index_mode=X`
|
||||
|
||||
Set the source of index pulses when reading or writing respectively. This
|
||||
is for use with drives which don't produce index pulse data. `X` can be
|
||||
`INDEXMODE_DRIVE` to get index pulses from the drive, `INDEXMODE_300` to
|
||||
fake 300RPM pulses, or `INDEXMODE_360` to fake 360RPM pulses. Note this
|
||||
has no effect on the _drive_, so it doesn't help with flippy disks, but is
|
||||
useful for using very old drives with FluxEngine itself. If you use this
|
||||
option, then any index marks in the sampled flux are, of course, garbage.
|
||||
|
||||
- `--flux_source.rescale=X, --flux_sink.rescale=X`
|
||||
|
||||
When reading or writing a floppy on a drive that doesn't match the
|
||||
original drive RPM, the flux periods can be scaled to compensate.
|
||||
|
||||
For example, to read or write a PC-98 1.2MB (360rpm) floppy using a 300rpm
|
||||
floppy drive:
|
||||
|
||||
`--flux_source.rescale=1.2 --flux_sink.rescale=1.2`
|
||||
Set the source of index pulses when reading or writing respectively. This
|
||||
is for use with drives which don't produce index pulse data. `X` can be
|
||||
`INDEXMODE_DRIVE` to get index pulses from the drive, `INDEXMODE_300` to
|
||||
fake 300RPM pulses, or `INDEXMODE_360` to fake 360RPM pulses. Note this
|
||||
has no effect on the _drive_, so it doesn't help with flippy disks, but is
|
||||
useful for using very old drives with FluxEngine itself. If you use this
|
||||
option, then any index marks in the sampled flux are, of course, garbage.
|
||||
|
||||
## Visualisation
|
||||
|
||||
@@ -439,8 +438,8 @@ wrote to do useful things. These are built alongside FluxEngine.
|
||||
|
||||
- `brother120tool`, `brother240tool`
|
||||
|
||||
Does things to Brother word processor disks. These are [documented on the
|
||||
Brother disk format page](disk-brother.md).
|
||||
Does things to Brother word processor disks. These are [documented on the
|
||||
Brother disk format page](disk-brother.md).
|
||||
|
||||
## The recommended workflow
|
||||
|
||||
@@ -466,13 +465,13 @@ $ fluxengine read brother -s brother.flux -o brother.img --decoder.write_csv_to=
|
||||
Apart from being drastically faster, this avoids touching the (potentially
|
||||
physically fragile) disk.
|
||||
|
||||
If the disk is particularly dodgy, you can force FluxEngine not to retry
|
||||
failed reads with `--retries=0`. This reduces head movement. **This is not
|
||||
If the disk is particularly dodgy, you can force FluxEngine not to retry failed
|
||||
reads with `--decoder.retries=0`. This reduces head movement. **This is not
|
||||
recommended.** Floppy disks are inherently unreliable, and the occasional bit
|
||||
error is perfectly normal; FluxEngine will retry and the sector will read
|
||||
fine next time. If you prevent retries, then not only do you get bad sectors
|
||||
in the resulting image, but the flux file itself contains the bad read, so
|
||||
attempting a decode of it will just reproduce the same bad data.
|
||||
error is perfectly normal; FluxEngine will retry and the sector will read fine
|
||||
next time. If you prevent retries, then not only do you get bad sectors in the
|
||||
resulting image, but the flux file itself contains the bad read, so attempting a
|
||||
decode of it will just reproduce the same bad data.
|
||||
|
||||
See also the [troubleshooting page](problems.md) for more information about
|
||||
reading dubious disks.
|
||||
|
||||
@@ -25,7 +25,7 @@ SetCompressor /solid lzma
|
||||
GreaseWeazle hardware. It also allows manipulation of flux files and disk \
|
||||
images, so it's useful without any hardware.$\r$\n\
|
||||
$\r$\n\
|
||||
This wizard will install WordGrinder on your computer.$\r$\n\
|
||||
This wizard will install FluxEngine on your computer.$\r$\n\
|
||||
$\r$\n\
|
||||
$_CLICK"
|
||||
|
||||
@@ -130,7 +130,7 @@ SectionEnd
|
||||
|
||||
Section "Desktop Shortcut"
|
||||
SetOutPath "$DOCUMENTS"
|
||||
CreateShortCut "$DESKTOP\WordGrinder.lnk" "$INSTDIR\fluxengine-gui.exe" "" "$INSTDIR\fluxengine-gui.exe" 0
|
||||
CreateShortCut "$DESKTOP\FluxEngine.lnk" "$INSTDIR\fluxengine-gui.exe" "" "$INSTDIR\fluxengine-gui.exe" 0
|
||||
SectionEnd
|
||||
|
||||
;--------------------------------
|
||||
|
||||
14
lib/build.mk
14
lib/build.mk
@@ -77,14 +77,16 @@ LIBFLUXENGINE_SRCS = \
|
||||
lib/vfs/cbmfs.cc \
|
||||
lib/vfs/cpmfs.cc \
|
||||
lib/vfs/fatfs.cc \
|
||||
lib/vfs/lif.cc \
|
||||
lib/vfs/machfs.cc \
|
||||
lib/vfs/prodos.cc \
|
||||
lib/vfs/smaky6fs.cc \
|
||||
lib/vfs/philefs.cc \
|
||||
lib/vfs/vfs.cc \
|
||||
lib/vfs/fluxsectorinterface.cc \
|
||||
lib/vfs/imagesectorinterface.cc \
|
||||
lib/vfs/lif.cc \
|
||||
lib/vfs/machfs.cc \
|
||||
lib/vfs/philefs.cc \
|
||||
lib/vfs/prodos.cc \
|
||||
lib/vfs/roland.cc \
|
||||
lib/vfs/smaky6fs.cc \
|
||||
lib/vfs/vfs.cc \
|
||||
lib/vfs/zdos.cc \
|
||||
|
||||
LIBFLUXENGINE_OBJS = $(patsubst %.cc, $(OBJDIR)/%.o, $(LIBFLUXENGINE_SRCS))
|
||||
OBJS += $(LIBFLUXENGINE_OBJS)
|
||||
|
||||
@@ -362,6 +362,14 @@ ByteWriter& ByteWriter::operator+=(std::istream& stream)
|
||||
return *this;
|
||||
}
|
||||
|
||||
ByteWriter& ByteWriter::pad(unsigned count, uint8_t b)
|
||||
{
|
||||
while (count--)
|
||||
this->write_8(b);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void BitWriter::push(uint32_t bits, size_t size)
|
||||
{
|
||||
bits <<= 32 - size;
|
||||
|
||||
@@ -345,6 +345,8 @@ public:
|
||||
return *this += stream;
|
||||
}
|
||||
|
||||
ByteWriter& pad(unsigned count, uint8_t byte = 0);
|
||||
|
||||
private:
|
||||
Bytes& _bytes;
|
||||
};
|
||||
|
||||
@@ -19,4 +19,36 @@ enum IndexMode {
|
||||
INDEXMODE_360 = 2;
|
||||
}
|
||||
|
||||
enum FluxSourceSinkType {
|
||||
FLUXTYPE_NOT_SET = 0;
|
||||
FLUXTYPE_A2R = 1;
|
||||
FLUXTYPE_AU = 2;
|
||||
FLUXTYPE_CWF = 3;
|
||||
FLUXTYPE_DRIVE = 4;
|
||||
FLUXTYPE_ERASE = 5;
|
||||
FLUXTYPE_FLUX = 6;
|
||||
FLUXTYPE_FLX = 7;
|
||||
FLUXTYPE_KRYOFLUX = 8;
|
||||
FLUXTYPE_SCP = 9;
|
||||
FLUXTYPE_TEST_PATTERN = 10;
|
||||
FLUXTYPE_VCD = 11;
|
||||
}
|
||||
|
||||
enum ImageReaderWriterType {
|
||||
IMAGETYPE_NOT_SET = 0;
|
||||
IMAGETYPE_D64 = 1;
|
||||
IMAGETYPE_D88 = 2;
|
||||
IMAGETYPE_DIM = 3;
|
||||
IMAGETYPE_DISKCOPY = 4;
|
||||
IMAGETYPE_FDI = 5;
|
||||
IMAGETYPE_IMD = 6;
|
||||
IMAGETYPE_IMG = 7;
|
||||
IMAGETYPE_JV3 = 8;
|
||||
IMAGETYPE_LDBS = 9;
|
||||
IMAGETYPE_NFD = 10;
|
||||
IMAGETYPE_NSI = 11;
|
||||
IMAGETYPE_RAW = 12;
|
||||
IMAGETYPE_TD0 = 13;
|
||||
}
|
||||
|
||||
|
||||
|
||||
346
lib/config.cc
346
lib/config.cc
@@ -11,10 +11,153 @@
|
||||
#include "lib/decoders/decoders.h"
|
||||
#include <fstream>
|
||||
#include <google/protobuf/text_format.h>
|
||||
#include <regex>
|
||||
|
||||
static Config config;
|
||||
|
||||
enum ConstructorMode
|
||||
{
|
||||
MODE_RO,
|
||||
MODE_WO,
|
||||
MODE_RW
|
||||
};
|
||||
|
||||
struct ImageConstructor
|
||||
{
|
||||
std::string extension;
|
||||
ImageReaderWriterType type;
|
||||
ConstructorMode mode;
|
||||
};
|
||||
|
||||
static const std::vector<FluxConstructor> fluxConstructors = {
|
||||
{/* The .flux format must be first. */
|
||||
.name = "FluxEngine (.flux)",
|
||||
.pattern = std::regex("^(.*\\.flux)$"),
|
||||
.source =
|
||||
[](auto& s, auto* proto)
|
||||
{
|
||||
proto->set_type(FLUXTYPE_FLUX);
|
||||
proto->mutable_fl2()->set_filename(s);
|
||||
}, .sink =
|
||||
[](auto& s, auto* proto)
|
||||
{
|
||||
proto->set_type(FLUXTYPE_FLUX);
|
||||
proto->mutable_fl2()->set_filename(s);
|
||||
}},
|
||||
{
|
||||
.name = "Supercard Pro (.scp)",
|
||||
.pattern = std::regex("^(.*\\.scp)$"),
|
||||
.source =
|
||||
[](auto& s, auto* proto)
|
||||
{
|
||||
proto->set_type(FLUXTYPE_SCP);
|
||||
proto->mutable_scp()->set_filename(s);
|
||||
}, .sink =
|
||||
[](auto& s, auto* proto)
|
||||
{
|
||||
proto->set_type(FLUXTYPE_SCP);
|
||||
proto->mutable_scp()->set_filename(s);
|
||||
}, },
|
||||
{.name = "AppleSauce (.a2r)",
|
||||
.pattern = std::regex("^(.*\\.a2r)$"),
|
||||
.source =
|
||||
[](auto& s, auto* proto)
|
||||
{
|
||||
proto->set_type(FLUXTYPE_A2R);
|
||||
proto->mutable_a2r()->set_filename(s);
|
||||
}, .sink =
|
||||
[](auto& s, auto* proto)
|
||||
{
|
||||
proto->set_type(FLUXTYPE_A2R);
|
||||
proto->mutable_a2r()->set_filename(s);
|
||||
}},
|
||||
{.name = "CatWeazle (.cwf)",
|
||||
.pattern = std::regex("^(.*\\.cwf)$"),
|
||||
.source =
|
||||
[](auto& s, auto* proto)
|
||||
{
|
||||
proto->set_type(FLUXTYPE_CWF);
|
||||
proto->mutable_cwf()->set_filename(s);
|
||||
}},
|
||||
{.pattern = std::regex("^erase:$"),
|
||||
.source =
|
||||
[](auto& s, auto* proto)
|
||||
{
|
||||
proto->set_type(FLUXTYPE_ERASE);
|
||||
}},
|
||||
{.name = "KryoFlux directory",
|
||||
.pattern = std::regex("^kryoflux:(.*)$"),
|
||||
.source =
|
||||
[](auto& s, auto* proto)
|
||||
{
|
||||
proto->set_type(FLUXTYPE_KRYOFLUX);
|
||||
proto->mutable_kryoflux()->set_directory(s);
|
||||
}},
|
||||
{.pattern = std::regex("^testpattern:(.*)"),
|
||||
.source =
|
||||
[](auto& s, auto* proto)
|
||||
{
|
||||
proto->set_type(FLUXTYPE_TEST_PATTERN);
|
||||
}},
|
||||
{.pattern = std::regex("^drive:(.*)"),
|
||||
.source =
|
||||
[](auto& s, auto* proto)
|
||||
{
|
||||
proto->set_type(FLUXTYPE_DRIVE);
|
||||
globalConfig().overrides()->mutable_drive()->set_drive(
|
||||
std::stoi(s));
|
||||
}, .sink =
|
||||
[](auto& s, auto* proto)
|
||||
{
|
||||
proto->set_type(FLUXTYPE_DRIVE);
|
||||
globalConfig().overrides()->mutable_drive()->set_drive(
|
||||
std::stoi(s));
|
||||
}},
|
||||
{.name = "FluxCopy directory",
|
||||
.pattern = std::regex("^flx:(.*)$"),
|
||||
.source =
|
||||
[](auto& s, auto* proto)
|
||||
{
|
||||
proto->set_type(FLUXTYPE_FLX);
|
||||
proto->mutable_flx()->set_directory(s);
|
||||
}},
|
||||
{.name = "Value Change Dump directory",
|
||||
.pattern = std::regex("^vcd:(.*)$"),
|
||||
.sink =
|
||||
[](auto& s, auto* proto)
|
||||
{
|
||||
proto->set_type(FLUXTYPE_VCD);
|
||||
proto->mutable_vcd()->set_directory(s);
|
||||
}},
|
||||
{.name = "Audio file directory",
|
||||
.pattern = std::regex("^au:(.*)$"),
|
||||
.sink =
|
||||
[](auto& s, auto* proto)
|
||||
{
|
||||
proto->set_type(FLUXTYPE_AU);
|
||||
proto->mutable_au()->set_directory(s);
|
||||
}},
|
||||
};
|
||||
|
||||
static const std::vector<ImageConstructor> imageConstructors = {
|
||||
{".adf", IMAGETYPE_IMG, MODE_RW},
|
||||
{".d64", IMAGETYPE_D64, MODE_RW},
|
||||
{".d81", IMAGETYPE_IMG, MODE_RW},
|
||||
{".d88", IMAGETYPE_D88, MODE_RW},
|
||||
{".dim", IMAGETYPE_DIM, MODE_RO},
|
||||
{".diskcopy", IMAGETYPE_DISKCOPY, MODE_RW},
|
||||
{".dsk", IMAGETYPE_IMG, MODE_RW},
|
||||
{".fdi", IMAGETYPE_FDI, MODE_RO},
|
||||
{".imd", IMAGETYPE_IMD, MODE_RW},
|
||||
{".img", IMAGETYPE_IMG, MODE_RW},
|
||||
{".jv3", IMAGETYPE_JV3, MODE_RO},
|
||||
{".nfd", IMAGETYPE_NFD, MODE_RO},
|
||||
{".nsi", IMAGETYPE_NSI, MODE_RW},
|
||||
{".st", IMAGETYPE_IMG, MODE_RW},
|
||||
{".td0", IMAGETYPE_TD0, MODE_RO},
|
||||
{".vgi", IMAGETYPE_IMG, MODE_RW},
|
||||
{".xdf", IMAGETYPE_IMG, MODE_RW},
|
||||
};
|
||||
|
||||
Config& globalConfig()
|
||||
{
|
||||
return config;
|
||||
@@ -29,7 +172,7 @@ ConfigProto* Config::combined()
|
||||
/* First apply any standalone options. */
|
||||
|
||||
std::set<std::string> options = _appliedOptions;
|
||||
std::set<const OptionRequirementProto*> requirements;
|
||||
std::set<const OptionPrerequisiteProto*> prereqs;
|
||||
for (const auto& option : _baseConfig.option())
|
||||
{
|
||||
if (options.find(option.name()) != options.end())
|
||||
@@ -257,7 +400,7 @@ const OptionProto& Config::findOption(const std::string& optionName)
|
||||
|
||||
void Config::checkOptionValid(const OptionProto& option)
|
||||
{
|
||||
for (const auto& req : option.requires())
|
||||
for (const auto& req : option.prerequisite())
|
||||
{
|
||||
bool matched = false;
|
||||
try
|
||||
@@ -334,72 +477,17 @@ void Config::clearOptions()
|
||||
invalidate();
|
||||
}
|
||||
|
||||
static void setFluxSourceImpl(std::string filename, FluxSourceProto* proto)
|
||||
static void setFluxSourceImpl(
|
||||
const std::string& filename, FluxSourceProto* proto)
|
||||
{
|
||||
static const std::vector<std::pair<std::regex,
|
||||
std::function<void(const std::string&, FluxSourceProto*)>>>
|
||||
formats = {
|
||||
{std::regex("^(.*\\.flux)$"),
|
||||
[](auto& s, auto* proto)
|
||||
{
|
||||
proto->set_type(FluxSourceProto::FLUX);
|
||||
proto->mutable_fl2()->set_filename(s);
|
||||
}},
|
||||
{std::regex("^(.*\\.scp)$"),
|
||||
[](auto& s, auto* proto)
|
||||
{
|
||||
proto->set_type(FluxSourceProto::SCP);
|
||||
proto->mutable_scp()->set_filename(s);
|
||||
}},
|
||||
{std::regex("^(.*\\.a2r)$"),
|
||||
[](auto& s, auto* proto)
|
||||
{
|
||||
proto->set_type(FluxSourceProto::A2R);
|
||||
proto->mutable_a2r()->set_filename(s);
|
||||
}},
|
||||
{std::regex("^(.*\\.cwf)$"),
|
||||
[](auto& s, auto* proto)
|
||||
{
|
||||
proto->set_type(FluxSourceProto::CWF);
|
||||
proto->mutable_cwf()->set_filename(s);
|
||||
}},
|
||||
{std::regex("^erase:$"),
|
||||
[](auto& s, auto* proto)
|
||||
{
|
||||
proto->set_type(FluxSourceProto::ERASE);
|
||||
}},
|
||||
{std::regex("^kryoflux:(.*)$"),
|
||||
[](auto& s, auto* proto)
|
||||
{
|
||||
proto->set_type(FluxSourceProto::KRYOFLUX);
|
||||
proto->mutable_kryoflux()->set_directory(s);
|
||||
}},
|
||||
{std::regex("^testpattern:(.*)"),
|
||||
[](auto& s, auto* proto)
|
||||
{
|
||||
proto->set_type(FluxSourceProto::TEST_PATTERN);
|
||||
}},
|
||||
{std::regex("^drive:(.*)"),
|
||||
[](auto& s, auto* proto)
|
||||
{
|
||||
proto->set_type(FluxSourceProto::DRIVE);
|
||||
globalConfig().overrides()->mutable_drive()->set_drive(
|
||||
std::stoi(s));
|
||||
}},
|
||||
{std::regex("^flx:(.*)$"),
|
||||
[](auto& s, auto* proto)
|
||||
{
|
||||
proto->set_type(FluxSourceProto::FLX);
|
||||
proto->mutable_flx()->set_directory(s);
|
||||
}},
|
||||
};
|
||||
|
||||
for (const auto& it : formats)
|
||||
for (const auto& it : fluxConstructors)
|
||||
{
|
||||
std::smatch match;
|
||||
if (std::regex_match(filename, match, it.first))
|
||||
if (std::regex_match(filename, match, it.pattern))
|
||||
{
|
||||
it.second(match[1], proto);
|
||||
if (!it.source)
|
||||
throw new InapplicableValueException();
|
||||
it.source(match[1], proto);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -412,56 +500,16 @@ void Config::setFluxSource(std::string filename)
|
||||
setFluxSourceImpl(filename, overrides()->mutable_flux_source());
|
||||
}
|
||||
|
||||
static void setFluxSinkImpl(std::string filename, FluxSinkProto* proto)
|
||||
static void setFluxSinkImpl(const std::string& filename, FluxSinkProto* proto)
|
||||
{
|
||||
static const std::vector<std::pair<std::regex,
|
||||
std::function<void(const std::string&, FluxSinkProto*)>>>
|
||||
formats = {
|
||||
{std::regex("^(.*\\.a2r)$"),
|
||||
[](auto& s, auto* proto)
|
||||
{
|
||||
proto->set_type(FluxSinkProto::A2R);
|
||||
proto->mutable_a2r()->set_filename(s);
|
||||
}},
|
||||
{std::regex("^(.*\\.flux)$"),
|
||||
[](auto& s, auto* proto)
|
||||
{
|
||||
proto->set_type(FluxSinkProto::FLUX);
|
||||
proto->mutable_fl2()->set_filename(s);
|
||||
}},
|
||||
{std::regex("^(.*\\.scp)$"),
|
||||
[](auto& s, auto* proto)
|
||||
{
|
||||
proto->set_type(FluxSinkProto::SCP);
|
||||
proto->mutable_scp()->set_filename(s);
|
||||
}},
|
||||
{std::regex("^vcd:(.*)$"),
|
||||
[](auto& s, auto* proto)
|
||||
{
|
||||
proto->set_type(FluxSinkProto::VCD);
|
||||
proto->mutable_vcd()->set_directory(s);
|
||||
}},
|
||||
{std::regex("^au:(.*)$"),
|
||||
[](auto& s, auto* proto)
|
||||
{
|
||||
proto->set_type(FluxSinkProto::AU);
|
||||
proto->mutable_au()->set_directory(s);
|
||||
}},
|
||||
{std::regex("^drive:(.*)"),
|
||||
[](auto& s, auto* proto)
|
||||
{
|
||||
proto->set_type(FluxSinkProto::DRIVE);
|
||||
globalConfig().overrides()->mutable_drive()->set_drive(
|
||||
std::stoi(s));
|
||||
}},
|
||||
};
|
||||
|
||||
for (const auto& it : formats)
|
||||
for (const auto& it : fluxConstructors)
|
||||
{
|
||||
std::smatch match;
|
||||
if (std::regex_match(filename, match, it.first))
|
||||
if (std::regex_match(filename, match, it.pattern))
|
||||
{
|
||||
it.second(match[1], proto);
|
||||
if (!it.sink)
|
||||
throw new InapplicableValueException();
|
||||
it.sink(match[1], proto);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -487,34 +535,14 @@ void Config::setVerificationFluxSource(std::string filename)
|
||||
|
||||
void Config::setImageReader(std::string filename)
|
||||
{
|
||||
static const std::map<std::string, std::function<void(ImageReaderProto*)>>
|
||||
formats = {
|
||||
// clang-format off
|
||||
{".adf", [](auto* proto) { proto->set_type(ImageReaderProto::IMG); }},
|
||||
{".d64", [](auto* proto) { proto->set_type(ImageReaderProto::D64); }},
|
||||
{".d81", [](auto* proto) { proto->set_type(ImageReaderProto::IMG); }},
|
||||
{".d88", [](auto* proto) { proto->set_type(ImageReaderProto::D88); }},
|
||||
{".dim", [](auto* proto) { proto->set_type(ImageReaderProto::DIM); }},
|
||||
{".diskcopy", [](auto* proto) { proto->set_type(ImageReaderProto::DISKCOPY); }},
|
||||
{".dsk", [](auto* proto) { proto->set_type(ImageReaderProto::IMG); }},
|
||||
{".fdi", [](auto* proto) { proto->set_type(ImageReaderProto::FDI); }},
|
||||
{".imd", [](auto* proto) { proto->set_type(ImageReaderProto::IMD); }},
|
||||
{".img", [](auto* proto) { proto->set_type(ImageReaderProto::IMG); }},
|
||||
{".jv3", [](auto* proto) { proto->set_type(ImageReaderProto::JV3); }},
|
||||
{".nfd", [](auto* proto) { proto->set_type(ImageReaderProto::NFD); }},
|
||||
{".nsi", [](auto* proto) { proto->set_type(ImageReaderProto::NSI); }},
|
||||
{".st", [](auto* proto) { proto->set_type(ImageReaderProto::IMG); }},
|
||||
{".td0", [](auto* proto) { proto->set_type(ImageReaderProto::TD0); }},
|
||||
{".vgi", [](auto* proto) { proto->set_type(ImageReaderProto::IMG); }},
|
||||
{".xdf", [](auto* proto) { proto->set_type(ImageReaderProto::IMG); }},
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
for (const auto& it : formats)
|
||||
for (const auto& it : imageConstructors)
|
||||
{
|
||||
if (endsWith(filename, it.first))
|
||||
if (endsWith(filename, it.extension))
|
||||
{
|
||||
it.second(overrides()->mutable_image_reader());
|
||||
if (it.mode == MODE_WO)
|
||||
throw new InapplicableValueException();
|
||||
|
||||
overrides()->mutable_image_reader()->set_type(it.type);
|
||||
overrides()->mutable_image_reader()->set_filename(filename);
|
||||
return;
|
||||
}
|
||||
@@ -525,31 +553,14 @@ void Config::setImageReader(std::string filename)
|
||||
|
||||
void Config::setImageWriter(std::string filename)
|
||||
{
|
||||
static const std::map<std::string, std::function<void(ImageWriterProto*)>>
|
||||
formats = {
|
||||
// clang-format off
|
||||
{".adf", [](auto* proto) { proto->set_type(ImageWriterProto::IMG); }},
|
||||
{".d64", [](auto* proto) { proto->set_type(ImageWriterProto::D64); }},
|
||||
{".d81", [](auto* proto) { proto->set_type(ImageWriterProto::IMG); }},
|
||||
{".d88", [](auto* proto) { proto->set_type(ImageWriterProto::D88); }},
|
||||
{".diskcopy", [](auto* proto) { proto->set_type(ImageWriterProto::DISKCOPY); }},
|
||||
{".dsk", [](auto* proto) { proto->set_type(ImageWriterProto::IMG); }},
|
||||
{".img", [](auto* proto) { proto->set_type(ImageWriterProto::IMG); }},
|
||||
{".imd", [](auto* proto) { proto->set_type(ImageWriterProto::IMD); }},
|
||||
{".ldbs", [](auto* proto) { proto->set_type(ImageWriterProto::LDBS); }},
|
||||
{".nsi", [](auto* proto) { proto->set_type(ImageWriterProto::NSI); }},
|
||||
{".raw", [](auto* proto) { proto->set_type(ImageWriterProto::RAW); }},
|
||||
{".st", [](auto* proto) { proto->set_type(ImageWriterProto::IMG); }},
|
||||
{".vgi", [](auto* proto) { proto->set_type(ImageWriterProto::IMG); }},
|
||||
{".xdf", [](auto* proto) { proto->set_type(ImageWriterProto::IMG); }},
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
for (const auto& it : formats)
|
||||
for (const auto& it : imageConstructors)
|
||||
{
|
||||
if (endsWith(filename, it.first))
|
||||
if (endsWith(filename, it.extension))
|
||||
{
|
||||
it.second(overrides()->mutable_image_writer());
|
||||
if (it.mode == MODE_RO)
|
||||
throw new InapplicableValueException();
|
||||
|
||||
overrides()->mutable_image_writer()->set_type(it.type);
|
||||
overrides()->mutable_image_writer()->set_filename(filename);
|
||||
return;
|
||||
}
|
||||
@@ -560,7 +571,7 @@ void Config::setImageWriter(std::string filename)
|
||||
|
||||
bool Config::hasFluxSource()
|
||||
{
|
||||
return (*this)->flux_source().type() != FluxSourceProto::NOT_SET;
|
||||
return (*this)->flux_source().type() != FLUXTYPE_NOT_SET;
|
||||
}
|
||||
|
||||
std::shared_ptr<FluxSource>& Config::getFluxSource()
|
||||
@@ -578,7 +589,7 @@ std::shared_ptr<FluxSource>& Config::getFluxSource()
|
||||
|
||||
bool Config::hasVerificationFluxSource() const
|
||||
{
|
||||
return _verificationFluxSourceProto.type() != FluxSourceProto::NOT_SET;
|
||||
return _verificationFluxSourceProto.type() != FLUXTYPE_NOT_SET;
|
||||
}
|
||||
|
||||
std::shared_ptr<FluxSource>& Config::getVerificationFluxSource()
|
||||
@@ -596,7 +607,7 @@ std::shared_ptr<FluxSource>& Config::getVerificationFluxSource()
|
||||
|
||||
bool Config::hasImageReader()
|
||||
{
|
||||
return (*this)->image_reader().type() != ImageReaderProto::NOT_SET;
|
||||
return (*this)->image_reader().type() != IMAGETYPE_NOT_SET;
|
||||
}
|
||||
|
||||
std::shared_ptr<ImageReader>& Config::getImageReader()
|
||||
@@ -614,7 +625,7 @@ std::shared_ptr<ImageReader>& Config::getImageReader()
|
||||
|
||||
bool Config::hasFluxSink()
|
||||
{
|
||||
return (*this)->flux_sink().type() != FluxSinkProto::NOT_SET;
|
||||
return (*this)->flux_sink().type() != FLUXTYPE_NOT_SET;
|
||||
}
|
||||
|
||||
std::unique_ptr<FluxSink> Config::getFluxSink()
|
||||
@@ -627,7 +638,7 @@ std::unique_ptr<FluxSink> Config::getFluxSink()
|
||||
|
||||
bool Config::hasImageWriter()
|
||||
{
|
||||
return (*this)->image_writer().type() != ImageWriterProto::NOT_SET;
|
||||
return (*this)->image_writer().type() != IMAGETYPE_NOT_SET;
|
||||
}
|
||||
|
||||
std::unique_ptr<ImageWriter> Config::getImageWriter()
|
||||
@@ -671,3 +682,8 @@ std::shared_ptr<Decoder>& Config::getDecoder()
|
||||
}
|
||||
return _decoder;
|
||||
}
|
||||
|
||||
const std::vector<FluxConstructor>& Config::getFluxFormats()
|
||||
{
|
||||
return fluxConstructors;
|
||||
}
|
||||
21
lib/config.h
21
lib/config.h
@@ -4,6 +4,7 @@
|
||||
|
||||
#include <google/protobuf/message.h>
|
||||
#include "lib/config.pb.h"
|
||||
#include "lib/common.pb.h"
|
||||
|
||||
class ConfigProto;
|
||||
class OptionProto;
|
||||
@@ -46,6 +47,22 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class InapplicableValueException : public ErrorException
|
||||
{
|
||||
public:
|
||||
InapplicableValueException():
|
||||
ErrorException("selected format cannot be used here")
|
||||
{}
|
||||
};
|
||||
|
||||
struct FluxConstructor
|
||||
{
|
||||
std::string name;
|
||||
std::regex pattern;
|
||||
std::function<void(const std::string& filename, FluxSourceProto*)> source;
|
||||
std::function<void(const std::string& filename, FluxSinkProto*)> sink;
|
||||
};
|
||||
|
||||
class Config
|
||||
{
|
||||
public:
|
||||
@@ -146,6 +163,10 @@ public:
|
||||
bool hasImageWriter();
|
||||
std::unique_ptr<ImageWriter> getImageWriter();
|
||||
|
||||
public:
|
||||
static const std::vector<FluxConstructor>& getFluxFormats();
|
||||
static std::vector<std::string> getImageFormats();
|
||||
|
||||
private:
|
||||
ConfigProto _baseConfig;
|
||||
ConfigProto _overridesConfig;
|
||||
|
||||
@@ -50,7 +50,7 @@ message ConfigProto
|
||||
repeated OptionGroupProto option_group = 20;
|
||||
}
|
||||
|
||||
message OptionRequirementProto
|
||||
message OptionPrerequisiteProto
|
||||
{
|
||||
optional string key = 1 [ (help) = "path to config value" ];
|
||||
repeated string value = 2 [ (help) = "list of required values" ];
|
||||
@@ -65,7 +65,7 @@ message OptionProto
|
||||
[ (help) = "message to display when option is in use" ];
|
||||
optional bool set_by_default = 6
|
||||
[ (help) = "this option is applied by default", default = false ];
|
||||
repeated OptionRequirementProto requires = 7
|
||||
repeated OptionPrerequisiteProto prerequisite = 7
|
||||
[ (help) = "prerequisites for this option" ];
|
||||
|
||||
optional ConfigProto config = 4
|
||||
|
||||
@@ -30,8 +30,8 @@ static void upgradeFluxFile(FluxFileProto& proto)
|
||||
error(
|
||||
"this is a version {} flux file, but this build of the client can "
|
||||
"only handle up to version {} --- please upgrade",
|
||||
proto.version(),
|
||||
FluxFileVersion::VERSION_2);
|
||||
(int)proto.version(),
|
||||
(int)FluxFileVersion::VERSION_2);
|
||||
}
|
||||
|
||||
FluxFileProto loadFl2File(const std::string filename)
|
||||
|
||||
@@ -10,26 +10,25 @@ std::unique_ptr<FluxSink> FluxSink::create(const FluxSinkProto& config)
|
||||
{
|
||||
switch (config.type())
|
||||
{
|
||||
case FluxSinkProto::DRIVE:
|
||||
case FLUXTYPE_DRIVE:
|
||||
return createHardwareFluxSink(config.drive());
|
||||
|
||||
case FluxSinkProto::A2R:
|
||||
case FLUXTYPE_A2R:
|
||||
return createA2RFluxSink(config.a2r());
|
||||
|
||||
case FluxSinkProto::AU:
|
||||
case FLUXTYPE_AU:
|
||||
return createAuFluxSink(config.au());
|
||||
|
||||
case FluxSinkProto::VCD:
|
||||
case FLUXTYPE_VCD:
|
||||
return createVcdFluxSink(config.vcd());
|
||||
|
||||
case FluxSinkProto::SCP:
|
||||
case FLUXTYPE_SCP:
|
||||
return createScpFluxSink(config.scp());
|
||||
|
||||
case FluxSinkProto::FLUX:
|
||||
case FLUXTYPE_FLUX:
|
||||
return createFl2FluxSink(config.fl2());
|
||||
|
||||
default:
|
||||
error("bad output disk config");
|
||||
return std::unique_ptr<FluxSink>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,17 +29,8 @@ message Fl2FluxSinkProto {
|
||||
|
||||
// Next: 10
|
||||
message FluxSinkProto {
|
||||
enum FluxSinkType {
|
||||
NOT_SET = 0;
|
||||
DRIVE = 1;
|
||||
A2R = 2;
|
||||
AU = 3;
|
||||
VCD = 4;
|
||||
SCP = 5;
|
||||
FLUX = 6;
|
||||
}
|
||||
|
||||
optional FluxSinkType type = 9 [default = NOT_SET, (help) = "flux sink type"];
|
||||
optional FluxSourceSinkType type = 9
|
||||
[default = FLUXTYPE_NOT_SET, (help) = "flux sink type"];
|
||||
|
||||
optional HardwareFluxSinkProto drive = 2;
|
||||
optional A2RFluxSinkProto a2r = 8;
|
||||
|
||||
@@ -180,7 +180,7 @@ public:
|
||||
trackdataWriter += fluxdata;
|
||||
}
|
||||
|
||||
operator std::string() const
|
||||
operator std::string() const override
|
||||
{
|
||||
return fmt::format("scp({})", _config.filename());
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ public:
|
||||
of << "\n";
|
||||
}
|
||||
|
||||
operator std::string() const
|
||||
operator std::string() const override
|
||||
{
|
||||
return fmt::format("vcd({})", _config.directory());
|
||||
}
|
||||
|
||||
@@ -142,7 +142,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void recalibrate() {}
|
||||
void recalibrate() override {}
|
||||
|
||||
private:
|
||||
Bytes findChunk(Bytes id)
|
||||
|
||||
@@ -15,7 +15,7 @@ public:
|
||||
return std::unique_ptr<const Fluxmap>();
|
||||
}
|
||||
|
||||
void recalibrate() {}
|
||||
void recalibrate() override {}
|
||||
};
|
||||
|
||||
std::unique_ptr<FluxSource> FluxSource::createEraseFluxSource(
|
||||
|
||||
@@ -39,8 +39,8 @@ public:
|
||||
|
||||
_extraConfig.mutable_drive()->set_rotational_period_ms(
|
||||
_proto.rotational_period_ms());
|
||||
if (_proto.has_tpi())
|
||||
_extraConfig.mutable_drive()->set_tpi(_proto.tpi());
|
||||
if (_proto.has_tpi())
|
||||
_extraConfig.mutable_drive()->set_tpi(_proto.tpi());
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -55,7 +55,7 @@ public:
|
||||
return std::make_unique<EmptyFluxSourceIterator>();
|
||||
}
|
||||
|
||||
void recalibrate() {}
|
||||
void recalibrate() override {}
|
||||
|
||||
private:
|
||||
void check_for_error(std::ifstream& ifs)
|
||||
|
||||
@@ -10,35 +10,34 @@ std::unique_ptr<FluxSource> FluxSource::create(const FluxSourceProto& config)
|
||||
{
|
||||
switch (config.type())
|
||||
{
|
||||
case FluxSourceProto::DRIVE:
|
||||
case FLUXTYPE_DRIVE:
|
||||
return createHardwareFluxSource(config.drive());
|
||||
|
||||
case FluxSourceProto::ERASE:
|
||||
case FLUXTYPE_ERASE:
|
||||
return createEraseFluxSource(config.erase());
|
||||
|
||||
case FluxSourceProto::KRYOFLUX:
|
||||
case FLUXTYPE_KRYOFLUX:
|
||||
return createKryofluxFluxSource(config.kryoflux());
|
||||
|
||||
case FluxSourceProto::TEST_PATTERN:
|
||||
case FLUXTYPE_TEST_PATTERN:
|
||||
return createTestPatternFluxSource(config.test_pattern());
|
||||
|
||||
case FluxSourceProto::SCP:
|
||||
case FLUXTYPE_SCP:
|
||||
return createScpFluxSource(config.scp());
|
||||
|
||||
case FluxSourceProto::A2R:
|
||||
case FLUXTYPE_A2R:
|
||||
return createA2rFluxSource(config.a2r());
|
||||
|
||||
case FluxSourceProto::CWF:
|
||||
case FLUXTYPE_CWF:
|
||||
return createCwfFluxSource(config.cwf());
|
||||
|
||||
case FluxSourceProto::FLUX:
|
||||
case FLUXTYPE_FLUX:
|
||||
return createFl2FluxSource(config.fl2());
|
||||
|
||||
case FluxSourceProto::FLX:
|
||||
case FLUXTYPE_FLX:
|
||||
return createFlxFluxSource(config.flx());
|
||||
|
||||
default:
|
||||
error("bad input disk configuration");
|
||||
return std::unique_ptr<FluxSource>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,20 +41,8 @@ message FlxFluxSourceProto {
|
||||
|
||||
// NEXT: 12
|
||||
message FluxSourceProto {
|
||||
enum FluxSourceType {
|
||||
NOT_SET = 0;
|
||||
DRIVE = 1;
|
||||
TEST_PATTERN = 2;
|
||||
ERASE = 3;
|
||||
KRYOFLUX = 4;
|
||||
SCP = 5;
|
||||
CWF = 6;
|
||||
FLUX = 7;
|
||||
FLX = 8;
|
||||
A2R = 9;
|
||||
}
|
||||
|
||||
optional FluxSourceType type = 9 [default = NOT_SET, (help) = "flux source type"];
|
||||
optional FluxSourceSinkType type = 9
|
||||
[default = FLUXTYPE_NOT_SET, (help) = "flux source type"];
|
||||
|
||||
optional A2rFluxSourceProto a2r = 11;
|
||||
optional CwfFluxSourceProto cwf = 7;
|
||||
|
||||
@@ -19,7 +19,7 @@ public:
|
||||
return readFlxBytes(Bytes::readFromFile(path));
|
||||
}
|
||||
|
||||
void recalibrate() {}
|
||||
void recalibrate() override {}
|
||||
|
||||
private:
|
||||
const std::string _path;
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <fstream>
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#include <filesystem>
|
||||
|
||||
#define MCLK_HZ (((18432000.0 * 73.0) / 14.0) / 2.0)
|
||||
#define SCLK_HZ (MCLK_HZ / 2)
|
||||
@@ -23,10 +24,18 @@ static bool has_suffix(const std::string& haystack, const std::string& needle)
|
||||
}
|
||||
|
||||
std::unique_ptr<Fluxmap> readStream(
|
||||
const std::string& dir, unsigned track, unsigned side)
|
||||
std::string dir, unsigned track, unsigned side)
|
||||
{
|
||||
std::string suffix = fmt::format("{:02}.{}.raw", track, side);
|
||||
|
||||
FILE* fp = fopen(dir.c_str(), "r");
|
||||
if (fp)
|
||||
{
|
||||
fclose(fp);
|
||||
int i = dir.find_last_of("/\\");
|
||||
dir = dir.substr(0, i);
|
||||
}
|
||||
|
||||
DIR* dirp = opendir(dir.c_str());
|
||||
if (!dirp)
|
||||
error("cannot access path '{}'", dir);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#define STREAM_H
|
||||
|
||||
extern std::unique_ptr<Fluxmap> readStream(
|
||||
const std::string& dir, unsigned track, unsigned side);
|
||||
std::string dir, unsigned track, unsigned side);
|
||||
extern std::unique_ptr<Fluxmap> readStream(const std::string& path);
|
||||
extern std::unique_ptr<Fluxmap> readStream(const Bytes& bytes);
|
||||
|
||||
|
||||
@@ -128,7 +128,7 @@ public:
|
||||
return fluxmap;
|
||||
}
|
||||
|
||||
void recalibrate() {}
|
||||
void recalibrate() override {}
|
||||
|
||||
private:
|
||||
void check_for_error()
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <climits>
|
||||
#include <variant>
|
||||
#include <optional>
|
||||
#include <regex>
|
||||
#include <fmt/format.h>
|
||||
|
||||
#if defined(_WIN32) || defined(__WIN32__)
|
||||
|
||||
@@ -15,37 +15,37 @@ std::unique_ptr<ImageReader> ImageReader::create(const ImageReaderProto& config)
|
||||
{
|
||||
switch (config.type())
|
||||
{
|
||||
case ImageReaderProto::DIM:
|
||||
case IMAGETYPE_DIM:
|
||||
return ImageReader::createDimImageReader(config);
|
||||
|
||||
case ImageReaderProto::D88:
|
||||
case IMAGETYPE_D88:
|
||||
return ImageReader::createD88ImageReader(config);
|
||||
|
||||
case ImageReaderProto::FDI:
|
||||
case IMAGETYPE_FDI:
|
||||
return ImageReader::createFdiImageReader(config);
|
||||
|
||||
case ImageReaderProto::IMD:
|
||||
case IMAGETYPE_IMD:
|
||||
return ImageReader::createIMDImageReader(config);
|
||||
|
||||
case ImageReaderProto::IMG:
|
||||
case IMAGETYPE_IMG:
|
||||
return ImageReader::createImgImageReader(config);
|
||||
|
||||
case ImageReaderProto::DISKCOPY:
|
||||
case IMAGETYPE_DISKCOPY:
|
||||
return ImageReader::createDiskCopyImageReader(config);
|
||||
|
||||
case ImageReaderProto::JV3:
|
||||
case IMAGETYPE_JV3:
|
||||
return ImageReader::createJv3ImageReader(config);
|
||||
|
||||
case ImageReaderProto::D64:
|
||||
case IMAGETYPE_D64:
|
||||
return ImageReader::createD64ImageReader(config);
|
||||
|
||||
case ImageReaderProto::NFD:
|
||||
case IMAGETYPE_NFD:
|
||||
return ImageReader::createNFDImageReader(config);
|
||||
|
||||
case ImageReaderProto::NSI:
|
||||
case IMAGETYPE_NSI:
|
||||
return ImageReader::createNsiImageReader(config);
|
||||
|
||||
case ImageReaderProto::TD0:
|
||||
case IMAGETYPE_TD0:
|
||||
return ImageReader::createTd0ImageReader(config);
|
||||
|
||||
default:
|
||||
|
||||
@@ -24,22 +24,8 @@ message ImageReaderProto
|
||||
default = false
|
||||
];
|
||||
|
||||
enum ImageReaderType {
|
||||
NOT_SET = 0;
|
||||
IMG = 1;
|
||||
DISKCOPY = 2;
|
||||
IMD = 3;
|
||||
JV3 = 4;
|
||||
D64 = 5;
|
||||
NSI = 6;
|
||||
TD0 = 7;
|
||||
DIM = 8;
|
||||
FDI = 9;
|
||||
D88 = 10;
|
||||
NFD = 11;
|
||||
}
|
||||
|
||||
optional ImageReaderType type = 14 [default = NOT_SET, (help) = "input image type"];
|
||||
optional ImageReaderWriterType type = 14
|
||||
[default = IMAGETYPE_NOT_SET, (help) = "input image type"];
|
||||
|
||||
optional ImgInputOutputProto img = 2;
|
||||
optional DiskCopyInputProto diskcopy = 3;
|
||||
|
||||
@@ -15,28 +15,28 @@ std::unique_ptr<ImageWriter> ImageWriter::create(const ImageWriterProto& config)
|
||||
{
|
||||
switch (config.type())
|
||||
{
|
||||
case ImageWriterProto::IMG:
|
||||
case IMAGETYPE_IMG:
|
||||
return ImageWriter::createImgImageWriter(config);
|
||||
|
||||
case ImageWriterProto::D64:
|
||||
case IMAGETYPE_D64:
|
||||
return ImageWriter::createD64ImageWriter(config);
|
||||
|
||||
case ImageWriterProto::LDBS:
|
||||
case IMAGETYPE_LDBS:
|
||||
return ImageWriter::createLDBSImageWriter(config);
|
||||
|
||||
case ImageWriterProto::DISKCOPY:
|
||||
case IMAGETYPE_DISKCOPY:
|
||||
return ImageWriter::createDiskCopyImageWriter(config);
|
||||
|
||||
case ImageWriterProto::NSI:
|
||||
case IMAGETYPE_NSI:
|
||||
return ImageWriter::createNsiImageWriter(config);
|
||||
|
||||
case ImageWriterProto::RAW:
|
||||
case IMAGETYPE_RAW:
|
||||
return ImageWriter::createRawImageWriter(config);
|
||||
|
||||
case ImageWriterProto::D88:
|
||||
case IMAGETYPE_D88:
|
||||
return ImageWriter::createD88ImageWriter(config);
|
||||
|
||||
case ImageWriterProto::IMD:
|
||||
case IMAGETYPE_IMD:
|
||||
return ImageWriter::createImdImageWriter(config);
|
||||
|
||||
default:
|
||||
|
||||
@@ -66,25 +66,14 @@ message ImdOutputProto
|
||||
// NEXT_TAG: 12
|
||||
message ImageWriterProto
|
||||
{
|
||||
enum ImageWriterType {
|
||||
NOT_SET = 0;
|
||||
IMG = 1;
|
||||
D64 = 2;
|
||||
LDBS = 3;
|
||||
DISKCOPY = 4;
|
||||
NSI = 5;
|
||||
RAW = 6;
|
||||
D88 = 7;
|
||||
IMD = 8;
|
||||
}
|
||||
|
||||
optional string filename = 1 [ (help) = "filename of output sector image" ];
|
||||
optional bool filesystem_sector_order = 10 [
|
||||
(help) = "read/write sector image in filesystem order",
|
||||
default = false
|
||||
];
|
||||
|
||||
optional ImageWriterType type = 11 [ default = NOT_SET, (help) = "image writer type" ];
|
||||
optional ImageReaderWriterType type = 11
|
||||
[ default = IMAGETYPE_NOT_SET, (help) = "image writer type" ];
|
||||
|
||||
optional ImgInputOutputProto img = 2;
|
||||
optional D64OutputProto d64 = 3;
|
||||
|
||||
@@ -273,6 +273,8 @@ public:
|
||||
case ImdOutputProto::RATE_DD:
|
||||
RATE = 2000;
|
||||
break;
|
||||
case ImdOutputProto::RATE_GUESS:
|
||||
break;
|
||||
}
|
||||
}
|
||||
header.ModeValue =
|
||||
|
||||
@@ -45,13 +45,16 @@ std::string Logger::toString(const AnyLogMessage& message)
|
||||
/* Start measuring the rotational speed */
|
||||
[&](const BeginSpeedOperationLogMessage& m)
|
||||
{
|
||||
stream << "Measuring rotational speed... ";
|
||||
indent();
|
||||
stream << "Measuring rotational speed...\n";
|
||||
},
|
||||
|
||||
/* Finish measuring the rotational speed */
|
||||
[&](const EndSpeedOperationLogMessage& m)
|
||||
{
|
||||
stream << fmt::format("{:.1f}ms ({:.1f}rpm)\n",
|
||||
indent();
|
||||
stream << fmt::format(
|
||||
"Rotational period is {:.1f}ms ({:.1f}rpm)\n",
|
||||
m.rotationalPeriod / 1e6,
|
||||
60e9 / m.rotationalPeriod);
|
||||
},
|
||||
|
||||
@@ -119,6 +119,7 @@ static ProtoField resolveProtoPath(
|
||||
switch (field->label())
|
||||
{
|
||||
case google::protobuf::FieldDescriptor::LABEL_OPTIONAL:
|
||||
case google::protobuf::FieldDescriptor::LABEL_REQUIRED:
|
||||
if (!create && !reflection->HasField(*message, field))
|
||||
throw ProtoPathNotFoundException(fmt::format(
|
||||
"could not find config field '{}'", field->name()));
|
||||
@@ -139,7 +140,7 @@ static ProtoField resolveProtoPath(
|
||||
break;
|
||||
|
||||
default:
|
||||
error("bad proto label {}", field->label());
|
||||
error("bad proto label for field '{}' in '{}'", item, path);
|
||||
}
|
||||
|
||||
descriptor = message->GetDescriptor();
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define PROTO_H
|
||||
|
||||
#include <google/protobuf/message.h>
|
||||
#include "lib/common.pb.h"
|
||||
#include "lib/config.pb.h"
|
||||
|
||||
class ProtoPathNotFoundException : public ErrorException
|
||||
|
||||
@@ -456,6 +456,9 @@ std::shared_ptr<TrackFlux> readAndDecodeTrack(FluxSource& fluxSource,
|
||||
auto trackFlux = std::make_shared<TrackFlux>();
|
||||
trackFlux->trackInfo = trackInfo;
|
||||
|
||||
if (fluxSource.isHardware())
|
||||
measureDiskRotation();
|
||||
|
||||
FluxSourceIteratorHolder fluxSourceIteratorHolder(fluxSource);
|
||||
int retriesRemaining = globalConfig()->decoder().retries();
|
||||
for (;;)
|
||||
@@ -498,8 +501,6 @@ std::shared_ptr<const DiskFlux> readDiskCommand(
|
||||
auto diskflux = std::make_shared<DiskFlux>();
|
||||
|
||||
log(BeginOperationLogMessage{"Reading and decoding disk"});
|
||||
if (fluxSource.isHardware())
|
||||
measureDiskRotation();
|
||||
auto locations = Layout::computeLocations();
|
||||
unsigned index = 0;
|
||||
for (auto& trackInfo : locations)
|
||||
|
||||
10
lib/sector.h
10
lib/sector.h
@@ -90,6 +90,16 @@ struct Sector : public LogicalLocation
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct fmt::formatter<Sector::Status> : formatter<string_view>
|
||||
{
|
||||
auto format(Sector::Status status, format_context& ctx) const
|
||||
{
|
||||
return formatter<string_view>::format(
|
||||
Sector::statusToString(status), ctx);
|
||||
}
|
||||
};
|
||||
|
||||
extern bool sectorPointerSortPredicate(const std::shared_ptr<const Sector>& lhs,
|
||||
const std::shared_ptr<const Sector>& rhs);
|
||||
extern bool sectorPointerEqualsPredicate(
|
||||
|
||||
@@ -76,7 +76,7 @@ public:
|
||||
"your FluxEngine firmware is at version {} but the client is "
|
||||
"for version {}; please upgrade",
|
||||
version,
|
||||
FLUXENGINE_PROTOCOL_VERSION);
|
||||
(int) FLUXENGINE_PROTOCOL_VERSION);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include "bytes.h"
|
||||
#include "greaseweazle.h"
|
||||
|
||||
Bytes fluxEngineToGreaseWeazle(const Bytes& fldata, nanoseconds_t clock)
|
||||
Bytes fluxEngineToGreaseweazle(const Bytes& fldata, nanoseconds_t clock)
|
||||
{
|
||||
Bytes gwdata;
|
||||
ByteWriter bw(gwdata);
|
||||
@@ -89,7 +89,7 @@ Bytes greaseWeazleToFluxEngine(const Bytes& gwdata, nanoseconds_t clock)
|
||||
break;
|
||||
|
||||
default:
|
||||
error("bad opcode in GreaseWeazle stream");
|
||||
error("bad opcode in Greaseweazle stream");
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#define EP_OUT 0x02
|
||||
#define EP_IN 0x83
|
||||
|
||||
extern Bytes fluxEngineToGreaseWeazle(const Bytes& fldata, nanoseconds_t clock);
|
||||
extern Bytes fluxEngineToGreaseweazle(const Bytes& fldata, nanoseconds_t clock);
|
||||
extern Bytes greaseWeazleToFluxEngine(const Bytes& gwdata, nanoseconds_t clock);
|
||||
extern Bytes stripPartialRotation(const Bytes& fldata);
|
||||
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
#include "globals.h"
|
||||
#include "usb.h"
|
||||
#include "lib/globals.h"
|
||||
#include "protocol.h"
|
||||
#include "fluxmap.h"
|
||||
#include "bytes.h"
|
||||
#include "lib/fluxmap.h"
|
||||
#include "lib/bytes.h"
|
||||
#include "lib/usb/usb.pb.h"
|
||||
#include "greaseweazle.h"
|
||||
#include "serial.h"
|
||||
#include "usb.h"
|
||||
#include <unistd.h>
|
||||
|
||||
static const char* gw_error(int e)
|
||||
{
|
||||
@@ -45,7 +46,7 @@ static uint32_t ss_rand_next(uint32_t x)
|
||||
return (x & 1) ? (x >> 1) ^ 0x80000062 : x >> 1;
|
||||
}
|
||||
|
||||
class GreaseWeazleUsb : public USB
|
||||
class GreaseweazleUsb : public USB
|
||||
{
|
||||
private:
|
||||
uint32_t read_28()
|
||||
@@ -72,11 +73,11 @@ private:
|
||||
command[0],
|
||||
buffer[1]);
|
||||
if (buffer[1])
|
||||
error("GreaseWeazle error: {}", gw_error(buffer[1]));
|
||||
error("Greaseweazle error: {}", gw_error(buffer[1]));
|
||||
}
|
||||
|
||||
public:
|
||||
GreaseWeazleUsb(const std::string& port, const GreaseWeazleProto& config):
|
||||
GreaseweazleUsb(const std::string& port, const GreaseweazleProto& config):
|
||||
_serial(SerialPort::openSerialPort(port)),
|
||||
_config(config)
|
||||
{
|
||||
@@ -90,12 +91,19 @@ public:
|
||||
else
|
||||
{
|
||||
error(
|
||||
"only GreaseWeazle firmware versions 22 and 24 or above are "
|
||||
"only Greaseweazle firmware versions 22 and 24 or above are "
|
||||
"currently "
|
||||
"supported, but you have version {}. Please file a bug.",
|
||||
version);
|
||||
}
|
||||
|
||||
/* Twiddle the baud rate, which indicates to the Greaseweazle that the
|
||||
* data stream has been reset. */
|
||||
|
||||
_serial->setBaudRate(10000);
|
||||
usleep(100000);
|
||||
_serial->setBaudRate(9600);
|
||||
|
||||
/* Configure the hardware. */
|
||||
|
||||
do_command({CMD_SET_BUS_TYPE, 3, (uint8_t)config.bus_type()});
|
||||
@@ -129,9 +137,9 @@ public:
|
||||
nanoseconds_t getRotationalPeriod(int hardSectorCount)
|
||||
{
|
||||
if (hardSectorCount != 0)
|
||||
error("hard sectors are currently unsupported on the GreaseWeazel");
|
||||
error("hard sectors are currently unsupported on the Greaseweazle");
|
||||
|
||||
/* The GreaseWeazle doesn't have a command to fetch the period directly,
|
||||
/* The Greaseweazle doesn't have a command to fetch the period directly,
|
||||
* so we have to do a flux read. */
|
||||
|
||||
switch (_version)
|
||||
@@ -181,7 +189,7 @@ public:
|
||||
break;
|
||||
|
||||
default:
|
||||
error("bad opcode in GreaseWeazle stream");
|
||||
error("bad opcode in Greaseweazle stream");
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -304,7 +312,7 @@ public:
|
||||
nanoseconds_t hardSectorThreshold)
|
||||
{
|
||||
if (hardSectorThreshold != 0)
|
||||
error("hard sectors are currently unsupported on the GreaseWeazel");
|
||||
error("hard sectors are currently unsupported on the Greaseweazle");
|
||||
|
||||
do_command({CMD_HEAD, 3, (uint8_t)side});
|
||||
|
||||
@@ -357,7 +365,7 @@ public:
|
||||
void write(int side, const Bytes& fldata, nanoseconds_t hardSectorThreshold)
|
||||
{
|
||||
if (hardSectorThreshold != 0)
|
||||
error("hard sectors are currently unsupported on the GreaseWeazel");
|
||||
error("hard sectors are currently unsupported on the Greaseweazle");
|
||||
|
||||
do_command({CMD_HEAD, 3, (uint8_t)side});
|
||||
switch (_version)
|
||||
@@ -371,7 +379,7 @@ public:
|
||||
do_command({CMD_WRITE_FLUX, 4, 1, 1});
|
||||
break;
|
||||
}
|
||||
_serial->write(fluxEngineToGreaseWeazle(fldata, _clock));
|
||||
_serial->write(fluxEngineToGreaseweazle(fldata, _clock));
|
||||
_serial->readByte(); /* synchronise */
|
||||
|
||||
do_command({CMD_GET_FLUX_STATUS, 2});
|
||||
@@ -380,7 +388,7 @@ public:
|
||||
void erase(int side, nanoseconds_t hardSectorThreshold)
|
||||
{
|
||||
if (hardSectorThreshold != 0)
|
||||
error("hard sectors are currently unsupported on the GreaseWeazel");
|
||||
error("hard sectors are currently unsupported on the Greaseweazle");
|
||||
|
||||
do_command({CMD_HEAD, 3, (uint8_t)side});
|
||||
|
||||
@@ -404,7 +412,7 @@ public:
|
||||
|
||||
void measureVoltages(struct voltages_frame* voltages)
|
||||
{
|
||||
error("unsupported operation on the GreaseWeazle");
|
||||
error("unsupported operation on the Greaseweazle");
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -416,16 +424,16 @@ private:
|
||||
};
|
||||
|
||||
std::unique_ptr<SerialPort> _serial;
|
||||
const GreaseWeazleProto& _config;
|
||||
const GreaseweazleProto& _config;
|
||||
int _version;
|
||||
nanoseconds_t _clock;
|
||||
nanoseconds_t _revolutions;
|
||||
};
|
||||
|
||||
USB* createGreaseWeazleUsb(
|
||||
const std::string& port, const GreaseWeazleProto& config)
|
||||
USB* createGreaseweazleUsb(
|
||||
const std::string& port, const GreaseweazleProto& config)
|
||||
{
|
||||
return new GreaseWeazleUsb(port, config);
|
||||
return new GreaseweazleUsb(port, config);
|
||||
}
|
||||
|
||||
// vim: sw=4 ts=4 et
|
||||
|
||||
@@ -88,6 +88,17 @@ public:
|
||||
return wlen;
|
||||
}
|
||||
|
||||
void setBaudRate(int baudRate) override
|
||||
{
|
||||
DCB dcb = {.DCBlength = sizeof(DCB),
|
||||
.BaudRate = baudRate,
|
||||
.fBinary = true,
|
||||
.ByteSize = 8,
|
||||
.Parity = NOPARITY,
|
||||
.StopBits = ONESTOPBIT};
|
||||
SetCommState(_handle, &dcb);
|
||||
}
|
||||
|
||||
private:
|
||||
static std::string get_last_error_string()
|
||||
{
|
||||
@@ -181,6 +192,14 @@ public:
|
||||
return wlen;
|
||||
}
|
||||
|
||||
void setBaudRate(int baudRate) override
|
||||
{
|
||||
struct termios t;
|
||||
tcgetattr(_fd, &t);
|
||||
cfsetspeed(&t, baudRate);
|
||||
tcsetattr(_fd, TCSANOW, &t);
|
||||
}
|
||||
|
||||
private:
|
||||
int _fd;
|
||||
};
|
||||
|
||||
@@ -10,6 +10,7 @@ public:
|
||||
virtual ~SerialPort();
|
||||
virtual ssize_t readImpl(uint8_t* buffer, size_t len) = 0;
|
||||
virtual ssize_t write(const uint8_t* buffer, size_t len) = 0;
|
||||
virtual void setBaudRate(int baudRate) = 0;
|
||||
|
||||
void read(uint8_t* buffer, size_t len);
|
||||
void read(Bytes& bytes);
|
||||
|
||||
@@ -52,7 +52,7 @@ static std::shared_ptr<CandidateDevice> selectDevice()
|
||||
|
||||
case GREASEWEAZLE_ID:
|
||||
std::cerr << fmt::format(
|
||||
"GreaseWeazle: {} on {}\n", c->serial, c->serialPort);
|
||||
"Greaseweazle: {} on {}\n", c->serial, c->serialPort);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -67,8 +67,8 @@ USB* get_usb_impl()
|
||||
globalConfig()->usb().greaseweazle().has_port())
|
||||
{
|
||||
const auto& conf = globalConfig()->usb().greaseweazle();
|
||||
log("Using GreaseWeazle on serial port {}", conf.port());
|
||||
return createGreaseWeazleUsb(conf.port(), conf);
|
||||
log("Using Greaseweazle on serial port {}", conf.port());
|
||||
return createGreaseweazleUsb(conf.port(), conf);
|
||||
}
|
||||
|
||||
/* Otherwise, select a device by USB ID. */
|
||||
@@ -81,10 +81,10 @@ USB* get_usb_impl()
|
||||
return createFluxengineUsb(candidate->device);
|
||||
|
||||
case GREASEWEAZLE_ID:
|
||||
log("Using GreaseWeazle {} on {}",
|
||||
log("Using Greaseweazle {} on {}",
|
||||
candidate->serial,
|
||||
candidate->serialPort);
|
||||
return createGreaseWeazleUsb(
|
||||
return createGreaseweazleUsb(
|
||||
candidate->serialPort, globalConfig()->usb().greaseweazle());
|
||||
|
||||
default:
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include "flags.h"
|
||||
|
||||
class Fluxmap;
|
||||
class GreaseWeazleProto;
|
||||
class GreaseweazleProto;
|
||||
namespace libusbp
|
||||
{
|
||||
class device;
|
||||
@@ -39,8 +39,8 @@ protected:
|
||||
extern USB& getUsb();
|
||||
|
||||
extern USB* createFluxengineUsb(libusbp::device& device);
|
||||
extern USB* createGreaseWeazleUsb(
|
||||
const std::string& serialPort, const GreaseWeazleProto& config);
|
||||
extern USB* createGreaseweazleUsb(
|
||||
const std::string& serialPort, const GreaseweazleProto& config);
|
||||
|
||||
static inline int usbGetVersion()
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@ syntax = "proto2";
|
||||
|
||||
import "lib/common.proto";
|
||||
|
||||
message GreaseWeazleProto {
|
||||
message GreaseweazleProto {
|
||||
enum BusType { /* note that these must match CMD_SET_BUS codes */
|
||||
BUSTYPE_INVALID = 0;
|
||||
IBMPC = 1;
|
||||
@@ -11,14 +11,14 @@ message GreaseWeazleProto {
|
||||
};
|
||||
|
||||
optional string port = 1
|
||||
[(help) = "GreaseWeazle serial port to use"];
|
||||
[(help) = "Greaseweazle serial port to use"];
|
||||
optional BusType bus_type = 2
|
||||
[(help) = "which FDD bus type is in use", default = IBMPC];
|
||||
}
|
||||
|
||||
message UsbProto {
|
||||
optional string serial = 1
|
||||
[(help) = "serial number of FluxEngine or GreaseWeazle device to use"];
|
||||
[(help) = "serial number of FluxEngine or Greaseweazle device to use"];
|
||||
|
||||
optional GreaseWeazleProto greaseweazle = 2 [(help) = "GreaseWeazle-specific options"];
|
||||
optional GreaseweazleProto greaseweazle = 2 [(help) = "Greaseweazle-specific options"];
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
uint32_t capabilities() const
|
||||
uint32_t capabilities() const override
|
||||
{
|
||||
return OP_GETFSDATA | OP_CREATE | OP_LIST | OP_GETFILE | OP_PUTFILE |
|
||||
OP_GETDIRENT | OP_DELETE | OP_MOVE | OP_CREATEDIR;
|
||||
@@ -229,7 +229,7 @@ public:
|
||||
throw CannotWriteException();
|
||||
}
|
||||
|
||||
void createDirectory(const Path& path)
|
||||
void createDirectory(const Path& path) override
|
||||
{
|
||||
AdfMount m(this);
|
||||
if (path.empty())
|
||||
|
||||
@@ -50,7 +50,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
uint32_t capabilities() const
|
||||
uint32_t capabilities() const override
|
||||
{
|
||||
return OP_LIST | OP_GETDIRENT | OP_GETFSDATA | OP_GETFILE;
|
||||
}
|
||||
|
||||
@@ -232,7 +232,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
uint32_t capabilities() const
|
||||
uint32_t capabilities() const override
|
||||
{
|
||||
return OP_GETFSDATA | OP_LIST | OP_GETFILE | OP_PUTFILE | OP_GETDIRENT |
|
||||
OP_DELETE;
|
||||
|
||||
@@ -195,7 +195,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
uint32_t capabilities() const
|
||||
uint32_t capabilities() const override
|
||||
{
|
||||
return OP_GETFSDATA | OP_LIST | OP_GETFILE | OP_GETDIRENT;
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
uint32_t capabilities() const
|
||||
uint32_t capabilities() const override
|
||||
{
|
||||
return OP_GETFSDATA | OP_LIST | OP_GETFILE | OP_GETDIRENT;
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
uint32_t capabilities() const
|
||||
uint32_t capabilities() const override
|
||||
{
|
||||
return OP_GETFSDATA | OP_CREATE | OP_LIST | OP_GETFILE | OP_PUTFILE |
|
||||
OP_GETDIRENT | OP_MOVE | OP_CREATEDIR | OP_DELETE;
|
||||
@@ -199,7 +199,7 @@ public:
|
||||
throwError(res);
|
||||
}
|
||||
|
||||
void createDirectory(const Path& path)
|
||||
void createDirectory(const Path& path) override
|
||||
{
|
||||
mount();
|
||||
auto pathStr = path.to_str();
|
||||
@@ -296,7 +296,7 @@ private:
|
||||
|
||||
default:
|
||||
throw FilesystemException(
|
||||
fmt::format("unknown fatfs error {}", res));
|
||||
fmt::format("unknown fatfs error {}", (int)res));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ public:
|
||||
return _changedSectors.put(track, side, sectorId);
|
||||
}
|
||||
|
||||
virtual bool isReadOnly()
|
||||
virtual bool isReadOnly() override
|
||||
{
|
||||
return (_fluxSink == nullptr);
|
||||
}
|
||||
|
||||
@@ -20,19 +20,19 @@ public:
|
||||
|
||||
public:
|
||||
std::shared_ptr<const Sector> get(
|
||||
unsigned track, unsigned side, unsigned sectorId)
|
||||
unsigned track, unsigned side, unsigned sectorId) override
|
||||
{
|
||||
return _image->get(track, side, sectorId);
|
||||
}
|
||||
|
||||
std::shared_ptr<Sector> put(
|
||||
unsigned track, unsigned side, unsigned sectorId)
|
||||
unsigned track, unsigned side, unsigned sectorId) override
|
||||
{
|
||||
_changed = true;
|
||||
return _image->put(track, side, sectorId);
|
||||
}
|
||||
|
||||
virtual bool isReadOnly()
|
||||
virtual bool isReadOnly() override
|
||||
{
|
||||
return (_writer == nullptr);
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
uint32_t capabilities() const
|
||||
uint32_t capabilities() const override
|
||||
{
|
||||
return OP_GETFSDATA | OP_CREATE | OP_LIST | OP_GETFILE | OP_PUTFILE |
|
||||
OP_GETDIRENT | OP_MOVE | OP_CREATEDIR | OP_DELETE;
|
||||
|
||||
@@ -160,7 +160,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
uint32_t capabilities() const
|
||||
uint32_t capabilities() const override
|
||||
{
|
||||
return OP_GETFSDATA | OP_LIST | OP_GETFILE | OP_GETDIRENT;
|
||||
}
|
||||
|
||||
@@ -140,7 +140,7 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
uint32_t capabilities() const
|
||||
uint32_t capabilities() const override
|
||||
{
|
||||
return OP_LIST | OP_GETDIRENT | OP_GETFILE | OP_GETFSDATA;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user