public void Assemble()
        {
            switch (type)
            {
            case FontType.Menu:     // menu font
                rom[index + 0x249300] = width;
                Bits.SetBytes(rom, index * 0x18 + 0x249400, graphics);
                break;

            case FontType.Dialogue:     // dialogue font
                rom[index + 0x249280] = width;
                Bits.SetBytes(rom, index * 0x30 + 0x37C000, graphics);
                break;

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

            case FontType.Triangles:     // triangles
                Bits.SetBytes(rom, index * 0x20 + 0x3DFA00, graphics);
                break;

            case FontType.BattleMenu:     // battle menu font
                Bits.SetBytes(rom, index * 0x20, graphics);
                break;
            }
        }
Beispiel #2
0
        private void Delete()
        {
            if (overlay.Select.Empty)
            {
                return;
            }
            if (tileset.Tileset == null || overlay.Select.Size == new Size(0, 0))
            {
                return;
            }
            Point location = overlay.Select.Location;
            Point terminal = overlay.Select.Terminal;

            byte[] changes = new byte[(overlay.Select.Width / 16) * (overlay.Select.Height / 16)];
            Bits.SetBytes(changes, 0xFF);
            commandStack.Push(new TilemapCommand(
                                  mold.Mold, width / 16, height / 16, changes,
                                  overlay.Select.X / 16, overlay.Select.Y / 16, overlay.Select.Width / 16, overlay.Select.Height / 16));
            commandCount++;
            SetTilemapImage();
            if (sequences != null)
            {
                sequences.SetSequenceFrameImages();
                sequences.RealignFrames();
            }
            animation.Assemble();
        }
Beispiel #3
0
 public void Assemble(ref int offset)
 {
     if (index == 0)
     {
         return;
     }
     //int offset = Bits.Get24Bit(data, index * 3 + 0x042748) - 0xC00000;
     Bits.SetInt24(rom, index * 3 + 0x42748, offset + 0xC00000);
     rom[offset++] = DelayTime;
     rom[offset++] = DecayFactor;
     rom[offset++] = Echo;
     foreach (SampleIndex sample in samples)
     {
         if (sample == null || !sample.Active)
         {
             continue;
         }
         rom[offset++] = (byte)sample.Sample;
         rom[offset++] = (byte)sample.Volume;
     }
     rom[offset++] = 0xFF;
     Bits.SetShort(rom, offset, Length); offset += 2;
     //
     AssembleSPCData();
     Bits.SetBytes(rom, offset, spcData);
     offset += spcData.Length;
 }
Beispiel #4
0
 public void Assemble()
 {
     fontPalettesDialogue.Assemble();
     fontPalettesMenu.Assemble();
     Bits.SetBit(Model.ROM, 0x3E2D6C, 7, true);
     Bits.SetBit(Model.ROM, 0x3E2D74, 7, true);
     foreach (FontCharacter f in fontMenu)
     {
         f.Assemble();
     }
     foreach (FontCharacter f in fontDialogue)
     {
         f.Assemble();
     }
     foreach (FontCharacter f in fontDescription)
     {
         f.Assemble();
     }
     foreach (FontCharacter f in fontTriangle)
     {
         f.Assemble();
     }
     Bits.SetBytes(rom, 0x3DF000, Model.DialogueGraphics, 0, 0x700);
     Bits.SetBytes(rom, 0x015943, Model.BattleDialogueTileset_bytes, 0, 0x100);
     //
     Bits.SetBytes(rom, 0x03F800, Model.NumeralGraphics, 0, 0x400);
     Model.NumeralPaletteSet.Assemble();
     Buffer.BlockCopy(Model.BattleMenuGraphics, 0, rom, 0x1F200, 0x600);
     Buffer.BlockCopy(Model.BattleMenuGraphics, 0x600, rom, 0x1ED00, 0x140);
     Model.BattleMenuPalette.Assemble();
 }
Beispiel #5
0
        // tooltips
        public void Assemble()
        {
            Model.ROM[0x037DCF] = (byte)this.music.SelectedIndex;
            //
            Model.Compress(Model.WorldMapLogos, 0x3E004C, 0x2000, 0xE1C, "World map logos, banners");
            //
            foreach (WorldMap wm in worldMaps)
            {
                wm.Assemble();
            }
            // Graphics
            Model.WorldMapLogoPalette.Assemble(Model.MenuPalettes, 0xE0);
            int offset  = Bits.GetShort(Model.ROM, 0x3E000C) + 0x3E0000;
            int maxComp = Bits.GetShort(Model.ROM, 0x3E000E) - Bits.GetShort(Model.ROM, 0x3E000C);

            Model.Compress(Model.MenuPalettes, offset, 0x200, maxComp, "World map logo palettes");
            Model.Compress(Model.WorldMapGraphics, 0x3E2E81, 0x8000, 0x56F6, "Graphics");
            //   Model.Compress(Model.WorldMapSprites, 0x3E90A7, 0x400, 0x1F8, "Sprite Graphics");
            // Tilesets
            byte[] compress  = new byte[0x800];
            int    totalSize = 0;
            int    pOffset   = 0x3E0014;
            int    dOffset   = 0x3E929F;
            int    size      = 0;

            for (int i = 0; i < Model.WorldMapTilesets.Length; i++)
            {
                Bits.SetShort(Model.ROM, pOffset, (ushort)dOffset);
                size       = Comp.Compress(Model.WorldMapTilesets[i], compress);
                totalSize += size + 1;
                if (totalSize > 0x4D8)
                {
                    MessageBox.Show(
                        "Recompressed tilesets exceed allotted ROM space by " + (totalSize - 0x4D6).ToString() + " bytes.\nSaving has been discontinued for tilesets " + i.ToString() + " and higher.\nChange or delete some tiles to reduce the size.",
                        "LAZY SHELL");
                    break;
                }
                else
                {
                    Model.ROM[dOffset] = 1; dOffset++;
                    Bits.SetBytes(Model.ROM, dOffset, compress, 0, size - 1);
                    dOffset += size;
                    pOffset += 2;
                }
            }
            Bits.SetShort(Model.ROM, pOffset, (ushort)dOffset);
            Model.Compress(Model.WorldMapLogoTileset, dOffset, 0x800, 0xC1, "World map logo tileset");
            // Palettes
            palettes.Assemble(Model.WorldMapPalettes, 0);
            Model.Compress(Model.WorldMapPalettes, 0x3E988C, 0x100, 0xD4, "Palette set");
            foreach (Location mp in locations)
            {
                mp.Assemble();
            }
            AssembleLocationTexts();
            this.Modified = false;
        }
