Make some progress decoding map trailer

This commit is contained in:
2020-06-07 01:44:28 +01:00
parent 0bf8233cd1
commit a6fdbaef2b
2 changed files with 119 additions and 5 deletions

View File

@@ -392,8 +392,11 @@ well-aligned amount.
Investigation has so far suggested the following:
* `Cell[0]` seems related to doors and canisters. Observed:
* Nothing special: 0x38
* ???: 0x39
* Imperial crate: 0x28
* Door: 0xB8
* `Cell[1]` seems related to special placeables (but not triggers). Bitfield. Observed:
* 0x01: Reactor
* 0x20: Door or door lock?
@@ -408,12 +411,12 @@ Investigation has so far suggested the following:
* `Cell[7]` Object 2 (Right) Area (Sets/*.set lookup)
* `Cell[6]` Object 2 (Right) Sprite + active flag
* `Cell[9]` Object 3 (Center) Area (Sets/*.set lookup)
* `Cell[10]` Object 3 (Right) Sprite + active flag
* `Cell[11]` all 255?
* `Cell[10]` Object 3 (Center) Sprite + active flag
* `Cell[11]` all 255? Vehicle?
* `Cell[12]` all 0?
* `Cell[13]` all 0?
* `Cell[14]` all 0?
* `Cell[15]` shows squad positions, MP start positions, etc, as 0x04
* `Cell[15]` shows squad positions, MP start positions, etc, as 0x04. Bitfield?
Mapping the altar in Chapter01 to the map01 set suggests it's a palette entry
lookup, 0-indexed. `U` debug in WH40K_TD.exe says the cell's `Object 3-Center`
@@ -515,10 +518,102 @@ Around 001841A0: mission objectives!
00184240 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
```
Since all the files are exactly the same length uncompressed, I'm going to
assume these are all a fixed number of fixed-size records when looking into it.
The size of the trailer for Chapter01 is 139,483 bytes.
Relative offsets from the start of the trailer, we have:
| Offset | Text |
| -------- | ---- |
| `0xEE` | Mania |
| `0x78A` | Dagon |
| `0xE26` | Nihasa |
| `0x14C2` | Samnu |
| `0x1b5e` | Bael |
| `0x2896` | Gigamen |
| `0x2f32` | Valefor |
| `0x35ce` | Baalberith |
| `0x3c6a` | Fenriz |
| `0x4306` | #Character |
| `0x49a2` | Apollyon |
So there are 1692 bytes between each name (the names probably don't come at the
start of each block, but it's still a useful stride). Presumably `#Character` is
a space for one of the player characters, while the others specify an NPC placed
on the map.
There's 56 of these records between the first and last name we see - `Ahpuch`.
Then there are a number of other strings that seem related to triggers / events,
including lots that say `NO FILE`. The first two are 96 bytes apart; from then
on they seem to be placed variably apart from each other; I've seen 96, 256, and
352 byte offsets.
At 0x20916 the mission objective is readable.
At 0x2092a the mission description is readable.
Generating another map with just 5 characters on it, things look different:
* Trailer size is 13543 bytes
* There are only 5 names
* There are none of the trigger/event strings
* Mission title is found at 0x2b93
* Mission briefing is found at 0x2c92
Since the trailer is a variable size, there must be a header that tells us how
many of each type of record to read. Peeking at the differences in `vbindiff`:
```
Chapter01.MAP.Trailer
0000 0000: 38 00 00 68 00 00 00 50 00 00 00 1A 00 00 00 14 8..h...P ........
0000 0010: 00 00 00 3A 00 00 00 00 38 25 00 04 00 00 00 00 ...:.... 8%......
0000 0020: 00 00 00 1A 00 00 00 00 00 00 00 00 00 00 00 00 ........ ........
0000 0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........ ........
0000 0040: 00 00 00 00 00 00 00 00 00 00 00 02 00 00 00 00 ........ ........
0000 0050: 00 00 00 32 00 00 00 00 00 00 00 00 00 00 00 00 ...2.... ........
TINYSQUAD.MAP.Trailer
0000 0000: 38 00 00 4B 00 00 00 3C 00 00 00 37 00 00 00 28 8..K...< ...7...(
0000 0010: 00 00 00 05 00 00 00 00 2B 3A 00 04 00 00 00 05 ........ +:......
0000 0020: 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 ........ ........
0000 0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ........ ........
0000 0040: 00 00 00 00 00 00 00 00 00 00 00 02 00 00 00 00 ........ ........
0000 0050: 00 00 00 32 00 00 00 00 00 00 00 00 00 00 00 00 ...2.... ........
```
here's a first guess at a header:
| Offset | Size | Meaning |
| ------ | ---- | ------- |
| 0 | 2 | ??? - invariant `38 00` |
| 2 | 2 | ??? - varies |
| 4 | 4 | ??? - varies |
| 8 | 4 | ??? - varies |
| 12 | 4 | ??? - varies |
| 16 | 4 | Number of character records (58 vs 5) |
| 20 | 4 | ??? - invariant `00 00 00 00` |
| 24 | 2 | ??? - varies. Seems related to character/squad position? |
| 26 | 2 | ??? - invariant `00 04` |
| 28 | 4 | ??? - varies (0 vs 5) |
| 32 | 4 | Number of objective/event records (26 vs 1) |
| 36 | 36? | Padding? |
0x4b contains the next non-null byte; is the gap between the the number of
objectives, and it, padding? Minus a bit? 0x50 is another non-null byte. Then
it's all zeroes until one byte before the first name at 0xee.
It's hard to say where the alignment should be at this point. We need to compare
more characters with each other. We might also be able to determine framing by
looking at the *end* of the character block.
Characters are organised into Squads somehow.
Individual cells seem to have a flag to say "We have a character in us", but not
the number for the character themselves, so the coordinates must be in the
per-character records also. There are several candidates for this.
Placing a single character at (64,49) causes those bytes to show up at four
offsets - 0x18 (!), 0x1F4, 0x1F8, and 0x6C8.
## Soldiers At War

View File

@@ -48,6 +48,25 @@ type Header struct {
// Need to investigate the rest of the header too
}
type Trailer struct {
Unknown1 uint16
Unknown2 uint16
Unknown3 uint32
Unknown4 uint32
Unknown5 uint32
NumCharacters uint32
Padding1 uint32
Unknown6 uint16
Unknown7 uint16
Unknown8 uint32
NumThingies uint32
Padding2 [36]byte
}
type Character struct {
Unknown1 uint32
}
func (h Header) Width() int {
return int(h.MaxWidth - h.MinWidth)
}