Exemple #1
0
        public static Animation Load(string filename, int nummodels)
        {
            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 SAANIM file.");
            }
            int aniaddr = ByteConverter.ToInt32(file, 8);
            Dictionary <int, string> labels = new Dictionary <int, string>();
            int tmpaddr = BitConverter.ToInt32(file, 0xC);

            if (tmpaddr != 0)
            {
                labels.Add(aniaddr, file.GetCString(tmpaddr));
            }
            if (magic == SAANIM)
            {
                Animation anim = new Animation(file, aniaddr, 0, nummodels, labels);
                ByteConverter.BigEndian = be;
                return(anim);
            }
            ByteConverter.BigEndian = be;
            throw new FormatException("Not a valid SAANIM file.");
        }
Exemple #2
0
        public static bool CheckAnimationFile(string filename)
        {
            bool be = ByteConverter.BigEndian;

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

            ByteConverter.BigEndian = be;
            if (magic == SAANIM)
            {
                return(file[7] <= CurrentVersion);
            }
            return(false);
        }
Exemple #3
0
        public static bool CheckLevelFile(string filename)
        {
            bool be = ByteConverter.BigEndian;

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

            ByteConverter.BigEndian = be;
            switch (format)
            {
            case SA1LVL:
            case SA2LVL:
                return(file[7] <= CurrentVersion);

            default:
                return(false);
            }
        }
Exemple #4
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, tool = 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:
                                tool = file.GetCString(tmpaddr);
                                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:
                                tool = chunk.GetCString(0);
                                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,
                    Tool        = tool,
                    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,
                    Tool        = tool,
                    Metadata    = meta
                };
                ByteConverter.BigEndian = be;
                return(table);
            }
            ByteConverter.BigEndian = be;
            throw new FormatException("Not a valid SA1LVL/SA2LVL file.");
        }
Exemple #5
0
        public ModelFile(string filename)
        {
            int  tmpaddr;
            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 SA1MDL/SA2MDL file.");
            }
            Metadata = new Dictionary <uint, byte[]>();
            Dictionary <int, string> labels = new Dictionary <int, string>();

            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);
                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 <Animation> anims = new List <Animation>();
                foreach (string item in animationFiles)
                {
                    anims.Add(Animation.Load(Path.Combine(path, item), Model.CountAnimated()));
                }
                Animations = anims.AsReadOnly();
                if (version == 1)
                {
                    tmpaddr = ByteConverter.ToInt32(file, 0x10);
                    if (tmpaddr != 0)
                    {
                        List <string> morphfiles = new List <string>();
                        int           addr       = ByteConverter.ToInt32(file, tmpaddr);
                        while (addr != -1)
                        {
                            morphfiles.Add(file.GetCString(addr));
                            tmpaddr += 4;
                            addr     = ByteConverter.ToInt32(file, tmpaddr);
                        }
                        morphFiles = morphfiles.ToArray();
                    }
                    else
                    {
                        morphFiles = new string[0];
                    }
                    List <Animation> morphs = new List <Animation>();
                    foreach (string item in morphFiles)
                    {
                        morphs.Add(Animation.Load(Path.Combine(path, item), Model.CountMorph()));
                    }
                    Morphs = morphs.AsReadOnly();
                }
                else
                {
                    morphFiles = new string[0];
                    Morphs     = new ReadOnlyCollection <Animation>(new List <Animation>());
                }
            }
            else
            {
                animationFiles = new string[0];
                morphFiles     = 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:
                                List <string> morphfiles = new List <string>();
                                while (ByteConverter.ToInt32(file, tmpaddr) != -1)
                                {
                                    morphfiles.Add(file.GetCString(ByteConverter.ToInt32(file, tmpaddr)));
                                    tmpaddr += 4;
                                }
                                morphFiles = morphfiles.ToArray();
                                break;

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

                            case ChunkTypes.Tool:
                                Tool = file.GetCString(tmpaddr);
                                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:
                                List <string> morphchunks = new List <string>();
                                while (ByteConverter.ToInt32(chunk, chunkaddr) != -1)
                                {
                                    morphchunks.Add(chunk.GetCString(ByteConverter.ToInt32(chunk, chunkaddr)));
                                    chunkaddr += 4;
                                }
                                morphFiles = morphchunks.ToArray();
                                break;

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

                            case ChunkTypes.Tool:
                                Tool = chunk.GetCString(chunkaddr);
                                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;

                default:
                    throw new FormatException("Not a valid SA1MDL/SA2MDL file.");
                }
                Model = new NJS_OBJECT(file, ByteConverter.ToInt32(file, 8), 0, Format, labels);
                string           path  = Path.GetDirectoryName(filename);
                List <Animation> anims = new List <Animation>();
                foreach (string item in animationFiles)
                {
                    anims.Add(Animation.Load(Path.Combine(path, item), Model.CountAnimated()));
                }
                Animations = anims.AsReadOnly();
                List <Animation> morphs = new List <Animation>();
                foreach (string item in morphFiles)
                {
                    morphs.Add(Animation.Load(Path.Combine(path, item), Model.CountMorph()));
                }
                Morphs = morphs.AsReadOnly();
            }
            ByteConverter.BigEndian = be;
        }
Exemple #6
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);
                    if (File.Exists(Path.GetFileNameWithoutExtension(filename) + ".action"))
                    {
                        using (TextReader tr = File.OpenText(Path.GetFileNameWithoutExtension(filename) + ".action"))
                        {
                            List <string> animlist = new List <string>();
                            int           count    = File.ReadLines(Path.GetFileNameWithoutExtension(filename) + ".action").Count();
                            for (int i = 0; i < count; i++)
                            {
                                string line = tr.ReadLine();
                                if (File.Exists(Path.Combine(path, line)))
                                {
                                    animlist.Add(line);
                                }
                            }
                            animationFiles = animlist.ToArray();
                        }
                    }
                    List <NJS_MOTION> anims = new List <NJS_MOTION>();
                    try
                    {
                        foreach (string item in animationFiles)
                        {
                            if (Path.GetExtension(item).ToLowerInvariant() == ".json")
                            {
                                JsonSerializer js = new JsonSerializer()
                                {
                                    Culture = System.Globalization.CultureInfo.InvariantCulture
                                };
                                using (TextReader tr = File.OpenText(Path.Combine(path, item)))
                                {
                                    using (JsonTextReader jtr = new JsonTextReader(tr))
                                        anims.Add(js.Deserialize <NJS_MOTION>(jtr));
                                }
                            }
                            else
                            {
                                anims.Add(NJS_MOTION.Load(Path.Combine(path, item), Model.CountAnimated()));
                            }
                        }
                    }
                    catch
                    {
                        anims.Clear();
                    }
                    Animations = anims.AsReadOnly();
                }
            }
            ByteConverter.BigEndian = be;
        }