Ejemplo n.º 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);
        }
Ejemplo n.º 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);
     }
 }
Ejemplo n.º 3
0
        public Event(string filename)
        {
            byte[] fc;
            if (Path.GetExtension(filename).Equals(".prs", StringComparison.OrdinalIgnoreCase))
            {
                fc = Prs.Decompress(filename);
            }
            else
            {
                fc = File.ReadAllBytes(filename);
            }
            bool battle = false;
            uint key;

            if (fc[0] == 0x81)
            {
                ByteConverter.BigEndian = true;
                key    = 0x8125FE60;
                battle = true;
            }
            else
            {
                ByteConverter.BigEndian = false;
                key = 0xC600000;
            }
            List <NJS_MOTION> motions = null;

            if (battle)
            {
                motions = ReadMotionFile(Path.ChangeExtension(filename, null) + "motion.bin");
            }
            Dictionary <string, NJS_OBJECT> models = new Dictionary <string, NJS_OBJECT>();
            int ptr = fc.GetPointer(0x20, key);

            if (ptr != 0)
            {
                int cnt = battle ? 18 : 16;
                Upgrades = new EventUpgrade[cnt];
                for (int i = 0; i < cnt; i++)
                {
                    Upgrades[i] = new EventUpgrade(fc, ptr, key, models);
                    ptr        += EventUpgrade.Size;
                }
            }
            int gcnt = ByteConverter.ToInt32(fc, 8);

            ptr = fc.GetPointer(0, key);
            if (ptr != 0)
            {
                Scenes = new List <EventScene>();
                for (int gn = 0; gn <= gcnt; gn++)
                {
                    Scenes.Add(new EventScene(fc, ptr, key, battle, models, motions));
                    ptr += EventScene.Size;
                }
            }
        }
Ejemplo n.º 4
0
        public EventScene(byte[] file, int address, uint imageBase, bool battle, Dictionary <string, NJS_OBJECT> models, List <NJS_MOTION> motions)
        {
            int ptr = file.GetPointer(address, imageBase);

            if (ptr != 0)
            {
                int cnt = ByteConverter.ToInt32(file, address + 4);
                Entities = new List <EventEntity>(cnt);
                for (int i = 0; i < cnt; i++)
                {
                    Entities.Add(new EventEntity(file, ptr, imageBase, battle, models, motions));
                    ptr += EventEntity.Size(battle);
                }
            }
            ptr = file.GetPointer(address + 8, imageBase);
            if (ptr != 0)
            {
                int cnt = ByteConverter.ToInt32(file, address + 12);
                CameraMotions = new List <NJS_MOTION>(cnt);
                for (int i = 0; i < cnt; i++)
                {
                    if (battle)
                    {
                        CameraMotions.Add(motions[ByteConverter.ToInt32(file, ptr)]);
                    }
                    else
                    {
                        CameraMotions.Add(new NJS_MOTION(file, file.GetPointer(ptr, imageBase), imageBase, 1));
                    }
                    ptr += sizeof(int);
                }
            }
            ptr = file.GetPointer(address + 24, imageBase);
            if (ptr != 0)
            {
                Big = new EventBig(file, ptr, imageBase, battle, models, motions);
            }
            FrameCount = ByteConverter.ToInt32(file, address + 28);
        }
Ejemplo n.º 5
0
        public static List <NJS_MOTION> ReadMotionFile(string filename)
        {
            List <NJS_MOTION> motions = new List <NJS_MOTION>();

            byte[] fc   = File.ReadAllBytes(filename);
            int    addr = 0;

            while (ByteConverter.ToInt64(fc, addr) != 0)
            {
                int ptr = ByteConverter.ToInt32(fc, addr);
                if (ptr == -1)
                {
                    motions.Add(null);
                }
                else
                {
                    motions.Add(new NJS_MOTION(fc, ptr, 0, ByteConverter.ToInt32(fc, addr + 4)));
                }
                addr += 8;
            }
            return(motions);
        }
Ejemplo n.º 6
0
        public LandTable(byte[] file, int address, uint imageBase, LandTableFormat format, Dictionary <int, string> labels)
        {
            Format = format;
            if (labels.ContainsKey(address))
            {
                Name = labels[address];
            }
            else
            {
                Name = "landtable_" + address.ToString("X8");
            }
            short colcnt = ByteConverter.ToInt16(file, address);
            Dictionary <int, Attach> attaches = new Dictionary <int, Attach>();

            switch (format)
            {
            case LandTableFormat.SA1:
            case LandTableFormat.SADX:
                short anicnt = ByteConverter.ToInt16(file, address + 2);
                Flags    = ByteConverter.ToInt32(file, address + 4);
                Unknown1 = ByteConverter.ToSingle(file, address + 8);
                COL      = new List <COL>();
                int tmpaddr = ByteConverter.ToInt32(file, address + 0xC);
                if (tmpaddr != 0)
                {
                    tmpaddr = (int)unchecked ((uint)tmpaddr - imageBase);
                    if (labels.ContainsKey(tmpaddr))
                    {
                        COLName = labels[tmpaddr];
                    }
                    else
                    {
                        COLName = "collist_" + tmpaddr.ToString("X8");
                    }
                    for (int i = 0; i < colcnt; i++)
                    {
                        COL.Add(new COL(file, tmpaddr, imageBase, format, labels, attaches));
                        tmpaddr += SAModel.COL.Size(format);
                    }
                }
                else
                {
                    COLName = "collist_" + Extensions.GenerateIdentifier();
                }
                Anim    = new List <GeoAnimData>();
                tmpaddr = ByteConverter.ToInt32(file, address + 0x10);
                if (tmpaddr != 0)
                {
                    tmpaddr = (int)unchecked ((uint)tmpaddr - imageBase);
                    if (labels.ContainsKey(tmpaddr))
                    {
                        AnimName = labels[tmpaddr];
                    }
                    else
                    {
                        AnimName = "animlist_" + tmpaddr.ToString("X8");
                    }
                    for (int i = 0; i < anicnt; i++)
                    {
                        Anim.Add(new GeoAnimData(file, tmpaddr, imageBase, format, labels, attaches));
                        tmpaddr += GeoAnimData.Size;
                    }
                }
                else
                {
                    AnimName = "animlist_" + Extensions.GenerateIdentifier();
                }
                tmpaddr = ByteConverter.ToInt32(file, address + 0x14);
                if (tmpaddr != 0)
                {
                    tmpaddr         = (int)unchecked ((uint)tmpaddr - imageBase);
                    TextureFileName = file.GetCString(tmpaddr, Encoding.ASCII);
                }
                TextureList = ByteConverter.ToUInt32(file, address + 0x18);
                Unknown2    = ByteConverter.ToInt32(file, address + 0x1C);
                Unknown3    = ByteConverter.ToInt32(file, address + 0x20);
                break;

            case LandTableFormat.SA2:
            case LandTableFormat.SA2B:
                short cnkcnt = ByteConverter.ToInt16(file, address + 2);
                Unknown1 = ByteConverter.ToSingle(file, address + 0xC);
                COL      = new List <COL>();
                tmpaddr  = ByteConverter.ToInt32(file, address + 0x10);
                if (tmpaddr != 0)
                {
                    tmpaddr = (int)unchecked ((uint)tmpaddr - imageBase);
                    if (labels.ContainsKey(tmpaddr))
                    {
                        COLName = labels[tmpaddr];
                    }
                    else
                    {
                        COLName = "collist_" + tmpaddr.ToString("X8");
                    }
                    for (int i = 0; i < colcnt; i++)
                    {
                        COL.Add(new COL(file, tmpaddr, imageBase, format, labels, cnkcnt < 0 ? null : (bool?)(i >= cnkcnt), attaches));
                        tmpaddr += SAModel.COL.Size(format);
                    }
                }
                else
                {
                    COLName = "collist_" + Extensions.GenerateIdentifier();
                }
                Anim     = new List <GeoAnimData>();
                AnimName = "animlist_" + Extensions.GenerateIdentifier();
                tmpaddr  = ByteConverter.ToInt32(file, address + 0x18);
                if (tmpaddr != 0)
                {
                    tmpaddr         = (int)unchecked ((uint)tmpaddr - imageBase);
                    TextureFileName = file.GetCString(tmpaddr, Encoding.ASCII);
                }
                TextureList = ByteConverter.ToUInt32(file, address + 0x1C);
                break;
            }
            Metadata = new Dictionary <uint, byte[]>();
        }
Ejemplo n.º 7
0
        public void SaveToFile(string filename, LandTableFormat format)
        {
            bool be = ByteConverter.BigEndian;

            ByteConverter.BigEndian = false;
            if (format == LandTableFormat.SADX)
            {
                format = LandTableFormat.SA1;
            }
            List <byte> file = new List <byte>();
            ulong       magic;

            switch (format)
            {
            case LandTableFormat.SA1:
                magic = SA1LVLVer;
                break;

            case LandTableFormat.SA2:
                magic = SA2LVLVer;
                break;

            case LandTableFormat.SA2B:
                magic = SA2BLVLVer;
                break;

            default:
                throw new ArgumentException("Cannot save " + format + " format levels to file!", "format");
            }
            file.AddRange(ByteConverter.GetBytes(magic));
            Dictionary <string, uint> labels = new Dictionary <string, uint>();

            byte[] lvl = GetBytes(0x10, format, labels, out uint addr);
            file.AddRange(ByteConverter.GetBytes(addr + 0x10));
            file.AddRange(ByteConverter.GetBytes(lvl.Length + 0x10));
            file.AddRange(lvl);
            if (labels.Count > 0)
            {
                List <byte> chunk    = new List <byte>(labels.Count * 8);
                int         straddr  = (labels.Count * 8) + 8;
                List <byte> strbytes = new List <byte>();
                foreach (KeyValuePair <string, uint> label in labels)
                {
                    chunk.AddRange(ByteConverter.GetBytes(label.Value));
                    chunk.AddRange(ByteConverter.GetBytes(straddr + strbytes.Count));
                    strbytes.AddRange(Encoding.UTF8.GetBytes(label.Key));
                    strbytes.Add(0);
                    strbytes.Align(4);
                }
                chunk.AddRange(ByteConverter.GetBytes(-1L));
                chunk.AddRange(strbytes);
                file.AddRange(ByteConverter.GetBytes((uint)ChunkTypes.Label));
                file.AddRange(ByteConverter.GetBytes(chunk.Count));
                file.AddRange(chunk);
            }
            if (!string.IsNullOrEmpty(Author))
            {
                List <byte> chunk = new List <byte>(Author.Length + 1);
                chunk.AddRange(Encoding.UTF8.GetBytes(Author));
                chunk.Add(0);
                chunk.Align(4);
                file.AddRange(ByteConverter.GetBytes((uint)ChunkTypes.Author));
                file.AddRange(ByteConverter.GetBytes(chunk.Count));
                file.AddRange(chunk);
            }
            if (!string.IsNullOrEmpty(Description))
            {
                List <byte> chunk = new List <byte>(Description.Length + 1);
                chunk.AddRange(Encoding.UTF8.GetBytes(Description));
                chunk.Add(0);
                chunk.Align(4);
                file.AddRange(ByteConverter.GetBytes((uint)ChunkTypes.Description));
                file.AddRange(ByteConverter.GetBytes(chunk.Count));
                file.AddRange(chunk);
            }
            foreach (KeyValuePair <uint, byte[]> item in Metadata)
            {
                file.AddRange(ByteConverter.GetBytes(item.Key));
                file.AddRange(ByteConverter.GetBytes(item.Value.Length));
                file.AddRange(item.Value);
            }
            file.AddRange(ByteConverter.GetBytes((uint)ChunkTypes.End));
            file.AddRange(new byte[4]);
            File.WriteAllBytes(filename, file.ToArray());
            ByteConverter.BigEndian = be;
        }
