Rise, Tarnished: Automating Elden Ring in Switch 2
Elden Ring's Tarnished Edition landed on the Switch 2, and my rune-farming script didn't. So I taught a $25 dev board to impersonate a Pro Controller, with AI as my embedded-dev copilot. The scaffold took minutes. Then the real work started.
Nine years ago, Bertrand Fan wrote Automating Zelda, a story about a Teensy microcontroller pretending to be a game controller so that Breath of the Wild could play itself. The article stuck with me. It stuck with me enough that I ended up contributing to his snowball-thrower project, and enough that nine years later, I built the same kind of machine for a different game and a console that didn't exist back then.
This is the story of teaching a $25 dev board to farm runes in Elden Ring on the Nintendo Switch 2, and of finding out how far modern AI tooling actually gets you when you leave your comfort zone.
Why farm at all
I love From Software's games. The Dark Souls series, Demon's Souls: the remake was a genuine reason I bought a PS5 at launch. It all culminated in Elden Ring and Shadow of the Erdtree, a world so dense that Future Press needed three massive volumes (I, II, III) to document it. The game was a hit on every platform it touched after its 2022 release, spawned the Nightreign spin-off, and now, in 2026, the complete "Tarnished Edition" is landing on the Nintendo Switch 2.
Here's the catch: From Software games notoriously lack cross-progression. Every new platform means starting over at level one. I've done the honest climb. It can be stressful. What I want on a new platform is to explore the Lands Between in a semi-god-like state, and that means one thing: level farming.
Located northeast of Greyoll’s Dragonbarrow, at a place known as Lenne’s Rise - a suitably elevated terrain - the game introduces a challenge similar to Indiana Jones and the Raiders of the Lost Ark. As players descend from this location, a huge boulder mysteriously spawns and rolls down after the hero. Defying typical physics as one might expect in a fantasy setting, the boulder specifically targets the player in a heart-pounding pursuit. If the player is able to quickly dodge this lethal trap, the boulder crashes down a cliff and shatters, rewarding the player with +1952 runes for their quick reflexes. 🪨🧺
Runes are the game's main currency and experience points that allows the protagonist to level up and become stronger! 💪If you are just starting your adventure in Elden Ring, this is one of the easiest ways to quickly acquire Runes to level up! Altough being a quick reward, doing this manually over and over again can (and will) become tedious.
In 2024 I solved this with a Cronus Zen, a man-in-the-middle adapter that sits between controller and console and runs scripted macros. It's infamous for enabling unfair advantages in multiplayer, but my use was strictly single-player: automating the rolling boulder at Lenne's Rise, a farming spot that yields around 240,000 runes per hour. Since level 100 costs roughly 2,000,000 runes total, a script left running does most of the tedious part for you. Most, not all. As with the Zelda automation, where the in-game weather could throw off the results, this farm has failure modes of its own: a pesky deer wandering onto the path to block or misguide you, or a system stutter (weather related?) causing an input to be slightly ignored or overplayed. Any of these can get the character killed, and the script keeps pressing buttons regardless. It wants an occasional check-in, not a full night unsupervised. My GPC script for it is here.
☝️~240,000 runes per hour, zero human input.
So when the Tarnished Edition was announced for Switch 2, my first thought was simple: plug in the Cronus Zen and reuse the script. The support page said no. No Switch 2 support.
Time to build something myself.
Finding a way in
The original Automating Zelda rig used a Teensy++ 2.0 emulating a HORI Pokken Tournament Pro Pad, a Wii U controller that happened to work on the Switch 1. That trick would most likely still work on the Switch 2. But nine years have passed, and I wanted to know if something better was possible now: emulating a real Switch Pro Controller.
The most promising prior art I found was esp-usb-ble-hid, a project that emulates a full Pro Controller on the console side and bridges generic HID input into it: any controller, on a Switch 1. A quick test confirmed that a real Switch Pro Controller works over USB on the Switch 2. That settled the feasibility question: full Pro Controller emulation on the new console should be possible.

I had an Adafruit ESP32-S3 TFT Feather sitting in a drawer, perfect for the job. And I had a second motive: I work with AI daily, and I wanted to see what current tooling does for embedded development, a domain I don't live in. If I express what I want, point at reference implementations and my previous work, do I get a working solution in minutes?
Spoiler: no. But the full answer is more interesting than that.
The build
My toolchain for the experiment:
- Odysseus - deep research and plan writing.
- Visual Studio Code Insiders + Copilot plugin - base implementation.
- GitHub Copilot App - feature build-out.
I started by writing a plan, with AI help, naturally, after running deep research on the existing solutions. The result lives in the repo: plan-switchProControllerEmulation.prompt.md. Then I set up PlatformIO in VS Code, bootstrapped a git repo, and handed the plan to Copilot running on Claude Opus 4.8. Off it went, full of confidence, and within minutes scaffolded a project that compiled cleanly and uploaded to the board.
Awesome! ❇️
Except it didn't work. The Switch 2 ignored it. My PC reported an unknown or damaged USB device. And I didn't even know whether a PC should recognize a Pro Controller out of the box. (It should, without any extra drivers, one of many things I learned on the way.)

