5.7 KiB
Contribution guide
Project structure
asm/: Non-decompiled assembly codeovXX/: Code for overlayXX*.s: Source file in assembly*.inc: External symbols imported by respective source file
build/: Build outputarm9_linker_script.lcf: Linker command file for ARM9 program, specifies the order to put code and data into the ROMarm9_objects.txt: List of object files to pass to the linkereur/: Compiled/linked filesasm/: Built assembly codesrc/: Built C/C++ codeoverlays/: Contains.binand.lzfiles for each overlay*.bin: Linked code/data to compress or put in the ROM*.lz: Compressed code to put in the ROMmain.bin.xMAP: Map file listing RAM addresses for all symbols
docs/: Documentation about the gameinclude/: Include filesph_eur/: Game assets, extracted from your own supplied ROMassets/: Unmodified assetsbanner/: Banner logo and text that shows on the DS home menuarm7.bin: Extracted ARM7 programarm9_ovdata.bin: Data about ARM9 overlays
src/: Source C/C++ filestools/: Tools for this projectcompress/: Compresses code before it is put in the ROMinclude/: Common C code for multiple toolsmwccarm/: Compiler toolchainrom/: Extracts and builds ROMsgen_externs.py: Generates.incfiles, usemake gen_externsto run itlcf.py: Generatesarm9_linker_script.lcfm2ctx.py: Generates context for decomp.mepatch_mwcc.py: Patches bugs in the toolchainprogress.py: Computes decompilation progressrequirements.txt: Python librariessetup.py: Sets up the project
assets.txt: The order of asset directories to put in the ROM*.sha1: SHA-1 digests of different versions of the game
Decompiling
See /docs/decompiling.md.
Creating new .c/.cpp files
New source files must be added to the LCF (Linker Command File). This is done via lcf.py, which generates the LCF when
building.
In lcf.py, you will see a list of overlays near the top. Each overlay then has a list of source files ending in .s, .c or
.cpp. Those source files, when compiled, are appended to the ROM in the order that they appear in the list.
So, to create a new source file, you put the path to the source file in the correct overlay so that it appears in the correct order in relation to other source files.
Code style
The code style is not strict, but please try to mimic the existing style as much as possible.
If it's impossible to match a function while following the code style, then it's OK to not follow it. But do let us know when this happens so we may amend the code style.
Below is an example of the code style in this project. If something is unclear, look at existing code. If the existing code is insufficient, then you may decide the code style in that situation.
// Space before pointer asterisk * and reference ampersand &
s32 MyClass::MyMethod(MyStruct *myStruct, s32 &anInteger) {
// Opening brace { on the same line
// Space after `if`, `while`, `for` and `switch`
if (myStruct->isCool) {
// Class member fields are prefixed with "m"
mInteger = anInteger;
}
// No space before asterisk * in pointer casts
// Space after cast operator
mPointer = (u32*) &anInteger;
// Prefer pre-increment ++i
// Use s32, s16, s8, etc. instead of int, short, char
for (s32 i = 0; i < 10; ++i) {
// Use `char` instead of s8 to indicate actual characters
char ch = 'A' + i * 2;
mString[i] = ch;
}
// Put long conditions on new line
if (
// Add clarifying parentheses for bool operators
(mInteger > 10 && mPointer != NULL) ||
(mInteger < 5)
) {
// Add clarifying parentheses for bitwise operators
mBool = ((mInteger >> 5) & 1) != 0;
}
do {
// Call member functions using `this`
this->DoStuff();
// In do-while loops, `while` on same line as closing brace }
} while (this->CanDoStuff());
switch (mInteger) {
// Indent `case`
// If possible, put braces after `case`
case 8: {
return *mPointer;
// If possible, put `break` after closing brace }
} break;
}
// No parentheses around return value
return mInteger;
}
Non-matching functions
This project supports non-matching functions, and you can build them by using make NONMATCHING=1.
Non-matching functions must be written as follows:
#include "global.hpp"
NONMATCH void MyFunction() {
#ifndef NONMATCHING
#include "../asm/path/to/asm.inc"
#else
// non-matching code here
#endif
}
When building normally, the NONMATCH macro will mark MyFunction as an assembly function, and the NONMATCHING macro will
not be defined so that the asm.inc file will be included.
Conversely, when building in non-matching mode, MyFunction will be a regular C/C++ function, and the non-matching code will
be inserted instead of asm.inc.
When contributing non-matching functions to this project, please build in both modes and fix any build errors you may get.
Delete the .o file between building in each mode so that the Makefile runs the compiler both times.
Note
The inline assembler does not function the same as the standalone assembler. See differences here.