tools(fifa17): answer "who writes item +0x60" — nothing does
The plan called this "the single blocker between 'we can mark a kit equipped'
and 'we can equip a kit'", and recorded that two attempts to find the writer
drowned at 1688 and 4144 instructions.
They drowned because +0x60 is a common struct offset. Two filters make it
readable: only an IMMEDIATE store can introduce a constant (a register store
just propagates one), and item-record code is recognisable by touching +0x4c
(cardtype) or +0x5c (itemState) within a few instructions.
Measured read-only against pid 6580:
- live +0x60 over all 27 resident records: {1: 23 players, 0: 4 staff}, never 4
- CardsDLL has 4 comparisons of +0x60 (0, 0, 1, 4); the 4 is the kit gate and
is the ONLY such comparison in the process
- CardsDLL has 29 immediate stores to +0x60, constants {-2,0,1,908,0x3f800000}
- FIFA17.exe, across 79 MB of code: ZERO stores of 4, zero comparisons with 4
- the gate function has one xref (a jmp) and its address is never taken
- every register store to +0x60 in CardsDLL is a struct copy or an init
So the gate is not a wire field we failed to send: the value it demands is never
produced by anything. Decoding it fully also shows every OTHER input is already
served — cardtype 7, itemState 101/102, teamid — leaving only the +0xba variant
selector beneath it, which makes a client-side patch the only remaining avenue.
This commit is contained in:
@@ -528,13 +528,6 @@ effects move in the permissive direction. There is also a second escape hatch in
|
||||
that gate -- `svc->0x308()` on service `0xed80ed8` -- that nobody resolved, so if
|
||||
squad submission behaves oddly afterwards, that is where to look.
|
||||
|
||||
**"List on Transfer Market" as a separate menu entry was not found.** The eight
|
||||
flags contain `TO_TRADE_PILE` and no listing action. `FUN_18003e550` publishes
|
||||
`DURATION` / `START_PRICE` / `ASKING_PRICE`, which is the listing panel, but
|
||||
whether it has its own enable predicate was not chased. The likely explanation is
|
||||
that listing is only reachable from the trade pile, so both entries share one root
|
||||
cause, but that is an inference and it is not established.
|
||||
|
||||
### Equipping club items
|
||||
|
||||
`itemState` really is the equip mechanism for the `IS_ACTIVE` tick:
|
||||
@@ -553,12 +546,29 @@ will not change the kit.
|
||||
|
||||
### Needs decompiling only
|
||||
|
||||
**Who writes item `+0x60`.** It gates the kit swap at value 4 and we can produce 1
|
||||
and 6. Both attempts to scan for it drowned: `+0x60` returns 1688 and 4144
|
||||
instructions depending on method. The narrower anchor is the `/club` and
|
||||
`/purchased` response handlers -- find the list-insert that assigns it, read the
|
||||
constants. This is the single blocker between "we can mark a kit equipped" and "we
|
||||
can equip a kit".
|
||||
**Who writes item `+0x60`. ANSWERED 2026-08-21 — NOTHING DOES.** It gates the kit
|
||||
swap at value 4 and we can produce 1 and 6. Both earlier scans drowned (`+0x60`
|
||||
returns 1688 and 4144 instructions) because it is a common struct offset. Two
|
||||
filters cut it to a readable set: only an IMMEDIATE store can introduce a
|
||||
constant, and item-record code is recognisable by touching `+0x4c`/`+0x5c`
|
||||
nearby. Measured with `fifa17-recon/tools/kit_gate_probe.py` against pid 6580:
|
||||
|
||||
| evidence | result |
|
||||
|---|---|
|
||||
| live `+0x60`, all 27 resident records | `{1: 23 players, 0: 4 staff}` — never 4 |
|
||||
| `cmp dword [reg+0x60], imm8` in CardsDLL | 4 sites: `0`, `0`, `1`, `4`; the `4` is the gate and is UNIQUE in the process |
|
||||
| immediate stores to `[reg+0x60]`, CardsDLL | 29; constants `{-2, 0, 1, 908, 0x3f800000}` — no 4 |
|
||||
| immediate stores of 4, FIFA17.exe (79 MB) | 0; also 0 comparisons against 4 |
|
||||
| xrefs to the gate function | 1 (`jmp` from `0x1801a5329`); address never taken |
|
||||
| register stores to `+0x60`, CardsDLL | all struct copies or inits to 0/1/-2 |
|
||||
|
||||
So the blocker is not a wire field we have not learned to send: the value the
|
||||
gate demands is never produced by anything. Every OTHER input to the gate is
|
||||
already served — `+0x4c == 7` (subtype 9), `+0x5c` 101/102
|
||||
(`activeHomeKit`/`activeAwayKit`), `+0x94` teamid — leaving only the `+0xba`
|
||||
variant selector below it. A client-side patch is therefore the only remaining
|
||||
avenue, and a small one; it is not proposed here.
|
||||
|
||||
|
||||
**The kit variant selector.** `FUN_1801bfac0` distinguishes home, away and third
|
||||
kits from `FUN_1801a8800` (`+0xba`, u16) and `FUN_1801a8040` (`+0xbf`, signed
|
||||
|
||||
Reference in New Issue
Block a user