⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 resourcepacker.cpp

📁 游戏编程精粹6第1章 通用编程,对入门的游戏开发者很有帮助.
💻 CPP
字号:
// ResourcePacker.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include "resourcefile.h"
#include "fileinterface.h"
#include <vector>
#include <algorithm>
typedef std::vector<ResourceFileEntry> FileEntryTable;
ResourceFileHeader fileHeader;
ResourceFileStringTable fileStringTable;

int g_nFilecount = 0;
int g_nDircount = 0;
int g_nFilesize = 0;
FileEntryTable fileTable;

#ifdef _MSC_VER
void SearchDir(const char* szDir);
void CheckFile(const char* szDir, _finddata_t &file);
#endif

#ifdef __GNUC__
#include <dirent.h>
#include<sys/stat.h>
void SearchDir(const char* szDir);
void CheckFile(const char* szDir, const char* szFile);
#endif

int main(int argc, char** argv)
{
	if(argc < 3)
	{
		printf("\nusage: ResourcePacker <directory> <filename> [packing order file]\n");
		return 1;
	}

	fileHeader.nVersion = 1;
	g_nFilecount = 0;
	g_nDircount = 0;
	g_nFilesize = 0;

	printf("Resource Packer:\n\n");
	
	SearchDir(argv[1]);

	// This is not the most optimal function, but it does the trick.
	if(argc == 4) //Do we have a packing order file?
	{
		//open the file
		FILE* fp = fopen(argv[3], "r");
		if(fp)
		{
			ResourceFileStringTable local_fileStringTable;
			FileEntryTable local_fileTable;

			char line[128];
			FileInterface fileInterface;
			for(int i = 0; fgets(line, 127, fp) != NULL; ++i)
			{
				int nLen = (int)strlen(line);
				if(line[nLen-1] == '\n')
				{
					line[nLen-1] = '\0';
				}

				FileStats stats;
				if (fileInterface.StatFile(line, &stats))
				{				
					local_fileStringTable.push_back(line);
					ResourceFileEntry file_entry;
					file_entry.nStringTableIndex = (uint16)(local_fileStringTable.size() - 1);
					file_entry.nFileSize = stats.nSize;
					file_entry.nFlags = 0;
					file_entry.nCompressedFileSize = stats.nSize;
					local_fileTable.push_back(file_entry);
				}
				else
				{
					printf("Error: Can not stat file (%s)!\n", line);
				}

			}
			fclose(fp);

			//Now that we've created an ordered list, push the rest of the file entries on.
			int nStringTableSize = (int)fileStringTable.size();
			for(int j = 0; j < nStringTableSize; ++j)
			{
				ResourceFileStringTable::iterator iter = local_fileStringTable.begin();

				// Is this entry already in our new list?
				iter = find(local_fileStringTable.begin(), local_fileStringTable.end(), fileStringTable[j]);
				
				if(iter == local_fileStringTable.end())
				{
					// It wasn't found, so let's push it on
					local_fileStringTable.push_back(fileStringTable[j]);
					ResourceFileEntry file_entry;
					file_entry.nStringTableIndex = (uint16)(local_fileStringTable.size() - 1);
					file_entry.nFileSize = fileTable[j].nFileSize;
					file_entry.nFlags = 0;
					file_entry.nCompressedFileSize = fileTable[j].nFileSize;
					local_fileTable.push_back(file_entry);
				}

			}

			// Clear the old tables
			fileStringTable.clear();
			fileTable.clear();

			// Move our values over
			ResourceFileStringTable::iterator iter1 = local_fileStringTable.begin();
			while(iter1 != local_fileStringTable.end())
			{
				fileStringTable.push_back(*iter1);
				++iter1;
			}
 
			FileEntryTable::iterator iter2 = local_fileTable.begin();
			while(iter2 != local_fileTable.end())
			{
				fileTable.push_back(*iter2);
				++iter2;
			}
		}		
	}

	fileHeader.nNumFiles = (int)fileTable.size();

	int nFilePointerStart = sizeof(ResourceFileHeader) + (sizeof(ResourceFileEntry) *fileHeader.nNumFiles);
	int nFilePointerCur = nFilePointerStart;

	FileInterface fileInterface;
	BaseFile* pFile = fileInterface.OpenFile(argv[2], BINARY_FILE, WRITEONLY);

	// Write the file header
	pFile->Write(&fileHeader, sizeof(ResourceFileHeader));

	//Grab the resource directory name length plus the '\' or '/'
	int nResDirNameLen = (int)strlen(argv[1]) + 1;

	// Write out the string table
	FileEntryTable::iterator iter = fileTable.begin();
	while(iter != fileTable.end())
	{
		const char* pszString = fileStringTable[(*iter).nStringTableIndex].c_str();

		// Chop off the resource directory name len.
		int nStringLen = (int)strlen(pszString) - nResDirNameLen;
		pFile->Write(&nStringLen, sizeof(uint16));

		// Chop off the resource directory name.
		pFile->Write((void*)&pszString[nResDirNameLen], nStringLen);
		nFilePointerCur += nStringLen + sizeof(uint16);
		++iter;
	}	

	// Setup the file pointers
	iter = fileTable.begin();
	while(iter != fileTable.end())
	{
		(*iter).nFilepointer = nFilePointerCur;
		nFilePointerCur += (*iter).nFileSize;
		++iter;
	}

	// Write the file entries.
	pFile->Write(&fileTable[0], (sizeof(ResourceFileEntry) *fileHeader.nNumFiles));

	// Now add the file entry data to the resource file.
	iter = fileTable.begin();
	while(iter != fileTable.end())
	{
		BaseFile* pFileEntry = fileInterface.OpenFile(fileStringTable[(*iter).nStringTableIndex].c_str(), BINARY_FILE, READONLY);
		if(NULL != pFileEntry)
		{

			printf("Adding File: %s, Size: %d\n", fileStringTable[(*iter).nStringTableIndex].c_str(), (*iter).nFileSize);

			// Create the data buffer.
			uint8* pBytes = new uint8[(*iter).nFileSize];
			
			// Read in the file contents into our buffer.
			pFileEntry->Read(pBytes, (*iter).nFileSize);

			// Write it out to the resource file.
			pFile->Write(pBytes, (*iter).nFileSize);

			//Delete the data buffer.
			delete[] pBytes;

			//Close the file.
			fileInterface.CloseFile(pFileEntry);
		}
		++iter;
	}

	fileInterface.CloseFile(pFile);

	printf("  Number of directories found: %d\n", g_nDircount);
	printf("  Number of files found: %d\n", g_nFilecount);
	printf("  Total file size: %d (%dK)\n", g_nFilesize, g_nFilesize/1024);

	return 0;
}

