Beispiel #1
0
        public static List <stamData> ReadLM(this BufferedStreamReader streamReader)
        {
            var stamList = new List <stamData>();
            var lmStart  = streamReader.Position();

            streamReader.Read <int>();
            var lmEnd = streamReader.Read <int>() + lmStart;

            streamReader.Seek(0x8, SeekOrigin.Current);
            while (streamReader.Position() < lmEnd)
            {
                var tag = streamReader.Peek <int>();
                switch (tag)
                {
                case stam:
                    stamList.Add(streamReader.ReadStam());
                    break;

                default:
                    streamReader.SkipBasicAXSStruct();
                    break;
                }

                //Make sure to stop the loop if needed
                if (stamList[stamList.Count - 1].lastStam == true)
                {
                    break;
                }
            }

            streamReader.Seek(lmEnd, SeekOrigin.Begin);

            return(stamList);
        }
        public static List <int> ReadVTBFMGX(BufferedStreamReader streamReader)
        {
            List <int> mgxIds = new List <int>(); //For now, just get these. The data inside is pretty accessible, but we have nothing to do with it

            int dataEnd = (int)streamReader.BaseStream().Length;

            //Seek past vtbf tag
            streamReader.Seek(0x10, SeekOrigin.Current);          //VTBF tags

            while (streamReader.Position() < dataEnd)
            {
                var data = ReadVTBFTag(streamReader, out string tagType, out int ptrCount, out int entryCount);
                switch (tagType)
                {
                case "DOC ":
                    break;

                case "MAGR":
                    Debug.WriteLine((int)data[0][0xFF]);
                    mgxIds.Add((int)data[0][0xFF]);
                    break;

                default:
                    //Data being null signfies that the last thing read wasn't a proper tag. This should mean the end of the VTBF stream if nothing else.
                    if (data == null)
                    {
                        return(mgxIds);
                    }
                    throw new System.Exception($"Unexpected tag at {streamReader.Position().ToString("X")}! {tagType} Please report!");
                }
            }

            return(mgxIds);
        }
Beispiel #3
0
        /// <summary>
        /// Creates a <see cref="HintFile"/> from a byte array.
        /// </summary>
        /// <param name="fileData">The hint file to parse.</param>
        public static unsafe HintFile FromArray(byte[] fileData)
        {
            using (MemoryStream fileDataStream = new MemoryStream(fileData))
            {
                var reader = new BufferedStreamReader(fileDataStream, 4096);

                // Get all entries.
                var   entries = new List <Entry>((fileData.Length / 2) / sizeof(Entry));
                Entry entry;

                do
                {
                    reader.Read(out entry);
                    entries.Add(entry);
                }while (entry != Entry.Null);
                entries.RemoveAt(entries.Count - 1);

                // Convert all entries to managed.
                fixed(byte *stringDataPtr = &fileData[reader.Position()])
                {
                    var managedEntries = new ManagedEntry[entries.Count];

                    for (int i = 0; i < managedEntries.Length; i++)
                    {
                        var textPtr = &stringDataPtr[entries[i].Offset];
                        var text    = _encoder.GetString(textPtr, Strlen(textPtr));
                        managedEntries[i] = new ManagedEntry(entries[i], text);
                    }

                    return(new HintFile(managedEntries));
                }
            }
        }
Beispiel #4
0
        public static stamData ReadStam(this BufferedStreamReader streamReader)
        {
            var stamDataObj = new stamData();
            var stamStart   = streamReader.Position();

            streamReader.Read <int>();
            streamReader.Seek(0x8, SeekOrigin.Current);
            var stamSize = streamReader.Read <int>();

            streamReader.Seek(0x8, SeekOrigin.Current);
            var stamTexCount = streamReader.Read <ushort>();

            streamReader.Seek(0x12, SeekOrigin.Current);

            int texOffset = streamReader.Read <int>();

            if (texOffset == 0)
            {
                stamDataObj.lastStam = true;
                return(stamDataObj);
            }
            streamReader.Seek(stamStart + texOffset, SeekOrigin.Begin);
            for (int i = 0; i < stamTexCount; i++)
            {
                var key0 = BitConverter.GetBytes(streamReader.Read <int>());
                int key1 = streamReader.Read <int>();
                stamDataObj.texIds.Add(key0[0].ToString("X2") + key0[1].ToString("X2") + key0[2].ToString("X2") + key0[3].ToString("X2") + key1.ToString("X"));
                streamReader.Seek(0x18, SeekOrigin.Current);
            }

            //streamReader.Seek(stamEnd, SeekOrigin.Begin);

            return(stamDataObj);
        }
        public static NGSSHAD ReadNGSSHAD(BufferedStreamReader streamReader, int offset)
        {
            NGSSHAD shad = new NGSSHAD();

            shad.unk0             = streamReader.Read <int>();
            shad.pixelShader      = streamReader.Read <PSO2String>();
            shad.vertexShader     = streamReader.Read <PSO2String>();
            shad.shadDetailOffset = streamReader.Read <int>();
            shad.shadExtraOffset  = streamReader.Read <int>();

            long bookmark = streamReader.Position();

            //Some shaders, like some player ones apparently, do not use the extra structs...
            if (shad.shadDetailOffset > 0)
            {
                streamReader.Seek(shad.shadDetailOffset + offset, System.IO.SeekOrigin.Begin);
                shad.shadDetail = streamReader.Read <SHADDetail>();

                streamReader.Seek(shad.shadExtraOffset + offset, System.IO.SeekOrigin.Begin);
                for (int i = 0; i < shad.shadDetail.shadExtraCount; i++)
                {
                    shad.shadExtra.Add(streamReader.Read <SHADExtraEntry>());
                }
            }
            else if (shad.shadExtraOffset > 0)
            {
                Console.WriteLine("**Apparently shadExtraOffset is allowed to be used without shadDetailOffset???**");
            }
            streamReader.Seek(bookmark, System.IO.SeekOrigin.Begin);

            return(shad);
        }
        public static LobbyActionCommon ReadNIFLRebootLAC(BufferedStreamReader streamReader, int offset)
        {
            var lac  = new LobbyActionCommon();
            var nifl = streamReader.Read <AquaCommon.NIFL>();
            var end  = nifl.NOF0Offset + offset;
            var rel0 = streamReader.Read <AquaCommon.REL0>();

            streamReader.Seek(rel0.REL0DataStart + offset, SeekOrigin.Begin);
            lac.header = streamReader.Read <LobbyActionCommon.lacHeader>();

            streamReader.Seek(lac.header.dataInfoPointer + offset, SeekOrigin.Begin);
            lac.info = streamReader.Read <LobbyActionCommon.dataInfo>();

            streamReader.Seek(lac.info.blockOffset + offset, SeekOrigin.Begin);

            for (int i = 0; i < lac.info.blockCount; i++)
            {
                var  block    = streamReader.Read <LobbyActionCommon.dataBlockReboot>();
                long bookmark = streamReader.Position();

                lac.rebootDataBlocks.Add(LobbyActionCommon.ReadDataBlockReboot(streamReader, offset, block));
                streamReader.Seek(bookmark, SeekOrigin.Begin);
            }

            return(lac);
        }
