<br><br><div><span class="gmail_quote">On 2/19/08, <b class="gmail_sendername">Andre de Leiradella</b> <<a href="mailto:leiradella@bigfoot.com">leiradella@bigfoot.com</a>> wrote:</span><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
Hi All,<br> <br> I'm designing a resource file format to hold game data (scripts, images,<br> musics, sound effects etc.) and would like some input from the community.<br> <br> First, why another resource file? Because I want two things other<br>
 resource files don't offer (at least that I'm aware of):<br> <br> A. Fast access through mmap (the file can be mmapped to the process<br> address space and used with very little setup)</blockquote><div><br>Well, mmap is a bit faster than reading/writing a file. I'm rather fond of it myself. Not to mention that having the data in a binary format is very nice. Do remember that addresses may not stay meaningful when mmaped into memory. The worst case is when they do stay meaningful on your machine, and on some other machines, but are not meaningful on every machine. This can lead you to putting addresses into the file and then having to redo everything so that you store offsets.<br>
<br></div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"> B. Spare space where I could insert the digital signature of the file.<br> This space must be filled with zeroes while computing the hash for the<br>
 signature.</blockquote><div><br>That isn't really a big deal, you can always create a zeroed out item in any resource file that can be used to store the signature after it is computed. Even better, you can just put the signature in a wrapper so that you don't actually change the signature of the file by adding the signature to the file. A simple header consisting of the length of the signature followed by the signature can be prepended to the file to sign it. Or, even simpler, you can just append the signature to the file and never care about the format.<br>
</div><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"> The preliminary version is working quite well. Data is accessed by name<br> (char *), with a reader that supports basic data input operations being<br>
 returned. Since the file is mmaped, the location of a given chunk of<br> data within the file is quickly found via a bsearch call. Data can be<br> stored without compression (good for mp3, ogg, jpeg...) or bzipped. The<br>
 resource file can even be part of another file, the most common use<br> being to append the resource file to an executable.<br> <br> There is also support for transparently using a directory instead of a<br> real resource file just like zziplib, and reading entries via SDL_RWops.<br>
 <br> So my questions are:<br> <br> 1. Is there any thing bad about mmapping a resource file? The file size<br> can easily be greater than 4 GiB.</blockquote><div><br>Well, by allowing your file to be so large you restrict yourself to 64 bit architectures. In general  32 bit machines can not address more than 4 gigs of process space. In reality they can rarely address more than 2 gigs of process space. If you don't care about 32 bit machines then there is really nothing wrong with what you are doing. Just remember that your addresses and offsets need to be 64 bits. </div>
<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"> 2. Are there other resource file formats that provide A and B above?</blockquote><div><br>
Well, your "A" requirement is a requirement of the implementation of the access library and has absolutely nothing to do with the file format. So basically all and/or no file format gives you that. You could take any existing file format and create a library for accessing it that uses mmap. If you look deep down in the file code for your favorite compiler you might find that ti already uses mmap to implement read and write in which case all libraries have this feature. <br>
<br> And your "B" requirement can be met by simply appending the signature to an existing file or by writing it to a different file, so pretty much all other file formats meet this requirement.<br></div><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
 3. Are there other important characteristics for a resource file format<br> I'm missing?<br></blockquote><div><br>That it is available right now and  you don't have to write it from scratch?<br></div><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
 4. Do you have requirements for a new resource file?</blockquote><div><br>No. </div><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"> The exposed interface so far is:</blockquote>
<div><br>Hmmm, you aren't being consistent about the use of uint32_t and int. The interface as written may blow up if you try to do arithmetic on offsets or lengths because you are mixing unsigned and signed integers for lengths and offsets. It depends on whether the "int" variables are 32 bits or 64 bits. <br>
<br>Above you mentioned that the file size can easily be bigger than 4 gigs but you seem to only have 32 bits of offset in this format which restricts you to <= 4 gigs. You need to changes this interface to use 64 bit offsets.<br>
<br>Bob Pendleton<br> </div><br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;"> --------------------8<--------------------<br> /* Seek modes. */<br>
 #define AF_SEEK_SET    0<br> #define AF_SEEK_CUR    1<br> #define AF_SEEK_END    2<br> <br> /* The opaque file type. */<br> struct af_file_t;<br> typedef struct af_file_t af_file_t;<br> <br> /* The opaque reader type. */<br>
 struct af_reader_t;<br> typedef struct af_reader_t af_reader_t;<br> <br> /* The callback type used to return the address of needed functions,<br>   i.e. BZ2_bzDecompress and friends. This allow the application<br>   to statically link support libraries as bzip2 or dinamically load them<br>
   from anywhere in the file system. */<br> typedef void *(*af_dynamic_link_t)(const char *library_name, const char<br> *function_name);<br> <br> /* Information filled by af_entry_get_info and af_iterate. */<br> typedef struct {<br>
    const char *name;<br>    uint8_t compression[4];<br>    uint32_t compressed_size;<br>    uint32_t uncompressed_size;<br>    const void *data;<br> } af_entry_info_t;<br> <br> /* Sets the callback for the load of support libraries. */<br>
 void af_set_dynamic_link_callback(af_dynamic_link_t call_back);<br> <br> /* Opens the resource file, possibly with an offset from the<br>   beginning of the named file. Size defaults to the number<br>   of bytes left in the file starting at offset, but can be specified<br>
   if the resource file is embedded in the middle of some<br>   other file. */<br> af_file_t *af_open(const char *name, uint32_t offset, uint32_t size);<br> <br> /* Closes the resource file, freeing all allocated resources. */<br>
 void af_close(af_file_t *file);<br> <br> /* Calls the process callback for all entries in the resource file. */<br> int af_iterate(af_file_t *file, int (*process)(af_entry_info_t *info,<br> void *udata), void *udata);<br>
 <br> /* Opens an entry for reading. */<br> af_reader_t *af_entry_open(af_file_t *file, const char *name);<br> <br> /* Reads size bytes into buffer. */<br> int af_entry_read(af_reader_t *reader, void *buffer, int size);<br>
 <br> /* Changes the location of the next read operation. */<br> int af_entry_seek(af_reader_t *reader, int offset, int whence);<br> <br> /* Closes the reader, freeing all allocated resources. */<br> int af_entry_close(af_reader_t *reader);<br>
 <br> /* Returns the current position within the entry. */<br> int af_entry_tell(af_reader_t *reader);<br> <br> /* Returns information of the entry associated with the reader. */<br> int af_entry_get_info(af_file_t *file, af_entry_info_t *info, const char<br>
 *name);<br> --------------------8<--------------------<br> <br> Cheers,<br> <br> Andre<br> _______________________________________________<br> SDL mailing list<br> <a href="mailto:SDL@lists.libsdl.org">SDL@lists.libsdl.org</a><br>
 <a href="http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org">http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org</a><br> </blockquote></div><br>