コード例 #1
0
        // assemblers
        private void Disassemble()
        {
            animationOffset = Bits.GetInt24(rom, 0x252000 + (index * 3)) - 0xC00000;
            int animationLength = Bits.GetShort(rom, animationOffset);

            buffer = Bits.GetBytes(rom, animationOffset, animationLength);
            //
            int    offset = 2;
            ushort sequencePacketPointer = Bits.GetShort(buffer, offset); offset += 2;
            ushort moldPacketPointer     = Bits.GetShort(buffer, offset); offset += 2;
            byte   sequenceCount         = buffer[offset++];
            byte   moldCount             = buffer[offset++];

            vramAllocation = (ushort)(buffer[offset] << 8); offset += 2;
            unknown        = Bits.GetShort(buffer, offset);
            //
            offset = sequencePacketPointer;
            for (int i = 0; i < sequenceCount; i++)
            {
                Sequence tSequence = new Sequence();
                tSequence.Disassemble(buffer, offset);
                sequences.Add(tSequence);
                offset += 2;
            }
            offset = moldPacketPointer;
            for (int i = 0; i < moldCount; i++)
            {
                Mold tMold = new Mold();
                tMold.Disassemble(buffer, offset, uniqueTiles, index, animationOffset);
                molds.Add(tMold);
                offset += 2;
            }
        }
コード例 #2
0
 public void SetScreenImages()
 {
     if (MinecartData == null)
     {
         return;
     }
     screenImages = new List <Bitmap>();
     for (int i = 0; i < L1Indexes.Count; i++)
     {
         if (L1Indexes[i] < 16)
         {
             byte[] tilemapL1 = Bits.GetBytes(Model.MinecartSSTilemap, L1Indexes[i] * 256, 256);
             byte[] tilemapL2;
             if (Index == 2)
             {
                 tilemapL2 = Bits.GetBytes(Model.MinecartSSTilemap, L2Indexes[i] * 256, 256);
             }
             else
             {
                 tilemapL2 = new byte[256];
             }
             SideTilemap tilemap     = new SideTilemap(tilemapL1, tilemapL2, tileset, paletteSet);
             Bitmap      screenImage = Do.PixelsToImage(tilemap.Pixels, 256, 256);
             screenImages.Add(new Bitmap(screenImage));
         }
         else
         {
             screenImages.Add(new Bitmap(256, 256));
         }
     }
     pictureBoxScreens.Invalidate();
 }
コード例 #3
0
 // main title tileset
 public Tileset(PaletteSet paletteSet, string type)
 {
     this.paletteSet = paletteSet;
     this.Width      = 16;
     this.Height     = 32;
     this.HeightL3   = 6;
     this.tilesize   = 2;
     this.Type       = TilesetType.Title;
     // Decompress data at offsets
     tilesets_bytes[0] = Bits.GetBytes(Model.TitleData, 0x0000, 0x1000);
     tilesets_bytes[1] = Bits.GetBytes(Model.TitleData, 0x1000, 0x1000);
     tilesets_bytes[2] = Bits.GetBytes(Model.TitleData, 0xBBE0, 0x300);
     // Create buffer the size of the combined graphicSets
     graphics   = Bits.GetBytes(Model.TitleData, 0x6C00, 0x4FE0);
     graphicsL3 = Bits.GetBytes(Model.TitleData, 0xBEA0, 0x1BC0);
     //
     tilesets_tiles[0] = new Tile[16 * 32];
     tilesets_tiles[1] = new Tile[16 * 32];
     tilesets_tiles[2] = new Tile[16 * 6];
     for (int i = 0; i < tilesets_tiles[0].Length; i++)
     {
         tilesets_tiles[0][i] = new Tile(i);
     }
     for (int i = 0; i < tilesets_tiles[1].Length; i++)
     {
         tilesets_tiles[1][i] = new Tile(i);
     }
     for (int i = 0; i < tilesets_tiles[2].Length; i++)
     {
         tilesets_tiles[2][i] = new Tile(i);
     }
     DrawTileset(tilesets_bytes[0], tilesets_tiles[0], graphics, 0x20);
     DrawTileset(tilesets_bytes[1], tilesets_tiles[1], graphics, 0x20);
     DrawTileset(tilesets_bytes[2], tilesets_tiles[2], graphicsL3, 0x20);
 }
