예제 #1
0
파일: SDAT.cs 프로젝트: awiebe/SM64DSe
        private byte[] GetFile(NitroFile sdat, uint fileID)
        {
            uint fatOffset = sdat.Read32(0x20);

            return(sdat.ReadBlock(sdat.Read32(fatOffset + 12 + 16 * fileID),
                                  sdat.Read32(fatOffset + 16 + 16 * fileID)));
        }
예제 #2
0
 public Cwdh(NitroFile file, WidthRegion firstReg)
     : base(file)
 {
     WidthRegion.ResetCount();
     this.firstRegion = firstReg;
     this.Size = 0x08 + this.firstRegion.GetTotalSize();
 }
예제 #3
0
        public BMD ConvertModelToBMD(ref NitroFile modelFile, string fileName, Vector3 scale, BMDExtraImportOptions extraOptions,
                                     bool save = true)
        {
            BMD importedModel = null;

            string modelFormat = fileName.Substring(fileName.Length - 3, 3).ToLower();

            switch (modelFormat)
            {
            case "obj":
                importedModel = ConvertOBJToBMD(ref modelFile, fileName, scale, extraOptions, save);
                break;

            case "dae":
                importedModel = ConvertDAEToBMD(ref modelFile, fileName, scale, extraOptions, save);
                break;

            case "imd":
                importedModel = ConvertIMDToBMD(ref modelFile, fileName, scale, extraOptions, save);
                break;

            default:
                importedModel = ConvertOBJToBMD(ref modelFile, fileName, scale, extraOptions, save);
                break;
            }

            return(importedModel);
        }
예제 #4
0
파일: Nclr.cs 프로젝트: pleonex/ninoimager
        public Nclr()
        {
            this.nitro = new NitroFile("NCLR", "1.0", BlockTypes);
            this.pltt = new Pltt(this.nitro);

            this.nitro.Blocks.Add(this.pltt);
        }
예제 #5
0
        public KCL ConvertModelToKCL(NitroFile modelFile, string fileName, float scale, float faceSizeThreshold,
                                     Dictionary <string, int> matColTypes, bool save = true)
        {
            KCL importedModel = null;

            string modelFormat = fileName.Substring(fileName.Length - 3, 3).ToLower();

            switch (modelFormat)
            {
            case "obj":
                importedModel = ConvertOBJToKCL(modelFile, fileName, scale, faceSizeThreshold, matColTypes, save);
                break;

            case "dae":
                importedModel = ConvertDAEToKCL(modelFile, fileName, scale, faceSizeThreshold, matColTypes, save);
                break;

            case "imd":
                importedModel = ConvertIMDToKCL(modelFile, fileName, scale, faceSizeThreshold, matColTypes, save);
                break;

            default:
                importedModel = ConvertOBJToKCL(modelFile, fileName, scale, faceSizeThreshold, matColTypes, save);
                break;
            }

            return(importedModel);
        }
예제 #6
0
        public static BCA ConvertAnimatedDAEToBCA(ref NitroFile animationFile, string fileName, BMDImporter.BCAImportationOptions bcaImportationOptions, bool save = true)
        {
            ModelBase loadedModel = new DAELoader(fileName).LoadModel();

            BCA importedAnimation = CallBCAWriter(ref animationFile, loadedModel, bcaImportationOptions, save);

            return(importedAnimation);
        }
예제 #7
0
        public static BCA CallBCAWriter(ref NitroFile animationFile, ModelBase model, BMDImporter.BCAImportationOptions bcaImportationOptions, bool save = true)
        {
            AbstractModelWriter bcaWriter = new BCAWriter(model, ref animationFile, bcaImportationOptions);

            bcaWriter.WriteModel(save);

            return(new BCA(animationFile));
        }
예제 #8
0
        protected BMD CallBMDWriter(ref NitroFile modelFile, ModelBase model, BMDExtraImportOptions extraOptions, bool save = true)
        {
            AbstractModelWriter bmdWriter = new BMDWriter(model, ref modelFile, extraOptions);

            bmdWriter.WriteModel(save);

            return(new BMD(modelFile));
        }
예제 #9
0
        public Cmap(NitroFile file)
            : base(file)
        {
            this.Id = IdMap++;

            this.Map = new int[0, 2];
            this.Size = 8 + 0xC;
        }
예제 #10
0
        protected BCA CallBCAWriter(ref NitroFile animationFile, ModelBase model, bool save = true)
        {
            AbstractModelWriter bcaWriter = new BCAWriter(model, ref animationFile);

            bcaWriter.WriteModel(save);

            return(new BCA(animationFile));
        }
예제 #11
0
 public Finf(NitroFile file)
     : base(file)
 {
     if (file.VersionS != "1.2")
         this.Size = 0x1C;
     else
         this.Size = 0x20;
 }
예제 #12
0
 public KCLWriter(ModelBase model, NitroFile modelFile, float scale, float faceSizeThreshold,
                  Dictionary <string, int> matColTypes) :
     base(model, modelFile.m_Name)
 {
     m_ModelFile         = modelFile;
     m_Scale             = scale;
     m_FaceSizeThreshold = faceSizeThreshold;
     m_MatColTypes       = matColTypes;
 }
예제 #13
0
        public static void ConvertToKCL(ModelBase model, ref NitroFile kclOut, float scale, float faceSizeThreshold,
                                        Dictionary <string, int> matColTypes)
        {
            // faceSizeThreshold is used for getting rid of very small faces below a given size, originally 0.001
            List <Triangle> triangles = readLoadedModel(model, faceSizeThreshold, matColTypes);

            scale *= 1000; //Scale of collision file is 1000 times larger than model file
            write_kcl(kclOut, triangles, 15, 1, scale);
        }
예제 #14
0
        public BCA ConvertAnimatedDAEToBCA(ref NitroFile animationFile, string fileName, bool save = true)
        {
            if (m_LoadedModel == null)
                m_LoadedModel = new DAELoader(fileName).LoadModel();

            BCA importedAnimation = CallBCAWriter(ref animationFile, m_LoadedModel, save);

            return importedAnimation;
        }
예제 #15
0
        public static KCL CallKCLWriter(NitroFile modelFile, ModelBase model, float scale, float faceSizeThreshold,
                                        Dictionary <string, int> matColTypes, bool save = true)
        {
            AbstractModelWriter kclWriter = new KCLWriter(model, modelFile, scale, faceSizeThreshold, matColTypes);

            kclWriter.WriteModel(save);

            return(new KCL(modelFile));
        }
