xfh
Recover files compressed with historical Amiga XPK tools.
xfh.cli
Command-line interface.
main
def main(argv: list[str] | None = None) -> int
Run the CLI and return its process status.
xfh.limits
Resource limits applied before allocating decompressed output.
Limits Objects
@dataclass(frozen=True, slots=True)
class Limits()
Limits used to bound work on untrusted compressed input.
xfh.__main__
Module entry point for python -m xfh.
xfh.models
Immutable metadata returned by the public API.
FileFormat Objects
class FileFormat(str, Enum)
Known XPK stream container variants.
ChunkInfo Objects
@dataclass(frozen=True, slots=True)
class ChunkInfo()
Metadata for one encoded stream chunk.
FileInfo Objects
@dataclass(frozen=True, slots=True)
class FileInfo()
Parsed stream metadata.
RecoveryIssue Objects
@dataclass(frozen=True, slots=True)
class RecoveryIssue()
One reason why salvage output is incomplete.
RecoveryResult Objects
@dataclass(frozen=True, slots=True)
class RecoveryResult()
Partial or complete output from explicit salvage mode.
xfh.codecs.ilzr
XPK ILZR decompression.
Derived from Ancient’s ILZRDecompressor, Copyright (c) 2017-2025 Teemu Suutari, under the BSD 2-Clause License.
decompress_ilzr
@register("ILZR")
def decompress_ilzr(payload: bytes,
output_size: int,
previous: bytes = b"") -> bytes
Decode incremental Lempel-Ziv-Renau data.
xfh.codecs.fast
XPK FAST decompression.
decompress_fast
@register("FAST")
def decompress_fast(payload: bytes,
output_size: int,
previous: bytes = b"") -> bytes
Decode one FAST chunk.
xfh.codecs.lzw_variants
CyberYAFA XPK LZW2, LZW3, LZW4, and LZW5 decompression.
Despite their names, these formats are control-bit LZ variants rather than dictionary-based LZW streams.
Derived from Ancient’s LZW2Decompressor, LZW4Decompressor, and LZW5Decompressor, Copyright (c) 2017-2025 Teemu Suutari, under the BSD 2-Clause License.
decompress_lzw2
@register("LZW2")
def decompress_lzw2(payload: bytes,
output_size: int,
previous: bytes = b"") -> bytes
Decode an LZW2 stream.
decompress_lzw3
@register("LZW3")
def decompress_lzw3(payload: bytes,
output_size: int,
previous: bytes = b"") -> bytes
Decode an LZW3 stream, whose packed representation matches LZW2.
decompress_lzw4
@register("LZW4")
def decompress_lzw4(payload: bytes,
output_size: int,
previous: bytes = b"") -> bytes
Decode an LZW4 stream.
decompress_lzw5
@register("LZW5")
def decompress_lzw5(payload: bytes,
output_size: int,
previous: bytes = b"") -> bytes
Decode an LZW5 stream.
xfh.codecs.rdcn
XPK RDCN decompression.
Derived from Ancient’s RDCNDecompressor, Copyright (c) 2017-2025 Teemu Suutari, under the BSD 2-Clause License.
decompress_rdcn
@register("RDCN")
def decompress_rdcn(payload: bytes,
output_size: int,
previous: bytes = b"") -> bytes
Decode Ross Data Compression chunks.
xfh.codecs.standard
XPK wrappers around standardized compression streams.
decompress_bzp2
@register("BZP2")
def decompress_bzp2(payload: bytes,
output_size: int,
previous: bytes = b"") -> bytes
Decode an XPK-wrapped bzip2 stream.
decompress_gzip
@register("GZIP")
def decompress_gzip(payload: bytes,
output_size: int,
previous: bytes = b"") -> bytes
Decode GZIP’s zlib-format payload.
xfh.codecs.zeno
XPK ZENO decompression.
Derived from Ancient’s ZENODecompressor, Copyright (c) 2017-2025 Teemu Suutari, under the BSD 2-Clause License.
decompress_zeno
@register("ZENO")
def decompress_zeno(payload: bytes,
output_size: int,
previous: bytes = b"") -> bytes
Decode ZENO’s variable-width dictionary stream.
xfh.codecs.impl
XPK File Imploder decompression.
decompress_impl
@register("IMPL")
def decompress_impl(payload: bytes,
output_size: int,
previous: bytes = b"") -> bytes
Decode an XPK-wrapped File Imploder stream.
xfh.codecs.sqsh
XPK SQSH decompression.
decompress_sqsh
@register("SQSH")
def decompress_sqsh(payload: bytes,
output_size: int,
previous: bytes = b"") -> bytes
Decode an SQSH sample-prediction and LZ stream.
xfh.codecs.pwpk
XPK PowerPacker (PWPK) decompression.
decompress_pwpk
@register("PWPK")
def decompress_pwpk(payload: bytes,
output_size: int,
previous: bytes = b"") -> bytes
Decode a PowerPacker chunk.
xfh.codecs.smpl
XPK SMPL decompression.
decompress_smpl
@register("SMPL")
def decompress_smpl(payload: bytes,
output_size: int,
previous: bytes = b"") -> bytes
Decode a static Huffman stream followed by byte delta prediction.
xfh.codecs._prefix
Small prefix-code helpers shared by XPK codecs.
PrefixDecoder Objects
class PrefixDecoder()
Decode explicit most-significant-bit-first prefix codes.
decode
def decode(bits: object) -> int
Decode one value from an object exposing read(count).
variable_length
def variable_length(bits: object, specifications: tuple[int, ...],
index: int) -> int
Decode an indexed variable-length integer with cumulative bases.
xfh.codecs._streams
Bounded byte and bit streams used by historical XPK codecs.
The stream behavior is derived from Ancient, Copyright (c) 2017-2025 Teemu Suutari, under the BSD 2-Clause License.
CoupledInput Objects
class CoupledInput()
Forward word reads and backward byte reads sharing one payload.
ByteInput Objects
class ByteInput()
A bounded forward byte stream.
BitReader Objects
class BitReader()
Read most- or least-significant bits from fixed-width words.
copy_forward
def copy_forward(output: bytearray, distance: int, count: int,
output_size: int) -> None
Copy an overlapping LZ match within a bounded output buffer.
xfh.codecs.crm
Crunch-Mania XPK codecs.
xfh.codecs.dlta
XPK DLTA decompression.
decompress_dlta
@register("DLTA")
def decompress_dlta(payload: bytes,
output_size: int,
previous: bytes = b"") -> bytes
Decode DLTA’s byte-delta transform.
xfh.codecs.mash
XPK MASH decompression.
decompress_mash
@register("MASH")
def decompress_mash(payload: bytes,
output_size: int,
previous: bytes = b"") -> bytes
Decode a MASH mixed literal and LZ stream.
xfh.codecs.wrappers
Nested and transform XPK codecs.
Derived from Ancient’s CYB2Decoder and SDHCDecompressor, Copyright (c) 2017-2025 Teemu Suutari, under the BSD 2-Clause License.
decompress_cyb2
@register("CYB2")
def decompress_cyb2(payload: bytes,
output_size: int,
previous: bytes = b"") -> bytes
Decode a CYB2 wrapper around another XPK codec payload.
decompress_sdhc
@register("SDHC")
def decompress_sdhc(payload: bytes,
output_size: int,
previous: bytes = b"") -> bytes
Decode SDHC’s optional nested stream and sample delta transform.
xfh.codecs.nuke
XPK NUKE decompression.
Derived from Ancient’s NUKEDecompressor, Copyright (c) 2017-2025 Teemu Suutari, under the BSD 2-Clause License.
decompress_nuke
@register("NUKE")
def decompress_nuke(payload: bytes,
output_size: int,
previous: bytes = b"") -> bytes
Decode one NUKE chunk.
decompress_duke
@register("DUKE")
def decompress_duke(payload: bytes,
output_size: int,
previous: bytes = b"") -> bytes
Decode NUKE data followed by DUKE’s byte-delta transform.
xfh.codecs.shri
XPK SHRI decompression.
Derived from Ancient’s SHRXDecompressor, Copyright (c) 2017-2025 Teemu Suutari, under the BSD 2-Clause License.
ShriState Objects
@dataclass(slots=True)
class ShriState()
Adaptive model carried by SHRI version 2 continuation chunks.
decompress_shri_chunk
def decompress_shri_chunk(payload: bytes,
output_size: int,
previous: bytes,
state: ShriState | None,
*,
shr3: bool = False) -> tuple[bytes, ShriState]
Decode one SHRI chunk and return its continuation model.
decompress_shri
@register("SHRI")
def decompress_shri(payload: bytes,
output_size: int,
previous: bytes = b"") -> bytes
Decode one independently initialized SHRI chunk.
decompress_shr3
@register("SHR3")
def decompress_shr3(payload: bytes,
output_size: int,
previous: bytes = b"") -> bytes
Decode one independently initialized SHR3 chunk.
xfh.codecs.rle
XPK byte-run codecs.
Derived from Ancient’s CBR0, FRLE, and RLEN decompressors, Copyright (c) 2017-2025 Teemu Suutari, under the BSD 2-Clause License.
decompress_cbr0
@register("CBR1")
@register("CBR0")
def decompress_cbr0(payload: bytes,
output_size: int,
previous: bytes = b"") -> bytes
Decode Commodore ByteRun-style CBR0/CBR1 data.
decompress_rlen
@register("RLEN")
def decompress_rlen(payload: bytes,
output_size: int,
previous: bytes = b"") -> bytes
Decode XPK RLEN data.
decompress_frle
@register("FRLE")
def decompress_frle(payload: bytes,
output_size: int,
previous: bytes = b"") -> bytes
Decode cache-oriented XPK FRLE data.
xfh.codecs.artm
XPK ARTM arithmetic decompression.
Derived from Ancient’s ARTMDecompressor and RangeDecoder, Copyright (c) 2017-2025 Teemu Suutari, under the BSD 2-Clause License.
decompress_artm
@register("ARTM")
def decompress_artm(payload: bytes,
output_size: int,
previous: bytes = b"") -> bytes
Decode ARTM’s adaptive arithmetic stream.
xfh.codecs.rake
XPK RAKE decompression.
Derived from Ancient’s RAKEDecompressor, Copyright (c) 2017-2025 Teemu Suutari, under the BSD 2-Clause License.
decompress_rake
@register("FRHT")
@register("RAKE")
def decompress_rake(payload: bytes,
output_size: int,
previous: bytes = b"") -> bytes
Decode one RAKE/FRHT chunk.
xfh.codecs.fbr2
XPK FBR2 decompression.
Derived from Ancient’s FBR2Decompressor, Copyright (c) 2017-2025 Teemu Suutari, under the BSD 2-Clause License.
decompress_fbr2
@register("FBR2")
def decompress_fbr2(payload: bytes,
output_size: int,
previous: bytes = b"") -> bytes
Decode CyberYAFA FBR2 byte runs.
xfh.codecs.none
The XPK NONE storage codec.
decompress_none
@register("NONE")
def decompress_none(payload: bytes,
output_size: int,
previous: bytes = b"") -> bytes
Return a raw NONE chunk after validating its declared size.
xfh.codecs.lz_small
Small historical XPK LZ codecs.
Derived from Ancient’s LZBSDecompressor, SLZ3Decompressor, and TDCSDecompressor, Copyright (c) 2017-2025 Teemu Suutari, under the BSD 2-Clause License.
decompress_lzbs
@register("LZBS")
def decompress_lzbs(payload: bytes,
output_size: int,
previous: bytes = b"") -> bytes
Decode the CyberYAFA LZBS format.
decompress_slz3
@register("SLZ3")
def decompress_slz3(payload: bytes,
output_size: int,
previous: bytes = b"") -> bytes
Decode the CyberYAFA SLZ3 format.
decompress_tdcs
@register("TDCS")
def decompress_tdcs(payload: bytes,
output_size: int,
previous: bytes = b"") -> bytes
Decode TDCS LZ77 data.
xfh.codecs.lhlb
XPK LHLB decompression.
Derived from Ancient’s LHDecompressor and DynamicHuffmanDecoder, Copyright (c) 2017-2025 Teemu Suutari, under the BSD 2-Clause License.
decompress_lhlb
@register("LHLB")
def decompress_lhlb(payload: bytes,
output_size: int,
previous: bytes = b"") -> bytes
Decode the lh.library-compatible LHLB format.
xfh.codecs.acca
XPK ACCA decompression.
Derived from Ancient’s ACCADecompressor, Copyright (c) 2017-2025 Teemu Suutari, under the BSD 2-Clause License.
decompress_acca
@register("ACCA")
def decompress_acca(payload: bytes,
output_size: int,
previous: bytes = b"") -> bytes
Decode Andre’s code compression algorithm.
xfh.codecs.hfmn
XPK HFMN decompression.
decompress_hfmn
@register("HFMN")
def decompress_hfmn(payload: bytes,
output_size: int,
previous: bytes = b"") -> bytes
Decode an HFMN dynamic Huffman stream.
xfh.codecs.blzw
XPK BLZW decompression.
Derived from Ancient’s BLZWDecompressor and LZWDecoder, Copyright (c) 2017-2025 Teemu Suutari, under the BSD 2-Clause License.
decompress_blzw
@register("BLZW")
def decompress_blzw(payload: bytes,
output_size: int,
previous: bytes = b"") -> bytes
Decode Bryan Ford’s XPK BLZW format.
xfh.codecs.huff
XPK HUFF decompression.
decompress_huff
@register("HUFF")
def decompress_huff(payload: bytes,
output_size: int,
previous: bytes = b"") -> bytes
Decode one HUFF chunk.
xfh.codecs
XPK codec registry.
register
def register(codec: str) -> Callable[[Decoder], Decoder]
Register a decoder by its four-character XPK identifier.
decode
def decode(codec: str,
payload: bytes,
output_size: int,
previous: bytes = b"") -> bytes
Decode one packed XPK chunk.
supported_codecs
def supported_codecs() -> frozenset[str]
Return codec identifiers implemented by this build.
xfh.errors
Public exception hierarchy.
XfhError Objects
class XfhError(Exception)
Base class for expected recovery failures.
InvalidFormatError Objects
class InvalidFormatError(XfhError)
The input is not a recognized XPK stream.
CorruptDataError Objects
class CorruptDataError(XfhError)
The stream is recognized but fails structural or checksum validation.
UnsupportedCodecError Objects
class UnsupportedCodecError(XfhError)
The stream uses a codec or mode which is not implemented.
PasswordRequiredError Objects
class PasswordRequiredError(XfhError)
The input is encrypted and needs a password.
ResourceLimitError Objects
class ResourceLimitError(XfhError)
The stream exceeds a configured recovery safety limit.
xfh.api
Public recovery API.
detect
def detect(data: bytes | bytearray | memoryview) -> FileFormat
Detect an XPK container variant.
inspect
def inspect(data: bytes | bytearray | memoryview,
*,
limits: Limits = DEFAULT_LIMITS) -> FileInfo
Parse and validate stream metadata without decompressing it.
decompress
def decompress(data: bytes | bytearray | memoryview,
*,
password: str | bytes | None = None,
limits: Limits = DEFAULT_LIMITS) -> bytes
Strictly decompress one complete stream.
salvage
def salvage(data: bytes | bytearray | memoryview,
*,
limits: Limits = DEFAULT_LIMITS) -> RecoveryResult
Recover verified chunks until the first decoding failure.
decompress_file
def decompress_file(source: str | os.PathLike[str],
destination: str | os.PathLike[str],
*,
overwrite: bool = False,
password: str | bytes | None = None,
limits: Limits = DEFAULT_LIMITS) -> FileInfo
Decompress to an atomic destination path.
xfh.container
Strict parsers for historical XPK stream containers.
ParsedChunk Objects
@dataclass(frozen=True, slots=True)
class ParsedChunk()
Internal chunk metadata and its encoded bytes.
ParsedFile Objects
@dataclass(frozen=True, slots=True)
class ParsedFile()
Internal parsed stream.
detect_format
def detect_format(data: bytes) -> FileFormat
Detect a supported container without parsing it.
parse
def parse(data: bytes, limits: Limits) -> ParsedFile
Parse and validate one complete stream.