Skip to main content

PyCAS - Python CAS File Reader

A pure Python library for reading and converting Atari 8-bit cassette (CAS) files. This library provides comprehensive support for the CAS file format as defined in the A8CAS specification.

Features

  • Pure Python: Compatible with Python 3.x, no external dependencies
  • Complete CAS format support: Handles all chunk types (FUJI, baud, data, fsk, pwms, pwmc, pwmd, pwml)
  • Binary conversion: Extract data chunks to binary (.bin) files
  • Flexible dumping: View chunk contents in hex, ASCII, or both formats
  • Chunk selection: Dump specific chunks or ranges
  • Metadata extraction: Read tape descriptions and baudrate information
  • CLI tool: Command-line interface for file inspection and conversion

Installation

From PyPI

pip install atari-cas-reader

From source

git clone https://github.com/yourusername/pycas.git
cd pycas
pip install -e .

Quick Start

As a Library

from pycas import CASReader, read_cas_file

# Simple usage - get data and metadata
byte_array, metadata = read_cas_file('tape.cas')
print(f"Description: {metadata['description']}")
print(f"Baudrate: {metadata['baudrate']}")
print(f"Data size: {len(byte_array)} bytes")

# Advanced usage with CASReader class
reader = CASReader('tape.cas')
reader.read()

# Get metadata
metadata = reader.get_metadata()
print(f"Chunks: {metadata['chunk_count']}")

# Get chunk information
for chunk_info in reader.get_chunk_info():
    print(f"[{chunk_info['index']}] {chunk_info['type']}: {chunk_info['length']} bytes")

# Extract data to byte array
data = reader.to_byte_array()

# Convert to binary file
reader.to_bin_file('output.bin')

# Get individual data blocks
for i, block in enumerate(reader.get_data_blocks()):
    print(f"Block {i}: {len(block)} bytes")

# Dump chunks in hex format
print(reader.dump_chunks(chunk_indices=[0, 1], show_hex=True, show_ascii=True))

Command-Line Interface

Show file information (default)

python -m pycas tape.cas

Output:

CAS File: tape.cas

Metadata:
  description: My Atari Program
  baudrate: 600
  chunk_count: 5
  data_block_count: 3

Chunks:
  [0] FUJI: 16 bytes (aux: 0)
  [1] baud: 2 bytes (aux: 0)
  [2] data: 132 bytes (aux: 0)
  [3] data: 132 bytes (aux: 0)
  [4] data: 64 bytes (aux: 0)

Total data bytes: 328

Convert to binary file

python -m pycas tape.cas --to-bin output.bin

Dump chunks in hex format

# Dump all chunks (hex only, default)
python -m pycas tape.cas dump

# Dump all chunks with both hex and ASCII
python -m pycas tape.cas dump --hex --ascii

# Dump specific chunk
python -m pycas tape.cas dump --chunk 0 --hex --ascii

# Dump chunk range
python -m pycas tape.cas dump --chunk 2-4 --hex --ascii

# Dump multiple chunks and ranges
python -m pycas tape.cas dump --chunk 0,2,5-7 --hex --ascii

# Dump ASCII only
python -m pycas tape.cas dump --ascii

Example dump output:

Chunk [2] Type: data, Length: 132, Aux: 0
--------------------------------------------------------------------------------
0000: 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 | UUUUUUUUUUUUUUUU
0010: 7f 7f 7f 00 01 02 03 04 05 06 07 08 09 0a 0b 0c | ................
0020: 48 45 4c 4c 4f 20 57 4f 52 4c 44 21 9b 00 00 00 | HELLO WORLD!....

CAS File Format

The CAS format stores Atari 8-bit cassette data as a series of chunks. Each chunk has:

  • Header (8 bytes):
    • Chunk type (4 bytes, ASCII)
    • Length (2 bytes, little-endian)
    • Auxiliary data (2 bytes, little-endian)
  • Data (variable length)

Supported Chunk Types

  • FUJI: Tape description (UTF-8 text)
  • baud: Transmission baudrate (default: 600 baud)
  • data: Standard SIO record (typically 132 bytes)
  • fsk : Non-standard FSK signal lengths
  • pwms: Turbo transmission settings
  • pwmc: Turbo synchronization signals
  • pwmd: Turbo data block
  • pwml: Raw PWM state sequence

API Reference

CASReader Class

