SZDD Format Guide
Purpose
This guide provides comprehensive documentation for working with Microsoft SZDD (Single-file LZSS) compressed files using Cabriolet. SZDD is Microsoft’s simple compression format used primarily in MS-DOS and early Windows for compressing individual files.
Concepts
What is an SZDD File?
SZDD files are Microsoft’s single-file compression format used extensively in:
-
MS-DOS file compression (COMPRESS.EXE)
-
MS-DOS file expansion (EXPAND.EXE)
-
Windows 9x installation files
-
System file distribution
-
Compressed executables and DLLs
The format is characterized by its simple structure and use of LZSS compression.
SZDD File Structure
An SZDD file has a simple structure:
┌─────────────────────────┐
│ SZDD Header │ Signature and metadata (14 bytes)
│ - Signature: "SZDD" │
│ - Format version │
│ - Missing character │
│ - Uncompressed size │
├─────────────────────────┤
│ Compressed Data │ LZSS compressed content
│ │
└─────────────────────────┘SZDD Header: Contains format signature, version, and optional metadata.
Missing Character: A special feature for filename reconstruction (e.g., file.ex_ → file.exe).
Compressed Data: LZSS-compressed file content.
Compression Support
SZDD files use LZSS compression exclusively:
-
LZSS MODE_EXPAND - Standard LZSS variant used by EXPAND.EXE
-
Fixed 4096-byte sliding window
-
Simple and fast decompression
For detailed algorithm information, see link:.
Basic Operations
Expanding SZDD Files
Decompress SZDD files (like MS-DOS EXPAND.EXE):
# Auto-detect output filename
cabriolet extract file.tx_
# Specify output filename
cabriolet extract file.tx_ file.txt
# For explicit format specification:
cabriolet extract --format szdd file.tx_ file.txt The expand command is a legacy alias for extract and is still supported for backward compatibility with MS-DOS EXPAND.EXE. |
require 'cabriolet'
decompressor = Cabriolet::SZDD::Decompressor.new
header = decompressor.open('file.tx_')
# Auto-detect output name from missing character
output = decompressor.auto_output_filename('file.tx_', header)
# Expand the file
bytes = decompressor.extract(header, output)
decompressor.close(header)
puts "Expanded to #{output} (#{bytes} bytes)"Expanded file.tx_ to file.txt (5,234 bytes)Getting SZDD Information
Display SZDD file metadata:
cabriolet info file.tx_
# For explicit format specification:
cabriolet info --format szdd file.tx_require 'cabriolet'
decompressor = Cabriolet::SZDD::Decompressor.new
header = decompressor.open('file.tx_')
puts "Format: #{header.format}" # :normal or :qbasic
puts "Uncompressed size: #{header.length} bytes"
puts "Missing character: '#{header.missing_char}'"
puts "Suggested filename: #{header.suggested_filename('file.tx_')}"
decompressor.close(header)SZDD File Information
==================================================
Filename: file.tx_
Format: NORMAL
Uncompressed size: 5,234 bytes
Missing character: 't'
Suggested filename: file.txtCompressing Files
Create SZDD compressed files (like MS-DOS COMPRESS.EXE):
# Auto-generate output name: file.txt → file.tx_
cabriolet create file.tx_ file.txt
# Specify output filename
cabriolet create file.tx_ file.txt
# Specify missing character explicitly
cabriolet create --missing-char=t file.tx_ file.txt
# Use QBasic format
cabriolet create --format=qbasic file.ba_ file.bas
# For explicit format specification:
cabriolet create --format szdd file.tx_ file.txt The compress command is a legacy alias for create and is still supported for backward compatibility with MS-DOS COMPRESS.EXE. |
require 'cabriolet'
compressor = Cabriolet::SZDD::Compressor.new
# Compress with auto-generated missing character
bytes = compressor.compress('file.txt', 'file.tx_')
puts "Compressed to file.tx_ (#{bytes} bytes)"Advanced Features
Missing Character Reconstruction
The missing character feature enables filename reconstruction:
require 'cabriolet'
decompressor = Cabriolet::SZDD::Decompressor.new
header = decompressor.open('program.ex_')
# Get missing character
missing = header.missing_char # => 'e'
# Reconstruct original filename
original = header.suggested_filename('program.ex_')
puts "Original filename: #{original}" # => "program.exe"
decompressor.close(header)Format detection
Detect SZDD format variant:
require 'cabriolet'
decompressor = Cabriolet::SZDD::Decompressor.new
header = decompressor.open('file.tx_')
case header.format
when :normal
puts "Standard SZDD format"
when :qbasic
puts "QBasic SZDD variant"
end
decompressor.close(header)Custom Missing Character
Specify custom missing character when compressing:
require 'cabriolet'
compressor = Cabriolet::SZDD::Compressor.new
# Compress with custom missing character
bytes = compressor.compress(
'myfile.txt',
'myfile.tx_',
missing_char: 't'
)
puts "Compressed with missing char 't'"QBasic Format Support
Work with QBasic-compressed files:
require 'cabriolet'
# Compress in QBasic format
compressor = Cabriolet::SZDD::Compressor.new
bytes = compressor.compress(
'program.bas',
'program.ba_',
format: :qbasic
)
# Decompress QBasic format
decompressor = Cabriolet::SZDD::Decompressor.new
header = decompressor.open('program.ba_')
if header.format == :qbasic
puts "QBasic format detected"
end
decompressor.extract(header, 'program.bas')
decompressor.close(header)Performance Optimization
Common Use Cases
MS-DOS File Distribution
Working with MS-DOS compressed files:
require 'cabriolet'
# Expand MS-DOS system file
decompressor = Cabriolet::SZDD::Decompressor.new
header = decompressor.open('command.co_')
output = decompressor.auto_output_filename('command.co_', header)
decompressor.extract(header, output)
decompressor.close(header)
puts "Expanded MS-DOS file: #{output}"Windows 9x Installation Files
Extract Windows installation files:
require 'cabriolet'
require 'fileutils'
decompressor = Cabriolet::SZDD::Decompressor.new
# Process all ._ files in directory
Dir.glob('install/*.ex_').each do |compressed|
header = decompressor.open(compressed)
output = decompressor.auto_output_filename(compressed, header)
decompressor.extract(header, output)
decompressor.close(header)
puts "Extracted: #{File.basename(output)}"
endBatch Compression
Compress multiple files:
require 'cabriolet'
compressor = Cabriolet::SZDD::Compressor.new
Dir.glob('source/*.txt').each do |file|
# Generate compressed filename: file.txt → file.tx_
output = file.sub(/\.([^.])$/, '._')
bytes = compressor.compress(file, output)
puts "Compressed #{file} → #{output} (#{bytes} bytes)"
endFilename Reconstruction
Reconstruct original filenames:
require 'cabriolet'
decompressor = Cabriolet::SZDD::Decompressor.new
Dir.glob('compressed/*._').each do |compressed|
header = decompressor.open(compressed)
# Use missing character to reconstruct name
suggested = header.suggested_filename(compressed)
puts "#{File.basename(compressed)} → #{File.basename(suggested)}"
puts " Missing char: '#{header.missing_char}'"
decompressor.close(header)
endTroubleshooting
Common Errors
"Invalid SZDD signature"
The file is not a valid SZDD file:
# Check file signature
hexdump -C file.tx_ | head -1
# Should show: "SZDD" (53 5A 44 44) or "SZ20" for QBasic"Missing character not found"
The header doesn’t contain a missing character. Specify output filename explicitly:
cabriolet extract file.tx_ file.txt"Decompression failed"
The compressed data is corrupted. Try salvage extraction:
# Extract partial data (planned feature)
cabriolet extract --salvage file.tx_ file.txt"Unknown format variant"
Unsupported SZDD variant. Check format with:
cabriolet info file.tx_Validation
Verify SZDD file integrity:
require 'cabriolet'
begin
decompressor = Cabriolet::SZDD::Decompressor.new
header = decompressor.open('file.tx_')
puts "SZDD file is valid"
puts "Format: #{header.format}"
puts "Size: #{header.length} bytes"
decompressor.close(header)
rescue Cabriolet::FormatError => e
puts "Invalid SZDD file: #{e.message}"
rescue Cabriolet::CorruptionError => e
puts "Corrupted SZDD: #{e.message}"
endBest practices
-
Use missing character: Store the missing character for proper filename reconstruction
-
Match format to use case:
-
Normal format for general files
-
QBasic format for QBasic programs
-
-
Validate before extraction: Check file integrity before expanding
-
Preserve metadata: Keep track of original filenames and sizes
-
Batch processing: Process multiple files efficiently with scripts
-
Handle errors gracefully: Account for corrupted or invalid files
Format Specifications
File Signature
SZDD files start with one of two signatures:
Offset Bytes Description
0x0000 4 Signature: "SZDD" (0x53 0x5A 0x44 0x44)
0x0004 4 Reserved (0x88 0xF0 0x27 0x33)
0x0008 1 Compression mode: 'A' (0x41)
0x0009 1 Missing character (ASCII)
0x000A 4 Uncompressed length (little-endian)Offset Bytes Description
0x0000 4 Signature: "SZ20" (0x53 0x5A 0x32 0x30)
0x0004 4 Reserved
0x0008 1 Compression mode: 'A' (0x41)
0x0009 1 Missing character
0x000A 4 Uncompressed lengthCompression Algorithm
-
Algorithm: LZSS MODE_EXPAND
-
Window size: 4096 bytes
-
Match length: 3-18 bytes
-
Format: See LZSS Compression Guide
For complete format specifications, see Format Specifications.
Next steps
-
Learn about LZSS compression
-
Review extracting files
-
Study Ruby API