Merge with develop
This commit is contained in:
commit
f928fa8b5c
5 changed files with 112 additions and 588 deletions
|
@ -157,7 +157,7 @@ bool CCmdArgs::haveAdditionalArg() const
|
||||||
|
|
||||||
// they don't have any short or long name, but need a name in help
|
// they don't have any short or long name, but need a name in help
|
||||||
if (arg.shortName.empty() && arg.longName.empty() && !arg.helpName.empty() && arg.found)
|
if (arg.shortName.empty() && arg.longName.empty() && !arg.helpName.empty() && arg.found)
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -297,7 +297,7 @@ int main(int argc, char **argv)
|
||||||
" default : DXTC1 if 24 bits, DXTC5 if 32 bits."
|
" default : DXTC1 if 24 bits, DXTC5 if 32 bits."
|
||||||
);
|
);
|
||||||
args.addArg("m", "mipmap", "", "Create MipMap");
|
args.addArg("m", "mipmap", "", "Create MipMap");
|
||||||
args.addArg("r", "reduce", "FACTOR", "Reduce the bitmap size before compressing\n\t\t\tFACTOR is 0, 1, 2, 3, 4, 5, 6, 7 or 8");
|
args.addArg("r", "reduce", "FACTOR", "Reduce the bitmap size before compressing\n FACTOR is 0, 1, 2, 3, 4, 5, 6, 7 or 8");
|
||||||
args.addAdditionalArg("input", "PNG or TGA files to convert", false);
|
args.addAdditionalArg("input", "PNG or TGA files to convert", false);
|
||||||
|
|
||||||
if (!args.parse(argc, argv)) return 1;
|
if (!args.parse(argc, argv)) return 1;
|
||||||
|
|
|
@ -32,6 +32,8 @@
|
||||||
#include "nel/misc/path.h"
|
#include "nel/misc/path.h"
|
||||||
#include "nel/misc/algo.h"
|
#include "nel/misc/algo.h"
|
||||||
#include "nel/misc/common.h"
|
#include "nel/misc/common.h"
|
||||||
|
#include "nel/misc/big_file.h"
|
||||||
|
#include "nel/misc/cmd_args.h"
|
||||||
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
@ -49,7 +51,7 @@ std::vector<CWildCard> WildCards;
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
bool keepFile (const char *fileName)
|
bool keepFile (const std::string &fileName)
|
||||||
{
|
{
|
||||||
uint i;
|
uint i;
|
||||||
bool ifPresent = false;
|
bool ifPresent = false;
|
||||||
|
@ -60,13 +62,13 @@ bool keepFile (const char *fileName)
|
||||||
if (WildCards[i].Not)
|
if (WildCards[i].Not)
|
||||||
{
|
{
|
||||||
// One ifnot condition met and the file is not added
|
// One ifnot condition met and the file is not added
|
||||||
if (testWildCard(file.c_str(), WildCards[i].Expression.c_str()))
|
if (testWildCard(file, WildCards[i].Expression))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ifPresent = true;
|
ifPresent = true;
|
||||||
ifTrue |= testWildCard(file.c_str(), WildCards[i].Expression.c_str());
|
ifTrue |= testWildCard(file, WildCards[i].Expression);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,199 +77,7 @@ bool keepFile (const char *fileName)
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
struct BNPFile
|
NLMISC::CBigFile::BNP gBNPHeader;
|
||||||
{
|
|
||||||
string Name;
|
|
||||||
uint32 Size;
|
|
||||||
uint32 Pos;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct BNPHeader
|
|
||||||
{
|
|
||||||
vector<BNPFile> Files;
|
|
||||||
uint32 OffsetFromBeginning;
|
|
||||||
|
|
||||||
// Append the header to the big file
|
|
||||||
bool append (const string &filename)
|
|
||||||
{
|
|
||||||
FILE *f = fopen (filename.c_str(), "ab");
|
|
||||||
if (f == NULL) return false;
|
|
||||||
|
|
||||||
uint32 nNbFile = (uint32)Files.size();
|
|
||||||
|
|
||||||
// value to be serialized
|
|
||||||
uint32 nNbFile2 = nNbFile;
|
|
||||||
|
|
||||||
#ifdef NL_BIG_ENDIAN
|
|
||||||
NLMISC_BSWAP32(nNbFile2);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (fwrite (&nNbFile2, sizeof(uint32), 1, f) != 1)
|
|
||||||
{
|
|
||||||
fclose(f);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint32 i = 0; i < nNbFile; ++i)
|
|
||||||
{
|
|
||||||
uint8 nStringSize = (uint8)Files[i].Name.size();
|
|
||||||
if (fwrite (&nStringSize, 1, 1, f) != 1)
|
|
||||||
{
|
|
||||||
fclose(f);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fwrite (Files[i].Name.c_str(), 1, nStringSize, f) != nStringSize)
|
|
||||||
{
|
|
||||||
fclose(f);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32 nFileSize = Files[i].Size;
|
|
||||||
|
|
||||||
#ifdef NL_BIG_ENDIAN
|
|
||||||
NLMISC_BSWAP32(nFileSize);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (fwrite (&nFileSize, sizeof(uint32), 1, f) != 1)
|
|
||||||
{
|
|
||||||
fclose(f);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32 nFilePos = Files[i].Pos;
|
|
||||||
|
|
||||||
#ifdef NL_BIG_ENDIAN
|
|
||||||
NLMISC_BSWAP32(nFilePos);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (fwrite (&nFilePos, sizeof(uint32), 1, f) != 1)
|
|
||||||
{
|
|
||||||
fclose(f);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32 nOffsetFromBeginning = OffsetFromBeginning;
|
|
||||||
|
|
||||||
#ifdef NL_BIG_ENDIAN
|
|
||||||
NLMISC_BSWAP32(nOffsetFromBeginning);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (fwrite (&nOffsetFromBeginning, sizeof(uint32), 1, f) != 1)
|
|
||||||
{
|
|
||||||
fclose(f);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose (f);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read the header from a big file
|
|
||||||
bool read (const string &filename)
|
|
||||||
{
|
|
||||||
FILE *f = fopen (filename.c_str(), "rb");
|
|
||||||
if (f == NULL) return false;
|
|
||||||
|
|
||||||
nlfseek64 (f, 0, SEEK_END);
|
|
||||||
uint32 nFileSize=CFile::getFileSize (filename);
|
|
||||||
nlfseek64 (f, nFileSize-sizeof(uint32), SEEK_SET);
|
|
||||||
|
|
||||||
uint32 nOffsetFromBeginning;
|
|
||||||
if (fread (&nOffsetFromBeginning, sizeof(uint32), 1, f) != 1)
|
|
||||||
{
|
|
||||||
fclose (f);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef NL_BIG_ENDIAN
|
|
||||||
NLMISC_BSWAP32(nOffsetFromBeginning);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (nlfseek64 (f, nOffsetFromBeginning, SEEK_SET) != 0)
|
|
||||||
{
|
|
||||||
fclose (f);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32 nNbFile;
|
|
||||||
if (fread (&nNbFile, sizeof(uint32), 1, f) != 1)
|
|
||||||
{
|
|
||||||
fclose (f);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef NL_BIG_ENDIAN
|
|
||||||
NLMISC_BSWAP32(nNbFile);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (uint32 i = 0; i < nNbFile; ++i)
|
|
||||||
{
|
|
||||||
uint8 nStringSize;
|
|
||||||
char sName[256];
|
|
||||||
if (fread (&nStringSize, 1, 1, f) != 1)
|
|
||||||
{
|
|
||||||
fclose (f);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (fread (sName, 1, nStringSize, f) != nStringSize)
|
|
||||||
{
|
|
||||||
fclose (f);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
sName[nStringSize] = 0;
|
|
||||||
BNPFile tmpBNPFile;
|
|
||||||
tmpBNPFile.Name = sName;
|
|
||||||
if (fread (&tmpBNPFile.Size, sizeof(uint32), 1, f) != 1)
|
|
||||||
{
|
|
||||||
fclose (f);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef NL_BIG_ENDIAN
|
|
||||||
NLMISC_BSWAP32(tmpBNPFile.Size);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (fread (&tmpBNPFile.Pos, sizeof(uint32), 1, f) != 1)
|
|
||||||
{
|
|
||||||
fclose (f);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef NL_BIG_ENDIAN
|
|
||||||
NLMISC_BSWAP32(tmpBNPFile.Pos);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Files.push_back (tmpBNPFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose (f);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
string gDestBNPFile;
|
|
||||||
BNPHeader gBNPHeader;
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
void append(const string &filename1, const string &filename2, uint32 sizeToRead)
|
|
||||||
{
|
|
||||||
FILE *f1 = fopen(filename1.c_str(), "ab");
|
|
||||||
FILE *f2 = fopen(filename2.c_str(), "rb");
|
|
||||||
if (f1 == NULL) return;
|
|
||||||
if (f2 == NULL) { fclose(f1); return; }
|
|
||||||
|
|
||||||
uint8 *ptr = new uint8[sizeToRead];
|
|
||||||
if (fread (ptr, sizeToRead, 1, f2) != 1)
|
|
||||||
nlwarning("%s read error", filename2.c_str());
|
|
||||||
if (fwrite (ptr, sizeToRead, 1, f1) != 1)
|
|
||||||
nlwarning("%s write error", filename1.c_str());
|
|
||||||
delete [] ptr;
|
|
||||||
|
|
||||||
fclose(f2);
|
|
||||||
fclose(f1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
bool i_comp(const string &s0, const string &s1)
|
bool i_comp(const string &s0, const string &s1)
|
||||||
|
@ -275,35 +85,24 @@ bool i_comp(const string &s0, const string &s1)
|
||||||
return nlstricmp (CFile::getFilename(s0).c_str(), CFile::getFilename(s1).c_str()) < 0;
|
return nlstricmp (CFile::getFilename(s0).c_str(), CFile::getFilename(s1).c_str()) < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void packSubRecurse ()
|
void packSubRecurse(const std::string &srcDirectory)
|
||||||
{
|
{
|
||||||
vector<string> pathContent;
|
vector<string> pathContent;
|
||||||
|
|
||||||
string cp = CPath::getCurrentPath();
|
printf ("Treating directory: %s\n", srcDirectory.c_str());
|
||||||
printf ("Treating directory : %s\n", cp.c_str());
|
CPath::getPathContent(srcDirectory, true, false, true, pathContent);
|
||||||
CPath::getPathContent(cp, true, false, true, pathContent);
|
|
||||||
|
// TODO: remove duplicate files
|
||||||
|
|
||||||
// Sort filename
|
// Sort filename
|
||||||
sort (pathContent.begin(), pathContent.end(), i_comp);
|
sort (pathContent.begin(), pathContent.end(), i_comp);
|
||||||
|
|
||||||
uint i;
|
for (uint i=0; i<pathContent.size(); ++i)
|
||||||
for (i=0; i<pathContent.size(); i++)
|
|
||||||
{
|
{
|
||||||
if (keepFile (pathContent[i].c_str()))
|
if (keepFile(pathContent[i]))
|
||||||
{
|
{
|
||||||
BNPFile ftmp;
|
if (gBNPHeader.appendFile(pathContent[i]))
|
||||||
|
|
||||||
// Check if we can read the source file
|
|
||||||
FILE *f = fopen (pathContent[i].c_str(), "rb");
|
|
||||||
if (f != NULL)
|
|
||||||
{
|
{
|
||||||
fclose (f);
|
|
||||||
ftmp.Name = CFile::getFilename(pathContent[i]);
|
|
||||||
ftmp.Size = CFile::getFileSize(pathContent[i]);
|
|
||||||
ftmp.Pos = gBNPHeader.OffsetFromBeginning;
|
|
||||||
gBNPHeader.Files.push_back(ftmp);
|
|
||||||
gBNPHeader.OffsetFromBeginning += ftmp.Size;
|
|
||||||
append(gDestBNPFile, pathContent[i].c_str(), ftmp.Size);
|
|
||||||
printf("adding %s\n", pathContent[i].c_str());
|
printf("adding %s\n", pathContent[i].c_str());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -315,261 +114,115 @@ void packSubRecurse ()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
void unpack (const string &dirName)
|
int main(int argc, char **argv)
|
||||||
{
|
|
||||||
FILE *bnp = fopen (gDestBNPFile.c_str(), "rb");
|
|
||||||
FILE *out;
|
|
||||||
if (bnp == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (uint32 i = 0; i < gBNPHeader.Files.size(); ++i)
|
|
||||||
{
|
|
||||||
BNPFile &rBNPFile = gBNPHeader.Files[i];
|
|
||||||
string filename = dirName + "/" + rBNPFile.Name;
|
|
||||||
out = fopen (filename.c_str(), "wb");
|
|
||||||
if (out != NULL)
|
|
||||||
{
|
|
||||||
nlfseek64 (bnp, rBNPFile.Pos, SEEK_SET);
|
|
||||||
uint8 *ptr = new uint8[rBNPFile.Size];
|
|
||||||
if (fread (ptr, rBNPFile.Size, 1, bnp) != 1)
|
|
||||||
nlwarning("%s read error", filename.c_str());
|
|
||||||
if (fwrite (ptr, rBNPFile.Size, 1, out) != 1)
|
|
||||||
nlwarning("%s write error", filename.c_str());
|
|
||||||
fclose (out);
|
|
||||||
delete [] ptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fclose (bnp);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
void usage()
|
|
||||||
{
|
|
||||||
printf ("USAGE : \n");
|
|
||||||
printf (" bnp_make /p <directory_name> [<destination_path>] [<destination_filename>] [option] ... [option]\n");
|
|
||||||
printf (" option : \n");
|
|
||||||
printf (" -if wildcard : add the file if it matches the wilcard (at least one 'if' conditions must be met for a file to be adding)\n");
|
|
||||||
printf (" -ifnot wildcard : add the file if it doesn't match the wilcard (all the 'ifnot' conditions must be met for a file to be adding)\n");
|
|
||||||
printf (" Pack the directory to a bnp file\n");
|
|
||||||
printf (" bnp_make /u <bnp_file>\n");
|
|
||||||
printf (" Unpack the bnp file to a directory\n");
|
|
||||||
printf (" bnp_make /l <bnp_file>\n");
|
|
||||||
printf (" List the files contained in the bnp file\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
uint readOptions (int nNbArg, char **ppArgs)
|
|
||||||
{
|
|
||||||
uint i;
|
|
||||||
uint optionCount = 0;
|
|
||||||
for (i=0; i<(uint)nNbArg; i++)
|
|
||||||
{
|
|
||||||
// If ?
|
|
||||||
if ((strcmp (ppArgs[i], "-if") == 0) && ((i+1)<(uint)nNbArg))
|
|
||||||
{
|
|
||||||
CWildCard card;
|
|
||||||
card.Expression = toLower(string(ppArgs[i+1]));
|
|
||||||
card.Not = false;
|
|
||||||
WildCards.push_back (card);
|
|
||||||
optionCount += 2;
|
|
||||||
}
|
|
||||||
// If not ?
|
|
||||||
if ((strcmp (ppArgs[i], "-ifnot") == 0) && ((i+1)<(uint)nNbArg))
|
|
||||||
{
|
|
||||||
CWildCard card;
|
|
||||||
card.Expression = toLower(string(ppArgs[i+1]));
|
|
||||||
card.Not = true;
|
|
||||||
WildCards.push_back (card);
|
|
||||||
optionCount += 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return optionCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
int main (int nNbArg, char **ppArgs)
|
|
||||||
{
|
{
|
||||||
NLMISC::CApplicationContext myApplicationContext;
|
NLMISC::CApplicationContext myApplicationContext;
|
||||||
|
|
||||||
if (nNbArg < 3)
|
NLMISC::CCmdArgs args;
|
||||||
|
|
||||||
|
args.addArg("p", "pack", "", "Pack the directory to a BNP file");
|
||||||
|
args.addArg("u", "unpack", "", "Unpack the BNP file to a directory");
|
||||||
|
args.addArg("l", "list", "", "List the files contained in the BNP file");
|
||||||
|
args.addArg("o", "output", "destination", "Output directory or file");
|
||||||
|
args.addArg("i", "if", "wildcard", "Add the file if it matches the wilcard (at least one 'if' conditions must be met for a file to be adding)");
|
||||||
|
args.addArg("n", "ifnot", "wildcard", "Add the file if it doesn't match the wilcard (all the 'ifnot' conditions must be met for a file to be adding)");
|
||||||
|
args.addAdditionalArg("input", "Input directory or BNP file depending on command");
|
||||||
|
|
||||||
|
if (!args.parse(argc, argv)) return 1;
|
||||||
|
|
||||||
|
if (args.haveArg("p"))
|
||||||
{
|
{
|
||||||
usage();
|
std::vector<std::string> filters;
|
||||||
return -1;
|
|
||||||
}
|
// If ?
|
||||||
|
filters = args.getLongArg("if");
|
||||||
|
|
||||||
if ((strcmp(ppArgs[1], "/p") == 0) || (strcmp(ppArgs[1], "/P") == 0) ||
|
for (uint i = 0; i < filters.size(); ++i)
|
||||||
(strcmp(ppArgs[1], "-p") == 0) || (strcmp(ppArgs[1], "-P") == 0))
|
|
||||||
{
|
|
||||||
// Pack a directory
|
|
||||||
uint count = readOptions (nNbArg, ppArgs);
|
|
||||||
nNbArg -= count;
|
|
||||||
|
|
||||||
// Read options
|
|
||||||
|
|
||||||
string sCurDir;
|
|
||||||
|
|
||||||
if (nNbArg >= 4)
|
|
||||||
{
|
{
|
||||||
// store current path
|
CWildCard card;
|
||||||
sCurDir = CPath::getCurrentPath();
|
card.Expression = toLower(filters[i]);
|
||||||
|
card.Not = false;
|
||||||
|
WildCards.push_back(card);
|
||||||
|
}
|
||||||
|
|
||||||
// go to the dest path
|
// If not ?
|
||||||
string sDestDir;
|
filters = args.getLongArg("ifnot");
|
||||||
if (CPath::setCurrentPath(ppArgs[3]))
|
|
||||||
|
for (uint i = 0; i < filters.size(); ++i)
|
||||||
|
{
|
||||||
|
CWildCard card;
|
||||||
|
card.Expression = toLower(filters[i]);
|
||||||
|
card.Not = true;
|
||||||
|
WildCards.push_back(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pack a directory
|
||||||
|
std::string srcDirectory = args.getAdditionalArg("input").front();
|
||||||
|
|
||||||
|
if (!CFile::isDirectory(srcDirectory) || !CFile::isExists(srcDirectory))
|
||||||
|
{
|
||||||
|
nlwarning("Error: %s doesn't exist or is not a directory!", srcDirectory.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Output directory or filename
|
||||||
|
if (args.haveArg("o"))
|
||||||
|
{
|
||||||
|
gBNPHeader.BigFileName = args.getArg("o").front();
|
||||||
|
|
||||||
|
if (CFile::isDirectory(gBNPHeader.BigFileName))
|
||||||
{
|
{
|
||||||
sDestDir = CPath::getCurrentPath();
|
gBNPHeader.BigFileName = CPath::standardizePath(gBNPHeader.BigFileName) + CFile::getFilename(srcDirectory);
|
||||||
|
|
||||||
bool tmp = CPath::setCurrentPath(sCurDir.c_str());
|
|
||||||
// restore current path, should not failed
|
|
||||||
nlassert (tmp); // removed in release
|
|
||||||
|
|
||||||
// go to the source dir
|
|
||||||
if (CPath::setCurrentPath(ppArgs[2]))
|
|
||||||
{
|
|
||||||
sCurDir = CPath::getCurrentPath();
|
|
||||||
|
|
||||||
gDestBNPFile = CPath::standardizePath(sDestDir);
|
|
||||||
|
|
||||||
if(nNbArg == 5)
|
|
||||||
{
|
|
||||||
gDestBNPFile += ppArgs[4];
|
|
||||||
// add ext if necessary
|
|
||||||
if (string(ppArgs[4]).find(".") == string::npos)
|
|
||||||
gDestBNPFile += string(".bnp");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const char *pos = strrchr (sCurDir.c_str(), '/');
|
|
||||||
if (pos != NULL)
|
|
||||||
{
|
|
||||||
gDestBNPFile += string(pos+1);
|
|
||||||
}
|
|
||||||
// get the dest file name
|
|
||||||
gDestBNPFile += string(".bnp");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
nlwarning ("ERROR (bnp_make) : can't set current directory to %s", ppArgs[2]);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
nlwarning ("ERROR (bnp_make) : can't set current directory to %s", ppArgs[3]);
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (chdir (ppArgs[2]) == -1)
|
gBNPHeader.BigFileName = CFile::getFilename(srcDirectory);
|
||||||
{
|
|
||||||
nlwarning ("ERROR (bnp_make) : can't set current directory to %s", ppArgs[2]);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
//getcwd (sCurDir, MAX_PATH);
|
|
||||||
gDestBNPFile = CPath::getCurrentPath() + string(".bnp");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
remove (gDestBNPFile.c_str());
|
if (CFile::getExtension(gBNPHeader.BigFileName) != "bnp")
|
||||||
gBNPHeader.OffsetFromBeginning = 0;
|
gBNPHeader.BigFileName += ".bnp";
|
||||||
packSubRecurse();
|
|
||||||
gBNPHeader.append (gDestBNPFile);
|
CFile::deleteFile(gBNPHeader.BigFileName);
|
||||||
return 0;
|
|
||||||
|
packSubRecurse(srcDirectory);
|
||||||
|
return gBNPHeader.appendHeader() ? 0:-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((strcmp(ppArgs[1], "/u") == 0) || (strcmp(ppArgs[1], "/U") == 0) ||
|
if (args.haveArg("u"))
|
||||||
(strcmp(ppArgs[1], "-u") == 0) || (strcmp(ppArgs[1], "-U") == 0))
|
|
||||||
{
|
{
|
||||||
string::size_type i;
|
gBNPHeader.BigFileName = args.getAdditionalArg("input").front();
|
||||||
string path;
|
|
||||||
gDestBNPFile = ppArgs[2];
|
|
||||||
if ((gDestBNPFile.rfind('/') != string::npos) || (gDestBNPFile.rfind('/') != string::npos))
|
|
||||||
{
|
|
||||||
string::size_type pos = gDestBNPFile.rfind('/');
|
|
||||||
if (pos == string::npos)
|
|
||||||
pos = gDestBNPFile.rfind('/');
|
|
||||||
for (i = 0; i <= pos; ++i)
|
|
||||||
path += gDestBNPFile[i];
|
|
||||||
string wholeName = gDestBNPFile;
|
|
||||||
gDestBNPFile = "";
|
|
||||||
for (; i < wholeName.size(); ++i)
|
|
||||||
gDestBNPFile += wholeName[i];
|
|
||||||
if (CPath::setCurrentPath(path.c_str()))
|
|
||||||
{
|
|
||||||
path = CPath::getCurrentPath();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
nlwarning ("ERROR (bnp_make) : can't set current directory to %s", path.c_str());
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (stricmp (gDestBNPFile.c_str()+gDestBNPFile.size()-4, ".bnp") != 0)
|
|
||||||
{
|
|
||||||
gDestBNPFile += ".bnp";
|
|
||||||
}
|
|
||||||
string dirName;
|
|
||||||
for (i = 0; i < gDestBNPFile.size()-4; ++i)
|
|
||||||
dirName += gDestBNPFile[i];
|
|
||||||
// Unpack a bnp file
|
|
||||||
if (!gBNPHeader.read (gDestBNPFile))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
//mkdir (dirName.c_str());
|
std::string dirName;
|
||||||
CFile::createDirectory(dirName);
|
|
||||||
|
|
||||||
unpack (dirName);
|
// Output directory or filename
|
||||||
|
if (args.haveArg("o"))
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((strcmp(ppArgs[1], "/l") == 0) || (strcmp(ppArgs[1], "/L") == 0) ||
|
|
||||||
(strcmp(ppArgs[1], "-l") == 0) || (strcmp(ppArgs[1], "-L") == 0))
|
|
||||||
{
|
|
||||||
string::size_type i;
|
|
||||||
string path;
|
|
||||||
gDestBNPFile = ppArgs[2];
|
|
||||||
if ((gDestBNPFile.rfind('/') != string::npos) || (gDestBNPFile.rfind('/') != string::npos))
|
|
||||||
{
|
{
|
||||||
string::size_type pos = gDestBNPFile.rfind('/');
|
dirName = args.getArg("o").front();
|
||||||
if (pos == string::npos)
|
|
||||||
pos = gDestBNPFile.rfind('/');
|
|
||||||
for (i = 0; i <= pos; ++i)
|
|
||||||
path += gDestBNPFile[i];
|
|
||||||
string wholeName = gDestBNPFile;
|
|
||||||
gDestBNPFile = "";
|
|
||||||
for (; i < wholeName.size(); ++i)
|
|
||||||
gDestBNPFile += wholeName[i];
|
|
||||||
if (CPath::setCurrentPath(path.c_str()))
|
|
||||||
{
|
|
||||||
path = CPath::getCurrentPath();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
nlwarning ("ERROR (bnp_make) : can't set current directory to %s", path.c_str());
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (stricmp (gDestBNPFile.c_str()+gDestBNPFile.size()-4, ".bnp") != 0)
|
else
|
||||||
{
|
{
|
||||||
gDestBNPFile += ".bnp";
|
dirName = CFile::getFilenameWithoutExtension(gBNPHeader.BigFileName);
|
||||||
}
|
}
|
||||||
string dirName;
|
|
||||||
for (i = 0; i < gDestBNPFile.size()-4; ++i)
|
|
||||||
dirName += gDestBNPFile[i];
|
|
||||||
|
|
||||||
// Unpack a bnp file
|
// Unpack a bnp file
|
||||||
if (!gBNPHeader.read (gDestBNPFile))
|
return gBNPHeader.unpack(dirName) ? 0:-1;
|
||||||
return -1;
|
}
|
||||||
|
|
||||||
for (i = 0; i < gBNPHeader.Files.size(); ++i)
|
if (args.haveArg("l"))
|
||||||
printf ("%s\n", gBNPHeader.Files[i].Name.c_str());
|
{
|
||||||
|
gBNPHeader.BigFileName = args.getAdditionalArg("input").front();
|
||||||
|
|
||||||
|
// Read header of BNP file
|
||||||
|
if (!gBNPHeader.readHeader()) return -1;
|
||||||
|
|
||||||
|
for (uint i = 0; i < gBNPHeader.SFiles.size(); ++i)
|
||||||
|
{
|
||||||
|
printf("%s\n", gBNPHeader.SFiles[i].Name.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
usage ();
|
args.displayHelp();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1745,92 +1745,6 @@ void CPatchManager::getPatchFromDesc(SFileToPatch &ftpOut, const CBNPFile &fIn,
|
||||||
} // end of else local BNP file exists
|
} // end of else local BNP file exists
|
||||||
}
|
}
|
||||||
|
|
||||||
// ****************************************************************************
|
|
||||||
bool CPatchManager::readBNPHeader(const string &SourceName, vector<SBNPFile> &Files)
|
|
||||||
{
|
|
||||||
/* *****
|
|
||||||
If the BNP Header format change, please modify 'EmptyBnpFileSize' as needed
|
|
||||||
***** */
|
|
||||||
FILE *f = fopen (SourceName.c_str(), "rb");
|
|
||||||
if (f == NULL) return false;
|
|
||||||
|
|
||||||
nlfseek64 (f, 0, SEEK_END);
|
|
||||||
uint32 nFileSize = NLMISC::CFile::getFileSize (SourceName);
|
|
||||||
nlfseek64 (f, nFileSize-sizeof(uint32), SEEK_SET);
|
|
||||||
|
|
||||||
uint32 nOffsetFromBeginning;
|
|
||||||
if (fread (&nOffsetFromBeginning, sizeof(uint32), 1, f) != 1)
|
|
||||||
{
|
|
||||||
fclose(f);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef NL_BIG_ENDIAN
|
|
||||||
NLMISC_BSWAP32(nOffsetFromBeginning);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (nlfseek64 (f, nOffsetFromBeginning, SEEK_SET) != 0)
|
|
||||||
{
|
|
||||||
fclose(f);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32 nNbFile;
|
|
||||||
if (fread (&nNbFile, sizeof(uint32), 1, f) != 1)
|
|
||||||
{
|
|
||||||
fclose(f);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef NL_BIG_ENDIAN
|
|
||||||
NLMISC_BSWAP32(nNbFile);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (uint32 i = 0; i < nNbFile; ++i)
|
|
||||||
{
|
|
||||||
uint8 nStringSize;
|
|
||||||
if (fread (&nStringSize, 1, 1, f) != 1)
|
|
||||||
{
|
|
||||||
fclose(f);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
char sName[256];
|
|
||||||
if (fread (sName, 1, nStringSize, f) != nStringSize)
|
|
||||||
{
|
|
||||||
fclose(f);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
sName[nStringSize] = 0;
|
|
||||||
|
|
||||||
SBNPFile tmpBNPFile;
|
|
||||||
tmpBNPFile.Name = sName;
|
|
||||||
if (fread (&tmpBNPFile.Size, sizeof(uint32), 1, f) != 1)
|
|
||||||
{
|
|
||||||
fclose(f);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef NL_BIG_ENDIAN
|
|
||||||
NLMISC_BSWAP32(tmpBNPFile.Size);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (fread (&tmpBNPFile.Pos, sizeof(uint32), 1, f) != 1)
|
|
||||||
{
|
|
||||||
fclose(f);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef NL_BIG_ENDIAN
|
|
||||||
NLMISC_BSWAP32(tmpBNPFile.Pos);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Files.push_back (tmpBNPFile);
|
|
||||||
}
|
|
||||||
fclose (f);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ****************************************************************************
|
// ****************************************************************************
|
||||||
bool CPatchManager::bnpUnpack(const string &srcBigfile, const string &dstPath, vector<string> &vFilenames)
|
bool CPatchManager::bnpUnpack(const string &srcBigfile, const string &dstPath, vector<string> &vFilenames)
|
||||||
{
|
{
|
||||||
|
@ -1856,8 +1770,10 @@ bool CPatchManager::bnpUnpack(const string &srcBigfile, const string &dstPath, v
|
||||||
setState(true,s);
|
setState(true,s);
|
||||||
|
|
||||||
// Read Header of the BNP File
|
// Read Header of the BNP File
|
||||||
vector<CPatchManager::SBNPFile> Files;
|
CBigFile::BNP bnpFile;
|
||||||
if (!readBNPHeader(SourceName, Files))
|
bnpFile.BigFileName = SourceName;
|
||||||
|
|
||||||
|
if (!bnpFile.readHeader())
|
||||||
{
|
{
|
||||||
ucstring s = CI18N::get("uiUnpackErrHead") + " " + SourceName;
|
ucstring s = CI18N::get("uiUnpackErrHead") + " " + SourceName;
|
||||||
setState(true,s);
|
setState(true,s);
|
||||||
|
@ -1865,54 +1781,14 @@ bool CPatchManager::bnpUnpack(const string &srcBigfile, const string &dstPath, v
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unpack
|
// Unpack
|
||||||
{
|
if (!bnpFile.unpack(DestPath))
|
||||||
FILE *bnp = fopen (SourceName.c_str(), "rb");
|
return false;
|
||||||
FILE *out;
|
|
||||||
if (bnp == NULL)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
for (uint32 i = 0; i < Files.size(); ++i)
|
|
||||||
{
|
|
||||||
CPatchManager::SBNPFile &rBNPFile = Files[i];
|
|
||||||
string filename = DestPath + rBNPFile.Name;
|
|
||||||
out = fopen (filename.c_str(), "wb");
|
|
||||||
if (out != NULL)
|
|
||||||
{
|
|
||||||
nlfseek64 (bnp, rBNPFile.Pos, SEEK_SET);
|
|
||||||
uint8 *ptr = new uint8[rBNPFile.Size];
|
|
||||||
|
|
||||||
if (fread (ptr, rBNPFile.Size, 1, bnp) != 1)
|
|
||||||
{
|
|
||||||
fclose(out);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool writeError = fwrite (ptr, rBNPFile.Size, 1, out) != 1;
|
|
||||||
if (writeError)
|
|
||||||
{
|
|
||||||
nlwarning("errno = %d", errno);
|
|
||||||
}
|
|
||||||
bool diskFull = ferror(out) && errno == 28 /* ENOSPC*/;
|
|
||||||
fclose (out);
|
|
||||||
delete [] ptr;
|
|
||||||
if (diskFull)
|
|
||||||
{
|
|
||||||
throw NLMISC::EDiskFullError(filename);
|
|
||||||
}
|
|
||||||
if (writeError)
|
|
||||||
{
|
|
||||||
throw NLMISC::EWriteError(filename);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fclose (bnp);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return names
|
// Return names
|
||||||
{
|
{
|
||||||
vFilenames.clear();
|
vFilenames.clear();
|
||||||
for (uint32 i = 0; i < Files.size(); ++i)
|
for (uint32 i = 0; i < bnpFile.SFiles.size(); ++i)
|
||||||
vFilenames.push_back(Files[i].Name);
|
vFilenames.push_back(bnpFile.SFiles[i].Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -2332,16 +2208,18 @@ void CCheckThread::run ()
|
||||||
|
|
||||||
sTranslate = CI18N::get("uiCheckInBNP") + " " + rCat.getFile(j);
|
sTranslate = CI18N::get("uiCheckInBNP") + " " + rCat.getFile(j);
|
||||||
pPM->setState(true, sTranslate);
|
pPM->setState(true, sTranslate);
|
||||||
vector<CPatchManager::SBNPFile> vFiles;
|
CBigFile::BNP bnpFile;
|
||||||
if (pPM->readBNPHeader(sBNPFilename, vFiles))
|
bnpFile.BigFileName = sBNPFilename;
|
||||||
|
|
||||||
|
if (bnpFile.readHeader())
|
||||||
{
|
{
|
||||||
// read the file inside the bnp and calculate the sha1
|
// read the file inside the bnp and calculate the sha1
|
||||||
FILE *bnp = fopen (sBNPFilename.c_str(), "rb");
|
FILE *bnp = fopen (sBNPFilename.c_str(), "rb");
|
||||||
if (bnp != NULL)
|
if (bnp != NULL)
|
||||||
{
|
{
|
||||||
for (uint32 k = 0; k < vFiles.size(); ++k)
|
for (uint32 k = 0; k < bnpFile.SFiles.size(); ++k)
|
||||||
{
|
{
|
||||||
CPatchManager::SBNPFile &rBNPFile = vFiles[k];
|
const CBigFile::SBNPFile &rBNPFile = bnpFile.SFiles[k];
|
||||||
// Is the real file exists ?
|
// Is the real file exists ?
|
||||||
string sRealFilename = rCat.getUnpackTo() + rBNPFile.Name;
|
string sRealFilename = rCat.getUnpackTo() + rBNPFile.Name;
|
||||||
if (NLMISC::CFile::fileExists(sRealFilename))
|
if (NLMISC::CFile::fileExists(sRealFilename))
|
||||||
|
|
|
@ -102,13 +102,6 @@ public:
|
||||||
uint32 SZFileSize; // Size of the SZ file
|
uint32 SZFileSize; // Size of the SZ file
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SBNPFile
|
|
||||||
{
|
|
||||||
std::string Name;
|
|
||||||
uint32 Size;
|
|
||||||
uint32 Pos;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SPatchInfo
|
struct SPatchInfo
|
||||||
{
|
{
|
||||||
struct SCat
|
struct SCat
|
||||||
|
@ -326,7 +319,6 @@ private:
|
||||||
|
|
||||||
void getPatchFromDesc(SFileToPatch &ftpOut, const CBNPFile &fIn, bool forceCheckSumTest);
|
void getPatchFromDesc(SFileToPatch &ftpOut, const CBNPFile &fIn, bool forceCheckSumTest);
|
||||||
|
|
||||||
bool readBNPHeader(const std::string &Filename, std::vector<SBNPFile> &FilesOut);
|
|
||||||
bool bnpUnpack(const std::string &srcBigfile, const std::string &dstPath, std::vector<std::string> &vFilenames);
|
bool bnpUnpack(const std::string &srcBigfile, const std::string &dstPath, std::vector<std::string> &vFilenames);
|
||||||
|
|
||||||
// stop the threads (called when knowing the thread ended)
|
// stop the threads (called when knowing the thread ended)
|
||||||
|
@ -471,6 +463,7 @@ private:
|
||||||
// The date to apply when file is buggy: use default of year 2001, just to have a coherent date
|
// The date to apply when file is buggy: use default of year 2001, just to have a coherent date
|
||||||
enum {DefaultResetDate= 31 * 366 * 24 * 3600};
|
enum {DefaultResetDate= 31 * 366 * 24 * 3600};
|
||||||
// The file size of a an empty BNP
|
// The file size of a an empty BNP
|
||||||
|
// If the BNP Header format change, please modify 'EmptyBnpFileSize' as needed
|
||||||
enum {EmptyBnpFileSize= 8};
|
enum {EmptyBnpFileSize= 8};
|
||||||
// Use an external downloader: (BitTorrent)
|
// Use an external downloader: (BitTorrent)
|
||||||
IAsyncDownloader* _AsyncDownloader;
|
IAsyncDownloader* _AsyncDownloader;
|
||||||
|
|
Loading…
Reference in a new issue