Congratulations /k/! | ||
Winners of the 2024 4chan Autumn Babby Cup |
SEN:P-AI/Game Memory Layout/PES2017
Player Stats Table
The Stats Table is an internal memory structure in PES17 containing all player stats that can be seen in the post-match screens but also a considerable number of "hidden stats" not displayed anywhere in the game.
It is dynamically allocated in memory by PES at the very beginning of the match, just before the first touch (not during the anthem cutscenes), updated in real-time for the duration of the match, and de-allocated from memory upon exiting the post-match results screen.
The most common location for the stats table is as specified:
- In a block of memory 0x90000 Bytes (144 4KiB Pages) in size, Committed, marked Private, with ReadWrite protection
- The Home team's stats table begins at offset 0x35010 from the start of the block
- The Away team's stats table begins 0x28E30 bytes after the home offset, or 0x5DE40 from the start of the block
This memory block location was originally thought to be hardcoded, but it was later discovered that it was only the result of a memory allocation pattern that rendered this particular method of finding the tables 95-80% accurate, with the accuracy decreasing the longer the game was running. This search pattern is still used by default, but a brute force search can also be used.
There is additional data before and possibly after both of tables that is part of the same fixed-layout data structure but has yet to be deciphered.
Player Stats Entry
Entry Count: 32 per team, in the same order as the Team-Player Table (Edit File)
Entry Length: 4784 (0x12B0) Bytes
ID | Offset | Length | Type | Description | Behavior |
---|---|---|---|---|---|
0 | 0x0000 | 4 Bytes | uint32 | Player ID | Fixed value, checking it is a good way to see if the table has been overwritten with garbage |
1 | 0x0004 | 36 Bytes | uint32x9 | Goals Scored | |
2 | 0x0028 | 36 Bytes | uint32x9 | Own Goals Scored | These next hundred or so "uint32x9" stats follow the same format:
The 36 bytes are broken into 9 "segments" of 32-bit integers. Each segment corresponds to 15 minutes of a match. Segments 1-3 are the 1st half, segments 4-6 are the 2nd half, segments 7 and 8 are the 1st and 2nd halves of Extra Time, and segment 9 is the Penalty Shootout. Injury time is counted as part of the last segment of the half. Stats are recorded separately for each segment, which means to get the actual value of the stat, you need to calculate the total of all 9 segments. |
3 | 0x004C | 36 Bytes | uint32x9 | Free kicks scored | |
4 | 0x0070 | 36 Bytes | uint32x9 | Penalties scored | |
5 | 0x0094 | 36 Bytes | uint32x9 | Assists | |
6 | 0x00B8 | 36 Bytes | uint32x9 | Shots | |
7 | 0x00DC | 36 Bytes | uint32x9 | Headers | |
8 | 0x0100 | 36 Bytes | uint32x9 | Shots (Strong Foot) | |
9 | 0x0124 | 36 Bytes | uint32x9 | Shots (Weak Foot) | |
10 | 0x0148 | 36 Bytes | uint32x9 | ?UNKNOWN 10 | Strongly correlated with goal scored |
11 | 0x016C | 36 Bytes | uint32x9 | Shots on Target | |
12 | 0x0190 | 36 Bytes | uint32x9 | Free kicks shot | Shots from free kicks in regular and extra time (default key: X. No matter from which half of the field is kicked, it is still considered a shot. Goal kicks are excluded since the game treats them as passes). |
13 | 0x01B4 | 36 Bytes | uint32x9 | Penalty kicks shot | Shots from (mid-match) penalties. |
14 | 0x01D8 | 36 Bytes | uint32x9 | Passes | Low Passes + Through Balls + Lofted/High Passes + Crosses = (total) Passes Ground Passes + Aerial Passes + Crosses == (total) Passes |
15 | 0x01FC | 36 Bytes | uint32x9 | Passes Made | |
16 | 0x0220 | 36 Bytes | uint32x9 | Low Passes | Low passes (default key: A) |
17 | 0x0244 | 36 Bytes | uint32x9 | Low Passes Made | |
18 | 0x0268 | 36 Bytes | uint32x9 | Through Balls | Low Through Ball (default key: Y) + Chipped Through Ball (default key: LB + Y) |
19 | 0x028C | 36 Bytes | uint32x9 | Through Balls Made | |
20 | 0x02B0 | 36 Bytes | uint32x9 | Lofted/High Passes | Lofted Pass (default key: B) + High Pass (default key: RT + B) |
21 | 0x02D4 | 36 Bytes | uint32x9 | Lofted/High Passes Made | |
22 | 0x02F8 | 36 Bytes | uint32x9 | Crosses | |
23 | 0x031C | 36 Bytes | uint32x9 | Crosses Made | Crosses where the sticker get the ball (the same way the game determinates when a pass in made or not). |
24 | 0x0340 | 36 Bytes | uint32x9 | Ground Passes | Low Passes + Low Through Ball (low passes) |
25 | 0x0364 | 36 Bytes | uint32x9 | Ground Passes Made | |
26 | 0x0388 | 36 Bytes | uint32x9 | Aerial Passes | Lofted/High Passes + Chipped Through Balls (lofted passes) |
27 | 0x03AC | 36 Bytes | uint32x9 | Aerial Passes Made | |
28 | 0x03D0 | 36 Bytes | uint32x9 | Low Through Balls | Low Through Ball (default key: Y) |
29 | 0x03F4 | 36 Bytes | uint32x9 | Low Through Balls Made | |
30 | 0x0418 | 36 Bytes | uint32x9 | Chipped Through Balls | Chipped Through Ball (default key: LB + Y) |
31 | 0x043C | 36 Bytes | uint32x9 | Chipped Through Balls Made | |
32 | 0x0460 | 36 Bytes | uint32x9 | ?Forward Passes | (The part where I gave up trying to find correlations but still saw similar patterns to the above) Not sure about these three, but maybe: forward passes |
33 | 0x0484 | 36 Bytes | uint32x9 | ?Forward Passes Made | |
34 | 0x04A8 | 36 Bytes | uint32x9 | ?Lateral Passes | Passes between two players on (almost) the same line |
35 | 0x04CC | 36 Bytes | uint32x9 | ?Lateral Passes Made | |
36 | 0x04F0 | 36 Bytes | uint32x9 | ?Backward Passes | Backward passes |
37 | 0x0514 | 36 Bytes | uint32x9 | ?Backward Passes Made | |
38 | 0x0538 | 36 Bytes | uint32x9 | Tackles | |
39 | 0x055C | 36 Bytes | uint32x9 | Tackles Won | |
40 | 0x0580 | 36 Bytes | uint32x9 | ?UNKNOWN 40 | |
41 | 0x05A4 | 36 Bytes | uint32x9 | ?UNKNOWN 41 | |
42 | 0x05C8 | 36 Bytes | uint32x9 | ?UNKNOWN 42 | Correlated with Tackles and/or Tackles Won. |
43 | 0x05EC | 36 Bytes | uint32x9 | Clearances | |
44 | 0x0610 | 36 Bytes | uint32x9 | Fouls | |
45 | 0x0634 | 36 Bytes | uint32x9 | Fouls Offside | |
46 | 0x0658 | 36 Bytes | uint32x9 | Yellow Cards | For some reason, the exact moment these stats are updated depends on the particular card cutscene used |
47 | 0x067C | 36 Bytes | uint32x9 | Red Cards | |
48 | 0x06A0 | 36 Bytes | uint32x9 | ?UNKNOWN 48 | |
49 | 0x06C4 | 36 Bytes | uint32x9 | ?UNKNOWN 49 | |
50 | 0x06E8 | 36 Bytes | uint32x9 | Free Kicks | |
51 | 0x070C | 36 Bytes | uint32x9 | ?UNKNOWN 51 | |
52 | 0x0730 | 36 Bytes | uint32x9 | Corner Kicks | |
53 | 0x0754 | 36 Bytes | uint32x9 | ?UNKNOWN 53 | |
54 | 0x0778 | 36 Bytes | uint32x9 | ?UNKNOWN 54 | |
55 | 0x079C | 36 Bytes | uint32x9 | ?UNKNOWN 55 | |
56 | 0x07C0 | 36 Bytes | uint32x9 | Touches | (These appeared to have some correlation to the total touches) It looks like that type of Touches is not related to the kind of Passes and it may depends also on how the player stops the ball. Also A_Touches (and maybe B_Touches and C_Touches as well) can be greater than Touches. |
57 | 0x07E4 | 36 Bytes | uint32x9 | ?A_Touches | |
58 | 0x0808 | 36 Bytes | uint32x9 | ?B_Touches | |
59 | 0x082C | 36 Bytes | uint32x9 | ?C_Touches | |
60 | 0x0850 | 36 Bytes | uint32x9 | ?UNKNOWN 60 | |
61 | 0x0874 | 36 Bytes | uint32x9 | ?UNKNOWN 61 | |
62 | 0x0898 | 36 Bytes | uint32x9 | ?UNKNOWN 62 | |
63 | 0x08BC | 36 Bytes | uint32x9 | Interceptions | |
64 | 0x08E0 | 36 Bytes | uint32x9 | ?A_Interceptions | (These appeared to have some correlation to the total interceptions) |
65 | 0x0904 | 36 Bytes | uint32x9 | ?B_Interceptions | |
66 | 0x0928 | 36 Bytes | uint32x9 | ?C_Interceptions | |
67 | 0x094C | 36 Bytes | uint32x9 | ?D_Interceptions | |
68 | 0x0970 | 36 Bytes | uint32x9 | ?UNKNOWN 68 | |
69 | 0x0994 | 36 Bytes | uint32x9 | ?UNKNOWN 69 | |
70 | 0x09B8 | 36 Bytes | uint32x9 | ?UNKNOWN 70 | |
71 | 0x09DC | 36 Bytes | uint32x9 | ?UNKNOWN 71 | |
72 | 0x0A00 | 36 Bytes | uint32x9 | ?UNKNOWN 72 | |
73 | 0x0A24 | 36 Bytes | uint32x9 | ?UNKNOWN 73 | |
74 | 0x0A48 | 36 Bytes | uint32x9 | ?UNKNOWN 74 | |
75 | 0x0A6C | 36 Bytes | uint32x9 | ?UNKNOWN 75 | |
76 | 0x0A90 | 36 Bytes | uint32x9 | ?UNKNOWN 76 | |
77 | 0x0AB4 | 36 Bytes | uint32x9 | ?UNKNOWN 77 | |
78 | 0x0AD8 | 36 Bytes | uint32x9 | ?UNKNOWN 78 | |
79 | 0x0AFC | 36 Bytes | uint32x9 | ?UNKNOWN 79 | |
80 | 0x0B20 | 36 Bytes | uint32x9 | ?UNKNOWN 80 | |
81 | 0x0B44 | 36 Bytes | uint32x9 | ?UNKNOWN 81 | |
82 | 0x0B68 | 36 Bytes | uint32x9 | ?UNKNOWN 82 | |
83 | 0x0B8C | 36 Bytes | uint32x9 | ?UNKNOWN 83 | |
84 | 0x0BB0 | 36 Bytes | uint32x9 | ?UNKNOWN 84 | |
85 | 0x0BD4 | 36 Bytes | uint32x9 | ?UNKNOWN 85 | |
86 | 0x0BF8 | 36 Bytes | uint32x9 | ?UNKNOWN 86 | |
87 | 0x0C1C | 36 Bytes | uint32x9 | ?UNKNOWN 87 | |
88 | 0x0C40 | 36 Bytes | uint32x9 | ?UNKNOWN 88 | |
89 | 0x0C64 | 36 Bytes | uint32x9 | ?UNKNOWN 89 | |
90 | 0x0C88 | 36 Bytes | uint32x9 | ?UNKNOWN 90 | |
91 | 0x0CAC | 36 Bytes | uint32x9 | ?UNKNOWN 91 | |
92 | 0x0CD0 | 36 Bytes | uint32x9 | ?UNKNOWN 92 | |
93 | 0x0CF4 | 36 Bytes | uint32x9 | ?UNKNOWN 93 | |
94 | 0x0D18 | 36 Bytes | uint32x9 | ?UNKNOWN 94 | |
95 | 0x0D3C | 36 Bytes | uint32x9 | ?UNKNOWN 95 | |
96 | 0x0D60 | 36 Bytes | uint32x9 | ?UNKNOWN 96 | |
97 | 0x0D84 | 36 Bytes | uint32x9 | ?UNKNOWN 97 | |
98 | 0x0DA8 | 36 Bytes | uint32x9 | ?UNKNOWN 98 | |
99 | 0x0DCC | 36 Bytes | uint32x9 | ?UNKNOWN 99 | |
100 | 0x0DF0 | 36 Bytes | uint32x9 | ?UNKNOWN 100 | |
101 | 0x0E14 | 36 Bytes | uint32x9 | ?UNKNOWN 101 | |
102 | 0x0E38 | 36 Bytes | uint32x9 | ?UNKNOWN 102 | |
103 | 0x0E5C | 36 Bytes | uint32x9 | ?UNKNOWN 103 | |
104 | 0x0E80 | 36 Bytes | uint32x9 | ?UNKNOWN 104 | |
105 | 0x0EA4 | 36 Bytes | uint32x9 | ?UNKNOWN 105 | |
106 | 0x0EC8 | 36 Bytes | uint32x9 | ?UNKNOWN 106 | |
107 | 0x0EEC | 36 Bytes | uint32x9 | ?UNKNOWN 107 | |
108 | 0x0F10 | 36 Bytes | uint32x9 | ?UNKNOWN 108 | |
109 | 0x0F34 | 36 Bytes | uint32x9 | ?UNKNOWN 109 | |
110 | 0x0F58 | 36 Bytes | uint32x9 | Shots Faced | |
111 | 0x0F7C | 36 Bytes | uint32x9 | Shots Faced On Target | |
112 | 0x0FA0 | 36 Bytes | uint32x9 | Saves | |
113 | 0x0FC4 | 36 Bytes | uint32x9 | ?Saves On Target | (appears to be correlated to Saves in the same way other "(on target)" stats are, but I'm not entirely sure what it means, maybe that the shot saved was on target?) Only shots in the area are count for this stat, even if they are not on target. Shots saved from outside the box do not add value to this stat. It looks like the word "target" means "area" here. Saves in penalty shootout are not counted. |
114 | 0x0FE8 | 1 Byte | sint8 | First Minute on Pitch | when the player was first subbed on, 0 for starting players, -1 for benched players until they're subbed on |
115 | 0x0FE9 | 1 Byte | sint8 | Last Minute on Pitch | when the player was last on the pitch, -1 for benched players, for currently playing players this USUALLY matches the game clock but for recently subbed players, PES rounds it up to the next minute just to fuck with you. Players in undergoing treatment are counted on the pitch. |
116 | 0x0FEA | 1 Byte | uint8 | ?UNKNOWN 116 | |
117 | 0x0FEB | 1 Byte | uint8 | ?UNKNOWN 117 | |
118 | 0x0FEC | 1 Byte | uint8 | ?UNKNOWN 118 | |
119 | 0x0FED | 1 Byte | uint8 | ?UNKNOWN 119 | |
120 | 0x0FEE | 1 Byte | uint8 | ?UNKNOWN 120 | |
121 | 0x0FEF | 1 Byte | uint8 | ?UNKNOWN 121 | |
122 | 0x0FE0 | 4 Bytes | uint32 | ?UNKNOWN 122 | |
123 | 0x0FF4 | 4 Bytes | uint32 | Current Playing Position | [0-12] with the same values as the Edit File |
124 | 0x0FF8 | 52 Bytes | uint32 | Game Ticks Played | An array of 13 32-bit integers, each one corresponding to a playing position. Each element contains the number of "ticks" the player has spent playing in that position. The total sum of the array is the number of ticks the player, which is exact and the same for all unsubbed starting players. 1 real-time seconds is about 48 ticks, with what seems like no relation to framerate. 1 Game Minute is exactly 32*{Match Length Setting} ticks (320 for 10 minute matches). |
125 | 0x102C | 4 Bytes | uint32 | ?UNKNOWN 137 | (around 16840000 for Captians, 16770000 for other players, increases by some low number every so often) |
126 | 0x1030 | 4 Bytes | float32 | Player Rating | A 32-bit floating point number. Matches the rating exactly, in increments of 0.5, no more exact. This leaves no (known) way to determine Man Of The Match if there's a tie for highest rating. |
127 | 0x1034 | 560 Bytes | uint32 | Play Area Grid | This is an array of 140 32-bit integers representing a 10x14 grid of squares. About every real-time second, PES checks where each player is in this grid and increments the corresponding value. This is used to generate the pitch heat-map seen on the individual match records screen, however the highest intensity color it will show there corresponds to 12 seconds while most players will have one or more squares in the ballpark of 90 for a typical match. |
128 | 0x1264 | 4 Bytes | uint32 | Realtime (sec) on Pitch | Roughly the number of real-time seconds a player has been playing. For some reason this drifts by multiple seconds for players who should have been playing the exact same amount of time. |
129 | 0x1268 | 4 Bytes | uint32? | ?UNKNOWN 141 | (very high value) |
130 | 0x126C | 4 Bytes | uint32? | ?UNKNOWN 142 | Boolean value: 1 if player injured, 0 otherwise. (verification needed) |
131 | 0x1270 | 4 Bytes | uint32? | ?UNKNOWN 143 | (very high value, 0 for most/some players) |
132 | 0x1274 | 4 Bytes | uint32 | Stamina | Starts at 100 and periodically decreases throughout the match. During halftime/fulltime/extra-halftime, players will recover stamina in the UI but this value is not updated to match until the next half actually starts. |
133 | 0x1278 | 4 Bytes | uint32? | ?UNKNOWN 145 | Zero until the match starts. It constantly grows and it's related with player's movements across the pitch.
Apparently stamina, time on the pitch and many other stats do not affect this value. (may be related to calculating Average Speed) |
134 | 0x127C | 4 Bytes | uint32? | ?UNKNOWN 146 | Zero until the player makes a pass (no matter if completed or not), it grows every time the player passes the ball. Sometimes this rule is not followed and the value stays zero. Used to calculate Distance Dribbled, when 0, Distance Dribbled is also displayed as "0m". |
135 | 0x1280 | 4 Bytes | uint32? | ?UNKNOWN 147 | Zero until the player completes a pass, it grows after every completed pass. (very high value) |
136 | 0x1284 | 1 Byte | uint8 | ?UNKNOWN 148 FLAG | (Have no idea what these are for, but only the low bit is ever active, leading me to believe they're all Boolean flags) |
137 | 0x1285 | 1 Byte | uint8 | ?UNKNOWN 149 FLAG | |
138 | 0x1286 | 1 Byte | uint8 | ?UNKNOWN 150 FLAG | |
139 | 0x1287 | 1 Byte | uint8 | ?UNKNOWN 151 FLAG | |
140 | 0x1288 | 1 Byte | uint8 | ?UNKNOWN 152 FLAG | |
141 | 0x1289 | 1 Byte | uint8 | ?UNKNOWN 153 FLAG | |
142 | 0x128A | 1 Byte | uint8 | ?UNKNOWN 154 FLAG | |
143 | 0x128B | 1 Byte | uint8 | ?UNKNOWN 155 FLAG | |
144 | 0x128C | 1 Byte | uint8 | ?UNKNOWN 156 FLAG | |
145 | 0x128D | 1 Byte | uint8 | ?UNKNOWN 157 FLAG | |
146 | 0x128E | 1 Byte | uint8 | ?UNKNOWN 158 FLAG | |
147 | 0x128F | 1 Byte | uint8 | ?UNKNOWN 159 FLAG | |
148 | 0x1290 | 1 Byte | uint8 | ?UNKNOWN 160 FLAG | |
149 | 0x1291 | 1 Byte | uint8 | ?UNKNOWN 161 FLAG | |
150 | 0x1292 | 1 Byte | uint8 | ?UNKNOWN 162 FLAG | |
151 | 0x1293 | 1 Byte | uint8 | ?UNKNOWN 163 FLAG | |
152 | 0x1294 | 1 Byte | uint8 | ?UNKNOWN 164 FLAG | |
153 | 0x1295 | 1 Byte | uint8 | ?UNKNOWN 165 FLAG | |
154 | 0x1296 | 1 Byte | uint8 | ?UNKNOWN 166 FLAG | |
155 | 0x1297 | 1 Byte | uint8 | ?UNKNOWN 167 FLAG | |
156 | 0x1298 | 1 Byte | uint8 | ?UNKNOWN 168 FLAG | |
157 | 0x1299 | 1 Byte | uint8 | ?UNKNOWN 169 FLAG | |
158 | 0x129A | 1 Byte | uint8 | ?UNKNOWN 170 FLAG | |
159 | 0x129B | 1 Byte | uint8 | ?UNKNOWN 171 FLAG | |
160 | 0x129C | 1 Byte | uint8 | ?UNKNOWN 172 FLAG | |
161 | 0x129D | 1 Byte | uint8 | ?UNKNOWN 173 FLAG | |
162 | 0x129E | 1 Byte | uint8 | ?UNKNOWN 174 FLAG | |
163 | 0x129F | 1 Byte | uint8 | ?UNKNOWN 175 FLAG | |
164 | 0x12A0 | 1 Byte | uint8 | ?UNKNOWN 176 FLAG | |
165 | 0x12A1 | 1 Byte | uint8 | ?UNKNOWN 177 FLAG | |
166 | 0x12A2 | 1 Byte | uint8 | ?UNKNOWN 178 FLAG | |
167 | 0x12A3 | 1 Byte | uint8 | ?UNKNOWN 179 FLAG | |
168 | 0x12A4 | 1 Byte | uint8 | ?UNKNOWN 180 FLAG | |
169 | 0x12A5 | 1 Byte | uint8 | ?UNKNOWN 181 FLAG | |
170 | 0x12A6 | 1 Byte | uint8 | ?UNKNOWN 182 FLAG | |
171 | 0x12A7 | 1 Byte | uint8 | ?UNKNOWN 183 FLAG | |
172 | 0x12A8 | 4 Bytes | uint32 | ?UNKNOWN 184 | |
173 | 0x12AC | 4 Bytes | validPair | ?Next Player Valid | This structure is a set of two 16-bit values which I call a "team/player valid pair." The first value is 0xFFFD for a valid Home player, 0xFFFE for a valid Away player, or 0xFFFF for an invalid player. For an invalid player, the second value is 0, but for a valid player it's some arbitrary value that depends on the team but doesn't seem to have any obvious correlation to IDs or anything like that. |
Unknown stats which have unidentified or uncertian purposes/meaning have "?" in front of the name. If you figure out what one of these is please feel free to edit this page. Unknown stats can be displayed in SEN:P-AI by checking the "show hidden stats" box in the columns menu and then checking the corresponding box next to the stat.
Team Data Table
The team data table is an internal data structure in PES that holds all kinds of data, including tactical, about the two currently selected teams.
It is allocated (perhaps statically?) by PES as soon as the game launches (but is unpopulated and thus unable to be found until two teams are selected) and only deallocated when the game closes, staying in the same place for the entire duration of a particular PES17.exe instance.
The most common location for the stats table is as specified:
- In a block of memory 0x60000 Bytes (96 4KiB Pages) in size, Committed, marked Private, with ReadWrite protection
- Beginning at offset 0x538B4 from the start of the block
It is unknown whether this pattern is static or just extremely common, since the allocation only ever happens once per PES17.exe instance (and at the very start of the program where memory allocations would follow a very consistent pattern).
Overall Structure
The substructures mentioned in the following table are described further below.
Size: 18736 (0x4930) bytes
Offset | Length | Type | Description |
---|---|---|---|
0x0000 | 1312 bytes | Team Data | Home team data |
0x0520 | 1312 bytes | Team Data | Away team data |
0x0A40 | 632 bytes | Team Tactics | Home Team Tactics |
0x0CB8 | 632 bytes | Team Tactics | Away Team Tactics |
0x0F30 | 7424 bytes | (32x) Player Data | Home Team Players |
0x2C30 | 7424 bytes | (32x) Player Data | Away Team Players |