Beispiel #1
0
        /// <summary>
        /// Validates that the next string is a certain value and throws an exception if it is not.
        /// </summary>
        /// <param name="value">value to be validated</param>
        /// <param name="reader">BinaryReader instance</param>
        public static void ValidateNextString(string value, BinaryReader reader)
        {
            string label = ReadCString(reader);

            if (!label.ToUpperInvariant().Equals(value.ToUpperInvariant()))
            {
                // Turn on debugging so we can log the exception.
                if (!TQDebug.DebugEnabled)
                {
                    TQDebug.DebugEnabled = true;
                }

                TQDebug.DebugWriteLine(string.Format(
                                           CultureInfo.InvariantCulture,
                                           "Error reading file at position {2}.  Expecting '{0}'.  Got '{1}'",
                                           value,
                                           label,
                                           reader.BaseStream.Position - label.Length - 4));

                throw new ArgumentException(string.Format(
                                                CultureInfo.InvariantCulture,
                                                "Error reading file at position {2}.  Expecting '{0}'.  Got '{1}'",
                                                value,
                                                label,
                                                reader.BaseStream.Position - label.Length - 4));
            }
        }
Beispiel #2
0
        /// <summary>
        /// Parses the raw data and converts to internal data.
        /// </summary>
        private void ParseRawData()
        {
            // First create a memory stream so we can decode the binary data as needed.
            using (BinaryReader reader = new BinaryReader(new MemoryStream(this.rawData, false)))
            {
                int offset = 0;
                try
                {
                    this.ParseItemBlock(offset, reader);
                }
                catch (ArgumentException)
                {
                    throw;
                }

                try
                {
                    string outfile = string.Concat(Path.Combine(TQData.TQVaultSaveFolder, this.PlayerName), " Export.txt");
                    using (StreamWriter outStream = new StreamWriter(outfile, false))
                    {
                        outStream.WriteLine("Number of Sacks = {0}", this.numberOfSacks);

                        if (!this.sack.IsEmpty)
                        {
                            outStream.WriteLine();
                            outStream.WriteLine("SACK 0");

                            int itemNumber = 0;
                            foreach (Item item in this.sack)
                            {
                                object[] params1 = new object[20];

                                params1[0] = itemNumber;
                                params1[1] = item.ToString();
                                params1[2] = item.PositionX;
                                params1[3] = item.PositionY;
                                params1[4] = item.Seed;

                                outStream.WriteLine("  {0,5:n0} {1}", params1);
                                itemNumber++;
                            }
                        }
                    }
                }
                catch (IOException exception)
                {
                    if (!TQDebug.DebugEnabled)
                    {
                        TQDebug.DebugEnabled = true;
                    }

                    TQDebug.DebugWriteLine(string.Format(CultureInfo.InvariantCulture, "Error Exporting - '{0} Export.txt'", Path.Combine(TQData.TQVaultSaveFolder, this.PlayerName)));
                    TQDebug.DebugWriteLine(exception.ToString());
                }
            }
        }
Beispiel #3
0
        /// <summary>
        /// Writes a record to a file.
        /// </summary>
        /// <param name="baseFolder">string holding the base folder path</param>
        /// <param name="record">Record we are writing</param>
        /// <param name="destinationFileName">Filename for the new file.</param>
        public void Write(string baseFolder, string record, string destinationFileName)
        {
            try
            {
                if (!this.fileHasBeenRead)
                {
                    this.ReadARCToC();
                }

                string dataID = string.Concat(Path.GetFileNameWithoutExtension(this.FileName), "\\", record);
                byte[] data   = this.GetData(dataID);
                if (data == null)
                {
                    return;
                }

                string destination = baseFolder;
                if (!destination.EndsWith("\\", StringComparison.OrdinalIgnoreCase))
                {
                    destination = string.Concat(destination, "\\");
                }

                destination = string.Concat(destination, destinationFileName);

                // If there is a sub directory in the arc file then we need to create it.
                if (!Directory.Exists(Path.GetDirectoryName(destination)))
                {
                    Directory.CreateDirectory(Path.GetDirectoryName(destination));
                }

                using (FileStream outStream = new FileStream(destination, FileMode.Create, FileAccess.Write))
                {
                    outStream.Write(data, 0, data.Length);
                }
            }
            catch (IOException exception)
            {
                if (!TQDebug.DebugEnabled)
                {
                    TQDebug.DebugEnabled = true;
                }

                TQDebug.DebugWriteLine(exception.ToString());
                return;
            }
        }
Beispiel #4
0
        /// <summary>
        /// Reads the ARC file table of contents to determine if the file is readable.
        /// </summary>
        /// <returns>True if able to read the ToC</returns>
        public bool Read()
        {
            try
            {
                if (!this.fileHasBeenRead)
                {
                    this.ReadARCToC();
                }

                return(this.directoryEntries != null);
            }
            catch (IOException exception)
            {
                if (!TQDebug.DebugEnabled)
                {
                    TQDebug.DebugEnabled = true;
                }

                // Write the exception to the debug log.
                TQDebug.DebugWriteLine(exception.ToString());
                return(false);
            }
        }