Ejemplo n.º 8
0
        public byte[] GetBytes(uint imageBase, LandTableFormat format, Dictionary <string, uint> labels, out uint address)
        {
            List <byte> result = new List <byte>();

            byte[]     tmpbyte;
            uint[]     colmdladdrs = new uint[COL.Count];
            uint       tmpaddr;
            List <COL> cnk = new List <COL>();
            List <COL> bas = new List <COL>();

            foreach (COL item in COL)
            {
                if (item.Model.Attach is BasicAttach)
                {
                    bas.Add(item);
                }
                else
                {
                    cnk.Add(item);
                }
            }
            COL.Clear();
            COL.AddRange(cnk);
            COL.AddRange(bas);
            for (int i = 0; i < COL.Count; i++)
            {
                if (labels.ContainsKey(COL[i].Model.Name))
                {
                    colmdladdrs[i] = labels[COL[i].Model.Name];
                }
                else
                {
                    result.Align(4);
                    tmpbyte        = COL[i].Model.GetBytes(imageBase + (uint)result.Count, format == LandTableFormat.SADX, labels, out tmpaddr);
                    colmdladdrs[i] = tmpaddr + (uint)result.Count + imageBase;
                    result.AddRange(tmpbyte);
                }
            }
            uint[] animmdladdrs = new uint[Anim.Count];
            uint[] animaniaddrs = new uint[Anim.Count];
            for (int i = 0; i < Anim.Count; i++)
            {
                if (labels.ContainsKey(Anim[i].Model.Name))
                {
                    animmdladdrs[i] = labels[Anim[i].Model.Name];
                }
                else
                {
                    result.Align(4);
                    tmpbyte = Anim[i].Model.GetBytes(imageBase + (uint)result.Count, format == LandTableFormat.SADX, labels,
                                                     out tmpaddr);
                    animmdladdrs[i] = tmpaddr + (uint)result.Count + imageBase;
                    result.AddRange(tmpbyte);
                }
                uint mtnaddr;
                if (labels.ContainsKey(Anim[i].Animation.Name))
                {
                    mtnaddr = labels[Anim[i].Animation.Name];
                }
                else
                {
                    result.Align(4);
                    result.AddRange(Anim[i].Animation.GetBytes(imageBase + (uint)result.Count, labels, out mtnaddr));
                }
                result.Align(4);
                animaniaddrs[i] = (uint)result.Count + imageBase;
                result.AddRange(ByteConverter.GetBytes(animmdladdrs[i]));
                result.AddRange(ByteConverter.GetBytes(mtnaddr));
            }
            uint coladdr;

            if (COL.Count > 0)
            {
                if (labels.ContainsKey(COLName))
                {
                    coladdr = labels[COLName];
                }
                else
                {
                    coladdr = imageBase + (uint)result.Count;
                    labels.Add(COLName, coladdr);
                    for (int i = 0; i < COL.Count; i++)
                    {
                        result.Align(4);
                        result.AddRange(COL[i].GetBytes(imageBase + (uint)result.Count, colmdladdrs[i], format));
                    }
                }
            }
            else
            {
                coladdr = 0;
            }
            uint animaddr;

            if (Anim.Count > 0)
            {
                if (labels.ContainsKey(AnimName))
                {
                    animaddr = labels[AnimName];
                }
                else
                {
                    animaddr = imageBase + (uint)result.Count;
                    labels.Add(AnimName, animaddr);
                    for (int i = 0; i < Anim.Count; i++)
                    {
                        result.Align(4);
                        result.AddRange(Anim[i].GetBytes(imageBase + (uint)result.Count, animmdladdrs[i], animaniaddrs[i]));
                    }
                }
            }
            else
            {
                animaddr = 0;
            }
            result.Align(4);
            uint texnameaddr = 0;

            if (TextureFileName != null)
            {
                texnameaddr = imageBase + (uint)result.Count;
                result.AddRange(Encoding.ASCII.GetBytes(TextureFileName));
                result.Add(0);
            }
            result.Align(4);
            address = (uint)result.Count;
            result.AddRange(ByteConverter.GetBytes((ushort)COL.Count));
            switch (format)
            {
            case LandTableFormat.SA1:
            case LandTableFormat.SADX:
                result.AddRange(ByteConverter.GetBytes((ushort)Anim.Count));
                result.AddRange(ByteConverter.GetBytes(Flags));
                result.AddRange(ByteConverter.GetBytes(Unknown1));
                result.AddRange(ByteConverter.GetBytes(coladdr));
                result.AddRange(ByteConverter.GetBytes(animaddr));
                result.AddRange(ByteConverter.GetBytes(texnameaddr));
                result.AddRange(ByteConverter.GetBytes(TextureList));
                result.AddRange(ByteConverter.GetBytes(Unknown2));
                result.AddRange(ByteConverter.GetBytes(Unknown3));
                break;

            case LandTableFormat.SA2:
            case LandTableFormat.SA2B:
                result.AddRange(ByteConverter.GetBytes((ushort)cnk.Count));
                result.AddRange(new byte[8]);                         // TODO: figure out what these do
                result.AddRange(ByteConverter.GetBytes(Unknown1));
                result.AddRange(ByteConverter.GetBytes(coladdr));
                result.AddRange(ByteConverter.GetBytes(animaddr));
                result.AddRange(ByteConverter.GetBytes(texnameaddr));
                result.AddRange(ByteConverter.GetBytes(TextureList));
                break;
            }
            labels.Add(Name, address + imageBase);
            return(result.ToArray());
        }
Ejemplo n.º 9
0
        public static LandTable LoadFromFile(string filename)
        {
            bool be = ByteConverter.BigEndian;

            ByteConverter.BigEndian = false;
            byte[] file    = File.ReadAllBytes(filename);
            ulong  magic   = ByteConverter.ToUInt64(file, 0) & FormatMask;
            byte   version = file[7];

            if (version > CurrentVersion)
            {
                throw new FormatException("Not a valid SA1LVL/SA2LVL file.");
            }
            Dictionary <int, string> labels = new Dictionary <int, string>();
            string author = null, description = null;
            Dictionary <uint, byte[]> meta = new Dictionary <uint, byte[]>();

            if (version < 2)
            {
                if (version == 1)
                {
                    int tmpaddr = ByteConverter.ToInt32(file, 0xC);
                    if (tmpaddr != 0)
                    {
                        int addr = ByteConverter.ToInt32(file, tmpaddr);
                        while (addr != -1)
                        {
                            labels.Add(addr, file.GetCString(ByteConverter.ToInt32(file, tmpaddr + 4)));
                            tmpaddr += 8;
                            addr     = ByteConverter.ToInt32(file, tmpaddr);
                        }
                    }
                }
            }
            else
            {
                int tmpaddr = ByteConverter.ToInt32(file, 0xC);
                if (tmpaddr != 0)
                {
                    bool finished = false;
                    while (!finished)
                    {
                        ChunkTypes type      = (ChunkTypes)ByteConverter.ToUInt32(file, tmpaddr);
                        int        chunksz   = ByteConverter.ToInt32(file, tmpaddr + 4);
                        int        nextchunk = tmpaddr + 8 + chunksz;
                        tmpaddr += 8;
                        if (version == 2)
                        {
                            switch (type)
                            {
                            case ChunkTypes.Label:
                                while (ByteConverter.ToInt64(file, tmpaddr) != -1)
                                {
                                    labels.Add(ByteConverter.ToInt32(file, tmpaddr), file.GetCString(ByteConverter.ToInt32(file, tmpaddr + 4)));
                                    tmpaddr += 8;
                                }
                                break;

                            case ChunkTypes.Author:
                                author = file.GetCString(tmpaddr);
                                break;

                            case ChunkTypes.Tool:
                                break;

                            case ChunkTypes.Description:
                                description = file.GetCString(tmpaddr);
                                break;

                            case ChunkTypes.End:
                                finished = true;
                                break;
                            }
                        }
                        else
                        {
                            byte[] chunk = new byte[chunksz];
                            Array.Copy(file, tmpaddr, chunk, 0, chunksz);
                            int chunkaddr = 0;
                            switch (type)
                            {
                            case ChunkTypes.Label:
                                while (ByteConverter.ToInt64(chunk, chunkaddr) != -1)
                                {
                                    labels.Add(ByteConverter.ToInt32(chunk, chunkaddr),
                                               chunk.GetCString(ByteConverter.ToInt32(chunk, chunkaddr + 4)));
                                    chunkaddr += 8;
                                }
                                break;

                            case ChunkTypes.Author:
                                author = chunk.GetCString(0);
                                break;

                            case ChunkTypes.Tool:
                                break;

                            case ChunkTypes.Description:
                                description = chunk.GetCString(0);
                                break;

                            case ChunkTypes.End:
                                finished = true;
                                break;

                            default:
                                meta.Add((uint)type, chunk);
                                break;
                            }
                        }
                        tmpaddr = nextchunk;
                    }
                }
            }
            if (magic == SA1LVL)
            {
                LandTable table = new LandTable(file, ByteConverter.ToInt32(file, 8), 0, LandTableFormat.SA1, labels)
                {
                    Author      = author,
                    Description = description,
                    Metadata    = meta
                };
                ByteConverter.BigEndian = be;
                return(table);
            }
            if (magic == SA2LVL)
            {
                LandTable table = new LandTable(file, ByteConverter.ToInt32(file, 8), 0, LandTableFormat.SA2, labels)
                {
                    Author      = author,
                    Description = description,
                    Metadata    = meta
                };
                ByteConverter.BigEndian = be;
                return(table);
            }
            if (magic == SA2BLVL)
            {
                LandTable table = new LandTable(file, ByteConverter.ToInt32(file, 8), 0, LandTableFormat.SA2B, labels)
                {
                    Author      = author,
                    Description = description,
                    Metadata    = meta
                };
                ByteConverter.BigEndian = be;
                return(table);
            }
            ByteConverter.BigEndian = be;
            throw new FormatException("Not a valid SA1LVL/SA2LVL file.");
        }
Ejemplo n.º 10
0
 public AnimationHeader(byte[] file, int address, uint imageBase, ModelFormat format, Dictionary <int, string> labels)
 {
     Model     = new NJS_OBJECT(file, (int)(ByteConverter.ToUInt32(file, address) - imageBase), imageBase, format);
     Animation = new Animation(file, (int)(ByteConverter.ToUInt32(file, address + 4) - imageBase), imageBase,
                               Model.CountAnimated(), labels);
 }
Ejemplo n.º 11
0
 public PolyChunkMaterial(byte[] file, int address)
 {
     Header   = ByteConverter.ToUInt16(file, address);
     address += sizeof(ushort);
     Size     = ByteConverter.ToUInt16(file, address);
     address += sizeof(ushort);
     switch (Type)
     {
     case ChunkType.Material_Diffuse:
     case ChunkType.Material_DiffuseAmbient:
     case ChunkType.Material_DiffuseSpecular:
     case ChunkType.Material_DiffuseAmbientSpecular:
     case ChunkType.Material_Diffuse2:
     case ChunkType.Material_DiffuseAmbient2:
     case ChunkType.Material_DiffuseSpecular2:
     case ChunkType.Material_DiffuseAmbientSpecular2:
         Diffuse  = VColor.FromBytes(file, address, ColorType.ARGB8888_16);
         address += VColor.Size(ColorType.ARGB8888_16);
         break;
     }
     switch (Type)
     {
     case ChunkType.Material_Ambient:
     case ChunkType.Material_DiffuseAmbient:
     case ChunkType.Material_AmbientSpecular:
     case ChunkType.Material_DiffuseAmbientSpecular:
     case ChunkType.Material_Ambient2:
     case ChunkType.Material_DiffuseAmbient2:
     case ChunkType.Material_AmbientSpecular2:
     case ChunkType.Material_DiffuseAmbientSpecular2:
         Ambient  = VColor.FromBytes(file, address, ColorType.XRGB8888_16);
         address += VColor.Size(ColorType.XRGB8888_16);
         break;
     }
     switch (Type)
     {
     case ChunkType.Material_Specular:
     case ChunkType.Material_DiffuseSpecular:
     case ChunkType.Material_AmbientSpecular:
     case ChunkType.Material_DiffuseAmbientSpecular:
     case ChunkType.Material_Specular2:
     case ChunkType.Material_DiffuseSpecular2:
     case ChunkType.Material_AmbientSpecular2:
     case ChunkType.Material_DiffuseAmbientSpecular2:
         Specular         = VColor.FromBytes(file, address, ColorType.XRGB8888_16);
         SpecularExponent = (byte)(ByteConverter.ToUInt16(file, address + 2) >> 8);
         address         += VColor.Size(ColorType.XRGB8888_16);
         break;
     }
     switch (Type)
     {
     case ChunkType.Material_Diffuse2:
     case ChunkType.Material_Ambient2:
     case ChunkType.Material_DiffuseAmbient2:
     case ChunkType.Material_Specular2:
     case ChunkType.Material_DiffuseSpecular2:
     case ChunkType.Material_AmbientSpecular2:
     case ChunkType.Material_DiffuseAmbientSpecular2:
         Second = true;
         break;
     }
 }
Ejemplo n.º 12
0
        public BasicAttach(byte[] file, int address, uint imageBase, bool DX, Dictionary <int, string> labels)
            : this()
        {
            if (labels.ContainsKey(address))
            {
                Name = labels[address];
            }
            else
            {
                Name = "attach_" + address.ToString("X8");
            }
            Vertex = new Vertex[ByteConverter.ToInt32(file, address + 8)];
            Normal = new Vertex[Vertex.Length];
            int tmpaddr = (int)(ByteConverter.ToUInt32(file, address) - imageBase);

            if (labels.ContainsKey(tmpaddr))
            {
                VertexName = labels[tmpaddr];
            }
            else
            {
                VertexName = "vertex_" + tmpaddr.ToString("X8");
            }
            for (int i = 0; i < Vertex.Length; i++)
            {
                Vertex[i] = new Vertex(file, tmpaddr);
                tmpaddr  += SAModel.Vertex.Size;
            }
            tmpaddr = ByteConverter.ToInt32(file, address + 4);
            if (tmpaddr != 0)
            {
                tmpaddr = (int)((uint)tmpaddr - imageBase);
                if (labels.ContainsKey(tmpaddr))
                {
                    NormalName = labels[tmpaddr];
                }
                else
                {
                    NormalName = "normal_" + tmpaddr.ToString("X8");
                }
                for (int i = 0; i < Vertex.Length; i++)
                {
                    Normal[i] = new Vertex(file, tmpaddr);
                    tmpaddr  += SAModel.Vertex.Size;
                }
            }
            else
            {
                for (int i = 0; i < Vertex.Length; i++)
                {
                    Normal[i] = new Vertex(0, 1, 0);
                }
            }
            int maxmat  = -1;
            int meshcnt = ByteConverter.ToInt16(file, address + 0x14);

            tmpaddr = ByteConverter.ToInt32(file, address + 0xC);
            if (tmpaddr != 0)
            {
                tmpaddr = (int)unchecked ((uint)tmpaddr - imageBase);
                if (labels.ContainsKey(tmpaddr))
                {
                    MeshName = labels[tmpaddr];
                }
                else
                {
                    MeshName = "meshlist_" + tmpaddr.ToString("X8");
                }
                for (int i = 0; i < meshcnt; i++)
                {
                    Mesh.Add(new NJS_MESHSET(file, tmpaddr, imageBase, labels));
                    maxmat   = Math.Max(maxmat, Mesh[i].MaterialID);
                    tmpaddr += NJS_MESHSET.Size(DX);
                }
            }
            // fixes case where model declares material array as shorter than it really is
            int matcnt = Math.Max(ByteConverter.ToInt16(file, address + 0x16), maxmat + 1);

            tmpaddr = ByteConverter.ToInt32(file, address + 0x10);
            if (tmpaddr != 0)
            {
                tmpaddr = (int)unchecked ((uint)tmpaddr - imageBase);
                if (labels.ContainsKey(tmpaddr))
                {
                    MaterialName = labels[tmpaddr];
                }
                else
                {
                    MaterialName = "matlist_" + tmpaddr.ToString("X8");
                }
                for (int i = 0; i < matcnt; i++)
                {
                    Material.Add(new NJS_MATERIAL(file, tmpaddr, labels));
                    tmpaddr += NJS_MATERIAL.Size;
                }
            }
            Bounds = new BoundingSphere(file, address + 0x18);
        }
