Great, thanks!
I'll remove my version of that "fix" from my patch DLL then; it was just a quick cheap hack anyway.
BTW: I'm leaving my Engine.exe patch DLL as DSOUND.dll; no point rewriting that one for anything else, since the 3D View doesn't actually use sound?
And in any case, lack of EAX wouldn't be an issue in the 3D View anyway, even if it
had sound.
Having DSOUND.dll as the patch for the Engine won't affect the Editor itself, because in my CP the 3D View engine sits in \Engine folder - this is so that dgVoodoo can be used with it, as it would otherwise interfere badly with the Editor (the 2D part).
The only idea I have besides InjectDLL shim you've mentioned is writing the launcher that injects it. It's quickly described here.
Unfortunately, the DLL injection method you've linked to is not useful in my case:
I need the DLL to run when Drakan.exe is launched (
not some other process which then launches Drakan.exe). This is required for compatibility with existing shortcuts, etc.
Hence the shimming idea.
Remember, any file replacements I do through my installer can be easily (accidentally) undone by misguided users installing the CP,
then (re)installing your AiO patch. Yes, it has happened before - although so far, no real damage has been done... yet.
To paraphrase the conclusion of the Discord conversation I've had with Zalasus concerning this issue:
It's a case of "assume nothing, prepare for everything".
BTW: Yes, I do plan to have a launcher / settings editor for Drakan.exe eventually - but it will be invoked from within Drakan.exe itself (if it's started without passing the right commandline param to skip the launcher); in that respect, you could say that Drakan.exe will effectively be its own launcher.
The basic idea is to gather ALL of the settings for Drakan (incl. Arokh.ini, dgVoodoo.conf, etc) in ONE place: the launcher. Currently the settings are located all over the place, and that's causing users unnecessary difficulties.
TL;dr: I'm currently redoing my code as DINPUT.dll; the CP installer will then install your DINPUT.dll as AiO.dll, and my DINPUT.dll has that listed in its import table.
The only function of the InjectDLL shim will be to check if the DINPUT.dll is still the CP version; I don't want to put any other functionality in the shim, in case it doesn't actually activate for whatever reason.
(In particular, are those shims even supported in WINE?)
Out of curiosity, was there a lot of assembly work in your other fixes?
My fixes are almost entirely in assembly.
To be fair, I find C/C++ much too confusing for my tastes - additionally, setting up the build environment for that is like being flipped off with a middle finger the size of Burj Khalifa.
I very much prefer easier languages, such as assembly.
Some of the patch logic is instead written in Pascal (Lazarus), mostly because of the conveniences it provides for working with strings, floats, and/or file IO - as well as the forms (although there are of course no forms in the Drakan.exe patches - not
yet, anyway).
Currently that means all of my DEM importer code (as well as the GUI for my upcoming layer visibility calculation code); the file parser for the dedicated server player name reservation feature has also been written in Lazarus.
As for the assembly part, I use a combination of 3 approaches: "usual" hooking by overwriting jump/call addresses, overwriting procedure entry points (a'la Detours), or assembling new code directly in place (if it's only a few opcodes and there is enough space for them).
The KERNEL32.GetProcAddress hook instead takes advantage of the hotpatch allowance provided by Microsoft (5 NOPs, then MOV EDI,EDI at proc entry).
MOV EDI,EDI gets overwritten last, to ensure that the proc entry point always contains valid code at all times.
BTW: I plan to release the source for those fixes when I release the next CP build; there's no point in releasing the source earlier, since that'll be the first release of those fixes, and even that initial version is not complete yet.
EDIT: In fact, I've just gone over some of my previous code; in particular, ended up completely redoing the way the keybindings are remapped in the 3D View - my previous approach to dealing with it was so clunky, it was a miracle it worked at all.
Go to 0x438594; the function was moved up a bit to make space for extra conditional check
Hmm, not sure I quite follow what's going on there.
I can clearly see that the circumstances leading to the infinite loop are now accounted for, breaking out of the loop if that's the case - but what's the actual meaning of [EAX + 8]?
And how does that relate to my earlier tests, where manually breaking out of the infinite loop made the engine stubbornly wind up straight back inside it anyway?
In other news: since with this, my patch for Engine.exe is complete for the time being, I've attached the source for it.
Currently it performs 2 functions:
- Detects invisible 16-bit textures (full transparency) at load time and replaces them with a procedurally-generated visible texture,
- Allows moving the camera with WASD + left SHIFT & CTRL (hold V to slow down the movement speed); but these keybindings are not really usable in practice without also using the modified Editor binary, though - due to the resulting keybinding conflicts between the patched 3D View and the unpatched Editor.
I've also attached the source for my NULL renderer.
It's originally been written as a straight-up replacement for DDRAW.dll - but since that would have caused other problems, I've modified it to be a standalone DLL.
So instead of replacing whichever version of DDRAW.dll would get normally loaded, my patch code simply hooks DDRAW.dll if Drakan is launched with "-dedicated -norender" commandline params.
I've tested that already, and it works beautifully
BTW:
I've tried to reproduce the texture loading issues, but failed miserably.
However, I DID notice another problem, where LFE's cause increasing amounts of lag, proportional to the amount of playing time. More verbose description at the link above.