diff --git a/Makefile b/Makefile index 159ce58..e26e72e 100644 --- a/Makefile +++ b/Makefile @@ -28,19 +28,16 @@ endif # Detect the architecture ifeq ($(OSTYPE), Windows) -# At this time only i386 is supported on Windows -ARCH := i386 -# seems like mingw doesn't set CC by default -CC := gcc +ifdef PROCESSOR_ARCHITEW6432 +# 64 bit Windows +ARCH := $(PROCESSOR_ARCHITEW6432) else -# Some platforms call it "amd64" and some "x86_64" -ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/amd64/x86_64/) +# 32 bit Windows +ARCH := $(PROCESSOR_ARCHITECTURE) endif - -# Refuse all other platforms as a firewall against PEBKAC -# (You'll need some #ifdef for your unsupported plattform!) -ifeq ($(findstring $(ARCH), i386 x86_64 sparc64 ia64),) -$(error arch $(ARCH) is currently not supported) +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/') endif # ---------- @@ -73,6 +70,11 @@ endif # ---------- +# Defines the operating system and architecture +CFLAGS += -DOSTYPE=\"$(OSTYPE)\" -DARCH=\"$(ARCH)\" + +# ---------- + # Base LDFLAGS. ifeq ($(OSTYPE), Darwin) LDFLAGS := -shared -arch i386 -arch x86_64 diff --git a/src/header/local.h b/src/header/local.h index f59cbfb..70d543e 100644 --- a/src/header/local.h +++ b/src/header/local.h @@ -641,6 +641,7 @@ typedef struct int ofs; fieldtype_t type; int flags; + short save_ver; } field_t; diff --git a/src/savegame/savegame.c b/src/savegame/savegame.c index 2a30e0f..5046823 100644 --- a/src/savegame/savegame.c +++ b/src/savegame/savegame.c @@ -54,40 +54,49 @@ * in tables/ are changed, otherwise * strange things may happen. */ -#define SAVEGAMEVER "YQ2-2" +#define SAVEGAMEVER "YQ2-3" /* - * This macros are used to - * prohibit loading of savegames - * created on other systems or - * architectures. This will - * crash q2 in spectecular - * ways + * This macros are used to prohibit loading of savegames + * created on other systems or architectures. This will + * crash q2 in spectacular ways */ -#if defined(__FreeBSD__) - #define OS "FreeBSD" -#elif defined(__APPLE__) - #define OS "MacOS X" +#ifndef OSTYPE +#error OSTYPE should be defined by the build system +#endif + +#ifndef ARCH +#error ARCH should be defined by the build system +#endif + +/* + * Older operating system and architecture detection + * macros, implemented by savegame version YQ2-1. + */ +#if defined(__APPLE__) +#define OSTYPE_1 "MacOS X" +#elif defined(__FreeBSD__) +#define OSTYPE_1 "FreeBSD" #elif defined(__OpenBSD__) - #define OS "OpenBSD" +#define OSTYPE_1 "OpenBSD" #elif defined(__linux__) - #define OS "Linux" + #define OSTYPE_1 "Linux" #elif defined(_WIN32) - #define OS "Windows" + #define OSTYPE_1 "Windows" #else - #define OS "Unknown" + #define OSTYPE_1 "Unknown" #endif #if defined(__i386__) - #define ARCH "i386" +#define ARCH_1 "i386" #elif defined(__x86_64__) - #define ARCH "amd64" +#define ARCH_1 "amd64" #elif defined(__sparc__) - #define ARCH "sparc64" +#define ARCH_1 "sparc64" #elif defined(__ia64__) - #define ARCH "ia64" + #define ARCH_1 "ia64" #else - #define ARCH "unknown" + #define ARCH_1 "unknown" #endif /* @@ -692,7 +701,7 @@ WriteClient(FILE *f, gclient_t *client) * Read the client struct from a file */ void -ReadClient(FILE *f, gclient_t *client) +ReadClient(FILE *f, gclient_t *client, short save_ver) { field_t *field; @@ -701,6 +710,16 @@ ReadClient(FILE *f, gclient_t *client) for (field = clientfields; field->name; field++) { ReadField(f, field, (byte *)client); + + if (field->save_ver <= save_ver) + { + ReadField(f, field, (byte *)client); + } + } + + if (save_ver < 3) + { + InitClientResp(client); } } @@ -746,7 +765,7 @@ WriteGame(const char *filename, qboolean autosave) strncpy(str_ver, SAVEGAMEVER, sizeof(str_ver)); strncpy(str_game, GAMEVERSION, sizeof(str_game)); - strncpy(str_os, OS, sizeof(str_os)); + strncpy(str_os, OSTYPE, sizeof(str_os) - 1); strncpy(str_arch, ARCH, sizeof(str_arch)); fwrite(str_ver, sizeof(str_ver), 1, f); @@ -780,6 +799,7 @@ ReadGame(const char *filename) char str_game[32]; char str_os[32]; char str_arch[32]; + short save_ver = 0; gi.FreeTags(TAG_GAME); @@ -796,27 +816,84 @@ 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)) + if (!strcmp(str_ver, SAVEGAMEVER)) + { + save_ver = 3; + + 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-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 { fclose(f); gi.error("Savegame from an incompatible version.\n"); } - else if (strcmp(str_game, GAMEVERSION)) - { - fclose(f); - gi.error("Savegame from an other game.so.\n"); - } - else if (strcmp(str_os, OS)) - { - 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"); - } g_edicts = gi.TagMalloc(game.maxentities * sizeof(g_edicts[0]), TAG_GAME); globals.edicts = g_edicts; @@ -827,7 +904,7 @@ ReadGame(const char *filename) for (i = 0; i < game.maxclients; i++) { - ReadClient(f, &game.clients[i]); + ReadClient(f, &game.clients[i], save_ver); } fclose(f); diff --git a/src/savegame/tables/clientfields.h b/src/savegame/tables/clientfields.h index 2e2491c..1469277 100644 --- a/src/savegame/tables/clientfields.h +++ b/src/savegame/tables/clientfields.h @@ -12,4 +12,7 @@ {"newweapon", CLOFS(newweapon), F_ITEM}, {"", CLOFS(zCameraTrack), F_EDICT}, {"", CLOFS(zCameraLocalEntity), F_EDICT}, +{"resp.coop_respawn.weapon", CLOFS(resp.coop_respawn.weapon), F_ITEM, 0, 3}, +{"resp.coop_respawn.lastweapon", CLOFS(resp.coop_respawn.lastweapon), F_ITEM, 0, 3}, +{"resp.coop_respawn.lastweapon2", CLOFS(resp.coop_respawn.lastweapon2), F_ITEM, 0, 3}, {NULL, 0, F_INT} diff --git a/src/savegame/tables/gamefunc_decs.h b/src/savegame/tables/gamefunc_decs.h index 23bcab6..9cc08b0 100644 --- a/src/savegame/tables/gamefunc_decs.h +++ b/src/savegame/tables/gamefunc_decs.h @@ -14,7 +14,7 @@ extern void WriteLevelLocals ( FILE * f ) ; extern void WriteEdict ( FILE * f , edict_t * ent ) ; extern void ReadGame ( const char * filename ) ; extern void WriteGame ( const char * filename , qboolean autosave ) ; -extern void ReadClient ( FILE * f , gclient_t * client ) ; +extern void ReadClient ( FILE * f , gclient_t * client , short save_ver ) ; extern void WriteClient ( FILE * f , gclient_t * client ) ; extern void ReadField ( FILE * f , field_t * field , byte * base ) ; extern void WriteField2 ( FILE * f , field_t * field , byte * base ) ;