Esempio n. 1
0
        public static BMD GetModel(string name)
        {
            if (Program.m_ROM == null)
            {
                return(null);
            }

            if (m_Models.ContainsKey(name))
            {
                CachedModel found = m_Models[name];
                found.m_References++;
                return(found.m_Model);
            }

            NitroFile mdfile = Program.m_ROM.GetFileFromName(name);

            if (mdfile == null)
            {
                return(null);
            }

            BMD model = new BMD(mdfile);

            model.PrepareToRender();

            CachedModel cmdl = new CachedModel();

            cmdl.m_Model        = model;
            cmdl.m_DisplayLists = null;
            cmdl.m_References   = 1;
            m_Models.Add(name, cmdl);

            return(model);
        }
Esempio n. 2
0
            public OctreeNode(NitroFile file, uint baseoffset, uint offset, Vector3 pos, Vector3 size)
            {
                m_Pos       = pos;
                m_Size      = size;
                m_LOL       = false;
                m_PlaneList = new List <int>();

                uint node = file.Read32(offset);

                if ((node & 0x80000000) != 0)
                {
                    uint   lolz = baseoffset + (node & 0x7FFFFFFF) + 2;
                    int    n    = 0;
                    string lmao = "";
                    for (; ;)
                    {
                        ushort p = file.Read16(lolz);
                        if (p == 0)
                        {
                            break;
                        }
                        else if (p == 37)
                        {
                            m_LOL = true;
                        }

                        m_PlaneList.Add(p - 1);
                        lmao += (p - 1).ToString() + " ";
                        lolz += 2;
                        n++;
                    }

                    if (n > maxkids)
                    {
                        maxkids = n;
                    }

                    //if (m_LOL)
                    //   MessageBox.Show(lmao);

                    m_NumPlanes = n;
                    OctreeNode.m_List.Add(this);
                }
                else
                {
                    uint parentoffset = baseoffset + node;
                    uint child0offset = parentoffset;
                    size /= 2f;
                    for (int z = 0; z < 2; z++)
                    {
                        for (int y = 0; y < 2; y++)
                        {
                            for (int x = 0; x < 2; x++)
                            {
                                new OctreeNode(file, child0offset, parentoffset, pos + new Vector3(size.X * x, size.Y * y, size.Z * z), size); parentoffset += 4;
                            }
                        }
                    }
                }
            }
Esempio n. 3
0
        private void btnLZDecompressWithHeader_Click(object sender, EventArgs e)
        {
            NitroFile file = Program.m_ROM.GetFileFromName(m_SelectedFile);

            // NitroFile automatically decompresses on load if LZ77 header present
            file.SaveChanges();
        }
Esempio n. 4
0
        public static KCL GetKCL(string name)
        {
            if (m_Clsns.ContainsKey(name))
            {
                CachedKCL found = m_Clsns[name];
                found.m_References++;
                return(found.m_Clsn);
            }

            if (!Program.m_ROM.FileExists(name))
            {
                return(null);
            }
            NitroFile kclfile = Program.m_ROM.GetFileFromName(name);

            KCL clsn = new KCL(kclfile);

            CachedKCL ckcl = new CachedKCL();

            ckcl.m_Clsn       = clsn;
            ckcl.m_References = 1;
            m_Clsns.Add(name, ckcl);

            return(clsn);
        }
Esempio n. 5
0
        public SDAT(NitroFile sdat)
        {
            m_File = sdat;
            m_FileName = m_File.m_Name;

            m_Header = new SDATHeader(m_File);
            m_Info = new SDATInfo(m_File, m_Header.m_InfoOffset);
        }
        public SDAT(NitroFile sdat)
        {
            m_File     = sdat;
            m_FileName = m_File.m_Name;

            m_Header = new SDATHeader(m_File);
            m_Info   = new SDATInfo(m_File, m_Header.m_InfoOffset);
        }
            public SDATInfo(NitroFile sdat, uint offset)
            {
                m_Offset       = offset;
                m_Type         = sdat.ReadString(m_Offset + 0x00, 4).ToCharArray();
                m_Size         = sdat.Read32(m_Offset + 0x04);
                m_RecordOffset = new uint[8];
                for (int i = 0; i < 8; i++)
                {
                    m_RecordOffset[i] = sdat.Read32(m_Offset + 0x08 + (uint)(i * 4));
                }
                m_Reserved = sdat.ReadBlock(m_Offset + 0x28, 24);

                m_Records = new SDATInfoRecord[8];
                for (int i = 0; i < 8; i++)
                {
                    m_Records[i] = new SDATInfoRecord(sdat, m_Offset + m_RecordOffset[i]);
                }
                m_Records0SEQ = new SDATInfoSEQ[m_Records[0].m_Count];
                for (int i = 0; i < m_Records[0].m_Count; i++)
                {
                    m_Records0SEQ[i] = new SDATInfoSEQ(sdat, m_Offset + m_Records[0].m_EntryOffset[i]);
                }
                m_Records1SEQARC = new SDATInfoSEQARC[m_Records[1].m_Count];
                for (int i = 0; i < m_Records[1].m_Count; i++)
                {
                    m_Records1SEQARC[i] = new SDATInfoSEQARC(sdat, m_Offset + m_Records[1].m_EntryOffset[i]);
                }
                m_Records2BANK = new SDATInfoBANK[m_Records[2].m_Count];
                for (int i = 0; i < m_Records[2].m_Count; i++)
                {
                    m_Records2BANK[i] = new SDATInfoBANK(sdat, m_Offset + m_Records[2].m_EntryOffset[i]);
                }
                m_Records3WAVEARC = new SDATInfoWAVEARC[m_Records[3].m_Count];
                for (int i = 0; i < m_Records[3].m_Count; i++)
                {
                    m_Records3WAVEARC[i] = new SDATInfoWAVEARC(sdat, m_Offset + m_Records[3].m_EntryOffset[i]);
                }
                m_Records4PLAYER = new SDATInfoPLAYER[m_Records[4].m_Count];
                for (int i = 0; i < m_Records[4].m_Count; i++)
                {
                    m_Records4PLAYER[i] = new SDATInfoPLAYER(sdat, m_Offset + m_Records[4].m_EntryOffset[i]);
                }
                m_Records5GROUP = new SDATInfoGROUP[m_Records[5].m_Count];
                for (int i = 0; i < m_Records[5].m_Count; i++)
                {
                    m_Records5GROUP[i] = new SDATInfoGROUP(sdat, m_Offset + m_Records[5].m_EntryOffset[i]);
                }
                m_Records6PLAYER2 = new SDATInfoPLAYER2[m_Records[6].m_Count];
                for (int i = 0; i < m_Records[6].m_Count; i++)
                {
                    m_Records6PLAYER2[i] = new SDATInfoPLAYER2(sdat, m_Offset + m_Records[6].m_EntryOffset[i]);
                }
                m_Records7STREAM = new SDATInfoSTREAM[m_Records[7].m_Count];
                for (int i = 0; i < m_Records[7].m_Count; i++)
                {
                    m_Records7STREAM[i] = new SDATInfoSTREAM(sdat, m_Offset + m_Records[7].m_EntryOffset[i]);
                }
            }
Esempio n. 8
0
        public BCA(NitroFile file)
        {
            m_File = file;
            m_FileName = m_File.m_Name;

            ReadHeader();

            ReadAnimationData();
        }
Esempio n. 9
0
        private void btnKCLEditor_Click(object sender, EventArgs e)
        {
            uint          ovlID   = Program.m_ROM.GetLevelOverlayID(lbxLevels.SelectedIndex);
            NitroOverlay  curOvl  = new NitroOverlay(Program.m_ROM, ovlID);
            NitroFile     curKCL  = Program.m_ROM.GetFileFromInternalID(curOvl.Read16((uint)(0x6A)));
            KCLEditorForm kclForm = new KCLEditorForm(curKCL);

            kclForm.Show();
        }
                public SDATInfoPLAYER(NitroFile sdat, uint offset)
                {
                    m_Offset = offset;

                    m_SequenceMax         = sdat.Read8(m_Offset + 0x00);
                    m_Padding             = sdat.Read8(m_Offset + 0x01);
                    m_AllocChannelBitFlag = sdat.Read16(m_Offset + 0x02);
                    m_HeapSize            = sdat.Read32(m_Offset + 0x04);
                }
Esempio n. 11
0
        public BCA(NitroFile file)
        {
            m_File     = file;
            m_FileName = m_File.m_Name;

            ReadHeader();

            ReadAnimationData();
        }
                    /* Value	Type
                     * 0x0700	SEQ
                     * 0x0803	SEQARC
                     * 0x0601	BANK
                     * 0x0402	WAVEARC
                     *
                     * m_Index is the entry number in the relevant Record (SEQ/SEQARC/BANK/WAVEARC).
                     */

                    public GroupEntry(NitroFile sdat, uint offset)
                    {
                        m_Offset = offset;

                        m_Type     = sdat.Read8(m_Offset + 0x00);
                        m_LoadFlag = sdat.Read8(m_Offset + 0x01);
                        m_Padding  = sdat.Read16(m_Offset + 0x02);
                        m_Index    = sdat.Read32(m_Offset + 0x04);
                    }
Esempio n. 13
0
 public KCLEditorForm(NitroFile kclIn)
 {
     InitializeComponent();
     LoadKCL(kclIn);
     LoadColours();
     cmbPolygonMode.Items.Add("Fill");
     cmbPolygonMode.Items.Add("Wireframe");
     cmbPolygonMode.SelectedIndex = 0;
     matColTypes = new Dictionary <string, int>();
 }
