This is not a complete decode in the sense that I've not yet matched the
results up against in-game height map data, but decoding these on Linux
produces ASCII art that looks undeniably like iso-bar maps.
For WRLD records, the MHDT subrecord is:
x1 = sint16()
y1 = sint16()
x2 = sint16()
y2 = sint16()
for x in [x1, x2 + 1]:
for y in [y1, y2 + 1]:
m1[x][y] = uint8()
m2[x][y] = uint8()
m3[x][y] = uint8()
m4[x][y] = uint8()
The four matrices are very similar and obviously describe the same terrain
grid. Perhaps m1 through m4 represent quadrants of each (x,y) cell? The value
zero may have special significance, since it is frequently adjacent to values
that are much larger (steep slopes?). The primary evidence for a correct
decoding is that the x and y values predict the correct subrecord size, and the
four resulting iso-bar maps are very similar.
For the CELL record, the format is very similar to the WRLD records, except
that the size appears to be hard-coded for x1=0, x2=32, y1=0, y2=32 and there's
only one matrix. There's also 4 bytes of extra data at the beginning of the
subrecord.
unknown1 = uint16()
unknown2 = uint16()
for x in [0, 32]:
for y in [0, 32]:
m[x][y] = uint8()
The value of unknown1 is 0x0000 in all but ten cases. Four of those records
have 0x8000 suggesting a flag of some sort, and decode correctly. The
remaining six values are 0xFFFF (3 times), 0x019d, 0x091b, and 0x0b91. These
records all appear to be corrupt in the sense that the decoding above does not
produce identifiable "map terain".
The significance of unknown2 is unclear, but I suspect a base elevation. The
value 0xC65A occurs 3466 times and 0xC400 occurs 1796 times. Many other values
cluster around 0xC500 and 0x4600. Simply printing the 32x32 matrix as
two-digit hex bytes will easily reveal identifiable terrain because most
adjacent cells only have a delta of 0 or 1 from their neighbors. The lowest
point in any cell appears to always be zero, and the full byte range for the
matrix values is rarely used. Only 0.2% of the values are greater than 100,
and 98.3% are less than 60.
Visualizing the WRLD results is a little more difficult, since each (x,y) cell
differs more significantly from it's neighbor, the worlds are often larger than
32x32, and the full range of the byte is used more frequently. What worked
best for me was to scale each byte into the range 0-9 and then print the matrix
as before.
Since I'm unable to correlate the terrain data with actual game terrain, I
thought I'd describe the results briefly here in case someone else recognizes
something. Scaled height values (0-9) are in parentheses.
Riften has a low northwest corner (0), highly varied terrain and a high mount
(9) in the upper center. Markarth is basically flat (0), with the high point
(6) in northeast corner. Whiterun undulates gently (1-3), with the highest
point (9) in the southwest corner. Skuldafn has a low northwest corner (0), and
is mostly flat (2), with some terrain in the southern portion (5). Deepwood
Redoubt has a low northwest corner (0) and is otherwise flat (2). Sovengarde
has a low northwest corner (0), is generally flat (2) and has a peanut-shaped
mount (5-9). Solitude is most flat (0-1) with a couple of higher spots (2-3).
It seems suspicious that there are so many low northwest corners. It's
possible that there's some row delta encoding in use like in the LAND records,
but there's no evidence of signed values in the data, and I can't find a
working scheme.
Original issue reported on code.google.com by cfcohe...@gmail.com on 25 Jan 2015 at 4:28
Original issue reported on code.google.com by
cfcohe...@gmail.com
on 25 Jan 2015 at 4:28