There are some things we do have to test with any replatforming, that a couple of people have hinted at: collision problems, visportal problems, light-interaction problems, possibly (but unconfirmed) ai pathing.
The light interaction problems are specific to MS Visual Studio. The VP and collision problems are down to different floating-point architecture in MSVS 2012 and above. Prior to msvs2012, the intermediate results of 32-bit floating point calculations were 80-bit. From 2012, they are truncated to 32-bit. You can see the difference with this bit of test code:
float a = -272.514099f;
float b = -272.514160f;
float c = -93.7499619f;
float d = -93.7499771f;
float e = d * a; // Result: 25548.1914
float f = b * c; // Result: 25548.1914
float g = e - f; // Result: 0.0f
float h = d * a - b * c; // Result in 2013: 0.
// Result in 2010: -0.00156380842
That's a real example I tracked down in a map where a visportal was glitching, when we experimented with using the vs2013 compilers. We need to check the result of that test code in any new compiler setup.
There are parts of the game and engine that rely on the greater intermediate precision. That problem stalled our work on the 64-bit build during 2.03 development. We could fix the problem for any given line of code by using doubles, but we have no way to track down all the places that need the fix. The resulting bugs are rare and hard to rep.
I've been doing a little reading about floating point promotions in C/C++, and dependence on extra precision on intermediates calculations is technically a bug. From what I've seen, there is no requirement in C/C++ standards to promote to double/long double on calculations with only floats, so a compiler can keep things as floats if it wants. This means MSVS2012+ does conform to the standard, even if it's not the desired behaviour. This is a problem that will need to be solved when TDM is ported to a CPU that doesn't give extra precision for free.
Based on some tests with GCC (see below), what I suspect what might be happening with MSVS2012+ is that it's using SSE to perform floating point calculations (by compiling for 64 bit, you implicitly have a CPU with SSE support). Because that can operate with single precision directly, it will give you single precision intermediate results. MSVS2012+ might work if you disable SSE for floating point (or force 387 FPU).
I did some quick tests with your code snippet in GCC and found the following results:
$ gcc -g test.c && ./a.out
$ gcc -m32 -g test.c && ./a.out
$ gcc -mfpmath=sse -g test.c && ./a.out
$ gcc -mfpmath=387 -g test.c && ./a.out
$ gcc -march=x86-64 -m32 -mfpmath=sse -g test.c && ./a.out
The first test compiles to 64 bit (x86-64) with just the default settings for the architecture. This exhibits the rounding bug.
The second test compiles to 32 bit (i386) , again with defaults for the architecture. This does not exhibit the rounding bug.
The third test compiles to 64 bit (x86-64) with the SSE used for floating point results. This is the same as the first test and exhibits the rounding bug.
The fourth test compiles to 64 bit (x86-64) with the 387 used for floating point results. This gives the correct result.
The fifth test compiles to 32 bit but with the x86-64 instruction set, and the SSE used for floating point results. This exhibits the rounding bug.
The above to me indicates that the use of SSE is causing it to round to float with every calculation, so is the probably the cause of the glitches you witnessed in your 64 bit port.
After the above discovery, I decided to add -mfpmath=387 the CMake file and recompile from scratch. After doing so there were no noticeable changes on the known bugs for my 64 bit port. AIs are still blind to the player, some AIs just "stand still", and the skybox still changes colour. So, it indicates these bugs aren't due to intermediate precision and rounding.
Since then I have made some futher observations about those bugs:
AI blindness seems to apply only to the player, as they notice things like bodies and open doors.
The random colour of the skybox seems to be taking its colour from the lower left pixel of the screen. As for when it happens, I suspect it happens when certain things are in your field of view (or at least potentially visible). Holding a candle seems to provoke it more.
Knocking out a "standing still" AI while its completely unaware knocks it out but they remain upright with no visible sign that they're knocked out. If they're doing the walking on the spot thing, they'll continue to do it while asleep. The only way to tell if they're knocked out is if you bump into them and see if they react. If they're slightly suspicious they'll drop immediately. Much the same happens if you kill them while they're unaware, although death is more obvious when they don't react to damage or the arrow sticking out of them. I have dug into it much still, but I suspect the animation system is getting stuck in a state for certain AIs, and it only breaks out for certain conditions (such as suspicions and alerts).
Nice diagnosis. I've seen those string pointers misused before and winced, but only in debug code. Lots of ::Print() functions return a pointer to freed memory too. Debug print functions tend to pass the pointers uncopied to the console, which'll try to access them later. You occasionally see garbage on the console as a result if you have debug logging on.
Thanks. Stuff like stale pointers and such are things that should be fix at some point in time (even if they're just in debug mode). One thing that bothered me in the code base was seeing the use of sprintf() style functions instead of snprintf() style.
Edited by NagaHuntress, 13 August 2015 - 10:30 AM.