diff --git a/fifa17-recon/docs/plan-2026-08-06-card-subsystem.md b/fifa17-recon/docs/plan-2026-08-06-card-subsystem.md index aa9dac4..3e14abd 100644 --- a/fifa17-recon/docs/plan-2026-08-06-card-subsystem.md +++ b/fifa17-recon/docs/plan-2026-08-06-card-subsystem.md @@ -575,10 +575,31 @@ kits from `FUN_1801a8800` (`+0xba`, u16) and `FUN_1801a8040` (`+0xbf`, signed byte). Which wire atom sets it is unknown, so we cannot serve a specific kit deliberately. Note `+0xba` is the same slot as the unresolved ball subtitle. -**`FUN_1801aa190`.** The one unopened link inside the eight-flag chain: it is -claimed to resolve `statsList[4]` and `[5]` at `+0x104 + idx*4`. It changes no -action today because we send no `statsList`, but it is two minutes of work and it -would close the chain. +**`FUN_1801aa190`. CLOSED 2026-08-21.** The one unopened link inside the +eight-flag chain. It is eleven instructions, and it resolves TWO parallel arrays +rather than the one the earlier claim described: + +``` +mov rax, [rcx+0x10] ; the ITEM record (same +0x10 hop the kit gate uses) +test r8b, r8b +jz .low +mov eax, [rax + rdx*4 + 0x124] ; array B +ret +.low: +mov eax, [rax + rcx*4 + 0x104] ; array A <- the claimed statsList +ret +``` + +So the signature is `f(self, int idx, bool which)`: `+0x104 + idx*4` when the +flag is clear, `+0x124 + idx*4` when it is set. The two arrays are 0x20 apart, +i.e. eight ints each (`+0x104..+0x123`, `+0x124..+0x143`). + +LIVE (pid 6580, production-served records): BOTH arrays read all zeros on every +resident record, players included — e.g. resourceId 20801 rating 94 has +`A = [0]*8`, `B = [0]*8`. That confirms "changes no action today because we send +no statsList", and extends it: the sibling array at `+0x124` is equally empty. +Any action flag derived from either is reading 0 in production, so neither can +be the reason an action is greyed. **The `BOUGHT_FOR` consumer.** `+0x34` = atom `0x185 lastSalePrice` is resolved. What remains is whether the field is visible anywhere worth populating. @@ -628,11 +649,33 @@ the live save. **Re-read `+0x30` after a refetch** to decide between "monotonic clock" and "sequence counter". Low value; nothing we send reaches it. -**Confirm the FUT roster database is loaded.** The `fcc_discardcoins` result -proves `g_db` is loaded and complete; it says nothing about the separate database -behind `LoadFUTDatabase` / `.dbFUTVer` / `DL_FUT_LIVEDB`, whose strings live in -FIFA17.exe and not in CardsDLL. These are different databases and they should stop -being conflated. +**Confirm the FUT roster database is loaded. PARTLY ANSWERED 2026-08-21 — the +two databases are now definitively distinct; the load FLAG is still unlocated.** +The `fcc_discardcoins` result proves `g_db` is loaded and complete; it says +nothing about the separate database behind `LoadFUTDatabase` / `.dbFUTVer` / +`DL_FUT_LIVEDB`. Scanning FIFA17.exe's 79 MB of code+data in the live process +(pid 6580) recovers the whole API name set, and it settles the distinction: + +``` +SetFUTDatabaseUnloaded UpdateFUTDBVersion StartFUTRosterDownload +LoadFUTDatabase UnLoadFUTDatabase GetFUTDBCRC +CancelRosterDownload DL_FUT_LIVEDB APPLY_FUT_LIVEDB +RosterXMLDownloadedFail .dbFUTVer .dbMajor .dbMinor .dbMajorCRC .dbMinorCRC +``` + +Every one of those lives in FIFA17.exe; none is in CardsDLL. So the FUT roster +DB is a DOWNLOADED, versioned, CRC-checked live database with its own +download -> apply -> load/unload lifecycle (and its own failure state, +`RosterXMLDownloadedFail`), which is a different kind of thing from the shipped +card tables CardsDLL reads. They should stop being conflated, and this is the +evidence for saying so. + +What is NOT answered: whether it is loaded right now. The process holds no +separate database file open — only Frostbite bundles (`.sb` / `.cas`) — which is +consistent with the roster DB living inside a bundle or in memory, so absence of +a file handle proves nothing either way. The `SetFUTDatabaseUnloaded` state +implies a boolean somewhere; that global was not located, so "is it loaded" +remains open and needs the flag found before it can be answered honestly. ### Needs a launch the user must drive -- ranked, and short