Beispiel #6
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();
        }
Beispiel #7
0
        public void AssembleSPCData()
        {
            int offset = 0;

            spcData = new byte[percussives.Count * 5 + 1];
            foreach (Percussives percussive in percussives)
            {
                spcData[offset++] = (byte)percussive.PitchIndex;
                spcData[offset++] = percussive.Sample;
                spcData[offset++] = percussive.Pitch;
                spcData[offset++] = percussive.Volume;
                spcData[offset++] = percussive.Balance;
            }
            spcData[offset++] = 0xFF;
            int spcOffset = offset + 16;
            int length    = spcOffset;

            for (int i = 0; i < channels.Length; i++)
            {
                if (activeChannels[i] && channels[i] != null)
                {
                    foreach (SPCCommand ssc in channels[i])
                    {
                        length += ssc.Length;
                    }
                }
            }
            this.Length = length;
            Array.Resize <byte>(ref spcData, length);
            for (int i = 0; i < 8; i++)
            {
                if (activeChannels[i] && channels[i] != null)
                {
                    Bits.SetShort(spcData, offset, spcOffset + 0x2000);
                }
                else
                {
                    Bits.SetShort(spcData, offset, 0);
                }
                offset += 2;
                if (!activeChannels[i] || channels[i] == null)
                {
                    continue;
                }
                foreach (SPCCommand ssc in channels[i])
                {
                    Bits.SetBytes(spcData, spcOffset, ssc.CommandData);
                    spcOffset += ssc.Length;
                }
            }
        }
Beispiel #8
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();
        }
Beispiel #9
0
        private void Assemble()
        {
            int offset = 0;

            byte[]    temp         = new byte[0x700];
            MenuTexts lastMenuText = null;

            foreach (MenuTexts menuText in Model.MenuTexts)
            {
                if (lastMenuText != null && menuText.Length != 0 && Bits.Compare(menuText.Text, lastMenuText.Text))
                {
                    Bits.SetShort(Model.ROM, menuText.Index * 2 + 0x3EEF00, lastMenuText.Offset);
                    menuText.Offset = lastMenuText.Offset;
                    continue;
                }
                if (offset + menuText.Length + 1 >= 0x700)
                {
                    MessageBox.Show("Menu texts exceed allotted ROM space. Stopped saving at index " + menuText.Index + ".");
                    break;
                }
                menuText.Offset = offset;
                lastMenuText    = menuText;
                //
                Bits.SetShort(Model.ROM, menuText.Index * 2 + 0x3EEF00, offset);
                Bits.SetChars(temp, offset, menuText.Text);
                offset        += menuText.Length;
                temp[offset++] = 0;
                switch (menuText.Index)
                {
                case 14: Bits.SetByteBits(Model.ROM, 0x03328E, (byte)(menuText.X * 2), 0x3F); break;

                case 15: Bits.SetByteBits(Model.ROM, 0x03327E, (byte)(menuText.X * 2), 0x3F); break;

                case 16: Bits.SetByteBits(Model.ROM, 0x033282, (byte)(menuText.X * 2), 0x3F); break;

                case 17: Bits.SetByteBits(Model.ROM, 0x033286, (byte)(menuText.X * 2), 0x3F); break;

                case 18: Bits.SetByteBits(Model.ROM, 0x03328A, (byte)(menuText.X * 2), 0x3F); break;

                case 19: Bits.SetByteBits(Model.ROM, 0x03327A, (byte)(menuText.X * 2), 0x3F); break;
                }
            }
            Bits.SetBytes(Model.ROM, 0x3EF000, temp);
            //Bits.SetShort(Model.Data, 0x3EF600, 0x344F);
            menus.Assemble();
            menus.Modified = false;
            this.Modified  = false;
        }
 public void Assemble(ref int offset)
 {
     if (sample == null)
     {
         Bits.SetInt24(rom, index * 3 + 0x042333, 0);
         return;
     }
     Bits.SetInt24(rom, index * 3 + 0x042333, offset + 0xC00000);
     Bits.SetShort(rom, offset, sample.Length); offset += 2;
     Bits.SetBytes(rom, offset, sample);
     offset += sample.Length;
     //
     Bits.SetShort(rom, index * 2 + 0x04248F, loopStart);
     Bits.SetShort(rom, index * 2 + 0x042577, relGain);
     Bits.SetShort(rom, index * 2 + 0x04265F, relFreq);
 }
        private void Assemble()
        {
            effect.Assemble();
            animation.Assemble();
            int i       = 0;
            int pointer = 0x252C00;
            int offset  = 0x330000;

            for (; i < 39 && offset < 0x33FFFF; i++, pointer += 3)
            {
                if (animations[i].BUFFER.Length + offset > 0x33FFFF)
                {
                    break;
                }
                Bits.SetShort(Model.ROM, pointer, (ushort)offset);
                Bits.SetByte(Model.ROM, pointer + 2, (byte)((offset >> 16) + 0xC0));
                Bits.SetBytes(Model.ROM, offset, animations[i].BUFFER);
                offset += animations[i].BUFFER.Length;
            }
            if (i < 39)
            {
                MessageBox.Show("The available space for animation data in bank 0x330000 has exceeded the alotted space.\nAnimation #'s " + i.ToString() + " through 38 will not saved. Please make sure the available animation bytes is not negative.", "LAZY SHELL");
            }
            offset = 0x340000;
            for (; i < 64 && offset < 0x34CFFF; i++, pointer += 3)
            {
                if (animations[i].BUFFER.Length + offset > 0x34CFFF)
                {
                    break;
                }
                Bits.SetShort(Model.ROM, pointer, (ushort)offset);
                Bits.SetByte(Model.ROM, pointer + 2, (byte)((offset >> 16) + 0xC0));
                Bits.SetBytes(Model.ROM, offset, animations[i].BUFFER);
                offset += animations[i].BUFFER.Length;
            }
            if (i < 64)
            {
                MessageBox.Show("The available space for animation data in bank 0x340000 has exceeded the alotted space.\nAnimation #'s " + i.ToString() + " through 63 will not saved. Please make sure the available animation bytes is not negative.", "LAZY SHELL");
            }
            molds.Modified     = false;
            sequences.Modified = false;
            this.Modified      = false;
        }
