The file systems used on consoles are rather simple, which has some implications. For example, simply opening and closing files takes a lot more time than you first might realize. When there are too many files in a folder, we need extra seeks to read file table data. There are hard limits on the number of files in a folder and the length of filenames. We want to allow artists and level designers to organize their data in a logical way, and we want to be able to quickly find data during development. However, even changing the folder being read from will cause an implicit seek. Checking if a file exists or a file's size may also cause an implicit seek.
Our solution to the overhead of handling files is to have a simple, platform independent game file system. All files are combined into several large archive files, and these files are kept open at all time. When the archive files are created, we hash filenames and store the hash. The archive file's table of contents is always kept in memory and contains the hashed filenames, the archive file handle, offsets of the files in the archive and the sizes of the files in the archive.
Since we have all archive files open at all time, we never need to use the expensive open/close system calls. As we always have the table of contents in memory, we can quickly return the size of every file. As all file request are simply seeks inside the already opened archive files, we do not cause extra seeks when we change to read from another directory.