More file format musing
This commit is contained in:
@@ -1,18 +1,71 @@
|
|||||||
# `Anim/WarHammer.ani`
|
# `Anim/WarHammer.ani`
|
||||||
|
|
||||||
This turns out to simply be an [`obj`](obj.md#WarHammer.ani) file. However, some
|
This turns out to simply be an [`obj`](obj.md) file.
|
||||||
other files are implicated in its interpretation:
|
|
||||||
|
|
||||||
- `Data/AniObDef.dat`
|
The first 1,064 sprites are all of the same Ultramarine, carryng a bolter. There
|
||||||
|
are eight "facing" orientations:
|
||||||
|
|
||||||
|
* North
|
||||||
|
* Northeast
|
||||||
|
* East
|
||||||
|
* Southeast
|
||||||
|
* South
|
||||||
|
* Southwest
|
||||||
|
* West
|
||||||
|
* Northwest
|
||||||
|
|
||||||
|
For each orientation, an action is pictured in a variable number of frames. The
|
||||||
|
final frame for each action appears to be "stationary".
|
||||||
|
|
||||||
|
* Walk (13 frames)
|
||||||
|
* Run (9 frames)
|
||||||
|
* Crouch down (8 frames)
|
||||||
|
* Stand up (8 frames)
|
||||||
|
* Take aim (standing) (6 frames)
|
||||||
|
* Fire (standing) (6 frames)
|
||||||
|
* Relax aim (standing) (6 frames)
|
||||||
|
* Throw grenade (standing) (18 frames)
|
||||||
|
* Take aim (crouched) (5 frames)
|
||||||
|
* Fire (crouched) (5 frames)
|
||||||
|
* Relax aim (crouched) (5 frames)
|
||||||
|
* Throw grenade (crouched) (17 frames)
|
||||||
|
* Draw melee weapon (standing) (10 frames)
|
||||||
|
* Strike down with melee weapon (standing) (8 frames)
|
||||||
|
* Stab with melee weapon (standing) (9 frames)
|
||||||
|
|
||||||
|
Added together and multiplied by 87, that's 1064.
|
||||||
|
|
||||||
|
The next sprite is a walking-north action for an ultramarine with a flamer. The
|
||||||
|
total number of frames for this character is 1120 - 56 additional frames, or 7
|
||||||
|
per orientation. Could be an extra action, or an extra frame per action.
|
||||||
|
|
||||||
|
Also notable is that while the bolter showed muzzle flash in the animation, the
|
||||||
|
flamer only showed a tiny hint of fire. I think the animation for spewing flame
|
||||||
|
is held elsewhere.
|
||||||
|
|
||||||
|
I strongly suspect the actions and the number of frames in each action are
|
||||||
|
configurable. So, what other files are implicated in its interpretation? Here's
|
||||||
|
a few possibilities:
|
||||||
|
|
||||||
|
* `Data/AniObDef.dat`
|
||||||
|
* `Data/Coordinates.dat`
|
||||||
|
* `Data/HasAction.dat`
|
||||||
|
* `Data/VehicDef.dat`
|
||||||
|
* `Data/WeapDef.dat`
|
||||||
- `Idx/WarHammer.idx`
|
- `Idx/WarHammer.idx`
|
||||||
|
|
||||||
Including comments, the former is 4098 lines, giving approx. 45 lines for each
|
## `Data/AniObDef.dat`
|
||||||
|
|
||||||
|
Including comments, this is 4098 lines, giving approx. 45 lines for each
|
||||||
of the ~188 characters in the `ani`. That doesn't seem many, and there's no
|
of the ~188 characters in the `ani`. That doesn't seem many, and there's no
|
||||||
obvious correspondence between the commented-on names (`SMOKE01`?) and the
|
obvious correspondence between the commented-on names (`SMOKE01`?) and the
|
||||||
viewed frames... but then, I've not viewed all the frames.
|
viewed frames... but then, I've not viewed all the frames.
|
||||||
|
|
||||||
Still, I think a focus in `WarHammer.idx` (1,880,078 bytes, binary, so around
|
|
||||||
10KiB per character, in theory) is more reasonable.
|
## `Idx/WarHammer.idx`
|
||||||
|
|
||||||
|
`WarHammer.idx` (1,880,078 bytes, binary, so around 10KiB per character, in
|
||||||
|
theory) is more reasonable.
|
||||||
|
|
||||||
Here's a list of operations on the file when `WH40K_TD.EXE` is instructed to
|
Here's a list of operations on the file when `WH40K_TD.EXE` is instructed to
|
||||||
place an Ultramarine squad:
|
place an Ultramarine squad:
|
||||||
@@ -310,22 +363,15 @@ read(<WarHammer.ani>, "\xbe\xe5\xb6\x09\x0c\x0f\x00\x00", 8) = 8
|
|||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
Notable is that we still load 5 type 2 records, even though there's just a
|
Notable is that we read from `idx` **before** we read from `ani` - so it does
|
||||||
single librarian, and 8 compass points. Why 5?
|
seem like the former should tell us where to pull from the latter.
|
||||||
|
|
||||||
Also notable is that we read from `idx` **before** we read from `ani`.
|
We still load 5 type 2 records, even though there's just a single librarian, and
|
||||||
|
8 compass points. Why 5? After looking in `idx`, we load 10 sprites from `ani`,
|
||||||
|
which is at least a multiple. Do any of the records we load from `idx` specify
|
||||||
|
sprite directory offsets that match?
|
||||||
|
|
||||||
Other data may be loaded at program start, of course. What other files seem
|
## `Data/HasAction.dat`
|
||||||
relevant?
|
|
||||||
|
|
||||||
* `Data/AniObDef.dat`
|
|
||||||
* `Data/HasAction.dat`
|
|
||||||
* `Data/VehicDef.dat`
|
|
||||||
* `Data/WeapDef.dat`
|
|
||||||
|
|
||||||
These all reference animations in one way or another.
|
|
||||||
|
|
||||||
## `HasAction.dat`
|
|
||||||
|
|
||||||
This file seems relevant as it says whether or not particular animations exist
|
This file seems relevant as it says whether or not particular animations exist
|
||||||
for the different types of character, which maps directly to what is stored in
|
for the different types of character, which maps directly to what is stored in
|
||||||
|
@@ -9,7 +9,7 @@ remake.
|
|||||||
* [✓] [`Anim/`](obj.md#WarHammer.ani)
|
* [✓] [`Anim/`](obj.md#WarHammer.ani)
|
||||||
* [`WarHammer.ani`](obj.md#WarHammer.ani)
|
* [`WarHammer.ani`](obj.md#WarHammer.ani)
|
||||||
* [`Assign/`](obj.md#assign)
|
* [`Assign/`](obj.md#assign)
|
||||||
* `*.asn` # Unknown, seems to be related to .obj files
|
* `*.asn` # Specify properties for frames in .obj files
|
||||||
* `Cursor/`
|
* `Cursor/`
|
||||||
* `*.ani` # RIFF data, standard ANI format \o/
|
* `*.ani` # RIFF data, standard ANI format \o/
|
||||||
* [`Cursors.cur`](obj.md) # `obj` file containing pointers and drag elements
|
* [`Cursors.cur`](obj.md) # `obj` file containing pointers and drag elements
|
||||||
@@ -23,6 +23,7 @@ remake.
|
|||||||
* **TODO**
|
* **TODO**
|
||||||
* `ChaNames.dat` # list of character names
|
* `ChaNames.dat` # list of character names
|
||||||
* `Coordinates.dat` # Weapon Firing Coordinates
|
* `Coordinates.dat` # Weapon Firing Coordinates
|
||||||
|
* `Credits.dat` # list of credits
|
||||||
* `Defs.dat` # defines properties for objects and tiles, each of which seems to have an id
|
* `Defs.dat` # defines properties for objects and tiles, each of which seems to have an id
|
||||||
* `GDestroy.dat` # table of what destroys what?
|
* `GDestroy.dat` # table of what destroys what?
|
||||||
|
|
||||||
@@ -39,7 +40,6 @@ remake.
|
|||||||
* `WeapDef.dat` # Weapon definitions
|
* `WeapDef.dat` # Weapon definitions
|
||||||
* **PROBABLY NOT NEEDED**
|
* **PROBABLY NOT NEEDED**
|
||||||
* `BugHunt.dat` # Contains SMF text for Bug hunt random missions
|
* `BugHunt.dat` # Contains SMF text for Bug hunt random missions
|
||||||
* `Credits.dat` # list of credits
|
|
||||||
* `GenArm.dat` # "Random campaign armory levels - space marine"
|
* `GenArm.dat` # "Random campaign armory levels - space marine"
|
||||||
* `HeroArm.dat` # "Random campaign armory levels - Veteran"
|
* `HeroArm.dat` # "Random campaign armory levels - Veteran"
|
||||||
* `MHeroArm.dat` # "Random campaign armory levels - Veteran"
|
* `MHeroArm.dat` # "Random campaign armory levels - Veteran"
|
||||||
@@ -49,11 +49,9 @@ remake.
|
|||||||
* `SpArm.dat` # "RANDOM CAMPAIGN ARMORY LEVELS - Veteran"
|
* `SpArm.dat` # "RANDOM CAMPAIGN ARMORY LEVELS - Veteran"
|
||||||
* `VetArm.dat` # "RANDOM CAMPAIGN ARMORY LEVELS - Veteran"
|
* `VetArm.dat` # "RANDOM CAMPAIGN ARMORY LEVELS - Veteran"
|
||||||
* `*.chk` # checksums? Mentions all the .dat files
|
* `*.chk` # checksums? Mentions all the .dat files
|
||||||
* `*.cyc` # ColorCycle DataFile.
|
* `Cycle.cyc` # ColorCycle DataFile.
|
||||||
* `*.dta` # localized strings and things
|
|
||||||
* `Encyclopedia.dta` # encyclopedia entries
|
* `Encyclopedia.dta` # encyclopedia entries
|
||||||
* `KeyMap.dta` # unknown
|
* `keymap.dta` # unknown
|
||||||
* `Keymap.dta` # unknown
|
|
||||||
* `USEng.dta` # Localized strings
|
* `USEng.dta` # Localized strings
|
||||||
* `EquipmentMenuData` # gzip-compressed, presumably to do with (initial?) squad configuration
|
* `EquipmentMenuData` # gzip-compressed, presumably to do with (initial?) squad configuration
|
||||||
* `Filters/`
|
* `Filters/`
|
||||||
@@ -105,7 +103,7 @@ Phew.
|
|||||||
* *Almost everything* seems to be in a data file somewhere. Helpful!
|
* *Almost everything* seems to be in a data file somewhere. Helpful!
|
||||||
* `make loader` creates a `load` binary that will try to load various bits
|
* `make loader` creates a `load` binary that will try to load various bits
|
||||||
of data from `investigation/` and `orig/`. I use it to investigate file
|
of data from `investigation/` and `orig/`. I use it to investigate file
|
||||||
formats and the parsers I'm writing. Ensure you're in a `GOPATH`!
|
formats and the parsers I'm writing.
|
||||||
|
|
||||||
## Cross-links / associations
|
## Cross-links / associations
|
||||||
|
|
||||||
|
@@ -6,80 +6,6 @@ be placed on it - a `SURFACE`, `LEFT`, `RIGHT`, and `CENTER`. Maps reference
|
|||||||
objects in a space-efficient way via sets, which seem to be a kind of object
|
objects in a space-efficient way via sets, which seem to be a kind of object
|
||||||
palette.
|
palette.
|
||||||
|
|
||||||
## Assign
|
|
||||||
|
|
||||||
The `Assign/` directory contains a matching `.asn` file for each `Obj/*.obj`.
|
|
||||||
It's a plain-text format which seems to assign properties to frames, and has
|
|
||||||
references to a `<name>.flc` file which does not exist in the tree.
|
|
||||||
|
|
||||||
Theory: .obj files were originally generated from `.flc` files. This is an
|
|
||||||
AutoDesk format for visual data, so this suggests the .obj files contain pixels
|
|
||||||
\o/
|
|
||||||
|
|
||||||
`blank.asn` references 6 frames (0-5):
|
|
||||||
|
|
||||||
```
|
|
||||||
# single pixel tile
|
|
||||||
# transpix.obj/.asn
|
|
||||||
#/--> transpix.flc
|
|
||||||
#
|
|
||||||
|
|
||||||
0-5:DEF 1;
|
|
||||||
|
|
||||||
|
|
||||||
0-5:TYPE 13;
|
|
||||||
|
|
||||||
|
|
||||||
END OF FILE
|
|
||||||
```
|
|
||||||
|
|
||||||
`jungtil.asn` references 18 frames (0-17):
|
|
||||||
|
|
||||||
```
|
|
||||||
# jungle floor
|
|
||||||
# jungtil.obj/.asn
|
|
||||||
# /--> d:\warflics\missions\jungtil.flc
|
|
||||||
#
|
|
||||||
|
|
||||||
0:DEF 2;
|
|
||||||
1-11:DEF 454;
|
|
||||||
|
|
||||||
|
|
||||||
#damaged frames!!!!
|
|
||||||
12:DEF 2;
|
|
||||||
13-16:DEF 454;
|
|
||||||
17:DEF 454;
|
|
||||||
|
|
||||||
|
|
||||||
0:TYPE 2;
|
|
||||||
1-11:TYPE 0;
|
|
||||||
12:TYPE 2;
|
|
||||||
13-16:TYPE 0;
|
|
||||||
17:TYPE 0;
|
|
||||||
|
|
||||||
|
|
||||||
0:DESTROY 12;
|
|
||||||
1-3:DESTROY 13;
|
|
||||||
4-6:DESTROY 14;
|
|
||||||
7-9:DESTROY 15;
|
|
||||||
10-11:DESTROY 16;
|
|
||||||
17:DESTROY 15;
|
|
||||||
|
|
||||||
1-11:Dmg1Lnk 17;
|
|
||||||
|
|
||||||
END OF FILE
|
|
||||||
```
|
|
||||||
|
|
||||||
So it seems this visual data can have quite complicated attributes. At a minimum
|
|
||||||
we see:
|
|
||||||
|
|
||||||
* `TYPE`
|
|
||||||
* `DEF`
|
|
||||||
* `DESTROY`
|
|
||||||
* `Dmg1Lnk`
|
|
||||||
|
|
||||||
The `type` field **may** tell us what format each sprite is in.
|
|
||||||
|
|
||||||
## OBJ container structure
|
## OBJ container structure
|
||||||
|
|
||||||
`.obj` files represent visual data. They contain a number of sprites, which are
|
`.obj` files represent visual data. They contain a number of sprites, which are
|
||||||
@@ -512,60 +438,144 @@ break *0x41DD10
|
|||||||
This lets me focus very narrowly on what happens when loading sprites, and
|
This lets me focus very narrowly on what happens when loading sprites, and
|
||||||
might give clues.
|
might give clues.
|
||||||
|
|
||||||
|
## Assign
|
||||||
|
|
||||||
|
The `Assign/` directory contains a matching `.asn` file for each `Obj/*.obj`.
|
||||||
|
It's a plain-text format which seems to assign properties to frames, and has
|
||||||
|
references to a `<name>.flc` file which does not exist in the tree.
|
||||||
|
|
||||||
|
Theory: .obj files were originally generated from `.flc` files. This is an
|
||||||
|
AutoDesk format for visual data, so this suggests the .obj files contain pixels
|
||||||
|
\o/
|
||||||
|
|
||||||
|
`blank.asn` references 6 frames (0-5):
|
||||||
|
|
||||||
|
```
|
||||||
|
# single pixel tile
|
||||||
|
# transpix.obj/.asn
|
||||||
|
#/--> transpix.flc
|
||||||
|
#
|
||||||
|
|
||||||
|
0-5:DEF 1;
|
||||||
|
|
||||||
|
|
||||||
|
0-5:TYPE 13;
|
||||||
|
|
||||||
|
|
||||||
|
END OF FILE
|
||||||
|
```
|
||||||
|
|
||||||
|
`jungtil.asn` references 18 frames (0-17):
|
||||||
|
|
||||||
|
```
|
||||||
|
# jungle floor
|
||||||
|
# jungtil.obj/.asn
|
||||||
|
# /--> d:\warflics\missions\jungtil.flc
|
||||||
|
#
|
||||||
|
|
||||||
|
0:DEF 2;
|
||||||
|
1-11:DEF 454;
|
||||||
|
|
||||||
|
|
||||||
|
#damaged frames!!!!
|
||||||
|
12:DEF 2;
|
||||||
|
13-16:DEF 454;
|
||||||
|
17:DEF 454;
|
||||||
|
|
||||||
|
|
||||||
|
0:TYPE 2;
|
||||||
|
1-11:TYPE 0;
|
||||||
|
12:TYPE 2;
|
||||||
|
13-16:TYPE 0;
|
||||||
|
17:TYPE 0;
|
||||||
|
|
||||||
|
|
||||||
|
0:DESTROY 12;
|
||||||
|
1-3:DESTROY 13;
|
||||||
|
4-6:DESTROY 14;
|
||||||
|
7-9:DESTROY 15;
|
||||||
|
10-11:DESTROY 16;
|
||||||
|
17:DESTROY 15;
|
||||||
|
|
||||||
|
1-11:Dmg1Lnk 17;
|
||||||
|
|
||||||
|
END OF FILE
|
||||||
|
```
|
||||||
|
|
||||||
|
So it seems this visual data can have quite complicated attributes. We see:
|
||||||
|
|
||||||
|
* `DEF`
|
||||||
|
* `DESTROY`
|
||||||
|
* `Dmg1Lnk`
|
||||||
|
* `MacroLnk`
|
||||||
|
* `TYPE`
|
||||||
|
|
||||||
|
Each command takes the form:
|
||||||
|
|
||||||
|
```
|
||||||
|
<sprite-spec>:<command> <args>;
|
||||||
|
```
|
||||||
|
|
||||||
|
The sprite-spec can either be a single number, or a range of n-m.
|
||||||
|
|
||||||
|
### `DESTROY`
|
||||||
|
|
||||||
|
### `DEF`
|
||||||
|
|
||||||
|
I wonder if this `DEF`ines sprites an object, represented by an integer. In
|
||||||
|
`Data/Defs.dat`, we see sections that `EDIT <integer>`. Perhaps the two point to
|
||||||
|
the same thing?
|
||||||
|
|
||||||
|
`Assign/cabbage.asn` has `DEF 17` and `DEF 20`, covering two ranges of sprites.
|
||||||
|
`Data/Defs.dat` has `EDIT 17 # TREE LEAVES` and `EDIT 20 # NON-CENTERED CENTER
|
||||||
|
BUSHES`.
|
||||||
|
|
||||||
|
`Assign/TZEENTCH.asn` has `DEF 24` and `DEF 25`. `Data/Defs.dat` has `EDIT 24 #
|
||||||
|
SWITCHES & HOSES AS CENTER OBJS...RIGHT` and `EDIT 25 # SWITCHES & HOSES AS
|
||||||
|
CENTER OBJS...LEFT`.
|
||||||
|
|
||||||
|
`Assign/altar.asn` has `DEF 232`, and `Data/Defs.data` has `EDIT 232 # MRS
|
||||||
|
BUILDING PIECES - POOL TABLE`.
|
||||||
|
|
||||||
|
These all seem really close.
|
||||||
|
|
||||||
|
Then we have `EDIT 19 #big rocks` and these instances of `DEF 19;`:
|
||||||
|
|
||||||
|
```
|
||||||
|
Assign/grayroks.asn:5:0-7:DEF 19;
|
||||||
|
Assign/grayroks.asn:9:8-15:DEF 19;
|
||||||
|
Assign/sn_roks.asn:6:0-7:DEF 19;
|
||||||
|
Assign/sn_roks.asn:10:8-15:DEF 19;
|
||||||
|
```
|
||||||
|
|
||||||
|
The sprites for `grayroks` depicts some grey rocks, while `sn_roks` depicts
|
||||||
|
the same, but with snow on them. So this seems correct to me.
|
||||||
|
|
||||||
|
Does each object ID represent a unique thing? Or is it an index for a set of
|
||||||
|
characteristics that may be shared across multiple things? A set could quite
|
||||||
|
easily specify both `grayroks` and `sn_roks` for a map...
|
||||||
|
|
||||||
|
### `Dmg1Lnk`
|
||||||
|
|
||||||
|
This command is fairly easy. It takes a sprite-spec and says "if damage has been
|
||||||
|
sustained and you would normally display these sprites, display this sprite
|
||||||
|
instead". This is particularly obvious for the `cabbage` pair.
|
||||||
|
|
||||||
|
### `MacroLnk`
|
||||||
|
|
||||||
|
### `TYPE`
|
||||||
|
|
||||||
|
|
||||||
## WarHammer.ani
|
## WarHammer.ani
|
||||||
|
|
||||||
This 400MiB file appears to be a standard object file, it's just very large.
|
This 400MiB file appears to be a standard object file, it's just very large.
|
||||||
The directory contains 188,286 sprites!
|
The directory contains 188,286 sprites!
|
||||||
|
|
||||||
The first 1,064 sprites are all of the same Ultramarine, carryng a bolter. There
|
The field at 0x10 in each sprite header is set in `WarHammer.ani`, but not in
|
||||||
are eight "facing" orientations:
|
|
||||||
|
|
||||||
* North
|
|
||||||
* Northeast
|
|
||||||
* East
|
|
||||||
* Southeast
|
|
||||||
* South
|
|
||||||
* Southwest
|
|
||||||
* West
|
|
||||||
* Northwest
|
|
||||||
|
|
||||||
For each orientation, an action is pictured in a variable number of frames. The
|
|
||||||
final frame appears to be "stationary".
|
|
||||||
|
|
||||||
* Walk (13 frames)
|
|
||||||
* Run (9 frames)
|
|
||||||
* Crouch down (8 frames)
|
|
||||||
* Stand up (8 frames)
|
|
||||||
* Take aim (standing) (6 frames)
|
|
||||||
* Fire (standing) (6 frames)
|
|
||||||
* Relax aim (standing) (6 frames)
|
|
||||||
* Throw grenade (standing) (18 frames)
|
|
||||||
* Take aim (crouched) (5 frames)
|
|
||||||
* Fire (crouched) (5 frames)
|
|
||||||
* Relax aim (crouched) (5 frames)
|
|
||||||
* Throw grenade (crouched) (17 frames)
|
|
||||||
* Draw melee weapon (standing) (10 frames)
|
|
||||||
* Strike down with melee weapon (standing) (8 frames)
|
|
||||||
* Stab with melee weapon (standing) (9 frames)
|
|
||||||
|
|
||||||
Added together and multiplied by 87, that's 1064.
|
|
||||||
|
|
||||||
The next sprite is a walking-north action for an ultramarine with a flamer. The
|
|
||||||
total number of frames for this character is 1120 - 56 additional frames, or 7
|
|
||||||
per orientation. Could be an extra action, or an extra frame per action.
|
|
||||||
|
|
||||||
Also notable is that while the bolter showed muzzle flash in the animation, the
|
|
||||||
flamer only showed a tiny hint of fire. I think the animation for spewing flame
|
|
||||||
is held elsewhere.
|
|
||||||
|
|
||||||
I strongly suspect the actions and the number of frames in each action are
|
|
||||||
configurable. But where?
|
|
||||||
|
|
||||||
The field at 0x10 in the sprite header is set in `WarHammer.ani`, but not in
|
|
||||||
the other object files encountered so far. However, it seems to be
|
the other object files encountered so far. However, it seems to be
|
||||||
set statically to the bytes `[212 113 59 1]` for all of them.
|
set statically to the bytes `[212 113 59 1]` for all of them.
|
||||||
|
|
||||||
Assuming ~1000 sprites per character, `WarHammer.ani` contains 188 characters.
|
Assuming ~1000 sprites per character, `WarHammer.ani` contains 188 characters.
|
||||||
|
|
||||||
Two other files have been implicated in animation - `Data/AniObDefs.dat` and
|
Two other files have been implicated in animation - `Data/AniObDefs.dat` and
|
||||||
`Idx/WarHammer.idx`. More on those in `ani.md`.
|
`Idx/WarHammer.idx`. More on those in [ani.md](ani.md)
|
||||||
|
Reference in New Issue
Block a user