At a glance

Turn pool
The acting actor's AGL (actor+0x154), copied into ctx+0x6DC; input ends when the next command would not fit
Command cost
Runtime command record DAT_801C9360[char][cmd] + 0x74 - one byte is both the AP price and the pennant width
Tiers
30 favored / 42 off-class / 54 far tier - authored data, no class comparison in code
Disc source
The equipped weapon's section in the character's player battle file (extraction 863..865), copied verbatim at battle load
Input state
FUN_801D0748 state 0x50; it ends on auto-end, the confirm mask, or a cancel with nothing typed (leaving the entry)
Auto string
One remembered command string per character, preseeded into the entry and replayed on a bare confirm (the auto command string)
Art cost
A second gauge: the Spirit gauge actor+0x170 (0..100), which carries between fights
Editor
The ROM patcher's equipment editor and the randomizer's --weapon-specialty rewrite the cost bytes in place
Confidence
Confirmed - live-pinned and byte-validated against the disc; "command 0x0C = the arm" is Inferred (how we know)

What the AP bar does

On your turn the Arts bar fills with a row of pennants, one per direction you press, and stops accepting input when the next pennant would not fit. The pool is the character's AGL. Every direction has a price; three of the four never change. The fourth - the weapon-hand swing - is authored per weapon, and because the price is also the pennant's width, an off-class weapon looks wider and fits fewer commands in the same turn.

favored weaponarm costs 30 Arm30 Arm30 High30 Low30 High30 exactly spent off-class weaponarm costs 42 Arm42 Arm42 High30 Low30 6 AP left over far-tier weaponarm costs 54 Arm54 Arm54 High30 12 AP left over AGL 150 turn pool = the character's AGL
The same 150-AGL turn with three weapons, pressing Arm, Arm, then the legs. Only the weapon-hand arm changes width; the wider it is, the fewer commands the turn admits.
TierArm costOver baseWho lands here
Favored class30-Vahn with a sword, Noa with a claw, Gala with a club
Off-class42+12 (×1.4)e.g. Gala holding a claw
Far tier54+24 (×1.8)Noa with any club or axe; Vahn's Astral Sword

Only the weapon hand depends on equipment - Left for Vahn and Gala, Right for Noa. The Ra-Seru arm and the two leg commands are always 30. The "off-class doubles the arm" folklore counts penalties: the Astral penalty (+24) is twice the off-class penalty (+12); the cost itself is ×1.4, not ×2.

How the gauge consumes it

One battle-overlay routine builds the gauge and spends it:

  1. Seedpool ctx+0x6DC = the acting actor's AGL +0x154
  2. Buildeach chip reads its command's +0x74 cost; the pennant is drawn cost − 6 pixels wide
  3. Pressif the pool is below the cost the press is refused; otherwise pool −= cost and the committed count ctx+0x19 goes up by one
  4. Auto-endonce none of the four costs fits the pool, the entry ends by itself

One byte is both price and width - a larger button and a more expensive command are the same value. The pennant is a text window and its label has to fit: 30 is retail's floor, 24 is still legible, below that the label smears (the patcher refuses costs below 24). The re-centre term only moves the pennant; the AP fill bar is unaffected at any cost.

The chips do not read Left / Right. Each chip's label is an icon id into the label-strip words RaSeru, Arms, Right, Left, High, Low. The entry opener stamps them so the Left chip reads Arms and the Right chip RaSeru; Noa's two arm seats are swapped, because her record holds the Ra-Seru in equipment index 2 and the weapon in index 3. An arm whose equipment byte is empty takes the plain direction word instead, and a committed pennant copies its chip's word, so the bar reads RaSeru / Arms too.

The Low chip's cost byte (ctx+0x16) is also the byte the battle action state machine uses as the War God Icon's Attack x2 pass counter, so every manual command entry leaves that counter non-zero. The Auto path does not build the gauge and leaves the byte alone.

Three neighbours share the machinery:

  • The Muscle Dome hand deals and spends the same records: a dome card is a direction command, its cost is the same byte, the commit debits the same pool (minigames).
  • The enemy analogue is not an analogue at all - it is the same mechanic. A monster fills its per-turn action queue by paying each move's +0x74 cost out of the same AGL gauge, so a turn admits AGL / cost actions on either side (battle action).
  • A Spirit turn lengthens the next turn's pool to min(base AGL × 7/5 + 8, 288) (formula).

Two budgets, not one

The AP pool bounds a turn by cost; the committed command buffer (actor+0x1DF..+0x1EE) bounds it by count - sixteen bytes. A plain press is one byte; a matched art replaces its last arrow with a two-byte starter pair, so an N-arrow art occupies N+1 bytes. At retail costs the pool binds long before sixteen tokens do; a mod that prices commands low enough hits the buffer instead.