Beispiel #5
0
        /// <summary>
        /// Parses the raw binary data for use within TQVault
        /// </summary>
        private void ParseRawData()
        {
            // First create a memory stream so we can decode the binary data as needed.
            using (MemoryStream stream = new MemoryStream(this.rawData, false))
            {
                using (BinaryReader reader = new BinaryReader(stream))
                {
                    // Find the block pairs until we find the block that contains the item data.
                    int blockNestLevel  = 0;
                    int currentOffset   = 0;
                    int itemOffset      = 0;
                    int equipmentOffset = 0;

                    // vaults start at the item data with no crap
                    bool foundItems     = this.IsVault;
                    bool foundEquipment = this.IsVault;

                    while ((!foundItems || !foundEquipment) && (currentOffset = this.FindNextBlockDelim(currentOffset)) != -1)
                    {
                        if (this.rawData[currentOffset] == beginBlockPattern[0])
                        {
                            // begin block
                            ++blockNestLevel;
                            currentOffset += beginBlockPattern.Length;

                            // skip past the 4 bytes of noise after begin_block
                            currentOffset += 4;

                            // Seek our stream to the correct position
                            stream.Seek(currentOffset, SeekOrigin.Begin);

                            // Now get the string for this block
                            string blockName = TQData.ReadCString(reader).ToUpperInvariant();

                            // Assign loc to our new stream position
                            currentOffset = (int)stream.Position;

                            // See if we accidentally got a begin_block or end_block
                            if (blockName.Equals("BEGIN_BLOCK"))
                            {
                                blockName      = "(NONAME)";
                                currentOffset -= beginBlockPattern.Length;
                            }
                            else if (blockName.Equals("END_BLOCK"))
                            {
                                blockName      = "(NONAME)";
                                currentOffset -= endBlockPattern.Length;
                            }
                            else if (blockName.Equals("ITEMPOSITIONSSAVEDASGRIDCOORDS"))
                            {
                                currentOffset += 4;
                                itemOffset     = currentOffset;                             // skip value for itemPositionsSavedAsGridCoords
                                foundItems     = true;
                            }
                            else if (blockName.Equals("USEALTERNATE"))
                            {
                                currentOffset  += 4;
                                equipmentOffset = currentOffset;                                 // skip value for useAlternate
                                foundEquipment  = true;
                            }

                            // Print the string with a nesting level indicator
                            ////string levelString = new string ('-', System.Math.Max(0,blockNestLevel*2-2));
                            ////out.WriteLine ("{0} {2:n0} '{1}'", levelString, blockName, loc);
                        }
                        else
                        {
                            // end block
                            --blockNestLevel;
                            currentOffset += endBlockPattern.Length;
                            ////if (blockNestLevel < 0)
                            ////{
                            //// out.WriteLine ("{0:n0} Block Nest Level < 0!!!", loc);
                            ////}
                        }
                    }
                    ////out.WriteLine ("Final Block Level = {0:n0}", blockNestLevel);

                    if (foundItems)
                    {
                        try
                        {
                            this.ParseItemBlock(itemOffset, reader);
                        }
                        catch (ArgumentException exception)
                        {
                            if (!TQDebug.DebugEnabled)
                            {
                                TQDebug.DebugEnabled = true;
                            }

                            TQDebug.DebugWriteLine(string.Format(CultureInfo.InvariantCulture, "Error parsing player file Item Block - '{0}'", this.PlayerName));
                            TQDebug.DebugWriteLine(exception.ToString());
                            throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "Error parsing player file Item Block- '{0}'", this.PlayerName), exception);
                        }

                        try
                        {
                            string outfile = string.Concat(Path.Combine(TQData.TQVaultSaveFolder, this.PlayerName), " Export.txt");
                            using (StreamWriter outStream = new StreamWriter(outfile, false))
                            {
                                outStream.WriteLine("Number of Sacks = {0}", this.numberOfSacks);

                                int sackNumber = 0;
                                foreach (SackCollection sack in this.sacks)
                                {
                                    if (!sack.IsEmpty)
                                    {
                                        outStream.WriteLine();
                                        outStream.WriteLine("SACK {0}", sackNumber);

                                        int itemNumber = 0;
                                        foreach (Item item in sack)
                                        {
                                            object[] params1 = new object[20];

                                            params1[0] = itemNumber;
                                            params1[1] = item.ToString();
                                            params1[2] = item.PositionX;
                                            params1[3] = item.PositionY;
                                            params1[4] = item.Seed;
                                            ////params1[5] =

                                            outStream.WriteLine("  {0,5:n0} {1}", params1);
                                            itemNumber++;
                                        }
                                    }

                                    sackNumber++;
                                }
                            }
                        }
                        catch (IOException exception)
                        {
                            if (!TQDebug.DebugEnabled)
                            {
                                TQDebug.DebugEnabled = true;
                            }

                            TQDebug.DebugWriteLine(string.Format(
                                                       CultureInfo.InvariantCulture,
                                                       "Error writing Export file - '{0}'",
                                                       string.Concat(Path.Combine(TQData.TQVaultSaveFolder, this.PlayerName), " Export.txt")));
                            TQDebug.DebugWriteLine(exception.ToString());
                        }
                    }

                    // Process the equipment block
                    if (foundEquipment && !this.IsVault)
                    {
                        try
                        {
                            this.ParseEquipmentBlock(equipmentOffset, reader);
                        }
                        catch (ArgumentException exception)
                        {
                            if (!TQDebug.DebugEnabled)
                            {
                                TQDebug.DebugEnabled = true;
                            }

                            TQDebug.DebugWriteLine(string.Format(CultureInfo.InvariantCulture, "Error parsing player file Equipment Block - '{0}'", this.PlayerName));
                            TQDebug.DebugWriteLine(exception.ToString());
                            throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "Error parsing player file Equipment Block - '{0}'", this.PlayerName), exception);
                        }

                        try
                        {
                            string outfile = string.Concat(Path.Combine(TQData.TQVaultSaveFolder, this.PlayerName), " Equipment Export.txt");
                            using (StreamWriter outStream = new StreamWriter(outfile, false))
                            {
                                if (!this.EquipmentSack.IsEmpty)
                                {
                                    int itemNumber = 0;
                                    foreach (Item item in this.EquipmentSack)
                                    {
                                        object[] params1 = new object[20];

                                        params1[0] = itemNumber;
                                        params1[1] = item.ToString();
                                        params1[2] = item.PositionX;
                                        params1[3] = item.PositionY;
                                        params1[4] = item.Seed;
                                        ////params1[5] =

                                        outStream.WriteLine("  {0,5:n0} {1}", params1);
                                        itemNumber++;
                                    }
                                }
                            }
                        }
                        catch (IOException exception)
                        {
                            if (!TQDebug.DebugEnabled)
                            {
                                TQDebug.DebugEnabled = true;
                            }

                            TQDebug.DebugWriteLine(string.Format(
                                                       CultureInfo.InvariantCulture,
                                                       "Error writing Export file - '{0}'",
                                                       string.Concat(Path.Combine(TQData.TQVaultSaveFolder, this.PlayerName), " Equipment Export.txt")));

                            TQDebug.DebugWriteLine(exception.ToString());
                        }
                    }
                }
            }
        }
