Skip to main content

Python library for handling Acorn DFS disc images (SSD/DSD format)

Project description

oaknut-dfs

PyPI version CI Python versions License: MIT

A Python library for reading, writing, and creating Acorn DFS floppy disc images, as used by the BBC Micro.

With oaknut-dfs you can open DFS floppy images (SSD/DSD) to browse the catalogue, read and write files, inspect metadata, and create new formatted discs — all from Python, with a pathlib-inspired API.

Looking for ADFS? The hierarchical Advanced Disc Filing System lives in the sibling oaknut-adfs package (from oaknut.adfs import ADFS). DFS and ADFS are independent filing systems and independent packages. For a unified command-line tool across DFS, ADFS, AFS, ROMFS and ZIP, see oaknut-disc.

Part of the oaknut monorepo.

Supported formats

  • Acorn DFS — 40-track and 80-track, single-sided (SSD) and double-sided (DSD)
  • Watford DFS — extended catalogue supporting up to 62 files
  • DSD interleaving — both interleaved and sequential double-sided layouts

Acorn load/exec addresses, the lock bit, and the BBC Micro character set (the acorn text codec, £, ¦) are handled through the shared oaknut-file metadata layer.

Installation

uv add oaknut-dfs      # or: pip install oaknut-dfs

oaknut-dfs is a standard Python package installable with any package manager; the examples use uv.

Usage

Opening and reading files

The disc format is auto-detected from the file extension and size; pass a format explicitly only to override detection.

from oaknut.dfs import DFS

with DFS.from_file("Zalaga.ssd") as dfs:
    print(dfs.title)   # 'ZALAG-L'

    # Navigate with a pathlib-inspired API.
    for entry in dfs.root / "$":
        s = entry.stat()
        print(f"{entry.name:10s}  {s.length:6d}  load={s.load_address:08X}")

    # Read file data.
    data = (dfs.root / "$" / "ZALAGA").read_bytes()

Creating a new disc

from oaknut.dfs import DFS, ACORN_DFS_80T_SINGLE_SIDED

with DFS.create_file("demo.ssd", ACORN_DFS_80T_SINGLE_SIDED, title="DEMO") as dfs:
    (dfs.root / "$.HELLO").write_bytes(b"Hello, World!", load_address=0x1900)
    (dfs.root / "$.README").write_bytes(b"oaknut-dfs demo disc")

Double-sided discs (DSD)

A DSD image holds two independent sides, each with its own catalogue — mirroring the BBC Micro, where the sides were accessed as separate drives (*DRIVE 0 and *DRIVE 2). Select a side with the side= argument.

from oaknut.dfs import DFS

with DFS.from_file("game.dsd") as side0:
    print(side0.title)

with DFS.from_file("game.dsd", side=1) as side2:
    print(side2.title)

Walking the disc

DFS directories ($, AZ) appear as children of a virtual root:

with DFS.from_file("disc.ssd") as dfs:
    for dirpath, dirnames, filenames in dfs.root.walk():
        for name in filenames:
            print(dirpath / name)

Development

The package is developed in the oaknut workspace. From the repository root:

uv sync                                 # install all workspace members editable
uv run pytest packages/oaknut-dfs/tests # this package's tests
uv run ruff check                       # lint

Architecture

A layered design, dependencies flowing strictly downward (every module imports only from the layer below):

DFS (dfs.py)                       user-facing DFS / DFSPath / DFSStat
  ↓
CataloguedSurface (catalogued_surface.py)
  ↓
Catalogue ABC (catalogue.py)   ←   AcornDFSCatalogue / WatfordDFSCatalogue
  ↓
Surface / SectorsView          (from oaknut-discimage)
  • dfs.py — user-facing DFS, DFSPath, DFSStat; methods mirror the DFS star commands (load, save, delete, rename, lock, …).
  • catalogue.py — the catalogue ABC (Catalogue, FileEntry, DiscInfo): 31-file cap, single-character directories, 7-char names.
  • acorn_dfs_catalogue.py / watford_dfs_catalogue.py — the Acorn (sectors 0–1, 31 files) and Watford (sectors 0–3, 62 files) catalogues.
  • catalogued_surface.py — pairs a Surface with a Catalogue.
  • formats.py — DFS and Watford disc-format constants.

Sector-level access (Surface, SectorsView, UnifiedDisc) lives in oaknut-discimage; metadata and the acorn codec in oaknut-file; BBC BASIC (de)tokenisation (for DFSPath.read_basic / write_basic) in oaknut-basic.

References

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

oaknut_dfs-12.10.0.tar.gz (102.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

oaknut_dfs-12.10.0-py3-none-any.whl (51.5 kB view details)

Uploaded Python 3

File details

Details for the file oaknut_dfs-12.10.0.tar.gz.

File metadata

  • Download URL: oaknut_dfs-12.10.0.tar.gz
  • Upload date:
  • Size: 102.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.23 {"installer":{"name":"uv","version":"0.11.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for oaknut_dfs-12.10.0.tar.gz
Algorithm Hash digest
SHA256 c17a8a7ba41b5d909c19593cdd0c8aaf24fe722bebb0c38031b4f88e8bda9bbf
MD5 c9f2158ce1b8a670a1afecfd2d7be701
BLAKE2b-256 3ee00a01acb6e5e1a7af04a0b0b98446adea10a964e5a01ba7e1b5e26d815ac3

See more details on using hashes here.

File details

Details for the file oaknut_dfs-12.10.0-py3-none-any.whl.

File metadata

  • Download URL: oaknut_dfs-12.10.0-py3-none-any.whl
  • Upload date:
  • Size: 51.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.23 {"installer":{"name":"uv","version":"0.11.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for oaknut_dfs-12.10.0-py3-none-any.whl
Algorithm Hash digest
SHA256 49834b41574ccb283d221047ab541fcfb08f2b6b9b911942946d17c797c7be80
MD5 978db852eed11f8ae30f004709ce9361
BLAKE2b-256 66f0baba2312fcd7ae94ad54cfd671a4e8647fab6adc2ffa64c33dc70ebcba7b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page