Example #1
0
        public Bitmap LoadImage(Boolean usingTMap, int sizeX, int sizeY, int bpp, int paletteRow = 0)
        {
            Bitmap bmp = new Bitmap(sizeX, sizeY);

            uint   tileoffset = 0, tilenum = 0;
            ushort tilecrap = 0;

            for (int my = 0; my < sizeY; my += 8)
            {
                for (int mx = 0; mx < sizeX; mx += 8)
                {
                    if (usingTMap)
                    {
                        tilecrap = m_TileMapFile.Read16(tileoffset);
                        tilenum  = (uint)(tilecrap & 0x03FF);
                    }

                    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); //Address of current pixel
                                byte palentry    = m_TileSetFile.Read8(totaloffset);   //Offset of current pixel's entry in palette file
                                //Palentry is double to get the position of the colour in the palette file
                                ushort pixel = m_PalFile.Read16((uint)(palentry * 2)); //Colour of current pixel from palette file
                                bmp.SetPixel(mx + tx, my + ty, Helper.BGR15ToColor(pixel));
                            }
                            else if (bpp == 4)
                            {
                                float totaloffset = (float)((float)(tilenum * 64 + ty * 8 + tx) / 2f);//Address of current pixel
                                byte  palentry    = 0;
                                if (totaloffset % 1 == 0)
                                {
                                    palentry = m_TileSetFile.Read8((uint)totaloffset); //Offset of current pixel's entry in palette file
                                    palentry = (byte)(palentry & 0x0F);                // Get 4 right bits
                                }
                                else
                                {
                                    palentry = m_TileSetFile.Read8((uint)totaloffset); //Offset of current pixel's entry in palette file
                                    palentry = (byte)(palentry >> 4);                  // Get 4 left bits
                                }
                                //Palentry is double to get the position of the colour in the palette file
                                ushort pixel = m_PalFile.Read16((uint)((palentry * 2) + (m_PaletteRow * 32)));//Colour of current pixel from palette file
                                bmp.SetPixel(mx + tx, my + ty, Helper.BGR15ToColor(pixel));
                            }
                        }
                    }

                    tileoffset += 2;
                    if (!usingTMap)
                    {
                        tilenum++;
                    }
                }
            }

            return(bmp);
        }
Example #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;
                            }
                        }
                    }
                }
            }
            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);
            }
Example #4
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 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);
                }
                    /* 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);
                    }
                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 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);
                }
Example #9
0
        private void WriteData()
        {
            // Encode and write all edited string entries
            foreach (int index in m_EditedEntries)
            {
                List <byte> entry = EncodeString(m_MsgData[index]);
                file.WriteBlock(m_StringHeaderData[index] + m_DAT1Start, entry.ToArray <byte>());
            }

            for (int i = 0; i < file.Read16(0x28); i++)
            {
                file.Write32(m_StringHeaderAddr[i], m_StringHeaderData[i]);
                file.Write16(m_StringWidthAddr[i], m_StringWidth[i]);
                file.Write16(m_StringHeightAddr[i], m_StringHeight[i]);
            }

            // Compress file
            //file.Compress();

            // Save changes
            file.SaveChanges();
        }
Example #10
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();
        }
Example #11
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\nYou must import an indexed bitmap with a maximum of 256 colours.");
                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])));
            }
            // Pad the palette to a multiple of 16 colours
            byte nColourSlots = (byte)((palette.Length % 16 != 0) ? ((palette.Length + 16) & ~15) : palette.Length);

            for (int i = palette.Length; i < nColourSlots; 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 since minimap sizes are hard-coded,
            // they are not based on the size of the imported image.
            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); }
            }

            m_SizeX = sizeX;
            m_SizeY = sizeY;
        }
Example #12
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);
        }
Example #13
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); }
            }
        }
Example #14
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());
        }
Example #15
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();
        }
Example #16
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);
 }
Example #17
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());
        }
Example #18
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);
        }
Example #19
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);
                }
Example #20
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; }
                }
            }
Example #21
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);
                    }
Example #22
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, NitroTexture>();
            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_TexCoordRot   = 0.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);
                        short trot   = (short)m_File.Read16(mchunkoffset + 0x14);
                        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_TexCoordRot   = ((float)trot * (float)Math.PI) / 2048.0f;
                        matgroup.m_TexCoordTrans = new Vector2((float)strans / 4096.0f, (float)ttrans / 4096.0f);
                    }
                    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_DSTexParam;
                    }
                    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 = null;
                    m_CurVertex.m_Normal   = null;

                    if ((matgroup.m_PolyAttribs & 0x8000) != 0x8000)
                    {
                        byte alpha = (byte)((matgroup.m_PolyAttribs >> 16) & 0x1F);
                        alpha           |= (byte)(alpha >> 5);
                        matgroup.m_Alpha = alpha;
                    }

                    if ((matgroup.m_DifAmbColors & 0x8000) == 0x8000)
                    {
                        m_CurVertex.m_Color = Color.FromArgb(matgroup.m_Alpha << 3, 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;
                    }
                }
            }

            int index = 0;

            foreach (KeyValuePair <string, uint> entry in m_TextureIDs)
            {
                if (!m_Textures.ContainsKey(entry.Key))
                {
                    Console.WriteLine("NOT IN TEXTURES: " + entry.Key);
                    uint palID = Math.Min(m_PaletteIDs.ElementAt(index).Value, (uint)m_PaletteIDs.Count - 1);
                    ReadTexture(entry.Value, palID);
                }
                index++;
            }
        }
Example #23
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));
                    }
                }
Example #24
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;
                }
            }
        }
Example #25
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);
 }
Example #26
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);
                }