Create() 공개 정적인 메소드

Create a QbKey from a string, the string can be an ascii CRC
public static Create ( string text ) : QbKey
text string
리턴 QbKey
예제 #1
0
        public override void Construct(BinaryEndianReader br, QbItemType type)
        {
            //System.Diagnostics.Debug.WriteLine(string.Format("{0} - 0x{1}", type.ToString(), (base.StreamPos(br) - 4).ToString("X").PadLeft(8, '0')));

            base.Construct(br, type);

            _values = new QbKey[base.ItemCount];

            uint   crc;
            string debug;

            for (int i = 0; i < base.ItemCount; i++)
            {
                crc   = br.ReadUInt32(base.Root.PakFormat.EndianType);
                debug = this.Root.LookupDebugName(crc);
                if (debug.Length != 0)
                {
                    _values[i] = QbKey.Create(crc, debug);
                }
                else
                {
                    _values[i] = QbKey.Create(crc);
                }
            }

            base.ConstructEnd(br);
        }
예제 #2
0
        /// <summary>
        /// Rename the filename and set the data types
        /// </summary>
        /// <param name="newFullQbFilename">Full QB filename</param>
        /// <param name="fileType">.qb or .sqb=QB, .mqb=mid, .img=img .dbg=dbg  etc</param>
        /// <param name="extension">.ngc for Wii for example</param>
        /// <param name="baseOn">base the qbKeys that are present on the passed item</param>
        public void SetFilename(string newFullQbFilename, QbKey itemType, string extension, PakHeaderItem baseOn)
        {
            if (newFullQbFilename.Length > PakHeaderItem.FileNameMaxLength)
            {
                throw new ApplicationException("newQbFilename is too long");
            }

            if (!itemType.HasText || itemType.Text.Length == 0)
            {
                throw new ApplicationException("fileType is not recognised");
            }

            //filename is stored in the header
            if ((this.Flags & PakHeaderFlags.Filename) == PakHeaderFlags.Filename)
            {
                this.Filename          = newFullQbFilename;
                this.FullFilenameQbKey = 0;
            }
            else
            {
                this.Filename = QbKey.Create(newFullQbFilename).Crc.ToString("X").PadLeft(8, '0').ToLower();

                if (baseOn == null || baseOn.FullFilenameQbKey != 0)
                {
                    this.FullFilenameQbKey = QbKey.Create(newFullQbFilename).Crc;
                }
                else
                {
                    this.FullFilenameQbKey = 0;
                }
            }

            string[] pts = newFullQbFilename.Split('.');

            string nameOnly = pts[0];

            if (baseOn == null || baseOn.FullFilenameQbKey != 0)
            {
                this.NameOnlyCrc = QbKey.Create(nameOnly).Crc;
            }
            else
            {
                this.NameOnlyCrc = 0;
            }


            this.FileType = itemType;

            if (baseOn == null || baseOn.PakFullFileNameQbKey != 0)
            {
                this.PakFullFileNameQbKey = QbKey.Create(newFullQbFilename).Crc;
            }
            else
            {
                this.PakFullFileNameQbKey = 0;
            }
        }
예제 #3
0
        public QbKey ToQbKey()
        {
            Type t = typeof(QbKey);

            if (t != _type)
            {
                throw new ApplicationException(getToError(_type, t));
            }
            return(QbKey.Create(_value));
        }
예제 #4
0
 public QbKey Clone()
 {
     if (this.HasText)
     {
         return(QbKey.Create(this.Text));
     }
     else
     {
         return(QbKey.Create(this.Crc));
     }
 }
예제 #5
0
 private void loadNonDebugQbKey()
 {
     if (File.Exists(FullNonDebugQbKeyFilename))
     {
         string[] f;
         foreach (string s in File.ReadAllLines(FullNonDebugQbKeyFilename))
         {
             f = s.Split('|');
             AddNonDebugQbKey(QbKey.Create(uint.Parse(f[0].Substring(2), System.Globalization.NumberStyles.HexNumber), f[1]), f[2], null);
         }
     }
 }
예제 #6
0
        /// <summary>
        /// The FileId is based on the filename, this will recalculate it, GH3 has a bug where the first character is missing from the path.
        /// The FileId doesn't appear to affect the game, it may just need to be unique
        /// </summary>
        public void SetNewFileId()
        {
            uint fileId = QbKey.Create(this.Filename).Crc;

            foreach (QbItemBase qbi in this.Items)
            {
                if (qbi.QbItemType != QbItemType.Unknown)
                {
                    qbi.FileId = fileId;
                }
            }
        }
