[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#593981: marked as done (unblock: openarena/0.8.5-4 openarena-data/0.8.5-3)



Your message dated Wed, 25 Aug 2010 19:22:49 +0100
with message-id <1282760569.11253.279.camel@kaa.jungle.aubergine.my-net-space.net>
and subject line Re: Bug#593981: unblock: openarena/0.8.5-4 openarena-data/0.8.5-3
has caused the Debian Bug report #593981,
regarding unblock: openarena/0.8.5-4 openarena-data/0.8.5-3
to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what this
message is talking about, this may indicate a serious mail system
misconfiguration somewhere. Please contact owner@bugs.debian.org
immediately.)


-- 
593981: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=593981
Debian Bug Tracking System
Contact owner@bugs.debian.org with problems
--- Begin Message ---
Package: release.debian.org
Severity: normal
User: release.debian.org@packages.debian.org
Usertags: freeze-exception

(Cc'd to the bug being fixed, because updated patches are attached.)

I have patches ready to fix important bug
<http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=592965>, which is a failure
to interoperate with older servers (our 0.8.5 client with a 0.8.1 server),
caused by the way in which I patched openarena to be DFSG-compliant.

Changes are necessary in both openarena and openarena-data; I suggest
looking at the openarena diff first.

The openarena-data changes also update the binary blobs generated by
qvmbrute.c, which are included in the source tarball since re-generating them
is entirely deterministic and includes a brute-force step taking a few minutes.
The new versions contain more information, which is ignored by the current
openarena.

I've tested the current openarena with the upgraded openarena-data, so
if this turns out to introduce regressions, we can revert the changes to
openarena without needing a new openarena-data. The most likely failure mode
would be that it's incompatible with 0.8.1 in a way I haven't spotted,
in which case we've neither gained nor lost anything.

Thanks,
    Simon
diff --git a/debian/changelog b/debian/changelog
index b2204d6..8c780d3 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,13 @@
+openarena (0.8.5-4) UNRELEASED; urgency=low
+
+  * Build a second copy of the game logic and install it in a subdirectory.
+    It turns out that OpenArena 0.8.1 and 0.8.5 aren't network-compatible.
+  * Depend on openarena-data (>= 0.8.5-3~) which causes us to load the
+    0.8.1-compatible game logic whenever the upstream version would use
+    0.8.1's bytecode (Closes: #592965)
+
+ -- Simon McVittie <smcv@debian.org>  Sat, 21 Aug 2010 00:02:54 +0100
+
 openarena (0.8.5-3) unstable; urgency=medium
 
   * Add patch from oax r203 to fix server crashes if a player joins, then
diff --git a/debian/control b/debian/control
index fe3244e..10a6efa 100644
--- a/debian/control
+++ b/debian/control
@@ -14,7 +14,7 @@ Homepage: http://openarena.ws/
 Package: openarena
 Architecture: any
 Depends: ${misc:Depends}, ${shlibs:Depends},
-         openarena-data (>= 0.8.5), openarena-data (<< 0.8.6~),
+         openarena-data (>= 0.8.5-3~), openarena-data (<< 0.8.6~),
          openarena-server (= ${binary:Version})
 Description: fast-paced 3D first-person shooter
  OpenArena is an open-source content package for ioQuake3 licensed under the
diff --git a/debian/openarena-server.install b/debian/openarena-server.install
index 714e52f..e475b7d 100644
--- a/debian/openarena-server.install
+++ b/debian/openarena-server.install
@@ -1,2 +1,3 @@
 debian/tmp/usr/games/openarena-server
 debian/tmp/usr/lib/games/openarena/*/*.so
+debian/tmp/usr/lib/games/openarena/*/*/*.so
diff --git a/debian/patches/0040-Add-OPENARENA_081_COMPATIBLE-define-for-network-comp.patch b/debian/patches/0040-Add-OPENARENA_081_COMPATIBLE-define-for-network-comp.patch
new file mode 100644
index 0000000..56f590f
--- /dev/null
+++ b/debian/patches/0040-Add-OPENARENA_081_COMPATIBLE-define-for-network-comp.patch
@@ -0,0 +1,387 @@
+From aee4d733e1e9324e8392ecc0e024b50e3176b938 Mon Sep 17 00:00:00 2001
+From: Simon McVittie <smcv@debian.org>
+Date: Fri, 20 Aug 2010 23:27:28 +0100
+Subject: [PATCH] Add OPENARENA_081_COMPATIBLE define for network compat with 0.8.1
+
+0.8.1 was approximately compatible with Quake III Arena, whereas 0.8.5
+is more like Team Arena. Unfortunately, these are not the same.
+
+Not forwarded: upstream expect everyone to use the precompiled bytecode they
+supply, which was built from unmodified 0.8.5 and 0.8.1 source code. We're not
+doing that in Debian for DFSG reasons, and I'd rather not add a second complete
+copy of the source.
+
+Origin: vendor, Debian
+Bug: http://openarena.ws/board/index.php?topic=3717.0
+Bug-Debian: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=592965
+Forwarded: no
+---
+ game/Makefile              |    4 ++++
+ game/code/cgame/cg_draw.c  |    6 +++---
+ game/code/game/ai_dmq3.c   |    2 ++
+ game/code/game/bg_misc.c   |   15 ++++++++++++---
+ game/code/game/bg_pmove.c  |    2 ++
+ game/code/game/bg_public.h |   11 ++++++++++-
+ game/code/game/g_active.c  |   11 ++++++++++-
+ game/code/game/g_combat.c  |    4 ++++
+ game/code/game/g_items.c   |    9 ++++++++-
+ 9 files changed, 55 insertions(+), 9 deletions(-)
+
+diff --git a/game/Makefile b/game/Makefile
+index 1520a96..f3dd3f1 100644
+--- a/game/Makefile
++++ b/game/Makefile
+@@ -852,6 +852,10 @@ endif
+ 

+ BASE_CFLAGS += -DPRODUCT_VERSION=\\\"$(VERSION)\\\"

+ 

++ifeq ($(OPENARENA_081_COMPATIBLE),1)

++  BASE_CFLAGS += -DOPENARENA_081_COMPATIBLE

++endif

++

+ ifeq ($(V),1)

+ echo_cmd=@:

+ Q=

+diff --git a/game/code/cgame/cg_draw.c b/game/code/cgame/cg_draw.c
+index e4d2b2a..32f74dd 100644
+--- a/game/code/cgame/cg_draw.c
++++ b/game/code/cgame/cg_draw.c
+@@ -1890,7 +1890,6 @@ static void CG_DrawHoldableItem( void ) {
+ }
+ #endif // MISSIONPACK
+ 
+-#ifndef MISSIONPACK
+ /*
+ ===================
+ CG_DrawPersistantPowerup
+@@ -1898,6 +1897,7 @@ CG_DrawPersistantPowerup
+ */
+ #if 1 // sos001208 - DEAD // sago - ALIVE
+ static void CG_DrawPersistantPowerup( void ) { 
++#ifdef HAVE_STAT_PERSISTANT_POWERUP
+ 	int		value;
+ 
+ 	value = cg.snap->ps.stats[STAT_PERSISTANT_POWERUP];
+@@ -1905,9 +1905,9 @@ static void CG_DrawPersistantPowerup( void ) {
+ 		CG_RegisterItemVisuals( value );
+ 		CG_DrawPic( 640-ICON_SIZE, (SCREEN_HEIGHT-ICON_SIZE)/2 - ICON_SIZE, ICON_SIZE, ICON_SIZE, cg_items[ value ].icon );
+ 	}
++#endif
+ }
+ #endif
+-#endif // MISSIONPACK
+ 
+ 
+ /*
+@@ -3243,8 +3243,8 @@ static void CG_Draw2D(stereoFrame_t stereoFrame)
+ 
+                         #ifndef MISSIONPACK
+ 			CG_DrawHoldableItem();
+-			CG_DrawPersistantPowerup();
+ 			#endif
++			CG_DrawPersistantPowerup();
+ 
+                         CG_DrawReward();
+ 		}
+diff --git a/game/code/game/ai_dmq3.c b/game/code/game/ai_dmq3.c
+index 9037445..9731fdd 100644
+--- a/game/code/game/ai_dmq3.c
++++ b/game/code/game/ai_dmq3.c
+@@ -1881,10 +1881,12 @@ void BotUpdateInventory(bot_state_t *bs) {
+ 	bs->inventory[INVENTORY_INVISIBILITY] = bs->cur_ps.powerups[PW_INVIS] != 0;
+ 	bs->inventory[INVENTORY_REGEN] = bs->cur_ps.powerups[PW_REGEN] != 0;
+ 	bs->inventory[INVENTORY_FLIGHT] = bs->cur_ps.powerups[PW_FLIGHT] != 0;
++#ifdef HAVE_STAT_PERSISTANT_POWERUP
+ 	bs->inventory[INVENTORY_SCOUT] = bs->cur_ps.stats[STAT_PERSISTANT_POWERUP] == MODELINDEX_SCOUT;
+ 	bs->inventory[INVENTORY_GUARD] = bs->cur_ps.stats[STAT_PERSISTANT_POWERUP] == MODELINDEX_GUARD;
+ 	bs->inventory[INVENTORY_DOUBLER] = bs->cur_ps.stats[STAT_PERSISTANT_POWERUP] == MODELINDEX_DOUBLER;
+ 	bs->inventory[INVENTORY_AMMOREGEN] = bs->cur_ps.stats[STAT_PERSISTANT_POWERUP] == MODELINDEX_AMMOREGEN;
++#endif
+ 	bs->inventory[INVENTORY_REDFLAG] = bs->cur_ps.powerups[PW_REDFLAG] != 0;
+ 	bs->inventory[INVENTORY_BLUEFLAG] = bs->cur_ps.powerups[PW_BLUEFLAG] != 0;
+ 	bs->inventory[INVENTORY_NEUTRALFLAG] = bs->cur_ps.powerups[PW_NEUTRALFLAG] != 0;
+diff --git a/game/code/game/bg_misc.c b/game/code/game/bg_misc.c
+index 767cc7e..c701434 100644
+--- a/game/code/game/bg_misc.c
++++ b/game/code/game/bg_misc.c
+@@ -655,6 +655,7 @@ Only in CTF games
+ /* sounds */ ""
+ 	},
+ 
++#ifdef HAVE_MISSIONPACK_ITEMLIST
+ /*QUAKED holdable_kamikaze (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
+ */
+ 	{
+@@ -702,6 +703,7 @@ Only in CTF games
+ /* precache */ "",
+ /* sounds */ ""
+ 	},
++#endif
+ 
+ /*QUAKED ammo_nails (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
+ */
+@@ -751,6 +753,7 @@ Only in CTF games
+ /* sounds */ ""
+ 	},
+ 
++#ifdef HAVE_MISSIONPACK_ITEMLIST
+ 	//
+ 	// PERSISTANT POWERUP ITEMS
+ 	//
+@@ -817,6 +820,7 @@ Only in CTF games
+ /* precache */ "",
+ /* sounds */ ""
+ 	},
++#endif
+ 
+         
+ 	/*QUAKED team_CTF_neutralflag (0 0 1) (-16 -16 -16) (16 16 16)
+@@ -1214,6 +1218,9 @@ qboolean BG_CanItemBeGrabbed( int gametype, const entityState_t *ent, const play
+ 		return qtrue;
+ 
+ 	case IT_ARMOR:
++		upperBound = ps->stats[STAT_MAX_HEALTH] * 2;
++
++#ifdef HAVE_STAT_PERSISTANT_POWERUP
+ 		if( bg_itemlist[ps->stats[STAT_PERSISTANT_POWERUP]].giTag == PW_SCOUT ) {
+ 			return qfalse;
+ 		}
+@@ -1222,9 +1229,7 @@ qboolean BG_CanItemBeGrabbed( int gametype, const entityState_t *ent, const play
+ 		if( bg_itemlist[ps->stats[STAT_PERSISTANT_POWERUP]].giTag == PW_GUARD ) {
+ 			upperBound = ps->stats[STAT_MAX_HEALTH];
+ 		}
+-		else {
+-			upperBound = ps->stats[STAT_MAX_HEALTH] * 2;
+-		}
++#endif
+ 
+ 		if ( ps->stats[STAT_ARMOR] >= upperBound ) {
+ 			return qfalse;
+@@ -1232,12 +1237,14 @@ qboolean BG_CanItemBeGrabbed( int gametype, const entityState_t *ent, const play
+ 		return qtrue;
+ 
+ 	case IT_HEALTH:
++#ifdef HAVE_STAT_PERSISTANT_POWERUP
+ 		// small and mega healths will go over the max, otherwise
+ 		// don't pick up if already at max
+ 		if( bg_itemlist[ps->stats[STAT_PERSISTANT_POWERUP]].giTag == PW_GUARD ) {
+ 			upperBound = ps->stats[STAT_MAX_HEALTH];
+ 		}
+ 		else
++#endif
+ 		if ( item->quantity == 5 || item->quantity == 100 ) {
+ 			if ( ps->stats[STAT_HEALTH] >= ps->stats[STAT_MAX_HEALTH] * 2 ) {
+ 				return qfalse;
+@@ -1253,6 +1260,7 @@ qboolean BG_CanItemBeGrabbed( int gametype, const entityState_t *ent, const play
+ 	case IT_POWERUP:
+ 		return qtrue;	// powerups are always picked up
+ 
++#ifdef HAVE_STAT_PERSISTANT_POWERUP
+ 	case IT_PERSISTANT_POWERUP:
+ 
+ 		//In Double D we don't want persistant Powerups (or maybe, can be discussed)
+@@ -1273,6 +1281,7 @@ qboolean BG_CanItemBeGrabbed( int gametype, const entityState_t *ent, const play
+ 		}
+ 
+ 		return qtrue;
++#endif
+ 
+ 	case IT_TEAM: // team items, such as flags	
+ 		if( gametype == GT_1FCTF ) {
+diff --git a/game/code/game/bg_pmove.c b/game/code/game/bg_pmove.c
+index 8bb6a2c..2fd3ba5 100644
+--- a/game/code/game/bg_pmove.c
++++ b/game/code/game/bg_pmove.c
+@@ -1696,6 +1696,7 @@ static void PM_Weapon( void ) {
+ 		break;
+ 	}
+ 
++#ifdef HAVE_STAT_PERSISTANT_POWERUP
+ 	if( bg_itemlist[pm->ps->stats[STAT_PERSISTANT_POWERUP]].giTag == PW_SCOUT ) {
+ 		addTime /= 1.5;
+ 	}
+@@ -1704,6 +1705,7 @@ static void PM_Weapon( void ) {
+ 		addTime /= 1.3;
+   }
+   else
++#endif
+ 	if ( pm->ps->powerups[PW_HASTE] ) {
+ 		addTime /= 1.3;
+ 	}
+diff --git a/game/code/game/bg_public.h b/game/code/game/bg_public.h
+index b0efb3e..3fcd777 100644
+--- a/game/code/game/bg_public.h
++++ b/game/code/game/bg_public.h
+@@ -25,6 +25,14 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ // because games can change separately from the main system version, we need a
+ // second version that must match between game and cgame
+ 
++#if defined(MISSIONPACK) || !defined(OPENARENA_081_COMPATIBLE)
++// MISSIONPACK and 0.8.5 break ABI and network compatibility, because
++// STAT_PERSISTANT_POWERUP wasn't added at the end of its enum. Sad times.
++#   define HAVE_STAT_PERSISTANT_POWERUP
++// Adding objects to the middle of the bg_itemlist also breaks network compat.
++#   define HAVE_MISSIONPACK_ITEMLIST
++#endif
++
+ #if defined(BG_PUBLIC_H)
+ #else
+ #define BG_PUBLIC_H 1
+@@ -223,13 +231,14 @@ void Pmove (pmove_t *pmove);
+ 
+ //===================================================================================
+ 
+-
+ // player_state->stats[] indexes
+ // NOTE: may not have more than 16
+ typedef enum {
+ 	STAT_HEALTH,
+ 	STAT_HOLDABLE_ITEM,
++#ifdef HAVE_STAT_PERSISTANT_POWERUP
+ 	STAT_PERSISTANT_POWERUP,
++#endif
+ 	STAT_WEAPONS,					// 16 bit fields
+ 	STAT_ARMOR,				
+ 	STAT_DEAD_YAW,					// look this direction when dead (FIXME: get rid of?)
+diff --git a/game/code/game/g_active.c b/game/code/game/g_active.c
+index c905261..b66f982 100644
+--- a/game/code/game/g_active.c
++++ b/game/code/game/g_active.c
+@@ -437,10 +437,13 @@ void ClientTimerActions( gentity_t *ent, int msec ) {
+ 			continue;
+ 
+ 		// regenerate
++#ifdef HAVE_STAT_PERSISTANT_POWERUP
+ 		if( bg_itemlist[client->ps.stats[STAT_PERSISTANT_POWERUP]].giTag == PW_GUARD ) {
+ 			maxHealth = client->ps.stats[STAT_MAX_HEALTH] / 2;
+ 		}
+-		else if ( client->ps.powerups[PW_REGEN] ) {
++		else
++#endif
++		if ( client->ps.powerups[PW_REGEN] ) {
+ 			maxHealth = client->ps.stats[STAT_MAX_HEALTH];
+ 		}
+ 		else {
+@@ -484,6 +487,7 @@ void ClientTimerActions( gentity_t *ent, int msec ) {
+ 			client->ps.stats[STAT_ARMOR]--;
+ 		}
+ 	}
++#ifdef HAVE_STAT_PERSISTANT_POWERUP
+ 	if( bg_itemlist[client->ps.stats[STAT_PERSISTANT_POWERUP]].giTag == PW_AMMOREGEN ) {
+ 		int w, max, inc, t, i;
+     int weapList[]={WP_MACHINEGUN,WP_SHOTGUN,WP_GRENADE_LAUNCHER,WP_ROCKET_LAUNCHER,WP_LIGHTNING,WP_RAILGUN,WP_PLASMAGUN,WP_BFG,WP_NAILGUN,WP_PROX_LAUNCHER,WP_CHAINGUN};
+@@ -520,6 +524,7 @@ void ClientTimerActions( gentity_t *ent, int msec ) {
+ 		  }
+     }
+ 	}
++#endif
+ }
+ 
+ /*
+@@ -968,10 +973,12 @@ void ClientThink_real( gentity_t *ent ) {
+ 	// set speed
+ 	client->ps.speed = g_speed.value;
+ 
++#ifdef HAVE_STAT_PERSISTANT_POWERUP
+ 	if( bg_itemlist[client->ps.stats[STAT_PERSISTANT_POWERUP]].giTag == PW_SCOUT ) {
+ 		client->ps.speed *= 1.5;
+ 	}
+ 	else
++#endif
+ 	if ( client->ps.powerups[PW_HASTE] ) {
+ 		client->ps.speed *= 1.3;
+ 	}
+@@ -1278,6 +1285,7 @@ void ClientEndFrame( gentity_t *ent ) {
+ 	}
+ 
+ 	// set powerup for player animation
++#ifdef HAVE_STAT_PERSISTANT_POWERUP
+ 	if( bg_itemlist[ent->client->ps.stats[STAT_PERSISTANT_POWERUP]].giTag == PW_GUARD ) {
+ 		ent->client->ps.powerups[PW_GUARD] = level.time;
+ 	}
+@@ -1290,6 +1298,7 @@ void ClientEndFrame( gentity_t *ent ) {
+ 	if( bg_itemlist[ent->client->ps.stats[STAT_PERSISTANT_POWERUP]].giTag == PW_AMMOREGEN ) {
+ 		ent->client->ps.powerups[PW_AMMOREGEN] = level.time;
+ 	}
++#endif
+ 	if ( ent->client->invulnerabilityTime > level.time ) {
+ 		ent->client->ps.powerups[PW_INVULNERABILITY] = level.time;
+ 	}
+diff --git a/game/code/game/g_combat.c b/game/code/game/g_combat.c
+index 8c81284..22ce65a 100644
+--- a/game/code/game/g_combat.c
++++ b/game/code/game/g_combat.c
+@@ -227,7 +227,9 @@ void TossClientPersistantPowerups( gentity_t *ent ) {
+ 	powerup->r.contents = CONTENTS_TRIGGER;
+ 	trap_LinkEntity( powerup );
+ 
++#ifdef HAVE_STAT_PERSISTANT_POWERUP
+ 	ent->client->ps.stats[STAT_PERSISTANT_POWERUP] = 0;
++#endif
+ 	ent->client->persistantPowerup = NULL;
+ }
+ 
+@@ -1071,9 +1073,11 @@ void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker,
+ 	// unless they are rocket jumping
+ 	if ( attacker->client && attacker != targ ) {
+ 		max = attacker->client->ps.stats[STAT_MAX_HEALTH];
++#ifdef HAVE_STAT_PERSISTANT_POWERUP
+ 		if( bg_itemlist[attacker->client->ps.stats[STAT_PERSISTANT_POWERUP]].giTag == PW_GUARD ) {
+ 			max /= 2;
+ 		}
++#endif
+ 		damage = damage * max / 100;
+ 	}
+ 
+diff --git a/game/code/game/g_items.c b/game/code/game/g_items.c
+index cc003bc..1fd4619 100644
+--- a/game/code/game/g_items.c
++++ b/game/code/game/g_items.c
+@@ -118,6 +118,7 @@ int Pickup_Powerup( gentity_t *ent, gentity_t *other ) {
+ //======================================================================
+ 
+ int Pickup_PersistantPowerup( gentity_t *ent, gentity_t *other ) {
++#ifdef HAVE_STAT_PERSISTANT_POWERUP
+ 	int		clientNum;
+ 	char	userinfo[MAX_INFO_STRING];
+ 	float	handicap;
+@@ -185,6 +186,7 @@ int Pickup_PersistantPowerup( gentity_t *ent, gentity_t *other ) {
+ 		break;
+ 	}
+ 
++#endif
+ 	return -1;
+ }
+ 
+@@ -277,11 +279,13 @@ int Pickup_Health (gentity_t *ent, gentity_t *other) {
+ 	int			max;
+ 	int			quantity;
+ 
++#ifdef HAVE_STAT_PERSISTANT_POWERUP
+ 	// small and mega healths will go over the max
+ 	if( other->client && bg_itemlist[other->client->ps.stats[STAT_PERSISTANT_POWERUP]].giTag == PW_GUARD ) {
+ 		max = other->client->ps.stats[STAT_MAX_HEALTH];
+ 	}
+ 	else
++#endif
+ 	if ( ent->item->quantity != 5 && ent->item->quantity != 100 ) {
+ 		max = other->client->ps.stats[STAT_MAX_HEALTH];
+ 	} else {
+@@ -315,10 +319,13 @@ int Pickup_Armor( gentity_t *ent, gentity_t *other ) {
+ 
+ 	other->client->ps.stats[STAT_ARMOR] += ent->item->quantity;
+ 
++#ifdef HAVE_STAT_PERSISTANT_POWERUP
+ 	if( other->client && bg_itemlist[other->client->ps.stats[STAT_PERSISTANT_POWERUP]].giTag == PW_GUARD ) {
+ 		upperBound = other->client->ps.stats[STAT_MAX_HEALTH];
+ 	}
+-	else {
++	else
++#endif
++	{
+ 		upperBound = other->client->ps.stats[STAT_MAX_HEALTH] * 2;
+ 	}
+ 
+-- 
+1.7.1
+
diff --git a/debian/patches/0041-If-a-QVM-starts-with-NTVE-followed-by-a-nonempty-str.patch b/debian/patches/0041-If-a-QVM-starts-with-NTVE-followed-by-a-nonempty-str.patch
new file mode 100644
index 0000000..8aee1d4
--- /dev/null
+++ b/debian/patches/0041-If-a-QVM-starts-with-NTVE-followed-by-a-nonempty-str.patch
@@ -0,0 +1,57 @@
+From 88632d58a1bb664b54621aac6bdf14b80315cfd9 Mon Sep 17 00:00:00 2001
+From: Simon McVittie <smcv@debian.org>
+Date: Sat, 21 Aug 2010 16:03:22 +0100
+Subject: [PATCH] If a QVM starts with NTVE followed by a nonempty string, look in that subdir
+
+This lets each version have a different substitute shared object, if
+necessary for network compatibility (OpenArena broke network
+compatibility between 0.8.1 and 0.8.5 by removing some #ifdef MISSIONPACK).
+
+Origin: vendor, Debian
+Bug-Debian: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=592965
+Forwarded: no (amends an earlier patch which hasn't been forwarded yet)
+---
+ engine/code/qcommon/vm.c |   20 ++++++++++++++++++++
+ 1 files changed, 20 insertions(+), 0 deletions(-)
+
+diff --git a/engine/code/qcommon/vm.c b/engine/code/qcommon/vm.c
+index 83832d1..2c1a7f5 100644
+--- a/engine/code/qcommon/vm.c
++++ b/engine/code/qcommon/vm.c
+@@ -372,6 +372,7 @@ vmHeader_t *VM_LoadQVM( vm_t *vm, qboolean alloc ) {
+ 	union {
+ 		vmHeader_t	*h;
+ 		void				*v;
++		char				*s;
+ 	} header;
+ 
+ 	// load the image
+@@ -386,6 +387,25 @@ vmHeader_t *VM_LoadQVM( vm_t *vm, qboolean alloc ) {
+ 
+ 	if (LittleLong( header.h->vmMagic ) == VM_MAGIC_USE_NATIVE) {
+ 		Com_Printf( "...which has vmMagic VM_MAGIC_USE_NATIVE.\n" );
++
++		if (header.s[sizeof(int)] != '\0') {
++			Com_sprintf( filename, sizeof(filename), "%.*s/%s", length - sizeof(int), header.s + sizeof(int), vm->name );
++			filename[sizeof(filename)-1] = '\0';
++
++			if (FS_CheckDirTraversal( filename )) {
++				Com_Printf( "Directory traversal detected! %s", filename );
++				VM_Free( vm );
++				return NULL;
++			}
++
++			vm->dllHandle = Sys_LoadDll( filename, vm->fqpath , &vm->entryPoint, VM_DllSyscall );
++
++			if (vm->dllHandle != NULL) {
++				Com_Printf( "Loaded prefixed DLL file %s.\n", filename );
++				return header.h;
++			}
++		}
++
+ 		Com_Printf( "Loading DLL file %s instead.\n", vm->name );
+ 		vm->dllHandle = Sys_LoadDll( vm->name, vm->fqpath , &vm->entryPoint, VM_DllSyscall );
+ 		if ( !vm->dllHandle ) {
+-- 
+1.7.1
+
diff --git a/debian/patches/series b/debian/patches/series
index 4f37be5..485ad3a 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -31,3 +31,5 @@
 0037-Put-a-error-marker-in-engine-s-ui_shared.h-to-make-s.patch
 0038-Fix-buffer-overflow-report-and-patch-by-Eugene-C.-46.patch
 0039-Used-self-enemy-before-it-was-initialized.-Might-hav.patch
+0040-Add-OPENARENA_081_COMPATIBLE-define-for-network-comp.patch
+0041-If-a-QVM-starts-with-NTVE-followed-by-a-nonempty-str.patch
diff --git a/debian/rules b/debian/rules
index e8216f8..67adff2 100755
--- a/debian/rules
+++ b/debian/rules
@@ -44,11 +44,17 @@ GAME_OPTIONS = \
 	BUILD_GAME_SO=1 \
 	CROSS_COMPILING=1
 
+GAME_081_OPTIONS = \
+	$(GAME_OPTIONS) \
+	BUILD_DIR=build-0.8.1-compat \
+	OPENARENA_081_COMPATIBLE=1
+
 build: build-stamp
 build-stamp:
 	dh_testdir
 	$(MAKE) -C engine $(ENGINE_OPTIONS)
 	$(MAKE) -C game $(GAME_OPTIONS)
+	$(MAKE) -C game $(GAME_081_OPTIONS)
 	touch $@
 
 clean:
@@ -57,6 +63,7 @@ clean:
 	rm -f build-stamp
 	rm -rf engine/build
 	rm -rf game/build
+	rm -rf game/build-0.8.1-compat
 	rm -f debian/openarena32.xpm
 	dh_clean
 
@@ -65,7 +72,7 @@ install: build
 	dh_testroot
 	dh_clean -k
 	install -d debian/tmp/usr/games
-	install -d debian/tmp/usr/lib/games/openarena/baseoa/
+	install -d debian/tmp/usr/lib/games/openarena/baseoa/pak0/
 	install -d debian/tmp/usr/lib/games/openarena/missionpack/
 	install engine/build/release-$(Q3PLATFORM)-$(Q3ARCH)/ioquake3.$(Q3ARCH) \
 		debian/tmp/usr/games/openarena
@@ -73,6 +80,8 @@ install: build
 		debian/tmp/usr/games/openarena-server
 	install -m644 game/build/release-$(Q3PLATFORM)-$(Q3ARCH)/baseq3/*.so \
 		debian/tmp/usr/lib/games/openarena/baseoa/
+	install -m644 game/build-0.8.1-compat/release-$(Q3PLATFORM)-$(Q3ARCH)/baseq3/*.so \
+		debian/tmp/usr/lib/games/openarena/baseoa/pak0/
 	install -m644 game/build/release-$(Q3PLATFORM)-$(Q3ARCH)/missionpack/*.so\
 		debian/tmp/usr/lib/games/openarena/missionpack/
 	convert -scale 32x32 debian/openarena128.png debian/openarena32.xpm
Index: qvmbrute.c
===================================================================
--- qvmbrute.c	(revision 11184)
+++ qvmbrute.c	(working copy)
@@ -1,5 +1,7 @@
 /* Attempt to find CRC-32 collisions for QVM files.
  *
+ * Usage: qvmbrute.c DESIRED-CRC [OUTPUT-FILENAME [SUBDIRECTORY]]
+ *
  * Copyright 2010 Simon McVittie <smcv@debian.org>
  * Copying and distribution of this file, with or without modification, are
  * permitted in any medium without royalty provided this notice is preserved.
@@ -19,21 +21,40 @@
 main (int argc, char **argv)
 {
 	u_int32_t i;
-	unsigned char qvm[] = { 'N', 'T', 'V', 'E', 0, 0, 0, 0,
-		'c', 'c', 'c', 'c', 'x', 'x', 'x', 'x' };
+	unsigned char qvm[1024] = { 0 };
 	u_int32_t target = strtoul (argv[1], NULL, 0);
+	char *subdir = "";
+	size_t fixed_len;
 	u_int32_t crc;
 
-	/* calculate CRC of first 8 bytes */
-	crc = crc32 (crc32 (0, NULL, 0), qvm, 8);
+	/* subdirectory to embed in the dummy file */
+	if (argc > 3) {
+		subdir = argv[3];
+	}
+
+	/* length of fixed part */
+	fixed_len = strlen (subdir) + 8;
+
+	/* The fixed part is "NTVE" + subdir + four reserved '\0' bytes
+	 * (the first of which acts as '\0' termination for subdir).
+	 *
+	 * CCCC is replaced by the complement of the CRC-32 of the fixed part,
+	 * yielding crc32 (fixed part + CCCC) = FFFFFFFF.
+	 * XXXX is replaced by a brute-forced number such that
+	 * crc32 (fixed part + CCCC + XXXX) is as desired. */
+	snprintf ((char *) qvm, sizeof (qvm) - 1, "NTVE%s%c%c%c%cCCCCXXXX",
+			subdir, 0, 0, 0, 0);
+
+	/* calculate CRC of first fixed_len bytes */
+	crc = crc32 (crc32 (0, NULL, 0), qvm, fixed_len);
 	/* put the complement of it, in little-endian, in the next 4 */
