Exemple #1
0
    public static void Extract(string tfaiFile, string tfafFile, string targetDir)
    {
        Console.WriteLine("Extracting to {0}", targetDir);

        // Read the index file first
        var entries = ArchiveIndexReader.ReadIndex(tfaiFile);

        using (var stream = new FileStream(tfafFile, FileMode.Open))
        {
            foreach (var entry in entries)
            {
                Console.Write("Extracting {0}...", entry.Path);

                var fullPath = Path.Combine(targetDir, entry.Path);
                if (entry.Directory)
                {
                    Directory.CreateDirectory(fullPath);
                }
                else
                {
                    using (var outStream = new FileStream(fullPath, FileMode.Create))
                    {
                        byte[] buffer = new byte[entry.Size];
                        stream.Read(buffer, 0, buffer.Length);
                        outStream.Write(buffer, 0, buffer.Length);
                    }
                }

                Console.WriteLine();
            }
        }
    }
    public static SaveGameFile Load(string basePath, string currentSaveDir)
    {
        var result = new SaveGameFile();

        var indexPath = basePath + ".tfai";

        var archiveIndex = ArchiveIndexReader.ReadIndex(indexPath);

        using var dataStream = new FileStream(basePath + ".tfaf", FileMode.Open);

        byte[] gameStateData   = null;
        byte[] spellPacketData = null;
        byte[] partyConfigData = null;
        byte[] mapFleeData     = null;
        byte[] uiStateData     = null;

        bool GrabData(ArchiveIndexEntry entry, string filename, ref byte[] bufferOut)
        {
            if (entry.Path == filename)
            {
                if (bufferOut != null)
                {
                    throw new CorruptSaveException($"File {filename} exists twice in the save game!");
                }

                var buffer = new byte[entry.Size];
                dataStream.Read(buffer);
                if (Debugger.IsAttached)
                {
                    var fullPath = Path.Join(currentSaveDir, entry.Path);
                    File.WriteAllBytes(fullPath, buffer);
                }

                bufferOut = buffer;
                return(true);
            }

            return(false);
        }

        foreach (var entry in archiveIndex)
        {
            var fullPath = Path.Join(currentSaveDir, entry.Path);

            if (entry.Directory)
            {
                Directory.CreateDirectory(fullPath);
                continue;
            }

            if (GrabData(entry, MainStateFile, ref gameStateData) ||
                GrabData(entry, ActionSequencesSpellsFile, ref spellPacketData) ||
                GrabData(entry, PartyConfigFile, ref partyConfigData) ||
                GrabData(entry, MapFleeFile, ref mapFleeData) ||
                GrabData(entry, UiStateFile, ref uiStateData))
            {
                continue;
            }

            CopyStreamToFile(dataStream, entry.Size, fullPath);
        }

        if (gameStateData == null)
        {
            throw new CorruptSaveException($"Save file is missing {MainStateFile}");
        }

        if (spellPacketData == null)
        {
            throw new CorruptSaveException($"Save file is missing {ActionSequencesSpellsFile}");
        }

        if (partyConfigData == null)
        {
            throw new CorruptSaveException($"Save file is missing {PartyConfigFile}");
        }

        if (mapFleeData == null)
        {
            throw new CorruptSaveException($"Save file is missing {MapFleeFile}");
        }

        if (uiStateData == null)
        {
            throw new CorruptSaveException($"Save file is missing {UiStateFile}");
        }

        result.GameState = SavedGameState.Load(gameStateData, spellPacketData, partyConfigData, mapFleeData);

        result.UiState = SavedUiState.Load(uiStateData);

        // Load the optional Co8 data if it exists
        var co8Path = basePath + ".co8";

        if (File.Exists(co8Path))
        {
            result.Co8State = SavedCo8State.Load(co8Path);
        }

        return(result);
    }