示例#1
0
        public MixFile(string filename, PackageHashType type, int priority)
        {
            this.filename = filename;
            this.priority = priority;
            this.type     = type;
            s             = GlobalFileSystem.Open(filename);

            // Detect format type
            s.Seek(0, SeekOrigin.Begin);
            var isCncMix = s.ReadUInt16() != 0;

            // The C&C mix format doesn't contain any flags or encryption
            var isEncrypted = false;

            if (!isCncMix)
            {
                isEncrypted = (s.ReadUInt16() & 0x2) != 0;
            }

            List <PackageEntry> entries;

            if (isEncrypted)
            {
                long unused;
                entries = ParseHeader(DecryptHeader(s, 4, out dataStart), 0, out unused);
            }
            else
            {
                entries = ParseHeader(s, isCncMix ? 0 : 4, out dataStart);
            }

            index = entries.ToDictionaryWithConflictLog(x => x.Hash,
                                                        "{0} ({1} format, Encrypted: {2}, DataStart: {3})".F(filename, isCncMix ? "C&C" : "RA/TS/RA2", isEncrypted, dataStart),
                                                        null, x => "(offs={0}, len={1})".F(x.Offset, x.Length));
        }
示例#2
0
		public MixFile(string filename, PackageHashType type, int priority)
		{
			this.filename = filename;
			this.priority = priority;
			this.type = type;
			s = GlobalFileSystem.Open(filename);

			// Detect format type
			s.Seek(0, SeekOrigin.Begin);
			var isCncMix = s.ReadUInt16() != 0;

			// The C&C mix format doesn't contain any flags or encryption
			var isEncrypted = false;
			if (!isCncMix)
				isEncrypted = (s.ReadUInt16() & 0x2) != 0;

			List<PackageEntry> entries;
			if (isEncrypted)
			{
				long unused;
				entries = ParseHeader(DecryptHeader(s, 4, out dataStart), 0, out unused);
			}
			else
				entries = ParseHeader(s, isCncMix ? 0 : 4, out dataStart);

			index = entries.ToDictionaryWithConflictLog(x => x.Hash,
				"{0} ({1} format, Encrypted: {2}, DataStart: {3})".F(filename, (isCncMix ? "C&C" : "RA/TS/RA2"), isEncrypted, dataStart),
				null, x => "(offs={0}, len={1})".F(x.Offset, x.Length)
			);
		}
示例#3
0
        // Save a mix to disk with the given contents
        public MixFile(FileSystem context, string filename, int priority, Dictionary <string, byte[]> contents)
        {
            this.filename = filename;
            this.priority = priority;
            this.type     = PackageHashType.Classic;
            this.context  = context;

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

            s = File.Create(filename);
            try
            {
                index = new Dictionary <uint, PackageEntry>();
                contents.Add("local mix database.dat", new XccLocalDatabase(contents.Keys.Append("local mix database.dat")).Data());
                Write(contents);
            }
            catch
            {
                Dispose();
                throw;
            }
        }
示例#4
0
        public static uint HashFilename(string name, PackageHashType type)
        {
            var padding      = name.Length % 4 != 0 ? 4 - name.Length % 4 : 0;
            var paddedLength = name.Length + padding;

            // Avoid stack overflows by only allocating small buffers on the stack, and larger ones on the heap.
            // 64 chars covers most real filenames.
            var upperPaddedName = paddedLength < 64 ? stackalloc char[paddedLength] : new char[paddedLength];

            name.AsSpan().ToUpperInvariant(upperPaddedName);

            switch (type)
            {
            case PackageHashType.Classic:
            {
                for (var p = 0; p < padding; p++)
                {
                    upperPaddedName[paddedLength - 1 - p] = '\0';
                }

                var asciiBytes = paddedLength < 64 ? stackalloc byte[paddedLength] : new byte[paddedLength];
                Encoding.ASCII.GetBytes(upperPaddedName, asciiBytes);

                var data   = MemoryMarshal.Cast <byte, uint>(asciiBytes);
                var result = 0u;
                foreach (var next in data)
                {
                    result = ((result << 1) | (result >> 31)) + next;
                }

                return(result);
            }

            case PackageHashType.CRC32:
            {
                var length = name.Length;
                var lengthRoundedDownToFour = length / 4 * 4;
                if (length != lengthRoundedDownToFour)
                {
                    upperPaddedName[length] = (char)(length - lengthRoundedDownToFour);
                    for (var p = 1; p < padding; p++)
                    {
                        upperPaddedName[length + p] = upperPaddedName[lengthRoundedDownToFour];
                    }
                }

                var asciiBytes = paddedLength < 64 ? stackalloc byte[paddedLength] : new byte[paddedLength];
                Encoding.ASCII.GetBytes(upperPaddedName, asciiBytes);

                return(CRC32.Calculate(asciiBytes));
            }

            default: throw new NotImplementedException($"Unknown hash type `{type}`");
            }
        }
