Кто поможет перевести код с C#(вроде) на Delphi

krivetko-man

Местный
Регистрация
22 Ноя 2008
Сообщения
53
Реакции
62
Credits
56
Код:
using Nemerle.Utility;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System;

namespace Stalker_Mod_Manager
{
    public class StalkerDB : GameDB
    {
        #region nested types

        public enum Type
        {
            | CS;
            | SocEn;
            | SocRu;
        }

        [ Record ]
        private class FileEntry
        {
            [ Accessor ] private _offset : int;
            [ Accessor ] private _size   : int;
            [ Accessor ] private _file   : string;
        }

        private class BitStack
        {
            private _bits : BitArray;
            private mutable _iter : int;

            public this(data : array[byte], start : int, length : int)
            {
                when (start < 0 || start > data.Length)
                    throw ArgumentOutOfRangeException("The specified start is not inside the array.");
                when (length < 0)
                    throw ArgumentOutOfRangeException("Length must be non-negative.");
                when (start + length > data.Length)
                    throw ArgumentOutOfRangeException("The specified range is not inside the array.");
                _bits = BitArray(length * 8);
                _iter = 0;
                for (mutable i = start; i != start + length; ++i)
                {
                    mutable n : int = data[i];
                    repeat (8)
                    {
                        _bits.Set(_iter, n & 0x80 != 0);
                        n <<= 1;
                        ++_iter;
                    }
                }
                _iter = 0;
            }

            public PopByte() : byte
            {
                mutable n = 0;
                when (_bits.Get(_iter))
                    n |= 1;
                ++_iter;
                repeat (7)
                {
                    n <<= 1;
                    when (_bits.Get(_iter))
                        n |= 1;
                    ++_iter;
                }
                n :> byte;
            }

            public PopBit() : int
            {
                def result = if(_bits[_iter]) 1 else 0;
                ++_iter;
                result;
            }
        }

        #endregion

        #region state

        private _fileEntries : Dictionary.[string, FileEntry];
        private _dbPath      : string;

        #endregion

        #region interface

        public this(dbPath : string, dbType : StalkerDB.Type)
        {
            def ForEachDbCs(Do)
            {
                foreach (dir in [ "levels", "localization", "mp", "resources", "patches" ])
                {
                    def dbs = Directory.GetFiles(Path.Combine(dbPath, dir), "*.db*");
                    Array.Sort(dbs, StringComparer.InvariantCultureIgnoreCase);
                    foreach (path in dbs)
                        Do(path, Path.Combine(dir, Path.GetFileName(path)));
                }
            }
            def ForEachDbSoC(Do)
            {
                def dbs = Directory.GetFiles(dbPath, "gamedata.db*");
                Array.Sort(dbs, StringComparer.InvariantCultureIgnoreCase);
                foreach (path in dbs)
                    Do(path, Path.GetFileName(path));
            }
            def ProcessDb(absolutePath, relativePath)
            {
                using (def reader = BinaryReader(File.OpenRead(absolutePath)))
                    ReadDatabase(reader, relativePath, dbType);
            }
            _dbPath      = dbPath;
            _fileEntries = Dictionary(StringComparer.OrdinalIgnoreCase);
            match (dbType)
            {
                | SocRu | SocEn => ForEachDbSoC(ProcessDb);
                | CS              => ForEachDbCs(ProcessDb);
            }
            
        }

        public OpenRead(filePath : string) : Stream
        {
            if (_fileEntries.ContainsKey(filePath))
            {
                def entry = _fileEntries[filePath];
                StalkerDBStream(Path.Combine(_dbPath, entry.File), entry.Offset, entry.Size);
            }
            else
            {
                throw FileNotFoundException($"The database does not contain \"$filePath\"");
            }
        }

        public Exists(path : string) : bool
        {
            _fileEntries.ContainsKey(path);
        }

        public GetFiles() : IEnumerable.[string]
        {
            foreach (entry when entry.Value.Size > 0 in _fileEntries)
                yield entry.Key;
        }

        public override ToString() : string
        {
            def builder = System.Text.StringBuilder();
            foreach (pair in _fileEntries)
            {
                _ = builder.AppendLine($"$(pair.Key) ($(pair.Value.Offset), $(pair.Value.Size))");
            }
            builder.ToString();
        }

        #endregion

        #region implementation

