From 8283d95680d84aad00088fd196919e3030859b47 Mon Sep 17 00:00:00 2001 From: Michael Malloy Date: Sat, 6 Feb 2021 22:53:40 -0600 Subject: [PATCH] Finished reformatting; fixed name violations, other IDE Messages; Massive code cleanup --- AssemblyInfo.cs | 7 +- BNS.cs | 453 ++++--- BNS_Data.cs | 28 +- BNS_Header.cs | 102 +- BNS_Info.cs | 355 +++--- Brlan.cs | 54 +- Brlyt.cs | 38 +- CertificateChain.cs | 293 +++-- ColorIndexConverter.cs | 247 ++-- CommonKey.cs | 14 +- ContentIndices.cs | 41 +- HbcTransmitter.cs | 277 +++-- Headers.cs | 444 ++++--- HexView.cs | 206 ++-- IosPatcher.cs | 299 +++-- Lz77.cs | 694 ++++++----- MessageEventArgs.cs | 15 +- NusClient.cs | 836 +++++++------ Region.cs | 14 +- Shared.cs | 311 +++-- StoreType.cs | 14 +- TMD.cs | 1026 ++++++++-------- TMD_Content.cs | 64 +- TPL.cs | 2599 ++++++++++++++++++++-------------------- TPL_Header.cs | 38 +- TPL_PaletteFormat.cs | 14 +- TPL_PaletteHeader.cs | 80 +- TPL_TextureEntry.cs | 38 +- TPL_TextureFormat.cs | 28 +- TPL_TextureHeader.cs | 192 +-- Ticket.cs | 911 +++++++------- U8.cs | 1638 +++++++++++++------------ U8_Header.cs | 60 +- U8_Node.cs | 66 +- U8_NodeType.cs | 10 +- WAD.cs | 2004 ++++++++++++++++--------------- Wave.cs | 377 +++--- WaveDataChunk.cs | 54 +- WaveFmtChunk.cs | 102 +- WaveHeader.cs | 46 +- WaveSmplChunk.cs | 142 +-- WaveSmplLoop.cs | 72 +- 42 files changed, 7653 insertions(+), 6650 deletions(-) diff --git a/AssemblyInfo.cs b/AssemblyInfo.cs index 670ef23..49a6f1b 100644 --- a/AssemblyInfo.cs +++ b/AssemblyInfo.cs @@ -1,10 +1,9 @@ using System.Reflection; using System.Resources; using System.Runtime.InteropServices; -using System.Security.Permissions; [assembly: AssemblyTitle("libWiiSharp_Modified")] -[assembly: AssemblyDescription("a wii related .NET library modified to add features for othe programs.")] +[assembly: AssemblyDescription("A wii related .NET library modified to add features for othe programs.")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Leathl,SC reproductions")] [assembly: AssemblyProduct("libWiiSharp_Modified")] @@ -14,6 +13,4 @@ using System.Security.Permissions; [assembly: Guid("af701263-5875-4866-9c09-d7f62e9f0ff0")] [assembly: AssemblyFileVersion("0.4.0.0")] [assembly: NeutralResourcesLanguage("en")] -[assembly: AssemblyVersion("0.4.0.0")] -[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] -[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] +[assembly: AssemblyVersion("0.4.0.0")] \ No newline at end of file diff --git a/BNS.cs b/BNS.cs index 0f0718a..5612574 100644 --- a/BNS.cs +++ b/BNS.cs @@ -25,56 +25,60 @@ namespace libWiiSharp { public class BNS : IDisposable { - + private BNS_Header bnsHeader = new BNS_Header(); private BNS_Info bnsInfo = new BNS_Info(); private BNS_Data bnsData = new BNS_Data(); - private int[,] lSamples = new int[2, 2]; + // Unused + //private int[,] lSamples = new int[2, 2]; private int[,] rlSamples = new int[2, 2]; private int[] tlSamples = new int[2]; + // Unused + /* private int[] hbcDefTbl = new int[16] - { - 674, - 1040, - 3598, - -1738, - 2270, - -583, - 3967, - -1969, - 1516, - 381, - 3453, - -1468, - 2606, - -617, - 3795, - -1759 - }; - private int[] defTbl = new int[16] - { - 1820, - -856, - 3238, - -1514, - 2333, - -550, - 3336, - -1376, - 2444, - -949, - 3666, - -1764, - 2654, - -701, - 3420, - -1398 - }; + { + 674, + 1040, + 3598, + -1738, + 2270, + -583, + 3967, + -1969, + 1516, + 381, + 3453, + -1468, + 2606, + -617, + 3795, + -1759 + }; + */ + private readonly int[] defTbl = new int[16] + { + 1820, + -856, + 3238, + -1514, + 2333, + -550, + 3336, + -1376, + 2444, + -949, + 3666, + -1764, + 2654, + -701, + 3420, + -1398 + }; private int[] pHist1 = new int[2]; private int[] pHist2 = new int[2]; private int tempSampleCount; private byte[] waveFile; - private bool loopFromWave; + private readonly bool loopFromWave; private bool converted; private bool toMono; private bool isDisposed; @@ -84,8 +88,8 @@ namespace libWiiSharp /// public bool HasLoop { - get => this.bnsInfo.HasLoop == (byte) 1; - set => this.bnsInfo.HasLoop = value ? (byte) 1 : (byte) 0; + get => bnsInfo.HasLoop == 1; + set => bnsInfo.HasLoop = value ? 1 : 0; } /// @@ -93,8 +97,8 @@ namespace libWiiSharp /// public uint LoopStart { - get => this.bnsInfo.LoopStart; - set => this.bnsInfo.LoopStart = value; + get => bnsInfo.LoopStart; + set => bnsInfo.LoopStart = value; } /// @@ -102,8 +106,8 @@ namespace libWiiSharp /// public uint TotalSampleCount { - get => this.bnsInfo.LoopEnd; - set => this.bnsInfo.LoopEnd = value; + get => bnsInfo.LoopEnd; + set => bnsInfo.LoopEnd = value; } /// @@ -112,8 +116,8 @@ namespace libWiiSharp /// public bool StereoToMono { - get => this.toMono; - set => this.toMono = value; + get => toMono; + set => toMono = value; } public event EventHandler Progress; @@ -123,7 +127,10 @@ namespace libWiiSharp } - public BNS(string waveFile) => this.waveFile = File.ReadAllBytes(waveFile); + public BNS(string waveFile) + { + this.waveFile = File.ReadAllBytes(waveFile); + } public BNS(string waveFile, bool loopFromWave) { @@ -131,7 +138,10 @@ namespace libWiiSharp this.loopFromWave = loopFromWave; } - public BNS(byte[] waveFile) => this.waveFile = waveFile; + public BNS(byte[] waveFile) + { + this.waveFile = waveFile; + } public BNS(byte[] waveFile, bool loopFromWave) { @@ -141,31 +151,31 @@ namespace libWiiSharp #region IDisposable Members - ~BNS() => this.Dispose(false); + ~BNS() => Dispose(false); public void Dispose() { - this.Dispose(true); - GC.SuppressFinalize((object) this); + Dispose(true); + GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { - if (disposing && !this.isDisposed) + if (disposing && !isDisposed) { - this.bnsHeader = (BNS_Header) null; - this.bnsInfo = (BNS_Info) null; - this.bnsData = (BNS_Data) null; - this.lSamples = (int[,]) null; - this.rlSamples = (int[,]) null; - this.tlSamples = (int[]) null; - this.hbcDefTbl = (int[]) null; - this.pHist1 = (int[]) null; - this.pHist2 = (int[]) null; - this.waveFile = (byte[]) null; + bnsHeader = null; + bnsInfo = null; + bnsData = null; + //this.lSamples = (int[,])null; + rlSamples = null; + tlSamples = null; + //this.hbcDefTbl = (int[])null; + pHist1 = null; + pHist2 = null; + waveFile = null; } - this.isDisposed = true; + isDisposed = true; } #endregion @@ -179,7 +189,7 @@ namespace libWiiSharp /// public static int GetBnsLength(byte[] bnsFile) { - uint sampleRate = (uint) Shared.Swap(BitConverter.ToUInt16(bnsFile, 44)); + uint sampleRate = Shared.Swap(BitConverter.ToUInt16(bnsFile, 44)); uint sampleCount = Shared.Swap(BitConverter.ToUInt32(bnsFile, 52)); return (int)(sampleCount / sampleRate); @@ -188,13 +198,19 @@ namespace libWiiSharp /// /// Converts the Wave file to BNS /// - public void Convert() => this.convert(this.waveFile, this.loopFromWave); + public void Convert() + { + Convert(waveFile, loopFromWave); + } /// /// Returns the BNS file as a Byte Array. If not already converted, it will be done first. /// /// - public byte[] ToByteArray() => this.ToMemoryStream().ToArray(); + public byte[] ToByteArray() + { + return ToMemoryStream().ToArray(); + } /// /// Returns the BNS file as a Memory Stream. If not already converted, it will be done first. @@ -202,14 +218,17 @@ namespace libWiiSharp /// public MemoryStream ToMemoryStream() { - if (!this.converted) - this.convert(this.waveFile, this.loopFromWave); + if (!converted) + { + Convert(waveFile, loopFromWave); + } + MemoryStream memoryStream = new MemoryStream(); try { - this.bnsHeader.Write((Stream) memoryStream); - this.bnsInfo.Write((Stream) memoryStream); - this.bnsData.Write((Stream) memoryStream); + bnsHeader.Write(memoryStream); + bnsInfo.Write(memoryStream); + bnsData.Write(memoryStream); return memoryStream; } catch @@ -226,12 +245,13 @@ namespace libWiiSharp public void Save(string destinationFile) { if (File.Exists(destinationFile)) - File.Delete(destinationFile); - using (FileStream fileStream = new FileStream(destinationFile, FileMode.Create)) { - byte[] array = this.ToMemoryStream().ToArray(); - fileStream.Write(array, 0, array.Length); + File.Delete(destinationFile); } + + using FileStream fileStream = new FileStream(destinationFile, FileMode.Create); + byte[] array = ToMemoryStream().ToArray(); + fileStream.Write(array, 0, array.Length); } /// @@ -240,83 +260,96 @@ namespace libWiiSharp /// public void SetLoop(int loopStartSample) { - this.bnsInfo.HasLoop = (byte) 1; - this.bnsInfo.LoopStart = (uint) loopStartSample; + bnsInfo.HasLoop = 1; + bnsInfo.LoopStart = (uint)loopStartSample; } #endregion #region Private Functions - private void convert(byte[] waveFile, bool loopFromWave) + private void Convert(byte[] waveFile, bool loopFromWave) { Wave wave = new Wave(waveFile); int numLoops = wave.NumLoops; int loopStart = wave.LoopStart; - this.bnsInfo.ChannelCount = (byte) wave.NumChannels; - this.bnsInfo.SampleRate = (ushort) wave.SampleRate; - if (this.bnsInfo.ChannelCount > (byte) 2 || this.bnsInfo.ChannelCount < (byte) 1) - throw new Exception("Unsupported Amount of Channels!"); - if (wave.BitDepth != 16) - throw new Exception("Only 16bit Wave files are supported!"); - this.bnsData.Data = wave.DataFormat == 1 ? this.Encode(wave.SampleData) : throw new Exception("The format of this Wave file is not supported!"); - if (this.bnsInfo.ChannelCount == (byte) 1) + bnsInfo.ChannelCount = (byte)wave.NumChannels; + bnsInfo.SampleRate = (ushort)wave.SampleRate; + if (bnsInfo.ChannelCount > 2 || bnsInfo.ChannelCount < 1) { - this.bnsHeader.InfoLength = 96U; - this.bnsHeader.DataOffset = 128U; - this.bnsInfo.Size = 96U; - this.bnsInfo.Channel1StartOffset = 28U; - this.bnsInfo.Channel2StartOffset = 0U; - this.bnsInfo.Channel1Start = 40U; - this.bnsInfo.Coefficients1Offset = 0U; + throw new Exception("Unsupported Amount of Channels!"); } - this.bnsData.Size = (uint) (this.bnsData.Data.Length + 8); - this.bnsHeader.DataLength = this.bnsData.Size; - this.bnsHeader.FileSize = (uint) this.bnsHeader.Size + this.bnsInfo.Size + this.bnsData.Size; + + if (wave.BitDepth != 16) + { + throw new Exception("Only 16bit Wave files are supported!"); + } + + bnsData.Data = wave.DataFormat == 1 ? Encode(wave.SampleData) : throw new Exception("The format of this Wave file is not supported!"); + if (bnsInfo.ChannelCount == 1) + { + bnsHeader.InfoLength = 96U; + bnsHeader.DataOffset = 128U; + bnsInfo.Size = 96U; + bnsInfo.Channel1StartOffset = 28U; + bnsInfo.Channel2StartOffset = 0U; + bnsInfo.Channel1Start = 40U; + bnsInfo.Coefficients1Offset = 0U; + } + bnsData.Size = (uint)(bnsData.Data.Length + 8); + bnsHeader.DataLength = bnsData.Size; + bnsHeader.FileSize = bnsHeader.Size + bnsInfo.Size + bnsData.Size; if (loopFromWave && numLoops == 1 && loopStart != -1) { - this.bnsInfo.LoopStart = (uint) loopStart; - this.bnsInfo.HasLoop = (byte) 1; + bnsInfo.LoopStart = (uint)loopStart; + bnsInfo.HasLoop = 1; } - this.bnsInfo.LoopEnd = (uint) this.tempSampleCount; + bnsInfo.LoopEnd = (uint)tempSampleCount; for (int index = 0; index < 16; ++index) { - this.bnsInfo.Coefficients1[index] = this.defTbl[index]; - if (this.bnsInfo.ChannelCount == (byte) 2) - this.bnsInfo.Coefficients2[index] = this.defTbl[index]; + bnsInfo.Coefficients1[index] = defTbl[index]; + if (bnsInfo.ChannelCount == 2) + { + bnsInfo.Coefficients2[index] = defTbl[index]; + } } - this.converted = true; + converted = true; } private byte[] Encode(byte[] inputFrames) { int[] inputBuffer = new int[14]; - this.tempSampleCount = inputFrames.Length / (this.bnsInfo.ChannelCount == (byte) 2 ? 4 : 2); - int num1 = inputFrames.Length / (this.bnsInfo.ChannelCount == (byte) 2 ? 4 : 2) % 14; - Array.Resize(ref inputFrames, inputFrames.Length + (14 - num1) * (this.bnsInfo.ChannelCount == (byte) 2 ? 4 : 2)); - int num2 = inputFrames.Length / (this.bnsInfo.ChannelCount == (byte) 2 ? 4 : 2); + tempSampleCount = inputFrames.Length / (bnsInfo.ChannelCount == 2 ? 4 : 2); + int num1 = inputFrames.Length / (bnsInfo.ChannelCount == 2 ? 4 : 2) % 14; + Array.Resize(ref inputFrames, inputFrames.Length + (14 - num1) * (bnsInfo.ChannelCount == 2 ? 4 : 2)); + int num2 = inputFrames.Length / (bnsInfo.ChannelCount == 2 ? 4 : 2); int num3 = (num2 + 13) / 14; List intList1 = new List(); List intList2 = new List(); int startIndex = 0; - if (this.toMono && this.bnsInfo.ChannelCount == (byte) 2) - this.bnsInfo.ChannelCount = (byte) 1; - else if (this.toMono) - this.toMono = false; + if (toMono && bnsInfo.ChannelCount == 2) + { + bnsInfo.ChannelCount = 1; + } + else if (toMono) + { + toMono = false; + } + for (int index = 0; index < num2; ++index) { - intList1.Add((int) BitConverter.ToInt16(inputFrames, startIndex)); + intList1.Add(BitConverter.ToInt16(inputFrames, startIndex)); startIndex += 2; - if (this.bnsInfo.ChannelCount == (byte) 2 || this.toMono) + if (bnsInfo.ChannelCount == 2 || toMono) { - intList2.Add((int) BitConverter.ToInt16(inputFrames, startIndex)); + intList2.Add(BitConverter.ToInt16(inputFrames, startIndex)); startIndex += 2; } } - byte[] numArray1 = new byte[this.bnsInfo.ChannelCount == (byte) 2 ? num3 * 16 : num3 * 8]; + byte[] numArray1 = new byte[bnsInfo.ChannelCount == 2 ? num3 * 16 : num3 * 8]; int num4 = 0; int num5 = num3 * 8; - this.bnsInfo.Channel2Start = this.bnsInfo.ChannelCount == (byte) 2 ? (uint) num5 : 0U; + bnsInfo.Channel2Start = bnsInfo.ChannelCount == 2 ? (uint)num5 : 0U; int[] array1 = intList1.ToArray(); int[] array2 = intList2.ToArray(); for (int index1 = 0; index1 < num3; ++index1) @@ -326,31 +359,45 @@ namespace libWiiSharp if (index1 % (num3 / 100) != 0) { if (index1 + 1 != num3) - goto label_14; + { + goto label_14; + } } - this.ChangeProgress((index1 + 1) * 100 / num3); + ChangeProgress((index1 + 1) * 100 / num3); } catch { } - label_14: + label_14: for (int index2 = 0; index2 < 14; ++index2) + { inputBuffer[index2] = array1[index1 * 14 + index2]; - byte[] numArray2 = this.RepackAdpcm(0, this.defTbl, inputBuffer); + } + + byte[] numArray2 = RepackAdpcm(0, defTbl, inputBuffer); for (int index2 = 0; index2 < 8; ++index2) + { numArray1[num4 + index2] = numArray2[index2]; + } + num4 += 8; - if (this.bnsInfo.ChannelCount == (byte) 2) + if (bnsInfo.ChannelCount == 2) { for (int index2 = 0; index2 < 14; ++index2) + { inputBuffer[index2] = array2[index1 * 14 + index2]; - byte[] numArray3 = this.RepackAdpcm(1, this.defTbl, inputBuffer); + } + + byte[] numArray3 = RepackAdpcm(1, defTbl, inputBuffer); for (int index2 = 0; index2 < 8; ++index2) + { numArray1[num5 + index2] = numArray3[index2]; + } + num5 += 8; } } - this.bnsInfo.LoopEnd = (uint) (num3 * 7); + bnsInfo.LoopEnd = (uint)(num3 * 7); return numArray1; } @@ -361,15 +408,19 @@ namespace libWiiSharp double num1 = 999999999.0; for (int tableIndex = 0; tableIndex < 8; ++tableIndex) { - double outError; - byte[] numArray3 = this.CompressAdpcm(index, table, tableIndex, inputBuffer, out outError); + byte[] numArray3 = CompressAdpcm(index, table, tableIndex, inputBuffer, out double outError); if (outError < num1) { num1 = outError; for (int index1 = 0; index1 < 8; ++index1) + { numArray1[index1] = numArray3[index1]; + } + for (int index1 = 0; index1 < 2; ++index1) - numArray2[index1] = this.tlSamples[index1]; + { + numArray2[index1] = tlSamples[index1]; + } } } for (int index1 = 0; index1 < 2; ++index1) @@ -395,27 +446,30 @@ namespace libWiiSharp int num1 = 0; int num2 = table[2 * tableIndex]; int num3 = table[2 * tableIndex + 1]; - int stdExponent = this.DetermineStdExponent(index, table, tableIndex, inputBuffer); + int stdExponent = DetermineStdExponent(index, table, tableIndex, inputBuffer); while (stdExponent <= 15) { bool flag = false; num1 = 0; - numArray[0] = (byte) (stdExponent | tableIndex << 4); + numArray[0] = (byte)(stdExponent | tableIndex << 4); for (int index1 = 0; index1 < 2; ++index1) - this.tlSamples[index1] = this.rlSamples[index, index1]; + { + tlSamples[index1] = rlSamples[index, index1]; + } + int num4 = 0; for (int index1 = 0; index1 < 14; ++index1) { - int num5 = this.tlSamples[1] * num2 + this.tlSamples[0] * num3 >> 11; + int num5 = tlSamples[1] * num2 + tlSamples[0] * num3 >> 11; int input1 = inputBuffer[index1] - num5 >> stdExponent; if (input1 <= 7 && input1 >= -8) { - int num6 = this.Clamp(input1, -8, 7); - numArray[index1 / 2 + 1] = (index1 & 1) == 0 ? (byte) (num6 << 4) : (byte) ((uint) numArray[index1 / 2 + 1] | (uint) (num6 & 15)); + int num6 = Clamp(input1, -8, 7); + numArray[index1 / 2 + 1] = (index1 & 1) == 0 ? (byte)(num6 << 4) : (byte)(numArray[index1 / 2 + 1] | (uint)(num6 & 15)); int input2 = num5 + (num6 << stdExponent); - this.tlSamples[0] = this.tlSamples[1]; - this.tlSamples[1] = this.Clamp(input2, (int) short.MinValue, (int) short.MaxValue); - num1 += (int) Math.Pow((double) (this.tlSamples[1] - inputBuffer[index1]), 2.0); + tlSamples[0] = tlSamples[1]; + tlSamples[1] = Clamp(input2, short.MinValue, short.MaxValue); + num1 += (int)Math.Pow(tlSamples[1] - inputBuffer[index1], 2.0); } else { @@ -425,11 +479,16 @@ namespace libWiiSharp } } if (!flag) + { num4 = 14; + } + if (num4 == 14) + { break; + } } - outError = (double) num1; + outError = num1; return numArray; } @@ -440,39 +499,54 @@ namespace libWiiSharp int num2 = table[2 * tableIndex]; int num3 = table[2 * tableIndex + 1]; for (int index1 = 0; index1 < 2; ++index1) - numArray[index1] = this.rlSamples[index, index1]; + { + numArray[index1] = rlSamples[index, index1]; + } + for (int index1 = 0; index1 < 14; ++index1) { int num4 = numArray[1] * num2 + numArray[0] * num3 >> 11; int num5 = inputBuffer[index1] - num4; if (num5 > num1) + { num1 = num5; + } + numArray[0] = numArray[1]; numArray[1] = inputBuffer[index1]; } - return this.FindExponent((double) num1); + return FindExponent(num1); } private int FindExponent(double residual) { int num = 0; for (; residual > 7.5 || residual < -8.5; residual /= 2.0) + { ++num; + } + return num; } private int Clamp(int input, int min, int max) { if (input < min) + { return min; + } + return input > max ? max : input; } private void ChangeProgress(int progressPercentage) { - EventHandler progress = this.Progress; + EventHandler progress = Progress; if (progress == null) + { return; + } + progress(new object(), new ProgressChangedEventArgs(progressPercentage, new object())); } @@ -492,33 +566,48 @@ namespace libWiiSharp { BNS bns = new BNS(); byte[] samples = bns.Read(inputFile); - Wave wave = new Wave((int) bns.bnsInfo.ChannelCount, 16, (int) bns.bnsInfo.SampleRate, samples); - if (bns.bnsInfo.HasLoop == (byte) 1) - wave.AddLoop((int) bns.bnsInfo.LoopStart); + Wave wave = new Wave(bns.bnsInfo.ChannelCount, 16, bns.bnsInfo.SampleRate, samples); + if (bns.bnsInfo.HasLoop == 1) + { + wave.AddLoop((int)bns.bnsInfo.LoopStart); + } + return wave; } public static Wave BnsToWave(string pathToFile) { BNS bns = new BNS(); - byte[] samples = (byte[]) null; + byte[] samples = null; using (FileStream fileStream = new FileStream(pathToFile, FileMode.Open)) - samples = bns.Read((Stream) fileStream); - Wave wave = new Wave((int) bns.bnsInfo.ChannelCount, 16, (int) bns.bnsInfo.SampleRate, samples); - if (bns.bnsInfo.HasLoop == (byte) 1) - wave.AddLoop((int) bns.bnsInfo.LoopStart); + { + samples = bns.Read(fileStream); + } + + Wave wave = new Wave(bns.bnsInfo.ChannelCount, 16, bns.bnsInfo.SampleRate, samples); + if (bns.bnsInfo.HasLoop == 1) + { + wave.AddLoop((int)bns.bnsInfo.LoopStart); + } + return wave; } public static Wave BnsToWave(byte[] bnsFile) { BNS bns = new BNS(); - byte[] samples = (byte[]) null; + byte[] samples = null; using (MemoryStream memoryStream = new MemoryStream(bnsFile)) - samples = bns.Read((Stream) memoryStream); - Wave wave = new Wave((int) bns.bnsInfo.ChannelCount, 16, (int) bns.bnsInfo.SampleRate, samples); - if (bns.bnsInfo.HasLoop == (byte) 1) - wave.AddLoop((int) bns.bnsInfo.LoopStart); + { + samples = bns.Read(memoryStream); + } + + Wave wave = new Wave(bns.bnsInfo.ChannelCount, 16, bns.bnsInfo.SampleRate, samples); + if (bns.bnsInfo.HasLoop == 1) + { + wave.AddLoop((int)bns.bnsInfo.LoopStart); + } + return wave; } @@ -529,38 +618,43 @@ namespace libWiiSharp private byte[] Read(Stream input) { input.Seek(0L, SeekOrigin.Begin); - this.bnsHeader.Read(input); - this.bnsInfo.Read(input); - this.bnsData.Read(input); - return this.Decode(); + bnsHeader.Read(input); + bnsInfo.Read(input); + bnsData.Read(input); + return Decode(); } private byte[] Decode() { List byteList = new List(); - int num = this.bnsData.Data.Length / (this.bnsInfo.ChannelCount == (byte) 2 ? 16 : 8); + int num = bnsData.Data.Length / (bnsInfo.ChannelCount == 2 ? 16 : 8); int dataOffset1 = 0; int dataOffset2 = num * 8; - byte[] numArray1 = new byte[0]; + //byte[] numArray1 = new byte[0]; byte[] numArray2 = new byte[0]; for (int index1 = 0; index1 < num; ++index1) { - byte[] numArray3 = this.DecodeAdpcm(0, dataOffset1); - if (this.bnsInfo.ChannelCount == (byte) 2) - numArray2 = this.DecodeAdpcm(1, dataOffset2); + byte[] numArray3 = DecodeAdpcm(0, dataOffset1); + if (bnsInfo.ChannelCount == 2) + { + numArray2 = DecodeAdpcm(1, dataOffset2); + } + for (int index2 = 0; index2 < 14; ++index2) { byteList.Add(numArray3[index2 * 2]); byteList.Add(numArray3[index2 * 2 + 1]); - if (this.bnsInfo.ChannelCount == (byte) 2) + if (bnsInfo.ChannelCount == 2) { byteList.Add(numArray2[index2 * 2]); byteList.Add(numArray2[index2 * 2 + 1]); } } dataOffset1 += 8; - if (this.bnsInfo.ChannelCount == (byte) 2) + if (bnsInfo.ChannelCount == 2) + { dataOffset2 += 8; + } } return byteList.ToArray(); } @@ -568,26 +662,29 @@ namespace libWiiSharp private byte[] DecodeAdpcm(int channel, int dataOffset) { byte[] numArray = new byte[28]; - int num1 = (int) this.bnsData.Data[dataOffset] >> 4 & 15; - int num2 = 1 << ((int) this.bnsData.Data[dataOffset] & 15); - int num3 = this.pHist1[channel]; - int num4 = this.pHist2[channel]; - int num5 = channel == 0 ? this.bnsInfo.Coefficients1[num1 * 2] : this.bnsInfo.Coefficients2[num1 * 2]; - int num6 = channel == 0 ? this.bnsInfo.Coefficients1[num1 * 2 + 1] : this.bnsInfo.Coefficients2[num1 * 2 + 1]; + int num1 = bnsData.Data[dataOffset] >> 4 & 15; + int num2 = 1 << (bnsData.Data[dataOffset] & 15); + int num3 = pHist1[channel]; + int num4 = pHist2[channel]; + int num5 = channel == 0 ? bnsInfo.Coefficients1[num1 * 2] : bnsInfo.Coefficients2[num1 * 2]; + int num6 = channel == 0 ? bnsInfo.Coefficients1[num1 * 2 + 1] : bnsInfo.Coefficients2[num1 * 2 + 1]; for (int index = 0; index < 14; ++index) { - short num7 = (short) this.bnsData.Data[dataOffset + (index / 2 + 1)]; - int num8 = (index & 1) != 0 ? (int) num7 & 15 : (int) num7 >> 4; + short num7 = bnsData.Data[dataOffset + (index / 2 + 1)]; + int num8 = (index & 1) != 0 ? num7 & 15 : num7 >> 4; if (num8 >= 8) + { num8 -= 16; - int num9 = this.Clamp((num2 * num8 << 11) + (num5 * num3 + num6 * num4) + 1024 >> 11, (int) short.MinValue, (int) short.MaxValue); - numArray[index * 2] = (byte) ((uint) (short) num9 & (uint) byte.MaxValue); - numArray[index * 2 + 1] = (byte) ((uint) (short) num9 >> 8); + } + + int num9 = Clamp((num2 * num8 << 11) + (num5 * num3 + num6 * num4) + 1024 >> 11, short.MinValue, short.MaxValue); + numArray[index * 2] = (byte)((uint)(short)num9 & byte.MaxValue); + numArray[index * 2 + 1] = (byte)((uint)(short)num9 >> 8); num4 = num3; num3 = num9; } - this.pHist1[channel] = num3; - this.pHist2[channel] = num4; + pHist1[channel] = num3; + pHist2[channel] = num4; return numArray; } #endregion diff --git a/BNS_Data.cs b/BNS_Data.cs index f8a1580..ac9a487 100644 --- a/BNS_Data.cs +++ b/BNS_Data.cs @@ -23,41 +23,41 @@ namespace libWiiSharp { internal class BNS_Data { - private byte[] magic = new byte[4] + private readonly byte[] magic = new byte[4] { - (byte) 68, - (byte) 65, - (byte) 84, - (byte) 65 + 68, + 65, + 84, + 65 }; private uint size = 315392; private byte[] data; public uint Size { - get => this.size; - set => this.size = value; + get => size; + set => size = value; } public byte[] Data { - get => this.data; - set => this.data = value; + get => data; + set => data = value; } public void Write(Stream outStream) { - byte[] bytes = BitConverter.GetBytes(Shared.Swap(this.size)); - outStream.Write(this.magic, 0, this.magic.Length); + byte[] bytes = BitConverter.GetBytes(Shared.Swap(size)); + outStream.Write(magic, 0, magic.Length); outStream.Write(bytes, 0, bytes.Length); - outStream.Write(this.data, 0, this.data.Length); + outStream.Write(data, 0, data.Length); } public void Read(Stream input) { BinaryReader binaryReader = new BinaryReader(input); - this.size = Shared.CompareByteArrays(this.magic, binaryReader.ReadBytes(4)) ? Shared.Swap(binaryReader.ReadUInt32()) : throw new Exception("This is not a valid BNS audfo file!"); - this.data = binaryReader.ReadBytes((int) this.size - 8); + size = Shared.CompareByteArrays(magic, binaryReader.ReadBytes(4)) ? Shared.Swap(binaryReader.ReadUInt32()) : throw new Exception("This is not a valid BNS audfo file!"); + data = binaryReader.ReadBytes((int)size - 8); } } } diff --git a/BNS_Header.cs b/BNS_Header.cs index df463dc..e6648eb 100644 --- a/BNS_Header.cs +++ b/BNS_Header.cs @@ -23,12 +23,12 @@ namespace libWiiSharp { internal class BNS_Header { - private byte[] magic = new byte[4] + private readonly byte[] magic = new byte[4] { - (byte) 66, - (byte) 78, - (byte) 83, - (byte) 32 + 66, + 78, + 83, + 32 }; private uint flags = 4278124800; private uint fileSize = 315584; @@ -41,80 +41,82 @@ namespace libWiiSharp public uint DataOffset { - get => this.dataOffset; - set => this.dataOffset = value; + get => dataOffset; + set => dataOffset = value; } public uint InfoLength { - get => this.infoLength; - set => this.infoLength = value; + get => infoLength; + set => infoLength = value; } public ushort Size { - get => this.size; - set => this.size = value; + get => size; + set => size = value; } public uint DataLength { - get => this.dataLength; - set => this.dataLength = value; + get => dataLength; + set => dataLength = value; } public uint FileSize { - get => this.fileSize; - set => this.fileSize = value; + get => fileSize; + set => fileSize = value; } public void Write(Stream outStream) { - outStream.Write(this.magic, 0, this.magic.Length); - byte[] bytes1 = BitConverter.GetBytes(this.flags); - Array.Reverse((Array) bytes1); - outStream.Write(bytes1, 0, bytes1.Length); - byte[] bytes2 = BitConverter.GetBytes(this.fileSize); - Array.Reverse((Array) bytes2); - outStream.Write(bytes2, 0, bytes2.Length); - byte[] bytes3 = BitConverter.GetBytes(this.size); - Array.Reverse((Array) bytes3); - outStream.Write(bytes3, 0, bytes3.Length); - byte[] bytes4 = BitConverter.GetBytes(this.chunkCount); - Array.Reverse((Array) bytes4); - outStream.Write(bytes4, 0, bytes4.Length); - byte[] bytes5 = BitConverter.GetBytes(this.infoOffset); - Array.Reverse((Array) bytes5); - outStream.Write(bytes5, 0, bytes5.Length); - byte[] bytes6 = BitConverter.GetBytes(this.infoLength); - Array.Reverse((Array) bytes6); - outStream.Write(bytes6, 0, bytes6.Length); - byte[] bytes7 = BitConverter.GetBytes(this.dataOffset); - Array.Reverse((Array) bytes7); - outStream.Write(bytes7, 0, bytes7.Length); - byte[] bytes8 = BitConverter.GetBytes(this.dataLength); - Array.Reverse((Array) bytes8); - outStream.Write(bytes8, 0, bytes8.Length); + outStream.Write(magic, 0, magic.Length); + byte[] bytes1 = BitConverter.GetBytes(flags); + Array.Reverse(bytes1); + outStream.Write(bytes1, 0, bytes1.Length); + byte[] bytes2 = BitConverter.GetBytes(fileSize); + Array.Reverse(bytes2); + outStream.Write(bytes2, 0, bytes2.Length); + byte[] bytes3 = BitConverter.GetBytes(size); + Array.Reverse(bytes3); + outStream.Write(bytes3, 0, bytes3.Length); + byte[] bytes4 = BitConverter.GetBytes(chunkCount); + Array.Reverse(bytes4); + outStream.Write(bytes4, 0, bytes4.Length); + byte[] bytes5 = BitConverter.GetBytes(infoOffset); + Array.Reverse(bytes5); + outStream.Write(bytes5, 0, bytes5.Length); + byte[] bytes6 = BitConverter.GetBytes(infoLength); + Array.Reverse(bytes6); + outStream.Write(bytes6, 0, bytes6.Length); + byte[] bytes7 = BitConverter.GetBytes(dataOffset); + Array.Reverse(bytes7); + outStream.Write(bytes7, 0, bytes7.Length); + byte[] bytes8 = BitConverter.GetBytes(dataLength); + Array.Reverse(bytes8); + outStream.Write(bytes8, 0, bytes8.Length); } public void Read(Stream input) { BinaryReader binaryReader = new BinaryReader(input); - if (!Shared.CompareByteArrays(this.magic, binaryReader.ReadBytes(4))) + if (!Shared.CompareByteArrays(magic, binaryReader.ReadBytes(4))) { binaryReader.BaseStream.Seek(28L, SeekOrigin.Current); - if (!Shared.CompareByteArrays(this.magic, binaryReader.ReadBytes(4))) + if (!Shared.CompareByteArrays(magic, binaryReader.ReadBytes(4))) + { throw new Exception("This is not a valid BNS audio file!"); + } } - this.flags = Shared.Swap(binaryReader.ReadUInt32()); - this.fileSize = Shared.Swap(binaryReader.ReadUInt32()); - this.size = Shared.Swap(binaryReader.ReadUInt16()); - this.chunkCount = Shared.Swap(binaryReader.ReadUInt16()); - this.infoOffset = Shared.Swap(binaryReader.ReadUInt32()); - this.infoLength = Shared.Swap(binaryReader.ReadUInt32()); - this.dataOffset = Shared.Swap(binaryReader.ReadUInt32()); - this.dataLength = Shared.Swap(binaryReader.ReadUInt32()); + flags = Shared.Swap(binaryReader.ReadUInt32()); + fileSize = Shared.Swap(binaryReader.ReadUInt32()); + size = Shared.Swap(binaryReader.ReadUInt16()); + chunkCount = Shared.Swap(binaryReader.ReadUInt16()); + infoOffset = Shared.Swap(binaryReader.ReadUInt32()); + infoLength = Shared.Swap(binaryReader.ReadUInt32()); + dataOffset = Shared.Swap(binaryReader.ReadUInt32()); + dataLength = Shared.Swap(binaryReader.ReadUInt32()); } } } diff --git a/BNS_Info.cs b/BNS_Info.cs index 01cf279..df92670 100644 --- a/BNS_Info.cs +++ b/BNS_Info.cs @@ -24,12 +24,12 @@ namespace libWiiSharp internal class BNS_Info { //Private Variables - private byte[] magic = new byte[4] + private readonly byte[] magic = new byte[4] { - (byte) 73, - (byte) 78, - (byte) 70, - (byte) 79 + 73, + 78, + 70, + 79 }; private uint size = 160; private byte codec; @@ -72,230 +72,233 @@ namespace libWiiSharp //Public Variables public byte HasLoop { - get => this.hasLoop; - set => this.hasLoop = value; + get => hasLoop; + set => hasLoop = value; } public uint Coefficients1Offset { - get => this.coefficients1Offset; - set => this.coefficients1Offset = value; + get => coefficients1Offset; + set => coefficients1Offset = value; } public uint Channel1StartOffset { - get => this.channel1StartOffset; - set => this.channel1StartOffset = value; + get => channel1StartOffset; + set => channel1StartOffset = value; } public uint Channel2StartOffset { - get => this.channel2StartOffset; - set => this.channel2StartOffset = value; + get => channel2StartOffset; + set => channel2StartOffset = value; } public uint Size { - get => this.size; - set => this.size = value; + get => size; + set => size = value; } public ushort SampleRate { - get => this.sampleRate; - set => this.sampleRate = value; + get => sampleRate; + set => sampleRate = value; } public byte ChannelCount { - get => this.channelCount; - set => this.channelCount = value; + get => channelCount; + set => channelCount = value; } public uint Channel1Start { - get => this.channel1Start; - set => this.channel1Start = value; + get => channel1Start; + set => channel1Start = value; } public uint Channel2Start { - get => this.channel2Start; - set => this.channel2Start = value; + get => channel2Start; + set => channel2Start = value; } public uint LoopStart { - get => this.loopStart; - set => this.loopStart = value; + get => loopStart; + set => loopStart = value; } public uint LoopEnd { - get => this.loopEnd; - set => this.loopEnd = value; + get => loopEnd; + set => loopEnd = value; } public int[] Coefficients1 { - get => this.coefficients1; - set => this.coefficients1 = value; + get => coefficients1; + set => coefficients1 = value; } public int[] Coefficients2 { - get => this.coefficients2; - set => this.coefficients2 = value; + get => coefficients2; + set => coefficients2 = value; } public void Write(Stream outStream) { - outStream.Write(this.magic, 0, this.magic.Length); - byte[] bytes1 = BitConverter.GetBytes(this.size); - Array.Reverse((Array) bytes1); + outStream.Write(magic, 0, magic.Length); + byte[] bytes1 = BitConverter.GetBytes(size); + Array.Reverse(bytes1); outStream.Write(bytes1, 0, bytes1.Length); - outStream.WriteByte(this.codec); - outStream.WriteByte(this.hasLoop); - outStream.WriteByte(this.channelCount); - outStream.WriteByte(this.zero); - byte[] bytes2 = BitConverter.GetBytes(this.sampleRate); - Array.Reverse((Array) bytes2); + outStream.WriteByte(codec); + outStream.WriteByte(hasLoop); + outStream.WriteByte(channelCount); + outStream.WriteByte(zero); + byte[] bytes2 = BitConverter.GetBytes(sampleRate); + Array.Reverse(bytes2); outStream.Write(bytes2, 0, bytes2.Length); - byte[] bytes3 = BitConverter.GetBytes(this.pad0); - Array.Reverse((Array) bytes3); + byte[] bytes3 = BitConverter.GetBytes(pad0); + Array.Reverse(bytes3); outStream.Write(bytes3, 0, bytes3.Length); - byte[] bytes4 = BitConverter.GetBytes(this.loopStart); - Array.Reverse((Array) bytes4); + byte[] bytes4 = BitConverter.GetBytes(loopStart); + Array.Reverse(bytes4); outStream.Write(bytes4, 0, bytes4.Length); - byte[] bytes5 = BitConverter.GetBytes(this.loopEnd); - Array.Reverse((Array) bytes5); + byte[] bytes5 = BitConverter.GetBytes(loopEnd); + Array.Reverse(bytes5); outStream.Write(bytes5, 0, bytes5.Length); - byte[] bytes6 = BitConverter.GetBytes(this.offsetToChannelStart); - Array.Reverse((Array) bytes6); + byte[] bytes6 = BitConverter.GetBytes(offsetToChannelStart); + Array.Reverse(bytes6); outStream.Write(bytes6, 0, bytes6.Length); - byte[] bytes7 = BitConverter.GetBytes(this.pad1); - Array.Reverse((Array) bytes7); + byte[] bytes7 = BitConverter.GetBytes(pad1); + Array.Reverse(bytes7); outStream.Write(bytes7, 0, bytes7.Length); - byte[] bytes8 = BitConverter.GetBytes(this.channel1StartOffset); - Array.Reverse((Array) bytes8); + byte[] bytes8 = BitConverter.GetBytes(channel1StartOffset); + Array.Reverse(bytes8); outStream.Write(bytes8, 0, bytes8.Length); - byte[] bytes9 = BitConverter.GetBytes(this.channel2StartOffset); - Array.Reverse((Array) bytes9); + byte[] bytes9 = BitConverter.GetBytes(channel2StartOffset); + Array.Reverse(bytes9); outStream.Write(bytes9, 0, bytes9.Length); - byte[] bytes10 = BitConverter.GetBytes(this.channel1Start); - Array.Reverse((Array) bytes10); + byte[] bytes10 = BitConverter.GetBytes(channel1Start); + Array.Reverse(bytes10); outStream.Write(bytes10, 0, bytes10.Length); - byte[] bytes11 = BitConverter.GetBytes(this.coefficients1Offset); - Array.Reverse((Array) bytes11); + byte[] bytes11 = BitConverter.GetBytes(coefficients1Offset); + Array.Reverse(bytes11); outStream.Write(bytes11, 0, bytes11.Length); - if (this.channelCount == (byte) 2) + if (channelCount == 2) { - byte[] bytes12 = BitConverter.GetBytes(this.pad2); - Array.Reverse((Array) bytes12); + byte[] bytes12 = BitConverter.GetBytes(pad2); + Array.Reverse(bytes12); outStream.Write(bytes12, 0, bytes12.Length); - byte[] bytes13 = BitConverter.GetBytes(this.channel2Start); - Array.Reverse((Array) bytes13); + byte[] bytes13 = BitConverter.GetBytes(channel2Start); + Array.Reverse(bytes13); outStream.Write(bytes13, 0, bytes13.Length); - byte[] bytes14 = BitConverter.GetBytes(this.coefficients2Offset); - Array.Reverse((Array) bytes14); + byte[] bytes14 = BitConverter.GetBytes(coefficients2Offset); + Array.Reverse(bytes14); outStream.Write(bytes14, 0, bytes14.Length); - byte[] bytes15 = BitConverter.GetBytes(this.pad3); - Array.Reverse((Array) bytes15); + byte[] bytes15 = BitConverter.GetBytes(pad3); + Array.Reverse(bytes15); outStream.Write(bytes15, 0, bytes15.Length); - foreach (int num in this.coefficients1) + foreach (int num in coefficients1) { byte[] bytes16 = BitConverter.GetBytes(num); - Array.Reverse((Array) bytes16); + Array.Reverse(bytes16); outStream.Write(bytes16, 2, bytes16.Length - 2); } - byte[] bytes17 = BitConverter.GetBytes(this.channel1Gain); - Array.Reverse((Array) bytes17); + byte[] bytes17 = BitConverter.GetBytes(channel1Gain); + Array.Reverse(bytes17); outStream.Write(bytes17, 0, bytes17.Length); - byte[] bytes18 = BitConverter.GetBytes(this.channel1PredictiveScale); - Array.Reverse((Array) bytes18); + byte[] bytes18 = BitConverter.GetBytes(channel1PredictiveScale); + Array.Reverse(bytes18); outStream.Write(bytes18, 0, bytes18.Length); - byte[] bytes19 = BitConverter.GetBytes(this.channel1PreviousValue); - Array.Reverse((Array) bytes19); + byte[] bytes19 = BitConverter.GetBytes(channel1PreviousValue); + Array.Reverse(bytes19); outStream.Write(bytes19, 0, bytes19.Length); - byte[] bytes20 = BitConverter.GetBytes(this.channel1NextPreviousValue); - Array.Reverse((Array) bytes20); + byte[] bytes20 = BitConverter.GetBytes(channel1NextPreviousValue); + Array.Reverse(bytes20); outStream.Write(bytes20, 0, bytes20.Length); - byte[] bytes21 = BitConverter.GetBytes(this.channel1LoopPredictiveScale); - Array.Reverse((Array) bytes21); + byte[] bytes21 = BitConverter.GetBytes(channel1LoopPredictiveScale); + Array.Reverse(bytes21); outStream.Write(bytes21, 0, bytes21.Length); - byte[] bytes22 = BitConverter.GetBytes(this.channel1LoopPreviousValue); - Array.Reverse((Array) bytes22); + byte[] bytes22 = BitConverter.GetBytes(channel1LoopPreviousValue); + Array.Reverse(bytes22); outStream.Write(bytes22, 0, bytes22.Length); - byte[] bytes23 = BitConverter.GetBytes(this.channel1LoopNextPreviousValue); - Array.Reverse((Array) bytes23); + byte[] bytes23 = BitConverter.GetBytes(channel1LoopNextPreviousValue); + Array.Reverse(bytes23); outStream.Write(bytes23, 0, bytes23.Length); - byte[] bytes24 = BitConverter.GetBytes(this.channel1LoopPadding); - Array.Reverse((Array) bytes24); + byte[] bytes24 = BitConverter.GetBytes(channel1LoopPadding); + Array.Reverse(bytes24); outStream.Write(bytes24, 0, bytes24.Length); - foreach (int num in this.coefficients2) + foreach (int num in coefficients2) { byte[] bytes16 = BitConverter.GetBytes(num); - Array.Reverse((Array) bytes16); + Array.Reverse(bytes16); outStream.Write(bytes16, 2, bytes16.Length - 2); } - byte[] bytes25 = BitConverter.GetBytes(this.channel2Gain); - Array.Reverse((Array) bytes25); + byte[] bytes25 = BitConverter.GetBytes(channel2Gain); + Array.Reverse(bytes25); outStream.Write(bytes25, 0, bytes25.Length); - byte[] bytes26 = BitConverter.GetBytes(this.channel2PredictiveScale); - Array.Reverse((Array) bytes26); + byte[] bytes26 = BitConverter.GetBytes(channel2PredictiveScale); + Array.Reverse(bytes26); outStream.Write(bytes26, 0, bytes26.Length); - byte[] bytes27 = BitConverter.GetBytes(this.channel2PreviousValue); - Array.Reverse((Array) bytes27); + byte[] bytes27 = BitConverter.GetBytes(channel2PreviousValue); + Array.Reverse(bytes27); outStream.Write(bytes27, 0, bytes27.Length); - byte[] bytes28 = BitConverter.GetBytes(this.channel2NextPreviousValue); - Array.Reverse((Array) bytes28); + byte[] bytes28 = BitConverter.GetBytes(channel2NextPreviousValue); + Array.Reverse(bytes28); outStream.Write(bytes28, 0, bytes28.Length); - byte[] bytes29 = BitConverter.GetBytes(this.channel2LoopPredictiveScale); - Array.Reverse((Array) bytes29); + byte[] bytes29 = BitConverter.GetBytes(channel2LoopPredictiveScale); + Array.Reverse(bytes29); outStream.Write(bytes29, 0, bytes29.Length); - byte[] bytes30 = BitConverter.GetBytes(this.channel2LoopPreviousValue); - Array.Reverse((Array) bytes30); + byte[] bytes30 = BitConverter.GetBytes(channel2LoopPreviousValue); + Array.Reverse(bytes30); outStream.Write(bytes30, 0, bytes30.Length); - byte[] bytes31 = BitConverter.GetBytes(this.channel2LoopNextPreviousValue); - Array.Reverse((Array) bytes31); + byte[] bytes31 = BitConverter.GetBytes(channel2LoopNextPreviousValue); + Array.Reverse(bytes31); outStream.Write(bytes31, 0, bytes31.Length); - byte[] bytes32 = BitConverter.GetBytes(this.channel2LoopPadding); - Array.Reverse((Array) bytes32); + byte[] bytes32 = BitConverter.GetBytes(channel2LoopPadding); + Array.Reverse(bytes32); outStream.Write(bytes32, 0, bytes32.Length); } else { - if (this.channelCount != (byte) 1) + if (channelCount != 1) + { return; - foreach (int num in this.coefficients1) + } + + foreach (int num in coefficients1) { byte[] bytes12 = BitConverter.GetBytes(num); - Array.Reverse((Array) bytes12); + Array.Reverse(bytes12); outStream.Write(bytes12, 2, bytes12.Length - 2); } - byte[] bytes13 = BitConverter.GetBytes(this.channel1Gain); - Array.Reverse((Array) bytes13); + byte[] bytes13 = BitConverter.GetBytes(channel1Gain); + Array.Reverse(bytes13); outStream.Write(bytes13, 0, bytes13.Length); - byte[] bytes14 = BitConverter.GetBytes(this.channel1PredictiveScale); - Array.Reverse((Array) bytes14); + byte[] bytes14 = BitConverter.GetBytes(channel1PredictiveScale); + Array.Reverse(bytes14); outStream.Write(bytes14, 0, bytes14.Length); - byte[] bytes15 = BitConverter.GetBytes(this.channel1PreviousValue); - Array.Reverse((Array) bytes15); + byte[] bytes15 = BitConverter.GetBytes(channel1PreviousValue); + Array.Reverse(bytes15); outStream.Write(bytes15, 0, bytes15.Length); - byte[] bytes16 = BitConverter.GetBytes(this.channel1NextPreviousValue); - Array.Reverse((Array) bytes16); + byte[] bytes16 = BitConverter.GetBytes(channel1NextPreviousValue); + Array.Reverse(bytes16); outStream.Write(bytes16, 0, bytes16.Length); - byte[] bytes17 = BitConverter.GetBytes(this.channel1LoopPredictiveScale); - Array.Reverse((Array) bytes17); + byte[] bytes17 = BitConverter.GetBytes(channel1LoopPredictiveScale); + Array.Reverse(bytes17); outStream.Write(bytes17, 0, bytes17.Length); - byte[] bytes18 = BitConverter.GetBytes(this.channel1LoopPreviousValue); - Array.Reverse((Array) bytes18); + byte[] bytes18 = BitConverter.GetBytes(channel1LoopPreviousValue); + Array.Reverse(bytes18); outStream.Write(bytes18, 0, bytes18.Length); - byte[] bytes19 = BitConverter.GetBytes(this.channel1LoopNextPreviousValue); - Array.Reverse((Array) bytes19); + byte[] bytes19 = BitConverter.GetBytes(channel1LoopNextPreviousValue); + Array.Reverse(bytes19); outStream.Write(bytes19, 0, bytes19.Length); - byte[] bytes20 = BitConverter.GetBytes(this.channel1LoopPadding); - Array.Reverse((Array) bytes20); + byte[] bytes20 = BitConverter.GetBytes(channel1LoopPadding); + Array.Reverse(bytes20); outStream.Write(bytes20, 0, bytes20.Length); } } @@ -303,62 +306,74 @@ namespace libWiiSharp public void Read(Stream input) { BinaryReader binaryReader = new BinaryReader(input); - this.size = Shared.CompareByteArrays(this.magic, binaryReader.ReadBytes(4)) ? Shared.Swap(binaryReader.ReadUInt32()) : throw new Exception("This is not a valid BNS audfo file!"); - this.codec = binaryReader.ReadByte(); - this.hasLoop = binaryReader.ReadByte(); - this.channelCount = binaryReader.ReadByte(); - this.zero = binaryReader.ReadByte(); - this.sampleRate = Shared.Swap(binaryReader.ReadUInt16()); - this.pad0 = Shared.Swap(binaryReader.ReadUInt16()); - this.loopStart = Shared.Swap(binaryReader.ReadUInt32()); - this.loopEnd = Shared.Swap(binaryReader.ReadUInt32()); - this.offsetToChannelStart = Shared.Swap(binaryReader.ReadUInt32()); - this.pad1 = Shared.Swap(binaryReader.ReadUInt32()); - this.channel1StartOffset = Shared.Swap(binaryReader.ReadUInt32()); - this.channel2StartOffset = Shared.Swap(binaryReader.ReadUInt32()); - this.channel1Start = Shared.Swap(binaryReader.ReadUInt32()); - this.coefficients1Offset = Shared.Swap(binaryReader.ReadUInt32()); - if (this.channelCount == (byte) 2) + size = Shared.CompareByteArrays(magic, binaryReader.ReadBytes(4)) ? Shared.Swap(binaryReader.ReadUInt32()) : throw new Exception("This is not a valid BNS audfo file!"); + codec = binaryReader.ReadByte(); + hasLoop = binaryReader.ReadByte(); + channelCount = binaryReader.ReadByte(); + zero = binaryReader.ReadByte(); + sampleRate = Shared.Swap(binaryReader.ReadUInt16()); + pad0 = Shared.Swap(binaryReader.ReadUInt16()); + loopStart = Shared.Swap(binaryReader.ReadUInt32()); + loopEnd = Shared.Swap(binaryReader.ReadUInt32()); + offsetToChannelStart = Shared.Swap(binaryReader.ReadUInt32()); + pad1 = Shared.Swap(binaryReader.ReadUInt32()); + channel1StartOffset = Shared.Swap(binaryReader.ReadUInt32()); + channel2StartOffset = Shared.Swap(binaryReader.ReadUInt32()); + channel1Start = Shared.Swap(binaryReader.ReadUInt32()); + coefficients1Offset = Shared.Swap(binaryReader.ReadUInt32()); + if (channelCount == 2) { - this.pad2 = Shared.Swap(binaryReader.ReadUInt32()); - this.channel2Start = Shared.Swap(binaryReader.ReadUInt32()); - this.coefficients2Offset = Shared.Swap(binaryReader.ReadUInt32()); - this.pad3 = Shared.Swap(binaryReader.ReadUInt32()); + pad2 = Shared.Swap(binaryReader.ReadUInt32()); + channel2Start = Shared.Swap(binaryReader.ReadUInt32()); + coefficients2Offset = Shared.Swap(binaryReader.ReadUInt32()); + pad3 = Shared.Swap(binaryReader.ReadUInt32()); for (int index = 0; index < 16; ++index) - this.coefficients1[index] = (int) (short) Shared.Swap(binaryReader.ReadUInt16()); - this.channel1Gain = Shared.Swap(binaryReader.ReadUInt16()); - this.channel1PredictiveScale = Shared.Swap(binaryReader.ReadUInt16()); - this.channel1PreviousValue = Shared.Swap(binaryReader.ReadUInt16()); - this.channel1NextPreviousValue = Shared.Swap(binaryReader.ReadUInt16()); - this.channel1LoopPredictiveScale = Shared.Swap(binaryReader.ReadUInt16()); - this.channel1LoopPreviousValue = Shared.Swap(binaryReader.ReadUInt16()); - this.channel1LoopNextPreviousValue = Shared.Swap(binaryReader.ReadUInt16()); - this.channel1LoopPadding = Shared.Swap(binaryReader.ReadUInt16()); + { + coefficients1[index] = (short)Shared.Swap(binaryReader.ReadUInt16()); + } + + channel1Gain = Shared.Swap(binaryReader.ReadUInt16()); + channel1PredictiveScale = Shared.Swap(binaryReader.ReadUInt16()); + channel1PreviousValue = Shared.Swap(binaryReader.ReadUInt16()); + channel1NextPreviousValue = Shared.Swap(binaryReader.ReadUInt16()); + channel1LoopPredictiveScale = Shared.Swap(binaryReader.ReadUInt16()); + channel1LoopPreviousValue = Shared.Swap(binaryReader.ReadUInt16()); + channel1LoopNextPreviousValue = Shared.Swap(binaryReader.ReadUInt16()); + channel1LoopPadding = Shared.Swap(binaryReader.ReadUInt16()); for (int index = 0; index < 16; ++index) - this.coefficients2[index] = (int) (short) Shared.Swap(binaryReader.ReadUInt16()); - this.channel2Gain = Shared.Swap(binaryReader.ReadUInt16()); - this.channel2PredictiveScale = Shared.Swap(binaryReader.ReadUInt16()); - this.channel2PreviousValue = Shared.Swap(binaryReader.ReadUInt16()); - this.channel2NextPreviousValue = Shared.Swap(binaryReader.ReadUInt16()); - this.channel2LoopPredictiveScale = Shared.Swap(binaryReader.ReadUInt16()); - this.channel2LoopPreviousValue = Shared.Swap(binaryReader.ReadUInt16()); - this.channel2LoopNextPreviousValue = Shared.Swap(binaryReader.ReadUInt16()); - this.channel2LoopPadding = Shared.Swap(binaryReader.ReadUInt16()); + { + coefficients2[index] = (short)Shared.Swap(binaryReader.ReadUInt16()); + } + + channel2Gain = Shared.Swap(binaryReader.ReadUInt16()); + channel2PredictiveScale = Shared.Swap(binaryReader.ReadUInt16()); + channel2PreviousValue = Shared.Swap(binaryReader.ReadUInt16()); + channel2NextPreviousValue = Shared.Swap(binaryReader.ReadUInt16()); + channel2LoopPredictiveScale = Shared.Swap(binaryReader.ReadUInt16()); + channel2LoopPreviousValue = Shared.Swap(binaryReader.ReadUInt16()); + channel2LoopNextPreviousValue = Shared.Swap(binaryReader.ReadUInt16()); + channel2LoopPadding = Shared.Swap(binaryReader.ReadUInt16()); } else { - if (this.channelCount != (byte) 1) + if (channelCount != 1) + { return; + } + for (int index = 0; index < 16; ++index) - this.coefficients1[index] = (int) (short) Shared.Swap(binaryReader.ReadUInt16()); - this.channel1Gain = Shared.Swap(binaryReader.ReadUInt16()); - this.channel1PredictiveScale = Shared.Swap(binaryReader.ReadUInt16()); - this.channel1PreviousValue = Shared.Swap(binaryReader.ReadUInt16()); - this.channel1NextPreviousValue = Shared.Swap(binaryReader.ReadUInt16()); - this.channel1LoopPredictiveScale = Shared.Swap(binaryReader.ReadUInt16()); - this.channel1LoopPreviousValue = Shared.Swap(binaryReader.ReadUInt16()); - this.channel1LoopNextPreviousValue = Shared.Swap(binaryReader.ReadUInt16()); - this.channel1LoopPadding = Shared.Swap(binaryReader.ReadUInt16()); + { + coefficients1[index] = (short)Shared.Swap(binaryReader.ReadUInt16()); + } + + channel1Gain = Shared.Swap(binaryReader.ReadUInt16()); + channel1PredictiveScale = Shared.Swap(binaryReader.ReadUInt16()); + channel1PreviousValue = Shared.Swap(binaryReader.ReadUInt16()); + channel1NextPreviousValue = Shared.Swap(binaryReader.ReadUInt16()); + channel1LoopPredictiveScale = Shared.Swap(binaryReader.ReadUInt16()); + channel1LoopPreviousValue = Shared.Swap(binaryReader.ReadUInt16()); + channel1LoopNextPreviousValue = Shared.Swap(binaryReader.ReadUInt16()); + channel1LoopPadding = Shared.Swap(binaryReader.ReadUInt16()); } } } diff --git a/Brlan.cs b/Brlan.cs index 275e280..300b109 100644 --- a/Brlan.cs +++ b/Brlan.cs @@ -24,55 +24,77 @@ namespace libWiiSharp { public class Brlan { - public static string[] GetBrlanTpls(string pathTobrlan) => Brlan.getBrlanTpls(File.ReadAllBytes(pathTobrlan)); + public static string[] GetBrlanTpls(string pathTobrlan) + { + return Brlan.PrivGetBrlanTpls(File.ReadAllBytes(pathTobrlan)); + } - public static string[] GetBrlanTpls(byte[] brlanFile) => Brlan.getBrlanTpls(brlanFile); + public static string[] GetBrlanTpls(byte[] brlanFile) + { + return Brlan.PrivGetBrlanTpls(brlanFile); + } public static string[] GetBrlanTpls(WAD wad, bool banner) { if (!wad.HasBanner) + { return new string[0]; - string str = nameof (banner); + } + + string str = nameof(banner); if (!banner) + { str = "icon"; + } + for (int index1 = 0; index1 < wad.BannerApp.Nodes.Count; ++index1) { if (wad.BannerApp.StringTable[index1].ToLower() == str + ".bin") { - U8 u8 = U8.Load(wad.BannerApp.Data[index1]); - string[] a = new string[0]; - for (int index2 = 0; index2 < u8.Nodes.Count; ++index2) - { - if (u8.StringTable[index2].ToLower() == str + "_start.brlan" || u8.StringTable[index2].ToLower() == str + "_loop.brlan" || u8.StringTable[index2].ToLower() == str + ".brlan") - a = Shared.MergeStringArrays(a, Brlan.getBrlanTpls(u8.Data[index2])); - } - return a; + U8 u8 = U8.Load(wad.BannerApp.Data[index1]); + string[] a = new string[0]; + for (int index2 = 0; index2 < u8.Nodes.Count; ++index2) + { + if (u8.StringTable[index2].ToLower() == str + "_start.brlan" || u8.StringTable[index2].ToLower() == str + "_loop.brlan" || u8.StringTable[index2].ToLower() == str + ".brlan") + { + a = Shared.MergeStringArrays(a, Brlan.GetBrlanTpls(u8.Data[index2])); + } + } + return a; } } - return new string[0]; + return new string[0]; } - private static string[] getBrlanTpls(byte[] brlanFile) + private static string[] PrivGetBrlanTpls(byte[] brlanFile) { List stringList = new List(); - int numOfTpls = Brlan.getNumOfTpls(brlanFile); + int numOfTpls = Brlan.GetNumOfTpls(brlanFile); int index1 = 36 + numOfTpls * 4; for (int index2 = 0; index2 < numOfTpls; ++index2) { string empty = string.Empty; - while (brlanFile[index1] != (byte) 0) + while (brlanFile[index1] != 0) + { empty += Convert.ToChar(brlanFile[index1++]).ToString(); + } + stringList.Add(empty); ++index1; } for (int index2 = stringList.Count - 1; index2 >= 0; --index2) { if (!stringList[index2].ToLower().EndsWith(".tpl")) + { stringList.RemoveAt(index2); + } } return stringList.ToArray(); } - private static int getNumOfTpls(byte[] brlanFile) => (int) Shared.Swap(BitConverter.ToUInt16(brlanFile, 28)); + private static int GetNumOfTpls(byte[] brlanFile) + { + return Shared.Swap(BitConverter.ToUInt16(brlanFile, 28)); + } } } diff --git a/Brlyt.cs b/Brlyt.cs index 631e6b6..7150f35 100644 --- a/Brlyt.cs +++ b/Brlyt.cs @@ -24,17 +24,29 @@ namespace libWiiSharp { public class Brlyt { - public static string[] GetBrlytTpls(string pathToBrlyt) => Brlyt.getBrlytTpls(File.ReadAllBytes(pathToBrlyt)); + public static string[] GetBrlytTpls(string pathToBrlyt) + { + return PrivGetBrlytTpls(File.ReadAllBytes(pathToBrlyt)); + } - public static string[] GetBrlytTpls(byte[] brlytFile) => Brlyt.getBrlytTpls(brlytFile); + public static string[] GetBrlytTpls(byte[] brlytFile) + { + return PrivGetBrlytTpls(brlytFile); + } public static string[] GetBrlytTpls(WAD wad, bool banner) { if (!wad.HasBanner) + { return new string[0]; - string str = nameof (banner); + } + + string str = nameof(banner); if (!banner) + { str = "icon"; + } + for (int index1 = 0; index1 < wad.BannerApp.Nodes.Count; ++index1) { if (wad.BannerApp.StringTable[index1].ToLower() == str + ".bin") @@ -44,7 +56,9 @@ namespace libWiiSharp for (int index2 = 0; index2 < u8.Nodes.Count; ++index2) { if (u8.StringTable[index2].ToLower() == str + ".brlyt") - a = Shared.MergeStringArrays(a, Brlyt.getBrlytTpls(u8.Data[index2])); + { + a = Shared.MergeStringArrays(a, Brlyt.GetBrlytTpls(u8.Data[index2])); + } } return a; } @@ -52,27 +66,35 @@ namespace libWiiSharp return new string[0]; } - private static string[] getBrlytTpls(byte[] brlytFile) + private static string[] PrivGetBrlytTpls(byte[] brlytFile) { List stringList = new List(); - int numOfTpls = Brlyt.getNumOfTpls(brlytFile); + int numOfTpls = Brlyt.GetNumOfTpls(brlytFile); int index1 = 48 + numOfTpls * 8; for (int index2 = 0; index2 < numOfTpls; ++index2) { string empty = string.Empty; - while (brlytFile[index1] != (byte) 0) + while (brlytFile[index1] != 0) + { empty += Convert.ToChar(brlytFile[index1++]).ToString(); + } + stringList.Add(empty); ++index1; } for (int index2 = stringList.Count - 1; index2 >= 0; --index2) { if (!stringList[index2].ToLower().EndsWith(".tpl")) + { stringList.RemoveAt(index2); + } } return stringList.ToArray(); } - private static int getNumOfTpls(byte[] brlytFile) => (int) Shared.Swap(BitConverter.ToUInt16(brlytFile, 44)); + private static int GetNumOfTpls(byte[] brlytFile) + { + return Shared.Swap(BitConverter.ToUInt16(brlytFile, 44)); + } } } diff --git a/CertificateChain.cs b/CertificateChain.cs index 7705afa..9b7ec45 100644 --- a/CertificateChain.cs +++ b/CertificateChain.cs @@ -24,9 +24,9 @@ namespace libWiiSharp { public class CertificateChain : IDisposable { - private const string certCaHash = "5B7D3EE28706AD8DA2CBD5A6B75C15D0F9B6F318"; - private const string certCpHash = "6824D6DA4C25184F0D6DAF6EDB9C0FC57522A41C"; - private const string certXsHash = "09787045037121477824BC6A3E5E076156573F8A"; + //private const string certCaHash = "5B7D3EE28706AD8DA2CBD5A6B75C15D0F9B6F318"; + //private const string certCpHash = "6824D6DA4C25184F0D6DAF6EDB9C0FC57522A41C"; + //private const string certXsHash = "09787045037121477824BC6A3E5E076156573F8A"; private SHA1 sha = SHA1.Create(); private bool[] certsComplete = new bool[3]; private byte[] certCa = new byte[1024]; @@ -34,33 +34,36 @@ namespace libWiiSharp private byte[] certXs = new byte[768]; private bool isDisposed; - public bool CertsComplete => this.certsComplete[0] && this.certsComplete[1] && this.certsComplete[2]; + public bool CertsComplete => certsComplete[0] && certsComplete[1] && certsComplete[2]; public event EventHandler Debug; - ~CertificateChain() => this.Dispose(false); + ~CertificateChain() => Dispose(false); public void Dispose() { - this.Dispose(true); - GC.SuppressFinalize((object) this); + Dispose(true); + GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { - if (disposing && !this.isDisposed) + if (disposing && !isDisposed) { - this.sha.Clear(); - this.sha = (SHA1) null; - this.certsComplete = (bool[]) null; - this.certCa = (byte[]) null; - this.certCp = (byte[]) null; - this.certXs = (byte[]) null; + sha.Clear(); + sha = null; + certsComplete = null; + certCa = null; + certCp = null; + certXs = null; } - this.isDisposed = true; + isDisposed = true; } - public static CertificateChain Load(string pathToCert) => CertificateChain.Load(File.ReadAllBytes(pathToCert)); + public static CertificateChain Load(string pathToCert) + { + return CertificateChain.Load(File.ReadAllBytes(pathToCert)); + } public static CertificateChain Load(byte[] certFile) { @@ -68,7 +71,7 @@ namespace libWiiSharp MemoryStream memoryStream = new MemoryStream(certFile); try { - certificateChain.parseCert((Stream) memoryStream); + certificateChain.ParseCert(memoryStream); } catch { @@ -82,11 +85,14 @@ namespace libWiiSharp public static CertificateChain Load(Stream cert) { CertificateChain certificateChain = new CertificateChain(); - certificateChain.parseCert(cert); + certificateChain.ParseCert(cert); return certificateChain; } - public static CertificateChain FromTikTmd(string pathToTik, string pathToTmd) => CertificateChain.FromTikTmd(File.ReadAllBytes(pathToTik), File.ReadAllBytes(pathToTmd)); + public static CertificateChain FromTikTmd(string pathToTik, string pathToTmd) + { + return CertificateChain.FromTikTmd(File.ReadAllBytes(pathToTik), File.ReadAllBytes(pathToTmd)); + } public static CertificateChain FromTikTmd(byte[] tikFile, byte[] tmdFile) { @@ -94,7 +100,7 @@ namespace libWiiSharp MemoryStream memoryStream1 = new MemoryStream(tikFile); try { - certificateChain.grabFromTik((Stream) memoryStream1); + certificateChain.GrabFromTik(memoryStream1); } catch { @@ -104,7 +110,7 @@ namespace libWiiSharp MemoryStream memoryStream2 = new MemoryStream(tmdFile); try { - certificateChain.grabFromTmd((Stream) memoryStream2); + certificateChain.GrabFromTmd(memoryStream2); } catch { @@ -118,19 +124,22 @@ namespace libWiiSharp public static CertificateChain FromTikTmd(Stream tik, Stream tmd) { CertificateChain certificateChain = new CertificateChain(); - certificateChain.grabFromTik(tik); - certificateChain.grabFromTmd(tmd); + certificateChain.GrabFromTik(tik); + certificateChain.GrabFromTmd(tmd); return certificateChain; } - public void LoadFile(string pathToCert) => this.LoadFile(File.ReadAllBytes(pathToCert)); + public void LoadFile(string pathToCert) + { + LoadFile(File.ReadAllBytes(pathToCert)); + } public void LoadFile(byte[] certFile) { MemoryStream memoryStream = new MemoryStream(certFile); try { - this.parseCert((Stream) memoryStream); + ParseCert(memoryStream); } catch { @@ -140,16 +149,22 @@ namespace libWiiSharp memoryStream.Dispose(); } - public void LoadFile(Stream cert) => this.parseCert(cert); + public void LoadFile(Stream cert) + { + ParseCert(cert); + } - public void LoadFromTikTmd(string pathToTik, string pathToTmd) => this.LoadFromTikTmd(File.ReadAllBytes(pathToTik), File.ReadAllBytes(pathToTmd)); + public void LoadFromTikTmd(string pathToTik, string pathToTmd) + { + LoadFromTikTmd(File.ReadAllBytes(pathToTik), File.ReadAllBytes(pathToTmd)); + } public void LoadFromTikTmd(byte[] tikFile, byte[] tmdFile) { MemoryStream memoryStream1 = new MemoryStream(tikFile); try { - this.grabFromTik((Stream) memoryStream1); + GrabFromTik(memoryStream1); } catch { @@ -159,7 +174,7 @@ namespace libWiiSharp MemoryStream memoryStream2 = new MemoryStream(tmdFile); try { - this.grabFromTmd((Stream) memoryStream2); + GrabFromTmd(memoryStream2); } catch { @@ -167,22 +182,27 @@ namespace libWiiSharp throw; } memoryStream2.Dispose(); - if (!this.CertsComplete) + if (!CertsComplete) + { throw new Exception("Couldn't locate all certs!"); + } } public void LoadFromTikTmd(Stream tik, Stream tmd) { - this.grabFromTik(tik); - this.grabFromTmd(tmd); + GrabFromTik(tik); + GrabFromTmd(tmd); } public void Save(string savePath) { if (File.Exists(savePath)) + { File.Delete(savePath); - using (FileStream fileStream = new FileStream(savePath, FileMode.Create)) - this.writeToStream((Stream) fileStream); + } + + using FileStream fileStream = new FileStream(savePath, FileMode.Create); + WriteToStream(fileStream); } public MemoryStream ToMemoryStream() @@ -190,7 +210,7 @@ namespace libWiiSharp MemoryStream memoryStream = new MemoryStream(); try { - this.writeToStream((Stream) memoryStream); + WriteToStream(memoryStream); return memoryStream; } catch @@ -205,7 +225,7 @@ namespace libWiiSharp MemoryStream memoryStream = new MemoryStream(); try { - this.writeToStream((Stream) memoryStream); + WriteToStream(memoryStream); } catch { @@ -217,73 +237,73 @@ namespace libWiiSharp return array; } - private void writeToStream(Stream writeStream) + private void WriteToStream(Stream writeStream) { - this.fireDebug("Writing Certificate Chain..."); - if (!this.CertsComplete) + FireDebug("Writing Certificate Chain..."); + if (!CertsComplete) { - this.fireDebug(" Certificate Chain incomplete..."); + FireDebug(" Certificate Chain incomplete..."); throw new Exception("At least one certificate is missing!"); } writeStream.Seek(0L, SeekOrigin.Begin); object[] objArray1 = new object[1]; long position = writeStream.Position; - objArray1[0] = (object) position.ToString("x8"); - this.fireDebug(" Writing Certificate CA... (Offset: 0x{0})", objArray1); - writeStream.Write(this.certCa, 0, this.certCa.Length); + objArray1[0] = position.ToString("x8"); + FireDebug(" Writing Certificate CA... (Offset: 0x{0})", objArray1); + writeStream.Write(certCa, 0, certCa.Length); object[] objArray2 = new object[1]; position = writeStream.Position; - objArray2[0] = (object) position.ToString("x8"); - this.fireDebug(" Writing Certificate CP... (Offset: 0x{0})", objArray2); - writeStream.Write(this.certCp, 0, this.certCp.Length); + objArray2[0] = position.ToString("x8"); + FireDebug(" Writing Certificate CP... (Offset: 0x{0})", objArray2); + writeStream.Write(certCp, 0, certCp.Length); object[] objArray3 = new object[1]; position = writeStream.Position; - objArray3[0] = (object) position.ToString("x8"); - this.fireDebug(" Writing Certificate XS... (Offset: 0x{0})", objArray3); - writeStream.Write(this.certXs, 0, this.certXs.Length); - this.fireDebug("Writing Certificate Chain Finished..."); + objArray3[0] = position.ToString("x8"); + FireDebug(" Writing Certificate XS... (Offset: 0x{0})", objArray3); + writeStream.Write(certXs, 0, certXs.Length); + FireDebug("Writing Certificate Chain Finished..."); } - private void parseCert(Stream certFile) + private void ParseCert(Stream certFile) { - this.fireDebug("Parsing Certificate Chain..."); + FireDebug("Parsing Certificate Chain..."); int num = 0; for (int index = 0; index < 3; ++index) { - this.fireDebug(" Scanning at Offset 0x{0}:", (object) num.ToString("x8")); + FireDebug(" Scanning at Offset 0x{0}:", (object)num.ToString("x8")); try { - certFile.Seek((long) num, SeekOrigin.Begin); + certFile.Seek(num, SeekOrigin.Begin); byte[] array = new byte[1024]; certFile.Read(array, 0, array.Length); - this.fireDebug(" Checking for Certificate CA..."); - if (this.isCertCa(array) && !this.certsComplete[1]) + FireDebug(" Checking for Certificate CA..."); + if (IsCertCa(array) && !certsComplete[1]) { - this.fireDebug(" Certificate CA detected..."); - this.certCa = array; - this.certsComplete[1] = true; + FireDebug(" Certificate CA detected..."); + certCa = array; + certsComplete[1] = true; num += 1024; continue; } - this.fireDebug(" Checking for Certificate CP..."); - if (this.isCertCp(array) && !this.certsComplete[2]) + FireDebug(" Checking for Certificate CP..."); + if (IsCertCp(array) && !certsComplete[2]) { - this.fireDebug(" Certificate CP detected..."); + FireDebug(" Certificate CP detected..."); Array.Resize(ref array, 768); - this.certCp = array; - this.certsComplete[2] = true; + certCp = array; + certsComplete[2] = true; num += 768; continue; } - this.fireDebug(" Checking for Certificate XS..."); - if (this.isCertXs(array)) + FireDebug(" Checking for Certificate XS..."); + if (IsCertXs(array)) { - if (!this.certsComplete[0]) + if (!certsComplete[0]) { - this.fireDebug(" Certificate XS detected..."); + FireDebug(" Certificate XS detected..."); Array.Resize(ref array, 768); - this.certXs = array; - this.certsComplete[0] = true; + certXs = array; + certsComplete[0] = true; num += 768; continue; } @@ -291,58 +311,58 @@ namespace libWiiSharp } catch (Exception ex) { - this.fireDebug("Error: {0}", (object) ex.Message); + FireDebug("Error: {0}", (object)ex.Message); } - num += 768; + num += 768; } - if (!this.CertsComplete) + if (!CertsComplete) { - this.fireDebug(" Couldn't locate all Certificates..."); + FireDebug(" Couldn't locate all Certificates..."); throw new Exception("Couldn't locate all certs!"); } - this.fireDebug("Parsing Certificate Chain Finished..."); + FireDebug("Parsing Certificate Chain Finished..."); } - private void grabFromTik(Stream tik) + private void GrabFromTik(Stream tik) { - this.fireDebug("Scanning Ticket for Certificates..."); + FireDebug("Scanning Ticket for Certificates..."); int num = 676; for (int index = 0; index < 3; ++index) { - this.fireDebug(" Scanning at Offset 0x{0}:", (object) num.ToString("x8")); + FireDebug(" Scanning at Offset 0x{0}:", (object)num.ToString("x8")); try { - tik.Seek((long) num, SeekOrigin.Begin); + tik.Seek(num, SeekOrigin.Begin); byte[] array = new byte[1024]; tik.Read(array, 0, array.Length); - this.fireDebug(" Checking for Certificate CA..."); - if (this.isCertCa(array) && !this.certsComplete[1]) + FireDebug(" Checking for Certificate CA..."); + if (IsCertCa(array) && !certsComplete[1]) { - this.fireDebug(" Certificate CA detected..."); - this.certCa = array; - this.certsComplete[1] = true; + FireDebug(" Certificate CA detected..."); + certCa = array; + certsComplete[1] = true; num += 1024; continue; } - this.fireDebug(" Checking for Certificate CP..."); - if (this.isCertCp(array) && !this.certsComplete[2]) + FireDebug(" Checking for Certificate CP..."); + if (IsCertCp(array) && !certsComplete[2]) { - this.fireDebug(" Certificate CP detected..."); + FireDebug(" Certificate CP detected..."); Array.Resize(ref array, 768); - this.certCp = array; - this.certsComplete[2] = true; + certCp = array; + certsComplete[2] = true; num += 768; continue; } - this.fireDebug(" Checking for Certificate XS..."); - if (this.isCertXs(array)) + FireDebug(" Checking for Certificate XS..."); + if (IsCertXs(array)) { - if (!this.certsComplete[0]) + if (!certsComplete[0]) { - this.fireDebug(" Certificate XS detected..."); + FireDebug(" Certificate XS detected..."); Array.Resize(ref array, 768); - this.certXs = array; - this.certsComplete[0] = true; + certXs = array; + certsComplete[0] = true; num += 768; continue; } @@ -353,52 +373,52 @@ namespace libWiiSharp } num += 768; } - this.fireDebug("Scanning Ticket for Certificates Finished..."); + FireDebug("Scanning Ticket for Certificates Finished..."); } - private void grabFromTmd(Stream tmd) + private void GrabFromTmd(Stream tmd) { - this.fireDebug("Scanning TMD for Certificates..."); + FireDebug("Scanning TMD for Certificates..."); byte[] buffer = new byte[2]; tmd.Seek(478L, SeekOrigin.Begin); tmd.Read(buffer, 0, 2); - int num = 484 + (int) Shared.Swap(BitConverter.ToUInt16(buffer, 0)) * 36; + int num = 484 + Shared.Swap(BitConverter.ToUInt16(buffer, 0)) * 36; for (int index = 0; index < 3; ++index) { - this.fireDebug(" Scanning at Offset 0x{0}:", (object) num.ToString("x8")); + FireDebug(" Scanning at Offset 0x{0}:", (object)num.ToString("x8")); try { - tmd.Seek((long) num, SeekOrigin.Begin); + tmd.Seek(num, SeekOrigin.Begin); byte[] array = new byte[1024]; tmd.Read(array, 0, array.Length); - this.fireDebug(" Checking for Certificate CA..."); - if (this.isCertCa(array) && !this.certsComplete[1]) + FireDebug(" Checking for Certificate CA..."); + if (IsCertCa(array) && !certsComplete[1]) { - this.fireDebug(" Certificate CA detected..."); - this.certCa = array; - this.certsComplete[1] = true; + FireDebug(" Certificate CA detected..."); + certCa = array; + certsComplete[1] = true; num += 1024; continue; } - this.fireDebug(" Checking for Certificate CP..."); - if (this.isCertCp(array) && !this.certsComplete[2]) + FireDebug(" Checking for Certificate CP..."); + if (IsCertCp(array) && !certsComplete[2]) { - this.fireDebug(" Certificate CP detected..."); + FireDebug(" Certificate CP detected..."); Array.Resize(ref array, 768); - this.certCp = array; - this.certsComplete[2] = true; + certCp = array; + certsComplete[2] = true; num += 768; continue; } - this.fireDebug(" Checking for Certificate XS..."); - if (this.isCertXs(array)) + FireDebug(" Checking for Certificate XS..."); + if (IsCertXs(array)) { - if (!this.certsComplete[0]) + if (!certsComplete[0]) { - this.fireDebug(" Certificate XS detected..."); + FireDebug(" Certificate XS detected..."); Array.Resize(ref array, 768); - this.certXs = array; - this.certsComplete[0] = true; + certXs = array; + certsComplete[0] = true; num += 768; continue; } @@ -409,41 +429,62 @@ namespace libWiiSharp } num += 768; } - this.fireDebug("Scanning TMD for Certificates Finished..."); + FireDebug("Scanning TMD for Certificates Finished..."); } - private bool isCertXs(byte[] part) + private bool IsCertXs(byte[] part) { if (part.Length < 768) + { return false; + } + if (part.Length > 768) + { Array.Resize(ref part, 768); - return part[388] == (byte) 88 && part[389] == (byte) 83 && Shared.CompareByteArrays(this.sha.ComputeHash(part), Shared.HexStringToByteArray("09787045037121477824BC6A3E5E076156573F8A")); + } + + return part[388] == 88 && part[389] == 83 && Shared.CompareByteArrays(sha.ComputeHash(part), Shared.HexStringToByteArray("09787045037121477824BC6A3E5E076156573F8A")); } - private bool isCertCa(byte[] part) + private bool IsCertCa(byte[] part) { if (part.Length < 1024) + { return false; + } + if (part.Length > 1024) + { Array.Resize(ref part, 1024); - return part[644] == (byte) 67 && part[645] == (byte) 65 && Shared.CompareByteArrays(this.sha.ComputeHash(part), Shared.HexStringToByteArray("5B7D3EE28706AD8DA2CBD5A6B75C15D0F9B6F318")); + } + + return part[644] == 67 && part[645] == 65 && Shared.CompareByteArrays(sha.ComputeHash(part), Shared.HexStringToByteArray("5B7D3EE28706AD8DA2CBD5A6B75C15D0F9B6F318")); } - private bool isCertCp(byte[] part) + private bool IsCertCp(byte[] part) { if (part.Length < 768) + { return false; + } + if (part.Length > 768) + { Array.Resize(ref part, 768); - return part[388] == (byte) 67 && part[389] == (byte) 80 && Shared.CompareByteArrays(this.sha.ComputeHash(part), Shared.HexStringToByteArray("6824D6DA4C25184F0D6DAF6EDB9C0FC57522A41C")); + } + + return part[388] == 67 && part[389] == 80 && Shared.CompareByteArrays(sha.ComputeHash(part), Shared.HexStringToByteArray("6824D6DA4C25184F0D6DAF6EDB9C0FC57522A41C")); } - private void fireDebug(string debugMessage, params object[] args) + private void FireDebug(string debugMessage, params object[] args) { - EventHandler debug = this.Debug; + EventHandler debug = Debug; if (debug == null) + { return; + } + debug(new object(), new MessageEventArgs(string.Format(debugMessage, args))); } } diff --git a/ColorIndexConverter.cs b/ColorIndexConverter.cs index fefb44d..33f4929 100644 --- a/ColorIndexConverter.cs +++ b/ColorIndexConverter.cs @@ -25,16 +25,16 @@ namespace libWiiSharp { private uint[] rgbaPalette; private byte[] tplPalette; - private uint[] rgbaData; + private readonly uint[] rgbaData; private byte[] tplData; - private TPL_TextureFormat tplFormat; - private TPL_PaletteFormat paletteFormat; - private int width; - private int height; + private readonly TPL_TextureFormat tplFormat; + private readonly TPL_PaletteFormat paletteFormat; + private readonly int width; + private readonly int height; - public byte[] Palette => this.tplPalette; + public byte[] Palette => tplPalette; - public byte[] Data => this.tplData; + public byte[] Data => tplData; public ColorIndexConverter( uint[] rgbaData, @@ -44,118 +44,135 @@ namespace libWiiSharp TPL_PaletteFormat paletteFormat) { if (tplFormat != TPL_TextureFormat.CI4 && tplFormat != TPL_TextureFormat.CI8) + { throw new Exception("Texture format must be either CI4 or CI8"); + } + if (paletteFormat != TPL_PaletteFormat.IA8 && paletteFormat != TPL_PaletteFormat.RGB565 && paletteFormat != TPL_PaletteFormat.RGB5A3) + { throw new Exception("Palette format must be either IA8, RGB565 or RGB5A3!"); + } + this.rgbaData = rgbaData; this.width = width; this.height = height; this.tplFormat = tplFormat; this.paletteFormat = paletteFormat; - this.buildPalette(); + BuildPalette(); if (tplFormat != TPL_TextureFormat.CI4) { if (tplFormat == TPL_TextureFormat.CI8) - this.toCI8(); + { + ToCI8(); + } else - this.toCI14X2(); + { + ToCI14X2(); + } } else - this.toCI4(); + { + ToCI4(); + } } - private void toCI4() + private void ToCI4() { - byte[] numArray = new byte[Shared.AddPadding(this.width, 8) * Shared.AddPadding(this.height, 8) / 2]; + byte[] numArray = new byte[Shared.AddPadding(width, 8) * Shared.AddPadding(height, 8) / 2]; int num = 0; - for (int index1 = 0; index1 < this.height; index1 += 8) + for (int index1 = 0; index1 < height; index1 += 8) { - for (int index2 = 0; index2 < this.width; index2 += 8) + for (int index2 = 0; index2 < width; index2 += 8) { for (int index3 = index1; index3 < index1 + 8; ++index3) { for (int index4 = index2; index4 < index2 + 8; index4 += 2) { - uint colorIndex1 = this.getColorIndex(index3 >= this.height || index4 >= this.width ? 0U : this.rgbaData[index3 * this.width + index4]); - uint colorIndex2 = this.getColorIndex(index3 >= this.height || index4 >= this.width ? 0U : (index3 * this.width + index4 + 1 < this.rgbaData.Length ? this.rgbaData[index3 * this.width + index4 + 1] : 0U)); - numArray[num++] = (byte) ((uint) (byte) colorIndex1 << 4 | (uint) (byte) colorIndex2); + uint colorIndex1 = GetColorIndex(index3 >= height || index4 >= width ? 0U : rgbaData[index3 * width + index4]); + uint colorIndex2 = GetColorIndex(index3 >= height || index4 >= width ? 0U : (index3 * width + index4 + 1 < rgbaData.Length ? rgbaData[index3 * width + index4 + 1] : 0U)); + numArray[num++] = (byte)((uint)(byte)colorIndex1 << 4 | (byte)colorIndex2); } } } } - this.tplData = numArray; + tplData = numArray; } - private void toCI8() + private void ToCI8() { - byte[] numArray = new byte[Shared.AddPadding(this.width, 8) * Shared.AddPadding(this.height, 4)]; + byte[] numArray = new byte[Shared.AddPadding(width, 8) * Shared.AddPadding(height, 4)]; int num1 = 0; - for (int index1 = 0; index1 < this.height; index1 += 4) + for (int index1 = 0; index1 < height; index1 += 4) { - for (int index2 = 0; index2 < this.width; index2 += 8) + for (int index2 = 0; index2 < width; index2 += 8) { for (int index3 = index1; index3 < index1 + 4; ++index3) { for (int index4 = index2; index4 < index2 + 8; ++index4) { - uint num2 = index3 >= this.height || index4 >= this.width ? 0U : this.rgbaData[index3 * this.width + index4]; - numArray[num1++] = (byte) this.getColorIndex(num2); + uint num2 = index3 >= height || index4 >= width ? 0U : rgbaData[index3 * width + index4]; + numArray[num1++] = (byte)GetColorIndex(num2); } } } } - this.tplData = numArray; + tplData = numArray; } - private void toCI14X2() + private void ToCI14X2() { - byte[] numArray1 = new byte[Shared.AddPadding(this.width, 4) * Shared.AddPadding(this.height, 4) * 2]; + byte[] numArray1 = new byte[Shared.AddPadding(width, 4) * Shared.AddPadding(height, 4) * 2]; int num1 = 0; - for (int index1 = 0; index1 < this.height; index1 += 4) + for (int index1 = 0; index1 < height; index1 += 4) { - for (int index2 = 0; index2 < this.width; index2 += 4) + for (int index2 = 0; index2 < width; index2 += 4) { for (int index3 = index1; index3 < index1 + 4; ++index3) { for (int index4 = index2; index4 < index2 + 4; ++index4) { - byte[] bytes = BitConverter.GetBytes((ushort) this.getColorIndex(index3 >= this.height || index4 >= this.width ? 0U : this.rgbaData[index3 * this.width + index4])); + byte[] bytes = BitConverter.GetBytes((ushort)GetColorIndex(index3 >= height || index4 >= width ? 0U : rgbaData[index3 * width + index4])); byte[] numArray2 = numArray1; int index5 = num1; int num2 = index5 + 1; - int num3 = (int) bytes[1]; - numArray2[index5] = (byte) num3; + int num3 = bytes[1]; + numArray2[index5] = (byte)num3; byte[] numArray3 = numArray1; int index6 = num2; num1 = index6 + 1; - int num4 = (int) bytes[0]; - numArray3[index6] = (byte) num4; + int num4 = bytes[0]; + numArray3[index6] = (byte)num4; } } } } - this.tplData = numArray1; + tplData = numArray1; } - private void buildPalette() + private void BuildPalette() { int num1 = 256; - if (this.tplFormat == TPL_TextureFormat.CI4) + if (tplFormat == TPL_TextureFormat.CI4) + { num1 = 16; - else if (this.tplFormat == TPL_TextureFormat.CI14X2) + } + else if (tplFormat == TPL_TextureFormat.CI14X2) + { num1 = 16384; + } + List uintList = new List(); List ushortList = new List(); uintList.Add(0U); - ushortList.Add((ushort) 0); - for (int index = 1; index < this.rgbaData.Length && uintList.Count != num1; ++index) + ushortList.Add(0); + for (int index = 1; index < rgbaData.Length && uintList.Count != num1; ++index) { - if ((long) (this.rgbaData[index] >> 24 & (uint) byte.MaxValue) >= (this.tplFormat == TPL_TextureFormat.CI14X2 ? 1L : 25L)) + if ((rgbaData[index] >> 24 & byte.MaxValue) >= (tplFormat == TPL_TextureFormat.CI14X2 ? 1L : 25L)) { - ushort num2 = Shared.Swap(this.convertToPaletteValue((int) this.rgbaData[index])); - if (!uintList.Contains(this.rgbaData[index]) && !ushortList.Contains(num2)) + ushort num2 = Shared.Swap(ConvertToPaletteValue((int)rgbaData[index])); + if (!uintList.Contains(rgbaData[index]) && !ushortList.Contains(num2)) { - uintList.Add(this.rgbaData[index]); + uintList.Add(rgbaData[index]); ushortList.Add(num2); } } @@ -165,127 +182,133 @@ namespace libWiiSharp uintList.Add(uint.MaxValue); ushortList.Add(ushort.MaxValue); } - this.tplPalette = Shared.UShortArrayToByteArray(ushortList.ToArray()); - this.rgbaPalette = uintList.ToArray(); + tplPalette = Shared.UShortArrayToByteArray(ushortList.ToArray()); + rgbaPalette = uintList.ToArray(); } - private ushort convertToPaletteValue(int rgba) + private ushort ConvertToPaletteValue(int rgba) { int num1 = 0; int num2; - if (this.paletteFormat == TPL_PaletteFormat.IA8) + if (paletteFormat == TPL_PaletteFormat.IA8) { - int num3 = ((rgba & (int) byte.MaxValue) + (rgba >> 8 & (int) byte.MaxValue) + (rgba >> 16 & (int) byte.MaxValue)) / 3 & (int) byte.MaxValue; - num2 = (int) (ushort) ((rgba >> 24 & (int) byte.MaxValue) << 8 | num3); + int num3 = ((rgba & byte.MaxValue) + (rgba >> 8 & byte.MaxValue) + (rgba >> 16 & byte.MaxValue)) / 3 & byte.MaxValue; + num2 = (ushort)((rgba >> 24 & byte.MaxValue) << 8 | num3); } - else if (this.paletteFormat == TPL_PaletteFormat.RGB565) + else if (paletteFormat == TPL_PaletteFormat.RGB565) { - num2 = (int) (ushort) ((rgba >> 16 & (int) byte.MaxValue) >> 3 << 11 | (rgba >> 8 & (int) byte.MaxValue) >> 2 << 5 | (rgba & (int) byte.MaxValue) >> 3); + num2 = (ushort)((rgba >> 16 & byte.MaxValue) >> 3 << 11 | (rgba >> 8 & byte.MaxValue) >> 2 << 5 | (rgba & byte.MaxValue) >> 3); } else { - int num3 = rgba >> 16 & (int) byte.MaxValue; - int num4 = rgba >> 8 & (int) byte.MaxValue; - int num5 = rgba & (int) byte.MaxValue; - int num6 = rgba >> 24 & (int) byte.MaxValue; + int num3 = rgba >> 16 & byte.MaxValue; + int num4 = rgba >> 8 & byte.MaxValue; + int num5 = rgba & byte.MaxValue; + int num6 = rgba >> 24 & byte.MaxValue; if (num6 <= 218) { int num7 = num1 & -32769; - int num8 = num3 * 15 / (int) byte.MaxValue & 15; - int num9 = num4 * 15 / (int) byte.MaxValue & 15; - int num10 = num5 * 15 / (int) byte.MaxValue & 15; - int num11 = num6 * 7 / (int) byte.MaxValue & 7; + int num8 = num3 * 15 / byte.MaxValue & 15; + int num9 = num4 * 15 / byte.MaxValue & 15; + int num10 = num5 * 15 / byte.MaxValue & 15; + int num11 = num6 * 7 / byte.MaxValue & 7; num2 = num7 | num11 << 12 | num10 | num9 << 4 | num8 << 8; } else { int num7 = num1 | 32768; - int num8 = num3 * 31 / (int) byte.MaxValue & 31; - int num9 = num4 * 31 / (int) byte.MaxValue & 31; - int num10 = num5 * 31 / (int) byte.MaxValue & 31; + int num8 = num3 * 31 / byte.MaxValue & 31; + int num9 = num4 * 31 / byte.MaxValue & 31; + int num10 = num5 * 31 / byte.MaxValue & 31; num2 = num7 | num10 | num9 << 5 | num8 << 10; } } - return (ushort) num2; + return (ushort)num2; } - private uint getColorIndex(uint value) + private uint GetColorIndex(uint value) { - uint num1 = (uint) int.MaxValue; + uint num1 = int.MaxValue; uint num2 = 0; - if ((long) (value >> 24 & (uint) byte.MaxValue) < (this.tplFormat == TPL_TextureFormat.CI14X2 ? 1L : 25L)) - return 0; - ushort paletteValue1 = this.convertToPaletteValue((int) value); - for (int index = 0; index < this.rgbaPalette.Length; ++index) + if ((value >> 24 & byte.MaxValue) < (tplFormat == TPL_TextureFormat.CI14X2 ? 1L : 25L)) { - ushort paletteValue2 = this.convertToPaletteValue((int) this.rgbaPalette[index]); - if ((int) paletteValue1 == (int) paletteValue2) - return (uint) index; - uint distance = this.getDistance(paletteValue1, paletteValue2); + return 0; + } + + ushort paletteValue1 = ConvertToPaletteValue((int)value); + for (int index = 0; index < rgbaPalette.Length; ++index) + { + ushort paletteValue2 = ConvertToPaletteValue((int)rgbaPalette[index]); + if (paletteValue1 == paletteValue2) + { + return (uint)index; + } + + uint distance = GetDistance(paletteValue1, paletteValue2); if (distance < num1) { num1 = distance; - num2 = (uint) index; + num2 = (uint)index; } } - return num2; + return num2; } - private uint getDistance(ushort color, ushort paletteColor) + private uint GetDistance(ushort color, ushort paletteColor) { - int rgbaValue1 = (int) this.convertToRgbaValue(color); - uint rgbaValue2 = this.convertToRgbaValue(paletteColor); - uint val1_1 = (uint) rgbaValue1 >> 24 & (uint) byte.MaxValue; - uint val1_2 = (uint) rgbaValue1 >> 16 & (uint) byte.MaxValue; - uint val1_3 = (uint) rgbaValue1 >> 8 & (uint) byte.MaxValue; - uint val1_4 = (uint) (rgbaValue1 & (int) byte.MaxValue); - uint val2_1 = rgbaValue2 >> 24 & (uint) byte.MaxValue; - uint val2_2 = rgbaValue2 >> 16 & (uint) byte.MaxValue; - uint val2_3 = rgbaValue2 >> 8 & (uint) byte.MaxValue; - uint val2_4 = rgbaValue2 & (uint) byte.MaxValue; - int num1 = (int) Math.Max(val1_1, val2_1) - (int) Math.Min(val1_1, val2_1); + int rgbaValue1 = (int)ConvertToRgbaValue(color); + uint rgbaValue2 = ConvertToRgbaValue(paletteColor); + uint val1_1 = (uint)rgbaValue1 >> 24 & byte.MaxValue; + uint val1_2 = (uint)rgbaValue1 >> 16 & byte.MaxValue; + uint val1_3 = (uint)rgbaValue1 >> 8 & byte.MaxValue; + uint val1_4 = (uint)(rgbaValue1 & byte.MaxValue); + uint val2_1 = rgbaValue2 >> 24 & byte.MaxValue; + uint val2_2 = rgbaValue2 >> 16 & byte.MaxValue; + uint val2_3 = rgbaValue2 >> 8 & byte.MaxValue; + uint val2_4 = rgbaValue2 & byte.MaxValue; + int num1 = (int)Math.Max(val1_1, val2_1) - (int)Math.Min(val1_1, val2_1); uint num2 = Math.Max(val1_2, val2_2) - Math.Min(val1_2, val2_2); uint num3 = Math.Max(val1_3, val2_3) - Math.Min(val1_3, val2_3); uint num4 = Math.Max(val1_4, val2_4) - Math.Min(val1_4, val2_4); - int num5 = (int) num2; - return (uint) (num1 + num5) + num3 + num4; + int num5 = (int)num2; + return (uint)(num1 + num5) + num3 + num4; } - private uint convertToRgbaValue(ushort pixel) + private uint ConvertToRgbaValue(ushort pixel) { - if (this.paletteFormat == TPL_PaletteFormat.IA8) + if (paletteFormat == TPL_PaletteFormat.IA8) { - int num1 = (int) pixel >> 8; - int num2 = (int) pixel & (int) byte.MaxValue; - return (uint) (num1 | num1 << 8 | num1 << 16 | num2 << 24); + int num1 = pixel >> 8; + int num2 = pixel & byte.MaxValue; + return (uint)(num1 | num1 << 8 | num1 << 16 | num2 << 24); } - if (this.paletteFormat == TPL_PaletteFormat.RGB565) + if (paletteFormat == TPL_PaletteFormat.RGB565) { - int num1 = ((int) pixel >> 11 & 31) << 3 & (int) byte.MaxValue; - int num2 = ((int) pixel >> 5 & 63) << 2 & (int) byte.MaxValue; - int num3 = ((int) pixel & 31) << 3 & (int) byte.MaxValue; - int maxValue = (int) byte.MaxValue; - return (uint) (num3 | num2 << 8 | num1 << 16 | maxValue << 24); + int num1 = (pixel >> 11 & 31) << 3 & byte.MaxValue; + int num2 = (pixel >> 5 & 63) << 2 & byte.MaxValue; + int num3 = (pixel & 31) << 3 & byte.MaxValue; + int maxValue = byte.MaxValue; + return (uint)(num3 | num2 << 8 | num1 << 16 | maxValue << 24); } int num4; int num5; int num6; int num7; - if (((int) pixel & 32768) != 0) + if ((pixel & 32768) != 0) { - num4 = ((int) pixel >> 10 & 31) * (int) byte.MaxValue / 31; - num5 = ((int) pixel >> 5 & 31) * (int) byte.MaxValue / 31; - num6 = ((int) pixel & 31) * (int) byte.MaxValue / 31; - num7 = (int) byte.MaxValue; + num4 = (pixel >> 10 & 31) * byte.MaxValue / 31; + num5 = (pixel >> 5 & 31) * byte.MaxValue / 31; + num6 = (pixel & 31) * byte.MaxValue / 31; + num7 = byte.MaxValue; } else { - num7 = ((int) pixel >> 12 & 7) * (int) byte.MaxValue / 7; - num4 = ((int) pixel >> 8 & 15) * (int) byte.MaxValue / 15; - num5 = ((int) pixel >> 4 & 15) * (int) byte.MaxValue / 15; - num6 = ((int) pixel & 15) * (int) byte.MaxValue / 15; + num7 = (pixel >> 12 & 7) * byte.MaxValue / 7; + num4 = (pixel >> 8 & 15) * byte.MaxValue / 15; + num5 = (pixel >> 4 & 15) * byte.MaxValue / 15; + num6 = (pixel & 15) * byte.MaxValue / 15; } - return (uint) (num6 | num5 << 8 | num4 << 16 | num7 << 24); + return (uint)(num6 | num5 << 8 | num4 << 16 | num7 << 24); } } } diff --git a/CommonKey.cs b/CommonKey.cs index 573f34b..4a19edd 100644 --- a/CommonKey.cs +++ b/CommonKey.cs @@ -20,11 +20,17 @@ namespace libWiiSharp { public class CommonKey { - private static string standardKey = "ebe42a225e8593e448d9c5457381aaf7"; - private static string koreanKey = "63b82bb4f4614e2e13f2fefbba4c9b7e"; + private static readonly string standardKey = "ebe42a225e8593e448d9c5457381aaf7"; + private static readonly string koreanKey = "63b82bb4f4614e2e13f2fefbba4c9b7e"; - public static byte[] GetStandardKey() => Shared.HexStringToByteArray(CommonKey.standardKey); + public static byte[] GetStandardKey() + { + return Shared.HexStringToByteArray(CommonKey.standardKey); + } - public static byte[] GetKoreanKey() => Shared.HexStringToByteArray(CommonKey.koreanKey); + public static byte[] GetKoreanKey() + { + return Shared.HexStringToByteArray(CommonKey.koreanKey); + } } } diff --git a/ContentIndices.cs b/ContentIndices.cs index 4750e57..7d8d9f9 100644 --- a/ContentIndices.cs +++ b/ContentIndices.cs @@ -20,26 +20,29 @@ using System; namespace libWiiSharp { - public struct ContentIndices : IComparable - { - private int index; - private int contentIndex; - - public int Index => this.index; - - public int ContentIndex => this.contentIndex; - - public ContentIndices(int index, int contentIndex) + public struct ContentIndices : IComparable { - this.index = index; - this.contentIndex = contentIndex; - } + private readonly int index; + private readonly int contentIndex; - public int CompareTo(object obj) - { - if (obj is ContentIndices contentIndices) - return this.contentIndex.CompareTo(contentIndices.contentIndex); - throw new ArgumentException(); + public int Index => index; + + public int ContentIndex => contentIndex; + + public ContentIndices(int index, int contentIndex) + { + this.index = index; + this.contentIndex = contentIndex; + } + + public int CompareTo(object obj) + { + if (obj is ContentIndices contentIndices) + { + return contentIndex.CompareTo(contentIndices.contentIndex); + } + + throw new ArgumentException(); + } } - } } diff --git a/HbcTransmitter.cs b/HbcTransmitter.cs index 5a634b9..5cc51ad 100644 --- a/HbcTransmitter.cs +++ b/HbcTransmitter.cs @@ -52,8 +52,8 @@ namespace libWiiSharp private bool compress; private string ipAddress; private int port = 4299; - private string lastErrorMessage = string.Empty; - private Protocol protocol; + //private string lastErrorMessage = string.Empty; + private readonly Protocol protocol; private TcpClient tcpClient; private NetworkStream nwStream; private string lastError = string.Empty; @@ -67,8 +67,8 @@ namespace libWiiSharp /// public int Blocksize { - get => this.blocksize; - set => this.blocksize = value; + get => blocksize; + set => blocksize = value; } /// @@ -76,8 +76,8 @@ namespace libWiiSharp /// public int WiiloadVersionMayor { - get => this.wiiloadMayor; - set => this.wiiloadMayor = value; + get => wiiloadMayor; + set => wiiloadMayor = value; } /// @@ -85,8 +85,8 @@ namespace libWiiSharp /// public int WiiloadVersionMinor { - get => this.wiiloadMinor; - set => this.wiiloadMinor = value; + get => wiiloadMinor; + set => wiiloadMinor = value; } /// @@ -95,12 +95,15 @@ namespace libWiiSharp /// public bool Compress { - get => this.compress; + get => compress; set { - if (this.protocol == Protocol.HAXX) + if (protocol == Protocol.HAXX) + { return; - this.compress = value; + } + + compress = value; } } @@ -109,8 +112,8 @@ namespace libWiiSharp /// public string IpAddress { - get => this.ipAddress; - set => this.ipAddress = value; + get => ipAddress; + set => ipAddress = value; } /// The port used for the transmission. @@ -118,141 +121,153 @@ namespace libWiiSharp /// public int Port { - get => this.port; - set => this.port = value; + get => port; + set => port = value; } /// /// After a successfully completed transmission, this value holds the number of transmitted bytes. /// - public int TransmittedLength => this.transmittedLength; + public int TransmittedLength => transmittedLength; /// /// After a successfully completed transmission, this value holds the compression ratio. /// Will be 0 if the data wasn't compressed. /// - public int CompressionRatio => this.compressionRatio; + public int CompressionRatio => compressionRatio; /// /// Holds the last occured error message. /// - public string LastError => this.lastError; + public string LastError => lastError; public HbcTransmitter(Protocol protocol, string ipAddress) { this.protocol = protocol; this.ipAddress = ipAddress; - this.wiiloadMinor = protocol == Protocol.HAXX ? 4 : 5; - this.compress = protocol == Protocol.JODI; + wiiloadMinor = protocol == Protocol.HAXX ? 4 : 5; + compress = protocol == Protocol.JODI; } #region IDisposable Members - ~HbcTransmitter() => this.Dispose(false); + ~HbcTransmitter() => Dispose(false); public void Dispose() { - this.Dispose(true); - GC.SuppressFinalize((object) this); + Dispose(true); + GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { - if (disposing && !this.isDisposed) + if (disposing && !isDisposed) { - this.ipAddress = (string) null; - this.lastErrorMessage = (string) null; - this.lastError = (string) null; - if (this.nwStream != null) + ipAddress = null; + //this.lastErrorMessage = (string)null; + lastError = null; + if (nwStream != null) { - this.nwStream.Close(); - this.nwStream = (NetworkStream) null; + nwStream.Close(); + nwStream = null; } - if (this.tcpClient != null) + if (tcpClient != null) { - this.tcpClient.Close(); - this.tcpClient = (TcpClient) null; + tcpClient.Close(); + tcpClient = null; } } - this.isDisposed = true; + isDisposed = true; } #endregion #region Public Functions - public bool TransmitFile(string pathToFile) => this.transmit(Path.GetFileName(pathToFile), File.ReadAllBytes(pathToFile)); + public bool TransmitFile(string pathToFile) + { + return Transmit(Path.GetFileName(pathToFile), File.ReadAllBytes(pathToFile)); + } - public bool TransmitFile(string fileName, byte[] fileData) => this.transmit(fileName, fileData); + public bool TransmitFile(string fileName, byte[] fileData) + { + return Transmit(fileName, fileData); + } #endregion #region Private Functions - private bool transmit(string fileName, byte[] fileData) + private bool Transmit(string fileName, byte[] fileData) { - this.fireDebug("Transmitting {0} to {1}:{2}...", (object) fileName, (object) this.ipAddress, (object) this.port); + FireDebug("Transmitting {0} to {1}:{2}...", fileName, ipAddress, port); if (!Environment.OSVersion.ToString().ToLower().Contains("windows")) - this.compress = false; + { + compress = false; + } + if (fileName.ToLower().EndsWith(".zip")) - this.compress = false; - this.tcpClient = new TcpClient(); + { + compress = false; + } + + tcpClient = new TcpClient(); byte[] buffer1 = new byte[4]; - this.fireDebug(" Connecting..."); + FireDebug(" Connecting..."); try { - this.tcpClient.Connect(this.ipAddress, 4299); + tcpClient.Connect(ipAddress, 4299); } catch (Exception ex) { - this.fireDebug(" -> Connection Failed:\n" + ex.Message); - this.lastError = "Connection Failed:\n" + ex.Message; - this.tcpClient.Close(); + FireDebug(" -> Connection Failed:\n" + ex.Message); + lastError = "Connection Failed:\n" + ex.Message; + tcpClient.Close(); return false; } - this.nwStream = this.tcpClient.GetStream(); - this.fireDebug(" Sending Magic..."); - buffer1[0] = (byte) 72; - buffer1[1] = (byte) 65; - buffer1[2] = (byte) 88; - buffer1[3] = (byte) 88; + nwStream = tcpClient.GetStream(); + FireDebug(" Sending Magic..."); + buffer1[0] = 72; + buffer1[1] = 65; + buffer1[2] = 88; + buffer1[3] = 88; try { - this.nwStream.Write(buffer1, 0, 4); + nwStream.Write(buffer1, 0, 4); } catch (Exception ex) { - this.fireDebug(" -> Error sending Magic:\n" + ex.Message); - this.lastError = "Error sending Magic:\n" + ex.Message; - this.nwStream.Close(); - this.tcpClient.Close(); + FireDebug(" -> Error sending Magic:\n" + ex.Message); + lastError = "Error sending Magic:\n" + ex.Message; + nwStream.Close(); + tcpClient.Close(); return false; } - this.fireDebug(" Sending Version Info..."); - buffer1[0] = (byte) this.wiiloadMayor; - buffer1[1] = (byte) this.wiiloadMinor; - buffer1[2] = (byte) (fileName.Length + 2 >> 8 & (int) byte.MaxValue); - buffer1[3] = (byte) (fileName.Length + 2 & (int) byte.MaxValue); + FireDebug(" Sending Version Info..."); + buffer1[0] = (byte)wiiloadMayor; + buffer1[1] = (byte)wiiloadMinor; + buffer1[2] = (byte)(fileName.Length + 2 >> 8 & byte.MaxValue); + buffer1[3] = (byte)(fileName.Length + 2 & byte.MaxValue); try { - this.nwStream.Write(buffer1, 0, 4); + nwStream.Write(buffer1, 0, 4); } catch (Exception ex) { - this.fireDebug(" -> Error sending Version Info:\n" + ex.Message); - this.lastError = "Error sending Version Info:\n" + ex.Message; - this.nwStream.Close(); - this.tcpClient.Close(); + FireDebug(" -> Error sending Version Info:\n" + ex.Message); + lastError = "Error sending Version Info:\n" + ex.Message; + nwStream.Close(); + tcpClient.Close(); return false; } byte[] buffer2; - if (this.compress) + if (compress) { - this.fireDebug(" Compressing File..."); + FireDebug(" Compressing File..."); try { - buffer2 = zlibWrapper.Compress(fileData); + buffer2 = ZlibWrapper.Compress(fileData); } catch { - this.fireDebug(" -> Compression failed, continuing without compression..."); - this.compress = false; + FireDebug(" -> Compression failed, continuing without compression..."); + compress = false; buffer2 = fileData; fileData = new byte[0]; } @@ -262,88 +277,93 @@ namespace libWiiSharp buffer2 = fileData; fileData = new byte[0]; } - this.fireDebug(" Sending Filesize..."); - buffer1[0] = (byte) (buffer2.Length >> 24 & (int) byte.MaxValue); - buffer1[1] = (byte) (buffer2.Length >> 16 & (int) byte.MaxValue); - buffer1[2] = (byte) (buffer2.Length >> 8 & (int) byte.MaxValue); - buffer1[3] = (byte) (buffer2.Length & (int) byte.MaxValue); + FireDebug(" Sending Filesize..."); + buffer1[0] = (byte)(buffer2.Length >> 24 & byte.MaxValue); + buffer1[1] = (byte)(buffer2.Length >> 16 & byte.MaxValue); + buffer1[2] = (byte)(buffer2.Length >> 8 & byte.MaxValue); + buffer1[3] = (byte)(buffer2.Length & byte.MaxValue); try { - this.nwStream.Write(buffer1, 0, 4); + nwStream.Write(buffer1, 0, 4); } catch (Exception ex) { - this.fireDebug(" -> Error sending Filesize:\n" + ex.Message); - this.lastError = "Error sending Filesize:\n" + ex.Message; - this.nwStream.Close(); - this.tcpClient.Close(); + FireDebug(" -> Error sending Filesize:\n" + ex.Message); + lastError = "Error sending Filesize:\n" + ex.Message; + nwStream.Close(); + tcpClient.Close(); return false; } - if (this.protocol != Protocol.HAXX) + if (protocol != Protocol.HAXX) { - buffer1[0] = (byte) (fileData.Length >> 24 & (int) byte.MaxValue); - buffer1[1] = (byte) (fileData.Length >> 16 & (int) byte.MaxValue); - buffer1[2] = (byte) (fileData.Length >> 8 & (int) byte.MaxValue); - buffer1[3] = (byte) (fileData.Length & (int) byte.MaxValue); + buffer1[0] = (byte)(fileData.Length >> 24 & byte.MaxValue); + buffer1[1] = (byte)(fileData.Length >> 16 & byte.MaxValue); + buffer1[2] = (byte)(fileData.Length >> 8 & byte.MaxValue); + buffer1[3] = (byte)(fileData.Length & byte.MaxValue); try { - this.nwStream.Write(buffer1, 0, 4); + nwStream.Write(buffer1, 0, 4); } catch (Exception ex) { - this.fireDebug(" -> Error sending Filesize:\n" + ex.Message); - this.lastError = "Error sending Filesize:\n" + ex.Message; - this.nwStream.Close(); - this.tcpClient.Close(); + FireDebug(" -> Error sending Filesize:\n" + ex.Message); + lastError = "Error sending Filesize:\n" + ex.Message; + nwStream.Close(); + tcpClient.Close(); return false; } } - this.fireDebug(" Sending File..."); + FireDebug(" Sending File..."); int offset = 0; int num1 = 0; - int num2 = buffer2.Length / this.Blocksize; - int num3 = buffer2.Length % this.Blocksize; + int num2 = buffer2.Length / Blocksize; + int num3 = buffer2.Length % Blocksize; try { do { - this.fireProgress(++num1 * 100 / num2); - this.nwStream.Write(buffer2, offset, this.Blocksize); - offset += this.Blocksize; + FireProgress(++num1 * 100 / num2); + nwStream.Write(buffer2, offset, Blocksize); + offset += Blocksize; } while (num1 < num2); if (num3 > 0) - this.nwStream.Write(buffer2, offset, buffer2.Length - offset); + { + nwStream.Write(buffer2, offset, buffer2.Length - offset); + } } catch (Exception ex) { - this.fireDebug(" -> Error sending File:\n" + ex.Message); - this.lastError = "Error sending File:\n" + ex.Message; - this.nwStream.Close(); - this.tcpClient.Close(); + FireDebug(" -> Error sending File:\n" + ex.Message); + lastError = "Error sending File:\n" + ex.Message; + nwStream.Close(); + tcpClient.Close(); return false; } - this.fireDebug(" Sending Arguments..."); + FireDebug(" Sending Arguments..."); byte[] buffer3 = new byte[fileName.Length + 2]; for (int index = 0; index < fileName.Length; ++index) - buffer3[index] = (byte) fileName.ToCharArray()[index]; + { + buffer3[index] = (byte)fileName.ToCharArray()[index]; + } + try { - this.nwStream.Write(buffer3, 0, buffer3.Length); + nwStream.Write(buffer3, 0, buffer3.Length); } catch (Exception ex) { - this.fireDebug(" -> Error sending Arguments:\n" + ex.Message); - this.lastError = "Error sending Arguments:\n" + ex.Message; - this.nwStream.Close(); - this.tcpClient.Close(); + FireDebug(" -> Error sending Arguments:\n" + ex.Message); + lastError = "Error sending Arguments:\n" + ex.Message; + nwStream.Close(); + tcpClient.Close(); return false; } - this.nwStream.Close(); - this.tcpClient.Close(); - this.transmittedLength = buffer2.Length; - this.compressionRatio = !this.compress || fileData.Length == 0 ? 0 : buffer2.Length * 100 / fileData.Length; - this.fireDebug("Transmitting {0} to {1}:{2} Finished...", (object) fileName, (object) this.ipAddress, (object) this.port); + nwStream.Close(); + tcpClient.Close(); + transmittedLength = buffer2.Length; + compressionRatio = !compress || fileData.Length == 0 ? 0 : buffer2.Length * 100 / fileData.Length; + FireDebug("Transmitting {0} to {1}:{2} Finished...", fileName, ipAddress, port); return true; } #endregion @@ -359,28 +379,34 @@ namespace libWiiSharp /// public event EventHandler Debug; - private void fireDebug(string debugMessage, params object[] args) + private void FireDebug(string debugMessage, params object[] args) { - EventHandler debug = this.Debug; + EventHandler debug = Debug; if (debug == null) + { return; + } + debug(new object(), new MessageEventArgs(string.Format(debugMessage, args))); } - private void fireProgress(int progressPercentage) + private void FireProgress(int progressPercentage) { - EventHandler progress = this.Progress; + EventHandler progress = Progress; if (progress == null) + { return; - progress(new object(), new ProgressChangedEventArgs(progressPercentage, (object) string.Empty)); + } + + progress(new object(), new ProgressChangedEventArgs(progressPercentage, string.Empty)); } #endregion } - internal class zlibWrapper + internal class ZlibWrapper { [DllImport("zlib1.dll")] - private static extern zlibWrapper.ZLibError compress2( + private static extern ZlibWrapper.ZLibError Compress2( byte[] dest, ref int destLength, byte[] source, @@ -391,9 +417,12 @@ namespace libWiiSharp { byte[] array = new byte[inFile.Length + 64]; int destLength = -1; - zlibWrapper.ZLibError zlibError = zlibWrapper.compress2(array, ref destLength, inFile, inFile.Length, 6); - if (zlibError != zlibWrapper.ZLibError.Z_OK || destLength <= -1 || destLength >= inFile.Length) + ZlibWrapper.ZLibError zlibError = ZlibWrapper.Compress2(array, ref destLength, inFile, inFile.Length, 6); + if (zlibError != ZlibWrapper.ZLibError.Z_OK || destLength <= -1 || destLength >= inFile.Length) + { throw new Exception("An error occured while compressing! Code: " + zlibError.ToString()); + } + Array.Resize(ref array, destLength); return array; } diff --git a/Headers.cs b/Headers.cs index 361d07c..b6f65d5 100644 --- a/Headers.cs +++ b/Headers.cs @@ -24,8 +24,8 @@ namespace libWiiSharp { public class Headers { - private static uint imd5Magic = 1229800501; - private static uint imetMagic = 1229800788; + private static readonly uint imd5Magic = 1229800501; + private static readonly uint imetMagic = 1229800788; /// /// Convert HeaderType to int to get it's Length. @@ -53,7 +53,10 @@ namespace libWiiSharp /// /// /// - public static Headers.HeaderType DetectHeader(string pathToFile) => Headers.DetectHeader(File.ReadAllBytes(pathToFile)); + public static Headers.HeaderType DetectHeader(string pathToFile) + { + return Headers.DetectHeader(File.ReadAllBytes(pathToFile)); + } /// /// Checks the byte array for Headers. @@ -62,11 +65,17 @@ namespace libWiiSharp /// public static Headers.HeaderType DetectHeader(byte[] file) { - if (file.Length > 68 && (int) Shared.Swap(BitConverter.ToUInt32(file, 64)) == (int) Headers.imetMagic) + if (file.Length > 68 && (int)Shared.Swap(BitConverter.ToUInt32(file, 64)) == (int)Headers.imetMagic) + { return Headers.HeaderType.ShortIMET; - if (file.Length > 132 && (int) Shared.Swap(BitConverter.ToUInt32(file, 128)) == (int) Headers.imetMagic) + } + + if (file.Length > 132 && (int)Shared.Swap(BitConverter.ToUInt32(file, 128)) == (int)Headers.imetMagic) + { return Headers.HeaderType.IMET; - return file.Length > 4 && (int) Shared.Swap(BitConverter.ToUInt32(file, 0)) == (int) Headers.imd5Magic ? Headers.HeaderType.IMD5 : Headers.HeaderType.None; + } + + return file.Length > 4 && (int)Shared.Swap(BitConverter.ToUInt32(file, 0)) == (int)Headers.imd5Magic ? Headers.HeaderType.IMD5 : Headers.HeaderType.None; } /// @@ -81,22 +90,28 @@ namespace libWiiSharp { file.Seek(64L, SeekOrigin.Begin); file.Read(buffer, 0, buffer.Length); - if ((int) Shared.Swap(BitConverter.ToUInt32(buffer, 0)) == (int) Headers.imetMagic) + if ((int)Shared.Swap(BitConverter.ToUInt32(buffer, 0)) == (int)Headers.imetMagic) + { return Headers.HeaderType.ShortIMET; + } } if (file.Length > 132L) { file.Seek(128L, SeekOrigin.Begin); file.Read(buffer, 0, buffer.Length); - if ((int) Shared.Swap(BitConverter.ToUInt32(buffer, 0)) == (int) Headers.imetMagic) + if ((int)Shared.Swap(BitConverter.ToUInt32(buffer, 0)) == (int)Headers.imetMagic) + { return Headers.HeaderType.IMET; + } } if (file.Length > 4L) { file.Seek(0L, SeekOrigin.Begin); file.Read(buffer, 0, buffer.Length); - if ((int) Shared.Swap(BitConverter.ToUInt32(buffer, 0)) == (int) Headers.imd5Magic) + if ((int)Shared.Swap(BitConverter.ToUInt32(buffer, 0)) == (int)Headers.imd5Magic) + { return Headers.HeaderType.IMD5; + } } return Headers.HeaderType.None; } @@ -106,10 +121,10 @@ namespace libWiiSharp { private bool hashesMatch = true; private bool isShortImet; - private byte[] additionalPadding = new byte[64]; - private byte[] padding = new byte[64]; - private uint imetMagic = 1229800788; - private uint sizeOfHeader = 1536; + private readonly byte[] additionalPadding = new byte[64]; + private readonly byte[] padding = new byte[64]; + private readonly uint imetMagic = 1229800788; + private readonly uint sizeOfHeader = 1536; private uint unknown = 3; private uint iconSize; private uint bannerSize; @@ -122,10 +137,10 @@ namespace libWiiSharp private byte[] spanishTitle = new byte[84]; private byte[] italianTitle = new byte[84]; private byte[] dutchTitle = new byte[84]; - private byte[] unknownTitle1 = new byte[84]; - private byte[] unknownTitle2 = new byte[84]; + private readonly byte[] unknownTitle1 = new byte[84]; + private readonly byte[] unknownTitle2 = new byte[84]; private byte[] koreanTitle = new byte[84]; - private byte[] padding2 = new byte[588]; + private readonly byte[] padding2 = new byte[588]; private byte[] hash = new byte[16]; /// @@ -133,8 +148,8 @@ namespace libWiiSharp /// public bool IsShortIMET { - get => this.isShortImet; - set => this.isShortImet = value; + get => isShortImet; + set => isShortImet = value; } /// @@ -142,8 +157,8 @@ namespace libWiiSharp /// public uint IconSize { - get => this.iconSize; - set => this.iconSize = value; + get => iconSize; + set => iconSize = value; } /// @@ -151,8 +166,8 @@ namespace libWiiSharp /// public uint BannerSize { - get => this.bannerSize; - set => this.bannerSize = value; + get => bannerSize; + set => bannerSize = value; } /// @@ -160,8 +175,8 @@ namespace libWiiSharp /// public uint SoundSize { - get => this.soundSize; - set => this.soundSize = value; + get => soundSize; + set => soundSize = value; } /// @@ -169,8 +184,8 @@ namespace libWiiSharp /// public string JapaneseTitle { - get => this.returnTitleAsString(this.japaneseTitle); - set => this.setTitleFromString(value, 0); + get => ReturnTitleAsString(japaneseTitle); + set => SetTitleFromString(value, 0); } /// @@ -178,8 +193,8 @@ namespace libWiiSharp /// public string EnglishTitle { - get => this.returnTitleAsString(this.englishTitle); - set => this.setTitleFromString(value, 1); + get => ReturnTitleAsString(englishTitle); + set => SetTitleFromString(value, 1); } /// @@ -187,8 +202,8 @@ namespace libWiiSharp /// public string GermanTitle { - get => this.returnTitleAsString(this.germanTitle); - set => this.setTitleFromString(value, 2); + get => ReturnTitleAsString(germanTitle); + set => SetTitleFromString(value, 2); } /// @@ -196,8 +211,8 @@ namespace libWiiSharp /// public string FrenchTitle { - get => this.returnTitleAsString(this.frenchTitle); - set => this.setTitleFromString(value, 3); + get => ReturnTitleAsString(frenchTitle); + set => SetTitleFromString(value, 3); } /// @@ -205,8 +220,8 @@ namespace libWiiSharp /// public string SpanishTitle { - get => this.returnTitleAsString(this.spanishTitle); - set => this.setTitleFromString(value, 4); + get => ReturnTitleAsString(spanishTitle); + set => SetTitleFromString(value, 4); } /// @@ -214,8 +229,8 @@ namespace libWiiSharp /// public string ItalianTitle { - get => this.returnTitleAsString(this.italianTitle); - set => this.setTitleFromString(value, 5); + get => ReturnTitleAsString(italianTitle); + set => SetTitleFromString(value, 5); } /// @@ -223,8 +238,8 @@ namespace libWiiSharp /// public string DutchTitle { - get => this.returnTitleAsString(this.dutchTitle); - set => this.setTitleFromString(value, 6); + get => ReturnTitleAsString(dutchTitle); + set => SetTitleFromString(value, 6); } /// @@ -232,8 +247,8 @@ namespace libWiiSharp /// public string KoreanTitle { - get => this.returnTitleAsString(this.koreanTitle); - set => this.setTitleFromString(value, 7); + get => ReturnTitleAsString(koreanTitle); + set => SetTitleFromString(value, 7); } /// @@ -241,20 +256,20 @@ namespace libWiiSharp /// public string[] AllTitles => new string[8] { - this.JapaneseTitle, - this.EnglishTitle, - this.GermanTitle, - this.FrenchTitle, - this.SpanishTitle, - this.ItalianTitle, - this.DutchTitle, - this.KoreanTitle + JapaneseTitle, + EnglishTitle, + GermanTitle, + FrenchTitle, + SpanishTitle, + ItalianTitle, + DutchTitle, + KoreanTitle }; /// /// When parsing an IMET header, this value will turn false if the hash stored in the header doesn't match the headers hash. /// - public bool HashesMatch => this.hashesMatch; + public bool HashesMatch => hashesMatch; #region Public Functions /// @@ -262,7 +277,10 @@ namespace libWiiSharp /// /// /// - public static Headers.IMET Load(string pathToFile) => Headers.IMET.Load(File.ReadAllBytes(pathToFile)); + public static Headers.IMET Load(string pathToFile) + { + return Headers.IMET.Load(File.ReadAllBytes(pathToFile)); + } /// /// Loads the IMET Header of a byte array. @@ -278,11 +296,14 @@ namespace libWiiSharp case Headers.HeaderType.IMET: Headers.IMET imet = new Headers.IMET(); if (headerType == Headers.HeaderType.ShortIMET) + { imet.isShortImet = true; + } + MemoryStream memoryStream = new MemoryStream(fileOrHeader); try { - imet.parseHeader((Stream) memoryStream); + imet.ParseHeader(memoryStream); } catch { @@ -310,8 +331,11 @@ namespace libWiiSharp case Headers.HeaderType.IMET: Headers.IMET imet = new Headers.IMET(); if (headerType == Headers.HeaderType.ShortIMET) + { imet.isShortImet = true; - imet.parseHeader(fileOrHeader); + } + + imet.ParseHeader(fileOrHeader); return imet; default: throw new Exception("No IMET Header found!"); @@ -334,15 +358,23 @@ namespace libWiiSharp int soundSize, params string[] titles) { - Headers.IMET imet = new Headers.IMET(); - imet.isShortImet = isShortImet; + Headers.IMET imet = new Headers.IMET + { + isShortImet = isShortImet + }; for (int titleIndex = 0; titleIndex < titles.Length; ++titleIndex) - imet.setTitleFromString(titles[titleIndex], titleIndex); + { + imet.SetTitleFromString(titles[titleIndex], titleIndex); + } + for (int length = titles.Length; length < 8; ++length) - imet.setTitleFromString(titles.Length > 1 ? titles[1] : titles[0], length); - imet.iconSize = (uint) iconSize; - imet.bannerSize = (uint) bannerSize; - imet.soundSize = (uint) soundSize; + { + imet.SetTitleFromString(titles.Length > 1 ? titles[1] : titles[0], length); + } + + imet.iconSize = (uint)iconSize; + imet.bannerSize = (uint)bannerSize; + imet.soundSize = (uint)soundSize; return imet; } @@ -367,13 +399,13 @@ namespace libWiiSharp Headers.HeaderType headerType = Headers.DetectHeader(file); switch (headerType) { - case Headers.HeaderType.ShortIMET: - case Headers.HeaderType.IMET: - byte[] numArray = new byte[(int) (file.Length - headerType)]; - Array.Copy((Array) file, (int) headerType, (Array) numArray, 0, numArray.Length); - return numArray; - default: - throw new Exception("No IMET Header found!"); + case Headers.HeaderType.ShortIMET: + case Headers.HeaderType.IMET: + byte[] numArray = new byte[(int)(file.Length - headerType)]; + Array.Copy(file, (int)headerType, numArray, 0, numArray.Length); + return numArray; + default: + throw new Exception("No IMET Header found!"); } } @@ -384,7 +416,9 @@ namespace libWiiSharp public void SetAllTitles(string newTitle) { for (int titleIndex = 0; titleIndex < 10; ++titleIndex) - this.setTitleFromString(newTitle, titleIndex); + { + SetTitleFromString(newTitle, titleIndex); + } } /// @@ -396,7 +430,7 @@ namespace libWiiSharp MemoryStream memoryStream = new MemoryStream(); try { - this.writeToStream((Stream) memoryStream); + WriteToStream(memoryStream); return memoryStream; } catch @@ -410,13 +444,19 @@ namespace libWiiSharp /// Returns the Header as a byte array. /// /// - public byte[] ToByteArray() => this.ToMemoryStream().ToArray(); + public byte[] ToByteArray() + { + return ToMemoryStream().ToArray(); + } /// /// Writes the Header to the given stream. /// /// - public void Write(Stream writeStream) => this.writeToStream(writeStream); + public void Write(Stream writeStream) + { + WriteToStream(writeStream); + } /// /// Changes the Titles. @@ -425,105 +465,125 @@ namespace libWiiSharp public void ChangeTitles(params string[] newTitles) { for (int titleIndex = 0; titleIndex < newTitles.Length; ++titleIndex) - this.setTitleFromString(newTitles[titleIndex], titleIndex); + { + SetTitleFromString(newTitles[titleIndex], titleIndex); + } + for (int length = newTitles.Length; length < 8; ++length) - this.setTitleFromString(newTitles.Length > 1 ? newTitles[1] : newTitles[0], length); + { + SetTitleFromString(newTitles.Length > 1 ? newTitles[1] : newTitles[0], length); + } } /// /// Returns a string array with the Titles. /// /// - public string[] GetTitles() => new string[8] + public string[] GetTitles() { - this.JapaneseTitle, - this.EnglishTitle, - this.GermanTitle, - this.FrenchTitle, - this.SpanishTitle, - this.ItalianTitle, - this.DutchTitle, - this.KoreanTitle - }; + return new string[8] +{ + JapaneseTitle, + EnglishTitle, + GermanTitle, + FrenchTitle, + SpanishTitle, + ItalianTitle, + DutchTitle, + KoreanTitle +}; + } #endregion #region Private Functions - private void writeToStream(Stream writeStream) + private void WriteToStream(Stream writeStream) { writeStream.Seek(0L, SeekOrigin.Begin); - if (!this.isShortImet) - writeStream.Write(this.additionalPadding, 0, this.additionalPadding.Length); - writeStream.Write(this.padding, 0, this.padding.Length); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.imetMagic)), 0, 4); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.sizeOfHeader)), 0, 4); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.unknown)), 0, 4); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.iconSize)), 0, 4); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.bannerSize)), 0, 4); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.soundSize)), 0, 4); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.flags)), 0, 4); - writeStream.Write(this.japaneseTitle, 0, this.japaneseTitle.Length); - writeStream.Write(this.englishTitle, 0, this.englishTitle.Length); - writeStream.Write(this.germanTitle, 0, this.germanTitle.Length); - writeStream.Write(this.frenchTitle, 0, this.frenchTitle.Length); - writeStream.Write(this.spanishTitle, 0, this.spanishTitle.Length); - writeStream.Write(this.italianTitle, 0, this.italianTitle.Length); - writeStream.Write(this.dutchTitle, 0, this.dutchTitle.Length); - writeStream.Write(this.unknownTitle1, 0, this.unknownTitle1.Length); - writeStream.Write(this.unknownTitle2, 0, this.unknownTitle2.Length); - writeStream.Write(this.koreanTitle, 0, this.koreanTitle.Length); - writeStream.Write(this.padding2, 0, this.padding2.Length); - int position = (int) writeStream.Position; - this.hash = new byte[16]; - writeStream.Write(this.hash, 0, this.hash.Length); + if (!isShortImet) + { + writeStream.Write(additionalPadding, 0, additionalPadding.Length); + } + + writeStream.Write(padding, 0, padding.Length); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(imetMagic)), 0, 4); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(sizeOfHeader)), 0, 4); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(unknown)), 0, 4); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(iconSize)), 0, 4); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(bannerSize)), 0, 4); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(soundSize)), 0, 4); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(flags)), 0, 4); + writeStream.Write(japaneseTitle, 0, japaneseTitle.Length); + writeStream.Write(englishTitle, 0, englishTitle.Length); + writeStream.Write(germanTitle, 0, germanTitle.Length); + writeStream.Write(frenchTitle, 0, frenchTitle.Length); + writeStream.Write(spanishTitle, 0, spanishTitle.Length); + writeStream.Write(italianTitle, 0, italianTitle.Length); + writeStream.Write(dutchTitle, 0, dutchTitle.Length); + writeStream.Write(unknownTitle1, 0, unknownTitle1.Length); + writeStream.Write(unknownTitle2, 0, unknownTitle2.Length); + writeStream.Write(koreanTitle, 0, koreanTitle.Length); + writeStream.Write(padding2, 0, padding2.Length); + int position = (int)writeStream.Position; + hash = new byte[16]; + writeStream.Write(hash, 0, hash.Length); byte[] numArray = new byte[writeStream.Position]; writeStream.Seek(0L, SeekOrigin.Begin); writeStream.Read(numArray, 0, numArray.Length); - this.computeHash(numArray, !this.isShortImet ? 64 : 0); - writeStream.Seek((long) position, SeekOrigin.Begin); - writeStream.Write(this.hash, 0, this.hash.Length); + ComputeHash(numArray, !isShortImet ? 64 : 0); + writeStream.Seek(position, SeekOrigin.Begin); + writeStream.Write(hash, 0, hash.Length); } - private void computeHash(byte[] headerBytes, int hashPos) + private void ComputeHash(byte[] headerBytes, int hashPos) { MD5 md5 = MD5.Create(); - this.hash = md5.ComputeHash(headerBytes, hashPos, 1536); + hash = md5.ComputeHash(headerBytes, hashPos, 1536); md5.Clear(); } - private void parseHeader(Stream headerStream) + private void ParseHeader(Stream headerStream) { headerStream.Seek(0L, SeekOrigin.Begin); byte[] buffer1 = new byte[4]; - if (!this.isShortImet) - headerStream.Read(this.additionalPadding, 0, this.additionalPadding.Length); - headerStream.Read(this.padding, 0, this.padding.Length); + if (!isShortImet) + { + headerStream.Read(additionalPadding, 0, additionalPadding.Length); + } + + headerStream.Read(padding, 0, padding.Length); headerStream.Read(buffer1, 0, 4); - if ((int) Shared.Swap(BitConverter.ToUInt32(buffer1, 0)) != (int) this.imetMagic) + if ((int)Shared.Swap(BitConverter.ToUInt32(buffer1, 0)) != (int)imetMagic) + { throw new Exception("Invalid Magic!"); + } + headerStream.Read(buffer1, 0, 4); - if ((int) Shared.Swap(BitConverter.ToUInt32(buffer1, 0)) != (int) this.sizeOfHeader) + if ((int)Shared.Swap(BitConverter.ToUInt32(buffer1, 0)) != (int)sizeOfHeader) + { throw new Exception("Invalid Header Size!"); + } + headerStream.Read(buffer1, 0, 4); - this.unknown = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); + unknown = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); headerStream.Read(buffer1, 0, 4); - this.iconSize = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); + iconSize = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); headerStream.Read(buffer1, 0, 4); - this.bannerSize = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); + bannerSize = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); headerStream.Read(buffer1, 0, 4); - this.soundSize = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); + soundSize = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); headerStream.Read(buffer1, 0, 4); - this.flags = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); - headerStream.Read(this.japaneseTitle, 0, this.japaneseTitle.Length); - headerStream.Read(this.englishTitle, 0, this.englishTitle.Length); - headerStream.Read(this.germanTitle, 0, this.germanTitle.Length); - headerStream.Read(this.frenchTitle, 0, this.frenchTitle.Length); - headerStream.Read(this.spanishTitle, 0, this.spanishTitle.Length); - headerStream.Read(this.italianTitle, 0, this.italianTitle.Length); - headerStream.Read(this.dutchTitle, 0, this.dutchTitle.Length); - headerStream.Read(this.unknownTitle1, 0, this.unknownTitle1.Length); - headerStream.Read(this.unknownTitle2, 0, this.unknownTitle2.Length); - headerStream.Read(this.koreanTitle, 0, this.koreanTitle.Length); - headerStream.Read(this.padding2, 0, this.padding2.Length); + flags = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); + headerStream.Read(japaneseTitle, 0, japaneseTitle.Length); + headerStream.Read(englishTitle, 0, englishTitle.Length); + headerStream.Read(germanTitle, 0, germanTitle.Length); + headerStream.Read(frenchTitle, 0, frenchTitle.Length); + headerStream.Read(spanishTitle, 0, spanishTitle.Length); + headerStream.Read(italianTitle, 0, italianTitle.Length); + headerStream.Read(dutchTitle, 0, dutchTitle.Length); + headerStream.Read(unknownTitle1, 0, unknownTitle1.Length); + headerStream.Read(unknownTitle2, 0, unknownTitle2.Length); + headerStream.Read(koreanTitle, 0, koreanTitle.Length); + headerStream.Read(padding2, 0, padding2.Length); headerStream.Read(this.hash, 0, this.hash.Length); headerStream.Seek(-16L, SeekOrigin.Current); headerStream.Write(new byte[16], 0, 16); @@ -531,12 +591,12 @@ namespace libWiiSharp headerStream.Seek(0L, SeekOrigin.Begin); headerStream.Read(buffer2, 0, buffer2.Length); MD5 md5 = MD5.Create(); - byte[] hash = md5.ComputeHash(buffer2, !this.isShortImet ? 64 : 0, 1536); + byte[] hash = md5.ComputeHash(buffer2, !isShortImet ? 64 : 0, 1536); md5.Clear(); - this.hashesMatch = Shared.CompareByteArrays(hash, this.hash); + hashesMatch = Shared.CompareByteArrays(hash, this.hash); } - private string returnTitleAsString(byte[] title) + private string ReturnTitleAsString(byte[] title) { string empty = string.Empty; for (int index = 0; index < 84; index += 2) @@ -547,12 +607,14 @@ namespace libWiiSharp title[index] }, 0); if (ch != char.MinValue) - empty += ch.ToString(); + { + empty += ch.ToString(); + } } return empty; } - private void setTitleFromString(string title, int titleIndex) + private void SetTitleFromString(string title, int titleIndex) { byte[] numArray = new byte[84]; for (int index = 0; index < title.Length; ++index) @@ -564,28 +626,28 @@ namespace libWiiSharp switch (titleIndex) { case 0: - this.japaneseTitle = numArray; + japaneseTitle = numArray; break; case 1: - this.englishTitle = numArray; + englishTitle = numArray; break; case 2: - this.germanTitle = numArray; + germanTitle = numArray; break; case 3: - this.frenchTitle = numArray; + frenchTitle = numArray; break; case 4: - this.spanishTitle = numArray; + spanishTitle = numArray; break; case 5: - this.italianTitle = numArray; + italianTitle = numArray; break; case 6: - this.dutchTitle = numArray; + dutchTitle = numArray; break; case 7: - this.koreanTitle = numArray; + koreanTitle = numArray; break; } } @@ -594,24 +656,24 @@ namespace libWiiSharp public class IMD5 { - private uint imd5Magic = 1229800501; + private readonly uint imd5Magic = 1229800501; private uint fileSize; - private byte[] padding = new byte[8]; + private readonly byte[] padding = new byte[8]; private byte[] hash = new byte[16]; /// /// The size of the file without the IMD5 Header. /// - public uint FileSize => this.fileSize; + public uint FileSize => fileSize; /// /// The hash of the file without the IMD5 Header. /// - public byte[] Hash => this.hash; + public byte[] Hash => hash; - private IMD5() - { - } + private IMD5() + { + } #region Public Functions /// @@ -619,7 +681,10 @@ namespace libWiiSharp /// /// /// - public static Headers.IMD5 Load(string pathToFile) => Headers.IMD5.Load(File.ReadAllBytes(pathToFile)); + public static Headers.IMD5 Load(string pathToFile) + { + return Headers.IMD5.Load(File.ReadAllBytes(pathToFile)); + } /// /// Loads the IMD5 Header of a byte array. @@ -629,12 +694,15 @@ namespace libWiiSharp public static Headers.IMD5 Load(byte[] fileOrHeader) { if (Headers.DetectHeader(fileOrHeader) != Headers.HeaderType.IMD5) + { throw new Exception("No IMD5 Header found!"); + } + Headers.IMD5 imD5 = new Headers.IMD5(); MemoryStream memoryStream = new MemoryStream(fileOrHeader); try { - imD5.parseHeader((Stream) memoryStream); + imD5.ParseHeader(memoryStream); } catch { @@ -653,9 +721,12 @@ namespace libWiiSharp public static Headers.IMD5 Load(Stream fileOrHeader) { if (Headers.DetectHeader(fileOrHeader) != Headers.HeaderType.IMD5) + { throw new Exception("No IMD5 Header found!"); + } + Headers.IMD5 imD5 = new Headers.IMD5(); - imD5.parseHeader(fileOrHeader); + imD5.ParseHeader(fileOrHeader); return imD5; } @@ -666,9 +737,11 @@ namespace libWiiSharp /// public static Headers.IMD5 Create(byte[] file) { - Headers.IMD5 imD5 = new Headers.IMD5(); - imD5.fileSize = (uint) file.Length; - imD5.computeHash(file); + IMD5 imD5 = new IMD5 + { + fileSize = (uint)file.Length + }; + imD5.ComputeHash(file); return imD5; } @@ -680,8 +753,8 @@ namespace libWiiSharp { byte[] buffer = Headers.IMD5.AddHeader(File.ReadAllBytes(pathToFile)); File.Delete(pathToFile); - using (FileStream fileStream = new FileStream(pathToFile, FileMode.Create)) - fileStream.Write(buffer, 0, buffer.Length); + using FileStream fileStream = new FileStream(pathToFile, FileMode.Create); + fileStream.Write(buffer, 0, buffer.Length); } /// @@ -694,7 +767,7 @@ namespace libWiiSharp Headers.IMD5 imD5 = Headers.IMD5.Create(file); MemoryStream memoryStream1 = new MemoryStream(); MemoryStream memoryStream2 = memoryStream1; - imD5.writeToStream((Stream) memoryStream2); + imD5.WriteToStream(memoryStream2); memoryStream1.Write(file, 0, file.Length); byte[] array = memoryStream1.ToArray(); memoryStream1.Dispose(); @@ -709,8 +782,8 @@ namespace libWiiSharp { byte[] buffer = Headers.IMD5.RemoveHeader(File.ReadAllBytes(pathToFile)); File.Delete(pathToFile); - using (FileStream fileStream = new FileStream(pathToFile, FileMode.Create)) - fileStream.Write(buffer, 0, buffer.Length); + using FileStream fileStream = new FileStream(pathToFile, FileMode.Create); + fileStream.Write(buffer, 0, buffer.Length); } /// @@ -736,7 +809,7 @@ namespace libWiiSharp MemoryStream memoryStream = new MemoryStream(); try { - this.writeToStream((Stream) memoryStream); + WriteToStream(memoryStream); return memoryStream; } catch @@ -750,43 +823,52 @@ namespace libWiiSharp /// Returns the IMD5 Header as a byte array. /// /// - public byte[] ToByteArray() => this.ToMemoryStream().ToArray(); + public byte[] ToByteArray() + { + return ToMemoryStream().ToArray(); + } /// /// Writes the IMD5 Header to the given stream. /// /// - public void Write(Stream writeStream) => this.writeToStream(writeStream); + public void Write(Stream writeStream) + { + WriteToStream(writeStream); + } #endregion #region Private Functions - private void writeToStream(Stream writeStream) + private void WriteToStream(Stream writeStream) { writeStream.Seek(0L, SeekOrigin.Begin); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.imd5Magic)), 0, 4); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.fileSize)), 0, 4); - writeStream.Write(this.padding, 0, this.padding.Length); - writeStream.Write(this.hash, 0, this.hash.Length); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(imd5Magic)), 0, 4); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(fileSize)), 0, 4); + writeStream.Write(padding, 0, padding.Length); + writeStream.Write(hash, 0, hash.Length); } - private void computeHash(byte[] bytesToHash) + private void ComputeHash(byte[] bytesToHash) { MD5 md5 = MD5.Create(); - this.hash = md5.ComputeHash(bytesToHash); + hash = md5.ComputeHash(bytesToHash); md5.Clear(); } - private void parseHeader(Stream headerStream) + private void ParseHeader(Stream headerStream) { headerStream.Seek(0L, SeekOrigin.Begin); byte[] buffer = new byte[4]; headerStream.Read(buffer, 0, 4); - if ((int) Shared.Swap(BitConverter.ToUInt32(buffer, 0)) != (int) this.imd5Magic) - throw new Exception("Invalid Magic!"); + if ((int)Shared.Swap(BitConverter.ToUInt32(buffer, 0)) != (int)imd5Magic) + { + throw new Exception("Invalid Magic!"); + } + headerStream.Read(buffer, 0, 4); - this.fileSize = Shared.Swap(BitConverter.ToUInt32(buffer, 0)); - headerStream.Read(this.padding, 0, this.padding.Length); - headerStream.Read(this.hash, 0, this.hash.Length); + fileSize = Shared.Swap(BitConverter.ToUInt32(buffer, 0)); + headerStream.Read(padding, 0, padding.Length); + headerStream.Read(hash, 0, hash.Length); } #endregion } diff --git a/HexView.cs b/HexView.cs index 864765d..985df04 100644 --- a/HexView.cs +++ b/HexView.cs @@ -34,33 +34,6 @@ namespace libWiiSharp private static string savedValue; #region Public Functions - /// - /// Displays the byte array like a hex editor in a ListView. - /// Columns will be created, estimated width is ~685 px. - /// Big files (25kB ++) will take quite a long time, so don't use this for big files. - /// - /// - /// - public static void DumpToListView(byte[] data, ListView listView) => HexView.dumpToListView(data, listView); - - /// - /// Displays the byte array like a hex editor in a DataGridView. - /// Columns will be created, estimated width is ~685 px. - /// Big files (25kB ++) will take quite a long time, so don't use this for big files. - /// - /// - /// - public static void DumpToDataGridView(byte[] data, DataGridView dataGridView) => HexView.dumpToDataGridView(data, dataGridView); - - /// - /// Dumps a DataGridView back to a byte array. - /// The DataGridView must have the right format. - /// Big files (25kB ++) will take quite a long time, so don't use this for big files. - /// - /// - /// - public static byte[] DumpFromDataGridView(DataGridView dataGridView) => HexView.dumpFromDataGridView(dataGridView); - /// /// Displays the byte array like a hex editor in a RichTextBox. /// Big files (25kB ++) will take quite a long time, so don't use this for big files. @@ -89,15 +62,6 @@ namespace libWiiSharp textBox.Text = HexView.DumpAsString(data).Replace("\n", "\r\n"); } - /// - /// Displays the byte array like a hex editor as a string array. - /// Be sure to use "Courier New" as a font, so every char has the same width. - /// Big files (25kB ++) will take quite a long time, so don't use this for big files. - /// - /// - /// - public static string[] DumpAsStringArray(byte[] data) => HexView.dumpAsStringArray(data); - /// /// Displays the byte array like a hex editor as a string. /// Be sure to use "Courier New" as a font, so every char has the same width. @@ -105,7 +69,10 @@ namespace libWiiSharp /// /// /// - public static string DumpAsString(byte[] data) => string.Join("\n", HexView.dumpAsStringArray(data)); + public static string DumpAsString(byte[] data) + { + return string.Join("\n", HexView.DumpAsStringArray(data)); + } /// /// Link your DataGridView's CellEndEdit event with this function. @@ -121,32 +88,46 @@ namespace libWiiSharp DataGridView dataGridView = sender as DataGridView; if (dataGridView.Columns[e.ColumnIndex].HeaderText.ToLower() == "dump") { - string str = (string) dataGridView.Rows[e.RowIndex].Cells[17].Value; + string str = (string)dataGridView.Rows[e.RowIndex].Cells[17].Value; if (!(str != HexView.savedValue)) + { return; + } + if (str.Length != 16) + { throw new Exception(); + } + for (int index = 0; index < 16; ++index) { - if ((int) HexView.toAscii(byte.Parse((string) dataGridView.Rows[e.RowIndex].Cells[index + 1].Value, NumberStyles.HexNumber)) != (int) str[index]) - dataGridView.Rows[e.RowIndex].Cells[index + 1].Value = (object) HexView.fromAscii(str[index]).ToString("x2"); + if (HexView.ToAscii(byte.Parse((string)dataGridView.Rows[e.RowIndex].Cells[index + 1].Value, NumberStyles.HexNumber)) != str[index]) + { + dataGridView.Rows[e.RowIndex].Cells[index + 1].Value = HexView.FromAscii(str[index]).ToString("x2"); + } } } else - { - if (((string) dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value).Length == 1) - dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = (object) ("0" + dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value?.ToString()); + { + if (((string)dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value).Length == 1) + { + dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = "0" + dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value?.ToString(); + } + int startIndex = int.Parse(dataGridView.Columns[e.ColumnIndex].HeaderText, NumberStyles.HexNumber); - string str = ((string) dataGridView.Rows[e.RowIndex].Cells[17].Value).Remove(startIndex, 1).Insert(startIndex, HexView.toAscii(byte.Parse((string) dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value, NumberStyles.HexNumber)).ToString()); - dataGridView.Rows[e.RowIndex].Cells[17].Value = (object) str; - if (((string) dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value).Length <= 2) + string str = ((string)dataGridView.Rows[e.RowIndex].Cells[17].Value).Remove(startIndex, 1).Insert(startIndex, HexView.ToAscii(byte.Parse((string)dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value, NumberStyles.HexNumber)).ToString()); + dataGridView.Rows[e.RowIndex].Cells[17].Value = str; + if (((string)dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value).Length <= 2) + { return; - dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = (object) ((string) dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value).Remove(0, ((string) dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value).Length - 2); + } + + dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = ((string)dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value).Remove(0, ((string)dataGridView.Rows[e.RowIndex].Cells[e.ColumnIndex].Value).Length - 2); } } catch { - ((DataGridView) sender).Rows[e.RowIndex].Cells[e.ColumnIndex].Value = (object) HexView.savedValue; + ((DataGridView)sender).Rows[e.RowIndex].Cells[e.ColumnIndex].Value = savedValue; } } @@ -157,17 +138,26 @@ namespace libWiiSharp /// /// /// - public static void DataGridView_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e) => HexView.savedValue = (string) ((DataGridView) sender).Rows[e.RowIndex].Cells[e.ColumnIndex].Value; + public static void DataGridView_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e) + { + HexView.savedValue = (string)((DataGridView)sender).Rows[e.RowIndex].Cells[e.ColumnIndex].Value; + } #endregion #region Private Functions - private static string[] dumpAsStringArray(byte[] data) + /// + /// Displays the byte array like a hex editor as a string array. + /// Be sure to use "Courier New" as a font, so every char has the same width. + /// Big files (25kB ++) will take quite a long time, so don't use this for big files. + /// + /// + /// + private static string[] DumpAsStringArray(byte[] data) { List stringList = new List(); - string empty = string.Empty; int num; char ascii; - for (num = 0; (double) (data.Length - num) / 16.0 >= 1.0; num += 16) + for (num = 0; (data.Length - num) / 16.0 >= 1.0; num += 16) { string str1 = string.Empty + num.ToString("x8") + " "; string str2 = string.Empty; @@ -175,7 +165,7 @@ namespace libWiiSharp { str1 = str1 + data[num + index].ToString("x2") + " "; string str3 = str2; - ascii = HexView.toAscii(data[num + index]); + ascii = HexView.ToAscii(data[num + index]); string str4 = ascii.ToString(); str2 = str3 + str4; } @@ -192,33 +182,43 @@ namespace libWiiSharp { str1 = str1 + data[num + index].ToString("x2") + " "; string str3 = str2; - ascii = HexView.toAscii(data[num + index]); + ascii = HexView.ToAscii(data[num + index]); string str4 = ascii.ToString(); str2 = str3 + str4; } else + { str1 += " "; + } } string str5 = str1 + " " + str2; stringList.Add(str5); } return stringList.ToArray(); } - - private static byte[] dumpFromDataGridView(DataGridView dataGridView) + // Unused + /* + /// + /// Dumps a DataGridView back to a byte array. + /// The DataGridView must have the right format. + /// Big files (25kB ++) will take quite a long time, so don't use this for big files. + /// + /// + /// + private static byte[] DumpFromDataGridView(DataGridView dataGridView) { try { List byteList = new List(); - for (int index1 = 0; !string.IsNullOrEmpty((string) dataGridView.Rows[index1].Cells[1].Value); ++index1) + for (int index1 = 0; !string.IsNullOrEmpty((string)dataGridView.Rows[index1].Cells[1].Value); ++index1) { for (int index2 = 0; index2 < 16; ++index2) { - if (!string.IsNullOrEmpty((string) dataGridView.Rows[index1].Cells[index2 + 1].Value)) - byteList.Add(byte.Parse((string) dataGridView.Rows[index1].Cells[index2 + 1].Value, NumberStyles.HexNumber)); + if (!string.IsNullOrEmpty((string)dataGridView.Rows[index1].Cells[index2 + 1].Value)) + byteList.Add(byte.Parse((string)dataGridView.Rows[index1].Cells[index2 + 1].Value, NumberStyles.HexNumber)); } if (index1 == dataGridView.Rows.Count - 1) - break; + break; } return byteList.ToArray(); } @@ -228,7 +228,14 @@ namespace libWiiSharp } } - private static void dumpToDataGridView(byte[] data, DataGridView dataGridView) + /// + /// Displays the byte array like a hex editor in a DataGridView. + /// Columns will be created, estimated width is ~685 px. + /// Big files (25kB ++) will take quite a long time, so don't use this for big files. + /// + /// + /// + private static void DumpToDataGridView(byte[] data, DataGridView dataGridView) { dataGridView.Columns.Clear(); dataGridView.Rows.Clear(); @@ -237,63 +244,70 @@ namespace libWiiSharp { HeaderText = "Offset", Width = 80, - CellTemplate = (DataGridViewCell) new DataGridViewTextBoxCell() + CellTemplate = (DataGridViewCell)new DataGridViewTextBoxCell() }); for (int index = 0; index < 16; ++index) dataGridView.Columns.Add(new DataGridViewColumn() { HeaderText = index.ToString("x1"), Width = 30, - CellTemplate = (DataGridViewCell) new DataGridViewTextBoxCell() - }); - dataGridView.Columns.Add(new DataGridViewColumn() - { - HeaderText = "Dump", - Width = 125, - CellTemplate = (DataGridViewCell) new DataGridViewTextBoxCell() + CellTemplate = (DataGridViewCell)new DataGridViewTextBoxCell() }); + dataGridView.Columns.Add(new DataGridViewColumn() + { + HeaderText = "Dump", + Width = 125, + CellTemplate = (DataGridViewCell)new DataGridViewTextBoxCell() + }); int num; - for (num = 0; (double) (data.Length - num) / 16.0 >= 1.0; num += 16) + for (num = 0; (double)(data.Length - num) / 16.0 >= 1.0; num += 16) { DataGridViewRow dataGridViewRow = new DataGridViewRow(); - int index1 = dataGridViewRow.Cells.Add((DataGridViewCell) new DataGridViewTextBoxCell()); - dataGridViewRow.Cells[index1].Value = (object) num.ToString("x8"); + int index1 = dataGridViewRow.Cells.Add((DataGridViewCell)new DataGridViewTextBoxCell()); + dataGridViewRow.Cells[index1].Value = (object)num.ToString("x8"); dataGridViewRow.Cells[index1].ReadOnly = true; string empty = string.Empty; for (int index2 = 0; index2 < 16; ++index2) { - int index3 = dataGridViewRow.Cells.Add((DataGridViewCell) new DataGridViewTextBoxCell()); - dataGridViewRow.Cells[index3].Value = (object) data[num + index2].ToString("x2"); - empty += HexView.toAscii(data[num + index2]).ToString(); + int index3 = dataGridViewRow.Cells.Add((DataGridViewCell)new DataGridViewTextBoxCell()); + dataGridViewRow.Cells[index3].Value = (object)data[num + index2].ToString("x2"); + empty += HexView.ToAscii(data[num + index2]).ToString(); } - int index4 = dataGridViewRow.Cells.Add((DataGridViewCell) new DataGridViewTextBoxCell()); - dataGridViewRow.Cells[index4].Value = (object) empty; + int index4 = dataGridViewRow.Cells.Add((DataGridViewCell)new DataGridViewTextBoxCell()); + dataGridViewRow.Cells[index4].Value = (object)empty; dataGridView.Rows.Add(dataGridViewRow); } if (data.Length <= num) return; DataGridViewRow dataGridViewRow1 = new DataGridViewRow(); - int index5 = dataGridViewRow1.Cells.Add((DataGridViewCell) new DataGridViewTextBoxCell()); - dataGridViewRow1.Cells[index5].Value = (object) num.ToString("x8"); + int index5 = dataGridViewRow1.Cells.Add((DataGridViewCell)new DataGridViewTextBoxCell()); + dataGridViewRow1.Cells[index5].Value = (object)num.ToString("x8"); dataGridViewRow1.Cells[index5].ReadOnly = true; string empty1 = string.Empty; for (int index1 = 0; index1 < 16; ++index1) { if (index1 < data.Length - num) { - int index2 = dataGridViewRow1.Cells.Add((DataGridViewCell) new DataGridViewTextBoxCell()); - dataGridViewRow1.Cells[index2].Value = (object) data[num + index1].ToString("x2"); - empty1 += HexView.toAscii(data[num + index1]).ToString(); + int index2 = dataGridViewRow1.Cells.Add((DataGridViewCell)new DataGridViewTextBoxCell()); + dataGridViewRow1.Cells[index2].Value = (object)data[num + index1].ToString("x2"); + empty1 += HexView.ToAscii(data[num + index1]).ToString(); } else - dataGridViewRow1.Cells.Add((DataGridViewCell) new DataGridViewTextBoxCell()); + dataGridViewRow1.Cells.Add((DataGridViewCell)new DataGridViewTextBoxCell()); } - int index6 = dataGridViewRow1.Cells.Add((DataGridViewCell) new DataGridViewTextBoxCell()); - dataGridViewRow1.Cells[index6].Value = (object) empty1; + int index6 = dataGridViewRow1.Cells.Add((DataGridViewCell)new DataGridViewTextBoxCell()); + dataGridViewRow1.Cells[index6].Value = (object)empty1; dataGridView.Rows.Add(dataGridViewRow1); } - private static void dumpToListView(byte[] data, ListView listView) + /// + /// Displays the byte array like a hex editor in a ListView. + /// Columns will be created, estimated width is ~685 px. + /// Big files (25kB ++) will take quite a long time, so don't use this for big files. + /// + /// + /// + private static void DumpToListView(byte[] data, ListView listView) { listView.Columns.Clear(); listView.Items.Clear(); @@ -304,14 +318,14 @@ namespace libWiiSharp listView.Columns.Add(index.ToString("x1"), index.ToString("x1"), 30, HorizontalAlignment.Left, string.Empty); listView.Columns.Add("Dump", "Dump", 125, HorizontalAlignment.Left, string.Empty); int num; - for (num = 0; (double) (data.Length - num) / 16.0 >= 1.0; num += 16) + for (num = 0; (double)(data.Length - num) / 16.0 >= 1.0; num += 16) { ListViewItem listViewItem = new ListViewItem(num.ToString("x8")); string empty = string.Empty; for (int index = 0; index < 16; ++index) { listViewItem.SubItems.Add(data[num + index].ToString("x2")); - empty += HexView.toAscii(data[num + index]).ToString(); + empty += HexView.ToAscii(data[num + index]).ToString(); } listViewItem.SubItems.Add(empty); listView.Items.Add(listViewItem); @@ -325,7 +339,7 @@ namespace libWiiSharp if (index < data.Length - num) { listViewItem1.SubItems.Add(data[num + index].ToString("x2")); - empty1 += HexView.toAscii(data[num + index]).ToString(); + empty1 += HexView.ToAscii(data[num + index]).ToString(); } else listViewItem1.SubItems.Add(string.Empty); @@ -333,10 +347,18 @@ namespace libWiiSharp listViewItem1.SubItems.Add(empty1); listView.Items.Add(listViewItem1); } + */ - private static char toAscii(byte value) => value >= (byte) 32 && value <= (byte) 126 ? (char) value : '.'; - private static byte fromAscii(char value) => (byte) value; + private static char ToAscii(byte value) + { + return value >= 32 && value <= 126 ? (char)value : '.'; + } + + private static byte FromAscii(char value) + { + return (byte)value; + } #endregion } -} +} \ No newline at end of file diff --git a/IosPatcher.cs b/IosPatcher.cs index 82c5d4d..a09b49f 100644 --- a/IosPatcher.cs +++ b/IosPatcher.cs @@ -37,8 +37,8 @@ namespace libWiiSharp /// public void LoadIOS(ref WAD iosWad) { - this.wadFile = iosWad; - this.getEsIndex(); + wadFile = iosWad; + GetEsIndex(); } /// @@ -46,262 +46,295 @@ namespace libWiiSharp /// Returns the number of applied patches. /// /// - public int PatchFakeSigning() => this.esIndex < 0 ? -1 : this.patchFakeSigning(ref this.wadFile.Contents[this.esIndex]); + public int PatchFakeSigning() + { + return esIndex < 0 ? -1 : PrivPatchFakeSigning(ref wadFile.Contents[esIndex]); + } /// /// Patches es_identify. /// Returns the number of applied patches. /// /// - public int PatchEsIdentify() => this.esIndex < 0 ? -1 : this.patchEsIdentify(ref this.wadFile.Contents[this.esIndex]); + public int PatchEsIdentify() + { + return esIndex < 0 ? -1 : PrivPatchEsIdentify(ref wadFile.Contents[esIndex]); + } /// /// Patches nand permissions. /// Returns the number of applied patches. /// /// - public int PatchNandPermissions() => this.esIndex < 0 ? -1 : this.patchNandPermissions(ref this.wadFile.Contents[this.esIndex]); + public int PatchNandPermissions() + { + return esIndex < 0 ? -1 : PrivPatchNandPermissions(ref wadFile.Contents[esIndex]); + } - public int PatchVP() => this.esIndex < 0 ? -1 : this.patchVP(ref this.wadFile.Contents[this.esIndex]); + public int PatchVP() + { + return esIndex < 0 ? -1 : PrivPatchVP(ref wadFile.Contents[esIndex]); + } /// /// Patches fakesigning, es_identify and nand permissions. /// Returns the number of applied patches. /// /// - public int PatchAll() => this.esIndex < 0 ? -1 : this.patchAll(ref this.wadFile.Contents[this.esIndex]); + public int PatchAll() + { + return esIndex < 0 ? -1 : PrivPatchAll(ref wadFile.Contents[esIndex]); + } - public int PatchFakeSigning(ref byte[] esModule) => this.patchFakeSigning(ref esModule); + public int PatchFakeSigning(ref byte[] esModule) + { + return PatchFakeSigning(ref esModule); + } - public int PatchEsIdentify(ref byte[] esModule) => this.patchEsIdentify(ref esModule); + public int PatchEsIdentify(ref byte[] esModule) + { + return PatchEsIdentify(ref esModule); + } - public int PatchNandPermissions(ref byte[] esModule) => this.patchNandPermissions(ref esModule); + public int PatchNandPermissions(ref byte[] esModule) + { + return PrivPatchNandPermissions(ref esModule); + } - public int PatchVP(ref byte[] esModule) => this.patchVP(ref esModule); + public int PatchVP(ref byte[] esModule) + { + return PrivPatchVP(ref esModule); + } - public int PatchAll(ref byte[] esModule) => this.patchAll(ref esModule); + public int PatchAll(ref byte[] esModule) + { + return PrivPatchAll(ref esModule); + } #endregion #region Private Functions - private int patchFakeSigning(ref byte[] esModule) + private int PrivPatchFakeSigning(ref byte[] esModule) { - this.fireDebug("Patching Fakesigning..."); + FireDebug("Patching Fakesigning..."); int num = 0; byte[] second1 = new byte[4] { - (byte) 32, - (byte) 7, - (byte) 35, - (byte) 162 + 32, + 7, + 35, + 162 }; byte[] second2 = new byte[4] { - (byte) 32, - (byte) 7, - (byte) 75, - (byte) 11 + 32, + 7, + 75, + 11 }; for (int firstIndex = 0; firstIndex < esModule.Length - 4; ++firstIndex) { - this.fireProgress((firstIndex + 1) * 100 / esModule.Length); + FireProgress((firstIndex + 1) * 100 / esModule.Length); if (Shared.CompareByteArrays(esModule, firstIndex, second1, 0, 4) || Shared.CompareByteArrays(esModule, firstIndex, second2, 0, 4)) { - this.fireDebug(" Patching at Offset: 0x{0}", (object) firstIndex.ToString("x8").ToUpper()); - esModule[firstIndex + 1] = (byte) 0; + FireDebug(" Patching at Offset: 0x{0}", (object)firstIndex.ToString("x8").ToUpper()); + esModule[firstIndex + 1] = 0; firstIndex += 4; ++num; } } - this.fireDebug("Patching Fakesigning Finished... (Patches applied: {0})", (object) num); - return num; - } - - private int patchEsIdentify(ref byte[] esModule) - { - this.fireDebug("Patching ES_Identify..."); - int num = 0; - byte[] second = new byte[4] - { - (byte) 40, - (byte) 3, - (byte) 209, - (byte) 35 - }; - for (int firstIndex = 0; firstIndex < esModule.Length - 4; ++firstIndex) - { - this.fireProgress((firstIndex + 1) * 100 / esModule.Length); - if (Shared.CompareByteArrays(esModule, firstIndex, second, 0, 4)) - { - this.fireDebug(" Patching at Offset: 0x{0}", (object) firstIndex.ToString("x8").ToUpper()); - esModule[firstIndex + 2] = (byte) 0; - esModule[firstIndex + 3] = (byte) 0; - firstIndex += 4; - ++num; - } - } - this.fireDebug("Patching ES_Identify Finished... (Patches applied: {0})", (object) num); + FireDebug("Patching Fakesigning Finished... (Patches applied: {0})", (object)num); return num; } - private int patchNandPermissions(ref byte[] esModule) + private int PrivPatchEsIdentify(ref byte[] esModule) { - this.fireDebug("Patching NAND Permissions..."); + FireDebug("Patching ES_Identify..."); + int num = 0; + byte[] second = new byte[4] + { + 40, + 3, + 209, + 35 + }; + for (int firstIndex = 0; firstIndex < esModule.Length - 4; ++firstIndex) + { + FireProgress((firstIndex + 1) * 100 / esModule.Length); + if (Shared.CompareByteArrays(esModule, firstIndex, second, 0, 4)) + { + FireDebug(" Patching at Offset: 0x{0}", (object)firstIndex.ToString("x8").ToUpper()); + esModule[firstIndex + 2] = 0; + esModule[firstIndex + 3] = 0; + firstIndex += 4; + ++num; + } + } + FireDebug("Patching ES_Identify Finished... (Patches applied: {0})", (object)num); + return num; + } + + private int PrivPatchNandPermissions(ref byte[] esModule) + { + FireDebug("Patching NAND Permissions..."); int num = 0; byte[] second = new byte[6] { - (byte) 66, - (byte) 139, - (byte) 208, - (byte) 1, - (byte) 37, - (byte) 102 + 66, + 139, + 208, + 1, + 37, + 102 }; for (int firstIndex = 0; firstIndex < esModule.Length - 6; ++firstIndex) { - this.fireProgress((firstIndex + 1) * 100 / esModule.Length); + FireProgress((firstIndex + 1) * 100 / esModule.Length); if (Shared.CompareByteArrays(esModule, firstIndex, second, 0, 6)) { - this.fireDebug(" Patching at Offset: 0x{0}", (object) firstIndex.ToString("x8").ToUpper()); - esModule[firstIndex + 2] = (byte) 224; + FireDebug(" Patching at Offset: 0x{0}", (object)firstIndex.ToString("x8").ToUpper()); + esModule[firstIndex + 2] = 224; firstIndex += 6; ++num; } } - this.fireDebug("Patching NAND Permissions Finished... (Patches applied: {0})", (object) num); + FireDebug("Patching NAND Permissions Finished... (Patches applied: {0})", (object)num); return num; } - private int patchVP(ref byte[] esModule) + private int PrivPatchVP(ref byte[] esModule) { - this.fireDebug("Patching VP..."); + FireDebug("Patching VP..."); int num = 0; byte[] second = new byte[4] { - (byte) 210, - (byte) 1, - (byte) 78, - (byte) 86 + 210, + 1, + 78, + 86 }; for (int firstIndex = 0; firstIndex < esModule.Length - 4; ++firstIndex) { - this.fireProgress((firstIndex + 1) * 100 / esModule.Length); + FireProgress((firstIndex + 1) * 100 / esModule.Length); if (Shared.CompareByteArrays(esModule, firstIndex, second, 0, 4)) { - this.fireDebug(" Patching for VP at Offset: 0x{0}", (object) firstIndex.ToString("x8").ToUpper()); - esModule[firstIndex] = (byte) 224; + FireDebug(" Patching for VP at Offset: 0x{0}", (object)firstIndex.ToString("x8").ToUpper()); + esModule[firstIndex] = 224; firstIndex += 4; ++num; } } - this.fireDebug("Patching VP Finished... (Patches applied: {0})", (object) num); + FireDebug("Patching VP Finished... (Patches applied: {0})", (object)num); return num; } - private int patchAll(ref byte[] esModule) + private int PrivPatchAll(ref byte[] esModule) { - this.fireDebug("Patching Fakesigning, ES_Identify, NAND Permissions and VP ..."); + FireDebug("Patching Fakesigning, ES_Identify, NAND Permissions and VP ..."); int num = 0; byte[] second1 = new byte[4] { - (byte) 32, - (byte) 7, - (byte) 35, - (byte) 162 + 32, + 7, + 35, + 162 }; byte[] second2 = new byte[4] { - (byte) 32, - (byte) 7, - (byte) 75, - (byte) 11 + 32, + 7, + 75, + 11 }; byte[] second3 = new byte[4] { - (byte) 40, - (byte) 3, - (byte) 209, - (byte) 35 + 40, + 3, + 209, + 35 }; byte[] second4 = new byte[6] { - (byte) 66, - (byte) 139, - (byte) 208, - (byte) 1, - (byte) 37, - (byte) 102 + 66, + 139, + 208, + 1, + 37, + 102 }; byte[] second5 = new byte[4] { - (byte) 210, - (byte) 1, - (byte) 78, - (byte) 86 + 210, + 1, + 78, + 86 }; for (int firstIndex = 0; firstIndex < esModule.Length - 6; ++firstIndex) { - this.fireProgress((firstIndex + 1) * 100 / esModule.Length); + FireProgress((firstIndex + 1) * 100 / esModule.Length); if (Shared.CompareByteArrays(esModule, firstIndex, second1, 0, 4) || Shared.CompareByteArrays(esModule, firstIndex, second2, 0, 4)) { - this.fireDebug(" Patching Fakesigning at Offset: 0x{0}", (object) firstIndex.ToString("x8").ToUpper()); - esModule[firstIndex + 1] = (byte) 0; + FireDebug(" Patching Fakesigning at Offset: 0x{0}", (object)firstIndex.ToString("x8").ToUpper()); + esModule[firstIndex + 1] = 0; firstIndex += 4; ++num; } else if (Shared.CompareByteArrays(esModule, firstIndex, second3, 0, 4)) { - this.fireDebug(" Patching ES_Identify at Offset: 0x{0}", (object) firstIndex.ToString("x8").ToUpper()); - esModule[firstIndex + 2] = (byte) 0; - esModule[firstIndex + 3] = (byte) 0; + FireDebug(" Patching ES_Identify at Offset: 0x{0}", (object)firstIndex.ToString("x8").ToUpper()); + esModule[firstIndex + 2] = 0; + esModule[firstIndex + 3] = 0; firstIndex += 4; ++num; } else if (Shared.CompareByteArrays(esModule, firstIndex, second4, 0, 6)) { - this.fireDebug(" Patching NAND Permissions at Offset: 0x{0}", (object) firstIndex.ToString("x8").ToUpper()); - esModule[firstIndex + 2] = (byte) 224; + FireDebug(" Patching NAND Permissions at Offset: 0x{0}", (object)firstIndex.ToString("x8").ToUpper()); + esModule[firstIndex + 2] = 224; firstIndex += 6; ++num; } else if (Shared.CompareByteArrays(esModule, firstIndex, second5, 0, 4)) { - this.fireDebug(" Patching VP at Offset: 0x{0}", (object) firstIndex.ToString("x8").ToUpper()); - esModule[firstIndex] = (byte) 224; + FireDebug(" Patching VP at Offset: 0x{0}", (object)firstIndex.ToString("x8").ToUpper()); + esModule[firstIndex] = 224; firstIndex += 4; ++num; } } - this.fireDebug("Patching Fakesigning, ES_Identify, NAND Permissions and VP Finished... (Patches applied: {0})", (object) num); + FireDebug("Patching Fakesigning, ES_Identify, NAND Permissions and VP Finished... (Patches applied: {0})", (object)num); return num; } - private void getEsIndex() + private void GetEsIndex() { - this.fireDebug("Scanning for ES Module..."); + FireDebug("Scanning for ES Module..."); string str = "$IOSVersion:"; - for (int index1 = this.wadFile.NumOfContents - 1; index1 >= 0; --index1) + for (int index1 = wadFile.NumOfContents - 1; index1 >= 0; --index1) { - this.fireDebug(" Scanning Content #{0} of {1}...", (object) (index1 + 1), (object) this.wadFile.NumOfContents); - this.fireProgress((index1 + 1) * 100 / this.wadFile.NumOfContents); - for (int index2 = 0; index2 < this.wadFile.Contents[index1].Length - 64; ++index2) + FireDebug(" Scanning Content #{0} of {1}...", index1 + 1, wadFile.NumOfContents); + FireProgress((index1 + 1) * 100 / wadFile.NumOfContents); + for (int index2 = 0; index2 < wadFile.Contents[index1].Length - 64; ++index2) { - if (Encoding.ASCII.GetString(this.wadFile.Contents[index1], index2, 12) == str) + if (Encoding.ASCII.GetString(wadFile.Contents[index1], index2, 12) == str) { int index3 = index2 + 12; - while (this.wadFile.Contents[index1][index3] == (byte) 32) - ++index3; - if (Encoding.ASCII.GetString(this.wadFile.Contents[index1], index3, 3) == "ES:") + while (wadFile.Contents[index1][index3] == 32) { - this.fireDebug(" -> ES Module found!"); - this.fireDebug("Scanning for ES Module Finished..."); - this.esIndex = index1; - this.fireProgress(100); + ++index3; + } + + if (Encoding.ASCII.GetString(wadFile.Contents[index1], index3, 3) == "ES:") + { + FireDebug(" -> ES Module found!"); + FireDebug("Scanning for ES Module Finished..."); + esIndex = index1; + FireProgress(100); return; } } } } - this.fireDebug("/!\\/!\\/!\\ ES Module wasn't found! /!\\/!\\/!\\"); + FireDebug("/!\\/!\\/!\\ ES Module wasn't found! /!\\/!\\/!\\"); throw new Exception("ES module wasn't found!"); } #endregion @@ -315,20 +348,26 @@ namespace libWiiSharp /// Fires debugging messages. You may write them into a log file or log textbox. /// public event EventHandler Debug; - private void fireDebug(string debugMessage, params object[] args) + private void FireDebug(string debugMessage, params object[] args) { - EventHandler debug = this.Debug; + EventHandler debug = Debug; if (debug == null) + { return; + } + debug(new object(), new MessageEventArgs(string.Format(debugMessage, args))); } - private void fireProgress(int progressPercentage) + private void FireProgress(int progressPercentage) { - EventHandler progress = this.Progress; + EventHandler progress = Progress; if (progress == null) + { return; - progress(new object(), new ProgressChangedEventArgs(progressPercentage, (object) string.Empty)); + } + + progress(new object(), new ProgressChangedEventArgs(progressPercentage, string.Empty)); } #endregion } diff --git a/Lz77.cs b/Lz77.cs index 0fd79c3..428d136 100644 --- a/Lz77.cs +++ b/Lz77.cs @@ -9,352 +9,400 @@ using System.IO; namespace libWiiSharp { - public class Lz77 - { - private const int N = 4096; - private const int F = 18; - private const int threshold = 2; - private static uint lz77Magic = 1280980791; - private int[] leftSon = new int[4097]; - private int[] rightSon = new int[4353]; - private int[] dad = new int[4097]; - private ushort[] textBuffer = new ushort[4113]; - private int matchPosition; - private int matchLength; - - public static uint Lz77Magic => Lz77.lz77Magic; - - public static bool IsLz77Compressed(string file) => Lz77.IsLz77Compressed(File.ReadAllBytes(file)); - - public static bool IsLz77Compressed(byte[] file) + public class Lz77 { - Headers.HeaderType headerType = Headers.DetectHeader(file); - return (int) Shared.Swap(BitConverter.ToUInt32(file, (int) headerType)) == (int) Lz77.lz77Magic; - } + //private const int N = 4096; + //private const int F = 18; + //private const int threshold = 2; + private static readonly uint lz77Magic = 1280980791; + //private readonly int[] leftSon = new int[4097]; + //private readonly int[] rightSon = new int[4353]; + //private readonly int[] dad = new int[4097]; + private readonly ushort[] textBuffer = new ushort[4113]; + //private int matchPosition; + //private int matchLength; - 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) Lz77.lz77Magic; - } + public static uint Lz77Magic => Lz77.lz77Magic; - public void Compress(string inFile, string outFile) - { - Stream stream = (Stream) null; - using (FileStream fileStream = new FileStream(inFile, FileMode.Open)) - stream = this.compress((Stream) fileStream); - byte[] buffer = new byte[stream.Length]; - stream.Read(buffer, 0, buffer.Length); - if (File.Exists(outFile)) - File.Delete(outFile); - using (FileStream fileStream = new FileStream(outFile, FileMode.Create)) - fileStream.Write(buffer, 0, buffer.Length); - } - - public byte[] Compress(byte[] file) => ((MemoryStream) this.compress((Stream) new MemoryStream(file))).ToArray(); - - public Stream Compress(Stream file) => this.compress(file); - - public void Decompress(string inFile, string outFile) - { - Stream stream = (Stream) null; - using (FileStream fileStream = new FileStream(inFile, FileMode.Open)) - stream = this.decompress((Stream) fileStream); - byte[] buffer = new byte[stream.Length]; - stream.Read(buffer, 0, buffer.Length); - if (File.Exists(outFile)) - File.Delete(outFile); - using (FileStream fileStream = new FileStream(outFile, FileMode.Create)) - fileStream.Write(buffer, 0, buffer.Length); - } - - public byte[] Decompress(byte[] file) => ((MemoryStream) this.decompress((Stream) new MemoryStream(file))).ToArray(); - - public Stream Decompress(Stream file) => this.decompress(file); - - private Stream decompress(Stream inFile) - { - if (!Lz77.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) Lz77.lz77Magic) - { - inFile.Dispose(); - throw new Exception("Invaild Magic!"); - } - if (buffer[4] != (byte) 16) - { - inFile.Dispose(); - throw new Exception("Unsupported Compression Type!"); - } - uint num2 = BitConverter.ToUInt32(buffer, 4) >> 8; - for (int index = 0; index < 4078; ++index) - this.textBuffer[index] = (ushort) 223; - int num3 = 4078; - uint num4 = 7; - int num5 = 7; - MemoryStream memoryStream = new MemoryStream(); -label_10: - while (true) - { - num4 <<= 1; - ++num5; - if (num5 == 8) + public static bool IsLz77Compressed(string file) { - int num6; - if ((num6 = inFile.ReadByte()) != -1) - { - num4 = (uint) num6; - num5 = 0; - } - else - goto label_24; + return Lz77.IsLz77Compressed(File.ReadAllBytes(file)); } - if (((int) num4 & 128) == 0) - { - int num6; - if ((long) (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 = (int) (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 = (int) 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 = (int) (byte) num8; - textBuffer[index2] = (ushort) num12; - num3 = num11 & 4095; - ++num1; - } - goto label_10; - } -label_24: - return (Stream) memoryStream; - } - private Stream compress(Stream inFile) - { - if (Lz77.IsLz77Compressed(inFile)) - return inFile; - inFile.Seek(0L, SeekOrigin.Begin); - int num1 = 0; - int[] numArray1 = new int[17]; - uint num2 = (uint) (((int) Convert.ToUInt32(inFile.Length) << 8) + 16); - MemoryStream memoryStream = new MemoryStream(); - memoryStream.Write(BitConverter.GetBytes(Shared.Swap(Lz77.lz77Magic)), 0, 4); - memoryStream.Write(BitConverter.GetBytes(num2), 0, 4); - this.InitTree(); - numArray1[0] = 0; - int num3 = 1; - int num4 = 128; - int p = 0; - int r = 4078; - for (int index = p; index < r; ++index) - this.textBuffer[index] = ushort.MaxValue; - int num5; - int num6; - for (num5 = 0; num5 < 18 && (num6 = inFile.ReadByte()) != -1; ++num5) - this.textBuffer[r + num5] = (ushort) num6; - if (num5 == 0) - return inFile; - for (int index = 1; index <= 18; ++index) - this.InsertNode(r - index); - this.InsertNode(r); - do - { - if (this.matchLength > num5) - this.matchLength = num5; - if (this.matchLength <= 2) + public static bool IsLz77Compressed(byte[] file) { - this.matchLength = 1; - numArray1[num3++] = (int) this.textBuffer[r]; + Headers.HeaderType headerType = Headers.DetectHeader(file); + return (int)Shared.Swap(BitConverter.ToUInt32(file, (int)headerType)) == (int)Lz77.lz77Magic; } - else + + public static bool IsLz77Compressed(Stream file) { - numArray1[0] |= num4; - int[] numArray2 = numArray1; - int index1 = num3; - int num7 = index1 + 1; - int num8 = (int) (ushort) (r - this.matchPosition - 1 >> 8 & 15) | this.matchLength - 3 << 4; - numArray2[index1] = num8; - int[] numArray3 = numArray1; - int index2 = num7; - num3 = index2 + 1; - int num9 = (int) (ushort) (r - this.matchPosition - 1 & (int) byte.MaxValue); - numArray3[index2] = num9; + 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)Lz77.lz77Magic; } - if ((num4 >>= 1) == 0) + + public void Compress(string inFile, string outFile) { - for (int index = 0; index < num3; ++index) - memoryStream.WriteByte((byte) numArray1[index]); - num1 += num3; - numArray1[0] = 0; - num3 = 1; - num4 = 128; + Stream stream = null; + using (FileStream fileStream = new FileStream(inFile, FileMode.Open)) + { + stream = Compress(fileStream); + } + + byte[] buffer = new byte[stream.Length]; + stream.Read(buffer, 0, buffer.Length); + if (File.Exists(outFile)) + { + File.Delete(outFile); + } + + using (FileStream fileStream = new FileStream(outFile, FileMode.Create)) + { + fileStream.Write(buffer, 0, buffer.Length); + } } - int matchLength = this.matchLength; - int num10; - int num11; - for (num10 = 0; num10 < matchLength && (num11 = inFile.ReadByte()) != -1; ++num10) + + public byte[] Compress(byte[] file) { - this.DeleteNode(p); - this.textBuffer[p] = (ushort) num11; - if (p < 17) - this.textBuffer[p + 4096] = (ushort) num11; - p = p + 1 & 4095; - r = r + 1 & 4095; - this.InsertNode(r); + return ((MemoryStream)Compress(new MemoryStream(file))).ToArray(); } - while (num10++ < matchLength) + + public Stream Compress(Stream file) { - this.DeleteNode(p); - p = p + 1 & 4095; - r = r + 1 & 4095; - if (--num5 != 0) + return Compress(file); + } + + public void Decompress(string inFile, string outFile) + { + Stream stream = null; + using (FileStream fileStream = new FileStream(inFile, FileMode.Open)) + { + stream = Decompress(fileStream); + } + + byte[] buffer = new byte[stream.Length]; + stream.Read(buffer, 0, buffer.Length); + if (File.Exists(outFile)) + { + File.Delete(outFile); + } + + using (FileStream fileStream = new FileStream(outFile, FileMode.Create)) + { + fileStream.Write(buffer, 0, buffer.Length); + } + } + + public byte[] Decompress(byte[] file) + { + return ((MemoryStream)PrivDecompress(new MemoryStream(file))).ToArray(); + } + + public Stream Decompress(Stream file) + { + return PrivDecompress(file); + } + + private Stream PrivDecompress(Stream inFile) + { + if (!Lz77.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)Lz77.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 PrivCompress(Stream inFile) + { + if (Lz77.IsLz77Compressed(inFile)) + return inFile; + inFile.Seek(0L, SeekOrigin.Begin); + int num1 = 0; + int[] numArray1 = new int[17]; + uint num2 = (uint)(((int)Convert.ToUInt32(inFile.Length) << 8) + 16); + MemoryStream memoryStream = new MemoryStream(); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(Lz77.lz77Magic)), 0, 4); + memoryStream.Write(BitConverter.GetBytes(num2), 0, 4); + this.InitTree(); + numArray1[0] = 0; + int num3 = 1; + int num4 = 128; + int p = 0; + int r = 4078; + for (int index = p; index < r; ++index) + this.textBuffer[index] = ushort.MaxValue; + int num5; + int num6; + for (num5 = 0; num5 < 18 && (num6 = inFile.ReadByte()) != -1; ++num5) + this.textBuffer[r + num5] = (ushort)num6; + if (num5 == 0) + return inFile; + for (int index = 1; index <= 18; ++index) + this.InsertNode(r - index); this.InsertNode(r); - } - } - while (num5 > 0); - if (num3 > 1) - { - for (int index = 0; index < num3; ++index) - memoryStream.WriteByte((byte) numArray1[index]); - num1 += num3; - } - if (num1 % 4 != 0) - { - for (int index = 0; index < 4 - num1 % 4; ++index) - memoryStream.WriteByte((byte) 0); - } - return (Stream) memoryStream; - } - - private void InitTree() - { - for (int index = 4097; index <= 4352; ++index) - this.rightSon[index] = 4096; - for (int index = 0; index < 4096; ++index) - this.dad[index] = 4096; - } - - private void InsertNode(int r) - { - int num1 = 1; - int index = 4097 + (this.textBuffer[r] != ushort.MaxValue ? (int) this.textBuffer[r] : 0); - this.rightSon[r] = this.leftSon[r] = 4096; - this.matchLength = 0; - int num2; - do - { - do - { - if (num1 >= 0) - { - if (this.rightSon[index] == 4096) + do { - this.rightSon[index] = r; - this.dad[r] = index; - return; + if (this.matchLength > num5) + this.matchLength = num5; + if (this.matchLength <= 2) + { + this.matchLength = 1; + numArray1[num3++] = (int)this.textBuffer[r]; + } + else + { + numArray1[0] |= num4; + int[] numArray2 = numArray1; + int index1 = num3; + int num7 = index1 + 1; + int num8 = (int)(ushort)(r - this.matchPosition - 1 >> 8 & 15) | this.matchLength - 3 << 4; + numArray2[index1] = num8; + int[] numArray3 = numArray1; + int index2 = num7; + num3 = index2 + 1; + int num9 = (int)(ushort)(r - this.matchPosition - 1 & (int)byte.MaxValue); + numArray3[index2] = num9; + } + if ((num4 >>= 1) == 0) + { + for (int index = 0; index < num3; ++index) + memoryStream.WriteByte((byte)numArray1[index]); + num1 += num3; + numArray1[0] = 0; + num3 = 1; + num4 = 128; + } + int matchLength = this.matchLength; + int num10; + int num11; + for (num10 = 0; num10 < matchLength && (num11 = inFile.ReadByte()) != -1; ++num10) + { + this.DeleteNode(p); + this.textBuffer[p] = (ushort)num11; + if (p < 17) + this.textBuffer[p + 4096] = (ushort)num11; + p = p + 1 & 4095; + r = r + 1 & 4095; + this.InsertNode(r); + } + while (num10++ < matchLength) + { + this.DeleteNode(p); + p = p + 1 & 4095; + r = r + 1 & 4095; + if (--num5 != 0) + this.InsertNode(r); + } } - index = this.rightSon[index]; - } - else - { - if (this.leftSon[index] == 4096) + while (num5 > 0); + if (num3 > 1) { - this.leftSon[index] = r; - this.dad[r] = index; - return; + for (int index = 0; index < num3; ++index) + memoryStream.WriteByte((byte)numArray1[index]); + num1 += num3; } - index = this.leftSon[index]; - } - num2 = 1; - while (num2 < 18 && (num1 = (int) this.textBuffer[r + num2] - (int) this.textBuffer[index + num2]) == 0) - ++num2; + if (num1 % 4 != 0) + { + for (int index = 0; index < 4 - num1 % 4; ++index) + memoryStream.WriteByte((byte)0); + } + return (Stream)memoryStream; } - while (num2 <= this.matchLength); - this.matchPosition = index; - } - while ((this.matchLength = num2) < 18); - this.dad[r] = this.dad[index]; - this.leftSon[r] = this.leftSon[index]; - this.rightSon[r] = this.rightSon[index]; - this.dad[this.leftSon[index]] = r; - this.dad[this.rightSon[index]] = r; - if (this.rightSon[this.dad[index]] == index) - this.rightSon[this.dad[index]] = r; - else - this.leftSon[this.dad[index]] = r; - this.dad[index] = 4096; - } - private void DeleteNode(int p) - { - if (this.dad[p] == 4096) - return; - int index; - if (this.rightSon[p] == 4096) - index = this.leftSon[p]; - else if (this.leftSon[p] == 4096) - { - index = this.rightSon[p]; - } - else - { - index = this.leftSon[p]; - if (this.rightSon[index] != 4096) + private void InitTree() { - do - { - index = this.rightSon[index]; - } - while (this.rightSon[index] != 4096); - this.rightSon[this.dad[index]] = this.leftSon[index]; - this.dad[this.leftSon[index]] = this.dad[index]; - this.leftSon[index] = this.leftSon[p]; - this.dad[this.leftSon[p]] = index; + for (int index = 4097; index <= 4352; ++index) + this.rightSon[index] = 4096; + for (int index = 0; index < 4096; ++index) + this.dad[index] = 4096; } - this.rightSon[index] = this.rightSon[p]; - this.dad[this.rightSon[p]] = index; - } - this.dad[index] = this.dad[p]; - if (this.rightSon[this.dad[p]] == p) - this.rightSon[this.dad[p]] = index; - else - this.leftSon[this.dad[p]] = index; - this.dad[p] = 4096; + private void InsertNode(int r) + { + int num1 = 1; + int index = 4097 + (this.textBuffer[r] != ushort.MaxValue ? (int)this.textBuffer[r] : 0); + this.rightSon[r] = this.leftSon[r] = 4096; + this.matchLength = 0; + int num2; + do + { + do + { + if (num1 >= 0) + { + if (this.rightSon[index] == 4096) + { + this.rightSon[index] = r; + this.dad[r] = index; + return; + } + index = this.rightSon[index]; + } + else + { + if (this.leftSon[index] == 4096) + { + this.leftSon[index] = r; + this.dad[r] = index; + return; + } + index = this.leftSon[index]; + } + num2 = 1; + while (num2 < 18 && (num1 = (int)this.textBuffer[r + num2] - (int)this.textBuffer[index + num2]) == 0) + ++num2; + } + while (num2 <= this.matchLength); + this.matchPosition = index; + } + while ((this.matchLength = num2) < 18); + this.dad[r] = this.dad[index]; + this.leftSon[r] = this.leftSon[index]; + this.rightSon[r] = this.rightSon[index]; + this.dad[this.leftSon[index]] = r; + this.dad[this.rightSon[index]] = r; + if (this.rightSon[this.dad[index]] == index) + this.rightSon[this.dad[index]] = r; + else + this.leftSon[this.dad[index]] = r; + this.dad[index] = 4096; + } + private void DeleteNode(int p) + { + if (this.dad[p] == 4096) + return; + int index; + if (this.rightSon[p] == 4096) + index = this.leftSon[p]; + else if (this.leftSon[p] == 4096) + { + index = this.rightSon[p]; + } + else + { + index = this.leftSon[p]; + if (this.rightSon[index] != 4096) + { + do + { + index = this.rightSon[index]; + } + while (this.rightSon[index] != 4096); + this.rightSon[this.dad[index]] = this.leftSon[index]; + this.dad[this.leftSon[index]] = this.dad[index]; + this.leftSon[index] = this.leftSon[p]; + this.dad[this.leftSon[p]] = index; + } + this.rightSon[index] = this.rightSon[p]; + this.dad[this.rightSon[p]] = index; + } + this.dad[index] = this.dad[p]; + if (this.rightSon[this.dad[p]] == p) + this.rightSon[this.dad[p]] = index; + else + this.leftSon[this.dad[p]] = index; + this.dad[p] = 4096; + } + */ } - } } diff --git a/MessageEventArgs.cs b/MessageEventArgs.cs index cc07d39..cd389f8 100644 --- a/MessageEventArgs.cs +++ b/MessageEventArgs.cs @@ -8,12 +8,15 @@ using System; namespace libWiiSharp { - public class MessageEventArgs : EventArgs - { - private string message; + public class MessageEventArgs : EventArgs + { + private readonly string message; - public string Message => this.message; + public string Message => message; - public MessageEventArgs(string message) => this.message = message; - } + public MessageEventArgs(string message) + { + this.message = message; + } + } } diff --git a/NusClient.cs b/NusClient.cs index 45c0603..92121e3 100644 --- a/NusClient.cs +++ b/NusClient.cs @@ -13,424 +13,474 @@ using System.Security.Cryptography; namespace libWiiSharp { - public class NusClient : IDisposable - { - private const string nusUrl = "http://nus.cdn.shop.wii.com/ccs/download/"; - private WebClient wcNus = new WebClient(); - private bool useLocalFiles; - private bool continueWithoutTicket; - private bool isDisposed; - - public bool UseLocalFiles + public class NusClient : IDisposable { - get => this.useLocalFiles; - set => this.useLocalFiles = value; - } + private const string nusUrl = "http://nus.cdn.shop.wii.com/ccs/download/"; + private readonly WebClient wcNus = new WebClient(); + private bool useLocalFiles; + private bool continueWithoutTicket; + private bool isDisposed; - public bool ContinueWithoutTicket - { - get => this.continueWithoutTicket; - set => this.continueWithoutTicket = value; - } - - public event EventHandler Progress; - - public event EventHandler Debug; - - ~NusClient() => this.Dispose(false); - - public void Dispose() - { - this.Dispose(true); - GC.SuppressFinalize((object) this); - } - - protected virtual void Dispose(bool disposing) - { - if (disposing && !this.isDisposed) - this.wcNus.Dispose(); - this.isDisposed = true; - } - - public void DownloadTitle( - string titleId, - string titleVersion, - string outputDir, - params StoreType[] storeTypes) - { - if (titleId.Length != 16) - throw new Exception("Title ID must be 16 characters long!"); - this.downloadTitle(titleId, titleVersion, outputDir, storeTypes); - } - - public TMD DownloadTMD(string titleId, string titleVersion) => titleId.Length == 16 ? this.downloadTmd(titleId, titleVersion) : throw new Exception("Title ID must be 16 characters long!"); - - public Ticket DownloadTicket(string titleId) => titleId.Length == 16 ? this.downloadTicket(titleId) : throw new Exception("Title ID must be 16 characters long!"); - - public byte[] DownloadSingleContent(string titleId, string titleVersion, string contentId) - { - if (titleId.Length != 16) - throw new Exception("Title ID must be 16 characters long!"); - return this.downloadSingleContent(titleId, titleVersion, contentId); - } - - public void DownloadSingleContent( - string titleId, - string titleVersion, - string contentId, - string savePath) - { - if (titleId.Length != 16) - throw new Exception("Title ID must be 16 characters long!"); - if (!Directory.Exists(Path.GetDirectoryName(savePath))) - Directory.CreateDirectory(Path.GetDirectoryName(savePath)); - if (System.IO.File.Exists(savePath)) - System.IO.File.Delete(savePath); - byte[] bytes = this.downloadSingleContent(titleId, titleVersion, contentId); - System.IO.File.WriteAllBytes(savePath, bytes); - } - - private byte[] downloadSingleContent(string titleId, string titleVersion, string contentId) - { - uint num = uint.Parse(contentId, NumberStyles.HexNumber); - contentId = num.ToString("x8"); - this.fireDebug("Downloading Content (Content ID: {0}) of Title {1} v{2}...", (object) contentId, (object) titleId, string.IsNullOrEmpty(titleVersion) ? (object) "[Latest]" : (object) titleVersion); - this.fireDebug(" Checking for Internet connection..."); - if (!this.CheckInet()) - { - this.fireDebug(" Connection not found..."); - throw new Exception("You're not connected to the internet!"); - } - this.fireProgress(0); - string str1 = "tmd" + (string.IsNullOrEmpty(titleVersion) ? string.Empty : "." + titleVersion); - string str2 = string.Format("{0}{1}/", (object) "http://nus.cdn.shop.wii.com/ccs/download/", (object) titleId); - string empty = string.Empty; - int contentIndex = 0; - this.fireDebug(" Downloading TMD..."); - byte[] tmdFile = this.wcNus.DownloadData(str2 + str1); - this.fireDebug(" Parsing TMD..."); - TMD tmd = TMD.Load(tmdFile); - this.fireProgress(20); - this.fireDebug(" Looking for Content ID {0} in TMD...", (object) contentId); - bool flag = false; - for (int index = 0; index < tmd.Contents.Length; ++index) - { - if ((int) tmd.Contents[index].ContentID == (int) num) + public bool UseLocalFiles { - this.fireDebug(" Content ID {0} found in TMD...", (object) contentId); - flag = true; - empty = tmd.Contents[index].ContentID.ToString("x8"); - contentIndex = index; - break; + get => useLocalFiles; + set => useLocalFiles = value; } - } - if (!flag) - { - this.fireDebug(" Content ID {0} wasn't found in TMD...", (object) contentId); - throw new Exception("Content ID wasn't found in the TMD!"); - } - if (!File.Exists("cetk")) - { - fireDebug(" Downloading Ticket..."); - byte[] tikArray = wcNus.DownloadData(str2 + "cetk"); - Console.WriteLine("Downloading"); - } - Console.WriteLine("Continuing"); - this.fireDebug("Parsing Ticket..."); - Ticket tik = Ticket.Load("cetk"); - this.fireProgress(40); - this.fireDebug(" Downloading Content... ({0} bytes)", (object) tmd.Contents[contentIndex].Size); - byte[] content = this.wcNus.DownloadData(str2 + empty); - this.fireProgress(80); - this.fireDebug(" Decrypting Content..."); - byte[] array = this.decryptContent(content, contentIndex, tik, tmd); - Array.Resize(ref array, (int) tmd.Contents[contentIndex].Size); - if (!Shared.CompareByteArrays(SHA1.Create().ComputeHash(array), tmd.Contents[contentIndex].Hash)) - { - this.fireDebug("/!\\ /!\\ /!\\ Hashes do not match /!\\ /!\\ /!\\"); - throw new Exception("Hashes do not match!"); - } - this.fireProgress(100); - this.fireDebug("Downloading Content (Content ID: {0}) of Title {1} v{2} Finished...", (object) contentId, (object) titleId, string.IsNullOrEmpty(titleVersion) ? (object) "[Latest]" : (object) titleVersion); - return array; - } - private Ticket downloadTicket(string titleId) - { - if (!CheckInet()) - throw new Exception("You're not connected to the internet!"); - - string titleUrl = string.Format("{0}{1}/", nusUrl, titleId); - byte[] tikArray = wcNus.DownloadData(titleUrl + "cetk"); - - return Ticket.Load(tikArray); - } - - private TMD downloadTmd(string titleId, string titleVersion) - { - if (!this.CheckInet()) - throw new Exception("You're not connected to the internet!"); - return TMD.Load(this.wcNus.DownloadData(string.Format("{0}{1}/", (object) "http://nus.cdn.shop.wii.com/ccs/download/", (object) titleId) + ("tmd" + (string.IsNullOrEmpty(titleVersion) ? string.Empty : "." + titleVersion)))); - } - - private void downloadTitle( - string titleId, - string titleVersion, - string outputDir, - StoreType[] storeTypes) - { - this.fireDebug("Downloading Title {0} v{1}...", (object) titleId, string.IsNullOrEmpty(titleVersion) ? (object) "[Latest]" : (object) titleVersion); - if (storeTypes.Length < 1) - { - this.fireDebug(" No store types were defined..."); - throw new Exception("You must at least define one store type!"); - } - string str1 = string.Format("{0}{1}/", (object) "http://nus.cdn.shop.wii.com/ccs/download/", (object) titleId); - bool flag1 = false; - bool flag2 = false; - bool flag3 = false; - this.fireProgress(0); - for (int index = 0; index < storeTypes.Length; ++index) - { - switch (storeTypes[index]) + public bool ContinueWithoutTicket { - case StoreType.EncryptedContent: - this.fireDebug(" -> Storing Encrypted Content..."); - flag1 = true; - break; - case StoreType.DecryptedContent: - this.fireDebug(" -> Storing Decrypted Content..."); - flag2 = true; - break; - case StoreType.WAD: - this.fireDebug(" -> Storing WAD..."); - flag3 = true; - break; - case StoreType.All: - this.fireDebug(" -> Storing Decrypted Content..."); - this.fireDebug(" -> Storing Encrypted Content..."); - this.fireDebug(" -> Storing WAD..."); - flag2 = true; - flag1 = true; - flag3 = true; - break; + get => continueWithoutTicket; + set => continueWithoutTicket = value; } - } - this.fireDebug(" Checking for Internet connection..."); - if (!this.CheckInet()) - { - this.fireDebug(" Connection not found..."); - throw new Exception("You're not connected to the internet!"); - } - if ((int) outputDir[outputDir.Length - 1] != (int) Path.DirectorySeparatorChar) - outputDir += Path.DirectorySeparatorChar.ToString(); - if (!Directory.Exists(outputDir)) - Directory.CreateDirectory(outputDir); - string str2 = "tmd" + (string.IsNullOrEmpty(titleVersion) ? string.Empty : "." + titleVersion); - this.fireDebug(" Downloading TMD..."); - try - { - this.wcNus.DownloadFile(str1 + str2, outputDir + str2); - } - catch (Exception ex) - { - this.fireDebug(" Downloading TMD Failed..."); - throw new Exception("Downloading TMD Failed:\n" + ex.Message); - } - if (!File.Exists(outputDir + "cetk")) - { - //Download cetk - fireDebug(" Downloading Ticket..."); - try + public event EventHandler Progress; + + public event EventHandler Debug; + + ~NusClient() => Dispose(false); + + public void Dispose() { - wcNus.DownloadFile(string.Format("{0}{1}/", nusUrl, titleId) + "cetk", outputDir + "cetk"); + Dispose(true); + GC.SuppressFinalize(this); } - catch (Exception ex) + + protected virtual void Dispose(bool disposing) { - if (!continueWithoutTicket || !flag1) + if (disposing && !isDisposed) { - fireDebug(" Downloading Ticket Failed..."); - throw new Exception("CETK Doesn't Exist and Downloading Ticket Failed:\n" + ex.Message); + wcNus.Dispose(); } - flag2 = false; - flag3 = false; + isDisposed = true; } - } + + public void DownloadTitle( + string titleId, + string titleVersion, + string outputDir, + params StoreType[] storeTypes) + { + if (titleId.Length != 16) + { + throw new Exception("Title ID must be 16 characters long!"); + } + + PrivDownloadTitle(titleId, titleVersion, outputDir, storeTypes); + } + + public TMD DownloadTMD(string titleId, string titleVersion) + { + return titleId.Length == 16 ? DownloadTmd(titleId, titleVersion) : throw new Exception("Title ID must be 16 characters long!"); + } + + public Ticket DownloadTicket(string titleId) + { + return titleId.Length == 16 ? PrivDownloadTicket(titleId) : throw new Exception("Title ID must be 16 characters long!"); + } + + public byte[] DownloadSingleContent(string titleId, string titleVersion, string contentId) + { + if (titleId.Length != 16) + { + throw new Exception("Title ID must be 16 characters long!"); + } + + return PrivDownloadSingleContent(titleId, titleVersion, contentId); + } + + public void DownloadSingleContent( + string titleId, + string titleVersion, + string contentId, + string savePath) + { + if (titleId.Length != 16) + { + throw new Exception("Title ID must be 16 characters long!"); + } + + if (!Directory.Exists(Path.GetDirectoryName(savePath))) + { + Directory.CreateDirectory(Path.GetDirectoryName(savePath)); + } + + if (System.IO.File.Exists(savePath)) + { + System.IO.File.Delete(savePath); + } + + byte[] bytes = PrivDownloadSingleContent(titleId, titleVersion, contentId); + System.IO.File.WriteAllBytes(savePath, bytes); + } + + private byte[] PrivDownloadSingleContent(string titleId, string titleVersion, string contentId) + { + uint num = uint.Parse(contentId, NumberStyles.HexNumber); + contentId = num.ToString("x8"); + FireDebug("Downloading Content (Content ID: {0}) of Title {1} v{2}...", contentId, titleId, string.IsNullOrEmpty(titleVersion) ? "[Latest]" : titleVersion); + FireDebug(" Checking for Internet connection..."); + if (!CheckInet()) + { + FireDebug(" Connection not found..."); + throw new Exception("You're not connected to the internet!"); + } + FireProgress(0); + string str1 = "tmd" + (string.IsNullOrEmpty(titleVersion) ? string.Empty : "." + titleVersion); + string str2 = string.Format("{0}{1}/", "http://nus.cdn.shop.wii.com/ccs/download/", titleId); + string empty = string.Empty; + int contentIndex = 0; + FireDebug(" Downloading TMD..."); + byte[] tmdFile = wcNus.DownloadData(str2 + str1); + FireDebug(" Parsing TMD..."); + TMD tmd = TMD.Load(tmdFile); + FireProgress(20); + FireDebug(" Looking for Content ID {0} in TMD...", (object)contentId); + bool flag = false; + for (int index = 0; index < tmd.Contents.Length; ++index) + { + if ((int)tmd.Contents[index].ContentID == (int)num) + { + FireDebug(" Content ID {0} found in TMD...", (object)contentId); + flag = true; + empty = tmd.Contents[index].ContentID.ToString("x8"); + contentIndex = index; + break; + } + } + if (!flag) + { + FireDebug(" Content ID {0} wasn't found in TMD...", (object)contentId); + throw new Exception("Content ID wasn't found in the TMD!"); + } + if (!File.Exists("cetk")) + { + FireDebug(" Downloading Ticket..."); + //byte[] tikArray = wcNus.DownloadData(str2 + "cetk"); + Console.WriteLine("Downloading"); + } + Console.WriteLine("Continuing"); + FireDebug("Parsing Ticket..."); + Ticket tik = Ticket.Load("cetk"); + FireProgress(40); + FireDebug(" Downloading Content... ({0} bytes)", (object)tmd.Contents[contentIndex].Size); + byte[] content = wcNus.DownloadData(str2 + empty); + FireProgress(80); + FireDebug(" Decrypting Content..."); + byte[] array = DecryptContent(content, contentIndex, tik, tmd); + Array.Resize(ref array, (int)tmd.Contents[contentIndex].Size); + if (!Shared.CompareByteArrays(SHA1.Create().ComputeHash(array), tmd.Contents[contentIndex].Hash)) + { + FireDebug("/!\\ /!\\ /!\\ Hashes do not match /!\\ /!\\ /!\\"); + throw new Exception("Hashes do not match!"); + } + FireProgress(100); + FireDebug("Downloading Content (Content ID: {0}) of Title {1} v{2} Finished...", contentId, titleId, string.IsNullOrEmpty(titleVersion) ? "[Latest]" : titleVersion); + return array; + } + + private Ticket PrivDownloadTicket(string titleId) + { + if (!CheckInet()) + { + throw new Exception("You're not connected to the internet!"); + } + + string titleUrl = string.Format("{0}{1}/", nusUrl, titleId); + byte[] tikArray = wcNus.DownloadData(titleUrl + "cetk"); + + return Ticket.Load(tikArray); + } + + private TMD DownloadTmd(string titleId, string titleVersion) + { + if (!CheckInet()) + { + throw new Exception("You're not connected to the internet!"); + } + + return TMD.Load(wcNus.DownloadData(string.Format("{0}{1}/", "http://nus.cdn.shop.wii.com/ccs/download/", titleId) + ("tmd" + (string.IsNullOrEmpty(titleVersion) ? string.Empty : "." + titleVersion)))); + } + + private void PrivDownloadTitle( + string titleId, + string titleVersion, + string outputDir, + StoreType[] storeTypes) + { + FireDebug("Downloading Title {0} v{1}...", titleId, string.IsNullOrEmpty(titleVersion) ? "[Latest]" : titleVersion); + if (storeTypes.Length < 1) + { + FireDebug(" No store types were defined..."); + throw new Exception("You must at least define one store type!"); + } + string str1 = string.Format("{0}{1}/", "http://nus.cdn.shop.wii.com/ccs/download/", titleId); + bool flag1 = false; + bool flag2 = false; + bool flag3 = false; + FireProgress(0); + for (int index = 0; index < storeTypes.Length; ++index) + { + switch (storeTypes[index]) + { + case StoreType.EncryptedContent: + FireDebug(" -> Storing Encrypted Content..."); + flag1 = true; + break; + case StoreType.DecryptedContent: + FireDebug(" -> Storing Decrypted Content..."); + flag2 = true; + break; + case StoreType.WAD: + FireDebug(" -> Storing WAD..."); + flag3 = true; + break; + case StoreType.All: + FireDebug(" -> Storing Decrypted Content..."); + FireDebug(" -> Storing Encrypted Content..."); + FireDebug(" -> Storing WAD..."); + flag2 = true; + flag1 = true; + flag3 = true; + break; + } + } + FireDebug(" Checking for Internet connection..."); + if (!CheckInet()) + { + FireDebug(" Connection not found..."); + throw new Exception("You're not connected to the internet!"); + } + if (outputDir[outputDir.Length - 1] != Path.DirectorySeparatorChar) + { + outputDir += Path.DirectorySeparatorChar.ToString(); + } + + if (!Directory.Exists(outputDir)) + { + Directory.CreateDirectory(outputDir); + } + + string str2 = "tmd" + (string.IsNullOrEmpty(titleVersion) ? string.Empty : "." + titleVersion); + FireDebug(" Downloading TMD..."); + try + { + wcNus.DownloadFile(str1 + str2, outputDir + str2); + } + catch (Exception ex) + { + FireDebug(" Downloading TMD Failed..."); + throw new Exception("Downloading TMD Failed:\n" + ex.Message); + } + + if (!File.Exists(outputDir + "cetk")) + { + //Download cetk + FireDebug(" Downloading Ticket..."); + try + { + wcNus.DownloadFile(string.Format("{0}{1}/", nusUrl, titleId) + "cetk", outputDir + "cetk"); + } + catch (Exception ex) + { + if (!continueWithoutTicket || !flag1) + { + FireDebug(" Downloading Ticket Failed..."); + throw new Exception("CETK Doesn't Exist and Downloading Ticket Failed:\n" + ex.Message); + } + + flag2 = false; + flag3 = false; + } + } - this.fireProgress(10); - this.fireDebug(" Parsing TMD..."); - TMD tmd = TMD.Load(outputDir + str2); - if (string.IsNullOrEmpty(titleVersion)) - this.fireDebug(" -> Title Version: {0}", (object) tmd.TitleVersion); - this.fireDebug(" -> {0} Contents", (object) tmd.NumOfContents); - this.fireDebug(" Parsing Ticket..."); - Ticket tik = Ticket.Load(outputDir + "cetk"); - string[] strArray1 = new string[(int) tmd.NumOfContents]; - uint contentId; - for (int index1 = 0; index1 < (int) tmd.NumOfContents; ++index1) - { - this.fireDebug(" Downloading Content #{0} of {1}... ({2} bytes)", (object) (index1 + 1), (object) tmd.NumOfContents, (object) tmd.Contents[index1].Size); - this.fireProgress((index1 + 1) * 60 / (int) tmd.NumOfContents + 10); - if (this.useLocalFiles) - { - string str3 = outputDir; - contentId = tmd.Contents[index1].ContentID; - string str4 = contentId.ToString("x8"); - if (System.IO.File.Exists(str3 + str4)) - { - this.fireDebug(" Using Local File, Skipping..."); - continue; - } + FireProgress(10); + FireDebug(" Parsing TMD..."); + TMD tmd = TMD.Load(outputDir + str2); + if (string.IsNullOrEmpty(titleVersion)) + { + FireDebug(" -> Title Version: {0}", (object)tmd.TitleVersion); + } + + FireDebug(" -> {0} Contents", (object)tmd.NumOfContents); + FireDebug(" Parsing Ticket..."); + Ticket tik = Ticket.Load(outputDir + "cetk"); + string[] strArray1 = new string[tmd.NumOfContents]; + uint contentId; + for (int index1 = 0; index1 < tmd.NumOfContents; ++index1) + { + FireDebug(" Downloading Content #{0} of {1}... ({2} bytes)", index1 + 1, tmd.NumOfContents, tmd.Contents[index1].Size); + FireProgress((index1 + 1) * 60 / tmd.NumOfContents + 10); + if (useLocalFiles) + { + string str3 = outputDir; + contentId = tmd.Contents[index1].ContentID; + string str4 = contentId.ToString("x8"); + if (System.IO.File.Exists(str3 + str4)) + { + FireDebug(" Using Local File, Skipping..."); + continue; + } + } + try + { + WebClient wcNus = this.wcNus; + string str3 = str1; + contentId = tmd.Contents[index1].ContentID; + string str4 = contentId.ToString("x8"); + string address = str3 + str4; + string str5 = outputDir; + contentId = tmd.Contents[index1].ContentID; + string str6 = contentId.ToString("x8"); + string fileName = str5 + str6; + wcNus.DownloadFile(address, fileName); + string[] strArray2 = strArray1; + int index2 = index1; + contentId = tmd.Contents[index1].ContentID; + string str7 = contentId.ToString("x8"); + strArray2[index2] = str7; + } + catch (Exception ex) + { + FireDebug(" Downloading Content #{0} of {1} failed...", index1 + 1, tmd.NumOfContents); + throw new Exception("Downloading Content Failed:\n" + ex.Message); + } + } + if (flag2 | flag3) + { + SHA1 shA1 = SHA1.Create(); + for (int contentIndex = 0; contentIndex < tmd.NumOfContents; ++contentIndex) + { + FireDebug(" Decrypting Content #{0} of {1}...", contentIndex + 1, tmd.NumOfContents); + FireProgress((contentIndex + 1) * 20 / tmd.NumOfContents + 75); + string str3 = outputDir; + contentId = tmd.Contents[contentIndex].ContentID; + string str4 = contentId.ToString("x8"); + byte[] array = DecryptContent(System.IO.File.ReadAllBytes(str3 + str4), contentIndex, tik, tmd); + Array.Resize(ref array, (int)tmd.Contents[contentIndex].Size); + if (!Shared.CompareByteArrays(shA1.ComputeHash(array), tmd.Contents[contentIndex].Hash)) + { + FireDebug("/!\\ /!\\ /!\\ Hashes do not match /!\\ /!\\ /!\\"); + throw new Exception(string.Format("Content #{0}: Hashes do not match!", contentIndex)); + } + string str5 = outputDir; + contentId = tmd.Contents[contentIndex].ContentID; + string str6 = contentId.ToString("x8"); + System.IO.File.WriteAllBytes(str5 + str6 + ".app", array); + } + shA1.Clear(); + } + if (flag3) + { + FireDebug(" Building Certificate Chain..."); + CertificateChain cert = CertificateChain.FromTikTmd(outputDir + "cetk", outputDir + str2); + byte[][] contents = new byte[tmd.NumOfContents][]; + for (int index1 = 0; index1 < tmd.NumOfContents; ++index1) + { + byte[][] numArray1 = contents; + int index2 = index1; + string str3 = outputDir; + contentId = tmd.Contents[index1].ContentID; + string str4 = contentId.ToString("x8"); + byte[] numArray2 = System.IO.File.ReadAllBytes(str3 + str4 + ".app"); + numArray1[index2] = numArray2; + } + FireDebug(" Creating WAD..."); + WAD.Create(cert, tik, tmd, contents).Save(outputDir + tmd.TitleID.ToString("x16") + "v" + tmd.TitleVersion.ToString() + ".wad"); + } + if (!flag1) + { + FireDebug(" Deleting Encrypted Contents..."); + for (int index = 0; index < strArray1.Length; ++index) + { + if (System.IO.File.Exists(outputDir + strArray1[index])) + { + System.IO.File.Delete(outputDir + strArray1[index]); + } + } + } + if (flag3 && !flag2) + { + FireDebug(" Deleting Decrypted Contents..."); + for (int index = 0; index < strArray1.Length; ++index) + { + if (System.IO.File.Exists(outputDir + strArray1[index] + ".app")) + { + System.IO.File.Delete(outputDir + strArray1[index] + ".app"); + } + } + } + if (!flag2 && !flag1) + { + FireDebug(" Deleting TMD and Ticket..."); + System.IO.File.Delete(outputDir + str2); + System.IO.File.Delete(outputDir + "cetk"); + } + FireDebug("Downloading Title {0} v{1} Finished...", titleId, string.IsNullOrEmpty(titleVersion) ? "[Latest]" : titleVersion); + FireProgress(100); } - try + + private byte[] DecryptContent(byte[] content, int contentIndex, Ticket tik, TMD tmd) { - WebClient wcNus = this.wcNus; - string str3 = str1; - contentId = tmd.Contents[index1].ContentID; - string str4 = contentId.ToString("x8"); - string address = str3 + str4; - string str5 = outputDir; - contentId = tmd.Contents[index1].ContentID; - string str6 = contentId.ToString("x8"); - string fileName = str5 + str6; - wcNus.DownloadFile(address, fileName); - string[] strArray2 = strArray1; - int index2 = index1; - contentId = tmd.Contents[index1].ContentID; - string str7 = contentId.ToString("x8"); - strArray2[index2] = str7; + Array.Resize(ref content, Shared.AddPadding(content.Length, 16)); + byte[] titleKey = tik.TitleKey; + byte[] numArray = new byte[16]; + byte[] bytes = BitConverter.GetBytes(tmd.Contents[contentIndex].Index); + numArray[0] = bytes[1]; + numArray[1] = bytes[0]; + RijndaelManaged rijndaelManaged = new RijndaelManaged + { + Mode = CipherMode.CBC, + Padding = PaddingMode.None, + KeySize = 128, + BlockSize = 128, + Key = titleKey, + IV = numArray + }; + ICryptoTransform decryptor = rijndaelManaged.CreateDecryptor(); + MemoryStream memoryStream = new MemoryStream(content); + CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read); + byte[] buffer = new byte[content.Length]; + cryptoStream.Read(buffer, 0, buffer.Length); + cryptoStream.Dispose(); + memoryStream.Dispose(); + return buffer; } - catch (Exception ex) + + private bool CheckInet() { - this.fireDebug(" Downloading Content #{0} of {1} failed...", (object) (index1 + 1), (object) tmd.NumOfContents); - throw new Exception("Downloading Content Failed:\n" + ex.Message); + try + { + Dns.GetHostEntry("www.google.com"); + return true; + } + catch + { + return false; + } } - } - if (flag2 | flag3) - { - SHA1 shA1 = SHA1.Create(); - for (int contentIndex = 0; contentIndex < (int) tmd.NumOfContents; ++contentIndex) + + private void FireDebug(string debugMessage, params object[] args) { - this.fireDebug(" Decrypting Content #{0} of {1}...", (object) (contentIndex + 1), (object) tmd.NumOfContents); - this.fireProgress((contentIndex + 1) * 20 / (int) tmd.NumOfContents + 75); - string str3 = outputDir; - contentId = tmd.Contents[contentIndex].ContentID; - string str4 = contentId.ToString("x8"); - byte[] array = this.decryptContent(System.IO.File.ReadAllBytes(str3 + str4), contentIndex, tik, tmd); - Array.Resize(ref array, (int) tmd.Contents[contentIndex].Size); - if (!Shared.CompareByteArrays(shA1.ComputeHash(array), tmd.Contents[contentIndex].Hash)) - { - this.fireDebug("/!\\ /!\\ /!\\ Hashes do not match /!\\ /!\\ /!\\"); - throw new Exception(string.Format("Content #{0}: Hashes do not match!", (object) contentIndex)); - } - string str5 = outputDir; - contentId = tmd.Contents[contentIndex].ContentID; - string str6 = contentId.ToString("x8"); - System.IO.File.WriteAllBytes(str5 + str6 + ".app", array); + EventHandler debug = Debug; + if (debug == null) + { + return; + } + + debug(new object(), new MessageEventArgs(string.Format(debugMessage, args))); } - shA1.Clear(); - } - if (flag3) - { - this.fireDebug(" Building Certificate Chain..."); - CertificateChain cert = CertificateChain.FromTikTmd(outputDir + "cetk", outputDir + str2); - byte[][] contents = new byte[(int) tmd.NumOfContents][]; - for (int index1 = 0; index1 < (int) tmd.NumOfContents; ++index1) + + private void FireProgress(int progressPercentage) { - byte[][] numArray1 = contents; - int index2 = index1; - string str3 = outputDir; - contentId = tmd.Contents[index1].ContentID; - string str4 = contentId.ToString("x8"); - byte[] numArray2 = System.IO.File.ReadAllBytes(str3 + str4 + ".app"); - numArray1[index2] = numArray2; + EventHandler progress = Progress; + if (progress == null) + { + return; + } + + progress(new object(), new ProgressChangedEventArgs(progressPercentage, string.Empty)); } - this.fireDebug(" Creating WAD..."); - WAD.Create(cert, tik, tmd, contents).Save(outputDir + tmd.TitleID.ToString("x16") + "v" + tmd.TitleVersion.ToString() + ".wad"); - } - if (!flag1) - { - this.fireDebug(" Deleting Encrypted Contents..."); - for (int index = 0; index < strArray1.Length; ++index) - { - if (System.IO.File.Exists(outputDir + strArray1[index])) - System.IO.File.Delete(outputDir + strArray1[index]); - } - } - if (flag3 && !flag2) - { - this.fireDebug(" Deleting Decrypted Contents..."); - for (int index = 0; index < strArray1.Length; ++index) - { - if (System.IO.File.Exists(outputDir + strArray1[index] + ".app")) - System.IO.File.Delete(outputDir + strArray1[index] + ".app"); - } - } - if (!flag2 && !flag1) - { - this.fireDebug(" Deleting TMD and Ticket..."); - System.IO.File.Delete(outputDir + str2); - System.IO.File.Delete(outputDir + "cetk"); - } - this.fireDebug("Downloading Title {0} v{1} Finished...", (object) titleId, string.IsNullOrEmpty(titleVersion) ? (object) "[Latest]" : (object) titleVersion); - this.fireProgress(100); } - - private byte[] decryptContent(byte[] content, int contentIndex, Ticket tik, TMD tmd) - { - Array.Resize(ref content, Shared.AddPadding(content.Length, 16)); - byte[] titleKey = tik.TitleKey; - byte[] numArray = new byte[16]; - byte[] bytes = BitConverter.GetBytes(tmd.Contents[contentIndex].Index); - numArray[0] = bytes[1]; - numArray[1] = bytes[0]; - RijndaelManaged rijndaelManaged = new RijndaelManaged(); - rijndaelManaged.Mode = CipherMode.CBC; - rijndaelManaged.Padding = PaddingMode.None; - rijndaelManaged.KeySize = 128; - rijndaelManaged.BlockSize = 128; - rijndaelManaged.Key = titleKey; - rijndaelManaged.IV = numArray; - ICryptoTransform decryptor = rijndaelManaged.CreateDecryptor(); - MemoryStream memoryStream = new MemoryStream(content); - CryptoStream cryptoStream = new CryptoStream((Stream) memoryStream, decryptor, CryptoStreamMode.Read); - byte[] buffer = new byte[content.Length]; - cryptoStream.Read(buffer, 0, buffer.Length); - cryptoStream.Dispose(); - memoryStream.Dispose(); - return buffer; - } - - private bool CheckInet() - { - try - { - Dns.GetHostEntry("www.google.com"); - return true; - } - catch - { - return false; - } - } - - private void fireDebug(string debugMessage, params object[] args) - { - EventHandler debug = this.Debug; - if (debug == null) - return; - debug(new object(), new MessageEventArgs(string.Format(debugMessage, args))); - } - - private void fireProgress(int progressPercentage) - { - EventHandler progress = this.Progress; - if (progress == null) - return; - progress(new object(), new ProgressChangedEventArgs(progressPercentage, (object) string.Empty)); - } - } } diff --git a/Region.cs b/Region.cs index d98312a..9e542db 100644 --- a/Region.cs +++ b/Region.cs @@ -6,11 +6,11 @@ namespace libWiiSharp { - public enum Region : ushort - { - Japan, - USA, - Europe, - Free, - } + public enum Region : ushort + { + Japan, + USA, + Europe, + Free, + } } diff --git a/Shared.cs b/Shared.cs index 7b36820..2bbe5e3 100644 --- a/Shared.cs +++ b/Shared.cs @@ -11,138 +11,185 @@ using System.Net; namespace libWiiSharp { - public static class Shared - { - public static string[] MergeStringArrays(string[] a, string[] b) + public static class Shared { - List stringList = new List((IEnumerable) a); - foreach (string str in b) - { - if (!stringList.Contains(str)) - stringList.Add(str); - } - stringList.Sort(); - return stringList.ToArray(); + public static string[] MergeStringArrays(string[] a, string[] b) + { + List stringList = new List(a); + foreach (string str in b) + { + if (!stringList.Contains(str)) + { + stringList.Add(str); + } + } + stringList.Sort(); + return stringList.ToArray(); + } + + public static bool CompareByteArrays( + byte[] first, + int firstIndex, + byte[] second, + int secondIndex, + int length) + { + if (first.Length < length || second.Length < length) + { + return false; + } + + for (int index = 0; index < length; ++index) + { + if (first[firstIndex + index] != second[secondIndex + index]) + { + return false; + } + } + return true; + } + + public static bool CompareByteArrays(byte[] first, byte[] second) + { + if (first.Length != second.Length) + { + return false; + } + + for (int index = 0; index < first.Length; ++index) + { + if (first[index] != second[index]) + { + return false; + } + } + return true; + } + + public static string ByteArrayToString(byte[] byteArray, char separator = ' ') + { + string str = string.Empty; + foreach (byte num in byteArray) + { + str = str + num.ToString("x2").ToUpper() + separator.ToString(); + } + + return str.Remove(str.Length - 1); + } + + public static byte[] HexStringToByteArray(string hexString) + { + byte[] numArray = new byte[hexString.Length / 2]; + for (int index = 0; index < hexString.Length / 2; ++index) + { + numArray[index] = byte.Parse(hexString.Substring(index * 2, 2), NumberStyles.HexNumber); + } + + return numArray; + } + + public static int CountCharsInString(string theString, char theChar) + { + int num1 = 0; + foreach (int num2 in theString) + { + if (num2 == theChar) + { + ++num1; + } + } + return num1; + } + + public static long AddPadding(long value) + { + return Shared.AddPadding(value, 64); + } + + public static long AddPadding(long value, int padding) + { + if (value % padding != 0L) + { + value += padding - value % padding; + } + + return value; + } + + public static int AddPadding(int value) + { + return Shared.AddPadding(value, 64); + } + + public static int AddPadding(int value, int padding) + { + if (value % padding != 0) + { + value += padding - value % padding; + } + + return value; + } + + public static ushort Swap(ushort value) + { + return (ushort)IPAddress.HostToNetworkOrder((short)value); + } + + public static uint Swap(uint value) + { + return (uint)IPAddress.HostToNetworkOrder((int)value); + } + + public static ulong Swap(ulong value) + { + return (ulong)IPAddress.HostToNetworkOrder((long)value); + } + + public static byte[] UShortArrayToByteArray(ushort[] array) + { + List byteList = new List(); + foreach (ushort num in array) + { + byte[] bytes = BitConverter.GetBytes(num); + byteList.AddRange(bytes); + } + return byteList.ToArray(); + } + + public static byte[] UIntArrayToByteArray(uint[] array) + { + List byteList = new List(); + foreach (uint num in array) + { + byte[] bytes = BitConverter.GetBytes(num); + byteList.AddRange(bytes); + } + return byteList.ToArray(); + } + + public static uint[] ByteArrayToUIntArray(byte[] array) + { + uint[] numArray = new uint[array.Length / 4]; + int num = 0; + for (int startIndex = 0; startIndex < array.Length; startIndex += 4) + { + numArray[num++] = BitConverter.ToUInt32(array, startIndex); + } + + return numArray; + } + + public static ushort[] ByteArrayToUShortArray(byte[] array) + { + ushort[] numArray = new ushort[array.Length / 2]; + int num = 0; + for (int startIndex = 0; startIndex < array.Length; startIndex += 2) + { + numArray[num++] = BitConverter.ToUInt16(array, startIndex); + } + + return numArray; + } } - - public static bool CompareByteArrays( - byte[] first, - int firstIndex, - byte[] second, - int secondIndex, - int length) - { - if (first.Length < length || second.Length < length) - return false; - for (int index = 0; index < length; ++index) - { - if ((int) first[firstIndex + index] != (int) second[secondIndex + index]) - return false; - } - return true; - } - - public static bool CompareByteArrays(byte[] first, byte[] second) - { - if (first.Length != second.Length) - return false; - for (int index = 0; index < first.Length; ++index) - { - if ((int) first[index] != (int) second[index]) - return false; - } - return true; - } - - public static string ByteArrayToString(byte[] byteArray, char separator = ' ') - { - string str = string.Empty; - foreach (byte num in byteArray) - str = str + num.ToString("x2").ToUpper() + separator.ToString(); - return str.Remove(str.Length - 1); - } - - public static byte[] HexStringToByteArray(string hexString) - { - byte[] numArray = new byte[hexString.Length / 2]; - for (int index = 0; index < hexString.Length / 2; ++index) - numArray[index] = byte.Parse(hexString.Substring(index * 2, 2), NumberStyles.HexNumber); - return numArray; - } - - public static int CountCharsInString(string theString, char theChar) - { - int num1 = 0; - foreach (int num2 in theString) - { - if (num2 == (int) theChar) - ++num1; - } - return num1; - } - - public static long AddPadding(long value) => Shared.AddPadding(value, 64); - - public static long AddPadding(long value, int padding) - { - if (value % (long) padding != 0L) - value += (long) padding - value % (long) padding; - return value; - } - - public static int AddPadding(int value) => Shared.AddPadding(value, 64); - - public static int AddPadding(int value, int padding) - { - if (value % padding != 0) - value += padding - value % padding; - return value; - } - - public static ushort Swap(ushort value) => (ushort) IPAddress.HostToNetworkOrder((short) value); - - public static uint Swap(uint value) => (uint) IPAddress.HostToNetworkOrder((int) value); - - public static ulong Swap(ulong value) => (ulong) IPAddress.HostToNetworkOrder((long) value); - - public static byte[] UShortArrayToByteArray(ushort[] array) - { - List byteList = new List(); - foreach (ushort num in array) - { - byte[] bytes = BitConverter.GetBytes(num); - byteList.AddRange((IEnumerable) bytes); - } - return byteList.ToArray(); - } - - public static byte[] UIntArrayToByteArray(uint[] array) - { - List byteList = new List(); - foreach (uint num in array) - { - byte[] bytes = BitConverter.GetBytes(num); - byteList.AddRange((IEnumerable) bytes); - } - return byteList.ToArray(); - } - - public static uint[] ByteArrayToUIntArray(byte[] array) - { - uint[] numArray = new uint[array.Length / 4]; - int num = 0; - for (int startIndex = 0; startIndex < array.Length; startIndex += 4) - numArray[num++] = BitConverter.ToUInt32(array, startIndex); - return numArray; - } - - public static ushort[] ByteArrayToUShortArray(byte[] array) - { - ushort[] numArray = new ushort[array.Length / 2]; - int num = 0; - for (int startIndex = 0; startIndex < array.Length; startIndex += 2) - numArray[num++] = BitConverter.ToUInt16(array, startIndex); - return numArray; - } - } } diff --git a/StoreType.cs b/StoreType.cs index fe6ee13..14ed770 100644 --- a/StoreType.cs +++ b/StoreType.cs @@ -6,11 +6,11 @@ namespace libWiiSharp { - public enum StoreType - { - EncryptedContent, - DecryptedContent, - WAD, - All, - } + public enum StoreType + { + EncryptedContent, + DecryptedContent, + WAD, + All, + } } diff --git a/TMD.cs b/TMD.cs index f5bc11b..ca8cdcb 100644 --- a/TMD.cs +++ b/TMD.cs @@ -18,510 +18,572 @@ namespace libWiiSharp Shared = 32769, // 0x8001 } public class TMD : IDisposable - { - private bool fakeSign; - private bool sortContents; - private uint signatureExponent = 65537; - private byte[] signature = new byte[256]; - private byte[] padding = new byte[60]; - private byte[] issuer = new byte[64]; - private byte version; - private byte caCrlVersion; - private byte signerCrlVersion; - private byte paddingByte; - private ulong startupIos; - private ulong titleId; - private uint titleType; - private ushort groupId; - private ushort padding2; - private ushort region; - private byte[] reserved = new byte[58]; - private uint accessRights; - private ushort titleVersion; - private ushort numOfContents; - private ushort bootIndex; - private ushort padding3; - private List contents; - private bool isDisposed; - - public Region Region { - get => (Region) this.region; - set => this.region = (ushort) value; - } + private bool fakeSign; + private bool sortContents; + private uint signatureExponent = 65537; + private byte[] signature = new byte[256]; + private byte[] padding = new byte[60]; + private byte[] issuer = new byte[64]; + private byte version; + private byte caCrlVersion; + private byte signerCrlVersion; + private byte paddingByte; + private ulong startupIos; + private ulong titleId; + private uint titleType; + private ushort groupId; + private ushort padding2; + private ushort region; + private byte[] reserved = new byte[58]; + private uint accessRights; + private ushort titleVersion; + private ushort numOfContents; + private ushort bootIndex; + private ushort padding3; + private List contents; + private bool isDisposed; - public ulong StartupIOS - { - get => this.startupIos; - set => this.startupIos = value; - } - - public ulong TitleID - { - get => this.titleId; - set => this.titleId = value; - } - - public ushort TitleVersion - { - get => this.titleVersion; - set => this.titleVersion = value; - } - - public ushort NumOfContents => this.numOfContents; - - public ushort BootIndex - { - get => this.bootIndex; - set - { - if ((int) value > (int) this.numOfContents) - return; - this.bootIndex = value; - } - } - - public TMD_Content[] Contents - { - get => this.contents.ToArray(); - set - { - this.contents = new List((IEnumerable) value); - this.numOfContents = (ushort) value.Length; - } - } - - public bool FakeSign - { - get => this.fakeSign; - set => this.fakeSign = value; - } - - public bool SortContents - { - get => this.sortContents; - set => this.sortContents = true; - } - - public event EventHandler Debug; - - ~TMD() => this.Dispose(false); - - public void Dispose() - { - this.Dispose(true); - GC.SuppressFinalize((object) this); - } - - protected virtual void Dispose(bool disposing) - { - if (disposing && !this.isDisposed) - { - this.signature = (byte[]) null; - this.padding = (byte[]) null; - this.issuer = (byte[]) null; - this.reserved = (byte[]) null; - this.contents.Clear(); - this.contents = (List) null; - } - this.isDisposed = true; - } - - public static TMD Load(string pathToTmd) => TMD.Load(File.ReadAllBytes(pathToTmd)); - - public static TMD Load(byte[] tmdFile) - { - TMD tmd = new TMD(); - MemoryStream memoryStream = new MemoryStream(tmdFile); - try - { - tmd.parseTmd((Stream) memoryStream); - } - catch - { - memoryStream.Dispose(); - throw; - } - memoryStream.Dispose(); - return tmd; - } - - public static TMD Load(Stream tmd) - { - TMD tmd1 = new TMD(); - tmd1.parseTmd(tmd); - return tmd1; - } - - public void LoadFile(string pathToTmd) => this.LoadFile(File.ReadAllBytes(pathToTmd)); - - public void LoadFile(byte[] tmdFile) - { - MemoryStream memoryStream = new MemoryStream(tmdFile); - try - { - this.parseTmd((Stream) memoryStream); - } - catch - { - memoryStream.Dispose(); - throw; - } - memoryStream.Dispose(); - } - - public void LoadFile(Stream tmd) => this.parseTmd(tmd); - - public void Save(string savePath) => this.Save(savePath, false); - - public void Save(string savePath, bool fakeSign) - { - if (fakeSign) - this.fakeSign = true; - if (File.Exists(savePath)) - File.Delete(savePath); - using (FileStream fileStream = new FileStream(savePath, FileMode.Create)) - this.writeToStream((Stream) fileStream); - } - - public MemoryStream ToMemoryStream() => this.ToMemoryStream(false); - - public MemoryStream ToMemoryStream(bool fakeSign) - { - if (fakeSign) - this.fakeSign = true; - MemoryStream memoryStream = new MemoryStream(); - try - { - this.writeToStream((Stream) memoryStream); - return memoryStream; - } - catch - { - memoryStream.Dispose(); - throw; - } - } - - public byte[] ToByteArray() => this.ToByteArray(false); - - public byte[] ToByteArray(bool fakeSign) - { - if (fakeSign) - this.fakeSign = true; - MemoryStream memoryStream = new MemoryStream(); - try - { - this.writeToStream((Stream) memoryStream); - } - catch - { - memoryStream.Dispose(); - throw; - } - byte[] array = memoryStream.ToArray(); - memoryStream.Dispose(); - return array; - } - - public void UpdateContents(string contentDir) - { - bool flag = true; - char directorySeparatorChar; - for (int index = 0; index < this.contents.Count; ++index) - { - string str1 = contentDir; - directorySeparatorChar = Path.DirectorySeparatorChar; - string str2 = directorySeparatorChar.ToString(); - string str3 = this.contents[index].ContentID.ToString("x8"); - if (!File.Exists(str1 + str2 + str3 + ".app")) + public Region Region { - flag = false; - break; + get => (Region)region; + set => region = (ushort)value; } - } - if (!flag) - { - for (int index = 0; index < this.contents.Count; ++index) + + public ulong StartupIOS { - string str1 = contentDir; - directorySeparatorChar = Path.DirectorySeparatorChar; - string str2 = directorySeparatorChar.ToString(); - string str3 = this.contents[index].ContentID.ToString("x8"); - if (!File.Exists(str1 + str2 + str3 + ".app")) - throw new Exception("Couldn't find all content files!"); + get => startupIos; + set => startupIos = value; } - } - byte[][] conts = new byte[this.contents.Count][]; - for (int index = 0; index < this.contents.Count; ++index) - { - string str1 = contentDir; - directorySeparatorChar = Path.DirectorySeparatorChar; - string str2 = directorySeparatorChar.ToString(); - string str3 = flag ? this.contents[index].ContentID.ToString("x8") : this.contents[index].Index.ToString("x8"); - string path = str1 + str2 + str3 + ".app"; - conts[index] = File.ReadAllBytes(path); - } - this.updateContents(conts); - } - public void UpdateContents(byte[][] contents) => this.updateContents(contents); + public ulong TitleID + { + get => titleId; + set => titleId = value; + } - public string GetUpperTitleID() - { - byte[] bytes = BitConverter.GetBytes(Shared.Swap((uint) this.titleId)); - return new string(new char[4] - { + public ushort TitleVersion + { + get => titleVersion; + set => titleVersion = value; + } + + public ushort NumOfContents => numOfContents; + + public ushort BootIndex + { + get => bootIndex; + set + { + if (value > numOfContents) + { + return; + } + + bootIndex = value; + } + } + + public TMD_Content[] Contents + { + get => contents.ToArray(); + set + { + contents = new List(value); + numOfContents = (ushort)value.Length; + } + } + + public bool FakeSign + { + get => fakeSign; + set => fakeSign = value; + } + + public bool SortContents + { + get => sortContents; + set => sortContents = true; + } + + public event EventHandler Debug; + + ~TMD() => Dispose(false); + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (disposing && !isDisposed) + { + signature = null; + padding = null; + issuer = null; + reserved = null; + contents.Clear(); + contents = null; + } + isDisposed = true; + } + + public static TMD Load(string pathToTmd) + { + return TMD.Load(File.ReadAllBytes(pathToTmd)); + } + + public static TMD Load(byte[] tmdFile) + { + TMD tmd = new TMD(); + MemoryStream memoryStream = new MemoryStream(tmdFile); + try + { + tmd.ParseTmd(memoryStream); + } + catch + { + memoryStream.Dispose(); + throw; + } + memoryStream.Dispose(); + return tmd; + } + + public static TMD Load(Stream tmd) + { + TMD tmd1 = new TMD(); + tmd1.ParseTmd(tmd); + return tmd1; + } + + public void LoadFile(string pathToTmd) + { + LoadFile(File.ReadAllBytes(pathToTmd)); + } + + public void LoadFile(byte[] tmdFile) + { + MemoryStream memoryStream = new MemoryStream(tmdFile); + try + { + ParseTmd(memoryStream); + } + catch + { + memoryStream.Dispose(); + throw; + } + memoryStream.Dispose(); + } + + public void LoadFile(Stream tmd) + { + ParseTmd(tmd); + } + + public void Save(string savePath) + { + Save(savePath, false); + } + + public void Save(string savePath, bool fakeSign) + { + if (fakeSign) + { + this.fakeSign = true; + } + + if (File.Exists(savePath)) + { + File.Delete(savePath); + } + + using FileStream fileStream = new FileStream(savePath, FileMode.Create); + WriteToStream(fileStream); + } + + public MemoryStream ToMemoryStream() + { + return ToMemoryStream(false); + } + + public MemoryStream ToMemoryStream(bool fakeSign) + { + if (fakeSign) + { + this.fakeSign = true; + } + + MemoryStream memoryStream = new MemoryStream(); + try + { + WriteToStream(memoryStream); + return memoryStream; + } + catch + { + memoryStream.Dispose(); + throw; + } + } + + public byte[] ToByteArray() + { + return ToByteArray(false); + } + + public byte[] ToByteArray(bool fakeSign) + { + if (fakeSign) + { + this.fakeSign = true; + } + + MemoryStream memoryStream = new MemoryStream(); + try + { + WriteToStream(memoryStream); + } + catch + { + memoryStream.Dispose(); + throw; + } + byte[] array = memoryStream.ToArray(); + memoryStream.Dispose(); + return array; + } + + public void UpdateContents(string contentDir) + { + bool flag = true; + char directorySeparatorChar; + for (int index = 0; index < contents.Count; ++index) + { + string str1 = contentDir; + directorySeparatorChar = Path.DirectorySeparatorChar; + string str2 = directorySeparatorChar.ToString(); + string str3 = contents[index].ContentID.ToString("x8"); + if (!File.Exists(str1 + str2 + str3 + ".app")) + { + flag = false; + break; + } + } + if (!flag) + { + for (int index = 0; index < contents.Count; ++index) + { + string str1 = contentDir; + directorySeparatorChar = Path.DirectorySeparatorChar; + string str2 = directorySeparatorChar.ToString(); + string str3 = contents[index].ContentID.ToString("x8"); + if (!File.Exists(str1 + str2 + str3 + ".app")) + { + throw new Exception("Couldn't find all content files!"); + } + } + } + byte[][] conts = new byte[contents.Count][]; + for (int index = 0; index < contents.Count; ++index) + { + string str1 = contentDir; + directorySeparatorChar = Path.DirectorySeparatorChar; + string str2 = directorySeparatorChar.ToString(); + string str3 = flag ? contents[index].ContentID.ToString("x8") : contents[index].Index.ToString("x8"); + string path = str1 + str2 + str3 + ".app"; + conts[index] = File.ReadAllBytes(path); + } + UpdateContents(conts); + } + + public void UpdateContents(byte[][] contents) + { + UpdateContents(contents); + } + + public string GetUpperTitleID() + { + byte[] bytes = BitConverter.GetBytes(Shared.Swap((uint)titleId)); + return new string(new char[4] + { (char) bytes[0], (char) bytes[1], (char) bytes[2], (char) bytes[3] - }); - } - - public string GetNandBlocks() => this.calculateNandBlocks(); - - public void AddContent(TMD_Content content) - { - this.contents.Add(content); - this.numOfContents = (ushort) this.contents.Count; - } - - public void RemoveContent(int contentIndex) - { - for (int index = 0; index < (int) this.numOfContents; ++index) - { - if ((int) this.contents[index].Index == contentIndex) - { - this.contents.RemoveAt(index); - break; + }); } - } - this.numOfContents = (ushort) this.contents.Count; - } - public void RemoveContentByID(int contentId) - { - for (int index = 0; index < (int) this.numOfContents; ++index) - { - if ((long) this.contents[index].ContentID == (long) contentId) + public string GetNandBlocks() { - this.contents.RemoveAt(index); - break; + return CalculateNandBlocks(); } - } - this.numOfContents = (ushort) this.contents.Count; - } - public ContentIndices[] GetSortedContentList() - { - List contentIndicesList = new List(); - for (int index = 0; index < this.contents.Count; ++index) - contentIndicesList.Add(new ContentIndices(index, (int) this.contents[index].Index)); - if (this.sortContents) - contentIndicesList.Sort(); - return contentIndicesList.ToArray(); - } - - private void writeToStream(Stream writeStream) - { - this.fireDebug("Writing TMD..."); - if (this.fakeSign) - { - this.fireDebug(" Clearing Signature..."); - this.signature = new byte[256]; - } - MemoryStream memoryStream = new MemoryStream(); - memoryStream.Seek(0L, SeekOrigin.Begin); - this.fireDebug(" Writing Signature Exponent... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); - memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.signatureExponent)), 0, 4); - this.fireDebug(" Writing Signature... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); - memoryStream.Write(this.signature, 0, this.signature.Length); - this.fireDebug(" Writing Padding... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); - memoryStream.Write(this.padding, 0, this.padding.Length); - this.fireDebug(" Writing Issuer... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); - memoryStream.Write(this.issuer, 0, this.issuer.Length); - this.fireDebug(" Writing Version... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); - memoryStream.WriteByte(this.version); - this.fireDebug(" Writing CA Crl Version... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); - memoryStream.WriteByte(this.caCrlVersion); - this.fireDebug(" Writing Signer Crl Version... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); - memoryStream.WriteByte(this.signerCrlVersion); - this.fireDebug(" Writing Padding Byte... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); - memoryStream.WriteByte(this.paddingByte); - this.fireDebug(" Writing Startup IOS... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); - memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.startupIos)), 0, 8); - this.fireDebug(" Writing Title ID... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); - memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.titleId)), 0, 8); - this.fireDebug(" Writing Title Type... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); - memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.titleType)), 0, 4); - this.fireDebug(" Writing Group ID... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); - memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.groupId)), 0, 2); - this.fireDebug(" Writing Padding2... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); - memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.padding2)), 0, 2); - this.fireDebug(" Writing Region... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); - memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.region)), 0, 2); - this.fireDebug(" Writing Reserved... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); - memoryStream.Write(this.reserved, 0, this.reserved.Length); - this.fireDebug(" Writing Access Rights... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); - memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.accessRights)), 0, 4); - this.fireDebug(" Writing Title Version... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); - memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.titleVersion)), 0, 2); - this.fireDebug(" Writing NumOfContents... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); - memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.numOfContents)), 0, 2); - this.fireDebug(" Writing Boot Index... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); - memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.bootIndex)), 0, 2); - this.fireDebug(" Writing Padding3... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); - memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.padding3)), 0, 2); - List contentIndicesList = new List(); - for (int index = 0; index < this.contents.Count; ++index) - contentIndicesList.Add(new ContentIndices(index, (int) this.contents[index].Index)); - if (this.sortContents) - contentIndicesList.Sort(); - for (int index = 0; index < contentIndicesList.Count; ++index) - { - this.fireDebug(" Writing Content #{1} of {2}... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper().ToUpper(), (object) (index + 1), (object) this.numOfContents); - memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.contents[contentIndicesList[index].Index].ContentID)), 0, 4); - memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.contents[contentIndicesList[index].Index].Index)), 0, 2); - memoryStream.Write(BitConverter.GetBytes(Shared.Swap((ushort) this.contents[contentIndicesList[index].Index].Type)), 0, 2); - memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.contents[contentIndicesList[index].Index].Size)), 0, 8); - memoryStream.Write(this.contents[contentIndicesList[index].Index].Hash, 0, this.contents[contentIndicesList[index].Index].Hash.Length); - } - byte[] array = memoryStream.ToArray(); - memoryStream.Dispose(); - if (this.fakeSign) - { - this.fireDebug(" Fakesigning TMD..."); - byte[] numArray = new byte[20]; - SHA1 shA1 = SHA1.Create(); - for (ushort index = 0; index < ushort.MaxValue; ++index) + public void AddContent(TMD_Content content) { - byte[] bytes = BitConverter.GetBytes(index); - array[482] = bytes[1]; - array[483] = bytes[0]; - if (shA1.ComputeHash(array)[0] == (byte) 0) - { - this.fireDebug(" -> Signed ({0})", (object) index); - break; - } - if (index == (ushort) 65534) - { - this.fireDebug(" -> Signing Failed..."); - throw new Exception("Fakesigning failed..."); - } + contents.Add(content); + numOfContents = (ushort)contents.Count; } - shA1.Clear(); - } - writeStream.Seek(0L, SeekOrigin.Begin); - writeStream.Write(array, 0, array.Length); - this.fireDebug("Writing TMD Finished..."); - } - private void updateContents(byte[][] conts) - { - SHA1 shA1 = SHA1.Create(); - for (int index = 0; index < this.contents.Count; ++index) - { - this.contents[index].Size = (ulong) conts[index].Length; - this.contents[index].Hash = shA1.ComputeHash(conts[index]); - } - shA1.Clear(); - } + public void RemoveContent(int contentIndex) + { + for (int index = 0; index < numOfContents; ++index) + { + if (contents[index].Index == contentIndex) + { + contents.RemoveAt(index); + break; + } + } + numOfContents = (ushort)contents.Count; + } - private void parseTmd(Stream tmdFile) - { - this.fireDebug("Pasing TMD..."); - tmdFile.Seek(0L, SeekOrigin.Begin); - byte[] buffer = new byte[8]; - this.fireDebug(" Reading Signature Exponent... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper()); - tmdFile.Read(buffer, 0, 4); - this.signatureExponent = Shared.Swap(BitConverter.ToUInt32(buffer, 0)); - this.fireDebug(" Reading Signature... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper()); - tmdFile.Read(this.signature, 0, this.signature.Length); - this.fireDebug(" Reading Padding... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper()); - tmdFile.Read(this.padding, 0, this.padding.Length); - this.fireDebug(" Reading Issuer... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper()); - tmdFile.Read(this.issuer, 0, this.issuer.Length); - this.fireDebug(" Reading Version... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper()); - this.fireDebug(" Reading CA Crl Version... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper()); - this.fireDebug(" Reading Signer Crl Version... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper()); - this.fireDebug(" Reading Padding Byte... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper()); - tmdFile.Read(buffer, 0, 4); - this.version = buffer[0]; - this.caCrlVersion = buffer[1]; - this.signerCrlVersion = buffer[2]; - this.paddingByte = buffer[3]; - this.fireDebug(" Reading Startup IOS... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper()); - tmdFile.Read(buffer, 0, 8); - this.startupIos = Shared.Swap(BitConverter.ToUInt64(buffer, 0)); - this.fireDebug(" Reading Title ID... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper()); - tmdFile.Read(buffer, 0, 8); - this.titleId = Shared.Swap(BitConverter.ToUInt64(buffer, 0)); - this.fireDebug(" Reading Title Type... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper()); - tmdFile.Read(buffer, 0, 4); - this.titleType = Shared.Swap(BitConverter.ToUInt32(buffer, 0)); - this.fireDebug(" Reading Group ID... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper()); - tmdFile.Read(buffer, 0, 2); - this.groupId = Shared.Swap(BitConverter.ToUInt16(buffer, 0)); - this.fireDebug(" Reading Padding2... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper()); - tmdFile.Read(buffer, 0, 2); - this.padding2 = Shared.Swap(BitConverter.ToUInt16(buffer, 0)); - this.fireDebug(" Reading Region... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper()); - tmdFile.Read(buffer, 0, 2); - this.region = Shared.Swap(BitConverter.ToUInt16(buffer, 0)); - this.fireDebug(" Reading Reserved... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper()); - tmdFile.Read(this.reserved, 0, this.reserved.Length); - this.fireDebug(" Reading Access Rights... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper()); - tmdFile.Read(buffer, 0, 4); - this.accessRights = Shared.Swap(BitConverter.ToUInt32(buffer, 0)); - this.fireDebug(" Reading Title Version... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper()); - this.fireDebug(" Reading NumOfContents... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper()); - this.fireDebug(" Reading Boot Index... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper()); - this.fireDebug(" Reading Padding3... (Offset: 0x{0})", (object) tmdFile.Position.ToString("x8").ToUpper()); - tmdFile.Read(buffer, 0, 8); - this.titleVersion = Shared.Swap(BitConverter.ToUInt16(buffer, 0)); - this.numOfContents = Shared.Swap(BitConverter.ToUInt16(buffer, 2)); - this.bootIndex = Shared.Swap(BitConverter.ToUInt16(buffer, 4)); - this.padding3 = Shared.Swap(BitConverter.ToUInt16(buffer, 6)); - this.contents = new List(); - for (int index = 0; index < (int) this.numOfContents; ++index) - { - this.fireDebug(" Reading Content #{0} of {1}... (Offset: 0x{2})", (object) (index + 1), (object) this.numOfContents, (object) tmdFile.Position.ToString("x8").ToUpper().ToUpper()); - TMD_Content tmdContent = new TMD_Content(); - tmdContent.Hash = new byte[20]; - tmdFile.Read(buffer, 0, 8); - tmdContent.ContentID = Shared.Swap(BitConverter.ToUInt32(buffer, 0)); - tmdContent.Index = Shared.Swap(BitConverter.ToUInt16(buffer, 4)); - tmdContent.Type = (ContentType) Shared.Swap(BitConverter.ToUInt16(buffer, 6)); - tmdFile.Read(buffer, 0, 8); - tmdContent.Size = Shared.Swap(BitConverter.ToUInt64(buffer, 0)); - tmdFile.Read(tmdContent.Hash, 0, tmdContent.Hash.Length); - this.contents.Add(tmdContent); - } - this.fireDebug("Pasing TMD Finished..."); - } + public void RemoveContentByID(int contentId) + { + for (int index = 0; index < numOfContents; ++index) + { + if (contents[index].ContentID == contentId) + { + contents.RemoveAt(index); + break; + } + } + numOfContents = (ushort)contents.Count; + } - private string calculateNandBlocks() - { - int num1 = 0; - int num2 = 0; - for (int index = 0; index < (int) this.numOfContents; ++index) - { - num2 += (int) this.contents[index].Size; - if (this.contents[index].Type == ContentType.Normal) - num1 += (int) this.contents[index].Size; - } - int num3 = (int) Math.Ceiling((double) num1 / 131072.0); - int num4 = (int) Math.Ceiling((double) num2 / 131072.0); - return num3 == num4 ? num4.ToString() : string.Format("{0} - {1}", (object) num3, (object) num4); - } + public ContentIndices[] GetSortedContentList() + { + List contentIndicesList = new List(); + for (int index = 0; index < contents.Count; ++index) + { + contentIndicesList.Add(new ContentIndices(index, contents[index].Index)); + } - private void fireDebug(string debugMessage, params object[] args) - { - EventHandler debug = this.Debug; - if (debug == null) - return; - debug(new object(), new MessageEventArgs(string.Format(debugMessage, args))); + if (sortContents) + { + contentIndicesList.Sort(); + } + + return contentIndicesList.ToArray(); + } + + private void WriteToStream(Stream writeStream) + { + FireDebug("Writing TMD..."); + if (fakeSign) + { + FireDebug(" Clearing Signature..."); + signature = new byte[256]; + } + MemoryStream memoryStream = new MemoryStream(); + memoryStream.Seek(0L, SeekOrigin.Begin); + FireDebug(" Writing Signature Exponent... (Offset: 0x{0})", (object)memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(signatureExponent)), 0, 4); + FireDebug(" Writing Signature... (Offset: 0x{0})", (object)memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(signature, 0, signature.Length); + FireDebug(" Writing Padding... (Offset: 0x{0})", (object)memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(padding, 0, padding.Length); + FireDebug(" Writing Issuer... (Offset: 0x{0})", (object)memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(issuer, 0, issuer.Length); + FireDebug(" Writing Version... (Offset: 0x{0})", (object)memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.WriteByte(version); + FireDebug(" Writing CA Crl Version... (Offset: 0x{0})", (object)memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.WriteByte(caCrlVersion); + FireDebug(" Writing Signer Crl Version... (Offset: 0x{0})", (object)memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.WriteByte(signerCrlVersion); + FireDebug(" Writing Padding Byte... (Offset: 0x{0})", (object)memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.WriteByte(paddingByte); + FireDebug(" Writing Startup IOS... (Offset: 0x{0})", (object)memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(startupIos)), 0, 8); + FireDebug(" Writing Title ID... (Offset: 0x{0})", (object)memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(titleId)), 0, 8); + FireDebug(" Writing Title Type... (Offset: 0x{0})", (object)memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(titleType)), 0, 4); + FireDebug(" Writing Group ID... (Offset: 0x{0})", (object)memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(groupId)), 0, 2); + FireDebug(" Writing Padding2... (Offset: 0x{0})", (object)memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(padding2)), 0, 2); + FireDebug(" Writing Region... (Offset: 0x{0})", (object)memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(region)), 0, 2); + FireDebug(" Writing Reserved... (Offset: 0x{0})", (object)memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(reserved, 0, reserved.Length); + FireDebug(" Writing Access Rights... (Offset: 0x{0})", (object)memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(accessRights)), 0, 4); + FireDebug(" Writing Title Version... (Offset: 0x{0})", (object)memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(titleVersion)), 0, 2); + FireDebug(" Writing NumOfContents... (Offset: 0x{0})", (object)memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(numOfContents)), 0, 2); + FireDebug(" Writing Boot Index... (Offset: 0x{0})", (object)memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(bootIndex)), 0, 2); + FireDebug(" Writing Padding3... (Offset: 0x{0})", (object)memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(padding3)), 0, 2); + List contentIndicesList = new List(); + for (int index = 0; index < contents.Count; ++index) + { + contentIndicesList.Add(new ContentIndices(index, contents[index].Index)); + } + + if (sortContents) + { + contentIndicesList.Sort(); + } + + for (int index = 0; index < contentIndicesList.Count; ++index) + { + FireDebug(" Writing Content #{1} of {2}... (Offset: 0x{0})", memoryStream.Position.ToString("x8").ToUpper().ToUpper(), index + 1, numOfContents); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(contents[contentIndicesList[index].Index].ContentID)), 0, 4); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(contents[contentIndicesList[index].Index].Index)), 0, 2); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap((ushort)contents[contentIndicesList[index].Index].Type)), 0, 2); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(contents[contentIndicesList[index].Index].Size)), 0, 8); + memoryStream.Write(contents[contentIndicesList[index].Index].Hash, 0, contents[contentIndicesList[index].Index].Hash.Length); + } + byte[] array = memoryStream.ToArray(); + memoryStream.Dispose(); + if (fakeSign) + { + FireDebug(" Fakesigning TMD..."); + //byte[] numArray = new byte[20]; + SHA1 shA1 = SHA1.Create(); + for (ushort index = 0; index < ushort.MaxValue; ++index) + { + byte[] bytes = BitConverter.GetBytes(index); + array[482] = bytes[1]; + array[483] = bytes[0]; + if (shA1.ComputeHash(array)[0] == 0) + { + FireDebug(" -> Signed ({0})", (object)index); + break; + } + if (index == 65534) + { + FireDebug(" -> Signing Failed..."); + throw new Exception("Fakesigning failed..."); + } + } + shA1.Clear(); + } + writeStream.Seek(0L, SeekOrigin.Begin); + writeStream.Write(array, 0, array.Length); + FireDebug("Writing TMD Finished..."); + } + + /* + private void PrivUpdateContents(byte[][] conts) + { + SHA1 shA1 = SHA1.Create(); + for (int index = 0; index < this.contents.Count; ++index) + { + this.contents[index].Size = (ulong)conts[index].Length; + this.contents[index].Hash = shA1.ComputeHash(conts[index]); + } + shA1.Clear(); + } + */ + + private void ParseTmd(Stream tmdFile) + { + FireDebug("Pasing TMD..."); + tmdFile.Seek(0L, SeekOrigin.Begin); + byte[] buffer = new byte[8]; + FireDebug(" Reading Signature Exponent... (Offset: 0x{0})", (object)tmdFile.Position.ToString("x8").ToUpper()); + tmdFile.Read(buffer, 0, 4); + signatureExponent = Shared.Swap(BitConverter.ToUInt32(buffer, 0)); + FireDebug(" Reading Signature... (Offset: 0x{0})", (object)tmdFile.Position.ToString("x8").ToUpper()); + tmdFile.Read(signature, 0, signature.Length); + FireDebug(" Reading Padding... (Offset: 0x{0})", (object)tmdFile.Position.ToString("x8").ToUpper()); + tmdFile.Read(padding, 0, padding.Length); + FireDebug(" Reading Issuer... (Offset: 0x{0})", (object)tmdFile.Position.ToString("x8").ToUpper()); + tmdFile.Read(issuer, 0, issuer.Length); + FireDebug(" Reading Version... (Offset: 0x{0})", (object)tmdFile.Position.ToString("x8").ToUpper()); + FireDebug(" Reading CA Crl Version... (Offset: 0x{0})", (object)tmdFile.Position.ToString("x8").ToUpper()); + FireDebug(" Reading Signer Crl Version... (Offset: 0x{0})", (object)tmdFile.Position.ToString("x8").ToUpper()); + FireDebug(" Reading Padding Byte... (Offset: 0x{0})", (object)tmdFile.Position.ToString("x8").ToUpper()); + tmdFile.Read(buffer, 0, 4); + version = buffer[0]; + caCrlVersion = buffer[1]; + signerCrlVersion = buffer[2]; + paddingByte = buffer[3]; + FireDebug(" Reading Startup IOS... (Offset: 0x{0})", (object)tmdFile.Position.ToString("x8").ToUpper()); + tmdFile.Read(buffer, 0, 8); + startupIos = Shared.Swap(BitConverter.ToUInt64(buffer, 0)); + FireDebug(" Reading Title ID... (Offset: 0x{0})", (object)tmdFile.Position.ToString("x8").ToUpper()); + tmdFile.Read(buffer, 0, 8); + titleId = Shared.Swap(BitConverter.ToUInt64(buffer, 0)); + FireDebug(" Reading Title Type... (Offset: 0x{0})", (object)tmdFile.Position.ToString("x8").ToUpper()); + tmdFile.Read(buffer, 0, 4); + titleType = Shared.Swap(BitConverter.ToUInt32(buffer, 0)); + FireDebug(" Reading Group ID... (Offset: 0x{0})", (object)tmdFile.Position.ToString("x8").ToUpper()); + tmdFile.Read(buffer, 0, 2); + groupId = Shared.Swap(BitConverter.ToUInt16(buffer, 0)); + FireDebug(" Reading Padding2... (Offset: 0x{0})", (object)tmdFile.Position.ToString("x8").ToUpper()); + tmdFile.Read(buffer, 0, 2); + padding2 = Shared.Swap(BitConverter.ToUInt16(buffer, 0)); + FireDebug(" Reading Region... (Offset: 0x{0})", (object)tmdFile.Position.ToString("x8").ToUpper()); + tmdFile.Read(buffer, 0, 2); + region = Shared.Swap(BitConverter.ToUInt16(buffer, 0)); + FireDebug(" Reading Reserved... (Offset: 0x{0})", (object)tmdFile.Position.ToString("x8").ToUpper()); + tmdFile.Read(reserved, 0, reserved.Length); + FireDebug(" Reading Access Rights... (Offset: 0x{0})", (object)tmdFile.Position.ToString("x8").ToUpper()); + tmdFile.Read(buffer, 0, 4); + accessRights = Shared.Swap(BitConverter.ToUInt32(buffer, 0)); + FireDebug(" Reading Title Version... (Offset: 0x{0})", (object)tmdFile.Position.ToString("x8").ToUpper()); + FireDebug(" Reading NumOfContents... (Offset: 0x{0})", (object)tmdFile.Position.ToString("x8").ToUpper()); + FireDebug(" Reading Boot Index... (Offset: 0x{0})", (object)tmdFile.Position.ToString("x8").ToUpper()); + FireDebug(" Reading Padding3... (Offset: 0x{0})", (object)tmdFile.Position.ToString("x8").ToUpper()); + tmdFile.Read(buffer, 0, 8); + titleVersion = Shared.Swap(BitConverter.ToUInt16(buffer, 0)); + numOfContents = Shared.Swap(BitConverter.ToUInt16(buffer, 2)); + bootIndex = Shared.Swap(BitConverter.ToUInt16(buffer, 4)); + padding3 = Shared.Swap(BitConverter.ToUInt16(buffer, 6)); + contents = new List(); + for (int index = 0; index < numOfContents; ++index) + { + FireDebug(" Reading Content #{0} of {1}... (Offset: 0x{2})", index + 1, numOfContents, tmdFile.Position.ToString("x8").ToUpper().ToUpper()); + TMD_Content tmdContent = new TMD_Content + { + Hash = new byte[20] + }; + tmdFile.Read(buffer, 0, 8); + tmdContent.ContentID = Shared.Swap(BitConverter.ToUInt32(buffer, 0)); + tmdContent.Index = Shared.Swap(BitConverter.ToUInt16(buffer, 4)); + tmdContent.Type = (ContentType)Shared.Swap(BitConverter.ToUInt16(buffer, 6)); + tmdFile.Read(buffer, 0, 8); + tmdContent.Size = Shared.Swap(BitConverter.ToUInt64(buffer, 0)); + tmdFile.Read(tmdContent.Hash, 0, tmdContent.Hash.Length); + contents.Add(tmdContent); + } + FireDebug("Pasing TMD Finished..."); + } + + private string CalculateNandBlocks() + { + int num1 = 0; + int num2 = 0; + for (int index = 0; index < numOfContents; ++index) + { + num2 += (int)contents[index].Size; + if (contents[index].Type == ContentType.Normal) + { + num1 += (int)contents[index].Size; + } + } + int num3 = (int)Math.Ceiling(num1 / 131072.0); + int num4 = (int)Math.Ceiling(num2 / 131072.0); + return num3 == num4 ? num4.ToString() : string.Format("{0} - {1}", num3, num4); + } + + private void FireDebug(string debugMessage, params object[] args) + { + EventHandler debug = Debug; + if (debug == null) + { + return; + } + + debug(new object(), new MessageEventArgs(string.Format(debugMessage, args))); + } } - } } diff --git a/TMD_Content.cs b/TMD_Content.cs index 68c9ee2..11ca0ef 100644 --- a/TMD_Content.cs +++ b/TMD_Content.cs @@ -6,42 +6,42 @@ namespace libWiiSharp { - public class TMD_Content - { - private uint contentId; - private ushort index; - private ushort type; - private ulong size; - private byte[] hash = new byte[20]; - - public uint ContentID + public class TMD_Content { - get => this.contentId; - set => this.contentId = value; - } + private uint contentId; + private ushort index; + private ushort type; + private ulong size; + private byte[] hash = new byte[20]; - public ushort Index - { - get => this.index; - set => this.index = value; - } + public uint ContentID + { + get => contentId; + set => contentId = value; + } - public ContentType Type - { - get => (ContentType) this.type; - set => this.type = (ushort) value; - } + public ushort Index + { + get => index; + set => index = value; + } - public ulong Size - { - get => this.size; - set => this.size = value; - } + public ContentType Type + { + get => (ContentType)type; + set => type = (ushort)value; + } - public byte[] Hash - { - get => this.hash; - set => this.hash = value; + public ulong Size + { + get => size; + set => size = value; + } + + public byte[] Hash + { + get => hash; + set => hash = value; + } } - } } diff --git a/TPL.cs b/TPL.cs index 9bec3e4..235b2b7 100644 --- a/TPL.cs +++ b/TPL.cs @@ -13,1370 +13,1411 @@ using System.Runtime.InteropServices; namespace libWiiSharp { - public class TPL : IDisposable - { - private TPL_Header tplHeader = new TPL_Header(); - private List tplTextureEntries = new List(); - private List tplTextureHeaders = new List(); - private List tplPaletteHeaders = new List(); - private List textureData = new List(); - private List paletteData = new List(); - private bool isDisposed; - - public int NumOfTextures => (int) this.tplHeader.NumOfTextures; - - public event EventHandler Debug; - - ~TPL() => this.Dispose(false); - - public void Dispose() + public class TPL : IDisposable { - this.Dispose(true); - GC.SuppressFinalize((object) this); - } + private TPL_Header tplHeader = new TPL_Header(); + private List tplTextureEntries = new List(); + private List tplTextureHeaders = new List(); + private List tplPaletteHeaders = new List(); + private List textureData = new List(); + private List paletteData = new List(); + private bool isDisposed; - protected virtual void Dispose(bool disposing) - { - if (disposing && !this.isDisposed) - { - this.tplHeader = (TPL_Header) null; - this.tplTextureEntries.Clear(); - this.tplTextureEntries = (List) null; - this.tplTextureHeaders.Clear(); - this.tplTextureHeaders = (List) null; - this.tplPaletteHeaders.Clear(); - this.tplPaletteHeaders = (List) null; - this.textureData.Clear(); - this.textureData = (List) null; - this.paletteData.Clear(); - this.paletteData = (List) null; - } - this.isDisposed = true; - } + public int NumOfTextures => (int)tplHeader.NumOfTextures; - public static TPL Load(string pathToTpl) - { - TPL tpl = new TPL(); - MemoryStream memoryStream = new MemoryStream(File.ReadAllBytes(pathToTpl)); - try - { - tpl.parseTpl((Stream) memoryStream); - } - catch - { - memoryStream.Dispose(); - throw; - } - memoryStream.Dispose(); - return tpl; - } + public event EventHandler Debug; - public static TPL Load(byte[] tplFile) - { - TPL tpl = new TPL(); - MemoryStream memoryStream = new MemoryStream(tplFile); - try - { - tpl.parseTpl((Stream) memoryStream); - } - catch - { - memoryStream.Dispose(); - throw; - } - memoryStream.Dispose(); - return tpl; - } + ~TPL() => Dispose(false); - public static TPL Load(Stream tpl) - { - TPL tpl1 = new TPL(); - tpl1.parseTpl(tpl); - return tpl1; - } - - public static TPL FromImage( - string pathToImage, - TPL_TextureFormat tplFormat, - TPL_PaletteFormat paletteFormat = TPL_PaletteFormat.RGB5A3) - { - return TPL.FromImages(new string[1]{ pathToImage }, new TPL_TextureFormat[1] - { - tplFormat - }, new TPL_PaletteFormat[1]{ paletteFormat }); - } - - public static TPL FromImage( - Image img, - TPL_TextureFormat tplFormat, - TPL_PaletteFormat paletteFormat = TPL_PaletteFormat.RGB5A3) - { - return TPL.FromImages(new Image[1]{ img }, new TPL_TextureFormat[1] - { - tplFormat - }, new TPL_PaletteFormat[1]{ paletteFormat }); - } - - public static TPL FromImages( - string[] imagePaths, - TPL_TextureFormat[] tplFormats, - TPL_PaletteFormat[] paletteFormats) - { - if (tplFormats.Length < imagePaths.Length) - throw new Exception("You must specify a format for each image!"); - List imageList = new List(); - foreach (string imagePath in imagePaths) - imageList.Add(Image.FromFile(imagePath)); - TPL tpl = new TPL(); - tpl.createFromImages(imageList.ToArray(), tplFormats, paletteFormats); - return tpl; - } - - public static TPL FromImages( - Image[] images, - TPL_TextureFormat[] tplFormats, - TPL_PaletteFormat[] paletteFormats) - { - if (tplFormats.Length < images.Length) - throw new Exception("You must specify a format for each image!"); - TPL tpl = new TPL(); - tpl.createFromImages(images, tplFormats, paletteFormats); - return tpl; - } - - public void LoadFile(string pathToTpl) - { - MemoryStream memoryStream = new MemoryStream(File.ReadAllBytes(pathToTpl)); - try - { - this.parseTpl((Stream) memoryStream); - } - catch - { - memoryStream.Dispose(); - throw; - } - memoryStream.Dispose(); - } - - public void LoadFile(byte[] tplFile) - { - MemoryStream memoryStream = new MemoryStream(tplFile); - try - { - this.parseTpl((Stream) memoryStream); - } - catch - { - memoryStream.Dispose(); - throw; - } - memoryStream.Dispose(); - } - - public void LoadFile(Stream tpl) => this.parseTpl(tpl); - - public void CreateFromImage( - string pathToImage, - TPL_TextureFormat tplFormat, - TPL_PaletteFormat paletteFormat = TPL_PaletteFormat.RGB5A3) - { - this.CreateFromImages(new string[1]{ pathToImage }, new TPL_TextureFormat[1] - { - tplFormat - }, new TPL_PaletteFormat[1]{ paletteFormat }); - } - - public void CreateFromImage( - Image img, - TPL_TextureFormat tplFormat, - TPL_PaletteFormat paletteFormat = TPL_PaletteFormat.RGB5A3) - { - this.CreateFromImages(new Image[1]{ img }, new TPL_TextureFormat[1] - { - tplFormat - }, new TPL_PaletteFormat[1]{ paletteFormat }); - } - - public void CreateFromImages( - string[] imagePaths, - TPL_TextureFormat[] tplFormats, - TPL_PaletteFormat[] paletteFormats) - { - if (tplFormats.Length < imagePaths.Length) - throw new Exception("You must specify a format for each image!"); - List imageList = new List(); - foreach (string imagePath in imagePaths) - imageList.Add(Image.FromFile(imagePath)); - this.createFromImages(imageList.ToArray(), tplFormats, paletteFormats); - } - - public void CreateFromImages( - Image[] images, - TPL_TextureFormat[] tplFormats, - TPL_PaletteFormat[] paletteFormats) - { - if (tplFormats.Length < images.Length) - throw new Exception("You must specify a format for each image!"); - this.createFromImages(images, tplFormats, paletteFormats); - } - - public void Save(string savePath) - { - if (File.Exists(savePath)) - File.Delete(savePath); - FileStream fileStream = new FileStream(savePath, FileMode.Create); - try - { - this.writeToStream((Stream) fileStream); - } - catch - { - fileStream.Dispose(); - throw; - } - fileStream.Dispose(); - } - - public MemoryStream ToMemoryStream() - { - MemoryStream memoryStream = new MemoryStream(); - try - { - this.writeToStream((Stream) memoryStream); - return memoryStream; - } - catch - { - memoryStream.Dispose(); - throw; - } - } - - public byte[] ToByteArray() => this.ToMemoryStream().ToArray(); - - public Image ExtractTexture() => this.ExtractTexture(0); - - public Image ExtractTexture(int index) - { - byte[] data; - switch (this.tplTextureHeaders[index].TextureFormat) - { - case 0: - data = this.fromI4(this.textureData[index], (int) this.tplTextureHeaders[index].TextureWidth, (int) this.tplTextureHeaders[index].TextureHeight); - break; - case 1: - data = this.fromI8(this.textureData[index], (int) this.tplTextureHeaders[index].TextureWidth, (int) this.tplTextureHeaders[index].TextureHeight); - break; - case 2: - data = this.fromIA4(this.textureData[index], (int) this.tplTextureHeaders[index].TextureWidth, (int) this.tplTextureHeaders[index].TextureHeight); - break; - case 3: - data = this.fromIA8(this.textureData[index], (int) this.tplTextureHeaders[index].TextureWidth, (int) this.tplTextureHeaders[index].TextureHeight); - break; - case 4: - data = this.fromRGB565(this.textureData[index], (int) this.tplTextureHeaders[index].TextureWidth, (int) this.tplTextureHeaders[index].TextureHeight); - break; - case 5: - data = this.fromRGB5A3(this.textureData[index], (int) this.tplTextureHeaders[index].TextureWidth, (int) this.tplTextureHeaders[index].TextureHeight); - break; - case 6: - data = this.fromRGBA8(this.textureData[index], (int) this.tplTextureHeaders[index].TextureWidth, (int) this.tplTextureHeaders[index].TextureHeight); - break; - case 8: - data = this.fromCI4(this.textureData[index], this.paletteToRgba(index), (int) this.tplTextureHeaders[index].TextureWidth, (int) this.tplTextureHeaders[index].TextureHeight); - break; - case 9: - data = this.fromCI8(this.textureData[index], this.paletteToRgba(index), (int) this.tplTextureHeaders[index].TextureWidth, (int) this.tplTextureHeaders[index].TextureHeight); - break; - case 10: - data = this.fromCI14X2(this.textureData[index], this.paletteToRgba(index), (int) this.tplTextureHeaders[index].TextureWidth, (int) this.tplTextureHeaders[index].TextureHeight); - break; - case 14: - data = this.fromCMP(this.textureData[index], (int) this.tplTextureHeaders[index].TextureWidth, (int) this.tplTextureHeaders[index].TextureHeight); - break; - default: - throw new FormatException("Unsupported Texture Format!"); - } - return (Image) this.rgbaToImage(data, (int) this.tplTextureHeaders[index].TextureWidth, (int) this.tplTextureHeaders[index].TextureHeight); - } - - public void ExtractTexture(string savePath) => this.ExtractTexture(0, savePath); - - public void ExtractTexture(int index, string savePath) - { - if (File.Exists(savePath)) - File.Delete(savePath); - Image texture = this.ExtractTexture(index); - switch (Path.GetExtension(savePath).ToLower()) - { - case ".tif": - case ".tiff": - texture.Save(savePath, ImageFormat.Tiff); - break; - case ".bmp": - texture.Save(savePath, ImageFormat.Bmp); - break; - case ".gif": - texture.Save(savePath, ImageFormat.Gif); - break; - case ".jpg": - case ".jpeg": - texture.Save(savePath, ImageFormat.Jpeg); - break; - default: - texture.Save(savePath, ImageFormat.Png); - break; - } - } - - public Image[] ExtractAllTextures() - { - List imageList = new List(); - for (int index = 0; (long) index < (long) this.tplHeader.NumOfTextures; ++index) - imageList.Add(this.ExtractTexture(index)); - return imageList.ToArray(); - } - - public void ExtractAllTextures(string saveDir) - { - if (Directory.Exists(saveDir)) - Directory.CreateDirectory(saveDir); - for (int index = 0; (long) index < (long) this.tplHeader.NumOfTextures; ++index) - this.ExtractTexture(index, saveDir + Path.DirectorySeparatorChar.ToString() + "Texture_" + index.ToString("x2") + ".png"); - } - - public void AddTexture( - string imagePath, - TPL_TextureFormat tplFormat, - TPL_PaletteFormat paletteFormat = TPL_PaletteFormat.RGB5A3) - { - this.AddTexture(Image.FromFile(imagePath), tplFormat, paletteFormat); - } - - public void AddTexture(Image img, TPL_TextureFormat tplFormat, TPL_PaletteFormat paletteFormat = TPL_PaletteFormat.RGB5A3) - { - TPL_TextureEntry tplTextureEntry = new TPL_TextureEntry(); - TPL_TextureHeader tplTextureHeader = new TPL_TextureHeader(); - TPL_PaletteHeader tplPaletteHeader = new TPL_PaletteHeader(); - byte[] numArray1 = this.imageToTpl(img, tplFormat); - byte[] numArray2 = new byte[0]; - tplTextureHeader.TextureHeight = (ushort) img.Height; - tplTextureHeader.TextureWidth = (ushort) img.Width; - tplTextureHeader.TextureFormat = (uint) tplFormat; - if (tplFormat == TPL_TextureFormat.CI4 || tplFormat == TPL_TextureFormat.CI8 || tplFormat == TPL_TextureFormat.CI14X2) - { - ColorIndexConverter colorIndexConverter = new ColorIndexConverter(this.imageToRgba(img), img.Width, img.Height, tplFormat, paletteFormat); - numArray1 = colorIndexConverter.Data; - numArray2 = colorIndexConverter.Palette; - tplPaletteHeader.NumberOfItems = (ushort) (numArray2.Length / 2); - tplPaletteHeader.PaletteFormat = (uint) paletteFormat; - } - this.tplTextureEntries.Add(tplTextureEntry); - this.tplTextureHeaders.Add(tplTextureHeader); - this.tplPaletteHeaders.Add(tplPaletteHeader); - this.textureData.Add(numArray1); - this.paletteData.Add(numArray2); - ++this.tplHeader.NumOfTextures; - } - - public void RemoveTexture(int index) - { - if ((long) this.tplHeader.NumOfTextures <= (long) index) - return; - this.tplTextureEntries.RemoveAt(index); - this.tplTextureHeaders.RemoveAt(index); - this.tplPaletteHeaders.RemoveAt(index); - this.textureData.RemoveAt(index); - this.paletteData.RemoveAt(index); - --this.tplHeader.NumOfTextures; - } - - public TPL_TextureFormat GetTextureFormat(int index) => (TPL_TextureFormat) this.tplTextureHeaders[index].TextureFormat; - - public TPL_PaletteFormat GetPaletteFormat(int index) => (TPL_PaletteFormat) this.tplPaletteHeaders[index].PaletteFormat; - - public Size GetTextureSize(int index) => new Size((int) this.tplTextureHeaders[index].TextureWidth, (int) this.tplTextureHeaders[index].TextureHeight); - - private void writeToStream(Stream writeStream) - { - this.fireDebug("Writing TPL..."); - writeStream.Seek(0L, SeekOrigin.Begin); - this.fireDebug(" Writing TPL Header... (Offset: 0x{0})", (object) writeStream.Position); - this.tplHeader.Write(writeStream); - int position1 = (int) writeStream.Position; - writeStream.Seek((long) (this.tplHeader.NumOfTextures * 8U), SeekOrigin.Current); - int num = 0; - for (int index = 0; (long) index < (long) this.tplHeader.NumOfTextures; ++index) - { - if (this.tplTextureHeaders[index].TextureFormat == 8U || this.tplTextureHeaders[index].TextureFormat == 9U || this.tplTextureHeaders[index].TextureFormat == 10U) - ++num; - } - int position2 = (int) writeStream.Position; - writeStream.Seek((long) (num * 12), SeekOrigin.Current); - for (int index = 0; (long) index < (long) this.tplHeader.NumOfTextures; ++index) - { - if (this.tplTextureHeaders[index].TextureFormat == 8U || this.tplTextureHeaders[index].TextureFormat == 9U || this.tplTextureHeaders[index].TextureFormat == 10U) + public void Dispose() { - this.fireDebug(" Writing Palette of Texture #{1}... (Offset: 0x{0})", (object) writeStream.Position, (object) (index + 1)); - writeStream.Seek(Shared.AddPadding(writeStream.Position, 32), SeekOrigin.Begin); - this.tplPaletteHeaders[index].PaletteDataOffset = (uint) writeStream.Position; - writeStream.Write(this.paletteData[index], 0, this.paletteData[index].Length); + Dispose(true); + GC.SuppressFinalize(this); } - } - int position3 = (int) writeStream.Position; - writeStream.Seek((long) (this.tplHeader.NumOfTextures * 36U), SeekOrigin.Current); - for (int index = 0; (long) index < (long) this.tplHeader.NumOfTextures; ++index) - { - this.fireDebug(" Writing Texture #{1} of {2}... (Offset: 0x{0})", (object) writeStream.Position, (object) (index + 1), (object) this.tplHeader.NumOfTextures); - writeStream.Seek((long) Shared.AddPadding((int) writeStream.Position, 32), SeekOrigin.Begin); - this.tplTextureHeaders[index].TextureDataOffset = (uint) writeStream.Position; - writeStream.Write(this.textureData[index], 0, this.textureData[index].Length); - } - while (writeStream.Position % 32L != 0L) - writeStream.WriteByte((byte) 0); - writeStream.Seek((long) position2, SeekOrigin.Begin); - for (int index = 0; (long) index < (long) this.tplHeader.NumOfTextures; ++index) - { - if (this.tplTextureHeaders[index].TextureFormat == 8U || this.tplTextureHeaders[index].TextureFormat == 9U || this.tplTextureHeaders[index].TextureFormat == 10U) + + protected virtual void Dispose(bool disposing) { - this.fireDebug(" Writing Palette Header of Texture #{1}... (Offset: 0x{0})", (object) writeStream.Position, (object) (index + 1)); - this.tplTextureEntries[index].PaletteHeaderOffset = (uint) writeStream.Position; - this.tplPaletteHeaders[index].Write(writeStream); - } - } - writeStream.Seek((long) position3, SeekOrigin.Begin); - for (int index = 0; (long) index < (long) this.tplHeader.NumOfTextures; ++index) - { - this.fireDebug(" Writing Texture Header #{1} of {2}... (Offset: 0x{0})", (object) writeStream.Position, (object) (index + 1), (object) this.tplHeader.NumOfTextures); - this.tplTextureEntries[index].TextureHeaderOffset = (uint) writeStream.Position; - this.tplTextureHeaders[index].Write(writeStream); - } - writeStream.Seek((long) position1, SeekOrigin.Begin); - for (int index = 0; (long) index < (long) this.tplHeader.NumOfTextures; ++index) - { - this.fireDebug(" Writing Texture Entry #{1} of {2}... (Offset: 0x{0})", (object) writeStream.Position, (object) (index + 1), (object) this.tplHeader.NumOfTextures); - this.tplTextureEntries[index].Write(writeStream); - } - this.fireDebug("Writing TPL Finished..."); - } - - private void parseTpl(Stream tplFile) - { - this.fireDebug("Parsing TPL..."); - this.tplHeader = new TPL_Header(); - this.tplTextureEntries = new List(); - this.tplTextureHeaders = new List(); - this.tplPaletteHeaders = new List(); - this.textureData = new List(); - this.paletteData = new List(); - tplFile.Seek(0L, SeekOrigin.Begin); - byte[] buffer1 = new byte[4]; - this.fireDebug(" Reading TPL Header: Magic... (Offset: 0x{0})", (object) tplFile.Position); - tplFile.Read(buffer1, 0, 4); - if ((int) Shared.Swap(BitConverter.ToUInt32(buffer1, 0)) != (int) this.tplHeader.TplMagic) - { - this.fireDebug(" -> Invalid Magic: 0x{0}", (object) Shared.Swap(BitConverter.ToUInt32(buffer1, 0))); - throw new Exception("TPL Header: Invalid Magic!"); - } - this.fireDebug(" Reading TPL Header: NumOfTextures... (Offset: 0x{0})", (object) tplFile.Position); - tplFile.Read(buffer1, 0, 4); - this.tplHeader.NumOfTextures = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); - this.fireDebug(" Reading TPL Header: Headersize... (Offset: 0x{0})", (object) tplFile.Position); - tplFile.Read(buffer1, 0, 4); - if ((int) Shared.Swap(BitConverter.ToUInt32(buffer1, 0)) != (int) this.tplHeader.HeaderSize) - { - this.fireDebug(" -> Invalid Headersize: 0x{0}", (object) Shared.Swap(BitConverter.ToUInt32(buffer1, 0))); - throw new Exception("TPL Header: Invalid Headersize!"); - } - for (int index = 0; (long) index < (long) this.tplHeader.NumOfTextures; ++index) - { - this.fireDebug(" Reading Texture Entry #{1} of {2}... (Offset: 0x{0})", (object) tplFile.Position, (object) (index + 1), (object) this.tplHeader.NumOfTextures); - TPL_TextureEntry tplTextureEntry = new TPL_TextureEntry(); - tplFile.Read(buffer1, 0, 4); - tplTextureEntry.TextureHeaderOffset = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); - tplFile.Read(buffer1, 0, 4); - tplTextureEntry.PaletteHeaderOffset = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); - this.tplTextureEntries.Add(tplTextureEntry); - } - for (int index = 0; (long) index < (long) this.tplHeader.NumOfTextures; ++index) - { - this.fireDebug(" Reading Texture Header #{1} of {2}... (Offset: 0x{0})", (object) tplFile.Position, (object) (index + 1), (object) this.tplHeader.NumOfTextures); - TPL_TextureHeader tplTextureHeader = new TPL_TextureHeader(); - TPL_PaletteHeader tplPaletteHeader = new TPL_PaletteHeader(); - tplFile.Seek((long) this.tplTextureEntries[index].TextureHeaderOffset, SeekOrigin.Begin); - tplFile.Read(buffer1, 0, 4); - tplTextureHeader.TextureHeight = Shared.Swap(BitConverter.ToUInt16(buffer1, 0)); - tplTextureHeader.TextureWidth = Shared.Swap(BitConverter.ToUInt16(buffer1, 2)); - tplFile.Read(buffer1, 0, 4); - tplTextureHeader.TextureFormat = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); - tplFile.Read(buffer1, 0, 4); - tplTextureHeader.TextureDataOffset = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); - tplFile.Read(buffer1, 0, 4); - tplTextureHeader.WrapS = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); - tplFile.Read(buffer1, 0, 4); - tplTextureHeader.WrapT = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); - tplFile.Read(buffer1, 0, 4); - tplTextureHeader.MinFilter = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); - tplFile.Read(buffer1, 0, 4); - tplTextureHeader.MagFilter = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); - tplFile.Read(buffer1, 0, 4); - tplTextureHeader.LodBias = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); - tplFile.Read(buffer1, 0, 4); - tplTextureHeader.EdgeLod = buffer1[0]; - tplTextureHeader.MinLod = buffer1[1]; - tplTextureHeader.MaxLod = buffer1[2]; - tplTextureHeader.Unpacked = buffer1[3]; - if (this.tplTextureEntries[index].PaletteHeaderOffset != 0U) - { - this.fireDebug(" Reading Palette Header #{1} of {2}... (Offset: 0x{0})", (object) tplFile.Position, (object) (index + 1), (object) this.tplHeader.NumOfTextures); - tplFile.Seek((long) this.tplTextureEntries[index].PaletteHeaderOffset, SeekOrigin.Begin); - tplFile.Read(buffer1, 0, 4); - tplPaletteHeader.NumberOfItems = Shared.Swap(BitConverter.ToUInt16(buffer1, 0)); - tplPaletteHeader.Unpacked = buffer1[2]; - tplPaletteHeader.Pad = buffer1[3]; - tplFile.Read(buffer1, 0, 4); - tplPaletteHeader.PaletteFormat = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); - tplFile.Read(buffer1, 0, 4); - tplPaletteHeader.PaletteDataOffset = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); - } - tplFile.Seek((long) tplTextureHeader.TextureDataOffset, SeekOrigin.Begin); - byte[] buffer2 = new byte[this.textureByteSize((TPL_TextureFormat) tplTextureHeader.TextureFormat, (int) tplTextureHeader.TextureWidth, (int) tplTextureHeader.TextureHeight)]; - byte[] buffer3 = new byte[(int) tplPaletteHeader.NumberOfItems * 2]; - this.fireDebug(" Reading Texture #{1} of {2}... (Offset: 0x{0})", (object) tplFile.Position, (object) (index + 1), (object) this.tplHeader.NumOfTextures); - tplFile.Read(buffer2, 0, buffer2.Length); - if (this.tplTextureEntries[index].PaletteHeaderOffset != 0U) - { - this.fireDebug(" Reading Palette #{1} of {2}... (Offset: 0x{0})", (object) tplFile.Position, (object) (index + 1), (object) this.tplHeader.NumOfTextures); - tplFile.Seek((long) tplPaletteHeader.PaletteDataOffset, SeekOrigin.Begin); - tplFile.Read(buffer3, 0, buffer3.Length); - } - else - buffer3 = new byte[0]; - this.tplTextureHeaders.Add(tplTextureHeader); - this.tplPaletteHeaders.Add(tplPaletteHeader); - this.textureData.Add(buffer2); - this.paletteData.Add(buffer3); - } - } - - private int textureByteSize(TPL_TextureFormat tplFormat, int width, int height) - { - switch (tplFormat) - { - case TPL_TextureFormat.I4: - return Shared.AddPadding(width, 8) * Shared.AddPadding(height, 8) / 2; - case TPL_TextureFormat.I8: - case TPL_TextureFormat.IA4: - return Shared.AddPadding(width, 8) * Shared.AddPadding(height, 4); - case TPL_TextureFormat.IA8: - case TPL_TextureFormat.RGB565: - case TPL_TextureFormat.RGB5A3: - return Shared.AddPadding(width, 4) * Shared.AddPadding(height, 4) * 2; - case TPL_TextureFormat.RGBA8: - return Shared.AddPadding(width, 4) * Shared.AddPadding(height, 4) * 4; - case TPL_TextureFormat.CI4: - return Shared.AddPadding(width, 8) * Shared.AddPadding(height, 8) / 2; - case TPL_TextureFormat.CI8: - return Shared.AddPadding(width, 8) * Shared.AddPadding(height, 4); - case TPL_TextureFormat.CI14X2: - return Shared.AddPadding(width, 4) * Shared.AddPadding(height, 4) * 2; - case TPL_TextureFormat.CMP: - return width * height; - default: - throw new FormatException("Unsupported Texture Format!"); - } - } - - private void createFromImages( - Image[] images, - TPL_TextureFormat[] tplFormats, - TPL_PaletteFormat[] paletteFormats) - { - this.tplHeader = new TPL_Header(); - this.tplTextureEntries = new List(); - this.tplTextureHeaders = new List(); - this.tplPaletteHeaders = new List(); - this.textureData = new List(); - this.paletteData = new List(); - this.tplHeader.NumOfTextures = (uint) images.Length; - for (int index = 0; index < images.Length; ++index) - { - Image image = images[index]; - TPL_TextureEntry tplTextureEntry = new TPL_TextureEntry(); - TPL_TextureHeader tplTextureHeader = new TPL_TextureHeader(); - TPL_PaletteHeader tplPaletteHeader = new TPL_PaletteHeader(); - byte[] numArray1 = this.imageToTpl(image, tplFormats[index]); - byte[] numArray2 = new byte[0]; - tplTextureHeader.TextureHeight = (ushort) image.Height; - tplTextureHeader.TextureWidth = (ushort) image.Width; - tplTextureHeader.TextureFormat = (uint) tplFormats[index]; - if (tplFormats[index] == TPL_TextureFormat.CI4 || tplFormats[index] == TPL_TextureFormat.CI8 || tplFormats[index] == TPL_TextureFormat.CI14X2) - { - ColorIndexConverter colorIndexConverter = new ColorIndexConverter(this.imageToRgba(image), image.Width, image.Height, tplFormats[index], paletteFormats[index]); - numArray1 = colorIndexConverter.Data; - numArray2 = colorIndexConverter.Palette; - tplPaletteHeader.NumberOfItems = (ushort) (numArray2.Length / 2); - tplPaletteHeader.PaletteFormat = (uint) paletteFormats[index]; - } - this.tplTextureEntries.Add(tplTextureEntry); - this.tplTextureHeaders.Add(tplTextureHeader); - this.tplPaletteHeaders.Add(tplPaletteHeader); - this.textureData.Add(numArray1); - this.paletteData.Add(numArray2); - } - } - - private byte[] imageToTpl(Image img, TPL_TextureFormat tplFormat) - { - switch (tplFormat) - { - case TPL_TextureFormat.I4: - return this.toI4((Bitmap) img); - case TPL_TextureFormat.I8: - return this.toI8((Bitmap) img); - case TPL_TextureFormat.IA4: - return this.toIA4((Bitmap) img); - case TPL_TextureFormat.IA8: - return this.toIA8((Bitmap) img); - case TPL_TextureFormat.RGB565: - return this.toRGB565((Bitmap) img); - case TPL_TextureFormat.RGB5A3: - return this.toRGB5A3((Bitmap) img); - case TPL_TextureFormat.RGBA8: - return this.toRGBA8((Bitmap) img); - case TPL_TextureFormat.CI4: - case TPL_TextureFormat.CI8: - case TPL_TextureFormat.CI14X2: - return new byte[0]; - default: - throw new FormatException("Format not supported!\nCurrently, images can only be converted to the following formats:\nI4, I8, IA4, IA8, RGB565, RGB5A3, RGBA8, CI4, CI8 , CI14X2."); - } - } - - private uint[] imageToRgba(Image img) - { - Bitmap bitmap = (Bitmap) img; - BitmapData bitmapdata = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); - byte[] numArray = new byte[bitmapdata.Height * Math.Abs(bitmapdata.Stride)]; - Marshal.Copy(bitmapdata.Scan0, numArray, 0, numArray.Length); - bitmap.UnlockBits(bitmapdata); - return Shared.ByteArrayToUIntArray(numArray); - } - - private Bitmap rgbaToImage(byte[] data, int width, int height) - { - if (width == 0) - width = 1; - if (height == 0) - height = 1; - Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); - try - { - BitmapData bitmapdata = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.WriteOnly, bitmap.PixelFormat); - Marshal.Copy(data, 0, bitmapdata.Scan0, data.Length); - bitmap.UnlockBits(bitmapdata); - return bitmap; - } - catch - { - bitmap.Dispose(); - throw; - } - } - - private uint[] paletteToRgba(int index) - { - TPL_PaletteFormat paletteFormat = (TPL_PaletteFormat) this.tplPaletteHeaders[index].PaletteFormat; - int numberOfItems = (int) this.tplPaletteHeaders[index].NumberOfItems; - uint[] numArray = new uint[numberOfItems]; - for (int index1 = 0; index1 < numberOfItems; ++index1) - { - if (index1 < numberOfItems) - { - ushort uint16 = BitConverter.ToUInt16(new byte[2] - { - this.paletteData[index][index1 * 2 + 1], - this.paletteData[index][index1 * 2] - }, 0); - int num1; - int num2; - int num3; - int num4; - switch (paletteFormat) - { - case TPL_PaletteFormat.IA8: - num1 = (int) uint16 & (int) byte.MaxValue; - num2 = num1; - num3 = num1; - num4 = (int) uint16 >> 8; - break; - case TPL_PaletteFormat.RGB565: - num2 = ((int) uint16 >> 11 & 31) << 3 & (int) byte.MaxValue; - num3 = ((int) uint16 >> 5 & 63) << 2 & (int) byte.MaxValue; - num1 = ((int) uint16 & 31) << 3 & (int) byte.MaxValue; - num4 = (int) byte.MaxValue; - break; - default: - if (((int) uint16 & 32768) != 0) - { - num4 = (int) byte.MaxValue; - num2 = ((int) uint16 >> 10 & 31) * (int) byte.MaxValue / 31; - num3 = ((int) uint16 >> 5 & 31) * (int) byte.MaxValue / 31; - num1 = ((int) uint16 & 31) * (int) byte.MaxValue / 31; - break; - } - num4 = ((int) uint16 >> 12 & 7) * (int) byte.MaxValue / 7; - num2 = ((int) uint16 >> 8 & 15) * (int) byte.MaxValue / 15; - num3 = ((int) uint16 >> 4 & 15) * (int) byte.MaxValue / 15; - num1 = ((int) uint16 & 15) * (int) byte.MaxValue / 15; - break; - } - numArray[index1] = (uint) (num1 | num3 << 8 | num2 << 16 | num4 << 24); - } - } - return numArray; - } - - private int avg(int w0, int w1, int c0, int c1) - { - int num1 = c0 >> 11; - int num2 = c1 >> 11; - int num3 = (w0 * num1 + w1 * num2) / (w0 + w1) << 11 & (int) ushort.MaxValue; - int num4 = c0 >> 5 & 63; - int num5 = c1 >> 5 & 63; - int num6 = (w0 * num4 + w1 * num5) / (w0 + w1) << 5 & (int) ushort.MaxValue; - int num7 = num3 | num6; - int num8 = c0 & 31; - int num9 = c1 & 31; - int num10 = (w0 * num8 + w1 * num9) / (w0 + w1); - return num7 | num10; - } - - private byte[] fromRGBA8(byte[] tpl, int width, int height) - { - uint[] array = new uint[width * height]; - int num1 = 0; - for (int index1 = 0; index1 < height; index1 += 4) - { - for (int index2 = 0; index2 < width; index2 += 4) - { - for (int index3 = 0; index3 < 2; ++index3) - { - for (int index4 = index1; index4 < index1 + 4; ++index4) + if (disposing && !isDisposed) { - for (int index5 = index2; index5 < index2 + 4; ++index5) - { - ushort num2 = Shared.Swap(BitConverter.ToUInt16(tpl, num1++ * 2)); - if (index5 < width && index4 < height) + tplHeader = null; + tplTextureEntries.Clear(); + tplTextureEntries = null; + tplTextureHeaders.Clear(); + tplTextureHeaders = null; + tplPaletteHeaders.Clear(); + tplPaletteHeaders = null; + textureData.Clear(); + textureData = null; + paletteData.Clear(); + paletteData = null; + } + isDisposed = true; + } + + public static TPL Load(string pathToTpl) + { + TPL tpl = new TPL(); + MemoryStream memoryStream = new MemoryStream(File.ReadAllBytes(pathToTpl)); + try + { + tpl.ParseTpl(memoryStream); + } + catch + { + memoryStream.Dispose(); + throw; + } + memoryStream.Dispose(); + return tpl; + } + + public static TPL Load(byte[] tplFile) + { + TPL tpl = new TPL(); + MemoryStream memoryStream = new MemoryStream(tplFile); + try + { + tpl.ParseTpl(memoryStream); + } + catch + { + memoryStream.Dispose(); + throw; + } + memoryStream.Dispose(); + return tpl; + } + + public static TPL Load(Stream tpl) + { + TPL tpl1 = new TPL(); + tpl1.ParseTpl(tpl); + return tpl1; + } + + public static TPL FromImage( + string pathToImage, + TPL_TextureFormat tplFormat, + TPL_PaletteFormat paletteFormat = TPL_PaletteFormat.RGB5A3) + { + return TPL.FromImages(new string[1] { pathToImage }, new TPL_TextureFormat[1] + { + tplFormat + }, new TPL_PaletteFormat[1] { paletteFormat }); + } + + public static TPL FromImage( + Image img, + TPL_TextureFormat tplFormat, + TPL_PaletteFormat paletteFormat = TPL_PaletteFormat.RGB5A3) + { + return TPL.FromImages(new Image[1] { img }, new TPL_TextureFormat[1] + { + tplFormat + }, new TPL_PaletteFormat[1] { paletteFormat }); + } + + public static TPL FromImages( + string[] imagePaths, + TPL_TextureFormat[] tplFormats, + TPL_PaletteFormat[] paletteFormats) + { + if (tplFormats.Length < imagePaths.Length) + { + throw new Exception("You must specify a format for each image!"); + } + + List imageList = new List(); + foreach (string imagePath in imagePaths) + { + imageList.Add(Image.FromFile(imagePath)); + } + + TPL tpl = new TPL(); + tpl.PrivCreateFromImages(imageList.ToArray(), tplFormats, paletteFormats); + return tpl; + } + + public static TPL FromImages( + Image[] images, + TPL_TextureFormat[] tplFormats, + TPL_PaletteFormat[] paletteFormats) + { + if (tplFormats.Length < images.Length) + { + throw new Exception("You must specify a format for each image!"); + } + + TPL tpl = new TPL(); + tpl.PrivCreateFromImages(images, tplFormats, paletteFormats); + return tpl; + } + + public void LoadFile(string pathToTpl) + { + MemoryStream memoryStream = new MemoryStream(File.ReadAllBytes(pathToTpl)); + try + { + ParseTpl(memoryStream); + } + catch + { + memoryStream.Dispose(); + throw; + } + memoryStream.Dispose(); + } + + public void LoadFile(byte[] tplFile) + { + MemoryStream memoryStream = new MemoryStream(tplFile); + try + { + ParseTpl(memoryStream); + } + catch + { + memoryStream.Dispose(); + throw; + } + memoryStream.Dispose(); + } + + public void LoadFile(Stream tpl) + { + ParseTpl(tpl); + } + + public void CreateFromImage( + string pathToImage, + TPL_TextureFormat tplFormat, + TPL_PaletteFormat paletteFormat = TPL_PaletteFormat.RGB5A3) + { + CreateFromImages(new string[1] { pathToImage }, new TPL_TextureFormat[1] + { + tplFormat + }, new TPL_PaletteFormat[1] { paletteFormat }); + } + + public void CreateFromImage( + Image img, + TPL_TextureFormat tplFormat, + TPL_PaletteFormat paletteFormat = TPL_PaletteFormat.RGB5A3) + { + PrivCreateFromImages(new Image[1] { img }, new TPL_TextureFormat[1] + { + tplFormat + }, new TPL_PaletteFormat[1] { paletteFormat }); + } + + public void CreateFromImages( + string[] imagePaths, + TPL_TextureFormat[] tplFormats, + TPL_PaletteFormat[] paletteFormats) + { + if (tplFormats.Length < imagePaths.Length) + { + throw new Exception("You must specify a format for each image!"); + } + + List imageList = new List(); + foreach (string imagePath in imagePaths) + { + imageList.Add(Image.FromFile(imagePath)); + } + + PrivCreateFromImages(imageList.ToArray(), tplFormats, paletteFormats); + } + + public void CreateFromImages( + Image[] images, + TPL_TextureFormat[] tplFormats, + TPL_PaletteFormat[] paletteFormats) + { + if (tplFormats.Length < images.Length) + { + throw new Exception("You must specify a format for each image!"); + } + + PrivCreateFromImages(images, tplFormats, paletteFormats); + } + + public void Save(string savePath) + { + if (File.Exists(savePath)) + { + File.Delete(savePath); + } + + FileStream fileStream = new FileStream(savePath, FileMode.Create); + try + { + WriteToStream(fileStream); + } + catch + { + fileStream.Dispose(); + throw; + } + fileStream.Dispose(); + } + + public MemoryStream ToMemoryStream() + { + MemoryStream memoryStream = new MemoryStream(); + try + { + WriteToStream(memoryStream); + return memoryStream; + } + catch + { + memoryStream.Dispose(); + throw; + } + } + + public byte[] ToByteArray() + { + return ToMemoryStream().ToArray(); + } + + public Image ExtractTexture() + { + return ExtractTexture(0); + } + + public Image ExtractTexture(int index) + { + byte[] data = tplTextureHeaders[index].TextureFormat switch + { + 0 => FromI4(textureData[index], tplTextureHeaders[index].TextureWidth, tplTextureHeaders[index].TextureHeight), + 1 => FromI8(textureData[index], tplTextureHeaders[index].TextureWidth, tplTextureHeaders[index].TextureHeight), + 2 => FromIA4(textureData[index], tplTextureHeaders[index].TextureWidth, tplTextureHeaders[index].TextureHeight), + 3 => FromIA8(textureData[index], tplTextureHeaders[index].TextureWidth, tplTextureHeaders[index].TextureHeight), + 4 => FromRGB565(textureData[index], tplTextureHeaders[index].TextureWidth, tplTextureHeaders[index].TextureHeight), + 5 => FromRGB5A3(textureData[index], tplTextureHeaders[index].TextureWidth, tplTextureHeaders[index].TextureHeight), + 6 => FromRGBA8(textureData[index], tplTextureHeaders[index].TextureWidth, tplTextureHeaders[index].TextureHeight), + 8 => FromCI4(textureData[index], PaletteToRgba(index), tplTextureHeaders[index].TextureWidth, tplTextureHeaders[index].TextureHeight), + 9 => FromCI8(textureData[index], PaletteToRgba(index), tplTextureHeaders[index].TextureWidth, tplTextureHeaders[index].TextureHeight), + 10 => FromCI14X2(textureData[index], PaletteToRgba(index), tplTextureHeaders[index].TextureWidth, tplTextureHeaders[index].TextureHeight), + 14 => FromCMP(textureData[index], tplTextureHeaders[index].TextureWidth, tplTextureHeaders[index].TextureHeight), + _ => throw new FormatException("Unsupported Texture Format!"), + }; + return RgbaToImage(data, tplTextureHeaders[index].TextureWidth, tplTextureHeaders[index].TextureHeight); + } + + public void ExtractTexture(string savePath) + { + ExtractTexture(0, savePath); + } + + public void ExtractTexture(int index, string savePath) + { + if (File.Exists(savePath)) + { + File.Delete(savePath); + } + + Image texture = ExtractTexture(index); + switch (Path.GetExtension(savePath).ToLower()) + { + case ".tif": + case ".tiff": + texture.Save(savePath, ImageFormat.Tiff); + break; + case ".bmp": + texture.Save(savePath, ImageFormat.Bmp); + break; + case ".gif": + texture.Save(savePath, ImageFormat.Gif); + break; + case ".jpg": + case ".jpeg": + texture.Save(savePath, ImageFormat.Jpeg); + break; + default: + texture.Save(savePath, ImageFormat.Png); + break; + } + } + + public Image[] ExtractAllTextures() + { + List imageList = new List(); + for (int index = 0; index < tplHeader.NumOfTextures; ++index) + { + imageList.Add(ExtractTexture(index)); + } + + return imageList.ToArray(); + } + + public void ExtractAllTextures(string saveDir) + { + if (Directory.Exists(saveDir)) + { + Directory.CreateDirectory(saveDir); + } + + for (int index = 0; index < tplHeader.NumOfTextures; ++index) + { + ExtractTexture(index, saveDir + Path.DirectorySeparatorChar.ToString() + "Texture_" + index.ToString("x2") + ".png"); + } + } + + public void AddTexture( + string imagePath, + TPL_TextureFormat tplFormat, + TPL_PaletteFormat paletteFormat = TPL_PaletteFormat.RGB5A3) + { + AddTexture(Image.FromFile(imagePath), tplFormat, paletteFormat); + } + + public void AddTexture(Image img, TPL_TextureFormat tplFormat, TPL_PaletteFormat paletteFormat = TPL_PaletteFormat.RGB5A3) + { + TPL_TextureEntry tplTextureEntry = new TPL_TextureEntry(); + TPL_TextureHeader tplTextureHeader = new TPL_TextureHeader(); + TPL_PaletteHeader tplPaletteHeader = new TPL_PaletteHeader(); + byte[] numArray1 = ImageToTpl(img, tplFormat); + byte[] numArray2 = new byte[0]; + tplTextureHeader.TextureHeight = (ushort)img.Height; + tplTextureHeader.TextureWidth = (ushort)img.Width; + tplTextureHeader.TextureFormat = (uint)tplFormat; + if (tplFormat == TPL_TextureFormat.CI4 || tplFormat == TPL_TextureFormat.CI8 || tplFormat == TPL_TextureFormat.CI14X2) + { + ColorIndexConverter colorIndexConverter = new ColorIndexConverter(ImageToRgba(img), img.Width, img.Height, tplFormat, paletteFormat); + numArray1 = colorIndexConverter.Data; + numArray2 = colorIndexConverter.Palette; + tplPaletteHeader.NumberOfItems = (ushort)(numArray2.Length / 2); + tplPaletteHeader.PaletteFormat = (uint)paletteFormat; + } + tplTextureEntries.Add(tplTextureEntry); + tplTextureHeaders.Add(tplTextureHeader); + tplPaletteHeaders.Add(tplPaletteHeader); + textureData.Add(numArray1); + paletteData.Add(numArray2); + ++tplHeader.NumOfTextures; + } + + public void RemoveTexture(int index) + { + if (tplHeader.NumOfTextures <= index) + { + return; + } + + tplTextureEntries.RemoveAt(index); + tplTextureHeaders.RemoveAt(index); + tplPaletteHeaders.RemoveAt(index); + textureData.RemoveAt(index); + paletteData.RemoveAt(index); + --tplHeader.NumOfTextures; + } + + public TPL_TextureFormat GetTextureFormat(int index) + { + return (TPL_TextureFormat)tplTextureHeaders[index].TextureFormat; + } + + public TPL_PaletteFormat GetPaletteFormat(int index) + { + return (TPL_PaletteFormat)tplPaletteHeaders[index].PaletteFormat; + } + + public Size GetTextureSize(int index) + { + return new Size(tplTextureHeaders[index].TextureWidth, tplTextureHeaders[index].TextureHeight); + } + + private void WriteToStream(Stream writeStream) + { + FireDebug("Writing TPL..."); + writeStream.Seek(0L, SeekOrigin.Begin); + FireDebug(" Writing TPL Header... (Offset: 0x{0})", (object)writeStream.Position); + tplHeader.Write(writeStream); + int position1 = (int)writeStream.Position; + writeStream.Seek(tplHeader.NumOfTextures * 8U, SeekOrigin.Current); + int num = 0; + for (int index = 0; index < tplHeader.NumOfTextures; ++index) + { + if (tplTextureHeaders[index].TextureFormat == 8U || tplTextureHeaders[index].TextureFormat == 9U || tplTextureHeaders[index].TextureFormat == 10U) { - if (index3 == 0) - { - int num3 = (int) num2 >> 8 & (int) byte.MaxValue; - int num4 = (int) num2 & (int) byte.MaxValue; - array[index5 + index4 * width] |= (uint) (num4 << 16 | num3 << 24); - } - else - { - int num3 = (int) num2 >> 8 & (int) byte.MaxValue; - int num4 = (int) num2 & (int) byte.MaxValue; - array[index5 + index4 * width] |= (uint) (num3 << 8 | num4); - } + ++num; } - } } - } - } - } - return Shared.UIntArrayToByteArray(array); - } - - private byte[] toRGBA8(Bitmap img) - { - uint[] rgba = this.imageToRgba((Image) img); - int width = img.Width; - int height = img.Height; - int index1 = 0; - int num1 = 0; - byte[] numArray1 = new byte[Shared.AddPadding(width, 4) * Shared.AddPadding(height, 4) * 4]; - uint[] numArray2 = new uint[32]; - uint[] numArray3 = new uint[32]; - uint[] numArray4 = new uint[32]; - uint[] numArray5 = new uint[32]; - for (int index2 = 0; index2 < height; index2 += 4) - { - for (int index3 = 0; index3 < width; index3 += 4) - { - for (int index4 = index2; index4 < index2 + 4; ++index4) - { - for (int index5 = index3; index5 < index3 + 4; ++index5) + int position2 = (int)writeStream.Position; + writeStream.Seek(num * 12, SeekOrigin.Current); + for (int index = 0; index < tplHeader.NumOfTextures; ++index) { - uint num2 = index4 >= height || index5 >= width ? 0U : rgba[index5 + index4 * width]; - numArray2[index1] = num2 >> 16 & (uint) byte.MaxValue; - numArray3[index1] = num2 >> 8 & (uint) byte.MaxValue; - numArray4[index1] = num2 & (uint) byte.MaxValue; - numArray5[index1] = num2 >> 24 & (uint) byte.MaxValue; - ++index1; - } - } - if (index1 == 16) - { - for (int index4 = 0; index4 < 16; ++index4) - { - byte[] numArray6 = numArray1; - int index5 = num1; - int num2 = index5 + 1; - int num3 = (int) (byte) numArray5[index4]; - numArray6[index5] = (byte) num3; - byte[] numArray7 = numArray1; - int index6 = num2; - num1 = index6 + 1; - int num4 = (int) (byte) numArray2[index4]; - numArray7[index6] = (byte) num4; - } - for (int index4 = 0; index4 < 16; ++index4) - { - byte[] numArray6 = numArray1; - int index5 = num1; - int num2 = index5 + 1; - int num3 = (int) (byte) numArray3[index4]; - numArray6[index5] = (byte) num3; - byte[] numArray7 = numArray1; - int index6 = num2; - num1 = index6 + 1; - int num4 = (int) (byte) numArray4[index4]; - numArray7[index6] = (byte) num4; - } - index1 = 0; - } - } - } - return numArray1; - } - - private byte[] fromRGB5A3(byte[] tpl, int width, int height) - { - uint[] array = new uint[width * height]; - int num1 = 0; - for (int index1 = 0; index1 < height; index1 += 4) - { - for (int index2 = 0; index2 < width; index2 += 4) - { - for (int index3 = index1; index3 < index1 + 4; ++index3) - { - for (int index4 = index2; index4 < index2 + 4; ++index4) - { - ushort num2 = Shared.Swap(BitConverter.ToUInt16(tpl, num1++ * 2)); - if (index3 < height && index4 < width) - { - int num3; - int num4; - int num5; - int num6; - if (((int) num2 & 32768) != 0) + if (tplTextureHeaders[index].TextureFormat == 8U || tplTextureHeaders[index].TextureFormat == 9U || tplTextureHeaders[index].TextureFormat == 10U) { - num3 = ((int) num2 >> 10 & 31) * (int) byte.MaxValue / 31; - num4 = ((int) num2 >> 5 & 31) * (int) byte.MaxValue / 31; - num5 = ((int) num2 & 31) * (int) byte.MaxValue / 31; - num6 = (int) byte.MaxValue; + FireDebug(" Writing Palette of Texture #{1}... (Offset: 0x{0})", writeStream.Position, index + 1); + writeStream.Seek(Shared.AddPadding(writeStream.Position, 32), SeekOrigin.Begin); + tplPaletteHeaders[index].PaletteDataOffset = (uint)writeStream.Position; + writeStream.Write(paletteData[index], 0, paletteData[index].Length); + } + } + int position3 = (int)writeStream.Position; + writeStream.Seek(tplHeader.NumOfTextures * 36U, SeekOrigin.Current); + for (int index = 0; index < tplHeader.NumOfTextures; ++index) + { + FireDebug(" Writing Texture #{1} of {2}... (Offset: 0x{0})", writeStream.Position, index + 1, tplHeader.NumOfTextures); + writeStream.Seek(Shared.AddPadding((int)writeStream.Position, 32), SeekOrigin.Begin); + tplTextureHeaders[index].TextureDataOffset = (uint)writeStream.Position; + writeStream.Write(textureData[index], 0, textureData[index].Length); + } + while (writeStream.Position % 32L != 0L) + { + writeStream.WriteByte(0); + } + + writeStream.Seek(position2, SeekOrigin.Begin); + for (int index = 0; index < tplHeader.NumOfTextures; ++index) + { + if (tplTextureHeaders[index].TextureFormat == 8U || tplTextureHeaders[index].TextureFormat == 9U || tplTextureHeaders[index].TextureFormat == 10U) + { + FireDebug(" Writing Palette Header of Texture #{1}... (Offset: 0x{0})", writeStream.Position, index + 1); + tplTextureEntries[index].PaletteHeaderOffset = (uint)writeStream.Position; + tplPaletteHeaders[index].Write(writeStream); + } + } + writeStream.Seek(position3, SeekOrigin.Begin); + for (int index = 0; index < tplHeader.NumOfTextures; ++index) + { + FireDebug(" Writing Texture Header #{1} of {2}... (Offset: 0x{0})", writeStream.Position, index + 1, tplHeader.NumOfTextures); + tplTextureEntries[index].TextureHeaderOffset = (uint)writeStream.Position; + tplTextureHeaders[index].Write(writeStream); + } + writeStream.Seek(position1, SeekOrigin.Begin); + for (int index = 0; index < tplHeader.NumOfTextures; ++index) + { + FireDebug(" Writing Texture Entry #{1} of {2}... (Offset: 0x{0})", writeStream.Position, index + 1, tplHeader.NumOfTextures); + tplTextureEntries[index].Write(writeStream); + } + FireDebug("Writing TPL Finished..."); + } + + private void ParseTpl(Stream tplFile) + { + FireDebug("Parsing TPL..."); + tplHeader = new TPL_Header(); + tplTextureEntries = new List(); + tplTextureHeaders = new List(); + tplPaletteHeaders = new List(); + textureData = new List(); + paletteData = new List(); + tplFile.Seek(0L, SeekOrigin.Begin); + byte[] buffer1 = new byte[4]; + FireDebug(" Reading TPL Header: Magic... (Offset: 0x{0})", (object)tplFile.Position); + tplFile.Read(buffer1, 0, 4); + if ((int)Shared.Swap(BitConverter.ToUInt32(buffer1, 0)) != (int)tplHeader.TplMagic) + { + FireDebug(" -> Invalid Magic: 0x{0}", (object)Shared.Swap(BitConverter.ToUInt32(buffer1, 0))); + throw new Exception("TPL Header: Invalid Magic!"); + } + FireDebug(" Reading TPL Header: NumOfTextures... (Offset: 0x{0})", (object)tplFile.Position); + tplFile.Read(buffer1, 0, 4); + tplHeader.NumOfTextures = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); + FireDebug(" Reading TPL Header: Headersize... (Offset: 0x{0})", (object)tplFile.Position); + tplFile.Read(buffer1, 0, 4); + if ((int)Shared.Swap(BitConverter.ToUInt32(buffer1, 0)) != (int)tplHeader.HeaderSize) + { + FireDebug(" -> Invalid Headersize: 0x{0}", (object)Shared.Swap(BitConverter.ToUInt32(buffer1, 0))); + throw new Exception("TPL Header: Invalid Headersize!"); + } + for (int index = 0; index < tplHeader.NumOfTextures; ++index) + { + FireDebug(" Reading Texture Entry #{1} of {2}... (Offset: 0x{0})", tplFile.Position, index + 1, tplHeader.NumOfTextures); + TPL_TextureEntry tplTextureEntry = new TPL_TextureEntry(); + tplFile.Read(buffer1, 0, 4); + tplTextureEntry.TextureHeaderOffset = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); + tplFile.Read(buffer1, 0, 4); + tplTextureEntry.PaletteHeaderOffset = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); + tplTextureEntries.Add(tplTextureEntry); + } + for (int index = 0; index < tplHeader.NumOfTextures; ++index) + { + FireDebug(" Reading Texture Header #{1} of {2}... (Offset: 0x{0})", tplFile.Position, index + 1, tplHeader.NumOfTextures); + TPL_TextureHeader tplTextureHeader = new TPL_TextureHeader(); + TPL_PaletteHeader tplPaletteHeader = new TPL_PaletteHeader(); + tplFile.Seek(tplTextureEntries[index].TextureHeaderOffset, SeekOrigin.Begin); + tplFile.Read(buffer1, 0, 4); + tplTextureHeader.TextureHeight = Shared.Swap(BitConverter.ToUInt16(buffer1, 0)); + tplTextureHeader.TextureWidth = Shared.Swap(BitConverter.ToUInt16(buffer1, 2)); + tplFile.Read(buffer1, 0, 4); + tplTextureHeader.TextureFormat = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); + tplFile.Read(buffer1, 0, 4); + tplTextureHeader.TextureDataOffset = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); + tplFile.Read(buffer1, 0, 4); + tplTextureHeader.WrapS = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); + tplFile.Read(buffer1, 0, 4); + tplTextureHeader.WrapT = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); + tplFile.Read(buffer1, 0, 4); + tplTextureHeader.MinFilter = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); + tplFile.Read(buffer1, 0, 4); + tplTextureHeader.MagFilter = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); + tplFile.Read(buffer1, 0, 4); + tplTextureHeader.LodBias = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); + tplFile.Read(buffer1, 0, 4); + tplTextureHeader.EdgeLod = buffer1[0]; + tplTextureHeader.MinLod = buffer1[1]; + tplTextureHeader.MaxLod = buffer1[2]; + tplTextureHeader.Unpacked = buffer1[3]; + if (tplTextureEntries[index].PaletteHeaderOffset != 0U) + { + FireDebug(" Reading Palette Header #{1} of {2}... (Offset: 0x{0})", tplFile.Position, index + 1, tplHeader.NumOfTextures); + tplFile.Seek(tplTextureEntries[index].PaletteHeaderOffset, SeekOrigin.Begin); + tplFile.Read(buffer1, 0, 4); + tplPaletteHeader.NumberOfItems = Shared.Swap(BitConverter.ToUInt16(buffer1, 0)); + tplPaletteHeader.Unpacked = buffer1[2]; + tplPaletteHeader.Pad = buffer1[3]; + tplFile.Read(buffer1, 0, 4); + tplPaletteHeader.PaletteFormat = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); + tplFile.Read(buffer1, 0, 4); + tplPaletteHeader.PaletteDataOffset = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); + } + tplFile.Seek(tplTextureHeader.TextureDataOffset, SeekOrigin.Begin); + byte[] buffer2 = new byte[TextureByteSize((TPL_TextureFormat)tplTextureHeader.TextureFormat, tplTextureHeader.TextureWidth, tplTextureHeader.TextureHeight)]; + byte[] buffer3 = new byte[tplPaletteHeader.NumberOfItems * 2]; + FireDebug(" Reading Texture #{1} of {2}... (Offset: 0x{0})", tplFile.Position, index + 1, tplHeader.NumOfTextures); + tplFile.Read(buffer2, 0, buffer2.Length); + if (tplTextureEntries[index].PaletteHeaderOffset != 0U) + { + FireDebug(" Reading Palette #{1} of {2}... (Offset: 0x{0})", tplFile.Position, index + 1, tplHeader.NumOfTextures); + tplFile.Seek(tplPaletteHeader.PaletteDataOffset, SeekOrigin.Begin); + tplFile.Read(buffer3, 0, buffer3.Length); } else { - num6 = ((int) num2 >> 12 & 7) * (int) byte.MaxValue / 7; - num3 = ((int) num2 >> 8 & 15) * (int) byte.MaxValue / 15; - num4 = ((int) num2 >> 4 & 15) * (int) byte.MaxValue / 15; - num5 = ((int) num2 & 15) * (int) byte.MaxValue / 15; + buffer3 = new byte[0]; } - array[index3 * width + index4] = (uint) (num5 | num4 << 8 | num3 << 16 | num6 << 24); - } - } - } - } - } - return Shared.UIntArrayToByteArray(array); - } - private byte[] toRGB5A3(Bitmap img) - { - uint[] rgba = this.imageToRgba((Image) img); - int width = img.Width; - int height = img.Height; - int num1 = -1; - byte[] numArray = new byte[Shared.AddPadding(width, 4) * Shared.AddPadding(height, 4) * 2]; - for (int index1 = 0; index1 < height; index1 += 4) - { - for (int index2 = 0; index2 < width; index2 += 4) + tplTextureHeaders.Add(tplTextureHeader); + tplPaletteHeaders.Add(tplPaletteHeader); + textureData.Add(buffer2); + paletteData.Add(buffer3); + } + } + + private int TextureByteSize(TPL_TextureFormat tplFormat, int width, int height) { - for (int index3 = index1; index3 < index1 + 4; ++index3) - { - for (int index4 = index2; index4 < index2 + 4; ++index4) + return tplFormat switch { - int num2; - if (index3 >= height || index4 >= width) - { - num2 = 0; - } - else - { - int num3 = (int) rgba[index4 + index3 * width]; - int num4 = 0; - int num5 = num3 >> 16 & (int) byte.MaxValue; - int num6 = num3 >> 8 & (int) byte.MaxValue; - int num7 = num3 & (int) byte.MaxValue; - int num8 = num3 >> 24 & (int) byte.MaxValue; - if (num8 <= 218) + TPL_TextureFormat.I4 => Shared.AddPadding(width, 8) * Shared.AddPadding(height, 8) / 2, + TPL_TextureFormat.I8 or TPL_TextureFormat.IA4 => Shared.AddPadding(width, 8) * Shared.AddPadding(height, 4), + TPL_TextureFormat.IA8 or TPL_TextureFormat.RGB565 or TPL_TextureFormat.RGB5A3 => Shared.AddPadding(width, 4) * Shared.AddPadding(height, 4) * 2, + TPL_TextureFormat.RGBA8 => Shared.AddPadding(width, 4) * Shared.AddPadding(height, 4) * 4, + TPL_TextureFormat.CI4 => Shared.AddPadding(width, 8) * Shared.AddPadding(height, 8) / 2, + TPL_TextureFormat.CI8 => Shared.AddPadding(width, 8) * Shared.AddPadding(height, 4), + TPL_TextureFormat.CI14X2 => Shared.AddPadding(width, 4) * Shared.AddPadding(height, 4) * 2, + TPL_TextureFormat.CMP => width * height, + _ => throw new FormatException("Unsupported Texture Format!"), + }; + } + + private void PrivCreateFromImages( + Image[] images, + TPL_TextureFormat[] tplFormats, + TPL_PaletteFormat[] paletteFormats) + { + tplHeader = new TPL_Header(); + tplTextureEntries = new List(); + tplTextureHeaders = new List(); + tplPaletteHeaders = new List(); + textureData = new List(); + paletteData = new List(); + tplHeader.NumOfTextures = (uint)images.Length; + for (int index = 0; index < images.Length; ++index) + { + Image image = images[index]; + TPL_TextureEntry tplTextureEntry = new TPL_TextureEntry(); + TPL_TextureHeader tplTextureHeader = new TPL_TextureHeader(); + TPL_PaletteHeader tplPaletteHeader = new TPL_PaletteHeader(); + byte[] numArray1 = ImageToTpl(image, tplFormats[index]); + byte[] numArray2 = new byte[0]; + tplTextureHeader.TextureHeight = (ushort)image.Height; + tplTextureHeader.TextureWidth = (ushort)image.Width; + tplTextureHeader.TextureFormat = (uint)tplFormats[index]; + if (tplFormats[index] == TPL_TextureFormat.CI4 || tplFormats[index] == TPL_TextureFormat.CI8 || tplFormats[index] == TPL_TextureFormat.CI14X2) { - int num9 = num4 & -32769; - int num10 = num5 * 15 / (int) byte.MaxValue & 15; - int num11 = num6 * 15 / (int) byte.MaxValue & 15; - int num12 = num7 * 15 / (int) byte.MaxValue & 15; - int num13 = num8 * 7 / (int) byte.MaxValue & 7; - num2 = num9 | (num13 << 12 | num10 << 8 | num11 << 4 | num12); + ColorIndexConverter colorIndexConverter = new ColorIndexConverter(ImageToRgba(image), image.Width, image.Height, tplFormats[index], paletteFormats[index]); + numArray1 = colorIndexConverter.Data; + numArray2 = colorIndexConverter.Palette; + tplPaletteHeader.NumberOfItems = (ushort)(numArray2.Length / 2); + tplPaletteHeader.PaletteFormat = (uint)paletteFormats[index]; } - else - num2 = num4 | 32768 | ((num5 * 31 / (int) byte.MaxValue & 31) << 10 | (num6 * 31 / (int) byte.MaxValue & 31) << 5 | num7 * 31 / (int) byte.MaxValue & 31); - } - int num14; - numArray[num14 = num1 + 1] = (byte) (num2 >> 8); - numArray[num1 = num14 + 1] = (byte) (num2 & (int) byte.MaxValue); + tplTextureEntries.Add(tplTextureEntry); + tplTextureHeaders.Add(tplTextureHeader); + tplPaletteHeaders.Add(tplPaletteHeader); + textureData.Add(numArray1); + paletteData.Add(numArray2); } - } } - } - return numArray; - } - private byte[] fromRGB565(byte[] tpl, int width, int height) - { - uint[] array = new uint[width * height]; - int num1 = 0; - for (int index1 = 0; index1 < height; index1 += 4) - { - for (int index2 = 0; index2 < width; index2 += 4) + private byte[] ImageToTpl(Image img, TPL_TextureFormat tplFormat) { - for (int index3 = index1; index3 < index1 + 4; ++index3) - { - for (int index4 = index2; index4 < index2 + 4; ++index4) + return tplFormat switch { - ushort num2 = Shared.Swap(BitConverter.ToUInt16(tpl, num1++ * 2)); - if (index3 < height && index4 < width) - { - int num3 = ((int) num2 >> 11 & 31) << 3 & (int) byte.MaxValue; - int num4 = ((int) num2 >> 5 & 63) << 2 & (int) byte.MaxValue; - int num5 = ((int) num2 & 31) << 3 & (int) byte.MaxValue; - array[index3 * width + index4] = (uint) (num5 | num4 << 8 | num3 << 16 | -16777216); - } - } - } + TPL_TextureFormat.I4 => ToI4((Bitmap)img), + TPL_TextureFormat.I8 => ToI8((Bitmap)img), + TPL_TextureFormat.IA4 => ToIA4((Bitmap)img), + TPL_TextureFormat.IA8 => ToIA8((Bitmap)img), + TPL_TextureFormat.RGB565 => ToRGB565((Bitmap)img), + TPL_TextureFormat.RGB5A3 => ToRGB5A3((Bitmap)img), + TPL_TextureFormat.RGBA8 => ToRGBA8((Bitmap)img), + TPL_TextureFormat.CI4 or TPL_TextureFormat.CI8 or TPL_TextureFormat.CI14X2 => new byte[0], + _ => throw new FormatException("Format not supported!\nCurrently, images can only be converted to the following formats:\nI4, I8, IA4, IA8, RGB565, RGB5A3, RGBA8, CI4, CI8 , CI14X2."), + }; } - } - return Shared.UIntArrayToByteArray(array); - } - private byte[] toRGB565(Bitmap img) - { - uint[] rgba = this.imageToRgba((Image) img); - int width = img.Width; - int height = img.Height; - int num1 = -1; - byte[] numArray = new byte[Shared.AddPadding(width, 4) * Shared.AddPadding(height, 4) * 2]; - for (int index1 = 0; index1 < height; index1 += 4) - { - for (int index2 = 0; index2 < width; index2 += 4) + private uint[] ImageToRgba(Image img) { - for (int index3 = index1; index3 < index1 + 4; ++index3) - { - for (int index4 = index2; index4 < index2 + 4; ++index4) + Bitmap bitmap = (Bitmap)img; + BitmapData bitmapdata = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); + byte[] numArray = new byte[bitmapdata.Height * Math.Abs(bitmapdata.Stride)]; + Marshal.Copy(bitmapdata.Scan0, numArray, 0, numArray.Length); + bitmap.UnlockBits(bitmapdata); + return Shared.ByteArrayToUIntArray(numArray); + } + + private Bitmap RgbaToImage(byte[] data, int width, int height) + { + if (width == 0) { - ushort num2; - if (index3 >= height || index4 >= width) - { - num2 = (ushort) 0; - } - else - { - int num3 = (int) rgba[index4 + index3 * width]; - num2 = (ushort) ((uint) ((int) (((uint) num3 >> 16 & (uint) byte.MaxValue) >> 3) << 11 | (int) (((uint) num3 >> 8 & (uint) byte.MaxValue) >> 2) << 5) | (uint) (num3 & (int) byte.MaxValue) >> 3); - } - int num4; - numArray[num4 = num1 + 1] = (byte) ((uint) num2 >> 8); - numArray[num1 = num4 + 1] = (byte) ((uint) num2 & (uint) byte.MaxValue); + width = 1; } - } - } - } - return numArray; - } - private byte[] fromI4(byte[] tpl, int width, int height) - { - uint[] array = new uint[width * height]; - int num1 = 0; - for (int index1 = 0; index1 < height; index1 += 8) - { - for (int index2 = 0; index2 < width; index2 += 8) - { - for (int index3 = index1; index3 < index1 + 8; ++index3) - { - for (int index4 = index2; index4 < index2 + 8; index4 += 2) + if (height == 0) { - int num2 = (int) tpl[num1++]; - if (index3 < height && index4 < width) - { - int num3 = (num2 >> 4) * (int) byte.MaxValue / 15; - array[index3 * width + index4] = (uint) (num3 | num3 << 8 | num3 << 16 | -16777216); - int num4 = (num2 & 15) * (int) byte.MaxValue / 15; - if (index3 * width + index4 + 1 < array.Length) - array[index3 * width + index4 + 1] = (uint) (num4 | num4 << 8 | num4 << 16 | -16777216); - } + height = 1; } - } - } - } - return Shared.UIntArrayToByteArray(array); - } - private byte[] toI4(Bitmap img) - { - uint[] rgba = this.imageToRgba((Image) img); - int width = img.Width; - int height = img.Height; - int num1 = 0; - byte[] numArray = new byte[Shared.AddPadding(width, 8) * Shared.AddPadding(height, 8) / 2]; - for (int index1 = 0; index1 < height; index1 += 8) - { - for (int index2 = 0; index2 < width; index2 += 8) - { - for (int index3 = index1; index3 < index1 + 8; ++index3) - { - for (int index4 = index2; index4 < index2 + 8; index4 += 2) + Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); + try { - byte num2; - if (index4 >= width || index3 >= height) - { - num2 = (byte) 0; - } - else - { - int num3 = (int) rgba[index4 + index3 * width]; - int num4 = (int) (((uint) (num3 & (int) byte.MaxValue) + ((uint) num3 >> 8 & (uint) byte.MaxValue) + ((uint) num3 >> 16 & (uint) byte.MaxValue)) / 3U) & (int) byte.MaxValue; - int num5 = index4 + index3 * width + 1 < rgba.Length ? (int) rgba[index4 + index3 * width + 1] : 0; - uint num6 = ((uint) (num5 & (int) byte.MaxValue) + ((uint) num5 >> 8 & (uint) byte.MaxValue) + ((uint) num5 >> 16 & (uint) byte.MaxValue)) / 3U & (uint) byte.MaxValue; - num2 = (byte) ((int) ((uint) (num4 * 15) / (uint) byte.MaxValue) << 4 | (int) (num6 * 15U / (uint) byte.MaxValue) & 15); - } - numArray[num1++] = num2; + BitmapData bitmapdata = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.WriteOnly, bitmap.PixelFormat); + Marshal.Copy(data, 0, bitmapdata.Scan0, data.Length); + bitmap.UnlockBits(bitmapdata); + return bitmap; } - } - } - } - return numArray; - } - - private byte[] fromI8(byte[] tpl, int width, int height) - { - uint[] array = new uint[width * height]; - int num1 = 0; - for (int index1 = 0; index1 < height; index1 += 4) - { - for (int index2 = 0; index2 < width; index2 += 8) - { - for (int index3 = index1; index3 < index1 + 4; ++index3) - { - for (int index4 = index2; index4 < index2 + 8; ++index4) + catch { - int num2 = (int) tpl[num1++]; - if (index3 < height && index4 < width) - array[index3 * width + index4] = (uint) (num2 | num2 << 8 | num2 << 16 | -16777216); + bitmap.Dispose(); + throw; } - } } - } - return Shared.UIntArrayToByteArray(array); - } - private byte[] toI8(Bitmap img) - { - uint[] rgba = this.imageToRgba((Image) img); - int width = img.Width; - int height = img.Height; - int num1 = 0; - byte[] numArray = new byte[Shared.AddPadding(width, 8) * Shared.AddPadding(height, 4)]; - for (int index1 = 0; index1 < height; index1 += 4) - { - for (int index2 = 0; index2 < width; index2 += 8) + private uint[] PaletteToRgba(int index) { - for (int index3 = index1; index3 < index1 + 4; ++index3) - { - for (int index4 = index2; index4 < index2 + 8; ++index4) + TPL_PaletteFormat paletteFormat = (TPL_PaletteFormat)tplPaletteHeaders[index].PaletteFormat; + int numberOfItems = tplPaletteHeaders[index].NumberOfItems; + uint[] numArray = new uint[numberOfItems]; + for (int index1 = 0; index1 < numberOfItems; ++index1) { - byte num2; - if (index4 >= width || index3 >= height) - { - num2 = (byte) 0; - } - else - { - int num3 = (int) rgba[index4 + index3 * width]; - num2 = (byte) (((uint) (num3 & (int) byte.MaxValue) + ((uint) num3 >> 8 & (uint) byte.MaxValue) + ((uint) num3 >> 16 & (uint) byte.MaxValue)) / 3U & (uint) byte.MaxValue); - } - numArray[num1++] = num2; + if (index1 < numberOfItems) + { + ushort uint16 = BitConverter.ToUInt16(new byte[2] + { + paletteData[index][index1 * 2 + 1], + paletteData[index][index1 * 2] + }, 0); + int num1; + int num2; + int num3; + int num4; + switch (paletteFormat) + { + case TPL_PaletteFormat.IA8: + num1 = uint16 & byte.MaxValue; + num2 = num1; + num3 = num1; + num4 = uint16 >> 8; + break; + case TPL_PaletteFormat.RGB565: + num2 = (uint16 >> 11 & 31) << 3 & byte.MaxValue; + num3 = (uint16 >> 5 & 63) << 2 & byte.MaxValue; + num1 = (uint16 & 31) << 3 & byte.MaxValue; + num4 = byte.MaxValue; + break; + default: + if ((uint16 & 32768) != 0) + { + num4 = byte.MaxValue; + num2 = (uint16 >> 10 & 31) * byte.MaxValue / 31; + num3 = (uint16 >> 5 & 31) * byte.MaxValue / 31; + num1 = (uint16 & 31) * byte.MaxValue / 31; + break; + } + num4 = (uint16 >> 12 & 7) * byte.MaxValue / 7; + num2 = (uint16 >> 8 & 15) * byte.MaxValue / 15; + num3 = (uint16 >> 4 & 15) * byte.MaxValue / 15; + num1 = (uint16 & 15) * byte.MaxValue / 15; + break; + } + numArray[index1] = (uint)(num1 | num3 << 8 | num2 << 16 | num4 << 24); + } } - } + return numArray; } - } - return numArray; - } - private byte[] fromIA4(byte[] tpl, int width, int height) - { - uint[] array = new uint[width * height]; - int num1 = 0; - for (int index1 = 0; index1 < height; index1 += 4) - { - for (int index2 = 0; index2 < width; index2 += 8) + private int Avg(int w0, int w1, int c0, int c1) { - for (int index3 = index1; index3 < index1 + 4; ++index3) - { - for (int index4 = index2; index4 < index2 + 8; ++index4) + int num1 = c0 >> 11; + int num2 = c1 >> 11; + int num3 = (w0 * num1 + w1 * num2) / (w0 + w1) << 11 & ushort.MaxValue; + int num4 = c0 >> 5 & 63; + int num5 = c1 >> 5 & 63; + int num6 = (w0 * num4 + w1 * num5) / (w0 + w1) << 5 & ushort.MaxValue; + int num7 = num3 | num6; + int num8 = c0 & 31; + int num9 = c1 & 31; + int num10 = (w0 * num8 + w1 * num9) / (w0 + w1); + return num7 | num10; + } + + private byte[] FromRGBA8(byte[] tpl, int width, int height) + { + uint[] array = new uint[width * height]; + int num1 = 0; + for (int index1 = 0; index1 < height; index1 += 4) { - int num2 = (int) tpl[num1++]; - if (index3 < height && index4 < width) - { - int num3 = (num2 & 15) * (int) byte.MaxValue / 15 & (int) byte.MaxValue; - int num4 = (num2 >> 4) * (int) byte.MaxValue / 15 & (int) byte.MaxValue; - array[index3 * width + index4] = (uint) (num3 | num3 << 8 | num3 << 16 | num4 << 24); - } + for (int index2 = 0; index2 < width; index2 += 4) + { + for (int index3 = 0; index3 < 2; ++index3) + { + for (int index4 = index1; index4 < index1 + 4; ++index4) + { + for (int index5 = index2; index5 < index2 + 4; ++index5) + { + ushort num2 = Shared.Swap(BitConverter.ToUInt16(tpl, num1++ * 2)); + if (index5 < width && index4 < height) + { + if (index3 == 0) + { + int num3 = num2 >> 8 & byte.MaxValue; + int num4 = num2 & byte.MaxValue; + array[index5 + index4 * width] |= (uint)(num4 << 16 | num3 << 24); + } + else + { + int num3 = num2 >> 8 & byte.MaxValue; + int num4 = num2 & byte.MaxValue; + array[index5 + index4 * width] |= (uint)(num3 << 8 | num4); + } + } + } + } + } + } } - } + return Shared.UIntArrayToByteArray(array); } - } - return Shared.UIntArrayToByteArray(array); - } - private byte[] toIA4(Bitmap img) - { - uint[] rgba = this.imageToRgba((Image) img); - int width = img.Width; - int height = img.Height; - int num1 = 0; - byte[] numArray = new byte[Shared.AddPadding(width, 8) * Shared.AddPadding(height, 4)]; - for (int index1 = 0; index1 < height; index1 += 4) - { - for (int index2 = 0; index2 < width; index2 += 8) + private byte[] ToRGBA8(Bitmap img) { - for (int index3 = index1; index3 < index1 + 4; ++index3) - { - for (int index4 = index2; index4 < index2 + 8; ++index4) + uint[] rgba = ImageToRgba(img); + int width = img.Width; + int height = img.Height; + int index1 = 0; + int num1 = 0; + byte[] numArray1 = new byte[Shared.AddPadding(width, 4) * Shared.AddPadding(height, 4) * 4]; + uint[] numArray2 = new uint[32]; + uint[] numArray3 = new uint[32]; + uint[] numArray4 = new uint[32]; + uint[] numArray5 = new uint[32]; + for (int index2 = 0; index2 < height; index2 += 4) { - byte num2; - if (index4 >= width || index3 >= height) - { - num2 = (byte) 0; - } - else - { - uint num3 = rgba[index4 + index3 * width]; - num2 = (byte) ((int) ((uint) (((int) (((num3 & (uint) byte.MaxValue) + (num3 >> 8 & (uint) byte.MaxValue) + (num3 >> 16 & (uint) byte.MaxValue)) / 3U) & (int) byte.MaxValue) * 15) / (uint) byte.MaxValue) & 15 | (int) ((num3 >> 24 & (uint) byte.MaxValue) * 15U / (uint) byte.MaxValue) << 4); - } - numArray[num1++] = num2; + for (int index3 = 0; index3 < width; index3 += 4) + { + for (int index4 = index2; index4 < index2 + 4; ++index4) + { + for (int index5 = index3; index5 < index3 + 4; ++index5) + { + uint num2 = index4 >= height || index5 >= width ? 0U : rgba[index5 + index4 * width]; + numArray2[index1] = num2 >> 16 & byte.MaxValue; + numArray3[index1] = num2 >> 8 & byte.MaxValue; + numArray4[index1] = num2 & byte.MaxValue; + numArray5[index1] = num2 >> 24 & byte.MaxValue; + ++index1; + } + } + if (index1 == 16) + { + for (int index4 = 0; index4 < 16; ++index4) + { + byte[] numArray6 = numArray1; + int index5 = num1; + int num2 = index5 + 1; + int num3 = (byte)numArray5[index4]; + numArray6[index5] = (byte)num3; + byte[] numArray7 = numArray1; + int index6 = num2; + num1 = index6 + 1; + int num4 = (byte)numArray2[index4]; + numArray7[index6] = (byte)num4; + } + for (int index4 = 0; index4 < 16; ++index4) + { + byte[] numArray6 = numArray1; + int index5 = num1; + int num2 = index5 + 1; + int num3 = (byte)numArray3[index4]; + numArray6[index5] = (byte)num3; + byte[] numArray7 = numArray1; + int index6 = num2; + num1 = index6 + 1; + int num4 = (byte)numArray4[index4]; + numArray7[index6] = (byte)num4; + } + index1 = 0; + } + } } - } + return numArray1; } - } - return numArray; - } - private byte[] fromIA8(byte[] tpl, int width, int height) - { - uint[] array = new uint[width * height]; - int num1 = 0; - for (int index1 = 0; index1 < height; index1 += 4) - { - for (int index2 = 0; index2 < width; index2 += 4) + private byte[] FromRGB5A3(byte[] tpl, int width, int height) { - for (int index3 = index1; index3 < index1 + 4; ++index3) - { - for (int index4 = index2; index4 < index2 + 4; ++index4) + uint[] array = new uint[width * height]; + int num1 = 0; + for (int index1 = 0; index1 < height; index1 += 4) { - int num2 = (int) Shared.Swap(BitConverter.ToUInt16(tpl, num1++ * 2)); - if (index3 < height && index4 < width) - { - uint num3 = (uint) (num2 >> 8); - uint num4 = (uint) (num2 & (int) byte.MaxValue); - array[index3 * width + index4] = (uint) ((int) num4 | (int) num4 << 8 | (int) num4 << 16 | (int) num3 << 24); - } + for (int index2 = 0; index2 < width; index2 += 4) + { + for (int index3 = index1; index3 < index1 + 4; ++index3) + { + for (int index4 = index2; index4 < index2 + 4; ++index4) + { + ushort num2 = Shared.Swap(BitConverter.ToUInt16(tpl, num1++ * 2)); + if (index3 < height && index4 < width) + { + int num3; + int num4; + int num5; + int num6; + if ((num2 & 32768) != 0) + { + num3 = (num2 >> 10 & 31) * byte.MaxValue / 31; + num4 = (num2 >> 5 & 31) * byte.MaxValue / 31; + num5 = (num2 & 31) * byte.MaxValue / 31; + num6 = byte.MaxValue; + } + else + { + num6 = (num2 >> 12 & 7) * byte.MaxValue / 7; + num3 = (num2 >> 8 & 15) * byte.MaxValue / 15; + num4 = (num2 >> 4 & 15) * byte.MaxValue / 15; + num5 = (num2 & 15) * byte.MaxValue / 15; + } + array[index3 * width + index4] = (uint)(num5 | num4 << 8 | num3 << 16 | num6 << 24); + } + } + } + } } - } + return Shared.UIntArrayToByteArray(array); } - } - return Shared.UIntArrayToByteArray(array); - } - private byte[] toIA8(Bitmap img) - { - uint[] rgba = this.imageToRgba((Image) img); - int width = img.Width; - int height = img.Height; - int num1 = 0; - byte[] numArray1 = new byte[Shared.AddPadding(width, 4) * Shared.AddPadding(height, 4) * 2]; - for (int index1 = 0; index1 < height; index1 += 4) - { - for (int index2 = 0; index2 < width; index2 += 4) + private byte[] ToRGB5A3(Bitmap img) { - for (int index3 = index1; index3 < index1 + 4; ++index3) - { - for (int index4 = index2; index4 < index2 + 4; ++index4) + uint[] rgba = ImageToRgba(img); + int width = img.Width; + int height = img.Height; + int num1 = -1; + byte[] numArray = new byte[Shared.AddPadding(width, 4) * Shared.AddPadding(height, 4) * 2]; + for (int index1 = 0; index1 < height; index1 += 4) { - ushort num2; - if (index4 >= width || index3 >= height) - { - num2 = (ushort) 0; - } - else - { - int num3 = (int) rgba[index4 + index3 * width]; - num2 = (ushort) ((uint) (((int) ((uint) num3 >> 24) & (int) byte.MaxValue) << 8) | ((uint) (num3 & (int) byte.MaxValue) + ((uint) num3 >> 8 & (uint) byte.MaxValue) + ((uint) num3 >> 16 & (uint) byte.MaxValue)) / 3U & (uint) byte.MaxValue); - } - Array.Reverse((Array) BitConverter.GetBytes(num2)); - byte[] numArray2 = numArray1; - int index5 = num1; - int num4 = index5 + 1; - int num5 = (int) (byte) ((uint) num2 >> 8); - numArray2[index5] = (byte) num5; - byte[] numArray3 = numArray1; - int index6 = num4; - num1 = index6 + 1; - int num6 = (int) (byte) ((uint) num2 & (uint) byte.MaxValue); - numArray3[index6] = (byte) num6; + for (int index2 = 0; index2 < width; index2 += 4) + { + for (int index3 = index1; index3 < index1 + 4; ++index3) + { + for (int index4 = index2; index4 < index2 + 4; ++index4) + { + int num2; + if (index3 >= height || index4 >= width) + { + num2 = 0; + } + else + { + int num3 = (int)rgba[index4 + index3 * width]; + int num4 = 0; + int num5 = num3 >> 16 & byte.MaxValue; + int num6 = num3 >> 8 & byte.MaxValue; + int num7 = num3 & byte.MaxValue; + int num8 = num3 >> 24 & byte.MaxValue; + if (num8 <= 218) + { + int num9 = num4 & -32769; + int num10 = num5 * 15 / byte.MaxValue & 15; + int num11 = num6 * 15 / byte.MaxValue & 15; + int num12 = num7 * 15 / byte.MaxValue & 15; + int num13 = num8 * 7 / byte.MaxValue & 7; + num2 = num9 | (num13 << 12 | num10 << 8 | num11 << 4 | num12); + } + else + { + num2 = num4 | 32768 | ((num5 * 31 / byte.MaxValue & 31) << 10 | (num6 * 31 / byte.MaxValue & 31) << 5 | num7 * 31 / byte.MaxValue & 31); + } + } + int num14; + numArray[num14 = num1 + 1] = (byte)(num2 >> 8); + numArray[num1 = num14 + 1] = (byte)(num2 & byte.MaxValue); + } + } + } } - } + return numArray; } - } - return numArray1; - } - private byte[] fromCI4(byte[] tpl, uint[] paletteData, int width, int height) - { - uint[] array = new uint[width * height]; - int num1 = 0; - for (int index1 = 0; index1 < height; index1 += 8) - { - for (int index2 = 0; index2 < width; index2 += 8) + private byte[] FromRGB565(byte[] tpl, int width, int height) { - for (int index3 = index1; index3 < index1 + 8; ++index3) - { - for (int index4 = index2; index4 < index2 + 8; index4 += 2) + uint[] array = new uint[width * height]; + int num1 = 0; + for (int index1 = 0; index1 < height; index1 += 4) { - byte num2 = tpl[num1++]; - if (index3 < height && index4 < width) - { - array[index3 * width + index4] = paletteData[(int) num2 >> 4]; - if (index3 * width + index4 + 1 < array.Length) - array[index3 * width + index4 + 1] = paletteData[(int) num2 & 15]; - } + for (int index2 = 0; index2 < width; index2 += 4) + { + for (int index3 = index1; index3 < index1 + 4; ++index3) + { + for (int index4 = index2; index4 < index2 + 4; ++index4) + { + ushort num2 = Shared.Swap(BitConverter.ToUInt16(tpl, num1++ * 2)); + if (index3 < height && index4 < width) + { + int num3 = (num2 >> 11 & 31) << 3 & byte.MaxValue; + int num4 = (num2 >> 5 & 63) << 2 & byte.MaxValue; + int num5 = (num2 & 31) << 3 & byte.MaxValue; + array[index3 * width + index4] = (uint)(num5 | num4 << 8 | num3 << 16 | -16777216); + } + } + } + } } - } + return Shared.UIntArrayToByteArray(array); } - } - return Shared.UIntArrayToByteArray(array); - } - private byte[] fromCI8(byte[] tpl, uint[] paletteData, int width, int height) - { - uint[] array = new uint[width * height]; - int num1 = 0; - for (int index1 = 0; index1 < height; index1 += 4) - { - for (int index2 = 0; index2 < width; index2 += 8) + private byte[] ToRGB565(Bitmap img) { - for (int index3 = index1; index3 < index1 + 4; ++index3) - { - for (int index4 = index2; index4 < index2 + 8; ++index4) + uint[] rgba = ImageToRgba(img); + int width = img.Width; + int height = img.Height; + int num1 = -1; + byte[] numArray = new byte[Shared.AddPadding(width, 4) * Shared.AddPadding(height, 4) * 2]; + for (int index1 = 0; index1 < height; index1 += 4) { - ushort num2 = (ushort) tpl[num1++]; - if (index3 < height && index4 < width) - array[index3 * width + index4] = paletteData[(int) num2]; + for (int index2 = 0; index2 < width; index2 += 4) + { + for (int index3 = index1; index3 < index1 + 4; ++index3) + { + for (int index4 = index2; index4 < index2 + 4; ++index4) + { + ushort num2; + if (index3 >= height || index4 >= width) + { + num2 = 0; + } + else + { + int num3 = (int)rgba[index4 + index3 * width]; + num2 = (ushort)((uint)((int)(((uint)num3 >> 16 & byte.MaxValue) >> 3) << 11 | (int)(((uint)num3 >> 8 & byte.MaxValue) >> 2) << 5) | (uint)(num3 & byte.MaxValue) >> 3); + } + int num4; + numArray[num4 = num1 + 1] = (byte)((uint)num2 >> 8); + numArray[num1 = num4 + 1] = (byte)(num2 & (uint)byte.MaxValue); + } + } + } } - } + return numArray; } - } - return Shared.UIntArrayToByteArray(array); - } - private byte[] fromCI14X2(byte[] tpl, uint[] paletteData, int width, int height) - { - uint[] array = new uint[width * height]; - int num1 = 0; - for (int index1 = 0; index1 < height; index1 += 4) - { - for (int index2 = 0; index2 < width; index2 += 4) + private byte[] FromI4(byte[] tpl, int width, int height) { - for (int index3 = index1; index3 < index1 + 4; ++index3) - { - for (int index4 = index2; index4 < index2 + 4; ++index4) + uint[] array = new uint[width * height]; + int num1 = 0; + for (int index1 = 0; index1 < height; index1 += 8) { - ushort num2 = Shared.Swap(BitConverter.ToUInt16(tpl, num1++ * 2)); - if (index3 < height && index4 < width) - array[index3 * width + index4] = paletteData[(int) num2 & 16383]; + for (int index2 = 0; index2 < width; index2 += 8) + { + for (int index3 = index1; index3 < index1 + 8; ++index3) + { + for (int index4 = index2; index4 < index2 + 8; index4 += 2) + { + int num2 = tpl[num1++]; + if (index3 < height && index4 < width) + { + int num3 = (num2 >> 4) * byte.MaxValue / 15; + array[index3 * width + index4] = (uint)(num3 | num3 << 8 | num3 << 16 | -16777216); + int num4 = (num2 & 15) * byte.MaxValue / 15; + if (index3 * width + index4 + 1 < array.Length) + { + array[index3 * width + index4 + 1] = (uint)(num4 | num4 << 8 | num4 << 16 | -16777216); + } + } + } + } + } } - } + return Shared.UIntArrayToByteArray(array); } - } - return Shared.UIntArrayToByteArray(array); - } - private byte[] fromCMP(byte[] tpl, int width, int height) - { - uint[] array = new uint[width * height]; - ushort[] numArray1 = new ushort[4]; - int[] numArray2 = new int[4]; - int index1 = 0; - for (int index2 = 0; index2 < height; ++index2) - { - for (int index3 = 0; index3 < width; ++index3) + private byte[] ToI4(Bitmap img) { - int num1 = Shared.AddPadding(width, 8); - int num2 = index3 & 3; - int num3 = index3 >> 2 & 1; - int num4 = index3 >> 3; - int num5 = index2 & 3; - int num6 = index2 >> 2 & 1; - int num7 = index2 >> 3; - int startIndex = 8 * num3 + 16 * num6 + 32 * num4 + 4 * num1 * num7; - numArray1[0] = Shared.Swap(BitConverter.ToUInt16(tpl, startIndex)); - numArray1[1] = Shared.Swap(BitConverter.ToUInt16(tpl, startIndex + 2)); - if ((int) numArray1[0] > (int) numArray1[1]) - { - numArray1[2] = (ushort) this.avg(2, 1, (int) numArray1[0], (int) numArray1[1]); - numArray1[3] = (ushort) this.avg(1, 2, (int) numArray1[0], (int) numArray1[1]); - } - else - { - numArray1[2] = (ushort) this.avg(1, 1, (int) numArray1[0], (int) numArray1[1]); - numArray1[3] = (ushort) 0; - } - uint num8 = Shared.Swap(BitConverter.ToUInt32(tpl, startIndex + 4)); - int num9 = num2 + 4 * num5; - int num10 = (int) numArray1[(int) (num8 >> 30 - 2 * num9) & 3]; - numArray2[0] = num10 >> 8 & 248; - numArray2[1] = num10 >> 3 & 248; - numArray2[2] = num10 << 3 & 248; - numArray2[3] = (int) byte.MaxValue; - if (((int) (num8 >> 30 - 2 * num9) & 3) == 3 && (int) numArray1[0] <= (int) numArray1[1]) - numArray2[3] = 0; - array[index1] = (uint) (numArray2[0] << 16 | numArray2[1] << 8 | numArray2[2] | numArray2[3] << 24); - ++index1; + uint[] rgba = ImageToRgba(img); + int width = img.Width; + int height = img.Height; + int num1 = 0; + byte[] numArray = new byte[Shared.AddPadding(width, 8) * Shared.AddPadding(height, 8) / 2]; + for (int index1 = 0; index1 < height; index1 += 8) + { + for (int index2 = 0; index2 < width; index2 += 8) + { + for (int index3 = index1; index3 < index1 + 8; ++index3) + { + for (int index4 = index2; index4 < index2 + 8; index4 += 2) + { + byte num2; + if (index4 >= width || index3 >= height) + { + num2 = 0; + } + else + { + int num3 = (int)rgba[index4 + index3 * width]; + int num4 = (int)(((uint)(num3 & byte.MaxValue) + ((uint)num3 >> 8 & byte.MaxValue) + ((uint)num3 >> 16 & byte.MaxValue)) / 3U) & byte.MaxValue; + int num5 = index4 + index3 * width + 1 < rgba.Length ? (int)rgba[index4 + index3 * width + 1] : 0; + uint num6 = ((uint)(num5 & byte.MaxValue) + ((uint)num5 >> 8 & byte.MaxValue) + ((uint)num5 >> 16 & byte.MaxValue)) / 3U & byte.MaxValue; + num2 = (byte)((int)((uint)(num4 * 15) / byte.MaxValue) << 4 | (int)(num6 * 15U / byte.MaxValue) & 15); + } + numArray[num1++] = num2; + } + } + } + } + return numArray; } - } - return Shared.UIntArrayToByteArray(array); - } - private void fireDebug(string debugMessage, params object[] args) - { - EventHandler debug = this.Debug; - if (debug == null) - return; - debug(new object(), new MessageEventArgs(string.Format(debugMessage, args))); + private byte[] FromI8(byte[] tpl, int width, int height) + { + uint[] array = new uint[width * height]; + int num1 = 0; + for (int index1 = 0; index1 < height; index1 += 4) + { + for (int index2 = 0; index2 < width; index2 += 8) + { + for (int index3 = index1; index3 < index1 + 4; ++index3) + { + for (int index4 = index2; index4 < index2 + 8; ++index4) + { + int num2 = tpl[num1++]; + if (index3 < height && index4 < width) + { + array[index3 * width + index4] = (uint)(num2 | num2 << 8 | num2 << 16 | -16777216); + } + } + } + } + } + return Shared.UIntArrayToByteArray(array); + } + + private byte[] ToI8(Bitmap img) + { + uint[] rgba = ImageToRgba(img); + int width = img.Width; + int height = img.Height; + int num1 = 0; + byte[] numArray = new byte[Shared.AddPadding(width, 8) * Shared.AddPadding(height, 4)]; + for (int index1 = 0; index1 < height; index1 += 4) + { + for (int index2 = 0; index2 < width; index2 += 8) + { + for (int index3 = index1; index3 < index1 + 4; ++index3) + { + for (int index4 = index2; index4 < index2 + 8; ++index4) + { + byte num2; + if (index4 >= width || index3 >= height) + { + num2 = 0; + } + else + { + int num3 = (int)rgba[index4 + index3 * width]; + num2 = (byte)(((uint)(num3 & byte.MaxValue) + ((uint)num3 >> 8 & byte.MaxValue) + ((uint)num3 >> 16 & byte.MaxValue)) / 3U & byte.MaxValue); + } + numArray[num1++] = num2; + } + } + } + } + return numArray; + } + + private byte[] FromIA4(byte[] tpl, int width, int height) + { + uint[] array = new uint[width * height]; + int num1 = 0; + for (int index1 = 0; index1 < height; index1 += 4) + { + for (int index2 = 0; index2 < width; index2 += 8) + { + for (int index3 = index1; index3 < index1 + 4; ++index3) + { + for (int index4 = index2; index4 < index2 + 8; ++index4) + { + int num2 = tpl[num1++]; + if (index3 < height && index4 < width) + { + int num3 = (num2 & 15) * byte.MaxValue / 15 & byte.MaxValue; + int num4 = (num2 >> 4) * byte.MaxValue / 15 & byte.MaxValue; + array[index3 * width + index4] = (uint)(num3 | num3 << 8 | num3 << 16 | num4 << 24); + } + } + } + } + } + return Shared.UIntArrayToByteArray(array); + } + + private byte[] ToIA4(Bitmap img) + { + uint[] rgba = ImageToRgba(img); + int width = img.Width; + int height = img.Height; + int num1 = 0; + byte[] numArray = new byte[Shared.AddPadding(width, 8) * Shared.AddPadding(height, 4)]; + for (int index1 = 0; index1 < height; index1 += 4) + { + for (int index2 = 0; index2 < width; index2 += 8) + { + for (int index3 = index1; index3 < index1 + 4; ++index3) + { + for (int index4 = index2; index4 < index2 + 8; ++index4) + { + byte num2; + if (index4 >= width || index3 >= height) + { + num2 = 0; + } + else + { + uint num3 = rgba[index4 + index3 * width]; + num2 = (byte)((int)((uint)(((int)(((num3 & byte.MaxValue) + (num3 >> 8 & byte.MaxValue) + (num3 >> 16 & byte.MaxValue)) / 3U) & byte.MaxValue) * 15) / byte.MaxValue) & 15 | (int)((num3 >> 24 & byte.MaxValue) * 15U / byte.MaxValue) << 4); + } + numArray[num1++] = num2; + } + } + } + } + return numArray; + } + + private byte[] FromIA8(byte[] tpl, int width, int height) + { + uint[] array = new uint[width * height]; + int num1 = 0; + for (int index1 = 0; index1 < height; index1 += 4) + { + for (int index2 = 0; index2 < width; index2 += 4) + { + for (int index3 = index1; index3 < index1 + 4; ++index3) + { + for (int index4 = index2; index4 < index2 + 4; ++index4) + { + int num2 = Shared.Swap(BitConverter.ToUInt16(tpl, num1++ * 2)); + if (index3 < height && index4 < width) + { + uint num3 = (uint)(num2 >> 8); + uint num4 = (uint)(num2 & byte.MaxValue); + array[index3 * width + index4] = (uint)((int)num4 | (int)num4 << 8 | (int)num4 << 16 | (int)num3 << 24); + } + } + } + } + } + return Shared.UIntArrayToByteArray(array); + } + + private byte[] ToIA8(Bitmap img) + { + uint[] rgba = ImageToRgba(img); + int width = img.Width; + int height = img.Height; + int num1 = 0; + byte[] numArray1 = new byte[Shared.AddPadding(width, 4) * Shared.AddPadding(height, 4) * 2]; + for (int index1 = 0; index1 < height; index1 += 4) + { + for (int index2 = 0; index2 < width; index2 += 4) + { + for (int index3 = index1; index3 < index1 + 4; ++index3) + { + for (int index4 = index2; index4 < index2 + 4; ++index4) + { + ushort num2; + if (index4 >= width || index3 >= height) + { + num2 = 0; + } + else + { + int num3 = (int)rgba[index4 + index3 * width]; + num2 = (ushort)((uint)(((int)((uint)num3 >> 24) & byte.MaxValue) << 8) | ((uint)(num3 & byte.MaxValue) + ((uint)num3 >> 8 & byte.MaxValue) + ((uint)num3 >> 16 & byte.MaxValue)) / 3U & byte.MaxValue); + } + Array.Reverse(BitConverter.GetBytes(num2)); + byte[] numArray2 = numArray1; + int index5 = num1; + int num4 = index5 + 1; + int num5 = (byte)((uint)num2 >> 8); + numArray2[index5] = (byte)num5; + byte[] numArray3 = numArray1; + int index6 = num4; + num1 = index6 + 1; + int num6 = (byte)(num2 & (uint)byte.MaxValue); + numArray3[index6] = (byte)num6; + } + } + } + } + return numArray1; + } + + private byte[] FromCI4(byte[] tpl, uint[] paletteData, int width, int height) + { + uint[] array = new uint[width * height]; + int num1 = 0; + for (int index1 = 0; index1 < height; index1 += 8) + { + for (int index2 = 0; index2 < width; index2 += 8) + { + for (int index3 = index1; index3 < index1 + 8; ++index3) + { + for (int index4 = index2; index4 < index2 + 8; index4 += 2) + { + byte num2 = tpl[num1++]; + if (index3 < height && index4 < width) + { + array[index3 * width + index4] = paletteData[num2 >> 4]; + if (index3 * width + index4 + 1 < array.Length) + { + array[index3 * width + index4 + 1] = paletteData[num2 & 15]; + } + } + } + } + } + } + return Shared.UIntArrayToByteArray(array); + } + + private byte[] FromCI8(byte[] tpl, uint[] paletteData, int width, int height) + { + uint[] array = new uint[width * height]; + int num1 = 0; + for (int index1 = 0; index1 < height; index1 += 4) + { + for (int index2 = 0; index2 < width; index2 += 8) + { + for (int index3 = index1; index3 < index1 + 4; ++index3) + { + for (int index4 = index2; index4 < index2 + 8; ++index4) + { + ushort num2 = tpl[num1++]; + if (index3 < height && index4 < width) + { + array[index3 * width + index4] = paletteData[num2]; + } + } + } + } + } + return Shared.UIntArrayToByteArray(array); + } + + private byte[] FromCI14X2(byte[] tpl, uint[] paletteData, int width, int height) + { + uint[] array = new uint[width * height]; + int num1 = 0; + for (int index1 = 0; index1 < height; index1 += 4) + { + for (int index2 = 0; index2 < width; index2 += 4) + { + for (int index3 = index1; index3 < index1 + 4; ++index3) + { + for (int index4 = index2; index4 < index2 + 4; ++index4) + { + ushort num2 = Shared.Swap(BitConverter.ToUInt16(tpl, num1++ * 2)); + if (index3 < height && index4 < width) + { + array[index3 * width + index4] = paletteData[num2 & 16383]; + } + } + } + } + } + return Shared.UIntArrayToByteArray(array); + } + + private byte[] FromCMP(byte[] tpl, int width, int height) + { + uint[] array = new uint[width * height]; + ushort[] numArray1 = new ushort[4]; + int[] numArray2 = new int[4]; + int index1 = 0; + for (int index2 = 0; index2 < height; ++index2) + { + for (int index3 = 0; index3 < width; ++index3) + { + int num1 = Shared.AddPadding(width, 8); + int num2 = index3 & 3; + int num3 = index3 >> 2 & 1; + int num4 = index3 >> 3; + int num5 = index2 & 3; + int num6 = index2 >> 2 & 1; + int num7 = index2 >> 3; + int startIndex = 8 * num3 + 16 * num6 + 32 * num4 + 4 * num1 * num7; + numArray1[0] = Shared.Swap(BitConverter.ToUInt16(tpl, startIndex)); + numArray1[1] = Shared.Swap(BitConverter.ToUInt16(tpl, startIndex + 2)); + if (numArray1[0] > numArray1[1]) + { + numArray1[2] = (ushort)Avg(2, 1, numArray1[0], numArray1[1]); + numArray1[3] = (ushort)Avg(1, 2, numArray1[0], numArray1[1]); + } + else + { + numArray1[2] = (ushort)Avg(1, 1, numArray1[0], numArray1[1]); + numArray1[3] = 0; + } + uint num8 = Shared.Swap(BitConverter.ToUInt32(tpl, startIndex + 4)); + int num9 = num2 + 4 * num5; + int num10 = numArray1[(int)(num8 >> 30 - 2 * num9) & 3]; + numArray2[0] = num10 >> 8 & 248; + numArray2[1] = num10 >> 3 & 248; + numArray2[2] = num10 << 3 & 248; + numArray2[3] = byte.MaxValue; + if (((int)(num8 >> 30 - 2 * num9) & 3) == 3 && numArray1[0] <= numArray1[1]) + { + numArray2[3] = 0; + } + + array[index1] = (uint)(numArray2[0] << 16 | numArray2[1] << 8 | numArray2[2] | numArray2[3] << 24); + ++index1; + } + } + return Shared.UIntArrayToByteArray(array); + } + + private void FireDebug(string debugMessage, params object[] args) + { + EventHandler debug = Debug; + if (debug == null) + { + return; + } + + debug(new object(), new MessageEventArgs(string.Format(debugMessage, args))); + } } - } } diff --git a/TPL_Header.cs b/TPL_Header.cs index 8a857b6..aa75863 100644 --- a/TPL_Header.cs +++ b/TPL_Header.cs @@ -9,27 +9,27 @@ using System.IO; namespace libWiiSharp { - public class TPL_Header - { - private uint tplMagic = 2142000; - private uint numOfTextures; - private uint headerSize = 12; - - public uint TplMagic => this.tplMagic; - - public uint NumOfTextures + public class TPL_Header { - get => this.numOfTextures; - set => this.numOfTextures = value; - } + private readonly uint tplMagic = 2142000; + private uint numOfTextures; + private readonly uint headerSize = 12; - public uint HeaderSize => this.headerSize; + public uint TplMagic => tplMagic; - public void Write(Stream writeStream) - { - writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.tplMagic)), 0, 4); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.numOfTextures)), 0, 4); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.headerSize)), 0, 4); + public uint NumOfTextures + { + get => numOfTextures; + set => numOfTextures = value; + } + + public uint HeaderSize => headerSize; + + public void Write(Stream writeStream) + { + writeStream.Write(BitConverter.GetBytes(Shared.Swap(tplMagic)), 0, 4); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(numOfTextures)), 0, 4); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(headerSize)), 0, 4); + } } - } } diff --git a/TPL_PaletteFormat.cs b/TPL_PaletteFormat.cs index ca1e4f7..74f463d 100644 --- a/TPL_PaletteFormat.cs +++ b/TPL_PaletteFormat.cs @@ -6,11 +6,11 @@ namespace libWiiSharp { - public enum TPL_PaletteFormat - { - IA8 = 0, - RGB565 = 1, - RGB5A3 = 2, - None = 255, // 0x000000FF - } + public enum TPL_PaletteFormat + { + IA8 = 0, + RGB565 = 1, + RGB5A3 = 2, + None = 255, // 0x000000FF + } } diff --git a/TPL_PaletteHeader.cs b/TPL_PaletteHeader.cs index dcadc7d..8bc2470 100644 --- a/TPL_PaletteHeader.cs +++ b/TPL_PaletteHeader.cs @@ -9,51 +9,51 @@ using System.IO; namespace libWiiSharp { - public class TPL_PaletteHeader - { - private ushort numberOfItems; - private byte unpacked; - private byte pad; - private uint paletteFormat = (uint) byte.MaxValue; - private uint paletteDataOffset; - - public ushort NumberOfItems + public class TPL_PaletteHeader { - get => this.numberOfItems; - set => this.numberOfItems = value; - } + private ushort numberOfItems; + private byte unpacked; + private byte pad; + private uint paletteFormat = byte.MaxValue; + private uint paletteDataOffset; - public byte Unpacked - { - get => this.unpacked; - set => this.unpacked = value; - } + public ushort NumberOfItems + { + get => numberOfItems; + set => numberOfItems = value; + } - public byte Pad - { - get => this.pad; - set => this.pad = value; - } + public byte Unpacked + { + get => unpacked; + set => unpacked = value; + } - public uint PaletteFormat - { - get => this.paletteFormat; - set => this.paletteFormat = value; - } + public byte Pad + { + get => pad; + set => pad = value; + } - public uint PaletteDataOffset - { - get => this.paletteDataOffset; - set => this.paletteDataOffset = value; - } + public uint PaletteFormat + { + get => paletteFormat; + set => paletteFormat = value; + } - public void Write(Stream writeStream) - { - writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.numberOfItems)), 0, 2); - writeStream.WriteByte(this.unpacked); - writeStream.WriteByte(this.pad); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.paletteFormat)), 0, 4); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.paletteDataOffset)), 0, 4); + public uint PaletteDataOffset + { + get => paletteDataOffset; + set => paletteDataOffset = value; + } + + public void Write(Stream writeStream) + { + writeStream.Write(BitConverter.GetBytes(Shared.Swap(numberOfItems)), 0, 2); + writeStream.WriteByte(unpacked); + writeStream.WriteByte(pad); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(paletteFormat)), 0, 4); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(paletteDataOffset)), 0, 4); + } } - } } diff --git a/TPL_TextureEntry.cs b/TPL_TextureEntry.cs index 2fbd77b..0fdf907 100644 --- a/TPL_TextureEntry.cs +++ b/TPL_TextureEntry.cs @@ -9,27 +9,27 @@ using System.IO; namespace libWiiSharp { - public class TPL_TextureEntry - { - private uint textureHeaderOffset; - private uint paletteHeaderOffset; - - public uint TextureHeaderOffset + public class TPL_TextureEntry { - get => this.textureHeaderOffset; - set => this.textureHeaderOffset = value; - } + private uint textureHeaderOffset; + private uint paletteHeaderOffset; - public uint PaletteHeaderOffset - { - get => this.paletteHeaderOffset; - set => this.paletteHeaderOffset = value; - } + public uint TextureHeaderOffset + { + get => textureHeaderOffset; + set => textureHeaderOffset = value; + } - public void Write(Stream writeStream) - { - writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.textureHeaderOffset)), 0, 4); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.paletteHeaderOffset)), 0, 4); + public uint PaletteHeaderOffset + { + get => paletteHeaderOffset; + set => paletteHeaderOffset = value; + } + + public void Write(Stream writeStream) + { + writeStream.Write(BitConverter.GetBytes(Shared.Swap(textureHeaderOffset)), 0, 4); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(paletteHeaderOffset)), 0, 4); + } } - } } diff --git a/TPL_TextureFormat.cs b/TPL_TextureFormat.cs index fc77391..78b56c5 100644 --- a/TPL_TextureFormat.cs +++ b/TPL_TextureFormat.cs @@ -6,18 +6,18 @@ namespace libWiiSharp { - public enum TPL_TextureFormat - { - I4 = 0, - I8 = 1, - IA4 = 2, - IA8 = 3, - RGB565 = 4, - RGB5A3 = 5, - RGBA8 = 6, - CI4 = 8, - CI8 = 9, - CI14X2 = 10, // 0x0000000A - CMP = 14, // 0x0000000E - } + public enum TPL_TextureFormat + { + I4 = 0, + I8 = 1, + IA4 = 2, + IA8 = 3, + RGB565 = 4, + RGB5A3 = 5, + RGBA8 = 6, + CI4 = 8, + CI8 = 9, + CI14X2 = 10, // 0x0000000A + CMP = 14, // 0x0000000E + } } diff --git a/TPL_TextureHeader.cs b/TPL_TextureHeader.cs index 3665e2e..6454708 100644 --- a/TPL_TextureHeader.cs +++ b/TPL_TextureHeader.cs @@ -9,115 +9,115 @@ using System.IO; namespace libWiiSharp { - public class TPL_TextureHeader - { - private ushort textureHeight; - private ushort textureWidth; - private uint textureFormat; - private uint textureDataOffset; - private uint wrapS; - private uint wrapT; - private uint minFilter = 1; - private uint magFilter = 1; - private uint lodBias; - private byte edgeLod; - private byte minLod; - private byte maxLod; - private byte unpacked; - - public ushort TextureHeight + public class TPL_TextureHeader { - get => this.textureHeight; - set => this.textureHeight = value; - } + private ushort textureHeight; + private ushort textureWidth; + private uint textureFormat; + private uint textureDataOffset; + private uint wrapS; + private uint wrapT; + private uint minFilter = 1; + private uint magFilter = 1; + private uint lodBias; + private byte edgeLod; + private byte minLod; + private byte maxLod; + private byte unpacked; - public ushort TextureWidth - { - get => this.textureWidth; - set => this.textureWidth = value; - } + public ushort TextureHeight + { + get => textureHeight; + set => textureHeight = value; + } - public uint TextureFormat - { - get => this.textureFormat; - set => this.textureFormat = value; - } + public ushort TextureWidth + { + get => textureWidth; + set => textureWidth = value; + } - public uint TextureDataOffset - { - get => this.textureDataOffset; - set => this.textureDataOffset = value; - } + public uint TextureFormat + { + get => textureFormat; + set => textureFormat = value; + } - public uint WrapS - { - get => this.wrapS; - set => this.wrapS = value; - } + public uint TextureDataOffset + { + get => textureDataOffset; + set => textureDataOffset = value; + } - public uint WrapT - { - get => this.wrapT; - set => this.wrapT = value; - } + public uint WrapS + { + get => wrapS; + set => wrapS = value; + } - public uint MinFilter - { - get => this.minFilter; - set => this.minFilter = value; - } + public uint WrapT + { + get => wrapT; + set => wrapT = value; + } - public uint MagFilter - { - get => this.magFilter; - set => this.magFilter = value; - } + public uint MinFilter + { + get => minFilter; + set => minFilter = value; + } - public uint LodBias - { - get => this.lodBias; - set => this.lodBias = value; - } + public uint MagFilter + { + get => magFilter; + set => magFilter = value; + } - public byte EdgeLod - { - get => this.edgeLod; - set => this.edgeLod = value; - } + public uint LodBias + { + get => lodBias; + set => lodBias = value; + } - public byte MinLod - { - get => this.minLod; - set => this.minLod = value; - } + public byte EdgeLod + { + get => edgeLod; + set => edgeLod = value; + } - public byte MaxLod - { - get => this.maxLod; - set => this.maxLod = value; - } + public byte MinLod + { + get => minLod; + set => minLod = value; + } - public byte Unpacked - { - get => this.unpacked; - set => this.unpacked = value; - } + public byte MaxLod + { + get => maxLod; + set => maxLod = value; + } - public void Write(Stream writeStream) - { - writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.textureHeight)), 0, 2); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.textureWidth)), 0, 2); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.textureFormat)), 0, 4); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.textureDataOffset)), 0, 4); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.wrapS)), 0, 4); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.wrapT)), 0, 4); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.minFilter)), 0, 4); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.magFilter)), 0, 4); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.lodBias)), 0, 4); - writeStream.WriteByte(this.edgeLod); - writeStream.WriteByte(this.minLod); - writeStream.WriteByte(this.maxLod); - writeStream.WriteByte(this.unpacked); + public byte Unpacked + { + get => unpacked; + set => unpacked = value; + } + + public void Write(Stream writeStream) + { + writeStream.Write(BitConverter.GetBytes(Shared.Swap(textureHeight)), 0, 2); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(textureWidth)), 0, 2); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(textureFormat)), 0, 4); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(textureDataOffset)), 0, 4); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(wrapS)), 0, 4); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(wrapT)), 0, 4); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(minFilter)), 0, 4); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(magFilter)), 0, 4); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(lodBias)), 0, 4); + writeStream.WriteByte(edgeLod); + writeStream.WriteByte(minLod); + writeStream.WriteByte(maxLod); + writeStream.WriteByte(unpacked); + } } - } } diff --git a/Ticket.cs b/Ticket.cs index fe2f306..ac4288e 100644 --- a/Ticket.cs +++ b/Ticket.cs @@ -19,474 +19,523 @@ namespace libWiiSharp public class Ticket : IDisposable { - private byte newKeyIndex; - private byte[] decryptedTitleKey = new byte[16]; - private bool fakeSign; - private bool titleKeyChanged; - private byte[] newEncryptedTitleKey = new byte[0]; - private bool reDecrypt; - private uint signatureExponent = 65537; - private byte[] signature = new byte[256]; - private byte[] padding = new byte[60]; - private byte[] issuer = new byte[64]; - private byte[] unknown = new byte[63]; - private byte[] encryptedTitleKey = new byte[16]; - private byte unknown2; - private ulong ticketId; - private uint consoleId; - private ulong titleId; - private ushort unknown3 = ushort.MaxValue; - private ushort numOfDlc; - private ulong unknown4; - private byte padding2; - private byte commonKeyIndex; - private byte[] unknown5 = new byte[48]; - private byte[] unknown6 = new byte[32]; - private ushort padding3; - private uint enableTimeLimit; - private uint timeLimit; - private byte[] padding4 = new byte[88]; - private bool isDisposed; + private byte newKeyIndex; + private byte[] decryptedTitleKey = new byte[16]; + private bool fakeSign; + private bool titleKeyChanged; + private byte[] newEncryptedTitleKey = new byte[0]; + private bool reDecrypt; + private uint signatureExponent = 65537; + private byte[] signature = new byte[256]; + private byte[] padding = new byte[60]; + private byte[] issuer = new byte[64]; + private byte[] unknown = new byte[63]; + private byte[] encryptedTitleKey = new byte[16]; + private byte unknown2; + private ulong ticketId; + private uint consoleId; + private ulong titleId; + private ushort unknown3 = ushort.MaxValue; + private ushort numOfDlc; + private ulong unknown4; + private byte padding2; + private byte commonKeyIndex; + private byte[] unknown5 = new byte[48]; + private byte[] unknown6 = new byte[32]; + private ushort padding3; + private uint enableTimeLimit; + private uint timeLimit; + private byte[] padding4 = new byte[88]; + private bool isDisposed; - public byte[] TitleKey - { - get => this.decryptedTitleKey; - set - { - this.decryptedTitleKey = value; - this.titleKeyChanged = true; - this.reDecrypt = false; - } - } + public byte[] TitleKey + { + get => decryptedTitleKey; + set + { + decryptedTitleKey = value; + titleKeyChanged = true; + reDecrypt = false; + } + } - public CommonKeyType CommonKeyIndex - { - get => (CommonKeyType) this.newKeyIndex; - set => this.newKeyIndex = (byte) value; - } + public CommonKeyType CommonKeyIndex + { + get => (CommonKeyType)newKeyIndex; + set => newKeyIndex = (byte)value; + } - public ulong TicketID - { - get => this.ticketId; - set => this.ticketId = value; - } + public ulong TicketID + { + get => ticketId; + set => ticketId = value; + } - public uint ConsoleID - { - get => this.consoleId; - set => this.consoleId = value; - } + public uint ConsoleID + { + get => consoleId; + set => consoleId = value; + } - public ulong TitleID - { - get => this.titleId; - set - { - this.titleId = value; - if (!this.reDecrypt) - return; - this.reDecryptTitleKey(); - } - } + public ulong TitleID + { + get => titleId; + set + { + titleId = value; + if (!reDecrypt) + { + return; + } - public ushort NumOfDLC - { - get => this.numOfDlc; - set => this.numOfDlc = value; - } + ReDecryptTitleKey(); + } + } - public bool FakeSign - { - get => this.fakeSign; - set => this.fakeSign = value; - } + public ushort NumOfDLC + { + get => numOfDlc; + set => numOfDlc = value; + } - public bool TitleKeyChanged => this.titleKeyChanged; + public bool FakeSign + { + get => fakeSign; + set => fakeSign = value; + } - public event EventHandler Debug; + public bool TitleKeyChanged => titleKeyChanged; - ~Ticket() => this.Dispose(false); + public event EventHandler Debug; - public void Dispose() - { - this.Dispose(true); - GC.SuppressFinalize((object) this); - } + ~Ticket() => Dispose(false); - protected virtual void Dispose(bool disposing) - { - if (disposing && !this.isDisposed) - { - this.decryptedTitleKey = (byte[]) null; - this.newEncryptedTitleKey = (byte[]) null; - this.signature = (byte[]) null; - this.padding = (byte[]) null; - this.issuer = (byte[]) null; - this.unknown = (byte[]) null; - this.encryptedTitleKey = (byte[]) null; - this.unknown5 = (byte[]) null; - this.unknown6 = (byte[]) null; - this.padding4 = (byte[]) null; - } - this.isDisposed = true; - } + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } - public static Ticket Load(string pathToTicket) => Ticket.Load(File.ReadAllBytes(pathToTicket)); + protected virtual void Dispose(bool disposing) + { + if (disposing && !isDisposed) + { + decryptedTitleKey = null; + newEncryptedTitleKey = null; + signature = null; + padding = null; + issuer = null; + unknown = null; + encryptedTitleKey = null; + unknown5 = null; + unknown6 = null; + padding4 = null; + } + isDisposed = true; + } - public static Ticket Load(byte[] ticket) - { - Ticket ticket1 = new Ticket(); - MemoryStream memoryStream = new MemoryStream(ticket); - try - { - ticket1.parseTicket((Stream) memoryStream); - } - catch - { - memoryStream.Dispose(); - throw; - } - memoryStream.Dispose(); - return ticket1; - } + public static Ticket Load(string pathToTicket) + { + return Ticket.Load(File.ReadAllBytes(pathToTicket)); + } - public static Ticket Load(Stream ticket) - { - Ticket ticket1 = new Ticket(); - ticket1.parseTicket(ticket); - return ticket1; - } + public static Ticket Load(byte[] ticket) + { + Ticket ticket1 = new Ticket(); + MemoryStream memoryStream = new MemoryStream(ticket); + try + { + ticket1.ParseTicket(memoryStream); + } + catch + { + memoryStream.Dispose(); + throw; + } + memoryStream.Dispose(); + return ticket1; + } - public void LoadFile(string pathToTicket) => this.LoadFile(File.ReadAllBytes(pathToTicket)); + public static Ticket Load(Stream ticket) + { + Ticket ticket1 = new Ticket(); + ticket1.ParseTicket(ticket); + return ticket1; + } - public void LoadFile(byte[] ticket) - { - MemoryStream memoryStream = new MemoryStream(ticket); - try - { - this.parseTicket((Stream) memoryStream); - } - catch - { - memoryStream.Dispose(); - throw; - } - memoryStream.Dispose(); - } + public void LoadFile(string pathToTicket) + { + LoadFile(File.ReadAllBytes(pathToTicket)); + } - public void LoadFile(Stream ticket) => this.parseTicket(ticket); + public void LoadFile(byte[] ticket) + { + MemoryStream memoryStream = new MemoryStream(ticket); + try + { + ParseTicket(memoryStream); + } + catch + { + memoryStream.Dispose(); + throw; + } + memoryStream.Dispose(); + } - public void Save(string savePath) => this.Save(savePath, false); + public void LoadFile(Stream ticket) + { + ParseTicket(ticket); + } - public void Save(string savePath, bool fakeSign) - { - if (fakeSign) - this.fakeSign = true; - if (File.Exists(savePath)) - File.Delete(savePath); - using (FileStream fileStream = new FileStream(savePath, FileMode.Create)) - this.writeToStream((Stream) fileStream); - } + public void Save(string savePath) + { + Save(savePath, false); + } - public MemoryStream ToMemoryStream() => this.ToMemoryStream(false); + public void Save(string savePath, bool fakeSign) + { + if (fakeSign) + { + this.fakeSign = true; + } - public MemoryStream ToMemoryStream(bool fakeSign) - { - if (fakeSign) - this.fakeSign = true; - MemoryStream memoryStream = new MemoryStream(); - try - { - this.writeToStream((Stream) memoryStream); - return memoryStream; - } - catch - { - memoryStream.Dispose(); - throw; - } - } + if (File.Exists(savePath)) + { + File.Delete(savePath); + } - public byte[] ToByteArray() => this.ToByteArray(false); + using FileStream fileStream = new FileStream(savePath, FileMode.Create); + WriteToStream(fileStream); + } - public byte[] ToByteArray(bool fakeSign) - { - if (fakeSign) - this.fakeSign = true; - MemoryStream memoryStream = new MemoryStream(); - try - { - this.writeToStream((Stream) memoryStream); - } - catch - { - memoryStream.Dispose(); - throw; - } - byte[] array = memoryStream.ToArray(); - memoryStream.Dispose(); - return array; - } + public MemoryStream ToMemoryStream() + { + return ToMemoryStream(false); + } - public void SetTitleKey(string newTitleKey) => this.SetTitleKey(newTitleKey.ToCharArray()); + public MemoryStream ToMemoryStream(bool fakeSign) + { + if (fakeSign) + { + this.fakeSign = true; + } - public void SetTitleKey(char[] newTitleKey) - { - if (newTitleKey.Length != 16) - throw new Exception("The title key must be 16 characters long!"); - for (int index = 0; index < 16; ++index) - this.encryptedTitleKey[index] = (byte) newTitleKey[index]; - this.decryptTitleKey(); - this.titleKeyChanged = true; - this.reDecrypt = true; - this.newEncryptedTitleKey = this.encryptedTitleKey; - } + MemoryStream memoryStream = new MemoryStream(); + try + { + WriteToStream(memoryStream); + return memoryStream; + } + catch + { + memoryStream.Dispose(); + throw; + } + } - public void SetTitleKey(byte[] newTitleKey) - { - this.encryptedTitleKey = newTitleKey.Length == 16 ? newTitleKey : throw new Exception("The title key must be 16 characters long!"); - this.decryptTitleKey(); - this.titleKeyChanged = true; - this.reDecrypt = true; - this.newEncryptedTitleKey = newTitleKey; - } + public byte[] ToByteArray() + { + return ToByteArray(false); + } - public string GetUpperTitleID() - { - byte[] bytes = BitConverter.GetBytes(Shared.Swap((uint) this.titleId)); - return new string(new char[4] - { + public byte[] ToByteArray(bool fakeSign) + { + if (fakeSign) + { + this.fakeSign = true; + } + + MemoryStream memoryStream = new MemoryStream(); + try + { + WriteToStream(memoryStream); + } + catch + { + memoryStream.Dispose(); + throw; + } + byte[] array = memoryStream.ToArray(); + memoryStream.Dispose(); + return array; + } + + public void SetTitleKey(string newTitleKey) + { + SetTitleKey(newTitleKey.ToCharArray()); + } + + public void SetTitleKey(char[] newTitleKey) + { + if (newTitleKey.Length != 16) + { + throw new Exception("The title key must be 16 characters long!"); + } + + for (int index = 0; index < 16; ++index) + { + encryptedTitleKey[index] = (byte)newTitleKey[index]; + } + + DecryptTitleKey(); + titleKeyChanged = true; + reDecrypt = true; + newEncryptedTitleKey = encryptedTitleKey; + } + + public void SetTitleKey(byte[] newTitleKey) + { + encryptedTitleKey = newTitleKey.Length == 16 ? newTitleKey : throw new Exception("The title key must be 16 characters long!"); + DecryptTitleKey(); + titleKeyChanged = true; + reDecrypt = true; + newEncryptedTitleKey = newTitleKey; + } + + public string GetUpperTitleID() + { + byte[] bytes = BitConverter.GetBytes(Shared.Swap((uint)titleId)); + return new string(new char[4] + { (char) bytes[0], (char) bytes[1], (char) bytes[2], (char) bytes[3] - }); - } - - private void writeToStream(Stream writeStream) - { - this.fireDebug("Writing Ticket..."); - this.fireDebug(" Encrypting Title Key..."); - this.encryptTitleKey(); - this.fireDebug(" -> Decrypted Title Key: {0}", (object) Shared.ByteArrayToString(this.decryptedTitleKey)); - this.fireDebug(" -> Encrypted Title Key: {0}", (object) Shared.ByteArrayToString(this.encryptedTitleKey)); - if (this.fakeSign) - { - this.fireDebug(" Clearing Signature..."); - this.signature = new byte[256]; - } - MemoryStream memoryStream = new MemoryStream(); - memoryStream.Seek(0L, SeekOrigin.Begin); - this.fireDebug(" Writing Signature Exponent... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); - memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.signatureExponent)), 0, 4); - this.fireDebug(" Writing Signature... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); - memoryStream.Write(this.signature, 0, this.signature.Length); - this.fireDebug(" Writing Padding... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); - memoryStream.Write(this.padding, 0, this.padding.Length); - this.fireDebug(" Writing Issuer... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); - memoryStream.Write(this.issuer, 0, this.issuer.Length); - this.fireDebug(" Writing Unknown... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); - memoryStream.Write(this.unknown, 0, this.unknown.Length); - this.fireDebug(" Writing Title Key... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); - memoryStream.Write(this.encryptedTitleKey, 0, this.encryptedTitleKey.Length); - this.fireDebug(" Writing Unknown2... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); - memoryStream.WriteByte(this.unknown2); - this.fireDebug(" Writing Ticket ID... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); - memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.ticketId)), 0, 8); - this.fireDebug(" Writing Console ID... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); - memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.consoleId)), 0, 4); - this.fireDebug(" Writing Title ID... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); - memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.titleId)), 0, 8); - this.fireDebug(" Writing Unknwon3... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); - memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.unknown3)), 0, 2); - this.fireDebug(" Writing NumOfDLC... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); - memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.numOfDlc)), 0, 2); - this.fireDebug(" Writing Unknwon4... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); - memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.unknown4)), 0, 8); - this.fireDebug(" Writing Padding2... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); - memoryStream.WriteByte(this.padding2); - this.fireDebug(" Writing Common Key Index... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); - memoryStream.WriteByte(this.commonKeyIndex); - object[] objArray1 = new object[1]; - long position = memoryStream.Position; - objArray1[0] = (object) position.ToString("x8").ToUpper(); - this.fireDebug(" Writing Unknown5... (Offset: 0x{0})", objArray1); - memoryStream.Write(this.unknown5, 0, this.unknown5.Length); - object[] objArray2 = new object[1]; - position = memoryStream.Position; - objArray2[0] = (object) position.ToString("x8").ToUpper(); - this.fireDebug(" Writing Unknown6... (Offset: 0x{0})", objArray2); - memoryStream.Write(this.unknown6, 0, this.unknown6.Length); - object[] objArray3 = new object[1]; - position = memoryStream.Position; - objArray3[0] = (object) position.ToString("x8").ToUpper(); - this.fireDebug(" Writing Padding3... (Offset: 0x{0})", objArray3); - memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.padding3)), 0, 2); - object[] objArray4 = new object[1]; - position = memoryStream.Position; - objArray4[0] = (object) position.ToString("x8").ToUpper(); - this.fireDebug(" Writing Enable Time Limit... (Offset: 0x{0})", objArray4); - memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.enableTimeLimit)), 0, 4); - object[] objArray5 = new object[1]; - position = memoryStream.Position; - objArray5[0] = (object) position.ToString("x8").ToUpper(); - this.fireDebug(" Writing Time Limit... (Offset: 0x{0})", objArray5); - memoryStream.Write(BitConverter.GetBytes(Shared.Swap(this.timeLimit)), 0, 4); - object[] objArray6 = new object[1]; - position = memoryStream.Position; - objArray6[0] = (object) position.ToString("x8").ToUpper(); - this.fireDebug(" Writing Padding4... (Offset: 0x{0})", objArray6); - memoryStream.Write(this.padding4, 0, this.padding4.Length); - byte[] array = memoryStream.ToArray(); - memoryStream.Dispose(); - if (this.fakeSign) - { - this.fireDebug(" Fakesigning Ticket..."); - byte[] numArray = new byte[20]; - SHA1 shA1 = SHA1.Create(); - for (ushort index = 0; index < ushort.MaxValue; ++index) - { - byte[] bytes = BitConverter.GetBytes(index); - array[498] = bytes[1]; - array[499] = bytes[0]; - if (shA1.ComputeHash(array)[0] == (byte) 0) - { - this.fireDebug(" -> Signed ({0})", (object) index); - break; - } - if (index == (ushort) 65534) - { - this.fireDebug(" -> Signing Failed..."); - throw new Exception("Fakesigning failed..."); - } + }); } - shA1.Clear(); - } - writeStream.Seek(0L, SeekOrigin.Begin); - writeStream.Write(array, 0, array.Length); - this.fireDebug("Writing Ticket Finished..."); - } - private void parseTicket(Stream ticketFile) - { - this.fireDebug("Parsing Ticket..."); - ticketFile.Seek(0L, SeekOrigin.Begin); - byte[] buffer = new byte[8]; - this.fireDebug(" Reading Signature Exponent... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper()); - ticketFile.Read(buffer, 0, 4); - this.signatureExponent = Shared.Swap(BitConverter.ToUInt32(buffer, 0)); - this.fireDebug(" Reading Signature... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper()); - ticketFile.Read(this.signature, 0, this.signature.Length); - this.fireDebug(" Reading Padding... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper()); - ticketFile.Read(this.padding, 0, this.padding.Length); - this.fireDebug(" Reading Issuer... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper()); - ticketFile.Read(this.issuer, 0, this.issuer.Length); - this.fireDebug(" Reading Unknown... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper()); - ticketFile.Read(this.unknown, 0, this.unknown.Length); - this.fireDebug(" Reading Title Key... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper()); - ticketFile.Read(this.encryptedTitleKey, 0, this.encryptedTitleKey.Length); - this.fireDebug(" Reading Unknown2... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper()); - this.unknown2 = (byte) ticketFile.ReadByte(); - this.fireDebug(" Reading Ticket ID.. (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper()); - ticketFile.Read(buffer, 0, 8); - this.ticketId = Shared.Swap(BitConverter.ToUInt64(buffer, 0)); - this.fireDebug(" Reading Console ID... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper()); - ticketFile.Read(buffer, 0, 4); - this.consoleId = Shared.Swap(BitConverter.ToUInt32(buffer, 0)); - this.fireDebug(" Reading Title ID... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper()); - ticketFile.Read(buffer, 0, 8); - this.titleId = Shared.Swap(BitConverter.ToUInt64(buffer, 0)); - this.fireDebug(" Reading Unknown3... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper()); - this.fireDebug(" Reading NumOfDLC... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper()); - ticketFile.Read(buffer, 0, 4); - this.unknown3 = Shared.Swap(BitConverter.ToUInt16(buffer, 0)); - this.numOfDlc = Shared.Swap(BitConverter.ToUInt16(buffer, 2)); - this.fireDebug(" Reading Unknown4... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper()); - ticketFile.Read(buffer, 0, 8); - this.unknown4 = Shared.Swap(BitConverter.ToUInt64(buffer, 0)); - this.fireDebug(" Reading Padding2... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper()); - this.padding2 = (byte) ticketFile.ReadByte(); - this.fireDebug(" Reading Common Key Index... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper()); - this.commonKeyIndex = (byte) ticketFile.ReadByte(); - this.newKeyIndex = this.commonKeyIndex; - this.fireDebug(" Reading Unknown5... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper()); - ticketFile.Read(this.unknown5, 0, this.unknown5.Length); - this.fireDebug(" Reading Unknown6... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper()); - ticketFile.Read(this.unknown6, 0, this.unknown6.Length); - this.fireDebug(" Reading Padding3... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper()); - ticketFile.Read(buffer, 0, 2); - this.padding3 = Shared.Swap(BitConverter.ToUInt16(buffer, 0)); - this.fireDebug(" Reading Enable Time Limit... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper()); - this.fireDebug(" Reading Time Limit... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper()); - ticketFile.Read(buffer, 0, 8); - this.enableTimeLimit = Shared.Swap(BitConverter.ToUInt32(buffer, 0)); - this.timeLimit = Shared.Swap(BitConverter.ToUInt32(buffer, 4)); - this.fireDebug(" Reading Padding4... (Offset: 0x{0})", (object) ticketFile.Position.ToString("x8").ToUpper()); - ticketFile.Read(this.padding4, 0, this.padding4.Length); - this.fireDebug(" Decrypting Title Key..."); - this.decryptTitleKey(); - this.fireDebug(" -> Encrypted Title Key: {0}", (object) Shared.ByteArrayToString(this.encryptedTitleKey)); - this.fireDebug(" -> Decrypted Title Key: {0}", (object) Shared.ByteArrayToString(this.decryptedTitleKey)); - this.fireDebug("Parsing Ticket Finished..."); - } + private void WriteToStream(Stream writeStream) + { + FireDebug("Writing Ticket..."); + FireDebug(" Encrypting Title Key..."); + EncryptTitleKey(); + FireDebug(" -> Decrypted Title Key: {0}", (object)Shared.ByteArrayToString(decryptedTitleKey)); + FireDebug(" -> Encrypted Title Key: {0}", (object)Shared.ByteArrayToString(encryptedTitleKey)); + if (fakeSign) + { + FireDebug(" Clearing Signature..."); + signature = new byte[256]; + } + MemoryStream memoryStream = new MemoryStream(); + memoryStream.Seek(0L, SeekOrigin.Begin); + FireDebug(" Writing Signature Exponent... (Offset: 0x{0})", (object)memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(signatureExponent)), 0, 4); + FireDebug(" Writing Signature... (Offset: 0x{0})", (object)memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(signature, 0, signature.Length); + FireDebug(" Writing Padding... (Offset: 0x{0})", (object)memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(padding, 0, padding.Length); + FireDebug(" Writing Issuer... (Offset: 0x{0})", (object)memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(issuer, 0, issuer.Length); + FireDebug(" Writing Unknown... (Offset: 0x{0})", (object)memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(unknown, 0, unknown.Length); + FireDebug(" Writing Title Key... (Offset: 0x{0})", (object)memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(encryptedTitleKey, 0, encryptedTitleKey.Length); + FireDebug(" Writing Unknown2... (Offset: 0x{0})", (object)memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.WriteByte(unknown2); + FireDebug(" Writing Ticket ID... (Offset: 0x{0})", (object)memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(ticketId)), 0, 8); + FireDebug(" Writing Console ID... (Offset: 0x{0})", (object)memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(consoleId)), 0, 4); + FireDebug(" Writing Title ID... (Offset: 0x{0})", (object)memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(titleId)), 0, 8); + FireDebug(" Writing Unknwon3... (Offset: 0x{0})", (object)memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(unknown3)), 0, 2); + FireDebug(" Writing NumOfDLC... (Offset: 0x{0})", (object)memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(numOfDlc)), 0, 2); + FireDebug(" Writing Unknwon4... (Offset: 0x{0})", (object)memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(unknown4)), 0, 8); + FireDebug(" Writing Padding2... (Offset: 0x{0})", (object)memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.WriteByte(padding2); + FireDebug(" Writing Common Key Index... (Offset: 0x{0})", (object)memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.WriteByte(commonKeyIndex); + object[] objArray1 = new object[1]; + long position = memoryStream.Position; + objArray1[0] = position.ToString("x8").ToUpper(); + FireDebug(" Writing Unknown5... (Offset: 0x{0})", objArray1); + memoryStream.Write(unknown5, 0, unknown5.Length); + object[] objArray2 = new object[1]; + position = memoryStream.Position; + objArray2[0] = position.ToString("x8").ToUpper(); + FireDebug(" Writing Unknown6... (Offset: 0x{0})", objArray2); + memoryStream.Write(unknown6, 0, unknown6.Length); + object[] objArray3 = new object[1]; + position = memoryStream.Position; + objArray3[0] = position.ToString("x8").ToUpper(); + FireDebug(" Writing Padding3... (Offset: 0x{0})", objArray3); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(padding3)), 0, 2); + object[] objArray4 = new object[1]; + position = memoryStream.Position; + objArray4[0] = position.ToString("x8").ToUpper(); + FireDebug(" Writing Enable Time Limit... (Offset: 0x{0})", objArray4); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(enableTimeLimit)), 0, 4); + object[] objArray5 = new object[1]; + position = memoryStream.Position; + objArray5[0] = position.ToString("x8").ToUpper(); + FireDebug(" Writing Time Limit... (Offset: 0x{0})", objArray5); + memoryStream.Write(BitConverter.GetBytes(Shared.Swap(timeLimit)), 0, 4); + object[] objArray6 = new object[1]; + position = memoryStream.Position; + objArray6[0] = position.ToString("x8").ToUpper(); + FireDebug(" Writing Padding4... (Offset: 0x{0})", objArray6); + memoryStream.Write(padding4, 0, padding4.Length); + byte[] array = memoryStream.ToArray(); + memoryStream.Dispose(); + if (fakeSign) + { + FireDebug(" Fakesigning Ticket..."); + //byte[] numArray = new byte[20]; + SHA1 shA1 = SHA1.Create(); + for (ushort index = 0; index < ushort.MaxValue; ++index) + { + byte[] bytes = BitConverter.GetBytes(index); + array[498] = bytes[1]; + array[499] = bytes[0]; + if (shA1.ComputeHash(array)[0] == 0) + { + FireDebug(" -> Signed ({0})", (object)index); + break; + } + if (index == 65534) + { + FireDebug(" -> Signing Failed..."); + throw new Exception("Fakesigning failed..."); + } + } + shA1.Clear(); + } + writeStream.Seek(0L, SeekOrigin.Begin); + writeStream.Write(array, 0, array.Length); + FireDebug("Writing Ticket Finished..."); + } - private void decryptTitleKey() - { - byte[] numArray = this.commonKeyIndex == (byte) 1 ? CommonKey.GetKoreanKey() : CommonKey.GetStandardKey(); - byte[] bytes = BitConverter.GetBytes(Shared.Swap(this.titleId)); - Array.Resize(ref bytes, 16); - RijndaelManaged rijndaelManaged = new RijndaelManaged(); - rijndaelManaged.Mode = CipherMode.CBC; - rijndaelManaged.Padding = PaddingMode.None; - rijndaelManaged.KeySize = 128; - rijndaelManaged.BlockSize = 128; - rijndaelManaged.Key = numArray; - rijndaelManaged.IV = bytes; - ICryptoTransform decryptor = rijndaelManaged.CreateDecryptor(); - MemoryStream memoryStream = new MemoryStream(this.encryptedTitleKey); - CryptoStream cryptoStream = new CryptoStream((Stream) memoryStream, decryptor, CryptoStreamMode.Read); - cryptoStream.Read(this.decryptedTitleKey, 0, this.decryptedTitleKey.Length); - cryptoStream.Dispose(); - memoryStream.Dispose(); - decryptor.Dispose(); - rijndaelManaged.Clear(); - } + private void ParseTicket(Stream ticketFile) + { + FireDebug("Parsing Ticket..."); + ticketFile.Seek(0L, SeekOrigin.Begin); + byte[] buffer = new byte[8]; + FireDebug(" Reading Signature Exponent... (Offset: 0x{0})", (object)ticketFile.Position.ToString("x8").ToUpper()); + ticketFile.Read(buffer, 0, 4); + signatureExponent = Shared.Swap(BitConverter.ToUInt32(buffer, 0)); + FireDebug(" Reading Signature... (Offset: 0x{0})", (object)ticketFile.Position.ToString("x8").ToUpper()); + ticketFile.Read(signature, 0, signature.Length); + FireDebug(" Reading Padding... (Offset: 0x{0})", (object)ticketFile.Position.ToString("x8").ToUpper()); + ticketFile.Read(padding, 0, padding.Length); + FireDebug(" Reading Issuer... (Offset: 0x{0})", (object)ticketFile.Position.ToString("x8").ToUpper()); + ticketFile.Read(issuer, 0, issuer.Length); + FireDebug(" Reading Unknown... (Offset: 0x{0})", (object)ticketFile.Position.ToString("x8").ToUpper()); + ticketFile.Read(unknown, 0, unknown.Length); + FireDebug(" Reading Title Key... (Offset: 0x{0})", (object)ticketFile.Position.ToString("x8").ToUpper()); + ticketFile.Read(encryptedTitleKey, 0, encryptedTitleKey.Length); + FireDebug(" Reading Unknown2... (Offset: 0x{0})", (object)ticketFile.Position.ToString("x8").ToUpper()); + unknown2 = (byte)ticketFile.ReadByte(); + FireDebug(" Reading Ticket ID.. (Offset: 0x{0})", (object)ticketFile.Position.ToString("x8").ToUpper()); + ticketFile.Read(buffer, 0, 8); + ticketId = Shared.Swap(BitConverter.ToUInt64(buffer, 0)); + FireDebug(" Reading Console ID... (Offset: 0x{0})", (object)ticketFile.Position.ToString("x8").ToUpper()); + ticketFile.Read(buffer, 0, 4); + consoleId = Shared.Swap(BitConverter.ToUInt32(buffer, 0)); + FireDebug(" Reading Title ID... (Offset: 0x{0})", (object)ticketFile.Position.ToString("x8").ToUpper()); + ticketFile.Read(buffer, 0, 8); + titleId = Shared.Swap(BitConverter.ToUInt64(buffer, 0)); + FireDebug(" Reading Unknown3... (Offset: 0x{0})", (object)ticketFile.Position.ToString("x8").ToUpper()); + FireDebug(" Reading NumOfDLC... (Offset: 0x{0})", (object)ticketFile.Position.ToString("x8").ToUpper()); + ticketFile.Read(buffer, 0, 4); + unknown3 = Shared.Swap(BitConverter.ToUInt16(buffer, 0)); + numOfDlc = Shared.Swap(BitConverter.ToUInt16(buffer, 2)); + FireDebug(" Reading Unknown4... (Offset: 0x{0})", (object)ticketFile.Position.ToString("x8").ToUpper()); + ticketFile.Read(buffer, 0, 8); + unknown4 = Shared.Swap(BitConverter.ToUInt64(buffer, 0)); + FireDebug(" Reading Padding2... (Offset: 0x{0})", (object)ticketFile.Position.ToString("x8").ToUpper()); + padding2 = (byte)ticketFile.ReadByte(); + FireDebug(" Reading Common Key Index... (Offset: 0x{0})", (object)ticketFile.Position.ToString("x8").ToUpper()); + commonKeyIndex = (byte)ticketFile.ReadByte(); + newKeyIndex = commonKeyIndex; + FireDebug(" Reading Unknown5... (Offset: 0x{0})", (object)ticketFile.Position.ToString("x8").ToUpper()); + ticketFile.Read(unknown5, 0, unknown5.Length); + FireDebug(" Reading Unknown6... (Offset: 0x{0})", (object)ticketFile.Position.ToString("x8").ToUpper()); + ticketFile.Read(unknown6, 0, unknown6.Length); + FireDebug(" Reading Padding3... (Offset: 0x{0})", (object)ticketFile.Position.ToString("x8").ToUpper()); + ticketFile.Read(buffer, 0, 2); + padding3 = Shared.Swap(BitConverter.ToUInt16(buffer, 0)); + FireDebug(" Reading Enable Time Limit... (Offset: 0x{0})", (object)ticketFile.Position.ToString("x8").ToUpper()); + FireDebug(" Reading Time Limit... (Offset: 0x{0})", (object)ticketFile.Position.ToString("x8").ToUpper()); + ticketFile.Read(buffer, 0, 8); + enableTimeLimit = Shared.Swap(BitConverter.ToUInt32(buffer, 0)); + timeLimit = Shared.Swap(BitConverter.ToUInt32(buffer, 4)); + FireDebug(" Reading Padding4... (Offset: 0x{0})", (object)ticketFile.Position.ToString("x8").ToUpper()); + ticketFile.Read(padding4, 0, padding4.Length); + FireDebug(" Decrypting Title Key..."); + DecryptTitleKey(); + FireDebug(" -> Encrypted Title Key: {0}", (object)Shared.ByteArrayToString(encryptedTitleKey)); + FireDebug(" -> Decrypted Title Key: {0}", (object)Shared.ByteArrayToString(decryptedTitleKey)); + FireDebug("Parsing Ticket Finished..."); + } - private void encryptTitleKey() - { - this.commonKeyIndex = this.newKeyIndex; - byte[] numArray = this.commonKeyIndex == (byte) 1 ? CommonKey.GetKoreanKey() : CommonKey.GetStandardKey(); - byte[] bytes = BitConverter.GetBytes(Shared.Swap(this.titleId)); - Array.Resize(ref bytes, 16); - RijndaelManaged rijndaelManaged = new RijndaelManaged(); - rijndaelManaged.Mode = CipherMode.CBC; - rijndaelManaged.Padding = PaddingMode.None; - rijndaelManaged.KeySize = 128; - rijndaelManaged.BlockSize = 128; - rijndaelManaged.Key = numArray; - rijndaelManaged.IV = bytes; - ICryptoTransform encryptor = rijndaelManaged.CreateEncryptor(); - MemoryStream memoryStream = new MemoryStream(this.decryptedTitleKey); - CryptoStream cryptoStream = new CryptoStream((Stream) memoryStream, encryptor, CryptoStreamMode.Read); - cryptoStream.Read(this.encryptedTitleKey, 0, this.encryptedTitleKey.Length); - cryptoStream.Dispose(); - memoryStream.Dispose(); - encryptor.Dispose(); - rijndaelManaged.Clear(); - } + private void DecryptTitleKey() + { + byte[] numArray = commonKeyIndex == 1 ? CommonKey.GetKoreanKey() : CommonKey.GetStandardKey(); + byte[] bytes = BitConverter.GetBytes(Shared.Swap(titleId)); + Array.Resize(ref bytes, 16); + RijndaelManaged rijndaelManaged = new RijndaelManaged + { + Mode = CipherMode.CBC, + Padding = PaddingMode.None, + KeySize = 128, + BlockSize = 128, + Key = numArray, + IV = bytes + }; + ICryptoTransform decryptor = rijndaelManaged.CreateDecryptor(); + MemoryStream memoryStream = new MemoryStream(encryptedTitleKey); + CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read); + cryptoStream.Read(decryptedTitleKey, 0, decryptedTitleKey.Length); + cryptoStream.Dispose(); + memoryStream.Dispose(); + decryptor.Dispose(); + rijndaelManaged.Clear(); + } - private void reDecryptTitleKey() - { - this.encryptedTitleKey = this.newEncryptedTitleKey; - this.decryptTitleKey(); - } + private void EncryptTitleKey() + { + commonKeyIndex = newKeyIndex; + byte[] numArray = commonKeyIndex == 1 ? CommonKey.GetKoreanKey() : CommonKey.GetStandardKey(); + byte[] bytes = BitConverter.GetBytes(Shared.Swap(titleId)); + Array.Resize(ref bytes, 16); + RijndaelManaged rijndaelManaged = new RijndaelManaged + { + Mode = CipherMode.CBC, + Padding = PaddingMode.None, + KeySize = 128, + BlockSize = 128, + Key = numArray, + IV = bytes + }; + ICryptoTransform encryptor = rijndaelManaged.CreateEncryptor(); + MemoryStream memoryStream = new MemoryStream(decryptedTitleKey); + CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Read); + cryptoStream.Read(encryptedTitleKey, 0, encryptedTitleKey.Length); + cryptoStream.Dispose(); + memoryStream.Dispose(); + encryptor.Dispose(); + rijndaelManaged.Clear(); + } - private void fireDebug(string debugMessage, params object[] args) - { - EventHandler debug = this.Debug; - if (debug == null) - return; - debug(new object(), new MessageEventArgs(string.Format(debugMessage, args))); + private void ReDecryptTitleKey() + { + encryptedTitleKey = newEncryptedTitleKey; + DecryptTitleKey(); + } + + private void FireDebug(string debugMessage, params object[] args) + { + EventHandler debug = Debug; + if (debug == null) + { + return; + } + + debug(new object(), new MessageEventArgs(string.Format(debugMessage, args))); + } } - } } diff --git a/U8.cs b/U8.cs index 23ef256..e63e7f1 100644 --- a/U8.cs +++ b/U8.cs @@ -13,773 +13,941 @@ using System.Text; namespace libWiiSharp { - public class U8 : IDisposable - { - private const int dataPadding = 32; - private Headers.HeaderType headerType; - private object header; - private U8_Header u8Header = new U8_Header(); - private U8_Node rootNode = new U8_Node(); - private List u8Nodes = new List(); - private List stringTable = new List(); - private List data = new List(); - private int iconSize = -1; - private int bannerSize = -1; - private int soundSize = -1; - private bool lz77; - private bool isDisposed; - - public Headers.HeaderType HeaderType => this.headerType; - - public object Header => this.header; - - public U8_Node RootNode => this.rootNode; - - public List Nodes => this.u8Nodes; - - public string[] StringTable => this.stringTable.ToArray(); - - public byte[][] Data => this.data.ToArray(); - - public int NumOfNodes => (int) this.rootNode.SizeOfData - 1; - - public int IconSize => this.iconSize; - - public int BannerSize => this.bannerSize; - - public int SoundSize => this.soundSize; - - public bool Lz77Compress + public class U8 : IDisposable { - get => this.lz77; - set => this.lz77 = value; - } + //private const int dataPadding = 32; + private Headers.HeaderType headerType; + private object header; + private U8_Header u8Header = new U8_Header(); + private U8_Node rootNode = new U8_Node(); + private List u8Nodes = new List(); + private List stringTable = new List(); + private List data = new List(); + private int iconSize = -1; + private int bannerSize = -1; + private int soundSize = -1; + private bool lz77; + private bool isDisposed; - public event EventHandler Progress; + public Headers.HeaderType HeaderType => headerType; - public event EventHandler Warning; + public object Header => header; - public event EventHandler Debug; + public U8_Node RootNode => rootNode; - public U8() => this.rootNode.Type = U8_NodeType.Directory; + public List Nodes => u8Nodes; - ~U8() => this.Dispose(false); + public string[] StringTable => stringTable.ToArray(); - public void Dispose() - { - this.Dispose(true); - GC.SuppressFinalize((object) this); - } + public byte[][] Data => data.ToArray(); - protected virtual void Dispose(bool disposing) - { - if (disposing && !this.isDisposed) - { - this.header = (object) null; - this.u8Header = (U8_Header) null; - this.rootNode = (U8_Node) null; - this.u8Nodes.Clear(); - this.u8Nodes = (List) null; - this.stringTable.Clear(); - this.stringTable = (List) null; - this.data.Clear(); - this.data = (List) null; - } - this.isDisposed = true; - } + public int NumOfNodes => (int)rootNode.SizeOfData - 1; - public static bool IsU8(string pathToFile) => U8.IsU8(File.ReadAllBytes(pathToFile)); + public int IconSize => iconSize; - public static bool IsU8(byte[] file) - { - if (Lz77.IsLz77Compressed(file)) - { - byte[] file1 = new byte[file.Length > 2000 ? 2000 : file.Length]; - for (int index = 0; index < file1.Length; ++index) - file1[index] = file[index]; - return U8.IsU8(new Lz77().Decompress(file1)); - } - Headers.HeaderType headerType = Headers.DetectHeader(file); - return Shared.Swap(BitConverter.ToUInt32(file, (int) headerType)) == 1437218861U; - } + public int BannerSize => bannerSize; - public static U8 Load(string pathToU8) => U8.Load(File.ReadAllBytes(pathToU8)); + public int SoundSize => soundSize; - public static U8 Load(byte[] u8File) - { - U8 u8 = new U8(); - MemoryStream memoryStream = new MemoryStream(u8File); - try - { - u8.parseU8((Stream) memoryStream); - } - catch - { - memoryStream.Dispose(); - throw; - } - memoryStream.Dispose(); - return u8; - } - - public static U8 Load(Stream u8File) - { - U8 u8 = new U8(); - u8.parseU8(u8File); - return u8; - } - - public static U8 FromDirectory(string pathToDirectory) - { - U8 u8 = new U8(); - u8.createFromDir(pathToDirectory); - return u8; - } - - public void LoadFile(string pathToU8) => this.LoadFile(File.ReadAllBytes(pathToU8)); - - public void LoadFile(byte[] u8File) - { - MemoryStream memoryStream = new MemoryStream(u8File); - try - { - this.parseU8((Stream) memoryStream); - } - catch - { - memoryStream.Dispose(); - throw; - } - memoryStream.Dispose(); - } - - public void LoadFile(Stream u8File) => this.parseU8(u8File); - - public void CreateFromDirectory(string pathToDirectory) => this.createFromDir(pathToDirectory); - - public void Save(string savePath) - { - if (File.Exists(savePath)) - File.Delete(savePath); - using (FileStream fileStream = new FileStream(savePath, FileMode.Create)) - this.writeToStream((Stream) fileStream); - } - - public MemoryStream ToMemoryStream() - { - MemoryStream memoryStream = new MemoryStream(); - try - { - this.writeToStream((Stream) memoryStream); - return memoryStream; - } - catch - { - memoryStream.Dispose(); - throw; - } - } - - public byte[] ToByteArray() => this.ToMemoryStream().ToArray(); - - public void Unpack(string saveDir) => this.unpackToDir(saveDir); - - public void Extract(string saveDir) => this.unpackToDir(saveDir); - - public void AddHeaderImet(bool shortImet, params string[] titles) - { - if (this.iconSize == -1) - throw new Exception("icon.bin wasn't found!"); - if (this.bannerSize == -1) - throw new Exception("banner.bin wasn't found!"); - if (this.soundSize == -1) - throw new Exception("sound.bin wasn't found!"); - this.header = (object) Headers.IMET.Create(shortImet, this.iconSize, this.bannerSize, this.soundSize, titles); - this.headerType = shortImet ? Headers.HeaderType.ShortIMET : Headers.HeaderType.IMET; - } - - public void AddHeaderImd5() => this.headerType = Headers.HeaderType.IMD5; - - public void ReplaceFile(int fileIndex, string pathToNewFile, bool changeFileName = false) - { - if (this.u8Nodes[fileIndex].Type == U8_NodeType.Directory) - throw new Exception("You can't replace a directory with a file!"); - this.data[fileIndex] = File.ReadAllBytes(pathToNewFile); - if (changeFileName) - this.stringTable[fileIndex] = Path.GetFileName(pathToNewFile); - if (this.stringTable[fileIndex].ToLower() == "icon.bin") - this.iconSize = this.getRealSize(File.ReadAllBytes(pathToNewFile)); - else if (this.stringTable[fileIndex].ToLower() == "banner.bin") - { - this.bannerSize = this.getRealSize(File.ReadAllBytes(pathToNewFile)); - } - else - { - if (!(this.stringTable[fileIndex].ToLower() == "sound.bin")) - return; - this.soundSize = this.getRealSize(File.ReadAllBytes(pathToNewFile)); - } - } - - public void ReplaceFile(int fileIndex, byte[] newData) - { - if (this.u8Nodes[fileIndex].Type == U8_NodeType.Directory) - throw new Exception("You can't replace a directory with a file!"); - this.data[fileIndex] = newData; - if (this.stringTable[fileIndex].ToLower() == "icon.bin") - this.iconSize = this.getRealSize(newData); - else if (this.stringTable[fileIndex].ToLower() == "banner.bin") - { - this.bannerSize = this.getRealSize(newData); - } - else - { - if (!(this.stringTable[fileIndex].ToLower() == "sound.bin")) - return; - this.soundSize = this.getRealSize(newData); - } - } - - public int GetNodeIndex(string fileOrDirName) - { - for (int index = 0; index < this.u8Nodes.Count; ++index) - { - if (this.stringTable[index].ToLower() == fileOrDirName.ToLower()) - return index; - } - return -1; - } - - public void RenameNode(int index, string newName) => this.stringTable[index] = newName; - - public void RenameNode(string oldName, string newName) => this.stringTable[this.GetNodeIndex(oldName)] = newName; - - public void AddDirectory(string path) => this.addEntry(path, new byte[0]); - - public void AddFile(string path, byte[] data) => this.addEntry(path, data); - - public void RemoveDirectory(string path) => this.removeEntry(path); - - public void RemoveFile(string path) => this.removeEntry(path); - - private void writeToStream(Stream writeStream) - { - this.fireDebug("Writing U8 File..."); - this.fireDebug(" Updating Rootnode..."); - this.rootNode.SizeOfData = (uint) (this.u8Nodes.Count + 1); - MemoryStream memoryStream = new MemoryStream(); - memoryStream.Seek((long) this.u8Header.OffsetToRootNode + (long) ((this.u8Nodes.Count + 1) * 12), SeekOrigin.Begin); - this.fireDebug(" Writing String Table... (Offset: 0x{0})", (object) memoryStream.Position.ToString("x8").ToUpper()); - memoryStream.WriteByte((byte) 0); - int num = (int) memoryStream.Position - 1; - long position; - for (int index = 0; index < this.u8Nodes.Count; ++index) - { - object[] objArray = new object[4]; - position = memoryStream.Position; - objArray[0] = (object) position.ToString("x8").ToUpper(); - objArray[1] = (object) (index + 1); - objArray[2] = (object) this.u8Nodes.Count; - objArray[3] = (object) this.stringTable[index]; - this.fireDebug(" -> Entry #{1} of {2}: \"{3}\"... (Offset: 0x{0})", objArray); - this.u8Nodes[index].OffsetToName = (ushort) ((ulong) memoryStream.Position - (ulong) num); - byte[] bytes = Encoding.ASCII.GetBytes(this.stringTable[index]); - memoryStream.Write(bytes, 0, bytes.Length); - memoryStream.WriteByte((byte) 0); - } - this.u8Header.HeaderSize = (uint) ((ulong) memoryStream.Position - (ulong) this.u8Header.OffsetToRootNode); - this.u8Header.OffsetToData = 0U; - for (int index = 0; index < this.u8Nodes.Count; ++index) - { - this.fireProgress((index + 1) * 100 / this.u8Nodes.Count); - if (this.u8Nodes[index].Type == U8_NodeType.File) + public bool Lz77Compress { - memoryStream.Seek((long) Shared.AddPadding((int) memoryStream.Position, 32), SeekOrigin.Begin); - object[] objArray = new object[3]; - position = memoryStream.Position; - objArray[0] = (object) position.ToString("x8").ToUpper(); - objArray[1] = (object) (index + 1); - objArray[2] = (object) this.u8Nodes.Count; - this.fireDebug(" Writing Data #{1} of {2}... (Offset: 0x{0})", objArray); - if (this.u8Header.OffsetToData == 0U) - this.u8Header.OffsetToData = (uint) memoryStream.Position; - this.u8Nodes[index].OffsetToData = (uint) memoryStream.Position; - this.u8Nodes[index].SizeOfData = (uint) this.data[index].Length; - memoryStream.Write(this.data[index], 0, this.data[index].Length); + get => lz77; + set => lz77 = value; } - else - this.fireDebug(" Node #{0} of {1} is a Directory...", (object) (index + 1), (object) this.u8Nodes.Count); - } - while (memoryStream.Position % 16L != 0L) - memoryStream.WriteByte((byte) 0); - memoryStream.Seek(0L, SeekOrigin.Begin); - object[] objArray1 = new object[1]; - position = memoryStream.Position; - objArray1[0] = (object) position.ToString("x8").ToUpper(); - this.fireDebug(" Writing Header... (Offset: 0x{0})", objArray1); - this.u8Header.Write((Stream) memoryStream); - object[] objArray2 = new object[1]; - position = memoryStream.Position; - objArray2[0] = (object) position.ToString("x8").ToUpper(); - this.fireDebug(" Writing Rootnode... (Offset: 0x{0})", objArray2); - this.rootNode.Write((Stream) memoryStream); - for (int index = 0; index < this.u8Nodes.Count; ++index) - { - object[] objArray3 = new object[3]; - position = memoryStream.Position; - objArray3[0] = (object) position.ToString("x8").ToUpper(); - objArray3[1] = (object) (index + 1); - objArray3[2] = (object) this.u8Nodes.Count; - this.fireDebug(" Writing Node Entry #{1} of {2}... (Offset: 0x{0})", objArray3); - this.u8Nodes[index].Write((Stream) memoryStream); - } - byte[] numArray = memoryStream.ToArray(); - memoryStream.Dispose(); - if (this.lz77) - { - this.fireDebug(" Lz77 Compressing U8 File..."); - numArray = new Lz77().Compress(numArray); - } - if (this.headerType == Headers.HeaderType.IMD5) - { - this.fireDebug(" Adding IMD5 Header..."); - writeStream.Seek(0L, SeekOrigin.Begin); - Headers.IMD5.Create(numArray).Write(writeStream); - } - else if (this.headerType == Headers.HeaderType.IMET || this.headerType == Headers.HeaderType.ShortIMET) - { - this.fireDebug(" Adding IMET Header..."); - ((Headers.IMET) this.header).IconSize = (uint) this.iconSize; - ((Headers.IMET) this.header).BannerSize = (uint) this.bannerSize; - ((Headers.IMET) this.header).SoundSize = (uint) this.soundSize; - writeStream.Seek(0L, SeekOrigin.Begin); - ((Headers.IMET) this.header).Write(writeStream); - } - writeStream.Write(numArray, 0, numArray.Length); - this.fireDebug("Writing U8 File Finished..."); - } - private void unpackToDir(string saveDir) - { - this.fireDebug("Unpacking U8 File to: {0}", (object) saveDir); - if (!Directory.Exists(saveDir)) - Directory.CreateDirectory(saveDir); - string[] strArray = new string[this.u8Nodes.Count]; - strArray[0] = saveDir; - int[] numArray = new int[this.u8Nodes.Count]; - int index1 = 0; - for (int index2 = 0; index2 < this.u8Nodes.Count; ++index2) - { - this.fireDebug(" Unpacking Entry #{0} of {1}", (object) (index2 + 1), (object) this.u8Nodes.Count); - this.fireProgress((index2 + 1) * 100 / this.u8Nodes.Count); - if (this.u8Nodes[index2].Type == U8_NodeType.Directory) - { - this.fireDebug(" -> Directory: \"{0}\"", (object) this.stringTable[index2]); - if ((int) strArray[index1][strArray[index1].Length - 1] != (int) Path.DirectorySeparatorChar) - { - // ISSUE: explicit reference operation - strArray[index1] += Path.DirectorySeparatorChar.ToString(); - } - Directory.CreateDirectory(strArray[index1] + this.stringTable[index2]); - strArray[index1 + 1] = strArray[index1] + this.stringTable[index2]; - ++index1; - numArray[index1] = (int) this.u8Nodes[index2].SizeOfData; - } - else - { - this.fireDebug(" -> File: \"{0}\"", (object) this.stringTable[index2]); - this.fireDebug(" -> Size: {0} bytes", (object) this.data[index2].Length); - using (FileStream fileStream = new FileStream(strArray[index1] + Path.DirectorySeparatorChar.ToString() + this.stringTable[index2], FileMode.Create)) - fileStream.Write(this.data[index2], 0, this.data[index2].Length); - } - while (index1 > 0 && numArray[index1] == index2 + 2) - --index1; - } - this.fireDebug("Unpacking U8 File Finished"); - } + public event EventHandler Progress; - private void parseU8(Stream u8File) - { - this.fireDebug("Pasing U8 File..."); - this.u8Header = new U8_Header(); - this.rootNode = new U8_Node(); - this.u8Nodes = new List(); - this.stringTable = new List(); - this.data = new List(); - this.fireDebug(" Detecting Header..."); - this.headerType = Headers.DetectHeader(u8File); - Headers.HeaderType headerType = this.headerType; - this.fireDebug(" -> {0}", (object) this.headerType.ToString()); - if (this.headerType == Headers.HeaderType.IMD5) - { - this.fireDebug(" Reading IMD5 Header..."); - this.header = (object) Headers.IMD5.Load(u8File); - byte[] buffer = new byte[u8File.Length]; - u8File.Read(buffer, 0, buffer.Length); - MD5 md5 = MD5.Create(); - byte[] hash1 = md5.ComputeHash(buffer, (int) this.headerType, (int) ((int) u8File.Length - this.headerType)); - md5.Clear(); - byte[] hash2 = ((Headers.IMD5) this.header).Hash; - if (!Shared.CompareByteArrays(hash1, hash2)) - { - this.fireDebug("/!\\ /!\\ /!\\ Hashes do not match /!\\ /!\\ /!\\"); - this.fireWarning("Hashes of IMD5 header and file do not match! The content might be corrupted!"); - } - } - else if (this.headerType == Headers.HeaderType.IMET || this.headerType == Headers.HeaderType.ShortIMET) - { - this.fireDebug(" Reading IMET Header..."); - this.header = (object) Headers.IMET.Load(u8File); - if (!((Headers.IMET) this.header).HashesMatch) - { - this.fireDebug("/!\\ /!\\ /!\\ Hashes do not match /!\\ /!\\ /!\\"); - this.fireWarning("The hash stored in the IMET header doesn't match the headers hash! The header and/or file might be corrupted!"); - } - } - this.fireDebug(" Checking for Lz77 Compression..."); - if (Lz77.IsLz77Compressed(u8File)) - { - this.fireDebug(" -> Lz77 Compression Found..."); - this.fireDebug(" Decompressing U8 Data..."); - Stream file = new Lz77().Decompress(u8File); - headerType = Headers.DetectHeader(file); - u8File = file; - this.lz77 = true; - } - u8File.Seek((long) headerType, SeekOrigin.Begin); - byte[] buffer1 = new byte[4]; - this.fireDebug(" Reading U8 Header: Magic... (Offset: 0x{0})", (object) u8File.Position.ToString("x8").ToUpper()); - u8File.Read(buffer1, 0, 4); - if ((int) Shared.Swap(BitConverter.ToUInt32(buffer1, 0)) != (int) this.u8Header.U8Magic) - { - this.fireDebug(" -> Invalid Magic!"); - throw new Exception("U8 Header: Invalid Magic!"); - } - this.fireDebug(" Reading U8 Header: Offset to Rootnode... (Offset: 0x{0})", (object) u8File.Position.ToString("x8").ToUpper()); - u8File.Read(buffer1, 0, 4); - if ((int) Shared.Swap(BitConverter.ToUInt32(buffer1, 0)) != (int) this.u8Header.OffsetToRootNode) - { - this.fireDebug(" -> Invalid Offset to Rootnode"); - throw new Exception("U8 Header: Invalid Offset to Rootnode!"); - } - this.fireDebug(" Reading U8 Header: Header Size... (Offset: 0x{0})", (object) u8File.Position.ToString("x8").ToUpper()); - u8File.Read(buffer1, 0, 4); - this.u8Header.HeaderSize = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); - this.fireDebug(" Reading U8 Header: Offset to Data... (Offset: 0x{0})", (object) u8File.Position.ToString("x8").ToUpper()); - u8File.Read(buffer1, 0, 4); - this.u8Header.OffsetToData = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); - u8File.Seek(16L, SeekOrigin.Current); - object[] objArray1 = new object[1]; - long position1 = u8File.Position; - objArray1[0] = (object) position1.ToString("x8").ToUpper(); - this.fireDebug(" Reading Rootnode... (Offset: 0x{0})", objArray1); - u8File.Read(buffer1, 0, 4); - this.rootNode.Type = (U8_NodeType) Shared.Swap(BitConverter.ToUInt16(buffer1, 0)); - this.rootNode.OffsetToName = Shared.Swap(BitConverter.ToUInt16(buffer1, 2)); - u8File.Read(buffer1, 0, 4); - this.rootNode.OffsetToData = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); - u8File.Read(buffer1, 0, 4); - this.rootNode.SizeOfData = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); - int num = (int) ((long) headerType + (long) this.u8Header.OffsetToRootNode + (long) (this.rootNode.SizeOfData * 12U)); - int position2 = (int) u8File.Position; - for (int index = 0; (long) index < (long) (this.rootNode.SizeOfData - 1U); ++index) - { - object[] objArray2 = new object[3]; - position1 = u8File.Position; - objArray2[0] = (object) position1.ToString("x8").ToUpper(); - objArray2[1] = (object) (index + 1); - objArray2[2] = (object) (uint) ((int) this.rootNode.SizeOfData - 1); - this.fireDebug(" Reading Node #{1} of {2}... (Offset: 0x{0})", objArray2); - this.fireProgress((int) ((long) ((index + 1) * 100) / (long) (this.rootNode.SizeOfData - 1U))); - U8_Node u8Node = new U8_Node(); - string empty = string.Empty; - byte[] numArray = new byte[0]; - u8File.Seek((long) position2, SeekOrigin.Begin); - object[] objArray3 = new object[1]; - position1 = u8File.Position; - objArray3[0] = (object) position1.ToString("x8").ToUpper(); - this.fireDebug(" -> Reading Node Entry... (Offset: 0x{0})", objArray3); - u8File.Read(buffer1, 0, 4); - u8Node.Type = (U8_NodeType) Shared.Swap(BitConverter.ToUInt16(buffer1, 0)); - u8Node.OffsetToName = Shared.Swap(BitConverter.ToUInt16(buffer1, 2)); - u8File.Read(buffer1, 0, 4); - u8Node.OffsetToData = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); - u8File.Read(buffer1, 0, 4); - u8Node.SizeOfData = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); - position2 = (int) u8File.Position; - this.fireDebug(" -> {0}", (object) u8Node.Type.ToString()); - u8File.Seek((long) (num + (int) u8Node.OffsetToName), SeekOrigin.Begin); - object[] objArray4 = new object[1]; - position1 = u8File.Position; - objArray4[0] = (object) position1.ToString("x8").ToUpper(); - this.fireDebug(" -> Reading Node Name... (Offset: 0x{0})", objArray4); - do - { - char ch = (char) u8File.ReadByte(); - if (ch != char.MinValue) - empty += ch.ToString(); - else - break; - } - while (empty.Length <= (int) byte.MaxValue); - this.fireDebug(" -> {0}", (object) empty); - if (u8Node.Type == U8_NodeType.File) - { - u8File.Seek((long) headerType + (long) u8Node.OffsetToData, SeekOrigin.Begin); - object[] objArray5 = new object[1]; - position1 = u8File.Position; - objArray5[0] = (object) position1.ToString("x8").ToUpper(); - this.fireDebug(" -> Reading Node Data (Offset: 0x{0})", objArray5); - numArray = new byte[(int) u8Node.SizeOfData]; - u8File.Read(numArray, 0, numArray.Length); - } - if (empty.ToLower() == "icon.bin") - this.iconSize = this.getRealSize(numArray); - else if (empty.ToLower() == "banner.bin") - this.bannerSize = this.getRealSize(numArray); - else if (empty.ToLower() == "sound.bin") - this.soundSize = this.getRealSize(numArray); - this.u8Nodes.Add(u8Node); - this.stringTable.Add(empty); - this.data.Add(numArray); - } - this.fireDebug("Pasing U8 File Finished..."); - } + public event EventHandler Warning; - private void createFromDir(string path) - { - this.fireDebug("Creating U8 File from: {0}", (object) path); - if ((int) path[path.Length - 1] != (int) Path.DirectorySeparatorChar) - path += Path.DirectorySeparatorChar.ToString(); - this.fireDebug(" Collecting Content..."); - string[] dirContent = this.getDirContent(path, true); - int num1 = 1; - int num2 = 0; - this.fireDebug(" Creating U8 Header..."); - this.u8Header = new U8_Header(); - this.rootNode = new U8_Node(); - this.u8Nodes = new List(); - this.stringTable = new List(); - this.data = new List(); - this.fireDebug(" Creating Rootnode..."); - this.rootNode.Type = U8_NodeType.Directory; - this.rootNode.OffsetToName = (ushort) 0; - this.rootNode.OffsetToData = 0U; - this.rootNode.SizeOfData = (uint) (dirContent.Length + 1); - for (int index1 = 0; index1 < dirContent.Length; ++index1) - { - this.fireDebug(" Creating Node #{0} of {1}", (object) (index1 + 1), (object) dirContent.Length); - this.fireProgress((index1 + 1) * 100 / dirContent.Length); - U8_Node u8Node = new U8_Node(); - byte[] data = new byte[0]; - string theString = dirContent[index1].Remove(0, path.Length - 1); - if (Directory.Exists(dirContent[index1])) + public event EventHandler Debug; + + public U8() { - this.fireDebug(" -> Directory"); - u8Node.Type = U8_NodeType.Directory; - u8Node.OffsetToData = (uint) Shared.CountCharsInString(theString, Path.DirectorySeparatorChar); - int num3 = this.u8Nodes.Count + 2; - for (int index2 = 0; index2 < dirContent.Length; ++index2) - { - if (dirContent[index2].Contains(dirContent[index1] + "\\")) - ++num3; - } - u8Node.SizeOfData = (uint) num3; + rootNode.Type = U8_NodeType.Directory; } - else + + ~U8() => Dispose(false); + + public void Dispose() { - this.fireDebug(" -> File"); - this.fireDebug(" -> Reading File Data..."); - data = File.ReadAllBytes(dirContent[index1]); - u8Node.Type = U8_NodeType.File; - u8Node.OffsetToData = (uint) num2; - u8Node.SizeOfData = (uint) data.Length; - num2 += Shared.AddPadding(num2 + data.Length, 32); + Dispose(true); + GC.SuppressFinalize(this); } - u8Node.OffsetToName = (ushort) num1; - num1 += Path.GetFileName(dirContent[index1]).Length + 1; - this.fireDebug(" -> Reading Name..."); - string fileName = Path.GetFileName(dirContent[index1]); - if (fileName.ToLower() == "icon.bin") - this.iconSize = this.getRealSize(data); - else if (fileName.ToLower() == "banner.bin") - this.bannerSize = this.getRealSize(data); - else if (fileName.ToLower() == "sound.bin") - this.soundSize = this.getRealSize(data); - this.u8Nodes.Add(u8Node); - this.stringTable.Add(fileName); - this.data.Add(data); - } - this.fireDebug(" Updating U8 Header..."); - this.u8Header.HeaderSize = (uint) ((this.u8Nodes.Count + 1) * 12 + num1); - this.u8Header.OffsetToData = (uint) Shared.AddPadding((int) this.u8Header.OffsetToRootNode + (int) this.u8Header.HeaderSize, 32); - this.fireDebug(" Calculating Data Offsets..."); - for (int index = 0; index < this.u8Nodes.Count; ++index) - { - this.fireDebug(" -> Node #{0} of {1}...", (object) (index + 1), (object) this.u8Nodes.Count); - int offsetToData = (int) this.u8Nodes[index].OffsetToData; - this.u8Nodes[index].OffsetToData = (uint) ((ulong) this.u8Header.OffsetToData + (ulong) offsetToData); - } - this.fireDebug("Creating U8 File Finished..."); - } - private string[] getDirContent(string dir, bool root) - { - string[] files = Directory.GetFiles(dir); - string[] directories = Directory.GetDirectories(dir); - string str1 = ""; - if (!root) - str1 = str1 + dir + "\n"; - for (int index = 0; index < files.Length; ++index) - str1 = str1 + files[index] + "\n"; - foreach (string dir1 in directories) - { - foreach (string str2 in this.getDirContent(dir1, false)) - str1 = str1 + str2 + "\n"; - } - return str1.Split(new char[1]{ '\n' }, StringSplitOptions.RemoveEmptyEntries); - } - - private int getRealSize(byte[] data) - { - if (data[0] != (byte) 73 || data[1] != (byte) 77 || (data[2] != (byte) 68 || data[3] != (byte) 53)) - return data.Length; - return data[32] == (byte) 76 && data[33] == (byte) 90 && (data[34] == (byte) 55 && data[35] == (byte) 55) ? BitConverter.ToInt32(data, 36) >> 8 : data.Length - 32; - } - - private void addEntry(string nodePath, byte[] fileData) - { - if (nodePath.StartsWith("/")) - nodePath = nodePath.Remove(0, 1); - string[] strArray = nodePath.Split('/'); - int index1 = -1; - int num1 = this.u8Nodes.Count > 0 ? this.u8Nodes.Count - 1 : 0; - int num2 = 0; - List intList = new List(); - for (int index2 = 0; index2 < strArray.Length - 1; ++index2) - { - for (int index3 = num2; index3 <= num1; ++index3) + protected virtual void Dispose(bool disposing) { - if (!(this.stringTable[index3].ToLower() == strArray[index2].ToLower())) - { - if (index3 == num1 - 1) - throw new Exception("Path wasn't found!"); - } - else - { - if (index2 == strArray.Length - 2) - index1 = index3; - num1 = (int) this.u8Nodes[index3].SizeOfData - 1; - num2 = index3 + 1; - intList.Add(index3); - break; - } + if (disposing && !isDisposed) + { + header = null; + u8Header = null; + rootNode = null; + u8Nodes.Clear(); + u8Nodes = null; + stringTable.Clear(); + stringTable = null; + data.Clear(); + data = null; + } + isDisposed = true; } - } - int num3 = index1 > -1 ? (int) this.u8Nodes[index1].SizeOfData - 2 : (this.rootNode.SizeOfData > 1U ? (int) this.rootNode.SizeOfData - 2 : -1); - U8_Node u8Node = new U8_Node(); - u8Node.Type = fileData.Length == 0 ? U8_NodeType.Directory : U8_NodeType.File; - u8Node.SizeOfData = fileData.Length == 0 ? (uint) (num3 + 2) : (uint) fileData.Length; - u8Node.OffsetToData = fileData.Length == 0 ? (uint) Shared.CountCharsInString(nodePath, '/') : 0U; - this.stringTable.Insert(num3 + 1, strArray[strArray.Length - 1]); - this.u8Nodes.Insert(num3 + 1, u8Node); - this.data.Insert(num3 + 1, fileData); - ++this.rootNode.SizeOfData; - foreach (int index2 in intList) - { - if (this.u8Nodes[index2].Type == U8_NodeType.Directory) - ++this.u8Nodes[index2].SizeOfData; - } - for (int index2 = num3 + 1; index2 < this.u8Nodes.Count; ++index2) - { - if (this.u8Nodes[index2].Type == U8_NodeType.Directory) - ++this.u8Nodes[index2].SizeOfData; - } - } - private void removeEntry(string nodePath) - { - if (nodePath.StartsWith("/")) - nodePath = nodePath.Remove(0, 1); - string[] strArray = nodePath.Split('/'); - int index1 = -1; - int num1 = this.u8Nodes.Count - 1; - int num2 = 0; - List intList = new List(); - for (int index2 = 0; index2 < strArray.Length; ++index2) - { - for (int index3 = num2; index3 < num1; ++index3) + public static bool IsU8(string pathToFile) { - if (!(this.stringTable[index3].ToLower() == strArray[index2].ToLower())) - { - if (index3 == num1 - 1) - throw new Exception("Path wasn't found!"); - } - else - { - if (index2 == strArray.Length - 1) - index1 = index3; + return U8.IsU8(File.ReadAllBytes(pathToFile)); + } + + public static bool IsU8(byte[] file) + { + if (Lz77.IsLz77Compressed(file)) + { + byte[] file1 = new byte[file.Length > 2000 ? 2000 : file.Length]; + for (int index = 0; index < file1.Length; ++index) + { + file1[index] = file[index]; + } + + return U8.IsU8(new Lz77().Decompress(file1)); + } + Headers.HeaderType headerType = Headers.DetectHeader(file); + return Shared.Swap(BitConverter.ToUInt32(file, (int)headerType)) == 1437218861U; + } + + public static U8 Load(string pathToU8) + { + return U8.Load(File.ReadAllBytes(pathToU8)); + } + + public static U8 Load(byte[] u8File) + { + U8 u8 = new U8(); + MemoryStream memoryStream = new MemoryStream(u8File); + try + { + u8.ParseU8(memoryStream); + } + catch + { + memoryStream.Dispose(); + throw; + } + memoryStream.Dispose(); + return u8; + } + + public static U8 Load(Stream u8File) + { + U8 u8 = new U8(); + u8.ParseU8(u8File); + return u8; + } + + public static U8 FromDirectory(string pathToDirectory) + { + U8 u8 = new U8(); + u8.CreateFromDir(pathToDirectory); + return u8; + } + + public void LoadFile(string pathToU8) + { + LoadFile(File.ReadAllBytes(pathToU8)); + } + + public void LoadFile(byte[] u8File) + { + MemoryStream memoryStream = new MemoryStream(u8File); + try + { + ParseU8(memoryStream); + } + catch + { + memoryStream.Dispose(); + throw; + } + memoryStream.Dispose(); + } + + public void LoadFile(Stream u8File) + { + ParseU8(u8File); + } + + public void CreateFromDirectory(string pathToDirectory) + { + CreateFromDir(pathToDirectory); + } + + public void Save(string savePath) + { + if (File.Exists(savePath)) + { + File.Delete(savePath); + } + + using FileStream fileStream = new FileStream(savePath, FileMode.Create); + WriteToStream(fileStream); + } + + public MemoryStream ToMemoryStream() + { + MemoryStream memoryStream = new MemoryStream(); + try + { + WriteToStream(memoryStream); + return memoryStream; + } + catch + { + memoryStream.Dispose(); + throw; + } + } + + public byte[] ToByteArray() + { + return ToMemoryStream().ToArray(); + } + + public void Unpack(string saveDir) + { + UnpackToDir(saveDir); + } + + public void Extract(string saveDir) + { + UnpackToDir(saveDir); + } + + public void AddHeaderImet(bool shortImet, params string[] titles) + { + if (iconSize == -1) + { + throw new Exception("icon.bin wasn't found!"); + } + + if (bannerSize == -1) + { + throw new Exception("banner.bin wasn't found!"); + } + + 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; + } + + public void AddHeaderImd5() + { + headerType = Headers.HeaderType.IMD5; + } + + public void ReplaceFile(int fileIndex, string pathToNewFile, bool changeFileName = false) + { + if (u8Nodes[fileIndex].Type == U8_NodeType.Directory) + { + throw new Exception("You can't replace a directory with a file!"); + } + + data[fileIndex] = File.ReadAllBytes(pathToNewFile); + if (changeFileName) + { + stringTable[fileIndex] = Path.GetFileName(pathToNewFile); + } + + if (stringTable[fileIndex].ToLower() == "icon.bin") + { + iconSize = GetRealSize(File.ReadAllBytes(pathToNewFile)); + } + else if (stringTable[fileIndex].ToLower() == "banner.bin") + { + bannerSize = GetRealSize(File.ReadAllBytes(pathToNewFile)); + } else - intList.Add(index3); - num1 = (int) this.u8Nodes[index3].SizeOfData - 1; - num2 = index3 + 1; - break; - } + { + if (!(stringTable[fileIndex].ToLower() == "sound.bin")) + { + return; + } + + soundSize = GetRealSize(File.ReadAllBytes(pathToNewFile)); + } } - } - int num3 = 0; - if (this.u8Nodes[index1].Type == U8_NodeType.Directory) - { - for (int index2 = (int) this.u8Nodes[index1].SizeOfData - 2; index2 >= index1; --index2) + + public void ReplaceFile(int fileIndex, byte[] newData) { - this.stringTable.RemoveAt(index2); - this.u8Nodes.RemoveAt(index2); - this.data.RemoveAt(index2); - ++num3; + if (u8Nodes[fileIndex].Type == U8_NodeType.Directory) + { + throw new Exception("You can't replace a directory with a file!"); + } + + data[fileIndex] = newData; + if (stringTable[fileIndex].ToLower() == "icon.bin") + { + iconSize = GetRealSize(newData); + } + else if (stringTable[fileIndex].ToLower() == "banner.bin") + { + bannerSize = GetRealSize(newData); + } + else + { + if (!(stringTable[fileIndex].ToLower() == "sound.bin")) + { + return; + } + + soundSize = GetRealSize(newData); + } } - } - else - { - this.stringTable.RemoveAt(index1); - this.u8Nodes.RemoveAt(index1); - this.data.RemoveAt(index1); - ++num3; - } - this.rootNode.SizeOfData -= (uint) num3; - foreach (int index2 in intList) - { - if (this.u8Nodes[index2].Type == U8_NodeType.Directory) - this.u8Nodes[index2].SizeOfData -= (uint) num3; - } - for (int index2 = index1 + 1; index2 < this.u8Nodes.Count; ++index2) - { - if (this.u8Nodes[index2].Type == U8_NodeType.Directory) - this.u8Nodes[index2].SizeOfData -= (uint) num3; - } - } - private void fireWarning(string warningMessage) - { - EventHandler warning = this.Warning; - if (warning == null) - return; - warning(new object(), new MessageEventArgs(warningMessage)); - } + public int GetNodeIndex(string fileOrDirName) + { + for (int index = 0; index < u8Nodes.Count; ++index) + { + if (stringTable[index].ToLower() == fileOrDirName.ToLower()) + { + return index; + } + } + return -1; + } - private void fireDebug(string debugMessage, params object[] args) - { - EventHandler debug = this.Debug; - if (debug == null) - return; - debug(new object(), new MessageEventArgs(string.Format(debugMessage, args))); - } + public void RenameNode(int index, string newName) + { + stringTable[index] = newName; + } - private void fireProgress(int progressPercentage) - { - EventHandler progress = this.Progress; - if (progress == null) - return; - progress(new object(), new ProgressChangedEventArgs(progressPercentage, (object) string.Empty)); + public void RenameNode(string oldName, string newName) + { + stringTable[GetNodeIndex(oldName)] = newName; + } + + public void AddDirectory(string path) + { + AddEntry(path, new byte[0]); + } + + public void AddFile(string path, byte[] data) + { + AddEntry(path, data); + } + + public void RemoveDirectory(string path) + { + RemoveEntry(path); + } + + public void RemoveFile(string path) + { + RemoveEntry(path); + } + + private void WriteToStream(Stream writeStream) + { + FireDebug("Writing U8 File..."); + FireDebug(" Updating Rootnode..."); + rootNode.SizeOfData = (uint)(u8Nodes.Count + 1); + MemoryStream memoryStream = new MemoryStream(); + memoryStream.Seek(u8Header.OffsetToRootNode + (u8Nodes.Count + 1) * 12, SeekOrigin.Begin); + FireDebug(" Writing String Table... (Offset: 0x{0})", (object)memoryStream.Position.ToString("x8").ToUpper()); + memoryStream.WriteByte(0); + int num = (int)memoryStream.Position - 1; + long position; + for (int index = 0; index < u8Nodes.Count; ++index) + { + object[] objArray = new object[4]; + position = memoryStream.Position; + objArray[0] = position.ToString("x8").ToUpper(); + objArray[1] = index + 1; + objArray[2] = u8Nodes.Count; + objArray[3] = stringTable[index]; + FireDebug(" -> Entry #{1} of {2}: \"{3}\"... (Offset: 0x{0})", objArray); + u8Nodes[index].OffsetToName = (ushort)((ulong)memoryStream.Position - (ulong)num); + byte[] bytes = Encoding.ASCII.GetBytes(stringTable[index]); + memoryStream.Write(bytes, 0, bytes.Length); + memoryStream.WriteByte(0); + } + u8Header.HeaderSize = (uint)((ulong)memoryStream.Position - u8Header.OffsetToRootNode); + u8Header.OffsetToData = 0U; + for (int index = 0; index < u8Nodes.Count; ++index) + { + FireProgress((index + 1) * 100 / u8Nodes.Count); + if (u8Nodes[index].Type == U8_NodeType.File) + { + memoryStream.Seek(Shared.AddPadding((int)memoryStream.Position, 32), SeekOrigin.Begin); + object[] objArray = new object[3]; + position = memoryStream.Position; + objArray[0] = position.ToString("x8").ToUpper(); + objArray[1] = index + 1; + objArray[2] = u8Nodes.Count; + FireDebug(" Writing Data #{1} of {2}... (Offset: 0x{0})", objArray); + if (u8Header.OffsetToData == 0U) + { + u8Header.OffsetToData = (uint)memoryStream.Position; + } + + u8Nodes[index].OffsetToData = (uint)memoryStream.Position; + u8Nodes[index].SizeOfData = (uint)data[index].Length; + memoryStream.Write(data[index], 0, data[index].Length); + } + else + { + FireDebug(" Node #{0} of {1} is a Directory...", index + 1, u8Nodes.Count); + } + } + while (memoryStream.Position % 16L != 0L) + { + memoryStream.WriteByte(0); + } + + memoryStream.Seek(0L, SeekOrigin.Begin); + object[] objArray1 = new object[1]; + position = memoryStream.Position; + objArray1[0] = position.ToString("x8").ToUpper(); + FireDebug(" Writing Header... (Offset: 0x{0})", objArray1); + u8Header.Write(memoryStream); + object[] objArray2 = new object[1]; + position = memoryStream.Position; + objArray2[0] = position.ToString("x8").ToUpper(); + FireDebug(" Writing Rootnode... (Offset: 0x{0})", objArray2); + rootNode.Write(memoryStream); + for (int index = 0; index < u8Nodes.Count; ++index) + { + object[] objArray3 = new object[3]; + position = memoryStream.Position; + objArray3[0] = position.ToString("x8").ToUpper(); + objArray3[1] = index + 1; + objArray3[2] = u8Nodes.Count; + FireDebug(" Writing Node Entry #{1} of {2}... (Offset: 0x{0})", objArray3); + u8Nodes[index].Write(memoryStream); + } + byte[] numArray = memoryStream.ToArray(); + memoryStream.Dispose(); + if (lz77) + { + FireDebug(" Lz77 Compressing U8 File..."); + numArray = new Lz77().Compress(numArray); + } + if (headerType == Headers.HeaderType.IMD5) + { + FireDebug(" Adding IMD5 Header..."); + writeStream.Seek(0L, SeekOrigin.Begin); + Headers.IMD5.Create(numArray).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(0L, SeekOrigin.Begin); + ((Headers.IMET)header).Write(writeStream); + } + writeStream.Write(numArray, 0, numArray.Length); + FireDebug("Writing U8 File Finished..."); + } + + private void UnpackToDir(string saveDir) + { + FireDebug("Unpacking U8 File to: {0}", (object)saveDir); + if (!Directory.Exists(saveDir)) + { + Directory.CreateDirectory(saveDir); + } + + string[] strArray = new string[u8Nodes.Count]; + strArray[0] = saveDir; + int[] numArray = new int[u8Nodes.Count]; + int index1 = 0; + for (int index2 = 0; index2 < u8Nodes.Count; ++index2) + { + FireDebug(" Unpacking Entry #{0} of {1}", index2 + 1, u8Nodes.Count); + FireProgress((index2 + 1) * 100 / u8Nodes.Count); + if (u8Nodes[index2].Type == U8_NodeType.Directory) + { + FireDebug(" -> Directory: \"{0}\"", (object)stringTable[index2]); + if (strArray[index1][strArray[index1].Length - 1] != Path.DirectorySeparatorChar) + { + // ISSUE: explicit reference operation + strArray[index1] += Path.DirectorySeparatorChar.ToString(); + } + Directory.CreateDirectory(strArray[index1] + stringTable[index2]); + strArray[index1 + 1] = strArray[index1] + stringTable[index2]; + ++index1; + numArray[index1] = (int)u8Nodes[index2].SizeOfData; + } + else + { + FireDebug(" -> File: \"{0}\"", (object)stringTable[index2]); + FireDebug(" -> Size: {0} bytes", (object)data[index2].Length); + using FileStream fileStream = new FileStream(strArray[index1] + Path.DirectorySeparatorChar.ToString() + stringTable[index2], FileMode.Create); + fileStream.Write(data[index2], 0, data[index2].Length); + } + while (index1 > 0 && numArray[index1] == index2 + 2) + { + --index1; + } + } + FireDebug("Unpacking U8 File Finished"); + } + + private void ParseU8(Stream u8File) + { + FireDebug("Pasing U8 File..."); + u8Header = new U8_Header(); + rootNode = new U8_Node(); + u8Nodes = new List(); + stringTable = new List(); + data = new List(); + FireDebug(" Detecting Header..."); + this.headerType = Headers.DetectHeader(u8File); + Headers.HeaderType headerType = this.headerType; + FireDebug(" -> {0}", (object)this.headerType.ToString()); + if (this.headerType == Headers.HeaderType.IMD5) + { + FireDebug(" Reading IMD5 Header..."); + header = Headers.IMD5.Load(u8File); + byte[] buffer = new byte[u8File.Length]; + u8File.Read(buffer, 0, buffer.Length); + MD5 md5 = MD5.Create(); + byte[] hash1 = md5.ComputeHash(buffer, (int)this.headerType, (int)((int)u8File.Length - this.headerType)); + md5.Clear(); + byte[] hash2 = ((Headers.IMD5)header).Hash; + if (!Shared.CompareByteArrays(hash1, hash2)) + { + FireDebug("/!\\ /!\\ /!\\ Hashes do not match /!\\ /!\\ /!\\"); + FireWarning("Hashes of IMD5 header and file do not match! The content might be corrupted!"); + } + } + else if (this.headerType == Headers.HeaderType.IMET || this.headerType == Headers.HeaderType.ShortIMET) + { + FireDebug(" Reading IMET Header..."); + header = Headers.IMET.Load(u8File); + if (!((Headers.IMET)header).HashesMatch) + { + FireDebug("/!\\ /!\\ /!\\ Hashes do not match /!\\ /!\\ /!\\"); + FireWarning("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..."); + Stream file = new Lz77().Decompress(u8File); + headerType = Headers.DetectHeader(file); + u8File = file; + lz77 = true; + } + u8File.Seek((long)headerType, SeekOrigin.Begin); + byte[] buffer1 = new byte[4]; + FireDebug(" Reading U8 Header: Magic... (Offset: 0x{0})", (object)u8File.Position.ToString("x8").ToUpper()); + u8File.Read(buffer1, 0, 4); + if ((int)Shared.Swap(BitConverter.ToUInt32(buffer1, 0)) != (int)u8Header.U8Magic) + { + FireDebug(" -> Invalid Magic!"); + throw new Exception("U8 Header: Invalid Magic!"); + } + FireDebug(" Reading U8 Header: Offset to Rootnode... (Offset: 0x{0})", (object)u8File.Position.ToString("x8").ToUpper()); + u8File.Read(buffer1, 0, 4); + if ((int)Shared.Swap(BitConverter.ToUInt32(buffer1, 0)) != (int)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})", (object)u8File.Position.ToString("x8").ToUpper()); + u8File.Read(buffer1, 0, 4); + u8Header.HeaderSize = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); + FireDebug(" Reading U8 Header: Offset to Data... (Offset: 0x{0})", (object)u8File.Position.ToString("x8").ToUpper()); + u8File.Read(buffer1, 0, 4); + u8Header.OffsetToData = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); + u8File.Seek(16L, SeekOrigin.Current); + object[] objArray1 = new object[1]; + long position1 = u8File.Position; + objArray1[0] = position1.ToString("x8").ToUpper(); + FireDebug(" Reading Rootnode... (Offset: 0x{0})", objArray1); + u8File.Read(buffer1, 0, 4); + rootNode.Type = (U8_NodeType)Shared.Swap(BitConverter.ToUInt16(buffer1, 0)); + rootNode.OffsetToName = Shared.Swap(BitConverter.ToUInt16(buffer1, 2)); + u8File.Read(buffer1, 0, 4); + rootNode.OffsetToData = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); + u8File.Read(buffer1, 0, 4); + rootNode.SizeOfData = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); + int num = (int)((long)headerType + u8Header.OffsetToRootNode + rootNode.SizeOfData * 12U); + int position2 = (int)u8File.Position; + for (int index = 0; index < rootNode.SizeOfData - 1U; ++index) + { + object[] objArray2 = new object[3]; + position1 = u8File.Position; + objArray2[0] = position1.ToString("x8").ToUpper(); + objArray2[1] = index + 1; + objArray2[2] = (uint)((int)rootNode.SizeOfData - 1); + FireDebug(" Reading Node #{1} of {2}... (Offset: 0x{0})", objArray2); + FireProgress((int)((index + 1) * 100 / (rootNode.SizeOfData - 1U))); + U8_Node u8Node = new U8_Node(); + string empty = string.Empty; + byte[] numArray = new byte[0]; + u8File.Seek(position2, SeekOrigin.Begin); + object[] objArray3 = new object[1]; + position1 = u8File.Position; + objArray3[0] = position1.ToString("x8").ToUpper(); + FireDebug(" -> Reading Node Entry... (Offset: 0x{0})", objArray3); + u8File.Read(buffer1, 0, 4); + u8Node.Type = (U8_NodeType)Shared.Swap(BitConverter.ToUInt16(buffer1, 0)); + u8Node.OffsetToName = Shared.Swap(BitConverter.ToUInt16(buffer1, 2)); + u8File.Read(buffer1, 0, 4); + u8Node.OffsetToData = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); + u8File.Read(buffer1, 0, 4); + u8Node.SizeOfData = Shared.Swap(BitConverter.ToUInt32(buffer1, 0)); + position2 = (int)u8File.Position; + FireDebug(" -> {0}", (object)u8Node.Type.ToString()); + u8File.Seek(num + u8Node.OffsetToName, SeekOrigin.Begin); + object[] objArray4 = new object[1]; + position1 = u8File.Position; + objArray4[0] = position1.ToString("x8").ToUpper(); + FireDebug(" -> Reading Node Name... (Offset: 0x{0})", objArray4); + do + { + char ch = (char)u8File.ReadByte(); + if (ch != char.MinValue) + { + empty += ch.ToString(); + } + else + { + break; + } + } + while (empty.Length <= byte.MaxValue); + FireDebug(" -> {0}", (object)empty); + if (u8Node.Type == U8_NodeType.File) + { + u8File.Seek((long)headerType + u8Node.OffsetToData, SeekOrigin.Begin); + object[] objArray5 = new object[1]; + position1 = u8File.Position; + objArray5[0] = position1.ToString("x8").ToUpper(); + FireDebug(" -> Reading Node Data (Offset: 0x{0})", objArray5); + numArray = new byte[(int)u8Node.SizeOfData]; + u8File.Read(numArray, 0, numArray.Length); + } + if (empty.ToLower() == "icon.bin") + { + iconSize = GetRealSize(numArray); + } + else if (empty.ToLower() == "banner.bin") + { + bannerSize = GetRealSize(numArray); + } + else if (empty.ToLower() == "sound.bin") + { + soundSize = GetRealSize(numArray); + } + + u8Nodes.Add(u8Node); + stringTable.Add(empty); + data.Add(numArray); + } + FireDebug("Pasing U8 File Finished..."); + } + + private void CreateFromDir(string path) + { + FireDebug("Creating U8 File from: {0}", (object)path); + if (path[path.Length - 1] != Path.DirectorySeparatorChar) + { + path += Path.DirectorySeparatorChar.ToString(); + } + + FireDebug(" Collecting Content..."); + string[] dirContent = GetDirContent(path, true); + int num1 = 1; + int num2 = 0; + FireDebug(" Creating U8 Header..."); + u8Header = new U8_Header(); + rootNode = new U8_Node(); + u8Nodes = new List(); + stringTable = new List(); + data = new List(); + FireDebug(" Creating Rootnode..."); + rootNode.Type = U8_NodeType.Directory; + rootNode.OffsetToName = 0; + rootNode.OffsetToData = 0U; + rootNode.SizeOfData = (uint)(dirContent.Length + 1); + for (int index1 = 0; index1 < dirContent.Length; ++index1) + { + FireDebug(" Creating Node #{0} of {1}", index1 + 1, dirContent.Length); + FireProgress((index1 + 1) * 100 / dirContent.Length); + U8_Node u8Node = new U8_Node(); + byte[] data = new byte[0]; + string theString = dirContent[index1].Remove(0, path.Length - 1); + if (Directory.Exists(dirContent[index1])) + { + FireDebug(" -> Directory"); + u8Node.Type = U8_NodeType.Directory; + u8Node.OffsetToData = (uint)Shared.CountCharsInString(theString, Path.DirectorySeparatorChar); + int num3 = u8Nodes.Count + 2; + for (int index2 = 0; index2 < dirContent.Length; ++index2) + { + if (dirContent[index2].Contains(dirContent[index1] + "\\")) + { + ++num3; + } + } + u8Node.SizeOfData = (uint)num3; + } + else + { + FireDebug(" -> File"); + FireDebug(" -> Reading File Data..."); + data = File.ReadAllBytes(dirContent[index1]); + u8Node.Type = U8_NodeType.File; + u8Node.OffsetToData = (uint)num2; + u8Node.SizeOfData = (uint)data.Length; + num2 += Shared.AddPadding(num2 + data.Length, 32); + } + u8Node.OffsetToName = (ushort)num1; + num1 += Path.GetFileName(dirContent[index1]).Length + 1; + FireDebug(" -> Reading Name..."); + string fileName = Path.GetFileName(dirContent[index1]); + if (fileName.ToLower() == "icon.bin") + { + iconSize = GetRealSize(data); + } + else if (fileName.ToLower() == "banner.bin") + { + bannerSize = GetRealSize(data); + } + else if (fileName.ToLower() == "sound.bin") + { + soundSize = GetRealSize(data); + } + + u8Nodes.Add(u8Node); + stringTable.Add(fileName); + this.data.Add(data); + } + FireDebug(" Updating U8 Header..."); + u8Header.HeaderSize = (uint)((u8Nodes.Count + 1) * 12 + num1); + u8Header.OffsetToData = (uint)Shared.AddPadding((int)u8Header.OffsetToRootNode + (int)u8Header.HeaderSize, 32); + FireDebug(" Calculating Data Offsets..."); + for (int index = 0; index < u8Nodes.Count; ++index) + { + FireDebug(" -> Node #{0} of {1}...", index + 1, u8Nodes.Count); + int offsetToData = (int)u8Nodes[index].OffsetToData; + u8Nodes[index].OffsetToData = (uint)(u8Header.OffsetToData + (ulong)offsetToData); + } + FireDebug("Creating U8 File Finished..."); + } + + private string[] GetDirContent(string dir, bool root) + { + string[] files = Directory.GetFiles(dir); + string[] directories = Directory.GetDirectories(dir); + string str1 = ""; + if (!root) + { + str1 = str1 + dir + "\n"; + } + + for (int index = 0; index < files.Length; ++index) + { + str1 = str1 + files[index] + "\n"; + } + + foreach (string dir1 in directories) + { + foreach (string str2 in GetDirContent(dir1, false)) + { + str1 = str1 + str2 + "\n"; + } + } + return str1.Split(new char[1] { '\n' }, StringSplitOptions.RemoveEmptyEntries); + } + + private int GetRealSize(byte[] data) + { + if (data[0] != 73 || data[1] != 77 || (data[2] != 68 || data[3] != 53)) + { + return data.Length; + } + + return data[32] == 76 && data[33] == 90 && (data[34] == 55 && data[35] == 55) ? BitConverter.ToInt32(data, 36) >> 8 : data.Length - 32; + } + + private void AddEntry(string nodePath, byte[] fileData) + { + if (nodePath.StartsWith("/")) + { + nodePath = nodePath.Remove(0, 1); + } + + string[] strArray = nodePath.Split('/'); + int index1 = -1; + int num1 = u8Nodes.Count > 0 ? u8Nodes.Count - 1 : 0; + int num2 = 0; + List intList = new List(); + for (int index2 = 0; index2 < strArray.Length - 1; ++index2) + { + for (int index3 = num2; index3 <= num1; ++index3) + { + if (!(stringTable[index3].ToLower() == strArray[index2].ToLower())) + { + if (index3 == num1 - 1) + { + throw new Exception("Path wasn't found!"); + } + } + else + { + if (index2 == strArray.Length - 2) + { + index1 = index3; + } + + num1 = (int)u8Nodes[index3].SizeOfData - 1; + num2 = index3 + 1; + intList.Add(index3); + break; + } + } + } + int num3 = index1 > -1 ? (int)u8Nodes[index1].SizeOfData - 2 : (rootNode.SizeOfData > 1U ? (int)rootNode.SizeOfData - 2 : -1); + U8_Node u8Node = new U8_Node + { + Type = fileData.Length == 0 ? U8_NodeType.Directory : U8_NodeType.File, + SizeOfData = fileData.Length == 0 ? (uint)(num3 + 2) : (uint)fileData.Length, + OffsetToData = fileData.Length == 0 ? (uint)Shared.CountCharsInString(nodePath, '/') : 0U + }; + stringTable.Insert(num3 + 1, strArray[strArray.Length - 1]); + u8Nodes.Insert(num3 + 1, u8Node); + data.Insert(num3 + 1, fileData); + ++rootNode.SizeOfData; + foreach (int index2 in intList) + { + if (u8Nodes[index2].Type == U8_NodeType.Directory) + { + ++u8Nodes[index2].SizeOfData; + } + } + for (int index2 = num3 + 1; index2 < u8Nodes.Count; ++index2) + { + if (u8Nodes[index2].Type == U8_NodeType.Directory) + { + ++u8Nodes[index2].SizeOfData; + } + } + } + + private void RemoveEntry(string nodePath) + { + if (nodePath.StartsWith("/")) + { + nodePath = nodePath.Remove(0, 1); + } + + string[] strArray = nodePath.Split('/'); + int index1 = -1; + int num1 = u8Nodes.Count - 1; + int num2 = 0; + List intList = new List(); + for (int index2 = 0; index2 < strArray.Length; ++index2) + { + for (int index3 = num2; index3 < num1; ++index3) + { + if (!(stringTable[index3].ToLower() == strArray[index2].ToLower())) + { + if (index3 == num1 - 1) + { + throw new Exception("Path wasn't found!"); + } + } + else + { + if (index2 == strArray.Length - 1) + { + index1 = index3; + } + else + { + intList.Add(index3); + } + + num1 = (int)u8Nodes[index3].SizeOfData - 1; + num2 = index3 + 1; + break; + } + } + } + int num3 = 0; + if (u8Nodes[index1].Type == U8_NodeType.Directory) + { + for (int index2 = (int)u8Nodes[index1].SizeOfData - 2; index2 >= index1; --index2) + { + stringTable.RemoveAt(index2); + u8Nodes.RemoveAt(index2); + data.RemoveAt(index2); + ++num3; + } + } + else + { + stringTable.RemoveAt(index1); + u8Nodes.RemoveAt(index1); + data.RemoveAt(index1); + ++num3; + } + rootNode.SizeOfData -= (uint)num3; + foreach (int index2 in intList) + { + if (u8Nodes[index2].Type == U8_NodeType.Directory) + { + u8Nodes[index2].SizeOfData -= (uint)num3; + } + } + for (int index2 = index1 + 1; index2 < u8Nodes.Count; ++index2) + { + if (u8Nodes[index2].Type == U8_NodeType.Directory) + { + u8Nodes[index2].SizeOfData -= (uint)num3; + } + } + } + + private void FireWarning(string warningMessage) + { + EventHandler warning = Warning; + if (warning == null) + { + return; + } + + warning(new object(), new MessageEventArgs(warningMessage)); + } + + private void FireDebug(string debugMessage, params object[] args) + { + EventHandler debug = Debug; + if (debug == null) + { + return; + } + + debug(new object(), new MessageEventArgs(string.Format(debugMessage, args))); + } + + private void FireProgress(int progressPercentage) + { + EventHandler progress = Progress; + if (progress == null) + { + return; + } + + progress(new object(), new ProgressChangedEventArgs(progressPercentage, string.Empty)); + } } - } } diff --git a/U8_Header.cs b/U8_Header.cs index 5c484c7..549074f 100644 --- a/U8_Header.cs +++ b/U8_Header.cs @@ -9,39 +9,39 @@ using System.IO; namespace libWiiSharp { - public class U8_Header - { - private uint u8Magic = 1437218861; - private uint offsetToRootNode = 32; - private uint headerSize; - private uint offsetToData; - private byte[] padding = new byte[16]; - - public uint U8Magic => this.u8Magic; - - public uint OffsetToRootNode => this.offsetToRootNode; - - public uint HeaderSize + public class U8_Header { - get => this.headerSize; - set => this.headerSize = value; - } + private readonly uint u8Magic = 1437218861; + private readonly uint offsetToRootNode = 32; + private uint headerSize; + private uint offsetToData; + private readonly byte[] padding = new byte[16]; - public uint OffsetToData - { - get => this.offsetToData; - set => this.offsetToData = value; - } + public uint U8Magic => u8Magic; - public byte[] Padding => this.padding; + public uint OffsetToRootNode => offsetToRootNode; - public void Write(Stream writeStream) - { - writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.u8Magic)), 0, 4); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.offsetToRootNode)), 0, 4); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.headerSize)), 0, 4); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.offsetToData)), 0, 4); - writeStream.Write(this.padding, 0, 16); + public uint HeaderSize + { + get => headerSize; + set => headerSize = value; + } + + public uint OffsetToData + { + get => offsetToData; + set => offsetToData = value; + } + + public byte[] Padding => padding; + + public void Write(Stream writeStream) + { + writeStream.Write(BitConverter.GetBytes(Shared.Swap(u8Magic)), 0, 4); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(offsetToRootNode)), 0, 4); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(headerSize)), 0, 4); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(offsetToData)), 0, 4); + writeStream.Write(padding, 0, 16); + } } - } } diff --git a/U8_Node.cs b/U8_Node.cs index 618542c..4b1277b 100644 --- a/U8_Node.cs +++ b/U8_Node.cs @@ -9,43 +9,43 @@ using System.IO; namespace libWiiSharp { - public class U8_Node - { - private ushort type; - private ushort offsetToName; - private uint offsetToData; - private uint sizeOfData; - - public U8_NodeType Type + public class U8_Node { - get => (U8_NodeType) this.type; - set => this.type = (ushort) value; - } + private ushort type; + private ushort offsetToName; + private uint offsetToData; + private uint sizeOfData; - public ushort OffsetToName - { - get => this.offsetToName; - set => this.offsetToName = value; - } + public U8_NodeType Type + { + get => (U8_NodeType)type; + set => type = (ushort)value; + } - public uint OffsetToData - { - get => this.offsetToData; - set => this.offsetToData = value; - } + public ushort OffsetToName + { + get => offsetToName; + set => offsetToName = value; + } - public uint SizeOfData - { - get => this.sizeOfData; - set => this.sizeOfData = value; - } + public uint OffsetToData + { + get => offsetToData; + set => offsetToData = value; + } - public void Write(Stream writeStream) - { - writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.type)), 0, 2); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.offsetToName)), 0, 2); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.offsetToData)), 0, 4); - writeStream.Write(BitConverter.GetBytes(Shared.Swap(this.sizeOfData)), 0, 4); + public uint SizeOfData + { + get => sizeOfData; + set => sizeOfData = value; + } + + public void Write(Stream writeStream) + { + writeStream.Write(BitConverter.GetBytes(Shared.Swap(type)), 0, 2); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(offsetToName)), 0, 2); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(offsetToData)), 0, 4); + writeStream.Write(BitConverter.GetBytes(Shared.Swap(sizeOfData)), 0, 4); + } } - } } diff --git a/U8_NodeType.cs b/U8_NodeType.cs index 131ca4d..7739f46 100644 --- a/U8_NodeType.cs +++ b/U8_NodeType.cs @@ -6,9 +6,9 @@ namespace libWiiSharp { - public enum U8_NodeType : ushort - { - File = 0, - Directory = 256, // 0x0100 - } + public enum U8_NodeType : ushort + { + File = 0, + Directory = 256, // 0x0100 + } } diff --git a/WAD.cs b/WAD.cs index 46cb065..ef75955 100644 --- a/WAD.cs +++ b/WAD.cs @@ -23,1011 +23,1129 @@ namespace libWiiSharp HiddenChannels = 0x00010008, } public class WAD : IDisposable - { - private SHA1 sha = SHA1.Create(); - private DateTime creationTimeUTC = new DateTime(1970, 1, 1); - private bool hasBanner; - private bool lz77CompressBannerAndIcon = true; - private bool lz77DecompressBannerAndIcon; - private bool keepOriginalFooter; - private WAD_Header wadHeader; - private CertificateChain cert = new CertificateChain(); - private Ticket tik = new Ticket(); - private TMD tmd = new TMD(); - private List contents; - private U8 bannerApp = new U8(); - private byte[] footer = new byte[0]; - private bool isDisposed; - - public Region Region { - get => this.tmd.Region; - set => this.tmd.Region = value; - } + private SHA1 sha = SHA1.Create(); + private DateTime creationTimeUTC = new DateTime(1970, 1, 1); + private bool hasBanner; + private bool lz77CompressBannerAndIcon = true; + private bool lz77DecompressBannerAndIcon; + private bool keepOriginalFooter; + private WAD_Header wadHeader; + private CertificateChain cert = new CertificateChain(); + private Ticket tik = new Ticket(); + private TMD tmd = new TMD(); + private List contents; + private U8 bannerApp = new U8(); + private byte[] footer = new byte[0]; + private bool isDisposed; - public int NumOfContents => (int) this.tmd.NumOfContents; - - public byte[][] Contents => this.contents.ToArray(); - - public bool FakeSign - { - get => this.tik.FakeSign && this.tmd.FakeSign; - set - { - this.tik.FakeSign = value; - this.tmd.FakeSign = value; - } - } - - public U8 BannerApp - { - get => this.bannerApp; - set => this.bannerApp = value; - } - - public ulong StartupIOS - { - get => this.tmd.StartupIOS; - set => this.tmd.StartupIOS = value; - } - - public ulong TitleID - { - get => this.tik.TitleID; - set - { - this.tik.TitleID = value; - this.tmd.TitleID = value; - } - } - - public string UpperTitleID => this.tik.GetUpperTitleID(); - - public ushort TitleVersion - { - get => this.tmd.TitleVersion; - set => this.tmd.TitleVersion = value; - } - - public ushort BootIndex - { - get => this.tmd.BootIndex; - set => this.tmd.BootIndex = value; - } - - public DateTime CreationTimeUTC => this.creationTimeUTC; - - public bool HasBanner => this.hasBanner; - - public bool Lz77CompressBannerAndIcon - { - get => this.lz77CompressBannerAndIcon; - set - { - this.lz77CompressBannerAndIcon = value; - if (!value) - return; - this.lz77DecompressBannerAndIcon = false; - } - } - - public bool Lz77DecompressBannerAndIcon - { - get => this.lz77DecompressBannerAndIcon; - set - { - this.lz77DecompressBannerAndIcon = value; - if (!value) - return; - this.lz77CompressBannerAndIcon = false; - } - } - - public string NandBlocks => this.tmd.GetNandBlocks(); - - public string[] ChannelTitles - { - get => this.hasBanner ? ((Headers.IMET) this.bannerApp.Header).AllTitles : new string[0]; - set => this.ChangeChannelTitles(value); - } - - public bool KeepOriginalFooter - { - get => this.keepOriginalFooter; - set => this.keepOriginalFooter = value; - } - - public TMD_Content[] TmdContents => this.tmd.Contents; - - public CommonKeyType CommonKeyType - { - get => this.tik.CommonKeyIndex; - set => this.tik.CommonKeyIndex = value; - } - - public bool SortContents - { - get => this.tmd.SortContents; - set => this.tmd.SortContents = value; - } - - public event EventHandler Progress; - - public event EventHandler Warning; - - public event EventHandler Debug; - - public WAD() - { - this.cert.Debug += new EventHandler(this.cert_Debug); - this.tik.Debug += new EventHandler(this.tik_Debug); - this.tmd.Debug += new EventHandler(this.tmd_Debug); - this.bannerApp.Debug += new EventHandler(this.bannerApp_Debug); - this.bannerApp.Warning += new EventHandler(this.bannerApp_Warning); - } - - ~WAD() => this.Dispose(false); - - public void Dispose() - { - this.Dispose(true); - GC.SuppressFinalize((object) this); - } - - protected virtual void Dispose(bool disposing) - { - if (disposing && !this.isDisposed) - { - this.sha.Clear(); - this.sha = (SHA1) null; - this.wadHeader = (WAD_Header) null; - this.cert.Dispose(); - this.tik.Dispose(); - this.tmd.Dispose(); - this.contents.Clear(); - this.contents = (List) null; - this.bannerApp.Dispose(); - this.footer = (byte[]) null; - } - this.isDisposed = true; - } - - public static WAD Load(string pathToWad) => WAD.Load(File.ReadAllBytes(pathToWad)); - - public static WAD Load(byte[] wadFile) - { - WAD wad = new WAD(); - MemoryStream memoryStream = new MemoryStream(wadFile); - try - { - wad.parseWad((Stream) memoryStream); - } - catch - { - memoryStream.Dispose(); - throw; - } - memoryStream.Dispose(); - return wad; - } - - public static WAD Load(Stream wad) - { - WAD wad1 = new WAD(); - wad1.parseWad(wad); - return wad1; - } - - public static WAD Create(string contentDir) - { - string[] files1 = Directory.GetFiles(contentDir, "*cert*"); - string[] files2 = Directory.GetFiles(contentDir, "*tik*"); - string[] files3 = Directory.GetFiles(contentDir, "*tmd*"); - CertificateChain cert = CertificateChain.Load(files1[0]); - Ticket tik = Ticket.Load(files2[0]); - TMD tmd = TMD.Load(files3[0]); - bool flag = true; - for (int index = 0; index < tmd.Contents.Length; ++index) - { - if (!File.Exists(contentDir + Path.DirectorySeparatorChar.ToString() + tmd.Contents[index].ContentID.ToString("x8") + ".app")) + public Region Region { - flag = false; - break; + get => tmd.Region; + set => tmd.Region = value; } - } - if (!flag) - { - for (int index = 0; index < tmd.Contents.Length; ++index) - { - if (!File.Exists(contentDir + Path.DirectorySeparatorChar.ToString() + tmd.Contents[index].Index.ToString("x8") + ".app")) - throw new Exception("Couldn't find all content files!"); - } - } - byte[][] contents = new byte[tmd.Contents.Length][]; - for (int index = 0; index < tmd.Contents.Length; ++index) - { - string path = contentDir + Path.DirectorySeparatorChar.ToString() + (flag ? tmd.Contents[index].ContentID.ToString("x8") : tmd.Contents[index].Index.ToString("x8")) + ".app"; - contents[index] = File.ReadAllBytes(path); - } - return WAD.Create(cert, tik, tmd, contents); - } - public static WAD Create( - string pathToCert, - string pathToTik, - string pathToTmd, - string contentDir) - { - CertificateChain cert = CertificateChain.Load(pathToCert); - Ticket tik = Ticket.Load(pathToTik); - TMD tmd = TMD.Load(pathToTmd); - bool flag = true; - for (int index = 0; index < tmd.Contents.Length; ++index) - { - if (!File.Exists(contentDir + Path.DirectorySeparatorChar.ToString() + tmd.Contents[index].ContentID.ToString("x8") + ".app")) - { - flag = false; - break; - } - } - if (!flag) - { - for (int index = 0; index < tmd.Contents.Length; ++index) - { - if (!File.Exists(contentDir + Path.DirectorySeparatorChar.ToString() + tmd.Contents[index].Index.ToString("x8") + ".app")) - throw new Exception("Couldn't find all content files!"); - } - } - byte[][] contents = new byte[tmd.Contents.Length][]; - for (int index = 0; index < tmd.Contents.Length; ++index) - { - string path = contentDir + Path.DirectorySeparatorChar.ToString() + (flag ? tmd.Contents[index].ContentID.ToString("x8") : tmd.Contents[index].Index.ToString("x8")) + ".app"; - contents[index] = File.ReadAllBytes(path); - } - return WAD.Create(cert, tik, tmd, contents); - } + public int NumOfContents => tmd.NumOfContents; - public static WAD Create(byte[] cert, byte[] tik, byte[] tmd, byte[][] contents) - { - CertificateChain cert1 = CertificateChain.Load(cert); - Ticket ticket = Ticket.Load(tik); - TMD tmd1 = TMD.Load(tmd); - Ticket tik1 = ticket; - TMD tmd2 = tmd1; - byte[][] contents1 = contents; - return WAD.Create(cert1, tik1, tmd2, contents1); - } + public byte[][] Contents => contents.ToArray(); - public static WAD Create(CertificateChain cert, Ticket tik, TMD tmd, byte[][] contents) - { - WAD wad = new WAD() - { - cert = cert, - tik = tik, - tmd = tmd, - contents = new List((IEnumerable) contents), - wadHeader = new WAD_Header() - }; - wad.wadHeader.TmdSize = (uint) (484 + tmd.Contents.Length * 36); - int num1 = 0; - for (int index = 0; index < contents.Length - 1; ++index) - num1 += Shared.AddPadding(contents[index].Length); - int num2 = num1 + contents[contents.Length - 1].Length; - wad.wadHeader.ContentSize = (uint) num2; - for (int index = 0; index < wad.tmd.Contents.Length; ++index) - { - if (wad.tmd.Contents[index].Index == (ushort) 0) + public bool FakeSign { - try - { - wad.bannerApp.LoadFile(contents[index]); - wad.hasBanner = true; + get => tik.FakeSign && tmd.FakeSign; + set + { + tik.FakeSign = value; + tmd.FakeSign = value; + } + } + + public U8 BannerApp + { + get => bannerApp; + set => bannerApp = value; + } + + public ulong StartupIOS + { + get => tmd.StartupIOS; + set => tmd.StartupIOS = value; + } + + public ulong TitleID + { + get => tik.TitleID; + set + { + tik.TitleID = value; + tmd.TitleID = value; + } + } + + public string UpperTitleID => tik.GetUpperTitleID(); + + public ushort TitleVersion + { + get => tmd.TitleVersion; + set => tmd.TitleVersion = value; + } + + public ushort BootIndex + { + get => tmd.BootIndex; + set => tmd.BootIndex = value; + } + + public DateTime CreationTimeUTC => creationTimeUTC; + + public bool HasBanner => hasBanner; + + public bool Lz77CompressBannerAndIcon + { + get => lz77CompressBannerAndIcon; + set + { + lz77CompressBannerAndIcon = value; + if (!value) + { + return; + } + + lz77DecompressBannerAndIcon = false; + } + } + + public bool Lz77DecompressBannerAndIcon + { + get => lz77DecompressBannerAndIcon; + set + { + lz77DecompressBannerAndIcon = value; + if (!value) + { + return; + } + + lz77CompressBannerAndIcon = false; + } + } + + public string NandBlocks => tmd.GetNandBlocks(); + + public string[] ChannelTitles + { + get => hasBanner ? ((Headers.IMET)bannerApp.Header).AllTitles : new string[0]; + set => ChangeChannelTitles(value); + } + + public bool KeepOriginalFooter + { + get => keepOriginalFooter; + set => keepOriginalFooter = value; + } + + public TMD_Content[] TmdContents => tmd.Contents; + + public CommonKeyType CommonKeyType + { + get => tik.CommonKeyIndex; + set => tik.CommonKeyIndex = value; + } + + public bool SortContents + { + get => tmd.SortContents; + set => tmd.SortContents = value; + } + + public event EventHandler Progress; + + public event EventHandler Warning; + + public event EventHandler Debug; + + public WAD() + { + cert.Debug += new EventHandler(Cert_Debug); + tik.Debug += new EventHandler(Tik_Debug); + tmd.Debug += new EventHandler(Tmd_Debug); + bannerApp.Debug += new EventHandler(BannerApp_Debug); + bannerApp.Warning += new EventHandler(BannerApp_Warning); + } + + ~WAD() => Dispose(false); + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (disposing && !isDisposed) + { + sha.Clear(); + sha = null; + wadHeader = null; + cert.Dispose(); + tik.Dispose(); + tmd.Dispose(); + contents.Clear(); + contents = null; + bannerApp.Dispose(); + footer = null; + } + isDisposed = true; + } + + public static WAD Load(string pathToWad) + { + return WAD.Load(File.ReadAllBytes(pathToWad)); + } + + public static WAD Load(byte[] wadFile) + { + WAD wad = new WAD(); + MemoryStream memoryStream = new MemoryStream(wadFile); + try + { + wad.ParseWad(memoryStream); + } + catch + { + memoryStream.Dispose(); + throw; + } + memoryStream.Dispose(); return wad; - } - catch - { - wad.hasBanner = false; + } + + public static WAD Load(Stream wad) + { + WAD wad1 = new WAD(); + wad1.ParseWad(wad); + return wad1; + } + + public static WAD Create(string contentDir) + { + string[] files1 = Directory.GetFiles(contentDir, "*cert*"); + string[] files2 = Directory.GetFiles(contentDir, "*tik*"); + string[] files3 = Directory.GetFiles(contentDir, "*tmd*"); + CertificateChain cert = CertificateChain.Load(files1[0]); + Ticket tik = Ticket.Load(files2[0]); + TMD tmd = TMD.Load(files3[0]); + bool flag = true; + for (int index = 0; index < tmd.Contents.Length; ++index) + { + if (!File.Exists(contentDir + Path.DirectorySeparatorChar.ToString() + tmd.Contents[index].ContentID.ToString("x8") + ".app")) + { + flag = false; + break; + } + } + if (!flag) + { + for (int index = 0; index < tmd.Contents.Length; ++index) + { + if (!File.Exists(contentDir + Path.DirectorySeparatorChar.ToString() + tmd.Contents[index].Index.ToString("x8") + ".app")) + { + throw new Exception("Couldn't find all content files!"); + } + } + } + byte[][] contents = new byte[tmd.Contents.Length][]; + for (int index = 0; index < tmd.Contents.Length; ++index) + { + string path = contentDir + Path.DirectorySeparatorChar.ToString() + (flag ? tmd.Contents[index].ContentID.ToString("x8") : tmd.Contents[index].Index.ToString("x8")) + ".app"; + contents[index] = File.ReadAllBytes(path); + } + return WAD.Create(cert, tik, tmd, contents); + } + + public static WAD Create( + string pathToCert, + string pathToTik, + string pathToTmd, + string contentDir) + { + CertificateChain cert = CertificateChain.Load(pathToCert); + Ticket tik = Ticket.Load(pathToTik); + TMD tmd = TMD.Load(pathToTmd); + bool flag = true; + for (int index = 0; index < tmd.Contents.Length; ++index) + { + if (!File.Exists(contentDir + Path.DirectorySeparatorChar.ToString() + tmd.Contents[index].ContentID.ToString("x8") + ".app")) + { + flag = false; + break; + } + } + if (!flag) + { + for (int index = 0; index < tmd.Contents.Length; ++index) + { + if (!File.Exists(contentDir + Path.DirectorySeparatorChar.ToString() + tmd.Contents[index].Index.ToString("x8") + ".app")) + { + throw new Exception("Couldn't find all content files!"); + } + } + } + byte[][] contents = new byte[tmd.Contents.Length][]; + for (int index = 0; index < tmd.Contents.Length; ++index) + { + string path = contentDir + Path.DirectorySeparatorChar.ToString() + (flag ? tmd.Contents[index].ContentID.ToString("x8") : tmd.Contents[index].Index.ToString("x8")) + ".app"; + contents[index] = File.ReadAllBytes(path); + } + return WAD.Create(cert, tik, tmd, contents); + } + + public static WAD Create(byte[] cert, byte[] tik, byte[] tmd, byte[][] contents) + { + CertificateChain cert1 = CertificateChain.Load(cert); + Ticket ticket = Ticket.Load(tik); + TMD tmd1 = TMD.Load(tmd); + Ticket tik1 = ticket; + TMD tmd2 = tmd1; + byte[][] contents1 = contents; + return WAD.Create(cert1, tik1, tmd2, contents1); + } + + public static WAD Create(CertificateChain cert, Ticket tik, TMD tmd, byte[][] contents) + { + WAD wad = new WAD() + { + cert = cert, + tik = tik, + tmd = tmd, + contents = new List(contents), + wadHeader = new WAD_Header() + }; + wad.wadHeader.TmdSize = (uint)(484 + tmd.Contents.Length * 36); + int num1 = 0; + for (int index = 0; index < contents.Length - 1; ++index) + { + num1 += Shared.AddPadding(contents[index].Length); + } + + int num2 = num1 + contents[contents.Length - 1].Length; + wad.wadHeader.ContentSize = (uint)num2; + for (int index = 0; index < wad.tmd.Contents.Length; ++index) + { + if (wad.tmd.Contents[index].Index == 0) + { + try + { + wad.bannerApp.LoadFile(contents[index]); + wad.hasBanner = true; + return wad; + } + catch + { + wad.hasBanner = false; + return wad; + } + } + } return wad; - } } - } - return wad; - } - public void LoadFile(string pathToWad) => this.LoadFile(File.ReadAllBytes(pathToWad)); - - public void LoadFile(byte[] wadFile) - { - MemoryStream memoryStream = new MemoryStream(wadFile); - try - { - this.parseWad((Stream) memoryStream); - } - catch - { - memoryStream.Dispose(); - throw; - } - memoryStream.Dispose(); - } - - public void LoadFile(Stream wad) => this.parseWad(wad); - - public void CreateNew(string contentDir) - { - string[] files1 = Directory.GetFiles(contentDir, "*cert*"); - string[] files2 = Directory.GetFiles(contentDir, "*tik*"); - string[] files3 = Directory.GetFiles(contentDir, "*tmd*"); - CertificateChain cert = CertificateChain.Load(files1[0]); - Ticket tik = Ticket.Load(files2[0]); - TMD tmd = TMD.Load(files3[0]); - bool flag = true; - for (int index = 0; index < tmd.Contents.Length; ++index) - { - if (!File.Exists(contentDir + Path.DirectorySeparatorChar.ToString() + tmd.Contents[index].ContentID.ToString("x8") + ".app")) + public void LoadFile(string pathToWad) { - flag = false; - break; + LoadFile(File.ReadAllBytes(pathToWad)); } - } - if (!flag) - { - for (int index = 0; index < tmd.Contents.Length; ++index) + + public void LoadFile(byte[] wadFile) { - if (!File.Exists(contentDir + Path.DirectorySeparatorChar.ToString() + tmd.Contents[index].Index.ToString("x8") + ".app")) - throw new Exception("Couldn't find all content files!"); + MemoryStream memoryStream = new MemoryStream(wadFile); + try + { + ParseWad(memoryStream); + } + catch + { + memoryStream.Dispose(); + throw; + } + memoryStream.Dispose(); } - } - byte[][] contents = new byte[tmd.Contents.Length][]; - for (int index = 0; index < tmd.Contents.Length; ++index) - { - string path = contentDir + Path.DirectorySeparatorChar.ToString() + (flag ? tmd.Contents[index].ContentID.ToString("x8") : tmd.Contents[index].Index.ToString("x8")) + ".app"; - contents[index] = File.ReadAllBytes(path); - } - this.CreateNew(cert, tik, tmd, contents); - } - public void CreateNew( - string pathToCert, - string pathToTik, - string pathToTmd, - string contentDir) - { - CertificateChain cert = CertificateChain.Load(pathToCert); - Ticket tik = Ticket.Load(pathToTik); - TMD tmd = TMD.Load(pathToTmd); - bool flag = true; - for (int index = 0; index < tmd.Contents.Length; ++index) - { - if (!File.Exists(contentDir + Path.DirectorySeparatorChar.ToString() + tmd.Contents[index].ContentID.ToString("x8") + ".app")) + public void LoadFile(Stream wad) { - flag = false; - break; + ParseWad(wad); } - } - if (!flag) - { - for (int index = 0; index < tmd.Contents.Length; ++index) + + public void CreateNew(string contentDir) { - if (!File.Exists(contentDir + Path.DirectorySeparatorChar.ToString() + tmd.Contents[index].Index.ToString("x8") + ".app")) - throw new Exception("Couldn't find all content files!"); + string[] files1 = Directory.GetFiles(contentDir, "*cert*"); + string[] files2 = Directory.GetFiles(contentDir, "*tik*"); + string[] files3 = Directory.GetFiles(contentDir, "*tmd*"); + CertificateChain cert = CertificateChain.Load(files1[0]); + Ticket tik = Ticket.Load(files2[0]); + TMD tmd = TMD.Load(files3[0]); + bool flag = true; + for (int index = 0; index < tmd.Contents.Length; ++index) + { + if (!File.Exists(contentDir + Path.DirectorySeparatorChar.ToString() + tmd.Contents[index].ContentID.ToString("x8") + ".app")) + { + flag = false; + break; + } + } + if (!flag) + { + for (int index = 0; index < tmd.Contents.Length; ++index) + { + if (!File.Exists(contentDir + Path.DirectorySeparatorChar.ToString() + tmd.Contents[index].Index.ToString("x8") + ".app")) + { + throw new Exception("Couldn't find all content files!"); + } + } + } + byte[][] contents = new byte[tmd.Contents.Length][]; + for (int index = 0; index < tmd.Contents.Length; ++index) + { + string path = contentDir + Path.DirectorySeparatorChar.ToString() + (flag ? tmd.Contents[index].ContentID.ToString("x8") : tmd.Contents[index].Index.ToString("x8")) + ".app"; + contents[index] = File.ReadAllBytes(path); + } + CreateNew(cert, tik, tmd, contents); } - } - byte[][] contents = new byte[tmd.Contents.Length][]; - for (int index = 0; index < tmd.Contents.Length; ++index) - { - string path = contentDir + Path.DirectorySeparatorChar.ToString() + (flag ? tmd.Contents[index].ContentID.ToString("x8") : tmd.Contents[index].Index.ToString("x8")) + ".app"; - contents[index] = File.ReadAllBytes(path); - } - this.CreateNew(cert, tik, tmd, contents); - } - public void CreateNew(byte[] cert, byte[] tik, byte[] tmd, byte[][] contents) => this.CreateNew(CertificateChain.Load(cert), Ticket.Load(tik), TMD.Load(tmd), contents); - - public void CreateNew(CertificateChain cert, Ticket tik, TMD tmd, byte[][] contents) - { - this.cert = cert; - this.tik = tik; - this.tmd = tmd; - this.contents = new List((IEnumerable) contents); - this.wadHeader = new WAD_Header(); - this.wadHeader.TmdSize = (uint) (484 + tmd.Contents.Length * 36); - int num = 0; - for (int index = 0; index < contents.Length - 1; ++index) - num += Shared.AddPadding(contents[index].Length); - this.wadHeader.ContentSize = (uint) (num + contents[contents.Length - 1].Length); - for (int index = 0; index < this.tmd.Contents.Length; ++index) - { - if (this.tmd.Contents[index].Index == (ushort) 0) + public void CreateNew( + string pathToCert, + string pathToTik, + string pathToTmd, + string contentDir) { - try - { - this.bannerApp.LoadFile(contents[index]); - this.hasBanner = true; - break; - } - catch - { - this.hasBanner = false; - break; - } + CertificateChain cert = CertificateChain.Load(pathToCert); + Ticket tik = Ticket.Load(pathToTik); + TMD tmd = TMD.Load(pathToTmd); + bool flag = true; + for (int index = 0; index < tmd.Contents.Length; ++index) + { + if (!File.Exists(contentDir + Path.DirectorySeparatorChar.ToString() + tmd.Contents[index].ContentID.ToString("x8") + ".app")) + { + flag = false; + break; + } + } + if (!flag) + { + for (int index = 0; index < tmd.Contents.Length; ++index) + { + if (!File.Exists(contentDir + Path.DirectorySeparatorChar.ToString() + tmd.Contents[index].Index.ToString("x8") + ".app")) + { + throw new Exception("Couldn't find all content files!"); + } + } + } + byte[][] contents = new byte[tmd.Contents.Length][]; + for (int index = 0; index < tmd.Contents.Length; ++index) + { + string path = contentDir + Path.DirectorySeparatorChar.ToString() + (flag ? tmd.Contents[index].ContentID.ToString("x8") : tmd.Contents[index].Index.ToString("x8")) + ".app"; + contents[index] = File.ReadAllBytes(path); + } + CreateNew(cert, tik, tmd, contents); } - } - } - public void Save(string savePath) - { - if (File.Exists(savePath)) - File.Delete(savePath); - using (FileStream fileStream = new FileStream(savePath, FileMode.Create)) - this.writeToStream((Stream) fileStream); - } + public void CreateNew(byte[] cert, byte[] tik, byte[] tmd, byte[][] contents) + { + CreateNew(CertificateChain.Load(cert), Ticket.Load(tik), TMD.Load(tmd), contents); + } - public MemoryStream ToMemoryStream() - { - MemoryStream memoryStream = new MemoryStream(); - try - { - this.writeToStream((Stream) memoryStream); - return memoryStream; - } - catch - { - memoryStream.Dispose(); - throw; - } - } + public void CreateNew(CertificateChain cert, Ticket tik, TMD tmd, byte[][] contents) + { + this.cert = cert; + this.tik = tik; + this.tmd = tmd; + this.contents = new List(contents); + wadHeader = new WAD_Header + { + TmdSize = (uint)(484 + tmd.Contents.Length * 36) + }; + int num = 0; + for (int index = 0; index < contents.Length - 1; ++index) + { + num += Shared.AddPadding(contents[index].Length); + } - public byte[] ToByteArray() - { - MemoryStream memoryStream = new MemoryStream(); - try - { - this.writeToStream((Stream) memoryStream); - } - catch - { - memoryStream.Dispose(); - throw; - } - byte[] array = memoryStream.ToArray(); - memoryStream.Dispose(); - return array; - } + wadHeader.ContentSize = (uint)(num + contents[contents.Length - 1].Length); + for (int index = 0; index < this.tmd.Contents.Length; ++index) + { + if (this.tmd.Contents[index].Index == 0) + { + try + { + bannerApp.LoadFile(contents[index]); + hasBanner = true; + break; + } + catch + { + hasBanner = false; + break; + } + } + } + } - public void ChangeTitleID(LowerTitleID lowerID, string upperID) - { - uint num1 = upperID.Length == 4 ? BitConverter.ToUInt32(new byte[4] - { + public void Save(string savePath) + { + if (File.Exists(savePath)) + { + File.Delete(savePath); + } + + using FileStream fileStream = new FileStream(savePath, FileMode.Create); + WriteToStream(fileStream); + } + + public MemoryStream ToMemoryStream() + { + MemoryStream memoryStream = new MemoryStream(); + try + { + WriteToStream(memoryStream); + return memoryStream; + } + catch + { + memoryStream.Dispose(); + throw; + } + } + + public byte[] ToByteArray() + { + MemoryStream memoryStream = new MemoryStream(); + try + { + WriteToStream(memoryStream); + } + catch + { + memoryStream.Dispose(); + throw; + } + byte[] array = memoryStream.ToArray(); + memoryStream.Dispose(); + return array; + } + + public void ChangeTitleID(LowerTitleID lowerID, string upperID) + { + uint num1 = upperID.Length == 4 ? BitConverter.ToUInt32(new byte[4] + { (byte) upperID[3], (byte) upperID[2], (byte) upperID[1], (byte) upperID[0] - }, 0) : throw new Exception("Upper Title ID must be 4 characters long!"); - ulong num2 = (ulong) lowerID << 32 | (ulong) num1; - this.tik.TitleID = num2; - this.tmd.TitleID = num2; - } - - public void ChangeStartupIOS(int newIos) => this.StartupIOS = 4294967296UL | (ulong) (uint) newIos; - - public void ChangeTitleKey(string newTitleKey) => this.tik.SetTitleKey(newTitleKey); - - public void ChangeTitleKey(char[] newTitleKey) => this.tik.SetTitleKey(newTitleKey); - - public void ChangeTitleKey(byte[] newTitleKey) => this.tik.SetTitleKey(newTitleKey); - - public byte[] GetContentByIndex(int index) - { - for (int index1 = 0; index1 < (int) this.tmd.NumOfContents; ++index1) - { - if ((int) this.tmd.Contents[index1].Index == index) - return this.contents[index1]; - } - throw new Exception(string.Format("Content with index {0} not found!", (object) index)); - } - - public byte[] GetContentByID(int contentID) - { - for (int index = 0; index < (int) this.tmd.NumOfContents; ++index) - { - if ((int) this.tmd.Contents[index].Index == contentID) - return this.contents[index]; - } - throw new Exception(string.Format("Content with content ID {0} not found!", (object) contentID)); - } - - public void ChangeChannelTitles(params string[] newTitles) - { - if (!this.hasBanner) - return; - ((Headers.IMET) this.bannerApp.Header).ChangeTitles(newTitles); - } - - public void AddContent(byte[] newContent, int contentID, int index, ContentType type = ContentType.Normal) - { - this.tmd.AddContent(new TMD_Content() - { - ContentID = (uint) contentID, - Index = (ushort) index, - Type = type, - Size = (ulong) newContent.Length, - Hash = this.sha.ComputeHash(newContent) - }); - this.contents.Add(newContent); - this.wadHeader.TmdSize = (uint) (484 + (int) this.tmd.NumOfContents * 36); - } - - public void RemoveContent(int index) - { - for (int index1 = 0; index1 < this.tmd.Contents.Length; ++index1) - { - if ((int) this.tmd.Contents[index1].Index == index) - { - this.tmd.RemoveContent(index); - this.contents.RemoveAt(index1); - this.wadHeader.TmdSize = (uint) (484 + (int) this.tmd.NumOfContents * 36); - return; + }, 0) : throw new Exception("Upper Title ID must be 4 characters long!"); + ulong num2 = (ulong)lowerID << 32 | num1; + tik.TitleID = num2; + tmd.TitleID = num2; } - } - throw new Exception(string.Format("Content with index {0} not found!", (object) index)); - } - public void RemoveContentByID(int contentID) - { - for (int index = 0; index < this.tmd.Contents.Length; ++index) - { - if ((int) this.tmd.Contents[index].Index == contentID) + public void ChangeStartupIOS(int newIos) { - this.tmd.RemoveContentByID(contentID); - this.contents.RemoveAt(index); - this.wadHeader.TmdSize = (uint) (484 + (int) this.tmd.NumOfContents * 36); - return; + StartupIOS = 4294967296UL | (uint)newIos; } - } - throw new Exception(string.Format("Content with content ID {0} not found!", (object) contentID)); - } - public void RemoveAllContents() - { - if (!this.hasBanner) - { - this.tmd.Contents = new TMD_Content[0]; - this.contents = new List(); - this.wadHeader.TmdSize = (uint) (484 + (int) this.tmd.NumOfContents * 36); - } - else - { - for (int index = 0; index < (int) this.tmd.NumOfContents; ++index) + public void ChangeTitleKey(string newTitleKey) { - if (this.tmd.Contents[index].Index == (ushort) 0) - { - byte[] content1 = this.contents[index]; - TMD_Content content2 = this.tmd.Contents[index]; - this.tmd.Contents = new TMD_Content[0]; - this.contents = new List(); - this.tmd.AddContent(content2); - this.contents.Add(content1); - this.wadHeader.TmdSize = (uint) (484 + (int) this.tmd.NumOfContents * 36); - break; - } + tik.SetTitleKey(newTitleKey); } - } - } - public void Unpack(string unpackDir, bool nameContentID = false) => this.unpackAll(unpackDir, nameContentID); - - public void RemoveFooter() - { - this.footer = new byte[0]; - this.wadHeader.FooterSize = 0U; - this.keepOriginalFooter = true; - } - - public void AddFooter(byte[] footer) => this.ChangeFooter(footer); - - public void ChangeFooter(byte[] newFooter) - { - if (newFooter.Length % 64 != 0) - Array.Resize(ref newFooter, Shared.AddPadding(newFooter.Length)); - this.footer = newFooter; - this.wadHeader.FooterSize = (uint) newFooter.Length; - this.keepOriginalFooter = true; - } - - private void writeToStream(Stream writeStream) - { - this.fireDebug("Writing Wad..."); - if (!this.keepOriginalFooter) - { - this.fireDebug(" Building Footer Timestamp..."); - this.createFooterTimestamp(); - } - if (this.hasBanner) - { - if (this.lz77CompressBannerAndIcon || this.lz77DecompressBannerAndIcon) + public void ChangeTitleKey(char[] newTitleKey) { - for (int index = 0; index < this.bannerApp.Nodes.Count; ++index) - { - if (this.bannerApp.StringTable[index].ToLower() == "icon.bin" || this.bannerApp.StringTable[index].ToLower() == "banner.bin") + tik.SetTitleKey(newTitleKey); + } + + public void ChangeTitleKey(byte[] newTitleKey) + { + tik.SetTitleKey(newTitleKey); + } + + public byte[] GetContentByIndex(int index) + { + for (int index1 = 0; index1 < tmd.NumOfContents; ++index1) { - if (!Lz77.IsLz77Compressed(this.bannerApp.Data[index]) && this.lz77CompressBannerAndIcon) - { - this.fireDebug(" Compressing {0}...", (object) this.bannerApp.StringTable[index]); - byte[] file = new byte[this.bannerApp.Data[index].Length - 32]; - Array.Copy((Array) this.bannerApp.Data[index], 32, (Array) file, 0, file.Length); - byte[] numArray = Headers.IMD5.AddHeader(new Lz77().Compress(file)); - this.bannerApp.Data[index] = numArray; - this.bannerApp.Nodes[index].SizeOfData = (uint) numArray.Length; - } - else if (Lz77.IsLz77Compressed(this.bannerApp.Data[index]) && this.lz77DecompressBannerAndIcon) - { - this.fireDebug(" Decompressing {0}...", (object) this.bannerApp.StringTable[index]); - byte[] file = new byte[this.bannerApp.Data[index].Length - 32]; - Array.Copy((Array) this.bannerApp.Data[index], 32, (Array) file, 0, file.Length); - byte[] numArray = Headers.IMD5.AddHeader(new Lz77().Decompress(file)); - this.bannerApp.Data[index] = numArray; - this.bannerApp.Nodes[index].SizeOfData = (uint) numArray.Length; - } + if (tmd.Contents[index1].Index == index) + { + return contents[index1]; + } } - } + throw new Exception(string.Format("Content with index {0} not found!", index)); } - for (int index = 0; index < this.contents.Count; ++index) - { - if (this.tmd.Contents[index].Index == (ushort) 0) - { - this.fireDebug(" Saving Banner App..."); - this.contents[index] = this.bannerApp.ToByteArray(); - break; - } - } - } - this.fireDebug(" Updating Header..."); - int num = 0; - for (int index = 0; index < this.contents.Count - 1; ++index) - num += Shared.AddPadding(this.contents[index].Length); - this.wadHeader.ContentSize = (uint) (num + this.contents[this.contents.Count - 1].Length); - this.wadHeader.TmdSize = (uint) (484 + (int) this.tmd.NumOfContents * 36); - this.fireDebug(" Updating TMD Contents..."); - this.tmd.UpdateContents(this.contents.ToArray()); - this.fireDebug(" Writing Wad Header... (Offset: 0x{0})", (object) writeStream.Position.ToString("x8").ToUpper()); - writeStream.Seek(0L, SeekOrigin.Begin); - this.wadHeader.Write(writeStream); - this.fireDebug(" Writing Certificate Chain... (Offset: 0x{0})", (object) writeStream.Position.ToString("x8").ToUpper()); - writeStream.Seek((long) Shared.AddPadding((int) writeStream.Position), SeekOrigin.Begin); - byte[] byteArray1 = this.cert.ToByteArray(); - writeStream.Write(byteArray1, 0, byteArray1.Length); - this.fireDebug(" Writing Ticket... (Offset: 0x{0})", (object) writeStream.Position.ToString("x8").ToUpper()); - writeStream.Seek((long) Shared.AddPadding((int) writeStream.Position), SeekOrigin.Begin); - byte[] byteArray2 = this.tik.ToByteArray(); - writeStream.Write(byteArray2, 0, byteArray2.Length); - this.fireDebug(" Writing TMD... (Offset: 0x{0})", (object) writeStream.Position.ToString("x8").ToUpper()); - writeStream.Seek((long) Shared.AddPadding((int) writeStream.Position), SeekOrigin.Begin); - byte[] byteArray3 = this.tmd.ToByteArray(); - writeStream.Write(byteArray3, 0, byteArray3.Length); - ContentIndices[] sortedContentList = this.tmd.GetSortedContentList(); - for (int index = 0; index < sortedContentList.Length; ++index) - { - writeStream.Seek((long) Shared.AddPadding((int) writeStream.Position), SeekOrigin.Begin); - this.fireProgress((index + 1) * 100 / this.contents.Count); - this.fireDebug(" Writing Content #{1} of {2}... (Offset: 0x{0})", (object) writeStream.Position.ToString("x8").ToUpper(), (object) (index + 1), (object) this.contents.Count); - this.fireDebug(" -> Content ID: 0x{0}", (object) this.tmd.Contents[sortedContentList[index].Index].ContentID.ToString("x8")); - this.fireDebug(" -> Index: 0x{0}", (object) this.tmd.Contents[sortedContentList[index].Index].Index.ToString("x4")); - this.fireDebug(" -> Type: 0x{0} ({1})", (object) ((ushort) this.tmd.Contents[sortedContentList[index].Index].Type).ToString("x4"), (object) this.tmd.Contents[sortedContentList[index].Index].Type.ToString()); - this.fireDebug(" -> Size: {0} bytes", (object) this.tmd.Contents[sortedContentList[index].Index].Size); - this.fireDebug(" -> Hash: {0}", (object) Shared.ByteArrayToString(this.tmd.Contents[sortedContentList[index].Index].Hash)); - byte[] buffer = this.encryptContent(this.contents[sortedContentList[index].Index], sortedContentList[index].Index); - writeStream.Write(buffer, 0, buffer.Length); - } - if (this.wadHeader.FooterSize != 0U) - { - this.fireDebug(" Writing Footer... (Offset: 0x{0})", (object) writeStream.Position.ToString("x8").ToUpper()); - writeStream.Seek((long) Shared.AddPadding((int) writeStream.Position), SeekOrigin.Begin); - writeStream.Write(this.footer, 0, this.footer.Length); - } - while (writeStream.Position % 64L != 0L) - writeStream.WriteByte((byte) 0); - this.fireDebug("Writing Wad Finished... (Written Bytes: {0})", (object) writeStream.Position); - } - private void unpackAll(string unpackDir, bool nameContentId) - { - this.fireDebug("Unpacking Wad to: {0}", (object) unpackDir); - if (!Directory.Exists(unpackDir)) - Directory.CreateDirectory(unpackDir); - string str1 = this.tik.TitleID.ToString("x16"); - this.fireDebug(" Saving Certificate Chain: {0}.cert", (object) str1); - CertificateChain cert = this.cert; - string str2 = unpackDir; - char directorySeparatorChar = Path.DirectorySeparatorChar; - string str3 = directorySeparatorChar.ToString(); - string str4 = str1; - string savePath1 = str2 + str3 + str4 + ".cert"; - cert.Save(savePath1); - this.fireDebug(" Saving Ticket: {0}.tik", (object) str1); - Ticket tik = this.tik; - string str5 = unpackDir; - directorySeparatorChar = Path.DirectorySeparatorChar; - string str6 = directorySeparatorChar.ToString(); - string str7 = str1; - string savePath2 = str5 + str6 + str7 + ".tik"; - tik.Save(savePath2); - this.fireDebug(" Saving TMD: {0}.tmd", (object) str1); - TMD tmd = this.tmd; - string str8 = unpackDir; - directorySeparatorChar = Path.DirectorySeparatorChar; - string str9 = directorySeparatorChar.ToString(); - string str10 = str1; - string savePath3 = str8 + str9 + str10 + ".tmd"; - tmd.Save(savePath3); - for (int index = 0; index < (int) this.tmd.NumOfContents; ++index) - { - this.fireProgress((index + 1) * 100 / (int) this.tmd.NumOfContents); - this.fireDebug(" Saving Content #{0} of {1}: {2}.app", (object) (index + 1), (object) this.tmd.NumOfContents, nameContentId ? (object) this.tmd.Contents[index].ContentID.ToString("x8") : (object) this.tmd.Contents[index].Index.ToString("x8")); - this.fireDebug(" -> Content ID: 0x{0}", (object) this.tmd.Contents[index].ContentID.ToString("x8")); - this.fireDebug(" -> Index: 0x{0}", (object) this.tmd.Contents[index].Index.ToString("x4")); - object[] objArray = new object[2]; - ushort num = (ushort) this.tmd.Contents[index].Type; - objArray[0] = (object) num.ToString("x4"); - objArray[1] = (object) this.tmd.Contents[index].Type.ToString(); - this.fireDebug(" -> Type: 0x{0} ({1})", objArray); - this.fireDebug(" -> Size: {0} bytes", (object) this.tmd.Contents[index].Size); - this.fireDebug(" -> Hash: {0}", (object) Shared.ByteArrayToString(this.tmd.Contents[index].Hash)); - string str11 = unpackDir; - directorySeparatorChar = Path.DirectorySeparatorChar; - string str12 = directorySeparatorChar.ToString(); - string str13; - if (!nameContentId) + public byte[] GetContentByID(int contentID) { - num = this.tmd.Contents[index].Index; - str13 = num.ToString("x8"); + for (int index = 0; index < tmd.NumOfContents; ++index) + { + if (tmd.Contents[index].Index == contentID) + { + return contents[index]; + } + } + throw new Exception(string.Format("Content with content ID {0} not found!", contentID)); } - else - str13 = this.tmd.Contents[index].ContentID.ToString("x8"); - using (FileStream fileStream = new FileStream(str11 + str12 + str13 + ".app", FileMode.Create)) - fileStream.Write(this.contents[index], 0, this.contents[index].Length); - } - this.fireDebug(" Saving Footer: {0}.footer", (object) str1); - string str14 = unpackDir; - directorySeparatorChar = Path.DirectorySeparatorChar; - string str15 = directorySeparatorChar.ToString(); - string str16 = str1; - using (FileStream fileStream = new FileStream(str14 + str15 + str16 + ".footer", FileMode.Create)) - fileStream.Write(this.footer, 0, this.footer.Length); - this.fireDebug("Unpacking Wad Finished..."); - } - private void parseWad(Stream wadFile) - { - this.fireDebug("Parsing Wad..."); - wadFile.Seek(0L, SeekOrigin.Begin); - byte[] buffer = new byte[4]; - this.wadHeader = new WAD_Header(); - this.contents = new List(); - this.fireDebug(" Parsing Header... (Offset: 0x{0})", (object) wadFile.Position.ToString("x8").ToUpper()); - wadFile.Read(buffer, 0, 4); - if ((int) Shared.Swap(BitConverter.ToUInt32(buffer, 0)) != (int) this.wadHeader.HeaderSize) - throw new Exception("Invalid Headersize!"); - wadFile.Read(buffer, 0, 4); - this.wadHeader.WadType = Shared.Swap(BitConverter.ToUInt32(buffer, 0)); - wadFile.Seek(12L, SeekOrigin.Current); - wadFile.Read(buffer, 0, 4); - this.wadHeader.TmdSize = Shared.Swap(BitConverter.ToUInt32(buffer, 0)); - wadFile.Read(buffer, 0, 4); - this.wadHeader.ContentSize = Shared.Swap(BitConverter.ToUInt32(buffer, 0)); - wadFile.Read(buffer, 0, 4); - this.wadHeader.FooterSize = Shared.Swap(BitConverter.ToUInt32(buffer, 0)); - this.fireDebug(" Parsing Certificate Chain... (Offset: 0x{0})", (object) wadFile.Position.ToString("x8").ToUpper()); - wadFile.Seek((long) Shared.AddPadding((int) wadFile.Position), SeekOrigin.Begin); - byte[] numArray1 = new byte[(int) this.wadHeader.CertSize]; - wadFile.Read(numArray1, 0, numArray1.Length); - this.cert.LoadFile(numArray1); - this.fireDebug(" Parsing Ticket... (Offset: 0x{0})", (object) wadFile.Position.ToString("x8").ToUpper()); - wadFile.Seek((long) Shared.AddPadding((int) wadFile.Position), SeekOrigin.Begin); - byte[] numArray2 = new byte[(int) this.wadHeader.TicketSize]; - wadFile.Read(numArray2, 0, numArray2.Length); - this.tik.LoadFile(numArray2); - this.fireDebug(" Parsing TMD... (Offset: 0x{0})", (object) wadFile.Position.ToString("x8").ToUpper()); - wadFile.Seek((long) Shared.AddPadding((int) wadFile.Position), SeekOrigin.Begin); - byte[] numArray3 = new byte[(int) this.wadHeader.TmdSize]; - wadFile.Read(numArray3, 0, numArray3.Length); - this.tmd.LoadFile(numArray3); - if ((long) this.tmd.TitleID != (long) this.tik.TitleID) - this.fireWarning("The Title ID in the Ticket doesn't match the one in the TMD!"); - long position; - for (int contentIndex = 0; contentIndex < (int) this.tmd.NumOfContents; ++contentIndex) - { - this.fireProgress((contentIndex + 1) * 100 / (int) this.tmd.NumOfContents); - object[] objArray1 = new object[3] + public void ChangeChannelTitles(params string[] newTitles) { - (object) (contentIndex + 1), - (object) this.tmd.NumOfContents, + if (!hasBanner) + { + return; + } ((Headers.IMET)bannerApp.Header).ChangeTitles(newTitles); + } + + public void AddContent(byte[] newContent, int contentID, int index, ContentType type = ContentType.Normal) + { + tmd.AddContent(new TMD_Content() + { + ContentID = (uint)contentID, + Index = (ushort)index, + Type = type, + Size = (ulong)newContent.Length, + Hash = sha.ComputeHash(newContent) + }); + contents.Add(newContent); + wadHeader.TmdSize = (uint)(484 + tmd.NumOfContents * 36); + } + + public void RemoveContent(int index) + { + for (int index1 = 0; index1 < tmd.Contents.Length; ++index1) + { + if (tmd.Contents[index1].Index == index) + { + tmd.RemoveContent(index); + contents.RemoveAt(index1); + wadHeader.TmdSize = (uint)(484 + tmd.NumOfContents * 36); + return; + } + } + throw new Exception(string.Format("Content with index {0} not found!", index)); + } + + public void RemoveContentByID(int contentID) + { + for (int index = 0; index < tmd.Contents.Length; ++index) + { + if (tmd.Contents[index].Index == contentID) + { + tmd.RemoveContentByID(contentID); + contents.RemoveAt(index); + wadHeader.TmdSize = (uint)(484 + tmd.NumOfContents * 36); + return; + } + } + throw new Exception(string.Format("Content with content ID {0} not found!", contentID)); + } + + public void RemoveAllContents() + { + if (!hasBanner) + { + tmd.Contents = new TMD_Content[0]; + contents = new List(); + wadHeader.TmdSize = (uint)(484 + tmd.NumOfContents * 36); + } + else + { + for (int index = 0; index < tmd.NumOfContents; ++index) + { + if (tmd.Contents[index].Index == 0) + { + byte[] content1 = contents[index]; + TMD_Content content2 = tmd.Contents[index]; + tmd.Contents = new TMD_Content[0]; + contents = new List(); + tmd.AddContent(content2); + contents.Add(content1); + wadHeader.TmdSize = (uint)(484 + tmd.NumOfContents * 36); + break; + } + } + } + } + + public void Unpack(string unpackDir, bool nameContentID = false) + { + UnpackAll(unpackDir, nameContentID); + } + + public void RemoveFooter() + { + footer = new byte[0]; + wadHeader.FooterSize = 0U; + keepOriginalFooter = true; + } + + public void AddFooter(byte[] footer) + { + ChangeFooter(footer); + } + + public void ChangeFooter(byte[] newFooter) + { + if (newFooter.Length % 64 != 0) + { + Array.Resize(ref newFooter, Shared.AddPadding(newFooter.Length)); + } + + footer = newFooter; + wadHeader.FooterSize = (uint)newFooter.Length; + keepOriginalFooter = true; + } + + private void WriteToStream(Stream writeStream) + { + FireDebug("Writing Wad..."); + if (!keepOriginalFooter) + { + FireDebug(" Building Footer Timestamp..."); + CreateFooterTimestamp(); + } + if (hasBanner) + { + if (lz77CompressBannerAndIcon || lz77DecompressBannerAndIcon) + { + for (int index = 0; index < bannerApp.Nodes.Count; ++index) + { + if (bannerApp.StringTable[index].ToLower() == "icon.bin" || bannerApp.StringTable[index].ToLower() == "banner.bin") + { + if (!Lz77.IsLz77Compressed(bannerApp.Data[index]) && lz77CompressBannerAndIcon) + { + FireDebug(" Compressing {0}...", (object)bannerApp.StringTable[index]); + byte[] file = new byte[bannerApp.Data[index].Length - 32]; + Array.Copy(bannerApp.Data[index], 32, file, 0, file.Length); + byte[] numArray = Headers.IMD5.AddHeader(new Lz77().Compress(file)); + bannerApp.Data[index] = numArray; + bannerApp.Nodes[index].SizeOfData = (uint)numArray.Length; + } + else if (Lz77.IsLz77Compressed(bannerApp.Data[index]) && lz77DecompressBannerAndIcon) + { + FireDebug(" Decompressing {0}...", (object)bannerApp.StringTable[index]); + byte[] file = new byte[bannerApp.Data[index].Length - 32]; + Array.Copy(bannerApp.Data[index], 32, file, 0, file.Length); + byte[] numArray = Headers.IMD5.AddHeader(new Lz77().Decompress(file)); + bannerApp.Data[index] = numArray; + bannerApp.Nodes[index].SizeOfData = (uint)numArray.Length; + } + } + } + } + for (int index = 0; index < contents.Count; ++index) + { + if (tmd.Contents[index].Index == 0) + { + FireDebug(" Saving Banner App..."); + contents[index] = bannerApp.ToByteArray(); + break; + } + } + } + FireDebug(" Updating Header..."); + int num = 0; + for (int index = 0; index < contents.Count - 1; ++index) + { + num += Shared.AddPadding(contents[index].Length); + } + + wadHeader.ContentSize = (uint)(num + contents[contents.Count - 1].Length); + wadHeader.TmdSize = (uint)(484 + tmd.NumOfContents * 36); + FireDebug(" Updating TMD Contents..."); + tmd.UpdateContents(contents.ToArray()); + FireDebug(" Writing Wad Header... (Offset: 0x{0})", (object)writeStream.Position.ToString("x8").ToUpper()); + writeStream.Seek(0L, SeekOrigin.Begin); + wadHeader.Write(writeStream); + FireDebug(" Writing Certificate Chain... (Offset: 0x{0})", (object)writeStream.Position.ToString("x8").ToUpper()); + writeStream.Seek(Shared.AddPadding((int)writeStream.Position), SeekOrigin.Begin); + byte[] byteArray1 = cert.ToByteArray(); + writeStream.Write(byteArray1, 0, byteArray1.Length); + FireDebug(" Writing Ticket... (Offset: 0x{0})", (object)writeStream.Position.ToString("x8").ToUpper()); + writeStream.Seek(Shared.AddPadding((int)writeStream.Position), SeekOrigin.Begin); + byte[] byteArray2 = tik.ToByteArray(); + writeStream.Write(byteArray2, 0, byteArray2.Length); + FireDebug(" Writing TMD... (Offset: 0x{0})", (object)writeStream.Position.ToString("x8").ToUpper()); + writeStream.Seek(Shared.AddPadding((int)writeStream.Position), SeekOrigin.Begin); + byte[] byteArray3 = tmd.ToByteArray(); + writeStream.Write(byteArray3, 0, byteArray3.Length); + ContentIndices[] sortedContentList = tmd.GetSortedContentList(); + for (int index = 0; index < sortedContentList.Length; ++index) + { + writeStream.Seek(Shared.AddPadding((int)writeStream.Position), SeekOrigin.Begin); + FireProgress((index + 1) * 100 / contents.Count); + FireDebug(" Writing Content #{1} of {2}... (Offset: 0x{0})", writeStream.Position.ToString("x8").ToUpper(), index + 1, contents.Count); + FireDebug(" -> Content ID: 0x{0}", (object)tmd.Contents[sortedContentList[index].Index].ContentID.ToString("x8")); + FireDebug(" -> Index: 0x{0}", (object)tmd.Contents[sortedContentList[index].Index].Index.ToString("x4")); + FireDebug(" -> Type: 0x{0} ({1})", ((ushort)tmd.Contents[sortedContentList[index].Index].Type).ToString("x4"), tmd.Contents[sortedContentList[index].Index].Type.ToString()); + FireDebug(" -> Size: {0} bytes", (object)tmd.Contents[sortedContentList[index].Index].Size); + FireDebug(" -> Hash: {0}", (object)Shared.ByteArrayToString(tmd.Contents[sortedContentList[index].Index].Hash)); + byte[] buffer = EncryptContent(contents[sortedContentList[index].Index], sortedContentList[index].Index); + writeStream.Write(buffer, 0, buffer.Length); + } + if (wadHeader.FooterSize != 0U) + { + FireDebug(" Writing Footer... (Offset: 0x{0})", (object)writeStream.Position.ToString("x8").ToUpper()); + writeStream.Seek(Shared.AddPadding((int)writeStream.Position), SeekOrigin.Begin); + writeStream.Write(footer, 0, footer.Length); + } + while (writeStream.Position % 64L != 0L) + { + writeStream.WriteByte(0); + } + + FireDebug("Writing Wad Finished... (Written Bytes: {0})", (object)writeStream.Position); + } + + private void UnpackAll(string unpackDir, bool nameContentId) + { + FireDebug("Unpacking Wad to: {0}", (object)unpackDir); + if (!Directory.Exists(unpackDir)) + { + Directory.CreateDirectory(unpackDir); + } + + string str1 = this.tik.TitleID.ToString("x16"); + FireDebug(" Saving Certificate Chain: {0}.cert", (object)str1); + CertificateChain cert = this.cert; + string str2 = unpackDir; + char directorySeparatorChar = Path.DirectorySeparatorChar; + string str3 = directorySeparatorChar.ToString(); + string str4 = str1; + string savePath1 = str2 + str3 + str4 + ".cert"; + cert.Save(savePath1); + FireDebug(" Saving Ticket: {0}.tik", (object)str1); + Ticket tik = this.tik; + string str5 = unpackDir; + directorySeparatorChar = Path.DirectorySeparatorChar; + string str6 = directorySeparatorChar.ToString(); + string str7 = str1; + string savePath2 = str5 + str6 + str7 + ".tik"; + tik.Save(savePath2); + FireDebug(" Saving TMD: {0}.tmd", (object)str1); + TMD tmd = this.tmd; + string str8 = unpackDir; + directorySeparatorChar = Path.DirectorySeparatorChar; + string str9 = directorySeparatorChar.ToString(); + string str10 = str1; + string savePath3 = str8 + str9 + str10 + ".tmd"; + tmd.Save(savePath3); + for (int index = 0; index < this.tmd.NumOfContents; ++index) + { + FireProgress((index + 1) * 100 / this.tmd.NumOfContents); + FireDebug(" Saving Content #{0} of {1}: {2}.app", index + 1, this.tmd.NumOfContents, nameContentId ? this.tmd.Contents[index].ContentID.ToString("x8") : this.tmd.Contents[index].Index.ToString("x8")); + FireDebug(" -> Content ID: 0x{0}", (object)this.tmd.Contents[index].ContentID.ToString("x8")); + FireDebug(" -> Index: 0x{0}", (object)this.tmd.Contents[index].Index.ToString("x4")); + object[] objArray = new object[2]; + ushort num = (ushort)this.tmd.Contents[index].Type; + objArray[0] = num.ToString("x4"); + objArray[1] = this.tmd.Contents[index].Type.ToString(); + FireDebug(" -> Type: 0x{0} ({1})", objArray); + FireDebug(" -> Size: {0} bytes", (object)this.tmd.Contents[index].Size); + FireDebug(" -> Hash: {0}", (object)Shared.ByteArrayToString(this.tmd.Contents[index].Hash)); + string str11 = unpackDir; + directorySeparatorChar = Path.DirectorySeparatorChar; + string str12 = directorySeparatorChar.ToString(); + string str13; + if (!nameContentId) + { + num = this.tmd.Contents[index].Index; + str13 = num.ToString("x8"); + } + else + { + str13 = this.tmd.Contents[index].ContentID.ToString("x8"); + } + + using FileStream fileStream = new FileStream(str11 + str12 + str13 + ".app", FileMode.Create); + fileStream.Write(contents[index], 0, contents[index].Length); + } + FireDebug(" Saving Footer: {0}.footer", (object)str1); + string str14 = unpackDir; + directorySeparatorChar = Path.DirectorySeparatorChar; + string str15 = directorySeparatorChar.ToString(); + string str16 = str1; + using (FileStream fileStream = new FileStream(str14 + str15 + str16 + ".footer", FileMode.Create)) + { + fileStream.Write(footer, 0, footer.Length); + } + + FireDebug("Unpacking Wad Finished..."); + } + + private void ParseWad(Stream wadFile) + { + FireDebug("Parsing Wad..."); + wadFile.Seek(0L, SeekOrigin.Begin); + byte[] buffer = new byte[4]; + wadHeader = new WAD_Header(); + contents = new List(); + FireDebug(" Parsing Header... (Offset: 0x{0})", (object)wadFile.Position.ToString("x8").ToUpper()); + wadFile.Read(buffer, 0, 4); + if ((int)Shared.Swap(BitConverter.ToUInt32(buffer, 0)) != (int)wadHeader.HeaderSize) + { + throw new Exception("Invalid Headersize!"); + } + + wadFile.Read(buffer, 0, 4); + wadHeader.WadType = Shared.Swap(BitConverter.ToUInt32(buffer, 0)); + wadFile.Seek(12L, SeekOrigin.Current); + wadFile.Read(buffer, 0, 4); + wadHeader.TmdSize = Shared.Swap(BitConverter.ToUInt32(buffer, 0)); + wadFile.Read(buffer, 0, 4); + wadHeader.ContentSize = Shared.Swap(BitConverter.ToUInt32(buffer, 0)); + wadFile.Read(buffer, 0, 4); + wadHeader.FooterSize = Shared.Swap(BitConverter.ToUInt32(buffer, 0)); + FireDebug(" Parsing Certificate Chain... (Offset: 0x{0})", (object)wadFile.Position.ToString("x8").ToUpper()); + wadFile.Seek(Shared.AddPadding((int)wadFile.Position), SeekOrigin.Begin); + byte[] numArray1 = new byte[(int)wadHeader.CertSize]; + wadFile.Read(numArray1, 0, numArray1.Length); + cert.LoadFile(numArray1); + FireDebug(" Parsing Ticket... (Offset: 0x{0})", (object)wadFile.Position.ToString("x8").ToUpper()); + wadFile.Seek(Shared.AddPadding((int)wadFile.Position), SeekOrigin.Begin); + byte[] numArray2 = new byte[(int)wadHeader.TicketSize]; + wadFile.Read(numArray2, 0, numArray2.Length); + tik.LoadFile(numArray2); + FireDebug(" Parsing TMD... (Offset: 0x{0})", (object)wadFile.Position.ToString("x8").ToUpper()); + wadFile.Seek(Shared.AddPadding((int)wadFile.Position), SeekOrigin.Begin); + byte[] numArray3 = new byte[(int)wadHeader.TmdSize]; + wadFile.Read(numArray3, 0, numArray3.Length); + tmd.LoadFile(numArray3); + if ((long)tmd.TitleID != (long)tik.TitleID) + { + FireWarning("The Title ID in the Ticket doesn't match the one in the TMD!"); + } + + long position; + for (int contentIndex = 0; contentIndex < tmd.NumOfContents; ++contentIndex) + { + FireProgress((contentIndex + 1) * 100 / tmd.NumOfContents); + object[] objArray1 = new object[3] + { + contentIndex + 1, + tmd.NumOfContents, null - }; - position = wadFile.Position; - objArray1[2] = (object) position.ToString("x8").ToUpper(); - this.fireDebug(" Reading Content #{0} of {1}... (Offset: 0x{2})", objArray1); - this.fireDebug(" -> Content ID: 0x{0}", (object) this.tmd.Contents[contentIndex].ContentID.ToString("x8")); - object[] objArray2 = new object[1]; - ushort num = this.tmd.Contents[contentIndex].Index; - objArray2[0] = (object) num.ToString("x4"); - this.fireDebug(" -> Index: 0x{0}", objArray2); - object[] objArray3 = new object[2]; - num = (ushort) this.tmd.Contents[contentIndex].Type; - objArray3[0] = (object) num.ToString("x4"); - objArray3[1] = (object) this.tmd.Contents[contentIndex].Type.ToString(); - this.fireDebug(" -> Type: 0x{0} ({1})", objArray3); - this.fireDebug(" -> Size: {0} bytes", (object) this.tmd.Contents[contentIndex].Size); - this.fireDebug(" -> Hash: {0}", (object) Shared.ByteArrayToString(this.tmd.Contents[contentIndex].Hash)); - wadFile.Seek((long) Shared.AddPadding((int) wadFile.Position), SeekOrigin.Begin); - byte[] numArray4 = new byte[Shared.AddPadding((int) this.tmd.Contents[contentIndex].Size, 16)]; - wadFile.Read(numArray4, 0, numArray4.Length); - byte[] array = this.decryptContent(numArray4, contentIndex); - Array.Resize(ref array, (int) this.tmd.Contents[contentIndex].Size); - if (!Shared.CompareByteArrays(this.tmd.Contents[contentIndex].Hash, this.sha.ComputeHash(array, 0, (int) this.tmd.Contents[contentIndex].Size))) - { - this.fireDebug("/!\\ /!\\ /!\\ Hashes do not match /!\\ /!\\ /!\\"); - // ISSUE: variable of a boxed type - int local = contentIndex + 1; - string str1 = this.tmd.Contents[contentIndex].ContentID.ToString("x8"); - num = this.tmd.Contents[contentIndex].Index; - string str2 = num.ToString("x4"); - this.fireWarning(string.Format("Content #{0} (Content ID: 0x{1}; Index: 0x{2}): Hashes do not match! The content might be corrupted!", (object) local, (object) str1, (object) str2)); + }; + position = wadFile.Position; + objArray1[2] = position.ToString("x8").ToUpper(); + FireDebug(" Reading Content #{0} of {1}... (Offset: 0x{2})", objArray1); + FireDebug(" -> Content ID: 0x{0}", (object)tmd.Contents[contentIndex].ContentID.ToString("x8")); + object[] objArray2 = new object[1]; + ushort num = tmd.Contents[contentIndex].Index; + objArray2[0] = num.ToString("x4"); + FireDebug(" -> Index: 0x{0}", objArray2); + object[] objArray3 = new object[2]; + num = (ushort)tmd.Contents[contentIndex].Type; + objArray3[0] = num.ToString("x4"); + objArray3[1] = tmd.Contents[contentIndex].Type.ToString(); + FireDebug(" -> Type: 0x{0} ({1})", objArray3); + FireDebug(" -> Size: {0} bytes", (object)tmd.Contents[contentIndex].Size); + FireDebug(" -> Hash: {0}", (object)Shared.ByteArrayToString(tmd.Contents[contentIndex].Hash)); + wadFile.Seek(Shared.AddPadding((int)wadFile.Position), SeekOrigin.Begin); + byte[] numArray4 = new byte[Shared.AddPadding((int)tmd.Contents[contentIndex].Size, 16)]; + wadFile.Read(numArray4, 0, numArray4.Length); + byte[] array = DecryptContent(numArray4, contentIndex); + Array.Resize(ref array, (int)tmd.Contents[contentIndex].Size); + if (!Shared.CompareByteArrays(tmd.Contents[contentIndex].Hash, sha.ComputeHash(array, 0, (int)tmd.Contents[contentIndex].Size))) + { + FireDebug("/!\\ /!\\ /!\\ Hashes do not match /!\\ /!\\ /!\\"); + // ISSUE: variable of a boxed type + int local = contentIndex + 1; + string str1 = tmd.Contents[contentIndex].ContentID.ToString("x8"); + num = tmd.Contents[contentIndex].Index; + string str2 = num.ToString("x4"); + FireWarning(string.Format("Content #{0} (Content ID: 0x{1}; Index: 0x{2}): Hashes do not match! The content might be corrupted!", local, str1, str2)); + } + contents.Add(array); + if (tmd.Contents[contentIndex].Index == 0) + { + try + { + bannerApp.LoadFile(array); + hasBanner = true; + } + catch + { + hasBanner = false; + } + } + } + if (wadHeader.FooterSize != 0U) + { + object[] objArray = new object[1]; + position = wadFile.Position; + objArray[0] = position.ToString("x8").ToUpper(); + FireDebug(" Reading Footer... (Offset: 0x{0})", objArray); + footer = new byte[(int)wadHeader.FooterSize]; + wadFile.Seek(Shared.AddPadding((int)wadFile.Position), SeekOrigin.Begin); + wadFile.Read(footer, 0, footer.Length); + ParseFooterTimestamp(); + } + FireDebug("Parsing Wad Finished..."); } - this.contents.Add(array); - if (this.tmd.Contents[contentIndex].Index == (ushort) 0) + + private byte[] DecryptContent(byte[] content, int contentIndex) { - try - { - this.bannerApp.LoadFile(array); - this.hasBanner = true; - } - catch - { - this.hasBanner = false; - } + int length = content.Length; + Array.Resize(ref content, Shared.AddPadding(content.Length, 16)); + byte[] titleKey = tik.TitleKey; + byte[] numArray = new byte[16]; + byte[] bytes = BitConverter.GetBytes(tmd.Contents[contentIndex].Index); + numArray[0] = bytes[1]; + numArray[1] = bytes[0]; + RijndaelManaged rijndaelManaged = new RijndaelManaged + { + Mode = CipherMode.CBC, + Padding = PaddingMode.None, + KeySize = 128, + BlockSize = 128, + Key = titleKey, + IV = numArray + }; + ICryptoTransform decryptor = rijndaelManaged.CreateDecryptor(); + MemoryStream memoryStream = new MemoryStream(content); + CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read); + byte[] buffer = new byte[length]; + cryptoStream.Read(buffer, 0, buffer.Length); + cryptoStream.Dispose(); + memoryStream.Dispose(); + return buffer; + } + + private byte[] EncryptContent(byte[] content, int contentIndex) + { + Array.Resize(ref content, Shared.AddPadding(content.Length, 16)); + byte[] titleKey = tik.TitleKey; + byte[] numArray = new byte[16]; + byte[] bytes = BitConverter.GetBytes(tmd.Contents[contentIndex].Index); + numArray[0] = bytes[1]; + numArray[1] = bytes[0]; + RijndaelManaged rijndaelManaged = new RijndaelManaged + { + Mode = CipherMode.CBC, + Padding = PaddingMode.None, + KeySize = 128, + BlockSize = 128, + Key = titleKey, + IV = numArray + }; + ICryptoTransform encryptor = rijndaelManaged.CreateEncryptor(); + MemoryStream memoryStream = new MemoryStream(content); + CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Read); + byte[] buffer = new byte[content.Length]; + cryptoStream.Read(buffer, 0, buffer.Length); + cryptoStream.Dispose(); + memoryStream.Dispose(); + return buffer; + } + + private void CreateFooterTimestamp() + { + byte[] bytes = new ASCIIEncoding().GetBytes("TmStmp" + ((int)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds).ToString()); + Array.Resize(ref bytes, 64); + wadHeader.FooterSize = (uint)bytes.Length; + footer = bytes; + } + + private void ParseFooterTimestamp() + { + creationTimeUTC = new DateTime(1970, 1, 1); + if ((footer[0] != 67 || footer[1] != 77 || (footer[2] != 105 || footer[3] != 105) || (footer[4] != 85 || footer[5] != 84)) && (footer[0] != 84 || footer[1] != 109 || (footer[2] != 83 || footer[3] != 116) || (footer[4] != 109 || footer[5] != 112))) + { + return; + } + + string s = new ASCIIEncoding().GetString(footer, 6, 10); + int num = 0; + ref int local = ref num; + if (!int.TryParse(s, out local)) + { + return; + } + + creationTimeUTC = creationTimeUTC.AddSeconds(num); + } + + private void FireDebug(string debugMessage, params object[] args) + { + EventHandler debug = Debug; + if (debug == null) + { + return; + } + + debug(new object(), new MessageEventArgs(string.Format(debugMessage, args))); + } + + private void FireWarning(string warningMessage) + { + EventHandler warning = Warning; + if (warning == null) + { + return; + } + + warning(new object(), new MessageEventArgs(warningMessage)); + } + + private void FireProgress(int progressPercentage) + { + EventHandler progress = Progress; + if (progress == null) + { + return; + } + + progress(new object(), new ProgressChangedEventArgs(progressPercentage, string.Empty)); + } + + private void Cert_Debug(object sender, MessageEventArgs e) + { + FireDebug(" Certificate Chain: {0}", (object)e.Message); + } + + private void Tik_Debug(object sender, MessageEventArgs e) + { + FireDebug(" Ticket: {0}", (object)e.Message); + } + + private void Tmd_Debug(object sender, MessageEventArgs e) + { + FireDebug(" TMD: {0}", (object)e.Message); + } + + private void BannerApp_Debug(object sender, MessageEventArgs e) + { + FireDebug(" BannerApp: {0}", (object)e.Message); + } + + private void BannerApp_Warning(object sender, MessageEventArgs e) + { + FireWarning(e.Message); } - } - if (this.wadHeader.FooterSize != 0U) - { - object[] objArray = new object[1]; - position = wadFile.Position; - objArray[0] = (object) position.ToString("x8").ToUpper(); - this.fireDebug(" Reading Footer... (Offset: 0x{0})", objArray); - this.footer = new byte[(int) this.wadHeader.FooterSize]; - wadFile.Seek((long) Shared.AddPadding((int) wadFile.Position), SeekOrigin.Begin); - wadFile.Read(this.footer, 0, this.footer.Length); - this.parseFooterTimestamp(); - } - this.fireDebug("Parsing Wad Finished..."); } - private byte[] decryptContent(byte[] content, int contentIndex) - { - int length = content.Length; - Array.Resize(ref content, Shared.AddPadding(content.Length, 16)); - byte[] titleKey = this.tik.TitleKey; - byte[] numArray = new byte[16]; - byte[] bytes = BitConverter.GetBytes(this.tmd.Contents[contentIndex].Index); - numArray[0] = bytes[1]; - numArray[1] = bytes[0]; - RijndaelManaged rijndaelManaged = new RijndaelManaged(); - rijndaelManaged.Mode = CipherMode.CBC; - rijndaelManaged.Padding = PaddingMode.None; - rijndaelManaged.KeySize = 128; - rijndaelManaged.BlockSize = 128; - rijndaelManaged.Key = titleKey; - rijndaelManaged.IV = numArray; - ICryptoTransform decryptor = rijndaelManaged.CreateDecryptor(); - MemoryStream memoryStream = new MemoryStream(content); - CryptoStream cryptoStream = new CryptoStream((Stream) memoryStream, decryptor, CryptoStreamMode.Read); - byte[] buffer = new byte[length]; - cryptoStream.Read(buffer, 0, buffer.Length); - cryptoStream.Dispose(); - memoryStream.Dispose(); - return buffer; - } - - private byte[] encryptContent(byte[] content, int contentIndex) - { - Array.Resize(ref content, Shared.AddPadding(content.Length, 16)); - byte[] titleKey = this.tik.TitleKey; - byte[] numArray = new byte[16]; - byte[] bytes = BitConverter.GetBytes(this.tmd.Contents[contentIndex].Index); - numArray[0] = bytes[1]; - numArray[1] = bytes[0]; - RijndaelManaged rijndaelManaged = new RijndaelManaged(); - rijndaelManaged.Mode = CipherMode.CBC; - rijndaelManaged.Padding = PaddingMode.None; - rijndaelManaged.KeySize = 128; - rijndaelManaged.BlockSize = 128; - rijndaelManaged.Key = titleKey; - rijndaelManaged.IV = numArray; - ICryptoTransform encryptor = rijndaelManaged.CreateEncryptor(); - MemoryStream memoryStream = new MemoryStream(content); - CryptoStream cryptoStream = new CryptoStream((Stream) memoryStream, encryptor, CryptoStreamMode.Read); - byte[] buffer = new byte[content.Length]; - cryptoStream.Read(buffer, 0, buffer.Length); - cryptoStream.Dispose(); - memoryStream.Dispose(); - return buffer; - } - - private void createFooterTimestamp() - { - byte[] bytes = new ASCIIEncoding().GetBytes("TmStmp" + ((int) (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds).ToString()); - Array.Resize(ref bytes, 64); - this.wadHeader.FooterSize = (uint) bytes.Length; - this.footer = bytes; - } - - private void parseFooterTimestamp() - { - this.creationTimeUTC = new DateTime(1970, 1, 1); - if ((this.footer[0] != (byte) 67 || this.footer[1] != (byte) 77 || (this.footer[2] != (byte) 105 || this.footer[3] != (byte) 105) || (this.footer[4] != (byte) 85 || this.footer[5] != (byte) 84)) && (this.footer[0] != (byte) 84 || this.footer[1] != (byte) 109 || (this.footer[2] != (byte) 83 || this.footer[3] != (byte) 116) || (this.footer[4] != (byte) 109 || this.footer[5] != (byte) 112))) - return; - string s = new ASCIIEncoding().GetString(this.footer, 6, 10); - int num = 0; - ref int local = ref num; - if (!int.TryParse(s, out local)) - return; - this.creationTimeUTC = this.creationTimeUTC.AddSeconds((double) num); - } - - private void fireDebug(string debugMessage, params object[] args) - { - EventHandler debug = this.Debug; - if (debug == null) - return; - debug(new object(), new MessageEventArgs(string.Format(debugMessage, args))); - } - - private void fireWarning(string warningMessage) - { - EventHandler warning = this.Warning; - if (warning == null) - return; - warning(new object(), new MessageEventArgs(warningMessage)); - } - - private void fireProgress(int progressPercentage) - { - EventHandler progress = this.Progress; - if (progress == null) - return; - progress(new object(), new ProgressChangedEventArgs(progressPercentage, (object) string.Empty)); - } - - private void cert_Debug(object sender, MessageEventArgs e) => this.fireDebug(" Certificate Chain: {0}", (object) e.Message); - - private void tik_Debug(object sender, MessageEventArgs e) => this.fireDebug(" Ticket: {0}", (object) e.Message); - - private void tmd_Debug(object sender, MessageEventArgs e) => this.fireDebug(" TMD: {0}", (object) e.Message); - - private void bannerApp_Debug(object sender, MessageEventArgs e) => this.fireDebug(" BannerApp: {0}", (object) e.Message); - - private void bannerApp_Warning(object sender, MessageEventArgs e) => this.fireWarning(e.Message); - } - public class WAD_Header { - private uint headerSize = 0x20; + private readonly uint headerSize = 0x20; private uint wadType = 0x49730000; - private uint certSize = 0xA00; - private uint reserved = 0x00; - private uint tikSize = 0x2A4; + private readonly uint certSize = 0xA00; + private readonly uint reserved = 0x00; + private readonly uint tikSize = 0x2A4; private uint tmdSize; private uint contentSize; private uint footerSize = 0x00; - public uint HeaderSize { get { return headerSize; } } - public uint WadType { get { return wadType; } set { wadType = value; } } - public uint CertSize { get { return certSize; } } - public uint Reserved { get { return reserved; } } - public uint TicketSize { get { return tikSize; } } - public uint TmdSize { get { return tmdSize; } set { tmdSize = value; } } - public uint ContentSize { get { return contentSize; } set { contentSize = value; } } - public uint FooterSize { get { return footerSize; } set { footerSize = value; } } + public uint HeaderSize => headerSize; + public uint WadType { get => wadType; set => wadType = value; } + public uint CertSize => certSize; + public uint Reserved => reserved; + public uint TicketSize => tikSize; + public uint TmdSize { get => tmdSize; set => tmdSize = value; } + public uint ContentSize { get => contentSize; set => contentSize = value; } + public uint FooterSize { get => footerSize; set => footerSize = value; } public void Write(Stream writeStream) { diff --git a/Wave.cs b/Wave.cs index de01fab..3920c13 100644 --- a/Wave.cs +++ b/Wave.cs @@ -9,200 +9,213 @@ using System.IO; namespace libWiiSharp { - public class Wave : IDisposable - { - private WaveHeader header = new WaveHeader(); - private WaveFmtChunk fmt = new WaveFmtChunk(); - private WaveDataChunk data = new WaveDataChunk(); - private WaveSmplChunk smpl = new WaveSmplChunk(); - private bool hasSmpl; - private bool isDisposed; - - public int SampleRate => (int) this.fmt.SampleRate; - - public int BitDepth => (int) this.fmt.BitsPerSample; - - public int NumChannels => (int) this.fmt.NumChannels; - - public int NumLoops => !this.hasSmpl ? 0 : (int) this.smpl.NumLoops; - - public int LoopStart => this.NumLoops == 0 ? 0 : (int) this.smpl.Loops[0].LoopStart; - - public int NumSamples => (int) ((long) this.data.DataSize / (long) ((int) this.fmt.BitsPerSample / 8) / (long) this.fmt.NumChannels); - - public int DataFormat => (int) this.fmt.AudioFormat; - - public byte[] SampleData => this.data.Data; - - public int PlayLength => (int) ((long) (this.data.DataSize / (uint) this.fmt.NumChannels) / (long) ((int) this.fmt.BitsPerSample / 8) / (long) this.fmt.SampleRate); - - public Wave(string pathToFile) + public class Wave : IDisposable { - using (FileStream fileStream = new FileStream(pathToFile, FileMode.Open)) - { - using (BinaryReader reader = new BinaryReader((Stream) fileStream)) - this.parseWave(reader); - } - } + private WaveHeader header = new WaveHeader(); + private WaveFmtChunk fmt = new WaveFmtChunk(); + private WaveDataChunk data = new WaveDataChunk(); + private WaveSmplChunk smpl = new WaveSmplChunk(); + private bool hasSmpl; + private bool isDisposed; - public Wave(Stream wave) => this.parseWave(new BinaryReader(wave)); + public int SampleRate => (int)fmt.SampleRate; - public Wave(byte[] waveFile) - { - using (MemoryStream memoryStream = new MemoryStream(waveFile)) - { - using (BinaryReader reader = new BinaryReader((Stream) memoryStream)) - this.parseWave(reader); - } - } + public int BitDepth => fmt.BitsPerSample; - public Wave(int numChannels, int bitsPerSample, int sampleRate, byte[] samples) - { - this.fmt.SampleRate = (uint) sampleRate; - this.fmt.NumChannels = (ushort) numChannels; - this.fmt.BitsPerSample = (ushort) bitsPerSample; - this.data.Data = samples; - } + public int NumChannels => fmt.NumChannels; - ~Wave() => this.Dispose(false); + public int NumLoops => !hasSmpl ? 0 : (int)smpl.NumLoops; - public void Dispose() - { - this.Dispose(true); - GC.SuppressFinalize((object) this); - } + public int LoopStart => NumLoops == 0 ? 0 : (int)smpl.Loops[0].LoopStart; - protected virtual void Dispose(bool disposing) - { - if (disposing && !this.isDisposed) - { - this.header = (WaveHeader) null; - this.fmt = (WaveFmtChunk) null; - this.data = (WaveDataChunk) null; - this.smpl = (WaveSmplChunk) null; - } - this.isDisposed = true; - } + public int NumSamples => (int)(data.DataSize / (fmt.BitsPerSample / 8) / fmt.NumChannels); - public void Write(Stream writeStream) => this.writeToStream(new BinaryWriter(writeStream)); + public int DataFormat => (int)fmt.AudioFormat; - public MemoryStream ToMemoryStream() - { - MemoryStream memoryStream = new MemoryStream(); - this.writeToStream(new BinaryWriter((Stream) memoryStream)); - return memoryStream; - } + public byte[] SampleData => data.Data; - public byte[] ToByteArray() => this.ToMemoryStream().ToArray(); + public int PlayLength => (int)(data.DataSize / fmt.NumChannels / (fmt.BitsPerSample / 8) / fmt.SampleRate); - public void Save(string savePath) - { - using (FileStream fileStream = new FileStream(savePath, FileMode.Create)) - { - using (BinaryWriter writer = new BinaryWriter((Stream) fileStream)) - this.writeToStream(writer); - } - } - - public void AddLoop(int loopStartSample) - { - this.smpl.AddLoop(loopStartSample, this.NumSamples); - this.hasSmpl = true; - } - - public void RemoveLoop() => this.hasSmpl = false; - - public void TrimStart(int newStartSample) - { - int offset = (int) this.fmt.NumChannels * ((int) this.fmt.BitsPerSample / 8) * newStartSample; - MemoryStream memoryStream = new MemoryStream(); - memoryStream.Write(this.data.Data, offset, this.data.Data.Length - offset); - this.data.Data = memoryStream.ToArray(); - memoryStream.Dispose(); - } - - private void writeToStream(BinaryWriter writer) - { - this.header.FileSize = (uint) (4 + (int) this.fmt.FmtSize + 8 + (int) this.data.DataSize + 8 + (this.hasSmpl ? (int) this.smpl.SmplSize + 8 : 0)); - this.header.Write(writer); - this.fmt.Write(writer); - this.data.Write(writer); - if (!this.hasSmpl) - return; - this.smpl.Write(writer); - } - - private void parseWave(BinaryReader reader) - { - bool[] flagArray = new bool[3]; - while (reader.BaseStream.Position < reader.BaseStream.Length - 4L) - { - uint num1 = Shared.Swap(reader.ReadUInt32()); - uint num2 = reader.ReadUInt32(); - long offset = reader.BaseStream.Position + (long) num2; - switch (num1) + public Wave(string pathToFile) { - case 1380533830: - try - { - reader.BaseStream.Seek(-8L, SeekOrigin.Current); - this.header.Read(reader); - flagArray[0] = true; - break; - } - catch - { - reader.BaseStream.Seek(offset, SeekOrigin.Begin); - break; - } - case 1684108385: - try - { - reader.BaseStream.Seek(-8L, SeekOrigin.Current); - this.data.Read(reader); - flagArray[2] = true; - break; - } - catch - { - reader.BaseStream.Seek(offset, SeekOrigin.Begin); - break; - } - case 1718449184: - try - { - reader.BaseStream.Seek(-8L, SeekOrigin.Current); - this.fmt.Read(reader); - flagArray[1] = true; - break; - } - catch - { - reader.BaseStream.Seek(offset, SeekOrigin.Begin); - break; - } - case 1936552044: - try - { - reader.BaseStream.Seek(-8L, SeekOrigin.Current); - this.smpl.Read(reader); - this.hasSmpl = true; - break; - } - catch - { - reader.BaseStream.Seek(offset, SeekOrigin.Begin); - break; - } - default: - reader.BaseStream.Seek((long) num2, SeekOrigin.Current); - break; + using FileStream fileStream = new FileStream(pathToFile, FileMode.Open); + using BinaryReader reader = new BinaryReader(fileStream); + ParseWave(reader); + } + + public Wave(Stream wave) + { + ParseWave(new BinaryReader(wave)); + } + + public Wave(byte[] waveFile) + { + using MemoryStream memoryStream = new MemoryStream(waveFile); + using BinaryReader reader = new BinaryReader(memoryStream); + ParseWave(reader); + } + + public Wave(int numChannels, int bitsPerSample, int sampleRate, byte[] samples) + { + fmt.SampleRate = (uint)sampleRate; + fmt.NumChannels = (ushort)numChannels; + fmt.BitsPerSample = (ushort)bitsPerSample; + data.Data = samples; + } + + ~Wave() => Dispose(false); + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (disposing && !isDisposed) + { + header = null; + fmt = null; + data = null; + smpl = null; + } + isDisposed = true; + } + + public void Write(Stream writeStream) + { + WriteToStream(new BinaryWriter(writeStream)); + } + + public MemoryStream ToMemoryStream() + { + MemoryStream memoryStream = new MemoryStream(); + WriteToStream(new BinaryWriter(memoryStream)); + return memoryStream; + } + + public byte[] ToByteArray() + { + return ToMemoryStream().ToArray(); + } + + public void Save(string savePath) + { + using FileStream fileStream = new FileStream(savePath, FileMode.Create); + using BinaryWriter writer = new BinaryWriter(fileStream); + WriteToStream(writer); + } + + public void AddLoop(int loopStartSample) + { + smpl.AddLoop(loopStartSample, NumSamples); + hasSmpl = true; + } + + public void RemoveLoop() + { + hasSmpl = false; + } + + public void TrimStart(int newStartSample) + { + int offset = fmt.NumChannels * (fmt.BitsPerSample / 8) * newStartSample; + MemoryStream memoryStream = new MemoryStream(); + memoryStream.Write(data.Data, offset, data.Data.Length - offset); + data.Data = memoryStream.ToArray(); + memoryStream.Dispose(); + } + + private void WriteToStream(BinaryWriter writer) + { + header.FileSize = (uint)(4 + (int)fmt.FmtSize + 8 + (int)data.DataSize + 8 + (hasSmpl ? (int)smpl.SmplSize + 8 : 0)); + header.Write(writer); + fmt.Write(writer); + data.Write(writer); + if (!hasSmpl) + { + return; + } + + smpl.Write(writer); + } + + private void ParseWave(BinaryReader reader) + { + bool[] flagArray = new bool[3]; + while (reader.BaseStream.Position < reader.BaseStream.Length - 4L) + { + uint num1 = Shared.Swap(reader.ReadUInt32()); + uint num2 = reader.ReadUInt32(); + long offset = reader.BaseStream.Position + num2; + switch (num1) + { + case 1380533830: + try + { + reader.BaseStream.Seek(-8L, SeekOrigin.Current); + header.Read(reader); + flagArray[0] = true; + break; + } + catch + { + reader.BaseStream.Seek(offset, SeekOrigin.Begin); + break; + } + case 1684108385: + try + { + reader.BaseStream.Seek(-8L, SeekOrigin.Current); + data.Read(reader); + flagArray[2] = true; + break; + } + catch + { + reader.BaseStream.Seek(offset, SeekOrigin.Begin); + break; + } + case 1718449184: + try + { + reader.BaseStream.Seek(-8L, SeekOrigin.Current); + fmt.Read(reader); + flagArray[1] = true; + break; + } + catch + { + reader.BaseStream.Seek(offset, SeekOrigin.Begin); + break; + } + case 1936552044: + try + { + reader.BaseStream.Seek(-8L, SeekOrigin.Current); + smpl.Read(reader); + hasSmpl = true; + break; + } + catch + { + reader.BaseStream.Seek(offset, SeekOrigin.Begin); + break; + } + default: + reader.BaseStream.Seek(num2, SeekOrigin.Current); + break; + } + if (flagArray[0] && flagArray[1] && (flagArray[2] && hasSmpl)) + { + break; + } + } + if (!flagArray[0] || !flagArray[1] || !flagArray[2]) + { + throw new Exception("Couldn't parse Wave file..."); + } } - if (flagArray[0] && flagArray[1] && (flagArray[2] && this.hasSmpl)) - break; - } - if (!flagArray[0] || !flagArray[1] || !flagArray[2]) - throw new Exception("Couldn't parse Wave file..."); } - } } diff --git a/WaveDataChunk.cs b/WaveDataChunk.cs index 7dd5a04..aa5c1ac 100644 --- a/WaveDataChunk.cs +++ b/WaveDataChunk.cs @@ -9,35 +9,35 @@ using System.IO; namespace libWiiSharp { - internal class WaveDataChunk - { - private uint dataId = 1684108385; - private uint dataSize = 8; - private byte[] data; - - public uint DataSize => this.dataSize; - - public byte[] Data + internal class WaveDataChunk { - get => this.data; - set - { - this.data = value; - this.dataSize = (uint) this.data.Length; - } - } + private readonly uint dataId = 1684108385; + private uint dataSize = 8; + private byte[] data; - public void Write(BinaryWriter writer) - { - writer.Write(Shared.Swap(this.dataId)); - writer.Write(this.dataSize); - writer.Write(this.data, 0, this.data.Length); - } + public uint DataSize => dataSize; - public void Read(BinaryReader reader) - { - this.dataSize = (int) Shared.Swap(reader.ReadUInt32()) == (int) this.dataId ? reader.ReadUInt32() : throw new Exception("Wrong chunk ID!"); - this.data = reader.ReadBytes((int) this.dataSize); + public byte[] Data + { + get => data; + set + { + data = value; + dataSize = (uint)data.Length; + } + } + + public void Write(BinaryWriter writer) + { + writer.Write(Shared.Swap(dataId)); + writer.Write(dataSize); + writer.Write(data, 0, data.Length); + } + + public void Read(BinaryReader reader) + { + dataSize = (int)Shared.Swap(reader.ReadUInt32()) == (int)dataId ? reader.ReadUInt32() : throw new Exception("Wrong chunk ID!"); + data = reader.ReadBytes((int)dataSize); + } } - } } diff --git a/WaveFmtChunk.cs b/WaveFmtChunk.cs index 57bde38..ada58d1 100644 --- a/WaveFmtChunk.cs +++ b/WaveFmtChunk.cs @@ -9,62 +9,62 @@ using System.IO; namespace libWiiSharp { - internal class WaveFmtChunk - { - private uint fmtId = 1718449184; - private uint fmtSize = 16; - private ushort audioFormat = 1; - private ushort numChannels = 2; - private uint sampleRate = 44100; - private uint byteRate; - private ushort blockAlign; - private ushort bitsPerSample = 16; - - public uint FmtSize => this.fmtSize; - - public ushort NumChannels + internal class WaveFmtChunk { - get => this.numChannels; - set => this.numChannels = value; - } + private readonly uint fmtId = 1718449184; + private uint fmtSize = 16; + private ushort audioFormat = 1; + private ushort numChannels = 2; + private uint sampleRate = 44100; + private uint byteRate; + private ushort blockAlign; + private ushort bitsPerSample = 16; - public uint SampleRate - { - get => this.sampleRate; - set => this.sampleRate = value; - } + public uint FmtSize => fmtSize; - public ushort BitsPerSample - { - get => this.bitsPerSample; - set => this.bitsPerSample = value; - } + public ushort NumChannels + { + get => numChannels; + set => numChannels = value; + } - public uint AudioFormat => (uint) this.audioFormat; + public uint SampleRate + { + get => sampleRate; + set => sampleRate = value; + } - public void Write(BinaryWriter writer) - { - this.byteRate = this.sampleRate * (uint) this.numChannels * (uint) this.bitsPerSample / 8U; - this.blockAlign = (ushort) ((int) this.numChannels * (int) this.bitsPerSample / 8); - writer.Write(Shared.Swap(this.fmtId)); - writer.Write(this.fmtSize); - writer.Write(this.audioFormat); - writer.Write(this.numChannels); - writer.Write(this.sampleRate); - writer.Write(this.byteRate); - writer.Write(this.blockAlign); - writer.Write(this.bitsPerSample); - } + public ushort BitsPerSample + { + get => bitsPerSample; + set => bitsPerSample = value; + } - public void Read(BinaryReader reader) - { - this.fmtSize = (int) Shared.Swap(reader.ReadUInt32()) == (int) this.fmtId ? reader.ReadUInt32() : throw new Exception("Wrong chunk ID!"); - this.audioFormat = reader.ReadUInt16(); - this.numChannels = reader.ReadUInt16(); - this.sampleRate = reader.ReadUInt32(); - this.byteRate = reader.ReadUInt32(); - this.blockAlign = reader.ReadUInt16(); - this.bitsPerSample = reader.ReadUInt16(); + public uint AudioFormat => audioFormat; + + public void Write(BinaryWriter writer) + { + byteRate = sampleRate * numChannels * bitsPerSample / 8U; + blockAlign = (ushort)(numChannels * bitsPerSample / 8); + writer.Write(Shared.Swap(fmtId)); + writer.Write(fmtSize); + writer.Write(audioFormat); + writer.Write(numChannels); + writer.Write(sampleRate); + writer.Write(byteRate); + writer.Write(blockAlign); + writer.Write(bitsPerSample); + } + + public void Read(BinaryReader reader) + { + fmtSize = (int)Shared.Swap(reader.ReadUInt32()) == (int)fmtId ? reader.ReadUInt32() : throw new Exception("Wrong chunk ID!"); + audioFormat = reader.ReadUInt16(); + numChannels = reader.ReadUInt16(); + sampleRate = reader.ReadUInt32(); + byteRate = reader.ReadUInt32(); + blockAlign = reader.ReadUInt16(); + bitsPerSample = reader.ReadUInt16(); + } } - } } diff --git a/WaveHeader.cs b/WaveHeader.cs index 17442d6..fc7a897 100644 --- a/WaveHeader.cs +++ b/WaveHeader.cs @@ -9,30 +9,32 @@ using System.IO; namespace libWiiSharp { - internal class WaveHeader - { - private uint headerId = 1380533830; - private uint fileSize = 12; - private uint format = 1463899717; - - public uint FileSize + internal class WaveHeader { - get => this.fileSize; - set => this.fileSize = value; - } + private readonly uint headerId = 1380533830; + private uint fileSize = 12; + private readonly uint format = 1463899717; - public void Write(BinaryWriter writer) - { - writer.Write(Shared.Swap(this.headerId)); - writer.Write(this.fileSize); - writer.Write(Shared.Swap(this.format)); - } + public uint FileSize + { + get => fileSize; + set => fileSize = value; + } - public void Read(BinaryReader reader) - { - this.fileSize = (int) Shared.Swap(reader.ReadUInt32()) == (int) this.headerId ? reader.ReadUInt32() : throw new Exception("Not a valid RIFF Wave file!"); - if ((int) Shared.Swap(reader.ReadUInt32()) != (int) this.format) - throw new Exception("Not a valid RIFF Wave file!"); + public void Write(BinaryWriter writer) + { + writer.Write(Shared.Swap(headerId)); + writer.Write(fileSize); + writer.Write(Shared.Swap(format)); + } + + public void Read(BinaryReader reader) + { + fileSize = (int)Shared.Swap(reader.ReadUInt32()) == (int)headerId ? reader.ReadUInt32() : throw new Exception("Not a valid RIFF Wave file!"); + if ((int)Shared.Swap(reader.ReadUInt32()) != (int)format) + { + throw new Exception("Not a valid RIFF Wave file!"); + } + } } - } } diff --git a/WaveSmplChunk.cs b/WaveSmplChunk.cs index e5d5192..f014fc9 100644 --- a/WaveSmplChunk.cs +++ b/WaveSmplChunk.cs @@ -10,79 +10,81 @@ using System.IO; namespace libWiiSharp { - internal class WaveSmplChunk - { - private uint smplId = 1936552044; - private uint smplSize = 36; - private uint manufacturer; - private uint product; - private uint samplePeriod; - private uint unityNote = 60; - private uint pitchFraction; - private uint smpteFormat; - private uint smpteOffset; - private uint numLoops; - private uint samplerData; - private List smplLoops = new List(); - - public uint SmplSize => this.smplSize; - - public uint NumLoops => this.numLoops; - - public WaveSmplLoop[] Loops => this.smplLoops.ToArray(); - - public void AddLoop(int loopStartSample, int loopEndSample) + internal class WaveSmplChunk { - this.RemoveAllLoops(); - ++this.numLoops; - this.smplLoops.Add(new WaveSmplLoop() - { - LoopStart = (uint) loopStartSample, - LoopEnd = (uint) loopEndSample - }); - } + private readonly uint smplId = 1936552044; + private uint smplSize = 36; + private uint manufacturer; + private uint product; + private uint samplePeriod; + private uint unityNote = 60; + private uint pitchFraction; + private uint smpteFormat; + private uint smpteOffset; + private uint numLoops; + private uint samplerData; + private readonly List smplLoops = new List(); - public void RemoveAllLoops() - { - this.smplLoops.Clear(); - this.numLoops = 0U; - } + public uint SmplSize => smplSize; - public void Write(BinaryWriter writer) - { - writer.Write(Shared.Swap(this.smplId)); - writer.Write(this.smplSize); - writer.Write(this.manufacturer); - writer.Write(this.product); - writer.Write(this.samplePeriod); - writer.Write(this.unityNote); - writer.Write(this.pitchFraction); - writer.Write(this.smpteFormat); - writer.Write(this.smpteOffset); - writer.Write(this.numLoops); - writer.Write(this.samplerData); - for (int index = 0; (long) index < (long) this.numLoops; ++index) - this.smplLoops[index].Write(writer); - } + public uint NumLoops => numLoops; - public void Read(BinaryReader reader) - { - this.smplSize = (int) Shared.Swap(reader.ReadUInt32()) == (int) this.smplId ? reader.ReadUInt32() : throw new Exception("Wrong chunk ID!"); - this.manufacturer = reader.ReadUInt32(); - this.product = reader.ReadUInt32(); - this.samplePeriod = reader.ReadUInt32(); - this.unityNote = reader.ReadUInt32(); - this.pitchFraction = reader.ReadUInt32(); - this.smpteFormat = reader.ReadUInt32(); - this.smpteOffset = reader.ReadUInt32(); - this.numLoops = reader.ReadUInt32(); - this.samplerData = reader.ReadUInt32(); - for (int index = 0; (long) index < (long) this.numLoops; ++index) - { - WaveSmplLoop waveSmplLoop = new WaveSmplLoop(); - waveSmplLoop.Read(reader); - this.smplLoops.Add(waveSmplLoop); - } + public WaveSmplLoop[] Loops => smplLoops.ToArray(); + + public void AddLoop(int loopStartSample, int loopEndSample) + { + RemoveAllLoops(); + ++numLoops; + smplLoops.Add(new WaveSmplLoop() + { + LoopStart = (uint)loopStartSample, + LoopEnd = (uint)loopEndSample + }); + } + + public void RemoveAllLoops() + { + smplLoops.Clear(); + numLoops = 0U; + } + + public void Write(BinaryWriter writer) + { + writer.Write(Shared.Swap(smplId)); + writer.Write(smplSize); + writer.Write(manufacturer); + writer.Write(product); + writer.Write(samplePeriod); + writer.Write(unityNote); + writer.Write(pitchFraction); + writer.Write(smpteFormat); + writer.Write(smpteOffset); + writer.Write(numLoops); + writer.Write(samplerData); + for (int index = 0; index < numLoops; ++index) + { + smplLoops[index].Write(writer); + } + } + + public void Read(BinaryReader reader) + { + smplSize = (int)Shared.Swap(reader.ReadUInt32()) == (int)smplId ? reader.ReadUInt32() : throw new Exception("Wrong chunk ID!"); + manufacturer = reader.ReadUInt32(); + product = reader.ReadUInt32(); + samplePeriod = reader.ReadUInt32(); + unityNote = reader.ReadUInt32(); + pitchFraction = reader.ReadUInt32(); + smpteFormat = reader.ReadUInt32(); + smpteOffset = reader.ReadUInt32(); + numLoops = reader.ReadUInt32(); + samplerData = reader.ReadUInt32(); + for (int index = 0; index < numLoops; ++index) + { + WaveSmplLoop waveSmplLoop = new WaveSmplLoop(); + waveSmplLoop.Read(reader); + smplLoops.Add(waveSmplLoop); + } + } } - } } diff --git a/WaveSmplLoop.cs b/WaveSmplLoop.cs index 0c297ed..d747fb4 100644 --- a/WaveSmplLoop.cs +++ b/WaveSmplLoop.cs @@ -8,45 +8,45 @@ using System.IO; namespace libWiiSharp { - internal class WaveSmplLoop - { - private uint cuePointId; - private uint type; - private uint start; - private uint end; - private uint fraction; - private uint playCount; - - public uint LoopStart + internal class WaveSmplLoop { - get => this.start; - set => this.start = value; - } + private uint cuePointId; + private uint type; + private uint start; + private uint end; + private uint fraction; + private uint playCount; - public uint LoopEnd - { - get => this.end; - set => this.end = value; - } + public uint LoopStart + { + get => start; + set => start = value; + } - public void Write(BinaryWriter writer) - { - writer.Write(this.cuePointId); - writer.Write(this.type); - writer.Write(this.start); - writer.Write(this.end); - writer.Write(this.fraction); - writer.Write(this.playCount); - } + public uint LoopEnd + { + get => end; + set => end = value; + } - public void Read(BinaryReader reader) - { - this.cuePointId = reader.ReadUInt32(); - this.type = reader.ReadUInt32(); - this.start = reader.ReadUInt32(); - this.end = reader.ReadUInt32(); - this.fraction = reader.ReadUInt32(); - this.playCount = reader.ReadUInt32(); + public void Write(BinaryWriter writer) + { + writer.Write(cuePointId); + writer.Write(type); + writer.Write(start); + writer.Write(end); + writer.Write(fraction); + writer.Write(playCount); + } + + public void Read(BinaryReader reader) + { + cuePointId = reader.ReadUInt32(); + type = reader.ReadUInt32(); + start = reader.ReadUInt32(); + end = reader.ReadUInt32(); + fraction = reader.ReadUInt32(); + playCount = reader.ReadUInt32(); + } } - } }