Skip to main content

diskii - Apple II Disk Image Tool & Library

Project description

diskii - Apple II Disk Image Tool & Library

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

  • 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
  • BASIC syntax validation: ROM-compliant syntax checking for Apple II BASIC programs
  • Robust error handling: Graceful handling of corrupted or invalid images
  • Type-safe: Full type annotations throughout
  • Comprehensive testing: Extensive test suite with real disk images

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

# Extract all files from a disk
diskii extract mydisk.po

# Extract specific files
diskii extract mydisk.dsk HELLO.BAS

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

# 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, ProDOS*

*ProDOS on 13-sector images is theoretically possible but extremely rare in practice.

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

  • Advanced copy operations: Batch file operations with progress reporting
  • CLI interface: Command-line tools for disk manipulation

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.2.1.tar.gz (115.9 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.2.1-py3-none-any.whl (144.6 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: diskii-0.2.1.tar.gz
  • Upload date:
  • Size: 115.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.1.2 CPython/3.13.7 Linux/6.1.149-3-MANJARO

File hashes

Hashes for diskii-0.2.1.tar.gz
Algorithm Hash digest
SHA256 0742c7678439f6aa7536d7dad1c4c7fe80dfb197307220257e968273d5f3ee0e
MD5 164a88bb53f6bff651e0f47b240b7ba6
BLAKE2b-256 e47ab33bc1f73485495cce0bb7d1385be47a7796c51d75388c93329a1743e4c5

See more details on using hashes here.

File details

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

File metadata

  • Download URL: diskii-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 144.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.1.2 CPython/3.13.7 Linux/6.1.149-3-MANJARO

File hashes

Hashes for diskii-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 8653c3936c9370206e419db8397fd5db39a70e3488531d3665904b624ad35d47
MD5 d915c5c4abf64605ea262c526cf68cfc
BLAKE2b-256 2fbe6cb68803f1eead55cd2b23c6a6d20ce3cce950d870d4d197a8a3805e5baf

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