Esempio n. 14
0
 public KCLEditorForm(NitroFile kclIn)
 {
     InitializeComponent();
     LoadKCL(kclIn);
     LoadColours();
     cmbPolygonMode.Items.Add("Fill");
     cmbPolygonMode.Items.Add("Wireframe");
     cmbPolygonMode.SelectedIndex = 0;
     matColTypes = new Dictionary<string, int>();
 }
 public SDATInfoRecord(NitroFile sdat, uint offset)
 {
     m_Offset      = offset;
     m_Count       = sdat.Read32(m_Offset);
     m_EntryOffset = new uint[m_Count];
     for (int i = 0; i < m_Count; i++)
     {
         m_EntryOffset[i] = sdat.Read32(m_Offset + 0x04 + (uint)(i * 4));
     }
 }
Esempio n. 16
0
        public BMD_KLC_Editor(string fileName)
        {
            InitializeComponent();
            panProperties.Controls.Clear();
            m_ModelName = fileName;
            if (m_ModelName.EndsWith(".bmd"))
            {
                m_ModelFile = Program.m_ROM.GetFileFromName(m_ModelName);
                m_Model     = new BMD(m_ModelFile);

                Text = fileName.Split('/').Last();
                TreeNode modelNode  = tvModelContent.Nodes.Add("Model");
                TreeNode chunksNode = modelNode.Nodes.Add("Chunks");

                int i = 0;
                foreach (BMD.ModelChunk chunk in m_Model.m_ModelChunks)
                {
                    TreeNode chunkNode = chunksNode.Nodes.Add(i.ToString(), chunk.m_Name);
                    chunkNode.Tag = chunk;
                    TreeNode matGroupsNode = chunkNode.Nodes.Add("Material Groups");

                    int i2 = 0;
                    foreach (BMD.MaterialGroup matGroup in chunk.m_MatGroups)
                    {
                        TreeNode matGroupNode = matGroupsNode.Nodes.Add(i2.ToString(), matGroup.m_Name);
                        matGroupNode.Tag = matGroup;
                        TreeNode vtxListsNode = matGroupNode.Nodes.Add("Vertex Lists");

                        int i3 = 0;
                        foreach (BMD.VertexList vtxList in matGroup.m_Geometry)
                        {
                            TreeNode vtxListNode = vtxListsNode.Nodes.Add(i3.ToString(), "Vertex Group[" + i3.ToString() + "] (" + m_primitiveNames[vtxList.m_PolyType] + ")");
                            vtxListNode.Tag = vtxList;
                            TreeNode vertsNode = vtxListNode.Nodes.Add("Vertices");

                            int i4 = 0;
                            foreach (BMD.Vertex vtx in vtxList.m_VertexList)
                            {
                                TreeNode vtxNode = vertsNode.Nodes.Add(i4.ToString(), "Vertex[" + i4.ToString() + "] (" + vtx.m_Position + ")");
                                vtxNode.Tag = vtx;
                                vtxNode.Nodes.Add("Position: " + vtx.m_Position);
                                vtxNode.Nodes.Add("Normal: " + vtx.m_Normal);
                                vtxNode.Nodes.Add("Texture Coordinates: " + vtx.m_TexCoord);
                                vtxNode.Nodes.Add("Vertex Color: " + vtx.m_Color);
                                vtxNode.Nodes.Add("Matrix ID: " + vtx.m_MatrixID);
                                i4++;
                            }
                            i3++;
                        }
                        i2++;
                    }
                    i++;
                }
            }
        }
                public SDATInfoBANK(NitroFile sdat, uint offset)
                {
                    m_Offset = offset;

                    m_FileID  = sdat.Read32(m_Offset + 0x00);
                    m_WaveArc = new ushort[4];
                    for (int i = 0; i < 4; i++)
                    {
                        m_WaveArc[i] = sdat.Read16(m_Offset + 0x04 + (uint)(i * 2));
                    }
                }
                public SDATInfoWAVEARC(NitroFile sdat, uint offset)
                {
                    m_Offset = offset;

                    uint num = sdat.Read32(m_Offset + 0x00);

                    m_FileID = (num & 16777215u);
                    m_Flag   = (byte)(num >> 24);

                    //er.Write((uint)((long)((long)this.flags << 24) | (long)((ulong)(this.fileID & 16777215u))));
                }
                public SDATInfoGROUP(NitroFile sdat, uint offset)
                {
                    m_Offset = offset;

                    m_Count        = sdat.Read32(m_Offset + 0x00);
                    m_GroupEntries = new GroupEntry[m_Count];
                    for (int i = 0; i < m_Count; i++)
                    {
                        m_GroupEntries[i] = new GroupEntry(sdat, m_Offset + 0x04 + (uint)(i * 8));
                    }
                }
Esempio n. 20
0
        public void LoadKCL(NitroFile kcl)
        {
            m_KCL = new KCL(kcl);

            m_Planes = m_KCL.m_Planes;

            lbxPlanes.Items.Clear();

            for (int i = 0; i < m_Planes.Count; i++)
            {
                lbxPlanes.Items.Add("Plane " + i.ToString("00000"));
            }
        }
                public SDATInfoSEQ(NitroFile sdat, uint offset)
                {
                    m_File   = sdat;
                    m_Offset = offset;

                    m_FileID          = sdat.Read32(m_Offset + 0x00);
                    m_Bank            = sdat.Read16(m_Offset + 0x04);
                    m_Volume          = sdat.Read8(m_Offset + 0x06);
                    m_ChannelPriority = sdat.Read8(m_Offset + 0x07);
                    m_PlayerPriority  = sdat.Read8(m_Offset + 0x08);
                    m_PlayerNumber    = sdat.Read8(m_Offset + 0x09);
                    m_Unknown2        = sdat.ReadBlock(m_Offset + 0x0A, 2);
                }
                public SDATInfoSTREAM(NitroFile sdat, uint offset)
                {
                    m_Offset = offset;

                    m_FileID         = sdat.Read32(m_Offset + 0x00);
                    m_Volume         = sdat.Read8(m_Offset + 0x04);
                    m_PlayerPriority = sdat.Read8(m_Offset + 0x05);
                    m_PlayerNumber   = sdat.Read8(m_Offset + 0x06);
                    m_Reserved       = new byte[5];
                    for (int i = 0; i < 5; i++)
                    {
                        m_Reserved[i] = sdat.Read8(m_Offset + 0x07 + (uint)(i));
                    }
                }
Esempio n. 23
0
        public KCLEditorForm(NitroFile kclIn)
        {
            InitializeComponent();
            LoadKCL(kclIn);

            cmbPolygonMode.Items.Add("Fill");
            cmbPolygonMode.Items.Add("Wireframe");
            cmbPolygonMode.SelectedIndex = 0;

            glModelView.Initialise();
            glModelView.ProvidePickingDisplayLists(m_KCLMeshPickingDLists);
            glModelView.ProvideDisplayLists(m_KCLMeshDLists);
            glModelView.ProvideCallListForDisplayLists(CallListForKCLDisplayLists);
        }
Esempio n. 24
0
        private void LoadMinimapFiles()
        {
            m_PalFile     = Program.m_ROM.GetFileFromInternalID(m_Level.m_LevelSettings.MinimapPalFileID);
            m_TileSetFile = Program.m_ROM.GetFileFromInternalID(m_Level.m_LevelSettings.MinimapTsetFileID);
            for (int j = 0; j < m_NumAreas; j++)
            {
                try
                {
                    if (j < m_Level.m_MinimapFileIDs.Length && m_Level.m_MinimapFileIDs[j] != 0)
                    {
                        m_TileMapFiles[j] = (Program.m_ROM.GetFileFromInternalID(m_Level.m_MinimapFileIDs[j]));
                        tsMinimapEditor.Items[1 + j].Enabled = true;
                    }
                    else
                    {
                        tsMinimapEditor.Items[1 + j].Enabled = false;
                    }
                }
                catch//If the file doesn't exist
                {
                    tsMinimapEditor.Items[1 + j].Enabled = false;
                }
            }

            m_TileMapFile = m_TileMapFiles[m_CurArea];
            m_TileMapFile.ForceDecompression();// Only to get accurate size below

            m_IsUsingTileMap = true;

            m_SizeX              = m_SizeY = (int)(Math.Sqrt(m_TileMapFile.m_Data.Length / 2) * 8); // Minimaps are squares
            m_BPP                = 8;                                                               // Bits per pixel is always 8 for the minimaps
            dmnHeight.Text       = dmnWidth.Text = "" + m_SizeX;
            m_PaletteRow         = 0; dmnPaletteRow.Text = "" + m_PaletteRow;
            cbxBPP.SelectedIndex = 1;
            if (m_SizeX == 128)
            {
                chk128.Checked = true;
                chk256.Checked = false;
            }
            else if (m_SizeX == 256)
            {
                chk128.Checked = false;
                chk256.Checked = true;
            }

            txtSelNCG.Text = m_TileSetFile.m_Name;
            txtSelNCL.Text = m_PalFile.m_Name;
            txtSelNSC.Text = m_TileMapFile.m_Name;
        }
Esempio n. 25
0
        private void LoadBTP(String filename)
        {
            try
            {
                NitroFile file = Program.m_ROM.GetFileFromName(filename);
                m_BTP = new BTP(file);

                LoadOnlyBTPReferencedTextures();

                PopulateBTPListBoxes();

                EnableBTPFormControls();
            }
            catch (Exception ex) { MessageBox.Show("Error loading BTP:\n" + ex.Message + "\n" + ex.StackTrace); }
        }
Esempio n. 26
0
        public void LoadKCL(NitroFile kcl)
        {
            m_KCL = new KCL(kcl);

            m_Planes = m_KCL.m_Planes;

            lbxPlanes.Items.Clear();

            for (int i = 0; i < m_Planes.Count; i++)
            {
                lbxPlanes.Items.Add("Plane " + i.ToString("00000"));
            }

            LoadColours();
        }
