Наследование: System.IO.BinaryReader
Пример #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
        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);

            QbItemBase qib;
            QbItemType headerType;
            uint       headerValue;

            for (int i = 0; i < base.ItemCount; i++)
            {
                if (base.StreamPos(br) != base.Pointers[i]) //pointer test
                {
                    throw new ApplicationException(QbFile.FormatBadPointerExceptionMessage(this, base.StreamPos(br), base.Pointers[i]));
                }

                headerValue = br.ReadUInt32(this.Root.PakFormat.EndianType);
                headerType  = this.Root.PakFormat.GetQbItemType(headerValue);

                switch (headerType)
                {
                case QbItemType.StructHeader:
                    qib = new QbItemStruct(this.Root);
                    break;

                default:
                    throw new ApplicationException(string.Format("Location 0x{0}: Not a struct header type 0x{1}", (base.StreamPos(br) - 4).ToString("X").PadLeft(8, '0'), headerValue.ToString("X").PadLeft(8, '0')));
                }
                qib.Construct(br, headerType);
                AddItem(qib);
            }

            base.ConstructEnd(br);
        }
Пример #3
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);

            _unknown = br.ReadUInt32(base.Root.PakFormat.EndianType);
            uint decompressedSize = br.ReadUInt32(base.Root.PakFormat.EndianType);
            uint compressedSize   = br.ReadUInt32(base.Root.PakFormat.EndianType);

            // Get script data
            Lzss lz = new Lzss();

            _scriptData = br.ReadBytes((int)compressedSize);
            if (compressedSize < decompressedSize)
            {
                _scriptData = lz.Decompress(_scriptData);
            }

            if (_scriptData.Length != decompressedSize)
            {
                throw new ApplicationException(string.Format("Location 0x{0}: Script decompressed to {1} bytes not {2}", (base.StreamPos(br) - compressedSize).ToString("X").PadLeft(8, '0'), _scriptData.Length.ToString(), decompressedSize.ToString()));
            }

            // Padding...
            if ((base.StreamPos(br) % 4) != 0)
            {
                br.BaseStream.Seek(4 - (base.StreamPos(br) % 4), SeekOrigin.Current);
            }

            base.ConstructEnd(br);
        }
Пример #4
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);

            QbItemBase qib;
            QbItemType floatsType;
            uint floatsValue;
            bool is3d;
            for (int i = 0; i < base.ItemCount; i++)
            {
                if (base.StreamPos(br) != base.Pointers[i]) //pointer test
                    throw new ApplicationException(QbFile.FormatBadPointerExceptionMessage(this, base.StreamPos(br), base.Pointers[i]));

                floatsValue = br.ReadUInt32(this.Root.PakFormat.EndianType);
                floatsType = this.Root.PakFormat.GetQbItemType(floatsValue);

                is3d = (type == QbItemType.SectionFloatsX3 || type == QbItemType.StructItemFloatsX3 || type == QbItemType.ArrayFloatsX3);

                switch (floatsType)
                {
                    case QbItemType.Floats:
                        qib = new QbItemFloats(this.Root, is3d);
                        break;
                    default:
                        throw new ApplicationException(string.Format("Location 0x{0}: Not a float type 0x{1}", (base.StreamPos(br) - 4).ToString("X").PadLeft(8, '0'), floatsValue.ToString("X").PadLeft(8, '0')));
                }
                qib.Construct(br, floatsType);
                AddItem(qib);

                base.ConstructEnd(br);
            }
        }
Пример #5
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);

            QbItemBase qib = null;
            QbItemType arrayType;
            uint arrayValue;

            for (int i = 0; i < base.ItemCount; i++)
            {
                arrayValue = br.ReadUInt32(this.Root.PakFormat.EndianType);
                arrayType = this.Root.PakFormat.GetQbItemType(arrayValue);

                switch (arrayType)
                {
                    case QbItemType.Floats:
                        qib = new QbItemFloats(this.Root);
                        break;
                    case QbItemType.ArrayStruct:
                        qib = new QbItemStructArray(this.Root);
                        break;
                    case QbItemType.ArrayFloat:
                        qib = new QbItemFloat(this.Root);
                        break;
                    case QbItemType.ArrayString:
                    case QbItemType.ArrayStringW:
                        qib = new QbItemString(this.Root);
                        break;
                    case QbItemType.ArrayFloatsX2:
                    case QbItemType.ArrayFloatsX3:
                        qib = new QbItemFloatsArray(this.Root);
                        break;
                    case QbItemType.ArrayStringPointer:
                    case QbItemType.ArrayInteger:
                        qib = new QbItemInteger(this.Root);
                        break;
                    case QbItemType.ArrayArray:
                        qib = new QbItemArray(this.Root);
                        break;
                    case QbItemType.ArrayQbKey:
                    case QbItemType.ArrayQbKeyString:
                    case QbItemType.ArrayQbKeyStringQs: //GH:GH
                        qib = new QbItemQbKey(this.Root);
                        break;
                    case QbItemType.StructHeader:
                        qib = new QbItemStruct(this.Root);
                        break;
                    default:
                        throw new ApplicationException(string.Format("Location 0x{0}: Unknown array type 0x{1}", (base.StreamPos(br) - 4).ToString("X").PadLeft(8, '0'), arrayValue.ToString("X").PadLeft(8, '0')));
                }
                qib.Construct(br, arrayType);
                AddItem(qib);

            }
            base.ConstructEnd(br);
        }
Пример #6
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);

            this.Values = new uint[base.ItemCount];

            for (int i = 0; i < base.ItemCount; i++)
                _values[i] = br.ReadUInt32(base.Root.PakFormat.EndianType);

            base.ConstructEnd(br);
        }
Пример #7
0
        /// <summary>
        /// Pass null for br if the data was passed as a byte array in the constructor
        /// </summary>
        /// <param name="br"></param>
        /// <param name="type"></param>
        public override void Construct(BinaryEndianReader br, QbItemType type)
        {
            //System.Diagnostics.Debug.WriteLine(string.Format("{0} - 0x????????", this.GetType().ToString()));
            if (br != null)
            {
                base.Construct(br, type);

                //base.Position = (uint)base.StreamPos(br);
                _unknownData = br.ReadBytes(_length);

                base.ConstructEnd(br);
            }
        }
Пример #8
0
        /// <summary>
        /// Call after derived class has read its data in Construct()
        /// </summary>
        /// <param name="br"></param>
        public virtual void ConstructEnd(BinaryEndianReader br)
        {
            #region switch
            switch (_qbFormat)
            {
            case QbFormat.SectionValue:
                //Simple section type:
                //  ItemId, FileId, Value, Reserved
                _reserved = br.ReadUInt32(this.Root.PakFormat.EndianType);
                _length  += (1 * 4);
                break;

            case QbFormat.StructItemPointer:
                if (_nextItemPointer != 0 && this.StreamPos(br) != _nextItemPointer)     //pointer test
                {
                    throw new ApplicationException(QbFile.FormatBadPointerExceptionMessage(this, this.StreamPos(br), _nextItemPointer));
                }
                break;

            case QbFormat.StructItemValue:
                //Simple struct type:
                //  ItemId, Value (4 byte), NextItemPointer
                _nextItemPointer = br.ReadUInt32(this.Root.PakFormat.EndianType);
                _length         += (1 * 4);

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

            case QbFormat.ArrayPointer:
                //Complex array type:
                //  ItemCount, Pointer, Pointers -  (if length is 1 then pointer points to first item and Pointers are abscent)
                for (int i = 0; i < _items.Count; i++)     //_items.Count is 0 for strings (it checks it's own)
                {
                    if (_pointers[i] != _items[i].Position)
                    {
                        throw new ApplicationException(QbFile.FormatBadPointerExceptionMessage(this, _items[i].Position, _pointers[i]));
                    }
                }
                break;

            default:
                break;
            }
            #endregion

            setChildMode();
            //_itemCount = (uint)this.CalcItemCount();
        }
Пример #9
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);

            this.Values = new int[base.ItemCount];

            for (int i = 0; i < base.ItemCount; i++)
            {
                _values[i] = br.ReadInt32(base.Root.PakFormat.EndianType);
            }

            base.ConstructEnd(br);
        }
