Skip to content

feat(map): add 3DS and PSP vector maps with a local Hyrule atlas - #1

Merged
doodlewind merged 13 commits into
mainfrom
feat/pocket-map
Sep 8, 2026
Merged

feat(map): add 3DS and PSP vector maps with a local Hyrule atlas#1
doodlewind merged 13 commits into
mainfrom
feat/pocket-map

Conversation

@doodlewind

@doodlewind doodlewind commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Behavior

Pocket Map provides OSM vector maps and a complete local Hyrule raster atlas on Nintendo 3DS and PSP. Both support local pan/zoom, place search, a keyboard, labels and persistent saved places. Sources switch without restarting, with separate cameras, pins and bookmark stores.

The Mac owns HTTPS, SQLite, PBF parsing, styling, simplification, triangulation, image codecs and Unicode label baking in an isolated capability process. The Solid 1.9 guest owns camera movement, bounded resource demand, visible labels and UI. The runtime pins d5f04587 from pocketjs#377.

Shared resources and vector rendering

  • createOffloadMeshCollection / ResourceMesh use the same demand, cache, retry, invalidation, fallback and disposal contracts as images. The guest receives native handles, never PBF or vertex arrays.
  • Mac preparation emits at most 4,096 quantized vertices and 2,048 indexed colored triangles per tile. Complete polygon tessellation preserves retained holes. Dense-tile preparation filters small parcels, joins and deduplicates roads, and admits complete features by importance; it never truncates an arbitrary triangle prefix. Simplification stops at two logical pixels.
  • Materialization uploads retained vertices once. 3DS PICA and PSP GE transform and clip the resident buffers using handle/affine commands; panning does not retransmit screen pixels or expand triangles every frame.
  • Source geometry at z14 is reused through display z18. At most 12 visible labels have components, with collision checks and one new identity admitted per frame. ASCII uses the shared glyph atlas; other scripts use cached image fallbacks, including PSP search/saved-place rows.
  • VersaTiles is the default vector source, with configurable endpoints. Official OSM vector endpoints disable predictive HTTP downloads; HTTP validators and cache expiry remain respected.

Vector design and Google Maps 5.0 / Mapbox comparison documents the choices and limits. This does not implement routing, a full Mapbox style engine, 3D buildings or SDF text.

Navigation and local atlas

3DS uses the lower screen as a resistive touchpad with inertial pan, search, saved-place controls and source switching. Hold ZL for the zoom rail; D-pad up/down changes levels. Direction prediction persists across gesture lifts and biases a forward corridor. OSM permits four extra tiles; local Hyrule permits twelve, including up to six next-level tiles for five seconds after zoom-in.

Both hosts supply bounded input-sampling time to inputDeltaSeconds(). Camera travel follows elapsed input time across missed vblanks, with a 66.666 ms catch-up cap. Virtual timers and resource pumps remain fixed. Stationary view calculations and unchanged resource unions are skipped; direction confidence and zoom prediction still expire.

prepare:hyrule downloads 1,365 JPEG source tiles from a pinned Zelda Dungeon revision, bakes 21,845 RGB565 tiles, and indexes 2,576 places. Runtime Hyrule reads/searches require no HTTP. Downloaded artwork, SQLite caches, keys and raw QA captures remain ignored. Saved places support naming, paging, navigation, rename and delete confirmation; SQLite receipts make lost write acknowledgements safe to retry.

PSP entry and USB adapter

The PSP entry shares the camera, prediction, provider, annotations, collections and saved-place model with 3DS, with a 480×272 viewport and 24 terrain entries instead of 40. Analog/D-pad pan; L opens places; R opens map commands; Triangle opens the keyboard; Circle confirms and Cross cancels. Keyboard shoulders change case/symbols without opening map menus. SELECT recalibrates the analog center, addressing the untouched test PSP's biased nub.

bun run psp builds an app-specific PRX and dist/psp/EBOOT.PBP with the XMB title Pocket Map. bun run host:psp uses the public connectOffloadUsbProvider export with the existing capability worker. PSPLINK serves the app-specific host0 mailbox.

The native transport worker owns blocking file RPCs, with eight fixed buffers and at most one UI submission, completion and upload per frame. Mac epoch/device boot/sequence identities fence stale responses. Three shared reads bound app concurrency; the PSP GE pool is capped at 4 MiB including retired buffers. The Mac's local cache and bookmark store can be shared with the LAN provider. PSP setup, controls, architecture and hardware evidence.

Validation and installation

  • 25 app tests / 981 assertions and TypeScript pass with the pinned runtime. Production PSP build succeeds using the default repository command.
  • Compiled 3DS guest replay passes 1,903 frames / 17 checks for vectors and 1,713 frames / 20 checks for Hyrule, including delayed replies, reconnect, input and source switching. Maxima remain three active reads, 40 resident entries and three staging tickets, which drain.
  • Real PSP scripted checkpoints cover OSM, keyboard typing/backspace, SF search, continuous pan, zoom, bookmark create/list/delete, Hyrule and return to OSM. The temporary bookmark is removed. Raw captures stay ignored; three actual PSP framebuffers are committed below and in the documentation. These are scripted hardware receipts, not physical-button acceptance.
  • Suspending usbhostfs_pc for over five seconds leaves the PSP UI thread running and cached map intact; communication recovers after resume. Final nonsmoke build is loaded for manual use, with no reported PSP exception and centered idle input.
  • Memory Stick installation: ms0:/PSP/GAME/PocketMap/EBOOT.PBP, 2,651,772 bytes, SHA-256 d591b8145e1052db819569c995eb5b9debb00aedd5124584c5fd7f2d82ef6097. The installed file was copied back and compared byte-for-byte.

The EBOOT does not bootstrap the PSPLINK USB driver. Runtime testing uses its corresponding PRX under PSPLINK; standalone XMB USB startup has not been implemented or validated. Uncached content requires the Mac and an active host0 connection.

Measured limits

Four SF meshes total 107,464 terrain bytes, about 79.5% below the equivalent old raster records; labels and transport overhead are separate. This is a viewport sample, not a universal compression ratio or measured USB ceiling.

The settled PSP scene improved from about 33.5 → 18.1 → 14.3 ms CPU-side work after resource and stationary-map optimizations; final stable intervals advance 120 frames in about two seconds. Loading new resources and mounting UI still cause longer frames. There is no uninterrupted 60 fps claim during navigation.

The 3DS timing binary was uploaded with equal readback. Its settled samples also reach 120 frames per two seconds; physical sustained-input acceptance remains pending. Compiled old/new guest replay changes 320/160/160 pixels per second under 60/30/mixed timing to approximately 320 in all three cases. Dense-tile preparation was separately checked against 362 cached MVTs, all fitting the unchanged geometry bounds.

Real PSP captures

OSM on PSP
PSP keyboard
Hyrule on PSP

@doodlewind doodlewind changed the title feat(map): add paired 3DS maps and saved places feat(map): add paired 3DS Hyrule maps and saved places Sep 6, 2026
@doodlewind doodlewind changed the title feat(map): add paired 3DS Hyrule maps and saved places feat(map): add 3DS vector maps and a local Hyrule atlas Sep 7, 2026
@doodlewind doodlewind changed the title feat(map): add 3DS vector maps and a local Hyrule atlas feat(map): add 3DS and PSP vector maps with a local Hyrule atlas Sep 7, 2026
@doodlewind
doodlewind marked this pull request as ready for review September 8, 2026 16:48
@doodlewind
doodlewind merged commit a8719b0 into main Sep 8, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant