예제 #1
0
        private static void BackupAndPlaceFiles(Language language)
        {
            ReadOnlyCollection <SWFile> swFiles          = SWFileManager.GetFiles();
            ILookup <Type, SWFile>      swFileTypeLookup = swFiles.ToLookup(f => f.GetType());
            IEnumerable <string>        archives         = swFileTypeLookup[typeof(ArchivedSWFile)].Select(f => f.Path).Union(swFileTypeLookup[typeof(PatchedSWFile)].Select(f => f.Path));
            IEnumerable <string>        otherSWFiles     = swFileTypeLookup[typeof(SWFile)].Select(f => f.Path + Path.GetFileName(f.PathD));
            IEnumerable <string>        translationFiles = archives.Distinct().Union(otherSWFiles);

            foreach (string path in translationFiles)
            {
                string originalFilePath    = Path.Combine(UserSettings.GamePath, path);
                string translationFilePath = Path.Combine(language.Path, path);
                string backupFilePath      = Path.Combine(language.BackupPath, path);

                BackupAndPlaceFile(originalFilePath, translationFilePath, backupFilePath);
            }
        }
예제 #2
0
        private static bool IsTranslationOutdatedOrMissing(Language language)
        {
            if (Methods.IsTranslationOutdated(language))
            {
                return(true);
            }

            ReadOnlyCollection <SWFile> swFiles              = SWFileManager.GetFiles();
            ILookup <Type, SWFile>      things               = swFiles.ToLookup(f => f.GetType());
            IEnumerable <string>        archivesPaths        = things[typeof(ArchivedSWFile)].Select(f => f.Path).Union(things[typeof(PatchedSWFile)].Select(f => f.Path));
            IEnumerable <string>        otherSWFilesPaths    = things[typeof(SWFile)].Select(f => f.Path + Path.GetFileName(f.PathD));
            IEnumerable <string>        translationFilePaths = archivesPaths.Distinct().Union(otherSWFilesPaths).Select(f => Path.Combine(language.Path, f));

            foreach (string path in translationFilePaths)
            {
                if (!File.Exists(path))
                {
                    return(true);
                }
            }

            return(false);
        }
