public void UnexpectedFileTypeException_CallConstructorWithExpectedTypeName_HasCorrectMessage()
        {
            var testFileTypeName = "TestFileType";
            var exception        = new UnexpectedFileTypeException(testFileTypeName);

            Assert.NotEmpty(exception.Message);
            Assert.Equal(testFileTypeName, exception.ExpectedTypeName);
        }
        public void UnexpectedFileTypeException_CallConstructorWithExpectedTypeNameAndMessage_HasCorrectMessage()
        {
            var testFileTypeName = "AnotherTestFileType";
            var testMessage      = "This is a test of the message.";
            var exception        = new UnexpectedFileTypeException(testFileTypeName, testMessage);

            Assert.Equal(testMessage, exception.Message);
            Assert.Equal(testFileTypeName, exception.ExpectedTypeName);
        }
Esempio n. 3
0
        /// <summary>
        ///  Extracts the screen script information.
        /// </summary>
        /// <param name="stream">The stream to extract the screen script from.</param>
        /// <param name="fileName">The path or name of the screen script file being extracted.</param>
        /// <returns>The extracted <see cref="FesScreen"/> information.</returns>
        ///
        /// <exception cref="ArgumentNullException">
        ///  <paramref name="stream"/> or <paramref name="fileName"/> is null.
        /// </exception>
        /// <exception cref="ObjectDisposedException">
        ///  The <paramref name="stream"/> is closed.
        /// </exception>
        public static FesScreen Extract(Stream stream, string fileName)
        {
            BinaryReader reader = new BinaryReader(stream);
            FESHDR       hdr    = reader.ReadUnmanaged <FESHDR>();

            UnexpectedFileTypeException.ThrowIfInvalid(hdr.Signature, FESHDR.ExpectedSignature);

            byte[] scriptData = Zlib.Decompress(reader, hdr.CompressedLength, hdr.DecompressedLength);

            /*byte[] compressed = reader.ReadBytes(hdr.CompressedLength);
             * byte[] decompressed = new byte[hdr.DecompressedLength];
             * int decompressedLength = hdr.DecompressedLength;
             * Zlib.Uncompress(decompressed, ref decompressedLength, compressed, hdr.CompressedLength);*/

            string[] lines;
            using (MemoryStream ms = new MemoryStream(scriptData))
                using (StreamReader sr = new StreamReader(ms, CatUtils.ShiftJIS))
                    lines = sr.ReadLinesToEnd();

            return(new FesScreen(fileName, lines));
        }
        /// <summary>
        ///  Extracts the scene script information.
        /// </summary>
        /// <param name="stream">The stream to extract the scene script from.</param>
        /// <param name="fileName">The path or name of the scene script file being extracted.</param>
        /// <returns>The extracted <see cref="CstScene"/> information.</returns>
        ///
        /// <exception cref="ArgumentNullException">
        ///  <paramref name="stream"/> or <paramref name="fileName"/> is null.
        /// </exception>
        /// <exception cref="ObjectDisposedException">
        ///  The <paramref name="stream"/> is closed.
        /// </exception>
        public static CstScene Extract(Stream stream, string fileName)
        {
            BinaryReader reader = new BinaryReader(stream);
            CATSCENEHDR  hdr    = reader.ReadUnmanaged <CATSCENEHDR>();

            UnexpectedFileTypeException.ThrowIfInvalid(hdr.Signature, CATSCENEHDR.ExpectedSignature);

            byte[] scriptData = Zlib.Decompress(reader, hdr.CompressedLength, hdr.DecompressedLength);

            /*byte[] compressed = reader.ReadBytes(hdr.CompressedLength);
             * byte[] decompressed = new byte[hdr.DecompressedLength];
             * int decompressedLength = hdr.DecompressedLength;
             * Zlib.Uncompress(decompressed, ref decompressedLength, compressed, hdr.CompressedLength);*/

            SCRIPTLINE[] lines;

            using (var ms = new MemoryStream(scriptData))
                lines = ReadScript(ms);

            return(new CstScene(fileName, lines));
        }
        /// <summary>
        ///  Extracts the ANM animation from an ANM file stream.
        /// </summary>
        /// <param name="stream">The stream to extract the ANM from.</param>
        /// <param name="fileName">The path or name of the ANM file being extracted.</param>
        /// <returns>The extracted ANM animation.</returns>
        ///
        /// <exception cref="ArgumentNullException">
        ///  <paramref name="stream"/> or <paramref name="fileName"/> is null.
        /// </exception>
        /// <exception cref="ArgumentException">
        ///  The <paramref name="stream"/> is closed.
        /// </exception>
        public static AnmAnimation Extract(Stream stream, string fileName)
        {
            if (fileName == null)
            {
                throw new ArgumentNullException(nameof(fileName));
            }
            BinaryReader reader = new BinaryReader(stream);

            ANMHDR hdr = reader.ReadUnmanaged <ANMHDR>();

            UnexpectedFileTypeException.ThrowIfInvalid(hdr.Signature, ANMHDR.ExpectedSignature);

            reader.ReadBytes(20);             // Unused (?)

            ANMLINE[] frames = new ANMLINE[hdr.LineCount];
            for (int i = 0; i < hdr.LineCount; i++)
            {
                frames[i] = reader.ReadUnmanaged <ANMLINE>();
            }

            return(new AnmAnimation(Path.GetFileName(fileName), hdr, frames));
        }
        /// <summary>
        ///  Decrypts the KIFINT archives using the known archive type, install directory, and name of executable with
        ///  the V_CODE2 used to decrypt.
        /// </summary>
        /// <param name="type">The type of archive to look for and decrypt.</param>
        /// <param name="stream">The stream to the open KIFINT archive.</param>
        /// <param name="installDir">The installation directory for both the archives and executable.</param>
        /// <param name="exePath">The path to the executable to extract the V_CODE2 key from.</param>
        /// <returns>The <see cref="KifintLookup"/> merged with all loaded archives.</returns>
        ///
        /// <exception cref="ArgumentNullException">
        ///  <paramref name="stream"/>, <paramref name="kifintPath"/>, or <paramref name="exePath"/> is null.
        /// </exception>
        /// <exception cref="ObjectDisposedException">
        ///  The <paramref name="stream"/> is closed.
        /// </exception>
        private static KifintArchive LoadLookup(KifintType type, Stream stream, string kifintPath, string vcode2,
                                                KifintProgressArgs progress, KifintProgressCallback callback)
        {
            if (kifintPath == null)
            {
                throw new ArgumentNullException(nameof(kifintPath));
            }
            if (vcode2 == null)
            {
                throw new ArgumentNullException(nameof(vcode2));
            }

            BinaryReader reader = new BinaryReader(stream);
            KIFHDR       hdr    = reader.ReadUnmanaged <KIFHDR>();

            UnexpectedFileTypeException.ThrowIfInvalid(hdr.Signature, KIFHDR.ExpectedSignature);

            KIFENTRY[] entries = reader.ReadUnmanagedArray <KIFENTRY>(hdr.EntryCount);

            progress.EntryName  = null;
            progress.EntryIndex = 0;
            progress.EntryCount = entries.Length;

            // Table of contents seed
            uint     tocSeed      = GenerateTocSeed(vcode2);
            uint     fileKey      = 0;
            int      fileKeyIndex = -1;
            Blowfish blowfish     = null;

            // Obtain the decryption file key if one exists
            for (int i = 0; i < hdr.EntryCount; i++)
            {
                if (entries[i].FileName == KeyFileName)
                {
                    fileKey      = MersenneTwister.GenRand(entries[i].Length);
                    blowfish     = CatDebug.NewBlowfish(fileKey);
                    fileKeyIndex = i;
                    break;
                }
            }

            const int ProgressThreshold = 500;

            // Decrypt the KIFINT entries using the file key
            if (fileKeyIndex != -1)
            {
                for (uint i = 0; i < hdr.EntryCount; i++, progress.EntryIndex++)
                {
                    if (unchecked ((int)i) == fileKeyIndex)
                    {
                        continue;
                    }

                    // Give the entry the correct name
                    UnobfuscateFileName(entries[i].FileNameRaw, unchecked (tocSeed + i));
                    // Apply the extra offset before decryption
                    entries[i].Offset += i;
                    // Decrypt the entry's offset and length
                    blowfish.Decrypt(ref entries[i].Info);

                    progress.EntryName = entries[i].FileName;
                    if (i % ProgressThreshold == 0 || i + 1 == hdr.EntryCount)
                    {
                        callback?.Invoke(progress);
                    }
                }
            }

            return(new KifintArchive(kifintPath, entries, fileKeyIndex != -1, fileKey, type, blowfish));
        }
        private static bool DecryptArchive(Stream inStream, string kifintPath, string kifintBackup, string vcode2, bool isBackup,
                                           KifintProgressArgs progress, KifintProgressCallback callback)
        {
            if (kifintPath == null)
            {
                throw new ArgumentNullException(nameof(kifintPath));
            }
            if (vcode2 == null)
            {
                throw new ArgumentNullException(nameof(vcode2));
            }

            /*const string BackupName = "intbackup";
             * string dir = Path.GetDirectoryName(kifintPath);
             * string name = Path.GetFileName(kifintPath);
             * string kifintBackup = Path.Combine(dir, BackupName, name);
             * bool isBackup = Path.GetFileName(dir).ToLower() == BackupName;
             * if (isBackup) {
             *      dir = Path.GetDirectoryName(dir);
             *      kifintPath = Path.Combine(dir, name);
             * }
             * else {
             *
             * }*/
            Directory.CreateDirectory(Path.GetDirectoryName(kifintBackup));

            BinaryReader reader = new BinaryReader(inStream);
            KIFHDR       hdr    = reader.ReadUnmanaged <KIFHDR>();

            try {
                UnexpectedFileTypeException.ThrowIfInvalid(hdr.Signature, KIFHDR.ExpectedSignature);
            } catch (UnexpectedFileTypeException) {
                if (!isBackup && File.Exists(kifintBackup))
                {
                    inStream.Close();
                    // We must have stopped while decrypting an archive. Let's restart from the already-made backup
                    using (inStream = File.OpenRead(kifintBackup))
                        DecryptArchive(inStream, kifintPath, kifintBackup, vcode2, true, progress, callback);
                    return(true);
                }
                throw;
            }

            List <KIFENTRY> entries = new List <KIFENTRY>(hdr.EntryCount);

            entries.AddRange(reader.ReadUnmanagedArray <KIFENTRY>(hdr.EntryCount));

            // Table of contents seed
            uint     tocSeed  = GenerateTocSeed(vcode2);
            uint     fileKey  = 0;
            bool     decrypt  = false;
            Blowfish blowfish = null;
            int      keyIndex = -1;

            // Obtain the decryption file key if one exists
            for (int i = 0; i < hdr.EntryCount; i++)
            {
                if (entries[i].FileName == KeyFileName)
                {
                    fileKey  = MersenneTwister.GenRand(entries[i].Length);
                    decrypt  = true;
                    blowfish = CatDebug.NewBlowfish(fileKey);
                    keyIndex = i;
                    break;
                }
            }

            // This archive is already decrypted, return and let the calling method know
            if (!decrypt)
            {
                return(false);
            }

            if (isBackup)
            {
                using (Stream outStream = File.Create(kifintPath))
                    DecryptArchiveSave(hdr, entries, tocSeed, fileKey, blowfish, keyIndex, inStream, outStream,
                                       progress, callback);
            }
            else
            {
                if (File.Exists(kifintBackup))
                {
                    File.Delete(kifintBackup);
                }
                inStream.Close();
                File.Move(kifintPath, kifintBackup);
                using (inStream = File.OpenRead(kifintBackup))
                    using (Stream outStream = File.Create(kifintPath))
                        DecryptArchiveSave(hdr, entries, tocSeed, fileKey, blowfish, keyIndex, inStream, outStream,
                                           progress, callback);
            }

            return(true);
        }