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

📄 dnfile.cpp

📁 网络游戏魔域的服务端与客户端完整源代码 包括详细的说明文档与开发日志
💻 CPP
字号:
//--------------------------------------------------------------------------------------
// File Name: DnFile.cpp
// Create by: Huang Yuhang
// Create on: 2003/11/16 20:13
//--------------------------------------------------------------------------------------
#pragma warning(disable:4786)
#include "../include/DnFile.h"
#include "Windows.h"
#include    <io.h>


//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
const unsigned long DAWNFILE_BUFFERSIZE	=	1024*1024;
CRITICAL_SECTION	g_DnFileCriticalSection;
CDnFile g_objDnFile;
//--------------------------------------------------------------------------------------
CDnFile::CDnFile()
{
	m_pBuffer		= NULL;
	m_pExtendBuffer	= NULL;
	m_fpExtend		= NULL;
	this->Create();
	InitializeCriticalSection ( &g_DnFileCriticalSection );
}

CDnFile::~CDnFile()
{
	this->Destroy();
	LeaveCriticalSection ( &g_DnFileCriticalSection );
	DeleteCriticalSection ( &g_DnFileCriticalSection );
}
//--------------------------------------------------------------------------------------
void CDnFile::BeforeUseDnFile()
{
	EnterCriticalSection ( &g_DnFileCriticalSection );
}
//--------------------------------------------------------------------------------------
void CDnFile::AfterUseDnFile()
{
	LeaveCriticalSection ( &g_DnFileCriticalSection );
}
//--------------------------------------------------------------------------------------
FILE*	CDnFile::GetFPtr(const char* pszFile, unsigned long& usFileSize)
{
	this->ClearPtr();
	if(!pszFile)
		return false;
	char szFileCopy[512];
	strcpy(szFileCopy, pszFile);
	strlwr(szFileCopy);
	unsigned long uFileNameLength = strlen(szFileCopy);
	for(int i = 0; i < uFileNameLength; i ++)
	{
		if(szFileCopy[i] == '/')
		{
			szFileCopy[i] = '\\';
		}
	}
	unsigned long idFile = this->GenerateID(szFileCopy);
	if(!this->CheckDisperseFile(idFile))
	{
		unsigned long uFileNameLength = strlen(szFileCopy);
		for(int i = 0; i < uFileNameLength; i ++)
		{
			if(szFileCopy[i] == '\\')
			{
				szFileCopy[i] = '\0';
			}
		}
		unsigned long idPack = this->GenerateID(szFileCopy);
		map<unsigned long, DnpInfo*>::iterator iter = m_mapDnp.find(idPack);
		if(iter != m_mapDnp.end())
		{
			DnpInfo* pInfoDnp = iter->second;
			if(pInfoDnp)
			{
				map<unsigned long, FileIndexInfo*>::iterator iterFile = pInfoDnp->mapIndex.find(idFile);
				if(iterFile != pInfoDnp->mapIndex.end())
				{
					fseek(pInfoDnp->fpDnp, iterFile->second->uOffset, SEEK_SET);
					usFileSize = iterFile->second->uSize;
					return pInfoDnp->fpDnp;
				}
			}
		}
	}
	m_fpExtend = fopen(pszFile, "rb");
	if(m_fpExtend)
		usFileSize = filelength(fileno(m_fpExtend));
	return 	m_fpExtend;	
}
//--------------------------------------------------------------------------------------
void*	CDnFile::GetMPtr(const char* pszFile, unsigned long& usFileSize)
{
	this->ClearPtr();
	if(!pszFile)
		return false;
	char szFileCopy[512];
	strcpy(szFileCopy, pszFile);
	strlwr(szFileCopy);
	unsigned long uFileNameLength = strlen(szFileCopy);
	for(int i = 0; i < uFileNameLength; i ++)
	{
		if(szFileCopy[i] == '/')
		{
			szFileCopy[i] = '\\';
		}
	}
	unsigned long idFile = this->GenerateID(szFileCopy);
	if(!this->CheckDisperseFile(idFile))
	{
		unsigned long uFileNameLength = strlen(szFileCopy);
		for(int i = 0; i < uFileNameLength; i ++)
		{
			if(szFileCopy[i] == '\\')
			{
				szFileCopy[i] = '\0';
			}
		}
		unsigned long idPack = this->GenerateID(szFileCopy);
		map<unsigned long, DnpInfo*>::iterator iter = m_mapDnp.find(idPack);
		if(iter != m_mapDnp.end())
		{
			DnpInfo* pInfoDnp = iter->second;
			if(pInfoDnp)
			{
				map<unsigned long, FileIndexInfo*>::iterator iterFile = pInfoDnp->mapIndex.find(idFile);
				if(iterFile != pInfoDnp->mapIndex.end())
				{
					FileIndexInfo* pInfo = iterFile->second;
					fseek(pInfoDnp->fpDnp, iterFile->second->uOffset, SEEK_SET);
					if(iterFile->second->uSize > DAWNFILE_BUFFERSIZE)
					{
						m_pExtendBuffer = new unsigned char[iterFile->second->uSize];
						if(!m_pExtendBuffer)
							return NULL;
						usFileSize = iterFile->second->uSize;
						fread(m_pExtendBuffer, sizeof(char), iterFile->second->uSize, pInfoDnp->fpDnp);
						return m_pExtendBuffer;
					}
					else
					{
						fread(m_pBuffer, sizeof(char), iterFile->second->uSize, pInfoDnp->fpDnp);
						usFileSize = iterFile->second->uSize;
						return m_pBuffer;
					}
				}
			}
		}
	}
	return 	NULL;	
}
//--------------------------------------------------------------------------------------
bool	CDnFile::CheckDisperseFile(const unsigned long uFileID)
{
	int nAmount = m_mapDisperseFiles.size();
	map<unsigned long, unsigned char>::iterator iter = m_mapDisperseFiles.find(uFileID);
	if(iter == m_mapDisperseFiles.end())
		return false;
	return true;
}
//--------------------------------------------------------------------------------------
bool	CDnFile::CheckDisperseFile(const char* pszFile)
{
	if(!pszFile)
		return false;
	char szFileCopy[512];
	strcpy(szFileCopy, pszFile);
	strupr(szFileCopy);
	unsigned long idFile = this->GenerateID(pszFile);
	map<unsigned long, unsigned char>::iterator iter = m_mapDisperseFiles.find(idFile);
	if(iter == m_mapDisperseFiles.end())
		return false;
	return true;
}
//--------------------------------------------------------------------------------------
void	CDnFile::AddDisperseFile(const char* pszFile)
{
	if(!pszFile)
		return;
	char szFileCopy[512];
	strcpy(szFileCopy, pszFile);
	strlwr(szFileCopy);
	unsigned long uFileNameLength = strlen(szFileCopy);
	for(int i = 0; i < uFileNameLength; i ++)
	{
		if(szFileCopy[i] == '/')
		{
			szFileCopy[i] = '\\';
		}
	}
	unsigned long idFile = this->GenerateID(szFileCopy);
	m_mapDisperseFiles[idFile] = 0;
}