-	qvm[8] = ~(crc & 0xFF);
-	qvm[9] = ~((crc >> 8) & 0xFF);
-	qvm[10] = ~((crc >> 16) & 0xFF);
-	qvm[11] = ~((crc >> 24) & 0xFF);
-	/* by mathematical properties of CRC32, the CRC of those 12 bytes is
+	qvm[fixed_len + 0] = ~(crc & 0xFF);
+	qvm[fixed_len + 1] = ~((crc >> 8) & 0xFF);
+	qvm[fixed_len + 2] = ~((crc >> 16) & 0xFF);
+	qvm[fixed_len + 3] = ~((crc >> 24) & 0xFF);
+	/* by mathematical properties of CRC32, the CRC up to that point is
 	 * 0xFFFFFFFF */
-	crc = crc32 (crc32 (0, NULL, 0), qvm, 12);
+	crc = crc32 (crc32 (0, NULL, 0), qvm, fixed_len + 4);
 	assert (crc == 0xFFFFFFFF);
 
 	/* it's possible to do the last bit by mathematics, but brute force
@@ -59,13 +80,14 @@
 	}
 
 	/* check our working */
-	memcpy (qvm + 12, &i, 4);
-	crc = crc32 (crc32 (0, NULL, 0), qvm, 16);
+	memcpy (qvm + fixed_len + 4, &i, 4);
+	crc = crc32 (crc32 (0, NULL, 0), qvm, fixed_len + 8);
 	assert (crc == target);
 
