early-access version 3232
This commit is contained in:
parent
997f157033
commit
a47b53e126
9 changed files with 147 additions and 378 deletions
|
@ -1,7 +1,7 @@
|
||||||
yuzu emulator early access
|
yuzu emulator early access
|
||||||
=============
|
=============
|
||||||
|
|
||||||
This is the source code for early-access 3231.
|
This is the source code for early-access 3232.
|
||||||
|
|
||||||
## Legal Notice
|
## Legal Notice
|
||||||
|
|
||||||
|
|
|
@ -183,26 +183,20 @@ struct System::Impl {
|
||||||
Initialize(system);
|
Initialize(system);
|
||||||
}
|
}
|
||||||
|
|
||||||
SystemResultStatus Run() {
|
void Run() {
|
||||||
std::unique_lock<std::mutex> lk(suspend_guard);
|
std::unique_lock<std::mutex> lk(suspend_guard);
|
||||||
status = SystemResultStatus::Success;
|
|
||||||
|
|
||||||
kernel.Suspend(false);
|
kernel.Suspend(false);
|
||||||
core_timing.SyncPause(false);
|
core_timing.SyncPause(false);
|
||||||
is_paused.store(false, std::memory_order_relaxed);
|
is_paused.store(false, std::memory_order_relaxed);
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SystemResultStatus Pause() {
|
void Pause() {
|
||||||
std::unique_lock<std::mutex> lk(suspend_guard);
|
std::unique_lock<std::mutex> lk(suspend_guard);
|
||||||
status = SystemResultStatus::Success;
|
|
||||||
|
|
||||||
core_timing.SyncPause(true);
|
core_timing.SyncPause(true);
|
||||||
kernel.Suspend(true);
|
kernel.Suspend(true);
|
||||||
is_paused.store(true, std::memory_order_relaxed);
|
is_paused.store(true, std::memory_order_relaxed);
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsPaused() const {
|
bool IsPaused() const {
|
||||||
|
@ -553,12 +547,12 @@ void System::Initialize() {
|
||||||
impl->Initialize(*this);
|
impl->Initialize(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
SystemResultStatus System::Run() {
|
void System::Run() {
|
||||||
return impl->Run();
|
impl->Run();
|
||||||
}
|
}
|
||||||
|
|
||||||
SystemResultStatus System::Pause() {
|
void System::Pause() {
|
||||||
return impl->Pause();
|
impl->Pause();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool System::IsPaused() const {
|
bool System::IsPaused() const {
|
||||||
|
|
|
@ -152,13 +152,13 @@ public:
|
||||||
* Run the OS and Application
|
* Run the OS and Application
|
||||||
* This function will start emulation and run the relevant devices
|
* This function will start emulation and run the relevant devices
|
||||||
*/
|
*/
|
||||||
[[nodiscard]] SystemResultStatus Run();
|
void Run();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pause the OS and Application
|
* Pause the OS and Application
|
||||||
* This function will pause emulation and stop the relevant devices
|
* This function will pause emulation and stop the relevant devices
|
||||||
*/
|
*/
|
||||||
[[nodiscard]] SystemResultStatus Pause();
|
void Pause();
|
||||||
|
|
||||||
/// Check if the core is currently paused.
|
/// Check if the core is currently paused.
|
||||||
[[nodiscard]] bool IsPaused() const;
|
[[nodiscard]] bool IsPaused() const;
|
||||||
|
|
|
@ -200,12 +200,6 @@ bool MappingFactory::IsDriverValid(const MappingData& data) const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// The following drivers don't need to be mapped
|
// The following drivers don't need to be mapped
|
||||||
if (data.engine == "tas") {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (data.engine == "touch") {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (data.engine == "touch_from_button") {
|
if (data.engine == "touch_from_button") {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,79 +26,33 @@
|
||||||
namespace InputCommon {
|
namespace InputCommon {
|
||||||
|
|
||||||
struct InputSubsystem::Impl {
|
struct InputSubsystem::Impl {
|
||||||
void Initialize() {
|
template <typename Engine>
|
||||||
mapping_factory = std::make_shared<MappingFactory>();
|
void RegisterEngine(std::string name, std::shared_ptr<Engine>& engine) {
|
||||||
MappingCallback mapping_callback{[this](const MappingData& data) { RegisterInput(data); }};
|
MappingCallback mapping_callback{[this](const MappingData& data) { RegisterInput(data); }};
|
||||||
|
|
||||||
keyboard = std::make_shared<Keyboard>("keyboard");
|
engine = std::make_shared<Engine>(name);
|
||||||
keyboard->SetMappingCallback(mapping_callback);
|
engine->SetMappingCallback(mapping_callback);
|
||||||
keyboard_factory = std::make_shared<InputFactory>(keyboard);
|
|
||||||
keyboard_output_factory = std::make_shared<OutputFactory>(keyboard);
|
|
||||||
Common::Input::RegisterInputFactory(keyboard->GetEngineName(), keyboard_factory);
|
|
||||||
Common::Input::RegisterOutputFactory(keyboard->GetEngineName(), keyboard_output_factory);
|
|
||||||
|
|
||||||
mouse = std::make_shared<Mouse>("mouse");
|
std::shared_ptr<InputFactory> input_factory = std::make_shared<InputFactory>(engine);
|
||||||
mouse->SetMappingCallback(mapping_callback);
|
std::shared_ptr<OutputFactory> output_factory = std::make_shared<OutputFactory>(engine);
|
||||||
mouse_factory = std::make_shared<InputFactory>(mouse);
|
Common::Input::RegisterInputFactory(engine->GetEngineName(), std::move(input_factory));
|
||||||
mouse_output_factory = std::make_shared<OutputFactory>(mouse);
|
Common::Input::RegisterOutputFactory(engine->GetEngineName(), std::move(output_factory));
|
||||||
Common::Input::RegisterInputFactory(mouse->GetEngineName(), mouse_factory);
|
}
|
||||||
Common::Input::RegisterOutputFactory(mouse->GetEngineName(), mouse_output_factory);
|
|
||||||
|
|
||||||
touch_screen = std::make_shared<TouchScreen>("touch");
|
void Initialize() {
|
||||||
touch_screen_factory = std::make_shared<InputFactory>(touch_screen);
|
mapping_factory = std::make_shared<MappingFactory>();
|
||||||
Common::Input::RegisterInputFactory(touch_screen->GetEngineName(), touch_screen_factory);
|
|
||||||
|
|
||||||
gcadapter = std::make_shared<GCAdapter>("gcpad");
|
|
||||||
gcadapter->SetMappingCallback(mapping_callback);
|
|
||||||
gcadapter_input_factory = std::make_shared<InputFactory>(gcadapter);
|
|
||||||
gcadapter_output_factory = std::make_shared<OutputFactory>(gcadapter);
|
|
||||||
Common::Input::RegisterInputFactory(gcadapter->GetEngineName(), gcadapter_input_factory);
|
|
||||||
Common::Input::RegisterOutputFactory(gcadapter->GetEngineName(), gcadapter_output_factory);
|
|
||||||
|
|
||||||
udp_client = std::make_shared<CemuhookUDP::UDPClient>("cemuhookudp");
|
|
||||||
udp_client->SetMappingCallback(mapping_callback);
|
|
||||||
udp_client_input_factory = std::make_shared<InputFactory>(udp_client);
|
|
||||||
udp_client_output_factory = std::make_shared<OutputFactory>(udp_client);
|
|
||||||
Common::Input::RegisterInputFactory(udp_client->GetEngineName(), udp_client_input_factory);
|
|
||||||
Common::Input::RegisterOutputFactory(udp_client->GetEngineName(),
|
|
||||||
udp_client_output_factory);
|
|
||||||
|
|
||||||
tas_input = std::make_shared<TasInput::Tas>("tas");
|
|
||||||
tas_input->SetMappingCallback(mapping_callback);
|
|
||||||
tas_input_factory = std::make_shared<InputFactory>(tas_input);
|
|
||||||
tas_output_factory = std::make_shared<OutputFactory>(tas_input);
|
|
||||||
Common::Input::RegisterInputFactory(tas_input->GetEngineName(), tas_input_factory);
|
|
||||||
Common::Input::RegisterOutputFactory(tas_input->GetEngineName(), tas_output_factory);
|
|
||||||
|
|
||||||
camera = std::make_shared<Camera>("camera");
|
|
||||||
camera->SetMappingCallback(mapping_callback);
|
|
||||||
camera_input_factory = std::make_shared<InputFactory>(camera);
|
|
||||||
camera_output_factory = std::make_shared<OutputFactory>(camera);
|
|
||||||
Common::Input::RegisterInputFactory(camera->GetEngineName(), camera_input_factory);
|
|
||||||
Common::Input::RegisterOutputFactory(camera->GetEngineName(), camera_output_factory);
|
|
||||||
|
|
||||||
virtual_amiibo = std::make_shared<VirtualAmiibo>("virtual_amiibo");
|
|
||||||
virtual_amiibo->SetMappingCallback(mapping_callback);
|
|
||||||
virtual_amiibo_input_factory = std::make_shared<InputFactory>(virtual_amiibo);
|
|
||||||
virtual_amiibo_output_factory = std::make_shared<OutputFactory>(virtual_amiibo);
|
|
||||||
Common::Input::RegisterInputFactory(virtual_amiibo->GetEngineName(),
|
|
||||||
virtual_amiibo_input_factory);
|
|
||||||
Common::Input::RegisterOutputFactory(virtual_amiibo->GetEngineName(),
|
|
||||||
virtual_amiibo_output_factory);
|
|
||||||
|
|
||||||
virtual_gamepad = std::make_shared<VirtualGamepad>("virtual_gamepad");
|
|
||||||
virtual_gamepad->SetMappingCallback(mapping_callback);
|
|
||||||
virtual_gamepad_input_factory = std::make_shared<InputFactory>(virtual_gamepad);
|
|
||||||
Common::Input::RegisterInputFactory(virtual_gamepad->GetEngineName(),
|
|
||||||
virtual_gamepad_input_factory);
|
|
||||||
|
|
||||||
|
RegisterEngine("keyboard", keyboard);
|
||||||
|
RegisterEngine("mouse", mouse);
|
||||||
|
RegisterEngine("touch", touch_screen);
|
||||||
|
RegisterEngine("gcpad", gcadapter);
|
||||||
|
RegisterEngine("cemuhookudp", udp_client);
|
||||||
|
RegisterEngine("tas", tas_input);
|
||||||
|
RegisterEngine("camera", camera);
|
||||||
|
RegisterEngine("virtual_amiibo", virtual_amiibo);
|
||||||
|
RegisterEngine("virtual_gamepad", virtual_gamepad);
|
||||||
#ifdef HAVE_SDL2
|
#ifdef HAVE_SDL2
|
||||||
sdl = std::make_shared<SDLDriver>("sdl");
|
RegisterEngine("sdl", sdl);
|
||||||
sdl->SetMappingCallback(mapping_callback);
|
|
||||||
sdl_input_factory = std::make_shared<InputFactory>(sdl);
|
|
||||||
sdl_output_factory = std::make_shared<OutputFactory>(sdl);
|
|
||||||
Common::Input::RegisterInputFactory(sdl->GetEngineName(), sdl_input_factory);
|
|
||||||
Common::Input::RegisterOutputFactory(sdl->GetEngineName(), sdl_output_factory);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Common::Input::RegisterInputFactory("touch_from_button",
|
Common::Input::RegisterInputFactory("touch_from_button",
|
||||||
|
@ -107,45 +61,25 @@ struct InputSubsystem::Impl {
|
||||||
std::make_shared<StickFromButton>());
|
std::make_shared<StickFromButton>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Engine>
|
||||||
|
void UnregisterEngine(std::shared_ptr<Engine>& engine) {
|
||||||
|
Common::Input::UnregisterInputFactory(engine->GetEngineName());
|
||||||
|
Common::Input::UnregisterOutputFactory(engine->GetEngineName());
|
||||||
|
engine.reset();
|
||||||
|
}
|
||||||
|
|
||||||
void Shutdown() {
|
void Shutdown() {
|
||||||
Common::Input::UnregisterInputFactory(keyboard->GetEngineName());
|
UnregisterEngine(keyboard);
|
||||||
Common::Input::UnregisterOutputFactory(keyboard->GetEngineName());
|
UnregisterEngine(mouse);
|
||||||
keyboard.reset();
|
UnregisterEngine(touch_screen);
|
||||||
|
UnregisterEngine(gcadapter);
|
||||||
Common::Input::UnregisterInputFactory(mouse->GetEngineName());
|
UnregisterEngine(udp_client);
|
||||||
Common::Input::UnregisterOutputFactory(mouse->GetEngineName());
|
UnregisterEngine(tas_input);
|
||||||
mouse.reset();
|
UnregisterEngine(camera);
|
||||||
|
UnregisterEngine(virtual_amiibo);
|
||||||
Common::Input::UnregisterInputFactory(touch_screen->GetEngineName());
|
UnregisterEngine(virtual_gamepad);
|
||||||
touch_screen.reset();
|
|
||||||
|
|
||||||
Common::Input::UnregisterInputFactory(gcadapter->GetEngineName());
|
|
||||||
Common::Input::UnregisterOutputFactory(gcadapter->GetEngineName());
|
|
||||||
gcadapter.reset();
|
|
||||||
|
|
||||||
Common::Input::UnregisterInputFactory(udp_client->GetEngineName());
|
|
||||||
Common::Input::UnregisterOutputFactory(udp_client->GetEngineName());
|
|
||||||
udp_client.reset();
|
|
||||||
|
|
||||||
Common::Input::UnregisterInputFactory(tas_input->GetEngineName());
|
|
||||||
Common::Input::UnregisterOutputFactory(tas_input->GetEngineName());
|
|
||||||
tas_input.reset();
|
|
||||||
|
|
||||||
Common::Input::UnregisterInputFactory(camera->GetEngineName());
|
|
||||||
Common::Input::UnregisterOutputFactory(camera->GetEngineName());
|
|
||||||
camera.reset();
|
|
||||||
|
|
||||||
Common::Input::UnregisterInputFactory(virtual_amiibo->GetEngineName());
|
|
||||||
Common::Input::UnregisterOutputFactory(virtual_amiibo->GetEngineName());
|
|
||||||
virtual_amiibo.reset();
|
|
||||||
|
|
||||||
Common::Input::UnregisterInputFactory(virtual_gamepad->GetEngineName());
|
|
||||||
virtual_gamepad.reset();
|
|
||||||
|
|
||||||
#ifdef HAVE_SDL2
|
#ifdef HAVE_SDL2
|
||||||
Common::Input::UnregisterInputFactory(sdl->GetEngineName());
|
UnregisterEngine(sdl);
|
||||||
Common::Input::UnregisterOutputFactory(sdl->GetEngineName());
|
|
||||||
sdl.reset();
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Common::Input::UnregisterInputFactory("touch_from_button");
|
Common::Input::UnregisterInputFactory("touch_from_button");
|
||||||
|
@ -173,119 +107,88 @@ struct InputSubsystem::Impl {
|
||||||
return devices;
|
return devices;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] AnalogMapping GetAnalogMappingForDevice(
|
[[nodiscard]] std::shared_ptr<InputEngine> GetInputEngine(
|
||||||
const Common::ParamPackage& params) const {
|
const Common::ParamPackage& params) const {
|
||||||
if (!params.Has("engine") || params.Get("engine", "") == "any") {
|
if (!params.Has("engine") || params.Get("engine", "") == "any") {
|
||||||
return {};
|
return nullptr;
|
||||||
}
|
}
|
||||||
const std::string engine = params.Get("engine", "");
|
const std::string engine = params.Get("engine", "");
|
||||||
|
if (engine == keyboard->GetEngineName()) {
|
||||||
|
return keyboard;
|
||||||
|
}
|
||||||
if (engine == mouse->GetEngineName()) {
|
if (engine == mouse->GetEngineName()) {
|
||||||
return mouse->GetAnalogMappingForDevice(params);
|
return mouse;
|
||||||
}
|
}
|
||||||
if (engine == gcadapter->GetEngineName()) {
|
if (engine == gcadapter->GetEngineName()) {
|
||||||
return gcadapter->GetAnalogMappingForDevice(params);
|
return gcadapter;
|
||||||
}
|
}
|
||||||
if (engine == udp_client->GetEngineName()) {
|
if (engine == udp_client->GetEngineName()) {
|
||||||
return udp_client->GetAnalogMappingForDevice(params);
|
return udp_client;
|
||||||
}
|
|
||||||
if (engine == tas_input->GetEngineName()) {
|
|
||||||
return tas_input->GetAnalogMappingForDevice(params);
|
|
||||||
}
|
}
|
||||||
#ifdef HAVE_SDL2
|
#ifdef HAVE_SDL2
|
||||||
if (engine == sdl->GetEngineName()) {
|
if (engine == sdl->GetEngineName()) {
|
||||||
return sdl->GetAnalogMappingForDevice(params);
|
return sdl;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] AnalogMapping GetAnalogMappingForDevice(
|
||||||
|
const Common::ParamPackage& params) const {
|
||||||
|
const auto input_engine = GetInputEngine(params);
|
||||||
|
|
||||||
|
if (input_engine == nullptr) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return input_engine->GetAnalogMappingForDevice(params);
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] ButtonMapping GetButtonMappingForDevice(
|
[[nodiscard]] ButtonMapping GetButtonMappingForDevice(
|
||||||
const Common::ParamPackage& params) const {
|
const Common::ParamPackage& params) const {
|
||||||
if (!params.Has("engine") || params.Get("engine", "") == "any") {
|
const auto input_engine = GetInputEngine(params);
|
||||||
|
|
||||||
|
if (input_engine == nullptr) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
const std::string engine = params.Get("engine", "");
|
|
||||||
if (engine == gcadapter->GetEngineName()) {
|
return input_engine->GetButtonMappingForDevice(params);
|
||||||
return gcadapter->GetButtonMappingForDevice(params);
|
|
||||||
}
|
|
||||||
if (engine == udp_client->GetEngineName()) {
|
|
||||||
return udp_client->GetButtonMappingForDevice(params);
|
|
||||||
}
|
|
||||||
if (engine == tas_input->GetEngineName()) {
|
|
||||||
return tas_input->GetButtonMappingForDevice(params);
|
|
||||||
}
|
|
||||||
#ifdef HAVE_SDL2
|
|
||||||
if (engine == sdl->GetEngineName()) {
|
|
||||||
return sdl->GetButtonMappingForDevice(params);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] MotionMapping GetMotionMappingForDevice(
|
[[nodiscard]] MotionMapping GetMotionMappingForDevice(
|
||||||
const Common::ParamPackage& params) const {
|
const Common::ParamPackage& params) const {
|
||||||
if (!params.Has("engine") || params.Get("engine", "") == "any") {
|
const auto input_engine = GetInputEngine(params);
|
||||||
|
|
||||||
|
if (input_engine == nullptr) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
const std::string engine = params.Get("engine", "");
|
|
||||||
if (engine == udp_client->GetEngineName()) {
|
return input_engine->GetMotionMappingForDevice(params);
|
||||||
return udp_client->GetMotionMappingForDevice(params);
|
|
||||||
}
|
|
||||||
#ifdef HAVE_SDL2
|
|
||||||
if (engine == sdl->GetEngineName()) {
|
|
||||||
return sdl->GetMotionMappingForDevice(params);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Common::Input::ButtonNames GetButtonName(const Common::ParamPackage& params) const {
|
Common::Input::ButtonNames GetButtonName(const Common::ParamPackage& params) const {
|
||||||
if (!params.Has("engine") || params.Get("engine", "") == "any") {
|
if (!params.Has("engine") || params.Get("engine", "") == "any") {
|
||||||
return Common::Input::ButtonNames::Undefined;
|
return Common::Input::ButtonNames::Undefined;
|
||||||
}
|
}
|
||||||
const std::string engine = params.Get("engine", "");
|
const auto input_engine = GetInputEngine(params);
|
||||||
if (engine == mouse->GetEngineName()) {
|
|
||||||
return mouse->GetUIName(params);
|
if (input_engine == nullptr) {
|
||||||
}
|
|
||||||
if (engine == gcadapter->GetEngineName()) {
|
|
||||||
return gcadapter->GetUIName(params);
|
|
||||||
}
|
|
||||||
if (engine == udp_client->GetEngineName()) {
|
|
||||||
return udp_client->GetUIName(params);
|
|
||||||
}
|
|
||||||
if (engine == tas_input->GetEngineName()) {
|
|
||||||
return tas_input->GetUIName(params);
|
|
||||||
}
|
|
||||||
#ifdef HAVE_SDL2
|
|
||||||
if (engine == sdl->GetEngineName()) {
|
|
||||||
return sdl->GetUIName(params);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return Common::Input::ButtonNames::Invalid;
|
return Common::Input::ButtonNames::Invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return input_engine->GetUIName(params);
|
||||||
|
}
|
||||||
|
|
||||||
bool IsStickInverted(const Common::ParamPackage& params) {
|
bool IsStickInverted(const Common::ParamPackage& params) {
|
||||||
const std::string engine = params.Get("engine", "");
|
const auto input_engine = GetInputEngine(params);
|
||||||
if (engine == mouse->GetEngineName()) {
|
|
||||||
return mouse->IsStickInverted(params);
|
if (input_engine == nullptr) {
|
||||||
}
|
|
||||||
if (engine == gcadapter->GetEngineName()) {
|
|
||||||
return gcadapter->IsStickInverted(params);
|
|
||||||
}
|
|
||||||
if (engine == udp_client->GetEngineName()) {
|
|
||||||
return udp_client->IsStickInverted(params);
|
|
||||||
}
|
|
||||||
if (engine == tas_input->GetEngineName()) {
|
|
||||||
return tas_input->IsStickInverted(params);
|
|
||||||
}
|
|
||||||
#ifdef HAVE_SDL2
|
|
||||||
if (engine == sdl->GetEngineName()) {
|
|
||||||
return sdl->IsStickInverted(params);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return input_engine->IsStickInverted(params);
|
||||||
|
}
|
||||||
|
|
||||||
bool IsController(const Common::ParamPackage& params) {
|
bool IsController(const Common::ParamPackage& params) {
|
||||||
const std::string engine = params.Get("engine", "");
|
const std::string engine = params.Get("engine", "");
|
||||||
if (engine == mouse->GetEngineName()) {
|
if (engine == mouse->GetEngineName()) {
|
||||||
|
@ -353,28 +256,8 @@ struct InputSubsystem::Impl {
|
||||||
std::shared_ptr<VirtualAmiibo> virtual_amiibo;
|
std::shared_ptr<VirtualAmiibo> virtual_amiibo;
|
||||||
std::shared_ptr<VirtualGamepad> virtual_gamepad;
|
std::shared_ptr<VirtualGamepad> virtual_gamepad;
|
||||||
|
|
||||||
std::shared_ptr<InputFactory> keyboard_factory;
|
|
||||||
std::shared_ptr<InputFactory> mouse_factory;
|
|
||||||
std::shared_ptr<InputFactory> gcadapter_input_factory;
|
|
||||||
std::shared_ptr<InputFactory> touch_screen_factory;
|
|
||||||
std::shared_ptr<InputFactory> udp_client_input_factory;
|
|
||||||
std::shared_ptr<InputFactory> tas_input_factory;
|
|
||||||
std::shared_ptr<InputFactory> camera_input_factory;
|
|
||||||
std::shared_ptr<InputFactory> virtual_amiibo_input_factory;
|
|
||||||
std::shared_ptr<InputFactory> virtual_gamepad_input_factory;
|
|
||||||
|
|
||||||
std::shared_ptr<OutputFactory> keyboard_output_factory;
|
|
||||||
std::shared_ptr<OutputFactory> mouse_output_factory;
|
|
||||||
std::shared_ptr<OutputFactory> gcadapter_output_factory;
|
|
||||||
std::shared_ptr<OutputFactory> udp_client_output_factory;
|
|
||||||
std::shared_ptr<OutputFactory> tas_output_factory;
|
|
||||||
std::shared_ptr<OutputFactory> camera_output_factory;
|
|
||||||
std::shared_ptr<OutputFactory> virtual_amiibo_output_factory;
|
|
||||||
|
|
||||||
#ifdef HAVE_SDL2
|
#ifdef HAVE_SDL2
|
||||||
std::shared_ptr<SDLDriver> sdl;
|
std::shared_ptr<SDLDriver> sdl;
|
||||||
std::shared_ptr<InputFactory> sdl_input_factory;
|
|
||||||
std::shared_ptr<OutputFactory> sdl_output_factory;
|
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -46,30 +46,28 @@
|
||||||
|
|
||||||
static Core::Frontend::WindowSystemType GetWindowSystemType();
|
static Core::Frontend::WindowSystemType GetWindowSystemType();
|
||||||
|
|
||||||
EmuThread::EmuThread(Core::System& system_) : system{system_} {}
|
EmuThread::EmuThread(Core::System& system) : m_system{system} {}
|
||||||
|
|
||||||
EmuThread::~EmuThread() = default;
|
EmuThread::~EmuThread() = default;
|
||||||
|
|
||||||
void EmuThread::run() {
|
void EmuThread::run() {
|
||||||
std::string name = "EmuControlThread";
|
const char* name = "EmuControlThread";
|
||||||
MicroProfileOnThreadCreate(name.c_str());
|
MicroProfileOnThreadCreate(name);
|
||||||
Common::SetCurrentThreadName(name.c_str());
|
Common::SetCurrentThreadName(name);
|
||||||
|
|
||||||
auto& gpu = system.GPU();
|
auto& gpu = m_system.GPU();
|
||||||
auto stop_token = stop_source.get_token();
|
auto stop_token = m_stop_source.get_token();
|
||||||
bool debugger_should_start = system.DebuggerEnabled();
|
|
||||||
|
|
||||||
system.RegisterHostThread();
|
m_system.RegisterHostThread();
|
||||||
|
|
||||||
// Main process has been loaded. Make the context current to this thread and begin GPU and CPU
|
// Main process has been loaded. Make the context current to this thread and begin GPU and CPU
|
||||||
// execution.
|
// execution.
|
||||||
gpu.ObtainContext();
|
gpu.ObtainContext();
|
||||||
|
|
||||||
emit LoadProgress(VideoCore::LoadCallbackStage::Prepare, 0, 0);
|
emit LoadProgress(VideoCore::LoadCallbackStage::Prepare, 0, 0);
|
||||||
|
|
||||||
if (Settings::values.use_disk_shader_cache.GetValue()) {
|
if (Settings::values.use_disk_shader_cache.GetValue()) {
|
||||||
system.Renderer().ReadRasterizer()->LoadDiskResources(
|
m_system.Renderer().ReadRasterizer()->LoadDiskResources(
|
||||||
system.GetCurrentProcessProgramID(), stop_token,
|
m_system.GetCurrentProcessProgramID(), stop_token,
|
||||||
[this](VideoCore::LoadCallbackStage stage, std::size_t value, std::size_t total) {
|
[this](VideoCore::LoadCallbackStage stage, std::size_t value, std::size_t total) {
|
||||||
emit LoadProgress(stage, value, total);
|
emit LoadProgress(stage, value, total);
|
||||||
});
|
});
|
||||||
|
@ -79,57 +77,35 @@ void EmuThread::run() {
|
||||||
gpu.ReleaseContext();
|
gpu.ReleaseContext();
|
||||||
gpu.Start();
|
gpu.Start();
|
||||||
|
|
||||||
system.GetCpuManager().OnGpuReady();
|
m_system.GetCpuManager().OnGpuReady();
|
||||||
|
m_system.RegisterExitCallback([this] { m_stop_source.request_stop(); });
|
||||||
|
|
||||||
system.RegisterExitCallback([this]() {
|
if (m_system.DebuggerEnabled()) {
|
||||||
stop_source.request_stop();
|
m_system.InitializeDebugger();
|
||||||
SetRunning(false);
|
}
|
||||||
});
|
|
||||||
|
|
||||||
// Holds whether the cpu was running during the last iteration,
|
|
||||||
// so that the DebugModeLeft signal can be emitted before the
|
|
||||||
// next execution step
|
|
||||||
bool was_active = false;
|
|
||||||
while (!stop_token.stop_requested()) {
|
while (!stop_token.stop_requested()) {
|
||||||
if (running) {
|
std::unique_lock lk{m_should_run_mutex};
|
||||||
if (was_active) {
|
if (m_should_run) {
|
||||||
emit DebugModeLeft();
|
m_system.Run();
|
||||||
}
|
m_is_running.store(true);
|
||||||
|
m_is_running.notify_all();
|
||||||
|
|
||||||
running_guard = true;
|
Common::CondvarWait(m_should_run_cv, lk, stop_token, [&] { return !m_should_run; });
|
||||||
Core::SystemResultStatus result = system.Run();
|
|
||||||
if (result != Core::SystemResultStatus::Success) {
|
|
||||||
running_guard = false;
|
|
||||||
this->SetRunning(false);
|
|
||||||
emit ErrorThrown(result, system.GetStatusDetails());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (debugger_should_start) {
|
|
||||||
system.InitializeDebugger();
|
|
||||||
debugger_should_start = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
running_wait.Wait();
|
|
||||||
result = system.Pause();
|
|
||||||
if (result != Core::SystemResultStatus::Success) {
|
|
||||||
running_guard = false;
|
|
||||||
this->SetRunning(false);
|
|
||||||
emit ErrorThrown(result, system.GetStatusDetails());
|
|
||||||
}
|
|
||||||
running_guard = false;
|
|
||||||
|
|
||||||
if (!stop_token.stop_requested()) {
|
|
||||||
was_active = true;
|
|
||||||
emit DebugModeEntered();
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
std::unique_lock lock{running_mutex};
|
m_system.Pause();
|
||||||
Common::CondvarWait(running_cv, lock, stop_token, [&] { return IsRunning(); });
|
m_is_running.store(false);
|
||||||
|
m_is_running.notify_all();
|
||||||
|
|
||||||
|
emit DebugModeEntered();
|
||||||
|
Common::CondvarWait(m_should_run_cv, lk, stop_token, [&] { return m_should_run; });
|
||||||
|
emit DebugModeLeft();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shutdown the main emulated process
|
// Shutdown the main emulated process
|
||||||
system.ShutdownMainProcess();
|
m_system.DetachDebugger();
|
||||||
|
m_system.ShutdownMainProcess();
|
||||||
|
|
||||||
#if MICROPROFILE_ENABLED
|
#if MICROPROFILE_ENABLED
|
||||||
MicroProfileOnThreadExit();
|
MicroProfileOnThreadExit();
|
||||||
|
|
|
@ -47,7 +47,7 @@ class EmuThread final : public QThread {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit EmuThread(Core::System& system_);
|
explicit EmuThread(Core::System& system);
|
||||||
~EmuThread() override;
|
~EmuThread() override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -57,30 +57,30 @@ public:
|
||||||
void run() override;
|
void run() override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets whether the emulation thread is running or not
|
* Sets whether the emulation thread should run or not
|
||||||
* @param running_ Boolean value, set the emulation thread to running if true
|
* @param should_run Boolean value, set the emulation thread to running if true
|
||||||
* @note This function is thread-safe
|
|
||||||
*/
|
*/
|
||||||
void SetRunning(bool running_) {
|
void SetRunning(bool should_run) {
|
||||||
std::unique_lock lock{running_mutex};
|
// TODO: Prevent other threads from modifying the state until we finish.
|
||||||
running = running_;
|
{
|
||||||
lock.unlock();
|
// Notify the running thread to change state.
|
||||||
running_cv.notify_all();
|
std::unique_lock run_lk{m_should_run_mutex};
|
||||||
if (!running) {
|
m_should_run = should_run;
|
||||||
running_wait.Set();
|
m_should_run_cv.notify_one();
|
||||||
/// Wait until effectively paused
|
}
|
||||||
while (running_guard)
|
|
||||||
;
|
// Wait until paused, if pausing.
|
||||||
|
if (!should_run) {
|
||||||
|
m_is_running.wait(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the emulation thread is running or not
|
* Check if the emulation thread is running or not
|
||||||
* @return True if the emulation thread is running, otherwise false
|
* @return True if the emulation thread is running, otherwise false
|
||||||
* @note This function is thread-safe
|
|
||||||
*/
|
*/
|
||||||
bool IsRunning() const {
|
bool IsRunning() const {
|
||||||
return running;
|
return m_is_running.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -88,18 +88,17 @@ public:
|
||||||
*/
|
*/
|
||||||
void ForceStop() {
|
void ForceStop() {
|
||||||
LOG_WARNING(Frontend, "Force stopping EmuThread");
|
LOG_WARNING(Frontend, "Force stopping EmuThread");
|
||||||
stop_source.request_stop();
|
m_stop_source.request_stop();
|
||||||
SetRunning(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool running = false;
|
Core::System& m_system;
|
||||||
std::stop_source stop_source;
|
|
||||||
std::mutex running_mutex;
|
std::stop_source m_stop_source;
|
||||||
std::condition_variable_any running_cv;
|
std::mutex m_should_run_mutex;
|
||||||
Common::Event running_wait{};
|
std::condition_variable_any m_should_run_cv;
|
||||||
std::atomic_bool running_guard{false};
|
std::atomic<bool> m_is_running{false};
|
||||||
Core::System& system;
|
bool m_should_run{true};
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
/**
|
/**
|
||||||
|
@ -120,8 +119,6 @@ signals:
|
||||||
*/
|
*/
|
||||||
void DebugModeLeft();
|
void DebugModeLeft();
|
||||||
|
|
||||||
void ErrorThrown(Core::SystemResultStatus, std::string);
|
|
||||||
|
|
||||||
void LoadProgress(VideoCore::LoadCallbackStage stage, std::size_t value, std::size_t total);
|
void LoadProgress(VideoCore::LoadCallbackStage stage, std::size_t value, std::size_t total);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1497,7 +1497,7 @@ void GMainWindow::SetupSigInterrupts() {
|
||||||
|
|
||||||
void GMainWindow::HandleSigInterrupt(int sig) {
|
void GMainWindow::HandleSigInterrupt(int sig) {
|
||||||
if (sig == SIGINT) {
|
if (sig == SIGINT) {
|
||||||
exit(1);
|
_exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calling into Qt directly from a signal handler is not safe,
|
// Calling into Qt directly from a signal handler is not safe,
|
||||||
|
@ -1793,15 +1793,16 @@ void GMainWindow::ShutdownGame() {
|
||||||
Settings::values.use_speed_limit.SetValue(true);
|
Settings::values.use_speed_limit.SetValue(true);
|
||||||
|
|
||||||
system->SetShuttingDown(true);
|
system->SetShuttingDown(true);
|
||||||
system->DetachDebugger();
|
|
||||||
discord_rpc->Pause();
|
discord_rpc->Pause();
|
||||||
|
|
||||||
RequestGameExit();
|
RequestGameExit();
|
||||||
|
emu_thread->disconnect();
|
||||||
|
emu_thread->SetRunning(true);
|
||||||
|
|
||||||
emit EmulationStopping();
|
emit EmulationStopping();
|
||||||
|
|
||||||
// Wait for emulation thread to complete and delete it
|
// Wait for emulation thread to complete and delete it
|
||||||
if (!emu_thread->wait(5000)) {
|
if (system->DebuggerEnabled() || !emu_thread->wait(5000)) {
|
||||||
emu_thread->ForceStop();
|
emu_thread->ForceStop();
|
||||||
emu_thread->wait();
|
emu_thread->wait();
|
||||||
}
|
}
|
||||||
|
@ -2918,8 +2919,6 @@ void GMainWindow::OnStartGame() {
|
||||||
|
|
||||||
emu_thread->SetRunning(true);
|
emu_thread->SetRunning(true);
|
||||||
|
|
||||||
connect(emu_thread.get(), &EmuThread::ErrorThrown, this, &GMainWindow::OnCoreError);
|
|
||||||
|
|
||||||
UpdateMenuState();
|
UpdateMenuState();
|
||||||
OnTasStateChanged();
|
OnTasStateChanged();
|
||||||
|
|
||||||
|
@ -3903,79 +3902,6 @@ void GMainWindow::OnMouseActivity() {
|
||||||
mouse_center_timer.stop();
|
mouse_center_timer.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GMainWindow::OnCoreError(Core::SystemResultStatus result, std::string details) {
|
|
||||||
QMessageBox::StandardButton answer;
|
|
||||||
QString status_message;
|
|
||||||
const QString common_message =
|
|
||||||
tr("The game you are trying to load requires additional files from your Switch to be "
|
|
||||||
"dumped "
|
|
||||||
"before playing.<br/><br/>For more information on dumping these files, please see the "
|
|
||||||
"following wiki page: <a "
|
|
||||||
"href='https://yuzu-emu.org/wiki/"
|
|
||||||
"dumping-system-archives-and-the-shared-fonts-from-a-switch-console/'>Dumping System "
|
|
||||||
"Archives and the Shared Fonts from a Switch Console</a>.<br/><br/>Would you like to "
|
|
||||||
"quit "
|
|
||||||
"back to the game list? Continuing emulation may result in crashes, corrupted save "
|
|
||||||
"data, or other bugs.");
|
|
||||||
switch (result) {
|
|
||||||
case Core::SystemResultStatus::ErrorSystemFiles: {
|
|
||||||
QString message;
|
|
||||||
if (details.empty()) {
|
|
||||||
message =
|
|
||||||
tr("yuzu was unable to locate a Switch system archive. %1").arg(common_message);
|
|
||||||
} else {
|
|
||||||
message = tr("yuzu was unable to locate a Switch system archive: %1. %2")
|
|
||||||
.arg(QString::fromStdString(details), common_message);
|
|
||||||
}
|
|
||||||
|
|
||||||
answer = QMessageBox::question(this, tr("System Archive Not Found"), message,
|
|
||||||
QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
|
|
||||||
status_message = tr("System Archive Missing");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case Core::SystemResultStatus::ErrorSharedFont: {
|
|
||||||
const QString message =
|
|
||||||
tr("yuzu was unable to locate the Switch shared fonts. %1").arg(common_message);
|
|
||||||
answer = QMessageBox::question(this, tr("Shared Fonts Not Found"), message,
|
|
||||||
QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
|
|
||||||
status_message = tr("Shared Font Missing");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
answer = QMessageBox::question(
|
|
||||||
this, tr("Fatal Error"),
|
|
||||||
tr("yuzu has encountered a fatal error, please see the log for more details. "
|
|
||||||
"For more information on accessing the log, please see the following page: "
|
|
||||||
"<a href='https://community.citra-emu.org/t/how-to-upload-the-log-file/296'>How "
|
|
||||||
"to "
|
|
||||||
"Upload the Log File</a>.<br/><br/>Would you like to quit back to the game "
|
|
||||||
"list? "
|
|
||||||
"Continuing emulation may result in crashes, corrupted save data, or other "
|
|
||||||
"bugs."),
|
|
||||||
QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
|
|
||||||
status_message = tr("Fatal Error encountered");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (answer == QMessageBox::Yes) {
|
|
||||||
if (emu_thread) {
|
|
||||||
ShutdownGame();
|
|
||||||
|
|
||||||
Settings::RestoreGlobalState(system->IsPoweredOn());
|
|
||||||
system->HIDCore().ReloadInputDevices();
|
|
||||||
UpdateStatusButtons();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Only show the message if the game is still running.
|
|
||||||
if (emu_thread) {
|
|
||||||
emu_thread->SetRunning(true);
|
|
||||||
message_label->setText(status_message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) {
|
void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) {
|
||||||
if (behavior == ReinitializeKeyBehavior::Warning) {
|
if (behavior == ReinitializeKeyBehavior::Warning) {
|
||||||
const auto res = QMessageBox::information(
|
const auto res = QMessageBox::information(
|
||||||
|
|
|
@ -332,7 +332,6 @@ private slots:
|
||||||
void ResetWindowSize900();
|
void ResetWindowSize900();
|
||||||
void ResetWindowSize1080();
|
void ResetWindowSize1080();
|
||||||
void OnCaptureScreenshot();
|
void OnCaptureScreenshot();
|
||||||
void OnCoreError(Core::SystemResultStatus, std::string);
|
|
||||||
void OnReinitializeKeys(ReinitializeKeyBehavior behavior);
|
void OnReinitializeKeys(ReinitializeKeyBehavior behavior);
|
||||||
void OnLanguageChanged(const QString& locale);
|
void OnLanguageChanged(const QString& locale);
|
||||||
void OnMouseActivity();
|
void OnMouseActivity();
|
||||||
|
|
Loading…
Reference in a new issue