Compare commits

..

1 Commits

Author SHA1 Message Date
a0ce33806a Android #97 2023-10-11 00:57:24 +00:00
18 changed files with 79 additions and 234 deletions

View File

@ -5,6 +5,6 @@
GITDATE="`git show -s --date=short --format='%ad' | sed 's/-//g'`" GITDATE="`git show -s --date=short --format='%ad' | sed 's/-//g'`"
GITREV="`git show -s --format='%h'`" GITREV="`git show -s --format='%h'`"
ARTIFACTS_DIR="$PWD/artifacts" ARTIFACTS_DIR="artifacts"
mkdir -p "${ARTIFACTS_DIR}/" mkdir -p "${ARTIFACTS_DIR}/"

View File

@ -11,7 +11,7 @@ ccache -s
mkdir build || true && cd build mkdir build || true && cd build
cmake .. \ cmake .. \
-DBoost_USE_STATIC_LIBS=ON \ -DBoost_USE_STATIC_LIBS=ON \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \ -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_FLAGS="-march=x86-64-v2" \ -DCMAKE_CXX_FLAGS="-march=x86-64-v2" \
-DCMAKE_CXX_COMPILER=/usr/lib/ccache/g++ \ -DCMAKE_CXX_COMPILER=/usr/lib/ccache/g++ \
-DCMAKE_C_COMPILER=/usr/lib/ccache/gcc \ -DCMAKE_C_COMPILER=/usr/lib/ccache/gcc \
@ -31,19 +31,6 @@ ccache -s
ctest -VV -C Release ctest -VV -C Release
# Separate debug symbols from specified executables
for EXE in yuzu; do
EXE_PATH="bin/$EXE"
# Copy debug symbols out
objcopy --only-keep-debug $EXE_PATH $EXE_PATH.debug
# Add debug link and strip debug symbols
objcopy -g --add-gnu-debuglink=$EXE_PATH.debug $EXE_PATH $EXE_PATH.out
# Overwrite original with stripped copy
mv $EXE_PATH.out $EXE_PATH
done
# Strip debug symbols from all executables
find bin/ -type f -not -regex '.*.debug' -exec strip -g {} ';'
DESTDIR="$PWD/AppDir" ninja install DESTDIR="$PWD/AppDir" ninja install
rm -vf AppDir/usr/bin/yuzu-cmd AppDir/usr/bin/yuzu-tester rm -vf AppDir/usr/bin/yuzu-cmd AppDir/usr/bin/yuzu-tester

View File

@ -59,9 +59,4 @@ if [ "${RELEASE_NAME}" = "mainline" ] || [ "${RELEASE_NAME}" = "early-access" ];
cp "build/${APPIMAGE_NAME}" "${DIR_NAME}/yuzu-${RELEASE_NAME}.AppImage" cp "build/${APPIMAGE_NAME}" "${DIR_NAME}/yuzu-${RELEASE_NAME}.AppImage"
fi fi
# Copy debug symbols to artifacts
cd build/bin
tar $COMPRESSION_FLAGS "${ARTIFACTS_DIR}/${REV_NAME}-debug.tar.xz" *.debug
cd -
. .ci/scripts/common/post-upload.sh . .ci/scripts/common/post-upload.sh

View File

@ -120,10 +120,6 @@ QWidget#connectedControllers {
background: transparent; background: transparent;
} }
QWidget#closeButtons {
background: transparent;
}
QWidget#playersSupported, QWidget#playersSupported,
QWidget#controllersSupported, QWidget#controllersSupported,
QWidget#controllerSupported1, QWidget#controllerSupported1,

View File

@ -1380,10 +1380,6 @@ QWidget#connectedControllers {
background: transparent; background: transparent;
} }
QWidget#closeButtons {
background: transparent;
}
QWidget#playersSupported, QWidget#playersSupported,
QWidget#controllersSupported, QWidget#controllersSupported,
QWidget#controllerSupported1, QWidget#controllerSupported1,

View File

@ -2305,10 +2305,6 @@ QWidget#connectedControllers {
background: transparent; background: transparent;
} }
QWidget#closeButtons {
background: transparent;
}
QWidget#playersSupported, QWidget#playersSupported,
QWidget#controllersSupported, QWidget#controllersSupported,
QWidget#controllerSupported1, QWidget#controllerSupported1,

