[HGE]-源码分析-10 resource

资源相关,先来张外部调用接口的图

文档里有更具体的用法   

游戏基本都是引擎+资源组成的,为了管理,资源一般都会打包,防止丢失容易管理 


bool CALL HGE_Impl::Resource_AttachPack(const char *filename, const char *password)
{
	char *szName;
	CResourceList *resItem=res;
	unzFile zip;

	szName=Resource_MakePath(filename);
	strupr(szName);//把字符串里的内容转换成大写

	while(resItem)
	{
		if(!strcmp(szName,resItem->filename)) return false;//遍历资源列表,如果已经载入了就退出
		resItem=resItem->next;
	}
	
	zip=unzOpen(szName);
	if(!zip) return false;
	unzClose(zip);

	resItem=new CResourceList;
	strcpy(resItem->filename, szName);
	if(password) strcpy(resItem->password, password);
	else resItem->password[0]=0;
	resItem->next=res;
	res=resItem;

	return true;
}
附加一个包到资源列表,并不是把资源载入内存了,只是把包放在资源列表里

里面会有一个检测操作,检测这个包里是有文件的,unzOpen后返回指向第一个资源的句柄


void CALL HGE_Impl::Resource_RemovePack(const char *filename)
{
	char *szName;
	CResourceList *resItem=res, *resPrev=0;

	szName=Resource_MakePath(filename);
	strupr(szName);

	while(resItem)
	{
		if(!strcmp(szName,resItem->filename))
		{
			if(resPrev) resPrev->next=resItem->next;
			else res=resItem->next;
			delete resItem;
			break;
		}

		resPrev=resItem;
		resItem=resItem->next;
	}
}

去掉附加的包~,遍历列表删除节点就行


void CALL HGE_Impl::Resource_RemoveAllPacks()
{
	CResourceList *resItem=res, *resNextItem;

	while(resItem)
	{
		resNextItem=resItem->next;
		delete resItem;
		resItem=resNextItem;
	}

	res=0;
}

去掉所有附加的包,直接清空了资源列表




void* CALL HGE_Impl::Resource_Load(const char *filename, DWORD *size)
{
	static char *res_err="Can't load resource: %s";

	CResourceList *resItem=res;
	char szName[_MAX_PATH];
	char szZipName[_MAX_PATH];
	unzFile zip;
	unz_file_info file_info;
	int done, i;
	void *ptr;
	HANDLE hF;

	if(filename[0]=='\\' || filename[0]=='/' || filename[1]==':') goto _fromfile; // skip absolute paths

	// Load from pack
 
	strcpy(szName,filename);
	strupr(szName);
	for(i=0; szName[i]; i++) { if(szName[i]=='/') szName[i]='\\'; }// '/'和'\'转化,本身在windows里没有区别,都可以表示路径

	while(resItem)
	{
		zip=unzOpen(resItem->filename);//返回一个句柄
		done=unzGoToFirstFile(zip);//把句柄定位到包里的第一个文件
		while(done==UNZ_OK)
		{
			unzGetCurrentFileInfo(zip, &file_info, szZipName, sizeof(szZipName), NULL, 0, NULL, 0);//获取文件信息和路径
			strupr(szZipName);
			for(i=0; szZipName[i]; i++)	{ if(szZipName[i]=='/') szZipName[i]='\\'; }//在转一下 \和/
			if(!strcmp(szName,szZipName))//验证是不是要载入的文件
			{
				if(unzOpenCurrentFilePassword(zip, resItem->password[0] ? resItem->password : 0) != UNZ_OK)
				{//解压密码不对贴出错误信息然后退出
					unzClose(zip);
					sprintf(szName, res_err, filename);
					_PostError(szName);
					return 0;
				}

				ptr = malloc(file_info.uncompressed_size);//分配内存,资源未压缩的大小
				if(!ptr)
				{//分配失败。。
					unzCloseCurrentFile(zip);
					unzClose(zip);
					sprintf(szName, res_err, filename);
					_PostError(szName);
					return 0;
				}

				if(unzReadCurrentFile(zip, ptr, file_info.uncompressed_size) < 0)//读出文件,成功后返回0
				{
					unzCloseCurrentFile(zip);
					unzClose(zip);
					free(ptr);
					sprintf(szName, res_err, filename);
					_PostError(szName);
					return 0;
				}
				unzCloseCurrentFile(zip);
				unzClose(zip);
				if(size) *size=file_info.uncompressed_size;
				return ptr;
			}
			
			done=unzGoToNextFile(zip);//不是的话句柄后移继续找
		}
		
		unzClose(zip);
		resItem=resItem->next;
	}

	// Load from file  直接读一个文件
_fromfile:
	//过程和上面差不多,只不过用windows的接口直接读取了,获取的也是文件句柄
	hF = CreateFile(Resource_MakePath(filename), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL);
	if(hF == INVALID_HANDLE_VALUE)
	{
		sprintf(szName, res_err, filename);
		_PostError(szName);
		return 0;
	}
	file_info.uncompressed_size = GetFileSize(hF, NULL);
	ptr = malloc(file_info.uncompressed_size);
	if(!ptr)
	{
		CloseHandle(hF);
		sprintf(szName, res_err, filename);
		_PostError(szName);
		return 0;
	}
	if(ReadFile(hF, ptr, file_info.uncompressed_size, &file_info.uncompressed_size, NULL ) == 0)
	{
		CloseHandle(hF);
		free(ptr);
		sprintf(szName, res_err, filename);
		_PostError(szName);
		return 0;
	}
	
	CloseHandle(hF);
	if(size) *size=file_info.uncompressed_size;
	return ptr;
}

