pokeemmo/AGENTS.md
cloyir 22856a2941
Some checks failed
CI / build (push) Has been cancelled
CI / docs_validate (push) Has been cancelled
CI / allcontributors (push) Has been cancelled
Docs / deploy (push) Has been cancelled
用Kimi Code生成了AGENTS.md
2026-03-04 02:13:13 +08:00

12 KiB

AGENTS.md - AI Coding Agent Guide for pokeemerald-expansion

Project Overview

pokeemerald-expansion is a comprehensive GBA ROM hack base for creating Pokémon ROM hacks, built on top of pret's pokeemerald decompilation project. It is not a playable game on its own but provides developers with a toolkit featuring hundreds of features from various core series Pokémon games.

  • Target Platform: Game Boy Advance (ARM7TDMI processor)
  • Primary Language: C (C17 standard) with ARM assembly
  • Build System: GNU Make with devkitARM toolchain
  • Repository: https://github.com/rh-hideout/pokeemerald-expansion
  • Community: ROM Hacking Hideout (RHH) Discord

Technology Stack

Compiler & Toolchain

  • Compiler: arm-none-eabi-gcc (devkitARM recommended)
  • Architecture: ARMv4T (ARM7TDMI)
  • ABI: APCS-GNU
  • Optimization: -O2 (default), -Og (debug), LTO supported for release

Build Tools (in tools/ directory)

Tool Purpose
gbagfx Convert PNG/PAL to GBA graphics formats (1bpp, 4bpp, 8bpp, gbapal)
mid2agb Convert MIDI files to GBA sound format
wav2agb Convert WAV files to GBA sound format
mapjson Process map data from JSON to assembly
jsonproc JSON preprocessor for data files
trainerproc Process trainer data from .party files
preproc Preprocessor with character map support
scaninc Dependency scanner for includes
ramscrgen Generate RAM linker script sections
gbafix Fix GBA ROM header
patchelf Patch ELF files for testing
compresSmol Compression tool for graphics

Testing Framework

  • Test Runner: Custom framework running on mGBA emulator
  • Test Location: test/ directory
  • Test Command: make check
  • Parallel Testing: Uses mgba-rom-test-hydra for multi-process test execution

Build Commands

Standard Builds

# Default build (produces pokeemerald.gba)
make

# Parallel build (recommended)
make -j$(nproc)

# Release build (optimized, NDEBUG enabled)
make release

# Debug build (with debug symbols, -Og optimization)
make debug

# Clean build artifacts
make clean

# Clean without cleaning tools
make tidy

Testing Commands

# Run all tests
make check

# Run specific test file
make check TESTS=test/pokemon.c

# Run tests matching pattern
make check TESTS="Pokemon*"

Game Variants

# Build for different games (though Emerald is the main target)
make emerald   # Default
make firered   # FireRed variant
make leafgreen # LeafGreen variant

Build Options

# Enable Link Time Optimization (set in config.mk)
make release

# Disable LTO
make RELEASE=1 LTO=0

# Keep intermediate files
make KEEP_TEMPS=1

# Static analysis
make ANALYZE=1

Code Organization

Directory Structure

├── src/                    # C source files (350+ files)
│   ├── data/              # Data definitions (moves, items, species, etc.)
│   └── ...                # Game logic organized by feature
├── include/               # Header files (280+ files)
│   ├── config/            # Configuration headers (19 config files)
│   └── constants/         # Constant definitions
├── asm/                   # Assembly files (mostly macros)
├── data/                  # Assembly data files, maps, scripts
│   ├── maps/             # Map data (520+ maps)
│   ├── layouts/          # Map layouts
│   └── scripts/          # Event scripts
├── graphics/              # Graphics assets (sprites, backgrounds, etc.)
├── sound/                 # Audio data and songs
├── test/                  # Test files
├── tools/                 # Build tools (C programs)
├── constants/             # Assembly constants
├── libagbsyscall/         # GBA system call library
├── docs/                  # Documentation
└── migration_scripts/     # Scripts for migrating from other versions

