Upcoming Events
Unite 2010
11/10 - 11/12 @ Montréal, Canada

GDC China
12/5 - 12/7 @ Shanghai, China

Asia Game Show 2010
12/24 - 12/27  

GDC 2011
2/28 - 3/4 @ San Francisco, CA

More events...
Quick Stats
100 people currently visiting GDNet.
2406 articles in the reference section.

Help us fight cancer!
Join SETI Team GDNet!
Link to us Events 4 Gamers
Intel sponsors gamedev.net search:

Introduction

In this article I intend to demonstrate one way of organising all your game related media files in to a single "PAK" file. A couple of good reasons to do this would be for easier distribution of your application data and to apply a degree of protection to your individual files to stop them from being misused. This article is aimed at beginner to intermediate level game programmers but you should be au fait with C++ and concepts such as linked lists, which are used in the code.

The Format

The format of this PAK file will be quite simple. It will consist of an unencrypted file header, a file-table containing information on each file added to the PAK and then each actual file concatenated together at the end. The file-table and the included file's data will be encrypted. For the purposes of this article I will keep it simple and stick to using a Caesar cipher.

PAK File Header

File Table



Concatenated File Data


The PAK File Class

I think now would be a good time to introduce the PAK class I am going to use. It is shown below:

class CPakFile
{
private:
  // Private Variables
  char             m_szFolderPath[300];
  char             m_szPakName[300];				
  sPakHeader       m_Header;
  sFileTableEntry* m_FileTable;				

  // Private Functions
  BOOL  GenerateHFT();
  BOOL  WorkOutOffsets();	

public:
  CPakFile();
  ~CPakFile();		

  BOOL  CreatePak( char* Path, char* Output);
};

The first two variables m_szFolderPath and m_szPakName will be the absolute paths to a compilation folder and the location / filename of the PAK to be output. The compilation folder will just be a folder containing every file you want to add to the PAK collated together. These two values will be read in from edit boxes in the accompanying compile tool and passed to the Create() method. There is also a file header variable of type sPakHeader and the linked list file-table of type sFileTableEntry which are two structures I will look at below. On instantiation of this class, the constructor defaults the variables and then adds a blank dummy node to the head of the linked list file-table. To save space, I will just let you look at this in the accompanying source code. The other two private functions generate the header and the file table and then works out the individual file offsets for inside the PAK respectively. They are both called by the Create() method, which is currently the only public method.

The File Header

The file header for this PAK can be relatively simple. I am just going to use the following structure outlined below:

struct sPakHeader									
{
  char   szSignature[6];
  float  fVersion;
  DWORD  dwNumFTEntries;
  BOOL   bCipherAddition;
  BYTE   iCipherValue;
  char   szUniqueID[10];
  DWORD  dwReserved;
};

I feel that most of its contents are self-explanatory. The iCipherAddition variable just indicates whether the cipher value is added or subtracted from each BYTE sized element that is encrypted. For those of you who don't know, a Caesar cipher is where you transpose each value that is to be encrypted "left or right" by a certain, consistent value. As a quick example, the letter 'A' encrypted using a +3 Caesar cipher would become the letter 'D'. The dwNumFTEntries variable is the number of file table entries (the number of files) in the PAK.



The File Table

Contents
  The Format
  The File Table

  Source code
  Printable version
  Discuss this article