Ejemplo n.º 1
0
        /// <summary>
        /// Binds an opcode to a function.
        /// </summary>
        /// <typeparam name="Tfunc">A function delegate to bind.</typeparam>
        /// <param name="ID"></param>
        /// <param name="Argc"></param>
        /// <param name="Function"></param>
        public void Bind <Tfunc>(ushort ID, int Argc, Tfunc Function)
        {
            Type T = typeof(Tfunc);

            ScriptFunctionMeta MetaFunction = new ScriptFunctionMeta();

            if (T == typeof(ScriptFunction))
            {
                MetaFunction.Function = (ScriptFunction)Convert.ChangeType(Function, typeof(ScriptFunction));
            }
            else
            {
                MetaFunction.BooleanFunction = (ScriptFunctionBoolean)Convert.ChangeType(Function, typeof(ScriptFunctionBoolean));
            }
            MetaFunction.Arguments = Argc;

            functions.Add(ID, MetaFunction);

            /*functions.insert(
             *
             * {
             *  id,
             *              {
             *
             *      [=] (ScriptArguments& args) { script_bind.do_unpacked_call(function, args); },
             *                      argc, "opcode", ""
             *              }
             *      });*/
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Finds the function based on an opcode (ID).
        /// </summary>
        /// <param name="ID">The opcode (ID) of a function.</param>
        /// <param name="Func">The function to find.</param>
        /// <returns></returns>
        public bool FindOpcode(ushort ID, out ScriptFunctionMeta Func)
        {
            try
            {
                var it = functions[ID];
            }
            catch (KeyNotFoundException)
            {
                Func = new ScriptFunctionMeta();
                return(false);
            }

            Func = functions[ID];
            return(true);
        }
Ejemplo n.º 3
0
        private void ExecuteThread(SCMThread Thread, int MSPassed)
        {
            ///TODO: Fully implement this.

            /*auto player = state->world->getPlayer();
             *
             * if (player)
             * {*/
            if (Thread.IsMission && Thread.DeathOrArrestCheck /*&&
                                                               * (player->isWasted() || player->isBusted())*/)
            {
                Thread.WastedOrBusted = true;
                Thread.StackDepth     = 0;
                Thread.ProgramCounter = Thread.Calls[(int)Thread.StackDepth];
            }
            //}

            // There is 02a1 opcode that is used only during "Kingdom Come", which
            // basically acts like a wait command, but waiting time can be skipped
            // by pressing 'X'? PS2 button
            if (Thread.AllowWaitSkip /*&& getState()->input[0].pressed(GameInputState::Jump)*/)
            {
                Thread.WakeCounter   = 0;
                Thread.AllowWaitSkip = false;
            }
            if (Thread.WakeCounter > 0)
            {
                Thread.WakeCounter = Math.Max(Thread.WakeCounter - MSPassed, 0);
            }
            if (Thread.WakeCounter > 0)
            {
                return;
            }

            while (Thread.WakeCounter == 0)
            {
                var PC     = Thread.ProgramCounter;
                var Opcode = file.Read <ushort>(PC);

                bool IsNegatedConditional = ((Opcode & SCM_NEGATE_CONDITIONAL_MASK) ==
                                             SCM_NEGATE_CONDITIONAL_MASK);
                Opcode = (ushort)(Opcode & ~SCM_NEGATE_CONDITIONAL_MASK);

                ScriptFunctionMeta FoundCode;
                if (!module.FindOpcode(Opcode, out FoundCode))
                {
                    throw new IllegalInstruction <Exception>(Opcode, PC, Thread.Name);
                }

                ScriptFunctionMeta Code = FoundCode;

                PC += sizeof(ushort);

                List <SCMOpcodeParameter> Parameters = new List <SCMOpcodeParameter>();

                bool HasExtraParameters = Code.Arguments < 0;
                var  RequiredParams     = Math.Abs(Code.Arguments);

                for (int p = 0; p < RequiredParams || HasExtraParameters; ++p)
                {
                    //byte was originally SCMByte ... might have to change to char.
                    var type_r = file.Read <byte>(PC);
                    var type   = (SCMType)type_r;

                    if (type_r > 42)
                    {
                        // for implicit strings, we need the byte we just read.
                        type = SCMType.TString;
                    }
                    else
                    {
                        PC += sizeof(byte);
                    }

                    //TODO: Is this correct?
                    //Parameters.push_back(SCMOpcodeParameter{ type, { 0} });
                    Parameters.Add(new SCMOpcodeParameter(type));

                    switch (type)
                    {
                    case SCMType.EndOfArgList:
                        HasExtraParameters = false;
                        break;

                    case SCMType.TInt8:
                        lock (Parameters)     //Thread safety
                        {
                            SCMOpcodeParameter Param = Parameters.LastOrDefault();
                            Param.Integer = file.Read <byte>(PC);
                            Parameters[Parameters.Count - 1] = Param;
                        }
                        PC += sizeof(byte);
                        break;

                    case SCMType.TInt16:
                        lock (Parameters)     //Thread safety
                        {
                            SCMOpcodeParameter Param = Parameters.LastOrDefault();
                            Param.Integer = file.Read <short>(PC);
                            Parameters[Parameters.Count - 1] = Param;
                        }
                        PC += sizeof(byte) * 2;
                        break;

                    case SCMType.TGlobal:
                    {
                        var v = file.Read <ushort>(PC);

                        lock (Parameters)         //Thread safety
                        {
                            SCMOpcodeParameter Param = Parameters.LastOrDefault();
                            //TODO: This was originally GlobalData.data() + v...
                            Param.GlobalPtr = (IntPtr)globalData.ToArray().Length + v * SCM_VARIABLE_SIZE;
                            Parameters[Parameters.Count - 1] = Param;
                        }

                        if (v >= file.GlobalsSize)
                        {
                            Debug.WriteLine("ERROR: ScriptMachine.cs: Global out of bounds! " +
                                            v.ToString() + " " +
                                            file.GlobalsSize.ToString());
                        }
                        PC += sizeof(byte) * 2;
                    }
                    break;

                    case SCMType.TLocal:
                    {
                        var v = file.Read <ushort>(PC);

                        lock (Parameters)
                        {
                            SCMOpcodeParameter Param = Parameters.LastOrDefault();
                            //Not sure if this is correct, was originally Locals.data() + v...
                            Param.GlobalPtr = (IntPtr)Thread.Locals.ToArray().Length + v * SCM_VARIABLE_SIZE;
                            Parameters[Parameters.Count - 1] = Param;
                        }

                        if (v >= SCM_THREAD_LOCAL_SIZE)
                        {
                            Debug.WriteLine("Scriptmachine.CS: Local out of bounds!");
                        }
                        PC += sizeof(byte) * 2;
                    }
                    break;

                    case SCMType.TInt32:
                        lock (Parameters)     //Thread safety
                        {
                            SCMOpcodeParameter Param = Parameters.LastOrDefault();
                            Param.Integer = file.Read <int>(PC);
                            Parameters[Parameters.Count - 1] = Param;
                        }
                        PC += sizeof(byte) * 4;
                        break;

                    case SCMType.TString:
                        lock (Parameters)     //Thread safety
                        {
                            SCMOpcodeParameter Param = Parameters.LastOrDefault();
                            char[]             Str   = Param.Str.ToArray();
                            //Copy a string from the file data to the string.
                            Array.Copy(file.Data.ToArray(), (int)PC, Str, 0, 8);
                            Param.Str = new string(Str);
                            Parameters[Parameters.Count - 1] = Param;
                        }

                        PC += sizeof(byte) * 8;
                        break;

                    case SCMType.TFloat16:
                        lock (Parameters)     //Thread safety
                        {
                            SCMOpcodeParameter Param = Parameters.LastOrDefault();
                            Param.Real = file.Read <short>(PC) / 16f;
                            Parameters[Parameters.Count - 1] = Param;
                        }
                        PC += sizeof(byte) * 2;
                        break;

                    default:
                        throw new UnknownType <Exception>((char)type, PC, Thread.Name);
                    }
                    ;

                    ScriptArguments Sca = new ScriptArguments(Parameters, Thread, this);