home *** CD-ROM | disk | FTP | other *** search
/ Xentax forum attachments archive / xentax.7z / 5036 / source.7z / xb360_onechanbara2.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2012-02-05  |  73.5 KB  |  2,098 lines

  1. #include "xentax.h"
  2. #include "xb360_onechanbara2.h"
  3.  
  4. namespace XB360 { namespace Onechanbara2 {
  5.  
  6. struct SURFACEINFO {
  7.  float32 bbox_xmin;
  8.  float32 bbox_ymin;
  9.  float32 bbox_zmin;
  10.  float32 bbox_xmax;
  11.  float32 bbox_ymax;
  12.  float32 bbox_zmax;
  13.  uint32  index;
  14.  uint16  elem;
  15.  uint16  type;
  16.  uint32  name;
  17. };
  18.  
  19. struct TEXTASSINFO {
  20.  uint32 material_index;
  21.  uint32 trilist;
  22. };
  23.  
  24. struct TRILISTINFO {
  25.  uint32 triangles;
  26.  uint32 offset;
  27. };
  28.  
  29. class extractor {
  30.  private :
  31.   std::string pathname;
  32.  private :
  33.   bool decompress(const char* filename, const char* extension);
  34.   bool processPK1(const char* filename);
  35.   bool processPK2(const char* filename);
  36.   bool processPK3(const char* filename);
  37.   bool processTEX(const char* filename);
  38.   bool processMDL(const char* filename);
  39.   bool processTMO(const char* filename);
  40.  public :
  41.   bool extract(void);
  42.  public :
  43.   extractor(const char* pn);
  44.  ~extractor();
  45. };
  46.  
  47. std::string GetTEXFromMDL(const std::string& filename);
  48. bool GetFilenamesFromTEX(const std::string& texfile, std::deque<std::string>& filenames);
  49.  
  50. };};
  51.  
  52. namespace XB360 { namespace Onechanbara2 {
  53.  
  54. extractor::extractor(const char* pn) : pathname(pn)
  55. {
  56. }
  57.  
  58. extractor::~extractor()
  59. {
  60. }
  61.  
  62. bool extractor::extract(void)
  63. {
  64.  using namespace std;
  65.  
  66.  // CAT files are archives that do not contain filenames
  67.  bool decompressCAT = true;
  68.  bool doPK1 = true;
  69.  
  70.  // CAN files are archives that also contain filenames
  71.  bool decompressCAN = true;
  72.  bool doPK2 = true;
  73.  
  74.  // CMP files are variable files in the demo, gamegui, and sys directories
  75.  bool decompressCMP = true;
  76.  bool doPK3 = true;
  77.  
  78.  // XPR files are texture files
  79.  bool decompressXPR = true;
  80.  bool doTEX = true;
  81.  
  82.  // TMD files are model files
  83.  bool decompressTMD = true;
  84.  bool doMDL = true;
  85.  bool doTMO = false;
  86.  
  87.  // decompress CAT files
  88.  if(decompressCAT) {
  89.     cout << "STAGE 1" << endl;
  90.     cout << "Decompressing CAT files to PK1 files using XBox360 unbundler." << endl;
  91.     deque<string> filelist;
  92.     BuildFilenameList(filelist, "cat", pathname.c_str());
  93.     for(size_t i = 0; i < filelist.size(); i++) {
  94.         cout << "Processing file " << (i + 1) << " of " << filelist.size() << ": " << filelist[i] << "." << endl;
  95.         if(!decompress(filelist[i].c_str(), "pk1")) return false;
  96.        }
  97.     cout << endl;
  98.    }
  99.  
  100.  // decompress CAN files
  101.  if(decompressCAN) {
  102.     cout << "STAGE 2" << endl;
  103.     cout << "Decompressing CAN files to PK2 files using XBox360 unbundler." << endl;
  104.     deque<string> filelist;
  105.     BuildFilenameList(filelist, "can", pathname.c_str());
  106.     for(size_t i = 0; i < filelist.size(); i++) {
  107.         cout << "Processing file " << (i + 1) << " of " << filelist.size() << ": " << filelist[i] << "." << endl;
  108.         if(!decompress(filelist[i].c_str(), "pk2")) return false;
  109.        }
  110.     cout << endl;
  111.    }
  112.  
  113.  // decompress CMP files
  114.  if(decompressCMP) {
  115.     cout << "STAGE 3" << endl;
  116.     cout << "Decompressing CMP files to PK3 files using XBox360 unbundler." << endl;
  117.     deque<string> filelist;
  118.     BuildFilenameList(filelist, "cmp", pathname.c_str());
  119.     for(size_t i = 0; i < filelist.size(); i++) {
  120.         cout << "Processing file " << (i + 1) << " of " << filelist.size() << ": " << filelist[i] << "." << endl;
  121.         if(!decompress(filelist[i].c_str(), "pk3")) return false;
  122.        }
  123.     cout << endl;
  124.    }
  125.  
  126.  // decompress XPR files
  127.  if(decompressXPR) {
  128.     cout << "STAGE 4" << endl;
  129.     cout << "Decompressing XPR files to TEX files using XBox360 unbundler." << endl;
  130.     deque<string> filelist;
  131.     BuildFilenameList(filelist, "xpr", pathname.c_str());
  132.     for(size_t i = 0; i < filelist.size(); i++) {
  133.         cout << "Processing file " << (i + 1) << " of " << filelist.size() << ": " << filelist[i] << "." << endl;
  134.         if(!decompress(filelist[i].c_str(), "tex")) return false;
  135.        }
  136.     cout << endl;
  137.    }
  138.  
  139.  // decompress TMD files
  140.  if(decompressTMD) {
  141.     cout << "STAGE 5" << endl;
  142.     cout << "Decompressing TMD files to MDL files using XBox360 unbundler." << endl;
  143.     deque<string> filelist;
  144.     BuildFilenameList(filelist, "tmd", pathname.c_str());
  145.     for(size_t i = 0; i < filelist.size(); i++) {
  146.         cout << "Processing file " << (i + 1) << " of " << filelist.size() << ": " << filelist[i] << "." << endl;
  147.         if(!decompress(filelist[i].c_str(), "mdl")) return false;
  148.        }
  149.     cout << endl;
  150.    }
  151.  
  152.  // process PK1 files
  153.  if(doPK1) {
  154.     cout << "STAGE 6" << endl;
  155.     cout << "Processing PK1 files." << endl;
  156.     deque<string> filelist;
  157.     BuildFilenameList(filelist, "pk1", pathname.c_str());
  158.     for(size_t i = 0; i < filelist.size(); i++) {
  159.         cout << "Processing file " << (i + 1) << " of " << filelist.size() << ": " << filelist[i] << "." << endl;
  160.         if(!processPK1(filelist[i].c_str())) return false;
  161.        }
  162.     cout << endl;
  163.    }
  164.  
  165.  // process PK2 files
  166.  if(doPK2) {
  167.     cout << "STAGE 7" << endl;
  168.     cout << "Processing PK2 files." << endl;
  169.     deque<string> filelist;
  170.     BuildFilenameList(filelist, "pk2", pathname.c_str());
  171.     for(size_t i = 0; i < filelist.size(); i++) {
  172.         cout << "Processing file " << (i + 1) << " of " << filelist.size() << ": " << filelist[i] << "." << endl;
  173.         if(!processPK2(filelist[i].c_str())) return false;
  174.        }
  175.     cout << endl;
  176.    }
  177.  
  178.  // process PK3 files
  179.  if(doPK3) {
  180.     cout << "STAGE 8" << endl;
  181.     cout << "Processing PK3 files." << endl;
  182.     deque<string> filelist;
  183.     BuildFilenameList(filelist, "pk3", pathname.c_str());
  184.     for(size_t i = 0; i < filelist.size(); i++) {
  185.         cout << "Processing file " << (i + 1) << " of " << filelist.size() << ": " << filelist[i] << "." << endl;
  186.         if(!processPK3(filelist[i].c_str())) return false;
  187.        }
  188.     cout << endl;
  189.    }
  190.  
  191.  // process TEX files
  192.  if(doTEX) {
  193.     cout << "STAGE 9" << endl;
  194.     cout << "Processing TEX files." << endl;
  195.     deque<string> filelist;
  196.     BuildFilenameList(filelist, "tex", pathname.c_str());
  197.     for(size_t i = 0; i < filelist.size(); i++) {
  198.         cout << "Processing file " << (i + 1) << " of " << filelist.size() << ": " << filelist[i] << "." << endl;
  199.         if(!processTEX(filelist[i].c_str())) return false;
  200.        }
  201.     cout << endl;
  202.    }
  203.  
  204.  // process MDL files
  205.  if(doMDL) {
  206.     cout << "STAGE 10" << endl;
  207.     cout << "Processing MDL files." << endl;
  208.     deque<string> filelist;
  209.     BuildFilenameList(filelist, "mdl", pathname.c_str());
  210.     for(size_t i = 0; i < filelist.size(); i++) {
  211.         cout << "Processing file " << (i + 1) << " of " << filelist.size() << ": " << filelist[i] << "." << endl;
  212.         if(!processMDL(filelist[i].c_str())) return false;
  213.        }
  214.     cout << endl;
  215.    }
  216.  
  217.  // process TMO files
  218.  if(doTMO) {
  219.     cout << "STAGE 11" << endl;
  220.     cout << "Processing TMO files." << endl;
  221.     deque<string> filelist;
  222.     BuildFilenameList(filelist, "tmo", pathname.c_str());
  223.     for(size_t i = 0; i < filelist.size(); i++) {
  224.         cout << "Processing file " << (i + 1) << " of " << filelist.size() << ": " << filelist[i] << "." << endl;
  225.         if(!processTMO(filelist[i].c_str())) return false;
  226.        }
  227.     cout << endl;
  228.    }
  229.  
  230.  //processMDL("C:\\Users\\semory\\sticklove\\source\\xentax\\Release\\onechanbara\\Player\\pl00_00_00\\000.mdl");
  231.  //processTMO("C:\\Users\\semory\\sticklove\\source\\xentax\\Release\\onechanbara\\Player\\pl00_00mot\\000.tmo");
  232.  
  233.  return true;
  234. }
  235.  
  236. bool extractor::decompress(const char* filename, const char* extension)
  237. {
  238.  using namespace std;
  239.  
  240.  // make sure file is compressed
  241.  ifstream ifile(filename, ios::binary);
  242.  if(!ifile) return error("Failed to open file.");
  243.  uint32 magic = BE_read_uint32(ifile);
  244.  if(ifile.fail()) return error("Read failure.");
  245.  
  246.  // file is not compressed
  247.  if(!(magic >= 0xFF51200 && magic <= 0xFF512FF))
  248.    {
  249.     // build filename
  250.     string ofname = GetPathnameFromFilename(filename);
  251.     ofname += GetShortFilenameWithoutExtension(filename);
  252.     ofname += ".";
  253.     ofname += extension;
  254.  
  255.     // create output file
  256.     ofstream ofile(ofname.c_str(), ios::binary);
  257.     if(!ofile) return error("Failed to create output file.");
  258.  
  259.     // compute filesize
  260.     ifile.seekg(0, ios::end);
  261.     size_t filesize = (size_t)ifile.tellg();
  262.     ifile.seekg(0, ios::beg);
  263.  
  264.     // read data
  265.     boost::shared_array<char> data(new char[filesize]);
  266.     ifile.read(data.get(), filesize);
  267.     if(ifile.fail()) return error("Read failure.");
  268.     ifile.close();
  269.  
  270.     // copy data
  271.     ofile.write(data.get(), filesize);
  272.  
  273.     // delete original
  274.     //DeleteFileA(filename);
  275.     return true;
  276.    }
  277.  else
  278.     ifile.close();
  279.  
  280.  // command line
  281.  string param1 = "\"";
  282.  param1 += pathname;
  283.  param1 += "xbdecompress.exe";
  284.  param1 += "\"";
  285.  param1 += " ";
  286.  param1 += "\"";
  287.  param1 += filename;
  288.  param1 += "\"";
  289.  param1 += " ";
  290.  param1 += "\"";
  291.  param1 += GetPathnameFromFilename(filename);
  292.  param1 += GetShortFilenameWithoutExtension(filename);
  293.  param1 += ".";
  294.  param1 += extension;
  295.  param1 += "\"";
  296.  
  297.  // process startup information
  298.  STARTUPINFOA sinfo;
  299.  ZeroMemory(&sinfo, sizeof(sinfo));
  300.  sinfo.cb = sizeof(sinfo);
  301.  
  302.  // process information
  303.  PROCESS_INFORMATION pinfo;
  304.  ZeroMemory(&pinfo, sizeof(pinfo));
  305.  
  306.  // run xbdecompress
  307.  char buffer[1024];
  308.  memmove(buffer, param1.c_str(), param1.length() + 1);
  309.  if(!CreateProcessA(NULL, buffer, NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS, NULL, NULL, &sinfo, &pinfo)) return error("Failed to run xbdecompress on XPR file.");
  310.  WaitForSingleObject(pinfo.hProcess, INFINITE);
  311.  CloseHandle(pinfo.hProcess);
  312.  CloseHandle(pinfo.hThread);
  313.  
  314.  // delete original
  315.  //DeleteFileA(filename);
  316.  return true;
  317. }
  318.  
  319. bool extractor::processPK1(const char* filename)
  320. {
  321.  using namespace std;
  322.  
  323.  // open file
  324.  ifstream ifile(filename, ios::binary);
  325.  if(!ifile) return error("error");
  326.  
  327.  // read header
  328.  std::deque<std::pair<size_t, size_t>> header;
  329.  for(;;) {
  330.      uint32 p01 = BE_read_uint32(ifile); if(ifile.fail()) return error("Read failure.");
  331.      uint32 p02 = BE_read_uint32(ifile); if(ifile.fail()) return error("Read failure.");
  332.      if(p01 == 0xFFFFFFFF && p02 == 0xFFFFFFFF) break;
  333.      if(header.size() > 1000) return error("Unexpected number of PAK sections.");
  334.      header.push_back(std::pair<size_t, size_t>(p01, p02));
  335.     }
  336.  
  337.  // create directory to store files
  338.  string pakpath = GetPathnameFromFilename(filename);
  339.  pakpath += GetShortFilenameWithoutExtension(filename);
  340.  pakpath += "\\";
  341.  CreateDirectoryA(pakpath.c_str(), NULL);
  342.  
  343.  // process files
  344.  deque<string> subpacks;
  345.  for(size_t i = 0; i < header.size(); i++)
  346.     {
  347.      // move to data
  348.      ifile.seekg(header[i].first);
  349.      if(ifile.fail()) return error("Seek failure.");
  350.      if(header[i].second == 0) continue;
  351.  
  352.      // read data
  353.      boost::shared_array<char> data(new char[header[i].second]);
  354.      ifile.read(data.get(), header[i].second);
  355.      if(ifile.fail()) return error("Read failure.");
  356.  
  357.      // create filename
  358.      stringstream ss;
  359.      ss << pakpath << setfill('0') << setw(3) << i << ".";
  360.      uint32 value = *reinterpret_cast<uint32*>(data.get());
  361.      switch(value) {
  362.        case(0x746D6F30) : ss << "tmo"; break;
  363.        case(0x746D6430) : ss << "mdl"; break;
  364.        case(0x32525058) : ss << "tex"; break;
  365.        case(0x54495400) : ss << "tit"; break;
  366.        case(0x544C4900) : ss << "tli"; break;
  367.        case(0x50524D70) : ss << "prm"; break;
  368.        case(0x52435354) : ss << "rcs"; break;
  369.        case(0x44544F4C) : ss << "dto"; break;
  370.        case(0x4C43504F) : ss << "lcp"; break;
  371.        case(0x4244534C) : ss << "bds"; break;
  372.        case(0x4553544D) : ss << "mts"; break;
  373.        case(0x64697242) : ss << "dir"; break;
  374.        case(0x6C6C6F52) : ss << "llo"; break;
  375.        case(0x706F7250) : ss << "por"; break;
  376.        case(0x7366664F) : ss << "sff"; break;
  377.        case(0x74697753) : ss << "tiw"; break;
  378.        case(0x00000000) : ss << "dat"; break;
  379.        case(0x01000000) : ss << "dat"; break;
  380.        case(0x01000100) : ss << "dat"; break;
  381.        case(0x01000200) : ss << "dat"; break;
  382.        case(0x01000300) : ss << "dat"; break;
  383.        case(0x01000400) : ss << "dat"; break;
  384.        case(0x01000500) : ss << "dat"; break;
  385.        case(0x02000000) : ss << "pla"; break;
  386.        case(0x10000000) : ss << "pk1"; subpacks.push_back(ss.str()); break; // more pk1 files!
  387.        case(0x20000000) : ss << "pk1"; subpacks.push_back(ss.str()); break; // more pk1 files!
  388.        case(0x30000000) : ss << "pk1"; subpacks.push_back(ss.str()); break; // more pk1 files!
  389.        case(0x40000000) : ss << "pk1"; subpacks.push_back(ss.str()); break; // more pk1 files!
  390.        case(0x50000000) : ss << "pk1"; subpacks.push_back(ss.str()); break; // more pk1 files!
  391.        case(0x60000000) : ss << "pk1"; subpacks.push_back(ss.str()); break; // more pk1 files!
  392.        case(0x70000000) : ss << "pk1"; subpacks.push_back(ss.str()); break; // more pk1 files!
  393.        case(0x80000000) : ss << "pk1"; subpacks.push_back(ss.str()); break; // more pk1 files!
  394.        case(0x90000000) : ss << "pk1"; subpacks.push_back(ss.str()); break; // more pk1 files!
  395.        case(0xA0000000) : ss << "pk1"; subpacks.push_back(ss.str()); break; // more pk1 files!
  396.        case(0xB0000000) : ss << "pk1"; subpacks.push_back(ss.str()); break; // more pk1 files!
  397.        case(0xC0000000) : ss << "pk1"; subpacks.push_back(ss.str()); break; // more pk1 files!
  398.        default : ss << "dat";
  399.       }
  400.  
  401.      // save data
  402.      ofstream ofile(ss.str().c_str(), ios::binary);
  403.      ofile.write(data.get(), header[i].second);
  404.     }
  405.  
  406.  // delete original
  407.  ifile.close();
  408.  //DeleteFileA(filename);
  409.  
  410.  // process subpacks
  411.  for(size_t i = 0; i < subpacks.size(); i++)
  412.      if(!processPK1(subpacks[i].c_str())) return false;
  413.  
  414.  return true;
  415. }
  416.  
  417. bool extractor::processPK2(const char* filename)
  418. {
  419.  using namespace std;
  420.  
  421.  // open file
  422.  ifstream ifile(filename, ios::binary);
  423.  if(!ifile) return error("error");
  424.  
  425.  // filesize
  426.  ifile.seekg(0, ios::end);
  427.  size_t filesize = (size_t)ifile.tellg();
  428.  ifile.seekg(0, ios::beg);
  429.  
  430.  // read header
  431.  struct triple { size_t offset, size; string name; };
  432.  deque<triple> header;
  433.  size_t position = 0;
  434.  for(;;)
  435.     {
  436.      // seek position
  437.      ifile.seekg(position);
  438.      if(ifile.fail()) return error("Seek failure.");
  439.  
  440.      // read item
  441.      uint32 p01 = BE_read_uint32(ifile); if(ifile.fail()) return error("Read failure.");
  442.      uint32 p02 = BE_read_uint32(ifile); if(ifile.fail()) return error("Read failure.");
  443.      if(p01 == 0xFFFFFFFF && p02 == 0xFFFFFFFF) break;
  444.  
  445.      // name follows
  446.      bool is_name = false;
  447.      uint32 namelen = 0;
  448.      if(p01 < p02) {
  449.         if((p02 - p01) == 0x10) { namelen = 0x10; is_name = true; }
  450.         else if((p02 - p01) == 0x20) { namelen = 0x20; is_name = true; }
  451.         else if((p02 - p01) == 0x30) { namelen = 0x30; is_name = true; }
  452.         else if(p02 == 0xFFFFFFFF) { namelen = filesize - p01; is_name = true; }
  453.        }
  454.  
  455.      // extract name
  456.      if(is_name) {
  457.         ifile.seekg(p01);
  458.         char buffer[1024];
  459.         read_string(ifile, buffer, 1024);
  460.         header.back().name = buffer;
  461.        }
  462.      else {
  463.         triple item;
  464.         item.offset = p01;
  465.         item.size = p02;
  466.         header.push_back(item);
  467.        }
  468.  
  469.      // move position
  470.      if(is_name) position += 4;
  471.      else position += 8;
  472.     }
  473.  
  474.  // create directory to store files
  475.  string sendpath = GetPathnameFromFilename(filename);
  476.  sendpath += GetShortFilenameWithoutExtension(filename);
  477.  sendpath += "\\";
  478.  CreateDirectoryA(sendpath.c_str(), NULL);
  479.  
  480.  // process files
  481.  deque<string> subpacks;
  482.  for(size_t i = 0; i < header.size(); i++)
  483.     {
  484.      // move to data
  485.      ifile.seekg(header[i].offset);
  486.      if(ifile.fail()) return error("Seek failure.");
  487.      if(header[i].size == 0) continue;
  488.  
  489.      // read data
  490.      boost::shared_array<char> data(new char[header[i].size]);
  491.      ifile.read(data.get(), header[i].size);
  492.      if(ifile.fail()) return error("Read failure.");
  493.  
  494.      // create filename
  495.      stringstream ss;
  496.      ss << sendpath;
  497.      if(header[i].name.length()) ss << GetShortFilenameWithoutExtension(header[i].name) << ".";
  498.      else ss << setfill('0') << setw(3) << i << ".";
  499.  
  500.      // save data
  501.      uint32 value = *reinterpret_cast<uint32*>(data.get());
  502.      switch(value) {
  503.        case(0x746D6F30) : ss << "tmo"; break;
  504.        case(0x746D6430) : ss << "mdl"; break;
  505.        case(0x32525058) : ss << "tex"; break;
  506.        case(0x54495400) : ss << "tit"; break;
  507.        case(0x544C4900) : ss << "tli"; break;
  508.        case(0x50524D70) : ss << "prm"; break;
  509.        case(0x52435354) : ss << "rcs"; break;
  510.        case(0x44544F4C) : ss << "dto"; break;
  511.        case(0x4C43504F) : ss << "lcp"; break;
  512.        case(0x4244534C) : ss << "bds"; break;
  513.        case(0x4553544D) : ss << "mts"; break;
  514.        case(0x64697242) : ss << "dir"; break;
  515.        case(0x6C6C6F52) : ss << "llo"; break;
  516.        case(0x706F7250) : ss << "por"; break;
  517.        case(0x7366664F) : ss << "sff"; break;
  518.        case(0x74697753) : ss << "tiw"; break;
  519.        case(0x00000000) : ss << "dat"; break;
  520.        case(0x01000000) : ss << "dat"; break;
  521.        case(0x01000100) : ss << "dat"; break;
  522.        case(0x01000200) : ss << "dat"; break;
  523.        case(0x01000300) : ss << "dat"; break;
  524.        case(0x01000400) : ss << "dat"; break;
  525.        case(0x01000500) : ss << "dat"; break;
  526.        case(0x02000000) : ss << "pla"; break;
  527.        case(0x10000000) : ss << "pak"; subpacks.push_back(ss.str()); break; // more pak files!
  528.        case(0x20000000) : ss << "pak"; subpacks.push_back(ss.str()); break; // more pak files!
  529.        case(0x30000000) : ss << "pak"; subpacks.push_back(ss.str()); break; // more pak files!
  530.        case(0x40000000) : ss << "pak"; subpacks.push_back(ss.str()); break; // more pak files!
  531.        case(0x50000000) : ss << "pak"; subpacks.push_back(ss.str()); break; // more pak files!
  532.        case(0x60000000) : ss << "pak"; subpacks.push_back(ss.str()); break; // more pak files!
  533.        case(0x70000000) : ss << "pak"; subpacks.push_back(ss.str()); break; // more pak files!
  534.        case(0x80000000) : ss << "pak"; subpacks.push_back(ss.str()); break; // more pak files!
  535.        case(0x90000000) : ss << "pak"; subpacks.push_back(ss.str()); break; // more pak files!
  536.        case(0xA0000000) : ss << "pak"; subpacks.push_back(ss.str()); break; // more pak files!
  537.        case(0xB0000000) : ss << "pak"; subpacks.push_back(ss.str()); break; // more pak files!
  538.        case(0xC0000000) : ss << "pak"; subpacks.push_back(ss.str()); break; // more pak files!
  539.        default : ss << "dat";
  540.       }
  541.  
  542.      // save data
  543.      ofstream ofile(ss.str().c_str(), ios::binary);
  544.      ofile.write(data.get(), header[i].size);
  545.     }
  546.  
  547.  // delete original
  548.  ifile.close();
  549.  //DeleteFileA(filename);
  550.  
  551.  // process subpacks
  552.  for(size_t i = 0; i < subpacks.size(); i++)
  553.      if(!processPK1(subpacks[i].c_str())) return false;
  554.  
  555.  return true;
  556. }
  557.  
  558. bool extractor::processPK3(const char* filename)
  559. {
  560.  using namespace std;
  561.  
  562.  // open file
  563.  ifstream ifile(filename, ios::binary);
  564.  if(!ifile) return error("Failed to open file.");
  565.  
  566.  // read magic
  567.  uint32 magic = BE_read_uint32(ifile);
  568.  if(ifile.fail()) return error("Read failure.");
  569.  
  570.  // determine file extension
  571.  string extension = "";
  572.  if(magic == 0x30646D74) extension = "mdl";
  573.  else if(magic == 0x58505232) extension = "tex";
  574.  else if(magic == 0x54455854) extension = "sub";
  575.  else return error("Unknown PK3 file format.");
  576.  
  577.  // build filename
  578.  string ofname = GetPathnameFromFilename(filename);
  579.  ofname += GetShortFilenameWithoutExtension(filename);
  580.  ofname += ".";
  581.  ofname += extension;
  582.  
  583.  // create output file
  584.  ofstream ofile(ofname.c_str(), ios::binary);
  585.  if(!ofile) return error("Failed to create output file.");
  586.  
  587.  // compute filesize
  588.  ifile.seekg(0, ios::end);
  589.  size_t filesize = (size_t)ifile.tellg();
  590.  ifile.seekg(0, ios::beg);
  591.  
  592.  // read data
  593.  boost::shared_array<char> data(new char[filesize]);
  594.  ifile.read(data.get(), filesize);
  595.  if(ifile.fail()) return error("Read failure.");
  596.  ifile.close();
  597.  
  598.  // copy data
  599.  ofile.write(data.get(), filesize);
  600.  
  601.  // delete original
  602.  //DeleteFileA(filename);
  603.  return true;
  604. }
  605.  
  606. bool extractor::processTEX(const char* filename)
  607. {
  608.  using namespace std;
  609.  
  610.  // file properties
  611.  string filepath = GetPathnameFromFilename(filename);
  612.  string shrtname = GetShortFilename(filename);
  613.  
  614.  // create storage path
  615.  string savepath = GetPathnameFromFilename(filename);
  616.  savepath += GetShortFilenameWithoutExtension(filename);
  617.  savepath += "\\";
  618.  CreateDirectoryA(savepath.c_str(), NULL);
  619.  
  620.  // create storage path subdirectory
  621.  // some XPR files have subdirectories, and unless you have a subdirectory name that way, unbundler won't save anything
  622.  // fortunately, the subdirectory is always called tex
  623.  string savepathsubdir = savepath;
  624.  savepathsubdir += "tex\\";
  625.  CreateDirectoryA(savepathsubdir.c_str(), NULL);
  626.  
  627.  // unbundle and delete RDF files
  628.  bool retval = XB360Unbundle(pathname.c_str(), filename, savepath.c_str());
  629.  string rdffile = filepath;
  630.  rdffile += shrtname;
  631.  rdffile += ".rdf";
  632.  DeleteFileA(rdffile.c_str());
  633.  return retval;
  634. }
  635.  
  636. bool extractor::processMDL(const char* filename)
  637. {
  638.  // validate
  639.  using namespace std;
  640.  if(!filename || !strlen(filename)) return error("Invalid filename.");
  641.  
  642.  // variables
  643.  string fn_path = GetPathnameFromFilename(filename);
  644.  string fn_name = GetShortFilenameWithoutExtension(filename);
  645.  
  646.  // data
  647.  uint32 fileinfo[30];
  648.  deque<SURFACEINFO> surface_data;
  649.  deque<TEXTASSINFO> textass_data;
  650.  deque<TRILISTINFO> trilist_data;
  651.  
  652.  // data
  653.  GEOMETRY geometry;
  654.  MATERIAL_LIST materials;
  655.  TEXTURE_LIST textures;
  656.  SKELETON_LIST skeletons;
  657.  
  658.  // initialize geometry
  659.  geometry.id = "mesh";
  660.  geometry.name = "mesh";
  661.  geometry.meshlist.push_back(boost::shared_ptr<MESH>(new MESH()));
  662.  
  663.  // enable debug mode
  664.  bool debug = true;
  665.  ofstream dfile;
  666.  if(debug) {
  667.     stringstream ss;
  668.     ss << fn_path << fn_name << ".txt";
  669.     dfile.open(ss.str().c_str());
  670.    }
  671.  
  672.  // open file
  673.  ifstream ifile(filename, ios::binary);
  674.  if(!ifile) return error("Failed to open MDL file.");
  675.  
  676.  //
  677.  // PROCESS #01
  678.  // READ AND PROCESS FILE HEADER
  679.  //
  680.  
  681.  // read header
  682.  auto head01 = BE_read_uint32(ifile);
  683.  auto head02 = BE_read_uint32(ifile);
  684.  auto head03 = BE_read_uint32(ifile);
  685.  auto head04 = BE_read_uint32(ifile);
  686.  auto head05 = BE_read_float32(ifile);
  687.  auto head06 = BE_read_float32(ifile);
  688.  auto head07 = BE_read_float32(ifile);
  689.  auto head08 = BE_read_float32(ifile);
  690.  auto head09 = BE_read_float32(ifile);
  691.  auto head10 = BE_read_float32(ifile);
  692.  if(debug) dfile << "HEADER" << endl;
  693.  if(debug) dfile << head01 << endl;
  694.  if(debug) dfile << head02 << endl;
  695.  if(debug) dfile << head03 << endl;
  696.  if(debug) dfile << head04 << endl;
  697.  if(debug) dfile << head05 << endl;
  698.  if(debug) dfile << head06 << endl;
  699.  if(debug) dfile << head07 << endl;
  700.  if(debug) dfile << head08 << endl;
  701.  if(debug) dfile << head09 << endl;
  702.  if(debug) dfile << head10 << endl;
  703.  if(debug) dfile << endl;
  704.  
  705.  // validate header
  706.  if(head01 != 0x30646D74) return error("Invalid MDL file.");
  707.  if(head04 != 0x28) return error("Invalid MDL file.");
  708.  
  709.  // determine vertex size
  710.  uint32 vertexsize = 0;
  711.  switch(head02) {
  712.    case(0x1D01AF) : vertexsize = 0x0C; break; // OK (HUD)
  713.    case(0x1D01BF) : vertexsize = 0x0C; break; // OK (PLAYER WEAPONS)
  714.    case(0x1D02BF) : vertexsize = 0x0C; break; // OK
  715.    case(0x1D80A7) : vertexsize = 0x18; break; // OK
  716.    case(0x1D80AF) : vertexsize = 0x1C; break; // OK
  717.    case(0x1D81A7) : vertexsize = 0x18; break; // OK
  718.    case(0x1D81AF) : vertexsize = 0x1C; break; // OK
  719.    case(0x1D82A7) : vertexsize = 0x18; break; // OK (HUGE MAPS)
  720.    case(0x1D82AF) : vertexsize = 0x1C; break; // OK (HUGE MAPS)
  721.    case(0x1DB8A7) : vertexsize = 0x20; break; // OK (LEVEL MODELS)
  722.    case(0x1DB8AF) : vertexsize = 0x24; break; // OK (LEVEL MODELS)
  723.    case(0x1DB9A7) : vertexsize = 0x20; break; // OK (PLAYER AND ENEMIES)
  724.    default : {
  725.         stringstream msg;
  726.         msg << "Unknown vertex type " << head02 << ".";
  727.         return error(msg.str().c_str());
  728.        }
  729.  }
  730.  
  731.  // determine index size and type
  732.  unsigned char indextype = FACE_FORMAT_UINT_16;
  733.  unsigned char indexsize = 2;
  734.  if(head02 == 0x1D02BF || head02 == 0x1D82A7 || head02 == 0x1D82AF) {
  735.     indextype = FACE_FORMAT_UINT_32;
  736.     indexsize = 4;
  737.    }
  738.  
  739.  //
  740.  // PROCESS #02
  741.  // READ AND SAVE FILE INFORMATION
  742.  //
  743.  if(debug) dfile << "FILE INFORMATION" << endl;
  744.  for(size_t i = 0; i < 30; i++) fileinfo[i] = BE_read_uint32(ifile);
  745.  if(debug) for(size_t i = 0; i < 30; i++) if(debug) dfile << fileinfo[i] << endl;
  746.  if(debug) dfile << endl;
  747.  
  748.  //
  749.  // PROCESS #03
  750.  // READ SURFACE INFORMATION PART 1
  751.  //
  752.  
  753.  // move to surface information
  754.  if(debug) dfile << "SURFACE INFORMATION PART 1" << endl;
  755.  ifile.seekg(fileinfo[0]);
  756.  if(ifile.fail()) return error("Seek failure.");
  757.  
  758.  // process surfaces
  759.  uint32 n_surfaces = fileinfo[1];
  760.  if(n_surfaces == 0 || n_surfaces > 1000) return error("Unexpected number of surfaces.");
  761.  for(uint32 i = 0; i < n_surfaces; i++)
  762.     {
  763.      auto param01 = BE_read_float32(ifile);
  764.      auto param02 = BE_read_float32(ifile);
  765.      auto param03 = BE_read_float32(ifile);
  766.      auto param04 = BE_read_float32(ifile);
  767.      auto param05 = BE_read_float32(ifile);
  768.      auto param06 = BE_read_float32(ifile);
  769.      auto param07 = BE_read_uint32(ifile);
  770.      auto param08 = BE_read_uint16(ifile);
  771.      auto param09 = BE_read_uint16(ifile);
  772.      auto param10 = BE_read_uint32(ifile);
  773.      auto param11 = BE_read_uint32(ifile);
  774.      auto param12 = BE_read_uint32(ifile);
  775.      auto param13 = BE_read_uint32(ifile);
  776.      auto param14 = BE_read_uint32(ifile);
  777.      auto param15 = BE_read_uint32(ifile);
  778.      if(debug) dfile << setw(3) << param07 << " ";
  779.      if(debug) dfile << setw(3) << param08 << " ";
  780.      if(debug) dfile << setw(3) << param09 << " ";
  781.      if(debug) dfile << param10 << " ";
  782.      if(debug) dfile << setw(3) << param11 << " ";
  783.      if(debug) dfile << setw(3) << param12 << " ";
  784.      if(debug) dfile << setw(3) << param13 << " ";
  785.      if(debug) dfile << setw(3) << param14 << " ";
  786.      if(debug) dfile << endl;
  787.      SURFACEINFO si;
  788.      si.bbox_xmin = param01;
  789.      si.bbox_ymin = param02;
  790.      si.bbox_zmin = param03;
  791.      si.bbox_xmax = param04;
  792.      si.bbox_ymax = param05;
  793.      si.bbox_zmax = param06;
  794.      si.index = param07;
  795.      si.elem = param08;
  796.      si.type = param09;
  797.      si.name = param10;
  798.      surface_data.push_back(si);
  799.     }
  800.   if(debug) dfile << endl;
  801.  
  802.  //
  803.  // PROCESS #04
  804.  // READ SURFACE INFORMATION PART 2
  805.  //
  806.  
  807.  // move to surface information
  808.  if(debug) dfile << "SURFACE INFORMATION PART 2" << endl;
  809.  ifile.seekg(fileinfo[2]);
  810.  if(ifile.fail()) return error("Seek failure.");
  811.  
  812.  // read surface information
  813.  uint32 n_values = fileinfo[3];
  814.  for(size_t i = 0; i < n_surfaces; i++)
  815.     {
  816.      // read group information
  817.      boost::shared_array<uint16> data(new uint16[surface_data[i].elem]);
  818.      BE_read_array(ifile, data.get(), surface_data[i].elem);
  819.      if(ifile.fail()) return error("Read failure.");
  820.  
  821.      // 20XX reference to part 4
  822.      // 40XX reference to part 3
  823.      // 30XX reference to group
  824.      uint16 curr_0x2000 = 0xFFFF; // texture_data reference
  825.      uint16 curr_0x3000 = 0xFFFF; // trilist_data reference
  826.      uint16 curr_0x4000 = 0xFFFF; // unknown reference
  827.  
  828.      // for each item read
  829.      for(size_t j = 0; j < surface_data[i].elem; j++) {
  830.          if(data[j] == 0x1000) {
  831.             curr_0x2000 = 0xFFFF;
  832.             curr_0x3000 = 0xFFFF;
  833.             curr_0x4000 = 0xFFFF;
  834.            }
  835.          else if((data[j] & 0xFF00) == 0x2000) curr_0x2000 = (uint16)(data[j] & 0x00FF);
  836.          else if((data[j] & 0xFF00) == 0x3000) {
  837.             curr_0x3000 = (uint16)(data[j] & 0x00FF);
  838.             TEXTASSINFO info = { curr_0x2000, curr_0x3000 };
  839.             textass_data.push_back(info);
  840.            }
  841.          else if((data[j] & 0xFF00) == 0x4000) curr_0x4000 = (uint16)(data[j] & 0x00FF);
  842.         }
  843.     }
  844.  if(debug) dfile << "Number of texture-group associations = " << textass_data.size() << endl;
  845.  if(debug) for(size_t i = 0; i < textass_data.size(); i++)  dfile << textass_data[i].material_index << "," << textass_data[i].trilist << endl;
  846.  if(debug) dfile << endl;
  847.  
  848.  //
  849.  // PROCESS #05
  850.  // READ SURFACE INFORMATION PART 3
  851.  //
  852.  
  853.  if(fileinfo[6] != 0)
  854.    {
  855.     // move to surface information
  856.     if(debug) dfile << "SURFACE INFORMATION PART 3" << endl;
  857.     ifile.seekg(fileinfo[6]);
  858.     if(ifile.fail()) return error("Seek failure.");
  859.    
  860.     // read data
  861.     uint32 n_items = fileinfo[7];
  862.     if(debug) dfile << "Number of items = " << n_items << endl;
  863.     for(uint32 i = 0; i < n_items; i++)
  864.        {
  865.         auto p01 = BE_read_uint32(ifile);
  866.         auto p02 = BE_read_uint32(ifile);
  867.         auto p03 = BE_read_uint32(ifile);
  868.         auto p04 = BE_read_uint32(ifile);
  869.         auto p05 = BE_read_uint32(ifile);
  870.         auto p06 = BE_read_uint32(ifile);
  871.         auto p07 = BE_read_uint32(ifile);
  872.         auto p08 = BE_read_uint32(ifile);
  873.         auto p09 = BE_read_uint32(ifile);
  874.         auto p10 = BE_read_uint32(ifile);
  875.         auto p11 = BE_read_uint32(ifile);
  876.         auto p12 = BE_read_uint32(ifile);
  877.         auto p13 = BE_read_uint32(ifile);
  878.         auto p14 = BE_read_uint32(ifile);
  879.         auto p15 = BE_read_uint32(ifile);
  880.         auto p16 = BE_read_uint32(ifile);
  881.         auto p17 = BE_read_uint32(ifile);
  882.         auto p18 = BE_read_uint32(ifile);
  883.         auto p19 = BE_read_uint32(ifile);
  884.         auto p20 = BE_read_uint32(ifile);
  885.         auto p21 = BE_read_uint32(ifile);
  886.         auto p22 = BE_read_uint32(ifile);
  887.         auto p23 = BE_read_uint32(ifile);
  888.         auto p24 = BE_read_uint32(ifile);
  889.         auto p25 = BE_read_uint32(ifile);
  890.         auto p26 = BE_read_uint32(ifile);
  891.         auto p27 = BE_read_uint32(ifile);
  892.         auto p28 = BE_read_uint32(ifile);
  893.         auto p29 = BE_read_uint32(ifile);
  894.         auto p30 = BE_read_uint32(ifile);
  895.         auto p31 = BE_read_uint32(ifile);
  896.         auto p32 = BE_read_uint32(ifile);
  897.         auto p33 = BE_read_uint32(ifile);
  898.         if(debug) dfile << setw(3) << p01 << " ";
  899.         if(debug) dfile << setw(3) << p02 << " ";
  900.         if(debug) dfile << setw(3) << p03 << " ";
  901.         if(debug) dfile << setw(3) << p04 << " ";
  902.         if(debug) dfile << setw(3) << p05 << " ";
  903.         if(debug) dfile << setw(3) << p06 << " ";
  904.         if(debug) dfile << setw(3) << p07 << " ";
  905.         if(debug) dfile << setw(3) << p08 << " ";
  906.         if(debug) dfile << setw(3) << p09 << " ";
  907.         if(debug) dfile << setw(3) << p10 << " ";
  908.         if(debug) dfile << setw(3) << p11 << " ";
  909.         if(debug) dfile << setw(3) << p12 << " ";
  910.         if(debug) dfile << setw(3) << p13 << " ";
  911.         if(debug) dfile << setw(3) << p14 << " ";
  912.         if(debug) dfile << setw(3) << p15 << " ";
  913.         if(debug) dfile << setw(3) << p16 << " ";
  914.         if(debug) dfile << setw(3) << p17 << " ";
  915.         if(debug) dfile << setw(3) << p18 << " ";
  916.         if(debug) dfile << setw(3) << p19 << " ";
  917.         if(debug) dfile << setw(3) << p20 << " ";
  918.         if(debug) dfile << setw(3) << p21 << " ";
  919.         if(debug) dfile << setw(3) << p22 << " ";
  920.         if(debug) dfile << setw(3) << p23 << " ";
  921.         if(debug) dfile << setw(3) << p24 << " ";
  922.         if(debug) dfile << setw(3) << p25 << " ";
  923.         if(debug) dfile << setw(3) << p26 << " ";
  924.         if(debug) dfile << setw(3) << p27 << " ";
  925.         if(debug) dfile << setw(3) << p28 << " ";
  926.         if(debug) dfile << setw(3) << p29 << " ";
  927.         if(debug) dfile << setw(3) << p30 << " ";
  928.         if(debug) dfile << setw(3) << p31 << " ";
  929.         if(debug) dfile << setw(3) << p32 << " ";
  930.         if(debug) dfile << setw(3) << p33 << " ";
  931.         if(debug) dfile << endl;
  932.        }
  933.     if(debug) dfile << endl;
  934.    }
  935.  
  936.  //
  937.  // PROCESS #06
  938.  // READ MATERIALS
  939.  //
  940.  
  941.  if(fileinfo[8] != 0)
  942.    {
  943.     // move to surface information
  944.     if(debug) dfile << "MATERIALS" << endl;
  945.     ifile.seekg(fileinfo[8]);
  946.     if(ifile.fail()) return error("Seek failure.");
  947.     
  948.     // read data
  949.     uint32 n_items = fileinfo[9];
  950.     if(debug) dfile << "Number of items = " << n_items << endl;
  951.  
  952.     for(uint32 i = 0; i < n_items; i++)
  953.        {
  954.         // read material
  955.         auto p01 = BE_read_uint32 (ifile); // 0x05
  956.         auto p02 = BE_read_uint32 (ifile); // 0x00
  957.         auto p03 = BE_read_uint32 (ifile); // base texture index
  958.         auto p04 = BE_read_float32(ifile); // crap
  959.         auto p05 = BE_read_float32(ifile); // crap
  960.         auto p06 = BE_read_float32(ifile); // crap
  961.         auto p07 = BE_read_float32(ifile); // crap
  962.         auto p08 = BE_read_uint32 (ifile); // 0xFFFFFFFF
  963.         auto p09 = BE_read_uint32 (ifile); // 0xFFFFFFFF
  964.         auto p10 = BE_read_float32(ifile); // crap
  965.         auto p11 = BE_read_float32(ifile); // crap
  966.         auto p12 = BE_read_float32(ifile); // crap
  967.         auto p13 = BE_read_float32(ifile); // crap
  968.         auto p14 = BE_read_uint32 (ifile); // 0xFFFFFFFF
  969.         auto p15 = BE_read_uint32 (ifile); // 0xFFFFFFFF
  970.         auto p16 = BE_read_float32(ifile); // crap
  971.         auto p17 = BE_read_float32(ifile); // crap
  972.         auto p18 = BE_read_float32(ifile); // crap
  973.         auto p19 = BE_read_float32(ifile); // end of 3 4xfloats
  974.         auto p20 = BE_read_uint32 (ifile); // 0x03
  975.         auto p21 = BE_read_uint32 (ifile); // normal map index
  976.         auto p22 = BE_read_float32(ifile); // crap
  977.         auto p23 = BE_read_float32(ifile); // crap
  978.         auto p24 = BE_read_float32(ifile); // crap
  979.         auto p25 = BE_read_float32(ifile); // crap
  980.         auto p26 = BE_read_uint32 (ifile); // 0x04
  981.         auto p27 = BE_read_uint32 (ifile); // specular map index
  982.         auto p28 = BE_read_float32(ifile); // crap
  983.         auto p29 = BE_read_float32(ifile); // crap
  984.         auto p30 = BE_read_float32(ifile); // crap
  985.         auto p31 = BE_read_float32(ifile); // crap
  986.         auto p32 = BE_read_uint32 (ifile); // 0x01
  987.         auto p33 = BE_read_uint32 (ifile); // 0x00
  988.         auto p34 = BE_read_uint32 (ifile); // 0x01
  989.         auto p35 = BE_read_uint32 (ifile); // 0x01
  990.         auto p36 = BE_read_uint32 (ifile); // 0x01
  991.         auto p37 = BE_read_float32(ifile); // crap
  992.         auto p38 = BE_read_float32(ifile); // crap
  993.         auto p39 = BE_read_float32(ifile); // crap
  994.         auto p40 = BE_read_float32(ifile); // crap
  995.         auto p41 = BE_read_float32(ifile); // crap
  996.         auto p42 = BE_read_float32(ifile); // crap
  997.         auto p43 = BE_read_float32(ifile); // crap
  998.         auto p44 = BE_read_float32(ifile); // crap
  999.         auto p45 = BE_read_float32(ifile); // crap
  1000.         auto p46 = BE_read_float32(ifile); // crap
  1001.         auto p47 = BE_read_float32(ifile); // crap
  1002.         auto p48 = BE_read_float32(ifile); // crap
  1003.         auto p49 = BE_read_float32(ifile); // crap
  1004.         auto p50 = BE_read_float32(ifile); // crap
  1005.         if(debug) dfile << p01 << " "; // << endl;
  1006.         if(debug) dfile << p02 << " "; // << endl;
  1007.         if(debug) dfile << p03 << " "; // << endl;
  1008.         if(debug) dfile << p08 << " "; // << endl;
  1009.         if(debug) dfile << p09 << " "; // << endl;
  1010.         if(debug) dfile << p14 << " "; // << endl;
  1011.         if(debug) dfile << p15 << " "; // << endl;
  1012.         if(debug) dfile << p20 << " "; // << endl;
  1013.         if(debug) dfile << p21 << " "; // << endl;
  1014.         if(debug) dfile << p26 << " "; // << endl;
  1015.         if(debug) dfile << p27 << " "; // << endl;
  1016.         if(debug) dfile << p32 << " "; // << endl;
  1017.         if(debug) dfile << p33 << " "; // << endl;
  1018.         if(debug) dfile << p34 << " "; // << endl;
  1019.         if(debug) dfile << p35 << " "; // << endl;
  1020.         if(debug) dfile << p36 << " "; // << endl;
  1021.         if(debug) dfile << endl;
  1022.  
  1023.         // build material name
  1024.         stringstream name;
  1025.         name << "material_" << setfill('0') << setw(3) << i;
  1026.  
  1027.         // save material
  1028.         MATERIAL m;
  1029.         m.id = name.str();
  1030.         m.basemap = p03;
  1031.         m.normmap = p21;
  1032.         m.specmap = p27;
  1033.         m.bumpmap = 0xFFFFFFFF;
  1034.         materials.push_back(m);
  1035.        }
  1036.     if(debug) dfile << endl;
  1037.    }
  1038.  
  1039.  //
  1040.  // PROCESS #07
  1041.  // READ TRIANGLE GROUP DATA
  1042.  //
  1043.  
  1044.  if(fileinfo[10])
  1045.    {
  1046.     // move to triangle information
  1047.     if(debug) dfile << "TRIANGLE GROUPS (TRIANGLES, POSITION)" << endl;
  1048.     ifile.seekg(fileinfo[10]);
  1049.     if(ifile.fail()) return error("Seek failure.");
  1050.  
  1051.     // number of groups
  1052.     uint32 n_groups = fileinfo[11];
  1053.     if(n_groups == 0) return error("Invalid number of triangle groups.");
  1054.  
  1055.     // read triangle information
  1056.     if(indextype == FACE_FORMAT_UINT_16) {
  1057.        for(uint32 i = 0; i < n_groups; i++) {
  1058.            uint32 p1 = BE_read_uint16(ifile); // number of triangles
  1059.            BE_read_uint16(ifile);             // always 0
  1060.            uint32 p2 = BE_read_uint32(ifile); // triangle offset
  1061.            TRILISTINFO info = { p1, p2 };
  1062.            trilist_data.push_back(info);
  1063.            if(debug) dfile << "g[" << i << "] = (" << p1 << ", " << p2 << ")" << endl;
  1064.           }
  1065.       }
  1066.     else if(indextype == FACE_FORMAT_UINT_32) {
  1067.        for(uint32 i = 0; i < n_groups; i++) {
  1068.            uint32 p1 = BE_read_uint32(ifile); // number of triangles
  1069.            uint32 p2 = BE_read_uint32(ifile); // triangle offset
  1070.            TRILISTINFO info = { p1, p2 };
  1071.            trilist_data.push_back(info);
  1072.            if(debug) dfile << "g[" << i << "] = (" << p1 << ", " << p2 << ")" << endl;
  1073.           }
  1074.       }
  1075.     if(debug) dfile << endl;
  1076.    }
  1077.  
  1078.  //
  1079.  // PROCESS #08
  1080.  // READ INDEX BUFFER
  1081.  //
  1082.  
  1083.  // move to index buffer
  1084.  if(debug) dfile << "INDEX BUFFER DATA" << endl;
  1085.  ifile.seekg(fileinfo[12]);
  1086.  if(ifile.fail()) return error("Seek failure.");
  1087.  
  1088.  // number of triangles
  1089.  uint32 n_triangles = fileinfo[13];
  1090.  if(n_triangles == 0) return error("Invalid number of triangles.");
  1091.  
  1092.  // process triangle groups
  1093.  for(size_t i = 0; i < trilist_data.size(); i++)
  1094.     {
  1095.      // get texture-material association data
  1096.      TEXTASSINFO ai = textass_data[i];
  1097.      if(!(ai.material_index < materials.size())) return error("Texture association data is invalid.");
  1098.      uint32 ib_material = ai.material_index;
  1099.  
  1100.      // surface name
  1101.      stringstream ss;
  1102.      ss << "surface_" << setfill('0') << setw(3) << i;
  1103.  
  1104.      // move to data offset
  1105.      uint32 ib_offset = 3*indexsize*trilist_data[i].offset;
  1106.      ifile.seekg(fileinfo[12] + ib_offset);
  1107.      if(ifile.fail()) return error("Seek failure.");
  1108.  
  1109.      // read index buffer
  1110.      uint32 ib_tris = trilist_data[i].triangles;
  1111.      uint32 ib_elem = ib_tris*3;
  1112.      uint32 ib_char = ib_elem*indexsize;
  1113.      boost::shared_array<char> ib_data(new char[ib_char]);
  1114.      if(indextype == FACE_FORMAT_UINT_16) BE_read_array(ifile, reinterpret_cast<uint16*>(ib_data.get()), ib_elem);
  1115.      else BE_read_array(ifile, reinterpret_cast<uint32*>(ib_data.get()), ib_elem);
  1116.      if(ifile.fail()) return error("Read failure.");
  1117.  
  1118.      // create index buffer
  1119.      IDX_BUFFER ib;
  1120.      ib.format = indextype;
  1121.      ib.type = FACE_TYPE_TRIANGLES;
  1122.      ib.name = ss.str();
  1123.      ib.elem = ib_elem;
  1124.      ib.data = ib_data;
  1125.      ib.material = ib_material;
  1126.  
  1127.      // save index buffer
  1128.      geometry.meshlist[0]->surfaces.push_back(ib);
  1129.     }
  1130.  if(debug) dfile << endl;
  1131.  
  1132.  //
  1133.  // PROCESS #09
  1134.  // READ VERTEX BUFFER
  1135.  //
  1136.  
  1137.  // move to vertex buffer
  1138.  if(debug) dfile << "VERTEX BUFFER DATA" << endl;
  1139.  ifile.seekg(fileinfo[15]);
  1140.  if(ifile.fail()) return error("Seek failure.");
  1141.  
  1142.  // number of vertices
  1143.  uint32 n_vertices = fileinfo[14];
  1144.  if(n_vertices == 0) return error("Invalid number of vertices.");
  1145.  
  1146.  // create vertex buffer
  1147.  geometry.meshlist[0]->vertices.flags = VERTEX_POSITION | VERTEX_UV;
  1148.  geometry.meshlist[0]->vertices.elem = n_vertices;
  1149.  geometry.meshlist[0]->vertices.data.reset(new VERTEX[n_vertices]);
  1150.  if(head02 == 0x1DB9A7) {
  1151.     geometry.meshlist[0]->vertices.flags |= VERTEX_WEIGHTS;
  1152.     geometry.meshlist[0]->vertices.skeleton = 0;
  1153.    }
  1154.  
  1155.  // read vertices
  1156.  uint32 max_bone_index = 0;
  1157.  for(size_t i = 0; i < n_vertices; i++)
  1158.     {
  1159.      // 0x1D02AF
  1160.      // 0x0C (12 bytes)
  1161.      // OK
  1162.      if(head02 == 0x1D01AF)
  1163.        {
  1164.         float v01 = BE_read_float32(ifile); //  4
  1165.         float v02 = BE_read_float32(ifile); //  8
  1166.         float v03 = BE_read_float32(ifile); // 12
  1167.         if(debug) dfile << v01 << endl;
  1168.         if(debug) dfile << v02 << endl;
  1169.         if(debug) dfile << v03 << endl;
  1170.         if(debug) dfile << endl;
  1171.         geometry.meshlist[0]->vertices.data[i].vx =  v01;
  1172.         geometry.meshlist[0]->vertices.data[i].vy =  v02;
  1173.         geometry.meshlist[0]->vertices.data[i].vz =  v03;
  1174.         geometry.meshlist[0]->vertices.data[i].tu = 0.0f;
  1175.         geometry.meshlist[0]->vertices.data[i].tv = 0.0f;
  1176.        }
  1177.      // 0x1D01BF
  1178.      // 0x0C (12 bytes)
  1179.      // OK
  1180.      if(head02 == 0x1D01BF)
  1181.        {
  1182.         float v01 = BE_read_float32(ifile); //  4
  1183.         float v02 = BE_read_float32(ifile); //  8
  1184.         float v03 = BE_read_float32(ifile); // 12
  1185.         if(debug) dfile << v01 << endl;
  1186.         if(debug) dfile << v02 << endl;
  1187.         if(debug) dfile << v03 << endl;
  1188.         if(debug) dfile << endl;
  1189.         geometry.meshlist[0]->vertices.data[i].vx =  v01;
  1190.         geometry.meshlist[0]->vertices.data[i].vy =  v02;
  1191.         geometry.meshlist[0]->vertices.data[i].vz =  v03;
  1192.         geometry.meshlist[0]->vertices.data[i].tu = 0.0f;
  1193.         geometry.meshlist[0]->vertices.data[i].tv = 0.0f;
  1194.        }
  1195.      // 0x1D02BF
  1196.      // 0x0C (12 bytes)
  1197.      // OK
  1198.      else if(head02 == 0x1D02BF)
  1199.        {
  1200.         float v01 = BE_read_float32(ifile); //  4
  1201.         float v02 = BE_read_float32(ifile); //  8
  1202.         float v03 = BE_read_float32(ifile); // 12
  1203.         if(debug) dfile << v01 << endl;
  1204.         if(debug) dfile << v02 << endl;
  1205.         if(debug) dfile << v03 << endl;
  1206.         if(debug) dfile << endl;
  1207.         geometry.meshlist[0]->vertices.data[i].vx =  v01;
  1208.         geometry.meshlist[0]->vertices.data[i].vy =  v02;
  1209.         geometry.meshlist[0]->vertices.data[i].vz =  v03;
  1210.         geometry.meshlist[0]->vertices.data[i].tu = 0.0f;
  1211.         geometry.meshlist[0]->vertices.data[i].tv = 0.0f;
  1212.        }
  1213.      // 0x1D80A7
  1214.      // 0x18 (24 bytes)
  1215.      // OK
  1216.      else if(head02 == 0x1D80A7)
  1217.        {
  1218.         auto v01 = BE_read_float32(ifile); //  4
  1219.         auto v02 = BE_read_float32(ifile); //  8
  1220.         auto v03 = BE_read_float32(ifile); // 12
  1221.         auto v04 = BE_read_sint16(ifile);  // 14
  1222.         auto v05 = BE_read_sint16(ifile);  // 16
  1223.         auto v06 = BE_read_sint16(ifile);  // 18
  1224.         auto v07 = BE_read_sint16(ifile);  // 20
  1225.         auto v08 = BE_read_uint32(ifile);  // 24
  1226.         if(debug) dfile << v01 << endl;
  1227.         if(debug) dfile << v02 << endl;
  1228.         if(debug) dfile << v03 << endl;
  1229.         if(debug) dfile << v04 << endl;
  1230.         if(debug) dfile << v05 << endl;
  1231.         if(debug) dfile << v06 << endl;
  1232.         if(debug) dfile << v07 << endl;
  1233.         if(debug) dfile << v08 << endl;
  1234.         if(debug) dfile << endl;
  1235.         geometry.meshlist[0]->vertices.data[i].vx =  v01;
  1236.         geometry.meshlist[0]->vertices.data[i].vy =  v02;
  1237.         geometry.meshlist[0]->vertices.data[i].vz =  v03;
  1238.         geometry.meshlist[0]->vertices.data[i].tu =  v06/1023.0f;
  1239.         geometry.meshlist[0]->vertices.data[i].tv = -v07/1023.0f;
  1240.        }
  1241.      // 0x1D80A7
  1242.      // 0x18 (24 bytes)
  1243.      // OK
  1244.      else if(head02 == 0x1D81A7)
  1245.        {
  1246.         auto v01 = BE_read_float32(ifile); //  4
  1247.         auto v02 = BE_read_float32(ifile); //  8
  1248.         auto v03 = BE_read_float32(ifile); // 12
  1249.         auto v04 = BE_read_sint16(ifile);  // 14
  1250.         auto v05 = BE_read_sint16(ifile);  // 16
  1251.         auto v06 = BE_read_sint16(ifile);  // 18
  1252.         auto v07 = BE_read_sint16(ifile);  // 20
  1253.         auto v08 = BE_read_uint32(ifile);  // 24
  1254.         if(debug) dfile << v01 << endl;
  1255.         if(debug) dfile << v02 << endl;
  1256.         if(debug) dfile << v03 << endl;
  1257.         if(debug) dfile << v04 << endl;
  1258.         if(debug) dfile << v05 << endl;
  1259.         if(debug) dfile << v06 << endl;
  1260.         if(debug) dfile << v07 << endl;
  1261.         if(debug) dfile << v08 << endl;
  1262.         if(debug) dfile << endl;
  1263.         geometry.meshlist[0]->vertices.data[i].vx =  v01;
  1264.         geometry.meshlist[0]->vertices.data[i].vy =  v02;
  1265.         geometry.meshlist[0]->vertices.data[i].vz = -v03;
  1266.         geometry.meshlist[0]->vertices.data[i].tu =  v06/1023.0f;
  1267.         geometry.meshlist[0]->vertices.data[i].tv = -v07/1023.0f;
  1268.        }
  1269.      // 0x1D80AF
  1270.      // 0x1C (28 bytes)
  1271.      // OK
  1272.      else if(head02 == 0x1D80AF)
  1273.        {
  1274.         auto v01 = BE_read_float32(ifile); //  4
  1275.         auto v02 = BE_read_float32(ifile); //  8
  1276.         auto v03 = BE_read_float32(ifile); // 12
  1277.         auto v04 = BE_read_sint16(ifile);  // 14
  1278.         auto v05 = BE_read_sint16(ifile);  // 16
  1279.         auto v06 = BE_read_sint16(ifile);  // 18
  1280.         auto v07 = BE_read_sint16(ifile);  // 20
  1281.         auto v08 = BE_read_uint32(ifile);  // 24
  1282.         auto v09 = BE_read_uint32(ifile);  // 28
  1283.         if(debug) dfile << v01 << endl;
  1284.         if(debug) dfile << v02 << endl;
  1285.         if(debug) dfile << v03 << endl;
  1286.         if(debug) dfile << v04 << endl;
  1287.         if(debug) dfile << v05 << endl;
  1288.         if(debug) dfile << v06 << endl;
  1289.         if(debug) dfile << v07 << endl;
  1290.         if(debug) dfile << v08 << endl;
  1291.         if(debug) dfile << v09 << endl;
  1292.         if(debug) dfile << endl;
  1293.         geometry.meshlist[0]->vertices.data[i].vx =  v01;
  1294.         geometry.meshlist[0]->vertices.data[i].vy =  v02;
  1295.         geometry.meshlist[0]->vertices.data[i].vz =  v03;
  1296.         geometry.meshlist[0]->vertices.data[i].tu =  v06/1023.0f;
  1297.         geometry.meshlist[0]->vertices.data[i].tv = -v07/1023.0f;
  1298.        }
  1299.      // 0x1D81AF
  1300.      // 0x1C (28 bytes)
  1301.      // OK
  1302.      else if(head02 == 0x1D81AF)
  1303.        {
  1304.         auto v01 = BE_read_float32(ifile); //  4
  1305.         auto v02 = BE_read_float32(ifile); //  8
  1306.         auto v03 = BE_read_float32(ifile); // 12
  1307.         auto v04 = BE_read_sint16(ifile);  // 14
  1308.         auto v05 = BE_read_sint16(ifile);  // 16
  1309.         auto v06 = BE_read_sint16(ifile);  // 18
  1310.         auto v07 = BE_read_sint16(ifile);  // 20
  1311.         auto v08 = BE_read_uint32(ifile);  // 24
  1312.         auto v09 = BE_read_uint32(ifile);  // 28
  1313.         if(debug) dfile << v01 << endl;
  1314.         if(debug) dfile << v02 << endl;
  1315.         if(debug) dfile << v03 << endl;
  1316.         if(debug) dfile << v04 << endl;
  1317.         if(debug) dfile << v05 << endl;
  1318.         if(debug) dfile << v06 << endl;
  1319.         if(debug) dfile << v07 << endl;
  1320.         if(debug) dfile << v08 << endl;
  1321.         if(debug) dfile << v09 << endl;
  1322.         if(debug) dfile << endl;
  1323.         geometry.meshlist[0]->vertices.data[i].vx =  v01;
  1324.         geometry.meshlist[0]->vertices.data[i].vy =  v02;
  1325.         geometry.meshlist[0]->vertices.data[i].vz =  v03;
  1326.         geometry.meshlist[0]->vertices.data[i].tu =  v06/1023.0f;
  1327.         geometry.meshlist[0]->vertices.data[i].tv = -v07/1023.0f;
  1328.        }
  1329.      // 0x1D82A7
  1330.      // 0x18 (24 bytes)
  1331.      // OK
  1332.      else if(head02 == 0x1D82A7)
  1333.        {
  1334.         auto v01 = BE_read_float32(ifile); //  4
  1335.         auto v02 = BE_read_float32(ifile); //  8
  1336.         auto v03 = BE_read_float32(ifile); // 12
  1337.         auto v04 = BE_read_sint16(ifile);  // 14
  1338.         auto v05 = BE_read_sint16(ifile);  // 16
  1339.         auto v06 = BE_read_sint16(ifile);  // 18
  1340.         auto v07 = BE_read_sint16(ifile);  // 20
  1341.         auto v08 = BE_read_uint32(ifile);  // 24
  1342.         if(debug) dfile << v01 << endl;
  1343.         if(debug) dfile << v02 << endl;
  1344.         if(debug) dfile << v03 << endl;
  1345.         if(debug) dfile << v04 << endl;
  1346.         if(debug) dfile << v05 << endl;
  1347.         if(debug) dfile << v06 << endl;
  1348.         if(debug) dfile << v07 << endl;
  1349.         if(debug) dfile << v08 << endl;
  1350.         if(debug) dfile << endl;
  1351.         geometry.meshlist[0]->vertices.data[i].vx =  v01;
  1352.         geometry.meshlist[0]->vertices.data[i].vy =  v02;
  1353.         geometry.meshlist[0]->vertices.data[i].vz =  v03;
  1354.         geometry.meshlist[0]->vertices.data[i].tu =  v06/1023.0f;
  1355.         geometry.meshlist[0]->vertices.data[i].tv = -v07/1023.0f;
  1356.        }
  1357.      // 0x1D82AF
  1358.      // 0x1C (28 bytes)
  1359.      // OK
  1360.      else if(head02 == 0x1D82AF)
  1361.        {
  1362.         auto v01 = BE_read_float32(ifile); //  4
  1363.         auto v02 = BE_read_float32(ifile); //  8
  1364.         auto v03 = BE_read_float32(ifile); // 12
  1365.         auto v04 = BE_read_sint16(ifile);  // 14
  1366.         auto v05 = BE_read_sint16(ifile);  // 16
  1367.         auto v06 = BE_read_sint16(ifile);  // 18
  1368.         auto v07 = BE_read_sint16(ifile);  // 20
  1369.         auto v08 = BE_read_uint32(ifile);  // 24
  1370.         auto v09 = BE_read_uint32(ifile);  // 28
  1371.         if(debug) dfile << v01 << endl;
  1372.         if(debug) dfile << v02 << endl;
  1373.         if(debug) dfile << v03 << endl;
  1374.         if(debug) dfile << v04 << endl;
  1375.         if(debug) dfile << v05 << endl;
  1376.         if(debug) dfile << v06 << endl;
  1377.         if(debug) dfile << v07 << endl;
  1378.         if(debug) dfile << v08 << endl;
  1379.         if(debug) dfile << v09 << endl;
  1380.         if(debug) dfile << endl;
  1381.         geometry.meshlist[0]->vertices.data[i].vx =  v01;
  1382.         geometry.meshlist[0]->vertices.data[i].vy =  v02;
  1383.         geometry.meshlist[0]->vertices.data[i].vz =  v03;
  1384.         geometry.meshlist[0]->vertices.data[i].tu =  v06/1023.0f;
  1385.         geometry.meshlist[0]->vertices.data[i].tv = -v07/1023.0f;
  1386.        }
  1387.      // 0x1DB8A7
  1388.      // 0x20 (32 bytes)
  1389.      // OK
  1390.      else if(head02 == 0x1DB8A7)
  1391.        {
  1392.         auto v01 = BE_read_float32(ifile); //  4
  1393.         auto v02 = BE_read_float32(ifile); //  8
  1394.         auto v03 = BE_read_float32(ifile); // 12
  1395.         auto v04 = BE_read_sint16(ifile);  // 14
  1396.         auto v05 = BE_read_sint16(ifile);  // 16
  1397.         auto v06 = BE_read_sint16(ifile);  // 18
  1398.         auto v07 = BE_read_sint16(ifile);  // 20
  1399.         auto v08 = BE_read_uint32(ifile);  // 24
  1400.         auto v09 = BE_read_uint16(ifile);  // 26
  1401.         auto v10 = BE_read_uint16(ifile);  // 28
  1402.         auto v11 = BE_read_uint16(ifile);  // 30
  1403.         auto v12 = BE_read_uint16(ifile);  // 32
  1404.         if(debug) dfile << v01 << endl;
  1405.         if(debug) dfile << v02 << endl;
  1406.         if(debug) dfile << v03 << endl;
  1407.         if(debug) dfile << v04 << endl;
  1408.         if(debug) dfile << v05 << endl;
  1409.         if(debug) dfile << v06 << endl;
  1410.         if(debug) dfile << v07 << endl;
  1411.         if(debug) dfile << v08 << endl;
  1412.         if(debug) dfile << v09 << endl;
  1413.         if(debug) dfile << v10 << endl;
  1414.         if(debug) dfile << v11 << endl;
  1415.         if(debug) dfile << v12 << endl;
  1416.         if(debug) dfile << endl;
  1417.         geometry.meshlist[0]->vertices.data[i].vx =  v01;
  1418.         geometry.meshlist[0]->vertices.data[i].vy =  v02;
  1419.         geometry.meshlist[0]->vertices.data[i].vz =  v03;
  1420.         geometry.meshlist[0]->vertices.data[i].tu =  v06/1023.0f;
  1421.         geometry.meshlist[0]->vertices.data[i].tv = -v07/1023.0f;
  1422.        }
  1423.      // 0x1DB8AF
  1424.      // 0x24 (36 bytes)
  1425.      // OK
  1426.      else if(head02 == 0x1DB8AF)
  1427.        {
  1428.         auto v01 = BE_read_float32(ifile); //  4
  1429.         auto v02 = BE_read_float32(ifile); //  8
  1430.         auto v03 = BE_read_float32(ifile); // 12
  1431.         auto v04 = BE_read_sint16(ifile);  // 14
  1432.         auto v05 = BE_read_sint16(ifile);  // 16
  1433.         auto v06 = BE_read_sint16(ifile);  // 18
  1434.         auto v07 = BE_read_sint16(ifile);  // 20
  1435.         auto v08 = BE_read_uint16(ifile);  // 22
  1436.         auto v09 = BE_read_uint16(ifile);  // 24
  1437.         auto v10 = BE_read_uint32(ifile);  // 28
  1438.         auto v11 = BE_read_uint32(ifile);  // 32
  1439.         auto v12 = BE_read_uint32(ifile);  // 36
  1440.         if(debug) dfile << v01 << endl;
  1441.         if(debug) dfile << v02 << endl;
  1442.         if(debug) dfile << v03 << endl;
  1443.         if(debug) dfile << v04 << endl;
  1444.         if(debug) dfile << v05 << endl;
  1445.         if(debug) dfile << v06 << endl;
  1446.         if(debug) dfile << v07 << endl;
  1447.         if(debug) dfile << v08 << endl;
  1448.         if(debug) dfile << v09 << endl;
  1449.         if(debug) dfile << v10 << endl;
  1450.         if(debug) dfile << v11 << endl;
  1451.         if(debug) dfile << v12 << endl;
  1452.         if(debug) dfile << endl;
  1453.         geometry.meshlist[0]->vertices.data[i].vx =  v01;
  1454.         geometry.meshlist[0]->vertices.data[i].vy =  v02;
  1455.         geometry.meshlist[0]->vertices.data[i].vz =  v03;
  1456.         geometry.meshlist[0]->vertices.data[i].tu =  v06/1023.0f;
  1457.         geometry.meshlist[0]->vertices.data[i].tv = -v07/1023.0f;
  1458.        }
  1459.      // 0x1DB9A7
  1460.      // 0x20 (32 bytes)
  1461.      // OK
  1462.      else if(head02 == 0x1DB9A7)
  1463.        {
  1464.         auto v01 = BE_read_float32(ifile); //  4
  1465.         auto v02 = BE_read_float32(ifile); //  8
  1466.         auto v03 = BE_read_float32(ifile); // 12
  1467.         auto v04 = BE_read_uint08(ifile);  // 14
  1468.         auto v05 = BE_read_uint08(ifile);  // 15
  1469.         auto v06 = BE_read_uint08(ifile);  // 16
  1470.         auto v07 = BE_read_uint08(ifile);  // 17
  1471.         auto v08 = BE_read_sint16(ifile);  // 18
  1472.         auto v09 = BE_read_sint16(ifile);  // 20
  1473.         auto v10 = BE_read_uint32(ifile);  // 24
  1474.         auto v11 = BE_read_uint08(ifile);  // 25
  1475.         auto v12 = BE_read_uint08(ifile);  // 26
  1476.         auto v13 = BE_read_uint08(ifile);  // 27
  1477.         auto v14 = BE_read_uint08(ifile);  // 28
  1478.         auto v15 = BE_read_uint08(ifile);  // 29
  1479.         auto v16 = BE_read_uint08(ifile);  // 30
  1480.         auto v17 = BE_read_uint08(ifile);  // 31
  1481.         auto v18 = BE_read_uint08(ifile);  // 32
  1482.         if(debug) dfile << "vertex " << i << endl;
  1483.         if(debug) dfile << v01 << endl;
  1484.         if(debug) dfile << v02 << endl;
  1485.         if(debug) dfile << v03 << endl;
  1486.         if(debug) dfile << (uint16)v04 << endl;
  1487.         if(debug) dfile << (uint16)v05 << endl;
  1488.         if(debug) dfile << (uint16)v06 << endl;
  1489.         if(debug) dfile << (uint16)v07 << endl;
  1490.         if(debug) dfile << v08 << endl;
  1491.         if(debug) dfile << v09 << endl;
  1492.         if(debug) dfile << v10 << endl;
  1493.         if(debug) dfile << (uint16)v11 << endl;
  1494.         if(debug) dfile << (uint16)v12 << endl;
  1495.         if(debug) dfile << (uint16)v13 << endl;
  1496.         if(debug) dfile << (uint16)v14 << endl;
  1497.         if(debug) dfile << (uint16)v15 << endl;
  1498.         if(debug) dfile << (uint16)v16 << endl;
  1499.         if(debug) dfile << (uint16)v17 << endl;
  1500.         if(debug) dfile << (uint16)v18 << endl;
  1501.         if(debug) dfile << endl;
  1502.         geometry.meshlist[0]->vertices.data[i].vx =  v01;
  1503.         geometry.meshlist[0]->vertices.data[i].vy =  v02;
  1504.         geometry.meshlist[0]->vertices.data[i].vz =  v03;
  1505.         geometry.meshlist[0]->vertices.data[i].tu =  v08/1023.0f;
  1506.         geometry.meshlist[0]->vertices.data[i].tv = -v09/1023.0f;
  1507.         geometry.meshlist[0]->vertices.data[i].w1 = v11/255.0f;
  1508.         geometry.meshlist[0]->vertices.data[i].w2 = v12/255.0f;
  1509.         geometry.meshlist[0]->vertices.data[i].w3 = v13/255.0f;
  1510.         geometry.meshlist[0]->vertices.data[i].w4 = v14/255.0f;
  1511.         geometry.meshlist[0]->vertices.data[i].b1 = v15;
  1512.         geometry.meshlist[0]->vertices.data[i].b2 = v16;
  1513.         geometry.meshlist[0]->vertices.data[i].b3 = v17;
  1514.         geometry.meshlist[0]->vertices.data[i].b4 = v18;
  1515.  
  1516.         //if(v11 > max_bone_index) max_bone_index = v11; // max is 255
  1517.         //if(v12 > max_bone_index) max_bone_index = v12; // max is 127
  1518.         //if(v13 > max_bone_index) max_bone_index = v13; // max is 81
  1519.         //if(v14 > max_bone_index) max_bone_index = v14; // max is 9
  1520.  
  1521.         //if(v15 > max_bone_index) max_bone_index = v15; // max is 31
  1522.         //if(v16 > max_bone_index) max_bone_index = v16; // max is 31
  1523.         //if(v17 > max_bone_index) max_bone_index = v17; // max is 
  1524.         //if(v18 > max_bone_index) max_bone_index = v18; // max is 
  1525.        }
  1526.     }
  1527.  if(debug) dfile << endl;
  1528.  //cout << "Max bone index = " << max_bone_index << endl;
  1529.  
  1530.  //
  1531.  // PROCESS #10
  1532.  // READ SEPARATE UV DATA
  1533.  //
  1534.  
  1535.  // move to offset
  1536.  if(debug) dfile << "SEPARATE UV DATA" << endl;
  1537.  ifile.seekg(fileinfo[17]);
  1538.  if(ifile.fail()) return error("Seek failure.");
  1539.  if(head02 == 0x1D01AF || head02 == 0x1D01BF || head02 == 0x1D02BF) {
  1540.     for(size_t i = 0; i < n_vertices; i++) {
  1541.         auto v1 = BE_read_sint16(ifile);
  1542.         auto v2 = BE_read_sint16(ifile);
  1543.         if(debug) dfile << "v1 = " << v1 << endl;
  1544.         if(debug) dfile << "v2 = " << v2 << endl;
  1545.         geometry.meshlist[0]->vertices.data[i].tu =  v1/1023.0f;
  1546.         geometry.meshlist[0]->vertices.data[i].tv = -v2/1023.0f;
  1547.        }
  1548.    }
  1549.  if(debug) dfile << endl;
  1550.  
  1551.  //
  1552.  // PROCESS #11
  1553.  // READ BONE MATRICES
  1554.  //
  1555.  
  1556.  // process bones
  1557.  if(fileinfo[23])
  1558.    {
  1559.     // move to bone matrices
  1560.     if(debug) dfile << "BONE MATRICES" << endl;
  1561.     ifile.seekg(fileinfo[23]);
  1562.     if(ifile.fail()) return error("Seek failure.");
  1563.  
  1564.     // data to save
  1565.     deque<boost::shared_array<float>> mlist;
  1566.     JOINTTREE jtree;
  1567.  
  1568.     // read matrices
  1569.     uint32 n_bones = fileinfo[24];
  1570.     if(debug) dfile << "number of bones = " << n_bones << endl;
  1571.     for(size_t i = 0; i < n_bones; i++) {
  1572.         boost::shared_array<float> m(new float[16]);
  1573.         m[ 0] = BE_read_float32(ifile);
  1574.         m[ 1] = BE_read_float32(ifile);
  1575.         m[ 2] = BE_read_float32(ifile);
  1576.         m[ 3] = BE_read_float32(ifile);
  1577.         m[ 4] = BE_read_float32(ifile);
  1578.         m[ 5] = BE_read_float32(ifile);
  1579.         m[ 6] = BE_read_float32(ifile);
  1580.         m[ 7] = BE_read_float32(ifile);
  1581.         m[ 8] = BE_read_float32(ifile);
  1582.         m[ 9] = BE_read_float32(ifile);
  1583.         m[10] = BE_read_float32(ifile);
  1584.         m[11] = BE_read_float32(ifile);
  1585.         m[12] = BE_read_float32(ifile);
  1586.         m[13] = BE_read_float32(ifile);
  1587.         m[14] = BE_read_float32(ifile);
  1588.         m[15] = BE_read_float32(ifile);
  1589.         mlist.push_back(m);
  1590.         if(debug) dfile << m[ 0] << " " << m[ 1] << " " << m[ 2] << " " << m[ 3] << endl;
  1591.         if(debug) dfile << m[ 4] << " " << m[ 5] << " " << m[ 6] << " " << m[ 7] << endl;
  1592.         if(debug) dfile << m[ 8] << " " << m[ 9] << " " << m[10] << " " << m[11] << endl;
  1593.         if(debug) dfile << m[12] << " " << m[13] << " " << m[14] << " " << m[15] << endl;
  1594.         if(debug) dfile << endl;
  1595.        }
  1596.  
  1597.     // move to bone information
  1598.     if(debug) dfile << "BONES" << endl;
  1599.     ifile.seekg(fileinfo[25]);
  1600.     if(ifile.fail()) return error("Seek failure.");
  1601.     if(n_bones != fileinfo[26]) return error("Number of joints do not match.");
  1602.  
  1603.     // read bone information
  1604.     for(size_t i = 0; i < n_bones; i++)
  1605.        {
  1606.         // joint
  1607.         JOINT joint;
  1608.         uint32 index = (uint32)i;
  1609.    
  1610.         // joint name
  1611.         char name[5];
  1612.         ifile.read(&name[0], 4);
  1613.         std::reverse(&name[0], &name[4]);
  1614.         name[4] = '\0';
  1615.         joint.name = name;
  1616.    
  1617.         // joint matrix
  1618.         joint.matrix = mlist[i];
  1619.  
  1620.         // joint relative positions
  1621.         float x = BE_read_float32(ifile);
  1622.         float y = BE_read_float32(ifile);
  1623.         float z = BE_read_float32(ifile);
  1624.         joint.rel_x = x;
  1625.         joint.rel_y = y;
  1626.         joint.rel_z = z;
  1627.  
  1628.         // set parent
  1629.         uint32 parent = BE_read_uint32(ifile);
  1630.         uint32 xxxxxx = BE_read_uint32(ifile);
  1631.         joint.parent = parent;
  1632.    
  1633.         // insert joint
  1634.         jtree.InsertJoint(index, joint);
  1635.  
  1636.         if(debug) dfile << "index = " << index << endl;   
  1637.         if(debug) dfile << "name = " << name << endl;   
  1638.         if(debug) dfile << "x = " << x << endl;
  1639.         if(debug) dfile << "y = " << y << endl;
  1640.         if(debug) dfile << "z = " << z << endl;
  1641.         if(debug) dfile << "parent = " << parent << endl;
  1642.         if(debug) dfile << "xxxxxx = " << xxxxxx << endl;
  1643.         if(debug) dfile << endl;
  1644.        }
  1645.  
  1646.     // print joint tree in debug mode
  1647.     if(debug) {
  1648.        stringstream ss;
  1649.        jtree.PrintJointTree(ss);
  1650.        dfile << ss.str() << endl;
  1651.       }
  1652.  
  1653.     // insert skeleton
  1654.     SKELETON skel = { "skeleton", jtree };
  1655.     skeletons.push_back(skel);
  1656.    }
  1657.  
  1658.  //
  1659.  // PROCESS #12
  1660.  // READ TEXTURES
  1661.  //
  1662.  
  1663.  if(fileinfo[27])
  1664.    {
  1665.     // move to texture information
  1666.     if(debug) dfile << "TEXTURES" << endl;
  1667.     ifile.seekg(fileinfo[27]);
  1668.     if(ifile.fail()) return error("Seek failure.");
  1669.    
  1670.     // read texture information
  1671.     uint32 n_textures = fileinfo[28];
  1672.     for(uint32 i = 0; i < n_textures; i++)
  1673.        {
  1674.         uint32 param1 = BE_read_uint32(ifile); // index
  1675.         uint32 param2 = BE_read_uint32(ifile); // 0
  1676.         uint16 param3 = BE_read_uint16(ifile); // 0x0001
  1677.         uint16 param4 = BE_read_uint16(ifile); // 0x0200 | 0x0400
  1678.         uint16 param5 = BE_read_uint16(ifile); // 0x0200 | 0x0400
  1679.         uint16 param6 = BE_read_uint16(ifile); // 0x2000 | 0xFF00
  1680.         if(debug) dfile << "param1 = " << param1 << endl;
  1681.         if(debug) dfile << "param2 = " << param2 << endl;
  1682.         if(debug) dfile << "param3 = " << param3 << endl;
  1683.         if(debug) dfile << "param4 = " << param4 << endl;
  1684.         if(debug) dfile << "param5 = " << param5 << endl;
  1685.         if(debug) dfile << "param6 = " << param6 << endl;
  1686.         if(debug) dfile << endl;
  1687.    
  1688.         // texture id
  1689.         stringstream id;
  1690.         id << "texture_" << setfill('0') << setw(3) << param1;
  1691.    
  1692.         // texture filename
  1693.         stringstream fn;
  1694.         fn << setfill('0') << setw(3) << param1 << ".dds.tga";
  1695.    
  1696.         // add texture
  1697.         TEXTURE item;
  1698.         item.id = id.str();
  1699.         item.filename = fn.str();
  1700.         textures.push_back(item);
  1701.        }
  1702.     if(debug) dfile << endl;
  1703.    }
  1704.  
  1705.  // replace texture names
  1706.  string texfile = GetTEXFromMDL(filename);
  1707.  if(texfile.length()) {
  1708.     deque<string> filelist;
  1709.     GetFilenamesFromTEX(texfile, filelist);
  1710.     if(filelist.size() == textures.size()) {
  1711.        for(size_t i = 0; i < textures.size(); i++) {
  1712.            string shortname = GetShortFilename(filelist[i]);
  1713.            textures[i].filename = shortname;
  1714.            textures[i].filename += ".tga";
  1715.           }
  1716.       }
  1717.     else {
  1718.        stringstream ss;
  1719.        ss << "The number of textures do not match. ";
  1720.        ss << "Expecting " << textures.size() << " but obtained " << filelist.size() << "."; 
  1721.        error(ss.str().c_str());
  1722.       }
  1723.    }
  1724.  
  1725.  // save geometry
  1726.  return GeometryToDAE(fn_path.c_str(), fn_name.c_str(), geometry, materials, textures, skeletons);
  1727. }
  1728.  
  1729. bool extractor::processTMO(const char* filename)
  1730. {
  1731.  ifstream ifile(filename, ios::binary);
  1732.  if(!ifile) return error("");
  1733.  
  1734.  uint32 head01 = BE_read_uint32(ifile);
  1735.  uint32 head02 = BE_read_uint32(ifile);
  1736.  uint32 head03 = BE_read_uint32(ifile);
  1737.  uint32 head04 = BE_read_uint32(ifile);
  1738.  uint32 head05 = BE_read_uint32(ifile);
  1739.  uint32 head06 = BE_read_uint32(ifile); // number of bones
  1740.  uint32 head07 = BE_read_uint32(ifile);
  1741.  uint32 head08 = BE_read_uint32(ifile); // number of bones
  1742.  uint32 head09 = BE_read_uint32(ifile);
  1743.  uint32 head10 = BE_read_uint32(ifile);
  1744.  uint32 head11 = BE_read_uint32(ifile);
  1745.  uint32 head12 = BE_read_uint32(ifile);
  1746.  uint32 head13 = BE_read_uint32(ifile);
  1747.  uint32 head14 = BE_read_uint32(ifile);
  1748.  uint32 head15 = BE_read_uint32(ifile);
  1749.  uint32 head16 = BE_read_uint32(ifile);
  1750.  cout << head01 << endl;
  1751.  cout << head02 << endl;
  1752.  cout << head03 << endl;
  1753.  cout << head04 << endl;
  1754.  cout << head05 << endl;
  1755.  cout << head06 << endl;
  1756.  cout << head07 << endl;
  1757.  cout << head08 << endl;
  1758.  cout << head09 << endl;
  1759.  cout << head10 << endl;
  1760.  cout << head11 << endl;
  1761.  cout << head12 << endl;
  1762.  cout << head13 << endl;
  1763.  cout << head14 << endl;
  1764.  cout << head15 << endl;
  1765.  cout << head16 << endl;
  1766.  
  1767.  // read bone information
  1768.  uint32 n_bones = head06;
  1769.  for(size_t i = 0; i < n_bones; i++)
  1770.     {
  1771.      // joint name
  1772.      char name[5];
  1773.      ifile.read(&name[0], 4);
  1774.      std::reverse(&name[0], &name[4]);
  1775.      name[4] = '\0';
  1776.  
  1777.      // joint relative positions
  1778.      float x = BE_read_float32(ifile);
  1779.      float y = BE_read_float32(ifile);
  1780.      float z = BE_read_float32(ifile);
  1781.  
  1782.      // set parent
  1783.      uint32 parent = BE_read_uint32(ifile);
  1784.      uint32 xxxxxx = BE_read_uint32(ifile);
  1785.  
  1786.      cout << "index = " << i << endl;   
  1787.      cout << "name = " << name << endl;   
  1788.      cout << "x = " << x << endl;
  1789.      cout << "y = " << y << endl;
  1790.      cout << "z = " << z << endl;
  1791.      cout << "parent = " << parent << endl;
  1792.      cout << "xxxxxx = " << xxxxxx << endl;
  1793.      cout << endl;
  1794.     }
  1795.  
  1796.  ifile.seekg(head05);
  1797.  uint16 sect01 = BE_read_uint16(ifile);
  1798.  uint16 sect02 = BE_read_uint16(ifile);
  1799.  uint32 sect03 = BE_read_uint32(ifile);
  1800.  uint32 sect04 = BE_read_uint32(ifile);
  1801.  uint32 sect05 = BE_read_uint32(ifile);
  1802.  cout << "sect01 = " << sect01 << endl;
  1803.  cout << "sect02 = " << sect02 << endl;
  1804.  cout << "sect03 = " << sect03 << endl;
  1805.  cout << "sect04 = " << sect04 << endl;
  1806.  cout << "sect05 = " << sect05 << endl;
  1807.  
  1808.  for(size_t i = 0; i < sect02; i++)
  1809.     {
  1810.      cout << "i = " << i << endl;
  1811.      for(size_t j = 0; j < 27; j++) {
  1812.          uint32 temp = BE_read_uint32(ifile);
  1813.          cout << temp << endl;
  1814.         }
  1815.      cout << endl;
  1816.     }
  1817.  
  1818.  ifile.seekg(head14);
  1819.  uint32 param1 = BE_read_uint32(ifile);
  1820.  uint32 param2 = BE_read_uint32(ifile);
  1821.  cout << "param1 = " << param1 << endl;
  1822.  cout << "param2 = " << param2 << endl;
  1823.  
  1824.  for(size_t i = 0; i < sect01; i++)
  1825.     {
  1826.      cout << "i = " << i << endl;
  1827.      auto p1 = BE_read_uint16(ifile);
  1828.      auto p2 = BE_read_uint16(ifile);
  1829.      auto p3 = BE_read_uint16(ifile);
  1830.      auto p4 = BE_read_uint16(ifile);
  1831.      cout << "p1 = " << p1 << endl;
  1832.      cout << "p2 = " << p2 << endl;
  1833.      cout << "p3 = " << p3 << endl;
  1834.      cout << "p4 = " << p4 << endl;
  1835.      cout << endl;
  1836.     }
  1837.  
  1838.  float fp01 = BE_read_float32(ifile);
  1839.  float fp02 = BE_read_float32(ifile);
  1840.  float fp03 = BE_read_float32(ifile);
  1841.  float fp04 = BE_read_float32(ifile);
  1842.  float fp05 = BE_read_float32(ifile);
  1843.  float fp06 = BE_read_float32(ifile);
  1844.  float fp07 = BE_read_float32(ifile);
  1845.  float fp08 = BE_read_float32(ifile);
  1846.  float fp09 = BE_read_float32(ifile);
  1847.  float fp10 = BE_read_float32(ifile);
  1848.  float fp11 = BE_read_float32(ifile);
  1849.  float fp12 = BE_read_float32(ifile);
  1850.  cout << "fp01 = " << fp01 << endl;
  1851.  cout << "fp02 = " << fp02 << endl;
  1852.  cout << "fp03 = " << fp03 << endl;
  1853.  cout << "fp04 = " << fp04 << endl;
  1854.  cout << "fp05 = " << fp05 << endl;
  1855.  cout << "fp06 = " << fp06 << endl;
  1856.  cout << "fp07 = " << fp07 << endl;
  1857.  cout << "fp08 = " << fp08 << endl;
  1858.  cout << "fp09 = " << fp09 << endl;
  1859.  cout << "fp10 = " << fp10 << endl;
  1860.  cout << "fp11 = " << fp11 << endl;
  1861.  cout << "fp12 = " << fp12 << endl;
  1862. /*
  1863.  for(;;)
  1864.     {
  1865.      for(size_t i = 0; i < sect01; i++)
  1866.         {
  1867.          cout << "i = " << i << endl;
  1868.          auto p1 = BE_read_uint16(ifile);
  1869.          auto p2 = BE_read_uint16(ifile);
  1870.          auto p3 = BE_read_uint16(ifile);
  1871.          auto p4 = BE_read_uint16(ifile);
  1872.          cout << "p1 = " << p1 << endl;
  1873.          cout << "p2 = " << p2 << endl;
  1874.          cout << "p3 = " << p3 << endl;
  1875.          cout << "p4 = " << p4 << endl;
  1876.          cout << endl;
  1877.         }
  1878.     }
  1879. */
  1880.  return true;
  1881. }
  1882.  
  1883. std::string GetTEXFromMDL(const std::string& filename)
  1884. {
  1885.  using namespace std;
  1886.  if(!filename.length()) return string();
  1887.  
  1888.  string path = GetPathnameFromFilename(filename);
  1889.  string name = GetShortFilenameWithoutExtension(filename);
  1890.  string name_with_ext = GetShortFilename(filename);
  1891.  
  1892.  // METHOD #1
  1893.  // SAME PATH - SAME NAME
  1894.  string test1 = path;
  1895.  test1 += name;
  1896.  test1 += ".tex";
  1897.  if(GetFileAttributesA(test1.c_str()) != INVALID_FILE_ATTRIBUTES) return test1;
  1898.  
  1899.  // METHOD #2
  1900.  // SAME PATH - DIFFERENT NAME
  1901.  if(name == "000" || name == "001" || name == "002" || name == "003" || name == "004") {
  1902.     string test0 = path; test0 += "000.tex";
  1903.     string test1 = path; test1 += "001.tex";
  1904.     string test2 = path; test2 += "002.tex";
  1905.     string test3 = path; test3 += "003.tex";
  1906.     string test4 = path; test4 += "004.tex";
  1907.     if(GetFileAttributesA(test0.c_str()) != INVALID_FILE_ATTRIBUTES) return test0;
  1908.     if(GetFileAttributesA(test1.c_str()) != INVALID_FILE_ATTRIBUTES) return test1;
  1909.     if(GetFileAttributesA(test2.c_str()) != INVALID_FILE_ATTRIBUTES) return test2;
  1910.     if(GetFileAttributesA(test3.c_str()) != INVALID_FILE_ATTRIBUTES) return test3;
  1911.     if(GetFileAttributesA(test4.c_str()) != INVALID_FILE_ATTRIBUTES) return test4;
  1912.    } 
  1913.  
  1914.  // METHOD #3
  1915.  // REPLACE _mdl.mdl WITH _tex.tex
  1916.  size_t position = name_with_ext.find("_mdl.mdl");
  1917.  if(position != string::npos) {
  1918.     string test1 = path;
  1919.     string test2 = name_with_ext.replace(position, 8, "_tex.tex");
  1920.     test1 += test2;
  1921.     if(GetFileAttributesA(test1.c_str()) != INVALID_FILE_ATTRIBUTES) return test1;
  1922.    }
  1923.  
  1924.  // METHOD #4
  1925.  // REPLACE _mdl.mdl WITH _tex_color1.tex
  1926.  if(position != string::npos) {
  1927.     string test1 = path;
  1928.     string test2 = name_with_ext.substr(0, position);
  1929.     test1 += test2;
  1930.     test1 += "_tex_color1.tex";
  1931.     if(GetFileAttributesA(test1.c_str()) != INVALID_FILE_ATTRIBUTES) return test1;
  1932.    }
  1933.  
  1934.  // METHOD #5
  1935.  // REPLACE _mdl.mdl WITH _tex_democolor.tex
  1936.  if(position != string::npos) {
  1937.     string test1 = path;
  1938.     string test2 = name_with_ext.substr(0, position);
  1939.     test1 += test2;
  1940.     test1 += "_tex_democolor.tex";
  1941.     if(GetFileAttributesA(test1.c_str()) != INVALID_FILE_ATTRIBUTES) return test1;
  1942.    }
  1943.  
  1944.  // METHOD #6a
  1945.  // REPLACE EVERYTHING AFTER _tmd WITH _color1_xpr\\000\\xxx.tex
  1946.  position = path.find("_tmd\\000\\");
  1947.  if(position != string::npos) {
  1948.     string test1 = path.substr(0, position);
  1949.     test1 += "_color1_xpr\\000\\";
  1950.     if(name == "000") test1 += "000.tex";
  1951.     else if(name == "001") test1 += "001.tex";
  1952.     else if(name == "002") test1 += "002.tex";
  1953.     if(GetFileAttributesA(test1.c_str()) != INVALID_FILE_ATTRIBUTES) return test1;
  1954.    }
  1955.  
  1956.  // METHOD #6b
  1957.  // REPLACE EVERYTHING AFTER _tmd WITH _color1_xpr\\001\\xxx.tex
  1958.  position = path.find("_tmd\\001\\");
  1959.  if(position != string::npos) {
  1960.     string test1 = path.substr(0, position);
  1961.     test1 += "_color1_xpr\\001\\";
  1962.     if(name == "000") test1 += "000.tex";
  1963.     else if(name == "001") test1 += "001.tex";
  1964.     else if(name == "002") test1 += "002.tex";
  1965.     if(GetFileAttributesA(test1.c_str()) != INVALID_FILE_ATTRIBUTES) return test1;
  1966.    }
  1967.  
  1968.  // METHOD #6c
  1969.  // REPLACE EVERYTHING AFTER _tmd WITH _color1_xpr\\000\\xxx.tex
  1970.  position = path.find("_tmd\\");
  1971.  if(position != string::npos) {
  1972.     string test1 = path.substr(0, position);
  1973.     test1 += "_color1_xpr\\000\\";
  1974.     if(name == "000") test1 += "000.tex";
  1975.     else if(name == "001") test1 += "001.tex";
  1976.     else if(name == "002") test1 += "002.tex";
  1977.     if(GetFileAttributesA(test1.c_str()) != INVALID_FILE_ATTRIBUTES) return test1;
  1978.    }
  1979.  
  1980.  // METHOD #6d
  1981.  // REPLACE EVERYTHING AFTER _tmd WITH _color1_xpr\\000\\000.tex
  1982.  position = path.find("_tmd\\");
  1983.  if(position != string::npos) {
  1984.     string test1 = path.substr(0, position);
  1985.     test1 += "_color1_xpr\\000\\000.tex";
  1986.     if(GetFileAttributesA(test1.c_str()) != INVALID_FILE_ATTRIBUTES) return test1;
  1987.    }
  1988.  
  1989.  // METHOD #7
  1990.  // REPLACE SFX\\SFX\\XXX.MDL WITH SFX\\XXX.TEX
  1991.  position = path.find("sfx\\sfx\\");
  1992.  if(position != string::npos) {
  1993.     string test1 = path.substr(0, position);
  1994.     test1 += "sfx\\";
  1995.     test1 += name;
  1996.     test1 += ".tex";
  1997.     if(GetFileAttributesA(test1.c_str()) != INVALID_FILE_ATTRIBUTES) return test1;
  1998.    }
  1999.  
  2000.  // METHOD #8
  2001.  // REPLACE field\\fieldbg WITH field\\field_xbg
  2002.  position = path.find("field\\fieldbg");
  2003.  if(position != string::npos)
  2004.    {
  2005.     // build path part 1
  2006.     string test1 = path.substr(0, position);
  2007.     test1 += "field\\field_xbg";
  2008.  
  2009.     // build path part 2
  2010.     string test2 = path.substr(position + 13);
  2011.     size_t strip_position = test2.find("bf_fieldbg");
  2012.     if(strip_position != string::npos) {
  2013.        string test3 = test2.substr(0, strip_position);
  2014.        test1 += test3;
  2015.        if(name == "000") test1 += "000.tex";
  2016.        else if(name == "001") test1 += "001.tex";
  2017.        else if(name == "002") test1 += "002.tex";
  2018.        else if(name == "003") test1 += "003.tex";
  2019.        if(GetFileAttributesA(test1.c_str()) != INVALID_FILE_ATTRIBUTES) return test1;
  2020.       }
  2021.    }
  2022.  
  2023.  // METHOD #8
  2024.  // REPLACE field\\fieldbg WITH field\\field_xbg
  2025.  position = path.find("field\\fieldbg");
  2026.  if(position != string::npos)
  2027.    {
  2028.     // build path part 1
  2029.     string test1 = path.substr(0, position);
  2030.     test1 += "field\\field_xbg";
  2031.  
  2032.     // build path part 2
  2033.     string test2 = path.substr(position + 13);
  2034.     test1 += test2;
  2035.  
  2036.     // strip ending
  2037.     size_t strip_position = test1.find("_tmd\\");
  2038.     if(strip_position != string::npos) {
  2039.        string test3 = test1.substr(0, strip_position);
  2040.        test3 += "_xpr\\000.tex";
  2041.        if(GetFileAttributesA(test3.c_str()) != INVALID_FILE_ATTRIBUTES) return test3;
  2042.       }
  2043.    }
  2044.  
  2045.  return string();
  2046. }
  2047.  
  2048. bool GetFilenamesFromTEX(const std::string& texfile, std::deque<std::string>& filenames)
  2049. {
  2050.  // open texture file
  2051.  using namespace std;
  2052.  ifstream ifile(texfile, ios::binary);
  2053.  if(!ifile) return error("Failed to open TEX file; model will have to be manually textured.");
  2054.  
  2055.  // read number of textures
  2056.  ifile.seekg(0xC);
  2057.  if(ifile.fail()) return error("Seek failure; model will have to be manually textured.");
  2058.  
  2059.  // read number of textures
  2060.  uint32 n_textures = BE_read_uint32(ifile);
  2061.  if(ifile.fail()) return error("Read failure; model will have to be manually textured.");
  2062.  
  2063.  if(n_textures < 1 || n_textures > 1000)
  2064.     return error("Unexpected number of textures; model will have to be manually textured.");
  2065.  
  2066.  // move to filename offset
  2067.  ifile.seekg(16*n_textures + 20);
  2068.  if(ifile.fail()) return error("Seek failure; model will have to be manually textured.");
  2069.  
  2070.  // read filenames
  2071.  for(size_t i = 0; i < n_textures; i++) {
  2072.      char buffer[1024];
  2073.      read_string(ifile, buffer, 1024);
  2074.      if(ifile.fail()) return error("Read filename failure; model will have to be manually textured.");
  2075.      filenames.push_back(string(buffer));
  2076.     }
  2077.  
  2078.  if(filenames.size() == 0) return error("Filename search yielded no textures;  model will have to be manually textured.");
  2079.  return true;
  2080. }
  2081.  
  2082. };};
  2083.  
  2084. namespace XB360 { namespace Onechanbara2 {
  2085.  
  2086. bool extract(void)
  2087. {
  2088.  char pathname[MAX_PATH];
  2089.  GetModulePathname(pathname, MAX_PATH);
  2090.  return extract(pathname);
  2091. }
  2092.  
  2093. bool extract(const char* pathname)
  2094. {
  2095.  return extractor(pathname).extract();
  2096. }
  2097.  
  2098. };};