Esempio n. 27
0
        private void btnLZForceCompression_Click(object sender, EventArgs e)
        {
            NitroFile file = Program.m_ROM.GetFileFromName(m_SelectedFile);

            try
            {
                file.ForceCompression();
            }
            catch (Exception ex)
            {
                MessageBox.Show("There was an error trying to compress the file \"" + file.m_Name + "\" with " +
                                "LZ77 compression (no header)\n\n" + ex.Message + "\n\n" + ex.StackTrace);
            }
            file.SaveChanges();
        }
                public SDATInfoPLAYER2(NitroFile sdat, uint offset)
                {
                    m_Offset = offset;

                    m_Count         = sdat.Read8(m_Offset + 0x00);
                    m_ChannelNumber = new byte[16];
                    for (int i = 0; i < 16; i++)
                    {
                        m_ChannelNumber[i] = sdat.Read8(m_Offset + 0x01 + (uint)(i));
                    }
                    m_Padding = new byte[7];
                    for (int i = 0; i < 7; i++)
                    {
                        m_Padding[i] = sdat.Read8(m_Offset + 0x11 + (uint)(i));
                    }
                }
Esempio n. 29
0
            public byte[] m_Type; // 'SDAT' (4)

            #endregion Fields

            #region Constructors

            public SDATHeader(NitroFile sdat)
            {
                m_Type = sdat.ReadBlock(0x00, 4);
                m_Magic = sdat.Read32(0x04);
                m_FileSize = sdat.Read32(0x08);
                m_Size = sdat.Read16(0x0C);
                m_Block = sdat.Read16(0x0E);
                m_SymbolOffset = sdat.Read32(0x10);
                m_SymbolSize = sdat.Read32(0x14);
                m_InfoOffset = sdat.Read32(0x18);
                m_InfoSize = sdat.Read32(0x1C);
                m_FatOffset = sdat.Read32(0x20);
                m_FatSize = sdat.Read32(0x24);
                m_FileBlockOffset = sdat.Read32(0x28);
                m_FileBlockSize = sdat.Read32(0x2C);
                m_Reserved = sdat.ReadBlock(0x30, 16);
            }
            public byte[] m_Reserved;      // unused, 0s	(16)

            public SDATHeader(NitroFile sdat)
            {
                m_Type            = sdat.ReadBlock(0x00, 4);
                m_Magic           = sdat.Read32(0x04);
                m_FileSize        = sdat.Read32(0x08);
                m_Size            = sdat.Read16(0x0C);
                m_Block           = sdat.Read16(0x0E);
                m_SymbolOffset    = sdat.Read32(0x10);
                m_SymbolSize      = sdat.Read32(0x14);
                m_InfoOffset      = sdat.Read32(0x18);
                m_InfoSize        = sdat.Read32(0x1C);
                m_FatOffset       = sdat.Read32(0x20);
                m_FatSize         = sdat.Read32(0x24);
                m_FileBlockOffset = sdat.Read32(0x28);
                m_FileBlockSize   = sdat.Read32(0x2C);
                m_Reserved        = sdat.ReadBlock(0x30, 16);
            }
Esempio n. 31
0
        private void WriteChanges()
        {
            NitroFile kclFile = m_KCL.m_File;

            uint planeStart = (kclFile.Read32(8));

            planeStart += (uint)(0x10);

            for (int i = 0; i < m_Planes.Count; i++)
            {
                uint posColType = (uint)(planeStart + (i * 16) + 0x0E); //Get the address of this plane's Collision Type variable

                kclFile.Write16(posColType, (ushort)m_Planes[i].type);  //Write the new value to file
            }

            kclFile.SaveChanges();
        }
Esempio n. 32
0
        /// <summary>
        /// Open KPS.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ROMFileSelect r = new ROMFileSelect();

            r.ShowDialog();
            string file = r.m_SelectedFile;

            if (file != null && file != "")
            {
                nf = new NitroFile(Program.m_ROM, Program.m_ROM.GetFileIDFromName(file));

                MemoryStream src = new MemoryStream(nf.m_Data);
                BinaryReader br  = new BinaryReader(src);

                if (src.Length >= 0x10)
                {
                    UInt32 magic1 = br.ReadUInt32();
                    UInt32 magic2 = br.ReadUInt32();
                    if (magic1 == 0x00100001)
                    {
                        if (magic2 == 0x00140018)
                        {
                            OpenDkl(nf.m_Data, false);
                        }
                        else if (magic2 == 0x0018001C)
                        {
                            OpenDkl(nf.m_Data, true);
                        }
                        else
                        {
                            OpenBin(nf.m_Data);
                        }
                    }
                    else
                    {
                        OpenBin(nf.m_Data);
                    }
                }

                else
                {
                    OpenBin(nf.m_Data);
                }
            }
        }
Esempio n. 33
0
        private void btnEditCollisionMap_Click(object sender, EventArgs e)
        {
            uint         overlayID      = Program.m_ROM.GetLevelOverlayID(lbxLevels.SelectedIndex);
            NitroOverlay currentOverlay = new NitroOverlay(Program.m_ROM, overlayID);
            NitroFile    currentKCL     = Program.m_ROM.GetFileFromInternalID(currentOverlay.Read16((uint)(0x6A)));

            if (!Properties.Settings.Default.UseSimpleModelAndCollisionMapImporters)
            {
                ModelAndCollisionMapEditor kclForm =
                    new ModelAndCollisionMapEditor(null, currentKCL.m_Name, 1f, ModelAndCollisionMapEditor.StartMode.CollisionMap);
                kclForm.Show();
            }
            else
            {
                KCLEditorForm kclForm = new KCLEditorForm(currentKCL);
                kclForm.Show();
            }
        }
Esempio n. 34
0
        private void TextureEditorForm_Load(object sender, System.EventArgs e)
        {
            if (m_Name == null)
            {
                m_ROMFileSelect.ReInitialize("Select a SPT file to load", new string[] { ".spt" });
                DialogResult result = m_ROMFileSelect.ShowDialog();
                if (result != DialogResult.OK)
                {
                    Close();
                }
                else
                {
                    m_Name            = m_ROMFileSelect.m_SelectedFile;
                    m_ParticleTexFile = Program.m_ROM.GetFileFromName(m_Name);

                    cmbRepeatX.Items.Add(Particle.Texture.RepeatMode.CLAMP);
                    cmbRepeatX.Items.Add(Particle.Texture.RepeatMode.REPEAT);
                    cmbRepeatX.Items.Add(Particle.Texture.RepeatMode.FLIP);
                    cmbRepeatX.SelectedIndex = -1;

                    cmbRepeatY.Items.Add(Particle.Texture.RepeatMode.CLAMP);
                    cmbRepeatY.Items.Add(Particle.Texture.RepeatMode.REPEAT);
                    cmbRepeatY.Items.Add(Particle.Texture.RepeatMode.FLIP);
                    cmbRepeatY.SelectedIndex = -1;

                    cmbFormat.Items.Add("A3I5");
                    cmbFormat.Items.Add("Color4");
                    cmbFormat.Items.Add("Color16");
                    cmbFormat.Items.Add("Color256");
                    cmbFormat.Items.Add("Texel4x4 (unsupported)");
                    cmbFormat.Items.Add("A5I3");
                    cmbFormat.Items.Add("Direct");
                    cmbFormat.SelectedIndex = prevFormat = -1;

                    LoadTexture();
                    RefreshImage();
                    PopulatePaletteSettings();
                    UpdateForm();
                    ResetColourButtonValue(btnModelPalettesSelectedColour);
                }
            }
        }
Esempio n. 35
0
        private void btnReplaceRaw_Click(object sender, EventArgs e)
        {
            if (m_SelectedFile == null || m_SelectedFile.Equals(""))
            {
                return;
            }

            OpenFileDialog ofd = new OpenFileDialog();

            if (ofd.ShowDialog() == DialogResult.Cancel)
            {
                return;
            }

            NitroFile file = Program.m_ROM.GetFileFromName(m_SelectedFile);

            file.Clear();
            file.WriteBlock(0, System.IO.File.ReadAllBytes(ofd.FileName));
            file.SaveChanges();
        }
