# VBForums UtilityBank > UtilityBank - Tutorials >  Tutorial - Resource File

## cyborg

I've seen a few people asking about how to create resource files for their games etc.
Instead of answering all of them, I desided to make a tutorial on the subject.

The first thing you need to know when creating a file format (a resource file in this case) is what to put in it, and where to put it.
I've created a rather simple format which can store any sort of file in binary mode. The layout is made up of three sections: header, dir, and data.
The header contains information about the resource file itself. The dir part contains info about each seperate file stored in the resource file. The data section contains the data from all files stored.

*Header:*
ID
Version
FileCount

ID contains a string that is 4 bytes long. It identifies the file, so that you know what format you have loaded in your app.
Version contains the version of the format. In case you need to improve the format in a later program/game version you will need to make your program know what load function to run at different versions of the format.
FileCount stores the number of files that are loaded in the resource file.

*Dir:*
FileName
FileSize

Dir is an array that have one instance for each file.
FileName stores the name of each particular file (not the whole path though). It is locked at 64 characters in this case, so you cannot have longer filenames than that.
FileSize stores the exact size (in bytes) of each file.

*Data:*
Data

The data section only contains the information inside each file. All files are stacked upon each other.

This is how the file will look like. Now we can head on to the coding.

It is probably a good idea to start making UDTs (User Defined Types) for each section of the file. Based on the info above, they will look like this:


VB Code:
Private Type HeaderUDT
    ID As String * 4        'the FourCC (holds a string to identify what filetype it is)
    Version As Integer      'version number
    FileCount As Long       'how many files are in the pack
End Type
 Private Type DirUDT
    FileName As String * 64 'name of each file. 64 characters long
    FileSize As Long        'size of each file
End Type
 Private Type DataUDT
    Data() As Byte          'the files themselves
End Type

Now we also need a UDT for the file itself.


VB Code:
Private Type ResourceFileUDT
    Header As HeaderUDT         'the header information for the resource file
    Dir() As DirUDT             'array of file information
    FileData() As DataUDT       'array of file data
End Type
 Public ResourceFile As ResourceFileUDT  'everything is held in this valiable

I've made the file public, so any data can be reached from any module/class/form or whatever.

What's left now is to create functions that can load/add/export etc.
I will start of by explaining the NewFile function.

VB Code:
Public Sub NewFile()
    'set the basic header information for a empty resource file
    With ResourceFile
        .Header.ID = "RESF"     'i chose this fourCC, but you can use whatever you want for your filetype
        .Header.Version = 1     '1st version
        .Header.FileCount = 0   'no files in it yet
        ReDim .Dir(0)           'create empty array
        ReDim .FileData(0)
    End With
End Sub
This will put the information needed in the header and also reset the arrays.

The next function is AddFile. It will add an external file into the resource file.

VB Code:
Public Sub AddFile(FileName As String)
    With ResourceFile
        .Header.FileCount = .Header.FileCount + 1   'filecount is increased by one.
        
        ReDim Preserve .Dir(.Header.FileCount - 1)  'extend the arrays to hold another element (minus one because we want it zero-based)
        ReDim Preserve .FileData(.Header.FileCount - 1)
        
        .Dir(.Header.FileCount - 1).FileName = FormatFileName(FileName) 'get the filename without the directory path
        
        Open FileName For Binary As #1  'open the file for binary input
            .Dir(.Header.FileCount - 1).FileSize = LOF(1) 'get the size of the file
            ReDim .FileData(.Header.FileCount - 1).Data(LOF(1) - 1) 'redimention the data array (zero based)
            
            Get 1, 1, .FileData(.Header.FileCount - 1).Data() 'read the data to the array
        Close #1
    End With
End Sub

First I add one to the FileCount value to tell that we've added a file.
The next thing I do is to resize the arrays to be able to hold the new file.
Then I call a function called FormatFileName. I will explain that function in a minute.
Now all that's left to do is to open the file, get its filesize using LOF, and store the data.

