Compare commits

..

36 Commits

Author SHA1 Message Date
ameerj
8d45dd3b73 Vulkan: Use 3D helpers for MSAA scaling on NV drivers 510+
Nvidia Vulkan drivers 510+ crash when blitting MSAA images. Fall-back to 3D scale helpers for MSAA image scaling.
2022-03-23 23:30:17 -04:00
Ameer J
fb4d80b169 Merge pull request #8073 from Shoegzer/compile_fixes
Add include to fix compiling
2022-03-23 16:31:02 -04:00
Shoegzer
a8896e940a Add include to fix compiling 2022-03-23 16:18:48 -04:00
bunnei
749efbb84b Merge pull request #8031 from Morph1984/cleanup-mii-please
applets: Cleanup MiiEdit applet implementation
2022-03-22 21:56:42 -07:00
bunnei
f8773e4ba0 Merge pull request #8070 from yuzu-emu/revert-8016-kill-mem-use
Revert "dynarmic: Reduce size of code caches"
2022-03-22 18:34:19 -07:00
bunnei
e439c31c9e Revert "dynarmic: Reduce size of code caches" 2022-03-22 18:32:54 -07:00
Morph
6e232b9efe applets/mii: Remove unused include 2022-03-21 23:57:31 -04:00
Morph
bcca849d0c applets/mii: Remove frontend parameters
These are unused for now as we do not support a frontend implementation.
2022-03-21 23:57:31 -04:00
Morph
c50401903f applets/mii: Cleanup MiiEdit applet implementation
This also enables proper support for MiiEdit applets which are used in games with firmware versions prior to 10.2.0 by handling the 2 different versions of applet inputs and outputs.
2022-03-21 23:57:31 -04:00
Morph
1d5f6b173d applets/mii: Cleanup MiiEdit applet types 2022-03-21 23:57:31 -04:00
Morph
7c44a4ede3 applets/mii: Move MiiEdit applet types into its own file 2022-03-21 23:57:31 -04:00
Morph
aa44ef7b64 service: Move mii enums and structs into its own file
Moves these into types.h, since other files also make use of these types.
2022-03-21 23:57:31 -04:00
Morph
e05e6853fa applets: Rename Mii to MiiEdit 2022-03-21 23:57:31 -04:00
Narr the Reg
f83cd2e8b9 Merge pull request #8067 from ameerj/qt-browser-include
qt_web_browser: Add missing includes
2022-03-21 21:33:09 -06:00
ameerj
b3cfccdb80 qt_web_browser: Add missing includes 2022-03-21 22:42:14 -04:00
Ameer J
75046a3351 Merge pull request #8038 from liamwhite/exit-register-detection
shader_recompiler/EXIT: increment output register on failed enable test
2022-03-21 21:24:07 -04:00
bunnei
82ac66f8a4 Merge pull request #8048 from ameerj/include-purge
general: Reduce unused includes across the project
2022-03-21 18:03:54 -07:00
bunnei
ff2e891022 Merge pull request #7812 from FernandoS27/made-straight-from-the-nut
BufferCache: Find direction of the stream buffer increase.
2022-03-20 15:23:53 -07:00
Fernando Sahmkow
3b0d233cbd BufferCache: Find direction of the stream buffer increase. 2022-03-20 21:37:23 +01:00
Mai M
628534a9ac Merge pull request #8054 from merryhime/dynarmic
dynarmic: Accelerate SHA256 and implement for A32 frontend
2022-03-20 10:37:38 -04:00
Merry
d1c0cdf4f2 dynarmic: Accelerate SHA256 and implement for A32 frontend
* Implements hardware acceleration for SHA256 instructions.
 * Adds SHA256 instructions introduced in ARMv8 to A32 frontend.
 * Implements polyfill for processors that do not support hardware
   accelerated SHA instructions.
2022-03-20 14:06:17 +00:00
Fernando S
7c05c987a3 Merge pull request #8036 from ameerj/starbit-nv
vk_texture_cache: Do not reinterpret DepthStencil source images
2022-03-20 13:35:59 +01:00
bunnei
150f6db4d1 Merge pull request #7840 from lioncash/bitor
texture_cache: Amend unintended bitwise OR in SynchronizeAliases
2022-03-20 02:19:30 -07:00
bunnei
5960d54722 Merge pull request #8040 from Morph1984/handle-table
KHandleTable: Optimize table entry layout
2022-03-19 23:17:37 -07:00
bunnei
474318ee37 Merge pull request #8047 from ameerj/msvc-test-disable
.ci/build-msvc: Disable YUZU_TESTS cmake variable
2022-03-19 16:28:17 -07:00
bunnei
17ebe211ec Merge pull request #8025 from lat9nq/cmd-specify-config
yuzu_cmd: Allow user to specify config file location
2022-03-19 01:33:50 -07:00
ameerj
c85a3e5a28 build-msvc: Disable tests 2022-03-19 02:35:09 -04:00
Liam
536d7ed7b1 Address review comments 2022-03-18 15:55:46 -04:00
Liam
d400b618a7 shader_recompiler/EXIT: skip render targets with no outputs 2022-03-18 09:26:25 -04:00
Morph
8b7d571b66 KHandleTable: Optimize table entry layout
Since the handle type is not being used, we can reduce the amount of space each entry takes up by 4 bytes.
2022-03-18 00:28:25 -04:00
Liam
6fa17f3372 shader_recompiler/EXIT: increment output register on failed enable test 2022-03-17 22:09:31 -04:00
ameerj
4d840aa903 vk_texture_cache: Do not reinterpret DepthStencil source images
Fixes star pointer interactions in Super Mario Galaxy on some drivers, notably Nvidia.

Co-Authored-By: Fernando S. <1731197+fernandos27@users.noreply.github.com>
2022-03-17 20:55:05 -04:00
lat9nq
24d51e1c92 yuzu_cmd: Allow user to specify config file location
Adds an option `-c` or `--config` with one required argument that allows
the user to specify to where the config file is located. Useful for
scripts that run specific games with different preferences for settings.
2022-03-15 03:48:40 -04:00
Lioncash
e015dc8264 texture_cache: Ensure has_blacklisted is always initialized
Resolves a -Wmaybe_uninitialized warning
2022-02-02 14:37:27 -05:00
Lioncash
7367e55d1d texture_cache: Remove dead code within SynchronizeAliases
Since these were being copied by value, none of the changes applied in
the loop would be reflected.

However, from the looks of it, this would already be applied within
CopyImage() anyways, so this can be removed.
2022-02-02 14:37:22 -05:00
Lioncash
856f576c05 texture_cache: Amend unintended bitwise OR in SynchronizeAliases 2022-02-02 14:20:58 -05:00
37 changed files with 727 additions and 653 deletions

View File

@@ -8,7 +8,7 @@ steps:
displayName: 'Install vulkan-sdk'
- script: python -m pip install --upgrade pip conan
displayName: 'Install conan'
- script: refreshenv && mkdir build && cd build && cmake -G "Visual Studio 16 2019" -A x64 -DYUZU_USE_BUNDLED_QT=1 -DYUZU_USE_BUNDLED_SDL2=1 -DYUZU_USE_QT_WEB_ENGINE=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${COMPAT} -DUSE_DISCORD_PRESENCE=ON -DENABLE_QT_TRANSLATION=ON -DDISPLAY_VERSION=${{ parameters['version'] }} -DCMAKE_BUILD_TYPE=Release .. && cd ..
- script: refreshenv && mkdir build && cd build && cmake -G "Visual Studio 16 2019" -A x64 -DYUZU_USE_BUNDLED_QT=1 -DYUZU_USE_BUNDLED_SDL2=1 -DYUZU_USE_QT_WEB_ENGINE=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${COMPAT} -DYUZU_TESTS=OFF -DUSE_DISCORD_PRESENCE=ON -DENABLE_QT_TRANSLATION=ON -DDISPLAY_VERSION=${{ parameters['version'] }} -DCMAKE_BUILD_TYPE=Release .. && cd ..
displayName: 'Configure CMake'
- task: MSBuild@1
displayName: 'Build'

View File

