Esempio n. 1
0
        /* Save out our material mappings archive */
        public override PAKReturnType Save()
        {
            try
            {
                //Re-write out to the PAK
                ExtraBinaryUtils BinaryUtils   = new ExtraBinaryUtils();
                BinaryWriter     ArchiveWriter = new BinaryWriter(File.OpenWrite(FilePathPAK));
                ArchiveWriter.BaseStream.SetLength(0);
                ArchiveWriter.Write(FileHeaderJunk);
                ArchiveWriter.Write(MaterialMappingEntries.Count);
                foreach (EntryMaterialMappingsPAK ThisMatRemap in MaterialMappingEntries)
                {
                    ArchiveWriter.Write(ThisMatRemap.MapHeader);
                    ArchiveWriter.Write(ThisMatRemap.MapEntryCoupleCount);
                    ArchiveWriter.Write(ThisMatRemap.MapJunk);
                    ArchiveWriter.Write(ThisMatRemap.MapFilename.Length);
                    BinaryUtils.WriteString(ThisMatRemap.MapFilename, ArchiveWriter);
                    foreach (string MaterialName in ThisMatRemap.MapMatEntries)
                    {
                        ArchiveWriter.Write(MaterialName.Length);
                        BinaryUtils.WriteString(MaterialName, ArchiveWriter);
                    }
                }
                ArchiveWriter.Close();

                return(PAKReturnType.SUCCESS);
            }
            catch (IOException) { return(PAKReturnType.FAIL_COULD_NOT_ACCESS_FILE); }
            catch (Exception) { return(PAKReturnType.FAIL_UNKNOWN); }
        }
Esempio n. 2
0
        /* Replace an existing file in the TexturePAK archive */
        public override PAKReturnType ReplaceFile(string PathToNewFile, string FileName)
        {
            try
            {
                //Get the texture entry & parse new DDS
                int EntryIndex = GetFileIndex(FileName);
                if (EntryIndex == -1)
                {
                    return(PAKReturnType.FAIL_GENERAL_LOGIC_ERROR);                  //CHANGED FOR OPENCAGE
                }
                TEX4      TextureEntry = TextureEntries[EntryIndex];
                DDSReader NewTexture   = new DDSReader(PathToNewFile);

                //Currently we only apply the new texture to the "biggest", some have lower mips that we don't edit (TODO)
                TEX4_Part BiggestPart = TextureEntry.Texture_V2;
                if (BiggestPart.HeaderPos == -1 || !BiggestPart.Saved)
                {
                    BiggestPart = TextureEntry.Texture_V1;
                }
                if (BiggestPart.HeaderPos == -1 || !BiggestPart.Saved)
                {
                    return(PAKReturnType.FAIL_REQUEST_IS_UNSUPPORTED); //Shouldn't reach this.
                }

                //CATHODE seems to ignore texture header information regarding size, so as default, resize any imported textures to the original size.
                //An option is provided in the toolkit to write size information to the header (done above) however, so don't resize if that's the case.
                //More work needs to be done to figure out why CATHODE doesn't honour the header's size value.
                int OriginalLength = BiggestPart.Length;
                Array.Resize(ref NewTexture.DataBlock, OriginalLength);

                //Update our internal knowledge of the textures
                BiggestPart.Length  = (int)NewTexture.DataBlock.Length;
                BiggestPart.Width   = (Int16)NewTexture.Width;
                BiggestPart.Height  = (Int16)NewTexture.Height;
                TextureEntry.Format = NewTexture.Format;
                //TODO: Update smallest here too if it exists!
                //Will need to be written into the PAK at "Pull PAK sections before/after V2" too - headers are handled already.

                //Load the BIN and write out updated BIN texture header
                BinaryWriter     ArchiveFileBinWriter = new BinaryWriter(File.OpenWrite(FilePathBIN));
                ExtraBinaryUtils BinaryUtils          = new ExtraBinaryUtils();
                ArchiveFileBinWriter.BaseStream.Position = TextureEntry.HeaderPos;
                BinaryUtils.WriteString(TextureEntry.Magic, ArchiveFileBinWriter);
                ArchiveFileBinWriter.Write(BitConverter.GetBytes((int)TextureEntry.Format));
                ArchiveFileBinWriter.Write((TextureEntry.Texture_V2.Length == -1) ? 0 : TextureEntry.Texture_V2.Length);
                ArchiveFileBinWriter.Write(TextureEntry.Texture_V1.Length);
                ArchiveFileBinWriter.Write(TextureEntry.Texture_V1.Width);
                ArchiveFileBinWriter.Write(TextureEntry.Texture_V1.Height);
                ArchiveFileBinWriter.Write(TextureEntry.Unk_V1);
                ArchiveFileBinWriter.Write(TextureEntry.Texture_V2.Width);
                ArchiveFileBinWriter.Write(TextureEntry.Texture_V2.Height);
                ArchiveFileBinWriter.Write(TextureEntry.Unk_V2);
                ArchiveFileBinWriter.Write(TextureEntry.UnknownHeaderBytes);
                ArchiveFileBinWriter.Close();

                //Update headers for V1+2 in PAK if they exist
                BinaryWriter   ArchiveFileWriter = new BinaryWriter(File.OpenWrite(FilePathPAK));
                BigEndianUtils BigEndian         = new BigEndianUtils();
                if (TextureEntry.Texture_V1.HeaderPos != -1)
                {
                    ArchiveFileWriter.BaseStream.Position = TextureEntry.Texture_V1.HeaderPos;
                    ArchiveFileWriter.Write(TextureEntry.Texture_V1.UnknownHeaderLead);
                    ArchiveFileWriter.Write(BigEndian.FlipEndian(BitConverter.GetBytes(TextureEntry.Texture_V1.Length)));
                    ArchiveFileWriter.Write(BigEndian.FlipEndian(BitConverter.GetBytes(TextureEntry.Texture_V1.Length)));
                    ArchiveFileWriter.Write(TextureEntry.Texture_V1.UnknownHeaderTrail_1);
                    ArchiveFileWriter.Write(BigEndian.FlipEndian(BitConverter.GetBytes((Int16)EntryIndex)));
                    ArchiveFileWriter.Write(TextureEntry.Texture_V1.UnknownHeaderTrail_2);
                }
                if (TextureEntry.Texture_V2.HeaderPos != -1)
                {
                    ArchiveFileWriter.BaseStream.Position = TextureEntry.Texture_V2.HeaderPos;
                    ArchiveFileWriter.Write(TextureEntry.Texture_V2.UnknownHeaderLead);
                    ArchiveFileWriter.Write(BigEndian.FlipEndian(BitConverter.GetBytes(TextureEntry.Texture_V2.Length)));
                    ArchiveFileWriter.Write(BigEndian.FlipEndian(BitConverter.GetBytes(TextureEntry.Texture_V2.Length)));
                    ArchiveFileWriter.Write(TextureEntry.Texture_V2.UnknownHeaderTrail_1);
                    ArchiveFileWriter.Write(BigEndian.FlipEndian(BitConverter.GetBytes((Int16)EntryIndex)));
                    ArchiveFileWriter.Write(TextureEntry.Texture_V2.UnknownHeaderTrail_2);
                }
                ArchiveFileWriter.Close();

                //Pull PAK sections before/after V2
                BinaryReader ArchiveFile = new BinaryReader(File.OpenRead(FilePathPAK));
                byte[]       PAK_Pt1     = ArchiveFile.ReadBytes(BiggestPart.StartPos);
                ArchiveFile.BaseStream.Position += OriginalLength;
                byte[] PAK_Pt2 = ArchiveFile.ReadBytes((int)ArchiveFile.BaseStream.Length - (int)ArchiveFile.BaseStream.Position);
                ArchiveFile.Close();

                //Write the PAK back out with new content
                ArchiveFileWriter = new BinaryWriter(File.OpenWrite(FilePathPAK));
                ArchiveFileWriter.BaseStream.SetLength(0);
                ArchiveFileWriter.Write(PAK_Pt1);
                ArchiveFileWriter.Write(NewTexture.DataBlock);
                ArchiveFileWriter.Write(PAK_Pt2);
                ArchiveFileWriter.Close();

                return(PAKReturnType.SUCCESS);
            }
            catch (IOException) { return(PAKReturnType.FAIL_COULD_NOT_ACCESS_FILE); }
            catch (Exception) { return(PAKReturnType.FAIL_UNKNOWN); }
        }
Esempio n. 3
0
        /* Load the contents of an existing ModelPAK */
        public override PAKReturnType Load()
        {
            if (!File.Exists(FilePathPAK))
            {
                return(PAKReturnType.FAIL_TRIED_TO_LOAD_VIRTUAL_ARCHIVE);
            }

            /* TODO: Verify the PAK loading is a ModelPAK by BIN version number */

            try
            {
                //First, parse the MTL file to find material info
                string       PathToMTL      = FilePathPAK.Substring(0, FilePathPAK.Length - 3) + "MTL";
                BinaryReader ArchiveFileMtl = new BinaryReader(File.OpenRead(PathToMTL));

                //Header
                ArchiveFileMtl.BaseStream.Position += 40; //There are some knowns here, just not required for us yet
                int MaterialEntryCount = ArchiveFileMtl.ReadInt16();
                ArchiveFileMtl.BaseStream.Position += 2;  //Skip unknown

                //Strings - more work will be done on materials eventually,
                //but taking their names for now is good enough for model export
                List <string> MaterialEntries    = new List <string>();
                string        ThisMaterialString = "";
                for (int i = 0; i < MaterialEntryCount; i++)
                {
                    while (true)
                    {
                        byte ThisByte = ArchiveFileMtl.ReadByte();
                        if (ThisByte == 0x00)
                        {
                            MaterialEntries.Add(ThisMaterialString);
                            ThisMaterialString = "";
                            break;
                        }
                        ThisMaterialString += (char)ThisByte;
                    }
                }
                ArchiveFileMtl.Close();

                //Read the header info from BIN
                BinaryReader ArchiveFileBin = new BinaryReader(File.OpenRead(FilePathBIN));
                ArchiveFileBin.BaseStream.Position += 4; //Skip magic
                TableCountPt2 = ArchiveFileBin.ReadInt32();
                ArchiveFileBin.BaseStream.Position += 4; //Skip unknown
                TableCountPt1 = ArchiveFileBin.ReadInt32();

                //Skip past table 1
                for (int i = 0; i < TableCountPt1; i++)
                {
                    byte ThisByte = 0x00;
                    while (ThisByte != 0xFF)
                    {
                        ThisByte = ArchiveFileBin.ReadByte();
                    }
                }
                ArchiveFileBin.BaseStream.Position += 23;

                //Read file list info
                FilenameListEnd = ArchiveFileBin.ReadInt32();
                int FilenameListStart = (int)ArchiveFileBin.BaseStream.Position;

                //Read all file names (bytes)
                byte[] filename_bytes = ArchiveFileBin.ReadBytes(FilenameListEnd);

                //Read table 2 (skipping all unknowns for now)
                ExtraBinaryUtils BinaryUtils = new ExtraBinaryUtils();
                for (int i = 0; i < TableCountPt2; i++)
                {
                    CS2 new_entry = new CS2();
                    new_entry.FilenameOffset            = ArchiveFileBin.ReadInt32();
                    new_entry.Filename                  = BinaryUtils.GetStringFromByteArray(filename_bytes, new_entry.FilenameOffset);
                    ArchiveFileBin.BaseStream.Position += 4;
                    new_entry.ModelPartNameOffset       = ArchiveFileBin.ReadInt32();
                    new_entry.ModelPartName             = BinaryUtils.GetStringFromByteArray(filename_bytes, new_entry.ModelPartNameOffset);
                    ArchiveFileBin.BaseStream.Position += 44;
                    new_entry.MaterialLibaryIndex       = ArchiveFileBin.ReadInt32();
                    new_entry.MaterialName              = MaterialEntries[new_entry.MaterialLibaryIndex];
                    ArchiveFileBin.BaseStream.Position += 8;
                    new_entry.BlockSize                 = ArchiveFileBin.ReadInt32();
                    ArchiveFileBin.BaseStream.Position += 14;
                    new_entry.ScaleFactor               = ArchiveFileBin.ReadInt16(); //Maybe?
                    ArchiveFileBin.BaseStream.Position += 2;
                    new_entry.VertCount                 = ArchiveFileBin.ReadInt16();
                    new_entry.FaceCount                 = ArchiveFileBin.ReadInt16();
                    new_entry.BoneCount                 = ArchiveFileBin.ReadInt16();
                    ModelEntries.Add(new_entry);
                }
                ArchiveFileBin.Close();

                //Get extra info from each header in the PAK
                BinaryReader   ArchiveFile = new BinaryReader(File.OpenRead(FilePathPAK));
                BigEndianUtils BigEndian   = new BigEndianUtils();
                ArchiveFile.BaseStream.Position += 32; //Skip header
                for (int i = 0; i < TableCountPt2; i++)
                {
                    ArchiveFile.BaseStream.Position += 8; //Skip unknowns
                    int ThisPakSize = BigEndian.ReadInt32(ArchiveFile);
                    if (ThisPakSize != BigEndian.ReadInt32(ArchiveFile))
                    {
                        //Dud entry... handle this somehow?
                    }
                    int ThisPakOffset = BigEndian.ReadInt32(ArchiveFile);
                    ArchiveFile.BaseStream.Position += 14;
                    int ThisIndex = BigEndian.ReadInt16(ArchiveFile);
                    ArchiveFile.BaseStream.Position += 12;

                    if (ThisIndex == -1)
                    {
                        continue; //Again, dud entry. Need to look into this!
                    }

                    //Push it into the correct entry
                    ModelEntries[ThisIndex].PakSize   = ThisPakSize;
                    ModelEntries[ThisIndex].PakOffset = ThisPakOffset;
                }
                HeaderListEnd = (int)ArchiveFile.BaseStream.Position;

                //Done!
                ArchiveFile.Close();
                return(PAKReturnType.SUCCESS);
            }
            catch (IOException) { return(PAKReturnType.FAIL_COULD_NOT_ACCESS_FILE); }
            catch (Exception) { return(PAKReturnType.FAIL_UNKNOWN); }
        }