把资源载入内存,两种载入方式,一种是从包里载入,会有类似解压然后提取资源的操作

另一种是直接载入资源,从文件载入(不在包内的)

成功后返回资源指针,并且通过参数传出大小(size)信息,指针是void的,需要大小信息给它正确寻址


void CALL HGE_Impl::Resource_Free(void *res)
{
	if(res) free(res);
}

释放资源


char* CALL HGE_Impl::Resource_MakePath(const char *filename)
{
	int i;
	//生成一个带路径的文件名
	if(!filename)
		strcpy(szTmpFilename, szAppPath);
	else if(filename[0]=='\\' || filename[0]=='/' || filename[1]==':')
		strcpy(szTmpFilename, filename);
	else
	{
		strcpy(szTmpFilename, szAppPath);
		if(filename) strcat(szTmpFilename, filename);
	}
	
	for(i=0; szTmpFilename[i]; i++) { if(szTmpFilename[i]=='/') szTmpFilename[i]='\\'; }
	return szTmpFilename;
}

生成完整的路径


char* CALL HGE_Impl::Resource_EnumFiles(const char *wildcard)
{
	if(wildcard)
	{
		if(hSearch) { FindClose(hSearch); hSearch=0; }
		hSearch=FindFirstFile(Resource_MakePath(wildcard), &SearchData);//重新创建搜索句柄,在文件夹下搜索指定的文件,SearchData保存搜索信息
									        //vc里还有一个FindFirstFileEx函数,使用附加属性搜索
		if(hSearch==INVALID_HANDLE_VALUE) { hSearch=0; return 0; }//无效返回值
		//如果搜到的是文件夹,就继续往下搜(递归调用空参数的函数),如果是文件则返回文件名
		if(!(SearchData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) return SearchData.cFileName;
		else return Resource_EnumFiles();
	}
	else
	{
		if(!hSearch) return 0;
		for(;;)
		{    //继续在上次生成的句柄位置往下搜下一个文件,如果不是文件夹则返回文件名
			if(!FindNextFile(hSearch, &SearchData))	{ FindClose(hSearch); hSearch=0; return 0; }
			if(!(SearchData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) return SearchData.cFileName;
		}
	}
}

char* CALL HGE_Impl::Resource_EnumFolders(const char *wildcard)
{
	if(wildcard)
	{
		if(hSearch) { FindClose(hSearch); hSearch=0; }
		hSearch=FindFirstFile(Resource_MakePath(wildcard), &SearchData);
		if(hSearch==INVALID_HANDLE_VALUE) { hSearch=0; return 0; }
		//搜的是文件夹,这个是文件操作里处理文件夹的统一操作,判断属性是文件夹,且文件名不是'.'和'..'
		//这个很奇怪啊,三个点的也建不了文件夹。。。不明白为什么都这样写
		if((SearchData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
		   strcmp(SearchData.cFileName,".") && strcmp(SearchData.cFileName,".."))
				return SearchData.cFileName;
		else return Resource_EnumFolders();
	}
	else
	{
		if(!hSearch) return 0;
		for(;;)
		{
			if(!FindNextFile(hSearch, &SearchData))	{ FindClose(hSearch); hSearch=0; return 0; }
			if((SearchData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
			   strcmp(SearchData.cFileName,".") && strcmp(SearchData.cFileName,".."))
					return SearchData.cFileName;
		}
	}
}

这两个一起,一个是找到指定路径下的文件,一个是找文件夹,具体的注释里有写


HGE资源操作主要用zlib的库,从包里载入文件。




  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值