As mentioned, the problem is with indirect calls, where you don't know what it's trying to call, so no amount of MSDN or headers is going to help until you actually run that code and see where that pointer is pointing. It has little to do with runtime or if it's inter-modular or not, it might be calling the next function after the one that does the call, but until the codepath is exercised it's unknown.
Here is an example (simplified code from the real game), I hope you know a bit of x86 asm:
Code:
mov edi, [esi+8]
mov eax, [edi]
push 1
call dword ptr [eax]
Which can be translated to:
int (__stdcall *i_f)(int);
// ...
edi = *(u32 *)(esi+8);
eax = *(u32 *)(edi);
i_f = (void *)*(u32 *)(eax);
i_f(1);
but it may also be
int (__thiscall *i_f)(int, int);
// ...
edi = *(u32 *)(esi+8);
eax = *(u32 *)(edi);
i_f = (void *)*(u32 *)(eax);
i_f(ecx, 1); // ecx is "this" pointer
or maybe
int (__fastcall *i_f)(int, int, int);
// ...
edi = *(u32 *)(esi+8);
eax = *(u32 *)(edi);
i_f = (void *)*(u32 *)(eax);
i_f(ecx, edx, 1);
From the 'push' instruction it's known that one arg is passed through the stack, but is it one of calling conventions that pass some of the args in the registers directly like __fastcall? There is no way to know. I'm doing some heuristics like where if the function never uses the registers from certain calling conventions, it can be assumed that those conventions are not used there, but it doesn't help much as IA32 is very register starved architecture and most functions use all the available registers.