BBC Micro DFS disc image tool - catalogue, extract, create, and build with BBC BASIC detokenizer
Project description
beebtools
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:
-
Detokenize - decode the binary line records back to
LIST-style text, expanding keyword tokens, decoding line-number references, and handlingREMandDATAtails correctly (they are literal ASCII and must not be expanded). -
Pretty-print (optional,
--pretty) - add operator spacing to the raw detokenized text. BBC BASIC stores only the spaces the programmer explicitly typed, so code likeIFx>100THENx=0:y=0is normal. The pretty-printer adds spaces around operators and punctuation while leaving string literals,REMtails, andDATAtails completely untouched. -
Anti-listing trap detection - some 1980s software used
*|followed byVDU 21(disable output) bytes as a copy-protection trick. TypingLISTon the real machine would blank the screen after that line.beebtoolsconverts*|statements toREM *|and strips the control characters, so the program is readable.
Features
-
Read DFS catalogues from
.ssdand.dsddisc images -
Extract individual files by DFS name (
T.MYPROG, or bareMYPROG) -
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:
*SCUMPIis passed through verbatim, no false spacing -
.infsidecar 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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5882492fd2133c8785c890d3613f5210a7e17293fc8b8c82065b92e3fc2f3542
|
|
| MD5 |
19bdc653cf4791dfb886aec3b6163b8e
|
|
| BLAKE2b-256 |
cb707abef178623f62e250e13b220820181c06bc10b8efcc2af531e75fbe355f
|
Provenance
The following attestation bundles were made for beebtools-0.3.0.tar.gz:
Publisher:
publish.yml on acscpt/beebtools
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
beebtools-0.3.0.tar.gz -
Subject digest:
5882492fd2133c8785c890d3613f5210a7e17293fc8b8c82065b92e3fc2f3542 - Sigstore transparency entry: 1203703149
- Sigstore integration time:
-
Permalink:
acscpt/beebtools@5dd6075518081536e85d1331bc4c533d1227e567 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/acscpt
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@5dd6075518081536e85d1331bc4c533d1227e567 -
Trigger Event:
push
-
Statement type:
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0a7b197e0c5f70c24425a90e4ae1bec5201848d55263d945af72443e87e9cd51
|
|
| MD5 |
1aa147d3da95afa847acdb0d62f62438
|
|
| BLAKE2b-256 |
118cd3bfe5a421e15e5f8428e8c8d6e1ddffbc7316f4b7baac522ee5ce62326d
|
Provenance
The following attestation bundles were made for beebtools-0.3.0-py3-none-any.whl:
Publisher:
publish.yml on acscpt/beebtools
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
beebtools-0.3.0-py3-none-any.whl -
Subject digest:
0a7b197e0c5f70c24425a90e4ae1bec5201848d55263d945af72443e87e9cd51 - Sigstore transparency entry: 1203703162
- Sigstore integration time:
-
Permalink:
acscpt/beebtools@5dd6075518081536e85d1331bc4c533d1227e567 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/acscpt
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@5dd6075518081536e85d1331bc4c533d1227e567 -
Trigger Event:
push
-
Statement type: