> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/pret/pokeemerald/llms.txt
> Use this file to discover all available pages before exploring further.

# Decompilation Standards

> Code conventions and matching requirements for pokeemerald contributions.

All non-modern code contributions must produce a ROM that is byte-identical to the original. This page describes what that means in practice, and the conventions you must follow to get there.

## The matching requirement

<Warning>
  `make compare` is the gating test for every PR. Your code must compile to identical machine code as the original ROM. If `make compare` fails, the contribution is not ready to merge.
</Warning>

```bash theme={null}
make compare
```

The target ROM is:

```
pokeemerald.gba  sha1: f3ae088181bf583e55daf962a92bb46f4f1d07b7
```

## agbcc vs. modern builds

The original game was compiled with **agbcc**, an old ARM C compiler derived from GCC 2.7. Non-modern code must compile cleanly under agbcc.

<Info>
  The repository supports a `MODERN` build flag that uses a current GCC toolchain. Modern-only code is guarded with `#if MODERN`. Do not introduce modern-only constructs into code paths that must match the original ROM.
</Info>

The most important agbcc constraint is **C89/C90 compatibility**. agbcc does not support C99 features. The most common mistake is declaring variables mid-block:

```c theme={null}
// Not valid under agbcc — declaration after a statement
void BadExample(void)
{
    DoSomething();
    int x = 5; // error: agbcc rejects this
}

// Correct — all declarations at the top of the block
void GoodExample(void)
{
    int x;
    DoSomething();
    x = 5;
}
```

## Integer types

Use the GBA integer types from `include/gba/types.h`. Do not use `int`, `unsigned int`, `short`, etc. directly in game structs or function signatures where a specific width is required.

| Type     | Width  | Signedness |
| -------- | ------ | ---------- |
| `u8`     | 8-bit  | unsigned   |
| `u16`    | 16-bit | unsigned   |
| `u32`    | 32-bit | unsigned   |
| `s8`     | 8-bit  | signed     |
| `s16`    | 16-bit | signed     |
| `s32`    | 32-bit | signed     |
| `bool8`  | 8-bit  | boolean    |
| `bool16` | 16-bit | boolean    |
| `bool32` | 32-bit | boolean    |

## Naming conventions

Follow the patterns already established in the codebase:

* **Functions and variables**: `snake_case`
* **Constants and macros**: `UPPER_CASE`
* **Files**: `snake_case` matching the existing `src/` and `include/` layout

Do not introduce camelCase or PascalCase for new identifiers outside of existing patterns.

## Key macros from global.h

Several macros defined in `include/global.h` have matching implications — they reflect patterns GameFreak used that the compiler must reproduce exactly.

### BLOCK\_CROSS\_JUMP

```c theme={null}
// Prevent cross-jump optimization.
#define BLOCK_CROSS_JUMP asm("");
```

Used to prevent agbcc from merging identical code blocks in a way that would change the output binary. Insert it where a function would otherwise mis-match due to the optimizer collapsing branches.

### Array size macros

```c theme={null}
#define ARRAY_COUNT(array) (size_t)(sizeof(array) / sizeof((array)[0]))

// GameFreak used a macro called "NELEMS", as evidenced by AgbAssert calls.
#define NELEMS(arr) (sizeof(arr)/sizeof(*(arr)))
```

Use `ARRAY_COUNT` for new code. `NELEMS` is retained because it matches AgbAssert call sites in the original binary.

### SWAP

```c theme={null}
#define SWAP(a, b, temp)    \
{                           \
    temp = a;               \
    a = b;                  \
    b = temp;               \
}
```

Use this macro wherever the original code performs an in-place swap via a temporary variable. Do not substitute `stdlib` or C99 compound-literal tricks.

### Fixed-point math

The GBA lacks an FPU. GameFreak used Q-format fixed-point arithmetic throughout. The relevant macros are:

```c theme={null}
// Converts a number to Q8.8 fixed-point format
#define Q_8_8(n)   ((s16)((n) * 256))

// Converts a number to Q4.12 fixed-point format
#define Q_4_12(n)  ((s16)((n) * 4096))

// Converts a number to Q24.8 fixed-point format
#define Q_24_8(n)  ((s32)((n) << 8))
```

Corresponding inverse macros (`Q_8_8_TO_INT`, `Q_4_12_TO_INT`, `Q_24_8_TO_INT`) are also defined. Use the appropriate format to match the original code's precision.

## gametypes.h and save-compatible types

`include/gametypes.h` defines families of typedefs for fields that appear in save data. The naming convention encodes the underlying width so it is visible at a glance:

```c theme={null}
typedef u8  mapsec_u8_t;
typedef u16 mapsec_u16_t;
typedef s16 mapsec_s16_t;
typedef s32 mapsec_s32_t;
```

<Note>
  The smallest typedef in a family (e.g. `mapsec_u8_t`) is the canonical type — the width at which the value is actually stored in flash memory. Larger variants exist only to describe places where the original code handled the value inconsistently.
</Note>

When adding a new persistent field, declare its typedef in `gametypes.h` following this pattern, and use the smallest type that fits the full range of valid values.

## Save data constraints

The vanilla game uses 96% of its available EEPROM. The remaining free space is not contiguous:

<Warning>
  * **SaveBlock1** can grow by at most **84 bytes**
  * **SaveBlock2** can grow by at most **120 bytes**
  * Additional free space exists after PC-boxed Pokémon data, but is less accessible

  Be conservative. Every byte added to a save block reduces the headroom available to all future contributors and ROM hackers.
</Warning>

Struct members that land in save blocks must be ordered to minimize compiler-inserted padding. Because field widths are visible in the `gametypes.h` typedef names, you can reason about padding without needing a `sizeof` check each time.

## asm stubs

Functions not yet decompiled exist as assembly stubs under `asm/`. The goal of the project is to replace each stub with matching C code.

```
asm/
└── battle_anim_utility_funcs.s   ← example stub awaiting decompilation
```

When you decompile a function:

1. Write the C implementation in the appropriate `src/` file.
2. Remove the corresponding `.s` stub (or the relevant label from it).
3. Run `make compare` to confirm the output is still byte-identical.

<Tip>
  Use `asm_unified` and the `NAKED` attribute when you need to write or preserve hand-written assembly within a C file:

  ```c theme={null}
  #define asm_unified(x) asm(".syntax unified\n" x "\n.syntax divided")
  #define NAKED __attribute__((naked))
  ```
</Tip>

## UBFIX and BUGFIX

The codebase uses two annotation macros to mark intentional fixes:

```c theme={null}
#ifdef UBFIX
#define SAFE_DIV(a, b) (((b) != 0) ? (a) / (b) : 0)
#else
#define SAFE_DIV(a, b) ((a) / (b))  // matches original behavior
#endif
```

* **`UBFIX`** — guards fixes for undefined behavior present in the original ROM. Enabled separately from a standard build.
* **`BUGFIX`** — guards fixes for observable gameplay bugs.

Do not silently fix UB or bugs in matching code. If you encounter undefined behavior while decompiling, reproduce it faithfully and guard any fix behind the appropriate macro so that `make compare` still passes with the fix disabled.

## IDE support macros

```c theme={null}
#if defined(__APPLE__) || defined(__CYGWIN__) || defined(__INTELLISENSE__)
#define _(x)        {x}
#define __(x)       {x}
#define INCBIN(...) {0}
#endif
```

These macros are defined only when an IDE preprocessor is detected. They exist solely to suppress false IDE errors. Do not rely on them in code that will actually be compiled.
