public void Save(string filename, Platform platform, Game game) { //Get Text Section var TextBlob = Encoding.UTF8.GetBytes(GMDContent.Content.Aggregate("", (output, c) => output + c.Text.Replace("\r\n", "\xa").Replace("\xa", "\r\n") + "\0")); //XOR, if needed if (platform == Platform.CTR && game == Game.DD) { TextBlob = new BinaryReaderX(XOR.ReXOR(TextBlob, 0)).ReadAllBytes(); } //Get Label Blob var LabelBlob = Encoding.ASCII.GetBytes(GMDContent.Content.Aggregate("", (output, c) => output + (c.Name.Contains("no_name") ? "" : c.Name + "\0"))); //Create LabelEntries var Entries = new List <LabelEntry>(); var LabelOffset = 0; var LabelCount = GMDContent.Content.Count(c => !c.Name.Contains("no_name")); for (int i = 0; i < GMDContent.Content.Count(); i++) { if (!GMDContent.Content[i].Name.Contains("no_name")) { Entries.Add(new LabelEntry { SectionID = i, LabelOffset = LabelOffset + (0x29080170 + LabelCount * 0x80) }); LabelOffset += Encoding.ASCII.GetByteCount(GMDContent.Content[i].Name) + 1; } } //Header var Header = new Header { Magic = GMDContent.ByteOrder == ByteOrder.BigEndian ? "\0DMG" : "GMD\0", Version = 0x00010201, Language = Language.ENGLISH, Zero1 = 0, LabelCount = LabelCount, SectionCount = GMDContent.Content.Count(), LabelSize = LabelBlob.Length, SectionSize = TextBlob.Length, NameSize = Encoding.ASCII.GetByteCount(GMDContent.Name) }; //Write stuff using (var bw = new BinaryWriterX(File.Create(filename), GMDContent.ByteOrder)) { //Header bw.WriteStruct(Header); bw.Write(Encoding.ASCII.GetBytes(GMDContent.Name + "\0")); //LabelEntries foreach (var entry in Entries) { bw.WriteStruct(entry); } //Labels bw.Write(LabelBlob); //Text Sections bw.Write(TextBlob); } }
public void Load(string filename) { using (var br = new BinaryReaderX(File.OpenRead(filename))) { // Set endianess if (br.PeekString() == "\0DMG") { br.ByteOrder = GMDContent.ByteOrder = ByteOrder.BigEndian; } // Header var Header = br.ReadStruct <Header>(); var Name = br.ReadCStringA(); var HeaderLength = (int)br.BaseStream.Position; GMDContent.Name = Name; // Label Entries var LabelEntries = (Header.LabelCount > 0) ? br.ReadMultiple <LabelEntry>(Header.LabelCount) : new List <LabelEntry>(); var LabelDataOffset = (int)br.BaseStream.Position; // Text br.BaseStream.Position = 0x28 + (Header.NameSize + 1) + (Header.LabelCount * 0x8) + Header.LabelSize; var text = br.ReadBytes(Header.SectionSize); // Text deobfuscation var deXor = XOR.DeXOR(text); using (var brt = new BinaryReaderX(deXor)) { var counter = 0; for (var i = 0; i < Header.SectionCount; i++) { var bk = brt.BaseStream.Position; var tmp = brt.ReadByte(); while (tmp != 0) { tmp = brt.ReadByte(); } var textSize = brt.BaseStream.Position - bk; brt.BaseStream.Position = bk; //Get Label if existent var label = ""; if (LabelEntries.Find(l => l.SectionID == i) != null) { bk = br.BaseStream.Position; br.BaseStream.Position = LabelEntries.Find(l => l.SectionID == i).LabelOffset - LabelEntries.First().LabelOffset + (HeaderLength + Header.LabelCount * 0x8); label = br.ReadCStringA(); br.BaseStream.Position = bk; } GMDContent.Content.Add(new Label { Name = label == "" ? "no_name_" + counter++.ToString() : label, Text = brt.ReadString((int)textSize, Encoding.UTF8).Replace("\r\n", "\xa").Replace("\xa", "\r\n"), TextID = i }); } } } }
public void Load(string filename) { using (var br = new BinaryReaderX(File.OpenRead(filename))) { // Set endianess if (br.PeekString() == "\0DMG") { br.ByteOrder = GMDContent.ByteOrder = ByteOrder.BigEndian; } // Header var Header = br.ReadStruct <Header>(); var Name = br.ReadCStringA(); GMDContent.Name = Name; //Check for platform difference var fullSize = 0x28 + Name.Length + 1 + Header.LabelCount * 0x14 + ((Header.LabelCount > 0) ? 0x100 * 0x4 : 0) + Header.LabelSize + Header.SectionSize; if (fullSize != br.BaseStream.Length) { //Mobile structure //Entry var LabelEntries = (Header.LabelCount > 0) ? br.ReadMultiple <LabelEntryMobile>(Header.LabelCount) : new List <LabelEntryMobile>(); //Bucketlist var Buckets = (Header.LabelCount > 0) ? br.ReadMultiple <long>(0x100) : new List <long>(); var LabelDataOffset = (int)br.BaseStream.Position; // Text br.BaseStream.Position = 0x28 + (Header.NameSize + 1) + (Header.LabelCount * 0x20 + ((Header.LabelCount > 0) ? 0x100 * 0x8 : 0)) + Header.LabelSize; var text = br.ReadBytes(Header.SectionSize); // Text deobfuscation var deXor = XOR.DeXOR(text); using (var brt = new BinaryReaderX(deXor)) { var counter = 0; for (var i = 0; i < Header.SectionCount; i++) { var bk = brt.BaseStream.Position; var tmp = brt.ReadByte(); while (tmp != 0) { tmp = brt.ReadByte(); } var textSize = brt.BaseStream.Position - bk; brt.BaseStream.Position = bk; //Get Label if existent var label = ""; if (LabelEntries.Find(l => l.SectionID == i) != null) { bk = br.BaseStream.Position; br.BaseStream.Position = LabelDataOffset + LabelEntries.Find(l => l.SectionID == i).LabelOffset; label = br.ReadCStringA(); br.BaseStream.Position = bk; } GMDContent.Content.Add(new Label { Name = label == "" ? "no_name_" + counter++.ToString("000") : label, Text = brt.ReadString((int)textSize, Encoding.UTF8).Replace("\r\n", "\xa").Replace("\xa", "\r\n"), TextID = i }); } } } else { //CTR structure //Entry var LabelEntries = (Header.LabelCount > 0) ? br.ReadMultiple <LabelEntry>(Header.LabelCount) : new List <LabelEntry>(); //Bucketlist var Buckets = (Header.LabelCount > 0) ? br.ReadMultiple <int>(0x100) : new List <int>(); var LabelDataOffset = (int)br.BaseStream.Position; // Text br.BaseStream.Position = 0x28 + (Header.NameSize + 1) + (Header.LabelCount * 0x14 + ((Header.LabelCount > 0) ? 0x100 * 0x4 : 0)) + Header.LabelSize; var text = br.ReadBytes(Header.SectionSize); // Text deobfuscation var deXor = XOR.DeXOR(text); using (var brt = new BinaryReaderX(deXor)) { var counter = 0; for (var i = 0; i < Header.SectionCount; i++) { var bk = brt.BaseStream.Position; var tmp = brt.ReadByte(); while (tmp != 0) { tmp = brt.ReadByte(); } var textSize = brt.BaseStream.Position - bk; brt.BaseStream.Position = bk; //Get Label if existent var label = ""; if (LabelEntries.Find(l => l.SectionID == i) != null) { bk = br.BaseStream.Position; br.BaseStream.Position = LabelDataOffset + LabelEntries.Find(l => l.SectionID == i).LabelOffset; label = br.ReadCStringA(); br.BaseStream.Position = bk; } GMDContent.Content.Add(new Label { Name = label == "" ? "no_name_" + counter++.ToString("000") : label, Text = brt.ReadString((int)textSize, Encoding.UTF8).Replace("\r\n", "\xa").Replace("\xa", "\r\n"), TextID = i }); } } } } }
public void Save(string filename, Platform platform, Game game) { //Get Text Blob var TextBlob = Encoding.UTF8.GetBytes(GMDContent.Content.Aggregate("", (output, c) => output + c.Text.Replace("\r\n", "\xa").Replace("\xa", "\r\n") + "\0")); //ReXOR, if needed if (platform == Platform.CTR && game == Game.DGS2) { TextBlob = new BinaryReaderX(XOR.ReXOR(TextBlob, 1)).ReadAllBytes(); } //Get Label Blob var LabelBlob = Encoding.ASCII.GetBytes(GMDContent.Content.Aggregate("", (output, c) => output + (c.Name.Contains("no_name") ? "" : c.Name + "\0"))); if (platform == Platform.Mobile || platform == Platform.Switch) { //Create Entries var LabelEntries = new List <LabelEntryMobile>(); var Buckets = new Dictionary <byte, int>(); int LabelOffset = 0; var LabelCount = GMDContent.Content.Count(c => !c.Name.Contains("no_name")); var counter = 0; for (var i = 0; i < GMDContent.Content.Count(); i++) { if (!GMDContent.Content[i].Name.Contains("no_name")) { LabelEntries.Add(new LabelEntryMobile { SectionID = i, Hash1 = ~Crc32.Create(GMDContent.Content[i].Name + GMDContent.Content[i].Name), Hash2 = ~Crc32.Create(GMDContent.Content[i].Name + GMDContent.Content[i].Name + GMDContent.Content[i].Name), LabelOffset = LabelOffset, ListLink = 0, ZeroPadding = platform == Platform.Switch ? 0xCDCDCDCD : 0 }); LabelOffset += Encoding.ASCII.GetByteCount(GMDContent.Content[i].Name) + 1; var bucket = (byte)(~Crc32.Create(GMDContent.Content[i].Name) & 0xff); if (Buckets.ContainsKey(bucket)) { LabelEntries[Buckets[bucket]].ListLink = counter; Buckets[bucket] = counter; } else { Buckets.Add(bucket, counter); } counter++; } } //Create bucketList Blob var BucketBlob = new long[0x100]; if (LabelCount > 0) { var counter2 = 0; for (var i = 0; i < GMDContent.Content.Count(); i++) { if (!GMDContent.Content[i].Name.Contains("no_name")) { var bucket = (byte)(~Crc32.Create(GMDContent.Content[i].Name) & 0xff); if (BucketBlob[bucket] == 0) { BucketBlob[bucket] = (counter2 == 0) ? -1 : counter2; } counter2++; } } } //Create Header var Header = new Header { Magic = "GMD\0", Version = 0x00010302, Language = Language.ENGLISH, LabelCount = LabelCount, SectionCount = GMDContent.Content.Count(), LabelSize = LabelBlob.Length, SectionSize = TextBlob.Length, NameSize = Encoding.ASCII.GetByteCount(GMDContent.Name) }; //Write Stuff using (var bw = new BinaryWriterX(File.Create(filename))) { //Header bw.WriteStruct(Header); bw.Write(Encoding.ASCII.GetBytes(GMDContent.Name + "\0")); //Entries foreach (var entry in LabelEntries) { bw.WriteStruct(entry); } //BucketList if (LabelCount > 0) { foreach (var bucket in BucketBlob) { bw.Write(bucket); } } //Labels bw.Write(LabelBlob); //Text Sections bw.Write(TextBlob); } } else if (platform == Platform.CTR) { //Create Entries var LabelEntries = new List <LabelEntry>(); var Buckets = new Dictionary <byte, int>(); int LabelOffset = 0; var LabelCount = GMDContent.Content.Count(c => !c.Name.Contains("no_name")); var counter = 0; for (var i = 0; i < GMDContent.Content.Count(); i++) { if (!GMDContent.Content[i].Name.Contains("no_name")) { LabelEntries.Add(new LabelEntry { SectionID = i, Hash1 = ~Crc32.Create(GMDContent.Content[i].Name + GMDContent.Content[i].Name), Hash2 = ~Crc32.Create(GMDContent.Content[i].Name + GMDContent.Content[i].Name + GMDContent.Content[i].Name), LabelOffset = LabelOffset, ListLink = 0 }); LabelOffset += Encoding.ASCII.GetByteCount(GMDContent.Content[i].Name) + 1; var bucket = (byte)(~Crc32.Create(GMDContent.Content[i].Name) & 0xff); if (Buckets.ContainsKey(bucket)) { LabelEntries[Buckets[bucket]].ListLink = counter; Buckets[bucket] = counter; } else { Buckets.Add(bucket, counter); } counter++; } } //Create bucketList Blob var BucketBlob = new int[0x100]; if (LabelCount > 0) { var counter2 = 0; for (var i = 0; i < GMDContent.Content.Count(); i++) { if (!GMDContent.Content[i].Name.Contains("no_name")) { var bucket = (byte)(~Crc32.Create(GMDContent.Content[i].Name) & 0xff); if (BucketBlob[bucket] == 0) { BucketBlob[bucket] = (counter2 == 0) ? -1 : counter2; } counter2++; } } } //Create Header var Header = new Header { Magic = "GMD\0", Version = 0x00010302, Language = Language.ENGLISH, LabelCount = LabelCount, SectionCount = GMDContent.Content.Count(), LabelSize = LabelBlob.Length, SectionSize = TextBlob.Length, NameSize = Encoding.ASCII.GetByteCount(GMDContent.Name) }; //Write Stuff using (var bw = new BinaryWriterX(File.Create(filename))) { //Header bw.WriteStruct(Header); bw.Write(Encoding.ASCII.GetBytes(GMDContent.Name + "\0")); //Entries foreach (var entry in LabelEntries) { bw.WriteStruct(entry); } //BucketList if (LabelCount > 0) { foreach (var bucket in BucketBlob) { bw.Write(bucket); } } //Labels bw.Write(LabelBlob); //Text Sections bw.Write(TextBlob); } } }
public void Save(string filename, Platform platform, Game game) { //Get Text Section var TextBlob = Encoding.UTF8.GetBytes(GMDContent.Content.Aggregate("", (output, c) => output + c.Text.Replace("\r\n", "\xa").Replace("\xa", "\r\n") + "\0")); //XOR, if needed if (platform == Platform.CTR && game == Game.DD) { TextBlob = new BinaryReaderX(XOR.ReXOR(TextBlob, 0)).ReadAllBytes(); } //Get Label Blob var LabelBlob = Encoding.ASCII.GetBytes(GMDContent.Content.Aggregate("", (output, c) => output + (c.Name.Contains("no_name_") ? "" : c.Name + "\0"))); //Create LabelEntries var LabelEntries = new List <LabelEntry>(); var LabelOffset = 0; var LabelCount = GMDContent.Content.Count(c => !c.Name.Contains("no_name_")); for (var i = 0; i < GMDContent.Content.Count(); i++) { if (GMDContent.Content[i].Name.Contains("no_name_")) { continue; } LabelEntries.Add(new LabelEntry { SectionID = i, LabelOffset = LabelOffset + _firstLabelOffset }); LabelOffset += Encoding.ASCII.GetByteCount(GMDContent.Content[i].Name) + 1; } //Header FileHeader.LabelCount = LabelCount; FileHeader.SectionCount = GMDContent.Content.Count; FileHeader.LabelSize = LabelBlob.Length; FileHeader.SectionSize = TextBlob.Length; FileHeader.NameSize = Encoding.ASCII.GetByteCount(GMDContent.Name); //Write stuff using (var bw = new BinaryWriterX(File.Create(filename), GMDContent.ByteOrder)) { //Header bw.WriteStruct(FileHeader); bw.Write(Encoding.ASCII.GetBytes(GMDContent.Name + "\0")); //LabelEntries foreach (var entry in LabelEntries) { bw.WriteStruct(entry); } //Labels bw.Write(LabelBlob); //Text Sections bw.Write(TextBlob); } }
public GMD(Stream input) { using (var br = new BinaryReaderX(input)) { // Set endianess if (br.PeekString() == "\0DMG") { br.ByteOrder = ByteOrder = ByteOrder.BigEndian; } // Header Header = br.ReadStruct <Header>(); Name = br.ReadCStringA(); // Entries if (Header.Version == Versions.Version1) { EntriesV1 = br.ReadMultiple <EntryV1>((int)Header.LabelCount); } else if (Header.Version == Versions.Version2) { EntriesV2 = br.ReadMultiple <EntryV2>((int)Header.LabelCount); } // Unknown Version 2 Section if (Header.Version == Versions.Version2) { var bk = br.BaseStream.Position; var temp = br.ReadUInt32(); while (temp < 0x100000 || temp == 0xffffffff) { temp = br.ReadUInt32(); } br.BaseStream.Position -= 4; temp = br.ReadByte(); while (temp == 0) { temp = br.ReadByte(); } br.BaseStream.Position--; var unkSize = br.BaseStream.Position - bk; br.BaseStream.Position = bk; UnknownV2 = br.ReadBytes((int)unkSize); } // Labels var counter = 0; for (var i = 0; i < Header.LabelCount; i++) { if (Header.LabelSize > 0) { Names.Add(br.ReadCStringA()); } else { Names.Add("no_name_" + i.ToString("0000")); } counter = i; } // Text var text = br.ReadBytes((int)Header.SectionSize); // Text deobfuscation var xor = new XOR(Header.Version); IsXORed = XOR.IsXORed(new MemoryStream(text)); if (IsXORed) { text = xor.Deobfuscate(text); } using (var brt = new BinaryReaderX(new MemoryStream(text), ByteOrder)) { for (var i = 0; i < Header.SectionCount; i++) { var bk = brt.BaseStream.Position; var tmp = brt.ReadByte(); while (tmp != 0) { tmp = brt.ReadByte(); } var textSize = brt.BaseStream.Position - bk; brt.BaseStream.Position = bk; Labels.Add(new Label { Name = i < Header.LabelCount ? Names[i] : "no_name_" + counter.ToString("0000"), Text = brt.ReadString((int)textSize, Encoding.UTF8), TextID = i }); if (i >= Header.LabelCount) { counter++; } } } } }
public void Save(Stream output) { using (var bw = new BinaryWriterX(output, ByteOrder)) { bw.BaseStream.Position = HeaderLength + Header.NameSize + 1; // Section Entries if (Header.Version == Versions.Version1) { foreach (var entry in EntriesV1) { bw.WriteStruct(entry); } } else if (Header.Version == Versions.Version2) { foreach (var entry in EntriesV2) { bw.WriteStruct(entry); } } // Unknown Version 2 Section if (Header.Version == Versions.Version2) { bw.Write(UnknownV2); } // Labels uint labelSize = 0; for (var i = 0; i < Header.LabelCount; i++) { bw.WriteASCII(Names[i]); bw.Write((byte)0); labelSize += (uint)Names[i].Length + 1; } Header.LabelSize = labelSize; // Sections var textStart = bw.BaseStream.Position; var textS = new MemoryStream(); using (var textW = new BinaryWriterX(textS, true)) { foreach (var label in Labels) { textW.Write(Encoding.UTF8.GetBytes(label.Text)); textW.Write((byte)0); } } //ReXOR if needed, only for version 1 for now if (Header.Version == Versions.Version1 && IsXORed) { var xor = new XOR(Header.Version); var tmp = xor.Obfuscate(new BinaryReaderX(textS).ReadAllBytes()); textS.Position = 0; new BinaryWriterX(textS, true).Write(tmp); } bw.Write(new BinaryReaderX(textS).ReadAllBytes()); Header.SectionSize = (uint)(bw.BaseStream.Position - textStart); // Header bw.BaseStream.Position = 0; bw.WriteStruct(Header); bw.WriteASCII(Name); bw.Write((byte)0); } }