Exemple #1
0
        public void Deserialize(BinaryReader reader)
        {
            Type = (Types)reader.ReadByte();

            switch (Type)
            {
            case Types.Null:
                break;

            case Types.LocalCoreUUID:
            case Types.UUIDRef:
                GUID = new BaseGGUUID().FromData(reader);
                break;

            case Types.ExternalCoreUUID:
            case Types.StreamingRef:
                GUID = new BaseGGUUID().FromData(reader);

                // This could be a Filename instance - no way to determine the type
                ExternalFile = new BaseString();
                ExternalFile.Deserialize(reader);
                break;

            default:
                throw new NotImplementedException();
            }
        }
Exemple #2
0
        public static HwShader FromData(BinaryReader reader, GameType gameType)
        {
            var shader = new HwShader();

            // shaderDataLength is discarded
            uint shaderDataLength = reader.ReadUInt32();

            shader.ResourceDataHash = BaseGGUUID.FromData(reader);

            shader.Unknown1 = reader.ReadUInt32();
            shader.TypeMask = (BaseProgramTypeMask)reader.ReadUInt32();
            shader.Unknown2 = reader.ReadUInt32();// Related to type mask

            // Horizon Zero Dawn has it hardcoded for some reason
            uint shaderEntryCount = gameType switch
            {
                GameType.DS => reader.ReadUInt32(),
                GameType.HZD => 4,
                _ => throw new NotImplementedException(),
            };

            shader.Programs = new List <ProgramEntry>((int)shaderEntryCount);

            for (uint i = 0; i < shaderEntryCount; i++)
            {
                shader.Programs.Add(ProgramEntry.FromData(reader, gameType));
            }

            uint rootSignatureDataLength = reader.ReadUInt32();

            shader.RootSignatureData = reader.ReadBytesStrict(rootSignatureDataLength);

            return(shader);
        }
        public static BaseGGUUID FromOther(BaseGGUUID other)
        {
            var x = new BaseGGUUID();

            x.AssignFromOther(other);

            return(x);
        }
            public static GUIDTableContainer FromData(SaveState state)
            {
                var container = new GUIDTableContainer();

                // Why do they try to keep GUID allocations balanced across 256 tables? I don't see the point
                for (int i = 0; i < HardcodedTableCount; i++)
                {
                    int guidCount = state.ReadVariableLengthOffset();

                    for (int j = 0; j < guidCount; j++)
                    {
                        container._tables[i].Add(BaseGGUUID.FromData(state.Reader));
                    }
                }

                return(container);
            }
