At a glance

Where
record[0] of each player battle file (PROT 0863 Vahn / 0864 Noa / 0865 Gala), resident in RAM at 0x80160EFC / 0x80176998 / 0x8018BA54. Display names, arrows and AP: the SCUS arts-name table at DAT_80075EC4.
Stride
0xD0 bytes 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); editors legaia_patcher::arts_power / super_art_power.
Confidence
Command prefix, stride, power byte at +0x24, effect class at +0x7A and 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 button combos live in two places

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

commands 1=L 2=R 3=D 4=U, 0 ends const + anim name slot 20 bytes power run 1-4 bytes hit timing, cues, status, repeat (Inferred) effect class action-entry tail +0x00 +0x10 +0x24 +0x7A +0xD0 Confirmed fields in solid boxes; dashed regions are schema-then-walk, positions documented but not byte-pinned
One record per action constant. The 0x24-byte matcher head is followed by a standard battle action entry (see player files § battle animations).
OffsetSizeFieldMeaning
+0x00u8[]command sequence1=L 2=R 3=D 4=U, 0-terminated. A Super Art record's field is a one-byte stub (no combo).
afteru8action constant0x1B..=0x32 (below).
afteru8 + u8[5]anim_index, anim_extraPrimary animation slot; extras chain multi-stage arts (Noa's Hurricane Kick).
+0x1020nameFixed-width name slot; populated for Super, Miracle and some Hyper Arts.
+0x24u8[1..4]power runPer-strike damage tier bytes (encoding). Confirmed; editor legaia_patcher::arts_power.
+0x7Au8impact-effect class1..=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)
FieldEncoding
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.
IdentifierByte; some values trigger special animations (0x67 in Heaven's Drop = Thunderbolt).
Anim speedByte; lower = slower.
Effect on enemy1 Toxic, 2 Numb, 3 Venom, 4 Sleep, 5 Confuse, 6 Curse, 7 Stone, 8 Faint.
Repeat frames3 bytes: count, start, end. Replays a frame range and any hits inside it (Super Tempest: 4 power bytes, 8 hits).
Background0 regular, 2 black (Super Arts, Tornado Flame).
Runtime addressWord 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 rangeTargetMultipliersNote
0x16-0x1AUDF (upper defence)12, 18, 20, 22, 28Standard high hit.
0x1B-0x1FLDF (lower defence)12, 18, 20, 22, 28Standard low hit.
0x0C-0x10UDFsameMisses short enemies.
0x11-0x15LDFsameMisses 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, 0x1B on the Miracle Art, regular arts at 0x1B + 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's 0x2C/0x2D): named, powered, but no menu row and no combo.

Action constants

Every entry in the battle action queue is one of these bytes:

ByteMeaning
0x00-0x05Nothing, Item, Magic, Attack, Spirit, Escape
0x07 / 0x08Faint animations 1 / 2
0x0A / 0x0BItem-or-magic animation / block animation
0x0C-0x0FLeft, Right, Down, Up
0x10Spirit animation
0x11-0x18Empty slots (never in static data)
0x19 / 0x1ARegular / Special Art Starter
0x1B-0x32Per-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).

SlotVahnNoaGala
0x00Vahn's CrazeNoa's ArkBiron Rage
0x01Burning FlareHurricane KickExplosive Fist
0x02Fire Blow-Lightning Storm
0x03Tornado Flame-Thunder Punch
0x04CycloneVulture BladeBull Horns
0x05HurricaneFrost BreathElectro Thrash
0x06PK ComboTempest BreakNeo Raising
0x07Spin ComboRushing GaleBlack Rain
0x08Pyro PummelTough LoveSide Kick
0x09Cross-KickSwan DriverHead-Splitter
0x0APower PunchBird StepGuillotine
0x0BSlash KickDolphin AttackBack Punch
0x0CSomersaultMirage LancerIronhead
0x0DCharging ScorchBlizzard BashBattering Ram
0x0EHyper ElbowSonic JavelinFlying 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).