Esempio n. 36
0
        public void ReadStrings(String fileName)
        {
            file = Program.m_ROM.GetFileFromName(fileName);

            inf1size = file.Read32(0x24);
            ushort numentries = file.Read16(0x28);

            m_MsgData = new string[numentries];
            m_StringLengths = new int[numentries];
            m_ShortVersions = new string[numentries];
            m_FileSize = file.Read32(0x08);
            m_StringHeaderAddr = new uint[numentries];
            m_StringHeaderData = new uint[numentries];
            m_DAT1Start = 0x20 + inf1size + 0x08;

            for (int i = 0; i < numentries; i++)
            {
                m_StringHeaderAddr[i] = (uint)(0x20 + 0x10 + (i * 8));
                m_StringHeaderData[i] = file.Read32(m_StringHeaderAddr[i]);
            }

            lbxMsgList.Items.Clear();//Reset list of messages
            lbxMsgList.BeginUpdate();// Only draw when EndUpdate is called, much faster, expecially for Mono

            for (int i = 0; i < m_MsgData.Length; i++)
            {
                uint straddr = file.Read32((uint)(0x30 + i * 8));
                straddr += 0x20 + inf1size + 0x8;

                int length = 0;

                string thetext = "";
                for (; ; )
                {
                    byte cur;
                    try
                    {
                        cur = file.Read8(straddr);
                    }
                    catch
                    {
                        break;
                    }
                    straddr++;
                    length++;
                    char thechar = '\0';

                    /*if ((cur >= 0x00) && (cur <= 0x09))
                        thechar = (char)('0' + cur);
                    else if ((cur >= 0x0A) && (cur <= 0x23))
                        thechar = (char)('A' + cur - 0x0A);
                    else if ((cur >= 0x2D) && (cur <= 0x46))
                        thechar = (char)('a' + cur - 0x2D);
                    else if ((cur >= 0x50) && (cur <= 0xCF))//Extended ASCII Characters
                        thechar = (char)(0x30 + cur);*/
                    // Some characters are two bytes long, can skip the second

                    if (langNames[langIndex] == "jpn")
                    {
                        if (JAP_CHARS.GetFirstToSecond().ContainsKey(cur))
                        {
                            thetext += JAP_CHARS.GetByFirst(cur);
                            straddr += (JAP_SIZES[JAP_CHARS.GetByFirst(cur)] - 1);
                            length += (int)(JAP_SIZES[JAP_CHARS.GetByFirst(cur)] - 1);
                        }
                    }
                    else
                    {
                        if ((cur >= 0x00 && cur <= 0x4F) || (cur >= 0xEE && cur <= 0xFB))
                        {
                            thetext += BASIC_EUR_US_CHARS.GetByFirst(cur);
                            straddr += (BASIC_EUR_US_SIZES[BASIC_EUR_US_CHARS.GetByFirst(cur)] - 1);
                            length += (int)(BASIC_EUR_US_SIZES[BASIC_EUR_US_CHARS.GetByFirst(cur)] - 1);
                        }
                        else if (cur >= 0x50 && cur <= 0xCF)
                        {
                            thetext += EXTENDED_ASCII_CHARS.GetByFirst(cur);
                            straddr += (EXTENDED_ASCII_SIZES[EXTENDED_ASCII_CHARS.GetByFirst(cur)] - 1);
                            length += (int)(EXTENDED_ASCII_SIZES[EXTENDED_ASCII_CHARS.GetByFirst(cur)] - 1);
                        }
                    }

                    if (thechar != '\0')
                        thetext += thechar;
                    else if (cur == 0xFD)
                        thetext += "\r\n";
                    else if (cur == 0xFF)
                        break;
                    else if (cur == 0xFE)// Special Character
                    {
                        int len = file.Read8(straddr);
                        thetext += "[\\r]";
                        thetext += String.Format("{0:X2}", cur);
                        for (int spec = 0; spec < len - 1; spec++)
                        {
                            thetext += String.Format("{0:X2}", file.Read8((uint)(straddr + spec)));
                        }
                        length += (len - 1);// Already increased by 1 at start
                        straddr += (uint)(len - 1);
                    }
                }

                m_MsgData[i] = thetext;
                m_StringLengths[i] = length;
                m_ShortVersions[i] = ShortVersion(m_MsgData[i], i);

                lbxMsgList.Items.Add(m_ShortVersions[i]);

                btnImport.Enabled = true; btnExport.Enabled = true;
            }
            lbxMsgList.EndUpdate();
        }
Esempio n. 37
0
            public OctreeNode(NitroFile file, uint baseoffset, uint offset, Vector3 pos, Vector3 size)
            {
                m_Pos = pos;
                m_Size = size;
                m_LOL = false;
                m_PlaneList = new List<int>();

                uint node = file.Read32(offset);
                if ((node & 0x80000000) != 0)
                {
                    uint lolz = baseoffset + (node & 0x7FFFFFFF) + 2;
                    int n = 0;
                    string lmao = "";
                    for (; ; )
                    {
                        ushort p = file.Read16(lolz);
                        if (p == 0)
                            break;
                        else if (p == 37)
                            m_LOL = true;

                        m_PlaneList.Add(p - 1);
                        lmao += (p - 1).ToString() + " ";
                        lolz += 2;
                        n++;
                    }

                    if (n > maxkids)
                        maxkids = n;

                    //if (m_LOL)
                     //   MessageBox.Show(lmao);

                    m_NumPlanes = n;
                    OctreeNode.m_List.Add(this);
                }
                else
                {
                    uint parentoffset = baseoffset + node;
                    uint child0offset = parentoffset;
                    size /= 2f;
                    for (int z = 0; z < 2; z++)
                        for (int y = 0; y < 2; y++)
                            for (int x = 0; x < 2; x++)
                            { new OctreeNode(file, child0offset, parentoffset, pos + new Vector3(size.X * x, size.Y * y, size.Z * z), size); parentoffset += 4; }
                }
            }
Esempio n. 38
0
                public SDATInfoPLAYER2(NitroFile sdat, uint offset)
                {
                    m_Offset = offset;

                    m_Count = sdat.Read8(m_Offset + 0x00);
                    m_ChannelNumber = new byte[16];
                    for (int i = 0; i < 16; i++)
                        m_ChannelNumber[i] = sdat.Read8(m_Offset + 0x01 + (uint)(i));
                    m_Padding = new byte[7];
                    for (int i = 0; i < 7; i++)
                        m_Padding[i] = sdat.Read8(m_Offset + 0x11 + (uint)(i));
                }
Esempio n. 39
0
        public void ImportBMP(string filename, int bpp, int sizeX, int sizeY, bool replaceMinimap = false, int numTilesX = 0, 
            int numTilesY = 0, byte[] tilePaletteRows = null)
        {
            // The tile maps (NSC / ISC) files for minimaps are always arranged a particular way - 0, 1, 2...15, 32 for 128 x 128
            Bitmap bmp = new Bitmap(filename);

            Color[] palette = bmp.Palette.Entries.ToArray<Color>();
            if (palette.Length > 256)
            {
                MessageBox.Show("Too many colours\n\n" +
                    "You must import an indexed bitmap with 256 colours or fewer.");
                return;
            }

            //Write new palette
            m_PalFile = Program.m_ROM.GetFileFromName(txtSelNCL.Text);
            m_PalFile.Clear();
            for (int i = 0; i < palette.Length; i++)
            {
                //Colour in BGR15 format (16 bits) written to every even address 0,2,4...
                m_PalFile.Write16((uint)i * 2, (ushort)(Helper.ColorToBGR15(palette[i])));
            }
            for (int i = palette.Length; i < 256; i++)
                m_PalFile.Write16((uint)i * 2, 0);

            m_PalFile.SaveChanges();

            // Fill current tmapfiles to use full mapsize x mapsize
            if (m_IsUsingTileMap)
            {
                m_TileMapFile = Program.m_ROM.GetFileFromName(txtSelNSC.Text);
                m_TileMapFile.Clear();
                sizeX = bmp.Width;
                sizeY = bmp.Height;
                uint addr = 0;
                int curTile = 0;
                int row = (int)(sizeX / 8);

                for (int my = 0; my < sizeY; my += 8)
                {
                    for (int mx = 0; mx < sizeX; mx += 8)
                    {
                        m_TileMapFile.Write16(addr, (ushort)curTile);
                        curTile++;
                        addr += 2;
                    }
                }
                if (chkNSCDcmp.Checked)
                    m_TileMapFile.ForceCompression();
                m_TileMapFile.SaveChanges();
            }// End If usingTMap

            //Check to see if there's already an identical tile and if so, change the current value to that
            //Works, but not if you want to keep existing data eg. multiple maps

            //List<List<byte>> tiles = new List<List<byte>>();
            //List<byte> curTilePal = new List<byte>();
            //uint tileoffset = 0;
            //for (int my = 0; my < sizeY; my += 8)
            //{
            //    for (int mx = 0; mx < sizeX; mx += 8)
            //    {
            //        ushort tilecrap = tmapfile.Read16(tileoffset);
            //        uint tilenum = (uint)(tilecrap & 0x03FF);

            //        curTilePal = new List<byte>();
            //        for (int ty = 0; ty < 8; ty++)
            //        {
            //            for (int tx = 0; tx < 8; tx++)
            //            {
            //                uint totaloffset = (uint)(tilenum * 64 + ty * 8 + tx);//Position of current pixel's entry
            //                curTilePal.Add((byte)(Array.IndexOf(palette, bmp.GetPixel(mx + tx, my + ty))));
            //            }
            //        }

            //        tiles.Add(curTilePal);

            //        if (posInList(tiles, curTilePal) != -1)
            //        {
            //            tmapfile.Write16(tileoffset, (ushort)(posInList(tiles, curTilePal)));
            //        }

            //        tileoffset += 2;
            //    }
            //}

            //Write the new image to file
            m_TileSetFile = Program.m_ROM.GetFileFromName(txtSelNCG.Text);
            m_TileSetFile.Clear();
            uint tileoffset = 0;
            uint tileNum = 0;
            for (int my = 0; my < sizeY; my += 8)
            {
                for (int mx = 0; mx < sizeX; mx += 8)
                {
                    for (int ty = 0; ty < 8; ty++)
                    {
                        for (int tx = 0; tx < 8; tx++)
                        {
                            if (bpp == 8)
                            {
                                uint totaloffset = (uint)(tileNum * 64 + ty * 8 + tx);//Position of current pixel's entry
                                byte palentry = (byte)(Array.IndexOf(palette, bmp.GetPixel(mx + tx, my + ty)));
                                m_TileSetFile.Write8(totaloffset, (byte)(palentry));
                            }
                            else if (bpp == 4)
                            {
                                float totaloffset = (float)((float)(tileNum * 64 + ty * 8 + tx) / 2f);//Address of current pixel
                                byte palentry = (byte)(Array.IndexOf(palette, bmp.GetPixel(mx + tx, my + ty)));

                                int currentTileIndex = (int)tileNum;
                                byte currentTileRowIndex = tilePaletteRows[currentTileIndex];

                                byte rowStartColourOffset = (byte)(16 * currentTileRowIndex);
                                byte rowEndColourOffset = (byte)(16 * (currentTileRowIndex + 1) - 1);

                                if (palentry < rowStartColourOffset || palentry > rowEndColourOffset) // Referencing colour outisde its row
                                {
                                    Color referencedColour = Helper.BGR15ToColor(m_PalFile.Read16((uint)(palentry * 2)));

                                    // Find the same colour in the correct row and set the current pixel to reference that instead
                                    for (int col = rowStartColourOffset; col < rowEndColourOffset; col++)
                                    {
                                        uint offset = (uint)(col * 2);

                                        if (offset >= m_PalFile.m_Data.Length) break;

                                        Color currentColour = Helper.BGR15ToColor(m_PalFile.Read16(offset));
                                        if (currentColour.Equals(referencedColour))
                                        {
                                            palentry = (byte)col;
                                            break;
                                        }
                                    }
                                }

                                if (totaloffset % 1 == 0)
                                {
                                    // Right 4 bits
                                    m_TileSetFile.Write8((uint)totaloffset, (byte)palentry);
                                    //(byte)((tsetfile.Read8((uint)totaloffset) & 0xF0) | palentry));
                                }
                                else
                                {
                                    // Left 4 bits
                                    m_TileSetFile.Write8((uint)totaloffset, (byte)((palentry << 4) |
                                        (m_TileSetFile.Read8((uint)totaloffset) & 0x0F)));
                                }
                            }
                        }
                    }

                    tileoffset += 2;
                    tileNum++;
                }
            }

            if (chkNCGDcmp.Checked)
                m_TileSetFile.ForceCompression();
            m_TileSetFile.SaveChanges();

            // If it's a minimap that's being replaced, fill the tile maps to allow for multiple maps
            // and ensure the image's displayed at the right size as you can't change the size of
            // a level's minimap - it seems to be hardcoded somewhere (in level header?)
            if (replaceMinimap)
            {
                try
                {
                    if (chk128.Checked)
                        FillMinimapTiles(128);
                    else if (chk256.Checked)
                        FillMinimapTiles(256);
                }
                catch (Exception ex) { MessageBox.Show(ex.Message + ex.Source + ex.StackTrace); }
            }
        }