Пример #10
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[0] = br.ReadSingle(base.Root.PakFormat.EndianType);
            _values[1] = br.ReadSingle(base.Root.PakFormat.EndianType);
            if (_values.Length > 2)
            {
                _values[2] = br.ReadSingle(base.Root.PakFormat.EndianType);
            }

            base.ConstructEnd(br);
        }
Пример #11
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);

            QbItemBase qib;
            QbItemType floatsType;
            uint       floatsValue;
            bool       is3d;

            for (int i = 0; i < base.ItemCount; i++)
            {
                if (base.StreamPos(br) != base.Pointers[i]) //pointer test
                {
                    throw new ApplicationException(QbFile.FormatBadPointerExceptionMessage(this, base.StreamPos(br), base.Pointers[i]));
                }

                floatsValue = br.ReadUInt32(this.Root.PakFormat.EndianType);
                floatsType  = this.Root.PakFormat.GetQbItemType(floatsValue);

                is3d = (type == QbItemType.SectionFloatsX3 || type == QbItemType.StructItemFloatsX3 || type == QbItemType.ArrayFloatsX3);

                switch (floatsType)
                {
                case QbItemType.Floats:
                    qib = new QbItemFloats(this.Root, is3d);
                    break;

                default:
                    throw new ApplicationException(string.Format("Location 0x{0}: Not a float type 0x{1}", (base.StreamPos(br) - 4).ToString("X").PadLeft(8, '0'), floatsValue.ToString("X").PadLeft(8, '0')));
                }
                qib.Construct(br, floatsType);
                AddItem(qib);

                base.ConstructEnd(br);
            }
        }
Пример #12
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);
        }
Пример #13
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);

            uint pointer;

            if (type != QbItemType.StructHeader)
            {
                _headerValue = br.ReadUInt32(base.Root.PakFormat.EndianType);
            }
            else
            {
                _headerValue = base.Root.PakFormat.GetQbItemValue(type, this.Root);
            }

            _headerType = base.Root.PakFormat.GetQbItemType(_headerValue);

            QbItemBase qib = null;
            QbItemType structType;
            uint       structValue;

            if (_headerType == QbItemType.StructHeader)
            {
                pointer = br.ReadUInt32(base.Root.PakFormat.EndianType); //Should be the current stream position after reading

                _iniNextItemPointer = pointer;

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

                while (pointer != 0)
                {
                    structValue = br.ReadUInt32(this.Root.PakFormat.EndianType);
                    structType  = this.Root.PakFormat.GetQbItemType(structValue);

                    switch (structType)
                    {
                    case QbItemType.StructItemStruct:
                        this.Root.PakFormat.StructItemChildrenType = StructItemChildrenType.StructItems;
                        qib = new QbItemStruct(this.Root);
                        break;

                    case QbItemType.StructItemStringPointer:
                    case QbItemType.StructItemInteger:
                        this.Root.PakFormat.StructItemChildrenType = StructItemChildrenType.StructItems;
                        qib = new QbItemInteger(this.Root);
                        break;

                    case QbItemType.StructItemQbKeyString:
                    case QbItemType.StructItemQbKeyStringQs:
                    case QbItemType.StructItemQbKey:
                        this.Root.PakFormat.StructItemChildrenType = StructItemChildrenType.StructItems;
                        qib = new QbItemQbKey(this.Root);
                        break;

                    case QbItemType.StructItemString:
                    case QbItemType.StructItemStringW:
                        this.Root.PakFormat.StructItemChildrenType = StructItemChildrenType.StructItems;
                        qib = new QbItemString(this.Root);
                        break;

                    case QbItemType.StructItemFloat:
                        this.Root.PakFormat.StructItemChildrenType = StructItemChildrenType.StructItems;
                        qib = new QbItemFloat(this.Root);
                        break;

                    case QbItemType.StructItemFloatsX2:
                    case QbItemType.StructItemFloatsX3:
                        this.Root.PakFormat.StructItemChildrenType = StructItemChildrenType.StructItems;
                        qib = new QbItemFloatsArray(this.Root);
                        break;

                    case QbItemType.StructItemArray:
                        this.Root.PakFormat.StructItemChildrenType = StructItemChildrenType.StructItems;
                        qib = new QbItemArray(this.Root);
                        break;

                    //Convert array types to structitems to fit in with this parser (if QbFile.HasStructItems is false then internal type will be swapped back to array)
                    case QbItemType.ArrayStruct:
                        structType = QbItemType.StructItemStruct;
                        qib        = new QbItemArray(this.Root);
                        break;

                    case QbItemType.ArrayInteger:
                        structType = QbItemType.StructItemInteger;
                        qib        = new QbItemInteger(this.Root);
                        break;

                    case QbItemType.ArrayQbKeyString:
                        structType = QbItemType.StructItemQbKeyString;
                        qib        = new QbItemQbKey(this.Root);
                        break;

                    case QbItemType.ArrayStringPointer:
                        structType = QbItemType.StructItemStringPointer;
                        qib        = new QbItemInteger(this.Root);
                        break;

                    case QbItemType.ArrayQbKeyStringQs:
                        structType = QbItemType.StructItemQbKeyStringQs;
                        qib        = new QbItemQbKey(this.Root);
                        break;

                    case QbItemType.ArrayQbKey:
                        structType = QbItemType.StructItemQbKey;
                        qib        = new QbItemQbKey(this.Root);
                        break;

                    case QbItemType.ArrayString:
                        structType = QbItemType.StructItemString;
                        qib        = new QbItemString(this.Root);
                        break;

                    case QbItemType.ArrayStringW:
                        structType = QbItemType.StructItemStringW;
                        qib        = new QbItemString(this.Root);
                        break;

                    case QbItemType.ArrayFloat:
                        structType = QbItemType.StructItemFloat;
                        qib        = new QbItemFloat(this.Root);
                        break;

                    case QbItemType.ArrayFloatsX2:
                        structType = QbItemType.StructItemFloatsX2;
                        qib        = new QbItemFloatsArray(this.Root);
                        break;

                    case QbItemType.ArrayFloatsX3:
                        structType = QbItemType.StructItemFloatsX3;
                        qib        = new QbItemFloatsArray(this.Root);
                        break;

                    case QbItemType.ArrayArray:
                        structType = QbItemType.StructItemArray;
                        qib        = new QbItemArray(this.Root);
                        break;

                    default:
                        qib = null;
                        break;
                    }

                    if (qib != null)
                    {
                        if (this.Root.PakFormat.StructItemChildrenType == StructItemChildrenType.NotSet) //will have been set to structItem if qib is not null)
                        {
                            this.Root.PakFormat.StructItemChildrenType = StructItemChildrenType.ArrayItems;
                        }

                        qib.Construct(br, structType);
                        AddItem(qib);
                        pointer = qib.NextItemPointer;
                    }
                    else
                    {
                        throw new ApplicationException(string.Format("Location 0x{0}: Unknown item type 0x{1} in struct ", (base.StreamPos(br) - 4).ToString("X").PadLeft(8, '0'), structValue.ToString("X").PadLeft(8, '0')));
                    }
                }
            }
            else
            {
                throw new ApplicationException(string.Format("Location 0x{0}: Struct without header type", (base.StreamPos(br) - 4).ToString("X").PadLeft(8, '0')));
            }

            base.ConstructEnd(br);
        }
Пример #14
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)
                {
                    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
        }
Пример #15
0
        private void parse()
        {
            _datItems.Clear();

            using (FileStream fs = File.OpenRead(_datFilename))
            {
                using (BinaryEndianReader br = new BinaryEndianReader(fs))
                {
                    uint files = br.ReadUInt32(_endianType);
                    _headerFileSize = br.ReadUInt32(_endianType);
                    QbKey songQk;

                    for (int i = 0; i < files; i++)
                    {
                        songQk = QbKey.Create(br.ReadUInt32(_endianType));
                        _datItems.Add(songQk.Crc, new DatItem(songQk, br.ReadUInt32(_endianType), br.ReadUInt32(_endianType), br.ReadBytes(8)));
                    }
                }
            }
        }
