In short
  • What you see. Gaza starts a melee from across the arena, takes a step or two, stops short and never strikes. The camera keeps orbiting because it never asks the battle whether anything is happening.
  • Why. A monster with no walk animation - 180 of the 186 - is moved to its target only by its looping “Move” clip, and the state that waits for it to arrive has no movement code and no timeout. Kemaro, the Seru spell that carries its target off the stage, leaves an “exit to idle at the next clip end” flag on Gaza when it puts him back. If his very next action is a melee from out of reach, that flag ends the Move clip after one loop, about 12 frames in, and the wait never ends.
  • Why Gaza 2. He has the longest idle loop (the flag's lifetime) and the shortest Move loop of the walk-less roster, and enough HP to survive Kemaro again and again.
  • The fix. Nine redundant words inside the wait are rewritten so a dead clip sends the state machine back to its own staging state, and the attacker resumes walking. Enable the Approach-softlock fix toggle.

At a glance

What stalls
The per-action battle state machine, parked in state 0x19 (attack approach)
Where
Battle-action overlay, PROT entry 0898, load base 0x801CE818
Trigger
Kemaro, then - inside one idle loop - a melee by its target, a monster with no walk animation, against an out-of-reach target
Affected
180 of 186 monsters take the affected path, but the clip lengths make Gaza 2 the one fight where the chain lines up in ordinary play
Fix
Nine same-size words at overlay offset +0x14D50; --approach-softlock-fix
Confidence
Confirmed - live captures on two emulator cores, replayed with the fix

What the orbit means

The orbiting camera carries no information of its own. The battle round driver sweeps the camera's idle azimuth every frame without consulting the action state machine, so an orbiting camera is what any stalled Legaia battle looks like. The component that stops advancing is the per-action state machine in the battle overlay.

Two independent live captures localise it. A poll-only emulator probe flags any action state held for thousands of frames; both captures park in the same state: 0x19, the attack approach.

Four ways out of an attack

Every physical attack enters approach setup, state 0x14. Its first act is a range check - “within reach” is a size-scaled radius, about 416 units for a boss-sized actor. From there the attack routes four ways:

State routing out of attack setup 0x14 setup in reach 0x1E strike the usual case out of reach, party member 0x19 wait run animation moves them 0x1E strike monster with a walk clip (6 of 186) 0x15 0x16 loop 0x17 0x1E strike the state machine itself steps the monster forward - guaranteed to arrive monster without a walk clip (180 of 186) 0x19 wait-in-range Move clip carries it 0x1E strike if the clip dies: no movement code, no timeout - the poll runs forever
The bottom lane is where almost every monster melee lives - and the only lane whose forward motion depends on an animation staying alive.

The decisive branch is the walk gate. Out of reach, a monster attacker needs its approach-transition clip - action tag 0x20 in its per-monster action table. If the tag is missing, setup stages the ordinary tag-1 “Move” locomotion clip instead and drops into the wait-in-range poll. A sweep of the monster archive puts numbers on it: 180 of 186 monsters have no tag 0x20, bosses included. All 186 carry the Move clip - the float or walk cycle the enemy viewer shows.

An approach the state machine does not perform

The two approach mechanisms differ in one property. The walking states 0x15–0x18 contain the state machine's own stepping code - a monster in that chain is moved by the engine. The fallback state 0x19 contains none: it re-derives facing, re-polls the range check, and on failure bumps a counter that nothing reads as a timeout. All movement comes from the staged animation's playback: the Move clip slides the actor along its facing at about 19 units per frame.

Position captures of ordinary play show this working every time: a healthy boss melee starts out of reach (438–1,078 units against a ~416 reach - standard formation spacing is out of reach; the models are large enough that it reads as adjacent) and the Move clip walks the boss in over 28–67 frames. The path fails only if the animation stops, and no code can observe that it stopped: the clip is staged once, in 0x14, and never again.

Healthy versus parked approach, measured from live captures frames since the approach began distance to target 0 416 1022 reach (~416, size-scaled) in reach at ~28 frames → strike healthy melee: Move clip playing, ~19 units/frame clip dies at ~12 frames frozen at 786 > reach - polls forever, battle over
The same fallback path, ~19 units/frame in both - until the staged clip dies. Nothing re-stages it, and state 0x19 has no timeout.

The trigger: Kemaro, then the melee

The second capture logs the actor's animation pair - staged clip versus playing clip - every frame, which pins what kills the clip. Kemaro carries its target ~2,500 units off-arena and stages his hit reaction there, which sets the “exit to idle at clip end” flag. Its put-back starts his idle pose through the mid-clip commit, which keeps that flag, so the flag waits for the end of his idle loop - 360 vsyncs. When his next action inside that window is the melee, the Move clip carries the flag and is swapped for idle at its first loop end, about 12 frames in.

v2900 v3000 v3100 v3200 v3300 v3400 v3500 Gaza's clip +0x1DC bit 2 battle action reaction, pinned on frame 3 idle idle - frozen out of reach set: swap to idle at the next clip end window: one idle loop, 360 vsyncs Noa's Kemaro cast ends Gaza's melee: state 0x19 polls forever 1 2 3 4 1 Kemaro stages his hit reaction off-arena and raises bit 2 2 put-back: idle starts through the commit that keeps bit 2 3 melee from out of reach: Move clip staged, bit 2 still set 4 first Move loop ends ~12 vsyncs in: bit 2 swaps it for idle
One parked approach on the retail disc, from the pad driver, with Gaza's HP and MP poked lower so that he melees (scale: vsyncs). The bit goes up with Kemaro and, but for the melee, would have come down harmlessly at the end of his idle loop. The melee started inside that window, so the Move clip carried the bit and died at its first loop end. Any other action in the window ends its own clip and spends the bit.
  • The window is one idle loop. Kemaro → another combatant's turn → melee runs the same clip 64 frames to a clean hit: the turn in between outlasted the loop. A cast by the boss in the window spends the flag harmlessly.
  • It reproduces on demand. Cast Kemaro with the caster acting directly before the boss, and the approach parks whenever his next action is the melee. A scripted run did exactly that on the first Kemaro, with the boss's HP and MP poked lower so that he melees; the patch's guard, poked into that park, unparked it.
  • A plain hit cannot cause it. Every other hit reaction plays to its end before the action is over, and that end clears the flag. Only Kemaro's put-back keeps it.
  • Gaza 2 is the extreme case. Of the 180 walk-less monsters he has the longest idle loop and the shortest Move loop, and the HP to survive Kemaro again and again. The few other candidates need a wide gap or die to Kemaro.
  • It is not an emulator artifact. The same recipe parks under both PCSX-Redux CPU cores with an identical onset, and every length in the chain is counted in game frames. A failed repro elsewhere is most likely the chain not lining up.
Frame-exact onset from the capture
v26536  summon cinematic: boss staged off-arena to (0,-2048),
        his damage-reaction clip plays (pair 2/2), restored, pair -> 0/0
v26867  summon action ends
v26873  boss melee starts DIRECTLY next - 0x14, target ~1022 away -> fallback
v26876  0x19, pair 1/1: Move clip ENGAGED, sliding ~19 units/vsync
v26888  pair 0/0: clip DEAD after ~12 vsyncs / ~236 units
        frozen at ~786 (> 416 reach) -> polls forever  = the softlock

The pair is actor+0x1DA (staged clip) / actor+0x1D9 (playing clip). The stale latch is bit 2 of the anim event flags actor+0x1DC: a later capture shows it still set after the put-back turns the pair to 0/0. The carried reaction clip never reaches its own end because Kemaro pins it on frame 3 with the target's speed scale set to 0 (0x801F8370..0x801F8380).

The fix: teach the poll to re-stage

Two fixes are possible. Retargeting the walk-gate fallback straight into the strike (one word - attack from wherever you stand) closes the softlock but removes every monster's approach walk, because out-of-reach is the norm. The shipped fix addresses the defect itself: the dead clip that nothing re-stages.

There is no free space for new code - every verified-dead run in the executable is occupied by other patch features - so the guard replaces nine redundant words inside the poll itself. State 0x19 recomputes the actor's facing every frame, but the target does not move during an approach and both neighbouring states recompute it anyway. Nine words with no observable effect, exactly where the guard needs to live.

The guard reads the staged-clip byte each poll. While the clip is alive nothing happens - healthy fights are byte-identical. If the clip is dead while the poll still fails, the guard sets the state byte back to 0x14. That single write is enough because the staging logic already exists in retail: the 0x14 arm re-runs next frame, re-checks the range, re-stages the Move clip, and the attacker resumes walking. If the clip dies again, the guard fires again - a stuttering but monotonic approach that always arrives.

The nine words, before and after
The nine-word window stock: facing recompute (redundant during an approach) 801e3568 lh a0,0x38(s8) 801e356c lh a1,0x34(s8) 801e3570 lh a2,0x38(s3) 801e3574 lh a3,0x34(s3) 801e3578 jal 0x80019b28 801e357c _nop 801e3580 addiu v0,v0,0x800 801e3584 andi v0,v0,0xfff 801e3588 sh v0,0x46(s3) target is static; 0x14 and 0x1E both re-derive this same size patched: the re-stage guard 801e3568 lbu v0,0x1da(s3) staged clip? 801e356c lui v1,0x8008 801e3570 lw v1,-0x42dc(v1) battle ctx 801e3574 ori a0,zero,0x14 801e3578 bne v0,zero,+3 alive → skip 801e357c _nop 801e3580 sb a0,0x7(v1) dead → state 0x14 801e3584 nop 801e3588 nop falls into the unchanged range-check call
One same-size nine-word rewrite at overlay offset +0x14D50. No injected routine, no reclaimed dead space, no new behaviour.

The walk gate that selects the lane: 801e3260 li a1,0x20 scans the action table for the approach-transition tag via FUN_80050E2C; not found → li a1,0x1, stage the Move clip into actor+0x1DA, jump to the 0x19 poll. Party reach comes from the static table DAT_80078870 = {256, 384, 1024}; monster reach from the size-scaled check FUN_8004E2F0.

The same bounce protects a party attacker whose run clip dies. The one shape it cannot rescue - a monster with no Move clip at all - does not exist: the roster sweep finds zero.

Apply the fix to your disc

Get the fix
Open the in-browser ROM patcher, load your disc image (processed entirely in the tab, never uploaded), tick “Approach-softlock fix”, and download the patched image or a PPF patch.
legaia-patcher randomize --input DISC.bin --approach-softlock-fix

The fix is seedless, composes with every other patch option, and the Balanced / Full Chaos presets enable it by default. See the patcher reference.

How we know

EvidenceAddressWhat it proves
Battle-action state machineFUN_801E295C (PROT 0898)The 0x14 → 0x15..0x19 → 0x1E routing; 0x19 has no movement code and no timeout
Battle round driverFUN_801D0748Camera orbit runs unconditionally - the symptom is generic
Action-table scan / range checkFUN_80050E2C / FUN_8004E2F0Tag 0x20 selects the walk chain; reach is size-scaled (~416 for a boss)
Monster archive sweepPROT 867180 of 186 monsters lack tag 0x20; all 186 carry the tag-1 Move clip
Two live park capturesPCSX-Redux poll probeBoth stall in 0x19; animation pair +0x1DA/+0x1D9 goes 1/1 → 0/0 ~12 frames in
Reproductionrecompiler + interpreter coresKemaro → melee parks on demand with identical onset
Disc oracle + replays+0x14D50, nine wordsExactly nine words change; both park states replay to a completed round with only those words poked

The full evidence trail is on settled RE threads.