Leaving the entry

The Arts input is state 0x50 of the command-menu state machine FUN_801D0748. It has three exits, two of them pad-driven, and all three consult the committed count ctx+0x19:

0x78attack-mode prompt 0x50Arts input 0x5Areview + target 0x6EBegin / Reselect Command cancel, empty auto-endor confirm last member press: pool −= cost cancel, typed: restart
The Arts entry and its exits. A cancel with a typed buffer is a restart inside 0x50, not an exit; Begin / Reselect opens once, after the last member that can act has committed.
  • Auto-end. The arm walks the four costs at ctx+0x14 against the pool; when none is affordable it writes 0x5A.
  • Confirm uses the configurable confirm mask _DAT_800846D0 - the same one the round prompt and every menu read - and is only tested once something is committed.
  • Cancel uses the sibling mask _DAT_800846D4 and forks on the count. With nothing typed it leaves to the attack-mode prompt 0x78 (0x28 instead when _DAT_800846C4 is set). With a typed buffer it restarts the entry: the gauge handler's case 0x26 wipes all sixteen queue bytes, re-seeds the pool from AGL and zeros the count, and the flow byte stays at 0x50.

The four direction tests read the packed pad word (_DAT_8007B874 | _DAT_8007B938), whose byte halves are swapped against the raw BIOS word - so the masks 0x8000 / 0x1000 / 0x4000 / 0x2000 are Left / Up / Down / Right, not Square / Triangle / Cross / Circle.

The auto command string

Retail has no "pick a saved art" list. It remembers one command string per character, opens the entry with it already laid out, and replays it on a bare confirm.

  1. Saveat the target confirm, FUN_801DA59C copies the actor's sixteen-byte window actor+0x1DF.. into one of two bands of the character record (+0x1A7 / +0x1B7, picked by whether the live AGL gauge exceeds its base). This runs before the queue builder tokenizes anything, so the string holds raw arrows, one swing byte per press.
  2. PreseedFUN_801DA34C copies it back when the attack-mode prompt takes Command, and the gauge build draws it: each command is tested against a scratch pool seeded from AGL, drawn as an ordinary pennant and debited; at the first command the pool cannot pay, the string is cut. The pool is then reset to full, so the entry opens with the string's pennants over a full bar and a committed count of 0.
  3. First press wipes ita direction press with the count at 0 zeroes the window and retires the preseeded pennants before storing the press - the pad replaces the preseed, it does not edit it.
  4. Bare confirm replays itwith no direction pressed, a zero count, a non-empty window and the confirm mask, the arm measures the string, stores its length as the count and enters 0x5A as a typed confirm does.

A replay costs no pool AP, but its arts still cost Spirit

The replay never runs the press case, so the turn pool is not debited; the gauge build only measured the string against one full pool. The two-band save keeps a string recorded under a raised gauge from replaying under the base one. The Spirit cost of the arts the string spells is charged again, because the queue builder re-tokenizes the raw arrows at the dispatch.

Captured example: Gala's off-class entry with a saved six-press string, a 197 pool and a 42-AP arm opens as five pennants - the window is cut to the prefix one full pool affords.

