Пример #1
0
        // Something... I forgot
        static void SplitF(string[] args)
        {
            //This code does the following:
            //1) Scan through a split INI file and find identically labelled models and motions
            //2) Add node count to the motions based on their models
            //3) Assign motions to matched models

            string inifilename;

            inifilename = args[0];
            byte[]  datafile  = File.ReadAllBytes(args[1]);
            uint    imageBase = uint.Parse(args[2], System.Globalization.NumberStyles.AllowHexSpecifier);
            IniData inifile   = IniSerializer.Deserialize <IniData>(inifilename);

            foreach (KeyValuePair <string, SA_Tools.FileInfo> fileinfo_mot in inifile.Files)
            {
                if (fileinfo_mot.Value.Type == "animation")
                {
                    string motionname = Path.GetFileNameWithoutExtension(fileinfo_mot.Value.Filename.Replace(".saanim", ""));
                    bool   sucksess   = false;
                    foreach (KeyValuePair <string, SA_Tools.FileInfo> fileinfo_mdl in inifile.Files)
                    {
                        string modelname = Path.GetFileNameWithoutExtension(fileinfo_mdl.Value.Filename.Replace(".sa1mdl", ""));
                        if (modelname == motionname)
                        {
                            //Console.WriteLine("Motion {0} fond", motionname);
                            NJS_OBJECT obj = new NJS_OBJECT(datafile, fileinfo_mdl.Value.Address, imageBase, ModelFormat.BasicDX, new Dictionary <int, Attach>());
                            //Console.WriteLine("Setting {0} model parts for motion {1}", obj.CountAnimated(), motionfilename);
                            fileinfo_mot.Value.CustomProperties.Remove("numparts");
                            fileinfo_mot.Value.CustomProperties.Add("numparts", obj.CountAnimated().ToString());
                            fileinfo_mdl.Value.CustomProperties.Remove("animations");
                            fileinfo_mdl.Value.CustomProperties.Add("animations", Path.GetFileName(fileinfo_mot.Value.Filename));
                            sucksess = true;
                        }
                    }
                    if (!sucksess)
                    {
                        Console.WriteLine("Model not found for {0}", fileinfo_mot.Value.Filename);
                    }
                }
            }
            IniSerializer.Serialize(inifile, "motions.ini");
            return;
        }
Пример #2
0
        static void Main(string[] args)
        {
            string[] arguments = Environment.GetCommandLineArgs();
            Game     game;
            string   filename;
            string   dir       = Environment.CurrentDirectory;
            bool     bigendian = false;

            if (args.Length == 0)
            {
                Console.WriteLine("USplit is a tool that lets you extract any data supported by SA Tools from any binary file.");
                Console.WriteLine("Usage: usplit <GAME> <FILENAME> <KEY> <TYPE> <ADDRESS> <PARAMETER1> <PARAMETER2> [-name <NAME>]\n");
                Console.WriteLine("Argument description:");
                Console.WriteLine("<GAME>: SA1, SADX, SA2, SA2B. Add '_b' (e.g. SADX_b) to switch to Big Endian.\n");
                Console.WriteLine("<FILENAME>: The name of the binary file, e.g. sonic.exe.\n");
                Console.WriteLine("<KEY>: Binary key, e.g. 400000 for sonic.exe or C900000 for SA1 STG file.\n");
                Console.WriteLine("<TYPE>: One of the following:\n" +
                                  "binary <length> [hex],\nlandtable, model, basicmodel, basicdxmodel, chunkmodel, gcmodel, action, animation <NJS_OBJECT address> [shortrot],\n" +
                                  "objlist, startpos, texlist, leveltexlist, triallevellist, bosslevellist, fieldstartpos, soundlist, soundtestlist,\nnextlevellist, " +
                                  "levelclearflags, deathzone, levelrankscores, levelranktimes, endpos, levelpathlist, pathlist,\nstagelightdatalist, weldlist" +
                                  "bmitemattrlist, creditstextlist, animindexlist, storysequence, musiclist <count>,\n" +
                                  "stringarray <count> [language], skyboxscale <count>, stageselectlist <count>, animationlist <count>,\n" +
                                  "masterstringlist <count>, cutscenetext <count>, recapscreen <count>, npctext <count>\n");
                Console.WriteLine("<ADDRESS>: The location of data in the file.\n");
                Console.WriteLine("<PARAMETER1>: length, count, secondary address etc. depending on data type\n");
                Console.WriteLine("<PARAMETER2>: 'hex' for binary to read length as hexadecimal, 'shortrot' for animation to read rotation as short\n");
                Console.WriteLine("<NAME>: Output file name (optional)\n");
                Console.WriteLine("Press ENTER to exit");
                Console.ReadLine();
                return;
            }
            //Args list: game, filename, key, type, address, [address2/count], [language], [name]
            switch (args[0])
            {
            case "SA1":
                game = Game.SA1;
                break;

            case "SA1_b":
                game      = Game.SA1;
                bigendian = true;
                break;

            case "SADX":
                game = Game.SADX;
                break;

            case "SADX_b":
                game      = Game.SADX;
                bigendian = true;
                break;

            case "SA2":
                game = Game.SA2;
                break;

            case "SA2_b":
                game      = Game.SA2;
                bigendian = true;
                break;

            case "SA2B":
                game = Game.SA2B;
                break;

            case "SA2B_b":
                game      = Game.SA2B;
                bigendian = true;
                break;

            default:
                return;
            }
            string model_extension     = ".sa1mdl";
            string landtable_extension = ".sa1lvl";

            ByteConverter.BigEndian = SonicRetro.SAModel.ByteConverter.BigEndian = bigendian;
            filename = args[1];
            byte[] datafile = File.ReadAllBytes(filename);
            if (Path.GetExtension(filename).ToLowerInvariant() == ".prs")
            {
                datafile = FraGag.Compression.Prs.Decompress(datafile);
            }
            Environment.CurrentDirectory = Path.Combine(Environment.CurrentDirectory, Path.GetDirectoryName(filename));
            uint            imageBase = uint.Parse(args[2], NumberStyles.AllowHexSpecifier);
            string          type      = args[3];
            int             address   = int.Parse(args[4], NumberStyles.AllowHexSpecifier);
            bool            SA2       = game == Game.SA2 | game == Game.SA2B;
            ModelFormat     modelfmt  = ModelFormat.BasicDX;
            LandTableFormat landfmt   = LandTableFormat.SADX;

            switch (game)
            {
            case Game.SA1:
                modelfmt            = ModelFormat.Basic;
                landfmt             = LandTableFormat.SA1;
                model_extension     = ".sa1mdl";
                landtable_extension = ".sa1lvl";
                break;

            case Game.SADX:
                modelfmt            = ModelFormat.BasicDX;
                landfmt             = LandTableFormat.SADX;
                model_extension     = ".sa1mdl";
                landtable_extension = ".sa1lvl";
                break;

            case Game.SA2:
                modelfmt            = ModelFormat.Chunk;
                landfmt             = LandTableFormat.SA2;
                model_extension     = ".sa2mdl";
                landtable_extension = ".sa2lvl";
                break;

            case Game.SA2B:
                modelfmt            = ModelFormat.Chunk;
                landfmt             = LandTableFormat.SA2B;
                model_extension     = ".sa2mdl";
                landtable_extension = ".sa2blvl";
                break;
            }
            Dictionary <string, MasterObjectListEntry>     masterobjlist = new Dictionary <string, MasterObjectListEntry>();
            Dictionary <string, Dictionary <string, int> > objnamecounts = new Dictionary <string, Dictionary <string, int> >();
            string fileOutputPath = dir + "\\" + address.ToString("X");

            Console.WriteLine("Game: {0}, file: {1}, key: 0x{2}, splitting {3} at 0x{4}", game.ToString(), filename, imageBase.ToString("X"), type, address.ToString("X"));
            if (args[args.Length - 2] == "-name")
            {
                fileOutputPath = dir + "\\" + args[args.Length - 1];
                Console.WriteLine("Name: {0}", args[args.Length - 1]);
            }
            switch (type)
            {
            case "landtable":
                new LandTable(datafile, address, imageBase, landfmt).SaveToFile(fileOutputPath + landtable_extension, landfmt);
                break;

            case "model":
            {
                NJS_OBJECT mdl = new NJS_OBJECT(datafile, address, imageBase, modelfmt, new Dictionary <int, Attach>());
                ModelFile.CreateFile(fileOutputPath + model_extension, mdl, null, null, null, null, modelfmt);
            }
            break;

            case "basicmodel":
            {
                NJS_OBJECT mdl = new NJS_OBJECT(datafile, address, imageBase, ModelFormat.Basic, new Dictionary <int, Attach>());
                ModelFile.CreateFile(fileOutputPath + ".sa1mdl", mdl, null, null, null, null, ModelFormat.Basic);
            }
            break;

            case "basicdxmodel":
            {
                NJS_OBJECT mdl = new NJS_OBJECT(datafile, address, imageBase, ModelFormat.BasicDX, new Dictionary <int, Attach>());
                ModelFile.CreateFile(fileOutputPath + ".sa1mdl", mdl, null, null, null, null, ModelFormat.BasicDX);
            }
            break;

            case "chunkmodel":
            {
                NJS_OBJECT mdl = new NJS_OBJECT(datafile, address, imageBase, ModelFormat.Chunk, new Dictionary <int, Attach>());
                ModelFile.CreateFile(fileOutputPath + ".sa2mdl", mdl, null, null, null, null, ModelFormat.Chunk);
            }
            break;

            case "gcmodel":
            {
                NJS_OBJECT mdl = new NJS_OBJECT(datafile, address, imageBase, ModelFormat.GC, new Dictionary <int, Attach>());
                ModelFile.CreateFile(fileOutputPath + ".sa2mdl", mdl, null, null, null, null, ModelFormat.GC);
            }
            break;

            case "action":
            {
                NJS_ACTION ani = new NJS_ACTION(datafile, address, imageBase, modelfmt, new Dictionary <int, Attach>());
                ani.Animation.Save(fileOutputPath + ".saanim");
                string[]   mdlanis = new string[0];
                NJS_OBJECT mdl     = ani.Model;
                mdlanis = (fileOutputPath + ".saanim").Split(',');
                ModelFile.CreateFile(fileOutputPath + "_model" + model_extension, mdl, mdlanis, null, null, null, modelfmt);
            }
            break;

            case "animation":
            {
                bool shortrot_enabled = false;
                if (args.Length > 6 && args[6] == "shortrot")
                {
                    shortrot_enabled = true;
                }
                NJS_OBJECT mdl = new NJS_OBJECT(datafile, int.Parse(args[5], NumberStyles.AllowHexSpecifier), imageBase, modelfmt, new Dictionary <int, Attach>());
                new NJS_MOTION(datafile, address, imageBase, mdl.CountAnimated(), shortrot: shortrot_enabled).Save(fileOutputPath + ".saanim");
                string[] mdlanis = new string[0];
                mdlanis = (fileOutputPath + ".saanim").Split(',');
                ModelFile.CreateFile(fileOutputPath + "_model" + model_extension, mdl, mdlanis, null, null, null, modelfmt);
            }
            break;

            case "objlist":
            {
                ObjectListEntry[] objs = ObjectList.Load(datafile, address, imageBase, SA2);
                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 + ".ini");
            }
            break;

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

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

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

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

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

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

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

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

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

            case "stringarray":
            {
                int       cnt  = int.Parse(args[5], NumberStyles.Integer, NumberFormatInfo.InvariantInfo);
                Languages lang = Languages.Japanese;
                if (args.Length > 6)
                {
                    lang = (Languages)Enum.Parse(typeof(Languages), args[6], true);
                }
                StringArray.Load(datafile, address, imageBase, cnt, lang).Save(fileOutputPath + ".txt");
            }
            break;

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

            case "cutscenetext":
            {
                int cnt = int.Parse(args[5], NumberStyles.Integer, NumberFormatInfo.InvariantInfo);
                new CutsceneText(datafile, address, imageBase, cnt).Save(fileOutputPath + ".txt", out string[] hashes);
            }
            break;

            case "recapscreen":
            {
                int cnt = int.Parse(args[5], NumberStyles.Integer, NumberFormatInfo.InvariantInfo);
                RecapScreenList.Load(datafile, address, imageBase, cnt).Save(fileOutputPath + ".txt", out string[][] hashes);
            }
            break;

            case "npctext":
            {
                int cnt = int.Parse(args[5], NumberStyles.Integer, NumberFormatInfo.InvariantInfo);
                NPCTextList.Load(datafile, address, imageBase, cnt).Save(fileOutputPath + ".txt", out string[][] hashes);
            }
            break;

            case "levelclearflags":
                LevelClearFlagList.Save(LevelClearFlagList.Load(datafile, address), fileOutputPath + ".ini");
                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);
                    address += 8;
                }
                flags.ToArray().Save(fileOutputPath + ".ini");
            }
            break;

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

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

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

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

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

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

            case "levelpathlist":
            {
                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);
                    }
                    address += 8;
                    lvlnum   = (ushort)ByteConverter.ToUInt32(datafile, address);
                }
            }
            break;

            case "pathlist":
            {
                PathList.Load(datafile, address, imageBase).Save(fileOutputPath, out string[] hashes);
            }
            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);
                }
            }
            break;

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

            case "masterstringlist":
            {
                int cnt = int.Parse(args[5], NumberStyles.Integer, NumberFormatInfo.InvariantInfo);
                for (int l = 0; l < 5; l++)
                {
                    Languages            lng = (Languages)l;
                    System.Text.Encoding enc = HelperFunctions.GetEncoding(game, lng);
                    string ld = Path.Combine(fileOutputPath, lng.ToString());
                    Directory.CreateDirectory(ld);
                    int ptr = datafile.GetPointer(address, imageBase);
                    for (int i = 0; i < cnt; i++)
                    {
                        int ptr2 = datafile.GetPointer(ptr, imageBase);
                        if (ptr2 != 0)
                        {
                            string fn = Path.Combine(ld, $"{i}.txt");
                            File.WriteAllText(fn, datafile.GetCString(ptr2, enc).Replace("\n", "\r\n"));
                        }
                        ptr += 4;
                    }
                    address += 4;
                }
            }
            break;

            case "binary":
            {
                int length;
                if (args.Length > 6 && args[6] == "hex")
                {
                    length = int.Parse(args[5], NumberStyles.AllowHexSpecifier);
                }
                else
                {
                    length = int.Parse(args[5]);
                }
                byte[] bin = new byte[length];
                Array.Copy(datafile, address, bin, 0, bin.Length);
                File.WriteAllBytes(fileOutputPath + ".bin", bin);
                Console.WriteLine("Length: {0} (0x{1}) bytes", length.ToString(), length.ToString("X"));
            }
            break;

            default:
                break;
            }
        }