This is where the experiment got real. My first rounds of feedback were as lazy as feedback gets: "It didn't work, what now?" The AI responded the way AI does: it reasoned, it reacted, it generated. My project sprouted USB protocol debug parameters. It also sprouted red herrings, at one point concluding that USB-C vendor authentication was the root cause. It wasn't.
The more rounds I did, the more I had to validate the AI's reasoning myself, which meant educating myself about what was actually happening on the wire and what was even possible. The devil was in the details, and pointing at a similar project was nowhere near enough. Afterwards I collected the full drift between plan and reality in plan-remarks.md, but the highlights:
- The Arduino framework was a dead end. It couldn't initialize the USB handshake correctly.
- ESP-IDF defaults to a 100 Hz tick rate. Even correct code fails the handshake because the board responds too slowly.
- The AI-generated HID descriptor was faulty. A custom gamepad descriptor that didn't match the component, a true definition of slop.
- Flash vs RAM descriptors. DMA needs the descriptors in RAM; putting them in flash breaks things quietly.
Each of these was a side-quest of its own, and each needed me to steer the AI firmly toward the right resolution. But once they were solved, I had an emulated Pro Controller that a PC recognized instantly: inputs easily verified in Steam's controller configuration panel.

From foundation to farm
With the foundation solid, the rest was a breeze:
- A Docker-based build system that doubles as a GitHub Action, so CI runs on every push.
- A rework of the one-off implementation into an engine plus declarative, GPC-style scripting.
- A controller overlay on the Feather's built-in display.
- Rumble read-back for experimental death detection, because deaths still happen and the script deserves to know.
- And finally, the port of the real Lenne's Rise boulder-farm routine from my earlier GPC script (v1.1.0).
The board narrates its own inputs.
The feature phase was where AI tooling genuinely shined. With the GitHub Copilot App I settled into a two-stage rhythm:
- Interactive mode to draft a plan as a GitHub Issue, something I could assess, review, and edit outside the session. This would work just as well in a team setting.
- Autopilot mode, which amounted to typing "Implement #12". Out came a PR on a branch that I could flash onto real hardware and validate before merging.

I had a working solution ready before launch day. All that was missing was a copy of the game to test it against.
Tarnished Edition Launch

The game was announced on April 2, 2025, about two months before the Nintendo Switch 2 released on June 5, 2025. Details were scarce at the time, but I knew right then that this alone justified getting the Switch 2 at launch. I'm a fan of physical media, so I was frustrated to later find out that one of the most high-profile third-party games for the system would ship as the dreaded Game-Key Card release: essentially a DRM key in the form of a game cartridge. It made little sense to me, especially after the successful Cyberpunk 2077 release on the Switch 2. Reportedly, the game is simply too big to fit. Oh well...
I'm not into buying physical Game-Key Cards, but I make exceptions: Resident Evil Requiem was one, and the Tarnished Edition had to be another. Of course I pre-ordered the physical copy! Shoutout to Gameroom.ee for the quick turnaround and having the game ready for pick-up on the launch day. 🎉🎈
Time is of the essence
Each platform behaves a bit differently, so although I had tested the setup against Elden Ring on PC, the timings needed verifying and adjusting for the Switch 2 build.
Here are the changes I had to make:
- It's evident that Elden Ring feels "heavier" on Switch 2 - Input requires more time. Map reloads more slowly;
- For some reason, I couldn't summon Torrent the same way as on PS5/PC - I needed to add an extra input to trigger it smoothly;
- Added a separate menu item to trigger "A" when changing Controller / Grip Order.
☝️Overall, all of these adjustments were minor to get the loop running.
What I actually learned
AI tools are powerful - well, I knew that already! But I couldn't express a wish and receive a working solution like magic: not in embedded development, not where the failure modes live in USB timing and descriptor bytes. The scaffold came in minutes; the working handshake took real debugging, real reading, and repeated correction of confidently wrong reasoning.
The pattern that emerged: Expressing a desire is not the same as receiving a result. AI accelerates you brilliantly on ground someone has mapped, and it will confidently walk you into a swamp on ground nobody has. The skill isn't prompting. The skill is knowing enough to tell the map from the swamp.
There's a bigger shift hiding in this story. Code is no longer the valuable asset it once was. Most of my repository was written by a machine in minutes, and anyone with the same tools could regenerate something like it tomorrow. What can't be regenerated is what it took to make it work: knowing that the handshake dies at a 100 Hz tick rate, knowing which confident claim is a red herring, knowing what a finished solution even looks like. The value has moved from the code itself to the knowledge and skills that turn it into a product, a service, or a solution. Or, in this particular case, a boulder farm.
Meanwhile, somewhere in the Lands Between, a boulder rolls down Lenne's Rise. Again. And again. My Tarnished stands at the bottom, collecting runes while I do other things. Sometimes a deer gets in the way. Sometimes the weather turns. That's fine: dying is part of the game.
Rise, Tarnished. Or at least, level up.