Esempio n. 4
0
        /* Load the contents of an existing PAK2 */
        public override PAKReturnType Load()
        {
            if (!File.Exists(FilePathPAK))
            {
                return(PAKReturnType.FAIL_TRIED_TO_LOAD_VIRTUAL_ARCHIVE);
            }

            try
            {
                //Open PAK
                BinaryReader ArchiveFile = new BinaryReader(File.OpenRead(FilePathPAK));

                //Read the header info
                string MagicValidation = "";
                for (int i = 0; i < 4; i++)
                {
                    MagicValidation += ArchiveFile.ReadChar();
                }
                if (MagicValidation != "PAK2")
                {
                    ArchiveFile.Close(); return(PAKReturnType.FAIL_ARCHIVE_IS_NOT_EXCPETED_TYPE);
                }
                OffsetListBegin = ArchiveFile.ReadInt32() + 16;
                NumberOfEntries = ArchiveFile.ReadInt32();
                ArchiveFile.BaseStream.Position += 4; //Skip "4"

                //Read all file names and create entries
                for (int i = 0; i < NumberOfEntries; i++)
                {
                    string ThisFileName = "";
                    for (byte b; (b = ArchiveFile.ReadByte()) != 0x00;)
                    {
                        ThisFileName += (char)b;
                    }

                    EntryPAK2 NewPakFile = new EntryPAK2();
                    NewPakFile.Filename = ThisFileName;
                    Pak2Files.Add(NewPakFile);
                }

                //Read all file offsets
                ArchiveFile.BaseStream.Position = OffsetListBegin;
                List <int> FileOffsets = new List <int>();
                FileOffsets.Add(OffsetListBegin + (NumberOfEntries * 4));
                for (int i = 0; i < NumberOfEntries; i++)
                {
                    FileOffsets.Add(ArchiveFile.ReadInt32());
                    Pak2Files[i].Offset = FileOffsets[i];
                }

                //Read in the files to entries
                ExtraBinaryUtils BinaryUtils = new ExtraBinaryUtils();
                for (int i = 0; i < NumberOfEntries; i++)
                {
                    //Must pass to RemoveLeadingNulls as each file starts with 0-3 null bytes to align files to a 4-byte block reader
                    Pak2Files[i].Content = BinaryUtils.RemoveLeadingNulls(ArchiveFile.ReadBytes(FileOffsets[i + 1] - FileOffsets[i]));
                }

                //Close PAK
                ArchiveFile.Close();
                return(PAKReturnType.SUCCESS);
            }
            catch (IOException) { return(PAKReturnType.FAIL_COULD_NOT_ACCESS_FILE); }
            catch (Exception) { return(PAKReturnType.FAIL_UNKNOWN); }
        }
