Merge branch 'master' into httpc

This commit is contained in:
PabloMK7 2023-10-02 20:25:32 +02:00
commit 3afcf52215
27 changed files with 41467 additions and 29415 deletions

3314
dist/languages/da_DK.ts vendored

File diff suppressed because it is too large Load Diff

3255
dist/languages/de.ts vendored

File diff suppressed because it is too large Load Diff

3332
dist/languages/el.ts vendored

File diff suppressed because it is too large Load Diff

3380
dist/languages/es_ES.ts vendored

File diff suppressed because it is too large Load Diff

3315
dist/languages/fi.ts vendored

File diff suppressed because it is too large Load Diff

3463
dist/languages/fr.ts vendored

File diff suppressed because it is too large Load Diff

3238
dist/languages/id.ts vendored

File diff suppressed because it is too large Load Diff

3259
dist/languages/it.ts vendored

File diff suppressed because it is too large Load Diff

3309
dist/languages/ja_JP.ts vendored

File diff suppressed because it is too large Load Diff

3449
dist/languages/ko_KR.ts vendored

File diff suppressed because it is too large Load Diff

3308
dist/languages/lt_LT.ts vendored

File diff suppressed because it is too large Load Diff

3254
dist/languages/nb.ts vendored

File diff suppressed because it is too large Load Diff

4126
dist/languages/nl.ts vendored

File diff suppressed because it is too large Load Diff

3315
dist/languages/pl_PL.ts vendored

File diff suppressed because it is too large Load Diff

3324
dist/languages/pt_BR.ts vendored

File diff suppressed because it is too large Load Diff

3336
dist/languages/ro_RO.ts vendored

File diff suppressed because it is too large Load Diff

3256
dist/languages/ru_RU.ts vendored

File diff suppressed because it is too large Load Diff

3265
dist/languages/tr_TR.ts vendored

File diff suppressed because it is too large Load Diff

3478
dist/languages/vi_VN.ts vendored

File diff suppressed because it is too large Load Diff

3237
dist/languages/zh_CN.ts vendored

File diff suppressed because it is too large Load Diff

3542
dist/languages/zh_TW.ts vendored

File diff suppressed because it is too large Load Diff

View File

@ -231,7 +231,8 @@ void Source::ParseConfig(SourceConfiguration::Configuration& config,
}
}
LOG_TRACE(Audio_DSP, "partially updating embedded buffer addr={:#010x} len={} id={}",
state.current_buffer_physical_address, config.length, config.buffer_id);
state.current_buffer_physical_address, static_cast<u32>(config.length),
config.buffer_id);
}
if (config.embedded_buffer_dirty) {
@ -266,8 +267,8 @@ void Source::ParseConfig(SourceConfiguration::Configuration& config,
});
}
LOG_TRACE(Audio_DSP, "enqueuing embedded addr={:#010x} len={} id={} start={}",
config.physical_address, config.length, config.buffer_id,
static_cast<u32>(config.play_position));
static_cast<u32>(config.physical_address), static_cast<u32>(config.length),
config.buffer_id, static_cast<u32>(config.play_position));
}
if (config.loop_related_dirty && config.loop_related != 0) {
@ -303,7 +304,8 @@ void Source::ParseConfig(SourceConfiguration::Configuration& config,
});
}
LOG_TRACE(Audio_DSP, "enqueuing queued {} addr={:#010x} len={} id={}", i,
b.physical_address, b.length, b.buffer_id);
static_cast<u32>(b.physical_address), static_cast<u32>(b.length),
b.buffer_id);
}
}
config.buffers_dirty = 0;

View File

@ -47,7 +47,7 @@ TimingEventType* Timing::RegisterEvent(const std::string& name, TimedCallback ca
}
void Timing::ScheduleEvent(s64 cycles_into_future, const TimingEventType* event_type,
std::uintptr_t user_data, std::size_t core_id) {
std::uintptr_t user_data, std::size_t core_id, bool thread_safe_mode) {
if (event_queue_locked) {
return;
}
@ -61,18 +61,29 @@ void Timing::ScheduleEvent(s64 cycles_into_future, const TimingEventType* event_
timer = timers.at(core_id).get();
}
s64 timeout = timer->GetTicks() + cycles_into_future;
if (current_timer == timer) {
// If this event needs to be scheduled before the next advance(), force one early
if (!timer->is_timer_sane)
timer->ForceExceptionCheck(cycles_into_future);
if (thread_safe_mode) {
// Events scheduled in thread safe mode come after blocking operations with
// unpredictable timings in the host machine, so there is no need to be cycle accurate.
// To prevent the event from scheduling before the next advance(), we set a minimum time
// of MAX_SLICE_LENGTH * 2 cycles into the future.
cycles_into_future = std::max(static_cast<s64>(MAX_SLICE_LENGTH * 2), cycles_into_future);
timer->event_queue.emplace_back(
Event{timeout, timer->event_fifo_id++, user_data, event_type});
std::push_heap(timer->event_queue.begin(), timer->event_queue.end(), std::greater<>());
} else {
timer->ts_queue.Push(Event{static_cast<s64>(timer->GetTicks() + cycles_into_future), 0,
user_data, event_type});
} else {
s64 timeout = timer->GetTicks() + cycles_into_future;
if (current_timer == timer) {
// If this event needs to be scheduled before the next advance(), force one early
if (!timer->is_timer_sane)
timer->ForceExceptionCheck(cycles_into_future);
timer->event_queue.emplace_back(
Event{timeout, timer->event_fifo_id++, user_data, event_type});
std::push_heap(timer->event_queue.begin(), timer->event_queue.end(), std::greater<>());
} else {
timer->ts_queue.Push(Event{static_cast<s64>(timer->GetTicks() + cycles_into_future), 0,
user_data, event_type});
}
}
}

View File

@ -254,9 +254,12 @@ public:
*/
TimingEventType* RegisterEvent(const std::string& name, TimedCallback callback);
// Make sure to use thread_safe_mode = true if called from a different thread than the
// emulator thread, such as coroutines.
void ScheduleEvent(s64 cycles_into_future, const TimingEventType* event_type,
std::uintptr_t user_data = 0,
std::size_t core_id = std::numeric_limits<std::size_t>::max());
std::size_t core_id = std::numeric_limits<std::size_t>::max(),
bool thread_safe_mode = false);
void UnscheduleEvent(const TimingEventType* event_type, std::uintptr_t user_data);