예제 #3
0
        private void Worker_DoWork(object sender, DoWorkEventArgs e)
        {
            Logger.Debug(Methods.MethodFullName("Patcher", Thread.CurrentThread.ManagedThreadId.ToString(), this.Language.ToString()));

            this.CurrentState = State.Load;
            IEnumerable <ArchivedSWFile> archivedSWFiles = SWFileManager.GetFiles().OfType <ArchivedSWFile>();
            string regionFldr        = this.Language.ApplyingRegionFolder == "jpc" ? "jp" : this.Language.ApplyingRegionFolder;
            string datasArchivesPath = Urls.TranslationGitHubHome + regionFldr + '/' + Strings.IniName.DatasArchives;

            Logger.Debug(Methods.MethodFullName(System.Reflection.MethodBase.GetCurrentMethod(), datasArchivesPath));
            Dictionary <string, string> passwordDictionary = LoadPasswords(datasArchivesPath);
            int archivedSWFilesCount = archivedSWFiles.Count();
            var archives             = archivedSWFiles.Select(f => f.Path).Distinct().ToDictionary(p => p, p =>
            {
                string archivePath = Path.Combine(UserSettings.GamePath, p);
                Logger.Info($"Loading archive=[{archivePath}]");
                byte[] fileBytes = File.ReadAllBytes(archivePath);
                var xms          = new XorMemoryStream(fileBytes, SecretByte);
                return(ZipFile.Read(xms));
            });

            this.CurrentState = State.Patch;
            int count = 1;

            foreach (ArchivedSWFile archivedSWFile in archivedSWFiles)
            {
                if (this.Worker.CancellationPending)
                {
                    e.Cancel = true;
                    return;
                }
                this.Worker.ReportProgress(count++ == archivedSWFilesCount ? int.MaxValue : Convert.ToInt32(((double)count / archivedSWFilesCount) * int.MaxValue));

                string archiveFileNameWithoutExtension = Path.GetFileNameWithoutExtension(archivedSWFile.Path);
                string archivePassword = null;

                if (passwordDictionary.ContainsKey(archiveFileNameWithoutExtension))
                {
                    archivePassword = passwordDictionary[archiveFileNameWithoutExtension];
                }

                Logger.Info($"Patching file=[{archivedSWFile.PathA}] archive=[{archivedSWFile.Path}]");
                if (archivedSWFile is PatchedSWFile patchedSWFile)
                {
                    MemoryStream ms     = Methods.GetZippedFileStream(archives[patchedSWFile.Path], patchedSWFile.PathA, archivePassword);
                    MemoryStream msDest = new MemoryStream();

                    string[] fullFormatArray = patchedSWFile.Format.Split(' ');
                    int      idIndex         = Convert.ToInt32(fullFormatArray[0]);
                    string   countFormat     = fullFormatArray[1];
                    string[] formatArray     = fullFormatArray.Skip(2).ToArray(); // skip idIndex and countFormat

                    #region Patching the File

                    ulong  dataCount  = 0;
                    ulong  dataSum    = 0;
                    ushort hashLength = 32;
                    byte[] hash       = new byte[hashLength];
                    int    lineCount  = 0;

                    for (int i = 0; i < formatArray.Length; i++)
                    {
                        if (formatArray[i] == "len")
                        {
                            lineCount++;
                            i++;
                        }
                    }

                    Dictionary <ulong, string[]> inputTable = this.ReadInputFile(patchedSWFile.Data, lineCount, idIndex);

                    using (var br = new BinaryReader(ms))
                        using (var bw = new BinaryWriter(msDest, new UTF8Encoding(false, true), true))
                        {
                            switch (countFormat)
                            {
                            case "1":
                                dataCount = br.ReadByte();
                                bw.Write(Convert.ToByte(dataCount));
                                break;

                            case "2":
                                dataCount = br.ReadUInt16();
                                bw.Write(Convert.ToUInt16(dataCount));
                                break;

                            case "4":
                                dataCount = br.ReadUInt32();
                                bw.Write(Convert.ToUInt32(dataCount));
                                break;

                            case "8":
                                dataCount = br.ReadUInt64();
                                bw.Write(Convert.ToUInt64(dataCount));
                                break;
                            }
                            ulong value = 0;

                            for (ulong i = 0; i < dataCount; i++)
                            {
                                if (this.Worker.CancellationPending)
                                {
                                    e.Cancel = true;
                                    break;
                                }

                                #region Object Reading

                                object[] current = new object[formatArray.Length];
                                for (int j = 0; j < formatArray.Length; j++)
                                {
                                    if (this.Worker.CancellationPending)
                                    {
                                        e.Cancel = true;
                                        break;
                                    }

                                    switch (formatArray[j])
                                    {
                                    case "1":
                                        current[j] = Convert.ToByte(br.ReadByte());
                                        break;

                                    case "2":
                                        current[j] = Convert.ToUInt16(br.ReadUInt16());
                                        break;

                                    case "4":
                                        current[j] = Convert.ToUInt32(br.ReadUInt32());
                                        break;

                                    case "8":
                                        current[j] = Convert.ToUInt64(br.ReadUInt64());
                                        break;

                                    case "len":
                                        switch (formatArray[++j])
                                        {
                                        case "1":
                                            value      = br.ReadByte();
                                            current[j] = Convert.ToByte(br.ReadByte());
                                            break;

                                        case "2":
                                            value      = br.ReadUInt16();
                                            current[j] = Convert.ToUInt16(value);
                                            break;

                                        case "4":
                                            value      = br.ReadUInt32();
                                            current[j] = Convert.ToUInt32(value);
                                            break;

                                        case "8":
                                            value      = br.ReadUInt64();
                                            current[j] = Convert.ToUInt64(value);
                                            break;
                                        }
                                        ulong  strBytesLength = value * 2;
                                        byte[] strBytes       = new byte[strBytesLength];
                                        current[j] = strBytes;

                                        for (ulong k = 0; k < strBytesLength; k++)
                                        {
                                            strBytes[k] = br.ReadByte();
                                        }
                                        break;
                                    }
                                }

                                #endregion Object Reading

                                #region Object Writing

                                int lenPosition = 0;
                                for (int j = 0; j < formatArray.Length; j++)
                                {
                                    if (this.Worker.CancellationPending)
                                    {
                                        e.Cancel = true;
                                        break;
                                    }

                                    switch (formatArray[j])
                                    {
                                    case "1":
                                        value = Convert.ToByte(current[j]);
                                        bw.Write(Convert.ToByte(value));
                                        break;

                                    case "2":
                                        value = Convert.ToUInt16(current[j]);
                                        bw.Write(Convert.ToUInt16(value));
                                        break;

                                    case "4":
                                        value = Convert.ToUInt32(current[j]);
                                        bw.Write(Convert.ToUInt32(value));
                                        break;

                                    case "8":
                                        value = Convert.ToUInt64(current[j]);
                                        bw.Write(Convert.ToUInt64(value));
                                        break;

                                    case "len":
                                        byte[] strBytes = null;
                                        j++;
                                        ulong id = Convert.ToUInt64(current[idIndex]);
                                        if (inputTable.ContainsKey(id))
                                        {
                                            strBytes = Encoding.Unicode.GetBytes(inputTable[id][lenPosition++]);
                                        }
                                        else
                                        {
                                            strBytes = current[j] as byte[];
                                        }
                                        value = Convert.ToUInt64(strBytes.Length / 2);

                                        switch (formatArray[j])
                                        {
                                        case "1":
                                            bw.Write(Convert.ToByte(value));
                                            break;

                                        case "2":
                                            bw.Write(Convert.ToUInt16(value));
                                            break;

                                        case "4":
                                            bw.Write(Convert.ToUInt32(value));
                                            break;

                                        case "8":
                                            bw.Write(Convert.ToUInt64(value));
                                            break;
                                        }

                                        foreach (byte b in strBytes)
                                        {
                                            dataSum += b;
                                            bw.Write(b);
                                        }
                                        break;
                                    }

                                    dataSum += value;
                                }

                                #endregion Object Writing
                            }

                            bw.Write(hashLength);
                            string hashString = GetMD5(Convert.ToString(dataSum));
                            for (int i = 0; i < hashLength; i++)
                            {
                                hash[i] = Convert.ToByte(hashString[i]);
                            }

                            bw.Write(hash);
                        }

                    #endregion Patching the File

                    Methods.ZipFileStream(archives[patchedSWFile.Path], patchedSWFile.PathA, msDest, archivePassword);
                }
                else
                {
                    var ms = new MemoryStream(archivedSWFile.Data);

                    if (Path.GetExtension(archivedSWFile.PathD) == ".zip")
                    {
                        Methods.AddZipToZip(archives[archivedSWFile.Path], archivedSWFile.PathA, ms, archivePassword);
                    }
                    else
                    {
                        Methods.ZipFileStream(archives[archivedSWFile.Path], archivedSWFile.PathA, ms, archivePassword);
                    }
                }
            }

            this.CurrentState = State.Save;
            foreach (KeyValuePair <string, ZipFile> archive in archives)
            {
                if (this.Worker.CancellationPending)
                {
                    e.Cancel = true;
                    return;
                }

                string  zipFileName          = archive.Key;
                ZipFile zipFile              = archive.Value;
                string  archivePath          = Path.Combine(this.Language.Path, zipFileName);
                string  archivePathDirectory = Path.GetDirectoryName(archivePath);

                Directory.CreateDirectory(archivePathDirectory);

                //Dirty af but will prevent "Not a valid Win32 FileTime" error
                foreach (ZipEntry ze in zipFile.Entries)
                {
                    ze.ModifiedTime = DateTime.Now;
                }

                using (var fs = new MemoryStream())
                {
                    zipFile.Save(fs);
                    byte[] buffer = fs.ToArray();
                    zipFile.Dispose(); // TODO: using () { }

                    for (int i = 0; i < buffer.Length; i++)
                    {
                        buffer[i] ^= SecretByte;
                    }

                    File.WriteAllBytes(archivePath, buffer);
                }
            }

            /*
             * Disabled for now since it's useless
             *
             * if (UserSettings.WantToPatchExe)
             * {
             *  this.CurrentState = State.ExePatch;
             *
             *  string regionId = this.Language.ApplyingRegionId == "jpc" ? "jp" : this.Language.ApplyingRegionId;
             *  string regionFolder = this.Language.ApplyingRegionFolder == "jpc" ? "jp" : this.Language.ApplyingRegionFolder;
             *  string gameExePath = Path.Combine(UserSettings.GamePath, Methods.GetGameExeName(regionId));
             *  byte[] gameExeBytes = File.ReadAllBytes(gameExePath);
             *  string gameExePatchedPath = Path.Combine(UserSettings.PatcherPath, regionFolder, Methods.GetGameExeName(regionId));
             *
             *  Methods.PatchExeFile(gameExeBytes, gameExePatchedPath, Urls.TranslationGitHubHome + regionFolder + '/' + Strings.IniName.BytesToPatch);
             * }
             */
        }