Rename the program, make it installable via pip
This commit is contained in:
parent
6b4233302a
commit
4f6f4010ae
21 changed files with 107 additions and 228 deletions
6
.gitignore
vendored
6
.gitignore
vendored
|
|
@ -1 +1,7 @@
|
|||
# SPDX-FileCopyrightText: 2022 Kattni Rembor, written for Adafruit Industries
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
__pycache__
|
||||
*.egg-info
|
||||
a2woz/__version__.py
|
||||
build
|
||||
|
|
|
|||
22
README.md
22
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.
|
||||
|
||||
|
|
|
|||
0
passport/.gitignore → a2woz/.gitignore
vendored
0
passport/.gitignore → a2woz/.gitignore
vendored
|
|
@ -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 = {}
|
||||
|
|
@ -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)
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
from passport.wozardry import Track, raise_if
|
||||
from .wozardry import Track, raise_if
|
||||
import bitarray
|
||||
import json
|
||||
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
from passport.loggers.default import DefaultLogger
|
||||
from .default import DefaultLogger
|
||||
import sys
|
||||
|
||||
class DebugLogger(DefaultLogger):
|
||||
|
|
@ -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):
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
from passport.loggers import BaseLogger
|
||||
from . import BaseLogger
|
||||
|
||||
class SilentLogger(BaseLogger):
|
||||
"""print nothing"""
|
||||
11
a2woz/strings.py
Normal file
11
a2woz/strings.py
Normal file
|
|
@ -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",
|
||||
}
|
||||
|
|
@ -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")
|
||||
|
|
@ -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",
|
||||
}
|
||||
14
pyproject.toml
Normal file
14
pyproject.toml
Normal file
|
|
@ -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"
|
||||
4
requirements.txt
Normal file
4
requirements.txt
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
# SPDX-FileCopyrightText: 2022 Jeff Epler for Adafruit Industries
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
33
setup.cfg
Normal file
33
setup.cfg
Normal file
|
|
@ -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
|
||||
Loading…
Reference in a new issue