private void FixObjectTypes(object data, Type type, OpenTagCache srcInfo) { // The object type enum changed in 11.1.498295 because a new armor type was added at value 3. // These are a bunch of hacks to fix this in most cases. var oldObjectTypeField = type.GetField("ObjectTypeOld"); var newObjectTypeField = type.GetField("ObjectTypeNew"); if (oldObjectTypeField != null && newObjectTypeField != null) { if (VersionDetection.Compare(srcInfo.Version, EngineVersion.V11_1_498295_Live) < 0) { var oldType = (ObjectTypeValueOld)oldObjectTypeField.GetValue(data); newObjectTypeField.SetValue(data, ConvertObjectType(oldType)); } else { var newType = (ObjectTypeValueNew)newObjectTypeField.GetValue(data); oldObjectTypeField.SetValue(data, ConvertObjectType(newType)); } } var phantom = data as PhysicsModel.PhantomType; if (phantom != null) { // Remove the armor bit added at position 8 in flags phantom.Flags = (uint)((phantom.Flags & ~0x1FFE00) | ((phantom.Flags & 0x1FFE00) >> 1)); } var chmt = data as ChocolateMountainNew; if (chmt != null && chmt.LightingVariables != null && chmt.LightingVariables.Count > 3) { chmt.LightingVariables.RemoveAt(3); // Remove armor data from chmt } }
/// <summary> /// Creates a vertex stream for a given engine version. /// </summary> /// <param name="version">The engine version.</param> /// <param name="stream">The base stream.</param> /// <returns>The created vertex stream.</returns> public static IVertexStream Create(EngineVersion version, Stream stream) { if (VersionDetection.Compare(version, EngineVersion.V1_235640_cert_ms25) >= 0) { return(new V1_235640.VertexStream(stream)); } return(new V1_106708.VertexStream(stream)); }
private ResourceLocation FixResourceLocation(ResourceLocation location, EngineVersion srcVersion, EngineVersion destVersion) { if (VersionDetection.Compare(destVersion, EngineVersion.V1_235640_cert_ms25) >= 0) { return(location); } switch (location) { case ResourceLocation.RenderModels: return(ResourceLocation.Resources); case ResourceLocation.Lightmaps: return(ResourceLocation.Textures); } return(location); }
public override bool Execute(List <string> args) { if (args.Count != 4) { return(false); } var srcTag = ArgumentParser.ParseTagIndex(_info.Cache, args[0]); if (srcTag == null) { return(false); } var csvPath = args[1]; var csvOutPath = args[2]; var targetDir = args[3]; // Load the CSV Console.WriteLine("Reading {0}...", csvPath); TagVersionMap tagMap; using (var reader = new StreamReader(File.OpenRead(csvPath))) tagMap = TagVersionMap.ParseCsv(reader); // Load destination files Console.WriteLine("Loading the target tags.dat..."); var destCachePath = Path.Combine(targetDir, "tags.dat"); var destInfo = new OpenTagCache { CacheFile = new FileInfo(destCachePath) }; using (var stream = destInfo.OpenCacheRead()) destInfo.Cache = new TagCache(stream); // Do version detection EngineVersion guessedVersion; destInfo.Version = VersionDetection.DetectVersion(destInfo.Cache, out guessedVersion); if (destInfo.Version == EngineVersion.Unknown) { Console.WriteLine("Unrecognized target version!"); return(true); } Console.WriteLine("- Detected version {0}", VersionDetection.GetVersionString(destInfo.Version)); if (_info.Version != EngineVersion.V11_1_498295_Live && destInfo.Version != EngineVersion.V1_106708_cert_ms23) { Console.Error.WriteLine("Conversion is only supported from 11.1.498295 Live to 1.106708 cert_ms23."); return(true); } // Set up version-specific objects destInfo.Serializer = new TagSerializer(destInfo.Version); destInfo.Deserializer = new TagDeserializer(destInfo.Version); StringIdResolverBase resolver; if (VersionDetection.Compare(destInfo.Version, EngineVersion.V11_1_498295_Live) >= 0) { resolver = new V11_1_498295.StringIdResolver(); } else { resolver = new V1_106708.StringIdResolver(); } // Load stringIDs Console.WriteLine("Loading the target string_ids.dat..."); var destStringIdsPath = Path.Combine(targetDir, "string_ids.dat"); destInfo.StringIdsFile = new FileInfo(destStringIdsPath); using (var stream = destInfo.StringIdsFile.OpenRead()) destInfo.StringIds = new StringIdCache(stream, resolver); // Load resources for the target build Console.WriteLine("Loading target resources..."); var destResources = new ResourceDataManager(); destResources.LoadCachesFromDirectory(destInfo.CacheFile.DirectoryName); // Load resources for our build Console.WriteLine("Loading source resources..."); var srcResources = new ResourceDataManager(); srcResources.LoadCachesFromDirectory(_info.CacheFile.DirectoryName); Console.WriteLine(); Console.WriteLine("CONVERTING FROM VERSION {0} TO {1}", VersionDetection.GetVersionString(_info.Version), VersionDetection.GetVersionString(destInfo.Version)); Console.WriteLine(); TagInstance resultTag; using (Stream srcStream = _info.OpenCacheRead(), destStream = destInfo.OpenCacheReadWrite()) resultTag = ConvertTag(srcTag, _info, srcStream, srcResources, destInfo, destStream, destResources, tagMap); Console.WriteLine(); Console.WriteLine("Repairing decal systems..."); FixDecalSystems(destInfo, resultTag.Index); Console.WriteLine(); Console.WriteLine("Saving stringIDs..."); using (var stream = destInfo.StringIdsFile.Open(FileMode.Open, FileAccess.ReadWrite)) destInfo.StringIds.Save(stream); Console.WriteLine("Writing {0}...", csvOutPath); using (var stream = new StreamWriter(File.Open(csvOutPath, FileMode.Create, FileAccess.ReadWrite))) tagMap.WriteCsv(stream); // Uncomment this to add the new tag as a dependency to cfgt to make testing easier /*using (var stream = destInfo.OpenCacheReadWrite()) * { * destInfo.Cache.Tags[0].Dependencies.Add(resultTag.Index); * destInfo.Cache.UpdateTag(stream, destInfo.Cache.Tags[0]); * }*/ Console.WriteLine(); Console.WriteLine("All done! The converted tag is:"); TagPrinter.PrintTagShort(resultTag); return(true); }
private GeometryReference ConvertGeometry(GeometryReference geometry, OpenTagCache srcInfo, ResourceDataManager srcResources, OpenTagCache destInfo, ResourceDataManager destResources) { if (geometry == null || geometry.Resource == null || geometry.Resource.Index < 0) { return(geometry); } // The format changed starting with version 1.235640, so if both versions are on the same side then they can be converted normally var srcCompare = VersionDetection.Compare(srcInfo.Version, EngineVersion.V1_235640_cert_ms25); var destCompare = VersionDetection.Compare(destInfo.Version, EngineVersion.V1_235640_cert_ms25); if ((srcCompare < 0 && destCompare < 0) || (srcCompare >= 0 && destCompare >= 0)) { geometry.Resource = ConvertResource(geometry.Resource, srcInfo, srcResources, destInfo, destResources); return(geometry); } Console.WriteLine("- Rebuilding geometry resource {0} in {1}...", geometry.Resource.Index, geometry.Resource.GetLocation()); using (MemoryStream inStream = new MemoryStream(), outStream = new MemoryStream()) { // First extract the model data srcResources.Extract(geometry.Resource, inStream); // Now open source and destination vertex streams inStream.Position = 0; var inVertexStream = VertexStreamFactory.Create(srcInfo.Version, inStream); var outVertexStream = VertexStreamFactory.Create(destInfo.Version, outStream); // Deserialize the definition data var resourceContext = new ResourceSerializationContext(geometry.Resource); var definition = srcInfo.Deserializer.Deserialize <RenderGeometryResourceDefinition>(resourceContext); // Convert each vertex buffer foreach (var buffer in definition.VertexBuffers) { ConvertVertexBuffer(buffer.Definition, inStream, inVertexStream, outStream, outVertexStream); } // Copy each index buffer over foreach (var buffer in definition.IndexBuffers) { if (buffer.Definition.Data.Size == 0) { continue; } inStream.Position = buffer.Definition.Data.Address.Offset; buffer.Definition.Data.Address = new ResourceAddress(ResourceAddressType.Resource, (int)outStream.Position); var bufferData = new byte[buffer.Definition.Data.Size]; inStream.Read(bufferData, 0, bufferData.Length); outStream.Write(bufferData, 0, bufferData.Length); StreamUtil.Align(outStream, 4); } // Update the definition data destInfo.Serializer.Serialize(resourceContext, definition); // Now inject the new resource data var newLocation = FixResourceLocation(geometry.Resource.GetLocation(), srcInfo.Version, destInfo.Version); outStream.Position = 0; destResources.Add(geometry.Resource, newLocation, outStream); } return(geometry); }