Compare commits
35 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5deecd714b | |||
| 322339a5fd | |||
| bfac21fca1 | |||
| b86fcf7c31 | |||
| 940375dfbb | |||
| 410df5446e | |||
| 04f48f0120 | |||
| b9b28c0457 | |||
| 614702488f | |||
| dcc4685557 | |||
| 3031223153 | |||
| 5a3463bc2b | |||
| 11a9bff36d | |||
| be56587ad7 | |||
| 54f007efc6 | |||
| 50d8e753c5 | |||
| 51df96b7c0 | |||
| f966c05a74 | |||
| 564f105277 | |||
| ecefc932e6 | |||
| 157985f556 | |||
| 1624f307d0 | |||
| 50a19b07d1 | |||
| 5303161aa1 | |||
| 06ad463ec8 | |||
| 60928cf8cd | |||
| 72aa418b0b | |||
| 08674aee87 | |||
| 1e474fb9d1 | |||
| 0902119302 | |||
| 8532849439 | |||
| d7f4434bd5 | |||
| b96caf200d | |||
| 779f4ac72d | |||
| 2e5866147e |
+1
-1
@@ -167,7 +167,7 @@ macro(yuzu_find_packages)
|
||||
set(REQUIRED_LIBS
|
||||
# Cmake Pkg Prefix Version Conan Pkg
|
||||
"Catch2 2.13.7 catch2/2.13.7"
|
||||
"fmt 8.0 fmt/8.0.0"
|
||||
"fmt 8.0.1 fmt/8.0.1"
|
||||
"lz4 1.8 lz4/1.9.2"
|
||||
"nlohmann_json 3.8 nlohmann_json/3.8.0"
|
||||
"ZLIB 1.2 zlib/1.2.11"
|
||||
|
||||
@@ -604,6 +604,7 @@ struct Values {
|
||||
BasicSetting<bool> extended_logging{false, "extended_logging"};
|
||||
BasicSetting<bool> use_debug_asserts{false, "use_debug_asserts"};
|
||||
BasicSetting<bool> use_auto_stub{false, "use_auto_stub"};
|
||||
BasicSetting<bool> enable_all_controllers{false, "enable_all_controllers"};
|
||||
|
||||
// Miscellaneous
|
||||
BasicSetting<std::string> log_filter{"*:Info", "log_filter"};
|
||||
|
||||
@@ -370,6 +370,11 @@ enum class ControllerType {
|
||||
RightJoycon,
|
||||
Handheld,
|
||||
GameCube,
|
||||
Pokeball,
|
||||
NES,
|
||||
SNES,
|
||||
N64,
|
||||
SegaGenesis,
|
||||
};
|
||||
|
||||
struct PlayerInput {
|
||||
|
||||
@@ -479,6 +479,8 @@ add_library(core STATIC
|
||||
hle/service/ns/language.h
|
||||
hle/service/ns/ns.cpp
|
||||
hle/service/ns/ns.h
|
||||
hle/service/ns/pdm_qry.cpp
|
||||
hle/service/ns/pdm_qry.h
|
||||
hle/service/ns/pl_u.cpp
|
||||
hle/service/ns/pl_u.h
|
||||
hle/service/nvdrv/devices/nvdevice.h
|
||||
|
||||
@@ -78,9 +78,9 @@ struct ConsoleUpdateCallback {
|
||||
class EmulatedConsole {
|
||||
public:
|
||||
/**
|
||||
* Contains all input data related to the console like motion and touch input
|
||||
* Contains all input data within the emulated switch console tablet such as touch and motion
|
||||
*/
|
||||
EmulatedConsole();
|
||||
explicit EmulatedConsole();
|
||||
~EmulatedConsole();
|
||||
|
||||
YUZU_NON_COPYABLE(EmulatedConsole);
|
||||
@@ -89,14 +89,16 @@ public:
|
||||
/// Removes all callbacks created from input devices
|
||||
void UnloadInput();
|
||||
|
||||
/// Sets the emulated console into configuring mode. Locking all HID service events from being
|
||||
/// moddified
|
||||
/**
|
||||
* Sets the emulated console into configuring mode
|
||||
* This prevents the modification of the HID state of the emulated console by input commands
|
||||
*/
|
||||
void EnableConfiguration();
|
||||
|
||||
/// Returns the emulated console to the normal behaivour
|
||||
/// Returns the emulated console into normal mode, allowing the modification of the HID state
|
||||
void DisableConfiguration();
|
||||
|
||||
/// Returns true if the emulated console is on configuring mode
|
||||
/// Returns true if the emulated console is in configuring mode
|
||||
bool IsConfiguring() const;
|
||||
|
||||
/// Reload all input devices
|
||||
@@ -116,7 +118,7 @@ public:
|
||||
|
||||
/**
|
||||
* Updates the current mapped motion device
|
||||
* @param ParamPackage with controller data to be mapped
|
||||
* @param param ParamPackage with controller data to be mapped
|
||||
*/
|
||||
void SetMotionParam(Common::ParamPackage param);
|
||||
|
||||
@@ -134,14 +136,14 @@ public:
|
||||
|
||||
/**
|
||||
* Adds a callback to the list of events
|
||||
* @param ConsoleUpdateCallback that will be triggered
|
||||
* @param update_callback A ConsoleUpdateCallback that will be triggered
|
||||
* @return an unique key corresponding to the callback index in the list
|
||||
*/
|
||||
int SetCallback(ConsoleUpdateCallback update_callback);
|
||||
|
||||
/**
|
||||
* Removes a callback from the list stopping any future events to this object
|
||||
* @param Key corresponding to the callback index in the list
|
||||
* @param key Key corresponding to the callback index in the list
|
||||
*/
|
||||
void DeleteCallback(int key);
|
||||
|
||||
@@ -151,20 +153,20 @@ private:
|
||||
|
||||
/**
|
||||
* Updates the motion status of the console
|
||||
* @param A CallbackStatus containing gyro and accelerometer data
|
||||
* @param callback A CallbackStatus containing gyro and accelerometer data
|
||||
*/
|
||||
void SetMotion(Common::Input::CallbackStatus callback);
|
||||
|
||||
/**
|
||||
* Updates the touch status of the console
|
||||
* @param callback: A CallbackStatus containing the touch position
|
||||
* @param index: Finger ID to be updated
|
||||
* @param callback A CallbackStatus containing the touch position
|
||||
* @param index Finger ID to be updated
|
||||
*/
|
||||
void SetTouch(Common::Input::CallbackStatus callback, std::size_t index);
|
||||
|
||||
/**
|
||||
* Triggers a callback that something has changed on the console status
|
||||
* @param Input type of the event to trigger
|
||||
* @param type Input type of the event to trigger
|
||||
*/
|
||||
void TriggerOnChange(ConsoleTriggerType type);
|
||||
|
||||
|
||||
@@ -27,6 +27,16 @@ NpadStyleIndex EmulatedController::MapSettingsTypeToNPad(Settings::ControllerTyp
|
||||
return NpadStyleIndex::Handheld;
|
||||
case Settings::ControllerType::GameCube:
|
||||
return NpadStyleIndex::GameCube;
|
||||
case Settings::ControllerType::Pokeball:
|
||||
return NpadStyleIndex::Pokeball;
|
||||
case Settings::ControllerType::NES:
|
||||
return NpadStyleIndex::NES;
|
||||
case Settings::ControllerType::SNES:
|
||||
return NpadStyleIndex::SNES;
|
||||
case Settings::ControllerType::N64:
|
||||
return NpadStyleIndex::N64;
|
||||
case Settings::ControllerType::SegaGenesis:
|
||||
return NpadStyleIndex::SegaGenesis;
|
||||
default:
|
||||
return NpadStyleIndex::ProController;
|
||||
}
|
||||
@@ -46,6 +56,16 @@ Settings::ControllerType EmulatedController::MapNPadToSettingsType(NpadStyleInde
|
||||
return Settings::ControllerType::Handheld;
|
||||
case NpadStyleIndex::GameCube:
|
||||
return Settings::ControllerType::GameCube;
|
||||
case NpadStyleIndex::Pokeball:
|
||||
return Settings::ControllerType::Pokeball;
|
||||
case NpadStyleIndex::NES:
|
||||
return Settings::ControllerType::NES;
|
||||
case NpadStyleIndex::SNES:
|
||||
return Settings::ControllerType::SNES;
|
||||
case NpadStyleIndex::N64:
|
||||
return Settings::ControllerType::N64;
|
||||
case NpadStyleIndex::SegaGenesis:
|
||||
return Settings::ControllerType::SegaGenesis;
|
||||
default:
|
||||
return Settings::ControllerType::ProController;
|
||||
}
|
||||
|
||||
@@ -132,8 +132,8 @@ struct ControllerUpdateCallback {
|
||||
class EmulatedController {
|
||||
public:
|
||||
/**
|
||||
* Contains all input data related to this controller. Like buttons, joysticks, motion.
|
||||
* @param Npad id type for this specific controller
|
||||
* Contains all input data (buttons, joysticks, vibration, and motion) within this controller.
|
||||
* @param npad_id_type npad id type for this specific controller
|
||||
*/
|
||||
explicit EmulatedController(NpadIdType npad_id_type_);
|
||||
~EmulatedController();
|
||||
@@ -155,7 +155,7 @@ public:
|
||||
|
||||
/**
|
||||
* Gets the NpadStyleIndex for this controller
|
||||
* @param If true tmp_npad_type will be returned
|
||||
* @param get_temporary_value If true tmp_npad_type will be returned
|
||||
* @return NpadStyleIndex set on the controller
|
||||
*/
|
||||
NpadStyleIndex GetNpadStyleIndex(bool get_temporary_value = false) const;
|
||||
@@ -168,7 +168,7 @@ public:
|
||||
|
||||
/**
|
||||
* Is the emulated connected
|
||||
* @param If true tmp_is_connected will be returned
|
||||
* @param get_temporary_value If true tmp_is_connected will be returned
|
||||
* @return true if the controller has the connected status
|
||||
*/
|
||||
bool IsConnected(bool get_temporary_value = false) const;
|
||||
@@ -179,14 +179,16 @@ public:
|
||||
/// Removes all callbacks created from input devices
|
||||
void UnloadInput();
|
||||
|
||||
/// Sets the emulated console into configuring mode. Locking all HID service events from being
|
||||
/// moddified
|
||||
/**
|
||||
* Sets the emulated controller into configuring mode
|
||||
* This prevents the modification of the HID state of the emulated controller by input commands
|
||||
*/
|
||||
void EnableConfiguration();
|
||||
|
||||
/// Returns the emulated console to the normal behaivour
|
||||
/// Returns the emulated controller into normal mode, allowing the modification of the HID state
|
||||
void DisableConfiguration();
|
||||
|
||||
/// Returns true if the emulated device is on configuring mode
|
||||
/// Returns true if the emulated controller is in configuring mode
|
||||
bool IsConfiguring() const;
|
||||
|
||||
/// Reload all input devices
|
||||
@@ -215,19 +217,19 @@ public:
|
||||
|
||||
/**
|
||||
* Updates the current mapped button device
|
||||
* @param ParamPackage with controller data to be mapped
|
||||
* @param param ParamPackage with controller data to be mapped
|
||||
*/
|
||||
void SetButtonParam(std::size_t index, Common::ParamPackage param);
|
||||
|
||||
/**
|
||||
* Updates the current mapped stick device
|
||||
* @param ParamPackage with controller data to be mapped
|
||||
* @param param ParamPackage with controller data to be mapped
|
||||
*/
|
||||
void SetStickParam(std::size_t index, Common::ParamPackage param);
|
||||
|
||||
/**
|
||||
* Updates the current mapped motion device
|
||||
* @param ParamPackage with controller data to be mapped
|
||||
* @param param ParamPackage with controller data to be mapped
|
||||
*/
|
||||
void SetMotionParam(std::size_t index, Common::ParamPackage param);
|
||||
|
||||
@@ -270,13 +272,13 @@ public:
|
||||
/// Returns the latest battery status from the controller
|
||||
BatteryLevelState GetBattery() const;
|
||||
|
||||
/*
|
||||
/**
|
||||
* Sends a specific vibration to the output device
|
||||
* @return returns true if vibration had no errors
|
||||
*/
|
||||
bool SetVibration(std::size_t device_index, VibrationValue vibration);
|
||||
|
||||
/*
|
||||
/**
|
||||
* Sends a small vibration to the output device
|
||||
* @return returns true if SetVibration was successfull
|
||||
*/
|
||||
@@ -290,14 +292,14 @@ public:
|
||||
|
||||
/**
|
||||
* Adds a callback to the list of events
|
||||
* @param ConsoleUpdateCallback that will be triggered
|
||||
* @param update_callback A ConsoleUpdateCallback that will be triggered
|
||||
* @return an unique key corresponding to the callback index in the list
|
||||
*/
|
||||
int SetCallback(ControllerUpdateCallback update_callback);
|
||||
|
||||
/**
|
||||
* Removes a callback from the list stopping any future events to this object
|
||||
* @param Key corresponding to the callback index in the list
|
||||
* @param key Key corresponding to the callback index in the list
|
||||
*/
|
||||
void DeleteCallback(int key);
|
||||
|
||||
@@ -310,43 +312,43 @@ private:
|
||||
|
||||
/**
|
||||
* Updates the button status of the controller
|
||||
* @param callback: A CallbackStatus containing the button status
|
||||
* @param index: Button ID of the to be updated
|
||||
* @param callback A CallbackStatus containing the button status
|
||||
* @param index Button ID of the to be updated
|
||||
*/
|
||||
void SetButton(Common::Input::CallbackStatus callback, std::size_t index, Common::UUID uuid);
|
||||
|
||||
/**
|
||||
* Updates the analog stick status of the controller
|
||||
* @param callback: A CallbackStatus containing the analog stick status
|
||||
* @param index: stick ID of the to be updated
|
||||
* @param callback A CallbackStatus containing the analog stick status
|
||||
* @param index stick ID of the to be updated
|
||||
*/
|
||||
void SetStick(Common::Input::CallbackStatus callback, std::size_t index, Common::UUID uuid);
|
||||
|
||||
/**
|
||||
* Updates the trigger status of the controller
|
||||
* @param callback: A CallbackStatus containing the trigger status
|
||||
* @param index: trigger ID of the to be updated
|
||||
* @param callback A CallbackStatus containing the trigger status
|
||||
* @param index trigger ID of the to be updated
|
||||
*/
|
||||
void SetTrigger(Common::Input::CallbackStatus callback, std::size_t index, Common::UUID uuid);
|
||||
|
||||
/**
|
||||
* Updates the motion status of the controller
|
||||
* @param callback: A CallbackStatus containing gyro and accelerometer data
|
||||
* @param index: motion ID of the to be updated
|
||||
* @param callback A CallbackStatus containing gyro and accelerometer data
|
||||
* @param index motion ID of the to be updated
|
||||
*/
|
||||
void SetMotion(Common::Input::CallbackStatus callback, std::size_t index);
|
||||
|
||||
/**
|
||||
* Updates the battery status of the controller
|
||||
* @param callback: A CallbackStatus containing the battery status
|
||||
* @param index: Button ID of the to be updated
|
||||
* @param callback A CallbackStatus containing the battery status
|
||||
* @param index Button ID of the to be updated
|
||||
*/
|
||||
void SetBattery(Common::Input::CallbackStatus callback, std::size_t index);
|
||||
|
||||
/**
|
||||
* Triggers a callback that something has changed on the controller status
|
||||
* @param type: Input type of the event to trigger
|
||||
* @param is_service_update: indicates if this event should be sended to only services
|
||||
* @param type Input type of the event to trigger
|
||||
* @param is_service_update indicates if this event should only be sent to HID services
|
||||
*/
|
||||
void TriggerOnChange(ControllerTriggerType type, bool is_service_update);
|
||||
|
||||
@@ -357,7 +359,7 @@ private:
|
||||
f32 motion_sensitivity{0.01f};
|
||||
bool force_update_motion{false};
|
||||
|
||||
// Temporary values to avoid doing changes while the controller is on configuration mode
|
||||
// Temporary values to avoid doing changes while the controller is in configuring mode
|
||||
NpadStyleIndex tmp_npad_type{NpadStyleIndex::None};
|
||||
bool tmp_is_connected{false};
|
||||
|
||||
|
||||
@@ -75,9 +75,9 @@ class EmulatedDevices {
|
||||
public:
|
||||
/**
|
||||
* Contains all input data related to external devices that aren't necesarily a controller
|
||||
* like keyboard and mouse
|
||||
* This includes devices such as the keyboard or mouse
|
||||
*/
|
||||
EmulatedDevices();
|
||||
explicit EmulatedDevices();
|
||||
~EmulatedDevices();
|
||||
|
||||
YUZU_NON_COPYABLE(EmulatedDevices);
|
||||
@@ -86,14 +86,16 @@ public:
|
||||
/// Removes all callbacks created from input devices
|
||||
void UnloadInput();
|
||||
|
||||
/// Sets the emulated console into configuring mode. Locking all HID service events from being
|
||||
/// moddified
|
||||
/**
|
||||
* Sets the emulated devices into configuring mode
|
||||
* This prevents the modification of the HID state of the emulated devices by input commands
|
||||
*/
|
||||
void EnableConfiguration();
|
||||
|
||||
/// Returns the emulated console to the normal behaivour
|
||||
/// Returns the emulated devices into normal mode, allowing the modification of the HID state
|
||||
void DisableConfiguration();
|
||||
|
||||
/// Returns true if the emulated device is on configuring mode
|
||||
/// Returns true if the emulated device is in configuring mode
|
||||
bool IsConfiguring() const;
|
||||
|
||||
/// Reload all input devices
|
||||
@@ -134,14 +136,14 @@ public:
|
||||
|
||||
/**
|
||||
* Adds a callback to the list of events
|
||||
* @param InterfaceUpdateCallback that will be triggered
|
||||
* @param update_callback InterfaceUpdateCallback that will be triggered
|
||||
* @return an unique key corresponding to the callback index in the list
|
||||
*/
|
||||
int SetCallback(InterfaceUpdateCallback update_callback);
|
||||
|
||||
/**
|
||||
* Removes a callback from the list stopping any future events to this object
|
||||
* @param Key corresponding to the callback index in the list
|
||||
* @param key Key corresponding to the callback index in the list
|
||||
*/
|
||||
void DeleteCallback(int key);
|
||||
|
||||
@@ -151,42 +153,42 @@ private:
|
||||
|
||||
/**
|
||||
* Updates the touch status of the keyboard device
|
||||
* @param callback: A CallbackStatus containing the key status
|
||||
* @param index: key ID to be updated
|
||||
* @param callback A CallbackStatus containing the key status
|
||||
* @param index key ID to be updated
|
||||
*/
|
||||
void SetKeyboardButton(Common::Input::CallbackStatus callback, std::size_t index);
|
||||
|
||||
/**
|
||||
* Updates the keyboard status of the keyboard device
|
||||
* @param callback: A CallbackStatus containing the modifier key status
|
||||
* @param index: modifier key ID to be updated
|
||||
* @param callback A CallbackStatus containing the modifier key status
|
||||
* @param index modifier key ID to be updated
|
||||
*/
|
||||
void SetKeyboardModifier(Common::Input::CallbackStatus callback, std::size_t index);
|
||||
|
||||
/**
|
||||
* Updates the mouse button status of the mouse device
|
||||
* @param callback: A CallbackStatus containing the button status
|
||||
* @param index: Button ID to be updated
|
||||
* @param callback A CallbackStatus containing the button status
|
||||
* @param index Button ID to be updated
|
||||
*/
|
||||
void SetMouseButton(Common::Input::CallbackStatus callback, std::size_t index);
|
||||
|
||||
/**
|
||||
* Updates the mouse wheel status of the mouse device
|
||||
* @param callback: A CallbackStatus containing the wheel status
|
||||
* @param index: wheel ID to be updated
|
||||
* @param callback A CallbackStatus containing the wheel status
|
||||
* @param index wheel ID to be updated
|
||||
*/
|
||||
void SetMouseAnalog(Common::Input::CallbackStatus callback, std::size_t index);
|
||||
|
||||
/**
|
||||
* Updates the mouse position status of the mouse device
|
||||
* @param callback: A CallbackStatus containing the position status
|
||||
* @param index: stick ID to be updated
|
||||
* @param callback A CallbackStatus containing the position status
|
||||
* @param index stick ID to be updated
|
||||
*/
|
||||
void SetMouseStick(Common::Input::CallbackStatus callback);
|
||||
|
||||
/**
|
||||
* Triggers a callback that something has changed on the device status
|
||||
* @param Input type of the event to trigger
|
||||
* @param type Input type of the event to trigger
|
||||
*/
|
||||
void TriggerOnChange(DeviceTriggerType type);
|
||||
|
||||
|
||||
@@ -135,6 +135,32 @@ NpadIdType HIDCore::GetFirstNpadId() const {
|
||||
return NpadIdType::Player1;
|
||||
}
|
||||
|
||||
void HIDCore::EnableAllControllerConfiguration() {
|
||||
player_1->EnableConfiguration();
|
||||
player_2->EnableConfiguration();
|
||||
player_3->EnableConfiguration();
|
||||
player_4->EnableConfiguration();
|
||||
player_5->EnableConfiguration();
|
||||
player_6->EnableConfiguration();
|
||||
player_7->EnableConfiguration();
|
||||
player_8->EnableConfiguration();
|
||||
other->EnableConfiguration();
|
||||
handheld->EnableConfiguration();
|
||||
}
|
||||
|
||||
void HIDCore::DisableAllControllerConfiguration() {
|
||||
player_1->DisableConfiguration();
|
||||
player_2->DisableConfiguration();
|
||||
player_3->DisableConfiguration();
|
||||
player_4->DisableConfiguration();
|
||||
player_5->DisableConfiguration();
|
||||
player_6->DisableConfiguration();
|
||||
player_7->DisableConfiguration();
|
||||
player_8->DisableConfiguration();
|
||||
other->DisableConfiguration();
|
||||
handheld->DisableConfiguration();
|
||||
}
|
||||
|
||||
void HIDCore::ReloadInputDevices() {
|
||||
player_1->ReloadFromSettings();
|
||||
player_2->ReloadFromSettings();
|
||||
|
||||
@@ -45,6 +45,12 @@ public:
|
||||
/// Returns the first connected npad id
|
||||
NpadIdType GetFirstNpadId() const;
|
||||
|
||||
/// Sets all emulated controllers into configuring mode.
|
||||
void EnableAllControllerConfiguration();
|
||||
|
||||
/// Sets all emulated controllers into normal mode.
|
||||
void DisableAllControllerConfiguration();
|
||||
|
||||
/// Reloads all input devices from settings
|
||||
void ReloadInputDevices();
|
||||
|
||||
|
||||
@@ -63,6 +63,8 @@ enum class NpadButton : u64 {
|
||||
LagonCUp = 1ULL << 32,
|
||||
LagonCRight = 1ULL << 33,
|
||||
LagonCDown = 1ULL << 34,
|
||||
|
||||
All = 0xFFFFFFFFFFFFFFFFULL,
|
||||
};
|
||||
DECLARE_ENUM_FLAG_OPERATORS(NpadButton);
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace Core::HID {
|
||||
/**
|
||||
* Converts raw input data into a valid battery status.
|
||||
*
|
||||
* @param Supported callbacks: Analog, Battery, Trigger.
|
||||
* @param callback Supported callbacks: Analog, Battery, Trigger.
|
||||
* @return A valid BatteryStatus object.
|
||||
*/
|
||||
Common::Input::BatteryStatus TransformToBattery(const Common::Input::CallbackStatus& callback);
|
||||
@@ -29,7 +29,7 @@ Common::Input::BatteryStatus TransformToBattery(const Common::Input::CallbackSta
|
||||
/**
|
||||
* Converts raw input data into a valid button status. Applies invert properties to the output.
|
||||
*
|
||||
* @param Supported callbacks: Analog, Button, Trigger.
|
||||
* @param callback Supported callbacks: Analog, Button, Trigger.
|
||||
* @return A valid TouchStatus object.
|
||||
*/
|
||||
Common::Input::ButtonStatus TransformToButton(const Common::Input::CallbackStatus& callback);
|
||||
@@ -37,7 +37,7 @@ Common::Input::ButtonStatus TransformToButton(const Common::Input::CallbackStatu
|
||||
/**
|
||||
* Converts raw input data into a valid motion status.
|
||||
*
|
||||
* @param Supported callbacks: Motion.
|
||||
* @param callback Supported callbacks: Motion.
|
||||
* @return A valid TouchStatus object.
|
||||
*/
|
||||
Common::Input::MotionStatus TransformToMotion(const Common::Input::CallbackStatus& callback);
|
||||
@@ -46,7 +46,7 @@ Common::Input::MotionStatus TransformToMotion(const Common::Input::CallbackStatu
|
||||
* Converts raw input data into a valid stick status. Applies offset, deadzone, range and invert
|
||||
* properties to the output.
|
||||
*
|
||||
* @param Supported callbacks: Stick.
|
||||
* @param callback Supported callbacks: Stick.
|
||||
* @return A valid StickStatus object.
|
||||
*/
|
||||
Common::Input::StickStatus TransformToStick(const Common::Input::CallbackStatus& callback);
|
||||
@@ -54,7 +54,7 @@ Common::Input::StickStatus TransformToStick(const Common::Input::CallbackStatus&
|
||||
/**
|
||||
* Converts raw input data into a valid touch status.
|
||||
*
|
||||
* @param Supported callbacks: Touch.
|
||||
* @param callback Supported callbacks: Touch.
|
||||
* @return A valid TouchStatus object.
|
||||
*/
|
||||
Common::Input::TouchStatus TransformToTouch(const Common::Input::CallbackStatus& callback);
|
||||
@@ -63,7 +63,7 @@ Common::Input::TouchStatus TransformToTouch(const Common::Input::CallbackStatus&
|
||||
* Converts raw input data into a valid trigger status. Applies offset, deadzone, range and
|
||||
* invert properties to the output. Button status uses the threshold property if necessary.
|
||||
*
|
||||
* @param Supported callbacks: Analog, Button, Trigger.
|
||||
* @param callback Supported callbacks: Analog, Button, Trigger.
|
||||
* @return A valid TriggerStatus object.
|
||||
*/
|
||||
Common::Input::TriggerStatus TransformToTrigger(const Common::Input::CallbackStatus& callback);
|
||||
@@ -72,22 +72,23 @@ Common::Input::TriggerStatus TransformToTrigger(const Common::Input::CallbackSta
|
||||
* Converts raw input data into a valid analog status. Applies offset, deadzone, range and
|
||||
* invert properties to the output.
|
||||
*
|
||||
* @param Supported callbacks: Analog.
|
||||
* @param callback Supported callbacks: Analog.
|
||||
* @return A valid AnalogStatus object.
|
||||
*/
|
||||
Common::Input::AnalogStatus TransformToAnalog(const Common::Input::CallbackStatus& callback);
|
||||
|
||||
/**
|
||||
* Converts raw analog data into a valid analog value
|
||||
* @param An analog object containing raw data and properties, bool that determines if the value
|
||||
* needs to be clamped between -1.0f and 1.0f.
|
||||
* @param analog An analog object containing raw data and properties
|
||||
* @param clamp_value determines if the value needs to be clamped between -1.0f and 1.0f.
|
||||
*/
|
||||
void SanitizeAnalog(Common::Input::AnalogStatus& analog, bool clamp_value);
|
||||
|
||||
/**
|
||||
* Converts raw stick data into a valid stick value
|
||||
* @param Two analog objects containing raw data and properties, bool that determines if the value
|
||||
* needs to be clamped into the unit circle.
|
||||
* @param analog_x raw analog data and properties for the x-axis
|
||||
* @param analog_y raw analog data and properties for the y-axis
|
||||
* @param clamp_value bool that determines if the value needs to be clamped into the unit circle.
|
||||
*/
|
||||
void SanitizeStick(Common::Input::AnalogStatus& analog_x, Common::Input::AnalogStatus& analog_y,
|
||||
bool clamp_value);
|
||||
|
||||
@@ -20,7 +20,7 @@ InputInterpreter::InputInterpreter(Core::System& system)
|
||||
InputInterpreter::~InputInterpreter() = default;
|
||||
|
||||
void InputInterpreter::PollInput() {
|
||||
const u64 button_state = npad.GetAndResetPressState();
|
||||
const auto button_state = npad.GetAndResetPressState();
|
||||
|
||||
previous_index = current_index;
|
||||
current_index = (current_index + 1) % button_states.size();
|
||||
@@ -32,30 +32,30 @@ void InputInterpreter::ResetButtonStates() {
|
||||
previous_index = 0;
|
||||
current_index = 0;
|
||||
|
||||
button_states[0] = 0xFFFFFFFFFFFFFFFF;
|
||||
button_states[0] = Core::HID::NpadButton::All;
|
||||
|
||||
for (std::size_t i = 1; i < button_states.size(); ++i) {
|
||||
button_states[i] = 0;
|
||||
button_states[i] = Core::HID::NpadButton::None;
|
||||
}
|
||||
}
|
||||
|
||||
bool InputInterpreter::IsButtonPressed(Core::HID::NpadButton button) const {
|
||||
return (button_states[current_index] & static_cast<u64>(button)) != 0;
|
||||
return True(button_states[current_index] & button);
|
||||
}
|
||||
|
||||
bool InputInterpreter::IsButtonPressedOnce(Core::HID::NpadButton button) const {
|
||||
const bool current_press = (button_states[current_index] & static_cast<u64>(button)) != 0;
|
||||
const bool previous_press = (button_states[previous_index] & static_cast<u64>(button)) != 0;
|
||||
const bool current_press = True(button_states[current_index] & button);
|
||||
const bool previous_press = True(button_states[previous_index] & button);
|
||||
|
||||
return current_press && !previous_press;
|
||||
}
|
||||
|
||||
bool InputInterpreter::IsButtonHeld(Core::HID::NpadButton button) const {
|
||||
u64 held_buttons{button_states[0]};
|
||||
Core::HID::NpadButton held_buttons{button_states[0]};
|
||||
|
||||
for (std::size_t i = 1; i < button_states.size(); ++i) {
|
||||
held_buttons &= button_states[i];
|
||||
}
|
||||
|
||||
return (held_buttons & static_cast<u64>(button)) != 0;
|
||||
return True(held_buttons & button);
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ private:
|
||||
Service::HID::Controller_NPad& npad;
|
||||
|
||||
/// Stores 9 consecutive button states polled from HID.
|
||||
std::array<u64, 9> button_states{};
|
||||
std::array<Core::HID::NpadButton, 9> button_states{};
|
||||
|
||||
std::size_t previous_index{};
|
||||
std::size_t current_index{};
|
||||
|
||||
@@ -263,6 +263,10 @@ void Controller_NPad::OnInit() {
|
||||
style.fullkey.Assign(1);
|
||||
style.gamecube.Assign(1);
|
||||
style.palma.Assign(1);
|
||||
style.lark.Assign(1);
|
||||
style.lucia.Assign(1);
|
||||
style.lagoon.Assign(1);
|
||||
style.lager.Assign(1);
|
||||
hid_core.SetSupportedStyleTag(style);
|
||||
}
|
||||
|
||||
@@ -506,7 +510,7 @@ void Controller_NPad::OnUpdate(const Core::Timing::CoreTiming& core_timing, u8*
|
||||
libnx_state.r_stick = pad_state.r_stick;
|
||||
npad.system_ext_lifo.WriteNextEntry(pad_state);
|
||||
|
||||
press_state |= static_cast<u32>(pad_state.npad_buttons.raw);
|
||||
press_state |= static_cast<u64>(pad_state.npad_buttons.raw);
|
||||
|
||||
std::memcpy(data + NPAD_OFFSET + (i * sizeof(NpadInternalState)),
|
||||
&controller.shared_memory_entry, sizeof(NpadInternalState));
|
||||
@@ -631,7 +635,7 @@ void Controller_NPad::OnMotionUpdate(const Core::Timing::CoreTiming& core_timing
|
||||
// This buffer only is updated on handheld on HW
|
||||
npad.sixaxis_handheld_lifo.WriteNextEntry(sixaxis_handheld_state);
|
||||
} else {
|
||||
// Hanheld doesn't update this buffer on HW
|
||||
// Handheld doesn't update this buffer on HW
|
||||
npad.sixaxis_fullkey_lifo.WriteNextEntry(sixaxis_fullkey_state);
|
||||
}
|
||||
|
||||
@@ -1145,8 +1149,8 @@ void Controller_NPad::ClearAllControllers() {
|
||||
}
|
||||
}
|
||||
|
||||
u32 Controller_NPad::GetAndResetPressState() {
|
||||
return press_state.exchange(0);
|
||||
Core::HID::NpadButton Controller_NPad::GetAndResetPressState() {
|
||||
return static_cast<Core::HID::NpadButton>(press_state.exchange(0));
|
||||
}
|
||||
|
||||
bool Controller_NPad::IsControllerSupported(Core::HID::NpadStyleIndex controller) const {
|
||||
|
||||
@@ -179,7 +179,7 @@ public:
|
||||
|
||||
// Logical OR for all buttons presses on all controllers
|
||||
// Specifically for cheat engine and other features.
|
||||
u32 GetAndResetPressState();
|
||||
Core::HID::NpadButton GetAndResetPressState();
|
||||
|
||||
static bool IsNpadIdValid(Core::HID::NpadIdType npad_id);
|
||||
static bool IsDeviceHandleValid(const Core::HID::SixAxisSensorHandle& device_handle);
|
||||
@@ -503,7 +503,7 @@ private:
|
||||
NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id);
|
||||
const NpadControllerData& GetControllerFromNpadIdType(Core::HID::NpadIdType npad_id) const;
|
||||
|
||||
std::atomic<u32> press_state{};
|
||||
std::atomic<u64> press_state{};
|
||||
|
||||
std::array<NpadControllerData, 10> controller_data{};
|
||||
KernelHelpers::ServiceContext& service_context;
|
||||
|
||||
@@ -1883,7 +1883,7 @@ public:
|
||||
{317, nullptr, "GetNpadLeftRightInterfaceType"},
|
||||
{318, nullptr, "HasBattery"},
|
||||
{319, nullptr, "HasLeftRightBattery"},
|
||||
{321, nullptr, "GetUniquePadsFromNpad"},
|
||||
{321, &HidSys::GetUniquePadsFromNpad, "GetUniquePadsFromNpad"},
|
||||
{322, nullptr, "GetIrSensorState"},
|
||||
{323, nullptr, "GetXcdHandleForNpadWithIrSensor"},
|
||||
{324, nullptr, "GetUniquePadButtonSet"},
|
||||
@@ -2054,6 +2054,18 @@ private:
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void GetUniquePadsFromNpad(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto npad_id_type{rp.PopEnum<Core::HID::NpadIdType>()};
|
||||
|
||||
const s64 total_entries = 0;
|
||||
LOG_WARNING(Service_HID, "(STUBBED) called, npad_id_type={}", npad_id_type);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push(total_entries);
|
||||
}
|
||||
};
|
||||
|
||||
class HidTmp final : public ServiceFramework<HidTmp> {
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "core/hle/service/ns/errors.h"
|
||||
#include "core/hle/service/ns/language.h"
|
||||
#include "core/hle/service/ns/ns.h"
|
||||
#include "core/hle/service/ns/pdm_qry.h"
|
||||
#include "core/hle/service/ns/pl_u.h"
|
||||
#include "core/hle/service/set/set.h"
|
||||
|
||||
@@ -570,11 +571,29 @@ IFactoryResetInterface::IFactoryResetInterface(Core::System& system_)
|
||||
|
||||
IFactoryResetInterface::~IFactoryResetInterface() = default;
|
||||
|
||||
IReadOnlyApplicationControlDataInterface::IReadOnlyApplicationControlDataInterface(
|
||||
Core::System& system_)
|
||||
: ServiceFramework{system_, "IReadOnlyApplicationControlDataInterface"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "GetApplicationControlData"},
|
||||
{1, nullptr, "GetApplicationDesiredLanguage"},
|
||||
{2, nullptr, "ConvertApplicationLanguageToLanguageCode"},
|
||||
{3, nullptr, "ConvertLanguageCodeToApplicationLanguage"},
|
||||
{4, nullptr, "SelectApplicationDesiredLanguage"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
IReadOnlyApplicationControlDataInterface::~IReadOnlyApplicationControlDataInterface() = default;
|
||||
|
||||
NS::NS(const char* name, Core::System& system_) : ServiceFramework{system_, name} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{7988, nullptr, "GetDynamicRightsInterface"},
|
||||
{7989, nullptr, "GetReadOnlyApplicationControlDataInterface"},
|
||||
{7989, &NS::PushInterface<IReadOnlyApplicationControlDataInterface>, "GetReadOnlyApplicationControlDataInterface"},
|
||||
{7991, nullptr, "GetReadOnlyApplicationRecordInterface"},
|
||||
{7992, &NS::PushInterface<IECommerceInterface>, "GetECommerceInterface"},
|
||||
{7993, &NS::PushInterface<IApplicationVersionInterface>, "GetApplicationVersionInterface"},
|
||||
@@ -738,6 +757,8 @@ void InstallInterfaces(SM::ServiceManager& service_manager, Core::System& system
|
||||
std::make_shared<NS_SU>(system)->InstallAsService(service_manager);
|
||||
std::make_shared<NS_VM>(system)->InstallAsService(service_manager);
|
||||
|
||||
std::make_shared<PDM_QRY>(system)->InstallAsService(service_manager);
|
||||
|
||||
std::make_shared<PL_U>(system)->InstallAsService(service_manager);
|
||||
}
|
||||
|
||||
|
||||
@@ -74,6 +74,13 @@ public:
|
||||
~IFactoryResetInterface() override;
|
||||
};
|
||||
|
||||
class IReadOnlyApplicationControlDataInterface final
|
||||
: public ServiceFramework<IReadOnlyApplicationControlDataInterface> {
|
||||
public:
|
||||
explicit IReadOnlyApplicationControlDataInterface(Core::System& system_);
|
||||
~IReadOnlyApplicationControlDataInterface() override;
|
||||
};
|
||||
|
||||
class NS final : public ServiceFramework<NS> {
|
||||
public:
|
||||
explicit NS(const char* name, Core::System& system_);
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
// Copyright 2021 yuzu Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "common/uuid.h"
|
||||
#include "core/hle/ipc_helpers.h"
|
||||
#include "core/hle/service/ns/pdm_qry.h"
|
||||
#include "core/hle/service/service.h"
|
||||
#include "core/hle/service/sm/sm.h"
|
||||
|
||||
namespace Service::NS {
|
||||
|
||||
PDM_QRY::PDM_QRY(Core::System& system_) : ServiceFramework{system_, "pdm:qry"} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "QueryAppletEvent"},
|
||||
{1, nullptr, "QueryPlayStatistics"},
|
||||
{2, nullptr, "QueryPlayStatisticsByUserAccountId"},
|
||||
{3, nullptr, "QueryPlayStatisticsByNetworkServiceAccountId"},
|
||||
{4, nullptr, "QueryPlayStatisticsByApplicationId"},
|
||||
{5, &PDM_QRY::QueryPlayStatisticsByApplicationIdAndUserAccountId, "QueryPlayStatisticsByApplicationIdAndUserAccountId"},
|
||||
{6, nullptr, "QueryPlayStatisticsByApplicationIdAndNetworkServiceAccountId"},
|
||||
{7, nullptr, "QueryLastPlayTimeV0"},
|
||||
{8, nullptr, "QueryPlayEvent"},
|
||||
{9, nullptr, "GetAvailablePlayEventRange"},
|
||||
{10, nullptr, "QueryAccountEvent"},
|
||||
{11, nullptr, "QueryAccountPlayEvent"},
|
||||
{12, nullptr, "GetAvailableAccountPlayEventRange"},
|
||||
{13, nullptr, "QueryApplicationPlayStatisticsForSystemV0"},
|
||||
{14, nullptr, "QueryRecentlyPlayedApplication"},
|
||||
{15, nullptr, "GetRecentlyPlayedApplicationUpdateEvent"},
|
||||
{16, nullptr, "QueryApplicationPlayStatisticsByUserAccountIdForSystemV0"},
|
||||
{17, nullptr, "QueryLastPlayTime"},
|
||||
{18, nullptr, "QueryApplicationPlayStatisticsForSystem"},
|
||||
{19, nullptr, "QueryApplicationPlayStatisticsByUserAccountIdForSystem"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
PDM_QRY::~PDM_QRY() = default;
|
||||
|
||||
void PDM_QRY::QueryPlayStatisticsByApplicationIdAndUserAccountId(Kernel::HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const auto unknown = rp.Pop<bool>();
|
||||
rp.Pop<u8>(); // Padding
|
||||
const auto application_id = rp.Pop<u64>();
|
||||
const auto user_account_uid = rp.PopRaw<Common::UUID>();
|
||||
|
||||
// TODO(German77): Read statistics of the game
|
||||
PlayStatistics statistics{
|
||||
.application_id = application_id,
|
||||
.total_launches = 1,
|
||||
};
|
||||
|
||||
LOG_WARNING(Service_NS,
|
||||
"(STUBBED) called. unknown={}. application_id=0x{:016X}, user_account_uid=0x{}",
|
||||
unknown, application_id, user_account_uid.Format());
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 12};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushRaw(statistics);
|
||||
}
|
||||
|
||||
} // namespace Service::NS
|
||||
@@ -0,0 +1,33 @@
|
||||
// Copyright 2021 yuzu Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
namespace Service::NS {
|
||||
|
||||
struct PlayStatistics {
|
||||
u64 application_id{};
|
||||
u32 first_entry_index{};
|
||||
u32 first_timestamp_user{};
|
||||
u32 first_timestamp_network{};
|
||||
u32 last_entry_index{};
|
||||
u32 last_timestamp_user{};
|
||||
u32 last_timestamp_network{};
|
||||
u32 play_time_in_minutes{};
|
||||
u32 total_launches{};
|
||||
};
|
||||
static_assert(sizeof(PlayStatistics) == 0x28, "PlayStatistics is an invalid size");
|
||||
|
||||
class PDM_QRY final : public ServiceFramework<PDM_QRY> {
|
||||
public:
|
||||
explicit PDM_QRY(Core::System& system_);
|
||||
~PDM_QRY() override;
|
||||
|
||||
private:
|
||||
void QueryPlayStatisticsByApplicationIdAndUserAccountId(Kernel::HLERequestContext& ctx);
|
||||
};
|
||||
|
||||
} // namespace Service::NS
|
||||
@@ -19,7 +19,6 @@
|
||||
namespace Core::Memory {
|
||||
namespace {
|
||||
constexpr auto CHEAT_ENGINE_NS = std::chrono::nanoseconds{1000000000 / 12};
|
||||
constexpr u32 KEYPAD_BITMASK = 0x3FFFFFF;
|
||||
|
||||
std::string_view ExtractName(std::string_view data, std::size_t start_index, char match) {
|
||||
auto end_index = start_index;
|
||||
@@ -61,7 +60,7 @@ u64 StandardVmCallbacks::HidKeysDown() {
|
||||
applet_resource
|
||||
->GetController<Service::HID::Controller_NPad>(Service::HID::HidController::NPad)
|
||||
.GetAndResetPressState();
|
||||
return press_state & KEYPAD_BITMASK;
|
||||
return static_cast<u64>(press_state & HID::NpadButton::All);
|
||||
}
|
||||
|
||||
void StandardVmCallbacks::DebugLog(u8 id, u64 value) {
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include "common/assert.h"
|
||||
@@ -59,6 +61,34 @@ Codec::~Codec() {
|
||||
av_buffer_unref(&av_gpu_decoder);
|
||||
}
|
||||
|
||||
#ifdef LIBVA_FOUND
|
||||
// List all the currently loaded Linux modules
|
||||
static std::vector<std::string> ListLinuxKernelModules() {
|
||||
using FILEPtr = std::unique_ptr<FILE, decltype(&std::fclose)>;
|
||||
auto module_listing = FILEPtr{fopen("/proc/modules", "rt"), std::fclose};
|
||||
std::vector<std::string> modules{};
|
||||
if (!module_listing) {
|
||||
LOG_WARNING(Service_NVDRV, "Could not open /proc/modules to collect available modules");
|
||||
return modules;
|
||||
}
|
||||
char* buffer = nullptr;
|
||||
size_t buf_len = 0;
|
||||
while (getline(&buffer, &buf_len, module_listing.get()) != -1) {
|
||||
// format for the module listing file (sysfs)
|
||||
// <name> <module_size> <depended_by_count> <depended_by_names> <status> <load_address>
|
||||
auto line = std::string(buffer);
|
||||
// we are only interested in module names
|
||||
auto name_pos = line.find_first_of(" ");
|
||||
if (name_pos == std::string::npos) {
|
||||
continue;
|
||||
}
|
||||
modules.push_back(line.erase(name_pos));
|
||||
}
|
||||
free(buffer);
|
||||
return modules;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool Codec::CreateGpuAvDevice() {
|
||||
#if defined(LIBVA_FOUND)
|
||||
static constexpr std::array<const char*, 3> VAAPI_DRIVERS = {
|
||||
@@ -67,8 +97,16 @@ bool Codec::CreateGpuAvDevice() {
|
||||
"amdgpu",
|
||||
};
|
||||
AVDictionary* hwdevice_options = nullptr;
|
||||
const auto loaded_modules = ListLinuxKernelModules();
|
||||
av_dict_set(&hwdevice_options, "connection_type", "drm", 0);
|
||||
for (const auto& driver : VAAPI_DRIVERS) {
|
||||
// first check if the target driver is loaded in the kernel
|
||||
bool found = std::any_of(loaded_modules.begin(), loaded_modules.end(),
|
||||
[&driver](const auto& module) { return module == driver; });
|
||||
if (!found) {
|
||||
LOG_DEBUG(Service_NVDRV, "Kernel driver {} is not loaded, trying the next one", driver);
|
||||
continue;
|
||||
}
|
||||
av_dict_set(&hwdevice_options, "kernel_driver", driver, 0);
|
||||
const int hwdevice_error = av_hwdevice_ctx_create(&av_gpu_decoder, AV_HWDEVICE_TYPE_VAAPI,
|
||||
nullptr, hwdevice_options, 0);
|
||||
@@ -85,11 +123,12 @@ bool Codec::CreateGpuAvDevice() {
|
||||
#endif
|
||||
static constexpr auto HW_CONFIG_METHOD = AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX;
|
||||
static constexpr std::array GPU_DECODER_TYPES{
|
||||
#ifdef linux
|
||||
AV_HWDEVICE_TYPE_VDPAU,
|
||||
#endif
|
||||
AV_HWDEVICE_TYPE_CUDA,
|
||||
#ifdef _WIN32
|
||||
AV_HWDEVICE_TYPE_D3D11VA,
|
||||
#else
|
||||
AV_HWDEVICE_TYPE_VDPAU,
|
||||
#endif
|
||||
};
|
||||
for (const auto& type : GPU_DECODER_TYPES) {
|
||||
|
||||
@@ -11,13 +11,9 @@ set(SHADER_FILES
|
||||
block_linear_unswizzle_2d.comp
|
||||
block_linear_unswizzle_3d.comp
|
||||
convert_abgr8_to_d24s8.frag
|
||||
convert_b10g11r11_to_d24s8.frag
|
||||
convert_d24s8_to_abgr8.frag
|
||||
convert_d24s8_to_b10g11r11.frag
|
||||
convert_d24s8_to_r16g16.frag
|
||||
convert_depth_to_float.frag
|
||||
convert_float_to_depth.frag
|
||||
convert_r16g16_to_d24s8.frag
|
||||
full_screen_triangle.vert
|
||||
fxaa.frag
|
||||
fxaa.vert
|
||||
|
||||
@@ -9,9 +9,10 @@ layout(binding = 0) uniform sampler2D color_texture;
|
||||
|
||||
void main() {
|
||||
ivec2 coord = ivec2(gl_FragCoord.xy);
|
||||
uvec4 color = uvec4(texelFetch(color_texture, coord, 0).rgba * (exp2(8) - 1.0f));
|
||||
uint depth_unorm = (color.r << 16) | (color.g << 8) | color.b;
|
||||
uvec4 color = uvec4(texelFetch(color_texture, coord, 0).abgr * (exp2(8) - 1.0f));
|
||||
uvec4 bytes = color << uvec4(24, 16, 8, 0);
|
||||
uint depth_stencil_unorm = bytes.x | bytes.y | bytes.z | bytes.w;
|
||||
|
||||
gl_FragDepth = float(depth_unorm) / (exp2(24.0) - 1.0f);
|
||||
gl_FragStencilRefARB = int(color.a);
|
||||
gl_FragDepth = float(depth_stencil_unorm & 0x00FFFFFFu) / (exp2(24.0) - 1.0f);
|
||||
gl_FragStencilRefARB = int(depth_stencil_unorm >> 24);
|
||||
}
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
// Copyright 2021 yuzu Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#version 450
|
||||
#extension GL_ARB_shader_stencil_export : require
|
||||
|
||||
layout(binding = 0) uniform sampler2D color_texture;
|
||||
|
||||
void main() {
|
||||
ivec2 coord = ivec2(gl_FragCoord.xy);
|
||||
vec4 color = texelFetch(color_texture, coord, 0).rgba;
|
||||
uint depth_stencil_unorm = (uint(color.b * (exp2(10) - 1.0f)) << 22)
|
||||
| (uint(color.g * (exp2(11) - 1.0f)) << 11)
|
||||
| (uint(color.r * (exp2(11) - 1.0f)));
|
||||
|
||||
gl_FragDepth = float(depth_stencil_unorm >> 8) / (exp2(24.0) - 1.0f);
|
||||
gl_FragStencilRefARB = int(depth_stencil_unorm & 0x00FF);
|
||||
}
|
||||
@@ -14,8 +14,10 @@ void main() {
|
||||
uint depth = uint(textureLod(depth_tex, coord, 0).r * (exp2(24.0) - 1.0f));
|
||||
uint stencil = uint(textureLod(stencil_tex, coord, 0).r);
|
||||
|
||||
color.r = float(depth >> 16) / (exp2(8) - 1.0);
|
||||
color.g = float((depth >> 8) & 0x00FF) / (exp2(8) - 1.0);
|
||||
color.b = float(depth & 0x00FF) / (exp2(8) - 1.0);
|
||||
color.a = float(stencil) / (exp2(8) - 1.0);
|
||||
highp uint depth_val =
|
||||
uint(textureLod(depth_tex, coord, 0).r * (exp2(32.0) - 1.0));
|
||||
lowp uint stencil_val = textureLod(stencil_tex, coord, 0).r;
|
||||
highp uvec4 components =
|
||||
uvec4(stencil_val, (uvec3(depth_val) >> uvec3(24u, 16u, 8u)) & 0x000000FFu);
|
||||
color.abgr = vec4(components) / (exp2(8.0) - 1.0);
|
||||
}
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
// Copyright 2021 yuzu Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#version 450
|
||||
|
||||
layout(binding = 0) uniform sampler2D depth_tex;
|
||||
layout(binding = 1) uniform isampler2D stencil_tex;
|
||||
|
||||
layout(location = 0) out vec4 color;
|
||||
|
||||
void main() {
|
||||
ivec2 coord = ivec2(gl_FragCoord.xy);
|
||||
uint depth = uint(textureLod(depth_tex, coord, 0).r * (exp2(24.0) - 1.0f));
|
||||
uint stencil = uint(textureLod(stencil_tex, coord, 0).r);
|
||||
|
||||
color.b = float(depth >> 22) / (exp2(10) - 1.0);
|
||||
color.g = float((depth >> 11) & 0x00FF) / (exp2(11) - 1.0);
|
||||
color.r = float(depth & 0x00FF) / (exp2(11) - 1.0);
|
||||
color.a = 1.0f;
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
// Copyright 2021 yuzu Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#version 450
|
||||
|
||||
layout(binding = 0) uniform sampler2D depth_tex;
|
||||
layout(binding = 1) uniform isampler2D stencil_tex;
|
||||
|
||||
layout(location = 0) out vec4 color;
|
||||
|
||||
void main() {
|
||||
ivec2 coord = ivec2(gl_FragCoord.xy);
|
||||
uint depth = uint(textureLod(depth_tex, coord, 0).r * (exp2(24.0) - 1.0f));
|
||||
uint stencil = uint(textureLod(stencil_tex, coord, 0).r);
|
||||
|
||||
color.r = float(depth >> 16) / (exp2(16) - 1.0);
|
||||
color.g = float((depth >> 16) & 0x00FF) / (exp2(16) - 1.0);
|
||||
color.b = 0.0f;
|
||||
color.a = 1.0f;
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
// Copyright 2021 yuzu Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#version 450
|
||||
#extension GL_ARB_shader_stencil_export : require
|
||||
|
||||
layout(binding = 0) uniform sampler2D color_texture;
|
||||
|
||||
void main() {
|
||||
ivec2 coord = ivec2(gl_FragCoord.xy);
|
||||
vec4 color = texelFetch(color_texture, coord, 0).rgba;
|
||||
uint depth_stencil_unorm = (uint(color.r * (exp2(16) - 1.0f)) << 16)
|
||||
| (uint(color.g * (exp2(16) - 1.0f)) << 16);
|
||||
|
||||
gl_FragDepth = float(depth_stencil_unorm >> 8) / (exp2(24.0) - 1.0f);
|
||||
gl_FragStencilRefARB = int(depth_stencil_unorm & 0x00FF);
|
||||
}
|
||||
@@ -5,13 +5,9 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include "video_core/host_shaders/convert_abgr8_to_d24s8_frag_spv.h"
|
||||
#include "video_core/host_shaders/convert_b10g11r11_to_d24s8_frag_spv.h"
|
||||
#include "video_core/host_shaders/convert_d24s8_to_abgr8_frag_spv.h"
|
||||
#include "video_core/host_shaders/convert_d24s8_to_b10g11r11_frag_spv.h"
|
||||
#include "video_core/host_shaders/convert_d24s8_to_r16g16_frag_spv.h"
|
||||
#include "video_core/host_shaders/convert_depth_to_float_frag_spv.h"
|
||||
#include "video_core/host_shaders/convert_float_to_depth_frag_spv.h"
|
||||
#include "video_core/host_shaders/convert_r16g16_to_d24s8_frag_spv.h"
|
||||
#include "video_core/host_shaders/full_screen_triangle_vert_spv.h"
|
||||
#include "video_core/host_shaders/vulkan_blit_color_float_frag_spv.h"
|
||||
#include "video_core/host_shaders/vulkan_blit_depth_stencil_frag_spv.h"
|
||||
@@ -361,11 +357,7 @@ BlitImageHelper::BlitImageHelper(const Device& device_, VKScheduler& scheduler_,
|
||||
convert_depth_to_float_frag(BuildShader(device, CONVERT_DEPTH_TO_FLOAT_FRAG_SPV)),
|
||||
convert_float_to_depth_frag(BuildShader(device, CONVERT_FLOAT_TO_DEPTH_FRAG_SPV)),
|
||||
convert_abgr8_to_d24s8_frag(BuildShader(device, CONVERT_ABGR8_TO_D24S8_FRAG_SPV)),
|
||||
convert_b10g11r11_to_d24s8_frag(BuildShader(device, CONVERT_B10G11R11_TO_D24S8_FRAG_SPV)),
|
||||
convert_r16g16_to_d24s8_frag(BuildShader(device, CONVERT_R16G16_TO_D24S8_FRAG_SPV)),
|
||||
convert_d24s8_to_abgr8_frag(BuildShader(device, CONVERT_D24S8_TO_ABGR8_FRAG_SPV)),
|
||||
convert_d24s8_to_b10g11r11_frag(BuildShader(device, CONVERT_D24S8_TO_B10G11R11_FRAG_SPV)),
|
||||
convert_d24s8_to_r16g16_frag(BuildShader(device, CONVERT_D24S8_TO_R16G16_FRAG_SPV)),
|
||||
linear_sampler(device.GetLogical().CreateSampler(SAMPLER_CREATE_INFO<VK_FILTER_LINEAR>)),
|
||||
nearest_sampler(device.GetLogical().CreateSampler(SAMPLER_CREATE_INFO<VK_FILTER_NEAREST>)) {
|
||||
if (device.IsExtShaderStencilExportSupported()) {
|
||||
@@ -461,30 +453,11 @@ void BlitImageHelper::ConvertR16ToD16(const Framebuffer* dst_framebuffer,
|
||||
}
|
||||
|
||||
void BlitImageHelper::ConvertABGR8ToD24S8(const Framebuffer* dst_framebuffer,
|
||||
const ImageView& src_image_view, u32 up_scale,
|
||||
u32 down_shift) {
|
||||
ImageView& src_image_view, u32 up_scale, u32 down_shift) {
|
||||
ConvertPipelineDepthTargetEx(convert_abgr8_to_d24s8_pipeline, dst_framebuffer->RenderPass(),
|
||||
convert_abgr8_to_d24s8_frag, true);
|
||||
Convert(*convert_abgr8_to_d24s8_pipeline, dst_framebuffer, src_image_view, up_scale,
|
||||
down_shift);
|
||||
}
|
||||
|
||||
void BlitImageHelper::ConvertB10G11R11ToD24S8(const Framebuffer* dst_framebuffer,
|
||||
const ImageView& src_image_view, u32 up_scale,
|
||||
u32 down_shift) {
|
||||
ConvertPipelineDepthTargetEx(convert_b10g11r11_to_d24s8_pipeline, dst_framebuffer->RenderPass(),
|
||||
convert_b10g11r11_to_d24s8_frag, true);
|
||||
Convert(*convert_b10g11r11_to_d24s8_pipeline, dst_framebuffer, src_image_view, up_scale,
|
||||
down_shift);
|
||||
}
|
||||
|
||||
void BlitImageHelper::ConvertR16G16ToD24S8(const Framebuffer* dst_framebuffer,
|
||||
const ImageView& src_image_view, u32 up_scale,
|
||||
u32 down_shift) {
|
||||
ConvertPipelineDepthTargetEx(convert_r16g16_to_d24s8_pipeline, dst_framebuffer->RenderPass(),
|
||||
convert_r16g16_to_d24s8_frag, true);
|
||||
Convert(*convert_r16g16_to_d24s8_pipeline, dst_framebuffer, src_image_view, up_scale,
|
||||
down_shift);
|
||||
ConvertColor(*convert_abgr8_to_d24s8_pipeline, dst_framebuffer, src_image_view, up_scale,
|
||||
down_shift);
|
||||
}
|
||||
|
||||
void BlitImageHelper::ConvertD24S8ToABGR8(const Framebuffer* dst_framebuffer,
|
||||
@@ -495,24 +468,6 @@ void BlitImageHelper::ConvertD24S8ToABGR8(const Framebuffer* dst_framebuffer,
|
||||
down_shift);
|
||||
}
|
||||
|
||||
void BlitImageHelper::ConvertD24S8ToB10G11R11(const Framebuffer* dst_framebuffer,
|
||||
ImageView& src_image_view, u32 up_scale,
|
||||
u32 down_shift) {
|
||||
ConvertPipelineColorTargetEx(convert_d24s8_to_b10g11r11_pipeline, dst_framebuffer->RenderPass(),
|
||||
convert_d24s8_to_b10g11r11_frag, false);
|
||||
ConvertDepthStencil(*convert_d24s8_to_b10g11r11_pipeline, dst_framebuffer, src_image_view,
|
||||
up_scale, down_shift);
|
||||
}
|
||||
|
||||
void BlitImageHelper::ConvertD24S8ToR16G16(const Framebuffer* dst_framebuffer,
|
||||
ImageView& src_image_view, u32 up_scale,
|
||||
u32 down_shift) {
|
||||
ConvertPipelineColorTargetEx(convert_d24s8_to_r16g16_pipeline, dst_framebuffer->RenderPass(),
|
||||
convert_d24s8_to_r16g16_frag, false);
|
||||
ConvertDepthStencil(*convert_d24s8_to_r16g16_pipeline, dst_framebuffer, src_image_view,
|
||||
up_scale, down_shift);
|
||||
}
|
||||
|
||||
void BlitImageHelper::Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
|
||||
const ImageView& src_image_view, u32 up_scale, u32 down_shift) {
|
||||
const VkPipelineLayout layout = *one_texture_pipeline_layout;
|
||||
@@ -560,6 +515,53 @@ void BlitImageHelper::Convert(VkPipeline pipeline, const Framebuffer* dst_frameb
|
||||
scheduler.InvalidateState();
|
||||
}
|
||||
|
||||
void BlitImageHelper::ConvertColor(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
|
||||
ImageView& src_image_view, u32 up_scale, u32 down_shift) {
|
||||
const VkPipelineLayout layout = *one_texture_pipeline_layout;
|
||||
const VkImageView src_view = src_image_view.ColorView();
|
||||
const VkSampler sampler = *nearest_sampler;
|
||||
const VkExtent2D extent{
|
||||
.width = std::max((src_image_view.size.width * up_scale) >> down_shift, 1U),
|
||||
.height = std::max((src_image_view.size.height * up_scale) >> down_shift, 1U),
|
||||
};
|
||||
scheduler.RequestRenderpass(dst_framebuffer);
|
||||
scheduler.Record([pipeline, layout, sampler, src_view, extent, up_scale, down_shift,
|
||||
this](vk::CommandBuffer cmdbuf) {
|
||||
const VkOffset2D offset{
|
||||
.x = 0,
|
||||
.y = 0,
|
||||
};
|
||||
const VkViewport viewport{
|
||||
.x = 0.0f,
|
||||
.y = 0.0f,
|
||||
.width = static_cast<float>(extent.width),
|
||||
.height = static_cast<float>(extent.height),
|
||||
.minDepth = 0.0f,
|
||||
.maxDepth = 0.0f,
|
||||
};
|
||||
const VkRect2D scissor{
|
||||
.offset = offset,
|
||||
.extent = extent,
|
||||
};
|
||||
const PushConstants push_constants{
|
||||
.tex_scale = {viewport.width, viewport.height},
|
||||
.tex_offset = {0.0f, 0.0f},
|
||||
};
|
||||
const VkDescriptorSet descriptor_set = one_texture_descriptor_allocator.Commit();
|
||||
UpdateOneTextureDescriptorSet(device, descriptor_set, sampler, src_view);
|
||||
|
||||
// TODO: Barriers
|
||||
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
|
||||
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptor_set,
|
||||
nullptr);
|
||||
cmdbuf.SetViewport(0, viewport);
|
||||
cmdbuf.SetScissor(0, scissor);
|
||||
cmdbuf.PushConstants(layout, VK_SHADER_STAGE_VERTEX_BIT, push_constants);
|
||||
cmdbuf.Draw(3, 1, 0, 0);
|
||||
});
|
||||
scheduler.InvalidateState();
|
||||
}
|
||||
|
||||
void BlitImageHelper::ConvertDepthStencil(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
|
||||
ImageView& src_image_view, u32 up_scale, u32 down_shift) {
|
||||
const VkPipelineLayout layout = *two_textures_pipeline_layout;
|
||||
|
||||
@@ -56,28 +56,19 @@ public:
|
||||
void ConvertR16ToD16(const Framebuffer* dst_framebuffer, const ImageView& src_image_view,
|
||||
u32 up_scale, u32 down_shift);
|
||||
|
||||
void ConvertABGR8ToD24S8(const Framebuffer* dst_framebuffer, const ImageView& src_image_view,
|
||||
void ConvertABGR8ToD24S8(const Framebuffer* dst_framebuffer, ImageView& src_image_view,
|
||||
u32 up_scale, u32 down_shift);
|
||||
|
||||
void ConvertB10G11R11ToD24S8(const Framebuffer* dst_framebuffer,
|
||||
const ImageView& src_image_view, u32 up_scale, u32 down_shift);
|
||||
|
||||
void ConvertR16G16ToD24S8(const Framebuffer* dst_framebuffer, const ImageView& src_image_view,
|
||||
u32 up_scale, u32 down_shift);
|
||||
|
||||
void ConvertD24S8ToABGR8(const Framebuffer* dst_framebuffer, ImageView& src_image_view,
|
||||
u32 up_scale, u32 down_shift);
|
||||
|
||||
void ConvertD24S8ToB10G11R11(const Framebuffer* dst_framebuffer, ImageView& src_image_view,
|
||||
u32 up_scale, u32 down_shift);
|
||||
|
||||
void ConvertD24S8ToR16G16(const Framebuffer* dst_framebuffer, ImageView& src_image_view,
|
||||
u32 up_scale, u32 down_shift);
|
||||
|
||||
private:
|
||||
void Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
|
||||
const ImageView& src_image_view, u32 up_scale, u32 down_shift);
|
||||
|
||||
void ConvertColor(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
|
||||
ImageView& src_image_view, u32 up_scale, u32 down_shift);
|
||||
|
||||
void ConvertDepthStencil(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
|
||||
ImageView& src_image_view, u32 up_scale, u32 down_shift);
|
||||
|
||||
@@ -114,11 +105,7 @@ private:
|
||||
vk::ShaderModule convert_depth_to_float_frag;
|
||||
vk::ShaderModule convert_float_to_depth_frag;
|
||||
vk::ShaderModule convert_abgr8_to_d24s8_frag;
|
||||
vk::ShaderModule convert_b10g11r11_to_d24s8_frag;
|
||||
vk::ShaderModule convert_r16g16_to_d24s8_frag;
|
||||
vk::ShaderModule convert_d24s8_to_abgr8_frag;
|
||||
vk::ShaderModule convert_d24s8_to_b10g11r11_frag;
|
||||
vk::ShaderModule convert_d24s8_to_r16g16_frag;
|
||||
vk::Sampler linear_sampler;
|
||||
vk::Sampler nearest_sampler;
|
||||
|
||||
@@ -131,11 +118,7 @@ private:
|
||||
vk::Pipeline convert_d16_to_r16_pipeline;
|
||||
vk::Pipeline convert_r16_to_d16_pipeline;
|
||||
vk::Pipeline convert_abgr8_to_d24s8_pipeline;
|
||||
vk::Pipeline convert_b10g11r11_to_d24s8_pipeline;
|
||||
vk::Pipeline convert_r16g16_to_d24s8_pipeline;
|
||||
vk::Pipeline convert_d24s8_to_abgr8_pipeline;
|
||||
vk::Pipeline convert_d24s8_to_b10g11r11_pipeline;
|
||||
vk::Pipeline convert_d24s8_to_r16g16_pipeline;
|
||||
};
|
||||
|
||||
} // namespace Vulkan
|
||||
|
||||
@@ -775,8 +775,18 @@ StagingBufferRef TextureCacheRuntime::DownloadStagingBuffer(size_t size) {
|
||||
|
||||
bool TextureCacheRuntime::ShouldReinterpret(Image& dst, Image& src) {
|
||||
if (VideoCore::Surface::GetFormatType(dst.info.format) ==
|
||||
VideoCore::Surface::SurfaceType::DepthStencil) {
|
||||
return !device.IsExtShaderStencilExportSupported();
|
||||
VideoCore::Surface::SurfaceType::DepthStencil &&
|
||||
!device.IsExtShaderStencilExportSupported()) {
|
||||
return true;
|
||||
}
|
||||
if (VideoCore::Surface::GetFormatType(src.info.format) ==
|
||||
VideoCore::Surface::SurfaceType::DepthStencil &&
|
||||
!device.IsExtShaderStencilExportSupported()) {
|
||||
return true;
|
||||
}
|
||||
if (dst.info.format == PixelFormat::D32_FLOAT_S8_UINT ||
|
||||
src.info.format == PixelFormat::D32_FLOAT_S8_UINT) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -1058,21 +1068,10 @@ void TextureCacheRuntime::ConvertImage(Framebuffer* dst, ImageView& dst_view, Im
|
||||
}
|
||||
break;
|
||||
case PixelFormat::A8B8G8R8_UNORM:
|
||||
case PixelFormat::B8G8R8A8_UNORM:
|
||||
if (src_view.format == PixelFormat::S8_UINT_D24_UNORM) {
|
||||
return blit_image_helper.ConvertD24S8ToABGR8(dst, src_view, up_scale, down_shift);
|
||||
}
|
||||
break;
|
||||
case PixelFormat::B10G11R11_FLOAT:
|
||||
if (src_view.format == PixelFormat::S8_UINT_D24_UNORM) {
|
||||
return blit_image_helper.ConvertD24S8ToB10G11R11(dst, src_view, up_scale, down_shift);
|
||||
}
|
||||
break;
|
||||
case PixelFormat::R16G16_UNORM:
|
||||
if (src_view.format == PixelFormat::S8_UINT_D24_UNORM) {
|
||||
return blit_image_helper.ConvertD24S8ToR16G16(dst, src_view, up_scale, down_shift);
|
||||
}
|
||||
break;
|
||||
case PixelFormat::R32_FLOAT:
|
||||
if (src_view.format == PixelFormat::D32_FLOAT) {
|
||||
return blit_image_helper.ConvertD32ToR32(dst, src_view, up_scale, down_shift);
|
||||
@@ -1084,16 +1083,7 @@ void TextureCacheRuntime::ConvertImage(Framebuffer* dst, ImageView& dst_view, Im
|
||||
}
|
||||
break;
|
||||
case PixelFormat::S8_UINT_D24_UNORM:
|
||||
if (src_view.format == PixelFormat::A8B8G8R8_UNORM ||
|
||||
src_view.format == PixelFormat::B8G8R8A8_UNORM) {
|
||||
return blit_image_helper.ConvertABGR8ToD24S8(dst, src_view, up_scale, down_shift);
|
||||
}
|
||||
if (src_view.format == PixelFormat::B10G11R11_FLOAT) {
|
||||
return blit_image_helper.ConvertB10G11R11ToD24S8(dst, src_view, up_scale, down_shift);
|
||||
}
|
||||
if (src_view.format == PixelFormat::R16G16_UNORM) {
|
||||
return blit_image_helper.ConvertR16G16ToD24S8(dst, src_view, up_scale, down_shift);
|
||||
}
|
||||
return blit_image_helper.ConvertABGR8ToD24S8(dst, src_view, up_scale, down_shift);
|
||||
break;
|
||||
case PixelFormat::D32_FLOAT:
|
||||
if (src_view.format == PixelFormat::R32_FLOAT) {
|
||||
@@ -1590,6 +1580,14 @@ VkImageView ImageView::StencilView() {
|
||||
return *stencil_view;
|
||||
}
|
||||
|
||||
VkImageView ImageView::ColorView() {
|
||||
if (color_view) {
|
||||
return *color_view;
|
||||
}
|
||||
color_view = MakeView(VK_FORMAT_R8G8B8A8_UNORM, VK_IMAGE_ASPECT_COLOR_BIT);
|
||||
return *color_view;
|
||||
}
|
||||
|
||||
VkImageView ImageView::StorageView(Shader::TextureType texture_type,
|
||||
Shader::ImageFormat image_format) {
|
||||
if (image_format == Shader::ImageFormat::Typeless) {
|
||||
|
||||
@@ -184,6 +184,8 @@ public:
|
||||
|
||||
[[nodiscard]] VkImageView StencilView();
|
||||
|
||||
[[nodiscard]] VkImageView ColorView();
|
||||
|
||||
[[nodiscard]] VkImageView StorageView(Shader::TextureType texture_type,
|
||||
Shader::ImageFormat image_format);
|
||||
|
||||
@@ -224,6 +226,7 @@ private:
|
||||
std::unique_ptr<StorageViews> storage_views;
|
||||
vk::ImageView depth_view;
|
||||
vk::ImageView stencil_view;
|
||||
vk::ImageView color_view;
|
||||
VkImage image_handle = VK_NULL_HANDLE;
|
||||
VkImageView render_target = VK_NULL_HANDLE;
|
||||
VkSampleCountFlagBits samples = VK_SAMPLE_COUNT_1_BIT;
|
||||
|
||||
@@ -472,7 +472,7 @@ template <class P>
|
||||
void TextureCache<P>::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst,
|
||||
const Tegra::Engines::Fermi2D::Surface& src,
|
||||
const Tegra::Engines::Fermi2D::Config& copy) {
|
||||
const BlitImages images = GetBlitImages(dst, src);
|
||||
const BlitImages images = GetBlitImages(dst, src, copy);
|
||||
const ImageId dst_id = images.dst_id;
|
||||
const ImageId src_id = images.src_id;
|
||||
|
||||
@@ -762,12 +762,15 @@ ImageId TextureCache<P>::FindImage(const ImageInfo& info, GPUVAddr gpu_addr,
|
||||
const bool broken_views =
|
||||
runtime.HasBrokenTextureViewFormats() || True(options & RelaxedOptions::ForceBrokenViews);
|
||||
const bool native_bgr = runtime.HasNativeBgr();
|
||||
ImageId image_id;
|
||||
const bool flexible_formats = True(options & RelaxedOptions::Format);
|
||||
ImageId image_id{};
|
||||
boost::container::small_vector<ImageId, 1> image_ids;
|
||||
const auto lambda = [&](ImageId existing_image_id, ImageBase& existing_image) {
|
||||
if (True(existing_image.flags & ImageFlagBits::Remapped)) {
|
||||
return false;
|
||||
}
|
||||
if (info.type == ImageType::Linear || existing_image.info.type == ImageType::Linear) {
|
||||
if (info.type == ImageType::Linear || existing_image.info.type == ImageType::Linear)
|
||||
[[unlikely]] {
|
||||
const bool strict_size = False(options & RelaxedOptions::Size) &&
|
||||
True(existing_image.flags & ImageFlagBits::Strong);
|
||||
const ImageInfo& existing = existing_image.info;
|
||||
@@ -776,17 +779,27 @@ ImageId TextureCache<P>::FindImage(const ImageInfo& info, GPUVAddr gpu_addr,
|
||||
IsPitchLinearSameSize(existing, info, strict_size) &&
|
||||
IsViewCompatible(existing.format, info.format, broken_views, native_bgr)) {
|
||||
image_id = existing_image_id;
|
||||
return true;
|
||||
image_ids.push_back(existing_image_id);
|
||||
return !flexible_formats && existing.format == info.format;
|
||||
}
|
||||
} else if (IsSubresource(info, existing_image, gpu_addr, options, broken_views,
|
||||
native_bgr)) {
|
||||
image_id = existing_image_id;
|
||||
return true;
|
||||
image_ids.push_back(existing_image_id);
|
||||
return !flexible_formats && existing_image.info.format == info.format;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
ForEachImageInRegion(*cpu_addr, CalculateGuestSizeInBytes(info), lambda);
|
||||
return image_id;
|
||||
if (image_ids.size() <= 1) [[likely]] {
|
||||
return image_id;
|
||||
}
|
||||
auto image_ids_compare = [this](ImageId a, ImageId b) {
|
||||
auto& image_a = slot_images[a];
|
||||
auto& image_b = slot_images[b];
|
||||
return image_a.modification_tick < image_b.modification_tick;
|
||||
};
|
||||
return *std::ranges::max_element(image_ids, image_ids_compare);
|
||||
}
|
||||
|
||||
template <class P>
|
||||
@@ -1078,32 +1091,58 @@ ImageId TextureCache<P>::JoinImages(const ImageInfo& info, GPUVAddr gpu_addr, VA
|
||||
|
||||
template <class P>
|
||||
typename TextureCache<P>::BlitImages TextureCache<P>::GetBlitImages(
|
||||
const Tegra::Engines::Fermi2D::Surface& dst, const Tegra::Engines::Fermi2D::Surface& src) {
|
||||
static constexpr auto FIND_OPTIONS = RelaxedOptions::Format | RelaxedOptions::Samples;
|
||||
const Tegra::Engines::Fermi2D::Surface& dst, const Tegra::Engines::Fermi2D::Surface& src,
|
||||
const Tegra::Engines::Fermi2D::Config& copy) {
|
||||
|
||||
static constexpr auto FIND_OPTIONS = RelaxedOptions::Samples;
|
||||
const GPUVAddr dst_addr = dst.Address();
|
||||
const GPUVAddr src_addr = src.Address();
|
||||
ImageInfo dst_info(dst);
|
||||
ImageInfo src_info(src);
|
||||
const bool can_be_depth_blit =
|
||||
dst_info.format == src_info.format && copy.filter == Tegra::Engines::Fermi2D::Filter::Point;
|
||||
ImageId dst_id;
|
||||
ImageId src_id;
|
||||
RelaxedOptions try_options = FIND_OPTIONS;
|
||||
if (can_be_depth_blit) {
|
||||
try_options |= RelaxedOptions::Format;
|
||||
}
|
||||
do {
|
||||
has_deleted_images = false;
|
||||
dst_id = FindImage(dst_info, dst_addr, FIND_OPTIONS);
|
||||
src_id = FindImage(src_info, src_addr, FIND_OPTIONS);
|
||||
const ImageBase* const dst_image = dst_id ? &slot_images[dst_id] : nullptr;
|
||||
src_id = FindImage(src_info, src_addr, try_options);
|
||||
dst_id = FindImage(dst_info, dst_addr, try_options);
|
||||
const ImageBase* const src_image = src_id ? &slot_images[src_id] : nullptr;
|
||||
DeduceBlitImages(dst_info, src_info, dst_image, src_image);
|
||||
if (GetFormatType(dst_info.format) != GetFormatType(src_info.format)) {
|
||||
continue;
|
||||
if (src_image && src_image->info.num_samples > 1) {
|
||||
RelaxedOptions find_options{FIND_OPTIONS | RelaxedOptions::ForceBrokenViews};
|
||||
src_id = FindOrInsertImage(src_info, src_addr, find_options);
|
||||
dst_id = FindOrInsertImage(dst_info, dst_addr, find_options);
|
||||
if (has_deleted_images) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
RelaxedOptions find_options{};
|
||||
if (src_info.num_samples > 1) {
|
||||
// it's a resolve, we must enforce the same format.
|
||||
find_options = RelaxedOptions::ForceBrokenViews;
|
||||
if (can_be_depth_blit) {
|
||||
const ImageBase* const dst_image = src_id ? &slot_images[src_id] : nullptr;
|
||||
DeduceBlitImages(dst_info, src_info, dst_image, src_image);
|
||||
if (GetFormatType(dst_info.format) != GetFormatType(src_info.format)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!src_id) {
|
||||
src_id = InsertImage(src_info, src_addr, RelaxedOptions{});
|
||||
}
|
||||
if (!dst_id) {
|
||||
dst_id = InsertImage(dst_info, dst_addr, RelaxedOptions{});
|
||||
}
|
||||
src_id = FindOrInsertImage(src_info, src_addr, find_options);
|
||||
dst_id = FindOrInsertImage(dst_info, dst_addr, find_options);
|
||||
} while (has_deleted_images);
|
||||
if (GetFormatType(dst_info.format) != SurfaceType::ColorTexture) {
|
||||
// Make sure the images are depth and/or stencil textures.
|
||||
do {
|
||||
has_deleted_images = false;
|
||||
src_id = FindOrInsertImage(src_info, src_addr, RelaxedOptions{});
|
||||
dst_id = FindOrInsertImage(dst_info, dst_addr, RelaxedOptions{});
|
||||
} while (has_deleted_images);
|
||||
}
|
||||
return BlitImages{
|
||||
.dst_id = dst_id,
|
||||
.src_id = src_id,
|
||||
@@ -1160,7 +1199,14 @@ template <class P>
|
||||
ImageViewId TextureCache<P>::FindRenderTargetView(const ImageInfo& info, GPUVAddr gpu_addr,
|
||||
bool is_clear) {
|
||||
const auto options = is_clear ? RelaxedOptions::Samples : RelaxedOptions{};
|
||||
const ImageId image_id = FindOrInsertImage(info, gpu_addr, options);
|
||||
ImageId image_id{};
|
||||
bool delete_state = has_deleted_images;
|
||||
do {
|
||||
has_deleted_images = false;
|
||||
image_id = FindOrInsertImage(info, gpu_addr, options);
|
||||
delete_state |= has_deleted_images;
|
||||
} while (has_deleted_images);
|
||||
has_deleted_images = delete_state;
|
||||
if (!image_id) {
|
||||
return NULL_IMAGE_VIEW_ID;
|
||||
}
|
||||
@@ -1783,7 +1829,13 @@ void TextureCache<P>::CopyImage(ImageId dst_id, ImageId src_id, std::vector<Imag
|
||||
const SubresourceExtent src_extent{.levels = 1, .layers = 1};
|
||||
const SubresourceRange dst_range{.base = dst_base, .extent = dst_extent};
|
||||
const SubresourceRange src_range{.base = src_base, .extent = src_extent};
|
||||
const ImageViewInfo dst_view_info(ImageViewType::e2D, dst.info.format, dst_range);
|
||||
PixelFormat dst_format = dst.info.format;
|
||||
if (GetFormatType(src.info.format) == SurfaceType::DepthStencil &&
|
||||
GetFormatType(dst_format) == SurfaceType::ColorTexture &&
|
||||
BytesPerBlock(dst_format) == 4) {
|
||||
dst_format = PixelFormat::A8B8G8R8_UNORM;
|
||||
}
|
||||
const ImageViewInfo dst_view_info(ImageViewType::e2D, dst_format, dst_range);
|
||||
const ImageViewInfo src_view_info(ImageViewType::e2D, src.info.format, src_range);
|
||||
const auto [dst_framebuffer_id, dst_view_id] = RenderTargetFromImage(dst_id, dst_view_info);
|
||||
Framebuffer* const dst_framebuffer = &slot_framebuffers[dst_framebuffer_id];
|
||||
|
||||
@@ -252,7 +252,8 @@ private:
|
||||
|
||||
/// Return a blit image pair from the given guest blit parameters
|
||||
[[nodiscard]] BlitImages GetBlitImages(const Tegra::Engines::Fermi2D::Surface& dst,
|
||||
const Tegra::Engines::Fermi2D::Surface& src);
|
||||
const Tegra::Engines::Fermi2D::Surface& src,
|
||||
const Tegra::Engines::Fermi2D::Config& copy);
|
||||
|
||||
/// Find or create a sampler from a guest descriptor sampler
|
||||
[[nodiscard]] SamplerId FindSampler(const TSCEntry& config);
|
||||
|
||||
@@ -1151,28 +1151,15 @@ bool IsSubresource(const ImageInfo& candidate, const ImageBase& image, GPUVAddr
|
||||
|
||||
void DeduceBlitImages(ImageInfo& dst_info, ImageInfo& src_info, const ImageBase* dst,
|
||||
const ImageBase* src) {
|
||||
bool is_resolve = false;
|
||||
const auto original_src_format = src_info.format;
|
||||
const auto original_dst_format = dst_info.format;
|
||||
if (src) {
|
||||
if (GetFormatType(src->info.format) != SurfaceType::ColorTexture) {
|
||||
src_info.format = src->info.format;
|
||||
}
|
||||
is_resolve = src->info.num_samples > 1;
|
||||
src_info.num_samples = src->info.num_samples;
|
||||
src_info.size = src->info.size;
|
||||
if (src && GetFormatType(src->info.format) != SurfaceType::ColorTexture) {
|
||||
src_info.format = src->info.format;
|
||||
}
|
||||
if (dst && GetFormatType(dst->info.format) != SurfaceType::ColorTexture) {
|
||||
dst_info.format = dst->info.format;
|
||||
}
|
||||
if (src && GetFormatType(src->info.format) != SurfaceType::ColorTexture) {
|
||||
if (dst) {
|
||||
if (GetFormatType(dst->info.format) == SurfaceType::ColorTexture) {
|
||||
src_info.format = original_src_format;
|
||||
}
|
||||
} else {
|
||||
dst_info.format = src->info.format;
|
||||
}
|
||||
dst_info.format = src->info.format;
|
||||
}
|
||||
if (dst && GetFormatType(dst->info.format) != SurfaceType::ColorTexture) {
|
||||
if (src) {
|
||||
@@ -1183,7 +1170,6 @@ void DeduceBlitImages(ImageInfo& dst_info, ImageInfo& src_info, const ImageBase*
|
||||
src_info.format = dst->info.format;
|
||||
}
|
||||
}
|
||||
ASSERT(!is_resolve || dst_info.format == src_info.format);
|
||||
}
|
||||
|
||||
u32 MapSizeBytes(const ImageBase& image) {
|
||||
|
||||
@@ -139,7 +139,6 @@ QtControllerSelectorDialog::QtControllerSelectorDialog(
|
||||
DisableUnsupportedPlayers();
|
||||
|
||||
for (std::size_t player_index = 0; player_index < NUM_PLAYERS; ++player_index) {
|
||||
system.HIDCore().GetEmulatedControllerByIndex(player_index)->EnableConfiguration();
|
||||
SetEmulatedControllers(player_index);
|
||||
}
|
||||
|
||||
@@ -218,7 +217,9 @@ QtControllerSelectorDialog::QtControllerSelectorDialog(
|
||||
resize(0, 0);
|
||||
}
|
||||
|
||||
QtControllerSelectorDialog::~QtControllerSelectorDialog() = default;
|
||||
QtControllerSelectorDialog::~QtControllerSelectorDialog() {
|
||||
system.HIDCore().DisableAllControllerConfiguration();
|
||||
}
|
||||
|
||||
int QtControllerSelectorDialog::exec() {
|
||||
if (parameters_met && parameters.enable_single_mode) {
|
||||
@@ -234,12 +235,11 @@ void QtControllerSelectorDialog::ApplyConfiguration() {
|
||||
|
||||
Settings::values.vibration_enabled.SetValue(ui->vibrationGroup->isChecked());
|
||||
Settings::values.motion_enabled.SetValue(ui->motionGroup->isChecked());
|
||||
for (std::size_t player_index = 0; player_index < NUM_PLAYERS; ++player_index) {
|
||||
system.HIDCore().GetEmulatedControllerByIndex(player_index)->DisableConfiguration();
|
||||
}
|
||||
}
|
||||
|
||||
void QtControllerSelectorDialog::LoadConfiguration() {
|
||||
system.HIDCore().EnableAllControllerConfiguration();
|
||||
|
||||
const auto* handheld = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Handheld);
|
||||
for (std::size_t index = 0; index < NUM_PLAYERS; ++index) {
|
||||
const auto* controller = system.HIDCore().GetEmulatedControllerByIndex(index);
|
||||
|
||||
@@ -508,6 +508,7 @@ void Config::ReadDebuggingValues() {
|
||||
ReadBasicSetting(Settings::values.extended_logging);
|
||||
ReadBasicSetting(Settings::values.use_debug_asserts);
|
||||
ReadBasicSetting(Settings::values.use_auto_stub);
|
||||
ReadBasicSetting(Settings::values.enable_all_controllers);
|
||||
|
||||
qt_config->endGroup();
|
||||
}
|
||||
@@ -1051,6 +1052,7 @@ void Config::SaveDebuggingValues() {
|
||||
WriteBasicSetting(Settings::values.quest_flag);
|
||||
WriteBasicSetting(Settings::values.use_debug_asserts);
|
||||
WriteBasicSetting(Settings::values.disable_macro_jit);
|
||||
WriteBasicSetting(Settings::values.enable_all_controllers);
|
||||
|
||||
qt_config->endGroup();
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ void ConfigureDebug::SetConfiguration() {
|
||||
ui->quest_flag->setChecked(Settings::values.quest_flag.GetValue());
|
||||
ui->use_debug_asserts->setChecked(Settings::values.use_debug_asserts.GetValue());
|
||||
ui->use_auto_stub->setChecked(Settings::values.use_auto_stub.GetValue());
|
||||
ui->enable_all_controllers->setChecked(Settings::values.enable_all_controllers.GetValue());
|
||||
ui->enable_graphics_debugging->setEnabled(runtime_lock);
|
||||
ui->enable_graphics_debugging->setChecked(Settings::values.renderer_debug.GetValue());
|
||||
ui->enable_shader_feedback->setEnabled(runtime_lock);
|
||||
@@ -67,6 +68,7 @@ void ConfigureDebug::ApplyConfiguration() {
|
||||
Settings::values.quest_flag = ui->quest_flag->isChecked();
|
||||
Settings::values.use_debug_asserts = ui->use_debug_asserts->isChecked();
|
||||
Settings::values.use_auto_stub = ui->use_auto_stub->isChecked();
|
||||
Settings::values.enable_all_controllers = ui->enable_all_controllers->isChecked();
|
||||
Settings::values.renderer_debug = ui->enable_graphics_debugging->isChecked();
|
||||
Settings::values.renderer_shader_feedback = ui->enable_shader_feedback->isChecked();
|
||||
Settings::values.cpu_debug_mode = ui->enable_cpu_debugging->isChecked();
|
||||
|
||||
@@ -198,6 +198,13 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QCheckBox" name="enable_all_controllers">
|
||||
<property name="text">
|
||||
<string>Enable all Controller Types</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
@@ -246,15 +246,15 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
||||
if (player_index == 0) {
|
||||
auto* emulated_controller_p1 =
|
||||
hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1);
|
||||
auto* emulated_controller_hanheld =
|
||||
auto* emulated_controller_handheld =
|
||||
hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld);
|
||||
emulated_controller_p1->SaveCurrentConfig();
|
||||
emulated_controller_p1->EnableConfiguration();
|
||||
emulated_controller_hanheld->SaveCurrentConfig();
|
||||
emulated_controller_hanheld->EnableConfiguration();
|
||||
if (emulated_controller_hanheld->IsConnected(true)) {
|
||||
emulated_controller_handheld->SaveCurrentConfig();
|
||||
emulated_controller_handheld->EnableConfiguration();
|
||||
if (emulated_controller_handheld->IsConnected(true)) {
|
||||
emulated_controller_p1->Disconnect();
|
||||
emulated_controller = emulated_controller_hanheld;
|
||||
emulated_controller = emulated_controller_handheld;
|
||||
} else {
|
||||
emulated_controller = emulated_controller_p1;
|
||||
}
|
||||
@@ -590,19 +590,19 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
|
||||
if (player_index == 0) {
|
||||
auto* emulated_controller_p1 =
|
||||
hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1);
|
||||
auto* emulated_controller_hanheld =
|
||||
auto* emulated_controller_handheld =
|
||||
hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld);
|
||||
bool is_connected = emulated_controller->IsConnected(true);
|
||||
|
||||
emulated_controller_p1->SetNpadStyleIndex(type);
|
||||
emulated_controller_hanheld->SetNpadStyleIndex(type);
|
||||
emulated_controller_handheld->SetNpadStyleIndex(type);
|
||||
if (is_connected) {
|
||||
if (type == Core::HID::NpadStyleIndex::Handheld) {
|
||||
emulated_controller_p1->Disconnect();
|
||||
emulated_controller_hanheld->Connect();
|
||||
emulated_controller = emulated_controller_hanheld;
|
||||
emulated_controller_handheld->Connect();
|
||||
emulated_controller = emulated_controller_handheld;
|
||||
} else {
|
||||
emulated_controller_hanheld->Disconnect();
|
||||
emulated_controller_handheld->Disconnect();
|
||||
emulated_controller_p1->Connect();
|
||||
emulated_controller = emulated_controller_p1;
|
||||
}
|
||||
@@ -650,10 +650,10 @@ ConfigureInputPlayer::~ConfigureInputPlayer() {
|
||||
if (player_index == 0) {
|
||||
auto* emulated_controller_p1 =
|
||||
hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1);
|
||||
auto* emulated_controller_hanheld =
|
||||
auto* emulated_controller_handheld =
|
||||
hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld);
|
||||
emulated_controller_p1->DisableConfiguration();
|
||||
emulated_controller_hanheld->DisableConfiguration();
|
||||
emulated_controller_handheld->DisableConfiguration();
|
||||
} else {
|
||||
emulated_controller->DisableConfiguration();
|
||||
}
|
||||
@@ -663,14 +663,14 @@ void ConfigureInputPlayer::ApplyConfiguration() {
|
||||
if (player_index == 0) {
|
||||
auto* emulated_controller_p1 =
|
||||
hid_core.GetEmulatedController(Core::HID::NpadIdType::Player1);
|
||||
auto* emulated_controller_hanheld =
|
||||
auto* emulated_controller_handheld =
|
||||
hid_core.GetEmulatedController(Core::HID::NpadIdType::Handheld);
|
||||
emulated_controller_p1->DisableConfiguration();
|
||||
emulated_controller_p1->SaveCurrentConfig();
|
||||
emulated_controller_p1->EnableConfiguration();
|
||||
emulated_controller_hanheld->DisableConfiguration();
|
||||
emulated_controller_hanheld->SaveCurrentConfig();
|
||||
emulated_controller_hanheld->EnableConfiguration();
|
||||
emulated_controller_handheld->DisableConfiguration();
|
||||
emulated_controller_handheld->SaveCurrentConfig();
|
||||
emulated_controller_handheld->EnableConfiguration();
|
||||
return;
|
||||
}
|
||||
emulated_controller->DisableConfiguration();
|
||||
@@ -947,6 +947,40 @@ void ConfigureInputPlayer::SetConnectableControllers() {
|
||||
Core::HID::NpadStyleIndex::GameCube);
|
||||
ui->comboControllerType->addItem(tr("GameCube Controller"));
|
||||
}
|
||||
|
||||
// Disable all unsupported controllers
|
||||
if (!Settings::values.enable_all_controllers) {
|
||||
return;
|
||||
}
|
||||
if (enable_all || npad_style_set.palma == 1) {
|
||||
index_controller_type_pairs.emplace_back(ui->comboControllerType->count(),
|
||||
Core::HID::NpadStyleIndex::Pokeball);
|
||||
ui->comboControllerType->addItem(tr("Poke Ball Plus"));
|
||||
}
|
||||
|
||||
if (enable_all || npad_style_set.lark == 1) {
|
||||
index_controller_type_pairs.emplace_back(ui->comboControllerType->count(),
|
||||
Core::HID::NpadStyleIndex::NES);
|
||||
ui->comboControllerType->addItem(tr("NES Controller"));
|
||||
}
|
||||
|
||||
if (enable_all || npad_style_set.lucia == 1) {
|
||||
index_controller_type_pairs.emplace_back(ui->comboControllerType->count(),
|
||||
Core::HID::NpadStyleIndex::SNES);
|
||||
ui->comboControllerType->addItem(tr("SNES Controller"));
|
||||
}
|
||||
|
||||
if (enable_all || npad_style_set.lagoon == 1) {
|
||||
index_controller_type_pairs.emplace_back(ui->comboControllerType->count(),
|
||||
Core::HID::NpadStyleIndex::N64);
|
||||
ui->comboControllerType->addItem(tr("N64 Controller"));
|
||||
}
|
||||
|
||||
if (enable_all || npad_style_set.lager == 1) {
|
||||
index_controller_type_pairs.emplace_back(ui->comboControllerType->count(),
|
||||
Core::HID::NpadStyleIndex::SegaGenesis);
|
||||
ui->comboControllerType->addItem(tr("Sega Genesis"));
|
||||
}
|
||||
};
|
||||
|
||||
if (!is_powered_on) {
|
||||
|
||||
+28
-26
@@ -3479,36 +3479,38 @@ void GMainWindow::filterBarSetChecked(bool state) {
|
||||
}
|
||||
|
||||
void GMainWindow::UpdateUITheme() {
|
||||
const QString default_icons = QStringLiteral("default");
|
||||
const QString& current_theme = UISettings::values.theme;
|
||||
const bool is_default_theme = current_theme == QString::fromUtf8(UISettings::themes[0].second);
|
||||
const QString default_theme = QStringLiteral("default");
|
||||
QString current_theme = UISettings::values.theme;
|
||||
QStringList theme_paths(default_theme_paths);
|
||||
|
||||
if (is_default_theme || current_theme.isEmpty()) {
|
||||
const QString theme_uri(QStringLiteral(":default/style.qss"));
|
||||
QFile f(theme_uri);
|
||||
if (f.open(QFile::ReadOnly | QFile::Text)) {
|
||||
QTextStream ts(&f);
|
||||
qApp->setStyleSheet(ts.readAll());
|
||||
setStyleSheet(ts.readAll());
|
||||
} else {
|
||||
qApp->setStyleSheet({});
|
||||
setStyleSheet({});
|
||||
}
|
||||
QIcon::setThemeName(default_icons);
|
||||
} else {
|
||||
const QString theme_uri(QLatin1Char{':'} + current_theme + QStringLiteral("/style.qss"));
|
||||
QFile f(theme_uri);
|
||||
if (f.open(QFile::ReadOnly | QFile::Text)) {
|
||||
QTextStream ts(&f);
|
||||
qApp->setStyleSheet(ts.readAll());
|
||||
setStyleSheet(ts.readAll());
|
||||
} else {
|
||||
LOG_ERROR(Frontend, "Unable to set style, stylesheet file not found");
|
||||
}
|
||||
QIcon::setThemeName(current_theme);
|
||||
if (current_theme.isEmpty()) {
|
||||
current_theme = default_theme;
|
||||
}
|
||||
|
||||
if (current_theme != default_theme) {
|
||||
QString theme_uri{QStringLiteral(":%1/style.qss").arg(current_theme)};
|
||||
QFile f(theme_uri);
|
||||
if (!f.open(QFile::ReadOnly | QFile::Text)) {
|
||||
LOG_ERROR(Frontend, "Unable to open style \"{}\", fallback to the default theme",
|
||||
UISettings::values.theme.toStdString());
|
||||
current_theme = default_theme;
|
||||
}
|
||||
}
|
||||
|
||||
QString theme_uri{QStringLiteral(":%1/style.qss").arg(current_theme)};
|
||||
QFile f(theme_uri);
|
||||
if (f.open(QFile::ReadOnly | QFile::Text)) {
|
||||
QTextStream ts(&f);
|
||||
qApp->setStyleSheet(ts.readAll());
|
||||
setStyleSheet(ts.readAll());
|
||||
} else {
|
||||
LOG_ERROR(Frontend, "Unable to set style \"{}\", stylesheet file not found",
|
||||
UISettings::values.theme.toStdString());
|
||||
qApp->setStyleSheet({});
|
||||
setStyleSheet({});
|
||||
}
|
||||
|
||||
QIcon::setThemeName(current_theme);
|
||||
QIcon::setThemeSearchPaths(theme_paths);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
namespace UISettings {
|
||||
|
||||
const Themes themes{{
|
||||
{"Light", "default"},
|
||||
{"Light Colorful", "colorful"},
|
||||
{"Default", "default"},
|
||||
{"Default Colorful", "colorful"},
|
||||
{"Dark", "qdarkstyle"},
|
||||
{"Dark Colorful", "colorful_dark"},
|
||||
{"Midnight Blue", "qdarkstyle_midnight_blue"},
|
||||
|
||||
Reference in New Issue
Block a user