HonorLee 5 months ago
parent
commit
8641be7c5a

+ 59 - 20
CrossgateToolkit/Anime.cs

@@ -11,6 +11,7 @@
 using System;
 using System.Collections.Generic;
 using System.IO;
+using System.Linq;
 using UnityEngine;
 
 namespace CrossgateToolkit
@@ -58,15 +59,30 @@ namespace CrossgateToolkit
     //动画数据
     public class AnimeDetail
     {
+        // 动画编号
         public uint Serial;
+        // 动画版本
         public string Version;
+        // 方向
         public int Direction;
+        // 动作
         public int ActionType;
+        // 动画循环时间
         public uint CycleTime;
+        // 帧数
         public uint FrameCount;
+
+        // 高版本 - 标识
+        public bool IsHighVersion;
+        // 高版本 - 调色板
+        public int Palet;
+        // 高版本 - 图像反转
+        public bool Reverse;
+        // 高版本 - 结束标识
+        public byte[] END_FLAG;
         public Dictionary<int,Texture2D> AnimeTextures = new Dictionary<int, Texture2D>();
         // public Texture2D AnimeTexture;
-        public AnimeFrameInfo[] AnimeFrameInfos;
+        public List<AnimeFrameInfo> AnimeFrameInfos;
         // public byte[] unknown;
     }
     //动画相关Enum类型
@@ -132,6 +148,8 @@ namespace CrossgateToolkit
             Once,
             OnceAndDestroy
         }
+        private static byte[] highVersionFlag = { 0xFF, 0xFF, 0xFF, 0xFF };
+        
         //动画列表缓存    Serial -> AnimeInfo
         private static Dictionary<uint, AnimeInfo> _animeInfoCache = new Dictionary<uint, AnimeInfo>();
         
@@ -143,9 +161,16 @@ namespace CrossgateToolkit
             FileStream dataFileStream = animeFile.OpenRead();
             BinaryReader infoFileReader = new BinaryReader(infoFileStream);
             BinaryReader dataFileReader = new BinaryReader(dataFileStream);
-
-            // Dictionary<uint, AnimeInfo> animeInfos = new Dictionary<uint, AnimeInfo>();
+            
             long DataLength = infoFileStream.Length / 12;
+            
+            //判断是否为高版本
+            bool isHighVersion = false;
+            dataFileStream.Position = 0x10;
+            byte[] tmpBytes = dataFileReader.ReadBytes(4);
+            if(tmpBytes.SequenceEqual(highVersionFlag)) isHighVersion = true;
+            
+            // 循环初始化动画数据
             for (int i = 0; i < DataLength; i++)
             {
                 //初始化对象
@@ -166,41 +191,49 @@ namespace CrossgateToolkit
                     animeData.ActionType = dataFileReader.ReadUInt16();
                     animeData.CycleTime = BitConverter.ToUInt32(dataFileReader.ReadBytes(4),0);
                     animeData.FrameCount = BitConverter.ToUInt32(dataFileReader.ReadBytes(4),0);
-                    animeData.AnimeFrameInfos = new AnimeFrameInfo[animeData.FrameCount];
-
-                    
+                    // 高版本
+                    if (isHighVersion)
+                    {
+                        animeData.IsHighVersion = true;
+                        animeData.Palet = dataFileReader.ReadUInt16();
+                        animeData.Reverse = dataFileReader.ReadUInt16() % 2 == 1;
+                        animeData.END_FLAG = dataFileReader.ReadBytes(4);
+                    }
+                    animeData.AnimeFrameInfos = new List<AnimeFrameInfo>();
                     
                     // if (animeInfo.Index == 101201) Debug.Log("----------------------------------");
                     for (int k = 0; k < animeData.FrameCount; k++)
                     {
-                        animeData.AnimeFrameInfos[k] = new AnimeFrameInfo();
+                        byte[] frameBytes = dataFileReader.ReadBytes(10);
+                        BinaryReader frameReader = new BinaryReader(new MemoryStream(frameBytes));
+                        AnimeFrameInfo animeFrameInfo = new AnimeFrameInfo();
                         //GraphicIndex序号
-                        animeData.AnimeFrameInfos[k].GraphicIndex = BitConverter.ToUInt32(dataFileReader.ReadBytes(4),0);
-                        animeData.AnimeFrameInfos[k].OffsetX = BitConverter.ToInt16(dataFileReader.ReadBytes(2),0);
-                        animeData.AnimeFrameInfos[k].OffsetY = BitConverter.ToInt16(dataFileReader.ReadBytes(2),0);
+                        animeFrameInfo.GraphicIndex = BitConverter.ToUInt32(frameReader.ReadBytes(4),0);
+                        animeFrameInfo.OffsetX = BitConverter.ToInt16(frameReader.ReadBytes(2),0);
+                        animeFrameInfo.OffsetY = BitConverter.ToInt16(frameReader.ReadBytes(2),0);
                         
                         //标识位
-                        int flag = BitConverter.ToInt16(dataFileReader.ReadBytes(2),0);
-
-                        // if (animeData.Index == 110053) Debug.Log("FLAG---" + " " + k + "  " + flag);
+                        int flag = BitConverter.ToInt16(frameReader.ReadBytes(2),0);
 
                         if (flag>20000)
                         {
                             //击打判定
-                            animeData.AnimeFrameInfos[k].Effect = EffectType.Hit;
-                            animeData.AnimeFrameInfos[k].AudioIndex = flag - 20000;
+                            animeFrameInfo.Effect = EffectType.Hit;
+                            animeFrameInfo.AudioIndex = flag - 20000;
                         }
                         else if(flag>10000)
                         {
                             //攻击动作结束判定
-                            animeData.AnimeFrameInfos[k].Effect = EffectType.HitOver;
-                            animeData.AnimeFrameInfos[k].AudioIndex = flag - 10000;
+                            animeFrameInfo.Effect = EffectType.HitOver;
+                            animeFrameInfo.AudioIndex = flag - 10000;
                         }
                         else
                         {
-                            animeData.AnimeFrameInfos[k].AudioIndex = flag;
+                            animeFrameInfo.AudioIndex = flag;
                         }
+                        animeData.AnimeFrameInfos.Add(animeFrameInfo);
                     }
+                    animeData.FrameCount = (uint) animeData.AnimeFrameInfos.Count;
 
                     if (!animeInfo.AnimeDatas.ContainsKey(animeData.Direction))
                         animeInfo.AnimeDatas.Add(animeData.Direction, new Dictionary<int, AnimeDetail>());
@@ -218,7 +251,11 @@ namespace CrossgateToolkit
             infoFileStream.Close();
             dataFileStream.Close();
             
-            Debug.Log("[CGTool] 加载AnimeInfo - 文件: " + animeInfoFile.Name + " 动画总量: " + DataLength);
+            Debug.Log("[CGTool] 加载AnimeInfo - 文件: [" +
+                      // (Graphic.Flag_HighVersion[Version] ? "H" : "N") + "] [" +
+                      Version + "] " +
+                      animeInfoFile.Name +
+                      " 动画总量: " + DataLength);
         }
         
         //获取动画数据信息
