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 lengthspwms: Turbo transmission settingspwmc: Turbo synchronization signalspwmd: Turbo data blockpwml: Raw PWM state sequence
API Reference
CASReader Class
Methods
read(): Parse the CAS file and load all chunksto_byte_array() -> bytearray: Extract all data chunks into a single byte arrayto_bin_file(output_path: str) -> int: Write data chunks to binary file, returns bytes writtenget_all_chunks_as_bytes() -> bytearray: Convert entire CAS file (including headers) to byte arrayget_metadata() -> dict: Extract metadata (description, baudrate, chunk counts)get_data_blocks() -> List[bytes]: Get list of all data chunk contentsget_chunk_info() -> List[dict]: Get information about all chunksdump_chunks(chunk_indices=None, show_hex=True, show_ascii=False) -> str: Format chunk contents for display
Properties
filepath: Path to the CAS filechunks: List of parsed Chunk objectsdata_blocks: List of data chunk contents
Chunk Class
Dataclass representing a CAS chunk:
header: ChunkHeader: Chunk header informationdata: bytes: Chunk data payload
ChunkHeader Class
Dataclass representing chunk header:
chunk_type: bytes: 4-byte chunk type identifierlength: int: Length of chunk dataaux_data: int: Auxiliary/metadata value
Utility Functions
read_cas_file(filepath: str) -> Tuple[bytearray, dict]: Convenience function returning data and metadataparse_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)
| File | Size | Uploaded | |
|---|---|---|---|
| atari_cas_reader-0.1.3.tar.gz | 11.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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
|