public static void TestChunked() { // reaper eternal rest: //using (Stream chunkedStream = IO.OpenFile(0x710000000000E54)) { // teChunkedData chunked = new teChunkedData(chunkedStream); //} // model: //using (Stream chunkedStream = OpenFile(0xD00000000004286)) { // teChunkedData chunked = new teChunkedData(chunkedStream); //} using (Stream chunkedStream = OpenFile(0xD000000000053AF)) { // orisa nyxl teChunkedData chunked = new teChunkedData(chunkedStream); } //var sw = new Stopwatch(); //const long count = 100; // //using (Stream chunkedStream = OpenFile(0xD00000000004286)) { // { // // setup static // teChunkedData chunked = new teChunkedData(chunkedStream, true); // chunkedStream.Position = 0; // } // sw.Start(); // for (int i = 0; i < count; i++) { // teChunkedData chunked = new teChunkedData(chunkedStream, true); // chunkedStream.Position = 0; // } // sw.Stop(); //} //Console.Out.WriteLine(sw.Elapsed); }
public static void Save(ICLIFlags flags, string directory, DataModels.Unlock unlock, VoiceSet voiceSet) { if (voiceSet == null) { return; } if (!(unlock.STU is STUUnlock_VoiceLine vl)) { return; } HashSet <ulong> voiceLines = new HashSet <ulong>(); using (Stream vlStream = IO.OpenFile(vl.m_F57B051E)) { teChunkedData chunkedData = new teChunkedData(vlStream); foreach (teEffectComponentVoiceStimulus voiceStimulus in chunkedData.GetChunks <teEffectComponentVoiceStimulus>()) { if (voiceSet.Stimuli.TryGetValue(voiceStimulus.Header.VoiceStimulus, out var stimuliLines)) { foreach (var voiceLine in stimuliLines) { voiceLines.Add(voiceLine); } } } } SaveVoiceLines(flags, voiceLines, voiceSet, directory); }
public void Parse(ICLIFlags toolFlags) { var flags = toolFlags as ExtractFlags; var testGuids = flags?.Positionals.Skip(3).Select(x => uint.Parse(x, System.Globalization.NumberStyles.HexNumber)); teChunkedData.Manager.ChunkTypes.Clear(); foreach (var guid in Program.TrackedFiles[0xC]) { if (!(testGuids ?? throw new InvalidDataException()).Contains(teResourceGUID.Index(guid))) { continue; } var path = Path.Combine(flags.OutputPath, "teModelChunk", teResourceGUID.Index(guid).ToString("X")); if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } using (Stream file = IO.OpenFile(guid)) using (BinaryReader reader = new BinaryReader(file)) { teChunkedData chunk = new teChunkedData(reader); for (int i = 0; i < chunk.Chunks.Length; ++i) { if (!(chunk.Chunks[i] is teDataChunk_Dummy dummy)) { continue; } var filename = Path.Combine(path, chunk.ChunkTags[i]); using (Stream target = File.OpenWrite(filename)) { dummy.Data.CopyTo(target); } } } } }
public void Parse(ICLIFlags toolFlags) { var flags = toolFlags as ExtractFlags; var testGuids = flags?.Positionals.Skip(3).Select(x => uint.Parse(x, System.Globalization.NumberStyles.HexNumber)); foreach (var guid in Program.TrackedFiles[0xC]) { if (!(testGuids ?? throw new InvalidDataException()).Contains(teResourceGUID.Index(guid))) { continue; } using (Stream file = IO.OpenFile(guid)) using (BinaryReader reader = new BinaryReader(file)) { teChunkedData chunk = new teChunkedData(reader); teModelChunk_STU stuChunk = chunk.GetChunk <teModelChunk_STU>(); var hitboxes = stuChunk.StructuredData.m_CB4D298D; var complex = hitboxes.Select(x => x.m_B7C8314A).OfType <STU_B3800E70>().First(); var lines = new List <string> { "ply", "format ascii 1.0", $"element vertex {complex.m_88FCECD7.Length}", "property float x", "property float y", "property float z", "end_header" }; lines.AddRange(complex.m_88FCECD7.Select(x => $"{x.X} {x.Y} {x.Z}")); // vertex File.WriteAllText(@"F:\Test.ply", string.Join("\n", lines)); } } }
public RefPoseSkeleton(teChunkedData chunkedData) { ChunkedData = chunkedData; if (_culture != null) { return; } _culture = (CultureInfo)CultureInfo.InvariantCulture.Clone(); _culture.NumberFormat.NumberDecimalSeparator = "."; }
private void SaveEffect(string dir, ulong guid) { using (Stream stream = OpenFile(guid)) { teChunkedData chunkedData = new teChunkedData(stream); ulong lastModel = 0; foreach (IChunk chunk in chunkedData.Chunks) { if (chunk is teEffectChunkShaderSetup shaderSetup) { //if (teResourceGUID.Index(lastModel) != 0x296B) continue; // the circle ExtractDebugShaders.SaveMaterial(dir, shaderSetup.Header.Material, GetFileName(guid)); } if (chunk is teEffectComponentParticle particle) { lastModel = particle.Header.Model; } else { lastModel = 0; } } foreach (teEffectComponentEntityControl entityControl in chunkedData.GetChunks <teEffectComponentEntityControl>()) { if (entityControl.Header.Animation == 0) { continue; } SaveAnimation(dir, entityControl.Header.Animation); } foreach (teEffectComponentModel model in chunkedData.GetChunks <teEffectComponentModel>()) { if (model.Header.Animation == 0) { continue; } SaveAnimation(dir, model.Header.Animation); } } }
public static void SaveModel(ICLIFlags flags, string path, FindLogic.Combo.ComboInfo info, ulong modelGUID) { bool convertModels = true; bool doRefpose = false; byte lod = 1; if (flags is ExtractFlags extractFlags) { convertModels = extractFlags.ConvertModels && !extractFlags.Raw; doRefpose = extractFlags.ExtractRefpose; lod = extractFlags.LOD; if (extractFlags.SkipModels) { return; } } FindLogic.Combo.ModelInfoNew modelInfo = info.Models[modelGUID]; string modelDirectory = Path.Combine(path, "Models", modelInfo.GetName()); if (convertModels) { string modelPath = Path.Combine(modelDirectory, $"{modelInfo.GetNameIndex()}.owmdl"); CreateDirectoryFromFile(modelPath); using (Stream modelStream = OpenFile(modelInfo.GUID)) { teChunkedData chunkedData = new teChunkedData(modelStream); OverwatchModel model = new OverwatchModel(chunkedData, modelInfo.GUID, (sbyte)lod); if (modelInfo.ModelLooks.Count > 0) { FindLogic.Combo.ModelLookInfo modelLookInfo = info.ModelLooks[modelInfo.ModelLooks.First()]; model.ModelLookFileName = Path.Combine("ModelLooks", modelLookInfo.GetNameIndex() + ".owmat"); } using (Stream fileStream = File.OpenWrite(modelPath)) { fileStream.SetLength(0); model.Write(fileStream); } if (doRefpose) { string refposePath = Path.Combine(modelDirectory, modelInfo.GetNameIndex() + ".smd"); using (Stream fileStream = File.OpenWrite(refposePath)) { fileStream.SetLength(0); var refpose = new RefPoseSkeleton(chunkedData); refpose.Write(fileStream); } } } } else { using (Stream modelStream = OpenFile(modelInfo.GUID)) { WriteFile(modelStream, Path.Combine(modelDirectory, modelInfo.GetNameIndex() + ".00C")); } } foreach (ulong modelModelLook in modelInfo.ModelLooks) { SaveModelLook(flags, modelDirectory, info, modelModelLook); } foreach (ulong looseMaterial in modelInfo.LooseMaterials) { SaveMaterial(flags, modelDirectory, info, looseMaterial); } foreach (ulong modelAnimation in modelInfo.Animations) { SaveAnimation(flags, modelDirectory, info, modelAnimation, modelGUID); } }
public void Process(EffectInfo effectInfo, KeyValuePair <ChunkPlaybackInfo, IChunk> chunk, Dictionary <ulong, ulong> replacements) { // todo: STUVoiceStimulus has f3099f20/m_volume // probably more stuff too // hey have some notes about particles: // 000000003CEC.006 - 000000001D3D.08F = ana - guardian: // one RPCE, 61 chunks // seems to be at correct position with rpce at rot: x=90 // 000000003796.006 - 000000001A31.08F = genji - warrior's salute: // one RPCE, 64 chunks. // VCCE might be a texture/material transform // A B C D = R G B A // see 'extract-debug-vcce' if (effectInfo == null) { return; } if (chunk.Value == null) { return; } if (replacements == null) { replacements = new Dictionary <ulong, ulong>(); } // if (chunk.Value.GetType() == typeof(TCFE)) { // TCFE tcfe = chunk.Value as TCFE; // if (tcfe == null) return; // effectInfo.EffectLength = tcfe.Data.EndTime1; // } else if (chunk.Value is teEffectComponentModel model) { AddDMCE(effectInfo, model, chunk.Key, replacements); } if (chunk.Value is teEffectComponentEntityControl control) { AddCECE(effectInfo, control, chunk.Key, replacements); } if (chunk.Value is teEffectComponentSound sound) { AddOSCE(effectInfo, sound, chunk.Key, replacements); } else if (chunk.Value is teEffectComponentEffect effectComponentEffect) { EffectInfo feceInfo = null; ulong effectGuid = effectComponentEffect.Header.Effect; if (replacements.ContainsKey(effectGuid)) { effectGuid = replacements[effectGuid]; } using (Stream effectStream = IO.OpenFile(effectGuid)) { if (effectStream != null) { teChunkedData subChunked = new teChunkedData(effectStream); EffectParser sub = new EffectParser(subChunked, effectGuid); feceInfo = sub.ProcessAll(replacements); } } AddFECE(effectInfo, effectGuid, feceInfo, chunk.Key, replacements); } else if (chunk.Value is teEffectComponentEntity entity) { AddNECE(effectInfo, entity, chunk.Key, replacements); } else if (chunk.Value is teEffectComponentVoiceStimulus voiceStimulus) { AddSVCE(effectInfo, voiceStimulus, chunk.Key, replacements); } // if (chunk.Value.GetType() == typeof(RPCE)) { // RPCE rpce = chunk.Value as RPCE; // if (rpce == null) return; // AddRPCE(effectInfo, rpce, chunk.Key, replacements); // } // if (chunk.Value.GetType() == typeof(SSCE)) { // SSCE ssce = chunk.Value as SSCE; // if (ssce == null) return; // // AddSSCE(effectInfo, ssce, chunk.Key.PreviousChunk?.GetType(), replacements); // } }
public EffectParser(teChunkedData chunked, ulong guid) { ChunkedData = chunked; GUID = guid; }
public static void SaveModel(ICLIFlags flags, string path, SaveContext info, ulong modelGUID) { bool convertModels = true; bool doRefpose = false; bool doStu = false; byte lod = 1; if (flags is ExtractFlags extractFlags) { convertModels = !extractFlags.RawModels && !extractFlags.Raw; doRefpose = extractFlags.ExtractRefpose; doStu = extractFlags.ExtractModelStu; lod = extractFlags.LOD; if (extractFlags.SkipModels) { return; } } FindLogic.Combo.ModelAsset modelInfo = info.m_info.m_models[modelGUID]; string modelDirectory = Path.Combine(path, "Models", modelInfo.GetName()); if (convertModels) { string modelPath = Path.Combine(modelDirectory, $"{modelInfo.GetNameIndex()}.owmdl"); using (Stream modelStream = OpenFile(modelInfo.m_GUID)) { if (modelStream == null) { return; } CreateDirectoryFromFile(modelPath); teChunkedData chunkedData = new teChunkedData(modelStream); OverwatchModel model = new OverwatchModel(chunkedData, modelInfo.m_GUID, (sbyte)lod); if (modelInfo.m_modelLooks.Count > 0) { FindLogic.Combo.ModelLookAsset modelLookInfo = info.m_info.m_modelLooks[modelInfo.m_modelLooks.First()]; model.ModelLookFileName = Path.Combine("ModelLooks", modelLookInfo.GetNameIndex() + ".owmat"); } using (Stream fileStream = File.OpenWrite(modelPath)) { fileStream.SetLength(0); model.Write(fileStream); } if (doRefpose) { string refposePath = Path.Combine(modelDirectory, modelInfo.GetNameIndex() + ".smd"); using (Stream fileStream = File.OpenWrite(refposePath)) { fileStream.SetLength(0); var refpose = new RefPoseSkeleton(chunkedData); refpose.Write(fileStream); } } if (doStu) { var stu = chunkedData.GetChunks <teModelChunk_STU>().Select(x => x.StructuredData).ToArray(); string stuPath = Path.Combine(modelDirectory, modelInfo.GetNameIndex() + ".json"); JSONTool.OutputJSONAlt(stu, new ListFlags { Output = stuPath }, false); } } } else { using (Stream modelStream = OpenFile(modelInfo.m_GUID)) { WriteFile(modelStream, Path.Combine(modelDirectory, modelInfo.GetNameIndex() + ".00C")); } } foreach (ulong modelModelLook in modelInfo.m_modelLooks) { SaveModelLook(flags, modelDirectory, info, modelModelLook); } foreach (ulong looseMaterial in modelInfo.m_looseMaterials) { SaveMaterial(flags, modelDirectory, info, looseMaterial); } foreach (ulong modelAnimation in modelInfo.n_animations) { SaveAnimation(flags, modelDirectory, info, modelAnimation, modelGUID); } }
public OverwatchModel(teChunkedData chunkedData, ulong guid, sbyte targetLod = 1) { _data = chunkedData; GUID = guid; TargetLod = targetLod; }
public static void TryConvertFile(Stream stream, string convertDir, string md5) { using (BinaryReader reader = new BinaryReader(stream, Encoding.UTF8, true)) { uint magic = reader.ReadUInt32(); stream.Position = 0; if (magic == teChunkedData.Magic) { teChunkedData chunkedData = new teChunkedData(reader); if (chunkedData.Header.StringIdentifier == "MODL") { OverwatchModel model = new OverwatchModel(chunkedData, 0); using (Stream file = File.OpenWrite(Path.Combine(convertDir, md5) + ".owmdl")) { file.SetLength(0); model.Write(file); } } } else if (magic == 0x4D4F5649) // MOVI { stream.Position = 128; using (Stream file = File.OpenWrite(Path.Combine(convertDir, md5) + ".bk2")) { file.SetLength(0); stream.CopyTo(file); } } else { // ok might be a heckin bundle /*int i = 0; * while (reader.BaseStream.Position < reader.BaseStream.Length) { * try { * magic = reader.ReadUInt32(); * if (magic != teChunkedData.Magic) { * reader.BaseStream.Position -= 3; * continue; * } * reader.BaseStream.Position -= 4; * teChunkedData chunkedData = new teChunkedData(reader); * if (chunkedData.Header.StringIdentifier == "MODL") { * OverwatchModel model = new OverwatchModel(chunkedData, 0); * using (Stream file = File.OpenWrite(Path.Combine(convertDir, md5) + $"-{i}.owmdl")) { * file.SetLength(0); * model.Write(file); * } * } * * i++; * } catch (Exception) { * // fine * } * }*/ try { //teStructuredData structuredData =new teStructuredData(stream, true); teTexture texture = new teTexture(reader); if (!texture.PayloadRequired && texture.Header.DataSize <= stream.Length && (texture.Header.Flags == teTexture.Flags.Tex1D || texture.Header.Flags == teTexture.Flags.Tex2D || texture.Header.Flags == teTexture.Flags.Tex3D || texture.Header.Flags == teTexture.Flags.Cube || texture.Header.Flags == teTexture.Flags.Array || texture.Header.Flags == teTexture.Flags.Unk16 || texture.Header.Flags == teTexture.Flags.Unk32 || texture.Header.Flags == teTexture.Flags.Unk128) && texture.Header.Height < 10000 && texture.Header.Width < 10000 && texture.Header.DataSize > 68) { using (Stream file = File.OpenWrite(Path.Combine(convertDir, md5) + ".dds")) { file.SetLength(0); texture.SaveToDDS(file, false, texture.Header.MipCount); } } } catch (Exception) { // fine } try { stream.Position = 0; teStructuredData structuredData = new teStructuredData(stream, true); if (structuredData.GetInstance <STUResourceKey>() != null) { var key = structuredData.GetInstance <STUResourceKey>(); Console.Out.WriteLine("found key"); var longKey = ulong.Parse(key.m_keyID, NumberStyles.HexNumber); var longRevKey = BitConverter.ToUInt64(BitConverter.GetBytes(longKey).Reverse().ToArray(), 0); var keyValueString = BitConverter.ToString(key.m_key).Replace("-", string.Empty); var keyNameProper = longRevKey.ToString("X16"); Console.Out.WriteLine("Added Encryption Key {0}, Value: {1}", keyNameProper, keyValueString); } // if (structuredData.GetInstance<STUHero>() != null) { // // } } catch (Exception) { // fine } } } }