Пример #3
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>();
            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     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, 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":
                {
                    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;
                }
                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);
        }
Пример #4
0
 private void LoadFile(string filename)
 {
     loaded = false;
     Environment.CurrentDirectory = Path.GetDirectoryName(filename);
     timer1.Stop();
     modelFile  = null;
     animation  = null;
     animations = null;
     animnum    = -1;
     animframe  = 0;
     if (ModelFile.CheckModelFile(filename))
     {
         modelFile  = new ModelFile(filename);
         outfmt     = modelFile.Format;
         model      = modelFile.Model;
         animations = new Animation[modelFile.Animations.Count];
         modelFile.Animations.CopyTo(animations, 0);
     }
     else
     {
         byte[] file = File.ReadAllBytes(filename);
         if (Path.GetExtension(filename).Equals(".prs", StringComparison.OrdinalIgnoreCase))
         {
             file = FraGag.Compression.Prs.Decompress(file);
         }
         SA_Tools.ByteConverter.BigEndian = false;
         uint?baseaddr = SA_Tools.HelperFunctions.SetupEXE(ref file);
         if (baseaddr.HasValue)
         {
             modelinfo.numericUpDown2.Value   = baseaddr.Value;
             modelinfo.numericUpDown2.Enabled = false;
             modelinfo.ComboBox1.Enabled      = false;
             modelinfo.checkBox2.Checked      = modelinfo.checkBox2.Enabled = false;
             LoadBinFile(file);
         }
         else if (Path.GetExtension(filename).Equals(".rel", StringComparison.OrdinalIgnoreCase))
         {
             SA_Tools.ByteConverter.BigEndian = true;
             SA_Tools.HelperFunctions.FixRELPointers(file);
             modelinfo.numericUpDown2.Value   = 0;
             modelinfo.numericUpDown2.Enabled = false;
             modelinfo.ComboBox1.Enabled      = false;
             modelinfo.checkBox2.Enabled      = false;
             modelinfo.checkBox2.Checked      = true;
             LoadBinFile(file);
         }
         else
         {
             using (FileTypeDialog ftd = new FileTypeDialog())
             {
                 if (ftd.ShowDialog(this) != DialogResult.OK)
                 {
                     return;
                 }
                 if (ftd.typBinary.Checked)
                 {
                     modelinfo.numericUpDown2.Enabled = true;
                     modelinfo.ComboBox1.Enabled      = true;
                     modelinfo.checkBox2.Enabled      = true;
                     LoadBinFile(file);
                 }
                 else if (ftd.typSA2MDL.Checked | ftd.typSA2BMDL.Checked)
                 {
                     ModelFormat fmt = outfmt = ModelFormat.Chunk;
                     ByteConverter.BigEndian = ftd.typSA2BMDL.Checked;
                     using (SA2MDLDialog dlg = new SA2MDLDialog())
                     {
                         int address = 0;
                         SortedDictionary <int, NJS_OBJECT> sa2models = new SortedDictionary <int, NJS_OBJECT>();
                         int i = ByteConverter.ToInt32(file, address);
                         while (i != -1)
                         {
                             sa2models.Add(i, new NJS_OBJECT(file, ByteConverter.ToInt32(file, address + 4), 0, fmt));
                             address += 8;
                             i        = ByteConverter.ToInt32(file, address);
                         }
                         foreach (KeyValuePair <int, NJS_OBJECT> item in sa2models)
                         {
                             dlg.modelChoice.Items.Add(item.Key + ": " + item.Value.Name);
                         }
                         dlg.ShowDialog(this);
                         i = 0;
                         foreach (KeyValuePair <int, NJS_OBJECT> item in sa2models)
                         {
                             if (i == dlg.modelChoice.SelectedIndex)
                             {
                                 model = item.Value;
                                 break;
                             }
                             i++;
                         }
                         if (dlg.checkBox1.Checked)
                         {
                             using (OpenFileDialog anidlg = new OpenFileDialog()
                             {
                                 DefaultExt = "bin",
                                 Filter = "Motion Files|*MTN.BIN;*MTN.PRS|All Files|*.*"
                             })
                             {
                                 if (anidlg.ShowDialog(this) == DialogResult.OK)
                                 {
                                     byte[] anifile = File.ReadAllBytes(anidlg.FileName);
                                     if (Path.GetExtension(anidlg.FileName).Equals(".prs", StringComparison.OrdinalIgnoreCase))
                                     {
                                         anifile = FraGag.Compression.Prs.Decompress(anifile);
                                     }
                                     address = 0;
                                     SortedDictionary <int, Animation> anis = new SortedDictionary <int, Animation>();
                                     i = ByteConverter.ToInt32(file, address);
                                     while (i != -1)
                                     {
                                         anis.Add(i, new Animation(file, ByteConverter.ToInt32(file, address + 4), 0, model.CountAnimated()));
                                         address += 8;
                                         i        = ByteConverter.ToInt32(file, address);
                                     }
                                     animations = new List <Animation>(anis.Values).ToArray();
                                 }
                             }
                         }
                     }
                 }
             }
         }
     }
     model.ProcessVertexData();
     NJS_OBJECT[] models = model.GetObjects();
     meshes = new Mesh[models.Length];
     for (int i = 0; i < models.Length; i++)
     {
         if (models[i].Attach != null)
         {
             try { meshes[i] = models[i].Attach.CreateD3DMesh(d3ddevice); }
             catch { }
         }
     }
     treeView1.Nodes.Clear();
     nodeDict = new Dictionary <NJS_OBJECT, TreeNode>();
     AddTreeNode(model, treeView1.Nodes);
     loaded         = saveToolStripMenuItem.Enabled = exportToolStripMenuItem.Enabled = findToolStripMenuItem.Enabled = true;
     selectedObject = model;
     SelectedItemChanged();
 }
Пример #5
0
 static bool CompareModels(NJS_OBJECT model1, NJS_OBJECT model2)
 {
     if (model1.GetFlags() != model2.GetFlags())
     {
         return(false);
     }
     if (model1.Position.X != model2.Position.X)
     {
         return(false);
     }
     if (model1.Position.Y != model2.Position.Y)
     {
         return(false);
     }
     if (model1.Position.Z != model2.Position.Z)
     {
         return(false);
     }
     if (model1.Rotation.X != model2.Rotation.X)
     {
         return(false);
     }
     if (model1.Rotation.Y != model2.Rotation.Y)
     {
         return(false);
     }
     if (model1.Rotation.Z != model2.Rotation.Z)
     {
         return(false);
     }
     if (model1.Scale.X != model2.Scale.X)
     {
         return(false);
     }
     if (model1.Scale.Y != model2.Scale.Y)
     {
         return(false);
     }
     if (model1.Scale.Z != model2.Scale.Z)
     {
         return(false);
     }
     if (model1.CountAnimated() != model2.CountAnimated())
     {
         return(false);
     }
     if (model1.Attach != null && model2.Attach != null)
     {
         BasicAttach attach1 = (BasicAttach)model1.Attach;
         BasicAttach attach2 = (BasicAttach)model2.Attach;
         if (attach1.Material.Count != attach2.Material.Count)
         {
             return(false);
         }
         if (attach1.Vertex.Length != attach2.Vertex.Length)
         {
             return(false);
         }
         if (attach1.Normal.Length != attach2.Normal.Length)
         {
             return(false);
         }
         if (attach1.Mesh.Count != attach2.Mesh.Count)
         {
             return(false);
         }
     }
     return(true);
 }