While working on the logicalevent functions, I realized that almost all the functions we want to uses are registered event procedures. There must be some way to call an event procedure by it's name, rather than finding all the functions addresses and adding them to stubs etc. This is something I've been meaning to look into for a long time, but this finally gave me the motivation to do it.
It turns out to be quite simple. ExecuteEventProcedure appears to take the name of the eventproc, followed by a vararg list of the arguments for the eventproc. If you try to call an unregistered eventproc, it helpfully returns -1. The eventprocs themselves appear to use normal C calling convention.
With some quick hacking, the following lua script plays the startup sound
r=exec_event_proc("RegisterProductTestEvent")
print(r)
sleep(1000)
r=exec_event_proc("PT_PlaySound",0x2001)
print(r)
sleep(1000)
(PT_ stands for product test, so the PT_ eventprocs aren't registered by default, but "RegisterProductTestEvent" is and this registers the others )
It will take a bit more hacking to make arbitrary event procs useful for lua, but this opens up huge possibilities. A large number of our stubs are already registered eventprocs.
Calling from C should be even easier, just ExecuteEventprocedure("foo",...). There will be a slight performance penalty for calling things this way, but for many functions it's probably worth it for the ease of maintenance.
There are more interesting possibilities too. We may be able to register our own replacements for some existing eventprocs (although you'd have to be careful, because some are called both directly from C and the eventproc interface), and modify some behavior without hooking whole tasks.