View File

@ -77,7 +77,6 @@ void AudioRenderer::Wait() {
"{}, got {}", "{}, got {}",
Message::RenderResponse, msg); Message::RenderResponse, msg);
} }
PostDSPClearCommandBuffer();
} }
void AudioRenderer::Send(Direction dir, u32 message) { void AudioRenderer::Send(Direction dir, u32 message) {
@ -97,14 +96,6 @@ void AudioRenderer::SetCommandBuffer(s32 session_id, CpuAddr buffer, u64 size, u
command_buffers[session_id].reset_buffer = reset; command_buffers[session_id].reset_buffer = reset;
} }
void AudioRenderer::PostDSPClearCommandBuffer() noexcept {
for (auto& buffer : command_buffers) {
buffer.buffer = 0;
buffer.size = 0;
buffer.reset_buffer = false;
}
}
u32 AudioRenderer::GetRemainCommandCount(s32 session_id) const noexcept { u32 AudioRenderer::GetRemainCommandCount(s32 session_id) const noexcept {
return command_buffers[session_id].remaining_command_count; return command_buffers[session_id].remaining_command_count;
} }

View File

@ -85,8 +85,6 @@ private:
*/ */
void CreateSinkStreams(); void CreateSinkStreams();
void PostDSPClearCommandBuffer() noexcept;
/// Core system /// Core system
Core::System& system; Core::System& system;
/// The output sink the AudioRenderer will send samples to /// The output sink the AudioRenderer will send samples to

View File

@ -544,7 +544,7 @@ void BufferCache<P>::CommitAsyncFlushesHigh() {
it++; it++;
} }
boost::container::small_vector<std::pair<BufferCopy, BufferId>, 16> downloads; boost::container::small_vector<std::pair<BufferCopy, BufferId>, 1> downloads;
u64 total_size_bytes = 0; u64 total_size_bytes = 0;
u64 largest_copy = 0; u64 largest_copy = 0;
for (const IntervalSet& intervals : committed_ranges) { for (const IntervalSet& intervals : committed_ranges) {
@ -914,11 +914,6 @@ void BufferCache<P>::BindHostGraphicsStorageBuffers(size_t stage) {
const u32 offset = buffer.Offset(binding.cpu_addr); const u32 offset = buffer.Offset(binding.cpu_addr);
const bool is_written = ((channel_state->written_storage_buffers[stage] >> index) & 1) != 0; const bool is_written = ((channel_state->written_storage_buffers[stage] >> index) & 1) != 0;
if (is_written) {
MarkWrittenBuffer(binding.buffer_id, binding.cpu_addr, size);
}
if constexpr (NEEDS_BIND_STORAGE_INDEX) { if constexpr (NEEDS_BIND_STORAGE_INDEX) {
runtime.BindStorageBuffer(stage, binding_index, buffer, offset, size, is_written); runtime.BindStorageBuffer(stage, binding_index, buffer, offset, size, is_written);
++binding_index; ++binding_index;
@ -936,11 +931,6 @@ void BufferCache<P>::BindHostGraphicsTextureBuffers(size_t stage) {
const u32 size = binding.size; const u32 size = binding.size;
SynchronizeBuffer(buffer, binding.cpu_addr, size); SynchronizeBuffer(buffer, binding.cpu_addr, size);
const bool is_written = ((channel_state->written_texture_buffers[stage] >> index) & 1) != 0;
if (is_written) {
MarkWrittenBuffer(binding.buffer_id, binding.cpu_addr, size);
}
const u32 offset = buffer.Offset(binding.cpu_addr); const u32 offset = buffer.Offset(binding.cpu_addr);
const PixelFormat format = binding.format; const PixelFormat format = binding.format;
if constexpr (SEPARATE_IMAGE_BUFFERS_BINDINGS) { if constexpr (SEPARATE_IMAGE_BUFFERS_BINDINGS) {
@ -972,8 +962,6 @@ void BufferCache<P>::BindHostTransformFeedbackBuffers() {
const u32 size = binding.size; const u32 size = binding.size;
SynchronizeBuffer(buffer, binding.cpu_addr, size); SynchronizeBuffer(buffer, binding.cpu_addr, size);
MarkWrittenBuffer(binding.buffer_id, binding.cpu_addr, size);
const u32 offset = buffer.Offset(binding.cpu_addr); const u32 offset = buffer.Offset(binding.cpu_addr);
host_bindings.buffers.push_back(&buffer); host_bindings.buffers.push_back(&buffer);
host_bindings.offsets.push_back(offset); host_bindings.offsets.push_back(offset);
@ -1023,11 +1011,6 @@ void BufferCache<P>::BindHostComputeStorageBuffers() {
const u32 offset = buffer.Offset(binding.cpu_addr); const u32 offset = buffer.Offset(binding.cpu_addr);
const bool is_written = const bool is_written =
((channel_state->written_compute_storage_buffers >> index) & 1) != 0; ((channel_state->written_compute_storage_buffers >> index) & 1) != 0;
if (is_written) {
MarkWrittenBuffer(binding.buffer_id, binding.cpu_addr, size);
}
if constexpr (NEEDS_BIND_STORAGE_INDEX) { if constexpr (NEEDS_BIND_STORAGE_INDEX) {
runtime.BindComputeStorageBuffer(binding_index, buffer, offset, size, is_written); runtime.BindComputeStorageBuffer(binding_index, buffer, offset, size, is_written);
++binding_index; ++binding_index;
@ -1045,12 +1028,6 @@ void BufferCache<P>::BindHostComputeTextureBuffers() {
const u32 size = binding.size; const u32 size = binding.size;
SynchronizeBuffer(buffer, binding.cpu_addr, size); SynchronizeBuffer(buffer, binding.cpu_addr, size);
const bool is_written =
((channel_state->written_compute_texture_buffers >> index) & 1) != 0;
if (is_written) {
MarkWrittenBuffer(binding.buffer_id, binding.cpu_addr, size);
}
const u32 offset = buffer.Offset(binding.cpu_addr); const u32 offset = buffer.Offset(binding.cpu_addr);
const PixelFormat format = binding.format; const PixelFormat format = binding.format;
if constexpr (SEPARATE_IMAGE_BUFFERS_BINDINGS) { if constexpr (SEPARATE_IMAGE_BUFFERS_BINDINGS) {
@ -1224,11 +1201,16 @@ void BufferCache<P>::UpdateUniformBuffers(size_t stage) {
template <class P> template <class P>
void BufferCache<P>::UpdateStorageBuffers(size_t stage) { void BufferCache<P>::UpdateStorageBuffers(size_t stage) {
const u32 written_mask = channel_state->written_storage_buffers[stage];
ForEachEnabledBit(channel_state->enabled_storage_buffers[stage], [&](u32 index) { ForEachEnabledBit(channel_state->enabled_storage_buffers[stage], [&](u32 index) {
// Resolve buffer // Resolve buffer
Binding& binding = channel_state->storage_buffers[stage][index]; Binding& binding = channel_state->storage_buffers[stage][index];
const BufferId buffer_id = FindBuffer(binding.cpu_addr, binding.size); const BufferId buffer_id = FindBuffer(binding.cpu_addr, binding.size);
binding.buffer_id = buffer_id; binding.buffer_id = buffer_id;
// Mark buffer as written if needed
if (((written_mask >> index) & 1) != 0) {
MarkWrittenBuffer(buffer_id, binding.cpu_addr, binding.size);
}
}); });
} }
@ -1237,6 +1219,10 @@ void BufferCache<P>::UpdateTextureBuffers(size_t stage) {
ForEachEnabledBit(channel_state->enabled_texture_buffers[stage], [&](u32 index) { ForEachEnabledBit(channel_state->enabled_texture_buffers[stage], [&](u32 index) {
Binding& binding = channel_state->texture_buffers[stage][index]; Binding& binding = channel_state->texture_buffers[stage][index];
binding.buffer_id = FindBuffer(binding.cpu_addr, binding.size); binding.buffer_id = FindBuffer(binding.cpu_addr, binding.size);
// Mark buffer as written if needed
if (((channel_state->written_texture_buffers[stage] >> index) & 1) != 0) {
MarkWrittenBuffer(binding.buffer_id, binding.cpu_addr, binding.size);
}
}); });
} }
@ -1266,6 +1252,7 @@ void BufferCache<P>::UpdateTransformFeedbackBuffer(u32 index) {
.size = size, .size = size,
.buffer_id = buffer_id, .buffer_id = buffer_id,
}; };
MarkWrittenBuffer(buffer_id, *cpu_addr, size);
} }
template <class P> template <class P>
@ -1292,6 +1279,10 @@ void BufferCache<P>::UpdateComputeStorageBuffers() {
// Resolve buffer // Resolve buffer
Binding& binding = channel_state->compute_storage_buffers[index]; Binding& binding = channel_state->compute_storage_buffers[index];
binding.buffer_id = FindBuffer(binding.cpu_addr, binding.size); binding.buffer_id = FindBuffer(binding.cpu_addr, binding.size);
// Mark as written if needed
if (((channel_state->written_compute_storage_buffers >> index) & 1) != 0) {
MarkWrittenBuffer(binding.buffer_id, binding.cpu_addr, binding.size);
}
}); });
} }
@ -1300,11 +1291,18 @@ void BufferCache<P>::UpdateComputeTextureBuffers() {
ForEachEnabledBit(channel_state->enabled_compute_texture_buffers, [&](u32 index) { ForEachEnabledBit(channel_state->enabled_compute_texture_buffers, [&](u32 index) {
Binding& binding = channel_state->compute_texture_buffers[index]; Binding& binding = channel_state->compute_texture_buffers[index];
binding.buffer_id = FindBuffer(binding.cpu_addr, binding.size); binding.buffer_id = FindBuffer(binding.cpu_addr, binding.size);
// Mark as written if needed
if (((channel_state->written_compute_texture_buffers >> index) & 1) != 0) {
MarkWrittenBuffer(binding.buffer_id, binding.cpu_addr, binding.size);
}
}); });
} }
template <class P> template <class P>
void BufferCache<P>::MarkWrittenBuffer(BufferId buffer_id, VAddr cpu_addr, u32 size) { void BufferCache<P>::MarkWrittenBuffer(BufferId buffer_id, VAddr cpu_addr, u32 size) {
if (memory_tracker.IsRegionCpuModified(cpu_addr, size)) {
SynchronizeBuffer(slot_buffers[buffer_id], cpu_addr, size);
}
memory_tracker.MarkRegionAsGpuModified(cpu_addr, size); memory_tracker.MarkRegionAsGpuModified(cpu_addr, size);
const IntervalType base_interval{cpu_addr, cpu_addr + size}; const IntervalType base_interval{cpu_addr, cpu_addr + size};

View File

@ -1048,10 +1048,6 @@ void Image::Scale(bool up_scale) {
} }
bool Image::ScaleUp(bool ignore) { bool Image::ScaleUp(bool ignore) {
const auto& resolution = runtime->resolution;
if (!resolution.active) {
return false;
}
if (True(flags & ImageFlagBits::Rescaled)) { if (True(flags & ImageFlagBits::Rescaled)) {
return false; return false;
} }
@ -1064,6 +1060,9 @@ bool Image::ScaleUp(bool ignore) {
return false; return false;
} }
flags |= ImageFlagBits::Rescaled; flags |= ImageFlagBits::Rescaled;
if (!runtime->resolution.active) {
return false;
}
has_scaled = true; has_scaled = true;
if (ignore) { if (ignore) {
current_texture = upscaled_backup.handle; current_texture = upscaled_backup.handle;
@ -1074,14 +1073,13 @@ bool Image::ScaleUp(bool ignore) {
} }
bool Image::ScaleDown(bool ignore) { bool Image::ScaleDown(bool ignore) {
const auto& resolution = runtime->resolution;
if (!resolution.active) {
return false;
}
if (False(flags & ImageFlagBits::Rescaled)) { if (False(flags & ImageFlagBits::Rescaled)) {
return false; return false;
} }
flags &= ~ImageFlagBits::Rescaled; flags &= ~ImageFlagBits::Rescaled;
if (!runtime->resolution.active) {
return false;
}
if (ignore) { if (ignore) {
current_texture = texture.handle; current_texture = texture.handle;
return true; return true;

View File

@ -1530,15 +1530,15 @@ bool Image::IsRescaled() const noexcept {
} }
bool Image::ScaleUp(bool ignore) { bool Image::ScaleUp(bool ignore) {
const auto& resolution = runtime->resolution;
if (!resolution.active) {
return false;
}
if (True(flags & ImageFlagBits::Rescaled)) { if (True(flags & ImageFlagBits::Rescaled)) {
return false; return false;
} }
ASSERT(info.type != ImageType::Linear); ASSERT(info.type != ImageType::Linear);
flags |= ImageFlagBits::Rescaled; flags |= ImageFlagBits::Rescaled;
const auto& resolution = runtime->resolution;
if (!resolution.active) {
return false;
}
has_scaled = true; has_scaled = true;
if (!scaled_image) { if (!scaled_image) {
const bool is_2d = info.type == ImageType::e2D; const bool is_2d = info.type == ImageType::e2D;
@ -1567,15 +1567,15 @@ bool Image::ScaleUp(bool ignore) {
} }
bool Image::ScaleDown(bool ignore) { bool Image::ScaleDown(bool ignore) {
const auto& resolution = runtime->resolution;
if (!resolution.active) {
return false;
}
if (False(flags & ImageFlagBits::Rescaled)) { if (False(flags & ImageFlagBits::Rescaled)) {
return false; return false;
} }
ASSERT(info.type != ImageType::Linear); ASSERT(info.type != ImageType::Linear);
flags &= ~ImageFlagBits::Rescaled; flags &= ~ImageFlagBits::Rescaled;
const auto& resolution = runtime->resolution;
if (!resolution.active) {
return false;
}
current_image = *original_image; current_image = *original_image;
if (ignore) { if (ignore) {
return true; return true;

View File

@ -885,7 +885,7 @@ boost::container::small_vector<BufferImageCopy, 16> UnswizzleImage(Tegra::Memory
}; };
const Extent3D num_tiles = AdjustTileSize(level_size, tile_size); const Extent3D num_tiles = AdjustTileSize(level_size, tile_size);
const Extent3D block = const Extent3D block =
AdjustMipBlockSize(num_tiles, level_info.block, level, level_info.num_levels); AdjustMipBlockSize(num_tiles, info.block, level, level_info.num_levels);
const u32 stride_alignment = StrideAlignment(num_tiles, info.block, gob, bpp_log2); const u32 stride_alignment = StrideAlignment(num_tiles, info.block, gob, bpp_log2);
size_t guest_layer_offset = 0; size_t guest_layer_offset = 0;
@ -1062,7 +1062,7 @@ boost::container::small_vector<SwizzleParameters, 16> FullUploadSwizzles(const I
const Extent3D level_size = AdjustMipSize(size, level); const Extent3D level_size = AdjustMipSize(size, level);
const Extent3D num_tiles = AdjustTileSize(level_size, tile_size); const Extent3D num_tiles = AdjustTileSize(level_size, tile_size);
const Extent3D block = const Extent3D block =
AdjustMipBlockSize(num_tiles, level_info.block, level, level_info.num_levels); AdjustMipBlockSize(num_tiles, info.block, level, level_info.num_levels);
params[level] = SwizzleParameters{ params[level] = SwizzleParameters{
.num_tiles = num_tiles, .num_tiles = num_tiles,
.block = block, .block = block,

View File

@ -66,10 +66,9 @@ struct Range {
switch (usage) { switch (usage) {
case MemoryUsage::Upload: case MemoryUsage::Upload:
case MemoryUsage::Stream: case MemoryUsage::Stream:
return VMA_ALLOCATION_CREATE_MAPPED_BIT | return VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT;
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT;
case MemoryUsage::Download: case MemoryUsage::Download:
return VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT; return VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT;
case MemoryUsage::DeviceLocal: case MemoryUsage::DeviceLocal:
return {}; return {};
} }
@ -253,7 +252,8 @@ vk::Image MemoryAllocator::CreateImage(const VkImageCreateInfo& ci) const {
vk::Buffer MemoryAllocator::CreateBuffer(const VkBufferCreateInfo& ci, MemoryUsage usage) const { vk::Buffer MemoryAllocator::CreateBuffer(const VkBufferCreateInfo& ci, MemoryUsage usage) const {
const VmaAllocationCreateInfo alloc_ci = { const VmaAllocationCreateInfo alloc_ci = {
.flags = VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT | MemoryUsageVmaFlags(usage), .flags = VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT |
MemoryUsageVmaFlags(usage),
.usage = MemoryUsageVma(usage), .usage = MemoryUsageVma(usage),
.requiredFlags = 0, .requiredFlags = 0,
.preferredFlags = MemoryUsagePreferedVmaFlags(usage), .preferredFlags = MemoryUsagePreferedVmaFlags(usage),

View File

@ -23,7 +23,6 @@
#include "yuzu/configuration/configure_vibration.h" #include "yuzu/configuration/configure_vibration.h"
#include "yuzu/configuration/input_profiles.h" #include "yuzu/configuration/input_profiles.h"
#include "yuzu/main.h" #include "yuzu/main.h"
#include "yuzu/util/controller_navigation.h"
namespace { namespace {
@ -133,8 +132,6 @@ QtControllerSelectorDialog::QtControllerSelectorDialog(
ui->checkboxPlayer7Connected, ui->checkboxPlayer8Connected, ui->checkboxPlayer7Connected, ui->checkboxPlayer8Connected,
}; };
ui->labelError->setVisible(false);
// Setup/load everything prior to setting up connections. // Setup/load everything prior to setting up connections.
// This avoids unintentionally changing the states of elements while loading them in. // This avoids unintentionally changing the states of elements while loading them in.
SetSupportedControllers(); SetSupportedControllers();
@ -146,8 +143,6 @@ QtControllerSelectorDialog::QtControllerSelectorDialog(
LoadConfiguration(); LoadConfiguration();
controller_navigation = new ControllerNavigation(system.HIDCore(), this);
for (std::size_t i = 0; i < NUM_PLAYERS; ++i) { for (std::size_t i = 0; i < NUM_PLAYERS; ++i) {
SetExplainText(i); SetExplainText(i);
UpdateControllerIcon(i); UpdateControllerIcon(i);
@ -156,8 +151,6 @@ QtControllerSelectorDialog::QtControllerSelectorDialog(
connect(player_groupboxes[i], &QGroupBox::toggled, [this, i](bool checked) { connect(player_groupboxes[i], &QGroupBox::toggled, [this, i](bool checked) {
if (checked) { if (checked) {
// Hide eventual error message about number of controllers
ui->labelError->setVisible(false);
for (std::size_t index = 0; index <= i; ++index) { for (std::size_t index = 0; index <= i; ++index) {
connected_controller_checkboxes[index]->setChecked(checked); connected_controller_checkboxes[index]->setChecked(checked);
} }
@ -206,12 +199,6 @@ QtControllerSelectorDialog::QtControllerSelectorDialog(
connect(ui->buttonBox, &QDialogButtonBox::accepted, this, connect(ui->buttonBox, &QDialogButtonBox::accepted, this,
&QtControllerSelectorDialog::ApplyConfiguration); &QtControllerSelectorDialog::ApplyConfiguration);
connect(controller_navigation, &ControllerNavigation::TriggerKeyboardEvent,
[this](Qt::Key key) {
QKeyEvent* event = new QKeyEvent(QEvent::KeyPress, key, Qt::NoModifier);
QCoreApplication::postEvent(this, event);
});
// Enhancement: Check if the parameters have already been met before disconnecting controllers. // Enhancement: Check if the parameters have already been met before disconnecting controllers.
// If all the parameters are met AND only allows a single player, // If all the parameters are met AND only allows a single player,
// stop the constructor here as we do not need to continue. // stop the constructor here as we do not need to continue.
@ -230,7 +217,6 @@ QtControllerSelectorDialog::QtControllerSelectorDialog(
} }
QtControllerSelectorDialog::~QtControllerSelectorDialog() { QtControllerSelectorDialog::~QtControllerSelectorDialog() {
controller_navigation->UnloadController();
system.HIDCore().DisableAllControllerConfiguration(); system.HIDCore().DisableAllControllerConfiguration();
} }
@ -305,31 +291,6 @@ void QtControllerSelectorDialog::CallConfigureInputProfileDialog() {
dialog.exec(); dialog.exec();
} }
void QtControllerSelectorDialog::keyPressEvent(QKeyEvent* evt) {
const auto num_connected_players = static_cast<int>(
std::count_if(player_groupboxes.begin(), player_groupboxes.end(),
[](const QGroupBox* player) { return player->isChecked(); }));
const auto min_supported_players = parameters.enable_single_mode ? 1 : parameters.min_players;
const auto max_supported_players = parameters.enable_single_mode ? 1 : parameters.max_players;
if ((evt->key() == Qt::Key_Enter || evt->key() == Qt::Key_Return) && !parameters_met) {
// Display error message when trying to validate using "Enter" and "OK" button is disabled
ui->labelError->setVisible(true);
return;
} else if (evt->key() == Qt::Key_Left && num_connected_players > min_supported_players) {
// Remove a player if possible
connected_controller_checkboxes[num_connected_players - 1]->setChecked(false);
return;
} else if (evt->key() == Qt::Key_Right && num_connected_players < max_supported_players) {
// Add a player, if possible
ui->labelError->setVisible(false);
connected_controller_checkboxes[num_connected_players]->setChecked(true);
return;
}
QDialog::keyPressEvent(evt);
}
bool QtControllerSelectorDialog::CheckIfParametersMet() { bool QtControllerSelectorDialog::CheckIfParametersMet() {
// Here, we check and validate the current configuration against all applicable parameters. // Here, we check and validate the current configuration against all applicable parameters.
const auto num_connected_players = static_cast<int>( const auto num_connected_players = static_cast<int>(

View File

@ -34,8 +34,6 @@ class HIDCore;
enum class NpadStyleIndex : u8; enum class NpadStyleIndex : u8;
} // namespace Core::HID } // namespace Core::HID
class ControllerNavigation;
class QtControllerSelectorDialog final : public QDialog { class QtControllerSelectorDialog final : public QDialog {
Q_OBJECT Q_OBJECT
@ -48,8 +46,6 @@ public:
int exec() override; int exec() override;
void keyPressEvent(QKeyEvent* evt) override;
private: private:
// Applies the current configuration. // Applies the current configuration.
void ApplyConfiguration(); void ApplyConfiguration();
@ -114,8 +110,6 @@ private:
Core::System& system; Core::System& system;
ControllerNavigation* controller_navigation = nullptr;
// This is true if and only if all parameters are met. Otherwise, this is false. // This is true if and only if all parameters are met. Otherwise, this is false.
// This determines whether the "OK" button can be clicked to exit the applet. // This determines whether the "OK" button can be clicked to exit the applet.
bool parameters_met{false}; bool parameters_met{false};

View File

@ -2624,53 +2624,13 @@
</spacer> </spacer>
</item> </item>
<item alignment="Qt::AlignBottom"> <item alignment="Qt::AlignBottom">
<widget class="QWidget" name="closeButtons" native="true"> <widget class="QDialogButtonBox" name="buttonBox">
<layout class="QVBoxLayout" name="verticalLayout_46"> <property name="enabled">
<property name="spacing"> <bool>true</bool>
<number>7</number> </property>
</property> <property name="standardButtons">
<property name="leftMargin"> <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
<number>0</number> </property>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="labelError">
<property name="enabled">
<bool>true</bool>
</property>
<property name="styleSheet">
<string notr="true">QLabel { color : red; }</string>
</property>
<property name="text">
<string>Not enough controllers</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="margin">
<number>0</number>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="enabled">
<bool>true</bool>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget> </widget>
</item> </item>
</layout> </layout>

View File

@ -63,15 +63,25 @@ bool SaveIconToFile(const std::string_view path, const QImage& image) {
}; };
#pragma pack(pop) #pragma pack(pop)
const QImage source_image = image.convertToFormat(QImage::Format_RGB32); QImage source_image = image.convertToFormat(QImage::Format_RGB32);
constexpr std::array<int, 7> scale_sizes{256, 128, 64, 48, 32, 24, 16};
constexpr int bytes_per_pixel = 4; constexpr int bytes_per_pixel = 4;
const int image_size = source_image.width() * source_image.height() * bytes_per_pixel;
const IconDir icon_dir{ BITMAPINFOHEADER info_header{};
.id_reserved = 0, info_header.biSize = sizeof(BITMAPINFOHEADER), info_header.biWidth = source_image.width(),
.id_type = 1, info_header.biHeight = source_image.height() * 2, info_header.biPlanes = 1,
.id_count = static_cast<WORD>(scale_sizes.size()), info_header.biBitCount = bytes_per_pixel * 8, info_header.biCompression = BI_RGB;
};
const IconDir icon_dir{.id_reserved = 0, .id_type = 1, .id_count = 1};
const IconDirEntry icon_entry{.width = static_cast<BYTE>(source_image.width()),
.height = static_cast<BYTE>(source_image.height() * 2),
.color_count = 0,
.reserved = 0,
.planes = 1,
.bit_count = bytes_per_pixel * 8,
.bytes_in_res =
static_cast<DWORD>(sizeof(BITMAPINFOHEADER) + image_size),
.image_offset = sizeof(IconDir) + sizeof(IconDirEntry)};
Common::FS::IOFile icon_file(path, Common::FS::FileAccessMode::Write, Common::FS::IOFile icon_file(path, Common::FS::FileAccessMode::Write,
Common::FS::FileType::BinaryFile); Common::FS::FileType::BinaryFile);
@ -82,55 +92,20 @@ bool SaveIconToFile(const std::string_view path, const QImage& image) {
if (!icon_file.Write(icon_dir)) { if (!icon_file.Write(icon_dir)) {
return false; return false;
} }
if (!icon_file.Write(icon_entry)) {
std::size_t image_offset = sizeof(IconDir) + (sizeof(IconDirEntry) * scale_sizes.size()); return false;
for (std::size_t i = 0; i < scale_sizes.size(); i++) { }
const int image_size = scale_sizes[i] * scale_sizes[i] * bytes_per_pixel; if (!icon_file.Write(info_header)) {
const IconDirEntry icon_entry{ return false;
.width = static_cast<BYTE>(scale_sizes[i]),
.height = static_cast<BYTE>(scale_sizes[i]),
.color_count = 0,
.reserved = 0,
.planes = 1,
.bit_count = bytes_per_pixel * 8,
.bytes_in_res = static_cast<DWORD>(sizeof(BITMAPINFOHEADER) + image_size),
.image_offset = static_cast<DWORD>(image_offset),
};
image_offset += icon_entry.bytes_in_res;
if (!icon_file.Write(icon_entry)) {
return false;
}
} }
for (std::size_t i = 0; i < scale_sizes.size(); i++) { for (int y = 0; y < image.height(); y++) {
const QImage scaled_image = source_image.scaled( const auto* line = source_image.scanLine(source_image.height() - 1 - y);
scale_sizes[i], scale_sizes[i], Qt::IgnoreAspectRatio, Qt::SmoothTransformation); std::vector<u8> line_data(source_image.width() * bytes_per_pixel);
const BITMAPINFOHEADER info_header{ std::memcpy(line_data.data(), line, line_data.size());
.biSize = sizeof(BITMAPINFOHEADER), if (!icon_file.Write(line_data)) {
.biWidth = scaled_image.width(),
.biHeight = scaled_image.height() * 2,
.biPlanes = 1,
.biBitCount = bytes_per_pixel * 8,
.biCompression = BI_RGB,
.biSizeImage{},
.biXPelsPerMeter{},
.biYPelsPerMeter{},
.biClrUsed{},
.biClrImportant{},
};
if (!icon_file.Write(info_header)) {
return false; return false;
} }
for (int y = 0; y < scaled_image.height(); y++) {
const auto* line = scaled_image.scanLine(scaled_image.height() - 1 - y);
std::vector<u8> line_data(scaled_image.width() * bytes_per_pixel);
std::memcpy(line_data.data(), line, line_data.size());
if (!icon_file.Write(line_data)) {
return false;
}
}
} }
icon_file.Close(); icon_file.Close();