LIB Format (Mythos Software)
Mythos Software's LIB Format is very similar to the LIB format used by Electronic Arts, which is fitting since EA was the publisher for Mythos Software. It is efficient in the sense that it only stores file names and starting positions in the header, so file lengths must be inferred. It does not support compression. There are two versions of LIB files. An earlier version used in The Lost Files of Sherlock Holmes: The Case of the Serrated Scalpel, and a later version used in The Lost Files of Sherlock Holmes: Case of the Rose Tattoo. The second version has a different layout and has yet to be examined.
Version 1 LIB files begin with "LIB", then character 0x1A, then the number of files. You actually have to read one more file entry than the header suggests, as there is an empty file entry at the end of the list used for a file size calculation.
|char||cSignature||"LIB", plus 0x1A|
|UINT16LE||fileCount||Number of files|
The signature is followed immediately by a file entry structure, repeated fileCount times.
Each file entry consists of the file name and its offset in the file. Even though the file name is fixed-width, it appears to be null-terminated.
|char||filename||File name (8.3 style), padded with nulls to 13 characters|
|UINT32LE||offset||File's offset from the start of the LIB archive|
Each file's size must be calculated by subtracting it from the next file's offset. There is an additional null-named file at the end with an offset equal to the size of the file so you don't need any special code to get the final file's size. This entry is not included in fileCount in the header.
While no files appear to use this, it is possible to hide data after the list of file entries and before the first file.
As there is an extra file entry to hold the size of the archive file, it is also possible to hide data at the end of the file as long as it comes after the offset of the final null-named file entry.
Both these methods produce valid files where the hidden data would always be ignored.
The Music.lib group affixes 12 spaces to the beginning of each file. Although this may just be part of the music format, it is also affixed to the driver files. It is unknown why these spaces are in this lib group, but they do not show up in other lib files. Perhaps it was required for the sound engine?
The following tools are able to work with files in this format.
|Name||Platform||Extract files?||Decompress on extract?||Create new?||Modify?||Compress on insert?||Access hidden data?||Edit metadata?||Notes|
This FreeBASIC code will extract all of the files from the LIB file into a folder named after the LIB file you specify.
' Specify the Mythos Software LIB file here: Dim As String LibFileName = "music.lib" Open LibFileName For Binary As #1 Print "Reading header..." ' Verify the format's magic word. Dim As String MagicWord = Space(3) Get #1, , MagicWord If MagicWord <> "LIB" Then Print "Not a Mythos Software .LIB file." End End If ' Header Structure Dim As Byte Unknown1 Get #1, , Unknown1 Dim As UShort NumberOfFiles Get #1, , NumberOfFiles ' An additional entry is made which has an empty file name and stores the length of the LIB file as the starting offset. ' This is used to calculate the length of the last file without needing special code to determine it based on the file size. NumberOfFiles = NumberOfFiles + 1 Print "Valid LIB File." ' Load the header filenames and their offsets. Dim FileName(1 To NumberOfFiles) As String Dim FileStart(1 To NumberOfFiles) As UInteger Dim As UShort FileNo For FileNo = 1 To NumberOfFiles FileName(FileNo) = Space(13) Get #1, , FileName(FileNo) FileName(FileNo) = Left(FileName(FileNo), InStr(FileName(FileNo), Chr(0)) - 1) Get #1, , FileStart(FileNo) Next FileNo ' Extract the files. Print "Extracting..." Dim As String LibFolder = Left(LibFileName, InStr(LibFileName, ".") - 1) MkDir("./" + LibFolder) Dim As ULongInt FileLength For FileNo = 1 To (NumberOfFiles - 1) ' Skip the last file which is not a real file anyway. FileLength = FileStart(FileNo + 1) - FileStart(FileNo) Print " ./" + LibFolder + "/" + FileName(FileNo) + " - " + Str(FileLength) + " bytes" Dim FileContents(0 To (FileLength - 1)) As Byte Get #1, FileStart(FileNo) + 1, FileContents() Open ("./" + LibFolder + "/" + FileName(FileNo)) For Binary As #2 Put #2, , FileContents() Close #2 Next FileNo Close #1 Print : Print Str(NumberOfFiles - 1) + " file(s) extracted." Sleep
This archive format was reverse engineered by TheAlmightyGuru. If you find this information helpful in a project you're working on, please give credit where credit is due. (A link back to this wiki would be nice too!)