Example #1
0
        public static int SplitDLLFile(string datafilename, string inifilename, string projectFolderName)
        {
            try
            {
                byte[]  datafile  = File.ReadAllBytes(datafilename);
                IniData inifile   = IniSerializer.Deserialize <IniData>(inifilename);
                uint    imageBase = HelperFunctions.SetupEXE(ref datafile).Value;
                Dictionary <string, int> exports;
                {
                    int      ptr               = BitConverter.ToInt32(datafile, BitConverter.ToInt32(datafile, 0x3c) + 4 + 20 + 96);
                    GCHandle handle            = GCHandle.Alloc(datafile, GCHandleType.Pinned);
                    IMAGE_EXPORT_DIRECTORY dir = (IMAGE_EXPORT_DIRECTORY)Marshal.PtrToStructure(
                        Marshal.UnsafeAddrOfPinnedArrayElement(datafile, ptr), typeof(IMAGE_EXPORT_DIRECTORY));
                    handle.Free();
                    exports = new Dictionary <string, int>(dir.NumberOfFunctions);
                    int nameaddr = dir.AddressOfNames;
                    int ordaddr  = dir.AddressOfNameOrdinals;
                    for (int i = 0; i < dir.NumberOfNames; i++)
                    {
                        string name = datafile.GetCString(BitConverter.ToInt32(datafile, nameaddr),
                                                          System.Text.Encoding.ASCII);
                        int addr = BitConverter.ToInt32(datafile,
                                                        dir.AddressOfFunctions + (BitConverter.ToInt16(datafile, ordaddr) * 4));
                        exports.Add(name, addr);
                        nameaddr += 4;
                        ordaddr  += 2;
                    }
                }
                ModelFormat     modelfmt = 0;
                LandTableFormat landfmt  = 0;
                string          modelext = null;
                string          landext  = null;
                switch (inifile.Game)
                {
                case Game.SADX:
                    modelfmt = ModelFormat.BasicDX;
                    landfmt  = LandTableFormat.SADX;
                    modelext = ".sa1mdl";
                    landext  = ".sa1lvl";
                    break;

                case Game.SA2B:
                    modelfmt = ModelFormat.Chunk;
                    landfmt  = LandTableFormat.SA2;
                    modelext = ".sa2mdl";
                    landext  = ".sa2lvl";
                    break;
                }
                int                       itemcount = 0;
                List <string>             labels    = new List <string>();
                ModelAnimationsDictionary models    = new ModelAnimationsDictionary();
                DllIniData                output    = new DllIniData()
                {
                    Name = inifile.ModuleName,
                    Game = inifile.Game
                };
                Stopwatch timer = new Stopwatch();
                timer.Start();
                foreach (KeyValuePair <string, FileInfo> item in inifile.Files)
                {
                    if (string.IsNullOrEmpty(item.Key))
                    {
                        continue;
                    }
                    FileInfo data = item.Value;
                    string   type = data.Type;
                    string   name = item.Key;
                    output.Exports[name] = type;
                    int address = exports[name];

                    string fileOutputPath = "";
                    if (data.Filename != null)
                    {
                        fileOutputPath = string.Concat(projectFolderName, data.Filename);

                        Console.WriteLine(name + " -> " + fileOutputPath);
                        Directory.CreateDirectory(Path.GetDirectoryName(fileOutputPath));
                    }
                    else
                    {
                        Console.WriteLine(name);
                    }
                    switch (type)
                    {
                    case "landtable":
                    {
                        LandTable land = new LandTable(datafile, address, imageBase, landfmt)
                        {
                            Description = name
                        };
                        DllItemInfo info = new DllItemInfo()
                        {
                            Export = name,
                            Label  = land.Name
                        };
                        output.Items.Add(info);
                        if (!labels.Contains(land.Name))
                        {
                            land.SaveToFile(fileOutputPath, landfmt);
                            output.Files[data.Filename] = new FileTypeHash("landtable", HelperFunctions.FileHash(fileOutputPath));
                            labels.AddRange(land.GetLabels());
                        }
                    }
                    break;

                    case "landtablearray":
                        for (int i = 0; i < data.Length; i++)
                        {
                            int ptr = BitConverter.ToInt32(datafile, address);
                            if (ptr != 0)
                            {
                                ptr = (int)(ptr - imageBase);
                                string    idx  = name + "[" + i.ToString(NumberFormatInfo.InvariantInfo) + "]";
                                LandTable land = new LandTable(datafile, ptr, imageBase, landfmt)
                                {
                                    Description = idx
                                };
                                DllItemInfo info = new DllItemInfo()
                                {
                                    Export = name,
                                    Index  = i,
                                    Label  = land.Name
                                };
                                output.Items.Add(info);
                                if (!labels.Contains(land.Name))
                                {
                                    string outputFN = Path.Combine(fileOutputPath, i.ToString(NumberFormatInfo.InvariantInfo) + landext);
                                    string fileName = Path.Combine(data.Filename, i.ToString(NumberFormatInfo.InvariantInfo) + landext);

                                    land.SaveToFile(outputFN, landfmt);
                                    output.Files[fileName] = new FileTypeHash("landtable", HelperFunctions.FileHash(outputFN));
                                    labels.AddRange(land.GetLabels());
                                }
                            }
                            address += 4;
                        }
                        break;

                    case "model":
                    {
                        NJS_OBJECT  mdl  = new NJS_OBJECT(datafile, address, imageBase, modelfmt);
                        DllItemInfo info = new DllItemInfo()
                        {
                            Export = name,
                            Label  = mdl.Name
                        };
                        output.Items.Add(info);
                        if (!labels.Contains(mdl.Name))
                        {
                            models.Add(new ModelAnimations(data.Filename, name, mdl, modelfmt));
                            labels.AddRange(mdl.GetLabels());
                        }
                    }
                    break;

                    case "morph":
                    {
                        BasicAttach dummy = new BasicAttach(datafile, address, imageBase, modelfmt == ModelFormat.BasicDX);
                        NJS_OBJECT  mdl   = new NJS_OBJECT()
                        {
                            Attach = dummy
                        };
                        DllItemInfo info = new DllItemInfo()
                        {
                            Export = name,
                            Label  = dummy.Name
                        };
                        output.Items.Add(info);
                        if (!labels.Contains(dummy.Name))
                        {
                            models.Add(new ModelAnimations(data.Filename, name, mdl, modelfmt));
                            labels.AddRange(mdl.GetLabels());
                        }
                    }
                    break;

                    case "modelarray":
                        for (int i = 0; i < data.Length; i++)
                        {
                            int ptr = BitConverter.ToInt32(datafile, address);
                            if (ptr != 0)
                            {
                                ptr = (int)(ptr - imageBase);
                                NJS_OBJECT  mdl  = new NJS_OBJECT(datafile, ptr, imageBase, modelfmt);
                                string      idx  = name + "[" + i.ToString(NumberFormatInfo.InvariantInfo) + "]";
                                DllItemInfo info = new DllItemInfo()
                                {
                                    Export = name,
                                    Index  = i,
                                    Label  = mdl.Name
                                };
                                output.Items.Add(info);
                                if (!labels.Contains(mdl.Name))
                                {
                                    string fn = Path.Combine(data.Filename, i.ToString(NumberFormatInfo.InvariantInfo) + modelext);
                                    models.Add(new ModelAnimations(fn, idx, mdl, modelfmt));
                                    labels.AddRange(mdl.GetLabels());
                                }
                            }
                            address += 4;
                        }
                        break;

                    case "modelsarray":
                        for (int i = 0; i < data.Length; i++)
                        {
                            int ptr = BitConverter.ToInt32(datafile, address);
                            if (ptr != 0)
                            {
                                ptr = (int)(ptr - imageBase);
                                BasicAttach dummy = new BasicAttach(datafile, ptr, imageBase, modelfmt == ModelFormat.BasicDX);
                                NJS_OBJECT  mdl   = new NJS_OBJECT()
                                {
                                    Attach = dummy
                                };
                                string      idx  = name + "[" + i.ToString(NumberFormatInfo.InvariantInfo) + "]";
                                DllItemInfo info = new DllItemInfo()
                                {
                                    Export = name,
                                    Index  = i,
                                    Label  = dummy.Name
                                };
                                output.Items.Add(info);
                                if (!labels.Contains(dummy.Name))
                                {
                                    string fn = Path.Combine(data.Filename, i.ToString(NumberFormatInfo.InvariantInfo) + modelext);
                                    models.Add(new ModelAnimations(fn, idx, mdl, ModelFormat.BasicDX));
                                    labels.AddRange(mdl.GetLabels());
                                }
                            }
                            address += 4;
                        }
                        break;

                    case "basicmodel":
                    {
                        NJS_OBJECT  mdl  = new NJS_OBJECT(datafile, address, imageBase, ModelFormat.Basic);
                        DllItemInfo info = new DllItemInfo()
                        {
                            Export = name,
                            Label  = mdl.Name
                        };
                        output.Items.Add(info);
                        if (!labels.Contains(mdl.Name))
                        {
                            models.Add(new ModelAnimations(data.Filename, name, mdl, ModelFormat.Basic));
                            labels.AddRange(mdl.GetLabels());
                        }
                    }
                    break;

                    case "basicmodelarray":
                        for (int i = 0; i < data.Length; i++)
                        {
                            int ptr = BitConverter.ToInt32(datafile, address);
                            if (ptr != 0)
                            {
                                ptr = (int)(ptr - imageBase);
                                NJS_OBJECT  mdl  = new NJS_OBJECT(datafile, ptr, imageBase, ModelFormat.Basic);
                                string      idx  = name + "[" + i.ToString(NumberFormatInfo.InvariantInfo) + "]";
                                DllItemInfo info = new DllItemInfo()
                                {
                                    Export = name,
                                    Index  = i,
                                    Label  = mdl.Name
                                };
                                output.Items.Add(info);
                                if (!labels.Contains(mdl.Name))
                                {
                                    string fn = Path.Combine(data.Filename, i.ToString(NumberFormatInfo.InvariantInfo) + ".sa1mdl");
                                    models.Add(new ModelAnimations(fn, idx, mdl, ModelFormat.Basic));
                                    labels.AddRange(mdl.GetLabels());
                                }
                            }
                            address += 4;
                        }
                        break;

                    case "basicdxmodel":
                    {
                        NJS_OBJECT  mdl  = new NJS_OBJECT(datafile, address, imageBase, ModelFormat.BasicDX);
                        DllItemInfo info = new DllItemInfo()
                        {
                            Export = name,
                            Label  = mdl.Name
                        };
                        output.Items.Add(info);
                        if (!labels.Contains(mdl.Name))
                        {
                            models.Add(new ModelAnimations(data.Filename, name, mdl, ModelFormat.BasicDX));
                            labels.AddRange(mdl.GetLabels());
                        }
                    }
                    break;

                    case "basicdxmodelarray":
                        for (int i = 0; i < data.Length; i++)
                        {
                            int ptr = BitConverter.ToInt32(datafile, address);
                            if (ptr != 0)
                            {
                                ptr = (int)(ptr - imageBase);
                                NJS_OBJECT  mdl  = new NJS_OBJECT(datafile, ptr, imageBase, ModelFormat.BasicDX);
                                string      idx  = name + "[" + i.ToString(NumberFormatInfo.InvariantInfo) + "]";
                                DllItemInfo info = new DllItemInfo()
                                {
                                    Export = name,
                                    Index  = i,
                                    Label  = mdl.Name
                                };
                                output.Items.Add(info);
                                if (!labels.Contains(mdl.Name))
                                {
                                    string fn = Path.Combine(data.Filename, i.ToString(NumberFormatInfo.InvariantInfo) + ".sa1mdl");
                                    models.Add(new ModelAnimations(fn, idx, mdl, ModelFormat.BasicDX));
                                    labels.AddRange(mdl.GetLabels());
                                }
                            }
                            address += 4;
                        }
                        break;

                    case "chunkmodel":
                    {
                        NJS_OBJECT  mdl  = new NJS_OBJECT(datafile, address, imageBase, ModelFormat.Chunk);
                        DllItemInfo info = new DllItemInfo()
                        {
                            Export = name,
                            Label  = mdl.Name
                        };
                        output.Items.Add(info);
                        if (!labels.Contains(mdl.Name))
                        {
                            models.Add(new ModelAnimations(data.Filename, name, mdl, ModelFormat.Chunk));
                            labels.AddRange(mdl.GetLabels());
                        }
                    }
                    break;

                    case "chunkmodelarray":
                        for (int i = 0; i < data.Length; i++)
                        {
                            int ptr = BitConverter.ToInt32(datafile, address);
                            if (ptr != 0)
                            {
                                ptr = (int)(ptr - imageBase);
                                NJS_OBJECT  mdl  = new NJS_OBJECT(datafile, ptr, imageBase, ModelFormat.Chunk);
                                string      idx  = name + "[" + i.ToString(NumberFormatInfo.InvariantInfo) + "]";
                                DllItemInfo info = new DllItemInfo()
                                {
                                    Export = name,
                                    Index  = i,
                                    Label  = mdl.Name
                                };
                                output.Items.Add(info);
                                if (!labels.Contains(mdl.Name))
                                {
                                    string fn = Path.Combine(data.Filename, i.ToString(NumberFormatInfo.InvariantInfo) + ".sa2mdl");
                                    models.Add(new ModelAnimations(fn, idx, mdl, ModelFormat.Chunk));
                                    labels.AddRange(mdl.GetLabels());
                                }
                            }
                            address += 4;
                        }
                        break;

                    case "actionarray":
                        for (int i = 0; i < data.Length; i++)
                        {
                            int ptr = BitConverter.ToInt32(datafile, address);
                            if (ptr != 0)
                            {
                                ptr = (int)(ptr - imageBase);
                                NJS_ACTION ani = new NJS_ACTION(datafile, ptr, imageBase, modelfmt);
                                string     idx = name + "[" + i.ToString(NumberFormatInfo.InvariantInfo) + "]";
                                ani.Animation.Name = item.Key + "_" + i;
                                DllItemInfo info = new DllItemInfo()
                                {
                                    Export = name,
                                    Index  = i,
                                    Label  = ani.Animation.Name,
                                    Field  = "motion"
                                };
                                output.Items.Add(info);
                                info = new DllItemInfo()
                                {
                                    Export = name,
                                    Index  = i,
                                    Label  = ani.Model.Name,
                                    Field  = "object"
                                };
                                output.Items.Add(info);
                                string outputFN = Path.Combine(fileOutputPath, i.ToString(NumberFormatInfo.InvariantInfo) + ".saanim");
                                string fn       = Path.Combine(data.Filename, i.ToString(NumberFormatInfo.InvariantInfo) + ".saanim");
                                ani.Animation.Save(outputFN);
                                output.Files[fn] = new FileTypeHash("animation", HelperFunctions.FileHash(outputFN));
                                if (models.Contains(ani.Model.Name))
                                {
                                    ModelAnimations           mdl = models[ani.Model.Name];
                                    System.Text.StringBuilder sb  = new System.Text.StringBuilder(260);
                                    PathRelativePathTo(sb, Path.GetFullPath(Path.Combine(projectFolderName, mdl.Filename)), 0, Path.GetFullPath(outputFN), 0);
                                    mdl.Animations.Add(sb.ToString());                                             // this is where the problem is
                                }
                                else
                                {
                                    string mfn           = Path.ChangeExtension(fn, modelext);
                                    string outputmfn     = Path.Combine(projectFolderName, mfn);
                                    string animationName = Path.GetFileName(outputFN);

                                    ModelFile.CreateFile(outputmfn, ani.Model, new[] { animationName }, null, null,
                                                         idx + "->object", null, modelfmt);
                                    output.Files[mfn] = new FileTypeHash("model", HelperFunctions.FileHash(outputmfn));
                                }
                            }
                            address += 4;
                        }
                        break;

                    case "texlist":
                        if (output.TexLists == null)
                        {
                            output.TexLists = new TexListContainer();
                        }
                        output.TexLists.Add((uint)(address + imageBase), new DllTexListInfo(name, null));
                        break;

                    case "texlistarray":
                        if (output.TexLists == null)
                        {
                            output.TexLists = new TexListContainer();
                        }
                        for (int i = 0; i < data.Length; i++)
                        {
                            uint ptr = BitConverter.ToUInt32(datafile, address);
                            if (ptr != 0 && !output.TexLists.ContainsKey(ptr))
                            {
                                output.TexLists.Add(ptr, new DllTexListInfo(name, i));
                            }
                            address += 4;
                        }
                        break;

                    case "animindexlist":
                    {
                        int c = 0;
                        int i = ByteConverter.ToInt16(datafile, address);
                        while (i != -1)
                        {
                            string outputFN = Path.Combine(fileOutputPath, i.ToString(NumberFormatInfo.InvariantInfo) + ".saanim");
                            string fileName = Path.Combine(data.Filename, i.ToString(NumberFormatInfo.InvariantInfo) + ".saanim");

                            NJS_MOTION  anim = new NJS_MOTION(datafile, datafile.GetPointer(address + 4, imageBase), imageBase, ByteConverter.ToInt16(datafile, address + 2));
                            DllItemInfo info = new DllItemInfo()
                            {
                                Export = name,
                                Index  = c,
                                Field  = "Animation",
                                Label  = anim.Name
                            };
                            anim.Save(outputFN);
                            output.Files[fileName] = new FileTypeHash("animindex", HelperFunctions.FileHash(outputFN));
                            address += 8;
                            i        = ByteConverter.ToInt16(datafile, address);
                            ++c;
                        }
                    }
                    break;
                    }
                    itemcount++;
                }
                foreach (ModelAnimations item in models)
                {
                    string modelOutputPath = string.Concat(projectFolderName, item.Filename);
                    //string modelOutputPath = item.Filename;

                    ModelFile.CreateFile(modelOutputPath, item.Model, item.Animations.ToArray(), null, null, item.Name, null,
                                         item.Format);
                    string type = "model";
                    switch (item.Format)
                    {
                    case ModelFormat.Basic:
                        type = "basicmodel";
                        break;

                    case ModelFormat.BasicDX:
                        type = "basicdxmodel";
                        break;

                    case ModelFormat.Chunk:
                        type = "chunkmodel";
                        break;
                    }
                    output.Files[item.Filename] = new FileTypeHash(type, HelperFunctions.FileHash(modelOutputPath));
                }
                IniSerializer.Serialize(output, Path.Combine(projectFolderName, Path.GetFileNameWithoutExtension(datafilename))
                                        + "_data.ini");
                timer.Stop();
                Console.WriteLine("Split " + itemcount + " items in " + timer.Elapsed.TotalSeconds + " seconds.");
                Console.WriteLine();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                Console.WriteLine(e.StackTrace);
                Console.WriteLine("Press any key to exit.");
                Console.ReadLine();
                return((int)ERRORVALUE.UnhandledException);
            }

            return((int)ERRORVALUE.Success);
        }
Example #2
0
        public static int SplitDLLFile(string datafilename, string inifilename, string projectFolderName)
        {
#if !DEBUG
            try
#endif
            {
                byte[]  datafile  = File.ReadAllBytes(datafilename);
                IniData inifile   = IniSerializer.Deserialize <IniData>(inifilename);
                uint    imageBase = HelperFunctions.SetupEXE(ref datafile).Value;
                Dictionary <string, int> exports;
                {
                    int      ptr               = BitConverter.ToInt32(datafile, BitConverter.ToInt32(datafile, 0x3c) + 4 + 20 + 96);
                    GCHandle handle            = GCHandle.Alloc(datafile, GCHandleType.Pinned);
                    IMAGE_EXPORT_DIRECTORY dir = (IMAGE_EXPORT_DIRECTORY)Marshal.PtrToStructure(
                        Marshal.UnsafeAddrOfPinnedArrayElement(datafile, ptr), typeof(IMAGE_EXPORT_DIRECTORY));
                    handle.Free();
                    exports = new Dictionary <string, int>(dir.NumberOfFunctions);
                    int nameaddr = dir.AddressOfNames;
                    int ordaddr  = dir.AddressOfNameOrdinals;
                    for (int i = 0; i < dir.NumberOfNames; i++)
                    {
                        string name = datafile.GetCString(BitConverter.ToInt32(datafile, nameaddr),
                                                          System.Text.Encoding.ASCII);
                        int addr = BitConverter.ToInt32(datafile,
                                                        dir.AddressOfFunctions + (BitConverter.ToInt16(datafile, ordaddr) * 4));
                        exports.Add(name, addr);
                        nameaddr += 4;
                        ordaddr  += 2;
                    }
                }
                ModelFormat     modelfmt = 0;
                LandTableFormat landfmt  = 0;
                string          modelext = null;
                string          landext  = null;
                switch (inifile.Game)
                {
                case Game.SADX:
                    modelfmt = ModelFormat.BasicDX;
                    landfmt  = LandTableFormat.SADX;
                    modelext = ".sa1mdl";
                    landext  = ".sa1lvl";
                    break;

                case Game.SA2B:
                    modelfmt = ModelFormat.Chunk;
                    landfmt  = LandTableFormat.SA2;
                    modelext = ".sa2mdl";
                    landext  = ".sa2lvl";
                    break;
                }
                int           itemcount = 0;
                List <string> labels    = new List <string>();
                Dictionary <string, string> anilabels = new Dictionary <string, string>();
                ModelAnimationsDictionary   models    = new ModelAnimationsDictionary();
                DllIniData output = new DllIniData()
                {
                    Name = inifile.ModuleName,
                    Game = inifile.Game
                };
                Stopwatch timer = new Stopwatch();
                timer.Start();
                foreach (KeyValuePair <string, FileInfo> item in inifile.Files)
                {
                    if (string.IsNullOrEmpty(item.Key))
                    {
                        continue;
                    }
                    FileInfo data = item.Value;
                    string   type = data.Type;
                    string   name = item.Key;
                    output.Exports[name] = type;
                    int address = exports[name];

                    string fileOutputPath = "";
                    if (data.Filename != null)
                    {
                        fileOutputPath = string.Concat(projectFolderName, data.Filename);

                        Console.WriteLine(name + " -> " + fileOutputPath);
                        Directory.CreateDirectory(Path.GetDirectoryName(fileOutputPath));
                    }
                    else
                    {
                        Console.WriteLine(name);
                    }
                    switch (type)
                    {
                    case "landtable":
                    {
                        LandTable land = new LandTable(datafile, address, imageBase, landfmt)
                        {
                            Description = name
                        };
                        DllItemInfo info = new DllItemInfo()
                        {
                            Export = name,
                            Label  = land.Name
                        };
                        output.Items.Add(info);
                        if (!labels.Contains(land.Name))
                        {
                            land.SaveToFile(fileOutputPath, landfmt);
                            output.Files[data.Filename] = new FileTypeHash("landtable", HelperFunctions.FileHash(fileOutputPath));
                            labels.AddRange(land.GetLabels());
                        }
                    }
                    break;

                    case "battlelandtable":
                    {
                        LandTable land = new LandTable(datafile, address, imageBase, LandTableFormat.SA2B)
                        {
                            Description = name
                        };
                        DllItemInfo info = new DllItemInfo()
                        {
                            Export = name,
                            Label  = land.Name
                        };
                        output.Items.Add(info);
                        if (!labels.Contains(land.Name))
                        {
                            land.SaveToFile(fileOutputPath, LandTableFormat.SA2B);
                            output.Files[data.Filename] = new FileTypeHash("landtable", HelperFunctions.FileHash(fileOutputPath));
                            labels.AddRange(land.GetLabels());
                        }
                    }
                    break;

                    case "landtablearray":
                        for (int i = 0; i < data.Length; i++)
                        {
                            int ptr = BitConverter.ToInt32(datafile, address);
                            if (ptr != 0)
                            {
                                ptr = (int)(ptr - imageBase);
                                string    idx  = name + "[" + i.ToString(NumberFormatInfo.InvariantInfo) + "]";
                                LandTable land = new LandTable(datafile, ptr, imageBase, landfmt)
                                {
                                    Description = idx
                                };
                                DllItemInfo info = new DllItemInfo()
                                {
                                    Export = name,
                                    Index  = i,
                                    Label  = land.Name
                                };
                                output.Items.Add(info);
                                if (!labels.Contains(land.Name))
                                {
                                    string outputFN = Path.Combine(fileOutputPath, i.ToString(NumberFormatInfo.InvariantInfo) + landext);
                                    string fileName = Path.Combine(data.Filename, i.ToString(NumberFormatInfo.InvariantInfo) + landext);

                                    land.SaveToFile(outputFN, landfmt);
                                    output.Files[fileName] = new FileTypeHash("landtable", HelperFunctions.FileHash(outputFN));
                                    labels.AddRange(land.GetLabels());
                                }
                            }
                            address += 4;
                        }
                        break;

                    case "model":
                    {
                        NJS_OBJECT  mdl  = new NJS_OBJECT(datafile, address, imageBase, modelfmt, new Dictionary <int, Attach>());
                        DllItemInfo info = new DllItemInfo()
                        {
                            Export = name,
                            Label  = mdl.Name
                        };
                        output.Items.Add(info);
                        if (!labels.Contains(mdl.Name))
                        {
                            models.Add(new ModelAnimations(data.Filename, name, mdl, modelfmt));
                            labels.AddRange(mdl.GetLabels());
                        }
                    }
                    break;

                    case "morph":
                    {
                        BasicAttach dummy = new BasicAttach(datafile, address, imageBase, modelfmt == ModelFormat.BasicDX);
                        NJS_OBJECT  mdl   = new NJS_OBJECT()
                        {
                            Attach = dummy
                        };
                        DllItemInfo info = new DllItemInfo()
                        {
                            Export = name,
                            Label  = dummy.Name
                        };
                        output.Items.Add(info);
                        if (!labels.Contains(dummy.Name))
                        {
                            models.Add(new ModelAnimations(data.Filename, name, mdl, modelfmt));
                            labels.AddRange(mdl.GetLabels());
                        }
                    }
                    break;

                    case "modelarray":
                        for (int i = 0; i < data.Length; i++)
                        {
                            int ptr = BitConverter.ToInt32(datafile, address);
                            if (ptr != 0)
                            {
                                ptr = (int)(ptr - imageBase);
                                NJS_OBJECT  mdl  = new NJS_OBJECT(datafile, ptr, imageBase, modelfmt, new Dictionary <int, Attach>());
                                string      idx  = name + "[" + i.ToString(NumberFormatInfo.InvariantInfo) + "]";
                                DllItemInfo info = new DllItemInfo()
                                {
                                    Export = name,
                                    Index  = i,
                                    Label  = mdl.Name
                                };
                                output.Items.Add(info);
                                if (!labels.Contains(mdl.Name))
                                {
                                    string fn = Path.Combine(data.Filename, i.ToString(NumberFormatInfo.InvariantInfo) + modelext);
                                    models.Add(new ModelAnimations(fn, idx, mdl, modelfmt));
                                    labels.AddRange(mdl.GetLabels());
                                }
                            }
                            address += 4;
                        }
                        break;

                    case "modelsarray":
                        for (int i = 0; i < data.Length; i++)
                        {
                            int ptr = BitConverter.ToInt32(datafile, address);
                            if (ptr != 0)
                            {
                                ptr = (int)(ptr - imageBase);
                                BasicAttach dummy = new BasicAttach(datafile, ptr, imageBase, modelfmt == ModelFormat.BasicDX);
                                NJS_OBJECT  mdl   = new NJS_OBJECT()
                                {
                                    Attach = dummy
                                };
                                string      idx  = name + "[" + i.ToString(NumberFormatInfo.InvariantInfo) + "]";
                                DllItemInfo info = new DllItemInfo()
                                {
                                    Export = name,
                                    Index  = i,
                                    Label  = dummy.Name
                                };
                                output.Items.Add(info);
                                if (!labels.Contains(dummy.Name))
                                {
                                    string fn = Path.Combine(data.Filename, i.ToString(NumberFormatInfo.InvariantInfo) + modelext);
                                    models.Add(new ModelAnimations(fn, idx, mdl, ModelFormat.BasicDX));
                                    labels.AddRange(mdl.GetLabels());
                                }
                            }
                            address += 4;
                        }
                        break;

                    case "basicmodel":
                    {
                        NJS_OBJECT  mdl  = new NJS_OBJECT(datafile, address, imageBase, ModelFormat.Basic, new Dictionary <int, Attach>());
                        DllItemInfo info = new DllItemInfo()
                        {
                            Export = name,
                            Label  = mdl.Name
                        };
                        output.Items.Add(info);
                        if (!labels.Contains(mdl.Name))
                        {
                            models.Add(new ModelAnimations(data.Filename, name, mdl, ModelFormat.Basic));
                            labels.AddRange(mdl.GetLabels());
                        }
                    }
                    break;

                    case "basicmodelarray":
                        for (int i = 0; i < data.Length; i++)
                        {
                            int ptr = BitConverter.ToInt32(datafile, address);
                            if (ptr != 0)
                            {
                                ptr = (int)(ptr - imageBase);
                                NJS_OBJECT  mdl  = new NJS_OBJECT(datafile, ptr, imageBase, ModelFormat.Basic, new Dictionary <int, Attach>());
                                string      idx  = name + "[" + i.ToString(NumberFormatInfo.InvariantInfo) + "]";
                                DllItemInfo info = new DllItemInfo()
                                {
                                    Export = name,
                                    Index  = i,
                                    Label  = mdl.Name
                                };
                                output.Items.Add(info);
                                if (!labels.Contains(mdl.Name))
                                {
                                    string fn = Path.Combine(data.Filename, i.ToString(NumberFormatInfo.InvariantInfo) + ".sa1mdl");
                                    models.Add(new ModelAnimations(fn, idx, mdl, ModelFormat.Basic));
                                    labels.AddRange(mdl.GetLabels());
                                }
                            }
                            address += 4;
                        }
                        break;

                    case "basicdxmodel":
                    {
                        NJS_OBJECT  mdl  = new NJS_OBJECT(datafile, address, imageBase, ModelFormat.BasicDX, new Dictionary <int, Attach>());
                        DllItemInfo info = new DllItemInfo()
                        {
                            Export = name,
                            Label  = mdl.Name
                        };
                        output.Items.Add(info);
                        if (!labels.Contains(mdl.Name))
                        {
                            models.Add(new ModelAnimations(data.Filename, name, mdl, ModelFormat.BasicDX));
                            labels.AddRange(mdl.GetLabels());
                        }
                    }
                    break;

                    case "basicdxmodelarray":
                        for (int i = 0; i < data.Length; i++)
                        {
                            int ptr = BitConverter.ToInt32(datafile, address);
                            if (ptr != 0)
                            {
                                ptr = (int)(ptr - imageBase);
                                NJS_OBJECT  mdl  = new NJS_OBJECT(datafile, ptr, imageBase, ModelFormat.BasicDX, new Dictionary <int, Attach>());
                                string      idx  = name + "[" + i.ToString(NumberFormatInfo.InvariantInfo) + "]";
                                DllItemInfo info = new DllItemInfo()
                                {
                                    Export = name,
                                    Index  = i,
                                    Label  = mdl.Name
                                };
                                output.Items.Add(info);
                                if (!labels.Contains(mdl.Name))
                                {
                                    string fn = Path.Combine(data.Filename, i.ToString(NumberFormatInfo.InvariantInfo) + ".sa1mdl");
                                    models.Add(new ModelAnimations(fn, idx, mdl, ModelFormat.BasicDX));
                                    labels.AddRange(mdl.GetLabels());
                                }
                            }
                            address += 4;
                        }
                        break;

                    case "chunkmodel":
                    {
                        NJS_OBJECT  mdl  = new NJS_OBJECT(datafile, address, imageBase, ModelFormat.Chunk, new Dictionary <int, Attach>());
                        DllItemInfo info = new DllItemInfo()
                        {
                            Export = name,
                            Label  = mdl.Name
                        };
                        output.Items.Add(info);
                        if (!labels.Contains(mdl.Name))
                        {
                            models.Add(new ModelAnimations(data.Filename, name, mdl, ModelFormat.Chunk));
                            labels.AddRange(mdl.GetLabels());
                        }
                    }
                    break;

                    case "chunkmodelarray":
                        for (int i = 0; i < data.Length; i++)
                        {
                            int ptr = BitConverter.ToInt32(datafile, address);
                            if (ptr != 0)
                            {
                                ptr = (int)(ptr - imageBase);
                                NJS_OBJECT  mdl  = new NJS_OBJECT(datafile, ptr, imageBase, ModelFormat.Chunk, new Dictionary <int, Attach>());
                                string      idx  = name + "[" + i.ToString(NumberFormatInfo.InvariantInfo) + "]";
                                DllItemInfo info = new DllItemInfo()
                                {
                                    Export = name,
                                    Index  = i,
                                    Label  = mdl.Name
                                };
                                output.Items.Add(info);
                                if (!labels.Contains(mdl.Name))
                                {
                                    string fn = Path.Combine(data.Filename, i.ToString(NumberFormatInfo.InvariantInfo) + ".sa2mdl");
                                    models.Add(new ModelAnimations(fn, idx, mdl, ModelFormat.Chunk));
                                    labels.AddRange(mdl.GetLabels());
                                }
                            }
                            address += 4;
                        }
                        break;

                    case "actionarray":
                        for (int i = 0; i < data.Length; i++)
                        {
                            int ptr = BitConverter.ToInt32(datafile, address);
                            if (ptr != 0)
                            {
                                ptr = (int)(ptr - imageBase);
                                NJS_ACTION ani     = new NJS_ACTION(datafile, ptr, imageBase, modelfmt, new Dictionary <int, Attach>());
                                string     nm      = item.Key + "_" + i;
                                bool       saveani = false;
                                if (!anilabels.ContainsKey(ani.Animation.Name))
                                {
                                    anilabels.Add(ani.Animation.Name, nm);
                                    ani.Animation.Name = nm;
                                    saveani            = true;
                                }
                                else
                                {
                                    nm = anilabels[ani.Animation.Name];
                                }
                                DllItemInfo info = new DllItemInfo()
                                {
                                    Export = name,
                                    Index  = i,
                                    Label  = nm,
                                    Field  = "motion"
                                };
                                output.Items.Add(info);
                                info = new DllItemInfo()
                                {
                                    Export = name,
                                    Index  = i,
                                    Label  = ani.Model.Name,
                                    Field  = "object"
                                };
                                output.Items.Add(info);
                                string outputFN = Path.Combine(fileOutputPath, i.ToString(NumberFormatInfo.InvariantInfo) + ".saanim");
                                string fn       = Path.Combine(data.Filename, i.ToString(NumberFormatInfo.InvariantInfo) + ".saanim");
                                if (saveani)
                                {
                                    ani.Animation.Save(outputFN);
                                    output.Files[fn] = new FileTypeHash("animation", HelperFunctions.FileHash(outputFN));
                                }
                                if (models.Contains(ani.Model.Name))
                                {
                                    ModelAnimations           mdl = models[ani.Model.Name];
                                    System.Text.StringBuilder sb  = new System.Text.StringBuilder(260);
                                    PathRelativePathTo(sb, Path.GetFullPath(Path.Combine(projectFolderName, mdl.Filename)), 0, Path.GetFullPath(outputFN), 0);
                                    mdl.Animations.Add(sb.ToString());                                             // this is where the problem is
                                }
                                else
                                {
                                    string mfn           = Path.ChangeExtension(fn, modelext);
                                    string outputmfn     = Path.Combine(projectFolderName, mfn);
                                    string animationName = Path.GetFileName(outputFN);

                                    ModelFile.CreateFile(outputmfn, ani.Model, new[] { animationName }, null, $"{name}[{i}]->object",
                                                         null, modelfmt);
                                    output.Files[mfn] = new FileTypeHash("model", HelperFunctions.FileHash(outputmfn));
                                }
                            }
                            address += 4;
                        }
                        break;

                    case "motionarray":
                    {
                        int[] nodecounts = data.CustomProperties["nodecounts"].Split(',').Select(a => int.Parse(a)).ToArray();
                        for (int i = 0; i < data.Length; i++)
                        {
                            int ptr = BitConverter.ToInt32(datafile, address);
                            if (ptr != 0)
                            {
                                ptr = (int)(ptr - imageBase);
                                NJS_MOTION ani     = new NJS_MOTION(datafile, ptr, imageBase, nodecounts[i]);
                                string     nm      = item.Key + "_" + i;
                                bool       saveani = false;
                                if (!anilabels.ContainsKey(ani.Name))
                                {
                                    anilabels.Add(ani.Name, nm);
                                    ani.Name = nm;
                                    saveani  = true;
                                }
                                else
                                {
                                    nm = anilabels[ani.Name];
                                }
                                DllItemInfo info = new DllItemInfo()
                                {
                                    Export = name,
                                    Index  = i,
                                    Label  = nm
                                };
                                output.Items.Add(info);
                                if (saveani)
                                {
                                    string outputFN = Path.Combine(fileOutputPath, i.ToString(NumberFormatInfo.InvariantInfo) + ".saanim");
                                    string fn       = Path.Combine(data.Filename, i.ToString(NumberFormatInfo.InvariantInfo) + ".saanim");
                                    ani.Save(outputFN);
                                    output.Files[fn] = new FileTypeHash("animation", HelperFunctions.FileHash(outputFN));
                                }
                            }
                            address += 4;
                        }
                    }
                    break;

                    case "texlist":
                        if (output.TexLists == null)
                        {
                            output.TexLists = new TexListContainer();
                        }
                        output.TexLists.Add((uint)(address + imageBase), new DllTexListInfo(name, null));
                        break;

                    case "texlistarray":
                        if (output.TexLists == null)
                        {
                            output.TexLists = new TexListContainer();
                        }
                        for (int i = 0; i < data.Length; i++)
                        {
                            uint ptr = BitConverter.ToUInt32(datafile, address);
                            if (ptr != 0 && !output.TexLists.ContainsKey(ptr))
                            {
                                output.TexLists.Add(ptr, new DllTexListInfo(name, i));
                            }
                            address += 4;
                        }
                        break;

                    case "animindexlist":
                    {
                        Directory.CreateDirectory(fileOutputPath);
                        List <string> hashes = new List <string>();
                        int           i      = ByteConverter.ToInt16(datafile, address);
                        while (i != -1)
                        {
                            new NJS_MOTION(datafile, datafile.GetPointer(address + 4, imageBase), imageBase, ByteConverter.ToInt16(datafile, address + 2))
                            .Save(fileOutputPath + "/" + i.ToString(NumberFormatInfo.InvariantInfo) + ".saanim");
                            hashes.Add(i.ToString(NumberFormatInfo.InvariantInfo) + ":" + HelperFunctions.FileHash(fileOutputPath + "/" + i.ToString(NumberFormatInfo.InvariantInfo) + ".saanim"));
                            address += 8;
                            i        = ByteConverter.ToInt16(datafile, address);
                        }
                        output.DataItems.Add(new DllDataItemInfo()
                            {
                                Type = type, Export = name, Filename = data.Filename, MD5Hash = string.Join("|", hashes.ToArray())
                            });
                    }
                    break;

                    case "charaobjectdatalist":
                    {
                        Directory.CreateDirectory(fileOutputPath);
                        List <CharaObjectData> result = new List <CharaObjectData>();
                        List <string>          hashes = new List <string>();
                        for (int i = 0; i < data.Length; i++)
                        {
                            string          chnm  = charaobjectnames[i];
                            CharaObjectData chara = new CharaObjectData();
                            NJS_OBJECT      model = new NJS_OBJECT(datafile, (int)(BitConverter.ToInt32(datafile, address) - imageBase), imageBase, ModelFormat.Chunk, new Dictionary <int, Attach>());
                            chara.MainModel = model.Name;
                            NJS_MOTION anim = new NJS_MOTION(datafile, (int)(BitConverter.ToInt32(datafile, address + 4) - imageBase), imageBase, model.CountAnimated());
                            chara.Animation1 = anim.Name;
                            anim.Save(Path.Combine(fileOutputPath, $"{chnm} Anim 1.saanim"));
                            hashes.Add($"{chnm} Anim 1.saanim:" + HelperFunctions.FileHash(Path.Combine(fileOutputPath, $"{chnm} Anim 1.saanim")));
                            anim             = new NJS_MOTION(datafile, (int)(BitConverter.ToInt32(datafile, address + 8) - imageBase), imageBase, model.CountAnimated());
                            chara.Animation2 = anim.Name;
                            anim.Save(Path.Combine(fileOutputPath, $"{chnm} Anim 2.saanim"));
                            hashes.Add($"{chnm} Anim 2.saanim:" + HelperFunctions.FileHash(Path.Combine(fileOutputPath, $"{chnm} Anim 2.saanim")));
                            anim             = new NJS_MOTION(datafile, (int)(BitConverter.ToInt32(datafile, address + 12) - imageBase), imageBase, model.CountAnimated());
                            chara.Animation3 = anim.Name;
                            anim.Save(Path.Combine(fileOutputPath, $"{chnm} Anim 3.saanim"));
                            hashes.Add($"{chnm} Anim 3.saanim:" + HelperFunctions.FileHash(Path.Combine(fileOutputPath, $"{chnm} Anim 3.saanim")));
                            ModelFile.CreateFile(Path.Combine(fileOutputPath, $"{chnm}.sa2mdl"), model, new[] { $"{chnm} Anim 1.saanim", $"{chnm} Anim 2.saanim", $"{chnm} Anim 3.saanim" }, null, null, null, ModelFormat.Chunk);
                            hashes.Add($"{chnm}.sa2mdl:" + HelperFunctions.FileHash(Path.Combine(fileOutputPath, $"{chnm}.sa2mdl")));
                            int ptr = BitConverter.ToInt32(datafile, address + 16);
                            if (ptr != 0)
                            {
                                model = new NJS_OBJECT(datafile, (int)(ptr - imageBase), imageBase, ModelFormat.Chunk, new Dictionary <int, Attach>());
                                chara.AccessoryModel      = model.Name;
                                chara.AccessoryAttachNode = "object_" + (BitConverter.ToInt32(datafile, address + 20) - imageBase).ToString("X8");
                                ModelFile.CreateFile(Path.Combine(fileOutputPath, $"{chnm} Accessory.sa2mdl"), model, null, null, null, null, ModelFormat.Chunk);
                                hashes.Add($"{chnm} Accessory.sa2mdl:" + HelperFunctions.FileHash(Path.Combine(fileOutputPath, $"{chnm} Accessory.sa2mdl")));
                            }
                            ptr = BitConverter.ToInt32(datafile, address + 24);
                            if (ptr != 0)
                            {
                                model                 = new NJS_OBJECT(datafile, (int)(ptr - imageBase), imageBase, ModelFormat.Chunk, new Dictionary <int, Attach>());
                                chara.SuperModel      = model.Name;
                                anim                  = new NJS_MOTION(datafile, (int)(BitConverter.ToInt32(datafile, address + 28) - imageBase), imageBase, model.CountAnimated());
                                chara.SuperAnimation1 = anim.Name;
                                anim.Save(Path.Combine(fileOutputPath, $"Super {chnm} Anim 1.saanim"));
                                hashes.Add($"Super {chnm} Anim 1.saanim:" + HelperFunctions.FileHash(Path.Combine(fileOutputPath, $"Super {chnm} Anim 1.saanim")));
                                anim = new NJS_MOTION(datafile, (int)(BitConverter.ToInt32(datafile, address + 32) - imageBase), imageBase, model.CountAnimated());
                                chara.SuperAnimation2 = anim.Name;
                                anim.Save(Path.Combine(fileOutputPath, $"Super {chnm} Anim 2.saanim"));
                                hashes.Add($"Super {chnm} Anim 2.saanim:" + HelperFunctions.FileHash(Path.Combine(fileOutputPath, $"Super {chnm} Anim 2.saanim")));
                                anim = new NJS_MOTION(datafile, (int)(BitConverter.ToInt32(datafile, address + 36) - imageBase), imageBase, model.CountAnimated());
                                chara.SuperAnimation3 = anim.Name;
                                anim.Save(Path.Combine(fileOutputPath, $"Super {chnm} Anim 3.saanim"));
                                hashes.Add($"Super {chnm} Anim 3.saanim:" + HelperFunctions.FileHash(Path.Combine(fileOutputPath, $"Super {chnm} Anim 3.saanim")));
                                ModelFile.CreateFile(Path.Combine(fileOutputPath, $"Super {chnm}.sa2mdl"), model, new[] { $"Super {chnm} Anim 1.saanim", $"Super {chnm} Anim 2.saanim", $"Super {chnm} Anim 3.saanim" }, null, null, null, ModelFormat.Chunk);
                                hashes.Add($"Super {chnm}.sa2mdl:" + HelperFunctions.FileHash(Path.Combine(fileOutputPath, $"Super {chnm}.sa2mdl")));
                            }
                            chara.Unknown1        = BitConverter.ToInt32(datafile, address + 40);
                            chara.Rating          = BitConverter.ToInt32(datafile, address + 44);
                            chara.DescriptionID   = BitConverter.ToInt32(datafile, address + 48);
                            chara.TextBackTexture = BitConverter.ToInt32(datafile, address + 52);
                            chara.Unknown5        = BitConverter.ToSingle(datafile, address + 56);
                            result.Add(chara);
                            address += 60;
                        }
                        IniSerializer.Serialize(result, Path.Combine(fileOutputPath, "info.ini"));
                        hashes.Add("info.ini:" + HelperFunctions.FileHash(Path.Combine(fileOutputPath, "info.ini")));
                        output.DataItems.Add(new DllDataItemInfo()
                            {
                                Type = type, Export = name, Filename = data.Filename, MD5Hash = string.Join("|", hashes.ToArray())
                            });
                    }
                    break;

                    case "kartspecialinfolist":
                    {
                        Directory.CreateDirectory(fileOutputPath);
                        List <KartSpecialInfo> result = new List <KartSpecialInfo>();
                        List <string>          hashes = new List <string>();
                        for (int i = 0; i < data.Length; i++)
                        {
                            KartSpecialInfo kart = new KartSpecialInfo
                            {
                                ID = ByteConverter.ToInt32(datafile, address)
                            };
                            NJS_OBJECT model = new NJS_OBJECT(datafile, (int)(BitConverter.ToInt32(datafile, address + 4) - imageBase), imageBase, ModelFormat.Chunk, new Dictionary <int, Attach>());
                            kart.Model = model.Name;
                            ModelFile.CreateFile(Path.Combine(fileOutputPath, $"{i}.sa2mdl"), model, null, null, null, null, ModelFormat.Chunk);
                            hashes.Add($"{i}.sa2mdl:" + HelperFunctions.FileHash(Path.Combine(fileOutputPath, $"{i}.sa2mdl")));
                            int ptr = BitConverter.ToInt32(datafile, address + 8);
                            if (ptr != 0)
                            {
                                model         = new NJS_OBJECT(datafile, (int)(ptr - imageBase), imageBase, ModelFormat.Chunk, new Dictionary <int, Attach>());
                                kart.LowModel = model.Name;
                                ModelFile.CreateFile(Path.Combine(fileOutputPath, $"{i} Low.sa2mdl"), model, null, null, null, null, ModelFormat.Chunk);
                                hashes.Add($"{i} Low.sa2mdl:" + HelperFunctions.FileHash(Path.Combine(fileOutputPath, $"{i} Low.sa2mdl")));
                            }
                            kart.TexList  = ByteConverter.ToUInt32(datafile, address + 12);
                            kart.Unknown1 = ByteConverter.ToInt32(datafile, address + 16);
                            kart.Unknown2 = ByteConverter.ToInt32(datafile, address + 20);
                            kart.Unknown3 = ByteConverter.ToInt32(datafile, address + 24);
                            result.Add(kart);
                            address += 0x1C;
                        }
                        IniSerializer.Serialize(result, Path.Combine(fileOutputPath, "info.ini"));
                        hashes.Add("info.ini:" + HelperFunctions.FileHash(Path.Combine(fileOutputPath, "info.ini")));
                        output.DataItems.Add(new DllDataItemInfo()
                            {
                                Type = type, Export = name, Filename = data.Filename, MD5Hash = string.Join("|", hashes.ToArray())
                            });
                    }
                    break;

                    case "chaomotiontable":
                    {
                        Directory.CreateDirectory(fileOutputPath);
                        List <ChaoMotionTableEntry> result = new List <ChaoMotionTableEntry>();
                        List <string>            hashes    = new List <string>();
                        int                      nodeCount = int.Parse(data.CustomProperties["nodecount"]);
                        Dictionary <int, string> mtns      = new Dictionary <int, string>();
                        for (int i = 0; i < data.Length; i++)
                        {
                            ChaoMotionTableEntry cmte = new ChaoMotionTableEntry();
                            int mtnaddr = (int)(ByteConverter.ToInt32(datafile, address) - imageBase);
                            if (!mtns.ContainsKey(mtnaddr))
                            {
                                NJS_MOTION motion = new NJS_MOTION(datafile, mtnaddr, imageBase, nodeCount, shortrot: true);
                                cmte.Motion = motion.Name;
                                mtns.Add(mtnaddr, motion.Name);
                                motion.Save(Path.Combine(fileOutputPath, $"{i}.saanim"));
                                hashes.Add($"{i}.saanim:" + HelperFunctions.FileHash(Path.Combine(fileOutputPath, $"{i}.saanim")));
                            }
                            else
                            {
                                cmte.Motion = mtns[mtnaddr];
                            }
                            cmte.Flag1        = ByteConverter.ToUInt16(datafile, address + 4);
                            cmte.Pose         = ByteConverter.ToUInt16(datafile, address + 6);
                            cmte.TransitionID = ByteConverter.ToInt32(datafile, address + 8);
                            cmte.Flag2        = ByteConverter.ToUInt32(datafile, address + 12);
                            cmte.StartFrame   = ByteConverter.ToSingle(datafile, address + 16);
                            cmte.EndFrame     = ByteConverter.ToSingle(datafile, address + 20);
                            cmte.PlaySpeed    = ByteConverter.ToSingle(datafile, address + 24);
                            result.Add(cmte);
                            address += 0x1C;
                        }
                        IniSerializer.Serialize(result, Path.Combine(fileOutputPath, "info.ini"));
                        hashes.Add("info.ini:" + HelperFunctions.FileHash(Path.Combine(fileOutputPath, "info.ini")));
                        output.DataItems.Add(new DllDataItemInfo()
                            {
                                Type = type, Export = name, Filename = data.Filename, MD5Hash = string.Join("|", hashes.ToArray())
                            });
                    }
                    break;
                    }
                    itemcount++;
                }
                foreach (ModelAnimations item in models)
                {
                    string modelOutputPath = string.Concat(projectFolderName, item.Filename);
                    //string modelOutputPath = item.Filename;

                    ModelFile.CreateFile(modelOutputPath, item.Model, item.Animations.ToArray(), null, item.Name, null, item.Format);
                    string type = "model";
                    switch (item.Format)
                    {
                    case ModelFormat.Basic:
                        type = "basicmodel";
                        break;

                    case ModelFormat.BasicDX:
                        type = "basicdxmodel";
                        break;

                    case ModelFormat.Chunk:
                        type = "chunkmodel";
                        break;
                    }
                    output.Files[item.Filename] = new FileTypeHash(type, HelperFunctions.FileHash(modelOutputPath));
                }
                IniSerializer.Serialize(output, Path.Combine(projectFolderName, Path.GetFileNameWithoutExtension(datafilename))
                                        + "_data.ini");
                timer.Stop();
                Console.WriteLine("Split " + itemcount + " items in " + timer.Elapsed.TotalSeconds + " seconds.");
                Console.WriteLine();
            }
#if !DEBUG
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                Console.WriteLine(e.StackTrace);
                Console.WriteLine("Press any key to exit.");
                Console.ReadLine();
                return((int)SA_Tools.Split.SplitERRORVALUE.UnhandledException);
            }
#endif
            return((int)SA_Tools.Split.SplitERRORVALUE.Success);
        }
Example #3
0
        private void button1_Click(object sender, EventArgs e)
        {
            bool success = false;
            uint address = (uint)numericUpDownBinaryAddress.Value;

            if (checkBoxBinaryMemory.Checked)
            {
                address -= (uint)numericUpDownBinaryKey.Value;
            }
            LandTableFormat format = (LandTableFormat)comboBoxBinaryFormat.SelectedIndex;
            LandTableFormat outfmt = format;

            if (format == LandTableFormat.SADX)
            {
                outfmt = LandTableFormat.SA1;
            }
            ByteConverter.BigEndian = checkBoxBinaryBigEndian.Checked;
            Settings.Author         = textBoxBinaryAuthor.Text;
            Settings.Save();
            SaveFileDialog sd = new SaveFileDialog();

            switch (comboBoxBinaryItemType.SelectedIndex)
            {
            //Level
            case 0:
                sd = new SaveFileDialog()
                {
                    DefaultExt = outfmt.ToString().ToLowerInvariant() + "lvl", Filter = outfmt.ToString().ToUpperInvariant() + "LVL Files|*." + outfmt.ToString().ToLowerInvariant() + "lvl|All Files|*.*"
                };
                if (sd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                {
                    new LandTable(file, (int)numericUpDownBinaryAddress.Value, (uint)numericUpDownBinaryKey.Value, format)
                    {
                        Author = textBoxBinaryAuthor.Text, Description = textBoxBinaryDescription.Text
                    }.SaveToFile(sd.FileName, outfmt);
                    if (checkBoxBinaryStructs.Checked)
                    {
                        ConvertToText(sd.FileName);
                    }
                    if (!checkBoxBinarySAModel.Checked)
                    {
                        File.Delete(sd.FileName);
                    }
                    success = true;
                }
                break;

            //Model
            case 1:
                sd = new SaveFileDialog()
                {
                    DefaultExt = outfmt.ToString().ToLowerInvariant() + "mdl", Filter = outfmt.ToString().ToUpperInvariant() + "MDL Files|*." + outfmt.ToString().ToLowerInvariant() + "mdl|All Files|*.*"
                };
                if (sd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                {
                    NJS_OBJECT tempmodel = new NJS_OBJECT(file, (int)address, (uint)numericUpDownBinaryKey.Value, (ModelFormat)comboBoxBinaryFormat.SelectedIndex, null);
                    ModelFile.CreateFile(sd.FileName, tempmodel, null, textBoxBinaryAuthor.Text, textBoxBinaryDescription.Text, null, (ModelFormat)comboBoxBinaryFormat.SelectedIndex);
                    ConvertToText(sd.FileName, checkBoxBinaryStructs.Checked, checkBoxBinaryNJA.Checked, false);
                    if (!checkBoxBinarySAModel.Checked)
                    {
                        File.Delete(sd.FileName);
                    }
                    success = true;
                }
                break;

            //Action
            case 2:
                sd = new SaveFileDialog()
                {
                    DefaultExt = outfmt.ToString().ToLowerInvariant() + "mdl", Filter = outfmt.ToString().ToUpperInvariant() + "MDL Files|*." + outfmt.ToString().ToLowerInvariant() + "mdl|All Files|*.*"
                };
                if (sd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                {
                    //Model
                    NJS_ACTION tempaction = new NJS_ACTION(file, (int)address, (uint)numericUpDownBinaryKey.Value, (ModelFormat)comboBoxBinaryFormat.SelectedIndex, null);
                    NJS_OBJECT tempmodel  = tempaction.Model;
                    ModelFile.CreateFile(sd.FileName, tempmodel, null, textBoxBinaryAuthor.Text, textBoxBinaryDescription.Text, null, (ModelFormat)comboBoxBinaryFormat.SelectedIndex);
                    ConvertToText(sd.FileName, checkBoxBinaryStructs.Checked, checkBoxBinaryNJA.Checked, false);
                    if (!checkBoxBinarySAModel.Checked)
                    {
                        File.Delete(sd.FileName);
                    }

                    //Action
                    string saanimPath = Path.Combine(Path.GetDirectoryName(sd.FileName), Path.GetFileNameWithoutExtension(sd.FileName) + ".saanim");

                    tempaction.Animation.Save(saanimPath);
                    ConvertToText(saanimPath, checkBoxBinaryStructs.Checked, false, checkBoxBinaryJSON.Checked);

                    if (checkBoxBinarySAModel.Checked)
                    {
                        using (TextWriter twmain = File.CreateText(Path.Combine(Path.GetDirectoryName(sd.FileName), Path.GetFileNameWithoutExtension(sd.FileName) + ".action")))
                        {
                            twmain.WriteLine(Path.GetFileName(saanimPath));
                            twmain.Flush();
                            twmain.Close();
                        }
                    }
                    else
                    {
                        File.Delete(saanimPath);
                    }
                    success = true;
                }
                break;
            }
            if (success)
            {
                MessageBox.Show("Data extracted!", "Binary Data Extractor", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }
Example #4
0
        public static int SplitFile(string datafilename, string inifilename, string projectFolderName)
        {
            try
            {
                byte[]  datafile = File.ReadAllBytes(datafilename);
                IniData inifile  = IniSerializer.Deserialize <IniData>(inifilename);
                if (inifile.MD5 != null && inifile.MD5.Count > 0)
                {
                    string datahash = HelperFunctions.FileHash(datafile);
                    if (!inifile.MD5.Any(h => h.Equals(datahash, StringComparison.OrdinalIgnoreCase)))
                    {
                        Console.WriteLine("The file {0} is not valid for use with the INI {1}.", datafilename, inifilename);
                        return((int)SplitERRORVALUE.InvalidDataMapping);
                    }
                }
                ByteConverter.BigEndian      = SonicRetro.SAModel.ByteConverter.BigEndian = inifile.BigEndian;
                Environment.CurrentDirectory = Path.Combine(Environment.CurrentDirectory, Path.GetDirectoryName(datafilename));
                if (inifile.Compressed)
                {
                    datafile = FraGag.Compression.Prs.Decompress(datafile);
                }
                uint imageBase = HelperFunctions.SetupEXE(ref datafile) ?? inifile.ImageBase.Value;
                if (Path.GetExtension(datafilename).Equals(".rel", StringComparison.OrdinalIgnoreCase))
                {
                    HelperFunctions.FixRELPointers(datafile);
                }
                bool            SA2      = inifile.Game == Game.SA2 | inifile.Game == Game.SA2B;
                ModelFormat     modelfmt = 0;
                LandTableFormat landfmt  = 0;
                switch (inifile.Game)
                {
                case Game.SA1:
                    modelfmt = ModelFormat.Basic;
                    landfmt  = LandTableFormat.SA1;
                    break;

                case Game.SADX:
                    modelfmt = ModelFormat.BasicDX;
                    landfmt  = LandTableFormat.SADX;
                    break;

                case Game.SA2:
                case Game.SA2B:
                    modelfmt = ModelFormat.Chunk;
                    landfmt  = LandTableFormat.SA2;
                    break;
                }
                int itemcount = 0;
                Dictionary <string, MasterObjectListEntry>     masterobjlist = new Dictionary <string, MasterObjectListEntry>();
                Dictionary <string, Dictionary <string, int> > objnamecounts = new Dictionary <string, Dictionary <string, int> >();
                Stopwatch timer = new Stopwatch();
                timer.Start();
                foreach (KeyValuePair <string, SA_Tools.FileInfo> item in inifile.Files)
                {
                    if (string.IsNullOrEmpty(item.Key))
                    {
                        continue;
                    }
                    string                      filedesc         = item.Key;
                    SA_Tools.FileInfo           data             = item.Value;
                    Dictionary <string, string> customProperties = data.CustomProperties;
                    string                      type             = data.Type;
                    int  address = data.Address;
                    bool nohash  = false;

                    string fileOutputPath = string.Concat(projectFolderName, data.Filename);
                    Console.WriteLine(item.Key + ": " + data.Address.ToString("X") + " → " + fileOutputPath);
                    Directory.CreateDirectory(Path.GetDirectoryName(fileOutputPath));
                    switch (type)
                    {
                    case "landtable":
                        new LandTable(datafile, address, imageBase, landfmt)
                        {
                            Description = item.Key
                        }.SaveToFile(fileOutputPath, landfmt);
                        break;

                    case "model":
                    {
                        NJS_OBJECT mdl     = new NJS_OBJECT(datafile, address, imageBase, modelfmt, new Dictionary <int, Attach>());
                        string[]   mdlanis = new string[0];
                        if (customProperties.ContainsKey("animations"))
                        {
                            mdlanis = customProperties["animations"].Split(',');
                        }
                        string[] mdlmorphs = new string[0];
                        if (customProperties.ContainsKey("morphs"))
                        {
                            mdlmorphs = customProperties["morphs"].Split(',');
                        }
                        ModelFile.CreateFile(fileOutputPath, mdl, mdlanis, null, item.Key, null, modelfmt);
                    }
                    break;

                    case "basicmodel":
                    {
                        NJS_OBJECT mdl     = new NJS_OBJECT(datafile, address, imageBase, ModelFormat.Basic, new Dictionary <int, Attach>());
                        string[]   mdlanis = new string[0];
                        if (customProperties.ContainsKey("animations"))
                        {
                            mdlanis = customProperties["animations"].Split(',');
                        }
                        string[] mdlmorphs = new string[0];
                        if (customProperties.ContainsKey("morphs"))
                        {
                            mdlmorphs = customProperties["morphs"].Split(',');
                        }
                        ModelFile.CreateFile(fileOutputPath, mdl, mdlanis, null, item.Key, null, ModelFormat.Basic);
                    }
                    break;

                    case "basicdxmodel":
                    {
                        NJS_OBJECT mdl     = new NJS_OBJECT(datafile, address, imageBase, ModelFormat.BasicDX, new Dictionary <int, Attach>());
                        string[]   mdlanis = new string[0];
                        if (customProperties.ContainsKey("animations"))
                        {
                            mdlanis = customProperties["animations"].Split(',');
                        }
                        string[] mdlmorphs = new string[0];
                        if (customProperties.ContainsKey("morphs"))
                        {
                            mdlmorphs = customProperties["morphs"].Split(',');
                        }
                        ModelFile.CreateFile(fileOutputPath, mdl, mdlanis, null, item.Key, null, ModelFormat.BasicDX);
                    }
                    break;

                    case "chunkmodel":
                    {
                        NJS_OBJECT mdl     = new NJS_OBJECT(datafile, address, imageBase, ModelFormat.Chunk, new Dictionary <int, Attach>());
                        string[]   mdlanis = new string[0];
                        if (customProperties.ContainsKey("animations"))
                        {
                            mdlanis = customProperties["animations"].Split(',');
                        }
                        string[] mdlmorphs = new string[0];
                        if (customProperties.ContainsKey("morphs"))
                        {
                            mdlmorphs = customProperties["morphs"].Split(',');
                        }
                        ModelFile.CreateFile(fileOutputPath, mdl, mdlanis, null, item.Key, null, ModelFormat.Chunk);
                    }
                    break;

                    case "gcmodel":
                    {
                        NJS_OBJECT mdl     = new NJS_OBJECT(datafile, address, imageBase, ModelFormat.GC, new Dictionary <int, Attach>());
                        string[]   mdlanis = new string[0];
                        if (customProperties.ContainsKey("animations"))
                        {
                            mdlanis = customProperties["animations"].Split(',');
                        }
                        string[] mdlmorphs = new string[0];
                        if (customProperties.ContainsKey("morphs"))
                        {
                            mdlmorphs = customProperties["morphs"].Split(',');
                        }
                        ModelFile.CreateFile(fileOutputPath, mdl, mdlanis, null, item.Key, null, ModelFormat.GC);
                    }
                    break;

                    case "action":
                    {
                        NJS_ACTION ani = new NJS_ACTION(datafile, address, imageBase, modelfmt, new Dictionary <int, Attach>());
                        ani.Animation.Name = filedesc;
                        ani.Animation.Save(fileOutputPath);
                    }
                    break;

                    case "animation":
                        new NJS_MOTION(datafile, address, imageBase, int.Parse(customProperties["numparts"], NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite, NumberFormatInfo.InvariantInfo))
                        {
                            Name = filedesc
                        }
                        .Save(fileOutputPath);
                        break;

                    case "objlist":
                    {
                        ObjectListEntry[] objs = ObjectList.Load(datafile, address, imageBase, SA2);
                        if (inifile.MasterObjectList != null)
                        {
                            foreach (ObjectListEntry obj in objs)
                            {
                                if (!masterobjlist.ContainsKey(obj.CodeString))
                                {
                                    masterobjlist.Add(obj.CodeString, new MasterObjectListEntry(obj));
                                }
                                if (!objnamecounts.ContainsKey(obj.CodeString))
                                {
                                    objnamecounts.Add(obj.CodeString, new Dictionary <string, int>()
                                        {
                                            { obj.Name, 1 }
                                        });
                                }
                                else if (!objnamecounts[obj.CodeString].ContainsKey(obj.Name))
                                {
                                    objnamecounts[obj.CodeString].Add(obj.Name, 1);
                                }
                                else
                                {
                                    objnamecounts[obj.CodeString][obj.Name]++;
                                }
                            }
                        }
                        objs.Save(fileOutputPath);
                    }
                    break;

                    case "startpos":
                        if (SA2)
                        {
                            SA2StartPosList.Load(datafile, address).Save(fileOutputPath);
                        }
                        else
                        {
                            SA1StartPosList.Load(datafile, address).Save(fileOutputPath);
                        }
                        break;

                    case "texlist":
                        TextureList.Load(datafile, address, imageBase).Save(fileOutputPath);
                        break;

                    case "leveltexlist":
                        new LevelTextureList(datafile, address, imageBase).Save(fileOutputPath);
                        break;

                    case "triallevellist":
                        TrialLevelList.Save(TrialLevelList.Load(datafile, address, imageBase), fileOutputPath);
                        break;

                    case "bosslevellist":
                        BossLevelList.Save(BossLevelList.Load(datafile, address), fileOutputPath);
                        break;

                    case "fieldstartpos":
                        FieldStartPosList.Load(datafile, address).Save(fileOutputPath);
                        break;

                    case "soundtestlist":
                        SoundTestList.Load(datafile, address, imageBase).Save(fileOutputPath);
                        break;

                    case "musiclist":
                    {
                        int muscnt = int.Parse(customProperties["length"], NumberStyles.Integer, NumberFormatInfo.InvariantInfo);
                        MusicList.Load(datafile, address, imageBase, muscnt).Save(fileOutputPath);
                    }
                    break;

                    case "soundlist":
                        SoundList.Load(datafile, address, imageBase).Save(fileOutputPath);
                        break;

                    case "stringarray":
                    {
                        int       cnt  = int.Parse(customProperties["length"], NumberStyles.Integer, NumberFormatInfo.InvariantInfo);
                        Languages lang = Languages.Japanese;
                        if (data.CustomProperties.ContainsKey("language"))
                        {
                            lang = (Languages)Enum.Parse(typeof(Languages), data.CustomProperties["language"], true);
                        }
                        StringArray.Load(datafile, address, imageBase, cnt, lang).Save(fileOutputPath);
                    }
                    break;

                    case "nextlevellist":
                        NextLevelList.Load(datafile, address).Save(fileOutputPath);
                        break;

                    case "cutscenetext":
                    {
                        int cnt = int.Parse(customProperties["length"], NumberStyles.Integer, NumberFormatInfo.InvariantInfo);
                        new CutsceneText(datafile, address, imageBase, cnt).Save(fileOutputPath, out string[] hashes);
                        data.MD5Hash = string.Join(",", hashes);
                        nohash       = true;
                    }
                    break;

                    case "recapscreen":
                    {
                        int cnt = int.Parse(customProperties["length"], NumberStyles.Integer, NumberFormatInfo.InvariantInfo);
                        RecapScreenList.Load(datafile, address, imageBase, cnt).Save(fileOutputPath, out string[][] hashes);
                        string[] hash2 = new string[hashes.Length];
                        for (int i = 0; i < hashes.Length; i++)
                        {
                            hash2[i] = string.Join(",", hashes[i]);
                        }
                        data.MD5Hash = string.Join(":", hash2);
                        nohash       = true;
                    }
                    break;

                    case "npctext":
                    {
                        int cnt = int.Parse(customProperties["length"], NumberStyles.Integer, NumberFormatInfo.InvariantInfo);
                        NPCTextList.Load(datafile, address, imageBase, cnt).Save(fileOutputPath, out string[][] hashes);
                        string[] hash2 = new string[hashes.Length];
                        for (int i = 0; i < hashes.Length; i++)
                        {
                            hash2[i] = string.Join(",", hashes[i]);
                        }
                        data.MD5Hash = string.Join(":", hash2);
                        nohash       = true;
                    }
                    break;

                    case "levelclearflags":
                        LevelClearFlagList.Save(LevelClearFlagList.Load(datafile, address), fileOutputPath);
                        break;

                    case "deathzone":
                    {
                        List <DeathZoneFlags> flags = new List <DeathZoneFlags>();
                        string        path          = Path.GetDirectoryName(fileOutputPath);
                        List <string> hashes        = new List <string>();
                        int           num           = 0;
                        while (ByteConverter.ToUInt32(datafile, address + 4) != 0)
                        {
                            flags.Add(new DeathZoneFlags(datafile, address));
                            string file = Path.Combine(path, num++.ToString(NumberFormatInfo.InvariantInfo) + (modelfmt == ModelFormat.Chunk ? ".sa2mdl" : ".sa1mdl"));
                            ModelFile.CreateFile(file, new NJS_OBJECT(datafile, datafile.GetPointer(address + 4, imageBase), imageBase, modelfmt, new Dictionary <int, Attach>()), null, null, null, null, modelfmt);
                            hashes.Add(HelperFunctions.FileHash(file));
                            address += 8;
                        }
                        flags.ToArray().Save(fileOutputPath);
                        hashes.Insert(0, HelperFunctions.FileHash(fileOutputPath));
                        data.MD5Hash = string.Join(",", hashes.ToArray());
                        nohash       = true;
                    }
                    break;

                    case "skyboxscale":
                    {
                        int cnt = int.Parse(customProperties["count"], NumberStyles.Integer, NumberFormatInfo.InvariantInfo);
                        SkyboxScaleList.Load(datafile, address, imageBase, cnt).Save(fileOutputPath);
                    }
                    break;

                    case "stageselectlist":
                    {
                        int cnt = int.Parse(customProperties["count"], NumberStyles.Integer, NumberFormatInfo.InvariantInfo);
                        StageSelectLevelList.Load(datafile, address, cnt).Save(fileOutputPath);
                    }
                    break;

                    case "levelrankscores":
                        LevelRankScoresList.Load(datafile, address).Save(fileOutputPath);
                        break;

                    case "levelranktimes":
                        LevelRankTimesList.Load(datafile, address).Save(fileOutputPath);
                        break;

                    case "endpos":
                        SA2EndPosList.Load(datafile, address).Save(fileOutputPath);
                        break;

                    case "animationlist":
                    {
                        int cnt = int.Parse(customProperties["count"], NumberStyles.Integer, NumberFormatInfo.InvariantInfo);
                        SA2AnimationInfoList.Load(datafile, address, cnt).Save(fileOutputPath);
                    }
                    break;

                    case "levelpathlist":
                    {
                        List <string> hashes = new List <string>();
                        ushort        lvlnum = (ushort)ByteConverter.ToUInt32(datafile, address);
                        while (lvlnum != 0xFFFF)
                        {
                            int ptr = ByteConverter.ToInt32(datafile, address + 4);
                            if (ptr != 0)
                            {
                                ptr = (int)((uint)ptr - imageBase);
                                SA1LevelAct level  = new SA1LevelAct(lvlnum);
                                string      lvldir = Path.Combine(fileOutputPath, level.ToString());
                                PathList.Load(datafile, ptr, imageBase).Save(lvldir, out string[] lvlhashes);
                                hashes.Add(level.ToString() + ":" + string.Join(",", lvlhashes));
                            }
                            address += 8;
                            lvlnum   = (ushort)ByteConverter.ToUInt32(datafile, address);
                        }
                        data.MD5Hash = string.Join("|", hashes.ToArray());
                        nohash       = true;
                    }
                    break;

                    case "pathlist":
                    {
                        PathList.Load(datafile, address, imageBase).Save(fileOutputPath, out string[] hashes);
                        data.MD5Hash = string.Join(",", hashes.ToArray());
                        nohash       = true;
                    }
                    break;

                    case "stagelightdatalist":
                        SA1StageLightDataList.Load(datafile, address).Save(fileOutputPath);
                        break;

                    case "weldlist":
                        WeldList.Load(datafile, address, imageBase).Save(fileOutputPath);
                        break;

                    case "bmitemattrlist":
                        BlackMarketItemAttributesList.Load(datafile, address, imageBase).Save(fileOutputPath);
                        break;

                    case "creditstextlist":
                        CreditsTextList.Load(datafile, address, imageBase).Save(fileOutputPath);
                        break;

                    case "animindexlist":
                    {
                        Directory.CreateDirectory(fileOutputPath);
                        List <string> hashes = new List <string>();
                        int           i      = ByteConverter.ToInt16(datafile, address);
                        while (i != -1)
                        {
                            new NJS_MOTION(datafile, datafile.GetPointer(address + 4, imageBase), imageBase, ByteConverter.ToInt16(datafile, address + 2))
                            .Save(fileOutputPath + "/" + i.ToString(NumberFormatInfo.InvariantInfo) + ".saanim");
                            hashes.Add(i.ToString(NumberFormatInfo.InvariantInfo) + ":" + HelperFunctions.FileHash(fileOutputPath + "/" + i.ToString(NumberFormatInfo.InvariantInfo) + ".saanim"));
                            address += 8;
                            i        = ByteConverter.ToInt16(datafile, address);
                        }
                        data.MD5Hash = string.Join("|", hashes.ToArray());
                        nohash       = true;
                    }
                    break;

                    case "storysequence":
                        SA2StoryList.Load(datafile, address).Save(fileOutputPath);
                        break;

                    default:                             // raw binary
                    {
                        byte[] bin = new byte[int.Parse(customProperties["size"], NumberStyles.HexNumber)];
                        Array.Copy(datafile, address, bin, 0, bin.Length);
                        File.WriteAllBytes(fileOutputPath, bin);
                    }
                    break;
                    }
                    if (!nohash)
                    {
                        data.MD5Hash = HelperFunctions.FileHash(fileOutputPath);
                    }
                    itemcount++;
                }
                if (inifile.MasterObjectList != null)
                {
                    foreach (KeyValuePair <string, MasterObjectListEntry> obj in masterobjlist)
                    {
                        KeyValuePair <string, int> name = new KeyValuePair <string, int>();
                        foreach (KeyValuePair <string, int> it in objnamecounts[obj.Key])
                        {
                            if (it.Value > name.Value)
                            {
                                name = it;
                            }
                        }
                        obj.Value.Name  = name.Key;
                        obj.Value.Names = objnamecounts[obj.Key].Select((it) => it.Key).ToArray();
                    }

                    string masterObjectListOutputPath = string.Concat(projectFolderName, inifile.MasterObjectList);

                    IniSerializer.Serialize(masterobjlist, masterObjectListOutputPath);
                }
                IniSerializer.Serialize(inifile, Path.Combine(projectFolderName, Path.GetFileNameWithoutExtension(datafilename) + "_data.ini"));
                timer.Stop();
                Console.WriteLine("Split " + itemcount + " items in " + timer.Elapsed.TotalSeconds + " seconds.");
                Console.WriteLine();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                Console.WriteLine(e.StackTrace);
                Console.WriteLine("Press any key to exit.");
                Console.ReadLine();
                return((int)SplitERRORVALUE.UnhandledException);
            }

            return((int)SplitERRORVALUE.Success);
        }
Example #5
0
 public GeoAnimData(NJS_ACTION action)
 {
     Model     = action.Model;
     Animation = action.Animation;
 }