Exemple #1
0
//
// ReadLumpData
//
static void ReadLumpData(lump_t *lump)
{
  size_t len;

  cur_comms->file_pos++;
  DisplaySetBar(1, cur_comms->file_pos);
  DisplayTicker();

# if DEBUG_LUMP
  PrintDebug("Reading... %s (%d)\n", lump->name, lump->length);
# endif
  
  if (lump->length == 0)
    return;

  lump->data = UtilCalloc(lump->length);

  fseek(in_file, lump->start, SEEK_SET);

  len = fread(lump->data, lump->length, 1, in_file);

  if (len != 1)
  {
    if (wad.current_level)
      PrintWarn("Trouble reading lump '%s' in %s\n",
          lump->name, wad.current_level->name);
    else
      PrintWarn("Trouble reading lump '%s'\n", lump->name);
  }

  lump->flags &= ~LUMP_READ_ME;
}
Exemple #2
0
//
// ReadWadFile
//
glbsp_ret_e ReadWadFile(const char *filename)
{
  int check;
  char *read_msg;

  // open input wad file & read header
  in_file = fopen(filename, "rb");

  if (! in_file)
  {
    if (errno == ENOENT)
      SetErrorMsg("Cannot open WAD file: %s", filename); 
    else
      SetErrorMsg("Cannot open WAD file: %s [%s]", filename, 
          strerror(errno));

    return GLBSP_E_ReadError;
  }
  
  if (! ReadHeader(filename))
  {
    fclose(in_file);
    return GLBSP_E_ReadError;
  }

  PrintMsg("Opened %cWAD file : %s\n", (wad.kind == IWAD) ? 'I' : 'P', 
      filename); 
  PrintVerbose("Reading %d dir entries at 0x%X\n", wad.num_entries, 
      wad.dir_start);

  // read directory
  ReadDirectory();

  DisplayOpen(DIS_FILEPROGRESS);
  DisplaySetTitle("glBSP Reading Wad");
  
  read_msg = UtilFormat("Reading: %s", filename);

  DisplaySetBarText(1, read_msg);
  DisplaySetBarLimit(1, CountLumpTypes(LUMP_READ_ME, LUMP_READ_ME));
  DisplaySetBar(1, 0);

  UtilFree(read_msg);

  cur_comms->file_pos = 0;

  // now read lumps
  check = ReadAllLumps();

  if (check != wad.num_entries)
    InternalError("Read directory count consistency failure (%d,%d)",
      check, wad.num_entries);
  
  wad.current_level = NULL;

  DisplayClose();

  return GLBSP_E_OK;
}
Exemple #3
0
static glbsp_ret_e HandleLevel(void)
{
  superblock_t *seg_list;
  node_t *root_node;
  node_t *root_stale_node;
  subsec_t *root_sub;

  glbsp_ret_e ret;

  if (cur_comms->cancelled)
    return GLBSP_E_Cancelled;

  DisplaySetBarLimit(1, 1000);
  DisplaySetBar(1, 0);

  cur_comms->build_pos = 0;

  LoadLevel();

  InitBlockmap();

  // create initial segs
  seg_list = CreateSegs();

  root_stale_node = (num_stale_nodes == 0) ? NULL : 
      LookupStaleNode(num_stale_nodes - 1);

  // recursively create nodes
  ret = BuildNodes(seg_list, &root_node, &root_sub, 0, root_stale_node);
  FreeSuper(seg_list);

  if (ret == GLBSP_E_OK)
  {
    ClockwiseBspTree(root_node);

    PrintVerbose("Built %d NODES, %d SSECTORS, %d SEGS, %d VERTEXES\n",
        num_nodes, num_subsecs, num_segs, num_normal_vert + num_gl_vert);

    if (root_node)
      PrintVerbose("Heights of left and right subtrees = (%d,%d)\n",
          ComputeBspHeight(root_node->r.node),
          ComputeBspHeight(root_node->l.node));

    SaveLevel(root_node);
  }

  FreeLevel();
  FreeQuickAllocCuts();
  FreeQuickAllocSupers();

  return ret;
}
Exemple #4
0
//
// WriteWadFile
//
glbsp_ret_e WriteWadFile(const char *filename)
{
  int check1, check2;
  char *write_msg;

  PrintMsg("\n");
  PrintMsg("Saving WAD as %s\n", filename);

  RecomputeDirectory();

  // create output wad file & write the header
  out_file = fopen(filename, "wb");

  if (! out_file)
  {
    SetErrorMsg("Cannot create WAD file: %s [%s]", filename,
        strerror(errno));

    return GLBSP_E_WriteError;
  }

  WriteHeader();

  DisplayOpen(DIS_FILEPROGRESS);
  DisplaySetTitle("glBSP Writing Wad");
  
  write_msg = UtilFormat("Writing: %s", filename);

  DisplaySetBarText(1, write_msg);
  DisplaySetBarLimit(1, CountLumpTypes(LUMP_IGNORE_ME, 0));
  DisplaySetBar(1, 0);

  UtilFree(write_msg);

  cur_comms->file_pos = 0;

  // now write all the lumps to the output wad
  check1 = WriteAllLumps();

  DisplayClose();

  // finally, write out the directory
  check2 = WriteDirectory();

  if (check1 != wad.num_entries || check2 != wad.num_entries)
    InternalError("Write directory count consistency failure (%d,%d,%d)",
      check1, check2, wad.num_entries);

  return GLBSP_E_OK;
}
Exemple #5
0
//
// WriteLumpData
//
static void WriteLumpData(lump_t *lump)
{
  size_t len;
  int align_size;

  cur_comms->file_pos++;
  DisplaySetBar(1, cur_comms->file_pos);
  DisplayTicker();

# if DEBUG_LUMP
  if (lump->flags & LUMP_COPY_ME)
    PrintDebug("Copying... %s (%d)\n", lump->name, lump->length);
  else
    PrintDebug("Writing... %s (%d)\n", lump->name, lump->length);
# endif
  
  if (ftell(out_file) != lump->new_start)
    PrintWarn("Consistency failure writing %s (%08lX, %08X\n", 
      lump->name, ftell(out_file), lump->new_start);
 
  if (lump->length == 0)
    return;

  if (lump->flags & LUMP_COPY_ME)
  {
    lump->data = UtilCalloc(lump->length);

    fseek(in_file, lump->start, SEEK_SET);

    len = fread(lump->data, lump->length, 1, in_file);

    if (len != 1)
      PrintWarn("Trouble reading lump %s to copy\n", lump->name);
  }

  len = fwrite(lump->data, lump->length, 1, out_file);
   
  if (len != 1)
    PrintWarn("Trouble writing lump %s\n", lump->name);
  
  align_size = ALIGN_LEN(lump->length) - lump->length;

  if (align_size > 0)
    fwrite(align_filler, align_size, 1, out_file);

  UtilFree(lump->data);

  lump->data = NULL;
}
Exemple #6
0
//
// PickNode
//
// Find the best seg in the seg_list to use as a partition line.
//
seg_t *PickNode(superblock_t *seg_list, int depth, const bbox_t *bbox)
{
  seg_t *best=NULL;

  int best_cost=INT_MAX;

  int progress=0;
  int prog_step=1<<24;
  int build_step=0;

# if DEBUG_PICKNODE
  PrintDebug("PickNode: BEGUN (depth %d)\n", depth);
# endif

  /* compute info for showing progress */
  if (depth <= 6)
  {
    static int depth_counts[7] = { 248, 100, 30, 10, 6, 4, 2 };
    
    int total = seg_list->real_num + seg_list->mini_num;

    build_step = depth_counts[depth];
    prog_step = 1 + ((total - 1) / build_step);

    if (total / prog_step < build_step)
    {
      cur_comms->build_pos += build_step - total / prog_step;
      build_step = total / prog_step;

      DisplaySetBar(1, cur_comms->build_pos);
      DisplaySetBar(2, cur_comms->file_pos + cur_comms->build_pos / 100);
    }
  }

  DisplayTicker();

  /* -AJA- another (optional) optimisation, when building just the GL
   *       nodes.  We assume that the original nodes are reasonably
   *       good choices, and re-use them as much as possible, saving
   *       *heaps* of time on really large levels.
   */
  if (cur_info->fast && seg_list->real_num >= SEG_FAST_THRESHHOLD)
  {
#   if DEBUG_PICKNODE
    PrintDebug("PickNode: Looking for Fast node...\n");
#   endif

    best = FindFastSeg(seg_list, bbox);

    if (best)
    {
      /* update progress */
      cur_comms->build_pos += build_step;
      DisplaySetBar(1, cur_comms->build_pos);
      DisplaySetBar(2, cur_comms->file_pos + cur_comms->build_pos / 100);

#     if DEBUG_PICKNODE
      PrintDebug("PickNode: Using Fast node (%1.1f,%1.1f) -> (%1.1f,%1.1f)\n",
          best->start->x, best->start->y, best->end->x, best->end->y);
#     endif

      return best;
    }
  }

  if (FALSE == PickNodeWorker(seg_list, seg_list, &best, &best_cost, 
      &progress, prog_step))
  {
    /* hack here : BuildNodes will detect the cancellation */
    return NULL;
  }

# if DEBUG_PICKNODE
  if (! best)
  {
    PrintDebug("PickNode: NO BEST FOUND !\n");
  }
  else
  {
    PrintDebug("PickNode: Best has score %d.%02d  (%1.1f,%1.1f) -> (%1.1f,%1.1f)\n", 
      best_cost / 100, best_cost % 100, best->start->x, best->start->y,
      best->end->x, best->end->y);
  }
# endif

  /* all finished, return best Seg */
  return best;
}
Exemple #7
0
/* returns FALSE if cancelled */
static int PickNodeWorker(superblock_t *part_list, 
    superblock_t *seg_list, seg_t ** best, int *best_cost,
    int *progress, int prog_step)
{
  seg_t *part;

  int num;
  int cost;

  /* use each Seg as partition */
  for (part=part_list->segs; part; part = part->next)
  {
    if (cur_comms->cancelled)
      return FALSE;

#   if DEBUG_PICKNODE
    PrintDebug("PickNode:   %sSEG %p  sector=%d  (%1.1f,%1.1f) -> (%1.1f,%1.1f)\n",
      part->linedef ? "" : "MINI", part, 
      part->sector ? part->sector->index : -1,
      part->start->x, part->start->y, part->end->x, part->end->y);
#   endif

    /* something for the user to look at */
    (*progress) += 1;

    if ((*progress % prog_step) == 0)
    {
      cur_comms->build_pos++;
      DisplaySetBar(1, cur_comms->build_pos);
      DisplaySetBar(2, cur_comms->file_pos + cur_comms->build_pos / 100);
    }

    /* ignore minisegs as partition candidates */
    if (! part->linedef)
      continue;
    
    cost = EvalPartition(seg_list, part, *best_cost);

    /* seg unsuitable or too costly ? */
    if (cost < 0 || cost >= *best_cost)
      continue;

    /* we have a new better choice */
    (*best_cost) = cost;

    /* remember which Seg */
    (*best) = part;
  }

  DisplayTicker();

  /* recursively handle sub-blocks */

  for (num=0; num < 2; num++)
  {
    if (part_list->subs[num])
      PickNodeWorker(part_list->subs[num], seg_list, best, best_cost,
        progress, prog_step);
  }

  return TRUE;
}
Exemple #8
0
glbsp_ret_e GlbspBuildNodes(const nodebuildinfo_t *info,
    const nodebuildfuncs_t *funcs, volatile nodebuildcomms_t *comms)
{
  char *file_msg;

  glbsp_ret_e ret = GLBSP_E_OK;

  cur_info  = info;
  cur_funcs = funcs;
  cur_comms = comms;

  cur_comms->total_big_warn = 0;
  cur_comms->total_small_warn = 0;

  // clear cancelled flag
  comms->cancelled = FALSE;

  // sanity check
  if (!cur_info->input_file  || cur_info->input_file[0] == 0 ||
      !cur_info->output_file || cur_info->output_file[0] == 0)
  {
    SetErrorMsg("INTERNAL ERROR: Missing in/out filename !");
    return GLBSP_E_BadArgs;
  }

  InitDebug();
  InitEndian();
 
  if (info->missing_output)
    PrintMsg("* No output file specified. Using: %s\n\n", info->output_file);

  if (info->same_filenames)
    PrintMsg("* Output file is same as input file. Using -loadall\n\n");

  // opens and reads directory from the input wad
  ret = ReadWadFile(cur_info->input_file);

  if (ret != GLBSP_E_OK)
  {
    TermDebug();
    return ret;
  }

  if (CountLevels() <= 0)
  {
    CloseWads();
    TermDebug();

    SetErrorMsg("No levels found in wad !");
    return GLBSP_E_Unknown;
  }
   
  PrintMsg("\n");
  PrintVerbose("Creating nodes using tunable factor of %d\n", info->factor);

  DisplayOpen(DIS_BUILDPROGRESS);
  DisplaySetTitle("glBSP Build Progress");

  file_msg = UtilFormat("File: %s", cur_info->input_file);
 
  DisplaySetBarText(2, file_msg);
  DisplaySetBarLimit(2, CountLevels() * 10);
  DisplaySetBar(2, 0);

  UtilFree(file_msg);
  
  cur_comms->file_pos = 0;
  
  // loop over each level in the wad
  while (FindNextLevel())
  {
    ret = HandleLevel();

    if (ret != GLBSP_E_OK)
      break;

    cur_comms->file_pos += 10;
    DisplaySetBar(2, cur_comms->file_pos);
  }

  DisplayClose();

  // writes all the lumps to the output wad
  if (ret == GLBSP_E_OK)
  {
    ret = WriteWadFile(cur_info->output_file);

    // when modifying the original wad, any GWA companion must be deleted
    if (ret == GLBSP_E_OK && cur_info->same_filenames)
      DeleteGwaFile(cur_info->output_file);

    PrintMsg("\n");
    PrintMsg("Total serious warnings: %d\n", cur_comms->total_big_warn);
    PrintMsg("Total minor warnings: %d\n", cur_comms->total_small_warn);

    ReportFailedLevels();
  }

  // close wads and free memory
  CloseWads();

  TermDebug();

  cur_info  = NULL;
  cur_comms = NULL;
  cur_funcs = NULL;

  return ret;
}