Beispiel #7
0
        private List <DatFileEntry>?GetEntriesForPointerPattern(string datFileName, BufferedStreamReader streamReader, int offset)
        {
            // Validate if first entry
            streamReader.Seek(offset, SeekOrigin.Begin);
            streamReader.Read(out DatFileEntry headerEntry);
            streamReader.Read(out DatFileEntry firstEntry);
            var savedPos = streamReader.Position();

            if (!headerEntry.IsFirstEntry(streamReader, MemoryToRawAddress, firstEntry, datFileName))
            {
                return(null);
            }

            streamReader.Seek(savedPos, SeekOrigin.Begin);

            // Populate other entries.
            var          entries = new List <DatFileEntry>(new[] { firstEntry });
            DatFileEntry entry;

            while (!(entry = streamReader.Read <DatFileEntry>()).IsLastEntry())
            {
                entries.Add(entry);
            }

            return(entries);
        }
 public static void AlignReader(BufferedStreamReader streamReader, int align)
 {
     //Align to int align
     while (streamReader.Position() % align > 0)
     {
         streamReader.Read <byte>();
     }
 }
Beispiel #9
0
        public static eertStruct ReadEert(this BufferedStreamReader streamReader)
        {
            eertStruct boneList = new eertStruct();
            long       bookmark = streamReader.Position();

            streamReader.Seek(0x4, SeekOrigin.Current);
            var len = streamReader.Read <int>();

            streamReader.Seek(0x4, SeekOrigin.Current);
            var trueLen = streamReader.Read <int>();

            boneList.boneCount = streamReader.Read <int>();

            streamReader.Seek(bookmark + 0x100, SeekOrigin.Begin);
            for (int i = 0; i < boneList.boneCount; i++)
            {
                rttaStruct bone = new rttaStruct();
                bookmark     = streamReader.Position();
                bone.magic   = streamReader.Read <int>();
                bone.len     = streamReader.Read <int>();
                bone.int_08  = streamReader.Read <int>();
                bone.trueLen = streamReader.Read <int>();

                bone.nodeName     = streamReader.Read <AquaCommon.PSO2String>();
                bone.int_30       = streamReader.Read <int>();
                bone.meshNodePtr  = streamReader.Read <int>();
                bone.int_38       = streamReader.Read <int>();
                bone.parentNodeId = streamReader.Read <int>();

                bone.childNodeCount = streamReader.Read <short>();
                streamReader.Seek(0x3E, SeekOrigin.Current);
                bone.pos     = streamReader.Read <Vector3>(); streamReader.Seek(0x4, SeekOrigin.Current);
                bone.quatRot = streamReader.Read <Quaternion>();
                bone.scale   = streamReader.Read <Vector3>(); streamReader.Seek(0x4, SeekOrigin.Current);

                boneList.rttaList.Add(bone);
                streamReader.Seek(bookmark + bone.trueLen, SeekOrigin.Begin);
            }

            return(boneList);
        }
Beispiel #10
0
        public static void SkipBasicAXSStruct(this BufferedStreamReader streamReader)
        {
            long bookmark = streamReader.Position();

            streamReader.Read <int>();
            var trueLen = streamReader.Read <int>(); //Doesn't include padding so shouldn't be used

            streamReader.Read <int>();
            var len = streamReader.Read <int>();

            streamReader.Seek(bookmark, SeekOrigin.Begin);

            if (len == 0)
            {
                len = trueLen;
            }
            streamReader.Seek(len, SeekOrigin.Current);
        }