@@ -263,7 +300,9 @@ namespace CrossgateToolkit
                 //载入图档
                 GraphicInfoData graphicInfoData = GraphicInfo.GetGraphicInfoDataByIndex(animeDetail.Version,animeDetail.AnimeFrameInfos[i].GraphicIndex);
                 if (graphicInfoData == null) continue;
-                GraphicDetail graphicDetail = GraphicData.GetGraphicDetail(graphicInfoData, palet);
+                int subPaletIndex = 0;
+                if (animeDetail.IsHighVersion) subPaletIndex = (int)animeDetail.Serial;
+                GraphicDetail graphicDetail = GraphicData.GetGraphicDetail(graphicInfoData, palet, subPaletIndex);
                 if(graphicDetail == null) continue;
                 graphicDetails[i] = graphicDetail;
                 if(graphicDetail.Height > textureHeight) textureHeight = graphicDetail.Height;

+ 22 - 3
CrossgateToolkit/AnimePlayer.cs

@@ -314,7 +314,7 @@ namespace CrossgateToolkit
             {
                 Anime.BakeAnimeFrames(animeOption.AnimeDetail, _paletIndex);
                 //获取动画帧数据
-                for (int i = 0; i < animeOption.AnimeDetail.AnimeFrameInfos.Length; i++)
+                for (int i = 0; i < animeOption.AnimeDetail.AnimeFrameInfos.Count; i++)
                 {
                     if(!animeOption.AnimeDetail.AnimeFrameInfos[i].AnimeSprites.ContainsKey(_paletIndex)) continue;
                     if(animeOption.AnimeDetail.AnimeFrameInfos[i].AnimeSprites[_paletIndex] == null) continue;
@@ -329,7 +329,7 @@ namespace CrossgateToolkit
             else
             {
                 //获取动画帧数据
-                for (int i = 0; i < animeOption.AnimeDetail.AnimeFrameInfos.Length; i++)
+                for (int i = 0; i < animeOption.AnimeDetail.AnimeFrameInfos.Count; i++)
                 {
                     AnimeFrameInfo animeFrameInfo = animeOption.AnimeDetail.AnimeFrameInfos[i];
                     GraphicInfoData graphicInfoData = GraphicInfo.GetGraphicInfoDataByIndex(
@@ -341,7 +341,10 @@ namespace CrossgateToolkit
                         continue;
                     }
 
-                    GraphicDetail graphicData = GraphicData.GetGraphicDetail(graphicInfoData, _paletIndex);
+                    int subPaletIndex = 0;
+                    if (animeOption.AnimeDetail.IsHighVersion) subPaletIndex = (int)animeOption.AnimeDetail.Serial;
+                    GraphicDetail graphicData =
+                        GraphicData.GetGraphicDetail(graphicInfoData, _paletIndex, subPaletIndex);
                     if (graphicData == null)
                     {
                         Debug.Log("GraphicData Serial:" +
@@ -504,6 +507,14 @@ namespace CrossgateToolkit
             {
                 _imageRenderer.sprite = _frames[_currentFrame].Sprite;
                 _imageRenderer.SetNativeSize();
+                if (_currentAnime.AnimeDetail.Reverse)
+                {
+                    _imageRenderer.transform.localScale = new Vector3(-1, 1, 1);
+                }
+                else
+                {
+                    _imageRenderer.transform.localScale = new Vector3(1, 1, 1);
+                }
                 Vector3 pos = Vector3.zero;
                 pos.x = _frames[_currentFrame].GraphicInfo.OffsetX;
                 pos.y = -_frames[_currentFrame].GraphicInfo.OffsetY;
@@ -516,6 +527,14 @@ namespace CrossgateToolkit
                 _rectTransform.sizeDelta = new Vector2(width, height);
                 _spriteRenderer.size = new Vector2(width, height);
                 _rectTransform.pivot = new Vector2(0.5f,0f);
+                if (_currentAnime.AnimeDetail.Reverse)
+                {
+                    _spriteRenderer.flipX = true;
+                }
+                else
+                {
+                    _spriteRenderer.flipX = false;
+                }
                 _rectTransform.localPosition = Vector3.zero;
             }
             frameTexture = _frames[_currentFrame].Sprite.texture;

+ 46 - 8
CrossgateToolkit/Graphic.cs

@@ -30,6 +30,9 @@ namespace CrossgateToolkit
         private static List<FilePair> _graphicFilePairs = new List<FilePair>();
         private static List<FilePair> _animeFilePairs = new List<FilePair>();
         
+        // 高版本号标识
+        // public static readonly Dictionary<string,bool> Flag_HighVersion = new Dictionary<string, bool>(); 
+        
         // 初始化
         public static void Init()
         {
@@ -61,10 +64,42 @@ namespace CrossgateToolkit
             }
         }
 
+        // 版本号分析
+        private class VersionInfo
+        {
+            public string Version;
+            public int VersionCode;
+            public string FullVersion;
+        }
+        private static VersionInfo AnalysisVersion(string prefix,string filename)
+        {
+            VersionInfo versionInfo = new VersionInfo();
+            versionInfo.FullVersion = filename.Substring(prefix.Length);
+            string[] versionArr = versionInfo.FullVersion.Split('_');
+            if (String.IsNullOrEmpty(versionArr[0]))
+            {
+                versionArr = versionArr.Skip(1).ToArray();
+            }
+
+            if (int.TryParse(versionArr[0], out int code))
+            {
+                versionInfo.VersionCode = code;
+            }
+            else
+            {
+                versionInfo.Version = versionArr[0].ToUpper();
+                if(int.TryParse(versionArr[^1], out int vcode))
+                {
+                    versionInfo.VersionCode = vcode;
+                }
+            }
+            
+            return versionInfo;
+        }
         // 分析目录,并获取对应配对文件
         private static void AnalysisDirectory(DirectoryInfo directoryInfo)
         {
-            Debug.Log("[CGTool] 开始分析目录: " + directoryInfo.FullName);
+            // Debug.Log("[CGTool] 开始分析目录: " + directoryInfo.FullName);
             string Version = directoryInfo.Name;
             FileInfo[] fileInfos = directoryInfo.GetFiles();
             fileInfos = fileInfos.OrderBy(f => f.Name).ToArray();
@@ -72,14 +107,17 @@ namespace CrossgateToolkit
             {
                 if (!fileInfo.Name.EndsWith(".bin",StringComparison.OrdinalIgnoreCase)) continue;
                 int suffixIndex = fileInfo.Name.LastIndexOf('.');
-                string versionStr;
+                
+                // 解析版本号
+                string filename = fileInfo.Name.Substring(0, suffixIndex);
+                
                 if (fileInfo.Name.StartsWith("graphicinfo", StringComparison.OrdinalIgnoreCase))
                 {
                     // 找到GraphicInfo文件
                     // 获取对应版本号 GraphicInfo(*).bin
-                    versionStr = fileInfo.Name.Substring(11, suffixIndex - 11);
+                    VersionInfo versionInfo = AnalysisVersion("graphicinfo", filename);
                     // 判断是否存在对应graphic文件,忽略大小写
-                    string graphicFileName = "graphic" + versionStr + ".bin";
+                    string graphicFileName = "graphic" + versionInfo.FullVersion + ".bin";
                     FileInfo graphicFileInfo = GetFileInfoByName(fileInfo.Directory, graphicFileName);
                     if (!graphicFileInfo.Exists)
                     {
@@ -89,16 +127,16 @@ namespace CrossgateToolkit
                     {
                         InfoFile = fileInfo,
                         DataFile = graphicFileInfo,
-                        Version = Version
+                        Version = versionInfo.Version ?? Version
                     };
                     _graphicFilePairs.Add(filePair);
                 }else if (fileInfo.Name.StartsWith("animeinfo", StringComparison.OrdinalIgnoreCase))
                 {
                     // 找到AnimeInfo文件
                     // 获取对应版本号 AnimeInfo(*).bin
-                    versionStr = fileInfo.Name.Substring(9, suffixIndex - 9);
+                    VersionInfo versionInfo = AnalysisVersion("animeinfo", filename);
                     // 判断是否存在对应anime文件
-                    string animeFileName = "anime" + versionStr + ".bin";
+                    string animeFileName = "anime" + versionInfo.FullVersion + ".bin";
                     FileInfo animeFileInfo = GetFileInfoByName(fileInfo.Directory, animeFileName);
                     if (!animeFileInfo.Exists)
                     {
@@ -108,7 +146,7 @@ namespace CrossgateToolkit
                     {
                         InfoFile = fileInfo,
                         DataFile = animeFileInfo,
-                        Version = Version
+                        Version = versionInfo.Version ?? Version
                     };
                     _animeFilePairs.Add(filePair);
                 }

+ 202 - 27
CrossgateToolkit/GraphicData.cs

@@ -42,6 +42,9 @@ namespace CrossgateToolkit
         //图档主色调,用于小地图绘制
         public Color32 PrimaryColor;
     }
+    
+    
+    
     // 图档数据
     public static class GraphicData
     {
@@ -52,9 +55,8 @@ namespace CrossgateToolkit
         // public static Dictionary<uint,Dictionary<int,GraphicDetail>> _indexCache = new Dictionary<uint, Dictionary<int, GraphicDetail>>();
         
         public static Dictionary<GraphicInfoData,Dictionary<int,GraphicDetail>> _cache = new Dictionary<GraphicInfoData, Dictionary<int, GraphicDetail>>();
-        
         // 获取图档
-        public static GraphicDetail GetGraphicDetail(GraphicInfoData graphicInfoData, int palet = 0)
+        public static GraphicDetail GetGraphicDetail(GraphicInfoData graphicInfoData, int palet = 0,int subPalet = 0)
         {
             GraphicDetail graphicDetail = null;
             if (_cache.ContainsKey(graphicInfoData))
@@ -65,13 +67,13 @@ namespace CrossgateToolkit
                 }
                 else
                 {
-                    graphicDetail = _loadGraphicDetail(graphicInfoData, palet);
+                    graphicDetail = _loadGraphicDetail(graphicInfoData, palet, subPalet);
                     _cache[graphicInfoData].Add(palet, graphicDetail);
                 }
             }
             else
             {
-                graphicDetail = _loadGraphicDetail(graphicInfoData, palet);
+                graphicDetail = _loadGraphicDetail(graphicInfoData, palet, subPalet);
                 _cache.Add(graphicInfoData, new Dictionary<int, GraphicDetail>());
                 _cache[graphicInfoData].Add(palet, graphicDetail);
             }
@@ -80,12 +82,14 @@ namespace CrossgateToolkit
         }
         
         // 解析图档
-        private static GraphicDetail _loadGraphicDetail(GraphicInfoData graphicInfoData,int palet = 0)
+        private static GraphicDetail _loadGraphicDetail(GraphicInfoData graphicInfoData,int palet = 0,int subPalet = 0)
         {
             GraphicDetail graphicDetail = new GraphicDetail();
             
             //获取图像数据
-            List<Color32> pixels = UnpackGraphic(graphicInfoData, palet);
+            List<Color32> pixels = UnpackGraphic(graphicInfoData, palet, subPalet);
+            if(pixels==null) return null;
+            
             graphicDetail.PrimaryColor = pixels.Last();
             pixels.RemoveAt(pixels.Count - 1);
 
@@ -100,7 +104,7 @@ namespace CrossgateToolkit
 
             // RGBA4444 减少内存占用
             texture2D = new Texture2D((int) graphicInfoData.Width, (int) graphicInfoData.Height,
-                TextureFormat.RGBA4444, false, false);
+                TextureFormat.RGBA4444, false, true);
             // 固定点过滤
             texture2D.filterMode = FilterMode.Point;
             texture2D.SetPixels32(pixels.ToArray());
@@ -365,10 +369,10 @@ namespace CrossgateToolkit
         #endregion
         
         //解压图像数据
-        private static List<Color32> UnpackGraphic(GraphicInfoData graphicInfoData,int PaletIndex=0){
+        private static List<Color32> UnpackGraphic(GraphicInfoData graphicInfoData,int PaletIndex=0,int SubPaletIndex=0){
             List<Color32> pixels = new List<Color32>();
             //获取调色板
-            List<Color32> palet = Palet.GetPalet(PaletIndex);
+            List<Color32> palet;
 
             //调整流指针
             BinaryReader fileReader = graphicInfoData.GraphicReader;
@@ -381,31 +385,38 @@ namespace CrossgateToolkit
             BinaryReader contentReader = new BinaryReader(new MemoryStream(Content));
 
             //16字节头信息
-            byte[] HEAD = contentReader.ReadBytes(2);
+            byte[] RD = contentReader.ReadBytes(2);
             int Version = contentReader.ReadByte();
             int Unknow = contentReader.ReadByte();
             uint Width = contentReader.ReadUInt32();
             uint Height = contentReader.ReadUInt32();
-            uint Length = contentReader.ReadUInt32();
-
+            uint DataLen = contentReader.ReadUInt32();
+            uint innerPaletLen = 0;
+            
+            
+            // 低版本头部长度为16,高版本为20
+            int headLen = 16;
+            if (Version > 1)
+            {
+                headLen = 20;
+                innerPaletLen = contentReader.ReadUInt32();
+            }
             
             //数据长度
-            uint contentLen = Length - 16;
+            int contentLen = (int)(DataLen - headLen);
             int pixelLen = (int) (graphicInfoData.Width * graphicInfoData.Height);
-
+            
             int[] paletIndex;
             if (graphicInfoData.UnpackedPaletIndex == null)
             {
                 //解压数据
                 byte[] contentBytes = contentReader.ReadBytes((int) contentLen);
                 NativeArray<byte> bytes = new NativeArray<byte>((int) contentBytes.Length, Allocator.TempJob);
-                
                 bytes.CopyFrom(contentBytes);
-
-                // Debug.Log(contentBytes.Length + "   " + bytes.Length);
+                long decompressLen = pixelLen + innerPaletLen;
+                
                 NativeArray<int> colorIndexs =
-                    new NativeArray<int>(pixelLen, Allocator.TempJob);
-
+                    new NativeArray<int>((int)decompressLen, Allocator.TempJob);
 
                 DecompressJob decompressJob = new DecompressJob()
                 {
@@ -425,6 +436,31 @@ namespace CrossgateToolkit
                 paletIndex = graphicInfoData.UnpackedPaletIndex;
             }
 
+            if (SubPaletIndex > 0)
+            {
+                palet = Palet.GetPalet(SubPaletIndex);
+                if (palet == null)
+                {
+                    GraphicInfoData subPaletInfoData = GraphicInfo.GetGraphicInfoData((uint)SubPaletIndex);
+                    Graphic.GetGraphicDetail((uint)SubPaletIndex);
+                    palet = subPaletInfoData.InnerPalet;
+                    Palet.AddPalet(SubPaletIndex, palet);
+                }
+            }
+            else
+            {
+                if (innerPaletLen > 0)
+                {
+                    int[] innerPaletIndex = paletIndex.Skip(pixelLen).Take((int) innerPaletLen).ToArray();
+                    palet = AnalysisInnerPalet(innerPaletIndex).ToList();
+                    paletIndex = paletIndex.Take(pixelLen).ToArray();
+                    graphicInfoData.InnerPalet = palet;
+                }
+                else
+                {
+                    palet = Palet.GetPalet(PaletIndex);
+                }
+            }
             //释放连接
             contentReader.Dispose();
             contentReader.Close();
@@ -435,8 +471,15 @@ namespace CrossgateToolkit
             int b = 0;
             foreach (int index in paletIndex)
             {
-                // Debug.Log(index);
-                Color32 color32 = palet[index];
+                Color32 color32;
+                if (index == 999 || (index > palet.Count - 1))
+                {
+                    color32 = Color.clear;
+                }
+                else
+                {
+                    color32 = palet[index];   
+                }
                 pixels.Add(color32);
                 r += color32.r;
                 g += color32.g;
@@ -471,6 +514,137 @@ namespace CrossgateToolkit
             pixels.Add(new Color32((byte) r, (byte) g, (byte) b, 255));
             return pixels;
         }
+
+        //分析高版本内部调色板
+        private static Color32[] AnalysisInnerPalet(int[] bytes)
+        {
+            int colorLen = bytes.Length / 3;
+            Color32[] palet = new Color32[colorLen + 1];
+            for (var i = 0; i < colorLen; i++)
+            {
+                int[] paletBytes = bytes.Skip(i * 3).Take(3).ToArray();
+                Color32 color32 = new Color32();
+                color32.r = (byte)paletBytes[2];
+                color32.g = (byte)paletBytes[1];
+                color32.b = (byte)paletBytes[0];
+                color32.a = 0xFF;
+                palet[i] = color32;
+            }
+            palet[colorLen] = Color.clear;
+            return palet;
+        }
+
+        #region 测试解压
+        private static int[] TestDecompress(byte[] bytes)
+        {
+            List<int> colorIndexs = new List<int>();
+            int _index = -1;
+
+            int next()
+            {
+                _index++;
+                if (_index > bytes.Length - 1) return -1;
+                return bytes[_index];
+            }
+
+            while (_index < (bytes.Length - 1))
+            {
+                int head = next();
+                if (head == -1) break;
+
+                int repeat = 0;
+                if (head < 0x10)
+                {
+                    repeat = head;
+                    for (var i = 0; i < repeat; i++)
+                    {
+                        colorIndexs.Add(next());
+                    }
+
+                }
+                else if (head < 0x20)
+                {
+                    repeat = head % 0x10 * 0x100 + next();
+                    for (var i = 0; i < repeat; i++)
+                    {
+                        colorIndexs.Add(next());
+                    }
+
+                }
+                else if (head < 0x80)
+                {
+                    repeat = head % 0x20 * 0x10000 + next() * 0x100 + next();
+                    for (var i = 0; i < repeat; i++)
+                    {
+                        colorIndexs.Add(next());
+                    }
+
+                }
+                else if (head < 0x90)
+                {
+                    repeat = head % 0x80;
+                    int index = next();
+                    for (var i = 0; i < repeat; i++)
+                    {
+                        colorIndexs.Add(index);
+                    }
+
+                }
+                else if (head < 0xa0)
+                {
+                    int index = next();
+                    repeat = head % 0x90 * 0x100 + next();
+                    for (var i = 0; i < repeat; i++)
+                    {
+                        colorIndexs.Add(index);
+                    }
+
+                }
+                else if (head < 0xc0)
+                {
+                    int index = next();
+                    repeat = head % 0xa0 * 0x10000 + next() * 0x100 + next();
+                    for (var i = 0; i < repeat; i++)
+                    {
+                        colorIndexs.Add(index);
+                    }
+
+                }
+                else if (head < 0xd0)
+                {
+                    repeat = head % 0xc0;
+                    for (var i = 0; i < repeat; i++)
+                    {
+                        colorIndexs.Add(999);
+                    }
+
+                }
+                else if (head < 0xe0)
+                {
+                    repeat = head % 0xd0 * 0x100 + next();
+                    for (var i = 0; i < repeat; i++)
+                    {
+                        colorIndexs.Add(999);
+                    }
+
+                }
+                else if (head < 0xff)
+                {
+                    repeat = head % 0xe0 * 0x10000 + next() * 0x100 + next();
+                    for (var i = 0; i < repeat; i++)
+                    {
+                        colorIndexs.Add(999);
+                    }
+                }
+            }
+
+            return colorIndexs.ToArray();
+
+
+        }
+
+        #endregion 测试解压
+        
     }
     
         //解压缩交给IJob处理
@@ -494,6 +668,7 @@ namespace CrossgateToolkit
         }
         private void AddColorIndex(int index)
         {
+            if (_colorIndex > colorIndexs.Length - 1) return;
             colorIndexs[_colorIndex] = index;
             _colorIndex++;
         }
@@ -508,9 +683,9 @@ namespace CrossgateToolkit
             {
                 while (_index<=_maxIndex)
                 {
-                    int index = NextByte();
-                    if(index==-1) break;
-                    AddColorIndex(index);
+                    int pindex = NextByte();
+                    if(pindex==-1) break;
+                    AddColorIndex(pindex);
                 }
             }
             else
@@ -586,7 +761,7 @@ namespace CrossgateToolkit
                         repeat = head % 0xc0;
                         for (var i = 0; i < repeat; i++)
                         {
-                            AddColorIndex(256);
+                            AddColorIndex(999);
                         }
     
                     }
@@ -595,7 +770,7 @@ namespace CrossgateToolkit
                         repeat = head % 0xd0 * 0x100 + NextByte();
                         for (var i = 0; i < repeat; i++)
                         {
-                            AddColorIndex(256);
+                            AddColorIndex(999);
                         }
     
                     }
@@ -604,7 +779,7 @@ namespace CrossgateToolkit
                         repeat = head % 0xe0 * 0x10000 + NextByte() * 0x100 + NextByte();
                         for (var i = 0; i < repeat; i++)
                         {
-                            AddColorIndex(256);
+                            AddColorIndex(999);
                         }
                     }
                 }

+ 8 - 4
CrossgateToolkit/GraphicInfo.cs

@@ -50,8 +50,10 @@ namespace CrossgateToolkit
         // GraphicInfo附加数据
         // GraphicInfo对应Graphic文件流读取器
         public BinaryReader GraphicReader;
+        public byte VERSION_FLAG;
         //已解压的调色板索引
         public int[] UnpackedPaletIndex;
+        public List<Color32> InnerPalet;
     }
 
     public class GraphicInfo:MonoBehaviour
@@ -91,15 +93,13 @@ namespace CrossgateToolkit
                 graphicInfoData.Unknow = fileReader.ReadBytes(4);
                 graphicInfoData.Serial = BitConverter.ToUInt32(fileReader.ReadBytes(4),0);
                 graphicInfoData.GraphicReader = graphicFileReader;
-
+                
                 //建立Index映射表
                 _indexCache[Version][graphicInfoData.Index] = graphicInfoData;
                 
                 //建立Serial映射表
                 if (graphicInfoData.Serial != 0) _cache[graphicInfoData.Serial] = graphicInfoData;
 
-
-
                 // _logger.Write("Index: " + graphicInfoData.Index + " Addr: " + graphicInfoData.Addr + 
                 //               " Width: " + graphicInfoData.Width + 
                 //               " Height: " + graphicInfoData.Height +
@@ -111,7 +111,11 @@ namespace CrossgateToolkit
                 //               " Unknow: " + BitConverter.ToString(graphicInfoData.Unknow).Replace("-", ",") +
                 //               " MapSerial: " + graphicInfoData.MapSerial);
             }
-            Debug.Log("[CGTool] 加载GraphicInfo - 文件: " + graphicInfoFile.Name + " 贴图总量: " + DataLength);
+
+            Debug.Log("[CGTool] 加载GraphicInfo - 文件: [" +
+                      // (Graphic.Flag_HighVersion[Version] ? "H" : "N") + "] [" +
+                      Version + "] " +
+                      graphicInfoFile.Name + " 贴图总量: " + DataLength);
         }
         
         //获取GraphicInfoData

+ 14 - 4
CrossgateToolkit/Palet.cs

@@ -39,15 +39,25 @@ namespace CrossgateToolkit
             foreach (FileInfo file in files)
             {
                 if (!file.Name.StartsWith("palet_") || !file.Name.EndsWith(".cgp")) continue;
-                string indexStr = file.Name.Substring(6, 2);
-                int index = Convert.ToInt32(indexStr);
-                List<Color32> paletData = _loadPalet(file);
-                if (paletData != null) _cache.Add(index, paletData);
+                string tmp = file.Name.Split("_")[1];
+                string indexStr = tmp.Split(".")[0];
+                // string indexStr = file.Name.Substring(6, 2);
+                if (int.TryParse(indexStr, out int index))
+                {
+                    List<Color32> paletData = _loadPalet(file);
+                    if (paletData != null) _cache.Add(index, paletData);    
+                }
             }
 
             Debug.Log("[CGTool] 调色板初始化完成,共加载" + _cache.Count + "个调色板");
         }
         
