示例#1
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}");
                            }
                        }
                    });
                });
示例#2
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 = new ArraySegment <AssetReference>(
                            result.AssetReferences,
                            (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);
                }
        }