Beispiel #11
0
        public static ipnbStruct ReadIpnb(this BufferedStreamReader streamReader)
        {
            long       bookmark = streamReader.Position();
            ipnbStruct ipbnStr  = new ipnbStruct();

            ipbnStr.magic     = streamReader.Read <int>();
            ipbnStr.len       = streamReader.Read <int>();
            ipbnStr.int_08    = streamReader.Read <int>();
            ipbnStr.paddedLen = streamReader.Read <int>();

            int count = (ipbnStr.len - 0x10) / 2;

            for (int i = 0; i < count; i++)
            {
                ipbnStr.shortList.Add(streamReader.Read <short>());
            }

            streamReader.Seek(bookmark + ipbnStr.paddedLen, SeekOrigin.Begin);
            return(ipbnStr);
        }
        public static PSO2Text ReadNIFLText(BufferedStreamReader streamReader, int offset, string fileName)
        {
            var txt  = new PSO2Text();
            var nifl = streamReader.Read <AquaCommon.NIFL>();
            var end  = nifl.NOF0Offset + offset;
            var rel0 = streamReader.Read <AquaCommon.REL0>();

            streamReader.Seek(rel0.REL0DataStart + offset, SeekOrigin.Begin);

            var categoryPointer = streamReader.Read <int>();
            var categoryCount   = streamReader.Read <int>();

            //Read through categories
            streamReader.Seek(categoryPointer + offset, SeekOrigin.Begin);
            for (int i = 0; i < categoryCount; i++)
            {
                var categoryNameOffset     = streamReader.Read <int>();
                var categoryDataInfoOffset = streamReader.Read <int>();
                var subCategoryCount       = streamReader.Read <int>();

                //Setup subcategory lists
                txt.text.Add(new List <List <PSO2Text.textPair> >());
                for (int j = 0; j < subCategoryCount; j++)
                {
                    txt.text[i].Add(new List <PSO2Text.textPair>());
                }

                //Get category name
                long bookmark = streamReader.Position();
                streamReader.Seek(categoryNameOffset + offset, SeekOrigin.Begin);

                txt.categoryNames.Add(ReadCString(streamReader));

                //Get Category Info
                streamReader.Seek(categoryDataInfoOffset + offset, SeekOrigin.Begin);

                for (int sub = 0; sub < subCategoryCount; sub++)
                {
                    var categoryIndexOffset = streamReader.Read <int>();
                    var subCategoryId       = streamReader.Read <int>();
                    var categoryIndexCount  = streamReader.Read <int>();
                    var bookMarkSub         = streamReader.Position();

                    streamReader.Seek(categoryIndexOffset + offset, SeekOrigin.Begin);
                    for (int j = 0; j < categoryIndexCount; j++)
                    {
                        var  pair          = new PSO2Text.textPair();
                        int  nameLoc       = streamReader.Read <int>();
                        int  textLoc       = streamReader.Read <int>();
                        long bookmarkLocal = streamReader.Position();

                        streamReader.Seek(nameLoc + offset, SeekOrigin.Begin);
                        pair.name = ReadCString(streamReader);

                        streamReader.Seek(textLoc + offset, SeekOrigin.Begin);
                        pair.str = ReadUTF16String(streamReader, end);

                        txt.text[i][subCategoryId].Add(pair);
                        streamReader.Seek(bookmarkLocal, SeekOrigin.Begin);
                    }
                    streamReader.Seek(bookMarkSub, SeekOrigin.Begin);
                }

                streamReader.Seek(bookmark, SeekOrigin.Begin);
            }

#if DEBUG
            if (fileName != null)
            {
                StringBuilder output = new StringBuilder();

                for (int i = 0; i < txt.text.Count; i++)
                {
                    output.AppendLine(txt.categoryNames[i]);

                    for (int j = 0; j < txt.text[i].Count; j++)
                    {
                        output.AppendLine($"Group {j}");

                        for (int k = 0; k < txt.text[i][j].Count; k++)
                        {
                            var pair = txt.text[i][j][k];
                            output.AppendLine($"{pair.name} - {pair.str}");
                        }
                        output.AppendLine();
                    }
                    output.AppendLine();
                }

                File.WriteAllText(fileName + ".txt", output.ToString());
            }
#endif
            return(txt);
        }
        public static AquaMotion ReadAAI(string filePath)
        {
            using (Stream stream = (Stream) new FileStream(filePath, FileMode.Open))
                using (var streamReader = new BufferedStreamReader(stream, 8192))
                {
                    int fType = streamReader.Read <int>();
                    if (fType != FAA)
                    {
                        return(null);
                    }
                    streamReader.Seek(0xC, SeekOrigin.Current);

                    int innerFtype = streamReader.Read <int>();
                    int len        = streamReader.Read <int>();
                    streamReader.Seek(len - 0x8, SeekOrigin.Current);

                    int    animDataMagic = streamReader.Read <int>();
                    ushort nodeCount     = streamReader.Read <ushort>();
                    ushort sht_06        = streamReader.Read <ushort>();
                    ushort sht_08        = streamReader.Read <ushort>();
                    ushort sht_0C        = streamReader.Read <ushort>();
                    int    timeCount     = streamReader.Read <int>();

                    int finalFrame  = streamReader.Read <int>();
                    int unkAddress0 = streamReader.Read <int>();
                    int unkAddress1 = streamReader.Read <int>();
                    int unkAddress2 = streamReader.Read <int>();

                    int unkAddress3 = streamReader.Read <int>();
                    int unkAddress4 = streamReader.Read <int>();
                    int unkAddress5 = streamReader.Read <int>();
                    int unkAddress6 = streamReader.Read <int>();

                    int unkAddress7       = streamReader.Read <int>();
                    int unkAddress8       = streamReader.Read <int>();
                    int nodeDefEndAddress = streamReader.Read <int>();
                    int unkAddress9       = streamReader.Read <int>();

                    int unkAddress10 = streamReader.Read <int>();
                    int int_44       = streamReader.Read <int>();

                    int clumpCount = 0;
                    List <AnimDefinitionNode> nodes = new List <AnimDefinitionNode>();
                    int ct14 = 0;
                    int ct24 = 0;
                    int ct30 = 0;
                    int ct34 = 0;
                    int ct44 = 0;
                    for (int i = 0; i < nodeCount; i++)
                    {
                        AnimDefinitionNode node = new AnimDefinitionNode();
                        node.header0   = streamReader.Read <ushort>();
                        node.dataCount = streamReader.Read <ushort>();
                        node.len       = streamReader.Read <int>();
                        node.nameData  = streamReader.Read <PSO2String>();
                        node.name      = node.nameData.GetString();
                        for (int j = 0; j < node.dataCount; j++)
                        {
                            clumpCount++;
                            var       test = streamReader.Position().ToString("X");
                            DataClump dc   = new DataClump();
                            dc.dcStart = streamReader.Read <DataClumpStart>();
                            switch (dc.dcStart.dcType)
                            {
                            case 0x14:
                                ct14++;
                                dc.d14 = streamReader.Read <DataClump14>();
                                break;

                            case 0x24:
                                ct24++;
                                dc.d24 = streamReader.Read <DataClump24>();
                                break;

                            case 0x30:
                                ct30++;
                                dc.d30 = streamReader.Read <DataClump30>();
                                break;

                            case 0x34:
                                ct34++;
                                dc.d34      = streamReader.Read <DataClump34>();
                                dc.dcString = dc.d34.clumpName.GetString();
                                break;

                            case 0x44:
                                ct44++;
                                dc.d44      = streamReader.Read <DataClump44>();
                                dc.dcString = dc.d44.clumpName.GetString();
                                break;

                            default:
                                MessageBox.Show($"clumpSize {dc.dcStart.dcType.ToString("X")} at {streamReader.Position().ToString("X")} is unexpected!");
                                break;
                            }
                            node.data.Add(dc);
                        }
                        nodes.Add(node);
                    }

                    return(null);

                    var offsetTimes = streamReader.ReadOffsetTimeSets(streamReader.Position(), timeCount);
                    List <List <OffsetTimeSet> > setsList = new List <List <OffsetTimeSet> >();

                    for (int i = 0; i < offsetTimes.Count; i++)
                    {
                        streamReader.Seek(offsetTimes[i].offset, SeekOrigin.Begin);
                        var position     = streamReader.Position();
                        int keyNodeCount = streamReader.Read <int>();

                        List <OffsetTimeSet> sets = new List <OffsetTimeSet>();
                        for (int j = 0; j < keyNodeCount; j++)
                        {
                            OffsetTimeSet set = streamReader.Read <OffsetTimeSet>();
                            sets.Add(set);
                        }
                        setsList.Add(sets);
                    }
                }
            return(null);
        }