Ejemplo n.º 13
0
        public byte[] GetBytes()
        {
            VertexChunk next = null;
            int         vertlimit;
            int         vertcount = Vertices.Count;

            switch (Type)
            {
            case ChunkType.Vertex_VertexSH:
                vertlimit = 65535 / 4;
                if (Vertices.Count > vertlimit)
                {
                    next = new VertexChunk(Type)
                    {
                        Vertices = Vertices.Skip(vertlimit).ToList()
                    };
                    vertcount = vertlimit;
                }
                break;

            case ChunkType.Vertex_VertexNormalSH:
                vertlimit = 65535 / 8;
                if (Vertices.Count > vertlimit)
                {
                    next = new VertexChunk(Type)
                    {
                        Vertices = Vertices.Skip(vertlimit).ToList(), Normals = Normals.Skip(vertlimit).ToList()
                    };
                    vertcount = vertlimit;
                }
                break;

            case ChunkType.Vertex_Vertex:
                vertlimit = 65535 / 3;
                if (Vertices.Count > vertlimit)
                {
                    next = new VertexChunk(Type)
                    {
                        Vertices = Vertices.Skip(vertlimit).ToList()
                    };
                    vertcount = vertlimit;
                }
                break;

            case ChunkType.Vertex_VertexDiffuse8:
                vertlimit = 65535 / 4;
                if (Vertices.Count > vertlimit)
                {
                    next = new VertexChunk(Type)
                    {
                        Vertices = Vertices.Skip(vertlimit).ToList(), Diffuse = Diffuse.Skip(vertlimit).ToList()
                    };
                    vertcount = vertlimit;
                }
                break;

            case ChunkType.Vertex_VertexUserFlags:
                vertlimit = 65535 / 4;
                if (Vertices.Count > vertlimit)
                {
                    next = new VertexChunk(Type)
                    {
                        Vertices = Vertices.Skip(vertlimit).ToList(), UserFlags = UserFlags.Skip(vertlimit).ToList()
                    };
                    vertcount = vertlimit;
                }
                break;

            case ChunkType.Vertex_VertexNinjaFlags:
                vertlimit = 65535 / 4;
                if (Vertices.Count > vertlimit)
                {
                    next = new VertexChunk(Type)
                    {
                        Vertices = Vertices.Skip(vertlimit).ToList(), NinjaFlags = NinjaFlags.Skip(vertlimit).ToList()
                    };
                    vertcount = vertlimit;
                }
                break;

            case ChunkType.Vertex_VertexDiffuseSpecular5:
            case ChunkType.Vertex_VertexDiffuseSpecular4:
                vertlimit = 65535 / 4;
                if (Vertices.Count > vertlimit)
                {
                    next = new VertexChunk(Type)
                    {
                        Vertices = Vertices.Skip(vertlimit).ToList(),
                        Diffuse  = Diffuse.Skip(vertlimit).ToList(),
                        Specular = Specular.Skip(vertlimit).ToList()
                    };
                    vertcount = vertlimit;
                }
                break;

            case ChunkType.Vertex_VertexNormal:
                vertlimit = 65535 / 6;
                if (Vertices.Count > vertlimit)
                {
                    next = new VertexChunk(Type)
                    {
                        Vertices = Vertices.Skip(vertlimit).ToList(), Normals = Normals.Skip(vertlimit).ToList()
                    };
                    vertcount = vertlimit;
                }
                break;

            case ChunkType.Vertex_VertexNormalDiffuse8:
                vertlimit = 65535 / 7;
                if (Vertices.Count > vertlimit)
                {
                    next = new VertexChunk(Type)
                    {
                        Vertices = Vertices.Skip(vertlimit).ToList(),
                        Normals  = Normals.Skip(vertlimit).ToList(),
                        Diffuse  = Diffuse.Skip(vertlimit).ToList()
                    };
                    vertcount = vertlimit;
                }
                break;

            case ChunkType.Vertex_VertexNormalUserFlags:
                vertlimit = 65535 / 7;
                if (Vertices.Count > vertlimit)
                {
                    next = new VertexChunk(Type)
                    {
                        Vertices  = Vertices.Skip(vertlimit).ToList(),
                        Normals   = Normals.Skip(vertlimit).ToList(),
                        UserFlags = UserFlags.Skip(vertlimit).ToList()
                    };
                    vertcount = vertlimit;
                }
                break;

            case ChunkType.Vertex_VertexNormalNinjaFlags:
                vertlimit = 65535 / 7;
                if (Vertices.Count > vertlimit)
                {
                    next = new VertexChunk(Type)
                    {
                        Vertices   = Vertices.Skip(vertlimit).ToList(),
                        Normals    = Normals.Skip(vertlimit).ToList(),
                        NinjaFlags = NinjaFlags.Skip(vertlimit).ToList()
                    };
                    vertcount = vertlimit;
                }
                break;

            case ChunkType.Vertex_VertexNormalDiffuseSpecular5:
            case ChunkType.Vertex_VertexNormalDiffuseSpecular4:
                vertlimit = 65535 / 4;
                if (Vertices.Count > vertlimit)
                {
                    next = new VertexChunk(Type)
                    {
                        Vertices = Vertices.Skip(vertlimit).ToList(),
                        Normals  = Normals.Skip(vertlimit).ToList(),
                        Diffuse  = Diffuse.Skip(vertlimit).ToList(),
                        Specular = Specular.Skip(vertlimit).ToList()
                    };
                    vertcount = vertlimit;
                }
                break;

            case ChunkType.End:
                break;

            default:
                throw new NotSupportedException("Unsupported chunk type " + Type + ".");
            }
            SetVertCount(vertcount);
            switch (Type)
            {
            case ChunkType.Vertex_Vertex:
                Size = (ushort)(vertcount * 3 + 1);
                break;

            case ChunkType.Vertex_VertexSH:
            case ChunkType.Vertex_VertexDiffuse8:
            case ChunkType.Vertex_VertexUserFlags:
            case ChunkType.Vertex_VertexNinjaFlags:
            case ChunkType.Vertex_VertexDiffuseSpecular5:
            case ChunkType.Vertex_VertexDiffuseSpecular4:
                Size = (ushort)(vertcount * 4 + 1);
                break;

            case ChunkType.Vertex_VertexNormal:
                Size = (ushort)(vertcount * 6 + 1);
                break;

            case ChunkType.Vertex_VertexNormalDiffuse8:
            case ChunkType.Vertex_VertexNormalUserFlags:
            case ChunkType.Vertex_VertexNormalNinjaFlags:
            case ChunkType.Vertex_VertexNormalDiffuseSpecular5:
            case ChunkType.Vertex_VertexNormalDiffuseSpecular4:
                Size = (ushort)(vertcount * 7 + 1);
                break;

            case ChunkType.Vertex_VertexNormalSH:
                Size = (ushort)(vertcount * 8 + 1);
                break;
            }
            List <byte> result = new List <byte>((Size * 4) + 4);

            result.AddRange(ByteConverter.GetBytes(Header1));
            result.AddRange(ByteConverter.GetBytes(Header2));
            for (int i = 0; i < vertcount; i++)
            {
                switch (Type)
                {
                case ChunkType.Vertex_VertexSH:
                    result.AddRange(Vertices[i].GetBytes());
                    result.AddRange(ByteConverter.GetBytes(1.0f));
                    break;

                case ChunkType.Vertex_VertexNormalSH:
                    result.AddRange(Vertices[i].GetBytes());
                    result.AddRange(ByteConverter.GetBytes(1.0f));
                    result.AddRange(Normals[i].GetBytes());
                    result.AddRange(ByteConverter.GetBytes(1.0f));
                    break;

                case ChunkType.Vertex_Vertex:
                    result.AddRange(Vertices[i].GetBytes());
                    break;

                case ChunkType.Vertex_VertexDiffuse8:
                    result.AddRange(Vertices[i].GetBytes());
                    result.AddRange(VColor.GetBytes(Diffuse[i], ColorType.ARGB8888_32));
                    break;

                case ChunkType.Vertex_VertexUserFlags:
                    result.AddRange(Vertices[i].GetBytes());
                    result.AddRange(ByteConverter.GetBytes(UserFlags[i]));
                    break;

                case ChunkType.Vertex_VertexNinjaFlags:
                    result.AddRange(Vertices[i].GetBytes());
                    result.AddRange(ByteConverter.GetBytes(NinjaFlags[i]));
                    break;

                case ChunkType.Vertex_VertexDiffuseSpecular5:
                    result.AddRange(Vertices[i].GetBytes());
                    result.AddRange(ByteConverter.GetBytes(
                                        ByteConverter.ToUInt16(VColor.GetBytes(Diffuse[i], ColorType.RGB565), 0)
                                        | (ByteConverter.ToUInt16(VColor.GetBytes(Specular[i], ColorType.RGB565), 0) << 16)));
                    break;

                case ChunkType.Vertex_VertexDiffuseSpecular4:
                    result.AddRange(Vertices[i].GetBytes());
                    result.AddRange(ByteConverter.GetBytes(
                                        ByteConverter.ToUInt16(VColor.GetBytes(Diffuse[i], ColorType.ARGB4444), 0)
                                        | (ByteConverter.ToUInt16(VColor.GetBytes(Specular[i], ColorType.RGB565), 0) << 16)));
                    break;

                case ChunkType.Vertex_VertexNormal:
                    result.AddRange(Vertices[i].GetBytes());
                    result.AddRange(Normals[i].GetBytes());
                    break;

                case ChunkType.Vertex_VertexNormalDiffuse8:
                    result.AddRange(Vertices[i].GetBytes());
                    result.AddRange(Normals[i].GetBytes());
                    result.AddRange(VColor.GetBytes(Diffuse[i], ColorType.ARGB8888_32));
                    break;

                case ChunkType.Vertex_VertexNormalUserFlags:
                    result.AddRange(Vertices[i].GetBytes());
                    result.AddRange(Normals[i].GetBytes());
                    result.AddRange(ByteConverter.GetBytes(UserFlags[i]));
                    break;

                case ChunkType.Vertex_VertexNormalNinjaFlags:
                    result.AddRange(Vertices[i].GetBytes());
                    result.AddRange(Normals[i].GetBytes());
                    result.AddRange(ByteConverter.GetBytes(NinjaFlags[i]));
                    break;

                case ChunkType.Vertex_VertexNormalDiffuseSpecular5:
                    result.AddRange(Vertices[i].GetBytes());
                    result.AddRange(Normals[i].GetBytes());
                    result.AddRange(ByteConverter.GetBytes(
                                        ByteConverter.ToUInt16(VColor.GetBytes(Diffuse[i], ColorType.RGB565), 0)
                                        | (ByteConverter.ToUInt16(VColor.GetBytes(Specular[i], ColorType.RGB565), 0) << 16)));
                    break;

                case ChunkType.Vertex_VertexNormalDiffuseSpecular4:
                    result.AddRange(Vertices[i].GetBytes());
                    result.AddRange(Normals[i].GetBytes());
                    result.AddRange(ByteConverter.GetBytes(
                                        ByteConverter.ToUInt16(VColor.GetBytes(Diffuse[i], ColorType.ARGB4444), 0)
                                        | (ByteConverter.ToUInt16(VColor.GetBytes(Specular[i], ColorType.RGB565), 0) << 16)));
                    break;
                }
            }
            if (next != null)
            {
                result.AddRange(next.GetBytes());
            }
            return(result.ToArray());
        }
