Prehistorik Level Format
Format type | Map/level |
---|---|
Map type | 2D tile-based |
Layer count | 2 |
Tile size (pixels) | 16×16 |
Viewport (pixels) | 320×200 |
Games |
Prehistorik stores its level data inside the historik.exe file.
File format
The level information is stored in such an awkward way that it is practically unmoddable. Each level has its own (mostly copy-pasted) code routine with a lot of hardcoded behaviour. For example, level 1 is the only level with secret areas; the first one is at the jumping fish (screen 6, counted from the start, not using the in-game data screen number), and the second one at the third screen after landing; just left of a ladder leading down to water (screen 14, again, counted from the start). The wrap areas for those screens are hardcoded in the code routine for the first level. Other levels simply don't have this code, meaning any attempts to add secret screens to them is futile.
All the address location information provided below is for the floppy version. On the CD-ROM version (included in GoG/Steam release) the locations are offset but correlatable to the locations on the floppy version.
Location of the level routines in historik.exe file:
- Level1: 0x00013F9F
- Level3: 0x00014E52
- Level5: 0x0001567C
- Level7: 0x00017D2B
Each level screen is split into a few separate structures. Here are a few of them:
Level | Count | Heights (offs) | Sizes (offs) | Data (offs) |
---|---|---|---|---|
1 | 19 | 0x00021668 | 0x00021A06 | 0x00021A2E |
3 | 19 | 0x000216C6 | 0x0002333A | 0x00023362 |
5 | 19 | 0x00021738 | 0x000247BA | 0x000247E0 |
7 | 19 | 0x000219AE | 0x000257C6 | 0x000257EE |
Each screen is an independent list of objects, starting at (0, 0) as the top-left corner of the screen. At Data offset located Count screens with Sizes+1 records (xPos, yPos, type) each.
Note that Height and Sizes are actually UINT16LE lists of Count items and Height is a level height in pixels (0..199) where death trigger located - for screens with bottomless pits it's usually 199, but the number is less for screens with secret area teleports or higher grounds.
! Spikes, cave entrances, hidden bonuses and other things
Each screen within a level is comprised of the following structure, repeated once for each object in the level.
Data type | Name | Description |
---|---|---|
INT16LE | xPos | X location of the object |
INT16LE | yPos | Y location of the object, in pixels from the top of the screen |
UINT16LE | nTile | Background tile element number from the corresponding ELEML#.MAT for the level (where # is a level number) |
This structure is repeated Sizes+1 times until the end of the current screen.
nTile types
Each nTile value in the structure above is as follows: ! This list is incomplete - and seems to match the sprites in eleml1.mat as extract by Wombat
Code | Description |
---|---|
0x00 | Trampoline! Causes strange behaviour though |
0x01 | Left ledge (earth) |
0x02 | Square block (earth) |
0x03 | Right ledge (earth) |
0x04 | Rock sign: "level 1" |
0x05 | Rock wall left ledge |
0x06 | Rock wall solid rectangle |
0x07 | Rock wall right ledge |
0x08 | Block of water with waves (background) |
0x09 | Rock wall with cave entry |
0x0A | Ladder |
0x0B | Green line? |
0x0C | Green line? |
0x0D | Pine tree |
0x0E | ! TODO |
0x0F | Different water with waves (background) |
0x10 | Palm tree |
0x11 | Underwater bubbles background |
0x12 | Underwater bubbles background #2 |
0x13 | Underwater bubbles background #3 |
0x14 | Green line? |
0x15 | Bush/shrubbery |
0x16 | Rock wall solid rectangle (without walkable top) |
0x17 | Cave background right |
0x18 | Cave background middle |
0x19 | Dinosaur |
Level parsing example source code
C
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
/*
(c) CTPAX-X Team 2019,2020
http://www.CTPAX-X.org/
you can redirect output from this tool to the text file:
hmapinfo > hist_map.txt
*/
/* scr_count, heights, sizes, scr_offs */
static uint32_t levels[4][4] = {
{19, 0x00021668, 0x00021A06, 0x00021A2E},
{19, 0x000216C6, 0x0002333A, 0x00023362},
{19, 0x00021738, 0x000247BA, 0x000247E0},
{19, 0x000219AE, 0x000257C6, 0x000257EE}
};
int main(void) {
FILE *fl;
uint16_t sz[20], ht[20];
int16_t item[3];
int32_t i, j, k;
fl = fopen("HISTORIK.EXE", "rb");
if (!fl) {
printf("Error: can't open \"HISTORIK.EXE\" file.\n\n");
return(1);
}
for (k = 0; k < 4; k++) {
printf("*** Level-%d\n", (k*2) + 1);
/* heights */
fseek(fl, levels[k][1], SEEK_SET);
fread(ht, 2, levels[k][0], fl);
/* sizes */
fseek(fl, levels[k][2], SEEK_SET);
fread(sz, 2, levels[k][0], fl);
/* calculate total records number for all screens at level */
j = 0;
for (i = 0; i < levels[k][0]; i++) {
printf("%2d ", sz[i] + 1);
j += sz[i];
}
printf("\nRecords: %d\n", j);
/* for each screen */
fseek(fl, levels[k][3], SEEK_SET);
for (i = 0; i < levels[k][0]; i++) {
printf("== SCR-%02d | height: %d\n", i + 1, ht[i]);
for (j = 0; j < sz[i] + 1; j++) {
fread(item, 3, 2, fl);
printf("OBJ# %3d at %3d,%3d\n", item[2], (item[0] / 16) * 16, item[1]);
}
printf("\n");
}
printf("FilePos: %lX\n\n\n", ftell(fl));
}
fclose(fl);
return(0);
}
Credits
This file format was reverse engineered by KeenRush. 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!)