예제 #7
0
        static PakHeaderItem()
        {                             // qb,     qb,    debug,   image,  midi
            string[] s = new string[] { ".qb", ".sqb", ".dbg", ".img", ".mqb", ".tex", ".skin", ".cam", ".col", ".fam", ".fnc", ".fnt", ".fnv", ".gap",
                                        ".hkc", ".imv", ".last", ".mcol", ".mdl", ".mdv", ".nav", ".nqb", ".oba", ".pfx", ".pimg", ".png", ".rag", ".rnb",
                                        ".rnb_lvl", ".rnb_mdl", ".scn", ".scv", ".shd", ".ska", ".ske", ".skiv", ".stex", ".table", ".tvx", ".wav", ".empty",
                                        ".clt", ".jam", ".note", ".nqb", ".perf", ".pimv", ".qs", ".qs.br", ".qs.de", ".qs.en", ".qs.es", ".qs.fr", ".qs.it",
                                        ".raw", ".rgn", ".trkobj", ".xml" };

            _itemTypes = new QbKey[s.Length];
            for (int i = 0; i < s.Length; i++)
            {
                _itemTypes[i] = QbKey.Create(s[i]);
            }
        }
예제 #8
0
        public override void Create(QbItemType type)
        {
            if (type != QbItemType.SectionQbKey && type != QbItemType.SectionQbKeyString && type != QbItemType.SectionQbKeyStringQs &&
                type != QbItemType.ArrayQbKey && type != QbItemType.ArrayQbKeyString && type != QbItemType.ArrayQbKeyStringQs &&
                type != QbItemType.StructItemQbKey && type != QbItemType.StructItemQbKeyString && type != QbItemType.StructItemQbKeyStringQs)
            {
                throw new ApplicationException(string.Format("type '{0}' is not a QB key item type", type.ToString()));
            }

            base.Create(type);

            this.Values = new QbKey[1]; //sets item count
            _values[0]  = QbKey.Create(0);
        }
예제 #9
0
        /// <summary>
        /// Convert text representations
        /// </summary>
        /// <param name="text"></param>
        /// <param name="toType">Type to convert to</param>
        /// <returns></returns>
        private string convert(Type toType)
        {
            byte[] b = null;
            float  f;
            uint   u;
            int    i;
            string result = _value;

            if (_currType == null)
            {
                _currType = _type;
            }

            if (_currType == toType)
            {
                return(_value);
            }

            if (!this.CanConvertTo(toType))
            {
                return(_value);
            }

            //if QBKey then swap between Hex and String
            if (_type == typeof(QbKey))
            {
                QbKey qb = QbKey.Create(_value);
                if (_currType == typeof(byte[]) && toType == typeof(string))
                {
                    if (_qbKey == qb)
                    {
                        return(_qbKey.ToString());
                    }
                    else
                    {
                        return(qb.ToString());
                    }
                }
                else if (_currType == typeof(string) && toType == typeof(byte[]))
                {
                    if (_value.Trim().Length != 0)
                    {
                        _qbKey = QbKey.Create(_value);
                    }
                    return(_qbKey.Crc.ToString("X").PadLeft(8, '0'));
                }
                else
                {
                    return(_value);
                }
            }


            //get the data into a byte array
            if (_currType == typeof(float))
            {
                if (float.TryParse(_value, out f))
                {
                    b = BitConverter.GetBytes(f);
                }
            }
            else if (_currType == typeof(uint))
            {
                if (uint.TryParse(_value, out u))
                {
                    b = BitConverter.GetBytes(u);
                }
            }
            else if (_currType == typeof(int))
            {
                if (int.TryParse(_value, out i))
                {
                    b = BitConverter.GetBytes(i);
                }
            }
            else if (_currType == typeof(byte[]))
            {
                if (_value.Length > 2)
                {
                    b = new byte[_value.Length / 2];
                    for (int c = 0; c < _value.Length; c += 2)
                    {
                        b[c / 2] = byte.Parse(_value.Substring(c, 2), System.Globalization.NumberStyles.HexNumber);
                    }
                    if (_typeNumeric && BitConverter.IsLittleEndian)
                    {
                        Array.Reverse(b);
                    }
                }
            }
            else if (_currType == typeof(string))
            {
                b = Encoding.Default.GetBytes(_value);
            }


            //else
            //    throw new ArgumentOutOfRangeException(string.Format("{0} is not supported", _currType.FullName));

            if (b != null)
            {
                //convert the data to the new type
                if (toType == typeof(float))
                {
                    f      = BitConverter.ToSingle(b, 0);
                    result = f.ToString();
                }
                else if (toType == typeof(uint))
                {
                    u      = BitConverter.ToUInt32(b, 0);
                    result = u.ToString();
                }
                else if (toType == typeof(int))
                {
                    i      = BitConverter.ToInt32(b, 0);
                    result = i.ToString();
                }
                else if (toType == typeof(byte[]))
                {
                    StringBuilder sb = new StringBuilder();
                    if (_typeNumeric && BitConverter.IsLittleEndian)
                    {
                        Array.Reverse(b);
                    }
                    foreach (byte x in b)
                    {
                        sb.Append(x.ToString("X").PadLeft(2, '0'));
                    }
                    result = sb.ToString();
                }
                else if (toType == typeof(string))
                {
                    result = Encoding.Default.GetString(b);
                }

                //else
                //    throw new ArgumentOutOfRangeException(string.Format("{0} is not supported", toType.FullName));
            }
            return(result);
        }