Beispiel #14
0
        public static void ReadFFUBorRDDA(this BufferedStreamReader streamReader, List <ffubStruct> ffubStructs, Dictionary <string, rddaStruct> rddaStructs,
                                          Dictionary <string, rddaStruct> imgRddaStructs, Dictionary <string, rddaStruct> vertRddaStructs, Dictionary <string, rddaStruct> faceRddaStructs, ref ffubStruct imgFfub, ref ffubStruct vertFfub, ref ffubStruct faceFfub)
        {
            long bookmark = streamReader.Position();

            int magic = streamReader.Read <int>();
            int len;

            switch (magic)
            {
            case ffub:
                var ffubData = streamReader.ReadFFUB(magic, out len);
                switch (ffubData.dataType)
                {
                case 0x2:
                    imgFfub = ffubData;
                    break;

                case 0x3:
                    vertFfub = ffubData;
                    break;

                case 0x9:
                    faceFfub = ffubData;
                    break;

                default:
                    ffubStructs.Add(ffubData);
                    Debug.WriteLine($"Unknown ffub type: {ffubData.dataType.ToString("X")}");
                    break;
                }
                break;

            case rdda:
                var    rddaData = streamReader.ReadRDDA(magic, out len);
                string md5      = $"{rddaData.md5_1.ToString("X")}{rddaData.md5_2.ToString("X")}";
                switch (rddaData.dataType)
                {
                case 0x2:
                    imgRddaStructs.Add(md5, rddaData);
                    break;

                case 0x3:
                    vertRddaStructs.Add(md5, rddaData);
                    break;

                case 0x9:
                    faceRddaStructs.Add(md5, rddaData);
                    break;

                default:
                    rddaStructs.Add(md5, rddaData);
                    Debug.WriteLine($"Unknown rdda type: {rddaData.dataType.ToString("X")}");
                    break;
                }
                break;

            default:
                throw new Exception(magic.ToString("X"));
            }
            streamReader.Seek(bookmark, SeekOrigin.Begin);
            streamReader.Seek(len, SeekOrigin.Current);
        }
        /// <summary>
        /// Reads an archive from a stream.
        /// </summary>
        /// <param name="stream">Stream pointing to the start of the archive.</param>
        /// <param name="archiveSize">Size of the archive file.</param>
        public ArchiveReader(Stream stream, int archiveSize)
        {
            _stream   = stream;
            _startPos = stream.Position;

            // Extract Data.
            using var streamReader = new BufferedStreamReader(stream, 2048);
            streamReader.Read(out int binCount);
            Groups = new Group[binCount];

            // Get group item counts.
            for (int x = 0; x < Groups.Length; x++)
            {
                Groups[x].Files = new Structs.Parser.File[streamReader.Read <byte>()];
            }

            // Alignment
            streamReader.Seek(Utilities.Utilities.RoundUp((int)streamReader.Position(), 4) - streamReader.Position(), SeekOrigin.Current);

            // Skip section containing first item for each group.
            streamReader.Seek(sizeof(short) * Groups.Length, SeekOrigin.Current);

            // Populate IDs
            for (int x = 0; x < Groups.Length; x++)
            {
                Groups[x].Id = streamReader.Read <ushort>();
            }

            // Populate offsets.
            int[] offsets = new int[Groups.Select(x => x.Files.Length).Sum()];
            for (int x = 0; x < offsets.Length; x++)
            {
                offsets[x] = streamReader.Read <int>();
            }

            int offsetIndex = 0;

            for (int x = 0; x < Groups.Length; x++)
            {
                var fileCount = Groups[x].Files.Length;
                for (int y = 0; y < fileCount; y++)
                {
                    // Do not fill if no more elements left.
                    if (offsetIndex >= offsets.Length)
                    {
                        break;
                    }

                    var offset          = (int)offsets[offsetIndex];
                    int nextOffsetIndex = offsetIndex;
                    offsetIndex += 1;

                    // Find next non-zero value within array; if not found, use archive size..
                    do
                    {
                        nextOffsetIndex += 1;
                    }while (nextOffsetIndex < offsets.Length && offsets[nextOffsetIndex] == 0);

                    var nextOffset = nextOffsetIndex < offsets.Length ? offsets[nextOffsetIndex] : archiveSize;

                    // Set offsets
                    Groups[x].Files[y].Offset = offset;
                    Groups[x].Files[y].Size   = nextOffset - offset;
                }
            }
        }
