diff --git a/fifa17-recon/data/futSelectTeam.syms b/fifa17-recon/data/futSelectTeam.syms new file mode 100644 index 0000000..df537b2 --- /dev/null +++ b/fifa17-recon/data/futSelectTeam.syms @@ -0,0 +1,934 @@ +k|J| +tz^WU +Gb\X[ +,j|L +cXXXX +gzW[rp +)l``b` +c^^^^ +zrbnz +r--) +&jzzx +Jl``` +c^^^\ +---- +k|X\^_ +c\Xxx +K|bjk +cxxxx +---% +{xx| +cxxxz +Frxz +{VVVW +cpxz~ +gr*: +sTVUU +cxz^W +[5555 +px~M +cUUU5 +cUU- +gz((+ +&rX` +&kVX +cUUUx +&r^\ +%%%% +&kUW +f[UUW +gcE[ +$gcE[ +cUU% +UUWT +xxxx +FsUU^ +$ecF[ +icD[ +T\Rb +sUW| +UUU\ +VUUU +BIGF +L286 +Apt Data:1:7:8 +game/globalComponents/globalComponents +game.globalComponents.ImageLoader +game/components/SelectTeam +game.components.SelectTeam +Coins +TournamentData +BackingFUT +VersusFUT +external.ion_fut.screens.futSelectTeam +__Packages.external.ion_fut.screens.futSelectTeam +__Packages.ion.manager.HelpProperties +EACondBold +10.000 +Screen +RtIL +RYgO +7uOO +XsOY +2sOY +<@OY +BG&Y +3NuIL +7NuI +3NuI +3NstY +7uOY +&v>Y +&v>t +3NYN +7NYN +tOYZ +BG&v +NZGO +NZGOZu +uOZu +mcCup +txtPrizeHeading +txtCoins +mcCoin +mcBacking +txtVs +mcTournamentInfo +mcSelectTeam +mcVersusFUT +publishObject +dpID +nHomeKitID +nAwayKitID +keyCode +controllerId +nSide +arrKitIDs +teamId +kitToResolve +side +isUser +arrKits +objProperties +Void +nXPos +DDS | +NVTT +DXT5 +8VTTT +UUVT +TTTU +0TUVT +TTUW +$$r +%UUU +WUUU +UUUSP +UUUM +UUUNK +72Ib +*72Ib +U;8I +WWWW?>I +UIFI +WWWWLKI +WWWVQNI +VVYVI +`]IB +daIB +heIB +VlhI +vtI"I +UU%!I +*;8I +U?>I +ULKI +Apt1 +_global +external +Object +ion_fut +screens +futSelectTeam +futSelectTeam::futSelectTeam() +OnExitScreen +cafe +utility +Delegate +Create +game +globalClasses +ScreenManager +SetOnExitScreenCallback +m_nFlowState +EA_ZONE +gScreenFlowManager +getFlowState +ION_Platform +IsFinal +CardNotification +eState +FUT_OFFLINE_DRAFT +FUT_OFFLINE_TOURNAMENT +FUT_OFFLINE_SEASON +m_bAllowSelectAnyTeam +FUT/ALLOW_ANY_CPU_TEAM +ION_Customization +GetAardvarkIntValue +mcPanelHome +mcPanelAway +mcReadyHome +mcReadyAway +mcKitHome +mcKitAway +mcLockHome +mcLockAway +InitComponents +InitializeScreen +Initialize +screen +BaseScreen +prototype +futSelectTeam::InitializeScreen() +_visible +HOME_SIDE +GameServices +eTeamSide +SIDE_HOME +AWAY_SIDE +SIDE_AWAY +NEUTRAL_SIDE +SIDE_NEUTRAL +m_arrPanelData +Array +m_arrKitPanelData +futSelectTeam::InitComponents() +InitializeKitConfig +InitializeTeamConfig +SetTeamAndKitConfigs +UIFDataProviderList +FUT_USER_CLUB_DATA_DP +UIFUtility +RegisterDataProvider +FUT_OPPONENT_CLUBS_LIST_DP +FUT_OPPONENTS_SQUADS_LIST_DP +FUT_OPPONENT_SQUAD_LINEUP_DP +FUT_USER_SQUAD_LINEUP_DP +FUT_CREATE_MATCH_DP +FUT_GET_MATCH_KITS_DP +SetupReadyTexts +initSideInfo +SetPanels +m_arrPanels +m_arrKitPanels +KitSelectDP +TeamSetupDP +AnimateIn +AnimateInComplete +BeginAnimateIn +futSelectTeam::AnimateInComplete() +m_bHasAnimatedIn +checkForDisconnect +gScreenNotAborted +LocalEventHandler +InputManager +AddLocalEventHandler +SetHandlerId +refreshCurrentConnectionStatus +HelpManager +Update +futSelectTeam::OnExitScreen() +AnimationManager +ClearAnimations +UnregisterDataProvider +INJURY_POPUP_ID +PopupManager +DeletePopup +TOTW_BELOW_MIN_POPUP_ID +USER_BELOW_MIN_POPUP_ID +OPP_BELOW_MIN_POPUP_ID +OPP_HAS_NO_VALID_SQUADS_ID +Shutdown +ClearSavedOpponentData +SQUAD_ID +UUID_UPPER +UUID_LOWER +UIFActionList +ACTION_SAVE_OPPONENT_DATA +SendActionObj +Publish +futSelectTeam::Publish() +header +USER_CLUB_DATA +SetUserClubData +initVersusFUTComponents +OPPONENT_CLUBS +m_arrOpponentClubs +data +MATCH_CREATED +FUT_PAFC_GAME +GetCurrentCountryIndex +SQUADS +GetCurrentLeagueIndex +ACTION_ADVANCE +SendAction +eSoundEvent +PRIMARY_SELECT +playSound +m_bShouldWaitForPublish +OPP_SQUADS_LIST +SetOpponentSquadListData +SQUAD_LINEUP_LOADED +IS_USER +SetSquadLineup +KITS_AVAILABLE +LENGTH +KIT_ +push +futSelectTeam::InitializeKitConfig() +SetupTeamsInfo +GetHomeTeamId +ACTION_MATCHDAY_HOME_TEAM_CHANGE +GetAwayTeamId +ACTION_MATCHDAY_AWAY_TEAM_CHANGE +ACTION_MATCHDAY_ADVANCE_KIT_SETUP +SetReadyStatus +FadeOut +GetKitArrayForFUT +HOME_KIT_ID +AWAY_KIT_ID +ION_Uniform +IsKitSelectCreated +EnterKitSelect +IsAlternatingMode +GetUnhighlightedSide +SetKitUnReady +InitializeKitsFromArray +Unhighlight +SetDisabled +SetHighlightedSide +GetHighlightedSide +Highlight +futSelectTeam::InitializeTeamConfig() +LEAGUE_ID +components +TeamSetupControl +TEAM_TOGGLE +GetUserSideForFUT +m_isInFUT +InitData +GetToggleValue +UpdateTeamInfo +m_bOpponentTeamInvalid +m_OppHasSquads +SetChemistryValue +ResetTeamInfo +FadeIn +SetupMouseSupport +SetWomenTeamsOnlyFilter +SetMenTeamsOnlyFilter +DeactivateReady +futSelectTeam::SetupTeamsInfo() +USER_TEAM_ID +ION_GameSetup +GetTeam +SetHomeTeamId +SetAwayTeamId +setCustomSelectionArray +Team +eAttribute +ION_Team +GetAttributes +futSelectTeam::LocalEventHandler() +WARNING: Preventing the user to move until a Publish occurs. +IsInTransition +Stop spamming buttons, the team select screen is in a transition. +GetUserControllerSide +GetScreenState +DataProviders +STATE_TEAM +InputCodes +LEFT +RIGHT +GetReadyStatus +DOWN +BACK +ADVANCE +OPTION_TOP +OPTION_LEFT +IsSwitchSidesActive +STATE_KIT +SetUniform +ExitKitSelect +RemoveKitLocks +ACTION_BACKOUT +CANCEL +SetKit +SaveKitsForMatch +FUT_TOTW_GAME +SetGoingToKickoffHub +SetHomeKitId +SetAwayKitId +GetHomeKitId +GetAwayKitId +ACTION_CREATE_MATCH +SetReady +SetKitReady +FUT_OPP_HAS_NO_VALID_SQUADS +PopupData +Okay_abbr2 +AddButton +ShowPopup +ValidateFullLineUp +m_sInjuryOrSuspendedWarning +m_bConceptPlayersInSquad +FUT_DB_Players_Not_Playable +FUT_TOTW_BELOW_MIN_PLAYERS +FUT_BELOW_MIN_PLAYERS +FUT_OPP_BELOW_MIN_PLAYERS +COUNTRY_TOGGLE +LEAGUE_TOGGLE +ACTION_GET_USER_SQUAD_LINEUP +ACTION_GET_OPPONENT_SQUAD_LINEUP +GoToViewSquad +PlatformManager +IsMicrosoft +USER_NAME +length +gEaso +showGamercard +getHelpContext +futSelectTeam::getHelpContext() +STATE_INVALID +FUT_VIEW_SQUAD_HOME +ltxt +manager +HelpItem +CreateHelpItem +FUT_VIEW_SQUAD_AWAY +ViewGamerCard +CreateHelpTickerItem +futSelectTeam::InitializeKitsFromArray() +GetAllAttributes +TYPE_UPPER +ITEM_NAME +ITEM_ID +ASSET_ID +StyleManager +FONT_TILE_HS +SetTitleTextFormat +SetToggleOffset +globalComponents +BasePanel +STYLE_FIFTEEN +SetBasePanelStyle +KIT_SCALE +kits +ToggleWithImage +STYLE_TOGGLE +SetStrokeVisibility +CheckIsKitLocked +futSelectTeam::GetKitArrayForFUT() +GetNonConflictingUniformID +eSortType +SORT_ASCENDING +Uniform +eSortColumn +SORT_NONE +eFilter +FILTER_UNFILTERED +GetIDs +LOCKED +NAME +shift +futSelectTeam::initVersusFUTComponents() +text +Versus_abbr +_height +FUT_Tournament +GetOfflineActiveTournamentId +GetOfflineTournamentInfo +TROPHY_ID +trophy +getArtAssetPath +SCALE_ASPECT_CENTER +setScaling +setSize +setImage +FUT_UC_TOURNAMENT_BONUS +PRIZE_FINAL +ION_Localization +LocalizeInteger +_width +textWidth +FUT_COINS_OFFSET +futSelectTeam::GoToViewSquad() +isUserTeam +CLUB_NAME +BADGE_TEAM_ID +SQUAD_NAME +RATING +SQUAD_RATING +CHEMISTRY +SQUAD_CHEMISTRY +SHOW_CHEM_LINE +SCREEN +VIEW_SQUADS +setContextDataObject +loadOverlayScreen +futSelectTeam::SetUserClubData() +m_arrUserClubs +PUBLIC +CLUB_ABBR +EST_DATE +ACTIVE_SQUAD_ID +SIDE_NAME +Away_Side +Home_Side +futSelectTeam::SetOpponentSquadListData() +split +FUT_NO_VALID_SQUADS +futSelectTeam::SetSquadLineup() +SetTeam +futSelectTeam::GetCurrentCountryIndex() +futSelectTeam::GetCurrentLeagueIndex() +futSelectTeam::GetUserSideForFUT() +bIsDemo +GetLockRules +SIDE_LOCK +futSelectTeam::ValidateFullLineUp() +FUT_SquadManagement +GetOpponentSquadLineup +GetSquadLineup +FUT_NUM_PLAYERS_IN_SQUAD +CARD_ID +ION_Card +GetPlayerCardInfo +IS_DREAM_PLAYER +FUT_NUM_PLAYERS_IN_SQUAD_EXTENDED +gFutHelpers +GetInjuryOrSuspendedSquadWarning +futSelectTeam::SaveKitsForMatch() +SIDE +NUM_KITS +ACTION_SAVE_MATCH_KIT +FUT_TOURNAMENT_CUP_SCALE +INJURY_OR_SUSPENDED_POPUP +TOTW_NUM_PLAYERS_BELOW_MIN_POPUP +USER_NUM_PLAYERS_BELOW_MIN_POPUP +OPP_NUM_PLAYERS_BELOW_MIN_POPUP +OPP_HAS_NO_VALID_SQUADS +SCALE_NONE +SCALE_ASPECT +SCALE_ABSOLUTE +ASSetPropFlags +HelpProperties +mXPos +GetXPos +SetXPos +registerClass +hj\W +hj/U +UUUV +'Z`XV +j`XVW +b$9^ +UW^} +hb>x +DA__\X +UWW^ +HbCA +hjCA/ ++{dA +b#9X7* +I^^|x +(Z``pP +Zxp` +\j~X +&j\xp +jXXXX +Fn%Vb= +xxxp +xh`` +WWWW +r\XXX +xxz_ +{XPpr +Hb__^\ +`x|x +``xX +]{jp +xxhh +X\\\ +U\T_ +`pz~ +_^^^ +cq,6 +-/+*+ +jjjj +jJJj +_^Xp +WV\p +TTWU +```h +pWUU +\UUU +$I"> +x^UU +/UUU +$IR`m +$IL# +cAxW +dI/U +&b%W +|UWV\ +j_uyQ +|UUVT +|WT\\ +j`ppp +|\\\\ +bpppp +)--- +||x|| +bzzzz +s"#)5 +K{&R +D(tFR``` +j5555 +){zxh` +hlUU_` +$Ithd +Ithd +hlUWVT +s(ljj +HR{O +IBww +@Bbb +Hl\\Xx +zzhh +@`pP +Htxxxx +hlHd +Ht%%%5 +ZZ\\ +H|xxxx +Hthd +xxxX +TV_] +H|hd +Xxx` +_\|p +pppP +H|xxxz +i|%%%5 +pX\T +H|xzzz +(dHt +H|`xz_ +UU^p +$G|(t +G|(t +(tG\ +VTTT +kUUU5 +(pXxx +XXXX +KOKK +'cUU^ +hs'c +$Gk(c +Gk(c +~ZZX +GkUWx +GkUUU\ +'Gk(c +p``H +zUU~ +X`pxZ +sUWx +c``` +@@@@ +WVT\ +Vw~U +_^_j +\XPp +^|~^ +c``pX\ +```` +UUUU +\\\\ +???? +p~UU +Ib'b +X\WU +A*++ +UUUX +VWUU +z^VW + W^x +\\\\j +TWVV +\^xx + W^~ + VWVt +cI^xxp +k$)WWVT +)W_VT +$1VTVT +(\\\\ +\\\\" +$1\\XX +pr`z +AXPp` +yU^r^ +$I2,r +PZrC +U{Bz +{||Z +kkki +c`p^ +cx6l +\\\\] +dIb`@@ +pvv] +'z@@ +XVUU +e9`p +UVVV +(.-5 +JJJJ +cQxxx +(%-)+ +VVVV +#9ZZxx +i-)- +1U_| +#9=* +VVTT +T\\X +X^__ +5-)+ +$I"'r + rrbJ +8)-%5 + ZZZZ +jjjk +1^UUU +g1G)^ +!XX\V +BIGF0 +Apt Data:1:5:8 +U555 +Urpp +~B'j +5555 +m*(( +;RRRR +m*** +:RRRR +`15555 +sZPPP +`95555 +Apppp +95555 +{PPPR +RRRR +rrp_ +&j2' +pppp +Ns%!U +%)%%%% +f)%! +` 6dC.kE! +Z%)70 +1E!W +1E!U +f1E! +F1Xp* +9f)U +xUU\ +JV~No +(n{$! +iJPPpp + +U`X\Y +h035^ +Lw!f +&T@a +]8RR +[OAq +D/Oz%F ++1.^- +_,_Y +..^O +CG|!@ +;}>| +nHT* +a8Nj +?'Un70 +^[zM2Bj @ +6nd[N +Z)MBc +wY=A +8p(a +:m"D +[dbt +E'0S +nT+bJuZ +V-:t +v)(n +(*s?p +cc?r +B%{r +-4Yi +sci,Iy +|3;= +o ++:Z/Y +]:AY +$(+~ +,^:(, +kp>C +luqYql +wf_q +XYX\ +@p77 +--X&q +{ cf +waF, +znrn; +VRwCE +5=#& +/J"} +_A4Z +gnB7% +q`Y +Q|!+ +[MMA +**rV +)~U(w*,)m +Z*SVd +$#&qi +qmUW= +F"MN +HaA%e% +(T!]5(\ +IK#k +v wQ +C(\M +];%P +7f&=kJ +%(oRtK +gRr? ++rq_ +/==7 +,IUk +D?t(zC, +\}oe +'^YY +nwzu +jdf, +i5hFc +z@xOrFp +aqgv +y^oT+ +dZ13 +d{g~ +ttzi +p,@B +upqH +1{pl0 +J4)~ +&W<;@ +p77Es +:aPw +`>(^& +lnW| +~+w8 diff --git a/fifa17-recon/tools/find_apt_in_cas.py b/fifa17-recon/tools/find_apt_in_cas.py new file mode 100755 index 0000000..13feae8 --- /dev/null +++ b/fifa17-recon/tools/find_apt_in_cas.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python3 +"""Find an APT/ActionScript symbol inside the FIFA 17 Frostbite .cas archives. + +Frosty is a GUI-only tool and its Legacy Explorer is the documented way to reach +these assets, but the chunks holding APT ActionScript are stored plainly enough to +grep — so a screen can be identified, and its whole symbol table recovered, +without driving the GUI at all. + +ALWAYS passes a control first: `KitAssignmentPopup` is a string from an +already-exported BIG, so if it misses, the archives are packed differently than +assumed and no negative from this tool may be quoted. + + python3 find_apt_in_cas.py FUT_GET_MATCH_KITS_DP + python3 find_apt_in_cas.py --dump 0x3707ecd7 fifa_installpackage_01/cas_01.cas +""" +import argparse +import glob +import os +import re +import sys + +ROOT = "/mnt/games/FIFA 17" +CONTROL = b"KitAssignmentPopup" + + +def cas_files(): + return sorted(glob.glob(os.path.join(ROOT, "**", "*.cas"), recursive=True)) + + +def find(needle: bytes): + control_total = 0 + hits = [] + for p in cas_files(): + d = open(p, "rb").read() + control_total += d.count(CONTROL) + start = 0 + while True: + i = d.find(needle, start) + if i < 0: + break + hits.append((p, i)) + start = i + 1 + return control_total, hits + + +def dump(path, off, span=90000): + with open(path, "rb") as f: + f.seek(max(0, off - span // 2)) + d = f.read(span) + seen = [] + for m in re.finditer(rb"[ -~]{4,}", d): + t = m.group().decode("latin1") + if t not in seen: + seen.append(t) + return seen + + +def main(): + ap = argparse.ArgumentParser() + ap.add_argument("needle", nargs="?") + ap.add_argument("--dump", metavar="OFFSET") + ap.add_argument("--file") + args = ap.parse_args() + + if args.dump: + path = args.file if os.path.isabs(args.file or "") else os.path.join( + ROOT, "Data/Win32/superbundlelayout", args.file or "") + for s in dump(path, int(args.dump, 0)): + print(s) + return 0 + + if not args.needle: + ap.error("needle required") + ctl, hits = find(args.needle.encode()) + print(f"control {CONTROL.decode()}: {ctl} hit(s)") + if ctl == 0: + print("CONTROL FAILED — archives not greppable this way; no negative is valid.") + return 1 + print(f"{args.needle}: {len(hits)} hit(s)") + for p, i in hits[:20]: + print(f" {os.path.relpath(p, ROOT)} @ {i:#x}") + return 0 + + +if __name__ == "__main__": + sys.exit(main())