uxie 0.1.0

Data fetching library for Pokemon Gen 4 romhacking - map headers, C parsing, and more
Documentation

uxie

A data fetching library for Pokemon Gen 4 romhacking. Provides unified access to ROM data from DSPRE projects and decompilation sources.

Table of Contents

Background

Working with Pokemon Gen 4 ROMs involves multiple data sources: binary files extracted via ndstool or ds-rom, DSPRE projects (folders containing arm9.bin and unpacked/ filesystem), and modern JSON/C source structures from decompilation projects (pokeplatinum/pokeheartgold). Each source has different formats and conventions.

uxie provides a unified interface for reading ROM data regardless of source. Its RomHeader::open() function auto-detects the format and returns a consistent struct. The library also includes utilities for reading map headers, parsing C enums and defines, and querying relationships between game data.

Etymology

uxie takes its name from Uxie, the legendary Pokemon known as the "Being of Knowledge."

Features

  • Smart Discovery: Automatically detects game version, internal project names, and table offsets. No manual configuration required for standard projects.
  • Unified ROM Access: Auto-detects and reads data from DSPRE projects and decompilation sources.
  • High-Level Workspace: Unified API for managing symbols, script mappings, and text banks across a project
  • Complex Expression Resolution: Evaluates C expressions in #define and enum blocks, including bitwise OR (|), left shifts (<<), and nested parentheses.
  • Enhanced Symbol Table: Automatically resolves cross-references between constants and supports .txt files with incremental indexing.
  • Map Header Parsing: Unified access to area data, scripts, and events across all Gen 4 games.
  • Format Agnostic: Seamlessly bridge legacy binary formats and modern JSON/YAML source data.
  • Bidirectional Script Resolution: Resolve script constants from names to values AND values to names using a shortest-name heuristic.

Install

Build from Source

git clone https://github.com/KalaayPT/uxie.git
cd uxie
cargo build --release

The binary will be at target/release/uxie. Verify installation:

./target/release/uxie --version

As a Library

Add to your Cargo.toml:

[dependencies]
uxie = { git = "https://github.com/KalaayPT/uxie.git", branch = "mother" }

CLI Usage

The Being of Knowledge offers several ways to query the secrets of the Sinnoh and Johto regions.

Common Flags

