diff --git a/CMakeLists.txt b/CMakeLists.txt index 5348393..769be70 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,13 +19,13 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -fno-strict-aliasing -fwrapv") string(REPLACE "-O3" "-O2" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") # Operating system -add_definitions(-DOSTYPE="${CMAKE_SYSTEM_NAME}") +add_definitions(-DYQ2OSTYPE="${CMAKE_SYSTEM_NAME}") # Architecture string string(REGEX REPLACE "amd64" "x86_64" ARCH "${CMAKE_SYSTEM_PROCESSOR}") string(REGEX REPLACE "i.86" "i386" ARCH "${ARCH}") string(REGEX REPLACE "^arm.*" "arm" ARCH "${ARCH}") -add_definitions(-DARCH="${ARCH}") +add_definitions(-DYQ2ARCH="${ARCH}") # Linker Flags if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") diff --git a/Makefile b/Makefile index f1f860a..9819467 100644 --- a/Makefile +++ b/Makefile @@ -16,28 +16,36 @@ # Detect the OS ifdef SystemRoot -OSTYPE := Windows +YQ2_OSTYPE := Windows else -OSTYPE := $(shell uname -s) +YQ2_OSTYPE := $(shell uname -s) endif # Special case for MinGW -ifneq (,$(findstring MINGW,$(OSTYPE))) -OSTYPE := Windows +ifneq (,$(findstring MINGW,$(YQ2_OSTYPE))) +YQ2_OSTYPE := Windows endif # Detect the architecture -ifeq ($(OSTYPE), Windows) +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 -ARCH := $(PROCESSOR_ARCHITEW6432) +YQ2_ARCH ?= $(PROCESSOR_ARCHITEW6432) else # 32 bit Windows -ARCH := $(PROCESSOR_ARCHITECTURE) +YQ2_ARCH ?= $(PROCESSOR_ARCHITECTURE) endif +endif # windows but MINGW_CHOST not defined else -# Normalize some abiguous ARCH strings -ARCH := $(shell uname -m | sed -e 's/i.86/i386/' -e 's/amd64/x86_64/' -e 's/^arm.*/arm/') +# 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/') endif # Detect the compiler @@ -71,7 +79,7 @@ endif # -fPIC for position independend code. # # -MMD to generate header dependencies. -ifeq ($(OSTYPE), Darwin) +ifeq ($(YQ2_OSTYPE), Darwin) CFLAGS := -O2 -fno-strict-aliasing -fomit-frame-pointer \ -Wall -pipe -g -fwrapv -arch i386 -arch x86_64 else @@ -97,13 +105,23 @@ endif # ---------- +# 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) +override CFLAGS += -msse -mfpmath=sse +endif + +# ---------- + # Defines the operating system and architecture -CFLAGS += -DOSTYPE=\"$(OSTYPE)\" -DARCH=\"$(ARCH)\" +CFLAGS += -DYQ2OSTYPE=\"$(YQ2_OSTYPE)\" -DYQ2ARCH=\"$(YQ2_ARCH)\" # ---------- # Base LDFLAGS. -ifeq ($(OSTYPE), Darwin) +ifeq ($(YQ2_OSTYPE), Darwin) LDFLAGS := -shared -arch i386 -arch x86_64 else LDFLAGS := -shared @@ -140,7 +158,7 @@ clean: # ---------- # The zaero game -ifeq ($(OSTYPE), Windows) +ifeq ($(YQ2_OSTYPE), Windows) zaero: @echo "===> Building game.dll" ${Q}mkdir -p release @@ -246,7 +264,7 @@ ZAERO_DEPS= $(ZAERO_OBJS:.o=.d) # ---------- -ifeq ($(OSTYPE), Windows) +ifeq ($(YQ2_OSTYPE), Windows) release/game.dll : $(ZAERO_OBJS) @echo "===> LD $@" ${Q}$(CC) $(LDFLAGS) -o $@ $(ZAERO_OBJS) diff --git a/src/savegame/savegame.c b/src/savegame/savegame.c index ea80e21..741b080 100644 --- a/src/savegame/savegame.c +++ b/src/savegame/savegame.c @@ -54,19 +54,19 @@ * in tables/ are changed, otherwise * strange things may happen. */ -#define SAVEGAMEVER "YQ2-3" +#define SAVEGAMEVER "YQ2-4" /* * This macros are used to prohibit loading of savegames * created on other systems or architectures. This will * crash q2 in spectacular ways */ -#ifndef OSTYPE -#error OSTYPE should be defined by the build system +#ifndef YQ2OSTYPE +#error YQ2OSTYPE should be defined by the build system #endif -#ifndef ARCH -#error ARCH should be defined by the build system +#ifndef YQ2ARCH +#error YQ2ARCH should be defined by the build system #endif /* @@ -766,8 +766,8 @@ WriteGame(const char *filename, qboolean autosave) strncpy(str_ver, SAVEGAMEVER, sizeof(str_ver)); strncpy(str_game, GAMEVERSION, sizeof(str_game)); - strncpy(str_os, OSTYPE, sizeof(str_os) - 1); - strncpy(str_arch, ARCH, sizeof(str_arch)); + strncpy(str_os, YQ2OSTYPE, sizeof(str_os) - 1); + strncpy(str_arch, YQ2ARCH, sizeof(str_arch)); fwrite(str_ver, sizeof(str_ver), 1, f); fwrite(str_game, sizeof(str_game), 1, f); @@ -817,85 +817,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 an other game.so.\n"); - } - else if (strcmp(str_os, OSTYPE)) - { - fclose(f); - gi.error("Savegame from an other os.\n"); - } - else if (strcmp(str_arch, ARCH)) - { - fclose(f); - gi.error("Savegame from an other architecure.\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 an other game.so.\n"); - } - else if (strcmp(str_os, OSTYPE)) - { - fclose(f); - gi.error("Savegame from an other os.\n"); - } - else if (strcmp(str_arch, ARCH)) - { - fclose(f); - gi.error("Savegame from an other architecure.\n"); - } - } - else if (!strcmp(str_ver, "YQ2-1")) - { - save_ver = 1; - - if (strcmp(str_game, GAMEVERSION)) - { - fclose(f); - gi.error("Savegame from an other game.so.\n"); - } - else if (strcmp(str_os, OSTYPE_1)) - { - fclose(f); - gi.error("Savegame from an other os.\n"); - } - - if (!strcmp(str_os, "Windows")) - { - /* Windows was forced to i386 */ - if (strcmp(str_arch, "i386")) - { - fclose(f); - gi.error("Savegame from an other architecure.\n"); - } - } - else - { - if (strcmp(str_arch, ARCH_1)) - { - fclose(f); - gi.error("Savegame from an other architecure.\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;