/// <summary> /// Checks whether a file is Lz77 compressed or not. /// </summary> /// <param name="file"></param> /// <returns></returns> public static bool IsLz77Compressed(Stream file) { Headers.HeaderType headerType = Headers.DetectHeader(file); byte[] buffer = new byte[4]; file.Seek((long)headerType, SeekOrigin.Begin); file.Read(buffer, 0, buffer.Length); return((int)Shared.Swap(BitConverter.ToUInt32(buffer, 0)) == (int)lz77Magic); }
/// <summary> /// Checks whether a file is Lz77 compressed or not. /// </summary> /// <param name="file"></param> /// <returns></returns> public static bool IsLz77Compressed(Stream file) { Headers.HeaderType h = Headers.DetectHeader(file); byte[] temp = new byte[4]; file.Seek((long)h, SeekOrigin.Begin); file.Read(temp, 0, temp.Length); return(Shared.Swap(BitConverter.ToUInt32(temp, 0)) == lz77Magic); }
/// <summary> /// Adds an IMET Header to the U8 file. /// </summary> /// <param name="shortImet"></param> /// <param name="titles"></param> public void AddHeaderImet(bool shortImet, params string[] titles) { if (iconSize == -1) { throw new Exception("icon.bin wasn't found!"); } else if (bannerSize == -1) { throw new Exception("banner.bin wasn't found!"); } else if (soundSize == -1) { throw new Exception("sound.bin wasn't found!"); } header = Headers.IMET.Create(shortImet, iconSize, bannerSize, soundSize, titles); headerType = (shortImet) ? Headers.HeaderType.ShortIMET : Headers.HeaderType.IMET; }
/// <summary> /// Checks whether a file is a U8 file or not. /// </summary> /// <param name="file"></param> /// <returns></returns> public static bool IsU8(byte[] file) { if (Lz77.IsLz77Compressed(file)) { byte[] partOfFile = new byte[(file.Length > 2000) ? 2000 : file.Length]; for (int i = 0; i < partOfFile.Length; i++) { partOfFile[i] = file[i]; } Lz77 l = new Lz77(); partOfFile = l.Decompress(partOfFile); return(IsU8(partOfFile)); } else { Headers.HeaderType h = Headers.DetectHeader(file); return(Shared.Swap(BitConverter.ToUInt32(file, (int)h)) == 0x55AA382D); } }
private void parseU8(Stream u8File) { fireDebug("Pasing U8 File..."); u8Header = new U8_Header(); rootNode = new U8_Node(); u8Nodes = new List<U8_Node>(); stringTable = new List<string>(); data = new List<byte[]>(); fireDebug(" Detecting Header..."); headerType = Headers.DetectHeader(u8File); Headers.HeaderType tempType = headerType; fireDebug(" -> {0}", headerType.ToString()); if (headerType == Headers.HeaderType.IMD5) { fireDebug(" Reading IMD5 Header..."); header = Headers.IMD5.Load(u8File); byte[] file = new byte[u8File.Length]; u8File.Read(file, 0, file.Length); MD5 m = MD5.Create(); byte[] newHash = m.ComputeHash(file, (int)headerType, (int)u8File.Length - (int)headerType); m.Clear(); if (!Shared.CompareByteArrays(newHash, ((Headers.IMD5)header).Hash)) { fireDebug(@"/!\ /!\ /!\ Hashes do not match /!\ /!\ /!\"); fireWarning(string.Format("Hashes of IMD5 header and file do not match! The content might be corrupted!")); } } else if (headerType == Headers.HeaderType.IMET || headerType == Headers.HeaderType.ShortIMET) { fireDebug(" Reading IMET Header..."); header = Headers.IMET.Load(u8File); if (!((Headers.IMET)header).HashesMatch) { fireDebug(@"/!\ /!\ /!\ Hashes do not match /!\ /!\ /!\"); fireWarning(string.Format("The hash stored in the IMET header doesn't match the headers hash! The header and/or file might be corrupted!")); } } fireDebug(" Checking for Lz77 Compression..."); if (Lz77.IsLz77Compressed(u8File)) { fireDebug(" -> Lz77 Compression Found..."); fireDebug(" Decompressing U8 Data..."); Lz77 l = new Lz77(); Stream decompressedFile = l.Decompress(u8File); tempType = Headers.DetectHeader(decompressedFile); u8File = decompressedFile; lz77 = true; } u8File.Seek((int)tempType, SeekOrigin.Begin); byte[] temp = new byte[4]; //Read U8 Header fireDebug(" Reading U8 Header: Magic... (Offset: 0x{0})", u8File.Position.ToString("x8").ToUpper()); u8File.Read(temp, 0, 4); if (Shared.Swap(BitConverter.ToUInt32(temp, 0)) != u8Header.U8Magic) { fireDebug(" -> Invalid Magic!"); throw new Exception("U8 Header: Invalid Magic!"); } fireDebug(" Reading U8 Header: Offset to Rootnode... (Offset: 0x{0})", u8File.Position.ToString("x8").ToUpper()); u8File.Read(temp, 0, 4); if (Shared.Swap(BitConverter.ToUInt32(temp, 0)) != u8Header.OffsetToRootNode) { fireDebug(" -> Invalid Offset to Rootnode"); throw new Exception("U8 Header: Invalid Offset to Rootnode!"); } fireDebug(" Reading U8 Header: Header Size... (Offset: 0x{0})", u8File.Position.ToString("x8").ToUpper()); u8File.Read(temp, 0, 4); u8Header.HeaderSize = Shared.Swap(BitConverter.ToUInt32(temp, 0)); fireDebug(" Reading U8 Header: Offset to Data... (Offset: 0x{0})", u8File.Position.ToString("x8").ToUpper()); u8File.Read(temp, 0, 4); u8Header.OffsetToData = Shared.Swap(BitConverter.ToUInt32(temp, 0)); u8File.Seek(16, SeekOrigin.Current); //Read Rootnode fireDebug(" Reading Rootnode... (Offset: 0x{0})", u8File.Position.ToString("x8").ToUpper()); u8File.Read(temp, 0, 4); rootNode.Type = (U8_NodeType)Shared.Swap(BitConverter.ToUInt16(temp, 0)); rootNode.OffsetToName = Shared.Swap(BitConverter.ToUInt16(temp, 2)); u8File.Read(temp, 0, 4); rootNode.OffsetToData = Shared.Swap(BitConverter.ToUInt32(temp, 0)); u8File.Read(temp, 0, 4); rootNode.SizeOfData = Shared.Swap(BitConverter.ToUInt32(temp, 0)); int stringTablePosition = (int)((int)tempType + u8Header.OffsetToRootNode + rootNode.SizeOfData * 12); int nodePosition = (int)u8File.Position; //Read Nodes for (int i = 0; i < rootNode.SizeOfData - 1; i++) { fireDebug(" Reading Node #{1} of {2}... (Offset: 0x{0})", u8File.Position.ToString("x8").ToUpper(), i + 1, rootNode.SizeOfData - 1); fireProgress((int)((i + 1) * 100 / (rootNode.SizeOfData - 1))); U8_Node tempNode = new U8_Node(); string tempName = string.Empty; byte[] tempData = new byte[0]; //Read Node Entry u8File.Seek(nodePosition, SeekOrigin.Begin); fireDebug(" -> Reading Node Entry... (Offset: 0x{0})", u8File.Position.ToString("x8").ToUpper()); u8File.Read(temp, 0, 4); tempNode.Type = (U8_NodeType)Shared.Swap(BitConverter.ToUInt16(temp, 0)); tempNode.OffsetToName = Shared.Swap(BitConverter.ToUInt16(temp, 2)); u8File.Read(temp, 0, 4); tempNode.OffsetToData = Shared.Swap(BitConverter.ToUInt32(temp, 0)); u8File.Read(temp, 0, 4); tempNode.SizeOfData = Shared.Swap(BitConverter.ToUInt32(temp, 0)); nodePosition = (int)u8File.Position; fireDebug(" -> {0}", tempNode.Type.ToString()); //Read Node Name u8File.Seek(stringTablePosition + tempNode.OffsetToName, SeekOrigin.Begin); fireDebug(" -> Reading Node Name... (Offset: 0x{0})", u8File.Position.ToString("x8").ToUpper()); for (;;) { char tempChar = (char)u8File.ReadByte(); if (tempChar == 0x00) break; tempName += tempChar; if (tempName.Length > 255) break; } fireDebug(" -> {0}", tempName); //Read Node Data if (tempNode.Type == U8_NodeType.File) { u8File.Seek((int)tempType + tempNode.OffsetToData, SeekOrigin.Begin); fireDebug(" -> Reading Node Data (Offset: 0x{0})", u8File.Position.ToString("x8").ToUpper()); tempData = new byte[tempNode.SizeOfData]; u8File.Read(tempData, 0, tempData.Length); } if (tempName.ToLower() == "icon.bin") iconSize = getRealSize(tempData); else if (tempName.ToLower() == "banner.bin") bannerSize = getRealSize(tempData); else if (tempName.ToLower() == "sound.bin") soundSize = getRealSize(tempData); u8Nodes.Add(tempNode); stringTable.Add(tempName); data.Add(tempData); } fireDebug("Pasing U8 File Finished..."); }
/// <summary> /// Adds an IMD5 Header to the U8 file. /// </summary> public void AddHeaderImd5() { headerType = Headers.HeaderType.IMD5; }
/// <summary> /// Adds an IMET Header to the U8 file. /// </summary> /// <param name="shortImet"></param> /// <param name="titles"></param> public void AddHeaderImet(bool shortImet, params string[] titles) { if (iconSize == -1) throw new Exception("icon.bin wasn't found!"); else if (bannerSize == -1) throw new Exception("banner.bin wasn't found!"); else if (soundSize == -1) throw new Exception("sound.bin wasn't found!"); header = Headers.IMET.Create(shortImet, iconSize, bannerSize, soundSize, titles); headerType = (shortImet) ? Headers.HeaderType.ShortIMET : Headers.HeaderType.IMET; }
private void parseU8(Stream u8File) { fireDebug("Pasing U8 File..."); u8Header = new U8_Header(); rootNode = new U8_Node(); u8Nodes = new List <U8_Node>(); stringTable = new List <string>(); data = new List <byte[]>(); fireDebug(" Detecting Header..."); headerType = Headers.DetectHeader(u8File); Headers.HeaderType tempType = headerType; fireDebug(" -> {0}", headerType.ToString()); if (headerType == Headers.HeaderType.IMD5) { fireDebug(" Reading IMD5 Header..."); header = Headers.IMD5.Load(u8File); byte[] file = new byte[u8File.Length]; u8File.Read(file, 0, file.Length); MD5 m = MD5.Create(); byte[] newHash = m.ComputeHash(file, (int)headerType, (int)u8File.Length - (int)headerType); m.Clear(); if (!Shared.CompareByteArrays(newHash, ((Headers.IMD5)header).Hash)) { fireDebug(@"/!\ /!\ /!\ Hashes do not match /!\ /!\ /!\"); fireWarning(string.Format("Hashes of IMD5 header and file do not match! The content might be corrupted!")); } } else if (headerType == Headers.HeaderType.IMET || headerType == Headers.HeaderType.ShortIMET) { fireDebug(" Reading IMET Header..."); header = Headers.IMET.Load(u8File); if (!((Headers.IMET)header).HashesMatch) { fireDebug(@"/!\ /!\ /!\ Hashes do not match /!\ /!\ /!\"); fireWarning(string.Format("The hash stored in the IMET header doesn't match the headers hash! The header and/or file might be corrupted!")); } } fireDebug(" Checking for Lz77 Compression..."); if (Lz77.IsLz77Compressed(u8File)) { fireDebug(" -> Lz77 Compression Found..."); fireDebug(" Decompressing U8 Data..."); Lz77 l = new Lz77(); Stream decompressedFile = l.Decompress(u8File); tempType = Headers.DetectHeader(decompressedFile); u8File = decompressedFile; lz77 = true; } u8File.Seek((int)tempType, SeekOrigin.Begin); byte[] temp = new byte[4]; //Read U8 Header fireDebug(" Reading U8 Header: Magic... (Offset: 0x{0})", u8File.Position.ToString("x8").ToUpper()); u8File.Read(temp, 0, 4); if (Shared.Swap(BitConverter.ToUInt32(temp, 0)) != u8Header.U8Magic) { fireDebug(" -> Invalid Magic!"); throw new Exception("U8 Header: Invalid Magic!"); } fireDebug(" Reading U8 Header: Offset to Rootnode... (Offset: 0x{0})", u8File.Position.ToString("x8").ToUpper()); u8File.Read(temp, 0, 4); if (Shared.Swap(BitConverter.ToUInt32(temp, 0)) != u8Header.OffsetToRootNode) { fireDebug(" -> Invalid Offset to Rootnode"); throw new Exception("U8 Header: Invalid Offset to Rootnode!"); } fireDebug(" Reading U8 Header: Header Size... (Offset: 0x{0})", u8File.Position.ToString("x8").ToUpper()); u8File.Read(temp, 0, 4); u8Header.HeaderSize = Shared.Swap(BitConverter.ToUInt32(temp, 0)); fireDebug(" Reading U8 Header: Offset to Data... (Offset: 0x{0})", u8File.Position.ToString("x8").ToUpper()); u8File.Read(temp, 0, 4); u8Header.OffsetToData = Shared.Swap(BitConverter.ToUInt32(temp, 0)); u8File.Seek(16, SeekOrigin.Current); //Read Rootnode fireDebug(" Reading Rootnode... (Offset: 0x{0})", u8File.Position.ToString("x8").ToUpper()); u8File.Read(temp, 0, 4); rootNode.Type = (U8_NodeType)Shared.Swap(BitConverter.ToUInt16(temp, 0)); rootNode.OffsetToName = Shared.Swap(BitConverter.ToUInt16(temp, 2)); u8File.Read(temp, 0, 4); rootNode.OffsetToData = Shared.Swap(BitConverter.ToUInt32(temp, 0)); u8File.Read(temp, 0, 4); rootNode.SizeOfData = Shared.Swap(BitConverter.ToUInt32(temp, 0)); int stringTablePosition = (int)((int)tempType + u8Header.OffsetToRootNode + rootNode.SizeOfData * 12); int nodePosition = (int)u8File.Position; //Read Nodes for (int i = 0; i < rootNode.SizeOfData - 1; i++) { fireDebug(" Reading Node #{1} of {2}... (Offset: 0x{0})", u8File.Position.ToString("x8").ToUpper(), i + 1, rootNode.SizeOfData - 1); fireProgress((int)((i + 1) * 100 / (rootNode.SizeOfData - 1))); U8_Node tempNode = new U8_Node(); string tempName = string.Empty; byte[] tempData = new byte[0]; //Read Node Entry u8File.Seek(nodePosition, SeekOrigin.Begin); fireDebug(" -> Reading Node Entry... (Offset: 0x{0})", u8File.Position.ToString("x8").ToUpper()); u8File.Read(temp, 0, 4); tempNode.Type = (U8_NodeType)Shared.Swap(BitConverter.ToUInt16(temp, 0)); tempNode.OffsetToName = Shared.Swap(BitConverter.ToUInt16(temp, 2)); u8File.Read(temp, 0, 4); tempNode.OffsetToData = Shared.Swap(BitConverter.ToUInt32(temp, 0)); u8File.Read(temp, 0, 4); tempNode.SizeOfData = Shared.Swap(BitConverter.ToUInt32(temp, 0)); nodePosition = (int)u8File.Position; fireDebug(" -> {0}", tempNode.Type.ToString()); //Read Node Name u8File.Seek(stringTablePosition + tempNode.OffsetToName, SeekOrigin.Begin); fireDebug(" -> Reading Node Name... (Offset: 0x{0})", u8File.Position.ToString("x8").ToUpper()); for (;;) { char tempChar = (char)u8File.ReadByte(); if (tempChar == 0x00) { break; } tempName += tempChar; if (tempName.Length > 255) { break; } } fireDebug(" -> {0}", tempName); //Read Node Data if (tempNode.Type == U8_NodeType.File) { u8File.Seek((int)tempType + tempNode.OffsetToData, SeekOrigin.Begin); fireDebug(" -> Reading Node Data (Offset: 0x{0})", u8File.Position.ToString("x8").ToUpper()); tempData = new byte[tempNode.SizeOfData]; u8File.Read(tempData, 0, tempData.Length); } if (tempName.ToLower() == "icon.bin") { iconSize = getRealSize(tempData); } else if (tempName.ToLower() == "banner.bin") { bannerSize = getRealSize(tempData); } else if (tempName.ToLower() == "sound.bin") { soundSize = getRealSize(tempData); } u8Nodes.Add(tempNode); stringTable.Add(tempName); data.Add(tempData); } fireDebug("Pasing U8 File Finished..."); }
/// <summary> /// Checks whether a file is Lz77 compressed or not. /// </summary> /// <param name="file"></param> /// <returns></returns> public static bool IsLz77Compressed(byte[] file) { Headers.HeaderType headerType = Headers.DetectHeader(file); return((int)Shared.Swap(BitConverter.ToUInt32(file, (int)headerType)) == (int)lz77Magic); }
private Stream PrivDecompress(Stream inFile) { if (!IsLz77Compressed(inFile)) { return(inFile); } inFile.Seek(0L, SeekOrigin.Begin); uint num1 = 0; Headers.HeaderType headerType = Headers.DetectHeader(inFile); byte[] buffer = new byte[8]; inFile.Seek((long)headerType, SeekOrigin.Begin); inFile.Read(buffer, 0, 8); if ((int)Shared.Swap(BitConverter.ToUInt32(buffer, 0)) != (int)lz77Magic) { inFile.Dispose(); throw new Exception("Invaild Magic!"); } if (buffer[4] != 16) { inFile.Dispose(); throw new Exception("Unsupported Compression Type!"); } uint num2 = BitConverter.ToUInt32(buffer, 4) >> 8; for (int index = 0; index < 4078; ++index) { textBuffer[index] = 223; } int num3 = 4078; uint num4 = 7; int num5 = 7; MemoryStream memoryStream = new MemoryStream(); label_10: while (true) { num4 <<= 1; ++num5; if (num5 == 8) { int num6; if ((num6 = inFile.ReadByte()) != -1) { num4 = (uint)num6; num5 = 0; } else { goto label_24; } } if (((int)num4 & 128) == 0) { int num6; if ((num6 = inFile.ReadByte()) != inFile.Length - 1L) { if (num1 < num2) { memoryStream.WriteByte((byte)num6); } ushort[] textBuffer = this.textBuffer; int index = num3; int num7 = index + 1; int num8 = (byte)num6; textBuffer[index] = (ushort)num8; num3 = num7 & 4095; ++num1; } else { goto label_24; } } else { break; } } int num9; int num10; if ((num9 = inFile.ReadByte()) != -1 && (num10 = inFile.ReadByte()) != -1) { int num6 = num10 | num9 << 8 & 3840; int num7 = (num9 >> 4 & 15) + 2; for (int index1 = 0; index1 <= num7; ++index1) { int num8 = this.textBuffer[num3 - num6 - 1 & 4095]; if (num1 < num2) { memoryStream.WriteByte((byte)num8); } ushort[] textBuffer = this.textBuffer; int index2 = num3; int num11 = index2 + 1; int num12 = (byte)num8; textBuffer[index2] = (ushort)num12; num3 = num11 & 4095; ++num1; } goto label_10; } label_24: return(memoryStream); }
private Stream decompress(Stream inFile) { if (!Lz77.IsLz77Compressed(inFile)) { return(inFile); } inFile.Seek(0, SeekOrigin.Begin); int i, j, k, r, c, z; uint flags, decompressedSize, currentSize = 0; Headers.HeaderType h = Headers.DetectHeader(inFile); byte[] temp = new byte[8]; inFile.Seek((int)h, SeekOrigin.Begin); inFile.Read(temp, 0, 8); if (Shared.Swap(BitConverter.ToUInt32(temp, 0)) != lz77Magic) { inFile.Dispose(); throw new Exception("Invaild Magic!"); } if (temp[4] != 0x10) { inFile.Dispose(); throw new Exception("Unsupported Compression Type!"); } decompressedSize = (BitConverter.ToUInt32(temp, 4)) >> 8; for (i = 0; i < N - F; i++) { textBuffer[i] = 0xdf; } r = N - F; flags = 7; z = 7; MemoryStream outFile = new MemoryStream(); while (true) { flags <<= 1; z++; if (z == 8) { if ((c = inFile.ReadByte()) == -1) { break; } flags = (uint)c; z = 0; } if ((flags & 0x80) == 0) { if ((c = inFile.ReadByte()) == inFile.Length - 1) { break; } if (currentSize < decompressedSize) { outFile.WriteByte((byte)c); } textBuffer[r++] = (byte)c; r &= (N - 1); currentSize++; } else { if ((i = inFile.ReadByte()) == -1) { break; } if ((j = inFile.ReadByte()) == -1) { break; } j = j | ((i << 8) & 0xf00); i = ((i >> 4) & 0x0f) + threshold; for (k = 0; k <= i; k++) { c = textBuffer[(r - j - 1) & (N - 1)]; if (currentSize < decompressedSize) { outFile.WriteByte((byte)c); } textBuffer[r++] = (byte)c; r &= (N - 1); currentSize++; } } } return(outFile); }