+        // 添加新调色板
+        public static void AddPalet(int index, List<Color32> paletData)
+        {
+            _cache[index] = paletData;
+        }
+        
         //加载缓存数据
         private static List<Color32> _loadPalet(FileInfo paletFile)
         {

BIN
Preview/AnimeHSupport.gif


BIN
Preview/PUK3Graphic.jpg


+ 135 - 0
Preview/PUK3Graphic.jpg.meta

@@ -0,0 +1,135 @@
+fileFormatVersion: 2
+guid: 62bc4f4bd580d4207b843fb0416ca42f
+TextureImporter:
+  internalIDToNameTable: []
+  externalObjects: {}
+  serializedVersion: 12
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 0
+    sRGBTexture: 1
+    linearTexture: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapsPreserveCoverage: 0
+    alphaTestReferenceValue: 0.5
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: 0.25
+    normalMapFilter: 0
+  isReadable: 0
+  streamingMipmaps: 0
+  streamingMipmapsPriority: 0
+  vTOnly: 0
+  ignoreMasterTextureLimit: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 6
+  cubemapConvolution: 0
+  seamlessCubemap: 0
+  textureFormat: 1
+  maxTextureSize: 2048
+  textureSettings:
+    serializedVersion: 2
+    filterMode: 1
+    aniso: 1
+    mipBias: 0
+    wrapU: 1
+    wrapV: 1
+    wrapW: 1
+  nPOTScale: 0
+  lightmap: 0
+  compressionQuality: 50
+  spriteMode: 1
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: 0.5, y: 0.5}
+  spritePixelsToUnits: 100
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spriteGenerateFallbackPhysicsShape: 1
+  alphaUsage: 1
+  alphaIsTransparency: 1
+  spriteTessellationDetail: -1
+  textureType: 8
+  textureShape: 1
+  singleChannelComponent: 0
+  flipbookRows: 1
+  flipbookColumns: 1
+  maxTextureSizeSet: 0
+  compressionQualitySet: 0
+  textureFormatSet: 0
+  ignorePngGamma: 0
+  applyGammaDecoding: 0
+  cookieLightType: 0
+  platformSettings:
+  - serializedVersion: 3
+    buildTarget: DefaultTexturePlatform
+    maxTextureSize: 2048
+    resizeAlgorithm: 0
+    textureFormat: -1
+    textureCompression: 1
+    compressionQuality: 50
+    crunchedCompression: 0
+    allowsAlphaSplitting: 0
+    overridden: 0
+    androidETC2FallbackOverride: 0
+    forceMaximumCompressionQuality_BC6H_BC7: 0
+  - serializedVersion: 3
+    buildTarget: Standalone
+    maxTextureSize: 2048
+    resizeAlgorithm: 0
+    textureFormat: -1
+    textureCompression: 1
+    compressionQuality: 50
+    crunchedCompression: 0
+    allowsAlphaSplitting: 0
+    overridden: 0
+    androidETC2FallbackOverride: 0
+    forceMaximumCompressionQuality_BC6H_BC7: 0
+  - serializedVersion: 3
+    buildTarget: Android
+    maxTextureSize: 2048
+    resizeAlgorithm: 0
+    textureFormat: -1
+    textureCompression: 1
+    compressionQuality: 50
+    crunchedCompression: 0
+    allowsAlphaSplitting: 0
+    overridden: 0
+    androidETC2FallbackOverride: 0
+    forceMaximumCompressionQuality_BC6H_BC7: 0
+  - serializedVersion: 3
+    buildTarget: Server
+    maxTextureSize: 2048
+    resizeAlgorithm: 0
+    textureFormat: -1
+    textureCompression: 1
+    compressionQuality: 50
+    crunchedCompression: 0
+    allowsAlphaSplitting: 0
+    overridden: 0
+    androidETC2FallbackOverride: 0
+    forceMaximumCompressionQuality_BC6H_BC7: 0
+  spriteSheet:
+    serializedVersion: 2
+    sprites: []
+    outline: []
+    physicsShape: []
+    bones: []
+    spriteID: 5e97eb03825dee720800000000000000
+    internalID: 0
+    vertices: []
+    indices: 
+    edges: []
+    weights: []
+    secondaryTextures: []
+    nameFileIdTable: {}
+  spritePackingTag: 
+  pSDRemoveMatte: 0
+  pSDShowRemoveMatteOption: 0
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

