Gamestudio Links
Zorro Links
Newest Posts
Change chart colours
by 7th_zorro. 05/11/24 09:25
Data from CSV not parsed correctly
by dr_panther. 05/06/24 18:50
Help with plotting multiple ZigZag
by degenerate_762. 04/30/24 23:23
AUM Magazine
Latest Screens
The Bible Game
A psychological thriller game
SHADOW (2014)
DEAD TASTE
Who's Online Now
2 registered members (AndrewAMD, 1 invisible), 1,086 guests, and 5 spiders.
Key: Admin, Global Mod, Mod
Newest Members
firatv, wandaluciaia, Mega_Rod, EternallyCurious, howardR
19050 Registered Users
Previous Thread
Next Thread
Print Thread
Rate Thread
About wait() #410383
11/02/12 06:24
11/02/12 06:24
Joined: Apr 2007
Posts: 3,751
Canada
WretchedSid Offline OP
Expert
WretchedSid  Offline OP
Expert

Joined: Apr 2007
Posts: 3,751
Canada
So, one of the biggest mysteries for me about Gamestudio is wait(), I have talked with quite a few people about it and no one really has a good idea how it works internally. Although it's commonly agreed to be one huge dirty stack hack.

From what I can see, a call to wait() isn't just a simple function call because it returns the currently running function. Instead I think it's actually more like a macro that expands into something like:
Code:
if(notifyScheduler(&stackTop, n) == 0)
   return;



The scheduler will then take the current stack pointer and simply copies everything from stackTop down to the current stack pointer into a buffer. StackTop is the address of the first argument that was pushed on the stack, which is also the reason for a) the interesting layout of local variables on the stack (and their weak scope) as well as b) the not existence of variadic functions (if variadic functions would exist, the compiler had to compile multiple versions of the function for each possible number of arguments).

The return address might be passed as well to the scheduler, but I guess it's much easier to just grab it of the stack upon entry, it's also much more accurate and doesn't require work from the linker.

I'm not too sure if some of the registers need to be saved as well, I tried to think of a few good reasons but as far as I can see it's impossible to call wait() from somewhere when there is data in the registers that isn't saved already somewhere.

The scheduler then creates a new entry, saves my and you along with the buffer and return address and that's it.
Then the main runloop finishes it's current step, everything is rendered etc, and then the scheduler kicks in on the next iteration and works off it's list checking which functions are due. I guess what happens there is that it grabs the current stack pointer, modifies the return address on the saved stack, moves something else than zero into eax (to make my pseudo code above work) and then copies the saved stack on the current stack and also restores my and you. Then it makes a jmp to the stored return address and thats it.

At least that's how I imagine it works from all I can see, but what would really interest me: How close is that to the truth? How does wait() actually work?


Shitlord by trade and passion. Graphics programmer at Laminar Research.
I write blog posts at feresignum.com
Re: About wait() [Re: WretchedSid] #410384
11/02/12 08:28
11/02/12 08:28
Joined: Jul 2000
Posts: 27,986
Frankfurt
jcl Offline

Chief Engineer
jcl  Offline

Chief Engineer

Joined: Jul 2000
Posts: 27,986
Frankfurt
It is pretty close. Only the issue with variadic functions has a different reason. Here's our source for wait(), somewhat simplified:

Code:
void CS_Wait(fixed time)
{
	static byte *local_stack,*local_offs;
	_asm
	{
		mov local_offs,ebx
		mov local_stack,ebp		
	}
	time -= 1;

// retrieve function name, stack size, and start address information
	byte *stack = local_stack+3*4; 
	byte *code = (byte*)((DWORD*)local_stack)[1]; // current return address from the stack
	char *name;		// of the function
	void *codestart;	// of the function
	long stacksize;		// local stack size
	long parasize;		// function parameter size
	CS_GetFunctionInfo(code,&name,&stacksize,&parasize,&codestart);
	CS_SchedulerInsert(code,stack,stacksize,code-local_offs,time,codestart,name);

// return to the caller
	_asm
	{
		mov esp,stack
		add esp,stacksize;	// skip local vars
		pop edi			// pop original registers
		pop esi  
		pop ebx  
		pop ebp
		ret			// back to caller
	}
}



