Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

TinyChat 3DS

Top screen: TinyChat 3DS transcript with prompt bubbles, generated story text, and a status bar showing tokens/s, context use, and tracked memory Bottom screen: text field, Send/Stop/Clear buttons, and a custom touch keyboard

A native .3dsx homebrew text-completion app for the New Nintendo 2DS XL / New 3DS family. It runs the 260K-parameter TinyStories model entirely on the console with a portable C FP32 engine adapted from llama2.c. There is no network inference, response table, or fake streaming.

This is a TinyStories completion model, not an instruction-following assistant. Start with Once upon a time. Quality is intentionally tiny.

Install on a console

  1. Download tinychat3ds-sdcard.zip from the latest release.
  2. Unzip it and copy the 3ds folder to the root of your SD card, so you end up with SD:/3ds/tinychat/ containing tinychat3ds.3dsx, tinychat3ds.smdh, stories260K.bin, and tok512.bin.
  3. Put the SD card back in the console and open the Homebrew Launcher.
  4. Pick TinyChat 3DS.

The model and tokenizer must sit next to the .3dsx in that exact folder — the app loads them from sdmc:/3ds/tinychat/. The release also ships a bare tinychat3ds.3dsx for people who already have the two data files in place.

Controls: tap the custom bottom-screen keyboard, then Send (or A). Tap Stop (or B) to cancel and Clear to reset. D-pad Up/Down scrolls the top-screen transcript; START exits.

Try it on a Mac without a console

./scripts/launch-azahar.sh

Azahar opens the packaged .3dsx from an isolated profile under tools/azahar-profile/user. If macOS blocks first launch, right-click tools/Azahar.app, choose Open once, then rerun the command.

Reproduce everything

Requirements on an Apple Silicon Mac are Docker Desktop, the Xcode command line tools, and standard curl/make. No administrator access is needed.

./scripts/setup-macos.sh   # pinned official model, devkitPro image, Azahar
make desktop              # build portable host CLI
make test                 # compare fixed greedy output with pinned upstream
make asan                 # host AddressSanitizer + UndefinedBehaviorSanitizer
make package              # build .3dsx and ready-to-copy SD folder
./scripts/benchmark.sh     # desktop-labelled timing only

Native devkitPro installations are also supported: set DEVKITARM, then ./scripts/build-3ds.sh uses it. Otherwise the script uses devkitPro's official, digest-pinned devkitarm container while Azahar remains native on the host.

Outputs:

  • 3ds/tinychat3ds.3dsx — native homebrew executable
  • dist/sd-card/3ds/tinychat/ — copy directly into an SD card root
  • build/tinychat-cli — host verifier sharing the exact inference core

Design and constraints

The checkpoint is read into one resident allocation; execution does not use POSIX mmap, OpenMP, NEON, ARM64, or GPU compute. The model uses a 128-token runtime KV cache and at most 48 new tokens per submission. State and cache are rebuilt on each Send, so each prompt is an independent completion even though the presentation is chat-like. All activation, cache, and sampler buffers are preallocated; there is no allocation per generated token.

The 3DS app calls libctru's documented osSetSpeedupEnable(true) for New-family hardware and uses one worker with the launcher's default affinity (-2). It does not request extra system-core time through APT_SetAppCpuTimeLimit, so it does not assume all New 3DS physical cores are available. The UI displays its tracked heap and libctru's live application-region free memory. libctru's OS API and thread API are the authoritative references.

Errors for missing/truncated/wrong-vocabulary files, invalid checkpoints, allocation failure, empty prompts, cancellation, EOS/BOS, and context limits are surfaced on screen. In particular, a tokenizer with entries beyond the checkpoint's exact 512 vocabulary is rejected, preventing accidental use of llama2.c's usual 32K tokenizer.

Verification status

  • Desktop (Apple M3, macOS 26.5): fixed greedy output is byte-identical to pinned upstream llama2.c; failure-path tests and sanitizers pass.
  • 3DS cross-build: verified as an ARMv6K 3DSX using devkitARM r68-1, libctru 2.7.0-1, citro2d 1.7.0-1, and citro3d 1.7.1-2.
  • Azahar: packaged into an isolated virtual SD and launched with the official Apple Silicon 2126.0 release. The screenshots above are from that run. See docs/VERIFICATION.md for observed GUI results and timings.
  • Real New 2DS XL: not tested. Emulator and desktop speed do not validate the eventual 20 token/s hardware target. Quantization and parallel kernels are intentionally deferred until this FP32 baseline is measured on hardware.

Exact revisions and SHA-256 hashes are in DEPENDENCIES.lock; third-party notices are in THIRD_PARTY.md.

License

MIT — see LICENSE. The bundled stories260K checkpoint and tok512.bin tokenizer come from karpathy/tinyllamas and are MIT-licensed; see THIRD_PARTY.md.

About

On-device 260K-parameter TinyStories completion running natively on a New Nintendo 3DS / 2DS XL

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages