LBX Format

From ModdingWiki
Jump to navigation Jump to search
LBX Format
Format typeArchive
Max files252
File Allocation Table (FAT)Beginning
Filenames?Sometimes, 8 w/desc
Metadata?None
Supports compression?No
Supports encryption?No
Supports subdirectories?No
Hidden data?Yes
Games

LBX is a container format created and use by the development company SimTex. It was first used in a used in a demo called Star Lords, which gave rise to Master of Orion. Later SimTex games also used the format: Master of Magic, Master of Orion 2, and 1830: Railroads & Robber Barons. The format usually contains multiple files, typically uncompressed. Though it uses a short integer to store the number of files in the header, there is only enough room to store 252 files in the offset area. It often doesn't store file names, or any reliable indication of what the contained files are for (the game is expected to know their purpose internally.) Therefore, while it is not overly difficult to pack or unpack an LBX archive, modding the game requires further knowledge of what each individual .LBX is supposed to contain.

Certain .LBX files in Master of Orion II are not actually .LBX archives, but rather renamed video files, so be sure to check the signature.

File format

The header of the format is as follows:

Offset Hex Data type Description
0 0x00 UINT16LE Number of files in archive
2 0x02 BYTE[4] Signature (AD FE 00 00)
6 0x06 UINT16LE Information about the contents
8 0x08 UINT32LE Offset to file (repeats for each file stored in the LBX)
(last offset) UINT32LE Offset to end of LBX

It is not unusual for there to be some rubbish data in between the header/index and the packaged data.

File names

File names and descriptions may or may not follow, and even if they do exist, there may not be as many as in the offset list. File names are fixed at 8 chars, null terminated, and descriptions are 22 chars, null terminated. File names begin at offset 512 (0x200 hex) and they will last until the first file starts:

Offset Hex Data type Description
0 0x00 BYTE[9] File name
A 0x0A BYTE[23] File description

Source Code

Extractor

This FreeBASIC program will extract all of the files from an LBX group, and intelligently adds file names if they exist.

#include "file.bi"

' Specify the SimTex LBX file here:
Dim As String LBXFileName = "portrait.lbx"

Open LBXFileName For Binary As #1

' Verify the format's magic word.
Dim As UShort FileCount
Dim As String MagicWord = Space(4)
Dim As UShort Info

Get #1, , FileCount
Get #1, , MagicWord
Get #1, , Info
If FileCount < 1 Then
    Print "Contains no files.": End
End If
If MagicWord <> Chr(173) + Chr(254) + Chr(0) + Chr(0) Then
    Print "Not a SimTex .LBX file.": End
End If

' Header Structure
Dim As ULong FileOffsets(1 To FileCount + 1)        ' +1 for the end of the file.
Dim As String FileNames(1 To FileCount + 1)
Dim As String FileDescriptions(1 To FileCount + 1)
Dim As UByte Nul
Dim As ULong File

' Load the offsets.
For File = 1 To FileCount
    Get #1, , FileOffsets(File)
Next File

' Set the last offset to the end of the file.
FileOffsets(FileCount + 1) = LOF(1)

' Jump to the start of the file names sections.
Seek #1, 513

' Load the file names and descriptions.
Dim As Byte EndofNames = 0
For File = 1 To FileCount
    ' In the LBX format, not every file has a name. It's not uncommon for there to be 6 files, but only two names. 
    ' Because of this, this trap prevents us from reading any further than the position of the first file.
    If 512 + (File * 32) > FileOffsets(1) Then          ' 512 is the start of the names/desc, 32 is their combined length.
        EndOfNames = 1
    End If
    
    If EndOfNames = 0 Then
        ' There are more names to read.
        FileNames(File) = Space(8)
        Get #1, , FileNames(File)
        
        Get #1, , Nul       ' Throw away the null-terminator.
    
        FileDescriptions(File) = Space(22)
        Get #1, , FileDescriptions(File)
    
        Get #1, , Nul       ' Throw away the null-terminator.
    Else
        ' We've reached the end of the names section, but there may be additional files, so give each a blank name.
        FileNames(File) = "Unnamed "
        FileDescriptions(File) = Space(22)
    End If
Next File

' Extract the files.
Print "Extracting from " + LBXFileName + "..."

Dim As String LBXFolder = Left(LBXFileName, InStr(LBXFileName, ".") - 1)
MkDir("./" + LBXFolder)

Dim As ULong FileLength
Dim As ULong Addition
Dim As String OutputFileName, BaseName

For File = 1 To FileCount
    ' Determine the length of the current file by subtracting the start of the file from the next file.
    FileLength = FileOffsets(File + 1) - FileOffsets(File)

    ' Get the base name of the file (LBX files often reuse names in the same path).
    BaseName = Trim(FileNames(File))
    If BaseName = "" Then
        BaseName = Trim(Str(File))
    EndIf

    Print Using "    ./\    \/\      \ - \                     \ - & bytes"; LBXFolder; BaseName; FileDescriptions(File); FileLength
    'Print "    ./" + LBXFolder + "/" + BaseName + " - " + FileDescriptions(File) + "  -  " + Str(FileLength) + " bytes"

    ' Read the file data from the LBX.
    Dim FileContents(0 To (FileLength - 1)) As Byte
    Get #1, FileOffsets(File) + 1, FileContents()

    ' Check for reusing the same file name.
    Addition = -1
    Do
        Addition = Addition + 1
        OutputFileName = "./" + LBXFolder + "/" + BaseName + IIf(Addition > 0, "-" + Str(Addition), "")
    Loop While FileExists(OutputFileName)

    ' Output the contents of the file 
    Open (OutputFileName) For Binary As #2
    Put #2, , FileContents()
    Close #2
Next File

Close #1
Print : Print Str(FileCount) + " file(s) extracted."

Credits

This group format was reverse engineered by SaxxonPike, and 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!)

External Links