Exemple #5
0
        public static HwIndexArray FromData(BinaryReader reader, GameType gameType)
        {
            var  array             = new HwIndexArray();
            uint indexElementCount = reader.ReadUInt32();

            if (indexElementCount > 0)
            {
                array.Flags = reader.ReadUInt32();
                var format        = (BaseIndexFormat)reader.ReadUInt32();
                var streamingMode = (BaseRenderDataStreamingMode)reader.ReadUInt32();

                array.ResourceDataHash = BaseGGUUID.FromData(reader);
                array.Buffer           = HwBuffer.FromIndexData(reader, gameType, format, streamingMode, indexElementCount);
            }

            return(array);
        }
            public IndexEntry FromData(BinaryReader reader)
            {
                uint pathLength = reader.ReadUInt32();

                if (pathLength > 0)
                {
                    // Strings are expected to be lowercase and prefixed with "cache:"
                    var fullPath = Encoding.UTF8.GetString(reader.ReadBytesStrict(pathLength));
                    FilePath = fullPath.Replace("cache:", "");

                    SMHasher.MurmurHash3_x64_128(Encoding.UTF8.GetBytes(FilePath + char.MinValue), 42, out ulong[] hash);
                    PathHash = hash[0];
                }

                GUID = new BaseGGUUID().FromData(reader);
                var unknown = reader.ReadBytesStrict(16);

                return(this);
            }
 public void AssignFromOther(BaseGGUUID other)
 {
     // No unions. No marshaling. Assign each manually...
     Data0  = other.Data0;
     Data1  = other.Data1;
     Data2  = other.Data2;
     Data3  = other.Data3;
     Data4  = other.Data4;
     Data5  = other.Data5;
     Data6  = other.Data6;
     Data7  = other.Data7;
     Data8  = other.Data8;
     Data9  = other.Data9;
     Data10 = other.Data10;
     Data11 = other.Data11;
     Data12 = other.Data12;
     Data13 = other.Data13;
     Data14 = other.Data14;
     Data15 = other.Data15;
 }
        public BaseGGUUID ReadIndexedGUID()
        {
            if (SaveVersion < 26)
            {
                // Inline read of 16 bytes
                return(BaseGGUUID.FromData(Reader));
            }

            // GUID pool lookup
            short value = Reader.ReadInt16();

            if (value == -1)
            {
                return(BaseGGUUID.Empty);
            }

            int index  = (value >> 8) & 0xFF;
            int offset = value & 0xFF;

            return(_GUIDPool.LookupGUID(index, offset));
        }
        public static HwVertexArray FromData(BinaryReader reader, GameType gameType)
        {
            var array = new HwVertexArray();

            array.VertexCount = reader.ReadUInt32();
            uint streamCount = reader.ReadUInt32();

            array.StreamingMode = (BaseRenderDataStreamingMode)reader.ReadByte();

            array.Streams = new List <VertexStream>((int)streamCount);

            for (uint i = 0; i < streamCount; i++)
            {
                uint flags            = reader.ReadUInt32();
                uint byteStride       = reader.ReadUInt32();
                uint elementDescCount = reader.ReadUInt32();

                var stream = new VertexStream();
                stream.Flags       = flags;
                stream.ElementInfo = new List <VertexElementDesc>((int)elementDescCount);

                for (uint j = 0; j < elementDescCount; j++)
                {
                    stream.ElementInfo.Add(new VertexElementDesc()
                    {
                        ByteOffset     = reader.ReadByte(),
                        StorageType    = (BaseVertexElementStorageType)reader.ReadByte(),
                        ComponentCount = reader.ReadByte(),
                        ElementType    = (BaseVertexElement)reader.ReadByte(),
                    });
                }

                stream.ResourceDataHash = BaseGGUUID.FromData(reader);
                stream.Buffer           = HwBuffer.FromVertexData(reader, gameType, array.StreamingMode, byteStride, array.VertexCount);

                array.Streams.Add(stream);
            }

            return(array);
        }
