Пример #1
0
        static void STEP_CORRUPT(bool _isRewinding, bool _isFastForwarding, bool _isPaused)
        {
            if (DisableRTC)
            {
                return;
            }

            if (!_isRewinding && !_isPaused)
            {
                if (RTC_PipeEngine.ProcessOnStep)
                {
                    RTC_PipeEngine.ExecutePipes();
                }
            }

            if (_isRewinding || _isFastForwarding || _isPaused)
            {
                return;
            }


            CPU_STEP_Count++;

            if (RTC_Core.AutoCorrupt && CPU_STEP_Count >= RTC_Core.ErrorDelay)
            {
                CPU_STEP_Count = 0;
                BlastLayer bl = RTC_Core.Blast(null, RTC_MemoryDomains.SelectedDomains);
                if (bl != null)
                {
                    bl.Apply();
                }
            }
        }
Пример #2
0
        //Generates or applies a blast layer using one of the multiple BlastRadius algorithms
        public static BlastLayer Blast(BlastLayer _layer, string[] _selectedDomains)
        {
            string     Domain        = null;
            long       MaxAddress    = -1;
            long       RandomAddress = -1;
            BlastUnit  bu;
            BlastLayer bl;

            try
            {
                if (_layer != null)
                {
                    _layer.Apply(); //If the BlastLayer was provided, there's no need to generate a new one.

                    return(_layer);
                }
                else if (RTC_Core.SelectedEngine == CorruptionEngine.EXTERNALROM)
                {   //External ROM Plugin: Bypasses domains and uses an alternative algorithm to fetch corruption.
                    //It will query a BlastLayer generated from a differential between an original and corrupted rom.
                    bl = RTC_ExternalRomPlugin.GetBlastLayer();
                    if (bl == null)
                    {
                        return(null);
                    }
                    else
                    {
                        return(bl);
                    }
                }
                else
                {
                    bl = new BlastLayer();

                    if (_selectedDomains == null || _selectedDomains.Count() == 0)
                    {
                        return(null);
                    }

                    // Age distortion BlastBytes
                    if (RTC_Core.SelectedEngine == CorruptionEngine.DISTORTION && RTC_DistortionEngine.CurrentAge < RTC_DistortionEngine.MaxAge)
                    {
                        RTC_DistortionEngine.CurrentAge++;
                    }

                    //Run Pipes on Corrupt Step if required
                    if (RTC_Core.SelectedEngine == CorruptionEngine.PIPE && !RTC_PipeEngine.ProcessOnStep)
                    {
                        RTC_PipeEngine.ExecutePipes();
                    }


                    // Capping intensity at engine-specific maximums

                    int _Intensity = Intensity;                     //general RTC intensity

                    if ((RTC_Core.SelectedEngine == CorruptionEngine.HELLGENIE || RTC_Core.SelectedEngine == CorruptionEngine.FREEZE) && _Intensity > RTC_HellgenieEngine.MaxCheats)
                    {
                        _Intensity = RTC_HellgenieEngine.MaxCheats;                         //Capping for cheat max
                    }
                    if (RTC_Core.SelectedEngine == CorruptionEngine.PIPE && _Intensity > RTC_PipeEngine.MaxPipes)
                    {
                        _Intensity = RTC_PipeEngine.MaxPipes; //Capping for pipe max
                    }
                    switch (Radius)                           //Algorithm branching
                    {
                    case BlastRadius.SPREAD:                  //Randomly spreads all corruption bytes to all selected domains

                        for (int i = 0; i < _Intensity; i++)
                        {
                            Domain = _selectedDomains[RND.Next(_selectedDomains.Length)];

                            MaxAddress    = RTC_MemoryDomains.getInterface(Domain).Size;
                            RandomAddress = RTC_Core.RND.RandomLong(MaxAddress - 1);

                            bu = getBlastUnit(Domain, RandomAddress);
                            if (bu != null)
                            {
                                bl.Layer.Add(bu);
                            }
                        }

                        break;

                    case BlastRadius.CHUNK:     //Randomly spreads the corruption bytes in one randomly selected domain

                        Domain = _selectedDomains[RND.Next(_selectedDomains.Length)];

                        MaxAddress = RTC_MemoryDomains.getInterface(Domain).Size;

                        for (int i = 0; i < _Intensity; i++)
                        {
                            RandomAddress = RTC_Core.RND.RandomLong(MaxAddress - 1);

                            bu = getBlastUnit(Domain, RandomAddress);
                            if (bu != null)
                            {
                                bl.Layer.Add(bu);
                            }
                        }

                        break;

                    case BlastRadius.BURST:                             // 10 shots of 10% chunk

                        for (int j = 0; j < 10; j++)
                        {
                            Domain = _selectedDomains[RND.Next(_selectedDomains.Length)];

                            MaxAddress = RTC_MemoryDomains.getInterface(Domain).Size;

                            for (int i = 0; i < (int)((double)_Intensity / 10); i++)
                            {
                                RandomAddress = RTC_Core.RND.RandomLong(MaxAddress - 1);

                                bu = getBlastUnit(Domain, RandomAddress);
                                if (bu != null)
                                {
                                    bl.Layer.Add(bu);
                                }
                            }
                        }

                        break;

                    case BlastRadius.NORMALIZED:                             // Blasts based on the size of the largest selected domain. Intensity =  Intensity / (domainSize[largestdomain]/domainSize[currentdomain])


                        //Find the smallest domain and base our normalization around it
                        //Domains aren't IComparable so I used keys

                        long[] domainSize = new long [_selectedDomains.Length];
                        for (int i = 0; i < _selectedDomains.Length; i++)
                        {
                            Domain        = _selectedDomains[i];
                            domainSize[i] = RTC_MemoryDomains.getInterface(Domain).Size;
                        }
                        //Sort the arrays
                        Array.Sort(domainSize, _selectedDomains);

                        for (int i = 0; i < _selectedDomains.Length; i++)
                        {
                            Domain = _selectedDomains[i];

                            //Get the intensity divider. The size of the largest domain divided by the size of the current domain
                            long normalized = ((domainSize[_selectedDomains.Length - 1] / (domainSize[i])));

                            for (int j = 0; j < (_Intensity / normalized); j++)
                            {
                                MaxAddress    = RTC_MemoryDomains.getInterface(Domain).Size;
                                RandomAddress = RTC_Core.RND.RandomLong(MaxAddress - 1);

                                bu = getBlastUnit(Domain, RandomAddress);
                                if (bu != null)
                                {
                                    bl.Layer.Add(bu);
                                }
                            }
                        }

                        break;

                    case BlastRadius.PROPORTIONAL:                                                                     //Blasts proportionally based on the total size of all selected domains

                        long totalSize = _selectedDomains.Select(it => RTC_MemoryDomains.getInterface(it).Size).Sum(); //Gets the total size of all selected domains

                        long[] normalizedIntensity = new long[_selectedDomains.Length];                                //matches the index of selectedDomains
                        for (int i = 0; i < _selectedDomains.Length; i++)
                        {                                                                                              //calculates the proportionnal normalized Intensity based on total selected domains size
                            double proportion = (double)RTC_MemoryDomains.getInterface(_selectedDomains[i]).Size / (double)totalSize;
                            normalizedIntensity[i] = Convert.ToInt64((double)_Intensity * proportion);
                        }

                        for (int i = 0; i < _selectedDomains.Length; i++)
                        {
                            Domain = _selectedDomains[i];

                            for (int j = 0; j < normalizedIntensity[i]; j++)
                            {
                                MaxAddress    = RTC_MemoryDomains.getInterface(Domain).Size;
                                RandomAddress = RTC_Core.RND.RandomLong(MaxAddress - 1);

                                bu = getBlastUnit(Domain, RandomAddress);
                                if (bu != null)
                                {
                                    bl.Layer.Add(bu);
                                }
                            }
                        }

                        break;

                    case BlastRadius.EVEN:                             //Evenly distributes the blasts through all selected domains

                        for (int i = 0; i < _selectedDomains.Length; i++)
                        {
                            Domain = _selectedDomains[i];

                            for (int j = 0; j < (_Intensity / _selectedDomains.Length); j++)
                            {
                                MaxAddress    = RTC_MemoryDomains.getInterface(Domain).Size;
                                RandomAddress = RTC_Core.RND.RandomLong(MaxAddress - 1);

                                bu = getBlastUnit(Domain, RandomAddress);
                                if (bu != null)
                                {
                                    bl.Layer.Add(bu);
                                }
                            }
                        }

                        break;

                    case BlastRadius.NONE:                             //Shouldn't ever happen but handled anyway
                        return(null);
                    }


                    if (bl.Layer.Count == 0)
                    {
                        return(null);
                    }
                    else
                    {
                        return(bl);
                    }
                }
            }
            catch (Exception ex)
            {
                DialogResult dr = MessageBox.Show("Something went wrong in the RTC Core. \n" +
                                                  "This is not a BizHawk error so you should probably send a screenshot of this to the devs\n\n" +
                                                  "If you know the steps to reproduce this error it would be greatly appreaciated.\n\n" +
                                                  (RTC_Core.coreForm.AutoCorrupt ? ">> STOP AUTOCORRUPT ?.\n\n" : "") +
                                                  $"domain:{Domain.ToString()} maxaddress:{MaxAddress.ToString()} randomaddress:{RandomAddress.ToString()} \n\n" +
                                                  ex.ToString(), "Error", (RTC_Core.coreForm.AutoCorrupt ? MessageBoxButtons.YesNo : MessageBoxButtons.OK));

                if (dr == DialogResult.Yes || dr == DialogResult.OK)
                {
                    RTC_Core.coreForm.AutoCorrupt = false;
                }

                return(null);
            }
        }