Key Source Directories

src/ - Main Source Code

Organized by functionality:

  • Battle System: battle_*.c files (battle logic, AI, animations, controllers)
  • Overworld: overworld.c, field_*.c (movement, effects, weather)
  • Pokémon: pokemon.c, evolution_scene.c, daycare.c
  • UI: menu.c, text.c, window.c, list_menu.c
  • Save/Load: save.c, load_save.c
  • Audio: sound.c, m4a.c, m4a_tables.c

include/config/ - Configuration Headers

Critical files for feature toggles:

  • general.h - General settings, generation constants (GEN_1 through GEN_9)
  • battle.h - Battle mechanics configuration
  • pokemon.h - Pokémon-related settings
  • overworld.h - Overworld feature toggles
  • debug.h - Debug menu settings
  • ai.h - Battle AI configuration

Coding Style Guidelines

Naming Conventions

Type Convention Example
Functions PascalCase void ProcessBattleActions(void)
Structs PascalCase struct BattlePokemon
Variables/Fields camelCase int currentHp
Global Variables g + PascalCase extern s32 gBattleMons
Static Variables s + PascalCase static u8 sMyCounter
Macros/Constants CAPS_WITH_UNDERSCORES #define MAX_LEVEL 100
Enums CAPS_WITH_UNDERSCORES enum Gimmick { GIMMICK_NONE, ... }

Code Formatting

  • Indentation: 4 spaces (no tabs for C/H files)
  • Assembly/Scripts: Use tabs
  • Braces: Opening brace on new line
  • Switch statements: Cases left-aligned with switch block
  • Comments:
    • Use // for single-line comments (capitalized, end with period)
    • Use /* */ for block comments explaining WHY, not WHAT

Example Code Style

void ProcessBattleActions(void)
{
    u32 i;
    
    for (i = 0; i < gBattlersCount; i++)
    {
        if (gBattleMons[i].hp == 0)
            continue;
        
        HandleTurnActionSelectionState(i);
    }
}

switch (gBattleTypeFlags)
{
case BATTLE_TYPE_TRAINER:
    SetTrainerBattleData();
    break;
case BATTLE_TYPE_WILD:
    SetWildBattleData();
    break;
}

Data Types

  • General numbers: Use u32 (unsigned) or s32 (signed)
  • Save block data: Use smallest possible type
  • EWRAM variables: Use smallest possible type
  • Booleans: Use bool8 or bool32 from types.h

Inline Configs

When adding configurable features, check configs within normal control flow:

// Correct
void SetDifficulty(u32 level)
{
    if (!B_VAR_DIFFICULTY)
        return;
    // ...
}

// Incorrect (using #ifdef)
#ifdef B_VAR_DIFFICULTY
    // This bypasses normal control flow
#endif

Testing System

Test Macros

Located in include/test/test.h:

TEST("My test name")
{
    // Test code here
    EXPECT(condition);
    EXPECT_EQ(a, b);
    EXPECT_NE(a, b);
    EXPECT_LT(a, b);
}

ASSUMPTIONS
{
    // Pre-test assumptions
    ASSUME(gSpeciesInfo[SPECIES_PIKACHU].baseHP > 0);
}

Test Features

  • PARAMETRIZE: Run test multiple times with different parameters
  • KNOWN_FAILING: Mark tests that are expected to fail
  • KNOWN_LEAKING: Mark tests with known memory leaks
  • BENCHMARK: Performance testing macros
  • SET_RNG: Control random number generation for reproducibility

Writing Tests

Tests go in test/ directory as .c files:

#include "global.h"
#include "test/test.h"
#include "battle_test.h"

TEST("Pokemon creation works")
{
    struct Pokemon mon;
    CreateMon(&mon, SPECIES_PIKACHU, 50, 0, FALSE, 0, OT_ID_RANDOM, 0);
    EXPECT_EQ(GetMonData(&mon, MON_DATA_LEVEL), 50);
}

Battle Tests

Special battle testing framework in test/test_runner_battle.c:

SINGLE_BATTLE_TEST("Thunderbolt deals damage")
{
    GIVEN {
        PLAYER(SPECIES_PIKACHU) { Moves(MOVE_THUNDERBOLT); }
        OPPONENT(SPECIES_CHARMANDER);
    } WHEN {
        TURN { MOVE(player, MOVE_THUNDERBOLT); }
    } SCENE {
        ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDERBOLT, player);
        HP_BAR(opponent);
    }
}

Configuration System

Generation Constants

In include/config/general.h:

#define GEN_1 0
#define GEN_2 1
#define GEN_3 2
#define GEN_4 3
#define GEN_5 4
#define GEN_6 5
#define GEN_7 6
#define GEN_8 7
#define GEN_9 8
#define GEN_LATEST GEN_9

Feature Configuration Pattern

Most features use config defines that can be set to specific generations:

// In include/config/battle.h
#define B_CRIT_CHANCE               GEN_7 // Gen7+ critical hit chance
#define B_EXP_CATCH                 GEN_7 // Gen7+ exp on catch
#define B_TRAINER_EXP_MULTIPLIER    GEN_7 // Gen7+ trainer EXP multiplier

Boolean Configs

#define B_FLAG_FORCE_SHINY      0     // If set, all wild Pokémon are shiny
#define B_FLAG_NO_WILD_ENCOUNTERS 0   // If set, disables wild encounters

Important Files and Locations

Entry Points

  • src/main.c - Main entry point (AgbMain function)
  • src/crt0.s - C runtime initialization (assembly)
  • ld_script_modern.ld - Linker script defining memory layout

Key Data Files

  • src/data/moves_info.h - Move definitions
  • src/data/items.h - Item definitions
  • src/data/species/ - Pokémon species data (split across multiple files)
  • src/data/trainers.h - Trainer definitions
  • src/data/wild_encounters.json - Wild encounter data (processed to .h)

Graphics Processing

  • graphics_file_rules.mk - Rules for converting PNG to GBA formats
  • Graphics converted automatically during build:
    • .png.4bpp (4-bit per pixel tiles)
    • .png.8bpp (8-bit per pixel tiles)
    • .pal.gbapal (palette files)

String/Text

  • src/strings.c - In-game text strings
  • charmap.txt - Character encoding map for preprocessor

Development Workflow

Branches

  • master - Stable branch with bugfixes
  • upcoming - Development branch for new features
  • expansion/X.Y.Z - Specific version tags

Contributing Workflow

  1. Create feature branch from upcoming (or master for bugfixes)
  2. Make changes following style guide
  3. Ensure tests pass: make check
  4. Submit PR to appropriate branch

Migration from pret/pokeemerald

git remote add RHH https://github.com/rh-hideout/pokeemerald-expansion
git pull RHH master  # or upcoming

Memory Layout

Defined in ld_script_modern.ld:

  • EWRAM: 0x2000000 - 0x2040000 (256 KB, external work RAM)
  • IWRAM: 0x3000000 - 0x3008000 (32 KB, internal work RAM, faster)
  • ROM: 0x8000000 - 0x8200000 (32 MB maximum)

Variable Placement

// External work RAM (slower, larger)
EWRAM_DATA u32 gLargeArray[1000];

// Internal work RAM (faster, limited)
IWRAM_DATA u32 gFastVariable;

// Common data (preserved across soft reset)
COMMON_DATA u32 gPersistentData;

Security Considerations

Save File Safety

  • New features that modify save structures must be gated behind configs
  • Default configs should not break existing saves
  • Test save compatibility when modifying save-related code

Buffer Safety

  • Use sized string functions when available
  • Be cautious with VarGet() and script buffers
  • Validate array bounds, especially with user-controlled values

Useful Resources

Common Issues

  1. "arm-none-eabi-gcc: command not found": Install devkitARM and ensure it's in PATH
  2. Tools not building: Run make tools explicitly first
  3. Clean build recommended after config changes: make clean && make
  4. PNG conversion errors: Ensure libpng is installed and PNG files are valid