CALL Package
This part of Ikarus makes possible to call engine functions directly from scripts.
In order to be able to invoke an engine function, you must know some of its properties. This includes the number and types of parameters, the type of return value, address of function and calling convention.
Knowledge about engine functions can be obtained using tools like IDA, which can analyze and convert GothicMod.exe / Gothic2.exe into a more human-readable format.
Info
In fact, machine code execution (ASM) is part of the CALL package, but due to its complexity, this functionality is discussed in a separate article.
Initialization
The best way to initialize all Ikarus functions is to call MEM_InitAll()
in the Init_Global()
initialization function.
Warning
If you want to use Ikarus in Gothic 1, it is best to define your own Init_Global()
function and call it from every world initialization function.
Implementation
Call modes
There are two modes:
Disposable
The simple mode that produces a disposable call that is used only once. All parameters are hardcoded.
Recyclable
The second version produces code that can be used more than once. Instead of the parameters the user specifies the address where the parameters are to be taken from. In addition to executing the code, the user will receive an address that he can use to repeat the call. This is much faster than rebuilding the call from scratch.
Receives a pointer. In case the pointer is non-zero, the code at this position is executed and 0 is returned. In case pointer is zero, the current mode is changed into recyclable mode, this means that the call functions expect instructions to build a recyclable call. This mode will continue until
CALL_End()
. This allows code like this:
Start and End
CALL_Open
Initializes a Recyclable call mode.
CALL_Begin
A practical wrapper for CALL_Open
. Makes a call if it had been already created, initializes it otherwise.
var int ptr
Zero if you need to create a new recyclable function to be called (usually, before first use). In this caseCALL_Open
is called andCALL_Begin
returns1
.
Return Value
The function returns 1
if the new call has been created, 0
is returned otherwise.
CALL_Close
Finalizes a function call in recyclable mode, restoring the previous execution context.
CALL_End
Finalizes a function call, pushes the pointer onto the stack, and runs the associated assembly code (makes an actual call).
Return Value
The function returns a pointer that could be used to repeat the call.
Tip
CALL_Close
only finalizes the function call, returning the pointer, while CALL_End
additionally handles pushing the pointer onto the stack and running associated assembly code.
Passing parameters
Parameters must be arranged on the machine stack from right to left i.e. from the parameter on the far right to the parameter on the far left. These functions generate machine code that will place parameters on the machine stack when executed.
Note
These functions do not impose any parameters on the Machine stack. Exactly it should say: You create the machine code that will put parameters on the machine stack when it is executed. And it is only carried out in the second step with the announcement of the calling convention.
CALL_IntParam
Passes an integer (int32
) as a parameter to the called function.
var int param
Address of an integer to be passed
CALL_FloatParam
Passes an IEEE 7554 floating-point number (single
/ zREAL
) as a parameter to the called function.
var int param
Address of a float to be passed
CALL_PtrParam
Passes a pointer (void*
) as a parameter to the called function.
var int param
Pointer to be passed
CALL_zStringPtrParam
Passes a string (zString*
) as a parameter to the called function.
var string param
String to be passed
Warning
This function only works when writing a disposable call!
CALL_cStringPtrParam
Passes a char array (char **
) as a parameter to the called function.
var string param
String to be passed as character array`
Warning
This function only works when writing a disposable call!
CALL_StructParam
Passes a structure (struct) as a parameter to the called function.
var int param
Pointer to the objectvar int words
Size of a structure (1 word = 32 bits)
Note
CALL_IntParam
, CALL_FloatParam
, and CALL_PtrParam
are functionally identical and are differentiated for code readability.
The call
The calling convention determines how the function's parameters are passed. IDA or another disassembler can be used to identify the convention used by a specific engine function.
The announcement of the calling convention, i.e. the call of one of the four functions below is also the time of calling the function. In particular, all parameters must already be specified at this point.
CALL__stdcall
Calls a function with __stdcall
(Standard Call) calling convention.
var int adr
Address of a function
CALL__thiscall
Calls a function with __thiscall
calling convention. Used with a member functions.
var int this
Pointer to the owner class object passed as athis
parametervar int adr
Address of a function
CALL__cdecl
Calls a function with __cdecl
calling convention. Used with non-Windows API and non-class functions.
var int adr
Address of a function
CALL__fastcall
Calls a function with __fastcall
calling convention.
var int ecx
First parameter of a functionvar int edx
Second parameter of a functionvar int adr
Address of a function
Return Value
As soon as the function call has taken place, i.e. after step 2, the return value can be queried. The following functions interpret the return value (usually this is the content of EAX immediately after the call) in the manner suggested in the function name. The result is then returned in a manner usable in Daedalus.
Note
Some return values are not stored in the EAX. In that case the call of the special function RetValIs
is required to get the return value.
Following functions are provided: CALL_RetValIsFloat
, CALL_RetValIszString
, CALL_RetValIsStruct
.
CALL_PutRetValTo
Simply places the return value to the given address (mostly the address of a daedalus integer). Must be called before The Call function.
var int adr
Destination address of the return value
CALL_RetValAsInt
Retrieves an integer returned by the called function.
The function returns an integer returned by the previously called engine function.
CALL_RetValIsFloat
Specifies that the return value is a float. Must be called before The Call function to allow getting the return value with CALL_RetValAsFloat
.
CALL_RetValAsFloat
Retrieves a float returned by the called function.
The function returns a float returned by the previously called engine function.
CALL_RetValAsPtr
Retrieves a pointer (void*
) returned by the called function.
The function returns a pointer returned by the previously called engine function.
CALL_RetValIsStruct
Specifies that the return value is a Structure. Must be called before The Call function to allow getting the return value with CALL_RetValAsStructPtr
.
var int size
Size of the returned structure in bytes
Danger
If the return value is a structure with a size larger than 32 bit, the space for the return value has to be allocated by the caller (this is us).The address to the allocated memory is expected on the stack as an additional parameter (pushed last).
Warning
It is in your responsibility to free the structure memory, when the return value is not needed any more.
CALL_RetValAsStructPtr
Retrieves a pointer to the structure returned by the called function and converts it to the instance. Can be used to make an assignment to an instance, for example an assignment to a var zCVob
if the return value is a pointer to a zCVob
.
The function returns an instance returned by the previously called engine function.
CALL_RetValIszString
Specifies that the return value is a zString
(20 bytes structure). Must be called before The Call function to allow getting the return value with CALL_RetValAszStringPtr
and CALL_RetValAszString
.
Note
CALL_RetValAszStringPtr
and CALL_RetValAszString
are quite different and should not be confused. Using CALL_RetValAszString
frees up memory that may still be needed. In a reverse with CALL_RetValAszStringPtr
memory that is no longer needed is not freed and can cause memory leak.
CALL_RetValAszStringPtr
Retrieves a zString
pointer and converts it to the daedalus string. (don't frees the memory)
The function returns a daedalus string form a zString
returned by the previously called engine function.
CALL_RetValAszString
Retrieves a zString
pointer and converts it to the daedalus string. (frees the memory)
The function returns a daedalus string form a zString
returned by the previously called engine function.
Function author note
A
zString
is merely a special case of a structure, with the difference, that it is used as a primitive datatype. Nobody will be willing to use it as a pointer to some memory or an instance in Daedalus. This function copies the contents of thezString
into a daedalus string and frees thezString
afterwards.
Examples
Apply overlay (Disposable)
Get time as string (Disposable)
e.g. "7:30"
for half past seven in the morning
Get the "sky time" (Disposable)
Sky time is a floating point value between 0 and 1 that jumps back from 1 to 0 at noon.
Delete Vob (Recyclable)
Call of the oCWorld.RemoveVob
. MEM_DeleteVob
is an ikarus built-in function.