Esempio n. 5
0
        /* Save out our PAK2 archive */
        public override PAKReturnType Save()
        {
            try
            {
                //Open/create PAK2 for writing
                BinaryWriter ArchiveFileWrite;
                if (File.Exists(FilePathPAK))
                {
                    ArchiveFileWrite = new BinaryWriter(File.OpenWrite(FilePathPAK));
                    ArchiveFileWrite.BaseStream.SetLength(0);
                }
                else
                {
                    ArchiveFileWrite = new BinaryWriter(File.Create(FilePathPAK));
                }
                ExtraBinaryUtils BinaryUtils = new ExtraBinaryUtils();

                //Write header
                BinaryUtils.WriteString("PAK2", ArchiveFileWrite);
                int OffsetListBegin_New = 0;
                for (int i = 0; i < Pak2Files.Count; i++)
                {
                    OffsetListBegin_New += Pak2Files[i].Filename.Length + 1;
                }
                ArchiveFileWrite.Write(OffsetListBegin_New);
                ArchiveFileWrite.Write(Pak2Files.Count);
                ArchiveFileWrite.Write(4);

                //Write filenames
                for (int i = 0; i < Pak2Files.Count; i++)
                {
                    BinaryUtils.WriteString(Pak2Files[i].Filename.Replace("\\", "/"), ArchiveFileWrite);
                    ArchiveFileWrite.Write((byte)0x00);
                }

                //Write placeholder offsets for now, we'll correct them after writing the content
                OffsetListBegin = (int)ArchiveFileWrite.BaseStream.Position;
                for (int i = 0; i < Pak2Files.Count; i++)
                {
                    ArchiveFileWrite.Write(0);
                }

                //Write files
                for (int i = 0; i < Pak2Files.Count; i++)
                {
                    while (ArchiveFileWrite.BaseStream.Position % 4 != 0)
                    {
                        ArchiveFileWrite.Write((byte)0x00);
                    }
                    ArchiveFileWrite.Write(Pak2Files[i].Content);
                    Pak2Files[i].Offset = (int)ArchiveFileWrite.BaseStream.Position;
                }

                //Re-write offsets with correct values
                ArchiveFileWrite.BaseStream.Position = OffsetListBegin;
                for (int i = 0; i < Pak2Files.Count; i++)
                {
                    ArchiveFileWrite.Write(Pak2Files[i].Offset);
                }

                ArchiveFileWrite.Close();
                return(PAKReturnType.SUCCESS);
            }
            catch (IOException) { return(PAKReturnType.FAIL_COULD_NOT_ACCESS_FILE); }
            catch (Exception) { return(PAKReturnType.FAIL_UNKNOWN); }
        }