Skip to content

feat: add RK3566 / ROCKNIX port - #279

Closed
hansfbaier wants to merge 2 commits into
djdiskmachine:masterfrom
hansfbaier:rk3566-port
Closed

hansfbaier wants to merge 2 commits into
djdiskmachine:masterfrom
hansfbaier:rk3566-port

Conversation

@hansfbaier

Copy link
Copy Markdown

Adds a build target and platform resources for RK3566 handhelds running
ROCKNIX — Powkiddy RGB30, Anbernic RG-ARC and friends.

The port is cross-compiled on an x86_64 host but links against the target's own
SDL2
, so the deliverable is a single executable: no bundled libraries, fonts or
C library.

What is added

File Purpose
projects/Makefile.RK3566 Build target: toolchain, sysroot, defines
projects/Makefile Two lines registering RK3566DIRS / RK3566FILES
projects/resources/RK3566/ config.xml, mapping.xml, launch script, sysroot setup, demo-song fetcher
projects/resources/packaging/lgpt_package.sh Registers RK3566 for release packaging
README.md Platform table row
docs/RK3566_PORT.md Build, deploy, input mapping and verification notes

Shared changes

SDLGUIWindowImp — drawing and presentation are now separate. The 320x240
screen is drawn at 1:1 into a fixed surface and Flush() scales it onto the
window with SDL_BlitScaled. Previously a fullscreen window kept its app-sized
surface, and whole-number scaling capped a 720x720 panel at 2x, which left the
text unreadably small (an 8x8 glyph is about 1.6 mm on that display).

This is the one change that touches other platforms, so in detail:

  • windowed behaviour is unchanged — the window is still SCREENMULT times the
    app size and the app fills it;
  • SCREENMULT becomes a presentation scale rather than a drawing scale, so a
    platform setting it (RG35XXPLUS sets 2) gets the same picture as before;
  • a fullscreen window now fills the display with the app area scaled and
    centred, instead of drawing at whole multiples in a corner;
  • Flush() always presents the full window rather than partial update rects.

SDLEventManager — quit hotkey and an array overrun. A configurable
QUITBUTTONS value quits the tracker when those joystick buttons are held
together, because its only quit control is the project picker's Exit button,
which cannot be reached once a project is loaded. Separately, SDL2 reports a
joystick instance id in event.jbutton.which; the code indexed four-element
arrays with it directly, which overran as soon as a second controller was
hotplugged. Events are now mapped back to the index the device was opened with.

SDLAudioDriver — includes <string.h> for memcpy/memmove, which newer
libstdc++ headers no longer pull in transitively.

Verified on

Powkiddy RGB30, ROCKNIX 20240815, kernel 6.9.12, glibc 2.38, SDL2 2.30.5:

  • the binary needs GLIBC_2.38 / GLIBCXX_3.4.32; the device provides
    GLIBC_2.38 / GLIBCXX_3.4.33;
  • launches from the EmulationStation Ports menu and fills the 720x720 panel;
  • gamepad read as 4 axes / 17 buttons / 0 hats with all 13 mappings attached —
    button numbers derived from the kernel's evdev layout and cross-checked
    against EmulationStation's own controller configuration;
  • audio opens at 44100 Hz stereo through PipeWire;
  • all five bundled demo songs load; playback confirmed on Bootloop-FastJump.

Caveats for review

  • I could only test the RK3566 build. The SDLGUIWindowImp change is
    platform-neutral as far as I can tell, but X64, X86 and RG35XXPLUS were not
    run — worth a look before merging.
  • The old framebuffer_ path used to skip presenting entirely; Flush() now
    always presents. That should be an improvement for fbcon targets but is
    untested there.
  • MIDI is stubbed (DUMMYMIDI) and ffmpeg sample import is not compiled in, as
    on the other handheld ports.

docs/RK3566_PORT.md has the full build and deploy instructions.

Cross-compiles LittleGPTracker for RK3566 handhelds running ROCKNIX
(Powkiddy RGB30 and friends), linking against the target's own SDL2 so
the deliverable is a single executable. Verified on an RGB30: it
launches, fills the 720x720 panel, reads the gamepad and plays audio.

