将资源合并为一个二进制文件 [英] Combining resources into a single binary file

查看:126
本文介绍了将资源合并为一个二进制文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何将一个应用程序的多种资源(图像,声音,脚本,xml等)组合到一个/多个二进制文件中,从而保护它们免受用户的伤害?典型步骤是什么(组织,加载,加密等)?

How does one combine several resources for an application (images, sounds, scripts, xmls, etc.) into a single/multiple binary file so that they're protected from user's hands? What are the typical steps (organizing, loading, encryption, etc...)?

这在游戏开发中尤为常见,但仍有许多游戏框架和引擎那里没有提供简便的方法来执行此操作,也没有描述一般的方法。我一直想学习如何做,但是我不知道从哪里开始。有人能指出我正确的方向吗?

This is particularly common in game development, yet a lot of the game frameworks and engines out there don't provide an easy way to do this, nor describe a general approach. I've been meaning to learn how to do it, but I don't know where to begin. Could anyone point me in the right direction?

推荐答案

有很多方法可以做到这一点。 m_pGladiator有一些好主意,尤其是在序列化方面。我还要发表其他意见。

There are lots of ways to do this. m_pGladiator has some good ideas, especially with seralization. I would like to make a few other comments.

首先,如果您要将一堆资源打包到一个文件中(我称这些包文件),那么我认为您应该避免加载整个文件,然后将其反序列化到内存中。原因很简单,那就是更多的内存。我想这在PC上确实不是问题,但这是一个好习惯,在控制台上工作时至关重要。尽管我们不(当前)按照m_pGladiator的建议对对象进行序列化,但我们正在朝着这一方向努力。

First, if you are going to pack a bunch of resources into a single file (I call these packfiles), then I think that you should work to avoid loading the whole file and then deseralizing out of that file into memory. The simple reason is that it's more memory. That's really not a problem on PC's I guess, but it's good practice, and it's essential when working on the console. While we don't (currently) serialize objects as m_pGladiator has suggested, we are moving towards that.

您可能有两种类型的打包文件。一个文件是您要任意访问文件内容的文件。第二种类型可能是文件的集合,在加载关卡时,您需要这些文件的 all 。一个基本的示例可能是:

There are two types of packfiles that you might have. One would be a file where you want arbitrary access to the contents of the files. A second type might be a collection of files where you need all of those files when loading a level. A basic example might be:


  1. 音频包文件可能包含游戏中的所有音频。您可能只需要为菜单或界面屏幕加载某些类型的音频,为级别加载不同的音频集。

  2. 属于第二类的类型可能是某个级别的所有模型/纹理/等。您基本上想在加载时将此文件的全部内容加载到游戏中,因为在玩家玩该关卡或分区时,您(可能)需要所有文件的内容。

我们构建的许多packfile都属于第二类。我们基本上打包了关卡内容,然后使用zlib之类的文件对其进行压缩。当我们在游戏时加载其中一个文件时,我们会读取少量文件,将读取的文件解压缩到内存缓冲区中,然后重复进行直到将整个文件读入内存。我们读入的缓冲区相对较小,而最终目标缓冲区足够大,可以容纳我们所需的最大未压缩数据集。这种方法很棘手,但同样,它节省了RAM,这是一个有趣的练习,而且由于您是系统资源的好管家,您会感到内心温暖。打包文件完全解压缩到目的地缓冲区后,我们将对该缓冲区进行最后一次遍历以修复指针位置等。仅当您将打包文件写成游戏知道的结构时,此方法才有效。换句话说,我们的packfile编写工具与游戏代码共享结构(或类)。我们基本上是在写出并压缩数据结构的精确表示形式。

many of the packfiles that we build fall into the second category. We basically package up the level contents, and then compresses them with something like zlib. When we load one of these at game time, we read a small amount of the file, uncompress what we've read into a memory buffer, and then repeat until the full file has been read into memory. The buffer we read into is relatively small while final destination buffer is large enough to hold the largest set of uncompressed data that we need. This method is tricky, but again, it saves on RAM, it's an interesting exercise to get working, and you feel all nice and warm inside because you are being a good steward of system resources. once the packfile has been completely uncompressed into it's destinatino buffer, we run a final pass on the buffer to fix up pointer locations, etc. This method only works when you write out your packfile as structures that the game knows. In other words, our packfile writing tools share struct (or classses) with the game code. We are basically writing out and compressing exact representations of data structures.

如果您只是想减少要在用户机器上运输和安装的文件数量,您可以使用类似我描述的第一种packfile的方法进行处理。也许您有1000多个纹理,只是想减少压缩和打包的文件数量。您可以编写一个小的实用程序,基本上可以读取要打包在一起的文件,然后在包文件中写一个包含文件及其偏移量的标头,然后可以一次写入一个文件的内容,另一个,在您的大二进制文件中。在游戏时,您可以简单地加载此packfile的标头并将文件名和偏移量存储在哈希中。当您需要读取文件时,可以对文件名进行哈希处理,以查看文件名是否存在于packfile中,如果存在,则可以通过查找偏移量然后从packfile中的该位置直接从packfile中读取内容。同样,此方法基本上是不考虑加密等将数据打包在一起的一种方法。它只是一种组织方法。

If you simply want to cut down on the number of files that you are shipping and installing on a users machine, you can do with something like the first kind of packfile that I describe. Maybe you have 1000s of textures and would just simply like to cut down on the sheer number of files that you have to zip up and package. You can write a small utility that will basically read the files that you want to package together and then write a header containing the files and their offsets in the packfile, and then you can write the contents of the file, one at a time, one after the other, in your large binary file. At game time, you can simply load the header of this packfile and store the filenames and offsets in a hash. When you need to read a file, you can hash the filename and see if it exists in your packfile, and if so, you can read the contents directly from the packfile by seeking to the offset and then reading from that location in the packfile. Again, this method is basically a way to pack data together without regards for encryption, etc. It's simply an organizational method.

但是,我再次强调一下,如果如果您按照我或m_pGladiator建议的方式进行操作,则我将尽力避免将整个文件拉入RAM,然后反序列化到RAM中的另一个位置。那是浪费资源(您可能有很多)。我想说,您可以先执行此操作以使其正常运行,然后再运行一次只能读取一部分文件然后解压缩到目标缓冲区的方法。您必须使用一个像这样工作的强制方案。 zlib和lzw都可以(我相信)。我不确定要使用MD5算法。

But again, I do want to stress that if you are going a route like I or m_pGladiator suggests, I would work hard to not have to pull the whole file into RAM and then deserialize to another location in RAM. That's a waste of resources (that you perhaps have plenty of). I would say that you can do this to get it working, and then once it's working, you can work on a method that only reads part of the file at a time and then decompresses to your destination buffer. You must use a comprsesion scheme that will work like this though. zlib and lzw both do (I believe). I'm not sure about an MD5 algorithm.

希望这会有所帮助。

这篇关于将资源合并为一个二进制文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