예제 #10
0
        public static void SetGenericItems(QbItemBase item, List <GenericQbItem> gItems)
        {
            MemberInfo[] ms = item.GetType().FindMembers(MemberTypes.Property,
                                                         /*BindingFlags.DeclaredOnly |*/ BindingFlags.Instance | BindingFlags.Public,
                                                         Type.FilterName, "*");

            int                  i = 0;
            GenericQbItem        gi;
            List <GenericQbItem> list = null;

            if (gItems.Count == 0)
            {
                //test if this is an array item
                GenericQbItem gqi = QbFile.CreateGenericArrayItem(item);

                //null if not an array type
                if (gqi != null)
                {
                    //use this item to identify the array to set to 0 items
                    MemberInfo m = Array.Find(ms, delegate(MemberInfo mi)
                    {
                        return(mi.Name == gqi.SourceProperty);
                    });
                    if (m != null)
                    {
                        Type t = ((PropertyInfo)m).GetValue(item, null).GetType();
                        if (t == typeof(QbKey[]))
                        {
                            ((PropertyInfo)m).SetValue(item, new QbKey[0], null);
                        }
                        else if (t == typeof(float[]))
                        {
                            ((PropertyInfo)m).SetValue(item, new float[0], null);
                        }
                        else if (t == typeof(uint[]))
                        {
                            ((PropertyInfo)m).SetValue(item, new uint[0], null);
                        }
                        else if (t == typeof(int[]))
                        {
                            ((PropertyInfo)m).SetValue(item, new int[0], null);
                        }
                        else if (t == typeof(string[]))
                        {
                            ((PropertyInfo)m).SetValue(item, new string[0], null);
                        }
                    }
                }
            }


            while (i < gItems.Count)
            {
                gi = gItems[i++];

                if (gi.ReadOnly)
                {
                    continue;
                }

                //list = null;

                list = new List <GenericQbItem>();
                list.Add(gi);
                while (i < gItems.Count && gi.SourceProperty == gItems[i].SourceProperty)
                {
                    list.Add(gItems[i++]);
                }

                MemberInfo m = Array.Find(ms, delegate(MemberInfo mi)
                {
                    return(mi.Name == gi.SourceProperty);
                });

                if (m != null)
                {
                    Type t = ((PropertyInfo)m).GetValue(item, null).GetType();
                    if (t == typeof(QbKey[]))
                    {
                        QbKey[] qb = new QbKey[list.Count];
                        QbKey   q;
                        string  qS;

                        for (int c = 0; c < list.Count; c++)
                        {
                            q  = list[c].ToQbKey();
                            qS = item.Root.LookupDebugName(q.Crc);
                            if (qS.Length != 0)
                            {
                                q = QbKey.Create(q.Crc, qS);
                            }
                            qb[c] = q;
                        }
                        ((PropertyInfo)m).SetValue(item, qb, null);
                    }
                    else if (t == typeof(float[]))
                    {
                        float[] f = new float[list.Count];
                        for (int c = 0; c < list.Count; c++)
                        {
                            f[c] = list[c].ToSingle();
                        }
                        ((PropertyInfo)m).SetValue(item, f, null);
                    }
                    else if (t == typeof(uint[]))
                    {
                        uint[] ui = new uint[list.Count];
                        for (int c = 0; c < list.Count; c++)
                        {
                            ui[c] = list[c].ToUInt32();
                        }
                        ((PropertyInfo)m).SetValue(item, ui, null);
                    }
                    else if (t == typeof(int[]))
                    {
                        int[] si = new int[list.Count];
                        for (int c = 0; c < list.Count; c++)
                        {
                            si[c] = list[c].ToInt32();
                        }
                        ((PropertyInfo)m).SetValue(item, si, null);
                    }
                    else if (t == typeof(string[]))
                    {
                        string[] s = new string[list.Count];
                        for (int c = 0; c < list.Count; c++)
                        {
                            s[c] = list[c].ToString();
                        }
                        ((PropertyInfo)m).SetValue(item, s, null);
                    }
                    else if (t == typeof(QbKey))
                    {
                        QbKey  q  = gi.ToQbKey();
                        string qS = item.Root.LookupDebugName(q.Crc);
                        if (qS.Length != 0)
                        {
                            q = QbKey.Create(q.Crc, qS);
                        }
                        ((PropertyInfo)m).SetValue(item, q, null);
                    }
                    else if (t == typeof(float))
                    {
                        ((PropertyInfo)m).SetValue(item, gi.ToSingle(), null);
                    }
                    else if (t == typeof(uint))
                    {
                        ((PropertyInfo)m).SetValue(item, gi.ToUInt32(), null);
                    }
                    else if (t == typeof(int))
                    {
                        ((PropertyInfo)m).SetValue(item, gi.ToInt32(), null);
                    }
                    else if (t == typeof(string))
                    {
                        ((PropertyInfo)m).SetValue(item, gi.ToString(), null);
                    }
                    else if (t == typeof(byte[]))
                    {
                        ((PropertyInfo)m).SetValue(item, gi.ToByteArray(), null);
                    }
                    else
                    {
                        throw new ApplicationException(string.Format("DataType {0} not supported.", t.Name));
                    }
                }
            }
        }
