private void CopyMeta(Stream outputStream, int address, out int metaDataSize) { var startAddress = outputStream.Align(512); var buffer = new VirtualStream(address); for (var i = 0; i < Index.Count; ++i) { var datum = Index[i]; if (datum.Class == TagClass.Sbsp || datum.Class == TagClass.Ltmp) { datum.Length = 0; datum.VirtualAddress = 0; Index.Update(datum.Identifier, datum); continue; } var data = Deserialize(datum.Identifier); var dataAddress = ( int )buffer.Position; Padding.AssertIsAligned(4, buffer); buffer.Write(data); buffer.Align( ); var length = ( int )buffer.Position - dataAddress; datum.Length = length; datum.VirtualAddress = dataAddress; Index.Update(datum.Identifier, datum); } buffer.Position = 0; buffer.BufferedCopyBytesTo(( int )buffer.Length, outputStream); metaDataSize = outputStream.Align(4096) - startAddress; }
private int CopyStructureMeta(Stream outputStream) { var allocationLength = 0; var scnrBlock = ( ScenarioBlock )Deserialize(Index.ScenarioIdent); var buffer = new byte[0x2000000]; // 32 mebibytes foreach (var scenarioStructureBspReferenceBlock in scnrBlock.StructureBSPs) { // create a virtual stream to write the meta into and assign the origin address // of the first valid memory after the index // // note: the virtual stream is used to generate valid pointer addressess var allocationAddress = VirtualBaseAddress + Index.GetSize( ) + TagIndexBase.HeaderSize; var virtualMemoryStream = new VirtualStream(buffer, allocationAddress); var sbspReference = scenarioStructureBspReferenceBlock.StructureBSP; var ltmpReference = scenarioStructureBspReferenceBlock.StructureLightmap; // if both references are null then we don't copy out the meta if (TagIdent.IsNull(ltmpReference.Ident) && TagIdent.IsNull(sbspReference.Ident)) { continue; } virtualMemoryStream.Write(new byte[16], 0, 16); // create an allocation header to hold information about this memory allocation var structureAllocationHeader = new StructureAllocationHeader { StructureBSPAddress = ( int )virtualMemoryStream.Position, FourCC = TagClass.Sbsp }; // grab the structurebsp from the cache and write it out to the virtual stream, // padding it to 4 byte alignement var sbspBlock = ( ScenarioStructureBspBlock )Deserialize(sbspReference.Ident); virtualMemoryStream.Write(sbspBlock); virtualMemoryStream.Align( ); // if the lightmap is not null write out the meta data into the virtual stream if (!TagIdent.IsNull(ltmpReference.Ident)) { structureAllocationHeader.LightmapAddress = ( int )virtualMemoryStream.Position; var ltmpBlock = ( ScenarioStructureLightmapBlock )Deserialize(ltmpReference.Ident); virtualMemoryStream.Write(ltmpBlock); } structureAllocationHeader.BlockLength = Padding.Align( virtualMemoryStream.Position - allocationAddress, 4096); // set the value of BlockLength to the length of the virtual stream, // then serialize and write the header to the output stream, followed by writing // the contents of the vitual stream to the output stream // finally pad the entire thing to 4096 byte alignment // copy data virtualMemoryStream.Seek(0, SeekOrigin.Begin); structureAllocationHeader.SerializeTo(virtualMemoryStream); virtualMemoryStream.Seek(-StructureAllocationHeader.SizeInBytes, SeekOrigin.Current); scenarioStructureBspReferenceBlock.StructureBlockInfo.BlockOffset = ( int )outputStream.Position; Padding.AssertIsAligned(512, outputStream); virtualMemoryStream.BufferedCopyBytesTo(structureAllocationHeader.BlockLength, outputStream); Padding.AssertIsAligned(512, outputStream); scenarioStructureBspReferenceBlock.StructureBlockInfo.BlockAddress = allocationAddress; scenarioStructureBspReferenceBlock.StructureBlockInfo.BlockLength = structureAllocationHeader.BlockLength; // return only the largest allocation size, because all allocations are in the // same virtual memory allocationLength = allocationLength > structureAllocationHeader.BlockLength ? allocationLength : structureAllocationHeader.BlockLength; } return(allocationLength); }