Compare commits

..

1 Commits

36 changed files with 214 additions and 487 deletions

View File

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

View File

@@ -11,7 +11,7 @@ ccache -s
mkdir build || true && cd build
cmake .. \
-DBoost_USE_STATIC_LIBS=ON \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_FLAGS="-march=x86-64-v2" \
-DCMAKE_CXX_COMPILER=/usr/lib/ccache/g++ \
-DCMAKE_C_COMPILER=/usr/lib/ccache/gcc \
@@ -31,19 +31,6 @@ ccache -s
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
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"
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

View File

@@ -11,6 +11,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/externals/cmake-modul
include(DownloadExternals)
include(CMakeDependentOption)
include(CTest)
include(FetchContent)
# Set bundled sdl2/qt as dependent options.
# OFF by default, but if ENABLE_SDL2 and MSVC are true then ON
@@ -98,8 +99,47 @@ if (ANDROID AND YUZU_DOWNLOAD_ANDROID_VVL)
DESTINATION "${vvl_lib_path}")
endif()
# On Android, fetch and compile libcxx before doing anything else
if (ANDROID)
set(CMAKE_SKIP_INSTALL_RULES ON)
set(LLVM_VERSION "15.0.6")
# Note: even though libcxx and libcxxabi have separate releases on the project page,
# the separated releases cannot be compiled. Only in-tree builds work. Therefore we
# must fetch the source release for the entire llvm tree.
FetchContent_Declare(llvm
URL "https://github.com/llvm/llvm-project/releases/download/llvmorg-${LLVM_VERSION}/llvm-project-${LLVM_VERSION}.src.tar.xz"
URL_HASH SHA256=9d53ad04dc60cb7b30e810faf64c5ab8157dadef46c8766f67f286238256ff92
TLS_VERIFY TRUE
)
FetchContent_MakeAvailable(llvm)
# libcxx has support for most of the range library, but it's gated behind a flag:
add_compile_definitions(_LIBCPP_ENABLE_EXPERIMENTAL)
# Disable standard header inclusion
set(ANDROID_STL "none")
# libcxxabi
set(LIBCXXABI_INCLUDE_TESTS OFF)
set(LIBCXXABI_ENABLE_SHARED FALSE)
set(LIBCXXABI_ENABLE_STATIC TRUE)
set(LIBCXXABI_LIBCXX_INCLUDES "${LIBCXX_TARGET_INCLUDE_DIRECTORY}" CACHE STRING "" FORCE)
add_subdirectory("${llvm_SOURCE_DIR}/libcxxabi" "${llvm_BINARY_DIR}/libcxxabi")
link_libraries(cxxabi_static)
# libcxx
set(LIBCXX_ABI_NAMESPACE "__ndk1" CACHE STRING "" FORCE)
set(LIBCXX_CXX_ABI "libcxxabi")
set(LIBCXX_INCLUDE_TESTS OFF)
set(LIBCXX_INCLUDE_BENCHMARKS OFF)
set(LIBCXX_INCLUDE_DOCS OFF)
set(LIBCXX_ENABLE_SHARED FALSE)
set(LIBCXX_ENABLE_STATIC TRUE)
set(LIBCXX_ENABLE_ASSERTIONS FALSE)
add_subdirectory("${llvm_SOURCE_DIR}/libcxx" "${llvm_BINARY_DIR}/libcxx")
set_target_properties(cxx-headers PROPERTIES INTERFACE_COMPILE_OPTIONS "-isystem${CMAKE_BINARY_DIR}/${LIBCXX_INSTALL_INCLUDE_DIR}")
link_libraries(cxx_static cxx-headers)
endif()
if (YUZU_USE_BUNDLED_VCPKG)
@@ -289,7 +329,7 @@ find_package(Boost 1.79.0 REQUIRED context)
find_package(enet 1.3 MODULE)
find_package(fmt 9 REQUIRED)
find_package(inih 52 MODULE COMPONENTS INIReader)
find_package(LLVM 17.0.2 MODULE COMPONENTS Demangle)
find_package(LLVM 17 MODULE COMPONENTS Demangle)
find_package(lz4 REQUIRED)
find_package(nlohmann_json 3.8 REQUIRED)
find_package(Opus 1.3 MODULE)

View File

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

View File

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

View File

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

View File

@@ -27,7 +27,7 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Windows" OR ANDROID)
set(CAN_BUILD_NX_TZDB false)
endif()
set(NX_TZDB_VERSION "221202")
set(NX_TZDB_VERSION "220816")
set(NX_TZDB_ARCHIVE "${CMAKE_CURRENT_BINARY_DIR}/${NX_TZDB_VERSION}.zip")
set(NX_TZDB_ROMFS_DIR "${CMAKE_CURRENT_BINARY_DIR}/nx_tzdb")

View File

