oaknut-basic
Read the documentation — getting started, the command reference, and the API.
Work with the persistent artefacts a BBC BASIC program leaves behind — both the code and the data:
- Programs. Convert a program between its compact on-disc tokenised form
and a plain-text listing — the two directions a real BBC Micro performs when
you
LOADandLISTit — plus line numbering for source typed without numbers. - Data files. Read and write the channel-based files a program creates with
OPENOUTand writes withPRINT#andBPUT#, translating their tagged records to and from native Python values.
The problem
Both formats are bytecode, not text, and idiosyncratic to the BBC.
A tokenised program packs keywords like PRINT and GOTO into single bytes,
folds line numbers into each line's header, and scrambles a reference such as
GOTO 100 into a three-byte form that can never be mistaken for a line
terminator. A text codec decoding one produces garbage.
A PRINT# data file is just as surprising: PRINT#channel, 42 writes a type
tag and the number's bytes in reverse, not the characters 4 2; strings
go out length-prefixed and backwards, and reals use the BBC's packed 5-byte
floating-point format. The file is meant to be read back only by INPUT#.
oaknut-basic reproduces the BBC BASIC II ROM's behaviour exactly — every
token value and flag, the line-number encoding, the record tags and the 5-byte
REAL format — so a program round-trips between bytes and text byte-for-byte,
and a data file round-trips through Python values byte-for-byte.
Installation
Install as a tool for the oaknut-basic command, or add it to a project for
the library:
uv tool install oaknut-basic # the command-line tool
uv add oaknut-basic # the importable library
pip works identically with the same names. oaknut-basic requires Python
3.11 or newer.
Command-line usage
$ oaknut-basic --help
Usage: oaknut-basic [OPTIONS] COMMAND [ARGS]...
Tools for BBC BASIC programs and data files.
Options:
--version Show the version and exit.
--help Show this message and exit.
Commands:
data Read and write BBC BASIC data files.
detokenise De-tokenise a stored BBC BASIC program into source text.
number Prepend ascending line numbers to an unnumbered BBC BASIC...
tokenise Tokenise BBC BASIC source text into a stored program.
The program commands read from a file or standard input and write to a file or
standard output, so each works file-to-file and as a pipe stage. That makes
them compose with oaknut-disc
to edit a program in place on a disc image:
disc get game.ssd MENU - | oaknut-basic detokenise > menu.bas
oaknut-basic tokenise menu.bas | disc put game.ssd MENU -
Tokenising and de-tokenising are exact inverses, so a program survives a
there-and-back trip unchanged. The tokenise command can also number
unnumbered source on the way in (--start / --step), exactly as typing it
under AUTO would.
The data subcommands turn a PRINT# data file into something host tools can
read. The inspect command shows its records as a table; decode and encode
are a lossless JSON round-trip pair for editing or generating a file:
oaknut-basic data inspect scores.dat
oaknut-basic data decode scores.dat | jq '.[0]'
echo '[42, "HELLO", 3.5]' | oaknut-basic data encode - scores.dat
Library usage
Programs are handled by the functions tokenise, detokenise, and
number_lines, all importable from oaknut.basic:
from oaknut.basic import tokenise, detokenise
program = tokenise('10 PRINT "HELLO"\n20 GOTO 10\n') # str -> bytes
listing = detokenise(program) # bytes -> str
assert tokenise(detokenise(program)) == program # byte-exact
When the program lives in a disc image, prefer the path-object wrappers
DFSPath.read_basic / write_basic (and the ADFS equivalents), which compose
the codec with the disc's character encoding and the correct load address.
Data files are handled by a context-managed, file-like object. The
module-level open mirrors the built-in one: a mode string selects a reader,
a writer, or a combined object, and accepts a path or a binary stream. The
polymorphic write picks the record type from the Python value; typed
read_int / read_float / read_str read it back without coercion:
from oaknut.basic import datafile
with datafile.open("scores.dat", "w") as f:
f.write("ALICE") # str -> string record
f.write(42) # int -> integer record
f.write(3.5) # float -> real record
with datafile.open("scores.dat", "r") as f:
for value in f: # yields "ALICE", 42, 3.5
print(value)
Strings use the BBC acorn character set by default, and reals convert through
the packed 5-byte REAL format exposed as pack_float5 / unpack_float5.
References
- BBC BASIC — Wikipedia overview of the language and its versions.
- BBC BASIC program format — BeebWiki reference for the on-disc tokenised format and the token table.
- Format of a random access file —
BeebWiki background on the disc filing system that holds these files; the
PRINT#record tags and 5-byte REAL format are documented in this package's own API reference.
Part of oaknut
oaknut-basic is one package in the
oaknut monorepo of tools for Acorn
computer filesystems, files, and formats. It backs the read_basic /
write_basic methods of the oaknut-dfs and oaknut-adfs packages, and is
usable on its own for the .bas / .bbc programs and the data files BBC BASIC
leaves on a disc.
License
MIT — see LICENSE.
Metadata
Release files for oaknut-basic 13.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| oaknut_basic-13.3.0.tar.gz | 68.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| oaknut_basic-13.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 113.2 kB
Release files / oaknut_basic-13.3.0.tar.gz
| Download URL | oaknut_basic-13.3.0.tar.gz |
|---|---|
| Size | 68.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e97a31ce889f1107b9f735587404b91d04d35ebe97234ec24d7ee65d076dd8e2
|
|
BLAKE2b-256 checksum How to use checksums |
7a572a72b495be84c503562436394fa10b0c05fa7000a75f37e7cfeb6dffc06d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.23 {"installer":{"name":"uv","version":"0.12.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}
|
Release files / oaknut_basic-13.3.0-py3-none-any.whl
| Download URL | oaknut_basic-13.3.0-py3-none-any.whl |
|---|---|
| Size | 44.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
01cf1bf9805aa78ce0f4453b2b207ff1a74fc7bf1e5297d807077f8f39a8f610
|
|
BLAKE2b-256 checksum How to use checksums |
530016b1410e296d7b9b4f34578e798edc4aad8111cfd4402c4ee0cecf5e7539
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.23 {"installer":{"name":"uv","version":"0.12.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}
|