AnimVahnNoaGala
0x01Power PunchTempest BreakBull Horns
0x02Slash KickTough LoveHead-Splitter
0x04Tornado FlameHurricane Kick 1Lightning Storm
0x05HurricaneHurricane Kick 2Back Punch
0x06Charging ScorchRushing GaleIronhead
0x07PK ComboSwan DriverBattering Ram
0x08Fire BlowFrost BreathFlying Knee Attack
0x09SomersaultLizard Tail-
0x0ACycloneJurassic Blow 2Thunder Punch
0x0BHyper ElbowBird StepGuillotine
0x0C-Dolphin AttackExplosive Fist
0x0DBurning FlareVulture BladeBlack Rain
0x0ESpin ComboMirage Lancer-
0x0FPyro PummelBlizzard Bash-
0x10Cross-KickSonic JavelinSide Kick
0x11Acrobatic BlitzElectro 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.

CharacterArtInput
VahnVahn's CrazeR D L U L U R D L
NoaNoa's ArkL U R D U L U D R
GalaBiron RageR 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.

1input arrowsThe player types 7-9 directions, e.g. ↑↓↑↑↑↓↑.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).

CharacterSuper ArtChainInputAP
VahnTri-SomersaultSomersault, Cyclone, Somersault↑↓↑↑↑↓↑60
VahnMaximum BlowCharging Scorch, Slash Kick, Power Punch↓→↑↓←←↓54
VahnFire TackleHyper Elbow, Power Punch, Charging Scorch←→←←↓→↑54
VahnPower SlashCharging Scorch, Somersault, Slash Kick↓→↑↓↑↓←54
VahnRolling ComboSpin Combo, Power Punch, PK Combo↑↓→←←↓↑↑←66
NoaTriple LizardBird Step, Swan Driver, Lizard Tail↓↓↓↑↑↑↓↑66
NoaSuper JavelinRushing Gale, Sonic Javelin↑↑←↓→↓→48
NoaSuper TempestDolphin Attack, Tempest Break→→←→→←↑↑↑60
NoaLove YouMirage Lancer, Lizard Tail, Tough Love→→↑↑↓↑↓←→72
NoaDragon FangsLizard Tail, Swan Driver, Acrobatic Blitz↑↓↑↑↑↓↓60
GalaBack Punch x3Ironhead, Flying Knee Attack, Back Punch↑↓↓↑←→←54
GalaSuper IronheadFlying Knee Attack, Head-Splitter, Ironhead↓↑←↑↑↓↓54
GalaRushing CrushBattering Ram, Flying Knee Attack, Head-Splitter←→↓↑←↑↑54
GalaHeaven's DropFlying Knee Attack, Head-Splitter, Black Rain↓↑←↑↑←↓↓60
GalaNeo Static RaisingBack 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.

OffsetTypeField
+0u8character: 0 Vahn, 1 Noa, 2 Gala
+1u8art display index
+2u8AP cost - a display mirror; the battle path computes multiplier × command count from code immediates and retail keeps the two consistent by authoring (arts gauge)
+4u16round value (meaning unconfirmed)
+8u32pointer 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
+0xCu32pointer to the name string
+0x10u32aux 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

FunctionAddressWhat it provesDump
Damage kernelFUN_801EC3E4 (overlay 0898)Reads the strike's power byte at art_record[+0x24 + cursor], cursor at actor+0x1F4; bounds +0x7A to < 6.-
Art materialiserFUN_8004AD80actor[+0x4C] = DAT_801C9360[char][slot] - the runtime copy of record[0]; fires the CD-XA shout and Hyper fanfare.-
Queue builder / tokenizerFUN_801EED1C (0x801EF2EC..0x801EF858)Emits a matched art's constant as row +0x18; Starter over the last arrow, leading arrows kept, tail-first restart.-
Super tablesfind 0x801F6524, replace 0x801F65E815 entries, capture-validated against a resident queue.-
Cue playoutFUN_801DEA50, FUN_801E22C8, FUN_801E09F8Per-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 renderersFUN_8004998C, FUN_80049348Spark along the swing path and afterimage tint keyed on actor[+0x21F] (the +0x7A class); neither reads the cue records.-
Name-table expanderFUN_80036514Scans DAT_80075EC4 rows by (character, index); returns the +0xC name pointer.-
AP display read0x801D4524 in FUN_801D33D8 (overlay 0899)The only reader of the name table's +2 byte is the status-panel renderer.-
Disc-gated testscrates/art/tests/arts_table_real.rs, crates/gamedata/tests/arts_scus_oracle.rsRecord 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.

See also