Пример #16
0
        public static void CreatePreview(int offset, int length, int fade, float volume, bool volumeApplied, string dstFilename, params AudioFile[] srcFilenames)
        {
            if (srcFilenames == null || srcFilenames.Length == 0 || (srcFilenames.Length == 1 && (srcFilenames[0] == null || srcFilenames[0].Name.Length == 0)))
                return;

            FileHelper.Delete(dstFilename);

            WavSingleChunkHeader[] whi = new WavSingleChunkHeader[srcFilenames.Length];
            BinaryEndianReader[] br = new BinaryEndianReader[srcFilenames.Length];
            float[] vols = new float[srcFilenames.Length];

            int outWav = 0; //use this input wav as the format for the output wav
            int maxLen = 0;

            for (int c = 0; c < srcFilenames.Length; c++)
            {
                br[c] = new BinaryEndianReader(File.OpenRead(srcFilenames[c].Name));
                whi[c] = ParseWavSingleChunkHeader(br[c].BaseStream);
                if (!volumeApplied)
                    vols[c] = srcFilenames[c].Volume / 100F; //get percentage
                else
                    vols[c] = 1; //100%

                //move to the correct point in each wav
                uint wOffset = (uint)(whi[c].AvgBytesPerSec * ((float)offset / 1000));
                wOffset -= wOffset % whi[c].BlockAlign;
                br[c].BaseStream.Seek((long)wOffset, SeekOrigin.Current);

                if (whi[c].AudioLength > maxLen)
                    maxLen = whi[c].AudioLength;

                if (whi[c].Channels == 2)
                    outWav = c;
            }

            WavSingleChunkHeader who = new WavSingleChunkHeader();

            if (length == 0)
                length = maxLen;

            uint wLength = (uint)(whi[outWav].AvgBytesPerSec * ((float)length / 1000));
            wLength -= wLength % whi[outWav].BlockAlign;

            who.FileId = "RIFF";
            who.FileLength = (uint)(br[outWav].BaseStream.Length - whi[outWav].FileLength) + wLength;
            who.RiffType = "WAVE";

            who.ChunkHeaderId = "fmt ";
            who.ChunkHeaderLength = whi[outWav].ChunkHeaderLength;
            who.FormatTag = whi[outWav].FormatTag;
            who.Channels = whi[outWav].Channels;
            who.SamplesPerSec = whi[outWav].SamplesPerSec;
            who.AvgBytesPerSec = whi[outWav].AvgBytesPerSec;
            who.BlockAlign = whi[outWav].BlockAlign;
            who.BitsPerSample = whi[outWav].BitsPerSample;
            who.ExtraBytes = whi[outWav].ExtraBytes;

            who.ChunkId = "data";
            who.ChunkLength = wLength;

            using (FileStream fso = File.OpenWrite(dstFilename))
            {
                WriteSingleChunkHeader(who, fso);

                int loops = (int)((who.AvgBytesPerSec / who.BlockAlign) * ((float)length / 1000));
                int fadeLen = (int)((who.AvgBytesPerSec / who.BlockAlign) * ((float)fade / 1000));

                Double maxVol = (volume / (float)srcFilenames.Length);  //reduce volume Audio in game
                maxVol *= 1F + ((srcFilenames.Length - 1) * 0.33F);  //add an extra third per file to cater for volume loss

                Double vol = 0; //initial volume
                if (fade == 0)
                    vol = maxVol;

                int b32;

                BinaryEndianWriter bw = new BinaryEndianWriter(fso);

                Double step = (double)(maxVol - 0) / fadeLen; //fade in
                if (Double.IsInfinity(step))
                    step = 0;
                int allLeft = 0;
                int allRight = 0;

                long[] streamPos = new long[br.Length]; //fast way to track pos in stream
                for (int c = 0; c < br.Length; c++)
                    streamPos[c] = br[c].BaseStream.Position;
                long[] streamLen = new long[br.Length]; //fast way to get length of stream
                for (int c = 0; c < br.Length; c++)
                    streamLen[c] = br[c].BaseStream.Length;

                for (int i = 0; i != loops; i++)
                {
                    if (i == fadeLen)
                        step = 0; //use max volume
                    if (i == loops - fadeLen) //fade out
                        step = (double)(0 - maxVol) / fadeLen;

                    allLeft = 0;
                    allRight = 0;

                    for (int c = 0; c < br.Length; c++) //each input stream
                    {
                        BinaryEndianReader b = br[c];
                        WavSingleChunkHeader w = whi[c];

                        //Left channel
                        b32 = 0;
                        if (streamPos[c] + 2 < streamLen[c])
                        {
                            b32 = (int)(b.ReadInt16(EndianType.Little) * vols[c]);
                            streamPos[c] += 2;
                        }
                        allLeft += (int)(b32 * vol);
                        allLeft = (short)Math.Max((int)short.MinValue, Math.Min((int)short.MaxValue, allLeft));

                        if (who.Channels > 1)
                        {
                            if (w.Channels > 1)
                            {
                                //Right channel
                                b32 = 0;
                                if (streamPos[c] + 2 < streamLen[c])
                                {
                                    b32 = (int)(b.ReadInt16(EndianType.Little) * vols[c]);
                                    streamPos[c] += 2;
                                }
                            }
                            allRight += (int)(b32 * vol);
                            allRight = (short)Math.Max((int)short.MinValue, Math.Min((int)short.MaxValue, allRight));
                        }
                    }

                    bw.Write((short)allLeft);
                    if (who.Channels > 1)
                        bw.Write((short)allRight);

                    vol += step;
                }

                foreach (BinaryEndianReader b in br)
                    b.Close();

                fso.Flush();
            }
        }
Пример #17
0
        private void parse(Stream stream)
        {
            _streamStartPosition = stream.Position;

            _items = new List<QbItemBase>();

            //if (stream.Position != 0)
            //    throw new ApplicationException("The stream must start at position 0 as this parser uses the position to validate pointers.");

            using (BinaryEndianReader br = new BinaryEndianReader(stream))
            {
                _magic = br.ReadUInt32(this.PakFormat.EndianType);
                _fileSize = br.ReadUInt32(this.PakFormat.EndianType);

                uint sectionValue;

                QbItemBase qib = new QbItemUnknown(20, this);
                qib.Construct(br, QbItemType.Unknown);
                AddItem(qib);

                while (this.StreamPos(br.BaseStream) < _fileSize)
                {
                    sectionValue = br.ReadUInt32(this.PakFormat.EndianType);
                    QbItemType sectionType = this.PakFormat.GetQbItemType(sectionValue);

                    switch (sectionType)
                    {
                        case QbItemType.SectionString:
                        case QbItemType.SectionStringW:
                            qib = new QbItemString(this);
                            break;
                        case QbItemType.SectionArray:
                            qib = new QbItemArray(this);
                            break;
                        case QbItemType.SectionStruct:
                            qib = new QbItemStruct(this);
                            break;
                        case QbItemType.SectionScript:
                            qib = new QbItemScript(this);
                            break;
                        case QbItemType.SectionFloat:
                            qib = new QbItemFloat(this);
                            break;
                        case QbItemType.SectionFloatsX2:
                        case QbItemType.SectionFloatsX3:
                            qib = new QbItemFloatsArray(this);
                            break;
                        case QbItemType.SectionInteger:
                        case QbItemType.SectionStringPointer:
                            qib = new QbItemInteger(this);
                            break;
                        case QbItemType.SectionQbKey:
                        case QbItemType.SectionQbKeyString:
                        case QbItemType.SectionQbKeyStringQs: //GH:GH
                            qib = new QbItemQbKey(this);
                            break;
                        default:
                            throw new ApplicationException(string.Format("Location 0x{0}: Unknown section type 0x{1}", (this.StreamPos(br.BaseStream) - 4).ToString("X").PadLeft(8, '0'), sectionValue.ToString("X").PadLeft(8, '0')));
                    }
                    qib.Construct(br, sectionType);

                    AddItem(qib);
                }
            }

            uint f = this.FileId; //gettin this sets the file id
        }
