home *** CD-ROM | disk | FTP | other *** search
- #include "xentax.h"
- #include "x_file.h"
- #include "x_findfile.h"
- #include "x_stream.h"
- #include "x_dds.h"
- #include "x_smc.h"
- #include "ps3_one_piece.h"
-
- #define X_SYSTEM PS3
- #define X_GAME OnePiece
-
- namespace X_SYSTEM { namespace X_GAME {
-
- #define GUSELESS 0
- #define GARCHIVE 1
- #define G1TG0050 2
- #define G1TG0060 3
- #define G1CT0001 4
- #define G1M_0034 5
-
- class extractor {
- private :
- std::string pathname;
- private :
- bool debug;
- std::ofstream dfile;
- private :
- bool unpack(const std::string& filename)const;
- char getFileType(std::ifstream& ifile)const;
- bool processBIN(const std::string& filename);
- bool processG1T(binary_stream& bs, const std::string& filepath);
- bool processG1M(binary_stream& bs, const std::string& filepath);
- private :
- bool processG1MG0044(const binary_stream& bs, SIMPLEMODELCONTAINER& smc);
- public :
- bool extract(void);
- public :
- extractor(const char* pn) : pathname(pn) {}
- ~extractor() {}
- };
-
- };};
-
- namespace X_SYSTEM { namespace X_GAME {
-
- bool extractor::unpack(const std::string& filename)const
- {
- // open file
- using namespace std;
- ifstream ifile;
- ifile.open(filename.c_str(), ios::binary);
- if(!ifile) return error("Could not open file.");
-
- // read header
- uint32 headMagic = BE_read_uint32(ifile); if(ifile.fail()) return error("Read failure.");
- uint32 headFiles = BE_read_uint32(ifile); if(ifile.fail()) return error("Read failure.");
- uint32 headScale = BE_read_uint32(ifile); if(ifile.fail()) return error("Read failure.");
- uint32 headUnk01 = BE_read_uint32(ifile); if(ifile.fail()) return error("Read failure.");
-
- // validate header
- if(headMagic != 0x077DF9) return error("Invalid header signature.");
- if(headFiles >= 0xFFFF) return error("No dynasty warriors game contains this many files.");
- if(headScale != 0x0800) return error("File assets should occur on 0x800 boundaries.");
-
- // read file table
- deque<pair<uint32, uint32>> filetable;
- for(size_t i = 0; i < headFiles; i++) {
- uint32 param1 = BE_read_uint32(ifile); // 0x00
- uint32 param2 = BE_read_uint32(ifile); // scaled offset
- uint32 param3 = BE_read_uint32(ifile); // filesize
- uint32 param4 = BE_read_uint32(ifile); // 0x00
- pair<uint32, uint32> p;
- p.first = param2; if(ifile.fail()) return error("Read failure.");
- p.second = param3; if(ifile.fail()) return error("Read failure.");
- filetable.push_back(p);
- }
-
- // create subdirectory string
- string subdpath = GetShortFilename(filename);
- for(size_t i = 0; i < subdpath.length(); i++) if(subdpath[i] == '.') subdpath[i] = '_';
-
- // create save path
- string savepath = GetPathnameFromFilename(filename);
- savepath += subdpath;
- savepath += "\\";
- CreateDirectoryA(savepath.c_str(), NULL);
-
- // for each item in the file table
- for(size_t i = 0; i < filetable.size(); i++)
- {
- // move to file position
- size_t position = filetable[i].first*headScale;
- size_t filesize = filetable[i].second;
- ifile.seekg(position);
- if(ifile.fail()) return error("Failed to seek file position.");
-
- // create file
- cout << "Reading file " << (i + 1) << " of " << filetable.size() << "." << endl;
- stringstream name;
- name << savepath << setfill('0') << setw(4) << i << ".bin";
- ofstream ofile(name.str().c_str(), ios::binary);
- if(!ofile) return error("Failed to create bin file.");
-
- // small files
- if(filesize < 0x2000000) // 32 MB
- {
- // read data
- boost::shared_array<char> data(new char[filesize]);
- ifile.read(data.get(), filesize);
- if(ifile.fail()) return error("Read failure.");
-
- // save data
- ofile.write(data.get(), filesize);
- if(ofile.fail()) return error("Failed to write to bin file.");
- }
- // large files
- else
- {
- // create buffer
- cout << " NOTE: This is a large file and might take a while to save." << endl;
- uint32 buffersize = 0x1000000; // 16 MB
- boost::shared_array<char> data(new char[buffersize]);
-
- // read and copy data
- uint32 bytes_left = filesize;
- while(bytes_left)
- {
- // specify how much to read
- uint32 datasize = buffersize;
- if(bytes_left < buffersize) datasize = bytes_left;
-
- // read data
- ifile.read(data.get(), datasize);
- if(ifile.fail()) return error("Read failure.");
-
- // save data
- ofile.write(data.get(), datasize);
- if(ofile.fail()) return error("Failed to write to bin file.");
-
- // update
- bytes_left -= datasize;
- }
- }
- }
-
- cout << endl;
- return true;
- }
-
- char extractor::getFileType(std::ifstream& ifile)const
- {
- // get filesize
- using namespace std;
- ifile.seekg(0, ios::end);
- uint32 filesize = (uint32)ifile.tellg();
- ifile.seekg(0, ios::beg);
-
- // read first uint32
- uint32 head01 = BE_read_uint32(ifile);
- if(ifile.fail()) {
- error("getFileType(): Read failure.");
- return GUSELESS;
- }
-
- // G1M_0034?
- if(head01 == 0x47314D5F) {
- uint32 head02 = BE_read_uint32(ifile);
- if(ifile.fail()) {
- error("getFileType(): Read failure.");
- return GUSELESS;
- }
- if(head02 == 0x30303334) return G1M_0034;
- return GUSELESS;
- }
-
- // G1TG0050 or G1TG0060?
- if(head01 == 0x47315447) {
- uint32 head02 = BE_read_uint32(ifile);
- if(ifile.fail()) {
- error("getFileType(): Read failure.");
- return GUSELESS;
- }
- if(head02 == 0x30303530) return G1TG0050;
- if(head02 == 0x30303630) return G1TG0060;
- return GUSELESS;
- }
-
- // G1CT0001?
- if(head01 == 0x47314354) {
- uint32 head02 = BE_read_uint32(ifile);
- if(ifile.fail()) {
- error("getFileType(): Read failure.");
- return GUSELESS;
- }
- if(head02 == 0x30303031) return G1CT0001;
- return GUSELESS;
- }
-
- // archive?
- if((head01 == 0) || !(head01 < 0x2FF)) return GUSELESS; // largest is 0x2D1
-
- // can we read all offsets?
- if(filesize < head01*sizeof(uint32)) return GUSELESS;
-
- // read offsets
- boost::shared_array<uint32> offsets(new uint32[head01]);
- BE_read_array(ifile, offsets.get(), head01);
- if(ifile.fail()) {
- error("getFileType(): Read failure.");
- return GUSELESS;
- }
-
- // check first offset
- uint32 prev = offsets[0];
- if((prev == 0) || !(prev < filesize)) return GUSELESS;
-
- // check other offsets
- for(uint32 i = 1; i < head01; i++) {
- if(offsets[i] == 0) return false;
- if(offsets[i] < offsets[i - 1]) return GUSELESS;
- if(!(offsets[i] < filesize)) return GUSELESS;
- }
-
- // move back to the beginning if it is!
- ifile.seekg(0, ios::beg);
- return GARCHIVE;
- }
-
- bool extractor::processBIN(const std::string& filename)
- {
- // open file
- using namespace std;
- ifstream ifile;
- ifile.open(filename.c_str(), ios::binary);
- if(!ifile) return error("processBIN: Could not open file.");
-
- // is this an archive?
- char ftype = getFileType(ifile);
- if(ifile.fail()) return error("processBIN: Seek failure.");
-
- // compute filesize
- ifile.seekg(0, ios::end);
- if(ifile.fail()) return error("processBIN: Seek failure.");
- uint32 filesize = (uint32)ifile.tellg();
- ifile.seekg(0, ios::beg);
- if(ifile.fail()) return error("processBIN: Seek failure.");
-
- // depending on file type
- switch(ftype) {
- case(GUSELESS) : break;
- case(GARCHIVE) : break;
- case(G1TG0050) : {
- string filepath = GetPathnameFromFilename(filename);
- filepath += GetShortFilenameWithoutExtension(filename);
- boost::shared_array<char> data(new char[filesize]);
- ifile.read(data.get(), filesize);
- if(ifile.fail()) return error("processBin: Read failure.");
- binary_stream bs(data, filesize);
- //processG1T(bs, filepath);
- break;
- }
- case(G1TG0060) : {
- string filepath = GetPathnameFromFilename(filename);
- filepath += GetShortFilenameWithoutExtension(filename);
- boost::shared_array<char> data(new char[filesize]);
- ifile.read(data.get(), filesize);
- if(ifile.fail()) return error("processBin: Read failure.");
- binary_stream bs(data, filesize);
- //processG1T(bs, filepath);
- break;
- }
- case(G1CT0001) : {
- break;
- }
- case(G1M_0034) : {
- string filepath = GetPathnameFromFilename(filename);
- filepath += GetShortFilenameWithoutExtension(filename);
- boost::shared_array<char> data(new char[filesize]);
- ifile.read(data.get(), filesize);
- if(ifile.fail()) return error("processBin: Read failure.");
- binary_stream bs(data, filesize);
- if(!processG1M(bs, filepath)) return false;
- break;
- }
- }
-
- /*
- // create buffer
- uint32 buffersize = 0x1000000; // 16 MB
- boost::shared_array<char> data(new char[buffersize]);
-
- uint32 foundModel = 0;
- uint32 foundG1TG5 = 0;
- uint32 foundG1TG6 = 0;
-
- // read and copy data
- uint32 bytes_left = filesize;
- while(bytes_left)
- {
- // specify how much to read
- uint32 datasize = buffersize;
- if(bytes_left < buffersize) datasize = bytes_left;
-
- // read data
- ifile.read(data.get(), datasize);
- if(ifile.fail()) {
- cout << "filesize, datasize = " << filesize << ", " << datasize << endl;
- return error("Read failure.");
- }
-
- // find data
- binary_stream bs(data, datasize);
- if(bs.search("G1M_0034", 8) != binary_stream::npos) foundModel++;
- if(bs.search("G1TG0050", 8) != binary_stream::npos) foundG1TG5++;
- if(bs.search("G1TG0060", 8) != binary_stream::npos) foundG1TG6++;
-
- // update
- bytes_left -= datasize;
- }
-
- if(debug && (foundModel || foundG1TG5 || foundG1TG6)) {
- dfile << filename << endl;
- if(ftype == GARCHIVE) dfile << "GARCHIVE" << endl;
- if(ftype == GUSELESS) dfile << "GUSELESS" << endl;
- if(ftype == G1M_0034) dfile << "G1M_0034" << endl;
- if(ftype == G1CT0001) dfile << "G1CT0001" << endl;
- if(ftype == G1TG0050) dfile << "G1TG0050" << endl;
- if(ftype == G1TG0060) dfile << "G1TG0060" << endl;
- if(foundModel) dfile << "Models: YES" << endl;
- if(foundG1TG5) dfile << "G1TG5s: YES" << endl;
- if(foundG1TG6) dfile << "G1TG6s: YES" << endl;
- }
- */
-
- return true;
- }
-
- bool extractor::processG1T(binary_stream& bs, const std::string& filepath)
- {
- using namespace std;
-
- // create folder to save files
- CreateDirectoryA(filepath.c_str(), NULL);
-
- // read header
- uint32 magic = bs.BE_read_uint32();
- uint32 version = bs.BE_read_uint32();
- uint32 section_size = bs.BE_read_uint32();
- uint32 table_offset = bs.BE_read_uint32();
- uint32 n_textures = bs.BE_read_uint32();
-
- // validate header
- if(magic != 0x47315447) return error("Expecting G1TG section.");
- if(!(version == 0x30303530 || version == 0x30303630)) return error("Invalid G1TG version.");
- if(n_textures == 0) return error("Invalid number of textures.");
-
- // move to table
- bs.seek(table_offset);
- if(bs.fail()) return error("Stream seek failure.");
-
- // read offset table
- deque<size_t> offset_list;
- for(size_t i = 0; i < n_textures; i++) {
- offset_list.push_back(bs.BE_read_uint32());
- if(bs.fail()) return error("Stream read failure.");
- }
-
- // process textures
- for(size_t i = 0; i < offset_list.size(); i++)
- {
- bs.seek(table_offset + offset_list[i]);
- if(bs.fail()) return error("Stream seek failure.");
-
- // read texture information
- // 0x08 bytes
- uint08 b1 = bs.BE_read_uint08(); // unknown
- uint08 b2 = bs.BE_read_uint08(); // texture type
- uint08 b3 = bs.BE_read_uint08(); // dx/dy
- uint08 b4 = bs.BE_read_uint08(); // unknown
- uint16 s1 = bs.BE_read_uint16(); // unknown
- uint16 s2 = bs.BE_read_uint16(); // unknown
-
- // header is extended depending on s2
- // 0x0C bytes
- if(s2 == 0x1201) { // version == 0x30303630) {
- uint32 v1 = bs.BE_read_uint32(); // 12
- uint32 v2 = bs.BE_read_uint32(); // 0
- uint32 v3 = bs.BE_read_uint32(); // 0 or 1
- }
-
- // number of bytes in header
- uint32 headerBytes = 0x08;
- if(s2 == 0x1201) headerBytes += 0x0C;
-
- // compute dimensions
- uint32 temp1 = ((b3 & 0xF0) >> 4);
- uint32 temp2 = ((b3 & 0x0F));
- uint32 dx = 1 << temp1;
- uint32 dy = 1 << temp2;
-
- // create texture file
- stringstream filename;
- filename << filepath << setfill('0') << setw(3) << i << ".dds";
- ofstream ofile(filename.str().c_str(), ios::binary);
-
- // save texture
- if(b2 == 0)
- {
- // read texture
- DWORD filesize = UncompressedDDSFileSize(dx, dy, 0, 0xFF, 0xFF00, 0xFF0000, 0xFF000000);
- boost::shared_array<char> buffer(new char[filesize]);
- bs.read((char*)buffer.get(), filesize);
-
- // save texture
- DDS_HEADER ddsh;
- CreateUncompressedDDSHeader(dx, dy, 0, 0xFF000000, 0xFF0000, 0xFF00, 0xFF, FALSE, &ddsh);
- DWORD signature = 0x20534444;
- ofile.write((char*)&signature, sizeof(signature));
- ofile.write((char*)&ddsh, sizeof(ddsh));
- ofile.write((char*)buffer.get(), filesize);
- }
- // UNCOMPRESSED DDS (PS3 works good)
- else if(b2 == 1)
- {
- // read texture
- DWORD filesize = UncompressedDDSFileSize(dx, dy, 0, 0xFF, 0xFF00, 0xFF0000, 0xFF000000);
- boost::shared_array<char> buffer(new char[filesize]);
- bs.read((char*)buffer.get(), filesize);
-
- // save texture
- DDS_HEADER ddsh;
- CreateUncompressedDDSHeader(dx, dy, 0, 0xFF000000, 0xFF0000, 0xFF00, 0xFF, FALSE, &ddsh);
- DWORD signature = 0x20534444;
- ofile.write((char*)&signature, sizeof(signature));
- ofile.write((char*)&ddsh, sizeof(ddsh));
- ofile.write((char*)buffer.get(), filesize);
- }
- // DXT1 (PS3 works good)
- else if(b2 == 6)
- {
- // read texture
- DWORD filesize = DXT1Filesize(dx, dy, 0);
- boost::shared_array<char> buffer(new char[filesize]);
- bs.read((char*)buffer.get(), filesize);
-
- // save texture
- DDS_HEADER ddsh;
- CreateDXT1Header(dx, dy, 0, FALSE, &ddsh);
- DWORD signature = 0x20534444;
- ofile.write((char*)&signature, sizeof(signature));
- ofile.write((char*)&ddsh, sizeof(ddsh));
- ofile.write((char*)buffer.get(), filesize);
- }
- // DXT5 (PS3 works good)
- else if(b2 == 8)
- {
- // read texture
- DWORD filesize = DXT5Filesize(dx, dy, 0);
- boost::shared_array<char> buffer(new char[filesize]);
- bs.read((char*)buffer.get(), filesize);
-
- // save texture
- DDS_HEADER ddsh;
- CreateDXT5Header(dx, dy, 0, FALSE, &ddsh);
- DWORD signature = 0x20534444;
- ofile.write((char*)&signature, sizeof(signature));
- ofile.write((char*)&ddsh, sizeof(ddsh));
- ofile.write((char*)buffer.get(), filesize);
- }
- else {
- stringstream msg;
- msg << "Unsupported texture type #" << (uint32)b2 << ".";
- return error(msg.str().c_str());
- }
- }
-
- return true;
- }
-
- bool extractor::processG1M(binary_stream& bs, const std::string& filepath)
- {
- using namespace std;
-
- // create model container
- SIMPLEMODELCONTAINER smc;
-
- // create folder to save files
- CreateDirectoryA(filepath.c_str(), NULL);
-
- // read header
- uint32 head01 = bs.BE_read_uint32(); // magic
- uint32 head02 = bs.BE_read_uint32(); // version
- uint32 head03 = bs.BE_read_uint32(); // total section size
- uint32 head04 = bs.BE_read_uint32(); // start offset
- uint32 head05 = bs.BE_read_uint32(); // 0x00
- uint32 head06 = bs.BE_read_uint32(); // number of chunks to read
-
- // validate header
- if(head01 != 0x47314D5F) return error("Expecting G1M_ section.");
- if(head02 != 0x30303334) return error("Invalid G1M_ version.");
- if(head03 == 0) return error("Invalid G1M_.");
- if(head04 == 0) return error("Invalid G1M_.");
-
- // move to start
- bs.seek(head04);
- if(bs.fail()) return error("processG1M: Seek failure.");
-
- // read chunks
- for(uint32 i = 0; i < head06; i++)
- {
- // read first chunk
- uint32 chunkname = bs.BE_read_uint32(); // chunk name
- uint32 chunkvers = bs.BE_read_uint32(); // chunk version
- uint32 chunksize = bs.BE_read_uint32(); // chunk size
-
- // process chunk
- switch(chunkname) {
- case(0x47314D46) : { // G1MF
- bs.move(chunksize - 0x0C);
- break;
- }
- case(0x47314D53) : { // G1MS
- bs.move(chunksize - 0x0C);
- break;
- }
- case(0x47314D4D) : { // G1MM
- bs.move(chunksize - 0x0C);
- break;
- }
- case(0x47314D47) : { // G1MG
- if(!processG1MG0044(bs, smc)) return false;
- bs.move(chunksize - 0x0C);
- break;
- }
- case(0x45585452) : { // EXTR
- bs.move(chunksize - 0x0C);
- break;
- }
- default : {
- stringstream ss;
- ss << "processG1M: Unknown chunk 0x" << std::hex << chunkname << std::dec << ".";
- return error(ss.str().c_str());
- }
- }
- }
-
- return true;
- }
-
- bool extractor::processG1MG0044(const binary_stream& bs, SIMPLEMODELCONTAINER& smc)
- {
- using namespace std;
-
- // copy stream
- binary_stream stream(bs);
- if(stream.fail()) return error("Cannot copy binary stream.");
-
- // read header
- uint32 platform = stream.BE_read_uint32();
- uint32 unknown1 = stream.BE_read_uint32();
- real32 min_x = stream.BE_read_real32();
- real32 min_y = stream.BE_read_real32();
- real32 min_z = stream.BE_read_real32();
- real32 max_x = stream.BE_read_real32();
- real32 max_y = stream.BE_read_real32();
- real32 max_z = stream.BE_read_real32();
- uint32 sections = stream.BE_read_uint32();
-
- // validate header
- if(platform != 0x50533300) return error("Only PS3 version of game is supported.");
- if(sections == 0) return error("Invalid number of sections.");
-
- // section information
- struct G1MG0044_ITEM {
- uint32 type;
- uint32 size;
- boost::shared_array<char> data;
- };
-
- // read section information
- deque<G1MG0044_ITEM> items;
- for(size_t i = 0; i < sections; i++) {
- G1MG0044_ITEM item;
- item.type = stream.BE_read_uint32();
- item.size = stream.BE_read_uint32();
- item.data.reset(new char[item.size - 0x8]);
- stream.read(item.data.get(), item.size - 0x8);
- items.push_back(item);
- }
-
- // for each section
- for(size_t i = 0; i < items.size(); i++)
- {
- // vertex section
- if(items[i].type == 0x00010004)
- {
- // binary stream from data
- binary_stream ss(items[i].data, items[i].size - 0x8);
- ss.seek(0);
-
- // read vertex sections
- uint32 n_meshes = ss.BE_read_uint32();
- for(size_t j = 0; j < n_meshes; j++)
- {
- // read mesh vertex info
- uint32 unknown1 = ss.BE_read_uint32();
- uint32 vertsize = ss.BE_read_uint32();
- uint32 vertices = ss.BE_read_uint32();
- uint32 unknown2 = ss.BE_read_uint32();
-
- // buffer name
- stringstream name;
- name << "vb_" << setfill('0') << setw(2) << i;
-
- // set vertex buffer properties
- VTX_BUFFER vb;
- vb.flags = 0;
- vb.name = name.str();
- vb.elem = vertices;
- vb.data.reset(new VERTEX[vertices]);
-
- // set vertex buffer flags
- if(vertsize == 0x10) {
- vb.flags |= VERTEX_POSITION;
- vb.flags |= VERTEX_NORMAL;
- vb.flags |= VERTEX_UV;
- }
- else if(vertsize == 0x14) {
- vb.flags |= VERTEX_POSITION;
- vb.flags |= VERTEX_NORMAL;
- vb.flags |= VERTEX_UV;
- }
- else if(vertsize == 0x18) {
- vb.flags |= VERTEX_POSITION;
- vb.flags |= VERTEX_NORMAL;
- }
- else if(vertsize == 0x1C) {
- vb.flags |= VERTEX_POSITION;
- vb.flags |= VERTEX_NORMAL;
- vb.flags |= VERTEX_UV;
- }
- else if(vertsize == 0x20) {
- vb.flags |= VERTEX_POSITION;
- vb.flags |= VERTEX_NORMAL;
- vb.flags |= VERTEX_UV;
- }
- else if(vertsize == 0x24) {
- vb.flags |= VERTEX_POSITION;
- vb.flags |= VERTEX_NORMAL;
- vb.flags |= VERTEX_UV;
- }
- else
- return error("Unknown vertex format.");
-
- // read vertices
- for(size_t k = 0; k < vertices; k++)
- {
- VERTEX vertex;
- if(vertsize == 0x10) {
- vertex.vx = ss.BE_read_real16();
- vertex.vy = ss.BE_read_real16();
- vertex.vz = ss.BE_read_real16();
- ss.BE_read_real16();
- vertex.nx = ss.BE_read_real16();
- vertex.ny = ss.BE_read_real16();
- vertex.nz = ss.BE_read_real16();
- ss.BE_read_real16();
- }
- else if(vertsize == 0x14) {
- vertex.vx = ss.BE_read_real16();
- vertex.vy = ss.BE_read_real16();
- vertex.vz = ss.BE_read_real16();
- ss.BE_read_real16();
- vertex.nx = ss.BE_read_real16();
- vertex.ny = ss.BE_read_real16();
- vertex.nz = ss.BE_read_real16();
- ss.BE_read_real16();
- vertex.tu = ss.BE_read_real16();
- vertex.tv = ss.BE_read_real16();
- }
- else if(vertsize == 0x18) {
- vertex.vx = ss.BE_read_real32();
- vertex.vy = ss.BE_read_real32();
- vertex.vz = ss.BE_read_real32();
- vertex.nx = ss.BE_read_real16();
- vertex.ny = ss.BE_read_real16();
- vertex.nz = ss.BE_read_real16();
- ss.BE_read_real16();
- ss.BE_read_real32();
- }
- else if(vertsize == 0x1C) {
- vertex.vx = ss.BE_read_real32();
- vertex.vy = ss.BE_read_real32();
- vertex.vz = ss.BE_read_real32();
- vertex.nx = ss.BE_read_real16();
- vertex.ny = ss.BE_read_real16();
- vertex.nz = ss.BE_read_real16();
- ss.BE_read_real16();
- ss.BE_read_real32();
- vertex.tu = ss.BE_read_real16();
- vertex.tv = ss.BE_read_real16();
- }
- else if(vertsize == 0x20) {
- vertex.vx = ss.BE_read_real32();
- vertex.vy = ss.BE_read_real32();
- vertex.vz = ss.BE_read_real32();
- vertex.nx = ss.BE_read_real16();
- vertex.ny = ss.BE_read_real16();
- vertex.nz = ss.BE_read_real16();
- ss.BE_read_real16();
- ss.BE_read_real32();
- ss.BE_read_real16();
- ss.BE_read_real16();
- vertex.tu = ss.BE_read_real16();
- vertex.tv = ss.BE_read_real16();
- }
- else if(vertsize == 0x24) {
- vertex.vx = ss.BE_read_real32();
- vertex.vy = ss.BE_read_real32();
- vertex.vz = ss.BE_read_real32();
- vertex.nx = ss.BE_read_real32();
- vertex.ny = ss.BE_read_real32();
- vertex.nz = ss.BE_read_real32();
- ss.BE_read_real32();
- vertex.tu = ss.BE_read_real32();
- vertex.tv = ss.BE_read_real32();
- }
-
- // save vertex
- vb.data[k] = vertex;
- }
- }
- }
- // index buffer section
- else if(items[i].type == 0x00010007)
- {
- // binary stream from data
- binary_stream ss(items[i].data, items[i].size - 0x8);
- ss.seek(0);
-
- // read face sections
- uint32 n_meshes = ss.BE_read_uint32();
- uint32 vb_index = 0;
- for(size_t j = 0; j < n_meshes; j++)
- {
- // read face data
- uint32 numindex = ss.BE_read_uint32();
- uint32 datatype = ss.BE_read_uint32();
- uint32 unknown1 = ss.BE_read_uint32();
-
- // set index buffer properties
- IDX_BUFFER ib;
- ib.type = FACE_TYPE_TRISTRIP;
- ib.elem = numindex;
- if(datatype == 0x10) ib.format = FACE_FORMAT_UINT_16;
- else if(datatype == 0x20) ib.format = FACE_FORMAT_UINT_32;
- else return error("Unknown index buffer data format.");
-
- // set index buffer name
- stringstream surface;
- surface << "surface_" << setfill('0') << setw(3) << j << ends;
- ib.name = surface.str();
-
- // determine index buffer data type size
- unsigned int typesize = 0;
- if(datatype == 0x10) typesize = sizeof(uint16);
- else if(datatype == 0x20) typesize = sizeof(uint32);
- else return error("Unknown index buffer data type.");
-
- // read face data
- unsigned int total_bytes = ib.elem*typesize;
- ib.data.reset(new char[total_bytes]);
- if(ib.format == FACE_FORMAT_UINT_16) ss.BE_read_array(reinterpret_cast<uint16*>(ib.data.get()), ib.elem);
- else if(ib.format == FACE_FORMAT_UINT_32) ss.BE_read_array(reinterpret_cast<uint32*>(ib.data.get()), ib.elem);
-
- // test face data
- uint32 min_index = 0;
- uint32 max_index = 0;
- if(ib.format == FACE_FORMAT_UINT_16) {
- //uint16 a; minimum(reinterpret_cast<uint16*>(ib.data.get()), ib.elem, a);
- //uint16 b; maximum(reinterpret_cast<uint16*>(ib.data.get()), ib.elem, b);
- //min_index = a;
- //max_index = b;
- }
- else if(ib.format == FACE_FORMAT_UINT_32) {
- //uint32 a; minimum(reinterpret_cast<uint32*>(ib.data.get()), ib.elem, a);
- //uint32 b; maximum(reinterpret_cast<uint32*>(ib.data.get()), ib.elem, b);
- //min_index = a;
- //max_index = b;
- }
- cout << " min index = " << min_index << endl;
- cout << " max index = " << max_index << endl;
-
- // set vertex buffer reference
- //if(min_index == 0) vb_index++; // there has got to be a better way
- //if(vb_index > 0) ib.reference = vb_index - 1;
- //else return error("Unexpected vertex buffer reference.");
-
- // save face data
- //fdlist.push_back(ib);
- }
- }
- }
-
- return true;
- }
-
- bool extractor::extract(void)
- {
- using namespace std;
- debug = true;
-
- bool unpackA = false;
- bool unpackB = false;
- bool unpackC = false;
- bool doBin = true;
-
- cout << "STAGE 1" << endl;
- if(unpackA) {
- cout << "Unpacking .A files..." << endl;
- deque<string> filelist;
- BuildFilenameList(filelist, ".A", pathname.c_str());
- for(size_t i = 0; i < filelist.size(); i++) {
- cout << "Processing file " << (i + 1) << " of " << filelist.size() << ": " << filelist[i] << "." << endl;
- if(!unpack(filelist[i])) return false;
- }
- cout << endl;
- }
-
- cout << "STAGE 2" << endl;
- if(unpackB) {
- cout << "Unpacking .B files..." << endl;
- deque<string> filelist;
- BuildFilenameList(filelist, ".B", pathname.c_str());
- for(size_t i = 0; i < filelist.size(); i++) {
- cout << "Processing file " << (i + 1) << " of " << filelist.size() << ": " << filelist[i] << "." << endl;
- if(!unpack(filelist[i])) return false;
- }
- cout << endl;
- }
-
- cout << "STAGE 3" << endl;
- if(unpackC) {
- cout << "Unpacking .C files..." << endl;
- deque<string> filelist;
- BuildFilenameList(filelist, ".C", pathname.c_str());
- for(size_t i = 0; i < filelist.size(); i++) {
- cout << "Processing file " << (i + 1) << " of " << filelist.size() << ": " << filelist[i] << "." << endl;
- if(!unpack(filelist[i])) return false;
- }
- cout << endl;
- }
-
- cout << "STAGE 4" << endl;
- if(doBin) {
- cout << "Analyzing .bin files..." << endl;
- deque<string> filelist;
- BuildFilenameList(filelist, ".bin", pathname.c_str());
- for(size_t i = 0; i < filelist.size(); i++) {
- cout << "Processing file " << (i + 1) << " of " << filelist.size() << ": " << filelist[i] << "." << endl;
- if(!processBIN(filelist[i])) return false;
- }
- cout << endl;
- }
-
- return true;
- }
-
- };};
-
- namespace X_SYSTEM { namespace X_GAME {
-
- bool extract(void)
- {
- char pathname[MAX_PATH];
- GetModulePathname(pathname, MAX_PATH);
- return extract(pathname);
- }
-
- bool extract(const char* pathname)
- {
- return extractor(pathname).extract();
- }
-
- };};