コード例 #4
0
 public void SetScreenImage()
 {
     if (MinecartData == null)
     {
         return;
     }
     if (screenIndex >= L1Indexes.Count)
     {
         return;
     }
     if (L1Indexes[screenIndex] < 16)
     {
         byte[] tilemapL1 = Bits.GetBytes(Model.MinecartSSTilemap, L1Indexes[screenIndex] * 256, 256);
         byte[] tilemapL2;
         if (Index == 2)
         {
             tilemapL2 = Bits.GetBytes(Model.MinecartSSTilemap, L2Indexes[screenIndex] * 256, 256);
         }
         else
         {
             tilemapL2 = new byte[256];
         }
         SideTilemap tilemap = new SideTilemap(tilemapL1, tilemapL2, tileset, paletteSet);
         screenImages[screenIndex] = Do.PixelsToImage(tilemap.Pixels, 256, 256);
     }
     else
     {
         screenImages[screenIndex] = new Bitmap(256, 256);
     }
     pictureBoxScreens.Invalidate();
 }
コード例 #5
0
        private void fillWith_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyData != Keys.Enter)
            {
                return;
            }
            if (currentROMData.SelectionLength < 3)
            {
                return;
            }
            int  column = ROMData.SelectionStart / 3;
            byte value;

            try
            {
                value = Convert.ToByte(fillWith.Text, 16);
                byte[] values = new byte[currentROMData.SelectionLength / 3];
                Bits.Fill(values, value);
                oldProperties.Add(new Change(offset + column,
                                             Bits.GetBytes(current, offset + column, values.Length), Color.Red));
                Bits.Fill(current, value, offset + column, values.Length);
            }
            catch
            {
                return;
            }
            RefreshHexEditor();
        }
コード例 #6
0
        // assemblers
        private void Disassemble()
        {
            animationOffset = Bits.GetInt24(rom, 0x252C00 + (index * 3)) - 0xC00000;
            ushort animationLength = Bits.GetShort(rom, animationOffset);

            buffer = Bits.GetBytes(rom, animationOffset, Bits.GetShort(rom, animationOffset));
            //
            int    offset                = 2;
            ushort graphicSetPointer     = Bits.GetShort(buffer, offset); offset += 2;
            ushort paletteSetPointer     = Bits.GetShort(buffer, offset); offset += 2;
            ushort sequencePacketPointer = Bits.GetShort(buffer, offset); offset += 2;
            ushort moldPacketPointer     = Bits.GetShort(buffer, offset); offset += 2;

            // skip 2 unknown bytes
            offset += 2;
            //
            width  = buffer[offset++];
            height = buffer[offset++];
            codec  = Bits.GetShort(buffer, offset); offset += 2;
            //
            int tileSetPointer = Bits.GetShort(buffer, offset);

            graphicSetLength = paletteSetPointer - graphicSetPointer;
            graphicSet       = new byte[0x2000];
            Buffer.BlockCopy(buffer, graphicSetPointer, graphicSet, 0, graphicSetLength);
            paletteSetLength = (ushort)(tileSetPointer - paletteSetPointer);
            paletteSet       = new PaletteSet(buffer, 0, paletteSetPointer, 8, 16, 32);
            tilesetLength    = sequencePacketPointer - tileSetPointer - 2;
            tileset_bytes    = new byte[64 * 4 * 2 * 4];
            Buffer.BlockCopy(buffer, tileSetPointer, tileset_bytes, 0, tilesetLength);
            //
            offset = sequencePacketPointer;
            for (int i = 0; Bits.GetShort(buffer, offset) != 0x0000; i++)
            {
                E_Sequence tSequence = new E_Sequence();
                tSequence.Disassemble(buffer, offset);
                sequences.Add(tSequence);
                offset += 2;
            }
            offset = moldPacketPointer;
            ushort end = 0;

            for (int i = 0; Bits.GetShort(buffer, offset) != 0x0000; i++)
            {
                if (Bits.GetShort(buffer, offset + 2) == 0x0000)
                {
                    end = animationLength;
                }
                else
                {
                    end = Bits.GetShort(buffer, offset + 2);
                }
                E_Mold tMold = new E_Mold();
                tMold.Disassemble(buffer, offset, end);
                molds.Add(tMold);
                offset += 2;
            }
        }
コード例 #7
0
ファイル: BRR.cs プロジェクト: TheBestNSMB/LazyShell-Ultimate
        public static byte[] BRRToWAV(byte[] inBrr, int rate, int loopStart)
        {
            if (inBrr == null)
            {
                inBrr = new byte[9];
            }
            p1 = 0; p2 = 0;
            short[] samples = new short[0];
            byte[]  BRR     = new byte[9];
            int     size    = (int)inBrr.Length;
            //if (size % 9 != 0)
            //{
            //    MessageBox.Show("Error : BRR file isn't a multiple of 9 bytes or is too big.");
            //    return null;
            //}
            int blockamount = size / 9;
            int offset      = 0;

            size = 0;
            for (int i = 0; i < blockamount; i++)
            {
                BRR     = Bits.GetBytes(inBrr, offset, 9); offset += 9;
                samples = append(samples, DecodeBRR(BRR));      //Append 16 BRR samples to existing array
                size   += 16;
            }
            //
            int position = loopStart / 9 * 16;

            if (position >= size)
            {
                position = 0;
            }
            size -= position;
            //
            byte[] outWav = new byte[(size << 1) + 44];
            offset = 0;
            Bits.SetChars(outWav, offset, "RIFF".ToCharArray()); offset     += 4;
            Bits.SetInt32(outWav, offset, (size << 1) + 36); offset         += 4;
            Bits.SetChars(outWav, offset, "WAVEfmt ".ToCharArray()); offset += 8;
            Bits.SetInt32(outWav, offset, 16); offset                   += 4;
            Bits.SetShort(outWav, offset, 1); offset                    += 2;
            Bits.SetShort(outWav, offset, 1); offset                    += 2;
            Bits.SetInt32(outWav, offset, rate); offset                 += 4;
            Bits.SetInt32(outWav, offset, rate * 2); offset             += 4;
            Bits.SetShort(outWav, offset, 2); offset                    += 2;
            Bits.SetShort(outWav, offset, 16); offset                   += 2;
            Bits.SetChars(outWav, offset, "data".ToCharArray()); offset += 4;
            Bits.SetInt32(outWav, offset, size << 1); offset            += 4;
            //
            for (int i = position; i < size + position; i++)
            {
                Bits.SetShort(outWav, offset, samples[i]);
                offset += 2;
            }
            return(outWav);
        }
コード例 #8
0
        private void copy_Click(object sender, EventArgs e)
        {
            if (ROMData.SelectionLength < 3)
            {
                return;
            }
            int column = ROMData.SelectionStart / 3;

            clipboard = Bits.GetBytes(rom, offset + column, ROMData.SelectionLength / 3);
        }
コード例 #9
0
        private void paste_Click(object sender, EventArgs e)
        {
            int column = ROMData.SelectionStart / 3;

            if (offset + column + clipboard.Length >= 0x400000)
            {
                return;
            }
            oldProperties.Add(new Change(offset + column,
                                         Bits.GetBytes(current, offset + column, clipboard.Length), Color.Red));
            Bits.SetBytes(current, offset + column, clipboard);
            RefreshHexEditor();
        }
コード例 #10
0
        private void redo_Click(object sender, EventArgs e)
        {
            if (newProperties.Count == 0)
            {
                return;
            }
            int offset = newProperties[newProperties.Count - 1].Offset;

            byte[] newValues = newProperties[newProperties.Count - 1].Values;
            newProperties.RemoveAt(newProperties.Count - 1);
            byte[] oldValues = Bits.GetBytes(current, offset, newValues.Length);
            oldProperties.Add(new Change(offset, oldValues, Color.Red));
            Bits.SetBytes(current, offset, newValues);
            RefreshHexEditor();
        }
コード例 #11
0
        // assemblers
        private void Disassemble()
        {
            int offset = Bits.GetInt24(rom, index * 3 + 0x042333);

            if (offset == 0)
            {
                return;
            }
            offset -= 0xC00000;
            int size = Bits.GetShort(rom, offset); offset += 2;

            sample    = Bits.GetBytes(rom, offset, size);
            loopStart = Bits.GetShort(rom, index * 2 + 0x04248F);
            relGain   = (short)Bits.GetShort(rom, index * 2 + 0x042577);
            relFreq   = (short)Bits.GetShort(rom, index * 2 + 0x04265F);
        }
