CAT Format (MPS Labs)
Format type | Archive |
Max files | 65,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.
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.
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 |
Platform | Extract files? |
Decompress on extract? |
Create new? |
Modify? |
Compress on insert? |
Access hidden data? |
Edit metadata? |
Notes |
Librarian |
Windows | Yes | N/A | Yes | Yes | N/A | No | Yes |
Stores and extracts 'last modified' date on v2 archives. |
Source Code
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
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!)