Results 1 to 2 of 2

Thread: Tutorial - Resource File

  1. #1

    Thread Starter
    Frenzied Member cyborg's Avatar
    Join Date
    May 2000
    Location
    Sweden
    Posts
    1,755

    Tutorial - Resource File

    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:
    1. Private Type HeaderUDT
    2.     ID As String * 4        'the FourCC (holds a string to identify what filetype it is)
    3.     Version As Integer      'version number
    4.     FileCount As Long       'how many files are in the pack
    5. End Type
    6.  
    7. Private Type DirUDT
    8.     FileName As String * 64 'name of each file. 64 characters long
    9.     FileSize As Long        'size of each file
    10. End Type
    11.  
    12. Private Type DataUDT
    13.     Data() As Byte          'the files themselves
    14. End Type

    Now we also need a UDT for the file itself.

    VB Code:
    1. Private Type ResourceFileUDT
    2.     Header As HeaderUDT         'the header information for the resource file
    3.     Dir() As DirUDT             'array of file information
    4.     FileData() As DataUDT       'array of file data
    5. End Type
    6.  
    7. 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:
    1. Public Sub NewFile()
    2.     'set the basic header information for a empty resource file
    3.     With ResourceFile
    4.         .Header.ID = "RESF"     'i chose this fourCC, but you can use whatever you want for your filetype
    5.         .Header.Version = 1     '1st version
    6.         .Header.FileCount = 0   'no files in it yet
    7.         ReDim .Dir(0)           'create empty array
    8.         ReDim .FileData(0)
    9.     End With
    10. 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:
    1. Public Sub AddFile(FileName As String)
    2.     With ResourceFile
    3.         .Header.FileCount = .Header.FileCount + 1   'filecount is increased by one.
    4.        
    5.         ReDim Preserve .Dir(.Header.FileCount - 1)  'extend the arrays to hold another element (minus one because we want it zero-based)
    6.         ReDim Preserve .FileData(.Header.FileCount - 1)
    7.        
    8.         .Dir(.Header.FileCount - 1).FileName = FormatFileName(FileName) 'get the filename without the directory path
    9.        
    10.         Open FileName For Binary As #1  'open the file for binary input
    11.             .Dir(.Header.FileCount - 1).FileSize = LOF(1) 'get the size of the file
    12.             ReDim .FileData(.Header.FileCount - 1).Data(LOF(1) - 1) 'redimention the data array (zero based)
    13.            
    14.             Get 1, 1, .FileData(.Header.FileCount - 1).Data() 'read the data to the array
    15.         Close #1
    16.     End With
    17. 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:
    1. Private Function FormatFileName(FileName As String) As String
    2.     Dim i As Long
    3.    
    4.     'step through the filename backwards until we hit a '\' or '/'
    5.     For i = Len(FileName) To 1 Step -1
    6.         If Mid(FileName, i, 1) = "/" Or Mid(FileName, i, 1) = "\" Then Exit For
    7.     Next
    8.    
    9.     'return the filename
    10.     FormatFileName = Mid(FileName, i + 1, Len(FileName) - i)
    11. 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:
    1. Public Sub ExportFile(Index As Long, FileName As String)
    2.     'index should point to the element in the directory array to the file you want to export
    3.     'filename should be whatever you want to name the exported file
    4.     Open FileName For Binary As #1 'open the new file
    5.         Put #1, , ResourceFile.FileData(Index).Data 'write the data to it
    6.     Close #1
    7. 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:
    1. Public Function SaveFile(FileName As String) As Boolean
    2.     'save the entire resource file
    3.     'returns true on success
    4.     Dim i As Long
    5.    
    6.     Open FileName For Binary As #1 'open the filename
    7.         With ResourceFile
    8.             'check to see that the values are correct, and that we dont try to save an empty file
    9.             If .Header.ID <> "RESF" Then GoTo SaveError
    10.             If .Header.Version <> 1 Then GoTo SaveError
    11.             If .Header.FileCount < 1 Then GoTo SaveError
    12.             Put #1, , .Header   'write data in correct order
    13.             Put #1, , .Dir
    14.             For i = 0 To .Header.FileCount - 1
    15.                 Put #1, , .FileData(i).Data 'stack the data from each file
    16.             Next
    17.         End With
    18.     Close #1
    19.     SaveFile = True
    20.     Exit Function
    21.    
    22. SaveError:
    23.     SaveFile = False
    24. 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:
    1. Public Function LoadFile(FileName As String) As Boolean
    2.     'load a resource file
    3.     'returns true on success
    4.     Dim i As Long
    5.     Dim j As Long
    6.    
    7.     Open FileName For Binary As #1 'open the file
    8.         With ResourceFile
    9.             Get #1, , .Header 'read its header
    10.            
    11.             'check to see that this is in fact the correct file type
    12.             If .Header.ID <> "RESF" Then GoTo LoadError
    13.             'check to see if the version is correct
    14.             If .Header.Version <> 1 Then GoTo LoadError
    15.             'there must be files within the resource file
    16.             If .Header.FileCount < 1 Then GoTo LoadError
    17.            
    18.             'redim the arrays to the correct amount
    19.             ReDim .Dir(.Header.FileCount - 1)
    20.             ReDim .FileData(.Header.FileCount - 1)
    21.            
    22.             For i = 0 To .Header.FileCount - 1
    23.                 Get #1, , .Dir(i) 'get the directory information for each file
    24.             Next
    25.            
    26.             For j = 0 To .Header.FileCount - 1
    27.                 ReDim .FileData(j).Data(.Dir(j).FileSize - 1) 'redim the data array to correct size
    28.                 Get #1, , .FileData(j).Data 'read data to array
    29.             Next
    30.         End With
    31.     Close #1
    32.     LoadFile = True
    33.     Exit Function
    34.    
    35. LoadError:
    36.     LoadFile = False
    37. 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.
    Attached Files Attached Files
    Last edited by cyborg; Apr 20th, 2007 at 08:33 AM.

  2. #2
    Lively Member
    Join Date
    Apr 2007
    Location
    Tamworth, UK
    Posts
    82

    Re: Tutorial - Resource File

    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

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

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width