Example #1
0
        public static SARC Analyze(string path)
        {
            var sarc = new SARC
            {
                FileName  = Path.GetFileNameWithoutExtension(path),
                FilePath  = Path.GetDirectoryName(path),
                Extension = Path.GetExtension(path),
                valid     = true
            };

            using (var fs = File.OpenRead(path))
                using (var br = new BinaryReader(fs))
                {
                    sarc.Signature = new string(br.ReadChars(4));
                    if (sarc.Signature != "SARC")
                    {
                        sarc.valid = false;
                        return(sarc);
                    }
                    sarc.HeaderSize = br.ReadUInt16();
                    sarc.Endianness = br.ReadUInt16();
                    sarc.FileSize   = br.ReadUInt32();
                    sarc.DataOffset = br.ReadUInt32();
                    sarc.Unknown    = br.ReadUInt32();
                    sarc.SFat       = new SFAT
                    {
                        Signature  = new string(br.ReadChars(4)),
                        HeaderSize = br.ReadUInt16(),
                        EntryCount = br.ReadUInt16(),
                        HashMult   = br.ReadUInt32(),
                        Entries    = new List <SFATEntry>()
                    };
                    if (sarc.SFat.Signature != "SFAT")
                    {
                        sarc.valid = false;
                        return(sarc);
                    }
                    for (var i = 0; i < sarc.SFat.EntryCount; i++)
                    {
                        var s = new SFATEntry
                        {
                            FileNameHash   = br.ReadUInt32(),
                            FileNameOffset = br.ReadUInt32(),
                            FileDataStart  = br.ReadUInt32(),
                            FileDataEnd    = br.ReadUInt32()
                        };
                        sarc.SFat.Entries.Add(s);
                    }
                    sarc.SFnt = new SFNT
                    {
                        Signature    = new string(br.ReadChars(4)),
                        HeaderSize   = br.ReadUInt16(),
                        Unknown      = br.ReadUInt16(),
                        StringOffset = (uint)br.BaseStream.Position
                    };
                    if (sarc.SFnt.Signature != "SFNT")
                    {
                        sarc.valid = false;
                        return(sarc);
                    }
                }
            sarc.Data = File.ReadAllBytes(path);
            if (sarc.FileSize == sarc.Data.Length)
            {
                return(sarc);
            }

            sarc.valid = false;
            sarc.Data  = null;
            return(sarc);
        }
