Skip to content

Stable branch Changelog

Giovanni Bajo edited this page Oct 14, 2024 · 17 revisions

Changelog of the stable branch.

This pages lists all main features that have been merged to the stable branch (trunk), and is updated quarterly. Bugfixes or small feature tweaks are not listed here. If you want to see the upcoming features, have a look at the preview branch which is where features are developed and stabilized.

2023 Q4

Upgrade builtin FatFS

Builtin FatFS has been upgraded to R0.15 Patch3.

2023 Q3

New logo

Libdragon now has a nice logo, designed by Spooky Илюха and Cedar Branch:

See the wiki page about Logos for more information.

Reworked display filtering options

display_init has been reworked to clarify the various filters performed by VI and rule out invalid configurations that might create video errors on specific configurations. The old ANTIALIAS_* macros have been deprecated (as in general antialias is just one of the possible filters) and in their place, you can now use the new FILTER_* macros:

  • FILTER_NONE: disable any kind of filtering; the framebuffer is scaled to the TV resolution just skipping pixels or duplicating them, with no interpolation at all.
  • FILTER_RESAMPLE: the framebuffer is scaled to the TV size using bilinear interpolation.
  • FILTER_DEDITHER: Post-process dithering as performed by RDP during triangle drawing, trying to reconstruct a 32-bpp cleaner output. Scaling is performed without bilinear.
  • FILTERS_RESAMPLE_ANTIALIAS: Post-process outer triangle edges to smooth them with the nearest pixels to avoid jagged lines; this is a crude form of anti-aliasing. Scaling is performed with bilinear filter.
  • FILTERS_RESAMPLE_ANTIALIAS_DEDITHER: Post-process using both dedither and antialiasing. Scaling is performed with bilinear filter.

Mikmod is not built anymore by default

Libdragon previously always built the mikmod module player library. This was a very old port using CPU only, that doesn't perform very well. The new RSP mixer library together with the xm64 player is a superior option for a game (even if it supports only the .XM format, you can use tools OpenMPT to convert other module formats to XM, with minimal to none loss).

If you still need mikmod, you can build it manually using the provided script tools/build-mikmod.sh.

New asset library

Libdragon now features a library to help loading asset files from the filesystem, with transparent compression support. The library is used via two main functions:

  • asset_load(): fully load a file from the filesystem into RDRAM, allocating the required memory from the heap. If the file is compressed, it is transparently decompressed during load.
  • asset_fopen(): return a FILE* which can be used to read and parse a file a bit at a time, with optional transparent decompression. This can be used for file formats that require parsing or for files that can be streamed.

To compress files, you can use the new mkasset tool. Currently two compression levels are support: level 1 which is very fast and with lower compression ratio, and level 2 which is slower but with higher compression ratio. The actual algorithms at the moment are LZ4 and LZH5 respectively but this is an implementation detail. Do not commit compressed assets to your repo as the compressed format can change at any time; instead, compress them during the build.

For more information, refer to the new Compression page in the wiki.

2023 Q2

Stack traces on crashes and interactive crash inspector

In case of any crash (unhandled MIPS exceptions, unhandled C++ exceptions) or assertion, you will automatically be shown a full stack trace (include source code file names and lines). This is very useful to quickly pinpoint the reason for the crash.

Schermata 2022-12-26 alle 15 55 22

The crash screen has also been rehauled and it is now a multi-page inspector offering also a builtin disassembler, in addition to register dumps:

Schermata 2022-12-26 alle 15 47 33

This happens fully automatic on recompilation after updating libdragon, provided that you use a n64.mk-based Makefile.

It is also possible to manually print a stack trace from a certain calling point using the new debug_backtrace() function.

Improved compatibility of SD card support

Libdragon's debug library allows to read and write files to SD cards supported by flashcarts, through a simple file-based API (fopen("sd:/file.txt", "w")). The support has been greatly enhanced in compatibility thanks to the integration of libcart. SD support is now available on:

  • 64Drive HW1 and HW2
  • EverDrive-64 V1, V2, V2.5, V3, X7 and X5
  • ED64Plus / Super 64
  • SummerCart64