예제 #11
0
        private void replaceFile(string qbFilename, long newLength, bool remove, WriteDataToStream callback)
        {
            int filePad = _pakFormat.FilePadSize;

            PakHeaderItem phi = null;

            if (_pakHeaders.ContainsKey(qbFilename.ToLower()))
            {
                phi = _pakHeaders[qbFilename.ToLower()];
            }
            else
            {
                string fqk = QbKey.Create(qbFilename).Crc.ToString("X").PadLeft(8, '0').ToLower();

                if (_pakHeaders.ContainsKey(fqk))
                {
                    phi = _pakHeaders[fqk];
                }
            }

            if (phi != null)
            {
                long pad = filePad - (newLength % filePad);
                if (pad == filePad)
                {
                    pad = 0;
                }

                string newPakFilename = string.Format("{0}_{1}", _pakFormat.FullPakFilename, Guid.NewGuid().ToString("N"));
                string newPabFilename = string.Format("{0}_{1}", _pakFormat.FullPabFilename, Guid.NewGuid().ToString("N"));

                uint minOffset  = uint.MaxValue;
                bool itemFound  = false;
                uint nextOffset = 0;

                foreach (PakHeaderItem ph in _pakHeaders.Values)
                {
                    if (itemFound)
                    {
                        nextOffset = ph.FileOffset + ph.HeaderStart;
                        itemFound  = false; //don't enter this if again
                    }

                    if (object.ReferenceEquals(phi, ph))
                    {
                        itemFound = true;
                    }

                    if (ph.HeaderStart + ph.FileOffset < minOffset)
                    {
                        minOffset = ph.HeaderStart + ph.FileOffset;
                    }
                }

                uint lastItemPad = 0;
                int  repPad      = filePad - ((int)phi.FileLength % filePad);
                if (repPad == filePad)
                {
                    repPad = 0;
                }

                //previously badly padded or last file
                if (nextOffset != 0 && (nextOffset - (phi.FileOffset + phi.HeaderStart)) % filePad != 0)
                {
                    repPad = (int)((nextOffset - (phi.FileOffset + phi.HeaderStart)) - phi.FileLength);
                }


                //position of the LAST header item
                long lastHeaderPos = 0;
                //the length of all the headers (like pak when there's a pab) with padding
                long allHeadersLen = minOffset;
                //position in the input file where our file is to be replaced (not including header pos)
                long fileReplacePos = (phi.HeaderStart + phi.FileOffset) - allHeadersLen;
                //position in the input file after the file that is to be replaced
                long fileAfterReplacePos = fileReplacePos + phi.FileLength + repPad; //item size before modifying header

                //open input pak
                using (FileStream fsPakI = File.Open(_pakFilename, FileMode.Open, FileAccess.Read))
                {
                    using (BinaryEndianReader brPakI = new BinaryEndianReader(fsPakI))
                    {
                        //open output pak temp file
                        using (FileStream fsPakO = File.Create(newPakFilename))
                        {
                            using (BinaryEndianWriter bwPakO = new BinaryEndianWriter(fsPakO))
                            {
                                long diffLen = 0;

                                //do not compensate for missing header when using zlib compression as the header is padded
                                if (remove && _pakFormat.CompressionType != CompressionType.ZLibChunk) //we need to cater for the header being removed on all items before it.
                                {
                                    diffLen = PakHeaderItem.FullHeaderLength;
                                    if ((phi.Flags & PakHeaderFlags.Filename) != PakHeaderFlags.Filename)
                                    {
                                        diffLen -= PakHeaderItem.FileNameMaxLength;
                                    }
                                }


                                //write out the headers
                                foreach (PakHeaderItem ph in _pakHeaders.Values)
                                {
                                    //apply offset change before finding file to be replaced
                                    //this will prevents the offset of the replaced file being changed
                                    ph.FileOffset = (uint)(ph.FileOffset - (long)diffLen);
                                    if (object.ReferenceEquals(phi, ph))
                                    {
                                        if (remove)
                                        {
                                            long remPad = filePad - (phi.FileLength % filePad);
                                            if (remPad == filePad)
                                            {
                                                remPad = 0;
                                            }

                                            diffLen = phi.FileLength + remPad; //now cater for the difference in file size
                                        }
                                        else
                                        {
                                            diffLen       = (long)((ph.FileLength + repPad) - (newLength + pad));
                                            ph.FileLength = (uint)newLength; //0 for remove
                                        }
                                    }

                                    lastHeaderPos += PakHeaderItem.FullHeaderLength;

                                    if (!(remove && object.ReferenceEquals(phi, ph)))
                                    {
                                        writeHeaderItem(bwPakO, ph);
                                    }


                                    if ((ph.Flags & PakHeaderFlags.Filename) != PakHeaderFlags.Filename)
                                    {
                                        lastHeaderPos -= PakHeaderItem.FileNameMaxLength;
                                    }
                                }

                                //Move to the "last" header
                                fsPakI.Seek(lastHeaderPos, SeekOrigin.Begin);

                                //write out "last" HeaderType
                                bwPakO.Write(brPakI.ReadBytes(4));

                                //Modify and write the offset of the "last" header's data
                                uint lastOffset = brPakI.ReadUInt32(_pakFormat.EndianType);
                                lastOffset = (uint)(lastOffset - (long)diffLen);

                                //fix bad padding on last file
                                if (nextOffset == 0 && ((lastOffset - (phi.FileOffset + phi.HeaderStart) % filePad) % filePad) != 0)
                                {
                                    lastItemPad = (uint)filePad - (uint)(lastOffset % filePad);
                                    lastOffset += lastItemPad;
                                }

                                bwPakO.Write(lastOffset, _pakFormat.EndianType);

                                //write out the end of the last header
                                copyData(fsPakI, fsPakO, allHeadersLen - fsPakI.Position);
                            }
                        }
                    }
                }

                //open input pak
                using (FileStream fsPakI = File.Open(_requiresPab ? _pakFormat.FullPabFilename : _pakFilename, FileMode.Open, FileAccess.Read))
                {
                    using (BinaryEndianReader brPakI = new BinaryEndianReader(fsPakI))
                    {
                        //open output pak temp file
                        using (FileStream fsPakO = _requiresPab ? File.Open(newPabFilename, FileMode.Create) : File.Open(newPakFilename, FileMode.Append))
                        {
                            using (BinaryEndianWriter bwPakO = new BinaryEndianWriter(fsPakO))
                            {
                                if (!_requiresPab)
                                {
                                    fsPakI.Seek(allHeadersLen, SeekOrigin.Begin);
                                }

                                //Write out the data starting from the last header to the start of the file to be replaced (minus the length of the type and offset)
                                copyData(fsPakI, fsPakO, fileReplacePos);

                                //Write the new file into the pak file
                                int pos = (int)fsPakO.Position;
                                callback(fsPakO);
                                if (pad != 0)
                                {
                                    fsPakO.Write(new byte[pad], 0, (int)pad);
                                }

                                if (!_requiresPab)
                                {
                                    fileAfterReplacePos += allHeadersLen;
                                }

                                if (lastItemPad != 0)
                                {
                                    fileAfterReplacePos -= lastItemPad; // a bit of a hack as this was not applied when this var was set as we didn't know the values
                                }
                                //write the remainder of source the pak file
                                fsPakI.Seek(fileAfterReplacePos, SeekOrigin.Begin);
                                copyData(fsPakI, fsPakO, fsPakI.Length - fileAfterReplacePos);

                                fsPakO.Flush();
                            }
                        }
                    }
                }

                fixUncompressedFileLengths(newPakFilename, newPabFilename);


                File.Delete(_pakFilename);
                File.Move(newPakFilename, _pakFilename);
                if (_requiresPab)
                {
                    File.Delete(_pakFormat.FullPabFilename);
                    File.Move(newPabFilename, _pakFormat.FullPabFilename);
                }


                _pakFormat.Compress();
            }
            else
            {
                throw new ApplicationException(string.Format("'{0}' does not exist in '{1}'", qbFilename, _pakFilename));
            }
        }
