OpenDingux Toolchain Documentation

Header Image

This page aims to be a step-by-step tutorial and resource about my OpenDingux Toolchain.

Features

Setup

This toolchain was developed mainly for Linux systems, however it runs completely fine on Windows under WSL too.

  1. Download the latest version of the Toolchain from here:
  2. Extract it to a common location, for example /opt/dingux_toolchain, using the unzip command. The rest of the guide will assume you installed the toolchain in this location.
    • If you're on Windows under WSL, DO NOT extract the zip file with WinRAR, 7Zip or any similar tool as it will break permissions.
    • If you're on Windows under WSL, DO NOT extract the zip file onto one of your Windows drives as it will break permissions. Instead choose one inside your WSL setup (e.g /opt/dingux_toolchain).
  3. Enter the toolchain folder and run the ./setup.sh script to setup important files in the toolchain.
  4. Either add source /opt/dingux_toolchain/envvars to your /etc/profile file if you have root access or run source /opt/dingux_toolchain/envvars manually each time you're using the toolchain.
  5. Done!

To cleanup the toolchain at a later date, run ./setup.sh clean

Building the example

The toolchain contains multiple example projects and templates for various uses. They can be found inside the templates directory.

  1. Copy the example you want to build into your development folder.
  2. Setup the build system using the meson build --cross-file=dingux command
  3. Write your code keeping C and C++ files inside the source folder and header files in the include folder.
    • When adding new .c / .cpp files, make sure to add them to the sources list inside the meson.build file.
    • Any other files that should be bundled with the OPK can be added to the resources folder. They can later on be accessed in the code using a relative path to it e.g "resources/logo.png"
  4. To compile your code, use the meson compile -C build command
    • To compile your code and immediately install the generated opk file onto your OpenDingux device run meson install -C build.
      • Make sure to plug in the device using the Device right USB port (Marked as USB/DC for example, NOT the OTG one)
      • The scripts assume that a device is available under the IP address 10.1.1.2 without any password. Confirm these settings in the settings/Network application on your device.

TLDR;

Using duxlink

Duxlink is designed after the nxlink tool using for Nintendo Switch homebrew. It's used to directly install OPK files on your OpenDingux device, run them or debug them using gbd. OPK files are installed on the internal SD card in /media/data/apps. To use the run or debug option, the OPK file must already be present in /media/data/apps.

Duxlink

Example usage

$ duxlink install application.opk
  Installing...
  16384 bytes transferred
  Done!

$ duxlink run application.opk
  Hello Dingux!

$ duxlink debug console_template.opk
  GNU gdb (GDB) 7.7.1
  ...
  Type "apropos word" to search for commands related to "word"...
  Reading symbols from opkrun...(no debugging symbols found)...done.
  (gdb)

libdingux examples

To use libdingux, it first has to be build the same way all other projects are build. Don't forget to run meson install -C build at the end to move the static library file to the right location!

Types

libdingux defines many type aliases for standard types. For example u32 for std::uint32_t, a 32 bit unsigned integer or vs8 for volatile std::int8_t, a 8 bit volatile, signed integer.


  u32 address = 0xDEADBEEF;
  vu32* reg = reinterpret_cast<vu32*>(address);

TypeSafe<T> is available for type-safe versions of standard types.


  using Capacity = TypeSafe<u32>;
  using Price = TypeSafe<u32>;

  // TypeSafe<T> prevents issues where 1000 things are sold for 10$ by accident
  // instead of 10 things for 1000$ by preventing implicit type conversions
  sell(Capacity(10), Price(1000));

Button input

On the RG350 and similar models, button input can be read from the /dev/input/event0 event.

static dux::sys::Input input("/dev/input/event0");

int main() {

  while (true) {
    // Update pressed buttons
    input.scanInput();

    // Get Pressed, released and held buttons
    auto pressedButtons = input.getPressedButtons();
    auto releasedButtons = input.getReleasedButtons();
    auto heldButtons = input.getHeldButtons();

    // True if the A button was pressed (true for one frame after pressing the button)
    if (pressedButtons.A) { /* ... */ }

    // True if the A button was released (true for one frame after releasing the button)
    if (releasedButtons.A) { /* ... */ }

    // True if the A button is being held down
    if (heldButtons.A) { /* ... */ }

  }
}

Framebuffer drawing

This should not be used unless absolutely necessary as it will not work anymore in updated OpenDingux versions. Instead use SDL or SDL2.

#include <dingux.hpp>

static dux::sys::Framebuffer fb0("/dev/fb0", 3);

int main() {

  u8* framebuffer = fb0.getAddress();
  std::size_t framebufferSize = fb0.getSize();
  u8 numberOfFrambuffers = fb0.getNumberOfFramebuffers();

    while (true) {

      // Fill all framebuffers with a white color
            std::memset(framebuffer, 0xFF, framebufferSize * numberOfFrambuffers);

    }

    return 0;
}