Protecting game assets?

BlitzMax Forums/BlitzMax Programming/Protecting game assets?

Bukky(Posted 2006) [#1]
How would one go about protecting their game assets when they launch a commercial game? For instance, is there a way to package my .OGG and .PNG files so that a user could not access or modify them?


Helios(Posted 2006) [#2]
Incbin?
Pak Files?
Encryption?


Bukky(Posted 2006) [#3]
Hey Helios,

Thanks for the speedy reply!

I will give Pak Files and Incbin a try.


Helios(Posted 2006) [#4]
Your welcome.


N(Posted 2006) [#5]
I use pak (well, sortof, it's a proprietary format based on the original Quake 1 pak format) files. I considered adding encryption to them, but really, what's the point? Any person dedicated enough could and 99% of the time would find a way to get the data. Pak files are more of a content management scheme than anything else -- lets me releases patches and stuff more efficiently.


ozak(Posted 2006) [#6]
Indeed. The original diablo had it's decryption code located, it's movies stripped and the indices into the packfile reallocated so the huge data file was only 50 megs without movies. So it's really not worth the trouble. You'd better off making a good regcode system :)


Bukky(Posted 2006) [#7]
Thank you all for the info.

Does anyone have any links for tutorials/utils (I found one util on this forum) for creating pak files and then using them in BlitzMax?

Also, as a bit of an aside, do any of you guys have any experience with companies such as TryMedia.com? Good? Bad? Alternatives?


Helios(Posted 2006) [#8]
Well creating pak files is relativly simple, basically what i do is i write out simple header infomation into the top of the pak file with the location/size/..etc of each files data and then i write out all the data of every file, so you end up with a file format sort of like this.

--------------
Header
- File 1
-- Size: 100
-- Location: HeaderSize+0
- File 2
-- Size: 200
-- Location: HeaderSize+100
- File 4
-- Size: 220
-- Location: HeaderSize+300
--------------

--------------
Data
-- File 1 Data (position would be HeaderSize+0)
-- File 2 Data (position would be HeaderSize+100)
-- File 3 Data (position would be HeaderSize+200)
--------------

Then when i load the pak file i mearly read in the header and use that infomation to grab the data of the file i want.

Hope you understood that, Im not exactly great at explaining things.


xlsior(Posted 2006) [#9]
Then when i load the pak file i mearly read in the header and use that infomation to grab the data of the file i want.


Of course, if you use a common file format like PNG, JPG, OGG, MP3, etc., people can still easily locate these headers and files in the container file as well, and strip them out... Unless you also encrypt them first, but that has downsides too since you need to add unencryption to all your file loading routines... In the end, it's going to be a trade-off between 'security' and speed/flexibility.


N(Posted 2006) [#10]
As far as structure goes, mine looks like this:


What you do is first read the first four bytes and see if it matches the magic number (which is 'IPAK', but checking a number is easier). If it does, you proceed to read the first two numbers which are the offset into the file that the directories are stored at and the amount of directories in the pak respectively.

One you do that, you seek directly to the directory offset and read the directories until you get what you want (which is usually a specific file).

Directories are laid out as such:
- The number of characters in the directory name, which in BlitzMax would be this, basically:
Local length:Int = pak.ReadInt( )
Local bytes:Byte[length]
pak.ReadBytes( bytes, length*2 )
Local name$ = String.FromShorts( bytes, length*2 )

- The offset into the pak from the start of the file the file's data is at
- The uncompressed size of the data
- The compressed size of the data

You then check and see if the compressed size is equal to the uncompressed size. If it is, then the data is not compressed (the tool I wrote to make my pak files checks to see if the compressed version is larger than the uncompressed version just in case).

Then, simply put, you read the data at the given offset into a buffer as large as comSize.

If it is compressed, you create another buffer as large as outSize and decompress it using the outSize as the target size.

In BlitzMax, this would, basically, be:
Rem
previously defined:
    - comSize
    - outSize
    - offset
EndRem

Local dbuf@[comSize]
pak.Seek( offset )
pak.ReadBytes( dbuf, comSize )
If comSize <> outSize Then
    Local cbuf@[outSize]
    uncompress( cbuf, outSize, dbuf, comSize ) ' outSize typically will not be changed
    dbuf = cbuf
EndIf
' Do what you wanted to with the data (now in dbuf)


Obviously, if you were to use a format like this, you could strip compression from your tool and simply use uncompressed data. All a matter of whether or not you think it's worthwhile to have compression.


Bukky(Posted 2006) [#11]
Thanks all for the suggestions! I'll try some things out tomorrow.


popcade(Posted 2006) [#12]
You can try post-packing tool like MoleBox
http://www.molebox.com/

Anyway I use it for compacting data to avoid obsolete files, not for security,you can still have a llok at it, compatible with Blitz Family.