Beispiel #12
0
        public byte[] Recompress(byte[] src, int width, int height)
        {
            byte[] dst       = new byte[256]; // 256 max size for compressed
            int    srcOffset = 0;
            int    dstOffset = 0;

            while (srcOffset < width * height)
            {
                dst[dstOffset] = src[srcOffset];
                // make a filler tile only if next TWO tiles are the same
                if (srcOffset < 0xFE &&
                    srcOffset + 1 < src.Length &&
                    srcOffset + 2 < src.Length &&
                    src[srcOffset] == src[srcOffset + 1] &&
                    src[srcOffset] == src[srcOffset + 2])
                {
                    dst[dstOffset] = 0xFE;
                    dstOffset++;
                    dst[dstOffset] = src[srcOffset];    // the tile to fill with
                    byte counter = 1;
                    while (srcOffset < 0xFF &&
                           srcOffset < src.Length &&
                           srcOffset + 1 < src.Length &&
                           src[srcOffset] == src[srcOffset + 1])
                    {
                        counter++;
                        srcOffset++;
                    }
                    dstOffset++;
                    dst[dstOffset] = counter;   // the amount to fill
                }
                srcOffset++;
                dstOffset++;
            }
            byte[] temp = new byte[dstOffset];
            Bits.SetBytes(temp, 0, dst);
            return(temp);
        }
        public void Assemble()
        {
            // set sm to new byte with largest possible size
            byte[] temp = new byte[0x10000];
            // now start writing dynamic data
            temp[6] = (byte)sequences.Count;
            temp[7] = (byte)molds.Count;
            temp[8] = (byte)(vramAllocation >> 8);
            // Sequences
            int offset = 12; // where sequences begin

            Bits.SetShort(temp, 2, (ushort)0x0C);
            int fOffset = sequences.Count * 2 + 2;  // offset of first frame packet

            foreach (Sequence s in sequences)
            {
                if (s.Frames.Count != 0 && s.Active)
                {
                    Bits.SetShort(temp, offset, (ushort)(fOffset + offset));
                    fOffset += s.Frames.Count * 2 - 1;
                }
                else if (s.Active)
                {
                    Bits.SetShort(temp, offset, (ushort)(fOffset + offset));
                    fOffset -= 1;
                }
                else
                {
                    Bits.SetShort(temp, offset, 0xFFFF);
                    fOffset -= 2;
                }
                offset += 2;
            }
            Bits.SetShort(temp, offset, 0); offset += 2;
            foreach (Sequence s in sequences)
            {
                foreach (Sequence.Frame f in s.Frames)
                {
                    Bits.SetByte(temp, offset++, f.Duration);
                    Bits.SetByte(temp, offset++, f.Mold);
                }
                if (s.Active)
                {
                    Bits.SetByte(temp, offset++, 0);
                }
            }
            // Molds
            Bits.SetShort(temp, 4, (ushort)offset);
            int mOffset = molds.Count * 2 + 2;    // offset of first mold tilemap

            foreach (Mold m in molds)
            {
                if (index == 162 && mOffset == 0x132)
                {
                    index = 162;
                }
                if (m.Tiles.Count != 0)
                {
                    if (m.Gridplane)
                    {
                        Bits.SetShort(temp, offset, (ushort)(mOffset + offset + 0x8000));
                        Mold.Tile tile = m.Tiles[0];
                        if (tile.Subtile_bytes != null)
                        {
                            mOffset += tile.Length - 2;
                        }
                    }
                    else
                    {
                        Bits.SetShort(temp, offset, (ushort)(mOffset + offset));
                        mOffset += m.Recompress(mOffset + offset, molds).Length - 1;
                    }
                }
                else
                {
                    Bits.SetShort(temp, offset, (ushort)0xFFFF);
                    mOffset -= 2;
                }
                offset += 2;
            }
            Bits.SetShort(temp, offset += 2, 0);
            foreach (Mold m in molds)
            {
                if (m.Tiles.Count == 0)
                {
                    continue;
                }
                if (m.Gridplane)
                {
                    Mold.Tile tile = m.Tiles[0];
                    if (tile.Subtile_bytes == null)
                    {
                        continue;
                    }
                    temp[offset] = (byte)(tile.Format & 3);
                    Bits.SetBit(temp, offset, 3, tile.Is16bit);
                    Bits.SetBit(temp, offset, 4, tile.YPlusOne == 1);
                    Bits.SetBit(temp, offset, 5, tile.YMinusOne == 1);
                    Bits.SetBit(temp, offset, 6, tile.Mirror);
                    Bits.SetBit(temp, offset++, 7, tile.Invert);
                    int size = tile.Is16bit ? tile.Length - 3 : tile.Length - 1;
                    // set bits for tiles that are 16bit
                    if (tile.Is16bit)
                    {
                        for (int i = 0; i < size; i++)
                        {
                            Bits.SetBit(temp, offset, i, tile.Subtile_bytes[i] >= 0x100);
                        }
                        offset += 2;
                    }
                    for (int i = 0; i < size; i++)
                    {
                        temp[offset++] = (byte)tile.Subtile_bytes[i];
                    }
                }
                else
                {
                    byte[] mold = m.Recompress(offset, molds);
                    mold.CopyTo(temp, offset);
                    offset        += mold.Length;
                    temp[offset++] = 0;
                }
            }
            // finally, set the animation length
            Bits.SetShort(temp, 0, (ushort)offset);
            buffer = new byte[offset];
            Bits.SetBytes(buffer, 0, temp);
        }
