Art Data - Tactical Arts records Inferred
Tap the right d-pad sequence in battle and your character performs a Tactical Art. These records are the data behind that system: for Vahn, Noa and Gala, one record per art holding the input combo, the per-strike damage tiers, the animation and the hit cues. A Miracle Art is a secret input that replaces the whole action queue; a Super Art is a find-and-replace over the queue's tail.
At a glance
- Where
record[0]of each player battle file (PROT 0863 Vahn / 0864 Noa / 0865 Gala), resident in RAM at0x80160EFC/0x80176998/0x8018BA54. Display names, arrows and AP: the SCUS arts-name table atDAT_80075EC4.- Stride
0xD0bytes per record, indexed by action constant:record = base + (c − 0x10) × 0xD0. Name-table rows are 20 bytes.- Parser
crates/art(parse_record,arts_table,tokenize, Miracle / Super matchers); editorslegaia_patcher::arts_power/super_art_power.- Confidence
- Command prefix, stride, power byte at
+0x24, effect class at+0x7Aand the name table are Confirmed; the variable-field tail offsets are Inferred from external RE work. - Used by
- Battle action SM, Arts gauge, Arts page, Randomizer (arts shuffle).
The matcher - what fires an art - reads the player-file record's command bytes. The menu draws its arrows from the SCUS name table. Editing one without the other makes the menu lie: the art still fires on the old combo. The arts randomizer edits both.
Art record layout
0x24-byte matcher head is followed by a standard battle action entry (see player files § battle animations).| Offset | Size | Field | Meaning |
|---|---|---|---|
+0x00 | u8[] | command sequence | 1=L 2=R 3=D 4=U, 0-terminated. A Super Art record's field is a one-byte stub (no combo). |
| after | u8 | action constant | 0x1B..=0x32 (below). |
| after | u8 + u8[5] | anim_index, anim_extra | Primary animation slot; extras chain multi-stage arts (Noa's Hurricane Kick). |
+0x10 | 20 | name | Fixed-width name slot; populated for Super, Miracle and some Hyper Arts. |
+0x24 | u8[1..4] | power run | Per-strike damage tier bytes (encoding). Confirmed; editor legaia_patcher::arts_power. |
+0x7A | u8 | impact-effect class | 1..=5, 0 = none. Selects the element spark and afterimage tint - this byte, not the cue script, makes an art read as its element. |
Variable-field tail (Inferred positions)
| Field | Encoding |
|---|---|
| Damage timing (×4) | One byte per power byte: the animation frame at which that hit fires. |
| Special effect cues (×2) | 2 words each: half-word effect id, then XYZ half-words. Active iff non-zero. |
| Hit effect cues (×4) | One word each: high half = frame, low half = cue code. |
| Identifier | Byte; some values trigger special animations (0x67 in Heaven's Drop = Thunderbolt). |
| Anim speed | Byte; lower = slower. |
| Effect on enemy | 1 Toxic, 2 Numb, 3 Venom, 4 Sleep, 5 Confuse, 6 Curse, 7 Stone, 8 Faint. |
| Repeat frames | 3 bytes: count, start, end. Replays a frame range and any hits inside it (Super Tempest: 4 power bytes, 8 hits). |
| Background | 0 regular, 2 black (Super Arts, Tornado Flame). |
| Runtime address | Word written after first use; always zero on disc. |
The runtime hit run the per-frame cue player walks sits at record + 0x14 + cursor × 8 (8-byte entries: timing, cue code, XYZ). Cue-code high bit = spawn an efect.dat billboard; a plain code selects a 3D move-VM prototype. Target-group codes: < 8 one actor, 8 the party, 9 the enemy row, 0xA everyone.
Power encoding
Each power byte names a defence target and a multiplier. Retail authors the run ascending; weak arts carry one byte, Hyper and Super Arts four.
| Byte range | Target | Multipliers | Note |
|---|---|---|---|
0x16-0x1A | UDF (upper defence) | 12, 18, 20, 22, 28 | Standard high hit. |
0x1B-0x1F | LDF (lower defence) | 12, 18, 20, 22, 28 | Standard low hit. |
0x0C-0x10 | UDF | same | Misses short enemies. |
0x11-0x15 | LDF | same | Misses floating enemies. |
| other | - | - | No damage. |
Indexed by action constant, not by combo
- Constants
0x19/0x1A(the two Art Starters) land on the two "Starter" records,0x1Bon the Miracle Art, regular arts at0x1B + display index. - Super Art finishers have records too -
0x2B..0x2F(Vahn, Gala),0x2E..0x32(Noa) - with real power tiers, so Super damage is ordinary record data. - Some records are reachable by neither route (Vahn's and Gala's
0x2A, Noa's0x2C/0x2D): named, powered, but no menu row and no combo.
Action constants
Every entry in the battle action queue is one of these bytes:
| Byte | Meaning |
|---|---|
0x00-0x05 | Nothing, Item, Magic, Attack, Spirit, Escape |
0x07 / 0x08 | Faint animations 1 / 2 |
0x0A / 0x0B | Item-or-magic animation / block animation |
0x0C-0x0F | Left, Right, Down, Up |
0x10 | Spirit animation |
0x11-0x18 | Empty slots (never in static data) |
0x19 / 0x1A | Regular / Special Art Starter |
0x1B-0x32 | Per-character arts - the same constant is a different art per character (crates/art/src/tables.rs) |
Learned-art slots and animation slots per character
A per-character byte (0x8008488D Vahn, 0x80084CA1 Noa, 0x8008506C Gala) tracks the highest learned slot; slots resolve to constants through a table with holes (Noa skips 0x02/0x03 because one learned slot covers all three Hurricane Kick levels). API: legaia_art::learned_art_action(character, slot).
| Slot | Vahn | Noa | Gala |
|---|---|---|---|
0x00 | Vahn's Craze | Noa's Ark | Biron Rage |
0x01 | Burning Flare | Hurricane Kick | Explosive Fist |
0x02 | Fire Blow | - | Lightning Storm |
0x03 | Tornado Flame | - | Thunder Punch |
0x04 | Cyclone | Vulture Blade | Bull Horns |
0x05 | Hurricane | Frost Breath | Electro Thrash |
0x06 | PK Combo | Tempest Break | Neo Raising |
0x07 | Spin Combo | Rushing Gale | Black Rain |
0x08 | Pyro Pummel | Tough Love | Side Kick |
0x09 | Cross-Kick | Swan Driver | Head-Splitter |
0x0A | Power Punch | Bird Step | Guillotine |
0x0B | Slash Kick | Dolphin Attack | Back Punch |
0x0C | Somersault | Mirage Lancer | Ironhead |
0x0D | Charging Scorch | Blizzard Bash | Battering Ram |
0x0E | Hyper Elbow | Sonic Javelin | Flying Knee Attack |
0x0F | - | Acrobatic Blitz | - |
0x10 | - | Lizard Tail | - |
Slot constants run 0x1B + slot. The record's anim_index indexes a separate per-character animation table (slot 0 = Spirit, 3 = Art Starter, with holes); API legaia_art::art_anim_name(character, anim_index).
| Anim | Vahn | Noa | Gala |
|---|---|---|---|
0x01 | Power Punch | Tempest Break | Bull Horns |
0x02 | Slash Kick | Tough Love | Head-Splitter |
0x04 | Tornado Flame | Hurricane Kick 1 | Lightning Storm |
0x05 | Hurricane | Hurricane Kick 2 | Back Punch |
0x06 | Charging Scorch | Rushing Gale | Ironhead |
0x07 | PK Combo | Swan Driver | Battering Ram |
0x08 | Fire Blow | Frost Breath | Flying Knee Attack |
0x09 | Somersault | Lizard Tail | - |
0x0A | Cyclone | Jurassic Blow 2 | Thunder Punch |
0x0B | Hyper Elbow | Bird Step | Guillotine |
0x0C | - | Dolphin Attack | Explosive Fist |
0x0D | Burning Flare | Vulture Blade | Black Rain |
0x0E | Spin Combo | Mirage Lancer | - |
0x0F | Pyro Pummel | Blizzard Bash | - |
0x10 | Cross-Kick | Sonic Javelin | Side Kick |
0x11 | Acrobatic Blitz | Electro Thrash | - |
0x12 | - | - | Neo Raising |
Miracle Arts
Each character has one. When the exact sequence is entered, the runtime clears the whole action queue and writes the art's replacement string: four directionals, the Special Starter, then the finisher constants. On disc the four directionals carry the high bit (0x8C..0x8F); the copy masks them to 0x0C..0x0F.
| Character | Art | Input |
|---|---|---|
| Vahn | Vahn's Craze | R D L U L U R D L |
| Noa | Noa's Ark | L U R D U L U D R |
| Gala | Biron Rage | R R D U D U D L L |
Super Arts
A Super Art is never matched against the raw input. The game first tokenizes the arrows into arts, then looks for a registered Find pattern at the tail of the queue and replaces it with the Super's finisher.
↑↓↑↑↑↓↑.pad
2tokenizeTail-first: each matched art overwrites its last arrow with a Starter (0x19) and inserts its constant; leading arrows stay, so one arrow can belong to two arts. Restarts after every match.legaia_art::tokenize
3queue19 27 0F 19 1F 0E 19 27 - Somersault, Cyclone, Somersault overlapping.actor[+0x1DF]
4Find at tailThe pattern must end the queue and every chain art must have paid its AP.table 0x801F6524
5Replace19 27 0F 19 1F 0E 1A 2B 2B 2B - Special Starter + Tri-Somersault × 3 hits. The Super charges no AP of its own.table 0x801F65E8
Because the Find pattern is what the physical input tokenizes to, laying the chain arts end to end does not trigger it. Every retail Super derives to a unique shortest input; fourteen of fifteen agree with the public walkthrough table (Dragon Fangs' printed six-arrow input drops one arrow and never performs Swan Driver).
| Character | Super Art | Chain | Input | AP |
|---|---|---|---|---|
| Vahn | Tri-Somersault | Somersault, Cyclone, Somersault | ↑↓↑↑↑↓↑ | 60 |
| Vahn | Maximum Blow | Charging Scorch, Slash Kick, Power Punch | ↓→↑↓←←↓ | 54 |
| Vahn | Fire Tackle | Hyper Elbow, Power Punch, Charging Scorch | ←→←←↓→↑ | 54 |
| Vahn | Power Slash | Charging Scorch, Somersault, Slash Kick | ↓→↑↓↑↓← | 54 |
| Vahn | Rolling Combo | Spin Combo, Power Punch, PK Combo | ↑↓→←←↓↑↑← | 66 |
| Noa | Triple Lizard | Bird Step, Swan Driver, Lizard Tail | ↓↓↓↑↑↑↓↑ | 66 |
| Noa | Super Javelin | Rushing Gale, Sonic Javelin | ↑↑←↓→↓→ | 48 |
| Noa | Super Tempest | Dolphin Attack, Tempest Break | →→←→→←↑↑↑ | 60 |
| Noa | Love You | Mirage Lancer, Lizard Tail, Tough Love | →→↑↑↓↑↓←→ | 72 |
| Noa | Dragon Fangs | Lizard Tail, Swan Driver, Acrobatic Blitz | ↑↓↑↑↑↓↓ | 60 |
| Gala | Back Punch x3 | Ironhead, Flying Knee Attack, Back Punch | ↑↓↓↑←→← | 54 |
| Gala | Super Ironhead | Flying Knee Attack, Head-Splitter, Ironhead | ↓↑←↑↑↓↓ | 54 |
| Gala | Rushing Crush | Battering Ram, Flying Knee Attack, Head-Splitter | ←→↓↑←↑↑ | 54 |
| Gala | Heaven's Drop | Flying Knee Attack, Head-Splitter, Black Rain | ↓↑←↑↑←↓↓ | 60 |
| Gala | Neo Static Raising | Back Punch, Guillotine, Neo Raising | ←→←↑←←→↑← | 66 |
Tables: crates/art/src/super_art.rs, miracle.rs.
Arts-name table (SCUS)
Display names, arrows and AP costs live in a static 20-byte-stride table in SCUS_942.54, sorted by character and terminated by a (99, 99) "End" row. Each character's index 0 is the Miracle Art (AP byte 99). This is also the table the MES 0xC5 substitution reads.
| Offset | Type | Field |
|---|---|---|
+0 | u8 | character: 0 Vahn, 1 Noa, 2 Gala |
+1 | u8 | art display index |
+2 | u8 | AP cost - a display mirror; the battle path computes multiplier × command count from code immediates and retail keeps the two consistent by authoring (arts gauge) |
+4 | u16 | round value (meaning unconfirmed) |
+8 | u32 | pointer to the arrow-glyph string: [count] then two-byte glyphs 0x81A9 L, 0x81A8 R, 0x81AB D, 0x81AA U; a 0xFF06 / 0xFF09 marker is not a direction |
+0xC | u32 | pointer to the name string |
+0x10 | u32 | aux string pointer |
The glyph string stores the physical direction (Noa's Arms / Ra-Seru are swapped) and is the oracle for both the record parser and the curated gamedata arts table - every AP agrees, and one walkthrough error surfaces (Vahn's Hyper Elbow is L R L on disc). Decoder legaia_art::arts_table::parse_from_scus; dump with art arts-table.
How we know
| Function | Address | What it proves | Dump |
|---|---|---|---|
| Damage kernel | FUN_801EC3E4 (overlay 0898) | Reads the strike's power byte at art_record[+0x24 + cursor], cursor at actor+0x1F4; bounds +0x7A to < 6. | - |
| Art materialiser | FUN_8004AD80 | actor[+0x4C] = DAT_801C9360[char][slot] - the runtime copy of record[0]; fires the CD-XA shout and Hyper fanfare. | - |
| Queue builder / tokenizer | FUN_801EED1C (0x801EF2EC..0x801EF858) | Emits a matched art's constant as row +0x18; Starter over the last arrow, leading arrows kept, tail-first restart. | - |
| Super tables | find 0x801F6524, replace 0x801F65E8 | 15 entries, capture-validated against a resident queue. | - |
| Cue playout | FUN_801DEA50, FUN_801E22C8, FUN_801E09F8 | Per-frame hit-cue walk at +0x14 + cursor×8; per-art cue list at 0x801F6470; special-attack sibling. | ghidra/scripts/funcs/overlay_battle_action_801dea50.txt |
| Element renderers | FUN_8004998C, FUN_80049348 | Spark along the swing path and afterimage tint keyed on actor[+0x21F] (the +0x7A class); neither reads the cue records. | - |
| Name-table expander | FUN_80036514 | Scans DAT_80075EC4 rows by (character, index); returns the +0xC name pointer. | - |
| AP display read | 0x801D4524 in FUN_801D33D8 (overlay 0899) | The only reader of the name table's +2 byte is the status-panel renderer. | - |
| Disc-gated tests | crates/art/tests/arts_table_real.rs, crates/gamedata/tests/arts_scus_oracle.rs | Record command bytes round-trip through the name-table oracle; curated AP + directions agree with SCUS (allowlist: Hyper Elbow). | - |
History: "PROT entry 0x05C4" and the SFX-table reading
0x05C4 = 1476 is past the last PROT index; the label survives only as the name of the record schema and of legaia_art::parse_record. The records are record[0] of the player files, and "Vahn = 0861" matched the same bytes through an over-read window. Separately, the byte table at 0x801F6418 was long documented as an SFX id table; its readers end in MoveImage copying a 16-entry palette row to VRAM (0xE0, 476) - no battle effect id plays a sound, all art audio is CD-XA. See do-not-re-walk.