-	printf ("crc32(\"NTVE\" 00000000 %.8x %.8x) == 0x%.8x\n",
-			ntohl(*((u_int32_t *) (qvm + 8))),
-			ntohl(*((u_int32_t *) (qvm + 12))),
+	printf ("crc32(\"NTVE%s\" 00000000 %.8x %.8x) == 0x%.8x\n",
+			subdir,
+			ntohl(*((u_int32_t *) (qvm + fixed_len))),
+			ntohl(*((u_int32_t *) (qvm + fixed_len + 4))),
 			crc);
 
 	if (argc > 2) {
@@ -75,7 +97,7 @@
 		f = fopen (argv[2], "w");
 
 		if (f == NULL ||
-				fwrite (qvm, 16, 1, f) < 1 ||
+				fwrite (qvm, fixed_len + 8, 1, f) < 1 ||
 				fclose (f) < 0) {
 			perror ("writing fake QVM");
 			return 1;
Index: changelog
===================================================================
--- changelog	(revision 11185)
+++ changelog	(working copy)
@@ -1,3 +1,11 @@
+openarena-data (0.8.5-3) UNRELEASED; urgency=low
+
+  * Encode a search prefix into the fake QVM files so we can load different
+    native code; OA 0.8.1 and 0.8.5 turn out not to be network-compatible.
+    (When combined with changes to openarena, this will close #592965)
+
+ -- Simon McVittie <smcv@debian.org>  Fri, 20 Aug 2010 23:57:11 +0100
+
 openarena-data (0.8.5-2) unstable; urgency=low
 
   * Include directory entries explicitly in the repacked PK3 files, so the
Index: rules
===================================================================
--- rules	(revision 11184)
+++ rules	(working copy)
@@ -12,12 +12,13 @@
 	set -e && \
 	cd debian && for c in baseoa/*.contents missionpack/*.contents; do \
 		pk3=$${c%.contents}; \
+		prefix=$$(basename $${pk3%.pk3}); \
 		dir=$${pk3%.pk3}; \
 		echo "adding any missing fake QVM files for $$c"; \
 		sed -n -e 's/#.*//; /\.qvm$$/p;' < $$c | \
 			while read crc filename; do \
-				test -f $$crc.qvm || $(MAKE) -C .. -f debian/rules debian/$$crc.qvm; \
-				cp $$crc.qvm ../$$dir/$$filename; \
+				test -f $$prefix-$$crc.qvm || $(MAKE) -C .. -f debian/rules QVMPREFIX=$$prefix QVMCRC=$$crc debian/$$prefix-$$crc.qvm; \
+				cp $$prefix-$$crc.qvm ../$$dir/$$filename; \
 			done; \
 		echo "compressing $$dir to $$pk3"; \
 		rm -f ../$$pk3; \
@@ -29,8 +30,8 @@
 
 DEB_BUILD_GNU_TYPE := $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
 
-debian/%.qvm: debian/qvmbrute
-	./debian/qvmbrute 0x$* $@
+debian/$(QVMPREFIX)-$(QVMCRC).qvm: debian/qvmbrute
+	./debian/qvmbrute 0x$(QVMCRC) $@ $(QVMPREFIX)
 
 debian/qvmbrute: debian/qvmbrute.c
 	$(DEB_BUILD_GNU_TYPE)-gcc -Wall -lz -o debian/qvmbrute debian/qvmbrute.c
Index: source/include-binaries
===================================================================
--- source/include-binaries	(revision 11184)
+++ source/include-binaries	(working copy)
@@ -1,9 +1,9 @@
-debian/087acd9c.qvm
-debian/37554497.qvm
-debian/438cf2c5.qvm
-debian/449831c5.qvm
-debian/6602cd55.qvm
-debian/73428e1b.qvm
-debian/b2b99e5d.qvm
-debian/c8703d61.qvm
-debian/d2225dd5.qvm
+debian/mp-pak0-449831c5.qvm
+debian/mp-pak0-73428e1b.qvm
+debian/mp-pak0-c8703d61.qvm
+debian/pak0-37554497.qvm
+debian/pak0-b2b99e5d.qvm
+debian/pak0-d2225dd5.qvm
+debian/pak6-patch085-087acd9c.qvm
+debian/pak6-patch085-438cf2c5.qvm
+debian/pak6-patch085-6602cd55.qvm

--- End Message ---
--- Begin Message ---
On Wed, 2010-08-25 at 11:58 +0100, Simon McVittie wrote:
> retitle 593981 unblock: openarena/0.8.5-4 openarena-data/0.8.5-3
> thanks
> 
> On Tue, 24 Aug 2010 at 20:08:49 +0100, Adam D. Barratt wrote:
> > Please go ahead, and let us know once the packages have been accepted.
> 
> Accepted, eventually... 300M binary packages are rather unwieldy :-(
> Please consider:
> 
>     unblock openarena/0.8.5-4 openarena-data/0.8.5-3

Unblocked (and a pre-emptive "easy" added).

Regards,

Adam


--- End Message ---

Reply to: