Beispiel #1
0
        private static string GetMotion(byte[] fc, int address, uint key, string fn, List <NJS_MOTION> motions, int cnt)
        {
            NJS_MOTION mtn = null;

            if (motions != null)
            {
                mtn = motions[ByteConverter.ToInt32(fc, address)];
            }
            else
            {
                int ptr3 = fc.GetPointer(address, key);
                if (ptr3 != 0)
                {
                    mtn = new NJS_MOTION(fc, ptr3, key, cnt);
                }
            }
            if (mtn == null)
            {
                return(null);
            }
            if (!motionfiles.ContainsKey(mtn.Name) || motionfiles[mtn.Name].Filename == null)
            {
                motionfiles[mtn.Name] = new MotionInfo(fn, mtn);
            }
            return(mtn.Name);
        }
Beispiel #2
0
 public EventEntity(byte[] file, int address, uint imageBase, bool battle, Dictionary <string, NJS_OBJECT> models, List <NJS_MOTION> motions)
 {
     Model = Event.GetModel(file, address, imageBase, models);
     if (battle)
     {
         Motion      = motions[ByteConverter.ToInt32(file, address + 4)];
         ShapeMotion = motions[ByteConverter.ToInt32(file, address + 8)];
         ShadowModel = Event.GetModel(file, address + 16, imageBase, models);
         Position    = new Vertex(file, address + 24);
         Flags       = ByteConverter.ToUInt32(file, address + 40);
     }
     else
     {
         int ptr = file.GetPointer(address + 4, imageBase);
         if (ptr != 0)
         {
             Motion = new NJS_MOTION(file, ptr, imageBase, Model.CountAnimated());
         }
         ptr = file.GetPointer(address + 8, imageBase);
         if (ptr != 0)
         {
             ShapeMotion = new NJS_MOTION(file, ptr, imageBase, Model.CountMorph());
         }
         Position = new Vertex(file, address + 16);
         Flags    = ByteConverter.ToUInt32(file, address + 28);
     }
 }
Beispiel #3
0
 private static void Convert(string[] args)
 {
     foreach (string filename in args)
     {
         Console.WriteLine(filename);
         removedFrames = 0;
         NJS_MOTION mtn = NJS_MOTION.Load(filename);
         foreach (var node in mtn.Models)
         {
             CheckValues(node.Value.Position);
             CheckValues(node.Value.Rotation);
             CheckValues(node.Value.Scale);
             CheckValues(node.Value.Vector);
             CheckValues(node.Value.Vertex);
             CheckValues(node.Value.Normal);
             CheckValues(node.Value.Target);
             CheckValues(node.Value.Roll);
             CheckValues(node.Value.Angle);
             CheckValues(node.Value.Color);
             CheckValues(node.Value.Intensity);
             CheckValues(node.Value.Spot);
             CheckValues(node.Value.Point);
             CheckValues(node.Value.Quaternion);
         }
         if (removedFrames > 0)
         {
             Console.WriteLine("Removed {0} frame{1}.", removedFrames, removedFrames == 1 ? "" : "s");
             mtn.Save(filename);
         }
     }
 }
Beispiel #4
0
        public GeoAnimData(byte[] file, int address, uint imageBase, LandTableFormat format, Dictionary <int, string> labels, Dictionary <int, Attach> attaches)
        {
            ModelFormat mfmt = 0;

            switch (format)
            {
            case LandTableFormat.SA1:
                mfmt = ModelFormat.Basic;
                break;

            case LandTableFormat.SADX:
                mfmt = ModelFormat.BasicDX;
                break;

            case LandTableFormat.SA2:
                mfmt = ModelFormat.Chunk;
                break;
            }
            Unknown1  = ByteConverter.ToInt32(file, address);
            Unknown2  = ByteConverter.ToSingle(file, address + 4);
            Unknown3  = ByteConverter.ToSingle(file, address + 8);
            Model     = new NJS_OBJECT(file, (int)(ByteConverter.ToUInt32(file, address + 0xC) - imageBase), imageBase, mfmt, labels, attaches);
            Animation = NJS_MOTION.ReadHeader(file, (int)(ByteConverter.ToUInt32(file, address + 0x10) - imageBase), imageBase, mfmt, labels, attaches);
            Unknown4  = ByteConverter.ToInt32(file, address + 0x14);
        }
Beispiel #5
0
        private static void Convert(string[] args)
        {
            foreach (string filename in args)
            {
                Console.WriteLine(filename);
                JsonSerializer js = new JsonSerializer()
                {
                    Culture = System.Globalization.CultureInfo.InvariantCulture
                };
                switch (Path.GetExtension(filename).ToLowerInvariant())
                {
                case ".saanim":
                    using (TextWriter tw = File.CreateText(Path.ChangeExtension(filename, ".json")))
                        using (JsonTextWriter jtw = new JsonTextWriter(tw)
                        {
                            Formatting = Formatting.Indented
                        })
                            js.Serialize(jtw, NJS_MOTION.Load(filename));
                    break;

                case ".json":
                    using (TextReader tr = File.OpenText(filename))
                        using (JsonTextReader jtr = new JsonTextReader(tr))
                            js.Deserialize <NJS_MOTION>(jtr).Save(Path.ChangeExtension(filename, ".saanim"));
                    break;

                default:
                    Console.WriteLine("Unknown file type.");
                    return;
                }
            }
        }
Beispiel #6
0
 static void Main(string[] args)
 {
     if (args.Length == 0)
     {
         Console.Write("Filename: ");
         args = new string[] { Console.ReadLine().Trim('"') };
     }
     foreach (string filename in args)
     {
         byte[] fc;
         if (Path.GetExtension(filename).Equals(".prs", StringComparison.OrdinalIgnoreCase))
         {
             fc = Prs.Decompress(filename);
         }
         else
         {
             fc = File.ReadAllBytes(filename);
         }
         string         path = Path.Combine(Path.GetDirectoryName(Path.GetFullPath(filename)), Path.GetFileNameWithoutExtension(filename));
         JsonSerializer js   = new JsonSerializer();
         EventIniData   ini;
         using (TextReader tr = File.OpenText(Path.Combine(path, Path.ChangeExtension(Path.GetFileName(filename), ".json"))))
             using (JsonTextReader jtr = new JsonTextReader(tr))
                 ini = js.Deserialize <EventIniData>(jtr);
         uint key;
         if (fc[0] == 0x81)
         {
             ByteConverter.BigEndian = true;
             key = 0x8125FE60;
         }
         else
         {
             ByteConverter.BigEndian = false;
             key = 0xC600000;
         }
         bool        battle               = ini.Game == Game.SA2B;
         List <byte> modelbytes           = new List <byte>(fc);
         Dictionary <string, uint> labels = new Dictionary <string, uint>();
         foreach (string file in ini.Files.Where(a => a.Key.EndsWith(".sa2mdl", StringComparison.OrdinalIgnoreCase) && HelperFunctions.FileHash(Path.Combine(path, a.Key)) != a.Value).Select(a => a.Key))
         {
             modelbytes.AddRange(new ModelFile(Path.Combine(path, file)).Model.GetBytes((uint)(key + modelbytes.Count), false, labels, out uint _));
         }
         if (battle)
         {
             List <byte> motionbytes             = new List <byte>(new byte[(ini.Motions.Count + 1) * 8]);
             Dictionary <string, int> partcounts = new Dictionary <string, int>(ini.Motions.Count);
             foreach (string file in ini.Files.Where(a => a.Key.EndsWith(".saanim", StringComparison.OrdinalIgnoreCase)).Select(a => a.Key))
             {
                 NJS_MOTION motion = NJS_MOTION.Load(Path.Combine(path, file));
                 motionbytes.AddRange(motion.GetBytes((uint)(key + motionbytes.Count), labels, out uint _));
                 partcounts.Add(motion.Name, motion.ModelParts);
             }
             byte[] mfc = motionbytes.ToArray();
             for (int i = 0; i < ini.Motions.Count; i++)
             {
                 if (ini.Motions[i] == null)
                 {
                     new byte[] { 0xFF, 0xFF, 0xFF, 0xFF }
                 }
Beispiel #7
0
 public GeoAnimData(NJS_OBJECT model, NJS_MOTION animation)
 {
     Model                = model;
     Animation            = animation;
     MaxFrame             = animation.Frames;
     AnimationSpeed       = 1.0f;
     Animation.ActionName = "action_" + Extensions.GenerateIdentifier();
     Animation.ObjectName = model.Name;
 }
Beispiel #8
0
        // Scan for Actions in a specific range
        static int ScanActions(uint addr, uint nummdl, ModelFormat modelfmt)
        {
            int count = 0;

            ByteConverter.BigEndian = BigEndian;
            if (nummdl == 0)
            {
                return(0);
            }
            for (uint address = addr; address < datafile.Length - 8; address += 1)
            {
                CurrentAddress = address;
                if (CancelScan)
                {
                    break;
                }
                if (ByteConverter.ToUInt32(datafile, (int)address) != addr + ImageBase)
                {
                    continue;
                }
                uint motaddr = ByteConverter.ToUInt32(datafile, (int)address + 4);
                if (motaddr < ImageBase)
                {
                    continue;
                }
                try
                {
                    NJS_MOTION mot = new NJS_MOTION(datafile, (int)(motaddr - ImageBase), ImageBase, (int)nummdl, null, false);
                    if (mot.Models.Count == 0)
                    {
                        continue;
                    }
                    addresslist.Add(motaddr - ImageBase, "NJS_MOTION");
                    Console.WriteLine("\rMotion found for model {0} at address {1}", addr.ToString("X8"), (motaddr - ImageBase).ToString("X"));
                    string fileOutputPath = Path.Combine(OutputFolder, "actions", (motaddr - ImageBase).ToString("X8"));
                    if (SingleOutputFolder)
                    {
                        fileOutputPath = Path.Combine(OutputFolder, (motaddr - ImageBase).ToString("X8"));
                    }
                    mot.Save(fileOutputPath + ".saanim", NoMeta);
                    uint[] arr = new uint[2];
                    arr[0] = addr;
                    arr[1] = nummdl;
                    actionlist.Add(motaddr - ImageBase, arr);
                    AddAction(addr, motaddr - ImageBase);
                    address += 7;
                    count++;
                }
                catch (Exception)
                {
                    continue;
                }
            }
            return(count);
        }
Beispiel #9
0
        public void ProcessShapeMotionVertexData(NJS_MOTION motion, int frame)
        {
            int        animindex = -1;
            NJS_OBJECT obj       = this;

            do
            {
                obj.ProcessShapeMotionVertexData(motion, frame, ref animindex);
                obj = obj.Sibling;
            } while (obj != null);
        }
Beispiel #10
0
        public static void BuildNBFile(string filename, string dest, int verbose = 0)
        {
            // Needs update to use filenames from an INI file
            Dictionary <int, string> sectionlist = IniSerializer.Deserialize <Dictionary <int, string> >(filename);
            List <byte> result = new List <byte>();

            result.AddRange(BitConverter.GetBytes(0x04424A4E));
            int numfiles = sectionlist.Count;

            result.AddRange(BitConverter.GetBytes(numfiles));
            foreach (var item in sectionlist)
            {
                string insidepath = Path.Combine(Environment.CurrentDirectory, Path.GetFileNameWithoutExtension(filename), item.Key.ToString("D2"));
                byte[] writeout;
                // Convert models and motions to BIN
                if (item.Value != "NULL")
                {
                    switch (Path.GetExtension(item.Value).ToLowerInvariant())
                    {
                    case ".sa1mdl":
                        ModelFile mdlfile = new ModelFile(insidepath + ".sa1mdl");
                        writeout = GetSections(mdlfile.Model);
                        result.AddRange(BitConverter.GetBytes((ushort)1));
                        result.AddRange(BitConverter.GetBytes((ushort)0xCDCD));
                        result.AddRange(BitConverter.GetBytes((uint)writeout.Length));
                        result.AddRange(writeout);
                        File.WriteAllBytes(insidepath + ".bin", writeout);
                        break;

                    case ".saanim":
                        NJS_MOTION mot = NJS_MOTION.Load(insidepath + ".saanim");
                        if (verbose > 1)
                        {
                            Console.WriteLine("Section {0}", item.Key);
                        }
                        writeout = GetSections(mot, verbose);
                        result.AddRange(BitConverter.GetBytes((ushort)3));
                        result.AddRange(BitConverter.GetBytes((ushort)0xCDCD));
                        result.AddRange(BitConverter.GetBytes((uint)writeout.Length));
                        result.AddRange(writeout);
                        File.WriteAllBytes(insidepath + ".bin", writeout);
                        break;
                    }
                }
                else
                {
                    result.AddRange(BitConverter.GetBytes((ushort)0));
                    result.AddRange(BitConverter.GetBytes((ushort)0xCDCD));
                    result.AddRange(BitConverter.GetBytes((uint)0));
                }
                //Build the NB file
                File.WriteAllBytes(dest, result.ToArray());
            }
        }
Beispiel #11
0
        public override void ProcessShapeMotionVertexData(NJS_MOTION motion, float frame, int animindex)
        {
            if (!motion.Models.ContainsKey(animindex))
            {
                ProcessVertexData();
                return;
            }
#if modellog
            Extensions.Log("Processing Chunk Attach " + Name + Environment.NewLine);
#endif
            if (Vertex != null)
            {
                foreach (VertexChunk chunk in Vertex)
                {
#if modellog
                    Extensions.Log("Vertex Declaration: " + chunk.IndexOffset + "-" + (chunk.IndexOffset + chunk.VertexCount - 1) + Environment.NewLine);
#endif
                    if (VertexBuffer.Length < chunk.IndexOffset + chunk.VertexCount)
                    {
                        Array.Resize(ref VertexBuffer, chunk.IndexOffset + chunk.VertexCount);
                    }
                    Vertex[]      vertdata = chunk.Vertices.ToArray();
                    Vertex[]      normdata = chunk.Normals.ToArray();
                    AnimModelData data     = motion.Models[animindex];
                    if (data.Vertex.Count > 0)
                    {
                        vertdata = data.GetVertex(frame);
                    }
                    if (data.Normal.Count > 0)
                    {
                        normdata = data.GetNormal(frame);
                    }
                    for (int i = 0; i < chunk.VertexCount; i++)
                    {
                        VertexBuffer[i + chunk.IndexOffset] = new VertexData(vertdata[i]);
                        if (normdata.Length > 0)
                        {
                            VertexBuffer[i + chunk.IndexOffset].Normal = normdata[i];
                        }
                        if (chunk.Diffuse.Count > 0)
                        {
                            VertexBuffer[i + chunk.IndexOffset].Color = chunk.Diffuse[i];
                        }
                    }
                }
            }
            List <MeshInfo> result = new List <MeshInfo>();
            if (Poly != null)
            {
                result = ProcessPolyList(PolyName, Poly, 0);
            }
            MeshInfo = result.ToArray();
        }
Beispiel #12
0
        public static void ExportINI(DllIniData IniData,
                                     Dictionary <string, bool> itemsToExport, string fileName)
        {
            string     dstfol = Path.GetDirectoryName(fileName);
            DllIniData output = new DllIniData()
            {
                Name     = IniData.Name,
                Game     = IniData.Game,
                Exports  = IniData.Exports,
                TexLists = IniData.TexLists
            };
            List <string> labels = new List <string>();

            foreach (KeyValuePair <string, FileTypeHash> item in
                     IniData.Files.Where(i => itemsToExport[i.Key]))
            {
                Directory.CreateDirectory(Path.GetDirectoryName(Path.Combine(dstfol, item.Key)));
                File.Copy(item.Key, Path.Combine(dstfol, item.Key), true);
                switch (item.Value.Type)
                {
                case "landtable":
                    LandTable tbl = LandTable.LoadFromFile(item.Key);
                    labels.AddRange(tbl.GetLabels());
                    break;

                case "model":
                case "basicmodel":
                case "chunkmodel":
                case "gcmodel":
                case "basicdxmodel":
                    NJS_OBJECT mdl = new ModelFile(item.Key).Model;
                    labels.AddRange(mdl.GetLabels());
                    break;

                case "animation":
                    NJS_MOTION ani = NJS_MOTION.Load(item.Key);
                    labels.Add(ani.Name);
                    break;
                }
                output.Files.Add(item.Key, new FileTypeHash(item.Value.Type, null));
            }
            output.Items = new List <DllItemInfo>(IniData.Items.Where(a => labels.Contains(a.Label)));
            foreach (var item in IniData.DataItems.Where(i => itemsToExport[i.Filename]))
            {
                Directory.CreateDirectory(Path.Combine(dstfol, item.Filename));
                CopyDirectory(new DirectoryInfo(item.Filename), Path.Combine(dstfol, item.Filename));
                output.DataItems.Add(item);
            }
            IniSerializer.Serialize(output, fileName);
        }
Beispiel #13
0
 private void ProcessShapeMotionVertexData(NJS_MOTION motion, int frame, ref int animindex)
 {
     if (Morph)
     {
         animindex++;
     }
     if (Attach != null)
     {
         Attach.ProcessShapeMotionVertexData(motion, frame, animindex);
     }
     foreach (NJS_OBJECT item in Children)
     {
         item.ProcessShapeMotionVertexData(motion, frame, ref animindex);
     }
 }
Beispiel #14
0
        private static void ProcessMTN(string fn, Dictionary <int, NJS_MOTION> mtns)
        {
            byte[] file = File.ReadAllBytes(fn);
            if (Path.GetExtension(fn).Equals(".prs", StringComparison.OrdinalIgnoreCase))
            {
                file = FraGag.Compression.Prs.Decompress(file);
            }
            ByteConverter.BigEndian = file[2] == 0;
            int address = 0;
            int i       = ByteConverter.ToInt16(file, address);

            while (i != -1)
            {
                int aniaddr = ByteConverter.ToInt32(file, address + 4);
                mtns[i]  = new NJS_MOTION(file, aniaddr, 0, ByteConverter.ToInt16(file, address + 2));
                address += 8;
                i        = ByteConverter.ToInt16(file, address);
            }
        }
Beispiel #15
0
        static void Main(string[] args)
        {
            string filename;

            Console.Write("File: ");
            if (args.Length > 0)
            {
                Console.WriteLine(filename = args[0]);
            }
            else
            {
                filename = Console.ReadLine().Trim('"');
            }
            JsonSerializer js = new JsonSerializer()
            {
                Culture = System.Globalization.CultureInfo.InvariantCulture
            };

            switch (Path.GetExtension(filename).ToLowerInvariant())
            {
            case ".saanim":
                using (TextWriter tw = File.CreateText(Path.ChangeExtension(filename, ".json")))
                    using (JsonTextWriter jtw = new JsonTextWriter(tw)
                    {
                        Formatting = Formatting.Indented
                    })
                        js.Serialize(jtw, NJS_MOTION.Load(filename));
                break;

            case ".json":
                using (TextReader tr = File.OpenText(filename))
                    using (JsonTextReader jtr = new JsonTextReader(tr))
                        js.Deserialize <NJS_MOTION>(jtr).Save(Path.ChangeExtension(filename, ".saanim"));
                break;

            default:
                Console.WriteLine("Unknown file type.");
                return;
            }
        }
Beispiel #16
0
        public GeoAnimData(byte[] file, int address, uint imageBase, LandTableFormat format, Dictionary <int, string> labels, Dictionary <int, Attach> attaches)
        {
            ModelFormat mfmt = 0;

            switch (format)
            {
            case LandTableFormat.SA1:
                mfmt = ModelFormat.Basic;
                break;

            case LandTableFormat.SADX:
                mfmt = ModelFormat.BasicDX;
                break;

            case LandTableFormat.SA2:
                mfmt = ModelFormat.Chunk;
                break;
            }
            Unknown1 = ByteConverter.ToInt32(file, address);
            Unknown2 = ByteConverter.ToSingle(file, address + 4);
            Unknown3 = ByteConverter.ToSingle(file, address + 8);
            Model    = new NJS_OBJECT(file, (int)(ByteConverter.ToUInt32(file, address + 0xC) - imageBase), imageBase, mfmt, labels, attaches);
            int actionaddr = (int)(ByteConverter.ToUInt32(file, address + 0x10) - imageBase);
            int motionaddr = (int)(ByteConverter.ToUInt32(file, actionaddr + 4) - imageBase);

            Animation = NJS_MOTION.ReadDirect(file, Model.CountAnimated(), motionaddr, imageBase, labels, attaches);
            Unknown4  = ByteConverter.ToInt32(file, address + 0x14);
            if (labels.ContainsKey(actionaddr))
            {
                ActionName = labels[actionaddr];
            }
            else
            {
                NJS_ACTION action = new NJS_ACTION(file, actionaddr, imageBase, mfmt, labels, attaches);
                ActionName = action.Name;
                labels.Add(actionaddr + (int)imageBase, ActionName);
            }
        }
Beispiel #17
0
        static NJS_MOTION ProcessMotion(byte[] file, int verbose = 0, int startaddress = 0)
        {
            int frames;
            InterpolationMode intmode;
            AnimFlags         animtype;
            int curaddr = 0;

            do
            {
                AnimSections section_type = (AnimSections)BitConverter.ToInt16(file, curaddr);
                int          section_size = BitConverter.ToInt32(file, curaddr + 4);
                int          section_addr = curaddr + 8;
                if (verbose > 1)
                {
                    Console.Write("Subsection type {0}, size {1}, data begins at {2}\n", section_type.ToString(), section_size, section_addr.ToString("X"));
                }
                switch (section_type)
                {
                case AnimSections.MKEY_F:
                    if (verbose > 1)
                    {
                        Console.Write(", calculated item count: {0}\n", (float)section_size / 16.0f);
                    }
                    break;

                case AnimSections.MKEY_A:
                    if (verbose > 1)
                    {
                        Console.Write(", calculated item count: {0}\n", (float)section_size / 16.0f);
                    }
                    break;

                case AnimSections.UNKNOWN:
                    if (verbose > 1)
                    {
                        Console.Write(", calculated item count: {0}\n", (float)section_size / 16.0f);
                    }
                    break;

                case AnimSections.MDATA2_HEADER:
                    if (verbose > 1)
                    {
                        Console.Write(", number of MDATA entries: {0}\n", BitConverter.ToInt32(file, section_addr) >> BitConverter.ToInt32(file, section_addr + 4));
                    }
                    break;

                case AnimSections.MOTION:
                    if (verbose > 0)
                    {
                        Console.WriteLine("Motion at {0}", (startaddress + section_addr).ToString("X"));
                    }
                    frames   = BitConverter.ToInt32(file, section_addr + 4);
                    intmode  = (InterpolationMode)BitConverter.ToInt16(file, section_addr + 10);
                    animtype = (AnimFlags)BitConverter.ToInt16(file, section_addr + 8);
                    int mdataaddr = BitConverter.ToInt32(file, section_addr);
                    if (verbose > 1)
                    {
                        Console.Write("\nMDATA header at: {0}, frames: {1}, flags: {2}, interpolation: {3}", mdataaddr.ToString("X"), frames, animtype.ToString(), intmode.ToString());
                    }
                    // Create motion stub
                    NJS_MOTION mot = new NJS_MOTION();
                    mot.Name              = "animation_" + section_addr.ToString("X8");
                    mot.MdataName         = mot.Name + "_mdat";
                    mot.Frames            = frames;
                    mot.InterpolationMode = intmode;
                    // Read the MDATA header and get the number of MDATA entries
                    mot.ModelParts = BitConverter.ToInt32(file, mdataaddr) >> BitConverter.ToInt32(file, mdataaddr + 4);
                    if (verbose > 1)
                    {
                        Console.WriteLine(", model parts: {0}", mot.ModelParts);
                    }
                    int tmpaddr = mdataaddr + 8;                             //Start of actual MDATA array
                    for (int u = 0; u < mot.ModelParts; u++)
                    {
                        //Console.Write("\nMotion data {0}", u.ToString());
                        AnimModelData data = new AnimModelData();
                        if (animtype.HasFlag(AnimFlags.Position))
                        {
                            uint posoff = ByteConverter.ToUInt32(file, tmpaddr + u * 16);
                            data.PositionName = mot.Name + "_mkey_" + u.ToString() + "_pos_" + posoff.ToString("X8");
                            int pos_count = ByteConverter.ToInt32(file, tmpaddr + u * 16 + 8);
                            //Console.Write(", position at: {0} ({1} entries)", posoff.ToString("X"), pos_count);
                            for (int p = 0; p < pos_count; p++)
                            {
                                int   index = ByteConverter.ToInt32(file, (int)posoff + p * 16);
                                float pos_x = ByteConverter.ToSingle(file, (int)posoff + p * 16 + 4);
                                float pos_y = ByteConverter.ToSingle(file, (int)posoff + p * 16 + 8);
                                float pos_z = ByteConverter.ToSingle(file, (int)posoff + p * 16 + 12);
                                //Console.WriteLine("\nAdded position index {3}: X: {0} Y: {1} Z: {2}", pos_x, pos_y, pos_z, index);
                                data.Position.Add(index, new Vertex(pos_x, pos_y, pos_z));
                            }
                        }
                        if (animtype.HasFlag(AnimFlags.Rotation))
                        {
                            uint rotoff = ByteConverter.ToUInt32(file, tmpaddr + u * 16 + 4);
                            data.RotationName = mot.Name + "_mkey_" + u.ToString() + "_rot_" + rotoff.ToString("X8");
                            int rot_count = ByteConverter.ToInt32(file, tmpaddr + u * 16 + 12);
                            //Console.Write(", rotation at: {0} ({1} entries)", rotoff.ToString("X"), rot_count);
                            for (int p = 0; p < rot_count; p++)
                            {
                                int index = ByteConverter.ToInt32(file, (int)rotoff + p * 16);
                                int rot_x = ByteConverter.ToInt32(file, (int)rotoff + p * 16 + 4);
                                int rot_y = ByteConverter.ToInt32(file, (int)rotoff + p * 16 + 8);
                                int rot_z = ByteConverter.ToInt32(file, (int)rotoff + p * 16 + 12);
                                //Console.WriteLine("\nAdded rotation index {3}: X: {0} Y: {1} Z: {2}", rot_x, rot_y, rot_z, index);
                                data.Rotation.Add(index, new Rotation(rot_x, rot_y, rot_z));
                            }
                        }
                        mot.Models.Add(u, data);
                    }
                    return(mot);
                }
                curaddr += 8 + section_size;
            }while (curaddr < file.Length);
            return(null);
        }
Beispiel #18
0
        static byte[] GetSections(NJS_MOTION motion, int verbose = 0)
        {
            List <byte> result = new List <byte>();

            int[] mkey_f_addr    = new int[motion.ModelParts];
            int[] mkey_a_addr    = new int[motion.ModelParts];
            int   mkey_f_section = 0;
            int   mkey_f_count   = 0;

            // Get MKEY_F
            foreach (var anim in motion.Models)
            {
                AnimModelData model = anim.Value;
                if (model.Position != null && model.Position.Count > 0)
                {
                    mkey_f_addr[anim.Key] = result.Count;
                    if (verbose > 1)
                    {
                        Console.WriteLine("MKEY_F: {0} at {1}", anim.Key, result.Count.ToString("X"));
                    }
                    foreach (var item in model.Position)
                    {
                        result.AddRange(BitConverter.GetBytes(item.Key));
                        result.AddRange(BitConverter.GetBytes(item.Value.X));
                        result.AddRange(BitConverter.GetBytes(item.Value.Y));
                        result.AddRange(BitConverter.GetBytes(item.Value.Z));
                        mkey_f_count++;
                    }
                }
            }
            if (mkey_f_count > 0)
            {
                result.InsertRange(mkey_f_section, BitConverter.GetBytes((uint)0));
                result.InsertRange(mkey_f_section + 4, BitConverter.GetBytes((uint)mkey_f_count * 16));
            }
            // Get MKEY_A
            int mkey_a_section = result.Count;
            int mkey_a_count   = 0;

            foreach (var anim in motion.Models)
            {
                AnimModelData model = anim.Value;
                if (model.Rotation != null && model.Rotation.Count > 0)
                {
                    mkey_a_addr[anim.Key] = result.Count;
                    if (verbose > 1)
                    {
                        Console.WriteLine("MKEY_A: {0} at {1}", anim.Key, result.Count.ToString("X"));
                    }
                    foreach (var item in model.Rotation)
                    {
                        result.AddRange(BitConverter.GetBytes(item.Key));
                        result.AddRange(BitConverter.GetBytes(item.Value.X));
                        result.AddRange(BitConverter.GetBytes(item.Value.Y));
                        result.AddRange(BitConverter.GetBytes(item.Value.Z));
                        mkey_a_count++;
                    }
                }
            }
            if (mkey_a_count > 0)
            {
                result.InsertRange(mkey_a_section, BitConverter.GetBytes((uint)1));
                result.InsertRange(mkey_a_section + 4, BitConverter.GetBytes((uint)mkey_a_count * 16));
            }
            // Get MDATA2 header
            int mdata_section = result.Count;

            for (int m = 0; m < motion.ModelParts; m++)
            {
                if (motion.Models.ContainsKey(m))
                {
                    AnimModelData model = motion.Models[m];
                    if (model.Position != null && model.Position.Count > 0)
                    {
                        result.AddRange(BitConverter.GetBytes((uint)(mkey_f_addr[m] + 8)));
                    }
                    else
                    {
                        result.AddRange(BitConverter.GetBytes((uint)0));
                    }
                    if (model.Rotation != null && model.Rotation.Count > 0)
                    {
                        result.AddRange(BitConverter.GetBytes((uint)(mkey_a_addr[m] + 8)));
                    }
                    else
                    {
                        result.AddRange(BitConverter.GetBytes((uint)0));
                    }
                    if (model.Position != null)
                    {
                        result.AddRange(BitConverter.GetBytes((uint)(model.Position.Count)));
                    }
                    else
                    {
                        result.AddRange(BitConverter.GetBytes((uint)0));
                    }
                    if (model.Rotation != null)
                    {
                        result.AddRange(BitConverter.GetBytes((uint)(model.Rotation.Count)));
                    }
                    else
                    {
                        result.AddRange(BitConverter.GetBytes((uint)0));
                    }
                }
                else
                {
                    result.AddRange(BitConverter.GetBytes((uint)0));
                    result.AddRange(BitConverter.GetBytes((uint)0));
                    result.AddRange(BitConverter.GetBytes((uint)0));
                    result.AddRange(BitConverter.GetBytes((uint)0));
                }
            }
            result.InsertRange(mdata_section, BitConverter.GetBytes((uint)3));
            result.InsertRange(mdata_section + 4, BitConverter.GetBytes((uint)(16 * motion.ModelParts + 8)));
            result.InsertRange(mdata_section + 8, BitConverter.GetBytes((uint)motion.ModelParts << 2));
            result.InsertRange(mdata_section + 12, BitConverter.GetBytes((uint)2));
            // Write motion header
            result.AddRange(BitConverter.GetBytes((uint)4));
            result.AddRange(BitConverter.GetBytes((uint)12));
            result.AddRange(BitConverter.GetBytes(mdata_section + 8));
            result.AddRange(BitConverter.GetBytes(motion.Frames));
            // It's MDATA2 so flags are hardcoded
            AnimFlags flags = 0;

            flags |= AnimFlags.Position;
            flags |= AnimFlags.Rotation;
            result.AddRange(BitConverter.GetBytes((short)flags));
            result.AddRange(BitConverter.GetBytes((short)motion.InterpolationMode));
            return(result.ToArray());
        }
Beispiel #19
0
        /// <summary>
        /// Exports a single level, model or animation file as text.
        /// </summary>
        /// <param name="source">Source pathname.</param>
        /// <param name="type">Type of text conversion.</param>
        /// <param name="destination">Destination pathname. Leave blank to export in the same folder with a swapped extension.</param>
        /// <param name="basicDX">Use the SADX2004 format for Basic models.</param>
        public static void ConvertFileToText(string source, TextType type, string destination = "", bool basicDX = true, bool overwrite = true)
        {
            string outext    = ".c";
            string extension = Path.GetExtension(source);

            switch (extension.ToLowerInvariant())
            {
            case ".sa2lvl":
            case ".sa1lvl":
                if (type == TextType.CStructs)
                {
                    if (destination == "")
                    {
                        destination = Path.Combine(Path.GetDirectoryName(source), Path.GetFileNameWithoutExtension(source) + outext);
                    }
                    if (!overwrite && File.Exists(destination))
                    {
                        while (File.Exists(destination))
                        {
                            destination = destination = Path.Combine(Path.GetDirectoryName(destination), Path.GetFileNameWithoutExtension(destination) + "_" + outext);
                        }
                    }
                    LandTable     land   = LandTable.LoadFromFile(source);
                    List <string> labels = new List <string>()
                    {
                        land.Name
                    };
                    using (StreamWriter sw = File.CreateText(destination))
                    {
                        sw.Write("/* Sonic Adventure ");
                        LandTableFormat fmt = land.Format;
                        switch (land.Format)
                        {
                        case LandTableFormat.SA1:
                        case LandTableFormat.SADX:
                            if (basicDX)
                            {
                                sw.Write("DX");
                                fmt = LandTableFormat.SADX;
                            }
                            else
                            {
                                sw.Write("1");
                                fmt = LandTableFormat.SA1;
                            }
                            break;

                        case LandTableFormat.SA2:
                            sw.Write("2");
                            fmt = LandTableFormat.SA2;
                            break;

                        case LandTableFormat.SA2B:
                            sw.Write("2 Battle");
                            fmt = LandTableFormat.SA2B;
                            break;
                        }
                        sw.WriteLine(" LandTable");
                        sw.WriteLine(" * ");
                        sw.WriteLine(" * Generated by DataToolbox");
                        sw.WriteLine(" * ");
                        if (!string.IsNullOrEmpty(land.Description))
                        {
                            sw.Write(" * Description: ");
                            sw.WriteLine(land.Description);
                            sw.WriteLine(" * ");
                        }
                        if (!string.IsNullOrEmpty(land.Author))
                        {
                            sw.Write(" * Author: ");
                            sw.WriteLine(land.Author);
                            sw.WriteLine(" * ");
                        }
                        sw.WriteLine(" */");
                        sw.WriteLine();
                        land.ToStructVariables(sw, fmt, labels, null);
                    }
                }
                break;

            case ".sa1mdl":
            case ".sa2mdl":
                ModelFile         modelFile  = new ModelFile(source);
                NJS_OBJECT        model      = modelFile.Model;
                List <NJS_MOTION> animations = new List <NJS_MOTION>(modelFile.Animations);
                if (type == TextType.CStructs)
                {
                    outext = ".c";
                    if (destination == "")
                    {
                        destination = Path.Combine(Path.GetDirectoryName(source), Path.GetFileNameWithoutExtension(source) + outext);
                    }
                    if (!overwrite && File.Exists(destination))
                    {
                        while (File.Exists(destination))
                        {
                            destination = destination = Path.Combine(Path.GetDirectoryName(destination), Path.GetFileNameWithoutExtension(destination) + "_" + outext);
                        }
                    }
                    using (StreamWriter sw = File.CreateText(destination))
                    {
                        sw.Write("/* NINJA ");
                        switch (modelFile.Format)
                        {
                        case ModelFormat.Basic:
                        case ModelFormat.BasicDX:
                            if (basicDX)
                            {
                                sw.Write("Basic (with Sonic Adventure DX additions)");
                            }
                            else
                            {
                                sw.Write("Basic");
                            }
                            break;

                        case ModelFormat.Chunk:
                            sw.Write("Chunk");
                            break;

                        case ModelFormat.GC:
                            sw.Write("GC");
                            break;
                        }
                        sw.WriteLine(" model");
                        sw.WriteLine(" * ");
                        sw.WriteLine(" * Generated by DataToolbox");
                        sw.WriteLine(" * ");
                        if (modelFile != null)
                        {
                            if (!string.IsNullOrEmpty(modelFile.Description))
                            {
                                sw.Write(" * Description: ");
                                sw.WriteLine(modelFile.Description);
                                sw.WriteLine(" * ");
                            }
                            if (!string.IsNullOrEmpty(modelFile.Author))
                            {
                                sw.Write(" * Author: ");
                                sw.WriteLine(modelFile.Author);
                                sw.WriteLine(" * ");
                            }
                        }
                        sw.WriteLine(" */");
                        sw.WriteLine();
                        List <string> labels_m = new List <string>()
                        {
                            model.Name
                        };
                        model.ToStructVariables(sw, basicDX, labels_m, null);
                        foreach (NJS_MOTION anim in animations)
                        {
                            anim.ToStructVariables(sw);
                        }
                    }
                }
                else if (type == TextType.NJA)
                {
                    outext = ".nja";
                    if (destination == "")
                    {
                        destination = Path.Combine(Path.GetDirectoryName(source), Path.GetFileNameWithoutExtension(source) + outext);
                    }
                    if (!overwrite && File.Exists(destination))
                    {
                        while (File.Exists(destination))
                        {
                            destination = destination = Path.Combine(Path.GetDirectoryName(destination), Path.GetFileNameWithoutExtension(destination) + "_" + outext);
                        }
                    }
                    using (StreamWriter sw2 = File.CreateText(destination))
                    {
                        List <string> labels_nj = new List <string>()
                        {
                            model.Name
                        };
                        model.ToNJA(sw2, basicDX, labels_nj, null);
                    }
                }
                break;

            case ".saanim":
                NJS_MOTION animation = NJS_MOTION.Load(source);
                if (type == TextType.CStructs)
                {
                    outext = ".c";
                    if (destination == "")
                    {
                        destination = Path.Combine(Path.GetDirectoryName(source), Path.GetFileNameWithoutExtension(source) + outext);
                    }
                    if (!overwrite && File.Exists(destination))
                    {
                        while (File.Exists(destination))
                        {
                            destination = destination = Path.Combine(Path.GetDirectoryName(destination), Path.GetFileNameWithoutExtension(destination) + "_" + outext);
                        }
                    }
                    using (StreamWriter sw = File.CreateText(destination))
                    {
                        sw.WriteLine("/* NINJA Motion");
                        sw.WriteLine(" * ");
                        sw.WriteLine(" * Generated by DataToolbox");
                        sw.WriteLine(" * ");
                        sw.WriteLine(" */");
                        sw.WriteLine();
                        animation.ToStructVariables(sw);
                    }
                }
                else if (type == TextType.JSON)
                {
                    outext = ".json";
                    if (destination == "")
                    {
                        destination = Path.Combine(Path.GetDirectoryName(source), Path.GetFileNameWithoutExtension(source) + outext);
                    }
                    if (!overwrite && File.Exists(destination))
                    {
                        while (File.Exists(destination))
                        {
                            destination = destination = Path.Combine(Path.GetDirectoryName(destination), Path.GetFileNameWithoutExtension(destination) + "_" + outext);
                        }
                    }
                    JsonSerializer js = new JsonSerializer()
                    {
                        Culture = System.Globalization.CultureInfo.InvariantCulture
                    };
                    using (TextWriter tw = File.CreateText(destination))
                        using (JsonTextWriter jtw = new JsonTextWriter(tw)
                        {
                            Formatting = Formatting.Indented
                        })
                            js.Serialize(jtw, animation);
                }
                break;
            }
        }
Beispiel #20
0
        static void Main(string[] args)
        {
            string[] arguments = Environment.GetCommandLineArgs();
            string   filename;
            bool     dx = true;
            string   outputfile;
            string   extension;
            string   dir = Environment.CurrentDirectory;

            if (args.Length == 0)
            {
                Console.WriteLine("Struct Exporter is a tool that lets you convert level, model and animation files to C structs.");
                Console.WriteLine("Usage: StructExporter <filename> [output path] [-nodx]\n");
                Console.WriteLine("Arguments: -nodx to output Basic models without SADX additions\n");
                Console.WriteLine("Supported file types: sa1lvl, sa2lvl, sa1mdl, sa2mdl, saanim\n");
                Console.WriteLine("Examples:");
                Console.WriteLine("StructExporter mylevel.sa1lvl");
                Console.WriteLine("StructExporter mylevel.sa1lvl D:\\mylevel.c");
                Console.WriteLine("StructExporter mymodel.sa1mdl D:\\mymodel.c -nodx\n");
                Console.WriteLine("You can also drag your file onto StructExporter.exe to get it converted.");
                Console.WriteLine("Press ENTER to exit");
                Console.ReadLine();
                return;
            }
            //Args list: game, filename, key, type, address, [address2/count], [language], [name]
            filename   = args[0];
            outputfile = Path.GetFileNameWithoutExtension(filename) + ".c";
            if (args.Length > 1)
            {
                if (args[args.Length - 1] == "-nodx")
                {
                    dx = false;
                }
                if (args[1] != "-nodx")
                {
                    outputfile = args[1];
                }
            }
            byte[] file = File.ReadAllBytes(filename);
            extension = Path.GetExtension(filename);
            switch (extension)
            {
            case ".sa2lvl":
            case ".sa1lvl":
                LandTable     land   = LandTable.LoadFromFile(filename);
                List <string> labels = new List <string>()
                {
                    land.Name
                };
                using (StreamWriter sw = File.CreateText(outputfile))
                {
                    sw.Write("/* Sonic Adventure ");
                    LandTableFormat fmt = land.Format;
                    switch (land.Format)
                    {
                    case LandTableFormat.SA1:
                    case LandTableFormat.SADX:
                        if (dx)
                        {
                            sw.Write("DX");
                            fmt = LandTableFormat.SADX;
                        }
                        else
                        {
                            sw.Write("1");
                            fmt = LandTableFormat.SA1;
                        }
                        break;

                    case LandTableFormat.SA2:
                        sw.Write("2");
                        fmt = LandTableFormat.SA2;
                        break;

                    case LandTableFormat.SA2B:
                        sw.Write("2 Battle");
                        fmt = LandTableFormat.SA2B;
                        break;
                    }
                    sw.WriteLine(" LandTable");
                    sw.WriteLine(" * ");
                    sw.WriteLine(" * Generated by StructExporter");
                    sw.WriteLine(" * ");
                    if (!string.IsNullOrEmpty(land.Description))
                    {
                        sw.Write(" * Description: ");
                        sw.WriteLine(land.Description);
                        sw.WriteLine(" * ");
                    }
                    if (!string.IsNullOrEmpty(land.Author))
                    {
                        sw.Write(" * Author: ");
                        sw.WriteLine(land.Author);
                        sw.WriteLine(" * ");
                    }
                    sw.WriteLine(" */");
                    sw.WriteLine();
                    land.ToStructVariables(sw, fmt, labels, null);
                }
                break;

            case ".sa1mdl":
            case ".sa2mdl":
                ModelFile         modelFile  = new ModelFile(filename);
                NJS_OBJECT        model      = modelFile.Model;
                List <NJS_MOTION> animations = new List <NJS_MOTION>(modelFile.Animations);
                using (StreamWriter sw = File.CreateText(outputfile))
                {
                    sw.Write("/* NINJA ");
                    switch (modelFile.Format)
                    {
                    case ModelFormat.Basic:
                    case ModelFormat.BasicDX:
                        if (dx)
                        {
                            sw.Write("Basic (with Sonic Adventure DX additions)");
                        }
                        else
                        {
                            sw.Write("Basic");
                        }
                        break;

                    case ModelFormat.Chunk:
                        sw.Write("Chunk");
                        break;

                    case ModelFormat.GC:
                        sw.Write("GC");
                        break;
                    }
                    sw.WriteLine(" model");
                    sw.WriteLine(" * ");
                    sw.WriteLine(" * Generated by StructExporter");
                    sw.WriteLine(" * ");
                    if (modelFile != null)
                    {
                        if (!string.IsNullOrEmpty(modelFile.Description))
                        {
                            sw.Write(" * Description: ");
                            sw.WriteLine(modelFile.Description);
                            sw.WriteLine(" * ");
                        }
                        if (!string.IsNullOrEmpty(modelFile.Author))
                        {
                            sw.Write(" * Author: ");
                            sw.WriteLine(modelFile.Author);
                            sw.WriteLine(" * ");
                        }
                    }
                    sw.WriteLine(" */");
                    sw.WriteLine();
                    List <string> labels_m = new List <string>()
                    {
                        model.Name
                    };
                    model.ToStructVariables(sw, dx, labels_m, null);
                    foreach (NJS_MOTION anim in animations)
                    {
                        anim.ToStructVariables(sw);
                    }
                }
                break;

            case ".saanim":
                NJS_MOTION animation = NJS_MOTION.Load(filename);
                using (StreamWriter sw = File.CreateText(outputfile))
                {
                    sw.WriteLine("/* NINJA Motion");
                    sw.WriteLine(" * ");
                    sw.WriteLine(" * Generated by StructExporter");
                    sw.WriteLine(" * ");
                    sw.WriteLine(" */");
                    sw.WriteLine();
                    animation.ToStructVariables(sw);
                    break;
                }
            }
        }
Beispiel #21
0
 public static LevelAnim ImportLevelAnimation(NJS_OBJECT objm, NJS_MOTION mot, EditorItemSelection selectionManager)
 {
     objm.ProcessVertexData();
     StateChanged();
     return(new LevelAnim(new GeoAnimData(objm, mot), levelAnims.Count, selectionManager));
 }
Beispiel #22
0
        static void Main(string[] args)
        {
            bool          nometa  = false;
            bool          nolabel = false;
            string        mode;
            string        fullpath_out;
            bool          bigendian = false;
            List <string> mdlanimfiles;

            if (args.Length == 0)
            {
                Console.WriteLine("Split any binary files supported by SA Tools.\n");
                Console.WriteLine("Usage:\n");
                Console.WriteLine("-Splitting binary files with INI data-");
                Console.WriteLine("split binary <file> <inifile> [output path] [-nometa] [-nolabel]\n");
                Console.WriteLine("-Splitting SA1/SADX NB files-");
                Console.WriteLine("split nb <file> [output path] -ini [split INI file]\n");
                Console.WriteLine("-Splitting SA2 MDL files-");
                Console.WriteLine("split mdl <file> [output path] -anim [animation files]\n");
                Console.WriteLine("-Splitting SA2B MDL files-");
                Console.WriteLine("split mdl_b <file> [output path] -anim [animation files]\n");
                Console.WriteLine("-Splitting dllexport entries from DLL files-");
                Console.WriteLine("split dllexport <file> <type> <name> [output path] [-p numparts]\n");
                Console.WriteLine("Press ENTER to exit.");
                Console.ReadLine();
                return;
            }
#if DEBUG
            if (SplitExtensions(args) == true)
            {
                return;
            }
#endif
            for (int u = 2; u < args.Length; u++)
            {
                if (args[u] == "-nometa")
                {
                    nometa = true;
                }
                if (args[u] == "-nolabel")
                {
                    nolabel = true;
                }
            }
            mode = args[0];
            switch (mode.ToLowerInvariant())
            {
            case "binary":
                string fullpath_bin = Path.GetFullPath(args[1]);
                if (!File.Exists(fullpath_bin))
                {
                    Console.WriteLine("File {0} doesn't exist.", fullpath_bin);
                    return;
                }
                Console.WriteLine("File: {0}", fullpath_bin);
                string fullpath_ini = Path.GetFullPath(args[2]);
                if (!File.Exists(fullpath_ini))
                {
                    Console.WriteLine("File {0} doesn't exist.", fullpath_ini);
                    return;
                }
                Console.WriteLine("Data mapping: {0}", fullpath_ini);
                fullpath_out = Path.GetDirectoryName(fullpath_bin);
                if (args.Length > 3)
                {
                    fullpath_out = args[3];
                    if (fullpath_out[fullpath_out.Length - 1] != '/')
                    {
                        fullpath_out = string.Concat(fullpath_out, '/');
                    }
                    fullpath_out = Path.GetFullPath(fullpath_out);
                }
                Console.WriteLine("Output folder: {0}", fullpath_out);
                if (nometa)
                {
                    Console.WriteLine("Labels are disabled");
                }
                if (Path.GetExtension(args[1]).ToLowerInvariant() == ".dll")
                {
                    SA_Tools.SplitDLL.SplitDLL.SplitDLLFile(fullpath_bin, fullpath_ini, fullpath_out, nometa, nolabel);
                }
                else
                {
                    SA_Tools.Split.Split.SplitFile(fullpath_bin, fullpath_ini, fullpath_out, nometa, nolabel);
                }
                break;

            case "nb":
            case "nb_b":
                string fullpath_nb = Path.GetFullPath(args[1]);
                string path_ini    = null;
                if (args[args.Length - 2].ToLowerInvariant() == "-ini")
                {
                    path_ini = Path.GetFullPath(args[args.Length - 1]);
                }
                if (!File.Exists(fullpath_nb))
                {
                    Console.WriteLine("File {0} doesn't exist.", fullpath_nb);
                    return;
                }
                Console.WriteLine("File: {0}", fullpath_nb);
                fullpath_out = Path.GetDirectoryName(fullpath_nb);
                if (args.Length > 2)
                {
                    fullpath_out = args[2];
                    if (fullpath_out[fullpath_out.Length - 1] != '/')
                    {
                        fullpath_out = string.Concat(fullpath_out, '/');
                    }
                    fullpath_out = Path.GetFullPath(fullpath_out);
                }
                Console.WriteLine("Output folder: {0}", fullpath_out);
                SA_Tools.Split.SplitNB.SplitNBFile(fullpath_nb, false, fullpath_out, 1, path_ini);
                break;

            case "mdl":
            case "mdl_b":
                string fullpath_mdl = Path.GetFullPath(args[1]);
                if (!File.Exists(fullpath_mdl))
                {
                    Console.WriteLine("File {0} doesn't exist.", fullpath_mdl);
                    return;
                }
                Console.Write("File: {0}", fullpath_mdl);
                if (mode == "mdl_b")
                {
                    bigendian = true;
                    Console.Write(" (Big Endian)\n");
                }
                else
                {
                    Console.Write(System.Environment.NewLine);
                }
                fullpath_out = Path.GetDirectoryName(fullpath_mdl);
                if (args.Length > 2)
                {
                    fullpath_out = args[2];
                    if (fullpath_out[fullpath_out.Length - 1] != '/')
                    {
                        fullpath_out = string.Concat(fullpath_out, '/');
                    }
                    fullpath_out = Path.GetFullPath(fullpath_out);
                }
                Console.WriteLine("Output path: {0}", fullpath_out);
                if (args.Length > 3)
                {
                    mdlanimfiles = new List <string>();
                    Console.WriteLine("Animation files:");
                    for (int u = 3; u < args.Length; u++)
                    {
                        string animpath = Path.GetFullPath(args[u]);
                        if (File.Exists(animpath))
                        {
                            mdlanimfiles.Add(animpath);
                            Console.WriteLine(animpath);
                        }
                        else
                        {
                            Console.WriteLine("File {0} doesn't exist.", animpath);
                        }
                    }
                    SA_Tools.SAArc.sa2MDL.Split(bigendian, fullpath_mdl, fullpath_out, mdlanimfiles.ToArray());
                }
                else
                {
                    SA_Tools.SAArc.sa2MDL.Split(bigendian, fullpath_mdl, fullpath_out, null);
                }
                break;

            case "dllexport":
                string fullpath_dllex = Path.GetFullPath(args[1]);
                string type           = args[2];
                string name           = args[3];
                string fileOutputPath = "";
                if (args.Length > 4)
                {
                    for (int i = 4; i < args.Length; i++)
                    {
                        if (args[i].Substring(0, 1) != "-" && args[i - 1].Substring(0, 1) != "-")
                        {
                            fileOutputPath = args[i];
                        }
                    }
                }
                if (!File.Exists(fullpath_dllex))
                {
                    Console.WriteLine("File {0} doesn't exist.", fullpath_dllex);
                    return;
                }
                Console.Write("File: {0}", fullpath_dllex);
                byte[] datafile  = File.ReadAllBytes(fullpath_dllex);
                uint   imageBase = SA_Tools.HelperFunctions.SetupEXE(ref datafile).Value;
                Dictionary <string, int> exports;
                Dictionary <int, string> labels = new Dictionary <int, string>();
                {
                    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 namex = datafile.GetCString(BitConverter.ToInt32(datafile, nameaddr),
                                                           System.Text.Encoding.ASCII);
                        int addr = BitConverter.ToInt32(datafile,
                                                        dir.AddressOfFunctions + (BitConverter.ToInt16(datafile, ordaddr) * 4));
                        exports.Add(namex, addr);
                        labels.Add(addr, namex);
                        nameaddr += 4;
                        ordaddr  += 2;
                    }
                    Console.Write(" ({0} exports)\n", exports.Count);
                }
                if (!exports.ContainsKey(name))
                {
                    Console.WriteLine("The export table has no item named {0}", name);
                    return;
                }
                int address = exports[name];
                Console.WriteLine("{0} {1}:{2}", type, name, address.ToString("X8"));
                switch (type)
                {
                // Landtables
                case "landtable":
                case "sa1landtable":
                case "sadxlandtable":
                case "sa2landtable":
                case "sa2blandtable":
                case "battlelandtable":
                    LandTableFormat landfmt_cur;
                    string          landext;
                    switch (type)
                    {
                    case "sa1landtable":
                        landfmt_cur = LandTableFormat.SA1;
                        landext     = ".sa1lvl";
                        break;

                    case "sadxlandtable":
                        landfmt_cur = LandTableFormat.SADX;
                        landext     = ".sa1lvl";
                        break;

                    case "sa2landtable":
                        landfmt_cur = LandTableFormat.SA2;
                        landext     = ".sa2lvl";
                        break;

                    case "sa2blandtable":
                    case "battlelandtable":
                        landfmt_cur = LandTableFormat.SA2B;
                        landext     = ".sa2blvl";
                        break;

                    case "landtable":
                    default:
                        landfmt_cur = LandTableFormat.SADX;
                        landext     = ".sa1lvl";
                        break;
                    }
                    LandTable land = new LandTable(datafile, address, imageBase, landfmt_cur, labels);
                    if (fileOutputPath == "")
                    {
                        fileOutputPath = land.Name + landext;
                    }
                    if (!Directory.Exists(Path.GetDirectoryName(fileOutputPath)))
                    {
                        Directory.CreateDirectory(Path.GetDirectoryName(fileOutputPath));
                    }
                    land.SaveToFile(fileOutputPath, landfmt_cur, nometa);
                    break;

                // NJS_OBJECT
                case "model":
                case "object":
                case "basicmodel":
                case "basicdxmodel":
                case "chunkmodel":
                case "gcmodel":
                {
                    ModelFormat modelfmt_obj;
                    string      modelext;
                    switch (type)
                    {
                    case "basicmodel":
                        modelfmt_obj = ModelFormat.Basic;
                        modelext     = ".sa1mdl";
                        break;

                    case "basicdxmodel":
                        modelfmt_obj = ModelFormat.BasicDX;
                        modelext     = ".sa1mdl";
                        break;

                    case "chunkmodel":
                        modelfmt_obj = ModelFormat.Chunk;
                        modelext     = ".sa2mdl";
                        break;

                    case "gcmodel":
                        modelfmt_obj = ModelFormat.GC;
                        modelext     = ".sa2bmdl";
                        break;

                    default:
                        modelfmt_obj = ModelFormat.BasicDX;
                        modelext     = ".sa1mdl";
                        break;
                    }
                    NJS_OBJECT mdl = new NJS_OBJECT(datafile, address, imageBase, modelfmt_obj, labels, new Dictionary <int, Attach>());
                    if (fileOutputPath == "")
                    {
                        fileOutputPath = mdl.Name + modelext;
                    }
                    if (!Directory.Exists(Path.GetDirectoryName(fileOutputPath)))
                    {
                        Directory.CreateDirectory(Path.GetDirectoryName(fileOutputPath));
                    }
                    ModelFile.CreateFile(fileOutputPath, mdl, null, null, null, null, modelfmt_obj, nometa);
                }
                break;

                // NJS_MOTION
                case "animation":
                case "motion":
                    int numparts = 0;
                    for (int a = 3; a < args.Length; a++)
                    {
                        if (args[a] == "-p")
                        {
                            numparts = int.Parse(args[a + 1], System.Globalization.NumberStyles.Integer);
                        }
                    }
                    NJS_MOTION ani = new NJS_MOTION(datafile, address, imageBase, numparts, labels);
                    if (fileOutputPath == "")
                    {
                        fileOutputPath = ani.Name + ".saanim";
                    }
                    string outpath = Path.GetDirectoryName(Path.GetFullPath(fileOutputPath));
                    Console.WriteLine("Output file: {0}", Path.GetFullPath(fileOutputPath));
                    if (!Directory.Exists(outpath))
                    {
                        Directory.CreateDirectory(outpath);
                    }
                    ani.Save(fileOutputPath, nometa);
                    break;

                default:
                    Console.WriteLine("Unrecognized export type {0}", type);
                    break;
                }
                break;

            default:
                Console.WriteLine("Incorrect mode specified. Press ENTER to exit.");
                Console.ReadLine();
                return;
            }
        }
Beispiel #23
0
        public override void ProcessShapeMotionVertexData(NJS_MOTION motion, int frame, int animindex)
        {
            if (!motion.Models.ContainsKey(animindex))
            {
                ProcessVertexData();
                return;
            }
            Vertex[]      vertdata = Vertex;
            Vertex[]      normdata = Normal;
            AnimModelData data     = motion.Models[animindex];

            if (data.Vertex.Count > 0)
            {
                vertdata = data.GetVertex(frame);
            }
            if (data.Normal.Count > 0)
            {
                normdata = data.GetNormal(frame);
            }
            List <MeshInfo> result = new List <MeshInfo>();

            foreach (NJS_MESHSET mesh in Mesh)
            {
                bool              hasVColor = mesh.VColor != null;
                bool              hasUV     = mesh.UV != null;
                List <Poly>       polys     = new List <Poly>();
                List <VertexData> verts     = new List <VertexData>();
                int currentstriptotal       = 0;
                foreach (Poly poly in mesh.Poly)
                {
                    Poly newpoly = null;
                    switch (mesh.PolyType)
                    {
                    case Basic_PolyType.Triangles:
                        newpoly = new Triangle();
                        break;

                    case Basic_PolyType.Quads:
                        newpoly = new Quad();
                        break;

                    case Basic_PolyType.NPoly:
                    case Basic_PolyType.Strips:
                        newpoly = new Strip(poly.Indexes.Length, ((Strip)poly).Reversed);
                        break;
                    }
                    for (int i = 0; i < poly.Indexes.Length; i++)
                    {
                        newpoly.Indexes[i] = (ushort)verts.Count;
                        verts.Add(new VertexData(
                                      vertdata[poly.Indexes[i]],
                                      normdata[poly.Indexes[i]],
                                      hasVColor ? (Color?)mesh.VColor[currentstriptotal] : null,
                                      hasUV ? mesh.UV[currentstriptotal++] : null));
                    }
                    polys.Add(newpoly);
                }
                NJS_MATERIAL mat = null;
                if (Material != null && mesh.MaterialID < Material.Count)
                {
                    mat = Material[mesh.MaterialID];
                }
                result.Add(new MeshInfo(mat, polys.ToArray(), verts.ToArray(), hasUV, hasVColor));
            }
            MeshInfo = result.ToArray();
        }
Beispiel #24
0
 public MotionInfo(string fn, NJS_MOTION mtn)
 {
     Filename = fn;
     Motion   = mtn;
 }
Beispiel #25
0
        public static void SplitNBFile(string filename, bool extractchunks, string outdir, int verbose = 0, string inifilename = null, bool overwrite = true)
        {
            Dictionary <int, string>     sectionlist = new Dictionary <int, string>();
            Dictionary <int, NJS_OBJECT> modellist   = new Dictionary <int, NJS_OBJECT>();
            Dictionary <int, NJS_MOTION> animlist    = new Dictionary <int, NJS_MOTION>();

            byte[] file = File.ReadAllBytes(filename);
            if (file.Length == 180920) // Patch in unused rotation for E101R, required for rebuilding with correct pointers
            {
                file[129896] = 0xE0;
                file[129897] = 0x0A;
                file[129904] = 0x02;
            }
            if (BitConverter.ToInt32(file, 0) != 0x04424A4E)
            {
                Console.WriteLine("Invalid NB file.");
                return;
            }
            if (!Directory.Exists(outdir))
            {
                Directory.CreateDirectory(outdir);
            }
            Environment.CurrentDirectory = outdir;
            int numfiles = BitConverter.ToInt16(file, 4);
            Dictionary <int, string> splitfilenames = new Dictionary <int, string>();

            if (inifilename != null)
            {
                inifilename = Path.GetFullPath(inifilename);
            }
            if (File.Exists(inifilename))
            {
                splitfilenames = IniSerializer.Deserialize <Dictionary <int, string> >(inifilename);
                if (verbose > 0)
                {
                    Console.WriteLine("Split INI: {0}", inifilename);
                }
            }
            else
            {
                if (verbose > 0)
                {
                    Console.WriteLine("Split INI {0} not found!", inifilename);
                }
                for (int i = 0; i < numfiles; i++)
                {
                    splitfilenames[i] = i.ToString("D2");
                }
            }
            int curaddr = 8;

            for (int i = 0; i < numfiles; i++)
            {
                ushort type  = BitConverter.ToUInt16(file, curaddr);
                byte[] chunk = new byte[BitConverter.ToInt32(file, curaddr + 4)];
                Array.Copy(file, curaddr + 8, chunk, 0, chunk.Length);
                switch (type)
                {
                case 0:
                    if (verbose > 0)
                    {
                        Console.WriteLine("\nSection {0} at {1} is empty", i.ToString("D2", NumberFormatInfo.InvariantInfo), curaddr.ToString("X"));
                    }
                    sectionlist.Add(i, "NULL");
                    break;

                case 1:
                    if (verbose > 0)
                    {
                        Console.WriteLine("\nSection {0} at {1} is a model", i.ToString("D2", NumberFormatInfo.InvariantInfo), curaddr.ToString("X"));
                    }
                    if (extractchunks)
                    {
                        File.WriteAllBytes(i.ToString("D2", NumberFormatInfo.InvariantInfo) + ".bin", chunk);
                    }
                    NJS_OBJECT mdl = ProcessModel(chunk, verbose, curaddr + 8);
                    //if (extractchunks) File.WriteAllBytes(i.ToString("D2", NumberFormatInfo.InvariantInfo) + "_p.bin", GetSections(mdl));
                    // Assume there is no description/texture for SAMDL project mode
                    string[] metadata    = new string[0];
                    string   outFilename = splitfilenames[i];
                    if (splitfilenames[i].Contains("|"))
                    {
                        metadata    = splitfilenames[i].Split('|');  // Filename|Description|Texture file
                        outFilename = metadata[0];
                    }
                    string outResult = outFilename + ".sa1mdl";
                    modellist.Add(i, mdl);
                    if (metadata.Length > 1)
                    {
                        outResult += ("|" + metadata[1]);
                    }
                    if (metadata.Length > 2)
                    {
                        outResult += ("|" + metadata[2]);
                    }
                    sectionlist.Add(i, outResult);
                    break;

                case 3:
                    if (verbose > 0)
                    {
                        Console.WriteLine("\nSection {0} at {1} is a motion", i.ToString("D2", NumberFormatInfo.InvariantInfo), curaddr.ToString("X"));
                    }
                    if (extractchunks)
                    {
                        File.WriteAllBytes(i.ToString("D2", NumberFormatInfo.InvariantInfo) + ".bin", chunk);
                    }
                    string desc = null;
                    if (splitfilenames[i].Contains("|"))
                    {
                        metadata    = splitfilenames[i].Split('|');                              // Filename|Description
                        outFilename = metadata[0];
                        desc        = metadata[1];
                    }
                    else
                    {
                        outFilename = splitfilenames[i];
                    }
                    NJS_MOTION mot = ProcessMotion(chunk, verbose, curaddr + 8);
                    mot.Description = desc;
                    //if (extractchunks) File.WriteAllBytes(i.ToString("D2", NumberFormatInfo.InvariantInfo) + "_p.bin", GetSections(mot));
                    animlist.Add(i, mot);
                    sectionlist.Add(i, outFilename + ".saanim");
                    break;

                default:
                    if (verbose > 0)
                    {
                        Console.WriteLine("\nSection {0} at {1} is an unknown type", i.ToString("D2", NumberFormatInfo.InvariantInfo), curaddr.ToString("X"));
                    }
                    if (extractchunks)
                    {
                        File.WriteAllBytes(i.ToString("D2", NumberFormatInfo.InvariantInfo) + ".bin", chunk);
                    }
                    sectionlist.Add(i, splitfilenames[i] + ".wtf");
                    break;
                }
                curaddr += chunk.Length + 8;
            }
            // Save models and animations
            foreach (var modelitem in modellist)
            {
                // If the filename field contains description/texture, split it
                string filenameString = splitfilenames[modelitem.Key];
                if (splitfilenames[modelitem.Key].Contains("|"))
                {
                    string[] filenameSplit = filenameString.Split('|');
                    filenameString = filenameSplit[0];
                }

                List <string> anims = new List <string>();
                foreach (var animitem in animlist)
                {
                    string filenameStringAnim = splitfilenames[animitem.Key];
                    if (splitfilenames[animitem.Key].Contains("|"))
                    {
                        string[] filenameSplitAnim = filenameStringAnim.Split('|');
                        filenameStringAnim = filenameSplitAnim[0];
                    }
                    if (modelitem.Value.CountAnimated() == animitem.Value.ModelParts)
                    {
                        if (File.Exists(Path.Combine(outdir, filenameStringAnim + ".saanim")) && !overwrite)
                        {
                            return;
                        }
                        if (!Directory.Exists(Path.GetDirectoryName(filenameStringAnim + ".saanim")) && Path.GetDirectoryName(filenameStringAnim + ".saanim") != "")
                        {
                            Directory.CreateDirectory(Path.GetDirectoryName(filenameStringAnim + ".saanim"));
                        }
                        animitem.Value.Save(filenameStringAnim + ".saanim");
                        System.Text.StringBuilder sb = new System.Text.StringBuilder(1024);
                        PathRelativePathTo(sb, Path.GetFullPath(Path.Combine(outdir, filenameStringAnim + ".saanim")), 0, Path.GetFullPath(filenameStringAnim + ".saanim"), 0);
                        anims.Add(sb.ToString());
                    }
                }
                if (File.Exists(Path.Combine(outdir, filenameString + ".sa1mdl")) && !overwrite)
                {
                    return;
                }
                if (!Directory.Exists(Path.GetDirectoryName(filenameString + ".sa1mdl")) && Path.GetDirectoryName(filenameString + ".sa1mdl") != "")
                {
                    Directory.CreateDirectory(Path.GetDirectoryName(filenameString + ".sa1mdl"));
                }
                ModelFile.CreateFile(filenameString + ".sa1mdl", modelitem.Value, anims.ToArray(), null, null, null, ModelFormat.Basic);
            }
            string sectionListFilename = Path.GetFileNameWithoutExtension(filename) + ".ini";

            if (inifilename != null)
            {
                sectionListFilename = Path.GetFileNameWithoutExtension(inifilename) + "_data.ini";
            }
            IniSerializer.Serialize(sectionlist, Path.Combine(outdir, sectionListFilename));
        }
Beispiel #26
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);
        }
Beispiel #27
0
        public static void Build(string filename)
        {
            nodenames.Clear();
            modelfiles.Clear();
            motionfiles.Clear();

            byte[] fc;
            if (Path.GetExtension(filename).Equals(".prs", StringComparison.OrdinalIgnoreCase))
            {
                fc = Prs.Decompress(filename);
            }
            else
            {
                fc = File.ReadAllBytes(filename);
            }
            string         path = Path.Combine(Path.GetDirectoryName(Path.GetFullPath(filename)), Path.GetFileNameWithoutExtension(filename));
            JsonSerializer js   = new JsonSerializer();
            EventIniData   ini;

            using (TextReader tr = File.OpenText(Path.Combine(path, Path.ChangeExtension(Path.GetFileName(filename), ".json"))))
                using (JsonTextReader jtr = new JsonTextReader(tr))
                    ini = js.Deserialize <EventIniData>(jtr);
            uint key;
            bool battle     = ini.Game == Game.SA2B;
            bool battlebeta = ini.Game == Game.SA2B;
            bool dcbeta     = ini.Game == Game.SA2;

            if (fc[0] == 0x81)
            {
                if (fc[0x2B] <= 1 && fc[0x2A] == 0)
                {
                    ByteConverter.BigEndian = true;
                    key    = 0x8125FE60;
                    battle = true;
                }
                else
                {
                    ByteConverter.BigEndian = true;
                    key        = 0x812FFE60;
                    battlebeta = true;
                }
            }
            else
            {
                if ((fc[37] == 0x25) || (fc[38] == 0x22) || ((fc[36] == 0) && ((fc[1] == 0xFE) || (fc[1] == 0xF2) || ((fc[1] == 0x27) && fc[2] == 0x9F))))
                {
                    ByteConverter.BigEndian = false;
                    key    = 0xC600000;
                    dcbeta = true;
                }
                else
                {
                    ByteConverter.BigEndian = false;
                    key = 0xC600000;
                }
            }
            List <byte> modelbytes           = new List <byte>(fc);
            Dictionary <string, uint> labels = new Dictionary <string, uint>();

            foreach (string file in ini.Files.Where(a => a.Key.EndsWith(".sa2mdl", StringComparison.OrdinalIgnoreCase) && HelperFunctions.FileHash(Path.Combine(path, a.Key)) != a.Value).Select(a => a.Key))
            {
                modelbytes.AddRange(new ModelFile(Path.Combine(path, file)).Model.GetBytes((uint)(key + modelbytes.Count), false, labels, new List <uint>(), out uint _));
            }
            if (battle)
            {
                foreach (string file in ini.Files.Where(a => a.Key.EndsWith(".sa2bmdl", StringComparison.OrdinalIgnoreCase) && HelperFunctions.FileHash(Path.Combine(path, a.Key)) != a.Value).Select(a => a.Key))
                {
                    modelbytes.AddRange(new ModelFile(Path.Combine(path, file)).Model.GetBytes((uint)(key + modelbytes.Count), false, labels, new List <uint>(), out uint _));
                }
                List <byte> motionbytes             = new List <byte>(new byte[(ini.Motions.Count + 1) * 8]);
                Dictionary <string, int> partcounts = new Dictionary <string, int>(ini.Motions.Count);
                foreach (string file in ini.Files.Where(a => a.Key.EndsWith(".saanim", StringComparison.OrdinalIgnoreCase)).Select(a => a.Key))
                {
                    NJS_MOTION motion = NJS_MOTION.Load(Path.Combine(path, file));
                    motionbytes.AddRange(motion.GetBytes((uint)motionbytes.Count, labels, out uint _));
                    partcounts.Add(motion.Name, motion.ModelParts);
                }
                byte[] mfc = motionbytes.ToArray();
                for (int i = 0; i < ini.Motions.Count; i++)
                {
                    if (ini.Motions[i] == null)
                    {
                        new byte[] { 0xFF, 0xFF, 0xFF, 0xFF }
                    }
Beispiel #28
0
        public static void ExportCPP(DllIniData IniData,
                                     Dictionary <string, bool> itemsToExport, string fileName)
        {
            using (TextWriter writer = File.CreateText(fileName))
            {
                bool            SA2      = IniData.Game == SA_Tools.SplitDLL.Game.SA2B;
                ModelFormat     modelfmt = SA2 ? ModelFormat.Chunk : ModelFormat.BasicDX;
                LandTableFormat landfmt  = SA2 ? LandTableFormat.SA2 : LandTableFormat.SADX;
                writer.WriteLine("// Generated by SA Tools DLL Mod Generator");
                writer.WriteLine();
                if (SA2)
                {
                    writer.WriteLine("#include \"SA2ModLoader.h\"");
                }
                else
                {
                    writer.WriteLine("#include \"SADXModLoader.h\"");
                }
                writer.WriteLine();
                List <string>             labels   = new List <string>();
                Dictionary <string, uint> texlists = new Dictionary <string, uint>();
                foreach (KeyValuePair <string, FileTypeHash> item in
                         IniData.Files.Where(i => itemsToExport[i.Key]))
                {
                    switch (item.Value.Type)
                    {
                    case "landtable":
                        LandTable tbl = LandTable.LoadFromFile(item.Key);
                        texlists.Add(tbl.Name, tbl.TextureList);
                        tbl.ToStructVariables(writer, landfmt, new List <string>());
                        labels.AddRange(tbl.GetLabels());
                        break;

                    case "model":
                        NJS_OBJECT mdl = new ModelFile(item.Key).Model;
                        mdl.ToStructVariables(writer, modelfmt == ModelFormat.BasicDX, new List <string>());
                        labels.AddRange(mdl.GetLabels());
                        break;

                    case "basicmodel":
                    case "chunkmodel":
                    case "gcmodel":
                        mdl = new ModelFile(item.Key).Model;
                        mdl.ToStructVariables(writer, false, new List <string>());
                        labels.AddRange(mdl.GetLabels());
                        break;

                    case "basicdxmodel":
                        mdl = new ModelFile(item.Key).Model;
                        mdl.ToStructVariables(writer, true, new List <string>());
                        labels.AddRange(mdl.GetLabels());
                        break;

                    case "animation":
                        NJS_MOTION ani = NJS_MOTION.Load(item.Key);
                        ani.ToStructVariables(writer);
                        labels.Add(ani.Name);
                        break;
                    }
                    writer.WriteLine();
                }
                foreach (var item in IniData.DataItems.Where(i => itemsToExport[i.Filename]))
                {
                    switch (item.Type)
                    {
                    case "animindexlist":
                    {
                        SortedDictionary <short, NJS_MOTION> anims = new SortedDictionary <short, NJS_MOTION>();
                        foreach (string file in Directory.GetFiles(item.Filename, "*.saanim"))
                        {
                            if (short.TryParse(Path.GetFileNameWithoutExtension(file), NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out short i))
                            {
                                anims.Add(i, NJS_MOTION.Load(file));
                            }
                        }
                        foreach (KeyValuePair <short, NJS_MOTION> obj in anims)
                        {
                            obj.Value.ToStructVariables(writer);
                            writer.WriteLine();
                        }
                        writer.WriteLine("AnimationIndex {0}[] = {{", item.Export);
                        List <string> objs = new List <string>(anims.Count);
                        foreach (KeyValuePair <short, NJS_MOTION> obj in anims)
                        {
                            objs.Add($"{{ {obj.Key}, {obj.Value.ModelParts}, &{obj.Value.Name} }}");
                        }
                        objs.Add("{ -1 }");
                        writer.WriteLine("\t" + string.Join("," + Environment.NewLine + "\t", objs.ToArray()));
                        writer.WriteLine("};");
                    }
                    break;

                    case "charaobjectdatalist":
                    {
                        foreach (string file in Directory.GetFiles(item.Filename, "*.sa2mdl"))
                        {
                            new ModelFile(file).Model.ToStructVariables(writer, false, new List <string>());
                            writer.WriteLine();
                        }
                        foreach (string file in Directory.GetFiles(item.Filename, "*.saanim"))
                        {
                            NJS_MOTION.Load(file).ToStructVariables(writer);
                            writer.WriteLine();
                        }
                        var data = IniSerializer.Deserialize <CharaObjectData[]>(Path.Combine(item.Filename, "info.ini"));
                        writer.WriteLine("CharaObjectData {0}[] = {{", item.Export);
                        List <string> objs = new List <string>(data.Length);
                        foreach (var obj in data)
                        {
                            objs.Add(obj.ToStruct());
                        }
                        writer.WriteLine("\t" + string.Join("," + Environment.NewLine + "\t", objs.ToArray()));
                        writer.WriteLine("};");
                    }
                    break;

                    case "kartspecialinfolist":
                    {
                        foreach (string file in Directory.GetFiles(item.Filename, "*.sa2mdl"))
                        {
                            new ModelFile(file).Model.ToStructVariables(writer, false, new List <string>());
                            writer.WriteLine();
                        }
                        var data = IniSerializer.Deserialize <KartSpecialInfo[]>(Path.Combine(item.Filename, "info.ini"));
                        writer.WriteLine("KartSpecialInfo {0}[] = {{", item.Export);
                        List <string> objs = new List <string>(data.Length);
                        for (int i = 0; i < data.Length; i++)
                        {
                            KartSpecialInfo obj = data[i];
                            objs.Add(obj.ToStruct());
                            texlists.Add($"{item.Export}[{i}]", obj.TexList);
                        }
                        writer.WriteLine("\t" + string.Join("," + Environment.NewLine + "\t", objs.ToArray()));
                        writer.WriteLine("};");
                    }
                    break;

                    case "kartmodelsarray":
                    {
                        foreach (string file in Directory.GetFiles(item.Filename, "*.sa2bmdl"))
                        {
                            new ModelFile(file).Model.ToStructVariables(writer, false, new List <string>());
                            writer.WriteLine();
                        }
                        foreach (string file in Directory.GetFiles(item.Filename, "*.sa1mdl"))
                        {
                            new ModelFile(file).Model.ToStructVariables(writer, false, new List <string>());
                            writer.WriteLine();
                        }
                        var data = IniSerializer.Deserialize <CharaObjectData[]>(Path.Combine(item.Filename, "info.ini"));
                        writer.WriteLine("KartModelsArray {0}[] = {{", item.Export);
                        List <string> objs = new List <string>(data.Length);
                        foreach (var obj in data)
                        {
                            objs.Add(obj.ToStruct());
                        }
                        writer.WriteLine("\t" + string.Join("," + Environment.NewLine + "\t", objs.ToArray()));
                        writer.WriteLine("};");
                    }
                    break;

                    case "motiontable":
                    {
                        foreach (string file in Directory.GetFiles(item.Filename, "*.saanim"))
                        {
                            NJS_MOTION.Load(file).ToStructVariables(writer);
                            writer.WriteLine();
                        }
                        var data = IniSerializer.Deserialize <MotionTableEntry[]>(Path.Combine(item.Filename, "info.ini"));
                        writer.WriteLine("MotionTableEntry {0}[] = {{", item.Export);
                        List <string> objs = new List <string>(data.Length);
                        foreach (var obj in data)
                        {
                            objs.Add(obj.ToStruct());
                        }
                        writer.WriteLine("\t" + string.Join("," + Environment.NewLine + "\t", objs.ToArray()));
                        writer.WriteLine("};");
                    }
                    break;
                    }
                }
                writer.WriteLine("extern \"C\" __declspec(dllexport) void __cdecl Init(const char *path, const HelperFunctions &helperFunctions)");
                writer.WriteLine("{");
                writer.WriteLine("\tHMODULE handle = GetModuleHandle(L\"{0}\");", IniData.Name);
                List <string> exports = new List <string>(IniData.Items.Where(item => labels.Contains(item.Label)).Select(item => item.Export).Distinct());
                foreach (KeyValuePair <string, string> item in IniData.Exports.Where(item => exports.Contains(item.Key)))
                {
                    writer.WriteLine("\t{0}{1} = ({0})GetProcAddress(handle, \"{1}\");", typemap[item.Value], item.Key);
                }
                foreach (DllItemInfo item in IniData.Items.Where(item => labels.Contains(item.Label)))
                {
                    if (typemap[IniData.Exports[item.Export]].EndsWith("**"))
                    {
                        writer.WriteLine("\t{0} = &{1};", item.ToString(), item.Label);
                    }
                    else
                    {
                        writer.WriteLine("\t*{0} = {1};", item.ToString(), item.Label);
                    }
                }
                foreach (var item in IniData.DataItems.Where(item => itemsToExport[item.Filename]))
                {
                    switch (item.Type)
                    {
                    case "animindexlist":
                    case "charaobjectdatalist":
                    case "kartspecialinfolist":
                    case "kartmodelsarray":
                        writer.WriteLine("\tHookExport(handle, \"{0}\", {0});", item.Export);
                        break;

                    default:
                        writer.WriteLine("\t{0}{1}_exp = ({0})GetProcAddress(handle, \"{1}\");", typemap[item.Type], item.Export);
                        writer.WriteLine("\t*{0}_exp = {0};", item.Export);
                        break;
                    }
                }
                if (texlists.Count > 0 && IniData.TexLists != null && IniData.TexLists.Items != null)
                {
                    exports = new List <string>(IniData.TexLists.Where(item => texlists.Values.Contains(item.Key)).Select(item => item.Value.Export).Distinct());
                    foreach (KeyValuePair <string, string> item in IniData.Exports.Where(item => exports.Contains(item.Key)))
                    {
                        writer.WriteLine("\t{0}{1} = ({0})GetProcAddress(handle, \"{1}\");", typemap[item.Value], item.Key);
                    }
                    foreach (KeyValuePair <string, uint> item in texlists.Where(item => IniData.TexLists.ContainsKey(item.Value)))
                    {
                        DllTexListInfo tex = IniData.TexLists[item.Value];
                        string         str;
                        if (tex.Index.HasValue)
                        {
                            str = $"{tex.Export}[{tex.Index.Value}]";
                        }
                        else
                        {
                            str = tex.Export;
                        }
                        writer.WriteLine("\t{0}.TexList = {1};", item.Key, str);
                    }
                }
                writer.WriteLine("}");
                writer.WriteLine();
                writer.WriteLine("extern \"C\" __declspec(dllexport) const ModInfo {0}ModInfo = {{ ModLoaderVer }};", SA2 ? "SA2" : "SADX");
            }
        }
Beispiel #29
0
 public override void ProcessShapeMotionVertexData(NJS_MOTION motion, float frame, int animindex)
 {
     throw new NotImplementedException();
 }
Beispiel #30
0
 public abstract void ProcessShapeMotionVertexData(NJS_MOTION motion, int frame, int animindex);