--- Begin Message ---
Package: gdb
Version: 6.0-2
Severity: normal
Tags: sid
While trying to get the highly i386-centric hhexen code going on ppc, I ran
into a segfault. Asking a backtrace in gdb produced a rather interesting
result:
...
skill 2, episode 1, map 1 skill 2, episode 1, map 1
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 16384 (LWP 1934)]
P_LoadACScripts (lump=808426069) at base/p_acs.c:310
310 ACScriptCount = *buffer++;
(gdb) bt
#0 P_LoadACScripts (lump=808426069) at base/p_acs.c:310
#1 0x10040a44 in P_SetupLevel (episode=808426069, map=45, playermask=3340,
skill=55) at base/p_setup.c:1100
#2 0x10019de8 in G_DoLoadLevel () at base/g_game.c:633
#3 0x1001b4d4 in G_InitNew (skill=sk_baby, episode=1, map=0) at
base/g_game.c:1673
#4 0x1001afd8 in G_StartNewGame (skill=sk_medium) at base/g_game.c:1332
#5 0x1001b31c in G_DoNewGame () at base/g_game.c:1587
#6 0x1001a6f4 in G_Ticker () at base/g_game.c:835
#7 0x100183d8 in TryRunTics () at base/d_net.c:891
#8 0x1001c5e0 in H2_GameLoop () at base/h2_main.c:550
#9 0x1001bdd0 in H2_Main () at base/h2_main.c:301
#10 0x1000f308 in main (argc=-200605696, argv=0x7ffffa24) at base/i_linux.c:1733
Note that skill _appears_ to have suddenly changed from 2 (sk_medium) to 0
(sk_baby) from the 4th to the 3th frame. However, definitely not by the
hhexen code... In reality, the input variable to G_StartNewGame() is only
used when passing it along to G_InitNew(). And effectively, as a fprintf()
which is the first statement inside G_InitNew() shows - the first of the two
"skill 2, ...\t" outputs right before the segfault - the value passed is
still 2.
Similarly further on:
(gdb) l base/g_game.c:633
628 memset (players[i].frags,0,sizeof(players[i].frags));
629 }
630
631 SN_StopAllSequences();
632 fprintf (stderr, "skill %d, episode %d, map %d\t", gameskill,
gameepisode, gamemap);
633 P_SetupLevel (gameepisode, gamemap, 0, gameskill);
634 displayplayer = consoleplayer; // view the guy you are
playing
635 starttime = I_GetTime ();
636 gameaction = ga_nothing;
637 Z_CheckHeap ();
As you can see, the second of those "skill..." outputs before the segfault
comes from inside G_DoLoadLevel(), using file global variables set by
G_InitNew(). They are still as they should be, and they are passed unchanged
to P_SetupLevel() right after that fprintf() - but gdb prints very different
values to the P_SetupLevel() call. (Note also that a literal 0 is used as
the third argument, which gdb manages to change into something completely
different in the backtrace)
This is an ppc running up to date sid. Application is CVS from hhexen
(:pserver:[email protected]:/cvs/cvsroot, password "anonymous",
module hhexen) with the attached patch. Run autogen.sh, copy config.* from
autotools-dev, be sure to have sdl, gl & glu dev libs installed, ./configure
--enable-gl, make, gdb ./hhexen-gl, run -g (mandatory within gdb to avoid
focus grab) and hit enter 4 times at the intro screen to start a new level -
segfault. Oh, and you need a data .wad file from a dos installation; if you
don't have hexen the demo .wad reportedly should work too, if you enable it
with some ./configure flag.
Regards,
Filip
-- System Information:
Debian Release: testing/unstable
Architecture: powerpc
Kernel: Linux aegir 2.4.20-ben10 #4 Mon Jun 23 19:34:48 CEST 2003 ppc
Locale: LANG=nl_BE@euro, LC_CTYPE=nl_BE@euro
Versions of packages gdb depends on:
ii libc6 2.3.2.ds1-10 GNU C Library: Shared libraries an
ii libncurses5 5.3.20030719-4 Shared libraries for terminal hand
ii libreadline4 4.3-8 GNU readline and history libraries
-- no debconf information
--
I have not lost my mind, its backed up on tape somewhere
diff -ru hhpatched/base/g_game.c hhexen-1.31/base/g_game.c
--- hhpatched/base/g_game.c 2002-05-07 06:40:04.000000000 +0200
+++ hhexen-1.31/base/g_game.c 2003-12-14 18:34:29.000000000 +0100
@@ -629,7 +629,8 @@
}
SN_StopAllSequences();
- P_SetupLevel (gameepisode, gamemap, 0, gameskill);
+ fprintf (stderr, "skill %d, episode %d, map %d\t", gameskill,
gameepisode, gamemap);
+ P_SetupLevel (gameepisode, gamemap, 0, gameskill);
displayplayer = consoleplayer; // view the guy you are playing
starttime = I_GetTime ();
gameaction = ga_nothing;
@@ -1328,7 +1329,7 @@
{
realMap = 1;
}
- G_InitNew(TempSkill, 1, realMap);
+ G_InitNew (skill, 1, realMap);
}
//==========================================================================
@@ -1616,6 +1617,7 @@
{
int i;
+ fprintf (stderr, "skill %d, episode %d, map %d\t", skill, episode, map);
if(paused)
{
paused = false;
@@ -1667,7 +1669,10 @@
//memset (localcmds,0,sizeof(localcmds));
//memset (netcmds,0,sizeof(netcmds));
+ fprintf (stderr, "skill %d, episode %d, map %d\t", gameskill,
gameepisode, gamemap);
G_DoLoadLevel();
+ fprintf (stderr, "skill %d, episode %d, map %d\t", gameskill,
gameepisode, gamemap);
+ fprintf (stderr, "skill %d, episode %d, map %d\n", skill, episode, map);
}
/*
diff -ru hhpatched/base/w_wad.c hhexen-1.31/base/w_wad.c
--- hhpatched/base/w_wad.c 2003-02-10 04:31:12.000000000 +0100
+++ hhexen-1.31/base/w_wad.c 2003-12-14 18:15:32.000000000 +0100
@@ -601,6 +601,7 @@
}
l = lumpinfo+lump;
//I_BeginRead();
+ //fprintf (stderr, "reading lump %d (%s), size %d\n", lump, l->name,
l->size);
lseek(l->handle, l->position, SEEK_SET);
c = read(l->handle, dest, l->size);
if(c < l->size)
@@ -637,6 +638,30 @@
return lumpcache[lump];
}
+patch_t *W_CacheLumpNumPatchT (int lump, int tag) {
+ /* FIXME: correct way:
+ unsigned char *chunk = W_CacheLumpNum(lump, tag);
+ patch_t *patch = malloc(...);
+ // assign individual struct fields to take care of padding issues
+ patch.width = chunk[0] + chunk[1] << 8; // always correct regardless of
endianness
+ ...
+ Z_Free(chunk); // is there a Z_Free()?
+ // free() patch in calling function, after use
+ */
+
+ patch_t *patch = W_CacheLumpNum(lump, tag);
+ patch->width = SHORT(patch->width);
+ patch->height = SHORT(patch->height);
+ patch->leftoffset = SHORT(patch->leftoffset);
+ patch->topoffset = SHORT(patch->topoffset);
+ // Hmm, what if width > 8 ???
+ //int i;
+ //for (i = 0; i < 8; i++) {
+ // patch->columnofs[i] = LONG(patch->columnofs[i]);
+ //}
+ return patch;
+}
+
//==========================================================================
//
// W_CacheLumpName
diff -ru hhpatched/include/h2def.h hhexen-1.31/include/h2def.h
--- hhpatched/include/h2def.h 2002-05-07 06:40:05.000000000 +0200
+++ hhexen-1.31/include/h2def.h 2003-12-14 18:11:22.000000000 +0100
@@ -972,6 +972,7 @@
int W_LumpLength(int lump);
void W_ReadLump(int lump, void *dest);
void *W_CacheLumpNum(int lump, int tag);
+patch_t *W_CacheLumpNumPatchT(int, int);
void *W_CacheLumpName(char *name, int tag);
void W_CheckForOldFiles(void);
diff -ru hhpatched/opengl/ogl_tex.c hhexen-1.31/opengl/ogl_tex.c
--- hhpatched/opengl/ogl_tex.c 2003-12-14 19:03:49.000000000 +0100
+++ hhexen-1.31/opengl/ogl_tex.c 2003-12-14 18:33:08.000000000 +0100
@@ -257,17 +257,17 @@
byte *source;
int w, i;
-/* y -= SHORT(patch->topoffset);
- x -= SHORT(patch->leftoffset);
- if(x < 0 || x+SHORT(patch->width) > SCREENWIDTH || y < 0
- || y+SHORT(patch->height) > SCREENHEIGHT)
+/* y -= patch->topoffset;
+ x -= patch->leftoffset;
+ if(x < 0 || x+patch->width > SCREENWIDTH || y < 0
+ || y+patch->height > SCREENHEIGHT)
{
I_Error("Bad V_DrawPatch");
}*/
col = 0;
desttop1 = rgbflat;// + y*SCREENWIDTH+x;
desttop2 = rgbaflat;
- w = SHORT(patch->width);
+ w = patch->width;
for(; col < w; /*x++,*/ col++, desttop1+=3, desttop2+=4)
{
column = (column_t *)((byte
*)patch+LONG(patch->columnofs[col]));
@@ -351,7 +351,7 @@
byte *rgbaflat =
(byte*)malloc(4*tex->width*tex->height);
memset(rgbaflat, 0, 4*tex->width*tex->height);
textype = DrawRealPatch(rgbflat, rgbaflat, palette,
tex->width, tex->height,
- W_CacheLumpNum(tex->patches[0].patch,
PU_CACHE), false);
+ W_CacheLumpNumPatchT(tex->patches[0].patch,
PU_CACHE), false);
if(textype == GL_RGBA) { free(rgbflat); rgbflat =
rgbaflat; }
else { free (rgbaflat); }
}
@@ -472,10 +472,10 @@
// This texture has only only one patch.
if(textype == GL_RGB)
DrawRealPatch(imgdata, 0, palette, 256,
tex->height,
- W_CacheLumpNum(tex->patches[0].patch,
PU_CACHE), false);
+
W_CacheLumpNumPatchT(tex->patches[0].patch, PU_CACHE), false);
else if(textype == GL_RGBA) // Mask out zeros.
DrawRealPatch(0, imgdata, palette, 256,
tex->height,
- W_CacheLumpNum(tex->patches[0].patch,
PU_CACHE), true);
+
W_CacheLumpNumPatchT(tex->patches[0].patch, PU_CACHE), true);
}
if(textype == GL_RGBA) // For masked data, calculate the
alpha-fill color.
{
@@ -526,7 +526,7 @@
if(!spritenames[pnum])
{
// There's no name for this patch, load it in.
- patch_t *patch = W_CacheLumpNum(firstspritelump+pnum, PU_CACHE);
+ patch_t *patch = W_CacheLumpNumPatchT(firstspritelump+pnum,
PU_CACHE);
int p2width = FindNextPower2(patch->width),
p2height = OGL_ValidTexHeight2(patch->width,
patch->height);// FindNextPower2(patch->height);
int flatsize = 4*p2width*p2height;
@@ -677,19 +677,21 @@
return p2h;
}
+#include <assert.h>
void OGL_SetPatch(int lump) // No mipmaps are generated.
{
if(!lumptexnames[lump])
{
// Load the patch.
- patch_t *patch = W_CacheLumpNum(lump, PU_CACHE);
+ patch_t *patch = W_CacheLumpNumPatchT (lump, PU_CACHE);
int p2width = FindNextPower2(patch->width),
p2height = OGL_ValidTexHeight2(patch->width,
patch->height);//FindNextPower2(patch->height);
int numpels = p2width*p2height;
byte *rgbflat = (byte *)malloc(3*numpels),
*rgbaflat = (byte*)malloc(4*numpels);
int ptype;
-
+
+ assert(rgbflat && rgbaflat);
memset(rgbaflat, 0, 4*numpels);
ptype = DrawRealPatch(rgbflat, rgbaflat,
W_CacheLumpNum(pallump,PU_CACHE),
p2width, p2height, patch, false);
--- End Message ---