public static T ReadFromMiloObjectBytes <T>(this MiloSerializer serializer, MiloObjectBytes entry) where T : ISerializable, new() { using (var ms = new MemoryStream(entry.Data)) { var obj = serializer.ReadFromStream <T>(ms); (obj as MiloObject).Name = entry.Name; return(obj); } }
protected MiloObject ParseDirEntryAsBlob(AwesomeReader ar, MiloObjectDir dir, string dirType) { // Reads data as a byte array var entrySize = GuessEntrySize(ar); var entryBytes = new MiloObjectBytes(dirType) { Name = dir.Name }; entryBytes.Data = ar.ReadBytes((int)entrySize); ar.BaseStream.Position += 4; return(entryBytes); }
public override void ReadFromStream(AwesomeReader ar, ISerializable data) { var dir = data as MiloObjectDir; int version = ReadMagic(ar, data); string dirType = null, dirName = null; dir.Extras.Clear(); // Clears for good measure if (version >= 24) { // Parses directory type/name dirType = ar.ReadString(); dirName = FileHelper.SanitizePath(ar.ReadString()); // Skip string hash related values (re-calculated during repack) ar.BaseStream.Position += 8; } int entryCount = ar.ReadInt32(); var entries = Enumerable.Range(0, entryCount).Select(x => new { Type = ar.ReadString(), Name = SanitizeFileName(FileHelper.SanitizePath(ar.ReadString())) }).ToArray(); var is360Gh2 = Is360GH2(); if (version == 10) { // Parses external resource paths? entryCount = ar.ReadInt32(); // Note: Entry can be empty var external = Enumerable.Range(0, entryCount) .Select(x => ar.ReadString()) .ToList(); dir.Extras.Add("ExternalResources", external); } else if (version == 25 && !is360Gh2) { var startOffset = ar.BaseStream.Position; MiloObject dirEntry; try { dirEntry = dirType switch { "ObjectDir" => ParseObjectDir(ar, dir), "WorldDir" => ParseWorldDir(ar, dir), "RndDir" => ParseRndDir(ar, dir), "SynthDir" => ParseSynthDir(ar, dir), _ => ParseDirEntryAsBlob(ar, dir, dirType) }; } catch { ar.BaseStream.Seek(startOffset, SeekOrigin.Begin); dirEntry = ParseDirEntryAsBlob(ar, dir, dirType); } dirEntry.Name = dirName; dir.Extras.Add("DirectoryEntry", dirEntry); } else if (version >= 24) { // GH2 and above var dirEntry = ParseDirEntryAsBlob(ar, dir, dirType); dirEntry.Name = dirName; dir.Extras.Add("DirectoryEntry", dirEntry); } foreach (var entry in entries) { var entryOffset = ar.BaseStream.Position; // TODO: De-serialize entries //try //{ // var miloEntry = ReadFromStream(ar.BaseStream, entry.Type); // miloEntry.Name = entry.Name; // dir.Entries.Add(miloEntry); // ar.BaseStream.Position += 4; // Skips padding // continue; //} //catch (Exception ex) //{ // // Catch exception and log? // ar.Basestream.Position = entryOffset; // Return to start //} // Reads data as a byte array var entrySize = GuessEntrySize(ar); var entryBytes = new MiloObjectBytes(entry.Type) { Name = entry.Name }; entryBytes.Data = ar.ReadBytes((int)entrySize); dir.Entries.Add(entryBytes); ar.BaseStream.Position += 4; } }
public override void ReadFromStream(AwesomeReader ar, ISerializable data) { var dir = data as MiloObjectDir; int version = ReadMagic(ar, data); string dirType = null, dirName = null; dir.Extras.Clear(); // Clears for good measure if (version >= 24) { // Parses directory type/name dirType = ar.ReadString(); dirName = FileHelper.SanitizePath(ar.ReadString()); //ar.BaseStream.Position += 8; // Skips string count + total length dir.Extras.Add("Num1", ar.ReadInt32()); dir.Extras.Add("Num2", ar.ReadInt32()); } int entryCount = ar.ReadInt32(); var entries = Enumerable.Range(0, entryCount).Select(x => new { Type = ar.ReadString(), Name = FileHelper.SanitizePath(ar.ReadString()) }).ToArray(); if (version == 10) { // Parses external resource paths? entryCount = ar.ReadInt32(); // Note: Entry can be empty var external = Enumerable.Range(0, entryCount) .Select(x => ar.ReadString()) .ToList(); dir.Extras.Add("ExternalResources", external); } else if (version == 25 && dirType == "ObjectDir") { // Hack for project 9 var dirEntry = new MiloObjectDirEntry() { Name = dirName }; dirEntry.Version = ar.ReadInt32(); dirEntry.SubVersion = ar.ReadInt32(); dirEntry.ProjectName = ar.ReadString(); // Skip matrices + constants var matCount = ar.ReadInt32(); // Usually 7 ar.BaseStream.Position += (matCount * 48) + 9; // Read imported milos var importedMiloCount = ar.ReadInt32(); dirEntry.ImportedMiloPaths = Enumerable.Range(0, importedMiloCount) .Select(x => ar.ReadString()) .ToArray(); // Boolean, true when sub directory? ar.ReadBoolean(); // Sub directory names seem to be in reverse order of serialization... var subDirCount = ar.ReadInt32(); var subDirNames = Enumerable.Range(0, subDirCount) .Select(x => ar.ReadString()) .ToArray(); // Read subdirectories foreach (var _ in subDirNames.Reverse()) { var subDir = new MiloObjectDir(); ReadFromStream(ar, subDir); dirEntry.SubDirectories.Add(subDir); } dir.Extras.Add("DirectoryEntry", dirEntry); ar.BaseStream.Position += 17; // 0'd data + ADDE } else if (version == 25 && (dirType == "WorldDir")) { // Read past unknown stuff, big hack int unk1 = ar.ReadInt32(); int unk2 = ar.ReadInt32(); float unk3 = ar.ReadSingle(); string unk4 = ar.ReadString(); int unk5 = ar.ReadInt32(); int unk6 = ar.ReadInt32(); // Hack for project 9 var dirEntry = new MiloObjectDirEntry() { Name = dirName }; dirEntry.Version = ar.ReadInt32(); dirEntry.SubVersion = ar.ReadInt32(); dirEntry.ProjectName = ar.ReadString(); // Skip matrices + constants var matCount = ar.ReadInt32(); // Usually 7 ar.BaseStream.Position += (matCount * 48) + 9; // Read imported milos var importedMiloCount = ar.ReadInt32(); dirEntry.ImportedMiloPaths = Enumerable.Range(0, importedMiloCount) .Select(x => ar.ReadString()) .ToArray(); // Boolean, true when sub directory? ar.ReadBoolean(); // Sub directory names seem to be in reverse order of serialization... var subDirCount = ar.ReadInt32(); var subDirNames = Enumerable.Range(0, subDirCount) .Select(x => ar.ReadString()) .ToArray(); // Read subdirectories foreach (var _ in subDirNames.Reverse()) { var subDir = new MiloObjectDir(); ReadFromStream(ar, subDir); dirEntry.SubDirectories.Add(subDir); } dir.Extras.Add("DirectoryEntry", dirEntry); ar.BaseStream.Position += 17; // 0'd data + ADDE } else if (version == 25 && (dirType == "RndDir" || dirType == "SynthDir")) { // Read past unknown stuff, big hack int unk1 = ar.ReadInt32(); // Hack for project 9 var dirEntry = new MiloObjectDirEntry() { Name = dirName }; dirEntry.Version = ar.ReadInt32(); dirEntry.SubVersion = ar.ReadInt32(); dirEntry.ProjectName = ar.ReadString(); // Skip matrices + constants var matCount = ar.ReadInt32(); // Usually 7 ar.BaseStream.Position += (matCount * 48) + 9; // Read imported milos var importedMiloCount = ar.ReadInt32(); dirEntry.ImportedMiloPaths = Enumerable.Range(0, importedMiloCount) .Select(x => ar.ReadString()) .ToArray(); // Boolean, true when sub directory? ar.ReadBoolean(); // Sub directory names seem to be in reverse order of serialization... var subDirCount = ar.ReadInt32(); var subDirNames = Enumerable.Range(0, subDirCount) .Select(x => ar.ReadString()) .ToArray(); // Read subdirectories foreach (var _ in subDirNames.Reverse()) { var subDir = new MiloObjectDir(); ReadFromStream(ar, subDir); dirEntry.SubDirectories.Add(subDir); } dir.Extras.Add("DirectoryEntry", dirEntry); ar.BaseStream.Position += 17; // 0'd data + ADDE } else if (version == 25 && (dirType == "PanelDir" || dirType == "VocalTrackDir" || dirType == "UILabelDir" || dirType == "UILabelDir" || dirType == "UIListDir" || dirType == "PitchArrowDir" || dirType == "Character")) { // Read past unknown stuff, big hack int unk1 = ar.ReadInt32(); int unk2 = ar.ReadInt32(); // Hack for project 9 var dirEntry = new MiloObjectDirEntry() { Name = dirName }; dirEntry.Version = ar.ReadInt32(); dirEntry.SubVersion = ar.ReadInt32(); dirEntry.ProjectName = ar.ReadString(); // Skip matrices + constants var matCount = ar.ReadInt32(); // Usually 7 ar.BaseStream.Position += (matCount * 48) + 9; // Read imported milos var importedMiloCount = ar.ReadInt32(); dirEntry.ImportedMiloPaths = Enumerable.Range(0, importedMiloCount) .Select(x => ar.ReadString()) .ToArray(); // Boolean, true when sub directory? ar.ReadBoolean(); // Sub directory names seem to be in reverse order of serialization... var subDirCount = ar.ReadInt32(); var subDirNames = Enumerable.Range(0, subDirCount) .Select(x => ar.ReadString()) .ToArray(); // Read subdirectories foreach (var _ in subDirNames.Reverse()) { var subDir = new MiloObjectDir(); ReadFromStream(ar, subDir); dirEntry.SubDirectories.Add(subDir); } dir.Extras.Add("DirectoryEntry", dirEntry); ar.BaseStream.Position += 17; // 0'd data + ADDE } else if (version == 25 && (dirType == "BackgroundDir" || dirType == "WorldInstance")) { // Read past unknown stuff, big hack int unk1 = ar.ReadInt32(); int unk2 = ar.ReadInt32(); int unk3 = ar.ReadInt32(); // Hack for project 9 var dirEntry = new MiloObjectDirEntry() { Name = dirName }; dirEntry.Version = ar.ReadInt32(); dirEntry.SubVersion = ar.ReadInt32(); dirEntry.ProjectName = ar.ReadString(); // Skip matrices + constants var matCount = ar.ReadInt32(); // Usually 7 ar.BaseStream.Position += (matCount * 48) + 9; // Read imported milos var importedMiloCount = ar.ReadInt32(); dirEntry.ImportedMiloPaths = Enumerable.Range(0, importedMiloCount) .Select(x => ar.ReadString()) .ToArray(); // Boolean, true when sub directory? ar.ReadBoolean(); // Sub directory names seem to be in reverse order of serialization... var subDirCount = ar.ReadInt32(); var subDirNames = Enumerable.Range(0, subDirCount) .Select(x => ar.ReadString()) .ToArray(); // Read subdirectories foreach (var _ in subDirNames.Reverse()) { var subDir = new MiloObjectDir(); ReadFromStream(ar, subDir); dirEntry.SubDirectories.Add(subDir); } dir.Extras.Add("DirectoryEntry", dirEntry); ar.BaseStream.Position += 17; // 0'd data + ADDE } else if (version == 25 && (dirType == "TrackPanelDir" || dirType == "H2HTrackPanelDir")) { // Read past unknown stuff, big hack int unk1 = ar.ReadInt32(); int unk2 = ar.ReadInt32(); int unk3 = ar.ReadInt32(); int unk4 = ar.ReadInt32(); // Hack for project 9 var dirEntry = new MiloObjectDirEntry() { Name = dirName }; dirEntry.Version = ar.ReadInt32(); dirEntry.SubVersion = ar.ReadInt32(); dirEntry.ProjectName = ar.ReadString(); // Skip matrices + constants var matCount = ar.ReadInt32(); // Usually 7 ar.BaseStream.Position += (matCount * 48) + 9; // Read imported milos var importedMiloCount = ar.ReadInt32(); dirEntry.ImportedMiloPaths = Enumerable.Range(0, importedMiloCount) .Select(x => ar.ReadString()) .ToArray(); // Boolean, true when sub directory? ar.ReadBoolean(); // Sub directory names seem to be in reverse order of serialization... var subDirCount = ar.ReadInt32(); var subDirNames = Enumerable.Range(0, subDirCount) .Select(x => ar.ReadString()) .ToArray(); // Read subdirectories foreach (var _ in subDirNames.Reverse()) { var subDir = new MiloObjectDir(); ReadFromStream(ar, subDir); dirEntry.SubDirectories.Add(subDir); } dir.Extras.Add("DirectoryEntry", dirEntry); ar.BaseStream.Position += 17; // 0'd data + ADDE } else if (version >= 24) { // GH2 and above // Reads data as a byte array var entrySize = GuessEntrySize(ar); var entryBytes = new MiloObjectBytes(dirType) { Name = dirName }; entryBytes.Data = ar.ReadBytes((int)entrySize); dir.Extras.Add("DirectoryEntry", entryBytes); ar.BaseStream.Position += 4; } foreach (var entry in entries) { var entryOffset = ar.BaseStream.Position; // TODO: De-serialize entries //try //{ // var miloEntry = ReadFromStream(ar.BaseStream, entry.Type); // miloEntry.Name = entry.Name; // dir.Entries.Add(miloEntry); // ar.BaseStream.Position += 4; // Skips padding // continue; //} //catch (Exception ex) //{ // // Catch exception and log? // ar.Basestream.Position = entryOffset; // Return to start //} // Reads data as a byte array var entrySize = GuessEntrySize(ar); var entryBytes = new MiloObjectBytes(entry.Type) { Name = entry.Name }; entryBytes.Data = ar.ReadBytes((int)entrySize); dir.Entries.Add(entryBytes); ar.BaseStream.Position += 4; } }