project-navigation
Personal tools

Author Topic: Still cannot load a map  (Read 4665 times)

Offline keybounce

  • Sergeant
  • *****
  • Posts: 330
    • View Profile
Still cannot load a map
« on: March 22, 2009, 09:57:21 pm »
I am still unable to load a locally compiled map.

I took a breakpoint right after loading a map, and looked through curTile. There are two fields that look crazy -- curTile -> brushes -> numsides (over 100 million), and curTile -> tnodes -> children (looks like {-1, MININT} ).

(gdb) p curTile->brushes[0]
$63 = {
  contentFlags = 16777472,
  numsides = 100663296,
  firstbrushside = 0,
  checkcount = 0
}

(gdb) # Is children valid???
(gdb) p curTile->tnodes[0]@3
$74 = {{
    type = 0,
    normal = {1, 0, 0},
    dist = 544,
    children = {1, -2147483648},
    pad = 0
  }, {
    type = 0,
    normal = {1, 0, 0},
    dist = 628,
    children = {-2147483648, 2},
    pad = 0
  }, {
    type = 1,
    normal = {0, 1, 0},
    dist = 352,
    children = {3, -2147483648},
    pad = 0
  }}
(gdb)

Everything else in curTile looks reasonable.

Offline tchristney

  • Rookie
  • ***
  • Posts: 75
    • View Profile
Re: Still cannot load a map
« Reply #1 on: March 23, 2009, 12:12:43 am »
You've probably specified this somewhere else on the forum, but what HW/OS version are you running? I have a MBP/10.5.6 and have not had any problems with locally compiled maps. If you are on PPC then there might be an endian issue? Another option could be some invalid type/size assumptions in a vararg call?

Offline keybounce

  • Sergeant
  • *****
  • Posts: 330
    • View Profile
Re: Still cannot load a map
« Reply #2 on: March 23, 2009, 03:47:57 am »
G4, 10.5.6.

Yes, seeing a number in the 100 million range makes me think that there's a 4 byte out-of-order issue there.

Offline keybounce

  • Sergeant
  • *****
  • Posts: 330
    • View Profile
Re: Still cannot load a map
« Reply #3 on: March 23, 2009, 04:25:59 am »
Here's a 100% certainty of a byteswap issue

