Prehistorik Level Format

From ModdingWiki
Jump to: navigation, search
Prehistorik Level Format
320px
There is no image of a map in this format — upload one!
Format typeMap/level
Map type2D tile-based
Layer count2
Tile size (pixels)16×16
Viewport (pixels)320×200
Games

Prehistorik stores its level data inside the historik.exe file.

File format

Secret teleporter locations indicated in red.

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.

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 20 0x00021668 0x00021A06 0x00021A2E
3 20 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 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 type Object type (see below)

This structure is repeated Sizes times until the end of the current screen.

Object types

Each type value in the structure above is as follows: ! This list is incomplete

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
  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] = {
  {20, 0x00021668, 0x00021A06, 0x00021A2E},
  {20, 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("%02X ", sz[i]);
      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]; j++) {
        fread(item, 3, 2, fl);
        printf("OBJ#%02X at %d,%d\n", item[2], item[0], 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!)