コード例 #12
0
        // event handlers
        private void browseFreshRom_Click(object sender, EventArgs e)
        {
            OpenFileDialog openFileDialog1 = new OpenFileDialog();

            openFileDialog1.InitialDirectory = settings.LastRomPath;
            openFileDialog1.Title            = "Select a SMRPG ROM";
            openFileDialog1.Filter           = "SMC files (*.SMC)|*.SMC|All files (*.*)|*.*";
            openFileDialog1.FilterIndex      = 2;
            openFileDialog1.RestoreDirectory = true;
            if (openFileDialog1.ShowDialog() != DialogResult.Cancel)
            {
Retry:
                try
                {
                    FileInfo     fInfo    = new FileInfo(openFileDialog1.FileName);
                    long         numBytes = fInfo.Length;
                    FileStream   fStream  = new FileStream(openFileDialog1.FileName, FileMode.Open, FileAccess.Read);
                    BinaryReader br       = new BinaryReader(fStream);
                    byte[]       temp     = br.ReadBytes((int)numBytes);
                    br.Close();
                    fStream.Close();
                    // remove header if it has one
                    if ((temp.Length & 0x200) == 0x200)
                    {
                        temp = Bits.GetBytes(temp, 0x200);
                    }
                    // Check if valid rom
                    System.Text.Encoding encoding = System.Text.Encoding.UTF8;
                    if (encoding.GetString(Bits.GetBytes(temp, 0x7FB2, 4)) != "ARWE")
                    {
                        MessageBox.Show("The game code for this ROM is invalid.", "LAZY SHELL");
                        return;
                    }
                    romSrc = temp;
                    freshRomTextBox.Text = openFileDialog1.FileName;
                    buttonOK.Enabled     = true;
                }
                catch (Exception ex)
                {
                    if (MessageBox.Show("Lazy Shell was unable to load the rom.\n\n" + ex.Message,
                                        "LAZY SHELL", MessageBoxButtons.RetryCancel, MessageBoxIcon.Error) != DialogResult.Cancel)
                    {
                        goto Retry;
                    }
                }
            }
        }
コード例 #13
0
        // assemblers
        private void Disassemble()
        {
            int offset;

            if (type == 0)
            {
                offset = index * 4 + 0x042826;
            }
            else
            {
                offset = index * 4 + 0x043E26;
            }
            //
            activeChannels = new bool[2];
            channels       = new List <SPCCommand> [2];
            for (int i = 0; i < 2; i++)
            {
                channels[i] = new List <SPCCommand>();
                int soundOffset = Bits.GetShort(Model.ROM, offset);
                offset += 2;
                if (soundOffset == 0)
                {
                    activeChannels[i] = false;
                    continue;
                }
                activeChannels[i] = true;
                if (type == 0)
                {
                    soundOffset = soundOffset - 0x3400 + 0x042C26;
                }
                else
                {
                    soundOffset = soundOffset - 0x3400 + 0x044226;
                }
                int length = 0;
                do
                {
                    soundOffset += length;
                    int opcode = rom[soundOffset];
                    length = SPCScriptEnums.CommandLengths[opcode];
                    byte[] commandData = Bits.GetBytes(rom, soundOffset, length);
                    channels[i].Add(new SPCCommand(commandData, this, i));
                }while (rom[soundOffset] != 0xD0 && rom[soundOffset] != 0xCD && rom[soundOffset] != 0xCE);
            }
        }
コード例 #14
0
        public int[] GetTilesetPixels()
        {
            int offset        = image * 4 + 0x251800;
            int bank          = (int)(((rom[offset] & 0x0F) << 16) + 0x280000);
            int graphicOffset = (int)((Bits.GetShort(rom, offset) & 0xFFF0) + bank); offset += 2;

            //
            byte[]    graphics  = Bits.GetBytes(rom, graphicOffset, 0x4000);
            int[]     palette   = Palette;
            Animation animation = Model.Animations[animationPacket];
            Mold      mold      = animation.Molds[0];

            foreach (Mold.Tile tile in mold.Tiles)
            {
                tile.DrawSubtiles(graphics, palette, mold.Gridplane);
            }
            //
            return(animation.TilesetPixels());
        }
コード例 #15
0
        // assemblers
        private void Disassemble()
        {
            switch (type)
            {
            case FontType.Menu:     // menu font
                width    = (byte)rom[index + 0x249300]; maxWidth = 8; height = 12;
                graphics = Bits.GetBytes(rom, index * 0x18 + 0x249400, 0x18);
                break;

            case FontType.Dialogue:     // dialogue font
                width    = (byte)rom[index + 0x249280]; maxWidth = 16; height = 12;
                graphics = Bits.GetBytes(rom, index * 0x30 + 0x37C000, 0x30);
                break;

            case FontType.Description:     // description font
                width    = (byte)rom[index + 0x249380]; maxWidth = 8; height = 8;
                graphics = Bits.GetBytes(rom, index * 0x10 + 0x37D800, 0x10);
                break;

            case FontType.Triangles:     // triangles
                if (index < 7)
                {
                    width = maxWidth = 8; height = 16;
                }
                else
                {
                    width = maxWidth = 16; height = 8;
                }
                graphics = Bits.GetBytes(rom, index * 0x20 + 0x3DFA00, 0x20);
                break;

            case FontType.BattleMenu:     // battle menu font
                width    = 8; maxWidth = 8; height = 8;
                graphics = Bits.GetBytes(Model.BattleMenuGraphics, index * 0x20, 0x20);
                break;

            case FontType.FlowerBonus:     // flower bonus font
                width    = 8; maxWidth = 8; height = 8;
                graphics = Bits.GetBytes(Model.BonusFontGraphics, index * 0x20, 0x20);
                break;
            }
        }
コード例 #16
0
        // assemblers
        private void Disassemble()
        {
            int offset = Bits.GetInt24(rom, index * 3 + 0x042748) - 0xC00000;

            delayTime   = rom[offset++];
            decayFactor = rom[offset++];
            echo        = rom[offset++];
            samples     = new SampleIndex[20];
            int i = 0;

            while (rom[offset] != 0xFF && i < 20)
            {
                samples[i++] = new SampleIndex(rom[offset++], rom[offset++]);
            }
            offset++;
            Length  = Bits.GetShort(rom, offset); offset += 2;
            spcData = Bits.GetBytes(rom, offset, Length);
            //
            CreateCommands();
        }
コード例 #17
0
        public void CreateCommands()
        {
            int offset = 0;

            percussives = new List <Percussives>();
            while (spcData[offset] != 0xFF)
            {
                percussives.Add(new Percussives(spcData[offset++], spcData[offset++], spcData[offset++], spcData[offset++], spcData[offset++]));
            }
            offset++;
            // now disassemble the scripts for each channel
            activeChannels = new bool[8];
            channels       = new List <SPCCommand> [8];
            for (int i = 0; i < 8; i++)
            {
                channels[i] = new List <SPCCommand>();
                int spcOffset = Bits.GetShort(spcData, offset);
                offset += 2;
                if (spcOffset == 0)
                {
                    activeChannels[i] = false;
                    continue;
                }
                activeChannels[i] = true;
                spcOffset        -= 0x2000;
                int length = 0;
                do
                {
                    spcOffset += length;
                    int opcode = spcData[spcOffset];
                    length = SPCScriptEnums.CommandLengths[opcode];
                    byte[] commandData = Bits.GetBytes(spcData, spcOffset, length);
                    channels[i].Add(new SPCCommand(commandData, this, i));
                }while (spcData[spcOffset] != 0xD0 && spcData[spcOffset] != 0xCE);
            }
        }
コード例 #18
0
 // constructor
 public Opening(Intro intro)
 {
     this.intro = intro;
     //
     openingTileset  = Bits.GetBytes(Model.OpeningData, 0, 0x480);
     openingGraphics = Bits.GetBytes(Model.OpeningData, 0x480);
     tileset         = new Tileset(openingTileset, openingGraphics, paletteSet, 16, 9, TilesetType.Opening);
     InitializeComponent();
     if (Model.ROM[0x00087D] == 0xEA &&
         Model.ROM[0x00087E] == 0xEA &&
         Model.ROM[0x00087F] == 0xEA &&
         Model.ROM[0x000880] == 0xEA)
     {
         disableGardenLoad.Checked = true;
     }
     if (Model.ROM[0x034872] == 0x4C &&
         Model.ROM[0x034873] == 0x44 &&
         Model.ROM[0x034874] == 0x00)
     {
         disableGardenNew.Checked = true;
     }
     //
     SetTilesetImage();
 }
