GothicKit / ZenKit

A re-implementation of file formats used by the early 2000's ZenGin
http://zk.gothickit.dev/
MIT License
49 stars 9 forks source link

High order functions #80

Closed Try closed 6 months ago

Try commented 1 year ago

In Daedalus it's possible to pass function to other functions as parameters:

func void _FF_CREATE(var func FUNCTION, var int DELAY, var int CYCLES, var int HASDATA, var int DATA, var int GAMETIME) { ... }

func void FF_APPLYEXTDATA(var func FUNCTION, var int DELAY, var int CYCLES, var int DATA) {
    _FF_CREATE(0x2a75, DELAY, CYCLES, TRUE, DATA, FALSE);
}

Couple of minor issues with it:

  1. De-compiled source has 0x2a75 (symbol id of FUNCTION) instead of FUNCTION
  2. Awkwardness of daedalus runtime (mostly on compiler side). It doesn't pass function pointer, it passes symbol-id instead In example above _FF_CREATE will receive id of FF_APPLYEXTDATA.FUNCTION symbol and won't be able use it directly.

Current workaround: it's possible to traverse reference chain up to original function:

// opengothic override
void LeGo::_FF_Create(int func, int delay, int cycles, int hasData, int data, bool gametime) {
  auto* sym = vm.find_symbol_by_index(uint32_t(func));
  while(sym!=nullptr && !sym->is_const()) { // not my idea - took it from Ikarus. Also sym->address is probably cleaner
    func = sym->get_int();
    sym = vm.find_symbol_by_index(uint32_t(func));
    }
 ...

Proposed changes:

lmichaelis commented 1 year ago

Introduce new opaque type struct phoenix::func { uint32_t value; }. When callback uses phoenix::func, VM should unroll reference chain internally and pass real symbol-id to game-engine.

Initial implementation at b8b70341. Do you also need support for returning funcs from externals?

lmichaelis commented 1 year ago

Fix handling of func forwarding in de-compiler :)

Should be fixed in phoenix-studio/a316d60. Had to force push to override broken commit :/

Before: image

After: image

Try commented 1 year ago

Do you also need support for returning funcs from externals?

Not really important - returning integer also works fine. Yet, this functionality is nice to have for completeness.

lmichaelis commented 1 year ago

Okay, does https://github.com/GothicKit/phoenix/compare/feature/daedalus-func-type now work for you?

Try commented 1 year ago

Okay, does https://github.com/GothicKit/phoenix/compare/feature/daedalus-func-type now work for you?

Tested locally on my side - works well, so please merge :)