macOS Quick Look extensions for 48K ZX Spectrum .SNA snapshot files.
- Spacebar Preview: Press spacebar on
.SNAfiles to see full 256×192 decoded image - Finder Thumbnails: File icons display decoded ZX Spectrum screenshots with correct aspect ratio
- Type: Quick Look Preview (spacebar)
- Entry:
PreviewViewController(QLPreviewingController) - Function: Renders 256×192 bitmap in preview panel
- Note: Uses UIKit coordinate system, full resolution display
- Type: Quick Look Thumbnail (Finder icons)
- Entry:
ThumbnailProvider(QLThumbnailProvider) - Function: Renders scaled thumbnail preserving 4:3 aspect ratio
- Note: Sandboxed XPC extension, scales to icon grid while maintaining aspect
- Extension:
.SNA - Size: 49,179 bytes (fixed, 48K Spectrum snapshot)
- Resolution: 256×192 pixels (4:3 aspect ratio)
- Memory Layout:
- Bytes 0-26: Registers + state (27 bytes)
- Bytes 27-6,910: Display memory (32×192 chars = 32×24 chars × 8 pixels)
- Bytes 6,911-7,678: Attributes (color + brightness per char)
The decoder reconstructs the ZX Spectrum display format:
- Parse attribute bytes (ink color, paper color, brightness)
- Iterate 24×32 character grid
- For each character, unpack 8 pixel rows from display memory
- Map bits to RGB using decoded color attributes
- Handle Spectrum's "venetian blinds" memory layout (Y coordinate transformation)
| Problem | Solution |
|---|---|
No standard .SNA UTType |
Declared custom com.hippietrail.sna in host app's Info.plist under UTExportedTypeDeclarations |
| Preview extension API | Used QLPreviewingController for spacebar; QLThumbnailProvider for icons |
| Two extensions in one target | Xcode requires separate targets; templates available for both |
| Shared decoding logic | Duplicated code in both extensions (only ~100 lines, acceptable for clarity) |
| Aspect ratio distortion | Calculate scale factor preserving 4:3 ratio; center in icon square |
| Extension binary missing | Swift files must be in target's "Compile Sources" build phase |
| Extensions not loading | Must install to /Applications (debug builds from Xcode don't work) |
❌ Merged both extensions in one Info.plist array → Broke preview functionality
❌ DRY refactoring with shared SnapshotDecoder.swift → Module compilation errors
❌ Manual pbxproj editing → Too fragile, UUID management errors
❌ Relied on file discovery → Swift files need explicit Build Phase entry or Xcode won't compile
❌ Used only request.maximumSize → Forced thumbnails to square; Finder ignored aspect ratio
✅ Constrained contextSize between minimumSize and maximumSize → Finder respects aspect ratio (per Apple docs & Stack Overflow)
# Build both extensions
xcodebuild build -scheme zxql-host-app
# Reset Quick Look daemon
qlmanage -r
# Test spacebar preview
qlmanage -p /path/to/file.sna
# Or in Finder
open -a Finder /path/to/files
# Press spacebar on .sna file
# Thumbnails auto-display in icon viewFor system-wide use (not just development):
cp -r /path/to/zxql-host-app.app /Applications/
# Extensions load automaticallyzxql-host-app/
├── Info-generated.plist # Declares com.hippietrail.sna UTType
└── AppDelegate.swift
zxql-preview-extension/
├── Info.plist # Preview extension config
├── PreviewViewController.swift # QLPreviewingController subclass
├── Base.lproj/
│ └── PreviewViewController.xib # UI (ImageView)
└── *.swift # Support code & color decoding
zxql-thumbnail-extension/
├── Info.plist # Thumbnail extension config
└── ThumbnailProvider.swift # QLThumbnailProvider subclass
# Contains: SNA decoder, color rendering
- zxql-preview-extension/Info.plist - Declares
com.apple.quicklook.previewextension point - zxql-preview-extension/PreviewViewController.swift - Spacebar preview implementation
- zxql-thumbnail-extension/Info.plist - Declares
com.apple.quicklook.thumbnailextension point - zxql-thumbnail-extension/ThumbnailProvider.swift - Finder icon implementation
- zxql-host-app/Info-generated.plist - UTType declaration for
.snafiles
Checklist for new file type:
- Create custom UTType in host app's Info.plist
- Add Preview Extension target (File > New > Target > macOS > Quick Look Preview Extension)
- Implement
QLPreviewingController - Add source files to Build Phases > Compile Sources
- Configure Info.plist with
QLSupportedContentTypes
- Implement
- Add Thumbnail Extension target (File > New > Target > macOS > Thumbnail Extension)
- Implement
QLThumbnailProvider - Add source files to Build Phases > Compile Sources
- Configure Info.plist with
QLSupportedContentTypes+QLThumbnailMinimumDimension
- Implement
- Test both via
qlmanage -rand spacebar/Finder - Install to
/Applications/for system-wide use