7.9 KiB
Offline map packs
Pyxis can read prebuilt raster map packs from an SD card. Importers accept only local, user-supplied map files and never download tiles. Before importing data, verify that its provider and license permit offline storage and use.
Browser installer (recommended)
Open the Pyxis web flasher in current Chrome or Edge and use Install Offline Maps:
- Download an OSM Bright MUI ZIP from Oxed's Map Tile Downloader.
- Turn the T-Deck off, remove its SD card, and mount the card on the computer.
- Choose the ZIP, enter a map name and pack ID, and wait for local validation.
- Click Install and Enable, then choose the SD-card root.
- After the verified completion message, safely eject the card and return it to the T-Deck.
The browser accepts stored ZIP entries rooted at either <z>/<x>/<y>.png or
maps/<style>/<z>/<x>/<y>.png. It rejects mixed styles, traversal, duplicate
paths or tile keys, symlinks, encrypted or unsupported compression, malformed
ZIP records, unsafe PNGs, quota violations, and noncanonical XYZ paths. Tiles
are validated and read back one at a time; the complete archive is not loaded
into JavaScript memory.
Installation refuses to overwrite an existing pack. A verified pack from an
earlier activation failure can be reselected with the exact same ZIP and
metadata. Tiles are published first, manifest.pmp is published last, and only
then is a CRC-protected redundant active-map-set slot updated and read back. An
interruption therefore leaves the previous map set usable. Unrelated SD-card
files are untouched; cleanup removes only receipt-owned installer paths.
Packs and map sets
A pack is an independent installation, update, removal, provenance, and attribution unit. A map set is an ordered collection of compatible packs that Pyxis uses together. Geographic packs do not require manual switching.
For example, regional-overview-z0-z9 and local-detail-z0-z16 can both
belong to the osm-bright map set. Pyxis checks the local-detail pack first and
then the regional-overview pack for every requested XYZ key. The detail pack
supplies its z10-z16 area while the overview pack supplies broader z0-z9
coverage. Outside the detail area at z10-z16, the key is uncovered. If a
higher-priority pack declares a tile but its file is missing, Pyxis safely tries
the next compatible pack.
The browser currently imports Coalition/MUI OSM Bright data into the bounded
osm-bright map set. Newly installed packs take priority over earlier packs
where their exact row-span coverage overlaps. Different styles or providers
must use a different map set rather than being blended implicitly.
Input requirements
The input must contain only canonical XYZ paths:
<xyz-directory>/<z>/<x>/<y>.png
z,x, andyare canonical unsigned decimal integers:0, not00or+0.- Zoom is 0 through 22; X and Y are each in
0..2^z-1. - Every PNG must be a valid, fully decodable, non-interlaced 256×256 PNG with at most 8 bits per sample. Critical-chunk ordering, supported ancillary semantics, CRCs, palette state, bounded deflate termination, exact scanline length, and row filters are validated; interlaced and 16-bit PNGs are intentionally unsupported by the browser importer.
- Symlinks and unexpected files or directory levels are rejected.
- Zoom levels must be contiguous. Complete rectangles use the compact version-1 manifest; sparse state or polygon coverage uses exact bounded row spans in version 2.
- A complete rectangle crossing the antimeridian can use
--antimeridian-zoom Zfor the compact version-1 representation. With explicit--sparse, disjoint coverage is represented exactly as row spans rather than guessed to be an antimeridian rectangle.
The importer requires non-empty printable-ASCII display name, attribution, source, and license fields. These values are stored in the manifest; they do not grant rights or replace compliance with the provider's terms.
Build a pack
Run from the repository root:
python3 tools/maps/build_map_pack.py ./my-xyz /media/$USER/SDCARD \
--pack-id regional-map \
--name "Regional Map" \
--attribution "Map data (c) Example contributors" \
--source "Local export supplied by the user" \
--license "CC-BY-4.0"
For an intentionally sparse state or polygon export, explicitly add --sparse.
The default CLI mode continues to reject incomplete rectangles so an accidental
missing tile cannot silently become declared sparse coverage.
For explicitly known antimeridian coverage, repeat the option for each affected zoom:
--antimeridian-zoom 8 --antimeridian-zoom 9
The pack ID must match [a-z0-9_-]{1,31}. The destination is:
<output-root>/pyxis-map/packs/<pack-id>/manifest.pmp
<output-root>/pyxis-map/packs/<pack-id>/tiles/<z>/<x>/<y>.png
The output root is normally the mounted SD-card root. The importer refuses to replace an existing pack.
Legacy single-pack selection from the CLI
With the SD card still mounted on the host and not in use by Pyxis, write the pack ID to the bounded selection marker without a trailing newline:
printf '%s' 'regional-map' > /media/$USER/SDCARD/pyxis-map/active-pack
sync /media/$USER/SDCARD
Safely unmount the card before inserting it into the T-Deck. Pyxis validates the marker, manifest, declared coverage, and canonical tile path before use. This marker selects one legacy pack only; it does not build a composited map set. The browser's redundant map-set records take precedence when present. Opening the map refreshes the selection. A missing or malformed pack is shown as unavailable; firmware never formats, repairs, deletes, or writes an immutable pack.
Resource limits and safe publication
Defaults bound an import to 100,000 tiles and 8 GiB of tile bytes. Set stricter limits when appropriate:
--max-tiles 25000 --max-bytes 2147483648
All input is validated before publication. On Linux, the importer pins source and output directories with descriptor-relative, no-follow operations; rejects changed files and directory identities; copies under the caller's quotas; writes the deterministic manifest in a private sibling directory; flushes files and directories; and independently validates the copied tree. Publication requires Linux renameat2(RENAME_NOREPLACE) and fails closed when atomic no-replace is unavailable. A pre-commit failure removes its temporary directory. If the post-rename parent-directory sync fails, the CLI reports exit status 3 and explicitly says the pack is published but durability is uncertain.
The firmware accepts two bounded PMPK wire formats. Version 1 retains fixed
26-byte per-zoom rectangular extents. Version 2 stores up to 512 canonical,
sorted 13-byte (zoom, y, x-minimum, x-maximum) row spans and verifies that
their exact tile total matches the manifest. Both use a 16-byte little-endian
header, five bounded printable-ASCII strings, and a final IEEE CRC-32.
The browser enables packs through redundant bounded active-pack.0 and
active-pack.1 records with generations and CRC-32. Map-set record version 2
stores the map-set ID, shared attribution, up to eight ordered pack IDs, and up
to 512 total canonical row spans. Firmware selects the newest valid record,
resolves each tile in pack-priority order, and ignores a torn or malformed peer.
Legacy 48-byte version-1 records and the plain active-pack marker remain
backward-compatible single-pack fallbacks.
Network policy
Pack creation is deliberately local-files-only. The importer contains no network client, URL support, provider endpoint, or tile-fetch mode. Obtain tiles separately under terms that explicitly allow offline use; do not use this tool to bulk-fetch from a live tile service.
The production map screen is also SD-only. It does not initiate DNS, HTTP, or TLS and has no online-download setting. Its lookup order is the decoded PSRAM cache, the enabled immutable packs in deterministic priority order, and then the bounded legacy SD tile cache.