예제 #12
0
        private void parsePak(PakFormat pakFormat, bool debugFile)
        {
            _debugFile   = debugFile;
            _pakFormat   = pakFormat;
            _pakFilename = (!_debugFile ? _pakFormat.FullPakFilename : _pakFormat.FullDebugFilename);

            Dictionary <uint, PakDbgQbKey> qbKeyFilenames = new Dictionary <uint, PakDbgQbKey>();

            //if PC or xbox then we need to look up the filename from the debug file
            //create a PakEditor and load the debug pak, then load all internal debug files, add the first line to our filenames dictionary
            if (!debugFile) // && (_pakFormat.PakFormatType == PakFormatType.PC || _pakFormat.PakFormatType == PakFormatType.XBox))
            {
                try
                {
                    _pakFormat.Decompress();
                    _pakFilename = _pakFormat.FullPakFilename;
                }
                catch (Exception ex)
                {
                    throw new Exception("Decompression Error", ex);
                }


                if (_pakFormat.DebugFileExists && _debugFile) // cancer
                {
                    string    debugFileContents;
                    string    filename;
                    uint      crc;
                    PakEditor pakDebug = new PakEditor(new PakFormat(_pakFormat.FullDebugFilename, "", _pakFormat.FullDebugFilename, _pakFormat.PakFormatType), true);
                    foreach (PakHeaderItem dphi in pakDebug.Headers.Values)
                    {
                        debugFileContents = string.Empty;
                        filename          = string.Empty;
                        crc = 0;
                        if (dphi.FullFilenameQbKey != 0)
                        {
                            crc = dphi.FullFilenameQbKey;
                        }
                        else if (dphi.PakFullFileNameQbKey != 0)
                        {
                            crc = dphi.PakFullFileNameQbKey;
                        }
                        else if (dphi.NameOnlyCrc != 0)
                        {
                            crc = dphi.NameOnlyCrc;
                        }

                        if (crc != 0)
                        {
                            filename = crc.ToString("X").PadLeft(8, '0');
                            if (pakDebug.Headers.ContainsKey(filename.ToLower()))
                            {
                                debugFileContents = pakDebug.ExtractFileToString(filename);

                                if (debugFileContents.Length != 0)
                                {
                                    addDebugFilename(debugFileContents, qbKeyFilenames, crc);
                                }
                            }
                        }
                    }
                }
            }

            long minOffset = uint.MaxValue;
            long maxOffset = 0;

            _pakHeaders = new Dictionary <string, PakHeaderItem>();

            using (Stream st = File.Open(_pakFilename, FileMode.Open, FileAccess.Read))
            {
                _pakFileLength = st.Length;

                using (BinaryEndianReader br = new BinaryEndianReader(st))
                {
                    PakHeaderItem phi = null;

                    QbKey lastQbKey    = QbKey.Create("last");
                    QbKey dotLastQbKey = QbKey.Create(".last");

                    do
                    {
                        phi = new PakHeaderItem();

                        phi.HeaderStart   = (uint)st.Position;
                        phi.IsStoredInPak = true;

                        phi.FileType = QbKey.Create(br.ReadUInt32(_pakFormat.EndianType));

                        //if the entry has the file type of last then we're done
                        if (phi.FileType == lastQbKey || phi.FileType == dotLastQbKey)
                        {
                            break;
                        }

                        phi.FileOffset           = br.ReadUInt32(_pakFormat.EndianType);
                        phi.FileLength           = br.ReadUInt32(_pakFormat.EndianType);
                        phi.PakFullFileNameQbKey = br.ReadUInt32(_pakFormat.EndianType);
                        phi.FullFilenameQbKey    = br.ReadUInt32(_pakFormat.EndianType);
                        phi.NameOnlyCrc          = br.ReadUInt32(_pakFormat.EndianType);
                        phi.Unknown = br.ReadUInt32(_pakFormat.EndianType);
                        phi.Flags   = (PakHeaderFlags)br.ReadUInt32(_pakFormat.EndianType);

                        if ((phi.Flags & PakHeaderFlags.Filename) != PakHeaderFlags.Filename)
                        {
                            uint crc = 0;

                            //get any Crc
                            if (phi.FullFilenameQbKey != 0)
                            {
                                crc = phi.FullFilenameQbKey;
                            }
                            else if (phi.PakFullFileNameQbKey != 0)
                            {
                                crc = phi.PakFullFileNameQbKey;
                            }
                            else if (phi.NameOnlyCrc != 0)
                            {
                                crc = phi.NameOnlyCrc;
                            }

                            if (!debugFile)
                            {
                                uint crc2 = 0;
                                //get a crc that exists in the debug names
                                if (qbKeyFilenames.ContainsKey(phi.FullFilenameQbKey))
                                {
                                    crc2 = phi.FullFilenameQbKey;
                                }
                                else if (qbKeyFilenames.ContainsKey(phi.PakFullFileNameQbKey))
                                {
                                    crc2 = phi.PakFullFileNameQbKey;
                                }
                                else if (qbKeyFilenames.ContainsKey(phi.NameOnlyCrc))
                                {
                                    crc2 = phi.NameOnlyCrc;
                                }

                                //if 0 then get any crc
                                if (crc2 != 0)
                                {
                                    phi.Filename   = qbKeyFilenames[crc2].Filename;
                                    phi.DebugQbKey = qbKeyFilenames[crc2].DebugQbKey;
                                    crc            = crc2;
                                }
                            }

                            if (phi.Filename == null)
                            {
                                if (crc != 0)
                                {
                                    phi.Filename = crc.ToString("X").PadLeft(8, '0');
                                }
                                else
                                {
                                    phi.Filename = string.Format("Unknown={0}", phi.HeaderStart.ToString("X").PadLeft(8, '0'));
                                }
                            }
                        }
                        else
                        {
                            phi.Filename = UTF8Encoding.UTF8.GetString(br.ReadBytes(PakHeaderItem.FileNameMaxLength)).TrimEnd(new char[] { '\0' });
                        }

                        try
                        {
                            _pakHeaders.Add(phi.Filename.ToLower(), phi);
                        }
                        catch (Exception ex)
                        {
                            throw new ApplicationException(string.Format("Error adding '{0}' to headers: {1}", phi.Filename, ex.Message));
                        }

                        if (phi.HeaderStart + phi.FileOffset < minOffset)
                        {
                            minOffset = phi.HeaderStart + phi.FileOffset;
                        }

                        if (phi.HeaderStart + phi.FileOffset > maxOffset)
                        {
                            maxOffset = phi.HeaderStart + phi.FileOffset;
                        }
                    }while (1 == 1); //minOffset > fs.Position + 0x100); //drop out if we reach the data



                    //this is a simple hack/fix to cater for padding on PAK files,
                    //it relies on the data starting at the top of the PAB file (which it always does, currently)
                    _requiresPab = maxOffset >= st.Length;

                    if (!debugFile)                                 //only when loading pak
                    {
                        _pakFormat.PakPabMinDataOffset = minOffset; //remember this value
                    }
                    //detect GH5 PAB files
                    if (_requiresPab)
                    {
                        foreach (PakHeaderItem ph in _pakHeaders.Values)
                        {
                            ph.FileOffset += (uint)(_pakFileLength - _pakFormat.PakPabMinDataOffset) - (_pakFormat.PakPabMinDataOffset == 0 ? ph.HeaderStart : 0); //gh5 doesn't hold the offset in relation to the data.
                        }
                        minOffset = _pakFileLength;
                    }
                }
            }

            _qbFilenames = new string[_pakHeaders.Count];
            int i = 0;

            foreach (PakHeaderItem hi in _pakHeaders.Values)
            {
                _qbFilenames[i++] = hi.Filename;
            }

            StructItemChildrenType s;

            if (!debugFile)
            {
                s = this.StructItemChildrenType;  //auto detect the structitemchildren type
            }
        }