예제 #16
0
파일: SDAT.cs 프로젝트: awiebe/SM64DSe
            public SDAT_File(string name, NitroFile file, uint fileID)
            {
                m_Name = name;
                uint fatOffset = file.Read32(0x20);

                m_Data        = new INitroROMBlock();
                m_Data.m_Data = file.ReadBlock(file.Read32(fatOffset + 12 + 16 * fileID),
                                               file.Read32(fatOffset + 16 + 16 * fileID));
            }
예제 #17
0
        public static BCA ConvertICAToBCA(ref NitroFile animationFile, string fileName, ModelBase loadedModel, float scale,
                                          BMDExtraImportOptions extraOptions, BMDImporter.BCAImportationOptions bcaImportationOptions, bool save = true)
        {
            ModelBase animatedModel = new NITROIntermediateCharacterAnimationLoader(loadedModel, fileName).LoadModel(scale);

            BCA importedAnimation = CallBCAWriter(ref animationFile, animatedModel, bcaImportationOptions, save);

            return(importedAnimation);
        }
예제 #18
0
        public BCA ConvertICAToBCA(ref NitroFile animationFile, string fileName, Vector3 scale,
                                   BMDExtraImportOptions extraOptions, bool save = true)
        {
            m_LoadedModel = new NITROIntermediateCharacterAnimationLoader(m_LoadedModel, fileName).LoadModel(scale);

            BCA importedAnimation = CallBCAWriter(ref animationFile, m_LoadedModel, save);

            return(importedAnimation);
        }
예제 #19
0
        public static BMD ConvertModelToBMD(ref NitroFile modelFile, string fileName, float scale, BMDExtraImportOptions extraOptions,
                                            bool save = true)
        {
            BMD importedModel = null;

            ModelBase loadedModel = GetModelLoader(fileName).LoadModel(scale);

            importedModel = CallBMDWriter(ref modelFile, loadedModel, extraOptions, save);

            return(importedModel);
        }
예제 #20
0
        public BCA ConvertAnimatedDAEToBCA(ref NitroFile animationFile, string fileName, bool save = true)
        {
            if (m_LoadedModel == null)
            {
                m_LoadedModel = new DAELoader(fileName).LoadModel();
            }

            BCA importedAnimation = CallBCAWriter(ref animationFile, m_LoadedModel, save);

            return(importedAnimation);
        }
예제 #21
0
        public static BMD ConvertIMDToBMD(ref NitroFile modelFile, string fileName, float scale, BMDExtraImportOptions extraOptions,
                                          bool save = true)
        {
            BMD importedModel = new BMD(modelFile);

            ModelBase loadedModel = new NITROIntermediateModelDataLoader(fileName).LoadModel(scale);

            importedModel = CallBMDWriter(ref modelFile, loadedModel, extraOptions, save);

            return(importedModel);
        }
예제 #22
0
        public static KCL ConvertOBJToKCL(NitroFile modelFile, string fileName, float scale, float faceSizeThreshold,
                                          Dictionary <string, int> matColTypes, bool save = true)
        {
            KCL importedModel = new KCL(modelFile);

            ModelBase loadedModel = new OBJLoader(fileName).LoadModel();

            importedModel = CallKCLWriter(modelFile, loadedModel, scale, faceSizeThreshold, matColTypes, save);

            return(importedModel);
        }
예제 #23
0
        public BMD ConvertDAEToBMD(ref NitroFile modelFile, string fileName, Vector3 scale, BMDExtraImportOptions extraOptions, 
            bool save = true)
        {
            BMD importedModel = new BMD(modelFile);

            if (m_LoadedModel == null)
                m_LoadedModel = new DAELoader(fileName).LoadModel(scale);

            importedModel = CallBMDWriter(ref modelFile, m_LoadedModel, extraOptions, save);

            return importedModel;
        }
예제 #24
0
        public KCL ConvertOBJToKCL(NitroFile modelFile, string fileName, float scale, float faceSizeThreshold,
            Dictionary<string, int> matColTypes, bool save = true)
        {
            KCL importedModel = new KCL(modelFile);

            if (m_LoadedModel == null)
                m_LoadedModel = new OBJLoader(fileName).LoadModel();

            importedModel = CallKCLWriter(modelFile, m_LoadedModel, fileName, scale, faceSizeThreshold, matColTypes, save);

            return importedModel;
        }
예제 #25
0
        public BMDWriter(ModelBase model, ref NitroFile modelFile, BMDImporter.BMDExtraImportOptions extraOptions)
            : base(model, modelFile.m_Name)
        {
            m_ModelFile = modelFile;
            m_ConvertToTriangleStrips = extraOptions.m_ConvertToTriangleStrips;
            m_KeepVertexOrderDuringStripping = extraOptions.m_KeepVertexOrderDuringStripping;
            m_AlwaysWriteFullVertexCmd23h = extraOptions.m_AlwaysWriteFullVertexCmd23h;

            if (m_ConvertToTriangleStrips)
            {
                Stripify();
            }
        }
예제 #26
0
        public BMD ConvertIMDToBMD(ref NitroFile modelFile, string fileName, Vector3 scale, BMDExtraImportOptions extraOptions,
                                   bool save = true)
        {
            BMD importedModel = new BMD(modelFile);

            if (m_LoadedModel == null)
            {
                m_LoadedModel = new NITROIntermediateModelDataLoader(fileName).LoadModel(scale);
            }

            importedModel = CallBMDWriter(ref modelFile, m_LoadedModel, extraOptions, save);

            return(importedModel);
        }
예제 #27
0
        public KCL ConvertDAEToKCL(NitroFile modelFile, string fileName, float scale, float faceSizeThreshold,
                                   Dictionary <string, int> matColTypes, bool save = true)
        {
            KCL importedModel = new KCL(modelFile);

            if (m_LoadedModel == null)
            {
                m_LoadedModel = new DAELoader(fileName).LoadModel();
            }

            importedModel = CallKCLWriter(modelFile, m_LoadedModel, fileName, scale, faceSizeThreshold, matColTypes, save);

            return(importedModel);
        }
