Wonderful Toolchain project update - September 2025

Published on September 5, 2025

Here’s what I’ve been tinkering with for the past three months with the Wonderful toolchain.

New tools

The highlight of this project update is the introduction of three new tools - some long awaited by users, others long awaited by myself.

agbpack

There are two primary forms of GBA homebrew:

  • Cartridge images, available via an attached ROM - the primary form of homebrew these days;
  • Multiboot images, loaded directly to memory via link cable - used for multiplayer games, early homebrew development (think Xboo PC cables), and by the GBA Movie Player.

Modern libraries, like gba-link-connection, provide an user-friendly interface for developing multiplayer games. As a result, there has been a small resurgence of interest in creating multiboot GBA software. However, it is still a rather constrained form - you have to fit the entire game in 256 KiB of EWRAM, and the largest games can take as long as 30 seconds (!) to be transmitted over the cable.

agbpack is a tool I developed which attempts to lessen both of these problems by taking advantage of in-place executable decompression:

  • With a compression ratio of 55-80%, games can be transferred significantly faster;
  • By allowing direct extraction into EWRAM, IWRAM and VRAM, uncompressed multiboot executables can use more than 256 KiB total space, making them a little less constrained.

Simply run:

    $ agbpack original_mb.gba packed_mb.gba

using any multiboot .gba file as input, and receive a compressed file back! (Note that supporting direct placement of data in IWRAM and VRAM requires adaptations to the toolchain.)

You can download the standalone tool here; it is also integrated by default into the Wonderful toolchain.

wf-…tool usage

I’ve long been a fan of bbbbbbr’s romusage tool for estimating the memory usage of cartridge images built using SDCC.

It doesn’t support ELF files, or the WonderSwan, so I decided to build my own variant of the tool: wf-wswantool usage.

Section                Range            Size    Used  Used%    Free  Free%
--------------- -------------------- ------- ------- ------ ------- ------
Internal RAM      0x0000 -> 0xFFFF     65536   21670    33%   43866    67% |=#####.###=.................|
+- Mono area      0x0000 -> 0x3FFF     16384   13478    82%    2906    18% |##.-####################=...|
+- Color area     0x4000 -> 0xFFFF     49152    8192    16%   40960    84% |####=.......................|
Cartridge ROM    0xE0000 -> 0xFFFFF   131072   48573    37%   82499    63% |.................-##########|
+- Linear $FF    0xE0000 -> 0xFFFFF   131072   48573    37%   82499    63% |.................-##########|
   +- Bank $FE   0xE0000 -> 0xEFFFF    65536       0     0%   65536   100% |............................|
   +- Bank $FF   0xF0000 -> 0xFFFFF    65536   48573    74%   16963    26% |.......#####################|

In addition, it supports the toolchain’s other target platforms - the WonderWitch and the GBA:

Section         Range          Size   Used  Used%   Free  Free%
--------- ------------------ ------ ------ ------ ------ ------
Code       0x0000 -> 0xFFFF   65536   5552     8%  59984    92%
Data       0x0000 -> 0xFFFF   65536  42094    64%  23442    36%
Section          Range            Size    Used  Used%    Free  Free%
--------- -------------------- ------- ------- ------ ------- ------
IWRAM       0x0000 -> 0x7FFF     32768   12680    38%   20088    62%
EWRAM      0x00000 -> 0x3FFFF   262144  245708    93%   16436     7%

As I’ve only really added the small set of features I relied on myself when using GBDK, don’t hesitate to propose additional ones!

wf-env

One slightly annoying aspect of the Wonderful toolchain’s installation was having to manually configure environment variables, like WONDERFUL_TOOLCHAIN, and adding /opt/wonderful/bin to PATH. In line with many other toolchains, I have added a command to perform this step for you:

    # bash, zsh, ...
    $ . wf-env

    # fish
    ~> . /opt/wonderful/bin/wf-env.fish

An useful additional feature is the -a argument - it adds all the installed toolchains to PATH. This allows you to use tools such as arm-none-eabi-nm or ia16-elf-objdump without having to manually type in or append their paths.

Toolchain improvements

WonderSwan target updates

  • Added helper functions for configuring horizontal/vertical blank timers.
  • Added startup files which allow creating “pin-strapped” (PCv2-compatible) cartridge images.
  • Added ia16_get_sp() helper function.
  • Added setjmp() and longjmp() implementations.
  • Fixed ws_bank_with_rom0() typo.
  • Fixed ws_cart_rtc_* helper functions.
  • Initial work on stdio file/console I/O started.
  • Updated binutils-ia16 on Windows to 2.43.1.
  • Documentation improvements: additional comments, fixed Doxygen function output.
  • Improved header support for the CLion IDE.
  • Removed the legacy wf-wswantool romlink linker. It was deprecated really early in the toolchain’s history, so it shouldn’t affect any existing projects.

One notable feature is that wswan/small-sram and wswan/medium-sram subtargets now support defining variables in internal RAM as follows, without having to explicitly specify an ELF section:

    uint16_t ws_iram my_table_in_iram[32];

As a side note, wf-mednafen received a minor update fixing some CPU/APU emulation bugs and improving the debugger port layout slightly. (While Mesen 2 is the recommended emulator for WonderSwan development these days, it does not yet cover more oddball usage scenarios.)

GBA target updates

Other than the integration of agbpack, the GBA target has received two new headers:

  • <gba/bios.h>, containing wrappers for BIOS SWI calls,
  • <gba/mmio.h>, containing macros for accessing (most of) the GBA’s memory-mapped I/O space.

A performance issue was identified where __muldi3 was built as Thumb in Thumb mode, which is both significantly larger and slower than always using the ARM variant (even with the overhead of interwork!) - this has been fixed.

With regards to packages, the GCC ARM toolchain has been updated (binutils 2.44 -> 2.45, GCC 15.1.0 -> 15.2.0); the version of libtonc packaged has also been updated.

I don’t think the target on its own is likely to leave the “experimental” stage soon, let alone become as friendly as something like Butano. Regardless, a bit of progress has been made this time around.

Miscellaneous changes

  • wf-fatfs has been updated to R0.16p1.
    • In addition, a bug which broke removing directories when the FF_WF_LIST_DOTDOT configuration option was enabled has been fixed.
  • wf-process has received LuaLS-compatible bindings for its API libraries.
  • wf-sox has been replaced with the sox_ng fork on Linux.
  • Added a minimal landing page to the toolchain’s website.
  • Some wf-tools now emit ANSI color codes as part of text output. (If you’re not a fan of that, the NO_COLOR environment variable is respected.)