In Wonderful's ecosystem, instead of relying on the linker and a post-link tool, linker wrappers are utilized instead. This allows handling everything from object linking to program file output in one step on the user side, as well as implementing high-level configuration facilities which generate a link script.
# This call... $ arm-none-eabi-ld -o program.elf [objects...] [flags...] # ...becomes: $ wf-gbatool link rom|multiboot -o program.gba --output-elf program.elf -- [objects...] [flags...] # By default, wfconfig.toml in the current working directory is used # (see below). To use a different file: $ wf-gbatool link rom|multiboot -c other_wfconfig.toml -o program.gba --output-elf program.elf -- [objects...] [flags...]
GBA cartridges contain some user-configurable metadata. To edit it, create a wfconfig.toml
file with the following contents:
[cartridge]
logo = "official"
title = "Program"
code = "XXXX"
maker = "WF"
The GBA contains two separate blocks of memory: 32 kilobytes of fast IWRAM and 256 kilobytes of slower EWRAM. In Wonderful's GBA target, memory which is not explicitly marked as belonging to IWRAM or EWRAM with a section attribute is placed in EWRAM by default. However, this can be changed to IWRAM by using he following wfconfig.toml configuration:
[memory]
data-region = "iwram"
wf-gbatool link
also allows you to easily use memory overlays: overlapping areas of memory containing code and data that can be easily swapped out. For example, the following wfconfig.toml
configuration:
[memory.overlay]
iwram = [
["one", "two"],
["one", "three"],
["four"]
]
creates three valid IWRAM layout configurations:
.iwram_one
and .iwram_two
may be loaded at the same time,.iwram_one
and .iwram_three
may be loaded at the same time (but without guarantees for .iwram_two
),.iwram_four
may be loaded (but without guarantees for any of the other sections).
This allows minimizing the amount of IWRAM space occupied by code. One can use the following helper (also provided in <gba/overlay.h>
) to load such an overlay from ROM to RAM:
#define gba_overlay_load(TYPE, NAME) \
{ \
extern char __load_addr_ ## TYPE ## _ ## NAME ; \
extern char __load_start_ ## TYPE ## _ ## NAME ; \
extern char __load_stop_ ## TYPE ## _ ## NAME ; \
memcpy( \
&__load_addr_ ## TYPE ## _ ## NAME , \
&__load_start_ ## TYPE ## _ ## NAME , \
&__load_stop_ ## TYPE ## _ ## NAME - \
&__load_start_ ## TYPE ## _ ## NAME ); \
}
#define gba_overlay_load_iwram(NAME) gba_overlay_load(iwram, NAME)
// EWRAM is also supported!
#define gba_overlay_load_ewram(NAME) gba_overlay_load(ewram, NAME)
From there, the helper can be used as follows:
__attribute__((noinline, section(".iwram_one"))) void func_a(void) {
// ...code...
}
__attribute__((noinline, section(".iwram_four"))) void func_b(void) {
// ...code...
}
// ...function...
gba_overlay_load_iwram(one);
func_a();
gba_overlay_load_iwram(four);
func_b();