Skip to content

Add a Nintendo DS port (Embedded Swift, CoreModel + Wi-Fi)#6

Merged
colemancda merged 17 commits into
masterfrom
feature/nds
Jul 23, 2026
Merged

Add a Nintendo DS port (Embedded Swift, CoreModel + Wi-Fi)#6
colemancda merged 17 commits into
masterfrom
feature/nds

Conversation

@colemancda

Copy link
Copy Markdown
Member

Summary

Adds a Nintendo DS port (NDS/) built with Embedded Swift for the DS's ARM946E-S (armv5te-none-none-eabi), reusing the real model stack — CoreFueling entities and predicates on top of CoreModel's in-memory store and FetchRequest evaluation engine — with live data fetched over Wi‑Fi. No hardcoded locations, no hardcoded server.

Screen split: the top screen renders the UI through a software rasterizer; the bottom (touch) screen hosts libnds' on-screen keyboard, which types into the locations search field.

How it works

  • Model layer, for real. The Makefile compiles FoundationEmbedded → CoreModel → CoreFueling as Embedded modules and links them into the ROM. Search runs through the actual Location.Query.search predicate and CoreModel's pure-Swift FetchRequest.evaluate; detail rows read FuelProduct entities through the location's relationship. The DS uses CoreModel.InMemoryStorage (the synchronous store) because bare-metal armv5te ships no _Concurrency runtime for the actor-based InMemoryModelStorage.
  • Networking. dswifi associates via the firmware WFC settings, then plain BSD sockets issue HTTP GETs against /v1/locations and /v1/fuelprice. A small byte-scanning JSON walker parses the same {status, message, data} envelope the other front ends decode (Embedded Swift has no JSONDecoder) and maps records into CoreModel.ModelData, mirroring FuelingAPI's mapping key for key.
  • Injected server. tools/gen_server.py bakes FUELING_SERVER_URL (the same variable the playground and Android use) into a generated, gitignored ServerConfig.swift, defaulting to the local test server. Hostnames resolve on-device via DNS. https is rejected at build time — the DS has no TLS stack.
  • UI. Renderer, screen model and navigation are copied from ClassicUI's ports/NDS (branch feature/nds) and adapted: runtime byte-array titles instead of StaticString, a search bar, and right-aligned detail values.

Companion changes

  • CoreFueling: Model.fueling now builds under Embedded (entity descriptions assembled from each type's own attribute/relationship tables, since the Embedded declarations don't conform to Entity); LocationCoordinate binds sin/cos/atan2 directly on bare-metal targets, which have no importable libc module.
  • Scripts/test-server.py: new --bind option (default unchanged) so emulators reaching the host over NAT can be served.

Depends on PureSwift/CoreModel#29, which gates the async ModelStorage/actor on canImport(_Concurrency), publishes InMemoryStorage, and fixes an internal Collection.contains helper that was an every-element membership test rather than a subsequence search — invisible on platforms where Foundation's StringProtocol.contains shadows it, but under Embedded it made searching "mill" match "1150 Timber Lane".

Testing

  • Root package: swift build + full suite, 27 tests pass.
  • Verified end to end in melonDS against the local test server: Wi‑Fi associates, both endpoints fetch and parse, the list renders live data, typing "mill" on the touch keyboard filters to exactly the three correct matches, and the detail screen shows address/city/state/ZIP/phone/parking plus fuel prices.

Notes for reviewers

  • Needs a Swift toolchain whose Embedded stdlib ships an armv5te-none-none-eabi slice (release toolchains only ship armv4t); override with make SWIFTC=…. Also devkitPro (devkitARM, libnds, calico, ndstool) and python3 with Pillow.
  • melonDS's slirp does not implement the QEMU-style 10.0.2.2 host alias (connect fails with errno 113), so emulator testing points FUELING_SERVER_URL at the host's LAN IP with the test server bound to 0.0.0.0.
  • The error screen surfaces the failed step, errno and HTTP status, with a Retry row.

@colemancda
colemancda merged commit d71098a into master Jul 23, 2026
4 checks passed
@colemancda
colemancda deleted the feature/nds branch July 23, 2026 23:36
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