The FormatFileName function removes the path and only returns the name of the file. Like this:

VB Code:
Private Function FormatFileName(FileName As String) As String
    Dim i As Long
    
    'step through the filename backwards until we hit a '\' or '/'
    For i = Len(FileName) To 1 Step -1
        If Mid(FileName, i, 1) = "/" Or Mid(FileName, i, 1) = "\" Then Exit For
    Next
    
    'return the filename
    FormatFileName = Mid(FileName, i + 1, Len(FileName) - i)
End Function
It searches for the last "/" or "\" and then gets the rest of the string.

Now that we can add file, we would also like to be able to export them.

VB Code:
Public Sub ExportFile(Index As Long, FileName As String)
    'index should point to the element in the directory array to the file you want to export
    'filename should be whatever you want to name the exported file
    Open FileName For Binary As #1 'open the new file
        Put #1, , ResourceFile.FileData(Index).Data 'write the data to it
    Close #1
End Sub
Don't think this needs much explanation... It just puts the data into a file.

Now on to the really important things - Saving the resource file.

VB Code:
Public Function SaveFile(FileName As String) As Boolean
    'save the entire resource file
    'returns true on success
    Dim i As Long
    
    Open FileName For Binary As #1 'open the filename
        With ResourceFile
            'check to see that the values are correct, and that we dont try to save an empty file
            If .Header.ID <> "RESF" Then GoTo SaveError
            If .Header.Version <> 1 Then GoTo SaveError
            If .Header.FileCount < 1 Then GoTo SaveError
            Put #1, , .Header   'write data in correct order
            Put #1, , .Dir
            For i = 0 To .Header.FileCount - 1
                Put #1, , .FileData(i).Data 'stack the data from each file
            Next
        End With
    Close #1
    SaveFile = True
    Exit Function
    
SaveError:
    SaveFile = False
End Function
It will start off by checking that all the header values are correct, then save the header and the dir.
The it loops though the array of file data and saves all files on top of each other.


Loading the resource file is a bit harded (but not that much)...

VB Code:
Public Function LoadFile(FileName As String) As Boolean
    'load a resource file
    'returns true on success
    Dim i As Long
    Dim j As Long
    
    Open FileName For Binary As #1 'open the file
        With ResourceFile
            Get #1, , .Header 'read its header
            
            'check to see that this is in fact the correct file type
            If .Header.ID <> "RESF" Then GoTo LoadError
            'check to see if the version is correct
            If .Header.Version <> 1 Then GoTo LoadError
            'there must be files within the resource file
            If .Header.FileCount < 1 Then GoTo LoadError
            
            'redim the arrays to the correct amount
            ReDim .Dir(.Header.FileCount - 1)
            ReDim .FileData(.Header.FileCount - 1)
            
            For i = 0 To .Header.FileCount - 1
                Get #1, , .Dir(i) 'get the directory information for each file
            Next
            
            For j = 0 To .Header.FileCount - 1
                ReDim .FileData(j).Data(.Dir(j).FileSize - 1) 'redim the data array to correct size
                Get #1, , .FileData(j).Data 'read data to array
            Next
        End With
    Close #1
    LoadFile = True
    Exit Function
    
LoadError:
    LoadFile = False
End Function
Start by getting the header.
Then we need to check that we've loaded a valid file.
Next thing is to set the sizes of the arrays to match what we have in the header.
Then load the dir data and the file data.

Since we load everything in the same order as we stored it, we don't need to keep track on the offset of each file and dir.

I've also attached a finished module file containing all of these functions.

----------


## kingzl3y

Hey Cyborg,
Listen i dont mean to be a pain, but is there anychance you can add some commenting in the above code,
Becuase i think this is what im looking for, however im unsure how to use it :x
Thanx  :wave:   :Thumb: 

EDIT: I understand what you've wrote, but without the commenting im a noob  :Frown:   :Smilie:

----------

