mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2024-11-04 17:27:16 -05:00
File format cleanup (#320)
* Configuration cleanup * Cleanup * cleanup file formats * make palettes a proper fileformat
This commit is contained in:
parent
0f7571a5b9
commit
a4efd41383
@ -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
|
||||
|
||||
}
|
||||
|
21
d2common/d2fileformats/d2dat/d2dat.go
Normal file
21
d2common/d2fileformats/d2dat/d2dat.go
Normal 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
|
||||
}
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user