File format cleanup (#320)

* Configuration cleanup

* Cleanup

* cleanup file formats

* make palettes a proper fileformat
This commit is contained in:
Alex Yatskov 2020-02-26 05:39:38 -08:00 committed by GitHub
parent 0f7571a5b9
commit a4efd41383
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 110 additions and 123 deletions

View File

@ -2,33 +2,21 @@ package d2datadict
import (
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2enum"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dat"
)
// PaletteRGB represents a color in a palette
type PaletteRGB struct {
R, G, B uint8
}
// PaletteType represents a palette
type PaletteRec struct {
Name d2enum.PaletteType
Colors [256]PaletteRGB
Colors [256]d2dat.DATColor
}
var Palettes map[d2enum.PaletteType]PaletteRec
// CreatePalette creates a palette
func CreatePalette(name d2enum.PaletteType, data []byte) PaletteRec {
result := PaletteRec{Name: name}
for i := 0; i <= 255; i++ {
result.Colors[i] = PaletteRGB{
B: data[i*3],
G: data[(i*3)+1],
R: data[(i*3)+2],
}
}
return result
palette, _ := d2dat.LoadDAT(data)
return PaletteRec{Name: name, Colors: palette.Colors}
}
func LoadPalette(paletteType d2enum.PaletteType, file []byte) {
@ -37,5 +25,4 @@ func LoadPalette(paletteType d2enum.PaletteType, file []byte) {
}
palette := CreatePalette(paletteType, file)
Palettes[paletteType] = palette
}

View File

@ -0,0 +1,21 @@
package d2dat
type DATColor struct {
R uint8
G uint8
B uint8
}
type DATPalette struct {
Colors [256]DATColor
}
func LoadDAT(data []byte) (*DATPalette, error) {
palette := &DATPalette{}
for i := 0; i < 256; i++ {
palette.Colors[i] = DATColor{B: data[i*3], G: data[i*3+1], R: data[i*3+2]}
}
return palette, nil
}

View File

@ -2,9 +2,7 @@ package d2dc6
import (
"encoding/binary"
"log"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
"github.com/go-restruct/restruct"
)
@ -19,7 +17,6 @@ type DC6File struct {
FramePointers []uint32 `struct:"[]uint32,size=Directions*FramesPerDirection"`
Frames []*DC6Frame `struct-size:"Directions*FramesPerDirection"`
valid bool
}
type DC6Header struct {
@ -53,83 +50,16 @@ type DC6Frame struct {
Length uint32 `struct:"uint32,sizeof=FrameData"`
FrameData []byte
Terminator []byte `struct:"[3]byte"`
colorData []byte
palette d2datadict.PaletteRec
valid bool
}
func (frame *DC6Frame) ColorData() []byte {
if frame.colorData == nil {
frame.completeLoad()
}
return frame.colorData
}
func (frame *DC6Frame) completeLoad() {
frame.valid = true
indexData := make([]int16, frame.Width*frame.Height)
for fi := range indexData {
indexData[fi] = -1
}
x := uint32(0)
y := frame.Height - 1
dataPointer := 0
for {
b := frame.FrameData[dataPointer]
dataPointer++
if b == 0x80 {
if y == 0 {
break
}
y--
x = 0
} else if (b & 0x80) > 0 {
transparentPixels := b & 0x7F
for ti := byte(0); ti < transparentPixels; ti++ {
indexData[x+(y*frame.Width)+uint32(ti)] = -1
}
x += uint32(transparentPixels)
} else {
for bi := 0; bi < int(b); bi++ {
indexData[x+(y*frame.Width)+uint32(bi)] = int16(frame.FrameData[dataPointer])
dataPointer++
}
x += uint32(b)
}
}
// Probably don't need this data again
frame.FrameData = nil
frame.colorData = make([]byte, int(frame.Width*frame.Height)*4)
for i := uint32(0); i < frame.Width*frame.Height; i++ {
if indexData[i] < 1 { // TODO: Is this == -1 or < 1?
continue
}
frame.colorData[i*4] = frame.palette.Colors[indexData[i]].R
frame.colorData[(i*4)+1] = frame.palette.Colors[indexData[i]].G
frame.colorData[(i*4)+2] = frame.palette.Colors[indexData[i]].B
frame.colorData[(i*4)+3] = 0xFF
}
}
// LoadDC6 uses restruct to read the binary dc6 data into structs then parses image data from the frame data.
func LoadDC6(data []byte, palette d2datadict.PaletteRec) (DC6File, error) {
result := DC6File{valid: true}
func LoadDC6(data []byte) (*DC6File, error) {
result := &DC6File{}
restruct.EnableExprBeta()
err := restruct.Unpack(data, binary.LittleEndian, &result)
if err != nil {
result.valid = false
log.Printf("failed to read dc6: %v", err)
}
for _, frame := range result.Frames {
frame.palette = palette
return nil, err
}
return result, err

View File

@ -24,8 +24,8 @@ type DS1 struct {
SubstitutionGroups []SubstitutionGroup
}
func LoadDS1(fileData []byte) DS1 {
ds1 := DS1{
func LoadDS1(fileData []byte) (*DS1, error) {
ds1 := &DS1{
NumberOfFloors: 1,
NumberOfWalls: 1,
NumberOfShadowLayers: 1,
@ -243,5 +243,5 @@ func LoadDS1(fileData []byte) DS1 {
}
}
}
return ds1
return ds1, nil
}

View File

@ -1,7 +1,7 @@
package d2dt1
import (
"log"
"fmt"
"github.com/OpenDiablo2/OpenDiablo2/d2common"
)
@ -19,13 +19,13 @@ const (
BlockFormatIsometric BlockDataFormat = 1
)
func LoadDT1(fileData []byte) DT1 {
result := DT1{}
func LoadDT1(fileData []byte) (*DT1, error) {
result := &DT1{}
br := d2common.CreateStreamReader(fileData)
ver1 := br.GetInt32()
ver2 := br.GetInt32()
if ver1 != 7 || ver2 != 6 {
log.Panicf("Expected to have a version of 7.6, but got %d.%d instead", ver1, ver2)
return nil, fmt.Errorf("Expected to have a version of 7.6, but got %d.%d instead", ver1, ver2)
}
br.SkipBytes(260)
numberOfTiles := br.GetInt32()
@ -79,5 +79,5 @@ func LoadDT1(fileData []byte) DT1 {
}
}
return result
return result, nil
}

View File

@ -6,7 +6,7 @@ import (
"math"
"github.com/OpenDiablo2/OpenDiablo2/d2common"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dat"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dc6"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dcc"
@ -53,7 +53,7 @@ type Animation struct {
subEndingFrame int
}
func createAnimationFromDCC(dcc *d2dcc.DCC, palette *d2datadict.PaletteRec, transparency int) (*Animation, error) {
func createAnimationFromDCC(dcc *d2dcc.DCC, palette *d2dat.DATPalette, transparency int) (*Animation, error) {
animation := &Animation{
playLength: 1.0,
playLoop: true,
@ -115,7 +115,7 @@ func createAnimationFromDCC(dcc *d2dcc.DCC, palette *d2datadict.PaletteRec, tran
return animation, nil
}
func createAnimationFromDC6(dc6 *d2dc6.DC6File) (*Animation, error) {
func createAnimationFromDC6(dc6 *d2dc6.DC6File, palette *d2dat.DATPalette) (*Animation, error) {
animation := &Animation{
playLength: 1.0,
playLoop: true,
@ -128,7 +128,52 @@ func createAnimationFromDC6(dc6 *d2dc6.DC6File) (*Animation, error) {
return nil, err
}
if err := image.ReplacePixels(dc6Frame.ColorData()); err != nil {
indexData := make([]int, dc6Frame.Width*dc6Frame.Height)
for i := range indexData {
indexData[i] = -1
}
x := 0
y := int(dc6Frame.Height) - 1
offset := 0
for {
b := int(dc6Frame.FrameData[offset])
offset++
if b == 0x80 {
if y == 0 {
break
}
y--
x = 0
} else if b&0x80 > 0 {
transparentPixels := b & 0x7f
for i := 0; i < transparentPixels; i++ {
indexData[x+y*int(dc6Frame.Width)+i] = -1
}
x += transparentPixels
} else {
for i := 0; i < b; i++ {
indexData[x+y*int(dc6Frame.Width)+i] = int(dc6Frame.FrameData[offset])
offset++
}
x += b
}
}
colorData := make([]byte, dc6Frame.Width*dc6Frame.Height*4)
for i := 0; i < int(dc6Frame.Width*dc6Frame.Height); i++ {
if indexData[i] < 1 { // TODO: Is this == -1 or < 1?
continue
}
colorData[i*4] = palette.Colors[indexData[i]].R
colorData[i*4+1] = palette.Colors[indexData[i]].G
colorData[i*4+2] = palette.Colors[indexData[i]].B
colorData[i*4+3] = 0xff
}
if err := image.ReplacePixels(colorData); err != nil {
return nil, err
}

View File

@ -30,12 +30,17 @@ func (am *animationManager) loadAnimation(animationPath, palettePath string, tra
ext := strings.ToLower(filepath.Ext(animationPath))
switch ext {
case ".dc6":
dc6, err := loadDC6(animationPath, palettePath)
dc6, err := loadDC6(animationPath)
if err != nil {
return nil, err
}
animation, err = createAnimationFromDC6(dc6)
palette, err := loadPalette(palettePath)
if err != nil {
return nil, err
}
animation, err = createAnimationFromDC6(dc6, palette)
if err != nil {
return nil, err
}

View File

@ -3,8 +3,8 @@ package d2asset
import (
"errors"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2cof"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dat"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dc6"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dcc"
)
@ -22,28 +22,23 @@ type assetManager struct {
fontManager *fontManager
}
func loadPalette(palettePath string) (*d2datadict.PaletteRec, error) {
func loadPalette(palettePath string) (*d2dat.DATPalette, error) {
verifyWasInit()
return singleton.paletteManager.loadPalette(palettePath)
}
func loadDC6(dc6Path, palettePath string) (*d2dc6.DC6File, error) {
func loadDC6(dc6Path string) (*d2dc6.DC6File, error) {
dc6Data, err := LoadFile(dc6Path)
if err != nil {
return nil, err
}
paletteData, err := loadPalette(palettePath)
dc6, err := d2dc6.LoadDC6(dc6Data)
if err != nil {
return nil, err
}
dc6, err := d2dc6.LoadDC6(dc6Data, *paletteData)
if err != nil {
return nil, err
}
return &dc6, nil
return dc6, nil
}
func loadDCC(dccPath string) (*d2dcc.DCC, error) {

View File

@ -2,7 +2,7 @@ package d2asset
import (
"github.com/OpenDiablo2/OpenDiablo2/d2common"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2data/d2datadict"
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2dat"
)
type paletteManager struct {
@ -17,9 +17,9 @@ func createPaletteManager() *paletteManager {
return &paletteManager{d2common.CreateCache(paletteBudget)}
}
func (pm *paletteManager) loadPalette(palettePath string) (*d2datadict.PaletteRec, error) {
func (pm *paletteManager) loadPalette(palettePath string) (*d2dat.DATPalette, error) {
if palette, found := pm.cache.Retrieve(palettePath); found {
return palette.(*d2datadict.PaletteRec), nil
return palette.(*d2dat.DATPalette), nil
}
paletteData, err := LoadFile(palettePath)
@ -27,7 +27,11 @@ func (pm *paletteManager) loadPalette(palettePath string) (*d2datadict.PaletteRe
return nil, err
}
palette := d2datadict.CreatePalette("", paletteData)
pm.cache.Insert(palettePath, &palette, 1)
return &palette, nil
palette, err := d2dat.LoadDAT(paletteData)
if err != nil {
return nil, err
}
pm.cache.Insert(palettePath, palette, 1)
return palette, nil
}

View File

@ -80,7 +80,7 @@ type MapRegion struct {
levelType d2datadict.LevelTypeRecord
levelPreset d2datadict.LevelPresetRecord
tiles []d2dt1.Tile
ds1 d2ds1.DS1
ds1 *d2ds1.DS1
palette d2datadict.PaletteRec
startX float64
startY float64
@ -111,7 +111,7 @@ func loadRegion(seed int64, tileOffsetX, tileOffsetY int, levelType d2enum.Regio
panic(err)
}
dt1 := d2dt1.LoadDT1(fileData)
dt1, _ := d2dt1.LoadDT1(fileData)
region.tiles = append(region.tiles, dt1.Tiles...)
}
}
@ -137,7 +137,7 @@ func loadRegion(seed int64, tileOffsetX, tileOffsetY int, levelType d2enum.Regio
if err != nil {
panic(err)
}
region.ds1 = d2ds1.LoadDS1(fileData)
region.ds1, _ = d2ds1.LoadDS1(fileData)
region.tileRect = d2common.Rectangle{
Left: tileOffsetX,
Top: tileOffsetY,