ThibaultLemaire/HomeworldSDL

Porting Generic ETG code to x86_64

Closed this issue · 2 comments

Following #2, I'm trying to port the generic etg code to x86_64.

The code compiles and works fine on x86 (so my hopes are high).

On 64b it compiles as well but when it tries to run the first hit effect, it segfaults.

A note on ETG

So ETG -- according to the header of src/Game/ETG.c -- stands for Effects of The Gods.

This is what I've gathered from skimming the source code:

  • It relates to all in-game SFX (the things you can enable/disable in the "Custom Effects" of the "Video" options. Particularly, the hit effects).
  • The effects are scripted with a DSL parsed at load time from .ebg files and then executed at game time using some kind of stack and a bunch of function pointers. (I think this is an instance of the bytecode pattern)

Handling the calling of those functions involves some assembly black magic to push values directly on the stack. Now of course porting to new architectures would involve porting that assembly code as well. Eventually, someone (markunderwood), when porting to arm, got fed up with that and decided to write equivalent C code that could theoretically be compiled to more architectures. Therefore, he called that feature generic etg.

The generic etg code involves wrapping existing functions, retrieving parameters from the parsed etg code, and instead of pushing them on the stack, passing them the usual way to the original function. This happens in wrapped_unlisted_functions.h and wrap.h.

Now, for that specific segfault. After some extensive gdb debugging, here are my conclusions:

The problem occurs when getting the 4th argument (index=3) for partSetTrHandle in wrap_partSetTrHandle.

According to the code in etgSetTextureParse the type of this parameter should be EVT_Constant (=6). This is confirmed by debugging the 32b version.

But for an unknown reason, the type is 72 (value constant across ~30 tests), which causes do_get_arg to jump to the default case and try dereferencing an erroneous pointer.

Debugging shows that etgSetTextureParse does indeed init all params' type to EVT_Constant, so this particular location in the etg effect table must be overwritten somewhere later. But where? The fact that it works on 32b means it must be a computational error due to sizes changing in 64b.