The mystery is solved!
When I did a clean boot then XG-2 always ran at ~30 FPS, as expected. I experimented with global Windows resolution timer without avail, XG-2 still ran fine.
(I tried XG-2 with the 15.6ms default system timer resolution, then, knowing that WPF sometimes sets it to 1ms, launching a compile in Visual Studio was enough to force it to 1ms, I always checked it.)
Everything was fine, so gave up and started to work on other things. Then later I re-tried XG-2 and it ran at 13 FPS!! I had no a clue why because I didn't do anything special inbetween.
I worked myself up into debugging to see what the f*ck was going on but all I saw that the game timing heavily relied on timeGetTime.
When low FPS' were produced it was just spinning in a loop, decreasing a very high counter towards zero.
Ok, so that was the cause but why was the counter so high? It came from a global that the game constantly updated and its value was ~10 or so when the game was starting up. But later, it went up to ~17000000.
All in all, debugging out where that global is updated, it turned out that XG-2 calls timeGetTime to query the current time. Need to know, that timeGetTime returns the time that has elapsed since Windows was started, in ms.
XG-2 divided it by 30 (the hardwired frame rate), to get how many frame would have been rendered if XG-2 were launched along with Windows (absolute frame number instead of relative). A bit weird, but it's ok after all.
The problem itself was that time value was stored into a global 32 bit float and that has only 23 bit precision, so, if one calculates it all it turns out that the float loses its precision after Windows is been running for about 3 days without rebooting.
Later in the spinning loop, it tried to substract 1.0 from that precision-loss float in each iteration but the counter remained the same (because the lowest bit of the integer couldn't be stored in the float). So, it always resulted in tons of iterations, hence the low fps. 😵
What is also very nice, is that the more time is Windows running for, the less fps you get because the float loses more and more precision. So I guess if I run my windows a few more days I'll only get 5-6 FPS's instead of 13.
Since rewriting the code by changing the float in question to a double would take too much time, I experimented with a stub WINMM.DLL where timeGetTime returns a value having the highest 8 bits masked out, to keep only the lower 24.
And voila, XG-2 ran at 34 FPS again.
😎
I also experimented with time dilating by scaling the value of timeGetTime and the game speed indeed changed. The only problem is, FPS changes too. Game logic and render speed are tied together in XG-2.