Esempio n. 40
0
                public SDATInfoSTREAM(NitroFile sdat, uint offset)
                {
                    m_Offset = offset;

                    m_FileID = sdat.Read32(m_Offset + 0x00);
                    m_Volume = sdat.Read8(m_Offset + 0x04);
                    m_PlayerPriority = sdat.Read8(m_Offset + 0x05);
                    m_PlayerNumber = sdat.Read8(m_Offset + 0x06);
                    m_Reserved = new byte[5];
                    for (int i = 0; i < 5; i++)
                        m_Reserved[i] = sdat.Read8(m_Offset + 0x07 + (uint)(i));
                }
Esempio n. 41
0
        private void LoadMinimapFiles()
        {
            m_PalFile = Program.m_ROM.GetFileFromInternalID(_owner.m_LevelSettings.MinimapPalFileID);
            m_TileSetFile = Program.m_ROM.GetFileFromInternalID(_owner.m_LevelSettings.MinimapTsetFileID);
            for (int j = 0; j < m_NumAreas; j++)
            {
                try
                {
                    if (j < _owner.m_MinimapFileIDs.Length && _owner.m_MinimapFileIDs[j] != 0)
                    {
                        m_TileMapFiles[j] = (Program.m_ROM.GetFileFromInternalID(_owner.m_MinimapFileIDs[j]));
                        tsMinimapEditor.Items[1 + j].Enabled = true;
                    }
                    else
                        tsMinimapEditor.Items[1 + j].Enabled = false;
                }
                catch//If the file doesn't exist
                {
                    tsMinimapEditor.Items[1 + j].Enabled = false;
                }
            }

            m_TileMapFile = m_TileMapFiles[m_CurArea];
            m_TileMapFile.ForceDecompression();// Only to get accurate size below

            m_IsUsingTileMap = true;

            m_SizeX = m_SizeY = (int)(Math.Sqrt(m_TileMapFile.m_Data.Length / 2) * 8);// Minimaps are squares
            m_BPP = 8;// Bits per pixel is always 8 for the minimaps
            dmnHeight.Text = dmnWidth.Text = "" + m_SizeX;
            m_PaletteRow = 0; dmnPaletteRow.Text = "" + m_PaletteRow;
            cbxBPP.SelectedIndex = 1;
            if (m_SizeX == 128)
            {
                chk128.Checked = true;
                chk256.Checked = false;
            }
            else if (m_SizeX == 256)
            {
                chk128.Checked = false;
                chk256.Checked = true;
            }

            txtSelNCG.Text = m_TileSetFile.m_Name;
            txtSelNCL.Text = m_PalFile.m_Name;
            txtSelNSC.Text = m_TileMapFile.m_Name;
        }
Esempio n. 42
0
        private void RedrawMinimap(Boolean usingTmap, int sizeX, int sizeY, int bpp, int paletteRow = 0)
        {
            m_TileSetFile = Program.m_ROM.GetFileFromName(txtSelNCG.Text);
            if (chkNCGDcmp.Checked)
            {
                m_TileSetFile.ForceDecompression();
            }

            m_PalFile = Program.m_ROM.GetFileFromName(txtSelNCL.Text);
            dmnPaletteRow.Items.Clear();
            for (int i = m_PalFile.m_Data.Length, j = 0; i > 0; i -= 32, j++)
            {
                dmnPaletteRow.Items.Insert(0, j);
            }

            if (!txtSelNSC.Text.Equals(""))
            {
                m_IsUsingTileMap = true;
                m_TileMapFile = Program.m_ROM.GetFileFromName(txtSelNSC.Text);
                if (chkNSCDcmp.Checked)
                {
                    m_TileMapFile.ForceDecompression();
                }
            }
            else
            {
                m_IsUsingTileMap = false;
            }

            Bitmap bmp = LoadImage(m_IsUsingTileMap, sizeX, sizeY, bpp, paletteRow);

            pbxMinimapGfx.Image = new Bitmap(bmp, new Size(sizeX * m_Zoom, sizeY * m_Zoom));
            pbxMinimapGfx.Refresh();

            LoadPalette();
        }
Esempio n. 43
0
        public KCL(NitroFile file)
        {
            m_File = file;

            m_Planes = new List<ColFace>();

            m_PointsSectionOffset = m_File.Read32(0x00);
            m_NormalsSectionOffset = m_File.Read32(0x04);
            m_PlanesSectionOffset = m_File.Read32(0x08);
            m_OctreeSectionOffset = m_File.Read32(0x0C);

            int planeid = 0;
            for (uint offset = m_PlanesSectionOffset + 0x10; offset < m_OctreeSectionOffset; offset += 0x10)
            {
                uint length = m_File.Read32(offset);

                ushort pt_id = m_File.Read16(offset + 0x04);
                int pt_x = (int)m_File.Read32((uint)(m_PointsSectionOffset + (pt_id*12)    ));
                int pt_y = (int)m_File.Read32((uint)(m_PointsSectionOffset + (pt_id*12) + 4));
                int pt_z = (int)m_File.Read32((uint)(m_PointsSectionOffset + (pt_id*12) + 8));

                ushort nr_id = m_File.Read16(offset + 0x06);
                short nr_x = (short)m_File.Read16((uint)(m_NormalsSectionOffset + (nr_id*6)    ));
                short nr_y = (short)m_File.Read16((uint)(m_NormalsSectionOffset + (nr_id*6) + 2));
                short nr_z = (short)m_File.Read16((uint)(m_NormalsSectionOffset + (nr_id*6) + 4));

                ushort d1_id = m_File.Read16(offset + 0x08);
                short d1_x = (short)m_File.Read16((uint)(m_NormalsSectionOffset + (d1_id*6)    ));
                short d1_y = (short)m_File.Read16((uint)(m_NormalsSectionOffset + (d1_id*6) + 2));
                short d1_z = (short)m_File.Read16((uint)(m_NormalsSectionOffset + (d1_id*6) + 4));

                ushort d2_id = m_File.Read16(offset + 0x0A);
                short d2_x = (short)m_File.Read16((uint)(m_NormalsSectionOffset + (d2_id*6)    ));
                short d2_y = (short)m_File.Read16((uint)(m_NormalsSectionOffset + (d2_id*6) + 2));
                short d2_z = (short)m_File.Read16((uint)(m_NormalsSectionOffset + (d2_id*6) + 4));

                ushort d3_id = m_File.Read16(offset + 0x0C);
                short d3_x = (short)m_File.Read16((uint)(m_NormalsSectionOffset + (d3_id*6)    ));
                short d3_y = (short)m_File.Read16((uint)(m_NormalsSectionOffset + (d3_id*6) + 2));
                short d3_z = (short)m_File.Read16((uint)(m_NormalsSectionOffset + (d3_id*6) + 4));

                ColFace plane = new ColFace((float)(length / 65536000f),
                    new Vector3((float)pt_x / 64000f, (float)pt_y / 64000f, (float)pt_z / 64000f),
                    new Vector3((float)nr_x / 1024f, (float)nr_y / 1024f, (float)nr_z / 1024f),
                    new Vector3((float)d1_x / 1024f, (float)d1_y / 1024f, (float)d1_z / 1024f),
                    new Vector3((float)d2_x / 1024f, (float)d2_y / 1024f, (float)d2_z / 1024f),
                    new Vector3((float)d3_x / 1024f, (float)d3_y / 1024f, (float)d3_z / 1024f),
                    m_File.Read16(offset + 0x0E));

               /* if (planeid == 31)
                    MessageBox.Show(string.Format("PLANE 32:\n{0}\n{1}\n{2}\n\n{3}\n{4}\n{5}\n\n{6}\n{7}\n{8}\n{9}\n{10}\n{11}",
                        d1_x, d1_y, d1_z,
                        d2_x, d2_y, d2_z,
                        plane.m_Position, plane.m_Normal, plane.m_Dir1, plane.m_Dir2, plane.m_Dir3, plane.m_Length));*/

                planeid++;

               /* if (Math.Abs(plane.m_Dir1.Length - 1f) > 0.0001f || Math.Abs(plane.m_Dir2.Length - 1f) > 0.0001f ||
                    Math.Abs(plane.m_Dir3.Length - 1f) > 0.0001f || Math.Abs(plane.m_Normal.Length - 1f) > 0.0001f ||
                    plane.m_Length < 0f)
                    MessageBox.Show(string.Format("WRONG PLANE | {0} | {1} | {2} | {3} | {4}",
                        plane.m_Dir1.Length, plane.m_Dir2.Length, plane.m_Dir3.Length, plane.m_Normal.Length, plane.m_Length));

                if (plane.m_Dir1.Length < 0.001f || plane.m_Dir2.Length < 0.001f ||
                    plane.m_Dir3.Length < 0.001f || plane.m_Normal.Length < 0.001f ||
                    Math.Abs(plane.m_Length) < 0.001f)
                    MessageBox.Show(string.Format("ZERO PLANE | {0} | {1} | {2} | {3} | {4}",
                        plane.m_Dir1.Length, plane.m_Dir2.Length, plane.m_Dir3.Length, plane.m_Normal.Length, plane.m_Length));

                Vector3 lol1 = Vector3.Cross(plane.m_Dir1, plane.m_Normal);
                float lol1len = plane.m_Length / (float)Math.Cos(Math.Acos(Math.Min(1f,Vector3.Dot(lol1, plane.m_Dir3))));
                Vector3 lol2 = Vector3.Cross(plane.m_Normal, plane.m_Dir2);
                float lol2len = plane.m_Length / (float)Math.Cos(Math.Acos(Math.Min(1f,Vector3.Dot(lol2, plane.m_Dir3))));
                if (Helper.VectorsEqual(plane.m_Position, Vector3.Multiply(lol1, lol1len)) ||
                    Helper.VectorsEqual(plane.m_Position, Vector3.Multiply(lol2, lol2len)))
                    MessageBox.Show(string.Format("WEIRD PLANE {5:X8} | {0} | {1} | {2} | {3} | {4}\n{6} | {7} / cos(acos({8})) = cos({9}) = {10}",
                        plane.m_Dir1, plane.m_Dir2, plane.m_Dir3, plane.m_Normal, plane.m_Length,
                        offset, lol2, plane.m_Length, Vector3.Dot(lol2, plane.m_Dir3), Math.Acos(Vector3.Dot(lol2, plane.m_Dir3)), Math.Cos(Math.Acos(Vector3.Dot(lol2, plane.m_Dir3)))));
                */
                m_Planes.Add(plane);
            }

            OctreeNode.maxkids = 0;
            int shift = (int)m_File.Read32(0x2C);
            Vector3 octreestart = new Vector3((float)(int)m_File.Read32(0x14) / 64000f, (float)(int)m_File.Read32(0x18) / 64000f, (float)(int)m_File.Read32(0x1C) / 64000f);
            float _cubesize = (float)(1 << shift) / 1024f;
            Vector3 cubesize = new Vector3(_cubesize, _cubesize, _cubesize);
            Vector3 octreesize = new Vector3((~m_File.Read32(0x20) >> shift) + 1, (~m_File.Read32(0x24) >> shift) + 1, (~m_File.Read32(0x28) >> shift) + 1);
            OctreeNode.m_List = new List<OctreeNode>();
            uint loloffset = m_OctreeSectionOffset;
            for (int z = 0; z < octreesize.Z; z++)
                for (int y = 0; y < octreesize.Y; y++)
                    for (int x = 0; x < octreesize.X; x++)
                    { new OctreeNode(m_File, m_OctreeSectionOffset, loloffset, octreestart + new Vector3(cubesize.X * x, cubesize.Y * y, cubesize.Z * z), cubesize); loloffset += 4; }

            //MessageBox.Show(OctreeNode.m_List.Count.ToString());
        }
