Press "Enter" to skip to content

Misadventures with DIY game cartridges (Part 01)

Last year a few news stories broke that foretold the end of Blu-Ray movies, except maybe not, but then again… the numbers are bleak.

Then, Nintendo announced the Switch 2, which, luckily, still supports physical game cartridges. The downside is that any game over 64GB will need to be partially downloaded, and some games won’t get physical releases at all, and instead will come in a box with an activation code.

All this sucks ass in my humble opinion. I love Nintendo; I think their products are whimsical and fun. But we’ve already seen Sony yoink games that people paid for off of their Playstations. Whether Nintendo is whimsical and fun is besides the point; this is what corporate control looks like.

Anyway, this was all pretense for why I started looking into how an open source game cartridge project might work. Here’s how far I got.

Software

Preface

I have a feeling that x86_64, particularly AMD’s APUs, will continue to be a cost-effective and widely adopted gaming platform in the future. After all, AMD APUs already power the Xbox, Playstation, Steam Deck, and the countless Rog Ally- and Legion Go-type devices hitting the market right now.

I do think that ARM-based handhelds will gain market share as well. Some of them can boot embedded Linux right out of the box, which is super helpful, but for this project I’m just going to target x86_64 as a proof of concept.

Embedded Linux

Here’s the overall goal: Create a modular Linux distribution that combines the best of both worlds; the durability and simplicity of cartridge-based games, but with some of the quality-of-life features that a persistent game OS system provides. I’m not saying this architecture is the way to do this, but it’s what I came up with:

- Minimal / embedded Linux foundation
    - ExFAT Partition where the game files are stored
        - game_config.yaml file that contains metadata and game-specific
          handling instructions.
    - Boot into XFCE4 with all desktop widgets disabled
    - Boot directly into Wine game

I originally started this project with Alpine Linux. I installed all the necessary drivers and software for the AMD GPU support, and then attempted to the launch the game without a window manager, but directly with xinit.

Window Manager

Technically this did work, but my Rog Ally’s hardware controller didn’t work within the game. This led me down a long rabbit hole, but I eventually discovered that Wine really leans on the window manager for mouse, keyboard, and random window generation, which games sadly love to do. So while I was hoping that I could boot games directly from the command line, a minimal window manager that is either suppressed or launched with no desktop widgets is at least one way forward.

Wine & WInetricks

We need a way to get the games onto the cartridge and installed inside a Wine “prefix.” I want this project to be on the legal up-and-up, so we need a way to get the game into an installed state without user interaction but also without distributing the game with the game cartridge OS (as that would be illegal).

Here’s how it will work:

- On first boot
    - Setup basic user metadata like timezone
    - Detect game files on game_files partition
        -  Read metadata and save_path from game_config.yaml
    - Create Wine prefix
        - Map files already in game_files partition rather than copying them
        - Create a symlink to the game save path (per game_config.yaml)
    - Install dependencies via Winetricks
- On subsequent boot
    - Launch XFCE suppressed
    - Boot Wine game
    - Detect game close
        - Shut down elegantly

In this paradigm a user will flash the game cartridge with the embedded Linux OS, then copy the game files onto the game_files partition. They will need to generate a game_config.yaml file, and that can be handled by a script, but there is no (real) standard for where games place their save files, so this is just something we’ll have to do by hand.

From there, a lot of the action happens on first boot. The game files are mapped, the Wine prefix is created, and the dependencies are installed via Winetricks. Since I want this system to work completely offline, the dependencies should be located in the game_files partition in a directory called dependencies. Since you can never rule out a game already having a folder named “dependencies,” the game_files partition will have to have a subdirectory called game_files.

Wrapping up

Once the Wine prefix is created and the dependencies installed, the game is in an “installed” state. As the final step, the first boot script needs to create a service that launches the game on boot.

This is all very hand-wavy because this part is still very much in development and testing. As mentioned above, I started this project on Alpine Linux, but I need more programmatic and scalable ways to support new hardware, update drivers, and modularize the game install process, so I will be investigating other embedded Linux deployment tools. I’m looking into Yocto and Buildroot, of course, but I just have to try them on real hardware to know for sure.

That’s where I’m going to leave it for today. I wouldn’t expect a GitHub repo until I figure out the deployment, but we’ll get there.

Be First to Comment

Leave a Reply

Your email address will not be published. Required fields are marked *