Ejemplo n.º 14
0
        public VertexChunk(byte[] file, int address)
            : this()
        {
            Header1 = ByteConverter.ToUInt32(file, address);
            Header2 = ByteConverter.ToUInt32(file, address + 4);
            address = address + 8;
            for (int i = 0; i < GetVertCount(); i++)
            {
                switch (Type)
                {
                case ChunkType.Vertex_VertexSH:
                    Vertices.Add(new Vertex(file, address));
                    address += Vertex.Size + sizeof(float);
                    break;

                case ChunkType.Vertex_VertexNormalSH:
                    Vertices.Add(new Vertex(file, address));
                    address += Vertex.Size + sizeof(float);
                    Normals.Add(new Vertex(file, address));
                    address += Vertex.Size + sizeof(float);
                    break;

                case ChunkType.Vertex_Vertex:
                    Vertices.Add(new Vertex(file, address));
                    address += Vertex.Size;
                    break;

                case ChunkType.Vertex_VertexDiffuse8:
                    Vertices.Add(new Vertex(file, address));
                    address += Vertex.Size;
                    Diffuse.Add(VColor.FromBytes(file, address, ColorType.ARGB8888_32));
                    address += VColor.Size(ColorType.ARGB8888_32);
                    break;

                case ChunkType.Vertex_VertexUserFlags:
                    Vertices.Add(new Vertex(file, address));
                    address += Vertex.Size;
                    UserFlags.Add(ByteConverter.ToUInt32(file, address));
                    address += sizeof(uint);
                    break;

                case ChunkType.Vertex_VertexNinjaFlags:
                    Vertices.Add(new Vertex(file, address));
                    address += Vertex.Size;
                    NinjaFlags.Add(ByteConverter.ToUInt32(file, address));
                    address += sizeof(uint);
                    break;

                case ChunkType.Vertex_VertexDiffuseSpecular5:
                    Vertices.Add(new Vertex(file, address));
                    address += Vertex.Size;
                    uint tmpcolor = ByteConverter.ToUInt32(file, address);
                    address += sizeof(uint);
                    Diffuse.Add(VColor.FromBytes(ByteConverter.GetBytes((ushort)(tmpcolor & 0xFFFF)), 0, ColorType.RGB565));
                    Specular.Add(VColor.FromBytes(ByteConverter.GetBytes((ushort)(tmpcolor >> 16)), 0, ColorType.RGB565));
                    break;

                case ChunkType.Vertex_VertexDiffuseSpecular4:
                    Vertices.Add(new Vertex(file, address));
                    address += Vertex.Size;
                    tmpcolor = ByteConverter.ToUInt32(file, address);
                    address += sizeof(uint);
                    Diffuse.Add(VColor.FromBytes(ByteConverter.GetBytes((ushort)(tmpcolor & 0xFFFF)), 0, ColorType.ARGB4444));
                    Specular.Add(VColor.FromBytes(ByteConverter.GetBytes((ushort)(tmpcolor >> 16)), 0, ColorType.RGB565));
                    break;

                case ChunkType.Vertex_VertexNormal:
                    Vertices.Add(new Vertex(file, address));
                    address += Vertex.Size;
                    Normals.Add(new Vertex(file, address));
                    address += Vertex.Size;
                    break;

                case ChunkType.Vertex_VertexNormalDiffuse8:
                    Vertices.Add(new Vertex(file, address));
                    address += Vertex.Size;
                    Normals.Add(new Vertex(file, address));
                    address += Vertex.Size;
                    Diffuse.Add(VColor.FromBytes(file, address, ColorType.ARGB8888_32));
                    address += VColor.Size(ColorType.ARGB8888_32);
                    break;

                case ChunkType.Vertex_VertexNormalUserFlags:
                    Vertices.Add(new Vertex(file, address));
                    address += Vertex.Size;
                    Normals.Add(new Vertex(file, address));
                    address += Vertex.Size;
                    UserFlags.Add(ByteConverter.ToUInt32(file, address));
                    address += sizeof(uint);
                    break;

                case ChunkType.Vertex_VertexNormalNinjaFlags:
                    Vertices.Add(new Vertex(file, address));
                    address += Vertex.Size;
                    Normals.Add(new Vertex(file, address));
                    address += Vertex.Size;
                    NinjaFlags.Add(ByteConverter.ToUInt32(file, address));
                    address += sizeof(uint);
                    break;

                case ChunkType.Vertex_VertexNormalDiffuseSpecular5:
                    Vertices.Add(new Vertex(file, address));
                    address += Vertex.Size;
                    Normals.Add(new Vertex(file, address));
                    address += Vertex.Size;
                    tmpcolor = ByteConverter.ToUInt32(file, address);
                    address += sizeof(uint);
                    Diffuse.Add(VColor.FromBytes(ByteConverter.GetBytes((ushort)(tmpcolor & 0xFFFF)), 0, ColorType.RGB565));
                    Specular.Add(VColor.FromBytes(ByteConverter.GetBytes((ushort)(tmpcolor >> 16)), 0, ColorType.RGB565));
                    break;

                case ChunkType.Vertex_VertexNormalDiffuseSpecular4:
                    Vertices.Add(new Vertex(file, address));
                    address += Vertex.Size;
                    Normals.Add(new Vertex(file, address));
                    address += Vertex.Size;
                    tmpcolor = ByteConverter.ToUInt32(file, address);
                    address += sizeof(uint);
                    Diffuse.Add(VColor.FromBytes(ByteConverter.GetBytes((ushort)(tmpcolor & 0xFFFF)), 0, ColorType.ARGB4444));
                    Specular.Add(VColor.FromBytes(ByteConverter.GetBytes((ushort)(tmpcolor >> 16)), 0, ColorType.RGB565));
                    break;

                default:
                    throw new NotSupportedException("Unsupported chunk type " + Type + " at " + address.ToString("X8") + ".");
                }
            }
        }
Ejemplo n.º 15
0
        public ChunkAttach(byte[] file, int address, uint imageBase, Dictionary <int, string> labels)
            : this()
        {
            if (labels.ContainsKey(address))
            {
                Name = labels[address];
            }
            else
            {
                Name = "attach_" + address.ToString("X8");
            }
            ChunkType ctype;
            int       tmpaddr = ByteConverter.ToInt32(file, address);

            if (tmpaddr != 0)
            {
                tmpaddr = (int)unchecked ((uint)tmpaddr - imageBase);
                Vertex  = new List <VertexChunk>();
                if (labels.ContainsKey(tmpaddr))
                {
                    VertexName = labels[tmpaddr];
                }
                else
                {
                    VertexName = "vertex_" + tmpaddr.ToString("X8");
                }
                ctype = (ChunkType)(ByteConverter.ToUInt32(file, tmpaddr) & 0xFF);
                while (ctype != ChunkType.End)
                {
                    VertexChunk chunk = new VertexChunk(file, tmpaddr);
                    Vertex.Add(chunk);
                    tmpaddr += (chunk.Size * 4) + 4;
                    ctype    = (ChunkType)(ByteConverter.ToUInt32(file, tmpaddr) & 0xFF);
                }
            }
            tmpaddr = ByteConverter.ToInt32(file, address + 4);
            if (tmpaddr != 0)
            {
                tmpaddr = (int)unchecked ((uint)tmpaddr - imageBase);
                Poly    = new List <PolyChunk>();
                if (labels.ContainsKey(tmpaddr))
                {
                    PolyName = labels[tmpaddr];
                }
                else
                {
                    PolyName = "poly_" + tmpaddr.ToString("X8");
                }
                PolyChunk chunk = PolyChunk.Load(file, tmpaddr);
                while (chunk.Type != ChunkType.End)
                {
                    if (chunk.Type != ChunkType.Null)
                    {
                        Poly.Add(chunk);
                    }
                    tmpaddr += chunk.ByteSize;
                    chunk    = PolyChunk.Load(file, tmpaddr);
                }
            }
            Bounds = new BoundingSphere(file, address + 8);
        }
Ejemplo n.º 16
0
        public ModelFile(byte[] file, string filename = null)
        {
            int  tmpaddr;
            bool be = ByteConverter.BigEndian;

            ByteConverter.BigEndian = false;
            ulong magic   = ByteConverter.ToUInt64(file, 0) & FormatMask;
            byte  version = file[7];

            if (version > CurrentVersion)
            {
                throw new FormatException("Not a valid SA1MDL/SA2MDL file.");
            }
            Metadata = new Dictionary <uint, byte[]>();
            Dictionary <int, string> labels   = new Dictionary <int, string>();
            Dictionary <int, Attach> attaches = new Dictionary <int, Attach>();

            if (version < 2)
            {
                if (version == 1)
                {
                    tmpaddr = ByteConverter.ToInt32(file, 0x14);
                    if (tmpaddr != 0)
                    {
                        int addr = ByteConverter.ToInt32(file, tmpaddr);
                        while (addr != -1)
                        {
                            labels.Add(addr, file.GetCString(ByteConverter.ToInt32(file, tmpaddr + 4)));
                            tmpaddr += 8;
                            addr     = ByteConverter.ToInt32(file, tmpaddr);
                        }
                    }
                }
                switch (magic)
                {
                case SA1MDL:
                    Format = ModelFormat.Basic;
                    break;

                case SA2MDL:
                    Format = ModelFormat.Chunk;
                    break;

                default:
                    throw new FormatException("Not a valid SA1MDL/SA2MDL file.");
                }
                Model = new NJS_OBJECT(file, ByteConverter.ToInt32(file, 8), 0, Format, labels, attaches);
                if (filename != null)
                {
                    tmpaddr = ByteConverter.ToInt32(file, 0xC);
                    if (tmpaddr != 0)
                    {
                        List <string> animfiles = new List <string>();
                        int           addr      = ByteConverter.ToInt32(file, tmpaddr);
                        while (addr != -1)
                        {
                            animfiles.Add(file.GetCString(addr));
                            tmpaddr += 4;
                            addr     = ByteConverter.ToInt32(file, tmpaddr);
                        }
                        animationFiles = animfiles.ToArray();
                    }
                    else
                    {
                        animationFiles = new string[0];
                    }
                    string            path  = Path.GetDirectoryName(filename);
                    List <NJS_MOTION> anims = new List <NJS_MOTION>();
                    try
                    {
                        foreach (string item in animationFiles)
                        {
                            anims.Add(NJS_MOTION.Load(Path.Combine(path, item), Model.CountAnimated()));
                        }
                    }
                    catch
                    {
                        anims.Clear();
                    }
                    Animations = anims.AsReadOnly();
                }
            }
            else
            {
                animationFiles = new string[0];
                tmpaddr        = ByteConverter.ToInt32(file, 0xC);
                if (tmpaddr != 0)
                {
                    bool finished = false;
                    while (!finished)
                    {
                        ChunkTypes type      = (ChunkTypes)ByteConverter.ToUInt32(file, tmpaddr);
                        int        chunksz   = ByteConverter.ToInt32(file, tmpaddr + 4);
                        int        nextchunk = tmpaddr + 8 + chunksz;
                        tmpaddr += 8;
                        if (version == 2)
                        {
                            switch (type)
                            {
                            case ChunkTypes.Label:
                                while (ByteConverter.ToInt64(file, tmpaddr) != -1)
                                {
                                    labels.Add(ByteConverter.ToInt32(file, tmpaddr), file.GetCString(ByteConverter.ToInt32(file, tmpaddr + 4)));
                                    tmpaddr += 8;
                                }
                                break;

                            case ChunkTypes.Animation:
                                List <string> animfiles = new List <string>();
                                while (ByteConverter.ToInt32(file, tmpaddr) != -1)
                                {
                                    animfiles.Add(file.GetCString(ByteConverter.ToInt32(file, tmpaddr)));
                                    tmpaddr += 4;
                                }
                                animationFiles = animfiles.ToArray();
                                break;

                            case ChunkTypes.Morph:
                                break;

                            case ChunkTypes.Author:
                                Author = file.GetCString(tmpaddr);
                                break;

                            case ChunkTypes.Tool:
                                break;

                            case ChunkTypes.Description:
                                Description = file.GetCString(tmpaddr);
                                break;

                            case ChunkTypes.Texture:
                                break;

                            case ChunkTypes.End:
                                finished = true;
                                break;
                            }
                        }
                        else
                        {
                            byte[] chunk = new byte[chunksz];
                            Array.Copy(file, tmpaddr, chunk, 0, chunksz);
                            int chunkaddr = 0;
                            switch (type)
                            {
                            case ChunkTypes.Label:
                                while (ByteConverter.ToInt64(chunk, chunkaddr) != -1)
                                {
                                    labels.Add(ByteConverter.ToInt32(chunk, chunkaddr),
                                               chunk.GetCString(ByteConverter.ToInt32(chunk, chunkaddr + 4)));
                                    chunkaddr += 8;
                                }
                                break;

                            case ChunkTypes.Animation:
                                List <string> animchunks = new List <string>();
                                while (ByteConverter.ToInt32(chunk, chunkaddr) != -1)
                                {
                                    animchunks.Add(chunk.GetCString(ByteConverter.ToInt32(chunk, chunkaddr)));
                                    chunkaddr += 4;
                                }
                                animationFiles = animchunks.ToArray();
                                break;

                            case ChunkTypes.Morph:
                                break;

                            case ChunkTypes.Author:
                                Author = chunk.GetCString(chunkaddr);
                                break;

                            case ChunkTypes.Tool:
                                break;

                            case ChunkTypes.Description:
                                Description = chunk.GetCString(chunkaddr);
                                break;

                            case ChunkTypes.End:
                                finished = true;
                                break;

                            default:
                                Metadata.Add((uint)type, chunk);
                                break;
                            }
                        }
                        tmpaddr = nextchunk;
                    }
                }
                switch (magic)
                {
                case SA1MDL:
                    Format = ModelFormat.Basic;
                    break;

                case SA2MDL:
                    Format = ModelFormat.Chunk;
                    break;

                case SA2BMDL:
                    Format = ModelFormat.GC;
                    break;

                default:
                    throw new FormatException("Not a valid SA1MDL/SA2MDL file.");
                }
                Model = new NJS_OBJECT(file, ByteConverter.ToInt32(file, 8), 0, Format, labels, attaches);
                if (filename != null)
                {
                    string            path  = Path.GetDirectoryName(filename);
                    List <NJS_MOTION> anims = new List <NJS_MOTION>();
                    try
                    {
                        foreach (string item in animationFiles)
                        {
                            anims.Add(NJS_MOTION.Load(Path.Combine(path, item), Model.CountAnimated()));
                        }
                    }
                    catch
                    {
                        anims.Clear();
                    }
                    Animations = anims.AsReadOnly();
                }
            }
            ByteConverter.BigEndian = be;
        }