예제 #28
0
        public Cglp(NitroFile file, Colour[][,] glyphs, byte boxWidth, byte boxHeight,
		            byte glyphWidth, byte glyphHeight, byte depth, RotationMode rotation)
            : base(file)
        {
            this.BoxWidth = boxWidth;
            this.BoxHeight = boxHeight;
            this.GlyphWidth = glyphWidth;
            this.GlyphHeight = glyphHeight;
            this.Depth = (byte)depth;
            this.Rotation = (byte)rotation;
            this.glyphs = new List<Colour[,]>(glyphs);

            int boxSize = this.BoxWidth * this.BoxHeight * this.Depth;
            this.Size = 0x08 + 0x08 + (int)Math.Ceiling(boxSize / 8.0) * this.glyphs.Count;
        }
        public void makeBinBackup(int file)
        {
            System.IO.DirectoryInfo dir = new System.IO.DirectoryInfo(ASMDir + "/bak");
            //Console.Out.WriteLine("Backing up " + file + " "+dir.FullName);
            if (!dir.Exists)
            {
                dir.Create();
            }

            dir = new System.IO.DirectoryInfo(ASMDir);
            System.IO.FileStream fs;

            string filename;

            if (file == -1)
            {
                filename = dir.FullName + "/bak/" + "main.bin";
            }
            else
            {
                filename = dir.FullName + "/bak/" + file + ".bin";
            }

            if (System.IO.File.Exists(filename))
            {
                return;
            }

            fs = new System.IO.FileStream(filename, System.IO.FileMode.CreateNew);

            NitroFile f = Program.m_ROM.GetFileFromName("arm9.bin");

            if (file != -1)
            {
                NitroOverlay ov = new NitroOverlay(Program.m_ROM, (uint)file);
                ov.SaveChanges();
                fs.Write(ov.m_Data, 0, f.m_Data.Length);
                fs.Close();
            }
            else
            {
                fs.Write(f.m_Data, 0, f.m_Data.Length);
                fs.Close();
            }
        }
예제 #30
0
        protected virtual void WriteFilenameToXML(XmlWriter writer, string exportPath, string element, ushort fileID, Dictionary <string, string> attributes = null)
        {
            writer.WriteStartElement(element);
            if (attributes != null)
            {
                foreach (string attr in attributes.Keys)
                {
                    writer.WriteAttributeString(attr, attributes[attr]);
                }
            }
            NitroFile file     = Program.m_ROM.GetFileFromInternalID(fileID);
            string    filename = file.m_Name;

            //writer.WriteElementString("Filename", filename);
            writer.WriteComment(filename);
            writer.WriteElementString("Location", "." + filename.Substring(filename.LastIndexOf('/')));
            writer.WriteEndElement();

            System.IO.File.WriteAllBytes(exportPath + "/" +
                                         filename.Substring(filename.LastIndexOf('/'), filename.Length - (filename.LastIndexOf('/'))),
                                         file.m_Data);
        }
예제 #31
0
        // File specified in <Location> will overwrite file with specified file ID
        protected virtual void ReadFileFromXML(XmlReader reader, string element, ushort fileID)
        {
            if (reader.IsEmptyElement)
            {
                return;
            }

            string location = null;

            while (reader.Read())
            {
                reader.MoveToContent();
                if (reader.NodeType.Equals(XmlNodeType.Element))
                {
                    if (reader.LocalName.Equals("Location"))
                    {
                        location = reader.ReadElementContentAsString();
                    }
                }
                else if (reader.NodeType.Equals(XmlNodeType.EndElement))
                {
                    if (reader.LocalName.Equals(element))
                    {
                        break;
                    }
                }
            }

            NitroFile currentFile = Program.m_ROM.GetFileFromInternalID(fileID);

            if (location != null)
            {
                byte[] fileToImport = System.IO.File.ReadAllBytes(m_ImportPath + "/" + location);
                currentFile.m_Data = fileToImport;
                m_FilesToSave.Add(currentFile);
            }
        }
예제 #32
0
        public KCL ConvertModelToKCL(NitroFile modelFile, string fileName, float scale, float faceSizeThreshold,
            Dictionary<string, int> matColTypes, bool save = true)
        {
            KCL importedModel = null;

            string modelFormat = fileName.Substring(fileName.Length - 3, 3).ToLower();
            switch (modelFormat)
            {
                case "obj":
                    importedModel = ConvertOBJToKCL(modelFile, fileName, scale, faceSizeThreshold, matColTypes, save);
                    break;
                case "dae":
                    importedModel = ConvertDAEToKCL(modelFile, fileName, scale, faceSizeThreshold, matColTypes, save);
                    break;
                case "imd":
                    importedModel = ConvertIMDToKCL(modelFile, fileName, scale, faceSizeThreshold, matColTypes, save);
                    break;
                default:
                    importedModel = ConvertOBJToKCL(modelFile, fileName, scale, faceSizeThreshold, matColTypes, save);
                    break;
            }

            return importedModel;
        }
예제 #33
0
파일: Ncgr.cs 프로젝트: pleonex/ninoimager
 public CHAR(NitroFile nitro)
     : base(nitro)
 {
 }
예제 #34
0
 public BCA ConvertICAToBCA(ref NitroFile animationFile, string fileName, bool save = true)
 {
     return ConvertICAToBCA(ref animationFile, fileName, Vector3.One, BMDExtraImportOptions.DEFAULT, save);
 }
예제 #35
0
 public Cwdh(NitroFile file)
     : base(file)
 {
     WidthRegion.ResetCount();
 }
예제 #36
0
 public BCAWriter(ModelBase model, ref NitroFile modelFile)
     : base(model, modelFile.m_Name)
 {
     m_ModelFile = modelFile;
 }
 public Arm9BinaryHandler()
 {
     f = Program.m_ROM.GetFileFromName("arm9.bin");
 }
