- clobber the whole x87 state for mmx (emms alone requires this)
- add all modified registers to clobber list
(in some cases use dummy output vars instead)
- use symbolic names
- use more relaxed constraints where possible
- allow gcc to allocate ebx replacement reg
The tags are often initially assigned from pointers and then copied
around, even from one tag type to the other.
As BSPTree::MoveSubTreeToArray() uses them to get the original pointer,
we need the pointers anyway, so just CRC-ing the pointers doesn't seem
like a good option. As the tags are assigned from other tag-types
sometimes, I probably would have needed to add Pointers for the same
values in addition to the ULONG tags, that are also copied around along
the tags, to keep the tags ULONG - that seemed like a worse alternative.
However, when writing (via BSPTree::Write_t()) the bn_ulPlaneTag tag
needs to be ULONG, so there I actually use CRC for 64bit pointers (via
IntPtrToID()) - when restoring (in Read_t()), the pointers aren't valid
anymore anyway, so that all should somehow be fine.
I assume that Write_t() is only used by the Editor, anyway, so I fear I
won't be able to test that part of the code on Linux anytime soon.
Sometimes pointers are casted to ULONG just to get an ID or tag - this
is fine for 32bit pointers, but 64bit pointers will truncate which might
result in not being so unique after all.
CRC-ing the pointer should yield a more likely to be unique 32bit value.
NULL is a special case that yields 0 instead of the CRC, so code that
handles IDs/Tags with value 0 differently will continue to work.
For 32bit builds, it just returns the pointer as ULONG.
turns out that using UINTPTR_MAX is a pain on several systems like
FreeBSD or even older Linux/glibc systems, so maybe let's not do that
anymore.
Now I check for known CPU-architectures instead.
I also added some sanity checks to make sure the detection was
correct.
bswap_32() is a function specific to Linux, unavailable on FreeBSD and
OS X. Instead of messing with other platform specific functions, #ifdef
and so on provide a fast inline implementation.
* td_pulObjects is explicitly set to NULL in the constructor - before
only td_ulObject was set to NONE (0), so on 64bit half of
td_pulObjects bytes would remain garbage
* only check td_ulObject for NONE if td_ctFrames <= 1 (until now it
would frequently check it for NONE even if td_ctFrames > 1, if
td_pulObjects was != NULL)
some versions of gcc want to inline DitherBitmap(), and this leads to trouble:
Sources/Engine/Graphics/Graphics.cpp:1167: Error: symbol `rowLoopE' is already defined
Sources/Engine/Graphics/Graphics.cpp:1170: Error: symbol `pixLoopEL' is already defined
...
((ULONG*)td_ulObject)[iFr] is fishy - and ULONG td_ulObject already is
in an union with ULONG* td_pulObjects, so use td_pulObjects when
appropriate (i.e. if td_ctFrames>1)
Also fixed some checks accordingly.
The code used to store the world pointer as a console variable
"pwoCurrentWorld" of type INDEX (int32) - that won't work for 64bit, so
I added CShell::SetCurrentWorld() and CShell::GetCurrentWorld() and
store it as a pointer.
introduced PLATFORM_32BIT and PLATFORM_64BIT macros, so you can do
#ifdef PLATFORM_64BIT if you need to.
I needed that for CDrawPort::GetID() to properly CRC a pointer.
Also added a sanity check in Engine/Base/Types.h that makes sure that
uintprt_t and size_t have the same size, as the code uses size_t to
store pointers (or cast from pointer to int) all over the place.
Made some "tags" from Engine/Templates/BSP_internal.h size_t instead of
ULONG - they're used to store pointers to identify vertices and such,
so they'd better be big enough to actually store a pointer.
Some more are still missing.
* FloatToInt() should now round correctly ot nearest, even for
negative numbers
* Log2() now calls log2f() instead of log10()*3.321 - no idea what the
previous code was about, I doubt it's faster (and the ASM code uses
something like log2, too).
* FastLog2() (for integers) now uses __builtin_clz() when building with
GCC/clang - the resulting ASM should be pretty similar to the inline
ASM below. I wonder why that function takes signed ints, log2(-1) in
reality is an irrational number (but the function returns 31)..
Also, both the inline ASM and my version return 0 for Log2(0), but
INT_MIN would be closer to the truth
* commented out FastMaxLog2(), it's unused.
* implemented _rotl() using a fast(er) trick from
http://blog.regehr.org/archives/1063
If you have...
void myfunc(char buf[16]) {
printf("%d\n", (int) sizeof (buf));
}
...this will print sizeof (char *) instead of 16, so this fixes a piece of
code that assumed the latter instead of the former.
Touches a lot of code to remove long constants like "1L", so this patch is
large and ugly, but I think it makes all those Clamp() calls look nicer in
the long run.
Most of the game is 64-bit clean, since we can build without assembly code
now. I've marked the things that are obviously still wrong with STUBBED lines.
That being said: a 64-bit build can already run the demos mostly correctly,
so we're actually almost there!
There are a few obvious things that are obviously wrong, to be fixed.
* Only use ENOSR and ENOPKG if defined
ENOSR and ENOPKG are part of the POSIX optional STREAMS extension, and
are not available on most other platforms than GNU/Linux.
* Support building on other GNU platforms than Linux
Build for other GNU platforms the same way as Linux: this includes
CMAKE_SYSTEM_NAME "GNU" (GNU/Hurd) and "GNU/kFreeBSD" (GNU/kFreeBSD).