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); }
/// <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); }