예제 #13
0
        /// <summary>
        /// Load type data from binary reader
        /// </summary>
        public virtual void Create(QbItemType type)
        {
            setQbFormat(type);

            _qbItemType  = type;
            _qbItemValue = this.Root.PakFormat.GetQbItemValue(type, this.Root);
            _position    = 0; //unknown

            #region switch
            switch (_qbFormat)
            {
            case QbFormat.SectionPointer:
                //Complex section type:
                //  ItemId, FileId, Pointer, Reserved

                _itemQbKey = QbKey.Create(0);
                _fileId    = this.Root.FileId;
                _pointer   = 0;
                _reserved  = 0;

                _length = (5 * 4);

                _itemCount = 1;

                _pointers    = new uint[1];
                _pointers[0] = 0;
                break;

            case QbFormat.SectionValue:
                //Simple section type:
                //  ItemId, FileId, Value, Reserved

                _itemQbKey = QbKey.Create(0);
                _fileId    = this.Root.FileId;

                _itemCount = 1;

                _length = (4 * 4);
                break;

            case QbFormat.StructItemPointer:
                //Complex struct type:
                //  ItemId, Pointer, NextItemPointer

                _itemQbKey       = QbKey.Create(0);
                _pointer         = 0;
                _nextItemPointer = 0;

                _itemCount   = 1;
                _pointers    = new uint[1];
                _pointers[0] = _pointer;

                _length = (4 * 4);
                break;

            case QbFormat.StructItemValue:
                //Simple struct type:
                //  ItemId, Value (4 byte), NextItemPointer

                _itemQbKey = QbKey.Create(0);      //always null?
                _itemCount = 1;

                _length = (3 * 4);
                break;

            case QbFormat.ArrayPointer:
                //Complex array type:
                //  ItemCount, Pointer, Pointers -  (if length is 1 then pointer points to first item and Pointers are abscent)

                _itemCount = 0;
                _pointer   = 0;
                _itemQbKey = null;

                _length = (3 * 4);

                _pointers = new uint[_itemCount];
                break;

            case QbFormat.ArrayValue:
                //Simple array type:
                //  ItemCount, Pointer, Pointers -  (if length is 1 then pointer points to first item and Pointers are abscent)

                _itemQbKey = null;
                _itemCount = 0;
                _length    = (2 * 4);
                break;

            case QbFormat.StructHeader:     //when struct array item
                _length = (1 * 4);
                break;

            case QbFormat.Floats:
                _itemCount = 2;
                _length    = (1 * 4);
                break;

            case QbFormat.Unknown:
                _position += 4;     //there is no header so re add the previously removed 4
                _length    = (0 * 4);
                break;

            default:
                break;
            }
            #endregion

            setChildMode();
            _itemCount = (uint)this.CalcItemCount();
        }