Ejemplo n.º 17
0
        public static void CreateFile(string filename, NJS_OBJECT model, string[] animationFiles, string author,
                                      string description, Dictionary <uint, byte[]> metadata, ModelFormat format)
        {
            bool be = ByteConverter.BigEndian;

            ByteConverter.BigEndian = false;
            if (format == ModelFormat.BasicDX)
            {
                format = ModelFormat.Basic;
            }
            List <byte> file = new List <byte>();
            ulong       magic;

            switch (format)
            {
            case ModelFormat.Basic:
            case ModelFormat.BasicDX:
                magic = SA1MDLVer;
                break;

            case ModelFormat.Chunk:
                magic = SA2MDLVer;
                break;

            case ModelFormat.GC:
                magic = SA2BMDLVer;
                break;

            default:
                throw new ArgumentException("Cannot save " + format.ToString() + " format models to file!", "format");
            }
            file.AddRange(ByteConverter.GetBytes(magic));
            Dictionary <string, uint> labels = new Dictionary <string, uint>();

            byte[] mdl = model.GetBytes(0x10, false, labels, out uint addr);
            file.AddRange(ByteConverter.GetBytes(addr + 0x10));
            file.AddRange(ByteConverter.GetBytes(mdl.Length + 0x10));
            file.AddRange(mdl);

            if (labels.Count > 0)
            {
                List <byte> chunk    = new List <byte>((labels.Count * 8) + 8);
                int         straddr  = (labels.Count * 8) + 8;
                List <byte> strbytes = new List <byte>();
                foreach (KeyValuePair <string, uint> label in labels)
                {
                    chunk.AddRange(ByteConverter.GetBytes(label.Value));
                    chunk.AddRange(ByteConverter.GetBytes(straddr + strbytes.Count));
                    strbytes.AddRange(Encoding.UTF8.GetBytes(label.Key));
                    strbytes.Add(0);
                    strbytes.Align(4);
                }
                chunk.AddRange(ByteConverter.GetBytes(-1L));
                chunk.AddRange(strbytes);
                file.AddRange(ByteConverter.GetBytes((uint)ChunkTypes.Label));
                file.AddRange(ByteConverter.GetBytes(chunk.Count));
                file.AddRange(chunk);
            }
            if (animationFiles != null && animationFiles.Length > 0)
            {
                List <byte> chunk    = new List <byte>((animationFiles.Length + 1) * 4);
                int         straddr  = (animationFiles.Length + 1) * 4;
                List <byte> strbytes = new List <byte>();
                for (int i = 0; i < animationFiles.Length; i++)
                {
                    chunk.AddRange(ByteConverter.GetBytes(straddr + strbytes.Count));
                    strbytes.AddRange(Encoding.UTF8.GetBytes(animationFiles[i]));
                    strbytes.Add(0);
                    strbytes.Align(4);
                }
                chunk.AddRange(ByteConverter.GetBytes(-1));
                chunk.AddRange(strbytes);
                file.AddRange(ByteConverter.GetBytes((uint)ChunkTypes.Animation));
                file.AddRange(ByteConverter.GetBytes(chunk.Count));
                file.AddRange(chunk);
            }
            if (!string.IsNullOrEmpty(author))
            {
                List <byte> chunk = new List <byte>(author.Length + 1);
                chunk.AddRange(Encoding.UTF8.GetBytes(author));
                chunk.Add(0);
                chunk.Align(4);
                file.AddRange(ByteConverter.GetBytes((uint)ChunkTypes.Author));
                file.AddRange(ByteConverter.GetBytes(chunk.Count));
                file.AddRange(chunk);
            }
            if (!string.IsNullOrEmpty(description))
            {
                List <byte> chunk = new List <byte>(description.Length + 1);
                chunk.AddRange(Encoding.UTF8.GetBytes(description));
                chunk.Add(0);
                chunk.Align(4);
                file.AddRange(ByteConverter.GetBytes((uint)ChunkTypes.Description));
                file.AddRange(ByteConverter.GetBytes(chunk.Count));
                file.AddRange(chunk);
            }
            if (metadata != null)
            {
                foreach (KeyValuePair <uint, byte[]> item in metadata)
                {
                    file.AddRange(ByteConverter.GetBytes(item.Key));
                    file.AddRange(ByteConverter.GetBytes(item.Value.Length));
                    file.AddRange(item.Value);
                }
            }
            file.AddRange(ByteConverter.GetBytes((uint)ChunkTypes.End));
            file.AddRange(new byte[4]);
            File.WriteAllBytes(filename, file.ToArray());
            ByteConverter.BigEndian = be;
        }
Ejemplo n.º 18
0
        public void SaveToFile(string filename)
        {
            bool be = ByteConverter.BigEndian;

            ByteConverter.BigEndian = false;
            List <byte> file = new List <byte>();
            ulong       magic;

            switch (Format)
            {
            case ModelFormat.Basic:
                magic = SA1MDLVer;
                break;

            case ModelFormat.Chunk:
                magic = SA2MDLVer;
                break;

            case ModelFormat.GC:
                magic = SA2BMDLVer;
                break;

            default:
                throw new ArgumentException("Cannot save " + Format.ToString() + " format models to file!", "Format");
            }
            file.AddRange(ByteConverter.GetBytes(magic));
            Dictionary <string, uint> labels = new Dictionary <string, uint>();

            byte[] mdl = Model.GetBytes(0x10, false, labels, out uint addr);
            file.AddRange(ByteConverter.GetBytes(addr + 0x10));
            file.AddRange(ByteConverter.GetBytes(mdl.Length + 0x10));
            file.AddRange(mdl);
            string path = Path.GetDirectoryName(filename);

            if (labels.Count > 0)
            {
                List <byte> chunk    = new List <byte>((labels.Count * 8) + 8);
                int         straddr  = (labels.Count * 8) + 8;
                List <byte> strbytes = new List <byte>();
                foreach (KeyValuePair <string, uint> label in labels)
                {
                    chunk.AddRange(ByteConverter.GetBytes(label.Value));
                    chunk.AddRange(ByteConverter.GetBytes(straddr + strbytes.Count));
                    strbytes.AddRange(Encoding.UTF8.GetBytes(label.Key));
                    strbytes.Add(0);
                    strbytes.Align(4);
                }
                chunk.AddRange(ByteConverter.GetBytes(-1L));
                chunk.AddRange(strbytes);
                file.AddRange(ByteConverter.GetBytes((uint)ChunkTypes.Label));
                file.AddRange(ByteConverter.GetBytes(chunk.Count));
                file.AddRange(chunk);
            }
            if (Animations.Count > 0)
            {
                List <byte> chunk    = new List <byte>((Animations.Count + 1) * 4);
                int         straddr  = (Animations.Count + 1) * 4;
                List <byte> strbytes = new List <byte>();
                for (int i = 0; i < Animations.Count; i++)
                {
                    Animations[i].Save(Path.Combine(path, animationFiles[i]));
                    chunk.AddRange(ByteConverter.GetBytes(straddr + strbytes.Count));
                    strbytes.AddRange(Encoding.UTF8.GetBytes(animationFiles[i]));
                    strbytes.Add(0);
                    strbytes.Align(4);
                }
                chunk.AddRange(ByteConverter.GetBytes(-1));
                chunk.AddRange(strbytes);
                file.AddRange(ByteConverter.GetBytes((uint)ChunkTypes.Animation));
                file.AddRange(ByteConverter.GetBytes(chunk.Count));
                file.AddRange(chunk);
            }
            if (!string.IsNullOrEmpty(Author))
            {
                List <byte> chunk = new List <byte>(Author.Length + 1);
                chunk.AddRange(Encoding.UTF8.GetBytes(Author));
                chunk.Add(0);
                chunk.Align(4);
                file.AddRange(ByteConverter.GetBytes((uint)ChunkTypes.Author));
                file.AddRange(ByteConverter.GetBytes(chunk.Count));
                file.AddRange(chunk);
            }
            if (!string.IsNullOrEmpty(Description))
            {
                List <byte> chunk = new List <byte>(Description.Length + 1);
                chunk.AddRange(Encoding.UTF8.GetBytes(Description));
                chunk.Add(0);
                chunk.Align(4);
                file.AddRange(ByteConverter.GetBytes((uint)ChunkTypes.Description));
                file.AddRange(ByteConverter.GetBytes(chunk.Count));
                file.AddRange(chunk);
            }
            foreach (KeyValuePair <uint, byte[]> item in Metadata)
            {
                file.AddRange(ByteConverter.GetBytes(item.Key));
                file.AddRange(ByteConverter.GetBytes(item.Value.Length));
                file.AddRange(item.Value);
            }
            file.AddRange(ByteConverter.GetBytes((uint)ChunkTypes.End));
            file.AddRange(new byte[4]);
            File.WriteAllBytes(filename, file.ToArray());
            ByteConverter.BigEndian = be;
        }
Ejemplo n.º 19
0
        public AnimModelData(byte[] file, int address, uint imageBase, AnimFlags animtype)
        {
            uint posoff = 0, rotoff = 0, scaoff = 0;

            if ((animtype & AnimFlags.Translate) == AnimFlags.Translate)
            {
                posoff = ByteConverter.ToUInt32(file, address);
                if (posoff > 0)
                {
                    posoff = posoff - imageBase;
                }
                address += 4;
            }
            if ((animtype & AnimFlags.Rotate) == AnimFlags.Rotate)
            {
                rotoff = ByteConverter.ToUInt32(file, address);
                if (rotoff > 0)
                {
                    rotoff = rotoff - imageBase;
                }
                address += 4;
            }
            if ((animtype & AnimFlags.Scale) == AnimFlags.Scale)
            {
                scaoff = ByteConverter.ToUInt32(file, address);
                if (scaoff > 0)
                {
                    scaoff = scaoff - imageBase;
                }
                address += 4;
            }
            try
            {
                int tmpaddr;
                if ((animtype & AnimFlags.Translate) == AnimFlags.Translate)
                {
                    int posframes = ByteConverter.ToInt32(file, address);
                    if (posframes > 0)
                    {
                        tmpaddr = (int)posoff;
                        for (int i = 0; i < posframes; i++)
                        {
                            Position.Add(ByteConverter.ToInt32(file, tmpaddr), new Vertex(file, tmpaddr + 4));
                            tmpaddr += 16;
                        }
                    }
                    address += 4;
                }
                if ((animtype & AnimFlags.Rotate) == AnimFlags.Rotate)
                {
                    int rotframes = ByteConverter.ToInt32(file, address);
                    if (rotframes > 0)
                    {
                        tmpaddr = (int)rotoff;
                        for (int i = 0; i < rotframes; i++)
                        {
                            Rotation.Add(ByteConverter.ToInt32(file, tmpaddr), new Rotation(file, tmpaddr + 4));
                            tmpaddr += 16;
                        }
                    }
                    address += 4;
                }
                if ((animtype & AnimFlags.Scale) == AnimFlags.Scale)
                {
                    int scaframes = ByteConverter.ToInt32(file, address);
                    if (scaframes > 0)
                    {
                        tmpaddr = (int)scaoff;
                        for (int i = 0; i < scaframes; i++)
                        {
                            Scale.Add(ByteConverter.ToInt32(file, tmpaddr), new Vertex(file, tmpaddr + 4));
                            tmpaddr += 16;
                        }
                    }
                    address += 4;
                }
            }
            catch (ArgumentOutOfRangeException)
            {
            }
        }
