Merge remote-tracking branch 'upstream/master' into feature/savestates-2
This commit is contained in:
		| @@ -319,7 +319,7 @@ System::ResultStatus System::Init(Frontend::EmuWindow& emu_window, u32 system_mo | ||||
|  | ||||
|     memory = std::make_unique<Memory::MemorySystem>(); | ||||
|  | ||||
|     timing = std::make_unique<Timing>(num_cores); | ||||
|     timing = std::make_unique<Timing>(num_cores, Settings::values.cpu_clock_percentage); | ||||
|  | ||||
|     kernel = std::make_unique<Kernel::KernelSystem>( | ||||
|         *memory, *timing, [this] { PrepareReschedule(); }, system_mode, num_cores, n3ds_mode); | ||||
|   | ||||
| @@ -22,14 +22,21 @@ bool Timing::Event::operator<(const Timing::Event& right) const { | ||||
|     return std::tie(time, fifo_order) < std::tie(right.time, right.fifo_order); | ||||
| } | ||||
|  | ||||
| Timing::Timing(std::size_t num_cores) { | ||||
| Timing::Timing(std::size_t num_cores, u32 cpu_clock_percentage) { | ||||
|     timers.resize(num_cores); | ||||
|     for (std::size_t i = 0; i < num_cores; ++i) { | ||||
|         timers[i] = std::make_shared<Timer>(); | ||||
|     } | ||||
|     UpdateClockSpeed(cpu_clock_percentage); | ||||
|     current_timer = timers[0]; | ||||
| } | ||||
|  | ||||
| void Timing::UpdateClockSpeed(u32 cpu_clock_percentage) { | ||||
|     for (auto& timer : timers) { | ||||
|         timer->cpu_clock_scale = 100.0 / cpu_clock_percentage; | ||||
|     } | ||||
| } | ||||
|  | ||||
| TimingEventType* Timing::RegisterEvent(const std::string& name, TimedCallback callback) { | ||||
|     // check for existing type with same name. | ||||
|     // we want event type names to remain unique so that we can use them for serialization. | ||||
| @@ -117,6 +124,8 @@ std::shared_ptr<Timing::Timer> Timing::GetTimer(std::size_t cpu_id) { | ||||
|     return timers[cpu_id]; | ||||
| } | ||||
|  | ||||
| Timing::Timer::Timer() = default; | ||||
|  | ||||
| Timing::Timer::~Timer() { | ||||
|     MoveEvents(); | ||||
| } | ||||
| @@ -130,7 +139,7 @@ u64 Timing::Timer::GetTicks() const { | ||||
| } | ||||
|  | ||||
| void Timing::Timer::AddTicks(u64 ticks) { | ||||
|     downcount -= ticks; | ||||
|     downcount -= static_cast<u64>(ticks * cpu_clock_scale); | ||||
| } | ||||
|  | ||||
| u64 Timing::Timer::GetIdleTicks() const { | ||||
|   | ||||
| @@ -176,6 +176,7 @@ public: | ||||
|  | ||||
|     class Timer { | ||||
|     public: | ||||
|         Timer(); | ||||
|         ~Timer(); | ||||
|  | ||||
|         s64 GetMaxSliceLength() const; | ||||
| @@ -218,7 +219,10 @@ public: | ||||
|         s64 slice_length = MAX_SLICE_LENGTH; | ||||
|         s64 downcount = MAX_SLICE_LENGTH; | ||||
|         s64 executed_ticks = 0; | ||||
|         u64 idled_cycles; | ||||
|         u64 idled_cycles = 0; | ||||
|         // Stores a scaling for the internal clockspeed. Changing this number results in | ||||
|         // under/overclocking the guest cpu | ||||
|         double cpu_clock_scale = 1.0; | ||||
|  | ||||
|         template <class Archive> | ||||
|         void serialize(Archive& ar, const unsigned int) { | ||||
| @@ -234,7 +238,7 @@ public: | ||||
|         friend class boost::serialization::access; | ||||
|     }; | ||||
|  | ||||
|     explicit Timing(std::size_t num_cores); | ||||
|     explicit Timing(std::size_t num_cores, u32 cpu_clock_percentage); | ||||
|  | ||||
|     ~Timing(){}; | ||||
|  | ||||
| @@ -261,6 +265,11 @@ public: | ||||
|         global_timer += ticks; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Updates the value of the cpu clock scaling to the new percentage. | ||||
|      */ | ||||
|     void UpdateClockSpeed(u32 cpu_clock_percentage); | ||||
|  | ||||
|     std::chrono::microseconds GetGlobalTimeUs() const; | ||||
|  | ||||
|     std::shared_ptr<Timer> GetTimer(std::size_t cpu_id); | ||||
| @@ -270,11 +279,15 @@ private: | ||||
|  | ||||
|     // unordered_map stores each element separately as a linked list node so pointers to | ||||
|     // elements remain stable regardless of rehashes/resizing. | ||||
|     std::unordered_map<std::string, TimingEventType> event_types; | ||||
|     std::unordered_map<std::string, TimingEventType> event_types = {}; | ||||
|  | ||||
|     std::vector<std::shared_ptr<Timer>> timers; | ||||
|     std::shared_ptr<Timer> current_timer; | ||||
|  | ||||
|     // Stores a scaling for the internal clockspeed. Changing this number results in | ||||
|     // under/overclocking the guest cpu | ||||
|     double cpu_clock_scale = 1.0; | ||||
|  | ||||
|     template <class Archive> | ||||
|     void serialize(Archive& ar, const unsigned int) { | ||||
|         // event_types set during initialization of other things | ||||
|   | ||||
| @@ -152,13 +152,16 @@ ResultCode VMManager::ChangeMemoryState(VAddr target, u32 size, MemoryState expe | ||||
|     } | ||||
|  | ||||
|     CASCADE_RESULT(auto vma, CarveVMARange(target, size)); | ||||
|     ASSERT(vma->second.size == size); | ||||
|  | ||||
|     vma->second.permissions = new_perms; | ||||
|     vma->second.meminfo_state = new_state; | ||||
|     UpdatePageTableForVMA(vma->second); | ||||
|  | ||||
|     MergeAdjacent(vma); | ||||
|     const VMAIter end = vma_map.end(); | ||||
|     // The comparison against the end of the range must be done using addresses since VMAs can be | ||||
|     // merged during this process, causing invalidation of the iterators. | ||||
|     while (vma != end && vma->second.base < target_end) { | ||||
|         vma->second.permissions = new_perms; | ||||
|         vma->second.meminfo_state = new_state; | ||||
|         UpdatePageTableForVMA(vma->second); | ||||
|         vma = std::next(MergeAdjacent(vma)); | ||||
|     } | ||||
|  | ||||
|     return RESULT_SUCCESS; | ||||
| } | ||||
|   | ||||
| @@ -46,10 +46,17 @@ static const ResultCode ERROR_NOT_LOADED = // 0xD8A12C0D | ||||
|  | ||||
| static bool VerifyBufferState(Kernel::Process& process, VAddr buffer_ptr, u32 size) { | ||||
|     auto vma = process.vm_manager.FindVMA(buffer_ptr); | ||||
|     return vma != process.vm_manager.vma_map.end() && | ||||
|            vma->second.base + vma->second.size >= buffer_ptr + size && | ||||
|            vma->second.permissions == Kernel::VMAPermission::ReadWrite && | ||||
|            vma->second.meminfo_state == Kernel::MemoryState::Private; | ||||
|     while (vma != process.vm_manager.vma_map.end()) { | ||||
|         if (vma->second.permissions != Kernel::VMAPermission::ReadWrite || | ||||
|             vma->second.meminfo_state != Kernel::MemoryState::Private) { | ||||
|             return false; | ||||
|         } | ||||
|         if (vma->second.base + vma->second.size >= buffer_ptr + size) { | ||||
|             return true; | ||||
|         } | ||||
|         vma = std::next(vma); | ||||
|     } | ||||
|     return false; | ||||
| } | ||||
|  | ||||
| void RO::Initialize(Kernel::HLERequestContext& ctx) { | ||||
|   | ||||
| @@ -44,6 +44,7 @@ void Apply() { | ||||
|  | ||||
|     auto& system = Core::System::GetInstance(); | ||||
|     if (system.IsPoweredOn()) { | ||||
|         system.CoreTiming().UpdateClockSpeed(values.cpu_clock_percentage); | ||||
|         Core::DSP().SetSink(values.sink_id, values.audio_device_id); | ||||
|         Core::DSP().EnableStretching(values.enable_audio_stretching); | ||||
|  | ||||
|   | ||||
| @@ -128,6 +128,7 @@ struct Values { | ||||
|  | ||||
|     // Core | ||||
|     bool use_cpu_jit; | ||||
|     int cpu_clock_percentage; | ||||
|  | ||||
|     // Data Storage | ||||
|     bool use_virtual_sd; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user