From 52ceabab71c91d710388e5280ae05cdb235e6066 Mon Sep 17 00:00:00 2001 From: "Yifeng \"Evan\" Wang" <7312949+doodlewind@users.noreply.github.com> Date: Sun, 6 Sep 2026 11:19:38 -0700 Subject: [PATCH 01/13] feat(map): add paired 3DS maps and saved places --- .github/workflows/check.yml | 19 ++++ .gitignore | 5 + .gitmodules | 4 + AGENTS.md | 9 ++ LICENSE | 21 ++++ README.md | 116 +++++++++++++++++++++- app/geo.ts | 18 ++++ app/main.tsx | 3 + app/map-pad.svg | 1 + app/map-pin.svg | 1 + app/model.ts | 185 ++++++++++++++++++++++++++++++++++++ app/saved.ts | 69 ++++++++++++++ app/shift-lock.svg | 1 + app/shift.svg | 1 + app/ui.tsx | 177 ++++++++++++++++++++++++++++++++++ docs/ARCHITECTURE.md | 129 +++++++++++++++++++++++++ docs/VALIDATION.md | 50 ++++++++++ docs/images/delete.png | Bin 0 -> 21664 bytes docs/images/keyboard.png | Bin 0 -> 194838 bytes docs/images/map.png | Bin 0 -> 194343 bytes docs/images/saved.png | Bin 0 -> 22532 bytes docs/images/search.png | Bin 0 -> 62827 bytes host/bookmarks.ts | 54 +++++++++++ host/cache.ts | 69 ++++++++++++++ host/provider.ts | 106 +++++++++++++++++++++ host/serve.ts | 10 ++ host/worker.ts | 8 ++ package.json | 9 ++ pocket.config.ts | 2 + pocket.json | 6 ++ runtime | 1 + scripts/build.ts | 13 +++ scripts/deploy.ts | 28 ++++++ scripts/quickjs-smoke.js | 47 +++++++++ scripts/setup.ts | 9 ++ scripts/sim.ts | 147 ++++++++++++++++++++++++++++ shared/types.ts | 7 ++ test/bookmarks.test.ts | 30 ++++++ test/geo.test.ts | 11 +++ test/model.test.ts | 23 +++++ test/provider.test.ts | 68 +++++++++++++ tsconfig.json | 4 + 42 files changed, 1460 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/check.yml create mode 100644 .gitignore create mode 100644 .gitmodules create mode 100644 AGENTS.md create mode 100644 LICENSE create mode 100644 app/geo.ts create mode 100644 app/main.tsx create mode 100644 app/map-pad.svg create mode 100644 app/map-pin.svg create mode 100644 app/model.ts create mode 100644 app/saved.ts create mode 100644 app/shift-lock.svg create mode 100644 app/shift.svg create mode 100644 app/ui.tsx create mode 100644 docs/ARCHITECTURE.md create mode 100644 docs/VALIDATION.md create mode 100644 docs/images/delete.png create mode 100644 docs/images/keyboard.png create mode 100644 docs/images/map.png create mode 100644 docs/images/saved.png create mode 100644 docs/images/search.png create mode 100644 host/bookmarks.ts create mode 100644 host/cache.ts create mode 100644 host/provider.ts create mode 100644 host/serve.ts create mode 100644 host/worker.ts create mode 100644 package.json create mode 100644 pocket.config.ts create mode 100644 pocket.json create mode 160000 runtime create mode 100644 scripts/build.ts create mode 100644 scripts/deploy.ts create mode 100644 scripts/quickjs-smoke.js create mode 100644 scripts/setup.ts create mode 100644 scripts/sim.ts create mode 100644 shared/types.ts create mode 100644 test/bookmarks.test.ts create mode 100644 test/geo.test.ts create mode 100644 test/model.test.ts create mode 100644 test/provider.test.ts create mode 100644 tsconfig.json diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml new file mode 100644 index 0000000..d62aef3 --- /dev/null +++ b/.github/workflows/check.yml @@ -0,0 +1,19 @@ +name: Map provider and model +on: [push, pull_request] +permissions: + contents: read +jobs: + check: + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - uses: actions/checkout@v7 + with: + submodules: recursive + - uses: oven-sh/setup-bun@v2 + with: + bun-version: 1.3.14 + - run: bun install --frozen-lockfile + working-directory: runtime + - run: bun run setup + - run: bun run check diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..33a0b38 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +node_modules/ +dist/ +.local/ +.DS_Store +*.log diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..33f6800 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,4 @@ +[submodule "runtime"] + branch = main + path = runtime + url = https://github.com/pocket-stack/pocketjs.git diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..1839902 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,9 @@ +# Pocket Map + +- Framework transport, resource lifecycle and tile geometry belong in PocketJS. +- Keep network requests, SQLite, image decoding and rasterization in the Mac worker. +- Bound guest tile demand, pending responses, native image staging and GPU residency. +- Import PocketJS APIs from `@pocketjs/framework/*`, Solid primitives from `solid-js`. +- Keep pairing keys, cached tiles, user searches and raw replay captures out of Git. Curated public demo images belong in docs/images/. +- Run the app's explicit tests; do not discover tests through the runtime submodule. +- Publish validated changes as a Draft PR with a Conventional Commits title. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..c025cd0 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Pocket Stack contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 91b79b1..bf5e1f9 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,117 @@ # Pocket Map -A Nintendo 3DS map app built with PocketJS, with a paired Mac providing map tiles and place search. +A map browser for Nintendo 3DS, built with [PocketJS](https://github.com/pocket-stack/pocketjs) and SolidJS 1.9. Search for places, pan with the resistive touch screen, and zoom the map on the upper display. A paired Mac handles network requests, SQLite caching, PNG decoding, label rasterization and saved places. + +

Pocket Map displaying real OpenStreetMap tiles on a compiled dual-screen guest Live Photon place results with the bottom-screen selection touchpad

+ +These are **compiled guest + Wasm captures using live OpenStreetMap DE and Photon data**, at the 3DS's 400×240 / 320×240 logical resolutions. They are not photographs of the console. Map data © [OpenStreetMap contributors](https://www.openstreetmap.org/copyright); tiles provided by [FOSSGIS / OpenStreetMap DE](https://openstreetmap.de/germanstyle/). + +## Try it + +Requirements: Bun 1.3.14, Docker with the PocketJS 3DS toolchain (or a supported native devkitPro install), a Mac and a 3DS on the same LAN, Homebrew Launcher and ftpd. The runtime submodule pins the image-resource support used by this app. + +```sh +git clone --recurse-submodules https://github.com/pocket-stack/pocket-map.git +cd pocket-map +cd runtime && bun install --frozen-lockfile && cd .. +bun run setup +bun run 3ds +# Open ftpd on the console first. Substitute its LAN IP. +bun run deploy 192.168.8.102 +bun run host 192.168.8.102 +``` + +Exit ftpd and open **Pocket Map** in HBL. The deployment script installs only this app and its pairing key, then reads both back for verification. Keys, saved places and the provider's cache stay under ignored `.local/`. `L + R + START` returns to HBL. + +| Control | Action | +| --- | --- | +| Bottom touchpad | Drag to pan; flick for inertia | +| Circle Pad / D-pad | Pan the upper map | +| `+` / `-` buttons | Animated zoom around the map center | +| Search / Y | Open the local keyboard; Find submits the query | +| Search results touchpad | Slide to choose a result, tap to open | +| D-pad up/down + A | Choose and open a search result or menu item | +| X / Back to pin | Return to the selected place | +| Hold L | Search, saved places, save map center, return to pin, or San Francisco | +| Hold R | Zoom, clear pin, retry tiles, or show controls | +| Save view / Save place | Name and save the center or selected search result on the Mac | +| Saved | Browse, rename, delete with confirmation, or return to a saved location | +| Saved page: Prev / Next or D-pad left/right | Turn five-place pages | +| B | Dismiss results/menu; backspace while typing | +| Shift | Tap for one uppercase letter; double-tap for caps lock | + +Typing, dragging, inertia and zoom transitions update locally. Missing tiles show a fallback; an already loaded previous zoom level stays visible during replacement. A disconnected Mac leaves resident tiles navigable. Search, new tiles and uncached labels require the Mac. + +## Saved places + +Use **Save view** to store the map center, or **Save place** on a search result. +The local keyboard names it before Save sends a command to the Mac. Saved opens +five-place pages, with Rename, Delete and Go to place actions. Deletion uses an +animated confirmation sheet; B / Keep place cancels it. + +The Mac stores user data in `.local/places.sqlite`, separate from the disposable +`.local/cache.sqlite`. Coordinates, zoom and names survive daemon restarts. +Mutations commit with an operation receipt: Retry after a missing acknowledgement +uses the same operation, so it cannot create a second copy or resurrect a deleted +place. Cancel after an unconfirmed command does not undo a Mac write; reopen +Saved to check its outcome. A connected Mac is needed for writes. The guest +retains up to four previously viewed pages during a disconnection. + +## Provider configuration + +The default small-demo configuration uses `https://tile.openstreetmap.de/{z}/{x}/{y}.png` and `https://photon.komoot.io/api/`, both verified reachable from the development Mac. The main `tile.openstreetmap.org` endpoint failed to connect in that network. No API keys are required by the selected demo endpoints. + +Override settings in `.local/provider.json`, then restart the host: + +```json +{ + "tileURL": "https://tile.openstreetmap.org/{z}/{x}/{y}.png", + "searchURL": "https://photon.komoot.io/api/", + "name": "OpenStreetMap", + "attribution": "OpenStreetMap contributors", + "maxZoom": 18 +} +``` + +The tile endpoint must return 256px PNGs; the search endpoint must implement the Photon response shape. HTTPS and loopback HTTP development endpoints are supported. The device sends typed tile coordinates, not arbitrary URLs. Tile identities include a hash of the source URL and rendition version. + +Public services have limited capacity: [OSM DE's terms](https://openstreetmap.de/germanstyle/#nutzungsbedingungen), [tile usage policy](https://operations.osmfoundation.org/policies/tiles/), and [Photon's demo policy](https://github.com/komoot/photon#demo-server) apply. **The current viewport has priority; at most four nearby tiles provide short-range look-ahead.** The margin is 64 screen pixels and movement prediction is capped at 128 pixels; there is no area downloader or multi-level pre-seeding. Searches require an explicit submit and are limited to one per 1.1 seconds on this provider. The Mac honors HTTP cache headers and conditional requests, using seven days for tiles without freshness headers. Use an appropriate hosted or self-hosted service before scaling beyond this personal demo. Endpoint configuration allows that switch without rebuilding the 3DS app. + +## Architecture and resource pattern + +```text +3DS UI thread 3DS network worker Mac provider worker +camera + controls authenticated TCP HTTPS + SQLite cache +visible tile demand -> bounded request queue -> fetch / PNG decode +ResourceImage fallback <- native image tickets <- binary R5G6B5 pixels +one image upload/frame eight staging slots bounded tile/label output +``` + +The app uses `createOffloadImageCollection` to declare the tile identity and rendition once. View owners declare demand; reads subscribe by key. The runtime merges demands, schedules requests, retries failed reads, uploads within the frame budget and frees textures on eviction. Cancelling a response before upload returns its native staging slot. + +```ts +const tiles = createOffloadImageCollection(runtime, io, { + key: (tile: TileInput) => `${tile.source}/${tile.z}/${tile.x}/${tile.y}`, + method: "map.tile", payload: JSON.stringify, + width: 256, height: 256, maxEntries: 40, + maxViews: 2, maxDemandsPerView: 16, +}); +const view = createResourceView(tiles, { demand: visibleTileDemand }); +// view.state(tile)} fallback={() => } /> +``` + +Map-specific behavior remains in [app/model.ts](app/model.ts) and [app/geo.ts](app/geo.ts): Mercator projection, longitude wrapping, visible priorities, selection and search. [host/provider.ts](host/provider.ts) owns source grants and image processing; [host/cache.ts](host/cache.ts) owns persistent HTTP caching. [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) records budgets, lifecycle and tradeoffs. + +## Validation + +```sh +bun run check +runtime/node_modules/.bin/tsc --noEmit +bun run sim # compiled guest, synthetic provider, interaction replay +bun run sim --live # current live viewport + one explicit place search +qjs --std --stack-size 131072 scripts/quickjs-smoke.js +``` + +Generated captures and receipts go to `dist/qa/`. Replay covers keyboard input, selecting places, drag/inertia, zoom, sustained movement while replies wait, reconnect, date-line navigation and bounded resource ownership. Replay also covers saving, a lost acknowledgement and safe retry, renaming, paging, delete confirmation and entering a prefetched tile. Stress tests use synthetic tiles, not automated public-service downloads. + +Native build, native transport, visual replay and physical interaction are separate checks. **No measured 60 fps claim is made yet.** Per-frame IO and image limits prevent network waits on the UI thread; JS, allocation, GPU uploads and presentation still need hardware measurement. See [docs/VALIDATION.md](docs/VALIDATION.md). diff --git a/app/geo.ts b/app/geo.ts new file mode 100644 index 0000000..a51f9b2 --- /dev/null +++ b/app/geo.ts @@ -0,0 +1,18 @@ +export const MAX_LATITUDE = 85.0511287798066; +export function project(lat: number, lon: number) { + if (!Number.isFinite(lat) || !Number.isFinite(lon)) throw new Error("Invalid coordinate"); + lat = Math.max(-MAX_LATITUDE, Math.min(MAX_LATITUDE, lat)); + const sine = Math.sin(lat * Math.PI / 180); + return { x: (((lon + 180) % 360 + 360) % 360) / 360 * 256, + y: (0.5 - Math.log((1 + sine) / (1 - sine)) / (4 * Math.PI)) * 256 }; +} +export function unproject(x: number, y: number) { + return { lon: x / 256 * 360 - 180, lat: Math.atan(Math.sinh(Math.PI * (1 - 2 * y / 256))) * 180 / Math.PI }; +} +export function wrapTile(x: number, z: number) { const n = 2 ** z; return ((x % n) + n) % n; } +export function scaleBar(lat: number, zoom: number) { + const metersPerPixel = 156543.03392804097 * Math.cos(lat * Math.PI / 180) / 2 ** zoom; + const target = metersPerPixel * 70, base = 10 ** Math.floor(Math.log10(target)); + const meters = [5, 2, 1].map(n => n * base).find(n => n <= target) ?? base / 2; + return { pixels: meters / metersPerPixel, label: meters >= 1000 ? `${meters / 1000} km` : `${meters} m` }; +} diff --git a/app/main.tsx b/app/main.tsx new file mode 100644 index 0000000..cd09b1d --- /dev/null +++ b/app/main.tsx @@ -0,0 +1,3 @@ +import { mount } from "@pocketjs/framework/solid"; +import MapApp from "./ui.tsx"; +mount(() => ); diff --git a/app/map-pad.svg b/app/map-pad.svg new file mode 100644 index 0000000..686a96e --- /dev/null +++ b/app/map-pad.svg @@ -0,0 +1 @@ + diff --git a/app/map-pin.svg b/app/map-pin.svg new file mode 100644 index 0000000..9c6b712 --- /dev/null +++ b/app/map-pin.svg @@ -0,0 +1 @@ + diff --git a/app/model.ts b/app/model.ts new file mode 100644 index 0000000..261bd3f --- /dev/null +++ b/app/model.ts @@ -0,0 +1,185 @@ +import { createSignal, createMemo } from "solid-js"; +import { createResourceRuntime, createResourceView } from "@pocketjs/framework/resource-view"; +import { createOffloadImageCollection, offloadResource } from "@pocketjs/framework/resource-offload"; +import { createTileCamera, planTileWindow } from "@pocketjs/framework/tile-viewport"; +import { offload } from "@pocketjs/framework/offload"; +import { analogX, analogY, onFrame, onButtonPress } from "@pocketjs/framework/lifecycle"; +import { BTN } from "@pocketjs/framework/input"; +import { simulationHz, virtualNow } from "@pocketjs/framework/clock"; +import { project, unproject, wrapTile } from "./geo.ts"; +import { createSavedPlaces, validPlaces, type MapMode } from "./saved.ts"; +import { HOME, type TileInput, type MapInfo, type SearchInput, type Place } from "../shared/types.ts"; + +export interface DrawTile { input: TileInput; column: number; row: number; priority: number } +export interface Layer { level: number; tiles: DrawTile[]; originX: number; originY: number } +export const MENU = { + places: ["Search places", "Saved places", "Save map center", "Back to pin", "San Francisco"], + map: ["Zoom in", "Zoom out", "Clear pin", "Retry tiles", "About & controls"], +}; +export function createMap(io = offload()) { + const [info, setInfo] = createSignal(); + const [online, setOnline] = createSignal(false), [status, setStatus] = createSignal("Waiting for paired Mac"); + const [mode, setMode] = createSignal("map"); + const [query, setQuery] = createSignal(""), [submitted, setSubmitted] = createSignal(); + const [selection, setSelection] = createSignal(0), [pin, setPin] = createSignal(); + const [menu, setMenu] = createSignal<"places" | "map">(), [menuIndex, setMenuIndex] = createSignal(0); + const [shift, setShift] = createSignal<"off" | "once" | "locked">("off"), [symbols, setSymbols] = createSignal(false); + const [front, setFront] = createSignal(), [back, setBack] = createSignal(); + const p = project(HOME.lat, HOME.lon); + const camera = createTileCamera({ width: 400, height: 240, x: p.x, y: p.y, zoom: HOME.zoom, minZoom: 1, maxZoom: 18, bounds: { width: 256, height: 256, wrapX: true } }); + const runtime = createResourceRuntime({ maxConcurrent: 3, startsPerFrame: 1, completionsPerFrame: 1, maxCollections: 4, available: () => io.connected() && !!info() && io.pending() < 3 }); + const tiles = createOffloadImageCollection(runtime, io, { key: (i: TileInput) => `${i.source}/${i.z}/${i.x}/${i.y}`, method: "map.tile", payload: JSON.stringify, + width: 256, height: 256, maxEntries: 40, maxViews: 2, maxDemandsPerView: 16, retry: { attempts: 3, delayFrames: 90, maxDelayFrames: 360 } }); + const labels = createOffloadImageCollection(runtime, io, { key: (i: Place) => `${i.name}/${i.detail}`, method: "map.label", payload: i => JSON.stringify({ name: i.name, detail: i.detail }), + width: 256, height: 32, maxEntries: 5, maxViews: 5, maxDemandsPerView: 1 }); + const [lookAhead, setLookAhead] = createSignal([]); + const frontView = createResourceView(tiles, { demand: () => [...(front()?.tiles.map(t => ({ input: t.input, priority: t.priority, pin: true })) ?? []), ...lookAhead().map(t => ({ input: t.input, priority: 1000 + t.priority, pin: false }))] }); + const backView = createResourceView(tiles, { demand: () => back()?.tiles.map(t => ({ input: t.input, priority: 100, pin: true })) ?? [] }); + const searches = runtime.createCollection({ key: (i: SearchInput) => JSON.stringify(i), maxEntries: 4, maxViews: 1, maxDemandsPerView: 1, + maxCost: 4 * 8192, cost: () => 8192, maxResponseBytes: 5000, retry: { attempts: 1, delayFrames: 60, maxDelayFrames: 60 }, + load: offloadResource(io, "map.search", JSON.stringify), materialize(raw: string): Place[] { + const rows = JSON.parse(raw); + if (!validPlaces(rows)) throw new Error("Invalid places response"); + return rows; + }, + }); + const results = createResourceView(searches, { demand: () => submitted() ? [{ input: submitted()!, priority: -10, pin: true }] : [] }); + const places = createMemo(() => submitted() ? results.value(submitted()!) ?? [] : []); + const saved = createSavedPlaces(io, runtime, mode, setMode); + const typing = () => mode() === "search" || mode() === "name"; + const listing = () => mode() === "results" || mode() === "saved"; + const rows = () => mode() === "saved" ? saved.page()?.items ?? [] : places(); + const selectedIndex = () => mode() === "saved" ? saved.selection() : selection(); + function select(index: number) { const n = Math.max(0, Math.min(rows().length - 1, index)); if (mode() === "saved") saved.setSelection(n); else setSelection(n); } + let previousView = camera.view(); + let frame = 0, previousSession = 0, infoRequest = 0, retryAt = 0, shiftAt = -10, levelAge = 0, candidateLevel = HOME.zoom; + let confirmed = false; + function search() { + const text = query().trim(); if (!text) return; + const pos = unproject(camera.view().x, camera.view().y); + const next = { query: text, lat: Math.round(pos.lat * 10) / 10, lon: Math.round(pos.lon * 10) / 10 }; + searches.invalidate(i => JSON.stringify(i) === JSON.stringify(next)); + setSubmitted(next); setSelection(0); setMode("results"); camera.stop(); + } + function openSearch() { if (saved.busy() || saved.modal() || mode() === "name") return; camera.stop(); setMode("search"); setMenu(undefined); } + function go(place = rows()[selectedIndex()]) { + if (!place) return; + const pos = project(place.lat, place.lon); camera.jump(pos.x, pos.y, Math.min(info()?.maxZoom ?? 18, place.zoom)); + setPin(place); setMode("map"); setMenu(undefined); + } + function home(name: string, lat: number, lon: number) { go({ id: name, name, detail: "", lat, lon, zoom: 14 }); } + function zoom(delta: number) { + if (delta > 0 && camera.view().zoom >= (info()?.maxZoom ?? 18)) return; + camera.zoomBy(delta); + } + function key(value: string) { + if (!typing() || saved.busy()) return; + const change = (fn: (value: string) => string) => mode() === "name" ? saved.changeName(fn(saved.name())) : setQuery(fn); + if (value === "DEL") change(q => q.slice(0, -1)); + else if (value === "SPACE") change(q => q.length < 80 ? q + " " : q); + else if (value === "GO") mode() === "name" ? saved.submit() : search(); + else if (value === "SHIFT") { + const now = virtualNow(); setShift(s => s === "locked" ? "off" : now - shiftAt < 0.35 ? "locked" : s === "off" ? "once" : "off"); shiftAt = now; + } else if (value === "123") setSymbols(s => !s); + else if (value.length === 1) { change(q => q.length < 80 ? q + (shift() !== "off" ? value.toUpperCase() : value) : q); if (shift() === "once") setShift("off"); } + } + function saveCurrent() { + camera.stop(); + if (mode() === "results") { const selected = places()[selection()]; if (selected) { const p = project(selected.lat, selected.lon); camera.jump(p.x, p.y, selected.zoom); setPin(selected); saved.begin(selected); } return; } + const view = camera.view(), pos = unproject(view.x, view.y), selected = pin(); + const target = selected && project(selected.lat, selected.lon); + let dx = target ? target.x - view.x : Infinity; dx -= Math.round(dx / 256) * 256; + saved.begin(target && Math.hypot(dx, target.y - view.y) * view.scale < 12 ? selected! : { id: "center", name: "Map center", detail: `${pos.lat.toFixed(5)}, ${pos.lon.toFixed(5)}`, ...pos, zoom: Math.round(view.zoom) }); + } + function dismiss() { if (saved.busy()) return; if (mode() === "name") { saved.cancelName(); return; } setMenu(undefined); setMode("map"); camera.stop(); } + function runMenu() { + const i = menuIndex(), bank = menu(); setMenu(undefined); confirmed = true; + if (bank === "places") { + if (i === 0) openSearch(); else if (i === 1) saved.open(); else if (i === 2) saveCurrent(); else if (i === 3) go(pin()); else home("San Francisco", HOME.lat, HOME.lon); + } else if (bank === "map") { + if (i < 2) zoom(i === 0 ? 1 : -1); else if (i === 2) setPin(undefined); else if (i === 3) tiles.invalidate(); else setMode("about"); + } + } + onButtonPress(BTN.CIRCLE, () => { if (saved.modal() || saved.busy()) return; if (menu()) runMenu(); else if (typing()) key("GO"); else if (listing()) go(); }); + onButtonPress(BTN.CROSS, () => { if (saved.modal()) { saved.cancelDelete(); return; } if (saved.busy()) return; if (menu()) { confirmed = true; setMenu(undefined); } else if (typing()) key("DEL"); else dismiss(); }); + onButtonPress(BTN.TRIANGLE, openSearch); + onButtonPress(BTN.SQUARE, () => { if (mode() === "map") go(pin()); }); + for (const [button, delta] of [[BTN.UP, -1], [BTN.DOWN, 1]] as const) onButtonPress(button, () => { + if (saved.modal() || saved.busy()) return; + if (menu()) setMenuIndex(i => Math.max(0, Math.min(4, i + delta))); + else if (listing()) select(selectedIndex() + delta); + }); + onButtonPress(BTN.LEFT, () => { if (mode() === "saved" && !menu() && !saved.modal()) saved.turnPage(-1); }); + onButtonPress(BTN.RIGHT, () => { if (mode() === "saved" && !menu() && !saved.modal()) saved.turnPage(1); }); + let previousButtons = 0; + onFrame(buttons => { + frame++; const session = io.session(); setOnline(session > 0); + if (session !== previousSession) { + if (infoRequest) { io.cancel(infoRequest); infoRequest = 0; } + runtime.cancel(); retryAt = 0; + if (session > 0) { tiles.invalidate(); searches.invalidate(); labels.invalidate(); saved.refresh(); setStatus("Connecting map service"); } + else setStatus("Mac disconnected - cached map"); + previousSession = session; + } + if (session > 0 && !infoRequest && frame >= retryAt) { + infoRequest = io.request("map.info", "{}", result => { + infoRequest = 0; retryAt = frame + 3600; + if (!result.ok) { setStatus(result.error); retryAt = frame + 120; return; } + try { + const value: MapInfo = JSON.parse(result.value); + if (typeof value.source !== "string" || !/^[a-f0-9]{16}$/.test(value.source) || typeof value.name !== "string" || typeof value.attribution !== "string" || !Number.isInteger(value.maxZoom) || value.maxZoom < 1 || value.maxZoom > 18) throw new Error("Invalid map provider"); + if (info()?.source !== value.source) { tiles.clear(); setFront(undefined); setBack(undefined); setLookAhead([]); } + setInfo(value); setStatus("Map ready"); + } catch { setStatus("Unsupported map provider"); retryAt = frame + 120; } + }); + } + const shoulders = buttons & (BTN.LTRIGGER | BTN.RTRIGGER); + if (!shoulders) { confirmed = false; if (menu()) setMenu(undefined); } + else if (!saved.modal() && !saved.busy() && mode() !== "name" && !confirmed && !menu() && shoulders !== (previousButtons & (BTN.LTRIGGER | BTN.RTRIGGER))) { + setMenu(shoulders & BTN.LTRIGGER ? "places" : "map"); setMenuIndex(0); camera.stop(); + } + const canPan = mode() === "map" && !shoulders && !saved.modal(); + const axisX = canPan ? analogX() : 0, axisY = canPan ? analogY() : 0; + const dx = canPan ? (buttons & BTN.LEFT ? 1 : 0) - (buttons & BTN.RIGHT ? 1 : 0) : 0; + const dy = canPan ? (buttons & BTN.UP ? 1 : 0) - (buttons & BTN.DOWN ? 1 : 0) : 0; + camera.step(1 / simulationHz(), dx ? dx * 180 : -axisX * 320, dy ? dy * 180 : -axisY * 320); + previousButtons = buttons; + if (!info()) return; + const view = camera.view(), next = Math.min(info()!.maxZoom, Math.max(1, Math.round(view.zoom))); + levelAge = next === candidateLevel ? levelAge + 1 : 0; candidateLevel = next; + let level = front()?.level ?? next; + if (next !== level && (levelAge >= 8 || Math.abs(next - level) > 1)) { + const previous = front(); + setBack(previous ? { ...previous, tiles: previous.tiles.filter(t => frontView.state(t.input).status === "ready") } : undefined); + level = next; + } + let leadX = view.x - previousView.x; leadX -= Math.round(leadX / 256) * 256; + const leadY = view.y - previousView.y; + const moving = view.moving && Math.hypot(leadX, leadY) * view.scale < 24 && Math.abs(view.zoom - level) < 0.02; + const planOptions = { ...view, level, width: 400, height: 240, maxTiles: 12, margin: 64, + leadX: moving ? Math.max(-128, Math.min(128, leadX * view.scale * 18)) : 0, + leadY: moving ? Math.max(-128, Math.min(128, leadY * view.scale * 18)) : 0, maxExtra: Math.abs(view.zoom - level) < 0.02 ? 4 : 0 }; + let window; + try { window = planTileWindow(planOptions); } + catch { level = next; window = planTileWindow({ ...planOptions, level, maxExtra: 0 }); } + previousView = view; + const address = (list: typeof window.visible) => list.filter(t => t.row >= 0 && t.row < 2 ** level).map(t => ({ ...t, input: { source: info()!.source, z: level, x: wrapTile(t.column, level), y: t.row } })); + const draw = address(window.visible), ahead = address(window.lookAhead); + if (ahead.length !== lookAhead().length || ahead.some((t, i) => { const o = lookAhead()[i]; return !o || t.input.z !== o.input.z || t.input.x !== o.input.x || t.input.y !== o.input.y; })) setLookAhead(ahead); + const previous = front(); + if (!previous || previous.level !== level || previous.tiles.length !== draw.length || draw.some(t => !previous.tiles.some(o => o.column === t.column && o.row === t.row))) { + // Solid's For keys by object identity. Keep overlapping tile instances; + // a one-column pan must not remount every resource/fallback on the screen. + const retained = draw.map(t => previous?.level === level + ? previous.tiles.find(o => o.column === t.column && o.row === t.row && o.input.source === t.input.source) ?? t : t); + setFront({ level, tiles: retained, originX: Math.min(...draw.map(t => t.column)) * 256, originY: Math.min(...draw.map(t => t.row)) * 256 }); + } + if (back() && front()?.tiles.every(t => frontView.state(t.input).status === "ready")) setBack(undefined); + }); + return { io, runtime, tiles, labels, frontView, backView, info, online, status, mode, setMode, query, setQuery, submitted, results, places, selection, setSelection, pin, menu, menuIndex, + shift, symbols, front, back, camera, saved, typing, listing, rows, selectedIndex, select, saveCurrent, lookAhead, search, openSearch, go, zoom, key, dismiss, runMenu, + clearBack: () => setBack(undefined), + diagnostics: () => ({ frame, pending: io.pending(), resources: runtime.stats(), tiles: tiles.stats(), camera: camera.view() }), + }; +} +export type MapModel = ReturnType; diff --git a/app/saved.ts b/app/saved.ts new file mode 100644 index 0000000..c1d4e37 --- /dev/null +++ b/app/saved.ts @@ -0,0 +1,69 @@ +import { createSignal, createMemo, onCleanup } from "solid-js"; +import { createResourceRuntime, createResourceView } from "@pocketjs/framework/resource-view"; +import { offloadResource } from "@pocketjs/framework/resource-offload"; +import type { offload } from "@pocketjs/framework/offload"; +import type { Place, BookmarkPage, BookmarkCommand } from "../shared/types.ts"; + +export type MapMode = "map" | "search" | "results" | "about" | "saved" | "name"; +export function validPlaces(rows: unknown): rows is Place[] { + return Array.isArray(rows) && rows.length <= 5 && rows.every(p => p && typeof p.id === "string" && p.id.length <= 80 && typeof p.name === "string" && p.name.length <= 36 && typeof p.detail === "string" && p.detail.length <= 60 && Number.isFinite(p.lat) && Math.abs(p.lat) <= 90 && Number.isFinite(p.lon) && Math.abs(p.lon) <= 180 && Number.isInteger(p.zoom) && p.zoom >= 1 && p.zoom <= 18); +} +export function createSavedPlaces(io: ReturnType, runtime: ReturnType, mode: () => MapMode, setMode: (mode: MapMode) => void) { + const [offset, setOffset] = createSignal(0), [selection, setSelection] = createSignal(0); + const [name, setName] = createSignal(""), [editing, setEditing] = createSignal(); + const [busy, setBusy] = createSignal(false), [error, setError] = createSignal(""); + const [deleting, setDeleting] = createSignal(), [modal, setModal] = createSignal(false); + let target: Place | undefined, returnMode: MapMode = "map", request = 0, last: BookmarkCommand | undefined; + const collection = runtime.createCollection({ key: (offset: number) => String(offset), maxEntries: 4, maxViews: 1, maxDemandsPerView: 1, + maxCost: 4 * 8192, cost: () => 8192, maxResponseBytes: 5000, retry: { attempts: 2, delayFrames: 60, maxDelayFrames: 120 }, + load: offloadResource(io, "bookmarks.list", offset => JSON.stringify({ offset })), materialize(raw: string): BookmarkPage { + const page = JSON.parse(raw); + if (!page || !validPlaces(page.items) || !Number.isSafeInteger(page.offset) || page.offset < 0 || page.offset > 995 || page.offset % 5 || !Number.isSafeInteger(page.total) || page.total < 0 || page.total > 1000 || page.items.length !== Math.min(5, Math.max(0, page.total - page.offset))) throw new Error("Invalid saved places response"); + return page; + } }); + const view = createResourceView(collection, { demand: () => mode() === "saved" || mode() === "name" ? [{ input: offset(), priority: -10, pin: true }] : [] }); + const page = createMemo(() => view.value(offset())); + const selected = () => page()?.items[Math.min(selection(), (page()?.items.length ?? 1) - 1)]; + function open() { if (busy()) return; collection.invalidate(); setSelection(0); setOffset(0); setMode("saved"); } + function begin(place: Place, rename = false) { + if (busy()) return; + target = place; returnMode = mode(); setEditing(rename ? place : undefined); setName(place.name); setError(""); last = undefined; setMode("name"); + } + function changeName(value: string) { if (busy()) return; setName(value.slice(0, 36)); last = undefined; setError(""); } + function perform(command: BookmarkCommand) { + if (busy()) return; + last = command; setBusy(true); setError(""); + request = io.request("bookmarks.command", JSON.stringify(command), result => { + request = 0; setBusy(false); + if (!result.ok) { setError("No confirmation. Retry is safe."); return; } + try { const reply = JSON.parse(result.value); if (!/^b_[a-f0-9]{24}$/.test(reply.id)) throw new Error(); } + catch { setError("No confirmation. Retry is safe."); return; } + collection.invalidate(undefined, true); last = undefined; setDeleting(undefined); + if (command.kind === "save") { setOffset(0); setSelection(0); } + else if (command.kind === "remove") setSelection(i => Math.max(0, i - 1)); + setMode("saved"); + }); + if (!request) { setBusy(false); setError("Mac unavailable. Tap Retry."); } + } + const operation = () => `m_${Date.now().toString(36)}_${Math.random().toString(36).slice(2)}_${Math.random().toString(36).slice(2)}`; + function submit() { + if (!target || !name().trim() || busy()) return; + if (last) { perform(last); return; } + perform(editing() ? { op: operation(), kind: "rename", id: editing()!.id, name: name().trim() } + : { op: operation(), kind: "save", place: { ...target, name: name().trim() } }); + } + function remove() { const p = deleting(); if (p) perform(last?.kind === "remove" ? last : { op: operation(), kind: "remove", id: p.id }); } + function askRemove() { const p = selected(); if (p && !busy()) { setError(""); last = undefined; setDeleting(p); } } + function cancelDelete() { if (!busy()) { setDeleting(undefined); setError(""); last = undefined; collection.invalidate(); } } + function cancelName() { if (busy()) return; collection.invalidate(); setMode(returnMode); setError(""); last = undefined; } + function turnPage(delta: number) { + const p = page(); if (!p || busy()) return; + const next = p.offset + delta * 5; + if (next >= 0 && next < p.total) { setOffset(next); setSelection(0); } + } + onCleanup(() => { if (request) io.cancel(request); }); + return { page, selected, selection, setSelection, name, changeName, editing, busy, error, deleting, modal, setModal, + open, begin, submit, askRemove, remove, cancelDelete, cancelName, turnPage, refresh: () => collection.invalidate(), + state: () => view.state(offset()), + }; +} diff --git a/app/shift-lock.svg b/app/shift-lock.svg new file mode 100644 index 0000000..fbc5c08 --- /dev/null +++ b/app/shift-lock.svg @@ -0,0 +1 @@ + diff --git a/app/shift.svg b/app/shift.svg new file mode 100644 index 0000000..cebacd2 --- /dev/null +++ b/app/shift.svg @@ -0,0 +1 @@ + diff --git a/app/ui.tsx b/app/ui.tsx new file mode 100644 index 0000000..a73c368 --- /dev/null +++ b/app/ui.tsx @@ -0,0 +1,177 @@ +import { createSignal, For, Show } from "solid-js"; +import { AuxiliarySurface, Image, Text, View, type NodeMirror } from "@pocketjs/framework/components"; +import { ClassicButton, ClassicFace, ClassicPanel, ClassicSheet } from "@pocketjs/framework/classic"; +import { ResourceImage } from "@pocketjs/framework/resource"; +import { createResourceView } from "@pocketjs/framework/resource-view"; +import { createGesture, createDragFilter } from "@pocketjs/framework/gesture"; +import { simulationHz } from "@pocketjs/framework/clock"; +import { onFrame } from "@pocketjs/framework/lifecycle"; +import * as hot from "@pocketjs/framework/hot"; +import { createMap, MENU, type MapModel, type Layer } from "./model.ts"; +import { project, unproject, scaleBar } from "./geo.ts"; +import type { Place } from "../shared/types.ts"; +const box = (x: number, y: number, w: number, h: number) => ({ posType: 1, insetL: x, insetT: y, width: w, height: h }); + +function TileLayer(p: { s: MapModel; back?: boolean }) { + let world: NodeMirror | undefined; + const layer = () => (p.back ? p.s.back() : p.s.front()); + const resources = p.back ? p.s.backView : p.s.frontView; + onFrame(() => { + const l = layer(); if (!l || !world) return; + const view = p.s.camera.view(), scale = 2 ** (view.zoom - l.level); + const worldWidth = 256 * 2 ** l.level; + let offsetX = l.originX - view.x * 2 ** l.level; + // Rebase at the viewport, including the nearest copy across the date line. + offsetX -= Math.round(offsetX / worldWidth) * worldWidth; + hot.prop(world, "translateX", 200 + offsetX * scale); + hot.prop(world, "translateY", 120 + (l.originY - view.y * 2 ** l.level) * scale); + hot.prop(world, "scaleX", scale); hot.prop(world, "scaleY", scale); + }); + return + {tile => resources.state(tile.input)} fallback={() => p.back || p.s.back() ? : + + + } errorFallback={() => Tile unavailable} />} + ; +} +function PlaceRow(p: { s: MapModel; place: Place; index: number }) { + const unicode = /[^\x20-\x7e]/.test(p.place.name + p.place.detail); + const image = createResourceView(p.s.labels, { demand: () => unicode && p.s.listing() ? [{ input: p.place, priority: -5, pin: true }] : [] }); + return + {p.index + 1} + + {p.place.name.slice(0, 36)} + {p.place.detail.slice(0, 43)} + }> image.state(p.place)} fallback={() => } /> + ; +} +function SearchResults(p: { s: MapModel }) { + return + {p.s.mode() === "saved" ? `Saved places${p.s.saved.page() ? " (" + p.s.saved.page()!.total + ")" : ""}` : `Places: ${p.s.query().slice(0, 32)}`} + {(place, i) => } + + {p.s.mode() === "saved" ? p.s.saved.state().status === "pending" ? "Loading saved places from your Mac..." : p.s.saved.state().status === "error" ? "Saved places unavailable. Reopen to retry." : "No saved places yet. Use Save view." : p.s.submitted() && p.s.results.state(p.s.submitted()!).status === "pending" ? "Searching with your Mac..." : p.s.submitted() && p.s.results.state(p.s.submitted()!).status === "error" ? "Search unavailable. Edit and retry." : "No places found. Try another name."} + + ; +} +function Context(p: { s: MapModel }) { + return {bank => + + {bank() === "places" ? "Places" : "Map controls"} + {(name, i) => + {name} + } + D-pad: choose A: open B: cancel + + }; +} +const LETTERS = ["q w e r t y u i o p", "a s d f g h j k l DEL", "SHIFT z x c v b n m .", "123 - , SPACE"]; +const SYMBOLS = ["1 2 3 4 5 6 7 8 9 0", "@ # / ( ) : ; ' ? DEL", "SHIFT ! $ % & * + = .", "123 - , SPACE"]; +function Keyboard(p: { s: MapModel }) { + const [pressed, setPressed] = createSignal(""); let root: NodeMirror | undefined; + const keys = () => (p.s.symbols() ? SYMBOLS : LETTERS).flatMap((line, row) => { + let x = 6; return line.split(" ").map((value, col) => { const w = row === 3 ? [36, 28, 28, 216][col] : 30.8; + const key = { value, x, y: 41 + row * 22, w: w - 2 }; x += w; return key; }); + }); + createGesture({ surface: "auxiliary", region: { node: () => root }, onDown(c) { + if (!p.s.typing() || p.s.menu() || p.s.saved.busy()) return; + const k = keys().find(k => c.x >= k.x && c.x < k.x + k.w && c.y >= k.y && c.y < k.y + 20); + if (k) { setPressed(k.value); p.s.key(k.value); } + }, onUp: () => setPressed(""), onCancel: () => setPressed("") }); + return + {k => + {k.value === "123" && p.s.symbols() ? "ABC" : k.value.length === 1 && p.s.shift() !== "off" ? k.value.toUpperCase() : k.value === "SPACE" ? "space" : k.value}}> + + + } + ; +} +function Deck(p: { s: MapModel }) { + let pad: NodeMirror | undefined; let dy = 0; + const filter = createDragFilter(); + const [touching, setTouching] = createSignal(false); + const typing = p.s.typing, results = p.s.listing, saved = () => p.s.mode() === "saved", naming = () => p.s.mode() === "name"; + const blocked = () => !!p.s.menu() || p.s.saved.modal() || p.s.saved.busy(); + const top = () => typing() ? 136 : 40, height = () => 194 - top(); + createGesture({ surface: "auxiliary", region: { node: () => pad }, panSlop: 2, + onDown() { if (blocked() || naming()) return; setTouching(true); dy = 0; filter.reset(); p.s.camera.beginDrag(); }, + onPanMove(c) { + if (blocked() || naming()) return; + if (results()) { dy += c.fdy; const step = Math.trunc(dy / 20); if (step) { p.s.select(p.s.selectedIndex() + step); dy -= step * 20; } } + else { const delta = filter.update(c.dx, c.dy, 1 / simulationHz()); p.s.camera.drag(delta.dx * 1.45, delta.dy * 1.45); } + }, + onPanEnd() { setTouching(false); if (blocked() || naming()) return; const v = filter.velocity(); p.s.camera.endDrag(results() ? 0 : v.x * 1.45, results() ? 0 : v.y * 1.45); }, + onTap() { setTouching(false); if (blocked() || naming()) return; p.s.camera.endDrag(0, 0); if (results()) p.s.go(); }, + onCancel() { setTouching(false); p.s.camera.stop(); }, + }); + // Build fixed controls outside the outer wrapper's mount stack on QuickJS. + const keyboard = ; + const search = typing() || saved() || p.s.mode() === "about" ? p.s.dismiss() : p.s.openSearch()} />; + const padView = + {naming() ? p.s.saved.editing() ? "Rename saved place" : "Save place to your Mac" : results() ? "Choose a place" : touching() ? "Moving map" : "Map touchpad"} + + + {results() ? "Slide to choose; tap to open" : "Drag to pan. Flick to glide."} + {saved() ? `Page ${Math.floor((p.s.saved.page()?.offset ?? 0) / 5) + 1} of ${Math.max(1, Math.ceil((p.s.saved.page()?.total ?? 0) / 5))} Left / Right: turn page` : results() ? "Or use D-pad and A" : "The upper screen follows your stylus"} + + {naming() ? p.s.saved.busy() ? "Saving on your Mac..." : p.s.saved.error() || "Name this location, then tap Save" : "Drag here to move the map"} + ; + const plus = saved() ? p.s.saved.turnPage(-1) : p.s.zoom(1)} />; + const minus = = p.s.saved.page()!.total : results())} onPress={() => saved() ? p.s.saved.turnPage(1) : p.s.zoom(-1)} />; + const left = naming() ? p.s.saved.changeName("") : typing() ? p.s.setQuery("") : saved() ? p.s.saved.begin(p.s.saved.selected()!, true) : results() ? p.s.dismiss() : p.s.go(p.s.pin())} />; + const middle = saved() ? p.s.saved.askRemove() : p.s.saveCurrent()} />; + const right = typing() ? p.s.key("GO") : results() ? p.s.go() : p.s.saved.open()} />; + const sheet = ; + return + + {search} + + {typing() ? `${(naming() ? p.s.saved.name() : p.s.query()).slice(-31)}|` : saved() ? "Saved on your paired Mac" : results() ? p.s.query().slice(0, 32) : p.s.online() ? "Explore with your Nintendo 3DS" : "Waiting for paired Mac"} + + {keyboard}{padView}{plus}{minus}{left}{middle}{right}{sheet} + ; +} + +export default function MapApp() { + const s = createMap(); (globalThis as unknown as { __map: MapModel }).__map = s; + let marker: NodeMirror | undefined, bar: NodeMirror | undefined, scaleText: NodeMirror | undefined, zoomText: NodeMirror | undefined; + onFrame(() => { + const v = s.camera.view(), pin = s.pin(); + hot.text(zoomText, `z${v.zoom.toFixed(1)}`); + if (pin) { const pos = project(pin.lat, pin.lon); let dx = pos.x - v.x; dx -= Math.round(dx / 256) * 256; + hot.prop(marker, "translateX", 200 + dx * v.scale - 8); hot.prop(marker, "translateY", 120 + (pos.y - v.y) * v.scale - 22); } + const scale = scaleBar(unproject(v.x, v.y).lat, v.zoom); hot.prop(bar, "scaleX", scale.pixels / 70); hot.text(scaleText, scale.label); + }); + const deck = ; + const map = + + + ; + return <> + {map} + + Pocket Map + + z14.0 + + + 500 m + + + + {s.status().slice(0, 35)} + + + + + + + Pocket Map + {"Stylus / Circle Pad / D-pad: pan\n+ and -: zoom around the map center\nY: search X: return to selected place\nHold L: places Hold R: map controls\n\nMaps: OpenStreetMap contributors\nosm.org/copyright | Tiles: OSM DE\nPlace search: Photon by komoot"} + + + (c) OpenStreetMap contributors + {deck}; +} diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md new file mode 100644 index 0000000..14008be --- /dev/null +++ b/docs/ARCHITECTURE.md @@ -0,0 +1,129 @@ +# Pocket Map architecture + +## Ownership + +**The 3DS guest has one JavaScript thread and no network or filesystem calls.** +Its state consists of a camera, two tile-layer descriptions, a bounded search +page, local keyboard text, saved-place pages and a selected place. Solid owns components and +subscriptions. Continuous camera movement writes paint transforms through +PocketJS `hot` APIs; a tile window change updates the component tree. + +The native offload worker owns sockets, the SD pairing-key read and binary +reception. The paired Mac's worker owns HTTPS, SQLite, PNG decoding, optional +Unicode label rasterization and R5G6B5 packing. Provider socket callbacks pass +bounded requests and replies; they do not execute these capabilities. + +## Working set + +| Budget | Limit | +| --- | --- | +| Active resource requests | 3 | +| Resource starts / materializations | 1 / 1 per frame | +| Tile collection | 40 entries, two view owners | +| Tile demand per view | 16 addresses (up to 12 visible + 4 look-ahead) | +| Native image staging | 8 × 131,088 bytes plus metadata | +| Native image envelope | 16–256px power-of-two sides, two bytes per pixel | +| Native image uploads | 1 per frame | +| Places per search | 5 | +| Saved places | 1,000 on Mac; four five-place pages cached on device | +| Saved-place name | 36 UTF-16 code units | +| Query text | 80 UTF-16 code units | +| Unicode label collection | 5 × 256×32 images | +| Mac concurrent tile decodes | 3 | +| Mac decoded-image cache | 64 entries, honoring HTTP expiry | +| Mac HTTP cache | 2,048 bounded responses in SQLite | + +The image collection reserves 18 bytes per pixel plus 512 bytes per entry: +native staging, old-plus-new core/GPU storage, the tiled upload scratch buffer +and the serialized ticket. Forty steady resident 256px tiles account for +about 15 MiB of core R5G6B5 plus GPU RGBA8 pixels; native staging, upload scratch, +fonts, UI nodes and JavaScript use separate memory. This is an admission upper bound, not a claim that +every tile allocates that amount. JSON responses retain the 4,096-byte record +and 2,500-code-unit payload limits. + +## One tile's lifecycle + +1. The camera's current viewport produces near-first tile coordinates and + up to four extra neighbors using a 64px margin and up to 128px directional + lead (0.3 seconds of recent movement). Visible entries are pinned; extras + have lower priority and are unpinned. The map + wraps longitude, clips polar rows and attaches the provider source identity. +2. `createResourceView` declares desired keys. The collection merges both zoom + layers' demand and reserves entry cost before starting an offload read. +3. The Mac resolves the named tile capability to its configured URL. It reads + a fresh cached PNG or fetches one with HTTP validators, checks its 256px + envelope, decodes it and packs opaque R5G6B5 pixels. +4. The 3DS worker receives binary pixels into a free native slot and publishes + a small ticket. Socket reads pause when staging credit is exhausted. +5. The scheduler materializes one completed resource per frame. The native + upload consumes no JS pixel array; `ResourceImage` replaces its fallback. +6. `releaseResponse` returns staging credit. Texture disposal waits until + cache eviction or invalidation with value removal. A cancelled or late + response also returns staging credit without an upload. + +**Rendering a resource does not request it.** Demand, subscriptions and +ownership have different roles. An old zoom layer retains loaded resources +while the new layer demands current tiles. It never requests an unseen parent +pyramid or downloads a city in advance. + +## Motion and recovery + +`createTileCamera` stores level-zero coordinates and log2 zoom. Dragging applies +screen-space deltas at the current scale. `createDragFilter` filters cumulative +touch travel with a 1px hysteresis and up to 3px additional lag. Fast motion +reduces filtering; stationary frames settle release velocity. The 1.45 touchpad +gain maps that 4px input-space bound to 5.8px on the map. Circle Pad movement approaches a +velocity; release follows exponential inertia. Zoom runs an anchored 180ms +transition. The integrator gives matching held-input/fling distances at 30 and +60 Hz. Mercator projection is application code. + +Tile positions are rebased near the viewport before reaching native float +transforms, including the nearest world copy at the date line. Tile enumeration +has a hard maximum; a mismatched old level cannot create an unbounded loop. + +On connection-generation changes, pending reads are cancelled and current +demand is revalidated. Resident tiles remain visible. An explicit source change +clears tiles, because the old source is a different identity. Exhausted tile +retries have a visible error fallback and an R-menu retry action. Search errors +and empty results have distinct messages; editing and submitting retries a +query. Local camera and query changes never wait for responses. + +## Framework additions + +PocketJS receives binary image responses, native staging ownership, the +`releaseResponse` cache hook, `createOffloadImageCollection`, and the camera / +visible-window / look-ahead functions in `tile-viewport`, and `createDragFilter` +in `gesture`. There is no OSM, Photon, Mercator, +search-history or map-service policy inside the framework. These APIs can +support image pages, photo renditions or diagram tiles using different keys +and demand plans. + +The image extension retains offload's authenticated LAN connection and JSON +control frames. It does not turn the older companion SVC socket API into a +worker API. Other native hosts still need to implement optional image staging +operations; an in-process iPhone provider is not part of this implementation. + +## Saved-place commands + +A fourth resource collection owns four five-place SQLite pages. Selection, +name editing, pagination and delete confirmation belong to the app controller. +**Writes bypass the resource cache.** `bookmarks.command` carries a bounded +operation ID and typed save / rename / remove payload. The Mac commits the +change and its receipt in one SQLite transaction. Repeating that operation ID +returns the stored result; using it with another payload is rejected. Receipts +remain after deletion, so delayed save retries cannot recreate deleted data. + +The UI waits for confirmation before changing its saved list. Missing replies +leave a retry action which retains the operation ID. Cancellation of that UI +cannot roll back a completed Mac write. Successful writes invalidate saved +pages; deleting the last row of a page makes the provider return the preceding +populated page. User data lives in `places.sqlite`; HTTP-cache eviction never +touches it. The Mac performs all SQL work in its provider worker. + +## Scope + +This app implements map browsing, place search and saved places. It has no GPS location, +turn-by-turn routing, satellite layer or offline-area downloader. Cached views +are a latency optimization. The public demo services are replaceable through +host configuration and have no availability guarantee. Network isolation and +bounded work do not establish a hardware frame-time guarantee. diff --git a/docs/VALIDATION.md b/docs/VALIDATION.md new file mode 100644 index 0000000..a4b0af5 --- /dev/null +++ b/docs/VALIDATION.md @@ -0,0 +1,50 @@ +# Validation + +## Local execution + +- Eight app tests cover Mercator wrapping, immediate controller motion while IO + waits, keyboard submission, menu ownership, HTTP validators, cache limits, + duplicate requests, pixel order, invalid image dimensions and bounded search + results, including a real Bun HTTP 304 cache revalidation. Saved-place tests reopen SQLite, replay committed writes, reject + operation-ID reuse, paginate, rename and delete. TypeScript checks pass. +- The compiled guest ran 1,591 simulated frames against a synthetic provider. + Replay covers real auxiliary hit testing, keyboard input, result selection, + placing a pin, touch inertia, animated zoom, 180 frames with replies withheld, + disconnect/reconnect, date-line navigation and menu presentation. +- Observed replay maxima: three pending guest requests, 40 resident tile + entries and eight native-image staging tickets. Staging drains to zero after + navigation settles. Generated receipts are in `dist/qa/replay.json`. +- Live OSM DE tiles and Photon search passed through the same compiled guest + and resource API. Captures in this README are from that Wasm replay. The live + check requests one viewport and one submitted query; it performs no pan scan. +- QuickJS passed 1,084 frames with a 128 KiB stack, including offline mount, + resource reveal, sustained panning, both zoom directions, local typing, + search, place navigation and reconnect. Texture tickets drained to zero. + +## Native boundaries + +The 3DS package builds with the pinned PocketJS ARM toolchain. Framework tests +exercise production `offload.c` through POSIX socket/thread shims, compare all +bytes of a 256×256 image, verify staging release and reconnect after realm +reset. ASan/UBSan cover 4,000 concurrent images with bounded credit, malformed +envelopes and token reuse. This verifies transport code; it does not emulate +libctru or PICA200 timing. + +The production `.3dsx` and an app-specific pairing key were uploaded through +ftpd and read back for equality. The install receipt, package digest and target +path are recorded in ignored `dist/qa/deploy.json`. The slot is +`c7771f0167312c63`, derived from `dev.pocket-stack.map`. + +**The physical device has connected and is returning frame telemetry.** A +stable interval reported 119–120 frames per two-second sample. The earlier +session recorded CPU frames above 16,667 microseconds and a lifetime maximum +of 263,387 microseconds. These counters do not identify which input caused a +frame or prove continuous 60 fps. The first device build remounted overlapping +tile components at window changes; the revised model retains their identities. + +The user physically confirmed the first build was usable, then requested +more caching, drag smoothing, layout changes and saved places. The revised +replay covers those flows, including lost-acknowledgement retries and a resident +prefetched tile becoming visible. Physical gesture and frame-time validation +of this revision remain pending. Build, native transport, Wasm visuals, device liveness and physical +input remain separate evidence. diff --git a/docs/images/delete.png b/docs/images/delete.png new file mode 100644 index 0000000000000000000000000000000000000000..1160479d005c91e4ada9d0bc4de44486e3b96c48 GIT binary patch literal 21664 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 sZVUe3&kOo6g*qX_3hfawE0?>=(oAE6JMTL1t6 literal 0 HcmV?d00001 diff --git a/docs/images/keyboard.png b/docs/images/keyboard.png new file mode 100644 index 0000000000000000000000000000000000000000..d8cf726328daa334aecaa236f89d81f5dddd57a6 GIT binary patch literal 194838 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 E14m?Txc~qF literal 0 HcmV?d00001 diff --git a/docs/images/map.png b/docs/images/map.png new file mode 100644 index 0000000000000000000000000000000000000000..211f0fd618d2e33ce5f0ffd9186621632a168dd4 GIT binary patch literal 194343 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 literal 0 HcmV?d00001 diff --git a/docs/images/saved.png b/docs/images/saved.png new file mode 100644 index 0000000000000000000000000000000000000000..06af7f3cdfd6aca3b86109b851005830a34e72b3 GIT binary patch literal 22532 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%0AHus8@`qc>cU`{g$gdO-1JspK8n;1=CwqwVQ)q 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 literal 0 HcmV?d00001 diff --git a/docs/images/search.png b/docs/images/search.png new file mode 100644 index 0000000000000000000000000000000000000000..c06c732d4eb630dc390db7ccc0148a53f9323d2f GIT binary patch literal 62827 zcmZ5|WmsHIvn>`F++nc6o#5^kJP=%h4G`Sj2@b*C-Q9z`2Z!M99^CEn<~`5%oqK-F zpWgfFUDaJxUA1cUgnp5iL`J|zfPjENmX;D%f`EXGe*bL%VBbf=GWd`oAZ}Qt#YI$H zAy3-j9JD2WQib@`yy=rWlXI>OjHflWR_RTgv>mz~r8t`x{fTM$s%tLIo_io26E8J| zNg?7#fdqf{xqG=(6q4qw{cbG}p->;-w=Q9vgP=-6NUNxF*UGgezM8gYv{!PLc~;o$ zCX17()(tR(hJ{9g1tKv6U3HP-M~y-L=mW6-4(KzVw*hIS$Ev>n-=R^)|NB;GK~mTM znJd5q=Yk(2>xx8hzYs&Zz(tPWGj*0M7kN1HKVN&FywTq`R^I@!Rhpe>JZ?Y@<1-w> z^aO7I=_jH8^-i!ahMpy;byzJQ-0p@`y8cYTwBugp=rJ|%pU*v?g0uTDQ+lmyv01QU zCFOt0G^SanF@+9@*u~I{`s!Q>RPFpSBaZXgZ)r4#Yxd4`l>id_D?yMihKVUo>##G7 zf#9`ZHC93AGWw8pOM!&YYh#wzYxwiMg2@yw-8#pcE~Prk)Kf061}6URyRhtzcoy&6Bb;KTk5_nBnr4Ll&K(o=8E$`^Gxk8-_4=n)AlR}?e9%`=U(eAN-LVU6DxE2y*M4Ho&SuvUn8j-8_a$)vQ{)4Ks4(|(Zc z@uzGY{l4C-BWG6P0o7sUY~)U_xqINl^PtVoDNl;@gU2E+c_ktnPerx(qAx=X zL~wP{hdz%Qauvx_RK=`oc|KEph2746VroX;{yN)XSrzizrpS5cI_{d{PdgL+mDO+o z>7g`FK9bTzdM2S_G%JGBnnhan1rJev2HjU9^(WSzh40;6W!+ua&M#~*qCK~%ojEqC z7$Hl#o>{0@H}}^ktIs$2J@V52`Q&yxp7dTB+qJo#JUYt->tXSx8FnXB%k6J9U(fvC z-OWvAKQZn=+}q`V^Rq*qcerk+)3dJNdhtT4Oa5}fVku#4CV;2v6mxgm;lby6PP6Ul z8zr`qcOsy2hJ7bV+r^%p@28kG{Qd~qf#(COv@0XBw8CXf^{+}Z&ztO|#FP=qUqgo! z;_4b|k=l)=aDSuAvn{i&TN|j;hFdBy{fuM1cqpJzuoI?oUci9$e;5b>fyUZWRUQT0Ere$r$=a{N_vK!Kd-VUv1h|1YUk$pMx*?6mwefIJiozlm%qeGOpq0u zMh#=Qk2*FwpNV3eVi$5hmg@*lm&Z`kPy?s7Kl}V^LXG~AIpe`Dk=l~m-)%?kU!^|^ z@;D@AHbzKY97m0B^)+bG!F6~?cT%}?9#h(}I?xb1SGmO(dQG(?(v&NnQ1PMnS=Xlh zu`3}zQ)!e{UL_ypo7P@_E zKTE}}YwPf8zEgu5E!L;eIhuWkUlL7R2!7(-R1{W@viEnmiuM~&nRZ8Le)G^U3n`=U ztdG16{*BWcgRj z*DB%-Ehi>{tU1?<+n8fhyu>zJ9a*D2fODLU7)k3PC}H6W#jeQlZ8zge6VB%xhfxJ( zL(;}Lt7rIOkG=E$+FddAYec#y4@G$XN1L=!-uv~ezJO_DU&iQ(w?(cScESD8sP&_4 zH>pLQ7j<(9XDi9dXYCYmdow9_rNMMTrL}$aw5yAcdB57^MV<4l1CS6;tCQX${~m*{ z&dgm~r59Is^4P;^a7+SmdsTXCtDJ9p*Hu1_I4<~guRq8gHeN8fu3DoZ7*G#mfxFYu*Otv?#ce{MX4$}W zE@b*2N6${5d<2PT)A~+#I}HPBApId>p_ve&DMh`|T0_@P*I9I}?)Ih0Q=QLBqhi_@ z^}py3V*(7>V7dM|_Ma!2zpz#ye~%$9M1CwBbAxi5bprp-Bxx*PSW7Pa|9RwIDEEIK z^{77l-xQ!4TbKEtI05mG2uQG*xX_e&tf+sFsQ($92=m35>7sR&v+sMB&(8zr_jva~ zf%-h<#aB@Jo>BTvsq*Et?sv)VEn3ld?1)QR$E4~Oh5~w|YJ#FOvBYgUP^YeySl5@nx4 zic3ZflY%;Wc$q4U$59>eQ_IZfX@VJDjs{#7?l3;{#dtXnyL2BrTvZiziy>-4pS}4rv zvuR!gbLsYO4@Pwp;0;XmN?sT_VXNigv2J25{kQ_0BMY+pa*w52~7 zqs3w7={qa{iSfjJJaF^lwxbc7sx1e7ZVU7qmfhh9LILasZFrs1` zwmb`sZzM1?am*?7*;|;S6r>rzKt}^KcT!xc27q%Nj)jE<_w|Dv`)`4snIeni3=4nP zV%Vb+mhuV#5!HSo&&SQ8bB}gFAQZR57I(|i*Wz};=X8L9+A!dPL#*^7=E5aRy$D zEdV10rt@v}ECxXNKKOy2>Z)Js0_ieXoa(PXB zgbRqY*jA$1M<#f%CDYVkpR6Kk?vR&^7!i*e5dv*-2ku&t+bt=9k8(mzP75_U%V_?< zz{og#E8un+uoa_k%*hg_PXlON&Sv2$Q?Ew3KU3|rXbmE?4>ve3=)E9wIy7M zQ9Ag@_2Zh##DlqC2p+PvX2`^fl5QA6Vjxn~f-d;WVnCSs#MVmS%m%`dz5}OlDGzF1 z3HIGt#voVHgn?;2l#&(gA7}3$e9+iU>K>@rH!gN%xkzIbsM!ZrL2oKNqIYRIKz#9C ze}sCj`JD0-s?;=mMZFh5W;goiily+5Hsz?Ex+pa+89GX@bwf`sMh{8mcWGA0BsJKo zkqAW;)QtA_4LqHLIb7MIfyhT`bh@uvQ(Rq83Jjvh@qi4O88)-fc8-e>bS<|dR->CV0J;uUvEBc~~KgOpPCm@~=S_z1Ay4=nPiZuVI zHKt7y^=;QY8NXFOR!#|nmc3S!RRq3|WKWb<-+uzs4J-p?v=i^W)d%jf^ld={c-b|i z25N-6I+%k;w_p{^1vLAor!kCY>OukyZJV{Lflkb&@zqB=%*WX0!O!gNGY0;u;)evgNPbw={0H3N86iQc&0o=K?$Hy_`J^Ar(cNGYlchXrJgOaYIEJG`ln~ zSE;@_J^JpC9BicC?Y&KjLu5y%pE+%9P|nav7(-jrbT5?O#;K7v?srWuMvDF4o+rV- z=T(%Tq?zzHoo__R{}jO}>A2w*92?2Mru};QR@~(Aga`G|Kj8xzwkSM<{)7$%FPV!K zb`x>a;hq=(#uSN) zJY_usyd3ODLL5voMq-Q@;GPn^5n-I$;OG81-=Z>UhHr_{$lGV>4S!NE$@`1s4g z@j5EX84Y`>lE&x8YI8FhDprT>FwA~Sp_6fYsaX?dQr>`?&==q~sO#W>_FSUMm(3g9 za?RH>vyTCB8xxLnn^S~(N0ffEcl$!P3XN1)N_{x^6ASW#3i*Ak*r(kB+@S2K^**Wf zf{bA?{(zjEndlKFk)es$L3LbtLm3t5h8!fFRU1RkYkIlR$UW(uU$YL$nH{Ljf2jU6 zo(#UU@BuTdyZj4Vi_K{zC4B_)w{@!38+yuPv)gNMaL3boFM0>RxL@%G!98wnji9wF zhV6{O_WfZer$X;8N$8^w;p6&`#~`(0s|1^$PN{(h>QtlynxZBBZZRqkWL3_xhfFi zX)hp4^4VX*@t$P@oqSc$Pmab<#ez7tkzk|q7On6Xm6l!4cREsB3`TRzDQqA&-?S+t@x=rB~G-f>;bzA|Zz5Tyc!GXe^ng`Am>={pN_q7lqOtz%=; zkfPdPIlgcOLmHQT@a`m5AZ8+ulkeSi7O9%=G5tNmi$?wFk~ba2{qxqf`+J6({<&a- z#WW}8-1I5bVaAN(_hz6Mqznm#T$w7g!u;iaA0Cr2D|1TtV$qr74~*08LHgumVE_Fj zM82{m4U9H0o;BIX^PoQtNW3RZ+SvOi9BeNm;t`2c0D#3KwyHp$l%k5c=3&OXCW%4H z;UDUK*)U2J_ME^7(c+apu4NTMMRwz*dSpj9LTg8%cBI2=bEapf!~2{RLaiSghGvhq zIc@C0psmIw=guKxqYLX}4x?VBGq6BG;BvMSEYdB>%L(V7t}r4ep8lojx(ROse0YI@ zZ-IX?zU-6Jf;$aQv3HZ4hP(s6^Lm=*1~sf>Llv#}x|Q^M5eGwx8ST5i0hA<4mS4Y- zuY6H&*6TC%IrqD4W8hwks+ag%8Fie!n(FHBZ?`s8q*w@GdrK%dA-?Z-Lia%DG;A?w zulvVmp0?MKd359;T5$9lqV!jBl1*k%6@#HQ7{$S%PGg8+(q3I%t>$M-P(uN=6m0n? zm`e>kxZX*gWMnO1yn*{0kaA{Hs*pB^UsuytMEZ{pqnr$6IxpqvBJk68w8QZv-?h-y z-NDKky04O0$DFDPCelBW}1NrXPX4R(l1D<}2DH()treC-ZFN*}_0m-2jo zuC|?G3dT{1G#ml4TnQw1oQrj5;QHKa0vN$H7xj2DX^kFCiXN`ici%#1)E$it7FJTQ znqIu&>`UjRq2^=Z@J3h8C7;Awvb}k9i%-mi_IZTdNlh!ZyhmH@Ehskgg7Ke)DbWtN zUE>W$V&B?~NNcivC1fNP`Y<+&Fl3{W`{w+?TDK{v&>^WOmSd{5F}372f~_=Sdmt7|6eWc+HG1t${I(`O)c%0b>XlJkWYKb;`8%Svw>}p zN%B7e)uGF-*6jiVU*T`DgBA?Nh z`7MJi%5wn+v-rtOYNDjc0n$~zV+Ov1`*~cwa{MAh2FBhX*)ZAbJqoUcr6q<$wIZ%e ze5IF-us>q7n98}#X8F~{we0|ZZ9rT)YDP3_o;YCM-DWr!Z3ax4rHWW*iI3kL&l~8< zkHX`Fz?gvnBErMBBi(Z9HvUbX626aYsqS#@YKC>O0W`42GbTspmbQ`T50r97!7-!; zspyPDDLH+>S)@qkg%`EPe1=3^DFaie$0jTE#UMOv{4SwM2_$kK9Tb(4gaRy$*&fYa zn?c00gL=2?NjIEGPi`hN6=N#oVm(?~el)wnglYg|z5txdh>Yv-=-^T1<6>ShsNY=8d}HOvHpFKAQ(9&v1@I$w5*4rX2 zk}5?R_j*m^4c+aZo8bevPsU(a`6vB_I$t=wNRqc~&u8YnQ>mjH*S&C0ks|EWXG(AT}%)t;-MjnYYi32~W z0={vg9WBQS51EQ_Yr#caAlzSW19wlv-VOwj!a;op2T2D6%Lf-|FKUt;ynG$m;$XB$ zqcfdh@t8and8eE_6Mx~oBnfbXdS0*->(dwVtsW9GgKwZktw-voPVKKrt9eEls;?Yk`m%~cB7yYrmkvnaL1g)PN2lFL4MVT}O_=%M;+wekSl>&Bf&7Wy9 zjDCLHfRhc-{KzWaCed__;2KWXWF^y-2z}l+cAlboj?ZChifwDUYkMeuel%N6|KWG0 zJ34N9jiSmtKv9)md{Kb2)SPOwmS>}e56qcDBXTa;Y-(CD`0{I+rd{(#>5&Z5jf?*v z$XAXXnKTQjD&o5UX8`Rjw-;1KMp~dm!f8ax4y&sbugp)~vdHnAg;`cDxFucWnvCRe z7fNVv*HM`x$8>XaqJ8SOr1evO9ok?`+CUKsm@KwP+CPAF93o2u!4*ctCGuXH8;7pX zmuP@{G=#@X@lC|Q;$8~*qyvYqqs#;i)yK28<{XZu3`Sf%XUw9M+cS;|^O=)ZDPI7J zRT)dQZKdgghaBu@dH39RH$0wRn`F~<${X;V5+uwaQuV}{`u`k!C^@c}dr5s7U%v(^ zm5I;3*lV|XBdS;FN?2HYq>L^JWs$R&yn=~srE2dEl0gd;%Ru{zK zKEml5tWkWP6MR26^l*H5Bm>at!!gWubWK^zhR(u)?}2&t**$M=IjPA>D1Tt{nF+>U{ z?1FhB&~UQ67f=E^=Am6JlcrevN9%;i&rv6jg&UZu`cYe;GZ^{VYJIakP^m7VWG)jw z=aUO@CBhm67a?--!nVJ;`s}y%+JSo-Q*C7MRPj*Q064vE{E=h5T(U!v3?PT zt~}z;O!Jx|HFoWKMr1ET#%SxYr+d~}BFQ)4o8{n45pYN)a&$Xyqnj(}^%RIvcMIuB z5N~YHTcAJI68`6KrjyZeJ@7`I0UH^Spyc?3_dA~+%UJIL3h`AW9` zprh+h&~FcSjTf`8t**A0{MLjI7+dsrG@%r-$LPFo5UJC(3~td=7-5i+!e~%Y#9js; zKpb4zKl7j~#4M|S5>%4qR_Az$2R#0fuSfjmSeqfAJ2CP{c#IcT&;@9mJ(fpJ+N_Lx$4-1< zhpwGOEWErFF(ra?r1h1hoF&)E6X`}L!*pMEl9nr5vZ2>AST1<{Riqx};y_y(j9Rc0 znu9`XMK20TtP~2EF2Ng}m;kfXY1A);${Ekh%EtgjWiWH+wdw>S21FQm{D-6(k`qj0 zYCP&->?mR%}AUiEi*~Hm>y=B z;PzsIP{`DG^3t@VAoLyC&8FuVs>V#IZy>n7et~}?fs27&bc=ShLQVWlWyFq?PyJ~K zrbmjSI=XEN@D>Q0{P?)}JJhbi9qnx&PRF&=I_N(Fy28J&RPqoMOniIx~2zX@O+b1s&`5c{q7U4J~lSy2=6e~QPDiK1xoD+?Z6N>+-_X}??^Xe>%P*w8PsV1U6x(&_xq(BK^!__m7KhS7{;>He zE#qTw5KSmrttmc8#86#wimprmeW>k(5vhG}ex0BCjMiwqf?2jNUM`)Nbktt(nUUU@ z9Gou-*>|rbE=a#H-G?ilO8%=ugNDtBdYVZco6S$>f~NlBbfO+E^jhvMQ~cZ=$I-KiFtLg&{)X4| zO%bdxggB46nk!b4bXcNf8@>~T1x$yOFQAs$VNd=aL-G2CvT*}9A3yh{-ryo~sTst4 z#vWT?St=G<l;{K58bE|=kYdFEBMr(;zS3_}ISFbixwKX*g@gQ=HqOSF$YbAQ3 zNQXtnr~#I9!nI+r=ztUSLL1huveW1u4Ww!o9uhR>!c^-OJ3Drl>(Wg}tnufo(no@a zb;8)g`>Z10${EEc0)HZ<2AX+(AsXF(>eUf4FH~ZW%qKN#{BayVjQH`l5U$~CD9v>gsC@|hdJ;Jyim#e z#_9%R{6=6k!@P(`)e@5l`*O4|S~tj1`-Z ze4#?CSJ?e$D)ZWDQapihQ*~)poP+2Y&CXtFtc`W6#!qKPW$g={%#jD)pz^=%(=OP5 z6#t-T#OJccU4HkKHZ(c{ceQ{+Kch8r8;&z(C;@*VQk9=8bO%15ypQ!ZBjA(ZhaxS% zkP#UV&xkfm3jN(Df4m_!0bw#J? zLPY$EFu_fj#UFu@slpQ%RHI0w%IkhxAAaBF{&Ih}J6|ED*liCZF^n^yPfntqGH4?$FJOaoz8Ztzto(lohWZci7F3d z1kdE1K3Y0d%E>?_27a`{Om>sow!hrdu@M|6)E+PLnPPRR)ya8rsh!n5(E~QBdi?9F zXTWS2QD>yWuPbqxL*nS6u7J?=u~@0u3nz@`)sTfib8dNc;VuIqA>ZhC%gtf?64pF9 zT&O>5uCGL|&q07jk`+xk;-bu^p*=cTksr#?kC9BAIqIWrK8z_YkvCYr5)wX^lp)or z2KUB=`tGdG{mmvkE6GkqfrBesnA(3Lu=?+Yrtfc%ahJqtP5Bo|D_2COqiyZe&5;F^ zB^a%*y1AG(qP~G(VhI#>#a#~dPnws`olKGwMUFlLc27Olh>o=u3ezLCy?)jrmk@`J zz?WR9@#@x(W>~5x+faW!?SBol>r=aEp53oy`)l=<`XoXDpFBtdq+FRVsPtP`zaQjO zNbNkshH94wou-*r4+c(1l2{DDG5~qeP(5N&K2KLIplfRB<`OrNuCtP4Dd^~Eit{E& zuw#At0v0`y*dLH#@JGfY(hQ|s(Fpy-smgB`%z0FlMCg$ycC%Qdn8@B>;kjxQo7sq9 zV#*Cq4#zXmuR|O%?b+G3*Y`;c#%9GHcb6Q@L;7I9n|=()iH*yak08tvygt>iiS=IM z*NbO-r^>Y}>ol6P@q~1=FBz9L;eLE4!&oKQ(EqDofN925!hR3Je-$jyphmrv)x{tt z@NF-z2@!XdHi8MVq%-SFVZD(vxXW9(7nv$Jr z8klON$S#+*HhqQi3N-@`65G5W&ZG5?no~`bxyNFM!^C{&2x`$tn-($Gvkth|9fWo& zvmuUutd>}%@X%?|mYulB*~C=)Ba`o9KQ;FZsIQ^pM4V&FtDIJNCVIPSR#&T|@27C@ z&oXsS=Y&L&fb{*#KPvMTOLCF4GtZe;b*d|2iOq4R2v?{7IIoX`b{NTnw#HxLgfB7@ znjW8Em!CwvJSY}kBcI>39wV9Ca-nLTUzRM3SY#~a%25%EGUiH^IlV-jShC3lN^^3q zo53t#G23^x_|rmFzjiEiuslMNDrA&q%v&k;3lV6g9)o`QN~$q}1T&O;HclrLyLt89 zZ{w~K1x9@FnVhI}VpDXs*PHi6Emx&6p^{mR2k)ivV{bjxql5M%AwSVonK%#*Kh?>q z(eViEXy|(VNDXxr%o3^*{Z`hp3i^R{NU^W(A;xZ9)M7omr=4+Yo>sBd@i}FAv66Y+ z`lmbS33q_yF9+<(@cX@1g>KY^$lSn}L>Y)M38XM308*t%D_{ewb?_X(eZR5ai8*{;K2AovE?tB0P<0z>xBB2$0Xt z?|rCvI}>IS@qgqQiArK=WR{c;xE5!JVjQidT~NhXz@7md8lAf!b#=ZOJ6E=p!>>tZ zpvfzM>uW&D$7xJdrOTUX=>bcYi>bm&&-4pz@kv?UlLxS1%3jTB+6Cfc!HAk} z`*ko|1U#A4(ce@*tZc7$F%SffWPj=ci_;nO#UUX&uz8)sJ)!{|$dI2l@XJsQz+|LxCh6YFz~WBSu|Im-u`8wG=&| zlOV-WUlHES41yTBuF>6|Cw+)1<-2GG8{eWDL@^z!;wE+9iw;2*H5Cy7{(y}!$>@xa z{n2f%g86-GJ|qex3fCMV7bDrboReqXqvHM=>7ih^xu}AAVh4DpSW@~}$d6mz$kSll zy$DWmMs?h(KKsC0%%k@L$nf^+XTIXwgx$x#0qHL_7~{QGtXMY-p0x~EwjPNcdM2zl zrwoGqnmrY6Ir=TkwK}TiN|0Z34N2XQOY3W@-PR7R6kIS`m3fg~a)XZ(DmiW$%gMPF zT1d@XSj4xsLaO&30?ApYOe3>&@Ux@j+M*Od&>sVohvb}qX59|t4200FLjhezT-QEs zC1_+qOlJgUHI88n2@$FOulfi5Jyoq7{YZX-EIhE^by^L!vO;!naF{fY2NE6m1!a9j z>JR)pB+=9v_jrDghY}J5`$hK^g6P!BRYei`?%dQ_Y(N$@huaI#LmY zBL*IglA9`cx4Ji1jsE|j0d3;%(T*T&V8fZ0g@qFW(geoZBvE`1cW?8Od!s&$CKL#h z_a#EDYx4F(Y@2gP5S*f>Vrci8{7Sn6V(*JUaY=cQhf#b7F~)N#MlIql&`FjyH2%I1 z`x6W+eJk`!7j56FT1$qRx)uPFNuY3mQLK@)ie$71z0f)Wa6!D!AI;3_(S9`!z$8-19hRqnW*9}S zxrC_&W{OBu^v2GGhm*Hbn4c6@ORt4JTq4opI}Bh1O-Cq2#$)eVs;==CG; z!R;X5(CsqYVIxRw^m83rm1Xd$76*P*mgGc^!@ewOJ1uz+r|tGVYyK=$jM;`AF5Wh@@bR z*-sc6!X0e~$1?050&&KvZ^o3`p)sXGKIg*o=G=0539bEh!aN|z`(q?nA@`{7AwqX( zH+XW@`+MwY4~?2%`==js{26>062^fMt}SplcLGug`^+r0s6UsgxDqda)GvO<9u5oS zB*q!INAhJJ_qPN6LznbafMK<1=&6dcBtv7wG93HT_^0>B&%&X7CW}(EW3Eo)}5^m3}(h zKP=02Oy8yk1dSoJKOc5-j2cCk?Xpc5=;$jnSW&xkGJ_1$gNI^RWiTqIC5r{^P|ker z1rz+UJb(PDQ?F|c)AoiruK7wsdWCm&u?3RSazn+0CVubtRsr!|@%@HnOaosgLtw#* z;a%U7gR~}5)6`(HK0~)gqgps2lFeJx!mxHvbRb@a1X4DjKoOTJ<|r=eqCtIjR>HVC_^R;Encca575k!7HmXpVG(^3eoz)bTayUZs z+*V=u40R&GL1>OghJq-Efj)}BqV0~I&dYORjxH*Xi6O}42TODv#f!$1dit2pCs}8c zQx_Dy7rQ29s{mskgWV&lh`893Ko`{5Swv^Fq^8|LEq5+Zd?xa zV^{=G$ZgA0;o5SGHR8)0+o1D1X<3$d^Up<{8x+s^F!ceq0}o%gs#X+6nmq!QE?Zl# zBo~#+Z`94*gl-06-(`|dT{-@;)FP8+60C$>mK5Ou>%oEIgoqd1WQ^1djR5!!Or9WbjM$dkh|C0GfBtIh>r#04O}h?85sJaKWV zva^#>mHL89KX?a2GPa^Kra=l8A(wpl{wIb5H;iPjffW0i?8vF-*U{?2TzdzutQsOK z8QydT`A`6PD+XZZO5d7rz>W3&PEj@AKT<^q!!AWBUTUncTYefM?|Frl5d}SW=Tdgy zL&6!n!UVauk``Nw?{s~pIAa&{Xu!||J(DSrQQr~=Y}nr_?@{W8;ZuQ8kv^r-agtM( z1sELg@>Aip8J*FWz~D5)Fh(FTMj)^>BC9nJg2K?{+Y$DB!S^WZYp%HBC6W?g(H5&@ z?=@#GDDd}QZq$EoSDhe3x1xt=-(yd2wa37rms#SAwBk)k0c*aa3TC2>qcZO5(VYl5 za43*uc|N1l$$O?yMr%wW7r7IDwJN3gmf`n#IC#C%UyR;QncjCM+h2#gXlIihe`C_( zAiT4=6Lsx|2knwkN~>IC;83gu3=!r`EJm^(=WxIJnce}DH8Q!otJ48WlXGs8FGL4sWlSWfY?M)s zbb-}_$Z95tTE|EF1RG>6ug&&%WB9+*JI>{p^80dQy9%*;dP@4jtJ_RztBP-k_{+U8 zqs+biTY_A=j-DV0U(t)})i-U0#QA5#Tz>?Lrv|1h>gKmYOL5#71=sLO98RjHiaGB( zwJAY8492;;8jSpImQOVY#&qxX^^AlqkgQ;kFrYd-F2fa05_K zwj+9vhyV+p4g;Fq-I4O%jdMi3K zM|DJxYP;8!!yiicW=Sk#xF;=GMc7kN+n0x&pAymj!_^wR@J5?9))U3nJ&Re@r^V7`KEu1SEv)_ypO%OYuW> zt|N{gKpd6Qogaws1U)WI&Z;3ADu3<3t#xDE=|vS19(a8E9FeH=t7`iEWO`^$@dyz9e zQNQyy#QAfNr7KhQ>QY1^q3%lQGl^*gl-t|&vEarog~dx>V%-+nx1(U_N|7`>@`#f2 z+MljU531RHZAkiy6ni%bM1Ro1#<&16R2cC=XkwI1#D&Or!MY>|M*frleDHK^QE4rkj_LKD*SP{`4K+Avh)Cv zLzLnT!{3lN+hW72-nlcl@~2^PI?dqkJ^`9f70jQnyY275@73xt=3(y&gD*pcHT`Jh{S3pkxjk(}`vqjW5=b>lCXr$bM%?zl=B9Gk>KAghWftRo@U7 zS+Qj=Ksf+r&hLJ|;ppp|;YoYZpnQ{+ZE~;Nr|k8iwb(@3DBKHc_4M7R&3)(1#8`pf z4N`;Q8f|hLa&RP^E*LwgAPH`RIK_p=t@D9Rn!z1)T<7yqcQ$B%RTUP+73dW8c(H{S z$W$$%u7eFXsfRJrhC!zgL#(y2m?Us+TjLp+`_jKiQ0_m$8x@h3_q=0aY)MR#umK@b z1V72?rkz={Vh9AuIT!xftN>H#s8iK-_P=;SH5b&B+^s*GR$%6)LMAD?O)-kUVK7Om zr5II8pCY;!9EiZ zbPq$Tcp<|e_69G5!@CJM(IVBBAX-Ho0juAM<{Mq4e|eq87ZT@z4uL%`5}m_97Kp;J-xli4Y82;T?~?*^nfq-oC|=4vmW%89 z(~?SZ6q@j#^aYmr8Pb0&(AjQuT7STeZT!h5SU7wO{@@$GTwPh$QjqvUT#^3N=N>Z- zzge{`%BZov7)*5B!VB~To4I#?`@&@5_iFw@My^)Tb<9A6ose6#9bhMKa}rum8W80{ zBp-nVDua}+A_52F85dy5=iz`duvi+2P}*^*O35Zv=~XOAA?Dkf7*o|;FB$!~$B$cB%o zwf|p~3pGnvj*e7LMljp}CEri&ofhSqDBg1eG$!sAR=^&3Y;B~DN(b;TBO`ZtH>Wb5 zQeKf#q9mZ9x1t*#QjB`y@QVd=-S$n-lQA|SA{W6MmjF=`2qA+ZL3udC!VqjR5YsWt zgc8VdTku*T%~iN-D~VJe=xcNXgze8v(a0Wt!u0%4iT%2Y7809vGdL|>{3*_~xD_xr z#M!G!4%c-^zn&p%Pcgj?w?7+v>;X=33VGD2PXh0{^vrcu9XuV>{gMGvosn-|k!(5{ zP~rD!GXynFAU291SBXGoeTrksHkHL}!I1S2=ZMz9tFCXUI5A=f64n*a|MxO(u>U_E zM~QYwq0LJ}OvXqVP;7mA#>Y`gtUloyq(>buu9P8%ov!pmwh(9%zh&TqZ60CV36)Muk}<~tNvt>B>FuG(0G z5k@aOknsW<>Y3iQ3M7qIN0s@T2HY=qb;)WL#S^uur4J&}s!x~rvdHL)xrSaSM|ikUYX;x{|6PI8kIb~< z56#gg()kFhU!y~qroYEryZ}!G)K{*6t#HR(-DH>Voe`=@9W7eQ=s;I2MRHWq+r!+6 zWpj_)oQeyy(zDKBxLF@zt1IHE;YYTCrYzyoHi+PTQnFC%(a{@nj`gU;0|=afIWAR8 zydDFFZnPm(2*-aFKl2wRlz{G$e@YZnGzzWKqzq8xK&rWZ|Nnp@M5%xX{d&B%VWz`1 zO`gl@Yav-s*e^JmP}dXN;{Fi0XIssBW`zdqsy;G3Y84gXicVO)YUJT&@6l1rTws?a zRV(tZo?osPnVJrkMij>$1{_HG!$~h>n>}0GR=ZEkkH_;B2WUm$bD_e{C-d8%rN@#c zNbCYUZ)Zs#L&p7HV~>Sae)cA5=YikcUt5O|n4xC{&*`4CczwYM ze?FeN`|zX0Si$ElxvdcX*dkW&#x^feGj%&NY zjosU^-`Si1hk=`97#D#A%*>Cp61=E3vY^`>Od9y62sC>F7EX5}r;k3u4lfhn9ne~R zi2=bo6S8Eh-Lf=U)0q4l(}K#>iTf^$C?U}9x-SKN>pr(zGBiN@EHMcU+OBXXox4eN zixefAyW^~-BW=VDoz#g6Mja?oDczdY=o!2J2|gBWQO$V|k1c)_ARXh5j$yVn(e@=} zz0mu8Z|*(F(WZMBBKbWT3DV`^wl-;g+e5nMVITZIUf!}R&T#404NU`$y9I9=cL^5U zU4pw42=4CgZoxeSch?ZyNpKDB9vn_*t#_Y2_8#MWJ-?uzx~;3OIje|#$`-?GVoa%j zMeY3h{dqVzM%HRs2%)Bnm@0e3H=%;1pXA%rU&g)1M47*M=aJ_2KR$g4E^x!1CDOh? z#rM&Zy&r|zS~DilGH;|o zl#VnPx5wker5*M~<;_@B4VeYE>pwkm-)Zbg=29hO<{&~E z*uxg(8E(?7GqU;6MCQs*J{im+TakH|07bK#1+L77I0woTI0u$6%F>BGEyl0B9}+*W8xcFlMG9$U#4606a(t# zxX{OvKJOg?W3ffFDo2-XIxI#HQ+}lB4^-rlq?y+i^Opb*_N&@2a2S3VPYk!HM1t=l z2r-3bJC}IFiom3`%oak~H3^5(9%1iuUCR?ceyB*iXfX! zgt(zM>E`;>46I+cLJp6Jh$Eia3E?sMR8ti;EWN4$6urURR~)6V0`Z=3GBzcn{?+Lr zw%S`BA8%ugd$LdLbiXPYSU8g3Js{$dfWFLmVLF^}9czD4JaMWgXBBQmcs&pcA~~iK zhQ9AnbZ+nW9d{rVIr!wH@caad?(rlwz)Ayk>MAQ&GZ5Igx9f7?%9_xb^w0Bq?l=b} z?M23|gEUw(@Vm^2HHwhnOHee{A>iYhj^xN2O&M}s-ju2k99?y z=Ln*hSiF>N&!8U~=is~wjg1*(#k*Il&LHJ;Y7=j{UrLcQ&C~2* z=L^Ao&OWCW&DC z3@qC(V@U(lqOe%yX~Z%Wq%H>(c+8GgaJ|*2(}*}gri_TA?YwB=FSH1yKnvn`wKGr= zCq{E*ZbLNvli`Gx{w&B6X!DzcTxrql+b;BAD!Q)7L{#^r;QL=wmL0EPNZTFQeFQJ+ zaVNQP1Y+oCXtBlco>C%m|_yj}HPj zuqT)c^T*M2fm*1nL?3G9<@?A#K;Nx z_Uiw4{i&mhp#y*4F!^r&vAXhn?9SZWpq@RsQ-(T|aLU6Xr7oFp#gPbqDUC_H8KRqJ zUZGWQcDv3%6=iZxLM~Ex=QM*Xf&nDzH4sv|9b|wqPNdC^ z^uTeRaG>8MvsWI5Pa@I)tu_QDC`^?lnA46e*bi-9mNyP{$j z2KgwTks^!>4P&mo0paPO%fol9_`BwQ%|rrQUs6)KV<$_GX&t_+UmP?#9DcaqWxU9Y zjcDyKs(IvbRbrfz;KA8Xh!~n7Lu64z-gc3_w}ro7b2ISCCUjFLl81p8R^1!vG8sI}!M$Er z$@)B+WBb^l?|l}FKri2N`d!#tavYTB+-J|(`+2&z#5P=R?w$8UIvtR`KnPZ8&JTix zcr#>ju~K!BrEt+90OGN^$h>tpa=qYPyI8a(ASE7X{TSn6Tu;P+ANc%&Klb^LbW$E_ zh-xBLq7C^&FZv1sh`|{%Vz!mTTpP~ybLI&Rp3Fe?mk<><#OhH656hlhzLilAm^G52 zd<~t8b(#;0O)c=JRTB=as~PVVHv7hDgVx{4T6ZXK&K_epv}4x3pPA5RUEP-YWgl$l z2geb19i;E6)UWmzG281y_WKV!wlqAc#M#x(hq~m;X!qH~fUS3>gEZ4?)nX?d6>>oK z2l9#&hEwf3{A*vFqqG8zzh3ELSR?RB==>yPZ#}Tf36G?IUfvPv3C3$L_A~19Yi5uQ7ToS=6(5h&#UuJh6Kq5o=IL2O`{AJCLUI# z1y`_vI5+N?;LDpNE5bcWr)vkE`{u4%qfC0tTlVRn7GX{&4@NJZQ#=%O^gfM+ki}+f z03Z_=mpuk2Qd$@Slehz$gwA*e(?1CDjM%0n3v5iuZ|3KSY;9AW*6hwod zb5V9Kdxd-v(thl$Iz$3g4do|p;G^^p_gaN^2#gvn&}}(sv3_8SGjb*}K_*KFmkd&W z{?C2}{QD?=5wgvm$ZDIw?o+=cap0Qv+?;~PqHbIp=T!!Wp@`v%amJ3s^S*<(9@?V3 zNH?^Vd-?zTFbC4Ar< zGuMFrzrWDz0;Yf12Lx&3NsxvRMqZeL=O#RGs`Q$r6Vj|u+rR+ugbt>lYv=bJy$ zanxC={$$%lB$(_1&8;o;rFKReO_Uv+^91rfDdf&rvWE48mxXpQO}W&K4S?Xpa5ZDd zbc&DgRbW#x$e1b1RsvF(id#_PLp0bP$7pD5*A`^CtvQ``8eCN2Xw0Y^7%&zYr}$9_ z-s$YqN0Y>NooKKo1sK1a@YfgBLQ!i{ivq~Tl;_AjC{Lom2i9@S;yCvGOcBCK5GQ1G zTbU#yaklf;rb=Zxxbb9R$WUUh*cHqO0)%XM3gL<>Vdsv2vfuE9jnusNNLz`*W|a$ku#Q}WKO*d_;z_|9^&B(Pi(4+aJ z)rhH~&9QvGP}n6A*WFDJ24)lYu>(E}dQ?gJWlAlc_9}D6*tHJO_i>@Pk2J1F@Eh>^>1YLc<_7?nsPqB-p|0 zYe&#wX#Bg`lggRMFZU-yMzky838gS-kGT=ra5O^2Gw|uv*dp;nGf)kc^kcS9jXDF8 zh7`^M+jo9||3sQZp)!6KvcjQa2GLZoYFhuy@80N&Mqr&gdd@5F#H#!~yA*WHlBV^hbh}*H>LyCSM}2V@*0$pCRh+#&smUIo?F+ww|JiQo~jf zi|4>H!>^vY3DLA6(TImU)GP66*7p6sJP4`HDTOYQAjprlLBShFb>?ia?w&u}v4@8j zar~eiY@QA;V`(g&1#d2K)dF$+za*bbz8*`E`vxQC668tZBvrE{vVZhj^~9u8S@wTv z*!T3*JC}z(h(cmXQ$gYNj z*q2&UnjHN!lwi(4!v0$Do?#=r>YnLaG?%FABc1$j-L0zil=|{N5oi3rcD+3chZ`GA z+j+(qrn`j6i;^3(cdY_Q0vSHKH?)355d0!D$M%Ax+g3?6p|c#zzWaycCW{GOmh$B* zD{2%P^E$n@YA!H81>X7=*%c!Rk0g1L(HESdXSLH#U3xx7)N;Ka;$=1)|2oHO+$efy zyXH%~{Zv$6+j)?_q%__vN^;Q2T4S@D1Wga_ej*IirqpuzI$=|yC!a72aYT#LFo>G} zOf!dw8kYXfxGTC?A5^L=SuxvC-*S9ndS`vuh{+0}6XUkI0Ew0l>{(J6s2|ynZB{vTc zUGRI%O7~PQ&|rR{flgLyJWQA2i;Tbobx2yxvQSq4-W$<*0xqV&3&On2W~*%!PN6wX@7U6>%PVx{;;+H_VJ`742{GCc8TJ%FtX$ zWE}_&DhX-I94U&Ri7SbhrjjZCeuS-+6P}(JG3oSf7dNjki-T$C2@Z>nyzoNz!$p=l zD8uzaJH>(U*YmoToh$5W)zc>=j?#~CriXZbL;6L{)`_&1&Q;yHw31kk;}h~GEJJXq%P~NdYwQ%D+w}7QT7YVlSE> z_k-(A7D9SkmiZ3}jX8hnY`PeLj!p#OFH+#=G#O*%7Y1%{kzkw!xu~+HJB+OAhrv0; zArHmauyWkVwwY-C(lJY-m3mkKa_?TnC=;xPnK9L!8h*EJ+XeVBEvwgKX{$sV|Lsfvva$zQ_PB*#Is}JDM~; z^^F;H8ZEI6mgi|A7EFdetN$%UUa&5b-KHL@V3;#l5dG8gV7exX6T}}9Jof8Op;sh- z;1#IX4pa(P8)J!-)n$HZ%&2xIwTrU$)2WE#|Vgqu)&3b$@94MLM4dXY{m-d@d|e7(;-Qyejs2{48NOMEdPM?z}_=+s5o^gQD2)< z(Z&4O7$W2V*(AS(Y>qP7XJKv;D1q}5jR{v)DN^fZ4NVSOkN8{T*zc?0Lx?RrU^~tB!C9br+Qs^|c|Q z!sg_nI8pFKs?4lCQ-+O@DIaXSu>i zlGYsiuuA(nWe!Qo_!c(l^X~2(YH!8$STk^NBjQQM%w7UbehZhY3EMCWS;!CUI^|kT zEzfHq;V=j&x#bB`L@0zo01JKuXbAXF|C}{yFMR)aM5(;K0+?uX#{-#BSD3LU4W1}c zpn!4s)_qR~qfiw$hkK)L7m%NZ3GZh-=M}D?@iBQ~-6OghZ{zmw(>fVhB`M=j*zA6m zqg-fm$q5mi0)5UfpJT}ppF;${v^&h>A`*qr_|`88=p)SgrYf~T5^XLjp8^Qdu;$xO z;8Rw6&|*88?ExxHYTNTo(U!D5F?)mh1O%NqqTnAzyUO2tdS9N%m@$Xd_~XP44X==c z-5&e%Vf{K#1&eae)9Od%j4D>^ZK%_#{~+Iw>n!3&nsBJO8-yQDGB~8#iTfXGX3XdP zltM=;tq!Y<(rL58jQDQhs;xj zrJ)UH^SfNtvkc|)R@EY?C4iQeyKd^BUEBdTO5+q;Oh?)4u-)a zoL-FL40U_ih=d5S0z6q8gu!}>SToJ@fA(&pTR%CW?b_aLO}k&LX&=q6e5+gz5k7ck z$5OHG7Byd*gagdD_8zka&y5 zboKX4s+@r5)S7~Co?F7#cs(hh*W(Z0G!e@02^tdr zRTZi&BffD9hx7}&rVnS(HSL^0PeZ3utd1hj#R(KgzB&*V`$(Hv6yw3gXE9oq4b4=Gfz-Otl^#A$ zZ+Ie(ezd1SH1mNT!)X2pe#_PEPbva9UI;9lt<1bhKZTuO|DJFNyFnP zdWs^DLfi0}au$It4?^eH{(Ox7hJIhmXJi#U%Iz{Zp-Fy4Ll#}?Z0_e@+21?d zG3;#wdfx|E9g=wV;I|8@K8(1XpYV+59TQ3OtGX4kmkB8iEkqsX z9eIDZRTcZ}SQFhNcXfgVGOiw)4lP(G1+F%yNQX46I9`wbtX$Jr8kqILPWxzYI@tP4 zPCdV~1M_IMiP@zCt_}6YJLD=K=YRYe8zh;#x+rPfgqJCNHLdq4%+@6h z`wK}lYf4j?y|XXVz>XNmwM%L7q}N{0j{JtbsKN{KA>`ei z{kYb>WRsEm`F}-oQ~Z3mmcW#mD{t==x1PgVZ)7zqa6(cuurYUy)6ge7O0(yj#IFx1 z5J2N?Lh+jnx$N`1X`PT^S04E!9kP8w+vZP685xl{1beK`lO-e-I8-baKLpn^0m{=( zj-lnFD^wQ!T@n)6%(KPgXS_wL+1XeQcE_LFsx}vA6Xc4Mb`RN*8?$Q>tx*vzIoL^+ zjhQk_r8zZHlNnwr|C3~@YA(~mTxq1H5}K;7g;}0thIB|6QFn*0Xq>30;whz<}D-wiA|8>qmbqFd}@MiTRkBAsbQYesYx!^l|pN z#&^S1d4GtCbEQeIS<1}bo)#(W^x*B)l9B<1freap$vc-T!YFcx)-R+8qJH>ckNy0f z7qDA6C}!l)cjEgTI8kp0Gx0RM*+~d#914%3dD~!XSR%CSQA{aKJvejlWcV}si!!XN z*eHCz4Hy6v%YxSO!&OQ`RAh8}$9l_CHq{zAYEaM=XoM(@x)32GHw4oS&OmV&`P5)~ zFY16XjfeW!z*^>Dd8UX84?RldTxH=~f@(TyNvNTyt95AxfBT|}d z089p5YVXJ;))$@TdI2=R2#tS%P~9cvmN*Jm?m&BGh}GWQY1+ufoUhh6{6iW`)|9|R z`-^F!9`MgEH}V~~!l9v($x-Uj7IU}y%->G+wPkWw=y7oWx|K`$qPG3lh%-fZP z_wMWvhlPh>qJ>+*pLG>2`L+oA<&5@%lf? z;~GRfoyR9g}}a>ht_ zqq7T+lvhwFXfMU`_uJaPXdzM3R?C$oosjFe)VbyJn@^px5ch8+GMGdPPir=}-*0i= zS7Yb7rEhJja`-^3kQtf!+!o^+K)NZ4X7!ta^bFbzo z^Nk&m0WRzE2RvCGXJ93j65zvZsPNY_Q&XJ7;DcYEiuY;t3%Zwbr(9!arR`mj`+};L z$SHia?j*XQ8!X-JRg)q-FiKs@aX2_g5W-i(>2L9o&q6;`RA8jE-=*AKY5!Y{ng!ro zUSG@Pe+4ec2ECz&SP=<~P$>LO50ZAnhFS3&DOn?)$=?q~Pt0$pt~KY$p%{U=2v4vh z_3c(C*5M1^X2bjBoqVfsshWVQUG}gYxs8>a>71|<7b2Xh2}|4WyAtcmy-K^TZFEEaR@S3?BR4cLM+ z+OMgpo!amnk}z`Cm|j_KjHtyQ?TqIA&@XfC zU($Z7PWTTwwu64nj&iCQU*m5e(UbhxM3;(=paazc}#{pM!Z* z=ld?X(}OpXfDaS(=>aaxFC10T98RreBS6Z}g3!~a`$b{3(~C5A_ijc{zpharwH-CP z4msN(5KyFp$WcYgopoQ{x%O%og95pSNlmdd@q17+@RMjiq()J2FE}~~k!22VR)tec zCFUs$Wi;@`=V@YR0VMuUJ|`_$%LN7UBn!D=RnK!LiPFQt-zt!+XYbhT+p=eEe-0OY z|077spCQr69n@U<-g5VrZl^CkP+qCb?PH0HKwW6y7U*E*5MCYmqzQptX;;0O8B_&( z2q-($$_On9R;~Dx8Wpb)9fcEE>CYhb-_TburJ0GTDyc-Jzr~BV-oa+DSF&=Cp7rYg zg;65yFK-v98oE4{^6xKL%M)X;|8a89Xj#gf7*W`iYiRhVuC~sR7m0KN2A!JJ$kGAS zwPnzKJhD~Wm#->THrs3df%3!|It!!^%o1AVr8JnS#he51?R(clGJ3yBZUR$d^reQG zCQ#ax{P;W{D(ocqY%bje>On-c#=42Klu3fWTh4(aFBrz5Pr1%B-X2qWTGch^!@1a8 zlRj$`xA2S}s%<#R_V%{N%>~7u7q$bd`RWB&n*D$cJBdJIMZcpDAXq2T}fgf(^nJ+2m)8#?#D+CJ7ILBOs4lB7*;1x zpRekF*Xc=6SSu4fusAt_4Z-uK$sa-WMVqJnYf{z${nzPrwb)56!ol#N2ZQqRLqZp+ z$4#e243`X*&1u@LUtc!e`8Hh%RG&s&at_><@E3wSCion3b`NYH8O^P{8;?=sk-SP# zp_*Du)DBt~XSZnZg<>4^kRHE$f>xsB4^RnW1D|X-T{r|%*!kB4@2Yh$Ib78byQmJ- zt}jDMj#WpeJH4b4Kc6Ov5+AcYvr6fAt=FXyYgfk9MpUz5wi#K-vZ+9UQKr#XgIaKj z($bAB;K$NAC<(Mq(`ZS>q0PV7NTLvdgOqG0Sk6PQ}-w#;ERv zcuz&nxJnsE+_tul>KE^e5!6lR2Ggt&2$(OsA5WPM3s_6KMz~iGB(h@Dd34_NkS0 zN?-xm;HJk=K9EdwoXqDmK}`8-PA7frxx3xil?P{00ro?wx5I2!or0(4GeHPUytp7# zPlE?sW~5AW=Y|&DteNky+4qF`E!nxG*o7IZ4JAu<7={&IW!3(SJ@~7=<(|Qc6@4j= z6)$;@j)E0;yo=iE`$((UeGyNv{NRmq^YG$u*a&LV2X&B)Ar5>K1>=dC@C1r)u$qYA z`}lacI4#LnrnC*-7}I-_{A$`)(QnVv{NmxlSHV9LB_=G<``5k4BM`xaB7r@>$Xe)S zVvN7`<#sA}{|!3Gg)i4;RlWcl+2Gugn-KGS(==*1Ljn>r zIm(p}vbyqyUTIe*o)L#qJCI-h0JRc88Bv&uZ1@z`L`zny!k#JQ_VpuFJ*wk>Jm3#} z?IN1KT_SV5ydqt-?TY?5;jT=_624$1`xi2^fI>nY^Y_lw!~^8JMoO>~+v0ShvYJ6N1BOeJ!YVSID?}}~?=&;e(64y9+57UtFOCy;^fHJ03>zBxWX#V7x={qGW z)_?HOMM2)M0K<64RJ9(l3ptHCHBmpgR}72+#V!;HC(u=}9uX&9RTys~ll+r~kFjx! zATIPI(1`FF^j-{A2PM`aOAT2J!)7dLhsH5d9G-IRTdOO~NB;LiPj!0hI40av(^tSRWn%UE)hb06?zA|%LN#=-bt z2DX<2KfKgw-xN2m$N&6o8QlV}ru_s$`7I{WG3Z_iUQeee>#Si}E?Hg!)~DXE!=UF| z|93xj*vfZ(VtyqjVWQ4KX4 zX8H%bTGiCzr_l8Ky5~Y^%g^<2tuTxb5z@=aa^J=3jGPF;kiulwN<`D$M|+fzpO`ob~#0dG8rdEKDKeHnPQ3rDSr! zXJrSHJQvK7X0Rg&q-24tSJN6~P@OvQ4HABM)lsf8%w6+C%{BJiHVWvA%uyTWfo1ib zu|IdgFI|=tm59}NDPUj;mDVAg*~GFq>D=v4q)EM7!ErgAH7DCkJ{$+7YdNwyzk~;m zTKHwTPKfuU*yjhNCR=e?|NeA$HsET=>7FIPvWd@zAh6QN(VEepO43( z4XFfB&J8%CQ6RS-Nfy@rhD=n0At;pyE0-Kn2r_06(tY1nz55;(bCPwe)Q~R{X(;SJ zX+-ZfMFPb0!~lX0O_HT3iQT74Bq;m?wl_PT!(l1y5K6HT{-i( zT7Aac2>=ujs;|Db+#mZjgwdcE=>+=P+XR>%+vAOx7W43)^(7CTp+@-r{fM&zj(YW= z(_7oeh+6+q)JBSecBK6K25$LCXwcz_J1CTn8*>h?@5_Au{L;IRJrtVt(;DV0UqK;* zA`v{&mc(YPY~5!p%1OUh0tzX&Y+8q!GX7g zQ7saL>DgD(DEhY;T?zle(?U&Ujb>c0TVH-3p5ViB8KAG=y@28k-!AC4jlvSP^|%M_ zTJ^5AOr?GWnfPZ@3LIZfmxIg4<{!_k5jQzU=QYzt0$J?Y-PHfh+beT~T|NvMo#P}7 z0Rk5%a##--jN03oLWNHZyMd;=>T0R0{c#Iiz14@CG)Ue|_uKj6 zRfoT@$ij=JW7)l{nx8mc?HaX?jxdZxVkGkV1M3R~?;Rr|sqvdoq{Hzrciv&4m0<#3P-Wd3w zdIOT+a<%EGwFaLh0bf*xL%o#w(-9*|_{i{$#^*4Cy1NXYA+jo zQNofwNZ#0-C-V=Y?0I~fZg_cscoHuLlt02<(XIvzXv$o%`d^$cUe~;_j5a^xHQjb7 z&)t(EdF>2sHBqP6%*Ay^1`3M9`td}{Q`4}0_z;>e^e%4>P*w_?!xVe)jVZ8wk3S`J z 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 literal 0 HcmV?d00001 diff --git a/host/bookmarks.ts b/host/bookmarks.ts new file mode 100644 index 0000000..ba7cf02 --- /dev/null +++ b/host/bookmarks.ts @@ -0,0 +1,54 @@ +import { Database } from "bun:sqlite"; +import { createHash } from "node:crypto"; +import { mkdirSync } from "node:fs"; +import { dirname } from "node:path"; +import type { BookmarkPage, BookmarkCommand, Place } from "../shared/types.ts"; + +/** User data has its own database: evicting the HTTP cache cannot erase it. + * Mutation receipts and changes commit together, including deletion receipts. */ +export class Bookmarks { + private db: Database; + constructor(path: string) { + if (path !== ":memory:") mkdirSync(dirname(path), { recursive: true }); + this.db = new Database(path); + this.db.exec(`PRAGMA journal_mode=WAL; + CREATE TABLE IF NOT EXISTS places (seq INTEGER PRIMARY KEY AUTOINCREMENT, id TEXT UNIQUE NOT NULL, name TEXT NOT NULL, detail TEXT NOT NULL, lat REAL NOT NULL, lon REAL NOT NULL, zoom INTEGER NOT NULL); + CREATE TABLE IF NOT EXISTS receipts (op TEXT PRIMARY KEY, body TEXT NOT NULL, result TEXT NOT NULL);`); + } + list(offset: number): BookmarkPage { + if (!Number.isSafeInteger(offset) || offset < 0 || offset > 995 || offset % 5) throw new Error("Invalid saved places page"); + const total = (this.db.query("SELECT count(*) AS n FROM places").get() as { n: number }).n; + offset = Math.min(offset, Math.max(0, Math.ceil(total / 5) - 1) * 5); + const items = this.db.query("SELECT id,name,detail,lat,lon,zoom FROM places ORDER BY seq DESC LIMIT 5 OFFSET ?").all(offset) as Place[]; + return { items, offset, total }; + } + command(command: BookmarkCommand): string { + if (!command || typeof command.op !== "string" || !/^[a-zA-Z0-9_-]{12,80}$/.test(command.op)) throw new Error("Invalid operation ID"); + const body = JSON.stringify(command); + if (body.length > 1200) throw new Error("Saved place exceeds budget"); + return this.db.transaction(() => { + const previous = this.db.query("SELECT body,result FROM receipts WHERE op=?").get(command.op) as { body: string; result: string } | null; + if (previous) { if (previous.body !== body) throw new Error("Operation ID reused with different data"); return previous.result; } + let id = command.id; + if (command.kind === "save") { + const p = command.place; + if (!p || typeof p.name !== "string" || !p.name.trim() || p.name.length > 36 || typeof p.detail !== "string" || p.detail.length > 60 || !Number.isFinite(p.lat) || Math.abs(p.lat) > 90 || !Number.isFinite(p.lon) || Math.abs(p.lon) > 180 || !Number.isInteger(p.zoom) || p.zoom < 1 || p.zoom > 18) throw new Error("Invalid saved place"); + if (this.list(0).total >= 1000) throw new Error("Saved places limit reached (1000)"); + id = "b_" + createHash("sha256").update(command.op).digest("hex").slice(0, 24); + this.db.query("INSERT INTO places (id,name,detail,lat,lon,zoom) VALUES (?,?,?,?,?,?)").run(id, p.name.trim(), p.detail, p.lat, p.lon, p.zoom); + } else { + if (typeof id !== "string" || !/^b_[a-f0-9]{24}$/.test(id)) throw new Error("Invalid saved place ID"); + if (!this.db.query("SELECT id FROM places WHERE id=?").get(id)) throw new Error("Saved place no longer exists"); + if (command.kind === "rename") { + if (typeof command.name !== "string" || !command.name.trim() || command.name.length > 36) throw new Error("Name must contain 1-36 characters"); + this.db.query("UPDATE places SET name=? WHERE id=?").run(command.name.trim(), id); + } else if (command.kind === "remove") this.db.query("DELETE FROM places WHERE id=?").run(id); + else throw new Error("Unknown saved place command"); + } + const result = JSON.stringify({ id }); + this.db.query("INSERT INTO receipts VALUES (?,?,?)").run(command.op, body, result); + return result; + })(); + } + close() { this.db.close(); } +} diff --git a/host/cache.ts b/host/cache.ts new file mode 100644 index 0000000..cd80eb7 --- /dev/null +++ b/host/cache.ts @@ -0,0 +1,69 @@ +import { Database } from "bun:sqlite"; +import { mkdirSync } from "node:fs"; +import { dirname } from "node:path"; +export type NetworkFetch = (url: string | URL | Request, options?: RequestInit) => Promise; + +/** Host-only HTTP cache. Completed tiles persist across provider reconnections; + * in-flight requests deduplicate, with bounded bodies and conditional expiry. */ +export class HttpCache { + private db: Database; + private pending = new Map>(); + private running = 0; + hits = 0; downloads = 0; + constructor(path: string, private network: NetworkFetch = fetch, private maxEntries = 2048) { + if (path !== ":memory:") mkdirSync(dirname(path), { recursive: true }); + this.db = new Database(path); + this.db.exec("PRAGMA journal_mode=WAL; CREATE TABLE IF NOT EXISTS http (url TEXT PRIMARY KEY, bytes BLOB NOT NULL, expires INTEGER NOT NULL, etag TEXT, modified TEXT, touched INTEGER NOT NULL)"); + } + get(url: string, options: { maxBytes: number; ttl: number; signal?: AbortSignal }): Promise { + const existing = this.pending.get(url); if (existing) return existing; + if (this.running >= 4) return Promise.reject(new Error("Host request budget exhausted")); + this.running++; + const request = this.read(url, options).finally(() => { this.pending.delete(url); this.running--; }); + this.pending.set(url, request); return request; + } + private async read(url: string, options: { maxBytes: number; ttl: number; signal?: AbortSignal }) { + const row = this.db.query("SELECT * FROM http WHERE url=?").get(url) as { bytes: Uint8Array; expires: number; etag: string; modified: string } | null; + const now = Date.now(); + if (row && row.expires > now && row.bytes.byteLength <= options.maxBytes) { + this.hits++; this.db.query("UPDATE http SET touched=? WHERE url=?").run(now, url); return row.bytes; + } + const headers: Record = { "User-Agent": "PocketMap/0.1 (+https://github.com/pocket-stack/pocket-map)", "Accept": "image/png,application/json" }; + if (row?.etag) headers["If-None-Match"] = row.etag; + if (row?.modified) headers["If-Modified-Since"] = row.modified; + // Bun's redirect:error rejects 304 as well. Manual mode preserves cache + // revalidation; the status checks below still reject actual redirects. + const response = await this.network(url, { headers, redirect: "manual", signal: options.signal ?? AbortSignal.timeout(6500) }); + const cacheControl = response.headers.get("cache-control") ?? ""; + const maxAge = /(?:^|,)\s*max-age=(\d+)/i.exec(cacheControl); + const expiresAt = Date.parse(response.headers.get("expires") ?? ""); + const age = Number(response.headers.get("age") ?? 0) || 0; + const ttl = maxAge ? Math.max(0, Number(maxAge[1]) - age) * 1000 : Number.isFinite(expiresAt) ? Math.max(0, expiresAt - now) : options.ttl; + let bytes: Uint8Array; + if (response.status === 304 && row) bytes = row.bytes; + else { + if (!response.ok) throw new Error(`Map service returned HTTP ${response.status}`); + if (Number(response.headers.get("content-length") ?? 0) > options.maxBytes) { await response.body?.cancel(); throw new Error("Map response exceeds budget"); } + const reader = response.body?.getReader(); if (!reader) throw new Error("Empty map response"); + const parts: Uint8Array[] = []; let size = 0; + try { + while (true) { + const part = await reader.read(); if (part.done) break; + size += part.value.byteLength; + if (size > options.maxBytes) { await reader.cancel(); throw new Error("Map response exceeds budget"); } + parts.push(part.value); + } + } finally { reader.releaseLock(); } + bytes = new Uint8Array(size); let at = 0; for (const part of parts) { bytes.set(part, at); at += part.length; } + this.downloads++; + } + if (/no-store/i.test(cacheControl)) this.db.query("DELETE FROM http WHERE url=?").run(url); + else { + this.db.query("INSERT OR REPLACE INTO http VALUES (?,?,?,?,?,?)").run(url, bytes, now + (/no-cache/i.test(cacheControl) ? 0 : ttl), response.headers.get("etag") ?? row?.etag ?? null, response.headers.get("last-modified") ?? row?.modified ?? null, now); + this.db.query("DELETE FROM http WHERE url IN (SELECT url FROM http ORDER BY touched DESC, url LIMIT -1 OFFSET ?)").run(this.maxEntries); + } + return bytes; + } + expires(url: string) { return (this.db.query("SELECT expires FROM http WHERE url=?").get(url) as { expires: number } | null)?.expires ?? 0; } + close() { this.db.close(); } +} diff --git a/host/provider.ts b/host/provider.ts new file mode 100644 index 0000000..ea1691b --- /dev/null +++ b/host/provider.ts @@ -0,0 +1,106 @@ +import { createHash } from "node:crypto"; +import { createCanvas, loadImage } from "@napi-rs/canvas"; +import type { OffloadImage } from "@pocketjs/framework/offload/provider"; +import { HttpCache, type NetworkFetch } from "./cache.ts"; +import { Bookmarks } from "./bookmarks.ts"; +import { join, dirname } from "node:path"; +import type { MapInfo, Place, SearchInput, TileInput } from "../shared/types.ts"; + +export interface ProviderConfig { tileURL: string; searchURL: string; name: string; attribution: string; maxZoom: number; cache: string } +export const defaultConfig: ProviderConfig = { + tileURL: "https://tile.openstreetmap.de/{z}/{x}/{y}.png", searchURL: "https://photon.komoot.io/api/", + name: "OpenStreetMap DE", attribution: "OpenStreetMap contributors", maxZoom: 18, cache: ".local/cache.sqlite", +}; +export function packRGB(rgba: Uint8ClampedArray | Uint8Array, width: number, height: number): OffloadImage { + if (rgba.byteLength !== width * height * 4) throw new Error("Invalid pixel plane"); + const pixels = new Uint8Array(width * height * 2); + for (let i = 0; i < width * height; i++) { + const alpha = rgba[i * 4 + 3] / 255; + const r = Math.round(rgba[i * 4] * alpha + 255 * (1 - alpha)); + const g = Math.round(rgba[i * 4 + 1] * alpha + 255 * (1 - alpha)); + const b = Math.round(rgba[i * 4 + 2] * alpha + 255 * (1 - alpha)); + const rgb = (r >> 3) | ((g >> 2) << 5) | ((b >> 3) << 11); + pixels[i * 2] = rgb & 255; pixels[i * 2 + 1] = rgb >> 8; + } + return { width, height, pixels, format: "r5g6b5" }; +} +export class MapProvider { + readonly info: MapInfo; + readonly cache: HttpCache; + readonly bookmarks: Bookmarks; + private decoded = new Map(); + private loading = new Map>(); + private searching = false; + private nextSearch = 0; + constructor(readonly config: ProviderConfig, network: NetworkFetch = fetch) { + for (const url of [config.tileURL, config.searchURL]) if (new URL(url).protocol !== "https:" && !/^http:\/\/(localhost|127\.0\.0\.1)(:|\/)/.test(url)) throw new Error("Use HTTPS or a local provider"); + if (!["{z}", "{x}", "{y}"].every(part => config.tileURL.includes(part)) || !Number.isInteger(config.maxZoom) || config.maxZoom < 1 || config.maxZoom > 18) throw new Error("Invalid tile source"); + this.info = { source: createHash("sha256").update(JSON.stringify([config.tileURL, "r5g6b5-v1"])).digest("hex").slice(0, 16), name: config.name.slice(0, 40), attribution: config.attribution.slice(0, 100), maxZoom: config.maxZoom }; + this.cache = new HttpCache(config.cache, network); + this.bookmarks = new Bookmarks(config.cache === ":memory:" ? ":memory:" : join(dirname(config.cache), "places.sqlite")); + } + methods() { return { + "map.info": () => JSON.stringify(this.info), + "map.tile": (raw: string) => this.tile(JSON.parse(raw)), + "map.search": async (raw: string) => JSON.stringify(await this.search(JSON.parse(raw))), + "map.label": (raw: string) => this.label(JSON.parse(raw)), + "bookmarks.list": (raw: string) => JSON.stringify(this.bookmarks.list(JSON.parse(raw).offset)), + "bookmarks.command": (raw: string) => this.bookmarks.command(JSON.parse(raw)), + }; } + tile(input: TileInput): Promise { + const { source, z, x, y } = input; + if (source !== this.info.source || ![z, x, y].every(Number.isInteger) || z < 0 || z > this.config.maxZoom || x < 0 || x >= 2 ** z || y < 0 || y >= 2 ** z) return Promise.reject(new Error("Invalid tile address or source")); + const key = `${z}/${x}/${y}`, hit = this.decoded.get(key); + if (hit && hit.expires > Date.now()) { this.decoded.delete(key); this.decoded.set(key, hit); return Promise.resolve(hit.image); } + const pending = this.loading.get(key); if (pending) return pending; + if (this.loading.size >= 3) return Promise.reject(new Error("Tile decode budget exhausted")); + const url = this.config.tileURL.replace("{z}", String(z)).replace("{x}", String(x)).replace("{y}", String(y)); + const work = this.decode(url) + .then(image => { this.decoded.set(key, { image, expires: this.cache.expires(url) }); if (this.decoded.size > 64) this.decoded.delete(this.decoded.keys().next().value!); return image; }) + .finally(() => this.loading.delete(key)); + this.loading.set(key, work); return work; + } + private async decode(url: string) { + const bytes = await this.cache.get(url, { maxBytes: 512 * 1024, ttl: 7 * 86400_000 }); + const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength); + if (bytes.length < 24 || view.getUint32(0) !== 0x89504e47 || view.getUint32(4) !== 0x0d0a1a0a || view.getUint32(12) !== 0x49484452 || view.getUint32(16) !== 256 || view.getUint32(20) !== 256) throw new Error("Expected a 256px PNG tile"); + const image = await loadImage(Buffer.from(bytes)); + if (image.width !== 256 || image.height !== 256) throw new Error("Invalid decoded tile size"); + const canvas = createCanvas(256, 256), ctx = canvas.getContext("2d"); ctx.drawImage(image, 0, 0); + return packRGB(ctx.getImageData(0, 0, 256, 256).data, 256, 256); + } + async search(input: SearchInput): Promise { + if (typeof input.query !== "string" || input.query.length > 80 || !Number.isFinite(input.lat) || Math.abs(input.lat) > 90 || !Number.isFinite(input.lon) || Math.abs(input.lon) > 180) throw new Error("Invalid place search"); + const query = input.query.trim(); if (!query) return []; + if (this.searching) throw new Error("A search is already running"); + this.searching = true; + try { + // Explicit submits only, at most one outgoing search per second. + await Bun.sleep(Math.max(0, this.nextSearch - Date.now())); this.nextSearch = Date.now() + 1100; + const url = new URL(this.config.searchURL); url.searchParams.set("q", query); url.searchParams.set("limit", "5"); url.searchParams.set("lang", "en"); + url.searchParams.set("lat", input.lat.toFixed(1)); url.searchParams.set("lon", input.lon.toFixed(1)); + const bytes = await this.cache.get(url.toString(), { maxBytes: 64 * 1024, ttl: 86400_000 }); + const result = JSON.parse(new TextDecoder().decode(bytes)); + if (!Array.isArray(result.features)) throw new Error("Invalid search response"); + const seen = new Set(), places: Place[] = []; + for (const feature of result.features.slice(0, 5)) { + const p = feature.properties, xy = feature.geometry?.coordinates; + if (!p || typeof p.name !== "string" || !Array.isArray(xy) || !xy.slice(0, 2).every(Number.isFinite) || Math.abs(xy[0]) > 180 || Math.abs(xy[1]) > 90) continue; + const id = `${String(p.osm_type).slice(0, 1)}${String(p.osm_id).slice(0, 20)}`; + if (seen.has(id)) continue; seen.add(id); + const detail = [...new Set([p.street, p.city, p.state, p.country].filter(n => typeof n === "string" && n !== p.name))].join(", ").slice(0, 60); + places.push({ id, name: p.name.slice(0, 36), detail, lon: xy[0], lat: xy[1], zoom: ["city", "town", "village", "state", "country"].includes(p.type) ? p.type === "country" ? 5 : 13 : 16 }); + } + return places; + } finally { this.searching = false; } + } + label(input: { name: string; detail: string }) { + if (typeof input.name !== "string" || input.name.length > 80 || typeof input.detail !== "string" || input.detail.length > 120) throw new Error("Invalid label"); + const canvas = createCanvas(256, 32), c = canvas.getContext("2d"); + c.fillStyle = "#f7f9fc"; c.fillRect(0, 0, 256, 32); + c.fillStyle = "#263748"; c.font = "bold 13px Arial"; c.fillText(input.name, 5, 13, 246); + c.fillStyle = "#627387"; c.font = "11px Arial"; c.fillText(input.detail, 5, 28, 246); + return packRGB(c.getImageData(0, 0, 256, 32).data, 256, 32); + } + close() { this.cache.close(); this.bookmarks.close(); } +} diff --git a/host/serve.ts b/host/serve.ts new file mode 100644 index 0000000..ad70725 --- /dev/null +++ b/host/serve.ts @@ -0,0 +1,10 @@ +import { resolve } from "node:path"; +import { connectOffloadProvider } from "@pocketjs/framework/offload/provider"; +import { defaultConfig } from "./provider.ts"; +const root = resolve(import.meta.dir, ".."); +const address = process.argv[2] ?? "192.168.8.102"; +const configPath = resolve(root, ".local/provider.json"); +const config = { ...defaultConfig, ...(await Bun.file(configPath).exists() ? await Bun.file(configPath).json() : {}), cache: resolve(root, ".local/cache.sqlite") }; +const key = (await Bun.file(resolve(root, ".local/pair.key")).text()).trim(); +connectOffloadProvider({ address, key, worker: new URL("./worker.ts", import.meta.url), data: config, log: console.log }); +console.log(`Pocket Map: ${config.name} -> ${address}; cache ${config.cache}`); diff --git a/host/worker.ts b/host/worker.ts new file mode 100644 index 0000000..27e4c40 --- /dev/null +++ b/host/worker.ts @@ -0,0 +1,8 @@ +import { dispatchOffload } from "@pocketjs/framework/offload/provider"; +import { MapProvider } from "./provider.ts"; +declare const self: { onmessage: (event: MessageEvent) => void; postMessage(value: unknown): void }; +let provider: MapProvider; +self.onmessage = async event => { + if (event.data.init) { provider = new MapProvider(event.data.init); return; } + self.postMessage(await dispatchOffload(provider.methods(), event.data)); +}; diff --git a/package.json b/package.json new file mode 100644 index 0000000..a2fd435 --- /dev/null +++ b/package.json @@ -0,0 +1,9 @@ +{ + "name": "pocket-map", "version": "0.1.0", "private": true, "type": "module", "license": "MIT", + "scripts": { + "setup": "bun scripts/setup.ts", "3ds": "bun scripts/build.ts", "host": "bun host/serve.ts", + "deploy": "bun scripts/deploy.ts", "sim": "bun scripts/sim.ts", + "test": "bun test --conditions=browser test/geo.test.ts test/provider.test.ts test/model.test.ts test/bookmarks.test.ts", + "check": "bun run test && runtime/node_modules/.bin/tsc --noEmit" + } +} diff --git a/pocket.config.ts b/pocket.config.ts new file mode 100644 index 0000000..1be934e --- /dev/null +++ b/pocket.config.ts @@ -0,0 +1,2 @@ +import { definePocketConfig } from "@pocketjs/framework/config"; +export default definePocketConfig({}); diff --git a/pocket.json b/pocket.json new file mode 100644 index 0000000..d8c622d --- /dev/null +++ b/pocket.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://pocketjs.dev/schema/pocket-2.json", "pocket": 2, + "id": "dev.pocket-stack.map", "name": "pocket-map", "title": "Pocket Map", "version": "0.1.0", + "engine": { "capabilities": { "requires": ["io.offload", "text.glyphs.baked", "input.buttons", "display.auxiliary", "input.touch.auxiliary"], "enhances": ["input.analog.left", "input.analog.right"] } }, + "app": { "entry": "app/main.tsx", "output": "pocketmap-main", "framework": "solid", "viewport": { "fixed": { "logical": [400, 240], "presentation": "native" } }, "surfaces": { "auxiliary": { "fixed": { "logical": [320, 240], "presentation": "native" } } } } +} diff --git a/runtime b/runtime new file mode 160000 index 0000000..e5c94e3 --- /dev/null +++ b/runtime @@ -0,0 +1 @@ +Subproject commit e5c94e387e4d88129881f0285c91f46c7d7f5ed4 diff --git a/scripts/build.ts b/scripts/build.ts new file mode 100644 index 0000000..f29f4aa --- /dev/null +++ b/scripts/build.ts @@ -0,0 +1,13 @@ +import { mkdirSync, writeFileSync, copyFileSync, existsSync } from "node:fs"; +import { resolve } from "node:path"; +import { resolve3dsBuildPlan } from "../runtime/tools/3ds-profile.ts"; +import { build3ds } from "../runtime/tools/3ds.ts"; +const root = resolve(import.meta.dir, ".."); +const plan = resolve3dsBuildPlan(await Bun.file(resolve(root, "pocket.json")).json()); +mkdirSync(resolve(root, "dist"), { recursive: true }); +const path = resolve(root, "dist/plan.json"); writeFileSync(path, JSON.stringify(plan, null, 2)); +await build3ds([`--plan=${path}`, `--project-root=${root}`, ...process.argv.slice(2)]); +for (const ext of ["3dsx", "pocket", "cia"]) { + const from = resolve(root, `runtime/dist/3ds/pocketmap-main.${ext}`); + if (existsSync(from)) copyFileSync(from, resolve(root, `dist/pocketmap-main.${ext}`)); +} diff --git a/scripts/deploy.ts b/scripts/deploy.ts new file mode 100644 index 0000000..f4b71d0 --- /dev/null +++ b/scripts/deploy.ts @@ -0,0 +1,28 @@ +import { randomBytes, createHash } from "node:crypto"; +import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs"; +const address = process.argv[2] ?? "192.168.8.102"; +const bytes = readFileSync("dist/pocketmap-main.3dsx"); +if (bytes.includes(Buffer.from("pocketjs-captures"))) throw new Error("Rebuild without capture before device deployment"); +mkdirSync(".local", { recursive: true }); +if (!existsSync(".local/pair.key")) writeFileSync(".local/pair.key", randomBytes(32).toString("hex"), { mode: 0o600, flag: "wx" }); +chmodSync(".local/pair.key", 0o600); +const manifest = await Bun.file("pocket.json").json(); +const slot = createHash("sha256").update(manifest.id).digest("hex").slice(0, 16); +const script = `import ftplib, hashlib, io, json, pathlib, sys +ftp=ftplib.FTP(); ftp.connect(sys.argv[1],5000,timeout=20); ftp.login() +for path in ['/3DS','/pocketjs','/pocketjs/offload']: + try: ftp.mkd(path) + except ftplib.error_perm as error: + if not str(error).startswith('550'): raise +receipt=[] +for local,remote in [('.local/pair.key','/pocketjs/offload/'+sys.argv[2]+'.key'),('dist/pocketmap-main.3dsx','/3DS/pocketmap-main.3dsx')]: + data=pathlib.Path(local).read_bytes() + ftp.storbinary('STOR '+remote,io.BytesIO(data),blocksize=65536) + read=io.BytesIO(); ftp.retrbinary('RETR '+remote,read.write) + assert read.getvalue()==data,'FTP readback mismatch' + receipt.append({'path':remote,'bytes':len(data),'verified':True,**({'sha256':hashlib.sha256(data).hexdigest()} if local.endswith('.3dsx') else {})}) +ftp.quit(); print(json.dumps(receipt,indent=2)) +`; +const result = Bun.spawnSync(["python3", "-c", script, address, slot], { stdout: "pipe", stderr: "pipe" }); +if (result.exitCode) throw new Error(result.stderr.toString()); +await Bun.write("dist/qa/deploy.json", result.stdout); console.log(result.stdout.toString()); diff --git a/scripts/quickjs-smoke.js b/scripts/quickjs-smoke.js new file mode 100644 index 0000000..f9203d5 --- /dev/null +++ b/scripts/quickjs-smoke.js @@ -0,0 +1,47 @@ +// QuickJS execution/stack check with host stubs. Pixels are covered by sim.ts. +let node = 3, texture = 1, session = -1, ticks = 0, token = 1; +const replies = [], tickets = new Set(), saved = []; +globalThis.ui = { __host: "3ds-dev", __hostAbi: 8, __viewport: { w: 400, h: 240 }, __auxiliarySurface: { root: 2, w: 320, h: 240 }, + __textures: { "shift.svg": 0, "shift-lock.svg": 1, "map-pad.svg": 2, "map-pin.svg": 3 }, __sprites: {}, createNode: () => node++, measureText: text => text.length * 7 }; +for (const name of ["destroyNode", "insertBefore", "removeChild", "setStyle", "setProp", "setPropBatch", "setText", "replaceText", "uploadTexture", "setImage", "setSprite", "animate", "cancelAnim", "setFocus", "setActive", "hitTest", "hitTestBounds", "hitTestAuxiliary", "hitTestBoundsAuxiliary", "setCursor", "setCursorPos", "loadStyles", "loadFontAtlas", "loadTileTexture", "freeTexture", "uploadImgEntry", "debugInspect", "debugRectXY", "debugRectWH", "debugPause", "debugStep", "debugStats", "__dbgActive", "__dbgPoll", "__dbgSend", "__dbgShot"]) ui[name] = () => 0; +globalThis.offload = { + session: () => session, take: () => replies.shift(), + uploadImage: id => tickets.has(id) ? texture++ : -1, releaseImage: id => tickets.delete(id), + submit(raw) { + const r = JSON.parse(raw); + if (r.response === "image") { const id = token++; tickets.add(id); replies.push(JSON.stringify({ id: r.id, image: { token: id, width: 256, height: r.method === "map.label" ? 32 : 256 } })); } + else { + let value; + if (r.method === "bookmarks.list") value = { items: saved, offset: 0, total: saved.length }; + else if (r.method === "bookmarks.command") { + const c = JSON.parse(r.payload), id = "b_0123456789abcdef01234567"; + if (c.kind === "save") saved.push({ ...c.place, id }); + else if (c.kind === "rename") saved[0].name = c.name; + else saved.length = 0; + value = { id }; + } else value = r.method === "map.info" ? { source: "0123456789abcdef", name: "Smoke map", attribution: "Test", maxZoom: 18 } : [{ id: "one", name: "Tokyo", detail: "Japan", lat: 35.68, lon: 139.76, zoom: 14 }]; + replies.push(JSON.stringify({ id: r.id, payload: JSON.stringify(value) })); + } + return true; + }, +}; +globalThis.__simHz = 60; +function frames(n, buttons = 0, analog = 0x8080) { for (let i = 0; i < n; i++) { frame(buttons, analog, [], [], [], 0x8080); ticks++; } } +function check(value, message) { if (!value) throw new Error(message); } +try { + std.loadScript(scriptArgs[1] || "runtime/dist/3ds/guest/pocketmap-main.js"); + const s = globalThis.__map; frames(30); check(s.mode() === "map", "offline mount"); + session = 1; frames(90); check(s.front().tiles.every(t => s.frontView.state(t.input).status === "ready"), "tile reveal"); + frames(300, 0, 0x80ff); s.zoom(1); frames(90); s.zoom(-1); frames(90); + s.openSearch(); s.key("t"); check(s.query() === "t", "local typing"); s.search(); frames(60); check(s.places().length === 1, "search"); + s.go(); frames(90); check(s.pin().name === "Tokyo", "place navigation"); + s.saveCurrent(); check(s.mode() === "name", "save naming mount"); s.saved.changeName("Saved in QuickJS"); s.key("GO"); frames(60); + check(s.mode() === "saved" && s.saved.page().total === 1, "saved list mount"); + s.saved.begin(s.saved.selected(), true); s.saved.changeName("Renamed"); s.key("GO"); frames(60); + check(s.saved.selected().name === "Renamed", "rename mount"); + s.saved.askRemove(); frames(20); s.saved.remove(); frames(60); check(s.saved.page().total === 0, "delete sheet lifecycle"); s.dismiss(); + frames(1, 0x100); frames(1); frames(1, 0x200); frames(1); + session = -1; frames(30); session = 2; frames(100); + check(s.diagnostics().tiles.entries <= 40 && tickets.size === 0, "resource ownership"); + std.puts(JSON.stringify({ ok: true, frames: ticks, nodeIds: node, uploads: texture, pendingTickets: tickets.size }) + "\n"); +} catch (error) { std.puts(String(error) + "\n" + error.stack + "\n"); std.exit(1); } diff --git a/scripts/setup.ts b/scripts/setup.ts new file mode 100644 index 0000000..9139295 --- /dev/null +++ b/scripts/setup.ts @@ -0,0 +1,9 @@ +import { existsSync, mkdirSync, symlinkSync, rmSync } from "node:fs"; +import { resolve, dirname, relative } from "node:path"; +const root = resolve(import.meta.dir, ".."); +for (const [name, target] of Object.entries({ "@pocketjs/framework": "runtime", "solid-js": "runtime/node_modules/solid-js", "@napi-rs/canvas": "runtime/node_modules/@napi-rs/canvas", "@types": "runtime/node_modules/@types", "bun-types": "runtime/node_modules/bun-types" })) { + const source = resolve(root, target), destination = resolve(root, "node_modules", name); + if (!existsSync(source)) throw new Error(`Missing ${target}; initialize the runtime submodule and run bun install there`); + mkdirSync(dirname(destination), { recursive: true }); rmSync(destination, { recursive: true, force: true }); + symlinkSync(relative(dirname(destination), source), destination, "dir"); +} diff --git a/scripts/sim.ts b/scripts/sim.ts new file mode 100644 index 0000000..64de800 --- /dev/null +++ b/scripts/sim.ts @@ -0,0 +1,147 @@ +import { mkdirSync } from "node:fs"; +import { createCanvas } from "@napi-rs/canvas"; +import { createWasmUi } from "../runtime/hosts/web/wasm-ops.js"; +import { NODE_TYPE, PROP, BTN } from "../runtime/contracts/spec/spec.ts"; +import { encodePNG } from "../runtime/tests/png.ts"; +import { dispatchOffload } from "../runtime/tools/offload-provider.ts"; +import { MapProvider, defaultConfig } from "../host/provider.ts"; +import type { MapModel } from "../app/model.ts"; +import type { OffloadImage } from "../runtime/contracts/spec/offload.ts"; +const live = process.argv.includes("--live"); +const fixture = createCanvas(256, 256), c = fixture.getContext("2d"); +c.fillStyle = "#e8e5d7"; c.fillRect(0, 0, 256, 256); c.fillStyle = "#b3ced7"; c.fillRect(170, 0, 86, 256); +for (let x = 14; x < 170; x += 30) { c.fillStyle = "#fffdf4"; c.fillRect(x, 0, 5, 256); } +for (let y = 20; y < 256; y += 32) { c.fillStyle = "#fffdf4"; c.fillRect(0, y, 170, 5); } +c.fillStyle = "#b8cfa4"; c.fillRect(50, 70, 55, 48); c.fillStyle = "#5e705e"; c.font = "13px Arial"; c.fillText("Replay fixture", 30, 155); +const provider = new MapProvider({ ...defaultConfig, cache: live ? ".local/cache.sqlite" : ":memory:" }, live ? fetch : (async url => { + if (String(url).includes("photon")) return new Response(JSON.stringify({ features: [ + { properties: { osm_type: "R", osm_id: 1, name: "San Francisco", city: "San Francisco", country: "United States", type: "city" }, geometry: { coordinates: [-122.4075, 37.7879] } }, + { properties: { osm_type: "N", osm_id: 2, name: "Museum of Modern Art", city: "San Francisco", type: "other" }, geometry: { coordinates: [-122.4007, 37.7859] } }, + ] })); + return new Response(fixture.toBuffer("image/png")); +}) as typeof fetch); +const wasm = await createWasmUi(await Bun.file("runtime/hosts/web/pocketjs.wasm").arrayBuffer(), { width: 400, height: 480 }); +const ops = wasm.ops; +ops.hitTestBoundsAuxiliary = (x, y) => ops.hitTestBounds!(x + 40, y + 240); +(ops as any).__viewport = { w: 400, h: 240 }; +const auxiliary = ops.createNode(NODE_TYPE.view); +for (const [prop, n] of [[PROP.posType, 1], [PROP.insetL, 40], [PROP.insetT, 240], [PROP.width, 320], [PROP.height, 240]]) ops.setProp(auxiliary, prop, n); +ops.insertBefore(1, auxiliary, 0); ops.__auxiliarySurface = { root: auxiliary, w: 320, h: 240 }; +const requests: string[] = [], replies: { at: number; raw: string }[] = []; +const images = new Map(); +let tick = 0, token = 1, session = 1, uploads = 0, maxStaging = 0, maxPending = 0, maxResident = 0, withhold = false, loseCommandAck = false; +let hit: number | undefined; +const checks: string[] = [], failures: string[] = []; +Object.assign(globalThis, { ui: ops, __pak: await Bun.file("runtime/dist/3ds/guest/pocketmap-main.pak").arrayBuffer(), __simHz: 60, + offload: { session: () => session, submit: (raw: string) => { if (requests.length >= 8) return false; requests.push(raw); return true; }, + take: () => { const n = replies.findIndex(r => r.at <= tick && !withhold); return n < 0 ? undefined : replies.splice(n, 1)[0].raw; }, + uploadImage: (id: number) => { + const image = images.get(id); if (!image || uploads >= 1) return -1; uploads++; + const bytes = new Uint8Array(8 + image.pixels.length), view = new DataView(bytes.buffer); + view.setUint16(0, image.width, true); view.setUint16(2, image.height, true); bytes[5] = 2; bytes.set(image.pixels, 8); + return ops.uploadImgEntry!(bytes); + }, + releaseImage: (id: number) => { images.delete(id); }, + }, +}); +(0, eval)(await Bun.file("runtime/dist/3ds/guest/pocketmap-main.js").text()); +const s = (globalThis as any).__map as MapModel; +if (!s) throw new Error("Guest did not mount"); +function check(value: unknown, text: string) { if (!value) { failures.push(text); throw new Error(text); } checks.push(text); } +async function frames(n: number, buttons = 0, touch?: [number, number], analog = 0x8080) { + if (touch && hit === undefined) { wasm.render(); hit = ops.hitTestBounds!(touch[0] + 40, touch[1] + 240); } + if (!touch) hit = undefined; + for (let i = 0; i < n; i++) { + tick++; uploads = 0; + (globalThis as any).frame(buttons, analog, touch ? [touch[0] | touch[1] << 9] : [], touch ? [hit] : [], touch ? [1] : [], 0x8080); + wasm.tick(); + const d = s.diagnostics(); maxPending = Math.max(maxPending, d.pending); maxResident = Math.max(maxResident, d.tiles.entries); + while (requests.length && images.size < 8) { + const raw = requests.shift()!; + const request = JSON.parse(raw), result = await dispatchOffload(provider.methods(), request); + if (loseCommandAck && request.method === "bookmarks.command") { + loseCommandAck = false; replies.push({ at: tick + 3, raw: JSON.stringify({ id: result.id, error: "Simulated lost acknowledgement" }) }); continue; + } + if (result.image) { + const id = token++; images.set(id, result.image); maxStaging = Math.max(maxStaging, images.size); + replies.push({ at: tick + 3, raw: JSON.stringify({ id: result.id, image: { token: id, width: result.image.width, height: result.image.height } }) }); + } else replies.push({ at: tick + 3, raw: JSON.stringify(result) }); + } + } +} +async function tap(x: number, y: number) { await frames(1, 0, [x, y]); await frames(1); } +async function press(button: number) { await frames(1, button); await frames(1); } +mkdirSync("dist/qa", { recursive: true }); +async function shot(name: string) { await Bun.write(`dist/qa/${live ? "live-" : "replay-"}${name}.png`, encodePNG(wasm.render().slice(), 400, 480)); } +await frames(3); await shot("loading"); await frames(75); +if (live && !s.front()!.tiles.every(t => s.frontView.state(t.input).status === "ready")) console.log(s.front()!.tiles.map(t => ({ input: t.input, state: s.frontView.state(t.input) }))); +check(s.front()!.tiles.every(t => s.frontView.state(t.input).status === "ready"), "All visible tiles materialize through resource demand and native image tickets"); +await shot("map"); +await tap(30, 18); check(s.mode() === "search", "Search touch button opens local keyboard"); +await shot("keyboard"); +if (live) { + // One requested view and one explicit search. Stress replay never uses public tiles. + s.setQuery("San Francisco"); s.search(); await frames(35); await shot("results"); + check(s.places().length > 0, "Live Photon search returned places"); +} else { + await tap(20, 50); check(s.query() === "q", "Resistive keyboard hit inserts immediately"); + s.setQuery("San Francisco"); await tap(263, 216); await frames(35); + check(s.mode() === "results" && s.places().length === 2, "Explicit Find shows bounded search results"); await shot("results"); + await press(BTN.DOWN); check(s.selection() === 1, "D-pad selects a place on the non-touch display"); + await tap(263, 216); await frames(60); check(s.mode() === "map" && s.pin()?.name === "Museum of Modern Art", "Go centers the map on the selected result and adds a pin"); await shot("pin"); + const before = s.camera.view(); + await frames(1, 0, [140, 110]); await frames(1, 0, [155, 123]); await frames(1, 0, [173, 140]); await frames(1); + const released = s.camera.view(); await frames(10); + check(released.x < before.x && s.camera.view().x < released.x, "Touchpad follows stylus immediately and continues with inertia"); + s.camera.stop(); const zoomBefore = s.camera.view().zoom; + await tap(287, 73); await frames(32); check(s.camera.view().zoom > zoomBefore + 0.99, "Zoom control changes scale through a smooth local transition"); await frames(50); await shot("zoom"); + withhold = true; const position = s.camera.view().y; + await frames(180, 0, undefined, 0x80ff); + check(s.camera.view().y > position, "Sustained Circle Pad pan continues while all replies are withheld"); + withhold = false; session = -1; await frames(12); await shot("disconnected"); session = 2; await frames(130); + check(s.online() && s.front()!.tiles.every(t => s.frontView.state(t.input).status === "ready"), "Reconnect fences old responses and refills the current viewport"); + s.camera.jump(255.999, 128, 8); await frames(60); await frames(160, 0, undefined, 0xff80); await frames(100); + check(s.camera.view().x >= 0 && s.camera.view().x < 256, "Date-line navigation keeps coordinates and tile demand bounded"); + await frames(1, BTN.LTRIGGER); await shot("places-menu"); await frames(1); + await frames(1, BTN.RTRIGGER); await shot("map-menu"); await frames(1); + console.log({ maxPending, maxResident, maxStaging }); + check(maxPending <= 4 && maxResident <= 40 && maxStaging <= 8, "Request credit, texture residency and staging remain within their independent budgets"); + await frames(100); check(images.size === 0, "Consumed and cancelled image staging is released after churn"); + await tap(155, 216); check(s.mode() === "name", "Save view opens a separate local naming keyboard"); + await shot("save-name"); await tap(40, 216); await tap(20, 50); check(s.saved.name() === "q", "Naming input updates locally without a host round trip"); + s.saved.changeName("My coffee stop"); loseCommandAck = true; + await tap(240, 216); await frames(20); + check(!!s.saved.error() && provider.bookmarks.list(0).total === 1, "A lost save acknowledgement leaves a visible retry state after the Mac commits"); + await tap(240, 216); await frames(35); + check(s.mode() === "saved" && s.saved.page()?.total === 1 && provider.bookmarks.list(0).total === 1, "Retry confirms the same save without duplicating user data"); await shot("saved"); + await tap(50, 216); check(s.mode() === "name" && !!s.saved.editing(), "Rename starts from the selected saved place"); + s.saved.changeName("Morning coffee"); await tap(240, 216); await frames(35); + check(s.saved.selected()?.name === "Morning coffee", "Rename updates the saved list after persistence"); + const savedPoint = s.saved.selected()!; await tap(263, 216); await frames(35); + check(s.mode() === "map" && s.pin()?.id === savedPoint.id, "Go to saved place restores coordinates, zoom and pin"); + await tap(263, 216); await frames(35); await tap(155, 216); await frames(16); await shot("delete"); + check(!!s.saved.deleting() && s.saved.modal(), "Delete opens the animated modal confirmation"); + await press(BTN.CROSS); await frames(15); check(provider.bookmarks.list(0).total === 1 && !s.saved.modal(), "B cancels deletion and keeps the place"); + for (let n = 0; n < 5; n++) provider.bookmarks.command({ op: `replay_place_000${n}`, kind: "save", place: { ...savedPoint, name: `Place ${n}` } }); + s.saved.refresh(); await frames(35); await tap(286, 152); await frames(35); + check(s.saved.page()?.offset === 5 && s.saved.selected()?.name === "Morning coffee", "Saved places paginate through the same right-hand control rail"); + await tap(155, 216); await frames(16); await tap(150, 180); await frames(35); + check(s.saved.page()?.offset === 0 && s.saved.page()?.total === 5 && !s.saved.modal(), "Deleting the last row of a page returns to a populated page"); + await tap(30, 18); await frames(50); + const oldTiles = s.front()!.tiles; + s.camera.stop(); s.camera.drag(256, 0); await frames(1); + const overlapping = s.front()!.tiles.filter(t => oldTiles.some(o => o.column === t.column && o.row === t.row)); + check(overlapping.length > 0 && overlapping.every(t => oldTiles.includes(t)), "Crossing a tile column retains existing component identities"); + await frames(40); + s.camera.jump(128, 128, 8); await frames(80); + const ahead = s.lookAhead(); check(ahead.length > 0 && ahead.length <= 4 && ahead.every(t => s.frontView.state(t.input).status === "ready"), "Modest look-ahead materializes no more than four adjacent tiles"); + if (ahead.length) { + const t = ahead[0], scale = 2 ** t.input.z; + s.camera.jump((t.column + 0.5) * 256 / scale, (t.row + 0.5) * 256 / scale, t.input.z); await frames(1); + check(s.frontView.state(t.input).status === "ready", "Entering a prefetched tile reveals its resident texture without waiting for the network"); + await frames(50); + } +} +const receipt = { mode: live ? "live OSM DE / Photon, compiled guest + Wasm" : "deterministic synthetic provider, compiled guest + Wasm", frames: tick, checks, maxPending, maxResident, maxStaging, downloads: provider.cache.downloads, cacheHits: provider.cache.hits, + hardwareAcceptance: "pending", performance: "Replay validates behavior and budgets, not device frame time" }; +await Bun.write(`dist/qa/${live ? "live" : "replay"}.json`, JSON.stringify(receipt, null, 2)); console.log(receipt); provider.close(); diff --git a/shared/types.ts b/shared/types.ts new file mode 100644 index 0000000..d23e762 --- /dev/null +++ b/shared/types.ts @@ -0,0 +1,7 @@ +export interface Place { id: string; name: string; detail: string; lat: number; lon: number; zoom: number } +export interface MapInfo { source: string; name: string; attribution: string; maxZoom: number } +export interface TileInput { source: string; z: number; x: number; y: number } +export interface SearchInput { query: string; lat: number; lon: number } +export interface BookmarkPage { items: Place[]; offset: number; total: number } +export interface BookmarkCommand { op: string; kind: "save" | "rename" | "remove"; id?: string; place?: Place; name?: string } +export const HOME = { lat: 37.7879, lon: -122.4075, zoom: 14 }; diff --git a/test/bookmarks.test.ts b/test/bookmarks.test.ts new file mode 100644 index 0000000..af80f10 --- /dev/null +++ b/test/bookmarks.test.ts @@ -0,0 +1,30 @@ +import { test, expect } from "bun:test"; +import { mkdtempSync, rmSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; +import { Bookmarks } from "../host/bookmarks.ts"; +import type { BookmarkCommand } from "../shared/types.ts"; +const place = { id: "N1", name: "Coffee", detail: "Market Street", lat: 37.7, lon: -122.4, zoom: 16 }; +test("saved places survive reopening, paginate and retain idempotent mutation receipts", () => { + const dir = mkdtempSync(join(tmpdir(), "pocket-map-saved-")); let db = new Bookmarks(join(dir, "places.sqlite")); + try { + const save: BookmarkCommand = { op: "save_receipt_0001", kind: "save", place }; + const reply = db.command(save); const id = JSON.parse(reply).id; + db.close(); db = new Bookmarks(join(dir, "places.sqlite")); + expect(db.command(save)).toBe(reply); expect(db.list(0).total).toBe(1); + const rename: BookmarkCommand = { op: "rename_receipt_01", kind: "rename", id, name: "Morning coffee" }; + expect(db.command(rename)).toBe(reply); expect(db.list(0).items[0].name).toBe("Morning coffee"); + for (let n = 0; n < 6; n++) db.command({ op: `save_next_item_0${n}`, kind: "save", place: { ...place, name: `Place ${n}` } }); + expect(db.list(0).items.map(p => p.name)).toEqual(["Place 5", "Place 4", "Place 3", "Place 2", "Place 1"]); + expect(db.list(5).items.map(p => p.name)).toEqual(["Place 0", "Morning coffee"]); + const remove: BookmarkCommand = { op: "remove_receipt_01", kind: "remove", id }; + db.command(remove); db.close(); db = new Bookmarks(join(dir, "places.sqlite")); + expect(db.command(remove)).toBe(reply); expect(db.command(save)).toBe(reply); expect(db.list(0).total).toBe(6); + expect(db.list(5).items).toHaveLength(1); // delayed save cannot resurrect a deleted place + db.command({ op: "remove_last_page", kind: "remove", id: db.list(5).items[0].id }); + expect(db.list(5).offset).toBe(0); expect(db.list(5).items).toHaveLength(5); + expect(() => db.command({ ...save, place: { ...place, name: "Different" } })).toThrow("reused"); + expect(() => db.command({ op: "bad_coordinates_1", kind: "save", place: { ...place, lat: NaN } })).toThrow("Invalid"); + expect(() => db.list(1)).toThrow("Invalid"); expect(() => db.list(1000)).toThrow("Invalid"); + } finally { db.close(); rmSync(dir, { recursive: true, force: true }); } +}); diff --git a/test/geo.test.ts b/test/geo.test.ts new file mode 100644 index 0000000..5cec7db --- /dev/null +++ b/test/geo.test.ts @@ -0,0 +1,11 @@ +import { expect, test } from "bun:test"; +import { project, unproject, wrapTile, scaleBar } from "../app/geo.ts"; +test("Mercator round trips real cities, wraps longitude and clamps poles", () => { + for (const [lat, lon] of [[37.7879, -122.4075], [35.6812, 139.7671], [51.5074, -0.1278], [-33.86, 151.2]]) { + const point = project(lat, lon), back = unproject(point.x, point.y); + expect(back.lat).toBeCloseTo(lat, 8); expect(back.lon).toBeCloseTo(lon, 8); + } + expect(project(0, 180).x).toBe(project(0, -180).x); + expect(project(90, 0).y).toBeCloseTo(0, 8); expect(wrapTile(-1, 4)).toBe(15); + const bar = scaleBar(37.78, 14); expect(bar.pixels).toBeLessThanOrEqual(70); expect(bar.pixels).toBeGreaterThan(15); +}); diff --git a/test/model.test.ts b/test/model.test.ts new file mode 100644 index 0000000..623f05e --- /dev/null +++ b/test/model.test.ts @@ -0,0 +1,23 @@ +import { expect, test } from "bun:test"; +import { createRoot } from "solid-js"; +import { createOffloadClient } from "@pocketjs/framework/offload"; +import { runFrameHooks, resetFrameHooks } from "../runtime/framework/src/frame.ts"; +import { __setAnalog } from "../runtime/framework/src/analog.ts"; +import { BTN } from "@pocketjs/framework/input"; +import { createMap } from "../app/model.ts"; +test("camera keeps moving while host requests wait; search is an explicit bounded command", () => { + resetFrameHooks(); + createRoot(dispose => { + const sent: string[] = []; + const io = createOffloadClient({ session: () => 1, submit: raw => { sent.push(raw); return true; }, take: () => undefined, uploadImage: () => 1, releaseImage() {} }); + const s = createMap(io); const before = s.camera.view().y; + for (let n = 0; n < 60; n++) { __setAnalog(0x80ff); runFrameHooks(0); io.step(); } + expect(s.camera.view().y).toBeGreaterThan(before); expect(sent).toHaveLength(1); expect(io.pending()).toBe(1); + s.openSearch(); s.key("a"); s.key("SPACE"); s.key("b"); expect(s.query()).toBe("a b"); + expect(s.submitted()).toBeUndefined(); s.search(); expect(s.submitted()?.query).toBe("a b"); expect(s.mode()).toBe("results"); + s.dismiss(); runFrameHooks(BTN.LTRIGGER); expect(s.menu()).toBe("places"); + runFrameHooks(BTN.LTRIGGER | BTN.CIRCLE); expect(s.mode()).toBe("search"); expect(s.menu()).toBeUndefined(); + dispose(); io.dispose(); + }); + resetFrameHooks(); +}); diff --git a/test/provider.test.ts b/test/provider.test.ts new file mode 100644 index 0000000..4f3cf1c --- /dev/null +++ b/test/provider.test.ts @@ -0,0 +1,68 @@ +import { expect, test } from "bun:test"; +import { createCanvas } from "@napi-rs/canvas"; +import { HttpCache, type NetworkFetch } from "../host/cache.ts"; +import { MapProvider, defaultConfig, packRGB } from "../host/provider.ts"; +const png = () => { const c = createCanvas(256, 256), ctx = c.getContext("2d"); ctx.fillStyle = "red"; ctx.fillRect(0, 0, 128, 256); ctx.fillStyle = "blue"; ctx.fillRect(128, 0, 128, 256); return c.toBuffer("image/png"); }; +test("host decodes PNGs, keeps exact PSM color order, deduplicates and rejects arbitrary URLs", async () => { + let calls = 0; + const provider = new MapProvider({ ...defaultConfig, cache: ":memory:" }, (async () => { calls++; return new Response(png()); }) as NetworkFetch); + try { + const input = { source: provider.info.source, z: 1, x: 0, y: 0 }; + const [a, b] = await Promise.all([provider.tile(input), provider.tile(input)]); + expect(a).toBe(b); expect(calls).toBe(1); expect(a.pixels.length).toBe(131072); + expect([...a.pixels.slice(0, 2)]).toEqual([31, 0]); expect([...a.pixels.slice(256, 258)]).toEqual([0, 248]); + await provider.tile(input); expect(calls).toBe(1); + await expect(provider.tile({ ...input, x: -1 })).rejects.toThrow(); + await expect(provider.tile({ ...input, source: "other" })).rejects.toThrow(); + await expect(provider.tile({ ...input, z: 99 })).rejects.toThrow(); + expect(calls).toBe(1); + expect([...packRGB(new Uint8Array([0, 0, 0, 0]), 1, 1).pixels]).toEqual([255, 255]); + } finally { provider.close(); } +}); +test("host cache persists reuse and conditional expiry, bounds bodies and honors no-store", async () => { + let calls = 0, conditional = false; + const cache = new HttpCache(":memory:", (async (_url, options) => { + calls++; conditional = !!(options?.headers as Record)["If-None-Match"]; + return calls === 1 ? new Response("cached", { headers: { etag: "one", "cache-control": "max-age=0" } }) : new Response(null, { status: 304, headers: { "cache-control": "max-age=3600" } }); + }) as NetworkFetch); + try { + const opts = { maxBytes: 20, ttl: 1000 }; + await cache.get("https://example.com/tile", opts); const b = await cache.get("https://example.com/tile", opts); await cache.get("https://example.com/tile", opts); + expect(conditional).toBe(true); expect(calls).toBe(2); expect(new TextDecoder().decode(b)).toBe("cached"); + } finally { cache.close(); } + const huge = new HttpCache(":memory:", (async () => new Response(new Uint8Array(40))) as NetworkFetch); + await expect(huge.get("https://example.com", { maxBytes: 20, ttl: 1000 })).rejects.toThrow("budget"); huge.close(); + let n = 0; + const noStore = new HttpCache(":memory:", (async () => { n++; return new Response("ok", { headers: { "cache-control": "no-store" } }); }) as NetworkFetch); + await noStore.get("https://example.com", { maxBytes: 20, ttl: 1000 }); await noStore.get("https://example.com", { maxBytes: 20, ttl: 1000 }); expect(n).toBe(2); noStore.close(); +}); +test("malformed dimensions cannot trigger an unbounded host image decode", async () => { + const bytes = png(); bytes.writeUInt32BE(100000, 16); + const provider = new MapProvider({ ...defaultConfig, cache: ":memory:" }, (async () => new Response(bytes)) as NetworkFetch); + await expect(provider.tile({ source: provider.info.source, z: 1, x: 0, y: 0 })).rejects.toThrow("256px"); provider.close(); +}); +test("real Bun fetch accepts conditional 304 without following redirects", async () => { + let calls = 0, followed = 0; + const server = Bun.serve({ port: 0, hostname: "127.0.0.1", fetch(request) { + if (new URL(request.url).pathname === "/redirect") return new Response(null, { status: 302, headers: { location: "/forbidden" } }); + if (new URL(request.url).pathname === "/forbidden") { followed++; return new Response("unexpected"); } + calls++; + return request.headers.has("if-none-match") ? new Response(null, { status: 304, headers: { "cache-control": "max-age=3600" } }) : new Response("tile", { headers: { etag: "v1", "cache-control": "max-age=0" } }); + } }); + const cache = new HttpCache(":memory:"); const options = { maxBytes: 20, ttl: 1000 }, url = `http://127.0.0.1:${server.port}`; + try { + await cache.get(url, options); expect(new TextDecoder().decode(await cache.get(url, options))).toBe("tile"); + await cache.get(url, options); expect(calls).toBe(2); + await expect(cache.get(url + "/redirect", options)).rejects.toThrow("302"); expect(followed).toBe(0); + } finally { cache.close(); server.stop(true); } +}); +test("search handles empty, malformed and duplicate results with a bounded response", async () => { + const feature = { properties: { name: "Tokyo", osm_type: "N", osm_id: 1, country: "Japan", type: "city" }, geometry: { coordinates: [139.76, 35.68] } }; + const provider = new MapProvider({ ...defaultConfig, cache: ":memory:" }, (async url => { + expect(new URL(String(url)).searchParams.get("limit")).toBe("5"); + return new Response(JSON.stringify({ features: [feature, feature, { ...feature, geometry: { coordinates: [500, 1000] } }] })); + }) as NetworkFetch); + expect(await provider.search({ query: " ", lat: 0, lon: 0 })).toEqual([]); + expect(await provider.search({ query: "Tokyo", lat: 0, lon: 0 })).toEqual([{ id: "N1", name: "Tokyo", detail: "Japan", lat: 35.68, lon: 139.76, zoom: 13 }]); + await expect(provider.search({ query: "x".repeat(81), lat: 0, lon: 0 })).rejects.toThrow(); provider.close(); +}); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..3224eea --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,4 @@ +{ + "compilerOptions": { "target": "ESNext", "module": "ESNext", "moduleResolution": "bundler", "lib": ["ESNext"], "types": ["bun"], "jsx": "preserve", "strict": true, "noEmit": true, "allowImportingTsExtensions": true, "skipLibCheck": true }, + "include": ["app", "host", "shared", "scripts", "test", "runtime/framework/src/jsx.d.ts"] +} From 501e79f37482e4365d2e33edfe05ba2e019dc668 Mon Sep 17 00:00:00 2001 From: "Yifeng \"Evan\" Wang" <7312949+doodlewind@users.noreply.github.com> Date: Sun, 6 Sep 2026 15:22:17 -0700 Subject: [PATCH 02/13] fix(map): isolate native work and bound cancelled tile traffic --- README.md | 6 +++-- docs/ARCHITECTURE.md | 20 +++++++++++++++-- docs/VALIDATION.md | 26 ++++++++++++++++++++-- host/config.ts | 5 +++++ host/provider.ts | 7 ++---- host/serve.ts | 5 +++-- package.json | 2 +- runtime | 2 +- test/transport.test.ts | 50 ++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 108 insertions(+), 15 deletions(-) create mode 100644 host/config.ts create mode 100644 test/transport.test.ts diff --git a/README.md b/README.md index bf5e1f9..cdc2c65 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Pocket Map -A map browser for Nintendo 3DS, built with [PocketJS](https://github.com/pocket-stack/pocketjs) and SolidJS 1.9. Search for places, pan with the resistive touch screen, and zoom the map on the upper display. A paired Mac handles network requests, SQLite caching, PNG decoding, label rasterization and saved places. +A map browser for Nintendo 3DS, built with [PocketJS](https://github.com/pocket-stack/pocketjs) and SolidJS 1.9. Search for places, pan with the resistive touch screen, and zoom the map on the upper display. A paired Mac handles network requests, SQLite caching, PNG decoding, label rasterization and saved places in a separate capability process.

Pocket Map displaying real OpenStreetMap tiles on a compiled dual-screen guest Live Photon place results with the bottom-screen selection touchpad

@@ -40,6 +40,8 @@ Exit ftpd and open **Pocket Map** in HBL. The deployment script installs only th | B | Dismiss results/menu; backspace while typing | | Shift | Tap for one uppercase letter; double-tap for caps lock | +The Mac keeps connection management separate from native decoding and network work. If the capability process exits, it is reaped and replaced on reconnect. Socket backpressure pauses traffic; cancelling a sent device request retains its wire credit until a reply or disconnection. + Typing, dragging, inertia and zoom transitions update locally. Missing tiles show a fallback; an already loaded previous zoom level stays visible during replacement. A disconnected Mac leaves resident tiles navigable. Search, new tiles and uncached labels require the Mac. ## Saved places @@ -80,7 +82,7 @@ Public services have limited capacity: [OSM DE's terms](https://openstreetmap.de ## Architecture and resource pattern ```text -3DS UI thread 3DS network worker Mac provider worker +3DS UI thread 3DS network worker Mac capability process camera + controls authenticated TCP HTTPS + SQLite cache visible tile demand -> bounded request queue -> fetch / PNG decode ResourceImage fallback <- native image tickets <- binary R5G6B5 pixels diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 14008be..1f10496 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -9,7 +9,7 @@ subscriptions. Continuous camera movement writes paint transforms through PocketJS `hot` APIs; a tile window change updates the component tree. The native offload worker owns sockets, the SD pairing-key read and binary -reception. The paired Mac's worker owns HTTPS, SQLite, PNG decoding, optional +reception. The paired Mac's capability process owns HTTPS, SQLite, PNG decoding, optional Unicode label rasterization and R5G6B5 packing. Provider socket callbacks pass bounded requests and replies; they do not execute these capabilities. @@ -66,6 +66,22 @@ ownership have different roles. An old zoom layer retains loaded resources while the new layer demands current tiles. It never requests an unseen parent pyramid or downloads a city in advance. +## Transport recovery + +**The Mac connection manager does not import the native canvas module.** It +starts the existing capability module with `isolation: "process"`, using Bun IPC +instead of a Web Worker. Socket loss, a process crash or a nine-second task +deadline ends that session. The old process is reaped before the next starts; +its replies cannot cross connection generations. SQLite mutations retain their +operation receipts across process replacement. + +The device retains transmission credit after a sent request is cancelled or +times out, until its reply arrives or the session ends. The Mac pauses reads at +eight executing requests and pauses writes until the socket drains. Slow image +transfer therefore cannot build a queue proportional to cancelled viewports. +Connection logs name socket failures, process exits and timed-out methods; +they omit query text and command payloads. + ## Motion and recovery `createTileCamera` stores level-zero coordinates and log2 zoom. Dragging applies @@ -118,7 +134,7 @@ leave a retry action which retains the operation ID. Cancellation of that UI cannot roll back a completed Mac write. Successful writes invalidate saved pages; deleting the last row of a page makes the provider return the preceding populated page. User data lives in `places.sqlite`; HTTP-cache eviction never -touches it. The Mac performs all SQL work in its provider worker. +touches it. The Mac performs all SQL work in its provider process. ## Scope diff --git a/docs/VALIDATION.md b/docs/VALIDATION.md index a4b0af5..0aec079 100644 --- a/docs/VALIDATION.md +++ b/docs/VALIDATION.md @@ -2,7 +2,7 @@ ## Local execution -- Eight app tests cover Mercator wrapping, immediate controller motion while IO +- Nine app tests cover Mercator wrapping, immediate controller motion while IO waits, keyboard submission, menu ownership, HTTP validators, cache limits, duplicate requests, pixel order, invalid image dimensions and bounded search results, including a real Bun HTTP 304 cache revalidation. Saved-place tests reopen SQLite, replay committed writes, reject @@ -12,7 +12,7 @@ placing a pin, touch inertia, animated zoom, 180 frames with replies withheld, disconnect/reconnect, date-line navigation and menu presentation. - Observed replay maxima: three pending guest requests, 40 resident tile - entries and eight native-image staging tickets. Staging drains to zero after + entries and three native-image staging tickets (the pool limit is eight). Staging drains to zero after navigation settles. Generated receipts are in `dist/qa/replay.json`. - Live OSM DE tiles and Photon search passed through the same compiled guest and resource API. Captures in this README are from that Wasm replay. The live @@ -48,3 +48,25 @@ replay covers those flows, including lost-acknowledgement retries and a resident prefetched tile becoming visible. Physical gesture and frame-time validation of this revision remain pending. Build, native transport, Wasm visuals, device liveness and physical input remain separate evidence. + +## Device disconnect investigation + +The uploaded revision lost its Mac daemon after a Bun 1.3.14 native crash on a +Worker thread. Session diagnostics added during recovery then recorded +`device response backlog exceeded` and request-credit exhaustion during tile +churn. The previous transport closed the socket at those limits, terminated +the active Worker and exposed the daemon to a native teardown crash. + +The fix uses a separate capability process, pauses transport input/output when +credit is occupied and preserves device reservations for cancelled sent work. +A native transport test covers both execution modes. Fault tests kill a child +process, disconnect eight times during fetch, trigger a wedged-task deadline, +and drain a paused receiver's burst of 64 full-size images without losing its +connection. An app test runs the actual PNG provider across three interrupted +fetches, then verifies every pixel of a returned 256px image. UI replay and +QuickJS checks cover the revised guest cancellation semantics. + +The revised Mac daemon is running with process isolation and socket +backpressure and has reconnected to the physical 3DS. The current guest patch +preserving transmission credit is built and passes replay / QuickJS checks; +its upload and physical interaction acceptance require ftpd to be opened. diff --git a/host/config.ts b/host/config.ts new file mode 100644 index 0000000..b36a7a3 --- /dev/null +++ b/host/config.ts @@ -0,0 +1,5 @@ +export interface ProviderConfig { tileURL: string; searchURL: string; name: string; attribution: string; maxZoom: number; cache: string } +export const defaultConfig: ProviderConfig = { + tileURL: "https://tile.openstreetmap.de/{z}/{x}/{y}.png", searchURL: "https://photon.komoot.io/api/", + name: "OpenStreetMap DE", attribution: "OpenStreetMap contributors", maxZoom: 18, cache: ".local/cache.sqlite", +}; diff --git a/host/provider.ts b/host/provider.ts index ea1691b..1606e5d 100644 --- a/host/provider.ts +++ b/host/provider.ts @@ -6,11 +6,8 @@ import { Bookmarks } from "./bookmarks.ts"; import { join, dirname } from "node:path"; import type { MapInfo, Place, SearchInput, TileInput } from "../shared/types.ts"; -export interface ProviderConfig { tileURL: string; searchURL: string; name: string; attribution: string; maxZoom: number; cache: string } -export const defaultConfig: ProviderConfig = { - tileURL: "https://tile.openstreetmap.de/{z}/{x}/{y}.png", searchURL: "https://photon.komoot.io/api/", - name: "OpenStreetMap DE", attribution: "OpenStreetMap contributors", maxZoom: 18, cache: ".local/cache.sqlite", -}; +import type { ProviderConfig } from "./config.ts"; +export { defaultConfig, type ProviderConfig } from "./config.ts"; export function packRGB(rgba: Uint8ClampedArray | Uint8Array, width: number, height: number): OffloadImage { if (rgba.byteLength !== width * height * 4) throw new Error("Invalid pixel plane"); const pixels = new Uint8Array(width * height * 2); diff --git a/host/serve.ts b/host/serve.ts index ad70725..334d9ae 100644 --- a/host/serve.ts +++ b/host/serve.ts @@ -1,10 +1,11 @@ import { resolve } from "node:path"; import { connectOffloadProvider } from "@pocketjs/framework/offload/provider"; -import { defaultConfig } from "./provider.ts"; +import { defaultConfig } from "./config.ts"; const root = resolve(import.meta.dir, ".."); const address = process.argv[2] ?? "192.168.8.102"; const configPath = resolve(root, ".local/provider.json"); const config = { ...defaultConfig, ...(await Bun.file(configPath).exists() ? await Bun.file(configPath).json() : {}), cache: resolve(root, ".local/cache.sqlite") }; const key = (await Bun.file(resolve(root, ".local/pair.key")).text()).trim(); -connectOffloadProvider({ address, key, worker: new URL("./worker.ts", import.meta.url), data: config, log: console.log }); +connectOffloadProvider({ address, key, worker: new URL("./worker.ts", import.meta.url), isolation: "process", data: config, + log: message => console.log(new Date().toISOString(), message) }); console.log(`Pocket Map: ${config.name} -> ${address}; cache ${config.cache}`); diff --git a/package.json b/package.json index a2fd435..d6aaaf2 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "scripts": { "setup": "bun scripts/setup.ts", "3ds": "bun scripts/build.ts", "host": "bun host/serve.ts", "deploy": "bun scripts/deploy.ts", "sim": "bun scripts/sim.ts", - "test": "bun test --conditions=browser test/geo.test.ts test/provider.test.ts test/model.test.ts test/bookmarks.test.ts", + "test": "bun test --conditions=browser test/geo.test.ts test/provider.test.ts test/model.test.ts test/bookmarks.test.ts test/transport.test.ts", "check": "bun run test && runtime/node_modules/.bin/tsc --noEmit" } } diff --git a/runtime b/runtime index e5c94e3..b43e0df 160000 --- a/runtime +++ b/runtime @@ -1 +1 @@ -Subproject commit e5c94e387e4d88129881f0285c91f46c7d7f5ed4 +Subproject commit b43e0df47ac68dbe922af0c0b57609ae6e4f51ac diff --git a/test/transport.test.ts b/test/transport.test.ts new file mode 100644 index 0000000..1b009a0 --- /dev/null +++ b/test/transport.test.ts @@ -0,0 +1,50 @@ +import { test, expect } from "bun:test"; +import { createServer, type Socket } from "node:net"; +import { createCanvas } from "@napi-rs/canvas"; +import { connectOffloadProvider } from "@pocketjs/framework/offload/provider"; +import { encodeOffloadRecord } from "../runtime/tools/offload-wire.ts"; +import { defaultConfig } from "../host/config.ts"; +function queue() { + const items: T[] = [], waits: ((value: T) => void)[] = []; + return { push(v: T) { const take = waits.shift(); if (take) take(v); else items.push(v); }, + take(): Promise { return items.length ? Promise.resolve(items.shift()!) : new Promise(resolve => waits.push(resolve)); } }; +} +test("actual map provider reconnects during PNG fetch and returns intact image pixels in a fresh process", async () => { + const canvas = createCanvas(256, 256), ctx = canvas.getContext("2d"); ctx.fillStyle = "red"; ctx.fillRect(0, 0, 256, 256); + const png = canvas.toBuffer("image/png"), fetched = queue(); let hold = true; + const http = Bun.serve({ hostname: "127.0.0.1", port: 0, async fetch() { fetched.push(); if (hold) await Bun.sleep(250); return new Response(png); } }); + const peers = queue<{ socket: Socket; read(): Promise; send(method: string, id: number, payload?: unknown, image?: boolean): void }>(); + const sockets = new Set(); + const server = createServer(socket => { + sockets.add(socket); socket.on("close", () => sockets.delete(socket)); socket.on("error", () => {}); + let paired = false, buffer = Buffer.alloc(0); const replies = queue(); + socket.on("data", bytes => { + buffer = Buffer.concat([buffer, Buffer.from(bytes)]); + if (!paired) { + if (buffer.length < 64) return; + expect(buffer.subarray(0, 64).toString()).toBe("ab".repeat(32)); buffer = buffer.subarray(64); paired = true; + peers.push({ socket, read: replies.take, send(method, id, payload = {}, image = false) { socket.write(encodeOffloadRecord(JSON.stringify({ v: 1, id, method, payload: JSON.stringify(payload), ...(image ? { response: "image" } : {}) }))); } }); + } + while (buffer.length >= 4) { + const length = buffer.readUInt32BE() & 0x7fffffff; expect(length).toBeLessThanOrEqual(131088); + if (buffer.length < length + 4) break; + replies.push(buffer.subarray(4, length + 4)); buffer = buffer.subarray(length + 4); + } + }); + }); + await new Promise(resolve => server.listen(0, "127.0.0.1", resolve)); + const provider = connectOffloadProvider({ address: "127.0.0.1", port: (server.address() as { port: number }).port, + key: "ab".repeat(32), isolation: "process", worker: new URL("../host/worker.ts", import.meta.url), + data: { ...defaultConfig, tileURL: `${http.url}{z}/{x}/{y}.png`, searchURL: String(http.url), cache: ":memory:" } }); + try { + for (let n = 0; n < 3; n++) { + const peer = await peers.take(); peer.send("map.info", 1); const info = JSON.parse(JSON.parse((await peer.read()).toString()).payload); + peer.send("map.tile", 2, { source: info.source, z: 1, x: 0, y: 0 }, true); await fetched.take(); peer.socket.destroy(); + } + hold = false; + const peer = await peers.take(); peer.send("map.info", 1); const info = JSON.parse(JSON.parse((await peer.read()).toString()).payload); + peer.send("map.tile", 2, { source: info.source, z: 1, x: 0, y: 0 }, true); + const image = await peer.read(); expect(image.length).toBe(131088); expect(image.subarray(0, 4).toString()).toBe("PIMG"); expect(image.readUInt32LE(4)).toBe(2); + for (let i = 16; i < image.length; i += 2) if (image[i] !== 31 || image[i + 1] !== 0) throw new Error(`Corrupted RGB565 pixel at ${i}`); + } finally { provider.close(); for (const socket of sockets) socket.destroy(); await new Promise(resolve => server.close(() => resolve())); http.stop(true); } +}, 12000); From 1c1373582765052228255e5e980cc1725e511a57 Mon Sep 17 00:00:00 2001 From: "Yifeng \"Evan\" Wang" <7312949+doodlewind@users.noreply.github.com> Date: Sun, 6 Sep 2026 15:34:59 -0700 Subject: [PATCH 03/13] chore(dev): reuse 3DS runtime for guest updates --- README.md | 29 +++++++++++++++++++++++++++++ docs/VALIDATION.md | 13 ++++++++++--- package.json | 2 ++ 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index cdc2c65..fb77683 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,35 @@ bun run host 192.168.8.102 Exit ftpd and open **Pocket Map** in HBL. The deployment script installs only this app and its pairing key, then reads both back for verification. Keys, saved places and the provider's cache stay under ignored `.local/`. `L + R + START` returns to HBL. +### Updating a running app + +**Guest code and assets can update while Pocket Map is running.** The native +runtime's development connection uses port 8131, separately from the Mac +offload connection. Pair it once through ftpd if this checkout is not already +paired: + +```sh +bun run 3ds:pair --host 192.168.8.102 --ftp-port 5000 +``` + +Exit ftpd and open Pocket Map. Subsequent guest updates use: + +```sh +bun run update # rebuild .pocket and discover the paired 3DS +bun run update --host 192.168.8.102 # explicit address when broadcast is unavailable +``` + +The command reuses PocketJS's package builder and development client. It waits +for the device's acceptance after its first rendered frame completes. A failed +guest falls back to the previous package. **An update recreates the JS realm**, +so camera and other in-memory UI state reset; saved places remain on the Mac. +The development key is stored under ignored `runtime/.pocket/3ds/devices/`. +`L + R + SELECT` opens the native connection/status menu. + +Changes to the native host, ABI, HBL icon or embedded recovery package still +require `bun run 3ds`, an ftpd deployment and a restart. Mac-only provider changes +require restarting the Mac daemon. Neither requires changing the guest's API. + | Control | Action | | --- | --- | | Bottom touchpad | Drag to pan; flick for inertia | diff --git a/docs/VALIDATION.md b/docs/VALIDATION.md index 0aec079..ff70009 100644 --- a/docs/VALIDATION.md +++ b/docs/VALIDATION.md @@ -67,6 +67,13 @@ fetches, then verifies every pixel of a returned 256px image. UI replay and QuickJS checks cover the revised guest cancellation semantics. The revised Mac daemon is running with process isolation and socket -backpressure and has reconnected to the physical 3DS. The current guest patch -preserving transmission credit is built and passes replay / QuickJS checks; -its upload and physical interaction acceptance require ftpd to be opened. +backpressure and has reconnected to the physical 3DS. The guest patch preserving +transmission credit passes replay / QuickJS checks and was uploaded through +ftpd with byte-for-byte readback: 1,686,296 bytes, SHA-256 +`cafcdcc0112c8bde54935f3105852c1d3eb582a5feab264cbeda143b515d1e13`. +Physical interaction acceptance of this patch remains pending. + +The console already has the native development pairing key. That key has been +reused locally for Pocket Map's runtime checkout. `bun run update` rebuilds +only the guest package and delegates delivery and acceptance to PocketJS's +existing development client; ftpd is unnecessary for subsequent guest changes. diff --git a/package.json b/package.json index d6aaaf2..d9829fd 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,8 @@ "scripts": { "setup": "bun scripts/setup.ts", "3ds": "bun scripts/build.ts", "host": "bun host/serve.ts", "deploy": "bun scripts/deploy.ts", "sim": "bun scripts/sim.ts", + "3ds:pair": "bun runtime/tools/3ds-dev.ts pair", + "update": "bun run 3ds --pocket-only && bun runtime/tools/3ds-dev.ts push --package dist/pocketmap-main.pocket", "test": "bun test --conditions=browser test/geo.test.ts test/provider.test.ts test/model.test.ts test/bookmarks.test.ts test/transport.test.ts", "check": "bun run test && runtime/node_modules/.bin/tsc --noEmit" } From 5205f7b1c7dc289c9512d581397245b7e4d3ac4c Mon Sep 17 00:00:00 2001 From: "Yifeng \"Evan\" Wang" <7312949+doodlewind@users.noreply.github.com> Date: Sun, 6 Sep 2026 16:53:23 -0700 Subject: [PATCH 04/13] feat(map): add complete local Hyrule atlas and place search --- README.md | 99 +++++++++++++++++++--------------- app/geo.ts | 7 +++ app/model.ts | 55 +++++++++++-------- app/saved.ts | 3 +- app/ui.tsx | 15 +++--- docs/ARCHITECTURE.md | 72 +++++++++++++++++-------- docs/VALIDATION.md | 72 +++++++++++++++++++++---- docs/images/hyrule-search.png | Bin 0 -> 35277 bytes docs/images/hyrule.png | Bin 0 -> 76994 bytes host/atlas.ts | 65 ++++++++++++++++++++++ host/bookmarks.ts | 29 ++++++---- host/config.ts | 2 +- host/provider.ts | 11 ++-- host/serve.ts | 8 ++- host/worker.ts | 14 +++-- package.json | 5 +- runtime | 2 +- scripts/prepare-hyrule.ts | 96 +++++++++++++++++++++++++++++++++ scripts/quickjs-smoke.js | 7 ++- scripts/sim.ts | 36 ++++++++++--- shared/types.ts | 15 ++++-- test/atlas.test.ts | 48 +++++++++++++++++ test/bookmarks.test.ts | 17 ++++++ 23 files changed, 538 insertions(+), 140 deletions(-) create mode 100644 docs/images/hyrule-search.png create mode 100644 docs/images/hyrule.png create mode 100644 host/atlas.ts create mode 100644 scripts/prepare-hyrule.ts create mode 100644 test/atlas.test.ts diff --git a/README.md b/README.md index fb77683..637ca0a 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,21 @@ # Pocket Map -A map browser for Nintendo 3DS, built with [PocketJS](https://github.com/pocket-stack/pocketjs) and SolidJS 1.9. Search for places, pan with the resistive touch screen, and zoom the map on the upper display. A paired Mac handles network requests, SQLite caching, PNG decoding, label rasterization and saved places in a separate capability process. +A map browser for Nintendo 3DS, built with [PocketJS](https://github.com/pocket-stack/pocketjs) and SolidJS 1.9. Explore the complete Hyrule map from **The Legend of Zelda: Breath of the Wild**, search 2,576 places, pan with the resistive touchpad, zoom and save locations. The paired Mac stores the complete atlas and search index. Browsing requires the LAN connection but makes **no internet requests**. An optional OpenStreetMap / Photon provider remains available. -

Pocket Map displaying real OpenStreetMap tiles on a compiled dual-screen guest Live Photon place results with the bottom-screen selection touchpad

+

Pocket Map displaying the local Hyrule atlas on a compiled dual-screen guest Local Kakariko search results with the bottom-screen selection touchpad

-These are **compiled guest + Wasm captures using live OpenStreetMap DE and Photon data**, at the 3DS's 400×240 / 320×240 logical resolutions. They are not photographs of the console. Map data © [OpenStreetMap contributors](https://www.openstreetmap.org/copyright); tiles provided by [FOSSGIS / OpenStreetMap DE](https://openstreetmap.de/germanstyle/). +These are **compiled guest + Wasm captures**, at the 3DS's 400×240 / 320×240 logical resolutions, not console photographs. Map artwork belongs to Nintendo; the pinned atlas and marker source is [Zelda Dungeon's map repository](https://github.com/zeldadungeon/maps/tree/d32a85656031d861cef38e32eb927a7d08a983a9/public/botw). Downloaded assets and generated databases stay outside Git. ## Try it -Requirements: Bun 1.3.14, Docker with the PocketJS 3DS toolchain (or a supported native devkitPro install), a Mac and a 3DS on the same LAN, Homebrew Launcher and ftpd. The runtime submodule pins the image-resource support used by this app. +Requirements: Bun 1.3.14, Docker with the PocketJS 3DS toolchain (or a supported native devkitPro install), Git, a Mac and a 3DS on the same LAN, Homebrew Launcher and ftpd. The runtime submodule pins the image-resource support used by this app. ```sh git clone --recurse-submodules https://github.com/pocket-stack/pocket-map.git cd pocket-map cd runtime && bun install --frozen-lockfile && cd .. bun run setup +bun run prepare:hyrule bun run 3ds # Open ftpd on the console first. Substitute its LAN IP. bun run deploy 192.168.8.102 @@ -23,34 +24,21 @@ bun run host 192.168.8.102 Exit ftpd and open **Pocket Map** in HBL. The deployment script installs only this app and its pairing key, then reads both back for verification. Keys, saved places and the provider's cache stay under ignored `.local/`. `L + R + START` returns to HBL. -### Updating a running app +### Updating this build -**Guest code and assets can update while Pocket Map is running.** The native -runtime's development connection uses port 8131, separately from the Mac -offload connection. Pair it once through ftpd if this checkout is not already -paired: +**The current `POCKETJS_OFFLOAD` native build excludes the development server +and package storage path.** PocketJS's ordinary 3DS runtime supports guest +updates on port 8131, but that connection is unavailable in this build, even +with a valid development key. Rebuild with `bun run 3ds`, deploy through ftpd, +and restart Pocket Map for guest or native changes. Mac-only provider changes +need only a daemon restart. The offload UI path omits synchronous SD package +work; enabling safe development updates here needs native host integration. -```sh -bun run 3ds:pair --host 192.168.8.102 --ftp-port 5000 -``` - -Exit ftpd and open Pocket Map. Subsequent guest updates use: - -```sh -bun run update # rebuild .pocket and discover the paired 3DS -bun run update --host 192.168.8.102 # explicit address when broadcast is unavailable -``` - -The command reuses PocketJS's package builder and development client. It waits -for the device's acceptance after its first rendered frame completes. A failed -guest falls back to the previous package. **An update recreates the JS realm**, -so camera and other in-memory UI state reset; saved places remain on the Mac. -The development key is stored under ignored `runtime/.pocket/3ds/devices/`. -`L + R + SELECT` opens the native connection/status menu. - -Changes to the native host, ABI, HBL icon or embedded recovery package still -require `bun run 3ds`, an ftpd deployment and a restart. Mac-only provider changes -require restarting the Mac daemon. Neither requires changing the guest's API. +For request timing and socket backpressure diagnostics, start the host with +`POCKET_MAP_TRACE=1 bun run host <3ds-ip>`. It records request IDs, method names, +provider duration, cumulative cache hits/downloads and socket drain waits. +Request payloads are omitted. A drain receipt measures the Mac socket's write +queue; it is not a device-render receipt. | Control | Action | | --- | --- | @@ -61,7 +49,7 @@ require restarting the Mac daemon. Neither requires changing the guest's API. | Search results touchpad | Slide to choose a result, tap to open | | D-pad up/down + A | Choose and open a search result or menu item | | X / Back to pin | Return to the selected place | -| Hold L | Search, saved places, save map center, return to pin, or San Francisco | +| Hold L | Search, saved places, save map center, return to pin, or map home | | Hold R | Zoom, clear pin, retry tiles, or show controls | | Save view / Save place | Name and save the center or selected search result on the Mac | | Saved | Browse, rename, delete with confirmation, or return to a saved location | @@ -71,7 +59,29 @@ require restarting the Mac daemon. Neither requires changing the guest's API. The Mac keeps connection management separate from native decoding and network work. If the capability process exits, it is reaped and replaced on reconnect. Socket backpressure pauses traffic; cancelling a sent device request retains its wire credit until a reply or disconnection. -Typing, dragging, inertia and zoom transitions update locally. Missing tiles show a fallback; an already loaded previous zoom level stays visible during replacement. A disconnected Mac leaves resident tiles navigable. Search, new tiles and uncached labels require the Mac. +Typing, dragging, inertia and zoom transitions update locally. Missing tiles show a fallback; an already loaded previous zoom level stays visible during replacement. A disconnected Mac leaves resident tiles navigable. Search, new tiles and uncached labels require the Mac, including in Hyrule mode. Offline here means independent of internet map services, not independent of the paired Mac. + +## Complete local Hyrule atlas + +`bun run prepare:hyrule` sparsely checks out a pinned Zelda Dungeon revision: +1,365 JPEG source tiles across six levels, about 49 MB. It rebakes the full +24,000px square source into **21,845 RGB565 textures across levels 0–7**, using +256px texture envelopes. Original source detail is preserved by subdividing +the 750px tiles; the top level is a 32,768px grid. Deflate compression is used +only for Mac storage. The 3DS receives raw pixels and performs no JPEG or +Deflate decoding. + +The completed `.local/hyrule/atlas.sqlite` is about **592 MB** and includes an +FTS5 index of regions, landmarks, towers, shrines, villages, Korok seeds and +treasures. Preparation publishes the database only after all levels complete. +It is reused on the next invocation; `--rebuild` explicitly replaces it. + +The Hyrule provider has no HTTP fallback or request throttle. It reads the +prepared textures and keeps 128 decoded renditions on the Mac. The device +retains 40 tiles and requests up to 12 neighboring tiles with a 256px margin +and at most 384px of directional prediction. Visible tiles retain priority. +The finite world clamps at its edges; Map home returns to the Great Plateau. +Try searching `Kakariko`, `Hyrule Castle`, `Shrine` or `Great Plateau`. ## Saved places @@ -80,19 +90,20 @@ The local keyboard names it before Save sends a command to the Mac. Saved opens five-place pages, with Rename, Delete and Go to place actions. Deletion uses an animated confirmation sheet; B / Keep place cancels it. -The Mac stores user data in `.local/places.sqlite`, separate from the disposable -`.local/cache.sqlite`. Coordinates, zoom and names survive daemon restarts. +The Mac stores Hyrule bookmarks in `.local/hyrule/places.sqlite`. The OSM provider +uses `.local/places.sqlite`, separate from `.local/cache.sqlite`. Geographic +bookmarks migrate without losing existing entries or operation receipts. Coordinates, zoom and names survive daemon restarts. Mutations commit with an operation receipt: Retry after a missing acknowledgement uses the same operation, so it cannot create a second copy or resurrect a deleted place. Cancel after an unconfirmed command does not undo a Mac write; reopen Saved to check its outcome. A connected Mac is needed for writes. The guest retains up to four previously viewed pages during a disconnection. -## Provider configuration +## Optional OpenStreetMap provider -The default small-demo configuration uses `https://tile.openstreetmap.de/{z}/{x}/{y}.png` and `https://photon.komoot.io/api/`, both verified reachable from the development Mac. The main `tile.openstreetmap.org` endpoint failed to connect in that network. No API keys are required by the selected demo endpoints. +Start `bun run host <3ds-ip> --osm` to use the geographic provider. Its configuration uses `https://tile.openstreetmap.de/{z}/{x}/{y}.png` and `https://photon.komoot.io/api/`, both verified reachable from the development Mac. The main `tile.openstreetmap.org` endpoint failed to connect in that network. No API keys are required by the selected demo endpoints. -Override settings in `.local/provider.json`, then restart the host: +Override OSM settings in `.local/provider.json`, then restart the host with `--osm`: ```json { @@ -106,14 +117,14 @@ Override settings in `.local/provider.json`, then restart the host: The tile endpoint must return 256px PNGs; the search endpoint must implement the Photon response shape. HTTPS and loopback HTTP development endpoints are supported. The device sends typed tile coordinates, not arbitrary URLs. Tile identities include a hash of the source URL and rendition version. -Public services have limited capacity: [OSM DE's terms](https://openstreetmap.de/germanstyle/#nutzungsbedingungen), [tile usage policy](https://operations.osmfoundation.org/policies/tiles/), and [Photon's demo policy](https://github.com/komoot/photon#demo-server) apply. **The current viewport has priority; at most four nearby tiles provide short-range look-ahead.** The margin is 64 screen pixels and movement prediction is capped at 128 pixels; there is no area downloader or multi-level pre-seeding. Searches require an explicit submit and are limited to one per 1.1 seconds on this provider. The Mac honors HTTP cache headers and conditional requests, using seven days for tiles without freshness headers. Use an appropriate hosted or self-hosted service before scaling beyond this personal demo. Endpoint configuration allows that switch without rebuilding the 3DS app. +Public services have limited capacity: [OSM DE's terms](https://openstreetmap.de/germanstyle/#nutzungsbedingungen), [tile usage policy](https://operations.osmfoundation.org/policies/tiles/), and [Photon's demo policy](https://github.com/komoot/photon#demo-server) apply. **The current viewport has priority; at most four nearby tiles provide short-range look-ahead.** The margin is 128 screen pixels and movement prediction is capped at 128 pixels; there is no area downloader or multi-level pre-seeding. The OSM DE service documents per-IP throttling after an unspecified high-speed tile allowance; a slow response does not necessarily produce HTTP 429. Searches require an explicit submit and are limited to one per 1.1 seconds on this provider. The Mac honors HTTP cache headers and conditional requests, using seven days for tiles without freshness headers. Use an appropriate hosted or self-hosted service before scaling beyond this personal demo. Endpoint configuration allows that switch without rebuilding the 3DS app. ## Architecture and resource pattern ```text 3DS UI thread 3DS network worker Mac capability process -camera + controls authenticated TCP HTTPS + SQLite cache -visible tile demand -> bounded request queue -> fetch / PNG decode +camera + controls authenticated TCP local atlas / optional HTTPS +visible tile demand -> bounded request queue -> SQLite textures + place index ResourceImage fallback <- native image tickets <- binary R5G6B5 pixels one image upload/frame eight staging slots bounded tile/label output ``` @@ -125,22 +136,24 @@ const tiles = createOffloadImageCollection(runtime, io, { key: (tile: TileInput) => `${tile.source}/${tile.z}/${tile.x}/${tile.y}`, method: "map.tile", payload: JSON.stringify, width: 256, height: 256, maxEntries: 40, - maxViews: 2, maxDemandsPerView: 16, + maxViews: 2, maxDemandsPerView: 24, }); const view = createResourceView(tiles, { demand: visibleTileDemand }); // view.state(tile)} fallback={() => } /> ``` -Map-specific behavior remains in [app/model.ts](app/model.ts) and [app/geo.ts](app/geo.ts): Mercator projection, longitude wrapping, visible priorities, selection and search. [host/provider.ts](host/provider.ts) owns source grants and image processing; [host/cache.ts](host/cache.ts) owns persistent HTTP caching. [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) records budgets, lifecycle and tradeoffs. +Map-specific behavior remains in [app/model.ts](app/model.ts) and [app/geo.ts](app/geo.ts): coordinate systems, visible priorities, selection and search. [host/atlas.ts](host/atlas.ts) reads the prepared Hyrule atlas; [host/provider.ts](host/provider.ts) and [host/cache.ts](host/cache.ts) implement the optional HTTP provider. [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) records budgets, lifecycle and tradeoffs. ## Validation ```sh bun run check runtime/node_modules/.bin/tsc --noEmit -bun run sim # compiled guest, synthetic provider, interaction replay +bun run sim # compiled guest, synthetic OSM provider, interaction replay +bun run sim --hyrule # complete local atlas, search and delayed-response navigation bun run sim --live # current live viewport + one explicit place search qjs --std --stack-size 131072 scripts/quickjs-smoke.js +qjs --std --stack-size 131072 scripts/quickjs-smoke.js runtime/dist/3ds/guest/pocketmap-main.js hyrule ``` Generated captures and receipts go to `dist/qa/`. Replay covers keyboard input, selecting places, drag/inertia, zoom, sustained movement while replies wait, reconnect, date-line navigation and bounded resource ownership. Replay also covers saving, a lost acknowledgement and safe retry, renaming, paging, delete confirmation and entering a prefetched tile. Stress tests use synthetic tiles, not automated public-service downloads. diff --git a/app/geo.ts b/app/geo.ts index a51f9b2..cd955aa 100644 --- a/app/geo.ts +++ b/app/geo.ts @@ -16,3 +16,10 @@ export function scaleBar(lat: number, zoom: number) { const meters = [5, 2, 1].map(n => n * base).find(n => n <= target) ?? base / 2; return { pixels: meters / metersPerPixel, label: meters >= 1000 ? `${meters / 1000} km` : `${meters} m` }; } +import type { Position } from "../shared/types.ts"; +export function worldPosition(position: Position) { + return position.space === "planar" ? { x: position.x, y: position.y } : project(position.lat, position.lon); +} +export function positionAt(x: number, y: number, planar: boolean): Position { + return planar ? { space: "planar", x, y } : unproject(x, y); +} diff --git a/app/model.ts b/app/model.ts index 261bd3f..52ba6d2 100644 --- a/app/model.ts +++ b/app/model.ts @@ -6,14 +6,14 @@ import { offload } from "@pocketjs/framework/offload"; import { analogX, analogY, onFrame, onButtonPress } from "@pocketjs/framework/lifecycle"; import { BTN } from "@pocketjs/framework/input"; import { simulationHz, virtualNow } from "@pocketjs/framework/clock"; -import { project, unproject, wrapTile } from "./geo.ts"; +import { project, worldPosition, positionAt, wrapTile } from "./geo.ts"; import { createSavedPlaces, validPlaces, type MapMode } from "./saved.ts"; import { HOME, type TileInput, type MapInfo, type SearchInput, type Place } from "../shared/types.ts"; export interface DrawTile { input: TileInput; column: number; row: number; priority: number } export interface Layer { level: number; tiles: DrawTile[]; originX: number; originY: number } export const MENU = { - places: ["Search places", "Saved places", "Save map center", "Back to pin", "San Francisco"], + places: ["Search places", "Saved places", "Save map center", "Back to pin", "Map home"], map: ["Zoom in", "Zoom out", "Clear pin", "Retry tiles", "About & controls"], }; export function createMap(io = offload()) { @@ -25,11 +25,12 @@ export function createMap(io = offload()) { const [menu, setMenu] = createSignal<"places" | "map">(), [menuIndex, setMenuIndex] = createSignal(0); const [shift, setShift] = createSignal<"off" | "once" | "locked">("off"), [symbols, setSymbols] = createSignal(false); const [front, setFront] = createSignal(), [back, setBack] = createSignal(); + const planar = () => info()?.space === "planar"; const p = project(HOME.lat, HOME.lon); const camera = createTileCamera({ width: 400, height: 240, x: p.x, y: p.y, zoom: HOME.zoom, minZoom: 1, maxZoom: 18, bounds: { width: 256, height: 256, wrapX: true } }); const runtime = createResourceRuntime({ maxConcurrent: 3, startsPerFrame: 1, completionsPerFrame: 1, maxCollections: 4, available: () => io.connected() && !!info() && io.pending() < 3 }); const tiles = createOffloadImageCollection(runtime, io, { key: (i: TileInput) => `${i.source}/${i.z}/${i.x}/${i.y}`, method: "map.tile", payload: JSON.stringify, - width: 256, height: 256, maxEntries: 40, maxViews: 2, maxDemandsPerView: 16, retry: { attempts: 3, delayFrames: 90, maxDelayFrames: 360 } }); + width: 256, height: 256, maxEntries: 40, maxViews: 2, maxDemandsPerView: 24, retry: { attempts: 3, delayFrames: 90, maxDelayFrames: 360 } }); const labels = createOffloadImageCollection(runtime, io, { key: (i: Place) => `${i.name}/${i.detail}`, method: "map.label", payload: i => JSON.stringify({ name: i.name, detail: i.detail }), width: 256, height: 32, maxEntries: 5, maxViews: 5, maxDemandsPerView: 1 }); const [lookAhead, setLookAhead] = createSignal([]); @@ -56,15 +57,16 @@ export function createMap(io = offload()) { let confirmed = false; function search() { const text = query().trim(); if (!text) return; - const pos = unproject(camera.view().x, camera.view().y); - const next = { query: text, lat: Math.round(pos.lat * 10) / 10, lon: Math.round(pos.lon * 10) / 10 }; + const v = camera.view(), pos = positionAt(v.x, v.y, planar()); + const next: SearchInput = { query: text, ...(pos.space === "planar" ? pos : { lat: Math.round(pos.lat * 10) / 10, lon: Math.round(pos.lon * 10) / 10 }) }; searches.invalidate(i => JSON.stringify(i) === JSON.stringify(next)); setSubmitted(next); setSelection(0); setMode("results"); camera.stop(); } function openSearch() { if (saved.busy() || saved.modal() || mode() === "name") return; camera.stop(); setMode("search"); setMenu(undefined); } function go(place = rows()[selectedIndex()]) { if (!place) return; - const pos = project(place.lat, place.lon); camera.jump(pos.x, pos.y, Math.min(info()?.maxZoom ?? 18, place.zoom)); + if ((place.space === "planar") !== planar()) return; + const pos = worldPosition(place); camera.jump(pos.x, pos.y, Math.min(info()?.maxZoom ?? 18, place.zoom)); setPin(place); setMode("map"); setMenu(undefined); } function home(name: string, lat: number, lon: number) { go({ id: name, name, detail: "", lat, lon, zoom: 14 }); } @@ -85,17 +87,18 @@ export function createMap(io = offload()) { } function saveCurrent() { camera.stop(); - if (mode() === "results") { const selected = places()[selection()]; if (selected) { const p = project(selected.lat, selected.lon); camera.jump(p.x, p.y, selected.zoom); setPin(selected); saved.begin(selected); } return; } - const view = camera.view(), pos = unproject(view.x, view.y), selected = pin(); - const target = selected && project(selected.lat, selected.lon); - let dx = target ? target.x - view.x : Infinity; dx -= Math.round(dx / 256) * 256; - saved.begin(target && Math.hypot(dx, target.y - view.y) * view.scale < 12 ? selected! : { id: "center", name: "Map center", detail: `${pos.lat.toFixed(5)}, ${pos.lon.toFixed(5)}`, ...pos, zoom: Math.round(view.zoom) }); + if (mode() === "results") { const selected = places()[selection()]; if (selected) { const p = worldPosition(selected); camera.jump(p.x, p.y, selected.zoom); setPin(selected); saved.begin(selected); } return; } + const view = camera.view(), pos = positionAt(view.x, view.y, planar()), selected = pin(); + const target = selected && worldPosition(selected); + let dx = target ? target.x - view.x : Infinity; if (!planar()) dx -= Math.round(dx / 256) * 256; + const detail = pos.space === "planar" ? `Hyrule ${pos.x.toFixed(2)}, ${pos.y.toFixed(2)}` : `${pos.lat.toFixed(5)}, ${pos.lon.toFixed(5)}`; + saved.begin(target && Math.hypot(dx, target.y - view.y) * view.scale < 12 ? selected! : { id: "center", name: "Map center", detail, ...pos, zoom: Math.round(view.zoom) }); } function dismiss() { if (saved.busy()) return; if (mode() === "name") { saved.cancelName(); return; } setMenu(undefined); setMode("map"); camera.stop(); } function runMenu() { const i = menuIndex(), bank = menu(); setMenu(undefined); confirmed = true; if (bank === "places") { - if (i === 0) openSearch(); else if (i === 1) saved.open(); else if (i === 2) saveCurrent(); else if (i === 3) go(pin()); else home("San Francisco", HOME.lat, HOME.lon); + if (i === 0) openSearch(); else if (i === 1) saved.open(); else if (i === 2) saveCurrent(); else if (i === 3) go(pin()); else if (info()?.home) go(info()!.home); else home("San Francisco", HOME.lat, HOME.lon); } else if (bank === "map") { if (i < 2) zoom(i === 0 ? 1 : -1); else if (i === 2) setPin(undefined); else if (i === 3) tiles.invalidate(); else setMode("about"); } @@ -127,8 +130,15 @@ export function createMap(io = offload()) { if (!result.ok) { setStatus(result.error); retryAt = frame + 120; return; } try { const value: MapInfo = JSON.parse(result.value); - if (typeof value.source !== "string" || !/^[a-f0-9]{16}$/.test(value.source) || typeof value.name !== "string" || typeof value.attribution !== "string" || !Number.isInteger(value.maxZoom) || value.maxZoom < 1 || value.maxZoom > 18) throw new Error("Invalid map provider"); - if (info()?.source !== value.source) { tiles.clear(); setFront(undefined); setBack(undefined); setLookAhead([]); } + if (typeof value.source !== "string" || !/^[a-f0-9]{16}$/.test(value.source) || typeof value.name !== "string" || typeof value.attribution !== "string" || !Number.isInteger(value.maxZoom) || value.maxZoom < 1 || value.maxZoom > 18 + || !Number.isInteger(value.minZoom ?? 1) || (value.minZoom ?? 1) < 0 || (value.minZoom ?? 1) > value.maxZoom + || value.space !== undefined && value.space !== "mercator" && value.space !== "planar" + || value.home !== undefined && (!validPlaces([value.home]) || (value.home.space === "planar") !== (value.space === "planar"))) throw new Error("Invalid map provider"); + if (info()?.source !== value.source) { + tiles.clear(); setFront(undefined); setBack(undefined); setLookAhead([]); setPin(undefined); + camera.setWorld({ minZoom: value.minZoom ?? 1, maxZoom: value.maxZoom, bounds: { width: 256, height: 256, wrapX: value.space !== "planar" } }); + if (value.home) { const home = worldPosition(value.home); camera.jump(home.x, home.y, value.home.zoom); } + } setInfo(value); setStatus("Map ready"); } catch { setStatus("Unsupported map provider"); retryAt = frame + 120; } }); @@ -145,7 +155,7 @@ export function createMap(io = offload()) { camera.step(1 / simulationHz(), dx ? dx * 180 : -axisX * 320, dy ? dy * 180 : -axisY * 320); previousButtons = buttons; if (!info()) return; - const view = camera.view(), next = Math.min(info()!.maxZoom, Math.max(1, Math.round(view.zoom))); + const view = camera.view(), next = Math.min(info()!.maxZoom, Math.max(info()!.minZoom ?? 1, Math.round(view.zoom))); levelAge = next === candidateLevel ? levelAge + 1 : 0; candidateLevel = next; let level = front()?.level ?? next; if (next !== level && (levelAge >= 8 || Math.abs(next - level) > 1)) { @@ -153,17 +163,20 @@ export function createMap(io = offload()) { setBack(previous ? { ...previous, tiles: previous.tiles.filter(t => frontView.state(t.input).status === "ready") } : undefined); level = next; } - let leadX = view.x - previousView.x; leadX -= Math.round(leadX / 256) * 256; + let leadX = view.x - previousView.x; if (!planar()) leadX -= Math.round(leadX / 256) * 256; const leadY = view.y - previousView.y; const moving = view.moving && Math.hypot(leadX, leadY) * view.scale < 24 && Math.abs(view.zoom - level) < 0.02; - const planOptions = { ...view, level, width: 400, height: 240, maxTiles: 12, margin: 64, - leadX: moving ? Math.max(-128, Math.min(128, leadX * view.scale * 18)) : 0, - leadY: moving ? Math.max(-128, Math.min(128, leadY * view.scale * 18)) : 0, maxExtra: Math.abs(view.zoom - level) < 0.02 ? 4 : 0 }; + // Start nearby work earlier without expanding the four-tile source budget. + // At 320px/s, a 64px margin did not even cover a cached 128 KiB LAN transfer. + const local = info()!.local === true, leadLimit = local ? 384 : 128; + const planOptions = { ...view, level, width: 400, height: 240, maxTiles: 12, margin: local ? 256 : 128, + leadX: moving ? Math.max(-leadLimit, Math.min(leadLimit, leadX * view.scale * (local ? 48 : 36))) : 0, + leadY: moving ? Math.max(-leadLimit, Math.min(leadLimit, leadY * view.scale * (local ? 48 : 36))) : 0, maxExtra: Math.abs(view.zoom - level) < 0.02 ? local ? 12 : 4 : 0 }; let window; try { window = planTileWindow(planOptions); } catch { level = next; window = planTileWindow({ ...planOptions, level, maxExtra: 0 }); } previousView = view; - const address = (list: typeof window.visible) => list.filter(t => t.row >= 0 && t.row < 2 ** level).map(t => ({ ...t, input: { source: info()!.source, z: level, x: wrapTile(t.column, level), y: t.row } })); + const address = (list: typeof window.visible) => list.filter(t => t.row >= 0 && t.row < 2 ** level && (!planar() || t.column >= 0 && t.column < 2 ** level)).map(t => ({ ...t, input: { source: info()!.source, z: level, x: wrapTile(t.column, level), y: t.row } })); const draw = address(window.visible), ahead = address(window.lookAhead); if (ahead.length !== lookAhead().length || ahead.some((t, i) => { const o = lookAhead()[i]; return !o || t.input.z !== o.input.z || t.input.x !== o.input.x || t.input.y !== o.input.y; })) setLookAhead(ahead); const previous = front(); @@ -176,7 +189,7 @@ export function createMap(io = offload()) { } if (back() && front()?.tiles.every(t => frontView.state(t.input).status === "ready")) setBack(undefined); }); - return { io, runtime, tiles, labels, frontView, backView, info, online, status, mode, setMode, query, setQuery, submitted, results, places, selection, setSelection, pin, menu, menuIndex, + return { io, runtime, tiles, labels, frontView, backView, info, planar, online, status, mode, setMode, query, setQuery, submitted, results, places, selection, setSelection, pin, menu, menuIndex, shift, symbols, front, back, camera, saved, typing, listing, rows, selectedIndex, select, saveCurrent, lookAhead, search, openSearch, go, zoom, key, dismiss, runMenu, clearBack: () => setBack(undefined), diagnostics: () => ({ frame, pending: io.pending(), resources: runtime.stats(), tiles: tiles.stats(), camera: camera.view() }), diff --git a/app/saved.ts b/app/saved.ts index c1d4e37..2927959 100644 --- a/app/saved.ts +++ b/app/saved.ts @@ -3,10 +3,11 @@ import { createResourceRuntime, createResourceView } from "@pocketjs/framework/r import { offloadResource } from "@pocketjs/framework/resource-offload"; import type { offload } from "@pocketjs/framework/offload"; import type { Place, BookmarkPage, BookmarkCommand } from "../shared/types.ts"; +import { validPosition } from "../shared/types.ts"; export type MapMode = "map" | "search" | "results" | "about" | "saved" | "name"; export function validPlaces(rows: unknown): rows is Place[] { - return Array.isArray(rows) && rows.length <= 5 && rows.every(p => p && typeof p.id === "string" && p.id.length <= 80 && typeof p.name === "string" && p.name.length <= 36 && typeof p.detail === "string" && p.detail.length <= 60 && Number.isFinite(p.lat) && Math.abs(p.lat) <= 90 && Number.isFinite(p.lon) && Math.abs(p.lon) <= 180 && Number.isInteger(p.zoom) && p.zoom >= 1 && p.zoom <= 18); + return Array.isArray(rows) && rows.length <= 5 && rows.every(p => p && typeof p.id === "string" && p.id.length <= 80 && typeof p.name === "string" && p.name.length <= 36 && typeof p.detail === "string" && p.detail.length <= 60 && Number.isInteger(p.zoom) && p.zoom >= 0 && p.zoom <= 18 && validPosition(p)); } export function createSavedPlaces(io: ReturnType, runtime: ReturnType, mode: () => MapMode, setMode: (mode: MapMode) => void) { const [offset, setOffset] = createSignal(0), [selection, setSelection] = createSignal(0); diff --git a/app/ui.tsx b/app/ui.tsx index a73c368..02e037c 100644 --- a/app/ui.tsx +++ b/app/ui.tsx @@ -8,7 +8,7 @@ import { simulationHz } from "@pocketjs/framework/clock"; import { onFrame } from "@pocketjs/framework/lifecycle"; import * as hot from "@pocketjs/framework/hot"; import { createMap, MENU, type MapModel, type Layer } from "./model.ts"; -import { project, unproject, scaleBar } from "./geo.ts"; +import { worldPosition, unproject, scaleBar } from "./geo.ts"; import type { Place } from "../shared/types.ts"; const box = (x: number, y: number, w: number, h: number) => ({ posType: 1, insetL: x, insetT: y, width: w, height: h }); @@ -22,7 +22,7 @@ function TileLayer(p: { s: MapModel; back?: boolean }) { const worldWidth = 256 * 2 ** l.level; let offsetX = l.originX - view.x * 2 ** l.level; // Rebase at the viewport, including the nearest copy across the date line. - offsetX -= Math.round(offsetX / worldWidth) * worldWidth; + if (!p.s.planar()) offsetX -= Math.round(offsetX / worldWidth) * worldWidth; hot.prop(world, "translateX", 200 + offsetX * scale); hot.prop(world, "translateY", 120 + (l.originY - view.y * 2 ** l.level) * scale); hot.prop(world, "scaleX", scale); hot.prop(world, "scaleY", scale); @@ -128,7 +128,7 @@ function Deck(p: { s: MapModel }) { {search} - {typing() ? `${(naming() ? p.s.saved.name() : p.s.query()).slice(-31)}|` : saved() ? "Saved on your paired Mac" : results() ? p.s.query().slice(0, 32) : p.s.online() ? "Explore with your Nintendo 3DS" : "Waiting for paired Mac"} + {typing() ? `${(naming() ? p.s.saved.name() : p.s.query()).slice(-31)}|` : saved() ? "Saved on your paired Mac" : results() ? p.s.query().slice(0, 32) : p.s.online() ? p.s.planar() ? "Hyrule - Breath of the Wild" : "Explore with your Nintendo 3DS" : "Waiting for paired Mac"} {keyboard}{padView}{plus}{minus}{left}{middle}{right}{sheet} ; @@ -140,9 +140,10 @@ export default function MapApp() { onFrame(() => { const v = s.camera.view(), pin = s.pin(); hot.text(zoomText, `z${v.zoom.toFixed(1)}`); - if (pin) { const pos = project(pin.lat, pin.lon); let dx = pos.x - v.x; dx -= Math.round(dx / 256) * 256; + if (pin) { const pos = worldPosition(pin); let dx = pos.x - v.x; if (!s.planar()) dx -= Math.round(dx / 256) * 256; hot.prop(marker, "translateX", 200 + dx * v.scale - 8); hot.prop(marker, "translateY", 120 + (pos.y - v.y) * v.scale - 22); } - const scale = scaleBar(unproject(v.x, v.y).lat, v.zoom); hot.prop(bar, "scaleX", scale.pixels / 70); hot.text(scaleText, scale.label); + const scale = s.planar() ? { pixels: 64, label: `${Math.round(64 / v.scale * 24000 / 256)} u` } : scaleBar(unproject(v.x, v.y).lat, v.zoom); + hot.prop(bar, "scaleX", scale.pixels / 70); hot.text(scaleText, scale.label); }); const deck = ; const map = @@ -169,9 +170,9 @@ export default function MapApp() { Pocket Map - {"Stylus / Circle Pad / D-pad: pan\n+ and -: zoom around the map center\nY: search X: return to selected place\nHold L: places Hold R: map controls\n\nMaps: OpenStreetMap contributors\nosm.org/copyright | Tiles: OSM DE\nPlace search: Photon by komoot"} + {`Stylus / Circle Pad / D-pad: pan\n+ and -: zoom around the map center\nY: search X: return to selected place\nHold L: places Hold R: map controls\n\n${s.planar() ? "Hyrule: Breath of the Wild\nMap art: Nintendo | Data: Zelda Dungeon\nMap and place search stored on your Mac" : "Maps: OpenStreetMap contributors\nosm.org/copyright | Tiles: OSM DE\nPlace search: Photon by komoot"}`} - (c) OpenStreetMap contributors + {s.info()?.attribution ?? "Map data"} {deck}; } diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 1f10496..cc75e7c 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -9,8 +9,10 @@ subscriptions. Continuous camera movement writes paint transforms through PocketJS `hot` APIs; a tile window change updates the component tree. The native offload worker owns sockets, the SD pairing-key read and binary -reception. The paired Mac's capability process owns HTTPS, SQLite, PNG decoding, optional -Unicode label rasterization and R5G6B5 packing. Provider socket callbacks pass +reception. The paired Mac's capability process owns SQLite atlas reads, texture +decompression, optional HTTPS/PNG decoding and Unicode label rasterization. +Atlas preparation performs JPEG decoding and R5G6B5 packing before browsing. +Provider socket callbacks pass bounded requests and replies; they do not execute these capabilities. ## Working set @@ -20,7 +22,7 @@ bounded requests and replies; they do not execute these capabilities. | Active resource requests | 3 | | Resource starts / materializations | 1 / 1 per frame | | Tile collection | 40 entries, two view owners | -| Tile demand per view | 16 addresses (up to 12 visible + 4 look-ahead) | +| Tile demand per view | 24 addresses (up to 12 visible + 12 local look-ahead; OSM extras capped at four) | | Native image staging | 8 × 131,088 bytes plus metadata | | Native image envelope | 16–256px power-of-two sides, two bytes per pixel | | Native image uploads | 1 per frame | @@ -30,8 +32,9 @@ bounded requests and replies; they do not execute these capabilities. | Query text | 80 UTF-16 code units | | Unicode label collection | 5 × 256×32 images | | Mac concurrent tile decodes | 3 | -| Mac decoded-image cache | 64 entries, honoring HTTP expiry | +| Mac decoded-image cache | 128 immutable atlas textures; 64 HTTP renditions honoring expiry | | Mac HTTP cache | 2,048 bounded responses in SQLite | +| Mac transport credit | Eight total executing requests, queued replies and blocked writes | The image collection reserves 18 bytes per pixel plus 512 bytes per entry: native staging, old-plus-new core/GPU storage, the tiled upload scratch buffer @@ -43,16 +46,19 @@ and 2,500-code-unit payload limits. ## One tile's lifecycle -1. The camera's current viewport produces near-first tile coordinates and - up to four extra neighbors using a 64px margin and up to 128px directional - lead (0.3 seconds of recent movement). Visible entries are pinned; extras - have lower priority and are unpinned. The map - wraps longitude, clips polar rows and attaches the provider source identity. +1. The camera's viewport produces near-first tile coordinates. Hyrule adds up + to 12 neighbors using a 256px margin and at most 384px directional lead; OSM + adds at most four, with a 128px margin and lead cap. Prediction uses the latest + displacement over 48 local-atlas frames or 36 geographic-map frames. Visible + entries are pinned; extras have lower priority and are unpinned. Hyrule clips + both axes; OSM wraps longitude and clips polar rows. Addresses include the + provider source identity. 2. `createResourceView` declares desired keys. The collection merges both zoom layers' demand and reserves entry cost before starting an offload read. -3. The Mac resolves the named tile capability to its configured URL. It reads - a fresh cached PNG or fetches one with HTTP validators, checks its 256px - envelope, decodes it and packs opaque R5G6B5 pixels. +3. The Mac looks up an already baked Hyrule texture in SQLite and decompresses + it to exactly 131,072 bytes, or returns a decoded-cache hit. This provider has + no HTTP path. The optional OSM provider reads a cached PNG or fetches it with + HTTP validators, validates dimensions, decodes and packs R5G6B5 pixels. 4. The 3DS worker receives binary pixels into a free native slot and publishes a small ticket. Socket reads pause when staging credit is exhausted. 5. The scheduler materializes one completed resource per frame. The native @@ -77,7 +83,10 @@ operation receipts across process replacement. The device retains transmission credit after a sent request is cancelled or times out, until its reply arrives or the session ends. The Mac pauses reads at -eight executing requests and pauses writes until the socket drains. Slow image +eight total executing requests, queued replies and blocked writes. While a +write waits for the socket to drain, other work can start within that shared +budget. The scheduler preserves a desired in-flight prefetch when transport +credit cannot admit its replacement. Slow image transfer therefore cannot build a queue proportional to cancelled viewports. Connection logs name socket failures, process exits and timed-out methods; they omit query text and command payloads. @@ -93,6 +102,14 @@ velocity; release follows exponential inertia. Zoom runs an anchored 180ms transition. The integrator gives matching held-input/fling distances at 30 and 60 Hz. Mercator projection is application code. +`camera.setWorld` validates and replaces zoom limits and world bounds when the +provider metadata arrives. It stops previous motion and clamps the camera +without replacing the camera object or resource owners. Hyrule uses a finite +256-unit square and zoom levels 0–7. Its source coordinates map through +`x = (east + 12000) / 24000 * 256` and +`y = (12000 - north) / 24000 * 256`. Search results and bookmarks use an explicit +planar position instead of treating game coordinates as latitude/longitude. + Tile positions are rebased near the viewport before reaching native float transforms, including the nearest world copy at the date line. Tile enumeration has a hard maximum; a mismatched old level cannot create an unbounded loop. @@ -134,12 +151,23 @@ leave a retry action which retains the operation ID. Cancellation of that UI cannot roll back a completed Mac write. Successful writes invalidate saved pages; deleting the last row of a page makes the provider return the preceding populated page. User data lives in `places.sqlite`; HTTP-cache eviction never -touches it. The Mac performs all SQL work in its provider process. - -## Scope - -This app implements map browsing, place search and saved places. It has no GPS location, -turn-by-turn routing, satellite layer or offline-area downloader. Cached views -are a latency optimization. The public demo services are replaceable through -host configuration and have no availability guarantee. Network isolation and -bounded work do not establish a hardware frame-time guarantee. +touches it. Hyrule uses `.local/hyrule/places.sqlite`; the geographic provider +uses `.local/places.sqlite`. Existing geographic records migrate transactionally +to typed positions while preserving IDs and operation receipts. The Mac performs +all SQL work in its provider process. + +## Atlas preparation and scope + +The pinned source contains 1,365 JPEG tiles in six levels. Preparation subdivides +750px source tiles into 256px RGB565 renditions, producing 21,845 tiles in eight +levels and a 2,576-place SQLite FTS5 index. Deflate compression applies only to +Mac storage. The completed atlas replaces its destination atomically after all +levels and metadata have been written. Downloaded art and generated databases +remain outside Git; source attribution is retained in the app and README. + +This app implements map browsing, place search and saved places. Hyrule is fully +installed on the paired Mac; new tiles still require the LAN connection. There +is no GPS, turn-by-turn routing or satellite layer. The optional geographic +provider has no area downloader, and public services have no availability +guarantee. Network isolation and bounded work do not establish a hardware +frame-time guarantee. diff --git a/docs/VALIDATION.md b/docs/VALIDATION.md index ff70009..eeb3d87 100644 --- a/docs/VALIDATION.md +++ b/docs/VALIDATION.md @@ -2,11 +2,13 @@ ## Local execution -- Nine app tests cover Mercator wrapping, immediate controller motion while IO +- Eleven app tests cover Mercator wrapping, immediate controller motion while IO waits, keyboard submission, menu ownership, HTTP validators, cache limits, duplicate requests, pixel order, invalid image dimensions and bounded search results, including a real Bun HTTP 304 cache revalidation. Saved-place tests reopen SQLite, replay committed writes, reject - operation-ID reuse, paginate, rename and delete. TypeScript checks pass. + operation-ID reuse, paginate, rename and delete. Atlas tests check pixel bytes, + cache reuse, FTS search, planar bookmarks, invalid addresses and corrupt data. + Legacy bookmark migration preserves entries and operation receipts. TypeScript checks pass. - The compiled guest ran 1,591 simulated frames against a synthetic provider. Replay covers real auxiliary hit testing, keyboard input, result selection, placing a pin, touch inertia, animated zoom, 180 frames with replies withheld, @@ -15,9 +17,10 @@ entries and three native-image staging tickets (the pool limit is eight). Staging drains to zero after navigation settles. Generated receipts are in `dist/qa/replay.json`. - Live OSM DE tiles and Photon search passed through the same compiled guest - and resource API. Captures in this README are from that Wasm replay. The live - check requests one viewport and one submitted query; it performs no pan scan. -- QuickJS passed 1,084 frames with a 128 KiB stack, including offline mount, + and resource API in the earlier geographic-provider check. That live check + requests one viewport and one submitted query; it performs no pan scan. The + README now shows the compiled guest using the complete local Hyrule atlas. +- QuickJS passed 1,084 frames in each of the geographic and Hyrule modes with a 128 KiB stack, including offline mount, resource reveal, sustained panning, both zoom directions, local typing, search, place navigation and reconnect. Texture tickets drained to zero. @@ -71,9 +74,58 @@ backpressure and has reconnected to the physical 3DS. The guest patch preserving transmission credit passes replay / QuickJS checks and was uploaded through ftpd with byte-for-byte readback: 1,686,296 bytes, SHA-256 `cafcdcc0112c8bde54935f3105852c1d3eb582a5feab264cbeda143b515d1e13`. -Physical interaction acceptance of this patch remains pending. +The Hyrule deployment below supersedes this binary. -The console already has the native development pairing key. That key has been -reused locally for Pocket Map's runtime checkout. `bun run update` rebuilds -only the guest package and delegates delivery and acceptance to PocketJS's -existing development client; ftpd is unnecessary for subsequent guest changes. +A subsequent source inspection found that `POCKETJS_OFFLOAD` excludes both +native development-server initialization and package storage. The existing +pairing key alone does not enable guest updates in this build. Earlier claims +that `bun run update` was ready for Pocket Map were incorrect; the unsupported +command has been removed. Guest fixes still need an ftpd/native deployment. + +## Complete Hyrule atlas and latency correction + +Preparation downloaded the pinned Zelda Dungeon source and generated all +21,845 textures (zoom 0–7) plus 2,576 searchable places. The completed SQLite file +is 591,581,184 bytes. A full verification inflated every texture to exactly +131,072 bytes, checked per-level counts and passed SQLite integrity checking. +The receipt is `dist/qa/hyrule-atlas.json`; source revision is +`d32a85656031d861cef38e32eb927a7d08a983a9`. Assets and databases are ignored. + +The Hyrule compiled-guest replay passes 11 checks across 1,001 frames using that +complete database. It searches Kakariko, navigates to the result, fits the finite +world without wrapping, holds image responses for half a second, enters a +prefetched tile and settles after sustained panning. Maxima remain three active +requests, 40 resident entries and three staging tickets. All tickets drain; +HTTP downloads remain zero. The OSM replay also passes all 27 checks after the +bookmark migration. Receipts are `dist/qa/hyrule.json` and `dist/qa/replay.json`. + +Two regressions demonstrated failures before the framework correction: + +- A blocked image write serialized new provider work. The revised connection + overlaps reads with writes inside eight total executing/queued/writing slots. + A deterministic socket fixture admits eight jobs while its first write waits, + then drains 20 images without disconnecting. +- A still-desired prefetch was cancelled before transport availability was + checked. It now remains useful while a replacement cannot be admitted; its + completed texture is reusable without sending the same tile again. + +The 49 affected resource/offload tests and eight tile-geometry tests pass, as +does framework TypeScript. Geometry coverage includes changing a live camera +from wrapping geographic bounds to a finite atlas and rejecting invalid bounds +without partially mutating camera state. + +The Hyrule native build was uploaded to `192.168.8.102:5000` and read back equal: +1,689,576 bytes, SHA-256 +`31033e5d9d3ef06ff247fd2c85d42b8d64cfd656f5c77d328fd4ba1cea0eca1f`. +The paired Mac is running the local atlas provider. Its connected-device trace +sample contains 375 tile requests: atlas work median/p95 1/1 ms, provider +round-trip median/p95 2/2 ms and zero HTTP downloads. Socket drain waits have +median/p95 353/434 ms over 374 writes. These are host-side measurements, not +render or input latency; each image still sends 128 KiB over the LAN. + +Earlier OSM traces had both cached 1–4 ms provider work and uncached work taking +seconds. The source's documented per-IP speed allowance means absence of HTTP +429 does not rule out throttling. The complete local atlas removes that external +service dependency. It does not establish the 3DS bandwidth limit or continuous +60 fps. The new device session has returned frame telemetry and image requests; +physical gesture acceptance remains separate from liveness and replay results. diff --git a/docs/images/hyrule-search.png b/docs/images/hyrule-search.png new file mode 100644 index 0000000000000000000000000000000000000000..338a916894a61a2cdbd6757aeed314e06d57c8a4 GIT binary patch literal 35277 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 jP4)b(); + private reads = 0; + private hits = 0; + constructor(directory: string) { + this.db = new Database(join(directory, "atlas.sqlite"), { readonly: true }); + const row = this.db.query("SELECT value FROM metadata WHERE key='manifest'").get() as { value: string } | null; + const manifest: AtlasManifest | undefined = row ? JSON.parse(row.value) : undefined; + if (!manifest || manifest.format !== ATLAS_FORMAT || manifest.tiles !== 21845 || manifest.info.space !== "planar") { + this.db.close(); throw new Error("Incomplete Hyrule atlas; run bun run prepare:hyrule"); + } + this.info = manifest.info; + this.bookmarks = new Bookmarks(join(directory, "places.sqlite")); + } + methods() { return { + "map.info": () => JSON.stringify(this.info), + "map.tile": (raw: string) => this.tile(JSON.parse(raw)), + "map.search": (raw: string) => JSON.stringify(this.search(JSON.parse(raw))), + "map.label": (raw: string) => renderLabel(JSON.parse(raw)), + "bookmarks.list": (raw: string) => JSON.stringify(this.bookmarks.list(JSON.parse(raw).offset)), + "bookmarks.command": (raw: string) => this.bookmarks.command(JSON.parse(raw)), + }; } + tile(input: TileInput): OffloadImage { + const { source, z, x, y } = input; + if (source !== this.info.source || ![z, x, y].every(Number.isInteger) || z < 0 || z > 7 || x < 0 || y < 0 || x >= 2 ** z || y >= 2 ** z) throw new Error("Invalid atlas tile"); + const key = `${z}/${x}/${y}`, hit = this.images.get(key); + if (hit) { this.hits++; this.images.delete(key); this.images.set(key, hit); return hit; } + const row = this.db.query("SELECT pixels FROM tiles WHERE z=? AND x=? AND y=?").get(z, x, y) as { pixels: Uint8Array } | null; + if (!row) throw new Error("Missing installed atlas tile"); + const pixels = new Uint8Array(inflateRawSync(row.pixels, { maxOutputLength: 131072 })); + if (pixels.length !== 131072) throw new Error("Invalid atlas pixels"); + const image: OffloadImage = { width: 256, height: 256, format: "r5g6b5", pixels }; + this.reads++; this.images.set(key, image); + if (this.images.size > 128) this.images.delete(this.images.keys().next().value!); + return image; + } + search(input: SearchInput): Place[] { + if (!input || typeof input.query !== "string" || input.query.length > 80 || !validPosition(input) || input.space !== "planar") throw new Error("Invalid atlas search"); + const words = input.query.match(/[\p{L}\p{N}]+/gu)?.slice(0, 8); + if (!words?.length) return []; + const match = words.map(word => `"${word}"*`).join(" AND "); + const rows = this.db.query(`SELECT id,name,detail,x,y,zoom FROM place_search WHERE place_search MATCH ? + ORDER BY rank, ((x-?)*(x-?)+(y-?)*(y-?)) LIMIT 5`).all(match, input.x, input.x, input.y, input.y) as Omit, "space">[]; + return rows.map(row => ({ ...row, space: "planar" })); + } + diagnostics() { return { atlasReads: this.reads, memoryHits: this.hits, downloads: 0 }; } + close() { this.db.close(); this.bookmarks.close(); } +} diff --git a/host/bookmarks.ts b/host/bookmarks.ts index ba7cf02..5978c94 100644 --- a/host/bookmarks.ts +++ b/host/bookmarks.ts @@ -3,6 +3,7 @@ import { createHash } from "node:crypto"; import { mkdirSync } from "node:fs"; import { dirname } from "node:path"; import type { BookmarkPage, BookmarkCommand, Place } from "../shared/types.ts"; +import { validPosition } from "../shared/types.ts"; /** User data has its own database: evicting the HTTP cache cannot erase it. * Mutation receipts and changes commit together, including deletion receipts. */ @@ -11,15 +12,22 @@ export class Bookmarks { constructor(path: string) { if (path !== ":memory:") mkdirSync(dirname(path), { recursive: true }); this.db = new Database(path); - this.db.exec(`PRAGMA journal_mode=WAL; - CREATE TABLE IF NOT EXISTS places (seq INTEGER PRIMARY KEY AUTOINCREMENT, id TEXT UNIQUE NOT NULL, name TEXT NOT NULL, detail TEXT NOT NULL, lat REAL NOT NULL, lon REAL NOT NULL, zoom INTEGER NOT NULL); - CREATE TABLE IF NOT EXISTS receipts (op TEXT PRIMARY KEY, body TEXT NOT NULL, result TEXT NOT NULL);`); + this.db.exec("PRAGMA journal_mode=WAL"); + this.db.transaction(() => { + const migrated = this.db.query("SELECT name FROM sqlite_master WHERE name='locations'").get(); + this.db.exec(`CREATE TABLE IF NOT EXISTS locations (seq INTEGER PRIMARY KEY AUTOINCREMENT, id TEXT UNIQUE NOT NULL, name TEXT NOT NULL, detail TEXT NOT NULL, position TEXT NOT NULL, zoom INTEGER NOT NULL); + CREATE TABLE IF NOT EXISTS receipts (op TEXT PRIMARY KEY, body TEXT NOT NULL, result TEXT NOT NULL);`); + if (!migrated && this.db.query("SELECT name FROM sqlite_master WHERE name='places'").get()) { + this.db.exec("INSERT INTO locations SELECT seq,id,name,detail,json_object('lat',lat,'lon',lon),zoom FROM places"); + } + })(); } list(offset: number): BookmarkPage { if (!Number.isSafeInteger(offset) || offset < 0 || offset > 995 || offset % 5) throw new Error("Invalid saved places page"); - const total = (this.db.query("SELECT count(*) AS n FROM places").get() as { n: number }).n; + const total = (this.db.query("SELECT count(*) AS n FROM locations").get() as { n: number }).n; offset = Math.min(offset, Math.max(0, Math.ceil(total / 5) - 1) * 5); - const items = this.db.query("SELECT id,name,detail,lat,lon,zoom FROM places ORDER BY seq DESC LIMIT 5 OFFSET ?").all(offset) as Place[]; + const rows = this.db.query("SELECT id,name,detail,position,zoom FROM locations ORDER BY seq DESC LIMIT 5 OFFSET ?").all(offset) as { id: string; name: string; detail: string; position: string; zoom: number }[]; + const items: Place[] = rows.map(({ position, ...row }) => ({ ...row, ...JSON.parse(position) })); return { items, offset, total }; } command(command: BookmarkCommand): string { @@ -32,17 +40,18 @@ export class Bookmarks { let id = command.id; if (command.kind === "save") { const p = command.place; - if (!p || typeof p.name !== "string" || !p.name.trim() || p.name.length > 36 || typeof p.detail !== "string" || p.detail.length > 60 || !Number.isFinite(p.lat) || Math.abs(p.lat) > 90 || !Number.isFinite(p.lon) || Math.abs(p.lon) > 180 || !Number.isInteger(p.zoom) || p.zoom < 1 || p.zoom > 18) throw new Error("Invalid saved place"); + if (!p || typeof p.name !== "string" || !p.name.trim() || p.name.length > 36 || typeof p.detail !== "string" || p.detail.length > 60 || !validPosition(p) || !Number.isInteger(p.zoom) || p.zoom < 0 || p.zoom > 18) throw new Error("Invalid saved place"); if (this.list(0).total >= 1000) throw new Error("Saved places limit reached (1000)"); id = "b_" + createHash("sha256").update(command.op).digest("hex").slice(0, 24); - this.db.query("INSERT INTO places (id,name,detail,lat,lon,zoom) VALUES (?,?,?,?,?,?)").run(id, p.name.trim(), p.detail, p.lat, p.lon, p.zoom); + const position = p.space === "planar" ? { space: p.space, x: p.x, y: p.y } : { lat: p.lat, lon: p.lon }; + this.db.query("INSERT INTO locations (id,name,detail,position,zoom) VALUES (?,?,?,?,?)").run(id, p.name.trim(), p.detail, JSON.stringify(position), p.zoom); } else { if (typeof id !== "string" || !/^b_[a-f0-9]{24}$/.test(id)) throw new Error("Invalid saved place ID"); - if (!this.db.query("SELECT id FROM places WHERE id=?").get(id)) throw new Error("Saved place no longer exists"); + if (!this.db.query("SELECT id FROM locations WHERE id=?").get(id)) throw new Error("Saved place no longer exists"); if (command.kind === "rename") { if (typeof command.name !== "string" || !command.name.trim() || command.name.length > 36) throw new Error("Name must contain 1-36 characters"); - this.db.query("UPDATE places SET name=? WHERE id=?").run(command.name.trim(), id); - } else if (command.kind === "remove") this.db.query("DELETE FROM places WHERE id=?").run(id); + this.db.query("UPDATE locations SET name=? WHERE id=?").run(command.name.trim(), id); + } else if (command.kind === "remove") this.db.query("DELETE FROM locations WHERE id=?").run(id); else throw new Error("Unknown saved place command"); } const result = JSON.stringify({ id }); diff --git a/host/config.ts b/host/config.ts index b36a7a3..e77e4c6 100644 --- a/host/config.ts +++ b/host/config.ts @@ -1,4 +1,4 @@ -export interface ProviderConfig { tileURL: string; searchURL: string; name: string; attribution: string; maxZoom: number; cache: string } +export interface ProviderConfig { tileURL: string; searchURL: string; name: string; attribution: string; maxZoom: number; cache: string; kind?: "osm" | "hyrule"; atlas?: string } export const defaultConfig: ProviderConfig = { tileURL: "https://tile.openstreetmap.de/{z}/{x}/{y}.png", searchURL: "https://photon.komoot.io/api/", name: "OpenStreetMap DE", attribution: "OpenStreetMap contributors", maxZoom: 18, cache: ".local/cache.sqlite", diff --git a/host/provider.ts b/host/provider.ts index 1606e5d..111dbd7 100644 --- a/host/provider.ts +++ b/host/provider.ts @@ -67,7 +67,7 @@ export class MapProvider { return packRGB(ctx.getImageData(0, 0, 256, 256).data, 256, 256); } async search(input: SearchInput): Promise { - if (typeof input.query !== "string" || input.query.length > 80 || !Number.isFinite(input.lat) || Math.abs(input.lat) > 90 || !Number.isFinite(input.lon) || Math.abs(input.lon) > 180) throw new Error("Invalid place search"); + if (input.space === "planar" || typeof input.query !== "string" || input.query.length > 80 || !Number.isFinite(input.lat) || Math.abs(input.lat) > 90 || !Number.isFinite(input.lon) || Math.abs(input.lon) > 180) throw new Error("Invalid place search"); const query = input.query.trim(); if (!query) return []; if (this.searching) throw new Error("A search is already running"); this.searching = true; @@ -91,7 +91,12 @@ export class MapProvider { return places; } finally { this.searching = false; } } - label(input: { name: string; detail: string }) { + label(input: { name: string; detail: string }) { return renderLabel(input); } + diagnostics() { return { httpHits: this.cache.hits, downloads: this.cache.downloads }; } + close() { this.cache.close(); this.bookmarks.close(); } +} + +export function renderLabel(input: { name: string; detail: string }) { if (typeof input.name !== "string" || input.name.length > 80 || typeof input.detail !== "string" || input.detail.length > 120) throw new Error("Invalid label"); const canvas = createCanvas(256, 32), c = canvas.getContext("2d"); c.fillStyle = "#f7f9fc"; c.fillRect(0, 0, 256, 32); @@ -99,5 +104,3 @@ export class MapProvider { c.fillStyle = "#627387"; c.font = "11px Arial"; c.fillText(input.detail, 5, 28, 246); return packRGB(c.getImageData(0, 0, 256, 32).data, 256, 32); } - close() { this.cache.close(); this.bookmarks.close(); } -} diff --git a/host/serve.ts b/host/serve.ts index 334d9ae..ba26b29 100644 --- a/host/serve.ts +++ b/host/serve.ts @@ -2,10 +2,14 @@ import { resolve } from "node:path"; import { connectOffloadProvider } from "@pocketjs/framework/offload/provider"; import { defaultConfig } from "./config.ts"; const root = resolve(import.meta.dir, ".."); -const address = process.argv[2] ?? "192.168.8.102"; +const address = process.argv.slice(2).find(arg => !arg.startsWith("--")) ?? "192.168.8.102"; const configPath = resolve(root, ".local/provider.json"); const config = { ...defaultConfig, ...(await Bun.file(configPath).exists() ? await Bun.file(configPath).json() : {}), cache: resolve(root, ".local/cache.sqlite") }; +config.kind = process.argv.includes("--osm") ? "osm" : process.argv.includes("--hyrule") ? "hyrule" : config.kind ?? "hyrule"; +config.atlas = resolve(root, ".local/hyrule"); +if (config.kind === "hyrule" && !await Bun.file(resolve(config.atlas, "atlas.sqlite")).exists()) throw new Error("Run bun run prepare:hyrule before starting the Hyrule host"); const key = (await Bun.file(resolve(root, ".local/pair.key")).text()).trim(); connectOffloadProvider({ address, key, worker: new URL("./worker.ts", import.meta.url), isolation: "process", data: config, + trace: process.env.POCKET_MAP_TRACE === "1", log: message => console.log(new Date().toISOString(), message) }); -console.log(`Pocket Map: ${config.name} -> ${address}; cache ${config.cache}`); +console.log(`Pocket Map: ${config.kind === "hyrule" ? "Hyrule (local atlas)" : config.name} -> ${address}; ${config.kind === "hyrule" ? config.atlas : config.cache}`); diff --git a/host/worker.ts b/host/worker.ts index 27e4c40..bbbd27c 100644 --- a/host/worker.ts +++ b/host/worker.ts @@ -1,8 +1,16 @@ import { dispatchOffload } from "@pocketjs/framework/offload/provider"; import { MapProvider } from "./provider.ts"; +import { AtlasProvider } from "./atlas.ts"; declare const self: { onmessage: (event: MessageEvent) => void; postMessage(value: unknown): void }; -let provider: MapProvider; +let provider: MapProvider | AtlasProvider; +const trace = process.env.POCKET_MAP_TRACE === "1"; self.onmessage = async event => { - if (event.data.init) { provider = new MapProvider(event.data.init); return; } - self.postMessage(await dispatchOffload(provider.methods(), event.data)); + if (event.data.init) { + provider = event.data.init.kind === "hyrule" ? new AtlasProvider(event.data.init.atlas) : new MapProvider(event.data.init); + return; + } + const started = Date.now(); + const reply = await dispatchOffload(provider.methods(), event.data); + if (trace) console.log(new Date().toISOString(), `Map request id=${event.data.id} method=${event.data.method} workMs=${Date.now() - started} stats=${JSON.stringify(provider.diagnostics())} error=${reply.error ?? "none"}`); + self.postMessage(reply); }; diff --git a/package.json b/package.json index d9829fd..6fef92a 100644 --- a/package.json +++ b/package.json @@ -3,9 +3,8 @@ "scripts": { "setup": "bun scripts/setup.ts", "3ds": "bun scripts/build.ts", "host": "bun host/serve.ts", "deploy": "bun scripts/deploy.ts", "sim": "bun scripts/sim.ts", - "3ds:pair": "bun runtime/tools/3ds-dev.ts pair", - "update": "bun run 3ds --pocket-only && bun runtime/tools/3ds-dev.ts push --package dist/pocketmap-main.pocket", - "test": "bun test --conditions=browser test/geo.test.ts test/provider.test.ts test/model.test.ts test/bookmarks.test.ts test/transport.test.ts", + "prepare:hyrule": "bun scripts/prepare-hyrule.ts", + "test": "bun test --conditions=browser test/geo.test.ts test/provider.test.ts test/model.test.ts test/bookmarks.test.ts test/transport.test.ts test/atlas.test.ts", "check": "bun run test && runtime/node_modules/.bin/tsc --noEmit" } } diff --git a/runtime b/runtime index b43e0df..a6c1702 160000 --- a/runtime +++ b/runtime @@ -1 +1 @@ -Subproject commit b43e0df47ac68dbe922af0c0b57609ae6e4f51ac +Subproject commit a6c1702a67b2ff18b0a1b1aa398a75bf3ce4251e diff --git a/scripts/prepare-hyrule.ts b/scripts/prepare-hyrule.ts new file mode 100644 index 0000000..45740b0 --- /dev/null +++ b/scripts/prepare-hyrule.ts @@ -0,0 +1,96 @@ +import { createHash } from "node:crypto"; +import { existsSync, mkdirSync, renameSync, rmSync, readdirSync } from "node:fs"; +import { resolve, join } from "node:path"; +import { deflateRawSync } from "node:zlib"; +import { Database } from "bun:sqlite"; +import { createCanvas, loadImage } from "@napi-rs/canvas"; +import { packRGB } from "../host/provider.ts"; +import { ATLAS_FORMAT, HYRULE_REVISION, type AtlasManifest } from "../host/atlas.ts"; +import type { MapInfo } from "../shared/types.ts"; + +const root = resolve(import.meta.dir, ".."), source = join(root, ".local/hyrule-source"); +const directory = join(root, ".local/hyrule"), output = join(directory, "atlas.sqlite"); +async function git(...args: string[]) { + const child = Bun.spawn(["git", ...args], { stdout: "pipe", stderr: "inherit" }); + const text = await new Response(child.stdout).text(); + if (await child.exited) throw new Error("Hyrule source checkout failed"); + return text.trim(); +} +mkdirSync(directory, { recursive: true }); +if (existsSync(output) && !process.argv.includes("--rebuild")) { + const db = new Database(output, { readonly: true }); + const manifest = JSON.parse((db.query("SELECT value FROM metadata WHERE key='manifest'").get() as { value: string }).value) as AtlasManifest; + db.close(); + if (manifest.revision !== HYRULE_REVISION || manifest.format !== ATLAS_FORMAT) throw new Error("Atlas version differs; use --rebuild"); + console.log(`Hyrule ready: ${manifest.tiles} local textures, ${manifest.places} searchable places`); + process.exit(0); +} +if (!existsSync(join(source, ".git"))) await git("clone", "--depth", "1", "--filter=blob:none", "--sparse", "--branch", "develop", "https://github.com/zeldadungeon/maps.git", source); +if (await git("-C", source, "rev-parse", "HEAD") !== HYRULE_REVISION) { + await git("-C", source, "fetch", "--depth", "1", "origin", HYRULE_REVISION); + await git("-C", source, "checkout", "--detach", HYRULE_REVISION); +} +await git("-C", source, "sparse-checkout", "set", "public/botw"); +const assets = join(source, "public/botw"); +for (let z = 0; z <= 5; z++) { + if (readdirSync(join(assets, `tiles/${z}`)).filter(file => file.endsWith(".jpg")).length !== 4 ** z) throw new Error("Incomplete source tile pyramid"); +} +console.log("Source verified: 1,365 JPEG tiles, full 24,000px map pyramid; baking on the Mac"); +const pending = join(directory, "atlas.build.sqlite"); +if (existsSync(pending)) rmSync(pending); +const db = new Database(pending); +db.exec(`PRAGMA journal_mode=DELETE; PRAGMA synchronous=NORMAL; + CREATE TABLE metadata (key TEXT PRIMARY KEY, value TEXT NOT NULL); + CREATE TABLE tiles (z INTEGER, x INTEGER, y INTEGER, pixels BLOB NOT NULL, PRIMARY KEY(z,x,y)) WITHOUT ROWID; + CREATE VIRTUAL TABLE place_search USING fts5(id UNINDEXED,name,detail,x UNINDEXED,y UNINDEXED,zoom UNINDEXED,tokenize='unicode61 remove_diacritics 2');`); +let tiles = 0, places = 0; +const insertTile = db.query("INSERT INTO tiles VALUES (?,?,?,?)"); +const canvas = createCanvas(256, 256), ctx = canvas.getContext("2d"); +ctx.imageSmoothingEnabled = true; +try { + for (let z = 0; z <= 7; z++) { + const sourceZ = Math.max(0, z - 2), divide = 2 ** (z - sourceZ), crop = 750 / divide; + for (let y = 0; y < 2 ** sourceZ; y++) for (let x = 0; x < 2 ** sourceZ; x++) { + const image = await loadImage(join(assets, `tiles/${sourceZ}/${x}_${y}.jpg`)); + if (image.width !== 750 || image.height !== 750) throw new Error("Invalid source tile dimensions"); + db.transaction(() => { + for (let dy = 0; dy < divide; dy++) for (let dx = 0; dx < divide; dx++) { + ctx.drawImage(image, dx * crop, dy * crop, crop, crop, 0, 0, 256, 256); + const image565 = packRGB(ctx.getImageData(0, 0, 256, 256).data, 256, 256); + insertTile.run(z, x * divide + dx, y * divide + dy, deflateRawSync(image565.pixels, { level: 1 })); tiles++; + } + })(); + if (tiles % 1024 < 16) console.log(`Baked ${tiles}/21845 textures`); + } + console.log(`Level ${z} complete (${tiles} textures)`); + } + const insertPlace = db.query("INSERT INTO place_search VALUES (?,?,?,?,?,?)"); + const seen = new Set(); + for (const file of ["locations", "pins", "seeds", "treasures"]) { + const groups = await Bun.file(join(assets, `markers/${file}.json`)).json(); + db.transaction(() => { + for (const group of groups) for (const layer of group.layers ?? []) for (const marker of layer.markers ?? []) { + if (!Array.isArray(marker.coords) || marker.coords.length !== 2 || !marker.coords.every(Number.isFinite)) continue; + const [north, east] = marker.coords; + const x = (east + 12000) / 24000 * 256, y = (12000 - north) / 24000 * 256; + if (x < 0 || y < 0 || x > 256 || y > 256) continue; + const kind = file === "seeds" ? "Korok seed" : file === "treasures" ? "Treasure" : group.name; + const name = String(marker.name ?? `${kind} ${marker.id ?? places + 1}`).replace(/<[^>]+>/g, "").slice(0, 36); + const key = `${name}/${x.toFixed(3)}/${y.toFixed(3)}`; + if (seen.has(key)) continue; seen.add(key); + const id = "h_" + createHash("sha256").update(key).digest("hex").slice(0, 24); + const detail = String(file === "seeds" || file === "treasures" ? `${kind} - ${group.name}` : kind).slice(0, 60); + insertPlace.run(id, name, detail, x, y, group.name === "Region" ? 3 : group.name === "Subregion" ? 4 : 6); places++; + } + })(); + } + const info: MapInfo = { source: createHash("sha256").update(`${ATLAS_FORMAT}/${HYRULE_REVISION}`).digest("hex").slice(0, 16), + name: "Hyrule - Breath of the Wild", attribution: "Nintendo | Zelda Dungeon", minZoom: 0, maxZoom: 7, space: "planar", local: true, + home: { id: "hyrule-home", name: "Great Plateau", detail: "Breath of the Wild", space: "planar", x: (12000 - 1900) / 24000 * 256, y: (12000 + 3750) / 24000 * 256, zoom: 4 } }; + const manifest: AtlasManifest = { format: ATLAS_FORMAT, revision: HYRULE_REVISION, tiles, places, info }; + if (tiles !== 21845) throw new Error("Incomplete atlas bake"); + db.query("INSERT INTO metadata VALUES ('manifest',?)").run(JSON.stringify(manifest)); + db.close(); renameSync(pending, output); + await Bun.write(join(directory, "manifest.json"), JSON.stringify(manifest, null, 2)); + console.log(`Hyrule ready: ${tiles} textures and ${places} searchable places, no runtime internet access`); +} catch (error) { db.close(); throw error; } diff --git a/scripts/quickjs-smoke.js b/scripts/quickjs-smoke.js index f9203d5..df3ae30 100644 --- a/scripts/quickjs-smoke.js +++ b/scripts/quickjs-smoke.js @@ -1,5 +1,6 @@ // QuickJS execution/stack check with host stubs. Pixels are covered by sim.ts. let node = 3, texture = 1, session = -1, ticks = 0, token = 1; +const hyrule = scriptArgs[2] === "hyrule"; const replies = [], tickets = new Set(), saved = []; globalThis.ui = { __host: "3ds-dev", __hostAbi: 8, __viewport: { w: 400, h: 240 }, __auxiliarySurface: { root: 2, w: 320, h: 240 }, __textures: { "shift.svg": 0, "shift-lock.svg": 1, "map-pad.svg": 2, "map-pin.svg": 3 }, __sprites: {}, createNode: () => node++, measureText: text => text.length * 7 }; @@ -19,7 +20,9 @@ globalThis.offload = { else if (c.kind === "rename") saved[0].name = c.name; else saved.length = 0; value = { id }; - } else value = r.method === "map.info" ? { source: "0123456789abcdef", name: "Smoke map", attribution: "Test", maxZoom: 18 } : [{ id: "one", name: "Tokyo", detail: "Japan", lat: 35.68, lon: 139.76, zoom: 14 }]; + } else value = r.method === "map.info" ? { source: "0123456789abcdef", name: "Smoke map", attribution: "Test", maxZoom: hyrule ? 7 : 18, + ...(hyrule ? { minZoom: 0, space: "planar", local: true, home: { id: "home", name: "Plateau", detail: "Test", space: "planar", x: 108, y: 168, zoom: 4 } } : {}) } + : [hyrule ? { id: "one", name: "Kakariko", detail: "Hyrule", space: "planar", x: 166, y: 149, zoom: 6 } : { id: "one", name: "Tokyo", detail: "Japan", lat: 35.68, lon: 139.76, zoom: 14 }]; replies.push(JSON.stringify({ id: r.id, payload: JSON.stringify(value) })); } return true; @@ -34,7 +37,7 @@ try { session = 1; frames(90); check(s.front().tiles.every(t => s.frontView.state(t.input).status === "ready"), "tile reveal"); frames(300, 0, 0x80ff); s.zoom(1); frames(90); s.zoom(-1); frames(90); s.openSearch(); s.key("t"); check(s.query() === "t", "local typing"); s.search(); frames(60); check(s.places().length === 1, "search"); - s.go(); frames(90); check(s.pin().name === "Tokyo", "place navigation"); + s.go(); frames(90); check(s.pin().name === (hyrule ? "Kakariko" : "Tokyo"), "place navigation"); s.saveCurrent(); check(s.mode() === "name", "save naming mount"); s.saved.changeName("Saved in QuickJS"); s.key("GO"); frames(60); check(s.mode() === "saved" && s.saved.page().total === 1, "saved list mount"); s.saved.begin(s.saved.selected(), true); s.saved.changeName("Renamed"); s.key("GO"); frames(60); diff --git a/scripts/sim.ts b/scripts/sim.ts index 64de800..fb8d3d7 100644 --- a/scripts/sim.ts +++ b/scripts/sim.ts @@ -5,15 +5,17 @@ import { NODE_TYPE, PROP, BTN } from "../runtime/contracts/spec/spec.ts"; import { encodePNG } from "../runtime/tests/png.ts"; import { dispatchOffload } from "../runtime/tools/offload-provider.ts"; import { MapProvider, defaultConfig } from "../host/provider.ts"; +import { AtlasProvider } from "../host/atlas.ts"; import type { MapModel } from "../app/model.ts"; import type { OffloadImage } from "../runtime/contracts/spec/offload.ts"; const live = process.argv.includes("--live"); +const hyrule = process.argv.includes("--hyrule"); const fixture = createCanvas(256, 256), c = fixture.getContext("2d"); c.fillStyle = "#e8e5d7"; c.fillRect(0, 0, 256, 256); c.fillStyle = "#b3ced7"; c.fillRect(170, 0, 86, 256); for (let x = 14; x < 170; x += 30) { c.fillStyle = "#fffdf4"; c.fillRect(x, 0, 5, 256); } for (let y = 20; y < 256; y += 32) { c.fillStyle = "#fffdf4"; c.fillRect(0, y, 170, 5); } c.fillStyle = "#b8cfa4"; c.fillRect(50, 70, 55, 48); c.fillStyle = "#5e705e"; c.font = "13px Arial"; c.fillText("Replay fixture", 30, 155); -const provider = new MapProvider({ ...defaultConfig, cache: live ? ".local/cache.sqlite" : ":memory:" }, live ? fetch : (async url => { +const provider = hyrule ? new AtlasProvider(".local/hyrule") : new MapProvider({ ...defaultConfig, cache: live ? ".local/cache.sqlite" : ":memory:" }, live ? fetch : (async url => { if (String(url).includes("photon")) return new Response(JSON.stringify({ features: [ { properties: { osm_type: "R", osm_id: 1, name: "San Francisco", city: "San Francisco", country: "United States", type: "city" }, geometry: { coordinates: [-122.4075, 37.7879] } }, { properties: { osm_type: "N", osm_id: 2, name: "Museum of Modern Art", city: "San Francisco", type: "other" }, geometry: { coordinates: [-122.4007, 37.7859] } }, @@ -30,6 +32,7 @@ ops.insertBefore(1, auxiliary, 0); ops.__auxiliarySurface = { root: auxiliary, w const requests: string[] = [], replies: { at: number; raw: string }[] = []; const images = new Map(); let tick = 0, token = 1, session = 1, uploads = 0, maxStaging = 0, maxPending = 0, maxResident = 0, withhold = false, loseCommandAck = false; +let replyDelay = 3; let hit: number | undefined; const checks: string[] = [], failures: string[] = []; Object.assign(globalThis, { ui: ops, __pak: await Bun.file("runtime/dist/3ds/guest/pocketmap-main.pak").arrayBuffer(), __simHz: 60, @@ -64,22 +67,41 @@ async function frames(n: number, buttons = 0, touch?: [number, number], analog = } if (result.image) { const id = token++; images.set(id, result.image); maxStaging = Math.max(maxStaging, images.size); - replies.push({ at: tick + 3, raw: JSON.stringify({ id: result.id, image: { token: id, width: result.image.width, height: result.image.height } }) }); - } else replies.push({ at: tick + 3, raw: JSON.stringify(result) }); + replies.push({ at: tick + replyDelay, raw: JSON.stringify({ id: result.id, image: { token: id, width: result.image.width, height: result.image.height } }) }); + } else replies.push({ at: tick + replyDelay, raw: JSON.stringify(result) }); } } } async function tap(x: number, y: number) { await frames(1, 0, [x, y]); await frames(1); } async function press(button: number) { await frames(1, button); await frames(1); } mkdirSync("dist/qa", { recursive: true }); -async function shot(name: string) { await Bun.write(`dist/qa/${live ? "live-" : "replay-"}${name}.png`, encodePNG(wasm.render().slice(), 400, 480)); } +async function shot(name: string) { await Bun.write(`dist/qa/${hyrule ? "hyrule-" : live ? "live-" : "replay-"}${name}.png`, encodePNG(wasm.render().slice(), 400, 480)); } await frames(3); await shot("loading"); await frames(75); if (live && !s.front()!.tiles.every(t => s.frontView.state(t.input).status === "ready")) console.log(s.front()!.tiles.map(t => ({ input: t.input, state: s.frontView.state(t.input) }))); check(s.front()!.tiles.every(t => s.frontView.state(t.input).status === "ready"), "All visible tiles materialize through resource demand and native image tickets"); await shot("map"); await tap(30, 18); check(s.mode() === "search", "Search touch button opens local keyboard"); await shot("keyboard"); -if (live) { +if (hyrule) { + check(s.planar() && s.info()?.local, "Hyrule opens as a local finite atlas with its own home and zoom bounds"); + s.setQuery("Kakariko"); s.search(); await frames(40); await shot("results"); + check(s.places().some(p => p.name.includes("Kakariko")), "SQLite place search finds Kakariko without an HTTP request"); + s.go(); await frames(100); await shot("village"); + check(s.pin()?.space === "planar" && s.front()!.tiles.every(t => s.frontView.state(t.input).status === "ready"), "Search navigation places the pin in atlas coordinates and resolves the village tiles"); + s.camera.jump(128, 128, 0); await frames(100); await shot("overview"); + check(s.front()!.tiles.length === 1 && s.front()!.tiles[0].input.z === 0, "Minimum zoom covers the finite world without wrapping copies"); + replyDelay = 30; + s.camera.jump((32 * 256 - 300) / 64, (32 * 256 + 128) / 64, 6); await frames(180); + const edge = { source: s.info()!.source, z: 6, x: 32, y: 32 }; + check(s.frontView.state(edge).status === "ready", "Local prefetch prepares a tile 100px beyond the edge with half-second response latency"); + s.camera.drag(-101, 0); await frames(1); + check(s.front()!.tiles.some(t => t.input.x === 32 && t.input.y === 32) && s.frontView.state(edge).status === "ready", "Crossing the local atlas edge reveals the prefetched tile immediately"); + await frames(180, 0, undefined, 0x80ff); await frames(220); + check(s.front()!.tiles.every(t => s.frontView.state(t.input).status === "ready"), "The local atlas catches up after sustained motion with delayed replies"); + check(s.lookAhead().length <= 12 && maxResident <= 40 && maxPending <= 4 && maxStaging <= 8, "Larger local prefetch stays within device request, staging and residency budgets"); + replyDelay = 3; await frames(100); await shot("pan"); + check(images.size === 0, "Atlas navigation releases every consumed or cancelled image ticket"); +} else if (live) { // One requested view and one explicit search. Stress replay never uses public tiles. s.setQuery("San Francisco"); s.search(); await frames(35); await shot("results"); check(s.places().length > 0, "Live Photon search returned places"); @@ -142,6 +164,6 @@ if (live) { await frames(50); } } -const receipt = { mode: live ? "live OSM DE / Photon, compiled guest + Wasm" : "deterministic synthetic provider, compiled guest + Wasm", frames: tick, checks, maxPending, maxResident, maxStaging, downloads: provider.cache.downloads, cacheHits: provider.cache.hits, +const receipt = { mode: hyrule ? "complete local Hyrule atlas, compiled guest + Wasm" : live ? "live OSM DE / Photon, compiled guest + Wasm" : "deterministic synthetic provider, compiled guest + Wasm", frames: tick, checks, maxPending, maxResident, maxStaging, ...provider.diagnostics(), hardwareAcceptance: "pending", performance: "Replay validates behavior and budgets, not device frame time" }; -await Bun.write(`dist/qa/${live ? "live" : "replay"}.json`, JSON.stringify(receipt, null, 2)); console.log(receipt); provider.close(); +await Bun.write(`dist/qa/${hyrule ? "hyrule" : live ? "live" : "replay"}.json`, JSON.stringify(receipt, null, 2)); console.log(receipt); provider.close(); diff --git a/shared/types.ts b/shared/types.ts index d23e762..6265bea 100644 --- a/shared/types.ts +++ b/shared/types.ts @@ -1,7 +1,16 @@ -export interface Place { id: string; name: string; detail: string; lat: number; lon: number; zoom: number } -export interface MapInfo { source: string; name: string; attribution: string; maxZoom: number } +export type Position = { space?: "mercator"; lat: number; lon: number } | { space: "planar"; x: number; y: number }; +export type Place = Position & { id: string; name: string; detail: string; zoom: number }; +export interface MapInfo { source: string; name: string; attribution: string; maxZoom: number; minZoom?: number; + space?: "mercator" | "planar"; home?: Place; local?: boolean } export interface TileInput { source: string; z: number; x: number; y: number } -export interface SearchInput { query: string; lat: number; lon: number } +export type SearchInput = Position & { query: string }; export interface BookmarkPage { items: Place[]; offset: number; total: number } export interface BookmarkCommand { op: string; kind: "save" | "rename" | "remove"; id?: string; place?: Place; name?: string } export const HOME = { lat: 37.7879, lon: -122.4075, zoom: 14 }; +export function validPosition(value: unknown): value is Position { + if (!value || typeof value !== "object") return false; + const p = value as Record; + return p.space === "planar" + ? typeof p.x === "number" && Number.isFinite(p.x) && p.x >= 0 && p.x <= 256 && typeof p.y === "number" && Number.isFinite(p.y) && p.y >= 0 && p.y <= 256 + : (p.space === undefined || p.space === "mercator") && typeof p.lat === "number" && Number.isFinite(p.lat) && Math.abs(p.lat) <= 90 && typeof p.lon === "number" && Number.isFinite(p.lon) && Math.abs(p.lon) <= 180; +} diff --git a/test/atlas.test.ts b/test/atlas.test.ts new file mode 100644 index 0000000..c62bb6f --- /dev/null +++ b/test/atlas.test.ts @@ -0,0 +1,48 @@ +import { expect, test } from "bun:test"; +import { Database } from "bun:sqlite"; +import { deflateRawSync } from "node:zlib"; +import { mkdtempSync, rmSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; +import { AtlasProvider, ATLAS_FORMAT } from "../host/atlas.ts"; + +test("local atlas reads packed textures and searches planar places without an HTTP provider", () => { + const dir = mkdtempSync(join(tmpdir(), "pocket-map-atlas-")), db = new Database(join(dir, "atlas.sqlite")); + const source = "123456789abcdef0"; + db.exec(`CREATE TABLE metadata (key TEXT PRIMARY KEY, value TEXT); + CREATE TABLE tiles (z INTEGER,x INTEGER,y INTEGER,pixels BLOB,PRIMARY KEY(z,x,y)); + CREATE VIRTUAL TABLE place_search USING fts5(id UNINDEXED,name,detail,x UNINDEXED,y UNINDEXED,zoom UNINDEXED);`); + db.query("INSERT INTO metadata VALUES ('manifest',?)").run(JSON.stringify({ format: ATLAS_FORMAT, tiles: 21845, + info: { source, name: "Fixture atlas", attribution: "Test", minZoom: 0, maxZoom: 7, space: "planar", local: true } })); + const pixels = new Uint8Array(131072); + for (let n = 0; n < pixels.length; n++) pixels[n] = n % 251; + db.query("INSERT INTO tiles VALUES (0,0,0,?)").run(deflateRawSync(pixels)); + db.query("INSERT INTO tiles VALUES (7,127,127,?)").run(deflateRawSync(pixels)); + db.query("INSERT INTO tiles VALUES (1,0,0,?)").run(deflateRawSync(new Uint8Array(131073))); + const place = db.query("INSERT INTO place_search VALUES (?,?,?,?,?,?)"); + place.run("h1", "Kakariko Village", "Village", 151, 130, 5); + place.run("h2", "Kakariko Bridge", "Landmark", 151, 140, 6); + for (let n = 0; n < 8; n++) place.run("s" + n, "Test Shrine " + n, "Shrine", 100 + n, 100, 6); + db.close(); + let atlas = new AtlasProvider(dir); + try { + expect(atlas.tile({ source, z: 0, x: 0, y: 0 }).pixels).toEqual(pixels); + expect(atlas.tile({ source, z: 0, x: 0, y: 0 }).pixels).toEqual(pixels); + expect(atlas.tile({ source, z: 7, x: 127, y: 127 }).pixels).toEqual(pixels); + expect(atlas.diagnostics()).toEqual({ atlasReads: 2, memoryHits: 1, downloads: 0 }); + expect(() => atlas.tile({ source: "wrong", z: 0, x: 0, y: 0 })).toThrow(); + expect(() => atlas.tile({ source, z: 8, x: 0, y: 0 })).toThrow(); + expect(() => atlas.tile({ source, z: 1, x: 1, y: 1 })).toThrow("Missing installed"); + expect(() => atlas.tile({ source, z: 1, x: 0, y: 0 })).toThrow(); + const query = { space: "planar" as const, x: 150, y: 130 }; + const rows = atlas.search({ ...query, query: "kak vil" }); + expect(rows).toHaveLength(1); expect(rows[0]).toMatchObject({ name: "Kakariko Village", space: "planar", x: 151, y: 130 }); + expect(atlas.search({ ...query, query: "shrine" })).toHaveLength(5); + expect(atlas.search({ ...query, query: "\" * -" })).toEqual([]); + expect(() => atlas.search({ query: "Kakariko", lat: 0, lon: 0 })).toThrow(); + const save = { op: "atlas_saved_place_1", kind: "save" as const, place: rows[0] }; + const receipt = atlas.bookmarks.command(save); atlas.close(); atlas = new AtlasProvider(dir); + expect(atlas.bookmarks.command(save)).toBe(receipt); + expect(atlas.bookmarks.list(0).items[0]).toMatchObject({ space: "planar", x: 151, y: 130 }); + } finally { atlas.close(); rmSync(dir, { recursive: true, force: true }); } +}); diff --git a/test/bookmarks.test.ts b/test/bookmarks.test.ts index af80f10..5842039 100644 --- a/test/bookmarks.test.ts +++ b/test/bookmarks.test.ts @@ -3,8 +3,25 @@ import { mkdtempSync, rmSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; import { Bookmarks } from "../host/bookmarks.ts"; +import { Database } from "bun:sqlite"; import type { BookmarkCommand } from "../shared/types.ts"; const place = { id: "N1", name: "Coffee", detail: "Market Street", lat: 37.7, lon: -122.4, zoom: 16 }; +test("legacy geographic bookmarks migrate once and keep their operation receipts", () => { + const dir = mkdtempSync(join(tmpdir(), "pocket-map-migrate-")), path = join(dir, "places.sqlite"); + const legacy = new Database(path); + legacy.exec(`CREATE TABLE places (seq INTEGER PRIMARY KEY,id TEXT,name TEXT,detail TEXT,lat REAL,lon REAL,zoom INTEGER); + CREATE TABLE receipts (op TEXT PRIMARY KEY,body TEXT,result TEXT); + INSERT INTO places VALUES (1,'old','Old favorite','San Francisco',37.7,-122.4,14); + INSERT INTO receipts VALUES ('retained','{}','{}');`); + legacy.close(); + let db = new Bookmarks(path); + try { + expect(db.list(0).items).toEqual([{ id: "old", name: "Old favorite", detail: "San Francisco", lat: 37.7, lon: -122.4, zoom: 14 }]); + db.close(); db = new Bookmarks(path); expect(db.list(0).total).toBe(1); + const check = new Database(path, { readonly: true }); + expect(check.query("SELECT op FROM receipts").get()).toEqual({ op: "retained" }); check.close(); + } finally { db.close(); rmSync(dir, { recursive: true, force: true }); } +}); test("saved places survive reopening, paginate and retain idempotent mutation receipts", () => { const dir = mkdtempSync(join(tmpdir(), "pocket-map-saved-")); let db = new Bookmarks(join(dir, "places.sqlite")); try { From a654870564acbf4cc6d7184e9f8a205336bb1061 Mon Sep 17 00:00:00 2001 From: "Yifeng \"Evan\" Wang" <7312949+doodlewind@users.noreply.github.com> Date: Sun, 6 Sep 2026 17:25:58 -0700 Subject: [PATCH 05/13] feat(map): add predictive navigation and live map layers --- README.md | 34 +++++++++- app/annotations.ts | 32 ++++++++++ app/marker-enemy.svg | 1 + app/marker-landmark.svg | 1 + app/marker-seed.svg | 1 + app/marker-shrine.svg | 1 + app/marker-special.svg | 1 + app/marker-stable.svg | 1 + app/marker-tower.svg | 1 + app/marker-treasure.svg | 1 + app/marker-village.svg | 1 + app/model.ts | 115 +++++++++++++++++++++------------- app/prediction.ts | 37 +++++++++++ app/saved.ts | 10 +-- app/ui.tsx | 85 +++++++++++++++++++------ docs/ARCHITECTURE.md | 36 ++++++++++- docs/VALIDATION.md | 30 +++++++++ docs/images/hyrule-search.png | Bin 35277 -> 36104 bytes docs/images/hyrule.png | Bin 76994 -> 84648 bytes docs/images/sources.png | Bin 0 -> 35638 bytes docs/images/zoom-rail.png | Bin 0 -> 50617 bytes host/atlas-format.ts | 2 + host/atlas.ts | 16 +++-- host/markers.ts | 74 ++++++++++++++++++++++ host/service.ts | 40 ++++++++++++ host/worker.ts | 7 +-- package.json | 2 +- runtime | 2 +- scripts/prepare-hyrule.ts | 19 +++--- scripts/quickjs-smoke.js | 13 +++- scripts/sim.ts | 36 ++++++++++- shared/types.ts | 13 +++- test/navigation.test.ts | 98 +++++++++++++++++++++++++++++ 33 files changed, 611 insertions(+), 99 deletions(-) create mode 100644 app/annotations.ts create mode 100644 app/marker-enemy.svg create mode 100644 app/marker-landmark.svg create mode 100644 app/marker-seed.svg create mode 100644 app/marker-shrine.svg create mode 100644 app/marker-special.svg create mode 100644 app/marker-stable.svg create mode 100644 app/marker-tower.svg create mode 100644 app/marker-treasure.svg create mode 100644 app/marker-village.svg create mode 100644 app/prediction.ts create mode 100644 docs/images/sources.png create mode 100644 docs/images/zoom-rail.png create mode 100644 host/atlas-format.ts create mode 100644 host/markers.ts create mode 100644 host/service.ts create mode 100644 test/navigation.test.ts diff --git a/README.md b/README.md index 637ca0a..317880f 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,9 @@ queue; it is not a device-render receipt. | D-pad up/down + A | Choose and open a search result or menu item | | X / Back to pin | Return to the selected place | | Hold L | Search, saved places, save map center, return to pin, or map home | -| Hold R | Zoom, clear pin, retry tiles, or show controls | +| Hold R | Zoom, label categories, switch map, clear pin, retry, or controls | +| Hold ZL + D-pad up/down | Open the vertical zoom rail; tap or hold to change levels | +| Map name on the lower screen | Switch Hyrule / OSM without restarting | | Save view / Save place | Name and save the center or selected search result on the Mac | | Saved | Browse, rename, delete with confirmation, or return to a saved location | | Saved page: Prev / Next or D-pad left/right | Turn five-place pages | @@ -79,10 +81,38 @@ It is reused on the next invocation; `--rebuild` explicitly replaces it. The Hyrule provider has no HTTP fallback or request throttle. It reads the prepared textures and keeps 128 decoded renditions on the Mac. The device retains 40 tiles and requests up to 12 neighboring tiles with a 256px margin -and at most 384px of directional prediction. Visible tiles retain priority. +and at most 512px of directional prediction. Repeated strokes accumulate camera +travel: lifting the stylus retains the direction for three seconds, followed by +expiry. Once direction is established, the extra tiles follow a forward corridor +instead of filling a surrounding ring. A turn changes the prediction. + +After zooming in, a five-second prediction window prepares up to six tiles from +the next level around the center. These share the 12-extra-tile budget with pan +prediction and the same 40-entry cache. Visible tiles retain priority. The finite world clamps at its edges; Map home returns to the Great Plateau. Try searching `Kakariko`, `Hyrule Castle`, `Shrine` or `Great Plateau`. +## Switching maps and game labels + +Tap the **Map** name on the lower screen, or use **R → Switch map**. Choose with +touch or D-pad / A. Each map remembers its last camera position, zoom and pin +for this guest session. The daemon keeps both providers available; all tile, +search and bookmark requests carry the selected source identity. Switching +clears old view demand and fences late responses. A pending bookmark mutation +must finish or be resolved before switching databases. + +Hyrule's separate marker index contains 2,576 annotations. **R → Map labels** +selects all labels, places/shrines/towers, collectibles, enemies, or hides labels. +Regions appear at wide zooms; detailed items such as Koroks and treasures appear +from level 6. The Mac performs spatial queries and density selection. The guest +receives bounded point/name/category records and draws small baked icons plus +text locally, so labels move with the map without another network round trip. +OSM's place labels remain part of its base tile images. + +`prepare:hyrule` refreshes the separate marker index without rebaking existing +terrain textures. Marker assets and SQLite stay outside Git; the small UI icons +are drawn for this app. + ## Saved places Use **Save view** to store the map center, or **Save place** on a search result. diff --git a/app/annotations.ts b/app/annotations.ts new file mode 100644 index 0000000..df6363c --- /dev/null +++ b/app/annotations.ts @@ -0,0 +1,32 @@ +import { createMemo, createSignal } from "solid-js"; +import { createResourceView, type createResourceRuntime } from "@pocketjs/framework/resource-view"; +import { offloadResource } from "@pocketjs/framework/resource-offload"; +import { visibleTiles } from "@pocketjs/framework/tile-viewport"; +import type { offload } from "@pocketjs/framework/offload"; +import { MARKER_KINDS, type MapInfo, type MapMarker, type MarkerInput, type MarkerLayer } from "../shared/types.ts"; +export const LAYERS: { id: MarkerLayer; name: string }[] = [ + { id: "all", name: "All map labels" }, { id: "travel", name: "Places, shrines & towers" }, + { id: "collectibles", name: "Koroks & treasures" }, { id: "enemies", name: "Enemies" }, { id: "off", name: "Hide labels" }, +]; +export function createAnnotations(io: ReturnType, runtime: ReturnType) { + const [layer, setLayer] = createSignal("all"), [demand, setDemand] = createSignal([]); + const collection = runtime.createCollection({ key: (i: MarkerInput) => `${i.source}/${i.layer}/${i.z}/${i.x}/${i.y}`, maxEntries: 12, maxViews: 1, maxDemandsPerView: 4, + cost: () => 8192, maxCost: 12 * 8192, maxResponseBytes: 5000, load: offloadResource(io, "map.markers", JSON.stringify), + materialize(raw: string): MapMarker[] { + const rows = JSON.parse(raw); + if (!Array.isArray(rows) || rows.length > 12 || !rows.every(m => Array.isArray(m) && m.length === 5 && Number.isSafeInteger(m[0]) && typeof m[1] === "string" && m[1].length <= 24 && MARKER_KINDS.includes(m[2]) && Number.isFinite(m[3]) && Number.isFinite(m[4]) && m[3] >= 0 && m[3] < 256 && m[4] >= 0 && m[4] < 256)) throw new Error("Invalid map annotations"); + return rows; + } }); + const view = createResourceView(collection, { demand: () => demand().map(input => ({ input, priority: 25, pin: true })) }); + const rows = createMemo(() => demand().flatMap(i => view.value(i) ?? [])); + return { layer, setLayer, rows, + reset() { setDemand([]); collection.clear(); }, + update(camera: { x: number; y: number; zoom: number }, level: number, info: MapInfo) { + const cells = Math.max(1, 2 ** (level - 1)); + const next: MarkerInput[] = info.markers && layer() !== "off" ? visibleTiles({ ...camera, zoom: level, level, width: 400, height: 240, tileSize: 512, maxTiles: 4 }) + .filter(t => t.column >= 0 && t.row >= 0 && t.column < cells && t.row < cells) + .map(t => ({ source: info.source, z: level, x: t.column, y: t.row, layer: layer() })) : []; + const old = demand(); if (next.length !== old.length || next.some((v, n) => JSON.stringify(v) !== JSON.stringify(old[n]))) setDemand(next); + }, + }; +} diff --git a/app/marker-enemy.svg b/app/marker-enemy.svg new file mode 100644 index 0000000..3bdee3c --- /dev/null +++ b/app/marker-enemy.svg @@ -0,0 +1 @@ + diff --git a/app/marker-landmark.svg b/app/marker-landmark.svg new file mode 100644 index 0000000..be92995 --- /dev/null +++ b/app/marker-landmark.svg @@ -0,0 +1 @@ + diff --git a/app/marker-seed.svg b/app/marker-seed.svg new file mode 100644 index 0000000..6f13562 --- /dev/null +++ b/app/marker-seed.svg @@ -0,0 +1 @@ + diff --git a/app/marker-shrine.svg b/app/marker-shrine.svg new file mode 100644 index 0000000..e244c34 --- /dev/null +++ b/app/marker-shrine.svg @@ -0,0 +1 @@ + diff --git a/app/marker-special.svg b/app/marker-special.svg new file mode 100644 index 0000000..40d51c5 --- /dev/null +++ b/app/marker-special.svg @@ -0,0 +1 @@ + diff --git a/app/marker-stable.svg b/app/marker-stable.svg new file mode 100644 index 0000000..13ce024 --- /dev/null +++ b/app/marker-stable.svg @@ -0,0 +1 @@ + diff --git a/app/marker-tower.svg b/app/marker-tower.svg new file mode 100644 index 0000000..7d422ad --- /dev/null +++ b/app/marker-tower.svg @@ -0,0 +1 @@ + diff --git a/app/marker-treasure.svg b/app/marker-treasure.svg new file mode 100644 index 0000000..c3cc111 --- /dev/null +++ b/app/marker-treasure.svg @@ -0,0 +1 @@ + diff --git a/app/marker-village.svg b/app/marker-village.svg new file mode 100644 index 0000000..2838bdb --- /dev/null +++ b/app/marker-village.svg @@ -0,0 +1 @@ + diff --git a/app/model.ts b/app/model.ts index 52ba6d2..16dde06 100644 --- a/app/model.ts +++ b/app/model.ts @@ -1,20 +1,23 @@ import { createSignal, createMemo } from "solid-js"; import { createResourceRuntime, createResourceView } from "@pocketjs/framework/resource-view"; import { createOffloadImageCollection, offloadResource } from "@pocketjs/framework/resource-offload"; -import { createTileCamera, planTileWindow } from "@pocketjs/framework/tile-viewport"; +import { createTileCamera } from "@pocketjs/framework/tile-viewport"; import { offload } from "@pocketjs/framework/offload"; import { analogX, analogY, onFrame, onButtonPress } from "@pocketjs/framework/lifecycle"; import { BTN } from "@pocketjs/framework/input"; import { simulationHz, virtualNow } from "@pocketjs/framework/clock"; -import { project, worldPosition, positionAt, wrapTile } from "./geo.ts"; +import { project, worldPosition, positionAt } from "./geo.ts"; import { createSavedPlaces, validPlaces, type MapMode } from "./saved.ts"; -import { HOME, type TileInput, type MapInfo, type SearchInput, type Place } from "../shared/types.ts"; +import { HOME, type TileInput, type MapInfo, type SearchInput, type Place, type MapKind } from "../shared/types.ts"; + +import { createMapPrediction } from "./prediction.ts"; +import { createAnnotations, LAYERS } from "./annotations.ts"; export interface DrawTile { input: TileInput; column: number; row: number; priority: number } export interface Layer { level: number; tiles: DrawTile[]; originX: number; originY: number } export const MENU = { places: ["Search places", "Saved places", "Save map center", "Back to pin", "Map home"], - map: ["Zoom in", "Zoom out", "Clear pin", "Retry tiles", "About & controls"], + map: ["Zoom in", "Zoom out", "Map labels", "Switch map", "Clear pin", "Retry tiles", "About & controls"], }; export function createMap(io = offload()) { const [info, setInfo] = createSignal(); @@ -25,16 +28,20 @@ export function createMap(io = offload()) { const [menu, setMenu] = createSignal<"places" | "map">(), [menuIndex, setMenuIndex] = createSignal(0); const [shift, setShift] = createSignal<"off" | "once" | "locked">("off"), [symbols, setSymbols] = createSignal(false); const [front, setFront] = createSignal(), [back, setBack] = createSignal(); + const [zoomHeld, setZoomHeld] = createSignal(false), [switching, setSwitching] = createSignal(false); + const [sourceError, setSourceError] = createSignal(""); + const [requestedKind, setRequestedKind] = createSignal(); + const remembered = new Map(); const planar = () => info()?.space === "planar"; const p = project(HOME.lat, HOME.lon); const camera = createTileCamera({ width: 400, height: 240, x: p.x, y: p.y, zoom: HOME.zoom, minZoom: 1, maxZoom: 18, bounds: { width: 256, height: 256, wrapX: true } }); - const runtime = createResourceRuntime({ maxConcurrent: 3, startsPerFrame: 1, completionsPerFrame: 1, maxCollections: 4, available: () => io.connected() && !!info() && io.pending() < 3 }); + const runtime = createResourceRuntime({ maxConcurrent: 3, startsPerFrame: 1, completionsPerFrame: 1, maxCollections: 5, available: () => !switching() && io.connected() && !!info() && io.pending() < 3 }); const tiles = createOffloadImageCollection(runtime, io, { key: (i: TileInput) => `${i.source}/${i.z}/${i.x}/${i.y}`, method: "map.tile", payload: JSON.stringify, width: 256, height: 256, maxEntries: 40, maxViews: 2, maxDemandsPerView: 24, retry: { attempts: 3, delayFrames: 90, maxDelayFrames: 360 } }); const labels = createOffloadImageCollection(runtime, io, { key: (i: Place) => `${i.name}/${i.detail}`, method: "map.label", payload: i => JSON.stringify({ name: i.name, detail: i.detail }), width: 256, height: 32, maxEntries: 5, maxViews: 5, maxDemandsPerView: 1 }); const [lookAhead, setLookAhead] = createSignal([]); - const frontView = createResourceView(tiles, { demand: () => [...(front()?.tiles.map(t => ({ input: t.input, priority: t.priority, pin: true })) ?? []), ...lookAhead().map(t => ({ input: t.input, priority: 1000 + t.priority, pin: false }))] }); + const frontView = createResourceView(tiles, { demand: () => [...(front()?.tiles.map(t => ({ input: t.input, priority: t.priority, pin: true })) ?? []), ...lookAhead().map(t => ({ input: t.input, priority: t.priority, pin: false }))] }); const backView = createResourceView(tiles, { demand: () => back()?.tiles.map(t => ({ input: t.input, priority: 100, pin: true })) ?? [] }); const searches = runtime.createCollection({ key: (i: SearchInput) => JSON.stringify(i), maxEntries: 4, maxViews: 1, maxDemandsPerView: 1, maxCost: 4 * 8192, cost: () => 8192, maxResponseBytes: 5000, retry: { attempts: 1, delayFrames: 60, maxDelayFrames: 60 }, @@ -46,33 +53,51 @@ export function createMap(io = offload()) { }); const results = createResourceView(searches, { demand: () => submitted() ? [{ input: submitted()!, priority: -10, pin: true }] : [] }); const places = createMemo(() => submitted() ? results.value(submitted()!) ?? [] : []); - const saved = createSavedPlaces(io, runtime, mode, setMode); + const saved = createSavedPlaces(io, runtime, mode, setMode, () => info()?.source); + const annotations = createAnnotations(io, runtime), prediction = createMapPrediction(); const typing = () => mode() === "search" || mode() === "name"; const listing = () => mode() === "results" || mode() === "saved"; const rows = () => mode() === "saved" ? saved.page()?.items ?? [] : places(); const selectedIndex = () => mode() === "saved" ? saved.selection() : selection(); function select(index: number) { const n = Math.max(0, Math.min(rows().length - 1, index)); if (mode() === "saved") saved.setSelection(n); else setSelection(n); } - let previousView = camera.view(); + prediction.reset(camera.view()); + const maps = () => info()?.maps ?? []; + const choices = () => mode() === "sources" ? maps().map(m => m.name) : LAYERS.map(l => l.name); + const choosing = () => mode() === "sources" || mode() === "layers"; + function openSources() { if (saved.busy() || saved.modal() || typing() || switching()) return; camera.stop(); setSourceError(""); setMode("sources"); setSelection(Math.max(0, maps().findIndex(m => m.kind === info()?.kind))); setMenu(undefined); } + function choose(index = selection()) { + if (mode() === "sources") { const kind = maps()[index]?.kind; if (kind) switchMap(kind); } + else if (mode() === "layers") { annotations.setLayer(LAYERS[index].id); dismiss(); } + } + function switchMap(kind: MapKind) { + if (saved.busy() || saved.modal() || typing() || switching()) return; + if (kind === info()?.kind) { dismiss(); return; } + const old = info(); if (old?.kind) remembered.set(old.kind, { ...camera.view(), pin: pin() }); + camera.stop(); if (infoRequest) io.cancel(infoRequest); infoRequest = 0; + setSourceError(""); setRequestedKind(kind); setSwitching(true); retryAt = 0; setMode("map"); setStatus(`Opening ${kind === "hyrule" ? "Hyrule" : "OpenStreetMap"}...`); + } let frame = 0, previousSession = 0, infoRequest = 0, retryAt = 0, shiftAt = -10, levelAge = 0, candidateLevel = HOME.zoom; let confirmed = false; function search() { const text = query().trim(); if (!text) return; const v = camera.view(), pos = positionAt(v.x, v.y, planar()); - const next: SearchInput = { query: text, ...(pos.space === "planar" ? pos : { lat: Math.round(pos.lat * 10) / 10, lon: Math.round(pos.lon * 10) / 10 }) }; + const next: SearchInput = { query: text, source: info()?.source, ...(pos.space === "planar" ? pos : { lat: Math.round(pos.lat * 10) / 10, lon: Math.round(pos.lon * 10) / 10 }) }; searches.invalidate(i => JSON.stringify(i) === JSON.stringify(next)); setSubmitted(next); setSelection(0); setMode("results"); camera.stop(); } - function openSearch() { if (saved.busy() || saved.modal() || mode() === "name") return; camera.stop(); setMode("search"); setMenu(undefined); } + function openSearch() { if (saved.busy() || saved.modal() || mode() === "name" || switching() || zoomHeld()) return; camera.stop(); setMode("search"); setMenu(undefined); } function go(place = rows()[selectedIndex()]) { if (!place) return; if ((place.space === "planar") !== planar()) return; const pos = worldPosition(place); camera.jump(pos.x, pos.y, Math.min(info()?.maxZoom ?? 18, place.zoom)); + prediction.reset(camera.view()); setPin(place); setMode("map"); setMenu(undefined); } function home(name: string, lat: number, lon: number) { go({ id: name, name, detail: "", lat, lon, zoom: 14 }); } function zoom(delta: number) { if (delta > 0 && camera.view().zoom >= (info()?.maxZoom ?? 18)) return; - camera.zoomBy(delta); + if (switching()) return; + prediction.zoom(delta); camera.zoomBy(delta); } function key(value: string) { if (!typing() || saved.busy()) return; @@ -100,21 +125,22 @@ export function createMap(io = offload()) { if (bank === "places") { if (i === 0) openSearch(); else if (i === 1) saved.open(); else if (i === 2) saveCurrent(); else if (i === 3) go(pin()); else if (info()?.home) go(info()!.home); else home("San Francisco", HOME.lat, HOME.lon); } else if (bank === "map") { - if (i < 2) zoom(i === 0 ? 1 : -1); else if (i === 2) setPin(undefined); else if (i === 3) tiles.invalidate(); else setMode("about"); + if (i < 2) zoom(i === 0 ? 1 : -1); else if (i === 2) { setMode("layers"); setSelection(LAYERS.findIndex(l => l.id === annotations.layer())); } else if (i === 3) openSources(); else if (i === 4) setPin(undefined); else if (i === 5) tiles.invalidate(); else setMode("about"); } } - onButtonPress(BTN.CIRCLE, () => { if (saved.modal() || saved.busy()) return; if (menu()) runMenu(); else if (typing()) key("GO"); else if (listing()) go(); }); + onButtonPress(BTN.CIRCLE, (_pressed, buttons) => { if (buttons & BTN.ZL || saved.modal() || saved.busy() || switching() || zoomHeld()) return; if (choosing()) choose(); else if (menu()) runMenu(); else if (typing()) key("GO"); else if (listing()) go(); }); onButtonPress(BTN.CROSS, () => { if (saved.modal()) { saved.cancelDelete(); return; } if (saved.busy()) return; if (menu()) { confirmed = true; setMenu(undefined); } else if (typing()) key("DEL"); else dismiss(); }); - onButtonPress(BTN.TRIANGLE, openSearch); - onButtonPress(BTN.SQUARE, () => { if (mode() === "map") go(pin()); }); - for (const [button, delta] of [[BTN.UP, -1], [BTN.DOWN, 1]] as const) onButtonPress(button, () => { - if (saved.modal() || saved.busy()) return; - if (menu()) setMenuIndex(i => Math.max(0, Math.min(4, i + delta))); + onButtonPress(BTN.TRIANGLE, (_pressed, buttons) => { if (!(buttons & BTN.ZL)) openSearch(); }); + onButtonPress(BTN.SQUARE, (_pressed, buttons) => { if (!(buttons & BTN.ZL) && !switching() && mode() === "map") go(pin()); }); + for (const [button, delta] of [[BTN.UP, -1], [BTN.DOWN, 1]] as const) onButtonPress(button, (_pressed, buttons) => { + if (saved.modal() || saved.busy() || switching() || buttons & BTN.ZL) return; + if (menu()) setMenuIndex(i => Math.max(0, Math.min(MENU[menu()!].length - 1, i + delta))); + else if (choosing()) setSelection(i => Math.max(0, Math.min(choices().length - 1, i + delta))); else if (listing()) select(selectedIndex() + delta); }); onButtonPress(BTN.LEFT, () => { if (mode() === "saved" && !menu() && !saved.modal()) saved.turnPage(-1); }); onButtonPress(BTN.RIGHT, () => { if (mode() === "saved" && !menu() && !saved.modal()) saved.turnPage(1); }); - let previousButtons = 0; + let previousButtons = 0, zoomRepeat = 0, zoomDirection = 0; onFrame(buttons => { frame++; const session = io.session(); setOnline(session > 0); if (session !== previousSession) { @@ -125,37 +151,50 @@ export function createMap(io = offload()) { previousSession = session; } if (session > 0 && !infoRequest && frame >= retryAt) { - infoRequest = io.request("map.info", "{}", result => { + infoRequest = io.request("map.info", JSON.stringify({ kind: requestedKind() }), result => { infoRequest = 0; retryAt = frame + 3600; - if (!result.ok) { setStatus(result.error); retryAt = frame + 120; return; } + if (!result.ok) { if (switching()) { setSourceError("Map unavailable. Choose again to retry."); setMode("sources"); } setStatus(result.error); setSwitching(false); setRequestedKind(info()?.kind); retryAt = frame + 120; return; } try { const value: MapInfo = JSON.parse(result.value); if (typeof value.source !== "string" || !/^[a-f0-9]{16}$/.test(value.source) || typeof value.name !== "string" || typeof value.attribution !== "string" || !Number.isInteger(value.maxZoom) || value.maxZoom < 1 || value.maxZoom > 18 || !Number.isInteger(value.minZoom ?? 1) || (value.minZoom ?? 1) < 0 || (value.minZoom ?? 1) > value.maxZoom || value.space !== undefined && value.space !== "mercator" && value.space !== "planar" || value.home !== undefined && (!validPlaces([value.home]) || (value.home.space === "planar") !== (value.space === "planar"))) throw new Error("Invalid map provider"); + if (value.maps !== undefined && (!Array.isArray(value.maps) || value.maps.length > 2 || !value.maps.every(m => (m.kind === "hyrule" || m.kind === "osm") && typeof m.name === "string" && m.name.length <= 40))) throw new Error("Invalid map catalog"); if (info()?.source !== value.source) { + runtime.cancel(); searches.clear(); labels.clear(); annotations.reset(); saved.reset(); setSubmitted(undefined); setQuery(""); tiles.clear(); setFront(undefined); setBack(undefined); setLookAhead([]); setPin(undefined); camera.setWorld({ minZoom: value.minZoom ?? 1, maxZoom: value.maxZoom, bounds: { width: 256, height: 256, wrapX: value.space !== "planar" } }); - if (value.home) { const home = worldPosition(value.home); camera.jump(home.x, home.y, value.home.zoom); } + const resume = value.kind && remembered.get(value.kind); + if (resume) { camera.jump(resume.x, resume.y, resume.zoom); setPin(resume.pin); } + else if (value.home) { const home = worldPosition(value.home); camera.jump(home.x, home.y, value.home.zoom); } + if (!resume && !value.home) { const p = project(HOME.lat, HOME.lon); camera.jump(p.x, p.y, HOME.zoom); } + prediction.reset(camera.view()); candidateLevel = Math.round(camera.view().zoom); levelAge = 0; } - setInfo(value); setStatus("Map ready"); - } catch { setStatus("Unsupported map provider"); retryAt = frame + 120; } + setInfo(value); setRequestedKind(value.kind); setSwitching(false); setStatus("Map ready"); + } catch { setSwitching(false); setRequestedKind(info()?.kind); setStatus("Unsupported map provider"); retryAt = frame + 120; } }); } + const zl = !!(buttons & BTN.ZL) && mode() === "map" && !saved.modal() && !saved.busy() && !switching(); + setZoomHeld(zl); + const zd = zl ? (buttons & BTN.UP ? 1 : 0) - (buttons & BTN.DOWN ? 1 : 0) : 0; + if (zl && !(previousButtons & BTN.ZL)) { camera.endDrag(0, 0); setMenu(undefined); } + if (zd && (zd !== zoomDirection || frame >= zoomRepeat)) { zoom(zd); zoomRepeat = frame + Math.round(simulationHz() * (zd === zoomDirection ? .28 : .4)); } + zoomDirection = zd; const shoulders = buttons & (BTN.LTRIGGER | BTN.RTRIGGER); if (!shoulders) { confirmed = false; if (menu()) setMenu(undefined); } - else if (!saved.modal() && !saved.busy() && mode() !== "name" && !confirmed && !menu() && shoulders !== (previousButtons & (BTN.LTRIGGER | BTN.RTRIGGER))) { + else if (!zl && !switching() && !saved.modal() && !saved.busy() && mode() !== "name" && !confirmed && !menu() && shoulders !== (previousButtons & (BTN.LTRIGGER | BTN.RTRIGGER))) { setMenu(shoulders & BTN.LTRIGGER ? "places" : "map"); setMenuIndex(0); camera.stop(); } - const canPan = mode() === "map" && !shoulders && !saved.modal(); + const canPan = mode() === "map" && !shoulders && !zl && !switching() && !saved.modal(); const axisX = canPan ? analogX() : 0, axisY = canPan ? analogY() : 0; const dx = canPan ? (buttons & BTN.LEFT ? 1 : 0) - (buttons & BTN.RIGHT ? 1 : 0) : 0; const dy = canPan ? (buttons & BTN.UP ? 1 : 0) - (buttons & BTN.DOWN ? 1 : 0) : 0; camera.step(1 / simulationHz(), dx ? dx * 180 : -axisX * 320, dy ? dy * 180 : -axisY * 320); previousButtons = buttons; if (!info()) return; - const view = camera.view(), next = Math.min(info()!.maxZoom, Math.max(info()!.minZoom ?? 1, Math.round(view.zoom))); + const view = camera.view(); prediction.sample(view, 1 / simulationHz(), !planar()); + const next = Math.min(info()!.maxZoom, Math.max(info()!.minZoom ?? 1, Math.round(view.zoom))); levelAge = next === candidateLevel ? levelAge + 1 : 0; candidateLevel = next; let level = front()?.level ?? next; if (next !== level && (levelAge >= 8 || Math.abs(next - level) > 1)) { @@ -163,21 +202,11 @@ export function createMap(io = offload()) { setBack(previous ? { ...previous, tiles: previous.tiles.filter(t => frontView.state(t.input).status === "ready") } : undefined); level = next; } - let leadX = view.x - previousView.x; if (!planar()) leadX -= Math.round(leadX / 256) * 256; - const leadY = view.y - previousView.y; - const moving = view.moving && Math.hypot(leadX, leadY) * view.scale < 24 && Math.abs(view.zoom - level) < 0.02; - // Start nearby work earlier without expanding the four-tile source budget. - // At 320px/s, a 64px margin did not even cover a cached 128 KiB LAN transfer. - const local = info()!.local === true, leadLimit = local ? 384 : 128; - const planOptions = { ...view, level, width: 400, height: 240, maxTiles: 12, margin: local ? 256 : 128, - leadX: moving ? Math.max(-leadLimit, Math.min(leadLimit, leadX * view.scale * (local ? 48 : 36))) : 0, - leadY: moving ? Math.max(-leadLimit, Math.min(leadLimit, leadY * view.scale * (local ? 48 : 36))) : 0, maxExtra: Math.abs(view.zoom - level) < 0.02 ? local ? 12 : 4 : 0 }; - let window; - try { window = planTileWindow(planOptions); } - catch { level = next; window = planTileWindow({ ...planOptions, level, maxExtra: 0 }); } - previousView = view; - const address = (list: typeof window.visible) => list.filter(t => t.row >= 0 && t.row < 2 ** level && (!planar() || t.column >= 0 && t.column < 2 ** level)).map(t => ({ ...t, input: { source: info()!.source, z: level, x: wrapTile(t.column, level), y: t.row } })); - const draw = address(window.visible), ahead = address(window.lookAhead); + let plan; + try { plan = prediction.plan(view, level, info()!); } + catch { level = next; plan = prediction.plan(view, level, info()!); } + const draw = plan.visible, ahead = plan.extra; + annotations.update(view, next, info()!); if (ahead.length !== lookAhead().length || ahead.some((t, i) => { const o = lookAhead()[i]; return !o || t.input.z !== o.input.z || t.input.x !== o.input.x || t.input.y !== o.input.y; })) setLookAhead(ahead); const previous = front(); if (!previous || previous.level !== level || previous.tiles.length !== draw.length || draw.some(t => !previous.tiles.some(o => o.column === t.column && o.row === t.row))) { @@ -189,7 +218,7 @@ export function createMap(io = offload()) { } if (back() && front()?.tiles.every(t => frontView.state(t.input).status === "ready")) setBack(undefined); }); - return { io, runtime, tiles, labels, frontView, backView, info, planar, online, status, mode, setMode, query, setQuery, submitted, results, places, selection, setSelection, pin, menu, menuIndex, + return { io, runtime, tiles, labels, frontView, backView, info, planar, online, zoomHeld, switching, sourceError, maps, choices, choosing, choose, openSources, switchMap, annotations, status, mode, setMode, query, setQuery, submitted, results, places, selection, setSelection, pin, menu, menuIndex, shift, symbols, front, back, camera, saved, typing, listing, rows, selectedIndex, select, saveCurrent, lookAhead, search, openSearch, go, zoom, key, dismiss, runMenu, clearBack: () => setBack(undefined), diagnostics: () => ({ frame, pending: io.pending(), resources: runtime.stats(), tiles: tiles.stats(), camera: camera.view() }), diff --git a/app/prediction.ts b/app/prediction.ts new file mode 100644 index 0000000..367c5ef --- /dev/null +++ b/app/prediction.ts @@ -0,0 +1,37 @@ +import { createTileIntent, planTileWindow, visibleTiles, type createTileCamera } from "@pocketjs/framework/tile-viewport"; +import type { MapInfo, TileInput } from "../shared/types.ts"; +import { wrapTile } from "./geo.ts"; +type View = ReturnType["view"]>; +export interface PlannedTile { input: TileInput; column: number; row: number; priority: number } +export function createMapPrediction() { + const intent = createTileIntent(); let previous: View | undefined, now = 0, zoomUntil = 0; + function reset(view: View) { intent.reset(); previous = view; zoomUntil = 0; } + return { + reset, + zoom(delta: number) { zoomUntil = delta > 0 ? now + 5 : 0; }, + sample(view: View, seconds: number, wraps: boolean) { + if (previous) { + let dx = view.x - previous.x; if (wraps) dx -= Math.round(dx / 256) * 256; + intent.sample(dx * view.scale, (view.y - previous.y) * view.scale, seconds); + } + previous = view; now += seconds; + }, + plan(view: View, level: number, info: MapInfo) { + const local = info.local === true, lead = intent.predict(local ? 512 : 128), directional = lead.confidence > .45; + const options = { ...view, level, width: 400, height: 240, maxTiles: 12, margin: local ? 256 : 128, + leadX: lead.x, leadY: lead.y, directional, maxExtra: local ? 12 : 4 }; + const window = planTileWindow(options); + const address = (list: typeof window.visible, z: number): PlannedTile[] => list + .filter(t => t.row >= 0 && t.row < 2 ** z && (info.space !== "planar" || t.column >= 0 && t.column < 2 ** z)) + .map(t => ({ ...t, input: { source: info.source, z, x: wrapTile(t.column, z), y: t.row } })); + const next = Math.round(view.targetZoom) + 1; + // Only the complete local atlas predicts another zoom level. Public OSM + // retains modest same-level look-ahead rather than multi-level pre-seeding. + const zoomTiles = local && now < zoomUntil && next > level && next <= info.maxZoom + ? address(visibleTiles({ ...options, zoom: next, level: next }), next).slice(0, 6) : []; + const extra = [...zoomTiles.map(t => ({ ...t, priority: 300 + t.priority })), + ...address(window.lookAhead, level).map(t => ({ ...t, priority: 1000 + t.priority }))].slice(0, local ? 12 : 4); + return { visible: address(window.visible, level), extra, intent: lead }; + }, + }; +} diff --git a/app/saved.ts b/app/saved.ts index 2927959..e0c1882 100644 --- a/app/saved.ts +++ b/app/saved.ts @@ -5,19 +5,19 @@ import type { offload } from "@pocketjs/framework/offload"; import type { Place, BookmarkPage, BookmarkCommand } from "../shared/types.ts"; import { validPosition } from "../shared/types.ts"; -export type MapMode = "map" | "search" | "results" | "about" | "saved" | "name"; +export type MapMode = "map" | "search" | "results" | "about" | "saved" | "name" | "sources" | "layers"; export function validPlaces(rows: unknown): rows is Place[] { return Array.isArray(rows) && rows.length <= 5 && rows.every(p => p && typeof p.id === "string" && p.id.length <= 80 && typeof p.name === "string" && p.name.length <= 36 && typeof p.detail === "string" && p.detail.length <= 60 && Number.isInteger(p.zoom) && p.zoom >= 0 && p.zoom <= 18 && validPosition(p)); } -export function createSavedPlaces(io: ReturnType, runtime: ReturnType, mode: () => MapMode, setMode: (mode: MapMode) => void) { +export function createSavedPlaces(io: ReturnType, runtime: ReturnType, mode: () => MapMode, setMode: (mode: MapMode) => void, source: () => string | undefined = () => undefined) { const [offset, setOffset] = createSignal(0), [selection, setSelection] = createSignal(0); const [name, setName] = createSignal(""), [editing, setEditing] = createSignal(); const [busy, setBusy] = createSignal(false), [error, setError] = createSignal(""); const [deleting, setDeleting] = createSignal(), [modal, setModal] = createSignal(false); let target: Place | undefined, returnMode: MapMode = "map", request = 0, last: BookmarkCommand | undefined; - const collection = runtime.createCollection({ key: (offset: number) => String(offset), maxEntries: 4, maxViews: 1, maxDemandsPerView: 1, + const collection = runtime.createCollection({ key: (offset: number) => `${source()}/${offset}`, maxEntries: 4, maxViews: 1, maxDemandsPerView: 1, maxCost: 4 * 8192, cost: () => 8192, maxResponseBytes: 5000, retry: { attempts: 2, delayFrames: 60, maxDelayFrames: 120 }, - load: offloadResource(io, "bookmarks.list", offset => JSON.stringify({ offset })), materialize(raw: string): BookmarkPage { + load: offloadResource(io, "bookmarks.list", offset => JSON.stringify({ offset, source: source() })), materialize(raw: string): BookmarkPage { const page = JSON.parse(raw); if (!page || !validPlaces(page.items) || !Number.isSafeInteger(page.offset) || page.offset < 0 || page.offset > 995 || page.offset % 5 || !Number.isSafeInteger(page.total) || page.total < 0 || page.total > 1000 || page.items.length !== Math.min(5, Math.max(0, page.total - page.offset))) throw new Error("Invalid saved places response"); return page; @@ -33,6 +33,7 @@ export function createSavedPlaces(io: ReturnType, runtime: Retur function changeName(value: string) { if (busy()) return; setName(value.slice(0, 36)); last = undefined; setError(""); } function perform(command: BookmarkCommand) { if (busy()) return; + command = { ...command, source: command.source ?? source() }; last = command; setBusy(true); setError(""); request = io.request("bookmarks.command", JSON.stringify(command), result => { request = 0; setBusy(false); @@ -65,6 +66,7 @@ export function createSavedPlaces(io: ReturnType, runtime: Retur onCleanup(() => { if (request) io.cancel(request); }); return { page, selected, selection, setSelection, name, changeName, editing, busy, error, deleting, modal, setModal, open, begin, submit, askRemove, remove, cancelDelete, cancelName, turnPage, refresh: () => collection.invalidate(), + reset() { if (request) io.cancel(request); request = 0; target = last = undefined; collection.clear(); setOffset(0); setSelection(0); setError(""); setBusy(false); setDeleting(undefined); }, state: () => view.state(offset()), }; } diff --git a/app/ui.tsx b/app/ui.tsx index 02e037c..9feb241 100644 --- a/app/ui.tsx +++ b/app/ui.tsx @@ -9,7 +9,8 @@ import { onFrame } from "@pocketjs/framework/lifecycle"; import * as hot from "@pocketjs/framework/hot"; import { createMap, MENU, type MapModel, type Layer } from "./model.ts"; import { worldPosition, unproject, scaleBar } from "./geo.ts"; -import type { Place } from "../shared/types.ts"; +import type { Place, MapMarker } from "../shared/types.ts"; +const MARKER_ICONS = { landmark: "marker-landmark.svg", tower: "marker-tower.svg", shrine: "marker-shrine.svg", stable: "marker-stable.svg", village: "marker-village.svg", seed: "marker-seed.svg", treasure: "marker-treasure.svg", enemy: "marker-enemy.svg", special: "marker-special.svg" }; const box = (x: number, y: number, w: number, h: number) => ({ posType: 1, insetL: x, insetT: y, width: w, height: h }); function TileLayer(p: { s: MapModel; back?: boolean }) { @@ -35,6 +36,44 @@ function TileLayer(p: { s: MapModel; back?: boolean }) {
} errorFallback={() => Tile unavailable} />}
; } +function Annotation(p: { s: MapModel; marker: MapMarker }) { + let root: NodeMirror | undefined; + onFrame(() => { + const v = p.s.camera.view(), x = 200 + (p.marker[3] - v.x) * v.scale, y = 120 + (p.marker[4] - v.y) * v.scale; + hot.prop(root, "translateX", x - 7); hot.prop(root, "translateY", y - 7); + hot.prop(root, "display", x < -100 || x > 410 || y < 18 || y > 235 ? 1 : 0); + }); + return + + + {p.marker[1].length > 16 ? p.marker[1].slice(0, 13) + "..." : p.marker[1]} + ; +} +function ZoomRail(p: { s: MapModel }) { + let thumb: NodeMirror | undefined, label: NodeMirror | undefined; + onFrame(() => { + const v = p.s.camera.view(), min = p.s.info()?.minZoom ?? 1, max = p.s.info()?.maxZoom ?? 18; + hot.prop(thumb, "translateY", 124 * (1 - (v.targetZoom - min) / Math.max(1, max - min))); + hot.text(label, `${Math.round(v.targetZoom)}`); + }); + return + Zoom + {p.s.info()?.maxZoom ?? 18} + + 4 + {p.s.info()?.minZoom ?? 1} + ZL + D-pad + ; +} +function ChoicePanel(p: { s: MapModel }) { + return + {p.s.mode() === "sources" ? "Choose a map" : "Map labels"} + {(name, i) => + {name} + } + {p.s.sourceError() || "D-pad: choose A: apply B: return"} + ; +} function PlaceRow(p: { s: MapModel; place: Place; index: number }) { const unicode = /[^\x20-\x7e]/.test(p.place.name + p.place.detail); const image = createResourceView(p.s.labels, { demand: () => unicode && p.s.listing() ? [{ input: p.place, priority: -5, pin: true }] : [] }); @@ -57,12 +96,12 @@ function SearchResults(p: { s: MapModel }) { } function Context(p: { s: MapModel }) { return {bank => - + {bank() === "places" ? "Places" : "Map controls"} - {(name, i) => + {(name, i) => {name} } - D-pad: choose A: open B: cancel + D-pad: choose A: open B: cancel }; } @@ -92,23 +131,23 @@ function Deck(p: { s: MapModel }) { const filter = createDragFilter(); const [touching, setTouching] = createSignal(false); const typing = p.s.typing, results = p.s.listing, saved = () => p.s.mode() === "saved", naming = () => p.s.mode() === "name"; - const blocked = () => !!p.s.menu() || p.s.saved.modal() || p.s.saved.busy(); + const blocked = () => !!p.s.menu() || p.s.saved.modal() || p.s.saved.busy() || p.s.switching() || p.s.zoomHeld(); const top = () => typing() ? 136 : 40, height = () => 194 - top(); createGesture({ surface: "auxiliary", region: { node: () => pad }, panSlop: 2, - onDown() { if (blocked() || naming()) return; setTouching(true); dy = 0; filter.reset(); p.s.camera.beginDrag(); }, + onDown() { if (blocked() || naming() || p.s.choosing()) return; setTouching(true); dy = 0; filter.reset(); p.s.camera.beginDrag(); }, onPanMove(c) { - if (blocked() || naming()) return; + if (blocked() || naming() || p.s.choosing()) return; if (results()) { dy += c.fdy; const step = Math.trunc(dy / 20); if (step) { p.s.select(p.s.selectedIndex() + step); dy -= step * 20; } } else { const delta = filter.update(c.dx, c.dy, 1 / simulationHz()); p.s.camera.drag(delta.dx * 1.45, delta.dy * 1.45); } }, - onPanEnd() { setTouching(false); if (blocked() || naming()) return; const v = filter.velocity(); p.s.camera.endDrag(results() ? 0 : v.x * 1.45, results() ? 0 : v.y * 1.45); }, - onTap() { setTouching(false); if (blocked() || naming()) return; p.s.camera.endDrag(0, 0); if (results()) p.s.go(); }, + onPanEnd() { setTouching(false); if (blocked() || naming() || p.s.choosing()) return; const v = filter.velocity(); p.s.camera.endDrag(results() ? 0 : v.x * 1.45, results() ? 0 : v.y * 1.45); }, + onTap() { setTouching(false); if (blocked() || naming() || p.s.choosing()) return; p.s.camera.endDrag(0, 0); if (results()) p.s.go(); }, onCancel() { setTouching(false); p.s.camera.stop(); }, }); // Build fixed controls outside the outer wrapper's mount stack on QuickJS. const keyboard = ; - const search = typing() || saved() || p.s.mode() === "about" ? p.s.dismiss() : p.s.openSearch()} />; - const padView = + const search = typing() || saved() || p.s.mode() === "about" || p.s.choosing() ? p.s.dismiss() : p.s.openSearch()} />; + const padView = {naming() ? p.s.saved.editing() ? "Rename saved place" : "Save place to your Mac" : results() ? "Choose a place" : touching() ? "Moving map" : "Map touchpad"} @@ -117,19 +156,24 @@ function Deck(p: { s: MapModel }) { {naming() ? p.s.saved.busy() ? "Saving on your Mac..." : p.s.saved.error() || "Name this location, then tap Save" : "Drag here to move the map"} ; - const plus = saved() ? p.s.saved.turnPage(-1) : p.s.zoom(1)} />; - const minus = = p.s.saved.page()!.total : results())} onPress={() => saved() ? p.s.saved.turnPage(1) : p.s.zoom(-1)} />; - const left = naming() ? p.s.saved.changeName("") : typing() ? p.s.setQuery("") : saved() ? p.s.saved.begin(p.s.saved.selected()!, true) : results() ? p.s.dismiss() : p.s.go(p.s.pin())} />; - const middle = saved() ? p.s.saved.askRemove() : p.s.saveCurrent()} />; - const right = typing() ? p.s.key("GO") : results() ? p.s.go() : p.s.saved.open()} />; + const plus = saved() ? p.s.saved.turnPage(-1) : p.s.zoom(1)} />; + const minus = = p.s.saved.page()!.total : results())} onPress={() => saved() ? p.s.saved.turnPage(1) : p.s.zoom(-1)} />; + const left = naming() ? p.s.saved.changeName("") : typing() ? p.s.setQuery("") : saved() ? p.s.saved.begin(p.s.saved.selected()!, true) : results() ? p.s.dismiss() : p.s.go(p.s.pin())} />; + const middle = saved() ? p.s.saved.askRemove() : p.s.saveCurrent()} />; + const right = typing() ? p.s.key("GO") : results() ? p.s.go() : p.s.saved.open()} />; const sheet = ; return {search} - + {typing() ? `${(naming() ? p.s.saved.name() : p.s.query()).slice(-31)}|` : saved() ? "Saved on your paired Mac" : results() ? p.s.query().slice(0, 32) : p.s.online() ? p.s.planar() ? "Hyrule - Breath of the Wild" : "Explore with your Nintendo 3DS" : "Waiting for paired Mac"} + + + {(name, i) => p.s.choose(i())} />} + + {keyboard}{padView}{plus}{minus}{left}{middle}{right}{sheet} ; } @@ -148,6 +192,7 @@ export default function MapApp() { const deck = ; const map = + {marker => } ; return <> @@ -161,7 +206,7 @@ export default function MapApp() { 500 m - + {s.status().slice(0, 35)} @@ -170,9 +215,9 @@ export default function MapApp() { Pocket Map - {`Stylus / Circle Pad / D-pad: pan\n+ and -: zoom around the map center\nY: search X: return to selected place\nHold L: places Hold R: map controls\n\n${s.planar() ? "Hyrule: Breath of the Wild\nMap art: Nintendo | Data: Zelda Dungeon\nMap and place search stored on your Mac" : "Maps: OpenStreetMap contributors\nosm.org/copyright | Tiles: OSM DE\nPlace search: Photon by komoot"}`} + {`Stylus / Circle Pad / D-pad: pan\n+ and -: zoom around the map center\nY: search X: return to selected place\nHold L: places Hold R: map controls\nHold ZL + Up/Down: zoom level\n\n${s.planar() ? "Hyrule: Breath of the Wild\nMap art: Nintendo | Data: Zelda Dungeon\nMap and place search stored on your Mac" : "Maps: OpenStreetMap contributors\nosm.org/copyright | Tiles: OSM DE\nPlace search: Photon by komoot"}`} - + {s.info()?.attribution ?? "Map data"} {deck}; } diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index cc75e7c..4b78145 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -29,6 +29,7 @@ bounded requests and replies; they do not execute these capabilities. | Places per search | 5 | | Saved places | 1,000 on Mac; four five-place pages cached on device | | Saved-place name | 36 UTF-16 code units | +| Marker resource cache | 12 windows; at most four demanded, 12 records per window | | Query text | 80 UTF-16 code units | | Unicode label collection | 5 × 256×32 images | | Mac concurrent tile decodes | 3 | @@ -47,9 +48,12 @@ and 2,500-code-unit payload limits. ## One tile's lifecycle 1. The camera's viewport produces near-first tile coordinates. Hyrule adds up - to 12 neighbors using a 256px margin and at most 384px directional lead; OSM - adds at most four, with a 128px margin and lead cap. Prediction uses the latest - displacement over 48 local-atlas frames or 36 geographic-map frames. Visible + to 12 neighbors using a 256px margin and at most 512px directional lead; OSM + adds at most four, with a 128px margin and lead cap. Prediction accumulates camera travel across gestures in constant space. A + settled direction chooses a forward corridor. Three idle seconds preserve + direction, followed by confidence decay. Sustained turns replace old intent. + Hyrule also prepares at most six next-level tiles for five seconds after a + zoom-in input, sharing the 12-extra-tile budget. Visible entries are pinned; extras have lower priority and are unpinned. Hyrule clips both axes; OSM wraps longitude and clips polar rows. Addresses include the provider source identity. @@ -171,3 +175,29 @@ is no GPS, turn-by-turn routing or satellite layer. The optional geographic provider has no area downloader, and public services have no availability guarantee. Network isolation and bounded work do not establish a hardware frame-time guarantee. + +## Source selection and annotation resources + +**Each request identifies its source.** `map.info({ kind })` returns the selected +metadata and the installed-source catalog. The worker routes tile/search and +bookmark calls by source identity rather than mutating a connection-wide active +provider. Delayed commands and retries therefore retain their original SQLite +database. Old guests that omit a source use the configured startup provider. + +The guest suspends new resource starts while source metadata is requested. It +keeps old pixels visible until metadata succeeds, then cancels old demand, +clears source-dependent collections and restores that map's remembered camera. +Source changes are unavailable during bookmark naming or mutation confirmation. + +The marker index uses SQLite R-tree queries on the Mac. Requests address fixed +512px annotation windows at an integer level and a category filter. Each reply +has at most 12 records; four windows cover the viewport. The host bounds query +candidates to 256 and chooses one marker per density grid slot. Region, travel, +enemy and collectible visibility use different zoom ranges. This reduces +clutter; it is not a full cross-window label-collision solver. + +Annotation responses share resource scheduling with terrain but have separate +cache costs and view ownership. Names and category icons are drawn locally at +constant screen size; only their transforms change during motion. No bitmap is +requested for every label or every frame. Icon assets are compiled into the +package. An annotation cache failure leaves terrain navigation available. diff --git a/docs/VALIDATION.md b/docs/VALIDATION.md index eeb3d87..37c5b65 100644 --- a/docs/VALIDATION.md +++ b/docs/VALIDATION.md @@ -129,3 +129,33 @@ seconds. The source's documented per-IP speed allowance means absence of HTTP service dependency. It does not establish the 3DS bandwidth limit or continuous 60 fps. The new device session has returned frame telemetry and image requests; physical gesture acceptance remains separate from liveness and replay results. + +## Directional navigation, live sources and labels + +The next revision passes 14 app tests and TypeScript. New cases exercise +repeated diagonal strokes separated by pauses, reversal/expiry, local next-level +prediction, OSM's four-tile same-level cap, the ZL chord without camera panning, +source restoration and delayed bookmark receipts routed to their original map. +Marker tests cover zoom/category filtering, reply limits and invalid windows. +Ten framework tile tests and framework TypeScript pass, including equivalent +30/60 Hz directional histories and camera zoom-target exposure. + +The compiled guest passes 20 Hyrule replay checks across 1,713 frames and all +27 geographic checks across 1,591 frames. New replay coverage uses actual lower +surface hit testing for repeated strokes and source switching, ZL zoom/rail +mounting, next-level demand, real indexed labels and category selection. The +OSM provider used during switching is synthetic: no public-service stress scan +runs. Maxima remain three pending requests, 40 tile entries and three staging +tickets. Hyrule made zero HTTP downloads; the synthetic OSM adapter served eight +tile fetches. All staging tickets drained. + +QuickJS passes 1,272 frames per startup provider at a 128 KiB stack, including +marker components, ZL, source/filter panels and switching both ways. The native +package includes all nine annotation icons, with the correct power-of-two +image envelopes. Wasm captures were visually checked for the labels, zoom rail, +source picker and category picker. Native build and readback do not substitute +for physical gesture or frame-time acceptance of this revision. + +The navigation build was uploaded and read back equal: 1,720,504 bytes; SHA-256 +`348e614c1016fceb175d701bd3ae14294f817367f326d13493473488e16a1e2a`. +The Mac daemon now exposes both maps through source-identified requests. diff --git a/docs/images/hyrule-search.png b/docs/images/hyrule-search.png index 338a916894a61a2cdbd6757aeed314e06d57c8a4..27f341f5e85a0e8f30bb2515687e6815a750e4d7 100644 GIT binary patch literal 36104 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%0A6JJ4Amg>47 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

!BJeFO##gueKMzyDDrK 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 literal 0 HcmV?d00001 diff --git a/docs/images/zoom-rail.png b/docs/images/zoom-rail.png new file mode 100644 index 0000000000000000000000000000000000000000..38e41edc2d2130798d356a943fa3bc2477db9d09 GIT binary patch literal 50617 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∓^?H&$FpUbz<)K+esxM(?4o0l=!YsWvcn1M5IK(4v<@1LhyF0 z{pknI5>s!JGUtYCmb0k;c(}SOtz6Cv2ww%pU@c4G9?@JRdn&M-7|xwoAoeFKaUYv= zq5y0zYidBVl5G1{=EKuKY}bt7KX{l)j*AD471dVKn1D52DVGE6{C}Tl{{-1mhBITl z%^ATvGm?=m`5b`}=UB_OB}-vzh85pP4PaRz&AQOW9&LRp3>)fvP77j2jGN$nh)idF z^XH9L2R*yS?G=Apz$`Z)F9{bH~b$ATs; zu0>#r)xU%(9sk3sS^Wg5_urasa}Se^_f~ZLCr6Ddbd5#sK40&DlP=bfIOhG+35?`(2(Mr z4`2`mFnk+h_01{~dKDw{T2soe*>69n^>Dso=4Q!r&n7+sVbkw&mEpI4|Ku&LS(Tde zp^VH0_cf#R`a`?xNaA_0*S){@#Dl)JLccOk>YE)cdEP?9f&XdhkIo72(8to6@a>ili3`-ux4fMov`tL$k#meQinCdtloL=+H+ zSn+Q$^BP$`iN68^l}cqk(7f4FoS7B0Pw>CQg|kpWUV(MZ>zicJ(c~n@1P*e7nzTz)0>||bD zHD(gHn#Hm+LUg1k0DK>bYo%3$43;BLiX-NGlR6o~>1{kSb0bZJHeFsg>g1884K5<3(>GTbc*+E+NRbe_4?>$sf_>TnD!rS z9lNRK

Pocket Map displaying the local Hyrule atlas on a compiled dual-screen guest Local Kakariko search results with the bottom-screen selection touchpad

+The Mac fetches OSM vector tiles, prepares bounded geometry and streams it to the 3DS GPU drawing path. Four real San Francisco tiles used **79.5% fewer terrain bytes** than the previous raw bitmap path; z14 geometry is reused through display z18. Hyrule retains its complete local raster atlas and 2,576 searchable places, with no internet requests while browsing. See [vector architecture, measurements and limits](docs/VECTOR_MAP.md). + +

Actual San Francisco vector data rendered by the compiled dual-screen Pocket Map guest Pocket Map displaying the local Hyrule atlas on a compiled dual-screen guest Local Kakariko search results with the bottom-screen selection touchpad

+ +OSM map data © [OpenStreetMap contributors](https://www.openstreetmap.org/copyright), served as Shortbread vectors by VersaTiles. These are **compiled guest + Wasm captures**, at the 3DS's 400×240 / 320×240 logical resolutions, not console photographs. Map artwork belongs to Nintendo; the pinned atlas and marker source is [Zelda Dungeon's map repository](https://github.com/zeldadungeon/maps/tree/d32a85656031d861cef38e32eb927a7d08a983a9/public/botw). Downloaded assets and generated databases stay outside Git. ## Try it -Requirements: Bun 1.3.14, Docker with the PocketJS 3DS toolchain (or a supported native devkitPro install), Git, a Mac and a 3DS on the same LAN, Homebrew Launcher and ftpd. The runtime submodule pins the image-resource support used by this app. +Requirements: Bun 1.3.14, Docker with the PocketJS 3DS toolchain (or a supported native devkitPro install), Git, a Mac and a 3DS on the same LAN, Homebrew Launcher and ftpd. The runtime submodule pins the mesh and image resource support used by this app. ```sh git clone --recurse-submodules https://github.com/pocket-stack/pocket-map.git cd pocket-map cd runtime && bun install --frozen-lockfile && cd .. +bun install --frozen-lockfile bun run setup bun run prepare:hyrule bun run 3ds @@ -107,7 +112,7 @@ Regions appear at wide zooms; detailed items such as Koroks and treasures appear from level 6. The Mac performs spatial queries and density selection. The guest receives bounded point/name/category records and draws small baked icons plus text locally, so labels move with the map without another network round trip. -OSM's place labels remain part of its base tile images. +OSM labels are independent of terrain geometry. Its menu offers Show / Hide labels; ASCII uses the shared local glyph atlas, with a cached image fallback for other scripts. `prepare:hyrule` refreshes the separate marker index without rebaking existing terrain textures. Marker assets and SQLite stay outside Git; the small UI icons @@ -129,50 +134,51 @@ place. Cancel after an unconfirmed command does not undo a Mac write; reopen Saved to check its outcome. A connected Mac is needed for writes. The guest retains up to four previously viewed pages during a disconnection. -## Optional OpenStreetMap provider +## OpenStreetMap vector provider -Start `bun run host <3ds-ip> --osm` to use the geographic provider. Its configuration uses `https://tile.openstreetmap.de/{z}/{x}/{y}.png` and `https://photon.komoot.io/api/`, both verified reachable from the development Mac. The main `tile.openstreetmap.org` endpoint failed to connect in that network. No API keys are required by the selected demo endpoints. +Start `bun run host <3ds-ip> --osm` to open OSM first. Hyrule remains available +from the source picker when its atlas is installed. For an OSM-only setup, skip +`prepare:hyrule` and use `--osm`. -Override OSM settings in `.local/provider.json`, then restart the host with `--osm`: - -```json -{ - "tileURL": "https://tile.openstreetmap.org/{z}/{x}/{y}.png", - "searchURL": "https://photon.komoot.io/api/", - "name": "OpenStreetMap", - "attribution": "OpenStreetMap contributors", - "maxZoom": 18 -} -``` +The default uses [VersaTiles' public Shortbread MVTs](https://docs.versatiles.org/guides/use_tiles_versatiles_org.html) +and [Photon place search](https://github.com/komoot/photon#demo-server), without +API keys. The Mac caches responses in SQLite, preserves HTTP validators and +prepares geometry in its isolated capability process. Search requires an +explicit submit and has a 1.1-second minimum interval. -The tile endpoint must return 256px PNGs; the search endpoint must implement the Photon response shape. HTTPS and loopback HTTP development endpoints are supported. The device sends typed tile coordinates, not arbitrary URLs. Tile identities include a hash of the source URL and rendition version. +Override the Shortbread endpoint in ignored `.local/provider.json`, then restart +the daemon. [VECTOR_MAP.md](docs/VECTOR_MAP.md#provider-configuration) includes an +OSM official endpoint example, protocol details, provider requirements and +measurement limits. Source z14 geometry remains resident while zooming through +z18; street-label windows query the same prepared source data. -Public services have limited capacity: [OSM DE's terms](https://openstreetmap.de/germanstyle/#nutzungsbedingungen), [tile usage policy](https://operations.osmfoundation.org/policies/tiles/), and [Photon's demo policy](https://github.com/komoot/photon#demo-server) apply. **The current viewport has priority; at most four nearby tiles provide short-range look-ahead.** The margin is 128 screen pixels and movement prediction is capped at 128 pixels; there is no area downloader or multi-level pre-seeding. The OSM DE service documents per-IP throttling after an unspecified high-speed tile allowance; a slow response does not necessarily produce HTTP 429. Searches require an explicit submit and are limited to one per 1.1 seconds on this provider. The Mac honors HTTP cache headers and conditional requests, using seven days for tiles without freshness headers. Use an appropriate hosted or self-hosted service before scaling beyond this personal demo. Endpoint configuration allows that switch without rebuilding the 3DS app. +Custom 256px PNG endpoints remain supported with `"format": "raster"`. Hyrule's +complete local JPEG-derived atlas stays on the R5G6B5 image path. ## Architecture and resource pattern -```text -3DS UI thread 3DS network worker Mac capability process -camera + controls authenticated TCP local atlas / optional HTTPS -visible tile demand -> bounded request queue -> SQLite textures + place index -ResourceImage fallback <- native image tickets <- binary R5G6B5 pixels -one image upload/frame eight staging slots bounded tile/label output -``` - -The app uses `createOffloadImageCollection` to declare the tile identity and rendition once. View owners declare demand; reads subscribe by key. The runtime merges demands, schedules requests, retries failed reads, uploads within the frame budget and frees textures on eviction. Cancelling a response before upload returns its native staging slot. +The app defines separate image and geometry collections. Both use the same +scheduler, view-demand merging, retry, fallback and eviction lifecycle: ```ts -const tiles = createOffloadImageCollection(runtime, io, { +const tiles = createOffloadMeshCollection(runtime, io, { key: (tile: TileInput) => `${tile.source}/${tile.z}/${tile.x}/${tile.y}`, - method: "map.tile", payload: JSON.stringify, - width: 256, height: 256, maxEntries: 40, - maxViews: 2, maxDemandsPerView: 24, + method: "map.mesh", payload: JSON.stringify, + maxEntries: 40, maxViews: 2, maxDemandsPerView: 24, }); const view = createResourceView(tiles, { demand: visibleTileDemand }); -// view.state(tile)} fallback={() => } /> +// view.state(tile)} fallback={() => } /> ``` -Map-specific behavior remains in [app/model.ts](app/model.ts) and [app/geo.ts](app/geo.ts): coordinate systems, visible priorities, selection and search. [host/atlas.ts](host/atlas.ts) reads the prepared Hyrule atlas; [host/provider.ts](host/provider.ts) and [host/cache.ts](host/cache.ts) implement the optional HTTP provider. [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) records budgets, lifecycle and tradeoffs. +Hyrule declares `createOffloadImageCollection` and renders `ResourceImage`. +Rendering starts no IO. The native worker owns reception; the scheduler admits +one materialization per frame; the collection returns staging and eventually +frees its native handles. + +Map-specific policy remains in [app/model.ts](app/model.ts), [app/prediction.ts](app/prediction.ts) +and [app/annotations.ts](app/annotations.ts). [host/vector-geometry.ts](host/vector-geometry.ts) +prepares OSM geometry; [host/atlas.ts](host/atlas.ts) reads Hyrule textures. +[ARCHITECTURE.md](docs/ARCHITECTURE.md) records budgets and lifecycle. ## Validation @@ -181,7 +187,8 @@ bun run check runtime/node_modules/.bin/tsc --noEmit bun run sim # compiled guest, synthetic OSM provider, interaction replay bun run sim --hyrule # complete local atlas, search and delayed-response navigation -bun run sim --live # current live viewport + one explicit place search +bun scripts/vector-sim.ts +bun scripts/vector-sim.ts --live # a small real vector viewport, cached on Mac qjs --std --stack-size 131072 scripts/quickjs-smoke.js qjs --std --stack-size 131072 scripts/quickjs-smoke.js runtime/dist/3ds/guest/pocketmap-main.js hyrule ``` diff --git a/app/annotations.ts b/app/annotations.ts index df6363c..701f85c 100644 --- a/app/annotations.ts +++ b/app/annotations.ts @@ -1,32 +1,133 @@ import { createMemo, createSignal } from "solid-js"; import { createResourceView, type createResourceRuntime } from "@pocketjs/framework/resource-view"; import { offloadResource } from "@pocketjs/framework/resource-offload"; +import { getOps } from "@pocketjs/framework/host"; import { visibleTiles } from "@pocketjs/framework/tile-viewport"; import type { offload } from "@pocketjs/framework/offload"; import { MARKER_KINDS, type MapInfo, type MapMarker, type MarkerInput, type MarkerLayer } from "../shared/types.ts"; export const LAYERS: { id: MarkerLayer; name: string }[] = [ - { id: "all", name: "All map labels" }, { id: "travel", name: "Places, shrines & towers" }, - { id: "collectibles", name: "Koroks & treasures" }, { id: "enemies", name: "Enemies" }, { id: "off", name: "Hide labels" }, + { id: "all", name: "All map labels" }, + { id: "travel", name: "Places, shrines & towers" }, + { id: "collectibles", name: "Koroks & treasures" }, + { id: "enemies", name: "Enemies" }, + { id: "off", name: "Hide labels" }, ]; +const metrics = new Map(); +export function labelMetrics(name: string) { + const cached = metrics.get(name); + if (cached) return cached; + const unicode = /[^\x20-\x7e]/.test(name); + const width = (text: string) => (unicode ? text.length * 13 : getOps().measureText(text, 0)); + let text = name; + while (text.length > 1 && width(text) > 166) text = text.slice(0, -1); + if (text !== name) { + text = text.slice(0, -3) + "..."; + } + const result = { text, width: Math.min(174, Math.ceil(width(text)) + 8) }; + metrics.set(name, result); + if (metrics.size > 256) metrics.delete(metrics.keys().next().value!); + return result; +} +export const labelWidth = (name: string) => labelMetrics(name).width; export function createAnnotations(io: ReturnType, runtime: ReturnType) { - const [layer, setLayer] = createSignal("all"), [demand, setDemand] = createSignal([]); - const collection = runtime.createCollection({ key: (i: MarkerInput) => `${i.source}/${i.layer}/${i.z}/${i.x}/${i.y}`, maxEntries: 12, maxViews: 1, maxDemandsPerView: 4, - cost: () => 8192, maxCost: 12 * 8192, maxResponseBytes: 5000, load: offloadResource(io, "map.markers", JSON.stringify), + const [layer, setLayer] = createSignal("all"), + [demand, setDemand] = createSignal([]); + const collection = runtime.createCollection({ + key: (i: MarkerInput) => `${i.source}/${i.layer}/${i.z}/${i.x}/${i.y}`, + maxEntries: 40, + maxViews: 1, + maxDemandsPerView: 12, + cost: () => 8192, + maxCost: 40 * 8192, + maxResponseBytes: 5000, + load: offloadResource(io, "map.markers", JSON.stringify), materialize(raw: string): MapMarker[] { const rows = JSON.parse(raw); - if (!Array.isArray(rows) || rows.length > 12 || !rows.every(m => Array.isArray(m) && m.length === 5 && Number.isSafeInteger(m[0]) && typeof m[1] === "string" && m[1].length <= 24 && MARKER_KINDS.includes(m[2]) && Number.isFinite(m[3]) && Number.isFinite(m[4]) && m[3] >= 0 && m[3] < 256 && m[4] >= 0 && m[4] < 256)) throw new Error("Invalid map annotations"); + if ( + !Array.isArray(rows) || + rows.length > 12 || + !rows.every( + (m) => + Array.isArray(m) && + m.length === 5 && + Number.isSafeInteger(m[0]) && + typeof m[1] === "string" && + m[1].length <= 24 && + MARKER_KINDS.includes(m[2]) && + Number.isFinite(m[3]) && + Number.isFinite(m[4]) && + m[3] >= 0 && + m[3] < 256 && + m[4] >= 0 && + m[4] < 256, + ) + ) + throw new Error("Invalid map annotations"); return rows; - } }); - const view = createResourceView(collection, { demand: () => demand().map(input => ({ input, priority: 25, pin: true })) }); - const rows = createMemo(() => demand().flatMap(i => view.value(i) ?? [])); - return { layer, setLayer, rows, - reset() { setDemand([]); collection.clear(); }, + }, + }); + const view = createResourceView(collection, { + demand: () => demand().map((input) => ({ input, priority: 25, pin: true })), + }); + const rows = createMemo(() => demand().flatMap((i) => view.value(i) ?? [])); + let placements = new Map(); + return { + layer, + setLayer, + rows, + placement: (id: number) => placements.get(id), + reset() { + setDemand([]); + collection.clear(); + }, update(camera: { x: number; y: number; zoom: number }, level: number, info: MapInfo) { - const cells = Math.max(1, 2 ** (level - 1)); - const next: MarkerInput[] = info.markers && layer() !== "off" ? visibleTiles({ ...camera, zoom: level, level, width: 400, height: 240, tileSize: 512, maxTiles: 4 }) - .filter(t => t.column >= 0 && t.row >= 0 && t.column < cells && t.row < cells) - .map(t => ({ source: info.source, z: level, x: t.column, y: t.row, layer: layer() })) : []; - const old = demand(); if (next.length !== old.length || next.some((v, n) => JSON.stringify(v) !== JSON.stringify(old[n]))) setDemand(next); + if (info.render === "mesh") level = Math.min(info.maxZoom, Math.max(0, Math.round(camera.zoom))); + const vector = info.render === "mesh", + size = vector ? 256 : 512; + const cells = Math.max(1, 2 ** (vector ? level : level - 1)); + const next: MarkerInput[] = + info.markers && layer() !== "off" + ? visibleTiles({ + ...camera, + zoom: vector ? camera.zoom : level, + level, + width: 400, + height: 240, + tileSize: size, + maxTiles: vector ? 12 : 4, + }) + .filter((t) => t.row >= 0 && t.row < cells && (vector || (t.column >= 0 && t.column < cells))) + .map((t) => ({ + source: info.source, + z: level, + x: vector ? ((t.column % cells) + cells) % cells : t.column, + y: t.row, + layer: layer(), + })) + : []; + if (vector) { + const placed = new Map(), + names = new Set(); + for (const marker of rows() + .slice() + .sort((a, b) => Number(placements.has(b[0])) - Number(placements.has(a[0])) || a[0] - b[0])) { + if (placed.size >= 12 || names.has(marker[1])) continue; + let dx = marker[3] - camera.x; + dx -= Math.round(dx / 256) * 256; + const width = labelWidth(marker[1]), + x = 200 + dx * 2 ** camera.zoom - width / 2, + y = 120 + (marker[4] - camera.y) * 2 ** camera.zoom - 7; + if (x < 2 || x + width > 398 || y < 29 || y > 208) continue; + if ([...placed.values()].some((p) => x < p.x + p.width + 4 && x + width + 4 > p.x && Math.abs(y - p.y) < 19)) + continue; + placed.set(marker[0], { x, y, width }); + names.add(marker[1]); + } + placements = placed; + } else placements.clear(); + const old = demand(); + if (next.length !== old.length || next.some((v, n) => JSON.stringify(v) !== JSON.stringify(old[n]))) + setDemand(next); }, }; } diff --git a/app/model.ts b/app/model.ts index 16dde06..c2dd501 100644 --- a/app/model.ts +++ b/app/model.ts @@ -1,6 +1,6 @@ import { createSignal, createMemo } from "solid-js"; import { createResourceRuntime, createResourceView } from "@pocketjs/framework/resource-view"; -import { createOffloadImageCollection, offloadResource } from "@pocketjs/framework/resource-offload"; +import { createOffloadImageCollection, createOffloadMeshCollection, offloadResource } from "@pocketjs/framework/resource-offload"; import { createTileCamera } from "@pocketjs/framework/tile-viewport"; import { offload } from "@pocketjs/framework/offload"; import { analogX, analogY, onFrame, onButtonPress } from "@pocketjs/framework/lifecycle"; @@ -35,14 +35,24 @@ export function createMap(io = offload()) { const planar = () => info()?.space === "planar"; const p = project(HOME.lat, HOME.lon); const camera = createTileCamera({ width: 400, height: 240, x: p.x, y: p.y, zoom: HOME.zoom, minZoom: 1, maxZoom: 18, bounds: { width: 256, height: 256, wrapX: true } }); - const runtime = createResourceRuntime({ maxConcurrent: 3, startsPerFrame: 1, completionsPerFrame: 1, maxCollections: 5, available: () => !switching() && io.connected() && !!info() && io.pending() < 3 }); - const tiles = createOffloadImageCollection(runtime, io, { key: (i: TileInput) => `${i.source}/${i.z}/${i.x}/${i.y}`, method: "map.tile", payload: JSON.stringify, + const runtime = createResourceRuntime({ maxConcurrent: 3, startsPerFrame: 1, completionsPerFrame: 1, maxCollections: 6, available: () => !switching() && io.connected() && !!info() && io.pending() < 3 }); + const rasterTiles = createOffloadImageCollection(runtime, io, { key: (i: TileInput) => `${i.source}/${i.z}/${i.x}/${i.y}`, method: "map.tile", payload: JSON.stringify, width: 256, height: 256, maxEntries: 40, maxViews: 2, maxDemandsPerView: 24, retry: { attempts: 3, delayFrames: 90, maxDelayFrames: 360 } }); + const vector = () => info()?.render === "mesh"; + const meshTiles = createOffloadMeshCollection(runtime, io, {key:(i:TileInput)=>`${i.source}/${i.z}/${i.x}/${i.y}`,method:"map.mesh",payload:JSON.stringify, + maxEntries:40,maxViews:2,maxDemandsPerView:24,retry:{attempts:3,delayFrames:90,maxDelayFrames:360}}); + const tiles = { invalidate(){rasterTiles.invalidate();meshTiles.invalidate();},clear(){rasterTiles.clear();meshTiles.clear();},stats:()=>vector()?meshTiles.stats():rasterTiles.stats() }; const labels = createOffloadImageCollection(runtime, io, { key: (i: Place) => `${i.name}/${i.detail}`, method: "map.label", payload: i => JSON.stringify({ name: i.name, detail: i.detail }), - width: 256, height: 32, maxEntries: 5, maxViews: 5, maxDemandsPerView: 1 }); + width: 256, height: 32, maxEntries: 24, maxViews: 29, maxDemandsPerView: 1 }); const [lookAhead, setLookAhead] = createSignal([]); - const frontView = createResourceView(tiles, { demand: () => [...(front()?.tiles.map(t => ({ input: t.input, priority: t.priority, pin: true })) ?? []), ...lookAhead().map(t => ({ input: t.input, priority: t.priority, pin: false }))] }); - const backView = createResourceView(tiles, { demand: () => back()?.tiles.map(t => ({ input: t.input, priority: 100, pin: true })) ?? [] }); + const frontDemand=()=>[...(front()?.tiles.map(t=>({input:t.input,priority:t.priority,pin:true}))??[]),...lookAhead().map(t=>({input:t.input,priority:t.priority,pin:false}))]; + const backDemand=()=>back()?.tiles.map(t=>({input:t.input,priority:100,pin:true}))??[]; + const rasterFront=createResourceView(rasterTiles,{demand:()=>vector()?[]:frontDemand()}); + const meshFront=createResourceView(meshTiles,{demand:()=>vector()?frontDemand():[]}); + const rasterBack=createResourceView(rasterTiles,{demand:()=>vector()?[]:backDemand()}); + const meshBack=createResourceView(meshTiles,{demand:()=>vector()?backDemand():[]}); + const frontView={state:(i:TileInput)=>vector()?meshFront.state(i):rasterFront.state(i)}; + const backView={state:(i:TileInput)=>vector()?meshBack.state(i):rasterBack.state(i)}; const searches = runtime.createCollection({ key: (i: SearchInput) => JSON.stringify(i), maxEntries: 4, maxViews: 1, maxDemandsPerView: 1, maxCost: 4 * 8192, cost: () => 8192, maxResponseBytes: 5000, retry: { attempts: 1, delayFrames: 60, maxDelayFrames: 60 }, load: offloadResource(io, "map.search", JSON.stringify), materialize(raw: string): Place[] { @@ -62,12 +72,13 @@ export function createMap(io = offload()) { function select(index: number) { const n = Math.max(0, Math.min(rows().length - 1, index)); if (mode() === "saved") saved.setSelection(n); else setSelection(n); } prediction.reset(camera.view()); const maps = () => info()?.maps ?? []; - const choices = () => mode() === "sources" ? maps().map(m => m.name) : LAYERS.map(l => l.name); + const labelLayers = () => vector() ? [LAYERS[0],LAYERS[4]] : LAYERS; + const choices = () => mode() === "sources" ? maps().map(m => m.name) : labelLayers().map(l => l.name); const choosing = () => mode() === "sources" || mode() === "layers"; function openSources() { if (saved.busy() || saved.modal() || typing() || switching()) return; camera.stop(); setSourceError(""); setMode("sources"); setSelection(Math.max(0, maps().findIndex(m => m.kind === info()?.kind))); setMenu(undefined); } function choose(index = selection()) { if (mode() === "sources") { const kind = maps()[index]?.kind; if (kind) switchMap(kind); } - else if (mode() === "layers") { annotations.setLayer(LAYERS[index].id); dismiss(); } + else if (mode() === "layers") { annotations.setLayer(labelLayers()[index].id); dismiss(); } } function switchMap(kind: MapKind) { if (saved.busy() || saved.modal() || typing() || switching()) return; @@ -125,7 +136,7 @@ export function createMap(io = offload()) { if (bank === "places") { if (i === 0) openSearch(); else if (i === 1) saved.open(); else if (i === 2) saveCurrent(); else if (i === 3) go(pin()); else if (info()?.home) go(info()!.home); else home("San Francisco", HOME.lat, HOME.lon); } else if (bank === "map") { - if (i < 2) zoom(i === 0 ? 1 : -1); else if (i === 2) { setMode("layers"); setSelection(LAYERS.findIndex(l => l.id === annotations.layer())); } else if (i === 3) openSources(); else if (i === 4) setPin(undefined); else if (i === 5) tiles.invalidate(); else setMode("about"); + if (i < 2) zoom(i === 0 ? 1 : -1); else if (i === 2) { setMode("layers"); setSelection(labelLayers().findIndex(l => l.id === annotations.layer())); } else if (i === 3) openSources(); else if (i === 4) setPin(undefined); else if (i === 5) tiles.invalidate(); else setMode("about"); } } onButtonPress(BTN.CIRCLE, (_pressed, buttons) => { if (buttons & BTN.ZL || saved.modal() || saved.busy() || switching() || zoomHeld()) return; if (choosing()) choose(); else if (menu()) runMenu(); else if (typing()) key("GO"); else if (listing()) go(); }); @@ -158,6 +169,8 @@ export function createMap(io = offload()) { const value: MapInfo = JSON.parse(result.value); if (typeof value.source !== "string" || !/^[a-f0-9]{16}$/.test(value.source) || typeof value.name !== "string" || typeof value.attribution !== "string" || !Number.isInteger(value.maxZoom) || value.maxZoom < 1 || value.maxZoom > 18 || !Number.isInteger(value.minZoom ?? 1) || (value.minZoom ?? 1) < 0 || (value.minZoom ?? 1) > value.maxZoom + || value.render !== undefined && value.render !== "mesh" + || value.render === "mesh" && (!Number.isInteger(value.dataZoom) || value.dataZoom! < 0 || value.dataZoom! > value.maxZoom) || value.space !== undefined && value.space !== "mercator" && value.space !== "planar" || value.home !== undefined && (!validPlaces([value.home]) || (value.home.space === "planar") !== (value.space === "planar"))) throw new Error("Invalid map provider"); if (value.maps !== undefined && (!Array.isArray(value.maps) || value.maps.length > 2 || !value.maps.every(m => (m.kind === "hyrule" || m.kind === "osm") && typeof m.name === "string" && m.name.length <= 40))) throw new Error("Invalid map catalog"); @@ -194,7 +207,7 @@ export function createMap(io = offload()) { previousButtons = buttons; if (!info()) return; const view = camera.view(); prediction.sample(view, 1 / simulationHz(), !planar()); - const next = Math.min(info()!.maxZoom, Math.max(info()!.minZoom ?? 1, Math.round(view.zoom))); + const next = Math.min(info()!.dataZoom ?? info()!.maxZoom, Math.max(info()!.minZoom ?? 1, Math.round(view.zoom))); levelAge = next === candidateLevel ? levelAge + 1 : 0; candidateLevel = next; let level = front()?.level ?? next; if (next !== level && (levelAge >= 8 || Math.abs(next - level) > 1)) { @@ -218,7 +231,7 @@ export function createMap(io = offload()) { } if (back() && front()?.tiles.every(t => frontView.state(t.input).status === "ready")) setBack(undefined); }); - return { io, runtime, tiles, labels, frontView, backView, info, planar, online, zoomHeld, switching, sourceError, maps, choices, choosing, choose, openSources, switchMap, annotations, status, mode, setMode, query, setQuery, submitted, results, places, selection, setSelection, pin, menu, menuIndex, + return { io, runtime, tiles, vector, labels, frontView, backView, info, planar, online, zoomHeld, switching, sourceError, maps, choices, choosing, choose, openSources, switchMap, annotations, status, mode, setMode, query, setQuery, submitted, results, places, selection, setSelection, pin, menu, menuIndex, shift, symbols, front, back, camera, saved, typing, listing, rows, selectedIndex, select, saveCurrent, lookAhead, search, openSearch, go, zoom, key, dismiss, runMenu, clearBack: () => setBack(undefined), diagnostics: () => ({ frame, pending: io.pending(), resources: runtime.stats(), tiles: tiles.stats(), camera: camera.view() }), diff --git a/app/prediction.ts b/app/prediction.ts index 367c5ef..8f600e8 100644 --- a/app/prediction.ts +++ b/app/prediction.ts @@ -19,7 +19,7 @@ export function createMapPrediction() { plan(view: View, level: number, info: MapInfo) { const local = info.local === true, lead = intent.predict(local ? 512 : 128), directional = lead.confidence > .45; const options = { ...view, level, width: 400, height: 240, maxTiles: 12, margin: local ? 256 : 128, - leadX: lead.x, leadY: lead.y, directional, maxExtra: local ? 12 : 4 }; + leadX: lead.x, leadY: lead.y, directional, maxExtra: info.prefetch === false ? 0 : local ? 12 : 4 }; const window = planTileWindow(options); const address = (list: typeof window.visible, z: number): PlannedTile[] => list .filter(t => t.row >= 0 && t.row < 2 ** z && (info.space !== "planar" || t.column >= 0 && t.column < 2 ** z)) diff --git a/app/ui.tsx b/app/ui.tsx index 9feb241..1f23109 100644 --- a/app/ui.tsx +++ b/app/ui.tsx @@ -1,12 +1,13 @@ import { createSignal, For, Show } from "solid-js"; import { AuxiliarySurface, Image, Text, View, type NodeMirror } from "@pocketjs/framework/components"; import { ClassicButton, ClassicFace, ClassicPanel, ClassicSheet } from "@pocketjs/framework/classic"; -import { ResourceImage } from "@pocketjs/framework/resource"; +import { ResourceImage, ResourceMesh } from "@pocketjs/framework/resource"; import { createResourceView } from "@pocketjs/framework/resource-view"; import { createGesture, createDragFilter } from "@pocketjs/framework/gesture"; import { simulationHz } from "@pocketjs/framework/clock"; import { onFrame } from "@pocketjs/framework/lifecycle"; import * as hot from "@pocketjs/framework/hot"; +import {labelWidth,labelMetrics} from "./annotations.ts"; import { createMap, MENU, type MapModel, type Layer } from "./model.ts"; import { worldPosition, unproject, scaleBar } from "./geo.ts"; import type { Place, MapMarker } from "../shared/types.ts"; @@ -29,24 +30,40 @@ function TileLayer(p: { s: MapModel; back?: boolean }) { hot.prop(world, "scaleX", scale); hot.prop(world, "scaleY", scale); }); return - {tile => {tile => { const Tile = p.s.vector() ? ResourceMesh : ResourceImage; return resources.state(tile.input)} fallback={() => p.back || p.s.back() ? : - } errorFallback={() => Tile unavailable} />} + } errorFallback={() => Tile unavailable} />; }} ; } +function UnicodeAnnotation(p:{s:MapModel;place:Place;width:number}) { + const image=createResourceView(p.s.labels,{demand:()=>[{input:p.place,priority:30,pin:true}]}); + return image.state(p.place)} fallback={()=>} />; +} function Annotation(p: { s: MapModel; marker: MapMarker }) { let root: NodeMirror | undefined; + const [visible,setVisible]=createSignal(false); + const vector=p.s.vector(),unicode=vector && /[^\x20-\x7e]/.test(p.marker[1]); + const place:Place={id:`label:${p.marker[0]}`,name:labelMetrics(p.marker[1]).text,detail:"",lat:0,lon:0,zoom:14}; + const width=vector?labelWidth(p.marker[1]):118; onFrame(() => { + if(vector){const at=p.s.annotations.placement(p.marker[0]);setVisible(!!at);hot.prop(root,"display",at?0:1);if(at){hot.prop(root,"translateX",at.x);hot.prop(root,"translateY",at.y);}return;} const v = p.s.camera.view(), x = 200 + (p.marker[3] - v.x) * v.scale, y = 120 + (p.marker[4] - v.y) * v.scale; hot.prop(root, "translateX", x - 7); hot.prop(root, "translateY", y - 7); hot.prop(root, "display", x < -100 || x > 410 || y < 18 || y > 235 ? 1 : 0); }); - return - - - {p.marker[1].length > 16 ? p.marker[1].slice(0, 13) + "..." : p.marker[1]} + return + + + + {p.marker[1].length > 16 ? p.marker[1].slice(0, 13) + "..." : p.marker[1]} + }> + + + {labelMetrics(p.marker[1]).text} + }> + ; } function ZoomRail(p: { s: MapModel }) { diff --git a/bun.lock b/bun.lock new file mode 100644 index 0000000..d11e2aa --- /dev/null +++ b/bun.lock @@ -0,0 +1,29 @@ +{ + "lockfileVersion": 1, + "configVersion": 1, + "workspaces": { + "": { + "name": "pocket-map", + "dependencies": { + "@mapbox/vector-tile": "3.0.0", + "earcut": "3.2.3", + "pbf": "5.1.2", + }, + }, + }, + "packages": { + "@mapbox/point-geometry": ["@mapbox/point-geometry@1.1.0", "", {}, "sha512-YGcBz1cg4ATXDCM/71L9xveh4dynfGmcLDqufR+nQQy3fKwsAZsWd/x4621/6uJaeB9mwOHE6hPeDgXz9uViUQ=="], + + "@mapbox/vector-tile": ["@mapbox/vector-tile@3.0.0", "", { "dependencies": { "@mapbox/point-geometry": "~1.1.0", "@types/geojson": "^7946.0.16", "pbf": "^5.0.0" } }, "sha512-Qf10S1uIHMk20ri/IVBnpS+esUEkVaR5Hftmz88jTInrpmWgPGJfPe3LVjjlE77trLx8tH6qjTG7uWH9hIq/0Q=="], + + "@types/geojson": ["@types/geojson@7946.0.16", "", {}, "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg=="], + + "earcut": ["earcut@3.2.3", "", {}, "sha512-vnS4AVwp1KHAF13i1vp1/2D5evWy3k5u/iW/B81QVsUZtV8cv2tU0b2VNFlqvh4kYwrFMDdjPCfAmfyJW9y14Q=="], + + "pbf": ["pbf@5.1.2", "", { "dependencies": { "resolve-protobuf-schema": "^2.1.0" }, "bin": { "pbf": "bin/pbf" } }, "sha512-mnvGdvOrIvJOBGUEdGkrVXjN8E/VkIJCkf2eS1DH2yv82ORUlLttmDt0rWY38yYZmVwciZwBUvHM20qxBZf40w=="], + + "protocol-buffers-schema": ["protocol-buffers-schema@3.6.1", "", {}, "sha512-VG2K63Igkiv9p76tk1lilczEK1cT+kCjKtkdhw1dQZV3k3IXJbd3o6Ho8b9zJZaHSnT2hKe4I+ObmX9w6m5SmQ=="], + + "resolve-protobuf-schema": ["resolve-protobuf-schema@2.1.0", "", { "dependencies": { "protocol-buffers-schema": "^3.3.1" } }, "sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ=="], + } +} diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 4b78145..00c2aee 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -10,7 +10,7 @@ PocketJS `hot` APIs; a tile window change updates the component tree. The native offload worker owns sockets, the SD pairing-key read and binary reception. The paired Mac's capability process owns SQLite atlas reads, texture -decompression, optional HTTPS/PNG decoding and Unicode label rasterization. +decompression, HTTPS/MVT parsing, styling, simplification, polygon triangulation and Unicode label rasterization. Custom raster sources retain the PNG decoder. Atlas preparation performs JPEG decoding and R5G6B5 packing before browsing. Provider socket callbacks pass bounded requests and replies; they do not execute these capabilities. @@ -23,16 +23,19 @@ bounded requests and replies; they do not execute these capabilities. | Resource starts / materializations | 1 / 1 per frame | | Tile collection | 40 entries, two view owners | | Tile demand per view | 24 addresses (up to 12 visible + 12 local look-ahead; OSM extras capped at four) | -| Native image staging | 8 × 131,088 bytes plus metadata | +| Shared image / mesh staging | 8 × 131,088 bytes plus metadata | | Native image envelope | 16–256px power-of-two sides, two bytes per pixel | -| Native image uploads | 1 per frame | +| Native image or mesh materializations | 1 per frame | | Places per search | 5 | | Saved places | 1,000 on Mac; four five-place pages cached on device | | Saved-place name | 36 UTF-16 code units | -| Marker resource cache | 12 windows; at most four demanded, 12 records per window | +| Label resource cache | 40 windows; at most 12 demanded, 12 records per window (Hyrule demands at most four) | | Query text | 80 UTF-16 code units | -| Unicode label collection | 5 × 256×32 images | +| Unicode label collection | 24 × 256×32 images; at most 12 map labels visible | | Mac concurrent tile decodes | 3 | +| Mac prepared geometry cache | 128 source tiles, honoring expiry | +| Native mesh entry | 4,096 vertices; 2,048 triangles; 36,880 wire bytes | +| Retained GPU geometry | 8 MiB including pending retirement; at most 196,608 bytes per mesh | | Mac decoded-image cache | 128 immutable atlas textures; 64 HTTP renditions honoring expiry | | Mac HTTP cache | 2,048 bounded responses in SQLite | | Mac transport credit | Eight total executing requests, queued replies and blocked writes | @@ -61,13 +64,17 @@ and 2,500-code-unit payload limits. layers' demand and reserves entry cost before starting an offload read. 3. The Mac looks up an already baked Hyrule texture in SQLite and decompresses it to exactly 131,072 bytes, or returns a decoded-cache hit. This provider has - no HTTP path. The optional OSM provider reads a cached PNG or fetches it with - HTTP validators, validates dimensions, decodes and packs R5G6B5 pixels. -4. The 3DS worker receives binary pixels into a free native slot and publishes + no HTTP path. The OSM provider reads or fetches an MVT using HTTP validators, + decodes PBF, applies a bounded detail policy and prepares indexed geometry. + Geometry at source z14 serves display levels through z18. +4. The 3DS worker receives binary pixels or geometry into a free native slot and publishes a small ticket. Socket reads pause when staging credit is exhausted. 5. The scheduler materializes one completed resource per frame. The native - upload consumes no JS pixel array; `ResourceImage` replaces its fallback. -6. `releaseResponse` returns staging credit. Texture disposal waits until + upload consumes no JS pixel or vertex array; `ResourceImage` or `ResourceMesh` + replaces its fallback. Mesh materialization also uploads an immutable GPU + buffer. Drawing submits a handle, transform and clip rectangle; eviction + frees the buffer after the preceding GPU frame retires. +6. `releaseResponse` returns staging credit. Texture / mesh disposal waits until cache eviction or invalidation with value removal. A cancelled or late response also returns staging credit without an upload. @@ -201,3 +208,5 @@ cache costs and view ownership. Names and category icons are drawn locally at constant screen size; only their transforms change during motion. No bitmap is requested for every label or every frame. Icon assets are compiled into the package. An annotation cache failure leaves terrain navigation available. + +The [vector map design](VECTOR_MAP.md) documents source selection, geometry format, label windows, GPU/CPU responsibilities and measured bandwidth. diff --git a/docs/VALIDATION.md b/docs/VALIDATION.md index 37c5b65..4baa8e9 100644 --- a/docs/VALIDATION.md +++ b/docs/VALIDATION.md @@ -159,3 +159,55 @@ for physical gesture or frame-time acceptance of this revision. The navigation build was uploaded and read back equal: 1,720,504 bytes; SHA-256 `348e614c1016fceb175d701bd3ae14294f817367f326d13493473488e16a1e2a`. The Mac daemon now exposes both maps through source-identified requests. + +## Vector OSM reconstruction + +The default OSM provider now uses Shortbread MVTs. Hyrule's existing raster +atlas, marker index, bookmarks and source switching remain available. See +[VECTOR_MAP.md](VECTOR_MAP.md) for the execution split and measurement scope. + +- 18 application tests / 161 assertions pass, including holes, clipping, + dense geometry, HTTP deduplication, overzoom source reuse and provider policy. +- Framework resource/offload regression: 64 tests / 682 assertions; the final + targeted image/mesh/offload suite also passes 22 tests / 140 assertions, + including the added consumer-exception cleanup case. +- Rust core: 131 tests pass, including malformed geometry, stale handles and + transformed/clipped TRI output. +- Synthetic MVT compiled-guest + Wasm replay: 1,403 frames, 13 checks; delayed + responses, disconnect, search, Hyrule raster switching and return to vector. +- Real San Francisco replay: 453 frames. Four MVTs become 107,464 wire bytes of + prepared geometry, versus 524,368 bytes for four old raw image records. + Additional display zooms z15–18 send zero terrain bytes; label JSON and Unicode + images remain separate traffic. Receipts include those costs. +- Existing complete-Hyrule compiled replay: 1,713 frames, 20 checks. +- QuickJS at 128 KiB stack: both startup modes pass 1,272 frames and release all + staging tickets. Wasm screenshots were inspected for geometry, holes, fixed-size + labels, CJK text and source switching. + +Native `.3dsx` builds pass with the pinned nightly and devkitPro image. These +checks establish build, protocol, resource and pixel behavior. Real 3DS input +and frame-time acceptance of the vector revision remain pending; Wasm CPU +numbers are not a hardware frame-rate claim. + +The vector build was deployed through ftpd and read back byte-for-byte equal: +1,736,564 bytes, SHA-256 +`2f33588ba2b1081f8c86146300b5210f39b1239fa155688c20f478d04bb64130`. +The Mac daemon starts OSM by default and keeps Hyrule available through the +source picker. Transfer verification does not establish physical interaction +or a measured frame rate. + +## Vector CPU baseline and retained GPU revision + +The first vector build was uploaded and connected to the physical device. +Although terrain bandwidth decreased, warm vector views often advanced only +40–60 frames per two-second telemetry interval. Many intervals recorded every +frame above 16.67 ms, including periods without new tile requests. This fails +the intended frame budget and is not evidence of continuous 60 fps. + +That build expanded and clipped every triangle on the CPU each frame. The +revised 3DS backend materializes immutable GPU buffers once and emits bounded +handle/transform/clip commands during navigation. Its telemetry splits UI/core, +frame preparation and submission durations. Core tests cover backend opt-in, +transform scaling, opacity fallback, off-screen culling and stale mesh handles. +The native build and app checks pass; physical timing of this revision remains +pending deployment and interaction. diff --git a/docs/VECTOR_MAP.md b/docs/VECTOR_MAP.md new file mode 100644 index 0000000..1b7499c --- /dev/null +++ b/docs/VECTOR_MAP.md @@ -0,0 +1,182 @@ +# OSM vector maps on 3DS + +## Data and execution + +**OSM now uses Shortbread vector tiles. Hyrule retains its complete raster atlas.** +The default endpoint is VersaTiles' public OSM service; the URL and source settings +live in the Mac provider configuration. The previous OSM route fetched PNGs and +sent a 256×256 R5G6B5 plane: 131,072 pixel bytes per tile. The new route fetches +MVT/PBF, prepares indexed geometry on the Mac and sends a bounded binary mesh. + +```mermaid +flowchart LR + OSM[Shortbread MVT] --> HTTP[Mac HTTP cache in SQLite] + HTTP --> Prep[Mac PBF decode, style, simplify, triangulate] + Prep --> Mesh[Prepared geometry cache] + Mesh --> Wire[Bounded offload staging] + Atlas[Local Hyrule raster atlas] --> Wire + Wire --> Resources[PocketJS resource collections] + Resources --> Core[Native immutable mesh buffers or textures] + Core --> GPU[3DS GPU transforms, clipping and rasterization] + Mesh --> Labels[Bounded label windows] + Labels --> Text[Local glyph atlas and Unicode image fallback] +``` + +The UI JavaScript thread updates the camera, resource demand and UI controls. +The 3DS native worker handles socket reception and validates binary envelopes. +The Mac capability process performs PBF decoding, geometry simplification, +polygon tessellation, HTTP, SQLite and Unicode text rendering. This follows the +worker/bucket separation in [Mapbox GL JS's architecture](https://github.com/mapbox/mapbox-gl-js/blob/main/ARCHITECTURE.md): +GPU drawing consumes prepared geometry; the GPU does not parse protobuf. + +**No extra JavaScript thread or device-side PBF parser is required.** The current +3DS worker uses lower priority and libctru affinity `-2`, rather than assuming +all New 3DS cores are available to applications. Moving the Mac preparation +stage into another native device worker is a future host implementation choice; +it does not change the guest resource API. + +## What carries over from Google Maps 5.0 + +Google's [December 2010 engineering article](https://googleblog.blogspot.com/2010/12/under-hood-of-google-maps-50-for.html) +describes geometry reuse across zoom and viewing angles, independently placed +labels, and offline caching. Its “100 times” comparison concerns viewing maps +across all zoom levels. It is not a promised ratio for one MVT or one prepared +mesh. + +Pocket Map implements these relevant parts: + +- Quantized coordinates and indexed triangles replace raster tile transmission. +- The device applies local pan/zoom transforms to resident geometry. +- **Source geometry at z14 is reused through display z18.** New high-zoom label + windows query the already prepared source tile and place road names on the + visible part of each line. They do not fetch another MVT. +- Lower source levels remain separate resources; a previous ready level stays + behind incoming content while zooming. +- Same-level directional look-ahead retains travel direction across gestures. + Public VersaTiles requests remain bounded to four extra tiles; the complete + Hyrule atlas permits twelve, including the next zoom level after zoom-in. +- Geometry, label windows and Unicode fallbacks share the resource scheduler. + +This is a 2D street map renderer. It does not implement Google/Mapbox's full +style engine, 3D buildings, routing, terrain, line-following rotated text or +arbitrary zoom-dependent style expressions. Prepared road widths scale with the +geometry. Dense tiles reduce minor detail to fit the device budget, so the +result is not visually identical to the previous server-rendered PNG. + +## Text + +**ASCII map labels use the existing shared baked glyph atlas.** Their positions +follow the map while their font size stays fixed. The guest chooses at most +12 visible labels, deduplicates names, avoids overlapping rectangles and keeps +already visible labels stable where possible. + +Names outside the baked font repertoire use a separately cached 256×32 label +image with a skeleton fallback. The Mac explicitly selects a CJK font when +needed. This preserves readable multilingual names without baking labels into +every map tile. Dynamic Unicode glyph pages are not implemented in this change. + +Mapbox's [text rendering design](https://github.com/mapbox/mapbox-gl-native/wiki/Text-Rendering) +uses a glyph atlas and signed distance fields. The current PICA200 backend uses +fixed fragment combiners; its programmable vertex shader does not provide the +fragment shader needed to copy Mapbox's SDF approach directly. Baked coverage +fonts are the applicable atlas path here. + +## Bounds and ownership + +| Stage | Bound | +| --- | --- | +| MVT response body | 2 MiB, in the Mac process | +| Considered source geometry | 200,000 points; 20,000 features per layer | +| Prepared entry | 4,096 vertices, 2,048 triangles, 36,880 bytes | +| Coordinates | Unsigned 1/16 logical pixels, inside the declared rectangle | +| Mac prepared cache | 128 source tiles, honoring HTTP expiry | +| Device geometry cache | 40 entries, two demand owners | +| Shared resource requests | 3 active, one start and one completion per frame | +| Shared native staging | Eight slots for images and meshes together | +| Materialization | One image or mesh per frame | +| Label windows | 40 cached; up to 12 demanded, at most 12 rows per reply | +| Visible labels | 12, with bounded overlap checks | +| Native mesh handles | 128 slots; generation-tagged, separate from textures | +| Retained 3DS mesh buffers | 8 MiB, including buffers awaiting GPU retirement | +| 3DS immediate vertex arena | 65,536 vertices shared by both screens | + +The provider triangulates complete polygons, preserving holes, then clips the +result. Coarser detail passes simplify complete shapes and omit minor layers; +they do not transmit an arbitrary triangle prefix. Invalid indices, coordinates, +versions or byte counts are rejected before acquiring native mesh residency. + +`createOffloadMeshCollection` owns materialization and eviction. `ResourceMesh` +borrows the handle and declares its fallback. Cancelled sent work retains its +wire credit until a response or disconnect; late responses release staging. +Meshes and images have the same lifecycle but separate native handle tables. + +**3DS mesh materialization uploads an immutable GPU vertex buffer once.** +Opaque mesh Views emit ten words per visible tile: its generation-tagged handle, +affine transform and clip rectangle. PICA transforms and clips the resident +vertices. Camera motion does not expand triangles into the immediate vertex +arena. Uploads share the one-per-frame image/mesh completion budget and fail +through the resource retry path if the buffer cannot be allocated. + +Replacing or evicting a resource cannot free memory still referenced by the +previous GPU frame. The backend retires these buffers after `C3D_FrameBegin` +confirms that frame has completed. Wasm and other existing backends retain the +CPU-clipped TRI path; 3DS also uses it for translucent mesh Views. The limits +bound work; device timing remains a separate validation gate. + +## Provider configuration + +The default [VersaTiles service](https://docs.versatiles.org/guides/use_tiles_versatiles_org.html) +uses `https://tiles.versatiles.org/tiles/osm/{z}/{x}/{y}`. Set a different +Shortbread endpoint in ignored `.local/provider.json` without rebuilding the +3DS application: + +```json +{ + "format": "vector", + "tileURL": "https://vector.openstreetmap.org/shortbread_v1/{z}/{x}/{y}.mvt", + "dataZoom": 14, + "maxZoom": 18, + "name": "OpenStreetMap" +} +``` + +Restart the daemon after changing its configuration. Source identity includes +the endpoint and prepared style revision, preventing old resources from being +mixed with a new source. HTTP requests identify Pocket Map, preserve validators +and honor cache expiry. When using `vector.openstreetmap.org`, predictive HTTP +downloads are disabled to follow its [vector tile policy](https://operations.osmfoundation.org/policies/vector/). +For regional offline use, obtain a licensed regional tile archive through a +provider's supported download workflow; do not scrape the public endpoint. + +## Measurements and reproduction + +A compiled guest + Wasm replay viewed four real San Francisco tiles at z14, +then zoomed through z18 and returned. The MVTs and receipts stay under ignored +`.local/` and `dist/qa/`; screenshots in `docs/images/` are curated captures. + +| Quantity | Measured | +| --- | --- | +| Four prepared mesh records, including wire headers | 107,464 bytes | +| Four equivalent old raw raster records | 524,368 bytes | +| Terrain byte reduction | 79.5% | +| Additional terrain transfers for z15–18 | 0 | + +Label-window JSON and occasional Unicode images are additional traffic. See +`dist/qa/vector-live.json` for these totals. Synthetic replay figures are not +used as a real-world compression ratio. Wasm software raster times do not +measure PICA200 performance or real 3DS frame rate. + +```sh +bun run check +bun run 3ds +bun scripts/vector-sim.ts # generated MVTs, delayed replies, disconnects +bun scripts/vector-sim.ts --live # a small real viewport, persistent HTTP cache +bun scripts/sim.ts --hyrule # complete real local atlas regression +qjs --std --stack-size 131072 scripts/quickjs-smoke.js runtime/dist/3ds/guest/pocketmap-main.js +``` + +Framework validation covers native socket transfer in both thread and process +provider modes, maximum-size geometry, malformed/truncated data, stale handles, +shared staging credit, cancellation, failed uploads, polygon clipping and +resource cleanup. Pocket Map tests cover polygon holes, dense-tile detail +reduction, source routing, label/geometry deduplication and source/display LOD. diff --git a/docs/images/vector-osm.png b/docs/images/vector-osm.png new file mode 100644 index 0000000000000000000000000000000000000000..98f71cd0ed60129fe1b5ba1f7b230ebc5c3dd0fe GIT binary patch literal 35442 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 KelF{r5}E+Yn!nNj literal 0 HcmV?d00001 diff --git a/docs/images/vector-zoom.png b/docs/images/vector-zoom.png new file mode 100644 index 0000000000000000000000000000000000000000..259a59778fd3e19405cc5f9fc6bbbc47db50bbc0 GIT binary patch literal 25684 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⩔#qF-;)c1-YWr;A}P?d2vSpgMU}LewEf+ zkj}z}pex~(A*hA3EPI6x+kl1}eg}x;PJvWf*AQQ6C+@$+8IO?DcjE8j8sE24i?;?D zPKcCH&-=(=X}~gpFV~17&LKg;=pmm(2Jt#ikKE20fdZDNyxu?t|j`N z#jlfkHJ8zj=aM6O`2JxMKH|B`%lYj?ZReB@cAGNzLZ*3TSpR##IY8&Bst z4&u;C7ntN9p`O+FAmv}B^ye#Odc@Ral8TsiUIE0P&KVvD-{nK8Qt=YSc(L=!%sk%{ zYzvqO4`w_wjf$9YT2`%hF^?m&q&~Y-+5QGac*3-LI3UAZUJbYLI+}BPXQfGTbZyBu ze!#evd;Ev&^=K0=HJf@pVEZgR@@&214IEzL^T?|Kxysd$(o zVRS#!g9+6AIy6;X@vYlOH>(Ma{A324Iv0;)LmG6VvWxfL1t;-K!-eb9m>^t|*SYc2%oev6m%h5Kb@_(JTLEg$SX!7QG z-UFpOvM7ZViMg~ixvQ)oNoX-z=@Og)tO7a zi7+`ORKJ(eQYtzwZy+0i0P@L$VMpExGso6jV6jZQvHIZ{Yi;$v&oQ z#!c_tXXSpAG>#QOxk^RbmBv+>Pb&+d4+FM;8{c}-XI8QG{sZOXXRcj}%x?9a14&)K zh?7GV)J=Wl|Jr$_#Vy~b!$?<#W50Jqxn!BVJiD4w&L3UF@Aja9$3f0j((w>%A+nP5 z5f4{U5@dfrQoFqelP}+0yb|^&a-zs`uB3B-3Y}jq&yt9Y0ZkH2 z#?8@o$z#B5dnpq?VMP)K86u8tHFDYbnfz$=$+$RR5PTS!usrUb5uTzmbwM)8u3rIb ze`jusEZ4l9lGCd0iPso*#QaAg?^NEC&ph!)6^rj>s_bZ1Z6+LNdaF}oS0$5rIc#8V zO+;b2-%H&%svM&4nnDU3eki}!vzNA#F!|Q)wGv5~kL+&vGwfT+ab3S@=})&*2hwDECcMwr10kf1qhK@6H^GAvwf1U)9%Y zZacg9F3b9Y6QIN;?*U5OeGH()jrho#$2r|Urh2TC|9kP`Ekwi?Kc)e7ph$3pp zjbq9F>5Ca1voda@Jnl>;fPxo(-RSg8xIb=tzDqG(0<6c+(25V@ z{XAREw~9(dETz`p^j^;C8r*3CYS5|!Z0Sqyg`IVRht zx0~jQbd~5V?YZMK`nlrwysHiQXRLQSj`$UZXy|KC1V+-UUD`@8hV>H9S+{~Hv%$KhUA17)vu4@}e>^-6U2njY#Nxc#?bSZ-Xb}PIhnGSx8 z>80j-TT!5w%CmlWd-GBCde0@CDE7De0%$ei- zvI1Qz-bP2})rBTM6bKU`rd^7g2$d^+;rrgqaF&O;y3nnl=58J!i~jwy<@&&DV4e5! z)F0>H+hIZym6;tOLf)03qF=L_nX<_}q7U%v^mI$1^ipHxcA`5Fk6!H!0a02K9rH!1 z*V`#qL$Y6R8*Q{j&d*+~#CUy`T+cjq%1cmMEm@bjS#1ouIY#PWyX!7b@nz-zZTjtQ zQEacj8{Y6*;pTS3drx=@GmL8uyMT4@f&dQf>pH-ucexU)6cY z0MgivyGPxWS9bFE=oBgm>9~s*H1e6D_e6L2byjpa`?J{AE7F zrz|{1`@1(ycM9OV9g`(o!iTL0C+EpvJ{-GQ86VOUWQvy#SMB$U5Jr18n%Zl;zU;p8kii*?un zH@zyi&bmD$rM~6!`3o{oi_0%mia|Hx-XL|GF#KO+N*@RvI(OeD>Epk@zvF^ZIN<(* zXHN now && row.bytes.byteLength <= options.maxBytes) { this.hits++; this.db.query("UPDATE http SET touched=? WHERE url=?").run(now, url); return row.bytes; } - const headers: Record = { "User-Agent": "PocketMap/0.1 (+https://github.com/pocket-stack/pocket-map)", "Accept": "image/png,application/json" }; + const headers: Record = { "User-Agent": "PocketMap/0.1 (+https://github.com/pocket-stack/pocket-map)", "Accept": "application/vnd.mapbox-vector-tile,application/x-protobuf,image/png,application/json" }; if (row?.etag) headers["If-None-Match"] = row.etag; if (row?.modified) headers["If-Modified-Since"] = row.modified; // Bun's redirect:error rejects 304 as well. Manual mode preserves cache diff --git a/host/config.ts b/host/config.ts index e77e4c6..a867d07 100644 --- a/host/config.ts +++ b/host/config.ts @@ -1,5 +1,5 @@ -export interface ProviderConfig { tileURL: string; searchURL: string; name: string; attribution: string; maxZoom: number; cache: string; kind?: "osm" | "hyrule"; atlas?: string } +export interface ProviderConfig { tileURL: string; format?: "raster" | "vector"; dataZoom?: number; searchURL: string; name: string; attribution: string; maxZoom: number; cache: string; kind?: "osm" | "hyrule"; atlas?: string } export const defaultConfig: ProviderConfig = { - tileURL: "https://tile.openstreetmap.de/{z}/{x}/{y}.png", searchURL: "https://photon.komoot.io/api/", - name: "OpenStreetMap DE", attribution: "OpenStreetMap contributors", maxZoom: 18, cache: ".local/cache.sqlite", + tileURL: "https://tiles.versatiles.org/tiles/osm/{z}/{x}/{y}", format: "vector", dataZoom: 14, searchURL: "https://photon.komoot.io/api/", + name: "OpenStreetMap", attribution: "OpenStreetMap contributors", maxZoom: 18, cache: ".local/cache.sqlite", }; diff --git a/host/provider.ts b/host/provider.ts index 111dbd7..cabf70b 100644 --- a/host/provider.ts +++ b/host/provider.ts @@ -1,6 +1,7 @@ import { createHash } from "node:crypto"; import { createCanvas, loadImage } from "@napi-rs/canvas"; -import type { OffloadImage } from "@pocketjs/framework/offload/provider"; +import type { OffloadImage, OffloadMesh } from "@pocketjs/framework/offload/provider"; +import { prepareVector, labelsInWindow, type PreparedTile } from "./vector-geometry.ts"; import { HttpCache, type NetworkFetch } from "./cache.ts"; import { Bookmarks } from "./bookmarks.ts"; import { join, dirname } from "node:path"; @@ -17,7 +18,8 @@ export function packRGB(rgba: Uint8ClampedArray | Uint8Array, width: number, hei const g = Math.round(rgba[i * 4 + 1] * alpha + 255 * (1 - alpha)); const b = Math.round(rgba[i * 4 + 2] * alpha + 255 * (1 - alpha)); const rgb = (r >> 3) | ((g >> 2) << 5) | ((b >> 3) << 11); - pixels[i * 2] = rgb & 255; pixels[i * 2 + 1] = rgb >> 8; + pixels[i * 2] = rgb & 255; + pixels[i * 2 + 1] = rgb >> 8; } return { width, height, pixels, format: "r5g6b5" }; } @@ -27,80 +29,289 @@ export class MapProvider { readonly bookmarks: Bookmarks; private decoded = new Map(); private loading = new Map>(); + private vectors = new Map(); + private preparing = new Map>(); + private meshBytes = 0; private searching = false; private nextSearch = 0; - constructor(readonly config: ProviderConfig, network: NetworkFetch = fetch) { - for (const url of [config.tileURL, config.searchURL]) if (new URL(url).protocol !== "https:" && !/^http:\/\/(localhost|127\.0\.0\.1)(:|\/)/.test(url)) throw new Error("Use HTTPS or a local provider"); - if (!["{z}", "{x}", "{y}"].every(part => config.tileURL.includes(part)) || !Number.isInteger(config.maxZoom) || config.maxZoom < 1 || config.maxZoom > 18) throw new Error("Invalid tile source"); - this.info = { source: createHash("sha256").update(JSON.stringify([config.tileURL, "r5g6b5-v1"])).digest("hex").slice(0, 16), name: config.name.slice(0, 40), attribution: config.attribution.slice(0, 100), maxZoom: config.maxZoom }; + constructor( + readonly config: ProviderConfig, + network: NetworkFetch = fetch, + ) { + for (const url of [config.tileURL, config.searchURL]) + if (new URL(url).protocol !== "https:" && !/^http:\/\/(localhost|127\.0\.0\.1)(:|\/)/.test(url)) + throw new Error("Use HTTPS or a local provider"); + if ( + !["{z}", "{x}", "{y}"].every((part) => config.tileURL.includes(part)) || + !Number.isInteger(config.maxZoom) || + config.maxZoom < 1 || + config.maxZoom > 18 + ) + throw new Error("Invalid tile source"); + if ( + config.format === "vector" && + (!Number.isInteger(config.dataZoom ?? 14) || (config.dataZoom ?? 14) < 0 || (config.dataZoom ?? 14) > 14) + ) + throw new Error("Invalid vector source zoom"); + this.info = { + source: createHash("sha256") + .update(JSON.stringify([config.tileURL, config.format === "vector" ? "mesh-shortbread-v1" : "r5g6b5-v1"])) + .digest("hex") + .slice(0, 16), + name: config.name.slice(0, 40), + attribution: config.attribution.slice(0, 100), + maxZoom: config.maxZoom, + ...(config.format === "vector" + ? { + render: "mesh" as const, + dataZoom: config.dataZoom ?? 14, + markers: true, + prefetch: new URL(config.tileURL).hostname !== "vector.openstreetmap.org", + } + : {}), + }; this.cache = new HttpCache(config.cache, network); - this.bookmarks = new Bookmarks(config.cache === ":memory:" ? ":memory:" : join(dirname(config.cache), "places.sqlite")); + this.bookmarks = new Bookmarks( + config.cache === ":memory:" ? ":memory:" : join(dirname(config.cache), "places.sqlite"), + ); + } + methods() { + return { + "map.info": () => JSON.stringify(this.info), + "map.mesh": (raw: string) => this.mesh(JSON.parse(raw)), + "map.markers": async (raw: string) => JSON.stringify(await this.markerRows(JSON.parse(raw))), + "map.tile": (raw: string) => this.tile(JSON.parse(raw)), + "map.search": async (raw: string) => JSON.stringify(await this.search(JSON.parse(raw))), + "map.label": (raw: string) => this.label(JSON.parse(raw)), + "bookmarks.list": (raw: string) => JSON.stringify(this.bookmarks.list(JSON.parse(raw).offset)), + "bookmarks.command": (raw: string) => this.bookmarks.command(JSON.parse(raw)), + }; } - methods() { return { - "map.info": () => JSON.stringify(this.info), - "map.tile": (raw: string) => this.tile(JSON.parse(raw)), - "map.search": async (raw: string) => JSON.stringify(await this.search(JSON.parse(raw))), - "map.label": (raw: string) => this.label(JSON.parse(raw)), - "bookmarks.list": (raw: string) => JSON.stringify(this.bookmarks.list(JSON.parse(raw).offset)), - "bookmarks.command": (raw: string) => this.bookmarks.command(JSON.parse(raw)), - }; } tile(input: TileInput): Promise { + if (this.config.format === "vector") return Promise.reject(new Error("Use map.mesh for this vector source")); const { source, z, x, y } = input; - if (source !== this.info.source || ![z, x, y].every(Number.isInteger) || z < 0 || z > this.config.maxZoom || x < 0 || x >= 2 ** z || y < 0 || y >= 2 ** z) return Promise.reject(new Error("Invalid tile address or source")); - const key = `${z}/${x}/${y}`, hit = this.decoded.get(key); - if (hit && hit.expires > Date.now()) { this.decoded.delete(key); this.decoded.set(key, hit); return Promise.resolve(hit.image); } - const pending = this.loading.get(key); if (pending) return pending; + if ( + source !== this.info.source || + ![z, x, y].every(Number.isInteger) || + z < 0 || + z > this.config.maxZoom || + x < 0 || + x >= 2 ** z || + y < 0 || + y >= 2 ** z + ) + return Promise.reject(new Error("Invalid tile address or source")); + const key = `${z}/${x}/${y}`, + hit = this.decoded.get(key); + if (hit && hit.expires > Date.now()) { + this.decoded.delete(key); + this.decoded.set(key, hit); + return Promise.resolve(hit.image); + } + const pending = this.loading.get(key); + if (pending) return pending; if (this.loading.size >= 3) return Promise.reject(new Error("Tile decode budget exhausted")); const url = this.config.tileURL.replace("{z}", String(z)).replace("{x}", String(x)).replace("{y}", String(y)); const work = this.decode(url) - .then(image => { this.decoded.set(key, { image, expires: this.cache.expires(url) }); if (this.decoded.size > 64) this.decoded.delete(this.decoded.keys().next().value!); return image; }) + .then((image) => { + this.decoded.set(key, { image, expires: this.cache.expires(url) }); + if (this.decoded.size > 64) this.decoded.delete(this.decoded.keys().next().value!); + return image; + }) .finally(() => this.loading.delete(key)); - this.loading.set(key, work); return work; + this.loading.set(key, work); + return work; + } + private vector(input: TileInput): Promise { + const { source, z, x, y } = input; + if ( + this.config.format !== "vector" || + source !== this.info.source || + ![z, x, y].every(Number.isInteger) || + z < 0 || + z > (this.config.dataZoom ?? 14) || + x < 0 || + y < 0 || + x >= 2 ** z || + y >= 2 ** z + ) + return Promise.reject(new Error("Invalid vector tile address or source")); + const key = `${z}/${x}/${y}`, + hit = this.vectors.get(key); + if (hit && hit.expires > Date.now()) { + this.vectors.delete(key); + this.vectors.set(key, hit); + return Promise.resolve(hit.value); + } + const pending = this.preparing.get(key); + if (pending) return pending; + if (this.preparing.size >= 3) return Promise.reject(new Error("Vector preparation budget exhausted")); + const url = this.config.tileURL.replace("{z}", String(z)).replace("{x}", String(x)).replace("{y}", String(y)); + const work = this.cache + .get(url, { maxBytes: 2 * 1024 * 1024, ttl: 7 * 86400_000 }) + .then((bytes) => { + const value = prepareVector(bytes, z); + this.meshBytes += value.mesh.bytes.length; + this.vectors.set(key, { value, expires: this.cache.expires(url) }); + if (this.vectors.size > 128) this.vectors.delete(this.vectors.keys().next().value!); + return value; + }) + .finally(() => this.preparing.delete(key)); + this.preparing.set(key, work); + return work; + } + async mesh(input: TileInput): Promise { + return (await this.vector(input)).mesh; + } + async markerRows(input: TileInput & { layer?: string }) { + if (this.config.format !== "vector" || input.layer === "off") return []; + if ( + ![input.z, input.x, input.y].every(Number.isInteger) || + input.z < 0 || + input.z > this.info.maxZoom || + input.x < 0 || + input.y < 0 || + input.x >= 2 ** input.z || + input.y >= 2 ** input.z + ) + throw new Error("Invalid label window"); + const dataZoom = Math.min(input.z, this.config.dataZoom ?? 14), + factor = 2 ** (input.z - dataZoom), + x = Math.floor(input.x / factor), + y = Math.floor(input.y / factor); + const tile = await this.vector({ ...input, z: dataZoom, x, y }), + scale = 2 ** dataZoom, + size = 256 / factor; + const labels = labelsInWindow(tile, input.z, (input.x % factor) * size, (input.y % factor) * size, size); + return labels.map((l, i) => [ + input.y * 2 ** input.z * 16 + input.x * 16 + i, + l.name, + "landmark", + (x * 256 + l.x) / scale, + (y * 256 + l.y) / scale, + ]); } + private async decode(url: string) { const bytes = await this.cache.get(url, { maxBytes: 512 * 1024, ttl: 7 * 86400_000 }); const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength); - if (bytes.length < 24 || view.getUint32(0) !== 0x89504e47 || view.getUint32(4) !== 0x0d0a1a0a || view.getUint32(12) !== 0x49484452 || view.getUint32(16) !== 256 || view.getUint32(20) !== 256) throw new Error("Expected a 256px PNG tile"); + if ( + bytes.length < 24 || + view.getUint32(0) !== 0x89504e47 || + view.getUint32(4) !== 0x0d0a1a0a || + view.getUint32(12) !== 0x49484452 || + view.getUint32(16) !== 256 || + view.getUint32(20) !== 256 + ) + throw new Error("Expected a 256px PNG tile"); const image = await loadImage(Buffer.from(bytes)); if (image.width !== 256 || image.height !== 256) throw new Error("Invalid decoded tile size"); - const canvas = createCanvas(256, 256), ctx = canvas.getContext("2d"); ctx.drawImage(image, 0, 0); + const canvas = createCanvas(256, 256), + ctx = canvas.getContext("2d"); + ctx.drawImage(image, 0, 0); return packRGB(ctx.getImageData(0, 0, 256, 256).data, 256, 256); } async search(input: SearchInput): Promise { - if (input.space === "planar" || typeof input.query !== "string" || input.query.length > 80 || !Number.isFinite(input.lat) || Math.abs(input.lat) > 90 || !Number.isFinite(input.lon) || Math.abs(input.lon) > 180) throw new Error("Invalid place search"); - const query = input.query.trim(); if (!query) return []; + if ( + input.space === "planar" || + typeof input.query !== "string" || + input.query.length > 80 || + !Number.isFinite(input.lat) || + Math.abs(input.lat) > 90 || + !Number.isFinite(input.lon) || + Math.abs(input.lon) > 180 + ) + throw new Error("Invalid place search"); + const query = input.query.trim(); + if (!query) return []; if (this.searching) throw new Error("A search is already running"); this.searching = true; try { // Explicit submits only, at most one outgoing search per second. - await Bun.sleep(Math.max(0, this.nextSearch - Date.now())); this.nextSearch = Date.now() + 1100; - const url = new URL(this.config.searchURL); url.searchParams.set("q", query); url.searchParams.set("limit", "5"); url.searchParams.set("lang", "en"); - url.searchParams.set("lat", input.lat.toFixed(1)); url.searchParams.set("lon", input.lon.toFixed(1)); + await Bun.sleep(Math.max(0, this.nextSearch - Date.now())); + this.nextSearch = Date.now() + 1100; + const url = new URL(this.config.searchURL); + url.searchParams.set("q", query); + url.searchParams.set("limit", "5"); + url.searchParams.set("lang", "en"); + url.searchParams.set("lat", input.lat.toFixed(1)); + url.searchParams.set("lon", input.lon.toFixed(1)); const bytes = await this.cache.get(url.toString(), { maxBytes: 64 * 1024, ttl: 86400_000 }); const result = JSON.parse(new TextDecoder().decode(bytes)); if (!Array.isArray(result.features)) throw new Error("Invalid search response"); - const seen = new Set(), places: Place[] = []; + const seen = new Set(), + places: Place[] = []; for (const feature of result.features.slice(0, 5)) { - const p = feature.properties, xy = feature.geometry?.coordinates; - if (!p || typeof p.name !== "string" || !Array.isArray(xy) || !xy.slice(0, 2).every(Number.isFinite) || Math.abs(xy[0]) > 180 || Math.abs(xy[1]) > 90) continue; + const p = feature.properties, + xy = feature.geometry?.coordinates; + if ( + !p || + typeof p.name !== "string" || + !Array.isArray(xy) || + !xy.slice(0, 2).every(Number.isFinite) || + Math.abs(xy[0]) > 180 || + Math.abs(xy[1]) > 90 + ) + continue; const id = `${String(p.osm_type).slice(0, 1)}${String(p.osm_id).slice(0, 20)}`; - if (seen.has(id)) continue; seen.add(id); - const detail = [...new Set([p.street, p.city, p.state, p.country].filter(n => typeof n === "string" && n !== p.name))].join(", ").slice(0, 60); - places.push({ id, name: p.name.slice(0, 36), detail, lon: xy[0], lat: xy[1], zoom: ["city", "town", "village", "state", "country"].includes(p.type) ? p.type === "country" ? 5 : 13 : 16 }); + if (seen.has(id)) continue; + seen.add(id); + const detail = [ + ...new Set([p.street, p.city, p.state, p.country].filter((n) => typeof n === "string" && n !== p.name)), + ] + .join(", ") + .slice(0, 60); + places.push({ + id, + name: p.name.slice(0, 36), + detail, + lon: xy[0], + lat: xy[1], + zoom: ["city", "town", "village", "state", "country"].includes(p.type) ? (p.type === "country" ? 5 : 13) : 16, + }); } return places; - } finally { this.searching = false; } + } finally { + this.searching = false; + } + } + label(input: { name: string; detail: string }) { + return renderLabel(input); + } + diagnostics() { + return { + httpHits: this.cache.hits, + downloads: this.cache.downloads, + meshBytes: this.meshBytes, + prepared: this.vectors.size, + }; + } + close() { + this.cache.close(); + this.bookmarks.close(); } - label(input: { name: string; detail: string }) { return renderLabel(input); } - diagnostics() { return { httpHits: this.cache.hits, downloads: this.cache.downloads }; } - close() { this.cache.close(); this.bookmarks.close(); } } export function renderLabel(input: { name: string; detail: string }) { - if (typeof input.name !== "string" || input.name.length > 80 || typeof input.detail !== "string" || input.detail.length > 120) throw new Error("Invalid label"); - const canvas = createCanvas(256, 32), c = canvas.getContext("2d"); - c.fillStyle = "#f7f9fc"; c.fillRect(0, 0, 256, 32); - c.fillStyle = "#263748"; c.font = "bold 13px Arial"; c.fillText(input.name, 5, 13, 246); - c.fillStyle = "#627387"; c.font = "11px Arial"; c.fillText(input.detail, 5, 28, 246); - return packRGB(c.getImageData(0, 0, 256, 32).data, 256, 32); - } + if ( + typeof input.name !== "string" || + input.name.length > 80 || + typeof input.detail !== "string" || + input.detail.length > 120 + ) + throw new Error("Invalid label"); + const canvas = createCanvas(256, 32), + c = canvas.getContext("2d"); + c.fillStyle = "#f7f9fc"; + c.fillRect(0, 0, 256, 32); + const family = /[\u3000-\u9fff]/.test(input.name + input.detail) + ? '"Hiragino Sans GB", "Noto Sans CJK SC", sans-serif' + : "Arial, sans-serif"; + c.fillStyle = "#263748"; + c.font = `bold 13px ${family}`; + c.fillText(input.name, 5, 13, 246); + c.fillStyle = "#627387"; + c.font = `11px ${family}`; + c.fillText(input.detail, 5, 28, 246); + return packRGB(c.getImageData(0, 0, 256, 32).data, 256, 32); +} diff --git a/host/serve.ts b/host/serve.ts index ba26b29..53f5c28 100644 --- a/host/serve.ts +++ b/host/serve.ts @@ -4,7 +4,8 @@ import { defaultConfig } from "./config.ts"; const root = resolve(import.meta.dir, ".."); const address = process.argv.slice(2).find(arg => !arg.startsWith("--")) ?? "192.168.8.102"; const configPath = resolve(root, ".local/provider.json"); -const config = { ...defaultConfig, ...(await Bun.file(configPath).exists() ? await Bun.file(configPath).json() : {}), cache: resolve(root, ".local/cache.sqlite") }; +const overrides = await Bun.file(configPath).exists() ? await Bun.file(configPath).json() : {}; +const config = { ...defaultConfig, ...overrides, format: overrides.format ?? (overrides.tileURL?.endsWith(".png") ? "raster" : defaultConfig.format), cache: resolve(root, ".local/cache.sqlite") }; config.kind = process.argv.includes("--osm") ? "osm" : process.argv.includes("--hyrule") ? "hyrule" : config.kind ?? "hyrule"; config.atlas = resolve(root, ".local/hyrule"); if (config.kind === "hyrule" && !await Bun.file(resolve(config.atlas, "atlas.sqlite")).exists()) throw new Error("Run bun run prepare:hyrule before starting the Hyrule host"); diff --git a/host/service.ts b/host/service.ts index 86e5415..5ed71b6 100644 --- a/host/service.ts +++ b/host/service.ts @@ -28,10 +28,11 @@ export class MapService { if (!p) throw new Error("Map is not installed on your Mac"); return JSON.stringify({ ...p.info, kind, maps: [...this.providers].map(([kind, p]) => ({ kind, name: p.info.name })) }); }, + "map.mesh": (raw:string) => {const v=JSON.parse(raw),p=this.resolve(v.source);if(!(p instanceof MapProvider))throw new Error("This source uses raster tiles");return p.mesh(v);}, "map.tile": (raw: string) => { const v = JSON.parse(raw); return this.resolve(v.source).tile(v); }, "map.search": async (raw: string) => { const v = JSON.parse(raw); return JSON.stringify(await this.resolve(v.source).search(v)); }, "map.label": (raw: string) => this.resolve().methods()["map.label"](raw), - "map.markers": (raw: string) => { const v = JSON.parse(raw), p = this.resolve(v.source); return JSON.stringify(p instanceof AtlasProvider ? p.markerRows(v) : []); }, + "map.markers": async (raw: string) => { const v = JSON.parse(raw), p = this.resolve(v.source); return JSON.stringify(await p.markerRows(v)); }, "bookmarks.list": (raw: string) => { const v = JSON.parse(raw); return JSON.stringify(this.resolve(v.source).bookmarks.list(v.offset)); }, "bookmarks.command": (raw: string) => { const v = JSON.parse(raw); return this.resolve(v.source).bookmarks.command(v); }, }; } diff --git a/host/vector-geometry.ts b/host/vector-geometry.ts new file mode 100644 index 0000000..d257320 --- /dev/null +++ b/host/vector-geometry.ts @@ -0,0 +1,405 @@ +import { VectorTile, classifyRings, type VectorTileFeature } from "@mapbox/vector-tile"; +import { PbfReader } from "pbf"; +import earcut from "earcut"; +import { prepareMesh, type OffloadMesh } from "@pocketjs/framework/offload/provider"; +export type Point = { x: number; y: number }; +export interface VectorLabel { + name: string; + x: number; + y: number; + rank: number; + maxZoom: number; + path?: Point[]; +} +export interface PreparedTile { + mesh: OffloadMesh; + labels: VectorLabel[]; + triangles: number; + vertices: number; + simplified: number; +} +const color = (hex: number) => (0xff000000 | ((hex & 255) << 16) | (hex & 0xff00) | (hex >>> 16)) >>> 0; +const LAND = color(0xf0ede3), + WATER = color(0xa6cddd), + PARK = color(0xc0d4ab), + BUILDING = color(0xd8d2c6), + ROAD = color(0xfffdf7), + EDGE = color(0xc7bfae), + MAIN = color(0xf5cf83); +/** Quantize shared coordinates once; clip triangles AFTER tessellation so holes + * retain their topology, including polygons crossing the tile boundary. */ +export class MeshBuilder { + points: [number, number][] = []; + faces: [number, number, number, number][] = []; + private indices = new Map(); + triangle(a: Point, b: Point, c: Point, fill: number) { + let poly = [a, b, c]; + for (const [axis, bound, le] of [ + ["x", 0, false], + ["x", 256, true], + ["y", 0, false], + ["y", 256, true], + ] as const) { + const next: Point[] = []; + for (let i = 0; i < poly.length; i++) { + const p = poly[i], + q = poly[(i + 1) % poly.length], + d = p[axis] - bound, + e = q[axis] - bound, + ip = le ? d <= 0 : d >= 0, + iq = le ? e <= 0 : e >= 0; + if (ip) next.push(p); + if (ip !== iq) { + const t = d / (d - e); + next.push({ x: p.x + (q.x - p.x) * t, y: p.y + (q.y - p.y) * t }); + } + } + poly = next; + if (poly.length < 3) return; + } + const ids = poly.map((p) => { + const x = Math.max(0, Math.min(4096, Math.round(p.x * 16))), + y = Math.max(0, Math.min(4096, Math.round(p.y * 16))), + key = `${x}/${y}`; + let id = this.indices.get(key); + if (id === undefined) { + id = this.points.length; + this.points.push([x, y]); + this.indices.set(key, id); + } + return id; + }); + for (let i = 1; i < ids.length - 1; i++) { + const [p, q, r] = [this.points[ids[0]], this.points[ids[i]], this.points[ids[i + 1]]]; + if ((q[0] - p[0]) * (r[1] - p[1]) !== (q[1] - p[1]) * (r[0] - p[0])) + this.faces.push([ids[0], ids[i], ids[i + 1], fill]); + } + } + polygon(rings: Point[][], fill: number) { + const coords: number[] = [], + holes: number[] = []; + for (const ring of rings) { + if (coords.length) holes.push(coords.length / 2); + for (const p of ring) coords.push(p.x, p.y); + } + const indices = earcut(coords, holes, 2); + for (let i = 0; i < indices.length; i += 3) { + const p = (n: number) => ({ x: coords[n * 2], y: coords[n * 2 + 1] }); + this.triangle(p(indices[i]), p(indices[i + 1]), p(indices[i + 2]), fill); + } + } + line(points: Point[], width: number, fill: number) { + // Bounded miter joins share vertices; no gaps at segment junctions. + if (points.length < 2) return; + const left: Point[] = [], + right: Point[] = []; + const normal = (a: Point, b: Point) => { + const dx = b.x - a.x, + dy = b.y - a.y, + n = Math.hypot(dx, dy) || 1; + return { x: -dy / n, y: dx / n }; + }; + for (let i = 0; i < points.length; i++) { + const a = normal(points[Math.max(0, i - 1)], points[i]), + b = normal(points[i], points[Math.min(i + 1, points.length - 1)]); + let nx = a.x + b.x, + ny = a.y + b.y; + const len = Math.hypot(nx, ny) || 1; + nx /= len; + ny /= len; + const dot = Math.abs(nx * (i === 0 ? b.x : a.x) + ny * (i === 0 ? b.y : a.y)); + const half = (width * 0.5) / Math.max(0.5, dot); + left.push({ x: points[i].x + nx * half, y: points[i].y + ny * half }); + right.push({ x: points[i].x - nx * half, y: points[i].y - ny * half }); + } + for (let i = 1; i < points.length; i++) { + this.triangle(left[i - 1], right[i - 1], left[i], fill); + this.triangle(right[i - 1], right[i], left[i], fill); + } + } + entry(): OffloadMesh { + return prepareMesh({ + width: 256, + height: 256, + vertices: this.points.map(([x, y]) => [x / 16, y / 16]), + triangles: this.faces, + }); + } +} +function simplify(points: Point[], epsilon: number): Point[] { + if (points.length <= 3) return points; + // Iterative Douglas-Peucker: host work, no recursion proportional to geometry. + const keep = new Uint8Array(points.length); + keep[0] = keep[points.length - 1] = 1; + const work: [number, number][] = [[0, points.length - 1]]; + while (work.length) { + const [a, b] = work.pop()!, + p = points[a], + q = points[b], + dx = q.x - p.x, + dy = q.y - p.y, + len = dx * dx + dy * dy; + let best = epsilon * epsilon, + at = -1; + for (let i = a + 1; i < b; i++) { + const t = len ? Math.max(0, Math.min(1, ((points[i].x - p.x) * dx + (points[i].y - p.y) * dy) / len)) : 0; + const x = points[i].x - p.x - t * dx, + y = points[i].y - p.y - t * dy, + d = x * x + y * y; + if (d > best) { + best = d; + at = i; + } + } + if (at >= 0) { + keep[at] = 1; + work.push([a, at], [at, b]); + } + } + const result = points.filter((_, i) => keep[i]); + return result.length >= 3 + ? result + : points.length > 3 && points[0].x === points.at(-1)!.x && points[0].y === points.at(-1)!.y + ? points + : result; +} +type Feature = { + layer: string; + kind: string; + type: number; + rings: Point[][]; + polygons: Point[][][]; + properties: VectorTileFeature["properties"]; +}; +const AREAS = [ + "ocean", + "water_polygons", + "land", + "landcover", + "sites", + "buildings", + "street_polygons", + "pier_polygons", +]; +const LINES = ["water_lines", "boundaries", "streets", "pier_lines"]; +function roadWidth(kind: string, z: number) { + return /motorway|trunk/.test(kind) + ? 3.0 + : /primary|secondary/.test(kind) + ? 2.4 + : /tertiary/.test(kind) + ? 1.8 + : /residential|unclassified|service/.test(kind) + ? z >= 13 + ? 1.1 + : 0.65 + : 0.5; +} +export function prepareVector(bytes: Uint8Array, z: number): PreparedTile { + if (bytes.length > 2 * 1024 * 1024) throw new Error("Vector source body exceeds budget"); + const tile = new VectorTile(new PbfReader(bytes)), + features: Feature[] = [], + labels: VectorLabel[] = []; + let total = 0; + for (const [name, layer] of Object.entries(tile.layers)) { + if (![...AREAS, ...LINES, "place_labels", "street_labels", "pois"].includes(name)) continue; + if (layer.length > 20000) throw new Error("Vector feature budget exceeded"); + for (let i = 0; i < layer.length; i++) { + const f = layer.feature(i), + geometry = f.loadGeometry(); + total += geometry.reduce((n, r) => n + r.length, 0); + if (total > 200000) throw new Error("Vector point budget exceeded"); + if (!Number.isInteger(f.extent) || f.extent < 1 || f.extent > 65536) throw new Error("Invalid vector extent"); + const scale = 256 / f.extent, + rings = geometry.map((r) => r.map((p) => ({ x: p.x * scale, y: p.y * scale }))); + if ( + rings.some((r) => + r.some( + (p) => !Number.isFinite(p.x) || !Number.isFinite(p.y) || Math.abs(p.x) > 65536 || Math.abs(p.y) > 65536, + ), + ) + ) + throw new Error("Invalid vector coordinates"); + const kind = String(f.properties.kind ?? ""), + properties = f.properties; + if (name.includes("labels") || name === "pois") { + const text = String(properties["name:en"] ?? properties.name_en ?? properties.name ?? "") + .trim() + .slice(0, 24); + if (!text) continue; + const line = rings.reduce((a, b) => (a.length >= b.length ? a : b), [] as Point[]); + if (!line.length) continue; + let anchor = line[0]; + if (line.length > 1) { + let length = 0; + for (let j = 1; j < line.length; j++) + length += Math.hypot(line[j].x - line[j - 1].x, line[j].y - line[j - 1].y); + let remaining = length / 2; + for (let j = 1; j < line.length; j++) { + const a = line[j - 1], + b = line[j], + d = Math.hypot(b.x - a.x, b.y - a.y); + if (d >= remaining) { + const t = d ? remaining / d : 0; + anchor = { x: a.x + (b.x - a.x) * t, y: a.y + (b.y - a.y) * t }; + break; + } + remaining -= d; + } + } + if (name === "street_labels" || anchor.x >= 0 && anchor.x < 256 && anchor.y >= 0 && anchor.y < 256) + labels.push({ + name: text, + ...anchor, + rank: name === "place_labels" ? 0 : name === "street_labels" ? 2 : 4, + maxZoom: + name === "place_labels" + ? /country|state/.test(kind) + ? 10 + : /city/.test(kind) + ? 14 + : /town/.test(kind) + ? 16 + : 18 + : 18, + path: name === "street_labels" ? simplify(line, 0.15) : undefined, + }); + continue; + } + const polygons = + f.type === 3 + ? classifyRings(geometry).map((p) => p.map((r) => r.map((q) => ({ x: q.x * scale, y: q.y * scale })))) + : []; + features.push({ layer: name, kind, type: f.type, rings, polygons, properties }); + } + } + // Complete features at successively coarser detail; never cut an arbitrary + // triangle prefix which could erase a polygon's holes or half a road. + for (let detail = 0; detail < 6; detail++) { + const mesh = new MeshBuilder(); + mesh.polygon( + [ + [ + { x: 0, y: 0 }, + { x: 256, y: 0 }, + { x: 256, y: 256 }, + { x: 0, y: 256 }, + ], + ], + LAND, + ); + const epsilon = [0.25, 0.5, 1, 2, 3, 5][detail]; + for (const layer of AREAS) + for (const f of features.filter((f) => f.layer === layer)) { + if ( + (detail >= 2 && layer === "buildings") || + (detail >= 4 && ["sites", "street_polygons", "pier_polygons"].includes(layer)) + ) + continue; + const fill = /water|ocean/.test(layer) + ? WATER + : layer === "buildings" + ? BUILDING + : /park|wood|forest|grass|scrub|garden|farmland/.test(f.kind) + ? PARK + : layer === "sites" + ? color(0xe3dfcf) + : LAND; + for (const polygon of f.polygons) + mesh.polygon( + polygon.map((r) => simplify(r, epsilon)), + fill, + ); + } + const lines = features + .filter((f) => LINES.includes(f.layer)) + .sort((a, b) => roadWidth(a.kind, z) - roadWidth(b.kind, z)); + for (const f of lines) { + if (detail >= 3 && /path|foot|cycle|service|tram/.test(f.kind)) continue; + if (detail >= 5 && f.layer === "streets" && roadWidth(f.kind, z) < 1.8) continue; + const paths = f.rings.map((r) => simplify(r, epsilon)); + const width = roadWidth(f.kind, z); + if (f.layer === "streets") { + for (const p of paths) mesh.line(p, width + (detail >= 1 ? 0.3 : 0.6), EDGE); + for (const p of paths) mesh.line(p, width, /motorway|trunk|primary|secondary/.test(f.kind) ? MAIN : ROAD); + } else + for (const p of paths) + mesh.line(p, f.layer === "water_lines" ? 0.8 : 0.5, f.layer === "water_lines" ? WATER : EDGE); + } + if (mesh.points.length <= 4096 && mesh.faces.length <= 2048) { + const picked = labels.sort((a, b) => a.rank - b.rank || a.name.localeCompare(b.name)).slice(0, 512); + return { + mesh: mesh.entry(), + labels: picked, + vertices: mesh.points.length, + triangles: mesh.faces.length, + simplified: detail, + }; + } + } + throw new Error("Vector tile cannot fit the device detail budget"); +} + +/** Choose stable anchors within a requested display tile. A z18 label window + * reuses its z14 source; street names are positioned on the clipped line. */ +export function labelsInWindow( + tile: PreparedTile, + zoom: number, + left: number, + top: number, + size: number, +): VectorLabel[] { + const result: VectorLabel[] = [], + factor = 256 / size; + for (const source of tile.labels) { + if (zoom > source.maxZoom) continue; + let anchor: Point | undefined; + if (source.path) { + let longest = 0; + for (let i = 1; i < source.path.length; i++) { + const a = source.path[i - 1], + b = source.path[i], + dx = b.x - a.x, + dy = b.y - a.y; + let lo = 0, + hi = 1; + for (const [p, q] of [ + [-dx, a.x - left], + [dx, left + size - a.x], + [-dy, a.y - top], + [dy, top + size - a.y], + ]) { + if (p === 0) { + if (q < 0) { + hi = -1; + break; + } + continue; + } + const r = q / p; + if (p < 0) lo = Math.max(lo, r); + else hi = Math.min(hi, r); + } + const length = (hi - lo) * Math.hypot(dx, dy); + if (hi > lo && length > longest) { + longest = length; + const t = (lo + hi) / 2; + anchor = { x: a.x + dx * t, y: a.y + dy * t }; + } + } + if (longest * factor < 24) continue; + } else if (source.x >= left && source.x < left + size && source.y >= top && source.y < top + size) anchor = source; + if ( + !anchor || + result.some( + (p) => + p.name === source.name || + (Math.abs(p.x - anchor!.x) * factor < 76 && Math.abs(p.y - anchor!.y) * factor < 19), + ) + ) + continue; + result.push({ ...source, ...anchor }); + if (result.length === 12) break; + } + return result; +} diff --git a/package.json b/package.json index f65ecbc..1f3a68c 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,22 @@ { - "name": "pocket-map", "version": "0.1.0", "private": true, "type": "module", "license": "MIT", + "name": "pocket-map", + "version": "0.1.0", + "private": true, + "type": "module", + "license": "MIT", "scripts": { - "setup": "bun scripts/setup.ts", "3ds": "bun scripts/build.ts", "host": "bun host/serve.ts", - "deploy": "bun scripts/deploy.ts", "sim": "bun scripts/sim.ts", + "setup": "bun scripts/setup.ts", + "3ds": "bun scripts/build.ts", + "host": "bun host/serve.ts", + "deploy": "bun scripts/deploy.ts", + "sim": "bun scripts/sim.ts", "prepare:hyrule": "bun scripts/prepare-hyrule.ts", - "test": "bun test --conditions=browser test/geo.test.ts test/provider.test.ts test/model.test.ts test/bookmarks.test.ts test/transport.test.ts test/atlas.test.ts test/navigation.test.ts", + "test": "bun test --conditions=browser test/geo.test.ts test/provider.test.ts test/model.test.ts test/bookmarks.test.ts test/transport.test.ts test/atlas.test.ts test/navigation.test.ts test/vector.test.ts", "check": "bun run test && runtime/node_modules/.bin/tsc --noEmit" + }, + "dependencies": { + "@mapbox/vector-tile": "3.0.0", + "earcut": "3.2.3", + "pbf": "5.1.2" } } diff --git a/runtime b/runtime index 9e136be..64bc5a0 160000 --- a/runtime +++ b/runtime @@ -1 +1 @@ -Subproject commit 9e136be80fd7f0f718bd392258676b98458aeb0c +Subproject commit 64bc5a0eb272de5f832115e84fc5350e0a89ae05 diff --git a/scripts/quickjs-smoke.js b/scripts/quickjs-smoke.js index b4ef91c..9747896 100644 --- a/scripts/quickjs-smoke.js +++ b/scripts/quickjs-smoke.js @@ -5,13 +5,15 @@ const replies = [], tickets = new Set(), saved = []; globalThis.ui = { __host: "3ds-dev", __hostAbi: 8, __viewport: { w: 400, h: 240 }, __auxiliarySurface: { root: 2, w: 320, h: 240 }, __textures: { "shift.svg": 0, "shift-lock.svg": 1, "map-pad.svg": 2, "map-pin.svg": 3 }, __sprites: {}, createNode: () => node++, measureText: text => text.length * 7 }; for (const name of ["landmark", "tower", "shrine", "stable", "village", "seed", "treasure", "enemy", "special"]) ui.__textures[`marker-${name}.svg`] = 4 + Object.keys(ui.__textures).length; -for (const name of ["destroyNode", "insertBefore", "removeChild", "setStyle", "setProp", "setPropBatch", "setText", "replaceText", "uploadTexture", "setImage", "setSprite", "animate", "cancelAnim", "setFocus", "setActive", "hitTest", "hitTestBounds", "hitTestAuxiliary", "hitTestBoundsAuxiliary", "setCursor", "setCursorPos", "loadStyles", "loadFontAtlas", "loadTileTexture", "freeTexture", "uploadImgEntry", "debugInspect", "debugRectXY", "debugRectWH", "debugPause", "debugStep", "debugStats", "__dbgActive", "__dbgPoll", "__dbgSend", "__dbgShot"]) ui[name] = () => 0; +for (const name of ["destroyNode", "insertBefore", "removeChild", "setStyle", "setProp", "setPropBatch", "setText", "replaceText", "uploadTexture", "setImage", "setMesh", "freeMesh", "setSprite", "animate", "cancelAnim", "setFocus", "setActive", "hitTest", "hitTestBounds", "hitTestAuxiliary", "hitTestBoundsAuxiliary", "setCursor", "setCursorPos", "loadStyles", "loadFontAtlas", "loadTileTexture", "freeTexture", "uploadImgEntry", "debugInspect", "debugRectXY", "debugRectWH", "debugPause", "debugStep", "debugStats", "__dbgActive", "__dbgPoll", "__dbgSend", "__dbgShot"]) ui[name] = () => 0; globalThis.offload = { session: () => session, take: () => replies.shift(), + uploadMesh: id => tickets.has(id) ? texture++ : -1, releaseMesh: id => tickets.delete(id), uploadImage: id => tickets.has(id) ? texture++ : -1, releaseImage: id => tickets.delete(id), submit(raw) { const r = JSON.parse(raw); - if (r.response === "image") { const id = token++; tickets.add(id); replies.push(JSON.stringify({ id: r.id, image: { token: id, width: 256, height: r.method === "map.label" ? 32 : 256 } })); } + if (r.response === "mesh") { const id=token++;tickets.add(id);replies.push(JSON.stringify({id:r.id,mesh:{token:id,width:256,height:256,bytes:16}})); } + else if (r.response === "image") { const id = token++; tickets.add(id); replies.push(JSON.stringify({ id: r.id, image: { token: id, width: 256, height: r.method === "map.label" ? 32 : 256 } })); } else { let value; if (r.method === "map.info") currentHyrule = JSON.parse(r.payload).kind ? JSON.parse(r.payload).kind === "hyrule" : hyrule; @@ -23,8 +25,8 @@ globalThis.offload = { else saved.length = 0; value = { id }; } else if (r.method === "map.markers") value = [[1, "Sheikah Tower", "tower", 108, 168], [2, "Shrine of Resurrection", "shrine", 108.5, 168.5]]; - else value = r.method === "map.info" ? { source: currentHyrule ? "0123456789abcdef" : "abcdef0123456789", kind: currentHyrule ? "hyrule" : "osm", markers: currentHyrule, maps: [{ kind: "hyrule", name: "Hyrule" }, { kind: "osm", name: "OSM" }], name: "Smoke map", attribution: "Test", maxZoom: currentHyrule ? 7 : 18, - ...(currentHyrule ? { minZoom: 0, space: "planar", local: true, home: { id: "home", name: "Plateau", detail: "Test", space: "planar", x: 108, y: 168, zoom: 4 } } : {}) } + else value = r.method === "map.info" ? { source: currentHyrule ? "0123456789abcdef" : "abcdef0123456789", kind: currentHyrule ? "hyrule" : "osm", markers: true, maps: [{ kind: "hyrule", name: "Hyrule" }, { kind: "osm", name: "OSM" }], name: "Smoke map", attribution: "Test", maxZoom: currentHyrule ? 7 : 18, + ...(currentHyrule ? { minZoom: 0, space: "planar", local: true, home: { id: "home", name: "Plateau", detail: "Test", space: "planar", x: 108, y: 168, zoom: 4 } } : {render:"mesh",dataZoom:14}) } : [hyrule ? { id: "one", name: "Kakariko", detail: "Hyrule", space: "planar", x: 166, y: 149, zoom: 6 } : { id: "one", name: "Tokyo", detail: "Japan", lat: 35.68, lon: 139.76, zoom: 14 }]; replies.push(JSON.stringify({ id: r.id, payload: JSON.stringify(value) })); } @@ -50,7 +52,7 @@ try { frames(1, 0x400); frames(1, 0x400 | 0x10); frames(20, 0x400); check(s.zoomHeld(), "ZL rail mount"); frames(1); s.openSources(); frames(2); check(s.mode() === "sources", "source picker mount"); s.choose(hyrule ? 1 : 0); frames(80); check(s.planar() !== hyrule, "hot source switch"); s.openSources(); s.choose(hyrule ? 0 : 1); frames(80); - s.setMode("layers"); frames(2); s.choose(4); frames(1); check(s.annotations.layer() === "off", "label filter mount"); + s.setMode("layers"); frames(2); s.choose(s.vector()?1:4); frames(1); check(s.annotations.layer() === "off", "label filter mount"); session = -1; frames(30); session = 2; frames(100); check(s.diagnostics().tiles.entries <= 40 && tickets.size === 0, "resource ownership"); std.puts(JSON.stringify({ ok: true, frames: ticks, nodeIds: node, uploads: texture, pendingTickets: tickets.size }) + "\n"); diff --git a/scripts/sim.ts b/scripts/sim.ts index 5db8c1b..ee03fe9 100644 --- a/scripts/sim.ts +++ b/scripts/sim.ts @@ -16,14 +16,14 @@ c.fillStyle = "#e8e5d7"; c.fillRect(0, 0, 256, 256); c.fillStyle = "#b3ced7"; c. for (let x = 14; x < 170; x += 30) { c.fillStyle = "#fffdf4"; c.fillRect(x, 0, 5, 256); } for (let y = 20; y < 256; y += 32) { c.fillStyle = "#fffdf4"; c.fillRect(0, y, 170, 5); } c.fillStyle = "#b8cfa4"; c.fillRect(50, 70, 55, 48); c.fillStyle = "#5e705e"; c.font = "13px Arial"; c.fillText("Replay fixture", 30, 155); -const provider = hyrule ? new AtlasProvider(".local/hyrule") : new MapProvider({ ...defaultConfig, cache: live ? ".local/cache.sqlite" : ":memory:" }, live ? fetch : (async url => { +const provider = hyrule ? new AtlasProvider(".local/hyrule") : new MapProvider({ ...defaultConfig, format: "raster", tileURL:"https://tile.openstreetmap.de/{z}/{x}/{y}.png", cache: live ? ".local/cache.sqlite" : ":memory:" }, live ? fetch : (async url => { if (String(url).includes("photon")) return new Response(JSON.stringify({ features: [ { properties: { osm_type: "R", osm_id: 1, name: "San Francisco", city: "San Francisco", country: "United States", type: "city" }, geometry: { coordinates: [-122.4075, 37.7879] } }, { properties: { osm_type: "N", osm_id: 2, name: "Museum of Modern Art", city: "San Francisco", type: "other" }, geometry: { coordinates: [-122.4007, 37.7859] } }, ] })); return new Response(fixture.toBuffer("image/png")); }) as typeof fetch); -const service = hyrule ? new MapService({ ...defaultConfig, cache: ":memory:", atlas: ".local/hyrule", kind: "hyrule" }, async () => new Response(fixture.toBuffer("image/png"))) : undefined; +const service = hyrule ? new MapService({ ...defaultConfig, format: "raster", tileURL:"https://tile.openstreetmap.de/{z}/{x}/{y}.png", cache: ":memory:", atlas: ".local/hyrule", kind: "hyrule" }, async () => new Response(fixture.toBuffer("image/png"))) : undefined; const wasm = await createWasmUi(await Bun.file("runtime/hosts/web/pocketjs.wasm").arrayBuffer(), { width: 400, height: 480 }); const ops = wasm.ops; ops.hitTestBoundsAuxiliary = (x, y) => ops.hitTestBounds!(x + 40, y + 240); diff --git a/scripts/vector-sim.ts b/scripts/vector-sim.ts new file mode 100644 index 0000000..14281db --- /dev/null +++ b/scripts/vector-sim.ts @@ -0,0 +1,283 @@ +/** Compiled guest + real core + provider. Synthetic network by default; --live + * captures only a few explicitly viewed areas and persists their MVT responses. */ +import { mkdirSync, existsSync } from "node:fs"; +import { createWasmUi } from "../runtime/hosts/web/wasm-ops.js"; +import { NODE_TYPE, PROP, BTN } from "../runtime/contracts/spec/spec.ts"; +import { encodePNG } from "../runtime/tests/png.ts"; +import { dispatchOffload } from "../runtime/tools/offload-provider.ts"; +import { validateMesh } from "../runtime/tools/offload-wire.ts"; +import { MapService } from "../host/service.ts"; +import { defaultConfig } from "../host/config.ts"; +import { vectorFixture } from "../test/vector-fixture.ts"; +import type { OffloadImage, OffloadMesh } from "../runtime/contracts/spec/offload.ts"; +import type { MapModel } from "../app/model.ts"; +const live = process.argv.includes("--live"), + prefix = live ? "vector-live" : "vector"; +const provider = new MapService( + { + ...defaultConfig, + cache: live ? ".local/vector-qa.sqlite" : ":memory:", + kind: "osm", + atlas: existsSync(".local/hyrule/atlas.sqlite") ? ".local/hyrule" : undefined, + }, + live + ? fetch + : async (url) => + String(url).includes("photon") + ? new Response( + JSON.stringify({ + features: [ + { + properties: { osm_type: "N", osm_id: 1, name: "Tokyo", country: "Japan", type: "city" }, + geometry: { coordinates: [139.76, 35.68] }, + }, + ], + }), + ) + : new Response(vectorFixture(), { headers: { "cache-control": "max-age=3600" } }), +); +const wasm = await createWasmUi(await Bun.file("runtime/hosts/web/pocketjs.wasm").arrayBuffer(), { + width: 400, + height: 480, + }), + ops = wasm.ops; +ops.hitTestBoundsAuxiliary = (x, y) => ops.hitTestBounds!(x + 40, y + 240); +(ops as any).__viewport = { w: 400, h: 240 }; +const aux = ops.createNode(NODE_TYPE.view); +for (const [p, n] of [ + [PROP.posType, 1], + [PROP.insetL, 40], + [PROP.insetT, 240], + [PROP.width, 320], + [PROP.height, 240], +]) + ops.setProp(aux, p, n); +ops.insertBefore(1, aux, 0); +ops.__auxiliarySurface = { root: aux, w: 320, h: 240 }; +const requests: string[] = [], + replies: { at: number; raw: string }[] = [], + images = new Map(), + meshes = new Map(); +let tick = 0, + next = 1, + session = 1, + uploads = 0, + delay = 3, + withhold = false, + meshBytes = 0, + imageBytes = 0, + jsonBytes = 0, + meshReplies = 0, + maxPending = 0, + maxStaging = 0, + maxEntries = 0; +const drawTimes: number[] = [], + checks: string[] = []; +Object.assign(globalThis, { + ui: ops, + __pak: await Bun.file("runtime/dist/3ds/guest/pocketmap-main.pak").arrayBuffer(), + __simHz: 60, + offload: { + session: () => session, + submit: (raw: string) => { + if (requests.length >= 8) return false; + requests.push(raw); + return true; + }, + take: () => { + const i = replies.findIndex((r) => r.at <= tick && !withhold); + return i < 0 ? undefined : replies.splice(i, 1)[0].raw; + }, + uploadMesh: (id: number) => { + const value = meshes.get(id); + if (!value || uploads >= 1) return -1; + uploads++; + return ops.uploadMesh!(value.bytes); + }, + releaseMesh: (id: number) => meshes.delete(id), + uploadImage: (id: number) => { + const image = images.get(id); + if (!image || uploads >= 1) return -1; + uploads++; + const b = new Uint8Array(8 + image.pixels.length), + v = new DataView(b.buffer); + v.setUint16(0, image.width, true); + v.setUint16(2, image.height, true); + b[5] = 2; + b.set(image.pixels, 8); + return ops.uploadImgEntry!(b); + }, + releaseImage: (id: number) => images.delete(id), + }, +}); +(0, eval)(await Bun.file("runtime/dist/3ds/guest/pocketmap-main.js").text()); +const s = (globalThis as any).__map as MapModel; +function check(ok: unknown, name: string) { + if (!ok) throw new Error(name); + checks.push(name); +} +async function frames(n: number, buttons = 0, touch?: [number, number], analog = 0x8080) { + let hit: number | undefined; + if (touch) { + wasm.render(); + hit = ops.hitTestBounds!(touch[0] + 40, touch[1] + 240); + } + for (let i = 0; i < n; i++) { + tick++; + uploads = 0; + (globalThis as any).frame( + buttons, + analog, + touch ? [touch[0] | (touch[1] << 9)] : [], + touch ? [hit] : [], + touch ? [1] : [], + 0x8080, + ); + wasm.tick(); + const start = performance.now(); + wasm.render(); + drawTimes.push(performance.now() - start); + const d = s.diagnostics(); + maxPending = Math.max(maxPending, d.pending); + maxEntries = Math.max(maxEntries, d.tiles.entries); + while (requests.length && images.size + meshes.size < 8) { + const req = JSON.parse(requests.shift()!), + result = await dispatchOffload(provider.methods(), req); + if (result.mesh) { + const token = next++; + meshes.set(token, result.mesh); + meshBytes += result.mesh.bytes.length + 12; + meshReplies++; + replies.push({ + at: tick + delay, + raw: JSON.stringify({ id: result.id, mesh: { token, ...validateMesh(result.mesh.bytes) } }), + }); + } else if (result.image) { + const token = next++; + images.set(token, result.image); + imageBytes += result.image.pixels.length + 20; + replies.push({ + at: tick + delay, + raw: JSON.stringify({ + id: result.id, + image: { token, width: result.image.width, height: result.image.height }, + }), + }); + } else { + if (req.method === "map.info" && result.payload && live) { + const info = JSON.parse(result.payload); + info.prefetch = false; + result.payload = JSON.stringify(info); + } + const raw = JSON.stringify(result); + jsonBytes += new TextEncoder().encode(raw).length + 4; + replies.push({ at: tick + delay, raw }); + } + maxStaging = Math.max(maxStaging, images.size + meshes.size); + } + } +} +mkdirSync("dist/qa", { recursive: true }); +async function shot(name: string) { + await Bun.write(`dist/qa/${prefix}-${name}.png`, encodePNG(wasm.render().slice(), 400, 480)); +} +try { + await frames(3); + await shot("loading"); + await frames(110); + check(s.vector(), "OSM selects the geometry collection"); + check( + s.front()!.tiles.every((t) => s.frontView.state(t.input).status === "ready"), + "Visible MVTs become native meshes", + ); + await shot("map"); + check(s.annotations.rows().length > 0, "Independent label demand reveals atlas text"); + const before = { meshReplies, meshBytes, jsonBytes }, + center = s.camera.view(); + for (let z = 15; z <= 18; z++) { + s.zoom(1); + await frames(32); + await shot(`zoom-${z}`); + } + check(s.camera.view().zoom === 18 && s.front()?.level === 14, "Data LOD stays at 14 while camera reaches 18"); + check( + meshReplies === before.meshReplies, + "Four additional zoom levels reuse the same geometry without tile transfers", + ); + const zoomBytes = { mesh: meshBytes - before.meshBytes, json: jsonBytes - before.jsonBytes }; + for (let z = 17; z >= 14; z--) { + s.zoom(-1); + await frames(28); + } + await shot("zoom-return"); + if (!live) { + delay = 30; + const x = s.camera.view().x; + await frames(80, 0, undefined, 0xff80); + check(s.camera.view().x !== x, "Continuous input stays live during delayed geometry replies"); + await shot("pan"); + await frames(220); + delay = 3; + check( + s.front()!.tiles.every((t) => s.frontView.state(t.input).status === "ready"), + "Directional pan resolves the new visible tiles", + ); + const hash = wasm.drawHash!(); + session = 0; + withhold = true; + await frames(25, 0, undefined, 0x80ff); + check(wasm.drawHash!() !== hash, "Cached geometry still pans while disconnected"); + session = 2; + withhold = false; + await frames(150); + s.openSearch(); + s.setQuery("Tokyo"); + s.search(); + await frames(45); + check(s.places()[0]?.name === "Tokyo", "Place search remains a Mac capability"); + s.go(); + await frames(130); + await shot("search"); + if (s.maps().some((m) => m.kind === "hyrule")) { + s.switchMap("hyrule"); + await frames(140); + check(!s.vector() && s.planar(), "Hot switch retains the real Hyrule raster atlas"); + await shot("hyrule"); + s.switchMap("osm"); + await frames(160); + check(s.vector() && !s.planar(), "Hot switch returns to OSM geometry"); + } + } + check( + maxPending <= 3 && maxStaging <= 3 && maxEntries <= 40, + "Shared admission, staging and residency remain bounded", + ); + await frames(100); + check(images.size === 0 && meshes.size === 0, "All native staging tickets drain"); + drawTimes.sort((a, b) => a - b); + const receipt = { + ok: true, + live, + checks, + frames: tick, + meshReplies, + meshBytes, + imageBytes, + jsonBytes, + zoomBytes, + averageMeshBytes: meshReplies ? meshBytes / meshReplies : 0, + rasterEquivalentBytes: meshReplies * 131092, + maxPending, + maxStaging, + maxEntries, + wasmSoftwareMs: { + median: drawTimes[Math.floor(drawTimes.length * 0.5)], + p95: drawTimes[Math.floor(drawTimes.length * 0.95)], + }, + provider: provider.diagnostics(), + }; + await Bun.write(`dist/qa/${prefix}.json`, JSON.stringify(receipt, null, 2)); + console.log(JSON.stringify(receipt, null, 2)); +} finally { + provider.close(); +} diff --git a/shared/types.ts b/shared/types.ts index 4be4ac5..73599c9 100644 --- a/shared/types.ts +++ b/shared/types.ts @@ -1,7 +1,7 @@ export type MapKind = "hyrule" | "osm"; export type Position = { space?: "mercator"; lat: number; lon: number } | { space: "planar"; x: number; y: number }; export type Place = Position & { id: string; name: string; detail: string; zoom: number }; -export interface MapInfo { source: string; name: string; attribution: string; maxZoom: number; minZoom?: number; +export interface MapInfo { source: string; name: string; attribution: string; maxZoom: number; render?: "mesh"; prefetch?: boolean; dataZoom?: number; minZoom?: number; space?: "mercator" | "planar"; home?: Place; local?: boolean; markers?: boolean; kind?: MapKind; maps?: { kind: MapKind; name: string }[] } export interface TileInput { source: string; z: number; x: number; y: number } export type SearchInput = Position & { query: string; source?: string }; diff --git a/test/navigation.test.ts b/test/navigation.test.ts index 0f3194f..b1d2cb8 100644 --- a/test/navigation.test.ts +++ b/test/navigation.test.ts @@ -83,7 +83,7 @@ test("marker index filters zoom/category and bounds replies; delayed bookmarks r expect(() => index.query({ source: atlas.source, z: 6, x: 32, y: 0, layer: "all" })).toThrow(); index.close(); const db = new Database(join(dir, "atlas.sqlite")); db.exec("CREATE TABLE metadata(key TEXT PRIMARY KEY,value TEXT)"); db.query("INSERT INTO metadata VALUES ('manifest',?)").run(JSON.stringify({ format: ATLAS_FORMAT, tiles: 21845, info: atlas })); db.close(); - const service = new MapService({ ...defaultConfig, cache: ":memory:", atlas: dir, kind: "hyrule" }, () => { throw new Error("Network must not run"); }); + const service = new MapService({ ...defaultConfig, format: "raster", tileURL:"https://tile.openstreetmap.de/{z}/{x}/{y}.png", cache: ":memory:", atlas: dir, kind: "hyrule" }, () => { throw new Error("Network must not run"); }); try { const methods = service.methods(), before = JSON.parse(methods["map.info"]('{}')); const command = JSON.stringify({ source: before.source, op: "source_saved_1", kind: "save", place: atlas.home }); diff --git a/test/provider.test.ts b/test/provider.test.ts index 4f3cf1c..a4187b4 100644 --- a/test/provider.test.ts +++ b/test/provider.test.ts @@ -5,7 +5,7 @@ import { MapProvider, defaultConfig, packRGB } from "../host/provider.ts"; const png = () => { const c = createCanvas(256, 256), ctx = c.getContext("2d"); ctx.fillStyle = "red"; ctx.fillRect(0, 0, 128, 256); ctx.fillStyle = "blue"; ctx.fillRect(128, 0, 128, 256); return c.toBuffer("image/png"); }; test("host decodes PNGs, keeps exact PSM color order, deduplicates and rejects arbitrary URLs", async () => { let calls = 0; - const provider = new MapProvider({ ...defaultConfig, cache: ":memory:" }, (async () => { calls++; return new Response(png()); }) as NetworkFetch); + const provider = new MapProvider({ ...defaultConfig, format: "raster", tileURL:"https://tile.openstreetmap.de/{z}/{x}/{y}.png", cache: ":memory:" }, (async () => { calls++; return new Response(png()); }) as NetworkFetch); try { const input = { source: provider.info.source, z: 1, x: 0, y: 0 }; const [a, b] = await Promise.all([provider.tile(input), provider.tile(input)]); @@ -38,7 +38,7 @@ test("host cache persists reuse and conditional expiry, bounds bodies and honors }); test("malformed dimensions cannot trigger an unbounded host image decode", async () => { const bytes = png(); bytes.writeUInt32BE(100000, 16); - const provider = new MapProvider({ ...defaultConfig, cache: ":memory:" }, (async () => new Response(bytes)) as NetworkFetch); + const provider = new MapProvider({ ...defaultConfig, format: "raster", tileURL:"https://tile.openstreetmap.de/{z}/{x}/{y}.png", cache: ":memory:" }, (async () => new Response(bytes)) as NetworkFetch); await expect(provider.tile({ source: provider.info.source, z: 1, x: 0, y: 0 })).rejects.toThrow("256px"); provider.close(); }); test("real Bun fetch accepts conditional 304 without following redirects", async () => { @@ -58,7 +58,7 @@ test("real Bun fetch accepts conditional 304 without following redirects", async }); test("search handles empty, malformed and duplicate results with a bounded response", async () => { const feature = { properties: { name: "Tokyo", osm_type: "N", osm_id: 1, country: "Japan", type: "city" }, geometry: { coordinates: [139.76, 35.68] } }; - const provider = new MapProvider({ ...defaultConfig, cache: ":memory:" }, (async url => { + const provider = new MapProvider({ ...defaultConfig, format: "raster", tileURL:"https://tile.openstreetmap.de/{z}/{x}/{y}.png", cache: ":memory:" }, (async url => { expect(new URL(String(url)).searchParams.get("limit")).toBe("5"); return new Response(JSON.stringify({ features: [feature, feature, { ...feature, geometry: { coordinates: [500, 1000] } }] })); }) as NetworkFetch); diff --git a/test/transport.test.ts b/test/transport.test.ts index 1b009a0..14258fb 100644 --- a/test/transport.test.ts +++ b/test/transport.test.ts @@ -35,7 +35,7 @@ test("actual map provider reconnects during PNG fetch and returns intact image p await new Promise(resolve => server.listen(0, "127.0.0.1", resolve)); const provider = connectOffloadProvider({ address: "127.0.0.1", port: (server.address() as { port: number }).port, key: "ab".repeat(32), isolation: "process", worker: new URL("../host/worker.ts", import.meta.url), - data: { ...defaultConfig, tileURL: `${http.url}{z}/{x}/{y}.png`, searchURL: String(http.url), cache: ":memory:" } }); + data: { ...defaultConfig, format: "raster", tileURL: `${http.url}{z}/{x}/{y}.png`, searchURL: String(http.url), cache: ":memory:" } }); try { for (let n = 0; n < 3; n++) { const peer = await peers.take(); peer.send("map.info", 1); const info = JSON.parse(JSON.parse((await peer.read()).toString()).payload); diff --git a/test/vector-fixture.ts b/test/vector-fixture.ts new file mode 100644 index 0000000..0bac933 --- /dev/null +++ b/test/vector-fixture.ts @@ -0,0 +1,125 @@ +import { PbfWriter } from "pbf"; +type Feature = { type: number; paths: [number, number][][]; properties: Record }; +export function vectorFixture(dense = false): Uint8Array { + const polygon = (paths: [number, number][][], properties: Record = {}): Feature => ({ + type: 3, + paths, + properties, + }); + const line = (points: [number, number][], name: string): Feature => ({ + type: 2, + paths: [points], + properties: { kind: "residential", name }, + }); + const road: Feature[] = []; + for (let n = 0; n < 6; n++) + road.push( + line( + [ + [-5, 24 + n * 38], + [260, 24 + n * 38], + ], + `Street ${n}`, + ), + line( + [ + [24 + n * 38, -5], + [24 + n * 38, 260], + ], + `Avenue ${n}`, + ), + ); + const layers: Record = { + ocean: [ + polygon([ + [ + [180, -5], + [260, -5], + [260, 260], + [180, 260], + ], + ]), + ], + land: [ + polygon( + [ + [ + [40, 40], + [160, 40], + [160, 145], + [40, 145], + ], + [ + [70, 70], + [70, 110], + [115, 110], + [115, 70], + ], + ], + { kind: "park" }, + ), + ], + streets: road, + street_labels: road, + place_labels: [{ type: 1, paths: [[[130, 185]]], properties: { name: "日本橋", kind: "suburb" } }], + }; + if (dense) + layers.buildings = Array.from({ length: 1600 }, (_, i) => { + const x = (i % 40) * 6, + y = Math.floor(i / 40) * 6; + return polygon([ + [ + [x, y], + [x + 4, y], + [x + 4, y + 4], + [x, y + 4], + ], + ]); + }); + const output = new PbfWriter(); + for (const [name, features] of Object.entries(layers)) + output.writeMessage( + 3, + (_, p) => { + p.writeVarintField(15, 2); + p.writeStringField(1, name); + p.writeVarintField(5, 4096); + const keys = [...new Set(features.flatMap((f) => Object.keys(f.properties)))], + values = [...new Set(features.flatMap((f) => Object.values(f.properties)))]; + for (const key of keys) p.writeStringField(3, key); + for (const value of values) p.writeMessage(4, (v, w) => w.writeStringField(1, v), value); + for (const feature of features) + p.writeMessage( + 2, + (f, w) => { + w.writeVarintField(3, f.type); + w.writePackedVarint( + 2, + Object.entries(f.properties).flatMap(([k, v]) => [keys.indexOf(k), values.indexOf(v)]), + ); + const commands: number[] = []; + let x = 0, + y = 0; + const zig = (n: number) => (n << 1) ^ (n >> 31); + for (const path of f.paths) { + if (!path.length) continue; + commands.push(9); + path.forEach((pt, i) => { + if (i === 1) commands.push(((path.length - 1) << 3) | 2); + const nx = Math.round(pt[0] * 16), + ny = Math.round(pt[1] * 16); + commands.push(zig(nx - x), zig(ny - y)); + x = nx; + y = ny; + }); + if (f.type === 3) commands.push(15); + } + w.writePackedVarint(4, commands); + }, + feature, + ); + }, + null, + ); + return output.finish(); +} diff --git a/test/vector.test.ts b/test/vector.test.ts new file mode 100644 index 0000000..3811c6b --- /dev/null +++ b/test/vector.test.ts @@ -0,0 +1,89 @@ +import { expect, test } from "bun:test"; +import { prepareVector, MeshBuilder } from "../host/vector-geometry.ts"; +import { MapProvider, defaultConfig } from "../host/provider.ts"; +import { vectorFixture } from "./vector-fixture.ts"; +import { createMapPrediction } from "../app/prediction.ts"; +import { validateMesh } from "../runtime/tools/offload-wire.ts"; +test("vector tessellation preserves holes, clips triangles and quantizes shared edges", () => { + const b = new MeshBuilder(); + b.polygon( + [ + [ + { x: -10, y: -10 }, + { x: 270, y: -10 }, + { x: 270, y: 270 }, + { x: -10, y: 270 }, + ], + [ + { x: 80, y: 80 }, + { x: 80, y: 176 }, + { x: 176, y: 176 }, + { x: 176, y: 80 }, + ], + ], + 0xff00ff00, + ); + const area = b.faces.reduce((sum, f) => { + const [a, c, d] = f.slice(0, 3).map((i) => b.points[i]); + return sum + Math.abs((c[0] - a[0]) * (d[1] - a[1]) - (c[1] - a[1]) * (d[0] - a[0])) / 512; + }, 0); + expect(area).toBe(256 * 256 - 96 * 96); + expect(validateMesh(b.entry().bytes).width).toBe(256); + expect(b.points.every((p) => p.every((v) => v >= 0 && v <= 4096))).toBe(true); +}); +test("dense cities reduce complete detail layers within the device envelope", () => { + const normal = prepareVector(vectorFixture(), 14), + dense = prepareVector(vectorFixture(true), 14); + for (const p of [normal, dense]) { + expect(p.mesh.bytes.length).toBeLessThan(36881); + expect(p.vertices).toBeLessThan(4097); + expect(p.triangles).toBeLessThan(2049); + expect(p.labels.length).toBeLessThan(513); + expect(validateMesh(p.mesh.bytes).height).toBe(256); + } + expect(dense.simplified).toBeGreaterThanOrEqual(2); + expect(normal.labels.some((l) => l.name === "日本橋")).toBe(true); + expect(() => prepareVector(new Uint8Array(2 * 1024 * 1024 + 1), 14)).toThrow(); +}); +test("vector geometry and labels deduplicate one cached MVT; invalid source/LOD cannot fetch", async () => { + let calls = 0; + const p = new MapProvider({ ...defaultConfig, cache: ":memory:" }, async () => { + calls++; + return new Response(vectorFixture(), { headers: { "cache-control": "max-age=3600" } }); + }); + try { + const input = { source: p.info.source, z: 14, x: 2621, y: 6332 }; + const [a, rows, b] = await Promise.all([p.mesh(input), p.markerRows(input), p.mesh(input)]); + expect(a).toBe(b); + expect(rows.length).toBeGreaterThan(0); + expect(calls).toBe(1); + await p.markerRows({ ...input, z: 18, x: input.x * 16 + 1, y: input.y * 16 + 1 }); + await p.mesh(input); + expect(calls).toBe(1); + expect(p.info.render).toBe("mesh"); + expect(p.info.maxZoom).toBe(18); + expect(p.info.dataZoom).toBe(14); + await expect(p.mesh({ ...input, z: 15 })).rejects.toThrow(); + await expect(p.mesh({ ...input, source: "wrong" })).rejects.toThrow(); + expect(calls).toBe(1); + } finally { + p.close(); + } +}); +test("public OSMF vector configuration never schedules unseen look-ahead", () => { + const p = createMapPrediction(), + v = { x: 128, y: 128, zoom: 4, targetZoom: 4, scale: 16, moving: true }; + p.reset(v); + p.sample({ ...v, x: 130 }, 1 / 60, true); + expect( + p.plan(v, 4, { + source: "fixture", + name: "OSM", + attribution: "OSM", + maxZoom: 18, + render: "mesh", + dataZoom: 14, + prefetch: false, + }).extra, + ).toHaveLength(0); +}); From f6548e8e53079f30ebfeef22a0544f74045e963f Mon Sep 17 00:00:00 2001 From: "Yifeng \"Evan\" Wang" <7312949+doodlewind@users.noreply.github.com> Date: Sun, 6 Sep 2026 19:10:14 -0700 Subject: [PATCH 07/13] docs(map): record retained GPU build deployment --- docs/VALIDATION.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/VALIDATION.md b/docs/VALIDATION.md index 4baa8e9..6253cfc 100644 --- a/docs/VALIDATION.md +++ b/docs/VALIDATION.md @@ -209,5 +209,7 @@ revised 3DS backend materializes immutable GPU buffers once and emits bounded handle/transform/clip commands during navigation. Its telemetry splits UI/core, frame preparation and submission durations. Core tests cover backend opt-in, transform scaling, opacity fallback, off-screen culling and stale mesh handles. -The native build and app checks pass; physical timing of this revision remains -pending deployment and interaction. +The native build and app checks pass. This revision was uploaded to +`192.168.8.102:5000` and read back equal: 1,740,768 bytes, SHA-256 +`fd9f701d9159aedc8a2e45ffa0aa9e98f0e5fc4d888e6ccca816a2033dd8a135`. +Physical timing remains pending interaction with this binary. From 78ab7aa0bee54da0b545d2036feaa738e7387c29 Mon Sep 17 00:00:00 2001 From: "Yifeng \"Evan\" Wang" <7312949+doodlewind@users.noreply.github.com> Date: Sun, 6 Sep 2026 20:48:24 -0700 Subject: [PATCH 08/13] fix(map): bound dense vector detail without rejecting tiles --- docs/VALIDATION.md | 36 ++++++++- docs/VECTOR_MAP.md | 11 ++- host/vector-geometry.ts | 165 ++++++++++++++++++++++++++++++++++++---- test/vector-fixture.ts | 6 +- test/vector.test.ts | 70 ++++++++++++++++- 5 files changed, 270 insertions(+), 18 deletions(-) diff --git a/docs/VALIDATION.md b/docs/VALIDATION.md index 6253cfc..e8cd002 100644 --- a/docs/VALIDATION.md +++ b/docs/VALIDATION.md @@ -212,4 +212,38 @@ transform scaling, opacity fallback, off-screen culling and stale mesh handles. The native build and app checks pass. This revision was uploaded to `192.168.8.102:5000` and read back equal: 1,740,768 bytes, SHA-256 `fd9f701d9159aedc8a2e45ffa0aa9e98f0e5fc4d888e6ccca816a2033dd8a135`. -Physical timing remains pending interaction with this binary. +Device telemetry received after deployment includes stable intervals of 120 +frames per two-second sample. These are settled-view observations; continuous +dragging and materialization remain separate measurements. + +## Dense vector tile availability + +The device's `Tile unavailable` reports corresponded to Mac preparation errors: +`Vector tile cannot fit the device detail budget`. Many failed requests were +HTTP-cache hits. Replaying all 362 cached MVTs without network access reproduced +66 failures across source zooms 3–14. In one failing z12 tile, the old last detail +pass still contained 4,413 triangles against the 2,048-triangle limit. + +The correction adds small-area filtering, coarse line joining/deduplication, +removal of secondary line detail and complete-feature budget admission. It +keeps the same native wire, vertex, triangle and residency limits. All 362 cached +tiles now prepare successfully; 18 require the final feature-admission pass. +The source blobs and raw comparison renders remain in ignored local QA paths. +Mac reference / bounded-mesh comparisons include urban, coastal and regional +tiles. Shape simplification stops at two logical pixels; dense scenes can omit +smaller geographic features and roads. + +22 app tests / 180 assertions and TypeScript pass. Generated fixtures cover +fragmented major roads, dense land parcels, junctions, loops, overlapping links, +last-pass admission and rejection without partial mutation. The compiled guest +replay passes its 13 checks across 1,403 frames, including delayed responses, +reconnect and the unchanged Hyrule raster path. This is a Mac provider change; +the installed 3DS binary does not require replacement. + +After the Mac daemon restarted with this correction, the running 3DS reconnected +and requested nine meshes. All nine replies succeeded from the HTTP cache, +with zero downloads or provider errors. Subsequent settled samples reported +120 frames per two seconds, UI/core maxima around 11 ms, preparation around +1 ms and submission below 0.6 ms. The recovery upload interval also recorded +seven additional CPU frames above 16.67 ms, with a window UI maximum of 27.6 ms; +settled timing must not be presented as uninterrupted 60 fps during loading. diff --git a/docs/VECTOR_MAP.md b/docs/VECTOR_MAP.md index 1b7499c..9258eab 100644 --- a/docs/VECTOR_MAP.md +++ b/docs/VECTOR_MAP.md @@ -102,7 +102,16 @@ fonts are the applicable atlas path here. The provider triangulates complete polygons, preserving holes, then clips the result. Coarser detail passes simplify complete shapes and omit minor layers; -they do not transmit an arbitrary triangle prefix. Invalid indices, coordinates, +they do not transmit an arbitrary triangle prefix. Dense tiles remove small +parcels/holes, minor line layers and road casings. Coarse road preparation joins +degree-two endpoints and deduplicates links on a tile-aligned grid; junctions +remain endpoints. Shape simplification tolerance stops at two logical pixels, +while feature selection can continue to reduce detail. A final admission pass +selects complete geographic areas and long major roads within the existing +vertex/triangle limits, then restores painter order. It can omit smaller roads +or decorative features instead of failing an otherwise valid tile. + +Invalid indices, coordinates, versions or byte counts are rejected before acquiring native mesh residency. `createOffloadMeshCollection` owns materialization and eviction. `ResourceMesh` diff --git a/host/vector-geometry.ts b/host/vector-geometry.ts index d257320..3a063e7 100644 --- a/host/vector-geometry.ts +++ b/host/vector-geometry.ts @@ -31,6 +31,7 @@ const LAND = color(0xf0ede3), export class MeshBuilder { points: [number, number][] = []; faces: [number, number, number, number][] = []; + priority = 0; private indices = new Map(); triangle(a: Point, b: Point, c: Point, fill: number) { let poly = [a, b, c]; @@ -117,6 +118,24 @@ export class MeshBuilder { this.triangle(right[i - 1], right[i], left[i], fill); } } + /** Admit a complete feature or leave the builder unchanged. */ + append(other: MeshBuilder): boolean { + if (!other.faces.length) return true; + if (this.faces.length + other.faces.length > 2048) return false; + const fresh: [number, number][] = [], remap: number[] = []; + for (const point of other.points) { + const existing = this.indices.get(`${point[0]}/${point[1]}`); + remap.push(existing ?? this.points.length + fresh.length); + if (existing === undefined) fresh.push(point); + } + if (this.points.length + fresh.length > 4096) return false; + for (const point of fresh) { + this.indices.set(`${point[0]}/${point[1]}`, this.points.length); + this.points.push(point); + } + for (const [a, b, c, fill] of other.faces) this.faces.push([remap[a], remap[b], remap[c], fill]); + return true; + } entry(): OffloadMesh { return prepareMesh({ width: 256, @@ -126,6 +145,34 @@ export class MeshBuilder { }); } } + +/** Last detail pass: choose complete features, then restore painter order. + * Geographic areas outrank decoration; long major roads outrank short links. + * This guarantees a bounded mesh even when a dense source survives simplification. */ +class BudgetMeshBuilder extends MeshBuilder { + private features: { mesh: MeshBuilder; priority: number; order: number }[] = []; + override polygon(rings: Point[][], fill: number) { + const mesh = new MeshBuilder(); + mesh.polygon(rings, fill); + this.features.push({ mesh, priority: this.priority, order: this.features.length }); + } + override line(points: Point[], width: number, fill: number) { + const mesh = new MeshBuilder(); + mesh.line(points, width, fill); + let length = 0; + for (let i = 1; i < points.length; i++) + length += Math.hypot(points[i].x - points[i - 1].x, points[i].y - points[i - 1].y); + this.features.push({ mesh, priority: this.priority + length, order: this.features.length }); + } + finish(): MeshBuilder { + const budget = new MeshBuilder(); + const selected = this.features.sort((a, b) => b.priority - a.priority || a.order - b.order) + .filter((feature) => budget.append(feature.mesh)); + const result = new MeshBuilder(); + for (const feature of selected.sort((a, b) => a.order - b.order)) result.append(feature.mesh); + return result; + } +} function simplify(points: Point[], epsilon: number): Point[] { if (points.length <= 3) return points; // Iterative Douglas-Peucker: host work, no recursion proportional to geometry. @@ -163,6 +210,14 @@ function simplify(points: Point[], epsilon: number): Point[] { ? points : result; } +function ringArea(ring: Point[]): number { + let area = 0; + for (let i = 0; i < ring.length; i++) { + const a = ring[i], b = ring[(i + 1) % ring.length]; + area += a.x * b.y - b.x * a.y; + } + return area / 2; +} type Feature = { layer: string; kind: string; @@ -182,6 +237,79 @@ const AREAS = [ "pier_polygons", ]; const LINES = ["water_lines", "boundaries", "streets", "pier_lines"]; + +/** Join degree-two endpoints before simplifying. MVT features often split one + * road into hundreds of short links; simplifying each link cannot reduce it. + * Junctions remain endpoints, so simplification cannot cut across a branch. */ +export function joinLinePaths(paths: Point[][]): Point[][] { + const edges = paths.filter((p) => p.length >= 2); + const nodes = new Map(); + const key = (p: Point) => `${p.x}/${p.y}`; + for (const [edge, path] of edges.entries()) + for (const end of [0, 1]) { + const k = key(path[end ? path.length - 1 : 0]); + const links = nodes.get(k) ?? []; + links.push({ edge, end }); + nodes.set(k, links); + } + const used = new Uint8Array(edges.length), result: Point[][] = []; + const walk = (edge: number, reverse: boolean) => { + const joined: Point[] = []; + while (!used[edge]) { + used[edge] = 1; + const path = edges[edge]; + for (let j = joined.length ? 1 : 0; j < path.length; j++) + joined.push(path[reverse ? path.length - 1 - j : j]); + const links = nodes.get(key(joined[joined.length - 1]))!; + if (links.length !== 2) break; + const next = links.find((link) => !used[link.edge]); + if (!next) break; + edge = next.edge; + reverse = next.end === 1; + } + result.push(joined); + }; + for (const [edge, path] of edges.entries()) { + if (used[edge]) continue; + if (nodes.get(key(path[0]))!.length !== 2) walk(edge, false); + else if (nodes.get(key(path[path.length - 1]))!.length !== 2) walk(edge, true); + } + for (let edge = 0; edge < edges.length; edge++) if (!used[edge]) walk(edge, false); + return result; +} + +/** At coarse detail, subpixel parallel links and short interchange edges have + * the same coverage. Snap to a tile-aligned grid and deduplicate before joining. */ +export function generalizeLinePaths(paths: Point[][], grid: number): Point[][] { + const edges = new Map(); + const snap = (p: Point) => ({ x: Math.round(p.x / grid) * grid, y: Math.round(p.y / grid) * grid }); + const key = (p: Point) => `${p.x}/${p.y}`; + for (const path of paths) { + if (!path.length) continue; + let a = snap(path[0]); + for (let i = 1; i < path.length; i++) { + const b = snap(path[i]), ka = key(a), kb = key(b); + if (ka !== kb) edges.set(ka < kb ? `${ka}:${kb}` : `${kb}:${ka}`, [a, b]); + a = b; + } + } + return joinLinePaths([...edges.values()]); +} + +function joinedLines(features: Feature[], grid: number): Feature[] { + const groups = new Map(); + for (const f of features) { + if (!LINES.includes(f.layer)) continue; + const key = `${f.layer}/${f.kind}`; + let group = groups.get(key); + if (!group) { + group = { ...f, rings: [] }; + groups.set(key, group); + } + for (const ring of f.rings) group.rings.push(ring); + } + return [...groups.values()].map((f) => ({ ...f, rings: grid ? generalizeLinePaths(f.rings, grid) : joinLinePaths(f.rings) })); +} function roadWidth(kind: string, z: number) { return /motorway|trunk/.test(kind) ? 3.0 @@ -275,9 +403,11 @@ export function prepareVector(bytes: Uint8Array, z: number): PreparedTile { } // Complete features at successively coarser detail; never cut an arbitrary // triangle prefix which could erase a polygon's holes or half a road. - for (let detail = 0; detail < 6; detail++) { - const mesh = new MeshBuilder(); - mesh.polygon( + const tolerances = [0.25, 0.5, 1, 2, 3, 5, 8, 12, 16, 20, 24]; + for (let detail = 0; detail < tolerances.length; detail++) { + const drawing = detail === tolerances.length - 1 ? new BudgetMeshBuilder() : new MeshBuilder(); + drawing.priority = Infinity; + drawing.polygon( [ [ { x: 0, y: 0 }, @@ -288,7 +418,7 @@ export function prepareVector(bytes: Uint8Array, z: number): PreparedTile { ], LAND, ); - const epsilon = [0.25, 0.5, 1, 2, 3, 5][detail]; + const epsilon = tolerances[detail]; for (const layer of AREAS) for (const f of features.filter((f) => f.layer === layer)) { if ( @@ -305,27 +435,36 @@ export function prepareVector(bytes: Uint8Array, z: number): PreparedTile { : layer === "sites" ? color(0xe3dfcf) : LAND; - for (const polygon of f.polygons) - mesh.polygon( - polygon.map((r) => simplify(r, epsilon)), - fill, + for (const polygon of f.polygons) { + if (detail >= 2 && Math.abs(ringArea(polygon[0])) < epsilon * epsilon) continue; + drawing.priority = (["ocean", "water_polygons", "land"].includes(layer) ? 1e9 : 1e6) + Math.abs(ringArea(polygon[0])); + drawing.polygon( + polygon.filter((r, i) => i === 0 || detail < 2 || Math.abs(ringArea(r)) >= epsilon * epsilon) + .map((r) => simplify(r, Math.min(epsilon, 2))), fill, ); + } } - const lines = features + const lines = (detail >= 6 ? joinedLines(features, [0, 0.5, 1, 1, 2][detail - 6]) : features) .filter((f) => LINES.includes(f.layer)) .sort((a, b) => roadWidth(a.kind, z) - roadWidth(b.kind, z)); for (const f of lines) { if (detail >= 3 && /path|foot|cycle|service|tram/.test(f.kind)) continue; + if (detail >= 5 && f.layer === "pier_lines") continue; + if (detail >= 6 && f.layer === "boundaries") continue; + if (detail >= 7 && f.layer === "water_lines" && f.kind === "canal") continue; + if (detail >= 7 && f.layer === "streets" && roadWidth(f.kind, z) < 2.4) continue; if (detail >= 5 && f.layer === "streets" && roadWidth(f.kind, z) < 1.8) continue; - const paths = f.rings.map((r) => simplify(r, epsilon)); + const paths = f.rings.map((r) => simplify(r, Math.min(epsilon, 2))); const width = roadWidth(f.kind, z); + drawing.priority = f.layer === "streets" ? width * 1e7 : 1e6; if (f.layer === "streets") { - for (const p of paths) mesh.line(p, width + (detail >= 1 ? 0.3 : 0.6), EDGE); - for (const p of paths) mesh.line(p, width, /motorway|trunk|primary|secondary/.test(f.kind) ? MAIN : ROAD); + if (detail < 6) for (const p of paths) drawing.line(p, width + (detail >= 1 ? 0.3 : 0.6), EDGE); + for (const p of paths) drawing.line(p, width, /motorway|trunk|primary|secondary/.test(f.kind) ? MAIN : ROAD); } else for (const p of paths) - mesh.line(p, f.layer === "water_lines" ? 0.8 : 0.5, f.layer === "water_lines" ? WATER : EDGE); + drawing.line(p, f.layer === "water_lines" ? 0.8 : 0.5, f.layer === "water_lines" ? WATER : EDGE); } + const mesh = drawing instanceof BudgetMeshBuilder ? drawing.finish() : drawing; if (mesh.points.length <= 4096 && mesh.faces.length <= 2048) { const picked = labels.sort((a, b) => a.rank - b.rank || a.name.localeCompare(b.name)).slice(0, 512); return { diff --git a/test/vector-fixture.ts b/test/vector-fixture.ts index 0bac933..4e79e49 100644 --- a/test/vector-fixture.ts +++ b/test/vector-fixture.ts @@ -1,5 +1,5 @@ import { PbfWriter } from "pbf"; -type Feature = { type: number; paths: [number, number][][]; properties: Record }; +export type Feature = { type: number; paths: [number, number][][]; properties: Record }; export function vectorFixture(dense = false): Uint8Array { const polygon = (paths: [number, number][][], properties: Record = {}): Feature => ({ type: 3, @@ -76,6 +76,10 @@ export function vectorFixture(dense = false): Uint8Array { ], ]); }); + return encodeVectorFixture(layers); +} + +export function encodeVectorFixture(layers: Record): Uint8Array { const output = new PbfWriter(); for (const [name, features] of Object.entries(layers)) output.writeMessage( diff --git a/test/vector.test.ts b/test/vector.test.ts index 3811c6b..3c32496 100644 --- a/test/vector.test.ts +++ b/test/vector.test.ts @@ -1,7 +1,7 @@ import { expect, test } from "bun:test"; -import { prepareVector, MeshBuilder } from "../host/vector-geometry.ts"; +import { prepareVector, MeshBuilder, joinLinePaths, generalizeLinePaths } from "../host/vector-geometry.ts"; import { MapProvider, defaultConfig } from "../host/provider.ts"; -import { vectorFixture } from "./vector-fixture.ts"; +import { vectorFixture, encodeVectorFixture, type Feature } from "./vector-fixture.ts"; import { createMapPrediction } from "../app/prediction.ts"; import { validateMesh } from "../runtime/tools/offload-wire.ts"; test("vector tessellation preserves holes, clips triangles and quantizes shared edges", () => { @@ -87,3 +87,69 @@ test("public OSMF vector configuration never schedules unseen look-ahead", () => }).extra, ).toHaveLength(0); }); + +test("coarse road joining preserves junctions, loops and every source edge", () => { + const point = (x: number, y: number) => ({ x, y }); + const paths = [ + [point(2, 0), point(1, 0)], [point(0, 0), point(1, 0)], + [point(2, 0), point(3, 0)], [point(2, 0), point(2, 1)], + [point(10, 0), point(11, 0)], [point(11, 0), point(11, 1)], + [point(11, 1), point(10, 0)], + ]; + const joined = joinLinePaths(paths); + expect(joined).toHaveLength(4); + expect(joined.reduce((sum, p) => sum + p.length - 1, 0)).toBe(7); + expect(joined.some((p) => p.length === 4 && p[0].x === p[3].x && p[0].y === p[3].y)).toBe(true); + expect(joined.filter((p) => [p[0], p.at(-1)!].some((v) => v.x === 2 && v.y === 0))).toHaveLength(3); + const generalized = generalizeLinePaths([ + [point(0.1, 0.1), point(1.1, 0.1), point(2.1, 0.1)], + [point(2.2, 0.2), point(1.2, 0.2), point(0.2, 0.2)], + ], 1); + expect(generalized).toHaveLength(1); + expect(generalized[0]).toHaveLength(3); +}); + +test("dense land parcels and fragmented major roads stay available without increasing device limits", () => { + const streets: Feature[] = [], landcover: Feature[] = []; + for (let row = 0; row < 12; row++) + for (let x = 0; x < 256; x++) + streets.push({ type: 2, paths: [[[x, 8 + row * 20], [x + 1, 8 + row * 20]]], properties: { kind: "motorway" } }); + for (let i = 0; i < 1600; i++) { + const x = (i % 40) * 6, y = Math.floor(i / 40) * 6; + landcover.push({ type: 3, properties: { kind: "grass" }, paths: [[[x, y], [x + 2, y], [x + 2, y + 2], [x, y + 2]]] }); + } + const prepared = prepareVector(encodeVectorFixture({ streets, landcover }), 12); + expect(prepared.simplified).toBeGreaterThanOrEqual(6); + expect(validateMesh(prepared.mesh.bytes).width).toBe(256); + expect(prepared.vertices).toBeLessThanOrEqual(4096); + expect(prepared.triangles).toBeLessThanOrEqual(2048); + expect(prepared.triangles).toBeGreaterThan(2); // Main roads survive. +}); + +test("last detail pass admits complete dense features and preserves the base plane", () => { + const streets: Feature[] = []; + // Disconnected crossing roads cannot be reduced by joining their endpoints. + for (let i = 0; i < 3000; i++) { + const a = (i % 65) * 4, b = Math.floor(i / 65) * 4; + streets.push({ type: 2, paths: [[[0, a], [256, b]]], properties: { kind: "motorway" } }); + } + const prepared = prepareVector(encodeVectorFixture({ streets }), 8); + expect(prepared.simplified).toBe(10); + expect(prepared.triangles).toBeGreaterThan(2); + expect(prepared.triangles).toBeLessThanOrEqual(2048); + expect(prepared.vertices).toBeLessThanOrEqual(4096); + expect(validateMesh(prepared.mesh.bytes).height).toBe(256); + const view = new DataView(prepared.mesh.bytes.buffer, prepared.mesh.bytes.byteOffset); + const first = 16 + prepared.vertices * 4; + expect(view.getUint32(first + 6, true)).toBe(0xffe3edf0); +}); + +test("feature admission cannot partially mutate a full mesh", () => { + const full = new MeshBuilder(), extra = new MeshBuilder(); + for (let i = 0; i < 2048; i++) + full.triangle({ x: 0, y: 0 }, { x: 256, y: 0 }, { x: 0, y: 256 }, 0xffffffff); + extra.line([{ x: 10, y: 10 }, { x: 100, y: 100 }], 2, 0xff00ff00); + const before = full.entry().bytes; + expect(full.append(extra)).toBe(false); + expect(full.entry().bytes).toEqual(before); +}); From 5de6b13bffacfaf03f1d4249b2e0fa5debc2d707 Mon Sep 17 00:00:00 2001 From: "Yifeng \"Evan\" Wang" <7312949+doodlewind@users.noreply.github.com> Date: Sun, 6 Sep 2026 21:22:57 -0700 Subject: [PATCH 09/13] fix(map): keep held-stick speed independent of frame cadence --- app/annotations.ts | 59 +++++++++++++++++++++++++--------------- app/model.ts | 6 ++-- app/prediction.ts | 19 ++++++++++--- app/ui.tsx | 6 ++-- docs/VALIDATION.md | 42 ++++++++++++++++++++++++++++ docs/VECTOR_MAP.md | 15 ++++++++++ runtime | 2 +- scripts/quickjs-smoke.js | 12 +++++++- scripts/vector-sim.ts | 16 ++++++++++- test/model.test.ts | 27 ++++++++++++++++++ test/navigation.test.ts | 49 +++++++++++++++++++++++++++++++++ 11 files changed, 218 insertions(+), 35 deletions(-) diff --git a/app/annotations.ts b/app/annotations.ts index 701f85c..7a94cf9 100644 --- a/app/annotations.ts +++ b/app/annotations.ts @@ -69,15 +69,19 @@ export function createAnnotations(io: ReturnType, runtime: Retur const view = createResourceView(collection, { demand: () => demand().map((input) => ({ input, priority: 25, pin: true })), }); - const rows = createMemo(() => demand().flatMap((i) => view.value(i) ?? [])); + const rows = createMemo(() => demand().flatMap((i) => view.value(i) ?? []).sort((a, b) => a[0] - b[0])); + const [renderRows, setRenderRows] = createSignal([]); + let last: { x: number; y: number; zoom: number; rows: MapMarker[] } | undefined; + let settled = false; let placements = new Map(); return { layer, setLayer, rows, + renderRows, placement: (id: number) => placements.get(id), reset() { - setDemand([]); + setDemand([]); setRenderRows([]); placements.clear(); last = undefined; collection.clear(); }, update(camera: { x: number; y: number; zoom: number }, level: number, info: MapInfo) { @@ -105,29 +109,40 @@ export function createAnnotations(io: ReturnType, runtime: Retur layer: layer(), })) : []; + const old = demand(); + if (next.length !== old.length || next.some((v, n) => { + const o = old[n]; return !o || v.source !== o.source || v.layer !== o.layer || v.z !== o.z || v.x !== o.x || v.y !== o.y; + })) setDemand(next); + const candidates = rows(); + if (settled && last?.x === camera.x && last.y === camera.y && last.zoom === camera.zoom && last.rows === candidates) return; + last = { ...camera, rows: candidates }; if (vector) { - const placed = new Map(), - names = new Set(); - for (const marker of rows() - .slice() - .sort((a, b) => Number(placements.has(b[0])) - Number(placements.has(a[0])) || a[0] - b[0])) { - if (placed.size >= 12 || names.has(marker[1])) continue; - let dx = marker[3] - camera.x; - dx -= Math.round(dx / 256) * 256; - const width = labelWidth(marker[1]), - x = 200 + dx * 2 ** camera.zoom - width / 2, - y = 120 + (marker[4] - camera.y) * 2 ** camera.zoom - 7; - if (x < 2 || x + width > 398 || y < 29 || y > 208) continue; - if ([...placed.values()].some((p) => x < p.x + p.width + 4 && x + width + 4 > p.x && Math.abs(y - p.y) < 19)) - continue; - placed.set(marker[0], { x, y, width }); - names.add(marker[1]); + const placed = new Map(), names = new Set(); + const shown = renderRows(), retained = new Map(shown.map(m => [m[0], m])), selected: MapMarker[] = []; + const scale = 2 ** camera.zoom; + function place(marker: MapMarker) { + if (placed.size >= 12 || placed.has(marker[0]) || names.has(marker[1])) return; + let dx = marker[3] - camera.x; dx -= Math.round(dx / 256) * 256; + const width = labelWidth(marker[1]), x = 200 + dx * scale - width / 2, y = 120 + (marker[4] - camera.y) * scale - 7; + if (x < 2 || x + width > 398 || y < 29 || y > 208) return; + for (const p of placed.values()) if (x < p.x + p.width + 4 && x + width + 4 > p.x && Math.abs(y - p.y) < 19) return; + placed.set(marker[0], { x, y, width }); names.add(marker[1]); selected.push(retained.get(marker[0]) ?? marker); } + // Keep visible identities first without sorting the whole candidate + // window each frame. Mount at most ONE newly visible label per frame; + // candidates outside the screen never create UI nodes/frame hooks. + for (const marker of candidates) if (retained.has(marker[0])) place(marker); + const retainedCount = selected.length; + for (const marker of candidates) place(marker); + settled = selected.length <= retainedCount + 1; + const mounted = selected.slice(0, retainedCount + 1); + for (let i = mounted.length; i < selected.length; i++) placed.delete(selected[i][0]); placements = placed; - } else placements.clear(); - const old = demand(); - if (next.length !== old.length || next.some((v, n) => JSON.stringify(v) !== JSON.stringify(old[n]))) - setDemand(next); + if (mounted.length !== shown.length || mounted.some((m, i) => m !== shown[i])) setRenderRows(mounted); + } else { + placements.clear(); settled = true; + setRenderRows(candidates); // Hyrule retains its bounded icon markers. + } }, }; } diff --git a/app/model.ts b/app/model.ts index c2dd501..4031653 100644 --- a/app/model.ts +++ b/app/model.ts @@ -5,7 +5,7 @@ import { createTileCamera } from "@pocketjs/framework/tile-viewport"; import { offload } from "@pocketjs/framework/offload"; import { analogX, analogY, onFrame, onButtonPress } from "@pocketjs/framework/lifecycle"; import { BTN } from "@pocketjs/framework/input"; -import { simulationHz, virtualNow } from "@pocketjs/framework/clock"; +import { inputDeltaSeconds, simulationHz, virtualNow } from "@pocketjs/framework/clock"; import { project, worldPosition, positionAt } from "./geo.ts"; import { createSavedPlaces, validPlaces, type MapMode } from "./saved.ts"; import { HOME, type TileInput, type MapInfo, type SearchInput, type Place, type MapKind } from "../shared/types.ts"; @@ -203,10 +203,10 @@ export function createMap(io = offload()) { const axisX = canPan ? analogX() : 0, axisY = canPan ? analogY() : 0; const dx = canPan ? (buttons & BTN.LEFT ? 1 : 0) - (buttons & BTN.RIGHT ? 1 : 0) : 0; const dy = canPan ? (buttons & BTN.UP ? 1 : 0) - (buttons & BTN.DOWN ? 1 : 0) : 0; - camera.step(1 / simulationHz(), dx ? dx * 180 : -axisX * 320, dy ? dy * 180 : -axisY * 320); + camera.step(inputDeltaSeconds(), dx ? dx * 180 : -axisX * 320, dy ? dy * 180 : -axisY * 320); previousButtons = buttons; if (!info()) return; - const view = camera.view(); prediction.sample(view, 1 / simulationHz(), !planar()); + const view = camera.view(); prediction.sample(view, inputDeltaSeconds(), !planar()); const next = Math.min(info()!.dataZoom ?? info()!.maxZoom, Math.max(info()!.minZoom ?? 1, Math.round(view.zoom))); levelAge = next === candidateLevel ? levelAge + 1 : 0; candidateLevel = next; let level = front()?.level ?? next; diff --git a/app/prediction.ts b/app/prediction.ts index 8f600e8..f0fbe9d 100644 --- a/app/prediction.ts +++ b/app/prediction.ts @@ -3,12 +3,14 @@ import type { MapInfo, TileInput } from "../shared/types.ts"; import { wrapTile } from "./geo.ts"; type View = ReturnType["view"]>; export interface PlannedTile { input: TileInput; column: number; row: number; priority: number } +interface Plan { visible: PlannedTile[]; extra: PlannedTile[]; intent: { x: number; y: number; confidence: number } } export function createMapPrediction() { const intent = createTileIntent(); let previous: View | undefined, now = 0, zoomUntil = 0; - function reset(view: View) { intent.reset(); previous = view; zoomUntil = 0; } + let cached: { info: MapInfo; level: number; zoom: number; target: number; x0: number; x1: number; y0: number; y1: number; at: number; plan: Plan } | undefined; + function reset(view: View) { intent.reset(); previous = view; zoomUntil = 0; cached = undefined; } return { reset, - zoom(delta: number) { zoomUntil = delta > 0 ? now + 5 : 0; }, + zoom(delta: number) { zoomUntil = delta > 0 ? now + 5 : 0; cached = undefined; }, sample(view: View, seconds: number, wraps: boolean) { if (previous) { let dx = view.x - previous.x; if (wraps) dx -= Math.round(dx / 256) * 256; @@ -16,7 +18,14 @@ export function createMapPrediction() { } previous = view; now += seconds; }, - plan(view: View, level: number, info: MapInfo) { + plan(view: View, level: number, info: MapInfo): Plan { + // Re-sort predictive demand at most 12 times/second while the visible + // tile set is unchanged. A newly exposed row/column is never delayed. + const scale = 2 ** level / 256, screen = 2 ** view.zoom; + const x0 = Math.floor((view.x - 200 / screen) * scale), x1 = Math.ceil((view.x + 200 / screen) * scale) - 1; + const y0 = Math.floor((view.y - 120 / screen) * scale), y1 = Math.ceil((view.y + 120 / screen) * scale) - 1; + if (cached && cached.info === info && cached.level === level && cached.zoom === view.zoom && cached.target === view.targetZoom + && cached.x0 === x0 && cached.x1 === x1 && cached.y0 === y0 && cached.y1 === y1 && now - cached.at < 1 / 12 - 1e-8) return cached.plan; const local = info.local === true, lead = intent.predict(local ? 512 : 128), directional = lead.confidence > .45; const options = { ...view, level, width: 400, height: 240, maxTiles: 12, margin: local ? 256 : 128, leadX: lead.x, leadY: lead.y, directional, maxExtra: info.prefetch === false ? 0 : local ? 12 : 4 }; @@ -31,7 +40,9 @@ export function createMapPrediction() { ? address(visibleTiles({ ...options, zoom: next, level: next }), next).slice(0, 6) : []; const extra = [...zoomTiles.map(t => ({ ...t, priority: 300 + t.priority })), ...address(window.lookAhead, level).map(t => ({ ...t, priority: 1000 + t.priority }))].slice(0, local ? 12 : 4); - return { visible: address(window.visible, level), extra, intent: lead }; + const plan = { visible: address(window.visible, level), extra, intent: lead }; + cached = { info, level, zoom: view.zoom, target: view.targetZoom, x0, x1, y0, y1, at: now, plan }; + return plan; }, }; } diff --git a/app/ui.tsx b/app/ui.tsx index 1f23109..da67921 100644 --- a/app/ui.tsx +++ b/app/ui.tsx @@ -4,7 +4,7 @@ import { ClassicButton, ClassicFace, ClassicPanel, ClassicSheet } from "@pocketj import { ResourceImage, ResourceMesh } from "@pocketjs/framework/resource"; import { createResourceView } from "@pocketjs/framework/resource-view"; import { createGesture, createDragFilter } from "@pocketjs/framework/gesture"; -import { simulationHz } from "@pocketjs/framework/clock"; +import { inputDeltaSeconds } from "@pocketjs/framework/clock"; import { onFrame } from "@pocketjs/framework/lifecycle"; import * as hot from "@pocketjs/framework/hot"; import {labelWidth,labelMetrics} from "./annotations.ts"; @@ -155,7 +155,7 @@ function Deck(p: { s: MapModel }) { onPanMove(c) { if (blocked() || naming() || p.s.choosing()) return; if (results()) { dy += c.fdy; const step = Math.trunc(dy / 20); if (step) { p.s.select(p.s.selectedIndex() + step); dy -= step * 20; } } - else { const delta = filter.update(c.dx, c.dy, 1 / simulationHz()); p.s.camera.drag(delta.dx * 1.45, delta.dy * 1.45); } + else { const delta = filter.update(c.dx, c.dy, inputDeltaSeconds()); p.s.camera.drag(delta.dx * 1.45, delta.dy * 1.45); } }, onPanEnd() { setTouching(false); if (blocked() || naming() || p.s.choosing()) return; const v = filter.velocity(); p.s.camera.endDrag(results() ? 0 : v.x * 1.45, results() ? 0 : v.y * 1.45); }, onTap() { setTouching(false); if (blocked() || naming() || p.s.choosing()) return; p.s.camera.endDrag(0, 0); if (results()) p.s.go(); }, @@ -209,7 +209,7 @@ export default function MapApp() { const deck = ; const map = - {marker => } + {marker => } ; return <> diff --git a/docs/VALIDATION.md b/docs/VALIDATION.md index e8cd002..c273a85 100644 --- a/docs/VALIDATION.md +++ b/docs/VALIDATION.md @@ -247,3 +247,45 @@ with zero downloads or provider errors. Subsequent settled samples reported 1 ms and submission below 0.6 ms. The recovery upload interval also recorded seven additional CPU frames above 16.67 ms, with a window UI maximum of 27.6 ms; settled timing must not be presented as uninterrupted 60 fps during loading. + +## Sustained controller motion + +The earlier guest advanced the camera by `1 / simulationHz()` per presented +frame. Holding full Circle Pad input therefore moved 320 pixels in a second +at 60 presented frames, but 160 pixels at 30 frames. The same failure reproduces +with the actual previous compiled guest in QuickJS; the camera's exponential +integrator was correct when supplied with the elapsed interval. + +The 3DS host now supplies input-sampling microseconds as recorded frame data. +Pocket Map passes `inputDeltaSeconds()` to camera integration, drag filtering +and directional intent. Virtual timers, core ticks and resource work budgets +remain unchanged. The elapsed step is bounded to 66.666 ms: a long pause cannot +cause a large catch-up jump, but rates below 15 fps cannot retain real-time +travel under that bound. + +Vector labels mount at most 12 visible components and admit at most one new +identity per frame. Hidden candidates no longer create UI nodes or frame hooks. +Unchanged placements reuse their previous result. Predictive tile sorting runs +at 12 Hz while a viewport's tile set and zoom remain unchanged; crossing a tile +boundary or changing source/zoom recomputes demand in that frame. + +- 25 application tests / 981 assertions and TypeScript pass. Four directions + retain 320 pixels/second under 60/45/30 Hz and alternating 16.667/33.333/50 ms + samples. Tests also cover the resume bound, visible-tile admission and label + mount limits. +- The actual new compiled guest in QuickJS reports 320.006, 319.997 and 320.000 + pixels per second under 60-frame, 30-frame and mixed-cadence input; the previous + guest reports 320, 160 and 160. Both OSM and Hyrule pass 1,572 frames with a + 128 KiB stack and no outstanding staging tickets. +- Compiled guest + Wasm replay passes 17 checks across 1,903 frames, including + varying input intervals with real resource loading. Complete-Hyrule replay + remains 1,713 frames / 20 checks with zero Hyrule HTTP downloads. +- PocketJS passes 80 clock, tape, tile and 3DS transport/profile tests, and + TypeScript. Tape v4 reproduces input intervals; legacy tapes ignore live + timing and keep their nominal step. +- The production binary builds: 1,745,104 bytes, SHA-256 + `f452efd99ee29491279780c621f59961466444d6fc59ab5948cd9b1568644330`. + Deployment and physical held-stick acceptance of this revision are pending. + +These replays establish distance per input time and bound label work. They do +not establish uninterrupted 60 fps on hardware during resource materialization. diff --git a/docs/VECTOR_MAP.md b/docs/VECTOR_MAP.md index 9258eab..20ad1b9 100644 --- a/docs/VECTOR_MAP.md +++ b/docs/VECTOR_MAP.md @@ -189,3 +189,18 @@ provider modes, maximum-size geometry, malformed/truncated data, stale handles, shared staging credit, cancellation, failed uploads, polygon clipping and resource cleanup. Pocket Map tests cover polygon holes, dense-tile detail reduction, source routing, label/geometry deduplication and source/display LOD. + +## Motion and label work per frame + +The host passes its elapsed input-sampling interval into the recorded frame. +Pocket Map integrates controller velocity using `inputDeltaSeconds()` rather +than counting presented frames; missing a vblank therefore does not halve +travel speed. A 66.666 ms upper bound limits movement after a pause. Virtual +animation ticks and resource admissions keep their fixed frame budgets. + +Only 12 collision-tested vector labels can own UI components. Candidate windows +remain cached data; they do not each create a component or frame hook. Existing +visible identities stay mounted and at most one new label mounts per frame. +Predictive tile sorting is reused for up to 1/12 second while visible tile +bounds and zoom stay fixed. A newly exposed tile invalidates that reuse in the +same frame, preserving immediate visible demand. diff --git a/runtime b/runtime index 64bc5a0..5394eb2 160000 --- a/runtime +++ b/runtime @@ -1 +1 @@ -Subproject commit 64bc5a0eb272de5f832115e84fc5350e0a89ae05 +Subproject commit 5394eb2fd6f761f3bbd46b005af6d3c8ac4685ba diff --git a/scripts/quickjs-smoke.js b/scripts/quickjs-smoke.js index 9747896..f69bfd1 100644 --- a/scripts/quickjs-smoke.js +++ b/scripts/quickjs-smoke.js @@ -34,12 +34,22 @@ globalThis.offload = { }, }; globalThis.__simHz = 60; -function frames(n, buttons = 0, analog = 0x8080) { for (let i = 0; i < n; i++) { frame(buttons, analog, [], [], [], 0x8080); ticks++; } } +function frames(n, buttons = 0, analog = 0x8080, elapsedUs) { for (let i = 0; i < n; i++) { frame(buttons, analog, [], [], [], 0x8080, elapsedUs); ticks++; } } function check(value, message) { if (!value) throw new Error(message); } try { std.loadScript(scriptArgs[1] || "runtime/dist/3ds/guest/pocketmap-main.js"); const s = globalThis.__map; frames(30); check(s.mode() === "map", "offline mount"); session = 1; frames(90); check(s.front().tiles.every(t => s.frontView.state(t.input).status === "ready"), "tile reveal"); + const center = s.camera.view(), motion = []; + for (const cadence of [Array(60).fill(16667), Array(30).fill(33333), Array.from({ length: 30 }, (_, i) => [16667, 33333, 50000][i % 3])]) { + s.camera.jump(center.x, center.y, center.zoom); + frames(60, 0, 0xff80, 16667); const start = s.camera.view(); + for (const us of cadence) frames(1, 0, 0xff80, us); + motion.push((s.camera.view().x - start.x) * start.scale); + } + std.puts(JSON.stringify({ motionPixelsPerSecond: motion }) + "\n"); + check(motion.every(px => Math.abs(px - 320) < .02), "held stick speed depends on presentation cadence"); + s.camera.jump(center.x, center.y, center.zoom); frames(300, 0, 0x80ff); s.zoom(1); frames(90); s.zoom(-1); frames(90); s.openSearch(); s.key("t"); check(s.query() === "t", "local typing"); s.search(); frames(60); check(s.places().length === 1, "search"); s.go(); frames(90); check(s.pin().name === (hyrule ? "Kakariko" : "Tokyo"), "place navigation"); diff --git a/scripts/vector-sim.ts b/scripts/vector-sim.ts index 14281db..62a04b2 100644 --- a/scripts/vector-sim.ts +++ b/scripts/vector-sim.ts @@ -116,7 +116,7 @@ function check(ok: unknown, name: string) { if (!ok) throw new Error(name); checks.push(name); } -async function frames(n: number, buttons = 0, touch?: [number, number], analog = 0x8080) { +async function frames(n: number, buttons = 0, touch?: [number, number], analog = 0x8080, inputElapsedUs?: number) { let hit: number | undefined; if (touch) { wasm.render(); @@ -132,6 +132,7 @@ async function frames(n: number, buttons = 0, touch?: [number, number], analog = touch ? [hit] : [], touch ? [1] : [], 0x8080, + inputElapsedUs, ); wasm.tick(); const start = performance.now(); @@ -192,6 +193,7 @@ try { ); await shot("map"); check(s.annotations.rows().length > 0, "Independent label demand reveals atlas text"); + check(s.annotations.renderRows().length <= 12, "Only the bounded visible vector labels mount UI"); const before = { meshReplies, meshBytes, jsonBytes }, center = s.camera.view(); for (let z = 15; z <= 18; z++) { @@ -248,6 +250,18 @@ try { check(s.vector() && !s.planar(), "Hot switch returns to OSM geometry"); } } + if (!live) { + const center = s.camera.view(); + for (const cadence of [Array(60).fill(16667), Array(30).fill(33333), Array.from({ length: 30 }, (_, i) => [16667, 33333, 50000][i % 3])]) { + s.camera.jump(center.x, center.y, 14); + await frames(60, 0, undefined, 0xff80, 16667); + const start = s.camera.view(); + for (const us of cadence) await frames(1, 0, undefined, 0xff80, us); + const pixels = (s.camera.view().x - start.x) * start.scale; + check(Math.abs(pixels - 320) < .02, `Compiled guest holds 320 px/s over ${cadence.length} sampled frames`); + } + await frames(200); + } check( maxPending <= 3 && maxStaging <= 3 && maxEntries <= 40, "Shared admission, staging and residency remain bounded", diff --git a/test/model.test.ts b/test/model.test.ts index 623f05e..f3fa2eb 100644 --- a/test/model.test.ts +++ b/test/model.test.ts @@ -3,6 +3,7 @@ import { createRoot } from "solid-js"; import { createOffloadClient } from "@pocketjs/framework/offload"; import { runFrameHooks, resetFrameHooks } from "../runtime/framework/src/frame.ts"; import { __setAnalog } from "../runtime/framework/src/analog.ts"; +import { __advanceClock, resetClock } from "../runtime/framework/src/clock.ts"; import { BTN } from "@pocketjs/framework/input"; import { createMap } from "../app/model.ts"; test("camera keeps moving while host requests wait; search is an explicit bounded command", () => { @@ -21,3 +22,29 @@ test("camera keeps moving while host requests wait; search is an explicit bounde }); resetFrameHooks(); }); + +test("held full stick travels at the same speed across missed and uneven presentation intervals", () => { + const cadences = [60, 45, 30].map(hz => Array.from({ length: hz }, (_, i) => Math.round((i + 1) * 1e6 / hz) - Math.round(i * 1e6 / hz))); + cadences.push(Array.from({ length: 30 }, (_, i) => [16667, 33333, 50000][i % 3])); + for (const analog of [0xff80, 0x0080, 0x80ff, 0x8000]) for (const cadence of cadences) { + resetFrameHooks(); resetClock(); + createRoot(dispose => { + const io = createOffloadClient({ session: () => 1, submit: () => true, take: () => undefined, uploadImage: () => 1, releaseImage() {} }); + const s = createMap(io); + function frame(us: number) { __advanceClock(us); __setAnalog(analog); runFrameHooks(0); io.step(); } + for (let i = 0; i < 60; i++) frame(16667); // Settle the intentional acceleration. + const start = s.camera.view(); + let previous = start; + for (const us of cadence) { + frame(us); const next = s.camera.view(); + const speed = Math.hypot(next.x - previous.x, next.y - previous.y) * next.scale * 1e6 / us; + expect(Math.abs(speed - 320)).toBeLessThan(.001); previous = next; + } + expect(Math.hypot(previous.x - start.x, previous.y - start.y) * start.scale).toBeCloseTo(320, 3); + frame(3e6); const resumed = s.camera.view(); + expect(Math.hypot(resumed.x - previous.x, resumed.y - previous.y) * start.scale).toBeLessThan(21.334); + dispose(); io.dispose(); + }); + } + resetClock(); resetFrameHooks(); __setAnalog(0x8080); +}); diff --git a/test/navigation.test.ts b/test/navigation.test.ts index b1d2cb8..50979ad 100644 --- a/test/navigation.test.ts +++ b/test/navigation.test.ts @@ -1,6 +1,8 @@ import { expect, test } from "bun:test"; import { createRoot } from "solid-js"; import { createTileCamera } from "@pocketjs/framework/tile-viewport"; +import { createAnnotations } from "../app/annotations.ts"; +import { createResourceRuntime } from "@pocketjs/framework/resource-view"; import { createMapPrediction } from "../app/prediction.ts"; import { createMap } from "../app/model.ts"; import { createOffloadClient } from "@pocketjs/framework/offload"; @@ -96,3 +98,50 @@ test("marker index filters zoom/category and bounds replies; delayed bookmarks r } finally { service.close(); } } finally { rmSync(dir, { recursive: true, force: true }); } }); + +test("prediction reuse never delays a newly exposed tile and expires within a directional turn", () => { + const c = createTileCamera({ width: 400, height: 240, x: 128, y: 128, zoom: 4, minZoom: 0, maxZoom: 7 }); + const p = createMapPrediction(); p.reset(c.view()); + const first = p.plan(c.view(), 4, atlas); + c.drag(-5, 0); p.sample(c.view(), 1 / 60, false); + expect(p.plan(c.view(), 4, atlas)).toBe(first); + // The right viewport edge crosses a column before the 12 Hz refresh. + c.drag(-55, 0); p.sample(c.view(), 1 / 60, false); + const crossed = p.plan(c.view(), 4, atlas); + expect(crossed).not.toBe(first); + expect(crossed.visible.some(t => !first.visible.some(o => o.column === t.column && o.row === t.row))).toBe(true); + for (let i = 0; i < 5; i++) p.sample(c.view(), 1 / 60, false); + expect(p.plan(c.view(), 4, atlas)).not.toBe(crossed); +}); + +test("vector label candidates do not mount hidden UI and admit at most one new identity per frame", () => { + resetFrameHooks(); + createRoot(dispose => { + const replies: string[] = []; + let requests = 0; + const io = createOffloadClient({ session: () => 1, submit(raw) { + const r = JSON.parse(raw), offset = requests++ * 12; + const rows = Array.from({ length: 12 }, (_, i) => [offset + i, `地点${offset + i}`, "landmark", + 128 + ((i % 3) * 120 + 70 - 200) / 16384, 128 + (Math.floor(i / 3) * 40 + 45 - 120) / 16384]); + replies.push(JSON.stringify({ id: r.id, payload: JSON.stringify(rows) })); return true; + }, take: () => replies.shift(), uploadImage: () => 1, releaseImage() {} }); + const runtime = createResourceRuntime({ maxConcurrent: 3, startsPerFrame: 1, completionsPerFrame: 1, maxCollections: 1 }); + const labels = createAnnotations(io, runtime), view = { x: 128, y: 128, zoom: 14 }, info: MapInfo = { ...osm, render: "mesh", dataZoom: 14, markers: true }; + let previous = new Set(); + for (let i = 0; i < 50; i++) { + labels.update(view, 14, info); runtime.step(); io.step(); + const current = labels.renderRows(); + expect(current.length).toBeLessThanOrEqual(12); + expect(current.filter(m => !previous.has(m[0])).length).toBeLessThanOrEqual(1); + previous = new Set(current.map(m => m[0])); + } + expect(labels.rows().length).toBeGreaterThan(12); + expect(labels.renderRows()).toHaveLength(12); + const settled = labels.renderRows(); labels.update(view, 14, info); + expect(labels.renderRows()).toBe(settled); + labels.setLayer("off"); labels.update(view, 14, info); + expect(labels.renderRows()).toHaveLength(0); + labels.reset(); expect(labels.placement(0)).toBeUndefined(); + dispose(); io.dispose(); + }); resetFrameHooks(); +}); From 0fcb51c2fcdcad8220765b03d147be137cd17eff Mon Sep 17 00:00:00 2001 From: "Yifeng \"Evan\" Wang" <7312949+doodlewind@users.noreply.github.com> Date: Sun, 6 Sep 2026 22:35:16 -0700 Subject: [PATCH 10/13] docs(map): record verified controller fix deployment --- docs/VALIDATION.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/VALIDATION.md b/docs/VALIDATION.md index c273a85..a203fc0 100644 --- a/docs/VALIDATION.md +++ b/docs/VALIDATION.md @@ -285,7 +285,9 @@ boundary or changing source/zoom recomputes demand in that frame. timing and keep their nominal step. - The production binary builds: 1,745,104 bytes, SHA-256 `f452efd99ee29491279780c621f59961466444d6fc59ab5948cd9b1568644330`. - Deployment and physical held-stick acceptance of this revision are pending. + Uploaded to `192.168.8.102:5000` at `/3DS/pocketmap-main.3dsx` and read back + byte-for-byte equal, together with the existing app pairing key. Physical + held-stick acceptance of this revision remains pending. These replays establish distance per input time and bound label work. They do not establish uninterrupted 60 fps on hardware during resource materialization. From 3797cae2aa22cd68aa65c182b4327c5e7fdbc83c Mon Sep 17 00:00:00 2001 From: "Yifeng \"Evan\" Wang" <7312949+doodlewind@users.noreply.github.com> Date: Mon, 7 Sep 2026 00:06:42 -0700 Subject: [PATCH 11/13] feat(psp): add USB vector maps and single-screen navigation --- README.md | 8 +- app/annotations.ts | 63 ++++---- app/map-view.tsx | 67 +++++++++ app/model.ts | 14 +- app/prediction.ts | 19 ++- app/psp.tsx | 276 +++++++++++++++++++++++++++++++++++ app/psp/Psp.toml | 1 + app/ui.tsx | 54 +------ docs/PSP.md | 69 +++++++++ docs/images/psp-hyrule.png | Bin 0 -> 91360 bytes docs/images/psp-keyboard.png | Bin 0 -> 34562 bytes docs/images/psp-map.png | Bin 0 -> 47673 bytes host/serve-usb.ts | 26 ++++ package.json | 5 +- pocket.psp.json | 34 +++++ runtime | 2 +- scripts/psp-smoke.js | 35 +++++ scripts/psp.ts | 67 +++++++++ scripts/watch-psp-smoke.ts | 79 ++++++++++ 19 files changed, 721 insertions(+), 98 deletions(-) create mode 100644 app/map-view.tsx create mode 100644 app/psp.tsx create mode 100644 app/psp/Psp.toml create mode 100644 docs/PSP.md create mode 100644 docs/images/psp-hyrule.png create mode 100644 docs/images/psp-keyboard.png create mode 100644 docs/images/psp-map.png create mode 100644 host/serve-usb.ts create mode 100644 pocket.psp.json create mode 100644 scripts/psp-smoke.js create mode 100644 scripts/psp.ts create mode 100644 scripts/watch-psp-smoke.ts diff --git a/README.md b/README.md index a37d208..e93b33c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Pocket Map -A map browser for Nintendo 3DS, built with [PocketJS](https://github.com/pocket-stack/pocketjs) and SolidJS 1.9. Browse **OSM vector maps** or the complete Hyrule map from **The Legend of Zelda: Breath of the Wild**. Pan with the resistive touchpad, zoom, search and save places on the paired Mac. +A map browser for Nintendo 3DS and PSP, built with [PocketJS](https://github.com/pocket-stack/pocketjs) and SolidJS 1.9. Browse **OSM vector maps** or the complete Hyrule map from **The Legend of Zelda: Breath of the Wild**. Pan with the resistive touchpad, zoom, search and save places on the paired Mac. The Mac fetches OSM vector tiles, prepares bounded geometry and streams it to the 3DS GPU drawing path. Four real San Francisco tiles used **79.5% fewer terrain bytes** than the previous raw bitmap path; z14 geometry is reused through display z18. Hyrule retains its complete local raster atlas and 2,576 searchable places, with no internet requests while browsing. See [vector architecture, measurements and limits](docs/VECTOR_MAP.md). @@ -10,6 +10,12 @@ OSM map data © [OpenStreetMap contributors](https://www.openstreetmap.org/copyr These are **compiled guest + Wasm captures**, at the 3DS's 400×240 / 320×240 logical resolutions, not console photographs. Map artwork belongs to Nintendo; the pinned atlas and marker source is [Zelda Dungeon's map repository](https://github.com/zeldadungeon/maps/tree/d32a85656031d861cef38e32eb927a7d08a983a9/public/botw). Downloaded assets and generated databases stay outside Git. +## PSP over USB + +The PSP port renders the same OSM vector geometry on its local GE, with a 480×272 single-screen UI, shoulder menus, a virtual keyboard and saved places on the Mac. The Mac performs network requests, vector preparation and image decoding through PocketJS's native USB offload worker. Hyrule retains its raster path. See [PSP setup, controls and measured limits](docs/PSP.md). + +Actual PSP framebuffer showing Pocket Map's OSM vector renderer + ## Try it Requirements: Bun 1.3.14, Docker with the PocketJS 3DS toolchain (or a supported native devkitPro install), Git, a Mac and a 3DS on the same LAN, Homebrew Launcher and ftpd. The runtime submodule pins the mesh and image resource support used by this app. diff --git a/app/annotations.ts b/app/annotations.ts index 7a94cf9..77151f6 100644 --- a/app/annotations.ts +++ b/app/annotations.ts @@ -29,7 +29,7 @@ export function labelMetrics(name: string) { return result; } export const labelWidth = (name: string) => labelMetrics(name).width; -export function createAnnotations(io: ReturnType, runtime: ReturnType) { +export function createAnnotations(io: ReturnType, runtime: ReturnType, viewport = { width: 400, height: 240 }) { const [layer, setLayer] = createSignal("all"), [demand, setDemand] = createSignal([]); const collection = runtime.createCollection({ @@ -73,6 +73,7 @@ export function createAnnotations(io: ReturnType, runtime: Retur const [renderRows, setRenderRows] = createSignal([]); let last: { x: number; y: number; zoom: number; rows: MapMarker[] } | undefined; let settled = false; + let demandAt: { x: number; y: number; zoom: number; level: number; info: MapInfo; layer: MarkerLayer } | undefined; let placements = new Map(); return { layer, @@ -81,7 +82,7 @@ export function createAnnotations(io: ReturnType, runtime: Retur renderRows, placement: (id: number) => placements.get(id), reset() { - setDemand([]); setRenderRows([]); placements.clear(); last = undefined; + setDemand([]); setRenderRows([]); placements.clear(); last = undefined; demandAt = undefined; collection.clear(); }, update(camera: { x: number; y: number; zoom: number }, level: number, info: MapInfo) { @@ -89,30 +90,36 @@ export function createAnnotations(io: ReturnType, runtime: Retur const vector = info.render === "mesh", size = vector ? 256 : 512; const cells = Math.max(1, 2 ** (vector ? level : level - 1)); - const next: MarkerInput[] = - info.markers && layer() !== "off" - ? visibleTiles({ - ...camera, - zoom: vector ? camera.zoom : level, - level, - width: 400, - height: 240, - tileSize: size, - maxTiles: vector ? 12 : 4, - }) - .filter((t) => t.row >= 0 && t.row < cells && (vector || (t.column >= 0 && t.column < cells))) - .map((t) => ({ - source: info.source, - z: level, - x: vector ? ((t.column % cells) + cells) % cells : t.column, - y: t.row, - layer: layer(), - })) - : []; - const old = demand(); - if (next.length !== old.length || next.some((v, n) => { - const o = old[n]; return !o || v.source !== o.source || v.layer !== o.layer || v.z !== o.z || v.x !== o.x || v.y !== o.y; - })) setDemand(next); + const demandChanged = !demandAt || demandAt.x !== camera.x || demandAt.y !== camera.y + || demandAt.zoom !== camera.zoom || demandAt.level !== level + || demandAt.info !== info || demandAt.layer !== layer(); + if (demandChanged) { + demandAt = { ...camera, level, info, layer: layer() }; + const next: MarkerInput[] = + info.markers && layer() !== "off" + ? visibleTiles({ + ...camera, + zoom: vector ? camera.zoom : level, + level, + width: viewport.width, + height: viewport.height, + tileSize: size, + maxTiles: vector ? 12 : 4, + }) + .filter((t) => t.row >= 0 && t.row < cells && (vector || (t.column >= 0 && t.column < cells))) + .map((t) => ({ + source: info.source, + z: level, + x: vector ? ((t.column % cells) + cells) % cells : t.column, + y: t.row, + layer: layer(), + })) + : []; + const old = demand(); + if (next.length !== old.length || next.some((v, n) => { + const o = old[n]; return !o || v.source !== o.source || v.layer !== o.layer || v.z !== o.z || v.x !== o.x || v.y !== o.y; + })) setDemand(next); + } const candidates = rows(); if (settled && last?.x === camera.x && last.y === camera.y && last.zoom === camera.zoom && last.rows === candidates) return; last = { ...camera, rows: candidates }; @@ -123,8 +130,8 @@ export function createAnnotations(io: ReturnType, runtime: Retur function place(marker: MapMarker) { if (placed.size >= 12 || placed.has(marker[0]) || names.has(marker[1])) return; let dx = marker[3] - camera.x; dx -= Math.round(dx / 256) * 256; - const width = labelWidth(marker[1]), x = 200 + dx * scale - width / 2, y = 120 + (marker[4] - camera.y) * scale - 7; - if (x < 2 || x + width > 398 || y < 29 || y > 208) return; + const width = labelWidth(marker[1]), x = viewport.width / 2 + dx * scale - width / 2, y = viewport.height / 2 + (marker[4] - camera.y) * scale - 7; + if (x < 2 || x + width > viewport.width - 2 || y < 29 || y > viewport.height - 32) return; for (const p of placed.values()) if (x < p.x + p.width + 4 && x + width + 4 > p.x && Math.abs(y - p.y) < 19) return; placed.set(marker[0], { x, y, width }); names.add(marker[1]); selected.push(retained.get(marker[0]) ?? marker); } diff --git a/app/map-view.tsx b/app/map-view.tsx new file mode 100644 index 0000000..b3f1f29 --- /dev/null +++ b/app/map-view.tsx @@ -0,0 +1,67 @@ +import { createSignal, For, Show } from "solid-js"; +import { Image, Text, View, type NodeMirror } from "@pocketjs/framework/components"; +import { ResourceImage, ResourceMesh } from "@pocketjs/framework/resource"; +import { createResourceView } from "@pocketjs/framework/resource-view"; +import { onFrame } from "@pocketjs/framework/lifecycle"; +import * as hot from "@pocketjs/framework/hot"; +import { labelWidth, labelMetrics } from "./annotations.ts"; +import type { MapModel, Layer } from "./model.ts"; +import type { Place, MapMarker } from "../shared/types.ts"; +const MARKER_ICONS = { landmark: "marker-landmark.svg", tower: "marker-tower.svg", shrine: "marker-shrine.svg", stable: "marker-stable.svg", village: "marker-village.svg", seed: "marker-seed.svg", treasure: "marker-treasure.svg", enemy: "marker-enemy.svg", special: "marker-special.svg" }; +const box = (x: number, y: number, w: number, h: number) => ({ posType: 1, insetL: x, insetT: y, width: w, height: h }); + +export function TileLayer(p: { s: MapModel; back?: boolean }) { + let world: NodeMirror | undefined; + let last:{layer:Layer;x:number;y:number;zoom:number}|undefined; + const layer = () => (p.back ? p.s.back() : p.s.front()); + const resources = p.back ? p.s.backView : p.s.frontView; + onFrame(() => { + const l = layer(); if (!l || !world) return; + const view = p.s.camera.view();if(last?.layer===l&&last.x===view.x&&last.y===view.y&&last.zoom===view.zoom)return;last={layer:l,...view}; + const scale = 2 ** (view.zoom - l.level); + const worldWidth = 256 * 2 ** l.level; + let offsetX = l.originX - view.x * 2 ** l.level; + // Rebase at the viewport, including the nearest copy across the date line. + if (!p.s.planar()) offsetX -= Math.round(offsetX / worldWidth) * worldWidth; + hot.prop(world, "translateX", p.s.viewport.width / 2 + offsetX * scale); + hot.prop(world, "translateY", p.s.viewport.height / 2 + (l.originY - view.y * 2 ** l.level) * scale); + hot.prop(world, "scaleX", scale); hot.prop(world, "scaleY", scale); + }); + return + {tile => { const Tile = p.s.vector() ? ResourceMesh : ResourceImage; return resources.state(tile.input)} fallback={() => p.back || p.s.back() ? : + + + } errorFallback={() => Tile unavailable} />; }} + ; +} +function UnicodeAnnotation(p:{s:MapModel;place:Place;width:number}) { + const image=createResourceView(p.s.labels,{demand:()=>[{input:p.place,priority:30,pin:true}]}); + return image.state(p.place)} fallback={()=>} />; +} +export function Annotation(p: { s: MapModel; marker: MapMarker }) { + let root: NodeMirror | undefined; + const [visible,setVisible]=createSignal(false); + const vector=p.s.vector(),unicode=vector && /[^\x20-\x7e]/.test(p.marker[1]); + const place:Place={id:`label:${p.marker[0]}`,name:labelMetrics(p.marker[1]).text,detail:"",lat:0,lon:0,zoom:14}; + let lastPlacement:ReturnType; + const width=vector?labelWidth(p.marker[1]):118; + onFrame(() => { + if(vector){const at=p.s.annotations.placement(p.marker[0]);if(at===lastPlacement)return;lastPlacement=at;setVisible(!!at);hot.prop(root,"display",at?0:1);if(at){hot.prop(root,"translateX",at.x);hot.prop(root,"translateY",at.y);}return;} + const v = p.s.camera.view(), x = p.s.viewport.width / 2 + (p.marker[3] - v.x) * v.scale, y = p.s.viewport.height / 2 + (p.marker[4] - v.y) * v.scale; + hot.prop(root, "translateX", x - 7); hot.prop(root, "translateY", y - 7); + hot.prop(root, "display", x < -100 || x > p.s.viewport.width + 10 || y < 18 || y > p.s.viewport.height - 5 ? 1 : 0); + }); + return + + + + {p.marker[1].length > 16 ? p.marker[1].slice(0, 13) + "..." : p.marker[1]} + }> + + + {labelMetrics(p.marker[1]).text} + }> + + ; +} diff --git a/app/model.ts b/app/model.ts index 4031653..1edd77d 100644 --- a/app/model.ts +++ b/app/model.ts @@ -19,7 +19,7 @@ export const MENU = { places: ["Search places", "Saved places", "Save map center", "Back to pin", "Map home"], map: ["Zoom in", "Zoom out", "Map labels", "Switch map", "Clear pin", "Retry tiles", "About & controls"], }; -export function createMap(io = offload()) { +export function createMap(io = offload(), viewport = { width: 400, height: 240 }, tileEntries = 40) { const [info, setInfo] = createSignal(); const [online, setOnline] = createSignal(false), [status, setStatus] = createSignal("Waiting for paired Mac"); const [mode, setMode] = createSignal("map"); @@ -34,13 +34,13 @@ export function createMap(io = offload()) { const remembered = new Map(); const planar = () => info()?.space === "planar"; const p = project(HOME.lat, HOME.lon); - const camera = createTileCamera({ width: 400, height: 240, x: p.x, y: p.y, zoom: HOME.zoom, minZoom: 1, maxZoom: 18, bounds: { width: 256, height: 256, wrapX: true } }); + const camera = createTileCamera({ ...viewport, x: p.x, y: p.y, zoom: HOME.zoom, minZoom: 1, maxZoom: 18, bounds: { width: 256, height: 256, wrapX: true } }); const runtime = createResourceRuntime({ maxConcurrent: 3, startsPerFrame: 1, completionsPerFrame: 1, maxCollections: 6, available: () => !switching() && io.connected() && !!info() && io.pending() < 3 }); const rasterTiles = createOffloadImageCollection(runtime, io, { key: (i: TileInput) => `${i.source}/${i.z}/${i.x}/${i.y}`, method: "map.tile", payload: JSON.stringify, - width: 256, height: 256, maxEntries: 40, maxViews: 2, maxDemandsPerView: 24, retry: { attempts: 3, delayFrames: 90, maxDelayFrames: 360 } }); + width: 256, height: 256, maxEntries: tileEntries, maxViews: 2, maxDemandsPerView: 24, retry: { attempts: 3, delayFrames: 90, maxDelayFrames: 360 } }); const vector = () => info()?.render === "mesh"; const meshTiles = createOffloadMeshCollection(runtime, io, {key:(i:TileInput)=>`${i.source}/${i.z}/${i.x}/${i.y}`,method:"map.mesh",payload:JSON.stringify, - maxEntries:40,maxViews:2,maxDemandsPerView:24,retry:{attempts:3,delayFrames:90,maxDelayFrames:360}}); + maxEntries:tileEntries,maxViews:2,maxDemandsPerView:24,retry:{attempts:3,delayFrames:90,maxDelayFrames:360}}); const tiles = { invalidate(){rasterTiles.invalidate();meshTiles.invalidate();},clear(){rasterTiles.clear();meshTiles.clear();},stats:()=>vector()?meshTiles.stats():rasterTiles.stats() }; const labels = createOffloadImageCollection(runtime, io, { key: (i: Place) => `${i.name}/${i.detail}`, method: "map.label", payload: i => JSON.stringify({ name: i.name, detail: i.detail }), width: 256, height: 32, maxEntries: 24, maxViews: 29, maxDemandsPerView: 1 }); @@ -64,7 +64,7 @@ export function createMap(io = offload()) { const results = createResourceView(searches, { demand: () => submitted() ? [{ input: submitted()!, priority: -10, pin: true }] : [] }); const places = createMemo(() => submitted() ? results.value(submitted()!) ?? [] : []); const saved = createSavedPlaces(io, runtime, mode, setMode, () => info()?.source); - const annotations = createAnnotations(io, runtime), prediction = createMapPrediction(); + const annotations = createAnnotations(io, runtime, viewport), prediction = createMapPrediction(viewport); const typing = () => mode() === "search" || mode() === "name"; const listing = () => mode() === "results" || mode() === "saved"; const rows = () => mode() === "saved" ? saved.page()?.items ?? [] : places(); @@ -196,7 +196,7 @@ export function createMap(io = offload()) { zoomDirection = zd; const shoulders = buttons & (BTN.LTRIGGER | BTN.RTRIGGER); if (!shoulders) { confirmed = false; if (menu()) setMenu(undefined); } - else if (!zl && !switching() && !saved.modal() && !saved.busy() && mode() !== "name" && !confirmed && !menu() && shoulders !== (previousButtons & (BTN.LTRIGGER | BTN.RTRIGGER))) { + else if (!zl && !switching() && !saved.modal() && !saved.busy() && !typing() && !confirmed && !menu() && shoulders !== (previousButtons & (BTN.LTRIGGER | BTN.RTRIGGER))) { setMenu(shoulders & BTN.LTRIGGER ? "places" : "map"); setMenuIndex(0); camera.stop(); } const canPan = mode() === "map" && !shoulders && !zl && !switching() && !saved.modal(); @@ -231,7 +231,7 @@ export function createMap(io = offload()) { } if (back() && front()?.tiles.every(t => frontView.state(t.input).status === "ready")) setBack(undefined); }); - return { io, runtime, tiles, vector, labels, frontView, backView, info, planar, online, zoomHeld, switching, sourceError, maps, choices, choosing, choose, openSources, switchMap, annotations, status, mode, setMode, query, setQuery, submitted, results, places, selection, setSelection, pin, menu, menuIndex, + return { viewport, io, runtime, tiles, vector, labels, frontView, backView, info, planar, online, zoomHeld, switching, sourceError, maps, choices, choosing, choose, openSources, switchMap, annotations, status, mode, setMode, query, setQuery, submitted, results, places, selection, setSelection, pin, menu, menuIndex, shift, symbols, front, back, camera, saved, typing, listing, rows, selectedIndex, select, saveCurrent, lookAhead, search, openSearch, go, zoom, key, dismiss, runMenu, clearBack: () => setBack(undefined), diagnostics: () => ({ frame, pending: io.pending(), resources: runtime.stats(), tiles: tiles.stats(), camera: camera.view() }), diff --git a/app/prediction.ts b/app/prediction.ts index f0fbe9d..9b5077d 100644 --- a/app/prediction.ts +++ b/app/prediction.ts @@ -4,9 +4,9 @@ import { wrapTile } from "./geo.ts"; type View = ReturnType["view"]>; export interface PlannedTile { input: TileInput; column: number; row: number; priority: number } interface Plan { visible: PlannedTile[]; extra: PlannedTile[]; intent: { x: number; y: number; confidence: number } } -export function createMapPrediction() { +export function createMapPrediction(viewport = { width: 400, height: 240 }) { const intent = createTileIntent(); let previous: View | undefined, now = 0, zoomUntil = 0; - let cached: { info: MapInfo; level: number; zoom: number; target: number; x0: number; x1: number; y0: number; y1: number; at: number; plan: Plan } | undefined; + let cached: { info: MapInfo; level: number; zoom: number; target: number; x0: number; x1: number; y0: number; y1: number; at: number; zoomPrediction: boolean; x: number; y: number; plan: Plan } | undefined; function reset(view: View) { intent.reset(); previous = view; zoomUntil = 0; cached = undefined; } return { reset, @@ -22,12 +22,16 @@ export function createMapPrediction() { // Re-sort predictive demand at most 12 times/second while the visible // tile set is unchanged. A newly exposed row/column is never delayed. const scale = 2 ** level / 256, screen = 2 ** view.zoom; - const x0 = Math.floor((view.x - 200 / screen) * scale), x1 = Math.ceil((view.x + 200 / screen) * scale) - 1; - const y0 = Math.floor((view.y - 120 / screen) * scale), y1 = Math.ceil((view.y + 120 / screen) * scale) - 1; + const x0 = Math.floor((view.x - viewport.width / 2 / screen) * scale), x1 = Math.ceil((view.x + viewport.width / 2 / screen) * scale) - 1; + const y0 = Math.floor((view.y - viewport.height / 2 / screen) * scale), y1 = Math.ceil((view.y + viewport.height / 2 / screen) * scale) - 1; + const stationary = cached?.plan.intent.confidence === 0 + && cached.x === view.x && cached.y === view.y && !view.moving && now >= zoomUntil; if (cached && cached.info === info && cached.level === level && cached.zoom === view.zoom && cached.target === view.targetZoom - && cached.x0 === x0 && cached.x1 === x1 && cached.y0 === y0 && cached.y1 === y1 && now - cached.at < 1 / 12 - 1e-8) return cached.plan; + && cached.x0 === x0 && cached.x1 === x1 && cached.y0 === y0 && cached.y1 === y1 + && cached.zoomPrediction === (now < zoomUntil) + && (stationary || now - cached.at < 1 / 12 - 1e-8)) return cached.plan; const local = info.local === true, lead = intent.predict(local ? 512 : 128), directional = lead.confidence > .45; - const options = { ...view, level, width: 400, height: 240, maxTiles: 12, margin: local ? 256 : 128, + const options = { ...view, level, ...viewport, maxTiles: 12, margin: local ? 256 : 128, leadX: lead.x, leadY: lead.y, directional, maxExtra: info.prefetch === false ? 0 : local ? 12 : 4 }; const window = planTileWindow(options); const address = (list: typeof window.visible, z: number): PlannedTile[] => list @@ -41,7 +45,8 @@ export function createMapPrediction() { const extra = [...zoomTiles.map(t => ({ ...t, priority: 300 + t.priority })), ...address(window.lookAhead, level).map(t => ({ ...t, priority: 1000 + t.priority }))].slice(0, local ? 12 : 4); const plan = { visible: address(window.visible, level), extra, intent: lead }; - cached = { info, level, zoom: view.zoom, target: view.targetZoom, x0, x1, y0, y1, at: now, plan }; + cached = { info, level, zoom: view.zoom, target: view.targetZoom, x0, x1, y0, y1, at: now, + zoomPrediction: now < zoomUntil, x: view.x, y: view.y, plan }; return plan; }, }; diff --git a/app/psp.tsx b/app/psp.tsx new file mode 100644 index 0000000..8f405de --- /dev/null +++ b/app/psp.tsx @@ -0,0 +1,276 @@ +import { createEffect, untrack, For, Show } from "solid-js"; +import { mount } from "@pocketjs/framework/solid"; +import { + Image, + Text, + View, + type NodeMirror, +} from "@pocketjs/framework/components"; +import { ClassicFace, ClassicPanel } from "@pocketjs/framework/classic"; +import { ResourceImage } from "@pocketjs/framework/resource"; +import { createResourceView } from "@pocketjs/framework/resource-view"; +import type { Place } from "../shared/types.ts"; +import { createOsk, Osk } from "@pocketjs/framework/osk"; +import { onFrame, onButtonPress } from "@pocketjs/framework/lifecycle"; +import { BTN } from "@pocketjs/framework/input"; +import * as hot from "@pocketjs/framework/hot"; +import { createMap, MENU, type MapModel } from "./model.ts"; +import { TileLayer, Annotation } from "./map-view.tsx"; +import { worldPosition } from "./geo.ts"; +const box = (x: number, y: number, w: number, h: number) => ({ + posType: 1, + insetL: x, + insetT: y, + width: w, + height: h, +}); +function RowLabel(p: { + s: MapModel; + place: () => Place | undefined; + title: () => string; + selected: () => boolean; +}) { + const unicode = () => !!p.place() && /[^\x20-\x7e]/.test(p.place()!.name); + const image = createResourceView(p.s.labels, { + demand: () => + unicode() ? [{ input: p.place()!, priority: -5, pin: true }] : [], + }); + return ( + + {p.title().slice(0, 45)} + + } + > + image.state(p.place()!)} + fallback={() => ( + + )} + /> + + ); +} +export function PspMapApp() { + const s = createMap(undefined, { width: 480, height: 272 }, 24); + (globalThis as unknown as { __map: typeof s }).__map = s; + const osk = createOsk({ + value: () => (s.mode() === "name" ? s.saved.name() : s.query()), + setValue: (text) => + s.mode() === "name" ? s.saved.changeName(text) : s.setQuery(text), + maxLength: 36, + closeOnCommit: false, + onCommit: () => s.key("GO"), + onClose: s.dismiss, + }); + createEffect(() => { + if (s.typing()) untrack(osk.open); + else osk.close(); + }); + createEffect(() => s.saved.setModal(!!s.saved.deleting())); + onButtonPress(BTN.SQUARE, () => { + if (s.mode() === "saved" && !s.menu() && !s.saved.modal()) + s.saved.askRemove(); + }); + onButtonPress(BTN.CIRCLE, () => { + if (s.saved.deleting() && !s.saved.busy()) s.saved.remove(); + }); + onButtonPress(BTN.START, () => { + if (s.mode() === "name") { + osk.open(); + return; + } + if (s.mode() === "saved" && s.saved.selected()) + s.saved.begin(s.saved.selected()!, true); + else if (s.listing() || s.mode() === "map") s.saveCurrent(); + }); + let marker: NodeMirror | undefined, zoom: NodeMirror | undefined; + onFrame(() => { + const v = s.camera.view(); + hot.text(zoom, `z${v.zoom.toFixed(1)}`); + const pin = s.pin(); + if (pin) { + const p = worldPosition(pin); + let dx = p.x - v.x; + if (!s.planar()) dx -= Math.round(dx / 256) * 256; + hot.prop(marker, "translateX", 240 + dx * v.scale - 8); + hot.prop(marker, "translateY", 136 + (p.y - v.y) * v.scale - 22); + } + }); + const rows = () => + s.menu() + ? MENU[s.menu()!] + : s.choosing() + ? s.choices() + : s.rows().map((p) => p.name); + const selected = () => + s.menu() ? s.menuIndex() : s.choosing() ? s.selection() : s.selectedIndex(); + const empty = () => + s.mode() === "saved" + ? s.saved.state().status === "pending" + ? "Loading saved places..." + : s.saved.state().status === "error" + ? "Saved places unavailable. Reopen to retry." + : "No saved places. START saves this view." + : s.submitted() && s.results.state(s.submitted()!).status === "pending" + ? "Searching places on your Mac..." + : s.submitted() && s.results.state(s.submitted()!).status === "error" + ? "Search unavailable. Triangle edits the query." + : "No places found. Triangle tries another query."; + const title = () => + s.menu() === "places" + ? "Places" + : s.menu() === "map" + ? "Map controls" + : s.choosing() + ? s.mode() === "sources" + ? "Choose map" + : "Map labels" + : s.mode() === "saved" + ? "Saved on your Mac" + : `Places: ${s.query()}`; + // Build each bounded subtree before mounting the outer screen on QuickJS. + const tiles = ( + + + + + {(marker) => } + + + + ); + const panel = ( + + + + {title().slice(0, 44)} + + + {(row, i) => ( + + (s.listing() ? s.rows()[i()] : undefined)} + title={() => row} + selected={() => selected() === i()} + /> + + )} + + + + {empty()} + + + + {s.mode() === "saved" + ? "O: open START: rename Square: delete X: map" + : "D-pad: choose O: open X: map"} + + + + ); + const keyboard = ( + + + + + {s.mode() === "name" ? "Save: " : "Search: "} + {osk.display().slice(-52)} + + + + + {s.saved.busy() + ? "Saving on your Mac..." + : s.saved.error() || + "D-pad + O: type Square: delete Triangle: space START: submit"} + + + + ); + return ( + + {tiles} + + + + Pocket Map + + + {s.online() ? "USB / PSPLINK" : "Mac disconnected"} + + + z14.0 + + + + + Analog: pan L: places R: zoom / map Triangle: search + + + {s.info()?.attribution || s.status()} + + + {panel} + + + + Pocket Map / PSP + + + Move with the analog stick or D-pad. Hold L for places, R for zoom + and map settings. Choose with D-pad and O. Triangle searches. START + saves a place; in Saved it renames. Left/right turns saved pages. + SELECT recalibrates the resting stick. X returns to the map. + + + + + + + Delete saved place? + + + {s.saved.deleting()?.name} + + + {s.saved.busy() + ? "Deleting on your Mac..." + : s.saved.error() || "O: delete X: keep place"} + + + + {keyboard} + + ); +} +mount(() => ); diff --git a/app/psp/Psp.toml b/app/psp/Psp.toml new file mode 100644 index 0000000..e2a98fc --- /dev/null +++ b/app/psp/Psp.toml @@ -0,0 +1 @@ +title = "Pocket Map" diff --git a/app/ui.tsx b/app/ui.tsx index da67921..c766a73 100644 --- a/app/ui.tsx +++ b/app/ui.tsx @@ -11,61 +11,9 @@ import {labelWidth,labelMetrics} from "./annotations.ts"; import { createMap, MENU, type MapModel, type Layer } from "./model.ts"; import { worldPosition, unproject, scaleBar } from "./geo.ts"; import type { Place, MapMarker } from "../shared/types.ts"; -const MARKER_ICONS = { landmark: "marker-landmark.svg", tower: "marker-tower.svg", shrine: "marker-shrine.svg", stable: "marker-stable.svg", village: "marker-village.svg", seed: "marker-seed.svg", treasure: "marker-treasure.svg", enemy: "marker-enemy.svg", special: "marker-special.svg" }; +import { TileLayer, Annotation } from "./map-view.tsx"; const box = (x: number, y: number, w: number, h: number) => ({ posType: 1, insetL: x, insetT: y, width: w, height: h }); -function TileLayer(p: { s: MapModel; back?: boolean }) { - let world: NodeMirror | undefined; - const layer = () => (p.back ? p.s.back() : p.s.front()); - const resources = p.back ? p.s.backView : p.s.frontView; - onFrame(() => { - const l = layer(); if (!l || !world) return; - const view = p.s.camera.view(), scale = 2 ** (view.zoom - l.level); - const worldWidth = 256 * 2 ** l.level; - let offsetX = l.originX - view.x * 2 ** l.level; - // Rebase at the viewport, including the nearest copy across the date line. - if (!p.s.planar()) offsetX -= Math.round(offsetX / worldWidth) * worldWidth; - hot.prop(world, "translateX", 200 + offsetX * scale); - hot.prop(world, "translateY", 120 + (l.originY - view.y * 2 ** l.level) * scale); - hot.prop(world, "scaleX", scale); hot.prop(world, "scaleY", scale); - }); - return - {tile => { const Tile = p.s.vector() ? ResourceMesh : ResourceImage; return resources.state(tile.input)} fallback={() => p.back || p.s.back() ? : - - - } errorFallback={() => Tile unavailable} />; }} - ; -} -function UnicodeAnnotation(p:{s:MapModel;place:Place;width:number}) { - const image=createResourceView(p.s.labels,{demand:()=>[{input:p.place,priority:30,pin:true}]}); - return image.state(p.place)} fallback={()=>} />; -} -function Annotation(p: { s: MapModel; marker: MapMarker }) { - let root: NodeMirror | undefined; - const [visible,setVisible]=createSignal(false); - const vector=p.s.vector(),unicode=vector && /[^\x20-\x7e]/.test(p.marker[1]); - const place:Place={id:`label:${p.marker[0]}`,name:labelMetrics(p.marker[1]).text,detail:"",lat:0,lon:0,zoom:14}; - const width=vector?labelWidth(p.marker[1]):118; - onFrame(() => { - if(vector){const at=p.s.annotations.placement(p.marker[0]);setVisible(!!at);hot.prop(root,"display",at?0:1);if(at){hot.prop(root,"translateX",at.x);hot.prop(root,"translateY",at.y);}return;} - const v = p.s.camera.view(), x = 200 + (p.marker[3] - v.x) * v.scale, y = 120 + (p.marker[4] - v.y) * v.scale; - hot.prop(root, "translateX", x - 7); hot.prop(root, "translateY", y - 7); - hot.prop(root, "display", x < -100 || x > 410 || y < 18 || y > 235 ? 1 : 0); - }); - return - - - - {p.marker[1].length > 16 ? p.marker[1].slice(0, 13) + "..." : p.marker[1]} - }> - - - {labelMetrics(p.marker[1]).text} - }> - - ; -} function ZoomRail(p: { s: MapModel }) { let thumb: NodeMirror | undefined, label: NodeMirror | undefined; onFrame(() => { diff --git a/docs/PSP.md b/docs/PSP.md new file mode 100644 index 0000000..7d992b9 --- /dev/null +++ b/docs/PSP.md @@ -0,0 +1,69 @@ +# Pocket Map on PSP + +The PSP version uses **PSPLINK USB for capabilities and the local GE for rendering**. The Mac fetches and parses OSM vector tiles, simplifies and triangulates them into PMH1 meshes, and decodes Hyrule images. The PSP pans and zooms its cached map without requesting a new screen image from the Mac. Search, saved places, labels and cache ownership share the 3DS model and provider. + +## Build and run + +Use the pinned PocketJS runtime, Bun dependencies and PSP toolchain. Install `usbhostfs_pc` and `pspsh` and start PSPLINK on the USB-connected console. + +```sh +bun run psp +# Keep these running in separate terminals. Only one usbhostfs process +# should own this PSP; its mounted root must match host:psp. +usbhostfs_pc -b 10000 dist/psplink +bun run host:psp +pspsh -e 'ldstart host0:/pocket-map.prx' +``` + +`dist/psp/EBOOT.PBP` is also generated, with the XMB title **Pocket Map**. To install it to a Memory Stick through an active PSPLINK session: + +```sh +cp dist/psp/EBOOT.PBP dist/psplink/pocket-map.pbp +pspsh -e 'mkdir ms0:/PSP/GAME/PocketMap' +pspsh -e 'cp host0:/pocket-map.pbp ms0:/PSP/GAME/PocketMap/EBOOT.PBP' +pspsh -e 'cp ms0:/PSP/GAME/PocketMap/EBOOT.PBP host0:/pocket-map-readback.pbp' +cmp dist/psp/EBOOT.PBP dist/psplink/pocket-map-readback.pbp +``` + +Rebuilds require a module restart: `pspsh -e reset`, wait for the USB connection, then load the PRX again. **The EBOOT does not install or start the PSPLINK USB driver.** Uncached content requires a running PSPLINK host0 connection and Mac provider. Hardware runtime validation used the PRX under PSPLINK; Memory Stick installation was checked by file readback. Standalone XMB USB startup has not been implemented or validated. `ldstart` loads the PRX, not the packaged PBP. + +Rest the analog nub at launch. The PSP host calibrates a stable center from 16 samples within a bounded startup window; full travel is rescaled around that center. Hold **SELECT with the nub at rest** to repeat calibration. The shared runtime then applies its normal deadzone. This addresses the test PSP's untouched raw reading of approximately `(162,133)` instead of `(128,128)`. + +| Control | Action | +| --- | --- | +| Analog nub / D-pad | Pan locally | +| Hold L, D-pad, Circle | Search, saved places, save center, return to pin or home | +| Hold R, D-pad, Circle | Zoom, labels, source selection, retry or help | +| Triangle | Open the keyboard | +| Keyboard: D-pad + Circle | Choose and type a key | +| Keyboard: Square / Triangle | Backspace / space | +| Keyboard: R / L | Uppercase / symbols | +| START | Submit text; save the map center or a search result | +| Saved places: START / Square | Rename / delete with confirmation | +| Saved places: left/right | Turn pages | +| Cross | Close keyboard, return to map, or cancel deletion | +| SELECT at rest | Recalibrate the analog nub | + +The keyboard uses the framework's modal input ownership, so its shoulder shortcuts cannot also open the map menus. Hyrule remains available through R → Switch map after `bun run prepare:hyrule` has downloaded the local atlas. + +## Resource limits + +The viewport is **480×272**. The PSP selects up to 24 terrain resources rather than the 3DS configuration's 40. Native transport has eight fixed staging slots; the shared resource runtime admits three concurrent reads and materializes one completion per frame. Retained GE vertex allocations, including retired buffers, have a 4 MiB limit. The Mac's SQLite HTTP cache and saved-place store remain under ignored `.local/` and can be reused by the LAN provider. + +Four sampled San Francisco PMH1 meshes total 107,464 terrain bytes (26,866 bytes/tile on average), compared with 524,288 bytes for four raw RGB565 tiles. A horizontal, integer-zoom pan exposing 3.75 tiles/second would require approximately 0.10 MB/s of terrain payload for those samples. **This is a workload estimate, not a measured USB ceiling**; it excludes labels, envelope/file RPC overhead, other movement directions and denser tiles. + +Pocket YouTube established the USB host0 transport route. Map tiles require independent request identities and reliable completion ownership, while video can discard superseded whole frames. PocketJS now places the blocking host0 RPCs on a lower-priority native worker; no file reads, image codecs or MVT parsing run inside the map's JavaScript frame callback. See the runtime's [PSP offload contract](../runtime/docs/PSP_OFFLOAD.md). + +## Hardware evidence + +The real PSP completed the scripted checkpoints: OSM map, keyboard typing/backspace, San Francisco search, continuous pan, zoom, save, saved-place list, confirmed deletion, Hyrule, and return to OSM. The test removes the bookmark it creates. Captures below are **real PSP framebuffers obtained through PSPLINK**, with the UI thread briefly suspended after a checkpoint so the framebuffer is complete. They are not physical-button acceptance receipts. + +

Real PSP rendering San Francisco vector geometry

+

Real PSP search keyboard with its text field

+

Real PSP rendering locally cached Hyrule raster tiles

+ +On the same settled SF view at 333 MHz, elapsed CPU-side frame work changed from approximately **33.5 ms → 18.1 ms → 14.3 ms** after skipping unchanged resource unions and repeated stationary-map calculations. Stable samples then advanced by 120 frames per approximately 2.00 seconds. Those settled frames fit 60 Hz; moving into new resources and mounting the keyboard/menu still produce longer frames. GE submission measured roughly 0.4–0.5 ms; submission duration alone is not GPU execution time. + +The USB host process was suspended for more than five seconds while the app ran. The PSP UI thread's run counter continued advancing and its cached map survived; communication recovered when the process resumed. This exercises a blocked transport, not just a provider error response. Performance logs taken during debugger screenshots include debugger preemption and should not be used as an uncontaminated frame-time percentile benchmark. + +To repeat the scripted hardware run, build with `bun run psp --smoke`, start `bun run test:psp:watch`, reset/load the PRX, and inspect `dist/qa/psp/smoke.json`. `--smoke` overrides controller input and disables automatic framebuffer dumps. Rebuild without that option and reload before handing the PSP back for manual use. diff --git a/docs/images/psp-hyrule.png b/docs/images/psp-hyrule.png new file mode 100644 index 0000000000000000000000000000000000000000..13edb1598a0088baa34c6ad82aa6c4c51aaf92ba GIT binary patch literal 91360 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

) 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ۓ^Ets0W?UG9!%kTDxY@#iiepK+K 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 Hu0mjf#q%#C literal 0 HcmV?d00001 diff --git a/host/serve-usb.ts b/host/serve-usb.ts new file mode 100644 index 0000000..d98fcf8 --- /dev/null +++ b/host/serve-usb.ts @@ -0,0 +1,26 @@ +import { resolve } from "node:path"; +import { connectOffloadUsbProvider } from "@pocketjs/framework/offload/provider"; +import { defaultConfig } from "./config.ts"; +const root = resolve(import.meta.dir, ".."); +const overrides = await Bun.file(resolve(root, ".local/provider.json")) + .json() + .catch(() => ({})); +const config = { + ...defaultConfig, + ...overrides, + cache: resolve(root, ".local/cache.sqlite"), + atlas: resolve(root, ".local/hyrule"), + kind: process.argv.includes("--hyrule") ? "hyrule" : "osm", +}; +const provider = connectOffloadUsbProvider({ + directory: resolve(root, "dist/psplink"), + app: "dev.pocket-stack.map", + worker: new URL("./worker.ts", import.meta.url), + data: config, + log: (message: string) => console.log(new Date().toISOString(), message), +}); +for (const signal of ["SIGINT", "SIGTERM"] as const) + process.on(signal, () => { + provider.close(); + process.exit(0); + }); diff --git a/package.json b/package.json index 1f3a68c..cd36157 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,10 @@ "sim": "bun scripts/sim.ts", "prepare:hyrule": "bun scripts/prepare-hyrule.ts", "test": "bun test --conditions=browser test/geo.test.ts test/provider.test.ts test/model.test.ts test/bookmarks.test.ts test/transport.test.ts test/atlas.test.ts test/navigation.test.ts test/vector.test.ts", - "check": "bun run test && runtime/node_modules/.bin/tsc --noEmit" + "check": "bun run test && runtime/node_modules/.bin/tsc --noEmit", + "psp": "bun scripts/psp.ts", + "host:psp": "bun host/serve-usb.ts", + "test:psp:watch": "bun scripts/watch-psp-smoke.ts" }, "dependencies": { "@mapbox/vector-tile": "3.0.0", diff --git a/pocket.psp.json b/pocket.psp.json new file mode 100644 index 0000000..da34a86 --- /dev/null +++ b/pocket.psp.json @@ -0,0 +1,34 @@ +{ + "$schema": "https://pocketjs.dev/schema/pocket-2.json", + "pocket": 2, + "id": "dev.pocket-stack.map", + "name": "pocket-map", + "title": "Pocket Map", + "version": "0.1.0", + "engine": { + "capabilities": { + "requires": [ + "io.offload", + "text.glyphs.baked", + "input.buttons" + ], + "enhances": [ + "input.analog.left" + ] + } + }, + "app": { + "entry": "app/psp.tsx", + "output": "pocketmap-psp", + "framework": "solid", + "viewport": { + "fixed": { + "logical": [ + 480, + 272 + ], + "presentation": "native" + } + } + } +} diff --git a/runtime b/runtime index 5394eb2..23aaff1 160000 --- a/runtime +++ b/runtime @@ -1 +1 @@ -Subproject commit 5394eb2fd6f761f3bbd46b005af6d3c8ac4685ba +Subproject commit 23aaff18ac20da4111a01645ef82616fdfe1411d diff --git a/scripts/psp-smoke.js b/scripts/psp-smoke.js new file mode 100644 index 0000000..497765a --- /dev/null +++ b/scripts/psp-smoke.js @@ -0,0 +1,35 @@ +// Appended only to the --smoke guest. Hardware receives the production UI and +// provider with a deterministic controller driver; no device IO is added here. +(() => { + const frame = globalThis.frame, s = globalThis.__map; + let phase=0, age=0, total=0, marked="", ended=false; + const QA="PSP USB regression"; + function mark(name){if(marked===name)return;const id=s.io.request("map.info",JSON.stringify({qa:name}),()=>{});if(id)marked=name;} + function next(){phase++;age=0;} + function ready(){return s.front()?.tiles.every(t=>s.frontView.state(t.input).status==="ready");} + function require(value,label){if(!value){mark(`FAILED ${label}`);ended=true;}} + globalThis.frame=(...args)=>{ + age++;total++;args[0]=0;args[1]=0x8080; + if(!ended){ + if(total>9000){mark(`FAILED timeout phase ${phase}`);ended=true;} + if(phase===0){if(s.info()&&ready()&&age>100){mark("map");next();}} + else if(phase===1){ + if(age===30)args[0]=0x1000; + if(age===60)mark("keyboard"); + if(age===80)args[0]=0x2000; + if(age===90){require(s.query().length>0,"keyboard type");args[0]=0x8000;} + if(age===100){require(s.query()==="","keyboard delete");s.setQuery("San Francisco");} + if(age===120)args[0]=8; + if(s.mode()==="results")next(); + } + else if(phase===2){if(s.rows().length){mark("search");if(age>140){args[0]=0x2000;next();}}} + else if(phase===3){if(age>120&&age<300)args[1]=0xff80;if(age===370)mark("pan");if(age>450){next();}} + else if(phase===4){if(age===20)args[0]=0x200;if(age===21)args[0]=0x2200;if(age>100&&ready()){mark("zoom");next();}} + else if(phase===5){if(age===80)args[0]=8;if(age===110){require(s.mode()==="name","save keyboard");s.saved.changeName(QA);mark("save");}if(age===140)args[0]=8;if(s.mode()==="saved")next();} + else if(phase===6){if(s.saved.page()?.items.some(p=>p.name===QA)){mark("saved");if(age===120)args[0]=0x8000;if(age===160)args[0]=0x2000;}if(age>160&&!s.saved.busy()&&!s.saved.deleting()&&!s.saved.page()?.items.some(p=>p.name===QA)){mark("deleted");next();}} + else if(phase===7){if(age===30)args[0]=0x4000;if(age>=60&&age<70)args[0]=0x200;if([62,64,66].includes(age))args[0]|=0x40;if(age===68)args[0]|=0x2000;if(age===90){require(s.mode()==="sources","source menu");s.setSelection(s.maps().findIndex(m=>m.kind==="hyrule"));}if(age===110)args[0]=0x2000;if(age>130&&s.info()?.kind==="hyrule"&&ready()){mark("hyrule");next();}} + else if(phase===8){if(age===140){s.switchMap("osm");}if(age>160&&s.info()?.kind==="osm"&&ready()){mark("done");ended=true;}} + } + frame(...args); + }; +})(); diff --git a/scripts/psp.ts b/scripts/psp.ts new file mode 100644 index 0000000..b53001e --- /dev/null +++ b/scripts/psp.ts @@ -0,0 +1,67 @@ +import { mkdirSync, copyFileSync } from "node:fs"; +import { resolve } from "node:path"; +const root = resolve(import.meta.dir, ".."), + runtime = resolve(process.env.POCKETJS_RUNTIME ?? resolve(root, "runtime")), + out = resolve(root, "dist/psp"); +const { validateAndResolveBuildPlan } = await import( + `${runtime}/framework/src/manifest/resolve.ts` +); +const result = validateAndResolveBuildPlan( + await Bun.file(resolve(root, "pocket.psp.json")).json(), + { target: "psp" }, +); +if (!result.ok) throw Error(JSON.stringify(result.diagnostics)); +mkdirSync(out, { recursive: true }); +const plan = resolve(out, "plan.json"); +await Bun.write(plan, JSON.stringify(result.plan, null, 2)); +const smoke = process.argv.includes("--smoke"); +if (smoke) { + const build = Bun.spawn( + [ + process.execPath, + `${runtime}/tools/build.ts`, + `--plan=${plan}`, + `--project-root=${root}`, + `--outdir=${out}`, + ], + { cwd: runtime, stdout: "inherit", stderr: "inherit" }, + ); + if (await build.exited) process.exit(1); + const bundle = resolve(out, "pocketmap-psp.js"); + await Bun.write( + bundle, + (await Bun.file(bundle).text()) + + "\n" + + (await Bun.file(resolve(root, "scripts/psp-smoke.js")).text()), + ); +} +const child = Bun.spawn( + [ + process.execPath, + `${runtime}/tools/psp.ts`, + `--plan=${plan}`, + `--project-root=${root}`, + `--outdir=${out}`, + "--release", + ...(smoke ? ["--skip-build", "--capture"] : []), + ...process.argv.slice(2).filter((a) => a !== "--smoke"), + ], + { + env: { + ...process.env, + ...(smoke ? { POCKETJS_CAPTURE_INPUT: "0:0", POCKETJS_CAP_N: "0" } : {}), + }, + cwd: runtime, + stdin: "inherit", + stdout: "inherit", + stderr: "inherit", + }, +); +if (await child.exited) process.exit(1); +const target = resolve(runtime, "hosts/psp/target/mipsel-sony-psp/release"); +mkdirSync(resolve(root, "dist/psplink"), { recursive: true }); +copyFileSync( + resolve(target, "pocketjs-psp.prx"), + resolve(root, "dist/psplink/pocket-map.prx"), +); +copyFileSync(resolve(target, "EBOOT.PBP"), resolve(out, "EBOOT.PBP")); diff --git a/scripts/watch-psp-smoke.ts b/scripts/watch-psp-smoke.ts new file mode 100644 index 0000000..e19d625 --- /dev/null +++ b/scripts/watch-psp-smoke.ts @@ -0,0 +1,79 @@ +/** Capture real GE framebuffers at smoke-driver checkpoints via PSPLINK. */ +import { readdirSync, readFileSync, mkdirSync, statSync } from "node:fs"; +import { resolve } from "node:path"; +const root = resolve(import.meta.dir, ".."), + mail = resolve(root, "dist/psplink/pocket-offload/c7771f0167312c63"), + out = resolve(root, "dist/qa/psp"); +mkdirSync(out, { recursive: true }); +const started = Date.now(); +const seen = new Set(); +let done = false; +let capturing = false; +const timer = setInterval(async () => { + if (capturing || done) return; + capturing = true; + try { + for (const name of readdirSync(mail).filter((n) => /^req[0-7]$/.test(n))) { + try { + if (statSync(resolve(mail, name)).mtimeMs < started) continue; + const b = readFileSync(resolve(mail, name)); + const q = JSON.parse(b.toString("utf8", 64)), + payload = JSON.parse(q.payload); + if (!payload.qa || seen.has(payload.qa)) continue; + seen.add(payload.qa); + console.log(payload.qa); + const stage = String(payload.qa).replace(/[^a-z0-9-]/gi, "-"); + await Bun.sleep(200); + await Bun.spawn(["pspsh", "-e", "thsusp @pocketjs_main"], { + stdout: "ignore", + }).exited; + try { + await Bun.sleep(25); + const shot = Bun.spawn( + ["pspsh", "-e", `scrshot host0:/qa-${stage}.bmp`], + { stdout: "ignore", stderr: "inherit" }, + ); + if (await shot.exited) throw Error("PSP screenshot failed"); + } finally { + await Bun.spawn(["pspsh", "-e", "thresm @pocketjs_main"], { + stdout: "ignore", + }).exited; + } + const png = Bun.spawn( + [ + "sips", + "-s", + "format", + "png", + resolve(root, `dist/psplink/qa-${stage}.bmp`), + "--out", + resolve(out, `${stage}.png`), + ], + { stdout: "ignore", stderr: "inherit" }, + ); + await png.exited; + await Bun.write( + resolve(out, "smoke.json"), + JSON.stringify( + { checkpoints: [...seen], time: new Date().toISOString() }, + null, + 2, + ), + ); + if (stage === "done" || stage.startsWith("FAILED")) { + done = true; + clearInterval(timer); + } + } catch {} + } + } finally { + capturing = false; + } +}, 40); +setTimeout(() => { + if (!done) { + clearInterval(timer); + console.error("Smoke capture deadline"); + process.exitCode = 1; + } +}, 240000).unref(); From f4ec845c8d299101c7055834ef921d902ed7a899 Mon Sep 17 00:00:00 2001 From: "Yifeng \"Evan\" Wang" <7312949+doodlewind@users.noreply.github.com> Date: Mon, 7 Sep 2026 00:12:08 -0700 Subject: [PATCH 12/13] chore(runtime): pin PSP offload contract regression tests --- runtime | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime b/runtime index 23aaff1..d09e5ff 160000 --- a/runtime +++ b/runtime @@ -1 +1 @@ -Subproject commit 23aaff18ac20da4111a01645ef82616fdfe1411d +Subproject commit d09e5ff18af8ad79f6a8cbad6b08a70293b0d1a3 From 701d34a71490a67d70edff4f103ed0679afef1f6 Mon Sep 17 00:00:00 2001 From: "Yifeng \"Evan\" Wang" <7312949+doodlewind@users.noreply.github.com> Date: Mon, 7 Sep 2026 00:17:04 -0700 Subject: [PATCH 13/13] chore(runtime): pin bounded native test deadlines --- runtime | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime b/runtime index d09e5ff..d5f0458 160000 --- a/runtime +++ b/runtime @@ -1 +1 @@ -Subproject commit d09e5ff18af8ad79f6a8cbad6b08a70293b0d1a3 +Subproject commit d5f04587fadb153e7f523cf748eeea8d4431a403

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 Y|16A4Mpf8~0QmPnUKN=mYvA+$0DoF>B>(^b literal 0 HcmV?d00001 diff --git a/host/atlas-format.ts b/host/atlas-format.ts new file mode 100644 index 0000000..d29c34b --- /dev/null +++ b/host/atlas-format.ts @@ -0,0 +1,2 @@ +export const HYRULE_REVISION = "d32a85656031d861cef38e32eb927a7d08a983a9"; +export const ATLAS_FORMAT = "pocket-map-atlas-rgb565-v1"; diff --git a/host/atlas.ts b/host/atlas.ts index c52b9e4..52738c4 100644 --- a/host/atlas.ts +++ b/host/atlas.ts @@ -1,13 +1,15 @@ import { Database } from "bun:sqlite"; import { inflateRawSync } from "node:zlib"; +import { existsSync } from "node:fs"; +import { MarkerIndex } from "./markers.ts"; import { join } from "node:path"; import type { OffloadImage } from "@pocketjs/framework/offload/provider"; import { Bookmarks } from "./bookmarks.ts"; import { renderLabel } from "./provider.ts"; -import { validPosition, type MapInfo, type Place, type SearchInput, type TileInput } from "../shared/types.ts"; +import { validPosition, type MapInfo, type Place, type SearchInput, type TileInput, type MarkerInput } from "../shared/types.ts"; -export const HYRULE_REVISION = "d32a85656031d861cef38e32eb927a7d08a983a9"; -export const ATLAS_FORMAT = "pocket-map-atlas-rgb565-v1"; +import { ATLAS_FORMAT } from "./atlas-format.ts"; +export { HYRULE_REVISION, ATLAS_FORMAT } from "./atlas-format.ts"; export interface AtlasManifest { format: string; revision: string; tiles: number; places: number; info: MapInfo } /** The installed atlas is complete and immutable. Reads never fall through to @@ -16,6 +18,7 @@ export class AtlasProvider { readonly info: MapInfo; readonly bookmarks: Bookmarks; private db: Database; + private markers?: MarkerIndex; private images = new Map(); private reads = 0; private hits = 0; @@ -26,11 +29,13 @@ export class AtlasProvider { if (!manifest || manifest.format !== ATLAS_FORMAT || manifest.tiles !== 21845 || manifest.info.space !== "planar") { this.db.close(); throw new Error("Incomplete Hyrule atlas; run bun run prepare:hyrule"); } - this.info = manifest.info; + if (existsSync(join(directory, "markers.sqlite"))) this.markers = new MarkerIndex(join(directory, "markers.sqlite")); + this.info = { ...manifest.info, markers: !!this.markers }; this.bookmarks = new Bookmarks(join(directory, "places.sqlite")); } methods() { return { "map.info": () => JSON.stringify(this.info), + "map.markers": (raw: string) => JSON.stringify(this.markerRows(JSON.parse(raw))), "map.tile": (raw: string) => this.tile(JSON.parse(raw)), "map.search": (raw: string) => JSON.stringify(this.search(JSON.parse(raw))), "map.label": (raw: string) => renderLabel(JSON.parse(raw)), @@ -60,6 +65,7 @@ export class AtlasProvider { ORDER BY rank, ((x-?)*(x-?)+(y-?)*(y-?)) LIMIT 5`).all(match, input.x, input.x, input.y, input.y) as Omit, "space">[]; return rows.map(row => ({ ...row, space: "planar" })); } + markerRows(input: MarkerInput) { if (input.source !== this.info.source) throw new Error("Unknown marker source"); return this.markers?.query(input) ?? []; } diagnostics() { return { atlasReads: this.reads, memoryHits: this.hits, downloads: 0 }; } - close() { this.db.close(); this.bookmarks.close(); } + close() { this.markers?.close(); this.db.close(); this.bookmarks.close(); } } diff --git a/host/markers.ts b/host/markers.ts new file mode 100644 index 0000000..205ec91 --- /dev/null +++ b/host/markers.ts @@ -0,0 +1,74 @@ +import { Database } from "bun:sqlite"; +import { existsSync, renameSync, rmSync } from "node:fs"; +import { join } from "node:path"; +import { HYRULE_REVISION } from "./atlas-format.ts"; +import { MARKER_KINDS, type MarkerInput, type MapMarker, type MarkerKind } from "../shared/types.ts"; + +const VERSION = `markers-v1/${HYRULE_REVISION}`; +const classify = (file: string, group: string): MarkerKind => file === "seeds" ? "seed" : file === "treasures" ? "treasure" + : group === "Sheikah Tower" ? "tower" : group === "Shrine" ? "shrine" : group === "Stable" ? "stable" + : /Village|Settlement|Lab/.test(group) ? "village" : /Talus|Hinox|Lynel|Molduga|Guardian/.test(group) ? "enemy" + : /Memory|Fairy|Statue/.test(group) ? "special" : "landmark"; + +/** A separate small index can be refreshed without rebaking 592 MB of pixels. */ +export async function prepareMarkers(directory: string, source: string) { + const output = join(directory, "markers.sqlite"); + if (existsSync(output)) { + const old = new Database(output, { readonly: true }); + const row = old.query("SELECT version,count FROM metadata").get() as { version: string; count: number } | null; old.close(); + if (row?.version === VERSION) return row.count; + } + const pending = join(directory, "markers.build.sqlite"); if (existsSync(pending)) rmSync(pending); + const db = new Database(pending); + db.exec(`CREATE TABLE metadata(version TEXT,count INTEGER); + CREATE TABLE markers(id INTEGER PRIMARY KEY,name TEXT,kind TEXT,x REAL,y REAL,minZoom INTEGER,maxZoom INTEGER,priority INTEGER); + CREATE VIRTUAL TABLE bounds USING rtree(id,x0,x1,y0,y1);`); + const insert = db.query("INSERT INTO markers VALUES (?,?,?,?,?,?,?,?)"), bounds = db.query("INSERT INTO bounds VALUES (?,?,?,?,?)"); + let count = 0; const seen = new Set(); + try { + for (const file of ["locations", "pins", "seeds", "treasures"]) { + const groups = await Bun.file(join(source, `markers/${file}.json`)).json(); + db.transaction(() => { + for (const group of groups) for (const layer of group.layers ?? []) for (const marker of layer.markers ?? []) { + if (!Array.isArray(marker.coords) || marker.coords.length !== 2 || !marker.coords.every(Number.isFinite)) continue; + const [north, east] = marker.coords, x = (east + 12000) / 24000 * 256, y = (12000 - north) / 24000 * 256; + if (x < 0 || x >= 256 || y < 0 || y >= 256) continue; + const kind = classify(file, group.name), label = marker.name ?? `${kind === "seed" ? "Korok" : group.name} ${marker.id ?? ""}`; + const name = String(label).replace(/<[^>]+>/g, "").replace(/[^\x20-\x7e]/g, "'").slice(0, 24); + const key = `${kind}/${x}/${y}/${name}`; if (seen.has(key)) continue; seen.add(key); + const min = group.name === "Region" ? 0 : group.name === "Subregion" ? 2 : kind === "tower" ? 2 + : kind === "seed" || kind === "treasure" ? 6 : kind === "enemy" ? 5 : kind === "landmark" ? 4 : 3; + const max = group.name === "Region" ? 2 : group.name === "Subregion" ? 4 : 7; + const priority = kind === "tower" ? 0 : kind === "village" ? 1 : kind === "shrine" ? 2 : kind === "stable" ? 3 : kind === "landmark" ? 4 : 5; + insert.run(++count, name, kind, x, y, min, max, priority); bounds.run(count, x, x, y, y); + } + })(); + } + db.query("INSERT INTO metadata VALUES (?,?)").run(VERSION, count); db.close(); renameSync(pending, output); return count; + } catch (error) { db.close(); throw error; } +} +export class MarkerIndex { + private db: Database; + constructor(path: string) { this.db = new Database(path, { readonly: true }); } + query(input: MarkerInput): MapMarker[] { + const { z, x, y, layer } = input, cells = Math.max(1, 2 ** (z - 1)); + if (![z, x, y].every(Number.isInteger) || z < 0 || z > 7 || x < 0 || y < 0 || x >= cells || y >= cells || !["all", "travel", "collectibles", "enemies", "off"].includes(layer)) throw new Error("Invalid marker window"); + if (layer === "off") return []; + const kinds = layer === "travel" ? ["tower", "shrine", "stable", "village", "landmark", "special"] : layer === "collectibles" ? ["seed", "treasure", "special"] : layer === "enemies" ? ["enemy"] : MARKER_KINDS; + const size = 512 / 2 ** z, x0 = x * size, y0 = y * size; + const rows = this.db.query(`SELECT m.id,m.name,m.kind,m.x,m.y FROM bounds b JOIN markers m ON m.id=b.id + WHERE b.x1>=? AND b.x0=? AND b.y0=? AND m.x=? AND m.y=? + AND kind IN (${kinds.map(() => "?").join(",")}) ORDER BY m.priority,m.id LIMIT 256`).all(x0, x0 + size, y0, y0 + size, x0, x0 + size, y0, y0 + size, z, z, ...kinds) as { id: number; name: string; kind: MarkerKind; x: number; y: number }[]; + // Labels occupy stable global grid slots; adjacent windows use the same grid. + // This bounds density without relaying a viewport-sized layout every frame. + const occupied = new Set(), result: MapMarker[] = []; + for (const r of rows) { + const cell = `${Math.floor(r.x * 2 ** z / 128)}/${Math.floor(r.y * 2 ** z / 32)}`; + if (occupied.has(cell)) continue; occupied.add(cell); + result.push([r.id, r.name, r.kind, +r.x.toFixed(5), +r.y.toFixed(5)]); + if (result.length === 12) break; + } + return result; + } + close() { this.db.close(); } +} diff --git a/host/service.ts b/host/service.ts new file mode 100644 index 0000000..86e5415 --- /dev/null +++ b/host/service.ts @@ -0,0 +1,40 @@ +import { existsSync } from "node:fs"; +import { join } from "node:path"; +import { MapProvider } from "./provider.ts"; +import { AtlasProvider } from "./atlas.ts"; +import type { ProviderConfig } from "./config.ts"; +import type { NetworkFetch } from "./cache.ts"; +import type { MapKind } from "../shared/types.ts"; + +/** Selection is in each request, never mutable connection-wide state. Old + * reads and lost command acknowledgements cannot cross databases on a switch. */ +export class MapService { + private providers = new Map(); + private selected: MapKind; + constructor(config: ProviderConfig, network?: NetworkFetch) { + this.providers.set("osm", new MapProvider(config, network)); + if (config.atlas && existsSync(join(config.atlas, "atlas.sqlite"))) this.providers.set("hyrule", new AtlasProvider(config.atlas)); + this.selected = config.kind ?? "osm"; + if (!this.providers.has(this.selected)) throw new Error("Prepare the Hyrule atlas first"); + } + private resolve(source?: string) { + if (source === undefined) return this.providers.get(this.selected)!; // Existing guest compatibility. + for (const p of this.providers.values()) if (p.info.source === source) return p; + throw new Error("Unknown map source"); + } + methods() { return { + "map.info": (raw: string) => { + const kind = JSON.parse(raw).kind ?? this.selected, p = this.providers.get(kind); + if (!p) throw new Error("Map is not installed on your Mac"); + return JSON.stringify({ ...p.info, kind, maps: [...this.providers].map(([kind, p]) => ({ kind, name: p.info.name })) }); + }, + "map.tile": (raw: string) => { const v = JSON.parse(raw); return this.resolve(v.source).tile(v); }, + "map.search": async (raw: string) => { const v = JSON.parse(raw); return JSON.stringify(await this.resolve(v.source).search(v)); }, + "map.label": (raw: string) => this.resolve().methods()["map.label"](raw), + "map.markers": (raw: string) => { const v = JSON.parse(raw), p = this.resolve(v.source); return JSON.stringify(p instanceof AtlasProvider ? p.markerRows(v) : []); }, + "bookmarks.list": (raw: string) => { const v = JSON.parse(raw); return JSON.stringify(this.resolve(v.source).bookmarks.list(v.offset)); }, + "bookmarks.command": (raw: string) => { const v = JSON.parse(raw); return this.resolve(v.source).bookmarks.command(v); }, + }; } + diagnostics() { return Object.fromEntries([...this.providers].map(([key, p]) => [key, p.diagnostics()])); } + close() { for (const p of this.providers.values()) p.close(); } +} diff --git a/host/worker.ts b/host/worker.ts index bbbd27c..f1ccad4 100644 --- a/host/worker.ts +++ b/host/worker.ts @@ -1,12 +1,11 @@ import { dispatchOffload } from "@pocketjs/framework/offload/provider"; -import { MapProvider } from "./provider.ts"; -import { AtlasProvider } from "./atlas.ts"; +import { MapService } from "./service.ts"; declare const self: { onmessage: (event: MessageEvent) => void; postMessage(value: unknown): void }; -let provider: MapProvider | AtlasProvider; +let provider: MapService; const trace = process.env.POCKET_MAP_TRACE === "1"; self.onmessage = async event => { if (event.data.init) { - provider = event.data.init.kind === "hyrule" ? new AtlasProvider(event.data.init.atlas) : new MapProvider(event.data.init); + provider = new MapService(event.data.init); return; } const started = Date.now(); diff --git a/package.json b/package.json index 6fef92a..f65ecbc 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "setup": "bun scripts/setup.ts", "3ds": "bun scripts/build.ts", "host": "bun host/serve.ts", "deploy": "bun scripts/deploy.ts", "sim": "bun scripts/sim.ts", "prepare:hyrule": "bun scripts/prepare-hyrule.ts", - "test": "bun test --conditions=browser test/geo.test.ts test/provider.test.ts test/model.test.ts test/bookmarks.test.ts test/transport.test.ts test/atlas.test.ts", + "test": "bun test --conditions=browser test/geo.test.ts test/provider.test.ts test/model.test.ts test/bookmarks.test.ts test/transport.test.ts test/atlas.test.ts test/navigation.test.ts", "check": "bun run test && runtime/node_modules/.bin/tsc --noEmit" } } diff --git a/runtime b/runtime index a6c1702..9e136be 160000 --- a/runtime +++ b/runtime @@ -1 +1 @@ -Subproject commit a6c1702a67b2ff18b0a1b1aa398a75bf3ce4251e +Subproject commit 9e136be80fd7f0f718bd392258676b98458aeb0c diff --git a/scripts/prepare-hyrule.ts b/scripts/prepare-hyrule.ts index 45740b0..11dae32 100644 --- a/scripts/prepare-hyrule.ts +++ b/scripts/prepare-hyrule.ts @@ -1,3 +1,4 @@ +import { prepareMarkers } from "../host/markers.ts"; import { createHash } from "node:crypto"; import { existsSync, mkdirSync, renameSync, rmSync, readdirSync } from "node:fs"; import { resolve, join } from "node:path"; @@ -17,21 +18,24 @@ async function git(...args: string[]) { return text.trim(); } mkdirSync(directory, { recursive: true }); +if (!existsSync(join(source, ".git"))) await git("clone", "--depth", "1", "--filter=blob:none", "--sparse", "--branch", "develop", "https://github.com/zeldadungeon/maps.git", source); +if (await git("-C", source, "rev-parse", "HEAD") !== HYRULE_REVISION) { + await git("-C", source, "fetch", "--depth", "1", "origin", HYRULE_REVISION); + await git("-C", source, "checkout", "--detach", HYRULE_REVISION); +} +await git("-C", source, "sparse-checkout", "set", "public/botw"); +const assets = join(source, "public/botw"); if (existsSync(output) && !process.argv.includes("--rebuild")) { const db = new Database(output, { readonly: true }); const manifest = JSON.parse((db.query("SELECT value FROM metadata WHERE key='manifest'").get() as { value: string }).value) as AtlasManifest; db.close(); if (manifest.revision !== HYRULE_REVISION || manifest.format !== ATLAS_FORMAT) throw new Error("Atlas version differs; use --rebuild"); + const markers = await prepareMarkers(directory, join(source, "public/botw")); + console.log(`Marker index ready: ${markers} annotations`); console.log(`Hyrule ready: ${manifest.tiles} local textures, ${manifest.places} searchable places`); process.exit(0); } -if (!existsSync(join(source, ".git"))) await git("clone", "--depth", "1", "--filter=blob:none", "--sparse", "--branch", "develop", "https://github.com/zeldadungeon/maps.git", source); -if (await git("-C", source, "rev-parse", "HEAD") !== HYRULE_REVISION) { - await git("-C", source, "fetch", "--depth", "1", "origin", HYRULE_REVISION); - await git("-C", source, "checkout", "--detach", HYRULE_REVISION); -} -await git("-C", source, "sparse-checkout", "set", "public/botw"); -const assets = join(source, "public/botw"); + for (let z = 0; z <= 5; z++) { if (readdirSync(join(assets, `tiles/${z}`)).filter(file => file.endsWith(".jpg")).length !== 4 ** z) throw new Error("Incomplete source tile pyramid"); } @@ -92,5 +96,6 @@ try { db.query("INSERT INTO metadata VALUES ('manifest',?)").run(JSON.stringify(manifest)); db.close(); renameSync(pending, output); await Bun.write(join(directory, "manifest.json"), JSON.stringify(manifest, null, 2)); + console.log(`Marker index ready: ${await prepareMarkers(directory, assets)} annotations`); console.log(`Hyrule ready: ${tiles} textures and ${places} searchable places, no runtime internet access`); } catch (error) { db.close(); throw error; } diff --git a/scripts/quickjs-smoke.js b/scripts/quickjs-smoke.js index df3ae30..b4ef91c 100644 --- a/scripts/quickjs-smoke.js +++ b/scripts/quickjs-smoke.js @@ -1,9 +1,10 @@ // QuickJS execution/stack check with host stubs. Pixels are covered by sim.ts. let node = 3, texture = 1, session = -1, ticks = 0, token = 1; -const hyrule = scriptArgs[2] === "hyrule"; +let currentHyrule; const hyrule = scriptArgs[2] === "hyrule"; const replies = [], tickets = new Set(), saved = []; globalThis.ui = { __host: "3ds-dev", __hostAbi: 8, __viewport: { w: 400, h: 240 }, __auxiliarySurface: { root: 2, w: 320, h: 240 }, __textures: { "shift.svg": 0, "shift-lock.svg": 1, "map-pad.svg": 2, "map-pin.svg": 3 }, __sprites: {}, createNode: () => node++, measureText: text => text.length * 7 }; +for (const name of ["landmark", "tower", "shrine", "stable", "village", "seed", "treasure", "enemy", "special"]) ui.__textures[`marker-${name}.svg`] = 4 + Object.keys(ui.__textures).length; for (const name of ["destroyNode", "insertBefore", "removeChild", "setStyle", "setProp", "setPropBatch", "setText", "replaceText", "uploadTexture", "setImage", "setSprite", "animate", "cancelAnim", "setFocus", "setActive", "hitTest", "hitTestBounds", "hitTestAuxiliary", "hitTestBoundsAuxiliary", "setCursor", "setCursorPos", "loadStyles", "loadFontAtlas", "loadTileTexture", "freeTexture", "uploadImgEntry", "debugInspect", "debugRectXY", "debugRectWH", "debugPause", "debugStep", "debugStats", "__dbgActive", "__dbgPoll", "__dbgSend", "__dbgShot"]) ui[name] = () => 0; globalThis.offload = { session: () => session, take: () => replies.shift(), @@ -13,6 +14,7 @@ globalThis.offload = { if (r.response === "image") { const id = token++; tickets.add(id); replies.push(JSON.stringify({ id: r.id, image: { token: id, width: 256, height: r.method === "map.label" ? 32 : 256 } })); } else { let value; + if (r.method === "map.info") currentHyrule = JSON.parse(r.payload).kind ? JSON.parse(r.payload).kind === "hyrule" : hyrule; if (r.method === "bookmarks.list") value = { items: saved, offset: 0, total: saved.length }; else if (r.method === "bookmarks.command") { const c = JSON.parse(r.payload), id = "b_0123456789abcdef01234567"; @@ -20,8 +22,9 @@ globalThis.offload = { else if (c.kind === "rename") saved[0].name = c.name; else saved.length = 0; value = { id }; - } else value = r.method === "map.info" ? { source: "0123456789abcdef", name: "Smoke map", attribution: "Test", maxZoom: hyrule ? 7 : 18, - ...(hyrule ? { minZoom: 0, space: "planar", local: true, home: { id: "home", name: "Plateau", detail: "Test", space: "planar", x: 108, y: 168, zoom: 4 } } : {}) } + } else if (r.method === "map.markers") value = [[1, "Sheikah Tower", "tower", 108, 168], [2, "Shrine of Resurrection", "shrine", 108.5, 168.5]]; + else value = r.method === "map.info" ? { source: currentHyrule ? "0123456789abcdef" : "abcdef0123456789", kind: currentHyrule ? "hyrule" : "osm", markers: currentHyrule, maps: [{ kind: "hyrule", name: "Hyrule" }, { kind: "osm", name: "OSM" }], name: "Smoke map", attribution: "Test", maxZoom: currentHyrule ? 7 : 18, + ...(currentHyrule ? { minZoom: 0, space: "planar", local: true, home: { id: "home", name: "Plateau", detail: "Test", space: "planar", x: 108, y: 168, zoom: 4 } } : {}) } : [hyrule ? { id: "one", name: "Kakariko", detail: "Hyrule", space: "planar", x: 166, y: 149, zoom: 6 } : { id: "one", name: "Tokyo", detail: "Japan", lat: 35.68, lon: 139.76, zoom: 14 }]; replies.push(JSON.stringify({ id: r.id, payload: JSON.stringify(value) })); } @@ -44,6 +47,10 @@ try { check(s.saved.selected().name === "Renamed", "rename mount"); s.saved.askRemove(); frames(20); s.saved.remove(); frames(60); check(s.saved.page().total === 0, "delete sheet lifecycle"); s.dismiss(); frames(1, 0x100); frames(1); frames(1, 0x200); frames(1); + frames(1, 0x400); frames(1, 0x400 | 0x10); frames(20, 0x400); check(s.zoomHeld(), "ZL rail mount"); frames(1); + s.openSources(); frames(2); check(s.mode() === "sources", "source picker mount"); s.choose(hyrule ? 1 : 0); frames(80); + check(s.planar() !== hyrule, "hot source switch"); s.openSources(); s.choose(hyrule ? 0 : 1); frames(80); + s.setMode("layers"); frames(2); s.choose(4); frames(1); check(s.annotations.layer() === "off", "label filter mount"); session = -1; frames(30); session = 2; frames(100); check(s.diagnostics().tiles.entries <= 40 && tickets.size === 0, "resource ownership"); std.puts(JSON.stringify({ ok: true, frames: ticks, nodeIds: node, uploads: texture, pendingTickets: tickets.size }) + "\n"); diff --git a/scripts/sim.ts b/scripts/sim.ts index fb8d3d7..5db8c1b 100644 --- a/scripts/sim.ts +++ b/scripts/sim.ts @@ -5,6 +5,7 @@ import { NODE_TYPE, PROP, BTN } from "../runtime/contracts/spec/spec.ts"; import { encodePNG } from "../runtime/tests/png.ts"; import { dispatchOffload } from "../runtime/tools/offload-provider.ts"; import { MapProvider, defaultConfig } from "../host/provider.ts"; +import { MapService } from "../host/service.ts"; import { AtlasProvider } from "../host/atlas.ts"; import type { MapModel } from "../app/model.ts"; import type { OffloadImage } from "../runtime/contracts/spec/offload.ts"; @@ -22,6 +23,7 @@ const provider = hyrule ? new AtlasProvider(".local/hyrule") : new MapProvider({ ] })); return new Response(fixture.toBuffer("image/png")); }) as typeof fetch); +const service = hyrule ? new MapService({ ...defaultConfig, cache: ":memory:", atlas: ".local/hyrule", kind: "hyrule" }, async () => new Response(fixture.toBuffer("image/png"))) : undefined; const wasm = await createWasmUi(await Bun.file("runtime/hosts/web/pocketjs.wasm").arrayBuffer(), { width: 400, height: 480 }); const ops = wasm.ops; ops.hitTestBoundsAuxiliary = (x, y) => ops.hitTestBounds!(x + 40, y + 240); @@ -61,7 +63,7 @@ async function frames(n: number, buttons = 0, touch?: [number, number], analog = const d = s.diagnostics(); maxPending = Math.max(maxPending, d.pending); maxResident = Math.max(maxResident, d.tiles.entries); while (requests.length && images.size < 8) { const raw = requests.shift()!; - const request = JSON.parse(raw), result = await dispatchOffload(provider.methods(), request); + const request = JSON.parse(raw), result = await dispatchOffload(service?.methods() ?? provider.methods(), request); if (loseCommandAck && request.method === "bookmarks.command") { loseCommandAck = false; replies.push({ at: tick + 3, raw: JSON.stringify({ id: result.id, error: "Simulated lost acknowledgement" }) }); continue; } @@ -83,6 +85,7 @@ await shot("map"); await tap(30, 18); check(s.mode() === "search", "Search touch button opens local keyboard"); await shot("keyboard"); if (hyrule) { + check(s.annotations.rows().length > 0, "Real indexed game markers materialize as bounded map labels"); check(s.planar() && s.info()?.local, "Hyrule opens as a local finite atlas with its own home and zoom bounds"); s.setQuery("Kakariko"); s.search(); await frames(40); await shot("results"); check(s.places().some(p => p.name.includes("Kakariko")), "SQLite place search finds Kakariko without an HTTP request"); @@ -90,6 +93,21 @@ if (hyrule) { check(s.pin()?.space === "planar" && s.front()!.tiles.every(t => s.frontView.state(t.input).status === "ready"), "Search navigation places the pin in atlas coordinates and resolves the village tiles"); s.camera.jump(128, 128, 0); await frames(100); await shot("overview"); check(s.front()!.tiles.length === 1 && s.front()!.tiles[0].input.z === 0, "Minimum zoom covers the finite world without wrapping copies"); + s.camera.jump(128, 128, 4); await frames(100); + const zoomPosition = s.camera.view(); + await frames(1, BTN.ZL | BTN.UP); await frames(20, BTN.ZL); await shot("zoom-rail"); + check(s.zoomHeld() && s.camera.view().zoom === 5 && s.camera.view().x === zoomPosition.x && s.camera.view().y === zoomPosition.y, "ZL owns Up/Down zoom without panning the map"); + check(s.lookAhead().some(t => t.input.z === 6), "Zoom in primes the next level through the shared resource collection"); + await frames(1); check(!s.zoomHeld(), "Releasing ZL dismisses its rail"); + const resume = s.camera.view(); await tap(180, 18); + check(s.mode() === "sources", "Map header opens the live source chooser"); await shot("sources"); + await tap(130, 53 + s.maps().findIndex(m => m.kind === "osm") * 30); await frames(100); + check(!s.planar() && s.front()!.tiles.every(t => t.input.source === s.info()!.source), "Hyrule switches to synthetic OSM without restarting the guest or daemon"); + await tap(180, 18); await tap(130, 53 + s.maps().findIndex(m => m.kind === "hyrule") * 30); await frames(100); + check(s.planar() && s.camera.view().x === resume.x && s.camera.view().zoom === resume.zoom, "Switching back restores Hyrule coordinates and zoom"); + s.setMode("layers"); await frames(2); await shot("layers"); s.choose(2); await frames(100); + check(s.annotations.layer() === "collectibles" && s.annotations.rows().every(m => m[2] !== "seed" && m[2] !== "treasure"), "Koroks and treasures remain hidden below their useful zoom range"); + s.annotations.setLayer("all"); replyDelay = 30; s.camera.jump((32 * 256 - 300) / 64, (32 * 256 + 128) / 64, 6); await frames(180); const edge = { source: s.info()!.source, z: 6, x: 32, y: 32 }; @@ -99,6 +117,18 @@ if (hyrule) { await frames(180, 0, undefined, 0x80ff); await frames(220); check(s.front()!.tiles.every(t => s.frontView.state(t.input).status === "ready"), "The local atlas catches up after sustained motion with delayed replies"); check(s.lookAhead().length <= 12 && maxResident <= 40 && maxPending <= 4 && maxStaging <= 8, "Larger local prefetch stays within device request, staging and residency budgets"); + replyDelay = 30; + s.camera.jump(128, 128, 6); await frames(120); + for (let stroke = 0; stroke < 4; stroke++) { + await frames(1, 0, [185, 95]); + for (let n = 1; n <= 6; n++) await frames(1, 0, [185 - n * 10, 95 + n * 8]); + await frames(30); + } + s.camera.stop(); await frames(12); + const directionView = s.camera.view(); + check(s.lookAhead().length > 3 && s.lookAhead().every(t => t.input.z === 6 && + ((t.column + .5) * 256 / 64 - directionView.x) - ((t.row + .5) * 256 / 64 - directionView.y) > 0), + "Repeated real touch strokes retain northeast-only look-ahead after lifting the stylus"); replyDelay = 3; await frames(100); await shot("pan"); check(images.size === 0, "Atlas navigation releases every consumed or cancelled image ticket"); } else if (live) { @@ -164,6 +194,6 @@ if (hyrule) { await frames(50); } } -const receipt = { mode: hyrule ? "complete local Hyrule atlas, compiled guest + Wasm" : live ? "live OSM DE / Photon, compiled guest + Wasm" : "deterministic synthetic provider, compiled guest + Wasm", frames: tick, checks, maxPending, maxResident, maxStaging, ...provider.diagnostics(), +const receipt = { mode: hyrule ? "complete local Hyrule atlas, compiled guest + Wasm" : live ? "live OSM DE / Photon, compiled guest + Wasm" : "deterministic synthetic provider, compiled guest + Wasm", frames: tick, checks, maxPending, maxResident, maxStaging, ...(service ? service.diagnostics() : provider.diagnostics()), hardwareAcceptance: "pending", performance: "Replay validates behavior and budgets, not device frame time" }; -await Bun.write(`dist/qa/${hyrule ? "hyrule" : live ? "live" : "replay"}.json`, JSON.stringify(receipt, null, 2)); console.log(receipt); provider.close(); +await Bun.write(`dist/qa/${hyrule ? "hyrule" : live ? "live" : "replay"}.json`, JSON.stringify(receipt, null, 2)); console.log(receipt); service?.close(); provider.close(); diff --git a/shared/types.ts b/shared/types.ts index 6265bea..4be4ac5 100644 --- a/shared/types.ts +++ b/shared/types.ts @@ -1,11 +1,12 @@ +export type MapKind = "hyrule" | "osm"; export type Position = { space?: "mercator"; lat: number; lon: number } | { space: "planar"; x: number; y: number }; export type Place = Position & { id: string; name: string; detail: string; zoom: number }; export interface MapInfo { source: string; name: string; attribution: string; maxZoom: number; minZoom?: number; - space?: "mercator" | "planar"; home?: Place; local?: boolean } + space?: "mercator" | "planar"; home?: Place; local?: boolean; markers?: boolean; kind?: MapKind; maps?: { kind: MapKind; name: string }[] } export interface TileInput { source: string; z: number; x: number; y: number } -export type SearchInput = Position & { query: string }; +export type SearchInput = Position & { query: string; source?: string }; export interface BookmarkPage { items: Place[]; offset: number; total: number } -export interface BookmarkCommand { op: string; kind: "save" | "rename" | "remove"; id?: string; place?: Place; name?: string } +export interface BookmarkCommand { op: string; source?: string; kind: "save" | "rename" | "remove"; id?: string; place?: Place; name?: string } export const HOME = { lat: 37.7879, lon: -122.4075, zoom: 14 }; export function validPosition(value: unknown): value is Position { if (!value || typeof value !== "object") return false; @@ -14,3 +15,9 @@ export function validPosition(value: unknown): value is Position { ? typeof p.x === "number" && Number.isFinite(p.x) && p.x >= 0 && p.x <= 256 && typeof p.y === "number" && Number.isFinite(p.y) && p.y >= 0 && p.y <= 256 : (p.space === undefined || p.space === "mercator") && typeof p.lat === "number" && Number.isFinite(p.lat) && Math.abs(p.lat) <= 90 && typeof p.lon === "number" && Number.isFinite(p.lon) && Math.abs(p.lon) <= 180; } + +export const MARKER_KINDS = ["landmark", "tower", "shrine", "stable", "village", "seed", "treasure", "enemy", "special"] as const; +export type MarkerKind = typeof MARKER_KINDS[number]; +export type MarkerLayer = "all" | "travel" | "collectibles" | "enemies" | "off"; +export interface MarkerInput { source: string; z: number; x: number; y: number; layer: MarkerLayer } +export type MapMarker = [id: number, name: string, kind: MarkerKind, x: number, y: number]; diff --git a/test/navigation.test.ts b/test/navigation.test.ts new file mode 100644 index 0000000..0f3194f --- /dev/null +++ b/test/navigation.test.ts @@ -0,0 +1,98 @@ +import { expect, test } from "bun:test"; +import { createRoot } from "solid-js"; +import { createTileCamera } from "@pocketjs/framework/tile-viewport"; +import { createMapPrediction } from "../app/prediction.ts"; +import { createMap } from "../app/model.ts"; +import { createOffloadClient } from "@pocketjs/framework/offload"; +import { runFrameHooks, resetFrameHooks } from "../runtime/framework/src/frame.ts"; +import { BTN } from "@pocketjs/framework/input"; +import { Database } from "bun:sqlite"; +import { mkdtempSync, mkdirSync, rmSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; +import { prepareMarkers, MarkerIndex } from "../host/markers.ts"; +import { MapService } from "../host/service.ts"; +import { ATLAS_FORMAT } from "../host/atlas.ts"; +import { defaultConfig } from "../host/config.ts"; +import type { MapInfo } from "../shared/types.ts"; +const atlas: MapInfo = { source: "123456789abcdef0", name: "Hyrule", attribution: "Test", kind: "hyrule", space: "planar", local: true, minZoom: 0, maxZoom: 7, + home: { id: "home", name: "Plateau", detail: "", space: "planar", x: 128, y: 128, zoom: 4 }, maps: [{ kind: "hyrule", name: "Hyrule" }, { kind: "osm", name: "OSM" }] }; +const osm: MapInfo = { source: "abcdef0123456789", name: "OSM", attribution: "Test", kind: "osm", maxZoom: 18, maps: atlas.maps }; +test("repeated diagonal strokes keep their forward corridor across lifts; zoom predicts only one next local level", () => { + const c = createTileCamera({ width: 400, height: 240, x: 128, y: 128, zoom: 4, minZoom: 0, maxZoom: 7 }); + const p = createMapPrediction(); p.reset(c.view()); + for (let stroke = 0; stroke < 4; stroke++) { + c.beginDrag(); for (let n = 0; n < 20; n++) { c.drag(-3, 3); p.sample(c.view(), 1 / 60, false); } + c.endDrag(0, 0); for (let n = 0; n < 40; n++) p.sample(c.view(), 1 / 60, false); + } + let plan = p.plan(c.view(), 4, atlas); + expect(plan.intent.x).toBeGreaterThan(350); expect(plan.intent.y).toBeLessThan(-350); + expect(plan.extra.length).toBeGreaterThan(4); expect(plan.extra.length).toBeLessThanOrEqual(12); + expect(plan.extra.every(t => ((t.column + .5) * 256 / 16 - c.view().x) * plan.intent.x + ((t.row + .5) * 256 / 16 - c.view().y) * plan.intent.y > 0)).toBe(true); + c.zoomBy(1); p.zoom(1); for (let n = 0; n < 60; n++) { c.step(1 / 60); p.sample(c.view(), 1 / 60, false); } + plan = p.plan(c.view(), 5, atlas); expect(plan.extra.some(t => t.input.z === 6)).toBe(true); + expect(plan.extra.every(t => t.input.z === 5 || t.input.z === 6)).toBe(true); + expect(p.plan(c.view(), 5, osm).extra.every(t => t.input.z === 5)).toBe(true); + expect(p.plan(c.view(), 5, osm).extra.length).toBeLessThanOrEqual(4); + p.zoom(-1); expect(p.plan(c.view(), 5, atlas).extra.every(t => t.input.z === 5)).toBe(true); + p.zoom(1); for (let n = 0; n < 301; n++) p.sample(c.view(), 1 / 60, false); + expect(p.plan(c.view(), 5, atlas).extra.every(t => t.input.z === 5)).toBe(true); +}); +test("ZL chord owns the D-pad; source changes fence old reads and restore each camera", () => { + resetFrameHooks(); + createRoot(dispose => { + const replies: string[] = [], sent: any[] = []; let withheld = false; + const io = createOffloadClient({ session: () => 1, submit(raw) { + const r = JSON.parse(raw), payload = JSON.parse(r.payload); sent.push({ ...r, payload }); + if (r.method === "map.info") replies.push(JSON.stringify({ id: r.id, payload: JSON.stringify(payload.kind === "osm" ? osm : atlas) })); + else if (!withheld) replies.push(JSON.stringify({ id: r.id, error: "Fixture has no images" })); + return true; + }, take: () => replies.shift(), uploadImage: () => 1, releaseImage() {} }); + const s = createMap(io), frames = (n: number, buttons = 0) => { for (let i = 0; i < n; i++) { runFrameHooks(buttons); io.step(); } }; + frames(10); expect(s.planar()).toBe(true); + const at = s.camera.view(); frames(1, BTN.ZL | BTN.UP); frames(20, BTN.ZL); + expect(s.zoomHeld()).toBe(true); expect(s.camera.view().zoom).toBe(5); + expect(s.camera.view().x).toBe(at.x); expect(s.camera.view().y).toBe(at.y); + frames(1); expect(s.zoomHeld()).toBe(false); + frames(1, BTN.ZL | BTN.DOWN); frames(50, BTN.ZL | BTN.DOWN); frames(20); + expect(s.camera.view().zoom).toBeLessThan(4); + s.camera.jump(100, 130, 5); withheld = true; frames(4); + s.switchMap("osm"); frames(10); expect(s.info()?.kind).toBe("osm"); expect(s.planar()).toBe(false); + expect(s.lookAhead().every(t => t.input.source === osm.source)).toBe(true); + s.camera.jump(200, 100, 12); s.switchMap("hyrule"); frames(10); + expect(s.camera.view()).toMatchObject({ x: 100, y: 130, zoom: 5 }); + expect(s.submitted()).toBeUndefined(); expect(s.pin()).toBeUndefined(); + s.saveCurrent(); s.saved.changeName("Home"); s.saved.submit(); frames(1); + const command = sent.findLast(r => r.method === "bookmarks.command"); expect(command.payload.source).toBe(atlas.source); + s.switchMap("osm"); expect(s.info()?.kind).toBe("hyrule"); // In-flight write owns its source. + dispose(); io.dispose(); + }); resetFrameHooks(); +}); +test("marker index filters zoom/category and bounds replies; delayed bookmarks retain their original source", async () => { + const dir = mkdtempSync(join(tmpdir(), "map-navigation-")); mkdirSync(join(dir, "markers")); + try { + const group = (name: string, count: number) => [{ name, layers: [{ markers: Array.from({ length: count }, (_, n) => ({ id: n, name: name + n, coords: [-n * 35, n * 45] })) }] }]; + for (const [file, groups] of [["locations", group("Landmark", 40)], ["pins", group("Shrine", 40)], ["seeds", group("Central", 40)], ["treasures", group("Gems", 40)]] as const) await Bun.write(join(dir, `markers/${file}.json`), JSON.stringify(groups)); + expect(await prepareMarkers(dir, dir)).toBe(160); + const index = new MarkerIndex(join(dir, "markers.sqlite")); + const all = index.query({ source: atlas.source, z: 6, x: 16, y: 16, layer: "all" }); + expect(all.length).toBeGreaterThan(0); expect(all.length).toBeLessThanOrEqual(12); expect(JSON.stringify(all).length).toBeLessThan(2500); + expect(index.query({ source: atlas.source, z: 6, x: 16, y: 16, layer: "collectibles" }).every(m => m[2] === "seed" || m[2] === "treasure")).toBe(true); + expect(index.query({ source: atlas.source, z: 2, x: 1, y: 1, layer: "collectibles" })).toEqual([]); + expect(index.query({ source: atlas.source, z: 6, x: 16, y: 16, layer: "off" })).toEqual([]); + expect(() => index.query({ source: atlas.source, z: 6, x: 32, y: 0, layer: "all" })).toThrow(); index.close(); + const db = new Database(join(dir, "atlas.sqlite")); db.exec("CREATE TABLE metadata(key TEXT PRIMARY KEY,value TEXT)"); + db.query("INSERT INTO metadata VALUES ('manifest',?)").run(JSON.stringify({ format: ATLAS_FORMAT, tiles: 21845, info: atlas })); db.close(); + const service = new MapService({ ...defaultConfig, cache: ":memory:", atlas: dir, kind: "hyrule" }, () => { throw new Error("Network must not run"); }); + try { + const methods = service.methods(), before = JSON.parse(methods["map.info"]('{}')); + const command = JSON.stringify({ source: before.source, op: "source_saved_1", kind: "save", place: atlas.home }); + const receipt = methods["bookmarks.command"](command); + const other = JSON.parse(methods["map.info"]('{"kind":"osm"}')); + expect(other.kind).toBe("osm"); expect(methods["bookmarks.command"](command)).toBe(receipt); + expect(JSON.parse(methods["bookmarks.list"](JSON.stringify({ source: other.source, offset: 0 }))).total).toBe(0); + expect(JSON.parse(methods["bookmarks.list"](JSON.stringify({ source: before.source, offset: 0 }))).total).toBe(1); + expect(() => methods["bookmarks.command"](JSON.stringify({ ...JSON.parse(command), source: "wrong" }))).toThrow(); + } finally { service.close(); } + } finally { rmSync(dir, { recursive: true, force: true }); } +}); From 274e71c7013b4ca8e740ba0a656329d6cd1e9ffe Mon Sep 17 00:00:00 2001 From: "Yifeng \"Evan\" Wang" <7312949+doodlewind@users.noreply.github.com> Date: Sun, 6 Sep 2026 18:55:47 -0700 Subject: [PATCH 06/13] feat(map): render OSM vectors with retained GPU geometry --- .github/workflows/check.yml | 1 + README.md | 77 +++---- app/annotations.ts | 133 ++++++++++-- app/model.ts | 35 +++- app/prediction.ts | 2 +- app/ui.tsx | 31 ++- bun.lock | 29 +++ docs/ARCHITECTURE.md | 29 ++- docs/VALIDATION.md | 52 +++++ docs/VECTOR_MAP.md | 182 ++++++++++++++++ docs/images/vector-osm.png | Bin 0 -> 35442 bytes docs/images/vector-zoom.png | Bin 0 -> 25684 bytes host/cache.ts | 2 +- host/config.ts | 6 +- host/provider.ts | 301 +++++++++++++++++++++++---- host/serve.ts | 3 +- host/service.ts | 3 +- host/vector-geometry.ts | 405 ++++++++++++++++++++++++++++++++++++ package.json | 20 +- runtime | 2 +- scripts/quickjs-smoke.js | 12 +- scripts/sim.ts | 4 +- scripts/vector-sim.ts | 283 +++++++++++++++++++++++++ shared/types.ts | 2 +- test/navigation.test.ts | 2 +- test/provider.test.ts | 6 +- test/transport.test.ts | 2 +- test/vector-fixture.ts | 125 +++++++++++ test/vector.test.ts | 89 ++++++++ 29 files changed, 1689 insertions(+), 149 deletions(-) create mode 100644 bun.lock create mode 100644 docs/VECTOR_MAP.md create mode 100644 docs/images/vector-osm.png create mode 100644 docs/images/vector-zoom.png create mode 100644 host/vector-geometry.ts create mode 100644 scripts/vector-sim.ts create mode 100644 test/vector-fixture.ts create mode 100644 test/vector.test.ts diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index d62aef3..353edbc 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -15,5 +15,6 @@ jobs: bun-version: 1.3.14 - run: bun install --frozen-lockfile working-directory: runtime + - run: bun install --frozen-lockfile - run: bun run setup - run: bun run check diff --git a/README.md b/README.md index 317880f..a37d208 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,24 @@ # Pocket Map -A map browser for Nintendo 3DS, built with [PocketJS](https://github.com/pocket-stack/pocketjs) and SolidJS 1.9. Explore the complete Hyrule map from **The Legend of Zelda: Breath of the Wild**, search 2,576 places, pan with the resistive touchpad, zoom and save locations. The paired Mac stores the complete atlas and search index. Browsing requires the LAN connection but makes **no internet requests**. An optional OpenStreetMap / Photon provider remains available. +A map browser for Nintendo 3DS, built with [PocketJS](https://github.com/pocket-stack/pocketjs) and SolidJS 1.9. Browse **OSM vector maps** or the complete Hyrule map from **The Legend of Zelda: Breath of the Wild**. Pan with the resistive touchpad, zoom, search and save places on the paired Mac. -