@@ -27,7 +27,7 @@ android {
namespace = "org.yuzu.yuzu_emu"
compileSdkVersion = "android-34"
ndkVersion = "26.1.10909125"
ndkVersion = "25.2.9519653"
buildFeatures {
viewBinding = true
@@ -203,23 +203,23 @@ ktlint {
}
dependencies {
implementation("androidx.core:core-ktx:1.12.0")
implementation("androidx.core:core-ktx:1.10.1")
implementation("androidx.appcompat:appcompat:1.6.1")
implementation("androidx.recyclerview:recyclerview:1.3.1")
implementation("androidx.recyclerview:recyclerview:1.3.0")
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
implementation("androidx.fragment:fragment-ktx:1.6.1")
implementation("androidx.fragment:fragment-ktx:1.6.0")
implementation("androidx.documentfile:documentfile:1.0.1")
implementation("com.google.android.material:material:1.9.0")
implementation("androidx.preference:preference-ktx:1.2.1")
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2")
implementation("androidx.preference:preference:1.2.0")
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1")
implementation("io.coil-kt:coil:2.2.2")
implementation("androidx.core:core-splashscreen:1.0.1")
implementation("androidx.window:window:1.2.0-beta03")
implementation("org.ini4j:ini4j:0.5.4")
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0")
implementation("androidx.navigation:navigation-fragment-ktx:2.7.4")
implementation("androidx.navigation:navigation-ui-ktx:2.7.4")
implementation("androidx.navigation:navigation-fragment-ktx:2.6.0")
implementation("androidx.navigation:navigation-ui-ktx:2.6.0")
implementation("info.debatty:java-string-similarity:2.0.0")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0")
}

View File

@@ -28,6 +28,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
android:appCategory="game"
android:localeConfig="@xml/locales_config"
android:banner="@drawable/tv_banner"
android:extractNativeLibs="true"
android:fullBackupContent="@xml/data_extraction_rules"
android:dataExtractionRules="@xml/data_extraction_rules_api_31"
android:enableOnBackInvokedCallback="true">

View File

@@ -3,8 +3,8 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
id("com.android.application") version "8.1.2" apply false
id("com.android.library") version "8.1.2" apply false
id("com.android.application") version "8.0.2" apply false
id("com.android.library") version "8.0.2" apply false
id("org.jetbrains.kotlin.android") version "1.8.21" apply false
}

View File

@@ -77,7 +77,6 @@ void AudioRenderer::Wait() {
"{}, got {}",
Message::RenderResponse, msg);
}
PostDSPClearCommandBuffer();
}
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;
}
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 {
return command_buffers[session_id].remaining_command_count;
}

View File

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

View File

@@ -39,12 +39,8 @@
#define Crash() exit(1)
#endif
#define LTO_NOINLINE __attribute__((noinline))
#else // _MSC_VER
#define LTO_NOINLINE
// Locale Cross-Compatibility
#define locale_t _locale_t

View File

@@ -211,11 +211,6 @@ struct Elf64_Rela {
Elf64_Sxword r_addend; /* Addend */
};
/* RELR relocation table entry */
using Elf32_Relr = Elf32_Word;
using Elf64_Relr = Elf64_Xword;
/* How to extract and insert information held in the r_info field. */
static inline u32 Elf32RelSymIndex(Elf32_Word r_info) {
@@ -333,9 +328,6 @@ constexpr u32 ElfDtFiniArray = 26; /* Array with addresses of fini fct */
constexpr u32 ElfDtInitArraySz = 27; /* Size in bytes of DT_INIT_ARRAY */
constexpr u32 ElfDtFiniArraySz = 28; /* Size in bytes of DT_FINI_ARRAY */
constexpr u32 ElfDtSymtabShndx = 34; /* Address of SYMTAB_SHNDX section */
constexpr u32 ElfDtRelrsz = 35; /* Size of RELR relative relocations */
constexpr u32 ElfDtRelr = 36; /* Address of RELR relative relocations */
constexpr u32 ElfDtRelrent = 37; /* Size of one RELR relative relocation */
} // namespace ELF
} // namespace Common

View File

