Skip to main content

BBC Micro DFS disc image tool - catalogue, extract, create, and build with BBC BASIC detokenizer

Project description

beebtools

PyPI Python 3.8+ License: MIT Tests

A Python tool for working with BBC Micro DFS disc images.

beebtools can read disc catalogues, extract and detokenize BBC BASIC programs to a more human-readable (and text editor friendly) format, including a pretty-printer that makes dense BBC BASIC code more legible.

Disc images and the DFS catalogue

BBC Micro software is widely preserved as .ssd (single-sided) and .dsd (double-sided interleaved) disc images. Each image is a raw sector-by-sector dump of the original floppy disc, laid out according to Acorn's Disc Filing System (DFS).

The first two sectors of each disc side hold the catalogue: disc title, file count, and one entry per file giving its name, DFS directory prefix, load and exec addresses, byte length, and start sector. beebtools reads this catalogue and can list it in a human-readable table, sorted by name, catalogue order, or file size.

Files are extracted by DFS name (T.MYPROG, $.!BOOT) or by bare name when unambiguous. On a double-sided .dsd image both sides are catalogued; if the same bare name appears on both sides, beebtools tells you and asks you to be specific. Bulk extraction (-a) pulls every file off the disc at once.

Programs: BBC BASIC and binary files

Most files you will want to look at on a BBC Micro disc are BBC BASIC programs. They are not stored as text. The BBC Micro's BASIC ROM tokenizes programs before saving them: keywords like PRINT, GOTO, and FOR are replaced with single bytes in the range 0x80-0xFF, GOTO and GOSUB targets are encoded as compact 3-byte line-number references, and the whole thing is written as a sequence of binary line records with no human-readable structure.

Binary files (machine code, data, sound samples) are stored as raw bytes and extracted as-is.

For BASIC files, beebtools does three things in sequence:

  1. Detokenize - decode the binary line records back to LIST-style text, expanding keyword tokens, decoding line-number references, and handling REM and DATA tails correctly (they are literal ASCII and must not be expanded).

  2. Pretty-print (optional, --pretty) - add operator spacing to the raw detokenized text. BBC BASIC stores only the spaces the programmer explicitly typed, so code like IFx>100THENx=0:y=0 is normal. The pretty-printer adds spaces around operators and punctuation while leaving string literals, REM tails, and DATA tails completely untouched.

  3. Anti-listing trap detection - some 1980s software used *| followed by VDU 21 (disable output) bytes as a copy-protection trick. Typing LIST on the real machine would blank the screen after that line. beebtools converts *| statements to REM *| and strips the control characters, so the program is readable.

Features

  • Read DFS catalogues from .ssd and .dsd disc images

  • Extract individual files by DFS name (T.MYPROG, or bare MYPROG)

  • Bulk-extract everything from a disc image at once

  • Detokenize BBC BASIC II programs to LIST-style plain text

  • Pretty-printer: add operator spacing to make terse BASIC readable

  • Anti-listing trap detection: neutralise copy-protection *| traps

  • Star command awareness: *SCUMPI is passed through verbatim, no false spacing

  • .inf sidecar format support: parse and produce the standard community interchange format for preserving DFS file metadata alongside extracted files

  • Create, modify, and build disc images from the command line or as a library

  • Zero dependencies - pure Python 3.8+, single package

Installation

pip install beebtools

For development (installs pytest and uses an editable install):

git clone https://github.com/acscpt/beebtools
cd beebtools
python -m venv .venv
source .venv/bin/activate   # Windows: .venv\Scripts\activate
pip install -e ".[dev]"

Commands

beebtools provides commands for inspecting, extracting, and building DFS disc images. Each command has its own detailed reference page.

Command Description
cat List disc catalogue with file types and metadata
search Search BASIC source for a text pattern or regex
extract Extract a single file or bulk-extract all files
create Create a blank formatted disc image
add Add a file to an existing disc image
delete Delete a file from a disc image
build Build a disc image from files with .inf sidecars