示例#5
0
        static Stream GetFromCache(PackageHashType type, string filename)
        {
            var index  = type == PackageHashType.CRC32 ? crcHashIndex : classicHashIndex;
            var folder = index[PackageEntry.HashFilename(filename, type)]
                         .Where(x => x.Exists(filename))
                         .MinByOrDefault(x => x.Priority);

            if (folder != null)
            {
                return(folder.GetContent(filename));
            }

            return(null);
        }
示例#6
0
		// Save a mix to disk with the given contents
		public MixFile(string filename, int priority, Dictionary<string, byte[]> contents)
		{
			this.filename = filename;
			this.priority = priority;
			this.type = PackageHashType.Classic;

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

			s = File.Create(filename);
			index = new Dictionary<uint, PackageEntry>();
			contents.Add("local mix database.dat", new XccLocalDatabase(contents.Keys.Append("local mix database.dat")).Data());
			Write(contents);
		}
示例#7
0
        public static uint HashFilename(string name, PackageHashType type)
        {
            switch (type)
            {
            case PackageHashType.Classic:
            {
                name = name.ToUpperInvariant();
                if (name.Length % 4 != 0)
                {
                    name = name.PadRight(name.Length + (4 - name.Length % 4), '\0');
                }

                using (var ms = new MemoryStream(Encoding.ASCII.GetBytes(name)))
                {
                    var  len    = name.Length >> 2;
                    uint result = 0;

                    while (len-- != 0)
                    {
                        result = ((result << 1) | (result >> 31)) + ms.ReadUInt32();
                    }

                    return(result);
                }
            }

            case PackageHashType.CRC32:
            {
                name = name.ToUpperInvariant();
                var l = name.Length;
                var a = l >> 2;
                if ((l & 3) != 0)
                {
                    name += (char)(l - (a << 2));
                    var i = 3 - (l & 3);
                    while (i-- != 0)
                    {
                        name += name[a << 2];
                    }
                }

                return(CRC32.Calculate(Encoding.ASCII.GetBytes(name)));
            }

            default: throw new NotImplementedException("Unknown hash type `{0}`".F(type));
            }
        }
示例#8
0
        public static uint HashFilename(string name, PackageHashType type)
        {
            switch (type)
            {
            case PackageHashType.Classic:
            {
                name = name.ToUpperInvariant();
                if (name.Length % 4 != 0)
                {
                    name = name.PadRight(name.Length + (4 - name.Length % 4), '\0');
                }

                var result = 0u;
                var data   = Encoding.ASCII.GetBytes(name);
                var i      = 0;
                while (i < data.Length)
                {
                    var next = (uint)(data[i++] | data[i++] << 8 | data[i++] << 16 | data[i++] << 24);
                    result = ((result << 1) | (result >> 31)) + next;
                }

                return(result);
            }

            case PackageHashType.CRC32:
            {
                name = name.ToUpperInvariant();
                var l = name.Length;
                var a = l >> 2;
                if ((l & 3) != 0)
                {
                    name += (char)(l - (a << 2));
                    var i = 3 - (l & 3);
                    while (i-- != 0)
                    {
                        name += name[a << 2];
                    }
                }

                return(CRC32.Calculate(Encoding.ASCII.GetBytes(name)));
            }

            default: throw new NotImplementedException($"Unknown hash type `{type}`");
            }
        }
示例#9
0
        public static uint HashFilename(string name, PackageHashType type)
        {
            switch (type)
            {
                case PackageHashType.Classic:
                    {
                        name = name.ToUpperInvariant();
                        if (name.Length % 4 != 0)
                            name = name.PadRight(name.Length + (4 - name.Length % 4), '\0');

                        var ms = new MemoryStream(Encoding.ASCII.GetBytes(name));
                        var reader = new BinaryReader(ms);

                        var len = name.Length >> 2;
                        uint result = 0;

                        while (len-- != 0)
                            result = ((result << 1) | (result >> 31)) + reader.ReadUInt32();

                        return result;
                    }

                case PackageHashType.CRC32:
                    {
                        name = name.ToUpperInvariant();
                        var l = name.Length;
                        var a = l >> 2;
                        if ((l & 3) != 0)
                        {
                            name += (char)(l - (a << 2));
                            var i = 3 - (l & 3);
                            while (i-- != 0)
                                name += name[a << 2];
                        }

                        return CRC32.Calculate(Encoding.ASCII.GetBytes(name));
                    }

                default: throw new NotImplementedException("Unknown hash type `{0}`".F(type));
            }
        }
示例#10
0
        static Stream GetFromCache(PackageHashType type, string filename)
        {
            var index = type == PackageHashType.CRC32 ? crcHashIndex : classicHashIndex;
            var folder = index[PackageEntry.HashFilename(filename, type)]
                .Where(x => x.Exists(filename))
                .MinByOrDefault(x => x.Priority);

            if (folder != null)
                return folder.GetContent(filename);

            return null;
        }
示例#11
0
		public static uint HashFilename(string name, PackageHashType type)
		{
			return PackageEntry.HashFilename(name, type);
		}
示例#12
0
 public static uint HashFilename(string name, PackageHashType type)
 {
     return(PackageEntry.HashFilename(name, type));
 }