Skip to content
← All articles
Project introduction

Porting sm64coopdx to Switch and New 3DS: keep the platform boundary small

Listen to the audio story

Porting Mario 64 co-op to two handhelds · 2:12 · AI-written script, synthetic voices

Transcript

Ava: A Nintendo Switch and a New 3DS walk into a codebase. One engine has to run on both, without turning into a mess.

Andrew: Those two consoles couldn't be more different.

Ava: That's the challenge in this post. The project brings the Coop Deluxe engine for Super Mario 64 to both. The multiplayer engine and Lua mods come from upstream work, so Antoine's fork focuses on the console adapters: graphics, input, audio, threading and packaging.

Andrew: So where's the hard part?

Ava: On the New 3DS, it's a graphics translation problem. The renderer goes through Citro3D and the PICA200 GPU, translating common color combinations into the chip's own stages. When the GPU can't represent an effect, the backend reports it instead of pretending.

Andrew: I like that. Compiling isn't the same as looking right.

Ava: Exactly. And there are hardware details too. The top screen is four hundred by two forty, the bottom is three twenty by two forty. The Circle Pad handles movement, the C-Stick handles the camera, and audio uses bounded buffers.

Andrew: How do they keep two toolchains from tangling?

Ava: A firm rule: the New 3DS target must add no libctru, Citro3D or devkitARM dependencies to the desktop and Switch builds. There are separate Docker compose files and build folders too. And there are two New 3DS build paths, a small platform shell first, then the full game.

Andrew: Does it actually play on a real 3DS?

Ava: Here the page is careful. There's a New 3DS release, but the port notes still say not to call it playable, and hardware gameplay is described as unverified. A release file doesn't prove stability or multiplayer compatibility.

Andrew: And the Switch side?

Ava: Documentation covers CoopNet, local wireless, an in-game keypad, crash diagnostics and packaging. Also, you need your own legally obtained North American ROM. No ROM comes with it.

Andrew: So the lesson is: keep the platform boundary small.

Ava: And be honest about what's verified. The full write-up has the architecture diagram and links to the notes.

Table of contents

The interesting part of a console port is rarely a single compiler flag. sm64coopdx-switch-N3DS brings the Coop Deluxe engine to two very different handheld targets. The work lives at the platform boundary: graphics, input, audio, threading, and packaging.

This fork builds on the Coop Deluxe Team’s sm64coopdx, which continues djoslin0’s sm64ex-coop. The multiplayer engine and Lua ecosystem are upstream work; the console adapters are the focus here.

1. One engine, different platform services

flowchart TD
  E["Shared CoopDX engine and Lua mods"] --> A["Platform APIs"]
  A --> S["Switch target"]
  A --> N["New 3DS target"]
  S --> SI["Switch controller backend"]
  S --> SN["Switch packaging and networking"]
  N --> G["Citro3D / PICA200 renderer"]
  N --> I["Circle Pad, C-Stick and touch"]
  N --> AU["NDSP audio and libctru threads"]

The repository’s New 3DS port notes[1] explicitly require that desktop and Switch builds gain no libctru, Citro3D, or devkitARM dependencies from the new target. That is the architectural constraint worth preserving.

2. New 3DS is a graphics translation problem

The New 3DS backend implements CoopDX’s rendering API through Citro3D and PICA200. It translates common color-combiner paths into TEV stages, handles texture swizzling, depth, scissor, blending, and fog, and reports degraded combiner cases.

That last point matters. A backend that compiles is not automatically a faithful renderer. Explicit diagnostics tell you where the target GPU cannot represent an effect in the initial implementation.

The hardware foundation also separates the 400×240 top screen from the 320×240 bottom screen. Native controls map Circle Pad movement and C-Stick camera input. NDSP uses bounded buffers for stereo PCM16 audio.

3. Build the shell before the game

There are two New 3DS paths: a small platform shell in Makefile.new3ds, and full-game integration in Makefile.new3ds-game.

make -f Makefile.new3ds port-smoke -j2
make -f Makefile.new3ds-game new3ds-integration-smoke -j2

These are documented compile checks, not commands I ran as part of writing this article. Separate Docker compose files and build subtrees keep the Switch and New 3DS toolchains apart.

4. Release files do not settle hardware status

The README links a New 3DS release, while the detailed port notes still say not to call the port playable and describe hardware gameplay as unverified. Those signals should be read together: an artifact exists, but that alone does not establish stability or full multiplayer compatibility.

Switch documentation covers CoopNet, local wireless, an in-game keypad, crash diagnostics, and packaging. Consult the Switch installation guide[2] for current instructions.

Builds require your own legally obtained North American SM64 ROM. This article supplies no ROM or extracted game assets.

5. Source trail

References

  1. antoinebou12. (). New 3DS port notes. [Source file or documentation] github.com.
  2. antoinebou12. (). Switch installation guide. [Source file or documentation] github.com.
  3. antoinebou12. (). sm64coopdx-switch-N3DS. [Software repository] github.com.
  4. antoinebou12. (). Switch build notes. [Source file or documentation] github.com.
  5. antoinebou12. (). Switch controller adapter. [Source file or documentation] github.com.

References use this article’s publication date.