Beispiel #16
0
        static void DumpFpk(string filePath)
        {
            var fileDict  = new Dictionary <int, string>();
            var storeDict = new Dictionary <int, byte[]>();
            var luaFiles  = new List <string>();
            var refText   = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase).Substring(6), "FpkTool.txt");

            //Get name references if they exist
            if (File.Exists(refText))
            {
                Console.WriteLine("FpkTool.txt exists");
                using (StreamReader reader = File.OpenText(refText))
                {
                    string line;
                    while ((line = reader.ReadLine()) != null)
                    {
                        string[] fileKey = line.Split(' ');
                        fileDict.Add(int.Parse(fileKey[0], System.Globalization.NumberStyles.HexNumber), fileKey[1]);
                    }
                }
            }
            else
            {
                Console.WriteLine("FpkTool.txt does not exist");
            }

            //Extract files and apply names if applicable
            Console.WriteLine("Proceeding...");
            if (File.Exists(filePath))
            {
                var fpk = File.ReadAllBytes(filePath);
                using (var fileStream = new FileStream(filePath, FileMode.Open))
                    using (var streamReader = new BufferedStreamReader(fileStream, 8192))
                    {
                        List <FileEntry> table = new List <FileEntry>();

                        streamReader.Seek(0xC, SeekOrigin.Begin);
                        streamReader.Read <UInt32>(out UInt32 entryCount);

                        for (int i = 0; i < entryCount; i++)
                        {
                            streamReader.Read(out FileEntry value);
                            table.Add(value);
                        }
                        long tableEnd = streamReader.Position();

                        foreach (FileEntry entry in table)
                        {
                            storeDict.Add(entry.Hash, streamReader.ReadBytes(entry.Offset + tableEnd, (int)entry.Length));
                        }
                    }

                var outputDirectory = Path.Combine(Path.GetDirectoryName(filePath), Path.GetFileNameWithoutExtension(filePath));
                Directory.CreateDirectory(outputDirectory + "_");
                using (StreamWriter fpkList = new StreamWriter(outputDirectory + ".txt"))
                {
                    foreach (var file in storeDict)
                    {
                        string name;
                        if (fileDict.ContainsKey(file.Key))
                        {
                            name = fileDict[file.Key];
                        }
                        else
                        {
                            name = file.Key.ToString("X") + ".lua";
                        }
                        var fileOutput = Path.Combine(outputDirectory + "_", $"{name}");
                        File.WriteAllBytes(fileOutput, file.Value);
                        fpkList.WriteLine(file.Key.ToString("X") + " " + name);
                    }
                }
            }
        }
