LIB Format (Electronic Arts)
|File Allocation Table (FAT)||Beginning|
Electronic Arts's LIB Format is a simple group file which 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. The format was used from 1990 to 1994 in at least 7 games. Various development teams used the format, although most of them were produced by Paul Grace, including the first game to use it.
There is a modified version of the format used by Mythos Software, one of EA's developers. This version may have been implemented by Scott Cronce, a programmer involved in the original format.
LIB files begin with "EALIB", then the number of files in the archive. You actually have to read one more file than the header suggests, as there is an empty file at the end used for a file size calculation.
|UINT16LE iFileCount||Number of files.|
The signature is followed immediately by a file entry structure, repeated iFileCount 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 cFilename||File name (8.3 style), padded with nulls to 12 characters, and null terminated.|
|BYTE bOffsetBytes||I think this is the number of bytes needed to be read by the file's offset, however, every LIB files seems to use UINT32LE, so it seems unnecessary.|
|UINT32LE iOffset||File's offset in 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 FreeBASIC code will extract all of the files from the LIB file into a folder named after the LIB file you specify.
' Specify the Electronic Arts LIB file here: Dim As String LibFileName = "imm1.lib" Open LibFileName For Binary As #1 Print "Reading header..." ' Verify the format's magic word. Dim As String MagicWord = Space(5) Get #1, , MagicWord If MagicWord <> "EALIB" Then Print "Not an Electronic Arts .LIB file." End End If ' Header Structure 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 Bytes As UByte Dim As UShort FileNo For FileNo = 1 To NumberOfFiles FileName(FileNo) = Space(13) ' Get the 8.3 file name, padded with nulls, and null terminating. Get #1, , FileName(FileNo) FileName(FileNo) = Left(FileName(FileNo), InStr(FileName(FileNo), Chr(0)) - 1) ' Get the length (in bytes) of the file start values (not sure if that's what this is, seems to always be 0x04). Get #1, , Bytes ' Get the file start offset. 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!)