The mod uses a classic x86 trampoline technique: the installer overwrites a small run of original bytes at a known offset insideDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/angelballay/pes6_game_physics_mod/llms.txt
Use this file to discover all available pages before exploring further.
pes6.exe with a single relative JMP instruction (0xE9 + rel32), redirecting execution into a naked C function. That function saves any registers it needs, runs additional C logic, re-executes the original instructions that were displaced by the patch, and finally jumps back to the instruction immediately following the patched region. This design means no original game logic is permanently lost — the hook merely wraps it.
Hook A — Context Hook at pes6.exe+1A5905
What is hooked and why
At offset0x1A5905 the game calls an internal function and moves the return value into EBX. At this exact call site the CPU registers hold the identities of the two players involved in the pass event:
ESI= passer (pointer to the passer’s in-memory player structure)EDX= receiver (pointer to the receiver’s in-memory player structure)
Original bytes (7 bytes)
JMP to Hook_Context_1A5905; the remaining 2 become NOP padding.
Naked assembly — Hook_Context_1A5905
Key addresses
| Symbol | Value | Description |
|---|---|---|
| Hook site | base + 0x1A5905 | Where the JMP is written |
g_call_1A1570 | base + 0x1A1570 | The original call target, re-executed inside the hook |
g_ctxReturn | base + 0x1A590C | Return address (byte immediately after the 7-byte patch) |
Hook B — Power Hook at pes6.exe+1A637B
What is hooked and why
At offset0x1A637B the game prepares a call to its internal ball-writing routine (pes6.exe+78020). Immediately before this call the EDI register holds the computed pass power value that will be written into ball+0x50. Intercepting here gives the mod the opportunity to read and modify EDI before the value is committed to the ball structure.
Original bytes (11 bytes)
JMP; bytes 5–10 become NOP padding.
Naked assembly — Hook_Power_1A637B
Key addresses
| Symbol | Value | Description |
|---|---|---|
| Hook site | base + 0x1A637B | Where the JMP is written |
g_call_78020 | base + 0x78020 | Ball-writing routine; receives the pass power value pushed via push edi, and writes it into ball+0x50 |
g_powerReturn | base + 0x1A6386 | Return address (byte immediately after the 11-byte patch) |
g_savedEDIForRestore ensures that EDI is restored to its original value after call_78020 completes. Only the value actually pushed onto the stack — and therefore written into the ball — is the modified one. The rest of the surrounding PES6 code sees an unchanged EDI.Safety checks — CheckBytes and conditional installation
Before either WriteJump call is made, the installer reads the bytes at the target address and compares them byte-for-byte against the known original sequence.
CheckBytes wraps the read in a structured-exception handler. If an access violation occurs (e.g., the address is not mapped), it logs the failure and returns false. If any single byte differs from the expected value, it logs the index, expected value, and actual value, then returns false. Only a perfect match proceeds to WriteJump.
The same pattern applies in InstallPowerHook for the 11-byte sequence at +1A637B. If either installer returns false, MainThread logs the error and exits without activating the mod.
WriteJump implementation
dst - src - 5 accounts for the fact that the CPU reads the JMP’s target relative to the address of the next instruction (i.e., source + 5). The NOP padding is essential for Hook B where 11 bytes are patched but a JMP only consumes 5 — without it, the 6 leftover bytes would be interpreted as stale partial instructions if execution ever fell through (it never does, but the padding is correct practice). FlushInstructionCache is called with the exact patched range to invalidate any pre-fetched instructions on all logical CPU cores.