Beispiel #6
0
        /// <summary>
        /// Reads the ARZ file.
        /// </summary>
        /// <returns>true on success</returns>
        public bool Read()
        {
            StreamWriter outStream = null;

            if (TQDebug.DatabaseDebugLevel > 2)
            {
                outStream = new StreamWriter("arzOut.txt", false);
            }

            try
            {
                // ARZ header file format
                //
                // 0x000000 int32
                // 0x000004 int32 start of dbRecord table
                // 0x000008 int32 size in bytes of dbRecord table
                // 0x00000c int32 numEntries in dbRecord table
                // 0x000010 int32 start of string table
                // 0x000014 int32 size in bytes of string table
                FileStream   instream = new FileStream(this.fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
                BinaryReader reader   = new BinaryReader(instream);
                try
                {
                    int[] header = new int[6];

                    for (int i = 0; i < 6; ++i)
                    {
                        header[i] = reader.ReadInt32();
                        if (outStream != null)
                        {
                            outStream.WriteLine("Header[{0}] = {1:n0} (0x{1:X})", i, header[i]);
                        }
                    }

                    int firstTableStart  = header[1];
                    int firstTableCount  = header[3];
                    int secondTableStart = header[4];

                    this.ReadStringTable(secondTableStart, reader, outStream);
                    this.ReadRecordTable(firstTableStart, firstTableCount, reader, outStream);

                    // 4 final int32's from file
                    // first int32 is numstrings in the stringtable
                    // second int32 is something ;)
                    // 3rd and 4th are crap (timestamps maybe?)
                    for (int i = 0; i < 4; ++i)
                    {
                        int val = reader.ReadInt32();
                        if (outStream != null)
                        {
                            outStream.WriteLine("{0:n0} 0x{0:X}", val);
                        }
                    }
                }
                catch (IOException)
                {
                    throw;
                }
                finally
                {
                    reader.Close();
                }
            }
            catch (IOException exception)
            {
                if (!TQDebug.DebugEnabled)
                {
                    TQDebug.DebugEnabled = true;
                }

                // Write the exception to the debug log.
                TQDebug.DebugWriteLine(exception.ToString());
                return(false);
            }
            finally
            {
                if (outStream != null)
                {
                    outStream.Close();
                }
            }

            return(true);
        }
Beispiel #7
0
            /// <summary>
            /// Decompresses an individual record.
            /// </summary>
            /// <param name="arzFile">ARZ file which we are decompressing.</param>
            /// <returns>decompressed DBRecord.</returns>
            public DBRecordCollection Decompress(ArzFile arzFile)
            {
                // record variables have this format:
                // 0x00 int16 specifies data type:
                //      0x0000 = int - data will be an int32
                //      0x0001 = float - data will be a Single
                //      0x0002 = string - data will be an int32 that is index into string table
                //      0x0003 = bool - data will be an int32
                // 0x02 int16 specifies number of values (usually 1, but sometimes more (for arrays)
                // 0x04 int32 key string ID (the id into the string table for this variable name
                // 0x08 data value
                byte[] data = this.DecompressBytes(arzFile);

                int numberOfDWords = data.Length / 4;

                if (data.Length % 4 != 0)
                {
                    // Turn on debugging so we can log the exception.
                    if (!TQDebug.DebugEnabled)
                    {
                        TQDebug.DebugEnabled = true;
                    }

                    TQDebug.DebugWriteLine(string.Format(CultureInfo.InvariantCulture, "Error in ARZFile - {0}", arzFile.fileName));
                    TQDebug.DebugWriteLine(string.Format(CultureInfo.InvariantCulture, "Error while parsing arz record {0}, data Length = {1} which is not a multiple of 4", this.ID, (int)data.Length));
                    throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "Error while parsing arz record {0}, data Length = {1} which is not a multiple of 4", this.ID, (int)data.Length));
                }

                DBRecordCollection record = new DBRecordCollection(this.ID, this.RecordType);

                // Create a memory stream to read the binary data
                using (BinaryReader inReader = new BinaryReader(new MemoryStream(data, false)))
                {
                    int i = 0;
                    while (i < numberOfDWords)
                    {
                        short  dataType     = inReader.ReadInt16();
                        short  valCount     = inReader.ReadInt16();
                        int    variableID   = inReader.ReadInt32();
                        string variableName = arzFile.Getstring(variableID);

                        if (variableName == null)
                        {
                            // Turn on debugging so we can log the exception.
                            if (!TQDebug.DebugEnabled)
                            {
                                TQDebug.DebugEnabled = true;
                            }

                            TQDebug.DebugWriteLine(string.Format(CultureInfo.InvariantCulture, "Error in ARZFile - {0}", arzFile.fileName));
                            TQDebug.DebugWriteLine(string.Format(CultureInfo.InvariantCulture, "Error while parsing arz record {0}, variable is NULL", this.ID));
                            throw new ArgumentNullException(string.Format(CultureInfo.InvariantCulture, "Error while parsing arz record {0}, variable is NULL", this.ID));
                        }

                        if (dataType < 0 || dataType > 3)
                        {
                            // Turn on debugging so we can log the exception.
                            if (!TQDebug.DebugEnabled)
                            {
                                TQDebug.DebugEnabled = true;
                            }

                            TQDebug.DebugWriteLine(string.Format(CultureInfo.InvariantCulture, "Error in ARZFile - {0}", arzFile.fileName));
                            TQDebug.DebugWriteLine(string.Format(CultureInfo.InvariantCulture, "Error while parsing arz record {0}, variable {1}, bad dataType {2}", this.ID, variableName, dataType));
                            throw new ArgumentOutOfRangeException(string.Format(CultureInfo.InvariantCulture, "Error while parsing arz record {0}, variable {1}, bad dataType {2}", this.ID, variableName, dataType));
                        }

                        Variable v = new Variable(variableName, (VariableDataType)dataType, valCount);

                        if (valCount < 1)
                        {
                            // Turn on debugging so we can log the exception.
                            if (!TQDebug.DebugEnabled)
                            {
                                TQDebug.DebugEnabled = true;
                            }

                            TQDebug.DebugWriteLine(string.Format(CultureInfo.InvariantCulture, "Error in ARZFile - {0}", arzFile.fileName));
                            TQDebug.DebugWriteLine(string.Format(CultureInfo.InvariantCulture, "Error while parsing arz record {0}, variable {1}, bad valCount {2}", this.ID, variableName, valCount));
                            throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "Error while parsing arz record {0}, variable {1}, bad valCount {2}", this.ID, variableName, valCount));
                        }

                        // increment our dword count
                        i += 2 + valCount;

                        for (int j = 0; j < valCount; ++j)
                        {
                            switch (v.DataType)
                            {
                            case VariableDataType.Integer:
                            case VariableDataType.Boolean:
                            {
                                int val = inReader.ReadInt32();
                                v[j] = val;
                                break;
                            }

                            case VariableDataType.Float:
                            {
                                float val = inReader.ReadSingle();
                                v[j] = val;
                                break;
                            }

                            case VariableDataType.StringVar:
                            {
                                int    id  = inReader.ReadInt32();
                                string val = arzFile.Getstring(id);
                                if (val == null)
                                {
                                    val = string.Empty;
                                }
                                else
                                {
                                    val = val.Trim();
                                }

                                v[j] = val;
                                break;
                            }

                            default:
                            {
                                int val = inReader.ReadInt32();
                                v[j] = val;
                                break;
                            }
                            }
                        }

                        record.Set(v);
                    }
                }

                return(record);
            }
