vn3ds

Open source · MIT

Ren'Py visual novels on the Nintendo 3DS, in stereoscopic 3D.

Paste one command, drag in a Ren'Py game, and it lands on your console, converted, over Wi-Fi. No Python on the 3DS: a native engine plays the game, with every layer at its own depth.

Snapshot, the demo game. Move your pointer: eachEach layer sits at its own depth.

Download

One command on your computer converts a visual novel and puts it on your 3DS, with vn3ds itself the first time. Over Wi-Fi it sends a compact edition; with the 3DS's SD card plugged into the computer it copies a full-quality one instead.

You need a 3DS with custom firmware (Luma3DS) and the Homebrew Launcher, on the same Wi-Fi as your computer or with its SD card at hand. For sound, sdmc:/3ds/dspfirm.cdc (most hacked consoles have it; the DSP1 app makes it).

Open this page on your computer. vn3ds converts games on a Mac or Windows PC, then sends them to the 3DS. Copy the link to open it there:

https://vn3ds.com/

Nothing to download by hand. The command fetches the converter (about 80 MB, once, with Python, ffmpeg and vn3ds inside), converts the game and sends vn3ds and the game together.

Pick your computer.

  1. Get your 3DS ready

    First time: open the Homebrew Launcher and press Y. The command sends vn3ds through it, then your game.

    Already have vn3ds? Open it and press Y.

  2. Open Terminal and paste this

    Press ⌘ Space, type Terminal and press Return.

    curl -fsSL https://arminjamak.github.io/vn3ds/install.sh | sh -s -- your game
  3. Drag the game in

    Add a space after the command, then drag the visual novel (its folder, the .zip you downloaded, an Android .apk or a Mac .app) into the window. That pastes its path. Press Return.

  4. Leave it running

    It converts the game, finds your 3DS and sends vn3ds and the game. The game appears on the vn3ds home screen straight away as a card with a progress bar and the time left, and opens once it's complete. Keep playing meanwhile; leave the window open until it says Done.

    SD card plugged into the computer instead? The same command copies the game and vn3ds onto it, in full quality.

Quick start from source

For developers, or if you'd rather build everything yourself. Everything runs from a terminal on your computer. Type your 3DS's IP address in step 3 and every command below fills it in, ready to copy.

  1. Get the code

    git clone https://github.com/arminjamak/vn3ds && cd vn3ds

    The converter needs Python 3.9 or newer, three packages and ffmpeg (for the JPEG pictures, Opus audio and H.264 movies).

    pip install pillow numpy scipy
  2. Build the engine

    Install devkitPro with the 3DS packages, then build. Opus is bundled. This produces engine/vn3ds.3dsx.

    sudo dkp-pacman -S 3ds-dev 3ds-zlib 3ds-libogg 3ds-libvorbisidec
    cd engine && make && cd ..
    or

    Skip the build and use the one-command route under Download: its standalone converter in Releases has vn3ds built in.

  3. Enter your 3DS's IP

    The commands below show 3DS_IP until you type one.

    Where to find it. Open the Homebrew Launcher and press Y (first time), or open vn3ds: the IP is shown at the bottom of its home screen, e.g. 192.168.1.42.

    Your computer and the 3DS must be on the same Wi-Fi.

  4. First install: engine and demo game

    With the Homebrew Launcher's netloader open (press Y), this converts Snapshot, sends vn3ds, which starts, saves itself to sdmc:/3ds/vn3ds.3dsx and opens its receiver, and sends Snapshot straight after.

    tools/vn3ds-port examples/demo --3ds 3DS_IP

    vn3ds-port sends the engine the way devkitPro's 3dslink does, built in, so there's nothing else to install. Leave out --3ds and it finds the console (or a plugged-in SD card) itself.

  5. Port and send any Ren'Py game

    Keep vn3ds open: it listens in the background, even while you play. Then point the tool at a game. It accepts a project folder, a PC, Linux or Mac build, an Android .apk, a .zip download or loose .rpa archives.

    tools/vn3ds-port path/to/Game --3ds 3DS_IP

    The game shows up on the home screen right away, with a progress bar and the time left, and opens once it's complete. Over Wi-Fi you get the compact wifi preset, on an SD card the sd one; --quality picks either, and both projected sizes are shown before converting. Compiled-only games are decompiled automatically, custom minigame screens it can't port show an outcome card, and port-report.txt lists anything that was skipped or approximated.

  6. Updates later

    Run the same command again. A game is stored as a few content-cut pack files, so a changed picture resends one pack, and a dropped connection reconnects and resumes on its own. An update to the game you're playing is kept aside and applied the next time you open it.

    tools/vn3ds-port path/to/Game --3ds 3DS_IP

    vn3ds itself travels with every game when the console's copy is missing or different. To send only vn3ds, use --install, then restart it.

    tools/vn3ds-port --install --3ds 3DS_IP
  7. Alternative: SD card

    Power the 3DS off, put its SD card in your computer and run this. It copies the game (only new or changed files) in the full-quality sd preset, and the engine when it's missing or different. Much faster for very large games.

    tools/vn3ds-port path/to/Game --sd /Volumes/YOUR_SD

    Using the ftpd homebrew app instead? Replace --3ds 3DS_IP with --ftp 3DS_IP:5000.