예제 #14
0
        /// <summary>
        /// Load type data from binary reader
        /// </summary>
        public virtual void Construct(BinaryEndianReader br, QbItemType type)
        {
            setQbFormat(type);
            _qbItemType  = type;
            _qbItemValue = this.Root.PakFormat.GetQbItemValue(type, this.Root);
            _position    = this.StreamPos(br) - (1 * 4); //subtract the already read header
            uint itemQbKeyCrc = 0;

            #region switch
            switch (_qbFormat)
            {
            case QbFormat.SectionPointer:
                //Complex section type:
                //  ItemId, FileId, Pointer, Reserved
                _hasQbKey = true;

                itemQbKeyCrc = br.ReadUInt32(this.Root.PakFormat.EndianType);
                _fileId      = br.ReadUInt32(this.Root.PakFormat.EndianType);
                _pointer     = br.ReadUInt32(this.Root.PakFormat.EndianType);
                _reserved    = br.ReadUInt32(this.Root.PakFormat.EndianType);

                _length = (5 * 4);

                if (type == QbItemType.SectionScript)
                {
                    _itemCount = 0;
                }
                else
                {
                    _itemCount = 1;
                }
                _pointers    = new uint[1];
                _pointers[0] = _pointer;

                if (this.StreamPos(br) != _pointer)     //pointer test
                {
                    throw new ApplicationException(QbFile.FormatBadPointerExceptionMessage(this, this.StreamPos(br), _pointer));
                }
                break;

            case QbFormat.SectionValue:
                //Simple section type:
                //  ItemId, FileId, Value, Reserved
                _hasQbKey = true;

                itemQbKeyCrc = br.ReadUInt32(this.Root.PakFormat.EndianType);
                _fileId      = br.ReadUInt32(this.Root.PakFormat.EndianType);

                _itemCount = 1;

                _length = (3 * 4);
                break;

            case QbFormat.StructItemPointer:
                //Complex struct type:
                //  ItemId, Pointer, NextItemPointer
                _hasQbKey = true;

                itemQbKeyCrc     = br.ReadUInt32(this.Root.PakFormat.EndianType);
                _pointer         = br.ReadUInt32(this.Root.PakFormat.EndianType);
                _nextItemPointer = br.ReadUInt32(this.Root.PakFormat.EndianType);

                if (this.StreamPos(br) != _pointer)     //pointer test
                {
                    throw new ApplicationException(QbFile.FormatBadPointerExceptionMessage(this, this.StreamPos(br), _pointer));
                }

                _itemCount   = 1;
                _pointers    = new uint[1];
                _pointers[0] = _pointer;

                _length = (4 * 4);
                break;

            case QbFormat.StructItemValue:
                //Simple struct type:
                //  ItemId, Value (4 byte), NextItemPointer
                _hasQbKey = true;

                itemQbKeyCrc = br.ReadUInt32(this.Root.PakFormat.EndianType);

                //always null?
                if (_itemQbKey == 0 && _qbItemType == QbItemType.StructItemQbKeyString)
                {
                    _itemQbKey = null;
                }

                _itemCount = 1;

                _length = (2 * 4);
                break;

            case QbFormat.ArrayPointer:
                //Complex array type:
                //  ItemCount, Pointer, Pointers -  (if length is 1 then pointer points to first item and Pointers are abscent)
                _hasQbKey = false;

                _itemCount   = br.ReadUInt32(this.Root.PakFormat.EndianType);
                _pointer     = br.ReadUInt32(this.Root.PakFormat.EndianType);
                itemQbKeyCrc = 0;

                _length = (3 * 4);

                if (_pointer != 0 && this.StreamPos(br) != _pointer)     //pointer test
                {
                    throw new ApplicationException(QbFile.FormatBadPointerExceptionMessage(this, this.StreamPos(br), _pointer));
                }

                _pointers = new uint[_itemCount];

                if (_itemCount == 1)
                {
                    _pointers[0] = _pointer;
                }
                else if (_itemCount > 1)
                {
                    for (int i = 0; i < _itemCount; i++)
                    {
                        _pointers[i] = br.ReadUInt32(this.Root.PakFormat.EndianType);
                    }

                    _length += (_itemCount * 4);
                }
                break;

            case QbFormat.ArrayValue:
                //Simple array type:
                //  ItemCount, Pointer, Pointers -  (if length is 1 then pointer points to first item and Pointers are abscent)
                _hasQbKey = false;

                itemQbKeyCrc = 0;
                _itemCount   = br.ReadUInt32(this.Root.PakFormat.EndianType);
                _length      = (2 * 4);
                if (_itemCount > 1)
                {
                    _pointer = br.ReadUInt32(this.Root.PakFormat.EndianType);
                    if (this.StreamPos(br) != _pointer)     //pointer test
                    {
                        throw new ApplicationException(QbFile.FormatBadPointerExceptionMessage(this, this.StreamPos(br), _pointer));
                    }
                    _length += (1 * 4);
                }
                break;

            case QbFormat.StructHeader:     //when struct array item
                _hasQbKey = false;
                _length   = (1 * 4);
                break;

            case QbFormat.Floats:
                _hasQbKey = false;
                _length   = (1 * 4);
                break;

            case QbFormat.Unknown:
                _hasQbKey  = false;
                _position += 4;     //there is no header so re add the previously removed 4
                _length    = (0 * 4);
                break;

            default:
                break;
            }
            #endregion

            if (!_hasQbKey)
            {
                _itemQbKey = null;
            }
            else
            {
                string debugName = Root.LookupDebugName(itemQbKeyCrc);
                if (debugName.Length != 0)
                {
                    _itemQbKey = QbKey.Create(itemQbKeyCrc, debugName);
                }
                else
                {
                    _itemQbKey = QbKey.Create(itemQbKeyCrc);
                }
            }
        }