Code: [Select]
Breakpoint 1, CMod_LoadBrushes (l=0xbfffbd40, shift=0xbfffbd58) at src/common/cmodel.c:271
271 if (!l)
(gdb) p l
$1 = (const lump_t *) 0xbfffbd40
Current language:  auto; currently c
(gdb) p *l
$2 = {
  fileofs = 838532,
  filelen = 12648
}
(gdb) list
266 {
267 const dBspBrush_t *in;
268 cBspBrush_t *out;
269 int i, count;
270
271 if (!l)
272 Com_Error(ERR_DROP, "CMod_LoadBrushes: No lump given");
273
274 in = (const void *) (cmod_base + l->fileofs);
275 if (l->filelen % sizeof(dBspBrush_t))
(gdb) n
274 in = (const void *) (cmod_base + l->fileofs);
(gdb) p cmod_base
$3 = (byte *) 0x2a2c602c "IBSPM"
(gdb) n
275 if (l->filelen % sizeof(dBspBrush_t))
(gdb) p in
$4 = (const dBspBrush_t *) 0x2a392bb0
(gdb) p *in
$5 = {
  firstbrushside = 0,
  numsides = 6,
  contentFlags = 65537
}
(gdb) n
277 count = l->filelen / sizeof(dBspBrush_t);
(gdb) n
278 Com_DPrintf(DEBUG_ENGINE, "%c...brushes: %i\n", COLORED_GREEN, count);
(gdb) n
...brushes: 1054
280 if (count > MAX_MAP_BRUSHES)
(gdb) n
284 out = Mem_PoolAlloc((count + 1) * sizeof(*out), com_cmodelSysPool, 0);
(gdb) n
286 curTile->numbrushes = count;
(gdb) n
287 curTile->brushes = out;
(gdb) n
289 for (i = 0; i < count; i++, out++, in++) {
(gdb) p count
$6 = 1054
(gdb) n
290 out->firstbrushside = LittleLong(in->firstbrushside);
(gdb) n
291 out->numsides = LittleLong(in->numsides);
(gdb) n
292 out->contentFlags = LittleLong(in->contentFlags);
(gdb) n
293 if (0 == i) Com_Printf("Read brushes, numsides %d\n", out->numsides);
(gdb) p in
$7 = (const dBspBrush_t *) 0x2a392bb0
(gdb) p *in
$8 = {
  firstbrushside = 0,
  numsides = 6,
  contentFlags = 65537
}
(gdb) p *out
$9 = {
  contentFlags = 16777472,
  numsides = 100663296,
  firstbrushside = 0,
  checkcount = 0
}
(gdb)

Now, look at the ufo2map source:

Code: [Select]
Kleiman-ibook:ufo2map michael$ egrep LittleLong *c
routing.c: wpMins[i] = LittleLong(wpMins[i]);
routing.c: wpMaxs[i] = LittleLong(wpMaxs[i]);
textures.c: textureref[i].value = LittleLong(mt->value);
textures.c: textureref[i].value = LittleLong(mt->value);

Ufo2map is not calling LittleLong on the brushes! This will cause the maps built on big-endian and little-endian machines to differ, and kills the maps on loading.

In fact,
Code: [Select]
Kleiman-ibook:ufo2map michael$ egrep BigLong *.c
Kleiman-ibook:ufo2map michael$ egrep LittleShort *.c
Kleiman-ibook:ufo2map michael$ egrep BigShort *.c
Kleiman-ibook:ufo2map michael$ egrep LittleFloat *.c
Kleiman-ibook:ufo2map michael$ egrep BigFloat *.c

No other byte swapping calls are made except those 4; are others being missed as well?
« Last Edit: March 23, 2009, 04:37:26 am by keybounce »

Offline keybounce

  • Sergeant
  • *****
  • Posts: 330
    • View Profile
Re: Still cannot load a map
« Reply #4 on: March 23, 2009, 05:58:22 am »
With that byte swap issue resolved, the map loads. Death occurs in the event loop.

Code: [Select]
Map:africa/af_drop_firebird  Offset:(-40, -16, 0)
wpMins:(128, 128, 0) wpMaxs:(143, 151, 3)
Shifted wpMins:(88, 112, 0) wpMaxs:(103, 135, 3)
Tile bounds: (88, 112, 0) to (103, 135, 3)
Source bounds: (128, 128, 0) to (143, 151, 3)
Done copying data.
Loaded routing for tile africa/af_drop_firebird in   1.0s
checksum for the map '+africa': 4273352497
ufo script checksum 3182143164
Created AI player (team 0)
Created AI player (team 7)
-------------------------------------
Connecting to localhost...

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x6f616450
0x6f616450 in ?? ()
(gdb) bt 12
#0  0x6f616450 in ?? ()
Cannot access memory at address 0x6f616450
Cannot access memory at address 0x6f616450
Cannot access memory at address 0x6f616450
Cannot access memory at address 0x6f616450
Cannot access memory at address 0x6f616450
Cannot access memory at address 0x6f616450
#1  0x0f87e0ec in SDL_PumpEvents ()
Cannot access memory at address 0x6f616450
Cannot access memory at address 0x6f616450
Cannot access memory at address 0x6f616450
Cannot access memory at address 0x6f616450
Cannot access memory at address 0x6f616450
#2  0x0f87e168 in SDL_PollEvent ()
Cannot access memory at address 0x6f616450
#3  0x00024478 in IN_Frame () at src/client/cl_input.c:1291
#4  0x00037184 in CL_Frame (now=107306, data=0x0) at src/client/cl_main.c:1089
#5  0x00128600 in tick_timer (now=107306, data=0x1840cacc) at src/common/common.c:1080
#6  0x00128a24 in Qcommon_Frame () at src/common/common.c:1161
#7  0x0019cb20 in main (argc=1, argv=0xbffff8ac) at src/ports/macosx/osx_main.m:142
(gdb) up 6
#6  0x00128a24 in Qcommon_Frame () at src/common/common.c:1161
1161 event->func(event->when, event->data);
Current language:  auto; currently c
(gdb) p event
$1 = (struct event *) 0x1836c18c
(gdb) p *event
$2 = {
  when = 107306,
  func = 0x1282e8 <tick_timer>,
  data = 0x1840cacc,
  next = 0x183e056c
}
(gdb) p event->when
$3 = 107306
(gdb) down
#5  0x00128600 in tick_timer (now=107306, data=0x1840cacc) at src/common/common.c:1080
1080 timer->func(now, timer->data);
(gdb) list tick_timer
1025
1026 Com_Printf("====== UFO Initialized ======\n\n");
1027 }
1028
1029 static void tick_timer (int now, void *data)
1030 {
1031 struct timer *timer = data;
1032 int old_interval = timer->interval;
1033
1034 /* Compute and store the lateness, updating the total */
(gdb)
1035 const int lateness = Sys_Milliseconds() - now;
1036 timer->total_lateness -= timer->recent_lateness[timer->next_lateness];
1037 timer->recent_lateness[timer->next_lateness] = lateness;
1038 timer->total_lateness += lateness;
1039 timer->next_lateness++;
1040 timer->next_lateness %= TIMER_LATENESS_HISTORY;
1041
1042 /* Is it time to check the mean yet? */
1043 timer->next_check--;
1044 if (timer->next_check <= 0) {
(gdb) p timer
$4 = (struct timer *) 0x1840cacc
(gdb) p *timer
$5 = {
  min_freq = 0xfb29a1c,
  interval = 20,
  recent_lateness = {1, 0, 1, 0, 41830, 0, 0, 2, 0, 1, 0, 1, 0, 1, 0, 0, 15, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 2, 0},
  next_lateness = 5,
  total_lateness = 41861,
  next_check = 11,
  checks_high = 0,
  checks_low = 1,
  func = 0x36fc0 <CL_Frame>,
  data = 0x0
}

I have no idea why it fails.
Attempting to use map-get results in a version mismatch warning.

To clarify: When map-get returned proper versions, I was able to load maps, but they looked horrible. I have not been able to get a locally compiled map to load and display.

Offline Mattn

  • Administrator
  • PHALANX Commander
  • *****
  • Posts: 4831
  • https://github.com/mgerhardy/vengi
    • View Profile
    • Vengi Voxel Tools
Re: Still cannot load a map
« Reply #5 on: March 23, 2009, 07:33:33 pm »
can you please post the patch with your fixes, too?

Offline keybounce

  • Sergeant
  • *****
  • Posts: 330
    • View Profile
Re: Still cannot load a map
« Reply #6 on: March 23, 2009, 08:05:07 pm »
Sure.

I could not figure out how to patch the map generation, but I could patch the map loading. This makes it a hack -- the map files are still in error, and won't checksum properly.

(Side note: It looks like the map generator stores two copies of the data structure, but the map loader only loads one copy. No, I don't follow what the code is doing.)
Code: [Select]
Index: src/server/sv_init.c
===================================================================
--- src/server/sv_init.c (revision 23662)
+++ src/server/sv_init.c (working copy)
@@ -291,6 +291,7 @@
 
  /* successfully parsed - this tile counts */
  numTiles++;
+ Com_Printf("SV_ParseMapTile: Just incremented numTiles, now %d\n", numTiles);
 }
 
 
Index: src/ports/unix/unix_main.c
===================================================================
--- src/ports/unix/unix_main.c (revision 23662)
+++ src/ports/unix/unix_main.c (working copy)
@@ -520,6 +520,8 @@
 #ifdef HAVE_CURSES
  signal(SIGWINCH, Sys_Signal);
 #endif
+ /* apple provides a nice backtrace feature on their own */
+#if !(defined (__APPLE__) || defined (MACOSX))
  signal(SIGHUP, Sys_Signal);
  signal(SIGINT, Sys_Signal);
  signal(SIGQUIT, Sys_Signal);
@@ -528,4 +530,5 @@
  signal(SIGFPE, Sys_Signal);
  signal(SIGSEGV, Sys_Signal);
  signal(SIGTERM, Sys_Signal);
+#endif
 }
Index: src/common/cmodel.c
===================================================================
--- src/common/cmodel.c (revision 23662)
+++ src/common/cmodel.c (working copy)
@@ -164,6 +164,8 @@
  }
  out->headnode = LittleLong(in->headnode);
  out->tile = numTiles; /* backlink to the loaded map tile */
+Com_Printf("CMod_LoadSubModels: Using numTiles for curTile, now %d\n", numTiles);
+assert(curTile == &mapTiles[numTiles]);
  }
 }
 