Your computer's IP

You don't need it for the commands, but it's the quickest way to check that both devices are on the same network. A browser can't read it reliably, so ask your terminal:

macOS
ipconfig getifaddr en0
Linux
hostname -I
Windows
ipconfig

On Windows, look for IPv4 Address under your Wi-Fi adapter. On a Mac, if en0 prints nothing, try en1.

Paste your computer's IP here.

What's inside

vn3ds doesn't run Ren'Py on the console. A converter compiles the game to a small bytecode and 3DS-ready textures, and a native C engine plays it. Owning the renderer is what makes the rest possible.

Stereoscopic depth per layer

Backgrounds sink into the screen, sprites sit at its surface and the textbox floats in front. Tune any tag's depth, or split a picture into several planes.

Handheld-documentary camera

Ren'Py's camera statement with true parallax: slow drift, punch-ins and tilts that slide a scene's layers past each other.

Native minigames, online leaderboard

Seven built-in minigames a story can call for a 0–100 score, with an online leaderboard. A game's own minigame screens can be ported as native games too.

Wi-Fi transfer while playing

vn3ds listens the whole time it's open. A small icon turns in the corner while a game arrives in the background, and nothing pauses. Updates resend only what changed.

Coverflow home screen

vn3ds starts on your library: games as cards, each showing a snapshot of where you left off. Autosave means you pick up exactly there.

Ports the Ren'Py you write

Labels, menus, ATL transforms, transitions, music and voice, Movie scenes and a useful subset of Python. Tested on Eternum: 431 labels, 12,000+ images.

Music that lands on the beat

Each track's tempo is measured when the game is converted, so a music change waits for the end of the phrase and the next track comes in on the downbeat.

A small Wi-Fi edition

Trellis JPEG pictures, CG variants stored as patches, mono Opus audio and 100 kbps H.264. Eternum comes to about 300 MB, against 790 MB in SD quality.

Animated scenes

Movie images are re-encoded to H.264 and played by the New 3DS's hardware decoder at the image's depth. An Old 3DS shows the first frame.

Snapshot

The bundled demo game, and the showcase for everything above: four chapters following Aron, who questions reality as a secret hobby. Its scenes are drawn as layered depth planes, its cast has a full range of expressions and speech-like voices, its original score changes on the beat, and each of the seven minigames turns up once in the story. It uses every optional engine feature, so it's also the reference for your own vn3ds.json.

It installs with the engine in step 4, or on its own once vn3ds is there:

tools/vn3ds-port examples/demo --3ds 3DS_IP
Snapshot's beach scene with Mira
The beach, composed from eight depth layers.