Curated game-data tables
Every fan who has played Legaia with a GameFAQs guide open knows these numbers: what Tornado Flame costs in AP, what the Rim Elm shop sells, what a Gimard drops. The project keeps a typed copy of those numbers - arts, magic, items, equipment, enemies, shops, casino, fishing - mined from public walkthroughs. When a record comes off the disc as anonymous bytes, these tables are the labels it is checked against; where the two disagree, the disc wins.
At a glance
- Where
- TOML tables under
data/gamedata/(committed; no Sony bytes) - Crate
crates/gamedata(legaia_gamedata::Database) + thegamedata-toolCLI; needs no disc- Sources
- Three GameFAQs walkthroughs (factual columns only) + Stann0x's music table
- Confidence
- Disc-checked wherever a disc record exists: prices, equip slots, accessory passives, enemy stats, spells, shop stock, casino prizes
- Rendered on
- Arts, Magic, Shops, Monsters, Music tracks
Why this exists
Reverse engineering yields raw records - an art's direction bytes, a spell's MP cost, a monster's stat block - but no names and no second source to check the numbers against. The curated tables supply both.
- Art records parsed from the disc get a name and a retail AP cost to check against.
- Item ids seen in cheat codes and inventory bytes resolve to display names.
- Spell records link to MP / element / target; monster records to location and drop tables.
- Boss stat blocks bracket the damage-formula work: predicted hits-to-kill must land inside the guide's numbers.
Source attribution
| Source | Supplies |
|---|---|
| Tan Yong Hua, Legend of Legaia Walkthrough v6.6 (1999) | Gap-filling; boss-HP estimates from its Master Course commentary |
| Psycho Penguin (mcfaddendaman), Legend of Legaia Walkthrough (2001) | Primary item / art / shop columns; the drop / steal table (PSM Magazine attribution) |
| Meth962, Legend of Legaia 100% Walkthrough v1.11 (FAQ 53721) | Per-enemy stat columns (from RAM dumps, so they outrank the others), boss movesets and rewards, Seru absorb rates, magic-levelling tables |
| Stann0x | The music table, contributed directly - see music tracks |
Only factual columns are committed - names, prices, command sequences, MP costs, locations, drop tables. Guide prose is copyrightable and is never reproduced; Sony-owned bytes stay out of the repo entirely.
Where the data lives
| File | Contents |
|---|---|
| arts.toml | Per-character arts: regular / hyper / super / miracle |
| magic.toml | 21 Seru spells + 8 Ra-Seru summons |
| items.toml | Consumables, key items, art books, fishing tackle |
| weapons.toml | 27 weapons |
| armor.toml | 51 entries: body 20, head 15, footwear 16 |
| accessories.toml | 77 accessories with structured effect classes |
| enemies.toml | 177 enemies: location, drop / steal, steal_chance (byte-exact from the SCUS steal table), full stat columns |
| bosses.toml | 22 main-story boss rows over 20 ids (the three Delilas share one) + Lapis + 7 Muscle Dome rounds: attacks, rewards, recommended level |
| shops.toml | Per-town shop inventories by item key |
| casino.toml | Sol / Vidna prize counters, Muscle Dome courses, Baka Fighter |
| sol_tower.toml | Sol Tower floor map + side-quest chains |
| fishing.toml | Vidna / Buma fishing prizes |
| characters.toml | Vahn / Noa / Gala affinities and weapon classes |
| music.toml | 81-track BGM disambiguation (Stann0x) |
| README.md | Source attribution + cross-validation rules |
Implementation: crates/gamedata.
Schema · Arts
Each art carries a player-facing command (tokens Arms / Ra-Seru / High / Low) and a directions array of raw direction bytes - the prefix that appears in the on-disc art record. The mapping is per character because Noa is left-handed.
| Token | Vahn / Gala | Noa |
|---|---|---|
Arms | L = 1 | R = 2 |
Ra-Seru | R = 2 | L = 1 |
High | U = 4 | U = 4 |
Low | D = 3 | D = 3 |
The action_constant field (0x1B..=0x32) joins the per-character art-name table in crates/art.
Schema · Magic
21 Seru spells and 8 Ra-Seru summons. element is one of eight lowercase values (fire … evil); target is single_enemy, all_enemies, single_ally, all_allies or self. Seru spells also carry absorb_lv1..3 - the percent chance a kill captures the Lv1 / Lv2 / Lv3 mist variant (Gimard 55/60/80, Gilium 1/1/1). Summons are egg-derived and have no absorb rate.
Magic levelling
legaia_gamedata::magic_leveling | Meaning |
|---|---|
XP_TO_LEVEL | 18, 51, 93, 145, 209, 289, 393, 537 - cumulative cost Lv2 → Lv9 |
SCALING_BP | Damage / heal multiplier in basis points: Lv1 = 10000, Lv9 = 20000 |
VERA_HEAL / ORB_HEAL / SPOON_HEAL | Per-level healer output (Vera 256-512, Orb 512-1024 AoE, Spoon 1024-2048 AoE) |
NIGHTO_HIT_PCT | Nighto's Confuse / Death base hit chance per level (fixed 8:1 split) |
xp_single_target / xp_multi_target | Damage-as-fraction-of-HP → XP award (0..=12 single, 0..=4 per enemy multi) |
Schema · Items, weapons, armor, accessories
Every row carries a stable snake_case key that the shop, casino, fishing and enemy tables reference. accessories.toml adds an effect_class (hp_max_pct, ap_accrual_pct, revive_once, elemental_def, …) - a structured re-encoding of the guide's effect text for the engine to dispatch on, and the field the disc's accessory passive index is checked against.
Schema · Enemies
Per enemy: name, location, optional element and boss, optional drop / steal keys, steal_chance, and the stat columns HP / MP / EXP / Gold / ATK / SPD / UDF / LDF / INT / AGL. The stats are the in-battle values the player fights, not the raw disc record - see cross-validation.
Schema · Shops
One [[shop]] per merchant, inventory as item keys. gamedata-tool shop <town> joins the keys against the four item tables and prints a priced inventory.
Schema · Casino + Muscle Dome
| Table | Holds |
|---|---|
[[slot_prize]] | Vidna casino counter and the Sol Tower F4 prize counter (location = "Sol"). Slot machines themselves only pay coins. |
[[muscle_dome_course]] | Beginner / Expert / Master: entry fee, clear reward, restrictions / allowed gating, encounter-order roster. Master's first-clear reward (War God Icon) requires Jette defeated in Absolute Fortress. |
[[muscle_dome_round]] | Normalised (course_key, round, boss_key, seru_level) rows: 8 for Beginner and Expert, 13 for Master |
[[muscle_dome_boss]] | Full per-enemy stat block, drop / steal with chances, attack list, immunities, element and weakness arrays, wiki_path provenance. Seru entries nest Lv1-3 stats as [[muscle_dome_boss.seru_level]]. |
[baka_fighter_meta] / [[baka_fighter]] | All-rounds-clear reward (460 coins), rule sketch, per-round button sequences |
[[muscle_paradise_secret]] | The Chicken King easter egg (run from the first battle in all three difficulties) |
Schema · Sol Tower
sol_tower.toml is location-scoped: a per-floor map ([[floor]] with named sections) and side-quest chains ([[side_quest]] with ordered steps and reward pointers). scene_label = "town0d" ties it to the scene name map and the field-VM bundle.
Cross-validation
Disc-free rules run with cargo test -p legaia-gamedata; the disc-gated joins skip without extracted/SCUS_942.54. The disc is the tie-breaker.
Disc-free rules
- Every art's
action_constantresolves to a name incrates/art; its direction bytes are in1..=4and equal the per-character mapping of its command tokens. - AP costs match kind: regulars ≤ 36, hypers 30-70, supers 48-72, miracles 99; one Miracle Art per character.
- Magic has exactly 21 Seru + 8 Ra-Seru rows; every element is canonical.
- Every shop / prize / fishing / Muscle Dome / drop / steal key resolves to an item row.
- Armor
slot∈ {armor, helmet, shoes};equip∈ {Vahn, Noa, Gala, None}; itemcategory∈ {consumable, permanent_stat, key, art_book, fishing_lure}.
Disc-gated joins
| Test | Joins | Result |
|---|---|---|
item_prices_vs_disc | Curated price vs the SCUS item record's u16 at +2 | Zero mismatches |
equip_slots_vs_disc | The equip table's four slot categories vs body / head / footwear / weapon | Name-exact; accessories absent from that table, as expected |
accessory_passives_vs_disc | effect_class vs the 64-slot passive index (descriptor +3) | 72 of 73 name-join; zero mismatches (gap: "Light Ra-Seru Egg" vs disc "Light Egg") |
enemy_stats_vs_disc | Stat columns vs the monster archive (PROT 0867), through the battle-load stat boost | All nine fields across 120+ enemies (±1 on fractional factors) |
magic_vs_disc | MP cost and target vs the SCUS spell table | 21 Seru + 7 of 8 summons byte-exact (Juggernaut is outside the named region; Horn's target byte is enemy-side by design) |
shop_inventory_vs_disc | Inline MAN stock records vs curated shops, by item-name set | Every disc shop matches; disc-only Soru's Bakery is asserted explicitly |
casino_prizes_vs_disc | The PROT 0899 prize-exchange blocks vs curated prizes, on (name, coin price) | Byte-exact both ways; Earth Egg @ 100000 is a separate hidden exchange |
The enemy join is the one with a twist: the curated stats are what the player fights, and retail boosts the disc record at battle load - UDF / LDF ×2, ATK ×5/4, INT ×9/8, HP / SPD / AGL unchanged - and scales rewards separately (EXP ×3/4, gold ×5/16). This international-vs-raw difficulty difference was first surfaced by Zetopheonix; the loader is on the battle page.
Where the disc overrides the walkthroughs
Forest / Magic Amulet cost 2000 (guides: 4000); Evil Medallion 9999 (guides: 9998); Mushura's Crazy Driver targets a single enemy (guides: all); the Gala helmet is spelled "Power Earring", singular. The casino prize layout is 8-byte records [u16 item_id][u16 story_gate][u32 coin_price] in 0x60-byte blocks - block 1 Vidna, block 0 the Muscle Dome counter, blocks 2 / 3 short pre-progression states.
Library API
use legaia_gamedata::{Database, Character};
let db = Database::load();
for art in db.arts_for(Character::Vahn) {
println!("{:?} {:>3} AP {}", art.kind, art.ap, art.name);
}
let art = db.find_art_by_directions(Character::Vahn, &[1, 2, 4]).unwrap(); // Hyper Elbow
let ap = db.ap_cost_for_action(Character::Gala, 0x1B).unwrap(); // 99, Biron Rage
for entry in db.shop_inventory("Rim Elm", "Variety Shop").unwrap() {
println!(" {:>20} {:>5}G", entry.name, entry.price.unwrap_or(0));
}
CLI
gamedata-tool list arts --character Noagamedata-tool list magic --element lightgamedata-tool find "Tornado Flame"gamedata-tool arts-by-command Vahn "Arms,Ra-Seru,High"gamedata-tool shop "Sol"gamedata-tool dump-json arts > arts.jsonFrom source: cargo run -p legaia-gamedata --bin gamedata-tool -- <subcommand>.
How this helps the reverse engineering
| Curated table | Grounds |
|---|---|
| Arts | Names for the command-byte sequences crates/art parses from the art records |
| Magic | MP costs, elements and names for the spell-table offsets the damage / MP-cost formulas read |
| Item keys | Stable identifiers, so a disc byte-id is one extra column rather than churn across consumers |
| Enemy + boss stats | Hits-to-kill predictions from the formulas must match Meth's blocks (Jette: HP 34,567 / ATK 277 / UDF 412 / SPD 274) |
| Seru absorb rates | The engine's capture roll (engine-core::seru_learning) reads Spell::absorb_lv1..3 |
| Magic XP curve | Per-cast levelling: xp_*_target award, XP_TO_LEVEL bump, SCALING_BP on the next cast |
How we know
| Function / table | Address | What it proves |
|---|---|---|
| Battle-load stat boost | FUN_80054CB0 | The ×2 / ×5/4 / ×9/8 factors between the disc record and the curated in-battle stats |
| Victory-spoils scaling | FUN_8004E568 | EXP ×3/4, gold ×5/16 |
| Ability bitfield writer | FUN_80042558 | Accessory passive index → bit in char+0xF4 |
| Steal table | DAT_80077828 | steal_chance column is byte-exact |
| Art records | PROT 0x05C4; runtime tables 0x80160EFC / 0x80176998 / 0x8018BA54 | Direction-byte prefix the directions array mirrors |
| Shop stock records | scene MAN op 0x49 sub-op 0 (legaia_asset::shop_stock) | Per-shop inventory join |
| Casino exchange | PROT 0899 (legaia_patcher::casino::CasinoExchange) | Prize-counter join |