Skip to content

Updates the VirtuaNES Download Play entry to use new GitHub username - #642

Open
b00t3r wants to merge 4 commits into
Universal-Team:masterfrom
b00t3r:master
Open

Updates the VirtuaNES Download Play entry to use new GitHub username#642
b00t3r wants to merge 4 commits into
Universal-Team:masterfrom
b00t3r:master

Conversation

@b00t3r

@b00t3r b00t3r commented Aug 23, 2026

Copy link
Copy Markdown

With updated URL to repo and some assets.

@github-actions

Copy link
Copy Markdown
Test Results
GitHub -- b00t3r/emus3ds-download-play
{
    "github": "b00t3r/emus3ds-download-play",
    "title": "VirtuaNES Download Play",
    "systems": [
        "3DS"
    ],
    "categories": [
        "emulator"
    ],
    "llm_generation": "yes",
    "icon": "https://raw.githubusercontent.com/b00t3r/emus3ds-download-play/main/virtuanes_3ds_top.png",
    "image": "https://raw.githubusercontent.com/b00t3r/emus3ds-download-play/main/virtuanes_3ds_top.png",
    "long_description": "VirtuaNES for the whole 2DS and 3DS family with local wireless multiplayer support. System A Hosts and system B Joins, it's as easy as pie!",
    "stars": 3,
    "author": "Jonathan Lim\u00e9n",
    "description": "This fork adds native local multiplayer to the VirtuaNES core in `bubble2k16/emus3ds`. The goal is to let two 3DS/2DS systems play the same two-player NES game together over local wireless while each console runs the NES emulator locally.",
    "avatar": "https://avatars.githubusercontent.com/u/24964287?v=4",
    "source": "https://github.com/b00t3r/emus3ds-download-play",
    "created": "2026-08-18T18:46:14Z",
    "download_page": "https://github.com/b00t3r/emus3ds-download-play/releases",
    "version": "v1.02-dp2",
    "version_title": "VirtuaNES 1.02 Download Play 2",
    "update_notes_md": "What's new in v1.02-dp2\n\n- Added Local Play ROM caching for faster repeat startup\n- Added the ability to view and delete cached multiplayer games\n- Updated artwork and icons for Universal Updater\n- Updated the README to explain Local Play caching behavior\n\nNotes\n\n- Based on VirtuaNES v1.02",
    "update_notes": "<p dir=\"auto\">What's new in v1.02-dp2</p>\n<ul dir=\"auto\">\n<li>Added Local Play ROM caching for faster repeat startup</li>\n<li>Added the ability to view and delete cached multiplayer games</li>\n<li>Updated artwork and icons for Universal Updater</li>\n<li>Updated the README to explain Local Play caching behavior</li>\n</ul>\n<p dir=\"auto\">Notes</p>\n<ul dir=\"auto\">\n<li>Based on VirtuaNES v1.02</li>\n</ul>",
    "updated": "2026-08-23T07:19:28Z",
    "downloads": {
        "virtuanes_3ds.3dsx": {
            "url": "https://github.com/b00t3r/emus3ds-download-play/releases/download/v1.02-dp2/virtuanes_3ds.3dsx",
            "size": 1162260,
            "size_str": "1 MiB"
        }
    },
    "image_length": 32220,
    "icon_index": -1,
    "color": "#245fae",
    "color_bg": "#1a4680"
}

https://raw.githubusercontent.com/b00t3r/emus3ds-download-play/main/virtuanes_3ds_top.png
https://raw.githubusercontent.com/b00t3r/emus3ds-download-play/main/virtuanes_3ds_top.png

@github-actions

