World File Format (.blp)

Overview

World files use the .blp extension (Blupi binary format). A single file stores the complete state of one mission: all tile positions, characters, animated decorations, and win conditions.

Read/write: CDecor::Read() and CDecor::Write() in src/decio.cpp.


File Naming

Pattern Location Description
data/world000.blpdata/world005.blp CD/install Tutorial / school missions (6 levels)
data/world100.blpdata/world137.blp CD/install Campaign episode 1 (normal)
data/world138.blpdata/world153.blp CD/install Campaign episode 2 (advanced)
data/world200.blpdata/world215.blp CD/install Bonus / advanced missions (16 levels)
data/user000.blpdata/user009.blp Local Save game slots (10 slots)
data/demo000.blpdata/demo003.blp CD/install Built-in demo recordings (4)
data/enigmes.blp CD/install Special puzzle / enigma world
data/info.blp CD/install Information / credits world

Files world100–world199 are read from the CD-ROM path (AddCDPath()). Files world200+ and user* are stored locally.


Mission Numbering

Range Episode
000–005 Episode 1: Tutorial / school (6 levels)
100–137 Episode 2: Normal campaign (~38 levels)
138–153 Episode 3: Advanced campaign (~16 levels, some numbers skipped)
200–215 Episode 4: Bonus missions (16 levels)

Skipped world numbers (e.g. 138 is absent in some builds) indicate cut content.


Binary File Layout

[ DescFile header ]    — fixed size
[ Cellule[] data  ]    — lgDecor bytes
[ Blupi[] data    ]    — lgBlupi bytes
[ Move[] data     ]    — lgMove bytes

DescFile Header (detailed)

typedef struct {
    short   majRev;              // major format version (e.g. 1)
    short   minRev;              // minor format version (e.g. 0)
    int32_t nbDecor;             // number of Cellule elements (= 100*100 = 10000)
    int32_t lgDecor;             // size of Cellule section in bytes
    int32_t nbBlupi;             // number of Blupi elements (= MAXBLUPI = 100)
    int32_t lgBlupi;             // size of Blupi section in bytes
    int32_t nbMove;              // number of Move elements (= MAXMOVE = 100)
    int32_t lgMove;              // size of Move section in bytes
    short   reserve1[100];       // 200 bytes reserved
    POINT   celCoin;             // scroll position (top-left visible cell)
    short   world;               // world / mission number
    int32_t time;                // game time (in ticks)
    char    buttonExist[40];     // MAXBUTTON=40: which toolbar buttons are available
    Term    term;                // win conditions (see data-structures.md)
    short   music;               // music track 0–9
    short   region;              // visual region 0–3
    int32_t totalTime;           // total time on mission (statistics)
    short   skill;               // difficulty 0–2
    POINT   memoPos[4];          // saved camera positions (F5–F8)
    short   reserve2[29];        // reserved
} DescFile;

Write — CDecor::Write()

BOOL CDecor::Write(int rank, BOOL bUser, int world, int time, int total)
{
    // Build file path:
    if (bUser)  sprintf(filename, "data/user%.3d.blp", rank);
    else        sprintf(filename, "data/world%.3d.blp", rank);

    // Open file for binary write
    // Write DescFile header
    // Write m_decor[100][100] (Cellule data)
    // Write m_blupi[100] (Blupi data) — active entries only
    // Write m_move[100] (Move data) — active entries only
    // Close file
}

Read — CDecor::Read()

BOOL CDecor::Read(int rank, BOOL bUser, int &world, int &time, int &total)
{
    // Build file path (try user/ first, then CD)
    // Read DescFile header
    // Verify nbDecor, nbBlupi, nbMove
    // Read Cellule data → m_decor[][]
    // Read Blupi data → m_blupi[] (convert OldBlupi if needed)
    // Read Move data → m_move[]
    // Apply m_region, m_music, m_skill, m_term etc.
}

Backward Compatibility — OldBlupi

src/decio.cpp defines OldBlupi — the older Blupi structure without listButton/listCel/listParam/repeatLevel* fields. When loading .blp files created by an older version, majRev/minRev in DescFile triggers automatic conversion from OldBlupi to the current Blupi layout.


File Existence Check

BOOL CDecor::FileExist(int rank, BOOL bUser, int &world, int &time, int &total)
// Opens file, reads only the header, closes — used for UI save slot listing