예제 #38
0
파일: BTP.cs 프로젝트: RicoPlays/sm64dse
        public BTP(NitroFile file, BMD model)
        {
            this.m_File = file;
            this.m_FileName = file.m_Name;
            this.m_Model = model;

            m_NumFrames = m_File.Read16(0x00);

            m_NumTextures = m_File.Read16(0x02);
            m_TextureHeadersOffset = m_File.Read32(0x04);
            m_TextureNames = new List<string>();

            m_NumPalettes = m_File.Read16(0x08);
            m_PaletteHeadersOffset = m_File.Read32(0x0C);
            m_PaletteNames = new List<string>();

            m_FrameChangesOffset = m_File.Read32(0x10);
            m_FrameTextureIDsOffset = m_File.Read32(0x14);
            m_FramePaletteIDsOffset = m_File.Read32(0x18);

            m_NumMaterials = m_File.Read16(0x1C);
            m_MaterialHeadersOffset = m_File.Read32(0x20);
            m_MaterialNames = new List<string>();

            for (int i = 0; i < m_NumTextures; i++)
            {
                m_TextureNames.Add(m_File.ReadString(m_File.Read32(m_TextureHeadersOffset + 0x04 + (uint)(i * 8)), 0));
            }

            for (int i = 0; i < m_NumPalettes; i++)
            {
                m_PaletteNames.Add(m_File.ReadString(m_File.Read32(m_PaletteHeadersOffset + 0x04 + (uint)(i * 8)), 0));
            }

            // Read in the frames for each material
            m_MaterialData = new Dictionary<string, BTPMaterialData>();
            m_Frames = new List<BTPFrameData>();
            for (int i = 0; i < m_NumMaterials; i++)
            {
                m_MaterialNames.Add(m_File.ReadString(m_File.Read32(m_MaterialHeadersOffset + 0x04 + (uint)(i * 12)), 0));

                ushort matFrameChanges = m_File.Read16(m_MaterialHeadersOffset + 0x08 + (uint)(i * 12));
                ushort startOffsetFrameChanges = m_File.Read16(m_MaterialHeadersOffset + 0x0A + (uint)(i * 12));

                int matNumFrames = 0;

                for (int j = 0; j < matFrameChanges; j++)
                {
                    ushort frameNum = m_File.Read16((uint)(m_FrameChangesOffset + (startOffsetFrameChanges * 2) + (j * 2)));
                    // If not the last frame in the sequence, length = (next frame number - current frame number) else,
                    // length = (number of frames in sequence - current frame number)
                    int nextFrameNum = (j != (matFrameChanges - 1)) ?
                        (int)m_File.Read16((uint)(m_FrameChangesOffset + (startOffsetFrameChanges * 2) + ((j + 1) * 2))) : -1;
                    int length = (nextFrameNum != -1) ? (nextFrameNum - frameNum) : (m_NumFrames - frameNum);

                    ushort texID = m_File.Read16((uint)(m_FrameTextureIDsOffset + (startOffsetFrameChanges * 2) + (j * 2)));
                    ushort palID = m_File.Read16((uint)(m_FramePaletteIDsOffset + (startOffsetFrameChanges * 2) + (j * 2)));

                    AddFrame(matNumFrames, m_Frames.Count, texID, palID, length);

                    matNumFrames += length;
                }

                BTPMaterialData matData = new BTPMaterialData(m_MaterialNames[i], matFrameChanges, startOffsetFrameChanges, matNumFrames);

                m_MaterialData.Add(m_MaterialNames[i], matData);
            }
        }
예제 #39
0
파일: Ncgr.cs 프로젝트: pleonex/ninoimager
 public Ncgr(string file)
 {
     this.nitro = new NitroFile(file, BlockTypes);
     this.GetInfo();
 }
예제 #40
0
        public BMD ConvertModelToBMD(ref NitroFile modelFile, string fileName, Vector3 scale, BMDExtraImportOptions extraOptions, 
            bool save = true)
        {
            BMD importedModel = null;

            string modelFormat = fileName.Substring(fileName.Length - 3, 3).ToLower();
            switch (modelFormat)
            {
                case "obj":
                    importedModel = ConvertOBJToBMD(ref modelFile, fileName, scale, extraOptions, save);
                    break;
                case "dae":
                    importedModel = ConvertDAEToBMD(ref modelFile, fileName, scale, extraOptions, save);
                    break;
                case "imd":
                    importedModel = ConvertIMDToBMD(ref modelFile, fileName, scale, extraOptions, save);
                    break;
                default:
                    importedModel = ConvertOBJToBMD(ref modelFile, fileName, scale, extraOptions, save);
                    break;
            }

            return importedModel;
        }
예제 #41
0
        public BCA ConvertICAToBCA(ref NitroFile animationFile, string fileName, Vector3 scale,
            BMDExtraImportOptions extraOptions, bool save = true)
        {
            m_LoadedModel = new NITROIntermediateCharacterAnimationLoader(m_LoadedModel, fileName).LoadModel(scale);

            BCA importedAnimation = CallBCAWriter(ref animationFile, m_LoadedModel, save);

            return importedAnimation;
        }
예제 #42
0
파일: Labl.cs 프로젝트: pleonex/ninoimager
 public Labl(NitroFile file)
     : base(file)
 {
 }