Пример #18
0
        public static void BuildPartition(string partitionBinFilename,
                                          string mainDolFilename,
                                          string appLoaderImgFilename,
                                          string bi2BinFilename,
                                          string bootBinFilename,
                                          string sourceDirectory,
                                          string partitionFilename,
                                          bool deleteWhileBuilding)
        {
            ulong totalSize = 0;

            BinaryEndianReader brFst = null;
            BinaryEndianWriter bwFst = new BinaryEndianWriter(new MemoryStream());
            BinaryEndianWriter bwStr = new BinaryEndianWriter(new MemoryStream());
            BinaryEndianWriter bwBootBin = null;
            BinaryEndianWriter bwPartitionBin = null;
            BinaryEndianWriter bwB12Bin = null;

            try
            {

                DirectoryInfo inputFolder = new DirectoryInfo(sourceDirectory);

                //DateTime n = DateTime.Now;
                uint fileCount = recurseFiles(true, inputFolder, bwFst, bwStr, ref totalSize, 0, null, 0, deleteWhileBuilding);
                //System.Diagnostics.Debug.WriteLine((DateTime.Now - n).Ticks);

                // get the file sizes we need - apploader and main.dol
                FileInfo appLoaderImg = new FileInfo(appLoaderImgFilename);
                FileInfo mainDol = new FileInfo(mainDolFilename);

                // now calculate the relative offsets
                uint pad1Size = 0x100 - (((uint)appLoaderImg.Length + 0x2440) % 0x100);
                uint pad2Size = 0x100 - ((uint)mainDol.Length % 0x100);

                // just a pad out for no real reason :)
                uint pad3Size = 0x2000;

                uint mainDolOffset = 0x2440 + (uint)appLoaderImg.Length + pad1Size;
                uint fstOffset = mainDolOffset + pad2Size + (uint)mainDol.Length;

                // modify the data size in partition.bin
                // read in partition.bin
                bwPartitionBin = new BinaryEndianWriter(new MemoryStream(File.ReadAllBytes(partitionBinFilename)));

                // now Actual size = scaled up by sizes
                totalSize += pad1Size + 0x2440 + pad2Size + pad3Size + (uint)mainDol.Length + (uint)appLoaderImg.Length;

                ulong dataSize = (totalSize / 0x7c00) * 0x8000;
                if (dataSize % 0x7c00 != 0)
                    dataSize += 0x8000;

                bwPartitionBin.Seek(0x2BC, SeekOrigin.Begin);
                bwPartitionBin.Write((uint)dataSize >> 2, EndianType.Big);

                // generate a boot.bin
                bwBootBin = new BinaryEndianWriter(new MemoryStream(File.ReadAllBytes(bootBinFilename)));
                // now the size offsets
                bwBootBin.Seek(0x420, SeekOrigin.Begin);
                bwBootBin.Write(mainDolOffset >> 2, EndianType.Big);
                bwBootBin.Write(fstOffset >> 2, EndianType.Big);
                bwBootBin.Write((uint)(bwFst.BaseStream.Length + bwStr.BaseStream.Length) >> 2, EndianType.Big);
                bwBootBin.Write((uint)(bwFst.BaseStream.Length + bwStr.BaseStream.Length) >> 2, EndianType.Big);

                // calculate what we need to modify the FST entries by
                ulong dataOffset = 0x2440 + pad1Size + (uint)appLoaderImg.Length + (uint)mainDol.Length + pad2Size + (uint)bwFst.BaseStream.Length + (uint)bwStr.BaseStream.Length + pad3Size;
                dataOffset = (dataOffset >> 2);

                // modify the fst.bin to include all the correct offsets
                brFst = new BinaryEndianReader(bwFst.BaseStream);
                brFst.BaseStream.Seek(8, SeekOrigin.Begin);
                uint fstEntries = brFst.ReadUInt32(EndianType.Big);

                for (int i = 1; i < fstEntries; i++) //1 as we've already skipped the root
                {
                    if (brFst.ReadByte() == 0) //file
                    {
                        brFst.BaseStream.Seek(3, SeekOrigin.Current); //skip the rest of the uint
                        uint temp = brFst.ReadUInt32(EndianType.Big);
                        bwFst.BaseStream.Seek(-4, SeekOrigin.Current); //THE STREAMS ARE THE SAME (be careful of bugs when the position moves)
                        bwFst.Write((uint)dataOffset + temp, EndianType.Big);
                        brFst.BaseStream.Seek(4, SeekOrigin.Current); //skip the rest of the file
                    }
                    else
                        brFst.BaseStream.Seek(0xc - 1, SeekOrigin.Current); //skip the rest of the directory
                }

                using (FileStream fs = new FileStream(partitionFilename, FileMode.Create))
                {
                    copyStream(bwPartitionBin.BaseStream, fs, 4);

                    copyStream(bwBootBin.BaseStream, fs, 4);

                    copyStream(bi2BinFilename, fs, 4);

                    copyStream(appLoaderImgFilename, fs, 4);

                    fs.Write(new byte[pad1Size], 0, (int)pad1Size);

                    copyStream(mainDolFilename, fs, 4);

                    fs.Write(new byte[pad2Size], 0, (int)pad2Size);

                    copyStream(bwFst.BaseStream, fs, 4);

                    copyStream(bwStr.BaseStream, fs, 4);

                    fs.Write(new byte[pad3Size], 0, (int)pad3Size);

                    //copy all the files to the end of the partition
                    totalSize = dataOffset; //will give the offsets the correct value (not that it matters here heh)
                    bwFst.BaseStream.Seek(0, SeekOrigin.Begin);
                    bwStr.BaseStream.Seek(0, SeekOrigin.Begin);
                    recurseFiles(true, inputFolder, bwFst, bwStr, ref totalSize, 0, fs, (ulong)fs.Position - dataOffset, deleteWhileBuilding);

                    if (deleteWhileBuilding)
                    {
                        try
                        {
                            inputFolder.Delete(true);
                        }
                        catch
                        {
                        }
                    }
                }

            }
            finally
            {
                if (brFst != null)
                    brFst.Close();
                bwFst.Close();
                bwStr.Close();
                if (bwBootBin != null)
                    bwBootBin.Close();
                if (bwPartitionBin != null)
                    bwPartitionBin.Close();
                if (bwB12Bin != null)
                    bwB12Bin.Close();
            }
        }
