From 157f11010585bff29d9f3cb8152fa6991e409c44 Mon Sep 17 00:00:00 2001 From: "M. Sz" Date: Sat, 30 Jan 2021 17:09:37 +0100 Subject: [PATCH] data encoding: added COF encoder --- d2common/d2enum/composite_type_string.go | 4 ++ d2common/d2fileformats/d2cof/cof.go | 64 ++++++++++++++++++++++- d2common/d2fileformats/d2cof/cof_layer.go | 13 ++--- d2common/d2fileformats/d2dcc/dcc.go | 29 +++++++++- 4 files changed, 102 insertions(+), 8 deletions(-) diff --git a/d2common/d2enum/composite_type_string.go b/d2common/d2enum/composite_type_string.go index e9b1a46e..5400d78a 100644 --- a/d2common/d2enum/composite_type_string.go +++ b/d2common/d2enum/composite_type_string.go @@ -37,3 +37,7 @@ func (i CompositeType) String() string { } return _CompositeType_name[_CompositeType_index[i]:_CompositeType_index[i+1]] } + +func (i CompositeType) Int() int { + return int(i) +} diff --git a/d2common/d2fileformats/d2cof/cof.go b/d2common/d2fileformats/d2cof/cof.go index 685a2cd3..915cd58b 100644 --- a/d2common/d2fileformats/d2cof/cof.go +++ b/d2common/d2fileformats/d2cof/cof.go @@ -35,6 +35,10 @@ const ( // COF is a structure that represents a COF file. type COF struct { + // unknown bytes for header + unknownHeaderBytes []byte + // unknown bytes (first "body's" bytes) + unknown1 []byte NumberOfDirections int FramesPerDirection int NumberOfLayers int @@ -62,9 +66,19 @@ func Load(fileData []byte) (*COF, error) { result.NumberOfLayers = int(b[headerNumLayers]) result.FramesPerDirection = int(b[headerFramesPerDir]) result.NumberOfDirections = int(b[headerNumDirs]) + result.unknownHeaderBytes = b[headerNumDirs+1 : headerSpeed] result.Speed = int(b[headerSpeed]) - streamReader.SkipBytes(3) //nolint:gomnd // Unknown data + // read unknown bytes + // previous streamReader.SkipBytes(3) + for i := 0; i < 3; i++ { + b, errSR := streamReader.ReadByte() + if errSR != nil { + return nil, errSR + } + + result.unknown1 = append(result.unknown1, b) + } result.CofLayers = make([]CofLayer, result.NumberOfLayers) result.CompositeLayers = make(map[d2enum.CompositeType]int) @@ -83,6 +97,7 @@ func Load(fileData []byte) (*COF, error) { layer.Transparent = b[layerTransparent] > 0 layer.DrawEffect = d2enum.DrawEffect(b[layerDrawEffect]) + layer.weaponClassByte = b[layerWeaponClass:] layer.WeaponClass = d2enum.WeaponClassFromString(strings.TrimSpace(strings.ReplaceAll( string(b[layerWeaponClass:]), badCharacter, ""))) @@ -124,3 +139,50 @@ func Load(fileData []byte) (*COF, error) { return result, nil } + +// Unmarshal unmarshals COF into byte slince +func (c *COF) Unmarshal() []byte { + var result []byte + + result = append(result, byte(c.NumberOfLayers)) + result = append(result, byte(c.FramesPerDirection)) + result = append(result, byte(c.NumberOfDirections)) + result = append(result, c.unknownHeaderBytes...) + result = append(result, byte(c.Speed)) + result = append(result, c.unknown1...) + + for i := range c.CofLayers { + result = append(result, byte(c.CofLayers[i].Type.Int())) + result = append(result, c.CofLayers[i].Shadow) + + if c.CofLayers[i].Selectable { + result = append(result, byte(1)) + } else { + result = append(result, byte(0)) + } + + if c.CofLayers[i].Transparent { + result = append(result, byte(1)) + } else { + result = append(result, byte(0)) + } + + result = append(result, byte(c.CofLayers[i].DrawEffect)) + + result = append(result, c.CofLayers[i].weaponClassByte...) + } + + for _, i := range c.AnimationFrames { + result = append(result, byte(i)) + } + + for direction := 0; direction < c.NumberOfDirections; direction++ { + for frame := 0; frame < c.FramesPerDirection; frame++ { + for i := 0; i < c.NumberOfLayers; i++ { + result = append(result, byte(c.Priority[direction][frame][i])) + } + } + } + + return result +} diff --git a/d2common/d2fileformats/d2cof/cof_layer.go b/d2common/d2fileformats/d2cof/cof_layer.go index 8a09f9c1..2658e691 100644 --- a/d2common/d2fileformats/d2cof/cof_layer.go +++ b/d2common/d2fileformats/d2cof/cof_layer.go @@ -4,10 +4,11 @@ import "github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum" // CofLayer is a structure that represents a single layer in a COF file. type CofLayer struct { - Type d2enum.CompositeType - Shadow byte - Selectable bool - Transparent bool - DrawEffect d2enum.DrawEffect - WeaponClass d2enum.WeaponClass + Type d2enum.CompositeType + Shadow byte + Selectable bool + Transparent bool + DrawEffect d2enum.DrawEffect + WeaponClass d2enum.WeaponClass + weaponClassByte []byte } diff --git a/d2common/d2fileformats/d2dcc/dcc.go b/d2common/d2fileformats/d2dcc/dcc.go index ffd59e41..611674d4 100644 --- a/d2common/d2fileformats/d2dcc/dcc.go +++ b/d2common/d2fileformats/d2dcc/dcc.go @@ -1,6 +1,9 @@ package d2dcc import ( + //"fmt" + //"os" + "errors" "github.com/OpenDiablo2/OpenDiablo2/d2common/d2datautils" @@ -18,6 +21,7 @@ type DCC struct { Directions []*DCCDirection directionOffsets []int fileData []byte + size int32 } // Load loads a DCC file. @@ -44,7 +48,8 @@ func Load(fileData []byte) (*DCC, error) { return nil, errors.New("this value isn't 1. It has to be 1") } - bm.GetInt32() // TotalSizeCoded + size := bm.GetInt32() // TotalSizeCoded + result.size = size result.directionOffsets = make([]int, result.NumberOfDirections) @@ -53,9 +58,31 @@ func Load(fileData []byte) (*DCC, error) { result.Directions[i] = result.decodeDirection(i) } + /*fmt.Println(fileData) + fmt.Println("\n\n\n") + fmt.Println(result.Encode()) + os.Exit(0)*/ + return result, nil } +func (d *DCC) Encode() []byte { + var result []byte + + result = append(result, byte(d.Signature)) + result = append(result, byte(d.Version)) + result = append(result, byte(d.NumberOfDirections)) + result = append(result, byte(d.FramesPerDirection)) + result = append(result, 0, 0, 0, 1) + result = append(result, 0, 0, 0, byte(d.size), 84, 4, 0) + + for i := 0; i < d.NumberOfDirections; i++ { + result = append(result, byte(d.directionOffsets[i])) + } + + return result +} + // decodeDirection decodes and returns the given direction func (d *DCC) decodeDirection(direction int) *DCCDirection { return CreateDCCDirection(d2datautils.CreateBitMuncher(d.fileData,