Beispiel #1
0
        public GameStream(FileSystemEntry manifestFileEntry)
        {
            ManifestFileEntry = manifestFileEntry;
            ManifestFile      = ManifestFile.FromFileSystemEntry(manifestFileEntry);

            ParseStreamFile(".bin", reader =>
            {
                foreach (var asset in ManifestFile.Assets)
                {
                    asset.InstanceData = reader.ReadBytes((int)asset.Header.InstanceDataSize);

                    if (asset.Name.StartsWith("GameMap:"))
                    {
                    }
                }
            });

            //ParseStreamFile(".relo", reader =>
            //{
            //    foreach (var asset in ManifestFile.Assets)
            //    {
            //        if (asset.Header.RelocationDataSize != 0)
            //        {
            //            uint reloValue;
            //            do
            //            {
            //                reloValue = reader.ReadUInt32();

            //                //asset.InstanceData[reloValue] += asset.InstanceData[0];
            //            } while (reloValue != 0xFFFFFFFF);
            //        }
            //    }
            //});
        }
Beispiel #2
0
        public GameStream(FileSystemEntry manifestFileEntry)
        {
            ManifestFileEntry = manifestFileEntry;
            ManifestFile      = ManifestFile.FromFileSystemEntry(manifestFileEntry);

            _assetReferenceToAssetLookup = new Dictionary <AssetReference, Asset>();
            foreach (var asset in ManifestFile.Assets)
            {
                var assetReference = new AssetReference(
                    asset.Header.TypeId,
                    asset.Header.InstanceId);
                _assetReferenceToAssetLookup[assetReference] = asset;
            }

            // Parse .bin, .relo, and .imp files simultaneously.
            ParseStreamFile(".bin", 3132817408u, binReader =>
            {
                ParseStreamFile(".relo", 3133014016u, reloReader =>
                {
                    ParseStreamFile(".imp", 3132162048u, impReader =>
                    {
                        foreach (var asset in ManifestFile.Assets)
                        {
                            ReadBinReloImpData(
                                binReader,
                                reloReader,
                                impReader,
                                asset,
                                out var instanceData,
                                out var relocationData,
                                out var imports);

                            if (instanceData.Length == 0)
                            {
                                continue;
                            }

                            if (AssetReaderCatalog.TryGetAssetReader(asset.Header.TypeId, out var assetReader))
                            {
                                using (var instanceDataStream = new MemoryStream(instanceData, false))
                                    using (var instanceDataReader = new BinaryReader(instanceDataStream, Encoding.ASCII, true))
                                    {
                                        asset.InstanceData = assetReader.Parse(asset, instanceDataReader, relocationData, imports);
                                    }
                            }
                            else
                            {
                                // TODO
                            }
                        }
                    });
                });
Beispiel #3
0
        public static ManifestFile FromFileSystemEntry(FileSystemEntry entry)
        {
            using (var stream = entry.Open())
                using (var reader = new BinaryReader(stream, Encoding.ASCII, true))
                {
                    var result = new ManifestFile
                    {
                        Header = ManifestHeader.Parse(reader)
                    };

                    switch (result.Header.Version)
                    {
                    case 5:
                    case 6:
                    case 7:
                        break;

                    default:
                        throw new InvalidDataException();
                    }

                    result.Assets = new Asset[result.Header.AssetCount];
                    for (var i = 0; i < result.Assets.Length; i++)
                    {
                        result.Assets[i] = new Asset
                        {
                            Header = AssetEntry.Parse(reader, result.Header.Version)
                        };
                    }

                    result.AssetReferences = new AssetReference[result.Header.AssetReferenceBufferSize / AssetReference.SizeInBytes];
                    for (var i = 0; i < result.AssetReferences.Length; i++)
                    {
                        result.AssetReferences[i] = AssetReference.Parse(reader);
                    }

                    foreach (var asset in result.Assets)
                    {
                        asset.AssetReferences = result.AssetReferences.AsSpan().Slice(
                            (int)asset.Header.AssetReferenceOffset / AssetReference.SizeInBytes,
                            (int)asset.Header.AssetReferenceCount);
                    }

                    {
                        var endPosition        = stream.Position + result.Header.ReferencedManifestNameBufferSize;
                        var manifestReferences = new List <ManifestReference>();

                        while (stream.Position < endPosition)
                        {
                            manifestReferences.Add(ManifestReference.Parse(reader));
                        }
                        result.ManifestReferences = manifestReferences;
                    }

                    {
                        var endPosition = stream.Position + result.Header.AssetNameBufferSize;
                        var assetNames  = ReadNameBuffer(reader, endPosition);

                        foreach (var asset in result.Assets)
                        {
                            asset.Name = assetNames[asset.Header.NameOffset];
                        }
                    }

                    {
                        var endPosition     = stream.Position + result.Header.SourceFileNameBufferSize;
                        var sourceFileNames = ReadNameBuffer(reader, endPosition);

                        foreach (var asset in result.Assets)
                        {
                            asset.SourceFileName = sourceFileNames[asset.Header.SourceFileNameOffset];
                        }
                    }

                    return(result);
                }
        }
Beispiel #4
0
        public GameStream(FileSystemEntry manifestFileEntry, Game game)
        {
            ManifestFileEntry = manifestFileEntry;
            ManifestFile      = ManifestFile.FromFileSystemEntry(manifestFileEntry);

            _assetReferenceToAssetLookup = new Dictionary <AssetReference, Asset>();
            foreach (var asset in ManifestFile.Assets)
            {
                var assetReference = new AssetReference(
                    asset.Header.TypeId,
                    asset.Header.InstanceId);
                _assetReferenceToAssetLookup[assetReference] = asset;
            }

            var assetParseContext = new AssetParseContext(game);

            // Parse .bin, .relo, and .imp files simultaneously.
            ParseStreamFile(".bin", 3132817408u, binReader =>
            {
                ParseStreamFile(".relo", 3133014016u, reloReader =>
                {
                    ParseStreamFile(".imp", 3132162048u, impReader =>
                    {
                        foreach (var asset in ManifestFile.Assets)
                        {
                            ReadBinReloImpData(
                                binReader,
                                reloReader,
                                impReader,
                                asset,
                                out var instanceData,
                                out var relocationData,
                                out var imports);

                            asset.AssetImports = imports;

                            if (instanceData.Length == 0)
                            {
                                continue;
                            }

                            if (Enum.IsDefined(typeof(AssetType), asset.Header.TypeId)) // TODO: Remove this.
                            {
                                if (AssetTypeUtility.ShouldSkipFor(asset.Header.TypeId, game.SageGame))
                                {
                                    Logger.Warn($"Skipped AssetType: {asset.Name.Split(':')[0]} = 0x{asset.Header.TypeId:X}");
                                    continue;
                                }

                                if (AssetReaderCatalog.TryGetAssetReader(asset.Header.TypeId, out var assetReader))
                                {
                                    using (var instanceDataStream = new MemoryStream(instanceData, false))
                                        using (var instanceDataReader = new BinaryReader(instanceDataStream, Encoding.ASCII, true))
                                        {
                                            var zero = instanceDataReader.ReadUInt32();
                                            if (zero != 0)
                                            {
                                                throw new InvalidDataException();
                                            }

                                            asset.InstanceData = assetReader(asset, instanceDataReader, imports, assetParseContext);

                                            var assetCollection = assetParseContext.AssetStore.GetAssetCollection(asset.Header.TypeId);
                                            if (assetCollection != null) // TODO: Eventually this shouldn't be null.
                                            {
                                                assetCollection.Add(asset.InstanceData);
                                            }
                                            else
                                            {
                                                var singleAssetStorage = assetParseContext.AssetStore.GetSingleAsset(asset.Header.TypeId);
                                                if (singleAssetStorage != null) // TODO: Eventually this shouldn't be null.
                                                {
                                                    singleAssetStorage.Current = (BaseAsset)asset.InstanceData;
                                                }
                                            }
                                        }
                                }
                                else
                                {
                                    // TODO
                                }
                            }
                            else
                            {
                                // TODO
                                Logger.Info($"Missing AssetType: {asset.Name.Split(':')[0]} = 0x{asset.Header.TypeId:X}");
                            }
                        }
                    });
                });
Beispiel #5
0
        public static ManifestFile FromFileSystemEntry(FileSystemEntry entry)
        {
            using (var stream = entry.Open())
                using (var reader = new BinaryReader(stream, Encoding.ASCII, true))
                {
                    var result = new ManifestFile
                    {
                        Header = ManifestHeader.Parse(reader)
                    };

                    if (result.Header.Version != 5)
                    {
                        throw new System.NotImplementedException();
                    }

                    result.Assets = new Asset[result.Header.AssetCount];
                    for (var i = 0; i < result.Assets.Length; i++)
                    {
                        result.Assets[i] = new Asset
                        {
                            Header = AssetEntry.Parse(reader)
                        };
                    }

                    result.AssetReferences = new AssetReference[result.Header.AssetReferenceBufferSize / AssetReference.SizeInBytes];
                    for (var i = 0; i < result.AssetReferences.Length; i++)
                    {
                        result.AssetReferences[i] = AssetReference.Parse(reader);
                    }

                    {
                        var endPosition        = stream.Position + result.Header.ReferencedManifestNameBufferSize;
                        var manifestReferences = new List <ManifestReference>();

                        while (stream.Position < endPosition)
                        {
                            manifestReferences.Add(ManifestReference.Parse(reader));
                        }
                        result.ManifestReferences = manifestReferences;
                    }

                    {
                        var endPosition = stream.Position + result.Header.AssetNameBufferSize;
                        var assetNames  = ReadNameBuffer(reader, endPosition);

                        foreach (var asset in result.Assets)
                        {
                            asset.Name = assetNames[asset.Header.NameOffset];
                        }
                    }

                    {
                        var endPosition     = stream.Position + result.Header.SourceFileNameBufferSize;
                        var sourceFileNames = ReadNameBuffer(reader, endPosition);

                        foreach (var asset in result.Assets)
                        {
                            asset.SourceFileName = sourceFileNames[asset.Header.SourceFileNameOffset];
                        }
                    }

                    var instanceDataOffset   = 4u;
                    var relocationDataOffset = 4u;
                    var importsDataOffset    = 4u;
                    foreach (var asset in result.Assets)
                    {
                        asset.InstanceDataOffset   = instanceDataOffset;
                        asset.RelocationDataOffset = relocationDataOffset;
                        asset.ImportsDataOffset    = importsDataOffset;

                        instanceDataOffset   += asset.Header.InstanceDataSize;
                        relocationDataOffset += asset.Header.RelocationDataSize;
                        importsDataOffset    += asset.Header.ImportsDataSize;
                    }

                    return(result);
                }
        }