用Kimi Code生成了AGENTS.md
This commit is contained in:
parent
fda85b5858
commit
22856a2941
400
AGENTS.md
Normal file
400
AGENTS.md
Normal file
@ -0,0 +1,400 @@
|
|||||||
|
# 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](https://github.com/pret/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
|
||||||
|
```bash
|
||||||
|
# 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
|
||||||
|
```bash
|
||||||
|
# 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
|
||||||
|
```bash
|
||||||
|
# Build for different games (though Emerald is the main target)
|
||||||
|
make emerald # Default
|
||||||
|
make firered # FireRed variant
|
||||||
|
make leafgreen # LeafGreen variant
|
||||||
|
```
|
||||||
|
|
||||||
|
### Build Options
|
||||||
|
```bash
|
||||||
|
# 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
|
||||||
|
```c
|
||||||
|
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:
|
||||||
|
```c
|
||||||
|
// 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`:
|
||||||
|
|
||||||
|
```c
|
||||||
|
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:
|
||||||
|
```c
|
||||||
|
#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`:
|
||||||
|
```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`:
|
||||||
|
```c
|
||||||
|
#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:
|
||||||
|
```c
|
||||||
|
// 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
|
||||||
|
```c
|
||||||
|
#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
|
||||||
|
```bash
|
||||||
|
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
|
||||||
|
```c
|
||||||
|
// 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
|
||||||
|
|
||||||
|
- **Documentation**: https://rh-hideout.github.io/pokeemerald-expansion/
|
||||||
|
- **Discord**: https://discord.gg/6CzjAG6GZk (RHH Server)
|
||||||
|
- ** pret/pokeemerald**: https://github.com/pret/pokeemerald (upstream)
|
||||||
|
- **Related Tools**:
|
||||||
|
- [porymap](https://github.com/huderlem/porymap) - Map editor
|
||||||
|
- [poryscript](https://github.com/huderlem/poryscript) - Scripting language
|
||||||
|
- [porytiles](https://github.com/grunt-lucas/porytiles) - Tileset tool
|
||||||
|
|
||||||
|
## 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
|
||||||
Loading…
x
Reference in New Issue
Block a user