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

  1. #include "xentax.h"
  2. #include "x_findfile.h"
  3. #include "x_file.h"
  4. #include "x_stream.h"
  5. #include "x_dds.h"
  6. #include "x_lwo.h"
  7. #include "x_smc.h"
  8. #include "x_pssg.h"
  9.  
  10. namespace PSSG {
  11.  
  12. struct PSSGPARAMETER {
  13.  std::string name;
  14. };
  15.  
  16. struct PSSGATTRIBUTE {
  17.  std::string parameter;
  18.  std::string attribute;
  19. };
  20.  
  21. struct BUFFERDATA {
  22.  uint32 elementCount;
  23.  std::string renderType;
  24.  std::string dataType;
  25.  uint32 offset;
  26.  uint32 stride;
  27.  boost::shared_array<char> data;
  28. };
  29.  
  30. struct RENDERDATA {
  31.  uint32 streamCount;                      // RENDERDATASOURCE:streamCount
  32.  std::string primitive;                   // RENDERINDEXSOURCE:primitive (if any)
  33.  std::string format;                      // RENDERINDEXSOURCE:format (if any)
  34.  uint32 count;                            // RENDERINDEXSOURCE:count (if any)
  35.  std::string id;                          // RENDERINDEXSOURCE:id (if any)
  36.  boost::shared_array<char> buffer;        // INDEXSOURCEDATA:data (if any)
  37.  boost::shared_array<std::string> blocks; // RENDERSTREAM[streamCount]:dataBlock (reference to Vertex, Normal, ST buffers)
  38. };
  39.  
  40. class extractor {
  41.  private :
  42.   std::string pathname;
  43.   std::string currfile;
  44.   std::ofstream dfile;
  45.   bool debug;
  46.  // tree nodes
  47.  private:
  48.   std::map<uint32, PSSGPARAMETER> nodelist;
  49.   std::map<uint32, PSSGATTRIBUTE> attrlist;
  50.   std::deque<uint32> offsets;  
  51.   std::map<uint32, uint32> parent_list;
  52.  // tree
  53.  private :
  54.   typedef std::map<uint32, boost::shared_ptr<TREENODE>> tree_type;
  55.   typedef tree_type::iterator tree_iterator;
  56.   typedef tree_type::value_type tree_node;
  57.   std::map<uint32, boost::shared_ptr<TREENODE>> tree;
  58.  // buffer map (vtx buffers)
  59.  private :
  60.   typedef std::map<std::string, BUFFERDATA> buffer_map_type;
  61.   typedef std::map<std::string, BUFFERDATA>::value_type buffer_map_value_type;
  62.   std::map<std::string, BUFFERDATA> buffer_map; // store buffers by name
  63.  // render map (idx buffers)
  64.  private :
  65.   typedef std::map<std::string, RENDERDATA> render_map_type;
  66.   typedef std::map<std::string, RENDERDATA>::value_type render_map_value_type;
  67.   std::map<std::string, RENDERDATA> render_map; // store buffers by name
  68.  private :
  69.   bool readAttributes(binary_stream& bs, const char* name);
  70.   bool readString(binary_stream& bs, std::string& str) {
  71.    uint32 size = bs.BE_read_uint32();
  72.    if(bs.fail()) return false;
  73.    char buffer[1024];
  74.    bs.read(buffer, size);
  75.    if(bs.fail()) return false;
  76.    buffer[size] = '\0';
  77.    str = buffer;
  78.    return true;
  79.   }
  80.   bool readNumber(binary_stream& bs, uint32& data) {
  81.    data = bs.BE_read_uint32();
  82.    return !bs.fail();
  83.   }
  84.   bool readVector3(binary_stream& bs, real32* data) {
  85.    data[0] = bs.BE_read_real32(); if(bs.fail()) return false;
  86.    data[1] = bs.BE_read_real32(); if(bs.fail()) return false;
  87.    data[2] = bs.BE_read_real32(); if(bs.fail()) return false;
  88.    return true;
  89.   }
  90.  private :
  91.   void clear(void);
  92.   bool processFile(const char* filename);
  93.   bool processParameter(const binary_stream& bs);
  94.   bool processChildren(const binary_stream& bs, boost::shared_ptr<TREENODE> node, uint32 parent, uint32 limit);
  95.   bool processTree(unsigned int node, unsigned int level);
  96.   bool processVertexBuffer(tree_iterator iter);
  97.   bool processRenderBuffer(tree_iterator iter);
  98.   bool processModel(void)const;
  99.  private :
  100.   bool processPSSGDATABASE(const binary_stream& bs, uint32 position);
  101.   bool processANIMATION(const binary_stream& bs, uint32 position);
  102.   bool processANIMATIONCHANNEL(const binary_stream& bs, uint32 position);
  103.   bool processANIMATIONCHANNELDATABLOCK(const binary_stream& bs, uint32 position);
  104.   bool processANIMATIONREF(const binary_stream& bs, uint32 position);
  105.   bool processANIMATIONSET(const binary_stream& bs, uint32 position);
  106.   bool processBOUNDINGBOX(const binary_stream& bs, uint32 position);
  107.   bool processCAMERANODE(const binary_stream& bs, uint32 position);
  108.   bool processCGSTREAM(const binary_stream& bs, uint32 position);
  109.   bool processCHANNELREF(const binary_stream& bs, uint32 position);
  110.   bool processCONSTANTCHANNEL(const binary_stream& bs, uint32 position);
  111.   bool processCUBEMAPTEXTURE(const binary_stream& bs, uint32 position);
  112.   bool processDATABLOCK(const binary_stream& bs, uint32 position);
  113.   bool processDATABLOCKDATA(const binary_stream& bs, uint32 position);
  114.   bool processDATABLOCKSTREAM(const binary_stream& bs, uint32 position);
  115.   bool processGLPASS(const binary_stream& bs, uint32 position);
  116.   bool processGLSHADER(const binary_stream& bs, uint32 position);
  117.   bool processGLSTATE(const binary_stream& bs, uint32 position);
  118.   bool processINDEXSOURCEDATA(const binary_stream& bs, uint32 position);
  119.   bool processINVERSEBINDMATRIX(const binary_stream& bs, uint32 position);
  120.   bool processJOINTNODE(const binary_stream& bs, uint32 position);
  121.   bool processKEYS(const binary_stream& bs, uint32 position);
  122.   bool processLIBRARY(const binary_stream& bs, uint32 position);
  123.   bool processLIGHTNODE(const binary_stream& bs, uint32 position);
  124.   bool processMODIFIERNETWORK(const binary_stream& bs, uint32 position);
  125.   bool processMODIFIERNETWORKCONNECTION(const binary_stream& bs, uint32 position);
  126.   bool processMODIFIERNETWORKENTRY(const binary_stream& bs, uint32 position);
  127.   bool processMODIFIERNETWORKINSTANCE(const binary_stream& bs, uint32 position);
  128.   bool processMODIFIERNETWORKINSTANCECOMPILE(const binary_stream& bs, uint32 position);
  129.   bool processMODIFIERNETWORKINSTANCEDYNAMICSTREAM(const binary_stream& bs, uint32 position);
  130.   bool processMODIFIERNETWORKINSTANCEDYNAMICSTREAMTYPE(const binary_stream& bs, uint32 position);
  131.   bool processMODIFIERNETWORKINSTANCEMODIFIERINPUT(const binary_stream& bs, uint32 position);
  132.   bool processMODIFIERNETWORKINSTANCEUNIQUEINPUT(const binary_stream& bs, uint32 position);
  133.   bool processMODIFIERNETWORKINSTANCEUNIQUEMODIFIERINPUT(const binary_stream& bs, uint32 position);
  134.   bool processMORPHMODIFIERWEIGHTS(const binary_stream& bs, uint32 position);
  135.   bool processNODE(const binary_stream& bs, uint32 position);
  136.   bool processRENDERDATASOURCE(const binary_stream& bs, uint32 position);
  137.   bool processRENDERINDEXSOURCE(const binary_stream& bs, uint32 position);
  138.   bool processRENDERINSTANCE(const binary_stream& bs, uint32 position);
  139.   bool processRENDERINSTANCESOURCE(const binary_stream& bs, uint32 position);
  140.   bool processRENDERINSTANCESTREAM(const binary_stream& bs, uint32 position);
  141.   bool processRENDERINTERFACEBOUND(const binary_stream& bs, uint32 position);
  142.   bool processRENDERNODE(const binary_stream& bs, uint32 position);
  143.   bool processRENDERSTREAM(const binary_stream& bs, uint32 position);
  144.   bool processRENDERSTREAMINSTANCE(const binary_stream& bs, uint32 position);
  145.   bool processRISTREAM(const binary_stream& bs, uint32 position);
  146.   bool processROOTNODE(const binary_stream& bs, uint32 position);
  147.   bool processSEGMENTSET(const binary_stream& bs, uint32 position);
  148.   bool processSHADER(const binary_stream& bs, uint32 position);
  149.   bool processSHADERGROUP(const binary_stream& bs, uint32 position);
  150.   bool processSHADERGROUPPASS(const binary_stream& bs, uint32 position);
  151.   bool processSHADERINPUT(const binary_stream& bs, uint32 position);
  152.   bool processSHADERINPUTDEFINITION(const binary_stream& bs, uint32 position);
  153.   bool processSHADERINSTANCE(const binary_stream& bs, uint32 position);
  154.   bool processSHADERPROGRAM(const binary_stream& bs, uint32 position);
  155.   bool processSHADERPROGRAMCODE(const binary_stream& bs, uint32 position);
  156.   bool processSHADERPROGRAMCODEBLOCK(const binary_stream& bs, uint32 position);
  157.   bool processSHADERSTREAMDEFINITION(const binary_stream& bs, uint32 position);
  158.   bool processSKELETON(const binary_stream& bs, uint32 position);
  159.   bool processSKINJOINT(const binary_stream& bs, uint32 position);
  160.   bool processSKINNODE(const binary_stream& bs, uint32 position);
  161.   bool processTEXTURE(const binary_stream& bs, uint32 position);
  162.   bool processTEXTUREIMAGEBLOCK(const binary_stream& bs, uint32 position);
  163.   bool processTEXTUREIMAGEBLOCKDATA(const binary_stream& bs, uint32 position);
  164.   bool processTRANSFORM(const binary_stream& bs, uint32 position);
  165.   bool processTYPEINFO(const binary_stream& bs, uint32 position);
  166.   bool processUSERATTRIBUTE(const binary_stream& bs, uint32 position);
  167.   bool processUSERATTRIBUTELIST(const binary_stream& bs, uint32 position);
  168.   bool processUSERDATA(const binary_stream& bs, uint32 position);
  169.   bool processWEIGHTS(const binary_stream& bs, uint32 position);
  170.   bool processXXX(const binary_stream& bs, uint32 position);
  171.  public :
  172.   bool extract(void);
  173.  public :
  174.   extractor(const char* pn);
  175.  ~extractor();
  176. };
  177.  
  178. };
  179.  
  180. namespace PSSG {
  181.  
  182. extractor::extractor(const char* pn) : pathname(pn), debug(true)
  183. {
  184. }
  185.  
  186. extractor::~extractor()
  187. {
  188. }
  189.  
  190. bool extractor::extract(void)
  191. {
  192.  // 
  193.  std::deque<std::string> filelist;
  194.  BuildFilenameList(filelist, "pssg", pathname.c_str());
  195.  for(size_t i = 0; i < filelist.size(); i++) {
  196.      std::cout << "Processing file " << (i + 1) << " of " << filelist.size() << ": " << filelist[i] << "." << std::endl;
  197.      if(!processFile(filelist[i].c_str())) return false;
  198.     }
  199.  std::cout << std::endl;
  200.  
  201.  return true;
  202. }
  203.  
  204. void extractor::clear(void)
  205. {
  206.  // clear buffers
  207.  buffer_map.clear();
  208.  render_map.clear();
  209.  
  210.  // clear previous data
  211.  nodelist.clear();
  212.  attrlist.clear();
  213.  tree.clear();
  214.  
  215.  // clear node stack
  216.  offsets.clear();
  217.  
  218.  // clear <node, parent node> map
  219.  parent_list.clear();
  220.  
  221.  // clear current filename
  222.  currfile.clear();
  223. }
  224.  
  225. bool extractor::processFile(const char* filename)
  226. {
  227.  using namespace std;
  228.  
  229.  // clear previous data and set current filename
  230.  clear();
  231.  currfile = filename;
  232.  
  233.  // create output file
  234.  if(debug) {
  235.     stringstream ss;
  236.     ss << GetPathnameFromFilename(currfile) << GetShortFilenameWithoutExtension(currfile) << ".txt";
  237.     dfile.close();
  238.     dfile.open(ss.str().c_str());
  239.     if(!dfile) return error("Failed to create debug file.");
  240.    }
  241.  
  242.  // open file
  243.  ifstream ifile(currfile.c_str(), std::ios::binary);
  244.  if(!ifile) return error("Failed to open PSSG file.");
  245.  
  246.  // compute filesize
  247.  ifile.seekg(0, ios::end);
  248.  uint32 filesize = (uint32)ifile.tellg();
  249.  ifile.seekg(0, ios::beg);
  250.  
  251.  // read file
  252.  boost::shared_array<char> filedata(new char[filesize]);
  253.  ifile.read(filedata.get(), filesize);
  254.  if(ifile.fail()) return error("Read failure.");
  255.  
  256.  // create binary stream
  257.  binary_stream bs(filedata, filesize);
  258.  
  259.  // read PSSG
  260.  unsigned int chunkname = bs.BE_read_uint32();
  261.  if(chunkname != 0x50535347) return error("Expecting PSSG chunk.");
  262.  
  263.  // read PSSG chunksize
  264.  unsigned int chunksize = bs.BE_read_uint32();
  265.  if(chunksize == 0) return error("Invalid PSSG chunksize.");
  266.  
  267.  // number of properties + 1
  268.  unsigned int n_properties = bs.BE_read_uint32();
  269.  if(n_properties > 9999) return error("Read an unexpected number of PSSG properties.");
  270.  
  271.  // number of parameters (each parameter has 0 or more properties)
  272.  unsigned int n_parameters = bs.BE_read_uint32();
  273.  if(n_parameters > 9999) return error("Read an unexpected number of PSSG parameters.");
  274.  
  275.  // read parameters
  276.  for(unsigned int i = 0; i < n_parameters; i++)
  277.     {
  278.      // read parameter index
  279.      uint32 index = bs.BE_read_uint32();
  280.      if(bs.fail()) return error("Read failure.");
  281.      if(index != i + 1) return error("Integer parameter index does not match.");
  282.  
  283.      // read parameter length
  284.      uint32 length = bs.BE_read_uint32();
  285.      if(bs.fail()) return error("Read failure.");
  286.  
  287.      // read parameter name
  288.      char parameter_name[128];
  289.      bs.BE_read_array(¶meter_name[0], length);
  290.      if(bs.fail()) return error("Read failure.");
  291.      parameter_name[length] = '\0';
  292.  
  293.      // debug
  294.      if(debug) dfile << parameter_name << " [" << index << "]" << endl;
  295.  
  296.      // macros
  297.      #define FIRST_TEST(TESTNAME) if(strcmp(parameter_name, TESTNAME) == 0) { if(!readAttributes(bs, TESTNAME)) return false; }
  298.      #define OTHER_TEST(TESTNAME) else if(strcmp(parameter_name, TESTNAME) == 0) { if(!readAttributes(bs, TESTNAME)) return false; }
  299.      #define FINAL_TEST else { stringstream ss; ss << "Unknown parameter type " << parameter_name << "." << ends; return error(ss.str().c_str()); }
  300.  
  301.      // read properties
  302.      FIRST_TEST("ANIMATION")
  303.      OTHER_TEST("ANIMATIONCHANNEL")
  304.      OTHER_TEST("ANIMATIONCHANNELDATABLOCK")
  305.      OTHER_TEST("ANIMATIONREF")
  306.      OTHER_TEST("ANIMATIONSET")
  307.      OTHER_TEST("BOUNDINGBOX")
  308.      OTHER_TEST("CAMERANODE")
  309.      OTHER_TEST("CGSTREAM")
  310.      OTHER_TEST("CHANNELREF")
  311.      OTHER_TEST("CONSTANTCHANNEL")
  312.      OTHER_TEST("CUBEMAPTEXTURE") // new
  313.      OTHER_TEST("DATABLOCK")
  314.      OTHER_TEST("DATABLOCKDATA")
  315.      OTHER_TEST("DATABLOCKSTREAM")
  316.      OTHER_TEST("GLPASS") // new
  317.      OTHER_TEST("GLSHADER") // new
  318.      OTHER_TEST("GLSTATE") // new
  319.      OTHER_TEST("INDEXSOURCEDATA")
  320.      OTHER_TEST("INVERSEBINDMATRIX")
  321.      OTHER_TEST("JOINTNODE")
  322.      OTHER_TEST("KEYS")
  323.      OTHER_TEST("LIBRARY")
  324.      OTHER_TEST("LIGHTNODE")
  325.      OTHER_TEST("MODIFIERNETWORK")
  326.      OTHER_TEST("MODIFIERNETWORKCONNECTION")
  327.      OTHER_TEST("MODIFIERNETWORKENTRY")
  328.      OTHER_TEST("MODIFIERNETWORKINSTANCE")
  329.      OTHER_TEST("MODIFIERNETWORKINSTANCECOMPILE")
  330.      OTHER_TEST("MODIFIERNETWORKINSTANCEDYNAMICSTREAM")
  331.      OTHER_TEST("MODIFIERNETWORKINSTANCEDYNAMICSTREAMTYPE")
  332.      OTHER_TEST("MODIFIERNETWORKINSTANCEMODIFIERINPUT")
  333.      OTHER_TEST("MODIFIERNETWORKINSTANCEUNIQUEINPUT")
  334.      OTHER_TEST("MODIFIERNETWORKINSTANCEUNIQUEMODIFIERINPUT")
  335.      OTHER_TEST("MORPHMODIFIERWEIGHTS")
  336.      OTHER_TEST("NODE")
  337.      OTHER_TEST("PSSGDATABASE")
  338.      OTHER_TEST("RENDERDATASOURCE")
  339.      OTHER_TEST("RENDERINDEXSOURCE")
  340.      OTHER_TEST("RENDERINSTANCE")
  341.      OTHER_TEST("RENDERINSTANCESOURCE")
  342.      OTHER_TEST("RENDERINSTANCESTREAM")
  343.      OTHER_TEST("RENDERINTERFACEBOUND")
  344.      OTHER_TEST("RENDERNODE")
  345.      OTHER_TEST("RENDERSTREAM")
  346.      OTHER_TEST("RENDERSTREAMINSTANCE")
  347.      OTHER_TEST("RISTREAM")
  348.      OTHER_TEST("ROOTNODE")
  349.      OTHER_TEST("SEGMENTSET")
  350.      OTHER_TEST("SHADER") // new
  351.      OTHER_TEST("SHADERGROUP")
  352.      OTHER_TEST("SHADERGROUPPASS")
  353.      OTHER_TEST("SHADERINPUT")
  354.      OTHER_TEST("SHADERINPUTDEFINITION")
  355.      OTHER_TEST("SHADERINSTANCE")
  356.      OTHER_TEST("SHADERPROGRAM")
  357.      OTHER_TEST("SHADERPROGRAMCODE")
  358.      OTHER_TEST("SHADERPROGRAMCODEBLOCK")
  359.      OTHER_TEST("SHADERSTREAMDEFINITION")
  360.      OTHER_TEST("SKELETON")
  361.      OTHER_TEST("SKINJOINT")
  362.      OTHER_TEST("SKINNODE")
  363.      OTHER_TEST("TEXTURE")
  364.      OTHER_TEST("TEXTUREIMAGEBLOCK")
  365.      OTHER_TEST("TEXTUREIMAGEBLOCKDATA")
  366.      OTHER_TEST("TRANSFORM")
  367.      OTHER_TEST("TYPEINFO")
  368.      OTHER_TEST("USERATTRIBUTE")
  369.      OTHER_TEST("USERATTRIBUTELIST")
  370.      OTHER_TEST("USERDATA")
  371.      OTHER_TEST("WEIGHTS")
  372.      OTHER_TEST("XXX")
  373.      FINAL_TEST
  374.  
  375.      // add parameter to map
  376.      typedef map<uint32, PSSGPARAMETER>::value_type value_type;
  377.      PSSGPARAMETER temp;
  378.      temp.name = parameter_name;
  379.      nodelist.insert(value_type(index, temp));
  380.     }
  381.  
  382.  // process offsets
  383.  uint32 root = (uint32)bs.tell();
  384.  offsets.push_back(root);
  385.  while(offsets.size()) { if(!processParameter(bs)) return false; }
  386.  
  387.  // traverse tree
  388.  if(debug) dfile << endl;
  389.  if(debug) dfile << "-----------" << endl;
  390.  if(debug) dfile << " PSSG TREE " << endl;
  391.  if(debug) dfile << "-----------" << endl;
  392.  
  393.  unsigned int level = 0;
  394.  if(!processTree(root, level)) return false;
  395.  
  396.  // save model
  397.  return processModel();
  398. }
  399.  
  400. bool extractor::readAttributes(binary_stream& bs, const char* name)
  401. {
  402.  using namespace std;
  403.  
  404.  // get number of attributes
  405.  uint32 items = bs.BE_read_uint32();
  406.  if(items > 9999) return error("Read an unexpected number of attributes.");
  407.  
  408.  // read attributes
  409.  for(size_t i = 0; i < items; i++)
  410.     {
  411.      // read attribute index
  412.      uint32 index = bs.BE_read_uint32();
  413.      if(bs.fail()) return error("Read failure.");
  414.  
  415.      // read attribute string length
  416.      uint32 namesize = bs.BE_read_uint32();
  417.      if(bs.fail()) return error("Read failure.");
  418.  
  419.      // read attribute name
  420.      boost::shared_array<char> attribute_name(new char[namesize + 1]);
  421.      bs.read(attribute_name.get(), namesize);
  422.      if(bs.fail()) return error("Read failure.");
  423.      attribute_name[namesize] = '\0';
  424.  
  425.      // set attribute
  426.      PSSGATTRIBUTE attr;
  427.      attr.parameter = name;
  428.      attr.attribute = attribute_name.get();
  429.      attrlist.insert(map<uint32, PSSGATTRIBUTE>::value_type(index, attr));
  430.  
  431.      // debug
  432.      if(debug) dfile << " " << attr.attribute << " [" << index << "]" << endl;
  433.     }
  434.  
  435.  return true;
  436. }
  437.  
  438. bool extractor::processChildren(const binary_stream& bs, boost::shared_ptr<TREENODE> node, uint32 parent, uint32 limit)
  439. {
  440.  // copy stream
  441.  using namespace std;
  442.  binary_stream stream(bs);
  443.  
  444.  // add child chunks to stack
  445.  uint32 bytes_read = 0;
  446.  while(bytes_read < limit)
  447.       {
  448.        // save offset
  449.        uint32 offset = (uint32)stream.tell();
  450.        offsets.push_back(offset);
  451.        node->children.push_back(offset);
  452.  
  453.        // save child/parent
  454.        typedef map<unsigned int, unsigned int>::value_type value_type;
  455.        parent_list.insert(value_type(offset, parent));
  456.  
  457.        // read chunk data
  458.        unsigned int chunktype = stream.BE_read_uint32(); if(stream.fail()) return error("Read failure.");
  459.        unsigned int chunksize = stream.BE_read_uint32(); if(stream.fail()) return error("Read failure.");
  460.        bytes_read += 4;
  461.        bytes_read += 4;
  462.        bytes_read += chunksize;
  463.  
  464.        // debug information
  465.        typedef map<uint32, PSSGPARAMETER>::iterator iterator;
  466.        iterator iter = nodelist.find(chunktype);
  467.        if(iter == nodelist.end()) return error("Typename not found during scan for child chunks.");
  468.        if(debug) dfile << "(offset, name, parent) = " << "(" << offset << "," << iter->second.name << "," << parent << ")" << endl;
  469.  
  470.        // skip data
  471.        stream.move(chunksize);
  472.       }
  473.  
  474.  return true;
  475. }
  476.  
  477. bool extractor::processParameter(const binary_stream& bs)
  478. {
  479.  using namespace std;
  480.  
  481.  // read offset from top of stack
  482.  unsigned position = offsets.front();
  483.  offsets.pop_front();
  484.  
  485.  // seek position
  486.  binary_stream stream(bs);
  487.  stream.seek(position);
  488.  
  489.  // read chunktype
  490.  unsigned int chunktype = stream.BE_read_uint32();
  491.  if(stream.at_end()) return true;
  492.  else if(stream.fail()) return error("Read failure.");
  493.  
  494.  // find parameter
  495.  typedef map<uint32, PSSGPARAMETER>::iterator iterator;
  496.  iterator iter = nodelist.find(chunktype);
  497.  if(iter == nodelist.end()) {
  498.     stringstream ss;
  499.     ss << "Could not find parameter at index " << chunktype << "." << ends;
  500.     return error(ss.str().c_str());
  501.    }
  502.  
  503.  #define FIRST_PARAMETER_TEST(nodename) if(iter->second.name == #nodename) return process##nodename##(stream, position)
  504.  #define OTHER_PARAMETER_TEST(nodename) else if(iter->second.name == #nodename) return process##nodename##(stream, position)
  505.  
  506.  // process parameter
  507.  FIRST_PARAMETER_TEST(PSSGDATABASE);
  508.  OTHER_PARAMETER_TEST(ANIMATION);
  509.  OTHER_PARAMETER_TEST(ANIMATIONCHANNEL);
  510.  OTHER_PARAMETER_TEST(ANIMATIONCHANNELDATABLOCK);
  511.  OTHER_PARAMETER_TEST(ANIMATIONREF);
  512.  OTHER_PARAMETER_TEST(ANIMATIONSET);
  513.  OTHER_PARAMETER_TEST(BOUNDINGBOX);
  514.  OTHER_PARAMETER_TEST(CAMERANODE);
  515.  OTHER_PARAMETER_TEST(CGSTREAM);
  516.  OTHER_PARAMETER_TEST(CHANNELREF);
  517.  OTHER_PARAMETER_TEST(CONSTANTCHANNEL);
  518.  OTHER_PARAMETER_TEST(CUBEMAPTEXTURE); // new
  519.  OTHER_PARAMETER_TEST(DATABLOCK);
  520.  OTHER_PARAMETER_TEST(DATABLOCKDATA);
  521.  OTHER_PARAMETER_TEST(DATABLOCKSTREAM);
  522.  OTHER_PARAMETER_TEST(GLPASS); // new
  523.  OTHER_PARAMETER_TEST(GLSHADER); // new
  524.  OTHER_PARAMETER_TEST(GLSTATE); // new
  525.  OTHER_PARAMETER_TEST(INDEXSOURCEDATA);
  526.  OTHER_PARAMETER_TEST(INVERSEBINDMATRIX);
  527.  OTHER_PARAMETER_TEST(JOINTNODE);
  528.  OTHER_PARAMETER_TEST(KEYS);
  529.  OTHER_PARAMETER_TEST(LIBRARY);
  530.  OTHER_PARAMETER_TEST(LIGHTNODE);
  531.  OTHER_PARAMETER_TEST(MODIFIERNETWORK);
  532.  OTHER_PARAMETER_TEST(MODIFIERNETWORKCONNECTION);
  533.  OTHER_PARAMETER_TEST(MODIFIERNETWORKENTRY);
  534.  OTHER_PARAMETER_TEST(MODIFIERNETWORKINSTANCE);
  535.  OTHER_PARAMETER_TEST(MODIFIERNETWORKINSTANCECOMPILE);
  536.  OTHER_PARAMETER_TEST(MODIFIERNETWORKINSTANCEDYNAMICSTREAM);
  537.  OTHER_PARAMETER_TEST(MODIFIERNETWORKINSTANCEDYNAMICSTREAMTYPE);
  538.  OTHER_PARAMETER_TEST(MODIFIERNETWORKINSTANCEMODIFIERINPUT);
  539.  OTHER_PARAMETER_TEST(MODIFIERNETWORKINSTANCEUNIQUEINPUT);
  540.  OTHER_PARAMETER_TEST(MODIFIERNETWORKINSTANCEUNIQUEMODIFIERINPUT);
  541.  OTHER_PARAMETER_TEST(MORPHMODIFIERWEIGHTS);
  542.  OTHER_PARAMETER_TEST(NODE);
  543.  OTHER_PARAMETER_TEST(RENDERDATASOURCE);
  544.  OTHER_PARAMETER_TEST(RENDERINDEXSOURCE);
  545.  OTHER_PARAMETER_TEST(RENDERINSTANCE);
  546.  OTHER_PARAMETER_TEST(RENDERINSTANCESOURCE);
  547.  OTHER_PARAMETER_TEST(RENDERINSTANCESTREAM);
  548.  OTHER_PARAMETER_TEST(RENDERINTERFACEBOUND);
  549.  OTHER_PARAMETER_TEST(RENDERNODE);
  550.  OTHER_PARAMETER_TEST(RENDERSTREAM);
  551.  OTHER_PARAMETER_TEST(RENDERSTREAMINSTANCE);
  552.  OTHER_PARAMETER_TEST(RISTREAM);
  553.  OTHER_PARAMETER_TEST(ROOTNODE);
  554.  OTHER_PARAMETER_TEST(SEGMENTSET);
  555.  OTHER_PARAMETER_TEST(SHADER); // new
  556.  OTHER_PARAMETER_TEST(SHADERGROUP);
  557.  OTHER_PARAMETER_TEST(SHADERGROUPPASS);
  558.  OTHER_PARAMETER_TEST(SHADERINPUT);
  559.  OTHER_PARAMETER_TEST(SHADERINPUTDEFINITION);
  560.  OTHER_PARAMETER_TEST(SHADERINSTANCE);
  561.  OTHER_PARAMETER_TEST(SHADERPROGRAM);
  562.  OTHER_PARAMETER_TEST(SHADERPROGRAMCODE);
  563.  OTHER_PARAMETER_TEST(SHADERPROGRAMCODEBLOCK);
  564.  OTHER_PARAMETER_TEST(SHADERSTREAMDEFINITION);
  565.  OTHER_PARAMETER_TEST(SKELETON);
  566.  OTHER_PARAMETER_TEST(SKINJOINT);
  567.  OTHER_PARAMETER_TEST(SKINNODE);
  568.  OTHER_PARAMETER_TEST(TEXTURE);
  569.  OTHER_PARAMETER_TEST(TEXTUREIMAGEBLOCK);
  570.  OTHER_PARAMETER_TEST(TEXTUREIMAGEBLOCKDATA);
  571.  OTHER_PARAMETER_TEST(TRANSFORM);
  572.  OTHER_PARAMETER_TEST(TYPEINFO);
  573.  OTHER_PARAMETER_TEST(USERATTRIBUTE);
  574.  OTHER_PARAMETER_TEST(USERATTRIBUTELIST);
  575.  OTHER_PARAMETER_TEST(USERDATA);
  576.  OTHER_PARAMETER_TEST(WEIGHTS);
  577.  OTHER_PARAMETER_TEST(XXX);
  578.  
  579.  // error
  580.  stringstream ss;
  581.  ss << "Unimplemented parameter test " << iter->second.name << ends;
  582.  return error(ss.str().c_str());
  583. }
  584.  
  585. bool extractor::processTree(unsigned int node, unsigned int level)
  586. {
  587.  using namespace std;
  588.  
  589.  // find node
  590.  tree_iterator iter = tree.find(node);
  591.  if(iter == tree.end()) return true;
  592.  
  593.  // find property name
  594.  typedef std::map<uint32, PSSGPARAMETER>::iterator parameter_iterator;
  595.  parameter_iterator pi = nodelist.find(iter->second->chunktype);
  596.  if(pi == nodelist.end()) {
  597.     stringstream ss;
  598.     ss << "Failed to find parameter for chunktype " << iter->second->chunktype << "." << ends;
  599.     return error(ss.str().c_str());
  600.    }
  601.  
  602.  // print tree node
  603.  if(debug) for(size_t i = 0; i < level; i++) dfile << " ";
  604.  if(debug) dfile << pi->second.name << endl;
  605.  
  606.  // process important nodes
  607.  if(pi->second.name == "DATABLOCK") processVertexBuffer(iter);
  608.  if(pi->second.name == "RENDERDATASOURCE") processRenderBuffer(iter);
  609.  if(pi->second.name == "SKELETON") {}
  610.  
  611.  // traverse children
  612.  deque<unsigned int>& children = iter->second->children;
  613.  for(size_t i = 0; i < children.size(); i++) processTree(children[i], level + 1);
  614.  return true;
  615. }
  616.  
  617. bool extractor::processVertexBuffer(tree_iterator iter)
  618. {
  619.  using namespace std;
  620.  
  621.  // convert TREENODE to DATABLOCK
  622.  DATABLOCK* info = static_cast<DATABLOCK*>(iter->second.get());
  623.  if(!info) return error("Failed to case from TREENODE to DATABLOCK.");
  624.  
  625.  // check number of streams
  626.  if(info->streamCount != 1) return error("Expecting only one DATABLOCK stream.");
  627.  
  628.  // validate children
  629.  deque<uint32>& children = info->children;
  630.  if(children.size() != 2) return error("Expecting DATABLOCKSTREAM and DATABLOCKDATA.");
  631.  
  632.  // child #1: DATABLOCKSTREAM
  633.  tree_iterator dbs_iter = tree.find(children[0]);
  634.  if(dbs_iter == tree.end()) return error("Could not find DATABLOCKSTREAM.");
  635.  map<uint32, PSSGPARAMETER>::iterator p1_iter = nodelist.find(dbs_iter->second->chunktype);
  636.  if(p1_iter == nodelist.end()) return error("Expecting DATABLOCKSTREAM parameter.");
  637.  if(p1_iter->second.name != "DATABLOCKSTREAM") return error("Expecting DATABLOCKSTREAM.");
  638.  DATABLOCKSTREAM* dbs = static_cast<DATABLOCKSTREAM*>(dbs_iter->second.get());
  639.  if(!dbs) return error("Failed to case from TREENODE to DATABLOCKSTREAM.");
  640.  
  641.  // child #2: DATABLOCKDATA
  642.  tree_iterator dbd_iter = tree.find(children[1]);
  643.  if(dbd_iter == tree.end()) return error("Could not find DATABLOCKDATA");
  644.  map<uint32, PSSGPARAMETER>::iterator p2_iter = nodelist.find(dbd_iter->second->chunktype);
  645.  if(p2_iter == nodelist.end()) return error("Expecting DATABLOCKDATA parameter.");
  646.  if(p2_iter->second.name != "DATABLOCKDATA") return error("Expecting DATABLOCKDATA.");
  647.  DATABLOCKDATA* dbd = static_cast<DATABLOCKDATA*>(dbd_iter->second.get());
  648.  if(!dbd) return error("Failed to case from TREENODE to DATABLOCKDATA.");
  649.  
  650.  // create buffer data
  651.  BUFFERDATA vd;
  652.  vd.elementCount = info->elementCount;
  653.  vd.renderType = dbs->renderType;
  654.  vd.dataType = dbs->dataType;
  655.  vd.offset = dbs->offset;
  656.  vd.stride = dbs->stride;
  657.  vd.data = dbd->data;
  658.  
  659.  // insert buffer data
  660.  buffer_map.insert(buffer_map_value_type(info->id, vd));
  661.  return true;
  662. }
  663.  
  664. bool extractor::processRenderBuffer(tree_iterator iter)
  665. {
  666.  using namespace std;
  667.  
  668.  // convert TREENODE to RENDERDATASOURCE
  669.  RENDERDATASOURCE* info = static_cast<RENDERDATASOURCE*>(iter->second.get());
  670.  if(!info) return error("Failed to case from TREENODE to RENDERDATASOURCE.");
  671.  if(!info->streamCount) return error("RENDERDATASOURCE must contain at least one stream.");
  672.  if(info->children.size() < 2) return error("RENDERDATASOURCE must have at least two children.");
  673.  
  674.  // prepare RENDERDATA
  675.  RENDERDATA rd;
  676.  rd.streamCount = info->streamCount;
  677.  rd.blocks.reset(new string[info->streamCount]);
  678.  
  679.  // first RENDERDATASOURCE
  680.  if(info->streamCount == info->children.size() - 1)
  681.    {
  682.     // find RENDERINDEXSOURCE node
  683.     tree_iterator node = tree.find(info->children[0]);
  684.     if(node == tree.end()) return error("Could not find RENDERINDEXSOURCE node.");
  685.     
  686.     // find RENDERINDEXSOURCE parameter
  687.     map<uint32, PSSGPARAMETER>::iterator param = nodelist.find(node->second->chunktype);
  688.     if(param == nodelist.end()) return error("Could not find parameter.");
  689.     if(param->second.name != "RENDERINDEXSOURCE") return error("Expecting RENDERINDEXSOURCE.");
  690.  
  691.     // safe to cast
  692.     RENDERINDEXSOURCE* ris = static_cast<RENDERINDEXSOURCE*>(node->second.get());
  693.     if(!ris) return error("Failed to cast from TREENODE to RENDERINDEXSOURCE.");
  694.     if(!ris->children.size()) return error("Invalid RENDERINDEXSOURCE.");
  695.     
  696.     // find INDEXSOURCEDATA node
  697.     node = tree.find(ris->children[0]);
  698.     if(node == tree.end()) return error("Could not find INDEXSOURCEDATA node.");
  699.     
  700.     // find INDEXSOURCEDATA parameter
  701.     param = nodelist.find(node->second->chunktype);
  702.     if(param == nodelist.end()) return error("Could not find parameter.");
  703.     if(param->second.name != "INDEXSOURCEDATA") return error("Expecting INDEXSOURCEDATA.");
  704.     
  705.     // safe to cast
  706.     INDEXSOURCEDATA* isd = static_cast<INDEXSOURCEDATA*>(node->second.get());
  707.     if(!isd) return error("Failed to cast from TREENODE to INDEXSOURCEDATA.");
  708.     
  709.     // prepare RENDERDATA
  710.     rd.primitive = ris->primitive;
  711.     rd.format = ris->format;
  712.     rd.count = ris->count;
  713.     rd.id = ris->id;
  714.     rd.buffer = isd->data;
  715.     
  716.     // read render streams
  717.     for(size_t i = 0; i < info->streamCount; i++)
  718.        {
  719.         // find RENDERSTREAM node
  720.         tree_iterator node = tree.find(info->children[i + 1]);
  721.         if(node == tree.end()) return error("Could not find node.");
  722.  
  723.         // find RENDERSTREAM parameter
  724.         map<uint32, PSSGPARAMETER>::iterator param = nodelist.find(node->second->chunktype);
  725.         if(param == nodelist.end()) return error("Could not find parameter.");
  726.         if(param->second.name != "RENDERSTREAM") {
  727.            stringstream ss;
  728.            ss << "Expecting RENDERSTREAM node but found " << param->second.name << " instead." << ends;
  729.            return error(ss.str().c_str());
  730.           }
  731.  
  732.         // safe to cast
  733.         RENDERSTREAM* rs = static_cast<RENDERSTREAM*>(node->second.get());
  734.         if(!rs) return error("Failed to cast from TREENODE to RENDERSTREAM.");
  735.  
  736.         // save blocks
  737.         rd.blocks[i] = string(rs->dataBlock.c_str() + 1); // remove # from front
  738.        }
  739.    }
  740.  // other RENDERDATASOURCE (TOTORI and MERURU)
  741.  else if(info->streamCount == info->children.size())
  742.    {
  743.     if(info->primitive == "triangles")
  744.       {
  745.        cout << "LOL #1" << endl;
  746.       }
  747.     else if(info->primitive.length() == 0)
  748.       {
  749.        cout << "LOL #2" << endl;
  750.       }
  751.     else
  752.        return error("Unexpected RENDERDATASOURCE processing error.");
  753.    }
  754.  else
  755.    {
  756.     return error("Unexpected RENDERDATASOURCE stream count.");
  757.    }
  758.  
  759.  // insert render data
  760.  render_map.insert(render_map_value_type(info->id, rd));
  761.  return true;
  762. }
  763.  
  764. bool extractor::processModel(void)const
  765. {
  766.  using namespace std;
  767.  typedef map<string, BUFFERDATA>::const_iterator buffer_map_iterator;
  768.  typedef map<string, RENDERDATA>::const_iterator render_map_iterator;
  769.  
  770.  // for each Vertex or SkinnableVertex
  771.  typedef map<string, deque<RENDERDATA>> maptype;
  772.  maptype assocmap;
  773.  for(buffer_map_iterator iter = buffer_map.begin(); iter != buffer_map.end(); iter++) {
  774.      const BUFFERDATA& bd = iter->second;
  775.      if(bd.renderType == "Vertex") assocmap.insert(maptype::value_type(iter->first, deque<RENDERDATA>()));
  776.      else if(bd.renderType == "SkinnableVertex") assocmap.insert(maptype::value_type(iter->first, deque<RENDERDATA>()));
  777.     }
  778.  
  779.  // fill association map
  780.  for(render_map_iterator iter = render_map.begin(); iter != render_map.end(); iter++)
  781.     {
  782.      // count number of vertex streams seen
  783.      uint32 vstreams = 0;
  784.  
  785.      // for each stream in RENDERDATA
  786.      const RENDERDATA& rd = iter->second;
  787.      for(uint32 streamIndex = 0; streamIndex < rd.streamCount; streamIndex++)
  788.         {
  789.          // find BUFFERDATA
  790.          buffer_map_iterator bmi = buffer_map.find(rd.blocks[streamIndex]);
  791.          if(bmi == buffer_map.end()) {
  792.             stringstream ss;
  793.             ss << "Blockname " << rd.blocks[streamIndex] << " lookup failed.";
  794.             return error(ss.str().c_str());
  795.            }
  796.  
  797.          // BUFFERDATA is vertex or SkinnableVertex
  798.          const BUFFERDATA& bd = bmi->second;
  799.          if(bd.renderType == "Vertex" || bd.renderType == "SkinnableVertex") {
  800.             maptype::iterator item = assocmap.find(rd.blocks[streamIndex]);
  801.             if(item == assocmap.end()) return error("A RENDERDATASOURCE that refers to an unknown vertex DATABLOCK.");
  802.             item->second.push_back(rd);
  803.            }
  804.  
  805.          // make sure there is only one vertex stream
  806.          if(bd.renderType == "Vertex") vstreams++;
  807.          else if(bd.renderType == "SkinnableVertex") vstreams++;
  808.          if(vstreams > 1) return error("Multiple vertex streams in RENDERDATASOURCE.");
  809.         }
  810.     }
  811.  
  812.  // create lightwave object
  813.  lwFileSaver saver;
  814.  saver.insertLayr(0, nullptr);
  815.  
  816.  // for each point set
  817.  uint32 currpnts = 0;
  818.  for(maptype::iterator iter = assocmap.begin(); iter != assocmap.end(); iter++)
  819.     {
  820.      // get BUFFERDATA
  821.      const buffer_map_iterator bmi = buffer_map.find(iter->first);
  822.      if(bmi == buffer_map.end()) return error("BUFFERDATA lookup failed.");
  823.  
  824.      // get BUFFERDATA
  825.      const BUFFERDATA& bd = bmi->second;
  826.      if(bd.elementCount == 0) return error("BUFFERDATA point set contains no vertices.");
  827.  
  828.      // OK to save points
  829.      if(!(bd.renderType == "Vertex" || bd.renderType == "SkinnableVertex"))
  830.         return error("Expecting Vertex or SkinnableVertex.");
  831.  
  832.      // initialize data pointer
  833.      boost::shared_array<lwVertex3D> data(new lwVertex3D[bd.elementCount]);
  834.      char* ptr = bd.data.get();
  835.      ptr += bd.offset;
  836.  
  837.      // convert points
  838.      for(size_t i = 0; i < bd.elementCount; i++)
  839.         {
  840.          if(bd.dataType == "float3") {
  841.             float* v = reinterpret_cast<float*>(ptr);
  842.             float a = v[0];
  843.             float b = v[1];
  844.             float c = v[2];
  845.             reverse_byte_order(&a);
  846.             reverse_byte_order(&b);
  847.             reverse_byte_order(&c);
  848.             data[i].x = a;
  849.             data[i].y = b;
  850.             data[i].z = c;
  851.            }
  852.          else {
  853.             stringstream ss;
  854.             ss << "Unknown Vertex data type " << bd.dataType << "." << endl;
  855.             return error(ss.str().c_str());
  856.            }
  857.          ptr += bd.stride;
  858.         }
  859.  
  860.      // insert points
  861.      saver.insertPnts(0, currpnts, data, bd.elementCount);
  862.  
  863.      // for each RENDERDATA source associated with this point set
  864.      for(size_t rdIndex = 0; rdIndex < iter->second.size(); rdIndex++)
  865.         {
  866.          const RENDERDATA& rd = iter->second[rdIndex];
  867.          for(size_t streamIndex = 0; streamIndex < rd.streamCount; streamIndex++)
  868.             {
  869.              // find buffer data
  870.              buffer_map_iterator iter = buffer_map.find(rd.blocks[streamIndex]);
  871.              if(iter == buffer_map.end()) return error("Blockname lookup failed.");
  872.  
  873.              // buffer data pointer
  874.              BUFFERDATA bmi = iter->second;
  875.              char* ptr = bmi.data.get();
  876.              ptr += bmi.offset;
  877.  
  878.              // UV vertex map
  879.              if(bmi.renderType == "ST")
  880.                {
  881.                 boost::shared_array<lwRefVertex2D> data(new lwRefVertex2D[bmi.elementCount]);
  882.                 for(size_t i = 0; i < bmi.elementCount; i++) {
  883.                     if(bmi.dataType == "float2") {
  884.                        float* v = reinterpret_cast<float*>(ptr);
  885.                        float a = v[0];
  886.                        float b = v[1];
  887.                        reverse_byte_order(&a);
  888.                        reverse_byte_order(&b);
  889.                        data[i].reference = i;
  890.                        data[i].x = a;
  891.                        data[i].y = 1.0f - b;
  892.                       }
  893.                     else if(bmi.dataType == "half2") {
  894.                        unsigned short* v = reinterpret_cast<unsigned short*>(ptr);
  895.                        unsigned short a = v[0];
  896.                        unsigned short b = v[1];
  897.                        reverse_byte_order(&a);
  898.                        reverse_byte_order(&b);
  899.                        data[i].reference = i;
  900.                        data[i].x = float_16_to_32(a);
  901.                        data[i].y = 1.0f - float_16_to_32(b);
  902.                       }
  903.                     else if(bmi.dataType == "float3") {
  904.                        float* v = reinterpret_cast<float*>(ptr);
  905.                        float a = v[0];
  906.                        float b = v[1];
  907.                        reverse_byte_order(&a);
  908.                        reverse_byte_order(&b);
  909.                        data[i].reference = i;
  910.                        data[i].x = a;
  911.                        data[i].y = 1.0f - b;
  912.                       }
  913.                     else {
  914.                        stringstream ss;
  915.                        ss << "Unknown ST data type " << bmi.dataType << "." << endl;
  916.                        return error(ss.str().c_str());
  917.                       }
  918.                     ptr += bmi.stride;
  919.                    }
  920.  
  921.                 saver.insertTxuv(0, currpnts, rd.id.c_str(), data, bmi.elementCount);
  922.                }
  923.              // normal vertex map
  924.              else if(bmi.renderType == "Normal" || bmi.renderType == "SkinnableNormal")
  925.                {
  926.                }
  927.              // weight vertex map
  928.  
  929.              // polygons
  930.              if(rd.primitive == "triangles")
  931.                {
  932.                 // create triangle buffer
  933.                 if(rd.count % 3) return error("Face buffer element count must be divisible by three.");
  934.                 uint32 triangles = rd.count/3;
  935.                 boost::shared_array<lwTriangle> tribuffer(new lwTriangle[triangles]);
  936.  
  937.                 // extract triangles from RENDERDATA
  938.                 char* ptr = rd.buffer.get();
  939.                 uint32 index = 0;
  940.                 if(rd.format == "uchar") {
  941.                    for(uint32 i = 0; i < triangles; i++) {
  942.                        unsigned char* temp = reinterpret_cast<unsigned char*>(ptr);
  943.                        tribuffer[i].a = (uint32)(temp[index++]);
  944.                        tribuffer[i].b = (uint32)(temp[index++]);
  945.                        tribuffer[i].c = (uint32)(temp[index++]);
  946.                       }
  947.                   }
  948.                 else if(rd.format == "ushort") {
  949.                    for(uint32 i = 0; i < triangles; i++) {
  950.                        unsigned short* temp = reinterpret_cast<unsigned short*>(ptr);
  951.                        unsigned short a = temp[index++];
  952.                        unsigned short b = temp[index++];
  953.                        unsigned short c = temp[index++];
  954.                        reverse_byte_order(&a);
  955.                        reverse_byte_order(&b);
  956.                        reverse_byte_order(&c);
  957.                        tribuffer[i].a = (uint32)a;
  958.                        tribuffer[i].b = (uint32)b;
  959.                        tribuffer[i].c = (uint32)c;
  960.                       }
  961.                   }
  962.                 else {
  963.                    stringstream ss;
  964.                    ss << "Unknown face format " << rd.format << "." << endl;
  965.                    return error(ss.str().c_str());
  966.                   }
  967.  
  968.                 // save polygons
  969.                 saver.insertSurf(rd.id.c_str());
  970.                 saver.insertPols(0, currpnts, rd.id.c_str(), tribuffer, triangles);
  971.                }
  972.             }
  973.         }
  974.  
  975.      // increment point set
  976.      currpnts++;
  977.     }
  978.  
  979.  string savename = GetPathnameFromFilename(currfile);
  980.  savename += GetShortFilenameWithoutExtension(currfile);
  981.  savename += ".lwo";
  982.  saver.save(savename.c_str());
  983.  
  984.  return true;
  985. }
  986.  
  987. bool extractor::processPSSGDATABASE(const binary_stream& bs, uint32 position)
  988. {
  989.  using namespace std;
  990.  if(debug) dfile << endl;
  991.  if(debug) dfile << "--------------" << endl;
  992.  if(debug) dfile << " PSSGDATABASE " << endl;
  993.  if(debug) dfile << "--------------" << endl;
  994.  if(debug) dfile << "offset = " << position << endl;
  995.  
  996.  // set stream position
  997.  binary_stream stream(bs);
  998.  stream.seek(position);
  999.  
  1000.  // create node
  1001.  boost::shared_ptr<TREENODE> node(new PSSGDATABASE);
  1002.  typedef map<uint32, boost::shared_ptr<TREENODE>>::value_type value_type;
  1003.  tree.insert(value_type(position, node));
  1004.  
  1005.  // set parent
  1006.  uint32 parent = 0;
  1007.  map<uint32, uint32>::iterator iter = parent_list.find(position);
  1008.  if(iter != parent_list.end()) parent = iter->second;
  1009.  if(debug) dfile << "parent = " << parent << endl;
  1010.  node->parent = parent;
  1011.  
  1012.  // read chunk properties
  1013.  PSSGDATABASE* info = static_cast<PSSGDATABASE*>(node.get());
  1014.  info->chunktype = stream.BE_read_uint32(); if(stream.fail()) return error("Read failed.");
  1015.  info->chunksize = stream.BE_read_uint32(); if(stream.fail()) return error("Read failed.");
  1016.  info->propbytes = stream.BE_read_uint32(); if(stream.fail()) return error("Read failed.");
  1017.  if(debug) dfile << "chunktype = " << info->chunktype << endl;
  1018.  if(debug) dfile << "chunksize = " << info->chunksize << endl;
  1019.  if(debug) dfile << "propbytes = " << info->propbytes << endl;
  1020.  
  1021.  // validate
  1022.  if(info->propbytes > 1000) return error("Unexpected number of property table bytes.");
  1023.  if(info->propbytes == 0) return error("Property table expected.");
  1024.  
  1025.  // read properties
  1026.  uint32 bytes_read = 0;
  1027.  while(bytes_read < info->propbytes)
  1028.       {
  1029.        // read index
  1030.        uint32 type = stream.BE_read_uint32();
  1031.        if(stream.fail()) return error("Read failed.");
  1032.        bytes_read += 4;
  1033.       
  1034.        // data bytes
  1035.        uint32 size = stream.BE_read_uint32();
  1036.        if(stream.fail()) return error("Read failed.");
  1037.        bytes_read += 4;
  1038.        bytes_read += size;
  1039.       
  1040.        // find index
  1041.        typedef map<uint32, PSSGATTRIBUTE>::iterator iterator;
  1042.        iterator iter = attrlist.find(type);
  1043.        if(iter == attrlist.end()) {
  1044.           stringstream ss;
  1045.           ss << "Failed to find property for index " << type << "." << ends;
  1046.           return error(ss.str().c_str());
  1047.          }
  1048.       
  1049.        // read attributes
  1050.        const string& parameter = iter->second.parameter;
  1051.        const string& attribute = iter->second.attribute;
  1052.        if(parameter == "PSSGDATABASE" && attribute == "creator") {
  1053.           if(!readString(stream, info->creator)) return false;
  1054.           if(debug) dfile << "info->creator = " << info->creator << endl;
  1055.          }
  1056.        else if(parameter == "PSSGDATABASE" && attribute == "creationMachine") {
  1057.           if(!readString(stream, info->creationMachine)) return false;
  1058.           if(debug) dfile << "creationMachine = " << info->creationMachine << endl;
  1059.          }
  1060.        else if(parameter == "PSSGDATABASE" && attribute == "creationDate") {
  1061.           if(!readString(stream, info->creationDate)) return false;
  1062.           if(debug) dfile << "creationDate = " << info->creationDate << endl;
  1063.          }
  1064.        else if(parameter == "PSSGDATABASE" && attribute == "scale") {
  1065.           if(!readVector3(stream, &info->scale[0])) return false;
  1066.           if(debug) dfile << "scale = " << "<" << info->scale[0] << "," << info->scale[1] << "," << info->scale[2] << ">" << endl;
  1067.          }
  1068.        else if(parameter == "PSSGDATABASE" && attribute == "up") {
  1069.           if(!readVector3(stream, &info->up[0])) return false;
  1070.           if(debug) dfile << "up = " << "<" << info->up[0] << "," << info->up[1] << "," << info->up[2] << ">" << endl;
  1071.          }
  1072.        else {
  1073.           stringstream ss;
  1074.           ss << "Unknown block property " << parameter << ":" << attribute << "." << ends;
  1075.           return error(ss.str().c_str());
  1076.          }
  1077.       }
  1078.  
  1079.  // add child chunks to stack
  1080.  if(info->chunksize == info->propbytes + 4) return true;
  1081.  return processChildren(stream, node, position, info->chunksize - bytes_read - 4);
  1082. }
  1083.  
  1084. bool extractor::processANIMATION(const binary_stream& bs, uint32 position)
  1085. {
  1086.  return true;
  1087. }
  1088.  
  1089. bool extractor::processANIMATIONCHANNEL(const binary_stream& bs, uint32 position)
  1090. {
  1091.  return true;
  1092. }
  1093.  
  1094. bool extractor::processANIMATIONCHANNELDATABLOCK(const binary_stream& bs, uint32 position)
  1095. {
  1096.  return true;
  1097. }
  1098.  
  1099. bool extractor::processANIMATIONREF(const binary_stream& bs, uint32 position)
  1100. {
  1101.  return true;
  1102. }
  1103.  
  1104. bool extractor::processANIMATIONSET(const binary_stream& bs, uint32 position)
  1105. {
  1106.  return true;
  1107. }
  1108.  
  1109. bool extractor::processBOUNDINGBOX(const binary_stream& bs, uint32 position)
  1110. {
  1111.  return true;
  1112. }
  1113.  
  1114. bool extractor::processCAMERANODE(const binary_stream& bs, uint32 position)
  1115. {
  1116.  return true;
  1117. }
  1118.  
  1119. bool extractor::processCGSTREAM(const binary_stream& bs, uint32 position)
  1120. {
  1121.  return true;
  1122. }
  1123.  
  1124. bool extractor::processCHANNELREF(const binary_stream& bs, uint32 position)
  1125. {
  1126.  return true;
  1127. }
  1128.  
  1129. bool extractor::processCONSTANTCHANNEL(const binary_stream& bs, uint32 position)
  1130. {
  1131.  return true;
  1132. }
  1133.  
  1134. bool extractor::processCUBEMAPTEXTURE(const binary_stream& bs, uint32 position)
  1135. {
  1136.  return true;
  1137. }
  1138.  
  1139. bool extractor::processDATABLOCK(const binary_stream& bs, uint32 position)
  1140. {
  1141.  using namespace std;
  1142.  if(debug) dfile << endl;
  1143.  if(debug) dfile << "-----------" << endl;
  1144.  if(debug) dfile << " DATABLOCK " << endl;
  1145.  if(debug) dfile << "-----------" << endl;
  1146.  if(debug) dfile << "offset = " << position << endl;
  1147.  
  1148.  // set stream position
  1149.  binary_stream stream(bs);
  1150.  stream.seek(position);
  1151.  
  1152.  // insert node
  1153.  boost::shared_ptr<TREENODE> node(new DATABLOCK);
  1154.  typedef map<uint32, boost::shared_ptr<TREENODE>>::value_type value_type;
  1155.  tree.insert(value_type(position, node));
  1156.  
  1157.  // set parent
  1158.  uint32 parent = 0;
  1159.  map<uint32, uint32>::iterator iter = parent_list.find(position);
  1160.  if(iter != parent_list.end()) parent = iter->second;
  1161.  if(debug) dfile << "parent = " << parent << endl;
  1162.  node->parent = parent;
  1163.  
  1164.  // read chunk properties
  1165.  DATABLOCK* info = static_cast<DATABLOCK*>(node.get());
  1166.  info->chunktype = stream.BE_read_uint32(); if(stream.fail()) return error("Read failed.");
  1167.  info->chunksize = stream.BE_read_uint32(); if(stream.fail()) return error("Read failed.");
  1168.  info->propbytes = stream.BE_read_uint32(); if(stream.fail()) return error("Read failed.");
  1169.  if(debug) dfile << "chunktype = " << info->chunktype << endl;
  1170.  if(debug) dfile << "chunksize = " << info->chunksize << endl;
  1171.  if(debug) dfile << "propbytes = " << info->propbytes << endl;
  1172.  
  1173.  // initialize attributes
  1174.  info->streamCount = 0;
  1175.  info->size = 0;
  1176.  info->elementCount = 0;
  1177.  info->allocationStrategy = 0;
  1178.  info->id = "";
  1179.  
  1180.  // validate
  1181.  if(info->propbytes > 1000) return error("Unexpected number of property table bytes.");
  1182.  if(info->propbytes == 0) return error("Property table expected.");
  1183.  
  1184.  // read properties
  1185.  uint32 bytes_read = 0;
  1186.  while(bytes_read < info->propbytes)
  1187.       {
  1188.        // read index
  1189.        uint32 type = stream.BE_read_uint32();
  1190.        if(stream.fail()) return error("Read failed.");
  1191.        bytes_read += 4;
  1192.       
  1193.        // data bytes
  1194.        uint32 size = stream.BE_read_uint32();
  1195.        if(stream.fail()) return error("Read failed.");
  1196.        bytes_read += 4;
  1197.        bytes_read += size;
  1198.       
  1199.        // find index
  1200.        typedef map<uint32, PSSGATTRIBUTE>::iterator iterator;
  1201.        iterator iter = attrlist.find(type);
  1202.        if(iter == attrlist.end()) {
  1203.           stringstream ss;
  1204.           ss << "Failed to find property for index " << type << "." << ends;
  1205.           return error(ss.str().c_str());
  1206.          }
  1207.       
  1208.        // read attributes
  1209.        const string& parameter = iter->second.parameter;
  1210.        const string& attribute = iter->second.attribute;
  1211.        if(parameter == "DATABLOCK" && attribute == "streamCount") {
  1212.           if(!readNumber(stream, info->streamCount)) return false;
  1213.           if(debug) dfile << "info->streamCount = " << info->streamCount << endl;
  1214.          }
  1215.        else if(parameter == "DATABLOCK" && attribute == "size") {
  1216.           if(!readNumber(stream, info->size)) return false;
  1217.           if(debug) dfile << "info->size = " << info->size << endl;
  1218.          }
  1219.        else if(parameter == "DATABLOCK" && attribute == "elementCount") {
  1220.           if(!readNumber(stream, info->elementCount)) return false;
  1221.           if(debug) dfile << "info->elementCount = " << info->elementCount << endl;
  1222.          }
  1223.        else if(parameter == "RENDERINTERFACEBOUND" && attribute == "allocationStrategy") {
  1224.           if(!readNumber(stream, info->allocationStrategy)) return false;
  1225.           if(debug) dfile << "info->allocationStrategy = " << info->allocationStrategy << endl;
  1226.          }
  1227.        else if(parameter == "XXX" && attribute == "id") {
  1228.           if(!readString(stream, info->id)) return false;
  1229.           if(debug) dfile << "info->id = " << info->id << endl;
  1230.          }
  1231.        else {
  1232.           stringstream ss;
  1233.           ss << "Unknown block property " << parameter << ":" << attribute << "." << ends;
  1234.           return error(ss.str().c_str());
  1235.          }
  1236.       }
  1237.  
  1238.  // add child chunks to stack
  1239.  if(info->chunksize == info->propbytes + 4) return true;
  1240.  return processChildren(stream, node, position, info->chunksize - bytes_read - 4);
  1241. }
  1242.  
  1243. bool extractor::processDATABLOCKDATA(const binary_stream& bs, uint32 position)
  1244. {
  1245.  using namespace std;
  1246.  if(debug) dfile << endl;
  1247.  if(debug) dfile << "---------------" << endl;
  1248.  if(debug) dfile << " DATABLOCKDATA " << endl;
  1249.  if(debug) dfile << "---------------" << endl;
  1250.  if(debug) dfile << "offset = " << position << endl;
  1251.  
  1252.  // set stream position
  1253.  binary_stream stream(bs);
  1254.  stream.seek(position);
  1255.  
  1256.  // insert node
  1257.  boost::shared_ptr<TREENODE> node(new DATABLOCKDATA);
  1258.  typedef map<uint32, boost::shared_ptr<TREENODE>>::value_type value_type;
  1259.  tree.insert(value_type(position, node));
  1260.  
  1261.  // set parent
  1262.  uint32 parent = 0;
  1263.  map<uint32, uint32>::iterator iter = parent_list.find(position);
  1264.  if(iter != parent_list.end()) parent = iter->second;
  1265.  if(debug) dfile << "parent = " << parent << endl;
  1266.  node->parent = parent;
  1267.  
  1268.  // read chunk properties
  1269.  DATABLOCKDATA* info = static_cast<DATABLOCKDATA*>(node.get());
  1270.  info->chunktype = stream.BE_read_uint32(); if(stream.fail()) return error("Read failed.");
  1271.  info->chunksize = stream.BE_read_uint32(); if(stream.fail()) return error("Read failed.");
  1272.  info->propbytes = stream.BE_read_uint32(); if(stream.fail()) return error("Read failed.");
  1273.  if(debug) dfile << "chunktype = " << info->chunktype << endl;
  1274.  if(debug) dfile << "chunksize = " << info->chunksize << endl;
  1275.  if(debug) dfile << "propbytes = " << info->propbytes << endl;
  1276.  
  1277.  // validate
  1278.  if(info->propbytes) return error("Property table unexpected.");
  1279.  
  1280.  // create chunk data
  1281.  unsigned int datasize = info->chunksize - 4;
  1282.  info->data.reset(new char[datasize]);
  1283.  
  1284.  // read chunk data
  1285.  stream.read((char*)info->data.get(), datasize);
  1286.  if(stream.fail()) return error("Read failed.");
  1287.  
  1288.  // no children
  1289.  return true;
  1290. }
  1291.  
  1292. bool extractor::processDATABLOCKSTREAM(const binary_stream& bs, uint32 position)
  1293. {
  1294.  using namespace std;
  1295.  if(debug) dfile << endl;
  1296.  if(debug) dfile << "-----------------" << endl;
  1297.  if(debug) dfile << " DATABLOCKSTREAM " << endl;
  1298.  if(debug) dfile << "-----------------" << endl;
  1299.  if(debug) dfile << "offset = " << position << endl;
  1300.  
  1301.  // set stream position
  1302.  binary_stream stream(bs);
  1303.  stream.seek(position);
  1304.  
  1305.  // insert node
  1306.  boost::shared_ptr<TREENODE> node(new DATABLOCKSTREAM);
  1307.  typedef map<uint32, boost::shared_ptr<TREENODE>>::value_type value_type;
  1308.  tree.insert(value_type(position, node));
  1309.  
  1310.  // set parent
  1311.  uint32 parent = 0;
  1312.  map<uint32, uint32>::iterator iter = parent_list.find(position);
  1313.  if(iter != parent_list.end()) parent = iter->second;
  1314.  if(debug) dfile << "parent = " << parent << endl;
  1315.  node->parent = parent;
  1316.  
  1317.  // read chunk properties
  1318.  DATABLOCKSTREAM* info = static_cast<DATABLOCKSTREAM*>(node.get());
  1319.  info->chunktype = stream.BE_read_uint32(); if(stream.fail()) return error("Read failed.");
  1320.  info->chunksize = stream.BE_read_uint32(); if(stream.fail()) return error("Read failed.");
  1321.  info->propbytes = stream.BE_read_uint32(); if(stream.fail()) return error("Read failed.");
  1322.  if(debug) dfile << "chunktype = " << info->chunktype << endl;
  1323.  if(debug) dfile << "chunksize = " << info->chunksize << endl;
  1324.  if(debug) dfile << "propbytes = " << info->propbytes << endl;
  1325.  
  1326.  // initialize attributes
  1327.  info->renderType = "";
  1328.  info->dataType = "";
  1329.  info->offset = 0;
  1330.  info->stride = 0;
  1331.  
  1332.  // validate
  1333.  if(info->propbytes > 1000) return error("Unexpected number of property table bytes.");
  1334.  if(info->propbytes == 0) return error("Property table expected.");
  1335.  
  1336.  // read properties
  1337.  uint32 bytes_read = 0;
  1338.  while(bytes_read < info->propbytes)
  1339.       {
  1340.        // read index
  1341.        uint32 type = stream.BE_read_uint32();
  1342.        if(stream.fail()) return error("Read failed.");
  1343.        bytes_read += 4;
  1344.       
  1345.        // data bytes
  1346.        uint32 size = stream.BE_read_uint32();
  1347.        if(stream.fail()) return error("Read failed.");
  1348.        bytes_read += 4;
  1349.        bytes_read += size;
  1350.       
  1351.        // find index
  1352.        typedef map<uint32, PSSGATTRIBUTE>::iterator iterator;
  1353.        iterator iter = attrlist.find(type);
  1354.        if(iter == attrlist.end()) {
  1355.           stringstream ss;
  1356.           ss << "Failed to find property for index " << type << "." << ends;
  1357.           return error(ss.str().c_str());
  1358.          }
  1359.       
  1360.        // read attributes
  1361.        const string& parameter = iter->second.parameter;
  1362.        const string& attribute = iter->second.attribute;
  1363.        if(parameter == "DATABLOCKSTREAM" && attribute == "renderType") {
  1364.           if(!readString(stream, info->renderType)) return false;
  1365.           if(debug) dfile << "info->renderType = " << info->renderType << endl;
  1366.          }
  1367.        else if(parameter == "DATABLOCKSTREAM" && attribute == "dataType") {
  1368.           if(!readString(stream, info->dataType)) return false;
  1369.           if(debug) dfile << "info->dataType = " << info->dataType << endl;
  1370.          }
  1371.        else if(parameter == "DATABLOCKSTREAM" && attribute == "offset") {
  1372.           if(!readNumber(stream, info->offset)) return false;
  1373.           if(debug) dfile << "info->offset = " << info->offset << endl;
  1374.          }
  1375.        else if(parameter == "DATABLOCKSTREAM" && attribute == "stride") {
  1376.           if(!readNumber(stream, info->stride)) return false;
  1377.           if(debug) dfile << "info->stride = " << info->stride << endl;
  1378.          }
  1379.        else {
  1380.           stringstream ss;
  1381.           ss << "Unknown block property " << parameter << ":" << attribute << "." << ends;
  1382.           return error(ss.str().c_str());
  1383.          }
  1384.       }
  1385.  
  1386.  // add child chunks to stack
  1387.  if(info->chunksize == info->propbytes + 4) return true;
  1388.  return processChildren(stream, node, position, info->chunksize - bytes_read - 4);
  1389. }
  1390.  
  1391. bool extractor::processGLPASS(const binary_stream& bs, uint32 position)
  1392. {
  1393.  return true;
  1394. }
  1395.  
  1396. bool extractor::processGLSHADER(const binary_stream& bs, uint32 position)
  1397. {
  1398.  return true;
  1399. }
  1400.  
  1401. bool extractor::processGLSTATE(const binary_stream& bs, uint32 position)
  1402. {
  1403.  return true;
  1404. }
  1405.  
  1406. bool extractor::processINDEXSOURCEDATA(const binary_stream& bs, uint32 position)
  1407. {
  1408.  using namespace std;
  1409.  if(debug) dfile << endl;
  1410.  if(debug) dfile << "-----------------" << endl;
  1411.  if(debug) dfile << " INDEXSOURCEDATA " << endl;
  1412.  if(debug) dfile << "-----------------" << endl;
  1413.  if(debug) dfile << "offset = " << position << endl;
  1414.  
  1415.  // set stream position
  1416.  binary_stream stream(bs);
  1417.  stream.seek(position);
  1418.  
  1419.  // insert node
  1420.  boost::shared_ptr<TREENODE> node(new INDEXSOURCEDATA);
  1421.  typedef map<uint32, boost::shared_ptr<TREENODE>>::value_type value_type;
  1422.  tree.insert(value_type(position, node));
  1423.  
  1424.  // set parent
  1425.  uint32 parent = 0;
  1426.  map<uint32, uint32>::iterator iter = parent_list.find(position);
  1427.  if(iter != parent_list.end()) parent = iter->second;
  1428.  if(debug) dfile << "parent = " << parent << endl;
  1429.  node->parent = parent;
  1430.  
  1431.  // read chunk properties
  1432.  INDEXSOURCEDATA* info = static_cast<INDEXSOURCEDATA*>(node.get());
  1433.  info->chunktype = stream.BE_read_uint32(); if(stream.fail()) return error("Read failed.");
  1434.  info->chunksize = stream.BE_read_uint32(); if(stream.fail()) return error("Read failed.");
  1435.  info->propbytes = stream.BE_read_uint32(); if(stream.fail()) return error("Read failed.");
  1436.  if(debug) dfile << "chunktype = " << info->chunktype << endl;
  1437.  if(debug) dfile << "chunksize = " << info->chunksize << endl;
  1438.  if(debug) dfile << "propbytes = " << info->propbytes << endl;
  1439.  
  1440.  // validate
  1441.  if(info->propbytes) return error("Property table unexpected.");
  1442.  
  1443.  // create chunk data
  1444.  uint32 datasize = info->chunksize - 4;
  1445.  info->data.reset(new char[datasize]);
  1446.  
  1447.  // read chunk data
  1448.  stream.read(info->data.get(), datasize);
  1449.  if(stream.fail()) return error("Read failed.");
  1450.  
  1451.  return true;
  1452. }
  1453.  
  1454. bool extractor::processINVERSEBINDMATRIX(const binary_stream& bs, uint32 position)
  1455. {
  1456.  return true;
  1457. }
  1458.  
  1459. bool extractor::processJOINTNODE(const binary_stream& bs, uint32 position)
  1460. {
  1461.  return true;
  1462. }
  1463.  
  1464. bool extractor::processKEYS(const binary_stream& bs, uint32 position)
  1465. {
  1466.  return true;
  1467. }
  1468.  
  1469. bool extractor::processLIBRARY(const binary_stream& bs, uint32 position)
  1470. {
  1471.  using namespace std;
  1472.  if(debug) dfile << endl;
  1473.  if(debug) dfile << "---------" << endl;
  1474.  if(debug) dfile << " LIBRARY " << endl;
  1475.  if(debug) dfile << "---------" << endl;
  1476.  if(debug) dfile << "offset = " << position << endl;
  1477.  
  1478.  // set stream position
  1479.  binary_stream stream(bs);
  1480.  stream.seek(position);
  1481.  
  1482.  // insert node
  1483.  boost::shared_ptr<TREENODE> node(new LIBRARY);
  1484.  typedef map<uint32, boost::shared_ptr<TREENODE>>::value_type value_type;
  1485.  tree.insert(value_type(position, node));
  1486.  
  1487.  // set parent
  1488.  uint32 parent = 0;
  1489.  map<uint32, uint32>::iterator iter = parent_list.find(position);
  1490.  if(iter != parent_list.end()) parent = iter->second;
  1491.  if(debug) dfile << "parent = " << parent << endl;
  1492.  node->parent = parent;
  1493.  
  1494.  // read chunk properties
  1495.  LIBRARY* info = static_cast<LIBRARY*>(node.get());
  1496.  info->chunktype = stream.BE_read_uint32(); if(stream.fail()) return error("Read failed.");
  1497.  info->chunksize = stream.BE_read_uint32(); if(stream.fail()) return error("Read failed.");
  1498.  info->propbytes = stream.BE_read_uint32(); if(stream.fail()) return error("Read failed.");
  1499.  if(debug) dfile << "chunktype = " << info->chunktype << endl;
  1500.  if(debug) dfile << "chunksize = " << info->chunksize << endl;
  1501.  if(debug) dfile << "propbytes = " << info->propbytes << endl;
  1502.  
  1503.  // validate
  1504.  if(info->propbytes > 1000) return error("Unexpected number of property table bytes.");
  1505.  if(info->propbytes == 0) return error("Property table expected.");
  1506.  
  1507.  // read properties
  1508.  uint32 bytes_read = 0;
  1509.  while(bytes_read < info->propbytes)
  1510.       {
  1511.        // read index
  1512.        uint32 type = stream.BE_read_uint32();
  1513.        if(stream.fail()) return error("Read failed.");
  1514.        bytes_read += 4;
  1515.       
  1516.        // data bytes
  1517.        uint32 size = stream.BE_read_uint32();
  1518.        if(stream.fail()) return error("Read failed.");
  1519.        bytes_read += 4;
  1520.        bytes_read += size;
  1521.       
  1522.        // find index
  1523.        typedef map<uint32, PSSGATTRIBUTE>::iterator iterator;
  1524.        iterator iter = attrlist.find(type);
  1525.        if(iter == attrlist.end()) {
  1526.           stringstream ss;
  1527.           ss << "Failed to find property for index " << type << "." << ends;
  1528.           return error(ss.str().c_str());
  1529.          }
  1530.       
  1531.        // aliases
  1532.        const string& parameter = iter->second.parameter;
  1533.        const string& attribute = iter->second.attribute;
  1534.  
  1535.        if(parameter == "LIBRARY" && attribute == "type") {
  1536.           if(!readString(stream, info->type)) return false;
  1537.           if(debug) dfile << "type = " << info->type << endl;
  1538.          }
  1539.        else {
  1540.           stringstream ss;
  1541.           ss << "Unknown block property " << parameter << ":" << attribute << "." << ends;
  1542.           return error(ss.str().c_str());
  1543.          }
  1544.       }
  1545.  
  1546.  // add child chunks to stack
  1547.  if(info->chunksize == info->propbytes + 4) return true;
  1548.  return processChildren(stream, node, position, info->chunksize - bytes_read - 4);
  1549. }
  1550.  
  1551. bool extractor::processLIGHTNODE(const binary_stream& bs, uint32 position)
  1552. {
  1553.  return true;
  1554. }
  1555.  
  1556. bool extractor::processMODIFIERNETWORK(const binary_stream& bs, uint32 position)
  1557. {
  1558.  return true;
  1559. }
  1560.  
  1561. bool extractor::processMODIFIERNETWORKCONNECTION(const binary_stream& bs, uint32 position)
  1562. {
  1563.  return true;
  1564. }
  1565.  
  1566. bool extractor::processMODIFIERNETWORKENTRY(const binary_stream& bs, uint32 position)
  1567. {
  1568.  return true;
  1569. }
  1570.  
  1571. bool extractor::processMODIFIERNETWORKINSTANCE(const binary_stream& bs, uint32 position)
  1572. {
  1573.  return true;
  1574. }
  1575.  
  1576. bool extractor::processMODIFIERNETWORKINSTANCECOMPILE(const binary_stream& bs, uint32 position)
  1577. {
  1578.  return true;
  1579. }
  1580.  
  1581. bool extractor::processMODIFIERNETWORKINSTANCEDYNAMICSTREAM(const binary_stream& bs, uint32 position)
  1582. {
  1583.  return true;
  1584. }
  1585.  
  1586. bool extractor::processMODIFIERNETWORKINSTANCEDYNAMICSTREAMTYPE(const binary_stream& bs, uint32 position)
  1587. {
  1588.  return true;
  1589. }
  1590.  
  1591. bool extractor::processMODIFIERNETWORKINSTANCEMODIFIERINPUT(const binary_stream& bs, uint32 position)
  1592. {
  1593.  return true;
  1594. }
  1595.  
  1596. bool extractor::processMODIFIERNETWORKINSTANCEUNIQUEINPUT(const binary_stream& bs, uint32 position)
  1597. {
  1598.  return true;
  1599. }
  1600.  
  1601. bool extractor::processMODIFIERNETWORKINSTANCEUNIQUEMODIFIERINPUT(const binary_stream& bs, uint32 position)
  1602. {
  1603.  return true;
  1604. }
  1605.  
  1606. bool extractor::processMORPHMODIFIERWEIGHTS(const binary_stream& bs, uint32 position)
  1607. {
  1608.  return true;
  1609. }
  1610.  
  1611. bool extractor::processNODE(const binary_stream& bs, uint32 position)
  1612. {
  1613.  return true;
  1614. }
  1615.  
  1616. bool extractor::processRENDERDATASOURCE(const binary_stream& bs, uint32 position)
  1617. {
  1618.  using namespace std;
  1619.  if(debug) dfile << endl;
  1620.  if(debug) dfile << "------------------" << endl;
  1621.  if(debug) dfile << " RENDERDATASOURCE " << endl;
  1622.  if(debug) dfile << "------------------" << endl;
  1623.  if(debug) dfile << "offset = " << position << endl;
  1624.  
  1625.  // set stream position
  1626.  binary_stream stream(bs);
  1627.  stream.seek(position);
  1628.  
  1629.  // insert node
  1630.  boost::shared_ptr<TREENODE> node(new RENDERDATASOURCE);
  1631.  typedef map<uint32, boost::shared_ptr<TREENODE>>::value_type value_type;
  1632.  tree.insert(value_type(position, node));
  1633.  
  1634.  // set parent
  1635.  uint32 parent = 0;
  1636.  map<uint32, uint32>::iterator iter = parent_list.find(position);
  1637.  if(iter != parent_list.end()) parent = iter->second;
  1638.  if(debug) dfile << "parent = " << parent << endl;
  1639.  node->parent = parent;
  1640.  
  1641.  // read chunk properties
  1642.  RENDERDATASOURCE* info = static_cast<RENDERDATASOURCE*>(node.get());
  1643.  info->chunktype = stream.BE_read_uint32(); if(stream.fail()) return error("Read failed.");
  1644.  info->chunksize = stream.BE_read_uint32(); if(stream.fail()) return error("Read failed.");
  1645.  info->propbytes = stream.BE_read_uint32(); if(stream.fail()) return error("Read failed.");
  1646.  if(debug) dfile << "chunktype = " << info->chunktype << endl;
  1647.  if(debug) dfile << "chunksize = " << info->chunksize << endl;
  1648.  if(debug) dfile << "propbytes = " << info->propbytes << endl;
  1649.  
  1650.  // initialize attributes
  1651.  info->streamCount = 0;
  1652.  info->primitive = "";
  1653.  info->id = "";
  1654.  
  1655.  // validate
  1656.  if(info->propbytes > 1000) return error("Unexpected number of property table bytes.");
  1657.  if(info->propbytes == 0) return error("Property table expected.");
  1658.  
  1659.  // read properties
  1660.  uint32 bytes_read = 0;
  1661.  while(bytes_read < info->propbytes)
  1662.       {
  1663.        // read index
  1664.        uint32 type = stream.BE_read_uint32();
  1665.        if(stream.fail()) return error("Read failed.");
  1666.        bytes_read += 4;
  1667.       
  1668.        // data bytes
  1669.        uint32 size = stream.BE_read_uint32();
  1670.        if(stream.fail()) return error("Read failed.");
  1671.        bytes_read += 4;
  1672.        bytes_read += size;
  1673.       
  1674.        // find index
  1675.        typedef map<uint32, PSSGATTRIBUTE>::iterator iterator;
  1676.        iterator iter = attrlist.find(type);
  1677.        if(iter == attrlist.end()) {
  1678.           stringstream ss;
  1679.           ss << "Failed to find property for index " << type << "." << ends;
  1680.           return error(ss.str().c_str());
  1681.          }
  1682.       
  1683.        // read attributes
  1684.        const string& parameter = iter->second.parameter;
  1685.        const string& attribute = iter->second.attribute;
  1686.        if(parameter == "RENDERDATASOURCE" && attribute == "streamCount") {
  1687.           if(!readNumber(stream, info->streamCount)) return false;
  1688.           if(debug) dfile << "info->streamCount = " << info->streamCount << endl;
  1689.          }
  1690.        else if(parameter == "RENDERDATASOURCE" && attribute == "primitive") {
  1691.           if(!readString(stream, info->primitive)) return false;
  1692.           if(debug) dfile << "info->primitive = " << info->primitive << endl;
  1693.          }
  1694.        else if(parameter == "XXX" && attribute == "id") {
  1695.           if(!readString(stream, info->id)) return false;
  1696.           if(debug) dfile << "info->id = " << info->id << endl;
  1697.          }
  1698.        else {
  1699.           stringstream ss;
  1700.           ss << "Unknown block property " << parameter << ":" << attribute << "." << ends;
  1701.           return error(ss.str().c_str());
  1702.          }
  1703.       }
  1704.  
  1705.  // add child chunks to stack
  1706.  if(info->chunksize == info->propbytes + 4) return true;
  1707.  return processChildren(stream, node, position, info->chunksize - bytes_read - 4);
  1708. }
  1709.  
  1710. bool extractor::processRENDERINDEXSOURCE(const binary_stream& bs, uint32 position)
  1711. {
  1712.  using namespace std;
  1713.  if(debug) dfile << endl;
  1714.  if(debug) dfile << "-------------------" << endl;
  1715.  if(debug) dfile << " RENDERINDEXSOURCE " << endl;
  1716.  if(debug) dfile << "-------------------" << endl;
  1717.  if(debug) dfile << "offset = " << position << endl;
  1718.  
  1719.  // set stream position
  1720.  binary_stream stream(bs);
  1721.  stream.seek(position);
  1722.  
  1723.  // insert node
  1724.  boost::shared_ptr<TREENODE> node(new RENDERINDEXSOURCE);
  1725.  typedef map<uint32, boost::shared_ptr<TREENODE>>::value_type value_type;
  1726.  tree.insert(value_type(position, node));
  1727.  
  1728.  // set parent
  1729.  uint32 parent = 0;
  1730.  map<uint32, uint32>::iterator iter = parent_list.find(position);
  1731.  if(iter != parent_list.end()) parent = iter->second;
  1732.  if(debug) dfile << "parent = " << parent << endl;
  1733.  node->parent = parent;
  1734.  
  1735.  // read chunk properties
  1736.  RENDERINDEXSOURCE* info = static_cast<RENDERINDEXSOURCE*>(node.get());
  1737.  info->chunktype = stream.BE_read_uint32(); if(stream.fail()) return error("Read failed.");
  1738.  info->chunksize = stream.BE_read_uint32(); if(stream.fail()) return error("Read failed.");
  1739.  info->propbytes = stream.BE_read_uint32(); if(stream.fail()) return error("Read failed.");
  1740.  if(debug) dfile << "chunktype = " << info->chunktype << endl;
  1741.  if(debug) dfile << "chunksize = " << info->chunksize << endl;
  1742.  if(debug) dfile << "propbytes = " << info->propbytes << endl;
  1743.  
  1744.  // initialize attributes
  1745.  info->primitive = "";
  1746.  info->format = "";
  1747.  info->count = 0;
  1748.  info->maximumIndex = 0;
  1749.  info->allocationStrategy = 0;
  1750.  info->id = "";
  1751.  info->size = 0;
  1752.  
  1753.  // validate
  1754.  if(info->propbytes > 1000) return error("Unexpected number of property table bytes.");
  1755.  if(info->propbytes == 0) return error("Property table expected.");
  1756.  
  1757.  // read properties
  1758.  uint32 bytes_read = 0;
  1759.  while(bytes_read < info->propbytes)
  1760.       {
  1761.        // read index
  1762.        uint32 type = stream.BE_read_uint32();
  1763.        if(stream.fail()) return error("Read failed.");
  1764.        bytes_read += 4;
  1765.       
  1766.        // data bytes
  1767.        uint32 size = stream.BE_read_uint32();
  1768.        if(stream.fail()) return error("Read failed.");
  1769.        bytes_read += 4;
  1770.        bytes_read += size;
  1771.       
  1772.        // find index
  1773.        typedef map<uint32, PSSGATTRIBUTE>::iterator iterator;
  1774.        iterator iter = attrlist.find(type);
  1775.        if(iter == attrlist.end()) {
  1776.           stringstream ss;
  1777.           ss << "Failed to find property for index " << type << "." << ends;
  1778.           return error(ss.str().c_str());
  1779.          }
  1780.       
  1781.        // read attributes
  1782.        const string& parameter = iter->second.parameter;
  1783.        const string& attribute = iter->second.attribute;
  1784.        if(parameter == "RENDERINDEXSOURCE" && attribute == "primitive") {
  1785.           if(!readString(stream, info->primitive)) return false;
  1786.           if(debug) dfile << "info->primitive = " << info->primitive << endl;
  1787.          }
  1788.        else if(parameter == "RENDERINDEXSOURCE" && attribute == "format") {
  1789.           if(!readString(stream, info->format)) return false;
  1790.           if(debug) dfile << "info->format = " << info->format << endl;
  1791.          }
  1792.        else if(parameter == "RENDERINDEXSOURCE" && attribute == "count") {
  1793.           if(!readNumber(stream, info->count)) return false;
  1794.           if(debug) dfile << "info->count = " << info->count << endl;
  1795.          }
  1796.        else if(parameter == "RENDERINDEXSOURCE" && attribute == "maximumIndex") {
  1797.           if(!readNumber(stream, info->maximumIndex)) return false;
  1798.           if(debug) dfile << "info->maximumIndex = " << info->maximumIndex << endl;
  1799.          }
  1800.        else if(parameter == "RENDERINTERFACEBOUND" && attribute == "allocationStrategy") {
  1801.           if(!readNumber(stream, info->allocationStrategy)) return false;
  1802.           if(debug) dfile << "info->allocationStrategy = " << info->allocationStrategy << endl;
  1803.          }
  1804.        else if(parameter == "XXX" && attribute == "id") {
  1805.           if(!readString(stream, info->id)) return false;
  1806.           if(debug) dfile << "info->id = " << info->id << endl;
  1807.          }
  1808.        else {
  1809.           stringstream ss;
  1810.           ss << "Unknown block property " << parameter << ":" << attribute << "." << ends;
  1811.           return error(ss.str().c_str());
  1812.          }
  1813.       }
  1814.  
  1815.  // add child chunks to stack
  1816.  if(info->chunksize == info->propbytes + 4) return true;
  1817.  return processChildren(stream, node, position, info->chunksize - bytes_read - 4);
  1818. }
  1819.  
  1820. bool extractor::processRENDERINSTANCE(const binary_stream& bs, uint32 position)
  1821. {
  1822.  return true;
  1823. }
  1824.  
  1825. bool extractor::processRENDERINSTANCESOURCE(const binary_stream& bs, uint32 position)
  1826. {
  1827.  return true;
  1828. }
  1829.  
  1830. bool extractor::processRENDERINSTANCESTREAM(const binary_stream& bs, uint32 position)
  1831. {
  1832.  return true;
  1833. }
  1834.  
  1835. bool extractor::processRENDERINTERFACEBOUND(const binary_stream& bs, uint32 position)
  1836. {
  1837.  return true;
  1838. }
  1839.  
  1840. bool extractor::processRENDERNODE(const binary_stream& bs, uint32 position)
  1841. {
  1842.  return true;
  1843. }
  1844.  
  1845. bool extractor::processRENDERSTREAM(const binary_stream& bs, uint32 position)
  1846. {
  1847.  using namespace std;
  1848.  if(debug) dfile << endl;
  1849.  if(debug) dfile << "--------------" << endl;
  1850.  if(debug) dfile << " RENDERSTREAM " << endl;
  1851.  if(debug) dfile << "--------------" << endl;
  1852.  if(debug) dfile << "offset = " << position << endl;
  1853.  
  1854.  // set stream position
  1855.  binary_stream stream(bs);
  1856.  stream.seek(position);
  1857.  
  1858.  // insert node
  1859.  boost::shared_ptr<TREENODE> node(new RENDERSTREAM);
  1860.  typedef map<uint32, boost::shared_ptr<TREENODE>>::value_type value_type;
  1861.  tree.insert(value_type(position, node));
  1862.  
  1863.  // set parent
  1864.  uint32 parent = 0;
  1865.  map<uint32, uint32>::iterator iter = parent_list.find(position);
  1866.  if(iter != parent_list.end()) parent = iter->second;
  1867.  if(debug) dfile << "parent = " << parent << endl;
  1868.  node->parent = parent;
  1869.  
  1870.  // read chunk properties
  1871.  RENDERSTREAM* info = static_cast<RENDERSTREAM*>(node.get());
  1872.  info->chunktype = stream.BE_read_uint32(); if(stream.fail()) return error("Read failed.");
  1873.  info->chunksize = stream.BE_read_uint32(); if(stream.fail()) return error("Read failed.");
  1874.  info->propbytes = stream.BE_read_uint32(); if(stream.fail()) return error("Read failed.");
  1875.  if(debug) dfile << "chunktype = " << info->chunktype << endl;
  1876.  if(debug) dfile << "chunksize = " << info->chunksize << endl;
  1877.  if(debug) dfile << "propbytes = " << info->propbytes << endl;
  1878.  
  1879.  // initialize attributes
  1880.  info->dataBlock = "";
  1881.  info->subStream = 0;
  1882.  info->id = "";
  1883.  
  1884.  // validate
  1885.  if(info->propbytes > 1000) return error("Unexpected number of property table bytes.");
  1886.  if(info->propbytes == 0) return error("Property table expected.");
  1887.  
  1888.  // read properties
  1889.  uint32 bytes_read = 0;
  1890.  while(bytes_read < info->propbytes)
  1891.       {
  1892.        // read index
  1893.        uint32 type = stream.BE_read_uint32();
  1894.        if(stream.fail()) return error("Read failed.");
  1895.        bytes_read += 4;
  1896.       
  1897.        // data bytes
  1898.        uint32 size = stream.BE_read_uint32();
  1899.        if(stream.fail()) return error("Read failed.");
  1900.        bytes_read += 4;
  1901.        bytes_read += size;
  1902.       
  1903.        // find index
  1904.        typedef map<uint32, PSSGATTRIBUTE>::iterator iterator;
  1905.        iterator iter = attrlist.find(type);
  1906.        if(iter == attrlist.end()) {
  1907.           stringstream ss;
  1908.           ss << "Failed to find property for index " << type << "." << ends;
  1909.           return error(ss.str().c_str());
  1910.          }
  1911.       
  1912.        // read attributes
  1913.        const string& parameter = iter->second.parameter;
  1914.        const string& attribute = iter->second.attribute;
  1915.        if(parameter == "RENDERSTREAM" && attribute == "dataBlock") {
  1916.           if(!readString(stream, info->dataBlock)) return false;
  1917.           if(debug) dfile << "info->dataBlock = " << info->dataBlock << endl;
  1918.          }
  1919.        else if(parameter == "RENDERSTREAM" && attribute == "subStream") {
  1920.           if(!readNumber(stream, info->subStream)) return false;
  1921.           if(debug) dfile << "info->subStream = " << info->subStream << endl;
  1922.          }
  1923.        else if(parameter == "XXX" && attribute == "id") {
  1924.           if(!readString(stream, info->id)) return false;
  1925.           if(debug) dfile << "info->id = " << info->id << endl;
  1926.          }
  1927.        else {
  1928.           stringstream ss;
  1929.           ss << "Unknown block property " << parameter << ":" << attribute << "." << ends;
  1930.           return error(ss.str().c_str());
  1931.          }
  1932.       }
  1933.  
  1934.  // no children
  1935.  return true;
  1936. }
  1937.  
  1938. bool extractor::processRENDERSTREAMINSTANCE(const binary_stream& bs, uint32 position)
  1939. {
  1940.  return true;
  1941. }
  1942.  
  1943. bool extractor::processRISTREAM(const binary_stream& bs, uint32 position)
  1944. {
  1945.  return true;
  1946. }
  1947.  
  1948. bool extractor::processROOTNODE(const binary_stream& bs, uint32 position)
  1949. {
  1950.  return true;
  1951. }
  1952.  
  1953. bool extractor::processSEGMENTSET(const binary_stream& bs, uint32 position)
  1954. {
  1955.  using namespace std;
  1956.  if(debug) dfile << endl;
  1957.  if(debug) dfile << "------------" << endl;
  1958.  if(debug) dfile << " SEGMENTSET " << endl;
  1959.  if(debug) dfile << "------------" << endl;
  1960.  if(debug) dfile << "offset = " << position << endl;
  1961.  
  1962.  // set stream position
  1963.  binary_stream stream(bs);
  1964.  stream.seek(position);
  1965.  
  1966.  // insert node
  1967.  boost::shared_ptr<TREENODE> node(new SEGMENTSET);
  1968.  typedef map<uint32, boost::shared_ptr<TREENODE>>::value_type value_type;
  1969.  tree.insert(value_type(position, node));
  1970.  
  1971.  // set parent
  1972.  uint32 parent = 0;
  1973.  map<uint32, uint32>::iterator iter = parent_list.find(position);
  1974.  if(iter != parent_list.end()) parent = iter->second;
  1975.  if(debug) dfile << "parent = " << parent << endl;
  1976.  node->parent = parent;
  1977.  
  1978.  // read chunk properties
  1979.  SEGMENTSET* info = static_cast<SEGMENTSET*>(node.get());
  1980.  info->chunktype = stream.BE_read_uint32(); if(stream.fail()) return error("Read failed.");
  1981.  info->chunksize = stream.BE_read_uint32(); if(stream.fail()) return error("Read failed.");
  1982.  info->propbytes = stream.BE_read_uint32(); if(stream.fail()) return error("Read failed.");
  1983.  if(debug) dfile << "chunktype = " << info->chunktype << endl;
  1984.  if(debug) dfile << "chunksize = " << info->chunksize << endl;
  1985.  if(debug) dfile << "propbytes = " << info->propbytes << endl;
  1986.  
  1987.  // validate
  1988.  if(info->propbytes > 1000) return error("Unexpected number of property table bytes.");
  1989.  if(info->propbytes == 0) return error("Property table expected.");
  1990.  
  1991.  // read properties
  1992.  uint32 bytes_read = 0;
  1993.  while(bytes_read < info->propbytes)
  1994.       {
  1995.        // read index
  1996.        uint32 type = stream.BE_read_uint32();
  1997.        if(stream.fail()) return error("Read failed.");
  1998.        bytes_read += 4;
  1999.       
  2000.        // data bytes
  2001.        uint32 size = stream.BE_read_uint32();
  2002.        if(stream.fail()) return error("Read failed.");
  2003.        bytes_read += 4;
  2004.        bytes_read += size;
  2005.       
  2006.        // find index
  2007.        typedef map<uint32, PSSGATTRIBUTE>::iterator iterator;
  2008.        iterator iter = attrlist.find(type);
  2009.        if(iter == attrlist.end()) {
  2010.           stringstream ss;
  2011.           ss << "Failed to find property for index " << type << "." << ends;
  2012.           return error(ss.str().c_str());
  2013.          }
  2014.       
  2015.        // read attributes
  2016.        const string& parameter = iter->second.parameter;
  2017.        const string& attribute = iter->second.attribute;
  2018.        if(parameter == "SEGMENTSET" && attribute == "segmentCount") {
  2019.           if(!readNumber(stream, info->segmentCount)) return false;
  2020.           if(debug) dfile << "info->segmentCount = " << info->segmentCount << endl;
  2021.          }
  2022.        else if(parameter == "XXX" && attribute == "id") {
  2023.           if(!readString(stream, info->id)) return false;
  2024.           if(debug) dfile << "info->id = " << info->id << endl;
  2025.          }
  2026.        else {
  2027.           stringstream ss;
  2028.           ss << "Unknown block property " << parameter << ":" << attribute << "." << ends;
  2029.           return error(ss.str().c_str());
  2030.          }
  2031.       }
  2032.  
  2033.  // add child chunks to stack
  2034.  if(info->chunksize == info->propbytes + 4) return true;
  2035.  return processChildren(stream, node, position, info->chunksize - bytes_read - 4);
  2036. }
  2037.  
  2038. bool extractor::processSHADER(const binary_stream& bs, uint32 position)
  2039. {
  2040.  return true;
  2041. }
  2042.  
  2043. bool extractor::processSHADERGROUP(const binary_stream& bs, uint32 position)
  2044. {
  2045.  return true;
  2046. }
  2047.  
  2048. bool extractor::processSHADERGROUPPASS(const binary_stream& bs, uint32 position)
  2049. {
  2050.  return true;
  2051. }
  2052.  
  2053. bool extractor::processSHADERINPUT(const binary_stream& bs, uint32 position)
  2054. {
  2055.  return true;
  2056. }
  2057.  
  2058. bool extractor::processSHADERINPUTDEFINITION(const binary_stream& bs, uint32 position)
  2059. {
  2060.  return true;
  2061. }
  2062.  
  2063. bool extractor::processSHADERINSTANCE(const binary_stream& bs, uint32 position)
  2064. {
  2065.  return true;
  2066. }
  2067.  
  2068. bool extractor::processSHADERPROGRAM(const binary_stream& bs, uint32 position)
  2069. {
  2070.  return true;
  2071. }
  2072.  
  2073. bool extractor::processSHADERPROGRAMCODE(const binary_stream& bs, uint32 position)
  2074. {
  2075.  return true;
  2076. }
  2077.  
  2078. bool extractor::processSHADERPROGRAMCODEBLOCK(const binary_stream& bs, uint32 position)
  2079. {
  2080.  return true;
  2081. }
  2082.  
  2083. bool extractor::processSHADERSTREAMDEFINITION(const binary_stream& bs, uint32 position)
  2084. {
  2085.  return true;
  2086. }
  2087.  
  2088. bool extractor::processSKELETON(const binary_stream& bs, uint32 position)
  2089. {
  2090.  return true;
  2091. }
  2092.  
  2093. bool extractor::processSKINJOINT(const binary_stream& bs, uint32 position)
  2094. {
  2095.  return true;
  2096. }
  2097.  
  2098. bool extractor::processSKINNODE(const binary_stream& bs, uint32 position)
  2099. {
  2100.  return true;
  2101. }
  2102.  
  2103. bool extractor::processTEXTURE(const binary_stream& bs, uint32 position)
  2104. {
  2105.  using namespace std;
  2106.  if(debug) dfile << endl;
  2107.  if(debug) dfile << "---------" << endl;
  2108.  if(debug) dfile << " TEXTURE " << endl;
  2109.  if(debug) dfile << "---------" << endl;
  2110.  if(debug) dfile << "offset = " << position << endl;
  2111.  
  2112.  // set stream position
  2113.  binary_stream stream(bs);
  2114.  stream.seek(position);
  2115.  
  2116.  // insert node
  2117.  boost::shared_ptr<TREENODE> node(new TEXTURE);
  2118.  typedef map<uint32, boost::shared_ptr<TREENODE>>::value_type value_type;
  2119.  tree.insert(value_type(position, node));
  2120.  
  2121.  // set parent
  2122.  uint32 parent = 0;
  2123.  map<uint32, uint32>::iterator iter = parent_list.find(position);
  2124.  if(iter != parent_list.end()) parent = iter->second;
  2125.  if(debug) dfile << "parent = " << parent << endl;
  2126.  node->parent = parent;
  2127.  
  2128.  // read chunk properties
  2129.  TEXTURE* info = static_cast<TEXTURE*>(node.get());
  2130.  info->chunktype = stream.BE_read_uint32(); if(stream.fail()) return error("Read failed.");
  2131.  info->chunksize = stream.BE_read_uint32(); if(stream.fail()) return error("Read failed.");
  2132.  info->propbytes = stream.BE_read_uint32(); if(stream.fail()) return error("Read failed.");
  2133.  if(debug) dfile << "chunktype = " << info->chunktype << endl;
  2134.  if(debug) dfile << "chunksize = " << info->chunksize << endl;
  2135.  if(debug) dfile << "propbytes = " << info->propbytes << endl;
  2136.  
  2137.  // initialize properties
  2138.  info->width = 0;
  2139.  info->height = 0;
  2140.  info->transient = 0;
  2141.  info->wrapS = 0;
  2142.  info->wrapT = 0;
  2143.  info->wrapR = 0;
  2144.  info->minFilter = 0;
  2145.  info->magFilter = 0;
  2146.  info->automipmap = 0;
  2147.  info->numberMipMapLevels = 0;
  2148.  info->gammaRemapR = 0;
  2149.  info->gammaRemapG = 0;
  2150.  info->gammaRemapB = 0;
  2151.  info->gammaRemapA = 0;
  2152.  info->lodBias = 0;
  2153.  info->resolveMSAA = 0;
  2154.  info->imageBlockCount = 0;
  2155.  info->allocationStrategy = 0;
  2156.  
  2157.  // validate
  2158.  if(info->propbytes > 1000) return error("Unexpected number of property table bytes.");
  2159.  if(info->propbytes == 0) return error("Property table expected.");
  2160.  
  2161.  // read properties
  2162.  uint32 bytes_read = 0;
  2163.  while(bytes_read < info->propbytes)
  2164.       {
  2165.        // read index
  2166.        uint32 type = stream.BE_read_uint32();
  2167.        if(stream.fail()) return error("Read failed.");
  2168.        bytes_read += 4;
  2169.       
  2170.        // data bytes
  2171.        uint32 size = stream.BE_read_uint32();
  2172.        if(stream.fail()) return error("Read failed.");
  2173.        bytes_read += 4;
  2174.        bytes_read += size;
  2175.       
  2176.        // find index
  2177.        typedef map<uint32, PSSGATTRIBUTE>::iterator iterator;
  2178.        iterator iter = attrlist.find(type);
  2179.        if(iter == attrlist.end()) {
  2180.           stringstream ss;
  2181.           ss << "Failed to find property for index " << type << "." << ends;
  2182.           return error(ss.str().c_str());
  2183.          }
  2184.       
  2185.        // read attributes
  2186.        const string& parameter = iter->second.parameter;
  2187.        const string& attribute = iter->second.attribute;
  2188.        if(parameter == "TEXTURE" && attribute == "width") {
  2189.           if(!readNumber(stream, info->width)) return false;
  2190.           if(debug) dfile << "info->width = " << info->width << endl;
  2191.          }
  2192.        else if(parameter == "TEXTURE" && attribute == "height") {
  2193.           if(!readNumber(stream, info->height)) return false;
  2194.           if(debug) dfile << "info->height = " << info->height << endl;
  2195.          }
  2196.        else if(parameter == "TEXTURE" && attribute == "texelFormat") {
  2197.           if(!readString(stream, info->texelFormat)) return false;
  2198.           if(debug) dfile << "info->texelFormat = " << info->texelFormat << endl;
  2199.          }
  2200.        else if(parameter == "TEXTURE" && attribute == "transient") {
  2201.           if(!readNumber(stream, info->transient)) return false;
  2202.           if(debug) dfile << "info->transient = " << info->transient << endl;
  2203.          }
  2204.        else if(parameter == "TEXTURE" && attribute == "wrapS") {
  2205.           if(!readNumber(stream, info->wrapS)) return false;
  2206.           if(debug) dfile << "info->wrapS = " << info->wrapS << endl;
  2207.          }
  2208.        else if(parameter == "TEXTURE" && attribute == "wrapT") {
  2209.           if(!readNumber(stream, info->wrapT)) return false;
  2210.           if(debug) dfile << "info->wrapT = " << info->wrapT << endl;
  2211.          }
  2212.        else if(parameter == "TEXTURE" && attribute == "wrapR") {
  2213.           if(!readNumber(stream, info->wrapR)) return false;
  2214.           if(debug) dfile << "info->wrapR = " << info->wrapR << endl;
  2215.          }
  2216.        else if(parameter == "TEXTURE" && attribute == "minFilter") {
  2217.           if(!readNumber(stream, info->minFilter)) return false;
  2218.           if(debug) dfile << "info->minFilter = " << info->minFilter << endl;
  2219.          }
  2220.        else if(parameter == "TEXTURE" && attribute == "magFilter") {
  2221.           if(!readNumber(stream, info->magFilter)) return false;
  2222.           if(debug) dfile << "info->magFilter = " << info->magFilter << endl;
  2223.          }
  2224.        else if(parameter == "TEXTURE" && attribute == "automipmap") {
  2225.           if(!readNumber(stream, info->automipmap)) return false;
  2226.           if(debug) dfile << "info->automipmap = " << info->automipmap << endl;
  2227.          }
  2228.        else if(parameter == "TEXTURE" && attribute == "numberMipMapLevels") {
  2229.           if(!readNumber(stream, info->numberMipMapLevels)) return false;
  2230.           if(debug) dfile << "info->numberMipMapLevels = " << info->numberMipMapLevels << endl;
  2231.          }
  2232.        else if(parameter == "TEXTURE" && attribute == "gammaRemapR") {
  2233.           if(!readNumber(stream, info->gammaRemapR)) return false;
  2234.           if(debug) dfile << "info->gammaRemapR = " << info->gammaRemapR << endl;
  2235.          }
  2236.        else if(parameter == "TEXTURE" && attribute == "gammaRemapG") {
  2237.           if(!readNumber(stream, info->gammaRemapG)) return false;
  2238.           if(debug) dfile << "info->gammaRemapG = " << info->gammaRemapG << endl;
  2239.          }
  2240.        else if(parameter == "TEXTURE" && attribute == "gammaRemapB") {
  2241.           if(!readNumber(stream, info->gammaRemapB)) return false;
  2242.           if(debug) dfile << "info->gammaRemapB = " << info->gammaRemapB << endl;
  2243.          }
  2244.        else if(parameter == "TEXTURE" && attribute == "gammaRemapA") {
  2245.           if(!readNumber(stream, info->gammaRemapA)) return false;
  2246.           if(debug) dfile << "info->gammaRemapA = " << info->gammaRemapA << endl;
  2247.          }
  2248.        else if(parameter == "TEXTURE" && attribute == "lodBias") {
  2249.           if(!readNumber(stream, info->lodBias)) return false;
  2250.           if(debug) dfile << "info->lodBias = " << info->lodBias << endl;
  2251.          }
  2252.        else if(parameter == "TEXTURE" && attribute == "resolveMSAA") {
  2253.           if(!readNumber(stream, info->resolveMSAA)) return false;
  2254.           if(debug) dfile << "info->resolveMSAA = " << info->resolveMSAA << endl;
  2255.          }
  2256.        else if(parameter == "TEXTURE" && attribute == "imageBlockCount") {
  2257.           if(!readNumber(stream, info->imageBlockCount)) return false;
  2258.           if(debug) dfile << "info->imageBlockCount = " << info->imageBlockCount << endl;
  2259.          }
  2260.        else if(parameter == "RENDERINTERFACEBOUND" && attribute == "allocationStrategy") {
  2261.           if(!readNumber(stream, info->allocationStrategy)) return false;
  2262.           if(debug) dfile << "info->allocationStrategy = " << info->allocationStrategy << endl;
  2263.          }
  2264.        else if(parameter == "XXX" && attribute == "id") {
  2265.           if(!readString(stream, info->filename)) return false;
  2266.           if(debug) dfile << "info->filename = " << info->filename << endl;
  2267.          }
  2268.        else {
  2269.           stringstream ss;
  2270.           ss << "Unknown block property " << parameter << ":" << attribute << "." << ends;
  2271.           return error(ss.str().c_str());
  2272.          }
  2273.       }
  2274.  
  2275.  // add child chunks to stack
  2276.  if(info->chunksize == info->propbytes + 4) return true;
  2277.  return processChildren(stream, node, position, info->chunksize - bytes_read - 4);
  2278. }
  2279.  
  2280. bool extractor::processTEXTUREIMAGEBLOCK(const binary_stream& bs, uint32 position)
  2281. {
  2282.  using namespace std;
  2283.  if(debug) dfile << endl;
  2284.  if(debug) dfile << "--------------------" << endl;
  2285.  if(debug) dfile << " TEXTUREIMAGEBLOCK " << endl;
  2286.  if(debug) dfile << "--------------------" << endl;
  2287.  if(debug) dfile << "offset = " << position << endl;
  2288.  
  2289.  // set stream position
  2290.  binary_stream stream(bs);
  2291.  stream.seek(position);
  2292.  
  2293.  // insert node
  2294.  boost::shared_ptr<TREENODE> node(new TEXTUREIMAGEBLOCK);
  2295.  typedef map<uint32, boost::shared_ptr<TREENODE>>::value_type value_type;
  2296.  tree.insert(value_type(position, node));
  2297.  
  2298.  // set parent
  2299.  uint32 parent = 0;
  2300.  map<uint32, uint32>::iterator iter = parent_list.find(position);
  2301.  if(iter != parent_list.end()) parent = iter->second;
  2302.  if(debug) dfile << "parent = " << parent << endl;
  2303.  node->parent = parent;
  2304.  
  2305.  // read chunk properties
  2306.  TEXTUREIMAGEBLOCK* info = static_cast<TEXTUREIMAGEBLOCK*>(node.get());
  2307.  info->chunktype = stream.BE_read_uint32(); if(stream.fail()) return error("Read failed.");
  2308.  info->chunksize = stream.BE_read_uint32(); if(stream.fail()) return error("Read failed.");
  2309.  info->propbytes = stream.BE_read_uint32(); if(stream.fail()) return error("Read failed.");
  2310.  if(debug) dfile << "chunktype = " << info->chunktype << endl;
  2311.  if(debug) dfile << "chunksize = " << info->chunksize << endl;
  2312.  if(debug) dfile << "propbytes = " << info->propbytes << endl;
  2313.  
  2314.  // validate
  2315.  if(info->propbytes > 1000) return error("Unexpected number of property table bytes.");
  2316.  if(info->propbytes == 0) return error("Property table expected.");
  2317.  
  2318.  // read properties
  2319.  uint32 bytes_read = 0;
  2320.  while(bytes_read < info->propbytes)
  2321.       {
  2322.        // read index
  2323.        uint32 type = stream.BE_read_uint32();
  2324.        if(stream.fail()) return error("Read failed.");
  2325.        bytes_read += 4;
  2326.       
  2327.        // data bytes
  2328.        uint32 size = stream.BE_read_uint32();
  2329.        if(stream.fail()) return error("Read failed.");
  2330.        bytes_read += 4;
  2331.        bytes_read += size;
  2332.       
  2333.        // find index
  2334.        typedef map<uint32, PSSGATTRIBUTE>::iterator iterator;
  2335.        iterator iter = attrlist.find(type);
  2336.        if(iter == attrlist.end()) {
  2337.           stringstream ss;
  2338.           ss << "Failed to find property for index " << type << "." << ends;
  2339.           return error(ss.str().c_str());
  2340.          }
  2341.       
  2342.        // read attributes
  2343.        const string& parameter = iter->second.parameter;
  2344.        const string& attribute = iter->second.attribute;
  2345.        if(parameter == "TEXTUREIMAGEBLOCK" && attribute == "typename") {
  2346.           if(!readString(stream, info->name)) return false;
  2347.           if(debug) dfile << "info->name = " << info->name << endl;
  2348.          }
  2349.        else if(parameter == "TEXTUREIMAGEBLOCK" && attribute == "size") {
  2350.           if(!readNumber(stream, info->size)) return false;
  2351.           if(debug) dfile << "info->size = " << info->size << endl;
  2352.          }
  2353.        else {
  2354.           stringstream ss;
  2355.           ss << "Unknown block property " << parameter << ":" << attribute << "." << ends;
  2356.           return error(ss.str().c_str());
  2357.          }
  2358.       }
  2359.  
  2360.  // add child chunks to stack
  2361.  if(info->chunksize == info->propbytes + 4) return true;
  2362.  return processChildren(stream, node, position, info->chunksize - bytes_read - 4);
  2363. }
  2364.  
  2365. bool extractor::processTEXTUREIMAGEBLOCKDATA(const binary_stream& bs, uint32 position)
  2366. {
  2367.  using namespace std;
  2368.  if(debug) dfile << endl;
  2369.  if(debug) dfile << "-----------------------" << endl;
  2370.  if(debug) dfile << " TEXTUREIMAGEBLOCKDATA " << endl;
  2371.  if(debug) dfile << "-----------------------" << endl;
  2372.  if(debug) dfile << "offset = " << position << endl;
  2373.  
  2374.  // set stream position
  2375.  binary_stream stream(bs);
  2376.  stream.seek(position);
  2377.  
  2378.  // insert node
  2379.  boost::shared_ptr<TREENODE> node(new TEXTUREIMAGEBLOCKDATA);
  2380.  typedef map<uint32, boost::shared_ptr<TREENODE>>::value_type value_type;
  2381.  tree.insert(value_type(position, node));
  2382.  
  2383.  // set parent
  2384.  uint32 parent = 0;
  2385.  map<uint32, uint32>::iterator iter = parent_list.find(position);
  2386.  if(iter != parent_list.end()) parent = iter->second;
  2387.  if(debug) dfile << "parent = " << parent << endl;
  2388.  node->parent = parent;
  2389.  
  2390.  // read chunk properties
  2391.  TEXTUREIMAGEBLOCKDATA* info = static_cast<TEXTUREIMAGEBLOCKDATA*>(node.get());
  2392.  info->chunktype = stream.BE_read_uint32(); if(stream.fail()) return error("Read failed.");
  2393.  info->chunksize = stream.BE_read_uint32(); if(stream.fail()) return error("Read failed.");
  2394.  info->propbytes = stream.BE_read_uint32(); if(stream.fail()) return error("Read failed.");
  2395.  if(debug) dfile << "chunktype = " << info->chunktype << endl;
  2396.  if(debug) dfile << "chunksize = " << info->chunksize << endl;
  2397.  if(debug) dfile << "propbytes = " << info->propbytes << endl;
  2398.  
  2399.  // validate
  2400.  if(info->propbytes) return error("Property table unexpected.");
  2401.  
  2402.  // get TEXTUREIMAGEBLOCK
  2403.  tree_iterator parent_ptr = tree.find(parent);
  2404.  if(parent_ptr == tree.end()) return error("Expecting TEXTUREIMAGEBLOCKDATA to have TEXTUREIMAGEBLOCK parent.");
  2405.  TEXTUREIMAGEBLOCK* tib = static_cast<TEXTUREIMAGEBLOCK*>(parent_ptr->second.get());
  2406.  if(!tib) return error("Static cast failed.");
  2407.  
  2408.  // get TEXTURE
  2409.  parent_ptr = tree.find(tib->parent);
  2410.  if(parent_ptr == tree.end()) return error("Expecting TEXTUREIMAGEBLOCK to have TEXTURE parent.");
  2411.  TEXTURE* texture = static_cast<TEXTURE*>(parent_ptr->second.get());
  2412.  if(!tib) return error("Static cast failed.");
  2413.  
  2414.  // read texture data
  2415.  info->data.reset(new unsigned char[tib->size]);
  2416.  stream.read((char*)info->data.get(), tib->size);
  2417.  if(stream.fail()) return error("Read failure.");
  2418.  
  2419.  // create filename
  2420.  if(!HasExtension(texture->filename, ".dds")) texture->filename += ".dds";
  2421.  stringstream filename;
  2422.  filename << GetPathnameFromFilename(currfile) << texture->filename;
  2423.  
  2424.  // save DDS file
  2425.  DDS_HEADER ddsh;
  2426.  if(texture->texelFormat == "dxt1") {
  2427.     CreateDXT1Header(texture->width, texture->height, texture->numberMipMapLevels, FALSE, &ddsh);
  2428.     ofstream ofile(filename.str().c_str(), ios::binary);
  2429.     if(!ofile) return error("Failed to create DDS file.");
  2430.     ofile.write("DDS ", 4);
  2431.     ofile.write((char*)&ddsh, sizeof(ddsh));
  2432.     ofile.write((char*)info->data.get(), tib->size);
  2433.     if(ofile.fail()) return error("Failed to write DDS data.");
  2434.    }
  2435.  else if(texture->texelFormat == "dxt2") {
  2436.     CreateDXT2Header(texture->width, texture->height, texture->numberMipMapLevels, FALSE, &ddsh);
  2437.     ofstream ofile(filename.str().c_str(), ios::binary);
  2438.     if(!ofile) return error("Failed to create DDS file.");
  2439.     ofile.write("DDS ", 4);
  2440.     ofile.write((char*)&ddsh, sizeof(ddsh));
  2441.     ofile.write((char*)info->data.get(), tib->size);
  2442.     if(ofile.fail()) return error("Failed to write DDS data.");
  2443.    }
  2444.  else if(texture->texelFormat == "dxt3") {
  2445.     CreateDXT3Header(texture->width, texture->height, texture->numberMipMapLevels, FALSE, &ddsh);
  2446.     ofstream ofile(filename.str().c_str(), ios::binary);
  2447.     if(!ofile) return error("Failed to create DDS file.");
  2448.     ofile.write("DDS ", 4);
  2449.     ofile.write((char*)&ddsh, sizeof(ddsh));
  2450.     ofile.write((char*)info->data.get(), tib->size);
  2451.     if(ofile.fail()) return error("Failed to write DDS data.");
  2452.    }
  2453.  else if(texture->texelFormat == "dxt4") {
  2454.     CreateDXT4Header(texture->width, texture->height, texture->numberMipMapLevels, FALSE, &ddsh);
  2455.     ofstream ofile(filename.str().c_str(), ios::binary);
  2456.     if(!ofile) return error("Failed to create DDS file.");
  2457.     ofile.write("DDS ", 4);
  2458.     ofile.write((char*)&ddsh, sizeof(ddsh));
  2459.     ofile.write((char*)info->data.get(), tib->size);
  2460.    }
  2461.  else if(texture->texelFormat == "dxt5") {
  2462.     CreateDXT5Header(texture->width, texture->height, texture->numberMipMapLevels, FALSE, &ddsh);
  2463.     ofstream ofile(filename.str().c_str(), ios::binary);
  2464.     if(!ofile) return error("Failed to create DDS file.");
  2465.     ofile.write("DDS ", 4);
  2466.     ofile.write((char*)&ddsh, sizeof(ddsh));
  2467.     ofile.write((char*)info->data.get(), tib->size);
  2468.     if(ofile.fail()) return error("Failed to write DDS data.");
  2469.    }
  2470.  else if(texture->texelFormat == "u8x4") {
  2471.     CreateUncompressedDDSHeader(texture->width, texture->height, texture->numberMipMapLevels, 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000, FALSE, &ddsh);
  2472.     ofstream ofile(filename.str().c_str(), ios::binary);
  2473.     if(!ofile) return error("Failed to create DDS file.");
  2474.     ofile.write("DDS ", 4);
  2475.     ofile.write((char*)&ddsh, sizeof(ddsh));
  2476.     ofile.write((char*)info->data.get(), tib->size);
  2477.     if(ofile.fail()) return error("Failed to write DDS data.");
  2478.    }
  2479.  else if(texture->texelFormat == "ui8x4") {
  2480.     CreateUncompressedDDSHeader(texture->width, texture->height, texture->numberMipMapLevels, 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000, FALSE, &ddsh);
  2481.     ofstream ofile(filename.str().c_str(), ios::binary);
  2482.     if(!ofile) return error("Failed to create DDS file.");
  2483.     ofile.write("DDS ", 4);
  2484.     ofile.write((char*)&ddsh, sizeof(ddsh));
  2485.     ofile.write((char*)info->data.get(), tib->size);
  2486.     if(ofile.fail()) return error("Failed to write DDS data.");
  2487.    }
  2488.  else {
  2489.     stringstream ss;
  2490.     ss << "Invalid texture compression method " << texture->texelFormat << ".";
  2491.     return error(ss.str().c_str());
  2492.    }
  2493.  
  2494.  // no children
  2495.  return true;
  2496. }
  2497.  
  2498. bool extractor::processTRANSFORM(const binary_stream& bs, uint32 position)
  2499. {
  2500.  return true;
  2501. }
  2502.  
  2503. bool extractor::processTYPEINFO(const binary_stream& bs, uint32 position)
  2504. {
  2505.  using namespace std;
  2506.  if(debug) dfile << endl;
  2507.  if(debug) dfile << "----------" << endl;
  2508.  if(debug) dfile << " TYPEINFO " << endl;
  2509.  if(debug) dfile << "----------" << endl;
  2510.  if(debug) dfile << "offset = " << position << endl;
  2511.  
  2512.  // set stream position
  2513.  binary_stream stream(bs);
  2514.  stream.seek(position);
  2515.  
  2516.  // insert node
  2517.  boost::shared_ptr<TREENODE> node(new TYPEINFO);
  2518.  typedef map<uint32, boost::shared_ptr<TREENODE>>::value_type value_type;
  2519.  tree.insert(value_type(position, node));
  2520.  
  2521.  // set parent
  2522.  uint32 parent = 0;
  2523.  map<uint32, uint32>::iterator iter = parent_list.find(position);
  2524.  if(iter != parent_list.end()) parent = iter->second;
  2525.  if(debug) dfile << "parent = " << parent << endl;
  2526.  node->parent = parent;
  2527.  
  2528.  // read chunk properties
  2529.  TYPEINFO* info = static_cast<TYPEINFO*>(node.get());
  2530.  info->chunktype = stream.BE_read_uint32(); if(stream.fail()) return error("Read failed.");
  2531.  info->chunksize = stream.BE_read_uint32(); if(stream.fail()) return error("Read failed.");
  2532.  info->propbytes = stream.BE_read_uint32(); if(stream.fail()) return error("Read failed.");
  2533.  if(debug) dfile << "chunktype = " << info->chunktype << endl;
  2534.  if(debug) dfile << "chunksize = " << info->chunksize << endl;
  2535.  if(debug) dfile << "propbytes = " << info->propbytes << endl;
  2536.  
  2537.  // validate
  2538.  if(info->propbytes > 1000) return error("Unexpected number of property table bytes.");
  2539.  if(info->propbytes == 0) return error("Property table expected.");
  2540.  
  2541.  // read properties
  2542.  uint32 bytes_read = 0;
  2543.  while(bytes_read < info->propbytes)
  2544.       {
  2545.        // read index
  2546.        uint32 type = stream.BE_read_uint32();
  2547.        if(stream.fail()) return error("Read failed.");
  2548.        bytes_read += 4;
  2549.       
  2550.        // data bytes
  2551.        uint32 size = stream.BE_read_uint32();
  2552.        if(stream.fail()) return error("Read failed.");
  2553.        bytes_read += 4;
  2554.        bytes_read += size;
  2555.       
  2556.        // find index
  2557.        typedef map<uint32, PSSGATTRIBUTE>::iterator iterator;
  2558.        iterator iter = attrlist.find(type);
  2559.        if(iter == attrlist.end()) {
  2560.           stringstream ss;
  2561.           ss << "Failed to find property for index " << type << "." << ends;
  2562.           return error(ss.str().c_str());
  2563.          }
  2564.       
  2565.        // read attributes
  2566.        const string& parameter = iter->second.parameter;
  2567.        const string& attribute = iter->second.attribute;
  2568.        if(parameter == "TYPEINFO" && attribute == "typeName") {
  2569.           if(!readString(stream, info->typeName)) return false;
  2570.           if(debug) dfile << "info->typeName = " << info->typeName << endl;
  2571.          }
  2572.        else if(parameter == "TYPEINFO" && attribute == "typeCount") {
  2573.           if(!readNumber(stream, info->typeCount)) return false;
  2574.           if(debug) dfile << "info->typeCount = " << info->typeCount << endl;
  2575.          }
  2576.        else {
  2577.           stringstream ss;
  2578.           ss << "Unknown block property " << parameter << ":" << attribute << "." << ends;
  2579.           return error(ss.str().c_str());
  2580.          }
  2581.       }
  2582.  
  2583.  // add child chunks to stack
  2584.  if(info->chunksize == info->propbytes + 4) return true;
  2585.  return processChildren(stream, node, position, info->chunksize - bytes_read - 4);
  2586. }
  2587.  
  2588. bool extractor::processUSERATTRIBUTE(const binary_stream& bs, uint32 position)
  2589. {
  2590.  return true;
  2591. }
  2592.  
  2593. bool extractor::processUSERATTRIBUTELIST(const binary_stream& bs, uint32 position)
  2594. {
  2595.  return true;
  2596. }
  2597.  
  2598. bool extractor::processUSERDATA(const binary_stream& bs, uint32 position)
  2599. {
  2600.  return true;
  2601. }
  2602.  
  2603. bool extractor::processWEIGHTS(const binary_stream& bs, uint32 position)
  2604. {
  2605.  return true;
  2606. }
  2607.  
  2608. bool extractor::processXXX(const binary_stream& bs, uint32 position)
  2609. {
  2610.  using namespace std;
  2611.  if(debug) dfile << endl;
  2612.  if(debug) dfile << "-----" << endl;
  2613.  if(debug) dfile << " XXX " << endl;
  2614.  if(debug) dfile << "-----" << endl;
  2615.  if(debug) dfile << "offset = " << position << endl;
  2616.  
  2617.  // set stream position
  2618.  binary_stream stream(bs);
  2619.  stream.seek(position);
  2620.  
  2621.  // insert node
  2622.  boost::shared_ptr<TREENODE> node(new XXX);
  2623.  typedef map<uint32, boost::shared_ptr<TREENODE>>::value_type value_type;
  2624.  tree.insert(value_type(position, node));
  2625.  
  2626.  // set parent
  2627.  uint32 parent = 0;
  2628.  map<uint32, uint32>::iterator iter = parent_list.find(position);
  2629.  if(iter != parent_list.end()) parent = iter->second;
  2630.  if(debug) dfile << "parent = " << parent << endl;
  2631.  node->parent = parent;
  2632.  
  2633.  // read chunk properties
  2634.  XXX* info = static_cast<XXX*>(node.get());
  2635.  info->chunktype = stream.BE_read_uint32(); if(stream.fail()) return error("Read failed.");
  2636.  info->chunksize = stream.BE_read_uint32(); if(stream.fail()) return error("Read failed.");
  2637.  info->propbytes = stream.BE_read_uint32(); if(stream.fail()) return error("Read failed.");
  2638.  if(debug) dfile << "chunktype = " << info->chunktype << endl;
  2639.  if(debug) dfile << "chunksize = " << info->chunksize << endl;
  2640.  if(debug) dfile << "propbytes = " << info->propbytes << endl;
  2641.  
  2642.  // initialize attributes
  2643.  info->id = "";
  2644.  
  2645.  // validate
  2646.  if(info->propbytes > 1000) return error("Unexpected number of property table bytes.");
  2647.  if(info->propbytes == 0) return error("Property table expected.");
  2648.  
  2649.  // read properties
  2650.  uint32 bytes_read = 0;
  2651.  while(bytes_read < info->propbytes)
  2652.       {
  2653.        // read index
  2654.        uint32 type = stream.BE_read_uint32();
  2655.        if(stream.fail()) return error("Read failed.");
  2656.        bytes_read += 4;
  2657.       
  2658.        // data bytes
  2659.        uint32 size = stream.BE_read_uint32();
  2660.        if(stream.fail()) return error("Read failed.");
  2661.        bytes_read += 4;
  2662.        bytes_read += size;
  2663.       
  2664.        // find index
  2665.        typedef map<uint32, PSSGATTRIBUTE>::iterator iterator;
  2666.        iterator iter = attrlist.find(type);
  2667.        if(iter == attrlist.end()) {
  2668.           stringstream ss;
  2669.           ss << "Failed to find property for index " << type << "." << ends;
  2670.           return error(ss.str().c_str());
  2671.          }
  2672.       
  2673.        // read attributes
  2674.        const string& parameter = iter->second.parameter;
  2675.        const string& attribute = iter->second.attribute;
  2676.        if(parameter == "XXX" && attribute == "id") {
  2677.           if(!readString(stream, info->id)) return false;
  2678.           if(debug) dfile << "info->id = " << info->id << endl;
  2679.          }
  2680.        else {
  2681.           stringstream ss;
  2682.           ss << "Unknown block property " << parameter << ":" << attribute << "." << ends;
  2683.           return error(ss.str().c_str());
  2684.          }
  2685.       }
  2686.  
  2687.  // add child chunks to stack
  2688.  if(info->chunksize == info->propbytes + 4) return true;
  2689.  return processChildren(stream, node, position, info->chunksize - bytes_read - 4);
  2690. }
  2691.  
  2692. };
  2693.  
  2694. namespace PSSG {
  2695.  
  2696. bool extract(void)
  2697. {
  2698.  std::string pathname = GetModulePathname();
  2699.  return extract(pathname.c_str());
  2700. }
  2701.  
  2702. bool extract(const char* pathname)
  2703. {
  2704.  return extractor(pathname).extract();
  2705. }
  2706.  
  2707. };