コード例 #19
0
 // accessor functions
 public byte[] Graphics(byte[] spriteGraphics)
 {
     return(Bits.GetBytes(spriteGraphics, graphicOffset - 0x280000, 0x4000));
 }
コード例 #20
0
            // assemblers
            public void Disassemble(byte[] buffer, int offset, bool gridplane)
            {
                this.buffer    = buffer;
                this.gridplane = gridplane;
                length         = 0;
                if (offset >= buffer.Length)
                {
                    return;
                }
                //
                if (gridplane)
                {
                    format = (byte)buffer[offset++];
                    //
                    is16bit   = (format & 0x08) == 0x08;
                    yPlusOne  = (format & 0x10) == 0x10 ? (byte)1 : (byte)0;
                    yMinusOne = (format & 0x20) == 0x20 ? (byte)1 : (byte)0;
                    mirror    = (format & 0x40) == 0x40;
                    invert    = (format & 0x80) == 0x80;
                    length++;
                    //
                    format &= 3;
                    //
                    int subtiles16bit = 0;
                    if (is16bit)
                    {
                        subtiles16bit = Bits.GetShort(buffer, offset);
                        offset       += 2;
                        length       += 2;
                    }
                    //
                    byte[] temp;
                    switch (format)
                    {
                    case 0: temp = Bits.GetBytes(buffer, offset, 9); length += 9; break;

                    case 1: temp = Bits.GetBytes(buffer, offset, 12); length += 12; break;

                    case 2: temp = Bits.GetBytes(buffer, offset, 12); length += 12; break;

                    case 3: temp = Bits.GetBytes(buffer, offset, 16); length += 16; break;

                    default: goto case 0;
                    }
                    subtile_bytes = new ushort[16];
                    for (int i = 0; i < 16; i++)
                    {
                        subtile_bytes[i] = 1;
                    }
                    temp.CopyTo(subtile_bytes, 0);
                    if (is16bit)
                    {
                        for (int i = 0, b = 1; i < temp.Length; i++, b *= 2)
                        {
                            if ((subtiles16bit & b) == b)
                            {
                                subtile_bytes[i] += 0x100;
                            }
                        }
                    }
                }
                else
                {
                    format  = (byte)(buffer[offset] & 0x0F);
                    mirror  = (format & 0x04) == 0x04;
                    invert  = (format & 0x08) == 0x08;
                    format &= 3;
                    // Set active quadrants
                    bool[] quadrants = new bool[4];
                    for (int i = 0, b = 128; i < 4; i++, b /= 2)
                    {
                        quadrants[i] = (buffer[offset] & b) == b;
                    }
                    //
                    offset++; length++;
                    y = (byte)(buffer[offset] ^ 0x80); offset++; length++;
                    x = (byte)(buffer[offset] ^ 0x80); offset++; length++;
                    // Set the subtiles
                    subtile_bytes = new ushort[4];
                    for (int i = 0; i < 4; i++)
                    {
                        if (quadrants[i])
                        {
                            if (format == 1)
                            {
                                subtile_bytes[i] = (ushort)(Bits.GetShort(buffer, offset) & 0x1FF);
                                offset++; length++;
                            }
                            else
                            {
                                subtile_bytes[i] = (ushort)buffer[offset];
                            }
                            offset++; length++;
                        }
                    }
                }
            }
