Another night of .obj failure

This commit is contained in:
2018-03-21 05:08:24 +00:00
parent 4db78f52fa
commit c4598590c2
4 changed files with 254 additions and 142 deletions

View File

@@ -142,12 +142,16 @@ I think this is rendered as a 1px dot with the colour `#ff00ff` in WH40K_TD.exe:
![blank.obj as rendered by WH40K_TD.exe](img/blank.obj.png)
In the 64x64 tile, the dot is in the very centre.
In the tile, the dot is in the very centre.
The colour itself doesn't show up in the data directly, so it's not a simple RGB
array of pixels. WH40K_TD.exe is a 16-bit-colour application and may use a
palette, but these factoids don't help me make immediate sense of the data. If
there's a palette in the first 24 bytes, it's not obvious.
array of pixels. WH40K_TD.exe is a 256-colour application, so the pixel data may
account for 1 of the 3 bytes.
All sprites seem to end with 0x00 - like a GIF image descriptor, this may say
"end of data".
So what's the 1? Simple RLE, like FLIC type 15 BYTE_RUN? - "Repeat 253 one time"?
There are 45 `TYPE 13` .obj files in the game. Comparing the above with the
start of the second sprite in `pillar.obj`:
@@ -177,46 +181,94 @@ start of the second sprite in `pillar.obj`:
Total size is 3340. The first 24 bytes look quite different to the remainder of
this file, lending weight to the 24-byte header theory.
Line-by-line comparison:
Line-by-line comparisons of first 16 bytes (all TYPE 13). 0x10..0x17 are all
0x00 in all examples so far.
```
a: blank.obj sprite 0, 1x1 tile (27 bytes)
b: pillar.obj sprite 1 (3340 bytes)
c: altar.obj sprite 0 (7465 bytes)
d: altar.obj sprite 1 (7368 bytes)
a 0x0000 10 01 61 01 01 00 01 00 | a | 16 1 97 1 1 0 1 0
b 0x0000 fa 00 25 01 2e 00 48 00 | H | 250 0 37 1 46 0 72 0
c 0x0000 d6 00 16 01 74 00 67 00 | t g | 214 0 22 1 116 0 103 0
d 0x0000 d6 00 19 01 74 00 64 00 | t d | 214 0 25 1 116 0 100 0
a 0x0008 00 00 00 00 03 00 00 00 | | 0 0 0 0 3 0 0 0
b 0x0008 00 00 00 00 f4 0c 00 00 | | 0 0 0 0 244 12 0 0
c 0x0008 00 00 00 00 11 1d 00 00 | | 0 0 0 0 17 29 0 0
d 0x0008 00 00 00 00 b0 1c 00 00 | | 0 0 0 0 176 28 0 0
```
a 0x0010 00 00 00 00 00 00 00 00 | | 0 0 0 0 0 0 0 0
b 0x0010 00 00 00 00 00 00 00 00 | | 0 0 0 0 0 0 0 0
Assuming a 24-byte header, 0x0c matches "remaining pixeldata" size in all cases.
Assuming a 24-byte header, 0x0c matches "remaining pixeldata" size in both cases
- 3 and 3316.
0x04 makes sense as x,y dimension in `blank.obj` where we *know* it's 1x1 pixel.
It's odd that the last 8 bytes of this putative header are empty in both cases.
I need to see if I can find any examples that store it.
0x04 makes sense as height & width, 2 16-bit values, in `blank.obj` where we
*know* it's 1x1 pixel.
It makes less sense as such for `pillar.obj` where the individual sprites fit
into the 64x64x64 volume of a cell:
![pillar.obj as individual sprites](img/pillar_6_sprites.png)
The pillar has more Y than X; the altar more X than Y, suggesting 0x04-0x05 are
X and 0x06-0x07 are Y. Measuring the rendered pixels by WH40K_TD.exe gives a
close correspondence in all cases.
WH40K_TD.exe crashes trying to load a set referencing `pillar` in it unless it's
in the CENTER position. Interesting.
Next: keep adding cases to the header comparison above until I make sense of it
all. Since `pillar.obj` is composable, it's not the best example I could have
picked. Need more non-composable ones, in case that makes a difference.
Not all pixeldatas are evenly divisible by 3. blank.obj seems to be the special
case.
The volume represented by a cell is a little odd. We see three faces of a fake
3D volume of size 64x64x32(ish). This is presented in an isomorphic fashion, so
the height is 32px at the leftmost and rightmost extents and 96 in the centre.
Overall width is 128px, and the minimum rectangle covering the whole space would
be 128x96, or 12288 bytes at 8bpp.
Or it could be represented as the three planes separately. So for an altar, we'd
have 64x64 pixels, plus 32x64 pixels, plus 32x64 pixels (minus a few around the
edges, perhaps) - 4096 + 2048 + 2048 = 8192. The sprite is only slightly smaller
than that.
Or perhaps we draw a normal X/Y rectangle which is then skewed appropriately.
That seems like it would be odd for pixeldata though?
Bytes per pixel (intuited from hypothetical x,y) for the four frames so far:
```
a: 1 * 1 = 1. 27 - 24 = 3. 24 bits / pixel
b: 46 * 72 = 3312. 3340 - 24 = 3316. 8 bits / pixel with 4 bytes left over.
c: 116 * 103 = 11948. 7465 - 24 = 7439. 4.9 bits / pixel
d: 116 * 100 = 11600. 7368 - 24 = 7344. 5.1 bits / pixel
```
| Offset | Purpose |
| ------ | ------- |
| 0x0000 | ?
| 0x0004 | ?
| 0x0008 | ?
| 0x0004 | x,y size (16 bits each) |
| 0x0008 | ? (blank in all cases so far)
| 0x000c | Size of remaining pixeldata |
| 0x0010 | Padding?
| 0x0014 | Padding?
| 0x0010 | Padding? |
| 0x0014 | Padding? |
We still don't know what the first 32 bits are all about. Perhaps they can help
to explain the differences in putative bpp.
0x002-0x003 changes in step with total number of pixels?
| ID | 0x2-0x3 | dec LE | Number of pixels |
| -- | ------- | ------ | ---------------- |
| a | 61 01 | 353 | 1 |
| b | 25 01 | 293 | 3312 |
| d | 19 01 | 281 | 11600 |
| c | 16 01 | 278 | 11948 |
Not clear what it means. If anything!
WH40K_TD.exe loops around "ReadInMissionFLCs", incl. address 0x0041dd10, where
it loads in all the .asc and .obj files in a set.
```
break *0x41DD10
```
This lets me focus very narrowly on what happens when loading sprites, and
might give clues.