-
Notifications
You must be signed in to change notification settings - Fork 108
Stable branch Changelog
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.
Builtin FatFS has been upgraded to R0.15 Patch3.
Libdragon now has a nice logo, designed by Spooky Илюха and Cedar Branch:
See the wiki page about Logos for more information.
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.
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
.
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.
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.
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:
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.
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
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.
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
.
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.
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.
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.
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.
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).
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);
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.
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.
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.
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.
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).
-
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 likemalloc_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 standardrspq_write()
function. This is currently used in the unstable channel for the RDP triangle primitive that might require many different parameters.
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.
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.