Improved USB debugging library

Libdragon's vendored usb library has been upgraded to the latest version, which offers better performance and supports connection / disconnection of the host tool, to ease debugging. If you are using UNFLoader to see the debugf() logs from libdragon, make sure to upgrade it to the latest version.

Separate prefix for the toolchain

It is now possible to install the toolchain in a different prefix from libdragon itself. Use $N64_GCCPREFIX to specify the prefix for the toolchain, while leaving $N64_INST pointing to libdragon installation directory. If $N64_GCCPREFIX is not defined, it will default to $N64_INST.

2023 Q1

Support for usage of fatfs

Years ago, libdragon started linking with fatfs, and this prevented software (such as flashcart menus) to bring their own copies of fatfs because of duplicated symbols failure. Now libdragon exports fatfs.h, so basically applications can rely on fatfs directly if they need to. Remember that for SD card access, you can use the libdragon debug library, without needing to use fatfs directly.

The change also allowed files on the SD card to be generated using the correct time whenever a RTC is present. Simply call rtc_init() to initialize the RTC, and then create a file via fopen("sd:/test.txt", "wb"): you will see it with the correct timestamp.

Binary toolchain built via CI

Historically, libdragon has provided a script to build a toolchain on a Linux system, but the user had to build the toolchain on their own computer. The only alternative for a long time was the usage of a Docker container. Now, libdragon builds via CI an updated toolchain that is uploaded on GitHub, for Windows and Linux (deb/rpm).

Please make sure to follow the installation instructions.

FPU Exceptions activated by default

Libdragon now activates MIPS FPU exceptions by default. This allows the game to instantly crash whenever there is a division by zero, or uninitialized memory is accessed by the floating point unit, which in turns helps catching bugs much earlier and with fewer surprises. When the exception screen triggers, it shows the PC address where the exception triggered, that you can lookup in the map file to see the name of the function.

2022 Q4

Speedup boot

We improved the libdragon boot by using PI DMA instead of CPU writes to load the binary from ROM, and also avoiding loading some part that was preloaded by IPL3. The boot was speedup by about 200ms for a standard ROM.

C++ exceptions

You can now reliably use C++ exceptions in libdragon games, they used to be unsupported before. Uncaught exceptions terminate the program and display an error message on the debug channel (on the unstable branch, they are properly caught and displayed in the upcoming inspector).

Support for arbitrary screen resolutions

Libdragon now supports configuring arbitrary resolution via display_init. Before, the choice was limited to a few common ones like (320x240, 640x480, etc.), but the VI hardware has a flexible resolution scaler so it is actually able to configure any resolution between 2 and 800 horizontal, and between 2 and 600 vertical. Assuming a proper 3D engine that adapts the viewport to the current resolution, increasing resolution to some custom value (until FPS is high enough) is a good way to increase the visual quality of a game.

This is an example configure a custom 444x240 resolution:

    display_init((resolution_t){ .width=444, .height=240, .interlaced=false }, DEPTH_16_BPP, GAMMA_NONE, ANTIALIAS_RESAMPLE);

Improved syntax for RSP assembly

RSP assembly syntax has been improved. It is now possible to reduce the number of arguments avoiding redundant ones, like in the following example where all lines produce the same instruction:

    vaddc $v01, $v01, $v02,e(0)
    vaddc $v01, $v01, $v02
    vaddc $v01, $v02,e(0)
    vaddc $v01, $v02

Moreover, a new dot-based syntax has been added to element specifiers that is easier to write and read, more similar to GLSL shaders, and also more orthogonal in its usage across the different opcodes:

    vaddc $v01, $v02.e4      # Add the contents of lane 4 of $v02 to all lanes in $v01
    vmov  $v01.e7, $v02.e1   # Move lane 1 of $v02 into lane 7 of $v01.

