예제 #1
0
        private static void ExecuteInput(object obj)
        {
            /*************************************************************
            * PERFORMANCE CRITICAL CODE                                  *
            * Even the smallest change must be thoroughly tested         *
            *************************************************************/

            //Increment running threads
            Interlocked.Increment(ref RunningInputThreads);

            //Get the input list - this should have been validated beforehand
            InputWrapper inputWrapper = (InputWrapper)obj;

            Parser.Input[][] inputArray = inputWrapper.InputArray;

            Stopwatch sw = new Stopwatch();

            List <int> indices = new List <int>(16);
            IVirtualControllerManager vcMngr = InputGlobals.ControllerMngr;

            int controllerCount = vcMngr.ControllerCount;

            int[] nonWaits = new int[controllerCount];

            //This is used to track which controller ports were used across all inputs
            //This helps prevent updating controllers that weren't used at the end
            int[] usedControllerPorts = new int[controllerCount];

            ConsoleBase curConsole = InputGlobals.CurrentConsole;

            //Don't check for overflow to improve performance
            unchecked
            {
                for (int i = 0; i < inputArray.Length; i++)
                {
                    ref Parser.Input[] inputs = ref inputArray[i];

                    indices.Clear();

                    //Press all buttons unless it's a release input
                    for (int j = 0; j < inputs.Length; j++)
                    {
                        indices.Add(j);

                        //Get a reference to avoid copying the struct
                        ref Parser.Input input = ref inputs[j];

                        //Don't do anything for a wait input
                        if (curConsole.IsWait(input) == true)
                        {
                            continue;
                        }

                        int port = input.controllerPort;

                        //Get the controller we're using
                        IVirtualController controller = vcMngr.GetController(port);

                        //These are set to 1 instead of incremented to prevent any chance of overflow
                        nonWaits[port]            = 1;
                        usedControllerPorts[port] = 1;

                        if (input.release == true)
                        {
                            controller.ReleaseInput(input);
                        }
                        else
                        {
                            controller.PressInput(input);
                        }
                    }

                    //Update the controllers if there are non-wait inputs
                    for (int waitIdx = 0; waitIdx < nonWaits.Length; waitIdx++)
                    {
                        if (nonWaits[waitIdx] > 0)
                        {
                            IVirtualController controller = vcMngr.GetController(waitIdx);
                            controller.UpdateController();
                            nonWaits[waitIdx] = 0;
                        }
                    }

                    sw.Start();

                    while (indices.Count > 0)
                    {
                        //End the input prematurely
                        if (StopRunningInputs == true)
                        {
                            goto End;
                        }

                        //Release buttons when we should
                        for (int j = indices.Count - 1; j >= 0; j--)
                        {
                            ref Parser.Input input = ref inputs[indices[j]];

                            if (sw.ElapsedMilliseconds < input.duration)
                            {
                                continue;
                            }

                            //Release if the input isn't a hold and isn't a wait input
                            if (input.hold == false && curConsole.IsWait(input) == false)
                            {
                                int port = input.controllerPort;

                                //Get the controller we're using
                                IVirtualController controller = vcMngr.GetController(port);

                                controller.ReleaseInput(input);

                                //Track that we have a non-wait or hold input so we can update the controller with all input releases at once
                                nonWaits[port] = 1;

                                usedControllerPorts[port] = 1;
                            }

                            indices.RemoveAt(j);
                        }

                        //Update the controllers if there are non-wait inputs
                        for (int waitIdx = 0; waitIdx < nonWaits.Length; waitIdx++)
                        {
                            if (nonWaits[waitIdx] > 0)
                            {
                                IVirtualController controller = vcMngr.GetController(waitIdx);
                                controller.UpdateController();

                                nonWaits[waitIdx] = 0;
                            }
                        }
                    }