Example #2
0
        static void UpdateArchives(Options opts)
        {
            Util.Log("Testing Crypto Server...");
            var passed_selftest = NetworkUtils.TestCryptoServer(IPAddress.Parse(opts.InputIP));

            foreach (var country in country_list.Keys)
            {
                var country_dir = Path.Combine("data", country);
                var country_id  = country_list[country];
                Directory.CreateDirectory(country_dir);
                foreach (var archive in badge_filelist)
                {
                    var archive_path = Path.Combine(country_dir, archive);
                    var sarc_path    = Path.Combine(country_dir, Path.GetFileNameWithoutExtension(archive_path) + ".sarc");
                    var xml_path     = Path.Combine(country_dir, Path.GetFileNameWithoutExtension(archive_path) + ".xml");
                    var server_file  = string.Format(server, country_id, archive);
                    Util.Log($"{country} / {archive}...", false);
                    if (!File.Exists(archive_path))
                    {
                        Util.Log("Downloading...", false);
                        var arc = NetworkUtils.TryDownload(server_file);
                        if (arc != null)
                        {
                            File.WriteAllBytes(archive_path, arc);
                            if (File.Exists(sarc_path))
                            {
                                File.Delete(sarc_path);
                            }
                        }
                        else
                        {
                            Util.Log("Download failed");
                            continue;
                        }
                    }
                    else
                    {
                        var old     = File.ReadAllBytes(archive_path);
                        var new_arc = NetworkUtils.DownloadFirstBytes(server_file);
                        if (new_arc == null)
                        {
                            continue;
                        }
                        if (!(new_arc.SequenceEqual(old.Take(new_arc.Length))))
                        {
                            Util.Log("Updating...", false);
                            var arc = NetworkUtils.TryDownload(server_file);
                            if (arc != null)
                            {
                                File.WriteAllBytes(archive_path, arc);
                                if (File.Exists(sarc_path))
                                {
                                    File.Delete(sarc_path);
                                }
                            }
                            else
                            {
                                Util.Log("Update failed");
                                continue;
                            }
                        }
                    }

                    if (!File.Exists(sarc_path) && passed_selftest)
                    {
                        keep_log = true;
                        Util.Log("Decrypting...", false);
                        var dec_boss = NetworkUtils.TryDecryptBOSS(File.ReadAllBytes(archive_path), IPAddress.Parse(opts.InputIP));
                        if (dec_boss == null)
                        {
                            continue;
                        }
                        File.WriteAllBytes(sarc_path, dec_boss.Skip(0x296).ToArray());

                        sarc = SARC.Analyze(sarc_path);
                        if (!sarc.valid)
                        {
                            Util.Log($"Not a valid SARC. Maybe bad decryption...?");
                            passed_selftest = false;
                            File.Delete(sarc_path);
                            continue;
                        }
                    }
                    else if (!File.Exists(sarc_path))
                    {
                        Util.Log("Done");
                        continue;
                    }
                    else
                    {
                        sarc = SARC.Analyze(sarc_path);
                        if (!sarc.valid)
                        {
                            Util.Log("SARC file corrupted");
                            File.Delete(sarc_path);
                            continue;
                        }
                    }



                    Util.Log($"Extracting...");
                    var sarchashes = Util.DeserializeFile <SARCFileHashes>(xml_path) ?? new SARCFileHashes();


                    var data_dir = Path.Combine(country_dir, Path.GetFileNameWithoutExtension(archive_path), "files");
                    var decompressed_data_dir = Path.Combine(country_dir, Path.GetFileNameWithoutExtension(archive_path), "decompressed");
                    Directory.CreateDirectory(data_dir);
                    Directory.CreateDirectory(decompressed_data_dir);

                    foreach (var entry in sarc.SFat.Entries)
                    {
                        var path = Path.Combine(data_dir, sarc.GetFilePath(entry));
                        var decompressed_path = Path.Combine(decompressed_data_dir,
                                                             Path.ChangeExtension(sarc.GetFilePath(entry), null));

                        Directory.CreateDirectory(Path.GetDirectoryName(path));
                        Directory.CreateDirectory(Path.GetDirectoryName(decompressed_path));

                        var hashresult = sarchashes.IsHashEqual(sarc.GetFilePath(entry), sarc.GetFileHash(entry));
                        sarchashes.SetHash(sarc.GetFilePath(entry), sarc.GetFileHash(entry));
                        if (!File.Exists(path))
                        {
                            Util.Log(hashresult == SARCHashResult.NotFound
                                ? $"New {country} file: {Path.GetFileName(path)}"
                                : hashresult == SARCHashResult.Equal
                                    ? $"{country} file: {Path.GetFileName(path)} was deleted"
                                    : $"Updated {country} file: {Path.GetFileName(path)}");
                            WriteSARCFileData(opts, entry, country, path, decompressed_path);
                        }
                        else
                        {
                            if (hashresult != SARCHashResult.NotEqual)
                            {
                                continue;
                            }
                            Util.Log($"Updated {country} file: {Path.GetFileName(path)}");

                            //Can't do nothing for updated files,
                            //or the file will ALWAYS say its updated every run, not the intended result.
                            WriteSARCFileData(opts, entry, country, path, decompressed_path);
                        }
                    }
                    Util.Serialize(sarchashes, xml_path);
                    Util.Log($"{country} / {archive}...Extraction Complete");
                }
            }
        }