A few more .idx realisations, and some parsing code

This commit is contained in:
2020-04-16 03:03:51 +01:00
parent beebfda3ba
commit b690c763bb
3 changed files with 98 additions and 50 deletions

View File

@@ -1,39 +1,58 @@
// package idx parses the Idx/WarHammer.idx file.
//
// No, I don't know what it's for yet.
// package idx parses the Idx/WarHammer.idx file. It groups the sprites in
// Anim/WarHammer.ani into playable animations.
package idx
import (
"encoding/binary"
//"fmt"
"log"
"fmt"
//"log"
"os"
//"strings"
)
type Type1Record struct {
Offset1 uint32 // Where the type2 for this type1 is to be found
Unknown1 uint32 // ???
Offset2 uint32 // Another offset? But what to?
}
type Type2Record struct {
Unknown1 [4]byte // ???
Offset uint32 // Where the type3 for this type2 is to be found
Unknown2 [4]byte // ??
}
type Type3Record struct {
First20 [20]byte
Last78 [78]byte
}
const (
NumGroups = 512 // Experimentally determined
)
type Idx struct {
Filename string
Groups []Group
}
Type1Records [512]Type1Record // Experimentally, there seem to be 512 of these
Type2Records []Type2Record
Type3Records []Type3Record
type Group struct {
Spec Spec
Records []Record
Details []Detail // Records and details are correlated by index
}
// type Spec links a set of animations to a starting sprite in WarHammer.ani
type Spec struct {
Offset uint32 // Where the Records for this Spec are to be found
Count uint32 // Number of Records for this Spec
SpriteIdx uint32 // Index of the first sprite in
}
type Record struct {
// A guess, but each group of 8 records with increasing compass points share
// this value.
ActionID uint16
Compass byte // It's odd to only have one byte. Maybe Unknown1 belongs to this too?
Unknown1 byte // ??? Only see values 0x33 and 0x00 for librarian.
Offset uint32 // Where the Detail for this Record is to be found.
NumFrames uint32 // A guess, but seems to fit. Number of frames for this action + compass.
}
type Detail struct {
FirstSprite uint16 // Relative offset from the group's SpriteIdx
LastSprite uint16 // Relative offset from the group's SpriteIdx
Unknown1 uint16 // Could also be LastSprite? Something else? AtRestSprite?
Unknown2 uint16 // Number of resting sprites, if we're AtRestSprite?
Padding [12]byte // Set to zero in the cases I've looked at so far.
// Remainder []byte // FIXME: no idea what this is yet, but we seem to have NumFrames*6 of them
}
func Load(filename string) (*Idx, error) {
@@ -44,29 +63,46 @@ func Load(filename string) (*Idx, error) {
defer f.Close()
out := &Idx{Filename: filename}
if err := binary.Read(f, binary.LittleEndian, &out.Type1Records); err != nil {
return nil, err
out := &Idx{
Filename: filename,
Groups: make([]Group, NumGroups),
}
for i, rec := range out.Type1Records {
var off1diff uint32
var off2diff uint32
var specs [NumGroups]Spec
if i > 0 && rec.Offset1 > 0 {
lastRec := out.Type1Records[i-1]
off1diff = rec.Offset1 - lastRec.Offset1
off2diff = rec.Offset2 - lastRec.Offset2
if err := binary.Read(f, binary.LittleEndian, &specs); err != nil {
return nil, fmt.Errorf("reading specs: %v", err)
}
for i, spec := range specs {
group := &out.Groups[i]
group.Spec = spec
group.Records = make([]Record, spec.Count)
group.Details = make([]Detail, spec.Count)
if _, err := f.Seek(int64(spec.Offset), 0); err != nil {
return nil, fmt.Errorf("spec %v: seeking: %v", i, err)
}
log.Printf(
"%.3d: 0x%.6x diff=%.6d %.4d 0x%.6x diff=%.6d",
i, rec.Offset1, off1diff, rec.Unknown1, rec.Offset2, off2diff,
// i,
// rec.Unknown1[0], rec.Unknown1[1], rec.Unknown1[2], rec.Unknown1[3],
// rec.Unknown1[4], rec.Unknown1[5], rec.Unknown1[6], rec.Unknown1[7],
)
// We can read all records at once
if err := binary.Read(f, binary.LittleEndian, &group.Records); err != nil {
return nil, fmt.Errorf("spec %v: reading records: %v", i, err)
}
// But we need to step through the records to learn where to read details
for j, rec := range group.Records {
// group.Details[j].Remainder = make([]byte, rec.NumFrames*6)
if _, err := f.Seek(int64(rec.Offset), 0); err != nil {
return nil, fmt.Errorf("spec %v, record %v: seeking to detail: %v", i, j, err)
}
if err := binary.Read(f, binary.LittleEndian, &group.Details[j]); err != nil {
return nil, fmt.Errorf("spec %v, record %v: reading detail: %v", i, j, err)
}
}
out.Groups[i] = *group
}
return out, nil