Captain Comic Map Format
Format type | Map/level |
---|---|
Map type | 2D tile-based |
Layer count | 1 |
Tile size (pixels) | 16×16 |
Viewport (pixels) | 192×160 |
Games |
The Captain Comic Map Format stores the playable game levels. Each level is stored in a separate file in the game directory, using the .PT filename extension.
The files only store the map background layer. The player start position can be changed by editing the executable file.
File format
The file consists of a width, height and then a list of tiles.
Signature
There is no signature, however careful processing of the header can be used to check whether the width and height correctly describe the file size. This could be confused with an image file however, so some other checks will be required (such as the absence of certain unused byte values, perhaps.)
Header
Each file begins with the following header.
Data type | Description |
---|---|
UINT16LE width | Width of map, in number of tiles |
UINT16LE height | Height of map, in number of tiles |
The map data follows immediately, with one byte for each tile, left-to-right and top-to-bottom. The total size of this section is the map width multiplied by the map height.
All maps are 128x10 tiles. Although the header uses UINT16LEs to store width and height, internally the game engine uses UINT8s, and the maximum width and height are hardcoded, so maps of different dimensions will not work properly.
Map codes
Map codes are direct indices into the tileset. So a map code of 0x01 means the second tile in the tileset should be drawn at that location. The tileset to use is matched up by filename (FOREST.TT2 provides the tiles for FOREST[0-2].PT, for example.)
Executable file
There is additional map data hard-coded in the game's main .exe file. The .exe file is lightly compressed with Microsoft_ EXEPACK. Working with an unpacked .exe is necessary for full control over the map data. The size of unpacked .exe assumed here is 82672.
At offset 63456 (0xF7E0) is a block of 1664 bytes containing the remaining level-related data. There are 8 blocks of 208 bytes, one for each level, 'level' meaning the complete regions - forest, lake, etc., and 'PT' for the three separate parts comprising the level.
Data type | Name | Description |
---|---|---|
char[14] | tilesetFilename | .tt2 filename |
char[14] | pt1Filename | First .pt filename |
char[14] | pt2Filename | Second .pt filename |
char[14] | pt3Filename | Third .pt filename |
UINT8[4] | doorTiles | Tileset indices of the four tiles used for drawing doors: top left, top right,
bottom left, bottom right. These are used to animate the doors. |
All filenames are 13 bytes long, padded with spaces, followed by a null terminator byte.
After this are four entries for the SHP files associated with the level. Each entry is of this form:
Data type | Name | Description |
---|---|---|
UINT8 | frameCount | Number of frames in the SHP file's animation |
UINT8 | spriteCount | Number of sprites (e.g. facing left, facing right, etc.) |
UINT8 | unknown | ! Unknown; always 0 or 1 |
char[14] | shapeFilename | SHP filename, null-terminated |
Note that multiplying number of frames by number of sprites by 160 (the number of bytes per frame), you do indeed get the total size of the shape file.
Finally there are three blocks of 25 bytes, one corresponding to each PT:
Data type | Name | Description |
---|---|---|
UINT8 | itemType | Item type. 0=corkscrew, 1=key, 2=boots, 3=lantern, 4=teleport wand, 5=gems, 6=crown, 7=gold, 8=cola, 14=shield |
UINT8 | itemY | Item coordinate (max 18) |
UINT8 | itemX | Item coordinate (max 255; the PT is 128 tiles wide, but the player can stand halfway between tiles) |
UINT8 | exitL | Exit behaviour. exitL controls what happens on walking off the left side of the PT, exitR controls the right. The values can be 0, 1, 2, giving the PT to load, or 255, meaning no PT change occurs. |
UINT8 | exitR | |
DOOR[3] | door | Door data for up to three doors in the level (see below) |
ENEMY[4] | enemy | Enemy data for up to four enemies (see below) |
This means there can be only one item or powerup per PT. The itemType is an index into the bitmaps found earlier in the EXE. (Not offsets; they just follow the same sequence.) (Slots between cola and shield (9-13) are for the five stages of the cola powerup display.)
DOOR is described as:
Data type | Name | Description |
---|---|---|
UINT8 | doorY | Y-coordinate of the door |
UINT8 | doorX | X-coordinate of the door |
UINT8 | targetLevel | Target level (0-7, as an index into the overall dataset described on this page) |
UINT8 | targetPT | The target PT (0-2) |
Empty/unused door slots are FF FF 00 00.
ENEMY is described as:
Data type | Name | Description |
---|---|---|
UINT8 | shape | Enemy's sprite, as an index into the level's SHP data (see above) |
UINT8 | behaviour | Enemy behaviour. behaviour & 0x7f has these effects: 1=enemy bounces around the walls 2=the enemy approaches then bounces side to side 3=the enemy chases along the ground 4=the enemy dives to head height then chases 5=the enemy sporadically dives to head height 127=no enemy spawns in this slot (this restricts the maximum simultaneous enemies) If the high bit (=128) is set, the enemy moves at high speed. |
After a padding of five null bytes, data for the next level begins.
To control the player's position when the game loads, two separate edits of the unpacked .exe are needed: two bytes at 0x265E give the starting level (0..7) and starting PT (0..2), with default values 01 00. The player's starting coordinates are given by two bytes at 0x96C3: y (0..17), x (0..255), default values 0C 0E.
Tools
The following tools are able to work with files in this format.
Name | Platform | View? | Create new? | Modify? | Access hidden data? | Edit metadata? | Notes |
---|---|---|---|---|---|---|---|
Camoto | Linux/Windows | Yes | Yes | Yes | N/A | N/A |
Credits
This file format was reverse engineered by Malvineous. The .exe file data was reverse-engineered by Ceidwad. 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!)