public override void WriteToStream(AwesomeWriter aw, ISerializable data)
        {
            var env = data as Environ;

            // TODO: Add version check
            var version = Magic();

            aw.Write(version);

            MiloSerializer.WriteToStream(aw.BaseStream, env.Draw);

            // Write lights
            aw.Write((int)env.Lights.Count);
            env.Lights.ForEach(x => aw.Write((string)x));

            // Write ambient color
            aw.Write((float)env.AmbientColor.R);
            aw.Write((float)env.AmbientColor.G);
            aw.Write((float)env.AmbientColor.B);
            aw.Write((float)env.AmbientColor.A);

            // Write fog info
            aw.Write((float)env.FogStart);
            aw.Write((float)env.FogEnd);

            aw.Write((float)env.FogColor.R);
            aw.Write((float)env.FogColor.G);
            aw.Write((float)env.FogColor.B);
            aw.Write((float)env.FogColor.A);

            aw.Write((bool)env.EnableFog);
        }
示例#2
0
        public override void WriteToStream(AwesomeWriter aw, ISerializable data)
        {
            var cam = data as Cam;

            // TODO: Add version check
            var version = Magic();

            aw.Write(version);

            MiloSerializer.WriteToStream(aw.BaseStream, cam.Trans);
            MiloSerializer.WriteToStream(aw.BaseStream, cam.Draw);

            aw.Write((float)cam.NearPlane);
            aw.Write((float)cam.FarPlane);
            aw.Write((float)cam.FOV);

            // Write screen area
            aw.Write((float)cam.ScreenArea.X);
            aw.Write((float)cam.ScreenArea.Y);
            aw.Write((float)cam.ScreenArea.Width);
            aw.Write((float)cam.ScreenArea.Height);

            // Write z-range
            aw.Write((float)cam.ZRange.X);
            aw.Write((float)cam.ZRange.Y);

            aw.Write((string)cam.TargetTexture);
        }
示例#3
0
 public static byte[] WriteToBytes(this MiloSerializer serializer, ISerializable obj)
 {
     using (var ms = new MemoryStream())
     {
         serializer.WriteToStream(ms, obj);
         return(ms.ToArray());
     }
 }
示例#4
0
        public override void WriteToStream(AwesomeWriter aw, ISerializable data)
        {
            var view = data as View;

            // TODO: Add version check
            var version = Magic();

            aw.Write(version);

            MiloSerializer.WriteToStream(aw.BaseStream, view.Anim);
            MiloSerializer.WriteToStream(aw.BaseStream, view.Trans);
            MiloSerializer.WriteToStream(aw.BaseStream, view.Draw);

            aw.Write((string)view.MainView);
            aw.Write((float)view.LODHeight);
            aw.Write((float)view.LODWidth);
        }
示例#5
0
        public override void WriteToStream(AwesomeWriter aw, ISerializable data)
        {
            var tex = data as Tex;

            // TODO: Add version check
            var version = Magic();

            aw.Write((int)version);

            if (MiloSerializer.Info.Version >= 25)
            {
                aw.Write((int)1); // Definitely needed!
            }
            if (version >= 10)
            {
                aw.Write(new byte[9]);
            }

            aw.Write((int)tex.Width);
            aw.Write((int)tex.Height);
            aw.Write((int)tex.Bpp);

            aw.Write(tex.ExternalPath);
            aw.Write((float)tex.IndexF);
            aw.Write((int)tex.Index);

            aw.Write((bool)tex.UseExternal);
            if (tex.Bitmap != null)
            {
                MiloSerializer.WriteToStream(aw.BaseStream, tex.Bitmap);
            }

            /*
             * if (!tex.UseExternal && tex.Bitmap != null)
             * {
             *  aw.Write(false);
             *  MiloSerializer.WriteToStream(aw.BaseStream, tex.Bitmap);
             * }
             * else
             * {
             *  aw.Write(true);
             * }*/
        }