BIN
Preview/V3Anime.jpg


+ 135 - 0
Preview/V3Anime.jpg.meta

@@ -0,0 +1,135 @@
+fileFormatVersion: 2
+guid: 60f5b634bb7de4ee1987e1b6048522fa
+TextureImporter:
+  internalIDToNameTable: []
+  externalObjects: {}
+  serializedVersion: 12
+  mipmaps:
+    mipMapMode: 0
+    enableMipMap: 0
+    sRGBTexture: 1
+    linearTexture: 0
+    fadeOut: 0
+    borderMipMap: 0
+    mipMapsPreserveCoverage: 0
+    alphaTestReferenceValue: 0.5
+    mipMapFadeDistanceStart: 1
+    mipMapFadeDistanceEnd: 3
+  bumpmap:
+    convertToNormalMap: 0
+    externalNormalMap: 0
+    heightScale: 0.25
+    normalMapFilter: 0
+  isReadable: 0
+  streamingMipmaps: 0
+  streamingMipmapsPriority: 0
+  vTOnly: 0
+  ignoreMasterTextureLimit: 0
+  grayScaleToAlpha: 0
+  generateCubemap: 6
+  cubemapConvolution: 0
+  seamlessCubemap: 0
+  textureFormat: 1
+  maxTextureSize: 2048
+  textureSettings:
+    serializedVersion: 2
+    filterMode: 1
+    aniso: 1
+    mipBias: 0
+    wrapU: 1
+    wrapV: 1
+    wrapW: 1
+  nPOTScale: 0
+  lightmap: 0
+  compressionQuality: 50
+  spriteMode: 1
+  spriteExtrude: 1
+  spriteMeshType: 1
+  alignment: 0
+  spritePivot: {x: 0.5, y: 0.5}
+  spritePixelsToUnits: 100
+  spriteBorder: {x: 0, y: 0, z: 0, w: 0}
+  spriteGenerateFallbackPhysicsShape: 1
+  alphaUsage: 1
+  alphaIsTransparency: 1
+  spriteTessellationDetail: -1
+  textureType: 8
+  textureShape: 1
+  singleChannelComponent: 0
+  flipbookRows: 1
+  flipbookColumns: 1
+  maxTextureSizeSet: 0
+  compressionQualitySet: 0
+  textureFormatSet: 0
+  ignorePngGamma: 0
+  applyGammaDecoding: 0
+  cookieLightType: 0
+  platformSettings:
+  - serializedVersion: 3
+    buildTarget: DefaultTexturePlatform
+    maxTextureSize: 2048
+    resizeAlgorithm: 0
+    textureFormat: -1
+    textureCompression: 1
+    compressionQuality: 50
+    crunchedCompression: 0
+    allowsAlphaSplitting: 0
+    overridden: 0
+    androidETC2FallbackOverride: 0
+    forceMaximumCompressionQuality_BC6H_BC7: 0
+  - serializedVersion: 3
+    buildTarget: Standalone
+    maxTextureSize: 2048
+    resizeAlgorithm: 0
+    textureFormat: -1
+    textureCompression: 1
+    compressionQuality: 50
+    crunchedCompression: 0
+    allowsAlphaSplitting: 0
+    overridden: 0
+    androidETC2FallbackOverride: 0
+    forceMaximumCompressionQuality_BC6H_BC7: 0
+  - serializedVersion: 3
+    buildTarget: Android
+    maxTextureSize: 2048
+    resizeAlgorithm: 0
+    textureFormat: -1
+    textureCompression: 1
+    compressionQuality: 50
+    crunchedCompression: 0
+    allowsAlphaSplitting: 0
+    overridden: 0
+    androidETC2FallbackOverride: 0
+    forceMaximumCompressionQuality_BC6H_BC7: 0
+  - serializedVersion: 3
+    buildTarget: Server
+    maxTextureSize: 2048
+    resizeAlgorithm: 0
+    textureFormat: -1
+    textureCompression: 1
+    compressionQuality: 50
+    crunchedCompression: 0
+    allowsAlphaSplitting: 0
+    overridden: 0
+    androidETC2FallbackOverride: 0
+    forceMaximumCompressionQuality_BC6H_BC7: 0
+  spriteSheet:
+    serializedVersion: 2
+    sprites: []
+    outline: []
+    physicsShape: []
+    bones: []
+    spriteID: 5e97eb03825dee720800000000000000
+    internalID: 0
+    vertices: []
+    indices: 
+    edges: []
+    weights: []
+    secondaryTextures: []
+    nameFileIdTable: {}
+  spritePackingTag: 
+  pSDRemoveMatte: 0
+  pSDShowRemoveMatteOption: 0
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 