Esempio n. 44
0
        public void SwitchBackground(int swapped)
        {
            m_PalFile = Program.m_ROM.GetFileFromName(txtSelNCL.Text);
            //The background colour is the first colour stored in the palette
            ushort first = m_PalFile.Read16((uint)0);//Read the first colour in the palette file
            ushort swappedColour = m_PalFile.Read16((uint)(swapped * 2));//Read the colour to be swapped
            //Colour in BGR15 format (16 bits) written to every even address 0,2,4...
            m_PalFile.Write16((uint)0, swappedColour);//Write new background colour to first entry
            m_PalFile.Write16((uint)(swapped * 2), first);//Write the previously first colour to the colour being swapped

            m_PalFile.SaveChanges();

            //Swap all palette file entries for the swapped colours in the graphic file
            m_TileSetFile = Program.m_ROM.GetFileFromName(txtSelNCG.Text);
            if (chkNCGDcmp.Checked)
                m_TileSetFile.ForceDecompression();
            uint tileoffset = 0, tilenum = 0;
            ushort tilecrap = 0;
            for (int my = 0; my < m_SizeY; my += 8)
            {
                for (int mx = 0; mx < m_SizeX; mx += 8)
                {
                    if (m_IsUsingTileMap)
                    {
                        tilecrap = m_TileMapFile.Read16(tileoffset);
                        tilenum = (uint)(tilecrap & 0x03FF);
                    }

                    for (int ty = 0; ty < 8; ty++)
                    {
                        for (int tx = 0; tx < 8; tx++)
                        {
                            if (m_BPP == 8)
                            {
                                uint totaloffset = (uint)(tilenum * 64 + ty * 8 + tx);//Position of current pixel's entry
                                byte palentry = m_TileSetFile.Read8(totaloffset);
                                if (palentry == 0)//If the current pixel points to first colour in palette,
                                    m_TileSetFile.Write8(totaloffset, (byte)(swapped));//point it to the swapped colour
                                if (palentry == (byte)swapped)//If the current pixel points to the swapped colour in palette,
                                    m_TileSetFile.Write8(totaloffset, (byte)0);//point it to the first colour
                            }
                            else if (m_BPP == 4)
                            {
                                float totaloffset = (float)((float)(tilenum * 64 + ty * 8 + tx) / 2f);//Address of current pixel
                                byte palentry = 0;
                                if (totaloffset % 1 == 0)
                                {
                                    // Right 4 bits
                                    palentry = m_TileSetFile.Read8((uint)totaloffset);//Offset of current pixel's entry in palette file
                                    palentry = (byte)(palentry & 0x0F);// Get 4 right bits
                                    if (palentry == 0)//If the current pixel points to first colour in palette,
                                        m_TileSetFile.Write8((uint)totaloffset, (byte)((m_TileSetFile.Read8((uint)totaloffset) & 0xF0) | swapped));//point it to the swapped colour
                                    if (palentry == (byte)swapped)//If the current pixel points to the swapped colour in palette,
                                        m_TileSetFile.Write8((uint)totaloffset, (byte)((m_TileSetFile.Read8((uint)totaloffset) & 0xF0) | 0));//point it to the first colour
                                }
                                else
                                {
                                    // Left 4 bits
                                    palentry = m_TileSetFile.Read8((uint)totaloffset);//Offset of current pixel's entry in palette file
                                    palentry = (byte)(palentry >> 4);
                                    if (palentry == 0)//If the current pixel points to first colour in palette,
                                        m_TileSetFile.Write8((uint)totaloffset, (byte)((swapped << 4) | (m_TileSetFile.Read8((uint)totaloffset) & 0x0F)));//point it to the swapped colour
                                    if (palentry == (byte)swapped)//If the current pixel points to the swapped colour in palette,
                                        m_TileSetFile.Write8((uint)totaloffset, (byte)(0 | (m_TileSetFile.Read8((uint)totaloffset) & 0x0F)));//point it to the first colour
                                }
                            }
                        }
                    }

                    tileoffset += 2;
                    if (!m_IsUsingTileMap)
                        tilenum++;
                }
            }

            if (chkNCGDcmp.Checked)
                m_TileSetFile.ForceCompression();
            m_TileSetFile.SaveChanges();

            RedrawMinimap(m_IsUsingTileMap, m_SizeX, m_SizeY, m_BPP, m_PaletteRow);
        }
Esempio n. 45
0
                public SDATInfoWAVEARC(NitroFile sdat, uint offset)
                {
                    m_Offset = offset;

                    uint num = sdat.Read32(m_Offset + 0x00);
                    m_FileID = (num & 16777215u);
                    m_Flag = (byte)(num >> 24);

                    //er.Write((uint)((long)((long)this.flags << 24) | (long)((ulong)(this.fileID & 16777215u))));
                }
Esempio n. 46
0
 public SDATInfoRecord(NitroFile sdat, uint offset)
 {
     m_Offset = offset;
     m_Count = sdat.Read32(m_Offset);
     m_EntryOffset = new uint[m_Count];
     for (int i = 0; i < m_Count; i++)
         m_EntryOffset[i] = sdat.Read32(m_Offset + 0x04 + (uint)(i * 4));
 }
Esempio n. 47
0
                public SDATInfoPLAYER(NitroFile sdat, uint offset)
                {
                    m_Offset = offset;

                    m_SequenceMax = sdat.Read8(m_Offset + 0x00);
                    m_Padding = sdat.Read8(m_Offset + 0x01);
                    m_AllocChannelBitFlag = sdat.Read16(m_Offset + 0x02);
                    m_HeapSize = sdat.Read32(m_Offset + 0x04);
                }
