public bool ContainsOffset(AnimationCommand parent, int offset)
        {
            bool found = false;

            foreach (AnimationCommand child in parent.Commands)
            {
                if (child.InternalOffset == offset)
                {
                    return(true);
                }
            }
            if (parent.Parent != null)
            {
                found = ContainsOffset(parent.Parent, offset);
            }
            return(found);
        }
        /// <summary>
        /// Returns the available space or final index for creating a new command, starting from this command.
        /// </summary>
        /// <param name="command">The first command to be replaced.</param>
        /// <param name="needed">The length of the new command (ie. the required space).</param>
        /// <param name="getIndex">Returns either the available space or the index of the last command to be replaced.</param>
        /// <returns></returns>
        public int AvailableSpace(int needed, bool getIndex)
        {
            int finalIndex        = this.Index;
            int available         = this.Length;
            AnimationCommand temp = this;

            while (
                needed > available &&
                temp.NextCommand != null &&
                temp.NextCommand.Opcode != 0x07 &&
                temp.NextCommand.Opcode != 0x11 &&
                temp.NextCommand.Opcode != 0x5E)
            {
                temp = temp.NextCommand;
                finalIndex++;
                available += temp.Length;
            }
            return(getIndex ? finalIndex : available);
        }
        // disassembler
        private void Disassemble(int offset)
        {
            int length = 0;
            AnimationCommand temp;

            switch (Opcode)
            {
            case 0x09:
                while ((offset & 0xFFFF) < 0xFFFF)
                {
                    // these are unusual cases, seems this is the only way
                    if (offset == 0x356076)
                    {
                        break;
                    }
                    if (offset == 0x356087)
                    {
                        break;
                    }
                    if (offset == 0x3560A9)
                    {
                        break;
                    }
                    if (offset == 0x3560CD)
                    {
                        break;
                    }
                    if (offset == 0x3560FE)
                    {
                        break;
                    }
                    if (offset == 0x356131)
                    {
                        break;
                    }
                    if (offset == 0x356152)
                    {
                        break;
                    }
                    if (offset == 0x35617A)
                    {
                        break;
                    }
                    if (offset == 0x3561AD)
                    {
                        break;
                    }
                    if (offset == 0x3561E0)
                    {
                        break;
                    }
                    if (offset == 0x356213)
                    {
                        break;
                    }
                    if (offset == 0x35624B)
                    {
                        break;
                    }
                    if (offset == 0x3A8A68)
                    {
                        break;
                    }
                    if (offset == 0x3A8AC0)
                    {
                        break;
                    }
                    if (offset == 0x3A8C8A)
                    {
                        break;
                    }
                    if ((offset & 0xFF0000) == 0x3A0000 && offset < 0x3A60D0)
                    {
                        break;
                    }
                    length = GetOpcodeLength(rom, offset);
                    temp   = new AnimationCommand(Bits.GetBytes(rom, offset, length), offset, script, this);
                    commands.Add(temp);
                    if (rom[offset] == 0x07 ||     // end animation packet
                        rom[offset] == 0x09 ||     // jump directly to address (thus ending this)
                        rom[offset] == 0x11 ||     // end subroutine
                        rom[offset] == 0x5E)       // end sprite subroutine
                    {
                        break;
                    }
                    offset += length;
                }
                break;

            case 0x10: goto case 0x09;

            case 0x5D: goto case 0x09;

            case 0x64:
                if (script.AMEM > 0x10)
                {
                    script.AMEM = 0;
                    offset      = (offset & 0xFF0000) + Bits.GetShort(rom, offset);
                }
                else
                {
                    offset = (offset & 0xFF0000) + Bits.GetShort(rom, offset + (script.AMEM * 2));
                }
                goto case 0x09;

            case 0x68:
                if (script.AMEM >= 0x40)
                {
                    script.AMEM = 0;
                    offset      = (offset & 0xFF0000) + Bits.GetShort(rom, offset);
                }
                else
                {
                    offset = (offset & 0xFF0000) + Bits.GetShort(rom, offset + (script.AMEM * 2));
                }
                //
                if (offset == 0x356919 ||
                    offset == 0x356969)
                {
                    offset += 2;
                }
                else
                {
                    offset = (offset & 0xFF0000) + Bits.GetShort(rom, offset + commandData[3]);
                }
                goto case 0x09;

            default:
                if (Opcode >= 0x24 && Opcode <= 0x2B)
                {
                    offset = (offset & 0xFF0000) + Bits.GetShort(commandData, 4);
                    goto case 0x09;
                }
                break;
            }
        }
        // constructor
        public AnimationCommand(byte[] commandData, int offset, AnimationScript script, AnimationCommand parent)
        {
            this.commandData    = commandData;
            this.parent         = parent;
            this.offset         = offset;
            this.originalOffset = offset;
            this.internalOffset = offset;
            this.script         = script; // for reading the "memory" variable
            //if (Opcode == 0x72 &&
            //    (Param1 & 0x01) == 0x01 &&
            //    (Param1 & 0x04) == 0x04)
            //    MessageBox.Show(script.Type + "," + script.Index);
            //
            int search = 0;

            switch (Opcode)
            {
            case 0xA3:
                break;

            case 0x09:
                search = (offset & 0xFF0000) + Bits.GetShort(commandData, 1);
                if (parent == null && !ContainsOffset(script, search))
                {
                    Disassemble((offset & 0xFF0000) + Bits.GetShort(commandData, 1));
                }
                else if (parent != null && !parent.ContainsOffset(parent, search))
                {
                    Disassemble((offset & 0xFF0000) + Bits.GetShort(commandData, 1));
                }
                break;

            case 0x10:
            case 0x64:
            case 0x68:
                if (offset == 0x3562C8 ||
                    offset == 0x3564FC)
                {
                    script.AMEM = 0;
                }
                if ((offset & 0xFF0000) == 0x350000 && Bits.GetShort(commandData, 1) == 0x8499)
                {
                    script.AMEM = 0;
                }
                if (offset == 0x3AA5EE)
                {
                    script.AMEM = 12;     // it's the only one that has enough pointers
                }
                Disassemble((offset & 0xFF0000) + Bits.GetShort(commandData, 1));
                break;

            case 0x5D:
                Disassemble((offset & 0xFF0000) + Bits.GetShort(commandData, 3));
                break;

            case 0x20:
            case 0x21: if ((Param1 & 0x0F) == 0)
                {
                    script.AMEM = Param2;
                }
                break;

            case 0x2C:
            case 0x2D: if ((Param1 & 0x0F) == 0)
                {
                    script.AMEM += Param2;
                }
                break;

            case 0x2E:
            case 0x2F: if ((Param1 & 0x0F) == 0)
                {
                    script.AMEM -= Param2;
                }
                break;

            case 0x30:
            case 0x31: if ((Param1 & 0x0F) == 0)
                {
                    script.AMEM++;
                }
                break;

            case 0x32:
            case 0x33: if ((Param1 & 0x0F) == 0)
                {
                    script.AMEM--;
                }
                break;

            case 0x34:
            case 0x35: if ((Param1 & 0x0F) == 0)
                {
                    script.AMEM = 0;
                }
                break;

            case 0x6A:
            case 0x6B: if ((Param1 & 0x0F) == 0)
                {
                    script.AMEM = (byte)(Param2 - 1);
                }
                break;

            default:
                if (Opcode >= 0x24 && Opcode <= 0x2B)
                {
                    search = (offset & 0xFF0000) + Bits.GetShort(commandData, 4);
                    if (parent == null && !ContainsOffset(script, search))
                    {
                        Disassemble((offset & 0xFF0000) + Bits.GetShort(commandData, 4));
                    }
                    else if (parent != null && !parent.ContainsOffset(parent, search))
                    {
                        Disassemble((offset & 0xFF0000) + Bits.GetShort(commandData, 4));
                    }
                }
                break;
            }
        }