BlocksDS
Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

C/C++ support

1. Introduction

BlocksDS supports modern C/C++ standard libraries by providing the following libraries:

  • picolibc, an embedded-centric fork of the Newlib C library;
  • libstdc++, the GNU C++ library.

However, this support includes some platform-specific caveats.

2. POSIX I/O

BlocksDS provides POSIX standard I/O using the tinystdio library, which is part of picolibc. It supports most of the functionality mandated by the C standard, as well as some extensions.

File I/O (fopen, opendir, etc.) is supported. Storage on cartridges and the DSi internal SD card can be accessed. A bundled read-only filesystem called NitroFS is also supported. For more information, check the filesystem documentation.

Console I/O (stdin, stdout) is supported; however, by default, no input or output is initialized:

  • stdout can be redirected to the built-in libnds console by initializing the console. This can be done using the consoleInit() or consoleDemoInit() functions.
  • stderr can be redirected to the built-in libnds console or a no$gba-compatible emulator debug output by using consoleDebugInit().

Standard output is unbuffered. When text is sent to them (by using printf() or fprintf(stderr, ...) it’s always sent to the console. The exceptions are ANSI escape sequences, which are buffered until the end of the sequence is received, and then sent to the console low level functions.

Remember that you can use fflush(stdout) or fflush(stderr) if buffering becomes an issue.

For more information about ANSI escape sequences, check this link.

  • stdin is tied to the keyboard of libnds. When sscanf(stdin, ...) is called, for example, the keyboard of libnds is used as input device. For more information, see the relevant examples bundled with BlocksDS.

3. argc and argv

To provide correct argv information, the loader needs to support argv structure passing. This is not supported by certain legacy loaders; for more information, see our page on legacy support.

Under compatible loading environment, argv[0] will hold the path of the .nds file. Other argv entries may be set as well, but this isn’t a common occurrence.

  • For cartridges, the drive name used is fat: - for example, fat:/homebrew/program.nds.
  • For DSi consoles loading .nds files from the internal SD card, the drive name used is sd: - for example, sd:/homebrew/program.nds.

4. Dynamic heap allocation

Functions like malloc, calloc, memalign and free are supported. They always return space from the main RAM region.

5. Time

gettimeofday and time are supported. Timezones are not handled in any particular manner, however.

6. Exit

If the NDS ROM loader supports it, exit can be used to return to the loader. You can also return from main() to get the same effect.

For more information, check this document.

In addition, atexit is supported for dynamically registering program exit handlers.

7. Multithreading

Functions like fopen() or malloc() need to be thread-safe, and picolibc uses locks to ensure that they are thread-safe. The implementation of the locking funtrions is platform-specific, and libnds has its implementation in this file.

In general, you don’t need to worry about them. However, if there is an unexpected crash because of running the undefined instruction 0xEBAD, it may mean that the locking functions have found a logic error.

Printing an error message is very expensive: it is required to include a text font as well as console handling functions. The locking functions simply have a function with an opcode that is defined to always be an undefined instruction in Thumb mode by the ARM Architecture Reference Manual.