While trying to get the demo working completely, I decided now would be the right to fully understand what each resource in DATA.WAR actually means. But why, you may ask? Everything seems to load fine ...
DATA.WAR is Warcraft 1s main game content file and contains almost everything from the game: Music, Sound, Levels, Art and so on. The old loading code was rather optimistic and had many assumptions here and there which manifested themselves in lots of hardcoded information scattered throughout the code.
One example of those assumptions was level information, which worked for the full version, but suddenly broke when I tried to load the second and third level of the demo version.
First of all, some background information: DATA.WAR has virtually no meta data. All it contains is a list of resources with their offsets and then the resources themselves, again with only their length and an RLE compression flag. As a result I have a hardcoded "Knowledge Base" which stores information about each resource. So far, so good, nothing wrong with that. Gotta store the info somewhere.
So, back to the levels:
Levels are created from three resources: LevelInfo, LevelPassable and LevelVisual.
LevelInfo has setup information: Gold and lumber for each player, starting units and buildings, roads, mission text, etc...
LevelPassable stores "this tile is blocked" for each map tile.
LevelVisual stores the type of tile for each tile (e.g. grass, water, etc..)
To actually create the map I also need to know which tile set (Grassland, Swamp, Dungeon) is the correct one matching the info in LevelVisual.
Back to the Knowledge Base: To match a LevelInfo with their LevelPassable and LevelVisual counterparts I gave them similar names, like "Humans 3" for LevelInfo, "Humans 3 (Passable)" for LevelPassable and "Humans 3 (Visual)" for LevelVisual. The LevelVisual resource had an additional index pointing to the matching tile set. A tile set is also made up of a total of three resources. Ok, so I gathered all the info for the full version of DATA.WAR and all was fine, I could create all levels.
In comes the demo DATA.WAR. It's basically the same as the full DATA.WAR just with more than half of the resources empty, because they're not used. So I load the first orc level, looks good. I load the second level ... hmm ... something's wrong. Load the first human level. Looks good. Load the second human level ... bam .. wrong again.
I quickly found out that the passable and visual resources for level 2 and 3 for the human and orc campaign were swapped. So "Humans 2 (Passable)" was actually "Humans 3 (Passable)" and vice versa.
To fix that, I created a second version of the Knowledge Base, which has the correct info for the demo.
But that's not really a good solution. I'd work, I'm sure, but it's not clean. And I'd bet that Blizzard themselves never did something weird like that. Basically setting the right indices somewhere and hope for the best.
Back to the beginning of my blog post: I knew almost nothing about the LevelInfo resource structure. There was lots of "move through the byte array until you've found 0xFFFF three times". So I dug around, compared data and lo and behold, I got most of the information I needed: LevelInfo contains a reference to the LevelPassable resource, the LevelVisual, the TileSet, the next level (for campaigns), even the race of the human player (Orcs or Humans).
I know a lot more about the LevelInfo resource now, but there's still some unknown data in it. It's also a weird format and there seem to be at least three different versions of, each with a slightly different layout.
There are more examples of previously unknown resources (UI layout, for example), which were implemented with lots of guessing and manual fixes.
I'll try to get version 0.2.0 released soon, since loading the demo levels shouldn't be much of a problem anymore.