diff --git a/d2common/d2fileformats/d2pl2/pl2.go b/d2common/d2fileformats/d2pl2/pl2.go new file mode 100644 index 00000000..40006f3c --- /dev/null +++ b/d2common/d2fileformats/d2pl2/pl2.go @@ -0,0 +1,63 @@ +package d2pl2 + +import ( + "encoding/binary" + + "github.com/go-restruct/restruct" +) + +type PL2File struct { + BasePalette PL2Palette + + LightLevelVariations [32]PL2PaletteTransform + InvColorVariations [16]PL2PaletteTransform + SelectedUintShift PL2PaletteTransform + AlphaBlend [3][256]PL2PaletteTransform + AdditiveBlend [256]PL2PaletteTransform + MultiplicativeBlend [256]PL2PaletteTransform + HueVariations [111]PL2PaletteTransform + RedTones PL2PaletteTransform + GreenTones PL2PaletteTransform + BlueTones PL2PaletteTransform + UnknownVariations [14]PL2PaletteTransform + MaxComponentBlend [256]PL2PaletteTransform + DarkendColorShift PL2PaletteTransform + + TextColors [13]PL2Color24Bits + TextColorShifts [13]PL2PaletteTransform +} + +type PL2Color struct { + R uint8 + G uint8 + B uint8 + _ uint8 +} + +type PL2Color24Bits struct { + R uint8 + G uint8 + B uint8 +} + +type PL2Palette struct { + Colors [256]PL2Color +} + +type PL2PaletteTransform struct { + Indices [256]uint8 +} + +// uses restruct to read the binary dc6 data into structs +func LoadPL2(data []byte) (*PL2File, error) { + result := &PL2File{} + + restruct.EnableExprBeta() + + err := restruct.Unpack(data, binary.LittleEndian, &result) + if err != nil { + return nil, err + } + + return result, nil +} diff --git a/d2common/d2resource/resource_paths.go b/d2common/d2resource/resource_paths.go index 5608ef8a..99341d90 100644 --- a/d2common/d2resource/resource_paths.go +++ b/d2common/d2resource/resource_paths.go @@ -280,4 +280,23 @@ const ( PaletteStatic = "/data/global/palette/static/pal.dat" PaletteTrademark = "/data/global/palette/trademark/pal.dat" PaletteUnits = "/data/global/palette/units/pal.dat" + + // --- Palette Transforms --- + + PaletteTransformAct1 = "/data/global/palette/act1/Pal.pl2" + PaletteTransformAct2 = "/data/global/palette/act2/Pal.pl2" + PaletteTransformAct3 = "/data/global/palette/act3/Pal.pl2" + PaletteTransformAct4 = "/data/global/palette/act4/Pal.pl2" + PaletteTransformAct5 = "/data/global/palette/act5/Pal.pl2" + PaletteTransformEndGame = "/data/global/palette/endgame/Pal.pl2" + PaletteTransformEndGame2 = "/data/global/palette/endgame2/Pal.pl2" + PaletteTransformFechar = "/data/global/palette/fechar/Pal.pl2" + PaletteTransformLoading = "/data/global/palette/loading/Pal.pl2" + PaletteTransformMenu0 = "/data/global/palette/menu0/Pal.pl2" + PaletteTransformMenu1 = "/data/global/palette/menu1/Pal.pl2" + PaletteTransformMenu2 = "/data/global/palette/menu2/Pal.pl2" + PaletteTransformMenu3 = "/data/global/palette/menu3/Pal.pl2" + PaletteTransformMenu4 = "/data/global/palette/menu4/Pal.pl2" + PaletteTransformSky = "/data/global/palette/sky/Pal.pl2" + PaletteTransformTrademark = "/data/global/palette/trademark/Pal.pl2" ) diff --git a/d2core/d2asset/asset_manager.go b/d2core/d2asset/asset_manager.go index 093835c0..6d9a5a6e 100644 --- a/d2core/d2asset/asset_manager.go +++ b/d2core/d2asset/asset_manager.go @@ -14,11 +14,12 @@ var ( ) type assetManager struct { - archiveManager *archiveManager - fileManager *fileManager - paletteManager *paletteManager - animationManager *animationManager - fontManager *fontManager + archiveManager *archiveManager + fileManager *fileManager + paletteManager *paletteManager + paletteTransformManager *paletteTransformManager + animationManager *animationManager + fontManager *fontManager } func loadDC6(dc6Path string) (*d2dc6.DC6File, error) { diff --git a/d2core/d2asset/d2asset.go b/d2core/d2asset/d2asset.go index 7751036b..53617530 100644 --- a/d2core/d2asset/d2asset.go +++ b/d2core/d2asset/d2asset.go @@ -9,6 +9,7 @@ import ( "github.com/OpenDiablo2/OpenDiablo2/d2core/d2config" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2term" + "github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2pl2" ) var singleton *assetManager @@ -17,18 +18,20 @@ func Initialize() error { verifyNotInit() var ( - config = d2config.Get() - archiveManager = createArchiveManager(config) - fileManager = createFileManager(config, archiveManager) - paletteManager = createPaletteManager() - animationManager = createAnimationManager() - fontManager = createFontManager() + config = d2config.Get() + archiveManager = createArchiveManager(config) + fileManager = createFileManager(config, archiveManager) + paletteManager = createPaletteManager() + paletteTransformManager = createPaletteTransformManager() + animationManager = createAnimationManager() + fontManager = createFontManager() ) singleton = &assetManager{ archiveManager, fileManager, paletteManager, + paletteTransformManager, animationManager, fontManager, } @@ -43,6 +46,7 @@ func Initialize() error { archiveManager.cache.SetVerbose(verbose) fileManager.cache.SetVerbose(verbose) paletteManager.cache.SetVerbose(verbose) + paletteTransformManager.cache.SetVerbose(verbose) animationManager.cache.SetVerbose(verbose) }) @@ -50,6 +54,7 @@ func Initialize() error { d2term.OutputInfo("archive cache: %f", float64(archiveManager.cache.GetWeight())/float64(archiveManager.cache.GetBudget())*100.0) d2term.OutputInfo("file cache: %f", float64(fileManager.cache.GetWeight())/float64(fileManager.cache.GetBudget())*100.0) d2term.OutputInfo("palette cache: %f", float64(paletteManager.cache.GetWeight())/float64(paletteManager.cache.GetBudget())*100.0) + d2term.OutputInfo("palette transform cache: %f", float64(paletteTransformManager.cache.GetWeight())/float64(paletteTransformManager.cache.GetBudget())*100.0) d2term.OutputInfo("animation cache: %f", float64(animationManager.cache.GetWeight())/float64(animationManager.cache.GetBudget())*100.0) d2term.OutputInfo("font cache: %f", float64(fontManager.cache.GetWeight())/float64(fontManager.cache.GetBudget())*100.0) }) @@ -58,6 +63,7 @@ func Initialize() error { archiveManager.cache.Clear() fileManager.cache.Clear() paletteManager.cache.Clear() + paletteTransformManager.cache.Clear() animationManager.cache.Clear() fontManager.cache.Clear() }) @@ -95,6 +101,11 @@ func LoadAnimation(animationPath, palettePath string) (*Animation, error) { return LoadAnimationWithTransparency(animationPath, palettePath, 255) } +func LoadPaletteTransform(pl2Path string) (*d2pl2.PL2File, error) { + verifyWasInit() + return singleton.paletteTransformManager.loadPaletteTransform(pl2Path) +} + func LoadAnimationWithTransparency(animationPath, palettePath string, transparency int) (*Animation, error) { verifyWasInit() return singleton.animationManager.loadAnimation(animationPath, palettePath, transparency) diff --git a/d2core/d2asset/palette_transform_manager.go b/d2core/d2asset/palette_transform_manager.go new file mode 100644 index 00000000..86eb5c9f --- /dev/null +++ b/d2core/d2asset/palette_transform_manager.go @@ -0,0 +1,37 @@ +package d2asset + +import ( + "github.com/OpenDiablo2/OpenDiablo2/d2common" + "github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2pl2" +) + +type paletteTransformManager struct { + cache *d2common.Cache +} + +const ( + paletteTransformBudget = 64 +) + +func createPaletteTransformManager() *paletteTransformManager { + return &paletteTransformManager{d2common.CreateCache(paletteTransformBudget)} +} + +func (pm *paletteTransformManager) loadPaletteTransform(path string) (*d2pl2.PL2File, error) { + if pl2, found := pm.cache.Retrieve(path); found { + return pl2.(*d2pl2.PL2File), nil + } + + data, err := LoadFile(path); + if err != nil { + return nil, err + } + + pl2, err := d2pl2.LoadPL2(data) + if err != nil { + return nil, err + } + + pm.cache.Insert(path, pl2, 1) + return pl2, nil +}