Beispiel #14
0
        public void Assemble()
        {
            ProgressBar progressBar = new ProgressBar("ASSEMBLING ANIMATIONS...", animations.Length);

            progressBar.Show();
            int i = 0;

            foreach (Animation sm in animations)
            {
                sm.Assemble();
                progressBar.PerformStep("ASSEMBLING ANIMATION #" + i);
                i++;
            }
            progressBar.Close();
            i = 0;
            int pointer = 0x252000;
            int offset  = 0x259000;

            for (; i < 42 && offset < 0x25FFFF; i++, pointer += 3)
            {
                if (animations[i].BUFFER.Length + offset > 0x25FFFF)
                {
                    break;
                }
                Bits.SetShort(rom, pointer, (ushort)offset);
                rom[pointer + 2] = (byte)((offset >> 16) + 0xC0);
                Bits.SetBytes(rom, offset, animations[i].BUFFER);
                offset += animations[i].BUFFER.Length;
            }
            if (i < 42)
            {
                MessageBox.Show("The available space for animation data in bank 0x250000 has exceeded the alotted space.\nAnimation #'s " + i.ToString() + " through 41 were not saved. Please make sure the available animation bytes is not negative.", "LAZY SHELL");
            }
            offset = 0x260000;
            for (; i < 107 && offset < 0x26FFFF; i++, pointer += 3)
            {
                if (animations[i].BUFFER.Length + offset > 0x26FFFF)
                {
                    break;
                }
                Bits.SetShort(rom, pointer, (ushort)offset);
                rom[pointer + 2] = (byte)((offset >> 16) + 0xC0);
                Bits.SetBytes(rom, offset, animations[i].BUFFER);
                offset += animations[i].BUFFER.Length;
            }
            if (i < 107)
            {
                MessageBox.Show("The available space for animation data in bank 0x260000 has exceeded the alotted space.\nAnimation #'s " + i.ToString() + " through 107 were not saved. Please make sure the available animation bytes is not negative.", "LAZY SHELL");
            }
            offset = 0x270000;
            for (; i < 249 && offset < 0x27FFFF; i++, pointer += 3)
            {
                if (animations[i].BUFFER.Length + offset > 0x27FFFF)
                {
                    break;
                }
                Bits.SetShort(rom, pointer, (ushort)offset);
                rom[pointer + 2] = (byte)((offset >> 16) + 0xC0);
                Bits.SetBytes(rom, offset, animations[i].BUFFER);
                offset += animations[i].BUFFER.Length;
            }
            if (i < 249)
            {
                MessageBox.Show("The available space for animation data in bank 0x270000 has exceeded the alotted space.\nAnimation #'s " + i.ToString() + " through 249 will not saved. Please make sure the available animation bytes is not negative.", "LAZY SHELL");
            }
            offset = 0x360000;
            for (; i < 444 && offset < 0x36FFFF; i++, pointer += 3)
            {
                if (animations[i].BUFFER.Length + offset > 0x36FFFF)
                {
                    break;
                }
                Bits.SetShort(rom, pointer, (ushort)offset);
                rom[pointer + 2] = (byte)((offset >> 16) + 0xC0);
                Bits.SetBytes(rom, offset, animations[i].BUFFER);
                offset += animations[i].BUFFER.Length;
            }
            if (i < 444)
            {
                MessageBox.Show("The available space for animation data in bank 0x360000 has exceeded the alotted space.\nAnimation #'s " + i.ToString() + " through 444 will not saved. Please make sure the available animation bytes is not negative.", "LAZY SHELL");
            }
            foreach (Sprite s in sprites)
            {
                s.Assemble();
            }
            foreach (ImagePacket gp in images)
            {
                gp.Assemble();
            }
            foreach (PaletteSet p in palettes)
            {
                p.Assemble(0);
            }
            Buffer.BlockCopy(Model.SpriteGraphics, 0, rom, 0x280000, 0xB4000);
            Model.HexEditor.SetOffset(animation.AnimationOffset);
            Model.HexEditor.Compare();
            molds.Modified     = false;
            sequences.Modified = false;
            this.Modified      = false;
        }
