public bool UnpackRepository() { if (!File.Exists(_sourceBigfileName)) { Console.WriteLine("Error: Cannot find source bigfile \"" + _sourceBigfileName + "\"."); return(false); } if (!File.Exists(_sourceTexturesFileName)) { Console.WriteLine("Error: Cannot find source textures file \"" + _sourceTexturesFileName + "\"."); return(false); } try { AssetDescSet assetData = new AssetDescSet(); LevelSet levelData = new LevelSet(); IntroSet introData = new IntroSet(); SFXClipSet clipData = new SFXClipSet(); TexDescSet textureData = new TexDescSet(); if (!LoadBigfileEntries(assetData)) { return(false); } CreateDirectories(); FileStream sourceBigFile = new FileStream(_sourceBigfileName, FileMode.Open, FileAccess.Read); FileStream sourceTexturesFile = new FileStream(_sourceTexturesFileName, FileMode.Open, FileAccess.Read); List <int> sfxIDs = new List <int>(); FileStream allClipsFile = new FileStream(_allClipsFileName, FileMode.Create, FileAccess.ReadWrite); allClipsFile.Write(new byte[16], 0, 16); #region Bigfile foreach (AssetDesc entry in assetData.Assets) { sourceBigFile.Position = entry.FileOffset; string outputFileName = Path.Combine(_projectFolderName, entry.FilePath); string outputFileDirectory = Path.GetDirectoryName(outputFileName); Directory.CreateDirectory(outputFileDirectory); FileStream outputFile = new FileStream(outputFileName, FileMode.Create, FileAccess.ReadWrite); CopyTo(outputFile, sourceBigFile, (int)entry.FileLength); outputFile.Flush(); string ext = Path.GetExtension(outputFileName); if (ext == ".pcm") { BinaryReader reader = new BinaryReader(outputFile, System.Text.Encoding.ASCII); reader.BaseStream.Position = 0; UInt32 dataStart = ((reader.ReadUInt32() >> 9) << 11) + 0x00000800; bool isUnit = (reader.ReadUInt32() == 0x00000000); if (isUnit) { Level level = new Level(); reader.BaseStream.Position = dataStart + 0x98; reader.BaseStream.Position = dataStart + reader.ReadUInt32(); level.UnitName = CleanName(new string(reader.ReadChars(8))); #region Events /*reader.BaseStream.Position = dataStart + 0xDC; * uint eventPointersOffset = reader.ReadUInt16(); * reader.BaseStream.Position = dataStart + eventPointersOffset; * int numPuzzles = reader.ReadInt32(); * for (int p = 0; p < numPuzzles; p++) * { * uint eventOffset = reader.ReadUInt32(); * uint nextEventPointer = (uint)reader.BaseStream.Position; * * reader.BaseStream.Position = dataStart + eventOffset; * reader.BaseStream.Position += 0x02; * * short numInstances = reader.ReadInt16(); * reader.BaseStream.Position += 0x0C; * * for (int i = 0; i < 0; i++) * { * uint instanceOffset = reader.ReadUInt32(); * uint nextInstancePointer = (uint)reader.BaseStream.Position; * * reader.BaseStream.Position = dataStart + instanceOffset; * short eventType = reader.ReadInt16(); * // Do EventInstance stuff here. * * reader.BaseStream.Position = nextInstancePointer; * } * * * reader.BaseStream.Position = nextEventPointer; * }*/ #endregion reader.BaseStream.Position = dataStart + 0xF8; level.StreamUnitID = reader.ReadInt32(); if (level.StreamUnitID > levelData.MaxID) { levelData.MaxID = level.StreamUnitID; } levelData.Add(level); #region Instances reader.BaseStream.Position = dataStart + 0x78; uint instanceCount = reader.ReadUInt32(); uint instanceStart = dataStart + reader.ReadUInt32(); for (int i = 0; i < instanceCount; i++) { Intro intro = new Intro(); reader.BaseStream.Position = instanceStart + 0x4C * i; intro.ObjectName = CleanName(new String(reader.ReadChars(16))); intro.UnitName = level.UnitName; intro.StreamUnitID = level.StreamUnitID; reader.BaseStream.Position += 4; intro.IntroUniqueID = reader.ReadInt32(); intro.Rotation.X = reader.ReadInt16(); intro.Rotation.Y = reader.ReadInt16(); intro.Rotation.Z = reader.ReadInt16(); reader.BaseStream.Position += 4; intro.Position.X = reader.ReadInt16(); intro.Position.Y = reader.ReadInt16(); intro.Position.Z = reader.ReadInt16(); if (intro.IntroUniqueID > introData.MaxID) { introData.MaxID = intro.IntroUniqueID; } introData.Add(intro); } #endregion } } else if (ext == ".pmf") { BinaryReader reader = new BinaryReader(outputFile, System.Text.Encoding.ASCII); reader.BaseStream.Position = 0; uint header = reader.ReadUInt32(); if (header == 0x61504D46 /*&& entry.FileHash == 0xf2c83bb8*/) // 0xf2c83bb8 for just raziel.pnf { reader.BaseStream.Position += 4; int clipCount = (int)reader.ReadUInt32(); reader.BaseStream.Position = 16; for (int clipNum = 0; clipNum < clipCount; clipNum++) { long clipHeaderStart = reader.BaseStream.Position; ushort sfxID = reader.ReadUInt16(); ushort waveID = reader.ReadUInt16(); reader.BaseStream.Position += 16; long currentPosition = reader.BaseStream.Position; long currentClipLength = reader.ReadUInt32() - 4; long currentClipStart = reader.BaseStream.Position + 4; long nextClipStart = currentClipStart + currentClipLength; reader.BaseStream.Position = clipHeaderStart; byte[] clipBuffer = reader.ReadBytes((int)(nextClipStart - clipHeaderStart)); SHA256 s256 = SHA256.Create(); byte[] s256Hash = s256.ComputeHash(clipBuffer); string s256String = ByteArrayToHexString(s256Hash); //string outputClipFileName = Path.Combine(_sfxFolderName, "clip-" + sfxID + "-" + waveID + "-" + s256String + ".sfx"); string outputClipFileName = Path.Combine(_sfxFolderName, "clip-" + sfxID + ".sfx"); FileStream outputClipFile = new FileStream(outputClipFileName, FileMode.Create); outputClipFile.Write(clipBuffer, 0, clipBuffer.Length); outputClipFile.Close(); if (!sfxIDs.Contains(sfxID)) { SFXClip clip = new SFXClip(); clip.SFXID = sfxID; clip.SFXName = "clip-" + sfxID; clipData.Add(clip); sfxIDs.Add(sfxID); } allClipsFile.Write(clipBuffer, 0, clipBuffer.Length); Console.WriteLine("\tExtracted clip: \"" + outputClipFileName + "\""); reader.BaseStream.Position = nextClipStart; } } } outputFile.Close(); Console.WriteLine("Extracted file: \"" + outputFileName + "\""); } #endregion #region Textures BinaryReader texturesReader = new BinaryReader(sourceTexturesFile); texturesReader.BaseStream.Position = headerLength; uint fileLength = (uint)sourceTexturesFile.Length; uint totalTextures = (uint)((fileLength - (long)headerLength) / (long)(textureWidth * textureHeight * 2) - 1); for (int t = 0; t <= totalTextures; t++) { string textureName = "texture-" + zeroFill(t.ToString(), 5) + ".png"; string outputFileName = Path.Combine(_textureFolderName, textureName); string relativePath = outputFileName.Substring(_projectFolderName.Length); TexDesc texDesc = new TexDesc(); texDesc.TextureIndex = textureData.Count; texDesc.FilePath = relativePath; textureData.Add(texDesc); Bitmap tempBitmap = ReadTexture(texturesReader); tempBitmap.Save(outputFileName, System.Drawing.Imaging.ImageFormat.Png); Console.WriteLine("Extracted file: \"" + outputFileName + "\""); } texturesReader.Close(); #endregion sourceBigFile.Close(); sourceTexturesFile.Close(); allClipsFile.Position = 0; allClipsFile.Write(BitConverter.GetBytes(0x61504D46), 0, 4); allClipsFile.Write(BitConverter.GetBytes((short)256), 0, 2); allClipsFile.Write(BitConverter.GetBytes((short)0), 0, 2); allClipsFile.Write(BitConverter.GetBytes((short)sfxIDs.Count), 0, 2); allClipsFile.Write(BitConverter.GetBytes((short)0), 0, 2); allClipsFile.Write(BitConverter.GetBytes(0x00000000), 0, 4); allClipsFile.Close(); string assetsFileData = JsonSerializer.Serialize(assetData, new JsonSerializerOptions { WriteIndented = true }); File.WriteAllText(_assetsFileName, assetsFileData, Encoding.ASCII); string levelsFileData = JsonSerializer.Serialize(levelData, new JsonSerializerOptions { WriteIndented = true }); File.WriteAllText(_levelsFileName, levelsFileData, Encoding.ASCII); string introsFileData = JsonSerializer.Serialize(introData, new JsonSerializerOptions { WriteIndented = true }); File.WriteAllText(_introsFileName, introsFileData, Encoding.ASCII); string clipsFileData = JsonSerializer.Serialize(clipData, new JsonSerializerOptions { WriteIndented = true }); File.WriteAllText(_clipsFileName, clipsFileData, Encoding.ASCII); string texturesFileData = JsonSerializer.Serialize(textureData, new JsonSerializerOptions { WriteIndented = true }); File.WriteAllText(_texturesFileName, texturesFileData, Encoding.ASCII); Console.WriteLine("Extracted " + assetData.Count.ToString() + " files from \"" + _sourceBigfileName + "\"."); Console.WriteLine("Extracted " + textureData.Count.ToString() + " files from \"" + _sourceTexturesFileName + "\"."); Console.WriteLine("Discovered " + levelData.Count + " unique levels."); Console.WriteLine("Discovered " + introData.Count + " unique intros."); Console.WriteLine("Discovered " + clipData.Count + " unique clips."); } catch (Exception) { Console.WriteLine("Error: Couldn't unpack the repository."); return(false); } return(true); }
public void Add(Intro intro) { _introList.Add(intro); }