@@ -373,7 +373,7 @@ struct KernelCore::Impl {
static inline thread_local u8 host_thread_id = UINT8_MAX;
/// Sets the host thread ID for the caller.
LTO_NOINLINE u32 SetHostThreadId(std::size_t core_id) {
u32 SetHostThreadId(std::size_t core_id) {
// This should only be called during core init.
ASSERT(host_thread_id == UINT8_MAX);
@@ -384,13 +384,13 @@ struct KernelCore::Impl {
}
/// Gets the host thread ID for the caller
LTO_NOINLINE u32 GetHostThreadId() const {
u32 GetHostThreadId() const {
return host_thread_id;
}
// Gets the dummy KThread for the caller, allocating a new one if this is the first time
LTO_NOINLINE KThread* GetHostDummyThread(KThread* existing_thread) {
const auto initialize{[](KThread* thread) LTO_NOINLINE {
KThread* GetHostDummyThread(KThread* existing_thread) {
const auto initialize{[](KThread* thread) {
ASSERT(KThread::InitializeDummyThread(thread, nullptr).IsSuccess());
return thread;
}};
@@ -424,11 +424,11 @@ struct KernelCore::Impl {
static inline thread_local bool is_phantom_mode_for_singlecore{false};
LTO_NOINLINE bool IsPhantomModeForSingleCore() const {
bool IsPhantomModeForSingleCore() const {
return is_phantom_mode_for_singlecore;
}
LTO_NOINLINE void SetIsPhantomModeForSingleCore(bool value) {
void SetIsPhantomModeForSingleCore(bool value) {
ASSERT(!is_multicore);
is_phantom_mode_for_singlecore = value;
}
@@ -439,14 +439,14 @@ struct KernelCore::Impl {
static inline thread_local KThread* current_thread{nullptr};
LTO_NOINLINE KThread* GetCurrentEmuThread() {
KThread* GetCurrentEmuThread() {
if (!current_thread) {
current_thread = GetHostDummyThread(nullptr);
}
return current_thread;
}
LTO_NOINLINE void SetCurrentEmuThread(KThread* thread) {
void SetCurrentEmuThread(KThread* thread) {
current_thread = thread;
}

View File

@@ -16,7 +16,7 @@ namespace Service::Capture {
void LoopProcess(Core::System& system) {
auto server_manager = std::make_unique<ServerManager>(system);
auto album_manager = std::make_shared<AlbumManager>(system);
auto album_manager = std::make_shared<AlbumManager>();
server_manager->RegisterNamedService(
"caps:a", std::make_shared<IAlbumAccessorService>(system, album_manager));

View File

@@ -128,9 +128,9 @@ void IAlbumAccessorService::GetAlbumFileListEx0(HLERequestContext& ctx) {
ctx.WriteBuffer(entries);
}
IPC::ResponseBuilder rb{ctx, 4};
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(result);
rb.Push<u64>(entries.size());
rb.Push(entries.size());
}
void IAlbumAccessorService::GetAutoSavingStorage(HLERequestContext& ctx) {

View File

@@ -8,15 +8,12 @@
#include "common/fs/file.h"
#include "common/fs/path_util.h"
#include "common/logging/log.h"
#include "core/core.h"
#include "core/hle/service/caps/caps_manager.h"
#include "core/hle/service/caps/caps_result.h"
#include "core/hle/service/time/time_manager.h"
#include "core/hle/service/time/time_zone_content_manager.h"
namespace Service::Capture {
AlbumManager::AlbumManager(Core::System& system_) : system{system_} {}
AlbumManager::AlbumManager() {}
AlbumManager::~AlbumManager() = default;
@@ -86,34 +83,6 @@ Result AlbumManager::GetAlbumFileList(std::vector<AlbumEntry>& out_entries, Albu
}
Result AlbumManager::GetAlbumFileList(std::vector<ApplicationAlbumFileEntry>& out_entries,
ContentType contex_type, s64 start_posix_time,
s64 end_posix_time, u64 aruid) const {
if (!is_mounted) {
return ResultIsNotMounted;
}
std::vector<ApplicationAlbumEntry> album_entries;
const auto start_date = ConvertToAlbumDateTime(start_posix_time);
const auto end_date = ConvertToAlbumDateTime(end_posix_time);
const auto result = GetAlbumFileList(album_entries, contex_type, start_date, end_date, aruid);
if (result.IsError()) {
return result;
}
for (const auto& album_entry : album_entries) {
ApplicationAlbumFileEntry entry{
.entry = album_entry,
.datetime = album_entry.datetime,
.unknown = {},
};
out_entries.push_back(entry);
}
return ResultSuccess;
}
Result AlbumManager::GetAlbumFileList(std::vector<ApplicationAlbumEntry>& out_entries,
ContentType contex_type, AlbumFileDateTime start_date,
AlbumFileDateTime end_date, u64 aruid) const {
if (!is_mounted) {
@@ -124,25 +93,31 @@ Result AlbumManager::GetAlbumFileList(std::vector<ApplicationAlbumEntry>& out_en
if (file_id.type != contex_type) {
continue;
}
if (file_id.date > start_date) {
continue;
}
if (file_id.date < end_date) {
continue;
}
if (out_entries.size() >= SdAlbumFileLimit) {
break;
}
const auto entry_size = Common::FS::GetSize(path);
ApplicationAlbumEntry entry{
.size = entry_size,
.hash{},
.datetime = file_id.date,
.storage = file_id.storage,
.content = contex_type,
.unknown = 1,
};
ApplicationAlbumFileEntry entry{.entry =
{
.size = entry_size,
.hash{},
.datetime = file_id.date,
.storage = file_id.storage,
.content = contex_type,
.unknown = 1,
},
.datetime = file_id.date,
.unknown = {}};
out_entries.push_back(entry);
}
@@ -299,12 +274,12 @@ Result AlbumManager::GetAlbumEntry(AlbumEntry& out_entry, const std::filesystem:
.application_id = static_cast<u64>(std::stoll(application, 0, 16)),
.date =
{
.year = static_cast<s16>(std::stoi(year)),
.month = static_cast<s8>(std::stoi(month)),
.day = static_cast<s8>(std::stoi(day)),
.hour = static_cast<s8>(std::stoi(hour)),
.minute = static_cast<s8>(std::stoi(minute)),
.second = static_cast<s8>(std::stoi(second)),
.year = static_cast<u16>(std::stoi(year)),
.month = static_cast<u8>(std::stoi(month)),
.day = static_cast<u8>(std::stoi(day)),
.hour = static_cast<u8>(std::stoi(hour)),
.minute = static_cast<u8>(std::stoi(minute)),
.second = static_cast<u8>(std::stoi(second)),
.unique_id = 0,
},
.storage = AlbumStorage::Sd,
@@ -364,23 +339,4 @@ Result AlbumManager::LoadImage(std::span<u8> out_image, const std::filesystem::p
return ResultSuccess;
}
AlbumFileDateTime AlbumManager::ConvertToAlbumDateTime(u64 posix_time) const {
Time::TimeZone::CalendarInfo calendar_date{};
const auto& time_zone_manager =
system.GetTimeManager().GetTimeZoneContentManager().GetTimeZoneManager();
time_zone_manager.ToCalendarTimeWithMyRules(posix_time, calendar_date);
return {
.year = calendar_date.time.year,
.month = calendar_date.time.month,
.day = calendar_date.time.day,
.hour = calendar_date.time.hour,
.minute = calendar_date.time.minute,
.second = calendar_date.time.second,
.unique_id = 0,
};
}
} // namespace Service::Capture

View File

@@ -37,7 +37,7 @@ namespace Service::Capture {
class AlbumManager {
public:
explicit AlbumManager(Core::System& system_);
explicit AlbumManager();
~AlbumManager();
Result DeleteAlbumFile(const AlbumFileId& file_id);
@@ -45,9 +45,6 @@ public:
Result GetAlbumFileList(std::vector<AlbumEntry>& out_entries, AlbumStorage storage,
u8 flags) const;
Result GetAlbumFileList(std::vector<ApplicationAlbumFileEntry>& out_entries,
ContentType contex_type, s64 start_posix_time, s64 end_posix_time,
u64 aruid) const;
Result GetAlbumFileList(std::vector<ApplicationAlbumEntry>& out_entries,
ContentType contex_type, AlbumFileDateTime start_date,
AlbumFileDateTime end_date, u64 aruid) const;
Result GetAutoSavingStorage(bool& out_is_autosaving) const;
@@ -68,12 +65,8 @@ private:
Result LoadImage(std::span<u8> out_image, const std::filesystem::path& path, int width,
int height, ScreenShotDecoderFlag flag) const;
AlbumFileDateTime ConvertToAlbumDateTime(u64 posix_time) const;
bool is_mounted{};
std::unordered_map<AlbumFileId, std::filesystem::path> album_files;
Core::System& system;
};
} // namespace Service::Capture

View File

@@ -41,13 +41,13 @@ enum class ScreenShotDecoderFlag : u64 {
// This is nn::capsrv::AlbumFileDateTime
struct AlbumFileDateTime {
s16 year{};
s8 month{};
s8 day{};
s8 hour{};
s8 minute{};
s8 second{};
s8 unique_id{};
u16 year{};
u8 month{};
u8 day{};
u8 hour{};
u8 minute{};
u8 second{};
u8 unique_id{};
friend constexpr bool operator==(const AlbumFileDateTime&, const AlbumFileDateTime&) = default;
friend constexpr bool operator>(const AlbumFileDateTime& a, const AlbumFileDateTime& b) {

View File

@@ -50,35 +50,22 @@ void IAlbumApplicationService::SetShimLibraryVersion(HLERequestContext& ctx) {
void IAlbumApplicationService::GetAlbumFileList0AafeAruidDeprecated(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
struct Parameters {
ContentType content_type;
INSERT_PADDING_BYTES(7);
s64 start_posix_time;
s64 end_posix_time;
u64 applet_resource_user_id;
};
static_assert(sizeof(Parameters) == 0x20, "Parameters has incorrect size.");
const auto parameters{rp.PopRaw<Parameters>()};
const auto pid{rp.Pop<s32>()};
const auto content_type{rp.PopEnum<ContentType>()};
const auto start_posix_time{rp.Pop<s64>()};
const auto end_posix_time{rp.Pop<s64>()};
const auto applet_resource_user_id{rp.Pop<u64>()};
LOG_WARNING(Service_Capture,
"(STUBBED) called. content_type={}, start_posix_time={}, end_posix_time={}, "
"applet_resource_user_id={}",
parameters.content_type, parameters.start_posix_time, parameters.end_posix_time,
parameters.applet_resource_user_id);
"(STUBBED) called. pid={}, content_type={}, start_posix_time={}, "
"end_posix_time={}, applet_resource_user_id={}",
pid, content_type, start_posix_time, end_posix_time, applet_resource_user_id);
Result result = ResultSuccess;
if (result.IsSuccess()) {
result = manager->IsAlbumMounted(AlbumStorage::Sd);
}
// TODO: Translate posix to DateTime
std::vector<ApplicationAlbumFileEntry> entries;
if (result.IsSuccess()) {
result = manager->GetAlbumFileList(entries, parameters.content_type,
parameters.start_posix_time, parameters.end_posix_time,
parameters.applet_resource_user_id);
}
const Result result =
manager->GetAlbumFileList(entries, content_type, {}, {}, applet_resource_user_id);
if (!entries.empty()) {
ctx.WriteBuffer(entries);
@@ -91,38 +78,19 @@ void IAlbumApplicationService::GetAlbumFileList0AafeAruidDeprecated(HLERequestCo
void IAlbumApplicationService::GetAlbumFileList3AaeAruid(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
struct Parameters {
ContentType content_type;
INSERT_PADDING_BYTES(1);
AlbumFileDateTime start_date_time;
AlbumFileDateTime end_date_time;
INSERT_PADDING_BYTES(6);
u64 applet_resource_user_id;
};
static_assert(sizeof(Parameters) == 0x20, "Parameters has incorrect size.");
const auto parameters{rp.PopRaw<Parameters>()};
const auto pid{rp.Pop<s32>()};
const auto content_type{rp.PopEnum<ContentType>()};
const auto start_date_time{rp.PopRaw<AlbumFileDateTime>()};
const auto end_date_time{rp.PopRaw<AlbumFileDateTime>()};
const auto applet_resource_user_id{rp.Pop<u64>()};
LOG_WARNING(Service_Capture,
"(STUBBED) called. content_type={}, start_date={}/{}/{}, "
"end_date={}/{}/{}, applet_resource_user_id={}",
parameters.content_type, parameters.start_date_time.year,
parameters.start_date_time.month, parameters.start_date_time.day,
parameters.end_date_time.year, parameters.end_date_time.month,
parameters.end_date_time.day, parameters.applet_resource_user_id);
"(STUBBED) called. pid={}, content_type={}, applet_resource_user_id={}", pid,
content_type, applet_resource_user_id);
Result result = ResultSuccess;
if (result.IsSuccess()) {
result = manager->IsAlbumMounted(AlbumStorage::Sd);
}
std::vector<ApplicationAlbumEntry> entries;
if (result.IsSuccess()) {
result =
manager->GetAlbumFileList(entries, parameters.content_type, parameters.start_date_time,
parameters.end_date_time, parameters.applet_resource_user_id);
}
std::vector<ApplicationAlbumFileEntry> entries;
const Result result = manager->GetAlbumFileList(entries, content_type, start_date_time,
end_date_time, applet_resource_user_id);
if (!entries.empty()) {
ctx.WriteBuffer(entries);

View File

@@ -156,8 +156,6 @@ public:
bool LoadNRO(std::span<const u8> data) {
local_memory.clear();
relocbase = local_memory.size();
local_memory.insert(local_memory.end(), data.begin(), data.end());
if (FixupRelocations()) {
@@ -183,8 +181,8 @@ public:
// https://refspecs.linuxbase.org/elf/gabi4+/ch5.dynamic.html
// https://refspecs.linuxbase.org/elf/gabi4+/ch4.reloc.html
VAddr dynamic_offset{mod_offset + callbacks->MemoryRead32(mod_offset + 4)};
VAddr rela_dyn = 0, relr_dyn = 0;
size_t num_rela = 0, num_relr = 0;
VAddr rela_dyn = 0;
size_t num_rela = 0;
while (true) {
const auto dyn{callbacks->ReadMemory<Elf64_Dyn>(dynamic_offset)};
dynamic_offset += sizeof(Elf64_Dyn);
@@ -198,12 +196,6 @@ public:
if (dyn.d_tag == ElfDtRelasz) {
num_rela = dyn.d_un.d_val / sizeof(Elf64_Rela);
}
if (dyn.d_tag == ElfDtRelr) {
relr_dyn = dyn.d_un.d_ptr;
}
if (dyn.d_tag == ElfDtRelrsz) {
num_relr = dyn.d_un.d_val / sizeof(Elf64_Relr);
}
}
for (size_t i = 0; i < num_rela; i++) {
@@ -215,29 +207,6 @@ public:
callbacks->MemoryWrite64(rela.r_offset, contents + rela.r_addend);
}
VAddr relr_where = 0;
for (size_t i = 0; i < num_relr; i++) {
const auto relr{callbacks->ReadMemory<Elf64_Relr>(relr_dyn + i * sizeof(Elf64_Relr))};
const auto incr{[&](VAddr where) {
callbacks->MemoryWrite64(where, callbacks->MemoryRead64(where) + relocbase);
}};
if ((relr & 1) == 0) {
// where pointer
relr_where = relocbase + relr;
incr(relr_where);
relr_where += sizeof(Elf64_Addr);
} else {
// bitmap
for (int bit = 1; bit < 64; bit++) {
if ((relr & (1ULL << bit)) != 0) {
incr(relr_where + i * sizeof(Elf64_Addr));
}
}
relr_where += 63 * sizeof(Elf64_Addr);
}
}
return true;
}
@@ -344,7 +313,6 @@ public:
Core::Memory::Memory& memory;
VAddr top_of_stack;
VAddr heap_pointer;
VAddr relocbase;
};
void DynarmicCallbacks64::CallSVC(u32 swi) {

View File

@@ -544,7 +544,7 @@ void BufferCache<P>::CommitAsyncFlushesHigh() {
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 largest_copy = 0;
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 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) {
runtime.BindStorageBuffer(stage, binding_index, buffer, offset, size, is_written);
++binding_index;
@@ -936,11 +931,6 @@ void BufferCache<P>::BindHostGraphicsTextureBuffers(size_t stage) {
const u32 size = binding.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 PixelFormat format = binding.format;
if constexpr (SEPARATE_IMAGE_BUFFERS_BINDINGS) {
@@ -972,8 +962,6 @@ void BufferCache<P>::BindHostTransformFeedbackBuffers() {
const u32 size = binding.size;
SynchronizeBuffer(buffer, binding.cpu_addr, size);
MarkWrittenBuffer(binding.buffer_id, binding.cpu_addr, size);
const u32 offset = buffer.Offset(binding.cpu_addr);
host_bindings.buffers.push_back(&buffer);
host_bindings.offsets.push_back(offset);
@@ -1023,11 +1011,6 @@ void BufferCache<P>::BindHostComputeStorageBuffers() {
const u32 offset = buffer.Offset(binding.cpu_addr);
const bool is_written =
((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) {
runtime.BindComputeStorageBuffer(binding_index, buffer, offset, size, is_written);
++binding_index;
@@ -1045,12 +1028,6 @@ void BufferCache<P>::BindHostComputeTextureBuffers() {
const u32 size = binding.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 PixelFormat format = binding.format;
if constexpr (SEPARATE_IMAGE_BUFFERS_BINDINGS) {
@@ -1224,11 +1201,16 @@ void BufferCache<P>::UpdateUniformBuffers(size_t stage) {
template <class P>
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) {
// Resolve buffer
Binding& binding = channel_state->storage_buffers[stage][index];
const BufferId buffer_id = FindBuffer(binding.cpu_addr, binding.size);
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) {
Binding& binding = channel_state->texture_buffers[stage][index];
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,
.buffer_id = buffer_id,
};
MarkWrittenBuffer(buffer_id, *cpu_addr, size);
}
template <class P>
@@ -1292,6 +1279,10 @@ void BufferCache<P>::UpdateComputeStorageBuffers() {
// Resolve buffer
Binding& binding = channel_state->compute_storage_buffers[index];
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) {
Binding& binding = channel_state->compute_texture_buffers[index];
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>
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);
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) {
const auto& resolution = runtime->resolution;
if (!resolution.active) {
return false;
}
if (True(flags & ImageFlagBits::Rescaled)) {
return false;
}
@@ -1064,6 +1060,9 @@ bool Image::ScaleUp(bool ignore) {
return false;
}
flags |= ImageFlagBits::Rescaled;
if (!runtime->resolution.active) {
return false;
}
has_scaled = true;
if (ignore) {
current_texture = upscaled_backup.handle;
@@ -1074,14 +1073,13 @@ bool Image::ScaleUp(bool ignore) {
}
bool Image::ScaleDown(bool ignore) {
const auto& resolution = runtime->resolution;
if (!resolution.active) {
return false;
}
if (False(flags & ImageFlagBits::Rescaled)) {
return false;
}
flags &= ~ImageFlagBits::Rescaled;
if (!runtime->resolution.active) {
return false;
}
if (ignore) {
current_texture = texture.handle;
return true;

View File

@@ -118,8 +118,6 @@ public:
void InsertUploadMemoryBarrier();
void TransitionImageLayout(Image& image) {}
FormatProperties FormatInfo(VideoCommon::ImageType type, GLenum internal_format) const;
bool HasNativeBgr() const noexcept {

View File

@@ -1530,15 +1530,15 @@ bool Image::IsRescaled() const noexcept {
}
bool Image::ScaleUp(bool ignore) {
const auto& resolution = runtime->resolution;
if (!resolution.active) {
return false;
}
if (True(flags & ImageFlagBits::Rescaled)) {
return false;
}
ASSERT(info.type != ImageType::Linear);
flags |= ImageFlagBits::Rescaled;
const auto& resolution = runtime->resolution;
if (!resolution.active) {
return false;
}
has_scaled = true;
if (!scaled_image) {
const bool is_2d = info.type == ImageType::e2D;
@@ -1567,15 +1567,15 @@ bool Image::ScaleUp(bool ignore) {
}
bool Image::ScaleDown(bool ignore) {
const auto& resolution = runtime->resolution;
if (!resolution.active) {
return false;
}
if (False(flags & ImageFlagBits::Rescaled)) {
return false;
}
ASSERT(info.type != ImageType::Linear);
flags &= ~ImageFlagBits::Rescaled;
const auto& resolution = runtime->resolution;
if (!resolution.active) {
return false;
}
current_image = *original_image;
if (ignore) {
return true;
@@ -2013,32 +2013,4 @@ void TextureCacheRuntime::AccelerateImageUpload(
ASSERT(false);
}
void TextureCacheRuntime::TransitionImageLayout(Image& image) {
if (!image.ExchangeInitialization()) {
VkImageMemoryBarrier barrier{
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
.pNext = nullptr,
.srcAccessMask = VK_ACCESS_NONE,
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT,
.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
.newLayout = VK_IMAGE_LAYOUT_GENERAL,
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
.image = image.Handle(),
.subresourceRange{
.aspectMask = image.AspectMask(),
.baseMipLevel = 0,
.levelCount = VK_REMAINING_MIP_LEVELS,
.baseArrayLayer = 0,
.layerCount = VK_REMAINING_ARRAY_LAYERS,
},
};
scheduler.RequestOutsideRenderPassOperationContext();
scheduler.Record([barrier = barrier](vk::CommandBuffer cmdbuf) {
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, barrier);
});
}
}
} // namespace Vulkan

View File

@@ -92,8 +92,6 @@ public:
void InsertUploadMemoryBarrier() {}
void TransitionImageLayout(Image& image);
bool HasBrokenTextureViewFormats() const noexcept {
// No known Vulkan driver has broken image views
return false;

View File

@@ -1016,7 +1016,6 @@ void TextureCache<P>::RefreshContents(Image& image, ImageId image_id) {
if (image.info.num_samples > 1 && !runtime.CanUploadMSAA()) {
LOG_WARNING(HW_GPU, "MSAA image uploads are not implemented");
runtime.TransitionImageLayout(image);
return;
}
if (True(image.flags & ImageFlagBits::AsynchronousDecode)) {

View File

@@ -68,7 +68,6 @@ struct LevelInfo {
Extent2D tile_size;
u32 bpp_log2;
u32 tile_width_spacing;
u32 num_levels;
};
[[nodiscard]] constexpr u32 AdjustTileSize(u32 shift, u32 unit_factor, u32 dimension) {
@@ -119,11 +118,11 @@ template <u32 GOB_EXTENT>
}
[[nodiscard]] constexpr Extent3D AdjustMipBlockSize(Extent3D num_tiles, Extent3D block_size,
u32 level, u32 num_levels) {
u32 level) {
return {
.width = AdjustMipBlockSize<GOB_SIZE_X>(num_tiles.width, block_size.width, level),
.height = AdjustMipBlockSize<GOB_SIZE_Y>(num_tiles.height, block_size.height, level),
.depth = level == 0 && num_levels == 1
.depth = level == 0
? block_size.depth
: AdjustMipBlockSize<GOB_SIZE_Z>(num_tiles.depth, block_size.depth, level),
};
@@ -167,6 +166,13 @@ template <u32 GOB_EXTENT>
}
[[nodiscard]] constexpr Extent3D TileShift(const LevelInfo& info, u32 level) {
if (level == 0) {
return Extent3D{
.width = info.block.width,
.height = info.block.height,
.depth = info.block.depth,
};
}
const Extent3D blocks = NumLevelBlocks(info, level);
return Extent3D{
.width = AdjustTileSize(info.block.width, GOB_SIZE_X, blocks.width),
@@ -251,7 +257,7 @@ template <u32 GOB_EXTENT>
}
[[nodiscard]] constexpr LevelInfo MakeLevelInfo(PixelFormat format, Extent3D size, Extent3D block,
u32 tile_width_spacing, u32 num_levels) {
u32 tile_width_spacing) {
const u32 bytes_per_block = BytesPerBlock(format);
return {
.size =
@@ -264,18 +270,16 @@ template <u32 GOB_EXTENT>
.tile_size = DefaultBlockSize(format),
.bpp_log2 = BytesPerBlockLog2(bytes_per_block),
.tile_width_spacing = tile_width_spacing,
.num_levels = num_levels,
};
}
[[nodiscard]] constexpr LevelInfo MakeLevelInfo(const ImageInfo& info) {
return MakeLevelInfo(info.format, info.size, info.block, info.tile_width_spacing,
info.resources.levels);
return MakeLevelInfo(info.format, info.size, info.block, info.tile_width_spacing);
}
[[nodiscard]] constexpr u32 CalculateLevelOffset(PixelFormat format, Extent3D size, Extent3D block,
u32 tile_width_spacing, u32 level) {
const LevelInfo info = MakeLevelInfo(format, size, block, tile_width_spacing, level);
const LevelInfo info = MakeLevelInfo(format, size, block, tile_width_spacing);
u32 offset = 0;
for (u32 current_level = 0; current_level < level; ++current_level) {
offset += CalculateLevelSize(info, current_level);
@@ -462,7 +466,7 @@ template <u32 GOB_EXTENT>
};
const u32 bpp_log2 = BytesPerBlockLog2(info.format);
const u32 alignment = StrideAlignment(num_tiles, info.block, bpp_log2, info.tile_width_spacing);
const Extent3D mip_block = AdjustMipBlockSize(num_tiles, info.block, 0, info.resources.levels);
const Extent3D mip_block = AdjustMipBlockSize(num_tiles, info.block, 0);
return Extent3D{
.width = Common::AlignUpLog2(num_tiles.width, alignment),
.height = Common::AlignUpLog2(num_tiles.height, GOB_SIZE_Y_SHIFT + mip_block.height),
@@ -529,8 +533,7 @@ void SwizzleBlockLinearImage(Tegra::MemoryManager& gpu_memory, GPUVAddr gpu_addr
UNIMPLEMENTED_IF(copy.image_extent != level_size);
const Extent3D num_tiles = AdjustTileSize(level_size, tile_size);
const Extent3D block =
AdjustMipBlockSize(num_tiles, level_info.block, level, level_info.num_levels);
const Extent3D block = AdjustMipBlockSize(num_tiles, level_info.block, level);
size_t host_offset = copy.buffer_offset;
@@ -695,7 +698,7 @@ u32 CalculateLevelStrideAlignment(const ImageInfo& info, u32 level) {
const Extent2D tile_size = DefaultBlockSize(info.format);
const Extent3D level_size = AdjustMipSize(info.size, level);
const Extent3D num_tiles = AdjustTileSize(level_size, tile_size);
const Extent3D block = AdjustMipBlockSize(num_tiles, info.block, level, info.resources.levels);
const Extent3D block = AdjustMipBlockSize(num_tiles, info.block, level);
const u32 bpp_log2 = BytesPerBlockLog2(info.format);
return StrideAlignment(num_tiles, block, bpp_log2, info.tile_width_spacing);
}
@@ -884,8 +887,7 @@ boost::container::small_vector<BufferImageCopy, 16> UnswizzleImage(Tegra::Memory
.image_extent = level_size,
};
const Extent3D num_tiles = AdjustTileSize(level_size, tile_size);
const Extent3D block =
AdjustMipBlockSize(num_tiles, level_info.block, level, level_info.num_levels);
const Extent3D block = AdjustMipBlockSize(num_tiles, level_info.block, level);
const u32 stride_alignment = StrideAlignment(num_tiles, info.block, gob, bpp_log2);
size_t guest_layer_offset = 0;
@@ -1039,7 +1041,7 @@ Extent3D MipBlockSize(const ImageInfo& info, u32 level) {
const Extent2D tile_size = DefaultBlockSize(info.format);
const Extent3D level_size = AdjustMipSize(info.size, level);
const Extent3D num_tiles = AdjustTileSize(level_size, tile_size);
return AdjustMipBlockSize(num_tiles, level_info.block, level, level_info.num_levels);
return AdjustMipBlockSize(num_tiles, level_info.block, level);
}
boost::container::small_vector<SwizzleParameters, 16> FullUploadSwizzles(const ImageInfo& info) {
@@ -1061,8 +1063,7 @@ boost::container::small_vector<SwizzleParameters, 16> FullUploadSwizzles(const I
for (s32 level = 0; level < num_levels; ++level) {
const Extent3D level_size = AdjustMipSize(size, level);
const Extent3D num_tiles = AdjustTileSize(level_size, tile_size);
const Extent3D block =
AdjustMipBlockSize(num_tiles, level_info.block, level, level_info.num_levels);
const Extent3D block = AdjustMipBlockSize(num_tiles, level_info.block, level);
params[level] = SwizzleParameters{
.num_tiles = num_tiles,
.block = block,
@@ -1291,11 +1292,11 @@ u32 MapSizeBytes(const ImageBase& image) {
}
}
static_assert(CalculateLevelSize(LevelInfo{{1920, 1080, 1}, {0, 2, 0}, {1, 1}, 2, 0, 1}, 0) ==
static_assert(CalculateLevelSize(LevelInfo{{1920, 1080, 1}, {0, 2, 0}, {1, 1}, 2, 0}, 0) ==
0x7f8000);
static_assert(CalculateLevelSize(LevelInfo{{32, 32, 1}, {0, 0, 4}, {1, 1}, 4, 0, 1}, 0) == 0x4000);
static_assert(CalculateLevelSize(LevelInfo{{32, 32, 1}, {0, 0, 4}, {1, 1}, 4, 0}, 0) == 0x40000);
static_assert(CalculateLevelSize(LevelInfo{{128, 8, 1}, {0, 4, 0}, {1, 1}, 4, 0, 1}, 0) == 0x4000);
static_assert(CalculateLevelSize(LevelInfo{{128, 8, 1}, {0, 4, 0}, {1, 1}, 4, 0}, 0) == 0x40000);
static_assert(CalculateLevelOffset(PixelFormat::R8_SINT, {1920, 1080, 1}, {0, 2, 0}, 0, 7) ==
0x2afc00);

View File

@@ -66,10 +66,9 @@ struct Range {
switch (usage) {
case MemoryUsage::Upload:
case MemoryUsage::Stream:
return VMA_ALLOCATION_CREATE_MAPPED_BIT |
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT;
return VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT;
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:
return {};
}
@@ -253,7 +252,8 @@ vk::Image MemoryAllocator::CreateImage(const VkImageCreateInfo& ci) const {
vk::Buffer MemoryAllocator::CreateBuffer(const VkBufferCreateInfo& ci, MemoryUsage usage) const {
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),
.requiredFlags = 0,
.preferredFlags = MemoryUsagePreferedVmaFlags(usage),

View File

@@ -23,7 +23,6 @@
#include "yuzu/configuration/configure_vibration.h"
#include "yuzu/configuration/input_profiles.h"
#include "yuzu/main.h"
#include "yuzu/util/controller_navigation.h"
namespace {
@@ -133,8 +132,6 @@ QtControllerSelectorDialog::QtControllerSelectorDialog(
ui->checkboxPlayer7Connected, ui->checkboxPlayer8Connected,
};
ui->labelError->setVisible(false);
// Setup/load everything prior to setting up connections.
// This avoids unintentionally changing the states of elements while loading them in.
SetSupportedControllers();
@@ -146,8 +143,6 @@ QtControllerSelectorDialog::QtControllerSelectorDialog(
LoadConfiguration();
controller_navigation = new ControllerNavigation(system.HIDCore(), this);
for (std::size_t i = 0; i < NUM_PLAYERS; ++i) {
SetExplainText(i);
UpdateControllerIcon(i);
@@ -156,8 +151,6 @@ QtControllerSelectorDialog::QtControllerSelectorDialog(
connect(player_groupboxes[i], &QGroupBox::toggled, [this, i](bool checked) {
if (checked) {
// Hide eventual error message about number of controllers
ui->labelError->setVisible(false);
for (std::size_t index = 0; index <= i; ++index) {
connected_controller_checkboxes[index]->setChecked(checked);
}
@@ -206,12 +199,6 @@ QtControllerSelectorDialog::QtControllerSelectorDialog(
connect(ui->buttonBox, &QDialogButtonBox::accepted, this,
&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.
// If all the parameters are met AND only allows a single player,
// stop the constructor here as we do not need to continue.
@@ -230,7 +217,6 @@ QtControllerSelectorDialog::QtControllerSelectorDialog(
}
QtControllerSelectorDialog::~QtControllerSelectorDialog() {
controller_navigation->UnloadController();
system.HIDCore().DisableAllControllerConfiguration();
}
@@ -305,31 +291,6 @@ void QtControllerSelectorDialog::CallConfigureInputProfileDialog() {
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() {
// Here, we check and validate the current configuration against all applicable parameters.
const auto num_connected_players = static_cast<int>(

View File

@@ -34,8 +34,6 @@ class HIDCore;
enum class NpadStyleIndex : u8;
} // namespace Core::HID
class ControllerNavigation;
class QtControllerSelectorDialog final : public QDialog {
Q_OBJECT
@@ -48,8 +46,6 @@ public:
int exec() override;
void keyPressEvent(QKeyEvent* evt) override;
private:
// Applies the current configuration.
void ApplyConfiguration();
@@ -114,8 +110,6 @@ private:
Core::System& system;
ControllerNavigation* controller_navigation = nullptr;
// 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.
bool parameters_met{false};

View File

@@ -2624,53 +2624,13 @@
</spacer>
</item>
<item alignment="Qt::AlignBottom">
<widget class="QWidget" name="closeButtons" native="true">
<layout class="QVBoxLayout" name="verticalLayout_46">
<property name="spacing">
<number>7</number>
</property>
<property name="leftMargin">
<number>0</number>
</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 class="QDialogButtonBox" name="buttonBox">
<property name="enabled">
<bool>true</bool>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>

View File

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