Пример #1
0
        public EndianIO GetResourceIO(int patchFileNumber)
        {
            var resPath = ResourceFilePath(patchFileNumber);

            if (!resourceIOs.ContainsKey(resPath))
            {
                if (!File.Exists(resPath))
                {
                    return(null);
                }

                var io = new EndianIO(resPath, FileMode.Open);
                io.Stream.Position = 0;
                var magic = io.Reader.ReadUInt32();
                if ((magic & 0xFFFFFF00) != 0x52455300)
                {
                    io.Close();
                    return(null);
                }

                resourceIOs.Add(resPath, io);
            }

            return(resourceIOs[resPath]);
        }
Пример #2
0
        public void Close()
        {
            if (indexIO != null)
            {
                indexIO.Close();
                indexIO = null;
            }
            if (resourceIOs != null)
            {
                foreach (var kvp in resourceIOs)
                {
                    kvp.Value.Close();
                }

                resourceIOs.Clear();
                resourceIOs = null;
            }
        }
Пример #3
0
        public void Rebuild(string destResourceFile, string replaceFromFolder = "", bool keepCompressed = false)
        {
            if (File.Exists(destResourceFile))
            {
                File.Delete(destResourceFile);
            }

            if (!String.IsNullOrEmpty(replaceFromFolder))
            {
                replaceFromFolder = replaceFromFolder.Replace("/", "\\");
                if (!replaceFromFolder.EndsWith("\\"))
                {
                    replaceFromFolder += "\\";
                }
            }

            var destResources = new EndianIO(destResourceFile, FileMode.CreateNew);

            byte[] header = { Header_Version, 0x53, 0x45, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
            if (PatchFileNumber > 0)
            {
                header = new byte[] { Header_Version, 0x53, 0x45, 0x52 }
            }
            ;                                                            // patch files start at 0x4 instead

            destResources.Writer.Write(header);

            var addedFiles = new List <string>();

            foreach (var file in Entries)
            {
                var replacePath = (String.IsNullOrEmpty(replaceFromFolder) ? String.Empty : Path.Combine(replaceFromFolder, file.GetFullName()));
                if (File.Exists(replacePath + ";" + file.FileType))
                {
                    replacePath += ";" + file.FileType;
                }

                bool isReplacing = !string.IsNullOrEmpty(replaceFromFolder) && File.Exists(replacePath);

                if (file.PatchFileNumber != PatchFileNumber && !isReplacing)
                {
                    continue; // file is located in a different patch resource and we aren't replacing it, so skip it
                }
                bool needToPad = destResources.Stream.Length % 0x10 != 0;
                if (PatchFileNumber > 0 && destResources.Stream.Length == 4)
                {
                    needToPad = false;                                        // for some reason patch files start at 0x4 instead of 0x10
                }
                if (file.IsCompressed && !isReplacing && PatchFileNumber > 0) // compressed files not padded in patch files?
                {
                    needToPad = false;
                }

                if (needToPad)
                {
                    long numPadding = 0x10 - (destResources.Stream.Length % 0x10);
                    destResources.Stream.SetLength(destResources.Stream.Length + numPadding);
                }

                if (file.Size <= 0 && file.CompressedSize <= 0)
                {
                    // patch indexes have offsets for 0-byte files set to 0, but in normal indexes it's the current resource file length
                    file.Offset = PatchFileNumber > 0 ? 0 : destResources.Stream.Length;
                    continue;
                }

                var offset = destResources.Stream.Length;
                destResources.Stream.Position = offset;

                if (isReplacing)
                {
                    file.PatchFileNumber = PatchFileNumber;

                    addedFiles.Add(replacePath);
                    using (var fs = File.OpenRead(replacePath))
                        file.CompressedSize = file.Size = (int)Utility.StreamCopy(destResources.Stream, fs, 40960, fs.Length);
                }
                else
                {
                    file.CompressedSize = (int)CopyEntryDataToStream(file, destResources.Stream, !keepCompressed);
                }

                file.Offset = offset;
            }

            // now add any files that weren't replaced
            if (!String.IsNullOrEmpty(replaceFromFolder))
            {
                addFilesFromFolder(replaceFromFolder, replaceFromFolder, destResources, ref addedFiles);
            }

            // read the fileIds.txt file if it exists, and set the IDs
            var idFile = Path.Combine(replaceFromFolder, "fileIds.txt");

            if (File.Exists(idFile))
            {
                var lines = File.ReadAllLines(idFile);
                foreach (var line in lines)
                {
                    if (String.IsNullOrEmpty(line.Trim()))
                    {
                        continue;
                    }

                    var sepIdx = line.LastIndexOf('=');
                    if (sepIdx < 0)
                    {
                        continue; // todo: warn user?
                    }
                    var fileName = line.Substring(0, sepIdx).Trim();
                    var fileId   = line.Substring(sepIdx + 1).Trim();
                    int id       = -1;
                    if (!int.TryParse(fileId, out id))
                    {
                        Console.WriteLine($"Warning: file {fileName} defined in fileIds.txt but has invalid id!");
                        continue;
                    }

                    var file = Entries.Find(s => s.GetFullName() == fileName);
                    if (file == null)
                    {
                        file = Entries.Find(s => s.GetFullName().Replace("\\", "/") == fileName);
                    }

                    if (file != null)
                    {
                        file.ID = id;
                    }
                    else
                    {
                        Console.WriteLine($"Warning: file {fileName} defined in fileIds.txt but doesn't exist?");
                    }
                }
            }

            destResources.Close();
            Save();
        }