Overview[]
A S2 map file (.s2m) is composed of 4 differents parts
- header
- compressed data #1 (zlib compression, default compression level)
- compressed data #2
- compressed data #3
Binary types[]
- Endianess: little-endian
- Integers : signed 4-bytes
- Strings format : 4-bytes length in front + chars
- Wide string format : 4-bytes length in front + chars (each char take 2 bytes, the second byte is zero).
- List : 4-bytes length in front + (repeated list data)
Notations[]
"List : String" will define a list of variable size composed of strings
2 Hello Stronghold
Binary representation :
2 5 H e l l o 10 S t r o n g h o l d
File header[]
The file header format is relativly simple and is composed of two lists.
- 4-bytes = number of string-typed options (A)
- Repeated A times :
- 4-bytes = length of option name (B)
- B-bytes = option name
- 4-bytes = length of option value (C)
- (C*2)-bytes = option value
- 4-bytes = number of integer-typed options (D)
- Repeated D times:
- 4-bytes = length of option name (E)
- E-bytes = option name
- 4-bytes = option value
Simplfiied version:
- List = options first chunk
- String = name
- String = value
- List = options second chunk
- String = name
- Integer = value
name | description | possible values | Additional comments |
---|---|---|---|
type | Map type | kingmaker, warcampaign, historical, freebuild | |
author | Firefly | Adding this value will cause the map to be not visible in editor | |
lastsave | ?? | ||
mapsize | 128, 256 | Same X / Y size | |
maxplayers | |||
version | 1 |
Compressed data (segment 1)[]
Scenario, other global options ?
- Map calendar date (Jan 1066) (Note: the month is a value between 0 and 11 included. Using an option not in this range will cause to use another text of the game. The strings are index and 0 index is January, 11 is December, etc...). Values allowed by the game:
- Year : in range [0;9999]. Binary editing allow use another value, even negative ones. Setting to a very high value may cause crash (?)
- Month : in range [0;11]. Setting another option will reset the next month to January. You proably find all in game data with higher values.
- Scenario
Compressed data (segment 2)[]
"static" map options (terrain)
Compressed data (segment 3)[]
"dynamic" map options (units)
Method[]
Find how ground level is encoded :
Make a map with only low ground
Make a map with only high ground
Decompress file and the differences are located into 1st compressed data segment.
The biggest difference is repetition of C4 D8 E6 FF in differentes places for high ground and 30 78 78 FF in low ground.
The hexadecimal editor tell this data is encountered 15.876 times. With a little of guess, we can think that if the map is squared, the level of ground data count must be a square. Google tell us that sqrt(15.876) = 126 It's an integer, and almost same as map size ~128, it show that it should be that. Maybe the difference is because the border are not counted (128 - 1 width border each side = 126).