Ejemplo n.º 20
0
        public NJS_MESHSET(byte[] file, int address, uint imageBase, Dictionary <int, string> labels)
        {
            MaterialID  = ByteConverter.ToUInt16(file, address);
            PolyType    = (Basic_PolyType)(MaterialID >> 0xE);
            MaterialID &= 0x3FFF;
            Poly[] polys   = new Poly[ByteConverter.ToInt16(file, address + 2)];
            int    tmpaddr = (int)(ByteConverter.ToUInt32(file, address + 4) - imageBase);

            if (labels.ContainsKey(tmpaddr))
            {
                PolyName = labels[tmpaddr];
            }
            else
            {
                PolyName = "poly_" + tmpaddr.ToString("X8");
            }
            int striptotal = 0;

            for (int i = 0; i < polys.Length; i++)
            {
                polys[i]    = SAModel.Poly.CreatePoly(PolyType, file, tmpaddr);
                striptotal += polys[i].Indexes.Length;
                tmpaddr    += polys[i].Size;
            }
            Poly    = new ReadOnlyCollection <Poly>(polys);
            PAttr   = ByteConverter.ToInt32(file, address + 8);
            tmpaddr = ByteConverter.ToInt32(file, address + 0xC);
            if (tmpaddr != 0)
            {
                tmpaddr = (int)unchecked ((uint)tmpaddr - imageBase);
                if (labels.ContainsKey(tmpaddr))
                {
                    PolyNormalName = labels[tmpaddr];
                }
                else
                {
                    PolyNormalName = "polynormal_" + tmpaddr.ToString("X8");
                }
                PolyNormal = new Vertex[polys.Length];
                for (int i = 0; i < polys.Length; i++)
                {
                    PolyNormal[i] = new Vertex(file, tmpaddr);
                    tmpaddr      += Vertex.Size;
                }
            }
            else
            {
                PolyNormalName = "polynormal_" + Extensions.GenerateIdentifier();
            }
            tmpaddr = ByteConverter.ToInt32(file, address + 0x10);
            if (tmpaddr != 0)
            {
                tmpaddr = (int)unchecked ((uint)tmpaddr - imageBase);
                if (labels.ContainsKey(tmpaddr))
                {
                    VColorName = labels[tmpaddr];
                }
                else
                {
                    VColorName = "vcolor_" + tmpaddr.ToString("X8");
                }
                VColor = new Color[striptotal];
                for (int i = 0; i < striptotal; i++)
                {
                    VColor[i] = SAModel.VColor.FromBytes(file, tmpaddr);
                    tmpaddr  += SAModel.VColor.Size(ColorType.ARGB8888_32);
                }
            }
            else
            {
                VColorName = "vcolor_" + Extensions.GenerateIdentifier();
            }
            tmpaddr = ByteConverter.ToInt32(file, address + 0x14);
            if (tmpaddr != 0)
            {
                tmpaddr = (int)unchecked ((uint)tmpaddr - imageBase);
                if (labels.ContainsKey(tmpaddr))
                {
                    UVName = labels[tmpaddr];
                }
                else
                {
                    UVName = "uv_" + tmpaddr.ToString("X8");
                }
                UV = new UV[striptotal];
                for (int i = 0; i < striptotal; i++)
                {
                    UV[i]    = new UV(file, tmpaddr);
                    tmpaddr += SAModel.UV.Size;
                }
            }
            else
            {
                UVName = "uv_" + Extensions.GenerateIdentifier();
            }
        }
Ejemplo n.º 21
0
        public override byte[] GetBytes(uint imageBase, bool DX, Dictionary <string, uint> labels, out uint address)
        {
            List <byte> result          = new List <byte>();
            uint        materialAddress = 0;

            if (Material != null && Material.Count > 0)
            {
                if (labels.ContainsKey(MaterialName))
                {
                    materialAddress = labels[MaterialName];
                }
                else
                {
                    materialAddress = imageBase;
                    labels.Add(MaterialName, materialAddress);
                    foreach (NJS_MATERIAL item in Material)
                    {
                        result.AddRange(item.GetBytes());
                    }
                }
            }
            uint meshAddress;

            if (labels.ContainsKey(MeshName))
            {
                meshAddress = labels[MeshName];
            }
            else
            {
                uint[] polyAddrs       = new uint[Mesh.Count];
                uint[] polyNormalAddrs = new uint[Mesh.Count];
                uint[] vColorAddrs     = new uint[Mesh.Count];
                uint[] uVAddrs         = new uint[Mesh.Count];
                for (int i = 0; i < Mesh.Count; i++)
                {
                    if (labels.ContainsKey(Mesh[i].PolyName))
                    {
                        polyAddrs[i] = labels[Mesh[i].PolyName];
                    }
                    else
                    {
                        result.Align(4);
                        polyAddrs[i] = (uint)result.Count + imageBase;
                        labels.Add(Mesh[i].PolyName, polyAddrs[i]);
                        for (int j = 0; j < Mesh[i].Poly.Count; j++)
                        {
                            result.AddRange(Mesh[i].Poly[j].GetBytes());
                        }
                    }
                }
                for (int i = 0; i < Mesh.Count; i++)
                {
                    if (Mesh[i].PolyNormal != null && Mesh[i].PolyNormal.Length > 0)
                    {
                        if (labels.ContainsKey(Mesh[i].PolyNormalName))
                        {
                            polyNormalAddrs[i] = labels[Mesh[i].PolyNormalName];
                        }
                        else
                        {
                            result.Align(4);
                            polyNormalAddrs[i] = (uint)result.Count + imageBase;
                            labels.Add(Mesh[i].PolyNormalName, polyNormalAddrs[i]);
                            for (int j = 0; j < Mesh[i].PolyNormal.Length; j++)
                            {
                                result.AddRange(Mesh[i].PolyNormal[j].GetBytes());
                            }
                        }
                    }
                }
                for (int i = 0; i < Mesh.Count; i++)
                {
                    if (Mesh[i].VColor != null && Mesh[i].VColor.Length > 0)
                    {
                        if (labels.ContainsKey(Mesh[i].VColorName))
                        {
                            vColorAddrs[i] = labels[Mesh[i].VColorName];
                        }
                        else
                        {
                            result.Align(4);
                            vColorAddrs[i] = (uint)result.Count + imageBase;
                            labels.Add(Mesh[i].VColorName, vColorAddrs[i]);
                            for (int j = 0; j < Mesh[i].VColor.Length; j++)
                            {
                                result.AddRange(VColor.GetBytes(Mesh[i].VColor[j]));
                            }
                        }
                    }
                }
                for (int i = 0; i < Mesh.Count; i++)
                {
                    if (Mesh[i].UV != null && Mesh[i].UV.Length > 0)
                    {
                        if (labels.ContainsKey(Mesh[i].UVName))
                        {
                            uVAddrs[i] = labels[Mesh[i].UVName];
                        }
                        else
                        {
                            result.Align(4);
                            uVAddrs[i] = (uint)result.Count + imageBase;
                            labels.Add(Mesh[i].UVName, uVAddrs[i]);
                            for (int j = 0; j < Mesh[i].UV.Length; j++)
                            {
                                result.AddRange(Mesh[i].UV[j].GetBytes());
                            }
                        }
                    }
                }
                result.Align(4);
                meshAddress = (uint)result.Count + imageBase;
                labels.Add(MeshName, meshAddress);
                for (int i = 0; i < Mesh.Count; i++)
                {
                    result.AddRange(Mesh[i].GetBytes(polyAddrs[i], polyNormalAddrs[i], vColorAddrs[i], uVAddrs[i], DX));
                }
            }
            result.Align(4);
            uint vertexAddress;

            if (labels.ContainsKey(VertexName))
            {
                vertexAddress = labels[VertexName];
            }
            else
            {
                vertexAddress = (uint)result.Count + imageBase;
                labels.Add(VertexName, vertexAddress);
                foreach (Vertex item in Vertex)
                {
                    if (item == null)
                    {
                        result.AddRange(new byte[SAModel.Vertex.Size]);
                    }
                    else
                    {
                        result.AddRange(item.GetBytes());
                    }
                }
            }
            result.Align(4);
            uint normalAddress;

            if (labels.ContainsKey(NormalName))
            {
                normalAddress = labels[NormalName];
            }
            else
            {
                normalAddress = (uint)result.Count + imageBase;
                labels.Add(NormalName, normalAddress);
                foreach (Vertex item in Normal)
                {
                    if (item == null)
                    {
                        result.AddRange(new byte[SAModel.Vertex.Size]);
                    }
                    else
                    {
                        result.AddRange(item.GetBytes());
                    }
                }
            }
            result.Align(4);
            address = (uint)result.Count;
            result.AddRange(ByteConverter.GetBytes(vertexAddress));
            result.AddRange(ByteConverter.GetBytes(normalAddress));
            result.AddRange(ByteConverter.GetBytes(Vertex.Length));
            result.AddRange(ByteConverter.GetBytes(meshAddress));
            result.AddRange(ByteConverter.GetBytes(materialAddress));
            result.AddRange(ByteConverter.GetBytes((short)Mesh.Count));
            result.AddRange(ByteConverter.GetBytes((short)Material.Count));
            result.AddRange(Bounds.GetBytes());
            if (DX)
            {
                result.AddRange(new byte[4]);
            }
            labels.Add(Name, address + imageBase);
            return(result.ToArray());
        }
Ejemplo n.º 22
0
            public Strip(byte[] file, int address, ChunkType type, byte userFlags)
            {
                Indexes  = new ushort[Math.Abs(ByteConverter.ToInt16(file, address))];
                Reversed = (ByteConverter.ToUInt16(file, address) & 0x8000) == 0x8000;
                address += 2;
                switch (type)
                {
                case ChunkType.Strip_StripUVN:
                case ChunkType.Strip_StripUVH:
                case ChunkType.Strip_StripUVN2:
                case ChunkType.Strip_StripUVH2:
                    UVs = new UV[Indexes.Length];
                    break;

                case ChunkType.Strip_StripColor:
                    VColors = new Color[Indexes.Length];
                    break;

                case ChunkType.Strip_StripUVNColor:
                case ChunkType.Strip_StripUVHColor:
                    UVs     = new UV[Indexes.Length];
                    VColors = new Color[Indexes.Length];
                    break;
                }
                if (userFlags > 0)
                {
                    UserFlags1 = new ushort[Indexes.Length - 2];
                }
                if (userFlags > 1)
                {
                    UserFlags2 = new ushort[Indexes.Length - 2];
                }
                if (userFlags > 2)
                {
                    UserFlags3 = new ushort[Indexes.Length - 2];
                }
                for (int i = 0; i < Indexes.Length; i++)
                {
                    Indexes[i] = ByteConverter.ToUInt16(file, address);
                    address   += 2;
                    switch (type)
                    {
                    case ChunkType.Strip_StripUVN:
                    case ChunkType.Strip_StripUVNColor:
                    case ChunkType.Strip_StripUVN2:
                        UVs[i]   = new UV(file, address, false);
                        address += UV.Size;
                        break;

                    case ChunkType.Strip_StripUVH:
                    case ChunkType.Strip_StripUVHColor:
                    case ChunkType.Strip_StripUVH2:
                        UVs[i]   = new UV(file, address, true);
                        address += UV.Size;
                        break;
                    }
                    switch (type)
                    {
                    case ChunkType.Strip_StripColor:
                    case ChunkType.Strip_StripUVNColor:
                    case ChunkType.Strip_StripUVHColor:
                        VColors[i] = VColor.FromBytes(file, address, ColorType.ARGB8888_16);
                        address   += VColor.Size(ColorType.ARGB8888_16);
                        break;
                    }
                    if (i > 1)
                    {
                        if (userFlags > 0)
                        {
                            UserFlags1[i - 2] = ByteConverter.ToUInt16(file, address);
                            address          += 2;
                            if (userFlags > 1)
                            {
                                UserFlags2[i - 2] = ByteConverter.ToUInt16(file, address);
                                address          += 2;
                                if (userFlags > 2)
                                {
                                    UserFlags3[i - 2] = ByteConverter.ToUInt16(file, address);
                                    address          += 2;
                                }
                            }
                        }
                    }
                }
            }
