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

  1. #include "xentax.h"
  2. #include "x_file.h"
  3. #include "x_findfile.h"
  4. #include "x_dds.h"
  5. #include "x_smc.h"
  6. #include "x_lwo.h"
  7. #include "ps3_touchshot.h"
  8.  
  9. #define X_SYSTEM PS3
  10. #define X_GAME   TOUCHSHOT
  11.  
  12. namespace X_SYSTEM { namespace X_GAME {
  13.  
  14. class extractor {
  15.  private :
  16.   std::string pathname;
  17.  private :
  18.   bool processCAT(const std::string& filename);
  19.   bool processCAN(const std::string& filename);
  20.   bool processGTF(const std::string& filename);
  21.   bool processTMD(const std::string& filename);
  22.  public :
  23.   bool extract(void);
  24.  public :
  25.   extractor(const char* pn) : pathname(pn) {}
  26.  ~extractor() {}
  27. };
  28.  
  29. };};
  30.  
  31. namespace X_SYSTEM { namespace X_GAME {
  32.  
  33. bool extractor::extract(void)
  34. {
  35.  using namespace std;
  36.  bool doCAT = true;
  37.  bool doCAN = true;
  38.  bool doGTF = true;
  39.  bool doTMD = true;
  40.  
  41.  if(doCAT) {
  42.     cout << "STAGE 1" << std::endl;
  43.     cout << "Processing CAT files..." << std::endl;
  44.     deque<string> filelist;
  45.     BuildFilenameList(filelist, "cat", pathname.c_str());
  46.     for(size_t i = 0; i < filelist.size(); i++) {
  47.         std::cout << "Processing file " << (i + 1) << " of " << filelist.size() << ": " << filelist[i] << "." << std::endl;
  48.         if(!processCAT(filelist[i])) return false;
  49.        }
  50.     std::cout << std::endl;
  51.    }
  52.  
  53.  if(doCAN) {
  54.     cout << "STAGE 2" << std::endl;
  55.     cout << "Processing CAN files..." << std::endl;
  56.     deque<string> filelist;
  57.     BuildFilenameList(filelist, "can", pathname.c_str());
  58.     for(size_t i = 0; i < filelist.size(); i++) {
  59.         std::cout << "Processing file " << (i + 1) << " of " << filelist.size() << ": " << filelist[i] << "." << std::endl;
  60.         if(!processCAN(filelist[i])) return false;
  61.        }
  62.     std::cout << std::endl;
  63.    }
  64.  
  65.  if(doGTF) {
  66.     cout << "STAGE 3" << std::endl;
  67.     cout << "Processing GTF files..." << std::endl;
  68.     deque<string> filelist;
  69.     BuildFilenameList(filelist, "gtf", pathname.c_str());
  70.     for(size_t i = 0; i < filelist.size(); i++) {
  71.         std::cout << "Processing file " << (i + 1) << " of " << filelist.size() << ": " << filelist[i] << "." << std::endl;
  72.         if(!processGTF(filelist[i])) return false;
  73.        }
  74.     std::cout << std::endl;
  75.    }
  76.  
  77.  if(doTMD) {
  78.     cout << "STAGE 4" << std::endl;
  79.     cout << "Processing TMD files..." << std::endl;
  80.     deque<string> filelist;
  81.     BuildFilenameList(filelist, "tmd", pathname.c_str());
  82.     for(size_t i = 0; i < filelist.size(); i++) {
  83.         std::cout << "Processing file " << (i + 1) << " of " << filelist.size() << ": " << filelist[i] << "." << std::endl;
  84.         if(!processTMD(filelist[i])) return false;
  85.        }
  86.     std::cout << std::endl;
  87.    }
  88.  
  89.  return true;
  90. }
  91.  
  92. bool extractor::processCAT(const std::string& filename)
  93. {
  94.  // open file
  95.  using namespace std;
  96.  ifstream ifile(filename.c_str(), ios::binary);
  97.  if(!ifile) return error("error");
  98.  
  99.  // read header
  100.  std::deque<std::pair<size_t, size_t>> header;
  101.  for(;;) {
  102.      uint32 p01 = BE_read_uint32(ifile); if(ifile.fail()) return error("Read failure.");
  103.      uint32 p02 = BE_read_uint32(ifile); if(ifile.fail()) return error("Read failure.");
  104.      if(p01 == 0xFFFFFFFF && p02 == 0xFFFFFFFF) break;
  105.      if(header.size() > 1000) return error("Unexpected number of CAT sections.");
  106.      header.push_back(std::pair<size_t, size_t>(p01, p02));
  107.     }
  108.  
  109.  // create directory to store files
  110.  string pakpath = GetPathnameFromFilename(filename);
  111.  pakpath += GetShortFilenameWithoutExtension(filename);
  112.  pakpath += "\\";
  113.  CreateDirectoryA(pakpath.c_str(), NULL);
  114.  
  115.  // process files
  116.  for(size_t i = 0; i < header.size(); i++)
  117.     {
  118.      // move to data
  119.      ifile.seekg(header[i].first);
  120.      if(ifile.fail()) return error("Seek failure.");
  121.      if(header[i].second == 0) continue;
  122.  
  123.      // read data
  124.      boost::shared_array<char> data(new char[header[i].second]);
  125.      ifile.read(data.get(), header[i].second);
  126.      if(ifile.fail()) return error("Read failure.");
  127.  
  128.      // create filename
  129.      stringstream ss;
  130.      ss << pakpath << setfill('0') << setw(3) << i << ".";
  131.      uint32 value = *reinterpret_cast<uint32*>(data.get());
  132.      switch(value) {
  133.        case(0x746D6430) : ss << "tmd"; break;
  134.        case(0x746D6F30) : ss << "tmo"; break;
  135.        case(0xFF000202) : ss << "gtf"; break;
  136.        case(0xFF010102) : ss << "gtf"; break;
  137.        default : ss << "tmp";
  138.       }
  139.  
  140.      // save data
  141.      ofstream ofile(ss.str().c_str(), ios::binary);
  142.      ofile.write(data.get(), header[i].second);
  143.     }
  144.  
  145.  return true;
  146. }
  147.  
  148. bool extractor::processCAN(const std::string& filename)
  149. {
  150.  // open file
  151.  using namespace std;
  152.  ifstream ifile(filename.c_str(), ios::binary);
  153.  if(!ifile) return error("error");
  154.  
  155.  // filesize
  156.  ifile.seekg(0, ios::end);
  157.  size_t filesize = (size_t)ifile.tellg();
  158.  ifile.seekg(0, ios::beg);
  159.  
  160.  // read header
  161.  struct triple { size_t offset; size_t size; string name; };
  162.  std::deque<triple> header;
  163.  size_t position = 0;
  164.  for(;;)
  165.     {
  166.      // seek position
  167.      ifile.seekg(position);
  168.      if(ifile.fail()) return error("Seek failure.");
  169.  
  170.      // read item
  171.      uint32 p01 = BE_read_uint32(ifile); if(ifile.fail()) return error("Read failure.");
  172.      uint32 p02 = BE_read_uint32(ifile); if(ifile.fail()) return error("Read failure.");
  173.      if(p01 == 0xFFFFFFFF && p02 == 0xFFFFFFFF) break;
  174.  
  175.      // name follows
  176.      bool is_name = false;
  177.      uint32 namelen = 0;
  178.      if(p01 < p02) {
  179.         if((p02 - p01) == 0x10) { namelen = 0x10; is_name = true; }
  180.         else if((p02 - p01) == 0x20) { namelen = 0x20; is_name = true; }
  181.         else if((p02 - p01) == 0x30) { namelen = 0x30; is_name = true; }
  182.         else if(p02 == 0xFFFFFFFF) { namelen = filesize - p01; is_name = true; }
  183.        }
  184.  
  185.      // extract name
  186.      if(is_name) {
  187.         ifile.seekg(p01);
  188.         char buffer[1024];
  189.         read_string(ifile, buffer, 1024);
  190.         header.back().name = buffer;
  191.        }
  192.      else {
  193.         triple item;
  194.         item.offset = p01;
  195.         item.size = p02;
  196.         header.push_back(item);
  197.        }
  198.  
  199.      // move position
  200.      if(is_name) position += 4;
  201.      else position += 8;
  202.     }
  203.  
  204.  // create directory to store files
  205.  string sendpath = GetPathnameFromFilename(filename);
  206.  sendpath += GetShortFilenameWithoutExtension(filename);
  207.  sendpath += "\\";
  208.  CreateDirectoryA(sendpath.c_str(), NULL);
  209.  
  210.  // process files
  211.  for(size_t i = 0; i < header.size(); i++)
  212.     {
  213.      // move to data
  214.      ifile.seekg(header[i].offset);
  215.      if(ifile.fail()) return error("Seek failure.");
  216.      if(header[i].size == 0) continue;
  217.  
  218.      // read data
  219.      boost::shared_array<char> data(new char[header[i].size]);
  220.      ifile.read(data.get(), header[i].size);
  221.      if(ifile.fail()) return error("Read failure.");
  222.  
  223.      // create filename
  224.      stringstream ss;
  225.      if(header[i].name.length())
  226.         ss << sendpath << header[i].name;
  227.      else {
  228.         ss << sendpath << setfill('0') << setw(3) << i << ".";
  229.         uint32 value = *reinterpret_cast<uint32*>(data.get());
  230.         switch(value) {
  231.           case(0x746D6430) : ss << "tmd"; break;
  232.           case(0x746D6F30) : ss << "tmo"; break;
  233.           case(0xFF000202) : ss << "gtf"; break;
  234.           case(0xFF010102) : ss << "gtf"; break;
  235.           default : ss << "tmp";
  236.          }
  237.        }
  238.  
  239.      // save data
  240.      ofstream ofile(ss.str().c_str(), ios::binary);
  241.      ofile.write(data.get(), header[i].size);
  242.     }
  243.  
  244.  return true;
  245. }
  246.  
  247. bool extractor::processGTF(const std::string& filename)
  248. {
  249.  // open file
  250.  using namespace std;
  251.  ifstream ifile(filename.c_str(), ios::binary);
  252.  if(!ifile) return error("error");
  253.  
  254.  // filesize
  255.  ifile.seekg(0, ios::end);
  256.  size_t filesize = (size_t)ifile.tellg();
  257.  ifile.seekg(0, ios::beg);
  258.  
  259.  // 0x020101FF (magic)
  260.  // 0x000FD200 (filesize) 1036800
  261.  // 0x00000001 (number of files)
  262.  // 0x00000000
  263.  
  264.  // 0x020101FF
  265.  // 00000080 000FD200 A6-01-0200 0000AAE4 0780-0438 00010000 00000F00 00000000 00000000 (x*y/2 = filesize)
  266.  // usually x*y*4 = filesize
  267.  // so filesize is shrunk by 8!
  268.  // so instead of 32 bits per pixel this is 4 bits per pixel!
  269.  
  270.  // 0x020200FF
  271.  // 00000100 00080000 86-01-0200 0000AAE4 0400-0400 00010000 00000000 00000000 00000001
  272.  // 00080100 00010000 88-01-0200 0000AAE4 0100-0100 00010000 00000000 00000000 00000002
  273.  // 00090100 00000800 86-01-0200 0000AAE4 0040-0040 00010000 00000000 00000000 00000003
  274.  // 00090900 00100000 88-01-0200 0000AAE4 0400-0400 00010000 00000000 00000000 00000004
  275.  // 00190900 00008000 86-01-0200 0000AAE4 0100-0100 00010000 00000000 00000000 00000005
  276.  // 00198900 00000800 86-01-0200 0000AAE4 0040-0040 00010000 00000000 00000000 00000000
  277.  
  278.  struct GTFITEM {
  279.   uint32 offset;
  280.   uint32 filesize;
  281.   uint08 unk01;
  282.   uint08 unk02; // number of mipmap levels including top level
  283.   uint16 unk03;
  284.   uint32 unk04; // 0xAAE4
  285.   uint16 dx;
  286.   uint16 dy;
  287.   uint32 unk05; // 0x10000
  288.   uint32 unk06; // 0x00
  289.   uint32 unk07; // 0x00
  290.   uint32 index;
  291.  };
  292.  
  293.  // read header
  294.  uint32 magic = BE_read_uint32(ifile);
  295.  uint32 datasize = BE_read_uint32(ifile);
  296.  uint32 numfiles = BE_read_uint32(ifile);
  297.  BE_read_uint32(ifile);
  298.  
  299.  // read file information
  300.  deque<GTFITEM> gtflist;
  301.  for(uint32 i = 0; i < numfiles; i++) {
  302.      GTFITEM item = {
  303.       BE_read_uint32(ifile),
  304.       BE_read_uint32(ifile),
  305.       BE_read_uint08(ifile),
  306.       BE_read_uint08(ifile),
  307.       BE_read_uint16(ifile),
  308.       BE_read_uint32(ifile),
  309.       BE_read_uint16(ifile),
  310.       BE_read_uint16(ifile),
  311.       BE_read_uint32(ifile),
  312.       BE_read_uint32(ifile),
  313.       BE_read_uint32(ifile),
  314.       BE_read_uint32(ifile),
  315.      };
  316.      gtflist.push_back(item);
  317.     }
  318.  
  319.  // create directory to store files
  320.  string savepath = GetPathnameFromFilename(filename);
  321.  savepath += GetShortFilenameWithoutExtension(filename);
  322.  savepath += "\\";
  323.  CreateDirectoryA(savepath.c_str(), NULL);
  324.  
  325.  // read file
  326.  for(uint32 i = 0; i < numfiles; i++)
  327.     {
  328.      // compute bits per pixel
  329.      if(gtflist[i].dx == 0 || gtflist[i].dy == 0) return error("Invalid image dimensions.");
  330.      uint32 bpp = 8*gtflist[i].filesize/(gtflist[i].dx*gtflist[i].dy);
  331.  
  332.      // move to offset
  333.      ifile.seekg(gtflist[i].offset);
  334.      if(ifile.fail()) { error("Seek failure."); continue; }
  335.  
  336.      // read data
  337.      uint32 ofsize = gtflist[i].filesize;
  338.      boost::shared_array<char> ofdata(new char[ofsize]);
  339.      BE_read_array(ifile, ofdata.get(), ofsize);
  340.      if(ifile.fail()) { error("Read failure."); continue; }
  341.  
  342.      // DDS format
  343.      uint32 format = gtflist[i].unk01;
  344.      uint32 mipmap = gtflist[i].unk02 - 1;
  345.  
  346.      // create DDS header
  347.      DDS_HEADER ddsh;
  348.      if(format == 134 || format == 166) CreateDXT1Header(gtflist[i].dx, gtflist[i].dy, mipmap, FALSE, &ddsh);
  349.      else if(format == 135 || format == 136 || format == 168) CreateDXT5Header(gtflist[i].dx, gtflist[i].dy, mipmap, FALSE, &ddsh);
  350.      else if(format == 190) CreateUncompressedDDSHeader(gtflist[i].dx, gtflist[i].dy, 0, 0xFF00, 0xFF0000, 0xFF000000, 0xFF, FALSE, &ddsh);
  351.      else return error("Unknown DDS format.");
  352.  
  353.      // save data
  354.      stringstream ofname;
  355.      ofname << savepath << setfill('0') << setw(3) << i << ".dds";
  356.      SaveDDSFile(ofname.str().c_str(), ddsh, ofdata, ofsize);
  357.     }
  358.  
  359.  return true;
  360. }
  361.  
  362. bool extractor::processTMD(const std::string& filename)
  363. {
  364.  // open file
  365.  using namespace std;
  366.  ifstream ifile(filename.c_str(), ios::binary);
  367.  if(!ifile) return error("error");
  368.  
  369.  // filesize
  370.  ifile.seekg(0, ios::end);
  371.  size_t filesize = (size_t)ifile.tellg();
  372.  ifile.seekg(0, ios::beg);
  373.  
  374.  // variables
  375.  string fn_path = GetPathnameFromFilename(filename);
  376.  string fn_name = GetShortFilenameWithoutExtension(filename);
  377.  
  378.  // enable debug mode
  379.  bool debug = true;
  380.  ofstream dfile;
  381.  if(debug) {
  382.     stringstream ss;
  383.     ss << fn_path << fn_name << ".txt";
  384.     dfile.open(ss.str().c_str());
  385.    }
  386.  
  387.  //
  388.  // PROCESS #00
  389.  // INITIALIZE MODEL CONTAINER
  390.  //
  391.  
  392.  SIMPLEMODELCONTAINER smc;
  393.  smc.vbuffer.flags = 0;
  394.  smc.vbuffer.name = "mesh";
  395.  smc.vbuffer.elem = 0;
  396.  
  397.  //
  398.  // PROCESS #01
  399.  // READ AND PROCESS FILE HEADER
  400.  //
  401.  
  402.  // read header
  403.  auto head01 = BE_read_uint32(ifile);
  404.  auto head02 = BE_read_uint32(ifile);
  405.  auto head03 = BE_read_uint32(ifile);
  406.  auto head04 = BE_read_uint32(ifile);
  407.  auto head05 = BE_read_real32(ifile);
  408.  auto head06 = BE_read_real32(ifile);
  409.  auto head07 = BE_read_real32(ifile);
  410.  auto head08 = BE_read_real32(ifile);
  411.  auto head09 = BE_read_real32(ifile);
  412.  auto head10 = BE_read_real32(ifile);
  413.  if(debug) dfile << "HEADER" << endl;
  414.  if(debug) dfile << head01 << endl;
  415.  if(debug) dfile << head02 << endl;
  416.  if(debug) dfile << head03 << endl;
  417.  if(debug) dfile << head04 << endl;
  418.  if(debug) dfile << head05 << endl;
  419.  if(debug) dfile << head06 << endl;
  420.  if(debug) dfile << head07 << endl;
  421.  if(debug) dfile << head08 << endl;
  422.  if(debug) dfile << head09 << endl;
  423.  if(debug) dfile << head10 << endl;
  424.  if(debug) dfile << endl;
  425.  
  426.  // validate header
  427.  if(head01 != 0x30646D74) return error("Invalid MDL file.");
  428.  if(head04 != 0x28) return error("Invalid MDL file.");
  429.  
  430.  // determine vertex size
  431.  uint32 vertexsize = 0;
  432.  uint08 indextype = FACE_FORMAT_UINT_16;
  433.  uint08 indexsize = 2;
  434.  switch(head02) {
  435.    case(0x01A7) : vertexsize = 0x0C; cout << "0x01A7" << endl; break; // OK
  436.    case(0x0905) : vertexsize = 0x0C; cout << "0x0905" << endl; break; // OK
  437.    case(0x0925) : vertexsize = 0x0C; cout << "0x0925" << endl; break; // OK
  438.    case(0x09A3) : vertexsize = 0x0C; cout << "0x09A3" << endl; break; // OK
  439.    case(0x09A7) : vertexsize = 0x0C; cout << "0x09A7" << endl; break; // OK
  440.    case(0x09AF) : vertexsize = 0x0C; cout << "0x09AF" << endl; break; // OK
  441.    case(0x09BF) : vertexsize = 0x0C; cout << "0x09BF" << endl; break; // OK
  442.    case(0x09E7) : vertexsize = 0x20; cout << "0x09E7" << endl; break; // OK
  443.    default : {
  444.         stringstream msg;
  445.         msg << "Unknown vertex type " << head02 << ".";
  446.         return error(msg.str().c_str());
  447.        }
  448.   }
  449.  
  450.  //
  451.  // PROCESS #02
  452.  // READ AND SAVE FILE INFORMATION
  453.  //
  454.  
  455.  if(debug) dfile << "FILE INFORMATION" << std::endl;
  456.  uint32 fileinfo[30];
  457.  for(size_t i = 0; i < 30; i++) fileinfo[i] = BE_read_uint32(ifile);
  458.  if(debug) {
  459.     // 0x20
  460.     dfile << "offset to surface data: " << fileinfo[0] << endl;
  461.     dfile << "number of surface data items: " << fileinfo[1] << endl;
  462.     // 0x30
  463.     dfile << "offset to surface info : " << fileinfo[2] << endl;
  464.     dfile << "number of surface info items: " << fileinfo[3] << endl;
  465.     dfile << "always 0: " << fileinfo[4] << endl;
  466.     dfile << "always 0: " << fileinfo[5] << endl;
  467.     // 0x40
  468.     dfile << "offset to unknown surface info: " << fileinfo[6] << endl;
  469.     dfile << "number of unknown surface info items: " << fileinfo[7] << endl; // each item is 0x84 bytes
  470.     dfile << "offset to material info: " << fileinfo[8] << endl;
  471.     dfile << "number of material info items: " << fileinfo[9] << endl;
  472.     // 0x50
  473.     dfile << "offset to triangle group info: " << fileinfo[10] << endl;
  474.     dfile << "number of triangle group info items: " << fileinfo[11] << endl;
  475.     dfile << "offset to index buffer: " << fileinfo[12] << endl;
  476.     dfile << "number of triangles: " << fileinfo[13] << endl;
  477.     // 0x60
  478.     dfile << "number of vertices: " << fileinfo[14] << endl;
  479.     dfile << "offset to vertex buffer: " << fileinfo[15] << endl;
  480.     dfile << "offset to unknown data: " << fileinfo[16] << endl; // 0x01A7, 0x09A3, 0x09A7, 0x09AF, 0x09BF, 0x09E7
  481.     dfile << "offset to separate UV data: " << fileinfo[17] << endl; // 0x01A7, 0x0905, 0x0925, 0x09A7, 0x09AF, 0x09BF, 0x09E7
  482.     // 0x70
  483.     dfile << "offset to unknown data: " << fileinfo[18] << endl; // 0x09AF, 0x09BF 
  484.     dfile << "offset to unknown data: " << fileinfo[19] << endl; // 0x09BF
  485.     dfile << "offset to unknown data: " << fileinfo[20] << endl; // 0x01A7, 0x0925, 0x09A3, 0x09A7, 0x09AF, 0x09BF, 0x09E7
  486.     dfile << "offset to unknown data: " << fileinfo[21] << endl; // 0x0905, 0x0925, 0x09A3, 0x09A7, 0x09AF, 0x09BF, 0x09E7
  487.     // 0x80
  488.     dfile << "offset to unknown data: " << fileinfo[22] << endl; // 0x0905, 0x0925, 0x09A3, 0x09A7, 0x09AF, 0x09BF, 0x09E7
  489.     dfile << "offset to joint matrix: " << fileinfo[23] << endl;
  490.     dfile << "number of joint matrix items: " << fileinfo[24] << endl;
  491.     dfile << "offset to joint data: " << fileinfo[25] << endl;
  492.     // 0x90
  493.     dfile << "number of joint items: " << fileinfo[26] << endl;
  494.     dfile << "offset to texture data: " << fileinfo[27] << endl;
  495.     dfile << "number of texture items: " << fileinfo[28] << endl;
  496.     dfile << "always 0: " << fileinfo[29] << endl;
  497.     dfile << std::endl;
  498.    }
  499.  
  500.  //
  501.  // PROCESS #03
  502.  // READ SURFACE GROUP DATA
  503.  //
  504.  
  505.  struct SURFACEGROUP {
  506.   real32 bbox_xmin;
  507.   real32 bbox_ymin;
  508.   real32 bbox_zmin;
  509.   real32 bbox_xmax;
  510.   real32 bbox_ymax;
  511.   real32 bbox_zmax;
  512.   uint32 index; // 0, 6, 10, 14, 18, 22
  513.   uint16 elem;  // 6, 4,  4,  4,  4,  4 (22 + 4 = 26 texture associations)
  514.   uint16 type;  // 1, 1,  1,  1,  1,  1
  515.  };
  516.  deque<SURFACEGROUP> surface_data;
  517.  
  518.  // move to surface information
  519.  if(fileinfo[0])
  520.    {
  521.     if(debug) dfile << "SURFACE GROUPS" << endl;
  522.     ifile.seekg(fileinfo[0]);
  523.     if(ifile.fail()) return error("Seek failure.");
  524.  
  525.     // process surfaces
  526.     uint32 n_groups = fileinfo[1];
  527.     if(n_groups == 0 || n_groups > 1000) return error("Unexpected number of surfaces.");
  528.     if(debug) dfile << "Number of groups = " << n_groups << std::endl;
  529.  
  530.     // process surfaces
  531.     for(uint32 i = 0; i < n_groups; i++)
  532.        {
  533.         if(debug) dfile << "SURFACE GROUP " << i << endl;
  534.         auto param01 = BE_read_real32(ifile);
  535.         auto param02 = BE_read_real32(ifile);
  536.         auto param03 = BE_read_real32(ifile);
  537.         auto param04 = BE_read_real32(ifile);
  538.         auto param05 = BE_read_real32(ifile);
  539.         auto param06 = BE_read_real32(ifile);
  540.         if(debug) dfile << "box_min_x = " << param01 << endl;
  541.         if(debug) dfile << "box_min_y = " << param02 << endl;
  542.         if(debug) dfile << "box_min_z = " << param03 << endl;
  543.         if(debug) dfile << "box_max_x = " << param04 << endl;
  544.         if(debug) dfile << "box_max_y = " << param05 << endl;
  545.         if(debug) dfile << "box_max_z = " << param06 << endl;
  546.    
  547.         // read index
  548.         auto param07 = BE_read_uint32(ifile);
  549.         if(debug) dfile << "index = " << param07 << endl;
  550.    
  551.         // read other parameters
  552.         auto param08 = BE_read_uint16(ifile);
  553.         auto param09 = BE_read_uint16(ifile);
  554.         if(debug) dfile << "elem = " << param08 << endl;
  555.         if(debug) dfile << "type = " << param09 << endl;
  556.         if(debug) dfile << endl;
  557.  
  558.         // set surface information
  559.         SURFACEGROUP sg;
  560.         sg.bbox_xmin = param01;
  561.         sg.bbox_ymin = param02;
  562.         sg.bbox_zmin = param03;
  563.         sg.bbox_xmax = param04;
  564.         sg.bbox_ymax = param05;
  565.         sg.bbox_zmax = param06;
  566.         sg.index = param07;
  567.         sg.elem = param08;
  568.         sg.type = param09;
  569.         surface_data.push_back(sg);
  570.        }
  571.    }
  572.  
  573.  //
  574.  // PROCESS #04
  575.  // READ SURFACE-TEXTURE ASSOCIATION DATA
  576.  //
  577.  
  578.  struct TEXTASSINFO {
  579.   uint32 material_index;
  580.   uint32 trigroup_index;
  581.  };
  582.  deque<TEXTASSINFO> textass_data;
  583.  
  584.  // There are 6 section groups for this data
  585.  // There are 6 textures for this data.
  586.  // There are 3 materials for this data.
  587.  // There are 7 unknown surface information items for this data.
  588.  // There are 7 triangle groups for this data.
  589.  // 0x20XX is a material reference index.
  590.  // 0x30XX is a triangle group reference index.
  591.  // 0x40XX is a ??? reference index.
  592.  // 0x2000 0x4000 0x3000 0x4001 0x3001 0x1000
  593.  // 0x2001 0x4002 0x3002 0x1000
  594.  // 0x2001 0x4003 0x3003 0x1000
  595.  // 0x2001 0x4004 0x3004 0x1000
  596.  // 0x2001 0x4005 0x3005 0x1000
  597.  // 0x2002 0x4006 0x3006 0x1000
  598.  
  599.  if(fileinfo[2])
  600.    {
  601.     // move to surface information
  602.     if(debug) dfile << "SURFACE-MATERIAL ASSOCIATION" << endl;
  603.     ifile.seekg(fileinfo[2]);
  604.     if(ifile.fail()) return error("Seek failure.");
  605.    
  606.     // read surface information
  607.     for(size_t i = 0; i < surface_data.size(); i++)
  608.        {
  609.         // read group information
  610.         boost::shared_array<uint16> data(new uint16[surface_data[i].elem]);
  611.         BE_read_array(ifile, data.get(), surface_data[i].elem);
  612.         if(ifile.fail()) return error("Read failure.");
  613.    
  614.         uint16 curr_0x2000 = 0xFFFF;
  615.         uint16 curr_0x3000 = 0xFFFF;
  616.         uint16 curr_0x4000 = 0xFFFF;
  617.    
  618.         // for each item read
  619.         for(size_t j = 0; j < surface_data[i].elem; j++)
  620.            {
  621.             if(data[j] == 0x1000)
  622.               {
  623.                curr_0x2000 = 0xFFFF;
  624.                curr_0x3000 = 0xFFFF;
  625.                curr_0x4000 = 0xFFFF;
  626.                if(debug) dfile << "0x1000" << endl;
  627.               }
  628.             else if((data[j] & 0xFF00) == 0x2000)
  629.               {
  630.                curr_0x2000 = (uint16)(data[j] & 0x00FF);
  631.                if(debug) dfile << "0x" << hex << data[j] << " ";
  632.               }
  633.             else if((data[j] & 0xFF00) == 0x3000)
  634.               {
  635.                curr_0x3000 = (uint16)(data[j] & 0x00FF);
  636.                if(debug) dfile << "0x" << hex << data[j] << " ";
  637.                TEXTASSINFO info = { curr_0x2000, curr_0x3000 };
  638.                textass_data.push_back(info);
  639.               }
  640.             else if((data[j] & 0xFF00) == 0x4000)
  641.               {
  642.                curr_0x4000 = (uint16)(data[j] & 0x00FF);
  643.                if(debug) dfile << "0x" << hex << data[j] << " ";
  644.               }
  645.            }
  646.        }
  647.     if(debug) dfile << dec << endl;
  648.     if(debug) dfile << "Number of material-trigroup associations = " << textass_data.size() << endl;
  649.     if(debug) for(size_t i = 0; i < textass_data.size(); i++)  dfile << textass_data[i].material_index << "," << textass_data[i].trigroup_index << endl;
  650.     if(debug) dfile << endl;
  651.    }
  652.  
  653.  //
  654.  // PROCESS #05
  655.  // READ UNKNOWN SURFACE INFORMATION
  656.  //
  657.  
  658.  if(fileinfo[6] != 0)
  659.    {
  660.     // move to surface information
  661.     if(debug) dfile << "UNKNOWN SURFACE INFORMATION" << endl;
  662.     ifile.seekg(fileinfo[6]);
  663.     if(ifile.fail()) return error("Seek failure.");
  664.    
  665.     // read data
  666.     uint32 n_items = fileinfo[7];
  667.     if(debug) dfile << "Number of items = " << n_items << endl;
  668.     for(uint32 i = 0; i < n_items; i++) {
  669.         for(size_t j = 0; j < 132; j++) if(debug) dfile << setw(4) << (uint16)BE_read_uint08(ifile) << " ";
  670.         if(debug) dfile << endl;
  671.        }
  672.     if(debug) dfile << endl;
  673.    }
  674.  
  675.  //
  676.  // PROCESS #06
  677.  // READ MATERIALS
  678.  //
  679.  
  680.  if(fileinfo[8] != 0)
  681.    {
  682.     // move to surface information
  683.     if(debug) dfile << "MATERIALS" << endl;
  684.     ifile.seekg(fileinfo[8]);
  685.     if(ifile.fail()) return error("Seek failure.");
  686.     
  687.     // read data
  688.     uint32 n_materials = fileinfo[9];
  689.     if(debug) dfile << "Number of materials = " << n_materials << endl;
  690.  
  691.     for(uint32 i = 0; i < n_materials; i++)
  692.        {
  693.         // read material
  694.         auto p01 = BE_read_uint32(ifile); // 0x05
  695.         auto p02 = BE_read_uint32(ifile); // 0x00
  696.         auto p03 = BE_read_uint32(ifile); // base texture index
  697.         auto p04 = BE_read_real32(ifile); // crap
  698.         auto p05 = BE_read_real32(ifile); // crap
  699.         auto p06 = BE_read_real32(ifile); // crap
  700.         auto p07 = BE_read_real32(ifile); // crap
  701.         auto p08 = BE_read_uint32(ifile); // 0xFFFFFFFF
  702.         auto p09 = BE_read_uint32(ifile); // 0xFFFFFFFF
  703.         auto p10 = BE_read_real32(ifile); // crap
  704.         auto p11 = BE_read_real32(ifile); // crap
  705.         auto p12 = BE_read_real32(ifile); // crap
  706.         auto p13 = BE_read_real32(ifile); // crap
  707.         auto p14 = BE_read_uint32(ifile); // 0xFFFFFFFF
  708.         auto p15 = BE_read_uint32(ifile); // 0xFFFFFFFF
  709.         auto p16 = BE_read_real32(ifile); // crap
  710.         auto p17 = BE_read_real32(ifile); // crap
  711.         auto p18 = BE_read_real32(ifile); // crap
  712.         auto p19 = BE_read_real32(ifile); // std::endl of 3 4xfloats
  713.         auto p20 = BE_read_uint32(ifile); // 0x03
  714.         auto p21 = BE_read_uint32(ifile); // normal map index
  715.         auto p22 = BE_read_real32(ifile); // crap
  716.         auto p23 = BE_read_real32(ifile); // crap
  717.         auto p24 = BE_read_real32(ifile); // crap
  718.         auto p25 = BE_read_real32(ifile); // crap
  719.         auto p26 = BE_read_uint32(ifile); // 0x04
  720.         auto p27 = BE_read_uint32(ifile); // specular map index
  721.         auto p28 = BE_read_real32(ifile); // crap
  722.         auto p29 = BE_read_real32(ifile); // crap
  723.         auto p30 = BE_read_real32(ifile); // crap
  724.         auto p31 = BE_read_real32(ifile); // crap
  725.         auto p32 = BE_read_uint32(ifile); // 0x01
  726.         auto p33 = BE_read_uint32(ifile); // 0x00
  727.         auto p34 = BE_read_uint32(ifile); // 0x01
  728.         auto p35 = BE_read_uint32(ifile); // 0x01
  729.         auto p36 = BE_read_uint32(ifile); // 0x01
  730.         auto p37 = BE_read_real32(ifile); // crap
  731.         auto p38 = BE_read_real32(ifile); // crap
  732.         auto p39 = BE_read_real32(ifile); // crap
  733.         auto p40 = BE_read_real32(ifile); // crap
  734.         auto p41 = BE_read_real32(ifile); // crap
  735.         auto p42 = BE_read_real32(ifile); // crap
  736.         auto p43 = BE_read_real32(ifile); // crap
  737.         auto p44 = BE_read_real32(ifile); // crap
  738.         auto p45 = BE_read_real32(ifile); // crap
  739.         auto p46 = BE_read_real32(ifile); // crap
  740.         auto p47 = BE_read_real32(ifile); // crap
  741.         auto p48 = BE_read_real32(ifile); // crap
  742.         auto p49 = BE_read_real32(ifile); // crap
  743.         auto p50 = BE_read_real32(ifile); // crap
  744.         if(debug) dfile << p01 << " ";
  745.         if(debug) dfile << p02 << " ";
  746.         if(debug) dfile << p03 << " ";
  747.         if(debug) dfile << p08 << " ";
  748.         if(debug) dfile << p09 << " ";
  749.         if(debug) dfile << p14 << " ";
  750.         if(debug) dfile << p15 << " ";
  751.         if(debug) dfile << p20 << " ";
  752.         if(debug) dfile << p21 << " ";
  753.         if(debug) dfile << p26 << " ";
  754.         if(debug) dfile << p27 << " ";
  755.         if(debug) dfile << p32 << " ";
  756.         if(debug) dfile << p33 << " ";
  757.         if(debug) dfile << p34 << " ";
  758.         if(debug) dfile << p35 << " ";
  759.         if(debug) dfile << p36 << " ";
  760.         if(debug) dfile << endl;
  761.  
  762.         // build material name
  763.         stringstream name;
  764.         name << "material_" << setfill('0') << setw(3) << i;
  765.  
  766.         // create material
  767.         SMC_MATERIAL mat;
  768.         mat.id = name.str();
  769.         mat.twoside = false;
  770.         mat.basemap = p03;
  771.         mat.normmap = p21;
  772.         mat.specmap = p27;
  773.         mat.tranmap = INVALID_TEXTURE_INDEX;//p03;
  774.         mat.bumpmap = INVALID_TEXTURE_INDEX;
  775.         mat.resmap1 = INVALID_TEXTURE_INDEX;
  776.         mat.resmap2 = INVALID_TEXTURE_INDEX;
  777.         mat.resmap3 = INVALID_TEXTURE_INDEX;
  778.         mat.resmap4 = INVALID_TEXTURE_INDEX;
  779.  
  780.         // save material
  781.         smc.materials.push_back(mat);
  782.        }
  783.     if(debug) dfile << endl;
  784.    }
  785.  
  786.  //
  787.  // PROCESS #07
  788.  // READ TRIANGLE GROUP DATA
  789.  //
  790.  
  791.  struct TRILISTINFO {
  792.   uint32 triangles;
  793.   uint32 offset;
  794.  };
  795.  deque<TRILISTINFO> trilist_data;
  796.  
  797.  if(fileinfo[10])
  798.    {
  799.     // move to triangle information
  800.     if(debug) dfile << "TRIANGLE GROUPS (TRIANGLES, POSITION)" << endl;
  801.     ifile.seekg(fileinfo[10]);
  802.     if(ifile.fail()) return error("Seek failure.");
  803.  
  804.     // number of groups
  805.     uint32 n_groups = fileinfo[11];
  806.     if(n_groups == 0) return error("Invalid number of triangle groups.");
  807.  
  808.     // read triangle information
  809.     for(uint32 i = 0; i < n_groups; i++) {
  810.         uint16 p1 = BE_read_uint16(ifile); // number of triangles
  811.         uint16 p2 = BE_read_uint16(ifile); // always 0x0508
  812.         uint32 p3 = BE_read_uint32(ifile); // triangle offset
  813.         TRILISTINFO info = { p1, p3 };
  814.         trilist_data.push_back(info);
  815.         if(debug) dfile << "trigroup[" << i << "] = (" << info.offset << ", " << info.triangles << ")" << endl;
  816.        }
  817.  
  818.     if(debug) dfile << endl;
  819.    }
  820.  
  821.  //
  822.  // PROCESS #08
  823.  // READ INDEX BUFFER
  824.  //
  825.  
  826.  if(fileinfo[12])
  827.    {
  828.     // move to index buffer
  829.     if(debug) dfile << "INDEX BUFFER DATA" << endl;
  830.     ifile.seekg(fileinfo[12]);
  831.     if(ifile.fail()) return error("Seek failure.");
  832.     
  833.     // number of triangles
  834.     uint32 n_triangles = fileinfo[13];
  835.     if(n_triangles == 0) return error("Invalid number of triangles.");
  836.     
  837.     // process triangle groups
  838.     for(size_t i = 0; i < trilist_data.size(); i++)
  839.        {
  840.         // get texture-material association data
  841.         TEXTASSINFO ai = textass_data[i];
  842.         if(!(ai.material_index < smc.materials.size())) return error("Texture association data is invalid.");
  843.         uint32 ib_material = ai.material_index;
  844.     
  845.         // surface name
  846.         stringstream ss;
  847.         ss << "trigroup_" << setfill('0') << setw(3) << i;
  848.     
  849.         // move to data offset
  850.         uint32 ib_offset = 3*indexsize*trilist_data[i].offset;
  851.         ifile.seekg(fileinfo[12] + ib_offset);
  852.         if(ifile.fail()) return error("Seek failure.");
  853.     
  854.         // read index buffer
  855.         uint32 ib_tris = trilist_data[i].triangles;
  856.         uint32 ib_elem = ib_tris*3;
  857.         uint32 ib_char = ib_elem*indexsize;
  858.         boost::shared_array<char> ib_data(new char[ib_char]);
  859.         if(indextype == FACE_FORMAT_UINT_16) BE_read_array(ifile, reinterpret_cast<uint16*>(ib_data.get()), ib_elem);
  860.         else BE_read_array(ifile, reinterpret_cast<uint32*>(ib_data.get()), ib_elem);
  861.         if(ifile.fail()) return error("Read failure.");
  862.     
  863.         // create index buffer
  864.         SMC_INDEX_BUFFER ib;
  865.         ib.format = indextype;
  866.         ib.type = FACE_TYPE_TRIANGLES;
  867.         ib.name = ss.str();
  868.         ib.elem = ib_elem;
  869.         ib.data = ib_data;
  870.         ib.tris = ib_tris;
  871.         ib.material = ib_material;
  872.     
  873.         // save index buffer
  874.         smc.ibuffer.push_back(ib);
  875.        }
  876.     if(debug) dfile << endl;
  877.    }
  878.  
  879.  //
  880.  // PROCESS #09
  881.  // READ VERTEX BUFFER
  882.  //
  883.  
  884.  if(fileinfo[15])
  885.    {
  886.     // number of vertices
  887.     uint32 n_vertices = fileinfo[14];
  888.     if(n_vertices == 0) return error("Invalid number of vertices.");
  889.  
  890.     // move to vertex buffer
  891.     if(debug) dfile << "VERTEX BUFFER DATA" << std::endl;
  892.     ifile.seekg(fileinfo[15]);
  893.     if(ifile.fail()) return error("Seek failure.");
  894.  
  895.     // create vertex buffer
  896.     smc.vbuffer.flags = VERTEX_POSITION;
  897.     smc.vbuffer.name = "vbuffer";
  898.     smc.vbuffer.elem = n_vertices;
  899.     smc.vbuffer.data.reset(new SMC_VERTEX[n_vertices]);
  900.  
  901.     // vertex flags
  902.     if(head02 == 0x01A7) {
  903.        smc.vbuffer.flags |= VERTEX_UV;
  904.     //   smc.vbuffer.flags |= VERTEX_WEIGHTS;
  905.     //   smc.vbuffer.flags |= VERTEX_WMAPIDX;
  906.       }
  907.     else if(head02 == 0x0905) {
  908.        smc.vbuffer.flags |= VERTEX_UV;
  909.       }
  910.     else if(head02 == 0x0925) {
  911.        smc.vbuffer.flags |= VERTEX_UV;
  912.       }
  913.     else if(head02 == 0x09A7) {
  914.        smc.vbuffer.flags |= VERTEX_UV;
  915.       }
  916.     else if(head02 == 0x09AF) {
  917.        smc.vbuffer.flags |= VERTEX_UV;
  918.       }
  919.     else if(head02 == 0x09BF) {
  920.        smc.vbuffer.flags |= VERTEX_UV;
  921.       }
  922.     else if(head02 == 0x09E7) {
  923.        smc.vbuffer.flags |= VERTEX_UV;
  924.       }
  925.  
  926.     // read vertices
  927.     for(size_t i = 0; i < n_vertices; i++)
  928.        {
  929.         if(head02 == 0x01A7)
  930.           {
  931.            float v01 = BE_read_real32(ifile); //  4
  932.            float v02 = BE_read_real32(ifile); //  8
  933.            float v03 = BE_read_real32(ifile); // 12
  934.            smc.vbuffer.data[i].vx = v01;
  935.            smc.vbuffer.data[i].vy = v02;
  936.            smc.vbuffer.data[i].vz = v03;
  937.            if(debug) dfile << v01 << endl;
  938.            if(debug) dfile << v02 << endl;
  939.            if(debug) dfile << v03 << endl;
  940.            if(debug) dfile << endl;
  941.           }
  942.         else if(head02 == 0x0905)
  943.           {
  944.            float v01 = BE_read_real32(ifile); //  4
  945.            float v02 = BE_read_real32(ifile); //  8
  946.            float v03 = BE_read_real32(ifile); // 12
  947.            smc.vbuffer.data[i].vx = v01;
  948.            smc.vbuffer.data[i].vy = v02;
  949.            smc.vbuffer.data[i].vz = v03;
  950.            if(debug) dfile << v01 << endl;
  951.            if(debug) dfile << v02 << endl;
  952.            if(debug) dfile << v03 << endl;
  953.            if(debug) dfile << endl;
  954.           }
  955.         else if(head02 == 0x0925)
  956.           {
  957.            float v01 = BE_read_real32(ifile); //  4
  958.            float v02 = BE_read_real32(ifile); //  8
  959.            float v03 = BE_read_real32(ifile); // 12
  960.            smc.vbuffer.data[i].vx = v01;
  961.            smc.vbuffer.data[i].vy = v02;
  962.            smc.vbuffer.data[i].vz = v03;
  963.            if(debug) dfile << v01 << endl;
  964.            if(debug) dfile << v02 << endl;
  965.            if(debug) dfile << v03 << endl;
  966.            if(debug) dfile << endl;
  967.           }
  968.         else if(head02 == 0x09A3) // ??? WRONG?
  969.           {
  970.            float v01 = BE_read_real32(ifile); //  4
  971.            float v02 = BE_read_real32(ifile); //  8
  972.            float v03 = BE_read_real32(ifile); // 12
  973.            smc.vbuffer.data[i].vx = v01;
  974.            smc.vbuffer.data[i].vy = v02;
  975.            smc.vbuffer.data[i].vz = v03;
  976.            if(debug) dfile << v01 << endl;
  977.            if(debug) dfile << v02 << endl;
  978.            if(debug) dfile << v03 << endl;
  979.            if(debug) dfile << endl;
  980.           }
  981.         else if(head02 == 0x09A7)
  982.           {
  983.            float v01 = BE_read_real32(ifile); //  4
  984.            float v02 = BE_read_real32(ifile); //  8
  985.            float v03 = BE_read_real32(ifile); // 12
  986.            smc.vbuffer.data[i].vx = v01;
  987.            smc.vbuffer.data[i].vy = v02;
  988.            smc.vbuffer.data[i].vz = v03;
  989.            if(debug) dfile << v01 << endl;
  990.            if(debug) dfile << v02 << endl;
  991.            if(debug) dfile << v03 << endl;
  992.            if(debug) dfile << endl;
  993.           }
  994.         else if(head02 == 0x09AF)
  995.           {
  996.            float v01 = BE_read_real32(ifile); //  4
  997.            float v02 = BE_read_real32(ifile); //  8
  998.            float v03 = BE_read_real32(ifile); // 12
  999.            smc.vbuffer.data[i].vx = v01;
  1000.            smc.vbuffer.data[i].vy = v02;
  1001.            smc.vbuffer.data[i].vz = v03;
  1002.            if(debug) dfile << v01 << endl;
  1003.            if(debug) dfile << v02 << endl;
  1004.            if(debug) dfile << v03 << endl;
  1005.            if(debug) dfile << endl;
  1006.           }
  1007.         else if(head02 == 0x09BF)
  1008.           {
  1009.            float v01 = BE_read_real32(ifile); //  4
  1010.            float v02 = BE_read_real32(ifile); //  8
  1011.            float v03 = BE_read_real32(ifile); // 12
  1012.            smc.vbuffer.data[i].vx = v01;
  1013.            smc.vbuffer.data[i].vy = v02;
  1014.            smc.vbuffer.data[i].vz = v03;
  1015.            if(debug) dfile << v01 << endl;
  1016.            if(debug) dfile << v02 << endl;
  1017.            if(debug) dfile << v03 << endl;
  1018.            if(debug) dfile << endl;
  1019.           }
  1020.         else if(head02 == 0x09E7)
  1021.           {
  1022.            auto v01 = BE_read_real32(ifile);
  1023.            auto v02 = BE_read_real32(ifile);
  1024.            auto v03 = BE_read_real32(ifile);
  1025.            auto v04 = BE_read_uint16(ifile);
  1026.            auto v05 = BE_read_uint16(ifile);
  1027.            auto v06 = BE_read_uint16(ifile);
  1028.            auto v07 = BE_read_uint16(ifile);
  1029.            auto v08 = BE_read_uint16(ifile);
  1030.            auto v09 = BE_read_uint16(ifile);
  1031.            auto v10 = BE_read_uint32(ifile);
  1032.            auto v11 = BE_read_sint16(ifile);
  1033.            auto v12 = BE_read_sint16(ifile);
  1034.            smc.vbuffer.data[i].vx = v01;
  1035.            smc.vbuffer.data[i].vy = v02;
  1036.            smc.vbuffer.data[i].vz = v03;
  1037.            smc.vbuffer.data[i].tu =  v11/1023.0f;
  1038.            smc.vbuffer.data[i].tv = -v12/1023.0f;
  1039.            if(debug) dfile << v01 << endl;
  1040.            if(debug) dfile << v02 << endl;
  1041.            if(debug) dfile << v03 << endl;
  1042.            if(debug) dfile << v04 << endl;
  1043.            if(debug) dfile << v05 << endl;
  1044.            if(debug) dfile << v06 << endl;
  1045.            if(debug) dfile << v07 << endl;
  1046.            if(debug) dfile << v08 << endl;
  1047.            if(debug) dfile << v09 << endl;
  1048.            if(debug) dfile << v10 << endl;
  1049.            if(debug) dfile << v11 << endl;
  1050.            if(debug) dfile << v12 << endl;
  1051.            if(debug) dfile << endl;
  1052.           }
  1053.        }
  1054.    }
  1055.  
  1056.  //
  1057.  // PROCESS #10
  1058.  // READ SEPARATE UV DATA
  1059.  //
  1060.  
  1061.  if(fileinfo[17])
  1062.    {
  1063.     // move to offset
  1064.     if(debug) dfile << "SEPARATE UV DATA" << std::endl;
  1065.     ifile.seekg(fileinfo[17]);
  1066.     if(ifile.fail()) return error("Seek failure.");
  1067.     if(head02 == 0x01A7 || head02 == 0x0905 || head02 == 0x0925 || head02 == 0x09A7 || head02 == 0x09AF || head02 == 0x09BF)
  1068.       {
  1069.        uint32 n_vertices = fileinfo[14];
  1070.        for(size_t i = 0; i < n_vertices; i++) {
  1071.            auto v1 = BE_read_sint16(ifile);
  1072.            auto v2 = BE_read_sint16(ifile);
  1073.            if(debug) dfile << "v1 = " << v1 << endl;
  1074.            if(debug) dfile << "v2 = " << v2 << endl;
  1075.            smc.vbuffer.data[i].tu =  v1/1024.0f;
  1076.            smc.vbuffer.data[i].tv = -v2/1024.0f;
  1077.           }
  1078.       }
  1079.     if(debug) dfile << std::endl;
  1080.    }
  1081.  
  1082.  //
  1083.  // PROCESS #11
  1084.  // READ BONE MATRICES
  1085.  //
  1086. /*
  1087.  // process bones
  1088.  if(fileinfo[23])
  1089.    {
  1090.     // move to bone matrices
  1091.     if(debug) dfile << "BONE MATRICES" << endl;
  1092.     ifile.seekg(fileinfo[23]);
  1093.     if(ifile.fail()) return error("Seek failure.");
  1094.  
  1095.     // data to save
  1096.     std::deque<boost::shared_array<float>> mlist;
  1097.     SKELETON skeleton;
  1098.     skeleton.set_identifier("skeleton");
  1099.  
  1100.     // read matrices
  1101.     uint32 n_bones = fileinfo[24];
  1102.     if(debug) dfile << "number of bones = " << n_bones << endl;
  1103.     for(size_t i = 0; i < n_bones; i++) {
  1104.         boost::shared_array<float> m(new float[16]);
  1105.         m[ 0] = BE_read_real32(ifile);
  1106.         m[ 1] = BE_read_real32(ifile);
  1107.         m[ 2] = BE_read_real32(ifile);
  1108.         m[ 3] = BE_read_real32(ifile);
  1109.         m[ 4] = BE_read_real32(ifile);
  1110.         m[ 5] = BE_read_real32(ifile);
  1111.         m[ 6] = BE_read_real32(ifile);
  1112.         m[ 7] = BE_read_real32(ifile);
  1113.         m[ 8] = BE_read_real32(ifile);
  1114.         m[ 9] = BE_read_real32(ifile);
  1115.         m[10] = BE_read_real32(ifile);
  1116.         m[11] = BE_read_real32(ifile);
  1117.         m[12] = BE_read_real32(ifile);
  1118.         m[13] = BE_read_real32(ifile);
  1119.         m[14] = BE_read_real32(ifile);
  1120.         m[15] = BE_read_real32(ifile);
  1121.         mlist.push_back(m);
  1122.         if(debug) dfile << m[ 0] << " " << m[ 1] << " " << m[ 2] << " " << m[ 3] << endl;
  1123.         if(debug) dfile << m[ 4] << " " << m[ 5] << " " << m[ 6] << " " << m[ 7] << endl;
  1124.         if(debug) dfile << m[ 8] << " " << m[ 9] << " " << m[10] << " " << m[11] << endl;
  1125.         if(debug) dfile << m[12] << " " << m[13] << " " << m[14] << " " << m[15] << endl;
  1126.         if(debug) dfile << endl;
  1127.        }
  1128.  
  1129.     // move to bone information
  1130.     if(debug) dfile << "BONES" << std::endl;
  1131.     ifile.seekg(fileinfo[25]);
  1132.     if(ifile.fail()) return error("Seek failure.");
  1133.     if(n_bones != fileinfo[26]) return error("Number of joints do not match.");
  1134.  
  1135.     // read bone information
  1136.     for(size_t i = 0; i < n_bones; i++)
  1137.        {
  1138.         // joint
  1139.         JOINT joint;
  1140.         uint32 index = (uint32)i;
  1141.    
  1142.         // joint name
  1143.         char name[5];
  1144.         ifile.read(&name[0], 4);
  1145.         std::reverse(&name[0], &name[4]);
  1146.         name[4] = '\0';
  1147.  
  1148.         // make joint name unique
  1149.         std::stringstream jnss;
  1150.         jnss << name << "_" << setfill('0') << setw(3) << i;
  1151.         joint.name = jnss.str();
  1152.    
  1153.         // joint matrix
  1154.         joint.matrix = mlist[i];
  1155.  
  1156.         // joint relative positions
  1157.         float x = BE_read_real32(ifile);
  1158.         float y = BE_read_real32(ifile);
  1159.         float z = BE_read_real32(ifile);
  1160.         joint.rel_x = x;
  1161.         joint.rel_y = y;
  1162.         joint.rel_z = z;
  1163.  
  1164.         // set parent
  1165.         uint32 parent = BE_read_uint32(ifile);
  1166.         uint32 xxxxxx = BE_read_uint32(ifile);
  1167.         joint.parent = parent;
  1168.    
  1169.         // debug information
  1170.         if(debug) dfile << "index = " << index << endl;   
  1171.         if(debug) dfile << "name = " << name << endl;   
  1172.         if(debug) dfile << "x = " << x << endl;
  1173.         if(debug) dfile << "y = " << y << endl;
  1174.         if(debug) dfile << "z = " << z << endl;
  1175.         if(debug) dfile << "parent = " << parent << endl;
  1176.         if(debug) dfile << "xxxxxx = " << xxxxxx << endl;
  1177.         if(debug) dfile << std::endl;
  1178.  
  1179.         // insert joint
  1180.         if(parent == INVALID_JOINT && i != 0) continue;
  1181.         else skeleton.insert(index, joint);
  1182.        }
  1183.  
  1184.     // print joint tree in debug mode
  1185.     if(debug) {
  1186.        stringstream ss;
  1187.        skeleton.PrintJointTree(ss);
  1188.        dfile << ss.str() << endl;
  1189.       }
  1190.  
  1191.     // create skeleton
  1192.     smc.skeletons.push_back(skeleton);
  1193.    }
  1194. */
  1195.  
  1196.  //
  1197.  // PROCESS #12
  1198.  // READ TEXTURES
  1199.  //
  1200.  
  1201.  if(fileinfo[27])
  1202.    {
  1203.     // move to texture information
  1204.     if(debug) dfile << "TEXTURES" << endl;
  1205.     ifile.seekg(fileinfo[27]);
  1206.     if(ifile.fail()) return error("Seek failure.");
  1207.    
  1208.     // read texture information
  1209.     uint32 n_textures = fileinfo[28];
  1210.     for(uint32 i = 0; i < n_textures; i++)
  1211.        {
  1212.         uint32 param1 = BE_read_uint32(ifile); // index
  1213.         uint32 param2 = BE_read_uint32(ifile); // 0
  1214.         uint16 param3 = BE_read_uint16(ifile); // 0x0001
  1215.         uint16 param4 = BE_read_uint16(ifile); // 0x0040 | 0x0100 | 0x0200 | 0x0400
  1216.         uint16 param5 = BE_read_uint16(ifile); // 0x0040 | 0x0100 | 0x0200 | 0x0400
  1217.         uint16 param6 = BE_read_uint16(ifile); // 0x2000 | 0xFF00
  1218.         if(debug) dfile << "param1 = " << param1 << endl;
  1219.         if(debug) dfile << "param2 = " << param2 << endl;
  1220.         if(debug) dfile << "param3 = " << param3 << endl;
  1221.         if(debug) dfile << "param4 = " << param4 << endl;
  1222.         if(debug) dfile << "param5 = " << param5 << endl;
  1223.         if(debug) dfile << "param6 = " << param6 << endl;
  1224.         if(debug) dfile << std::endl;
  1225.    
  1226.         // texture id
  1227.         stringstream id;
  1228.         id << "texture_" << setfill('0') << setw(3) << param1;
  1229.    
  1230.         // texture filename
  1231.         stringstream fn;
  1232.         fn << setfill('0') << setw(3) << param1 << ".tga";
  1233.    
  1234.         // insert texture
  1235.         SMC_TEXTURE item = { id.str(), fn.str() };
  1236.         smc.textures.push_back(item);
  1237.        }
  1238.     if(debug) dfile << endl;
  1239.    }
  1240.  
  1241.  // save geometry
  1242.  return SaveLWO(fn_path.c_str(), fn_name.c_str(), smc);
  1243. }
  1244.  
  1245. };};
  1246.  
  1247. namespace X_SYSTEM { namespace X_GAME {
  1248.  
  1249. bool extract(void)
  1250. {
  1251.  std::string pathname = GetModulePathname();
  1252.  return extract(pathname.c_str());
  1253. }
  1254.  
  1255. bool extract(const char* pathname)
  1256. {
  1257.  return extractor(pathname).extract();
  1258. }
  1259.  
  1260. };};