LBX Format
Format type | Archive |
---|---|
Max files | 252 |
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
- Master of Magic Real-Time Game Tweaker
- MoO2 Workshop contains a Windows utility which can extract from LBX files as well as work with Master of Orion II specific data elements.