Beispiel #17
0
        //We're not realistically going to fully convert everything, but we can get vertex data and bones if nothing else
        //Returns an aqp ready for the ConvertToNGSPSO2Mesh method
        public static AquaObject ReadAXS(string filePath, out AquaNode aqn)
        {
            AquaObject aqp = new NGSAquaObject();

            aqn = new AquaNode();

            using (Stream stream = (Stream) new FileStream(filePath, FileMode.Open))
                using (var streamReader = new BufferedStreamReader(stream, 8192))
                {
                    Debug.WriteLine(Path.GetFileName(filePath));
                    long                            last__oaPos      = 0;
                    eertStruct                      eertNodes        = null;
                    ipnbStruct                      tempLpnbList     = null;
                    List <ffubStruct>               ffubList         = new List <ffubStruct>();
                    List <XgmiStruct>               xgmiList         = new List <XgmiStruct>();
                    List <string>                   texNames         = new List <string>();
                    List <MeshDefinitions>          meshDefList      = new List <MeshDefinitions>();
                    List <stamData>                 stamList         = new List <stamData>();
                    Dictionary <string, rddaStruct> rddaList         = new Dictionary <string, rddaStruct>();
                    Dictionary <string, rddaStruct> imgRddaList      = new Dictionary <string, rddaStruct>();
                    Dictionary <string, rddaStruct> vertRddaList     = new Dictionary <string, rddaStruct>();
                    Dictionary <string, rddaStruct> faceRddaList     = new Dictionary <string, rddaStruct>();
                    Dictionary <string, int>        xgmiIdByCombined = new Dictionary <string, int>();
                    Dictionary <string, int>        xgmiIdByUnique   = new Dictionary <string, int>();
                    ffubStruct                      imgFfub          = new ffubStruct();
                    ffubStruct                      vertFfub         = new ffubStruct();
                    ffubStruct                      faceFfub         = new ffubStruct();

                    var fType = streamReader.Read <int>();

                    var fsaLen = streamReader.Read <int>();
                    streamReader.Seek(0x8, SeekOrigin.Current);
                    //Go to Vert definition, node, material, and misc data
                    while (streamReader.Position() < fsaLen)
                    {
                        var tag  = streamReader.Peek <int>();
                        var test = Encoding.UTF8.GetString(BitConverter.GetBytes(tag));
                        Debug.WriteLine(streamReader.Position().ToString("X"));
                        Debug.WriteLine(test);
                        switch (tag)
                        {
                        case __oa:
                            last__oaPos = streamReader.Position();
                            streamReader.Seek(0xD0, SeekOrigin.Current);
                            break;

                        case FIA:
                            streamReader.Seek(0x10, SeekOrigin.Current);
                            break;

                        case __lm:
                            var stam = streamReader.ReadLM();
                            if (stam != null && stam.Count > 0)
                            {
                                stamList = stam;
                            }
                            break;

                        case __bm:
                            streamReader.ReadBM(meshDefList, tempLpnbList, stamList, last__oaPos);
                            break;

                        case lpnb:
                            tempLpnbList = streamReader.ReadIpnb();
                            break;

                        case eert:
                            eertNodes = streamReader.ReadEert();
                            break;

                        //case ssem:
                        //  streamReader.SkipBasicAXSStruct(); //Maybe use for material data later. Remember to store ordered id for _bm mesh entries for this
                        // break;
                        case Xgmi:
                            var xgmiData = streamReader.ReadXgmi();
                            if (!xgmiIdByCombined.ContainsKey(xgmiData.stamCombinedId))
                            {
                                xgmiIdByCombined.Add(xgmiData.stamCombinedId, xgmiList.Count);
                            }
                            xgmiIdByUnique.Add(xgmiData.stamUniqueId, xgmiList.Count);
                            xgmiList.Add(xgmiData);
                            break;

                        default:
                            streamReader.SkipBasicAXSStruct();
                            break;
                        }
                    }

                    //Assemble aqn from eert
                    if (eertNodes != null)
                    {
                        for (int i = 0; i < eertNodes.boneCount; i++)
                        {
                            var       rttaNode = eertNodes.rttaList[i];
                            Matrix4x4 mat      = Matrix4x4.Identity;

                            mat *= Matrix4x4.CreateScale(rttaNode.scale);

                            var rotation = Matrix4x4.CreateFromQuaternion(rttaNode.quatRot);

                            mat *= rotation;

                            mat *= Matrix4x4.CreateTranslation(rttaNode.pos);

                            var parentId = rttaNode.parentNodeId;

                            //If there's a parent, multiply by it
                            if (i != 0)
                            {
                                if (rttaNode.parentNodeId == -1)
                                {
                                    parentId = 0;
                                }
                                var pn           = aqn.nodeList[parentId];
                                var parentInvTfm = new Matrix4x4(pn.m1.X, pn.m1.Y, pn.m1.Z, pn.m1.W,
                                                                 pn.m2.X, pn.m2.Y, pn.m2.Z, pn.m2.W,
                                                                 pn.m3.X, pn.m3.Y, pn.m3.Z, pn.m3.W,
                                                                 pn.m4.X, pn.m4.Y, pn.m4.Z, pn.m4.W);
                                Matrix4x4.Invert(parentInvTfm, out var invParentInvTfm);
                                mat = mat * invParentInvTfm;
                            }
                            else
                            {
                                parentId = -1;
                            }
                            rttaNode.nodeMatrix = mat;

                            //Create AQN node
                            NODE aqNode = new NODE();
                            aqNode.animatedFlag = 1;
                            aqNode.parentId     = parentId;
                            aqNode.unkNode      = -1;
                            aqNode.pos          = rttaNode.pos;
                            aqNode.eulRot       = QuaternionToEuler(rttaNode.quatRot);

                            if (Math.Abs(aqNode.eulRot.Y) > 120)
                            {
                                aqNode.scale = new Vector3(-1, -1, -1);
                            }
                            else
                            {
                                aqNode.scale = new Vector3(1, 1, 1);
                            }
                            Matrix4x4.Invert(mat, out var invMat);
                            aqNode.m1       = new Vector4(invMat.M11, invMat.M12, invMat.M13, invMat.M14);
                            aqNode.m2       = new Vector4(invMat.M21, invMat.M22, invMat.M23, invMat.M24);
                            aqNode.m3       = new Vector4(invMat.M31, invMat.M32, invMat.M33, invMat.M34);
                            aqNode.m4       = new Vector4(invMat.M41, invMat.M42, invMat.M43, invMat.M44);
                            aqNode.boneName = rttaNode.nodeName;
                            Debug.WriteLine($"{i} " + aqNode.boneName.GetString());
                            aqn.nodeList.Add(aqNode);
                        }
                    }


                    //Go to mesh buffers
                    streamReader.Seek(fsaLen, SeekOrigin.Begin);
                    if (streamReader.Position() >= stream.Length)
                    {
                        return(null);
                    }

                    var fType2 = streamReader.Read <int>();
                    //Read mesh data
                    if (fType2 != FMA)
                    {
                        Debug.WriteLine("Unexpected struct in location of FMA!");
                        return(null);
                    }
                    streamReader.Seek(0xC, SeekOrigin.Current);

                    //Skip daeh
                    int meshSettingLen = streamReader.ReadDAEH();

                    //Read ffub and rdda
                    //Count mesh count here for now and store starts and ends of data
                    long meshSettingStart = streamReader.Position();
                    while (streamReader.Position() < meshSettingStart + meshSettingLen)
                    {
                        streamReader.ReadFFUBorRDDA(ffubList, rddaList, imgRddaList, vertRddaList, faceRddaList, ref imgFfub, ref vertFfub, ref faceFfub);
                    }

                    int meshCount = meshDefList.Count;

                    //Read image data
                    var ext = Path.GetExtension(filePath);
                    for (int i = 0; i < xgmiList.Count; i++)
                    {
                        var xgmiData      = xgmiList[i];
                        var imgBufferInfo = imgRddaList[$"{xgmiData.md5_1.ToString("X")}{xgmiData.md5_2.ToString("X")}"];
                        Debug.WriteLine($"Image set {i}: " + imgBufferInfo.md5_1.ToString("X") + " " + imgBufferInfo.dataStartOffset.ToString("X") + " " + imgBufferInfo.toTagStruct.ToString("X") + " " + (meshSettingStart + imgFfub.dataStartOffset + imgBufferInfo.dataStartOffset).ToString("X"));

                        var position     = meshSettingStart + imgFfub.dataStartOffset + imgBufferInfo.dataStartOffset;
                        var buffer       = streamReader.ReadBytes(position, imgBufferInfo.dataSize);
                        var outImagePath = filePath.Replace(ext, $"_tex_{i}" + ".dds");
                        texNames.Add(Path.GetFileName(outImagePath));
                        try
                        {
                            string name = Path.GetFileName(filePath);
                            Debug.WriteLine($"{name}_xgmi_{ i}");
                            var image = AIFMethods.GetImage(xgmiData, buffer);
                            File.WriteAllBytes(filePath.Replace(ext, $"_tex_{i}" + ".dds"), image);
                        }
                        catch (Exception exc)
                        {
#if DEBUG
                            string name = Path.GetFileName(filePath);
                            Debug.WriteLine($"Extract tex {i} failed.");
                            File.WriteAllBytes($"C:\\{name}_xgmiHeader_{i}.bin", xgmiData.GetBytes());
                            File.WriteAllBytes($"C:\\{name}_xgmiBuffer_{i}.bin", buffer);
                            Debug.WriteLine(exc.Message);
#endif
                        }
                        buffer = null;
                    }


                    //Read model data - Since ffubs are initialized, they default to 0.
                    int vertFfubPadding = imgFfub.structSize;
                    int faceFfubPadding = imgFfub.structSize + vertFfub.structSize;

                    for (int i = 0; i < meshCount; i++)
                    {
                        var mesh       = meshDefList[i];
                        var nodeMatrix = Matrix4x4.Identity;
                        for (int bn = 0; bn < eertNodes.boneCount; bn++)
                        {
                            var node = eertNodes.rttaList[bn];
                            if (node.meshNodePtr == mesh.oaPos)
                            {
                                nodeMatrix = node.nodeMatrix;
                                break;
                            }
                        }
                        var vertBufferInfo = vertRddaList[$"{mesh.salvStr.md5_1.ToString("X")}{mesh.salvStr.md5_2.ToString("X")}"];
                        var faceBufferInfo = faceRddaList[$"{mesh.lxdiStr.md5_1.ToString("X")}{mesh.lxdiStr.md5_2.ToString("X")}"];
                        Debug.WriteLine($"Vert set {i}: " + vertBufferInfo.md5_1.ToString("X") + " " + vertBufferInfo.dataStartOffset.ToString("X") + " " + vertBufferInfo.toTagStruct.ToString("X") + " " + (meshSettingStart + vertFfubPadding + vertFfub.dataStartOffset + vertBufferInfo.dataStartOffset).ToString("X"));
                        Debug.WriteLine($"Face set {i}: " + faceBufferInfo.md5_1.ToString("X") + " " + faceBufferInfo.dataStartOffset.ToString("X") + " " + faceBufferInfo.toTagStruct.ToString("X") + " " + (meshSettingStart + faceFfubPadding + faceFfub.dataStartOffset + faceBufferInfo.dataStartOffset).ToString("X"));

                        //Vert data
                        var             vertCount = vertBufferInfo.dataSize / mesh.salvStr.vertLen;
                        AquaObject.VTXL vtxl      = new AquaObject.VTXL();

                        streamReader.Seek((meshSettingStart + vertFfubPadding + vertFfub.dataStartOffset + vertBufferInfo.dataStartOffset), SeekOrigin.Begin);
                        AquaObjectMethods.ReadVTXL(streamReader, mesh.vtxe, vtxl, vertCount, mesh.vtxe.vertDataTypes.Count);
                        vtxl.convertToLegacyTypes();

                        //Fix vert transforms
                        for (int p = 0; p < vtxl.vertPositions.Count; p++)
                        {
                            vtxl.vertPositions[p] = Vector3.Transform(vtxl.vertPositions[p], nodeMatrix);
                            if (vtxl.vertNormals.Count > 0)
                            {
                                vtxl.vertNormals[p] = Vector3.TransformNormal(vtxl.vertNormals[p], nodeMatrix);
                            }
                        }


                        //Handle bone indices
                        if (mesh.ipnbStr != null && mesh.ipnbStr.shortList.Count > 0)
                        {
                            vtxl.bonePalette = (mesh.ipnbStr.shortList.ConvertAll(delegate(short num) {
                                return((ushort)num);
                            }));

                            //Convert the indices based on the global bone list as pso2 will expect
                            for (int bn = 0; bn < vtxl.bonePalette.Count; bn++)
                            {
                                vtxl.bonePalette[bn] = (ushort)mesh.lpnbStr.shortList[vtxl.bonePalette[bn]];
                            }
                        }

                        aqp.vtxlList.Add(vtxl);

                        //Face data
                        AquaObject.GenericTriangles genMesh = new AquaObject.GenericTriangles();

                        int        faceIndexCount = faceBufferInfo.dataSize / 2;
                        List <int> faceList       = new List <int>();

                        streamReader.Seek((meshSettingStart + faceFfubPadding + faceFfub.dataStartOffset + faceBufferInfo.dataStartOffset), SeekOrigin.Begin);
                        int maxStep = streamReader.Read <ushort>();
                        for (int fId = 0; fId < faceIndexCount - 1; fId++)
                        {
                            faceList.Add(streamReader.Read <ushort>());
                        }

                        //Convert the data to something usable with this algorithm and then destripify it.
                        List <ushort> triList = unpackInds(inverseWatermarkTransform(faceList, maxStep)).ConvertAll(delegate(int num) {
                            return((ushort)num);
                        });
                        var tempFaceData = new AquaObject.stripData()
                        {
                            triStrips = triList, format0xC33 = true, triIdCount = triList.Count
                        };
                        genMesh.triList = tempFaceData.GetTriangles();

                        //Extra
                        genMesh.vertCount = vertCount;
                        genMesh.matIdList = new List <int>(new int[genMesh.triList.Count]);
                        for (int j = 0; j < genMesh.matIdList.Count; j++)
                        {
                            genMesh.matIdList[j] = aqp.tempMats.Count;
                        }
                        aqp.tempTris.Add(genMesh);

                        //Material
                        var mat = new AquaObject.GenericMaterial();
                        mat.texNames = GetTexNames(mesh, xgmiIdByCombined, xgmiIdByUnique, texNames);
                        aqp.tempMats.Add(mat);
                    }

                    return(aqp);
                }
        }
        public void readVertexList(Matrix4x4 mat)
        {
            var vtxe = ReadNjVtxe(streamReader, be);

            streamReader.Seek(vtxe.vertexListOffset, SeekOrigin.Begin);
            var vtxl = new VTXL();

            bool readUv     = false;
            bool readNormal = false;
            bool readColor  = false;

            int size = (int)vtxe.vertexSize;

            //pos
            size -= 0xC;

            //Process bitflags
            if ((vtxe.vertexType & 0x01) != 0)
            {
                readUv = true;
                size  -= 0x8;
            }
            if ((vtxe.vertexType & 0x02) != 0)
            {
                readNormal = true;
                size      -= 0xC;
            }
            if ((vtxe.vertexType & 0x04) != 0)
            {
                readColor = true;
                size     -= 0x4;
            }

            if (size != 0)
            {
                Console.WriteLine($"Vert size is not 0 at vtxe {(streamReader.Position() - 0x10).ToString("X")}");
            }
            //Read vertices
            for (int i = 0; i < vtxe.vertexCount; i++)
            {
                var pos    = streamReader.ReadBEV3(be) * rootScale;
                var newPos = Vector3.Transform(pos, mat);
                vtxl.vertPositions.Add(newPos);

                if (readNormal)
                {
                    var nrm    = streamReader.ReadBEV3(be);
                    var newNrm = Vector3.TransformNormal(nrm, mat);

                    vtxl.vertNormals.Add(newNrm);
                }
                if (readColor)
                {
                    byte[] color = new byte[4];
                    color[0] = streamReader.Read <byte>();
                    color[1] = streamReader.Read <byte>();
                    color[2] = streamReader.Read <byte>();
                    color[3] = streamReader.Read <byte>();

                    vtxl.vertColors.Add(color);
                }
                if (readUv)
                {
                    vtxl.uv1List.Add(streamReader.ReadBEV2(be));
                }

                //skip unexpected sections
                if (size > 0)
                {
                    streamReader.Seek(size, SeekOrigin.Current);
                }
            }

            aqObj.vtxlList.Add(vtxl);
        }
