private void Open(string path) { if (Directory.Exists(path)) { foreach (string p in (new DirectoryInfo(path)).GetFiles().Select(f => f.FullName)) { Open(p); } foreach (string p in (new DirectoryInfo(path)).GetDirectories().Select(f => f.FullName)) { Open(p); } } else if (File.Exists(path)) { string ext = Path.GetExtension(path).ToLower(); if (ext == ".lz") { byte[] filedata = File.ReadAllBytes(path); string decpath = Path.GetDirectoryName(path) + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(path); if (filedata[0] == 0x13 && filedata[4] == 0x11) // "LZ13" { filedata = filedata.Skip(4).ToArray(); } else if (filedata[0] == 0x17 && filedata[4] == 0x11) // Fire Emblem Heroes "LZ17" { var xorkey = BitConverter.ToUInt32(filedata, 0) >> 8; xorkey *= 0x8083; for (var i = 8; i < filedata.Length; i += 0x4) { BitConverter.GetBytes(BitConverter.ToUInt32(filedata, i) ^ xorkey).CopyTo(filedata, i); xorkey ^= BitConverter.ToUInt32(filedata, i); } filedata = filedata.Skip(4).ToArray(); } else if (filedata[0] == 0x4 && (BitConverter.ToUInt32(filedata, 0) >> 8) == filedata.Length - 4) { var xorkey = BitConverter.ToUInt32(filedata, 0) >> 8; xorkey *= 0x8083; for (var i = 4; i < filedata.Length; i += 0x4) { BitConverter.GetBytes(BitConverter.ToUInt32(filedata, i) ^ xorkey).CopyTo(filedata, i); xorkey ^= BitConverter.ToUInt32(filedata, i); } filedata = filedata.Skip(4).ToArray(); if (BitConverter.ToUInt32(filedata, 0) == filedata.Length) { File.WriteAllBytes(decpath, filedata); AddLine(RTB_Output, string.Format("Successfully decompressed {0}.", Path.GetFileName(decpath))); if (File.Exists(decpath)) { Open(decpath); } } else { AddLine(RTB_Output, string.Format("Unable to automatically decompress {0}.", Path.GetFileName(path))); } return; } try { File.WriteAllBytes(decpath, LZ11Decompress(filedata)); AddLine(RTB_Output, string.Format("Successfully decompressed {0}.", Path.GetFileName(decpath))); } catch (Exception ex) { AddLine(RTB_Output, string.Format("Unable to automatically decompress {0}.", Path.GetFileName(path))); Console.WriteLine(ex.Message); } if (File.Exists(decpath)) { Open(decpath); } } else if (ext == ".bin") { byte[] filedata = File.ReadAllBytes(path); var outname = Path.GetDirectoryName(path) + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(path) + ".txt"; if (BitConverter.ToUInt32(filedata, 0) == filedata.Length && new string(filedata.Skip(0x20).Take(0xC).Select(c => (char)c).ToArray()) == "MESS_ARCHIVE") { string archive_name = ExtractFireEmblemMessageArchive(outname, filedata); AddLine(RTB_Output, string.Format("Successfully Extracted {0} ({1}).", archive_name, Path.GetFileName(path))); } else if (TryExtractFireEmblemHeroesMessageArchive(outname, filedata)) { AddLine(RTB_Output, string.Format("Successfully extracted Heroes Message Archive {0}", Path.GetFileName(path))); } } else if (ext == ".arc") { byte[] filedata = File.ReadAllBytes(path); if (BitConverter.ToUInt32(filedata, 0) == filedata.Length || BitConverter.ToUInt32(filedata, filedata.Length - 4) == 0x43524654) { ExtractFireEmblemArchive(Path.GetDirectoryName(path) + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(path) + Path.DirectorySeparatorChar, filedata); } } else if (ext == ".ctpk") { AddText(RTB_Output, string.Format("Extracting images from {0}...", Path.GetFileName(path))); Ctpk.Read(path); AddLine(RTB_Output, "Complete!"); } else if (ext == ".bch") { AddText(RTB_Output, string.Format("Extracting textures from {0}...", Path.GetFileName(path))); AddLine(RTB_Output, BCHTool.parseBCH(path) ? "Complete!" : "Failure!"); } else if (ext == ".txt") { string[] textfile = File.ReadAllLines(path); if (textfile.Length > 6 && textfile[0].StartsWith("MESS_ARCHIVE") && textfile[3] == "Message Name: Message" && textfile.Skip(6).All(s => s.Contains(": "))) { AddText(RTB_Output, string.Format("Rebuilding Message Archive from {0}...", Path.GetFileName(path))); string outname = Path.GetDirectoryName(path) + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(path) + ".bin"; byte[] arch = MakeFireEmblemMessageArchive(textfile); File.WriteAllBytes(outname, arch); AddLine(RTB_Output, "Complete!"); byte[] cmp = LZ11Compress(arch); byte[] cmp2 = new byte[cmp.Length + 4]; cmp2[0] = 0x13; Array.Copy(cmp, 0, cmp2, 4, cmp.Length); Array.Copy(cmp, 1, cmp2, 1, 3); File.WriteAllBytes(outname + ".lz", cmp2); } } } }
private void Open(string path) { if (Directory.Exists(path)) { foreach (string p in (new DirectoryInfo(path)).GetFiles().Select(f => f.FullName)) { Open(p); } foreach (string p in (new DirectoryInfo(path)).GetDirectories().Select(f => f.FullName)) { Open(p); } } else if (File.Exists(path)) { string ext = Path.GetExtension(path).ToLower(); var yaz0 = false; using (var fs = File.OpenRead(path)) { if (fs.Length > 4 && fs.ReadByte() == 'Y' && fs.ReadByte() == 'a' && fs.ReadByte() == 'z' && fs.ReadByte() == '0') { yaz0 = true; } } if ((ModifierKeys == Keys.Control) && (MessageBox.Show("Compress " + path + "?", "Prompt", MessageBoxButtons.YesNo, MessageBoxIcon.Asterisk) == DialogResult.Yes)) { var cmp = LZ11Compress(File.ReadAllBytes(path)); byte[] cmp2 = new byte[cmp.Length + 4]; cmp2[0] = 0x13; Array.Copy(cmp, 0, cmp2, 4, cmp.Length); Array.Copy(cmp, 1, cmp2, 1, 3); File.WriteAllBytes(path + ".lz", cmp2); AddLine(RTB_Output, string.Format("LZ13 compressed {0} to {1}", path, path + ".lz")); } else if (yaz0) { var cmp = File.ReadAllBytes(path); File.WriteAllBytes(path + ".dec", Decompress(cmp)); AddLine(RTB_Output, string.Format("Yaz0 decompressed {0}.", path)); } else if (ext == ".lz") { byte[] filedata = File.ReadAllBytes(path); string decpath = Path.GetDirectoryName(path) + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(path); if (filedata[0] == 0x13 && filedata[4] == 0x11) // "LZ13" { filedata = filedata.Skip(4).ToArray(); } else if (filedata[0] == 0x17 && filedata[4] == 0x11) // Fire Emblem Heroes "LZ17" { byte[] first4 = filedata.Take(4).ToArray(); var xorkey = BitConverter.ToUInt32(filedata, 0) >> 8; xorkey *= 0x8083; for (var i = 8; i < filedata.Length; i += 0x4) { BitConverter.GetBytes(BitConverter.ToUInt32(filedata, i) ^ xorkey).CopyTo(filedata, i); xorkey ^= BitConverter.ToUInt32(filedata, i); } filedata = filedata.Skip(4).ToArray(); byte[] output = LZ11Decompress(filedata); byte[] output2 = new byte[4 + output.Length]; first4.CopyTo(output2, 0); output.CopyTo(output2, 4); File.WriteAllBytes(decpath, output2); AddLine(RTB_Output, string.Format("Successfully decompressed {0}.", Path.GetFileName(decpath))); return; } else if (filedata[0] == 0x4 && (BitConverter.ToUInt32(filedata, 0) >> 8) == filedata.Length - 4) { var xorkey = BitConverter.ToUInt32(filedata, 0) >> 8; xorkey *= 0x8083; for (var i = 4; i < filedata.Length; i += 0x4) { BitConverter.GetBytes(BitConverter.ToUInt32(filedata, i) ^ xorkey).CopyTo(filedata, i); xorkey ^= BitConverter.ToUInt32(filedata, i); } filedata = filedata.Skip(4).ToArray(); if (BitConverter.ToUInt32(filedata, 0) == filedata.Length) { File.WriteAllBytes(decpath, filedata); AddLine(RTB_Output, string.Format("Successfully decompressed {0}.", Path.GetFileName(decpath))); if (File.Exists(decpath)) { Open(decpath); } } else { AddLine(RTB_Output, string.Format("Unable to automatically decompress {0}.", Path.GetFileName(path))); } return; } try { File.WriteAllBytes(decpath, LZ11Decompress(filedata)); AddLine(RTB_Output, string.Format("Successfully decompressed {0}.", Path.GetFileName(decpath))); } catch (Exception ex) { AddLine(RTB_Output, string.Format("Unable to automatically decompress {0}.", Path.GetFileName(path))); Console.WriteLine(ex.Message); } if (File.Exists(decpath)) { Open(decpath); } } else if (ext == ".bin") { byte[] filedata = File.ReadAllBytes(path); var xorkey = BitConverter.ToUInt32(filedata, 0) >> 8; xorkey *= 0x8083; var lz = filedata.Skip(4).ToArray(); lz = LZ11Compress(lz); var output = new byte[4 + lz.Length + (lz.Length % 4 == 0?0:4 - lz.Length % 4)]; filedata.Take(4).ToArray().CopyTo(output, 0); lz.CopyTo(output, 4); for (var i = 8; i < output.Length; i += 0x4) { BitConverter.GetBytes(BitConverter.ToUInt32(output, i) ^ xorkey).CopyTo(output, i); xorkey = BitConverter.ToUInt32(output, i); } File.WriteAllBytes(Path.GetDirectoryName(path) + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(path) + ".bin.lz", output); AddLine(RTB_Output, string.Format("Successfully Compressed {0}.", Path.GetFileName(path))); /*var outname = Path.GetDirectoryName(path) + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(path) + ".txt"; * if (BitConverter.ToUInt32(filedata, 0) == filedata.Length && * new string(filedata.Skip(0x20).Take(0xC).Select(c => (char)c).ToArray()) == "MESS_ARCHIVE") * { * string archive_name = ExtractFireEmblemMessageArchive(outname, filedata); * AddLine(RTB_Output, string.Format("Successfully Extracted {0} ({1}).", archive_name, Path.GetFileName(path))); * } * else if (TryExtractFireEmblemHeroesMessageArchive(outname, filedata)) * { * AddLine(RTB_Output, string.Format("Successfully extracted Heroes Message Archive {0}", Path.GetFileName(path))); * } */ } else if (ext == ".arc") { byte[] filedata = File.ReadAllBytes(path); if (BitConverter.ToUInt32(filedata, 0) == filedata.Length || BitConverter.ToUInt32(filedata, filedata.Length - 4) == 0x43524654) { ExtractFireEmblemArchive(Path.GetDirectoryName(path) + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(path) + Path.DirectorySeparatorChar, filedata); } } else if (ext == ".ctpk") { AddText(RTB_Output, string.Format("Extracting images from {0}...", Path.GetFileName(path))); Ctpk.Read(path); AddLine(RTB_Output, "Complete!"); } else if (ext == ".bch") { AddText(RTB_Output, string.Format("Extracting textures from {0}...", Path.GetFileName(path))); AddLine(RTB_Output, BCHTool.parseBCH(path) ? "Complete!" : "Failure!"); } else if (ext == ".bfnt") { AddText(RTB_Output, string.Format("Extracting font textures from {0}...", Path.GetFileName(path))); var bfnt = File.ReadAllBytes(path); if (BitConverter.ToUInt16(bfnt, 0x20) != 0x30) { AddLine(RTB_Output, "Failure!"); } else { var w = BitConverter.ToUInt16(bfnt, 0x10); var h = BitConverter.ToUInt16(bfnt, 0x12); var texsize = BitConverter.ToUInt32(bfnt, 0x14); var texofs = BitConverter.ToUInt32(bfnt, 0x24); if (texsize != (w * h) / 2) { AddLine(RTB_Output, "Failure!"); } else { var num_textures = BitConverter.ToUInt16(bfnt, 0x1A); for (var i = 0; i < num_textures; i++) { var dat = new byte[texsize]; Array.Copy(bfnt, texofs + texsize * i, dat, 0, texsize); var outname = Path.GetDirectoryName(path) + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(path) + "_" + i + ".png";; using (var bmp = CTR.TextureUtil.DecodeByteArray(dat, w, h, CTR.TextureFormat.L4)) bmp.Save(outname, ImageFormat.Png); } AddLine(RTB_Output, "Complete!"); } } } else if (ext == ".txt") { string[] textfile = File.ReadAllLines(path); if (textfile.Length > 6 && textfile[0].StartsWith("MESS_ARCHIVE") && textfile[3] == "Message Name: Message" && textfile.Skip(6).All(s => s.Contains(": "))) { AddText(RTB_Output, string.Format("Rebuilding Message Archive from {0}...", Path.GetFileName(path))); string outname = Path.GetDirectoryName(path) + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(path) + ".bin"; byte[] arch = MakeFireEmblemMessageArchive(textfile); File.WriteAllBytes(outname, arch); AddLine(RTB_Output, "Complete!"); byte[] cmp = LZ11Compress(arch); byte[] cmp2 = new byte[cmp.Length + 4]; cmp2[0] = 0x13; Array.Copy(cmp, 0, cmp2, 4, cmp.Length); Array.Copy(cmp, 1, cmp2, 1, 3); File.WriteAllBytes(outname + ".lz", cmp2); } } } }