Пример #19
0
        /// <summary>
        /// Adds silence to wav files alter volume
        /// </summary>
        /// <param name="silenceInsertLength">Milliseconds to insert at start of wav</param>
        /// <param name="volume">0=silent, 1=100%</param>
        /// <param name="maxLength">If the wav is longer than this then crop (includes silence), if 0 then don't crop</param>
        /// <param name="srcFilenames">Filenames to pad</param>
        public static void SetLengthSilenceAndVolume(float silenceInsertLength, float maxLength, float volume, string fileName)
        {
            FileStream inS;
            FileStream outS;
            WavSingleChunkHeader h;
            uint silenceLen;
            string tmpName;

            //uint origChunkLen;

            int copied;
            byte[] buff = new byte[10000];

            for (int i = 0; i < buff.Length; i++)
                buff[i] = 0;

            tmpName = string.Format("{0}_{1}", fileName, Guid.NewGuid().ToString("N"));

            using (inS = new FileStream(fileName, FileMode.Open, FileAccess.Read))
            {
                using (outS = new FileStream(tmpName, FileMode.CreateNew, FileAccess.ReadWrite))
                {
                    h = ParseWavSingleChunkHeader(inS);

                    //origChunkLen = h.ChunkLength;

                    silenceLen = (uint)((float)h.AvgBytesPerSec * (silenceInsertLength / 1000F));
                    silenceLen -= silenceLen % h.BlockAlign;

                    uint newLenBytes = maxLength != 0 ? (uint)((float)h.AvgBytesPerSec * (maxLength / 1000F)) : h.ChunkLength + silenceLen;
                    newLenBytes -= newLenBytes % h.BlockAlign;

                    h.ChunkLength = (uint)((uint)inS.Length - h.DataOffset) + silenceLen;

                    if (h.ChunkLength > newLenBytes)
                        h.ChunkLength = newLenBytes;

                    h.ChunkLength -= h.ChunkLength % h.BlockAlign;
                    h.FileLength = (h.ChunkLength + (uint)h.DataOffset) - 8;

                    WriteSingleChunkHeader(h, outS);

                    copied = 0;
                    int len = 0;
                    while (copied < silenceLen)
                    {
                        len = buff.Length;
                        if (copied + buff.Length > silenceLen)
                            len = (int)silenceLen - copied;

                        outS.Write(buff, 0, len);
                        copied += len;
                    }

                    //origChunkLen = h.ChunkLength; //we need to copy this much

                    //copy audio and set volume
                    BinaryEndianWriter bw = new BinaryEndianWriter(outS);
                    BinaryEndianReader br = new BinaryEndianReader(inS);
                    int b32;
                    while (copied != h.ChunkLength) //length is block aligned so don't worry about channel count
                    {
                        b32 = (int)br.ReadInt16(EndianType.Little);
                        b32 = (int)((float)b32 * volume);

                        b32 = Math.Max((int)short.MinValue, Math.Min((int)short.MaxValue, b32));

                        bw.Write((short)b32, EndianType.Little);
                        copied += 2;
                    }

                    //copied = (int)origChunkLen;  //we've copied this much (silence included)
                    //while (copied < h.ChunkLength) //pad to the length we said it was in the header
                    //{
                    //    inS.Read(buff, 0, buff.Length);
                    //    if (copied + buff.Length < h.ChunkLength)
                    //        outS.Write(buff, 0, buff.Length);
                    //    else
                    //        outS.Write(buff, 0, (int)h.ChunkLength % - copied);
                    //    copied += buff.Length;
                    //}

                    outS.Flush();
                }
            }
            if (File.Exists(fileName))
            {
                if (File.Exists(tmpName))
                    FileHelper.Move(tmpName, fileName);
            }
        }
Пример #20
0
 protected uint StreamPos(BinaryEndianReader br)
 {
     return(Root.StreamPos(br.BaseStream));
 }
Пример #21
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));
        }
Пример #22
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')));

            _isUnicode = ((type == QbItemType.SectionStringW || type == QbItemType.ArrayStringW || type == QbItemType.StructItemStringW) &&
                (base.Root.PakFormat.PakFormatType == PakFormatType.PC || base.Root.PakFormat.PakFormatType == PakFormatType.XBox));

            byte[] bytes;

            base.Construct(br, type);

            this.Strings = new string[base.ItemCount];

            _charWidth = !_isUnicode ? 1 : 2;

            if (base.ItemCount != 0)
            {
                //use pointers to read quickly
                if (base.ItemCount > 1)
                {

                    for (int i = 0; i < base.ItemCount - 1; i++)
                    {
                        if (base.StreamPos(br) != base.Pointers[i]) //pointer test
                            throw new ApplicationException(QbFile.FormatBadPointerExceptionMessage(this, base.StreamPos(br), base.Pointers[i]));

                        bytes = br.ReadBytes((int)((base.Pointers[i + 1] - _charWidth) - base.StreamPos(br)));

                        _strings[i] = bytesToString(bytes); //handles unicode

                        if (!_isUnicode ? (br.ReadByte() != 0) : (br.ReadByte() != 0 || br.ReadByte() != 0))
                            throw new ApplicationException(string.Format("Null byte expected reading string array at 0x{0}", (base.StreamPos(br) - _charWidth).ToString("X").PadLeft(8, '0')));
                    }

                    if (base.StreamPos(br) != base.Pointers[base.ItemCount - 1]) //pointer test
                        throw new ApplicationException(QbFile.FormatBadPointerExceptionMessage(this, base.StreamPos(br), base.Pointers[base.ItemCount - 1]));
                }

                //use the slow method read the last string
                StringBuilder sb = new StringBuilder();
                //if we have come from an array we must align our position to %4
                int byteAmount = (int)(4 - (base.StreamPos(br) % 4));

                do
                {
                    bytes = br.ReadBytes(byteAmount);
                    sb.Append(bytesToString(bytes));
                    byteAmount = 4;
                }
                while (!_isUnicode ? (bytes[bytes.Length - 1] != '\0') : (bytes[bytes.Length - 1] != '\0' || bytes[bytes.Length - 2] != '\0'));

                //get text and remove any trailing null bytes
                _strings[base.ItemCount - 1] = sb.ToString().TrimEnd(new char[] { '\0' });
            }
            base.ConstructEnd(br);
        }