Beispiel #19
0
        public static bool TryGuess(Stream stream, int streamLength)
        {
            var data = new BufferedStreamReader(stream, 4096);
            var pos  = stream.Position;

            try
            {
                var initialPos = data.Position();

                // Total Groups
                data.Read(out int binCount);

                // Safeguard against unlikely big files.
                if (binCount is > short.MaxValue or < 1)
                {
                    return(false);
                }

                // Total Items
                Span <byte> groups = stackalloc byte[binCount];
                for (int x = 0; x < binCount; x++)
                {
                    groups[x] = data.Read <byte>();
                }

                // Alignment
                data.Seek(Utilities.RoundUp((int)data.Position(), 4) - data.Position(), SeekOrigin.Current);

                // Now compare against total running file count.
                int currentCount  = 0;
                int expectedCount = 0;

                for (int x = 0; x < binCount; x++)
                {
                    expectedCount = data.Read <short>();
                    if (currentCount != expectedCount)
                    {
                        return(false);
                    }

                    currentCount += groups[x];
                }

                // Skip group ids.
                data.Seek(sizeof(short) * binCount, SeekOrigin.Current);

                // Check offsets.
                var firstFileOffset = data.Peek <int>();

                if (streamLength != -1 && firstFileOffset > streamLength)
                {
                    return(false);
                }

                // Seek to expected first file position.
                data.Seek(sizeof(int) * currentCount, SeekOrigin.Current);
                data.Seek(Utilities.RoundUp((int)data.Position(), 16), SeekOrigin.Begin); // Alignment

                // Try checking if first file is past expected header size, or empty 0.
                var currentOffset = data.Position() - initialPos;
                return(firstFileOffset == 0 || firstFileOffset >= (currentOffset));
            }
            finally
            {
                stream.Position = pos;
            }
        }