예제 #43
0
파일: BCAWriter.cs 프로젝트: awiebe/SM64DSe
        public void Optimise(NitroFile bca)
        {
            uint numBones  = bca.Read16(0x00);
            uint numFrames = bca.Read16(0x02);

            BCAOffsetData offs = new BCAOffsetData
            {
                scaleOffset = bca.Read32(0x08),
                rotOffset   = bca.Read32(0x0c),
                posOffset   = bca.Read32(0x10),
                animOffset  = bca.Read32(0x14)
            };

            //Pass 1: The constant value pass
            if (numFrames > 1)
            {
                for (uint i = 0; i < numBones; ++i)
                {
                    for (uint j = 0; j < 9; ++j)
                    {
                        if (bca.Read8(offs.animOffset + 0x24 * i + 4 * j + 1) == 0)
                        {
                            continue;
                        }

                        uint dataOffset, unitSize;
                        offs.GetDataOffsetAndSize(j / 3, out dataOffset, out unitSize);

                        bool interped   = bca.Read8(offs.animOffset + 0x24 * i + 4 * j + 0) != 0;
                        uint firstValID = bca.Read16(offs.animOffset + 0x24 * i + 4 * j + 2);
                        uint numVals    = interped ?
                                          numFrames / 2 + 1 :
                                          numFrames;

                        uint[] vals = new uint[numVals];
                        for (uint k = 0; k < numVals; ++k)
                        {
                            vals[k] = bca.ReadVar(dataOffset + (firstValID + k) * unitSize, unitSize);
                        }

                        if (!Array.Exists(vals, x => x != vals[0])) //They're all the same.
                        {
                            uint addr = dataOffset + (firstValID + numVals) * unitSize;
                            BackSpace(bca, addr, (numVals - 1) * unitSize, ref offs);
                            bca.Write16(offs.animOffset + 0x24 * i + 4 * j + 0, 0x0000);
                            continue;
                        }

                        if (interped)
                        {
                            continue;
                        }

                        //Pass 2: The interpolation pass
                        bool  shouldInterp = true;
                        int[] valInts;
                        if (unitSize == 2)
                        {
                            valInts = Array.ConvertAll(vals, x => x >= 0x8000 ? (int)(x | 0xffff0000) : (int)x);
                        }
                        else
                        {
                            valInts = Array.ConvertAll(vals, x => (int)x);
                        }

                        for (int k = 0; k < numVals - 2; k += 2)
                        {
                            if (Math.Abs(valInts[k] - 2 * valInts[k + 1] + valInts[k + 2]) > 1)
                            {
                                shouldInterp = false;
                            }
                        }

                        if (!shouldInterp)
                        {
                            continue;
                        }

                        for (uint k = 0; k < numVals; k += 2)
                        {
                            bca.WriteVar(dataOffset + (firstValID + k / 2) * unitSize, unitSize,
                                         bca.ReadVar(dataOffset + (firstValID + k) * unitSize, unitSize));
                        }
                        if (numVals % 2 == 0) //can't interpolate on last frame even if that frame is odd
                        {
                            bca.WriteVar(dataOffset + (firstValID + numVals / 2) * unitSize, unitSize,
                                         bca.ReadVar(dataOffset + (firstValID + numVals - 1) * unitSize, unitSize));
                        }

                        bca.Write8(offs.animOffset + 0x24 * i + 4 * j + 0, 1);
                        BackSpace(bca, dataOffset + (firstValID + numVals) * unitSize,
                                  (numVals - 1) / 2 * unitSize, ref offs);
                    }
                }
            }

            //Pass 3: The share equal data pass.
            for (uint trID = 0; trID < 3; ++trID)
            {
                uint dataOffset, unitSize;
                offs.GetDataOffsetAndSize(trID, out dataOffset, out unitSize);

                BCAEntryToSort[] bcaEntries = new BCAEntryToSort[3 * numBones];
                for (uint i = 0; i < numBones; ++i)
                {
                    for (uint j = 0; j < 3; ++j)
                    {
                        bool constant   = bca.Read8(offs.animOffset + 0x24 * i + 4 * (3 * trID + j) + 1) == 0;
                        bool interped   = bca.Read8(offs.animOffset + 0x24 * i + 4 * (3 * trID + j) + 0) != 0;
                        uint firstValID = bca.Read16(offs.animOffset + 0x24 * i + 4 * (3 * trID + j) + 2);
                        uint numVals    = constant ? 1 : interped ?
                                          numFrames / 2 + 1 :
                                          numFrames;

                        bcaEntries[3 * i + j].boneID = i;
                        bcaEntries[3 * i + j].axisID = j;
                        bcaEntries[3 * i + j].data   = new uint[numVals];
                        for (uint k = 0; k < numVals; ++k)
                        {
                            bcaEntries[3 * i + j].data[k] =
                                bca.ReadVar(dataOffset + (firstValID + k) * unitSize, unitSize);
                        }
                    }
                }

                BCAEntryToSort[][] sortedEnts = bcaEntries.GroupBy(x => x.data, new UintArrEqualityComparer()).
                                                Select(g => g.ToArray()).
                                                ToArray();

                foreach (BCAEntryToSort[] entArr in sortedEnts)
                {
                    uint boneID = entArr[0].boneID;
                    uint axisID = entArr[0].axisID;

                    for (int i = 1; i < entArr.Length; ++i) //Using the 1st for reference; skip it
                    {
                        bool constant = bca.Read8(offs.animOffset + 0x24 * entArr[i].boneID +
                                                  4 * (3 * trID + entArr[i].axisID) + 1) == 0;
                        bool interped = bca.Read8(offs.animOffset + 0x24 * entArr[i].boneID +
                                                  4 * (3 * trID + entArr[i].axisID) + 0) != 0;
                        uint firstValID = bca.Read16(offs.animOffset + 0x24 * entArr[i].boneID +
                                                     4 * (3 * trID + entArr[i].axisID) + 2);
                        uint numVals = constant ? 1 : interped ?
                                       numFrames / 2 + 1 :
                                       numFrames;

                        uint sameValID = bca.Read16(offs.animOffset + 0x24 * boneID +
                                                    4 * (3 * trID + axisID) + 2);
                        if (firstValID != sameValID) //Avoid deleting entries when they are already shared
                        {
                            bca.Write16(offs.animOffset + 0x24 * entArr[i].boneID +
                                        4 * (3 * trID + entArr[i].axisID) + 2, (ushort)sameValID);
                            BackSpace(bca, dataOffset + (firstValID + numVals) * unitSize,
                                      numVals * unitSize, ref offs);
                        }
                    }
                }
            }

            if ((offs.posOffset - offs.rotOffset) % 4 != 0)
            {
                BackSpace(bca, offs.posOffset, 0xfffffffe, ref offs, true);
            }
        }
예제 #44
0
파일: BCAWriter.cs 프로젝트: awiebe/SM64DSe
 private static void WriteBCAAnimationDescriptor(NitroFile bca, uint offset, byte interpolation, bool isConstant, int startIndex)
 {
     bca.Write8(offset + 0x00, interpolation);                            // Interpolation
     bca.Write8(offset + 0x01, (isConstant == true) ? (byte)0 : (byte)1); // Index increments with each frame
     bca.Write16(offset + 0x02, (ushort)startIndex);                      // Starting index
 }
예제 #45
0
 public BMD ConvertIMDToBMD(ref NitroFile modelFile, string fileName, bool save = true)
 {
     return(ConvertIMDToBMD(ref modelFile, fileName, Vector3.One, BMDExtraImportOptions.DEFAULT, save));
 }
예제 #46
0
파일: Ncgr.cs 프로젝트: pleonex/ninoimager
 public Cpos(NitroFile nitro)
     : base(nitro)
 {
 }
예제 #47
0
파일: Ncgr.cs 프로젝트: pleonex/ninoimager
 public Ncgr()
 {
     this.nitro = new NitroFile("NCGR", "1.1", BlockTypes);
     this.charBlock = new CHAR(this.nitro);
     this.nitro.Blocks.Add(this.charBlock);
 }
예제 #48
0
        protected BCA CallBCAWriter(ref NitroFile animationFile, ModelBase model, bool save = true)
        {
            AbstractModelWriter bcaWriter = new BCAWriter(model, ref animationFile);

            bcaWriter.WriteModel(save);

            return new BCA(animationFile);
        }
예제 #49
0
파일: Ncgr.cs 프로젝트: pleonex/ninoimager
 public Ncgr(Stream str)
 {
     this.nitro = new NitroFile(str, BlockTypes);
     this.GetInfo();
 }
예제 #50
0
 public Cglp(NitroFile file)
     : base(file)
 {
 }
