예제 #1
0
        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);
        }
예제 #2
0
 public void Add(Intro intro)
 {
     _introList.Add(intro);
 }