#ifdef _MSC_VER
void SearchDir(const char* szDir)
{
	struct _finddata_t file;
	intptr_t hFile;

	char fulldirpath[4096];

	sprintf(fulldirpath, "%s\\*.*", szDir);


	if( (hFile = _findfirst( fulldirpath, &file )) == -1L )
	{
		printf( "ERROR: No files in current directory! (%s)\n" , fulldirpath);
	}
	else
	{

		CheckFile(szDir, file);
		/* Find the rest of the files */

		while( _findnext( hFile, &file ) == 0 )
		{
			CheckFile(szDir, file);
		}
		_findclose( hFile );
	}		
}

void CheckFile(const char* szDir, _finddata_t &file)
{

	if(file.attrib & _A_SUBDIR)
	{
		if(stricmp(file.name, ".") == 0)
		{
			return;
		}
		if(stricmp(file.name, "..") == 0)
		{
			return;
		}
		++g_nDircount;

		char szDir2[512];
		sprintf(szDir2,"%s\\%s",szDir,file.name);

		// if the file name is appended with ".\" then cut that off.
		// otherwise the hashed value will differ at load time.
		SearchDir((szDir2[0] == '.') ? (char*)&szDir2[2] : szDir2);
	}
	else
	{
		char szFullPath[512];
		sprintf(szFullPath,"%s\\%s",szDir,file.name);

		ResourceFileEntry file_entry;
		fileStringTable.push_back(szFullPath);
		file_entry.nStringTableIndex = (uint16)(fileStringTable.size() - 1);
		file_entry.nFileSize = file.size;
		file_entry.nFlags = 0;
		file_entry.nCompressedFileSize = file.size;
		fileTable.push_back(file_entry);

		g_nFilesize += file.size;
		++g_nFilecount;		
	}

}
#endif

#ifdef __GNUC__
void SearchDir(const char* szDir)
{
  DIR *dirp;
  struct dirent *dp;

  if ((dirp = opendir(szDir)) == NULL)
  {
	printf("Error! Can not open (%s)\n", szDir);
	return;
  }

  dp = readdir(dirp);
  while( dp != NULL )
  {  
	  CheckFile(szDir, dp->d_name);
	  dp = readdir(dirp);
  }

  closedir(dirp);
}

void CheckFile(const char* szDir, const char* szFile)
{
	char szFullPath[1024];
	sprintf(szFullPath, "%s/%s", szDir, szFile);
	struct stat s;
	if (stat(szFullPath, &s) == -1)
	{
		return;
	}
	
	if(strcmp(szFile, ".") == 0)
	{
		return;
	}
	if(strcmp(szFile, "..") == 0)
	{
		return;
	}
	
	if ((s.st_mode & S_IFMT) == S_IFDIR)
	{
		++g_nDircount;
		SearchDir(szFullPath);
	}
	else
	{
		ResourceFileEntry file_entry;
		fileStringTable.push_back(szFullPath);
		file_entry.nStringTableIndex = (uint16)(fileStringTable.size() - 1);
		file_entry.nFileSize = s.st_size;
		file_entry.nFlags = 0;
		file_entry.nCompressedFileSize = s.st_size;
		fileTable.push_back(file_entry);
		g_nFilesize += s.st_size;
		++g_nFilecount;			
	}
}
#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -