From 7275a593a62dd637bc32e373dc9d9ddfb91da6cb Mon Sep 17 00:00:00 2001 From: Daniel Gibson Date: Thu, 14 Jan 2021 03:53:47 +0100 Subject: [PATCH] Fix architecture detection on Windows in Makefile, bump SAVEGAMEVER .. and use YQ2ARCH and YQ2OSTYPE instead of just ARCH and OSTYPE for the defines, so it's consistent with the engine and xatrix+rogue. $PROCESSOR_ARCHITECTURE seems to contain the architecture of the host, but we need the architecture the current MinGW shell is targeting. $MINGW_CHOST seems to be just that, and on my system it's either i686-w64-mingw32 (mingw32.exe) or x86_64-w64-mingw32 (mingw64.exe) (No idea what it looks like for Windows on ARM...) As fixing this would otherwise break existing savegames, I bumped the SAVEGAMEVER to "YQ2-4" and added a quirk for older savegameversions: On Windows i386 savegames that contain "AMD64" instead of "i386" as architecture are also accepted. (For YQ2-1 this didn't seem necessary, apparently "i386" was hardcoded) --- CMakeLists.txt | 4 +- Makefile | 46 ++++++++---- src/savegame/savegame.c | 156 ++++++++++++++++++++-------------------- 3 files changed, 113 insertions(+), 93 deletions(-) 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;