예제 #51
0
 public BCA ConvertICAToBCA(ref NitroFile animationFile, string fileName, bool save = true)
 {
     return(ConvertICAToBCA(ref animationFile, fileName, Vector3.One, BMDExtraImportOptions.DEFAULT, save));
 }
예제 #52
0
        public void pack(ref NitroFile kcl, ref uint pos)
        {
            List <Octree> branches = new List <Octree>();

            branches.Add(this);
            uint free_list_offset = 0;
            List <List <int> > list_offsets_ind  = new List <List <int> >();
            List <uint>        list_offsets_addr = new List <uint>();

            //testing
            int zero_ind_count             = 0;
            int ind_already_in_count       = 0;
            int list_offsets_added_count   = 0;
            int else_branches_append_count = 0;
            //end testing
            int i = 0;

            while (i < branches.Count)
            {
                foreach (Octree node in branches[i].children)
                {
                    if (node.is_leaf)
                    {
                        if (node.indices.Count == 0)
                        {
                            zero_ind_count += 1;
                            continue;
                        }
                        if (indicesInList(list_offsets_ind, node.indices))
                        {
                            ind_already_in_count += 1;
                            continue;
                        }
                        list_offsets_ind.Add(node.indices);
                        list_offsets_addr.Add(free_list_offset);
                        list_offsets_added_count += 1;
                        free_list_offset         += (uint)(2 * ((node.indices.Count) + 1));
                    }
                    else
                    {
                        branches.Add(node);
                        else_branches_append_count += 1;
                    }
                }
                i += 1;
            }

            uint list_base = 0;

            foreach (Octree b in branches)
            {
                list_base += (uint)(4 * b.children.Count);
            }
            list_offsets_ind.Add(new List <int>());      //Add an empty indices list
            list_offsets_addr.Add(free_list_offset - 2); //with this address
            uint branch_base        = 0;
            uint free_branch_offset = (uint)(4 * (this.children.Count));

            foreach (Octree branch in branches)
            {
                foreach (Octree node in branch.children)
                {
                    if (node.is_leaf)
                    {
                        int key = posIndicesInList(list_offsets_ind, node.indices);
                        kcl.Write32(pos, (uint)(0x80000000 | (list_base + list_offsets_addr[key] - 2 - branch_base)));
                        pos += 4;
                    }
                    else
                    {
                        kcl.Write32(pos, (free_branch_offset - branch_base));
                        pos += 4;
                        free_branch_offset += (uint)(4 * (node.children.Count));
                    }
                }
                branch_base += (uint)(4 * (branch.children.Count));
            }

            list_offsets_ind.RemoveAt(list_offsets_ind.Count - 1);
            list_offsets_addr.RemoveAt(list_offsets_addr.Count - 1);

            foreach (List <int> indices in list_offsets_ind)
            {
                foreach (int index in indices)
                {
                    kcl.Write16(pos, (ushort)(index + 1));
                    pos += 2;
                }
                kcl.Write16(pos, (ushort)0);
                pos += 2;
            }
        }//End pack function
예제 #53
0
        protected BMD CallBMDWriter(ref NitroFile modelFile, ModelBase model, BMDExtraImportOptions extraOptions, bool save = true)
        {
            AbstractModelWriter bmdWriter = new BMDWriter(model, ref modelFile, extraOptions);

            bmdWriter.WriteModel(save);

            return new BMD(modelFile);
        }
예제 #54
0
 private static void WriteBCAAnimationDescriptor(NitroFile bca, uint offset, byte interpolation, bool isConstant, int startIndex)
 {
     bca.Write8(offset + 0x00, interpolation);// Interpolation
     bca.Write8(offset + 0x01, (isConstant == true) ? (byte)0 : (byte)1);// Index increments with each frame
     bca.Write16(offset + 0x02, (ushort)startIndex);// Starting index
 }
예제 #55
0
        private static void write_kcl(NitroFile kcl, List <Triangle> triangles, int max_triangles, int min_width, float scale)
        {
            kcl.Clear();

            //Need to scale each vertex (1000 times scale of model)
            foreach (Triangle t in triangles)
            {
                t.u = t.u.mul(scale);
                t.v = t.v.mul(scale);
                t.w = t.w.mul(scale);
            }

            uint pos = 0;

            List <Face>  faces         = new List <Face>();
            VertexWelder vertex_welder = new VertexWelder(1 / 64f, (int)(Math.Floor((double)(triangles.Count / 256))));
            VertexWelder normal_welder = new VertexWelder(1 / 1024f, (int)(Math.Floor((double)(4 * triangles.Count / 256))));

            foreach (Triangle t in triangles)
            {
                Face f = new Face();

                Vector a = unit(cross(t.u.sub(t.w), t.n));
                Vector b = unit(cross(t.v.sub(t.u), t.n));
                Vector c = unit(cross(t.w.sub(t.v), t.n));

                f.length       = new FixedPoint(dot(t.v.sub(t.u), c), 1 / 65536f);
                f.vertex_index = (ushort)vertex_welder.add(t.u);
                f.normal_index = (ushort)normal_welder.add(t.n);
                f.a_index      = (ushort)normal_welder.add(a);
                f.b_index      = (ushort)normal_welder.add(b);
                f.c_index      = (ushort)normal_welder.add(c);
                f.group        = (ushort)t.group;

                faces.Add(f);
            }

            //Vertex Section
            pos += 56;
            kcl.Write32(0x00, pos);//Vertex section offset

            foreach (Vertex vtx in vertex_welder.vertices)
            {
                kcl.Write32(pos, (uint)vtx.x.valToWrite());
                kcl.Write32(pos + 4, (uint)vtx.y.valToWrite());
                kcl.Write32(pos + 8, (uint)vtx.z.valToWrite());

                pos += 12;
            }

            //Vector Section
            kcl.Write32(0x04, pos);//Vector section offset

            foreach (Vector vct in normal_welder.vectors)
            {
                kcl.Write16(pos, (ushort)vct.x.valToWrite());
                kcl.Write16(pos + 2, (ushort)vct.y.valToWrite());
                kcl.Write16(pos + 4, (ushort)vct.z.valToWrite());

                pos += 6;
            }

            pos = (uint)((pos + 3) & ~3);

            //Planes Section
            kcl.Write32(0x08, pos - 0x10);//Planes section offset

            foreach (Face f in faces)
            {
                kcl.Write32(pos, (uint)f.length.valToWrite());
                kcl.Write16(pos + 4, (ushort)f.vertex_index);
                kcl.Write16(pos + 6, (ushort)f.normal_index);
                kcl.Write16(pos + 8, (ushort)f.a_index);
                kcl.Write16(pos + 10, (ushort)f.b_index);
                kcl.Write16(pos + 12, (ushort)f.c_index);
                kcl.Write16(pos + 14, (ushort)f.group);

                pos += 16;
            }


            //Octree Section
            kcl.Write32(0x0C, pos);//Octree offset

            Octree octree = new Octree(triangles, max_triangles, (float)min_width);

            octree.pack(ref kcl, ref pos);

            //Header
            kcl.Write32(0x10, (uint)327680);//Unknown
            kcl.Write32(0x14, (uint)octree.bas.x.valToWrite());
            kcl.Write32(0x18, (uint)octree.bas.y.valToWrite());
            kcl.Write32(0x1C, (uint)octree.bas.z.valToWrite());
            kcl.Write32(0x20, (uint)(~((int)octree.width_x - 1) & 0xFFFFFFFF));
            kcl.Write32(0x24, (uint)(~((int)octree.width_y - 1) & 0xFFFFFFFF));
            kcl.Write32(0x28, (uint)(~((int)octree.width_z - 1) & 0xFFFFFFFF));
            kcl.Write32(0x2C, (uint)(Math.Log(octree.base_width, 2)));
            kcl.Write32(0x30, (uint)(Math.Log(octree.nx, 2)));
            kcl.Write32(0x34, (uint)(Math.Log(octree.nx, 2)) + (uint)(Math.Log(octree.ny, 2)));

            kcl.SaveChanges();
        }//End writeKCL
