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)
This commit is contained in:
Daniel Gibson 2021-01-14 03:53:47 +01:00
parent 40fb2366d1
commit 7275a593a6
3 changed files with 113 additions and 93 deletions

View file

@ -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")

View file

@ -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)

View file

@ -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)
{
fclose(f);
gi.error("Savegame from an other game.so.\n");
if (strcmp(version_mappings[i].verstr, str_ver) == 0)
{
save_ver = version_mappings[i].vernum;
break;
}
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-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;