Work with ZIP files containing Acorn computer metadata.
Project description
oaknut-zip
A Python tool for extracting ZIP files containing Acorn computer metadata.
Standard unzip tools silently discard the load addresses, execution addresses, and file attributes that Acorn systems (BBC Micro, Master, Archimedes, RISC OS machines) store in ZIP archives. oaknut-zip preserves this metadata, writing it out in your choice of four formats.
The problem
When software for Acorn 8-bit and 32-bit systems is distributed as ZIP files, the archives often contain platform-specific metadata embedded using mechanisms that non-Acorn unzip tools ignore:
- SparkFS extra fields in the ZIP structure itself, carrying load/exec addresses and RISC OS file attributes.
- Bundled INF sidecar files inside the archive, in either Acorn or PiEconetBridge format.
- Unix filename encoding, where metadata is appended to filenames as comma- separated hex suffixes.
Extracting these archives with unzip or Python's zipfile module on Linux or
macOS produces the raw file data but loses all the Acorn metadata. For 6502 or
ARM executables, this means you no longer know where in memory a program should
be loaded or where execution should begin. For a PiEconetBridge fileserver, the
files become unserviceable without their attributes.
oaknut-zip reads all three metadata sources from the ZIP and writes them out in a format your target system can consume.
Prerequisites
oaknut-zip requires only uv. uv handles
Python installation, dependency resolution, and virtual environments
automatically --- you do not need to install anything else by hand.
Installing uv
macOS (Homebrew):
brew install uv
Linux / macOS (standalone installer):
curl -LsSf https://astral.sh/uv/install.sh | sh
Windows:
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
See the uv installation docs for other methods including pip, pipx, Cargo, Conda, Winget, and Scoop.
Installation
Run without installing
uvx oaknut-zip <command> [options]
This always uses the latest published version, but has a small startup overhead on each invocation.
Persistent install
uv tool install oaknut-zip
Subsequently run as just oaknut-zip:
oaknut-zip <command> [options]
This is faster to invoke, but you need uv tool upgrade oaknut-zip to
pick up new versions.
Usage
Commands
$ oaknut-zip --help
Usage: oaknut-zip [OPTIONS] COMMAND [ARGS]...
Work with ZIP files containing Acorn computer metadata.
Options:
--version Show the version and exit.
--help Show this message and exit.
Commands:
extract Extract a ZIP file, preserving Acorn metadata.
info Show summary of Acorn metadata in a ZIP file.
list List ZIP contents showing Acorn metadata.
Inspecting an archive
list --- tabular view of all entries
$ oaknut-zip list NetUtils.zip
NetUtils.zip
┏━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━┳━━━━━━━━━┓
┃ Filename ┃ Load ┃ Exec ┃ Length ┃ Attr ┃ Type ┃ Source ┃
┡━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━╇━━━━━━━━━┩
│ Free │ FFFF0E10 │ FFFF0E10 │ 000001E6 │ C18325D │ F0E │ sparkfs │
│ FSList │ FFFF0900 │ FFFF0900 │ 00000200 │ 1415365D │ F09 │ sparkfs │
│ PSList │ FFFF0900 │ FFFF0900 │ 000001B5 │ B861C5D │ F09 │ sparkfs │
│ Notify │ FFFF0E23 │ FFFF0E23 │ 0000012A │ C6B1E5D │ F0E │ sparkfs │
│ Remote │ FFFF0E10 │ FFFF0E10 │ 000001ED │ 1347085D │ F0E │ sparkfs │
│ Servers │ FFFF0900 │ FFFF091A │ 000001CF │ 17162C5D │ F09 │ sparkfs │
│ SetStation │ FFFFDD00 │ FFFFDD00 │ 00000200 │ 1761575D │ FDD │ sparkfs │
│ Stations │ FFFF08D5 │ FFFF08E1 │ 0000022B │ 13615A57 │ F08 │ sparkfs │
│ SJMon │ FFFF1B00 │ FFFF1B00 │ 00000D7E │ F6040D │ F1B │ sparkfs │
│ Users │ FFFF0E23 │ FFFF0E23 │ 00000139 │ 15355D │ F0E │ sparkfs │
│ View │ FFFF0900 │ FFFF0904 │ 000001FF │ 135A115D │ F09 │ sparkfs │
│ ReadMe │ FFFFFF52 │ 2FEEAFD0 │ 00000255 │ BEB2A55 │ FFF │ sparkfs │
└────────────┴──────────┴──────────┴──────────┴──────────┴──────┴─────────┘
The Source column shows where the metadata was found (see the
format identifier table below). The Type column
shows the RISC OS filetype extracted from the load address (when the top
12 bits are 0xFFF).
info --- summary statistics
$ oaknut-zip info NetUtils.zip
Archive: NetUtils.zip
Files: 12
Dirs: 0
SparkFS: 12 files with ARC0 extra fields
inf-trad: 0 files with bundled traditional INF
inf-pieb: 0 files with bundled PiEconetBridge INF
Filename: 0 files with encoded filenames
Plain: 0 files without Acorn metadata
Filetypes: 6 distinct
F08: 1 files
F09: 4 files
F0E: 4 files
F1B: 1 files
FDD: 1 files
FFF: 1 files
Extracting an archive
$ oaknut-zip extract --help
Usage: oaknut-zip extract [OPTIONS] ZIPFILE_PATH
Extract a ZIP file, preserving Acorn metadata.
Options:
-d, --output-dir PATH Output directory (default: ZIP filename
without extension).
-v, --verbose Show extraction progress.
--meta-format [inf-trad|inf-pieb|xattr|filename-riscos|filename-mos|none]
Metadata format: inf-trad, inf-pieb, xattr,
filename-riscos, filename-mos, or none.
--no-decode-filenames Do not decode metadata from filename
suffixes (,xxx or ,load,exec).
--owner INTEGER Econet owner ID for inf-pieb files (default:
0 = SYST).
--help Show this message and exit.
oaknut-zip uses a consistent <mechanism>-<flavour> naming scheme for format
identifiers. The same identifiers appear as metadata source labels in
the list and info commands, and as --meta-format choices for output:
| Identifier | As input source | As output format (--meta-format) |
|---|---|---|
sparkfs |
SparkFS/ARC0 extra fields in the ZIP structure | --- (not an output format) |
inf-trad |
Bundled traditional .inf sidecar files |
Traditional INF sidecar files |
inf-pieb |
Bundled PiEconetBridge .inf sidecar files |
PiEconetBridge INF sidecar files |
filename |
Metadata encoded in filenames (,xxx, ,load,exec, ,load-exec) |
--- (not an output format) |
filename-riscos |
--- | RISC OS filename encoding (,xxx or ,llllllll,eeeeeeee) |
filename-mos |
--- | MOS filename encoding (,load-exec) |
xattr |
--- | Extended attributes (user.econet_*) |
none |
--- | No metadata (raw extraction) |
Format 1: Traditional INF (default)
oaknut-zip extract NetUtils.zip
Each extracted file gets a companion .inf sidecar file:
$ cat SetStation.inf
SetStation FFFFDD00 FFFFDD00 00000200 1761575D
$ cat ReadMe.inf
ReadMe FFFFFF52 2FEEAFD0 00000255 BEB2A55
The fields are space-separated, with the filename left-padded to 11 characters:
filename load exec length [access]
| Field | Format | Description |
|---|---|---|
| filename | ASCII string | Leaf filename, left-padded to 11 chars |
| load | 8-digit hex | 32-bit load address; if top 12 bits = FFF, bits 8--19 encode the filetype |
| exec | 8-digit hex | 32-bit execution address (entry point for code) |
| length | 8-digit hex | File length in bytes |
| access | 2-digit hex | Acorn file attributes (optional; see attribute bits below) |
This is the standard format understood by BBC Micro emulators, disc image tools (BBCIM, Disc Image Manager), and other retro-computing utilities.
Format 2: PiEconetBridge INF
oaknut-zip extract --meta-format inf-pieb NetUtils.zip
Writes .inf sidecar files in the format used by
PiEconetBridge:
$ cat SetStation.inf
0 ffffdd00 ffffdd00 1761575d
$ cat ReadMe.inf
0 ffffff52 2feeafd0 beb2a55
The fields, all lowercase hex:
owner load exec perm
| Field | Format | Description |
|---|---|---|
| owner | short hex | Econet user ID (set with --owner, default 0 = SYST) |
| load | long hex | 32-bit load address |
| exec | long hex | 32-bit execution address |
| perm | short hex | File permissions byte |
PiEconetBridge reads this format from <filename>.inf when extended attribute
support is unavailable on the host filesystem (e.g. FAT32). This is the format
produced by the parse_acorn_zip.pl utility bundled with PiEconetBridge.
Format 3: Extended attributes (xattr)
oaknut-zip extract --meta-format xattr NetUtils.zip
Writes metadata directly into the filesystem's extended attributes, with no sidecar files:
$ xattr -l SetStation
user.econet_exec: FFFFDD00
user.econet_load: FFFFDD00
user.econet_owner: 0000
user.econet_perm: 1761575D
$ xattr -l ReadMe
user.econet_exec: 2FEEAFD0
user.econet_load: FFFFFF52
user.econet_owner: 0000
user.econet_perm: BEB2A55
The attribute names and value formats match PiEconetBridge's C implementation exactly:
| Attribute | Format (sprintf) | Example |
|---|---|---|
user.econet_owner |
%04X |
0000 |
user.econet_load |
%08X |
FFFFDD00 |
user.econet_exec |
%08X |
FFFFDD00 |
user.econet_perm |
%02X |
03 |
This is the preferred format for PiEconetBridge when the host filesystem
supports extended attributes. PiEconetBridge reads xattrs in preference
to .inf files when both are present.
Format 4: RISC OS filename encoding
oaknut-zip extract --meta-format filename-riscos NetUtils.zip
Encodes metadata directly into the output filenames using comma-separated hex
suffixes. No sidecar files are created. Filetype-stamped files get a ,xxx
suffix (e.g. FILE,fdd); files with literal load/exec addresses get
,llllllll,eeeeeeee (e.g. PROG,00001900,0000801f).
This is the most portable format --- it requires no filesystem-specific support and survives transfers between any systems. Files already carrying the correct suffix are not double-encoded.
Format 5: MOS filename encoding
oaknut-zip extract --meta-format filename-mos NetUtils.zip
Encodes metadata into output filenames using the ,load-exec convention
documented in the BeebWiki INF file format
specification. This format uses a comma prefix with load and exec addresses
separated by a dash, with variable-width hex digits (no zero-padding):
,1900-801f.
This is the convention used by MOS and SparkFS when encoding addresses in filenames. Unlike the RISC OS form (Format 4), it always encodes full load/exec addresses and does not special-case filetype-stamped files.
Format 6: No metadata
oaknut-zip extract --meta-format none NetUtils.zip
Extracts files only, discarding all Acorn metadata. Equivalent to a standard
unzip.
Metadata sources in ZIP files
oaknut-zip reads Acorn metadata from three sources within ZIP archives. When multiple sources are present for a given entry, they are used in priority order: SparkFS extra fields, then bundled INF sidecar files, then filename encoding.
SparkFS extra fields (ARC0)
ZIP archives created by SparkFS,
SparkPlug, or RISC OS zip tools embed Acorn metadata as a ZIP extra field with
header ID 0x4341 ("AC") and an "ARC0" signature.
The extra field layout (all values little-endian), as defined in the Info-ZIP extra field specification by David Pilling:
| Offset | Size | Description |
|---|---|---|
| 0 | 4 bytes | Signature "ARC0" |
| 4 | 4 bytes | Load address (uint32) |
| 8 | 4 bytes | Execution address (uint32) |
| 12 | 4 bytes | File attributes (uint32) |
| 16 | 4 bytes | Reserved (zero) |
This is the most reliable metadata source, as it is embedded in the ZIP structure itself and survives transfers between any systems.
Bundled INF sidecar files
Some ZIP archives include .inf sidecar files alongside the data files they
describe. oaknut-zip detects and parses these automatically, supporting both
flavours:
- Traditional INF (
filename load exec length [access]) --- reported as sourceinf-tradin the list and info commands. - PiEconetBridge INF (
owner load exec perm) --- reported as sourceinf-pieb.
When extracting, bundled .inf files are consumed as a metadata source rather
than extracted as separate files. The metadata is then written in whatever
output format was requested (inf-trad, inf-pieb, xattr, etc.). This allows,
for example, converting a PiEconetBridge archive to xattr format in a single
step.
With --meta-format none, bundled .inf files are extracted as-is (no
metadata is consumed).
Unix filename encoding
Because Unix filesystems have no way to store Acorn load/exec addresses natively, a convention exists for encoding the RISC OS filetype into the filename itself as a comma-separated hex suffix:
| Pattern | Example | Meaning |
|---|---|---|
filename,xxx |
HELLO,ffb |
RISC OS filetype FFB |
oaknut-zip also supports two additional forms that encode full load and exec addresses for files that are not filetype-stamped:
| Pattern | Example | Meaning |
|---|---|---|
filename,llllllll,eeeeeeee |
PROG,ffff0e10,0000801f |
Load and exec addresses |
filename,load-exec |
PROG,1900-801f |
Load and exec (MOS/SparkFS) |
The first form is used by python-zipinfo-riscos and requires exactly 8 hex digits per address. The second form, documented in the BeebWiki INF file format specification, uses variable-width hex digits separated by a dash and is the convention used by MOS and SparkFS.
oaknut-zip strips these suffixes from output filenames during extraction.
Use --no-decode-filenames to preserve the encoded filenames as-is.
RISC OS filetype encoding
When the top 12 bits of a load address are 0xFFF, the address does not
represent a literal memory location. Instead, bits 8--19 encode a
RISC OS filetype:
Load address: FFFtttxx
^^^
filetype (3 hex digits)
Example RISC OS filetypes:
| Type | Name | Description |
|---|---|---|
FF9 |
Sprite | Sprite or saved screen |
FFA |
Module | Relocatable module |
FFB |
BASIC | Tokenised BASIC program |
FFC |
Utility | Position independent code |
FFD |
Data | Arbitrary data |
FFE |
Command | Command (Exec) file |
FFF |
Text | Plain ASCII text with LF newlines |
Acorn file attribute bits
The attribute byte encodes access permissions in the Acorn filing system convention:
| Bit | Mask | Meaning |
|---|---|---|
| 0 | 0x01 |
Owner writable |
| 1 | 0x02 |
Owner readable |
| 3 | 0x08 |
Locked (DFS L) |
| 4 | 0x10 |
Public writable |
| 5 | 0x20 |
Public readable |
A file with attributes 0x03 is owner-readable and owner-writable (WR).
A value of 0x17 adds public read access (WR/R), which is the default
for files served by PiEconetBridge.
Development
After cloning, install the pre-commit hooks:
uv run --group dev pre-commit install
Running the tests
uv run --group test pytest tests/ -v
The test suite covers all parsing, formatting, and extraction logic, including integration tests against six real-world ZIP fixtures:
- NetUtils.zip --- Econet utilities from MDFS, with SparkFS/ARC0 extra fields. This is the archive that motivated the project.
- NetUtilB.zip --- A second Econet utilities pack, also with SparkFS metadata.
- MASTER.zip --- BBC Master utilities from MDFS, 344 files with SparkFS metadata and 36 distinct filetypes.
- sweh_econet_system.zip --- PiEconetBridge system files from
sweh, containing bundled
PiEconetBridge-format
.infsidecar files (no SparkFS extra fields). - testdir-unix.zip --- Test archive from
python-zipinfo-riscos,
with Unix filename encoding (
,xxxsuffixes). - testdir-ro.zip --- The same content as testdir-unix.zip but with SparkFS extra fields instead of filename encoding.
References
Metadata format specifications
- INF file format ---
BeebWiki specification for the Acorn
.infsidecar format. - ZIP extra field registry ---
Known ZIP extra field types, including the Acorn/SparkFS entry (
0x4341). - RISC OS filetype --- How RISC OS encodes filetypes in load addresses.
- ZipToInf documentation --- J.G.Harston's ZipToInf utility and INF format description.
- RISC OS filename translation ---
Documents the
,xxxfiletype suffix convention used on Unix filesystems. - INF file format --- J.G.Harston's detailed INF file format specification.
Tools and related projects
- PiEconetBridge ---
Econet bridge for Raspberry Pi; defines the
user.econet_*xattr convention and the alternative.infformat (owner load exec perm). - python-zipinfo-riscos ---
Python library for reading/writing RISC OS extra fields in ZIP archives;
source of the
,llllllll,eeeeeeeeload/exec filename encoding convention. - ZipTools --- J.G.Harston's suite of Acorn-aware ZIP utilities including ZipToInf.
- SparkFS --- David Pilling's RISC OS filing system for ZIP/Arc/Spark archives; originator of the ARC0 extra field format.
Forum discussion
- Stardot forum thread --- Discussion of the metadata-loss problem that motivated this tool.
- INF format discussion --- Community discussion on INF format variants and standardisation.
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 Distributions
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 oaknut_zip-0.2.4-py3-none-any.whl.
File metadata
- Download URL: oaknut_zip-0.2.4-py3-none-any.whl
- Upload date:
- Size: 20.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fde2bee9c27a24f7313064736877ed9d862dc06dc464864f2acb795a600723ee
|
|
| MD5 |
cace3e67efe6b1dcc59379bc8aa26878
|
|
| BLAKE2b-256 |
2664153363351767046c7a7f2fccd366ad77d50e5d6701d3833aa2678b1899aa
|