144 live cardtype-6 subtypes and 28 dead zones, all derived from the binary rather
than guessed, plus EA's own authored variants out of the dumped fcc_* tables.
MEASURED (decompiles read to their closing brace, lengths stated):
FUN_1800d8330 (714 chars) cardsubtypeid -> cardtype. The cardtype-6 space is
{51..136} u {201..220} u {250..273} u {300..341} = 172.
FUN_18013f4d0 (8,354 chars) subtype -> category(rec+0xb8), sub-sel(rec+0xbc i16),
amount(rec+0xbf i8), single(rec+0xc0). Two callees, a
range clamp and an enum map; no DB handle is touched,
which is why a consumable has no identity to look up.
FUN_1801bfac0 (42,813 chars) category -> FUT_CONSUMABLE_* string + a HARDCODED
5000xxx artwork constant. resourceId never reaches the
screen for a consumable.
fcc_trainingcards 143 rows / fcc_healingcards 27 / fcc_contractcards 13, each with
rowcount == rows_emitted == len(rows), so absences below are from a COMPLETE dump.
Two things the family will not forgive, both enforced in the builder rather than
documented and hoped for:
* `amount` (atom 0x1b) is MANDATORY for categories 0, 4, 5, 9, 10. The parser
initialises its temp to 0xffffffffffffffff, so omitting it stamps (byte)-1, and
the accessors FUN_1801a8040/FUN_1801a8060 are `(int)*(char *)` -- SIGNED. The
card reads "-1", not 0. consumable_item() raises instead.
* A DEAD-ZONE subtype does not self-label. It falls to the bottom default of
FUN_18013f4d0 and renders as an ordinary Squad Training (Pace) card with amount
0. There is no "DB Error" analogue here, so every subtype we ship comes from
data/consumables.json and the builder refuses the other 28.
Two corrections to the generated data, both from re-reading FUN_1801bfac0 case 5 and
case 0 rather than from the category table:
* subtype 220 is named FUT_CONSUMABLE_NAME_SQUADTRAINING, not ..._PLAYERFITNESS.
0xdc == 220 is the FIRST half of the squad-fitness test, so 220 always takes that
branch, and there is no ..._SQUADFITNESS string in the binary at all.
* all 28 dead zones are SQUADTRAINING, not PLAYERTRAINING: case 0 tests
`subtype - 0x33 < 7` then `subtype - 0x3d < 7` and no dead zone satisfies either.
Exactly 29 of 172 rows changed; nothing else moved.
INFERRED, and flagged as such in the module: the ?type= grouping. The vocabulary is
certain (FUN_18012ec50 arms healing=23, contract=24, training=25, development=6), but
the tab-to-arm binding has NEVER been observed -- only type=player, type=manager and
type=custom have ever come from this client.
Three families deliberately NOT shipped: manager_formation_mod (71-86) has zero rows
in the 143-row table AND FUN_1801bfac0 case 6 calls FUN_1801a0100 on the formations
result without the rowcount guard its twin case 7 has -- a crash candidate;
formation_mod (121-136) has artwork -1; manager_league (300-341) renders literally
"ML: %d" from a raw number and one shipped amount (2118) is in no league table.
Not wired into the server in this commit.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VUT92pz6RWKih9dSr8ZpxW
OpenFUT
Offline Ultimate Team — like SPT, but for FIFA 23.
OpenFUT replaces EA's retired FUT servers with a fully offline, single-player backend. You own FIFA 23 legitimately. You just want to keep playing after EA shut down the servers.
Repositories
| Repo | Purpose |
|---|---|
openfut-core |
Game-independent offline FUT backend |
openfut-bridge |
FIFA 23 integration layer + reverse-engineering proxy |
Architecture
FIFA 23 client
│
▼
┌─────────────────┐
│ openfut-bridge │ ← intercepts FUT traffic, maps routes, logs unknown
└────────┬────────┘
│
▼
┌─────────────────┐
│ openfut-core │ ← offline FUT backend: profiles, packs, squads, SBCs
└─────────────────┘
│
▼
SQLite database
Core is game-independent. It speaks a clean REST API and knows nothing about FIFA 23 internals.
Bridge is FIFA-specific. It speaks FIFA 23's wire protocol and translates it into Core API calls. Bridge is where all reverse engineering work happens.
Current Status
| Feature | Status |
|---|---|
| Local profiles + clubs | ✅ Working |
| Coin system | ✅ Working |
| Pack generator | ✅ Working |
| Card collection | ✅ Working |
| Squad builder | ✅ Working |
| Objectives engine | ✅ Working |
| SBC engine | ✅ Working |
| Match rewards | ✅ Working |
| NPC transfer market | ✅ Working |
| Statistics | ✅ Working |
| FIFA 23 integration | 🔴 Reverse engineering in progress |
| Chemistry calculation | 🟡 In progress |
| Full Draft mode | 🟡 In progress |
| Squad Battles AI generator | 🟡 In progress |
| Objectives claim flow | 🟡 In progress |
Running
# Start the offline backend
cd openfut-core
cargo run
# Start the proxy (for traffic capture / FIFA integration)
cd openfut-bridge
cargo run
Core listens on http://127.0.0.1:8080 by default.
Bridge listens on http://127.0.0.1:8443 by default.
Design Principles
- Offline-first. No EA account required. No internet connection needed.
- Single-player only. This is not a multiplayer server emulator.
- Data-driven. All cards, packs, SBCs, and objectives are JSON files. Everything is moddable.
- Clean architecture. Core has zero knowledge of FIFA 23. Bridge has zero game logic.
- No copyrighted assets. No real player images, no EA trademarks in data files.
Disclaimer
This project is not affiliated with EA Sports. You must own FIFA 23 legitimately to use this software. This project does not bypass any ownership verification and is intended only to restore offline playability of a game whose online services have been retired.