The port runs the same preseed, cut and replay in its Arts input session and draws the preseeded pennants through the shared bar on both hosts. Its named chain library (the chain editor's list) is separate data that nothing preseeds from. Because a turn performs however many arts the pool paid for, the shout cue and the learn-on-use check are per art, not per turn.

What a named art costs

The number of directions is paid from the AGL pool; the art those directions spell is paid from a different gauge - the Spirit gauge, actor+0x170, capped at 100. The game stores no per-art price. The arts queue builder computes it:

art cost = multiplier × command count
multiplier = 11 for the character's first art row, 10 for rows 1-3, 6 from row 4 on
             (halved while the AP Used Down passive - the Mettle Gem - is worn)
  • Example. Noa's Vulture Blade is a five-command art on a multiplier-10 row: 50 Spirit, 25 with the Mettle Gem.
  • When it is paid. The builder only adds the price to the accumulator actor+0x224; the action’s cleanup arm (0x801E5D74) takes it off the gauge. So the AP plate holds its figure until the art ends, and an art typed short of its price stays plain swings.
  • Where the gauge comes from. Every action pays +8 into Spirit at its Done step, a Spirit turn +32; the gauge is saved in the character record at the end of a fight and reloaded at the next, so a full gauge carries over.
  • Where the charge lands. The builder only tentatively debits (so a chained second art sees what the first committed) and puts the real charge in an accumulator actor+0x224, subtracted once in the Done band. A mod that changes an art's cost has to move the accumulator.
  • The pause menu's number is a second source. The AP the arts list shows is a byte of the static arts-name table, kept equal to the formula by hand for all 45 arts. A mod that changes one has to change the other.

Where the cost comes from

The game performs no class comparison. The cost is written once at battle load as a verbatim 43-word block copy out of the assembled battle-character buffer - no arithmetic between load and store, confirmed by a live write-watch across a field→battle transition. The source is the equipped weapon's section of the character's player battle file:

Section +0x04
u32 offset to the swing (arm) command record, in the LZS-decoded section
Record +0x74
u8 arm cost - the weapon-specialty byte

The descriptor table keys sections by item id, so each weapon has its own swing record per character's file - a claw is cheap in Noa's file and expensive in Gala's. Decoding all four files gives the byte-exact picture:

Character (file)Favored → 30Off-class → 42Far → 54
Vahn (863)blade / knife / sword / fistclaw, axeAstral Sword only
Noa (864)claw / feral / fang (+ knife)sword / bladeclub / axe
Gala (865)club / axe / maceclaw, knife-

Cross-checked live: Gala + Nail Glove reads 42, Gala + Ra-Seru Club reads 30, matching his file's sections. The cost lives inside an LZS-compressed stream, so an editor decompresses the section, rewrites one byte, recompresses, and writes back within the slot footprint.

"Off-class" itself is legible from the static item records: the description pointer is shared per weapon class and carries a Best:<character> token - knife/sword → Vahn, claw → Noa, club/axe → Gala. The Astral Sword has its own description, matches no character, and simply sits on the tier Noa reaches with any club.

Status limb gating

A Rot-class status stamps a hand-lettered "Rot" mark over individual command arrows and refuses their input. The stamp pass and the input gate read the same status bits, bit-for-bit - and the retail assignment is not one bit per arrow:

Status bitStampsBlocks
0x08 (limb 0)the LEFT chipLeft
0x10 (limb 1)the RIGHT chipRight
0x20 (limb 2)UP and DOWNUp and Down
0x1000 (Curse)the ring's Magic chipMagic

With all three limb bits set the whole Arm command is skipped and Attack is unusable. Rot rolls exactly one of the three limb bits per application.

The stamp is sized off the chip's AP cost and keeps the edge nearest the D-pad fixed, exactly as the cost-widened chip does; the High / Low stamps stay at the favoured width whatever those chips cost. The command ring marks the same states every frame, before the pad is read: all three limbs stamp Rot over the Attack chip, and Curse lays its plate over the Magic chip. Both play hosts of the port draw these marks.

Every weapon, every character

Weapon-hand swing cost from each character's file; all other commands read 30. A dash means the file has no section for the weapon (the equip mask stops them equipping it anyway). Classes are finer than blade / claw / club: Gala swings a Short Sword at 30 but a knife at 42; Vahn swings light clubs at 30 but the Power Club and every axe at 42.

WeaponVahn (Left)Noa (Right)Gala (Left)
Survival Knife, Battle Knife303042
Short Sword, Force Blade304230
Beast Buster, Chaos Breaker30-30
Nail Glove, Crimson Nails, Fighter Claw, Bloody Claw423042
Survival Club, Red Club305430
Power Club, Survival Axe, Battle Axe, Great Axe425430
Astral Sword54--
Character-locked gear (Ra-Seru weapons, Feral / Hard Beat / Heavy Strike, Holy / Golden Claw, Mace)303030
If the Astral Sword is forced onto another character

The value 54 exists in exactly one place on the disc - the Astral section of Vahn's file - and the other files have no section for that id. Forced into Noa's slot by a cheat, the section selector finds no match and takes the id-0 default entry: default mesh, default swing record, cost 30. She swings at the favored price and does not visibly hold the sword; the attack bonus still applies, because attack folds in at execution from the static equipment table, keyed by item id alone. A mod that wants the penalty to travel would have to add a section, and there is no room - every player file ends flush against its last slot. The in-place knob is the default record's own cost, which the ROM patcher's equipment editor exposes per section (not yet confirmed with a live capture of an edited save).

At execution: a different weapon read

Once a combo is committed, the execution resolver replays it one command per step and folds half the equipment slot's attack into the working ATK per swing - a read distinct from the gauge cost, covered in full on battle formulas. The battle loader deliberately folds no ATK at load; the fold happens here, per committed command.

Deep dive: dispatch bounds and the admission gate

The resolver FUN_801EC3E4 advances the input cursor at actor+0x1F4 and dispatches through PTR_801CF4B4[(actor+0x1D9) - 0xC], bounded at six arms (commands 0x0C..=0x11). The head admission gate tests a different band from a different place - (cmd - 0x0C) < 0x14 - so a command in 0x12..=0x1F is admitted and then folds nothing. 0x0E/0x0F share an arm; 0x10's slot is the same address the bounds check bails to - a live table entry that folds nothing. Retail applies no empty-slot test here. The call comes from SCUS_942.54 at 0x800478A0, which is why the resolver has no caller inside the overlay.

Common misconceptions

ClaimWhat the bytes say
"An off-class weapon doubles the arm command."Off-class is 30 → 42 (×1.4); the far tier is 30 → 54 (×1.8). The "double" counts penalties: +24 is twice +12.
"The game checks the weapon's class against the character."No comparison exists; the value is authored data. The equipment, item-property and accessory tables were each checked - none carries the cost.
"The cost is recalculated when equipment changes."Changing equipment alters only id bytes in the character record; the cost is read from the disc at the next battle load.
"The Astral Sword has a unique penalty."Its 54 is the same far tier Noa receives from any club or axe.
"The AP shown next to an art is what the bar charges."Two different gauges: a named art is paid from the Spirit gauge (actor+0x170), not the bar's pool - see what a named art costs.

How we know

Function / dataAddressWhat it proves
Gauge build + pressFUN_801D388C (overlay 0898)Case 9 / 0x2C reads +0x74 (store at 0x801D3B3C); case 0xB debits ctx+0x6DC; one byte is width and price.
Command menu SMFUN_801D0748State 0x50 Arts input: direction tests, auto-end, confirm / cancel masks; limb-bit stamp and gate agree bit-for-bit.
Auto string preseed / saveFUN_801DA34C / FUN_801DA59CCopy between actor+0x1DF.. and record +0x1A7 / +0x1B7; the gauge build's cut at the first unaffordable command.
Load-time writerFUN_800557B8 (SCUS)Verbatim 43-word copy; the single cost write fires at 0x80055810 under a live write-watch.
Character assemblyFUN_80052770 / FUN_80052FA0Section selection from the record's equip bytes; swing-record splice; id-0 default fallback.
Execution resolverFUN_801EC3E4Per-command fold into working ATK; called from SCUS 0x800478A0.
Enemy budgetFUN_801E9FD4The AI pays the same +0x74 costs from its AGL gauge.
Disc bytesPROT 863..865asset battle-data-pack decode of every weapon section's swing_rec + 0x74 - the tier tables above.
Live RAMDAT_801C9360[char][cmd]+0x74Gala + Nail Glove = 42, + Ra-Seru Club = 30, matching the file bytes.
Address appendix: records, context fields, static tables

Character records (stride 0x414 from 0x80084708): equip slots at +0x196..+0x19A (body, head, index 2, index 3, footwear), name at +0x2A7, accessories at +0x19B..+0x19D. Index 2 / 3 hold the weapon and Ra-Seru in the order the character's file expects: weapon in slot 2 for Vahn and Gala, slot 3 for Noa - the cheat-database "weapon = +0x198" label is Vahn's and Gala's layout.

Address / fieldMeaning
0x8007BD24Pointer to the battle context struct
0x801C9360Per-party-member pointer to the command-record pointer array; [char][cmd] + 0x74 is the cost byte
0x801F4B8C / 0x801F4B94Displayed command codes 0C 0F 0E 0D / icon bases 0D 10 11 0C; 0x0C is the arm whose cost tracks the weapon
ctx+0x06 / +0x13 / +0x14..17 / +0x19 / +0x1BMenu flow byte; active slot; per-command AP costs; commands committed; raised when the gauge build drew a preseeded string
0x800846D0 / 0x800846D4Configurable confirm / cancel pad masks the input state tests
ctx+0x6DCTurn pool, seeded from actor AGL (+0x154)
actor+0x158 / +0x16E / +0x170Working ATK; status word (limb bits); Spirit gauge (where a named art's cost lands, via the accumulator at +0x224)
0x80074368 (12-byte stride)Item property records; +1 equipment-row index, +8 shared per-class description pointer
0x80074F68 (8-byte stride)Equipment stat rows; +1 attack, +6 equip-character mask
0x80075EC4 (0x14 stride)Arts-name table; +2 is the menu's displayed art AP (the Spirit charge)

An emulator sweep of injected +0x74 values established the pennant legibility floor (24). A separate +2 in the build case is an empty-slot icon tweak, not the class penalty.

The full doc adds the gauge formulas, the animation-rate restore after an action, the arts-AP override hook and register-level detail: docs/subsystems/arts-command-gauge.md.

See also