Пример #23
0
        private CompressionType xBoxUncompress(string compFilename, string uncompFilename)
        {
            if (uncompFilename.ToLower() == compFilename.ToLower()) //nothing to do
            {
                return(CompressionType.None);
            }

            if (File.Exists(uncompFilename))
            {
                File.Delete(uncompFilename);
            }

            CompressionType ct = CompressionType.None;

            try
            {
                using (FileStream inFileStream = new FileStream(compFilename, FileMode.Open, FileAccess.Read))
                {
                    using (BinaryEndianReader br = new BinaryEndianReader(inFileStream))
                    {
                        uint chunkLen = 0;

                        while (chunkLen != 0xffffffff)
                        {
                            using (FileStream outFileStream = new FileStream(uncompFilename, chunkLen == 0 ? FileMode.Create : FileMode.Append))
                            {
                                using (ZlibOutputStream outZStream = new ZlibOutputStream(outFileStream, Rebex.IO.Compression.CompressionMode.Decompress))
                                {
                                    //test for newer GHWT+ compression
                                    long pos = inFileStream.Position;

                                    if (Encoding.ASCII.GetString(br.ReadBytes(4)) == "CHNK")
                                    {
                                        ct = CompressionType.ZLibChunk;

                                        EndianType et = this.EndianType;

                                        //Decompress each section
                                        uint headerLen = br.ReadUInt32(et);
                                        uint blockLen  = br.ReadUInt32(et);
                                        chunkLen = br.ReadUInt32(et);
                                        uint nextchunkLen    = br.ReadUInt32(et);
                                        uint uncompressedLen = br.ReadUInt32(et);
                                        uint uncompressedPos = br.ReadUInt32(et);

                                        _zLibHeaderLen = headerLen;
                                        if (uncompressedLen > this._zLibChunkSize)
                                        {
                                            this._zLibChunkSize = uncompressedLen;
                                        }

                                        inFileStream.Seek(headerLen - (inFileStream.Position - pos), SeekOrigin.Current);
                                        outZStream.WriteByte(0x58);  //Search deflate.cs for "Nanook" for the mod to stop it being written out
                                        outZStream.WriteByte(0x85);  //this is the header MS uses, thie zlib deflate uses 78DA ??

                                        copyStream(inFileStream, outZStream, (int)blockLen);

                                        if (chunkLen != 0xffffffff)
                                        {
                                            inFileStream.Seek((chunkLen - blockLen) - headerLen, SeekOrigin.Current);
                                        }
                                    }
                                    else
                                    {
                                        try
                                        {
                                            inFileStream.Seek(pos, SeekOrigin.Begin);

                                            outZStream.WriteByte(0x58);
                                            outZStream.WriteByte(0x85);
                                            copyStream(inFileStream, outZStream);
                                            ct = CompressionType.ZLib;
                                            break;
                                        }
                                        catch
                                        {
                                            break;  //no compression???
                                        }
                                    }

                                    outZStream.Flush();
                                    outFileStream.Flush();
                                    //outZStream.Close();
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                throw new ApplicationException(string.Format("Uncompress Failed: {0}", ex));
            }

            //using (DeflateStream ds = new DeflateStream(File.Open(compFilename, FileMode.Open), CompressionMode.Decompress))
            //{
            //    using (BinaryReader br = new BinaryReader(ds))
            //    {
            //        using (FileStream ms = File.Create(uncompFilename))
            //        {
            //            using (BinaryWriter bw = new BinaryWriter(ms))
            //            {
            //                long l;
            //                do
            //                {
            //                    l = ms.Length;
            //                    bw.Write(br.ReadBytes(10000));
            //                }
            //                while (l != ms.Length);
            //            }
            //        }
            //    }
            //}

            return(ct);
        }
Пример #24
0
        private CompressionType xBoxUncompress(string compFilename, string uncompFilename)
        {
            if (uncompFilename.ToLower() == compFilename.ToLower()) //nothing to do
                return CompressionType.None;

            if (File.Exists(uncompFilename))
                File.Delete(uncompFilename);

            CompressionType ct = CompressionType.None;

            try
            {
                using (FileStream inFileStream = new FileStream(compFilename, FileMode.Open, FileAccess.Read))
                {
                    using (BinaryEndianReader br = new BinaryEndianReader(inFileStream))
                    {
                        uint chunkLen = 0;

                        while (chunkLen != 0xffffffff)
                        {
                            using (FileStream outFileStream = new FileStream(uncompFilename, chunkLen == 0 ? FileMode.Create : FileMode.Append))
                            {
                                using (ZlibOutputStream outZStream = new ZlibOutputStream(outFileStream, Rebex.IO.Compression.CompressionMode.Decompress))
                                {
                                    //test for newer GHWT+ compression
                                    long pos = inFileStream.Position;

                                    if (Encoding.ASCII.GetString(br.ReadBytes(4)) == "CHNK")
                                    {
                                        ct = CompressionType.ZLibChunk;

                                        EndianType et = this.EndianType;

                                        //Decompress each section
                                        uint headerLen = br.ReadUInt32(et);
                                        uint blockLen = br.ReadUInt32(et);
                                        chunkLen = br.ReadUInt32(et);
                                        uint nextchunkLen = br.ReadUInt32(et);
                                        uint uncompressedLen = br.ReadUInt32(et);
                                        uint uncompressedPos = br.ReadUInt32(et);

                                        _zLibHeaderLen = headerLen;
                                        if (uncompressedLen > this._zLibChunkSize)
                                            this._zLibChunkSize = uncompressedLen;

                                        inFileStream.Seek(headerLen - (inFileStream.Position - pos), SeekOrigin.Current);
                                        outZStream.WriteByte(0x58);  //Search deflate.cs for "Nanook" for the mod to stop it being written out
                                        outZStream.WriteByte(0x85);  //this is the header MS uses, thie zlib deflate uses 78DA ??

                                        copyStream(inFileStream, outZStream, (int)blockLen);

                                        if (chunkLen != 0xffffffff)
                                            inFileStream.Seek((chunkLen - blockLen) - headerLen, SeekOrigin.Current);

                                    }
                                    else
                                    {
                                        try
                                        {
                                            inFileStream.Seek(pos, SeekOrigin.Begin);

                                            outZStream.WriteByte(0x58);
                                            outZStream.WriteByte(0x85);
                                            copyStream(inFileStream, outZStream);
                                            ct = CompressionType.ZLib;
                                            break;
                                        }
                                        catch
                                        {
                                            break;  //no compression???
                                        }
                                    }

                                    outZStream.Flush();
                                    outFileStream.Flush();
                                    //outZStream.Close();
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                throw new ApplicationException(string.Format("Uncompress Failed: {0}", ex));
            }

            //using (DeflateStream ds = new DeflateStream(File.Open(compFilename, FileMode.Open), CompressionMode.Decompress))
            //{
            //    using (BinaryReader br = new BinaryReader(ds))
            //    {
            //        using (FileStream ms = File.Create(uncompFilename))
            //        {
            //            using (BinaryWriter bw = new BinaryWriter(ms))
            //            {
            //                long l;
            //                do
            //                {
            //                    l = ms.Length;
            //                    bw.Write(br.ReadBytes(10000));
            //                }
            //                while (l != ms.Length);
            //            }
            //        }
            //    }
            //}

            return ct;
        }
Пример #25
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
            }
        }
Пример #26
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));
            }
        }
Пример #27
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);
                }
            }
        }
Пример #28
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')));

            _isUnicode = ((type == QbItemType.SectionStringW || type == QbItemType.ArrayStringW || type == QbItemType.StructItemStringW) &&
                          (base.Root.PakFormat.PakFormatType == PakFormatType.PC || base.Root.PakFormat.PakFormatType == PakFormatType.XBox));

            byte[] bytes;

            base.Construct(br, type);

            this.Strings = new string[base.ItemCount];

            _charWidth = !_isUnicode ? 1 : 2;

            if (base.ItemCount != 0)
            {
                //use pointers to read quickly
                if (base.ItemCount > 1)
                {
                    for (int i = 0; i < base.ItemCount - 1; i++)
                    {
                        if (base.StreamPos(br) != base.Pointers[i]) //pointer test
                        {
                            throw new ApplicationException(QbFile.FormatBadPointerExceptionMessage(this, base.StreamPos(br), base.Pointers[i]));
                        }

                        bytes = br.ReadBytes((int)((base.Pointers[i + 1] - _charWidth) - base.StreamPos(br)));

                        _strings[i] = bytesToString(bytes); //handles unicode

                        if (!_isUnicode ? (br.ReadByte() != 0) : (br.ReadByte() != 0 || br.ReadByte() != 0))
                        {
                            throw new ApplicationException(string.Format("Null byte expected reading string array at 0x{0}", (base.StreamPos(br) - _charWidth).ToString("X").PadLeft(8, '0')));
                        }
                    }

                    if (base.StreamPos(br) != base.Pointers[base.ItemCount - 1]) //pointer test
                    {
                        throw new ApplicationException(QbFile.FormatBadPointerExceptionMessage(this, base.StreamPos(br), base.Pointers[base.ItemCount - 1]));
                    }
                }


                //use the slow method read the last string
                StringBuilder sb = new StringBuilder();
                //if we have come from an array we must align our position to %4
                int byteAmount = (int)(4 - (base.StreamPos(br) % 4));

                do
                {
                    bytes = br.ReadBytes(byteAmount);
                    sb.Append(bytesToString(bytes));
                    byteAmount = 4;
                }while (!_isUnicode ? (bytes[bytes.Length - 1] != '\0') : (bytes[bytes.Length - 1] != '\0' || bytes[bytes.Length - 2] != '\0'));


                //get text and remove any trailing null bytes
                _strings[base.ItemCount - 1] = sb.ToString().TrimEnd(new char[] { '\0' });
            }
            base.ConstructEnd(br);
        }
Пример #29
0
        /// <summary>
        /// Call after derived class has read its data in Construct()
        /// </summary>
        /// <param name="br"></param>
        public virtual void ConstructEnd(BinaryEndianReader br)
        {
            #region switch
            switch (_qbFormat)
            {
                case QbFormat.SectionValue:
                    //Simple section type:
                    //  ItemId, FileId, Value, Reserved
                    _reserved = br.ReadUInt32(this.Root.PakFormat.EndianType);
                    _length += (1 * 4);
                    break;

                case QbFormat.StructItemPointer:
                    if (_nextItemPointer != 0 && this.StreamPos(br) != _nextItemPointer) //pointer test
                        throw new ApplicationException(QbFile.FormatBadPointerExceptionMessage(this, this.StreamPos(br), _nextItemPointer));
                    break;

                case QbFormat.StructItemValue:
                    //Simple struct type:
                    //  ItemId, Value (4 byte), NextItemPointer
                    _nextItemPointer = br.ReadUInt32(this.Root.PakFormat.EndianType);
                    _length += (1 * 4);

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

                case QbFormat.ArrayPointer:
                    //Complex array type:
                    //  ItemCount, Pointer, Pointers -  (if length is 1 then pointer points to first item and Pointers are abscent)
                    for (int i = 0; i < _items.Count; i++) //_items.Count is 0 for strings (it checks it's own)
                    {
                        if (_pointers[i] != _items[i].Position)
                            throw new ApplicationException(QbFile.FormatBadPointerExceptionMessage(this, _items[i].Position, _pointers[i]));
                    }
                    break;

                default:
                    break;
            }
            #endregion

            setChildMode();
            //_itemCount = (uint)this.CalcItemCount();
        }
