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
- 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 formatfile_info.py: Show detailed file metadata and type informationcreate_files.py: Demonstrate creating files on disk imagescross_format_copy.py: Copy files between ProDOS and DOS formatsbasic_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
- ProDOS Technical Reference
- ProDOS Format Notes
- DOS 3.3 Format Notes
- Disk Image Format Reference
- Applesoft BASIC Tokenized File Format
- Applesoft BASIC Programming Reference Manual
- BASIC Keywords and Tokens Reference
- Integer BASIC ROM Disassembly
- Applesoft BASIC ROM Disassembly
License
ISC License - see LICENSE file for details.
Contributing
Contributions are welcome! Please see CONTRIBUTING.md for guidelines.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file diskii-0.4.17.tar.gz.
File metadata
- Download URL: diskii-0.4.17.tar.gz
- Upload date:
- Size: 120.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.2.1 CPython/3.12.13 Linux/6.18.29-0-lts
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bc520a54da695e9beb9efa3dcb32df031258bb7dfcb6af872cc31f909f24630b
|
|
| MD5 |
181279e15f819fb2e2f3f9c3ef43ca71
|
|
| BLAKE2b-256 |
c139c95d9103aefc7f96134e400bb1c77477dc47eec1f47157a0e9008bf5d0b8
|
File details
Details for the file diskii-0.4.17-py3-none-any.whl.
File metadata
- Download URL: diskii-0.4.17-py3-none-any.whl
- Upload date:
- Size: 152.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.2.1 CPython/3.12.13 Linux/6.18.29-0-lts
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f78ca8f88db52be6ec3546befbbbca6f52e703998e4826fc3fd794a7fca9bf21
|
|
| MD5 |
21572f904b047e7639d1be18244cbe4b
|
|
| BLAKE2b-256 |
b94b68d49985ab809e56171f56278397e53cc12e462854c91d84efb06e9f8092
|