void CDnFile::ProcessDir ( const char* pszDir)
{
	_finddata_t filestruct;
	int p = 0;
	int fn = 0;
	char szSearch[255];
	if (strlen(pszDir) == 0)
	{
		strcpy(szSearch , "*.*");
	}
	else
	{
		strcpy(szSearch , pszDir);
		strcat(szSearch , "/*.*");
	}
	
	int hnd = _findfirst(szSearch , &filestruct);
	if(hnd == -1) 
	{
		return;
	}
	do
	{ 
		char szFullName[MAX_PATH] = "";
		if (strlen(pszDir) > 0)
		{
			sprintf(szFullName , "%s/%s" , pszDir , filestruct.name);		
		}
		else
		{
			strcpy(szFullName , filestruct.name);
		}
		
		if (!(filestruct.attrib & _A_SUBDIR)) 
		{
			// Process the file name
			char szFileCopy[512];
			strcpy(szFileCopy, szFullName);
			strlwr(szFileCopy);
			unsigned long uFileNameLength = strlen(szFileCopy);
			for(int i = 0; i < uFileNameLength; i ++)
			{
				if(szFileCopy[i] == '/')
				{
					szFileCopy[i] = '\\';
				}
			}
			DWORD id = this->GenerateID( szFileCopy ) ;
			m_mapDisperseFiles[id]=0;
		}
		else // Directory
		{
			if (strcmp(filestruct.name , "..") != 0 && strcmp(filestruct.name, ".") != 0)
			{
				ProcessDir(szFullName);
			}
		}
	}while(!_findnext(hnd , &filestruct)); 
}
//--------------------------------------------------------------------------------------
bool	CDnFile::OpenFile(const char* pszFile)
{

	if(!pszFile)
		return false;
	// 未打包目录中的文件列表预读, 优化未打包文件搜寻
	char* p = strchr ( pszFile, '.' ) ;
	if ( p )
	{
		char szDirName[MAX_PATH] = "";
		strncpy ( szDirName, pszFile, p - pszFile ) ;
		
		ProcessDir ( szDirName) ;
	}	
	char szFileCopy[512];
	strcpy(szFileCopy, pszFile);
	strlwr(szFileCopy);

	if(strlen(pszFile) < 4)
		return false;
	int nFileNameLength = strlen(szFileCopy);
	if(szFileCopy[nFileNameLength-1] != 'p' || szFileCopy[nFileNameLength-2] != 'n' ||
		szFileCopy[nFileNameLength-3] != 'd' || szFileCopy[nFileNameLength-4] != '.')
		return false;
	szFileCopy[nFileNameLength-4] = '\0';

	unsigned long idFile = this->GenerateID(szFileCopy);
	map<unsigned long, DnpInfo*>::iterator iter = m_mapDnp.find(idFile);
	if(iter != m_mapDnp.end())
		return false;

	DnpInfo* pDnpInfo = new DnpInfo;
	char szTemp[100];
	sprintf(szTemp, "new 0x%x\n", pDnpInfo);
	::OutputDebugString(szTemp);
	if(!pDnpInfo)
		return false;

	pDnpInfo->fpDnp = fopen(pszFile, "rb");
	if(!pDnpInfo->fpDnp)
	{
		delete(pDnpInfo);
		return false;
	}

	char szFileHeader[32]="";
	fread(szFileHeader, sizeof(char), 32, pDnpInfo->fpDnp);
	if(strcmp(szFileHeader, "DawnPack.TqDigital") != 0)
	{
		fclose(pDnpInfo->fpDnp);
		delete(pDnpInfo);
		return false;
	}

	unsigned long uVersion = 0;
	fread(&uVersion, sizeof(unsigned long), 1, pDnpInfo->fpDnp);
	if(uVersion != 1000)
	{
		fclose(pDnpInfo->fpDnp);
		delete(pDnpInfo);
		return false;
	}

	unsigned long uFileAmount = 0;
	fread(&uFileAmount, sizeof(unsigned long), 1, pDnpInfo->fpDnp);

	for(unsigned long uCounter = 0; uCounter < uFileAmount; uCounter++)
	{
		unsigned long idSubFile;
		unsigned long uFileOffset;
		unsigned long uFileSize;
		fread(&idSubFile, sizeof(unsigned long), 1, pDnpInfo->fpDnp);
		fread(&uFileSize, sizeof(unsigned long), 1, pDnpInfo->fpDnp);
		fread(&uFileOffset, sizeof(unsigned long), 1, pDnpInfo->fpDnp);

		FileIndexInfo* pinfoIndex = new FileIndexInfo;
		if(!pinfoIndex)
			return false;
		pinfoIndex->uOffset = uFileOffset;
		pinfoIndex->uSize = uFileSize;
		pDnpInfo->mapIndex[idSubFile] = pinfoIndex;
	}
	m_mapDnp[idFile] = pDnpInfo;
	return true;
}
//--------------------------------------------------------------------------------------
void	CDnFile::ClearPtr()
{
	if(m_pExtendBuffer)
	{
		delete[] m_pExtendBuffer;
		m_pExtendBuffer = NULL;
	}
	if(m_fpExtend)
	{
		fclose(m_fpExtend);
		m_fpExtend = NULL;
	}
}
//--------------------------------------------------------------------------------------
void	CDnFile::CloseFile(const char* pszFile)
{
	if(!pszFile)
		return;
	char szFileCopy[512];
	strcpy(szFileCopy, pszFile);
	strupr(szFileCopy);
	unsigned long idFile = this->GenerateID(pszFile);
	map<unsigned long, DnpInfo*>::iterator iter = m_mapDnp.find(idFile);
	if(iter != m_mapDnp.end())
		return;
	DnpInfo* pDnp = iter->second;
	if(pDnp)
	{
		fclose(pDnp->fpDnp);
		pDnp->mapIndex.clear();
		delete(pDnp);
	}
	m_mapDnp.erase(iter);
}
//--------------------------------------------------------------------------------------
void	CDnFile::Destroy()
{
	map<unsigned long, DnpInfo*>::iterator iter = m_mapDnp.begin();
	while(iter != m_mapDnp.end())
	{
		DnpInfo* pDnp = iter->second;
		if(pDnp)
		{
			fclose(pDnp->fpDnp);
			map<unsigned long, FileIndexInfo*>::iterator iterIndex = pDnp->mapIndex.begin();
			while(iterIndex != pDnp->mapIndex.end())
			{
				FileIndexInfo* pInfo = iterIndex->second;
				if(pInfo)
					delete pInfo;
				iterIndex ++;
			}
			pDnp->mapIndex.clear();
			delete(pDnp);
			char szTemp[100];
			sprintf(szTemp, "delete 0x%x\n", pDnp);
			::OutputDebugString(szTemp);
		}
		iter ++;
	}
	m_mapDnp.clear();
	if(m_pBuffer)
	{
		delete[] m_pBuffer;
		m_pBuffer = NULL;
	}
	if(m_pExtendBuffer)
	{
		delete[] m_pExtendBuffer;
		m_pExtendBuffer = NULL;
	}
	if(m_fpExtend)
	{
		fclose(m_fpExtend);
		m_fpExtend = NULL;
	}
	m_mapDisperseFiles.clear();
}
//--------------------------------------------------------------------------------------
void	CDnFile::Create()
{
	this->Destroy();
	m_pBuffer = new unsigned char[DAWNFILE_BUFFERSIZE];
}
//--------------------------------------------------------------------------------------
unsigned long	CDnFile::GenerateID(const char* str)
{
	if(!str)
		return 0;
	int i;
	unsigned int v;
	static unsigned m[70];
	strncpy((char *)m,str,256);
	for (i=0;i<256/4 && m[i];i++) ;
	m[i++]=0x9BE74448,m[i++]=0x66F42C48;
	v=0xF4FA8928;
	
	__asm {
		mov esi,0x37A8470E		;x0=0x37A8470E
			mov edi,0x7758B42B		;y0=0x7758B42B
			xor ecx,ecx
_loop:
		mov ebx,0x267B0B11		;w=0x267B0B11
			rol v,1
			lea eax,m
			xor ebx,v
			
			mov eax,[eax+ecx*4]
			mov edx,ebx
			xor esi,eax
			xor edi,eax
			
			add edx,edi
			or edx,0x2040801		;a=0x2040801
			and edx,0xBFEF7FDF		;c=0xBFEF7FDF
			
			mov eax,esi
			mul edx
			adc eax,edx
			mov edx,ebx
			adc eax,0
			
			add edx,esi
			or edx,0x804021			;b=0x804021
			and edx,0x7DFEFBFF		;d=0x7DFEFBFF
			
			mov esi,eax
			mov eax,edi
			mul edx
			
			add edx,edx
			adc eax,edx
			jnc _skip
			add eax,2
_skip:
		inc ecx;
		mov edi,eax
			cmp ecx,i
			jnz _loop
			xor esi,edi
			mov v,esi
	}
#ifdef _DEBUG
	char szTemp[512];
	sprintf(szTemp, "%s FileID: %u\n", str,v);
	::OutputDebugString(szTemp);	
#endif
	return v;
}
//--------------------------------------------------------------------------------------

⌨️ 快捷键说明

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