예제 #1
0
        private static CpkColumnInfo ReadColumn(BinaryReaderX tableBr, BinaryReaderX stringBr, BinaryReaderX dataBr)
        {
            // Read column info
            var flags      = tableBr.ReadByte();
            var nameOffset = tableBr.ReadInt32();

            // Resolve final information
            var name    = CpkSupport.ReadString(stringBr, nameOffset);
            var storage = (CpkColumnStorage)(flags >> 4);
            var type    = (CpkDataType)(flags & 0xF);

            switch (storage)
            {
            case CpkColumnStorage.Const:
                return(CpkColumnInfo.CreateConst(name, CpkValue.Read(type, tableBr, stringBr, dataBr)));

            case CpkColumnStorage.Default:
                return(CpkColumnInfo.CreateZero(name, type));

            case CpkColumnStorage.Row:
                return(CpkColumnInfo.CreateRow(name, type));

            default:
                throw new InvalidOperationException($"Unknown storage type '{storage}'.");
            }
        }
예제 #2
0
        public void Write(BinaryWriterX bw, StringWriter writer, ref long tablePosition, ref long dataPosition, long dataOffset)
        {
            bw.BaseStream.Position = tablePosition;

            switch (Type)
            {
            case CpkDataType.UInt8:
                bw.Write((byte)_value);
                break;

            case CpkDataType.SInt8:
                bw.Write((sbyte)_value);
                break;

            case CpkDataType.UInt16:
                bw.Write((ushort)_value);
                break;

            case CpkDataType.SInt16:
                bw.Write((short)_value);
                break;

            case CpkDataType.UInt32:
                bw.Write((uint)_value);
                break;

            case CpkDataType.SInt32:
                bw.Write((int)_value);
                break;

            case CpkDataType.UInt64:
                bw.Write((ulong)_value);
                break;

            case CpkDataType.SInt64:
                bw.Write((long)_value);
                break;

            case CpkDataType.Float:
                bw.Write((float)_value);
                break;

            case CpkDataType.String:
                bw.Write((int)writer.WriteString((string)_value));
                break;

            case CpkDataType.Data:
                bw.Write((int)(dataPosition - dataOffset));
                bw.Write(((byte[])_value).Length);
                CpkSupport.WriteData(bw, dataPosition, (byte[])_value);

                dataPosition = bw.BaseStream.Position;
                break;

            default:
                throw new InvalidOperationException($"'{Type}' not supported.");
            }

            tablePosition += GetSize();
        }
예제 #3
0
        public long WriteString(string value)
        {
            if (_cachedStrings.ContainsKey(value))
            {
                return(_cachedStrings[value]);
            }

            _cachedStrings[value] = _stringPosition;

            var bkPos = _bw.BaseStream.Position;

            CpkSupport.WriteString(_bw, _stringOffset + _stringPosition, value);
            _stringPosition         = _bw.BaseStream.Position - _stringOffset;
            _bw.BaseStream.Position = bkPos;

            return(_cachedStrings[value]);
        }
예제 #4
0
        public static CpkTable Create(Stream utfStream, string tableMagic)
        {
            // Read table info
            using var utfBr = new BinaryReaderX(utfStream, ByteOrder.BigEndian);
            var tableInfo = utfBr.ReadType <CpkTableInfo>();

            // Create readers
            var tableStream  = new SubStream(utfStream, 0x8, tableInfo.tableSize);
            var stringStream = new SubStream(tableStream, tableInfo.stringsOffset,
                                             tableInfo.binaryOffset - tableInfo.stringsOffset);
            var dataStream = new SubStream(tableStream, tableInfo.binaryOffset,
                                           tableInfo.tableSize - tableInfo.binaryOffset);

            using var tableBr  = new BinaryReaderX(tableStream, ByteOrder.BigEndian);
            using var stringBr = new BinaryReaderX(stringStream, ByteOrder.BigEndian);
            using var dataBr   = new BinaryReaderX(dataStream, ByteOrder.BigEndian);

            // Read table name
            var name = CpkSupport.ReadString(stringBr, tableInfo.nameOffset);

            // Read columns
            tableStream.Position = 0x18;

            var columns = new CpkColumnInfo[tableInfo.columnCount];

            for (var i = 0; i < tableInfo.columnCount; i++)
            {
                columns[i] = ReadColumn(tableBr, stringBr, dataBr);
            }

            // Read rows
            tableStream.Position = tableInfo.valuesOffset;

            var rows = new CpkRow[tableInfo.rowCount];

            for (var i = 0; i < tableInfo.rowCount; i++)
            {
                rows[i] = ReadRow(tableBr, stringBr, dataBr, columns);
            }

            return(new CpkTable(tableMagic, name, rows));
        }
예제 #5
0
        public static CpkValue Read(CpkDataType type, BinaryReaderX br, BinaryReaderX stringBr, BinaryReaderX dataBr)
        {
            switch (type)
            {
            case CpkDataType.UInt8:
                return(new CpkValue(type)
                {
                    _value = br.ReadByte()
                });

            case CpkDataType.SInt8:
                return(new CpkValue(type)
                {
                    _value = br.ReadSByte()
                });

            case CpkDataType.UInt16:
                return(new CpkValue(type)
                {
                    _value = br.ReadUInt16()
                });

            case CpkDataType.SInt16:
                return(new CpkValue(type)
                {
                    _value = br.ReadInt16()
                });

            case CpkDataType.UInt32:
                return(new CpkValue(type)
                {
                    _value = br.ReadUInt32()
                });

            case CpkDataType.SInt32:
                return(new CpkValue(type)
                {
                    _value = br.ReadInt32()
                });

            case CpkDataType.UInt64:
                return(new CpkValue(type)
                {
                    _value = br.ReadUInt64()
                });

            case CpkDataType.SInt64:
                return(new CpkValue(type)
                {
                    _value = br.ReadInt64()
                });

            case CpkDataType.Float:
                return(new CpkValue(type)
                {
                    _value = br.ReadSingle()
                });

            case CpkDataType.String:
                return(new CpkValue(type)
                {
                    _value = CpkSupport.ReadString(stringBr, br.ReadInt32())
                });

            case CpkDataType.Data:
                return(new CpkValue(type)
                {
                    _value = CpkSupport.ReadBytes(dataBr, br.ReadInt32(), br.ReadInt32())
                });

            default:
                throw new InvalidOperationException($"'{type}' not supported.");
            }
        }