GraphicInfo.cs 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. /**
  2. * 魔力宝贝图档解析脚本 - CGTool
  3. *
  4. * @Author HonorLee (dev@honorlee.me)
  5. * @Version 1.0 (2023-04-15)
  6. * @License GPL-3.0
  7. *
  8. * GraphicInfo.cs 图档索引解析类
  9. */
  10. using System;
  11. using System.Collections.Generic;
  12. using System.IO;
  13. using UnityEngine;
  14. namespace CrossgateToolkit
  15. {
  16. //GraphicInfo数据块
  17. public class GraphicInfoData
  18. {
  19. // GraphicInfo基础数据
  20. //4 bytes 索引
  21. public uint Index;
  22. //4 bytes Graphic 地址
  23. public uint Addr;
  24. //4 bytes Graphic 数据长度
  25. public uint Length;
  26. //4 bytes Graphic 偏移 - X
  27. public int OffsetX;
  28. //4 bytes Graphic 偏移 - Y
  29. public int OffsetY;
  30. //4 bytes Graphic 宽
  31. public uint Width;
  32. //4 bytes Graphic 高
  33. public uint Height;
  34. //4 bytes Graphic East占地
  35. public int East;
  36. //4 bytes Graphic South 占地
  37. public int South;
  38. //bool 穿越标识
  39. public bool Blocked;
  40. //1 byte 作为地面无层级遮挡[Test]
  41. public bool AsGround;
  42. //4 bytes 未知标识
  43. public byte[] Unknow;
  44. //4 bytes 编号
  45. public uint Serial;
  46. // GraphicInfo附加数据
  47. // GraphicInfo对应Graphic文件流读取器
  48. public BinaryReader GraphicReader;
  49. public byte VERSION_FLAG;
  50. //已解压的调色板索引
  51. public byte[] UnpackedPaletIndex;
  52. public List<Color32> InnerPalet;
  53. public bool IsEncrypted;
  54. public EncryptInfo EncryptInfo;
  55. }
  56. public class EncryptInfo
  57. {
  58. public long PwdIndex;
  59. public int PwdLen;
  60. public byte[] Pwd;
  61. }
  62. public class GraphicInfo:MonoBehaviour
  63. {
  64. //索引字典 Serial -> GraphicInfoData
  65. private static readonly Dictionary<uint,GraphicInfoData> _cache = new Dictionary<uint, GraphicInfoData>();
  66. // private static readonly Dictionary<uint,GraphicInfoData> _indexCache = new Dictionary<uint, GraphicInfoData>();
  67. private static readonly Dictionary<string,Dictionary<uint,GraphicInfoData>> _indexCache = new Dictionary<string, Dictionary<uint, GraphicInfoData>>();
  68. public static void Init(string Version,FileInfo graphicInfoFile,FileInfo graphicFile)
  69. {
  70. if(!_indexCache.ContainsKey(Version)) _indexCache.Add(Version,new Dictionary<uint, GraphicInfoData>());
  71. //创建流读取器
  72. FileStream fileStream = graphicInfoFile.OpenRead();
  73. BinaryReader fileReader = new BinaryReader(fileStream);
  74. FileStream graphicFileStream = graphicFile.OpenRead();
  75. BinaryReader graphicFileReader = new BinaryReader(graphicFileStream);
  76. byte[] head = graphicFileReader.ReadBytes(3);
  77. bool isEncrypted = false;
  78. EncryptInfo encryptInfo = null;
  79. if (head[0] == 0x52 && head[1] == 0x44) isEncrypted = false;
  80. else
  81. {
  82. isEncrypted = true;
  83. bool fromHead = head[0] % 2 == 0;
  84. encryptInfo = new EncryptInfo();
  85. encryptInfo.PwdLen = head[2];
  86. // 密码索引
  87. if (fromHead)
  88. {
  89. encryptInfo.PwdIndex = 3 + head[1];
  90. }
  91. else
  92. {
  93. // 获取文件大小
  94. long fileSize = graphicFile.Length;
  95. encryptInfo.PwdIndex = fileSize - encryptInfo.PwdLen - 3 - head[1] + 3;
  96. }
  97. // 获取密码
  98. graphicFileStream.Position = encryptInfo.PwdIndex;
  99. encryptInfo.Pwd = graphicFileReader.ReadBytes(encryptInfo.PwdLen);
  100. // 密码解密
  101. byte[] keyCodes = new byte[CGTool.ENCRYPT_KEY.Length];
  102. for (var i = 0; i < CGTool.ENCRYPT_KEY.Length; i++)
  103. {
  104. // 获取秘钥的ASCII码
  105. byte code = (byte)(CGTool.ENCRYPT_KEY[i]);
  106. keyCodes[i] = code;
  107. }
  108. // 解密密码
  109. for (int i = 0; i < encryptInfo.PwdLen; i++)
  110. {
  111. for (var i1 = 0; i1 < keyCodes.Length; i1++)
  112. {
  113. encryptInfo.Pwd[i] = (byte)(encryptInfo.Pwd[i] ^ keyCodes[i1]);
  114. }
  115. }
  116. }
  117. //解析Info数据表
  118. long DataLength = fileStream.Length/40;
  119. for (int i = 0; i < DataLength; i++)
  120. {
  121. GraphicInfoData graphicInfoData = new GraphicInfoData();
  122. graphicInfoData.Index = BitConverter.ToUInt32(fileReader.ReadBytes(4),0);
  123. graphicInfoData.Addr = BitConverter.ToUInt32(fileReader.ReadBytes(4),0);
  124. graphicInfoData.Length = BitConverter.ToUInt32(fileReader.ReadBytes(4),0);
  125. graphicInfoData.OffsetX = BitConverter.ToInt32(fileReader.ReadBytes(4),0);
  126. graphicInfoData.OffsetY = BitConverter.ToInt32(fileReader.ReadBytes(4),0);
  127. graphicInfoData.Width = BitConverter.ToUInt32(fileReader.ReadBytes(4),0);
  128. graphicInfoData.Height = BitConverter.ToUInt32(fileReader.ReadBytes(4),0);
  129. graphicInfoData.East = fileReader.ReadByte();
  130. graphicInfoData.South = fileReader.ReadByte();
  131. graphicInfoData.Blocked = fileReader.ReadByte() % 2 == 0;
  132. graphicInfoData.AsGround = fileReader.ReadByte() == 1;
  133. graphicInfoData.Unknow = fileReader.ReadBytes(4);
  134. graphicInfoData.Serial = BitConverter.ToUInt32(fileReader.ReadBytes(4),0);
  135. graphicInfoData.GraphicReader = graphicFileReader;
  136. graphicInfoData.IsEncrypted = isEncrypted;
  137. graphicInfoData.EncryptInfo = encryptInfo;
  138. // if (graphicInfoData.Serial >= 220000 && graphicInfoData.Width == 64 && graphicInfoData.Height == 47 && graphicInfoData.Blocked)
  139. // {
  140. // Debug.LogError(graphicInfoData.Serial + "穿越" + Blocked);
  141. // }
  142. //建立Index映射表
  143. _indexCache[Version][graphicInfoData.Index] = graphicInfoData;
  144. //建立Serial映射表
  145. if (graphicInfoData.Serial != 0) _cache[graphicInfoData.Serial] = graphicInfoData;
  146. // _logger.Write("Index: " + graphicInfoData.Index + " Addr: " + graphicInfoData.Addr +
  147. // " Width: " + graphicInfoData.Width +
  148. // " Height: " + graphicInfoData.Height +
  149. // " OffsetX: " + graphicInfoData.OffsetX +
  150. // " OffsetY: " + graphicInfoData.OffsetY +
  151. // " East: " + graphicInfoData.East +
  152. // " South: " + graphicInfoData.South +
  153. // " Blocked: " + graphicInfoData.Blocked +
  154. // " Unknow: " + BitConverter.ToString(graphicInfoData.Unknow).Replace("-", ",") +
  155. // " MapSerial: " + graphicInfoData.MapSerial);
  156. }
  157. Debug.Log("[CGTool] 加载GraphicInfo - 文件: [" +
  158. // (Graphic.Flag_HighVersion[Version] ? "H" : "N") + "] [" +
  159. Version + "] " +
  160. graphicInfoFile.Name + " 贴图总量: " + DataLength + (isEncrypted ? " 加密图档" : ""));
  161. }
  162. //获取GraphicInfoData
  163. public static GraphicInfoData GetGraphicInfoData(uint Serial)
  164. {
  165. _cache.TryGetValue(Serial, out var graphicInfoData);
  166. return graphicInfoData;
  167. }
  168. public static GraphicInfoData GetGraphicInfoDataByIndex(string Version,uint Index)
  169. {
  170. _indexCache.TryGetValue(Version, out var indexDict);
  171. if(indexDict == null) throw new Exception("找不到对应版本的GraphicInfo数据");
  172. indexDict.TryGetValue(Index, out var graphicInfoData);
  173. return graphicInfoData;
  174. }
  175. }
  176. }