@@ -122,8 +122,8 @@ add_library(core STATIC
frontend/applets/error.h
frontend/applets/general_frontend.cpp
frontend/applets/general_frontend.h
frontend/applets/mii.cpp
frontend/applets/mii.h
frontend/applets/mii_edit.cpp
frontend/applets/mii_edit.h
frontend/applets/profile_select.cpp
frontend/applets/profile_select.h
frontend/applets/software_keyboard.cpp
@@ -306,8 +306,9 @@ add_library(core STATIC
hle/service/am/applets/applet_error.h
hle/service/am/applets/applet_general_backend.cpp
hle/service/am/applets/applet_general_backend.h
hle/service/am/applets/applet_mii.cpp
hle/service/am/applets/applet_mii.h
hle/service/am/applets/applet_mii_edit.cpp
hle/service/am/applets/applet_mii_edit.h
hle/service/am/applets/applet_mii_edit_types.h
hle/service/am/applets/applet_profile_select.cpp
hle/service/am/applets/applet_profile_select.h
hle/service/am/applets/applet_software_keyboard.cpp

View File

@@ -148,8 +148,8 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable*
config.wall_clock_cntpct = uses_wall_clock;
// Code cache size
config.code_cache_size = 128_MiB;
config.far_code_offset = 100_MiB;
config.code_cache_size = 512_MiB;
config.far_code_offset = 400_MiB;
// Safe optimizations
if (Settings::values.cpu_debug_mode) {

View File

@@ -208,8 +208,8 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable*
config.wall_clock_cntpct = uses_wall_clock;
// Code cache size
config.code_cache_size = 128_MiB;
config.far_code_offset = 100_MiB;
config.code_cache_size = 512_MiB;
config.far_code_offset = 400_MiB;
// Safe optimizations
if (Settings::values.cpu_debug_mode) {

View File

@@ -1,19 +0,0 @@
// Copyright 2022 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "common/logging/log.h"
#include "core/frontend/applets/mii.h"
namespace Core::Frontend {
MiiApplet::~MiiApplet() = default;
void DefaultMiiApplet::ShowMii(
const MiiParameters& parameters,
const std::function<void(const Core::Frontend::MiiParameters& parameters)> callback) const {
LOG_INFO(Service_HID, "(STUBBED) called");
callback(parameters);
}
} // namespace Core::Frontend

View File

@@ -1,34 +0,0 @@
// Copyright 2022 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <functional>
#include "core/hle/service/mii/mii_manager.h"
namespace Core::Frontend {
struct MiiParameters {
bool is_editable;
Service::Mii::MiiInfo mii_data{};
};
class MiiApplet {
public:
virtual ~MiiApplet();
virtual void ShowMii(const MiiParameters& parameters,
const std::function<void(const Core::Frontend::MiiParameters& parameters)>
callback) const = 0;
};
class DefaultMiiApplet final : public MiiApplet {
public:
void ShowMii(const MiiParameters& parameters,
const std::function<void(const Core::Frontend::MiiParameters& parameters)>
callback) const override;
};
} // namespace Core::Frontend

View File

@@ -0,0 +1,18 @@
// Copyright 2022 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "common/logging/log.h"
#include "core/frontend/applets/mii_edit.h"
namespace Core::Frontend {
MiiEditApplet::~MiiEditApplet() = default;
void DefaultMiiEditApplet::ShowMiiEdit(const std::function<void()>& callback) const {
LOG_WARNING(Service_AM, "(STUBBED) called");
callback();
}
} // namespace Core::Frontend

View File

@@ -0,0 +1,23 @@
// Copyright 2022 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <functional>
namespace Core::Frontend {
class MiiEditApplet {
public:
virtual ~MiiEditApplet();
virtual void ShowMiiEdit(const std::function<void()>& callback) const = 0;
};
class DefaultMiiEditApplet final : public MiiEditApplet {
public:
void ShowMiiEdit(const std::function<void()>& callback) const override;
};
} // namespace Core::Frontend

View File

@@ -63,7 +63,7 @@ bool KHandleTable::Remove(Handle handle) {
return true;
}
ResultCode KHandleTable::Add(Handle* out_handle, KAutoObject* obj, u16 type) {
ResultCode KHandleTable::Add(Handle* out_handle, KAutoObject* obj) {
KScopedDisableDispatch dd(kernel);
KScopedSpinLock lk(m_lock);
@@ -75,7 +75,7 @@ ResultCode KHandleTable::Add(Handle* out_handle, KAutoObject* obj, u16 type) {
const auto linear_id = this->AllocateLinearId();
const auto index = this->AllocateEntry();
m_entry_infos[index].info = {.linear_id = linear_id, .type = type};
m_entry_infos[index].linear_id = linear_id;
m_objects[index] = obj;
obj->Open();
@@ -116,7 +116,7 @@ void KHandleTable::Unreserve(Handle handle) {
}
}
void KHandleTable::Register(Handle handle, KAutoObject* obj, u16 type) {
void KHandleTable::Register(Handle handle, KAutoObject* obj) {
KScopedDisableDispatch dd(kernel);
KScopedSpinLock lk(m_lock);
@@ -132,7 +132,7 @@ void KHandleTable::Register(Handle handle, KAutoObject* obj, u16 type) {
// Set the entry.
ASSERT(m_objects[index] == nullptr);
m_entry_infos[index].info = {.linear_id = static_cast<u16>(linear_id), .type = type};
m_entry_infos[index].linear_id = static_cast<u16>(linear_id);
m_objects[index] = obj;
obj->Open();

View File

@@ -42,7 +42,7 @@ public:
m_free_head_index = -1;
// Free all entries.
for (s32 i = 0; i < static_cast<s32>(m_table_size); ++i) {
for (s16 i = 0; i < static_cast<s16>(m_table_size); ++i) {
m_objects[i] = nullptr;
m_entry_infos[i].next_free_index = i - 1;
m_free_head_index = i;
@@ -104,17 +104,8 @@ public:
ResultCode Reserve(Handle* out_handle);
void Unreserve(Handle handle);
template <typename T>
ResultCode Add(Handle* out_handle, T* obj) {
static_assert(std::is_base_of_v<KAutoObject, T>);
return this->Add(out_handle, obj, obj->GetTypeObj().GetClassToken());
}
template <typename T>
void Register(Handle handle, T* obj) {
static_assert(std::is_base_of_v<KAutoObject, T>);
return this->Register(handle, obj, obj->GetTypeObj().GetClassToken());
}
ResultCode Add(Handle* out_handle, KAutoObject* obj);
void Register(Handle handle, KAutoObject* obj);
template <typename T>
bool GetMultipleObjects(T** out, const Handle* handles, size_t num_handles) const {
@@ -160,9 +151,6 @@ public:
}
private:
ResultCode Add(Handle* out_handle, KAutoObject* obj, u16 type);
void Register(Handle handle, KAutoObject* obj, u16 type);
s32 AllocateEntry() {
ASSERT(m_count < m_table_size);
@@ -179,7 +167,7 @@ private:
ASSERT(m_count > 0);
m_objects[index] = nullptr;
m_entry_infos[index].next_free_index = m_free_head_index;
m_entry_infos[index].next_free_index = static_cast<s16>(m_free_head_index);
m_free_head_index = index;
@@ -278,19 +266,13 @@ private:
}
union EntryInfo {
struct {
u16 linear_id;
u16 type;
} info;
s32 next_free_index;
u16 linear_id;
s16 next_free_index;
constexpr u16 GetLinearId() const {
return info.linear_id;
return linear_id;
}
constexpr u16 GetType() const {
return info.type;
}
constexpr s32 GetNextFreeIndex() const {
constexpr s16 GetNextFreeIndex() const {
return next_free_index;
}
};

View File

@@ -1,100 +0,0 @@
// Copyright 2022 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "common/assert.h"
#include "common/logging/log.h"
#include "core/core.h"
#include "core/frontend/applets/mii.h"
#include "core/hle/service/am/am.h"
#include "core/hle/service/am/applets/applet_mii.h"
namespace Service::AM::Applets {
Mii::Mii(Core::System& system_, LibraryAppletMode applet_mode_,
const Core::Frontend::MiiApplet& frontend_)
: Applet{system_, applet_mode_}, frontend{frontend_}, system{system_} {}
Mii::~Mii() = default;
void Mii::Initialize() {
is_complete = false;
const auto storage = broker.PopNormalDataToApplet();
ASSERT(storage != nullptr);
const auto data = storage->GetData();
ASSERT(data.size() == sizeof(MiiAppletInput));
std::memcpy(&input_data, data.data(), sizeof(MiiAppletInput));
}
bool Mii::TransactionComplete() const {
return is_complete;
}
ResultCode Mii::GetStatus() const {
return ResultSuccess;
}
void Mii::ExecuteInteractive() {
UNREACHABLE_MSG("Unexpected interactive applet data!");
}
void Mii::Execute() {
if (is_complete) {
return;
}
const auto callback = [this](const Core::Frontend::MiiParameters& parameters) {
DisplayCompleted(parameters);
};
switch (input_data.applet_mode) {
case MiiAppletMode::ShowMiiEdit: {
Service::Mii::MiiManager manager;
Core::Frontend::MiiParameters params{
.is_editable = false,
.mii_data = input_data.mii_char_info.mii_data,
};
frontend.ShowMii(params, callback);
break;
}
case MiiAppletMode::EditMii: {
Service::Mii::MiiManager manager;
Core::Frontend::MiiParameters params{
.is_editable = true,
.mii_data = input_data.mii_char_info.mii_data,
};
frontend.ShowMii(params, callback);
break;
}
case MiiAppletMode::CreateMii: {
Service::Mii::MiiManager manager;
Core::Frontend::MiiParameters params{
.is_editable = true,
.mii_data = manager.BuildDefault(0),
};
frontend.ShowMii(params, callback);
break;
}
default:
UNIMPLEMENTED_MSG("Unimplemented LibAppletMiiEdit mode={:02X}!", input_data.applet_mode);
}
}
void Mii::DisplayCompleted(const Core::Frontend::MiiParameters& parameters) {
is_complete = true;
std::vector<u8> reply(sizeof(AppletOutputForCharInfoEditing));
output_data = {
.result = ResultSuccess,
.mii_data = parameters.mii_data,
};
std::memcpy(reply.data(), &output_data, sizeof(AppletOutputForCharInfoEditing));
broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(reply)));
broker.SignalStateChanged();
}
} // namespace Service::AM::Applets

View File

@@ -1,90 +0,0 @@
// Copyright 2022 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <array>
#include "core/hle/result.h"
#include "core/hle/service/am/applets/applets.h"
#include "core/hle/service/mii/mii_manager.h"
namespace Core {
class System;
}
namespace Service::AM::Applets {
// This is nn::mii::AppletMode
enum class MiiAppletMode : u32 {
ShowMiiEdit = 0,
AppendMii = 1,
AppendMiiImage = 2,
UpdateMiiImage = 3,
CreateMii = 4,
EditMii = 5,
};
struct MiiCharInfo {
Service::Mii::MiiInfo mii_data{};
INSERT_PADDING_BYTES(0x28);
};
static_assert(sizeof(MiiCharInfo) == 0x80, "MiiCharInfo has incorrect size.");
// This is nn::mii::AppletInput
struct MiiAppletInput {
s32 version{};
MiiAppletMode applet_mode{};
u32 special_mii_key_code{};
union {
std::array<Common::UUID, 8> valid_uuid;
MiiCharInfo mii_char_info;
};
Common::UUID used_uuid;
INSERT_PADDING_BYTES(0x64);
};
static_assert(sizeof(MiiAppletInput) == 0x100, "MiiAppletInput has incorrect size.");
// This is nn::mii::AppletOutput
struct MiiAppletOutput {
ResultCode result{ResultSuccess};
s32 index{};
INSERT_PADDING_BYTES(0x18);
};
static_assert(sizeof(MiiAppletOutput) == 0x20, "MiiAppletOutput has incorrect size.");
// This is nn::mii::AppletOutputForCharInfoEditing
struct AppletOutputForCharInfoEditing {
ResultCode result{ResultSuccess};
Service::Mii::MiiInfo mii_data{};
INSERT_PADDING_BYTES(0x24);
};
static_assert(sizeof(AppletOutputForCharInfoEditing) == 0x80,
"AppletOutputForCharInfoEditing has incorrect size.");
class Mii final : public Applet {
public:
explicit Mii(Core::System& system_, LibraryAppletMode applet_mode_,
const Core::Frontend::MiiApplet& frontend_);
~Mii() override;
void Initialize() override;
bool TransactionComplete() const override;
ResultCode GetStatus() const override;
void ExecuteInteractive() override;
void Execute() override;
void DisplayCompleted(const Core::Frontend::MiiParameters& parameters);
private:
const Core::Frontend::MiiApplet& frontend;
MiiAppletInput input_data{};
AppletOutputForCharInfoEditing output_data{};
bool is_complete = false;
Core::System& system;
};
} // namespace Service::AM::Applets

View File

@@ -0,0 +1,139 @@
// Copyright 2022 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "common/assert.h"
#include "common/logging/log.h"
#include "core/core.h"
#include "core/frontend/applets/mii_edit.h"
#include "core/hle/service/am/am.h"
#include "core/hle/service/am/applets/applet_mii_edit.h"
#include "core/hle/service/mii/mii_manager.h"
namespace Service::AM::Applets {
MiiEdit::MiiEdit(Core::System& system_, LibraryAppletMode applet_mode_,
const Core::Frontend::MiiEditApplet& frontend_)
: Applet{system_, applet_mode_}, frontend{frontend_}, system{system_} {}
MiiEdit::~MiiEdit() = default;
void MiiEdit::Initialize() {
// Note: MiiEdit is not initialized with common arguments.
// Instead, it is initialized by an AppletInput storage with size 0x100 bytes.
// Do NOT call Applet::Initialize() here.
const auto storage = broker.PopNormalDataToApplet();
ASSERT(storage != nullptr);
const auto applet_input_data = storage->GetData();
ASSERT(applet_input_data.size() >= sizeof(MiiEditAppletInputCommon));
std::memcpy(&applet_input_common, applet_input_data.data(), sizeof(MiiEditAppletInputCommon));
LOG_INFO(Service_AM,
"Initializing MiiEdit Applet with MiiEditAppletVersion={} and MiiEditAppletMode={}",
applet_input_common.version, applet_input_common.applet_mode);
switch (applet_input_common.version) {
case MiiEditAppletVersion::Version3:
ASSERT(applet_input_data.size() ==
sizeof(MiiEditAppletInputCommon) + sizeof(MiiEditAppletInputV3));
std::memcpy(&applet_input_v3, applet_input_data.data() + sizeof(MiiEditAppletInputCommon),
sizeof(MiiEditAppletInputV3));
break;
case MiiEditAppletVersion::Version4:
ASSERT(applet_input_data.size() ==
sizeof(MiiEditAppletInputCommon) + sizeof(MiiEditAppletInputV4));
std::memcpy(&applet_input_v4, applet_input_data.data() + sizeof(MiiEditAppletInputCommon),
sizeof(MiiEditAppletInputV4));
break;
default:
UNIMPLEMENTED_MSG("Unknown MiiEditAppletVersion={} with size={}",
applet_input_common.version, applet_input_data.size());
ASSERT(applet_input_data.size() >=
sizeof(MiiEditAppletInputCommon) + sizeof(MiiEditAppletInputV4));
std::memcpy(&applet_input_v4, applet_input_data.data() + sizeof(MiiEditAppletInputCommon),
sizeof(MiiEditAppletInputV4));
break;
}
}
bool MiiEdit::TransactionComplete() const {
return is_complete;
}
ResultCode MiiEdit::GetStatus() const {
return ResultSuccess;
}
void MiiEdit::ExecuteInteractive() {
UNREACHABLE_MSG("Attempted to call interactive execution on non-interactive applet.");
}
void MiiEdit::Execute() {
if (is_complete) {
return;
}
// This is a default stub for each of the MiiEdit applet modes.
switch (applet_input_common.applet_mode) {
case MiiEditAppletMode::ShowMiiEdit:
case MiiEditAppletMode::AppendMii:
case MiiEditAppletMode::AppendMiiImage:
case MiiEditAppletMode::UpdateMiiImage:
MiiEditOutput(MiiEditResult::Success, 0);
break;
case MiiEditAppletMode::CreateMii:
case MiiEditAppletMode::EditMii: {
Service::Mii::MiiManager mii_manager;
const MiiEditCharInfo char_info{
.mii_info{applet_input_common.applet_mode == MiiEditAppletMode::EditMii
? applet_input_v4.char_info.mii_info
: mii_manager.BuildDefault(0)},
};
MiiEditOutputForCharInfoEditing(MiiEditResult::Success, char_info);
break;
}
default:
UNIMPLEMENTED_MSG("Unknown MiiEditAppletMode={}", applet_input_common.applet_mode);
MiiEditOutput(MiiEditResult::Success, 0);
break;
}
}
void MiiEdit::MiiEditOutput(MiiEditResult result, s32 index) {
const MiiEditAppletOutput applet_output{
.result{result},
.index{index},
};
std::vector<u8> out_data(sizeof(MiiEditAppletOutput));
std::memcpy(out_data.data(), &applet_output, sizeof(MiiEditAppletOutput));
is_complete = true;
broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(out_data)));
broker.SignalStateChanged();
}
void MiiEdit::MiiEditOutputForCharInfoEditing(MiiEditResult result,
const MiiEditCharInfo& char_info) {
const MiiEditAppletOutputForCharInfoEditing applet_output{
.result{result},
.char_info{char_info},
};
std::vector<u8> out_data(sizeof(MiiEditAppletOutputForCharInfoEditing));
std::memcpy(out_data.data(), &applet_output, sizeof(MiiEditAppletOutputForCharInfoEditing));
is_complete = true;
broker.PushNormalDataFromApplet(std::make_shared<IStorage>(system, std::move(out_data)));
broker.SignalStateChanged();
}
} // namespace Service::AM::Applets

View File

@@ -0,0 +1,45 @@
// Copyright 2022 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include "core/hle/result.h"
#include "core/hle/service/am/applets/applet_mii_edit_types.h"
#include "core/hle/service/am/applets/applets.h"
namespace Core {
class System;
} // namespace Core
namespace Service::AM::Applets {
class MiiEdit final : public Applet {
public:
explicit MiiEdit(Core::System& system_, LibraryAppletMode applet_mode_,
const Core::Frontend::MiiEditApplet& frontend_);
~MiiEdit() override;
void Initialize() override;
bool TransactionComplete() const override;
ResultCode GetStatus() const override;
void ExecuteInteractive() override;
void Execute() override;
void MiiEditOutput(MiiEditResult result, s32 index);
void MiiEditOutputForCharInfoEditing(MiiEditResult result, const MiiEditCharInfo& char_info);
private:
const Core::Frontend::MiiEditApplet& frontend;
Core::System& system;
MiiEditAppletInputCommon applet_input_common{};
MiiEditAppletInputV3 applet_input_v3{};
MiiEditAppletInputV4 applet_input_v4{};
bool is_complete{false};
};
} // namespace Service::AM::Applets

View File

@@ -0,0 +1,83 @@
// Copyright 2022 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <array>
#include "common/common_funcs.h"
#include "common/common_types.h"
#include "core/hle/service/mii/types.h"
namespace Service::AM::Applets {
enum class MiiEditAppletVersion : s32 {
Version3 = 0x3, // 1.0.0 - 10.1.1
Version4 = 0x4, // 10.2.0+
};
// This is nn::mii::AppletMode
enum class MiiEditAppletMode : u32 {
ShowMiiEdit = 0,
AppendMii = 1,
AppendMiiImage = 2,
UpdateMiiImage = 3,
CreateMii = 4,
EditMii = 5,
};
enum class MiiEditResult : u32 {
Success,
Cancel,
};
struct MiiEditCharInfo {
Service::Mii::MiiInfo mii_info{};
};
static_assert(sizeof(MiiEditCharInfo) == 0x58, "MiiEditCharInfo has incorrect size.");
struct MiiEditAppletInputCommon {
MiiEditAppletVersion version{};
MiiEditAppletMode applet_mode{};
};
static_assert(sizeof(MiiEditAppletInputCommon) == 0x8,
"MiiEditAppletInputCommon has incorrect size.");
struct MiiEditAppletInputV3 {
u32 special_mii_key_code{};
std::array<Common::UUID, 8> valid_uuids{};
Common::UUID used_uuid{};
INSERT_PADDING_BYTES(0x64);
};
static_assert(sizeof(MiiEditAppletInputV3) == 0x100 - sizeof(MiiEditAppletInputCommon),
"MiiEditAppletInputV3 has incorrect size.");
struct MiiEditAppletInputV4 {
u32 special_mii_key_code{};
MiiEditCharInfo char_info{};
INSERT_PADDING_BYTES(0x28);
Common::UUID used_uuid{};
INSERT_PADDING_BYTES(0x64);
};
static_assert(sizeof(MiiEditAppletInputV4) == 0x100 - sizeof(MiiEditAppletInputCommon),
"MiiEditAppletInputV4 has incorrect size.");
// This is nn::mii::AppletOutput
struct MiiEditAppletOutput {
MiiEditResult result{};
s32 index{};
INSERT_PADDING_BYTES(0x18);
};
static_assert(sizeof(MiiEditAppletOutput) == 0x20, "MiiEditAppletOutput has incorrect size.");
// This is nn::mii::AppletOutputForCharInfoEditing
struct MiiEditAppletOutputForCharInfoEditing {
MiiEditResult result{};
MiiEditCharInfo char_info{};
INSERT_PADDING_BYTES(0x24);
};
static_assert(sizeof(MiiEditAppletOutputForCharInfoEditing) == 0x80,
"MiiEditAppletOutputForCharInfoEditing has incorrect size.");
} // namespace Service::AM::Applets

View File

@@ -9,7 +9,7 @@
#include "core/frontend/applets/controller.h"
#include "core/frontend/applets/error.h"
#include "core/frontend/applets/general_frontend.h"
#include "core/frontend/applets/mii.h"
#include "core/frontend/applets/mii_edit.h"
#include "core/frontend/applets/profile_select.h"
#include "core/frontend/applets/software_keyboard.h"
#include "core/frontend/applets/web_browser.h"
@@ -20,7 +20,7 @@
#include "core/hle/service/am/applets/applet_controller.h"
#include "core/hle/service/am/applets/applet_error.h"
#include "core/hle/service/am/applets/applet_general_backend.h"
#include "core/hle/service/am/applets/applet_mii.h"
#include "core/hle/service/am/applets/applet_mii_edit.h"
#include "core/hle/service/am/applets/applet_profile_select.h"
#include "core/hle/service/am/applets/applet_software_keyboard.h"
#include "core/hle/service/am/applets/applet_web_browser.h"
@@ -173,12 +173,12 @@ void Applet::Initialize() {
AppletFrontendSet::AppletFrontendSet() = default;
AppletFrontendSet::AppletFrontendSet(ControllerApplet controller_applet, ErrorApplet error_applet,
MiiEdit mii_edit_,
ParentalControlsApplet parental_controls_applet,
MiiApplet mii_applet, PhotoViewer photo_viewer_,
ProfileSelect profile_select_,
PhotoViewer photo_viewer_, ProfileSelect profile_select_,
SoftwareKeyboard software_keyboard_, WebBrowser web_browser_)
: controller{std::move(controller_applet)}, error{std::move(error_applet)},
parental_controls{std::move(parental_controls_applet)}, mii{std::move(mii_applet)},
mii_edit{std::move(mii_edit_)}, parental_controls{std::move(parental_controls_applet)},
photo_viewer{std::move(photo_viewer_)}, profile_select{std::move(profile_select_)},
software_keyboard{std::move(software_keyboard_)}, web_browser{std::move(web_browser_)} {}
@@ -205,12 +205,12 @@ void AppletManager::SetAppletFrontendSet(AppletFrontendSet set) {
frontend.error = std::move(set.error);
}
if (set.parental_controls != nullptr) {
frontend.parental_controls = std::move(set.parental_controls);
if (set.mii_edit != nullptr) {
frontend.mii_edit = std::move(set.mii_edit);
}
if (set.mii != nullptr) {
frontend.mii = std::move(set.mii);
if (set.parental_controls != nullptr) {
frontend.parental_controls = std::move(set.parental_controls);
}
if (set.photo_viewer != nullptr) {
@@ -245,15 +245,15 @@ void AppletManager::SetDefaultAppletsIfMissing() {
frontend.error = std::make_unique<Core::Frontend::DefaultErrorApplet>();
}
if (frontend.mii_edit == nullptr) {
frontend.mii_edit = std::make_unique<Core::Frontend::DefaultMiiEditApplet>();
}
if (frontend.parental_controls == nullptr) {
frontend.parental_controls =
std::make_unique<Core::Frontend::DefaultParentalControlsApplet>();
}
if (frontend.mii == nullptr) {
frontend.mii = std::make_unique<Core::Frontend::DefaultMiiApplet>();
}
if (frontend.photo_viewer == nullptr) {
frontend.photo_viewer = std::make_unique<Core::Frontend::DefaultPhotoViewerApplet>();
}
@@ -289,7 +289,7 @@ std::shared_ptr<Applet> AppletManager::GetApplet(AppletId id, LibraryAppletMode
case AppletId::SoftwareKeyboard:
return std::make_shared<SoftwareKeyboard>(system, mode, *frontend.software_keyboard);
case AppletId::MiiEdit:
return std::make_shared<Mii>(system, mode, *frontend.mii);
return std::make_shared<MiiEdit>(system, mode, *frontend.mii_edit);
case AppletId::Web:
case AppletId::Shop:
case AppletId::OfflineWeb:

View File

@@ -20,8 +20,8 @@ namespace Core::Frontend {
class ControllerApplet;
class ECommerceApplet;
class ErrorApplet;
class MiiEditApplet;
class ParentalControlsApplet;
class MiiApplet;
class PhotoViewerApplet;
class ProfileSelectApplet;
class SoftwareKeyboardApplet;
@@ -179,8 +179,8 @@ protected:
struct AppletFrontendSet {
using ControllerApplet = std::unique_ptr<Core::Frontend::ControllerApplet>;
using ErrorApplet = std::unique_ptr<Core::Frontend::ErrorApplet>;
using MiiEdit = std::unique_ptr<Core::Frontend::MiiEditApplet>;
using ParentalControlsApplet = std::unique_ptr<Core::Frontend::ParentalControlsApplet>;
using MiiApplet = std::unique_ptr<Core::Frontend::MiiApplet>;
using PhotoViewer = std::unique_ptr<Core::Frontend::PhotoViewerApplet>;
using ProfileSelect = std::unique_ptr<Core::Frontend::ProfileSelectApplet>;
using SoftwareKeyboard = std::unique_ptr<Core::Frontend::SoftwareKeyboardApplet>;
@@ -188,7 +188,7 @@ struct AppletFrontendSet {
AppletFrontendSet();
AppletFrontendSet(ControllerApplet controller_applet, ErrorApplet error_applet,
ParentalControlsApplet parental_controls_applet, MiiApplet mii_applet,
MiiEdit mii_edit_, ParentalControlsApplet parental_controls_applet,
PhotoViewer photo_viewer_, ProfileSelect profile_select_,
SoftwareKeyboard software_keyboard_, WebBrowser web_browser_);
~AppletFrontendSet();
@@ -201,8 +201,8 @@ struct AppletFrontendSet {
ControllerApplet controller;
ErrorApplet error;
MiiEdit mii_edit;
ParentalControlsApplet parental_controls;
MiiApplet mii;
PhotoViewer photo_viewer;
ProfileSelect profile_select;
SoftwareKeyboard software_keyboard;

View File

@@ -1,4 +1,4 @@
// Copyright 2020 yuzu emulator team
// Copyright 2020 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
@@ -12,7 +12,6 @@
#include "core/hle/service/acc/profile_manager.h"
#include "core/hle/service/mii/mii_manager.h"
#include "core/hle/service/mii/raw_data.h"
#include "core/hle/service/mii/types.h"
namespace Service::Mii {

View File

@@ -1,315 +1,16 @@
// Copyright 2020 yuzu emulator team
// Copyright 2020 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <array>
#include <vector>
#include "common/bit_field.h"
#include "common/common_funcs.h"
#include "common/uuid.h"
#include "core/hle/result.h"
#include "core/hle/service/mii/types.h"
namespace Service::Mii {
enum class Source : u32 {
Database = 0,
Default = 1,
Account = 2,
Friend = 3,
};
enum class SourceFlag : u32 {
None = 0,
Database = 1 << 0,
Default = 1 << 1,
};
DECLARE_ENUM_FLAG_OPERATORS(SourceFlag);
struct MiiInfo {
Common::UUID uuid;
std::array<char16_t, 11> name;
u8 font_region;
u8 favorite_color;
u8 gender;
u8 height;
u8 build;
u8 type;
u8 region_move;
u8 faceline_type;
u8 faceline_color;
u8 faceline_wrinkle;
u8 faceline_make;
u8 hair_type;
u8 hair_color;
u8 hair_flip;
u8 eye_type;
u8 eye_color;
u8 eye_scale;
u8 eye_aspect;
u8 eye_rotate;
u8 eye_x;
u8 eye_y;
u8 eyebrow_type;
u8 eyebrow_color;
u8 eyebrow_scale;
u8 eyebrow_aspect;
u8 eyebrow_rotate;
u8 eyebrow_x;
u8 eyebrow_y;
u8 nose_type;
u8 nose_scale;
u8 nose_y;
u8 mouth_type;
u8 mouth_color;
u8 mouth_scale;
u8 mouth_aspect;
u8 mouth_y;
u8 beard_color;
u8 beard_type;
u8 mustache_type;
u8 mustache_scale;
u8 mustache_y;
u8 glasses_type;
u8 glasses_color;
u8 glasses_scale;
u8 glasses_y;
u8 mole_type;
u8 mole_scale;
u8 mole_x;
u8 mole_y;
u8 padding;
std::u16string Name() const;
};
static_assert(sizeof(MiiInfo) == 0x58, "MiiInfo has incorrect size.");
static_assert(std::has_unique_object_representations_v<MiiInfo>,
"All bits of MiiInfo must contribute to its value.");
#pragma pack(push, 4)
struct MiiInfoElement {
MiiInfoElement(const MiiInfo& info_, Source source_) : info{info_}, source{source_} {}
MiiInfo info{};
Source source{};
};
static_assert(sizeof(MiiInfoElement) == 0x5c, "MiiInfoElement has incorrect size.");
struct MiiStoreBitFields {
union {
u32 word_0{};
BitField<0, 8, u32> hair_type;
BitField<8, 7, u32> height;
BitField<15, 1, u32> mole_type;
BitField<16, 7, u32> build;
BitField<23, 1, HairFlip> hair_flip;
BitField<24, 7, u32> hair_color;
BitField<31, 1, u32> type;
};
union {
u32 word_1{};
BitField<0, 7, u32> eye_color;
BitField<7, 1, Gender> gender;
BitField<8, 7, u32> eyebrow_color;
BitField<16, 7, u32> mouth_color;
BitField<24, 7, u32> beard_color;
};
union {
u32 word_2{};
BitField<0, 7, u32> glasses_color;
BitField<8, 6, u32> eye_type;
BitField<14, 2, u32> region_move;
BitField<16, 6, u32> mouth_type;
BitField<22, 2, FontRegion> font_region;
BitField<24, 5, u32> eye_y;
BitField<29, 3, u32> glasses_scale;
};
union {
u32 word_3{};
BitField<0, 5, u32> eyebrow_type;
BitField<5, 3, MustacheType> mustache_type;
BitField<8, 5, u32> nose_type;
BitField<13, 3, BeardType> beard_type;
BitField<16, 5, u32> nose_y;
BitField<21, 3, u32> mouth_aspect;
BitField<24, 5, u32> mouth_y;
BitField<29, 3, u32> eyebrow_aspect;
};
union {
u32 word_4{};
BitField<0, 5, u32> mustache_y;
BitField<5, 3, u32> eye_rotate;
BitField<8, 5, u32> glasses_y;
BitField<13, 3, u32> eye_aspect;
BitField<16, 5, u32> mole_x;
BitField<21, 3, u32> eye_scale;
BitField<24, 5, u32> mole_y;
};
union {
u32 word_5{};
BitField<0, 5, u32> glasses_type;
BitField<8, 4, u32> favorite_color;
BitField<12, 4, u32> faceline_type;
BitField<16, 4, u32> faceline_color;
BitField<20, 4, u32> faceline_wrinkle;
BitField<24, 4, u32> faceline_makeup;
BitField<28, 4, u32> eye_x;
};
union {
u32 word_6{};
BitField<0, 4, u32> eyebrow_scale;
BitField<4, 4, u32> eyebrow_rotate;
BitField<8, 4, u32> eyebrow_x;
BitField<12, 4, u32> eyebrow_y;
BitField<16, 4, u32> nose_scale;
BitField<20, 4, u32> mouth_scale;
BitField<24, 4, u32> mustache_scale;
BitField<28, 4, u32> mole_scale;
};
};
static_assert(sizeof(MiiStoreBitFields) == 0x1c, "MiiStoreBitFields has incorrect size.");
static_assert(std::is_trivially_copyable_v<MiiStoreBitFields>,
"MiiStoreBitFields is not trivially copyable.");
struct MiiStoreData {
using Name = std::array<char16_t, 10>;
MiiStoreData();
MiiStoreData(const Name& name, const MiiStoreBitFields& bit_fields,
const Common::UUID& user_id);
// This corresponds to the above structure MiiStoreBitFields. I did it like this because the
// BitField<> type makes this (and any thing that contains it) not trivially copyable, which is
// not suitable for our uses.
struct {
std::array<u8, 0x1C> data{};
static_assert(sizeof(MiiStoreBitFields) == sizeof(data), "data field has incorrect size.");
Name name{};
Common::UUID uuid{};
} data;
u16 data_crc{};
u16 device_crc{};
};
static_assert(sizeof(MiiStoreData) == 0x44, "MiiStoreData has incorrect size.");
struct MiiStoreDataElement {
MiiStoreData data{};
Source source{};
};
static_assert(sizeof(MiiStoreDataElement) == 0x48, "MiiStoreDataElement has incorrect size.");
struct MiiDatabase {
u32 magic{}; // 'NFDB'
std::array<MiiStoreData, 0x64> miis{};
INSERT_PADDING_BYTES(1);
u8 count{};
u16 crc{};
};
static_assert(sizeof(MiiDatabase) == 0x1A98, "MiiDatabase has incorrect size.");
struct RandomMiiValues {
std::array<u8, 0xbc> values{};
};
static_assert(sizeof(RandomMiiValues) == 0xbc, "RandomMiiValues has incorrect size.");
struct RandomMiiData4 {
Gender gender{};
Age age{};
Race race{};
u32 values_count{};
std::array<u32, 47> values{};
};
static_assert(sizeof(RandomMiiData4) == 0xcc, "RandomMiiData4 has incorrect size.");
struct RandomMiiData3 {
u32 arg_1;
u32 arg_2;
u32 values_count;
std::array<u32, 47> values{};
};
static_assert(sizeof(RandomMiiData3) == 0xc8, "RandomMiiData3 has incorrect size.");
struct RandomMiiData2 {
u32 arg_1;
u32 values_count;
std::array<u32, 47> values{};
};
static_assert(sizeof(RandomMiiData2) == 0xc4, "RandomMiiData2 has incorrect size.");
struct DefaultMii {
u32 face_type{};
u32 face_color{};
u32 face_wrinkle{};
u32 face_makeup{};
u32 hair_type{};
u32 hair_color{};
u32 hair_flip{};
u32 eye_type{};
u32 eye_color{};
u32 eye_scale{};
u32 eye_aspect{};
u32 eye_rotate{};
u32 eye_x{};
u32 eye_y{};
u32 eyebrow_type{};
u32 eyebrow_color{};
u32 eyebrow_scale{};
u32 eyebrow_aspect{};
u32 eyebrow_rotate{};
u32 eyebrow_x{};
u32 eyebrow_y{};
u32 nose_type{};
u32 nose_scale{};
u32 nose_y{};
u32 mouth_type{};
u32 mouth_color{};
u32 mouth_scale{};
u32 mouth_aspect{};
u32 mouth_y{};
u32 mustache_type{};
u32 beard_type{};
u32 beard_color{};
u32 mustache_scale{};
u32 mustache_y{};
u32 glasses_type{};
u32 glasses_color{};
u32 glasses_scale{};
u32 glasses_y{};
u32 mole_type{};
u32 mole_scale{};
u32 mole_x{};
u32 mole_y{};
u32 height{};
u32 weight{};
Gender gender{};
u32 favorite_color{};
u32 region{};
FontRegion font_region{};
u32 type{};
INSERT_PADDING_WORDS(5);
};
static_assert(sizeof(DefaultMii) == 0xd8, "MiiStoreData has incorrect size.");
#pragma pack(pop)
// The Mii manager is responsible for loading and storing the Miis to the database in NAND along
// with providing an easy interface for HLE emulation of the mii service.
class MiiManager {

View File

@@ -6,7 +6,7 @@
#include <array>
#include "core/hle/service/mii/mii_manager.h"
#include "core/hle/service/mii/types.h"
namespace Service::Mii::RawData {

View File

@@ -1,11 +1,16 @@
// Copyright 2020 yuzu emulator team
// Copyright 2020 yuzu Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <array>
#include <type_traits>
#include "common/bit_field.h"
#include "common/common_funcs.h"
#include "common/common_types.h"
#include "common/uuid.h"
namespace Service::Mii {
@@ -25,7 +30,11 @@ enum class BeardType : u32 {
Beard5,
};
enum class BeardAndMustacheFlag : u32 { Beard = 1, Mustache, All = Beard | Mustache };
enum class BeardAndMustacheFlag : u32 {
Beard = 1,
Mustache,
All = Beard | Mustache,
};
DECLARE_ENUM_FLAG_OPERATORS(BeardAndMustacheFlag);
enum class FontRegion : u32 {
@@ -64,4 +73,298 @@ enum class Race : u32 {
All,
};
enum class Source : u32 {
Database = 0,
Default = 1,
Account = 2,
Friend = 3,
};
enum class SourceFlag : u32 {
None = 0,
Database = 1 << 0,
Default = 1 << 1,
};
DECLARE_ENUM_FLAG_OPERATORS(SourceFlag);
struct MiiInfo {
Common::UUID uuid;
std::array<char16_t, 11> name;
u8 font_region;
u8 favorite_color;
u8 gender;
u8 height;
u8 build;
u8 type;
u8 region_move;
u8 faceline_type;
u8 faceline_color;
u8 faceline_wrinkle;
u8 faceline_make;
u8 hair_type;
u8 hair_color;
u8 hair_flip;
u8 eye_type;
u8 eye_color;
u8 eye_scale;
u8 eye_aspect;
u8 eye_rotate;
u8 eye_x;
u8 eye_y;
u8 eyebrow_type;
u8 eyebrow_color;
u8 eyebrow_scale;
u8 eyebrow_aspect;
u8 eyebrow_rotate;
u8 eyebrow_x;
u8 eyebrow_y;
u8 nose_type;
u8 nose_scale;
u8 nose_y;
u8 mouth_type;
u8 mouth_color;
u8 mouth_scale;
u8 mouth_aspect;
u8 mouth_y;
u8 beard_color;
u8 beard_type;
u8 mustache_type;
u8 mustache_scale;
u8 mustache_y;
u8 glasses_type;
u8 glasses_color;
u8 glasses_scale;
u8 glasses_y;
u8 mole_type;
u8 mole_scale;
u8 mole_x;
u8 mole_y;
u8 padding;
};
static_assert(sizeof(MiiInfo) == 0x58, "MiiInfo has incorrect size.");
static_assert(std::has_unique_object_representations_v<MiiInfo>,
"All bits of MiiInfo must contribute to its value.");
#pragma pack(push, 4)
struct MiiInfoElement {
MiiInfoElement(const MiiInfo& info_, Source source_) : info{info_}, source{source_} {}
MiiInfo info{};
Source source{};
};
static_assert(sizeof(MiiInfoElement) == 0x5c, "MiiInfoElement has incorrect size.");
struct MiiStoreBitFields {
union {
u32 word_0{};
BitField<0, 8, u32> hair_type;
BitField<8, 7, u32> height;
BitField<15, 1, u32> mole_type;
BitField<16, 7, u32> build;
BitField<23, 1, HairFlip> hair_flip;
BitField<24, 7, u32> hair_color;
BitField<31, 1, u32> type;
};
union {
u32 word_1{};
BitField<0, 7, u32> eye_color;
BitField<7, 1, Gender> gender;
BitField<8, 7, u32> eyebrow_color;
BitField<16, 7, u32> mouth_color;
BitField<24, 7, u32> beard_color;
};
union {
u32 word_2{};
BitField<0, 7, u32> glasses_color;
BitField<8, 6, u32> eye_type;
BitField<14, 2, u32> region_move;
BitField<16, 6, u32> mouth_type;
BitField<22, 2, FontRegion> font_region;
BitField<24, 5, u32> eye_y;
BitField<29, 3, u32> glasses_scale;
};
union {
u32 word_3{};
BitField<0, 5, u32> eyebrow_type;
BitField<5, 3, MustacheType> mustache_type;
BitField<8, 5, u32> nose_type;
BitField<13, 3, BeardType> beard_type;
BitField<16, 5, u32> nose_y;
BitField<21, 3, u32> mouth_aspect;
BitField<24, 5, u32> mouth_y;
BitField<29, 3, u32> eyebrow_aspect;
};
union {
u32 word_4{};
BitField<0, 5, u32> mustache_y;
BitField<5, 3, u32> eye_rotate;
BitField<8, 5, u32> glasses_y;
BitField<13, 3, u32> eye_aspect;
BitField<16, 5, u32> mole_x;
BitField<21, 3, u32> eye_scale;
BitField<24, 5, u32> mole_y;
};
union {
u32 word_5{};
BitField<0, 5, u32> glasses_type;
BitField<8, 4, u32> favorite_color;
BitField<12, 4, u32> faceline_type;
BitField<16, 4, u32> faceline_color;
BitField<20, 4, u32> faceline_wrinkle;
BitField<24, 4, u32> faceline_makeup;
BitField<28, 4, u32> eye_x;
};
union {
u32 word_6{};
BitField<0, 4, u32> eyebrow_scale;
BitField<4, 4, u32> eyebrow_rotate;
BitField<8, 4, u32> eyebrow_x;
BitField<12, 4, u32> eyebrow_y;
BitField<16, 4, u32> nose_scale;
BitField<20, 4, u32> mouth_scale;
BitField<24, 4, u32> mustache_scale;
BitField<28, 4, u32> mole_scale;
};
};
static_assert(sizeof(MiiStoreBitFields) == 0x1c, "MiiStoreBitFields has incorrect size.");
static_assert(std::is_trivially_copyable_v<MiiStoreBitFields>,
"MiiStoreBitFields is not trivially copyable.");
struct MiiStoreData {
using Name = std::array<char16_t, 10>;
MiiStoreData();
MiiStoreData(const Name& name, const MiiStoreBitFields& bit_fields,
const Common::UUID& user_id);
// This corresponds to the above structure MiiStoreBitFields. I did it like this because the
// BitField<> type makes this (and any thing that contains it) not trivially copyable, which is
// not suitable for our uses.
struct {
std::array<u8, 0x1C> data{};
static_assert(sizeof(MiiStoreBitFields) == sizeof(data), "data field has incorrect size.");
Name name{};
Common::UUID uuid{};
} data;
u16 data_crc{};
u16 device_crc{};
};
static_assert(sizeof(MiiStoreData) == 0x44, "MiiStoreData has incorrect size.");
struct MiiStoreDataElement {
MiiStoreData data{};
Source source{};
};
static_assert(sizeof(MiiStoreDataElement) == 0x48, "MiiStoreDataElement has incorrect size.");
struct MiiDatabase {
u32 magic{}; // 'NFDB'
std::array<MiiStoreData, 0x64> miis{};
INSERT_PADDING_BYTES(1);
u8 count{};
u16 crc{};
};
static_assert(sizeof(MiiDatabase) == 0x1A98, "MiiDatabase has incorrect size.");
struct RandomMiiValues {
std::array<u8, 0xbc> values{};
};
static_assert(sizeof(RandomMiiValues) == 0xbc, "RandomMiiValues has incorrect size.");
struct RandomMiiData4 {
Gender gender{};
Age age{};
Race race{};
u32 values_count{};
std::array<u32, 47> values{};
};
static_assert(sizeof(RandomMiiData4) == 0xcc, "RandomMiiData4 has incorrect size.");
struct RandomMiiData3 {
u32 arg_1;
u32 arg_2;
u32 values_count;
std::array<u32, 47> values{};
};
static_assert(sizeof(RandomMiiData3) == 0xc8, "RandomMiiData3 has incorrect size.");
struct RandomMiiData2 {
u32 arg_1;
u32 values_count;
std::array<u32, 47> values{};
};
static_assert(sizeof(RandomMiiData2) == 0xc4, "RandomMiiData2 has incorrect size.");
struct DefaultMii {
u32 face_type{};
u32 face_color{};
u32 face_wrinkle{};
u32 face_makeup{};
u32 hair_type{};
u32 hair_color{};
u32 hair_flip{};
u32 eye_type{};
u32 eye_color{};
u32 eye_scale{};
u32 eye_aspect{};
u32 eye_rotate{};
u32 eye_x{};
u32 eye_y{};
u32 eyebrow_type{};
u32 eyebrow_color{};
u32 eyebrow_scale{};
u32 eyebrow_aspect{};
u32 eyebrow_rotate{};
u32 eyebrow_x{};
u32 eyebrow_y{};
u32 nose_type{};
u32 nose_scale{};
u32 nose_y{};
u32 mouth_type{};
u32 mouth_color{};
u32 mouth_scale{};
u32 mouth_aspect{};
u32 mouth_y{};
u32 mustache_type{};
u32 beard_type{};
u32 beard_color{};
u32 mustache_scale{};
u32 mustache_y{};
u32 glasses_type{};
u32 glasses_color{};
u32 glasses_scale{};
u32 glasses_y{};
u32 mole_type{};
u32 mole_scale{};
u32 mole_x{};
u32 mole_y{};
u32 height{};
u32 weight{};
Gender gender{};
u32 favorite_color{};
u32 region{};
FontRegion font_region{};
u32 type{};
INSERT_PADDING_WORDS(5);
};
static_assert(sizeof(DefaultMii) == 0xd8, "MiiStoreData has incorrect size.");
#pragma pack(pop)
} // namespace Service::Mii

View File

@@ -12,6 +12,7 @@
#include "core/hid/hid_types.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/k_event.h"
#include "core/hle/service/mii/mii_manager.h"
#include "core/hle/service/nfp/nfp.h"
#include "core/hle/service/nfp/nfp_user.h"

View File

@@ -9,7 +9,7 @@
#include "common/common_funcs.h"
#include "core/hle/service/kernel_helpers.h"
#include "core/hle/service/mii/mii_manager.h"
#include "core/hle/service/mii/types.h"
#include "core/hle/service/service.h"
namespace Kernel {

View File

@@ -11,9 +11,13 @@ void ExitFragment(TranslatorVisitor& v) {
const ProgramHeader sph{v.env.SPH()};
IR::Reg src_reg{IR::Reg::R0};
for (u32 render_target = 0; render_target < 8; ++render_target) {
if (!sph.ps.HasOutputComponents(render_target)) {
continue;
}
const std::array<bool, 4> mask{sph.ps.EnabledOutputComponents(render_target)};
for (u32 component = 0; component < 4; ++component) {
if (!mask[component]) {
++src_reg;
continue;
}
v.ir.SetFragColor(render_target, component, v.F(src_reg));

View File

@@ -196,6 +196,11 @@ struct ProgramHeader {
return {(bits & 1) != 0, (bits & 2) != 0, (bits & 4) != 0, (bits & 8) != 0};
}
[[nodiscard]] bool HasOutputComponents(u32 rt) const noexcept {
const u32 bits{omap.target >> (rt * 4)};
return (bits & 0xf) != 0;
}
[[nodiscard]] std::array<PixelImap, 4> GenericInputMap(u32 attribute) const {
const auto& vector{imap_generic_vector[attribute]};
return {vector.x, vector.y, vector.z, vector.w};

View File

@@ -1467,19 +1467,27 @@ typename BufferCache<P>::OverlapResult BufferCache<P>::ResolveOverlaps(VAddr cpu
overlap_ids.push_back(overlap_id);
overlap.Pick();
const VAddr overlap_cpu_addr = overlap.CpuAddr();
if (overlap_cpu_addr < begin) {
const bool expands_left = overlap_cpu_addr < begin;
if (expands_left) {
cpu_addr = begin = overlap_cpu_addr;
}
end = std::max(end, overlap_cpu_addr + overlap.SizeBytes());
const VAddr overlap_end = overlap_cpu_addr + overlap.SizeBytes();
const bool expands_right = overlap_end > end;
if (overlap_end > end) {
end = overlap_end;
}
stream_score += overlap.StreamScore();
if (stream_score > STREAM_LEAP_THRESHOLD && !has_stream_leap) {
// When this memory region has been joined a bunch of times, we assume it's being used
// as a stream buffer. Increase the size to skip constantly recreating buffers.
has_stream_leap = true;
begin -= PAGE_SIZE * 256;
cpu_addr = begin;
end += PAGE_SIZE * 256;
if (expands_right) {
begin -= PAGE_SIZE * 256;
cpu_addr = begin;
}
if (expands_left) {
end += PAGE_SIZE * 256;
}
}
}
return OverlapResult{

View File

@@ -367,17 +367,14 @@ BlitImageHelper::BlitImageHelper(const Device& device_, VKScheduler& scheduler_,
PipelineLayoutCreateInfo(two_textures_set_layout.address()))),
full_screen_vert(BuildShader(device, FULL_SCREEN_TRIANGLE_VERT_SPV)),
blit_color_to_color_frag(BuildShader(device, VULKAN_BLIT_COLOR_FLOAT_FRAG_SPV)),
blit_depth_stencil_frag(BuildShader(device, VULKAN_BLIT_DEPTH_STENCIL_FRAG_SPV)),
convert_depth_to_float_frag(BuildShader(device, CONVERT_DEPTH_TO_FLOAT_FRAG_SPV)),
convert_float_to_depth_frag(BuildShader(device, CONVERT_FLOAT_TO_DEPTH_FRAG_SPV)),
convert_abgr8_to_d24s8_frag(BuildShader(device, CONVERT_ABGR8_TO_D24S8_FRAG_SPV)),
convert_d24s8_to_abgr8_frag(BuildShader(device, CONVERT_D24S8_TO_ABGR8_FRAG_SPV)),
convert_s8d24_to_abgr8_frag(BuildShader(device, CONVERT_S8D24_TO_ABGR8_FRAG_SPV)),
linear_sampler(device.GetLogical().CreateSampler(SAMPLER_CREATE_INFO<VK_FILTER_LINEAR>)),
nearest_sampler(device.GetLogical().CreateSampler(SAMPLER_CREATE_INFO<VK_FILTER_NEAREST>)) {
if (device.IsExtShaderStencilExportSupported()) {
blit_depth_stencil_frag = BuildShader(device, VULKAN_BLIT_DEPTH_STENCIL_FRAG_SPV);
}
}
nearest_sampler(device.GetLogical().CreateSampler(SAMPLER_CREATE_INFO<VK_FILTER_NEAREST>)) {}
BlitImageHelper::~BlitImageHelper() = default;

View File

@@ -781,11 +781,6 @@ bool TextureCacheRuntime::ShouldReinterpret(Image& dst, Image& src) {
!device.IsExtShaderStencilExportSupported()) {
return true;
}
if (VideoCore::Surface::GetFormatType(src.info.format) ==
VideoCore::Surface::SurfaceType::DepthStencil &&
!device.IsExtShaderStencilExportSupported()) {
return true;
}
if (dst.info.format == PixelFormat::D32_FLOAT_S8_UINT ||
src.info.format == PixelFormat::D32_FLOAT_S8_UINT) {
return true;
@@ -1447,8 +1442,7 @@ bool Image::BlitScaleHelper(bool scale_up) {
runtime->blit_image_helper.BlitColor(blit_framebuffer.get(), color_view, dst_region,
src_region, operation, BLIT_OPERATION);
} else if (!runtime->device.IsBlitDepthStencilSupported() &&
aspect_mask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
} else if (aspect_mask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
if (!blit_framebuffer) {
blit_framebuffer = std::make_unique<Framebuffer>(*runtime, nullptr, view_ptr, extent);
}

View File

@@ -343,7 +343,7 @@ template <bool has_blacklists>
void TextureCache<P>::FillImageViews(DescriptorTable<TICEntry>& table,
std::span<ImageViewId> cached_image_view_ids,
std::span<ImageViewInOut> views) {
bool has_blacklisted;
bool has_blacklisted = false;
do {
has_deleted_images = false;
if constexpr (has_blacklists) {
@@ -1725,7 +1725,7 @@ void TextureCache<P>::SynchronizeAliases(ImageId image_id) {
});
const auto& resolution = Settings::values.resolution_info;
for (const AliasedImage* const aliased : aliased_images) {
if (!resolution.active | !any_rescaled) {
if (!resolution.active || !any_rescaled) {
CopyImage(image_id, aliased->id, aliased->copies);
continue;
}
@@ -1736,19 +1736,7 @@ void TextureCache<P>::SynchronizeAliases(ImageId image_id) {
continue;
}
ScaleUp(aliased_image);
const bool both_2d{image.info.type == ImageType::e2D &&
aliased_image.info.type == ImageType::e2D};
auto copies = aliased->copies;
for (auto copy : copies) {
copy.extent.width = std::max<u32>(
(copy.extent.width * resolution.up_scale) >> resolution.down_shift, 1);
if (both_2d) {
copy.extent.height = std::max<u32>(
(copy.extent.height * resolution.up_scale) >> resolution.down_shift, 1);
}
}
CopyImage(image_id, aliased->id, copies);
CopyImage(image_id, aliased->id, aliased->copies);
}
}

View File

@@ -614,6 +614,11 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
khr_push_descriptor = false;
break;
}
const u32 nv_major_version = (properties.driverVersion >> 22) & 0x3ff;
if (nv_major_version >= 510) {
LOG_WARNING(Render_Vulkan, "NVIDIA Drivers >= 510 do not support MSAA image blits");
cant_blit_msaa = true;
}
}
const bool is_radv = driver_id == VK_DRIVER_ID_MESA_RADV;
if (ext_extended_dynamic_state && is_radv) {

View File

@@ -11,6 +11,9 @@
#include <QWebEngineScriptCollection>
#include <QWebEngineSettings>
#include <QWebEngineUrlScheme>
#include "core/hid/input_interpreter.h"
#include "yuzu/applets/qt_web_browser_scripts.h"
#endif
#include "common/fs/path_util.h"

View File

@@ -5,6 +5,7 @@
#pragma once
#include <atomic>
#include <thread>
#include <QObject>

View File

@@ -24,7 +24,7 @@
#include "core/file_sys/vfs_real.h"
#include "core/frontend/applets/controller.h"
#include "core/frontend/applets/general_frontend.h"
#include "core/frontend/applets/mii.h"
#include "core/frontend/applets/mii_edit.h"
#include "core/frontend/applets/software_keyboard.h"
#include "core/hid/emulated_controller.h"
#include "core/hid/hid_core.h"
@@ -1280,8 +1280,8 @@ bool GMainWindow::LoadROM(const QString& filename, u64 program_id, std::size_t p
system->SetAppletFrontendSet({
std::make_unique<QtControllerSelector>(*this), // Controller Selector
std::make_unique<QtErrorDisplay>(*this), // Error Display
nullptr, // Mii Editor
nullptr, // Parental Controls
nullptr, // Mii editor
nullptr, // Photo Viewer
std::make_unique<QtProfileSelector>(*this), // Profile Selector
std::make_unique<QtSoftwareKeyboard>(*this), // Software Keyboard

View File

@@ -3,6 +3,7 @@
// Refer to the license.txt file included.
#include <memory>
#include <optional>
#include <sstream>
// Ignore -Wimplicit-fallthrough due to https://github.com/libsdl-org/SDL/issues/4307
@@ -28,11 +29,12 @@
namespace FS = Common::FS;
Config::Config() {
// TODO: Don't hardcode the path; let the frontend decide where to put the config files.
sdl2_config_loc = FS::GetYuzuPath(FS::YuzuPath::ConfigDir) / "sdl2-config.ini";
sdl2_config = std::make_unique<INIReader>(FS::PathToUTF8String(sdl2_config_loc));
const std::filesystem::path default_config_path =
FS::GetYuzuPath(FS::YuzuPath::ConfigDir) / "sdl2-config.ini";
Config::Config(std::optional<std::filesystem::path> config_path)
: sdl2_config_loc{config_path.value_or(default_config_path)},
sdl2_config{std::make_unique<INIReader>(FS::PathToUTF8String(sdl2_config_loc))} {
Reload();
}

View File

@@ -6,6 +6,7 @@
#include <filesystem>
#include <memory>
#include <optional>
#include <string>
#include "common/settings.h"
@@ -13,14 +14,14 @@
class INIReader;
class Config {
std::unique_ptr<INIReader> sdl2_config;
std::filesystem::path sdl2_config_loc;
std::unique_ptr<INIReader> sdl2_config;
bool LoadINI(const std::string& default_contents = "", bool retry = true);
void ReadValues();
public:
Config();
explicit Config(std::optional<std::filesystem::path> config_path);
~Config();
void Reload();

View File

@@ -62,7 +62,8 @@ static void PrintHelp(const char* argv0) {
"-f, --fullscreen Start in fullscreen mode\n"
"-h, --help Display this help and exit\n"
"-v, --version Output version information and exit\n"
"-p, --program Pass following string as arguments to executable\n";
"-p, --program Pass following string as arguments to executable\n"
"-c, --config Load the specified configuration file\n";
}
static void PrintVersion() {
@@ -74,7 +75,6 @@ int main(int argc, char** argv) {
Common::Log::Initialize();
Common::Log::SetColorConsoleBackendEnabled(true);
Common::DetachedTasks detached_tasks;
Config config;
int option_index = 0;
#ifdef _WIN32
@@ -87,19 +87,24 @@ int main(int argc, char** argv) {
}
#endif
std::string filepath;
std::optional<std::string> config_path;
std::string program_args;
bool fullscreen = false;
static struct option long_options[] = {
// clang-format off
{"fullscreen", no_argument, 0, 'f'},
{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'v'},
{"program", optional_argument, 0, 'p'},
{"config", required_argument, 0, 'c'},
{0, 0, 0, 0},
// clang-format on
};
while (optind < argc) {
int arg = getopt_long(argc, argv, "g:fhvp::", long_options, &option_index);
int arg = getopt_long(argc, argv, "g:fhvp::c:", long_options, &option_index);
if (arg != -1) {
switch (static_cast<char>(arg)) {
case 'f':
@@ -113,9 +118,12 @@ int main(int argc, char** argv) {
PrintVersion();
return 0;
case 'p':
Settings::values.program_args = argv[optind];
program_args = argv[optind];
++optind;
break;
case 'c':
config_path = optarg;
break;
}
} else {
#ifdef _WIN32
@@ -127,6 +135,12 @@ int main(int argc, char** argv) {
}
}
Config config{config_path};
if (!program_args.empty()) {
Settings::values.program_args = program_args;
}
#ifdef _WIN32
LocalFree(argv_w);
#endif