Skip to main content

diskii - Apple II Disk Image Tool & Library

Project description

diskii - Apple II Disk Image Tool & Library

builds.sr.ht status

diskii is both a command-line utility and Python library for reading, writing, and manipulating Apple II disk images. It supports both DOS 3.3 and ProDOS filesystems across various image formats.

Features

Disk Image Reading

  • Complete DOS 3.3 support: Read catalogs, extract files, handle all file types (T/I/A/B/S/R)
  • Full ProDOS support: Volume directories, subdirectories, all storage types (seedling/sapling/tree)
  • DOS 3.2 support: Read 13-sector disk images (.d13 format)
  • Multiple image formats: .dsk, .do, .po, .hdv, .d13
  • Automatic format detection: Smart detection based on file extension and content analysis

File Operations

  • File extraction: Read any file from disk images to host filesystem
  • File writing: Create new files on disk images with proper metadata
  • File type preservation: Maintain Apple II file types and auxiliary information
  • Cross-format operations: Copy files between DOS 3.3 and ProDOS images

Disk Image Creation

  • Blank disk creation: Create empty DOS 3.3, DOS 3.2, and ProDOS images
  • Multiple sizes supported: Standard 140K disks up to 32MB ProDOS volumes
  • Proper filesystem initialization: Correct VTOC, catalogs, and volume bitmaps

Advanced Features

  • Batch operations: Process multiple disk images in one command
  • Hierarchical directory support: Full ProDOS subdirectory navigation
  • Sparse file handling: Efficient handling of ProDOS sparse files
  • Free space tracking: Volume bitmap and VTOC management
  • BASIC (de)tokenization: Convert between tokenized and text BASIC programs with 100% Apple II ROM compliance
  • BASIC syntax validation: ROM-compliant syntax checking for Apple II BASIC programs
  • ProDOS corruption protection: Graceful handling of malformed directory entries
  • DOS file size accuracy: Respects Apple II directory size fields vs sector padding
  • Robust error handling: Comprehensive error detection and graceful degradation
  • Type-safe: Full type annotations throughout
  • Comprehensive testing: 1100+ tests with 100% pass rate, fuzzing coverage, and compatibility validation

Installation

pip install diskii

Or with Poetry:

poetry add diskii

Command Line Usage

diskii provides a comprehensive command-line interface for disk image manipulation:

# Show disk information
diskii info mydisk.dsk
diskii info *.dsk --summary              # Show summary for multiple disks

# Extract files from disk images  
diskii extract mydisk.po                 # Extract all files from one disk
diskii extract *.dsk --output extracted/ # Extract from multiple disks
diskii extract mydisk.dsk --files HELLO.BAS  # Extract specific files

# Add files to a disk
diskii add mydisk.po myfile.txt *.bas    # Add multiple files

# Create blank disk images
diskii create blank.po --name MYDISK

# Reorder sectors between different orderings
diskii reorder mydisk.dsk output.po

# BASIC program utilities
diskii basic detokenize HELLO.BAS
diskii basic tokenize myprogram.txt --variant applesoft
diskii basic validate myprogram.txt

For detailed help on any command:

diskii --help
diskii <command> --help

Python Library Usage

import diskii

# Open any disk image - format detected automatically
with diskii.open_disk_image("mydisk.dsk") as image:
    # Get volume information
    print(f"Volume: {image.get_volume_name()}")
    print(f"Format: {image.format}")
    
    # List all files
    files = image.get_file_list()
    for file_entry in files:
        print(f"{file_entry.filename} ({file_entry.size} bytes)")
        
        # Extract file
        data = file_entry.read_data()
        with open(file_entry.filename, 'wb') as f:
            f.write(data)

# Create a new blank disk
diskii.disk_creator.create_blank_prodos_image("new_disk.po", "MY.DISK")

# Add files to existing disk (requires read_only=False)
with diskii.open_disk_image("mydisk.po", read_only=False) as image:
    image.create_file("HELLO.TXT", 0x04, b"Hello from diskii!")

# BASIC program tokenization
import diskii

# Tokenize Applesoft BASIC program
program_text = '''10 HOME
20 PRINT "HELLO WORLD!"
30 END'''

tokenized = diskii.tokenize_applesoft(program_text)
detokenized = diskii.detokenize_applesoft(tokenized)

# Work with BASIC files on disk images
with diskii.open_disk_image("mydisk.po", read_only=False) as image:
    # Save as tokenized BASIC program
    image.create_file("HELLO.BAS", 0xFC, tokenized)
    
    # Read BASIC file and detokenize automatically
    files = image.get_file_list()
    for file_entry in files:
        if file_entry.is_basic_file():
            plain_text = file_entry.read_as_text()  # Auto-detokenizes
            raw_tokens = file_entry.read_as_tokens()  # Raw tokenized data