Copy link
Copy Markdown
Test Results
GitHub -- atticpad/atticpad
{
    "github": "atticpad/atticpad",
    "title": "AtticPad",
    "description": "Use your 3DS as a gamepad for a Windows or Linux PC over Wi-Fi.",
    "author": "ProPaint",
    "systems": [
        "3DS"
    ],
    "categories": [
        "app"
    ],
    "llm_generation": "yes",
    "icon": "https://raw.githubusercontent.com/atticpad/atticpad/main/clients/3ds/meta/icon.png",
    "image": "https://raw.githubusercontent.com/atticpad/atticpad/main/clients/3ds/meta/banner3d/preview.png",
    "unique_ids": [
        685852
    ],
    "long_description": "Use your 3DS as a gamepad for your PC, over Wi-Fi.\n\n**You need the server too.** It runs on the PC you want to play on, and it is\nwhat creates the virtual controller:\nhttps://github.com/atticpad/atticpad/releases\n\nWindows and Linux. One file, no installer.\n\n## What the 3DS sends\n\n- All buttons, Circle Pad, and C-Stick on a New 3DS\n- Gyro, for motion aiming\n- The touch screen, configurable via profiles on the server.\n- Its battery level, shown on the PC.\n\n## Setting it up\n\n1. Run the server on your PC. It shows you an address.\n2. Open AtticPad on the 3DS and scan the QR code the\n   server shows on screen. (or type the IP)\n3. Play.\n\n## Good to know\n\nEverything stays on your own network. No account, no internet, no cloud.\n\nPairing is a QR code. By default the server accepts any device\non your LAN without one, so run it on a network you trust.\n\nTested on a New 3DS. The Old 3DS should work but has never been tried.\n\nMIT licensed. Source, docs and issues:\nhttps://github.com/atticpad/atticpad",
    "download_filter": "3dsx|cia",
    "preinstall_message": "Install AtticPad server on your PC first, this app is a controller for it. github.com/atticpad/atticpad",
    "stars": 3,
    "avatar": "https://avatars.githubusercontent.com/u/316614385?v=4",
    "source": "https://github.com/atticpad/atticpad",
    "created": "2026-08-13T14:33:00Z",
    "license": "mit",
    "license_name": "MIT License",
    "download_page": "https://github.com/atticpad/atticpad/releases",
    "version": "v0.5.0",
    "version_title": "AtticPad v0.5.0",
    "update_notes_md": "\n**First public release.** AtticPad was built over several months before this\ntag; everything is listed once here rather than backdated into releases that\nwere never published. A 0.4.0 was prepared and never finalised, so its work is\npart of this release too.\n\nInstall instructions are in [`docs/INSTALL.md`](docs/INSTALL.md) \u2014 including a\nQR code you can scan straight from FBI to install on a 3DS without touching an\nSD card.\n\n### Highlights\n\n- **The server now tells the client where its touch controls are.** A new\n  message, `TOUCHMAP` (\u00a76.12), carries the active profile's touch regions \u2014\n  their rectangles and the button each one presses. The 3DS draws them on the\n  touchscreen, so the bottom screen finally shows the controls you actually\n  have instead of a fixed block of text. The server sends the layout when a\n  client connects, when the profile is edited and saved, and when a connected\n  pad is switched to a different profile.\n- **Protocol v1 is still frozen, and this did not unfreeze it.** \u00a74 requires a\n  client to silently discard message types it does not know, which is exactly\n  what a 0.4.0 client does with `TOUCHMAP`. Nothing that existed before changed\n  size, position or meaning. `docs/PROTOCOL.md` \u00a76.14 records what \"frozen\"\n  permits, so the next addition does not have to re-argue it.\n- **The web UI's test view draws a real Xbox 360 pad** instead of numbered\n  boxes: sticks, triggers, bumpers and d-pad light up in place, so it is\n  obvious at a glance which physical control a client is actually sending.\n\n### Fixed\n\n- **Analog sticks reached a diamond, not a circle.** The server shaped each\n  stick axis independently, so with the default quadratic response curve a\n  round stick became the locus `|x| + |y| = 1` \u2014 full deflection on a diagonal\n  produced only **0.66** of the magnitude a cardinal push did, so every\n  diagonal was a third slower than it should have been. Shaping is now radial:\n  the magnitude is shaped once and re-projected along the input direction, so\n  direction is preserved exactly and the reachable set is a disc. The deadzone\n  becomes a dead *disc* rather than a dead *cross*, so a nearly-horizontal push\n  no longer has its small vertical component silently zeroed. This was\n  server-side, so it affected every client at once and is fixed for all of them\n  without updating anything on the device.\n- **Bluetooth HID mode put the sticks and triggers on the wrong axes.** The\n  HID report descriptor declared the right stick on `Z`/`Rz` and the triggers\n  on `Rx`/`Ry` \u2014 the DualShock arrangement \u2014 while Windows assigns axis slots\n  by usage and games expect the Xbox one. The result was a right stick that\n  drove a trigger and a trigger that drove a stick axis. The descriptor now\n  matches what an Xbox Bluetooth controller reports: left stick `X`/`Y`, left\n  trigger `Z`, right stick `Rx`/`Ry`, right trigger `Rz`, D-pad on the hat.\n  **Re-pair the phone after updating** \u2014 a host caches the report descriptor\n  from pairing, so it will keep using the old axis map until you remove the\n  device and pair again.\n- **The web UI's pad view mis-drew controllers the browser does not remap.** It\n  assumed the Gamepad API's `standard` layout for every pad. One the browser\n  does not recognise reports no mapping and exposes its axes in the device's own\n  order, so the view drew the wrong controls and printed misleading axis\n  numbers. It now says so plainly and lists the raw axis and button values\n  instead of a picture that cannot be trusted.\n\n- **The Windows server crashed on startup** when it had no profiles directory,\n  because it freed uninitialised stack pointers on the built-in-profile\n  fallback path. Linux had the same bug and survived it by luck.\n- **Duplicating a profile failed** with \"could not write the profile file\" on a\n  machine that had never saved one. The profiles directory is now created on\n  demand.\n- **A profile saved to disk hid the built-in profiles** instead of taking\n  precedence over them, so editing one profile made the others disappear.\n  Startup and hot reload now assemble the list the same way, from one place.\n- **Reloading profiles left already-connected pads on their old profile.** A\n  live session now moves to a newly matching profile, unless it was pinned to\n  one by hand in the web UI.\n- **The Android in-session dialogs had square corners showing through.** The\n  platform draws its own opaque rectangular window behind a dialog, which showed\n  through the transparent corners of the app's rounded card as four grey\n  notches \u2014 visible against the near-black session screen.\n- **Debug and release Android builds can now coexist.** They shared an\n  application ID, so installing either over the other failed on the signature\n  mismatch and the only way through was to uninstall first, taking the app's\n  data with it. A debug build is now `net.atticpad.debug`, labelled \"AtticPad\n  debug\".\n\n### Everything else that is in this release\n\n- **Protocol v1**, frozen: a byte-exact UDP wire format with a 12-byte header,\n  capability bits, three-tier discovery, a PIN/QR pairing handshake, and\n  wrap-safe sequence and tick arithmetic. `docs/PROTOCOL.md` is normative.\n- **`libapad`** \u2014 the shared protocol core in C99: codec, session state machine,\n  HMAC-SHA256, PBKDF2, and sequence helpers. No `malloc` after init, no\n  floating point, no stdio; it runs on a 67 MHz ARM9 with 4 MB RAM.\n- **239 conformance vectors**, generated from the specification alone by an\n  author who did not read the codec, and shipped in every client as an\n  on-device self-test \u2014 on consoles, by holding **L+R+Start** at launch.\n- **Nintendo 3DS client** \u2014 `.cia` and `.3dsx`. Buttons, circle pad, C-stick,\n  gyro, touchscreen, battery reporting, on-screen IP entry, and a QR scanner\n  for pairing.\n- **Android client** \u2014 a single APK with no third-party runtime dependencies.\n  On-screen touch controls, physical gamepad passthrough, gyro and\n  accelerometer, QR scanning, and a foreground service that survives the\n  screen going off. Android 8.0+, arm64-v8a / armeabi-v7a / x86_64.\n- **Linux server** \u2014 creates virtual gamepads through `uinput`, enumerating as\n  an Xbox 360 controller so games recognise them without configuration.\n- **Windows server** \u2014 creates XInput gamepads through ViGEmBus, with a tray\n  application and driver detection.\n- **Mapping engine and profiles** \u2014 JSONC profiles owning deadzone, response\n  curve, inversion, touch regions and gyro aim, so no client ever applies a\n  deadzone of its own.\n- **Pairing** \u2014 a 6-digit PIN valid for 120 seconds, five-attempt lockout,\n  PBKDF2-HMAC-SHA256 session key derivation, and QR-code pairing that carries\n  the same secret without typing.\n- **Discovery** \u2014 mDNS where available, LAN broadcast, and manual IP entry.\n  Manual entry is a first-class path, because client-isolating access points\n  and VPNs break the other two.\n- **Local web UI** \u2014 bound to `127.0.0.1` only, for pad status, round-trip\n  latency, and a profile editor with hot reload.\n\n### Known limitations\n\n- The 3DS `.cia` is signed with the well-known test key, so it installs only on\n  a console running Luma3DS custom firmware.\n- The 3DS client has been run on a **New 3DS** only. Old 3DS is untested.\n- The Windows server requires **ViGEmBus**, whose upstream project is archived\n  and no longer updated. See `docs/INSTALL.md`.\n- **The server accepts unauthenticated clients by default.** Authentication\n  applies only while a pairing window is open, and pairing is not remembered\n  between sessions \u2014 there is no persistent trusted-device list yet. Run it\n  only on a network you trust. See `README.md`.\n- Pairing is toy-grade even when open: a 6-digit PIN cannot resist offline\n  brute-force by an attacker already on your LAN.\n- The server-sent touch layout is drawn by the **3DS client only**. Android\n  receives it through the same shared engine and ignores it; its on-screen\n  controls are still laid out by the app.\n- PS Vita, PSP, DS/DSi, Switch and desktop clients are designed but not built.\n  The Vita toolchain is additionally blocked upstream.\n\n[0.5.0]: https://github.com/atticpad/atticpad/releases/tag/v0.5.0\n\n---\n\n## Install\n\n**Server** \u2014 on the PC that needs a controller. Pick one:\n\n- **Windows:** download `atticpad-server-windows-x86_64.exe` and run it. It needs\n  the ViGEmBus driver, which is easiest to install with winget:\n\n  ```\n  winget install ViGEm.ViGEmBus\n  ```\n\n  or grab the installer from\n  [its releases page](https://github.com/nefarius/ViGEmBus/releases). SmartScreen\n  will warn about AtticPad's unsigned binary (*More info \u2192 Run anyway*).\n- **Linux:** download `atticpad-server-linux-x86_64`, `chmod +x` it, and run it.\n  It needs access to `/dev/uinput` \u2014 [INSTALL.md](https://github.com/atticpad/atticpad/blob/v0.5.0/docs/INSTALL.md) has the\n  one-line udev rule.\n\nThe server prints the address to type into a client, and serves a local page on\n<http://127.0.0.1:21150/> for pad status, round-trip latency and profile editing.\n\n**Client** \u2014 on the device you want to hold:\n\n- **Nintendo 3DS** (needs Luma3DS custom firmware) \u2014 open **FBI \u2192 Remote Install\n  \u2192 Scan QR Code** and scan this. No SD card, no cable:\n\n  <img src=\"https://raw.githubusercontent.com/atticpad/atticpad/v0.5.0/docs/img/fbi-install-qr.png\" alt=\"QR code that installs the AtticPad .cia from the latest release\" width=\"200\">\n\n  If that image does not load, the same code is attached to this release as\n  `atticpad-3ds-install-qr.png`, and FBI's *Receive URLs over the network* will\n  take the URL it encodes directly:\n  `https://github.com/atticpad/atticpad/releases/latest/download/atticpad-3ds.cia`\n\n  Or copy `atticpad-3ds.cia` to the SD card and install it with FBI from there.\n  `atticpad-3ds.3dsx` runs from the Homebrew Launcher instead, without installing.\n- **Android 8.0+** \u2014 sideload `atticpad-android.apk`. If you already have a debug\n  build installed, uninstall it first: the signatures differ.\n\nThen pair once. On the 3DS that means scanning the QR code the server shows \u2014\nthe console has no PIN keypad, so the QR is the only way in. On Android you can\nscan it or type the 6-digit PIN.\n\n**Before you use it on a network you do not control, read the security section\nof the README.** By default the server accepts any device on your LAN with no\nPIN.\n\nVerify what you downloaded:\n\n```\nsha256sum -c SHA256SUMS\n```\n",
    "update_notes": "<p dir=\"auto\"><strong>First public release.</strong> AtticPad was built over several months before this<br>\ntag; everything is listed once here rather than backdated into releases that<br>\nwere never published. A 0.4.0 was prepared and never finalised, so its work is<br>\npart of this release too.</p>\n<p dir=\"auto\">Install instructions are in <a href=\"docs/INSTALL.md\"><code class=\"notranslate\">docs/INSTALL.md</code></a> \u2014 including a<br>\nQR code you can scan straight from FBI to install on a 3DS without touching an<br>\nSD card.</p>\n<h3 dir=\"auto\">Highlights</h3>\n<ul dir=\"auto\">\n<li><strong>The server now tells the client where its touch controls are.</strong> A new<br>\nmessage, <code class=\"notranslate\">TOUCHMAP</code> (\u00a76.12), carries the active profile's touch regions \u2014<br>\ntheir rectangles and the button each one presses. The 3DS draws them on the<br>\ntouchscreen, so the bottom screen finally shows the controls you actually<br>\nhave instead of a fixed block of text. The server sends the layout when a<br>\nclient connects, when the profile is edited and saved, and when a connected<br>\npad is switched to a different profile.</li>\n<li><strong>Protocol v1 is still frozen, and this did not unfreeze it.</strong> \u00a74 requires a<br>\nclient to silently discard message types it does not know, which is exactly<br>\nwhat a 0.4.0 client does with <code class=\"notranslate\">TOUCHMAP</code>. Nothing that existed before changed<br>\nsize, position or meaning. <code class=\"notranslate\">docs/PROTOCOL.md</code> \u00a76.14 records what \"frozen\"<br>\npermits, so the next addition does not have to re-argue it.</li>\n<li><strong>The web UI's test view draws a real Xbox 360 pad</strong> instead of numbered<br>\nboxes: sticks, triggers, bumpers and d-pad light up in place, so it is<br>\nobvious at a glance which physical control a client is actually sending.</li>\n</ul>\n<h3 dir=\"auto\">Fixed</h3>\n<ul dir=\"auto\">\n<li>\n<p dir=\"auto\"><strong>Analog sticks reached a diamond, not a circle.</strong> The server shaped each<br>\nstick axis independently, so with the default quadratic response curve a<br>\nround stick became the locus <code class=\"notranslate\">|x| + |y| = 1</code> \u2014 full deflection on a diagonal<br>\nproduced only <strong>0.66</strong> of the magnitude a cardinal push did, so every<br>\ndiagonal was a third slower than it should have been. Shaping is now radial:<br>\nthe magnitude is shaped once and re-projected along the input direction, so<br>\ndirection is preserved exactly and the reachable set is a disc. The deadzone<br>\nbecomes a dead <em>disc</em> rather than a dead <em>cross</em>, so a nearly-horizontal push<br>\nno longer has its small vertical component silently zeroed. This was<br>\nserver-side, so it affected every client at once and is fixed for all of them<br>\nwithout updating anything on the device.</p>\n</li>\n<li>\n<p dir=\"auto\"><strong>Bluetooth HID mode put the sticks and triggers on the wrong axes.</strong> The<br>\nHID report descriptor declared the right stick on <code class=\"notranslate\">Z</code>/<code class=\"notranslate\">Rz</code> and the triggers<br>\non <code class=\"notranslate\">Rx</code>/<code class=\"notranslate\">Ry</code> \u2014 the DualShock arrangement \u2014 while Windows assigns axis slots<br>\nby usage and games expect the Xbox one. The result was a right stick that<br>\ndrove a trigger and a trigger that drove a stick axis. The descriptor now<br>\nmatches what an Xbox Bluetooth controller reports: left stick <code class=\"notranslate\">X</code>/<code class=\"notranslate\">Y</code>, left<br>\ntrigger <code class=\"notranslate\">Z</code>, right stick <code class=\"notranslate\">Rx</code>/<code class=\"notranslate\">Ry</code>, right trigger <code class=\"notranslate\">Rz</code>, D-pad on the hat.<br>\n<strong>Re-pair the phone after updating</strong> \u2014 a host caches the report descriptor<br>\nfrom pairing, so it will keep using the old axis map until you remove the<br>\ndevice and pair again.</p>\n</li>\n<li>\n<p dir=\"auto\"><strong>The web UI's pad view mis-drew controllers the browser does not remap.</strong> It<br>\nassumed the Gamepad API's <code class=\"notranslate\">standard</code> layout for every pad. One the browser<br>\ndoes not recognise reports no mapping and exposes its axes in the device's own<br>\norder, so the view drew the wrong controls and printed misleading axis<br>\nnumbers. It now says so plainly and lists the raw axis and button values<br>\ninstead of a picture that cannot be trusted.</p>\n</li>\n<li>\n<p dir=\"auto\"><strong>The Windows server crashed on startup</strong> when it had no profiles directory,<br>\nbecause it freed uninitialised stack pointers on the built-in-profile<br>\nfallback path. Linux had the same bug and survived it by luck.</p>\n</li>\n<li>\n<p dir=\"auto\"><strong>Duplicating a profile failed</strong> with \"could not write the profile file\" on a<br>\nmachine that had never saved one. The profiles directory is now created on<br>\ndemand.</p>\n</li>\n<li>\n<p dir=\"auto\"><strong>A profile saved to disk hid the built-in profiles</strong> instead of taking<br>\nprecedence over them, so editing one profile made the others disappear.<br>\nStartup and hot reload now assemble the list the same way, from one place.</p>\n</li>\n<li>\n<p dir=\"auto\"><strong>Reloading profiles left already-connected pads on their old profile.</strong> A<br>\nlive session now moves to a newly matching profile, unless it was pinned to<br>\none by hand in the web UI.</p>\n</li>\n<li>\n<p dir=\"auto\"><strong>The Android in-session dialogs had square corners showing through.</strong> The<br>\nplatform draws its own opaque rectangular window behind a dialog, which showed<br>\nthrough the transparent corners of the app's rounded card as four grey<br>\nnotches \u2014 visible against the near-black session screen.</p>\n</li>\n<li>\n<p dir=\"auto\"><strong>Debug and release Android builds can now coexist.</strong> They shared an<br>\napplication ID, so installing either over the other failed on the signature<br>\nmismatch and the only way through was to uninstall first, taking the app's<br>\ndata with it. A debug build is now <code class=\"notranslate\">net.atticpad.debug</code>, labelled \"AtticPad<br>\ndebug\".</p>\n</li>\n</ul>\n<h3 dir=\"auto\">Everything else that is in this release</h3>\n<ul dir=\"auto\">\n<li><strong>Protocol v1</strong>, frozen: a byte-exact UDP wire format with a 12-byte header,<br>\ncapability bits, three-tier discovery, a PIN/QR pairing handshake, and<br>\nwrap-safe sequence and tick arithmetic. <code class=\"notranslate\">docs/PROTOCOL.md</code> is normative.</li>\n<li><strong><code class=\"notranslate\">libapad</code></strong> \u2014 the shared protocol core in C99: codec, session state machine,<br>\nHMAC-SHA256, PBKDF2, and sequence helpers. No <code class=\"notranslate\">malloc</code> after init, no<br>\nfloating point, no stdio; it runs on a 67 MHz ARM9 with 4 MB RAM.</li>\n<li><strong>239 conformance vectors</strong>, generated from the specification alone by an<br>\nauthor who did not read the codec, and shipped in every client as an<br>\non-device self-test \u2014 on consoles, by holding <strong>L+R+Start</strong> at launch.</li>\n<li><strong>Nintendo 3DS client</strong> \u2014 <code class=\"notranslate\">.cia</code> and <code class=\"notranslate\">.3dsx</code>. Buttons, circle pad, C-stick,<br>\ngyro, touchscreen, battery reporting, on-screen IP entry, and a QR scanner<br>\nfor pairing.</li>\n<li><strong>Android client</strong> \u2014 a single APK with no third-party runtime dependencies.<br>\nOn-screen touch controls, physical gamepad passthrough, gyro and<br>\naccelerometer, QR scanning, and a foreground service that survives the<br>\nscreen going off. Android 8.0+, arm64-v8a / armeabi-v7a / x86_64.</li>\n<li><strong>Linux server</strong> \u2014 creates virtual gamepads through <code class=\"notranslate\">uinput</code>, enumerating as<br>\nan Xbox 360 controller so games recognise them without configuration.</li>\n<li><strong>Windows server</strong> \u2014 creates XInput gamepads through ViGEmBus, with a tray<br>\napplication and driver detection.</li>\n<li><strong>Mapping engine and profiles</strong> \u2014 JSONC profiles owning deadzone, response<br>\ncurve, inversion, touch regions and gyro aim, so no client ever applies a<br>\ndeadzone of its own.</li>\n<li><strong>Pairing</strong> \u2014 a 6-digit PIN valid for 120 seconds, five-attempt lockout,<br>\nPBKDF2-HMAC-SHA256 session key derivation, and QR-code pairing that carries<br>\nthe same secret without typing.</li>\n<li><strong>Discovery</strong> \u2014 mDNS where available, LAN broadcast, and manual IP entry.<br>\nManual entry is a first-class path, because client-isolating access points<br>\nand VPNs break the other two.</li>\n<li><strong>Local web UI</strong> \u2014 bound to <code class=\"notranslate\">127.0.0.1</code> only, for pad status, round-trip<br>\nlatency, and a profile editor with hot reload.</li>\n</ul>\n<h3 dir=\"auto\">Known limitations</h3>\n<ul dir=\"auto\">\n<li>The 3DS <code class=\"notranslate\">.cia</code> is signed with the well-known test key, so it installs only on<br>\na console running Luma3DS custom firmware.</li>\n<li>The 3DS client has been run on a <strong>New 3DS</strong> only. Old 3DS is untested.</li>\n<li>The Windows server requires <strong>ViGEmBus</strong>, whose upstream project is archived<br>\nand no longer updated. See <code class=\"notranslate\">docs/INSTALL.md</code>.</li>\n<li><strong>The server accepts unauthenticated clients by default.</strong> Authentication<br>\napplies only while a pairing window is open, and pairing is not remembered<br>\nbetween sessions \u2014 there is no persistent trusted-device list yet. Run it<br>\nonly on a network you trust. See <code class=\"notranslate\">README.md</code>.</li>\n<li>Pairing is toy-grade even when open: a 6-digit PIN cannot resist offline<br>\nbrute-force by an attacker already on your LAN.</li>\n<li>The server-sent touch layout is drawn by the <strong>3DS client only</strong>. Android<br>\nreceives it through the same shared engine and ignores it; its on-screen<br>\ncontrols are still laid out by the app.</li>\n<li>PS Vita, PSP, DS/DSi, Switch and desktop clients are designed but not built.<br>\nThe Vita toolchain is additionally blocked upstream.</li>\n</ul>\n<hr>\n<h2 dir=\"auto\">Install</h2>\n<p dir=\"auto\"><strong>Server</strong> \u2014 on the PC that needs a controller. Pick one:</p>\n<ul dir=\"auto\">\n<li>\n<p dir=\"auto\"><strong>Windows:</strong> download <code class=\"notranslate\">atticpad-server-windows-x86_64.exe</code> and run it. It needs<br>\nthe ViGEmBus driver, which is easiest to install with winget:</p>\n<pre class=\"notranslate\"><code class=\"notranslate\">winget install ViGEm.ViGEmBus\n</code></pre>\n<p dir=\"auto\">or grab the installer from<br>\n<a href=\"https://github.com/nefarius/ViGEmBus/releases\">its releases page</a>. SmartScreen<br>\nwill warn about AtticPad's unsigned binary (<em>More info \u2192 Run anyway</em>).</p>\n</li>\n<li>\n<p dir=\"auto\"><strong>Linux:</strong> download <code class=\"notranslate\">atticpad-server-linux-x86_64</code>, <code class=\"notranslate\">chmod +x</code> it, and run it.<br>\nIt needs access to <code class=\"notranslate\">/dev/uinput</code> \u2014 <a href=\"https://github.com/atticpad/atticpad/blob/v0.5.0/docs/INSTALL.md\">INSTALL.md</a> has the<br>\none-line udev rule.</p>\n</li>\n</ul>\n<p dir=\"auto\">The server prints the address to type into a client, and serves a local page on<br>\n<a href=\"http://127.0.0.1:21150/\" rel=\"nofollow\">http://127.0.0.1:21150/</a> for pad status, round-trip latency and profile editing.</p>\n<p dir=\"auto\"><strong>Client</strong> \u2014 on the device you want to hold:</p>\n<ul dir=\"auto\">\n<li>\n<p dir=\"auto\"><strong>Nintendo 3DS</strong> (needs Luma3DS custom firmware) \u2014 open <strong>FBI \u2192 Remote Install<br>\n\u2192 Scan QR Code</strong> and scan this. No SD card, no cable:</p>\n<a target=\"_blank\" rel=\"noopener noreferrer nofollow\" href=\"https://raw.githubusercontent.com/atticpad/atticpad/v0.5.0/docs/img/fbi-install-qr.png\"><img src=\"https://raw.githubusercontent.com/atticpad/atticpad/v0.5.0/docs/img/fbi-install-qr.png\" alt=\"QR code that installs the AtticPad .cia from the latest release\" width=\"200\" style=\"max-width: 100%;\"></a>\n<p dir=\"auto\">If that image does not load, the same code is attached to this release as<br>\n<code class=\"notranslate\">atticpad-3ds-install-qr.png</code>, and FBI's <em>Receive URLs over the network</em> will<br>\ntake the URL it encodes directly:<br>\n<code class=\"notranslate\">https://github.com/atticpad/atticpad/releases/latest/download/atticpad-3ds.cia</code></p>\n<p dir=\"auto\">Or copy <code class=\"notranslate\">atticpad-3ds.cia</code> to the SD card and install it with FBI from there.<br>\n<code class=\"notranslate\">atticpad-3ds.3dsx</code> runs from the Homebrew Launcher instead, without installing.</p>\n</li>\n<li>\n<p dir=\"auto\"><strong>Android 8.0+</strong> \u2014 sideload <code class=\"notranslate\">atticpad-android.apk</code>. If you already have a debug<br>\nbuild installed, uninstall it first: the signatures differ.</p>\n</li>\n</ul>\n<p dir=\"auto\">Then pair once. On the 3DS that means scanning the QR code the server shows \u2014<br>\nthe console has no PIN keypad, so the QR is the only way in. On Android you can<br>\nscan it or type the 6-digit PIN.</p>\n<p dir=\"auto\"><strong>Before you use it on a network you do not control, read the security section<br>\nof the README.</strong> By default the server accepts any device on your LAN with no<br>\nPIN.</p>\n<p dir=\"auto\">Verify what you downloaded:</p>\n<pre class=\"notranslate\"><code class=\"notranslate\">sha256sum -c SHA256SUMS\n</code></pre>",
    "updated": "2026-08-17T17:43:11Z",
    "downloads": {
        "atticpad-3ds.3dsx": {
            "url": "https://github.com/atticpad/atticpad/releases/download/v0.5.0/atticpad-3ds.3dsx",
            "size": 324996,
            "size_str": "317 KiB"
        },
        "atticpad-3ds.cia": {
            "url": "https://github.com/atticpad/atticpad/releases/download/v0.5.0/atticpad-3ds.cia",
            "size": 400320,
            "size_str": "390 KiB"
        }
    },
    "image_length": 62032,
    "icon_index": -1,
    "color": "#605039",
    "color_bg": "#605039",
    "qr": {
        "atticpad-3ds.cia": "https://db.universal-team.net/assets/images/qr/atticpad-3ds-cia.png"
    }
}