Methods

  • read(): Parse the CAS file and load all chunks
  • to_byte_array() -> bytearray: Extract all data chunks into a single byte array
  • to_bin_file(output_path: str) -> int: Write data chunks to binary file, returns bytes written
  • get_all_chunks_as_bytes() -> bytearray: Convert entire CAS file (including headers) to byte array
  • get_metadata() -> dict: Extract metadata (description, baudrate, chunk counts)
  • get_data_blocks() -> List[bytes]: Get list of all data chunk contents
  • get_chunk_info() -> List[dict]: Get information about all chunks
  • dump_chunks(chunk_indices=None, show_hex=True, show_ascii=False) -> str: Format chunk contents for display

Properties

  • filepath: Path to the CAS file
  • chunks: List of parsed Chunk objects
  • data_blocks: List of data chunk contents

Chunk Class

Dataclass representing a CAS chunk:

  • header: ChunkHeader: Chunk header information
  • data: bytes: Chunk data payload

ChunkHeader Class

Dataclass representing chunk header:

  • chunk_type: bytes: 4-byte chunk type identifier
  • length: int: Length of chunk data
  • aux_data: int: Auxiliary/metadata value

Utility Functions

  • read_cas_file(filepath: str) -> Tuple[bytearray, dict]: Convenience function returning data and metadata
  • parse_chunk_selection(chunk_spec: str, max_chunks: int) -> List[int]: Parse chunk selection string

Examples

Extract program data

from pycas import CASReader

reader = CASReader('program.cas')
reader.read()

# Save just the data chunks to binary
reader.to_bin_file('program.bin')
print(f"Extracted {len(reader.to_byte_array())} bytes")

Analyze tape structure

from pycas import CASReader

reader = CASReader('tape.cas')
reader.read()

print("Tape Analysis")
print("=" * 60)

metadata = reader.get_metadata()
print(f"Description: {metadata['description']}")
print(f"Baudrate: {metadata['baudrate']}")
print(f"\nChunk Structure:")

for info in reader.get_chunk_info():
    print(f"  [{info['index']:2d}] {info['type']:4s} - "
          f"{info['length']:4d} bytes (aux: {info['aux_data']})")

total_size = sum(chunk.header.length for chunk in reader.chunks)
print(f"\nTotal payload: {total_size} bytes")

Dump specific chunks

from pycas import CASReader, parse_chunk_selection

reader = CASReader('tape.cas')
reader.read()

# Parse user input like "0,2-5,7"
chunks = parse_chunk_selection("0,2-5,7", len(reader.chunks))

# Dump with hex and ASCII
output = reader.dump_chunks(chunks, show_hex=True, show_ascii=True)
print(output)

Development

Building from source

# Clone repository
git clone https://github.com/yourusername/pycas.git
cd pycas

# Install in development mode
pip install -e .

# Run tests (if available)
python -m pytest

Building for PyPI

# Install build tools
pip install build twine

# Build distribution
python -m build

# Upload to PyPI (requires credentials)
python -m twine upload dist/*

Requirements

  • Python >= 3.6
  • No external dependencies

License

MIT License - see LICENSE file for details

Contributing

Contributions are welcome! Please feel free to submit pull requests or open issues for bugs and feature requests.

References

Author

Claude.ai Sonnet 4.5 - Prompted by Aykut Kılıç

Changelog

0.1.0 (2025-01-XX)

  • Initial release
  • CAS file reading and parsing
  • Binary conversion support
  • Hex/ASCII dump functionality
  • Command-line interface
  • Complete chunk type support

Metadata

Release files for atari-cas-reader 0.1.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for atari-cas-reader 0.1.3
File Size Uploaded
atari_cas_reader-0.1.3.tar.gz 11.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for atari-cas-reader 0.1.3
File Interpreter ABI Platform
atari_cas_reader-0.1.3-py3-none-any.whl Python 3 none any Details

Total release size: 21.0 kB

Release files / atari_cas_reader-0.1.3.tar.gz

Download URL atari_cas_reader-0.1.3.tar.gz
Size 11.1 kB
Tags Source
SHA-256 checksum
How to use checksums
1b6dbdc48b4cfd47679f597e92ab2e7038883a6e69b62a1484d007cac089aafa
BLAKE2b-256 checksum
How to use checksums
400da314f4c14a96e0d74b456c0505ea035b2a2af978bdbe487f146d7b35ca7b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.4

Release files / atari_cas_reader-0.1.3-py3-none-any.whl

Download URL atari_cas_reader-0.1.3-py3-none-any.whl
Size 9.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6ee6e5a8653942503cba73b3d2fd86ebc62163f91e384de7cbaef40db5e8ee41
BLAKE2b-256 checksum
How to use checksums
6ebe53da610f11f24365101dec25af73aa5a0c7fa1b79f0eb56ff0898358ad38
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.4

Release history Release notifications | RSS feed

This release

0.1.3 This release

2 release files

0.1.2

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page