Congratulations /k/! | ||
Winners of the 2024 4chan Autumn Babby Cup |
Difference between revisions of "SEN:P-AI/Game Memory Layout/PES2017"
m (Some new discoveries.) |
|||
Line 24: | Line 24: | ||
|- | |- | ||
| 1|| 0x0004 || 36 Bytes || uint32x9|| Goals Scored | | 1|| 0x0004 || 36 Bytes || uint32x9|| Goals Scored | ||
|rowspan=" | |rowspan="9"| These next hundred or so "uint32x9" stats follow the same format: | ||
The 36 bytes are broken into 9 "segments" of 32-bit integers. Each match corresponds to a 15 minutes of a match, segments 1-3 are the first half and segments 4-6 are the second half. Injury time is counted as part of the last segment of the half. | The 36 bytes are broken into 9 "segments" of 32-bit integers. Each match corresponds to a 15 minutes of a match, segments 1-3 are the first half and segments 4-6 are the second half. Injury time is counted as part of the last segment of the half. | ||
Line 48: | Line 48: | ||
| 9|| 0x0124 || 36 Bytes || uint32x9|| ?UNKNOWN 9 | | 9|| 0x0124 || 36 Bytes || uint32x9|| ?UNKNOWN 9 | ||
|- | |- | ||
| 10|| 0x0148 || 36 Bytes || uint32x9|| ?UNKNOWN 10 | | 10|| 0x0148 || 36 Bytes || uint32x9|| ?UNKNOWN 10 || Strongly correlated with goal scored | ||
|- | |- | ||
| 11|| 0x016C || 36 Bytes || uint32x9|| Shots on Target || | | 11|| 0x016C || 36 Bytes || uint32x9|| Shots on Target || |
Revision as of 01:41, 20 February 2018
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 | These next hundred or so "uint32x9" stats follow the same format:
The 36 bytes are broken into 9 "segments" of 32-bit integers. Each match corresponds to a 15 minutes of a match, segments 1-3 are the first half and segments 4-6 are the second half. Injury time is counted as part of the last segment of the half. Extra time is either segments 7-9 with 10 minute segments but accounting for all 9 segments OR segments 7-8 keeping with the 15 minute length but leaving the segment 9 unused (penalties?). 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. |
2 | 0x0028 | 36 Bytes | uint32x9 | Own Goals Scored | |
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 | ?UNKNOWN 7 | |
8 | 0x0100 | 36 Bytes | uint32x9 | ?UNKNOWN 8 | |
9 | 0x0124 | 36 Bytes | uint32x9 | ?UNKNOWN 9 | |
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 | ?UNKNOWN 12 | |
13 | 0x01B4 | 36 Bytes | uint32x9 | ?UNKNOWN 13 | |
14 | 0x01D8 | 36 Bytes | uint32x9 | Passes | A_Passes + B_Passes + C_Passes + Crosses = (total) Passes X_Passes + Y_Passes + Crosses == (total) Passes |
15 | 0x01FC | 36 Bytes | uint32x9 | Passes Made | |
16 | 0x0220 | 36 Bytes | uint32x9 | A_Passes | Low passes (default key: A) |
17 | 0x0244 | 36 Bytes | uint32x9 | A_Passes Made | |
18 | 0x0268 | 36 Bytes | uint32x9 | B_Passes | Low Through Ball (default key: Y) + Chipped Through Ball (default key: LB + Y) |
19 | 0x028C | 36 Bytes | uint32x9 | B_Passes Made | |
20 | 0x02B0 | 36 Bytes | uint32x9 | C_Passes | Lofted Pass (default key: B) + High Pass (default key: RT + B) |
21 | 0x02D4 | 36 Bytes | uint32x9 | C_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 | X_Passes | A_Passes + Low Through Ball (low passes) |
25 | 0x0364 | 36 Bytes | uint32x9 | X_Passes Made | |
26 | 0x0388 | 36 Bytes | uint32x9 | Y_Passes | C_Passes + BY_Passes (lofted passes) |
27 | 0x03AC | 36 Bytes | uint32x9 | Y_Passes Made | |
28 | 0x03D0 | 36 Bytes | uint32x9 | BX_Passes | Low Through Ball (default key: Y) |
29 | 0x03F4 | 36 Bytes | uint32x9 | BX_Passes Made | |
30 | 0x0418 | 36 Bytes | uint32x9 | BY_Passes | Chipped Through Ball (default key: LB + Y) |
31 | 0x043C | 36 Bytes | uint32x9 | BY_Passes Made | |
32 | 0x0460 | 36 Bytes | uint32x9 | I_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 | I_Passes Made | |
34 | 0x04A8 | 36 Bytes | uint32x9 | J_Passes | Passes between two players on (almost) the same line |
35 | 0x04CC | 36 Bytes | uint32x9 | J_Passes Made | |
36 | 0x04F0 | 36 Bytes | uint32x9 | K_Passes | Backward passes |
37 | 0x0514 | 36 Bytes | uint32x9 | K_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 | |
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. |
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. |
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 | (0) |
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 | (very high value) |
134 | 0x127C | 4 Bytes | uint32? | ?UNKNOWN 146 | (very high value, 0 for a few players) |
135 | 0x1280 | 4 Bytes | uint32? | ?UNKNOWN 147 | (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.