コード例 #21
0
        // accessor functions
        /// <summary>
        /// Creates a pixel array of the sprite.
        /// </summary>
        /// <param name="byMold">Create the pixels by mold index.</param>
        /// <param name="byFCoord">Create the pixels by facing index.</param>
        /// <param name="moldIndex">The index of the mold (ignored if byMold == false).</param>
        /// <param name="fCoord">The index of the facing (ignored if byFacing == false)</param>
        /// <param name="palette">If want to use a particular palette.</param>
        /// <param name="mirror">Mirror the sprite pixels.</param>
        /// <param name="crop">Crop the sprite pixels to their edges.</param>
        /// <returns></returns>
        public int[] GetPixels(bool byMold, bool byFCoord, int moldIndex, int fCoord, int[] palette, bool mirror, bool crop, ref Size size)
        {
            // set palette to use
            if (palette == null)
            {
                palette = Palette;
            }
            // get offsets
            int animationNum    = Bits.GetShort(rom, this.index * 4 + 0x250002);
            int animationOffset = Bits.GetInt24(rom, 0x252000 + (animationNum * 3)) - 0xC00000;
            int animationLength = Bits.GetShort(rom, animationOffset);

            // get mold data
            byte[] sm     = Bits.GetBytes(rom, animationOffset, animationLength);
            int    offset = Bits.GetShort(sm, 2);

            if (byFCoord)
            {
                switch (fCoord)
                {
                case 0: mirror = !mirror; if (sm[6] < 13)
                    {
                        break;
                    }
                    offset += 24; break;

                case 1: mirror = !mirror; break;

                case 2: if (sm[6] < 11)
                    {
                        break;
                    }
                    offset += 20; break;

                case 4: if (sm[6] < 13)
                    {
                        break;
                    }
                    offset += 24; break;

                case 5: if (sm[6] < 2)
                    {
                        break;
                    }
                    offset += 2; break;

                case 6: if (sm[6] < 12)
                    {
                        break;
                    }
                    offset += 22; break;

                case 7: mirror = !mirror; if (sm[6] < 2)
                    {
                        break;
                    }
                    offset += 2; break;

                default: break;
                }
            }
            offset = Bits.GetShort(sm, offset);
            if (!byMold)
            {
                moldIndex = offset != 0xFFFF && sm[offset + 1] != 0 && sm[offset + 1] < sm[7] ? (int)sm[offset + 1] : 0;
            }
            offset  = Bits.GetShort(sm, 4);
            offset += moldIndex * 2;
            // create mold from data
            Mold mold = new Mold();

            mold.Disassemble(sm, offset, new List <Mold.Tile>(), animationNum, animationOffset);
            // generate subtiles in mold, then grab pixel array
            foreach (Mold.Tile t in mold.Tiles)
            {
                t.DrawSubtiles(Graphics, palette, mold.Gridplane);
            }
            int[] pixels = mold.MoldPixels();
            // crop image
            int lowY = 0, highY = 0, lowX = 0, highX = 0;

            if (crop)
            {
                bool stop = false;
                for (int y = 0; y < 256 && !stop; y++)
                {
                    for (int x = 0; x < 256; x++)
                    {
                        if (pixels[y * 256 + x] != 0)
                        {
                            lowY = y; lowX = x; stop = true; break;
                        }
                    }
                }
                stop = false;
                for (int y = 255; y >= 0 && !stop; y--)
                {
                    for (int x = 255; x >= 0; x--)
                    {
                        if (pixels[y * 256 + x] != 0)
                        {
                            highY = y; highX = x; stop = true; break;
                        }
                    }
                }
                stop = false;
                for (int y = 0; y < 256; y++)
                {
                    for (int x = 0; x < 256; x++)
                    {
                        if (pixels[y * 256 + x] != 0 && x < lowX)
                        {
                            lowX = x; break;
                        }
                    }
                }
                stop = false;
                for (int y = 255; y >= 0; y--)
                {
                    for (int x = 255; x >= 0; x--)
                    {
                        if (pixels[y * 256 + x] != 0 && x > highX)
                        {
                            highX = x; break;
                        }
                    }
                }
                stop = false;
                highY++; highX++;
            }
            else
            {
                highY = 256;
                highX = 256;
            }
            int imageHeight = highY - lowY;
            int imageWidth  = highX - lowX;

            if (crop)
            {
                int[] tempPixels = new int[imageWidth * imageHeight];
                for (int y = 0; y < imageHeight; y++)
                {
                    for (int x = 0; x < imageWidth; x++)
                    {
                        tempPixels[y * imageWidth + x] = pixels[(y + lowY) * 256 + x + lowX];
                    }
                }
                pixels = tempPixels;
            }
            int temp;

            if (mirror)
            {
                for (int y = 0; y < imageHeight; y++)
                {
                    for (int a = 0, c = imageWidth - 1; a < imageWidth / 2; a++, c--)
                    {
                        temp = pixels[(y * imageWidth) + a];
                        pixels[(y * imageWidth) + a] = pixels[(y * imageWidth) + c];
                        pixels[(y * imageWidth) + c] = temp;
                    }
                }
            }
            size = new Size(imageWidth, imageHeight);
            return(pixels);
        }