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); // } // } //}); }
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 } } }); });
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); } }
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}"); } } }); });
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); } }