TIM Resource Format
Format type | Archive |
---|---|
Max files | 65,535 |
File Allocation Table (FAT) | External + embedded |
Filenames? | Yes, 8.3 |
Metadata? | None |
Supports compression? | No |
Supports encryption? | No |
Supports subdirectories? | No |
Hidden data? | No |
Games |
The TIM Resource Format is used by The Incredible Machine to store much of the game data.
File format
The format comprised of multiple files. The index file is a .MAP file which stores the offsets of each subfile. The subfile data is split between a number of real files, and the .MAP file also provides the filenames of these real files. In The Incredible Machine, the index file is called RESOURCE.MAP and the data files are RESOURCE.001 to RESOURCE.004.
In theory data can be read from the data files alone (without the .MAP file) however if the data is to be modified then the .MAP file will have to be updated with the new offsets.
Signature
There is no known signature, other than carefully reading the file structure and verifying it seems correct (e.g. offsets don't go past the end of the file.) The data filenames can also be read from the .MAP file and checked to see whether they exist in the current directory.
Structure
The .MAP file begins with a header:
Data type | Name | Description |
---|---|---|
BYTE[4] | hash_idx | Hash string indexes |
UINT16LE | fileCount | Number of data files |
Note that hash indexes are hardcoded in the game execuatable file as sequences 0, 1, 6, 7, but the actual .MAP file uses 0, 1, 5, 7 so the internal table will be overwritten with these new values.
This is then followed by a file structure, repeated fileCount times:
Data type | Name | Description |
---|---|---|
char[13] | filename | Filename of real data file (DOS 8.3, null terminated) |
UINT16LE | count | Number of file entries |
FILE_ENTRY[count] | entry | Actual file entries |
A single FILE_ENTRY is defined as:
Data type | Name | Description |
---|---|---|
INT32LE | hash | Filename hash (see below) |
UINT32LE | offset | Offset of file from start of data |
To read the subfile data, the filename must be read from the .MAP file (the filename field above) along with the offset. The file identified by filename must then be opened. It should be in the same directory as the .MAP file. Seeking to offset in this newly opened file will result in the file pointer being at the start of the subfile header:
Data type | Name | Description |
---|---|---|
char[13] | filename | Filename of subfile (DOS 8.3, null terminated) |
UINT32LE | len | Length of subfile data, in bytes |
BYTE[len] | content | Subfile content |
If the .MAP file is not being used, the data files simply consist of the above subfile header and data concatenated one after the other. Subfiles aren't split between real files, so each data file can be considered independent (with the exception that the .MAP file contains the offsets for all the subfiles across all the data files.)
The game search for required file (like VM.OVL) in the current folder and if it didn't there then it calc a hash from filename (0x564CF4C0 in this example) and search inside the .MAP file index.
Here is a hash routine for the filenames:
/*
input:
s - pointer to ASCIIZ filename string
idx - pointer to an array of 4 bytes (hash indexes)
return:
hash - filename hash
*/
int32_t tim_hash(char *s, uint8_t *idx) {
int32_t i, c;
int16_t isum, ixor;
isum = 0;
ixor = 0;
for (i = 0; s[i]; i++) {
c = toupper(s[i]);
isum += c;
ixor ^= c;
}
/* both types here MUST be int16_t */
isum *= ixor;
c = 0;
for (ixor = 0; ixor < 4; ixor++) {
c <<= 8;
/* can use only existing characters
("i" holds the string length now) */
if (i > idx[ixor]) {
c |= toupper(s[idx[ixor]]);
}
}
c += isum;
return(c);
}
/*
// this MUST be overwritten with the correct one from the .MAP file!
uint8_t idx[4] = {0, 1, 6, 7}; // 0, 1, 5, 7
// example of usage
printf("%08X\n", tim_hash("vm.ovl", idx));
*/
Bitmap Subfiles
See The Incredible Machine Image Format.
This is an example of PART23.BMP which is the smalles of the bitmap files. It contains one sprite which is 16x16 pixels in size.
If anyone knows the compression used in the SCN section, please let me know. The length of the compressed data is 127: https://cloud.githubusercontent.com/assets/1974959/25874475/03651bf0-3513-11e7-98bb-b3640c20fb6f.png
PART28.BMP, the second largest bitmap and only 16x15 px in size, contains 137 compressed bytes: https://cloud.githubusercontent.com/assets/1974959/25874624/9f622b10-3513-11e7-8f24-d66877c0ad84.png
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 |
---|---|---|---|---|---|---|---|---|---|
Camoto | Linux/Windows | Yes | N/A | Yes | Yes | N/A | N/A | N/A |
Credits
This file format was reverse engineered by Malvineous. 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!)