Beispiel #8
0
        /// <summary>
        /// Read the table of contents of the ARC file
        /// </summary>
        private void ReadARCToC()
        {
            // Format of an ARC file
            // 0x08 - 4 bytes = # of files
            // 0x0C - 4 bytes = # of parts
            // 0x18 - 4 bytes = offset to directory structure
            //
            // Format of directory structure
            // 4-byte int = offset in file where this part begins
            // 4-byte int = size of compressed part
            // 4-byte int = size of uncompressed part
            // these triplets repeat for each part in the arc file
            // After these triplets are a bunch of null-terminated strings
            // which are the sub filenames.
            // After the subfilenames comes the subfile data:
            // 4-byte int = 3 == indicates start of subfile item  (maybe compressed flag??)
            //          1 == maybe uncompressed flag??
            // 4-byte int = offset in file where first part of this subfile begins
            // 4-byte int = compressed size of this file
            // 4-byte int = uncompressed size of this file
            // 4-byte crap
            // 4-byte crap
            // 4-byte crap
            // 4-byte int = numParts this file uses
            // 4-byte int = part# of first part for this file (starting at 0).
            // 4-byte int = length of filename string
            // 4-byte int = offset in directory structure for filename
            this.fileHasBeenRead = true;

            if (TQDebug.ArcFileDebugLevel > 0)
            {
                TQDebug.DebugWriteLine(string.Format(CultureInfo.InvariantCulture, "ARCFile.ReadARCToC({0})", this.FileName));
            }

            try
            {
                using (FileStream arcFile = new FileStream(this.FileName, FileMode.Open, FileAccess.Read))
                {
                    using (BinaryReader reader = new BinaryReader(arcFile))
                    {
                        if (TQDebug.ArcFileDebugLevel > 1)
                        {
                            TQDebug.DebugWriteLine(string.Format(CultureInfo.InvariantCulture, "File Length={0}", arcFile.Length));
                        }

                        // check the file header
                        if (reader.ReadByte() != 0x41)
                        {
                            return;
                        }

                        if (reader.ReadByte() != 0x52)
                        {
                            return;
                        }

                        if (reader.ReadByte() != 0x43)
                        {
                            return;
                        }

                        if (arcFile.Length < 0x21)
                        {
                            return;
                        }

                        reader.BaseStream.Seek(0x08, SeekOrigin.Begin);
                        int numEntries = reader.ReadInt32();
                        int numParts   = reader.ReadInt32();

                        if (TQDebug.ArcFileDebugLevel > 1)
                        {
                            TQDebug.DebugWriteLine(string.Format(CultureInfo.InvariantCulture, "numEntries={0}, numParts={1}", numEntries, numParts));
                        }

                        ARCPartEntry[] parts   = new ARCPartEntry[numParts];
                        ARCDirEntry[]  records = new ARCDirEntry[numEntries];

                        if (TQDebug.ArcFileDebugLevel > 2)
                        {
                            TQDebug.DebugWriteLine("Seeking to tocOffset location");
                        }

                        reader.BaseStream.Seek(0x18, SeekOrigin.Begin);
                        int tocOffset = reader.ReadInt32();

                        if (TQDebug.ArcFileDebugLevel > 1)
                        {
                            TQDebug.DebugWriteLine(string.Format(CultureInfo.InvariantCulture, "tocOffset = {0}", tocOffset));
                        }

                        // Make sure all 3 entries exist for the toc entry.
                        if (arcFile.Length < (tocOffset + 12))
                        {
                            return;
                        }

                        // Read in all of the part data
                        reader.BaseStream.Seek(tocOffset, SeekOrigin.Begin);
                        int i;
                        for (i = 0; i < numParts; ++i)
                        {
                            parts[i]                = new ARCPartEntry();
                            parts[i].FileOffset     = reader.ReadInt32();
                            parts[i].CompressedSize = reader.ReadInt32();
                            parts[i].RealSize       = reader.ReadInt32();

                            if (TQDebug.ArcFileDebugLevel > 2)
                            {
                                TQDebug.DebugWriteLine(string.Format(CultureInfo.InvariantCulture, "parts[{0}]", i));
                                TQDebug.DebugWriteLine(string.Format(
                                                           CultureInfo.InvariantCulture,
                                                           "  fileOffset={0}, compressedSize={1}, realSize={2}",
                                                           parts[i].FileOffset,
                                                           parts[i].CompressedSize,
                                                           parts[i].RealSize));
                            }
                        }

                        // Now record this offset so we can come back and read in the filenames
                        // after we have read in the file records
                        int fileNamesOffset = (int)arcFile.Position;

                        // Now seek to the location where the file record data is
                        // This offset is from the end of the file.
                        int fileRecordOffset = 44 * numEntries;

                        if (TQDebug.ArcFileDebugLevel > 1)
                        {
                            TQDebug.DebugWriteLine(string.Format(
                                                       CultureInfo.InvariantCulture,
                                                       "fileNamesOffset = {0}.  Seeking to {1} to read file record data.",
                                                       fileNamesOffset,
                                                       fileRecordOffset));
                        }

                        arcFile.Seek(-1 * fileRecordOffset, SeekOrigin.End);
                        for (i = 0; i < numEntries; ++i)
                        {
                            records[i] = new ARCDirEntry();

                            // storageType = 3 - compressed / 1- non compressed
                            int storageType = reader.ReadInt32();

                            if (TQDebug.ArcFileDebugLevel > 2)
                            {
                                TQDebug.DebugWriteLine(string.Format(CultureInfo.InvariantCulture, "StorageType={0}", storageType));
                            }

                            // Added by VillageIdiot to support stored types
                            records[i].StorageType    = storageType;
                            records[i].FileOffset     = reader.ReadInt32();
                            records[i].CompressedSize = reader.ReadInt32();
                            records[i].RealSize       = reader.ReadInt32();
                            int crap = reader.ReadInt32();                             // crap
                            if (TQDebug.ArcFileDebugLevel > 2)
                            {
                                TQDebug.DebugWriteLine(string.Format(CultureInfo.InvariantCulture, "Crap2={0}", crap));
                            }

                            crap = reader.ReadInt32();                             // crap
                            if (TQDebug.ArcFileDebugLevel > 2)
                            {
                                TQDebug.DebugWriteLine(string.Format(CultureInfo.InvariantCulture, "Crap3={0}", crap));
                            }

                            crap = reader.ReadInt32();                             // crap
                            if (TQDebug.ArcFileDebugLevel > 2)
                            {
                                TQDebug.DebugWriteLine(string.Format(CultureInfo.InvariantCulture, "Crap4={0}", crap));
                            }

                            int numberOfParts = reader.ReadInt32();
                            if (numberOfParts < 1)
                            {
                                records[i].Parts = null;
                                if (TQDebug.ArcFileDebugLevel > 2)
                                {
                                    TQDebug.DebugWriteLine(string.Format(CultureInfo.InvariantCulture, "File {0} is not compressed.", i));
                                }
                            }
                            else
                            {
                                records[i].Parts = new ARCPartEntry[numberOfParts];
                            }

                            int firstPart = reader.ReadInt32();
                            crap = reader.ReadInt32();                             // filename length
                            if (TQDebug.ArcFileDebugLevel > 2)
                            {
                                TQDebug.DebugWriteLine(string.Format(CultureInfo.InvariantCulture, "Filename Length={0}", crap));
                            }

                            crap = reader.ReadInt32();                             // filename offset
                            if (TQDebug.ArcFileDebugLevel > 2)
                            {
                                TQDebug.DebugWriteLine(string.Format(CultureInfo.InvariantCulture, "Filename Offset={0}", crap));

                                TQDebug.DebugWriteLine(string.Format(CultureInfo.InvariantCulture, "record[{0}]", i));
                                TQDebug.DebugWriteLine(string.Format(
                                                           CultureInfo.InvariantCulture,
                                                           "  offset={0} compressedSize={1} realSize={2}",
                                                           records[i].FileOffset,
                                                           records[i].CompressedSize,
                                                           records[i].RealSize));

                                if (storageType != 1 && records[i].IsActive)
                                {
                                    TQDebug.DebugWriteLine(string.Format(
                                                               CultureInfo.InvariantCulture,
                                                               "  numParts={0} firstPart={1} lastPart={2}",
                                                               records[i].Parts.Length,
                                                               firstPart,
                                                               firstPart + records[i].Parts.Length - 1));
                                }
                                else
                                {
                                    TQDebug.DebugWriteLine(string.Format(CultureInfo.InvariantCulture, "  INACTIVE firstPart={0}", firstPart));
                                }
                            }

                            if (storageType != 1 && records[i].IsActive)
                            {
                                for (int ip = 0; ip < records[i].Parts.Length; ++ip)
                                {
                                    records[i].Parts[ip] = parts[ip + firstPart];
                                }
                            }
                        }

                        // Now read in the record names
                        arcFile.Seek(fileNamesOffset, SeekOrigin.Begin);
                        byte[]        buffer = new byte[2048];
                        ASCIIEncoding ascii  = new ASCIIEncoding();
                        for (i = 0; i < numEntries; ++i)
                        {
                            // only Active files have a filename entry
                            if (records[i].IsActive)
                            {
                                // For each string, read bytes until I hit a 0x00 byte.
                                if (TQDebug.ArcFileDebugLevel > 2)
                                {
                                    TQDebug.DebugWriteLine(string.Format(CultureInfo.InvariantCulture, "Reading entry name {0:n0}", i));
                                }

                                int bufferSize = 0;

                                while ((buffer[bufferSize++] = reader.ReadByte()) != 0x00)
                                {
                                    if (buffer[bufferSize - 1] == 0x03)
                                    {
                                        // File is null?
                                        arcFile.Seek(-1, SeekOrigin.Current);                                         // backup
                                        bufferSize--;
                                        buffer[bufferSize] = 0x00;
                                        if (TQDebug.ArcFileDebugLevel > 2)
                                        {
                                            TQDebug.DebugWriteLine("Null file - inactive?");
                                        }

                                        break;
                                    }

                                    if (bufferSize >= buffer.Length)
                                    {
                                        TQDebug.DebugWriteLine("ARCFile.ReadARCToC() Error - Buffer size of 2048 has been exceeded.");
                                        if (TQDebug.ArcFileDebugLevel > 2)
                                        {
                                            TQDebug.DebugWriteLine("Buffer contents:\n");
                                            for (int j = 0; j < bufferSize; ++j)
                                            {
                                                TQDebug.DebugWrite(string.Format(CultureInfo.InvariantCulture, "0x{0:X}", buffer[j]));
                                            }

                                            TQDebug.DebugWriteLine(String.Empty);
                                        }
                                    }
                                }

                                if (TQDebug.ArcFileDebugLevel > 2)
                                {
                                    TQDebug.DebugWriteLine(string.Format(
                                                               CultureInfo.InvariantCulture,
                                                               "Read {0:n0} bytes for name.  Converting to string.",
                                                               bufferSize));
                                }

                                string newfile;
                                if (bufferSize >= 1)
                                {
                                    // Now convert the buffer to a string
                                    char[] chars = new char[ascii.GetCharCount(buffer, 0, bufferSize - 1)];
                                    ascii.GetChars(buffer, 0, bufferSize - 1, chars, 0);
                                    newfile = new string(chars);
                                }
                                else
                                {
                                    newfile = string.Format(CultureInfo.InvariantCulture, "Null File {0}", i);
                                }

                                records[i].FileName = TQData.NormalizeRecordPath(newfile);

                                if (TQDebug.ArcFileDebugLevel > 2)
                                {
                                    TQDebug.DebugWriteLine(string.Format(CultureInfo.InvariantCulture, "Name {0:n0} = '{1}'", i, records[i].FileName));
                                }
                            }
                        }

                        // Now convert the array of records into a Dictionary.
                        Dictionary <string, ARCDirEntry> dictionary = new Dictionary <string, ARCDirEntry>(numEntries);
                        if (TQDebug.ArcFileDebugLevel > 1)
                        {
                            TQDebug.DebugWriteLine("Creating Dictionary");
                        }

                        for (i = 0; i < numEntries; ++i)
                        {
                            if (records[i].IsActive)
                            {
                                dictionary.Add(records[i].FileName, records[i]);
                            }
                        }

                        this.directoryEntries = dictionary;

                        if (TQDebug.ArcFileDebugLevel > 0)
                        {
                            TQDebug.DebugWriteLine("Exiting ARCFile.ReadARCToC()");
                        }
                    }
                }
            }
            catch (IOException exception)
            {
                // Turn on debugging.
                if (!TQDebug.DebugEnabled)
                {
                    TQDebug.DebugEnabled = true;
                }

                // Write the errors to the debug log.
                TQDebug.DebugWriteLine("ARCFile.ReadARCToC() - Error reading arcfile");
                TQDebug.DebugWriteLine(exception.ToString());
            }
        }
