SCI/FreeSCI/Kernel hacking/Selectors
Selectors
Selectors are very important for some of the kernel functions. BaseSetter(), Animate(), Display(), GetEvent() and others take data from or write directly to selectors of a specified object (passed as a parameter or retreived from a node list), or even call object methods from kernel space.[1]
To prepare the usage of selectors, a variable has do be declared (in src/include/vm.h, selector_map_t). This variable will carry the numeric selector ID during run time. Now, the selector has to be mapped- this is happens once during initialization, to save time. It is performed by script_map_selectors(), which is located at the end of src/core/script.c (just use the "FIND_SELECTOR" macro).
If everything went right, accessing selectors should be really easy now. Just use the GET_SELECTOR(obj, selector) and PUT_SELECTOR(obj, selector, value) macros, where obj is a heap_ptr pointing to the object you want to read from or write to, and selector is the name of the selector to use.
An example for PUT_SELECTOR and GET_SELECTOR:
<syntax type="C">
void kSwapXY(state_t *s, int funct_nr, int argc, heap_ptr argp) { int posx, posy; heap_ptr obj = PARAM(0);
posx = GET_SELECTOR(obj, x); posy = GET_SELECTOR(obj, y); /* x and y are defined in selector_map_t */
PUT_SELECTOR(obj, y, posx); PUT_SELECTOR(obj, x, posy); }</syntax>
Also, it may be neccessary to invoke an actual method. To do this, a varargs macro has been provided: INVOKE_SELECTOR(obj, selector, argc...). In theory, this macro can be used to set and read selectors as well (it would even handle multiple sends correctly), but this is discouraged for the sake of clarity.
INVOKE_SELECTOR works very much like the other macros; it must be called directly from a kernel function (or from any function supplying valid argc, argp and s).
An example for INVOKE_SELECTOR:
<syntax type="C">
INVOKE_SELECTOR(obj, doit, 0); /* Call doit() without any parameters */ INVOKE_SELECTOR(s->game_obj, setCursor, 2, 999, 1); /* Call game_obj::setCursor(999, 1) */</syntax>
Notes
- ↑ Yes, this is evil. Don't do this at home, kids!