/// <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..."); }
private void writeToStream(Stream writeStream) { fireDebug("Writing U8 File..."); //Update Rootnode fireDebug(" Updating Rootnode..."); rootNode.SizeOfData = (uint)u8Nodes.Count + 1; MemoryStream u8Stream = new MemoryStream(); //Write Stringtable u8Stream.Seek(u8Header.OffsetToRootNode + ((u8Nodes.Count + 1) * 12), SeekOrigin.Begin); fireDebug(" Writing String Table... (Offset: 0x{0})", u8Stream.Position.ToString("x8").ToUpper()); u8Stream.WriteByte(0x00); int stringTablePosition = (int)u8Stream.Position - 1; for (int i = 0; i < u8Nodes.Count; i++) { fireDebug(" -> Entry #{1} of {2}: \"{3}\"... (Offset: 0x{0})", u8Stream.Position.ToString("x8").ToUpper(), i + 1, u8Nodes.Count, stringTable[i]); u8Nodes[i].OffsetToName = (ushort)(u8Stream.Position - stringTablePosition); byte[] stringBytes = System.Text.ASCIIEncoding.ASCII.GetBytes(stringTable[i]); u8Stream.Write(stringBytes, 0, stringBytes.Length); u8Stream.WriteByte(0x00); } u8Header.HeaderSize = (uint)(u8Stream.Position - u8Header.OffsetToRootNode); u8Header.OffsetToData = 0; //Write Data for (int i = 0; i < u8Nodes.Count; i++) { fireProgress((i + 1) * 100 / u8Nodes.Count); if (u8Nodes[i].Type == U8_NodeType.File) { u8Stream.Seek(Shared.AddPadding((int)u8Stream.Position, dataPadding), SeekOrigin.Begin); fireDebug(" Writing Data #{1} of {2}... (Offset: 0x{0})", u8Stream.Position.ToString("x8").ToUpper(), i + 1, u8Nodes.Count); if (u8Header.OffsetToData == 0) u8Header.OffsetToData = (uint)u8Stream.Position; u8Nodes[i].OffsetToData = (uint)u8Stream.Position; u8Nodes[i].SizeOfData = (uint)data[i].Length; u8Stream.Write(data[i], 0, data[i].Length); } else fireDebug(" Node #{0} of {1} is a Directory...", i + 1, u8Nodes.Count); } //Pad End to 16 bytes while (u8Stream.Position % 16 != 0) u8Stream.WriteByte(0x00); //Write Header + Nodes u8Stream.Seek(0, SeekOrigin.Begin); fireDebug(" Writing Header... (Offset: 0x{0})", u8Stream.Position.ToString("x8").ToUpper()); u8Header.Write(u8Stream); fireDebug(" Writing Rootnode... (Offset: 0x{0})", u8Stream.Position.ToString("x8").ToUpper()); rootNode.Write(u8Stream); for (int i = 0; i < u8Nodes.Count; i++) { fireDebug(" Writing Node Entry #{1} of {2}... (Offset: 0x{0})", u8Stream.Position.ToString("x8").ToUpper(), i + 1, u8Nodes.Count); u8Nodes[i].Write(u8Stream); } byte[] u8Array = u8Stream.ToArray(); u8Stream.Dispose(); if (lz77) { fireDebug(" Lz77 Compressing U8 File..."); Lz77 l = new Lz77(); u8Array = l.Compress(u8Array); } //Write File Header if (headerType == Headers.HeaderType.IMD5) { fireDebug(" Adding IMD5 Header..."); writeStream.Seek(0, SeekOrigin.Begin); Headers.IMD5 h = Headers.IMD5.Create(u8Array); h.Write(writeStream); } else if (headerType == Headers.HeaderType.IMET || headerType == Headers.HeaderType.ShortIMET) { fireDebug(" Adding IMET Header..."); ((Headers.IMET)header).IconSize = (uint)iconSize; ((Headers.IMET)header).BannerSize = (uint)bannerSize; ((Headers.IMET)header).SoundSize = (uint)soundSize; writeStream.Seek(0, SeekOrigin.Begin); ((Headers.IMET)header).Write(writeStream); } writeStream.Write(u8Array, 0, u8Array.Length); fireDebug("Writing U8 File Finished..."); }
/// <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 cbSourceSound_CheckedChanged(object sender, EventArgs e) { if (cbSourceSound.Checked) { tbAudioFile.Text = "Internal Sound"; if (Lz77.IsLz77Compressed(sourceSound)) { Lz77 l = new Lz77(); sourceSound = l.Decompress(sourceSound); } foreach (Label thisLabel in gbWaveInfo.Controls) if (thisLabel.Name.ToLower().Contains("value")) { thisLabel.ForeColor = System.Drawing.Color.Black; thisLabel.Text = "Gathering"; } bwGatherInfo.RunWorkerAsync(sourceSound); //this.Size = new System.Drawing.Size(510, 220); this.Size = new System.Drawing.Size(gbWaveInfo.Location.X + gbWaveInfo.Size.Width + 15, this.Size.Height); } else { if (tbAudioFile.Text == "Internal Sound") tbAudioFile.Text = string.Empty; //this.Size = new System.Drawing.Size(358, 220); this.Size = new System.Drawing.Size(btnCancel.Location.X + btnCancel.Size.Width + 15, this.Size.Height); } }
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..."); }
private void writeToStream(Stream writeStream) { fireDebug("Writing U8 File..."); //Update Rootnode fireDebug(" Updating Rootnode..."); rootNode.SizeOfData = (uint)u8Nodes.Count + 1; MemoryStream u8Stream = new MemoryStream(); //Write Stringtable u8Stream.Seek(u8Header.OffsetToRootNode + ((u8Nodes.Count + 1) * 12), SeekOrigin.Begin); fireDebug(" Writing String Table... (Offset: 0x{0})", u8Stream.Position.ToString("x8").ToUpper()); u8Stream.WriteByte(0x00); int stringTablePosition = (int)u8Stream.Position - 1; for (int i = 0; i < u8Nodes.Count; i++) { fireDebug(" -> Entry #{1} of {2}: \"{3}\"... (Offset: 0x{0})", u8Stream.Position.ToString("x8").ToUpper(), i + 1, u8Nodes.Count, stringTable[i]); u8Nodes[i].OffsetToName = (ushort)(u8Stream.Position - stringTablePosition); byte[] stringBytes = System.Text.ASCIIEncoding.ASCII.GetBytes(stringTable[i]); u8Stream.Write(stringBytes, 0, stringBytes.Length); u8Stream.WriteByte(0x00); } u8Header.HeaderSize = (uint)(u8Stream.Position - u8Header.OffsetToRootNode); u8Header.OffsetToData = 0; //Write Data for (int i = 0; i < u8Nodes.Count; i++) { fireProgress((i + 1) * 100 / u8Nodes.Count); if (u8Nodes[i].Type == U8_NodeType.File) { u8Stream.Seek(Shared.AddPadding((int)u8Stream.Position, dataPadding), SeekOrigin.Begin); fireDebug(" Writing Data #{1} of {2}... (Offset: 0x{0})", u8Stream.Position.ToString("x8").ToUpper(), i + 1, u8Nodes.Count); if (u8Header.OffsetToData == 0) { u8Header.OffsetToData = (uint)u8Stream.Position; } u8Nodes[i].OffsetToData = (uint)u8Stream.Position; u8Nodes[i].SizeOfData = (uint)data[i].Length; u8Stream.Write(data[i], 0, data[i].Length); } else { fireDebug(" Node #{0} of {1} is a Directory...", i + 1, u8Nodes.Count); } } //Pad End to 16 bytes while (u8Stream.Position % 16 != 0) { u8Stream.WriteByte(0x00); } //Write Header + Nodes u8Stream.Seek(0, SeekOrigin.Begin); fireDebug(" Writing Header... (Offset: 0x{0})", u8Stream.Position.ToString("x8").ToUpper()); u8Header.Write(u8Stream); fireDebug(" Writing Rootnode... (Offset: 0x{0})", u8Stream.Position.ToString("x8").ToUpper()); rootNode.Write(u8Stream); for (int i = 0; i < u8Nodes.Count; i++) { fireDebug(" Writing Node Entry #{1} of {2}... (Offset: 0x{0})", u8Stream.Position.ToString("x8").ToUpper(), i + 1, u8Nodes.Count); u8Nodes[i].Write(u8Stream); } byte[] u8Array = u8Stream.ToArray(); u8Stream.Dispose(); if (lz77) { fireDebug(" Lz77 Compressing U8 File..."); Lz77 l = new Lz77(); u8Array = l.Compress(u8Array); } //Write File Header if (headerType == Headers.HeaderType.IMD5) { fireDebug(" Adding IMD5 Header..."); writeStream.Seek(0, SeekOrigin.Begin); Headers.IMD5 h = Headers.IMD5.Create(u8Array); h.Write(writeStream); } else if (headerType == Headers.HeaderType.IMET || headerType == Headers.HeaderType.ShortIMET) { fireDebug(" Adding IMET Header..."); ((Headers.IMET)header).IconSize = (uint)iconSize; ((Headers.IMET)header).BannerSize = (uint)bannerSize; ((Headers.IMET)header).SoundSize = (uint)soundSize; writeStream.Seek(0, SeekOrigin.Begin); ((Headers.IMET)header).Write(writeStream); } writeStream.Write(u8Array, 0, u8Array.Length); fireDebug("Writing U8 File Finished..."); }
private void writeToStream(Stream writeStream) { fireDebug("Writing Wad..."); //Create Footer Timestamp if (!keepOriginalFooter) { fireDebug(" Building Footer Timestamp..."); createFooterTimestamp(); } //Save Banner App if (hasBanner) { //Compress icon.bin and banner.bin if (lz77CompressBannerAndIcon || lz77DecompressBannerAndIcon) { for (int i = 0; i < bannerApp.Nodes.Count; i++) { if (bannerApp.StringTable[i].ToLower() == "icon.bin" || bannerApp.StringTable[i].ToLower() == "banner.bin") { if (!Lz77.IsLz77Compressed(bannerApp.Data[i]) && lz77CompressBannerAndIcon) { fireDebug(" Compressing {0}...", bannerApp.StringTable[i]); //Get the data without the IMD5 Header byte[] fileData = new byte[bannerApp.Data[i].Length - 32]; Array.Copy(bannerApp.Data[i], 32, fileData, 0, fileData.Length); //Compress the data Lz77 l = new Lz77(); fileData = l.Compress(fileData); //Add a new IMD5 Header fileData = Headers.IMD5.AddHeader(fileData); bannerApp.Data[i] = fileData; //Update the node bannerApp.Nodes[i].SizeOfData = (uint)fileData.Length; } else if (Lz77.IsLz77Compressed(bannerApp.Data[i]) && lz77DecompressBannerAndIcon) { fireDebug(" Decompressing {0}...", bannerApp.StringTable[i]); //Get the data without the IMD5 Header byte[] fileData = new byte[bannerApp.Data[i].Length - 32]; Array.Copy(bannerApp.Data[i], 32, fileData, 0, fileData.Length); //Decompress the data Lz77 l = new Lz77(); fileData = l.Decompress(fileData); //Add a new IMD5 Header fileData = Headers.IMD5.AddHeader(fileData); bannerApp.Data[i] = fileData; //Update the node bannerApp.Nodes[i].SizeOfData = (uint)fileData.Length; } } } } for (int i = 0; i < contents.Count; i++) if (tmd.Contents[i].Index == 0x0000) { fireDebug(" Saving Banner App..."); contents[i] = bannerApp.ToByteArray(); break; } } //Update Header (Content Size) fireDebug(" Updating Header..."); int contentSize = 0; for (int i = 0; i < contents.Count - 1; i++) contentSize += Shared.AddPadding(contents[i].Length); contentSize += contents[contents.Count - 1].Length; wadHeader.ContentSize = (uint)contentSize; wadHeader.TmdSize = (uint)(484 + tmd.NumOfContents * 36); //Update Contents fireDebug(" Updating TMD Contents..."); tmd.UpdateContents(contents.ToArray()); //Write Header fireDebug(" Writing Wad Header... (Offset: 0x{0})", writeStream.Position.ToString("x8").ToUpper()); writeStream.Seek(0, SeekOrigin.Begin); wadHeader.Write(writeStream); //Write Cert fireDebug(" Writing Certificate Chain... (Offset: 0x{0})", writeStream.Position.ToString("x8").ToUpper()); writeStream.Seek(Shared.AddPadding((int)writeStream.Position), SeekOrigin.Begin); byte[] temp = cert.ToByteArray(); writeStream.Write(temp, 0, temp.Length); //Write Tik fireDebug(" Writing Ticket... (Offset: 0x{0})", writeStream.Position.ToString("x8").ToUpper()); writeStream.Seek(Shared.AddPadding((int)writeStream.Position), SeekOrigin.Begin); temp = tik.ToByteArray(); writeStream.Write(temp, 0, temp.Length); //Write TMD fireDebug(" Writing TMD... (Offset: 0x{0})", writeStream.Position.ToString("x8").ToUpper()); writeStream.Seek(Shared.AddPadding((int)writeStream.Position), SeekOrigin.Begin); temp = tmd.ToByteArray(); writeStream.Write(temp, 0, temp.Length); //Write Contents ContentIndices[] contentList = tmd.GetSortedContentList(); for (int i = 0; i < contentList.Length; i++) { writeStream.Seek(Shared.AddPadding((int)writeStream.Position), SeekOrigin.Begin); fireProgress((i + 1) * 100 / contents.Count); fireDebug(" Writing Content #{1} of {2}... (Offset: 0x{0})", writeStream.Position.ToString("x8").ToUpper(), i + 1, contents.Count); fireDebug(" -> Content ID: 0x{0}", tmd.Contents[contentList[i].Index].ContentID.ToString("x8")); fireDebug(" -> Index: 0x{0}", tmd.Contents[contentList[i].Index].Index.ToString("x4")); fireDebug(" -> Type: 0x{0} ({1})", ((ushort)tmd.Contents[contentList[i].Index].Type).ToString("x4"), tmd.Contents[contentList[i].Index].Type.ToString()); fireDebug(" -> Size: {0} bytes", tmd.Contents[contentList[i].Index].Size); fireDebug(" -> Hash: {0}", Shared.ByteArrayToString(tmd.Contents[contentList[i].Index].Hash)); temp = encryptContent(contents[contentList[i].Index], contentList[i].Index); writeStream.Write(temp, 0, temp.Length); } //Write Footer if (wadHeader.FooterSize > 0) { fireDebug(" Writing Footer... (Offset: 0x{0})", writeStream.Position.ToString("x8").ToUpper()); writeStream.Seek(Shared.AddPadding((int)writeStream.Position), SeekOrigin.Begin); writeStream.Write(footer, 0, footer.Length); } //Padding while (writeStream.Position % 64 != 0) writeStream.WriteByte(0x00); fireDebug("Writing Wad Finished... (Written Bytes: {0})", writeStream.Position); }
private void cmOptionsExtract_MouseClick(object sender, EventArgs e) { ToolStripMenuItem cmSender = sender as ToolStripMenuItem; if (cmSender.OwnerItem == tsExtractImages) { try { FolderBrowserDialog fbd = new FolderBrowserDialog(); if (cmSender.Text.ToLower() == "both") { fbd.Description = "Select the path where the images will be extracted to. Two folders \"Banner\" and \"Icon\" will be created."; } else { fbd.Description = "Select the path where the images will be extracted to."; } if (fbd.ShowDialog() == DialogResult.OK) { string bannerPath; string iconPath; switch (cmSender.Text.ToLower()) { case "banner": bannerPath = fbd.SelectedPath; iconPath = string.Empty; break; case "icon": bannerPath = string.Empty; iconPath = fbd.SelectedPath; break; default: //both bannerPath = fbd.SelectedPath + Path.DirectorySeparatorChar + "Banner"; iconPath = fbd.SelectedPath + Path.DirectorySeparatorChar + "Icon"; break; } if (!string.IsNullOrEmpty(bannerPath)) { if (!Directory.Exists(bannerPath)) Directory.CreateDirectory(bannerPath); if (string.IsNullOrEmpty(replacedBanner)) { for (int i = 0; i < bannerBin.NumOfNodes; i++) { if (bannerBin.StringTable[i].ToLower().EndsWith(".tpl")) { Image img = TPL.Load(bannerBin.Data[i]).ExtractTexture(); img.Save(bannerPath + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(bannerBin.StringTable[i]) + ".png"); } } } else { for (int i = 0; i < newBannerBin.NumOfNodes; i++) { if (newBannerBin.StringTable[i].ToLower().EndsWith(".tpl")) { Image img = TPL.Load(newBannerBin.Data[i]).ExtractTexture(); img.Save(bannerPath + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(newBannerBin.StringTable[i]) + ".png"); } } } } if (!string.IsNullOrEmpty(iconPath)) { if (!Directory.Exists(iconPath)) Directory.CreateDirectory(iconPath); if (string.IsNullOrEmpty(replacedIcon)) { for (int i = 0; i < iconBin.NumOfNodes; i++) { if (iconBin.StringTable[i].ToLower().EndsWith(".tpl")) { Image img = TPL.Load(iconBin.Data[i]).ExtractTexture(); img.Save(iconPath + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(iconBin.StringTable[i]) + ".png"); } } } else { for (int i = 0; i < newIconBin.NumOfNodes; i++) { if (newIconBin.StringTable[i].ToLower().EndsWith(".tpl")) { Image img = TPL.Load(newIconBin.Data[i]).ExtractTexture(); img.Save(iconPath + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(newIconBin.StringTable[i]) + ".png"); } } } } infoBox("Extracted images successfully!"); } } catch (Exception ex) { errorBox(ex.Message); } } else if (cmSender.OwnerItem == tsExtractSound) { try { byte[] soundFile = new byte[0]; if (string.IsNullOrEmpty(replacedSound)) { for (int i = 0; i < sourceWad.BannerApp.NumOfNodes; i++) { if (sourceWad.BannerApp.StringTable[i].ToLower() == "sound.bin") soundFile = sourceWad.BannerApp.Data[i]; } } else { soundFile = newSoundBin; } SaveFileDialog sfd = new SaveFileDialog(); if (cmSender.Name.ToLower() == "cmextractsoundasbin") { sfd.Filter = "BIN|*.bin"; sfd.FileName = "sound.bin"; } else if (cmSender.Name.ToLower() == "cmextractsoundasaudio") { if (soundFile[32] == 'R' && soundFile[33] == 'I' && soundFile[34] == 'F' && soundFile[35] == 'F') { sfd.Filter = "Wave|*.wav"; sfd.FileName = "sound.wav"; } else if (soundFile[32] == 'B' && soundFile[33] == 'N' && soundFile[34] == 'S' && soundFile[35] == ' ') { sfd.Filter = "Wave|*.wav"; sfd.FileName = "sound.wav"; } else if (soundFile[32] == 'F' && soundFile[33] == 'O' && soundFile[34] == 'R' && soundFile[35] == 'M') { sfd.Filter = "AIFF|*.aif;*.aiff"; sfd.FileName = "sound.aif"; } else if (soundFile[32] == 'L' && soundFile[33] == 'Z' && soundFile[34] == '7' && soundFile[35] == '7') { if (soundFile[41] == 'R' && soundFile[42] == 'I' && soundFile[43] == 'F' && soundFile[44] == 'F') { sfd.Filter = "Wave|*.wav"; sfd.FileName = "sound.wav"; } else if (soundFile[41] == 'B' && soundFile[42] == 'N' && soundFile[43] == 'S' && soundFile[44] == ' ') { sfd.Filter = "Wave|*.wav"; sfd.FileName = "sound.wave"; } else if (soundFile[41] == 'F' && soundFile[42] == 'O' && soundFile[43] == 'R' && soundFile[44] == 'M') { sfd.Filter = "AIFF|*.aif;*.aiff"; sfd.FileName = "sound.aif"; } else throw new Exception("Unsupported Audio Format!"); } else throw new Exception("Unsupported Audio Format!"); } if (sfd.ShowDialog() == DialogResult.OK) { if (File.Exists(sfd.FileName)) File.Delete(sfd.FileName); if (sfd.FileName.ToLower().EndsWith(".bin")) { File.WriteAllBytes(sfd.FileName, soundFile); infoBox("The sound.bin was successfully extraced!"); } else { soundFile = Headers.IMD5.RemoveHeader(soundFile); if (Lz77.IsLz77Compressed(soundFile)) { Lz77 l = new Lz77(); soundFile = l.Decompress(soundFile); } if (soundFile[0] == 'B' && soundFile[1] == 'N' && soundFile[2] == 'S' && soundFile[3] == ' ') { Wave w = BNS.BnsToWave(soundFile); w.Save(sfd.FileName); w.Dispose(); } else File.WriteAllBytes(sfd.FileName, soundFile); infoBox(string.Format("The sound.bin was successfully converted to {0}!", Path.GetFileName(sfd.FileName))); } } } catch (Exception ex) { errorBox(ex.Message); } } else if (cmSender.OwnerItem == tsExtractBrl) { try { FolderBrowserDialog fbd = new FolderBrowserDialog(); fbd.Description = "Select the path where the files will be extracted to."; if (fbd.ShowDialog() == DialogResult.OK) { if (cmSender == cmExtractBrlyt || cmSender == cmExtractBothBrl) { //Extract brlyts if (string.IsNullOrEmpty(replacedBanner)) { for (int i = 0; i < bannerBin.NumOfNodes; i++) { if (bannerBin.StringTable[i].ToLower().EndsWith(".brlyt")) { File.WriteAllBytes(fbd.SelectedPath + Path.DirectorySeparatorChar + bannerBin.StringTable[i], bannerBin.Data[i]); } } } else { for (int i = 0; i < newBannerBin.NumOfNodes; i++) { if (newBannerBin.StringTable[i].ToLower().EndsWith(".brlyt")) { File.WriteAllBytes(fbd.SelectedPath + Path.DirectorySeparatorChar + newBannerBin.StringTable[i], newBannerBin.Data[i]); } } } if (string.IsNullOrEmpty(replacedIcon)) { for (int i = 0; i < iconBin.NumOfNodes; i++) { if (iconBin.StringTable[i].ToLower().EndsWith(".brlyt")) { File.WriteAllBytes(fbd.SelectedPath + Path.DirectorySeparatorChar + iconBin.StringTable[i], iconBin.Data[i]); } } } else { for (int i = 0; i < newIconBin.NumOfNodes; i++) { if (newIconBin.StringTable[i].ToLower().EndsWith(".brlyt")) { File.WriteAllBytes(fbd.SelectedPath + Path.DirectorySeparatorChar + newIconBin.StringTable[i], newIconBin.Data[i]); } } } } if (cmSender == cmExtractBothBrl || cmSender == cmExtractBrlan) { //Extract brlans if (string.IsNullOrEmpty(replacedBanner)) { for (int i = 0; i < bannerBin.NumOfNodes; i++) { if (bannerBin.StringTable[i].ToLower().EndsWith(".brlan")) { File.WriteAllBytes(fbd.SelectedPath + Path.DirectorySeparatorChar + bannerBin.StringTable[i], bannerBin.Data[i]); } } } else { for (int i = 0; i < newBannerBin.NumOfNodes; i++) { if (newBannerBin.StringTable[i].ToLower().EndsWith(".brlan")) { File.WriteAllBytes(fbd.SelectedPath + Path.DirectorySeparatorChar + newBannerBin.StringTable[i], newBannerBin.Data[i]); } } } if (string.IsNullOrEmpty(replacedIcon)) { for (int i = 0; i < iconBin.NumOfNodes; i++) { if (iconBin.StringTable[i].ToLower().EndsWith(".brlan")) { File.WriteAllBytes(fbd.SelectedPath + Path.DirectorySeparatorChar + iconBin.StringTable[i], iconBin.Data[i]); } } } else { for (int i = 0; i < newIconBin.NumOfNodes; i++) { if (newIconBin.StringTable[i].ToLower().EndsWith(".brlan")) { File.WriteAllBytes(fbd.SelectedPath + Path.DirectorySeparatorChar + newIconBin.StringTable[i], newIconBin.Data[i]); } } } } infoBox("Extracted files successfully!"); } } catch (Exception ex) { errorBox(ex.Message); } } else //DOL { try { if (sourceWad.NumOfContents == 3) { int appIndex = 0; if (sourceWad.BootIndex == 1) appIndex = 2; else if (sourceWad.BootIndex == 2) appIndex = 1; if (appIndex > 0) { SaveFileDialog sfd = new SaveFileDialog(); sfd.Filter = "Wii Executables|*.dol"; sfd.FileName = (string.IsNullOrEmpty(tbAllLanguages.Text) ? tbEnglish.Text : tbAllLanguages.Text) + ".dol"; if (sfd.ShowDialog() == DialogResult.OK) { if (File.Exists(sfd.FileName)) File.Delete(sfd.FileName); File.WriteAllBytes(sfd.FileName, sourceWad.Contents[appIndex]); infoBox(string.Format("The DOL file was successfully extracted to {0}!", Path.GetFileName(sfd.FileName))); } } else errorBox("The DOL file couldn't be found!"); } else errorBox("The DOL file couldn't be found!"); } catch (Exception ex) { errorBox(ex.Message); } } }
private Stream compress(Stream inFile) { if (Lz77.IsLz77Compressed(inFile)) { return(inFile); } inFile.Seek(0, SeekOrigin.Begin); int textSize = 0; int codeSize = 0; int i, c, r, s, length, lastMatchLength, codeBufferPointer, mask; int[] codeBuffer = new int[17]; uint fileSize = ((Convert.ToUInt32(inFile.Length)) << 8) + 0x10; MemoryStream outFile = new MemoryStream(); outFile.Write(BitConverter.GetBytes(Shared.Swap(lz77Magic)), 0, 4); outFile.Write(BitConverter.GetBytes(fileSize), 0, 4); InitTree(); codeBuffer[0] = 0; codeBufferPointer = 1; mask = 0x80; s = 0; r = N - F; for (i = s; i < r; i++) { textBuffer[i] = 0xffff; } for (length = 0; length < F && (c = (int)inFile.ReadByte()) != -1; length++) { textBuffer[r + length] = (ushort)c; } if ((textSize = length) == 0) { return(inFile); } for (i = 1; i <= F; i++) { InsertNode(r - i); } InsertNode(r); do { if (matchLength > length) { matchLength = length; } if (matchLength <= threshold) { matchLength = 1; codeBuffer[codeBufferPointer++] = textBuffer[r]; } else { codeBuffer[0] |= mask; codeBuffer[codeBufferPointer++] = (char) (((r - matchPosition - 1) >> 8) & 0x0f) | ((matchLength - (threshold + 1)) << 4); codeBuffer[codeBufferPointer++] = (char)((r - matchPosition - 1) & 0xff); } if ((mask >>= 1) == 0) { for (i = 0; i < codeBufferPointer; i++) { outFile.WriteByte((byte)codeBuffer[i]); } codeSize += codeBufferPointer; codeBuffer[0] = 0; codeBufferPointer = 1; mask = 0x80; } lastMatchLength = matchLength; for (i = 0; i < lastMatchLength && (c = (int)inFile.ReadByte()) != -1; i++) { DeleteNode(s); textBuffer[s] = (ushort)c; if (s < F - 1) { textBuffer[s + N] = (ushort)c; } s = (s + 1) & (N - 1); r = (r + 1) & (N - 1); InsertNode(r); } while (i++ < lastMatchLength) { DeleteNode(s); s = (s + 1) & (N - 1); r = (r + 1) & (N - 1); if (--length != 0) { InsertNode(r); } } } while (length > 0); if (codeBufferPointer > 1) { for (i = 0; i < codeBufferPointer; i++) { outFile.WriteByte((byte)codeBuffer[i]); } codeSize += codeBufferPointer; } if (codeSize % 4 != 0) { for (i = 0; i < 4 - (codeSize % 4); i++) { outFile.WriteByte(0x00); } } return(outFile); }
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); }