Esempio n. 48
0
                    /* Value	Type
                     * 0x0700	SEQ
                     * 0x0803	SEQARC
                     * 0x0601	BANK
                     * 0x0402	WAVEARC
                     *
                     * m_Index is the entry number in the relevant Record (SEQ/SEQARC/BANK/WAVEARC).
                     */
                    public GroupEntry(NitroFile sdat, uint offset)
                    {
                        m_Offset = offset;

                        m_Type = sdat.Read8(m_Offset + 0x00);
                        m_LoadFlag = sdat.Read8(m_Offset + 0x01);
                        m_Padding = sdat.Read16(m_Offset + 0x02);
                        m_Index = sdat.Read32(m_Offset + 0x04);
                    }
Esempio n. 49
0
                public SDATInfoBANK(NitroFile sdat, uint offset)
                {
                    m_Offset = offset;

                    m_FileID = sdat.Read32(m_Offset + 0x00);
                    m_WaveArc = new ushort[4];
                    for (int i = 0; i < 4; i++)
                    {
                        m_WaveArc[i] = sdat.Read16(m_Offset + 0x04 + (uint)(i * 2));
                    }
                }
Esempio n. 50
0
                public SDATInfoSEQARC(NitroFile sdat, uint offset)
                {
                    m_Offset = offset;

                    m_FileID = sdat.Read32(m_Offset + 0x00);
                }
Esempio n. 51
0
                public SDATInfoGROUP(NitroFile sdat, uint offset)
                {
                    m_Offset = offset;

                    m_Count = sdat.Read32(m_Offset + 0x00);
                    m_GroupEntries = new GroupEntry[m_Count];
                    for (int i = 0; i < m_Count; i++)
                    {
                        m_GroupEntries[i] = new GroupEntry(sdat, m_Offset + 0x04 + (uint)(i * 8));
                    }
                }
Esempio n. 52
0
 public AnimationDescriptor(NitroFile file, uint offset)
 {
     m_Interpolate = file.Read8(offset + 0x00);
     m_ConstantValue = (file.Read8(offset + 0x01) != 1);
     m_StartOffset = file.Read16(offset + 0x02);
 }
Esempio n. 53
0
                public SDATInfoSEQ(NitroFile sdat, uint offset)
                {
                    m_File = sdat;
                    m_Offset = offset;

                    m_FileID = sdat.Read32(m_Offset + 0x00);
                    m_Bank = sdat.Read16(m_Offset + 0x04);
                    m_Volume = sdat.Read8(m_Offset + 0x06);
                    m_ChannelPriority = sdat.Read8(m_Offset + 0x07);
                    m_PlayerPriority = sdat.Read8(m_Offset + 0x08);
                    m_PlayerNumber = sdat.Read8(m_Offset + 0x09);
                    m_Unknown2 = sdat.ReadBlock(m_Offset + 0x0A, 2);
                }
Esempio n. 54
0
            char[] m_Type; // 'INFO'

            #endregion Fields

            #region Constructors

            public SDATInfo(NitroFile sdat, uint offset)
            {
                m_Offset = offset;
                m_Type = sdat.ReadString(m_Offset + 0x00, 4).ToCharArray();
                m_Size = sdat.Read32(m_Offset + 0x04);
                m_RecordOffset = new uint[8];
                for (int i = 0; i < 8; i++)
                    m_RecordOffset[i] = sdat.Read32(m_Offset + 0x08 + (uint)(i * 4));
                m_Reserved = sdat.ReadBlock(m_Offset + 0x28, 24);

                m_Records = new SDATInfoRecord[8];
                for (int i = 0; i < 8; i++)
                {
                    m_Records[i] = new SDATInfoRecord(sdat, m_Offset + m_RecordOffset[i]);
                }
                m_Records0SEQ = new SDATInfoSEQ[m_Records[0].m_Count];
                for (int i = 0; i < m_Records[0].m_Count; i++)
                {
                    m_Records0SEQ[i] = new SDATInfoSEQ(sdat, m_Offset + m_Records[0].m_EntryOffset[i]);
                }
                m_Records1SEQARC = new SDATInfoSEQARC[m_Records[1].m_Count];
                for (int i = 0; i < m_Records[1].m_Count; i++)
                {
                    m_Records1SEQARC[i] = new SDATInfoSEQARC(sdat, m_Offset + m_Records[1].m_EntryOffset[i]);
                }
                m_Records2BANK = new SDATInfoBANK[m_Records[2].m_Count];
                for (int i = 0; i < m_Records[2].m_Count; i++)
                {
                    m_Records2BANK[i] = new SDATInfoBANK(sdat, m_Offset + m_Records[2].m_EntryOffset[i]);
                }
                m_Records3WAVEARC = new SDATInfoWAVEARC[m_Records[3].m_Count];
                for (int i = 0; i < m_Records[3].m_Count; i++)
                {
                    m_Records3WAVEARC[i] = new SDATInfoWAVEARC(sdat, m_Offset + m_Records[3].m_EntryOffset[i]);
                }
                m_Records4PLAYER = new SDATInfoPLAYER[m_Records[4].m_Count];
                for (int i = 0; i < m_Records[4].m_Count; i++)
                {
                    m_Records4PLAYER[i] = new SDATInfoPLAYER(sdat, m_Offset + m_Records[4].m_EntryOffset[i]);
                }
                m_Records5GROUP = new SDATInfoGROUP[m_Records[5].m_Count];
                for (int i = 0; i < m_Records[5].m_Count; i++)
                {
                    m_Records5GROUP[i] = new SDATInfoGROUP(sdat, m_Offset + m_Records[5].m_EntryOffset[i]);
                }
                m_Records6PLAYER2 = new SDATInfoPLAYER2[m_Records[6].m_Count];
                for (int i = 0; i < m_Records[6].m_Count; i++)
                {
                    m_Records6PLAYER2[i] = new SDATInfoPLAYER2(sdat, m_Offset + m_Records[6].m_EntryOffset[i]);
                }
                m_Records7STREAM = new SDATInfoSTREAM[m_Records[7].m_Count];
                for (int i = 0; i < m_Records[7].m_Count; i++)
                {
                    m_Records7STREAM[i] = new SDATInfoSTREAM(sdat, m_Offset + m_Records[7].m_EntryOffset[i]);
                }
            }