Most commands (map, event, encounter, resolve-script) share these common options:

  • --project, -p: Path to the project root (defaults to current directory).
  • --decomp, -d: Optional local path OR GitHub raw URL (e.g., https://raw.githubusercontent.com/pret/pokeplatinum/master/) for symbol resolution.
  • --json: Output the result as a structured JSON object.

header

Read ROM header information. Auto-detects format from a file path or project directory:

# From current directory
uxie header

# From a specific ROM file or header.bin
uxie header path/to/header.bin

# Output as JSON
uxie header --json

map

Read map header data, including internal and pretty names.

# Read map header ID 0 from current project
uxie map 0

# Read from DSPRE project but resolve symbols using a remote decomp
uxie map 3 -p /path/to/dspre/ -d https://raw.githubusercontent.com/pret/pokeplatinum/master/

Example Output:

Map Header 0 (Platinum)
Internal Name:   D21R0101
Pretty Name:     Twinleaf Town
=========================
Area Data ID:    0
Matrix ID:       0
Script File ID:  0
...

event & encounter

Load and resolve event or encounter data:

# Resolve events for map 3
uxie event 3

# Fetch encounters for map 100 in JSON format
uxie encounter 100 --json

symbols

Parse C header files or symbol list files:

# Parse and resolve complex expressions
uxie symbols constants.h

# Parse a .txt list with incremental indexing
uxie symbols variables.txt

# Output only enums as JSON
uxie symbols constants.h --only-enums --json

resolve-script (untested)

Bidirectionally resolve constants within a script file (Names -> Values AND Values -> Names):

# Resolve using a specific decomp root (optional)
uxie resolve-script game_script.s --decomp /path/to/pokeplatinum/

Integration

uxie is designed to bridge the gap between different toolchains in the Gen 4 romhacking ecosystem:

  • Universal Symbols: Bridges C headers, assembly constants, and binary offsets into a single, searchable namespace.
  • Text & Archives: Seamlessly maps text archive IDs to their symbolic names and content, linking binary data to human-readable strings.
  • Format Fluidity: Provides a unified bridge between legacy binary formats (NARC, arm9.bin) and modern source-controlled data (JSON, YAML, C).
  • Toolchain Agnostic: Handles both legacy binary projects and modern decompilation trees transparently, allowing your tools to work anywhere knowledge is stored.

Library Usage

High-Level Workspace

The Workspace struct is the primary entry point. It automatically detects the project type (DSPRE or Decompilation) and sets up the environment.

use uxie::Workspace;

// Auto-detect and load from any supported project path
let workspace = Workspace::open("path/to/project")?;

// Resolve a constant name to its value
let val = workspace.resolve_constant("VARS_START"); // Some(16384)

// Bidirectional resolution: Names -> Values AND Values -> Names
let script = "SetFlag FLAG_UNK_0x000A";
let resolved = workspace.resolve_script_symbols(script);
println!("{}", resolved); // "SetFlag 10"

let binary_script = "SetFlag 10";
let symbolic = workspace.resolve_script_symbols(binary_script);
println!("{}", symbolic); // "SetFlag FLAG_UNK_0x000A" (shortest name heuristic)

Reading ROM Headers

use uxie::RomHeader;

// Auto-detect format from path
let header = RomHeader::open("path/to/header.bin")?;
let header = RomHeader::open("path/to/dspre-project/")?;

// Access header data
println!("Game: {:?}", header.detect_game());       // Some(Platinum)
println!("Family: {:?}", header.detect_game_family()); // Some(Platinum)
println!("Region: {:?}", header.region());          // Some("USA")

Reading Map Headers

use uxie::{Arm9Provider, GameFamily};

// Low-level provider access
let provider = Arm9Provider::new(
    "path/to/arm9.bin",
    0xE601C,  // Table offset
    559,      // Count
    GameFamily::Platinum,
);

let header = provider.get_map_header(0)?;
println!("Script file: {}", header.script_file_id());

Working with DSPRE Projects

use uxie::Workspace;

// Workspace handles DSPRE projects transparently
let workspace = Workspace::open("path/to/dspre-project")?;

println!("Project Type: {:?}", workspace.project_type); // Dspre
println!("Detected Game: {:?}", workspace.game);

Parsing C Headers

For complex projects, use SymbolTable to load multiple headers and resolve cross-references:

use uxie::SymbolTable;

let mut symbols = SymbolTable::new();

// Load all headers from a directory (handles .h, .hpp, and .txt)
symbols.load_headers_from_dir("include/constants")?;

// Resolve a constant from any of the loaded files
if let Some(val) = symbols.resolve_constant("ITEM_POKE_BALL") {
    println!("ID: {}", val);
}

You can also use the low-level parsing functions for single files:

use uxie::c_parser::{parse_enum, parse_and_resolve_defines};

let content = std::fs::read_to_string("header.h")?;

// Parse enums
if let Some(e) = parse_enum(&content) {
    for variant in &e.variants {
        println!("{} = {:?}", variant.name, variant.value);
    }
}

// Parse and resolve defines
let defines = parse_and_resolve_defines(&content);
for d in &defines {
    if let Some(resolved) = d.resolved {
        println!("#define {} {} (= {})", d.name, d.value, resolved);
    }
}

Supported Games

Game Code Family
Diamond ADAE (US), ADAJ (JP), ADAP (EU) DP
Pearl APAE (US), APAJ (JP), APAP (EU) DP
Platinum CPUE (US), CPUJ (JP), CPUP (EU) Platinum
HeartGold IPKE (US), IPKJ (JP), IPKP (EU) HGSS
SoulSilver IPGE (US), IPGJ (JP), IPGP (EU) HGSS

License

uxie is free software licensed under the MIT License. See LICENSE for details.