Accessory passive-effect table Confirmed
Accessories - the game calls them "Goods" - grant passive effects: max-HP/MP percent boosts,
stat boosts, status-nullify guards, elemental guards, AP / encounter / loot / escape modifiers. This page is
the static data in SCUS_942.54 (the game's main executable) behind those effects, and its shape
is the surprise: there is no separate per-accessory effect record. The executable defines a
64-slot passive-effect index space (0x00..=0x3F) - one index = one effect - and
equipping an item simply sets bit index in a per-character ability bitfield at character
record +0xF4. Every mechanic that honours a passive just tests its bit at the point of use. A
side effect of the shared index space: quest items alias their purchasable twins (Mei's Pendant literally
is a Life Ring, effect-wise).
Indexing (Ghidra-traced)
(FUN_80xxxxxx / DAT_80xxxxxx are Ghidra names - the disassembler's labels for traced functions and fixed RAM addresses.) From the per-frame stat aggregator FUN_80042558 (static SCUS_942.54), which walks each active party member's eight equipment-slot bytes at char record +0x196:
kind = item_table[id].byte(+0) ; DAT_80074368[id*0xC]
if kind == 1: index = equip_bonus[sub].byte(+5) ; DAT_80074F6D[sub*8]
if kind == 2: index = descriptor[sub].byte(+3) ; DAT_800752C3[sub*4]
if index < 0x40:
char[+0xF4 + (index>>5)*4] |= 1 << (index & 0x1F)
char +0xF4..+0x103is the per-character 4×u32 ability bitfield - the word the MP-cost ability bits0x10/0x20(indices0x04/0x05) live in.- The aggregator then ORs all three members' bitfields into the global 4×u32 mask at
DAT_80074358(bit-tested byFUN_800431D0) - how party-wide passives are consumed. - Index
≥ 0x40grants nothing. Retail data: every equip-bonus row carries+5 = 0x40(no equipment grants a passive; thekind == 1arm is latent) and every consumable descriptor carries+3 = 0x41. Only accessory and quest-item descriptor rows carry live indices.
The same gate (descriptor +3, < 0x40) is read by the menu overlay's Goods detail panel FUN_801D0F1C and the static description resolver FUN_80034250 to fetch the display text.
The battle damage finisher FUN_801DDB30 consumes the bitfield's first two words (+0xF4/+0xF8) directly as the party defender's elemental-resist / spirit words: its per-element ladder tests bit 0x1D + attacker_element (the contiguous elemental-guard band, so elements 0..=2 land in +0xF4 bits 29..31 and elements 3..=6 in +0xF8 bits 0..3), +0xF8 & 0x10 is the All-Guard (0x24) 3/4-scale gate, and +0xF8 & 0x100/0x200 (AP Boost 1/2, indices 0x28/0x29) accelerate the defender's spirit-gauge fill. Engine mirror: engine-vm::battle_formulas::DefenderResist.
Passive name/description table (0x8007625C)
A static 64-record table gives each index its menu name, effect description, and scope:
| Field | Value |
|---|---|
| Record base | 0x8007625C (file offset 0x66A5C) |
| Stride | 0xC bytes |
| Record count | 0x40 (indices 0x00..=0x3F) |
| Offset | Type | Field |
|---|---|---|
+0 | u32 | scope: 1 = party-wide (one wearer benefits the whole party), 0 = wearer-only |
+4 | u32 | pointer to the effect name string (e.g. "HP Boost 1") |
+8 | u32 | pointer to the effect description string (0x7C '|' is the line break) |
Party-wide scope is set on exactly indices 0x30..=0x37 and 0x3B..=0x3F (the battle-end / encounter / escape modifiers).
The 64-index space (bands)
Names/descriptions are the on-disc strings; the assignments are byte-verified against the curated gamedata accessory table (accessory_passives_vs_disc):
| Indices | Band | Examples |
|---|---|---|
0x00..=0x0C | percent stat boosts (HP/MP 10%/25%, ATK/DEF/SPD/INT/AGL 20%) | Life Ring, Magic Armband, Power Ring |
0x0D..=0x15 | combat behaviours (Attack ×2, Guard/Steal/Counter Attack, turn-order chains) | War God Icon, Evil God Icon, Speed Chain |
0x16..=0x1C | status-nullify guards | Cure Amulet, Wonder Amulet |
0x1D..=0x24 | elemental guards (Earth/Water/Fire/Wind/Thunder/Light/Dark + All) | Earth Jewel, Rainbow Jewel |
0x25..=0x2F | per-turn regen, AP modifiers, arts/magic/EXP boosts | Life Grail, Mettle Ring, Crimson Book |
0x30..=0x37 | party-wide battle-end / initiative / escape modifiers | Golden Book, Chicken King |
0x38..=0x3A | walk regen (HP/MP/AP) | Life Source |
0x3B..=0x3F | encounter modifiers + two display-text-only card slots | Good Luck Bell; Point/Platinum Card special-cased by id |
Quest items share indices with their purchasable twins (Mei's Pendant = Life Ring, each Egg / Talisman = the matching Jewel). Indices 0x3E/0x3F have populated description records, but the Point Card / Platinum Card descriptor rows carry the 0x41 sentinel; the cards are special-cased by item id in the Goods panel.
Stat-boost magnitudes + Talisman spell grants
The percent boosts (0x00..=0x0C) are applied inline by the aggregator - there is no magnitude table. Per index: +10% = base/10, +25% = base>>2, +20% = base/5, added to the copied base, then capped (HP 9999, AGL 280, others 999). The remaining indices are point-of-use flags: each consumer tests the bitfield bit where the mechanic lives (MP cost at cast time, the steal table for Steal Attack, guards in the battle damage path, encounter rate in the field step roll, loot in the battle-end reward resolver FUN_8004E568). The two escape bits are consumer-pinned in the run roll FUN_801E791C: 0x34 Escape Boost (Chicken Heart) scales the party's escape roll x1.5 and 0x37 Great Escape (Chicken King) forces the roll compare to a tie - assured escape, still blocked by the scripted no-escape flag, hence "non-boss"; both fold only from living wearers (see battle-action).
A separate arm of FUN_80042558 watches equip slots for specific item ids (not passive indices) and grants/revokes battle spells: the five Talismans 0x72..=0x76 grant summon spells 0x9A/0x9B/0x9C/0x9D/0x99, and the top-tier Ra-Seru weapons 0x09/0x11/0x19 grant 0x9E/0x9F/0xA0. A Talisman is therefore "guard passive by index + summon by id".
Parser + engine consumption
legaia_asset::accessory_passive::AccessoryPassiveTable::from_scus resolves the property / descriptor / equip-bonus index bytes and the 0x8007625C records from a SCUS_942.54 image; stat_boosts(index) mirrors the aggregator arithmetic and bit_location(index) the bitfield placement. CLI: asset accessory-passive <SCUS> [--json]. The disc-gated accessory_passive_real test pins the per-item indices, table text, scope flags, and the retail equip +5 sentinel invariant. The engine consumes it via engine-core::accessory_passives + World::refresh_party_ability_bits (the aggregator port) and compute_battle_stats_with_passives (percent-of-base boosts with the retail clamp block).
Superseded readings
The descriptor +3 byte was previously documented as a "constant 0x41 ('A') marker" and the equip record's +5 byte as "constant 0x40". Both are in fact this index space's no-passive sentinels: 0x41 on every consumable row, 0x40 on every retail equipment row - only accessory / quest-item rows carry live indices.