+ 18 - 4
README.md

@@ -21,8 +21,10 @@
 ![预览](Preview/Preview.png)
 
 ## 2、功能支持
-> 当前版本目前仅支持 魔力宝贝3.7-龙之沙漏 及以下版本的图档解析
-> 
+> 当前版本目前已支持 魔力宝贝3.7-龙之沙漏 及以下版本的图档解析,以及 4.0 版本以上图档、动画数据解析
+>
+> <font color="red">注意:当前版本 4.0 及以上地图暂不支持</font>
+>
 > 目前版本支持以下功能:
 > 
 > * `GraphicInfo` [图档索引解析](#获取图档索引数据)
@@ -36,8 +38,13 @@
 >   * `AnimePlayer` 动画关键帧(攻击/攻击完成)事件回调
 >   * `AnimePlayer` 音频帧事件回调
 
-![动画效果](Preview/AnimePlayer.png)
-![动画效果](Preview/AnimeSupport.gif)
+<div style="display: flex;flex-direction: column;align-items: center;">
+<div><img style="" src="Preview/AnimeSupport.gif"><img style="" src="Preview/AnimeHSupport.gif"></div>
+<div><img style="" src="Preview/AnimePlayer.png"></div>
+<div><img style="" src="Preview/PUK3Graphic.jpg"></div>
+
+</div>
+
 
 
 ## 3、使用说明
@@ -66,6 +73,8 @@ CGTool在初始化时对所配置图档根目录进行扫描,并按照``根目
 
 所涉及的所有Index则为图档序号、Serial为图档或动画的具体编号而非索引档中序号,实际使用时请注意区分
 
+
+
 其他相关部分会逐渐更新完善
 
 ### 框架初始化
@@ -307,6 +316,11 @@ player.Stop();
 
 
 ## 4、更新日志
+### v 2.2
+> `ADD` 增加 <font color="red">4.0 版本(乐园之卵)及后续版本图档、动画解析</font>
+>
+> `UPD` 调整图档目录版本号分析过程,以更好的适应多种图档目录结构
+
 ### v 2.1
 > `UPD` 图档合并方法进行统一处理,并增加地图相关简便方法