-
Notifications
You must be signed in to change notification settings - Fork 108
Stable branch Changelog
This pages lists all main features that have been merge to the stable branch (trunk
), and is updated quarterly. If you want to see the upcoming features, have a look at the unstable branch which is where features are developed and stabilized.
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.