Ejemplo n.º 23
0
        static void Main(string[] args)
        {
            if (args.Length == 0)
            {
                Console.Write("Filename: ");
                args = new string[] { Console.ReadLine().Trim('"') };
            }
            foreach (string filename in args)
            {
                Console.WriteLine("Splitting file {0}...", filename);
                byte[] fc;
                if (Path.GetExtension(filename).Equals(".prs", StringComparison.OrdinalIgnoreCase))
                {
                    fc = Prs.Decompress(filename);
                }
                else
                {
                    fc = File.ReadAllBytes(filename);
                }
                EventIniData ini = new EventIniData()
                {
                    Name = Path.GetFileNameWithoutExtension(filename)
                };
                string            path = Directory.CreateDirectory(Path.Combine(Path.GetDirectoryName(Path.GetFullPath(filename)), Path.GetFileNameWithoutExtension(filename))).FullName;
                uint              key;
                List <NJS_MOTION> motions = null;
                bool              battle;
                if (fc[0] == 0x81)
                {
                    Console.WriteLine("File is in GC/PC format.");
                    ByteConverter.BigEndian = true;
                    key         = 0x8125FE60;
                    ini.Game    = Game.SA2B;
                    battle      = true;
                    motions     = ReadMotionFile(Path.ChangeExtension(filename, null) + "motion.bin");
                    ini.Motions = motions.Select(a => a?.Name).ToList();
                    foreach (var mtn in motions.Where(a => a != null))
                    {
                        motionfiles[mtn.Name] = new MotionInfo(null, mtn);
                    }
                }
                else
                {
                    Console.WriteLine("File is in DC format.");
                    ByteConverter.BigEndian = false;
                    key      = 0xC600000;
                    ini.Game = Game.SA2;
                    battle   = false;
                }
                int ptr = fc.GetPointer(0x20, key);
                if (ptr != 0)
                {
                    for (int i = 0; i < (battle ? 18 : 16); i++)
                    {
                        string upnam = upgradenames[i];
                        string chnam = upnam;
                        switch (i)
                        {
                        case 0:
                            chnam = "Sonic";
                            break;

                        case 4:
                            chnam = "Shadow";
                            break;

                        case 6:
                            chnam = "Knuckles";
                            break;

                        case 12:
                            chnam = "Rouge";
                            break;

                        case 16:
                            chnam = "Mech Tails";
                            break;

                        case 17:
                            chnam = "Mech Eggman";
                            break;
                        }
                        UpgradeInfo info = new UpgradeInfo();
                        info.RootNode = GetModel(fc, ptr, key, $"{chnam} Root.sa2mdl");
                        if (info.RootNode != null)
                        {
                            int ptr2 = fc.GetPointer(ptr + 4, key);
                            if (ptr2 != 0)
                            {
                                info.AttachNode1 = $"object_{ptr2:X8}";
                            }
                            info.Model1 = GetModel(fc, ptr + 8, key, $"{upnam} Model 1.sa2mdl");
                            ptr2        = fc.GetPointer(ptr + 0xC, key);
                            if (ptr2 != 0)
                            {
                                info.AttachNode2 = $"object_{ptr2:X8}";
                            }
                            info.Model2 = GetModel(fc, ptr + 0x10, key, $"{upnam} Model 2.sa2mdl");
                        }
                        ini.Upgrades.Add(info);
                        ptr += 0x14;
                    }
                }
                else
                {
                    Console.WriteLine("Event contains no character upgrades.");
                }
                ptr = fc.GetPointer(0x18, key);
                if (ptr != 0)
                {
                    for (int i = 0; i < 93; i++)
                    {
                        string name = GetModel(fc, ptr, key, $"Mech Part {i + 1}.sa2mdl");
                        if (name != null)
                        {
                            ini.MechParts.Add(i, name);
                        }
                        ptr += 4;
                    }
                }
                else
                {
                    Console.WriteLine("Event contains no mech parts.");
                }
                int gcnt = ByteConverter.ToInt32(fc, 8);
                ptr = fc.GetPointer(0, key);
                if (ptr != 0)
                {
                    Console.WriteLine("Event contains {0} scene(s).", gcnt + 1);
                    for (int gn = 0; gn <= gcnt; gn++)
                    {
                        Directory.CreateDirectory(Path.Combine(path, $"Scene {gn + 1}"));
                        SceneInfo scn  = new SceneInfo();
                        int       ptr2 = fc.GetPointer(ptr, key);
                        int       ecnt = ByteConverter.ToInt32(fc, ptr + 4);
                        if (ptr2 != 0)
                        {
                            Console.WriteLine("Scene {0} contains {1} entit{2}.", gn + 1, ecnt, ecnt == 1 ? "y" : "ies");
                            for (int en = 0; en < ecnt; en++)
                            {
                                EntityInfo ent = new EntityInfo();
                                ent.Model = GetModel(fc, ptr2, key, $"Scene {gn + 1}\\Entity {en + 1} Model.sa2mdl");
                                if (ent.Model != null)
                                {
                                    ent.Motion = GetMotion(fc, ptr2 + 4, key, $"Scene {gn + 1}\\Entity {en + 1} Motion.saanim", motions, modelfiles[ent.Model].Model.CountAnimated());
                                    if (ent.Motion != null)
                                    {
                                        modelfiles[ent.Model].Motions.Add(motionfiles[ent.Motion].Filename);
                                    }
                                    ent.ShapeMotion = GetMotion(fc, ptr2 + 8, key, $"Scene {gn + 1}\\Entity {en + 1} Shape Motion.saanim", motions, modelfiles[ent.Model].Model.CountMorph());
                                    if (ent.ShapeMotion != null)
                                    {
                                        modelfiles[ent.Model].Motions.Add(motionfiles[ent.ShapeMotion].Filename);
                                    }
                                }
                                if (battle)
                                {
                                    ent.GCModel     = GetGCModel(fc, ptr2 + 12, key, $"Scene {gn + 1}\\Entity {en + 1} GC Model.sa2bmdl");
                                    ent.ShadowModel = GetModel(fc, ptr2 + 16, key, $"Scene {gn + 1}\\Entity {en + 1} Shadow Model.sa2mdl");
                                    ent.Position    = new Vertex(fc, ptr2 + 24);
                                    ent.Flags       = ByteConverter.ToUInt32(fc, ptr2 + 40);
                                }
                                else
                                {
                                    ent.Position = new Vertex(fc, ptr2 + 16);
                                    ent.Flags    = ByteConverter.ToUInt32(fc, ptr2 + 28);
                                }
                                scn.Entities.Add(ent);
                                ptr2 += ini.Game == Game.SA2B ? 0x2C : 0x20;
                            }
                        }
                        else
                        {
                            Console.WriteLine("Scene {0} contains no entities.", gn + 1);
                        }
                        ptr2 = fc.GetPointer(ptr + 8, key);
                        if (ptr2 != 0)
                        {
                            int cnt = ByteConverter.ToInt32(fc, ptr + 12);
                            for (int i = 0; i < cnt; i++)
                            {
                                scn.CameraMotions.Add(GetMotion(fc, ptr2, key, $"Scene {gn + 1}\\Camera Motion {i + 1}.saanim", motions, 1));
                                ptr2 += sizeof(int);
                            }
                        }
                        ptr2 = fc.GetPointer(ptr + 0x18, key);
                        if (ptr2 != 0)
                        {
                            BigInfo big = new BigInfo();
                            big.Model = GetModel(fc, ptr2, key, $"Scene {gn + 1}\\Big Model.sa2mdl");
                            if (big.Model != null)
                            {
                                int anicnt = modelfiles[big.Model].Model.CountAnimated();
                                int ptr3   = fc.GetPointer(ptr2 + 4, key);
                                if (ptr3 != 0)
                                {
                                    int cnt = ByteConverter.ToInt32(fc, ptr2 + 8);
                                    for (int i = 0; i < cnt; i++)
                                    {
                                        big.Motions.Add(new string[] { GetMotion(fc, ptr3, key, $"Scene {gn + 1}\\Big Motion {i + 1}a.saanim", motions, anicnt), GetMotion(fc, ptr3 + 4, key, $"Scene {gn + 1}\\Big Motion {i + 1}b.saanim", motions, anicnt) });
                                        ptr3 += 8;
                                    }
                                }
                            }
                            big.Unknown = ByteConverter.ToInt32(fc, ptr2 + 12);
                            scn.Big     = big;
                        }
                        scn.FrameCount = ByteConverter.ToInt32(fc, ptr + 28);
                        ini.Scenes.Add(scn);
                        ptr += 0x20;
                    }
                }
                else
                {
                    Console.WriteLine("Event contains no scenes.");
                }
                ptr = fc.GetPointer(0x1C, key);
                if (ptr != 0)
                {
                    ini.TailsTails = GetModel(fc, ptr, key, $"Tails' tails.sa2mdl");
                }
                else
                {
                    Console.WriteLine("Event does not contain Tails' tails.");
                }
                foreach (var item in motionfiles.Values)
                {
                    string fn = item.Filename ?? $"Unknown Motion {motions.IndexOf(item.Motion)}.saanim";
                    string fp = Path.Combine(path, fn);
                    item.Motion.Save(fp);
                    ini.Files.Add(fn, HelperFunctions.FileHash(fp));
                }
                foreach (var item in modelfiles.Values)
                {
                    string fp = Path.Combine(path, item.Filename);
                    ModelFile.CreateFile(fp, item.Model, item.Motions.ToArray(), null, null, null, item.Format);
                    ini.Files.Add(item.Filename, HelperFunctions.FileHash(fp));
                }
                JsonSerializer js = new JsonSerializer
                {
                    Formatting        = Formatting.Indented,
                    NullValueHandling = NullValueHandling.Ignore
                };
                using (var tw = File.CreateText(Path.Combine(path, Path.ChangeExtension(Path.GetFileName(filename), ".json"))))
                    js.Serialize(tw, ini);
            }
        }
Ejemplo n.º 24
0
 public PolyChunkTinyTextureID(byte[] file, int address)
 {
     Header = ByteConverter.ToUInt16(file, address);
     Second = Type == ChunkType.Tiny_TextureID2;
     Data   = ByteConverter.ToUInt16(file, address + 2);
 }
Ejemplo n.º 25
0
 public Vertex(byte[] file, int address)
 {
     X = ByteConverter.ToSingle(file, address);
     Y = ByteConverter.ToSingle(file, address + 4);
     Z = ByteConverter.ToSingle(file, address + 8);
 }
Ejemplo n.º 26
0
        public byte[] GetBytes(uint imageBase, Dictionary <string, uint> labels, out uint address)
        {
            List <byte> result = new List <byte>();

            uint[] posoffs = new uint[ModelParts];
            int[]  posframes = new int[ModelParts];
            uint[] rotoffs = new uint[ModelParts];
            int[]  rotframes = new int[ModelParts];
            uint[] scloffs = new uint[ModelParts];
            int[]  sclframes = new int[ModelParts];
            bool   hasPos = false, hasRot = false, hasScl = false;

            foreach (KeyValuePair <int, AnimModelData> model in Models)
            {
                if (model.Value.Position.Count > 0)
                {
                    hasPos = true;
                    result.Align(4);
                    posoffs[model.Key]   = imageBase + (uint)result.Count;
                    posframes[model.Key] = model.Value.Position.Count;
                    foreach (KeyValuePair <int, Vertex> item in model.Value.Position)
                    {
                        result.AddRange(ByteConverter.GetBytes(item.Key));
                        result.AddRange(item.Value.GetBytes());
                    }
                }
                if (model.Value.Rotation.Count > 0)
                {
                    hasRot = true;
                    result.Align(4);
                    rotoffs[model.Key]   = imageBase + (uint)result.Count;
                    rotframes[model.Key] = model.Value.Rotation.Count;
                    foreach (KeyValuePair <int, Rotation> item in model.Value.Rotation)
                    {
                        result.AddRange(ByteConverter.GetBytes(item.Key));
                        result.AddRange(item.Value.GetBytes());
                    }
                }
                if (model.Value.Scale.Count > 0)
                {
                    hasScl = true;
                    result.Align(4);
                    scloffs[model.Key]   = imageBase + (uint)result.Count;
                    sclframes[model.Key] = model.Value.Scale.Count;
                    foreach (KeyValuePair <int, Vertex> item in model.Value.Scale)
                    {
                        result.AddRange(ByteConverter.GetBytes(item.Key));
                        result.AddRange(item.Value.GetBytes());
                    }
                }
            }
            result.Align(4);
            uint modeldata = imageBase + (uint)result.Count;

            if (hasPos & !hasRot & !hasScl)
            {
                hasRot = true;
            }
            if (hasRot & !hasPos & !hasScl)
            {
                hasPos = true;
            }
            if (hasScl & !hasPos & !hasRot)
            {
                hasRot = true;
            }
            for (int i = 0; i < ModelParts; i++)
            {
                if (hasPos)
                {
                    result.AddRange(ByteConverter.GetBytes(posoffs[i]));
                }
                if (hasRot)
                {
                    result.AddRange(ByteConverter.GetBytes(rotoffs[i]));
                }
                if (hasScl)
                {
                    result.AddRange(ByteConverter.GetBytes(scloffs[i]));
                }
                if (hasPos)
                {
                    result.AddRange(ByteConverter.GetBytes(posframes[i]));
                }
                if (hasRot)
                {
                    result.AddRange(ByteConverter.GetBytes(rotframes[i]));
                }
                if (hasScl)
                {
                    result.AddRange(ByteConverter.GetBytes(sclframes[i]));
                }
            }
            result.Align(4);
            address = (uint)result.Count;
            result.AddRange(ByteConverter.GetBytes(modeldata));
            result.AddRange(ByteConverter.GetBytes(Frames));
            AnimFlags flags    = 0;
            ushort    numpairs = 0;

            if (hasPos)
            {
                flags |= AnimFlags.Translate;
                numpairs++;
            }
            if (hasRot)
            {
                flags |= AnimFlags.Rotate;
                numpairs++;
            }
            if (hasScl)
            {
                flags |= AnimFlags.Scale;
                numpairs++;
            }
            result.AddRange(ByteConverter.GetBytes((ushort)flags));
            result.AddRange(ByteConverter.GetBytes(numpairs));
            return(result.ToArray());
        }
Ejemplo n.º 27
0
        public byte[] GetBytes(uint imageBase, bool DX, Dictionary <string, uint> labels, out uint address)
        {
            for (int i = 1; i < Children.Count; i++)
            {
                Children[i - 1].Sibling = Children[i];
            }
            List <byte> result      = new List <byte>();
            uint        childaddr   = 0;
            uint        siblingaddr = 0;
            uint        attachaddr  = 0;

            byte[] tmpbyte;
            if (Children.Count > 0)
            {
                if (labels.ContainsKey(Children[0].Name))
                {
                    childaddr = labels[Children[0].Name];
                }
                else
                {
                    result.Align(4);
                    result.AddRange(Children[0].GetBytes(imageBase, DX, labels, out childaddr));
                    childaddr += imageBase;
                }
            }
            if (Sibling != null)
            {
                if (labels.ContainsKey(Sibling.Name))
                {
                    siblingaddr = labels[Sibling.Name];
                }
                else
                {
                    result.Align(4);
                    tmpbyte      = Sibling.GetBytes(imageBase + (uint)result.Count, DX, labels, out siblingaddr);
                    siblingaddr += imageBase + (uint)result.Count;
                    result.AddRange(tmpbyte);
                }
            }
            if (Attach != null)
            {
                if (labels.ContainsKey(Attach.Name))
                {
                    attachaddr = labels[Attach.Name];
                }
                else
                {
                    result.Align(4);
                    tmpbyte     = Attach.GetBytes(imageBase + (uint)result.Count, DX, labels, out attachaddr);
                    attachaddr += imageBase + (uint)result.Count;
                    result.AddRange(tmpbyte);
                }
            }
            result.Align(4);
            address = (uint)result.Count;
            ObjectFlags flags = GetFlags();

            result.AddRange(ByteConverter.GetBytes((int)flags));
            result.AddRange(ByteConverter.GetBytes(attachaddr));
            result.AddRange(Position.GetBytes());
            result.AddRange(Rotation.GetBytes());
            result.AddRange(Scale.GetBytes());
            result.AddRange(ByteConverter.GetBytes(childaddr));
            result.AddRange(ByteConverter.GetBytes(siblingaddr));
            labels.Add(Name, address + imageBase);
            return(result.ToArray());
        }