Пример #30
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);

            _unknown = br.ReadUInt32(base.Root.PakFormat.EndianType);
            uint decompressedSize = br.ReadUInt32(base.Root.PakFormat.EndianType);
            uint compressedSize = br.ReadUInt32(base.Root.PakFormat.EndianType);

            // Get script data
            Lzss lz = new Lzss();
            _scriptData = br.ReadBytes((int)compressedSize);
            if (compressedSize < decompressedSize)
                _scriptData = lz.Decompress(_scriptData);

            if (_scriptData.Length != decompressedSize)
                throw new ApplicationException(string.Format("Location 0x{0}: Script decompressed to {1} bytes not {2}", (base.StreamPos(br) - compressedSize).ToString("X").PadLeft(8, '0'), _scriptData.Length.ToString(), decompressedSize.ToString()));

            // Padding...
            if ((base.StreamPos(br) % 4) != 0)
                br.BaseStream.Seek(4 - (base.StreamPos(br) % 4), SeekOrigin.Current);

            base.ConstructEnd(br);
        }
Пример #31
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);
            }
        }
Пример #32
0
        private void parse(Stream stream)
        {
            _streamStartPosition = stream.Position;

            _items = new List <QbItemBase>();

            //if (stream.Position != 0)
            //    throw new ApplicationException("The stream must start at position 0 as this parser uses the position to validate pointers.");

            using (BinaryEndianReader br = new BinaryEndianReader(stream))
            {
                _magic    = br.ReadUInt32(this.PakFormat.EndianType);
                _fileSize = br.ReadUInt32(this.PakFormat.EndianType);

                uint sectionValue;

                QbItemBase qib = new QbItemUnknown(20, this);
                qib.Construct(br, QbItemType.Unknown);
                AddItem(qib);

                while (this.StreamPos(br.BaseStream) < _fileSize)
                {
                    sectionValue = br.ReadUInt32(this.PakFormat.EndianType);
                    QbItemType sectionType = this.PakFormat.GetQbItemType(sectionValue);

                    switch (sectionType)
                    {
                    case QbItemType.SectionString:
                    case QbItemType.SectionStringW:
                        qib = new QbItemString(this);
                        break;

                    case QbItemType.SectionArray:
                        qib = new QbItemArray(this);
                        break;

                    case QbItemType.SectionStruct:
                        qib = new QbItemStruct(this);
                        break;

                    case QbItemType.SectionScript:
                        qib = new QbItemScript(this);
                        break;

                    case QbItemType.SectionFloat:
                        qib = new QbItemFloat(this);
                        break;

                    case QbItemType.SectionFloatsX2:
                    case QbItemType.SectionFloatsX3:
                        qib = new QbItemFloatsArray(this);
                        break;

                    case QbItemType.SectionInteger:
                    case QbItemType.SectionStringPointer:
                        qib = new QbItemInteger(this);
                        break;

                    case QbItemType.SectionQbKey:
                    case QbItemType.SectionQbKeyString:
                    case QbItemType.SectionQbKeyStringQs:     //GH:GH
                        qib = new QbItemQbKey(this);
                        break;

                    default:
                        throw new ApplicationException(string.Format("Location 0x{0}: Unknown section type 0x{1}", (this.StreamPos(br.BaseStream) - 4).ToString("X").PadLeft(8, '0'), sectionValue.ToString("X").PadLeft(8, '0')));
                    }
                    qib.Construct(br, sectionType);

                    AddItem(qib);
                }
            }

            uint f = this.FileId; //gettin this sets the file id
        }
Пример #33
0
 protected uint StreamPos(BinaryEndianReader br)
 {
     return Root.StreamPos(br.BaseStream);
 }
Пример #34
0
        public static void CreateSilentWav(int length, string dstFilename, params string[] srcFilenames)
        {
            if (srcFilenames == null || (srcFilenames.Length == 1 && srcFilenames[0].Length == 0))
                return;

            FileHelper.Delete(dstFilename);

            WavSingleChunkHeader[] whi = new WavSingleChunkHeader[srcFilenames.Length];
            BinaryEndianReader[] br = new BinaryEndianReader[srcFilenames.Length];

            int outWav = 0; //use this input wav as the format for the output wav

            for (int c = 0; c < srcFilenames.Length; c++)
            {
                br[c] = new BinaryEndianReader(File.OpenRead(srcFilenames[c]));
                whi[c] = ParseWavSingleChunkHeader(br[c].BaseStream);

                if (whi[c].Channels == 2)
                    outWav = c;
            }

            WavSingleChunkHeader who = new WavSingleChunkHeader();

            uint wLength = (uint)((float)whi[outWav].AvgBytesPerSec * (float)(length / 1000F));
            wLength -= wLength % whi[outWav].BlockAlign;

            who.FileId = "RIFF";
            who.FileLength = (uint)(whi[outWav].DataOffset + wLength) - 8;
            who.RiffType = "WAVE";

            who.ChunkHeaderId = "fmt ";
            who.ChunkHeaderLength = whi[outWav].ChunkHeaderLength;
            who.FormatTag = whi[outWav].FormatTag;
            who.Channels = whi[outWav].Channels;
            who.SamplesPerSec = whi[outWav].SamplesPerSec;
            who.AvgBytesPerSec = whi[outWav].AvgBytesPerSec;
            who.BlockAlign = whi[outWav].BlockAlign;
            who.BitsPerSample = whi[outWav].BitsPerSample;
            who.ExtraBytes = whi[outWav].ExtraBytes;

            who.ChunkId = "data";
            who.ChunkLength = wLength;

            foreach (BinaryEndianReader b in br)
                b.Close();

            using (FileStream fso = File.OpenWrite(dstFilename))
            {
                WriteSingleChunkHeader(who, fso);

                byte[] buffer = new byte[who.AvgBytesPerSec];
                for (int i = 0; i < buffer.Length; i++)
                    buffer[i] = 0;
                long written = 0;

                while (written + buffer.Length < wLength)
                {
                    fso.Write(buffer, 0, buffer.Length);
                    written += buffer.Length;
                }

                if (written != wLength)
                    fso.Write(buffer, 0, (int)(wLength - written));

                fso.Flush();
            }
        }