Exemple #10
0
        public static HwTexture FromData(BinaryReader reader, GameType gameType)
        {
            var texture = new HwTexture();
            var header  = new TextureHeader();

            // 32 byte texture header
            header.Type   = (BaseTextureType)reader.ReadByte(); // 0
            _             = reader.ReadByte();                  // 1
            header.Width  = reader.ReadUInt16();                // 2
            header.Height = reader.ReadUInt16();                // 4

            header.ArraySliceCount = 0;
            header.Depth3D         = 0;

            switch (header.Type)
            {
            case BaseTextureType._2D:
            case BaseTextureType.CubeMap:
                _ = reader.ReadUInt16();
                break;

            case BaseTextureType._3D:
                header.Depth3D = 1u << reader.ReadByte();
                _ = reader.ReadByte();
                break;

            case BaseTextureType._2DArray:
                header.ArraySliceCount = reader.ReadUInt16();
                break;

            default:
                throw new NotImplementedException("Unknown texture type");
            }

            header.MipCount         = reader.ReadByte();                  // 8
            header.PixelFormat      = (BasePixelFormat)reader.ReadByte(); // 9
            header.Unknown1         = reader.ReadByte();                  // 10
            header.Unknown2         = reader.ReadByte();                  // 11
            header.Unknown3         = reader.ReadByte();                  // 12
            header.Flags            = reader.ReadByte();                  // 13
            header.Unknown4         = reader.ReadByte();                  // 14 Something to do with mips. Autogen?
            header.Unknown5         = reader.ReadByte();                  // 15
            header.ResourceDataHash = BaseGGUUID.FromData(reader);        // 16
            texture.Header          = header;

            // Raw pixel data handling
            uint containerSize        = reader.ReadUInt32();        // Size of the remaining data being read
            long containerEndPosition = reader.BaseStream.Position + containerSize;

            texture.EmbeddedDataSize = reader.ReadUInt32();         // Size of pixel data in this core object entry. This value is never used. if (a - b > 0) only.
            uint streamedDataSize = reader.ReadUInt32();            // Size of pixel data in external file. This value is never used. if (a > 0) only.

            texture.StreamedMipCount = reader.ReadUInt32();         // Number of mipmaps in external file

            if (gameType == GameType.DS)
            {
                texture.DeathStrandingUnknown = reader.ReadUInt64();
            }

            if (streamedDataSize > 0)
            {
                texture.StreamHandle = BaseStreamHandle.FromData(reader, gameType);
            }

            // TODO: Something is wrong here. EmbeddedDataSize doesn't always match the actual length of the byte array. Why? Does it depend on header flags?
            if (texture.EmbeddedDataSize > 0)
            {
                texture.EmbeddedTextureData = reader.ReadBytesStrict((uint)(containerEndPosition - reader.BaseStream.Position));
            }

            return(texture);
        }
        private void ReadHeaderData()
        {
            Reader.BaseStream.Position = SaveDataOffset + SaveDataLength - 0x8;
            uint typeDataChunkOffset = Reader.ReadUInt32();
            uint rawDataChunkOffset  = Reader.ReadUInt32();

            // String/GUID tables
            Reader.BaseStream.Position = SaveDataOffset + rawDataChunkOffset;
            {
                // UTF-8 strings
                StringPool = StringTableContainer.FromData(this);

                // UTF-16 strings
                WideStringPool = WideStringTableContainer.FromData(this);

                // GUIDs
                if (SaveVersion >= 26)
                {
                    GUIDPool = GUIDTableContainer.FromData(this);
                }
            }

            // Serialized type information and object instances
            Reader.BaseStream.Position = SaveDataOffset + typeDataChunkOffset;
            {
                // Create basic objects that are immediately registered with the engine
                int objectInstanceTypeCount = ReadVariableLengthOffset();
                LocalSaveObjects = new Dictionary <int, object>();

                for (int i = 0; i < objectInstanceTypeCount; i++)
                {
                    Type objectType    = RTTI.GetTypeByName(ReadIndexedString());
                    int  instanceCount = ReadVariableLengthOffset();

                    for (int j = 0; j < instanceCount; j++)
                    {
                        int objectId = ReadVariableLengthOffset();

                        LocalSaveObjects.Add(objectId, RTTI.CreateObjectInstance(objectType));
                    }
                }

                // Handles to game data objects
                int gameDataObjectCount = ReadVariableLengthOffset();
                GameDataObjects = new Dictionary <int, BaseGGUUID>();

                for (int i = 0; i < gameDataObjectCount; i++)
                {
                    int objectId = ReadVariableLengthOffset();
                    var guid     = new BaseGGUUID().FromData(Reader);

                    GameDataObjects.Add(objectId, guid);
                }

                // RTTI/class member layouts
                RTTIContainer = RTTIMapContainer.FromData(this);

                // File prefetch
                int prefetchFileCount = ReadVariableLengthOffset();
                PrefetchFilePaths = new List <string>(prefetchFileCount);

                for (int i = 0; i < prefetchFileCount; i++)
                {
                    PrefetchFilePaths.Add(ReadIndexedString());
                }
            }

            Reader.BaseStream.Position = SaveDataOffset;
        }
 public BaseRef(Type objectType)
 {
     Type         = Types.Null;
     GUID         = BaseGGUUID.Empty;
     ExternalFile = "";
 }