23#define WIN32_LEAN_AND_MEAN
40static const char *nodxtPrefix[] = {
46static const char *nodxtAnywhere[] = {
53#define LOG(x) logStuff x
54static void logStuff(
const char *fmt, ...)
56 static char buffer[1024];
59 _vsnprintf(buffer, 1024, fmt, va );
64 ::MessageBox(
NULL, buffer,
"textureCompress", MB_OK);
80#define DEBUG_LOG(x) debugLog x
81static void debugLog(
const char *fmt, ...)
83 static char buffer[1024];
86 _vsnprintf(buffer, 1024, fmt, va );
90 OutputDebugString( buffer );
93 fputs(buffer, theDebugMunkee->m_fp);
98#define DEBUG_LOG(x) {}
103static void usage(
const char *progname)
106 progname =
"textureCompress";
107 LOG ((
"Usage: %s sourceDir destDir cacheDir outFile dxtOutFile\n", progname));
116 void set(
const WIN32_FIND_DATA& info );
160static void TimetToFileTime(
time_t t, FILETIME& ft )
162 LONGLONG ll = Int32x32To64(t, 10000000) + 116444736000000000;
163 ft.dwLowDateTime = (
DWORD) ll;
164 ft.dwHighDateTime = ll >>32;
167static time_t FileTimeToTimet(
const FILETIME& ft )
169 LONGLONG ll = (ft.dwHighDateTime << 32) + ft.dwLowDateTime - 116444736000000000;
179 for (
int i=0; i<
filename.size(); ++i)
181 char c[2] = { tolower(info.cFileName[i]), 0 };
185 accessTime = FileTimeToTimet(info.ftLastAccessTime);
186 modTime = FileTimeToTimet(info.ftLastWriteTime);
190 struct stat origStat;
201 WIN32_FIND_DATA item;
203 char currDir[ MAX_PATH ];
212 GetCurrentDirectory( MAX_PATH, currDir );
215 if( SetCurrentDirectory(
m_dirPath.c_str() ) == 0 )
222 hFile = FindFirstFile(
"*", &item);
223 if( hFile == INVALID_HANDLE_VALUE )
233 if( item.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
235 if ( strcmp( item.cFileName,
"." ) && strcmp( item.cFileName,
".." ) )
247 if ( FindNextFile( hFile, &item ) == 0 )
257 SetCurrentDirectory( currDir );
275static char*
strtrim(
char* buffer)
277 if (buffer !=
NULL) {
279 char * source = buffer;
280 while ((*source != 0) && ((
unsigned char)*source <= 32))
285 if (source != buffer)
287 strcpy(buffer, source);
291 for (
int index = strlen(buffer)-1; index >= 0; index--)
293 if ((*source != 0) && ((
unsigned char)buffer[index] <= 32))
295 buffer[index] =
'\0';
311void eraseCachedFiles(
const std::string& sourceDirName,
const std::string& targetDirName,
const std::string& cacheDirName,
314 StringSet::const_iterator sit;
315 for (sit = cachedFilesToErase.begin(); sit != cachedFilesToErase.end(); ++sit)
317 std::string src = cacheDirName;
321 DEBUG_LOG((
"Erasing cached file: %s\n", src.c_str()));
322 DeleteFile(src.c_str());
327void copyCachedFiles(
const std::string& sourceDirName,
const std::string& targetDirName,
const std::string& cacheDirName,
330 StringSet::const_iterator sit;
331 for (sit = cachedFilesToCopy.begin(); sit != cachedFilesToCopy.end(); ++sit)
333 std::string src = cacheDirName;
337 std::string dest = targetDirName;
341 DEBUG_LOG((
"Copying cached file: %s\n", src.c_str()));
342 if (_chmod(dest.c_str(), _S_IWRITE | _S_IREAD) == -1)
344 DEBUG_LOG((
"Cannot chmod '%s'\n", dest.c_str()));
346 CopyFile(src.c_str(), dest.c_str(),
FALSE);
351void compressOrigFiles(
const std::string& sourceDirName,
const std::string& targetDirName,
const std::string& cacheDirName,
352 StringSet& origFilesToCompress,
const std::string& dxtOutFname)
354 char tmpPath[_MAX_PATH] =
"C:\\temp\\";
355 char tmpFname[_MAX_PATH] =
"C:\\temp\\tmp.txt";
356 GetTempPath(_MAX_PATH, tmpPath);
357 GetTempFileName(tmpPath,
"tex", 0, tmpFname);
358 HANDLE h = CreateFile(tmpFname, GENERIC_WRITE, 0,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY,
NULL);
361 DEBUG_LOG((
"Could not create temp file '%s'! Unable to compress textures!\n", tmpFname));
364 StringSet::const_iterator sit;
365 for (sit = origFilesToCompress.begin(); sit != origFilesToCompress.end(); ++sit)
367 std::string tmp = sourceDirName;
371 DEBUG_LOG((
"Compressing file: %s", tmp.c_str()));
373 WriteFile(h, tmp.c_str(), tmp.length(), &len,
NULL);
377 std::string commandLine;
378 commandLine =
"\\projects\\rts\\build\\nvdxt -list ";
379 commandLine.append(tmpFname);
380 commandLine.append(
" -24 dxt1c -32 dxt5 -full -outdir ");
381 commandLine.append(cacheDirName);
382 commandLine.append(
" > ");
383 commandLine.append(dxtOutFname);
385 DEBUG_LOG((
"Compressing textures with command line of '%s'\n", commandLine.c_str()));
386 int ret = system(commandLine.c_str());
387 DEBUG_LOG((
"system(%s) returned %d\n", commandLine.c_str(), ret));
388 DeleteFile(tmpFname);
391 for (sit = origFilesToCompress.begin(); sit != origFilesToCompress.end(); ++sit)
393 std::string orig = sourceDirName;
397 struct stat origStat;
398 stat( orig.c_str(), &origStat);
401 utb.actime = origStat.st_atime;
402 utb.modtime = origStat.st_mtime;
404 std::string src = cacheDirName;
407 src.replace(src.size()-4, 4,
".dds");
409 _utime(src.c_str(), &utb);
411 std::string dest = targetDirName;
414 dest.replace(dest.size()-4, 4,
".dds");
416 DEBUG_LOG((
"Copying new file from %s to %s\n", src.c_str(), dest.c_str()));
418 if (_chmod(dest.c_str(), _S_IWRITE | _S_IREAD) == -1)
420 DEBUG_LOG((
"Cannot chmod '%s'\n", dest.c_str()));
422 BOOL ret = CopyFile(src.c_str(), dest.c_str(),
FALSE);
428 _utime(dest.c_str(), &utb);
433void copyOrigFiles(
const std::string& sourceDirName,
const std::string& targetDirName,
const std::string& cacheDirName,
436 StringSet::const_iterator sit;
437 for (sit = origFilesToCopy.begin(); sit != origFilesToCopy.end(); ++sit)
439 std::string src = sourceDirName;
443 std::string dest = targetDirName;
447 if (_chmod(dest.c_str(), _S_IWRITE | _S_IREAD) == -1)
449 DEBUG_LOG((
"Cannot chmod '%s'\n", dest.c_str()));
451 BOOL res = CopyFile(src.c_str(), dest.c_str(),
FALSE);
452 DEBUG_LOG((
"Copying file: %s returns %d\n", src.c_str(), res));
457static void scanDir(
const std::string& sourceDirName,
const std::string& targetDirName,
const std::string& cacheDirName,
const std::string& dxtOutFname )
459 DEBUG_LOG((
"Scanning '%s'\n", sourceDirName.c_str()));
462 DEBUG_LOG((
"Scanning '%s'\n", targetDirName.c_str()));
465 DEBUG_LOG((
"Scanning '%s'\n", cacheDirName.c_str()));
478 for (FileInfoSet::iterator targetIt = targetFiles->begin(); targetIt != targetFiles->end(); ++targetIt)
483 FileInfoSet::iterator fit = sourceFiles->find(f);
484 if (fit == sourceFiles->end())
488 FileInfoSet::iterator ddsfit = sourceFiles->find(f);
489 if (ddsfit == sourceFiles->end())
491 fname.insert(0,
"\\");
492 fname.insert(0, targetDirName);
493 DEBUG_LOG((
"Deleting now-removed file '%s'\n", fname.c_str()));
494 DeleteFile(fname.c_str());
499 for (FileInfoSet::iterator cacheIt = cacheFiles->begin(); cacheIt != cacheFiles->end(); ++cacheIt)
505 cachedFilesToErase.insert(f.
filename);
509 f.
filename.replace(len-4, 4,
".tga");
510 FileInfoSet::iterator fit = sourceFiles->find(f);
511 if (fit != sourceFiles->end())
537 cachedFilesToErase.insert(fname);
542 FileInfoSet::iterator it = targetFiles->find(f);
543 if (it == targetFiles->end())
544 cachedFilesToCopy.insert(fname);
549 cachedFilesToErase.insert(fname);
553 for (FileInfoSet::iterator sourceIt = sourceFiles->begin(); sourceIt != sourceFiles->end(); ++sourceIt)
558 const char *s = fname.c_str();
560 const char *check = nodxtPrefix[0];
561 bool shouldSkip =
false;
564 if (fname.find(check) == 0)
569 check = nodxtPrefix[++index];
573 check = nodxtAnywhere[0];
574 while (check && !shouldSkip)
576 if (fname.find(check) != fname.npos)
581 check = nodxtAnywhere[++index];
587 if (fname.find(
".dds") != fname.npos)
595 origFilesToCopy.insert(s);
600 f.
filename.replace(len-4, 4,
".dds");
601 FileInfoSet::iterator fit = cacheFiles->find(f);
602 if (fit != cacheFiles->end())
607 origFilesToCompress.insert(fname);
612 origFilesToCompress.insert(fname);
618 eraseCachedFiles (sourceDirName, targetDirName, cacheDirName, cachedFilesToErase);
619 copyCachedFiles (sourceDirName, targetDirName, cacheDirName, cachedFilesToCopy);
620 copyOrigFiles (sourceDirName, targetDirName, cacheDirName, origFilesToCopy);
621 compressOrigFiles(sourceDirName, targetDirName, cacheDirName, origFilesToCompress, dxtOutFname);
628 HINSTANCE hPrevInstance,
639 char * token = strtok(lpCmdLine,
" ");
640 while (argc < 20 && token !=
NULL)
643 token = strtok(
NULL,
" ");
646int main(
int argc,
const char **argv)
656 const char *sourceDir = argv[1];
657 const char *targetDir = argv[2];
658 const char *cacheDir = argv[3];
665 scanDir(sourceDir, targetDir, cacheDir, argv[5]);
673 delete theDebugMunkee;
674 theDebugMunkee =
NULL;
DebugMunkee(const char *fname="debugLog.txt")
Directory(const std::string &dirPath)
FileInfoSet * getSubdirs(void)
FileInfoSet * getFiles(void)
bool operator()(const FileInfo &a, const FileInfo &b) const
void set(const WIN32_FIND_DATA &info)
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
void copyCachedFiles(const std::string &sourceDirName, const std::string &targetDirName, const std::string &cacheDirName, StringSet &cachedFilesToCopy)
void compressOrigFiles(const std::string &sourceDirName, const std::string &targetDirName, const std::string &cacheDirName, StringSet &origFilesToCompress, const std::string &dxtOutFname)
std::set< FileInfo, FileInfoComparator > FileInfoSet
std::set< std::string > StringSet
void eraseCachedFiles(const std::string &sourceDirName, const std::string &targetDirName, const std::string &cacheDirName, StringSet &cachedFilesToErase)
void copyOrigFiles(const std::string &sourceDirName, const std::string &targetDirName, const std::string &cacheDirName, StringSet &origFilesToCopy)
char * strtrim(char *buffer)