View Single Post
cybermind
Senior Member
Join Date: Oct 2004
Old 01-04-2006 , 23:20   Re: THE NEWBIE'S GUIDE TO FUNCTION SIGNATURE SCANNING
Reply With Quote #5

Quote:
Originally Posted by SeLfkiLL
Code:
	#ifdef WIN32
	typedef void (*func)(float, bool, float, bool);
	func thisfunc = (func)CBaseAnimating_Ignite_Sig.sig_addr; // Pointer to the function scanned from memory
	
	/* The CBaseAnimating object must be pushed onto the stack manually
	   for the real method to use (and thus its arguments as well). */
	__asm {
		mov ecx, cba;
		push flFlameLifetime;
		push bNPCOnly;
		push flSize;
		push bCalledByLevelDesigner;
		call thisfunc;
	};
	#else
There's a better* way to call a member function in Win32 than all that asm crap. BAILOPAN actually mentioned it a few weeks ago in #sourcemod, and I just tested to see if it works about an hour ago, ironically. Keep in mind this is only for member functions that do not have variable arguments. To handle those, do it like GCC and pass this as the first parameter. Here is the method BAILOPAN suggested:
Code:
	#ifdef WIN32
	/* the first parameter is the this pointer, the second is just a dummy, just pass 0 */
	typedef void (__fastcall *func)(CBaseAnimating*, void*, float, bool, float, bool);
	func thisfunc = (func)CBaseAnimating_Ignite_Sig.sig_addr; // Pointer to the function scanned from memory

	thisfunc(cba, 0, flFlameLifetime, (bool)bNPCOnly, flSize, (bool)bCalledByLevelDesigner); 

	#else
Basically, the fastcall calling convention passes the first 2 parameters (as long as they fit in a register, 32 or 64bits long) in ECX and EDX. As you already know, MSVC handles thiscall by passing this in ECX. By simply passing the CBA pointer and a dummy value in ECX and EDX via fastcall, we are putting the this pointer right where it needs to be, and the dummy in EDX is ignored. Luckily both thiscall and fastcall have the callee clean the stack (which is why variable argument functions need to be handled normally like cdecl).

*I'm sure 'better' is a point of contention here. Personally, I just never liked using possibly nonportable inline asm to do things that could be done without it. Granted the 6 ops you used are hardly nonportable, but it's the principle.
cybermind is offline