Beispiel #15
0
        //
        public void Assemble()
        {
            Model.ROM[0x0393EF] = (byte)this.music.SelectedIndex;
            MinecartData.Assemble();
            tilemap.Assemble();
            Model.MinecartM7PaletteSet.Assemble();
            Model.MinecartObjectPaletteSet.Assemble();
            Model.MinecartSSPaletteSet.Assemble();
            //
            int offset = 0x1E;

            byte[] dst = new byte[0x8000];
            Bits.SetShort(dst, 0x00, offset);
            if (!Model.Compress(Model.MinecartM7Graphics, dst, ref offset, 0x8000 - 0x1E, "stage 1,3 graphics"))
            {
                return;
            }
            Bits.SetShort(dst, 0x02, offset);
            if (!Model.Compress(Model.MinecartM7TilesetSubtiles, dst, ref offset, 0x8000 - 0x1E, "stage 1,3 subtiles"))
            {
                return;
            }
            Bits.SetShort(dst, 0x04, offset);
            if (!Model.Compress(Model.MinecartM7Palettes, dst, ref offset, 0x8000 - 0x1E, "stage 1,3 palettes"))
            {
                return;
            }
            Bits.SetShort(dst, 0x06, offset);
            if (!Model.Compress(Model.MinecartM7TilesetPalettes, dst, ref offset, 0x8000 - 0x1E, "stage 1,3 subtile palettes"))
            {
                return;
            }
            Bits.SetShort(dst, 0x08, offset);
            if (!Model.Compress(Model.MinecartM7TilemapA, dst, ref offset, 0x8000 - 0x1E, "stage 1 tilemap"))
            {
                return;
            }
            Bits.SetShort(dst, 0x0A, offset);
            if (!Model.Compress(Model.MinecartM7TilemapB, dst, ref offset, 0x8000 - 0x1E, "stage 3 tilemap"))
            {
                return;
            }
            Bits.SetShort(dst, 0x0C, offset);
            if (!Model.Compress(Model.MinecartM7TilesetBG, dst, ref offset, 0x8000 - 0x1E, "stage 1,3 background tileset"))
            {
                return;
            }
            Bits.SetShort(dst, 0x0E, offset);
            if (!Model.Compress(Model.MinecartObjectGraphics, dst, ref offset, 0x8000 - 0x1E, "object graphics"))
            {
                return;
            }
            Bits.SetShort(dst, 0x10, offset);
            if (!Model.Compress(Model.MinecartObjectPalettes, dst, ref offset, 0x8000 - 0x1E, "object palettes"))
            {
                return;
            }
            Bits.SetShort(dst, 0x12, offset);
            if (!Model.Compress(Model.MinecartSSTilemap, dst, ref offset, 0x8000 - 0x1E, "stage 2,4 tilemap"))
            {
                return;
            }
            Bits.SetShort(dst, 0x14, offset);
            if (!Model.Compress(Model.MinecartSSGraphics, dst, ref offset, 0x8000 - 0x1E, "stage 2,4 graphics"))
            {
                return;
            }
            Bits.SetShort(dst, 0x16, offset);
            if (!Model.Compress(Model.MinecartSSTileset, dst, ref offset, 0x8000 - 0x1E, "stage 2,4 tileset"))
            {
                return;
            }
            Bits.SetShort(dst, 0x18, offset);
            if (!Model.Compress(Model.MinecartSSPalettes, dst, ref offset, 0x8000 - 0x1E, "stage 2,4 palettes"))
            {
                return;
            }
            Bits.SetShort(dst, 0x1A, offset);
            if (!Model.Compress(Model.MinecartSSBGTileset, dst, ref offset, 0x8000 - 0x1E, "stage 4 BG tileset"))
            {
                return;
            }
            Bits.SetShort(dst, 0x1C, offset);
            if (!Model.Compress(Model.MinecartObjects, dst, ref offset, 0x8000 - 0x1E, "object & screen data"))
            {
                return;
            }
            //
            Bits.SetBytes(Model.ROM, 0x388000, dst);
            Bits.SetShort(Model.ROM, 0x039670, (ushort)startX.Value);
            Bits.SetShort(Model.ROM, 0x039679, (ushort)startY.Value);
        }