Beispiel #9
0
        /// <summary>
        /// Extracts the decoded ARC file contents into a folder.
        /// </summary>
        /// <param name="destination">Destination folder for the files.</param>
        /// <returns>true if successful, false on error.</returns>
        public bool ExtractArcFile(string destination)
        {
            try
            {
                if (TQDebug.ArcFileDebugLevel > 0)
                {
                    TQDebug.DebugWriteLine("ARCFile.ReadARCFile()");
                }

                if (!this.fileHasBeenRead)
                {
                    this.ReadARCToC();
                }

                foreach (ARCDirEntry dirEntry in this.directoryEntries.Values)
                {
                    string dataID = string.Concat(Path.GetFileNameWithoutExtension(this.FileName), "\\", dirEntry.FileName);

                    if (TQDebug.ArcFileDebugLevel > 1)
                    {
                        TQDebug.DebugWriteLine(string.Concat("Directory Filename = ", dirEntry.FileName));
                        TQDebug.DebugWriteLine(string.Concat("dataID = ", dataID));
                    }

                    byte[] data = this.GetData(dataID);

                    string filename = destination;
                    if (!filename.EndsWith("\\", StringComparison.Ordinal))
                    {
                        filename = string.Concat(filename, "\\");
                    }

                    filename = string.Concat(filename, dirEntry.FileName);

                    // If there is a sub directory in the arc file then we need to create it.
                    if (!Directory.Exists(Path.GetDirectoryName(filename)))
                    {
                        Directory.CreateDirectory(Path.GetDirectoryName(filename));
                    }

                    if (TQDebug.ArcFileDebugLevel > 1)
                    {
                        TQDebug.DebugWriteLine(string.Concat("Creating File - ", filename));
                    }

                    using (FileStream outStream = new FileStream(filename, FileMode.Create, FileAccess.Write))
                    {
                        outStream.Write(data, 0, data.Length);
                    }
                }

                if (TQDebug.ArcFileDebugLevel > 0)
                {
                    TQDebug.DebugWriteLine("Exiting ARCFile.ReadARCFile()");
                }

                return(true);
            }
            catch (IOException exception)
            {
                // Turn on debugging
                if (!TQDebug.DebugEnabled)
                {
                    TQDebug.DebugEnabled = true;
                }

                // Write the errors to the debug log.
                TQDebug.DebugWriteLine("ARCFile.ReadARCFile() - Error reading arcfile");
                TQDebug.DebugWriteLine(exception.ToString());
                return(false);
            }
        }
Beispiel #10
0
        /// <summary>
        /// Reads data from an ARC file and puts it into a Byte array (or NULL if not found)
        /// </summary>
        /// <param name="dataId">The string ID for the data which we are retieving.</param>
        /// <returns>Returns byte array of the data corresponding to the string ID.</returns>
        public byte[] GetData(string dataId)
        {
            if (TQDebug.ArcFileDebugLevel > 0)
            {
                TQDebug.DebugWriteLine(string.Format(CultureInfo.InvariantCulture, "ARCFile.GetData({0})", dataId));
            }

            if (!this.fileHasBeenRead)
            {
                this.ReadARCToC();
            }

            if (this.directoryEntries == null)
            {
                if (TQDebug.ArcFileDebugLevel > 1)
                {
                    TQDebug.DebugWriteLine(string.Format(CultureInfo.InvariantCulture, "Error - Could not read {0}", this.FileName));
                }

                // could not read the file
                return(null);
            }

            // First normalize the filename
            dataId = TQData.NormalizeRecordPath(dataId);
            if (TQDebug.ArcFileDebugLevel > 1)
            {
                TQDebug.DebugWriteLine(string.Format(CultureInfo.InvariantCulture, "Normalized dataID = {0}", dataId));
            }

            // Find our file in the toc.
            // First strip off the leading folder since it is just the ARC name
            int firstPathDelim = dataId.IndexOf('\\');

            if (firstPathDelim != -1)
            {
                dataId = dataId.Substring(firstPathDelim + 1);
            }

            // Now see if this file is in the toc.
            ARCDirEntry directoryEntry;

            if (directoryEntries.ContainsKey(dataId))
            {
                directoryEntry = this.directoryEntries[dataId];
            }
            else
            {
                // record not found
                if (TQDebug.ArcFileDebugLevel > 1)
                {
                    TQDebug.DebugWriteLine(string.Format(CultureInfo.InvariantCulture, "Error - {0} not found.", dataId));
                }
                return(null);
            }

            // Now open the ARC file and read in the record.
            using (FileStream arcFile = new FileStream(this.FileName, FileMode.Open, FileAccess.Read))
            {
                // Allocate memory for the uncompressed data
                byte[] data = new byte[directoryEntry.RealSize];

                // Now process each part of this record
                int startPosition = 0;

                // First see if the data was just stored without compression.
                if ((directoryEntry.StorageType == 1) && (directoryEntry.CompressedSize == directoryEntry.RealSize))
                {
                    if (TQDebug.ArcFileDebugLevel > 1)
                    {
                        TQDebug.DebugWriteLine(string.Format(
                                                   CultureInfo.InvariantCulture,
                                                   "Offset={0}  Size={1}",
                                                   directoryEntry.FileOffset,
                                                   directoryEntry.RealSize));
                    }

                    arcFile.Seek(directoryEntry.FileOffset, SeekOrigin.Begin);
                    arcFile.Read(data, 0, directoryEntry.RealSize);
                }
                else
                {
                    // The data was compressed so we attempt to decompress it.
                    foreach (ARCPartEntry partEntry in directoryEntry.Parts)
                    {
                        // seek to the part we want
                        arcFile.Seek(partEntry.FileOffset, SeekOrigin.Begin);

                        // Ignore the zlib compression method.
                        arcFile.ReadByte();

                        // Ignore the zlib compression flags.
                        arcFile.ReadByte();

                        // Create a deflate stream.
                        using (DeflateStream deflate = new DeflateStream(arcFile, CompressionMode.Decompress, true))
                        {
                            int bytesRead;
                            int partLength = 0;
                            while ((bytesRead = deflate.Read(data, startPosition, data.Length - startPosition)) > 0)
                            {
                                startPosition += bytesRead;
                                partLength    += bytesRead;

                                // break out of the read loop if we have processed this part completely.
                                if (partLength >= partEntry.RealSize)
                                {
                                    break;
                                }
                            }
                        }
                    }
                }

                if (TQDebug.ArcFileDebugLevel > 0)
                {
                    TQDebug.DebugWriteLine("Exiting ARCFile.GetData()");
                }

                return(data);
            }
        }