- Install arm-none-eabi-gcc (if you're on Windows, you can use msys2 and install
mingw-w64-arm-none-eabi-gcc
package; on Linux/macOS use your distro's package, e.g for Debian it isgcc-arm-none-eabi
, on macOS Homebrew it'sgcc-arm-embedded
; this guide won't work on macOS ≥10.15 because elf2mod is a 32-bit app). - Fetch Brew MP SDK 7.12.5 installer and platform SDK installer for the BREW version you'd like to target. Installers won't run on windows 10, so don't install them yet.
- Extract Brew MP SDK 7.12.5 installer with 7-Zip.
- Inside it, extract another installer called BREWMPTools.exe the same way.
- Extract platform SDK to some other directory.
gcc/g++ compiler flags:
-fshort-wchar -mword-relocations -ffunction-sections -fdata-sections
-fno-exceptions -marm -mthumb-interwork -march=armv5te -I$SDK_PATH/inc
-specs=nosys.specs -D__ARMCGCC -DDYNAMIC_APP
$SDK_PATH
is the path to the sdk
subdirectory in the platform SDK.
You might also want you preferred optimization flags, e.g. -O2
.
g++ also needs these:
-fno-use-cxa-atexit -fno-rtti
Linker flags (additionally to the flags that are passed to the compiler) (use gcc to link, not g++, even if you write in c++!):
-nostartfiles -Wl,--entry=AEEMod_Load -Wl,--emit-relocs -Wl,--default-script=elf2mod.x
-Wl,--no-wchar-size-warning -static-libgcc -Wl,--gc-sections
elf2mod.x
can be found at bin/elf2mod/src/gnu/
in the extracted BREWMPTools.exe
Basic implementation of some required initialization routines can be found in the platform SDK at path sdk/src
. You're especially interested in AEEModGen.c
, which is the default startup routine, and (unless you write an app without UI) AEEAppGen.c
, which is a basic applet startup routine.
After you linked the app, run elf2mod.exe -output AppName.mod AppName.elf
(where AppName.elf
is your linker output binary; elf2mod.exe
is in the Toolset at path bin/elf2mod.exe
; you can use Wine if you are on Linux/macOS) to create a MOD file.
You need this to successfully use C++ apps that use new/delete:
extern "C" {
#include <AEEStdLib.h>
}
void* operator new(size_t count) {
return MALLOC(count | ALLOC_NO_ZMEM);
}
void* operator new[](std::size_t count) {
return operator new(count);
}
void operator delete(void* ptr) noexcept {
return FREE(ptr);
}
void operator delete(void* ptr, std::size_t count) noexcept {
return operator delete(ptr);
}
void operator delete[](void* ptr) noexcept {
return operator delete(ptr);
}
void operator delete[](void* ptr, std::size_t count) noexcept {
return operator delete(ptr);
}
- You cannot use any functions from C/C++ standard library that do I/O or allocate memory. You will get either linking or runtime errors. Instead, you have to use the BREW APIs.
- C++ global variable constructors are not called. If you want them, use this instead of AEEModGen.c from the platform SDK: https://github.com/usernameak/OpenLara/blob/master/src/platform/brew/OpenLaraMod.c
- When including BREW headers in C++ apps, you might want to use
extern "C"
- MIF file should be called the same as the app directory. MOD file may have any name, but if you also need SIG file in order to sideload the app onto a phone, they should have identical names (supposedly case-sensitive).