CAT Format (MPS Labs)

From ModdingWiki
Jump to navigation Jump to search
CAT Format (MPS Labs)
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?Yes
Games

MPS Labs's Catalog format is used in several of their games to store multiple files in a single archive. The files do not have a signature, but they typically have a *.CAT extension. There are two known versions of the format which are very similar. They consist of a header to know how many files there will be, a file allocation table, and the file data.

File Formats

Version 1

The file begins with a header which contains the size of the file allocation table. From this, you can derive the number of files. After that, there is the FAT, then the file data. Only M1 Tank Platoon uses this format.

Header

Data Type Name Description
UINT16LE FAT Size Size of the FAT. Divide by 18 (width of a file record) to get the total number of files.

File Record

Data Type Name Description
char[12] File Name The file name in 8.3 format, padded right with nulls.
UINT32LE File Offset The position in the archive where the file begins.
UINT16LE File Size Length of the file.

Version 2

The file begins with the header which contains the number of files found in the archive, and then has a file record for each file, followed by the data payload.

Header

Data Type Name Description
UINT16LE File Count Number of files stored in the archive.

File Record

Data Type Name Description
char[12] File Name The file name in 8.3 format, padded right with nulls.
UINT16LE File Time DOS packed file time.
UINT16LE File Date DOS packed file date.
UINT32LE File Size Length of the file.
UINT32LE File Offset The position in the archive where the file begins.

Tools

The following tools are able to work with files in this format.

Name PlatformExtract files? Decompress on extract? Create new? Modify? Compress on insert? Access hidden data? Edit metadata? Notes
Librarian WindowsYesN/AYesYesN/ANoYes Stores and extracts 'last modified' date on v2 archives.

Source Code

Version 1 Extractor

Open "M1.CAT" For Binary As #1

Dim As UShort HeaderSize, FileCount

' Get the header size.
Get #1, , HeaderSize

FileCount = HeaderSize / 18		' Each record in the FAT is 18 bytes.

Print "Files: "; FileCount

Dim As String FileName(FileCount)
Dim As ULong FileOffset(FileCount)
Dim As UShort FileSize(FileCount)
Dim As Integer FileNo

For FileNo = 1 To FileCount
	' Load 12 bytes for the file name.
	FileName(FileNo) = Space(12)
	Get #1, , FileName(FileNo)
	
	' Trim off the null padding.
	FileName(FileNo) = Left(FileName(FileNo), InStr(FileName(FileNo), Chr(0)))

	' 4 bytes for the file offset.
	Get #1, , FileOffset(FileNo)

	' 2 bytes for the file size.
	Get #1, , FileSize(FileNo)
Next FileNo

Dim As String FileContents

For FileNo = 1 To FileCount
	Print "File #: "; FileNo
	Print "File Name: "; FileName(FileNo)
	Print "File Offset: "; FileOffset(FileNo)
	Print "File Size: "; FileSize(FileNo)

	' Just to the start of this file.
	Get #1, FileOffset(FileNo), ""
	
	' Prepare a buffer for the contents of the file.
	FileContents = Space(FileSize(FileNo))
	
	' Read the entire file into memory.
	Get #1, , FileContents
	
	' Write the file to disk with the proper name.
	Open FileName(FileNo) For Binary As #2
	Put #2, , FileContents
	Close #2
Next FileNo

Sleep

Version 2 Extractor

Open "C00C.CAT" For Binary As #1

Dim As UShort FileCount

' Get the file count from the header.
Get #1, , FileCount

Print "Total Files: "; FileCount

Dim As String FileName(FileCount)
Dim As UShort DOSTime(FileCount)
Dim As UShort DOSDate(FileCount)
Dim As ULong FileSize(FileCount)
Dim As ULong FileOffset(FileCount)
Dim As Integer FileNo

' Load the File Allocation Table.
For FileNo = 1 To FileCount
	' Load 12 bytes for the file name.
	FileName(FileNo) = Space(12)
	Get #1, , FileName(FileNo)
	
	' Trim off the null padding.
	FileName(FileNo) = Left(FileName(FileNo), InStr(FileName(FileNo), Chr(0)))

	' 2 bytes for the DOS Time.
	Get #1, , DOSTime(FileNo)

	' 2 bytes for the DOS Date.
	Get #1, , DOSDate(FileNo)

	' 4 bytes for the file size.
	Get #1, , FileSize(FileNo)

	' 4 bytes for the file offset.
	Get #1, , FileOffset(FileNo)
Next FileNo

Dim As String FileContents

' Extract the files.
For FileNo = 1 To FileCount
	Print "File #: "; FileNo
	Print "File Name: "; FileName(FileNo)
	Print "File Time: "; DOSTime(FileNo)   ' Not converted.
	Print "File Date: "; DOSDate(FileNo)   ' Not converted.
	Print "File Offset: "; FileOffset(FileNo)
	Print "File Size: "; FileSize(FileNo)

	' Just to the start of this file.
	Get #1, FileOffset(FileNo), ""
	
	' Prepare a buffer for the contents of the file.
	FileContents = Space(FileSize(FileNo))
	
	' Read the entire file into memory.
	Get #1, , FileContents
	
	' Write the file to disk with the proper name.
	Open FileName(FileNo) For Binary As #2
	Put #2, , FileContents
	Close #2
Next FileNo

Sleep

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