Re: About wait() [Re: jcl] #410386
11/02/12 09:14
11/02/12 09:14
Joined: Jul 2008
Posts: 894
T
TechMuc Offline
User
TechMuc  Offline
User
T

Joined: Jul 2008
Posts: 894
wow, thanks a lot for this answer. But one annotation:

Please, please please make this CS_GetFunctionInfo public (export symbols to acknex.dll).
This function would really really help a lot (e.g. getting stacksize of a single function, or the parametersize).

I do not need entries in afuns.h (or similar), just an export, so i can retrieve the address via GetProcAddress.

This would probably allow to implement a "real" profiler.

Last edited by TechMuc; 11/02/12 09:19.
Re: About wait() [Re: TechMuc] #410392
11/02/12 13:21
11/02/12 13:21
Joined: Apr 2007
Posts: 3,751
Canada
WretchedSid Offline OP
Expert
WretchedSid  Offline OP
Expert

Joined: Apr 2007
Posts: 3,751
Canada
Wow, thanks a lot indeed! That clears up a lot of things I've been wondering about.
Although I'm now confused about variadic functions, it seemed like a pretty good explanation to me but now I'm baffled what the actual reason is. Can you shed some light into this as well?


Shitlord by trade and passion. Graphics programmer at Laminar Research.
I write blog posts at feresignum.com
Re: About wait() [Re: WretchedSid] #410464
11/03/12 12:59
11/03/12 12:59
Joined: Jul 2008
Posts: 894
T
TechMuc Offline
User
TechMuc  Offline
User
T

Joined: Jul 2008
Posts: 894
btw: Is it correct that CS_GetFunctionInfo(code,&name,&stacksize,&parasize,&codestart);
expects 6 Parameters (before code, another parameter, which probably indicates the first lite-c function)?

If so could you please also export this variable? I think if you provide me with those 3 Functions:

1) internal wait
2) CS_GetFunctionInfo
3) 1st parameter of CS_GetFunctioninfo (My current way of calculating this parameter is:
Code:
void* _ev = (void*)a7_dll::engine_getscript("main");
global_code_start_address = (void*)(((int)_ev) & 0xFFFF0000);


which might be correct for my test script but for 100% nur for any 3dgs project laugh - [edit]I know now, that this is absolutly wrong[/edit]

a) Call Stack
b) debugging of local variables
c) debugging of argument values (okay more or less the same)
d) profiling

would be possible...

Last edited by TechMuc; 11/04/12 22:36.
Re: About wait() [Re: TechMuc] #410534
11/04/12 22:37
11/04/12 22:37
Joined: Jul 2008
Posts: 894
T
TechMuc Offline
User
TechMuc  Offline
User
T

Joined: Jul 2008
Posts: 894
Edit: Some kind of remark, with another video advertising post. Please help me out here by exporting those internal functions. I'm currently working with "fix relative" internal positions to retrieve the function pointers, which is a) unsafe b) not good for engine upgrades.

Video that i do not fake this stuff: http://www.dev-software.com/led/video/performance_1/Performance_Video_1.html

Re: About wait() [Re: TechMuc] #410553
11/05/12 13:03
11/05/12 13:03
Joined: Jul 2000
Posts: 27,986
Frankfurt
jcl Offline

Chief Engineer
jcl  Offline

Chief Engineer

Joined: Jul 2000
Posts: 27,986
Frankfurt
The first parameter was the codebase. We'll export this function in a future update so that you can externally use it.


Moderated by  old_bill, Tobias 

Gamestudio download | chip programmers | Zorro platform | shop | Data Protection Policy

oP group Germany GmbH | Birkenstr. 25-27 | 63549 Ronneburg / Germany | info (at) opgroup.de

Powered by UBB.threads™ PHP Forum Software 7.7.1