LZSS Compression
Purpose
This guide explains LZSS (Lempel-Ziv-Storer-Szymanski) compression used in SZDD, HLP, and KWAJ formats.
Concepts
What is LZSS?
LZSS is a dictionary-based compression algorithm that replaces repeated data with references to previous occurrences. It’s an improvement over LZ77 with better encoding efficiency.
Performance characteristics
| Metric | Value |
|---|---|
Compression ratio | 30-50% for text, 20-40% for executables |
Compression speed | Fast (10-50 MB/s) |
Decompression speed | Very fast (50-200 MB/s) |
Memory usage | Low (4-8 KB) |
Window size | Fixed 4096 bytes |
Usage
SZDD Files (MODE_EXPAND)
compressor = Cabriolet::SZDD::Compressor.new
# Automatically uses LZSS MODE_EXPAND
bytes = compressor.compress('file.txt', 'file.tx_')Command line:
cabriolet compress file.txt file.tx_
cabriolet expand file.tx_ file.txtAlgorithm Details
Encoding Process
-
Initialize sliding window (4096 bytes)
-
Search for longest match in window
-
Encode match as:
-
Literal byte (if no match or short)
-
Reference (offset, length) if match found
-
-
Slide window forward
-
Repeat until end of input
Compression Effectiveness
Comparison with Other Algorithms
| Algorithm | Ratio | Speed | Memory | Window |
|---|---|---|---|---|
LZSS | 30-50% | Fast | Low | 4 KB |
MSZIP | 40-60% | Medium | Medium | 32 KB |
LZX | 50-70% | Slow | High | 32KB-2MB |
Quantum | 45-65% | Medium | Medium | Variable |
Best practices
-
Use for text - LZSS excels on text files
-
Fast operations - Choose when speed matters
-
Low memory - Good for constrained environments
-
Legacy support - Required for SZDD/HLP formats
-
Skip pre-compressed - Don’t compress JPG, PNG, etc.
Examples
Compress MS-DOS File
require 'cabriolet'
# Compress for MS-DOS EXPAND.EXE
compressor = Cabriolet::SZDD::Compressor.new
compressor.compress('readme.txt', 'readme.tx_', format: :normal)
puts "Compressed with LZSS MODE_EXPAND"Create Windows Help
require 'cabriolet'
compressor = Cabriolet::HLP::Compressor.new
# Add files with LZSS MODE_MSHELP compression
compressor.add_file('system.dat', '|SYSTEM', compress: true)
compressor.add_file('topics.dat', '|TOPIC', compress: true)
# Images uncompressed
compressor.add_file('image.bmp', 'image.bmp', compress: false)
compressor.generate('help.hlp')Batch Compress Files
require 'cabriolet'
compressor = Cabriolet::SZDD::Compressor.new
Dir.glob('*.txt').each do |file|
output = file.sub(/\.([^.])$/, '._')
bytes = compressor.compress(file, output)
original = File.size(file)
ratio = (1 - bytes.to_f / original) * 100
puts "#{file}: #{original} → #{bytes} (#{ratio.round(1)}%)"
endTroubleshooting
Technical Notes
See also
-
MSZIP Compression for better ratio
-
LZX Compression for maximum compression