Implement indexed party roster sort
This commit is contained in:
@@ -316,14 +316,36 @@ depends_on = []
|
||||
|
||||
[[global]]
|
||||
address = "0x6718"
|
||||
name = ""
|
||||
category = "story-flag"
|
||||
name = "selected_party_slot"
|
||||
category = "index-pointer"
|
||||
type = "int"
|
||||
value_domain = "one of {0, 2}"
|
||||
usage = "TODO: confirm. Branch-read in 0 scenes / 6 scripts; compared against [0, 2]; writers=['ADDSKILL.BIN', 'CHMENU.BIN', 'DELCH.BIN', 'DRAWCHP.BIN']."
|
||||
source = "auto-shape"
|
||||
confidence = "med"
|
||||
depends_on = []
|
||||
value_domain = "0..99"
|
||||
usage = "Current/selected slot in the 100-entry party-unit arrays. UNITECH chooses a free slot here before populating it; CHMENU replaces it with the selected sorted roster slot, then uses it to index party_slot_flags, party_slot_character_id, and companion per-slot tables. A natural New Game enters SC0000 with slot 2 selected."
|
||||
source = "investigation"
|
||||
confidence = "high"
|
||||
depends_on = ["0x673c", "0x67a0"]
|
||||
|
||||
[[global]]
|
||||
address = "0x673c"
|
||||
name = "party_slot_flags"
|
||||
category = "data-table"
|
||||
type = "int[100]"
|
||||
value_domain = "bitfield"
|
||||
usage = "Per-party-slot state flags for slots 0..99. UNITECH creates the initial unit by setting slot 2 to 0x13; CALCARR counts slots whose flags intersect 0x6, and CHMENU includes slots with bit 1 set. Exact meanings of the remaining bits are not yet classified."
|
||||
source = "investigation"
|
||||
confidence = "high"
|
||||
depends_on = ["0x6718", "0x67a0"]
|
||||
|
||||
[[global]]
|
||||
address = "0x67a0"
|
||||
name = "party_slot_character_id"
|
||||
category = "data-table"
|
||||
type = "int[100]"
|
||||
value_domain = "character/unit definition id or 0"
|
||||
usage = "Character/unit definition id stored for each party slot. UNITECH writes character id 2 into initial slot 2 on a natural New Game; CHMENU reads this table for every active party_slot_flags entry when constructing its roster."
|
||||
source = "investigation"
|
||||
confidence = "high"
|
||||
depends_on = ["0x6718", "0x673c"]
|
||||
|
||||
[[global]]
|
||||
address = "0x671b"
|
||||
|
||||
@@ -2578,38 +2578,39 @@ observed_types = ["imm", "g-int", "l-int"]
|
||||
|
||||
[[opcode]]
|
||||
op = 0x12f
|
||||
label = "u0041ECB0"
|
||||
label = "sort-indices-by-key-sum"
|
||||
argc = 4
|
||||
abi_source = "kelebek+decode-validated"
|
||||
|
||||
[opcode.semantics]
|
||||
name = "u0041ECB0"
|
||||
category = "unknown"
|
||||
summary = ""
|
||||
name = "sort-indices-by-key-sum"
|
||||
category = "compute"
|
||||
summary = "(out_indices, key_a, key_b, count) - write a stable ascending permutation of indices 0..count-1, ordered by the signed 32-bit sum key_a[index] + key_b[index]."
|
||||
noop_headless = false
|
||||
source = "kelebek"
|
||||
confidence = "low"
|
||||
source = "investigation"
|
||||
confidence = "high"
|
||||
depends_on = []
|
||||
evidence = ""
|
||||
evidence = "Ghidra /v2: op_0x12f_sort_indices_by_key_sum@0x429360 resolves operands 1-3 as integer-array bases, seeds out_indices[0]=0, then performs insertion sort. It shifts a prior index only when signed unchecked(key_a[new]+key_b[new]) is strictly less than the prior sum, so equal keys retain source order. Operand 4 is fetched as the exclusive count. The final native loop merely re-encodes direct writes into AGE's protected integer representation. Release corpus: 40 sites. CHMENU@0x1c9b sorts 100 party-slot keys and reads the populated tail; a no-op leaves the initial party slot undiscoverable even though UNITECH created it."
|
||||
details = "Implemented with domain-preserving addressed-array access, native signed 32-bit key addition/overflow, stable insertion ordering, repeated count reads, and the native unconditional out_indices[0]=0 write. Focused tests lock stability/overflow/zero-count behavior; a natural SYSTEM4-to-SC0000 state carried into release CHMENU proves the initial slot remains selected after the real roster sort."
|
||||
|
||||
[[opcode.semantics.args]]
|
||||
i = 1
|
||||
role = ""
|
||||
role = "out_index_permutation"
|
||||
observed_types = ["l-int"]
|
||||
|
||||
[[opcode.semantics.args]]
|
||||
i = 2
|
||||
role = ""
|
||||
role = "primary_key_array"
|
||||
observed_types = ["g-int", "l-int"]
|
||||
|
||||
[[opcode.semantics.args]]
|
||||
i = 3
|
||||
role = ""
|
||||
role = "secondary_key_array"
|
||||
observed_types = ["l-int"]
|
||||
|
||||
[[opcode.semantics.args]]
|
||||
i = 4
|
||||
role = ""
|
||||
role = "count"
|
||||
observed_types = ["imm", "l-int"]
|
||||
|
||||
[[opcode]]
|
||||
|
||||
Reference in New Issue
Block a user