Beispiel #16
0
        public byte[] Recompress(int baseOffset, List <Mold> molds)
        {
            byte[] mold        = new byte[0x10000];
            int    offset      = 0;
            int    thisCounter = 0; // must be outside loop to avoid resetting

            for (int i = 0; i < tiles.Count; i++)
            {
                Tile tile = (Tile)tiles[i];
                #region first compare to find copies
                int  counter    = 0;
                int  copySize   = 0;
                Tile tileA      = new Tile();
                Tile thisTileA  = new Tile();
                Tile tileB      = new Tile();
                Tile thisTileB  = new Tile();
                int  copyOffset = 0;
                int  copyDiffX  = 0;
                int  copyDiffY  = 0;
                // look through each mold for copies
                foreach (Mold m in molds)
                {
                    // cancel if we've reached the same mold
                    if (m == this)
                    {
                        break;
                    }
                    // skip if gridplane; not copyable
                    if (m.Gridplane)
                    {
                        continue;
                    }
                    counter = 0;
                    // look through all mold's tiles for copies
                    while (counter + 1 < m.Tiles.Count && thisCounter + 1 < tiles.Count)
                    {
                        copySize   = 0;
                        tileA      = (Tile)m.Tiles[counter];
                        thisTileA  = (Tile)tiles[thisCounter];
                        tileB      = (Tile)m.Tiles[counter + 1];
                        thisTileB  = (Tile)tiles[thisCounter + 1];
                        copyOffset = tileA.TileOffset;
                        // tile's offset wasn't set, thus not a viable tile to copy from
                        if (copyOffset == 0)
                        {
                            counter++; continue;
                        }
                        copyDiffX = thisTileA.X - tileA.X;
                        copyDiffY = thisTileA.Y - tileA.Y;
                        // first check to see if going to be making a copy of more than one, regardless of active quadrants
                        if (tileB.TileOffset != 0 &&
                            thisTileA.Subtile_bytes[0] == tileA.Subtile_bytes[0] &&
                            thisTileA.Subtile_bytes[1] == tileA.Subtile_bytes[1] &&
                            thisTileA.Subtile_bytes[2] == tileA.Subtile_bytes[2] &&
                            thisTileA.Subtile_bytes[3] == tileA.Subtile_bytes[3] &&
                            thisTileA.Mirror == tileA.Mirror &&
                            thisTileA.Invert == tileA.Invert &&
                            thisTileB.Subtile_bytes[0] == tileB.Subtile_bytes[0] &&
                            thisTileB.Subtile_bytes[1] == tileB.Subtile_bytes[1] &&
                            thisTileB.Subtile_bytes[2] == tileB.Subtile_bytes[2] &&
                            thisTileB.Subtile_bytes[3] == tileB.Subtile_bytes[3] &&
                            thisTileB.Mirror == tileB.Mirror &&
                            thisTileB.Invert == tileB.Invert &&
                            copyDiffX == thisTileB.X - tileB.X &&
                            copyDiffY == thisTileB.Y - tileB.Y)
                        {
                            // v3.8: set TileOffset to 0 to prevent later molds from using as a copy
                            thisTileA.TileOffset = 0;
                            thisTileB.TileOffset = 0;
                            // we will be making a copy of at least 2
                            copySize = 2;
                            // now keep moving to find more copies
                            counter     += 2;
                            thisCounter += 2;
                            // cancel if at end of first mold's tiles
                            if (counter >= m.Tiles.Count ||
                                thisCounter >= tiles.Count)
                            {
                                break;
                            }
                            Tile tileC     = (Tile)m.Tiles[counter];
                            Tile thisTileC = (Tile)tiles[thisCounter];
                            while (copySize < 15 &&
                                   thisTileC.Subtile_bytes[0] == tileC.Subtile_bytes[0] &&
                                   thisTileC.Subtile_bytes[1] == tileC.Subtile_bytes[1] &&
                                   thisTileC.Subtile_bytes[2] == tileC.Subtile_bytes[2] &&
                                   thisTileC.Subtile_bytes[3] == tileC.Subtile_bytes[3] &&
                                   thisTileC.Mirror == tileC.Mirror &&
                                   copyDiffX == thisTileC.X - tileC.X &&
                                   copyDiffY == thisTileC.Y - tileC.Y)
                            {
                                // stop adding copies if the tile doesn't have an offset
                                // it is probably a copy itself, so we shouldn't add it
                                if (tileC.TileOffset == 0)
                                {
                                    break;
                                }
                                // v3.8: set TileOffset to 0 to prevent later molds from using as a copy
                                thisTileC.TileOffset = 0;
                                // adding another copy
                                copySize++;
                                // now set to check next one
                                counter++;
                                thisCounter++;
                                // cancel if at end of first mold's tiles
                                if (counter >= m.Tiles.Count ||
                                    thisCounter >= tiles.Count)
                                {
                                    break;
                                }
                                tileC     = (Tile)m.Tiles[counter];
                                thisTileC = (Tile)tiles[thisCounter];
                            }
                            // must break out of this loop too
                            if (tileC.TileOffset == 0)
                            {
                                break;
                            }
                        }
                        // otherwise, check to see if going to be making a copy of at least one,
                        // must have at least 3 quadrants active
                        else if (CompareTiles(thisTileA, tileA, true))
                        {
                            // since a copy, must set to 0 to prevent later molds from using as a copy
                            thisTileA.TileOffset = 0;
                            // we will be making a copy
                            copyOffset = tileA.TileOffset;
                            copyDiffX  = thisTileA.X - tileA.X;
                            copyDiffY  = thisTileA.Y - tileA.Y;
                            copySize++;
                            // move for next tile
                            thisCounter++;
                        }
                        // last tile wasn't a copy, so move to check next one
                        else
                        {
                            counter++;
                        }
                        // we've found a copy, so don't try checking for more
                        if (copySize > 0)
                        {
                            break;
                        }
                    }
                    // we've found a copy, so don't try checking in any more molds
                    if (copySize > 0)
                    {
                        break;
                    }
                }
                #endregion
                if (copySize > 0)
                {
                    mold[offset]     = 2;
                    mold[offset]    |= (byte)(copySize << 4);
                    mold[offset + 1] = (byte)copyDiffY;
                    mold[offset + 2] = (byte)copyDiffX;
                    Bits.SetShort(mold, offset + 3, (ushort)copyOffset);
                    offset += 5;
                    i      += copySize - 1;
                    thisCounter--;  // must move back one to synchronize counter (it ++'s later)
                }
                // set normal tile
                else
                {
                    tile.TileOffset = baseOffset + offset;
                    tile.Is16bit    = false;
                    for (int s = 0, b = 128; s < 4; s++, b /= 2)
                    {
                        if (tile.Subtile_bytes[s] != 0)
                        {
                            mold[offset] |= (byte)b;
                        }
                        if (tile.Subtile_bytes[s] >= 0x100)
                        {
                            mold[offset] |= 1;
                            tile.Is16bit  = true;
                        }
                    }
                    Bits.SetBit(mold, offset, 2, tile.Mirror);
                    Bits.SetBit(mold, offset, 3, tile.Invert);
                    offset++;
                    mold[offset] = (byte)(tile.Y ^ 0x80); offset++;
                    mold[offset] = (byte)(tile.X ^ 0x80); offset++;
                    for (int s = 0; s < 4; s++)
                    {
                        if (tile.Subtile_bytes[s] != 0)
                        {
                            if (!tile.Is16bit)
                            {
                                mold[offset++] = (byte)tile.Subtile_bytes[s];
                            }
                            else
                            {
                                Bits.SetShort(mold, offset, tile.Subtile_bytes[s]); offset += 2;
                            }
                        }
                    }
                }
                thisCounter++;
            }
            byte[] temp = new byte[offset];
            Bits.SetBytes(temp, 0, mold);
            return(temp);
        }
        public void Assemble(ref int offset)
        {
            // first make sure each channel ends with a termination command
            for (int i = 0; i < 2; i++)
            {
                if (channels[i] != null && channels[i].Count > 0)
                {
                    SPCCommand lastSSC = channels[i][channels[i].Count - 1];
                    if (lastSSC.Opcode != 0xD0 && lastSSC.Opcode != 0xCD && lastSSC.Opcode != 0xCE)
                    {
                        channels[i].Add(new SPCCommand(new byte[] { 0xD0 }, this, 0));
                    }
                }
            }
            //
            int channelSize1 = 0;
            int channelSize2 = 0;

            if (channels[0] != null && activeChannels[0])
            {
                foreach (SPCCommand ssc in channels[0])
                {
                    channelSize1 += ssc.Length;
                }
            }
            if (channels[1] != null && activeChannels[1])
            {
                foreach (SPCCommand ssc in channels[1])
                {
                    channelSize2 += ssc.Length;
                }
            }
            //
            int offsetStart1 = offset;
            int offsetStart2 = offset + channelSize1;

            if (channels[0] == null || !activeChannels[0])
            {
                offsetStart1 = 0;
            }
            if (channels[1] == null || !activeChannels[1])
            {
                offsetStart2 = 0;
            }
            //
            bool channel2in1 = true;

            if (offsetStart1 != 0 && offsetStart2 != 0 && channelSize2 <= channelSize1)
            {
                for (int a = channels[0].Count - 1, b = channels[1].Count - 1; a >= 0 && b >= 0; a--, b--)
                {
                    if (!Bits.Compare(channels[0][a].CommandData, channels[1][b].CommandData))
                    {
                        channel2in1 = false;
                    }
                }
            }
            else
            {
                channel2in1 = false;
            }
            if (channel2in1)
            {
                offsetStart2 -= channelSize2;
            }
            //
            if (type == 0)
            {
                if (offsetStart1 == 0)
                {
                    Bits.SetShort(rom, index * 4 + 0x042826, 0);
                }
                else
                {
                    Bits.SetShort(rom, index * 4 + 0x042826, offsetStart1 - 0x042C26 + 0x3400);
                }
                if (offsetStart2 == 0)
                {
                    Bits.SetShort(rom, index * 4 + 0x042826 + 2, 0);
                }
                else
                {
                    Bits.SetShort(rom, index * 4 + 0x042826 + 2, offsetStart2 - 0x042C26 + 0x3400);
                }
            }
            else
            {
                if (offsetStart1 == 0)
                {
                    Bits.SetShort(rom, index * 4 + 0x043E26, 0);
                }
                else
                {
                    Bits.SetShort(rom, index * 4 + 0x043E26, offsetStart1 - 0x044226 + 0x3400);
                }
                if (offsetStart2 == 0)
                {
                    Bits.SetShort(rom, index * 4 + 0x043E26 + 2, 0);
                }
                else
                {
                    Bits.SetShort(rom, index * 4 + 0x043E26 + 2, offsetStart2 - 0x044226 + 0x3400);
                }
            }
            if (channels[0] != null && activeChannels[0])
            {
                foreach (SPCCommand ssc in channels[0])
                {
                    Bits.SetBytes(rom, offsetStart1, ssc.CommandData);
                    offsetStart1 += ssc.Length;
                }
            }
            if (channels[1] != null && activeChannels[1])
            {
                foreach (SPCCommand ssc in channels[1])
                {
                    Bits.SetBytes(rom, offsetStart2, ssc.CommandData);
                    offsetStart2 += ssc.Length;
                }
            }
            if (channel2in1)
            {
                offset += channelSize1;
            }
            else
            {
                offset += channelSize1 + channelSize2;
            }
        }
        public int Assemble()
        {
            int size = this.buffer.Length;

            // set sm to new byte with largest possible size
            byte[] temp = new byte[0x10000];
            // not dynamic, can set before others
            temp[12] = width;
            temp[13] = height;
            Bits.SetShort(temp, 14, codec);
            // now start writing dynamic data
            int offset = 18;

            // Graphics
            Bits.SetShort(temp, 2, 0x12);
            Buffer.BlockCopy(graphicSet, 0, temp, 18, graphicSetLength);
            offset += graphicSetLength;
            // Palettes
            Bits.SetShort(temp, 4, (ushort)offset);
            paletteSet.Assemble(temp, offset);
            offset += paletteSetLength;
            // Tileset
            Bits.SetShort(temp, 16, (ushort)offset);
            int tilesetoffset = offset;

            foreach (Tile t in tileset_tiles.Tileset)
            {
                if (t.Index >= tilesetLength / 8)
                {
                    break;
                }
                if (t.Index > 0 && t.Index % 8 == 0)
                {
                    offset += 32;
                }
                for (int i = 0; i < 4; i++)
                {
                    Bits.SetShort(temp, offset, (byte)t.Subtiles[i].Index); offset++;
                    Bits.SetBit(temp, offset, 5, t.Subtiles[i].Priority1);
                    Bits.SetBit(temp, offset, 6, t.Subtiles[i].Mirror);
                    Bits.SetBit(temp, offset, 7, t.Subtiles[i].Invert);
                    if (i % 2 == 0)
                    {
                        offset++;
                    }
                    else if (i == 1)
                    {
                        offset += 29;
                    }
                    else if (i == 3)
                    {
                        offset -= 31;
                    }
                }
            }
            Buffer.BlockCopy(temp, tilesetoffset, tileset_bytes, 0, tileset_bytes.Length);
            //
            offset += 32;
            Bits.SetShort(temp, offset, 0xFFFF); offset += 2;
            // Sequences
            Bits.SetShort(temp, 6, (ushort)offset);
            int fOffset = sequences.Count * 2 + 2;  // offset of first frame packet

            foreach (E_Sequence s in sequences)
            {
                if (s.Frames.Count != 0)
                {
                    Bits.SetShort(temp, offset, (ushort)(fOffset + offset));
                    fOffset += s.Frames.Count * 2 + 1;
                }
                else
                {
                    Bits.SetShort(temp, offset, 0xFFFF);
                }
                offset += 2;
            }
            Bits.SetShort(temp, offset, 0); offset += 2;
            foreach (E_Sequence s in sequences)
            {
                foreach (E_Sequence.Frame f in s.Frames)
                {
                    Bits.SetByte(temp, offset, f.Duration); offset++;
                    Bits.SetByte(temp, offset, f.Mold); offset++;
                }
                Bits.SetByte(temp, offset, 0); offset++;
            }
            // Molds
            Bits.SetShort(temp, 8, (ushort)offset);
            int mOffset = molds.Count * 2 + 2;    // offset of first mold tilemap

            foreach (E_Mold m in molds)
            {
                if (!m.Empty)
                {
                    Bits.SetShort(temp, offset, (ushort)(mOffset + offset));
                    mOffset += m.Recompress(m.Mold, width, height).Length - 2;
                }
                else
                {
                    Bits.SetShort(temp, offset, 0xFFFF);
                }
                offset += 2;
            }
            Bits.SetShort(temp, offset, 0); offset += 2;
            foreach (E_Mold m in molds)
            {
                if (!m.Empty)
                {
                    byte[] mold = m.Recompress(m.Mold, width, height);
                    Buffer.BlockCopy(mold, 0, temp, offset, mold.Length);
                    offset += mold.Length;
                }
            }
            // finally, set the animation length
            Bits.SetShort(temp, 0, (ushort)offset);
            this.buffer = new byte[offset];
            Bits.SetBytes(this.buffer, 0, temp);
            //Do.Export(sm, "test.bin");
            return(size - this.buffer.Length);
        }