home *** CD-ROM | disk | FTP | other *** search
- #include "xentax.h"
- #include "x_file.h"
- #include "x_afs.h"
-
- struct AFSITEM {
- uint32 offset;
- uint32 size;
- };
-
- bool ExtractAFS(const char* filename)
- {
- // extract filename information
- if(!filename || !strlen(filename)) return error("Invalid filename.");
- std::string fname = GetShortFilename(filename);
- std::string fname_noext = GetShortFilenameWithoutExtension(filename);
- std::string pname = GetPathnameFromFilename(filename);
-
- // open file
- std::ifstream ifile(filename, std::ios::binary);
- if(!ifile) return error("Failed to open file.");
-
- // read magic
- uint32 magic = LE_read_uint32(ifile);
- if(ifile.fail()) return error("Read failure.");
- if(magic != 0x00534641) return error("Expecting AFS.");
-
- // read header
- uint32 head01 = LE_read_uint32(ifile); // number of files
- uint32 head02 = LE_read_uint32(ifile); // 0x800
- uint32 head03 = LE_read_uint32(ifile); // start?
-
- // move to start
- ifile.seekg(0x10);
- if(ifile.fail()) return error("Seek failure.");
-
- // build list of AFS items
- std::deque<AFSITEM> itemlist;
- for(uint32 i = 0; i < head01; i++) {
- uint32 p1 = LE_read_uint32(ifile);
- uint32 p2 = LE_read_uint32(ifile);
- AFSITEM item = { p1, p2 };
- itemlist.push_back(item);
- }
-
- // filename data
- std::map<std::string, uint32> namemap;
- std::deque<std::string> filelist;
-
- // move to last AFS item
- ifile.seekg(itemlist.back().offset);
- if(ifile.fail()) return error("Seek failure.");
-
- // now let's try to read filenames
- for(uint32 i = 0; i < head01; i++)
- {
- // read filename
- char buffer[0x20];
- memset(buffer, 0, 0x20);
- ifile.read(&buffer[0], 0x20);
- std::cout << buffer << std::endl;
- LE_read_uint32(ifile);
- LE_read_uint16(ifile);
- LE_read_uint16(ifile);
- LE_read_uint16(ifile);
- LE_read_uint16(ifile);
- LE_read_uint16(ifile);
- LE_read_uint16(ifile);
-
- // save filename
- std::map<std::string, uint32>::iterator iter = namemap.find(buffer);
- if(iter == namemap.end()) {
- namemap.insert(std::map<std::string, uint32>::value_type(buffer, 0));
- filelist.push_back(buffer);
- }
- else {
- std::stringstream ss;
- ss << buffer << "." << std::setfill('0') << std::setw(3) << iter->second;
- filelist.push_back(ss.str());
- iter->second++;
- }
- }
-
- // create subdirectory
- std::stringstream savepath;
- savepath << pname << fname_noext << "\\";
- CreateDirectoryA(savepath.str().c_str(), NULL);
-
- // now let's try to save files
- for(uint32 i = 0; i < head01; i++)
- {
- // move to AFS item
- ifile.seekg(itemlist[i].offset);
- if(ifile.fail()) return error("Seek failure.");
-
- if(itemlist[i].size)
- {
- // create file
- std::stringstream ss;
- ss << savepath.str() << filelist[i];
- std::ofstream ofile(ss.str().c_str(), std::ios::binary);
- if(!ofile) return error("Failed to create output file.");
-
- std::cout << "Saving " << ss.str() << " at " << itemlist[i].size << " bytes." << std::endl;
-
- // read file
- boost::shared_array<char> data(new char[itemlist[i].size]);
- ifile.read(data.get(), itemlist[i].size);
- if(ifile.fail()) return error("Read failure.");
-
- // save file
- ofile.write(data.get(), itemlist[i].size);
- if(ofile.fail()) return error("Write failure.");
- }
- }
-
- return true;
- }