Пример #1
0
        /* Load the contents of an existing TexturePAK */
        public override PAKReturnType Load()
        {
            if (!File.Exists(FilePathPAK))
            {
                return(PAKReturnType.FAIL_TRIED_TO_LOAD_VIRTUAL_ARCHIVE);
            }

            try
            {
                /* First, parse the BIN and pull ALL info from it */
                BinaryReader ArchiveFileBin = new BinaryReader(File.OpenRead(FilePathBIN));

                //Read the header info from the BIN
                VersionNumber_BIN = ArchiveFileBin.ReadInt32();
                if (VersionNumber_BIN != 45)
                {
                    return(PAKReturnType.FAIL_ARCHIVE_IS_NOT_EXCPETED_TYPE);
                }                                                                                        //BIN version number is 45 for textures
                NumberOfEntriesBIN = ArchiveFileBin.ReadInt32();
                HeaderListBeginBIN = ArchiveFileBin.ReadInt32();

                //Read all file names from BIN
                string ThisFileName = "";
                for (int i = 0; i < NumberOfEntriesBIN; i++)
                {
                    ThisFileName = "";
                    for (byte b; (b = ArchiveFileBin.ReadByte()) != 0x00;)
                    {
                        ThisFileName += (char)b;
                    }
                    if (Path.GetExtension(ThisFileName).ToUpper() != ".DDS")
                    {
                        ThisFileName += ".dds";
                    }
                    //Create texture entry and add filename
                    TEX4 TextureEntry = new TEX4();
                    TextureEntry.FileName = ThisFileName;
                    TextureEntries.Add(TextureEntry);
                }

                //Read the texture headers from the BIN
                ArchiveFileBin.BaseStream.Position = HeaderListBeginBIN + 12;
                for (int i = 0; i < NumberOfEntriesBIN; i++)
                {
                    TextureEntries[i].HeaderPos = (int)ArchiveFileBin.BaseStream.Position;
                    for (int x = 0; x < 4; x++)
                    {
                        TextureEntries[i].Magic += ArchiveFileBin.ReadChar();
                    }
                    TextureEntries[i].Format             = (TextureFormat)ArchiveFileBin.ReadInt32();
                    TextureEntries[i].Length_V2          = ArchiveFileBin.ReadInt32();
                    TextureEntries[i].Length_V1          = ArchiveFileBin.ReadInt32();
                    TextureEntries[i].Texture_V1.Width   = ArchiveFileBin.ReadInt16();
                    TextureEntries[i].Texture_V1.Height  = ArchiveFileBin.ReadInt16();
                    TextureEntries[i].Unk_V1             = ArchiveFileBin.ReadInt16();
                    TextureEntries[i].Texture_V2.Width   = ArchiveFileBin.ReadInt16();
                    TextureEntries[i].Texture_V2.Height  = ArchiveFileBin.ReadInt16();
                    TextureEntries[i].Unk_V2             = ArchiveFileBin.ReadInt16();
                    TextureEntries[i].UnknownHeaderBytes = ArchiveFileBin.ReadBytes(20);
                }

                /* Second, parse the PAK and pull ONLY header info from it - we'll pull textures when requested (to save memory) */
                ArchiveFileBin.Close();
                BinaryReader ArchiveFile = new BinaryReader(File.OpenRead(FilePathPAK));

                //Read the header info from the PAK
                BigEndianUtils BigEndian = new BigEndianUtils();
                ArchiveFile.BaseStream.Position += 4; //Skip nulls
                VersionNumber_PAK = BigEndian.ReadInt32(ArchiveFile);
                if (BigEndian.ReadInt32(ArchiveFile) != VersionNumber_BIN)
                {
                    throw new Exception("Archive version mismatch!");
                }
                NumberOfEntriesPAK = BigEndian.ReadInt32(ArchiveFile);
                if (BigEndian.ReadInt32(ArchiveFile) != NumberOfEntriesPAK)
                {
                    throw new Exception("PAK entry count mismatch!");
                }
                ArchiveFile.BaseStream.Position += 12; //Skip unknowns (1,1,1)

                //Read the texture headers from the PAK
                int OffsetTracker = (NumberOfEntriesPAK * 48) + 32;
                for (int i = 0; i < NumberOfEntriesPAK; i++)
                {
                    //Header indexes are out of order, so optimise replacements by saving position
                    int HeaderPosition = (int)ArchiveFile.BaseStream.Position;

                    //Pull the entry info
                    byte[] UnknownHeaderLead = ArchiveFile.ReadBytes(8);
                    int    PartLength        = BigEndian.ReadInt32(ArchiveFile);
                    if (PartLength != BigEndian.ReadInt32(ArchiveFile))
                    {
                        continue;
                    }
                    byte[] UnknownHeaderTrail_1 = ArchiveFile.ReadBytes(18);

                    //Find the entry
                    TEX4      TextureEntry = TextureEntries[BigEndian.ReadInt16(ArchiveFile)];
                    TEX4_Part TexturePart  = (!TextureEntry.Texture_V1.Saved) ? TextureEntry.Texture_V1 : TextureEntry.Texture_V2;

                    //Write out the info
                    TexturePart.HeaderPos            = HeaderPosition;
                    TexturePart.StartPos             = OffsetTracker;
                    TexturePart.UnknownHeaderLead    = UnknownHeaderLead;
                    TexturePart.Length               = PartLength;
                    TexturePart.Saved                = true;
                    TexturePart.UnknownHeaderTrail_1 = UnknownHeaderTrail_1;
                    TexturePart.UnknownHeaderTrail_2 = ArchiveFile.ReadBytes(12);

                    //Keep file offset updated
                    OffsetTracker += TexturePart.Length;
                }
                HeaderListEndPAK = (int)ArchiveFile.BaseStream.Position;

                //Close PAK
                ArchiveFile.Close();
                return(PAKReturnType.SUCCESS);
            }
            catch (IOException) { return(PAKReturnType.FAIL_COULD_NOT_ACCESS_FILE); }
            catch (Exception) { return(PAKReturnType.FAIL_UNKNOWN); }
        }
Пример #2
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); }
        }