Skip to content

acscpt/beebtools

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

29 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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.

About

A Python tool/library for working with BBC Micro DFS images and BBC BASIC detokenization

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages