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

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