Пример #35
0
        /// <summary>
        /// Test for silent wavs
        /// </summary>
        /// <param name="filename">input raw wav</param>
        /// <param name="tolerence">0=0% to 1=1%</param>
        /// <returns></returns>
        public static bool IsWavSilent(string filename, float tolerence)
        {
            long tested = 0;
            long silent = 0;
            int pos;

            using (FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
            {
                WavSingleChunkHeader h = WavProcessor.ParseWavSingleChunkHeader(fs);

                BinaryEndianReader br = new BinaryEndianReader(fs);

                for (int i = h.DataOffset; i < ((int)h.ChunkLength - 1024); i += (1024 * 1024)) //check at each meg
                {
                    int block = 0;

                    pos = i;
                    fs.Seek((long)pos, SeekOrigin.Begin);
                    while (block != 1024) //length is block aligned so don't worry about channel count
                    {
                        if (br.ReadInt16(EndianType.Little) == 0)
                            silent += 2;
                        tested += 2;
                        block++;
                    }
                }
            }
            if (((double)silent / (double)tested) >= (double)tolerence)
                return true;
            else
                return false;
        }
Пример #36
0
        public static WavSingleChunkHeader ParseWavSingleChunkHeader(Stream wavStream)
        {
            WavSingleChunkHeader w = new WavSingleChunkHeader();
            byte[] b;

            BinaryEndianReader r = new BinaryEndianReader(wavStream);

            b = r.ReadBytes(4);
            w.FileId = Encoding.Default.GetString(b);
            w.FileLength = r.ReadUInt32(EndianType.Little);
            b = r.ReadBytes(4);
            w.RiffType = Encoding.Default.GetString(b);

            b = r.ReadBytes(4);
            w.ChunkHeaderId = Encoding.Default.GetString(b);
            w.ChunkHeaderLength = r.ReadUInt32(EndianType.Little);
            long p = wavStream.Position;
            w.FormatTag = r.ReadUInt16(EndianType.Little);
            w.Channels = r.ReadUInt16(EndianType.Little);
            w.SamplesPerSec = r.ReadUInt32(EndianType.Little);
            w.AvgBytesPerSec = r.ReadUInt32(EndianType.Little);
            w.BlockAlign = r.ReadUInt16(EndianType.Little);
            w.BitsPerSample = r.ReadUInt16(EndianType.Little);

            if (wavStream.Position - p != w.ChunkHeaderLength)
                w.ExtraBytes = r.ReadBytes((int)(w.ChunkHeaderLength - (wavStream.Position - p)));

            b = r.ReadBytes(4);
            w.ChunkId = Encoding.Default.GetString(b);
            w.ChunkLength = r.ReadUInt32(EndianType.Little);

            w.DataOffset = (int)wavStream.Position;
            return w;
        }
Пример #37
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);

            uint pointer;

            if (type != QbItemType.StructHeader)
                _headerValue = br.ReadUInt32(base.Root.PakFormat.EndianType);
            else
                _headerValue = base.Root.PakFormat.GetQbItemValue(type, this.Root);

             _headerType = base.Root.PakFormat.GetQbItemType(_headerValue);

            QbItemBase qib = null;
            QbItemType structType;
            uint structValue;

            if (_headerType == QbItemType.StructHeader)
            {
                pointer = br.ReadUInt32(base.Root.PakFormat.EndianType); //Should be the current stream position after reading

                _iniNextItemPointer = pointer;

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

                while (pointer != 0)
                {
                    structValue = br.ReadUInt32(this.Root.PakFormat.EndianType);
                    structType = this.Root.PakFormat.GetQbItemType(structValue);

                    switch (structType)
                    {
                        case QbItemType.StructItemStruct:
                            this.Root.PakFormat.StructItemChildrenType = StructItemChildrenType.StructItems;
                            qib = new QbItemStruct(this.Root);
                            break;
                        case QbItemType.StructItemStringPointer:
                        case QbItemType.StructItemInteger:
                            this.Root.PakFormat.StructItemChildrenType = StructItemChildrenType.StructItems;
                            qib = new QbItemInteger(this.Root);
                            break;
                        case QbItemType.StructItemQbKeyString:
                        case QbItemType.StructItemQbKeyStringQs:
                        case QbItemType.StructItemQbKey:
                            this.Root.PakFormat.StructItemChildrenType = StructItemChildrenType.StructItems;
                            qib = new QbItemQbKey(this.Root);
                            break;
                        case QbItemType.StructItemString:
                        case QbItemType.StructItemStringW:
                            this.Root.PakFormat.StructItemChildrenType = StructItemChildrenType.StructItems;
                            qib = new QbItemString(this.Root);
                            break;
                        case QbItemType.StructItemFloat:
                            this.Root.PakFormat.StructItemChildrenType = StructItemChildrenType.StructItems;
                            qib = new QbItemFloat(this.Root);
                            break;
                        case QbItemType.StructItemFloatsX2:
                        case QbItemType.StructItemFloatsX3:
                            this.Root.PakFormat.StructItemChildrenType = StructItemChildrenType.StructItems;
                            qib = new QbItemFloatsArray(this.Root);
                            break;
                        case QbItemType.StructItemArray:
                            this.Root.PakFormat.StructItemChildrenType = StructItemChildrenType.StructItems;
                            qib = new QbItemArray(this.Root);
                            break;

                        //Convert array types to structitems to fit in with this parser (if QbFile.HasStructItems is false then internal type will be swapped back to array)
                        case QbItemType.ArrayStruct:
                            structType = QbItemType.StructItemStruct;
                            qib = new QbItemArray(this.Root);
                            break;
                        case QbItemType.ArrayInteger:
                            structType = QbItemType.StructItemInteger;
                            qib = new QbItemInteger(this.Root);
                            break;
                        case QbItemType.ArrayQbKeyString:
                            structType = QbItemType.StructItemQbKeyString;
                            qib = new QbItemQbKey(this.Root);
                            break;
                        case QbItemType.ArrayStringPointer:
                            structType = QbItemType.StructItemStringPointer;
                            qib = new QbItemInteger(this.Root);
                            break;
                        case QbItemType.ArrayQbKeyStringQs:
                            structType = QbItemType.StructItemQbKeyStringQs;
                            qib = new QbItemQbKey(this.Root);
                            break;
                        case QbItemType.ArrayQbKey:
                            structType = QbItemType.StructItemQbKey;
                            qib = new QbItemQbKey(this.Root);
                            break;
                        case QbItemType.ArrayString:
                            structType = QbItemType.StructItemString;
                            qib = new QbItemString(this.Root);
                            break;
                        case QbItemType.ArrayStringW:
                            structType = QbItemType.StructItemStringW;
                            qib = new QbItemString(this.Root);
                            break;
                        case QbItemType.ArrayFloat:
                            structType = QbItemType.StructItemFloat;
                            qib = new QbItemFloat(this.Root);
                            break;
                        case QbItemType.ArrayFloatsX2:
                            structType = QbItemType.StructItemFloatsX2;
                            qib = new QbItemFloatsArray(this.Root);
                            break;
                        case QbItemType.ArrayFloatsX3:
                            structType = QbItemType.StructItemFloatsX3;
                            qib = new QbItemFloatsArray(this.Root);
                            break;
                        case QbItemType.ArrayArray:
                            structType = QbItemType.StructItemArray;
                            qib = new QbItemArray(this.Root);
                            break;
                        default:
                            qib = null;
                            break;
                    }

                    if (qib != null)
                    {
                        if (this.Root.PakFormat.StructItemChildrenType == StructItemChildrenType.NotSet) //will have been set to structItem if qib is not null)
                            this.Root.PakFormat.StructItemChildrenType = StructItemChildrenType.ArrayItems;

                        qib.Construct(br, structType);
                        AddItem(qib);
                        pointer = qib.NextItemPointer;
                    }
                    else
                        throw new ApplicationException(string.Format("Location 0x{0}: Unknown item type 0x{1} in struct ", (base.StreamPos(br) - 4).ToString("X").PadLeft(8, '0'), structValue.ToString("X").PadLeft(8, '0')));

                }
            }
            else
                throw new ApplicationException(string.Format("Location 0x{0}: Struct without header type", (base.StreamPos(br) - 4).ToString("X").PadLeft(8, '0')));

            base.ConstructEnd(br);
        }
Пример #38
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);

            QbItemBase qib = null;
            QbItemType arrayType;
            uint       arrayValue;

            for (int i = 0; i < base.ItemCount; i++)
            {
                arrayValue = br.ReadUInt32(this.Root.PakFormat.EndianType);
                arrayType  = this.Root.PakFormat.GetQbItemType(arrayValue);

                switch (arrayType)
                {
                case QbItemType.Floats:
                    qib = new QbItemFloats(this.Root);
                    break;

                case QbItemType.ArrayStruct:
                    qib = new QbItemStructArray(this.Root);
                    break;

                case QbItemType.ArrayFloat:
                    qib = new QbItemFloat(this.Root);
                    break;

                case QbItemType.ArrayString:
                case QbItemType.ArrayStringW:
                    qib = new QbItemString(this.Root);
                    break;

                case QbItemType.ArrayFloatsX2:
                case QbItemType.ArrayFloatsX3:
                    qib = new QbItemFloatsArray(this.Root);
                    break;

                case QbItemType.ArrayStringPointer:
                case QbItemType.ArrayInteger:
                    qib = new QbItemInteger(this.Root);
                    break;

                case QbItemType.ArrayArray:
                    qib = new QbItemArray(this.Root);
                    break;

                case QbItemType.ArrayQbKey:
                case QbItemType.ArrayQbKeyString:
                case QbItemType.ArrayQbKeyStringQs:     //GH:GH
                    qib = new QbItemQbKey(this.Root);
                    break;

                case QbItemType.StructHeader:
                    qib = new QbItemStruct(this.Root);
                    break;

                default:
                    throw new ApplicationException(string.Format("Location 0x{0}: Unknown array type 0x{1}", (base.StreamPos(br) - 4).ToString("X").PadLeft(8, '0'), arrayValue.ToString("X").PadLeft(8, '0')));
                }
                qib.Construct(br, arrayType);
                AddItem(qib);
            }
            base.ConstructEnd(br);
        }