/// <summary> /// Copies the paths from the Index into the given stream at the current address /// note: Creates the table on an align(512) address then creates the table-index on /// an align(512) address following it. /// </summary> /// <param name="outputStream">The stream to write to</param> /// <returns>PathInfoStruct containing addresses/info of the paths table & index</returns> private PathsInfoStruct GeneratePathsTable(Stream outputStream) { var info = new PathsInfoStruct( ); // extract the paths from the index and copy them into a local list object. var paths = Index.Select(x => x.Path).ToList( ); info.PathCount = paths.Count; info.PathTableAddress = outputStream.Align(512); // pad the stream to align(512) and assign the new address to PathTableAddress. GenerateStringEntries(outputStream, paths); // Write the paths into the stream and subtract the PathTableAddress from the new stream position // to get the PathTableLength. info.PathTableLength = ( int )outputStream.Position - info.PathTableAddress; // pad the stream to align(512) and assign the new address to PathIndexAddress. info.PathIndexAddress = outputStream.Align(512); // write the index for the path table GenerateTableIndex(outputStream, paths); // finish on the next 512 alignment boundary outputStream.Align(512); Padding.AssertIsAligned(512, outputStream); // return the struct that contains the information about where in the stream this // resource was written return(info); }
private void CopyUnicodeTable(Stream outputStream) { var globalsBlock = ( GlobalsBlock )Deserialize(Index.GlobalsIdent); var newUnicodeBlockInfo = new MoonfishGlobalUnicodeBlockInfoStructBlock { EnglishStringCount = globalsBlock.UnicodeBlockInfo.EnglishStringCount, EnglishStringTableLength = globalsBlock.UnicodeBlockInfo.EnglishStringTableLength }; // calculate the size of the Unicode table-index & tables to the nearest 512 aligned block var alignedIndexSize = Padding.Align( globalsBlock.UnicodeBlockInfo.EnglishStringCount * sizeof(int) * 2, 512); var alignedTableSize = Padding.Align(globalsBlock.UnicodeBlockInfo.EnglishStringTableLength, 512); // move the stream to the start of the unicode data Seek(globalsBlock.UnicodeBlockInfo.EnglishStringIndexAddress, SeekOrigin.Begin); // copy the table-index and index to the output stream newUnicodeBlockInfo.EnglishStringIndexAddress = ( int )outputStream.Position; Padding.AssertIsAligned(512, outputStream); this.BufferedCopyBytesTo(alignedIndexSize, outputStream); newUnicodeBlockInfo.EnglishStringTableAddress = ( int )outputStream.Position; Padding.AssertIsAligned(512, outputStream); this.BufferedCopyBytesTo(alignedTableSize, outputStream); // assign the new UnicodeBlockInfo data to the globals block globalsBlock.UnicodeBlockInfo = newUnicodeBlockInfo; }
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); }