@@ -288,6 +290,14 @@
  out->firstbrushside = LittleLong(in->firstbrushside);
  out->numsides = LittleLong(in->numsides);
  out->contentFlags = LittleLong(in->contentFlags);
+/* BUGFIX! Local maps don't have the right byteswap */
+/* This is here only because I could not figure out how to fix ufo2map */
+ if (out->numsides > in->numsides) {
+ out->firstbrushside = in->firstbrushside;
+ out->numsides = in->numsides;
+ out->contentFlags = in->contentFlags;
+ }
+if (0 == i) Com_Printf("Read brushes, numsides %d\n", out->numsides);
  }
 }
 
@@ -903,6 +913,8 @@
  }
  /* Update the reroute table */
  if (!reroute[size][y][x]) {
+ /* This is 1 off from the current tile */
+ /* But it can't be zero, so that's intentional??? */
  reroute[size][y][x] = numTiles;
  } else {
  reroute[size][y][x] = ROUTING_NOT_REACHABLE;
@@ -1069,6 +1081,7 @@
  Com_Error(ERR_FATAL, "CM_AddMapTile: too many tiles loaded %i", numTiles);
 
  curTile = &mapTiles[numTiles];
+Com_Printf("CM_AddMapTile: curTile now matches numTile (%d).\n", numTiles);
  memset(curTile, 0, sizeof(*curTile));
  Q_strncpyz(curTile->name, name, sizeof(curTile->name));
 
@@ -1104,6 +1117,7 @@
  /* now increase the amount of loaded tiles */
  numTiles++;
 
+Com_Printf("CM_AddMapTile: numTiles++ (now %d); curTile no longer matches numTile.\n", numTiles);
  CMod_LoadRouting(name, &header.lumps[LUMP_ROUTING], sX, sY, sZ);
 
  FS_FreeFile(buf);
Index: build/maps.mk
===================================================================
--- build/maps.mk (revision 23662)
+++ build/maps.mk (working copy)
@@ -32,7 +32,8 @@
 endif
 
 NICE = 19
-UFO2MAPFLAGS = -v 2 -nice $(NICE) -extra -t $(NUMTHREADS)
+# UFO2MAPFLAGS = -v 2 -nice $(NICE) -extra -t $(NUMTHREADS)
+UFO2MAPFLAGS =        -nice $(NICE) -extra -t $(NUMTHREADS)
 FAST_UFO2MAPFLAGS = -v 2 -quant 6 -nice $(NICE) -t $(NUMTHREADS)
 ENTS_UFO2MAPFLAGS = -v 2 -nice $(NICE) -onlyents