Usage

# List what is on a disc image
beebtools cat mydisc.dsd

# Extract and detokenize a BASIC program
beebtools extract mydisc.dsd T.MYPROG

# Extract with operator spacing added
beebtools extract mydisc.dsd T.MYPROG --pretty

# Extract everything from a double-sided disc
beebtools extract mydisc.dsd -a --pretty -d output/

# Extract everything with .inf sidecars preserving DFS metadata
beebtools extract mydisc.dsd -a --inf -d output/

# Create a blank disc image
beebtools create blank.ssd --title "MY DISC" --boot EXEC

# Add a file to an existing image
beebtools add mydisc.ssd loader.bin --name $.LOADER --load 1900 --exec 1900

# Add a file using its .inf sidecar for metadata
beebtools add mydisc.ssd loader.bin --inf

# Delete a file from an image
beebtools delete mydisc.ssd $.LOADER

# Build a disc image from a directory of files with .inf sidecars
beebtools build output/ rebuilt.ssd --title "REBUILT"

Pretty-printer

When extracting BASIC files from a disc image, the --pretty flag adds operator spacing to make the dense tokenized code more readable.

  100 IFx>100ORy<0THENx=0:y=0
  110 FORi=1TO8:s=s+x*x:NEXTi
  120 SOUND1,-15,s,5:IFs>9999THENs=0

With --pretty:

  100 IFx > 100ORy < 0THENx = 0 : y = 0
  110 FORi = 1TO8 : s = s + x * x : NEXTi
  120 SOUND1, -15, s, 5 : IFs > 9999THENs = 0

See docs/pretty-printer.md for the full list of spacing rules and anti-listing trap handling.

Using as a library

from beebtools import openDiscImage, detokenize, prettyPrint

image = openDiscImage("mydisc.dsd")
for side in image.sides:
    catalogue = side.readCatalogue()
    for entry in catalogue.entries:
        if entry.isBasic:
            data = side.readFile(entry)
            lines = prettyPrint(detokenize(data))
            print("\n".join(lines))

See docs/library.md for creating disc images, building from .inf sidecars, and working with the .inf format programmatically.

Supported formats

Format Description
.ssd Single-sided 40 or 80 track
.dsd Double-sided interleaved

Both 40-track and 80-track images are supported. The tool does not currently support Watford DFS extended catalogues (62-file discs).

Documentation

See the docs/ folder for full command reference, pretty-printer details, and library API guide.

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

beebtools-0.3.0.tar.gz (54.2 kB view details)

Uploaded Source

Built Distribution

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

beebtools-0.3.0-py3-none-any.whl (33.5 kB view details)

Uploaded Python 3

File details

Details for the file beebtools-0.3.0.tar.gz.

File metadata

  • Download URL: beebtools-0.3.0.tar.gz
  • Upload date:
  • Size: 54.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for beebtools-0.3.0.tar.gz
Algorithm Hash digest
SHA256 5882492fd2133c8785c890d3613f5210a7e17293fc8b8c82065b92e3fc2f3542
MD5 19bdc653cf4791dfb886aec3b6163b8e
BLAKE2b-256 cb707abef178623f62e250e13b220820181c06bc10b8efcc2af531e75fbe355f

See more details on using hashes here.

Provenance

The following attestation bundles were made for beebtools-0.3.0.tar.gz:

Publisher: publish.yml on acscpt/beebtools

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file beebtools-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: beebtools-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 33.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for beebtools-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0a7b197e0c5f70c24425a90e4ae1bec5201848d55263d945af72443e87e9cd51
MD5 1aa147d3da95afa847acdb0d62f62438
BLAKE2b-256 118cd3bfe5a421e15e5f8428e8c8d6e1ddffbc7316f4b7baac522ee5ce62326d

See more details on using hashes here.

Provenance

The following attestation bundles were made for beebtools-0.3.0-py3-none-any.whl:

Publisher: publish.yml on acscpt/beebtools

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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