/* datapack specs & structure header: 0xFA script: 0xFB Uint32 scriptlength scriptdata files: 0xFC Uint16 amount_of_files amount_of_files[n] CStr filename Uint32 filelength filedata */ #include #include #include #include "DataPack.h" #include "Init.h" #include "FileIO.h" DataPack::DataPack(const char* _directory, const char* _filename) { filename = _filename; directory = _directory; datafile_size = 0; datafile = NULL; } DataPack::~DataPack(void) { if (datafile) { delete [] datafile; } } void DataPack::setDirectory(const char* _directory) { directory = _directory; } const char* DataPack::getDirectory(void) { return directory.c_str(); } void DataPack::setFilename(const char* _filename) { filename = _filename; } const char* DataPack::getFilename(void) { return filename.c_str(); } unsigned int DataPack::getDataFileSize(void) { return datafile_size; } exh::DataFile* DataPack::getDataFile(const char* datafilename) { for(unsigned int i = 0; i < datafile_size; i++) { if (!strcmp(datafile[i].filename, datafilename)) { return &datafile[i]; } } return NULL; } exh::DataFile* DataPack::getDataFile(unsigned int i) { return &datafile[i]; } int DataPack::readPack(void) { FileIO reader; if (reader.open(filename, std::ios::in | std::ios::binary)) { #ifdef __DEBUG fprintf(stdout, "Reading the datafile %s\n", getFilename()); #endif if (reader.readUChar() != 0xFA) { #ifdef __DEBUG fprintf( stderr, "Error reading datafile %s signature!\n", getFilename() ); #endif reader.close(); return -1; } while(!reader.isEnd()) { switch(reader.readUChar()) { case 0xFB: //script size reader.readUInt32(); break; case 0xFC: //amount of files datafile_size = reader.readUInt32(); datafile = new exh::DataFile[datafile_size]; for(unsigned int i = 0; i < datafile_size; i++) { const char *datafile_filename = reader.readCStr(); datafile[i].filename = new char[strlen(datafile_filename)+1]; strcpy(datafile[i].filename, datafile_filename); datafile[i].length = reader.readUInt32(); datafile[i].data = new char[datafile[i].length]; reader.readChar( datafile[i].data, datafile[i].length ); #ifdef __DEBUG fprintf( stdout, "\tReading %s (%d)\n", datafile[i].filename, datafile[i].length ); #endif } break; default: #ifdef __DEBUG fprintf( stderr, "Error reading datafile" \ " %s chunk information\n", getFilename() ); #endif reader.close(); return -1; } } reader.close(); return 1; } #ifdef __DEBUG fprintf( stderr, "Error: unable to open datafile %s%s!\n", getDirectory(), getFilename() ); #endif return -1; } //at least Wine 0.9.22 might fail mysteriously writing a working datapack //probably due to not reading some file properly (this case: bs_font.png) int DataPack::createPack(void) { init.readDirectoryContent(getDirectory()); FileIO writer; if (writer.open(filename, std::ios::out | std::ios::binary)) { fprintf(stdout, "Creating a datafile from %s directory\n", getDirectory()); //header fprintf(stdout, "\tWriting header chunk\n"); writer.writeUChar(0xFA); //script fprintf(stdout, "\tWriting script chunk\n"); writer.writeUChar(0xFB); writer.writeUInt32((Uint32)0x0); //script length //datafiles fprintf(stdout, "\tWriting file chunk\n"); writer.writeUChar(0xFC); writer.writeUInt32((Uint32)init.getFileListSize()); //amount of files for(unsigned int i = 0; i < init.getFileListSize(); i++) { FileIO reader(init.getDataFile(i).c_str()); unsigned int filesize = reader.getLength(); char* filedata = new char[filesize]; memcpy(filedata, reader.readFile(), filesize); reader.close(); writer.writeCStr(init.getDataFile(i).c_str()); writer.writeUInt32((Uint32)filesize); writer.writeFile(filedata, filesize); fprintf( stdout, "\t\t%d %s\n", filesize, init.getDataFile(i).c_str() ); delete [] filedata; } writer.close(); return 1; } fprintf(stderr, "Couldn't open %s for DataPack writing!\n", filename.c_str()); return -1; } //hexdump for datapack's structure debugging void DataPack::hexdumpPack(void) { FileIO reader(init.getFullPath(filename.c_str())); const char* dump = reader.readFile(); unsigned int filelength = reader.getLength(); reader.close(); printf("Hexdump of %s\n0x0000 : ", filename.c_str()); for(unsigned int i = 0, row = 0; i < filelength; i++) { printf("%02X ", (unsigned char)dump[i]); if ((i+2)%4 == 1) { printf(" "); } if ((i+2)%16 == 1) { printf("\n0x%04X : ", ++row); } } printf("\n"); delete [] dump; }