Ejemplo n.º 28
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));
         EventIniData ini  = IniSerializer.Deserialize <EventIniData>(Path.Combine(path, Path.ChangeExtension(Path.GetFileName(filename), ".ini")));
         uint         key;
         if (fc[0] == 0x81)
         {
             ByteConverter.BigEndian = true;
             key = 0x8125FE60;
         }
         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 => 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 address));
         }
         fc = modelbytes.ToArray();
         int ptr = fc.GetPointer(0x20, key);
         if (ptr != 0)
         {
             for (int i = 0; i < (ini.Game == Game.SA2B ? 18 : 16); i++)
             {
                 UpgradeInfo info = ini.Upgrades[i];
                 if (info.RootNode != null)
                 {
                     if (labels.ContainsKey(info.RootNode))
                     {
                         ByteConverter.GetBytes(labels[info.RootNode]).CopyTo(fc, ptr);
                     }
                     if (labels.ContainsKey(info.AttachNode1))
                     {
                         ByteConverter.GetBytes(labels[info.AttachNode1]).CopyTo(fc, ptr + 4);
                     }
                     if (labels.ContainsKey(info.Model1))
                     {
                         ByteConverter.GetBytes(labels[info.Model1]).CopyTo(fc, ptr + 8);
                     }
                     if (info.AttachNode2 != null && labels.ContainsKey(info.AttachNode2))
                     {
                         ByteConverter.GetBytes(labels[info.AttachNode2]).CopyTo(fc, ptr + 12);
                     }
                     if (info.Model2 != null && labels.ContainsKey(info.Model2))
                     {
                         ByteConverter.GetBytes(labels[info.Model2]).CopyTo(fc, ptr + 16);
                     }
                 }
                 ptr += 0x14;
             }
         }
         int gcnt = ByteConverter.ToInt32(fc, 8);
         ptr = fc.GetPointer(0, key);
         if (ptr != 0)
         {
             for (int gn = 0; gn <= gcnt; gn++)
             {
                 GroupInfo info = ini.Groups[gn];
                 int       ptr2 = fc.GetPointer(ptr, key);
                 int       ecnt = Math.Min(ByteConverter.ToInt32(fc, ptr + 4), info.Entities?.Count ?? 0);
                 if (ptr2 != 0)
                 {
                     for (int en = 0; en < ecnt; en++)
                     {
                         if (labels.ContainsKey(info.Entities[en]))
                         {
                             ByteConverter.GetBytes(labels[info.Entities[en]]).CopyTo(fc, ptr2);
                         }
                         ptr2 += ini.Game == Game.SA2B ? 0x2C : 0x20;
                     }
                 }
                 ptr2 = fc.GetPointer(ptr + 0x18, key);
                 if (ptr2 != 0 && info.Big != null && labels.ContainsKey(info.Big))
                 {
                     ByteConverter.GetBytes(labels[info.Big]).CopyTo(fc, ptr2);
                 }
                 ptr += 0x20;
             }
         }
         ptr = fc.GetPointer(0x18, key);
         if (ptr != 0)
         {
             for (int i = 0; i < 18; i++)
             {
                 if (ini.MechParts.ContainsKey(i) && labels.ContainsKey(ini.MechParts[i]))
                 {
                     ByteConverter.GetBytes(labels[ini.MechParts[i]]).CopyTo(fc, ptr);
                 }
                 ptr += 4;
             }
         }
         ptr = fc.GetPointer(0x1C, key);
         if (ptr != 0 && ini.TailsTails != null && labels.ContainsKey(ini.TailsTails))
         {
             ByteConverter.GetBytes(labels[ini.TailsTails]).CopyTo(fc, ptr);
         }
         if (Path.GetExtension(filename).Equals(".prs", StringComparison.OrdinalIgnoreCase))
         {
             Prs.Compress(fc, filename);
         }
         else
         {
             File.WriteAllBytes(filename, fc);
         }
     }
 }
Ejemplo n.º 29
0
 static void Main(string[] args)
 {
     if (args.Length == 0)
     {
         Console.Write("Filename: ");
         args = new string[] { Console.ReadLine().Trim('"') };
     }
     foreach (string filename in args)
     {
         Console.WriteLine("Splitting file {0}...", filename);
         byte[] fc;
         if (Path.GetExtension(filename).Equals(".prs", StringComparison.OrdinalIgnoreCase))
         {
             fc = Prs.Decompress(filename);
         }
         else
         {
             fc = File.ReadAllBytes(filename);
         }
         EventIniData ini = new EventIniData()
         {
             Name = Path.GetFileNameWithoutExtension(filename)
         };
         string path = Directory.CreateDirectory(Path.Combine(Path.GetDirectoryName(Path.GetFullPath(filename)), Path.GetFileNameWithoutExtension(filename))).FullName;
         uint   key;
         if (fc[0] == 0x81)
         {
             Console.WriteLine("File is in GC/PC format.");
             ByteConverter.BigEndian = true;
             key      = 0x8125FE60;
             ini.Game = Game.SA2B;
         }
         else
         {
             Console.WriteLine("File is in DC format.");
             ByteConverter.BigEndian = false;
             key      = 0xC600000;
             ini.Game = Game.SA2;
         }
         List <string> nodenames = new List <string>();
         Dictionary <string, KeyValuePair <string, NJS_OBJECT> > modelfiles = new Dictionary <string, KeyValuePair <string, NJS_OBJECT> >();
         int ptr = fc.GetPointer(0x20, key);
         if (ptr != 0)
         {
             for (int i = 0; i < (ini.Game == Game.SA2B ? 18 : 16); i++)
             {
                 UpgradeInfo info = new UpgradeInfo();
                 info.RootNode = GetModel(fc, ptr, key, Path.Combine(path, $"Upgrade {i + 1} Root.sa2mdl"), nodenames, modelfiles);
                 if (info.RootNode != null)
                 {
                     int ptr2 = fc.GetPointer(ptr + 4, key);
                     if (ptr2 != 0)
                     {
                         info.AttachNode1 = $"object_{ptr2:X8}";
                     }
                     info.Model1 = GetModel(fc, ptr + 8, key, Path.Combine(path, $"Upgrade {i + 1} Model 1.sa2mdl"), nodenames, modelfiles);
                     ptr2        = fc.GetPointer(ptr + 0xC, key);
                     if (ptr2 != 0)
                     {
                         info.AttachNode2 = $"object_{ptr2:X8}";
                     }
                     info.Model2 = GetModel(fc, ptr + 0x10, key, Path.Combine(path, $"Upgrade {i + 1} Model 2.sa2mdl"), nodenames, modelfiles);
                 }
                 ini.Upgrades.Add(info);
                 ptr += 0x14;
             }
         }
         else
         {
             Console.WriteLine("Event contains no character upgrades.");
         }
         int gcnt = ByteConverter.ToInt32(fc, 8);
         ptr = fc.GetPointer(0, key);
         if (ptr != 0)
         {
             Console.WriteLine("Event contains {0} group(s).", gcnt + 1);
             for (int gn = 0; gn <= gcnt; gn++)
             {
                 GroupInfo info = new GroupInfo();
                 int       ptr2 = fc.GetPointer(ptr, key);
                 int       ecnt = ByteConverter.ToInt32(fc, ptr + 4);
                 if (ptr2 != 0)
                 {
                     Console.WriteLine("Group {0} contains {1} entit{2}.", gn + 1, ecnt, ecnt == 1 ? "y" : "ies");
                     for (int en = 0; en < ecnt; en++)
                     {
                         string name = GetModel(fc, ptr2, key, Path.Combine(path, $"Group {gn + 1} Entity {en + 1} Model.sa2mdl"), nodenames, modelfiles);
                         if (name != null)
                         {
                             info.Entities.Add(name);
                         }
                         ptr2 += ini.Game == Game.SA2B ? 0x2C : 0x20;
                     }
                 }
                 else
                 {
                     Console.WriteLine("Group {0} contains no entities.", gn + 1);
                 }
                 ptr2 = fc.GetPointer(ptr + 0x18, key);
                 if (ptr2 != 0)
                 {
                     info.Big = GetModel(fc, ptr2, key, Path.Combine(path, $"Group {gn + 1} Big Model.sa2mdl"), nodenames, modelfiles);
                 }
                 ini.Groups.Add(info);
                 ptr += 0x20;
             }
         }
         else
         {
             Console.WriteLine("Event contains no groups.");
         }
         ptr = fc.GetPointer(0x18, key);
         if (ptr != 0)
         {
             for (int i = 0; i < 93; i++)
             {
                 string name = GetModel(fc, ptr, key, Path.Combine(path, $"Mech Part {i + 1}.sa2mdl"), nodenames, modelfiles);
                 if (name != null)
                 {
                     ini.MechParts.Add(i, name);
                 }
                 ptr += 4;
             }
         }
         else
         {
             Console.WriteLine("Event contains no mech parts.");
         }
         ptr = fc.GetPointer(0x1C, key);
         if (ptr != 0)
         {
             ini.TailsTails = GetModel(fc, ptr, key, Path.Combine(path, $"Tails tails.sa2mdl"), nodenames, modelfiles);
         }
         else
         {
             Console.WriteLine("Event does not contain Tails' tails.");
         }
         foreach (var item in modelfiles)
         {
             ModelFile.CreateFile(item.Value.Key, item.Value.Value, null, null, null, null, null, ModelFormat.Chunk);
             ini.Files.Add(Path.GetFileName(item.Value.Key), HelperFunctions.FileHash(item.Value.Key));
         }
         IniSerializer.Serialize(ini, Path.Combine(path, Path.ChangeExtension(Path.GetFileName(filename), ".ini")));
     }
 }
Ejemplo n.º 30
0
        public static PolyChunk Load(byte[] file, int address)
        {
            ChunkType type = (ChunkType)(ByteConverter.ToUInt16(file, address) & 0xFF);

            switch (type)
            {
            case ChunkType.Null:
                return(new PolyChunkNull(file, address));

            case ChunkType.Bits_BlendAlpha:
                return(new PolyChunkBitsBlendAlpha(file, address));

            case ChunkType.Bits_MipmapDAdjust:
                return(new PolyChunkBitsMipmapDAdjust(file, address));

            case ChunkType.Bits_SpecularExponent:
                return(new PolyChunkBitsSpecularExponent(file, address));

            case ChunkType.Bits_CachePolygonList:
                return(new PolyChunkBitsCachePolygonList(file, address));

            case ChunkType.Bits_DrawPolygonList:
                return(new PolyChunkBitsDrawPolygonList(file, address));

            case ChunkType.Tiny_TextureID:
            case ChunkType.Tiny_TextureID2:
                return(new PolyChunkTinyTextureID(file, address));

            case ChunkType.Material_Diffuse:
            case ChunkType.Material_Ambient:
            case ChunkType.Material_DiffuseAmbient:
            case ChunkType.Material_Specular:
            case ChunkType.Material_DiffuseSpecular:
            case ChunkType.Material_AmbientSpecular:
            case ChunkType.Material_DiffuseAmbientSpecular:
            case ChunkType.Material_Diffuse2:
            case ChunkType.Material_Ambient2:
            case ChunkType.Material_DiffuseAmbient2:
            case ChunkType.Material_Specular2:
            case ChunkType.Material_DiffuseSpecular2:
            case ChunkType.Material_AmbientSpecular2:
            case ChunkType.Material_DiffuseAmbientSpecular2:
                return(new PolyChunkMaterial(file, address));

            case ChunkType.Material_Bump:
                return(new PolyChunkMaterialBump(file, address));

            case ChunkType.Volume_Polygon3:
            case ChunkType.Volume_Polygon4:
            case ChunkType.Volume_Strip:
                return(new PolyChunkVolume(file, address));

            case ChunkType.Strip_Strip:
            case ChunkType.Strip_StripUVN:
            case ChunkType.Strip_StripUVH:
            case ChunkType.Strip_StripColor:
            case ChunkType.Strip_StripUVNColor:
            case ChunkType.Strip_StripUVHColor:
            case ChunkType.Strip_Strip2:
            case ChunkType.Strip_StripUVN2:
            case ChunkType.Strip_StripUVH2:
                return(new PolyChunkStrip(file, address));

            case ChunkType.End:
                return(new PolyChunkEnd(file, address));

            default:
                throw new NotSupportedException("Unsupported chunk type " + type + " at " + address.ToString("X8") + ".");
            }
        }