View File

@ -7,6 +7,7 @@
#include <algorithm>
#include <array>
#include <chrono>
#include <future>
#include <memory>
#include <string>
#include <vector>
@ -247,6 +248,76 @@ public:
std::chrono::nanoseconds timeout,
std::shared_ptr<WakeupCallback> callback);
private:
template <typename ResultFunctor>
class AsyncWakeUpCallback : public WakeupCallback {
public:
explicit AsyncWakeUpCallback(ResultFunctor res_functor, std::future<void> fut)
: functor(res_functor) {
future = std::move(fut);
}
void WakeUp(std::shared_ptr<Kernel::Thread> thread, Kernel::HLERequestContext& ctx,
Kernel::ThreadWakeupReason reason) {
functor(ctx);
}
private:
ResultFunctor functor;
std::future<void> future;
template <class Archive>
void serialize(Archive& ar, const unsigned int) {
if (!Archive::is_loading::value && future.valid()) {
future.wait();
}
ar& functor;
}
friend class boost::serialization::access;
};
public:
/**
* Puts the game thread to sleep and calls the specified async_section asynchronously.
* Once the execution of the async section finishes, result_function is called. Use this
* mechanism to run blocking IO operations, so that other game threads are allowed to run
* while the one performing the blocking operation waits.
* @param async_section Callable that takes Kernel::HLERequestContext& as argument
* and returns the amount of nanoseconds to wait before calling result_function.
* This callable is ran asynchronously.
* @param result_function Callable that takes Kernel::HLERequestContext& as argument
* and doesn't return anything. This callable is ran from the emulator thread
* and can be used to set the IPC result.
* @param really_async If set to false, it will call both async_section and result_function
* from the emulator thread.
*/
template <typename AsyncFunctor, typename ResultFunctor>
void RunAsync(AsyncFunctor async_section, ResultFunctor result_function,
bool really_async = true) {
if (really_async) {
this->SleepClientThread(
"RunAsync", std::chrono::nanoseconds(-1),
std::make_shared<AsyncWakeUpCallback<ResultFunctor>>(
result_function,
std::move(std::async(std::launch::async, [this, async_section] {
s64 sleep_for = async_section(*this);
this->thread->WakeAfterDelay(sleep_for, true);
}))));
} else {
s64 sleep_for = async_section(*this);
if (sleep_for > 0) {
auto parallel_wakeup = std::make_shared<AsyncWakeUpCallback<ResultFunctor>>(
result_function, std::move(std::future<void>()));
this->SleepClientThread("RunAsync", std::chrono::nanoseconds(sleep_for),
parallel_wakeup);
} else {
result_function(*this);
}
}
}
/**
* Resolves a object id from the request command buffer into a pointer to an object. See the
* "HLE handle protocol" section in the class documentation for more details.

View File

@ -244,13 +244,15 @@ void ThreadManager::ThreadWakeupCallback(u64 thread_id, s64 cycles_late) {
thread->ResumeFromWait();
}
void Thread::WakeAfterDelay(s64 nanoseconds) {
void Thread::WakeAfterDelay(s64 nanoseconds, bool thread_safe_mode) {
// Don't schedule a wakeup if the thread wants to wait forever
if (nanoseconds == -1)
return;
size_t core = thread_safe_mode ? core_id : std::numeric_limits<std::size_t>::max();
thread_manager.kernel.timing.ScheduleEvent(nsToCycles(nanoseconds),
thread_manager.ThreadWakeupEventType, thread_id);
thread_manager.ThreadWakeupEventType, thread_id,
core, thread_safe_mode);
}
void Thread::ResumeFromWait() {

View File

@ -238,8 +238,10 @@ public:
/**
* Schedules an event to wake up the specified thread after the specified delay
* @param nanoseconds The time this thread will be allowed to sleep for
* @param thread_safe_mode Set to true if called from a different thread than the emulator
* thread, such as coroutines.
*/
void WakeAfterDelay(s64 nanoseconds);
void WakeAfterDelay(s64 nanoseconds, bool thread_safe_mode = false);
/**
* Sets the result after the thread awakens (from either WaitSynchronization SVC)