https://raw.githubusercontent.com/atticpad/atticpad/main/clients/3ds/meta/icon.png
https://raw.githubusercontent.com/atticpad/atticpad/main/clients/3ds/meta/banner3d/preview.png
https://github.com/atticpad/atticpad/releases/tag/v0.5.0\n\n---\n\n## Install\n\nServer \u2014 on the PC that needs a controller. Pick one:\n\n- Windows: download atticpad-server-windows-x86_64.exe and run it. It needs\n the ViGEmBus driver, which is easiest to install with winget:\n\n \n winget install ViGEm.ViGEmBus\n \n\n or grab the installer from\n its releases page. SmartScreen\n will warn about AtticPad's unsigned binary (More info \u2192 Run anyway).\n- Linux: download atticpad-server-linux-x86_64, chmod +x it, and run it.\n It needs access to /dev/uinput \u2014 INSTALL.md has the\n one-line udev rule.\n\nThe server prints the address to type into a client, and serves a local page on\nhttp://127.0.0.1:21150/ for pad status, round-trip latency and profile editing.\n\nClient \u2014 on the device you want to hold:\n\n- Nintendo 3DS (needs Luma3DS custom firmware) \u2014 open FBI \u2192 Remote Install\n \u2192 Scan QR Code and scan this. No SD card, no cable:\n\n <img src="https://raw.githubusercontent.com/atticpad/atticpad/v0.5.0/docs/img/fbi-install-qr.png\" alt="QR code that installs the AtticPad .cia from the latest release" width="200">\n\n If that image does not load, the same code is attached to this release as\n `atticpad-3ds-install-qr.png
https://github.com/nefarius/ViGEmBus/releases\">its releases page. SmartScreen
\nwill warn about AtticPad's unsigned binary (More info \u2192 Run anyway).