# BASIC syntax validation with ROM compliance
program_text = '''10 HOME
20 FOR I = 1 TO 10
30 PRINT "COUNT: "; I
40 NEXT I
50 END'''

# Validate Applesoft BASIC syntax
errors = diskii.validate_basic_syntax(program_text, "applesoft")
if not errors:
    print("✅ Program syntax is valid!")
else:
    for error in errors:
        print(f"Line {error.line}: {error.message}")

# Advanced syntax validation with custom validator
validator = diskii.BASICSyntaxValidator("applesoft")
errors = validator.validate_program(program_text)

# Validate Integer BASIC programs
integer_program = '''10 HOME
20 FOR I = 1 TO 10
30 PRINT "COUNT: "; I
40 NEXT I
50 END'''

# Also test Integer BASIC tokenization functions
tokenized_integer = diskii.tokenize_integer_basic(integer_program)
detokenized_integer = diskii.detokenize_integer_basic(tokenized_integer)

errors = diskii.validate_basic_syntax(integer_program, "integer")

Supported Formats

Extension Description Sector Ordering Supported Filesystems
.dsk DOS order disk images (140KB) DOS order DOS 3.3, ProDOS
.do DOS order disk images DOS order DOS 3.3, ProDOS
.po ProDOS order disk images ProDOS order DOS 3.3, ProDOS
.hdv ProDOS hard disk volumes (up to 32MB) ProDOS order ProDOS
.d13 DOS 3.2 13-sector images DOS 3.2 order DOS 3.2

Error Handling

diskii provides comprehensive error handling:

try:
    with diskii.open_disk_image("questionable.dsk") as image:
        files = image.get_file_list()
except diskii.UnrecognizedFormatError:
    print("Not a valid disk image")
except diskii.CorruptedImageError:
    print("Image appears to be corrupted")
except diskii.AccessError:
    print("Cannot access the image file")

Examples

The examples/ directory contains practical usage examples:

  • directory_tree.py: Display disk contents in tree format
  • file_info.py: Show detailed file metadata and type information
  • create_files.py: Demonstrate creating files on disk images
  • cross_format_copy.py: Copy files between ProDOS and DOS formats
  • basic_tokenization.py: BASIC program tokenization and detokenization examples

Requirements

  • Python 3.11+ (no upper version limit)
  • No external dependencies for core functionality

Development

# Install with development dependencies
poetry install --with dev,docs

# Run tests
poetry run pytest

# Run with coverage
poetry run pytest --cov=src/diskii

# Run CiderPress 2 compatibility tests
poetry run pytest -m integration

# Run fuzzing tests (requires dev dependencies)
python tests/fuzz/run_fuzz_tests.py

# Format code
poetry run ruff format src/ tests/

# Type checking  
poetry run mypy src/

# Build documentation
cd docs && make html

Planned Features

  • GUI application: Desktop interface for disk browsing and editing

Not Planned (Pull Requests Welcome)

  • WOZ image format support
  • 2MG image format support
  • NIB image format support
  • Pascal or CP/M filesystem support (test infrastructure added, implementation welcome)

References

License

ISC License - see LICENSE file for details.

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for guidelines.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

diskii-0.3.5.tar.gz (119.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

diskii-0.3.5-py3-none-any.whl (147.9 kB view details)

Uploaded Python 3

File details

Details for the file diskii-0.3.5.tar.gz.

File metadata

  • Download URL: diskii-0.3.5.tar.gz
  • Upload date:
  • Size: 119.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.2.1 CPython/3.12.12 Linux/6.18.15-0-lts

File hashes

Hashes for diskii-0.3.5.tar.gz
Algorithm Hash digest
SHA256 326d85cf8c1905dea0428642296b16eb26fe93fc03b36a3c74c8ce229efa26a9
MD5 b8f0bf7da45b651951f42354d8775069
BLAKE2b-256 f3836bfaa316fe76b8a06ae4643e82c6f54a2dee941ec307cc561e294e75aada

See more details on using hashes here.

File details

Details for the file diskii-0.3.5-py3-none-any.whl.

File metadata

  • Download URL: diskii-0.3.5-py3-none-any.whl
  • Upload date:
  • Size: 147.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.2.1 CPython/3.12.12 Linux/6.18.15-0-lts

File hashes

Hashes for diskii-0.3.5-py3-none-any.whl
Algorithm Hash digest
SHA256 a68d8d9610002e8ea4b929bbcfcad07518d6620eb4201b4aa97e80373a10243c
MD5 7dd7495dddb80c0eba09249841699cc7
BLAKE2b-256 f9df0577309ae1d0e85da1aaff6098bb3521822fda63da02f2a46d54a12f63cd

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page