Expert users will notice that the syntax .eN always uniformly refers to a lane, even though it is ended differently in different opcodes. The equivalent version in SGI syntax for vmov would be:

    vaddc $v01, $v02[e4]
    vmov  $v01[e15], $v02[e9]   # !!!

In addition to .eN to specify a lane, there is also .qN and .hN for partial broadcasts in math opcodes.

2022 Q3

Add APIs to handle the reset button and the pre-NMI interrupt

When the reset button is pressed, a pre-NMI interrupt is generated and a 500ms grace time is given before the console is reset (as the RCP must be in idle state before the NMI happens). It is now possible to register a handler for the pre-NMI interrupt via register_RESET_handler(). Moreover, for simpler use cases where it is sufficient to poll whether the reset button was pressed or not, it is possible to call exception_reset_time() that will return the number of ticks since the button was pressed (or 0 if it wasn't pressed).

Some initial support has also be added to help leaving the RCP in idle state. For instance, the audio library will stop sending buffers to AI just before the NMI arrives, and the mixer library will also fade out the audio automatically during the 500ms grace time.

New surface_t structure

Libdragon now defines surface_t which is an arbitrary rectangular surface, with a specific pixel format (tex_format_t).

This is a building block upon which the new rdpq library will build upon (in the unstable branch). display_lock() has been updated to return a surface_t* now, so that it's possible to easily access the pixels of the current framebuffer if needed. Also graphics.h (the CPU-based drawing API) has been updated to draw upon a generic surface_t*, so that it can be used also on off-screen memory buffers.

Make dma_read_async / dma_write_async APIs work on the full PI range

Historically, both dma_read and dma_write constrain the provided PI addresses to the ROM address space, and this is impossible to change for backward compatibility.

The newer DMA APIs dma_read_async and dma_write_async (together with the raw counterparts: dma_read_raw_async and dma_write_raw_asycn) have been instead enhanced to work to the full address space, including for instance 64DD or SRAM.

2022 Q2

Support for CART interrupts

Devices on the cartridge connectors (eg: flashcarts, 64DD) can generate an interrupt called CART. It is now possible to register a handler for this interrupt via register_CART_handler() and enable it via set_CART_interrupt(true).

In fact, it is possible to register multiple interrupts as there will probably be more libraries that could wait for it (eg: a flashcard library and a 64DD library).

Misc new APIs

  • debug_hexdump() dumps a binary buffer to the debug channel, with a nice formatted hexdump format, including ASCII conversion.
  • malloc_uncached_aligned() allows to allocate an uncached memory buffer (just like malloc_uncached) but specifying an alignment for the base pointer.
  • rsp_write_begin() / rspq_write_arg() / rspq_write_end() allow to call a RSPQ function in an overlay with more than 16 arguments, which is the limit for the standard rspq_write() function. This is currently used in the unstable channel for the RDP triangle primitive that might require many different parameters.

Add workaround for AI hardware bug

A workaround has been added for the rare case of hitting a AI hardware bug that causes sound corruptions when the audio buffers happen to have some specific page alignment. The bug is also accurately reproduced on emulators such as Ares.

2022 Q2

Rework main exception handler including performance improvements

The main libdragon exception/interrupt handlers has been reworked with several improvements:

  • The exception frame is now saved to the standard user stack. Previously, a dedicated interrupt stack was used. In addition to saving memory for interrupt stack, this is a required step as we move towards a multi-threaded kernel, as each thread must have its own exception frame when preempted.
  • When servicing an interrupt, it is possible for an exception to trigger, reentrantly. This allows to better catch bugs in interrupt handlers (before, things like dereferencing a NULL pointer would go unnoticed as exceptions were disabled during interrupt servicing).
  • The state of the FPU is lazily saved for interrupt handlers, on the first actual usage of the FPU. Since most interrupt handlers do not need the FPU at all, the FPU state is not saved to the stack at all, improving speed.