Skip to content

Nintendo Switch port - #272

Open
emartinez-dev wants to merge 13 commits into
djdiskmachine:masterfrom
emartinez-dev:master
Open

Nintendo Switch port#272
emartinez-dev wants to merge 13 commits into
djdiskmachine:masterfrom
emartinez-dev:master

Conversation

@emartinez-dev

@emartinez-dev emartinez-dev commented Aug 17, 2026

Copy link
Copy Markdown

Description

This PR adds Nintendo Switch as a build target. The build produces a devkitPro/libnx homebrew .nro file, and the homebrew menu (hbmenu) starts it. The PR also adds the release package and two CI jobs.

The port uses the existing SDL2 adapters. Most of the new code is the platform adapter in sources/Adapters/SWITCH/.

Two of the defects below affect all platforms.

  • Songs played too fast on Switch. The audio thread used a semaphore from UnixSysSemaphore. That class calls sem_open. On devkitA64, sem_open is an ENOSYS stub that returns NULL, so sem_wait returned immediately and never blocked. The audio thread then rendered without any limit. Switch now installs SDLProcessFactory, which creates its semaphore with sem_init. No target compiled SDLProcess.cpp before this PR, so it also needed two corrections: its SDL_CreateThread call used the SDL1 signature, and its destructor leaked the semaphore.
  • The application crashed when you load a project while another project plays. onEvent() held the MixerService lock during the load, and MixerService::Close() destroyed that same mutex. The application now defers the load to the next onUpdate() call, after it releases the lock.
  • (all platforms) rules_base used \+ in its sed expression. \+ is a GNU extension, and BSD sed reads it as a literal + character. The generated .d files were malformed on macOS. The expression now uses the POSIX class [[:space:]]*.
  • (all platforms) Release packages stored README, CHANGELOG and LICENSE under a literal ../../../ path, because that zip command was missing the -j option. unzip refuses to extract such paths.

SDLGUIWindowImp now scales the user interface to the full screen when the application does not run in a window. Before, it scaled only when the video driver was fbcon. The Switch runs full screen but reports framebuffer_ == false, so it drew the interface at scale 1 in the center of a 720p screen. The new condition only adds a case that other platforms do not reach.

Type of change

  • Feature

  • Bug fix (non-breaking change which fixes an issue)

  • New feature (non-breaking change which adds functionality)

How Has This Been Tested?

Test Configuration:

  • Hardware: Nintendo Switch with Atmosphere custom firmware. I started the application from hbmenu, and also with nxlink -s to read the log output. I built on macOS with devkitA64, libnx and switch-sdl2.
  • Test steps:
    1. Run make PLATFORM=SWITCH in projects/. Then run nxlink -s lgpt-switch.nro.
    2. Play a complete song. The tempo and the pitch stay correct, and the log shows no overrun messages. Before the semaphore fix, a song of 2 to 3 minutes finished in about 30 seconds.
    3. Measure the audio settings on the console. A buffer of 512 samples with prebuffer count 4 gives audible crackle. A buffer of 1024 samples with prebuffer count 4 or 2 gives clean audio. The release uses 1024 samples and prebuffer count 2.
    4. Load a project. Then load a different project in the same session. Repeat this sequence. Before this PR it stopped the application.
    5. Run lgpt_package.sh with the lgpt-resources payload. Extract the package into an empty directory. Then copy the switch folder to an SD card that has no previous LGPT installation.

Proof pic, running on a Nintendo Switch OLED

image

Checklist:

  • I have performed a self-review of my code
  • I have commented particularly in hard-to-understand areas
  • I have updated CHANGELOG
  • I have updated docs/wiki/What-is-LittlePiggyTracker.md reflecting my changes
  • I have version bumped in sources/Application/Model/Project.h
  • My changes generate no new warnings (build without your change then apply your change to check this)

@djdiskmachine

Copy link
Copy Markdown
Owner

Awesome job mate, Piggy is really perfect for the Switch =D
Also, thanks for helping out with fixing my mistakes, the deferred load was definitely something I missed 👍

The semaphore change is something I need to have a look at, it was part of the fixes for "audio randomly dying" bug that came back from the dead several times.
Let me try to run this build on Raspi3 with MIDI just to make sure we didn't bring it back again.
I hope I'll have time to check it out before end of next week but I can't promise anything.

Cheers!

@djdiskmachine djdiskmachine left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks really promising!

@emartinez-dev

Copy link
Copy Markdown
Author

My pleasure! I loved playing with LGPTracker on my RG35XXH back then, but on Nintendo Switch it's even better, the screen is a true blessing. After using it for 2 days, I can say it's not perfect, but it works!

The only problems I found were on latency and loading really long samples. I wanted to chop a 20s amen break and the UI was a bit unresponsive, and the audio renders after 0.3~0.5s but maybe I can tune the buffer settings better.

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.

2 participants