        private ReadDatabase
            ( reader : BinaryReader
            , dbFile : string
            , dbType : StalkerDB.Type
            ) : void
        {
            mutable indexFound = false;
            while (!indexFound)
            {
                def flag   = reader.ReadUInt32();
                def offset = reader.ReadInt32();
                if (flag & 0x7FFFFFFF == 1)
                {
                    indexFound = true;
                    def data = reader.ReadBytes(offset);
                    match (dbType)
                    {
                        | SocRu => DecryptRu(data);
                        | SocEn => DecryptEn(data);
                        | CS     => ()
                    }
                    def index_size : int
                        = (data[3] << 0x18)
                        | (data[2] << 0x10)
                        | (data[1] << 0x08)
                        | (data[0] << 0x00);
                    def result = Decompress(BitStack(data, 4, offset - 4), index_size);
                    foreach ((size, _, _, path, offset) in ParseIndex(result))
                    {
                        if (_fileEntries.ContainsKey(path))
                            _fileEntries[path] = FileEntry(offset, size, dbFile);
                        else
                            _fileEntries.Add(path, FileEntry(offset, size, dbFile));
                    }
                }
                else
                {
                    _ = reader.BaseStream.Seek(offset, SeekOrigin.Current);
                }
            }
        }

        private static ParseIndex(index : IEnumerable.[byte]) : IEnumerable.[int * int * int * string * int]
        {
            def i = index.GetEnumerator();
            // iteration
            mutable dataRemains;
            def MoveNext() : void
            {
                dataRemains = i.MoveNext();
            }
            // general parsing
            def ParseChar() : char
            {
                def c = i.Current :> char;
                MoveNext();
                c;
            }
            def ParseString(length) : string
            {
                def chars = array(length);
                foreach (i in [0 .. length - 1])
                    chars[i] = ParseChar();
                string(chars);
            }
            def ParseHalfWord() : int
            {
                def lw = i.Current;
                MoveNext();
                def hw = i.Current;
                MoveNext();
                (hw << 0x8) | lw;
            }
            def ParseWord() : int
            {
                mutable n = 0;
                mutable shift = 0;
                repeat (4)
                {
                    n |= i.Current << shift;
                    shift += 0x8;
                    MoveNext();
                }
                n;
            }
            // main loop
            MoveNext();
            while (dataRemains)
            {
                def entryLength = ParseHalfWord();
                yield
                    ( ParseWord()
                    , ParseWord()
                    , ParseWord()
                    , ParseString(entryLength - 0x10)
                    , ParseWord()
                    );
            }
        }

        private static DecryptEn(data : array[byte]) : void
        {
            unchecked
            {
                def a1 : array[byte] = array(0x100);
                def a2 : array[byte] = array(0x100);
                for (mutable i = 0; i != 0x100; ++i)
                {
                    a1[i] = i :> byte;
                }
                mutable seed : uint = 0x5BBC4B;
                for (mutable i = 0; i != 0x400; ++i)
                {
                    seed = seed * 0x8088405 + 1;
                    mutable v1 : uint = seed >> 0x18;
                    seed = seed * 0x8088405 + 1;
                    mutable v2 : uint = seed >> 0x18;
                    while (v1 == v2)
                    {
                        seed = seed * 0x8088405 + 1;
                        v2 = seed >> 0x18;
                    }
                    a1[v1 :> int] <-> a1[v2 :> int];
                }
                for (mutable i = 0; i != 0x100; ++i)
                {
                    a2[a1[i] :> int] = i :> byte;
                }
                seed = 0x16EB2EB;
                for (mutable i = 0; i != data.Length; ++i)
                {
                    seed = seed * 0x8088405 + 1;
                    def index = data[i] ^ (seed >> 0x18);
                    data[i] = a2[index :> int];
                }
            }
        }

        private static DecryptRu(data : array[byte]) : void
        {
            unchecked
            {
                def a1 : array[byte] = array(0x100);
                def a2 : array[byte] = array(0x100);
                for (mutable i = 0; i != 0x100; ++i)
                {
                    a1[i] = i :> byte;
                }
                mutable seed : uint = 0x1329436;
                for (mutable i = 0; i != 0x800; ++i)
                {
                    seed = seed * 0x8088405 + 1;
                    mutable v1 : uint = seed >> 0x18;
                    seed = seed * 0x8088405 + 1;
                    mutable v2 : uint = seed >> 0x18;
                    while (v1 == v2)
                    {
                        seed = seed * 0x8088405 + 1;
                        v2 = seed >> 0x18;
                    }
                    a1[v1 :> int] <-> a1[v2 :> int];
                }
                for (mutable i = 0; i != 0x100; ++i)
                {
                    a2[a1[i] :> int] = i :> byte;
                }
                seed = 0x131A9D3;
                for (mutable i = 0; i != data.Length; ++i)
                {
                    seed = seed * 0x8088405 + 1;
                    def index = data[i] ^ (seed >> 0x18);
                    data[i] = a2[index :> int];
                }
            }
        }

