diff --git a/Makefile b/Makefile index 89d9aadb..aaef71c3 100755 --- a/Makefile +++ b/Makefile @@ -96,6 +96,13 @@ endif # Detect the architecture ifeq ($(YQ2_OSTYPE), Windows) +ifdef MINGW_CHOST +ifeq ($(MINGW_CHOST), x86_64-w64-mingw32) +YQ2_ARCH ?= x86_64 +else # i686-w64-mingw32 +YQ2_ARCH ?= i386 +endif +else # windows, but MINGW_CHOST not defined ifdef PROCESSOR_ARCHITEW6432 # 64 bit Windows YQ2_ARCH ?= $(PROCESSOR_ARCHITEW6432) @@ -103,6 +110,7 @@ else # 32 bit Windows YQ2_ARCH ?= $(PROCESSOR_ARCHITECTURE) endif +endif # windows but MINGW_CHOST not defined else # Normalize some abiguous YQ2_ARCH strings YQ2_ARCH ?= $(shell uname -m | sed -e 's/i.86/i386/' -e 's/amd64/x86_64/' -e 's/^arm.*/arm/') @@ -216,13 +224,12 @@ endif # ---------- -# If we're building with gcc for i386 let's define -ffloat-store. -# This helps the old and crappy x87 FPU to produce correct values. -# Would be nice if Clang had something comparable. +# Using the default x87 float math on 32bit x86 causes rounding trouble +# -ffloat-store could work around that, but the better solution is to +# just enforce SSE - every x86 CPU since Pentium3 supports that +# and this should even improve the performance on old CPUs ifeq ($(YQ2_ARCH), i386) -ifeq ($(COMPILER), gcc) -override CFLAGS += -ffloat-store -endif +override CFLAGS += -msse -mfpmath=sse endif # Force SSE math on x86_64. All sane compilers should do this @@ -378,6 +385,7 @@ all: config client server game ref_gl1 ref_gl3 ref_soft ref_vk config: @echo "Build configuration" @echo "============================" + @echo "YQ2_ARCH = $(YQ2_ARCH) COMPILER = $(COMPILER)" @echo "WITH_CURL = $(WITH_CURL)" @echo "WITH_OPENAL = $(WITH_OPENAL)" @echo "WITH_REFVK = $(WITH_REFVK)" diff --git a/src/game/savegame/savegame.c b/src/game/savegame/savegame.c index 3889c93b..f15ae38c 100644 --- a/src/game/savegame/savegame.c +++ b/src/game/savegame/savegame.c @@ -71,7 +71,7 @@ * load older savegames. This should be bumped if the files * in tables/ are changed, otherwise strange things may happen. */ -#define SAVEGAMEVER "YQ2-3" +#define SAVEGAMEVER "YQ2-4" #ifndef BUILD_DATE #define BUILD_DATE __DATE__ @@ -851,85 +851,87 @@ ReadGame(const char *filename) fread(str_os, sizeof(str_os), 1, f); fread(str_arch, sizeof(str_arch), 1, f); - if (!strcmp(str_ver, SAVEGAMEVER)) - { - save_ver = 3; + static const struct { + const char* verstr; + int vernum; + } version_mappings[] = { + {"YQ2-1", 1}, + {"YQ2-2", 2}, + {"YQ2-3", 3}, + {"YQ2-4", 4}, + }; - if (strcmp(str_game, GAMEVERSION)) + for (i=0; i < sizeof(version_mappings)/sizeof(version_mappings[0]); ++i) + { + if (strcmp(version_mappings[i].verstr, str_ver) == 0) { - fclose(f); - gi.error("Savegame from another game.so.\n"); - } - else if (strcmp(str_os, YQ2OSTYPE)) - { - fclose(f); - gi.error("Savegame from another os.\n"); - } - else if (strcmp(str_arch, YQ2ARCH)) - { - fclose(f); - gi.error("Savegame from another architecture.\n"); + save_ver = version_mappings[i].vernum; + break; } } - else if (!strcmp(str_ver, "YQ2-2")) - { - save_ver = 2; - if (strcmp(str_game, GAMEVERSION)) - { - fclose(f); - gi.error("Savegame from another game.so.\n"); - } - else if (strcmp(str_os, YQ2OSTYPE)) - { - fclose(f); - gi.error("Savegame from another os.\n"); - } - else if (strcmp(str_arch, YQ2ARCH)) - { - fclose(f); - gi.error("Savegame from another architecture.\n"); - } - } - else if (!strcmp(str_ver, "YQ2-1")) - { - save_ver = 1; - - if (strcmp(str_game, GAMEVERSION)) - { - fclose(f); - gi.error("Savegame from another game.so.\n"); - } - else if (strcmp(str_os, OSTYPE_1)) - { - fclose(f); - gi.error("Savegame from another os.\n"); - } - - if (!strcmp(str_os, "Windows")) - { - /* Windows was forced to i386 */ - if (strcmp(str_arch, "i386")) - { - fclose(f); - gi.error("Savegame from another architecture.\n"); - } - } - else - { - if (strcmp(str_arch, ARCH_1)) - { - fclose(f); - gi.error("Savegame from another architecture.\n"); - } - } - } - else + if (save_ver == 0) // not found in mappings table { fclose(f); gi.error("Savegame from an incompatible version.\n"); } + if (save_ver == 1) + { + if (strcmp(str_game, GAMEVERSION) != 0) + { + fclose(f); + gi.error("Savegame from another game.so.\n"); + } + else if (strcmp(str_os, OSTYPE_1) != 0) + { + fclose(f); + gi.error("Savegame from another os.\n"); + } + +#ifdef _WIN32 + /* Windows was forced to i386 */ + if (strcmp(str_arch, "i386") != 0) + { + fclose(f); + gi.error("Savegame from another architecture.\n"); + } +#else + if (strcmp(str_arch, ARCH_1) != 0) + { + fclose(f); + gi.error("Savegame from another architecture.\n"); + } +#endif + } + else // all newer savegame versions + { + if (strcmp(str_game, GAMEVERSION) != 0) + { + fclose(f); + gi.error("Savegame from another game.so.\n"); + } + else if (strcmp(str_os, YQ2OSTYPE) != 0) + { + fclose(f); + gi.error("Savegame from another os.\n"); + } + else if (strcmp(str_arch, YQ2ARCH) != 0) + { +#if defined(_WIN32) && (defined(__i386__) || defined(_M_IX86)) + // before savegame version "YQ2-4" (and after version 1), + // the official Win32 binaries accidentally had the YQ2ARCH "AMD64" + // instead of "i386" set due to a bug in the Makefile. + // This quirk allows loading those savegames anyway + if (save_ver >= 4 || strcmp(str_arch, "AMD64") != 0) +#endif + { + fclose(f); + gi.error("Savegame from another architecture.\n"); + } + } + } + g_edicts = gi.TagMalloc(game.maxentities * sizeof(g_edicts[0]), TAG_GAME); globals.edicts = g_edicts;