Sorry, meant to send this to the list first time around...
But I narrowed it down to 3 Wine calls in the critical loop: SetEvent, WaitForSingleObject and ResetEvent. I tried wrapping each of these functions with __asm__("pushfl\n"); at the start and __asm__("popfl\n"); at the end to preserve the flags - with this, PECrypt works fine and the game gets as far as trying to initialise DirectX. Not exactly a neat fix though.
Did you have to do all of them, or is it just one function that needs this treatment?
SetEvent definitely needs it. The others possibly don't. But I think it would be more robust to preserve the flag through all of them anyway, in case someone makes a change in future that causes one of the others to clear the direction flag too, which seems quite possible.
Are you sure it's not that we need to set the flag before
jumping to the entrypoint?
The flag is normally cleared. PECrypt sets it explicitly, then expects it to remain set across those three API calls.
PECrypt sounds like it should run very early on in the programs lifetime: how much stuff does it do before hitting this bug?
AFAIK, PECrypt just decrypts and decompresses the executable at startup, then it goes away and the program runs as normal. This bug does happen very early on.
If there is really widespread software that depends on this behaviour though there is precedent for including a hack for it - see the DllMain wrapper which preserves %ebx for an example.
Certainly anything compressed with PECrypt will depend on the flag being preserved. In general I'd imagine it's quite rare for programs to run with the direction flag set for long periods though.
Cheers, James