From 4f6f4010ae17d5a72098bac2a58ad2385cb848db Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Fri, 15 Apr 2022 10:20:48 -0500 Subject: [PATCH] Rename the program, make it installable via pip --- .gitignore | 6 + README.md | 22 ++- {passport => a2woz}/.gitignore | 0 {passport => a2woz}/__init__.py | 10 +- {passport => a2woz}/__main__.py | 17 +- {passport => a2woz}/a2rchery.py | 0 {passport => a2woz}/a2rimage.py | 4 +- {passport => a2woz}/eddimage.py | 2 +- {passport => a2woz}/loggers/__init__.py | 0 {passport => a2woz}/loggers/debug.py | 2 +- {passport => a2woz}/loggers/default.py | 4 +- {passport => a2woz}/loggers/silent.py | 2 +- a2woz/strings.py | 11 ++ {passport => a2woz}/util/__init__.py | 0 {passport => a2woz}/util/find.py | 0 {passport => a2woz}/wozardry.py | 0 passport/constants.py | 197 ------------------------ passport/strings.py | 7 - pyproject.toml | 14 ++ requirements.txt | 4 + setup.cfg | 33 ++++ 21 files changed, 107 insertions(+), 228 deletions(-) rename {passport => a2woz}/.gitignore (100%) rename {passport => a2woz}/__init__.py (94%) rename {passport => a2woz}/__main__.py (86%) rename {passport => a2woz}/a2rchery.py (100%) rename {passport => a2woz}/a2rimage.py (97%) rename {passport => a2woz}/eddimage.py (96%) rename {passport => a2woz}/loggers/__init__.py (100%) rename {passport => a2woz}/loggers/debug.py (80%) rename {passport => a2woz}/loggers/default.py (87%) rename {passport => a2woz}/loggers/silent.py (58%) create mode 100644 a2woz/strings.py rename {passport => a2woz}/util/__init__.py (100%) rename {passport => a2woz}/util/find.py (100%) rename {passport => a2woz}/wozardry.py (100%) delete mode 100644 passport/constants.py delete mode 100644 passport/strings.py create mode 100644 pyproject.toml create mode 100644 requirements.txt create mode 100644 setup.cfg diff --git a/.gitignore b/.gitignore index bee8a64..88f7125 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,7 @@ +# SPDX-FileCopyrightText: 2022 Kattni Rembor, written for Adafruit Industries +# +# SPDX-License-Identifier: MIT __pycache__ +*.egg-info +a2woz/__version__.py +build diff --git a/README.md b/README.md index 468f815..9a49e17 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,31 @@ -# woz rawconvert (was passport.py) +# a2woz - minimally process a2r files into woz files ## Usage +One-time installation: ```shell -python3 -mpassport input.a2r output.woz +pip install https://github.com/adafruit/a2woz +``` + +Convert a single file: +```shell +a2woz input.a2r +``` + +Convert multiple files, with output directory: +```shell +a2woz --output-dir out *.a2r +``` + +Full usage: +```shell +a2woz --help ``` ## Theory of a2r to woz raw conversion: The a2r file contains "1 and a fraction" revolutions, for each track. (It can actually contain multiple revolutions, but ignore that for now) -`passport.py rawconvert` takes a revolution, then finds all the "sync points". +`a2woz` takes a revolution, then finds all the "sync points". "sync points" are a sequence of 2 or more "FF36" or "FF40", which are used by the floppy interface controller to synchronize with data on the floppy. diff --git a/passport/.gitignore b/a2woz/.gitignore similarity index 100% rename from passport/.gitignore rename to a2woz/.gitignore diff --git a/passport/__init__.py b/a2woz/__init__.py similarity index 94% rename from passport/__init__.py rename to a2woz/__init__.py index da37a9c..6c7f8fa 100755 --- a/passport/__init__.py +++ b/a2woz/__init__.py @@ -1,8 +1,7 @@ -from passport.loggers import * -from passport.strings import * -from passport.constants import * -from passport.util import * -from passport import wozardry +from .loggers import * +from .strings import * +from .util import * +from . import wozardry import bitarray import io import json @@ -42,7 +41,6 @@ class BasePassportProcessor: # base class class RawConvert(BasePassportProcessor): def run(self): - self.g.logger.PrintByID("header") self.g.logger.PrintByID("reading", {"filename":self.g.filename}) self.tracks = {} diff --git a/passport/__main__.py b/a2woz/__main__.py similarity index 86% rename from passport/__main__.py rename to a2woz/__main__.py index 1d03137..3031c05 100755 --- a/passport/__main__.py +++ b/a2woz/__main__.py @@ -5,19 +5,18 @@ import click -from passport import eddimage, wozardry, a2rimage -from passport.loggers import DefaultLogger, DebugLogger -from passport import RawConvert -from passport.strings import __date__, STRINGS +from . import eddimage, wozardry, a2rimage +from .loggers import DefaultLogger, DebugLogger +from . import RawConvert, PassportGlobals +from .strings import STRINGS, version import argparse import os.path -__version__ = "0.2" # https://semver.org/ -__progname__ = "passport" +__progname__ = "a2woz" @click.command() @click.help_option() -@click.version_option(version=__version__) +@click.version_option(version=version) @click.option("--debug", "-d", is_flag="True", help="print debugging information while processing") @click.option("--output-dir", "output_dir", type=click.Path(file_okay=False, dir_okay=True), default=None, help="Output directory") @click.option("--output", "-o", "output_file", type=click.Path(), default=None, help="Output path, defaults to the input with the extension replaced with .woz. When multiple input files are specified, --output may not be used.") @@ -43,6 +42,9 @@ def main(debug, input_files, output_file, output_dir, overwrite): if output_dir is not None: os.makedirs(output_dir, exist_ok=True) + logger = DebugLogger if debug else DefaultLogger + logger(PassportGlobals()).PrintByID("header") + for input_file in input_files: base, ext = os.path.splitext(input_file) ext = ext.lower() @@ -56,7 +58,6 @@ def main(debug, input_files, output_file, output_dir, overwrite): if output_dir: output_file = os.path.join(output_dir, os.path.splitext(os.path.basename(input_file))[0] + ".woz") - logger = debug and DebugLogger or DefaultLogger with open(input_file, "rb") as f: RawConvert(input_file, reader(f), logger, output_file) diff --git a/passport/a2rchery.py b/a2woz/a2rchery.py similarity index 100% rename from passport/a2rchery.py rename to a2woz/a2rchery.py diff --git a/passport/a2rimage.py b/a2woz/a2rimage.py similarity index 97% rename from passport/a2rimage.py rename to a2woz/a2rimage.py index 3a7acc4..1963c96 100755 --- a/passport/a2rimage.py +++ b/a2woz/a2rimage.py @@ -1,5 +1,5 @@ -from passport.wozardry import Track, raise_if -from passport import a2rchery +from .wozardry import Track, raise_if +from . import a2rchery import bitarray import collections diff --git a/passport/eddimage.py b/a2woz/eddimage.py similarity index 96% rename from passport/eddimage.py rename to a2woz/eddimage.py index 25cf592..1f161bb 100644 --- a/passport/eddimage.py +++ b/a2woz/eddimage.py @@ -1,4 +1,4 @@ -from passport.wozardry import Track, raise_if +from .wozardry import Track, raise_if import bitarray import json diff --git a/passport/loggers/__init__.py b/a2woz/loggers/__init__.py similarity index 100% rename from passport/loggers/__init__.py rename to a2woz/loggers/__init__.py diff --git a/passport/loggers/debug.py b/a2woz/loggers/debug.py similarity index 80% rename from passport/loggers/debug.py rename to a2woz/loggers/debug.py index 343121f..77dfda0 100644 --- a/passport/loggers/debug.py +++ b/a2woz/loggers/debug.py @@ -1,4 +1,4 @@ -from passport.loggers.default import DefaultLogger +from .default import DefaultLogger import sys class DebugLogger(DefaultLogger): diff --git a/passport/loggers/default.py b/a2woz/loggers/default.py similarity index 87% rename from passport/loggers/default.py rename to a2woz/loggers/default.py index c7b1efb..535c2b1 100644 --- a/passport/loggers/default.py +++ b/a2woz/loggers/default.py @@ -1,5 +1,5 @@ -from passport.loggers import BaseLogger -from passport.strings import STRINGS +from . import BaseLogger +from ..strings import STRINGS import sys class DefaultLogger(BaseLogger): diff --git a/passport/loggers/silent.py b/a2woz/loggers/silent.py similarity index 58% rename from passport/loggers/silent.py rename to a2woz/loggers/silent.py index eecd3d4..c1c724a 100644 --- a/passport/loggers/silent.py +++ b/a2woz/loggers/silent.py @@ -1,4 +1,4 @@ -from passport.loggers import BaseLogger +from . import BaseLogger class SilentLogger(BaseLogger): """print nothing""" diff --git a/a2woz/strings.py b/a2woz/strings.py new file mode 100644 index 0000000..2aae364 --- /dev/null +++ b/a2woz/strings.py @@ -0,0 +1,11 @@ +try: + from .__version__ import version +except: + version = "UNKNOWN" + +_header = "a2woz " + version +STRINGS = { + "header": f"a2woz {version}\n", + "reading": "Reading from {filename}\n", + "writing": "Writing to {filename}\n", +} diff --git a/passport/util/__init__.py b/a2woz/util/__init__.py similarity index 100% rename from passport/util/__init__.py rename to a2woz/util/__init__.py diff --git a/passport/util/find.py b/a2woz/util/find.py similarity index 100% rename from passport/util/find.py rename to a2woz/util/find.py diff --git a/passport/wozardry.py b/a2woz/wozardry.py similarity index 100% rename from passport/wozardry.py rename to a2woz/wozardry.py diff --git a/passport/constants.py b/passport/constants.py deleted file mode 100644 index 2e57389..0000000 --- a/passport/constants.py +++ /dev/null @@ -1,197 +0,0 @@ -from passport.util import * - -kIDBoot1 = bytes.fromhex( - "8E E9 B7" - "8E F7 B7" - "A9 01" - "8D F8 B7" - "8D EA B7" - "AD E0 B7" - "8D E1 B7" - "A9 02" - "8D EC B7" - "A9 04" - "8D ED B7" - "AC E7 B7" - "88" - "8C F1 B7" - "A9 01" - "8D F4 B7" - "8A" - "4A" - "4A" - "4A" - "4A" - "AA" - "A9 00" - "9D F8 04" - "9D 78 04") - -kIDMaster = bytes.fromhex( - "8E E9 37" - "8E F7 37" - "A9 01" - "8D F8 37" - "8D EA 37" - "AD E0 37" - "8D E1 37" - "A9 02" - "8D EC 37" - "A9 04" - "8D ED 37" - "AC E7 37" - "88" - "8C F1 37" - "A9 01" - "8D F4 37" - "8A" - "4A" - "4A" - "4A" - "4A" - "AA" - "A9 00" - "9D F8 04" - "9D 78 04") - -kIDRWTS = bytes.fromhex( - "84 48" - "85 49" - "A0 02" - "8C" + find.WILDSTR + find.WILDSTR + \ - "A0 04" - "8C" + find.WILDSTR + find.WILDSTR + \ - "A0 01" - "B1 48" - "AA" - "A0 0F" - "D1 48" - "F0 1B" - "8A" - "48" - "B1 48" - "AA" - "68" - "48" - "91 48" - "BD 8E C0" - "A0 08" - "BD 8C C0" - "DD 8C C0" - "D0 F6" - "88" - "D0 F8" - "68" - "AA" - "BD 8E C0" - "BD 8C C0" - "A0 08" - "BD 8C C0" - "48") - -kIDDiversiDOSBootloader = bytes.fromhex("B3 A3 A0 D2 CF D2 D2 C5 8D 87 8D") - -kIDProDOSBootloader = bytes.fromhex( - "01" - "38" # SEC - "B0 03" # BCS +3 - "4C") # JMP - -kIDPascalBootloader1 = bytes.fromhex( - "01" - "E0 60" # CPX #$60 - "F0 03" # BEQ +3 - "4C" + find.WILDSTR + "08") # JMP $08** - -kIDPascalBootloader2 = bytes.fromhex( - "01" - "E0 70" # CPX #$70 - "B0 04" # BCS +4 - "E0 40" # CPX #$40 - "B0") # BCS - -kIDDavidDOS1 = bytes.fromhex( - "A5 27" - "C9 09" - "D0 17") - -kIDDavidDOS2 = bytes.fromhex( - "A2" + find.WILDSTR + \ - "BD" + find.WILDSTR + " 08" + \ - "9D" + find.WILDSTR + " 04" + \ - "CA" - "10 F7") - -kIDDatasoft = bytes.fromhex( - "01 4C 7E 08 04 8A 0C B8" - "00 56 10 7A 00 00 1A 16" - "12 0E 0A 06 53 18 9A 02" - "10 1B 02 10 4D 56 15 0B" - "BF 14 14 54 54 54 92 81" - "1B 10 10 41 06 73 0A 10" - "33 4E 00 73 12 10 33 7C" - "00 11 20 E3 49 50 73 1A" - "10 41 00 23 80 5B 0A 10" - "0B 4E 9D 0A 10 9D 0C 10" - "60 1E 53 10 90 53 BC 90" - "53 00 90 D8 52 00 D8 7C" - "00 53 80 0B 06 41 00 09" - "04 45 0C 63 04 90 94 D0" - "D4 23 04 91 A1 EB CD 06" - "95 A1 E1 98 97 86") - -kIDMicrograms1 = bytes.fromhex( - "A5 27" - "C9 09" - "D0 12" - "A9 C6" - "85 3F") - -kIDMicrograms2 = bytes.fromhex("4C 00") - -kIDQuickDOS = bytes.fromhex( - "A5 27" - "C9 09" - "D0 27" - "78" - "AD 83 C0") - -kIDRDOS = bytes.fromhex( - "01" - "A9 60" - "8D 01 08" - "A2 00" - "A0 1F" - "B9 00 08" - "49") - -kIDDOS33a = bytes.fromhex( - "01" - "A5 27" - "C9 09" - "D0 18" - "A5 2B" - "4A" - "4A" - "4A" - "4A" - "09 C0" - "85 3F" - "A9 5C" - "85 3E" - "18" - "AD FE 08" - "6D FF 08" + \ - find.WILDSTR + find.WILDSTR + find.WILDSTR + \ - "AE FF 08" - "30 15" - "BD 4D 08" - "85 3D" - "CE FF 08" - "AD FE 08" - "85 27" - "CE FE 08" - "A6 2B" - "6C 3E 00" - "EE FE 08" - "EE FE 08") diff --git a/passport/strings.py b/passport/strings.py deleted file mode 100644 index e4345d0..0000000 --- a/passport/strings.py +++ /dev/null @@ -1,7 +0,0 @@ -__date__ = "2019-03-03" - -STRINGS = { - "header": "Passport.py by 4am (" + __date__ + ")\n", # max 32 characters - "reading": "Reading from {filename}\n", - "writing": "Writing to {filename}\n", -} diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..f88c249 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,14 @@ +# SPDX-FileCopyrightText: 2022 Jeff Epler for Adafruit Industries +# +# SPDX-License-Identifier: MIT + +[build-system] +requires = [ + "setuptools>=45", + "setuptools_scm[toml]>=6.0", + "wheel", +] +build-backend = "setuptools.build_meta" + +[tool.setuptools_scm] +write_to = "a2woz/__version__.py" diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..ca8ae30 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +# SPDX-FileCopyrightText: 2022 Jeff Epler for Adafruit Industries +# +# SPDX-License-Identifier: MIT + diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..dfbee1a --- /dev/null +++ b/setup.cfg @@ -0,0 +1,33 @@ +# SPDX-FileCopyrightText: 2022 Jeff Epler for Adafruit Industries +# +# SPDX-License-Identifier: MIT + +[metadata] +name = a2woz +author = Jeff Epler for Adafruit Industries +author_email = jeff@adafruit.com +description = Visualize floppy disk flux patterns +long_description = file: README.md +long_description_content_type = text/markdown +url = https://github.com/adafruit/a2woz +classifiers = + Programming Language :: Python :: 3 + Programming Language :: Python :: 3.9 + Programming Language :: Python :: 3.10 + Programming Language :: Python :: Implementation :: CPython + License :: OSI Approved :: MIT License + Operating System :: OS Independent + +[options] +package_dir = + =. +packages = + a2woz + a2woz.loggers + a2woz.util +python_requires = >=3.9 +install_requires = + +[options.entry_points] +console_scripts = + a2woz = a2woz.__main__:main