LIB Format (Electronic Arts)

From ModdingWiki
Jump to navigation Jump to search
LIB Format (Electronic Arts)
Format typeArchive
Max files65,536
File Allocation Table (FAT)Beginning
Filenames?Yes, 8.3
Metadata?None
Supports compression?No
Supports encryption?No
Supports subdirectories?No
Hidden data?No
Games

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.

File format

Signature

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.

Data type Description
char cSignature[5] "EALIB".
UINT16LE iFileCount Number of files.

The signature is followed immediately by a file entry structure, repeated iFileCount times.

File Entry

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.

Data type Description
char cFilename[13] 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.


Source Code

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

Tools

Credits

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!)