protected void CalcOffset(Wz_File wzFile, IEnumerable <Wz_Image> imgList) { foreach (var img in imgList) { img.Offset = wzFile.CalcOffset(img.HashedOffsetPosition, img.HashedOffset); } }
public void LoadImg(string fileName, Wz_Node node) { Wz_File file = null; try { file = new Wz_File(fileName, this); file.TextEncoding = this.TextEncoding; var imgNode = new Wz_Node(node.Text); //跳过checksum检测 var img = new Wz_Image(node.Text, (int)file.FileStream.Length, 0, 0, 0, file) { OwnerNode = imgNode, Offset = 0, IsChecksumChecked = true }; imgNode.Value = img; node.Nodes.Add(imgNode); this.wz_files.Add(file); } catch { file?.Close(); throw; } }
/// <summary> /// 搜索node所属的wz_file,若搜索不到则返回null。 /// </summary> /// <param Name="node">要搜索的wznode。</param> /// <returns></returns> public static Wz_File GetNodeWzFile(this Wz_Node node, bool returnClosestWzFile = false) { Wz_File wzfile = null; while (node != null) { if ((wzfile = node.Value as Wz_File) != null) { if (wzfile.OwnerWzFile != null) { wzfile = wzfile.OwnerWzFile; node = wzfile.Node; } if (!wzfile.IsSubDir || returnClosestWzFile) { break; } } else if (node.Value is Wz_Image wzImg || (wzImg = (node as Wz_Image.Wz_ImageNode)?.Image) != null) { wzfile = GetImageWzFile(wzImg, returnClosestWzFile); break; } node = node.ParentNode; } return(wzfile); }
public bool IsKMST1125WzFormat(string fileName) { if (!string.Equals(Path.GetExtension(fileName), ".wz", StringComparison.OrdinalIgnoreCase)) { return(false); } string iniFile = Path.ChangeExtension(fileName, ".ini"); if (!File.Exists(iniFile)) { return(false); } // check if the file is an empty wzfile using (var file = new Wz_File(fileName, this)) { if (!file.Loaded) { return(false); } var tempNode = new Wz_Node(); if (!this.encryption.encryption_detected) { this.encryption.DetectEncryption(file); } file.FileStream.Position = file.Header.DataStartPosition; file.GetDirTree(tempNode); return(file.ImageCount == 0); } }
public bool Verify(Wz_File wzFile) { List <Wz_Image> imgList = EnumerableAllWzImage(wzFile.node).Where(_img => _img.WzFile == wzFile).ToList(); if (wzFile.header.VersionChecked) { this.CalcOffset(wzFile, imgList); } else { // find the wzImage with minimum size. Wz_Image minSizeImg = imgList.DefaultIfEmpty().Aggregate((_img1, _img2) => _img1.Size < _img2.Size ? _img1 : _img2); if (minSizeImg == null && imgList.Count > 0) { minSizeImg = imgList[0]; } if (minSizeImg != null) { this.DetectWithWzImage(wzFile, minSizeImg); } else if (wzFile.directories.Count > 0) { this.DetectWithAllWzDir(wzFile); } if (wzFile.header.VersionChecked) { this.CalcOffset(wzFile, imgList); } } return(wzFile.header.VersionChecked); }
public bool Verify(Wz_File wzFile) { List <Wz_Image> imgList = EnumerableAllWzImage(wzFile.node).Where(_img => _img.WzFile == wzFile).ToList(); if (wzFile.header.VersionChecked) { this.CalcOffset(wzFile, imgList); } else { if (imgList.Count > 0) { this.FastDetectWithAllWzImages(wzFile, imgList); } else if (wzFile.directories.Count > 0) { this.DetectWithAllWzDir(wzFile); } if (wzFile.header.VersionChecked) { this.CalcOffset(wzFile, imgList); } } return(wzFile.header.VersionChecked); }
public Wz_File LoadFile(string fileName, Wz_Node node, bool useBaseWz = false, bool loadWzAsFolder = false) { Wz_File file = null; try { file = new Wz_File(fileName, this); if (!file.Loaded) { throw new Exception("The file is not a valid wz file."); } this.wz_files.Add(file); file.TextEncoding = this.TextEncoding; if (!this.encryption.encryption_detected) { this.encryption.DetectEncryption(file); } node.Value = file; file.Node = node; file.FileStream.Position = file.Header.DataStartPosition; file.GetDirTree(node, useBaseWz, loadWzAsFolder); file.DetectWzType(); file.DetectWzVersion(); return(file); } catch { if (file != null) { file.Close(); this.wz_files.Remove(file); } throw; } }
protected bool DetectWithAllWzDir(Wz_File wzFile) { while (wzFile.header.TryGetNextVersion()) { bool isSuccess = wzFile.directories.All(testDir => { uint offs = wzFile.CalcOffset(testDir.HashedOffsetPosition, testDir.HashedOffset); if (offs < wzFile.header.DataStartPosition || offs + 1 > wzFile.header.DirEndPosition) // dir offset out of file size. { return(false); } wzFile.fileStream.Position = offs; if (wzFile.fileStream.ReadByte() != 0) // for splitted wz format, dir data only contains one byte: 0x00 { return(false); } return(true); }); if (isSuccess) { wzFile.header.VersionChecked = true; break; } } return(wzFile.header.VersionChecked); }
protected bool DetectWithWzImage(Wz_File wzFile, Wz_Image testWzImg) { while (wzFile.header.TryGetNextVersion()) { uint offs = wzFile.CalcOffset(testWzImg.HashedOffsetPosition, testWzImg.HashedOffset); if (offs < wzFile.header.DirEndPosition || offs + testWzImg.Size > wzFile.fileStream.Length) //img offset out of file size { continue; } wzFile.fileStream.Position = offs; var firstByte = (byte)wzFile.fileStream.ReadByte(); if (!FastCheckFirstByte(testWzImg, firstByte)) { continue; } testWzImg.Offset = offs; if (!testWzImg.TryExtract()) { continue; } testWzImg.Unextract(); wzFile.header.VersionChecked = true; break; } return(wzFile.header.VersionChecked); }
public void LoadFile(string fileName, Wz_Node node, bool useBaseWz) { Wz_File file; try { file = new Wz_File(fileName, this); file.TextEncoding = this.TextEncoding; if (!this.encryption.encryption_detected) { this.encryption.DetectEncryption(file); } this.wz_files.Add(file); node.Value = file; file.Node = node; file.FileStream.Position = 62; file.GetDirTree(node, useBaseWz); file.DetectWzType(); file.DetectWzVersion(); } catch { throw; } }
public Wz_Png(int w, int h, int data_length, int form, int offs, Wz_File wz_f) { this.w = w; this.h = h; this.data_length = data_length; this.form = form; this.offs = offs; this.wz_f = wz_f; }
public Wz_Sound(int offset, int length, byte[] header, int ms, Wz_File wz_f) { this.offset = offset; this.dataLength = length; this.header = header; this.ms = ms; this.wz_f = wz_f; TryDecryptHeader(); }
public Wz_Image(string name, int size, int cs32, uint hashOff, uint hashPos, Wz_File wz_f) { this.Name = name; this.WzFile = wz_f; this.Size = size; this.Checksum = cs32; this.HashedOffset = hashOff; this.HashedOffsetPosition = hashPos; this.Node = new Wz_ImageNode(name, this); this.extr = false; this.chec = false; this.checEnc = false; }
public static int GetMergedVersion(this Wz_File wzFile) { if (wzFile.Header.WzVersion != 0) { return(wzFile.Header.WzVersion); } foreach (var subFile in wzFile.MergedWzFiles) { if (subFile.Header.WzVersion != 0) { return(subFile.Header.WzVersion); } } return(0); }
protected bool FastDetectWithAllWzImages(Wz_File wzFile, IList <Wz_Image> imgList) { var imageSizes = new SizeRange[imgList.Count]; while (wzFile.header.TryGetNextVersion()) { int count = 0; bool isSuccess = imgList.All(img => { uint offs = wzFile.CalcOffset(img.HashedOffsetPosition, img.HashedOffset); if (offs < wzFile.header.DirEndPosition || offs + img.Size > wzFile.fileStream.Length) //img offset out of file size { return(false); } imageSizes[count++] = new SizeRange() { Start = offs, End = offs + img.Size, }; return(true); }); if (isSuccess) { // check if there's any image overlaps with another image. Array.Sort(imageSizes, 0, count); for (int i = 1; i < count; i++) { if (imageSizes[i - 1].End > imageSizes[i].Start) { isSuccess = false; break; } } if (isSuccess) { wzFile.header.VersionChecked = true; break; } } } return(wzFile.header.VersionChecked); }
public void MergeWzFile(Wz_File wz_File) { var children = wz_File.node.Nodes.ToList(); wz_File.node.Nodes.Clear(); foreach (var child in children) { this.node.Nodes.Add(child); } if (this.mergedWzFiles == null) { this.mergedWzFiles = new List <Wz_File>(); } this.mergedWzFiles.Add(wz_File); wz_File.ownerWzFile = this; }
/// <summary> /// 搜索node所属的wz_file,若搜索不到则返回null。 /// </summary> /// <param Name="node">要搜索的wznode。</param> /// <returns></returns> public static Wz_File GetNodeWzFile(this Wz_Node node) { Wz_File wzfile = null; Wz_Image wzImg = null; while (node != null) { if ((wzfile = node.Value as Wz_File) != null) { break; } if ((wzImg = node.Value as Wz_Image) != null || (wzImg = (node as Wz_Image.Wz_ImageNode)?.Image) != null) { wzfile = wzImg.WzFile; break; } node = node.ParentNode; } return(wzfile); }
public Wz_Directory(string name, int size, int cs32, uint hashOff, uint hashPos, Wz_File wz_f) { this.Name = name; this.WzFile = wz_f; this.Size = size; this.Checksum = cs32; this.HashedOffset = hashOff; this.HashedOffsetPosition = hashPos; }
public void DetectEncryption(Wz_File f) { int old_off = (int)f.FileStream.Position; f.FileStream.Position = f.Header.DataStartPosition; if (f.ReadInt32() <= 0) //只有文件头 无法预判 { return; } f.FileStream.Position++; int len = (int)(-f.BReader.ReadSByte()); byte[] bytes = f.BReader.ReadBytes(len); for (int i = 0; i < len; i++) { bytes[i] ^= (byte)(0xAA + i); } StringBuilder sb = new StringBuilder(); if (!this.encryption_detected) { //测试bms sb.Clear(); for (int i = 0; i < len; i++) { sb.Append((char)(keys_bms[i] ^ bytes[i])); } if (IsLegalNodeName(sb.ToString())) { this.EncType = Wz_CryptoKeyType.BMS; this.encryption_detected = true; goto lbl_end; } //测试kms sb.Clear(); for (int i = 0; i < len; i++) { sb.Append((char)(keys_kms[i] ^ bytes[i])); } if (IsLegalNodeName(sb.ToString())) { this.EncType = Wz_CryptoKeyType.KMS; this.encryption_detected = true; goto lbl_end; } //测试gms sb.Clear(); for (int i = 0; i < len; i++) { sb.Append((char)(keys_gms[i] ^ bytes[i])); } if (IsLegalNodeName(sb.ToString())) { this.EncType = Wz_CryptoKeyType.GMS; this.encryption_detected = true; goto lbl_end; } } lbl_end: f.FileStream.Position = old_off; }