home *** CD-ROM | disk | FTP | other *** search
/ Xentax forum attachments archive / xentax.7z / 7568 / macross30.7z / macross30.cpp
Encoding:
C/C++ Source or Header  |  2014-07-10  |  85.3 KB  |  2,429 lines

  1. #include "xentax.h"
  2. #include "x_file.h"
  3. #include "x_findfile.h"
  4. #include "x_zlib.h"
  5. #include "x_segs.h"
  6. #include "x_stream.h"
  7. #include "x_dds.h"
  8. #include "x_gui.h"
  9. #include "x_amc.h"
  10. #include "ps3_macross30.h"
  11. using namespace std;
  12.  
  13. #define X_SYSTEM PS3
  14. #define X_GAME   MACROSS30
  15.  
  16. static bool debug = true;
  17. // static set<uint32> set30;
  18. // static set<uint32> set31;
  19.  
  20. //
  21. // ARCHIVES
  22. //
  23.  
  24. namespace X_SYSTEM { namespace X_GAME {
  25.  
  26. struct DATTABLE1 {
  27.  uint32 p01; // 0 (file) or 1 (folder)
  28.  uint32 p02; // offset into string table
  29.  uint32 p03;
  30.  uint32 p04;
  31.  uint32 p05;
  32.  uint32 p06;
  33. };
  34.  
  35. struct DATTABLE2 {
  36.  uint32 p01; // offset into string table (folder)
  37.  uint32 p02; // 0x00000000
  38.  uint32 p03; // offset to FSTS data
  39.  uint32 p04; // size of FSTS data
  40.  uint32 p05; // number of FSTS items (also appears in FSTS header)
  41. };
  42.  
  43. struct FSTSITEM {
  44.  uint32 p01; // offset into string table
  45.  uint32 p02; // offset to data
  46.  uint32 p03; // size of uncompressed data
  47.  uint32 p04; // size of compressed data
  48. };
  49.  
  50. bool processDAT(LPCTSTR filename)
  51. {
  52.  // open file
  53.  ifstream ifile(filename, ios::binary);
  54.  if(!ifile) return error("Failed to open DAT file.");
  55.  
  56.  // determine filesize
  57.  uint32 filesize = 0x00;
  58.  ifile.seekg(0, ios::end);
  59.  filesize = (uint32)ifile.tellg();
  60.  ifile.seekg(0, ios::beg);
  61.  
  62.  // filename properties
  63.  STDSTRING pathname = GetPathnameFromFilename(filename).get();
  64.  STDSTRING shrtname = GetShortFilenameWithoutExtension(filename).get();
  65.  
  66.  // debug file
  67.  ofstream dfile;
  68.  if(debug) {
  69.     STDSTRINGSTREAM ss;
  70.     ss << pathname << shrtname << TEXT(".txt");
  71.     dfile.open(ss.str().c_str());
  72.     if(!dfile.is_open()) return error("Failed to create debug file.");
  73.    }
  74.  
  75.  // read header
  76.  uint32 h01 = LE_read_uint32(ifile); // PIDX0
  77.  uint32 h02 = LE_read_uint32(ifile); // offset to table to 0x20-byte entries
  78.  uint32 h03 = LE_read_uint32(ifile); // number of 0x20-byte entries
  79.  uint32 h04 = LE_read_uint32(ifile); // offset to table of 0x18-byte entries
  80.  uint32 h05 = LE_read_uint32(ifile); // number of 0x18-byte entries
  81.  uint32 h06 = LE_read_uint32(ifile); // unknown 0x00, 0x01, or 0x02
  82.  uint32 h07 = LE_read_uint32(ifile); // offset to table of 0x18-byte entries
  83.  uint32 h08 = LE_read_uint32(ifile); // number of bytes in table
  84.  uint32 h09 = LE_read_uint32(ifile); // offset to string table
  85.  uint32 h10 = LE_read_uint32(ifile); // length of string table
  86.  uint32 h11 = LE_read_uint32(ifile); // 0x00
  87.  uint32 h12 = LE_read_uint32(ifile); // 0x00
  88.  
  89.  // validate header
  90.  if(h01 != 0x58444950) return error("Not a DAT file.");
  91.  
  92.  // move to string table
  93.  ifile.seekg(h09);
  94.  if(ifile.fail()) return error("Seek failure.");
  95.  
  96.  // read string table into stream
  97.  boost::shared_array<char> strtabledata;
  98.  if(h10) {
  99.     strtabledata.reset(new char[h10]);
  100.     ifile.read(strtabledata.get(), h10);
  101.     if(ifile.fail()) return error("Read failure.");
  102.    }
  103.  binary_stream ststream(strtabledata, h10);
  104.  
  105.  // parse string table
  106.  deque<string> strtable;
  107.  if(h10) {
  108.     binary_stream bs(strtabledata, h10);
  109.     for(;;) {
  110.         string temp = bs.read_string();
  111.         if(bs.fail()) return error("Stream read failure.");
  112.         strtable.push_back(temp);
  113.         if(bs.at_end()) break;
  114.        }
  115.    }
  116.  if(debug) {
  117.     dfile << "-----------" << endl;
  118.     dfile << "STRINGTABLE" << endl;
  119.     dfile << "-----------" << endl;
  120.     dfile << endl;
  121.     dfile << "0x" << hex << strtable.size() << dec << " entries" << endl;
  122.     dfile << endl;
  123.     for(uint32 i = 0; i < strtable.size(); i++) {
  124.         dfile << "0x" << setfill('0') << setw(3) << hex << i << dec;
  125.         dfile << ": " << strtable[i] << endl;
  126.        }
  127.     dfile << endl;
  128.    }
  129.  
  130.  // process 1st table
  131.  deque<DATTABLE1> table1;
  132.  deque<string> pathlist1;
  133.  if(h04 && h05)
  134.    {
  135.     // move to table
  136.     ifile.seekg(h04);
  137.     if(ifile.fail()) return error("Seek failure.");
  138.  
  139.     // read parameters
  140.     for(uint32 i = 0; i < h05; i++) {
  141.         DATTABLE1 item;
  142.         item.p01 = LE_read_uint32(ifile);
  143.         item.p02 = LE_read_uint32(ifile);
  144.         item.p03 = LE_read_uint32(ifile);
  145.         item.p04 = LE_read_uint32(ifile);
  146.         item.p05 = LE_read_uint32(ifile);
  147.         item.p06 = LE_read_uint32(ifile);
  148.         table1.push_back(item);
  149.        }
  150.     if(dfile) dfile << endl;
  151.  
  152.     // set size of pathlist data
  153.     pathlist1.resize(h05);
  154.  
  155.     // build full paths
  156.     for(uint32 i = 0; i < h05; i++)
  157.        {
  158.         // item must be a folder
  159.         DATTABLE1 item = table1[i];
  160.         if(item.p01 != 1) continue;
  161.  
  162.         // read folder name
  163.         ststream.seek(item.p02);
  164.         string path = ststream.read_string();
  165.  
  166.         // for each file
  167.         for(uint32 j = 0; j < item.p03; j++)
  168.            {
  169.             // get subitem
  170.             uint32 subindex = item.p04 + j;
  171.             if(!(subindex < h05)) return error("Subindex out of range.");
  172.             DATTABLE1 subitem = table1[subindex];
  173.  
  174.             // read name
  175.             ststream.seek(subitem.p02);
  176.             string subname = ststream.read_string();
  177.  
  178.             // modify to full pathname
  179.             string combined = (pathlist1[i].length() ? pathlist1[i] : path);
  180.             combined += "\\";
  181.             combined += subname;
  182.             pathlist1[subindex] = combined;
  183.            }
  184.        }
  185.  
  186.     // BEGIN DEBUG
  187.     if(debug) {
  188.        dfile << "----------------" << endl;
  189.        dfile << "TABLE ENTRIES #1" << endl;
  190.        dfile << "----------------" << endl;
  191.        dfile << endl;
  192.        for(uint32 i = 0; i < h05; i++) {
  193.            DATTABLE1 item = table1[i];
  194.            dfile << setfill('0') << hex;
  195.            dfile << "0x" << setw(4) << i << ": ";
  196.            dfile << "0x" << setw(8) << item.p01 << " ";
  197.            dfile << "0x" << setw(8) << item.p02 << " ";
  198.            dfile << "0x" << setw(8) << item.p03 << " ";
  199.            dfile << "0x" << setw(8) << item.p04 << " ";
  200.            dfile << "0x" << setw(8) << item.p05 << " ";
  201.            dfile << "0x" << setw(8) << item.p06 << dec << " -- ";
  202.            ststream.seek(item.p02);
  203.            dfile << ststream.read_string() << " -- ";
  204.            dfile << pathlist1[i] << endl;
  205.           }
  206.        dfile << endl;
  207.       }
  208.     // END DEBUG
  209.    }
  210.  
  211.  // process 2nd section
  212.  deque<DATTABLE2> table2;
  213.  if(h07 && h08)
  214.    {
  215.     // move to data
  216.     ifile.seekg(h07);
  217.     if(ifile.fail()) return error("Seek failure.", __LINE__);
  218.  
  219.     // read data
  220.     boost::shared_array<char> data(new char[h08]);
  221.     ifile.read(data.get(), h08);
  222.     if(ifile.fail()) return error("Read failure.", __LINE__);
  223.     binary_stream bs(data, h08);
  224.  
  225.     // read number of items
  226.     uint32 n_items = bs.LE_read_uint32();
  227.     if(bs.fail()) return error("Stream read failure.", __LINE__);
  228.  
  229.     // read list of offsets
  230.     boost::shared_array<uint32> offsets(new uint32[n_items]);
  231.     bs.LE_read_array(offsets.get(), n_items);
  232.     if(bs.fail()) return error("Stream read failure.", __LINE__);
  233.  
  234.     // read items
  235.     for(uint32 i = 0; i < n_items; i++) {
  236.         bs.seek(offsets[i]);
  237.         if(bs.fail()) return error("Stream seek failure.", __LINE__);
  238.         DATTABLE2 item;
  239.         item.p01 = bs.LE_read_uint32();
  240.         item.p02 = bs.LE_read_uint32();
  241.         item.p03 = bs.LE_read_uint32();
  242.         item.p04 = bs.LE_read_uint32();
  243.         item.p05 = bs.LE_read_uint32();
  244.         table2.push_back(item);
  245.         if(debug) {
  246.            dfile << setfill('0') << hex;
  247.            dfile << "0x" << setw(4) << i << ": ";
  248.            dfile << "0x" << setw(8) << item.p01 << " ";
  249.            dfile << "0x" << setw(8) << item.p02 << " ";
  250.            dfile << "0x" << setw(8) << item.p03 << " ";
  251.            dfile << "0x" << setw(8) << item.p04 << " ";
  252.            dfile << "0x" << setw(8) << item.p05 << dec << " -- ";
  253.            ststream.seek(item.p01);
  254.            dfile << ststream.read_string() << endl;
  255.           }
  256.        }
  257.  
  258.     // BEGIN DEBUG
  259.     if(debug) {
  260.        dfile << "----------------" << endl;
  261.        dfile << "TABLE ENTRIES #2" << endl;
  262.        dfile << "----------------" << endl;
  263.        dfile << endl;
  264.        for(uint32 i = 0; i < n_items; i++) {
  265.            DATTABLE2 item = table2[i];
  266.            dfile << setfill('0') << hex;
  267.            dfile << "0x" << setw(4) << i << ": ";
  268.            dfile << "0x" << setw(8) << item.p01 << " ";
  269.            dfile << "0x" << setw(8) << item.p02 << " ";
  270.            dfile << "0x" << setw(8) << item.p03 << " ";
  271.            dfile << "0x" << setw(8) << item.p04 << " ";
  272.            dfile << "0x" << setw(8) << item.p05 << dec << " -- ";
  273.            ststream.seek(item.p01);
  274.            dfile << ststream.read_string() << endl;
  275.           }
  276.        dfile << endl;
  277.       }
  278.     // END DEBUG
  279.    }
  280.  
  281.  //
  282.  // PHASE #1
  283.  // PROCESS TABLE #1
  284.  //
  285.  
  286.  // string table stream
  287.  for(size_t i = 0; i < table1.size(); i++)
  288.     {
  289.      // file
  290.      DATTABLE1 item = table1[i];
  291.      if(item.p01 == 0)
  292.        {
  293.         // p02 = filename
  294.         ststream.seek(item.p02);
  295.         string filename = ststream.read_string();
  296.  
  297.         // p03 = 0
  298.         if(item.p03 != 0) return error("This is not a file!");
  299.  
  300.         // p04 = offset
  301.         uint32 offset = item.p04;
  302.         if(offset == 0) return error("File offset cannot be zero.");
  303.  
  304.         // p05 = uncompressed size
  305.         uint32 size_uncompressed = item.p05;
  306.         if(size_uncompressed == 0) continue; // nothing to do
  307.  
  308.         // p06 = compressed size
  309.         uint32 size_compressed = item.p06;
  310.         bool compressed = (size_compressed > 0);
  311.  
  312.         // create filename
  313.         STDSTRING ofname = pathname;
  314.         if(pathlist1[i].length()) ofname += Unicode08ToUnicode16(pathlist1[i].c_str()).get();
  315.         else ofname += Unicode08ToUnicode16(filename.c_str()).get();
  316.  
  317.         // create savepath
  318.         STDSTRING savepath = GetPathnameFromFilename(ofname.c_str()).get();
  319.         if(!savepath.length()) return error("Invalid save path.");
  320.  
  321.         // create directories recursively
  322.         int result = SHCreateDirectoryEx(NULL, savepath.c_str(), NULL);
  323.         if(result == ERROR_SUCCESS) ;
  324.         else if(result == ERROR_FILE_EXISTS) ;
  325.         else if(result == ERROR_ALREADY_EXISTS) ;
  326.         else if(result == ERROR_BAD_PATHNAME) return error("SHCreateDirectoryExA:ERROR_BAD_PATHNAME");
  327.         else if(result == ERROR_FILENAME_EXCED_RANGE) return error("SHCreateDirectoryExA:ERROR_FILENAME_EXCED_RANGE");
  328.         else if(result == ERROR_PATH_NOT_FOUND) return error("SHCreateDirectoryExA:ERROR_PATH_NOT_FOUND");
  329.         else if(result == ERROR_CANCELLED) return error("SHCreateDirectoryExA:ERROR_CANCELLED");
  330.         else return error("Unknown SHCreateDirectoryExA error.");
  331.  
  332.         // save compressed
  333.         if(compressed)
  334.           {
  335.            // create output file
  336.            wcout << "Saving " << ofname.c_str() << endl;
  337.            ofstream ofile(ofname.c_str(), ios::binary);
  338.            if(!ofile) return error("Failed to create output file.");
  339.            
  340.            // read first two bytes
  341.            ifile.seekg(offset);
  342.            if(ifile.fail()) return error("Seek failure.");
  343.            uint08 b1 = LE_read_uint08(ifile);
  344.            uint08 b2 = LE_read_uint08(ifile);
  345.            
  346.            // read first four bytes
  347.            ifile.seekg(offset);
  348.            if(ifile.fail()) return error("Seek failure.");
  349.            uint32 test = LE_read_uint32(ifile);
  350.            
  351.            // decompress
  352.            if(isZLIB(b1, b2)) {
  353.               ZLIBINFO2 info;
  354.               info.deflatedBytes = size_compressed;
  355.               info.inflatedBytes = size_uncompressed;
  356.               info.offset = offset;
  357.               deque<ZLIBINFO2> chunkdata;
  358.               chunkdata.push_back(info);
  359.               if(!InflateZLIB(ifile, chunkdata, 0, ofile))
  360.                  return false;
  361.              }
  362.            // SEGS
  363.            else if(test == 0x73676573) {
  364.               if(!extractSEGS(ifile, (uint64)offset, ofile))
  365.                  return false;
  366.              }
  367.            else {
  368.               cout << "file #0x" << hex << i << dec << endl;
  369.               cout << "offset #0x" << hex << offset << dec << endl;
  370.               return error("Unknown format.");
  371.              }
  372.           }
  373.         // save uncompressed
  374.         else
  375.           {
  376.            // seek data
  377.            wcout << "Saving " << ofname.c_str() << endl;
  378.            ifile.seekg(offset);
  379.            if(ifile.fail()) return error("Seek failure.");
  380.            
  381.            // read data
  382.            boost::shared_array<char> data;
  383.            if(size_uncompressed) {
  384.               data.reset(new char[size_uncompressed]);
  385.               ifile.read(data.get(), size_uncompressed);
  386.               if(ifile.fail()) return error("Read failure.");
  387.              }
  388.            
  389.            // save data
  390.            ofstream ofile(ofname.c_str(), ios::binary);
  391.            if(!ofile) return error("Failed to create output file.");
  392.            if(size_uncompressed) {
  393.               ofile.write(data.get(), size_uncompressed);
  394.               if(ofile.fail()) return error("Write failure.");
  395.              }
  396.           }
  397.        }
  398.     }
  399.  
  400.  //
  401.  // PHASE #1
  402.  // PROCESS TABLE #1
  403.  //
  404.  
  405.  // create savepath
  406.  STDSTRING savepath = pathname;
  407.  savepath += TEXT("FSTS");
  408.  savepath += TEXT("\\");
  409.  CreateDirectory(savepath.c_str(), NULL);
  410.  
  411.  // loop files
  412.  for(size_t i = 0; i < table2.size(); i++)
  413.     {
  414.      // p01 = filename
  415.      DATTABLE2 item = table2[i];
  416.      ststream.seek(item.p01);
  417.      string filename = ststream.read_string();
  418.  
  419.      // p02 = 0
  420.      if(item.p02 != 0) return error("Expecting 0x00000000.");
  421.  
  422.      // p03 = offset
  423.      uint32 offset = item.p03;
  424.      if(offset == 0) return error("File offset cannot be zero.");
  425.  
  426.      // p04 = size
  427.      uint32 size = item.p04;
  428.      if(offset == 0) return error("File size cannot be zero.");
  429.  
  430.      // create output filename
  431.      STDSTRING ofname = savepath;
  432.      ofname += Unicode08ToUnicode16(filename.c_str()).get();
  433.      ofname += TEXT(".fsts");
  434.  
  435.      // seek data
  436.      wcout << "Saving " << ofname.c_str() << endl;
  437.      ifile.seekg(offset);
  438.      if(ifile.fail()) return error("Seek failure.");
  439.      
  440.      // read data
  441.      boost::shared_array<char> data;
  442.      if(size) {
  443.         data.reset(new char[size]);
  444.         ifile.read(data.get(), size);
  445.         if(ifile.fail()) return error("Read failure.");
  446.        }
  447.      
  448.      // save data
  449.      ofstream ofile(ofname.c_str(), ios::binary);
  450.      if(!ofile) return error("Failed to create output file.");
  451.      if(size) {
  452.         ofile.write(data.get(), size);
  453.         if(ofile.fail()) return error("Write failure.");
  454.        }
  455.     }
  456.  
  457.  return true;
  458. }
  459.  
  460. bool processFST(LPCTSTR filename)
  461. {
  462.  // open file
  463.  ifstream ifile(filename, ios::binary);
  464.  if(!ifile) return error("Failed to open DAT file.");
  465.  
  466.  // determine filesize
  467.  uint32 filesize = 0x00;
  468.  ifile.seekg(0, ios::end);
  469.  filesize = (uint32)ifile.tellg();
  470.  ifile.seekg(0, ios::beg);
  471.  
  472.  // filename properties
  473.  STDSTRING pathname = GetPathnameFromFilename(filename).get();
  474.  STDSTRING shrtname = GetShortFilenameWithoutExtension(filename).get();
  475.  
  476.  // read header
  477.  uint32 h01 = LE_read_uint32(ifile); // magic
  478.  uint32 h02 = LE_read_uint32(ifile); // number of items
  479.  uint32 h03 = LE_read_uint32(ifile); // offset to items
  480.  uint32 h04 = LE_read_uint32(ifile); // offset to string table
  481.  uint32 h05 = LE_read_uint32(ifile); // size of string table
  482.  uint32 h06 = LE_read_uint32(ifile); // 0x00000000
  483.  uint32 h07 = LE_read_uint32(ifile); // 0x00000000
  484.  uint32 h08 = LE_read_uint32(ifile); // 0x00000000
  485.  
  486.  // validate header
  487.  if(h01 != 0x53545346) return error("Not an FSTS file.");
  488.  if(h02 == 0x00) return true; // nothing to do
  489.  
  490.  // move to items
  491.  ifile.seekg(h03);
  492.  if(ifile.fail()) return error("Seek failure.");
  493.  
  494.  // read items
  495.  std::deque<FSTSITEM> itemlist;
  496.  for(uint32 i = 0; i < h02; i++) {
  497.      FSTSITEM item;
  498.      item.p01 = LE_read_uint32(ifile);
  499.      item.p02 = LE_read_uint32(ifile);
  500.      item.p03 = LE_read_uint32(ifile);
  501.      item.p04 = LE_read_uint32(ifile);
  502.      itemlist.push_back(item);
  503.     }
  504.  
  505.  // move to string table
  506.  ifile.seekg(h04);
  507.  if(ifile.fail()) return error("Seek failure.");
  508.  
  509.  // read string table into binary stream
  510.  boost::shared_array<char> stringtable;
  511.  if(h05) {
  512.     stringtable.reset(new char[h05]);
  513.     ifile.read(stringtable.get(), h05);
  514.     if(ifile.fail()) return error("Read failure.");
  515.    }
  516.  
  517.  // process items
  518.  binary_stream bs(stringtable, h05); 
  519.  for(size_t i = 0; i < itemlist.size(); i++)
  520.     {
  521.      // p01 = filename
  522.      bs.seek(itemlist[i].p01);
  523.      string filename = bs.read_string();
  524.  
  525.      // replace '/' with '\' as mixing gives SHCreateDirectoryEx trouble
  526.      for(uint32 j = 0; j < filename.length(); j++)
  527.          if(filename[j] == '/') filename[j] = '\\';
  528.  
  529.      // p02 = offset
  530.      uint32 offset = itemlist[i].p02;
  531.      if(offset == 0) return error("File offset cannot be zero.");
  532.  
  533.      // p03 = uncompressed size
  534.      uint32 size_uncompressed = itemlist[i].p03;
  535.      if(size_uncompressed == 0) continue; // nothing to do
  536.  
  537.      // p04 = compressed size
  538.      uint32 size_compressed = itemlist[i].p04;
  539.      bool compressed = (size_compressed > 0);
  540.  
  541.      // create filename
  542.      STDSTRING ofname = pathname;
  543.      ofname += Unicode08ToUnicode16(filename.c_str()).get();
  544.  
  545.      // create savepath
  546.      STDSTRING savepath = GetPathnameFromFilename(ofname.c_str()).get();
  547.      if(!savepath.length()) return error("Invalid save path.");
  548.  
  549.      // create directories recursively
  550.      int result = SHCreateDirectoryEx(NULL, savepath.c_str(), NULL);
  551.      if(result == ERROR_SUCCESS) ;
  552.      else if(result == ERROR_FILE_EXISTS) ;
  553.      else if(result == ERROR_ALREADY_EXISTS) ;
  554.      else if(result == ERROR_BAD_PATHNAME) return error("SHCreateDirectoryExA:ERROR_BAD_PATHNAME");
  555.      else if(result == ERROR_FILENAME_EXCED_RANGE) return error("SHCreateDirectoryExA:ERROR_FILENAME_EXCED_RANGE");
  556.      else if(result == ERROR_PATH_NOT_FOUND) return error("SHCreateDirectoryExA:ERROR_PATH_NOT_FOUND");
  557.      else if(result == ERROR_CANCELLED) return error("SHCreateDirectoryExA:ERROR_CANCELLED");
  558.      else return error("Unknown SHCreateDirectoryExA error.");
  559.  
  560.      // save compressed
  561.      if(compressed)
  562.        {
  563.         // create output file
  564.         wcout << "Saving " << ofname.c_str() << endl;
  565.         ofstream ofile(ofname.c_str(), ios::binary);
  566.         if(!ofile) return error("Failed to create output file.");
  567.         
  568.         // read first two bytes
  569.         ifile.seekg(offset);
  570.         if(ifile.fail()) return error("Seek failure.");
  571.         uint08 b1 = LE_read_uint08(ifile);
  572.         uint08 b2 = LE_read_uint08(ifile);
  573.         
  574.         // read first four bytes
  575.         ifile.seekg(offset);
  576.         if(ifile.fail()) return error("Seek failure.");
  577.         uint32 test = LE_read_uint32(ifile);
  578.         
  579.         // decompress
  580.         if(isZLIB(b1, b2)) {
  581.            ZLIBINFO2 info;
  582.            info.deflatedBytes = size_compressed;
  583.            info.inflatedBytes = size_uncompressed;
  584.            info.offset = offset;
  585.            deque<ZLIBINFO2> chunkdata;
  586.            chunkdata.push_back(info);
  587.            if(!InflateZLIB(ifile, chunkdata, 0, ofile))
  588.               return false;
  589.           }
  590.         // SEGS
  591.         else if(test == 0x73676573) {
  592.            if(!extractSEGS(ifile, offset, ofile))
  593.               return false;
  594.           }
  595.         else {
  596.            cout << "file #0x" << hex << i << dec << endl;
  597.            cout << "offset #0x" << hex << offset << dec << endl;
  598.            return error("Unknown format.");
  599.           }
  600.        }
  601.      // save uncompressed
  602.      else
  603.        {
  604.         // seek data
  605.         wcout << "Saving " << ofname.c_str() << endl;
  606.         ifile.seekg(offset);
  607.         if(ifile.fail()) return error("Seek failure.");
  608.         
  609.         // read data
  610.         boost::shared_array<char> data;
  611.         if(size_uncompressed) {
  612.            data.reset(new char[size_uncompressed]);
  613.            ifile.read(data.get(), size_uncompressed);
  614.            if(ifile.fail()) return error("Read failure.");
  615.           }
  616.         
  617.         // save data
  618.         ofstream ofile(ofname.c_str(), ios::binary);
  619.         if(!ofile) return error("Failed to create output file.");
  620.         if(size_uncompressed) {
  621.            ofile.write(data.get(), size_uncompressed);
  622.            if(ofile.fail()) return error("Write failure.");
  623.           }
  624.        }
  625.     }
  626.  
  627.  return true;
  628. }
  629.  
  630. };};
  631.  
  632. //
  633. // TEXTURES
  634. //
  635.  
  636. namespace X_SYSTEM { namespace X_GAME {
  637.  
  638. bool processGFP(LPCTSTR filename)
  639. {
  640.  // open file
  641.  ifstream ifile(filename, ios::binary);
  642.  if(!ifile) return error("Failed to open DAT file.");
  643.  
  644.  // determine filesize
  645.  uint32 filesize = 0x00;
  646.  ifile.seekg(0, ios::end);
  647.  filesize = (uint32)ifile.tellg();
  648.  ifile.seekg(0, ios::beg);
  649.  
  650.  // filename properties
  651.  STDSTRING pathname = GetPathnameFromFilename(filename).get();
  652.  STDSTRING shrtname = GetShortFilenameWithoutExtension(filename).get();
  653.  
  654.  // create savepath
  655.  STDSTRING savepath = pathname;
  656.  savepath += shrtname;
  657.  savepath += TEXT("\\");
  658.  CreateDirectory(savepath.c_str(), NULL);
  659.  
  660.  // loop forever counting .GFP chunks
  661.  uint32 index = 0;
  662.  for(;;)
  663.     {
  664.      // save position
  665.      uint32 position = (uint32)ifile.tellg();
  666.      if(ifile.eof() || ifile.fail()) break;
  667.  
  668.      // read header
  669.      uint32 h01 = LE_read_uint32(ifile); // magic
  670.      uint32 h02 = LE_read_uint32(ifile); // version (2.00)
  671.      if(ifile.eof() || ifile.fail()) break;
  672.  
  673.      // validate header
  674.      if(h01 != 0x5046472E) return error("Not a GFP file.");
  675.      if(h02 != 0x30302E32) return error("Invalid GFP version.");
  676.  
  677.      // read first entry
  678.      uint32 p01 = LE_read_uint32(ifile); // DDS size (all images)
  679.      uint32 p02 = LE_read_uint32(ifile); // DDS size (1st image)
  680.      uint32 p03 = LE_read_uint32(ifile); // 0x20
  681.      uint32 p04 = LE_read_uint32(ifile); // offset from .GFP to first DDS
  682.      uint16 p05 = LE_read_uint16(ifile); // 0x0002 (sum these to get number of total DDS)
  683.      uint16 p06 = LE_read_uint16(ifile); // 0x0002 (sum these to get number of total DDS)
  684.      uint16 p07 = LE_read_uint16(ifile); // 0x0000 (sum these to get number of total DDS)
  685.      uint16 p08 = LE_read_uint16(ifile); // 0x0001 (sum these to get number of total DDS)
  686.  
  687.      // compute number of files
  688.      uint32 n_files = p04 / 0x18;
  689.      if(n_files != (p05 + p06 + p07 + p08)) return error("Incorrect number of files.");
  690.  
  691.      // append 1st file information
  692.      typedef std::pair<uint32,uint32> pair_t;
  693.      std::deque<pair_t> filelist;
  694.      filelist.push_back(pair_t(position + p04, p02));
  695.  
  696.      // append other file information
  697.      for(uint32 i = 0; i < n_files - 1; i++) {
  698.          uint32 p01 = LE_read_uint32(ifile); // offset from .GFP to DDS
  699.          uint32 p02 = LE_read_uint32(ifile); // DDS size
  700.          uint16 p03 = LE_read_uint16(ifile); // unknown
  701.          uint16 p04 = LE_read_uint16(ifile); // unknown
  702.          uint16 p05 = LE_read_uint16(ifile); // unknown
  703.          uint16 p06 = LE_read_uint16(ifile); // unknown
  704.          uint16 p07 = LE_read_uint16(ifile); // unknown
  705.          uint16 p08 = LE_read_uint16(ifile); // unknown
  706.          uint16 p09 = LE_read_uint16(ifile); // unknown
  707.          uint16 p10 = LE_read_uint16(ifile); // unknown
  708.          filelist.push_back(pair_t(position + p01, p02));
  709.         }
  710.  
  711.      // read DDS files
  712.      for(uint32 i = 0; i < n_files; i++)
  713.         {
  714.          // move to offset
  715.          uint32 offset = filelist[i].first;
  716.          ifile.seekg(offset);
  717.          if(ifile.fail()) return error("Seek failed.");
  718.  
  719.          // read data
  720.          uint32 size = filelist[i].second;
  721.          boost::shared_array<char> data(new char[size]);
  722.          ifile.read(data.get(), size);
  723.          if(ifile.fail()) return error("Read failed.");
  724.  
  725.          // create filename
  726.          STDSTRINGSTREAM ss;
  727.          ss << savepath;
  728.          ss << setfill(TEXT('0')) << setw(2) << index;
  729.          ss << TEXT("_");
  730.          ss << setfill(TEXT('0')) << setw(2) << i;
  731.          ss << TEXT(".dds");
  732.  
  733.          // create output file
  734.          ofstream ofile(ss.str().c_str(), ios::binary);
  735.          if(!ofile) return error("Failed to create output file.");
  736.  
  737.          // save data
  738.          ofile.write(data.get(), size);
  739.          if(ofile.fail()) return error("Write failure.");
  740.         }
  741.  
  742.      // move to next .GFP section
  743.      ifile.seekg((position + p01), ios::beg);
  744.      if(ifile.eof() || ifile.fail()) break;
  745.  
  746.      // increment count
  747.      index++;
  748.     }
  749.  
  750.  // success
  751.  return true;
  752. }
  753.  
  754. };};
  755.  
  756. //
  757. // MODELS
  758. //
  759.  
  760. namespace X_SYSTEM { namespace X_GAME {
  761.  
  762. class MDLProcess {
  763.  private :
  764.   STDSTRING filename;
  765.   STDSTRING pathname;
  766.   STDSTRING shrtname;
  767.  private :
  768.   std::ifstream ifile;
  769.   std::ofstream ofile;
  770.   std::ofstream dfile;
  771.  private :
  772.   binary_stream bs;
  773.   ADVANCEDMODELCONTAINER amc;
  774.  private :
  775.   bool processHLDM(void);
  776.   bool process_LDM(void);
  777.   bool processHRTM(void);
  778.   bool process_XET(void);
  779.   bool processHARF(void);
  780.   bool processMARF(void);
  781.   bool processLKSE(void);
  782.   bool process2MDB(void);
  783.   bool process2HMG(void);
  784.   bool process_2MG(uint32 index);
  785.   bool processTPMG(void);
  786.   bool processHMTA(void);
  787.   bool processDMBS(void);
  788.   bool processADOL(void);
  789.   bool processDONE(void);
  790.  public :
  791.   bool extract(LPCTSTR filename)
  792.   {
  793.    // open file
  794.    ifile.open(filename, ios::binary);
  795.    if(!ifile) return error("Failed to open file.");
  796.  
  797.    // determine filesize
  798.    uint32 filesize = 0x00;
  799.    ifile.seekg(0, ios::end);
  800.    filesize = (uint32)ifile.tellg();
  801.    ifile.seekg(0, ios::beg);
  802.    if(filesize < 0x10) return true; // nothing to do
  803.   
  804.    // filename properties
  805.    this->filename = filename;
  806.    pathname = GetPathnameFromFilename(filename).get();
  807.    shrtname = GetShortFilenameWithoutExtension(filename).get();
  808.  
  809.    // open debug file
  810.    if(debug) {
  811.       STDSTRING dfname = pathname;
  812.       dfname += shrtname;
  813.       dfname += TEXT(".txt");
  814.       dfile.open(dfname.c_str());
  815.       if(!dfile) return error("Failed to create debug file.");
  816.      }
  817.  
  818.    // read entire file into memory
  819.    boost::shared_array<char> data(new char[filesize]);
  820.    ifile.read(data.get(), filesize);
  821.    if(ifile.fail()) return error("Read failure.");
  822.  
  823.    // process chunks in following order
  824.    bs = binary_stream(data, filesize);
  825.    if(!processHLDM()) return false; // required
  826.    if(!process_LDM()) return false; // required
  827.    if(!processHRTM()) return false; // required
  828.    if(!process_XET()) return false; // required
  829.    if(!processHARF()) return false; // required
  830.    if(!processLKSE()) return false; // required
  831.    if(!process2MDB()) return false; // required
  832.    if(!process2HMG()) return false; // required
  833.    if(!processHMTA()) return false; // required
  834.    if(!processDMBS()) return false; // optional
  835.    if(!processADOL()) return false; // required
  836.    if(!processDONE()) return false; // required
  837.  
  838.    // save model
  839.    SaveAMC(pathname.c_str(), shrtname.c_str(), amc);
  840.    SaveOBJ(pathname.c_str(), shrtname.c_str(), amc);
  841.  
  842.    // success
  843.    return true;
  844.   }
  845.  public :
  846.   MDLProcess() {}
  847.  ~MDLProcess() {}
  848. };
  849.  
  850. bool MDLProcess::processHLDM(void)
  851. {
  852.  // read header
  853.  uint32 h01 = bs.BE_read_uint32(); // HLDM
  854.  uint32 h02 = bs.BE_read_uint32(); // unknown
  855.  uint32 h03 = bs.BE_read_uint32(); // unknown
  856.  uint32 h04 = bs.BE_read_uint32(); // unknown
  857.  
  858.  // validate header
  859.  if(h01 != 0x484C444D) return error("Invalid HLDM.");
  860.  if(h02 != 0x08) return error("HLDM h02 expecting 0x08.");
  861.  if(h03 != 0x01) return error("HLDM h03 expecting 0x01.");
  862.  if(h04 != 0x08) return error("HLDM h04 expecting 0x08.");
  863.  
  864.  // success
  865.  return true;
  866. }
  867.  
  868. bool MDLProcess::process_LDM(void)
  869. {
  870.  // read header
  871.  uint32 h01 = bs.BE_read_uint32(); // _LDM
  872.  uint32 h02 = bs.BE_read_uint32(); // 0x00000001
  873.  
  874.  // validate header
  875.  if(h01 != 0x5F4C444D) return error("Invalid _LDM.");
  876.  if(h02 != 0x01) return error("_LDM h02 expecting 0x01.");
  877.  
  878.  return true;
  879. }
  880.  
  881. bool MDLProcess::processHRTM(void)
  882. {
  883.  // read header
  884.  uint32 h01 = bs.BE_read_uint32(); // HRTM
  885.  uint32 h02 = bs.BE_read_uint32(); // size of chunk minus 0x10-byte header
  886.  uint32 h03 = bs.BE_read_uint32(); // 0x01
  887.  uint32 h04 = bs.BE_read_uint32(); // 0x04
  888.  
  889.  // validate header
  890.  if(h01 != 0x4852544D) return error("Invalid HRTM.");
  891.  if(h02 == 0x00) return error("Invalid HRTM chunk.");
  892.  if(h03 != 0x01) return error("HRTM h03 expecting 0x01.");
  893.  if(h04 != 0x04) return error("HRTM h04 expecting 0x04.");
  894.  
  895.  // next
  896.  // uint32 n - number of subchunks
  897.  // data - n LRTM subchunks
  898.  // LRTM appears to be shading and lighting information
  899.  
  900.  // skip past data for now
  901.  bs.move(h02);
  902.  if(bs.fail()) return error("Stream seek failure.");
  903.  
  904.  return true;
  905. }
  906.  
  907. bool MDLProcess::process_XET(void)
  908. {
  909.  // read header
  910.  uint32 h01 = bs.BE_read_uint32(); // _XET
  911.  uint32 h02 = bs.BE_read_uint32(); // size of chunk minus 0x10-byte header
  912.  uint32 h03 = bs.BE_read_uint32(); // number of textures
  913.  uint32 h04 = bs.BE_read_uint32(); // size of texture item (0x104)
  914.  
  915.  // validate header
  916.  if(h01 != 0x20584554) return error("Invalid _XET.");
  917.  if(h04 == 0x00) return error("_XET h04 > 0."); 
  918.  
  919.  // save position
  920.  auto position = bs.tell();
  921.  if(bs.fail()) return error("Stream tell failure.");
  922.  
  923.  // allocate text buffer
  924.  boost::shared_array<char> buffer(new char[h04]);
  925.  
  926.  // for each texture
  927.  for(uint32 i = 0; i < h03; i++) {
  928.      // read string
  929.      bs.read(buffer.get(), h04);
  930.      if(bs.fail()) return error("Stream read failure.");
  931.      // save string
  932.      AMC_IMAGEFILE item;
  933.      item.filename = buffer.get();
  934.      amc.iflist.push_back(item);
  935.     }
  936.  
  937.  // BEGIN DEBUG
  938.  if(debug) {
  939.     dfile << "----------" << endl;
  940.     dfile << " TEXTURES " << endl;
  941.     dfile << "----------" << endl;
  942.     dfile << endl;
  943.     for(uint32 i = 0; i < amc.iflist.size(); i++) {
  944.         dfile << "[0x" << setfill('0') << setw(2) << i << "]: ";
  945.         dfile << amc.iflist[i].filename.c_str() << endl;
  946.        }
  947.     dfile << endl;
  948.    }
  949.  // END DEBUG
  950.  
  951.  // skip past data
  952.  bs.seek(position + h02);
  953.  if(bs.fail()) return error("Stream seek failure.");
  954.  
  955.  return true;
  956. }
  957.  
  958. bool MDLProcess::processHARF(void)
  959. {
  960.  // read header
  961.  uint32 h01 = bs.BE_read_uint32(); // HARF
  962.  uint32 h02 = bs.BE_read_uint32(); // size of chunk minus 0x10-byte header
  963.  uint32 h03 = bs.BE_read_uint32(); // unknown 0x01
  964.  uint32 h04 = bs.BE_read_uint32(); // unknown 0x04
  965.  if(bs.fail()) return error("Stream read failure.");
  966.  
  967.  // validate header
  968.  if(h01 != 0x48415246) return error("Invalid HARF.");
  969.  if(h03 != 0x01) return error("HARF h03 expecting 0x01.");
  970.  if(h04 != 0x04) return error("HARF h04 expecting 0x04.");
  971.  
  972.  // save position
  973.  auto position = bs.tell();
  974.  if(bs.fail()) return error("Stream tell failure.");
  975.  
  976.  // read number of MARFS
  977.  uint32 n_MARF = bs.BE_read_uint32();
  978.  if(bs.fail()) return error("Stream read failure.");
  979.  
  980.  // read MARF chunks
  981.  for(uint32 i = 0; i < n_MARF; i++)
  982.      if(!processMARF()) return false;
  983.  
  984.  // skip past data
  985.  bs.seek(position + h02);
  986.  if(bs.fail()) return error("Stream seek failure.");
  987.  
  988.  return true;
  989. }
  990.  
  991. bool MDLProcess::processMARF(void)
  992. {
  993.  // read header
  994.  uint32 h01 = bs.BE_read_uint32(); // MARF
  995.  uint32 h02 = bs.BE_read_uint32(); // size of chunk minus 0x10-byte header
  996.  uint32 h03 = bs.BE_read_uint32(); // unknown 0x01
  997.  uint32 h04 = bs.BE_read_uint32(); // size of chunk minus 0x10-byte header
  998.  if(bs.fail()) return error("Stream read failure.");
  999.  
  1000.  // validate header
  1001.  if(h01 != 0x4D415246) return error("Invalid MARF.");
  1002.  if(h02 != 0xF8) return error("MARF expecting h02 == 0xF8.");
  1003.  if(h03 != 0x01) return error("MARF h03 expecting 0x01.");
  1004.  if(h02 != h04) return error("MARF expecting h02 == h04.");
  1005.  
  1006.  // save position
  1007.  auto position = bs.tell();
  1008.  if(bs.fail()) return error("Stream tell failure.");
  1009.  
  1010.  // struct MARFDATA {
  1011.  //  uint32 p01;     // unknown
  1012.  //  char p02[0x24]; // name
  1013.  //  uint32 p03;     // unknown
  1014.  //  uint32 p04;     // unknown
  1015.  //  uint32 p05;     // always 0xFFFFFFFF
  1016.  // };
  1017.  
  1018.  // skip past data
  1019.  bs.seek(position + h02);
  1020.  if(bs.fail()) return error("Stream seek failure.");
  1021.  
  1022.  return true;
  1023. }
  1024.  
  1025. bool MDLProcess::processLKSE(void)
  1026. {
  1027.  // read header
  1028.  uint32 h01 = bs.BE_read_uint32(); // LKSE
  1029.  uint32 h02 = bs.BE_read_uint32(); // size of chunk minus 0x10-byte header
  1030.  uint32 h03 = bs.BE_read_uint32(); // unknown 0x01
  1031.  uint32 h04 = bs.BE_read_uint32(); // size of chunk minus 0x10-byte header
  1032.  
  1033.  // validate header
  1034.  if(h01 != 0x4C4B5345) return error("Invalid LKSE.");
  1035.  if(h03 != 0x01) return error("LKSE h03 expecting 0x01.");
  1036.  if(h02 != h04) return error("LKSE h02 is not same as h04.");
  1037.  
  1038.  // save position
  1039.  auto position = bs.tell();
  1040.  if(bs.fail()) return error("Stream tell failure.");
  1041.  
  1042.  // read ES00 header (0x40 bytes)
  1043.  uint32 p01 = bs.BE_read_uint32(); // ES00
  1044.  uint32 p02 = bs.BE_read_uint32(); // offset from ES00 to past index data
  1045.  uint32 p03 = bs.BE_read_uint32(); // offset from ES00 to end
  1046.  uint16 p04 = bs.BE_read_uint16(); // number of matrices, indices and 4-byte garbage
  1047.  uint16 p05 = bs.BE_read_uint16(); // unknown
  1048.  uint16 p06 = bs.BE_read_uint16(); // number of 0x10-byte pairs
  1049.  uint16 p07 = bs.BE_read_uint16(); // unknown
  1050.  uint32 p08 = bs.BE_read_uint32(); // unknown
  1051.  uint32 p09 = bs.BE_read_uint32(); // unknown
  1052.  uint32 p10 = bs.BE_read_uint32(); // unknown
  1053.  uint32 p11 = bs.BE_read_uint32(); // unknown
  1054.  uint32 p12 = bs.BE_read_uint32(); // unknown
  1055.  uint32 p13 = bs.BE_read_uint32(); // unknown
  1056.  uint32 p14 = bs.BE_read_uint32(); // 0x00000000
  1057.  
  1058.  // read ES000 0x10-byte indices
  1059.  boost::shared_array<boost::shared_array<uint16>> part1;
  1060.  if(p06) {
  1061.     part1.reset(new boost::shared_array<uint16>[p06]);
  1062.     for(uint32 i = 0; i < p06; i++) {
  1063.         part1[i].reset(new uint16[8]);
  1064.         bs.BE_read_array(part1[i].get(), 8);
  1065.         if(bs.fail()) return error("Stream read failure.");
  1066.        }
  1067.    }
  1068.  
  1069.  // read ES000 0x30-byte floats
  1070.  boost::shared_array<boost::shared_array<real32>> part2;
  1071.  if(p04) {
  1072.     part2.reset(new boost::shared_array<real32>[p04]);
  1073.     for(uint32 i = 0; i < p04; i++) {
  1074.         part2[i].reset(new real32[12]);
  1075.         bs.BE_read_array(part2[i].get(), 12);
  1076.         if(bs.fail()) return error("Stream read failure.");
  1077.        }
  1078.    }
  1079.  
  1080.  // read ES000 0x02-byte indices
  1081.  boost::shared_array<uint16> part3;
  1082.  if(p04) {
  1083.     part3.reset(new uint16[p04]);
  1084.     for(uint32 i = 0; i < p04; i++) {
  1085.         part3[i] = bs.BE_read_uint16();
  1086.         if(bs.fail()) return error("Stream read failure.");
  1087.        }
  1088.    }
  1089.  
  1090.  // move to part 4
  1091.  bs.seek(position + p02);
  1092.  if(bs.fail()) return error("Stream seek failure.");
  1093.  
  1094.  // read ES000 0x04-byte data (floats?)
  1095.  boost::shared_array<uint32> part4;
  1096.  if(p04) {
  1097.     part4.reset(new uint32[p04]);
  1098.     for(uint32 i = 0; i < p04; i++) {
  1099.         part4[i] = bs.BE_read_uint32();
  1100.         if(bs.fail()) return error("Stream read failure.");
  1101.        }
  1102.    }
  1103.  
  1104.  // read ES000 part 5
  1105.  boost::shared_array<uint32> part5A;
  1106.  boost::shared_array<uint08> part5B;
  1107.  if(p05) {
  1108.     part5A.reset(new uint32[p05 * 2]);
  1109.     part5B.reset(new uint08[p05]);
  1110.     for(uint32 i = 0; i < p05; i++) {
  1111.         part5A[2*i + 0] = bs.BE_read_uint32();
  1112.         part5A[2*i + 1] = bs.BE_read_uint32();
  1113.        }
  1114.     for(uint32 i = 0; i < p05; i++) {
  1115.         part5B[i] = bs.BE_read_uint08();
  1116.        }
  1117.    }
  1118.  
  1119.  // BEGIN DEBUG
  1120.  if(debug) {
  1121.     dfile << "-----------" << endl;
  1122.     dfile << " LKSE:ES00 " << endl;
  1123.     dfile << "-----------" << endl;
  1124.     dfile << endl;
  1125.  
  1126.     dfile << "p01 = 0x" << setfill('0') << hex << setw(8) << p01 << dec << endl;
  1127.     dfile << "p02 = 0x" << setfill('0') << hex << setw(8) << p02 << dec << endl;
  1128.     dfile << "p03 = 0x" << setfill('0') << hex << setw(8) << p03 << dec << endl;
  1129.     dfile << "p04 = 0x" << setfill('0') << hex << setw(4) << p04 << dec << endl;
  1130.     dfile << "p05 = 0x" << setfill('0') << hex << setw(4) << p05 << dec << endl;
  1131.     dfile << "p06 = 0x" << setfill('0') << hex << setw(4) << p06 << dec << endl;
  1132.     dfile << "p07 = 0x" << setfill('0') << hex << setw(4) << p07 << dec << endl;
  1133.     dfile << "p08 = 0x" << setfill('0') << hex << setw(8) << p08 << dec << endl;
  1134.     dfile << "p09 = 0x" << setfill('0') << hex << setw(8) << p09 << dec << endl;
  1135.     dfile << "p10 = 0x" << setfill('0') << hex << setw(8) << p10 << dec << endl;
  1136.     dfile << "p11 = 0x" << setfill('0') << hex << setw(8) << p11 << dec << endl;
  1137.     dfile << "p12 = 0x" << setfill('0') << hex << setw(8) << p12 << dec << endl;
  1138.     dfile << "p13 = 0x" << setfill('0') << hex << setw(8) << p13 << dec << endl;
  1139.     dfile << "p14 = 0x" << setfill('0') << hex << setw(8) << p14 << dec << endl;
  1140.     dfile << endl;
  1141.  
  1142.     for(uint32 i = 0; i < p06; i++) {
  1143.         dfile << "[0x" << setfill('0') << setw(2) << hex << i << dec << "]: ";
  1144.         for(uint32 j = 0; j < 8; j++)
  1145.             dfile << setfill('0') << "0x" << hex << setw(4) << part1[i][j] << dec << " ";
  1146.         dfile << endl;
  1147.        }
  1148.     dfile << endl;
  1149.  
  1150.     for(uint32 i = 0; i < p04; i++) {
  1151.         dfile << "[0x" << setfill('0') << setw(2) << hex << i << dec << "]: ";
  1152.         for(uint32 j = 0; j < 12; j++) {
  1153.             uint32 temp = interpret_as_uint32(part2[i][j]);
  1154.             dfile << setfill('0') << "0x" << hex << setw(8) << temp << dec << " ";
  1155.            }
  1156.         dfile << endl;
  1157.        }
  1158.     dfile << endl;
  1159.  
  1160.     for(uint32 i = 0; i < p04; i++) {
  1161.         dfile << "[0x" << setfill('0') << setw(2) << hex << i << dec << "]: ";
  1162.         dfile << setfill('0') << "0x" << hex << setw(4) << part3[i] << dec << " ";
  1163.         dfile << endl;
  1164.        }
  1165.     dfile << endl;
  1166.  
  1167.     for(uint32 i = 0; i < p04; i++) {
  1168.         dfile << "[0x" << setfill('0') << setw(2) << hex << i << dec << "]: ";
  1169.         dfile << setfill('0') << "0x" << hex << setw(8) << part4[i] << dec << " ";
  1170.         dfile << endl;
  1171.        }
  1172.     dfile << endl;
  1173.  
  1174.     // part 5
  1175.     if(p05) {
  1176.        for(uint32 i = 0; i < p05; i++) {
  1177.            dfile << "[0x" << setfill('0') << setw(2) << hex << i << dec << "]: ";
  1178.            dfile << "0x" << hex << setw(8) << part5A[2*i] << ", 0x" << part5A[2*i + 1] << dec << " - ";
  1179.            dfile << "0x" << hex << setw(2) << (uint16)part5B[i] << dec << " ";
  1180.            dfile << endl;
  1181.           }
  1182.        dfile << endl;
  1183.       }
  1184.    }
  1185.  // END DEBUG
  1186.  
  1187.  // skip past data
  1188.  bs.seek(position + h02);
  1189.  if(bs.fail()) return error("Stream seek failure.");
  1190.  
  1191.  return true;
  1192. }
  1193.  
  1194. bool MDLProcess::process2MDB(void)
  1195. {
  1196.  // read header
  1197.  uint32 h01 = bs.BE_read_uint32(); // 2MDB
  1198.  uint32 h02 = bs.BE_read_uint32(); // size of chunk minus 0x10-byte header
  1199.  uint32 h03 = bs.BE_read_uint32(); // unknown 0x00
  1200.  uint32 h04 = bs.BE_read_uint32(); // unknown 0x00
  1201.  
  1202.  // validate header
  1203.  if(h01 != 0x324D4442) return error("Invalid 2MDB.");
  1204.  if(h02 != 0x30) return error("2MDB h02 expecting 0x30.");
  1205.  if(h03 != 0x00) return error("2MDB h03 expecting 0x00.");
  1206.  if(h04 != 0x00) return error("2MDB h04 expecting 0x00.");
  1207.  
  1208.  // save position
  1209.  auto position = bs.tell();
  1210.  if(bs.fail()) return error("Stream tell failure.");
  1211.  
  1212.  // read floats
  1213.  real32 p1[3] = {
  1214.   bs.BE_read_real32(),
  1215.   bs.BE_read_real32(),
  1216.   bs.BE_read_real32()
  1217.  };
  1218.  real32 p2[3] = {
  1219.   bs.BE_read_real32(),
  1220.   bs.BE_read_real32(),
  1221.   bs.BE_read_real32()
  1222.  };
  1223.  real32 p3[3] = {
  1224.   bs.BE_read_real32(),
  1225.   bs.BE_read_real32(),
  1226.   bs.BE_read_real32()
  1227.  };
  1228.  real32 p4[3] = {
  1229.   bs.BE_read_real32(),
  1230.   bs.BE_read_real32(),
  1231.   bs.BE_read_real32()
  1232.  };
  1233.  
  1234.  // BEGIN DEBUG
  1235.  if(debug) {
  1236.     dfile << "------------" << endl;
  1237.     dfile << " 2MDB CHUNK " << endl;
  1238.     dfile << "------------" << endl;
  1239.     dfile << endl;
  1240.     dfile << "p1 = <" << p1[0] << ", " << p1[1] << ", " << p1[2] << ">" << endl;
  1241.     dfile << "p2 = <" << p2[0] << ", " << p2[1] << ", " << p2[2] << ">" << endl;
  1242.     dfile << "p3 = <" << p3[0] << ", " << p3[1] << ", " << p3[2] << ">" << endl;
  1243.     dfile << "p4 = <" << p4[0] << ", " << p4[1] << ", " << p4[2] << ">" << endl;
  1244.     dfile << endl;
  1245.    }
  1246.  // END DEBUG
  1247.  
  1248.  // skip past data
  1249.  bs.seek(position + h02);
  1250.  if(bs.fail()) return error("Stream seek failure.");
  1251.  
  1252.  return true;
  1253. }
  1254.  
  1255. bool MDLProcess::process2HMG(void)
  1256. {
  1257.  // read header
  1258.  uint32 h01 = bs.BE_read_uint32(); // 2HMG
  1259.  uint32 h02 = bs.BE_read_uint32(); // size of chunk minus 0x10-byte header
  1260.  uint32 h03 = bs.BE_read_uint32(); // number of _2MG chunks
  1261.  uint32 h04 = bs.BE_read_uint32(); // unknown 0x00
  1262.  
  1263.  // BEGIN DEBUG
  1264.  if(debug) {
  1265.     dfile << "------------" << endl;
  1266.     dfile << " 2HMG CHUNK " << endl;
  1267.     dfile << "------------" << endl;
  1268.     dfile << endl;
  1269.     dfile << "h01 = 0x" << setfill('0') << setw(8) << hex << h01 << dec << " 2HMG" << endl;
  1270.     dfile << "h02 = 0x" << setfill('0') << setw(8) << hex << h02 << dec << " size of chunk minus 0x10-byte header" << endl;
  1271.     dfile << "h03 = 0x" << setfill('0') << setw(8) << hex << h03 << dec << " number of _2MG chunks" << endl;
  1272.     dfile << "h04 = 0x" << setfill('0') << setw(8) << hex << h04 << dec << " 0x00000000" << endl;
  1273.     dfile << endl;
  1274.    }
  1275.  // END DEBUG
  1276.  
  1277.  // validate header
  1278.  if(h01 != 0x32484D47) return error("Invalid 2HMG.");
  1279.  if(h04 != 0x00) return error("2HMG h04 expecting 0x00.");
  1280.  
  1281.  // save position
  1282.  auto position = bs.tell();
  1283.  if(bs.fail()) return error("Stream tell failure.");
  1284.  
  1285.  // process each mesh
  1286.  for(uint32 i = 0; i < h03; i++)
  1287.      if(!process_2MG(i)) return false;
  1288.  
  1289.  // skip past data
  1290.  bs.seek(position + h02);
  1291.  if(bs.fail()) return error("Stream seek failure.");
  1292.  
  1293.  return true;
  1294. }
  1295.  
  1296. bool MDLProcess::process_2MG(uint32 index)
  1297. {
  1298.  // read header
  1299.  uint32 h01 = bs.BE_read_uint32(); // _2MG
  1300.  uint32 h02 = bs.BE_read_uint32(); // size of chunk minus 0x10-byte header
  1301.  uint32 h03 = bs.BE_read_uint32(); // number of TPMG chunks
  1302.  uint32 h04 = bs.BE_read_uint32(); // unknown 0x00
  1303.  
  1304.  // validate header
  1305.  if(h01 != 0x20324D47) return error("Invalid _2MG.");
  1306.  if(h04 != 0x00) return error("_2MG h04 expecting 0x00.");
  1307.  
  1308.  // BEGIN DEBUG
  1309.  if(debug) {
  1310.     dfile << "------------" << endl;
  1311.     dfile << " _2MG CHUNK " << endl;
  1312.     dfile << "------------" << endl;
  1313.     dfile << endl;
  1314.     dfile << "_2MG index = 0x" << setfill('0') << setw(8) << hex << index << dec << endl;
  1315.     dfile << "h01 = 0x" << setfill('0') << setw(8) << hex << h01 << dec << " _2MG" << endl;
  1316.     dfile << "h02 = 0x" << setfill('0') << setw(8) << hex << h02 << dec << " size of chunk minus 0x10-byte header" << endl;
  1317.     dfile << "h03 = 0x" << setfill('0') << setw(4) << hex << h03 << dec << " number of TPMG chunks" << endl;
  1318.     dfile << "h04 = 0x" << setfill('0') << setw(8) << hex << h04 << dec << " 0x00000000" << endl;
  1319.     dfile << endl;
  1320.    }
  1321.  // END DEBUG
  1322.  
  1323.  // save position
  1324.  auto position = bs.tell();
  1325.  if(bs.fail()) return error("Stream tell failure.");
  1326.  
  1327.  // read string
  1328.  char p01[0x30];
  1329.  bs.read(&p01[0], 0x28);
  1330.  if(bs.fail()) return error("Stream read failure.");
  1331.  
  1332.  // read unknown
  1333.  uint32 p02 = bs.BE_read_uint32();
  1334.  if(bs.fail()) return error("Stream read failure.");
  1335.  if(p02 != h03) return error("_2MG p02 is not same as h03.");
  1336.  
  1337.  // read floats
  1338.  real32 p03[3] = {
  1339.   bs.BE_read_real32(),
  1340.   bs.BE_read_real32(),
  1341.   bs.BE_read_real32()
  1342.  };
  1343.  real32 p04[3] = {
  1344.   bs.BE_read_real32(),
  1345.   bs.BE_read_real32(),
  1346.   bs.BE_read_real32()
  1347.  };
  1348.  real32 p05[3] = {
  1349.   bs.BE_read_real32(),
  1350.   bs.BE_read_real32(),
  1351.   bs.BE_read_real32()
  1352.  };
  1353.  
  1354.  // BEGIN DEBUG
  1355.  if(debug) {
  1356.     dfile << "p01 = " << p01 << endl;
  1357.     dfile << "p02 = 0x" << setfill('0') << setw(8) << hex << p02 << dec << endl;
  1358.     dfile << "p03 = <" << p03[0] << ", " << p03[1] << ", " << p03[2] << ">" << endl;
  1359.     dfile << "p04 = <" << p04[0] << ", " << p04[1] << ", " << p04[2] << ">" << endl;
  1360.     dfile << "p05 = <" << p05[0] << ", " << p05[1] << ", " << p05[2] << ">" << endl;
  1361.     dfile << endl;
  1362.    }
  1363.  // END DEBUG
  1364.  
  1365.  // process each mesh
  1366.  for(uint32 i = 0; i < h03; i++)
  1367.      if(!processTPMG()) return false;
  1368.  
  1369.  // skip past data
  1370.  bs.seek(position + h02);
  1371.  if(bs.fail()) return error("Stream seek failure.");
  1372.  
  1373.  return true;
  1374. }
  1375.  
  1376. bool MDLProcess::processTPMG(void)
  1377. {
  1378.  // read header
  1379.  uint32 h01 = bs.BE_read_uint32(); // TPMG
  1380.  uint32 h02 = bs.BE_read_uint32(); // size of chunk minus 0x10-byte header
  1381.  uint32 h03 = bs.BE_read_uint32(); // 0x00
  1382.  uint32 h04 = bs.BE_read_uint32(); // 0x00
  1383.  
  1384.  // validate header
  1385.  if(h01 != 0x54504D47) return error("Invalid TPMG.");
  1386.  if(h03 != 0x00) return error("TPMG h04 expecting 0x00.");
  1387.  if(h04 != 0x00) return error("TPMG h04 expecting 0x00.");
  1388.  
  1389.  // save position
  1390.  auto position = bs.tell();
  1391.  if(bs.fail()) return error("Stream tell failure.");
  1392.  
  1393.  // read buffer information
  1394.  struct TPMGINFO {
  1395.   uint16 p01; // unknown
  1396.   uint16 p02; // vertex buffer format
  1397.   uint16 p03; // unknown 0x0010
  1398.   uint32 p04; // number of vertices
  1399.   uint16 p05; // number of indices
  1400.   uint32 p06; // unknown 0xFFFFFFFF
  1401.   uint16 p07; // unknown 0x0000
  1402.   uint16 p08; // offset to index buffer
  1403.   uint16 p09; // index buffer size in bytes #1
  1404.   uint16 p10; // index buffer size in bytes #2
  1405.   uint16 p11; // unknown 0x0000
  1406.   uint16 p12; // offset to vertex buffer
  1407.   uint16 p13; // unknown 0x0000
  1408.   uint16 p14; // unknown 0x0000
  1409.   uint16 p15; // bytes in 1st vertex buffer (sum to get total bytes)
  1410.   uint16 p16; // bytes in 2nd vertex buffer (sum to get total bytes)
  1411.   uint16 p17; // unknown 0x0000
  1412.   uint16 p18; // unknown 0x0000
  1413.   uint16 p19; // unknown 0x0000
  1414.   uint16 p20; // unknown 0x0000
  1415.   uint16 p21; // unknown SEE: data\ms\bjh\gb_bjh.mdl
  1416.   uint16 p22; // unknown sometimes not 0x00000
  1417.   uint16 p23; // unknown sometimes not 0x00000
  1418.   uint16 p24; // unknown sometimes not 0x00000
  1419.   uint16 p25; // size in bytes of additional data section
  1420.   uint16 p26; // unknown 0x0000
  1421.   uint16 p27; // unknown 0x0000
  1422.   uint16 p28; // unknown 0x0000
  1423.   uint32 p29; // offset to additional data section
  1424.   uint32 p30; // unknown
  1425.   uint32 p31; // unknown
  1426.   uint32 p32[0xE]; // unknown all 0x00000000
  1427.  };
  1428.  TPMGINFO info;
  1429.  info.p01 = bs.BE_read_uint16();
  1430.  info.p02 = bs.BE_read_uint16();
  1431.  info.p03 = bs.BE_read_uint16();
  1432.  info.p04 = bs.BE_read_uint32();
  1433.  info.p05 = bs.BE_read_uint16();
  1434.  info.p06 = bs.BE_read_uint32();
  1435.  info.p07 = bs.BE_read_uint16();
  1436.  info.p08 = bs.BE_read_uint16();
  1437.  info.p09 = bs.BE_read_uint16();
  1438.  info.p10 = bs.BE_read_uint16();
  1439.  info.p11 = bs.BE_read_uint16();
  1440.  info.p12 = bs.BE_read_uint16();
  1441.  info.p13 = bs.BE_read_uint16();
  1442.  info.p14 = bs.BE_read_uint16();
  1443.  info.p15 = bs.BE_read_uint16();
  1444.  info.p16 = bs.BE_read_uint16();
  1445.  info.p17 = bs.BE_read_uint16();
  1446.  info.p18 = bs.BE_read_uint16();
  1447.  info.p19 = bs.BE_read_uint16();
  1448.  info.p20 = bs.BE_read_uint16();
  1449.  info.p21 = bs.BE_read_uint16();
  1450.  info.p22 = bs.BE_read_uint16();
  1451.  info.p23 = bs.BE_read_uint16();
  1452.  info.p24 = bs.BE_read_uint16();
  1453.  info.p25 = bs.BE_read_uint16();
  1454.  info.p26 = bs.BE_read_uint16();
  1455.  info.p27 = bs.BE_read_uint16();
  1456.  info.p28 = bs.BE_read_uint16();
  1457.  info.p29 = bs.BE_read_uint32();
  1458.  info.p30 = bs.BE_read_uint32();
  1459.  info.p31 = bs.BE_read_uint32();
  1460.  bs.BE_read_array(&info.p32[0], 0x0E);
  1461.  if(bs.fail()) return error("Stream read failure.");
  1462.  
  1463.  // compute vertex stride
  1464.  // NOTE: vertex buffer may have zero padding, so don't check if length
  1465.  // is divisible by number of vertices.
  1466.  uint32 vertex_length = info.p15 + info.p16;
  1467.  if(!vertex_length) return error("Vertex stride cannot be zero.");
  1468.  
  1469.  // validate info
  1470.  if(info.p03 < 0x0010 || info.p03 > 0x0011) return error("info.p03 < 0x0010 || info.p03 > 0x0011");
  1471.  if(info.p04 >= 0xFFFF) return error("p04 >= 0xFFFF");
  1472.  if(info.p06 != 0xFFFFFFFF) return error("p06 != 0xFFFFFFFF");
  1473.  if(info.p07 != 0x0000) return error("p07 != 0x0000");
  1474.  if(info.p11 != 0x0000) return error("p11 != 0x0000");
  1475.  if(info.p13 != 0x0000) return error("p13 != 0x0000");
  1476.  if(info.p14 != 0x0000) return error("p14 != 0x0000");
  1477.  if(info.p17 != 0x0000) return error("p17 != 0x0000");
  1478.  if(info.p18 != 0x0000) return error("p18 != 0x0000");
  1479.  if(info.p19 != 0x0000) return error("p19 != 0x0000");
  1480.  if(info.p20 != 0x0000) return error("p20 != 0x0000");
  1481.  if(info.p26 != 0x0000) return error("p26 != 0x0000");
  1482.  if(info.p27 != 0x0000) return error("p27 != 0x0000");
  1483.  if(info.p28 != 0x0000) return error("p28 != 0x0000");
  1484.  for(uint32 i = 0; i < 0x0E; i++) if(info.p32[i] != 0x00000) return error("p32[i] != 0x0000");
  1485.  
  1486.  // TEST
  1487.  if(info.p25 && info.p29)
  1488.     cout << " MODEL HAS WEIGHTS 0x" << hex << info.p25 << dec << " BYTES" << endl;
  1489.  
  1490.  // seek index buffer data
  1491.  bs.seek(position + info.p08);
  1492.  if(bs.fail()) return error("Stream seek failure.");
  1493.  
  1494.  // compute number of indices
  1495.  // uint32 n_indices = (info.p09 + info.p10)/2;
  1496.  uint32 n_indices = info.p05;
  1497.  if(!n_indices) return error("Index buffer has no indices.");
  1498.  
  1499.  // read index buffer
  1500.  uint32 ib_size = info.p09 + info.p10;
  1501.  boost::shared_array<char> ibuffer(new char[ib_size]);
  1502.  bs.BE_read_array(reinterpret_cast<uint16*>(ibuffer.get()), info.p05);
  1503.  if(bs.fail()) return error("Stream read failure.");
  1504.  
  1505.  // set vertex stride and number of vertices
  1506.  // NOTE: although there is a number in the data that is close to the number of
  1507.  // vertices, it sometimes not the same, which forces us to recompute the number
  1508.  // from the stride and the buffer length. it's a pain in the ass, but that is
  1509.  // currently the only way to do it.
  1510.  uint32 vertex_stride = 0;
  1511.  uint32 n_vertices = 0;
  1512.  uint32 extra_vertex_flags = 0;
  1513.  if(info.p02 == 0x0303) vertex_stride = 0x18;      // done
  1514.  else if(info.p02 == 0x0606) vertex_stride = 0x1C; // done
  1515.  else if(info.p02 == 0x0707) vertex_stride = 0x10; // done
  1516.  else if(info.p02 == 0x0C08) vertex_stride = 0x10; // done
  1517.  else if(info.p02 == 0x0D09) vertex_stride = 0x14; // done
  1518.  else if(info.p02 == 0x0F0B) vertex_stride = 0x14; // done
  1519.  else if(info.p02 == 0x100C) vertex_stride = 0x14; // done
  1520.  else if(info.p02 == 0x110D) vertex_stride = 0x18; // done
  1521.  else if(info.p02 == 0x120E) vertex_stride = 0x1C; // done (big maps)
  1522.  else if(info.p02 == 0x130F) vertex_stride = 0x20; // done
  1523.  else if(info.p02 == 0x1511) vertex_stride = 0x28; // done (big maps)
  1524.  else if(info.p02 == 0x1A16) vertex_stride = 0x1C; // ???? (big maps, uncertain)
  1525.  else if(info.p02 == 0x1C18) vertex_stride = 0x24; // done (but strange normals)
  1526.  else if(info.p02 == 0x1D19) vertex_stride = 0x20; // done
  1527.  else if(info.p02 == 0x1E1A) vertex_stride = 0x2C; // done (big maps)
  1528.  else if(info.p02 == 0x1F1B) vertex_stride = 0x28; // done
  1529.  else if(info.p02 == 0x201C) vertex_stride = 0x24; // done
  1530.  else if(info.p02 == 0x2521) vertex_stride = 0x1C; // done (big maps, uncertain about two UV channels)
  1531.  else if(info.p02 == 0x2D29) vertex_stride = 0x28; // done (big maps, uncertain)
  1532.  else if(info.p02 == 0x2F2B) vertex_stride = 0x20; // done
  1533.  else if(info.p02 == 0x3430) vertex_stride = 0x18; // done (big maps)
  1534.  else if(info.p02 == 0x3C38) vertex_stride = 0x2C; // done
  1535.  else if(info.p02 == 0x403C) vertex_stride = 0x28; // done
  1536.  else if(info.p02 == 0x4440) vertex_stride = 0x38; // ???? (big maps, uncertain)
  1537.  else if(info.p02 == 0x4541) vertex_stride = 0x38; // ???? (big maps, uncertain)
  1538.  else if(info.p02 == 0x524E) vertex_stride = 0x28; // ???? (big maps, uncertain)
  1539.  else return error("Unknown vertex format.");
  1540.  n_vertices = vertex_length/vertex_stride;
  1541.  
  1542.  // initialize vertex buffer
  1543.  AMC_VTXBUFFER vb;
  1544.  vb.elem = n_vertices;
  1545.  vb.data.reset(new AMC_VERTEX[vb.elem]);
  1546.  vb.flags = AMC_VERTEX_POSITION | AMC_VERTEX_NORMAL | AMC_VERTEX_UV;
  1547.  vb.name = "default";
  1548.  vb.uvchan = 1;
  1549.  vb.uvtype[0] = AMC_DIFFUSE_MAP;
  1550.  vb.uvtype[1] = AMC_INVALID_MAP; // important to set!
  1551.  vb.uvtype[2] = AMC_INVALID_MAP; // important to set!
  1552.  vb.uvtype[3] = AMC_INVALID_MAP; // important to set!
  1553.  vb.uvtype[4] = AMC_INVALID_MAP; // important to set!
  1554.  vb.uvtype[5] = AMC_INVALID_MAP; // important to set!
  1555.  vb.uvtype[6] = AMC_INVALID_MAP; // important to set!
  1556.  vb.uvtype[7] = AMC_INVALID_MAP; // important to set!
  1557.  vb.colors = 0;
  1558.  
  1559.  // special cases
  1560.  switch(info.p02) {
  1561.    // no vertex normals
  1562.    case(0x0707) :
  1563.    case(0x0F0B) : {
  1564.         vb.flags &= ~AMC_VERTEX_NORMAL;
  1565.         break;
  1566.        }
  1567.    // no UV for test models
  1568.    case(0x0C08) : {
  1569.         vb.flags &= ~AMC_VERTEX_UV;
  1570.         vb.uvchan = 0;
  1571.         break;
  1572.        }
  1573.    // no UV but colors for viewer models
  1574.    case(0x100C) : {
  1575.         vb.flags &= ~AMC_VERTEX_UV;
  1576.         vb.uvchan = 0;
  1577.         vb.colors = 1;
  1578.         break;
  1579.        }
  1580.    // UV + colors
  1581.    case(0x130F) : {
  1582.         vb.colors = 1;
  1583.         break;
  1584.        }
  1585.    // two-channel UV map
  1586.    case(0x1A16) :
  1587.    case(0x1C18) :
  1588.    case(0x1D19) :
  1589.    case(0x1F1B) :
  1590.    case(0x201C) :
  1591.    case(0x2F2B) :
  1592.    case(0x3430) : {
  1593.         vb.uvchan = 2;
  1594.         vb.uvtype[1] = AMC_LIGHT_MAP; // actually ENVIRONMENT MAP
  1595.         break;
  1596.        }
  1597.    // two-channel UV map + one-channel color
  1598.    case(0x2521) : {
  1599.         vb.colors = 1;
  1600.         vb.uvchan = 2;
  1601.         vb.uvtype[1] = AMC_LIGHT_MAP;
  1602.         break;
  1603.        }
  1604.    // three-channel UV map
  1605.    case(0x1511) :
  1606.    case(0x1E1A) :
  1607.    case(0x2D29) : {
  1608.         vb.uvchan = 3;
  1609.         vb.uvtype[1] = AMC_LIGHT_MAP;
  1610.         vb.uvtype[2] = AMC_LIGHT_MAP;
  1611.         break;
  1612.        }
  1613.    // four-channel UV map
  1614.    case(0x403C) :
  1615.    case(0x524E) :
  1616.    case(0x3C38) : {
  1617.         vb.uvchan = 4;
  1618.         vb.uvtype[1] = AMC_LIGHT_MAP; // actually ENVIRONMENT MAP
  1619.         vb.uvtype[2] = AMC_LIGHT_MAP; // actually ENVIRONMENT MAP
  1620.         vb.uvtype[3] = AMC_LIGHT_MAP; // actually ENVIRONMENT MAP
  1621.         break;
  1622.        }
  1623.    // five-channel UV map
  1624.    case(0x4440) : {
  1625.         vb.uvchan = 5;
  1626.         vb.uvtype[1] = AMC_LIGHT_MAP; // actually ENVIRONMENT MAP
  1627.         vb.uvtype[2] = AMC_LIGHT_MAP; // actually ENVIRONMENT MAP
  1628.         vb.uvtype[3] = AMC_LIGHT_MAP; // actually ENVIRONMENT MAP
  1629.         vb.uvtype[4] = AMC_LIGHT_MAP; // actually ENVIRONMENT MAP
  1630.         break;
  1631.        }
  1632.    // six-channel UV map
  1633.    case(0x4541) : {
  1634.         vb.uvchan = 6;
  1635.         vb.uvtype[1] = AMC_LIGHT_MAP;
  1636.         vb.uvtype[2] = AMC_LIGHT_MAP;
  1637.         vb.uvtype[3] = AMC_LIGHT_MAP;
  1638.         vb.uvtype[4] = AMC_LIGHT_MAP;
  1639.         vb.uvtype[5] = AMC_LIGHT_MAP;
  1640.         break;
  1641.        }
  1642.   }
  1643.  
  1644.  // seek vertex buffer data
  1645.  bs.seek(position + info.p12);
  1646.  if(bs.fail()) return error("Stream seek failure.");
  1647.  
  1648.  // process vertices
  1649.  for(uint32 i = 0; i < n_vertices; i++)
  1650.     {
  1651.      if(info.p02 == 0x0303)
  1652.        {
  1653.         vb.data[i].vx = bs.BE_read_real32();
  1654.         vb.data[i].vy = bs.BE_read_real32();
  1655.         vb.data[i].vz = bs.BE_read_real32();
  1656.         cs::math::vector3D<cs::math::binary32> normal = ConvertNormal_S10S11S11(bs.BE_read_uint32());
  1657.         vb.data[i].nx = normal[2];
  1658.         vb.data[i].ny = normal[1];
  1659.         vb.data[i].nz = normal[0];
  1660.         bs.BE_read_sint08(); // unknown
  1661.         bs.BE_read_sint08(); // unknown
  1662.         bs.BE_read_sint08(); // unknown
  1663.         bs.BE_read_sint08(); // unknown
  1664.         vb.data[i].uv[0][0] = bs.BE_read_real16();
  1665.         vb.data[i].uv[0][1] = bs.BE_read_real16();
  1666.        }
  1667.      else if(info.p02 == 0x0606)
  1668.        {
  1669.         vb.data[i].vx = bs.BE_read_real32();
  1670.         vb.data[i].vy = bs.BE_read_real32();
  1671.         vb.data[i].vz = bs.BE_read_real32();
  1672.         cs::math::vector3D<cs::math::binary32> normal = ConvertNormal_S10S11S11(bs.BE_read_uint32());
  1673.         vb.data[i].nx = normal[2];
  1674.         vb.data[i].ny = normal[1];
  1675.         vb.data[i].nz = normal[0];
  1676.         bs.BE_read_sint08(); // unknown
  1677.         bs.BE_read_sint08(); // unknown
  1678.         bs.BE_read_sint08(); // unknown
  1679.         bs.BE_read_sint08(); // unknown
  1680.         bs.BE_read_sint08(); // unknown
  1681.         bs.BE_read_sint08(); // unknown
  1682.         bs.BE_read_sint08(); // unknown
  1683.         bs.BE_read_sint08(); // unknown
  1684.         vb.data[i].uv[0][0] = bs.BE_read_real16();
  1685.         vb.data[i].uv[0][1] = bs.BE_read_real16();
  1686.        }
  1687.      else if(info.p02 == 0x0707)
  1688.        {
  1689.         vb.data[i].vx = bs.BE_read_real32();
  1690.         vb.data[i].vy = bs.BE_read_real32();
  1691.         vb.data[i].vz = bs.BE_read_real32();
  1692.         vb.data[i].uv[0][0] = bs.BE_read_real16();
  1693.         vb.data[i].uv[0][1] = bs.BE_read_real16();
  1694.        }
  1695.      else if(info.p02 == 0x0C08)
  1696.        {
  1697.         vb.data[i].vx = bs.BE_read_real32();
  1698.         vb.data[i].vy = bs.BE_read_real32();
  1699.         vb.data[i].vz = bs.BE_read_real32();
  1700.         cs::math::vector3D<cs::math::binary32> normal = ConvertNormal_S10S11S11(bs.BE_read_uint32());
  1701.         vb.data[i].nx = normal[2];
  1702.         vb.data[i].ny = normal[1];
  1703.         vb.data[i].nz = normal[0];
  1704.        }
  1705.      else if(info.p02 == 0x0D09)
  1706.        {
  1707.         vb.data[i].vx = bs.BE_read_real32();
  1708.         vb.data[i].vy = bs.BE_read_real32();
  1709.         vb.data[i].vz = bs.BE_read_real32();
  1710.         cs::math::vector3D<cs::math::binary32> normal = ConvertNormal_S10S11S11(bs.BE_read_uint32());
  1711.         vb.data[i].nx = normal[2];
  1712.         vb.data[i].ny = normal[1];
  1713.         vb.data[i].nz = normal[0];
  1714.         vb.data[i].uv[0][0] = bs.BE_read_real16();
  1715.         vb.data[i].uv[0][1] = bs.BE_read_real16();
  1716.        }
  1717.      else if(info.p02 == 0x0F0B)
  1718.        {
  1719.         // similar to 0x707 but with added color
  1720.         vb.data[i].vx = bs.BE_read_real32();
  1721.         vb.data[i].vy = bs.BE_read_real32();
  1722.         vb.data[i].vz = bs.BE_read_real32();
  1723.         vb.data[i].uv[0][0] = bs.BE_read_real16();
  1724.         vb.data[i].uv[0][1] = bs.BE_read_real16();
  1725.         bs.BE_read_uint08(); // unknown
  1726.         bs.BE_read_uint08(); // unknown
  1727.         bs.BE_read_uint08(); // unknown
  1728.         bs.BE_read_uint08(); // unknown
  1729.        }
  1730.      else if(info.p02 == 0x100C)
  1731.        {
  1732.         vb.data[i].vx = bs.BE_read_real32();
  1733.         vb.data[i].vy = bs.BE_read_real32();
  1734.         vb.data[i].vz = bs.BE_read_real32();
  1735.         cs::math::vector3D<cs::math::binary32> normal = ConvertNormal_S10S11S11(bs.BE_read_uint32());
  1736.         vb.data[i].nx = normal[2];
  1737.         vb.data[i].ny = normal[1];
  1738.         vb.data[i].nz = normal[0];
  1739.         vb.data[i].color[0][0] = bs.BE_read_uint08()/255.0f; // unknown
  1740.         vb.data[i].color[0][1] = bs.BE_read_uint08()/255.0f; // unknown
  1741.         vb.data[i].color[0][2] = bs.BE_read_uint08()/255.0f; // unknown
  1742.         vb.data[i].color[0][3] = bs.BE_read_uint08()/255.0f; // unknown
  1743.        }
  1744.      else if(info.p02 == 0x110D)
  1745.        {
  1746.         vb.data[i].vx = bs.BE_read_real32();
  1747.         vb.data[i].vy = bs.BE_read_real32();
  1748.         vb.data[i].vz = bs.BE_read_real32();
  1749.         cs::math::vector3D<cs::math::binary32> normal = ConvertNormal_S10S11S11(bs.BE_read_uint32());
  1750.         vb.data[i].nx = normal[2];
  1751.         vb.data[i].ny = normal[1];
  1752.         vb.data[i].nz = normal[0];
  1753.         vb.data[i].uv[0][0] = bs.BE_read_real16();
  1754.         vb.data[i].uv[0][1] = bs.BE_read_real16();
  1755.         bs.BE_read_sint08(); // unknown
  1756.         bs.BE_read_sint08(); // unknown
  1757.         bs.BE_read_sint08(); // unknown
  1758.         bs.BE_read_sint08(); // unknown
  1759.        }
  1760.      else if(info.p02 == 0x120E)
  1761.        {
  1762.         vb.data[i].vx = bs.BE_read_real32();
  1763.         vb.data[i].vy = bs.BE_read_real32();
  1764.         vb.data[i].vz = bs.BE_read_real32();
  1765.         cs::math::vector3D<cs::math::binary32> normal = ConvertNormal_S10S11S11(bs.BE_read_uint32());
  1766.         vb.data[i].nx = normal[2];
  1767.         vb.data[i].ny = normal[1];
  1768.         vb.data[i].nz = normal[0];
  1769.         bs.BE_read_uint32(); // tangent/binormal
  1770.         vb.data[i].uv[0][0] = bs.BE_read_real16();
  1771.         vb.data[i].uv[0][1] = bs.BE_read_real16();
  1772.         vb.data[i].color[0][0] = bs.BE_read_uint08()/255.0f; // color???
  1773.         vb.data[i].color[0][1] = bs.BE_read_uint08()/255.0f; // color???
  1774.         vb.data[i].color[0][2] = bs.BE_read_uint08()/255.0f; // color???
  1775.         vb.data[i].color[0][3] = bs.BE_read_uint08()/255.0f; // color???
  1776.        }
  1777.      else if(info.p02 == 0x130F)
  1778.        {
  1779.         // similar to 0x120E but with extra tangent/binormal
  1780.         vb.data[i].vx = bs.BE_read_real32();
  1781.         vb.data[i].vy = bs.BE_read_real32();
  1782.         vb.data[i].vz = bs.BE_read_real32();
  1783.         cs::math::vector3D<cs::math::binary32> normal = ConvertNormal_S10S11S11(bs.BE_read_uint32());
  1784.         vb.data[i].nx = normal[2];
  1785.         vb.data[i].ny = normal[1];
  1786.         vb.data[i].nz = normal[0];
  1787.         bs.BE_read_uint32(); // tangent/binormal
  1788.         bs.BE_read_uint32(); // tangent/binormal
  1789.         vb.data[i].uv[0][0] = bs.BE_read_real16();
  1790.         vb.data[i].uv[0][1] = bs.BE_read_real16();
  1791.         vb.data[i].color[0][0] = bs.BE_read_uint08()/255.0f; // color???
  1792.         vb.data[i].color[0][1] = bs.BE_read_uint08()/255.0f; // color???
  1793.         vb.data[i].color[0][2] = bs.BE_read_uint08()/255.0f; // color???
  1794.         vb.data[i].color[0][3] = bs.BE_read_uint08()/255.0f; // color???
  1795.        }
  1796.      else if(info.p02 == 0x1511)
  1797.        {
  1798.         vb.data[i].vx = bs.BE_read_real32();
  1799.         vb.data[i].vy = bs.BE_read_real32();
  1800.         vb.data[i].vz = bs.BE_read_real32();
  1801.         bs.BE_read_uint08(); // unknown
  1802.         bs.BE_read_uint08(); // unknown
  1803.         bs.BE_read_uint08(); // unknown
  1804.         bs.BE_read_uint08(); // unknown
  1805.         cs::math::vector3D<cs::math::binary32> normal = ConvertNormal_S10S11S11(bs.BE_read_uint32());
  1806.         vb.data[i].nx = normal[2];
  1807.         vb.data[i].ny = normal[1];
  1808.         vb.data[i].nz = normal[0];
  1809.         bs.BE_read_uint32(); // tangent/binormal
  1810.         bs.BE_read_uint32(); // tangent/binormal
  1811.         vb.data[i].uv[0][0] = bs.BE_read_real16();
  1812.         vb.data[i].uv[0][1] = bs.BE_read_real16();
  1813.         vb.data[i].uv[1][0] = bs.BE_read_real16();
  1814.         vb.data[i].uv[1][1] = bs.BE_read_real16();
  1815.         vb.data[i].uv[2][0] = bs.BE_read_real16();
  1816.         vb.data[i].uv[2][1] = bs.BE_read_real16();
  1817.        }
  1818.      else if(info.p02 == 0x1A16)
  1819.        {
  1820.         vb.data[i].vx = bs.BE_read_real32();
  1821.         vb.data[i].vy = bs.BE_read_real32();
  1822.         vb.data[i].vz = bs.BE_read_real32();
  1823.         cs::math::vector3D<cs::math::binary32> normal = ConvertNormal_S10S11S11(bs.BE_read_uint32());
  1824.         vb.data[i].nx = normal[2];
  1825.         vb.data[i].ny = normal[1];
  1826.         vb.data[i].nz = normal[0];
  1827.         bs.BE_read_uint32(); // tangent/binormal
  1828.         vb.data[i].uv[0][0] = bs.BE_read_real16();
  1829.         vb.data[i].uv[0][1] = bs.BE_read_real16();
  1830.         vb.data[i].uv[1][0] = bs.BE_read_real16();
  1831.         vb.data[i].uv[1][1] = bs.BE_read_real16();
  1832.        }
  1833.      else if(info.p02 == 0x1C18)
  1834.        {
  1835.         vb.data[i].vx = bs.BE_read_real32();
  1836.         vb.data[i].vy = bs.BE_read_real32();
  1837.         vb.data[i].vz = bs.BE_read_real32();
  1838.         bs.BE_read_sint08(); // unknown
  1839.         bs.BE_read_sint08(); // unknown
  1840.         bs.BE_read_sint08(); // unknown
  1841.         bs.BE_read_sint08(); // unknown
  1842.         cs::math::vector3D<cs::math::binary32> normal = ConvertNormal_S10S11S11(bs.BE_read_uint32());
  1843.         vb.data[i].nx = normal[2];
  1844.         vb.data[i].ny = normal[1];
  1845.         vb.data[i].nz = normal[0];
  1846.         bs.BE_read_uint32(); // tangent/binormal
  1847.         bs.BE_read_uint32(); // tangent/binormal
  1848.         vb.data[i].uv[0][0] = bs.BE_read_real16();
  1849.         vb.data[i].uv[0][1] = bs.BE_read_real16();
  1850.         vb.data[i].uv[1][0] = bs.BE_read_real16();
  1851.         vb.data[i].uv[1][1] = bs.BE_read_real16();
  1852.        }
  1853.      else if(info.p02 == 0x1D19)
  1854.        {
  1855.         vb.data[i].vx = bs.BE_read_real32();
  1856.         vb.data[i].vy = bs.BE_read_real32();
  1857.         vb.data[i].vz = bs.BE_read_real32();
  1858.         cs::math::vector3D<cs::math::binary32> normal = ConvertNormal_S10S11S11(bs.BE_read_uint32());
  1859.         vb.data[i].nx = normal[2];
  1860.         vb.data[i].ny = normal[1];
  1861.         vb.data[i].nz = normal[0];
  1862.         bs.BE_read_uint32(); // tangent/binormal
  1863.         bs.BE_read_uint32(); // tangent/binormal
  1864.         vb.data[i].uv[0][0] = bs.BE_read_real16();
  1865.         vb.data[i].uv[0][1] = bs.BE_read_real16();
  1866.         vb.data[i].uv[1][0] = bs.BE_read_real16();
  1867.         vb.data[i].uv[1][1] = bs.BE_read_real16();
  1868.        }
  1869.      else if(info.p02 == 0x1E1A)
  1870.        {
  1871.         vb.data[i].vx = bs.BE_read_real32();
  1872.         vb.data[i].vy = bs.BE_read_real32();
  1873.         vb.data[i].vz = bs.BE_read_real32();
  1874.         bs.BE_read_sint08(); // unknown color???
  1875.         bs.BE_read_sint08(); // unknown color???
  1876.         bs.BE_read_sint08(); // unknown color???
  1877.         bs.BE_read_sint08(); // unknown color???
  1878.         cs::math::vector3D<cs::math::binary32> normal = ConvertNormal_S10S11S11(bs.BE_read_uint32());
  1879.         vb.data[i].nx = normal[2];
  1880.         vb.data[i].ny = normal[1];
  1881.         vb.data[i].nz = normal[0];
  1882.         bs.BE_read_uint32(); // tangent/binormal
  1883.         bs.BE_read_uint32(); // tangent/binormal
  1884.         vb.data[i].uv[0][0] = bs.BE_read_real16();
  1885.         vb.data[i].uv[0][1] = bs.BE_read_real16();
  1886.         vb.data[i].uv[1][0] = bs.BE_read_real16();
  1887.         vb.data[i].uv[1][1] = bs.BE_read_real16();
  1888.         vb.data[i].uv[2][0] = bs.BE_read_real16();
  1889.         vb.data[i].uv[2][1] = bs.BE_read_real16();
  1890.         bs.BE_read_sint08(); // unknown color???
  1891.         bs.BE_read_sint08(); // unknown color???
  1892.         bs.BE_read_sint08(); // unknown color???
  1893.         bs.BE_read_sint08(); // unknown color???
  1894.        }
  1895.      else if(info.p02 == 0x1F1B)
  1896.        {
  1897.         vb.data[i].vx = bs.BE_read_real32();
  1898.         vb.data[i].vy = bs.BE_read_real32();
  1899.         vb.data[i].vz = bs.BE_read_real32();
  1900.         bs.BE_read_sint08(); // unknown
  1901.         bs.BE_read_sint08(); // unknown
  1902.         bs.BE_read_sint08(); // unknown
  1903.         bs.BE_read_sint08(); // unknown
  1904.         cs::math::vector3D<cs::math::binary32> normal = ConvertNormal_S10S11S11(bs.BE_read_uint32());
  1905.         vb.data[i].nx = normal[2];
  1906.         vb.data[i].ny = normal[1];
  1907.         vb.data[i].nz = normal[0];
  1908.         bs.BE_read_uint32(); // tangent/binormal
  1909.         bs.BE_read_uint32(); // tangent/binormal
  1910.         vb.data[i].uv[0][0] = bs.BE_read_real16();
  1911.         vb.data[i].uv[0][1] = bs.BE_read_real16();
  1912.         vb.data[i].uv[1][0] = bs.BE_read_real16();
  1913.         vb.data[i].uv[1][1] = bs.BE_read_real16();
  1914.         bs.BE_read_sint08(); // unknown color???
  1915.         bs.BE_read_sint08(); // unknown color???
  1916.         bs.BE_read_sint08(); // unknown color???
  1917.         bs.BE_read_sint08(); // unknown color???
  1918.        }
  1919.      else if(info.p02 == 0x201C)
  1920.        {
  1921.         vb.data[i].vx = bs.BE_read_real32();
  1922.         vb.data[i].vy = bs.BE_read_real32();
  1923.         vb.data[i].vz = bs.BE_read_real32();
  1924.         bs.BE_read_sint08(); // unknown
  1925.         bs.BE_read_sint08(); // unknown
  1926.         bs.BE_read_sint08(); // unknown
  1927.         bs.BE_read_sint08(); // unknown
  1928.         cs::math::vector3D<cs::math::binary32> normal = ConvertNormal_S10S11S11(bs.BE_read_uint32());
  1929.         vb.data[i].nx = normal[2];
  1930.         vb.data[i].ny = normal[1];
  1931.         vb.data[i].nz = normal[0];
  1932.         bs.BE_read_uint32(); // tangent/binormal
  1933.         bs.BE_read_uint32(); // tangent/binormal
  1934.         vb.data[i].uv[0][0] = bs.BE_read_real16();
  1935.         vb.data[i].uv[0][1] = bs.BE_read_real16();
  1936.         vb.data[i].uv[1][0] = bs.BE_read_real16();
  1937.         vb.data[i].uv[1][1] = bs.BE_read_real16();
  1938.        }
  1939.      else if(info.p02 == 0x2521)
  1940.        {
  1941.         vb.data[i].vx = bs.BE_read_real32();
  1942.         vb.data[i].vy = bs.BE_read_real32();
  1943.         vb.data[i].vz = bs.BE_read_real32();
  1944.         vb.data[i].color[0][0] = bs.BE_read_uint08()/255.0f; // unknown color???
  1945.         vb.data[i].color[0][1] = bs.BE_read_uint08()/255.0f; // unknown color???
  1946.         vb.data[i].color[0][2] = bs.BE_read_uint08()/255.0f; // unknown color???
  1947.         vb.data[i].color[0][3] = bs.BE_read_uint08()/255.0f; // unknown color???
  1948.         cs::math::vector3D<cs::math::binary32> normal = ConvertNormal_S10S11S11(bs.BE_read_uint32());
  1949.         vb.data[i].nx = normal[2];
  1950.         vb.data[i].ny = normal[1];
  1951.         vb.data[i].nz = normal[0];
  1952.         vb.data[i].uv[0][0] = bs.BE_read_real16();
  1953.         vb.data[i].uv[0][1] = bs.BE_read_real16();
  1954.         vb.data[i].uv[1][0] = bs.BE_read_real16();
  1955.         vb.data[i].uv[1][1] = bs.BE_read_real16();
  1956.        }
  1957.      else if(info.p02 == 0x2D29)
  1958.        {
  1959.         vb.data[i].vx = bs.BE_read_real32();
  1960.         vb.data[i].vy = bs.BE_read_real32();
  1961.         vb.data[i].vz = bs.BE_read_real32();
  1962.         cs::math::vector3D<cs::math::binary32> normal = ConvertNormal_S10S11S11(bs.BE_read_uint32());
  1963.         vb.data[i].nx = normal[2];
  1964.         vb.data[i].ny = normal[1];
  1965.         vb.data[i].nz = normal[0];
  1966.         bs.BE_read_uint32(); // tangent/binormal
  1967.         bs.BE_read_uint32(); // tangent/binormal
  1968.         vb.data[i].uv[0][0] = bs.BE_read_real16();
  1969.         vb.data[i].uv[0][1] = bs.BE_read_real16();
  1970.         vb.data[i].uv[1][0] = bs.BE_read_real16();
  1971.         vb.data[i].uv[1][1] = bs.BE_read_real16();
  1972.         vb.data[i].uv[2][0] = bs.BE_read_real16();
  1973.         vb.data[i].uv[2][1] = bs.BE_read_real16();
  1974.         bs.BE_read_sint08(); // unknown color???
  1975.         bs.BE_read_sint08(); // unknown color???
  1976.         bs.BE_read_sint08(); // unknown color???
  1977.         bs.BE_read_sint08(); // unknown color???
  1978.        }
  1979.      else if(info.p02 == 0x2F2B)
  1980.        {
  1981.         vb.data[i].vx = bs.BE_read_real32();
  1982.         vb.data[i].vy = bs.BE_read_real32();
  1983.         vb.data[i].vz = bs.BE_read_real32();
  1984.         cs::math::vector3D<cs::math::binary32> normal = ConvertNormal_S10S11S11(bs.BE_read_uint32());
  1985.         vb.data[i].nx = normal[2];
  1986.         vb.data[i].ny = normal[1];
  1987.         vb.data[i].nz = normal[0];
  1988.         bs.BE_read_uint32(); // tangent/binormal
  1989.         bs.BE_read_uint32(); // tangent/binormal
  1990.         vb.data[i].uv[0][0] = bs.BE_read_real16();
  1991.         vb.data[i].uv[0][1] = bs.BE_read_real16();
  1992.         vb.data[i].uv[1][0] = bs.BE_read_real16();
  1993.         vb.data[i].uv[1][1] = bs.BE_read_real16();
  1994.        }
  1995.      else if(info.p02 == 0x3430)
  1996.        {
  1997.         vb.data[i].vx = bs.BE_read_real32();
  1998.         vb.data[i].vy = bs.BE_read_real32();
  1999.         vb.data[i].vz = bs.BE_read_real32();
  2000.         cs::math::vector3D<cs::math::binary32> normal = ConvertNormal_S10S11S11(bs.BE_read_uint32());
  2001.         vb.data[i].nx = normal[2];
  2002.         vb.data[i].ny = normal[1];
  2003.         vb.data[i].nz = normal[0];
  2004.         vb.data[i].uv[0][0] = bs.BE_read_real16();
  2005.         vb.data[i].uv[0][1] = bs.BE_read_real16();
  2006.         vb.data[i].uv[1][0] = bs.BE_read_real16();
  2007.         vb.data[i].uv[1][1] = bs.BE_read_real16();
  2008.        }
  2009.      else if(info.p02 == 0x3C38)
  2010.        {
  2011.         vb.data[i].vx = bs.BE_read_real32();
  2012.         vb.data[i].vy = bs.BE_read_real32();
  2013.         vb.data[i].vz = bs.BE_read_real32();
  2014.         bs.BE_read_sint08(); // unknown color???
  2015.         bs.BE_read_sint08(); // unknown color???
  2016.         bs.BE_read_sint08(); // unknown color???
  2017.         bs.BE_read_sint08(); // unknown color???
  2018.         cs::math::vector3D<cs::math::binary32> normal = ConvertNormal_S10S11S11(bs.BE_read_uint32());
  2019.         vb.data[i].nx = normal[2];
  2020.         vb.data[i].ny = normal[1];
  2021.         vb.data[i].nz = normal[0];
  2022.         bs.BE_read_uint32(); // tangent/binormal
  2023.         bs.BE_read_uint32(); // tangent/binormal
  2024.         vb.data[i].uv[0][0] = bs.BE_read_real16();
  2025.         vb.data[i].uv[0][1] = bs.BE_read_real16();
  2026.         vb.data[i].uv[1][0] = bs.BE_read_real16();
  2027.         vb.data[i].uv[1][1] = bs.BE_read_real16();
  2028.         vb.data[i].uv[2][0] = bs.BE_read_real16(); // same as channel 0
  2029.         vb.data[i].uv[2][1] = bs.BE_read_real16(); // same as channel 0
  2030.         vb.data[i].uv[3][0] = bs.BE_read_real16();
  2031.         vb.data[i].uv[3][1] = bs.BE_read_real16();
  2032.        }
  2033.      else if(info.p02 == 0x403C)
  2034.        {
  2035.         vb.data[i].vx = bs.BE_read_real32();
  2036.         vb.data[i].vy = bs.BE_read_real32();
  2037.         vb.data[i].vz = bs.BE_read_real32();
  2038.         cs::math::vector3D<cs::math::binary32> normal = ConvertNormal_S10S11S11(bs.BE_read_uint32());
  2039.         vb.data[i].nx = normal[2];
  2040.         vb.data[i].ny = normal[1];
  2041.         vb.data[i].nz = normal[0];
  2042.         bs.BE_read_uint32(); // tangent/binormal
  2043.         bs.BE_read_uint32(); // tangent/binormal
  2044.         vb.data[i].uv[0][0] = bs.BE_read_real16();
  2045.         vb.data[i].uv[0][1] = bs.BE_read_real16();
  2046.         vb.data[i].uv[1][0] = bs.BE_read_real16();
  2047.         vb.data[i].uv[1][1] = bs.BE_read_real16();
  2048.         vb.data[i].uv[2][0] = bs.BE_read_real16();
  2049.         vb.data[i].uv[2][1] = bs.BE_read_real16();
  2050.         vb.data[i].uv[3][0] = bs.BE_read_real16();
  2051.         vb.data[i].uv[3][1] = bs.BE_read_real16();
  2052.        }
  2053.      else if(info.p02 == 0x4440)
  2054.        {
  2055.         vb.data[i].vx = bs.BE_read_real32();
  2056.         vb.data[i].vy = bs.BE_read_real32();
  2057.         vb.data[i].vz = bs.BE_read_real32();
  2058.         bs.BE_read_sint08(); // unknown color???
  2059.         bs.BE_read_sint08(); // unknown color???
  2060.         bs.BE_read_sint08(); // unknown color???
  2061.         bs.BE_read_sint08(); // unknown color???
  2062.         bs.BE_read_sint08(); // unknown color???
  2063.         bs.BE_read_sint08(); // unknown color???
  2064.         bs.BE_read_sint08(); // unknown color???
  2065.         bs.BE_read_sint08(); // unknown color???
  2066.         cs::math::vector3D<cs::math::binary32> normal = ConvertNormal_S10S11S11(bs.BE_read_uint32());
  2067.         vb.data[i].nx = normal[2];
  2068.         vb.data[i].ny = normal[1];
  2069.         vb.data[i].nz = normal[0];
  2070.         bs.BE_read_uint32(); // tangent/binormal
  2071.         bs.BE_read_uint32(); // tangent/binormal
  2072.         vb.data[i].uv[0][0] = bs.BE_read_real16();
  2073.         vb.data[i].uv[0][1] = bs.BE_read_real16();
  2074.         vb.data[i].uv[1][0] = bs.BE_read_real16();
  2075.         vb.data[i].uv[1][1] = bs.BE_read_real16();
  2076.         vb.data[i].uv[2][0] = bs.BE_read_real16();
  2077.         vb.data[i].uv[2][1] = bs.BE_read_real16();
  2078.         vb.data[i].uv[3][0] = bs.BE_read_real16();
  2079.         vb.data[i].uv[3][1] = bs.BE_read_real16();
  2080.         vb.data[i].uv[4][0] = bs.BE_read_real16();
  2081.         vb.data[i].uv[4][1] = bs.BE_read_real16();
  2082.         bs.BE_read_sint08(); // unknown 0xFFFFFFFF
  2083.         bs.BE_read_sint08(); // unknown 0xFFFFFFFF
  2084.         bs.BE_read_sint08(); // unknown 0xFFFFFFFF
  2085.         bs.BE_read_sint08(); // unknown 0xFFFFFFFF
  2086.        }
  2087.      else if(info.p02 == 0x4541)
  2088.        {
  2089.         vb.data[i].vx = bs.BE_read_real32();
  2090.         vb.data[i].vy = bs.BE_read_real32();
  2091.         vb.data[i].vz = bs.BE_read_real32();
  2092.         bs.BE_read_sint08(); // unknown color???
  2093.         bs.BE_read_sint08(); // unknown color???
  2094.         bs.BE_read_sint08(); // unknown color???
  2095.         bs.BE_read_sint08(); // unknown color???
  2096.         bs.BE_read_sint08(); // unknown color???
  2097.         bs.BE_read_sint08(); // unknown color???
  2098.         bs.BE_read_sint08(); // unknown color???
  2099.         bs.BE_read_sint08(); // unknown color???
  2100.         cs::math::vector3D<cs::math::binary32> normal = ConvertNormal_S10S11S11(bs.BE_read_uint32());
  2101.         vb.data[i].nx = normal[2];
  2102.         vb.data[i].ny = normal[1];
  2103.         vb.data[i].nz = normal[0];
  2104.         bs.BE_read_uint32(); // tangent/binormal
  2105.         bs.BE_read_uint32(); // tangent/binormal
  2106.         vb.data[i].uv[0][0] = bs.BE_read_real16();
  2107.         vb.data[i].uv[0][1] = bs.BE_read_real16();
  2108.         vb.data[i].uv[1][0] = bs.BE_read_real16();
  2109.         vb.data[i].uv[1][1] = bs.BE_read_real16();
  2110.         vb.data[i].uv[2][0] = bs.BE_read_real16();
  2111.         vb.data[i].uv[2][1] = bs.BE_read_real16();
  2112.         vb.data[i].uv[3][0] = bs.BE_read_real16();
  2113.         vb.data[i].uv[3][1] = bs.BE_read_real16();
  2114.         vb.data[i].uv[4][0] = bs.BE_read_real16();
  2115.         vb.data[i].uv[4][1] = bs.BE_read_real16();
  2116.         vb.data[i].uv[5][0] = bs.BE_read_real16();
  2117.         vb.data[i].uv[5][1] = bs.BE_read_real16();
  2118.        }
  2119.      else if(info.p02 == 0x524E)
  2120.        {
  2121.         vb.data[i].vx = bs.BE_read_real32();
  2122.         vb.data[i].vy = bs.BE_read_real32();
  2123.         vb.data[i].vz = bs.BE_read_real32();
  2124.         bs.BE_read_sint08(); // unknown color???
  2125.         bs.BE_read_sint08(); // unknown color???
  2126.         bs.BE_read_sint08(); // unknown color???
  2127.         bs.BE_read_sint08(); // unknown color???
  2128.         bs.BE_read_sint08(); // unknown color???
  2129.         bs.BE_read_sint08(); // unknown color???
  2130.         bs.BE_read_sint08(); // unknown color???
  2131.         bs.BE_read_sint08(); // unknown color???
  2132.         cs::math::vector3D<cs::math::binary32> normal = ConvertNormal_S10S11S11(bs.BE_read_uint32());
  2133.         vb.data[i].nx = normal[2];
  2134.         vb.data[i].ny = normal[1];
  2135.         vb.data[i].nz = normal[0];
  2136.         vb.data[i].uv[0][0] = bs.BE_read_real16();
  2137.         vb.data[i].uv[0][1] = bs.BE_read_real16();
  2138.         vb.data[i].uv[1][0] = bs.BE_read_real16();
  2139.         vb.data[i].uv[1][1] = bs.BE_read_real16();
  2140.         vb.data[i].uv[2][0] = bs.BE_read_real16();
  2141.         vb.data[i].uv[2][1] = bs.BE_read_real16();
  2142.         vb.data[i].uv[3][0] = bs.BE_read_real16();
  2143.         vb.data[i].uv[3][1] = bs.BE_read_real16();
  2144.        }
  2145.     }
  2146.  
  2147.  // save index buffer
  2148.  AMC_IDXBUFFER ib;
  2149.  ib.format = AMC_UINT16;
  2150.  ib.type = AMC_TRIANGLES;
  2151.  ib.wind = AMC_CW;
  2152.  ib.name = "default";
  2153.  ib.elem = n_indices;
  2154.  ib.data = ibuffer;
  2155.  
  2156.  // insert vertex and index buffers
  2157.  amc.vblist.push_back(vb);
  2158.  amc.iblist.push_back(ib);
  2159.  
  2160.  // create surface
  2161.  AMC_SURFACE surface;
  2162.  stringstream ss;
  2163.  ss << "mesh_" << setfill('0') << setw(3) << amc.surfaces.size() << "_" << hex << setw(4) << info.p02 << dec;
  2164.  surface.name = ss.str();
  2165.  AMC_REFERENCE ref;
  2166.  ref.vb_index = amc.vblist.size() - 1;
  2167.  ref.vb_start = 0;
  2168.  ref.vb_width = n_vertices;
  2169.  ref.ib_index = amc.iblist.size() - 1;
  2170.  ref.ib_start = 0;
  2171.  ref.ib_width = n_indices;
  2172.  ref.jm_index = AMC_INVALID_JMAP_INDEX;
  2173.  surface.refs.push_back(ref);
  2174.  surface.surfmat = AMC_INVALID_SURFMAT;
  2175.  amc.surfaces.push_back(surface);
  2176.  
  2177.  // BEGIN DEBUG
  2178.  if(debug) {
  2179.     dfile << "------------" << endl;
  2180.     dfile << " TPMG CHUNK " << endl;
  2181.     dfile << "------------" << endl;
  2182.     dfile << endl;
  2183.     dfile << "p01 = 0x" << setfill('0') << setw(4) << hex << info.p01 << dec << endl;
  2184.     dfile << "p02 = 0x" << setfill('0') << setw(4) << hex << info.p02 << dec << endl;
  2185.     dfile << "p03 = 0x" << setfill('0') << setw(4) << hex << info.p03 << dec << endl;
  2186.     dfile << "p04 = 0x" << setfill('0') << setw(8) << hex << info.p04 << dec << endl;
  2187.     dfile << "p05 = 0x" << setfill('0') << setw(4) << hex << info.p05 << dec << endl;
  2188.     dfile << "p06 = 0x" << setfill('0') << setw(8) << hex << info.p06 << dec << endl;
  2189.     dfile << "p07 = 0x" << setfill('0') << setw(4) << hex << info.p07 << dec << endl;
  2190.     dfile << "p08 = 0x" << setfill('0') << setw(4) << hex << info.p08 << dec << endl;
  2191.     dfile << "p09 = 0x" << setfill('0') << setw(4) << hex << info.p09 << dec << endl;
  2192.     dfile << "p10 = 0x" << setfill('0') << setw(4) << hex << info.p10 << dec << endl;
  2193.     dfile << "p11 = 0x" << setfill('0') << setw(4) << hex << info.p11 << dec << endl;
  2194.     dfile << "p12 = 0x" << setfill('0') << setw(4) << hex << info.p12 << dec << " offset to vertex buffer" << endl;
  2195.     dfile << "p13 = 0x" << setfill('0') << setw(4) << hex << info.p13 << dec << endl;
  2196.     dfile << "p14 = 0x" << setfill('0') << setw(4) << hex << info.p14 << dec << endl;
  2197.     dfile << "p15 = 0x" << setfill('0') << setw(4) << hex << info.p15 << dec << endl;
  2198.     dfile << "p16 = 0x" << setfill('0') << setw(4) << hex << info.p16 << dec << endl;
  2199.     dfile << "p17 = 0x" << setfill('0') << setw(4) << hex << info.p17 << dec << endl;
  2200.     dfile << "p18 = 0x" << setfill('0') << setw(4) << hex << info.p18 << dec << endl;
  2201.     dfile << "p19 = 0x" << setfill('0') << setw(4) << hex << info.p19 << dec << endl;
  2202.     dfile << "p20 = 0x" << setfill('0') << setw(4) << hex << info.p20 << dec << endl;
  2203.     dfile << "p21 = 0x" << setfill('0') << setw(4) << hex << info.p21 << dec << endl;
  2204.     dfile << "p22 = 0x" << setfill('0') << setw(4) << hex << info.p22 << dec << endl;
  2205.     dfile << "p23 = 0x" << setfill('0') << setw(4) << hex << info.p23 << dec << endl;
  2206.     dfile << "p24 = 0x" << setfill('0') << setw(4) << hex << info.p24 << dec << endl;
  2207.     dfile << "p25 = 0x" << setfill('0') << setw(4) << hex << info.p25 << dec << endl;
  2208.     dfile << "p26 = 0x" << setfill('0') << setw(4) << hex << info.p26 << dec << endl;
  2209.     dfile << "p27 = 0x" << setfill('0') << setw(4) << hex << info.p27 << dec << endl;
  2210.     dfile << "p28 = 0x" << setfill('0') << setw(4) << hex << info.p28 << dec << endl;
  2211.     dfile << "p29 = 0x" << setfill('0') << setw(8) << hex << info.p29 << dec << endl;
  2212.     dfile << "p30 = 0x" << setfill('0') << setw(8) << hex << info.p30 << dec << endl;
  2213.     dfile << "p31 = 0x" << setfill('0') << setw(8) << hex << info.p31 << dec << endl;
  2214.     dfile << "vertex stride = 0x" << setfill('0') << setw(8) << hex << vertex_stride << dec << endl;
  2215.     dfile << "number of vertices = 0x" << setfill('0') << setw(8) << hex << n_vertices << dec << endl;
  2216.     dfile << endl;
  2217.    }
  2218.  // END DEBUG
  2219.  
  2220.  // skip past data
  2221.  bs.seek(position + h02);
  2222.  if(bs.fail()) return error("Stream seek failure.");
  2223.  
  2224.  return true;
  2225. }
  2226.  
  2227. bool MDLProcess::processHMTA(void)
  2228. {
  2229.  // read header
  2230.  uint32 h01 = bs.BE_read_uint32(); // HMTA
  2231.  uint32 h02 = bs.BE_read_uint32(); // size of chunk minus 0x10-byte header
  2232.  uint32 h03 = bs.BE_read_uint32(); // number of CMTA chunks (number also appears in 2HMG chunk)
  2233.  uint32 h04 = bs.BE_read_uint32(); // unknown 0x00
  2234.  
  2235.  // validate header
  2236.  if(h01 != 0x484D5441) return error("Invalid HMTA.");
  2237.  if(h04 != 0x00) return error("HMTA h04 expecting 0x00.");
  2238.  
  2239.  // next
  2240.  // data
  2241.  
  2242.  // skip past data for now
  2243.  bs.move(h02);
  2244.  if(bs.fail()) return error("Stream seek failure.");
  2245.  
  2246.  return true;
  2247. }
  2248.  
  2249. bool MDLProcess::processDMBS(void)
  2250. {
  2251.  // peek header and skip if not DMBS
  2252.  uint32 p01 = bs.BE_peek_uint32();
  2253.  if(p01 != 0x444E4253) return true;
  2254.  
  2255.  // read header
  2256.  uint32 h01 = bs.BE_read_uint32(); // DMBS
  2257.  uint32 h02 = bs.BE_read_uint32(); // size of chunk minus 0x10-byte header
  2258.  uint32 h03 = bs.BE_read_uint32(); // unknown 0x00
  2259.  uint32 h04 = bs.BE_read_uint32(); // unknown 0x00
  2260.  
  2261.  // validate header
  2262.  if(h01 != 0x444E4253) return error("Invalid DMBS.");
  2263.  if(h03 != 0x00) return error("DMBS h03 expecting 0x00.");
  2264.  if(h04 != 0x00) return error("DMBS h04 expecting 0x00.");
  2265.  
  2266.  // skip past data for now
  2267.  bs.move(h02);
  2268.  if(bs.fail()) return error("Stream seek failure.");
  2269.  
  2270.  return true;
  2271. }
  2272.  
  2273. bool MDLProcess::processADOL(void)
  2274. {
  2275.  // read header
  2276.  uint32 h01 = bs.BE_read_uint32(); // ADOL
  2277.  uint32 h02 = bs.BE_read_uint32(); // size of chunk minus 0x10-byte header
  2278.  uint32 h03 = bs.BE_read_uint32(); // unknown 0x00
  2279.  uint32 h04 = bs.BE_read_uint32(); // unknown 0x00
  2280.  
  2281.  // validate header
  2282.  if(h01 != 0x41444F4C) return error("Invalid ADOL.");
  2283.  if(h02 != 0x00) return error("ADOL h02 expecting 0x00.");
  2284.  if(h03 != 0x00) return error("ADOL h03 expecting 0x00.");
  2285.  if(h04 != 0x00) return error("ADOL h04 expecting 0x00.");
  2286.  
  2287.  // skip past data for now
  2288.  bs.move(h02);
  2289.  if(bs.fail()) return error("Stream seek failure.");
  2290.  
  2291.  return true;
  2292. }
  2293.  
  2294. bool MDLProcess::processDONE(void)
  2295. {
  2296.  // read header
  2297.  uint32 h01 = bs.BE_read_uint32(); // DONE
  2298.  uint32 h02 = bs.BE_read_uint32(); // size of chunk minus 0x10-byte header
  2299.  uint32 h03 = bs.BE_read_uint32(); // unknown 0x00
  2300.  uint32 h04 = bs.BE_read_uint32(); // unknown 0x00
  2301.  
  2302.  // validate header
  2303.  if(h01 != 0x20444E45) return error("Invalid DONE.");
  2304.  if(h02 != 0x00) return error("DONE h02 expecting 0x00.");
  2305.  if(h03 != 0x00) return error("DONE h03 expecting 0x00.");
  2306.  if(h04 != 0x00) return error("DONE h04 expecting 0x00.");
  2307.  
  2308.  // skip past data for now
  2309.  bs.move(h02);
  2310.  if(bs.fail()) return error("Stream seek failure.");
  2311.  
  2312.  return true;
  2313. }
  2314.  
  2315. bool processMDL(LPCTSTR filename)
  2316. {
  2317.  MDLProcess obj;
  2318.  return obj.extract(filename);
  2319. }
  2320.  
  2321. };};
  2322.  
  2323. //
  2324. // FUNCTIONS
  2325. //
  2326.  
  2327. namespace X_SYSTEM { namespace X_GAME {
  2328.  
  2329. bool add_title(void)
  2330. {
  2331.  // title
  2332.  STDSTRING p1;
  2333.  p1 += TEXT("[PS3] Macross 30 (Beta)");
  2334.  
  2335.  // instructions
  2336.  STDSTRING p2;
  2337.  p2 += TEXT("1. Do not run still in beta.");
  2338.  
  2339.  // notes
  2340.  STDSTRING p3;
  2341.  p3 += TEXT("1. Do not run still in beta.");
  2342.  
  2343.  // insert title
  2344.  AddGameTitle(p1.c_str(), p2.c_str(), p3.c_str(), extract);
  2345.  return true;
  2346. }
  2347.  
  2348. bool extract(void)
  2349. {
  2350.  STDSTRING pathname = GetModulePathname().get();
  2351.  return extract(pathname.c_str());
  2352. }
  2353.  
  2354. bool extract(LPCTSTR pname)
  2355. {
  2356.  // set pathname
  2357.  using namespace std;
  2358.  STDSTRING pathname(pname);
  2359.  if(!pathname.length()) pathname = GetModulePathname().get();
  2360.  
  2361.  // variables
  2362.  bool doDAT = true;
  2363.  bool doFST = true;
  2364.  bool doGFP = true;
  2365.  bool doMDL = true;
  2366.  
  2367.  if(doDAT) doDAT = YesNoBox("Process DAT (archive) files?\nClick 'No' if you have already done so.");
  2368.  if(doFST) doFST = YesNoBox("Process FST (archive) files?\nClick 'No' if you have already done so.");
  2369.  if(doGFP) doGFP = YesNoBox("Process GFP (texture) files?\nClick 'No' if you have already done so.");
  2370.  if(doMDL) doMDL = YesNoBox("Process MDL (model) files?\nClick 'No' if you have already done so.");
  2371.  
  2372.  // process archive
  2373.  cout << "STAGE 1" << endl;
  2374.  if(doDAT) {
  2375.     cout << "Processing .DAT files..." << endl;
  2376.     deque<STDSTRING> filelist;
  2377.     BuildFilenameList(filelist, TEXT(".DAT"), pathname.c_str());
  2378.     for(size_t i = 0; i < filelist.size(); i++) {
  2379.         wcout << "Processing file " << (i + 1) << " of " << filelist.size() << ": " << filelist[i] << "." << endl;
  2380.         if(!processDAT(filelist[i].c_str())) return false;
  2381.        }
  2382.     cout << endl;
  2383.    }
  2384.  
  2385.  // process archive
  2386.  cout << "STAGE 2" << endl;
  2387.  if(doFST) {
  2388.     cout << "Processing .FST files..." << endl;
  2389.     deque<STDSTRING> filelist;
  2390.     BuildFilenameList(filelist, TEXT(".FSTS"), pathname.c_str());
  2391.     for(size_t i = 0; i < filelist.size(); i++) {
  2392.         wcout << "Processing file " << (i + 1) << " of " << filelist.size() << ": " << filelist[i] << "." << endl;
  2393.         if(!processFST(filelist[i].c_str())) return false;
  2394.        }
  2395.     cout << endl;
  2396.    }
  2397.  
  2398.  // process archive
  2399.  cout << "STAGE 3" << endl;
  2400.  if(doGFP) {
  2401.     cout << "Processing .GFP files..." << endl;
  2402.     deque<STDSTRING> filelist;
  2403.     BuildFilenameList(filelist, TEXT(".GFP"), pathname.c_str());
  2404.     for(size_t i = 0; i < filelist.size(); i++) {
  2405.         wcout << "Processing file " << (i + 1) << " of " << filelist.size() << ": " << filelist[i] << "." << endl;
  2406.         if(!processGFP(filelist[i].c_str())) return false;
  2407.        }
  2408.     cout << endl;
  2409.    }
  2410.  
  2411.  // process archive
  2412.  cout << "STAGE 4" << endl;
  2413.  if(doMDL) {
  2414.     cout << "Processing .MDL files..." << endl;
  2415.     deque<STDSTRING> filelist;
  2416.     BuildFilenameList(filelist, TEXT(".MDL"), pathname.c_str());
  2417.     for(size_t i = 0; i < filelist.size(); i++) {
  2418.         wcout << "Processing file " << (i + 1) << " of " << filelist.size() << ": " << filelist[i] << "." << endl;
  2419.         if(!processMDL(filelist[i].c_str())) return false;
  2420.        }
  2421.     cout << endl;
  2422.    }
  2423.  
  2424.  return true;
  2425. }
  2426.  
  2427. }};
  2428.  
  2429.