        private static Decompress(data : BitStack, index_size : int) : IEnumerable.[byte]
        {
            // declare arrays
            def weights  : array[int]  = array(0x274);
            def parents  : array[int]  = array(0x3AD);
            def children : array[int]  = array(0x273);
            def buffer   : array[byte] = array(0x103B);
            def table : array[int] = array
                [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
                , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
                , 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
                , 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02
                , 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03
                , 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05
                , 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07
                , 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09
                , 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B
                , 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F
                , 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13
                , 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17
                , 0x18, 0x18, 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B, 0x1C, 0x1C, 0x1D, 0x1D, 0x1E, 0x1E, 0x1F, 0x1F
                , 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23, 0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27
                , 0x28, 0x28, 0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B, 0x2C, 0x2C, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F
                , 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F
                , 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03
                , 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03
                , 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04
                , 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04
                , 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04
                , 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05
                , 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05
                , 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05
                , 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05
                , 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06
                , 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06
                , 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06
                , 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07
                , 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07
                , 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07
                , 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
                ];
            // initialize arrays
            foreach (i in [0 .. 0x139])
            {
                weights[i]       = 1;
                parents[i+0x273] = i;
                children[i]      = i + 0x273;
            }
            foreach (j in [0x13A .. 0x272])
            {
                def i = (j - 0x13A) * 2;
                weights[j]     = weights[i] + weights[i + 1];
                parents[i]     = j;
                parents[i + 1] = j;
                children[j]    = i;
            }
            weights[0x273] = 0xFFFF;
            parents[0x272] = 0x0000;
            // decode
            mutable SI : int = 0xFC4;
            foreach (i in [0 .. SI-1])
            {
                buffer[i] = 0x20;
            }
            def decoded = Queue.[byte]();
            while (decoded.Count < index_size)
            {
                mutable leaf = children[0x272];
                while (leaf < 0x273)
                {
                    leaf += data.PopBit();
                    leaf = children[leaf];
                }
                leaf = leaf - 0x273;
                when (weights[0x272] == 0x4000)
                {
                    // half all child weights amd move children together
                    {
                        mutable j = 0;
                        foreach (i in [0 .. 0x272])
                        {
                            when (children[i] >= 0x273)
                            {
                                weights[j]  = (weights[i] + 1) / 2;
                                children[j] = children[i];
                                ++j;
                            }
                        }
                    }
                    // recalculate branches
                    foreach (j in [0x13A .. 0x272])
                    {
                        def i = (j - 0x13A) * 2;
                        // reset branch weight
                        def branchWeight = weights[i] + weights[i + 1];
                        weights[j] = branchWeight;
                        // keep branches sorted
                        mutable start = j - 1;
                        while (weights[start] > branchWeight)
                        {
                            --start;
                        }
                        ++start;
                        Array.Copy(weights, start, weights, start + 1, j - start);
                        weights[start] = branchWeight;
                        Array.Copy(children, start, children, start + 1, j - start);
                        children[start] = i;
                    }
                    // sync parents
                    foreach (i in [0 .. 0x272])
                    {
                        def child = children[i];
                        parents[child] = i;
                        when (child < 0x273)
                            parents[child + 1] = i;
                    }
                }
                // update the tree
                {
                    mutable first = parents[leaf + 0x273];
                    do
                    {
                        ++weights[first];                     // increment the leaf's weight
                        mutable firstWeight = weights[first]; // new weight
                        mutable last        = first + 1;      // next node
                        when (weights[last] < firstWeight)
                        {
                            while (weights[last] < firstWeight)
                                ++last;
                            --last;
                            // switch weights
                            weights[first] <-> weights[last];
                            // switch children
                            def firstChild = children[first];
                            def lastChild  = children[last];
                            children[first] <-> children[last];
                            // switch parents
                            parents[firstChild] = last;
                            when (firstChild < 0x273)
                                parents[firstChild + 1] = last;
                            parents[lastChild] = first;
                            when (lastChild < 0x273)
                                parents[lastChild + 1] = first;
                            // switch iterators
                            first = last;
                        }
                        first = parents[first];
                    } while (first != 0);
                }
                if (leaf < 0x100)
                {
                    decoded.Enqueue(leaf :> byte);
                    buffer[SI] = leaf :> byte;
                    SI = (SI + 1) & 0x0FFF;
                }
                else
                {
                    mutable offset = data.PopByte() :> int;
                    def high_bits = table[offset] << 6;
                    def count = table[offset + 0x100];
                    repeat (count - 2)
                    {
                        offset = (offset << 1) | data.PopBit();
                    }
                    def _tempOffset = offset;
                    offset = (high_bits | (offset & 0x3F)) + 1;
                    def EBP_E = 0xFFF & (SI - offset);
                    foreach (i in [0 .. leaf - 0xFE])
                    {
                        def value = buffer[0x0FFF & (EBP_E + i)];
                        decoded.Enqueue(value);
                        buffer[SI] = value;
                        SI = (SI + 1) & 0x0FFF;
                    }
                }
            }
            decoded;
        }

        #endregion
    }

Особенно важны:
private static DecryptEn(data : array[byte]) : void
private static DecryptRu(data : array[byte]) : void
private static Decompress(data : BitStack, index_size : int) : IEnumerable.[byte]

Очень очень надо!!! Сколько ни пытаюсь понять что здесь происходить, не понимаю!!!