예제 #56
0
파일: Nscr.cs 프로젝트: pleonex/ninoimager
 public Nscr()
 {
     this.nitro = new NitroFile("NSCR", "1.0", BlockTypes);
     this.scrn = new Scrn(this.nitro);
     this.nitro.Blocks.Add(this.scrn);
 }
예제 #57
0
 public BMDWriter(ModelBase model, ref NitroFile modelFile)
     : this(model, ref modelFile, BMDImporter.BMDExtraImportOptions.DEFAULT)
 {
 }
예제 #58
0
 public BMD ConvertDAEToBMD(ref NitroFile modelFile, string fileName, bool save = true)
 {
     return ConvertDAEToBMD(ref modelFile, fileName, Vector3.One, BMDExtraImportOptions.DEFAULT, save);
 }
예제 #59
0
파일: Nscr.cs 프로젝트: pleonex/ninoimager
 public Scrn(NitroFile nitro)
     : base(nitro)
 {
 }
예제 #60
0
파일: SDAT.cs 프로젝트: awiebe/SM64DSe
        //the last 2 record types don't exist in SM64DS.

        public SDAT(NitroFile file)
        {
            m_File     = file;
            m_Filename = file.m_Name;

            uint symbolOffset = file.Read32(0x10);
            uint infoOffset   = file.Read32(0x18);

            INitroROMBlock symbolBlock = new INitroROMBlock(file.ReadBlock(file.Read32(0x10), file.Read32(0x14)));
            INitroROMBlock infoBlock   = new INitroROMBlock(file.ReadBlock(file.Read32(0x18), file.Read32(0x1c)));
            INitroROMBlock fatBlock    = new INitroROMBlock(file.ReadBlock(file.Read32(0x20), file.Read32(0x24)));

            fatBlock.m_Data = fatBlock.ReadBlock(0x0c, fatBlock.Read32(0x08) * 0x10); //strip the header

            m_Sequences = new Sequence       [symbolBlock.Read32(symbolBlock.Read32(0x08))];
            m_SeqArcs   = new SequenceArchive[symbolBlock.Read32(symbolBlock.Read32(0x0c))];
            m_Banks     = new Bank           [symbolBlock.Read32(symbolBlock.Read32(0x10))];
            m_WaveArcs  = new SWAR           [symbolBlock.Read32(symbolBlock.Read32(0x14))];
            m_Players   = new Player         [symbolBlock.Read32(symbolBlock.Read32(0x18))];
            m_Groups    = new Group          [symbolBlock.Read32(symbolBlock.Read32(0x1c))];

            INitroROMBlock symbSeqBlock = new INitroROMBlock(
                symbolBlock.ReadBlock(symbolBlock.Read32(0x08) + 4, (uint)m_Sequences.Length * 4));
            INitroROMBlock symbSeqArcBlock = new INitroROMBlock(
                symbolBlock.ReadBlock(symbolBlock.Read32(0x0c) + 4, (uint)m_SeqArcs.Length * 8));
            INitroROMBlock symbBankBlock = new INitroROMBlock(
                symbolBlock.ReadBlock(symbolBlock.Read32(0x10) + 4, (uint)m_Banks.Length * 4));
            INitroROMBlock symbWaveBlock = new INitroROMBlock(
                symbolBlock.ReadBlock(symbolBlock.Read32(0x14) + 4, (uint)m_WaveArcs.Length * 4));
            INitroROMBlock symbPlayerBlock = new INitroROMBlock(
                symbolBlock.ReadBlock(symbolBlock.Read32(0x18) + 4, (uint)m_Players.Length * 4));
            INitroROMBlock symbGroupBlock = new INitroROMBlock(
                symbolBlock.ReadBlock(symbolBlock.Read32(0x1c) + 4, (uint)m_Groups.Length * 4));

            INitroROMBlock infoSeqBlock = new INitroROMBlock(
                infoBlock.ReadBlock(infoBlock.Read32(0x08) + 4, (uint)m_Sequences.Length * 4));
            INitroROMBlock infoSeqArcBlock = new INitroROMBlock(
                infoBlock.ReadBlock(infoBlock.Read32(0x0c) + 4, (uint)m_SeqArcs.Length * 4));
            INitroROMBlock infoBankBlock = new INitroROMBlock(
                infoBlock.ReadBlock(infoBlock.Read32(0x10) + 4, (uint)m_Banks.Length * 4));
            INitroROMBlock infoWaveBlock = new INitroROMBlock(
                infoBlock.ReadBlock(infoBlock.Read32(0x14) + 4, (uint)m_WaveArcs.Length * 4));
            INitroROMBlock infoPlayerBlock = new INitroROMBlock(
                infoBlock.ReadBlock(infoBlock.Read32(0x18) + 4, (uint)m_Players.Length * 4));
            INitroROMBlock infoGroupBlock = new INitroROMBlock(
                infoBlock.ReadBlock(infoBlock.Read32(0x1c) + 4, (uint)m_Groups.Length * 4));

            INitroROMBlock buffer = new INitroROMBlock();

            for (uint i = 0; i < m_WaveArcs.Length; ++i)
            {
                if (infoWaveBlock.Read32(4 * i) == 0) //An offset of 0 means "Does Not Exist".
                {
                    continue;
                }

                uint fileID  = infoBlock.Read32(infoWaveBlock.Read32(4 * i));
                SWAR waveArc = new SWAR(symbolBlock.ReadString(symbWaveBlock.Read32(4 * i), -1),
                                        new INitroROMBlock(GetFile(file, fileID)));
                m_WaveArcs[i] = waveArc;
            }

            for (uint i = 0; i < m_Banks.Length; ++i)
            {
                if (infoBankBlock.Read32(4 * i) == 0)
                {
                    continue;
                }

                buffer.m_Data = infoBlock.ReadBlock(infoBankBlock.Read32(4 * i), 12);
                Bank bank = new Bank();
                bank.m_File = new SDAT_File(symbolBlock.ReadString(symbBankBlock.Read32(4 * i), -1),
                                            file, buffer.Read32(0));
                bank.m_WaveArcs = new SWAR[4];
                for (uint j = 0; j < 4; ++j)
                {
                    uint waveArcID = buffer.Read16(4 + 2 * j);
                    bank.m_WaveArcs[j] = waveArcID != 0xffff ? m_WaveArcs[waveArcID] : null;
                }
                m_Banks[i] = bank;
            }

            for (uint i = 0; i < m_Players.Length; ++i)
            {
                buffer.m_Data = infoBlock.ReadBlock(infoPlayerBlock.Read32(4 * i), 8);
                Player player = new Player();
                player.m_Filename   = symbolBlock.ReadString(symbPlayerBlock.Read32(4 * i), -1);
                player.m_MaxNumSeqs = buffer.Read8(0);
                player.m_HeapSize   = buffer.Read32(4);
                m_Players[i]        = player;
            }

            for (uint i = 0; i < m_Sequences.Length; ++i)
            {
                if (infoSeqBlock.Read32(4 * i) == 0)
                {
                    continue;
                }

                buffer.m_Data = infoBlock.ReadBlock(infoSeqBlock.Read32(4 * i), 12);
                Sequence sequence = new Sequence();
                sequence.m_File = new SDAT_File(symbolBlock.ReadString(symbSeqBlock.Read32(4 * i), -1),
                                                file, buffer.Read32(0));
                sequence.m_Bank            = m_Banks[buffer.Read16(4)];
                sequence.m_Volume          = buffer.Read8(6);
                sequence.m_ChannelPriority = buffer.Read8(7);
                sequence.m_PlayerPriority  = buffer.Read8(8);
                sequence.m_Player          = m_Players[buffer.Read8(9)];
                m_Sequences[i]             = sequence;
            }

            for (uint i = 0; i < m_SeqArcs.Length; ++i)
            {
                if (infoSeqArcBlock.Read32(4 * i) == 0)
                {
                    continue;
                }

                uint            fileID = infoBlock.Read32(infoSeqArcBlock.Read32(4 * i));
                SequenceArchive seqArc = new SequenceArchive();
                seqArc.m_Filename  = symbolBlock.ReadString(symbSeqArcBlock.Read32(8 * i), -1);
                seqArc.m_Sequences = new SequenceArchive.Sequence[
                    symbolBlock.Read32(symbSeqArcBlock.Read32(8 * i + 4))];

                INitroROMBlock symbSeqArcSeqBlock = new INitroROMBlock(symbolBlock.ReadBlock(
                                                                           symbSeqArcBlock.Read32(8 * i + 4) + 4, (uint)seqArc.m_Sequences.Length * 4));
                INitroROMBlock ssar = new INitroROMBlock(GetFile(file, fileID));

                INitroROMBlock ssarInfo = new INitroROMBlock(
                    ssar.ReadBlock(0x20, (uint)seqArc.m_Sequences.Length * 12));
                seqArc.m_Data = new INitroROMBlock(
                    ssar.ReadBlock(ssar.Read32(0x18), (uint)ssar.m_Data.Length - ssar.Read32(0x18)));
                for (uint j = 0; j < seqArc.m_Sequences.Length; ++j)
                {
                    buffer.m_Data = ssarInfo.ReadBlock(12 * j, 12);
                    SequenceArchive.Sequence sequence = new SequenceArchive.Sequence();
                    sequence.m_Filename        = symbolBlock.ReadString(symbSeqArcSeqBlock.Read32(4 * j), -1);
                    sequence.m_SeqOffset       = buffer.Read32(0);
                    sequence.m_Bank            = m_Banks[buffer.Read16(4)];
                    sequence.m_Volume          = buffer.Read8(6);
                    sequence.m_ChannelPriority = buffer.Read8(7);
                    sequence.m_PlayerPriority  = buffer.Read8(8);
                    sequence.m_Player          = m_Players[buffer.Read8(9)];
                    seqArc.m_Sequences[j]      = sequence;
                }
                m_SeqArcs[i] = seqArc;
            }

            for (uint i = 0; i < m_Groups.Length; ++i)
            {
                if (infoGroupBlock.Read32(4 * i) == 0)
                {
                    continue;
                }

                Group group = new Group();
                group.m_Entries = new Group.Entry[
                    infoBlock.Read32(infoGroupBlock.Read32(4 * i))];
                buffer.m_Data = infoBlock.ReadBlock(infoGroupBlock.Read32(4 * i) + 4,
                                                    (uint)group.m_Entries.Length * 8);
                group.m_Filename = symbolBlock.ReadString(symbGroupBlock.Read32(4 * i), -1);

                for (uint j = 0; j < group.m_Entries.Length; ++j)
                {
                    uint        index = buffer.Read32(8 * j + 4);
                    Group.Entry entry = new Group.Entry();
                    entry.m_LoadFlag = buffer.Read8(8 * j + 1);
                    switch (buffer.Read8(8 * j))
                    {
                    case 0:
                        entry.m_Record = m_Sequences[index]; break;

                    case 3:
                        entry.m_Record = m_SeqArcs[index]; break;

                    case 1:
                        entry.m_Record = m_Banks[index]; break;

                    case 2:
                        entry.m_Record = m_WaveArcs[index]; break;

                    default:
                        throw new Exception("Group " + i + ", Record " + j +
                                            " has an unexpected record type: " + buffer.Read8(8 * j));
                    }
                    group.m_Entries[j] = entry;
                }
                m_Groups[i] = group;
            }
        }