Find CLoopModeGame_RegisterEventMapInternal
Locate CLoopModeGame_RegisterEventMapInternal, RegisterEventListener_Abstract, and all CLoopModeGame_OnXXXXXXX event handler functions in CS2 client.dll or libclient.so using IDA Pro MCP tools.
Method
1. Search for the anchor string
mcp__ida-pro-mcp__find_regex pattern="CLoopModeGame::OnClientPollNetworking"
2. Get cross-references to the string
mcp__ida-pro-mcp__xrefs_to addrs="<string_addr>"
There should be exactly one code xref — this is inside CLoopModeGame_RegisterEventMapInternal.
3. Decompile the referencing function
mcp__ida-pro-mcp__decompile addr="<function_addr>"
4. Match the characteristic code pattern
The function takes 4 parameters (a1, a2, a3, a4) and has two main branches:
- When
a3 != 0: Unregister events branch - When
a3 == 0: Register events branch (the one we care about)
In the register branch, look for repeated sequences of this pattern:
// Each event registration follows this pattern:
unknown_libname_XXX(&v_local, &unk_XXXXXXXX); // Get event descriptor
v_temp = v_local;
v_callback = sub_XXXXXXXX; // <-- This is a CLoopModeGame_OnXXXXXXX callback
v_handle = sub_XXXXXXXX(a2); // Get handle from a2
sub_XXXXXXXX(a1, &v_handle, 1, 1, v_temp, a4, "CLoopModeGame::OnXXXXXXX"); // <-- This is RegisterEventListener_Abstract
Key identifiers:
CLoopModeGame_RegisterEventMapInternal: The outer function containing all the event registrationsRegisterEventListener_Abstract: The function called with 7 arguments including the event name string as the last argument — it is the same function called for every event registration in the functionCLoopModeGame_OnClientPollNetworking: The callback function pointer stored before the call with string"CLoopModeGame::OnClientPollNetworking"CLoopModeGame_OnClientAdvanceTick: The callback function pointer stored before the call with string"CLoopModeGame::OnClientAdvanceTick"CLoopModeGame_OnClientPostAdvanceTick: The callback for"CLoopModeGame::OnClientPostAdvanceTick"CLoopModeGame_OnClientPreSimulate: The callback for"CLoopModeGame::OnClientPreSimulate"CLoopModeGame_OnClientPreOutput: The callback for"CLoopModeGame::OnClientPreOutput"CLoopModeGame_OnClientPreOutputParallelWithServer: The callback for"CLoopModeGame::OnClientPreOutputParallelWithServer"CLoopModeGame_OnClientPostOutput: The callback for"CLoopModeGame::OnClientPostOutput"CLoopModeGame_OnClientFrameSimulate: The callback for"CLoopModeGame::OnClientFrameSimulate"CLoopModeGame_OnClientAdvanceNonRenderedFrame: The callback for"CLoopModeGame::OnClientAdvanceNonRenderedFrame"CLoopModeGame_OnClientPostSimulate: The callback for"CLoopModeGame::OnClientPostSimulate"CLoopModeGame_OnClientPauseSimulate: The callback for"CLoopModeGame::OnClientPauseSimulate"CLoopModeGame_OnClientSimulate: The callback for"CLoopModeGame::OnClientSimulate"CLoopModeGame_OnPostDataUpdate: The callback for"CLoopModeGame::OnPostDataUpdate"CLoopModeGame_OnPreDataUpdate: The callback for"CLoopModeGame::OnPreDataUpdate"CLoopModeGame_OnFrameBoundary: The callback for"CLoopModeGame::OnFrameBoundary"
5. Identify all event handler callbacks
Scan through the entire register branch and collect ALL callback function addresses paired with their event name strings. The following 15 callbacks should be found:
CLoopModeGame_OnClientPollNetworking—"CLoopModeGame::OnClientPollNetworking"CLoopModeGame_OnClientAdvanceTick—"CLoopModeGame::OnClientAdvanceTick"CLoopModeGame_OnClientPostAdvanceTick—"CLoopModeGame::OnClientPostAdvanceTick"CLoopModeGame_OnClientPreSimulate—"CLoopModeGame::OnClientPreSimulate"CLoopModeGame_OnClientPreOutput—"CLoopModeGame::OnClientPreOutput"CLoopModeGame_OnClientPreOutputParallelWithServer—"CLoopModeGame::OnClientPreOutputParallelWithServer"CLoopModeGame_OnClientPostOutput—"CLoopModeGame::OnClientPostOutput"CLoopModeGame_OnClientFrameSimulate—"CLoopModeGame::OnClientFrameSimulate"CLoopModeGame_OnClientAdvanceNonRenderedFrame—"CLoopModeGame::OnClientAdvanceNonRenderedFrame"CLoopModeGame_OnClientPostSimulate—"CLoopModeGame::OnClientPostSimulate"CLoopModeGame_OnClientPauseSimulate—"CLoopModeGame::OnClientPauseSimulate"CLoopModeGame_OnClientSimulate—"CLoopModeGame::OnClientSimulate"CLoopModeGame_OnPostDataUpdate—"CLoopModeGame::OnPostDataUpdate"CLoopModeGame_OnPreDataUpdate—"CLoopModeGame::OnPreDataUpdate"CLoopModeGame_OnFrameBoundary—"CLoopModeGame::OnFrameBoundary"
For each registration block:
- The callback function pointer is assigned to a local variable just before the
RegisterEventListener_Abstractcall - The event name string (last argument) tells you the callback name — strip the
::and replace with_
6. Check if the functions are already renamed
mcp__ida-pro-mcp__lookup_funcs queries=["<RegisterEventMapInternal_addr>", "<RegisterEventListener_Abstract_addr>", "<callback1_addr>", "<callback2_addr>", ...]
7. Rename all functions that are still unnamed (sub_ prefix)
mcp__ida-pro-mcp__rename batch={"func": [
{"addr": "<addr>", "name": "CLoopModeGame_RegisterEventMapInternal"},
{"addr": "<addr>", "name": "RegisterEventListener_Abstract"},
{"addr": "<addr>", "name": "CLoopModeGame_OnClientPollNetworking"},
{"addr": "<addr>", "name": "CLoopModeGame_OnClientAdvanceTick"},
{"addr": "<addr>", "name": "CLoopModeGame_OnClientPostAdvanceTick"},
{"addr": "<addr>", "name": "CLoopModeGame_OnClientPreSimulate"},
{"addr": "<addr>", "name": "CLoopModeGame_OnClientPreOutput"},
{"addr": "<addr>", "name": "CLoopModeGame_OnClientPreOutputParallelWithServer"},
{"addr": "<addr>", "name": "CLoopModeGame_OnClientPostOutput"},
{"addr": "<addr>", "name": "CLoopModeGame_OnClientFrameSimulate"},
{"addr": "<addr>", "name": "CLoopModeGame_OnClientAdvanceNonRenderedFrame"},
{"addr": "<addr>", "name": "CLoopModeGame_OnClientPostSimulate"},
{"addr": "<addr>", "name": "CLoopModeGame_OnClientPauseSimulate"},
{"addr": "<addr>", "name": "CLoopModeGame_OnClientSimulate"},
{"addr": "<addr>", "name": "CLoopModeGame_OnPostDataUpdate"},
{"addr": "<addr>", "name": "CLoopModeGame_OnPreDataUpdate"},
{"addr": "<addr>", "name": "CLoopModeGame_OnFrameBoundary"}
]}
8. Generate and validate unique signatures
ALWAYS Use SKILL /generate-signature-for-function to generate a robust and unique signature for each function:
CLoopModeGame_RegisterEventMapInternalRegisterEventListener_AbstractCLoopModeGame_OnClientPollNetworkingCLoopModeGame_OnClientAdvanceTickCLoopModeGame_OnClientPostAdvanceTickCLoopModeGame_OnClientPreSimulateCLoopModeGame_OnClientPreOutputCLoopModeGame_OnClientPreOutputParallelWithServerCLoopModeGame_OnClientPostOutputCLoopModeGame_OnClientFrameSimulateCLoopModeGame_OnClientAdvanceNonRenderedFrameCLoopModeGame_OnClientPostSimulateCLoopModeGame_OnClientPauseSimulateCLoopModeGame_OnClientSimulateCLoopModeGame_OnPostDataUpdateCLoopModeGame_OnPreDataUpdateCLoopModeGame_OnFrameBoundary
9. Write IDA analysis output as YAML beside the binary
ALWAYS Use SKILL /write-func-as-yaml to write the analysis results for each function.
For CLoopModeGame_RegisterEventMapInternal:
Required parameters:
func_name:CLoopModeGame_RegisterEventMapInternalfunc_addr: The function address from step 3func_sig: The validated signature from step 8
For RegisterEventListener_Abstract:
Required parameters:
func_name:RegisterEventListener_Abstractfunc_addr: The function address from step 4func_sig: The validated signature from step 8
For each callback:
Required parameters:
func_name: The callback name from the list belowfunc_addr: The callback function address from step 5func_sig: The validated signature from step 8
Callbacks to write:
CLoopModeGame_OnClientPollNetworkingCLoopModeGame_OnClientAdvanceTickCLoopModeGame_OnClientPostAdvanceTickCLoopModeGame_OnClientPreSimulateCLoopModeGame_OnClientPreOutputCLoopModeGame_OnClientPreOutputParallelWithServerCLoopModeGame_OnClientPostOutputCLoopModeGame_OnClientFrameSimulateCLoopModeGame_OnClientAdvanceNonRenderedFrameCLoopModeGame_OnClientPostSimulateCLoopModeGame_OnClientPauseSimulateCLoopModeGame_OnClientSimulateCLoopModeGame_OnPostDataUpdateCLoopModeGame_OnPreDataUpdateCLoopModeGame_OnFrameBoundary
Note: These are all regular functions, NOT virtual functions, so no vtable parameters are needed.
Function Characteristics
CLoopModeGame_RegisterEventMapInternal
- Prototype:
void CLoopModeGame_RegisterEventMapInternal(void *pLoopModeGame, void *a2, int bUnregister, int a4) - Parameters:
pLoopModeGame: Pointer to the CLoopModeGame instancea2: Context parameter passed to event handle creationbUnregister: When non-zero, unregisters events; when zero, registers eventsa4: Additional parameter passed through to RegisterEventListener_Abstract
- Behavior: Registers (or unregisters) multiple game event listeners for the CLoopModeGame class
RegisterEventListener_Abstract
- Prototype:
void RegisterEventListener_Abstract(void *pListener, void *pHandle, int a3, int a4, void *pEventDescriptor, int a6, const char *pszEventName) - Parameters:
pListener: The listener object (CLoopModeGame instance)pHandle: Event handlea3: Flag (typically 1)a4: Flag (typically 1)pEventDescriptor: Event descriptor pointera6: Additional parameterpszEventName: Debug name string like"CLoopModeGame::OnClientPollNetworking"
Event Callbacks
The following 15 callbacks are individual event handler functions for various game loop events:
CLoopModeGame_OnClientPollNetworkingCLoopModeGame_OnClientAdvanceTickCLoopModeGame_OnClientPostAdvanceTickCLoopModeGame_OnClientPreSimulateCLoopModeGame_OnClientPreOutputCLoopModeGame_OnClientPreOutputParallelWithServerCLoopModeGame_OnClientPostOutputCLoopModeGame_OnClientFrameSimulateCLoopModeGame_OnClientAdvanceNonRenderedFrameCLoopModeGame_OnClientPostSimulateCLoopModeGame_OnClientPauseSimulateCLoopModeGame_OnClientSimulateCLoopModeGame_OnPostDataUpdateCLoopModeGame_OnPreDataUpdateCLoopModeGame_OnFrameBoundaryPrototype:
void CLoopModeGame_OnXXXXXXX(void *pEvent)(exact signature may vary)Purpose: Individual event handler callbacks for various game loop events
DLL Information
- DLL:
client.dll(Windows) /libclient.so(Linux)
Notes
- All functions are regular functions, NOT virtual functions
RegisterEventListener_Abstractis the same function called for every event registration — verify all calls reference the same address- The number of event callbacks may vary between game versions — collect ALL of them from the register branch
- Each callback is uniquely identified by its paired event name string
Output YAML Format
The output YAML filenames depend on the platform:
client.dll→<func_name>.windows.yamllibclient.so→<func_name>.linux.yaml
The following 17 YAML files should be generated (where {platform} is windows or linux):
CLoopModeGame_RegisterEventMapInternal.{platform}.yamlRegisterEventListener_Abstract.{platform}.yamlCLoopModeGame_OnClientPollNetworking.{platform}.yamlCLoopModeGame_OnClientAdvanceTick.{platform}.yamlCLoopModeGame_OnClientPostAdvanceTick.{platform}.yamlCLoopModeGame_OnClientPreSimulate.{platform}.yamlCLoopModeGame_OnClientPreOutput.{platform}.yamlCLoopModeGame_OnClientPreOutputParallelWithServer.{platform}.yamlCLoopModeGame_OnClientPostOutput.{platform}.yamlCLoopModeGame_OnClientFrameSimulate.{platform}.yamlCLoopModeGame_OnClientAdvanceNonRenderedFrame.{platform}.yamlCLoopModeGame_OnClientPostSimulate.{platform}.yamlCLoopModeGame_OnClientPauseSimulate.{platform}.yamlCLoopModeGame_OnClientSimulate.{platform}.yamlCLoopModeGame_OnPostDataUpdate.{platform}.yamlCLoopModeGame_OnPreDataUpdate.{platform}.yamlCLoopModeGame_OnFrameBoundary.{platform}.yaml