示例#6
0
        public override void WriteToStream(AwesomeWriter aw, ISerializable data)
        {
            var mesh = data as Mesh;

            // TODO: Add version check
            var version = Magic();

            aw.Write(version);

            MiloSerializer.WriteToStream(aw.BaseStream, mesh.Trans);
            MiloSerializer.WriteToStream(aw.BaseStream, mesh.Draw);

            aw.Write((string)mesh.Material);
            aw.Write((string)mesh.MainMesh);
            aw.Write((int)mesh.Unknown);
            aw.Write((int)1);
            aw.Write((byte)0);

            // Write vertices
            aw.Write((int)mesh.Vertices.Count);
            mesh.Vertices.ForEach(x =>
            {
                // TODO: Add switch statement for milo versions
                aw.Write((float)x.X);
                aw.Write((float)x.Y);
                aw.Write((float)x.Z);
                aw.Write((float)x.NormalX);
                aw.Write((float)x.NormalY);
                aw.Write((float)x.NormalZ);
                aw.Write((float)x.ColorR);
                aw.Write((float)x.ColorG);
                aw.Write((float)x.ColorB);
                aw.Write((float)x.ColorA);
                aw.Write((float)x.U);
                aw.Write((float)x.V);
            });

            // Write faces
            aw.Write((int)mesh.Faces.Count);
            mesh.Faces.ForEach(x =>
            {
                aw.Write((ushort)x.V1);
                aw.Write((ushort)x.V2);
                aw.Write((ushort)x.V3);
            });

            // Write group sizes
            aw.Write((int)mesh.Groups.Count);
            mesh.Groups.ForEach(x => aw.Write((byte)x.Size));

            const int boneCount = 4; // Always 4?
            var       bones     = mesh.Bones
                                  .Take(boneCount)
                                  .ToList();

            // Write bones
            if (bones.Count > 0)
            {
                bones.ForEach(x => aw.Write((string)x.Name));
                RepeatFor(boneCount - bones.Count, () => aw.Write((string)""));

                bones.ForEach(x => WriteMatrix(x.Mat, aw));
                RepeatFor(boneCount - bones.Count, () => WriteMatrix(Matrix4.Identity(), aw));
            }
            else
            {
                aw.Write((int)0);
            }

            if (mesh.Groups.Sum(x => x.Sections.Count) == 0 &&
                mesh.Groups.Sum(x => x.VertexIndicies.Count) == 0)
            {
                return;
            }

            // Write group sections + vertex indices
            mesh.Groups.ForEach(x =>
            {
                aw.Write((int)x.Sections.Count);
                aw.Write((int)x.VertexIndicies.Count);

                x.Sections.ForEach(y => aw.Write((int)y));
                x.VertexIndicies.ForEach(y => aw.Write((ushort)y));
            });
        }
        public override void WriteToStream(AwesomeWriter aw, ISerializable data)
        {
            var dir = data as MiloObjectDir;

            aw.Write((int)Magic());

            // Sort entries using sort order defined in games
            var sortedEntries = dir.Entries
                                .OrderBy(x => GetEntryTypeSortValue(x.Type))
                                .ToList();

            if (Magic() >= 24)
            {
                // Write extra info
                var dirEntry = dir.Extras["DirectoryEntry"] as MiloObject;
                aw.Write((string)dirEntry.Type);
                aw.Write((string)dirEntry.Name);

                // Calculate hash + blob sizes
                var hashCount = (sortedEntries.Count + 1) * 2;
                var blobSize  = sortedEntries.Select(x => x.Name.Length + 1).Sum() + (dirEntry.Name.Length + 1);

                aw.Write((int)hashCount);
                aw.Write((int)blobSize);
            }

            // Write entries
            aw.Write((int)sortedEntries.Count);
            foreach (var entry in sortedEntries)
            {
                // Used to preserve file name
                var dirtyName = UnsanitizeFileName(entry.Name);

                aw.Write((string)entry.Type);
                aw.Write((string)dirtyName);
            }

            if (Magic() >= 24)
            {
                var dirEntryRaw = dir.Extras["DirectoryEntry"] as ISerializable;

                if (Magic() == 25 &&
                    dir.Type == "ObjectDir" &&
                    dirEntryRaw is MiloObjectDirEntry dirEntry)
                {
                    // Hack for project 9
                    aw.Write((int)dirEntry.Version);
                    aw.Write((int)dirEntry.SubVersion);
                    aw.Write((string)dirEntry.ProjectName);

                    // Write matrices
                    aw.Write((int)7);
                    foreach (var mat in Enumerable
                             .Range(0, 7)
                             .Select(x => Matrix4.Identity()))
                    {
                        aw.Write((float)mat.M11);
                        aw.Write((float)mat.M12);
                        aw.Write((float)mat.M13);

                        aw.Write((float)mat.M21);
                        aw.Write((float)mat.M22);
                        aw.Write((float)mat.M23);

                        aw.Write((float)mat.M31);
                        aw.Write((float)mat.M32);
                        aw.Write((float)mat.M33);

                        aw.Write((float)mat.M41);
                        aw.Write((float)mat.M42);
                        aw.Write((float)mat.M43);
                    }

                    // Constants? I hope
                    aw.Write((int)0);
                    aw.Write((bool)true);
                    aw.Write((int)0);

                    // Write imported milo paths
                    if (!(dirEntry.ImportedMiloPaths is null))
                    {
                        aw.Write((int)dirEntry.ImportedMiloPaths.Length);

                        foreach (var path in dirEntry.ImportedMiloPaths)
                        {
                            aw.Write((string)path);
                        }
                    }
                    else
                    {
                        aw.Write((int)0);
                    }

                    // Might be different depending on dir being root/nested
                    // Root: false, Nested: true
                    aw.Write((bool)(dirEntry.SubDirectories.Count <= 0)); // TODO: Use a better way to determine if nested

                    // Write sub directory names
                    aw.Write((int)dirEntry.SubDirectories.Count);
                    foreach (var subName in dirEntry
                             .SubDirectories
                             .Select(x => $"{x.Name}.milo")
                             .Reverse()) // Seems to be reverse order of serialization
                    {
                        aw.Write((string)subName);
                    }

                    // Write sub directory data
                    foreach (var subDir in dirEntry.SubDirectories)
                    {
                        WriteToStream(aw, subDir);
                    }

                    aw.BaseStream.Position += 13; // Zero'd bytes
                }
                else
                {
                    MiloSerializer.WriteToStream(aw.BaseStream, dirEntryRaw);
                }

                aw.Write(ADDE_PADDING);
            }
示例#8
0
        public IActionResult TestSerialization([FromBody] ScanRequest request, bool testSerialize)
        {
            if (!Directory.Exists(request.InputPath))
            {
                return(BadRequest($"Directory \"{request.InputPath}\" does not exist!"));
            }

            var miloEntryRegex = new Regex(@"([^\\]*([.](rnd)|(gh)))\\([^\\]+)\\([^\\]+)$", RegexOptions.IgnoreCase);
            var miloEntries    = Directory.GetFiles(request.InputPath, "*", SearchOption.AllDirectories)
                                 .Where(x => miloEntryRegex.IsMatch(x))
                                 .Select(y =>
            {
                var match = miloEntryRegex.Match(y);

                var miloArchive   = match.Groups[1].Value;
                var miloEntryType = match.Groups[5].Value;
                var miloEntryName = match.Groups[6].Value;

                return(new
                {
                    FullPath = y,
                    MiloArchive = miloArchive,
                    MiloEntryType = miloEntryType,
                    MiloEntryName = miloEntryName
                });
            })
                                 .ToArray();

            //var groupedEntries = miloEntries.GroupBy(x => x.MiloEntryType).ToDictionary(g => g.Key, g => g.ToList());
            MiloSerializer serializer = new MiloSerializer(new SystemInfo()
            {
                Version = 10, Platform = Platform.PS2, BigEndian = false
            });
            var supportedTypes = new [] { "Cam", "Environ", "Mat", "Mesh", "Tex", "View" };

            var results = miloEntries
                          .Where(w => supportedTypes.Contains(w.MiloEntryType))
                          .OrderBy(x => x.MiloEntryType)
                          .ThenBy(y => y.FullPath)
                          .Select(z =>
            {
                ISerializable data    = null;
                string message        = "";
                bool converted        = false;
                bool perfectSerialize = true;

                try
                {
                    switch (z.MiloEntryType)
                    {
                    case "Cam":
                        data = serializer.ReadFromFile <Cam>(z.FullPath);
                        break;

                    case "Environ":
                        data = serializer.ReadFromFile <Environ>(z.FullPath);
                        break;

                    case "Mat":
                        data = serializer.ReadFromFile <Mat>(z.FullPath);
                        break;

                    case "Mesh":
                        data = serializer.ReadFromFile <Mesh>(z.FullPath);
                        break;

                    case "Tex":
                        data = serializer.ReadFromFile <Tex>(z.FullPath);
                        break;

                    case "View":
                        data = serializer.ReadFromFile <View>(z.FullPath);
                        break;

                    default:
                        throw new Exception("Not Supported");
                    }

                    (data as IMiloObject).Name = z.MiloEntryName;
                    converted = true;
                }
                catch (Exception ex)
                {
                    var trace = new StackTrace(ex, true);
                    var frame = trace.GetFrame(0);
                    var name  = frame.GetMethod().ReflectedType.Name;

                    message = $"{name}: {ex.Message}";
                }

                if (testSerialize)
                {
                    try
                    {
                        byte[] bytes;

                        using (var ms = new MemoryStream())
                        {
                            serializer.WriteToStream(ms, data);
                            bytes = ms.ToArray();
                        }

                        var origBytes = System.IO.File.ReadAllBytes(z.FullPath);

                        if (bytes.Length != origBytes.Length)
                        {
                            throw new Exception("Byte count doesn't match");
                        }

                        for (int i = 0; i < bytes.Length; i++)
                        {
                            if (bytes[i] != origBytes[i])
                            {
                                throw new Exception("Bytes don't match");
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        perfectSerialize = false;
                    }
                }

                return(new { Entry = z, Data = data, Message = message, Converted = converted, Serialized = perfectSerialize });
            }).ToList();

            /*
             * var textures = groupedEntries["Tex"]
             *  .Select(x => serializer.ReadFromFile<Tex>(x.FullPath))
             *  .ToList();
             *
             * var views = groupedEntries["View"]
             *  .Select(x => serializer.ReadFromFile<View>(x.FullPath))
             *  .ToList();
             *
             * var meshes = groupedEntries["Mesh"]
             *  .Select(x => serializer.ReadFromFile<Mesh>(x.FullPath))
             *  .ToList();
             */

            return(Ok(new
            {
                TotalCoverage = results.Count(x => x.Converted) / (double)results.Count,
                TotalScanned = results.Count,
                ByType = results
                         .GroupBy(x => x.Entry.MiloEntryType)
                         .ToDictionary(g => g.Key, g => new
                {
                    Coverage = g.Count(x => x.Converted) / (double)g.Count(),
                    Scanned = g.Count(),
                    //Converted = g
                    //    .Where(x => x.Converted)
                    //    .Select(x => new
                    //    {
                    //        x.Entry.FullPath
                    //    }),
                    NotConverted = g
                                   .Where(x => !x.Converted)
                                   .Select(x => new
                    {
                        x.Entry.FullPath,
                        x.Message
                    })
                }),
                NotSerialized = results
                                .Where(x => !x.Serialized)
                                .Select(y => y.Entry.FullPath)
                                //Converted = results
                                //    .Where(x => x.Converted)
                                //    .Select(x => new
                                //    {
                                //        x.Entry.FullPath
                                //    }),
                                //NotConverted = results
                                //    .Where(x => !x.Converted)
                                //    .Select(x => new
                                //    {
                                //        x.Entry.FullPath,
                                //        x.Message
                                //    })
            }));
        }
        public override void WriteToStream(AwesomeWriter aw, ISerializable data)
        {
            var dir = data as MiloObjectDir;

            aw.Write((int)Magic());

            if (Magic() >= 24)
            {
                // Write extra info
                var dirEntry = dir.Extras["DirectoryEntry"] as MiloObject;
                aw.Write((string)dirEntry.Type);
                aw.Write((string)dirEntry.Name);

                /*
                 * var entryNameLengths = dir.Entries.Select(x => ((string)x.Name).Length).Sum();
                 * aw.Write(0); // Unknown
                 * aw.Write(1 + ((string)dirEntry.Name).Length + dir.Entries.Count + entryNameLengths);
                 */

                if (dir.Extras.TryGetValue("Num1", out var num1))
                {
                    aw.Write((int)num1);
                }
                if (dir.Extras.TryGetValue("Num2", out var num2))
                {
                    aw.Write((int)num2);
                }

                aw.Write((int)dir.Entries.Count);
            }

            foreach (var entry in dir.Entries)
            {
                aw.Write((string)entry.Type);
                aw.Write((string)entry.Name);
            }

            if (Magic() >= 24)
            {
                var dirEntryRaw = dir.Extras["DirectoryEntry"] as ISerializable;

                if (Magic() == 25 &&
                    dir.Type == "ObjectDir" &&
                    dirEntryRaw is MiloObjectDirEntry dirEntry)
                {
                    // Hack for project 9
                    aw.Write((int)dirEntry.Version);
                    aw.Write((int)dirEntry.SubVersion);
                    aw.Write((string)dirEntry.ProjectName);

                    // Write matrices
                    aw.Write((int)7);
                    foreach (var mat in Enumerable
                             .Range(0, 7)
                             .Select(x => Matrix4.Identity()))
                    {
                        aw.Write((float)mat.M11);
                        aw.Write((float)mat.M12);
                        aw.Write((float)mat.M13);

                        aw.Write((float)mat.M21);
                        aw.Write((float)mat.M22);
                        aw.Write((float)mat.M23);

                        aw.Write((float)mat.M31);
                        aw.Write((float)mat.M32);
                        aw.Write((float)mat.M33);

                        aw.Write((float)mat.M41);
                        aw.Write((float)mat.M42);
                        aw.Write((float)mat.M43);
                    }

                    // Constants? I hope
                    aw.Write((int)0);
                    aw.Write((bool)true);
                    aw.Write((int)0);

                    // Write imported milo paths
                    if (!(dirEntry.ImportedMiloPaths is null))
                    {
                        aw.Write((int)dirEntry.ImportedMiloPaths.Length);

                        foreach (var path in dirEntry.ImportedMiloPaths)
                        {
                            aw.Write((string)path);
                        }
                    }
                    else
                    {
                        aw.Write((int)0);
                    }

                    // Might be different depending on dir being root/nested
                    // Root: false, Nested: true
                    aw.Write((bool)(dirEntry.SubDirectories.Count <= 0)); // TODO: Use a better way to determine if nested

                    // Write sub directory names
                    aw.Write((int)dirEntry.SubDirectories.Count);
                    foreach (var subName in dirEntry
                             .SubDirectories
                             .Select(x => $"{x.Name}.milo")
                             .Reverse()) // Seems to be reverse order of serialization
                    {
                        aw.Write((string)subName);
                    }

                    // Write sub directory data
                    foreach (var subDir in dirEntry.SubDirectories)
                    {
                        WriteToStream(aw, subDir);
                    }

                    aw.BaseStream.Position += 13; // Zero'd bytes
                }
                else
                {
                    MiloSerializer.WriteToStream(aw.BaseStream, dirEntryRaw);
                }

                aw.Write(ADDE_PADDING);
            }