Compare commits

..

2 Commits

Author SHA1 Message Date
lat9nq
287a0f72a5 decoders: Break instead of continue
continue causes a memory leak in A Hat in Time.
2021-06-04 05:12:14 -04:00
lat9nq
1feefabeba decoders: Avoid out-of-bounds access
This is not a real fix, so assert here and continue before crashing.
2021-06-04 05:03:54 -04:00
13 changed files with 34 additions and 217 deletions

View File

@@ -124,21 +124,21 @@ union ResultCode {
constexpr ResultCode(ErrorModule module_, u32 description_)
: raw(module.FormatValue(module_) | description.FormatValue(description_)) {}
[[nodiscard]] constexpr bool IsSuccess() const {
constexpr bool IsSuccess() const {
return raw == 0;
}
[[nodiscard]] constexpr bool IsError() const {
return !IsSuccess();
constexpr bool IsError() const {
return raw != 0;
}
};
[[nodiscard]] constexpr bool operator==(const ResultCode& a, const ResultCode& b) {
constexpr bool operator==(const ResultCode& a, const ResultCode& b) {
return a.raw == b.raw;
}
[[nodiscard]] constexpr bool operator!=(const ResultCode& a, const ResultCode& b) {
return !operator==(a, b);
constexpr bool operator!=(const ResultCode& a, const ResultCode& b) {
return a.raw != b.raw;
}
// Convenience functions for creating some common kinds of errors:
@@ -200,7 +200,7 @@ public:
* specify the success code. `success_code` must not be an error code.
*/
template <typename... Args>
[[nodiscard]] static ResultVal WithCode(ResultCode success_code, Args&&... args) {
static ResultVal WithCode(ResultCode success_code, Args&&... args) {
ResultVal<T> result;
result.emplace(success_code, std::forward<Args>(args)...);
return result;
@@ -259,49 +259,49 @@ public:
}
/// Returns true if the `ResultVal` contains an error code and no value.
[[nodiscard]] bool empty() const {
bool empty() const {
return result_code.IsError();
}
/// Returns true if the `ResultVal` contains a return value.
[[nodiscard]] bool Succeeded() const {
bool Succeeded() const {
return result_code.IsSuccess();
}
/// Returns true if the `ResultVal` contains an error code and no value.
[[nodiscard]] bool Failed() const {
bool Failed() const {
return empty();
}
[[nodiscard]] ResultCode Code() const {
ResultCode Code() const {
return result_code;
}
[[nodiscard]] const T& operator*() const {
const T& operator*() const {
return object;
}
[[nodiscard]] T& operator*() {
T& operator*() {
return object;
}
[[nodiscard]] const T* operator->() const {
const T* operator->() const {
return &object;
}
[[nodiscard]] T* operator->() {
T* operator->() {
return &object;
}
/// Returns the value contained in this `ResultVal`, or the supplied default if it is missing.
template <typename U>
[[nodiscard]] T ValueOr(U&& value) const {
T ValueOr(U&& value) const {
return !empty() ? object : std::move(value);
}
/// Asserts that the result succeeded and returns a reference to it.
[[nodiscard]] T& Unwrap() & {
T& Unwrap() & {
ASSERT_MSG(Succeeded(), "Tried to Unwrap empty ResultVal");
return **this;
}
[[nodiscard]] T&& Unwrap() && {
T&& Unwrap() && {
ASSERT_MSG(Succeeded(), "Tried to Unwrap empty ResultVal");
return std::move(**this);
}
@@ -320,7 +320,7 @@ private:
* `T` with and creates a success `ResultVal` contained the constructed value.
*/
template <typename T, typename... Args>
[[nodiscard]] ResultVal<T> MakeResult(Args&&... args) {
ResultVal<T> MakeResult(Args&&... args) {
return ResultVal<T>::WithCode(ResultSuccess, std::forward<Args>(args)...);
}
@@ -329,7 +329,7 @@ template <typename T, typename... Args>
* copy or move constructing.
*/
template <typename Arg>
[[nodiscard]] ResultVal<std::remove_reference_t<Arg>> MakeResult(Arg&& arg) {
ResultVal<std::remove_reference_t<Arg>> MakeResult(Arg&& arg) {
return ResultVal<std::remove_reference_t<Arg>>::WithCode(ResultSuccess, std::forward<Arg>(arg));
}

View File

@@ -63,6 +63,14 @@ void Swizzle(std::span<u8> output, std::span<const u8> input, u32 bytes_per_pixe
const u32 unswizzled_offset =
slice * pitch * height + line * pitch + column * bytes_per_pixel;
if (const auto offset = (TO_LINEAR ? unswizzled_offset : swizzled_offset);
offset >= input.size()) {
// TODO(Rodrigo): This is an out of bounds access that should never happen. To
// avoid crashing the emulator, break.
ASSERT_MSG(false, "offset {} exceeds input size {}!", offset, input.size());
break;
}
u8* const dst = &output[TO_LINEAR ? swizzled_offset : unswizzled_offset];
const u8* const src = &input[TO_LINEAR ? unswizzled_offset : swizzled_offset];
std::memcpy(dst, src, bytes_per_pixel);

View File

@@ -27,8 +27,6 @@ ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry,
ui->inputTab->Initialize(input_subsystem);
ui->generalTab->SetResetCallback([&] { this->close(); });
SetConfiguration();
PopulateSelectionList();

View File

@@ -2,15 +2,11 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <functional>
#include <utility>
#include <QCheckBox>
#include <QMessageBox>
#include <QSpinBox>
#include "common/settings.h"
#include "core/core.h"
#include "ui_configure_general.h"
#include "yuzu/configuration/config.h"
#include "yuzu/configuration/configuration_shared.h"
#include "yuzu/configuration/configure_general.h"
#include "yuzu/uisettings.h"
@@ -27,9 +23,6 @@ ConfigureGeneral::ConfigureGeneral(QWidget* parent)
connect(ui->toggle_frame_limit, &QCheckBox::clicked, ui->frame_limit,
[this]() { ui->frame_limit->setEnabled(ui->toggle_frame_limit->isChecked()); });
}
connect(ui->button_reset_defaults, &QPushButton::clicked, this,
&ConfigureGeneral::ResetDefaults);
}
ConfigureGeneral::~ConfigureGeneral() = default;
@@ -48,8 +41,6 @@ void ConfigureGeneral::SetConfiguration() {
ui->toggle_frame_limit->setChecked(Settings::values.use_frame_limit.GetValue());
ui->frame_limit->setValue(Settings::values.frame_limit.GetValue());
ui->button_reset_defaults->setEnabled(runtime_lock);
if (Settings::IsConfiguringGlobal()) {
ui->frame_limit->setEnabled(Settings::values.use_frame_limit.GetValue());
} else {
@@ -58,25 +49,6 @@ void ConfigureGeneral::SetConfiguration() {
}
}
// Called to set the callback when resetting settings to defaults
void ConfigureGeneral::SetResetCallback(std::function<void()> callback) {
reset_callback = std::move(callback);
}
void ConfigureGeneral::ResetDefaults() {
QMessageBox::StandardButton answer = QMessageBox::question(
this, tr("yuzu"),
tr("This reset all settings and remove all per-game configurations. This will not delete "
"game directories, profiles, or input profiles. Proceed?"),
QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
if (answer == QMessageBox::No) {
return;
}
UISettings::values.reset_to_defaults = true;
UISettings::values.is_game_list_reload_pending.exchange(true);
reset_callback();
}
void ConfigureGeneral::ApplyConfiguration() {
ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_multi_core, ui->use_multi_core,
use_multi_core);
@@ -133,8 +105,6 @@ void ConfigureGeneral::SetupPerGameUI() {
ui->toggle_background_pause->setVisible(false);
ui->toggle_hide_mouse->setVisible(false);
ui->button_reset_defaults->setVisible(false);
ConfigurationShared::SetColoredTristate(ui->toggle_frame_limit,
Settings::values.use_frame_limit, use_frame_limit);
ConfigurationShared::SetColoredTristate(ui->use_multi_core, Settings::values.use_multi_core,

View File

@@ -4,12 +4,9 @@
#pragma once
#include <functional>
#include <memory>
#include <QWidget>
class ConfigureDialog;
namespace ConfigurationShared {
enum class CheckState;
}
@@ -27,8 +24,6 @@ public:
explicit ConfigureGeneral(QWidget* parent = nullptr);
~ConfigureGeneral() override;
void SetResetCallback(std::function<void()> callback);
void ResetDefaults();
void ApplyConfiguration();
private:
@@ -39,8 +34,6 @@ private:
void SetupPerGameUI();
std::function<void()> reset_callback;
std::unique_ptr<Ui::ConfigureGeneral> ui;
ConfigurationShared::CheckState use_frame_limit;

View File

@@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>329</width>
<width>300</width>
<height>407</height>
</rect>
</property>
@@ -104,45 +104,6 @@
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="layout_reset">
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin">
<number>5</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property>
<item>
<widget class="QPushButton" name="button_reset_defaults">
<property name="text">
<string>Reset All Settings</string>
</property>
</widget>
</item>
<item>
<spacer name="spacer_reset">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
</layout>

View File

@@ -85,8 +85,6 @@ void PlayerControlPreview::SetConnectedStatus(bool checked) {
led_color[1] = led_pattern.position2 ? colors.led_on : colors.led_off;
led_color[2] = led_pattern.position3 ? colors.led_on : colors.led_off;
led_color[3] = led_pattern.position4 ? colors.led_on : colors.led_off;
is_enabled = checked;
ResetInputs();
}
void PlayerControlPreview::SetControllerType(const Settings::ControllerType type) {
@@ -110,7 +108,6 @@ void PlayerControlPreview::EndMapping() {
analog_mapping_index = Settings::NativeAnalog::NumAnalogs;
mapping_active = false;
blink_counter = 0;
ResetInputs();
}
void PlayerControlPreview::UpdateColors() {
@@ -159,23 +156,7 @@ void PlayerControlPreview::UpdateColors() {
// colors.right = QColor(Settings::values.players.GetValue()[player_index].body_color_right);
}
void PlayerControlPreview::ResetInputs() {
for (std::size_t index = 0; index < button_values.size(); ++index) {
button_values[index] = false;
}
for (std::size_t index = 0; index < axis_values.size(); ++index) {
axis_values[index].properties = {0, 1, 0};
axis_values[index].value = {0, 0};
axis_values[index].raw_value = {0, 0};
}
update();
}
void PlayerControlPreview::UpdateInput() {
if (!is_enabled && !mapping_active) {
return;
}
bool input_changed = false;
const auto& button_state = buttons;
for (std::size_t index = 0; index < button_values.size(); ++index) {

View File

@@ -100,7 +100,6 @@ private:
static LedPattern GetColorPattern(std::size_t index, bool player_on);
void UpdateColors();
void ResetInputs();
// Draw controller functions
void DrawHandheldController(QPainter& p, QPointF center);
@@ -177,7 +176,6 @@ private:
using StickArray =
std::array<std::unique_ptr<Input::AnalogDevice>, Settings::NativeAnalog::NUM_STICKS_HID>;
bool is_enabled{};
bool mapping_active{};
int blink_counter{};
QColor button_color{};

View File

@@ -28,7 +28,6 @@ ControllerDialog::ControllerDialog(QWidget* parent) : QWidget(parent, Qt::Dialog
// Configure focus so that widget is focusable and the dialog automatically forwards focus to
// it.
setFocusProxy(widget);
widget->SetConnectedStatus(false);
widget->setFocusPolicy(Qt::StrongFocus);
widget->setFocus();
}
@@ -37,8 +36,9 @@ void ControllerDialog::refreshConfiguration() {
const auto& players = Settings::values.players.GetValue();
constexpr std::size_t player = 0;
widget->SetPlayerInputRaw(player, players[player].buttons, players[player].analogs);
widget->SetControllerType(players[player].controller_type);
widget->SetConnectedStatus(players[player].connected);
widget->SetControllerType(players[player].controller_type);
widget->repaint();
}
QAction* ControllerDialog::toggleViewAction() {
@@ -56,7 +56,6 @@ void ControllerDialog::showEvent(QShowEvent* ev) {
if (toggle_view_action) {
toggle_view_action->setChecked(isVisible());
}
refreshConfiguration();
QWidget::showEvent(ev);
}
@@ -64,6 +63,5 @@ void ControllerDialog::hideEvent(QHideEvent* ev) {
if (toggle_view_action) {
toggle_view_action->setChecked(isVisible());
}
widget->SetConnectedStatus(false);
QWidget::hideEvent(ev);
}

View File

@@ -2596,53 +2596,13 @@ void GMainWindow::OnConfigure() {
&GMainWindow::OnLanguageChanged);
const auto result = configure_dialog.exec();
if (result != QDialog::Accepted && !UISettings::values.configuration_applied &&
!UISettings::values.reset_to_defaults) {
// Runs if the user hit Cancel or closed the window, and did not ever press the Apply button
// or `Reset to Defaults` button
if (result != QDialog::Accepted && !UISettings::values.configuration_applied) {
return;
} else if (result == QDialog::Accepted) {
// Only apply new changes if user hit Okay
// This is here to avoid applying changes if the user hit Apply, made some changes, then hit
// Cancel
configure_dialog.ApplyConfiguration();
} else if (UISettings::values.reset_to_defaults) {
LOG_INFO(Frontend, "Resetting all settings to defaults");
if (!Common::FS::RemoveFile(config->GetConfigFilePath())) {
LOG_WARNING(Frontend, "Failed to remove configuration file");
}
if (!Common::FS::RemoveDirContentsRecursively(
Common::FS::GetYuzuPath(Common::FS::YuzuPath::ConfigDir) / "custom")) {
LOG_WARNING(Frontend, "Failed to remove custom configuration files");
}
if (!Common::FS::RemoveDirRecursively(
Common::FS::GetYuzuPath(Common::FS::YuzuPath::CacheDir) / "game_list")) {
LOG_WARNING(Frontend, "Failed to remove game metadata cache files");
}
// Explicitly save the game directories, since reinitializing config does not explicitly do
// so.
QVector<UISettings::GameDir> old_game_dirs = std::move(UISettings::values.game_dirs);
QVector<u64> old_favorited_ids = std::move(UISettings::values.favorited_ids);
Settings::values.disabled_addons.clear();
config = std::make_unique<Config>();
UISettings::values.reset_to_defaults = false;
UISettings::values.game_dirs = std::move(old_game_dirs);
UISettings::values.favorited_ids = std::move(old_favorited_ids);
InitializeRecentFileMenuActions();
SetDefaultUIGeometry();
RestoreUIState();
ShowTelemetryCallout();
controller_dialog->refreshConfiguration();
}
controller_dialog->refreshConfiguration();
InitializeHotkeys();
if (UISettings::values.theme != old_theme) {
UpdateUITheme();
}

View File

@@ -97,7 +97,6 @@ struct Values {
bool cache_game_list;
bool configuration_applied;
bool reset_to_defaults;
};
extern Values values;

View File

@@ -317,43 +317,6 @@ void Config::ReadValues() {
sdl2_config->GetInteger("ControlsGeneral", "touch_diameter_x", 15);
Settings::values.touchscreen.diameter_y =
sdl2_config->GetInteger("ControlsGeneral", "touch_diameter_y", 15);
int num_touch_from_button_maps =
sdl2_config->GetInteger("ControlsGeneral", "touch_from_button_map", 0);
if (num_touch_from_button_maps > 0) {
for (int i = 0; i < num_touch_from_button_maps; ++i) {
Settings::TouchFromButtonMap map;
map.name = sdl2_config->Get("ControlsGeneral",
std::string("touch_from_button_maps_") + std::to_string(i) +
std::string("_name"),
"default");
const int num_touch_maps = sdl2_config->GetInteger(
"ControlsGeneral",
std::string("touch_from_button_maps_") + std::to_string(i) + std::string("_count"),
0);
map.buttons.reserve(num_touch_maps);
for (int j = 0; j < num_touch_maps; ++j) {
std::string touch_mapping =
sdl2_config->Get("ControlsGeneral",
std::string("touch_from_button_maps_") + std::to_string(i) +
std::string("_bind_") + std::to_string(j),
"");
map.buttons.emplace_back(std::move(touch_mapping));
}
Settings::values.touch_from_button_maps.emplace_back(std::move(map));
}
} else {
Settings::values.touch_from_button_maps.emplace_back(
Settings::TouchFromButtonMap{"default", {}});
num_touch_from_button_maps = 1;
}
Settings::values.use_touch_from_button =
sdl2_config->GetBoolean("ControlsGeneral", "use_touch_from_button", false);
Settings::values.touch_from_button_map_index =
std::clamp(Settings::values.touch_from_button_map_index, 0, num_touch_from_button_maps - 1);
Settings::values.udp_input_servers =
sdl2_config->Get("Controls", "udp_input_address", InputCommon::CemuhookUDP::DEFAULT_SRV);

View File

@@ -7,7 +7,7 @@
namespace DefaultINI {
const char* sdl2_config_file = R"(
[ControlsGeneral]
[Controls]
# The input devices and parameters for each Switch native input
# It should be in the format of "engine:[engine_name],[param1]:[value1],[param2]:[value2]..."
# Escape characters $0 (for ':'), $1 (for ',') and $2 (for '$') can be used in values
@@ -86,18 +86,6 @@ motion_device=
# - "min_x", "min_y", "max_x", "max_y": defines the udp device's touch screen coordinate system
touch_device=
# Whether to enable or disable touch input from button
# 0 (default): Disabled, 1: Enabled
use_touch_from_button=
# for mapping buttons to touch inputs.
#touch_from_button_map=1
#touch_from_button_maps_0_name=default
#touch_from_button_maps_0_count=2
#touch_from_button_maps_0_bind_0=foo
#touch_from_button_maps_0_bind_1=bar
# etc.
# Most desktop operating systems do not expose a way to poll the motion state of the controllers
# so as a way around it, cemuhook created a udp client/server protocol to broadcast the data directly
# from a controller device to the client program. Citra has a client that can connect and read