Beispiel #20
0
        public static void ReadBM(this BufferedStreamReader streamReader, List <MeshDefinitions> defs, ipnbStruct tempLpnbList, List <stamData> stamList, long last__oaPos)
        {
            int             counter = 0;
            MeshDefinitions mesh    = null;
            var             bmStart = streamReader.Position();

            streamReader.Read <int>();
            var bmEnd = streamReader.Read <int>() + bmStart;

            streamReader.Seek(0x8, SeekOrigin.Current);
            while (streamReader.Position() < bmEnd)
            {
                var tag = streamReader.Peek <int>();
                switch (tag)
                {
                case ydbm:
                    if (mesh != null)
                    {
                        Debug.WriteLine(defs.Count);
                        defs.Add(mesh);
                    }
                    mesh         = new MeshDefinitions();
                    mesh.oaPos   = last__oaPos;
                    mesh.lpnbStr = tempLpnbList;
                    mesh.ydbmStr = streamReader.ReadYdbm();
                    if (stamList.Count > counter)
                    {
                        mesh.stam = stamList[counter];
                    }
                    else if (stamList.Count > 0)
                    {
                        mesh.stam = stamList[stamList.Count - 1];
                    }
                    else
                    {
                        mesh.stam = null;
                    }
                    counter++;
                    break;

                case lxdi:
                    mesh.lxdiStr = streamReader.ReadLxdi();
                    break;

                case salv:
                    mesh.salvStr = streamReader.ReadSalv();
                    mesh.vtxe    = GenerateGenericPSO2VTXE(mesh.salvStr.vertDef0, mesh.salvStr.vertDef1, mesh.salvStr.vertDef2, mesh.salvStr.vertDef3, mesh.salvStr.vertDef4, mesh.salvStr.vertLen);
                    break;

                case ipnb:
                    mesh.ipnbStr = streamReader.ReadIpnb();
                    break;

                default:
                    streamReader.SkipBasicAXSStruct();
                    break;
                }
            }
            if (mesh != null)
            {
                Debug.WriteLine(defs.Count);
                defs.Add(mesh);
            }
        }