Outpost 2 Saved Game File Format
--------------------------------
Note: Saved games share much of the same loading code as the .map file format.
They consist of a prefix to the .map format and (possibly) some data near the end.
Outpost 2 .op2 File Format (Saved Games)
----------------------------------------
Offset Size Description
------ ---- -----------
0x0 0x19 "OUTPOST 2.00 SAVED GAME", 0x1A, 0 - String must match exactly or else load error
---------------------------
Note: The following is repeated as an array of 0x74 (116 decimal) elements
0x19+i*0x1E0 4 **TODO** Figure this out
0x1D+i*0x1E0 0x1DC **TODO** Figure this out
---------------------------
Note: From here, the format matches that of .map files
Outpost 2 .map File Format
--------------------------
Note: Logs discussed below are all base 2 logarithms.
Offset Size Description
------ ---- -----------
Section: Header
0x0 4 tag (must be >= 0x1010 or map is not loaded)
0x4 4 boolNotSure (for .map, but not saved games? flag...?)
0x8 4 logMapTileWidth (lg(mapTileWidth)
0xC 4 mapTileHeight - this gets rounded up to a power of 2
0x10 4 numTileSets
---------------------------
Section: Tile Data
0x14 X tileData - array of DWORDs of size mapTileWidth*mapTileHeight
The tileData consists of the following bit fields
5 cellType - determines speed of movement, bulldozed, walled, tubed, rubble areas (see Note below) (returned by GameMap.GetCellType)
11 tileIndex - this is an index into the tileInfo array described below (see Tile Set Section)
11 unitID - unitID (index of unit into unit array) of the unit that occupies this tile
1 lavaPresent
1 lavaPossible
1 expansion (lava or blight about to expand to here?)
1 microbePresent
1 unitImpassable - Set if a wall or building has been built on this tile
---------------------------
Section: ClipRegion - unit can only move within this map area
X+0x14 4 clipRegion.x1 - internal coordinate of left edge (0x20 normally, or -1 for around the world maps)
X+0x18 4 clipRegion.y1 - topmost edge (0 = "1"-1)
X+0x1C 4 clipRegion.x2 - rightmost edge (mapTileWidth + 0x1F, internal coordinates of rightmost tileX) or (0x7FFFFFFF if logTileWidth >= 9, around the world maps)
X+0x20 4 clipRegion.y2 - bottommost edge (tileHeight-2 = (tileHeight-1) - 1)
---------------------------
Section: Tile Set Sources
X+0x24 Y tileSetSource table (refers to the "well00??.bmp" files)
The tile set source table has up to 3 fields for each entry of the table
4 stringLength - length of filename
8 tileSetFilename
4 numTiles - number of tiles in this tile set
Note: The last two fields will not exist if the first field, stringLength == 0.
The game will attemp to read numTileSets (see Header Section) copies of these fields.
It will read 16 bytes for the fields were a string exists (stringLength != 0)
and 4 bytes where the string doesn't exist (stringLength == 0).
---------------------------
Section: Tile Set
0xA "TILE SET", 0x1A, NULL (10 characters, 0x1A, NULL terminated string) - Loading fails if string doesn't match
4 numTiles - Specifies how many tiles from the loaded tile sets are referenced
8*numTiles tileInfo array - tileData array (see Tile Data Section) indexes into this array to find tile graphic
The tileInfo array consists of an array of the following structure
2 tileSetIndex - index of tile set (see Tile Set Sources Section)
2 tileIndex - index of the tile in this tile set
2 numAnimations - number of following tiles that can be displayed to replace this one (See TileSet7 for more details TileNum 0) or CodeSection 0x0047030D
2 animationDelay - number of cycles elapsed before displaying next tile (See TileSet7 for more details TileNum 0)
4 numTerrainTypes
0x108*numTerrainTypes Array of TerrainType objects - (list of tile indexes, provides mappings to new tile indexes when graphics change. eg. bulldozed, tube/wall built)
2 firstTileIndex - first tile index to which this list applies
2 lastTileIndex - last tile index to which this list applies
2 bulldozedTileIndex - tile index to set when tiles in this group are bulldozed
2 rubbleTileIndex - index of common rubble tile (4 consecutive common rubble tiles followed by 4 rare rubble tiles)
2*6 tubePartial[6] - index of tube tiles (data is repeated **TODO** find out why)
32*5 wall[5][16] - arrays of wall tile groups (16 tiles in each array) (lava, microbe, normal, light damaged normal, heavy damaged normal)
2 lavaStartIndex - starting lava tile index
6 LavaInfo
2 animationLength - [6]
2 centerAnimationLength - [6] [Rand(value-1)] [numCenterTiles?]
2 numCenterTiles - [1] [centerAnimationLength?]
32 tube[16] - array of tube tile indexes (for tubes facing each direction)
2 scorched - scorched tile index (from vehicle explosion)
12 scorchedRange[3]
2 startTile
2 endTile
30 unknown[15] - **TODO** find out - various tile indexes, or 0 [unused?]
---------------------------
4 tag - must match tag at first DWORD of .map file else error (see Header Section)
---------------------------
Note: extra data can be read here, depending on the parameters to the load routine.
.map files shouldn't load any data here, probably only saved games (which do seem to load extra data here)
4 numUnits
4 **TODO** figure out what this is
4 **TODO** figure out what this is
4 **TODO** figure out what this is
4 sizeofUnit - 0x78 (120 bytes) if sizeofUnit != 0x78 && numUnits != 0 then Error
- - - - - - - - - - - - - -
Note: Reading continues here in a subroutine at 0x00446CF0
4 numObjects1 (number of 512 byte objects)
4 numObjects2 (number of 4 byte objects)
Note: if (numObjects1 == 0) return (successfully)
512*numObjects objectArray **TODO** find out what this object is
Note: if (numObjects2 == 0) return (successfuly)
4*numObjects2 objectArray **TODO** find out what this object is
Note: End of subroutine read
- - - - - - - - - - - - - -
4 unitID - **TODO** find out significance
4 unitID - **TODO** find out significance
0x1DF88 unitRecord[1023] - 1023 unit records of 120 bytes each
Note: End of "optional" data (not really optional for saved games files)
---------------------------
4 tag - must match tag at first DWORD of .map file else error (see Header Section)
---------------------------
Note: End of .map load.
Extra data seems to follow the last read. Appears to be tagged data. (eg. "LAVA_LEFT", "midd_lava", "RIGHT_LAVA", etc.)
This could potentially have been used by a map editor.
- - - - - - - - - - - - - -
4 int numTileGroups (
)
4
A list of the following items is found
4 int xSize
4 int ySize
4*xSize*ySize int data[xSize][ySize]
4 stringLen
stringLen string
- - - - - - - - - - - - - -
End of .map file
Loading Notes:
--------------
The numTiles in the Tile Set section are read into an array, processed, and then released from
memory. Processing differs depending on whether or not numTiles == 0. The
element at index 7 (the lava tile set) is special cased.
Note: cellType (5 bits) has one of the 32 following meanings, as can be found at [0x4DEBA8]:
Value Meaning
-------- -------
0 (0x0) Fast Passible 1 - rock vegetation
1 (0x1) Impassible 2 - meteor craters, cracks/crevasses
2 (0x2) Slow Passible 1 - lava rock (dark)
3 (0x3) Slow Passible 2 - rippled dirt/lava rock bumps
4 (0x4) Medium Passible 1 - dirt
5 (0x5) Medium Passible 2 - lava rock
6 (0x6) Impassible 1 - dirt/rock/lava rock mound/ice cap/volcanoe
7 (0x7) Fast Passable 2 - rock
8 (0x8) North Cliffs -
9 (0x9) Cliffs - High side -
10 (0xA) Cliffs - Low Side - cliffs, low side (and middle too)
11 (0xB) Vents and Fumaroles - fumaroles (only passable by GeoCons/RoboMiners?)
12 (0xC) zPad 12
13 (0xD) zPad 13
14 (0xE) zPad 14
15 (0xF) zPad 15
16 (0x10) zPad 16
17 (0x11) zPad 17
18 (0x12) zPad 18
19 (0x13) zPad 19
20 (0x14) zPad 20
21 (0x15) Dozed Area - bulldozed, non tubed area (buildings are tubed underneath)
22 (0x16) Rubble
23 (0x17) Normal Wall
24 (0x18) Microbe Wall
25 (0x19) Lava Wall
26 (0x1A) Tube0 - tubed (buildings are tubed underneath, including docks)
27 (0x1B) Tube1
28 (0x1C) Tube2
29 (0x1D) Tube3
30 (0x1E) Tube4
31 (0x1F) Tube5