Port files:
- projects/Makefile.RK3566: build target, with RK3566DIRS/RK3566FILES
  registered in projects/Makefile and the packaging script
- projects/resources/RK3566: config.xml, mapping.xml, launch script,
  sysroot setup and a demo-song fetcher

Shared SDL2 adapter changes:
- SDLGUIWindowImp: separate drawing from presentation. The 320x240 screen
  is drawn at 1:1 into a fixed surface and Flush() scales it onto the
  window with SDL_BlitScaled, so the UI can fill a panel that is not a
  whole multiple of the app resolution. A fullscreen window used to keep
  its app-sized surface, and whole-number scaling capped a 720x720 panel
  at 2x, which left the text unreadably small. Adds an opt-in
  LGPT_SCREENSHOT diagnostic.
- SDLEventManager: configurable quit hotkey (QUITBUTTONS), because the
  tracker's only quit control is the project picker's Exit button, which
  cannot be reached once a project is loaded. Also map SDL joystick
  instance ids back to the index the device was opened with, rather than
  indexing four-element arrays with them directly - which overran as soon
  as a second controller was hotplugged.
- SDLAudioDriver: include <string.h> for memcpy/memmove, which newer
  libstdc++ headers no longer pull in transitively.
The port was built with DUMMYMIDI, so the tracker had a stub that enumerated
nothing and opened nothing. Build the bundled RtMidi with its ALSA sequencer
backend instead and link libasound: the ALSA sequencer is how the kernel
presents USB MIDI interfaces (snd-usb-audio is built into ROCKNIX), and it is
independent of the audio server, so PipeWire and aseqnet ports work through it
too.

- projects/Makefile.RK3566: RTMIDI plus __LINUX_ALSA__/__LINUX_ALSASEQ__
  instead of DUMMYMIDI, and -lasound. Both spellings are defined because
  RtMidi 1.0.8 guards its ALSA code with the ALSASEQ one, which the desktop
  makefiles only get right by accident.
- setup-sysroot.sh: fetch the alsa-lib headers matching the device's libasound
  and copy the library itself into the sysroot. A runtime image has neither.
- Application::initMidiInput: accept "*" for MIDICTRLDEVICE, meaning every
  input present. The name of an interface has to be known in advance to be
  written into a config file, and on a handheld it is not; without a match the
  tracker opens no MIDI input at all.
- RTMidiInDevice/RTMidiOutDevice: RtMidi signals failure by throwing, and the
  port index comes from a list built earlier, so an interface unplugged in
  between took the tracker down with it. Report the failure and disable that
  one device instead. This is the case USB MIDI makes ordinary.
- config.xml: MIDICTRLDEVICE='*', documented together with how MIDI events are
  mapped onto tracker controls.

Verified on the device over the kernel's Midi Through loopback, which is an
ordinary sequencer client and so exercises the same code a USB interface
would. Input: a note 60 received through the mapping moved the song grid
cursor, by the press-plus-autorepeat count a held button produces. Output:
playback opened the tracked output port and aseqdump captured the Start byte
and 238 clock messages. The desktop X64 target still builds with the shared
adapter changes.

The RGB30's USB-C port is a peripheral in the device tree and ROCKNIX binds its
MTP/CDC gadget to it, so a keyboard attached there will not enumerate. That is
a property of the port; everything above the kernel is in place.
@djdiskmachine

Copy link
Copy Markdown
Owner

Thank you for contributing to Little Piggy Tracker.

I currently have very little time for maintaining this fork, thank you for understanding.

From what I can tell, this device combination is compatible with portmaster that can install Piggy. Maintaining a device is continuous work, rarely a one-shot. What does this merge request contribute that can't be achieved using Portmaster?

@hansfbaier

Copy link
Copy Markdown
Author

Ok understood. Thanks for explaining.

@hansfbaier hansfbaier closed this Oct 3, 2026
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