Esempio n. 55
0
        public BMD(NitroFile file)
        {
            m_File = file;
            m_FileName = file.m_Name;

            /* if (m_File.m_ID == 741)
                 lolol = true;
             else*/
            lolol = false;

            // Keep a list of pointers so it's easier to add/remove entries, space etc.
            m_PointerList = new List<PointerReference>();

            m_ScaleFactor = (float)(1 << (int)m_File.Read32(0x0));

            // ModelChunk refers to Bone
            m_NumModelChunks = m_File.Read32(0x04);
            m_ModelChunksOffset = m_File.Read32(0x08);
            AddPointer(0x08);
            for (int i = 0; i < m_NumModelChunks; i++)
            {
                AddPointer((uint)(m_ModelChunksOffset + (i * 64) + 0x04));
                AddPointer((uint)(m_ModelChunksOffset + (i * 64) + 0x34));
                AddPointer((uint)(m_ModelChunksOffset + (i * 64) + 0x38));
            }

            // PolyChunk refers to Display List
            m_NumPolyChunks = m_File.Read32(0x0C);
            m_PolyChunksOffset = m_File.Read32(0x10);
            AddPointer(0x10);
            for (int i = 0; i < m_NumPolyChunks; i++)
            {
                // Offset to Display List within Display List entries
                AddPointer((uint)(m_PolyChunksOffset + (i * 8) + 4));
                // Offsets within the Display List 16 byte headers
                AddPointer(m_File.Read32((uint)(m_PolyChunksOffset + (i * 8) + 4)) + 0x04);
                AddPointer(m_File.Read32((uint)(m_PolyChunksOffset + (i * 8) + 4)) + 0x0C);
            }
            m_NumTexChunks = m_File.Read32(0x14);
            m_TexChunksOffset = m_File.Read32(0x18);
            m_TextureIDs = new Dictionary<string, uint>();
            AddPointer(0x18);
            for (int i = 0; i < m_NumTexChunks; i++)
            {
                AddPointer((uint)(m_TexChunksOffset + (i * 20) + 0));
                AddPointer((uint)(m_TexChunksOffset + (i * 20) + 4));
                m_TextureIDs.Add(m_File.ReadString(m_File.Read32((uint)(m_TexChunksOffset + (20 * i))), 0), (uint)i);
            }
            m_NumPalChunks = m_File.Read32(0x1C);
            m_PalChunksOffset = m_File.Read32(0x20);
            m_PaletteIDs = new Dictionary<string, uint>();
            AddPointer(0x20);
            for (int i = 0; i < m_NumPalChunks; i++)
            {
                AddPointer((uint)(m_PalChunksOffset + (i * 16) + 0));
                AddPointer((uint)(m_PalChunksOffset + (i * 16) + 4));
                m_PaletteIDs.Add(m_File.ReadString(m_File.Read32((uint)(m_PalChunksOffset + (16 * i))), 0), (uint)i);
            }
            m_NumMatChunks = m_File.Read32(0x24);
            m_MatChunksOffset = m_File.Read32(0x28);
            AddPointer(0x28);
            for (int i = 0; i < m_NumMatChunks; i++)
            {
                AddPointer((uint)(m_MatChunksOffset + (i * 48) + 0));
            }
            m_BoneMapOffset = m_File.Read32(0x2C);
            AddPointer(0x2C);

            m_Textures = new Dictionary<string, Texture>();
            m_ModelChunks = new ModelChunk[m_NumModelChunks];

            for (uint c = 0; c < m_NumModelChunks; c++)
            {
                ModelChunk mdchunk = new ModelChunk(this);
                m_ModelChunks[c] = mdchunk;

                uint mdchunkoffset = m_ModelChunksOffset + (c * 64);

                mdchunk.m_ID = m_File.Read32(mdchunkoffset);
                mdchunk.m_Name = m_File.ReadString(m_File.Read32(mdchunkoffset + 0x04), 0);

                // transforms part
                {
                    int xscale = (int)m_File.Read32(mdchunkoffset + 0x10);
                    int yscale = (int)m_File.Read32(mdchunkoffset + 0x14);
                    int zscale = (int)m_File.Read32(mdchunkoffset + 0x18);
                    short xrot = (short)m_File.Read16(mdchunkoffset + 0x1C);
                    short yrot = (short)m_File.Read16(mdchunkoffset + 0x1E);
                    short zrot = (short)m_File.Read16(mdchunkoffset + 0x20);
                    int xtrans = (int)m_File.Read32(mdchunkoffset + 0x24);
                    int ytrans = (int)m_File.Read32(mdchunkoffset + 0x28);
                    int ztrans = (int)m_File.Read32(mdchunkoffset + 0x2C);

                    mdchunk.m_Scale = new Vector3((float)xscale / 4096.0f, (float)yscale / 4096.0f, (float)zscale / 4096.0f);
                    mdchunk.m_Rotation = new Vector3(((float)xrot * (float)Math.PI) / 2048.0f, ((float)yrot * (float)Math.PI) / 2048.0f, ((float)zrot * (float)Math.PI) / 2048.0f);
                    mdchunk.m_Translation = new Vector3((float)xtrans / 4096.0f, (float)ytrans / 4096.0f, (float)ztrans / 4096.0f);
                    mdchunk.m_Transform = Helper.SRTToMatrix(mdchunk.m_Scale, mdchunk.m_Rotation, mdchunk.m_Translation);

                    // Used when exporting bones
                    mdchunk.m_20_12Scale = new uint[] { (uint)xscale, (uint)yscale, (uint)zscale };
                    mdchunk.m_4_12Rotation = new ushort[] { (ushort)xrot, (ushort)yrot, (ushort)zrot };
                    mdchunk.m_20_12Translation = new uint[] { (uint)xtrans, (uint)ytrans, (uint)ztrans };

                    // if the chunk has a parent, apply the parent's transform to the chunk's transform.
                    // we don't need to go further than one level because the paren't transform already
                    // went through its parents' transforms.
                    short parent_offset = (short)m_File.Read16(mdchunkoffset + 0x8);
                    if (parent_offset < 0)
                    {
                        int parentchunkid = (int)(c + parent_offset);
                        Matrix4.Mult(ref mdchunk.m_Transform, ref m_ModelChunks[parentchunkid].m_Transform, out mdchunk.m_Transform);
                    }
                    mdchunk.m_ParentOffset = parent_offset;
                }
                // If 0x0A is set to 1 the bone has children, if 0 it doesn't
                mdchunk.m_HasChildren = (m_File.Read16(mdchunkoffset + 0x0A) == 1);

                mdchunk.m_SiblingOffset = (short)(m_File.Read16(mdchunkoffset + 0x0C));

                uint flags = m_File.Read32(mdchunkoffset + 0x3C);
                mdchunk.m_Billboard = ((flags & 0x1) == 0x1);

                uint numpairs = m_File.Read32(mdchunkoffset + 0x30);
                uint matlist = m_File.Read32(mdchunkoffset + 0x34);
                uint polylist = m_File.Read32(mdchunkoffset + 0x38);

                mdchunk.m_MatGroups = new MaterialGroup[numpairs];

                for (uint i = 0; i < numpairs; i++)
                {
                    MaterialGroup matgroup = new MaterialGroup();
                    mdchunk.m_MatGroups[i] = matgroup;

                    byte matID = m_File.Read8(matlist + i);
                    byte polyID = m_File.Read8(polylist + i);

                    uint mchunkoffset = (uint)(m_MatChunksOffset + (matID * 48));

                    matgroup.m_ID = matID;
                    matgroup.m_Name = m_File.ReadString(m_File.Read32(mchunkoffset), 0);
                    uint texid = m_File.Read32(mchunkoffset + 0x04);
                    uint palid = m_File.Read32(mchunkoffset + 0x08);
                    matgroup.m_TexParams = m_File.Read32(mchunkoffset + 0x20);
                    matgroup.m_PolyAttribs = m_File.Read32(mchunkoffset + 0x24);
                    matgroup.m_DifAmbColors = m_File.Read32(mchunkoffset + 0x28);
                    matgroup.m_SpeEmiColors = m_File.Read32(mchunkoffset + 0x2C);

                    if ((matgroup.m_PolyAttribs & 0x30) == 0x10)
                        matgroup.m_TexEnvMode = TextureEnvMode.Decal;
                    else
                        matgroup.m_TexEnvMode = TextureEnvMode.Modulate;

                    switch (matgroup.m_PolyAttribs & 0xC0)
                    {
                        case 0x00: matgroup.m_CullMode = CullFaceMode.FrontAndBack; break;
                        case 0x40: matgroup.m_CullMode = CullFaceMode.Front; break;
                        case 0x80: matgroup.m_CullMode = CullFaceMode.Back; break;
                    }

                    matgroup.m_DiffuseColor = Helper.BGR15ToColor((ushort)matgroup.m_DifAmbColors);
                    matgroup.m_AmbientColor = Helper.BGR15ToColor((ushort)(matgroup.m_DifAmbColors >> 16));
                    matgroup.m_SpecularColor = Helper.BGR15ToColor((ushort)matgroup.m_SpeEmiColors);
                    matgroup.m_EmissionColor = Helper.BGR15ToColor((ushort)(matgroup.m_SpeEmiColors >> 16));

                    switch (matgroup.m_TexParams >> 30)
                    {
                        case 0:
                            matgroup.m_TexCoordScale = new Vector2(1.0f, 1.0f);
                            matgroup.m_TexCoordTrans = new Vector2(0.0f, 0.0f);
                            break;

                        case 1:
                            {
                                int sscale = (int)m_File.Read32(mchunkoffset + 0x0C);
                                int tscale = (int)m_File.Read32(mchunkoffset + 0x10);
                                int strans = (int)m_File.Read32(mchunkoffset + 0x18);
                                int ttrans = (int)m_File.Read32(mchunkoffset + 0x1C);

                                matgroup.m_TexCoordScale = new Vector2((float)sscale / 4096.0f, (float)tscale / 4096.0f);
                                matgroup.m_TexCoordTrans = new Vector2((float)strans / 4096.0f, (float)ttrans / 4096.0f);
                                //matgroup.m_TexCoordTrans = new Vector2(0.0f, 16.0f);
                                /*System.Windows.Forms.MessageBox.Show(String.Format("textransform: scale:{0} trans:{1} rot:{2:X8}",
                                    matgroup.m_TexCoordScale, matgroup.m_TexCoordTrans,
                                    m_File.Read32(mchunkoffset + 0x1C)));*/
                            }
                            break;

                        case 2:
                            goto case 1;

                        case 3:
                            goto case 1;

                        default:
                            break;
                        // throw new Exception(String.Format("BMD: unsupported texture coord transform mode {0}", matgroup.m_TexParams >> 30));
                    }

                    if (texid != 0xFFFFFFFF)
                    {
                        matgroup.m_Texture = ReadTexture(texid, palid);
                        matgroup.m_TexParams |= matgroup.m_Texture.m_Params;
                    }
                    else
                        matgroup.m_Texture = null;

                    uint pchunkoffset = m_File.Read32((uint)(m_PolyChunksOffset + (polyID * 8) + 4));
                    uint dloffset = m_File.Read32(pchunkoffset + 0x0C);
                    uint dlsize = m_File.Read32(pchunkoffset + 0x08);
                    uint numbones = m_File.Read32(pchunkoffset);
                    uint bonesoffset = m_File.Read32(pchunkoffset + 0x04);

                    matgroup.m_BoneIDs = new ushort[numbones];
                    for (uint b = 0; b < numbones; b++)
                    {
                        byte idx1 = m_File.Read8(bonesoffset + b);
                        matgroup.m_BoneIDs[b] = m_File.Read16((uint)(m_BoneMapOffset + (2 * idx1)));
                    }

                    matgroup.m_Geometry = new List<VertexList>();

                    m_CurVertex.m_Position = new Vector3(0, 0, 0);
                    m_CurVertex.m_TexCoord = new Vector2(0, 0);
                    if ((matgroup.m_DifAmbColors & 0x8000) == 0x8000)
                    {
                        byte alpha = (byte)((matgroup.m_PolyAttribs >> 13) & 0xF8);
                        alpha |= (byte)(alpha >> 5);
                        matgroup.m_Alpha = alpha;

                        m_CurVertex.m_Color = Color.FromArgb(alpha, matgroup.m_DiffuseColor);
                    }
                    else
                        m_CurVertex.m_Color = Color.Black;

                    m_CurVertex.m_MatrixID = 0;

                    uint dlend = dloffset + dlsize;
                    for (uint pos = dloffset; pos < dlend; )
                    {
                        byte cmd1 = m_File.Read8(pos++);
                        byte cmd2 = m_File.Read8(pos++);
                        byte cmd3 = m_File.Read8(pos++);
                        byte cmd4 = m_File.Read8(pos++);

                        ProcessGXCommand(matgroup, cmd1, ref pos);
                        ProcessGXCommand(matgroup, cmd2, ref pos);
                        ProcessGXCommand(matgroup, cmd3, ref pos);
                        ProcessGXCommand(matgroup, cmd4, ref pos);
                    }
                }
            }

            foreach (ModelChunk mdchunk in m_ModelChunks)
            {
                foreach (MaterialGroup matgroup in mdchunk.m_MatGroups)
                {
                    matgroup.m_BoneMatrices = new Matrix4[matgroup.m_BoneIDs.Length];
                    for (uint b = 0; b < matgroup.m_BoneIDs.Length; b++)
                        matgroup.m_BoneMatrices[b] = m_ModelChunks[matgroup.m_BoneIDs[b]].m_Transform;
                }
            }
        }