\n\n
  • \n<p dir="auto">Linux: download <code class="notranslate">atticpad-server-linux-x86_64, <code class="notranslate">chmod +x it, and run it.
    \nIt needs access to <code class="notranslate">/dev/uinput \u2014 <a href="https://github.com/atticpad/atticpad/blob/v0.5.0/docs/INSTALL.md\">INSTALL.md has the
    \none-line udev rule.

    \n
  • \n\n<p dir="auto">The server prints the address to type into a client, and serves a local page on
    \n<a href="http://127.0.0.1:21150/\" rel="nofollow">http://127.0.0.1:21150/ for pad status, round-trip latency and profile editing.

    \n<p dir="auto">Client \u2014 on the device you want to hold:

    \n<ul dir="auto">\n
  • \n<p dir="auto">Nintendo 3DS (needs Luma3DS custom firmware) \u2014 open FBI \u2192 Remote Install
    \n\u2192 Scan QR Code
    and scan this. No SD card, no cable:

    \n<a target="_blank" rel="noopener noreferrer nofollow" href="https://raw.githubusercontent.com/atticpad/atticpad/v0.5.0/docs/img/fbi-install-qr.png\"><img src="https://raw.githubusercontent.com/atticpad/atticpad/v0.5.0/docs/img/fbi-install-qr.png\" alt="QR code that installs the AtticPad .cia from the latest release" width="200" style="max-width: 100%;">\n<p dir="auto">If that image does not load, the same code is attached to this release as
    \n<code class="notranslate">atticpad-3ds-install-qr.png
    https://db.universal-team.net/assets/images/qr/atticpad-3ds-cia.png

  • 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